⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 thread.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * COPYRIGHT:       See COPYING in the top level directory
 * PROJECT:         ReactOS system libraries
 * FILE:            lib/kernel32/thread/thread.c
 * PURPOSE:         Thread functions
 * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
 *                  Ariadne ( ariadne@xs4all.nl)
 *
 */

/* INCLUDES ******************************************************************/

#include <k32.h>

#define NDEBUG
#include "../include/debug.h"

/* FIXME: NDK */
#define HIGH_PRIORITY 31

/* FUNCTIONS *****************************************************************/
_SEH_FILTER(BaseThreadExceptionFilter)
{
   EXCEPTION_POINTERS * ExceptionInfo = _SEH_GetExceptionPointers();
   LONG ExceptionDisposition = EXCEPTION_EXECUTE_HANDLER;

   if (GlobalTopLevelExceptionFilter != NULL)
   {
      _SEH_TRY
      {
         ExceptionDisposition = GlobalTopLevelExceptionFilter(ExceptionInfo);
      }
      _SEH_HANDLE
      {
         ExceptionDisposition = UnhandledExceptionFilter(ExceptionInfo);
      }
      _SEH_END;
   }

   return ExceptionDisposition;
}

__declspec(noreturn)
VOID
STDCALL
BaseThreadStartup(LPTHREAD_START_ROUTINE lpStartAddress,
                  LPVOID lpParameter)
{
    volatile UINT uExitCode = 0;

    /* Attempt to call the Thread Start Address */
    _SEH_TRY
    {
        /* Get the exit code from the Thread Start */
        uExitCode = (lpStartAddress)((PVOID)lpParameter);
    }
    _SEH_EXCEPT(BaseThreadExceptionFilter)
    {
        /* Get the Exit code from the SEH Handler */
        uExitCode = _SEH_GetExceptionCode();
    } _SEH_END;
   
    /* Exit the Thread */
    ExitThread(uExitCode);
}

/*
 * @implemented
 */
HANDLE
STDCALL
CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,
             DWORD dwStackSize,
             LPTHREAD_START_ROUTINE lpStartAddress,
             LPVOID lpParameter,
             DWORD dwCreationFlags,
             LPDWORD lpThreadId)
{
    /* Act as if we're going to create a remote thread in ourselves */
    return CreateRemoteThread(NtCurrentProcess(),
                              lpThreadAttributes,
                              dwStackSize,
                              lpStartAddress,
                              lpParameter,
                              dwCreationFlags,
                              lpThreadId);
}

/*
 * @implemented
 */
