bfaa535ba1f15d92027ed926a62650a1c796a4c3
[reactos.git] / lib / rosrtl / thread / context.c
1 /* $Id$
2 */
3 /*
4 */
5
6 #include <ddk/ntddk.h>
7 #include <rosrtl/thread.h>
8
9 #if defined(_M_IX86)
10 #include <napi/i386/segment.h>
11 #include <napi/i386/floatsave.h>
12 #else
13 #error Unsupported architecture
14 #endif
15
16 NTSTATUS NTAPI RtlRosInitializeContextEx
17 (
18  IN HANDLE ProcessHandle,
19  IN PCONTEXT Context,
20  IN PTHREAD_START_ROUTINE StartAddress,
21  IN PUSER_STACK UserStack,
22  IN ULONG ParameterCount,
23  IN ULONG_PTR * Parameters
24 )
25 {
26  ULONG nDummy;
27  PCHAR pStackBase;
28  PCHAR pStackLimit;
29  ULONG_PTR nRetAddr = 0xDEADBEEF;
30  SIZE_T nParamsSize = ParameterCount * sizeof(ULONG_PTR);
31  NTSTATUS nErrCode;
32
33  /* fixed-size stack */
34  if(UserStack->FixedStackBase && UserStack->FixedStackLimit)
35  {
36   pStackBase = UserStack->FixedStackBase;
37   pStackLimit = UserStack->FixedStackLimit;
38  }
39  /* expandable stack */
40  else if(UserStack->ExpandableStackBase && UserStack->ExpandableStackLimit)
41  {
42   pStackBase = UserStack->ExpandableStackBase;
43   pStackLimit = UserStack->ExpandableStackLimit;
44  }
45  /* bad initial stack */
46  else
47   return STATUS_BAD_INITIAL_STACK;
48
49  /* stack base lower than the limit */
50  if(pStackBase <= pStackLimit)
51   return STATUS_BAD_INITIAL_STACK;
52
53 #if defined(_M_IX86)
54  /* Intel x86: all parameters passed on the stack */
55  /* too many parameters */
56  if((nParamsSize + sizeof(ULONG_PTR)) > (SIZE_T)(pStackBase - pStackLimit))
57   return STATUS_STACK_OVERFLOW;
58
59  memset(Context, 0, sizeof(CONTEXT));
60
61  /* initialize the context */
62  Context->ContextFlags = CONTEXT_FULL;
63  Context->FloatSave.ControlWord = FLOAT_SAVE_CONTROL;
64  Context->FloatSave.StatusWord = FLOAT_SAVE_STATUS;
65  Context->FloatSave.TagWord = FLOAT_SAVE_TAG;
66  Context->FloatSave.DataSelector = FLOAT_SAVE_DATA;
67  Context->Eip = (ULONG_PTR)StartAddress;
68  Context->SegGs = USER_DS;
69  Context->SegFs = TEB_SELECTOR;
70  Context->SegEs = USER_DS;
71  Context->SegDs = USER_DS;
72  Context->SegCs = USER_CS;
73  Context->SegSs = USER_DS;
74  Context->Esp = (ULONG_PTR)pStackBase - (nParamsSize + sizeof(ULONG_PTR));
75  Context->EFlags = ((ULONG_PTR)1 << 1) | ((ULONG_PTR)1 << 9);
76
77  /* write the parameters */
78  nErrCode = NtWriteVirtualMemory
79  (
80   ProcessHandle,
81   ((PUCHAR)pStackBase) - nParamsSize,
82   Parameters,
83   nParamsSize,
84   &nDummy
85  );
86
87  /* failure */
88  if(!NT_SUCCESS(nErrCode)) return nErrCode;
89
90  /* write the return address */
91  return NtWriteVirtualMemory
92  (
93   ProcessHandle,
94   ((PUCHAR)pStackBase) - (nParamsSize + sizeof(ULONG_PTR)),
95   &nRetAddr,
96   sizeof(ULONG_PTR),
97   &nDummy
98  );
99
100 #else
101 #error Unsupported architecture
102 #endif
103 }
104
105 /* EOF */