347 lines
9.8 KiB
C
347 lines
9.8 KiB
C
/*++
|
|
|
|
Copyright (c) 1990 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
srvatom.c
|
|
|
|
Abstract:
|
|
|
|
This file contains the Global Atom manager API routines
|
|
|
|
Author:
|
|
|
|
Steve Wood (stevewo) 29-Oct-1990
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "basesrv.h"
|
|
|
|
//
|
|
// Pointer to User function that returns a pointer to the
|
|
// global atom table associated with the windowstation
|
|
// userd by the specified thread.
|
|
//
|
|
|
|
NTSTATUS (*_UserGetGlobalAtomTable)(
|
|
HANDLE hThread,
|
|
PVOID *GlobalAtomTable
|
|
);
|
|
|
|
//
|
|
// Pointer to User function that sets a pointer to the
|
|
// global atom table into the windowstation associated
|
|
// with the specified thread.
|
|
//
|
|
|
|
NTSTATUS (*_UserSetGlobalAtomTable)(
|
|
HANDLE hThread,
|
|
PVOID GlobalAtomTable
|
|
);
|
|
|
|
NTSTATUS
|
|
BaseSrvGetGlobalAtomTable(
|
|
PVOID *GlobalAtomTable
|
|
)
|
|
{
|
|
STRING ProcedureName;
|
|
ANSI_STRING DllName;
|
|
UNICODE_STRING DllName_U;
|
|
HANDLE UserServerModuleHandle;
|
|
static BOOL fInit = FALSE;
|
|
NTSTATUS Status;
|
|
|
|
if ( _UserGetGlobalAtomTable == NULL ) {
|
|
|
|
if ( fInit == TRUE ) {
|
|
|
|
//
|
|
// If the exported atom routines cannot be found, deny access
|
|
//
|
|
|
|
return( STATUS_ACCESS_DENIED );
|
|
}
|
|
|
|
fInit = TRUE;
|
|
|
|
//
|
|
// Load pointers to the functions in winsrv.dll
|
|
//
|
|
|
|
RtlInitAnsiString( &DllName, "winsrv" );
|
|
RtlAnsiStringToUnicodeString( &DllName_U, &DllName, TRUE );
|
|
Status = LdrGetDllHandle(
|
|
UNICODE_NULL,
|
|
NULL,
|
|
&DllName_U,
|
|
(PVOID *)&UserServerModuleHandle
|
|
);
|
|
|
|
RtlFreeUnicodeString( &DllName_U );
|
|
|
|
if ( NT_SUCCESS(Status) ) {
|
|
|
|
//
|
|
// Now get the routined to query and set the
|
|
// atom table pointer.
|
|
//
|
|
|
|
RtlInitString( &ProcedureName, "_UserGetGlobalAtomTable" );
|
|
Status = LdrGetProcedureAddress(
|
|
(PVOID)UserServerModuleHandle,
|
|
&ProcedureName,
|
|
0L,
|
|
(PVOID *)&_UserGetGlobalAtomTable
|
|
);
|
|
|
|
RtlInitString( &ProcedureName, "_UserSetGlobalAtomTable" );
|
|
Status = LdrGetProcedureAddress(
|
|
(PVOID)UserServerModuleHandle,
|
|
&ProcedureName,
|
|
0L,
|
|
(PVOID *)&_UserSetGlobalAtomTable
|
|
);
|
|
}
|
|
|
|
//
|
|
// Deny access upon failure
|
|
//
|
|
|
|
if ( !NT_SUCCESS(Status) )
|
|
return( STATUS_ACCESS_DENIED );
|
|
}
|
|
|
|
Status = (*_UserGetGlobalAtomTable)(
|
|
CSR_SERVER_QUERYCLIENTTHREAD()->ThreadHandle,
|
|
GlobalAtomTable);
|
|
if ( !NT_SUCCESS(Status) ) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Lock the heap until the call is complete.
|
|
//
|
|
|
|
RtlLockHeap( BaseSrvHeap );
|
|
|
|
//
|
|
// If there is an atom table, return it.
|
|
//
|
|
|
|
if ( *GlobalAtomTable ) {
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
Status = BaseRtlCreateAtomTable( 37,
|
|
(USHORT)~MAXINTATOM,
|
|
GlobalAtomTable
|
|
);
|
|
|
|
if ( NT_SUCCESS(Status) ) {
|
|
Status = (*_UserSetGlobalAtomTable)(
|
|
CSR_SERVER_QUERYCLIENTTHREAD()->ThreadHandle,
|
|
*GlobalAtomTable);
|
|
if ( !NT_SUCCESS(Status) ) {
|
|
BaseRtlDestroyAtomTable( *GlobalAtomTable );
|
|
}
|
|
}
|
|
|
|
if ( !NT_SUCCESS(Status) ) {
|
|
RtlUnlockHeap( BaseSrvHeap );
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
ULONG
|
|
BaseSrvDestroyGlobalAtomTable(
|
|
IN OUT PCSR_API_MSG m,
|
|
IN OUT PCSR_REPLY_STATUS ReplyStatus
|
|
)
|
|
{
|
|
PBASE_DESTROYGLOBALATOMTABLE_MSG a = (PBASE_DESTROYGLOBALATOMTABLE_MSG)&m->u.ApiMessageData;
|
|
|
|
return BaseRtlDestroyAtomTable(a->GlobalAtomTable);
|
|
}
|
|
|
|
ULONG
|
|
BaseSrvGlobalAddAtom(
|
|
IN OUT PCSR_API_MSG m,
|
|
IN OUT PCSR_REPLY_STATUS ReplyStatus
|
|
)
|
|
{
|
|
PBASE_GLOBALATOMNAME_MSG a = (PBASE_GLOBALATOMNAME_MSG)&m->u.ApiMessageData;
|
|
PVOID GlobalAtomTable;
|
|
NTSTATUS Status;
|
|
UNICODE_STRING AtomName;
|
|
|
|
AtomName = a->AtomName;
|
|
if (a->AtomNameInClient) {
|
|
AtomName.Buffer = RtlAllocateHeap( BaseSrvHeap,
|
|
MAKE_TAG( TMP_TAG ),
|
|
AtomName.Length
|
|
);
|
|
if (AtomName.Buffer == NULL) {
|
|
return (ULONG)STATUS_NO_MEMORY;
|
|
}
|
|
|
|
Status = NtReadVirtualMemory( CSR_SERVER_QUERYCLIENTTHREAD()->Process->ProcessHandle,
|
|
a->AtomName.Buffer,
|
|
AtomName.Buffer,
|
|
AtomName.Length,
|
|
NULL
|
|
);
|
|
}
|
|
else {
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
|
|
if (NT_SUCCESS( Status )) {
|
|
Status = BaseSrvGetGlobalAtomTable(&GlobalAtomTable);
|
|
if (NT_SUCCESS( Status )) {
|
|
Status = BaseRtlAddAtomToAtomTable( GlobalAtomTable,
|
|
&AtomName,
|
|
NULL,
|
|
&a->Atom
|
|
);
|
|
RtlUnlockHeap( BaseSrvHeap );
|
|
}
|
|
}
|
|
|
|
if (a->AtomNameInClient) {
|
|
RtlFreeHeap( BaseSrvHeap, 0, AtomName.Buffer );
|
|
}
|
|
|
|
return( (ULONG)Status );
|
|
ReplyStatus; // get rid of unreferenced parameter warning message
|
|
}
|
|
|
|
|
|
ULONG
|
|
BaseSrvGlobalFindAtom(
|
|
IN OUT PCSR_API_MSG m,
|
|
IN OUT PCSR_REPLY_STATUS ReplyStatus
|
|
)
|
|
{
|
|
PBASE_GLOBALATOMNAME_MSG a = (PBASE_GLOBALATOMNAME_MSG)&m->u.ApiMessageData;
|
|
PVOID GlobalAtomTable;
|
|
UNICODE_STRING AtomName;
|
|
NTSTATUS Status;
|
|
|
|
AtomName = a->AtomName;
|
|
if (a->AtomNameInClient) {
|
|
AtomName.Buffer = RtlAllocateHeap( BaseSrvHeap,
|
|
MAKE_TAG( TMP_TAG ),
|
|
AtomName.Length
|
|
);
|
|
if (AtomName.Buffer == NULL) {
|
|
return (ULONG)STATUS_NO_MEMORY;
|
|
}
|
|
|
|
Status = NtReadVirtualMemory( CSR_SERVER_QUERYCLIENTTHREAD()->Process->ProcessHandle,
|
|
a->AtomName.Buffer,
|
|
AtomName.Buffer,
|
|
AtomName.Length,
|
|
NULL
|
|
);
|
|
}
|
|
else {
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
|
|
if (NT_SUCCESS( Status )) {
|
|
Status = BaseSrvGetGlobalAtomTable(&GlobalAtomTable);
|
|
if (NT_SUCCESS( Status )) {
|
|
Status = BaseRtlLookupAtomInAtomTable( GlobalAtomTable,
|
|
&AtomName,
|
|
NULL,
|
|
&a->Atom
|
|
);
|
|
RtlUnlockHeap( BaseSrvHeap );
|
|
}
|
|
}
|
|
|
|
if (a->AtomNameInClient) {
|
|
RtlFreeHeap( BaseSrvHeap, 0, AtomName.Buffer );
|
|
}
|
|
|
|
return( (ULONG)Status );
|
|
ReplyStatus; // get rid of unreferenced parameter warning message
|
|
}
|
|
|
|
ULONG
|
|
BaseSrvGlobalDeleteAtom(
|
|
IN OUT PCSR_API_MSG m,
|
|
IN OUT PCSR_REPLY_STATUS ReplyStatus
|
|
)
|
|
{
|
|
PBASE_GLOBALDELETEATOM_MSG a = (PBASE_GLOBALDELETEATOM_MSG)&m->u.ApiMessageData;
|
|
PVOID GlobalAtomTable;
|
|
NTSTATUS Status;
|
|
|
|
Status = BaseSrvGetGlobalAtomTable(&GlobalAtomTable);
|
|
if (NT_SUCCESS( Status )) {
|
|
Status = BaseRtlDeleteAtomFromAtomTable( GlobalAtomTable,
|
|
a->Atom
|
|
);
|
|
RtlUnlockHeap( BaseSrvHeap );
|
|
}
|
|
|
|
return( (ULONG)Status );
|
|
ReplyStatus; // get rid of unreferenced parameter warning message
|
|
}
|
|
|
|
ULONG
|
|
BaseSrvGlobalGetAtomName(
|
|
IN OUT PCSR_API_MSG m,
|
|
IN OUT PCSR_REPLY_STATUS ReplyStatus
|
|
)
|
|
{
|
|
PBASE_GLOBALATOMNAME_MSG a = (PBASE_GLOBALATOMNAME_MSG)&m->u.ApiMessageData;
|
|
UNICODE_STRING AtomName;
|
|
PVOID GlobalAtomTable;
|
|
NTSTATUS Status;
|
|
|
|
AtomName = a->AtomName;
|
|
if (a->AtomNameInClient) {
|
|
AtomName.Buffer = RtlAllocateHeap( BaseSrvHeap,
|
|
MAKE_TAG( TMP_TAG ),
|
|
AtomName.MaximumLength
|
|
);
|
|
if (AtomName.Buffer == NULL) {
|
|
return (ULONG)STATUS_NO_MEMORY;
|
|
}
|
|
}
|
|
|
|
Status = BaseSrvGetGlobalAtomTable(&GlobalAtomTable);
|
|
if (NT_SUCCESS( Status )) {
|
|
Status = BaseRtlQueryAtomInAtomTable( GlobalAtomTable,
|
|
a->Atom,
|
|
&AtomName,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
a->AtomName.Length = AtomName.Length;
|
|
if (NT_SUCCESS( Status ) && a->AtomNameInClient) {
|
|
Status = NtWriteVirtualMemory( CSR_SERVER_QUERYCLIENTTHREAD()->Process->ProcessHandle,
|
|
a->AtomName.Buffer,
|
|
AtomName.Buffer,
|
|
AtomName.Length,
|
|
NULL
|
|
);
|
|
}
|
|
RtlUnlockHeap( BaseSrvHeap );
|
|
}
|
|
|
|
if (a->AtomNameInClient) {
|
|
RtlFreeHeap( BaseSrvHeap, 0, AtomName.Buffer );
|
|
}
|
|
|
|
return( (ULONG)Status );
|
|
ReplyStatus; // get rid of unreferenced parameter warning message
|
|
}
|