528 lines
12 KiB
C
528 lines
12 KiB
C
|
/*++
|
||
|
|
||
|
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 );
|
||
|
}
|
||
|
}
|