Пример #1
0
HANDLE CSysinfo::OpenThread (DWORD tid, DWORD accessflag)
{
	HANDLE hThread = NULL;
	DWORD struct1[] = {0x18, 0, 0, 0, 0, 0}; //OBJECT_ATTRIBUTES
	DWORD struct2[] = {0,tid}; //CLIENT_ID
	NtOpenThread (&hThread, 
			   accessflag, 
			   struct1, 
			   struct2);

	return hThread;
}
Пример #2
0
static int wine_pthread_cancel(pthread_t thread)
{
  CLIENT_ID cid;
  NTSTATUS status;
  HANDLE handle;

  cid.UniqueProcess = 0;
  cid.UniqueThread = (HANDLE)thread;
  status = NtOpenThread( &handle, THREAD_TERMINATE, NULL, &cid );
  if (!status)
  {
    status = NtTerminateThread( handle, 0 );
    NtClose( handle );
  }
  if (status) return EINVAL;
  return 0;
}
Пример #3
0
static int wine_pthread_join(pthread_t thread, void **value_ptr)
{
  THREAD_BASIC_INFORMATION info;
  CLIENT_ID cid;
  NTSTATUS status;
  HANDLE handle;

  cid.UniqueProcess = 0;
  cid.UniqueThread = (HANDLE)thread;
  status = NtOpenThread( &handle, THREAD_QUERY_INFORMATION|SYNCHRONIZE, NULL, &cid );
  if (!status)
  {
    NtWaitForMultipleObjects( 1, &handle, FALSE, FALSE, NULL );
    status = NtQueryInformationThread( handle, ThreadBasicInformation, &info, sizeof(info), NULL );
    NtClose( handle );
    if (!status) *value_ptr = UlongToPtr(info.ExitStatus);
  }
  if (status) return EINVAL; /* FIXME: make this more correctly match windows errors */
  return 0;
}
Пример #4
0
/***********************************************************************
 * OpenThread  [KERNEL32.@]   Retrieves a handle to a thread from its thread id
 */
