[WS2_32_APITEST]
[reactos.git] / 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 <apitest.h>
9 #include <ndk/kefuncs.h>
10
11 #include <setjmp.h>
12 #include <time.h>
13
14 #ifdef _M_IX86
15 #define NTC_SEGMENT_BITS (0xFFFF)
16 #define NTC_EFLAGS_BITS (0x3C0CD5)
17 #endif
18
19 void continuePoint(void);
20
21 static jmp_buf jmpbuf;
22 static CONTEXT continueContext;
23 static unsigned int nRandBytes;
24
25 static int initrand(void)
26 {
27 unsigned int nRandMax;
28 unsigned int nRandMaxBits;
29 time_t tLoc;
30
31 nRandMax = RAND_MAX;
32 for(nRandMaxBits = 0; nRandMax != 0; nRandMax >>= 1, ++ nRandMaxBits);
33 nRandBytes = nRandMaxBits / CHAR_BIT;
34 //assert(nRandBytes != 0);
35 srand((unsigned)(time(&tLoc) & UINT_MAX));
36 return 1;
37 }
38
39 static void randbytes(void * p, size_t n)
40 {
41 unsigned char * b;
42 size_t i;
43 int r = rand();
44
45 b = (unsigned char *)p;
46 for(i = 0; i < n; ++ i)
47 {
48 if(i % nRandBytes == 0)
49 r = rand();
50 b[i] = (unsigned char)(r & UCHAR_MAX);
51 r >>= CHAR_BIT;
52 }
53 }
54
55 static ULONG randULONG(void)
56 {
57 ULONG n;
58 randbytes(&n, sizeof(n));
59 return n;
60 }
61
62 void check(CONTEXT * pContext)
63 {
64 #ifdef _M_IX86
65 ok(pContext->ContextFlags == CONTEXT_FULL,
66 "ContextFlags=0x%lx\n", pContext->ContextFlags);
67
68 /* Random data segments */
69 ok((pContext->SegGs & NTC_SEGMENT_BITS) ==
70 (continueContext.SegGs & NTC_SEGMENT_BITS),
71 "SegGs=0x%lx / 0x%lx\n", pContext->SegGs, continueContext.SegGs);
72
73 ok((pContext->SegFs & NTC_SEGMENT_BITS) ==
74 (continueContext.SegFs & NTC_SEGMENT_BITS),
75 "SegFs=0x%lx / 0x%lx\n", pContext->SegFs, continueContext.SegFs);
76
77 ok((pContext->SegEs & NTC_SEGMENT_BITS) ==
78 (continueContext.SegEs & NTC_SEGMENT_BITS),
79 "SegEs=0x%lx / 0x%lx\n", pContext->SegEs, continueContext.SegEs);
80
81 ok((pContext->SegDs & NTC_SEGMENT_BITS) ==
82 (continueContext.SegDs & NTC_SEGMENT_BITS),
83 "SegDs=0x%lx / 0x%lx\n", pContext->SegDs, continueContext.SegDs);
84
85 /* Integer registers */
86 ok(pContext->Edi == continueContext.Edi,
87 "Edi: 0x%lx != 0x%lx\n", pContext->Edi, continueContext.Edi);
88 ok(pContext->Esi == continueContext.Esi,
89 "Esi: 0x%lx != 0x%lx\n", pContext->Esi, continueContext.Esi);
90 ok(pContext->Ebx == continueContext.Ebx,
91 "Ebx: 0x%lx != 0x%lx\n", pContext->Ebx, continueContext.Ebx);
92 ok(pContext->Edx == continueContext.Edx,
93 "Edx: 0x%lx != 0x%lx\n", pContext->Edx, continueContext.Edx);
94 ok(pContext->Ecx == continueContext.Ecx,
95 "Ecx: 0x%lx != 0x%lx\n", pContext->Ecx, continueContext.Ecx);
96 ok(pContext->Eax == continueContext.Eax,
97 "Eax: 0x%lx != 0x%lx\n", pContext->Eax, continueContext.Eax);
98
99 /* Control registers and segments */
100 ok(pContext->Ebp == continueContext.Ebp,
101 "Ebp: 0x%lx != 0x%lx\n", pContext->Ebp, continueContext.Ebp);
102 ok(pContext->Eip == continueContext.Eip,
103 "Eip: 0x%lx != 0x%lx\n", pContext->Eip, continueContext.Eip);
104 ok(pContext->Esp == continueContext.Esp,
105 "Esp: 0x%lx != 0x%lx\n", pContext->Esp, continueContext.Esp);
106
107 ok((pContext->SegCs & NTC_SEGMENT_BITS) ==
108 (continueContext.SegCs & NTC_SEGMENT_BITS),
109 "SegCs: 0x%lx != 0x%lx\n", pContext->SegCs, continueContext.SegCs);
110
111 ok((pContext->EFlags & NTC_EFLAGS_BITS) ==
112 (continueContext.EFlags & NTC_EFLAGS_BITS),
113 "EFlags: 0x%lx != 0x%lx\n", pContext->EFlags, continueContext.EFlags);
114
115 ok((pContext->SegSs & NTC_SEGMENT_BITS) ==
116 (continueContext.SegSs & NTC_SEGMENT_BITS),
117 "SegSs: 0x%lx != 0x%lx\n", pContext->SegSs, continueContext.SegSs);
118 #endif
119
120 /* Return where we came from */
121 longjmp(jmpbuf, 1);
122 }
123
124 START_TEST(NtContinue)
125 {
126 #ifdef __RUNTIME_CHECKS__
127 skip("This test breaks MSVC runtime checks!");
128 return;
129 #endif /* __RUNTIME_CHECKS__ */
130 initrand();
131
132 /* First time */
133 if(setjmp(jmpbuf) == 0)
134 {
135 CONTEXT bogus;
136
137 continueContext.ContextFlags = CONTEXT_FULL;
138 GetThreadContext(GetCurrentThread(), &continueContext);
139
140 #ifdef _M_IX86
141 continueContext.ContextFlags = CONTEXT_FULL;
142
143 /* Fill the integer registers with random values */
144 continueContext.Edi = randULONG();
145 continueContext.Esi = randULONG();
146 continueContext.Ebx = randULONG();
147 continueContext.Edx = randULONG();
148 continueContext.Ecx = randULONG();
149 continueContext.Eax = randULONG();
150 continueContext.Ebp = randULONG();
151
152 /* Randomize all the allowed flags (determined experimentally with WinDbg) */
153 continueContext.EFlags = randULONG() & 0x3C0CD5;
154
155 /* Randomize the stack pointer as much as possible */
156 continueContext.Esp = (ULONG)(((ULONG_PTR)&bogus) & 0xFFFFFFFF) +
157 sizeof(bogus) - (randULONG() & 0xF) * 4;
158
159 /* continuePoint() is implemented in assembler */
160 continueContext.Eip = (ULONG)((ULONG_PTR)continuePoint & 0xFFFFFFF);
161
162 /* Can't do a lot about segments */
163 #endif
164
165 NtContinue(&continueContext, FALSE);
166 ok(0, "should never get here\n");
167 }
168
169 /* Second time */
170 return;
171 }