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