/*++ Copyright (c) 1990 Microsoft Corporation Module Name: context.c Abstract: This module contains the context management routines for Win32 Author: Mark Lucovsky (markl) 28-Sep-1990 Revision History: --*/ #include "basedll.h" #ifdef _X86_ extern PVOID BasepLockPrefixTable; extern PVOID __safe_se_handler_table[]; /* base of safe handler entry table */ extern BYTE __safe_se_handler_count; /* absolute symbol whose address is the count of table entries */ // // Specify address of kernel32 lock prefixes // IMAGE_LOAD_CONFIG_DIRECTORY _load_config_used = { sizeof(_load_config_used), // Reserved 0, // Reserved 0, // Reserved 0, // Reserved 0, // GlobalFlagsClear 0, // GlobalFlagsSet 0, // CriticalSectionTimeout (milliseconds) 0, // DeCommitFreeBlockThreshold 0, // DeCommitTotalFreeThreshold (ULONG) &BasepLockPrefixTable, // LockPrefixTable 0, 0, 0, 0, 0, 0, 0, // Reserved 0, // & security_cookie (ULONG)__safe_se_handler_table, (ULONG)&__safe_se_handler_count }; #endif VOID BaseInitializeContext( OUT PCONTEXT Context, IN PVOID Parameter OPTIONAL, IN PVOID InitialPc OPTIONAL, IN PVOID InitialSp OPTIONAL, IN BASE_CONTEXT_TYPE ContextType ) /*++ Routine Description: This function initializes a context structure so that it can be used in a subsequent call to NtCreateThread. Arguments: Context - Supplies a context buffer to be initialized by this routine. Parameter - Supplies the thread's parameter. InitialPc - Supplies an initial program counter value. InitialSp - Supplies an initial stack pointer value. NewThread - Supplies a flag that specifies that this is a new thread, or a new process. Return Value: Raises STATUS_BAD_INITIAL_STACK if the value of InitialSp is not properly aligned. Raises STATUS_BAD_INITIAL_PC if the value of InitialPc is not properly aligned. --*/ { ULONG ContextFlags; Context->Eax = (ULONG)InitialPc; Context->Ebx = (ULONG)Parameter; Context->SegGs = 0; Context->SegFs = KGDT_R3_TEB; Context->SegEs = KGDT_R3_DATA; Context->SegDs = KGDT_R3_DATA; Context->SegSs = KGDT_R3_DATA; Context->SegCs = KGDT_R3_CODE; // // Save context flags and set context flags to full. // ContextFlags = Context->ContextFlags; Context->ContextFlags = CONTEXT_FULL; // // Start the thread at IOPL=3. // Context->EFlags = 0x3000; // // Always start the thread at the thread start thunk. // Context->Esp = (ULONG) InitialSp - sizeof(PVOID); if ( ContextType == BaseContextTypeThread ) { Context->Eip = (ULONG) BaseThreadStartThunk; } else if ( ContextType == BaseContextTypeFiber ) { Context->Esp -= sizeof(PVOID); *(PULONG)Context->Esp = (ULONG) BaseFiberStart; Context->ContextFlags |= ContextFlags; // // If context switching of the floating state is specified, then // initialize the floating context. // if (ContextFlags == CONTEXT_FLOATING_POINT) { Context->FloatSave.ControlWord = 0x27f; Context->FloatSave.StatusWord = 0; Context->FloatSave.TagWord = 0xffff; Context->FloatSave.ErrorOffset = 0; Context->FloatSave.ErrorSelector = 0; Context->FloatSave.DataOffset = 0; Context->FloatSave.DataSelector = 0; if (USER_SHARED_DATA->ProcessorFeatures[PF_XMMI_INSTRUCTIONS_AVAILABLE] != FALSE) { Context->Dr6 = 0x1f80; } } } else { Context->Eip = (ULONG) BaseProcessStartThunk; } return; } VOID BaseFiberStart( VOID ) /*++ Routine Description: This function is called to start a Win32 fiber. Its purpose is to call BaseThreadStart, getting the necessary arguments from the fiber context record. Arguments: None. Return Value: None. --*/ { PFIBER Fiber; Fiber = GetCurrentFiber(); BaseThreadStart( (LPTHREAD_START_ROUTINE)Fiber->FiberContext.Eax, (LPVOID)Fiber->FiberContext.Ebx ); }