/*++

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"

extern PVOID BasepLockPrefixTable;

//
// Specify address of kernel32 lock prefixes
//
IMAGE_LOAD_CONFIG_DIRECTORY _load_config_used = {
    0,                              // 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
};

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.

--*/

{

    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;

    //
    // Start the thread at IOPL=3.
    //

    Context->EFlags = 0x3000;

    //
    // Always start the thread at the thread start thunk.
    //

    Context->Esp = (ULONG) InitialSp;

    if ( ContextType == BaseContextTypeThread ) {
        Context->Eip = (ULONG) BaseThreadStartThunk;
        }
    else if ( ContextType == BaseContextTypeFiber ) {
        Context->Eip = (ULONG) BaseFiberStart;
        }
    else {
        Context->Eip = (ULONG) BaseProcessStartThunk;
        }
    //
    // add code to check alignment and raise exception...
    //

    Context->ContextFlags = CONTEXT_FULL;
    Context->Esp -= sizeof(Parameter); // Reserve room for ret address
}

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 );
}