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 }
171