mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
813 lines
22 KiB
813 lines
22 KiB
/*++
|
|
|
|
Copyright (c) 1989 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
process.c
|
|
|
|
Abstract:
|
|
|
|
This module contains the worker routines called to create and maintain
|
|
the OS/2 process structure.
|
|
|
|
Author:
|
|
|
|
Steve Wood (stevewo) 04-Oct-1989
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
#define INCL_OS2V20_ERRORS
|
|
#define INCL_OS2V20_TASKING
|
|
#include "os2srv.h"
|
|
#include "os2tile.h"
|
|
|
|
#define THREAD_PRIORITY_LOWEST THREAD_BASE_PRIORITY_MIN
|
|
#define THREAD_PRIORITY_BELOW_NORMAL (THREAD_PRIORITY_LOWEST+1)
|
|
#define THREAD_PRIORITY_NORMAL 0
|
|
#define THREAD_PRIORITY_HIGHEST THREAD_BASE_PRIORITY_MAX
|
|
#define THREAD_PRIORITY_ABOVE_NORMAL (THREAD_PRIORITY_HIGHEST-1)
|
|
|
|
#define THREAD_PRIORITY_TIME_CRITICAL THREAD_BASE_PRIORITY_LOWRT
|
|
#define THREAD_PRIORITY_IDLE THREAD_BASE_PRIORITY_IDLE
|
|
|
|
BOOLEAN
|
|
SetThreadPriority(
|
|
HANDLE hThread,
|
|
LONG priority
|
|
);
|
|
|
|
NTSTATUS
|
|
Os2InitializeProcessStructure( VOID )
|
|
{
|
|
NTSTATUS Status;
|
|
ULONG i;
|
|
APIRET rc;
|
|
|
|
|
|
Status = RtlInitializeCriticalSection( &Os2StructureLock );
|
|
ASSERT( NT_SUCCESS( Status ) );
|
|
|
|
// // Obsolete code below: OS/2 ss was keeping processes around as zombie so
|
|
// // that DosCWait doesn't fail when father calls it after child termination.
|
|
// // However, it turns out that OS/2 doesn't do this.
|
|
// InitializeListHead( &Os2ZombieList );
|
|
|
|
for (i=0; i<MaxWaitReason; i++) {
|
|
InitializeListHead( &Os2WaitLists[ i ] );
|
|
}
|
|
|
|
for ( i = 0 ; (i < OS2_MAX_SESSION) ; i++ ) {
|
|
SessionTable[i].Session = NULL;
|
|
}
|
|
|
|
Os2LastProcessId = (PID)0;
|
|
Os2NextHigherProcessId = MAXIMUM_PROCESS_ID;
|
|
Os2RootProcess = NULL;
|
|
Os2RootProcess = Os2AllocateProcess();
|
|
ASSERT( Os2RootProcess != NULL );
|
|
InitializeListHead( &Os2SessionList );
|
|
InitializeListHead( &Os2RootProcess->ListLink );
|
|
Os2RootProcess->ProcessHandle = (HANDLE)0xFFFFFFFF;
|
|
Os2RootProcess->ClientId.UniqueProcess = (HANDLE)0xFFFFFFFF;
|
|
Os2RootProcess->ClientId.UniqueThread = (HANDLE)0xFFFFFFFF;
|
|
Os2RootProcess->Session = Os2AllocateSession(NULL, 0, &rc);
|
|
ASSERT(Os2RootProcess->Session);
|
|
|
|
return( Status );
|
|
}
|
|
|
|
PVOID
|
|
Os2CreateTidBitmap(
|
|
)
|
|
{
|
|
PVOID TidBMHeap;
|
|
PRTL_BITMAP TidBitMapHeader = (PRTL_BITMAP)RtlAllocateHeap( Os2Heap, 0,
|
|
sizeof( RTL_BITMAP )
|
|
);
|
|
/* TidBMHeap = RtlCreateHeap( HEAP_GROWABLE,
|
|
NULL,
|
|
(_64K + 7) / 8, // 8 bits per byte
|
|
(_64K + 7) / 8, // 8 bits per byte
|
|
NULL,
|
|
0
|
|
);
|
|
*/
|
|
TidBMHeap = RtlAllocateHeap(Os2Heap, 0, (_64K + 7) / 8);
|
|
if (TidBMHeap == NULL) {
|
|
return(NULL);
|
|
}
|
|
|
|
RtlInitializeBitMap(TidBitMapHeader ,TidBMHeap, _64K);
|
|
RtlClearAllBits(TidBitMapHeader);
|
|
RtlSetBits (TidBitMapHeader,0,1); // We don't use TID 0.
|
|
#ifdef PMNT
|
|
RtlSetBits (TidBitMapHeader,
|
|
PMNTFIRSTHIDDENTHREAD,
|
|
PMNTMAXHIDDENTHREADS); //PMNT Hidden thread
|
|
#endif
|
|
return(TidBitMapHeader);
|
|
}
|
|
|
|
ULONG
|
|
Os2AllocateTid(
|
|
#ifdef PMNT
|
|
IN ULONG Flags,
|
|
#endif
|
|
POS2_PROCESS Process
|
|
)
|
|
{
|
|
#ifdef PMNT
|
|
//
|
|
// BUGBUG - PMNT Hidden thread do not exit so there is no reason to resycle
|
|
// the numbers of the hidden thread.
|
|
//
|
|
if (Flags == DCT_RUNABLE_HIDDEN){
|
|
if (Process->LastHiddenThreadId == 0) {
|
|
Process->LastHiddenThreadId=PMNTFIRSTHIDDENTHREAD-1;
|
|
}
|
|
if (Process->LastHiddenThreadId >=
|
|
(PMNTFIRSTHIDDENTHREAD+PMNTMAXHIDDENTHREADS))
|
|
return(0xFFFFFFFF);
|
|
return(++Process->LastHiddenThreadId);
|
|
}
|
|
else
|
|
return((RtlFindClearBitsAndSet( Process->TidBitMapHeader,
|
|
1,
|
|
0
|
|
)));
|
|
#else
|
|
return((RtlFindClearBitsAndSet( Process->TidBitMapHeader,
|
|
1,
|
|
0
|
|
)));
|
|
#endif
|
|
}
|
|
|
|
VOID
|
|
Os2FreeTid(
|
|
ULONG Index,
|
|
POS2_PROCESS Process
|
|
)
|
|
{
|
|
if (Index > (_64K)) {
|
|
return;
|
|
}
|
|
RtlClearBits( Process->TidBitMapHeader,
|
|
Index,
|
|
1
|
|
);
|
|
}
|
|
|
|
POS2_PROCESS
|
|
Os2AllocateProcess( VOID )
|
|
{
|
|
PLIST_ENTRY ListHead, ListNext;
|
|
POS2_PROCESS Process = NULL;
|
|
POS2_PROCESS ScanProcess;
|
|
BOOLEAN SearchMode;
|
|
BOOLEAN NextHigherWasSet;
|
|
|
|
//
|
|
// Allocate an OS/2 Process Object
|
|
//
|
|
|
|
Process = (POS2_PROCESS)RtlAllocateHeap( Os2Heap, 0,
|
|
sizeof( OS2_PROCESS )
|
|
);
|
|
if (Process == NULL) {
|
|
return( NULL );
|
|
}
|
|
|
|
//
|
|
// Initialize the fields of the process object
|
|
//
|
|
|
|
RtlZeroMemory( Process, sizeof( OS2_PROCESS ) );
|
|
|
|
InitializeListHead( &Process->ChildrenList );
|
|
InitializeListHead( &Process->ThreadList );
|
|
InitializeListHead( &Process->SharedMemoryList );
|
|
|
|
//
|
|
// if there are 64K-1 processes in the system and there are two process
|
|
// creates occuring at the same time, they would both end up with the
|
|
// same pid, if the first to find it was not inserted in the process tree
|
|
// before the second found the pid. we don't worry about this case.
|
|
//
|
|
|
|
if (Os2RootProcess == NULL) {
|
|
Process->ProcessId = (PID)0; // root process has ProcessId 0
|
|
return( Process );
|
|
}
|
|
|
|
Process->TidBitMapHeader = Os2CreateTidBitmap();
|
|
|
|
if (Process->TidBitMapHeader == NULL) {
|
|
RtlFreeHeap(Os2Heap, 0, (PVOID)Process);
|
|
return( NULL );
|
|
}
|
|
SearchMode = FALSE;
|
|
while (TRUE) {
|
|
if (Os2LastProcessId == MAXIMUM_PROCESS_ID) {
|
|
Os2LastProcessId = MINIMUM_PROCESS_ID;
|
|
SearchMode = TRUE;
|
|
}
|
|
else if (!SearchMode && (Os2LastProcessId == Os2NextHigherProcessId)) {
|
|
Os2LastProcessId = (PID)((ULONG)Os2LastProcessId + 1);
|
|
SearchMode = TRUE;
|
|
}
|
|
else {
|
|
Os2LastProcessId = (PID)((ULONG)Os2LastProcessId + 1);
|
|
if (!SearchMode) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
// verify that the ProcessID is not allocated to another process
|
|
|
|
ListHead = &Os2RootProcess->ListLink;
|
|
ListNext = ListHead->Flink;
|
|
while (ListNext != ListHead) {
|
|
ScanProcess = CONTAINING_RECORD( ListNext, OS2_PROCESS, ListLink );
|
|
if ((ScanProcess->ProcessId == Os2LastProcessId) ||
|
|
(ScanProcess->CommandSubTreeId == Os2LastProcessId)
|
|
) {
|
|
break;
|
|
}
|
|
ListNext = ListNext->Flink;
|
|
}
|
|
if (ListNext != ListHead) { // This ProcessId is already allocated
|
|
continue; // to another process.
|
|
}
|
|
|
|
// find the next maximum available free number
|
|
|
|
NextHigherWasSet = FALSE;
|
|
Os2NextHigherProcessId = MAXIMUM_PROCESS_ID;
|
|
ListHead = &Os2RootProcess->ListLink;
|
|
ListNext = ListHead->Flink;
|
|
while (ListNext != ListHead) {
|
|
ScanProcess = CONTAINING_RECORD( ListNext, OS2_PROCESS, ListLink );
|
|
if ((ScanProcess->ProcessId > Os2LastProcessId) &&
|
|
(Os2NextHigherProcessId >= ScanProcess->ProcessId)) {
|
|
Os2NextHigherProcessId = ScanProcess->ProcessId;
|
|
NextHigherWasSet = TRUE;
|
|
}
|
|
if ((ScanProcess->CommandSubTreeId > Os2LastProcessId) &&
|
|
(Os2NextHigherProcessId >= ScanProcess->CommandSubTreeId)) {
|
|
Os2NextHigherProcessId = ScanProcess->CommandSubTreeId;
|
|
NextHigherWasSet = TRUE;
|
|
}
|
|
ListNext = ListNext->Flink;
|
|
}
|
|
if (NextHigherWasSet) {
|
|
Os2NextHigherProcessId = (PID)((ULONG)Os2NextHigherProcessId - 1);
|
|
}
|
|
break;
|
|
}
|
|
|
|
Process->ProcessId = Os2LastProcessId;
|
|
Process->CommandSubTreeId = Os2LastProcessId;
|
|
Process->ErrorAction = OS2_ENABLE_ACCESS_VIO_POPUP | OS2_ENABLE_HARD_ERROR_POPUP;
|
|
Process->FirstPtrace = TRUE;
|
|
Process->LinkMte = RtlAllocateHeap(Os2Heap, 0, sizeof(LinkMTE));
|
|
if (Process->LinkMte == NULL) {
|
|
RtlFreeHeap(Os2Heap, 0, ((PRTL_BITMAP)(Process->TidBitMapHeader))->Buffer);
|
|
RtlFreeHeap(Os2Heap, 0, Process->TidBitMapHeader);
|
|
RtlFreeHeap(Os2Heap, 0, (PVOID)(Process));
|
|
return(NULL);
|
|
}
|
|
((LinkMTE *)Process->LinkMte)->MTE = 0;
|
|
((LinkMTE *)Process->LinkMte)->NextMTE = NULL;
|
|
((LinkMTE *)Process->LinkMte)->NeedToTransfer = FALSE;
|
|
|
|
return( Process );
|
|
}
|
|
|
|
|
|
VOID
|
|
Os2DeallocateProcess(
|
|
IN POS2_PROCESS Process
|
|
)
|
|
{
|
|
LinkMTE *pLinkMte, *tmpMte;
|
|
|
|
if (Process->TidBitMapHeader) {
|
|
RtlFreeHeap(Os2Heap, 0, ((PRTL_BITMAP)(Process->TidBitMapHeader))->Buffer);
|
|
RtlFreeHeap(Os2Heap, 0, Process->TidBitMapHeader);
|
|
}
|
|
|
|
//
|
|
// Free LinkMTE list
|
|
//
|
|
pLinkMte = ((LinkMTE *)Process->LinkMte);
|
|
while ((tmpMte = pLinkMte) != NULL) {
|
|
pLinkMte = pLinkMte->NextMTE;
|
|
RtlFreeHeap(Os2Heap, 0, tmpMte);
|
|
}
|
|
|
|
RtlFreeHeap( Os2Heap, 0, Process );
|
|
}
|
|
|
|
VOID
|
|
Os2InsertProcess(
|
|
IN POS2_PROCESS ParentProcess,
|
|
IN POS2_PROCESS Process
|
|
)
|
|
{
|
|
|
|
if (!ARGUMENT_PRESENT( ParentProcess )) {
|
|
ParentProcess = Os2RootProcess;
|
|
}
|
|
ASSERT( Process->Parent == NULL );
|
|
ASSERT( IsListEmpty( &Process->ChildrenList ) );
|
|
|
|
Process->Parent = ParentProcess;
|
|
InsertTailList( &ParentProcess->ChildrenList, &Process->SiblingLink );
|
|
InsertTailList( &Os2RootProcess->ListLink, &Process->ListLink );
|
|
}
|
|
|
|
|
|
VOID
|
|
Os2RemoveProcess(
|
|
IN POS2_PROCESS Process
|
|
)
|
|
{
|
|
PLIST_ENTRY ListHead, ListNext, NextNext;
|
|
|
|
RemoveEntryList( &Process->SiblingLink );
|
|
RemoveEntryList( &Process->ListLink );
|
|
|
|
if ( !IsListEmpty( &Process->ChildrenList ) ) {
|
|
//
|
|
// Process is about to die and some childrent are still
|
|
// alive - Link all children into parent process
|
|
//
|
|
ListHead = &Process->ChildrenList;
|
|
ListNext = ListHead->Flink;
|
|
while (ListNext != ListHead) {
|
|
NextNext = ListNext->Flink;
|
|
InsertTailList( &Process->Parent->ChildrenList, ListNext );
|
|
(CONTAINING_RECORD( ListNext,OS2_PROCESS,SiblingLink))->Parent = Process->Parent;
|
|
ListNext = NextNext;
|
|
}
|
|
}
|
|
Os2FreeAllSharedMemoryForProcess( Process );
|
|
|
|
Os2DeRegisterCtrlHandler(Process);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
Os2SetProcessContext(
|
|
IN POS2_PROCESS Process,
|
|
IN POS2_THREAD Thread,
|
|
IN BOOLEAN StartedBySm,
|
|
IN ULONG HandleTableLength,
|
|
IN ULONG CurrentDrive,
|
|
IN ULONG CodePage
|
|
)
|
|
{
|
|
UNREFERENCED_PARAMETER(Thread);
|
|
Process->InitialPebOs2Data.Length = sizeof( Process->InitialPebOs2Data );
|
|
Process->InitialPebOs2Data.ClientStartAddress = NULL;
|
|
Process->InitialPebOs2Data.StartedBySm = StartedBySm;
|
|
Process->InitialPebOs2Data.SizeOfInheritedHandleTable = HandleTableLength;
|
|
Process->InitialPebOs2Data.InitialDefaultDrive = CurrentDrive;
|
|
Process->InitialPebOs2Data.CodePage = CodePage;
|
|
|
|
return( STATUS_SUCCESS );
|
|
}
|
|
|
|
|
|
POS2_THREAD
|
|
Os2AllocateThread(
|
|
#ifdef PMNT
|
|
IN ULONG Flags,
|
|
#endif
|
|
IN POS2_PROCESS Process
|
|
)
|
|
{
|
|
POS2_THREAD Thread;
|
|
|
|
//
|
|
// Allocate an OS/2 Thread Object
|
|
//
|
|
|
|
Thread = (POS2_THREAD)RtlAllocateHeap( Os2Heap, 0,
|
|
sizeof( OS2_THREAD )
|
|
);
|
|
if (Thread == NULL) {
|
|
return( NULL );
|
|
}
|
|
|
|
//
|
|
// Initialize the fields of the thread object
|
|
//
|
|
|
|
RtlZeroMemory( Thread, sizeof( OS2_THREAD ) );
|
|
|
|
Thread->Process = Process;
|
|
|
|
Thread->ThreadId = (TID)Os2AllocateTid(
|
|
#ifdef PMNT
|
|
Flags,
|
|
#endif
|
|
Thread->Process);
|
|
if (Thread->ThreadId == (TID)(0xFFFFFFFF))
|
|
return (NULL);
|
|
return( Thread );
|
|
}
|
|
|
|
|
|
VOID
|
|
Os2DeallocateThread(
|
|
IN POS2_THREAD Thread
|
|
)
|
|
{
|
|
if (Thread->WaitBlock != NULL) {
|
|
Os2DestroyWait( Thread->WaitBlock );
|
|
Thread->WaitBlock = NULL;
|
|
}
|
|
|
|
Os2FreeTid(
|
|
(ULONG)(Thread->ThreadId),
|
|
Thread->Process );
|
|
|
|
RtlFreeHeap( Os2Heap, 0, Thread );
|
|
}
|
|
|
|
VOID
|
|
Os2InsertThread(
|
|
IN POS2_PROCESS Process,
|
|
IN POS2_THREAD Thread
|
|
)
|
|
{
|
|
|
|
InsertTailList( &Process->ThreadList, &Thread->Link );
|
|
}
|
|
|
|
VOID
|
|
Os2RemoveThread(
|
|
IN POS2_PROCESS Process,
|
|
IN POS2_THREAD Thread
|
|
)
|
|
{
|
|
RemoveEntryList( &Thread->Link );
|
|
}
|
|
|
|
|
|
VOID
|
|
Os2SetThreadPriority(
|
|
IN POS2_THREAD Thread,
|
|
IN ULONG NewClass,
|
|
IN ULONG Delta
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
CHAR Level;
|
|
ULONG Os2Priority;
|
|
|
|
if (Thread->Dying == TRUE) {
|
|
return;
|
|
}
|
|
if (NewClass != PRTYC_NOCHANGE) {
|
|
Thread->Os2Class = (UCHAR)NewClass;
|
|
Level = (CHAR)Delta;
|
|
|
|
}
|
|
else {
|
|
Level = Thread->Os2Level + (CHAR)Delta;
|
|
if (Level < PRTYD_MINIMUM) {
|
|
Level = PRTYD_MINIMUM;
|
|
}
|
|
else if (Level > PRTYD_MAXIMUM) {
|
|
Level = PRTYD_MAXIMUM;
|
|
}
|
|
}
|
|
|
|
Thread->Os2Level = Level;
|
|
Thread->Priority = (KPRIORITY)(((Level + PRTYD_MAXIMUM) >> 3) |
|
|
((Thread->Os2Class-1) << 3));
|
|
|
|
if (Thread->Priority == 0) {
|
|
Thread->Priority = 1;
|
|
}
|
|
|
|
if (Thread->Os2Class == PRTYC_FOREGROUNDSERVER){
|
|
Thread->Priority = 15;
|
|
}
|
|
|
|
Os2Priority = (Thread->Os2Class << 8) | (UCHAR)Level;
|
|
Status = NtWriteVirtualMemory( Thread->Process->ProcessHandle,
|
|
&Thread->ClientOs2Tib->Priority,
|
|
&Os2Priority,
|
|
sizeof( Thread->ClientOs2Tib->Priority ),
|
|
NULL
|
|
);
|
|
ASSERT( NT_SUCCESS( Status ) );
|
|
|
|
//
|
|
// Write the priority into the 32-bit local info seg
|
|
// If the thread is in 16 bit, the next time it does
|
|
// an API, its local info seg will be updated
|
|
//
|
|
|
|
Status = NtWriteVirtualMemory( Thread->Process->ProcessHandle,
|
|
&Thread->ClientOs2Tib->LInfoSeg.prtyCurrent,
|
|
&Os2Priority,
|
|
sizeof( Thread->ClientOs2Tib->LInfoSeg.prtyCurrent ),
|
|
NULL
|
|
);
|
|
ASSERT( NT_SUCCESS( Status ) );
|
|
|
|
//
|
|
// YS - 6-21-93 - since os2 processes are win32 processes, csrss plays
|
|
// with their priorities. We can't set the process class to anything but
|
|
// normal, or we stop the system. Therefor - we have to set the priorities
|
|
// by win32 apis, as opposed to NT apis used so far.
|
|
// The way we map is clear from the code below. We are leaving the
|
|
// THREAD_PRIORITY_TIME_CRITICIAL to our service threads (os2ses\os2.c).
|
|
//
|
|
|
|
|
|
switch (Thread->Os2Class) {
|
|
|
|
case PRTYC_IDLETIME:
|
|
SetThreadPriority(Thread->ThreadHandle,
|
|
THREAD_PRIORITY_IDLE);
|
|
break;
|
|
|
|
case PRTYC_REGULAR:
|
|
//
|
|
// Set base level by priority, mapping from range (-31 , +31).
|
|
//
|
|
if (Level < -15) {
|
|
SetThreadPriority(Thread->ThreadHandle,
|
|
THREAD_PRIORITY_LOWEST);
|
|
}
|
|
else if (Level < 0) {
|
|
SetThreadPriority(Thread->ThreadHandle,
|
|
THREAD_PRIORITY_BELOW_NORMAL);
|
|
}
|
|
else if (Level < 15) {
|
|
SetThreadPriority(Thread->ThreadHandle,
|
|
THREAD_PRIORITY_NORMAL);
|
|
}
|
|
else {
|
|
SetThreadPriority(Thread->ThreadHandle,
|
|
THREAD_PRIORITY_ABOVE_NORMAL);
|
|
}
|
|
break;
|
|
|
|
case PRTYC_FOREGROUNDSERVER:
|
|
SetThreadPriority(Thread->ThreadHandle,
|
|
THREAD_PRIORITY_HIGHEST);
|
|
break;
|
|
|
|
case PRTYC_TIMECRITICAL:
|
|
SetThreadPriority(Thread->ThreadHandle,
|
|
THREAD_PRIORITY_HIGHEST);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
#if DBG
|
|
IF_OS2_DEBUG( TASKING ) {
|
|
KdPrint(("Os2SetThreadPriority - Set PID:TID %x:%x to priority %d. Class=%x, Level=%x\n",
|
|
Thread->Process->ProcessId, Thread->ThreadId, Thread->Priority, Thread->Os2Class, Level));
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
VOID
|
|
Os2SetProcessPriority(
|
|
IN POS2_PROCESS Process,
|
|
IN ULONG NewClass,
|
|
IN ULONG Delta
|
|
)
|
|
{
|
|
PLIST_ENTRY ListHead, ListNext;
|
|
|
|
ListHead = &Process->ThreadList;
|
|
ListNext = ListHead->Flink;
|
|
while (ListNext != ListHead) {
|
|
Os2SetThreadPriority( CONTAINING_RECORD( ListNext, OS2_THREAD, Link ),
|
|
NewClass,
|
|
Delta
|
|
);
|
|
ListNext = ListNext->Flink;
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
Os2SetProcessTreePriority(
|
|
IN POS2_PROCESS RootProcess,
|
|
IN ULONG NewClass,
|
|
IN ULONG Delta
|
|
)
|
|
{
|
|
PLIST_ENTRY ListHead, ListNext;
|
|
|
|
Os2SetProcessPriority( RootProcess, NewClass, Delta );
|
|
|
|
ListHead = &RootProcess->ChildrenList;
|
|
ListNext = ListHead->Flink;
|
|
while (ListNext != ListHead) {
|
|
Os2SetProcessTreePriority( CONTAINING_RECORD( ListNext,
|
|
OS2_PROCESS,
|
|
SiblingLink
|
|
),
|
|
NewClass,
|
|
Delta
|
|
);
|
|
ListNext = ListNext->Flink;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
POS2_PROCESS
|
|
Os2LocateProcessByProcessId(
|
|
IN POS2_API_MSG m OPTIONAL,
|
|
IN POS2_PROCESS CurrentProcess,
|
|
IN PID ProcessId,
|
|
IN BOOLEAN MustBeChild
|
|
)
|
|
{
|
|
PLIST_ENTRY ListHead, ListNext;
|
|
POS2_PROCESS Process;
|
|
POS2_PROCESS Parent;
|
|
POS2_THREAD Thread;
|
|
|
|
UNREFERENCED_PARAMETER(Thread);
|
|
|
|
if (ProcessId == 0) {
|
|
return( CurrentProcess );
|
|
}
|
|
|
|
ListHead = &Os2RootProcess->ListLink;
|
|
ListNext = ListHead->Flink;
|
|
while (ListNext != ListHead) {
|
|
Process = CONTAINING_RECORD( ListNext, OS2_PROCESS, ListLink );
|
|
if (Process->ProcessId == ProcessId) {
|
|
Parent = Process;
|
|
if (MustBeChild) {
|
|
while (Parent) {
|
|
if (Parent == CurrentProcess) {
|
|
break;
|
|
}
|
|
else {
|
|
Parent = Parent->Parent;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
else {
|
|
return( Process );
|
|
}
|
|
}
|
|
|
|
ListNext = ListNext->Flink;
|
|
}
|
|
|
|
if (ListNext != ListHead) {
|
|
if (Parent == CurrentProcess) {
|
|
return( Process );
|
|
}
|
|
else {
|
|
if (m != NULL) {
|
|
m->ReturnedErrorValue = ERROR_NOT_DESCENDANT;
|
|
}
|
|
|
|
return( NULL );
|
|
}
|
|
}
|
|
else {
|
|
if (m != NULL) {
|
|
m->ReturnedErrorValue = ERROR_INVALID_PROCID;
|
|
}
|
|
|
|
return( NULL );
|
|
}
|
|
}
|
|
|
|
|
|
POS2_THREAD
|
|
Os2LocateThreadByThreadId(
|
|
IN POS2_API_MSG m OPTIONAL,
|
|
IN POS2_THREAD CurrentThread,
|
|
IN TID ThreadId
|
|
)
|
|
{
|
|
PLIST_ENTRY ListHead, ListNext;
|
|
POS2_PROCESS Process;
|
|
POS2_THREAD Thread;
|
|
|
|
if (ThreadId == 0) {
|
|
return( CurrentThread );
|
|
}
|
|
|
|
Process = CurrentThread->Process;
|
|
|
|
ListHead = &Process->ThreadList;
|
|
ListNext = ListHead->Flink;
|
|
while (ListNext != ListHead) {
|
|
Thread = CONTAINING_RECORD( ListNext, OS2_THREAD, Link );
|
|
if (Thread->ThreadId == ThreadId) {
|
|
break;
|
|
}
|
|
|
|
ListNext = ListNext->Flink;
|
|
}
|
|
|
|
|
|
if (ListNext != ListHead) {
|
|
if (Thread->Dying == FALSE) {
|
|
return( Thread );
|
|
}
|
|
}
|
|
if (m != NULL) {
|
|
//
|
|
// No, this is not suppose to be ERROR_INVALID_TID. Look in
|
|
// the Cruiser sources, src\dos\task\tkforce.c and you will see.
|
|
//
|
|
|
|
m->ReturnedErrorValue = ERROR_INVALID_THREADID;
|
|
}
|
|
|
|
return( NULL );
|
|
}
|
|
|
|
POS2_PROCESS
|
|
Os2LocateProcessByClientId(
|
|
IN PCLIENT_ID ClientId
|
|
)
|
|
{
|
|
PLIST_ENTRY ListHead, ListNext;
|
|
POS2_PROCESS Process = NULL;
|
|
|
|
ListHead = &Os2RootProcess->ListLink;
|
|
ListNext = ListHead->Flink;
|
|
while (ListNext != ListHead) {
|
|
Process = CONTAINING_RECORD( ListNext, OS2_PROCESS, ListLink );
|
|
if (Process->ClientId.UniqueProcess == ClientId->UniqueProcess) {
|
|
break;
|
|
}
|
|
|
|
Process = NULL;
|
|
ListNext = ListNext->Flink;
|
|
}
|
|
|
|
return (Process);
|
|
}
|
|
|
|
POS2_THREAD
|
|
Os2LocateThreadByClientId(
|
|
POS2_PROCESS Process,
|
|
IN PCLIENT_ID ClientId
|
|
)
|
|
{
|
|
PLIST_ENTRY ListHead, ListNext;
|
|
POS2_THREAD Thread;
|
|
|
|
if (Process == NULL) {
|
|
|
|
ListHead = &Os2RootProcess->ListLink;
|
|
ListNext = ListHead->Flink;
|
|
while (ListNext != ListHead) {
|
|
Process = CONTAINING_RECORD( ListNext, OS2_PROCESS, ListLink );
|
|
if (Process->ClientId.UniqueProcess == ClientId->UniqueProcess) {
|
|
break;
|
|
}
|
|
|
|
Process = NULL;
|
|
ListNext = ListNext->Flink;
|
|
}
|
|
}
|
|
|
|
if (Process != NULL) {
|
|
ListHead = &Process->ThreadList;
|
|
ListNext = ListHead->Flink;
|
|
while (ListNext != ListHead) {
|
|
Thread = CONTAINING_RECORD( ListNext, OS2_THREAD, Link );
|
|
if (Thread->ClientId.UniqueThread == ClientId->UniqueThread) {
|
|
break;
|
|
}
|
|
|
|
ListNext = ListNext->Flink;
|
|
}
|
|
if (ListNext != ListHead) {
|
|
return( Thread );
|
|
}
|
|
}
|
|
|
|
return( NULL );
|
|
}
|