|
|
/*++
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 ); } }
|