-/* $Id$
- *
+/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: lib/kernel32/misc/atom.c
* PURPOSE: Atom functions
- * PROGRAMMER: Eric Kohl ( ariadne@xs4all.nl)
- * UPDATE HISTORY:
- * Created 01/11/98
- * Full rewrite 27/05/2001
+ * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
*/
+/* INCLUDES ******************************************************************/
#include <k32.h>
#define NDEBUG
#include "../include/debug.h"
-
/* GLOBALS *******************************************************************/
-static PRTL_ATOM_TABLE LocalAtomTable = NULL;
+PRTL_ATOM_TABLE BaseLocalAtomTable = NULL;
-static PRTL_ATOM_TABLE GetLocalAtomTable(VOID);
+/* FUNCTIONS *****************************************************************/
+PVOID
+WINAPI
+InternalInitAtomTable(VOID)
+{
+ /* Create or return the local table */
+ if (!BaseLocalAtomTable) RtlCreateAtomTable(0, &BaseLocalAtomTable);
+ return BaseLocalAtomTable;
+}
+
+ATOM
+WINAPI
+InternalAddAtom(BOOLEAN Local,
+ BOOLEAN Unicode,
+ LPCSTR AtomName)
+{
+ NTSTATUS Status;
+ ANSI_STRING AnsiString;
+ UNICODE_STRING UnicodeString;
+ PUNICODE_STRING AtomNameString;
+ ATOM Atom = INVALID_ATOM;
+
+ /* Check if it's an integer atom */
+ if ((ULONG_PTR)AtomName <= 0xFFFF)
+ {
+ /* Convert the name to an atom */
+ Atom = (ATOM)PtrToShort((PVOID)AtomName);
+ if (Atom >= MAXINTATOM)
+ {
+ /* Fail, atom number too large */
+ SetLastErrorByStatus(STATUS_INVALID_PARAMETER);
+ return INVALID_ATOM;
+ }
+
+ /* Return it */
+ return Atom;
+ }
+ else
+ {
+ /* Check if this is a unicode atom */
+ if (Unicode)
+ {
+ /* Use a unicode string */
+ AtomNameString = &UnicodeString;
+ RtlInitUnicodeString(AtomNameString, (LPWSTR)AtomName);
+ Status = STATUS_SUCCESS;
+ }
+ else
+ {
+ /* Use an ansi string */
+ RtlInitAnsiString(&AnsiString, AtomName );
+
+ /* Check if we can abuse the TEB */
+ if (AnsiString.MaximumLength > 260)
+ {
+ /* We can't, allocate a new string */
+ AtomNameString = &UnicodeString;
+ Status = RtlAnsiStringToUnicodeString(AtomNameString,
+ &AnsiString,
+ TRUE);
+ }
+ else
+ {
+ /* We can! Use the TEB */
+ AtomNameString = &NtCurrentTeb()->StaticUnicodeString;
+ Status = RtlAnsiStringToUnicodeString(AtomNameString,
+ &AnsiString,
+ FALSE);
+ }
+ }
+
+ /* Check for failure */
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastErrorByStatus(Status);
+ return Atom;
+ }
+ }
+
+ /* Check if we're doing local add */
+ if (Local)
+ {
+ /* Do a local add */
+ Status = RtlAddAtomToAtomTable(InternalInitAtomTable(),
+ AtomNameString->Buffer,
+ &Atom);
+ }
+ else
+ {
+ /* Do a global add */
+ Status = NtAddAtom(AtomNameString->Buffer,
+ AtomNameString->Length,
+ &Atom);
+ }
+
+ /* Check for failure */
+ if (!NT_SUCCESS(Status)) SetLastErrorByStatus(Status);
+
+ /* Check if we were non-static ANSI */
+ if (!(Unicode) && (AtomNameString == &UnicodeString))
+ {
+ /* Free the allocated buffer */
+ RtlFreeUnicodeString(AtomNameString);
+ }
+
+ /* Return the atom */
+ return Atom;
+}
+
+ATOM
+WINAPI
+InternalFindAtom(BOOLEAN Local,
+ BOOLEAN Unicode,
+ LPCSTR AtomName)
+{
+ NTSTATUS Status;
+ ANSI_STRING AnsiString;
+ UNICODE_STRING UnicodeString;
+ PUNICODE_STRING AtomNameString;
+ ATOM Atom = INVALID_ATOM;
+
+ /* Check if it's an integer atom */
+ if ((ULONG_PTR)AtomName <= 0xFFFF)
+ {
+ /* Convert the name to an atom */
+ Atom = (ATOM)PtrToShort((PVOID)AtomName);
+ if (Atom >= MAXINTATOM)
+ {
+ /* Fail, atom number too large */
+ SetLastErrorByStatus(STATUS_INVALID_PARAMETER);
+ DPRINT1("Invalid atom\n");
+ }
+
+ /* Return it */
+ return Atom;
+ }
+ else
+ {
+ /* Check if this is a unicode atom */
+ if (Unicode)
+ {
+ /* Use a unicode string */
+ AtomNameString = &UnicodeString;
+ RtlInitUnicodeString(AtomNameString, (LPWSTR)AtomName);
+ Status = STATUS_SUCCESS;
+ }
+ else
+ {
+ /* Use an ansi string */
+ RtlInitAnsiString(&AnsiString, AtomName);
+
+ /* Check if we can abuse the TEB */
+ if (AnsiString.MaximumLength > 260)
+ {
+ /* We can't, allocate a new string */
+ AtomNameString = &UnicodeString;
+ Status = RtlAnsiStringToUnicodeString(AtomNameString,
+ &AnsiString,
+ TRUE);
+ }
+ else
+ {
+ /* We can! Use the TEB */
+ AtomNameString = &NtCurrentTeb()->StaticUnicodeString;
+ Status = RtlAnsiStringToUnicodeString(AtomNameString,
+ &AnsiString,
+ FALSE);
+ }
+ }
+
+ /* Check for failure */
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed\n");
+ SetLastErrorByStatus(Status);
+ return Atom;
+ }
+ }
+
+ /* Check if we're doing local lookup */
+ if (Local)
+ {
+ /* Do a local lookup */
+ Status = RtlLookupAtomInAtomTable(InternalInitAtomTable(),
+ AtomNameString->Buffer,
+ &Atom);
+ }
+ else
+ {
+ /* Do a global search */
+ if (!AtomNameString->Length)
+ {
+ /* This is illegal in win32 */
+ DPRINT1("No name given\n");
+ Status = STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+ else
+ {
+ /* Call the global function */
+ Status = NtFindAtom(AtomNameString->Buffer,
+ AtomNameString->Length,
+ &Atom);
+ }
+ }
+
+ /* Check for failure */
+ if (!NT_SUCCESS(Status)) SetLastErrorByStatus(Status);
+
+ /* Check if we were non-static ANSI */
+ if (!(Unicode) && (AtomNameString == &UnicodeString))
+ {
+ /* Free the allocated buffer */
+ RtlFreeUnicodeString(AtomNameString);
+ }
+
+ /* Return the atom */
+ return Atom;
+}
+
+ATOM
+WINAPI
+InternalDeleteAtom(BOOLEAN Local,
+ ATOM Atom)
+{
+ NTSTATUS Status;
+
+ /* Validate it */
+ if (Atom >= MAXINTATOM)
+ {
+ /* Check if it's a local delete */
+ if (Local)
+ {
+ /* Delete it locally */
+ Status = RtlDeleteAtomFromAtomTable(InternalInitAtomTable(), Atom);
+ }
+ else
+ {
+ /* Delete it globall */
+ Status = NtDeleteAtom(Atom);
+ }
+
+ /* Check for success */
+ if (!NT_SUCCESS(Status))
+ {
+ /* Fail */
+ SetLastErrorByStatus(Status);
+ return INVALID_ATOM;
+ }
+ }
+
+ /* Return failure */
+ return 0;
+}
+
+UINT
+WINAPI
+InternalGetAtomName(BOOLEAN Local,
+ BOOLEAN Unicode,
+ ATOM Atom,
+ LPSTR AtomName,
+ DWORD Size)
+{
+ NTSTATUS Status;
+ DWORD RetVal = 0;
+ ANSI_STRING AnsiString;
+ UNICODE_STRING UnicodeString;
+ PVOID TempBuffer = NULL;
+ PWSTR AtomNameString;
+ ULONG AtomInfoLength;
+ ULONG AtomNameLength;
+ PATOM_BASIC_INFORMATION AtomInfo;
+
+ /* Normalize the size as not to overflow */
+ if (!Unicode && Size > 0x7000) Size = 0x7000;
+
+ /* Make sure it's valid too */
+ if (!Size)
+ {
+ SetLastErrorByStatus(STATUS_BUFFER_OVERFLOW);
+ return 0;
+ }
+
+ /* Check if this is a global query */
+ if (Local)
+ {
+ /* Set the query length */
+ AtomNameLength = Size * sizeof(WCHAR);
+
+ /* If it's unicode, just keep the name */
+ if (Unicode)
+ {
+ AtomNameString = (PWSTR)AtomName;
+ }
+ else
+ {
+ /* Allocate memory for the ansi buffer */
+ TempBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
+ 0,
+ AtomNameLength);
+ AtomNameString = TempBuffer;
+ }
+
+ /* Query the name */
+ Status = RtlQueryAtomInAtomTable(InternalInitAtomTable(),
+ Atom,
+ NULL,
+ NULL,
+ AtomNameString,
+ &AtomNameLength);
+ }
+ else
+ {
+ /* We're going to do a global query, so allocate a buffer */
+ AtomInfoLength = sizeof(ATOM_BASIC_INFORMATION) +
+ (Size * sizeof(WCHAR));
+ AtomInfo = TempBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
+ 0,
+ AtomInfoLength);
+
+ /* Query the name */
+ Status = NtQueryInformationAtom(Atom,
+ AtomBasicInformation,
+ AtomInfo,
+ AtomInfoLength,
+ &AtomInfoLength);
+ if (NT_SUCCESS(Status))
+ {
+ /* Success. Update the length and get the name */
+ AtomNameLength = (ULONG)AtomInfo->NameLength;
+ AtomNameString = AtomInfo->Name;
+ }
+ }
+
+ /* Check for global success */
+ if (NT_SUCCESS(Status))
+ {
+ /* Check if it was unicode */
+ if (Unicode)
+ {
+ /* We return the length in chars */
+ RetVal = AtomNameLength / sizeof(WCHAR);
+
+ /* Copy the memory if this was a global query */
+ if (AtomNameString != (PWSTR)AtomName)
+ {
+ RtlMoveMemory(AtomName, AtomNameString, AtomNameLength);
+ }
+
+ /* And null-terminate it if the buffer was too large */
+ if (RetVal < Size)
+ {
+ ((PWCHAR)AtomName)[RetVal] = UNICODE_NULL;
+ }
+ }
+ else
+ {
+ /* First create a unicode string with our data */
+ UnicodeString.Buffer = AtomNameString;
+ UnicodeString.Length = (USHORT)AtomNameLength;
+ UnicodeString.MaximumLength = (USHORT)(UnicodeString.Length +
+ sizeof(WCHAR));
+
+ /* Now prepare an ansi string for conversion */
+ AnsiString.Buffer = AtomName;
+ AnsiString.Length = 0;
+ AnsiString.MaximumLength = (USHORT)Size;
+
+ /* Convert it */
+ Status = RtlUnicodeStringToAnsiString(&AnsiString,
+ &UnicodeString,
+ FALSE);
+
+ /* Return the length */
+ if (NT_SUCCESS(Status)) RetVal = AnsiString.Length;
+ }
+ }
+
+ /* Free the temporary buffer if we have one */
+ if (TempBuffer) RtlFreeHeap(RtlGetProcessHeap(), 0, TempBuffer);
+
+ /* Check for failure */
+ if (!NT_SUCCESS(Status))
+ {
+ /* Fail */
+ DPRINT1("Failed: %lx\n", Status);
+ SetLastErrorByStatus(Status);
+ }
+
+ /* Return length */
+ return RetVal;
+}
/* FUNCTIONS *****************************************************************/
/*
* @implemented
*/
-ATOM STDCALL
+ATOM
+WINAPI
GlobalAddAtomA(LPCSTR lpString)
{
- UNICODE_STRING AtomName;
- NTSTATUS Status;
- ATOM Atom;
-
- if (HIWORD((ULONG)lpString) == 0)
- {
- if ((ULONG)lpString >= 0xC000)
- {
- SetLastErrorByStatus(STATUS_INVALID_PARAMETER);
- return (ATOM)0;
- }
- return (ATOM)LOWORD((ULONG)lpString);
- }
-
- if (lstrlenA(lpString) > 255)
- {
- /* This limit does not exist with NtAddAtom so the limit is probably
- * added for compability. -Gunnar
- */
- SetLastError(ERROR_INVALID_PARAMETER);
- return (ATOM)0;
- }
-
- RtlCreateUnicodeStringFromAsciiz(&AtomName,
- (LPSTR)lpString);
-
- Status = NtAddAtom(AtomName.Buffer,
- AtomName.Length,
- &Atom);
- RtlFreeUnicodeString(&AtomName);
- if (!NT_SUCCESS(Status))
- {
- SetLastErrorByStatus(Status);
- return (ATOM)0;
- }
-
- return Atom;
+ return InternalAddAtom(FALSE, FALSE, lpString);
}
-
/*
* @implemented
*/
-ATOM STDCALL
+ATOM
+WINAPI
GlobalAddAtomW(LPCWSTR lpString)
{
- ATOM Atom;
- NTSTATUS Status;
-
- if (HIWORD((ULONG)lpString) == 0)
- {
- if ((ULONG)lpString >= 0xC000)
- {
- SetLastErrorByStatus(STATUS_INVALID_PARAMETER);
- return (ATOM)0;
- }
- return (ATOM)LOWORD((ULONG)lpString);
- }
-
- if (lstrlenW(lpString) > 255)
- {
- /* This limit does not exist with NtAddAtom so the limit is probably
- * added for compability. -Gunnar
- */
- SetLastError(ERROR_INVALID_PARAMETER);
- return (ATOM)0;
- }
-
- Status = NtAddAtom((LPWSTR)lpString,
- wcslen(lpString),
- &Atom);
- if (!NT_SUCCESS(Status))
- {
- SetLastErrorByStatus(Status);
- return (ATOM)0;
- }
-
- return Atom;
+ return InternalAddAtom(FALSE, TRUE, (LPSTR)lpString);
}
-
/*
* @implemented
*/
-ATOM STDCALL
+ATOM
+WINAPI
GlobalDeleteAtom(ATOM nAtom)
{
- NTSTATUS Status;
-
- if (nAtom < 0xC000)
- {
- return 0;
- }
-
- Status = NtDeleteAtom(nAtom);
- if (!NT_SUCCESS(Status))
- {
- SetLastErrorByStatus(Status);
- return nAtom;
- }
-
- return 0;
+ return InternalDeleteAtom(FALSE, nAtom);
}
-
/*
* @implemented
*/
-ATOM STDCALL
+ATOM
+WINAPI
GlobalFindAtomA(LPCSTR lpString)
{
- UNICODE_STRING AtomName;
- NTSTATUS Status;
- ATOM Atom;
-
- if (HIWORD((ULONG)lpString) == 0)
- {
- if ((ULONG)lpString >= 0xC000)
- {
- SetLastErrorByStatus(STATUS_INVALID_PARAMETER);
- return (ATOM)0;
- }
- return (ATOM)LOWORD((ULONG)lpString);
- }
-
- if (lstrlenA(lpString) > 255)
- {
- /* This limit does not exist with NtAddAtom so the limit is probably
- * added for compability. -Gunnar
- */
- SetLastError(ERROR_INVALID_PARAMETER);
- return (ATOM)0;
- }
-
- RtlCreateUnicodeStringFromAsciiz(&AtomName,
- (LPSTR)lpString);
- Status = NtFindAtom(AtomName.Buffer,
- AtomName.Length,
- &Atom);
- RtlFreeUnicodeString(&AtomName);
- if (!NT_SUCCESS(Status))
- {
- SetLastErrorByStatus(Status);
- return (ATOM)0;
- }
-
- return Atom;
+ return InternalFindAtom(FALSE, FALSE, lpString);
}
-
/*
* @implemented
*/
-ATOM STDCALL
+ATOM
+WINAPI
GlobalFindAtomW(LPCWSTR lpString)
{
- ATOM Atom;
- NTSTATUS Status;
-
- if (HIWORD((ULONG)lpString) == 0)
- {
- if ((ULONG)lpString >= 0xC000)
- {
- SetLastErrorByStatus(STATUS_INVALID_PARAMETER);
- return (ATOM)0;
- }
- return (ATOM)LOWORD((ULONG)lpString);
- }
-
- if (lstrlenW(lpString) > 255)
- {
- /* This limit does not exist with NtAddAtom so the limit is probably
- * added for compability. -Gunnar
- */
- SetLastError(ERROR_INVALID_PARAMETER);
- return (ATOM)0;
- }
-
- Status = NtFindAtom((LPWSTR)lpString,
- wcslen(lpString),
- &Atom);
- if (!NT_SUCCESS(Status))
- {
- SetLastErrorByStatus(Status);
- return (ATOM)0;
- }
-
- return Atom;
+ return InternalFindAtom(FALSE, TRUE, (LPSTR)lpString);
}
-
-UINT STDCALL
+/*
+ * @implemented
+ */
+UINT
+WINAPI
GlobalGetAtomNameA(ATOM nAtom,
- LPSTR lpBuffer,
- int nSize)
+ LPSTR lpBuffer,
+ int nSize)
{
- PATOM_BASIC_INFORMATION Buffer;
- UNICODE_STRING AtomNameU;
- ANSI_STRING AtomName;
- ULONG BufferSize;
- ULONG ReturnLength;
- NTSTATUS Status;
-
- BufferSize = sizeof(ATOM_BASIC_INFORMATION) + nSize * sizeof(WCHAR);
- Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
- HEAP_ZERO_MEMORY,
- BufferSize);
- if (Buffer == NULL)
- {
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- return 0;
- }
-
- Status = NtQueryInformationAtom(nAtom,
- AtomBasicInformation,
- Buffer,
- BufferSize,
- &ReturnLength);
- if (!NT_SUCCESS(Status))
- {
- RtlFreeHeap(RtlGetProcessHeap(),
- 0,
- Buffer);
- SetLastErrorByStatus(Status);
- return 0;
- }
-
- RtlInitUnicodeString(&AtomNameU,
- Buffer->Name);
- AtomName.Buffer = lpBuffer;
- AtomName.Length = 0;
- AtomName.MaximumLength = nSize;
- RtlUnicodeStringToAnsiString(&AtomName,
- &AtomNameU,
- FALSE);
-
- ReturnLength = AtomName.Length;
- RtlFreeHeap(RtlGetProcessHeap(),
- 0,
- Buffer);
-
- return ReturnLength;
+ return InternalGetAtomName(FALSE, FALSE, nAtom, lpBuffer, (DWORD)nSize);
}
-
/*
* @implemented
*/
-UINT STDCALL
+UINT
+WINAPI
GlobalGetAtomNameW(ATOM nAtom,
- LPWSTR lpBuffer,
- int nSize)
-{
- PATOM_BASIC_INFORMATION Buffer;
- ULONG BufferSize;
- ULONG ReturnLength;
- NTSTATUS Status;
-
- BufferSize = sizeof(ATOM_BASIC_INFORMATION) + nSize * sizeof(WCHAR);
- Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
- HEAP_ZERO_MEMORY,
- BufferSize);
- if (Buffer == NULL)
- {
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- return 0;
- }
-
- Status = NtQueryInformationAtom(nAtom,
- AtomBasicInformation,
- Buffer,
- BufferSize,
- &ReturnLength);
- if (!NT_SUCCESS(Status))
- {
- RtlFreeHeap(RtlGetProcessHeap(),
- 0,
- Buffer);
- SetLastErrorByStatus(Status);
- return 0;
- }
-
- memcpy(lpBuffer, Buffer->Name, Buffer->NameLength);
- ReturnLength = Buffer->NameLength / sizeof(WCHAR);
- *(lpBuffer + ReturnLength) = 0;
- RtlFreeHeap(RtlGetProcessHeap(),
- 0,
- Buffer);
-
- return ReturnLength;
-}
-
-
-static PRTL_ATOM_TABLE
-GetLocalAtomTable(VOID)
+ LPWSTR lpBuffer,
+ int nSize)
{
- if (LocalAtomTable != NULL)
- {
- return LocalAtomTable;
- }
- RtlCreateAtomTable(37,
- &LocalAtomTable);
- return LocalAtomTable;
+ return InternalGetAtomName(FALSE,
+ TRUE,
+ nAtom,
+ (LPSTR)lpBuffer,
+ (DWORD)nSize);
}
-
/*
* @implemented
*/
-BOOL STDCALL
+BOOL
+WINAPI
InitAtomTable(DWORD nSize)
{
- NTSTATUS Status;
+ /* Normalize size */
+ if (nSize < 4 || nSize > 511) nSize = 37;
- /* nSize should be a prime number */
-
- if ( nSize < 4 || nSize >= 512 )
- {
- nSize = 37;
- }
-
- if (LocalAtomTable == NULL)
- {
- Status = RtlCreateAtomTable(nSize,
- &LocalAtomTable);
- if (!NT_SUCCESS(Status))
- {
- SetLastErrorByStatus(Status);
- return FALSE;
- }
- }
-
- return TRUE;
+ DPRINT("Here\n");
+ return NT_SUCCESS(RtlCreateAtomTable(nSize, &BaseLocalAtomTable));
}
-
/*
* @implemented
*/
-ATOM STDCALL
+ATOM
+WINAPI
AddAtomA(LPCSTR lpString)
{
- PRTL_ATOM_TABLE AtomTable;
- UNICODE_STRING AtomName;
- NTSTATUS Status;
- ATOM Atom;
-
- if (HIWORD((ULONG)lpString) == 0)
- {
- if ((ULONG)lpString >= 0xC000)
- {
- SetLastErrorByStatus(STATUS_INVALID_PARAMETER);
- return (ATOM)0;
- }
- return (ATOM)LOWORD((ULONG)lpString);
- }
-
- AtomTable = GetLocalAtomTable();
-
- RtlCreateUnicodeStringFromAsciiz(&AtomName,
- (LPSTR)lpString);
-
- Status = RtlAddAtomToAtomTable(AtomTable,
- AtomName.Buffer,
- &Atom);
- RtlFreeUnicodeString(&AtomName);
- if (!NT_SUCCESS(Status))
- {
- SetLastErrorByStatus(Status);
- return (ATOM)0;
- }
-
- return Atom;
+ return InternalAddAtom(TRUE, FALSE, lpString);
}
-
/*
* @implemented
*/
-ATOM STDCALL
+ATOM
+WINAPI
AddAtomW(LPCWSTR lpString)
{
- PRTL_ATOM_TABLE AtomTable;
- ATOM Atom;
- NTSTATUS Status;
-
- if (HIWORD((ULONG)lpString) == 0)
- {
- if ((ULONG)lpString >= 0xC000)
- {
- SetLastErrorByStatus(STATUS_INVALID_PARAMETER);
- return (ATOM)0;
- }
- return (ATOM)LOWORD((ULONG)lpString);
- }
-
- AtomTable = GetLocalAtomTable();
-
- Status = RtlAddAtomToAtomTable(AtomTable,
- (LPWSTR)lpString,
- &Atom);
- if (!NT_SUCCESS(Status))
- {
- SetLastErrorByStatus(Status);
- return (ATOM)0;
- }
-
- return Atom;
+ return InternalAddAtom(TRUE, TRUE, (LPSTR)lpString);
}
-
/*
* @implemented
*/
-ATOM STDCALL
+ATOM
+WINAPI
DeleteAtom(ATOM nAtom)
{
- PRTL_ATOM_TABLE AtomTable;
- NTSTATUS Status;
-
- if (nAtom < 0xC000)
- {
- return 0;
- }
-
- AtomTable = GetLocalAtomTable();
-
- Status = RtlDeleteAtomFromAtomTable(AtomTable,
- nAtom);
- if (!NT_SUCCESS(Status))
- {
- SetLastErrorByStatus(Status);
- return nAtom;
- }
-
- return 0;
+ return InternalDeleteAtom(TRUE, nAtom);
}
-
/*
* @implemented
*/
-ATOM STDCALL
+ATOM
+WINAPI
FindAtomA(LPCSTR lpString)
{
- PRTL_ATOM_TABLE AtomTable;
- UNICODE_STRING AtomName;
- NTSTATUS Status;
- ATOM Atom;
-
- if (HIWORD((ULONG)lpString) == 0)
- {
- if ((ULONG)lpString >= 0xC000)
- {
- SetLastErrorByStatus(STATUS_INVALID_PARAMETER);
- return (ATOM)0;
- }
- return (ATOM)LOWORD((ULONG)lpString);
- }
-
- AtomTable = GetLocalAtomTable();
- RtlCreateUnicodeStringFromAsciiz(&AtomName,
- (LPSTR)lpString);
- Status = RtlLookupAtomInAtomTable(AtomTable,
- AtomName.Buffer,
- &Atom);
- RtlFreeUnicodeString(&AtomName);
- if (!NT_SUCCESS(Status))
- {
- SetLastErrorByStatus(Status);
- return (ATOM)0;
- }
-
- return Atom;
+ return InternalFindAtom(TRUE, FALSE, lpString);
}
-
/*
* @implemented
*/
-ATOM STDCALL
+ATOM
+WINAPI
FindAtomW(LPCWSTR lpString)
{
- PRTL_ATOM_TABLE AtomTable;
- ATOM Atom;
- NTSTATUS Status;
-
- if (HIWORD((ULONG)lpString) == 0)
- {
- if ((ULONG)lpString >= 0xC000)
- {
- SetLastErrorByStatus(STATUS_INVALID_PARAMETER);
- return (ATOM)0;
- }
- return (ATOM)LOWORD((ULONG)lpString);
- }
-
- AtomTable = GetLocalAtomTable();
-
- Status = RtlLookupAtomInAtomTable(AtomTable,
- (LPWSTR)lpString,
- &Atom);
- if (!NT_SUCCESS(Status))
- {
- SetLastErrorByStatus(Status);
- return (ATOM)0;
- }
-
- return Atom;
-}
+ return InternalFindAtom(TRUE, TRUE, (LPSTR)lpString);
+}
/*
* @implemented
*/
-UINT STDCALL
+UINT
+WINAPI
GetAtomNameA(ATOM nAtom,
- LPSTR lpBuffer,
- int nSize)
+ LPSTR lpBuffer,
+ int nSize)
{
- PRTL_ATOM_TABLE AtomTable;
- PWCHAR Buffer;
- UNICODE_STRING AtomNameU;
- ANSI_STRING AtomName;
- ULONG NameLength;
- NTSTATUS Status;
-
- AtomTable = GetLocalAtomTable();
-
- NameLength = nSize * sizeof(WCHAR);
- Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
- HEAP_ZERO_MEMORY,
- NameLength);
- if (Buffer == NULL)
- {
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- return 0;
- }
-
- Status = RtlQueryAtomInAtomTable(AtomTable,
- nAtom,
- NULL,
- NULL,
- Buffer,
- &NameLength);
- if (!NT_SUCCESS(Status))
- {
- RtlFreeHeap(RtlGetProcessHeap(),
- 0,
- Buffer);
- SetLastErrorByStatus(Status);
- return 0;
- }
-
- RtlInitUnicodeString(&AtomNameU,
- Buffer);
- AtomName.Buffer = lpBuffer;
- AtomName.Length = 0;
- AtomName.MaximumLength = nSize;
- RtlUnicodeStringToAnsiString(&AtomName,
- &AtomNameU,
- FALSE);
-
- NameLength = AtomName.Length;
- RtlFreeHeap(RtlGetProcessHeap(),
- 0,
- Buffer);
-
- return NameLength;
+ return InternalGetAtomName(TRUE, FALSE, nAtom, lpBuffer, (DWORD)nSize);
}
-
/*
* @implemented
*/
-UINT STDCALL
+UINT
+WINAPI
GetAtomNameW(ATOM nAtom,
- LPWSTR lpBuffer,
- int nSize)
+ LPWSTR lpBuffer,
+ int nSize)
{
- PRTL_ATOM_TABLE AtomTable;
- ULONG NameLength;
- NTSTATUS Status;
-
- AtomTable = GetLocalAtomTable();
-
- NameLength = nSize * sizeof(WCHAR);
- Status = RtlQueryAtomInAtomTable(AtomTable,
- nAtom,
- NULL,
- NULL,
- lpBuffer,
- &NameLength);
- if (!NT_SUCCESS(Status))
- {
- return 0;
- }
-
- return(NameLength / sizeof(WCHAR));
+ return InternalGetAtomName(TRUE,
+ TRUE,
+ nAtom,
+ (LPSTR)lpBuffer,
+ (DWORD)nSize);
}
-
/* EOF */
#define NDEBUG\r
#include <internal/debug.h>\r
\r
+#define TAG_ATOM TAG('A', 't', 'o', 'm')\r
+\r
/* GLOBALS ****************************************************************/\r
\r
/* \r
return GlobalAtomTable;\r
}\r
\r
-NTSTATUS\r
-NTAPI\r
-RtlpQueryAtomInformation(PRTL_ATOM_TABLE AtomTable,\r
- RTL_ATOM Atom,\r
- PATOM_BASIC_INFORMATION AtomInformation,\r
- ULONG AtomInformationLength,\r
- PULONG ReturnLength)\r
-{\r
- NTSTATUS Status;\r
- ULONG UsageCount;\r
- ULONG Flags;\r
- ULONG NameLength;\r
-\r
- NameLength = AtomInformationLength - sizeof(ATOM_BASIC_INFORMATION) + sizeof(WCHAR);\r
- Status = RtlQueryAtomInAtomTable(AtomTable,\r
- Atom,\r
- &UsageCount,\r
- &Flags,\r
- AtomInformation->Name,\r
- &NameLength);\r
-\r
- if (!NT_SUCCESS(Status)) return Status;\r
- DPRINT("NameLength: %lu\n", NameLength);\r
-\r
- if (ReturnLength != NULL)\r
- {\r
- *ReturnLength = NameLength + sizeof(ATOM_BASIC_INFORMATION);\r
- }\r
-\r
- if (NameLength + sizeof(ATOM_BASIC_INFORMATION) > AtomInformationLength)\r
- {\r
- return STATUS_INFO_LENGTH_MISMATCH;\r
- }\r
-\r
- AtomInformation->UsageCount = (USHORT)UsageCount;\r
- AtomInformation->Flags = (USHORT)Flags;\r
- AtomInformation->NameLength = (USHORT)NameLength;\r
-\r
- return STATUS_SUCCESS;\r
-}\r
-\r
-NTSTATUS\r
-NTAPI\r
-RtlpQueryAtomTableInformation(PRTL_ATOM_TABLE AtomTable,\r
- RTL_ATOM Atom,\r
- PATOM_TABLE_INFORMATION AtomInformation,\r
- ULONG AtomInformationLength,\r
- PULONG ReturnLength)\r
-{\r
- ULONG Length;\r
- NTSTATUS Status;\r
-\r
- Length = sizeof(ATOM_TABLE_INFORMATION);\r
- DPRINT("RequiredLength: %lu\n", Length);\r
-\r
- if (ReturnLength) *ReturnLength = Length;\r
-\r
- if (Length > AtomInformationLength) return STATUS_INFO_LENGTH_MISMATCH;\r
-\r
- Status = RtlQueryAtomListInAtomTable(AtomTable,\r
- (AtomInformationLength - Length) /\r
- sizeof(RTL_ATOM),\r
- &AtomInformation->NumberOfAtoms,\r
- AtomInformation->Atoms);\r
- if (NT_SUCCESS(Status))\r
- {\r
- ReturnLength += AtomInformation->NumberOfAtoms * sizeof(RTL_ATOM);\r
- if (ReturnLength != NULL) *ReturnLength = Length;\r
- }\r
-\r
- return Status;\r
-}\r
-\r
/* FUNCTIONS ****************************************************************/\r
\r
/*\r
OUT PRTL_ATOM Atom)\r
{\r
PRTL_ATOM_TABLE AtomTable = ExpGetGlobalAtomTable();\r
+ NTSTATUS Status = STATUS_SUCCESS;\r
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();\r
+ LPWSTR CapturedName = NULL;\r
+ ULONG CapturedSize;\r
+ RTL_ATOM SafeAtom;\r
+ PAGED_CODE();\r
\r
/* Check for the table */\r
if (AtomTable == NULL) return STATUS_ACCESS_DENIED;\r
\r
- /* FIXME: SEH! */\r
+ /* Check for valid name */\r
+ if (AtomNameLength > (RTL_MAXIMUM_ATOM_LENGTH * sizeof(WCHAR)))\r
+ {\r
+ /* Fail */\r
+ DPRINT1("Atom name too long\n");\r
+ return STATUS_INVALID_PARAMETER;\r
+ }\r
\r
- /* Call the worker function */\r
- return RtlAddAtomToAtomTable(AtomTable, AtomName, Atom);\r
+ /* Check if we're called from user-mode*/\r
+ if (PreviousMode != KernelMode)\r
+ {\r
+ /* Enter SEH */\r
+ _SEH_TRY\r
+ {\r
+ /* Check if we have a name */\r
+ if (AtomName)\r
+ {\r
+ /* Probe the atom */\r
+ ProbeForRead(AtomName, AtomNameLength, sizeof(WCHAR));\r
+\r
+ /* Allocate an aligned buffer + the null char */\r
+ CapturedSize = ((AtomNameLength + sizeof(WCHAR)) &~\r
+ (sizeof(WCHAR) -1));\r
+ CapturedName = ExAllocatePoolWithTag(PagedPool,\r
+ CapturedSize,\r
+ TAG_ATOM);\r
+ if (!CapturedName)\r
+ {\r
+ /* Fail the call */\r
+ Status = STATUS_INSUFFICIENT_RESOURCES;\r
+ }\r
+ else\r
+ {\r
+ /* Copy the name and null-terminate it */\r
+ RtlMoveMemory(CapturedName, AtomName, AtomNameLength);\r
+ CapturedName[AtomNameLength / sizeof(WCHAR)] = UNICODE_NULL;\r
+ }\r
+\r
+ /* Probe the atom too */\r
+ if (Atom) ProbeForWriteUshort(Atom);\r
+ }\r
+ }\r
+ _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)\r
+ {\r
+ Status = _SEH_GetExceptionCode();\r
+ }\r
+ _SEH_END;\r
+ }\r
+ else\r
+ {\r
+ /* Simplify code and re-use one variable */\r
+ if (AtomName) CapturedName = AtomName;\r
+ }\r
+\r
+ /* Make sure probe worked */\r
+ if (NT_SUCCESS(Status))\r
+ {\r
+ /* Call the runtime function */\r
+ Status = RtlAddAtomToAtomTable(AtomTable, CapturedName, &SafeAtom);\r
+ if (NT_SUCCESS(Status) && (Atom))\r
+ {\r
+ /* Success and caller wants the atom back.. .enter SEH */\r
+ _SEH_TRY\r
+ {\r
+ /* Return the atom */\r
+ *Atom = SafeAtom;\r
+ }\r
+ _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)\r
+ {\r
+ Status = _SEH_GetExceptionCode();\r
+ }\r
+ _SEH_END;\r
+ }\r
+ }\r
+\r
+ /* If we captured anything, free it */\r
+ if ((CapturedName) && (CapturedName != AtomName)) ExFreePool(CapturedName);\r
+\r
+ /* Return to caller */\r
+ return Status;\r
}\r
\r
/*\r
NtDeleteAtom(IN RTL_ATOM Atom)\r
{\r
PRTL_ATOM_TABLE AtomTable = ExpGetGlobalAtomTable();\r
+ PAGED_CODE();\r
\r
/* Check for valid table */\r
if (AtomTable == NULL) return STATUS_ACCESS_DENIED;\r
OUT PRTL_ATOM Atom)\r
{\r
PRTL_ATOM_TABLE AtomTable = ExpGetGlobalAtomTable();\r
+ NTSTATUS Status = STATUS_SUCCESS;\r
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();\r
+ LPWSTR CapturedName = NULL;\r
+ ULONG CapturedSize;\r
+ RTL_ATOM SafeAtom;\r
+ PAGED_CODE();\r
\r
- /* Check for valid table */\r
+ /* Check for the table */\r
if (AtomTable == NULL) return STATUS_ACCESS_DENIED;\r
\r
- /* FIXME: SEH!!! */\r
+ /* Check for valid name */\r
+ if (AtomNameLength > (RTL_MAXIMUM_ATOM_LENGTH * sizeof(WCHAR)))\r
+ {\r
+ /* Fail */\r
+ DPRINT1("Atom name too long\n");\r
+ return STATUS_INVALID_PARAMETER;\r
+ }\r
+\r
+ /* Check if we're called from user-mode*/\r
+ if (PreviousMode != KernelMode)\r
+ {\r
+ /* Enter SEH */\r
+ _SEH_TRY\r
+ {\r
+ /* Check if we have a name */\r
+ if (AtomName)\r
+ {\r
+ /* Probe the atom */\r
+ ProbeForRead(AtomName, AtomNameLength, sizeof(WCHAR));\r
+\r
+ /* Allocate an aligned buffer + the null char */\r
+ CapturedSize = ((AtomNameLength + sizeof(WCHAR)) &~\r
+ (sizeof(WCHAR) -1));\r
+ CapturedName = ExAllocatePoolWithTag(PagedPool,\r
+ CapturedSize,\r
+ TAG_ATOM);\r
+ if (!CapturedName)\r
+ {\r
+ /* Fail the call */\r
+ Status = STATUS_INSUFFICIENT_RESOURCES;\r
+ }\r
+ else\r
+ {\r
+ /* Copy the name and null-terminate it */\r
+ RtlMoveMemory(CapturedName, AtomName, AtomNameLength);\r
+ CapturedName[AtomNameLength / sizeof(WCHAR)] = UNICODE_NULL;\r
+ }\r
+\r
+ /* Probe the atom too */\r
+ if (Atom) ProbeForWriteUshort(Atom);\r
+ }\r
+ }\r
+ _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)\r
+ {\r
+ Status = _SEH_GetExceptionCode();\r
+ }\r
+ _SEH_END;\r
+ }\r
+ else\r
+ {\r
+ /* Simplify code and re-use one variable */\r
+ if (AtomName) CapturedName = AtomName;\r
+ }\r
\r
- /* Call worker function */\r
- return RtlLookupAtomInAtomTable(AtomTable, AtomName, Atom);\r
+ /* Make sure probe worked */\r
+ if (NT_SUCCESS(Status))\r
+ {\r
+ /* Call the runtime function */\r
+ Status = RtlLookupAtomInAtomTable(AtomTable, CapturedName, &SafeAtom);\r
+ if (NT_SUCCESS(Status) && (Atom))\r
+ {\r
+ /* Success and caller wants the atom back.. .enter SEH */\r
+ _SEH_TRY\r
+ {\r
+ /* Return the atom */\r
+ *Atom = SafeAtom;\r
+ }\r
+ _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)\r
+ {\r
+ Status = _SEH_GetExceptionCode();\r
+ }\r
+ _SEH_END;\r
+ }\r
+ }\r
+\r
+ /* If we captured anything, free it */\r
+ if ((CapturedName) && (CapturedName != AtomName)) ExFreePool(CapturedName);\r
+\r
+ /* Return to caller */\r
+ return Status;\r
}\r
\r
/*\r
PULONG ReturnLength)\r
{\r
PRTL_ATOM_TABLE AtomTable = ExpGetGlobalAtomTable();\r
+ PATOM_BASIC_INFORMATION BasicInformation = AtomInformation;\r
+ PATOM_TABLE_INFORMATION TableInformation = AtomInformation;\r
NTSTATUS Status;\r
+ ULONG Flags, UsageCount, NameLength;\r
\r
/* Check for valid table */\r
if (AtomTable == NULL) return STATUS_ACCESS_DENIED;\r
/* Choose class */\r
switch (AtomInformationClass)\r
{\r
+ /* Caller requested info about an atom */\r
case AtomBasicInformation:\r
- Status = RtlpQueryAtomInformation(AtomTable,\r
- Atom,\r
- AtomInformation,\r
- AtomInformationLength,\r
- ReturnLength);\r
+\r
+ /* Size check */\r
+ *ReturnLength = FIELD_OFFSET(ATOM_BASIC_INFORMATION, Name);\r
+ if (*ReturnLength > AtomInformationLength)\r
+ {\r
+ /* Fail */\r
+ DPRINT1("Buffer too small\n");\r
+ return STATUS_INFO_LENGTH_MISMATCH;\r
+ }\r
+\r
+ /* Prepare query */\r
+ UsageCount = 0;\r
+ NameLength = AtomInformationLength - *ReturnLength;\r
+ BasicInformation->Name[0] = UNICODE_NULL;\r
+\r
+ /* Query the data */\r
+ Status = RtlQueryAtomInAtomTable(AtomTable,\r
+ Atom,\r
+ &UsageCount,\r
+ &Flags,\r
+ BasicInformation->Name,\r
+ &NameLength);\r
+ if (NT_SUCCESS(Status))\r
+ {\r
+ /* Return data */\r
+ BasicInformation->UsageCount = (USHORT)UsageCount;\r
+ BasicInformation->Flags = (USHORT)Flags;\r
+ BasicInformation->NameLength = (USHORT)NameLength;\r
+ *ReturnLength += NameLength + sizeof(WCHAR);\r
+ }\r
break;\r
\r
+ /* Caller requested info about an Atom Table */\r
case AtomTableInformation:\r
- Status = RtlpQueryAtomTableInformation(AtomTable,\r
- Atom,\r
- AtomInformation,\r
- AtomInformationLength,\r
- ReturnLength);\r
+\r
+ /* Size check */\r
+ *ReturnLength = FIELD_OFFSET(ATOM_TABLE_INFORMATION, Atoms);\r
+ if (*ReturnLength > AtomInformationLength)\r
+ {\r
+ /* Fail */\r
+ DPRINT1("Buffer too small\n");\r
+ return STATUS_INFO_LENGTH_MISMATCH;\r
+ }\r
+\r
+ /* Query the data */\r
+ Status = RtlQueryAtomListInAtomTable(AtomTable,\r
+ (AtomInformationLength - *ReturnLength) /\r
+ sizeof(RTL_ATOM),\r
+ &TableInformation->NumberOfAtoms,\r
+ TableInformation->Atoms);\r
+ if (NT_SUCCESS(Status))\r
+ {\r
+ /* Update the return length */\r
+ *ReturnLength += TableInformation->NumberOfAtoms *\r
+ sizeof(RTL_ATOM);\r
+ }\r
break;\r
\r
+ /* Caller was on crack */\r
default:\r
+\r
+ /* Unrecognized class */\r
Status = STATUS_INVALID_INFO_CLASS;\r
}\r
\r