windows-nt/Source/XPSP1/NT/base/win32/client/dllatom.c

528 lines
12 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1990 Microsoft Corporation
Module Name:
atom.c
Abstract:
This module contains the Win32 Atom Management APIs
Author:
Steve Wood (stevewo) 24-Sep-1990
Revision History:
--*/
#include "basedll.h"
typedef ATOM *PATOM;
BOOL
InternalGetIntAtom(
PUNICODE_STRING UnicodeAtomName,
PATOM Atom
);
ATOM
InternalAddAtom(
BOOLEAN UseLocalAtomTable,
BOOLEAN IsUnicodeAtomName,
LPCSTR AtomName
);
ATOM
InternalFindAtom(
BOOLEAN UseLocalAtomTable,
BOOLEAN IsUnicodeAtomName,
LPCSTR AtomName
);
ATOM
InternalDeleteAtom(
BOOLEAN UseLocalAtomTable,
ATOM nAtom
);
UINT
InternalGetAtomName(
BOOLEAN UseLocalAtomTable,
BOOLEAN IsUnicodeAtomName,
ATOM nAtom,
LPSTR AtomName,
DWORD nSize
);
ATOM
GlobalAddAtomA(
LPCSTR lpString
)
{
return( InternalAddAtom( FALSE, FALSE, lpString ) );
}
ATOM
GlobalFindAtomA(
LPCSTR lpString
)
{
return( InternalFindAtom( FALSE, FALSE, lpString) );
}
ATOM
GlobalDeleteAtom(
ATOM nAtom
)
{
return( InternalDeleteAtom( FALSE, nAtom ) );
}
UINT
GlobalGetAtomNameA(
ATOM nAtom,
LPSTR lpBuffer,
int nSize
)
{
return( InternalGetAtomName( FALSE, FALSE, nAtom, lpBuffer, (DWORD)nSize ) );
}
ATOM
APIENTRY
GlobalAddAtomW(
LPCWSTR lpString
)
{
return( InternalAddAtom( FALSE, TRUE, (LPSTR)lpString ) );
}
ATOM
APIENTRY
GlobalFindAtomW(
LPCWSTR lpString
)
{
return( InternalFindAtom( FALSE, TRUE, (LPSTR)lpString) );
}
UINT
APIENTRY
GlobalGetAtomNameW(
ATOM nAtom,
LPWSTR lpBuffer,
int nSize
)
{
return( InternalGetAtomName( FALSE, TRUE, nAtom, (LPSTR)lpBuffer, (DWORD)nSize ) );
}
PVOID BaseLocalAtomTable;
BOOL
APIENTRY
InitAtomTable(
DWORD nSize
)
{
if (nSize < 4 || nSize > 511) {
nSize = 37;
}
return RtlCreateAtomTable( nSize, &BaseLocalAtomTable ) == STATUS_SUCCESS;
}
ATOM
AddAtomA(
LPCSTR lpString
)
{
return( InternalAddAtom( TRUE, FALSE, lpString ) );
}
ATOM
FindAtomA(
LPCSTR lpString
)
{
return( InternalFindAtom( TRUE, FALSE, lpString ) );
}
ATOM
DeleteAtom(
ATOM nAtom
)
{
return( InternalDeleteAtom( TRUE, nAtom ) );
}
UINT
GetAtomNameA(
ATOM nAtom,
LPSTR lpBuffer,
int nSize
)
{
return( InternalGetAtomName( TRUE, FALSE, nAtom, lpBuffer, (DWORD)nSize ) );
}
ATOM
APIENTRY
AddAtomW(
LPCWSTR lpString
)
{
return( InternalAddAtom( TRUE, TRUE, (LPSTR)lpString ) );
}
ATOM
APIENTRY
FindAtomW(
LPCWSTR lpString
)
{
return( InternalFindAtom( TRUE, TRUE, (LPSTR)lpString ) );
}
UINT
APIENTRY
GetAtomNameW(
ATOM nAtom,
LPWSTR lpBuffer,
int nSize
)
{
return( InternalGetAtomName( TRUE, TRUE, nAtom, (LPSTR)lpBuffer, (DWORD)nSize ) );
}
PVOID
InternalInitAtomTable( void )
{
NTSTATUS Status;
if (BaseLocalAtomTable == NULL) {
Status = RtlCreateAtomTable( 0, &BaseLocalAtomTable );
}
return BaseLocalAtomTable;
}
ATOM
InternalAddAtom(
BOOLEAN UseLocalAtomTable,
BOOLEAN IsUnicodeAtomName,
LPCSTR AtomName
)
{
NTSTATUS Status;
ANSI_STRING AnsiString;
UNICODE_STRING UnicodeString;
PUNICODE_STRING UnicodeAtomName;
ATOM Atom;
if ( (ULONG_PTR)AtomName <= 0xFFFF ) {
Atom = (ATOM)PtrToShort((PVOID)AtomName);
if (Atom >= MAXINTATOM) {
BaseSetLastNTError( STATUS_INVALID_PARAMETER );
return( INVALID_ATOM );
}
else {
return( (ATOM)Atom );
}
}
else {
try {
if (IsUnicodeAtomName) {
UnicodeAtomName = &UnicodeString;
RtlInitUnicodeString( UnicodeAtomName, (PWSTR)AtomName );
Status = STATUS_SUCCESS;
}
else {
RtlInitAnsiString( &AnsiString, AtomName );
if (AnsiString.MaximumLength > STATIC_UNICODE_BUFFER_LENGTH) {
UnicodeAtomName = &UnicodeString;
Status = RtlAnsiStringToUnicodeString( UnicodeAtomName, &AnsiString, TRUE );
}
else {
UnicodeAtomName = &NtCurrentTeb()->StaticUnicodeString;
Status = RtlAnsiStringToUnicodeString( UnicodeAtomName, &AnsiString, FALSE );
}
}
}
except (EXCEPTION_EXECUTE_HANDLER) {
Status = GetExceptionCode();
}
if ( !NT_SUCCESS(Status) ) {
BaseSetLastNTError( Status );
return( INVALID_ATOM );
}
}
Atom = INVALID_ATOM;
try {
if (UseLocalAtomTable) {
Status = RtlAddAtomToAtomTable( InternalInitAtomTable(),
UnicodeAtomName->Buffer,
&Atom
);
}
else {
Status = NtAddAtom( UnicodeAtomName->Buffer,
UnicodeAtomName->Length,
&Atom
);
}
if (!NT_SUCCESS( Status )) {
BaseSetLastNTError( Status );
Atom = INVALID_ATOM;
}
}
finally {
if (!IsUnicodeAtomName && UnicodeAtomName == &UnicodeString) {
RtlFreeUnicodeString( UnicodeAtomName );
}
}
return( (ATOM)Atom );
}
ATOM
InternalFindAtom(
BOOLEAN UseLocalAtomTable,
BOOLEAN IsUnicodeAtomName,
LPCSTR AtomName
)
{
NTSTATUS Status;
ANSI_STRING AnsiString;
UNICODE_STRING UnicodeString;
PUNICODE_STRING UnicodeAtomName;
ATOM Atom;
if ( (ULONG_PTR)AtomName <= 0xFFFF ) {
Atom = (ATOM)PtrToShort((PVOID)AtomName);
if (Atom >= MAXINTATOM) {
BaseSetLastNTError( STATUS_INVALID_PARAMETER );
return( INVALID_ATOM );
}
else {
return( (ATOM)Atom );
}
}
else {
try {
if (IsUnicodeAtomName) {
UnicodeAtomName = &UnicodeString;
RtlInitUnicodeString( UnicodeAtomName, (PWSTR)AtomName );
Status = STATUS_SUCCESS;
}
else {
RtlInitAnsiString( &AnsiString, AtomName );
if (AnsiString.MaximumLength > STATIC_UNICODE_BUFFER_LENGTH) {
UnicodeAtomName = &UnicodeString;
Status = RtlAnsiStringToUnicodeString( UnicodeAtomName, &AnsiString, TRUE );
}
else {
UnicodeAtomName = &NtCurrentTeb()->StaticUnicodeString;
Status = RtlAnsiStringToUnicodeString( UnicodeAtomName, &AnsiString, FALSE );
}
}
}
except (EXCEPTION_EXECUTE_HANDLER) {
Status = GetExceptionCode();
}
if ( !NT_SUCCESS(Status) ) {
BaseSetLastNTError( Status );
return( INVALID_ATOM );
}
}
Atom = INVALID_ATOM;
try {
if (UseLocalAtomTable) {
Status = RtlLookupAtomInAtomTable( InternalInitAtomTable(),
UnicodeAtomName->Buffer,
&Atom
);
}
else {
if (UnicodeAtomName->Length == 0) {
SetLastError( ERROR_INVALID_NAME );
leave;
}
Status = NtFindAtom( UnicodeAtomName->Buffer,
UnicodeAtomName->Length,
&Atom
);
}
if (!NT_SUCCESS( Status )) {
BaseSetLastNTError( Status );
Atom = INVALID_ATOM;
leave;
}
}
finally {
if (!IsUnicodeAtomName && UnicodeAtomName == &UnicodeString) {
RtlFreeUnicodeString( UnicodeAtomName );
}
}
return( (ATOM)Atom );
}
ATOM
InternalDeleteAtom(
BOOLEAN UseLocalAtomTable,
ATOM nAtom
)
{
NTSTATUS Status;
if (nAtom >= MAXINTATOM) {
if (UseLocalAtomTable) {
Status = RtlDeleteAtomFromAtomTable( InternalInitAtomTable(), nAtom );
}
else {
Status = NtDeleteAtom( nAtom );
}
if (!NT_SUCCESS( Status )) {
BaseSetLastNTError( Status );
return( INVALID_ATOM );
}
}
return( 0 );
}
UINT
InternalGetAtomName(
BOOLEAN UseLocalAtomTable,
BOOLEAN IsUnicodeAtomName,
ATOM nAtom,
LPSTR AtomName,
DWORD nSize
)
{
NTSTATUS Status;
PVOID FreeBuffer = NULL;
ANSI_STRING AnsiString;
UNICODE_STRING UnicodeString;
PWSTR UnicodeAtomName;
ULONG AtomInfoLength, AtomNameLength;
DWORD ReturnValue;
PATOM_BASIC_INFORMATION AtomInfo;
//
// Trim nSize so that it will not overflow the 16-bit unicode string
// maximum length field. This prevents people that call us with a >=32KB
// query buffer from stubbing their toes when they call the Ansi version
// of the GetAtomName API
//
if (!IsUnicodeAtomName && nSize > 0x7000) {
nSize = 0x7000;
}
if (nSize == 0) {
BaseSetLastNTError( STATUS_BUFFER_OVERFLOW );
return( 0 );
}
if (UseLocalAtomTable) {
if (IsUnicodeAtomName) {
UnicodeAtomName = (PWSTR)AtomName;
}
else {
FreeBuffer = RtlAllocateHeap( RtlProcessHeap(),
MAKE_TAG( TMP_TAG ),
nSize * sizeof( WCHAR )
);
if (FreeBuffer == NULL) {
BaseSetLastNTError( STATUS_NO_MEMORY );
return( 0 );
}
UnicodeAtomName = (PWSTR)FreeBuffer;
}
AtomNameLength = nSize * sizeof( WCHAR );
Status = RtlQueryAtomInAtomTable( InternalInitAtomTable(),
nAtom,
NULL,
NULL,
UnicodeAtomName,
&AtomNameLength
);
}
else {
AtomInfoLength = sizeof( *AtomInfo ) + (nSize * sizeof( WCHAR ));
FreeBuffer = RtlAllocateHeap( RtlProcessHeap(),
MAKE_TAG( TMP_TAG ),
AtomInfoLength
);
if (FreeBuffer == NULL) {
BaseSetLastNTError( STATUS_NO_MEMORY );
return( 0 );
}
AtomInfo = (PATOM_BASIC_INFORMATION)FreeBuffer;
Status = NtQueryInformationAtom( nAtom,
AtomBasicInformation,
AtomInfo,
AtomInfoLength,
&AtomInfoLength
);
if (NT_SUCCESS( Status )) {
AtomNameLength = (ULONG)AtomInfo->NameLength;
UnicodeAtomName = AtomInfo->Name;
}
}
if (NT_SUCCESS( Status )) {
if (IsUnicodeAtomName) {
ReturnValue = AtomNameLength / sizeof( WCHAR );
if (UnicodeAtomName != (PWSTR)AtomName) {
RtlMoveMemory( AtomName, UnicodeAtomName, AtomNameLength );
}
if (ReturnValue < nSize) {
*((PWSTR)AtomName + ReturnValue) = UNICODE_NULL;
}
}
else {
UnicodeString.Buffer = UnicodeAtomName;
UnicodeString.Length = (USHORT)AtomNameLength;
UnicodeString.MaximumLength = (USHORT)(UnicodeString.Length + sizeof( UNICODE_NULL ));
AnsiString.Buffer = AtomName;
AnsiString.Length = 0;
AnsiString.MaximumLength = (USHORT)nSize;
Status = RtlUnicodeStringToAnsiString( &AnsiString, &UnicodeString, FALSE );
if (NT_SUCCESS( Status )) {
ReturnValue = AnsiString.Length;
}
}
}
if (FreeBuffer != NULL) {
RtlFreeHeap( RtlProcessHeap(), 0, FreeBuffer );
}
if (!NT_SUCCESS( Status )) {
BaseSetLastNTError( Status );
return( 0 );
}
else {
return( ReturnValue );
}
}