[CSRSRV]: Port the CsrWait* and CsrSession* APIs from CSRSRV2. Not yet used, so no real functional change. Fixup a few structures where needed. Initalize session support during CSRSRV initialization. We have a pretty good hybrid now, some few more changes here and there and we can perhaps start having the beginnings our own "basesrv.dll",

svn path=/trunk/; revision=55626
This commit is contained in:
Alex Ionescu 2012-02-16 06:57:27 +00:00
parent 0f20fb2587
commit 8bd17c0446
9 changed files with 794 additions and 2 deletions

View file

@ -11,6 +11,8 @@ list(APPEND SOURCE
procsup.c
thredsup.c
init.c
wait.c
session.c
${CMAKE_CURRENT_BINARY_DIR}/csrsrv.def)
add_library(csrsrv SHARED ${SOURCE})

View file

@ -986,6 +986,70 @@ ClientConnectionThread(HANDLE ServerPort)
RtlExitUserThread(STATUS_SUCCESS);
}
/*++
* @name CsrReleaseCapturedArguments
* @implemented NT5.1
*
* The CsrReleaseCapturedArguments routine releases a Capture Buffer
* that was previously captured with CsrCaptureArguments.
*
* @param ApiMessage
* Pointer to the CSR API Message containing the Capture Buffer
* that needs to be released.
*
* @return None.
*
* @remarks None.
*
*--*/
VOID
NTAPI
CsrReleaseCapturedArguments(IN PCSR_API_MESSAGE ApiMessage)
{
PCSR_CAPTURE_BUFFER RemoteCaptureBuffer, LocalCaptureBuffer;
SIZE_T BufferDistance;
ULONG PointerCount;
ULONG_PTR **PointerOffsets, *CurrentPointer;
/* Get the capture buffers */
RemoteCaptureBuffer = ApiMessage->CsrCaptureData;
LocalCaptureBuffer = RemoteCaptureBuffer->PreviousCaptureBuffer;
/* Free the previous one */
RemoteCaptureBuffer->PreviousCaptureBuffer = NULL;
/* Find out the difference between the two buffers */
BufferDistance = (ULONG_PTR)LocalCaptureBuffer - (ULONG_PTR)RemoteCaptureBuffer;
/* Save the pointer count and offset pointer */
PointerCount = RemoteCaptureBuffer->PointerCount;
PointerOffsets = (ULONG_PTR**)(RemoteCaptureBuffer + 1);
/* Start the loop */
while (PointerCount)
{
/* Get the current pointer */
CurrentPointer = *PointerOffsets++;
if (CurrentPointer)
{
/* Add it to the CSR Message structure */
CurrentPointer += (ULONG_PTR)ApiMessage;
/* Modify the pointer to take into account its new position */
*CurrentPointer += BufferDistance;
}
/* Move to the next Pointer */
PointerCount--;
}
/* Copy the data back */
RtlMoveMemory(LocalCaptureBuffer, RemoteCaptureBuffer, RemoteCaptureBuffer->Size);
/* Free our allocated buffer */
RtlFreeHeap(CsrHeap, 0, RemoteCaptureBuffer);
}
/* SESSION MANAGER FUNCTIONS**************************************************/
/*++

View file

@ -18,5 +18,7 @@
<file>procsup.c</file>
<file>thredsup.c</file>
<file>init.c</file>
<file>wait.c</file>
<file>session.c</file
<pch>srv.h</pch>
</module>

View file

@ -1116,6 +1116,15 @@ CsrServerInitialization(IN ULONG ArgumentCount,
__FUNCTION__, Status);
return Status;
}
/* Set up Session Support */
Status = CsrInitializeNtSessionList();
if (!NT_SUCCESS(Status))
{
DPRINT1("CSRSRV:%s: CsrInitializeSessions failed (Status=%08lx)\n",
__FUNCTION__, Status);
return Status;
}
/* Set up Process Support */
Status = CsrInitializeProcessStructure();

View file