HANDLE WINAPI OpenThread( DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwThreadId )
{
    NTSTATUS status;
    HANDLE handle;
    OBJECT_ATTRIBUTES attr;
    CLIENT_ID cid;

    attr.Length = sizeof(attr);
    attr.RootDirectory = 0;
    attr.Attributes = bInheritHandle ? OBJ_INHERIT : 0;
    attr.ObjectName = NULL;
    attr.SecurityDescriptor = NULL;
    attr.SecurityQualityOfService = NULL;

    cid.UniqueProcess = 0; /* FIXME */
    cid.UniqueThread = ULongToHandle(dwThreadId);
    status = NtOpenThread( &handle, dwDesiredAccess, &attr, &cid );
    if (status)
    {
        SetLastError( RtlNtStatusToDosError(status) );
        handle = 0;
    }
    return handle;
}
Пример #5
0
/*
* SfuAdjustCurrentThreadPriv
*
* Purpose:
*
* Impersonate thread and adjust privileges.
*
*/
BOOL SfuAdjustCurrentThreadPriv(
	PCLIENT_ID SourceThread
	)
{
	BOOL                         cond = FALSE;
	NTSTATUS                     status = STATUS_UNSUCCESSFUL;
	HANDLE			             hThread = NULL, hToken = NULL;
	OBJECT_ATTRIBUTES            obja;
	SECURITY_QUALITY_OF_SERVICE  SecurityQos;
	TOKEN_PRIVILEGES             *NewState = NULL;
	ULONG                        uLen;

	do {

		InitializeObjectAttributes(&obja, NULL, 0, NULL, NULL);
		status = NtOpenThread(&hThread, THREAD_DIRECT_IMPERSONATION, &obja, SourceThread);
		if (!NT_SUCCESS(status))
			break;

		SecurityQos.Length = sizeof(SecurityQos);
		SecurityQos.ImpersonationLevel = SecurityImpersonation;
		SecurityQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
		SecurityQos.EffectiveOnly = FALSE;
		status = NtImpersonateThread(NtCurrentThread(), hThread, &SecurityQos);
		if (!NT_SUCCESS(status))
			break;

		status = NtOpenThreadTokenEx(NtCurrentThread(), TOKEN_ADJUST_PRIVILEGES, FALSE, 0, &hToken);
		if (!NT_SUCCESS(status))
			break;

		uLen = sizeof(TOKEN_PRIVILEGES) + (6 * sizeof(LUID_AND_ATTRIBUTES));

		NewState = RtlAllocateHeap(NtCurrentPeb()->ProcessHeap, HEAP_ZERO_MEMORY, uLen);
		if (NewState == NULL)
			break;

		NewState->PrivilegeCount = 6;

		NewState->Privileges[0].Luid.LowPart = SE_TCB_PRIVILEGE;
		NewState->Privileges[0].Luid.HighPart = 0;
		NewState->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT | SE_PRIVILEGE_ENABLED;

		NewState->Privileges[1].Luid.LowPart = SE_TAKE_OWNERSHIP_PRIVILEGE;
		NewState->Privileges[1].Luid.HighPart = 0;
		NewState->Privileges[1].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT | SE_PRIVILEGE_ENABLED;

		NewState->Privileges[2].Luid.LowPart = SE_RESTORE_PRIVILEGE;
		NewState->Privileges[2].Luid.HighPart = 0;
		NewState->Privileges[2].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT | SE_PRIVILEGE_ENABLED;

		NewState->Privileges[3].Luid.LowPart = SE_DEBUG_PRIVILEGE;
		NewState->Privileges[3].Luid.HighPart = 0;
		NewState->Privileges[3].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT | SE_PRIVILEGE_ENABLED;

		NewState->Privileges[4].Luid.LowPart = SE_LOAD_DRIVER_PRIVILEGE;
		NewState->Privileges[4].Luid.HighPart = 0;
		NewState->Privileges[4].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT | SE_PRIVILEGE_ENABLED;

		NewState->Privileges[5].Luid.LowPart = SE_SECURITY_PRIVILEGE;
		NewState->Privileges[5].Luid.HighPart = 0;
		NewState->Privileges[5].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT | SE_PRIVILEGE_ENABLED;
		
		status = NtAdjustPrivilegesToken(hToken, FALSE, NewState, 0, NULL, NULL);

	} while (cond);

	if (hToken != NULL) NtClose(hToken);
	if (hThread != NULL) NtClose(hThread);
	if (NewState != NULL) RtlFreeHeap(NtCurrentPeb()->ProcessHeap, 0, NewState);

	return NT_SUCCESS(status);
}
Пример #6
0
BOOL GetThreadIDHTASKALIAS(
    DWORD  dwThreadID32,
    HTASKALIAS *ha
) {
    OBJECT_ATTRIBUTES   obja;
    THREAD_BASIC_INFORMATION ThreadInfo;
    HANDLE      hThread;
    NTSTATUS    Status;
    FILETIME    ftDummy;
    CLIENT_ID   cid;

    InitializeObjectAttributes(
            &obja,
            NULL,
            0,
            NULL,
            0 );

    cid.UniqueProcess = 0;      // Don't know it, 0 means any process
    cid.UniqueThread  = (HANDLE)dwThreadID32;

    Status = NtOpenThread(
                &hThread,
                THREAD_QUERY_INFORMATION,
                &obja,
                &cid );

    if ( !NT_SUCCESS(Status) ) {
#if DBG
        DbgPrint("WOW32: Could not get open thread handle\n");
#endif
        return( FALSE );
    }

    Status = NtQueryInformationThread(
        hThread,
        ThreadBasicInformation,
        (PVOID)&ThreadInfo,
        sizeof(THREAD_BASIC_INFORMATION),
        NULL
        );

    ha->dwProcessID32 = (DWORD)ThreadInfo.ClientId.UniqueProcess;
    ha->dwThreadID32  = dwThreadID32;

    GetThreadTimes( hThread,
        &ha->ftCreationTime,
        &ftDummy,
        &ftDummy,
        &ftDummy );

    Status = NtClose( hThread );
    if ( !NT_SUCCESS(Status) ) {
#if DBG
        DbgPrint("WOW32: Could not close thread handle\n");
        DbgBreakPoint();
#endif
        return( FALSE );
    }
    return( TRUE );
}
Пример #7
0
/*
 * @implemented
 */
