--- /dev/null
+/*
+ * PROJECT: ReactOS api tests
+ * LICENSE: GPL - See COPYING in the top level directory
+ * PURPOSE: Test for ZwContinue
+ * PROGRAMMER:
+ */
+
+#include <setjmp.h>
+#include <stdio.h>
+#include <time.h>
+#include <wine/test.h>
+
+#ifdef _M_IX86
+#define ZWC_SEGMENT_BITS (0xFFFF)
+#define ZWC_EFLAGS_BITS (0x3C0CD5)
+#endif
+
+void continuePoint(void);
+LONG NTAPI ZwContinue(IN CONTEXT *, IN BOOLEAN);
+
+static jmp_buf jmpbuf;
+static CONTEXT continueContext;
+static unsigned int nRandBytes;
+
+static int initrand(void)
+{
+ unsigned int nRandMax;
+ unsigned int nRandMaxBits;
+ time_t tLoc;
+
+ nRandMax = RAND_MAX;
+ for(nRandMaxBits = 0; nRandMax != 0; nRandMax >>= 1, ++ nRandMaxBits);
+ nRandBytes = nRandMaxBits / CHAR_BIT;
+ //assert(nRandBytes != 0);
+ srand((unsigned)(time(&tLoc) & UINT_MAX));
+ return 1;
+}
+
+static void randbytes(void * p, size_t n)
+{
+ unsigned char * b;
+ size_t i;
+ int r = rand();
+
+ b = (unsigned char *)p;
+ for(i = 0; i < n; ++ i)
+ {
+ if(i % nRandBytes == 0)
+ r = rand();
+ b[i] = (unsigned char)(r & UCHAR_MAX);
+ r >>= CHAR_BIT;
+ }
+}
+
+static ULONG randULONG(void)
+{
+ ULONG n;
+ randbytes(&n, sizeof(n));
+ return n;
+}
+
+void check(CONTEXT * pContext)
+{
+#ifdef _M_IX86
+ ok(pContext->ContextFlags == CONTEXT_FULL,
+ "ContextFlags=0x%lx\n", pContext->ContextFlags);
+
+ /* Random data segments */
+ ok((pContext->SegGs & ZWC_SEGMENT_BITS) ==
+ (continueContext.SegGs & ZWC_SEGMENT_BITS),
+ "SegGs=0x%lx / 0x%lx\n", pContext->SegGs, continueContext.SegGs);
+
+ ok((pContext->SegFs & ZWC_SEGMENT_BITS) ==
+ (continueContext.SegFs & ZWC_SEGMENT_BITS),
+ "SegFs=0x%lx / 0x%lx\n", pContext->SegFs, continueContext.SegFs);
+
+ ok((pContext->SegEs & ZWC_SEGMENT_BITS) ==
+ (continueContext.SegEs & ZWC_SEGMENT_BITS),
+ "SegEs=0x%lx / 0x%lx\n", pContext->SegEs, continueContext.SegEs);
+
+ ok((pContext->SegDs & ZWC_SEGMENT_BITS) ==
+ (continueContext.SegDs & ZWC_SEGMENT_BITS),
+ "SegDs=0x%lx / 0x%lx\n", pContext->SegDs, continueContext.SegDs);
+
+ /* Integer registers */
+ ok(pContext->Edi == continueContext.Edi,
+ "Edi: 0x%lx != 0x%lx\n", pContext->Edi, continueContext.Edi);
+ ok(pContext->Esi == continueContext.Esi,
+ "Esi: 0x%lx != 0x%lx\n", pContext->Esi, continueContext.Esi);
+ ok(pContext->Ebx == continueContext.Ebx,
+ "Ebx: 0x%lx != 0x%lx\n", pContext->Ebx, continueContext.Ebx);
+ ok(pContext->Edx == continueContext.Edx,
+ "Edx: 0x%lx != 0x%lx\n", pContext->Edx, continueContext.Edx);
+ ok(pContext->Ecx == continueContext.Ecx,
+ "Ecx: 0x%lx != 0x%lx\n", pContext->Ecx, continueContext.Ecx);
+ ok(pContext->Eax == continueContext.Eax,
+ "Eax: 0x%lx != 0x%lx\n", pContext->Eax, continueContext.Eax);
+
+ /* Control registers and segments */
+ ok(pContext->Ebp == continueContext.Ebp,
+ "Ebp: 0x%lx != 0x%lx\n", pContext->Ebp, continueContext.Ebp);
+ ok(pContext->Eip == continueContext.Eip,
+ "Eip: 0x%lx != 0x%lx\n", pContext->Eip, continueContext.Eip);
+ ok(pContext->Esp == continueContext.Esp,
+ "Esp: 0x%lx != 0x%lx\n", pContext->Esp, continueContext.Esp);
+
+ ok((pContext->SegCs & ZWC_SEGMENT_BITS) ==
+ (continueContext.SegCs & ZWC_SEGMENT_BITS),
+ "SegCs: 0x%lx != 0x%lx\n", pContext->SegCs, continueContext.SegCs);
+
+ ok((pContext->EFlags & ZWC_EFLAGS_BITS) ==
+ (continueContext.EFlags & ZWC_EFLAGS_BITS),
+ "EFlags: 0x%lx != 0x%lx\n", pContext->EFlags, continueContext.EFlags);
+
+ ok((pContext->SegSs & ZWC_SEGMENT_BITS) ==
+ (continueContext.SegSs & ZWC_SEGMENT_BITS),
+ "SegSs: 0x%lx != 0x%lx\n", pContext->SegSs, continueContext.SegSs);
+#endif
+
+ /* Return where we came from */
+ longjmp(jmpbuf, 1);
+}
+
+void Test_ZwContinue()
+{
+ initrand();
+
+ /* First time */
+ if(setjmp(jmpbuf) == 0)
+ {
+ CONTEXT bogus;
+
+ continueContext.ContextFlags = CONTEXT_FULL;
+ GetThreadContext(GetCurrentThread(), &continueContext);
+
+#ifdef _M_IX86
+ continueContext.ContextFlags = CONTEXT_FULL;
+
+ /* Fill the integer registers with random values */
+ continueContext.Edi = randULONG();
+ continueContext.Esi = randULONG();
+ continueContext.Ebx = randULONG();
+ continueContext.Edx = randULONG();
+ continueContext.Ecx = randULONG();
+ continueContext.Eax = randULONG();
+ continueContext.Ebp = randULONG();
+
+ /* Randomize all the allowed flags (determined experimentally with WinDbg) */
+ continueContext.EFlags = randULONG() & 0x3C0CD5;
+
+ /* Randomize the stack pointer as much as possible */
+ continueContext.Esp = (ULONG)(((ULONG_PTR)&bogus) & 0xFFFFFFFF) +
+ sizeof(bogus) - (randULONG() & 0xF) * 4;
+
+ /* continuePoint() is implemented in assembler */
+ continueContext.Eip = (ULONG)((ULONG_PTR)continuePoint & 0xFFFFFFF);
+
+ /* Can't do a lot about segments */
+#endif
+
+ ZwContinue(&continueContext, FALSE);
+ ok(0, "should never get here\n");
+ }
+
+ /* Second time */
+ return;
+}
+
+START_TEST(ZwContinue)
+{
+ Test_ZwContinue();
+}
+