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
initrand(void)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
randbytes(void * p,size_t n)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
randULONG(void)58 static ULONG randULONG(void)
59 {
60 ULONG n;
61 randbytes(&n, sizeof(n));
62 return n;
63 }
64
65 #ifdef _M_AMD64
randULONG64(void)66 static ULONG64 randULONG64(void)
67 {
68 return (ULONG64)randULONG() << 32 | randULONG();
69 }
70 #endif
71
check(CONTEXT * pContext)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
START_TEST(NtContinue)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