HANDLE
STDCALL
CreateRemoteThread(HANDLE hProcess,
                   LPSECURITY_ATTRIBUTES lpThreadAttributes,
                   DWORD dwStackSize,
                   LPTHREAD_START_ROUTINE lpStartAddress,
                   LPVOID lpParameter,
                   DWORD dwCreationFlags,
                   LPDWORD lpThreadId)
{
    NTSTATUS Status;
    INITIAL_TEB InitialTeb;
    CONTEXT Context;
    CLIENT_ID ClientId;
    OBJECT_ATTRIBUTES LocalObjectAttributes;
    POBJECT_ATTRIBUTES ObjectAttributes;
    HANDLE hThread;
    ULONG Dummy;
    
    DPRINT("CreateRemoteThread: hProcess: %ld dwStackSize: %ld lpStartAddress"
            ": %p lpParameter: %lx, dwCreationFlags: %lx\n", hProcess, 
            dwStackSize, lpStartAddress, lpParameter, dwCreationFlags);
    
    /* Clear the Context */
    RtlZeroMemory(&Context, sizeof(CONTEXT));
    
    /* Write PID */
    ClientId.UniqueProcess = hProcess;
    
    /* Create the Stack */
    Status = BasepCreateStack(hProcess,
                              dwStackSize,
                              dwCreationFlags & STACK_SIZE_PARAM_IS_A_RESERVATION ?
                              dwStackSize : 0,
                              &InitialTeb);    
    if(!NT_SUCCESS(Status))
    {
        SetLastErrorByStatus(Status);
        return NULL;
    }
    
    /* Create Initial Context */
    BasepInitializeContext(&Context,
                           lpParameter,
                           lpStartAddress,
                           InitialTeb.StackBase,
                           1);
    
    /* initialize the attributes for the thread object */
    ObjectAttributes = BasepConvertObjectAttributes(&LocalObjectAttributes,
                                                    lpThreadAttributes,
                                                    NULL);
    
    /* Create the Kernel Thread Object */
    Status = NtCreateThread(&hThread,
                            THREAD_ALL_ACCESS,
                            ObjectAttributes,
                            hProcess,
                            &ClientId,
                            &Context,
                            &InitialTeb,
                            TRUE);
    if(!NT_SUCCESS(Status))
    {
        BasepFreeStack(hProcess, &InitialTeb);
        SetLastErrorByStatus(Status);
        return NULL;
    }
    
    #ifdef SXS_SUPPORT_ENABLED
    /* Are we in the same process? */
    if (Process = NtCurrentProcess())
    {
        PTEB Teb;
        PVOID ActivationContextStack;
        PTHREAD_BASIC_INFORMATION ThreadBasicInfo;
        PACTIVATION_CONTEXT_BASIC_INFORMATION ActivationCtxInfo;
        ULONG_PTR Cookie;
        
        /* Get the TEB */
        Status = NtQueryInformationThread(hThread,
                                          ThreadBasicIformation,
                                          &ThreadBasicInfo,
                                          sizeof(ThreadBasicInfo),
                                          NULL);
                                          
        /* Allocate the Activation Context Stack */
        Status = RtlAllocateActivationContextStack(&ActivationContextStack);
        Teb = ThreadBasicInfo.TebBaseAddress;
        
        /* Save it */
        Teb->ActivationContextStackPointer = ActivationContextStack;
        
        /* Query the Context */
        Status = RtlQueryInformationActivationContext(1,
                                                      0,
                                                      NULL,
                                                      ActivationContextBasicInformation,
                                                      &ActivationCtxInfo,
                                                      sizeof(ActivationCtxInfo),
                                                      NULL);
                                                      
        /* Does it need to be activated? */
        if (!ActivationCtxInfo.hActCtx)
        {
            /* Activate it */
            Status = RtlActivateActivationContextEx(1,
                                                    Teb,
                                                    ActivationCtxInfo.hActCtx,
                                                    &Cookie);
        }
    }
    #endif
    
    /* FIXME: Notify CSR */

    /* Success */
    if(lpThreadId) *lpThreadId = (DWORD)ClientId.UniqueThread;
    
    /* Resume it if asked */
    if (!(dwCreationFlags & CREATE_SUSPENDED))
    {
        NtResumeThread(hThread, &Dummy);
    }
    
    /* Return handle to thread */
    return hThread;
}

/*
 * @implemented
 */
VOID
STDCALL
ExitThread(DWORD uExitCode)
{
    NTSTATUS Status;
    BOOLEAN LastThread;
    
    /*
     * Terminate process if this is the last thread
     * of the current process
     */
    Status = NtQueryInformationThread(NtCurrentThread(),
                                      ThreadAmILastThread,
                                      &LastThread,
                                      sizeof(BOOLEAN),
                                      NULL);
    if (NT_SUCCESS(Status) && LastThread)
    {
        /* Exit the Process */
        ExitProcess(uExitCode);
    }

    /* Notify DLLs and TLS Callbacks of termination */
    LdrShutdownThread();
    
    /* Tell the Kernel to free the Stack */
    NtCurrentTeb()->FreeStackOnTermination = TRUE;
    NtTerminateThread(NULL, uExitCode);
    
    /* We will never reach this place. This silences the compiler */
    ExitThread(uExitCode);
}

/*
 * @implemented
 */
HANDLE
WINAPI
OpenThread(DWORD dwDesiredAccess,
           BOOL bInheritHandle,
           DWORD dwThreadId)
{
    NTSTATUS errCode;
    HANDLE ThreadHandle;
    OBJECT_ATTRIBUTES ObjectAttributes;
    CLIENT_ID ClientId ;

    ClientId.UniqueProcess = 0;
    ClientId.UniqueThread = (HANDLE)dwThreadId;

    InitializeObjectAttributes(&ObjectAttributes,
                               NULL,
                               (bInheritHandle ? OBJ_INHERIT : 0),
                               NULL,
                               NULL);

    errCode = NtOpenThread(&ThreadHandle,
                           dwDesiredAccess,
                           &ObjectAttributes,
                           &ClientId);
    if (!NT_SUCCESS(errCode))
    {
        SetLastErrorByStatus (errCode);
        return NULL;
    }

    return ThreadHandle;
}

