update for HEAD-2003050101
[reactos.git] / lib / rosrtl / thread / context.c
diff --git a/lib/rosrtl/thread/context.c b/lib/rosrtl/thread/context.c
new file mode 100644 (file)
index 0000000..bfaa535
--- /dev/null
@@ -0,0 +1,105 @@
+/* $Id$
+*/
+/*
+*/
+
+#include <ddk/ntddk.h>
+#include <rosrtl/thread.h>
+
+#if defined(_M_IX86)
+#include <napi/i386/segment.h>
+#include <napi/i386/floatsave.h>
+#else
+#error Unsupported architecture
+#endif
+
+NTSTATUS NTAPI RtlRosInitializeContextEx
+(
+ IN HANDLE ProcessHandle,
+ IN PCONTEXT Context,
+ IN PTHREAD_START_ROUTINE StartAddress,
+ IN PUSER_STACK UserStack,
+ IN ULONG ParameterCount,
+ IN ULONG_PTR * Parameters
+)
+{
+ ULONG nDummy;
+ PCHAR pStackBase;
+ PCHAR pStackLimit;
+ ULONG_PTR nRetAddr = 0xDEADBEEF;
+ SIZE_T nParamsSize = ParameterCount * sizeof(ULONG_PTR);
+ NTSTATUS nErrCode;
+
+ /* fixed-size stack */
+ if(UserStack->FixedStackBase && UserStack->FixedStackLimit)
+ {
+  pStackBase = UserStack->FixedStackBase;
+  pStackLimit = UserStack->FixedStackLimit;
+ }
+ /* expandable stack */
+ else if(UserStack->ExpandableStackBase && UserStack->ExpandableStackLimit)
+ {
+  pStackBase = UserStack->ExpandableStackBase;
+  pStackLimit = UserStack->ExpandableStackLimit;
+ }
+ /* bad initial stack */
+ else
+  return STATUS_BAD_INITIAL_STACK;
+
+ /* stack base lower than the limit */
+ if(pStackBase <= pStackLimit)
+  return STATUS_BAD_INITIAL_STACK;
+
+#if defined(_M_IX86)
+ /* Intel x86: all parameters passed on the stack */
+ /* too many parameters */
+ if((nParamsSize + sizeof(ULONG_PTR)) > (SIZE_T)(pStackBase - pStackLimit))
+  return STATUS_STACK_OVERFLOW;
+
+ memset(Context, 0, sizeof(CONTEXT));
+
+ /* initialize the context */
+ Context->ContextFlags = CONTEXT_FULL;
+ Context->FloatSave.ControlWord = FLOAT_SAVE_CONTROL;
+ Context->FloatSave.StatusWord = FLOAT_SAVE_STATUS;
+ Context->FloatSave.TagWord = FLOAT_SAVE_TAG;
+ Context->FloatSave.DataSelector = FLOAT_SAVE_DATA;
+ Context->Eip = (ULONG_PTR)StartAddress;
+ Context->SegGs = USER_DS;
+ Context->SegFs = TEB_SELECTOR;
+ Context->SegEs = USER_DS;
+ Context->SegDs = USER_DS;
+ Context->SegCs = USER_CS;
+ Context->SegSs = USER_DS;
+ Context->Esp = (ULONG_PTR)pStackBase - (nParamsSize + sizeof(ULONG_PTR));
+ Context->EFlags = ((ULONG_PTR)1 << 1) | ((ULONG_PTR)1 << 9);
+
+ /* write the parameters */
+ nErrCode = NtWriteVirtualMemory
+ (
+  ProcessHandle,
+  ((PUCHAR)pStackBase) - nParamsSize,
+  Parameters,
+  nParamsSize,
+  &nDummy
+ );
+
+ /* failure */
+ if(!NT_SUCCESS(nErrCode)) return nErrCode;
+
+ /* write the return address */
+ return NtWriteVirtualMemory
+ (
+  ProcessHandle,
+  ((PUCHAR)pStackBase) - (nParamsSize + sizeof(ULONG_PTR)),
+  &nRetAddr,
+  sizeof(ULONG_PTR),
+  &nDummy
+ );
+
+#else
+#error Unsupported architecture
+#endif
+}
+
+/* EOF */