e2b254beda171f0de84a44f169b9ae5a31778e6d
[reactos.git] / modules / rostests / apitests / ntdll / NtContinue.c
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 void check(CONTEXT * pContext)
62 {
63 #ifdef _M_IX86
64 ok(pContext->ContextFlags == CONTEXT_FULL,
65 "ContextFlags=0x%lx\n", pContext->ContextFlags);
66
67 /* Random data segments */
68 ok((pContext->SegGs & NTC_SEGMENT_BITS) ==
69 (continueContext.SegGs & NTC_SEGMENT_BITS),
70 "SegGs=0x%lx / 0x%lx\n", pContext->SegGs, continueContext.SegGs);
71
72 ok((pContext->SegFs & NTC_SEGMENT_BITS) ==
73 (continueContext.SegFs & NTC_SEGMENT_BITS),
74 "SegFs=0x%lx / 0x%lx\n", pContext->SegFs, continueContext.SegFs);
75
76 ok((pContext->SegEs & NTC_SEGMENT_BITS) ==
77 (continueContext.SegEs & NTC_SEGMENT_BITS),
78 "SegEs=0x%lx / 0x%lx\n", pContext->SegEs, continueContext.SegEs);
79
80 ok((pContext->SegDs & NTC_SEGMENT_BITS) ==
81 (continueContext.SegDs & NTC_SEGMENT_BITS),
82 "SegDs=0x%lx / 0x%lx\n", pContext->SegDs, continueContext.SegDs);
83
84 /* Integer registers */
85 ok(pContext->Edi == continueContext.Edi,
86 "Edi: 0x%lx != 0x%lx\n", pContext->Edi, continueContext.Edi);
87 ok(pContext->Esi == continueContext.Esi,
88 "Esi: 0x%lx != 0x%lx\n", pContext->Esi, continueContext.Esi);
89 ok(pContext->Ebx == continueContext.Ebx,
90 "Ebx: 0x%lx != 0x%lx\n", pContext->Ebx, continueContext.Ebx);
91 ok(pContext->Edx == continueContext.Edx,
92 "Edx: 0x%lx != 0x%lx\n", pContext->Edx, continueContext.Edx);
93 ok(pContext->Ecx == continueContext.Ecx,
94 "Ecx: 0x%lx != 0x%lx\n", pContext->Ecx, continueContext.Ecx);
95 ok(pContext->Eax == continueContext.Eax,
96 "Eax: 0x%lx != 0x%lx\n", pContext->Eax, continueContext.Eax);
97
98 /* Control registers and segments */
99 ok(pContext->Ebp == continueContext.Ebp,
100 "Ebp: 0x%lx != 0x%lx\n", pContext->Ebp, continueContext.Ebp);
101 ok(pContext->Eip == continueContext.Eip,
102 "Eip: 0x%lx != 0x%lx\n", pContext->Eip, continueContext.Eip);
103 ok(pContext->Esp == continueContext.Esp,
104 "Esp: 0x%lx != 0x%lx\n", pContext->Esp, continueContext.Esp);
105
106 ok((pContext->SegCs & NTC_SEGMENT_BITS) ==
107 (continueContext.SegCs & NTC_SEGMENT_BITS),
108 "SegCs: 0x%lx != 0x%lx\n", pContext->SegCs, continueContext.SegCs);
109
110 ok((pContext->EFlags & NTC_EFLAGS_BITS) ==
111 (continueContext.EFlags & NTC_EFLAGS_BITS),
112 "EFlags: 0x%lx != 0x%lx\n", pContext->EFlags, continueContext.EFlags);
113
114 ok((pContext->SegSs & NTC_SEGMENT_BITS) ==
115 (continueContext.SegSs & NTC_SEGMENT_BITS),
116 "SegSs: 0x%lx != 0x%lx\n", pContext->SegSs, continueContext.SegSs);
117 #endif
118
119 /* Return where we came from */
120 longjmp(jmpbuf, 1);
121 }
122
123 START_TEST(NtContinue)
124 {
125 #ifdef __RUNTIME_CHECKS__
126 skip("This test breaks MSVC runtime checks!");
127 return;
128 #endif /* __RUNTIME_CHECKS__ */
129 initrand();
130
131 /* First time */
132 if(setjmp(jmpbuf) == 0)
133 {
134 CONTEXT bogus;
135
136 continueContext.ContextFlags = CONTEXT_FULL;
137 GetThreadContext(GetCurrentThread(), &continueContext);
138
139 #ifdef _M_IX86
140 continueContext.ContextFlags = CONTEXT_FULL;
141
142 /* Fill the integer registers with random values */
143 continueContext.Edi = randULONG();
144 continueContext.Esi = randULONG();
145 continueContext.Ebx = randULONG();
146 continueContext.Edx = randULONG();
147 continueContext.Ecx = randULONG();
148 continueContext.Eax = randULONG();
149 continueContext.Ebp = randULONG();
150
151 /* Randomize all the allowed flags (determined experimentally with WinDbg) */
152 continueContext.EFlags = randULONG() & 0x3C0CD5;
153
154 /* Randomize the stack pointer as much as possible */
155 continueContext.Esp = (ULONG)(((ULONG_PTR)&bogus) & 0xFFFFFFFF) +
156 sizeof(bogus) - (randULONG() & 0xF) * 4;
157
158 /* continuePoint() is implemented in assembler */
159 continueContext.Eip = (ULONG)((ULONG_PTR)continuePoint & 0xFFFFFFF);
160
161 /* Can't do a lot about segments */
162 #endif
163
164 NtContinue(&continueContext, FALSE);
165 ok(0, "should never get here\n");
166 }
167
168 /* Second time */
169 return;
170 }