NTSTATUS
NTAPI
DbgUiConvertStateChangeStructure(IN PDBGUI_WAIT_STATE_CHANGE WaitStateChange,
                                 OUT PVOID Win32DebugEvent)
{
    NTSTATUS Status;
    OBJECT_ATTRIBUTES ObjectAttributes;
    THREAD_BASIC_INFORMATION ThreadBasicInfo;
    LPDEBUG_EVENT DebugEvent = Win32DebugEvent;
    HANDLE ThreadHandle;

    /* Write common data */
    DebugEvent->dwProcessId = (DWORD)WaitStateChange->
                              AppClientId.UniqueProcess;
    DebugEvent->dwThreadId = (DWORD)WaitStateChange->AppClientId.UniqueThread;

    /* Check what kind of even this is */
    switch (WaitStateChange->NewState)
    {
    /* New thread */
    case DbgCreateThreadStateChange:

        /* Setup Win32 code */
        DebugEvent->dwDebugEventCode = CREATE_THREAD_DEBUG_EVENT;

        /* Copy data over */
        DebugEvent->u.CreateThread.hThread =
            WaitStateChange->StateInfo.CreateThread.HandleToThread;
        DebugEvent->u.CreateThread.lpStartAddress =
            WaitStateChange->StateInfo.CreateThread.NewThread.StartAddress;

        /* Query the TEB */
        Status = NtQueryInformationThread(WaitStateChange->StateInfo.
                                          CreateThread.HandleToThread,
                                          ThreadBasicInformation,
                                          &ThreadBasicInfo,
                                          sizeof(ThreadBasicInfo),
                                          NULL);
        if (!NT_SUCCESS(Status))
        {
            /* Failed to get PEB address */
            DebugEvent->u.CreateThread.lpThreadLocalBase = NULL;
        }
        else
        {
            /* Write PEB Address */
            DebugEvent->u.CreateThread.lpThreadLocalBase =
                ThreadBasicInfo.TebBaseAddress;
        }
        break;

    /* New process */
    case DbgCreateProcessStateChange:

        /* Write Win32 debug code */
        DebugEvent->dwDebugEventCode = CREATE_PROCESS_DEBUG_EVENT;

        /* Copy data over */
        DebugEvent->u.CreateProcessInfo.hProcess =
            WaitStateChange->StateInfo.CreateProcessInfo.HandleToProcess;
        DebugEvent->u.CreateProcessInfo.hThread =
            WaitStateChange->StateInfo.CreateProcessInfo.HandleToThread;
        DebugEvent->u.CreateProcessInfo.hFile =
            WaitStateChange->StateInfo.CreateProcessInfo.NewProcess.
            FileHandle;
        DebugEvent->u.CreateProcessInfo.lpBaseOfImage =
            WaitStateChange->StateInfo.CreateProcessInfo.NewProcess.
            BaseOfImage;
        DebugEvent->u.CreateProcessInfo.dwDebugInfoFileOffset =
            WaitStateChange->StateInfo.CreateProcessInfo.NewProcess.
            DebugInfoFileOffset;
        DebugEvent->u.CreateProcessInfo.nDebugInfoSize =
            WaitStateChange->StateInfo.CreateProcessInfo.NewProcess.
            DebugInfoSize;
        DebugEvent->u.CreateProcessInfo.lpStartAddress =
            WaitStateChange->StateInfo.CreateProcessInfo.NewProcess.
            InitialThread.StartAddress;

        /* Query TEB address */
        Status = NtQueryInformationThread(WaitStateChange->StateInfo.
                                          CreateProcessInfo.HandleToThread,
                                          ThreadBasicInformation,
                                          &ThreadBasicInfo,
                                          sizeof(ThreadBasicInfo),
                                          NULL);
        if (!NT_SUCCESS(Status))
        {
            /* Failed to get PEB address */
            DebugEvent->u.CreateProcessInfo.lpThreadLocalBase = NULL;
        }
        else
        {
            /* Write PEB Address */
            DebugEvent->u.CreateProcessInfo.lpThreadLocalBase =
                ThreadBasicInfo.TebBaseAddress;
        }

        /* Clear image name */
        DebugEvent->u.CreateProcessInfo.lpImageName = NULL;
        DebugEvent->u.CreateProcessInfo.fUnicode = TRUE;
        break;

    /* Thread exited */
    case DbgExitThreadStateChange:

        /* Write the Win32 debug code and the exit status */
        DebugEvent->dwDebugEventCode = EXIT_THREAD_DEBUG_EVENT;
        DebugEvent->u.ExitThread.dwExitCode =
            WaitStateChange->StateInfo.ExitThread.ExitStatus;
        break;

    /* Process exited */
    case DbgExitProcessStateChange:

        /* Write the Win32 debug code and the exit status */
        DebugEvent->dwDebugEventCode = EXIT_PROCESS_DEBUG_EVENT;
        DebugEvent->u.ExitProcess.dwExitCode =
            WaitStateChange->StateInfo.ExitProcess.ExitStatus;
        break;

    /* Any sort of exception */
    case DbgExceptionStateChange:
    case DbgBreakpointStateChange:
    case DbgSingleStepStateChange:

        /* Check if this was a debug print */
        if (WaitStateChange->StateInfo.Exception.ExceptionRecord.
                ExceptionCode == DBG_PRINTEXCEPTION_C)
        {
            /* Set the Win32 code */
            DebugEvent->dwDebugEventCode = OUTPUT_DEBUG_STRING_EVENT;

            /* Copy debug string information */
            DebugEvent->u.DebugString.lpDebugStringData =
                (PVOID)WaitStateChange->
                StateInfo.Exception.ExceptionRecord.
                ExceptionInformation[1];
            DebugEvent->u.DebugString.nDebugStringLength =
                WaitStateChange->StateInfo.Exception.ExceptionRecord.
                ExceptionInformation[0];
            DebugEvent->u.DebugString.fUnicode = FALSE;
        }
        else if (WaitStateChange->StateInfo.Exception.ExceptionRecord.
                 ExceptionCode == DBG_RIPEXCEPTION)
        {
            /* Set the Win32 code */
            DebugEvent->dwDebugEventCode = RIP_EVENT;

            /* Set exception information */
            DebugEvent->u.RipInfo.dwType =
                WaitStateChange->StateInfo.Exception.ExceptionRecord.
                ExceptionInformation[1];
            DebugEvent->u.RipInfo.dwError =
                WaitStateChange->StateInfo.Exception.ExceptionRecord.
                ExceptionInformation[0];
        }
        else
        {
            /* Otherwise, this is a debug event, copy info over */
            DebugEvent->dwDebugEventCode = EXCEPTION_DEBUG_EVENT;
            DebugEvent->u.Exception.ExceptionRecord =
                WaitStateChange->StateInfo.Exception.ExceptionRecord;
            DebugEvent->u.Exception.dwFirstChance =
                WaitStateChange->StateInfo.Exception.FirstChance;
        }
        break;

    /* DLL Load */
    case DbgLoadDllStateChange:

        /* Set the Win32 debug code */
        DebugEvent->dwDebugEventCode = LOAD_DLL_DEBUG_EVENT;

        /* Copy the rest of the data */
        DebugEvent->u.LoadDll.lpBaseOfDll =
            WaitStateChange->StateInfo.LoadDll.BaseOfDll;
        DebugEvent->u.LoadDll.hFile =
            WaitStateChange->StateInfo.LoadDll.FileHandle;
        DebugEvent->u.LoadDll.dwDebugInfoFileOffset =
            WaitStateChange->StateInfo.LoadDll.DebugInfoFileOffset;
        DebugEvent->u.LoadDll.nDebugInfoSize =
            WaitStateChange->StateInfo.LoadDll.DebugInfoSize;

        /* Open the thread */
        InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
        Status = NtOpenThread(&ThreadHandle,
                              THREAD_QUERY_INFORMATION,
                              &ObjectAttributes,
                              &WaitStateChange->AppClientId);
        if (NT_SUCCESS(Status))
        {
            /* Query thread information */
            Status = NtQueryInformationThread(ThreadHandle,
                                              ThreadBasicInformation,
                                              &ThreadBasicInfo,
                                              sizeof(ThreadBasicInfo),
                                              NULL);
            NtClose(ThreadHandle);
        }

        /* Check if we got thread information */
        if (NT_SUCCESS(Status))
        {
            /* Save the image name from the TIB */
            DebugEvent->u.LoadDll.lpImageName =
                ((PTEB)ThreadBasicInfo.TebBaseAddress)->
                NtTib.ArbitraryUserPointer;
        }
        else
        {
            /* Otherwise, no name */
            DebugEvent->u.LoadDll.lpImageName = NULL;
        }

        /* It's Unicode */
        DebugEvent->u.LoadDll.fUnicode = TRUE;
        break;

    /* DLL Unload */
    case DbgUnloadDllStateChange:

        /* Set Win32 code and DLL Base */
        DebugEvent->dwDebugEventCode = UNLOAD_DLL_DEBUG_EVENT;
        DebugEvent->u.UnloadDll.lpBaseOfDll =
            WaitStateChange->StateInfo.UnloadDll.BaseAddress;
        break;

    /* Anything else, fail */
    default:
        return STATUS_UNSUCCESSFUL;
    }

    /* Return success */
    return STATUS_SUCCESS;
}
Пример #8
0
NTSTATUS
SepServerInitialize(
  )

