Windows2000/private/ntos/ex/exatom.c
2020-09-30 17:12:32 +02:00

469 lines
9.1 KiB
C

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
exatom.c
Abstract:
This file contains functions for manipulating global atom tables
stored in kernel space.
Author:
Steve Wood (stevewo) 13-Dec-1995
Revision History:
--*/
#include "exp.h"
#pragma hdrstop
// Local Procedure prototype
PVOID
ExpGetGlobalAtomTable (
);
#if defined(ALLOC_PRAGMA)
#pragma alloc_text(PAGE, NtAddAtom)
#pragma alloc_text(PAGE, NtFindAtom)
#pragma alloc_text(PAGE, NtDeleteAtom)
#pragma alloc_text(PAGE, NtQueryInformationAtom)
#pragma alloc_text(PAGE, ExpGetGlobalAtomTable)
#endif
NTSYSAPI
NTSTATUS
NTAPI
NtAddAtom (
IN PWSTR AtomName,
IN ULONG Length,
OUT PRTL_ATOM Atom OPTIONAL
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
NTSTATUS Status;
RTL_ATOM ReturnAtom;
PVOID AtomTable = ExpGetGlobalAtomTable();
KPROCESSOR_MODE PreviousMode;
PWSTR CapturedAtomNameBuffer;
ULONG AllocLength;
PAGED_CODE();
if (AtomTable == NULL) {
return STATUS_ACCESS_DENIED;
}
if (Length > (RTL_ATOM_MAXIMUM_NAME_LENGTH * sizeof(WCHAR))) {
return STATUS_INVALID_PARAMETER;
}
PreviousMode = KeGetPreviousMode();
CapturedAtomNameBuffer = NULL;
Status = STATUS_SUCCESS;
if (PreviousMode != KernelMode) {
try {
if (ARGUMENT_PRESENT( AtomName )) {
AllocLength = (Length + sizeof( UNICODE_NULL ))&~(sizeof (WCHAR)-1);
ProbeForRead( AtomName, Length, sizeof( WCHAR ) );
CapturedAtomNameBuffer = ExAllocatePoolWithTag( PagedPool, AllocLength, 'motA' );
if (CapturedAtomNameBuffer == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlMoveMemory( CapturedAtomNameBuffer, AtomName, Length );
CapturedAtomNameBuffer[Length / sizeof (WCHAR)] = '\0';
}
if (ARGUMENT_PRESENT( Atom )) {
ProbeForWriteUshort( Atom );
}
} except (EXCEPTION_EXECUTE_HANDLER) {
Status = GetExceptionCode();
}
} else {
if (ARGUMENT_PRESENT( AtomName )) {
CapturedAtomNameBuffer = AtomName;
}
}
if (NT_SUCCESS( Status )) {
Status = RtlAddAtomToAtomTable( AtomTable, CapturedAtomNameBuffer, &ReturnAtom );
if (NT_SUCCESS( Status ) && ARGUMENT_PRESENT( Atom )) {
try {
*Atom = ReturnAtom;
} except (EXCEPTION_EXECUTE_HANDLER) {
Status = GetExceptionCode();
}
}
}
if ((CapturedAtomNameBuffer != NULL) && (CapturedAtomNameBuffer != AtomName)) {
ExFreePool( CapturedAtomNameBuffer );
}
return Status;
}
NTSYSAPI
NTSTATUS
NTAPI
NtFindAtom (
IN PWSTR AtomName,
IN ULONG Length,
OUT PRTL_ATOM Atom OPTIONAL
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
NTSTATUS Status;
RTL_ATOM ReturnAtom;
PVOID AtomTable = ExpGetGlobalAtomTable();
KPROCESSOR_MODE PreviousMode;
PWSTR CapturedAtomNameBuffer;
ULONG AllocLength;
PAGED_CODE();
if (AtomTable == NULL) {
return STATUS_ACCESS_DENIED;
}
if (Length > (RTL_ATOM_MAXIMUM_NAME_LENGTH * sizeof(WCHAR))) {
return STATUS_INVALID_PARAMETER;
}
PreviousMode = KeGetPreviousMode();
CapturedAtomNameBuffer = NULL;
Status = STATUS_SUCCESS;
if (PreviousMode != KernelMode) {
try {
if (ARGUMENT_PRESENT( AtomName )) {
AllocLength = (Length + sizeof( UNICODE_NULL ))&~(sizeof (WCHAR)-1);
ProbeForRead( AtomName, Length, sizeof( WCHAR ) );
CapturedAtomNameBuffer = ExAllocatePoolWithTag( PagedPool, AllocLength, 'motA' );
if (CapturedAtomNameBuffer == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlMoveMemory( CapturedAtomNameBuffer, AtomName, Length );
CapturedAtomNameBuffer[Length / sizeof (WCHAR)] = '\0';
}
if (ARGUMENT_PRESENT( Atom )) {
ProbeForWriteUshort( Atom );
}
} except (EXCEPTION_EXECUTE_HANDLER) {
Status = GetExceptionCode();
}
} else {
if (ARGUMENT_PRESENT( AtomName )) {
CapturedAtomNameBuffer = AtomName;
}
}
if (NT_SUCCESS( Status )) {
Status = RtlLookupAtomInAtomTable( AtomTable, CapturedAtomNameBuffer, &ReturnAtom );
if (NT_SUCCESS( Status ) && ARGUMENT_PRESENT( Atom )) {
try {
*Atom = ReturnAtom;
} except (EXCEPTION_EXECUTE_HANDLER) {
Status = GetExceptionCode();
}
}
}
if (CapturedAtomNameBuffer != NULL && CapturedAtomNameBuffer != AtomName) {
ExFreePool( CapturedAtomNameBuffer );
}
return Status;
}
NTSYSAPI
NTSTATUS
NTAPI
NtDeleteAtom (
IN RTL_ATOM Atom
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
NTSTATUS Status;
PVOID AtomTable = ExpGetGlobalAtomTable();
PAGED_CODE();
if (AtomTable == NULL) {
return STATUS_ACCESS_DENIED;
}
Status = RtlDeleteAtomFromAtomTable( AtomTable, Atom );
return Status;
}
NTSYSAPI
NTSTATUS
NTAPI
NtQueryInformationAtom(
IN RTL_ATOM Atom,
IN ATOM_INFORMATION_CLASS AtomInformationClass,
OUT PVOID AtomInformation,
IN ULONG AtomInformationLength,
OUT PULONG ReturnLength OPTIONAL
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
NTSTATUS Status;
KPROCESSOR_MODE PreviousMode;
ULONG RequiredLength;
ULONG UsageCount;
ULONG NameLength;
ULONG AtomFlags;
PATOM_BASIC_INFORMATION BasicInfo;
PATOM_TABLE_INFORMATION TableInfo;
PVOID AtomTable = ExpGetGlobalAtomTable();
PAGED_CODE();
if (AtomTable == NULL) {
return STATUS_ACCESS_DENIED;
}
// Assume successful completion.
Status = STATUS_SUCCESS;
try {
// Get previous processor mode and probe output argument if necessary.
PreviousMode = KeGetPreviousMode();
if (PreviousMode != KernelMode) {
ProbeForWrite( AtomInformation,
AtomInformationLength,
sizeof( ULONG ));
if (ARGUMENT_PRESENT( ReturnLength )) {
ProbeForWriteUlong( ReturnLength );
}
}
RequiredLength = 0;
switch (AtomInformationClass) {
case AtomBasicInformation:
RequiredLength = FIELD_OFFSET( ATOM_BASIC_INFORMATION, Name );
if (AtomInformationLength < RequiredLength) {
return STATUS_INFO_LENGTH_MISMATCH;
}
BasicInfo = (PATOM_BASIC_INFORMATION)AtomInformation;
UsageCount = 0;
NameLength = AtomInformationLength - RequiredLength;
BasicInfo->Name[ 0 ] = UNICODE_NULL;
Status = RtlQueryAtomInAtomTable( AtomTable,
Atom,
&UsageCount,
&AtomFlags,
&BasicInfo->Name[0],
&NameLength );
if (NT_SUCCESS(Status)) {
BasicInfo->UsageCount = (USHORT)UsageCount;
BasicInfo->Flags = (USHORT)AtomFlags;
BasicInfo->NameLength = (USHORT)NameLength;
RequiredLength += NameLength + sizeof( UNICODE_NULL );
}
break;
case AtomTableInformation:
RequiredLength = FIELD_OFFSET( ATOM_TABLE_INFORMATION, Atoms );
if (AtomInformationLength < RequiredLength) {
return STATUS_INFO_LENGTH_MISMATCH;
}
TableInfo = (PATOM_TABLE_INFORMATION)AtomInformation;
Status = RtlQueryAtomsInAtomTable( AtomTable,
(AtomInformationLength - RequiredLength) / sizeof( RTL_ATOM ),
&TableInfo->NumberOfAtoms,
&TableInfo->Atoms[0] );
if (NT_SUCCESS(Status)) {
RequiredLength += TableInfo->NumberOfAtoms * sizeof( RTL_ATOM );
}
break;
default:
Status = STATUS_INVALID_INFO_CLASS;
break;
}
if (ARGUMENT_PRESENT( ReturnLength )) {
*ReturnLength = RequiredLength;
}
} except (EXCEPTION_EXECUTE_HANDLER) {
Status = GetExceptionCode();
}
return Status;
}
// Local support routine
PKWIN32_GLOBALATOMTABLE_CALLOUT ExGlobalAtomTableCallout;
PVOID
ExpGetGlobalAtomTable (
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
if (ExGlobalAtomTableCallout != NULL) {
return ((*ExGlobalAtomTableCallout)());
} else {
#if DBG
DbgPrint( "EX: ExpGetGlobalAtomTable is about to return NULL!\n" );
DbgBreakPoint();
#endif
return NULL;
}
}