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

📄 thread.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 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
STDCALL
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 STDCALL
SwitchToThread(VOID)
{
  NTSTATUS Status;
  Status = NtYieldExecution();
  return Status != STATUS_NO_YIELD_PERFORMED;
}


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

/*
 * @implemented
 */
BOOL STDCALL
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->dwLowDateTime = KernelUserTimes.CreateTime.u.LowPart;
  lpCreationTime->dwHighDateTime = KernelUserTimes.CreateTime.u.HighPart;

  lpExitTime->dwLowDateTime = KernelUserTimes.ExitTime.u.LowPart;
  lpExitTime->dwHighDateTime = KernelUserTimes.ExitTime.u.HighPart;

  lpKernelTime->dwLowDateTime = KernelUserTimes.KernelTime.u.LowPart;
  lpKernelTime->dwHighDateTime = KernelUserTimes.KernelTime.u.HighPart;

  lpUserTime->dwLowDateTime = KernelUserTimes.UserTime.u.LowPart;
  lpUserTime->dwHighDateTime = KernelUserTimes.UserTime.u.HighPart;

  return(TRUE);
}


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

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

  return(TRUE);
}


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

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

  return(TRUE);
}


/*
 * @implemented
 */
BOOL STDCALL
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);
    }

  memcpy(lpExitCode, &ThreadBasic.ExitStatus, sizeof(DWORD));

  return(TRUE);
}


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

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

  return(PreviousResumeCount);
}


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

  if (0 == hThread)
    {
      SetLastError(ERROR_INVALID_HANDLE);
      return(FALSE);
    }

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

⌨️ 快捷键说明

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