{

    NTSTATUS Status;
    OBJECT_ATTRIBUTES ThreadAttributes;
    PTEB CurrentTeb;


    DbgPrint("Se: Server Initializing ...\n");

    //
    // Initialize global variables
    //

    RequestCount = 0;

    //
    // Get a handle to our thread to so that we can access our thread
    // even when impersonating an anonymous client (which we can't do
    // using NtCurrentThread()).
    //

    CurrentTeb = NtCurrentTeb();
    InitializeObjectAttributes(&ThreadAttributes, NULL, 0, NULL, NULL);
    Status = NtOpenThread(
                 &SepServerThread,           // TargetHandle
                 THREAD_ALL_ACCESS,          // DesiredAccess
                 &ThreadAttributes,          // ObjectAttributes
                 &CurrentTeb->ClientId       // ClientId
                 );
    ASSERT( NT_SUCCESS(Status) );


    //
    // Create the server's port
    //

    InitializeObjectAttributes(
        &ObjectAttributes,
        &PortName,
        0,
        NULL,
        NULL );

    Status = NtCreatePort(
                 &EarPort,
                 &ObjectAttributes,
                 0,
                 4,
                 4 * 256
                 ); SEASSERT_SUCCESS(Status);



    //
    // Spawn a copy of ourselves...
    //

    DbgPrint("Se: Server Spawning client process ...\n");
    SepServerSpawnClientProcess();


    DbgPrint("Se: Server waiting for start of test signal ...\n");

    Status = NtWaitForSingleObject(
                 EventHandle,
                 TRUE,
                 NULL
                 ); SEASSERT_SUCCESS(Status);

    Status = NtClose( EventHandle );  SEASSERT_SUCCESS(Status);


    return STATUS_SUCCESS;
}
Пример #9
0
BOOL GetPrivilege(ULONG Priviliage)
{
	BOOL bRet = FALSE;
	NTSTATUS St;
	BOOLEAN bEnable;

	bRet = NT_SUCCESS(RtlAdjustPrivilege(Priviliage,TRUE,FALSE,&bEnable)) || NT_SUCCESS(RtlAdjustPrivilege(Priviliage,TRUE,TRUE,&bEnable));
	if (!bRet)
	{
		PSYSTEM_PROCESSES_INFORMATION Processes = (PSYSTEM_PROCESSES_INFORMATION)GetSystemInformation(SystemProcessInformation);
		if (Processes)
		{
			UNICODE_STRING ProcessName = RTL_CONSTANT_STRING(L"services.exe");

			for (PSYSTEM_PROCESSES_INFORMATION Proc=Processes; ; *(ULONG*)&Proc += Proc->NextEntryDelta)
			{
				if (RtlEqualUnicodeString(&Proc->ProcessName,&ProcessName,TRUE))
				{
					HANDLE hThread;
					OBJECT_ATTRIBUTES ObjAttr;

					InitializeObjectAttributes(&ObjAttr,NULL,0,0,0);
					St = NtOpenThread(&hThread,THREAD_DIRECT_IMPERSONATION,&ObjAttr,&Proc->Threads[0].ClientId);
					if (NT_SUCCESS(St))
					{
						SECURITY_QUALITY_OF_SERVICE SecurityQos = {0};

						SecurityQos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
						SecurityQos.ImpersonationLevel = SecurityImpersonation;
						SecurityQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;

						St = NtImpersonateThread(NtCurrentThread(),hThread,&SecurityQos);
						if (NT_SUCCESS(St))
						{
							St = RtlAdjustPrivilege(Priviliage,TRUE,TRUE,&bEnable);
							bRet = NT_SUCCESS(St);
							if (!bRet)
							{
								DbgPrint(__FUNCTION__"(): RtlAdjustPrivilege failed with status %x\n",St);
							}
						}
						else
						{
							DbgPrint(__FUNCTION__"(): NtImpersonateThread failed with status %x\n",St);
						}

						NtClose(hThread);
					}
					else
					{
						DbgPrint(__FUNCTION__"(): NtOpenThread failed with status %x\n",St);
					}

					break;
				}

				if (!Proc->NextEntryDelta) break;
			}

			free(Processes);
		}
	}

	return bRet;
}
Пример #10
0
VOID
SetThreadFields(
    PSYSTEM_THREAD_INFORMATION ThreadInfo,
    HWND hwnd
    )
{
    TIME_FIELDS UserTime;
    TIME_FIELDS KernelTime;
    TIME_FIELDS RunTime;
    LARGE_INTEGER Time;
    CHAR TimeString[15];
    CHAR StartString[32];
    HANDLE hThread;
    CONTEXT ThreadContext;
    NTSTATUS Status;
    OBJECT_ATTRIBUTES Obja;
    ULONG PcValue;

    //
    // Display the selected thread information
    //

    //
    // Compute runtimes
    //

    RtlTimeToTimeFields ( &ThreadInfo->UserTime, &UserTime);
    RtlTimeToTimeFields ( &ThreadInfo->KernelTime, &KernelTime);

    RtlTimeToTimeFields ( &ThreadInfo->UserTime, &UserTime);
    RtlTimeToTimeFields ( &ThreadInfo->KernelTime, &KernelTime);
    Time.QuadPart = RefreshTimeOfDayInfo.CurrentTime.QuadPart - ThreadInfo->CreateTime.QuadPart;
    RtlTimeToTimeFields ( &Time, &RunTime);
    wsprintf(TimeString,"%3ld:%02ld:%02ld.%03ld",
                RunTime.Hour,
                RunTime.Minute,
                RunTime.Second,
                RunTime.Milliseconds
                );
    SetDlgItemText(
        hwnd,
        PXPLODE_THREADELAPSED_TIME,
        TimeString
        );

    wsprintf(TimeString,"%3ld:%02ld:%02ld.%03ld",
                UserTime.Hour,
                UserTime.Minute,
                UserTime.Second,
                UserTime.Milliseconds
                );
    SetDlgItemText(
        hwnd,
        PXPLODE_THREADUSER_TIME,
        TimeString
        );

    wsprintf(TimeString,"%3ld:%02ld:%02ld.%03ld",
                KernelTime.Hour,
                KernelTime.Minute,
                KernelTime.Second,
                KernelTime.Milliseconds
                );
    SetDlgItemText(
        hwnd,
        PXPLODE_THREADKERNEL_TIME,
        TimeString
        );

    wsprintf(StartString,"0x%08lx",
                ThreadInfo->StartAddress
                );
    SetDlgItemText(
        hwnd,
        PXPLODE_THREAD_START,
        StartString
        );

    //
    // Do the priority Group
    //

    SetDlgItemInt(
        hwnd,
        PXPLODE_THREAD_DYNAMIC,
        ThreadInfo->Priority,
        FALSE
        );
    switch ( ThreadInfo->BasePriority - DlgProcessInfo->BasePriority ) {

        case 2:
            CheckRadioButton(
                hwnd,
                PXPLODE_THREAD_HIGHEST,
                PXPLODE_THREAD_LOWEST,
                PXPLODE_THREAD_HIGHEST
                );
            break;

        case 1:
            CheckRadioButton(
                hwnd,
                PXPLODE_THREAD_HIGHEST,
                PXPLODE_THREAD_LOWEST,
                PXPLODE_THREAD_ABOVE
                );
            break;

        case -1:
            CheckRadioButton(
                hwnd,
                PXPLODE_THREAD_HIGHEST,
                PXPLODE_THREAD_LOWEST,
                PXPLODE_THREAD_BELOW
                );
            break;
        case -2:
            CheckRadioButton(
                hwnd,
                PXPLODE_THREAD_HIGHEST,
                PXPLODE_THREAD_LOWEST,
                PXPLODE_THREAD_LOWEST
                );
            break;
        case 0:
        default:
            CheckRadioButton(
                hwnd,
                PXPLODE_THREAD_HIGHEST,
                PXPLODE_THREAD_LOWEST,
                PXPLODE_THREAD_NORMAL
                );
            break;
        }
    //
    // Complete thread information
    //

    SetDlgItemInt(
        hwnd,
        PXPLODE_THREAD_SWITCHES,
        ThreadInfo->ContextSwitches,
        FALSE
        );

    PcValue = 0;
    InitializeObjectAttributes(&Obja, NULL, 0, NULL, NULL);
    Status = NtOpenThread(
                &hThread,
                THREAD_GET_CONTEXT,
                &Obja,
                &ThreadInfo->ClientId
                );
    if ( NT_SUCCESS(Status) ) {
        ThreadContext.ContextFlags = CONTEXT_CONTROL;
        Status = NtGetContextThread(hThread,&ThreadContext);
        NtClose(hThread);
        if ( NT_SUCCESS(Status) ) {
            PcValue = (ULONG) CONTEXT_TO_PROGRAM_COUNTER(&ThreadContext);
            }
        }
    if ( PcValue ) {
        wsprintf(StartString,"0x%08lx",
                    PcValue
                    );
        SetDlgItemText(
            hwnd,
            PXPLODE_THREAD_PC,
            StartString
            );
        }
    else {
        SetDlgItemText(
            hwnd,
            PXPLODE_THREAD_PC,
            "Unknown"
            );
        }


    //
    // Disable the thread buttons if we can't get at the thread or it's token
    //

    {
        HANDLE Thread;
        HANDLE Token;
        BOOL ThreadOK = FALSE;
        BOOL GotToken = FALSE;

        Thread = OpenThread(MAXIMUM_ALLOWED, FALSE, (DWORD)ThreadInfo->ClientId.UniqueThread);
        if (Thread != NULL) {

            ThreadOK = TRUE;

            if (OpenThreadToken(Thread, MAXIMUM_ALLOWED, TRUE, &Token)) {
                GotToken = TRUE;
                CloseHandle(Token);
            }
            CloseHandle(Thread);
        }

        EnableWindow(GetDlgItem(hwnd, PXPLODE_THREAD_ACL), ThreadOK);

        EnableWindow(GetDlgItem(hwnd, PXPLODE_THREAD_TOKEN), GotToken);
        EnableWindow(GetDlgItem(hwnd, PXPLODE_THREAD_TOKEN_ACL), GotToken);
    }
}