@ -16,7 +16,7 @@
/* GLOBALS ********************************************************************/
RTL_CRITICAL_SECTION ProcessDataLock, CsrWaitListsLock;
RTL_CRITICAL_SECTION ProcessDataLock;
PCSR_PROCESS CsrRootProcess;
SECURITY_QUALITY_OF_SERVICE CsrSecurityQos =
{

View file

@ -0,0 +1,175 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS CSR Sub System
* FILE: subsys/csr/csrsrv/session.c
* PURPOSE: CSR Server DLL Session Implementation
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
*/
/* INCLUDES ******************************************************************/
#include "srv.h"
#define NDEBUG
#include <debug.h>
/* DATA **********************************************************************/
RTL_CRITICAL_SECTION CsrNtSessionLock;
LIST_ENTRY CsrNtSessionList;
/* PRIVATE FUNCTIONS *********************************************************/
/*++
* @name CsrInitializeNtSessionList
*
* The CsrInitializeNtSessionList routine sets up support for CSR Sessions.
*
* @param None
*
* @return None
*
* @remarks None.
*
*--*/
NTSTATUS
NTAPI
CsrInitializeNtSessionList(VOID)
{
DPRINT("CSRSRV: %s called\n", __FUNCTION__);
/* Initialize the Session List */
InitializeListHead(&CsrNtSessionList);
/* Initialize the Session Lock */
return RtlInitializeCriticalSection(&CsrNtSessionLock);
}
/*++
* @name CsrAllocateNtSession
*
* The CsrAllocateNtSession routine allocates a new CSR NT Session.
*
* @param SessionId
* Session ID of the CSR NT Session to allocate.
*
* @return Pointer to the newly allocated CSR NT Session.
*
* @remarks None.
*
*--*/
PCSR_NT_SESSION
NTAPI
CsrAllocateNtSession(IN ULONG SessionId)
{
PCSR_NT_SESSION NtSession;
/* Allocate an NT Session Object */
NtSession = RtlAllocateHeap(CsrHeap, 0, sizeof(CSR_NT_SESSION));
if (NtSession)
{
/* Setup the Session Object */
NtSession->SessionId = SessionId;
NtSession->ReferenceCount = 1;
/* Insert it into the Session List */
CsrAcquireNtSessionLock();
InsertHeadList(&CsrNtSessionList, &NtSession->SessionLink);
CsrReleaseNtSessionLock();
}
else
{
ASSERT(NtSession != NULL);
}
/* Return the Session (or NULL) */
return NtSession;
}
/*++
* @name CsrReferenceNtSession
*
* The CsrReferenceNtSession increases the reference count of a CSR NT Session.
*
* @param Session
* Pointer to the CSR NT Session to reference.
*
* @return None.
*
* @remarks None.
*
*--*/
VOID
NTAPI
CsrReferenceNtSession(IN PCSR_NT_SESSION Session)
{
/* Acquire the lock */
CsrAcquireNtSessionLock();
/* Sanity checks */
ASSERT(!IsListEmpty(&Session->SessionLink));
ASSERT(Session->SessionId != 0);
ASSERT(Session->ReferenceCount != 0);
/* Increase the reference count */
Session->ReferenceCount++;
/* Release the lock */
CsrReleaseNtSessionLock();
}
/*++
* @name CsrDereferenceNtSession
*
* The CsrDereferenceNtSession decreases the reference count of a
* CSR NT Session.
*
* @param Session
* Pointer to the CSR NT Session to reference.
*
* @param ExitStatus
* If this is the last reference to the session, this argument
* specifies the exit status.
*
* @return None.
*
* @remarks CsrDereferenceNtSession will complete the session if
* the last reference to it has been closed.
*
*--*/
VOID
NTAPI
CsrDereferenceNtSession(IN PCSR_NT_SESSION Session,
IN NTSTATUS ExitStatus)
{
/* Acquire the lock */
CsrAcquireNtSessionLock();
/* Sanity checks */
ASSERT(!IsListEmpty(&Session->SessionLink));
ASSERT(Session->SessionId != 0);
ASSERT(Session->ReferenceCount != 0);
/* Dereference the Session Object */
if (!(--Session->ReferenceCount))
{
/* Remove it from the list */
RemoveEntryList(&Session->SessionLink);
/* Release the lock */
CsrReleaseNtSessionLock();
/* Tell SM that we're done here */
SmSessionComplete(CsrSmApiPort, Session->SessionId, ExitStatus);
/* Free the Session Object */
RtlFreeHeap(CsrHeap, 0, Session);
}
else
{
/* Release the lock, the Session is still active */
CsrReleaseNtSessionLock();
}
}
/* EOF */

View file

@ -407,4 +407,40 @@ CsrAddStaticServerThread(IN HANDLE hThread,
return CsrThread;
}
/*++
* @name CsrDereferenceThread
* @implemented NT4
*
* The CsrDereferenceThread routine removes a reference from a CSR Thread.
*
* @param CsrThread
* Pointer to the CSR Thread to dereference.
*
* @return None.
*
* @remarks If the reference count has reached zero (ie: the CSR Thread has
* no more active references), it will be deleted.
*
*--*/
VOID
NTAPI
CsrDereferenceThread(IN PCSR_THREAD CsrThread)
{
/* Acquire process lock */
CsrAcquireProcessLock();
/* Decrease reference count */
ASSERT(CsrThread->ReferenceCount > 0);
if (!(--CsrThread->ReferenceCount))
{
/* Call the generic cleanup code */
CsrThreadRefcountZero(CsrThread);
}
else
{
/* Just release the lock */
CsrReleaseProcessLock();
}
}
/* EOF */

View file

@ -0,0 +1,449 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS CSR Sub System
* FILE: subsys/csr/csrsrv/wait.c
* PURPOSE: CSR Server DLL Wait Implementation
* PROGRAMMERS: Emanuele Aliberti
* Alex Ionescu (alex@relsoft.net)
*/
/* INCLUDES ******************************************************************/
#include "srv.h"
#define NDEBUG
#include <debug.h>
/* DATA **********************************************************************/
RTL_CRITICAL_SECTION CsrWaitListsLock;
/* PRIVATE FUNCTIONS *********************************************************/
/*++
* @name CsrInitializeWait
*
* The CsrInitializeWait routine initializes a CSR Wait Object.
*
* @param WaitFunction
* Pointer to the function that will handle this wait.
*
* @param CsrWaitThread
* Pointer to the CSR Thread that will perform the wait.
*
* @param WaitApiMessage
* Pointer to the CSR API Message associated to this wait.
*
* @param WaitContext
* Pointer to a user-defined parameter associated to this wait.
*
* @param NewWaitBlock
* Pointed to the initialized CSR Wait Block for this wait.
*
* @return TRUE in case of success, FALSE othwerwise.
*
* @remarks None.
*
*--*/
BOOLEAN
NTAPI
CsrInitializeWait(IN CSR_WAIT_FUNCTION WaitFunction,
IN PCSR_THREAD CsrWaitThread,
IN OUT PCSR_API_MESSAGE WaitApiMessage,
IN PVOID WaitContext,
OUT PCSR_WAIT_BLOCK *NewWaitBlock)
{
ULONG Size;
PCSR_WAIT_BLOCK WaitBlock;
/* Calculate the size of the wait block */
Size = sizeof(CSR_WAIT_BLOCK) -
sizeof(WaitBlock->WaitApiMessage) +
WaitApiMessage->Header.u1.s1.TotalLength;
/* Allocate the Wait Block */
WaitBlock = RtlAllocateHeap(CsrHeap, 0, Size);
if (!WaitBlock)
{
/* Fail */
WaitApiMessage->Status = STATUS_NO_MEMORY;
return FALSE;
}
/* Initialize it */
WaitBlock->Size = Size;
WaitBlock->WaitThread = CsrWaitThread;
WaitBlock->WaitContext = WaitContext;
WaitBlock->WaitFunction = WaitFunction;
WaitBlock->UserWaitList.Flink = NULL;
WaitBlock->UserWaitList.Blink = NULL;
WaitBlock->WaitList = WaitBlock->UserWaitList;
/* Copy the message */
RtlMoveMemory(&WaitBlock->WaitApiMessage,
WaitApiMessage,
WaitApiMessage->Header.u1.s1.TotalLength);
/* Return the block */
*NewWaitBlock = WaitBlock;
return TRUE;
}
/*++
* @name CsrNotifyWaitBlock
*
* The CsrNotifyWaitBlock routine calls the wait function for a registered
* CSR Wait Block, and replies to the attached CSR API Message, if any.
*
* @param WaitBlock
* Pointer to the CSR Wait Block
*
* @param WaitList
* Pointer to the wait list for this wait.
*
* @param WaitArgument[1-2]
* User-defined values to pass to the wait function.
*
* @param WaitFlags
* Wait flags for this wait.
*
* @param DereferenceThread
* Specifies whether the CSR Thread should be dereferenced at the
* end of this wait.
*
* @return TRUE in case of success, FALSE otherwise.
*
* @remarks After a wait block is notified, the wait function becomes invalid.
*
*--*/
BOOLEAN
NTAPI
CsrNotifyWaitBlock(IN PCSR_WAIT_BLOCK WaitBlock,
IN PLIST_ENTRY WaitList,
IN PVOID WaitArgument1,
IN PVOID WaitArgument2,
IN ULONG WaitFlags,
IN BOOLEAN DereferenceThread)
{
/* Call the wait function */
if ((WaitBlock->WaitFunction)(WaitList,
WaitBlock->WaitThread,
&WaitBlock->WaitApiMessage,
WaitBlock->WaitContext,
WaitArgument1,
WaitArgument2,
WaitFlags))
{
/* The wait is done, clear the block */
WaitBlock->WaitThread->WaitBlock = NULL;
/* Check for captured arguments */
if (WaitBlock->WaitApiMessage.CsrCaptureData)
{
/* Release them */
CsrReleaseCapturedArguments(&WaitBlock->WaitApiMessage);
}
/* Reply to the port */
NtReplyPort(WaitBlock->WaitThread->Process->ClientPort,
(PPORT_MESSAGE)&WaitBlock->WaitApiMessage);
/* Check if we should dereference the thread */
if (DereferenceThread)
{
/* Remove it from the Wait List */
if (WaitBlock->WaitList.Flink)
{
RemoveEntryList(&WaitBlock->WaitList);
}
/* Remove it from the User Wait List */
if (WaitBlock->UserWaitList.Flink)
{
RemoveEntryList(&WaitBlock->UserWaitList);
}
/* Dereference teh thread */
CsrDereferenceThread(WaitBlock->WaitThread);
/* Free the wait block */
RtlFreeHeap(CsrHeap, 0, WaitBlock);
}
else
{
/* The wait is complete, but the thread is being kept alive */
WaitBlock->WaitFunction = NULL;
}
/* The wait suceeded */
return TRUE;
}
/* The wait failed */
return FALSE;
}
/* PUBLIC FUNCTIONS **********************************************************/
/*++
* @name CsrCreateWait
* @implemented NT4
*
* The CsrCreateWait routine creates a CSR Wait.
*
* @param WaitList
* Pointer to a list entry of the waits to associate.
*
* @param WaitFunction
* Pointer to the function that will handle this wait.
*
* @param CsrWaitThread
* Pointer to the CSR Thread that will perform the wait.
*
* @param WaitApiMessage
* Pointer to the CSR API Message associated to this wait.
*
* @param WaitContext
* Pointer to a user-defined parameter associated to this wait.
*
* @param UserWaitList
* Pointer to a list entry of the user-defined waits to associate.
*
* @return TRUE in case of success, FALSE otherwise.
*
* @remarks None.
*
*--*/
BOOLEAN
NTAPI
CsrCreateWait(IN PLIST_ENTRY WaitList,
IN CSR_WAIT_FUNCTION WaitFunction,
IN PCSR_THREAD CsrWaitThread,
IN OUT PCSR_API_MESSAGE WaitApiMessage,
IN PVOID WaitContext,
IN PLIST_ENTRY UserWaitList OPTIONAL)
{
PCSR_WAIT_BLOCK WaitBlock;
/* Initialize the wait */
if (!CsrInitializeWait(WaitFunction,
CsrWaitThread,
WaitApiMessage,
WaitContext,
&WaitBlock))
{
return FALSE;
}
/* Acquire the Wait Lock */
CsrAcquireWaitLock();
/* Make sure the thread wasn't destroyed */
if (CsrWaitThread->Flags & CsrThreadTerminated)
{
/* Fail the wait */
RtlFreeHeap(CsrHeap, 0, WaitBlock);
CsrReleaseWaitLock();
return FALSE;
}
/* Insert the wait in the queue */
InsertTailList(WaitList, &WaitBlock->WaitList);
/* Insert the User Wait too, if one was given */
if (UserWaitList) InsertTailList(UserWaitList, &WaitBlock->UserWaitList);
/* Return */
CsrReleaseWaitLock();
return TRUE;
}
/*++
* @name CsrDereferenceWait
* @implemented NT4
*
* The CsrDereferenceWait routine derefences a CSR Wait Block.
*
* @param WaitList
* Pointer to the Wait List associated to the wait.
* @return None.
*
* @remarks None.
*
*--*/
VOID
NTAPI
CsrDereferenceWait(IN PLIST_ENTRY WaitList)
{
PLIST_ENTRY NextEntry;
PCSR_WAIT_BLOCK WaitBlock;
/* Acquire the Process and Wait Locks */
CsrAcquireProcessLock();
CsrAcquireWaitLock();
/* Set the list pointers */
NextEntry = WaitList->Flink;
/* Start the loop */
while (NextEntry != WaitList)
{
/* Get the wait block */
WaitBlock = CONTAINING_RECORD(NextEntry, CSR_WAIT_BLOCK, WaitList);
/* Move to the next entry */
NextEntry = NextEntry->Flink;
/* Check if there's no Wait Routine */
if (!WaitBlock->WaitFunction)
{
/* Remove it from the Wait List */
if (WaitBlock->WaitList.Flink)
{
RemoveEntryList(&WaitBlock->WaitList);
}
/* Remove it from the User Wait List */
if (WaitBlock->UserWaitList.Flink)
{
RemoveEntryList(&WaitBlock->UserWaitList);
}
/* Dereference the thread waiting on it */
CsrDereferenceThread(WaitBlock->WaitThread);
/* Free the block */
RtlFreeHeap(CsrHeap, 0, WaitBlock);
}
}
/* Release the locks */
CsrReleaseWaitLock();
CsrReleaseProcessLock();
}
/*++
* @name CsrMoveSatisfiedWait
* @implemented NT5
*
* The CsrMoveSatisfiedWait routine moves satisfied waits from a wait list
* to another list entry.
*
* @param NewEntry
* Pointer to a list entry where the satisfied waits will be added.
*
* @param WaitList
* Pointer to a list entry to analyze for satisfied waits.
*
* @return None.
*
* @remarks None.
*
*--*/
VOID
NTAPI
CsrMoveSatisfiedWait(IN PLIST_ENTRY NewEntry,
IN PLIST_ENTRY WaitList)
{
PLIST_ENTRY NextEntry;
PCSR_WAIT_BLOCK WaitBlock;
/* Acquire the Wait Lock */
CsrAcquireWaitLock();
/* Set the List pointers */
NextEntry = WaitList->Flink;
/* Start looping */
while (NextEntry != WaitList)
{
/* Get the Wait block */
WaitBlock = CONTAINING_RECORD(NextEntry, CSR_WAIT_BLOCK, WaitList);
/* Go to the next entry */
NextEntry = NextEntry->Flink;
/* Check if there is a Wait Callback */
if (WaitBlock->WaitFunction)
{
/* Remove it from the Wait Block Queue */
RemoveEntryList(&WaitBlock->WaitList);
/* Insert the new entry */
InsertTailList(&WaitBlock->WaitList, NewEntry);
}
}
/* Release the wait lock */
CsrReleaseWaitLock();
}
/*++
* @name CsrNotifyWait
* @implemented NT4
*
* The CsrNotifyWait notifies a CSR Wait Block.
*
* @param WaitList
* Pointer to the list entry for this wait.
*
* @param WaitType
* Type of the wait to perform, either WaitAny or WaitAll.
*
* @param WaitArgument[1-2]
* User-defined argument to pass on to the wait function.
*
* @return TRUE in case of success, FALSE othwerwise.
*
* @remarks None.
*
*--*/
BOOLEAN
NTAPI
CsrNotifyWait(IN PLIST_ENTRY WaitList,
IN ULONG WaitType,
IN PVOID WaitArgument1,
IN PVOID WaitArgument2)
{
PLIST_ENTRY NextEntry;
PCSR_WAIT_BLOCK WaitBlock;
BOOLEAN NotifySuccess = FALSE;
/* Acquire the Wait Lock */
CsrAcquireWaitLock();
/* Set the List pointers */
NextEntry = WaitList->Flink;
/* Start looping */
while (NextEntry != WaitList)
{
/* Get the Wait block */
WaitBlock = CONTAINING_RECORD(NextEntry, CSR_WAIT_BLOCK, WaitList);
/* Go to the next entry */
NextEntry = NextEntry->Flink;
/* Check if there is a Wait Callback */
if (WaitBlock->WaitFunction)
{
/* Notify the Waiter */
NotifySuccess |= CsrNotifyWaitBlock(WaitBlock,
WaitList,
WaitArgument1,
WaitArgument2,
0,
FALSE);
/* We've already done a wait, so leave unless this is a Wait All */
if (WaitType != WaitAll) break;
}
}
/* Release the wait lock and return */
CsrReleaseWaitLock();
return NotifySuccess;
}
/* EOF */

View file

@ -22,6 +22,18 @@
#define ProcessStructureListLocked() \
(ProcessDataLock.OwningThread == NtCurrentTeb()->ClientId.UniqueThread)
#define CsrAcquireWaitLock() \
RtlEnterCriticalSection(&CsrWaitListsLock);
#define CsrReleaseWaitLock() \
RtlLeaveCriticalSection(&CsrWaitListsLock);
#define CsrAcquireNtSessionLock() \
RtlEnterCriticalSection(&CsrNtSessionLock);
#define CsrReleaseNtSessionLock() \
RtlLeaveCriticalSection(&CsrNtSessionLock);
typedef enum _CSR_THREAD_FLAGS
{
CsrThreadAltertable = 0x1,
@ -66,6 +78,13 @@ typedef struct _CSRSS_CON_PROCESS_DATA
LIST_ENTRY ConsoleLink;
} CSRSS_CON_PROCESS_DATA, *PCSRSS_CON_PROCESS_DATA;
typedef struct _CSR_NT_SESSION
{
ULONG ReferenceCount;
LIST_ENTRY SessionLink;
ULONG SessionId;
} CSR_NT_SESSION, *PCSR_NT_SESSION;
typedef struct _CSR_PROCESS
{
CLIENT_ID ClientId;
@ -102,13 +121,36 @@ typedef struct _CSR_THREAD
LIST_ENTRY HashLinks;
CLIENT_ID ClientId;
PCSR_PROCESS Process;
//struct _CSR_WAIT_BLOCK *WaitBlock;
struct _CSR_WAIT_BLOCK *WaitBlock;
HANDLE ThreadHandle;
ULONG Flags;
ULONG ReferenceCount;
ULONG ImpersonationCount;
} CSR_THREAD, *PCSR_THREAD;
typedef
BOOLEAN
(*CSR_WAIT_FUNCTION)(
IN PLIST_ENTRY WaitList,
IN PCSR_THREAD WaitThread,
IN PCSR_API_MESSAGE WaitApiMessage,
IN PVOID WaitContext,
IN PVOID WaitArgument1,
IN PVOID WaitArgument2,
IN ULONG WaitFlags
);
typedef struct _CSR_WAIT_BLOCK
{
ULONG Size;
LIST_ENTRY WaitList;
LIST_ENTRY UserWaitList;
PVOID WaitContext;
PCSR_THREAD WaitThread;
CSR_WAIT_FUNCTION WaitFunction;
CSR_API_MESSAGE WaitApiMessage;
} CSR_WAIT_BLOCK, *PCSR_WAIT_BLOCK;
typedef NTSTATUS (WINAPI *CSRSS_API_PROC)(PCSR_PROCESS ProcessData,
PCSR_API_MESSAGE Request);
@ -165,6 +207,10 @@ VOID
NTAPI
CsrRemoveProcess(IN PCSR_PROCESS CsrProcess);
VOID
NTAPI
CsrDereferenceThread(IN PCSR_THREAD CsrThread);
VOID
NTAPI
CsrInsertProcess(IN PCSR_PROCESS Parent OPTIONAL,
@ -179,6 +225,11 @@ VOID FASTCALL CsrApiCallHandler(PCSR_PROCESS ProcessData,
VOID WINAPI CsrSbApiRequestThread (PVOID PortHandle);
VOID NTAPI ClientConnectionThread(HANDLE ServerPort);
VOID
NTAPI
CsrReleaseCapturedArguments(IN PCSR_API_MESSAGE ApiMessage);
extern HANDLE CsrSmApiPort;
extern HANDLE CsrSbApiPort;
extern LIST_ENTRY CsrThreadHashTable[256];
extern PCSR_PROCESS CsrRootProcess;
@ -211,6 +262,10 @@ NTSTATUS NTAPI CsrUnlockProcess(IN PCSR_PROCESS CsrProcess);
//hack
VOID NTAPI CsrThreadRefcountZero(IN PCSR_THREAD CsrThread);
NTSTATUS
NTAPI
CsrInitializeNtSessionList(VOID);
/* api/user.c */
CSR_API(CsrRegisterServicesProcess);