/*
 * @implemented
 */
PTEB
GetTeb(VOID)
{
    return NtCurrentTeb();
}

/*
 * @implemented
 */
BOOL
WINAPI
SwitchToThread(VOID)
{
    NTSTATUS Status;
    Status = NtYieldExecution();
    return Status != STATUS_NO_YIELD_PERFORMED;
}


/*
 * @implemented
 */
DWORD
WINAPI
GetCurrentThreadId(VOID)
{
    return (DWORD)(NtCurrentTeb()->Cid).UniqueThread;
}

/*
 * @implemented
 */
BOOL
NTAPI
GetThreadTimes(HANDLE hThread,
               LPFILETIME lpCreationTime,
               LPFILETIME lpExitTime,
               LPFILETIME lpKernelTime,
               LPFILETIME lpUserTime)
{
    KERNEL_USER_TIMES KernelUserTimes;
    NTSTATUS Status;

    Status = NtQueryInformationThread(hThread,
                                      ThreadTimes,
                                      &KernelUserTimes,
                                      sizeof(KERNEL_USER_TIMES),
                                      NULL);
    if (!NT_SUCCESS(Status))
    {
        SetLastErrorByStatus(Status);
        return(FALSE);
    }

    *lpCreationTime = *(LPFILETIME)&KernelUserTimes.CreateTime;
    *lpExitTime = *(LPFILETIME)&KernelUserTimes.ExitTime;
    *lpKernelTime = *(LPFILETIME)&KernelUserTimes.KernelTime;
    *lpUserTime = *(LPFILETIME)&KernelUserTimes.UserTime;
    return TRUE;
}

/*
 * @implemented
 */
BOOL
WINAPI
GetThreadContext(HANDLE hThread,
                 LPCONTEXT lpContext)
{
    NTSTATUS Status;

    Status = NtGetContextThread(hThread, lpContext);
    if (!NT_SUCCESS(Status))
    {
        SetLastErrorByStatus(Status);
        return FALSE;
    }

    return TRUE;
}

/*
 * @implemented
 */
BOOL
WINAPI
SetThreadContext(HANDLE hThread,
                 CONST CONTEXT *lpContext)
{
    NTSTATUS Status;

    Status = NtSetContextThread(hThread, (PCONTEXT)lpContext);
    if (!NT_SUCCESS(Status))
    {
        SetLastErrorByStatus(Status);
        return FALSE;
    }

    return TRUE;
}

/*
 * @implemented
 */
BOOL
WINAPI
GetExitCodeThread(HANDLE hThread,
                  LPDWORD lpExitCode)
{
    THREAD_BASIC_INFORMATION ThreadBasic;
    NTSTATUS Status;

    Status = NtQueryInformationThread(hThread,
                                      ThreadBasicInformation,
                                      &ThreadBasic,
                                      sizeof(THREAD_BASIC_INFORMATION),
                                      NULL);
    if (!NT_SUCCESS(Status))
    {
        SetLastErrorByStatus(Status);
        return(FALSE);
    }

    *lpExitCode = ThreadBasic.ExitStatus;
    return TRUE;
}

/*
 * @implemented
 */
DWORD
WINAPI
ResumeThread(HANDLE hThread)
{
    ULONG PreviousResumeCount;
    NTSTATUS Status;

    Status = NtResumeThread(hThread, &PreviousResumeCount);
    if (!NT_SUCCESS(Status))
    {
        SetLastErrorByStatus(Status);
        return -1;
    }

    return PreviousResumeCount;
}

/*
 * @implemented
 */
BOOL
WINAPI
TerminateThread(HANDLE hThread,
                DWORD dwExitCode)
{
    NTSTATUS Status;

    if (!hThread)
    {
        SetLastError(ERROR_INVALID_HANDLE);
        return FALSE;
    }

    Status = NtTerminateThread(hThread, dwExitCode);
    if (!NT_SUCCESS(Status))
    {
        SetLastErrorByStatus(Status);
        return FALSE;
    }

    return TRUE;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -