[REDUNDANT/ARCHIVAL] Ntdll atom stuff

György 'Nog' Jeney nog at sdf.lonestar.org
Mon Apr 7 07:15:30 CDT 2003


Here's my implementation of the ntdll atom functions I hacked toghether
during
last week, I'm posting it here just incase someone finds use for them some
day.

-------------- next part --------------
--- ../cleanwine/include/winternl.h	2003-04-05 08:33:39.000000000 +0200
+++ include/winternl.h	2003-04-07 12:10:48.000000000 +0200
@@ -764,6 +764,25 @@
 
 typedef BOOLEAN (WINAPI * PWINSTATIONQUERYINFORMATIONW)(HANDLE,ULONG,WINSTATIONINFOCLASS,PVOID,ULONG,PULONG);
 
+typedef struct _ATOM_BASIC_INFORMATION
+{
+    USHORT RefCount;
+    USHORT Pin;
+    USHORT NameLen;
+    WCHAR Name[1];
+} ATOM_BASIC_INFORMATION, *PATOM_BASIC_INFORMATION;
+
+typedef WORD RTL_ATOM;
+typedef WORD *PRTL_ATOM;
+
+typedef PVOID RTL_ATOM_TABLE;
+typedef PVOID *PRTL_ATOM_TABLE;
+
+typedef enum _ATOM_INFORMATION_CLASS {
+    AtomBasicInformation,
+    AtomTableInformation
+} ATOM_INFORMATION_CLASS, *PATOM_INFORMATION_CLASS;
+
 /***********************************************************************
  * Defines
  */
@@ -822,6 +841,7 @@
 void WINAPIV DbgPrint(LPCSTR fmt, ...);
 
 NTSTATUS  WINAPI NtAccessCheck(PSECURITY_DESCRIPTOR,HANDLE,ACCESS_MASK,PGENERIC_MAPPING,PPRIVILEGE_SET,PULONG,PULONG,PBOOLEAN);
+NTSTATUS  WINAPI NtAddAtom(PCWSTR,PRTL_ATOM);
 NTSTATUS  WINAPI NtAdjustPrivilegesToken(HANDLE,BOOLEAN,PTOKEN_PRIVILEGES,DWORD,PTOKEN_PRIVILEGES,PDWORD);
 NTSTATUS  WINAPI NtAllocateVirtualMemory(HANDLE,PVOID*,PVOID,ULONG*,ULONG,ULONG);
 NTSTATUS  WINAPI NtClearEvent(HANDLE);
@@ -831,12 +851,14 @@
 NTSTATUS  WINAPI NtCreateKey(PHKEY,ACCESS_MASK,const OBJECT_ATTRIBUTES*,ULONG,const UNICODE_STRING*,ULONG,PULONG);
 NTSTATUS  WINAPI NtCreateSection(HANDLE*,ACCESS_MASK,const OBJECT_ATTRIBUTES*,const LARGE_INTEGER*,ULONG,ULONG,HANDLE);
 NTSTATUS  WINAPI NtCreateSemaphore(PHANDLE,ACCESS_MASK,const OBJECT_ATTRIBUTES*,ULONG,ULONG);
+NTSTATUS  WINAPI NtDeleteAtom(RTL_ATOM);
 NTSTATUS  WINAPI NtDeleteKey(HKEY);
 NTSTATUS  WINAPI NtDeleteValueKey(HKEY,const UNICODE_STRING *);
 NTSTATUS  WINAPI NtDeviceIoControlFile(HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,ULONG,PVOID,ULONG,PVOID,ULONG);
 NTSTATUS  WINAPI NtDuplicateObject(HANDLE,HANDLE,HANDLE,PHANDLE,ACCESS_MASK,ULONG,ULONG);
 NTSTATUS  WINAPI NtEnumerateKey(HKEY,ULONG,KEY_INFORMATION_CLASS,void *,DWORD,DWORD *);
 NTSTATUS  WINAPI NtEnumerateValueKey(HKEY,ULONG,KEY_VALUE_INFORMATION_CLASS,PVOID,ULONG,PULONG);
+NTSTATUS  WINAPI NtFindAtom(PCWSTR,PRTL_ATOM);
 NTSTATUS  WINAPI NtFlushKey(HKEY);
 NTSTATUS  WINAPI NtFlushVirtualMemory(HANDLE,LPCVOID*,ULONG*,ULONG);
 NTSTATUS  WINAPI NtFreeVirtualMemory(HANDLE,PVOID*,ULONG*,ULONG);
@@ -854,6 +876,7 @@
 NTSTATUS  WINAPI NtOpenThreadToken(HANDLE,DWORD,BOOLEAN,HANDLE *);
 NTSTATUS  WINAPI NtProtectVirtualMemory(HANDLE,PVOID*,ULONG*,ULONG,ULONG*);
 NTSTATUS  WINAPI NtPulseEvent(HANDLE,PULONG);
+NTSTATUS  WINAPI NtQueryInformationAtom(RTL_ATOM,ATOM_INFORMATION_CLASS,PVOID,ULONG,PULONG);
 NTSTATUS  WINAPI NtQueueApcThread(HANDLE,PNTAPCFUNC,ULONG_PTR,ULONG_PTR,ULONG_PTR);
 NTSTATUS  WINAPI NtQueryInformationProcess(HANDLE,PROCESSINFOCLASS,PVOID,ULONG,PULONG);
 NTSTATUS  WINAPI NtQueryInformationThread(HANDLE,THREADINFOCLASS,PVOID,ULONG,PULONG);
@@ -894,6 +917,7 @@
 NTSTATUS  WINAPI RtlAddAce(PACL,DWORD,DWORD,PACE_HEADER,DWORD);
 BOOL      WINAPI RtlAddAccessAllowedAce(PACL,DWORD,DWORD,PSID);
 BOOL      WINAPI RtlAddAccessAllowedAceEx(PACL,DWORD,DWORD,DWORD,PSID);
+NTSTATUS  WINAPI RtlAddAtomToAtomTable(RTL_ATOM_TABLE,PCWSTR,PRTL_ATOM);
 DWORD     WINAPI RtlAdjustPrivilege(DWORD,DWORD,DWORD,DWORD);
 BOOLEAN   WINAPI RtlAllocateAndInitializeSid(PSID_IDENTIFIER_AUTHORITY,BYTE,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,PSID *);
 PVOID     WINAPI RtlAllocateHeap(HANDLE,ULONG,ULONG);
@@ -920,15 +944,18 @@
 void      WINAPI RtlCopyString(STRING*,const STRING*);
 void      WINAPI RtlCopyUnicodeString(UNICODE_STRING*,const UNICODE_STRING*);
 NTSTATUS  WINAPI RtlCreateAcl(PACL,DWORD,DWORD);
+NTSTATUS  WINAPI RtlCreateAtomTable(ULONG,PRTL_ATOM_TABLE);
 DWORD     WINAPI RtlCreateEnvironment(DWORD,DWORD);
 HANDLE    WINAPI RtlCreateHeap(ULONG,PVOID,ULONG,ULONG,PVOID,PRTL_HEAP_DEFINITION);
 NTSTATUS  WINAPI RtlCreateSecurityDescriptor(PSECURITY_DESCRIPTOR,DWORD);
 BOOLEAN   WINAPI RtlCreateUnicodeString(PUNICODE_STRING,LPCWSTR);
 BOOLEAN   WINAPI RtlCreateUnicodeStringFromAsciiz(PUNICODE_STRING,LPCSTR);
 
+NTSTATUS  WINAPI RtlDeleteAtomFromAtomTable(RTL_ATOM_TABLE,RTL_ATOM);
 NTSTATUS  WINAPI RtlDeleteCriticalSection(RTL_CRITICAL_SECTION *);
 void      WINAPI RtlDeleteResource(LPRTL_RWLOCK);
 DWORD     WINAPI RtlDeleteSecurityObject(DWORD);
+NTSTATUS  WINAPI RtlDestroyAtomTable(RTL_ATOM_TABLE);
 DWORD     WINAPI RtlDestroyEnvironment(DWORD);
 HANDLE    WINAPI RtlDestroyHeap(HANDLE);
 BOOLEAN   WINAPI RtlDosPathNameToNtPathName_U(LPWSTR,PUNICODE_STRING,DWORD,DWORD);
@@ -966,6 +993,7 @@
 ULONG     WINAPI RtlFindSetBitsAndClear(PRTL_BITMAP,ULONG,ULONG);
 ULONG     WINAPI RtlFindSetRuns(PCRTL_BITMAP,PRTL_BITMAP_RUN,ULONG,BOOLEAN);
 BOOLEAN   WINAPI RtlFirstFreeAce(PACL,PACE_HEADER *);
+NTSTATUS  WINAPI RtlEmptyAtomTable(RTL_ATOM_TABLE,BOOLEAN);
 NTSTATUS  WINAPI RtlFormatCurrentUserKeyPath(PUNICODE_STRING);
 void      WINAPI RtlFreeAnsiString(PANSI_STRING);
 BOOLEAN   WINAPI RtlFreeHeap(HANDLE,ULONG,PVOID);
@@ -1017,6 +1045,7 @@
 DWORD     WINAPI RtlLengthSid(PSID);
 NTSTATUS  WINAPI RtlLocalTimeToSystemTime(const LARGE_INTEGER*,PLARGE_INTEGER);
 BOOLEAN   WINAPI RtlLockHeap(HANDLE);
+NTSTATUS  WINAPI RtlLookupAtomInAtomTable(RTL_ATOM_TABLE,PCWSTR,PRTL_ATOM);
 
 NTSTATUS  WINAPI RtlMakeSelfRelativeSD(PSECURITY_DESCRIPTOR,PSECURITY_DESCRIPTOR,LPDWORD);
 NTSTATUS  WINAPI RtlMultiByteToUnicodeN(LPWSTR,DWORD,LPDWORD,LPCSTR,DWORD);
@@ -1033,9 +1062,11 @@
 NTSTATUS  WINAPI RtlOemToUnicodeN(LPWSTR,DWORD,LPDWORD,LPCSTR,DWORD);
 DWORD     WINAPI RtlOpenCurrentUser(ACCESS_MASK,PHKEY);
 
+NTSTATUS  WINAPI RtlPinAtomInAtomTable(RTL_ATOM_TABLE,RTL_ATOM);
 BOOLEAN   WINAPI RtlPrefixString(const STRING*,const STRING*,BOOLEAN);
 BOOLEAN   WINAPI RtlPrefixUnicodeString(const UNICODE_STRING*,const UNICODE_STRING*,BOOLEAN);
 
+NTSTATUS  WINAPI RtlQueryAtomInAtomTable(RTL_ATOM_TABLE,RTL_ATOM,PULONG,PULONG,PWSTR,PULONG);
 DWORD     WINAPI RtlQueryEnvironmentVariable_U(DWORD,PUNICODE_STRING,PUNICODE_STRING) ;
 NTSTATUS  WINAPI RtlQueryTimeZoneInformation(LPTIME_ZONE_INFORMATION);
 void      WINAPI RtlRaiseException(PEXCEPTION_RECORD);
--- ../cleanwine/dlls/ntdll/Makefile.in	2003-04-05 08:32:52.000000000 +0200
+++ dlls/ntdll/Makefile.in	2003-04-05 11:36:07.000000000 +0200
@@ -71,6 +71,7 @@
 	$(TOPOBJDIR)/win32/except.c \
 	$(TOPOBJDIR)/win32/kernel32.c \
 	$(TOPOBJDIR)/win32/newfns.c \
+	atom.c \
 	cdrom.c \
 	critsection.c \
 	debugtools.c \
--- /dev/null	1970-01-01 02:00:00.000000000 +0200
+++ dlls/ntdll/atom.c	2003-04-07 13:58:08.000000000 +0200
@@ -0,0 +1,523 @@
+/* Ntdll atom API implementation
+ *
+ * Copyright 2003 Gyorgy 'Nog' Jeney
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "winternl.h"
+#include "wtypes.h"
+#include "ntstatus.h"
+#include "winnt.h"
+#include "wine/debug.h"
+#include "wine/server.h"
+#include "wine/unicode.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(atom);
+
+#define MAX_ATOM_LEN              255
+
+/***********************************************************************
+ *           ATOM_IsIntAtom
+ */
+static BOOLEAN ATOM_IsIntAtom(LPCWSTR atomstr, WORD *atomid)
+{
+  UINT atom = 0;
+  if(!HIWORD(atomstr)) atom = LOWORD(atomstr);
+  else {
+    if(*atomstr++ != '#') return FALSE;
+    while (*atomstr >= '0' && *atomstr <= '9') {
+      atom = atom * 10 + *atomstr - '0';
+      atomstr++;
+    }
+    if(*atomstr) return FALSE;
+  }
+  if(atom >= MAXINTATOM)
+    atom = 0;
+  *atomid = atom;
+  return TRUE;
+}
+
+/****************************************************************
+ *        NtAddAtom                  [ntdll.@]
+ *
+ * Adds an atom to the global atom table.
+ *
+ * PARAMS:
+ *   AtomName [I]: The value of the atom.
+ *   Atom [O]: The assigned value of the atom.
+ *
+ * RETURNS:
+ *   Status.
+ */
+NTSTATUS WINAPI NtAddAtom(IN PCWSTR AtomName, OUT PRTL_ATOM Atom)
+{
+  NTSTATUS res;
+
+  TRACE("(%s, %p)\n", debugstr_w(AtomName), Atom);
+
+  if(ATOM_IsIntAtom(AtomName, Atom)) {
+    if(*Atom) return STATUS_SUCCESS;
+    else return STATUS_INVALID_PARAMETER;
+  }
+
+  SERVER_START_REQ(add_atom) {
+    wine_server_add_data(req, AtomName, strlenW(AtomName) * sizeof(WCHAR));
+    if(!(res = wine_server_call(req)))
+      *Atom = reply->atom;
+  }
+  SERVER_END_REQ;
+
+  return res;
+}
+
+/****************************************************************
+ *        NtDeleteAtom               [ntdll.@]
+ *
+ * Deletes the specified atom from the global atom table.
+ *
+ * PARAMS:
+ *   Atom: [I]: Specifier of atom to delete.
+ *
+ * RETURNS:
+ *   Status.
+ */
+NTSTATUS WINAPI NtDeleteAtom(IN RTL_ATOM Atom)
+{
+  NTSTATUS res;
+
+  TRACE("(%x)\n", Atom);
+
+  if(Atom < MAXINTATOM)
+    return STATUS_SUCCESS;
+
+  SERVER_START_REQ(delete_atom) {
+    req->atom = Atom;
+    res = wine_server_call(req);
+  } SERVER_END_REQ;
+
+  return res;
+}
+
+/****************************************************************
+ *        NtFindAtom                 [ntdll.@]
+ *
+ * Finds an atom in the global atom table.
+ *
+ * PARAMS:
+ *   AtomName [I]: Name of the atom to find in the global atom table.
+ *   Atom [O]: The specifier to the atom found.
+ *
+ * RETURNS:
+ *   Status.
+ */
+NTSTATUS WINAPI NtFindAtom(IN PCWSTR AtomName, OUT PRTL_ATOM Atom)
+{
+  NTSTATUS res;
+
+  TRACE("(%s, %p)\n", debugstr_w(AtomName), Atom);
+
+  SERVER_START_REQ(find_atom) {
+    wine_server_add_data(req, AtomName, strlenW(AtomName) * sizeof(WCHAR));
+    if(!(res = wine_server_call(req)))
+      *Atom = reply->atom;
+  } SERVER_END_REQ;
+
+  return res;
+}
+
+/****************************************************************
+ *        NtQueryInformationAtom     [ntdll.@]
+ *
+ * Returns information about the specified global atom.
+ *
+ * PARAMS:
+ *   Atom [I]: The atom to request info about.
+ *   AtomInfoClass [I]: The information to request.
+ *   AtomInfo [O]: Buffer to hold the returned information.
+ *   AtomInfoLen [I]: The length of the buffer pointed to by AtomInfo.
+ *   RetLen [I]: The number of bytes actually used in AtomInfo.
+ *
+ * RETURNS:
+ *   Status.
+ */
+NTSTATUS WINAPI NtQueryInformationAtom(IN RTL_ATOM Atom, IN ATOM_INFORMATION_CLASS
+  AtomInfoClass, OUT PVOID AtomInfo, ULONG AtomInfoLen, PULONG RetLen)
+{
+  NTSTATUS res = 0;
+  WCHAR full_name[MAX_ATOM_LEN];
+
+  TRACE("(%x, %x, %p, %lx, %p)\n", Atom, AtomInfoClass, AtomInfo, AtomInfoLen,
+        RetLen);
+
+  switch(AtomInfoClass) {
+  case AtomBasicInformation: {
+    PATOM_BASIC_INFORMATION info = AtomInfo;
+    USHORT RefCount, Pin, len;
+
+    TRACE("AtomBasicInformation requested\n");
+
+    if(Atom < MAXINTATOM) {
+      *RetLen = AtomInfoLen - sizeof(ATOM_BASIC_INFORMATION);
+      return RtlQueryAtomInAtomTable(NULL, Atom, &info->RefCount, &info->Pin, info->Name, RetLen);
+    }
+
+    SERVER_START_REQ(atom_query_information) {
+      req->atom = Atom;
+      wine_server_set_reply(req, full_name, sizeof(full_name));
+      if(!(res = wine_server_call(req))) {
+        len = wine_server_reply_size(reply);
+        RefCount = reply->refcount;
+        Pin = reply->pin;
+      }
+    } SERVER_END_REQ;
+    if(res)
+      break;
+
+    len /= sizeof(WCHAR);
+
+    if(AtomInfoLen < (sizeof(ATOM_BASIC_INFORMATION) + len))
+      return STATUS_BUFFER_TOO_SMALL;
+
+    info->RefCount = RefCount;
+    info->Pin = Pin;
+    info->NameLen = len;
+    full_name[len] = 0;
+    strcpyW(info->Name, full_name);
+
+    TRACE("Found info: ref: %x, pin: %x, namelen: %x, name: %s\n", RefCount,
+          Pin, len, debugstr_w(full_name));
+    break;
+    }
+
+  case AtomTableInformation:
+    FIXME("AtomTableInformation not implemented\n");
+    res = STATUS_NOT_IMPLEMENTED;
+    break;
+
+  default:
+    FIXME("Info class %x not implemented\n", AtomInfoClass);
+    res = STATUS_NOT_IMPLEMENTED;
+  }
+
+  return res;
+}
+
+/****************************************************************
+ *        RtlCreateAtomTable         [ntdll.@]
+ *
+ * Creates an atom table.
+ *
+ * PARAMS:
+ *   Size [I]: The size of the atom table to create.
+ *   Table [O]: Handle to the atom table.
+ *
+ * RETURNS:
+ *   Status.
+ *
+ * NOTES:
+ *   If *Table is not null then this function thinks that it is getting an
+ *    already created atom table.
+ */
+NTSTATUS WINAPI RtlCreateAtomTable(IN ULONG Size, PRTL_ATOM_TABLE Table)
+{
+  NTSTATUS res;
+
+  TRACE("(%ld, %p)\n", Size, Table);
+
+  if(*Table)
+    return STATUS_SUCCESS;
+
+  SERVER_START_REQ(create_atom_table) {
+    req->entries = Size;
+    if(!(res = wine_server_call(req)))
+      *Table = reply->table;
+  } SERVER_END_REQ;
+    
+  return res;
+}
+
+/****************************************************************
+ *        RtlDestroyAtomTable        [ntdll.@]
+ *
+ * Destroys an Atom table.
+ *
+ * PARAMS:
+ *   Table [I]: Pointer to the atom table to destroy.
+ *
+ * RETURNS:
+ *   Status.
+ */
+NTSTATUS WINAPI RtlDestroyAtomTable(IN RTL_ATOM_TABLE Table)
+{
+  NTSTATUS res;
+
+  TRACE("(%p)\n", Table);
+
+  SERVER_START_REQ(destroy_atom_table) {
+    req->table = Table;
+    res = wine_server_call(req);
+  } SERVER_END_REQ;
+
+  return res;
+}
+
+/****************************************************************
+ *        RtlEmptyAtomTable          [ntdll.@]
+ *
+ * Removes all atoms from the specified atom table.
+ *
+ * PARAMS:
+ *   Table [I]: Handle to table to empty.
+ *   DeletePinned [I]: Also removed pinned atoms.
+ *
+ * RETURNS:
+ *   Status.
+ */
+NTSTATUS WINAPI RtlEmptyAtomTable(IN RTL_ATOM_TABLE Table, IN BOOLEAN DeletePinned)
+{
+  NTSTATUS res;
+
+  TRACE("(%p, %x)\n", Table, DeletePinned);
+
+  SERVER_START_REQ(empty_atom_table) {
+    req->table = Table;
+    req->delpinned = DeletePinned;
+    res = wine_server_call(req);
+  } SERVER_END_REQ;
+
+  return res;
+}
+
+/****************************************************************
+ *        RtlAddAtomToAtomTable      [ntdll.@]
+ *
+ * Adds an atom to an atom table.
+ *
+ * PARAMS:
+ *   Table [I]: Table to add the atom to.
+ *   AtomName [I]: Name of atom to add.
+ *   Atom [O]: Handle to the atom.
+ *
+ * RETURNS:
+ *   Status.
+ */
+NTSTATUS WINAPI RtlAddAtomToAtomTable(IN RTL_ATOM_TABLE Table, IN PCWSTR AtomName,
+  OUT PRTL_ATOM Atom)
+{
+  NTSTATUS res;
+
+  TRACE("(%p, %s, %p)\n", Table, debugstr_w(AtomName), Atom);
+
+  if(ATOM_IsIntAtom(AtomName, Atom)) {
+    if(*Atom) return STATUS_SUCCESS;
+    else return STATUS_INVALID_PARAMETER;
+  }
+
+  SERVER_START_REQ(add_atom_to_atom_table) {
+    wine_server_add_data(req, AtomName, strlenW(AtomName) * sizeof(WCHAR));
+    req->table = Table;
+    if(!(res = wine_server_call(req)))
+      *Atom = reply->atom;
+  } SERVER_END_REQ;
+
+  return res;
+}
+
+/****************************************************************
+ *        RtlDeleteAtomFromAtomTable [ntdll.@]
+ *
+ * Removes the specified atom from the specified atom table.
+ *
+ * PARAMS:
+ *   Table [I]: Table to delete the specified atom from.
+ *   Atom [I]: The atom to delete from the table.
+ *
+ * RETURNS:
+ *   Status.
+ */
+NTSTATUS WINAPI RtlDeleteAtomFromAtomTable(IN RTL_ATOM_TABLE Table, IN RTL_ATOM Atom)
+{
+  NTSTATUS res;
+
+  TRACE("(%p, %x)\n", Table, Atom);
+
+  if(Atom < MAXINTATOM)
+    return STATUS_SUCCESS;
+
+  SERVER_START_REQ(delete_atom_from_atom_table) {
+    req->table = Table;
+    req->atom = Atom;
+    res = wine_server_call(req);
+  } SERVER_END_REQ;
+
+  return res;
+}
+
+/****************************************************************
+ *        RtlLookupAtomInAtomTable   [ntdll.@]
+ *
+ * Finds an Atom in the specified atom table.
+ *
+ * PARAMS:
+ *   Table [I]: The atom table to search.
+ *   Name [I]: The name of the atom to find.
+ *   Atom [O]: The handle of the found atom.
+ *
+ * RETURNS:
+ *   Status.
+ */
+NTSTATUS WINAPI RtlLookupAtomInAtomTable(IN RTL_ATOM_TABLE Table, IN PCWSTR Name, OUT PRTL_ATOM Atom)
+{
+  NTSTATUS res;
+
+  TRACE("(%p, %s, %p)\n", Table, debugstr_w(Name), Atom);
+
+  if(ATOM_IsIntAtom(Name, Atom)) {
+    if(*Atom) return STATUS_SUCCESS;
+    else return STATUS_INVALID_PARAMETER;
+  }
+
+  SERVER_START_REQ(lookup_atom_in_atom_table) {
+    wine_server_add_data(req, Name, strlenW(Name) * sizeof(WCHAR));
+    req->table = Table;
+    if(!(res = wine_server_call(req)))
+      *Atom = reply->atom;
+  } SERVER_END_REQ;
+
+  return res;
+}
+
+/****************************************************************
+ *        RtlPinAtomInAtomTable      [ntdll.@]
+ *
+ * Pins the specified atom in the specified atom table.
+ *
+ * PARAMS:
+ *   Table [I]: The table in which to pin the atom.
+ *   Atom [I]: The atom to pin.
+ *
+ * RETURNS:
+ *   Status.
+ *
+ * NOTES:
+ *   Pinning an atom realy only sets a flag in the atom table entry that this
+ *   atom is locked.  Multiple calls to this fucntion with the same atom in the
+ *   same table will do nothing eaven though RtlQueryAtomInAtomTable does have a
+ *   pincount field.
+ */
+NTSTATUS WINAPI RtlPinAtomInAtomTable(IN RTL_ATOM_TABLE Table, IN RTL_ATOM Atom)
+{
+  NTSTATUS res;
+
+  TRACE("(%p, %x)\n", Table, Atom);
+
+  if(Atom < MAXINTATOM)
+    return STATUS_SUCCESS;
+
+  SERVER_START_REQ(pin_atom_in_atom_table) {
+    req->table = Table;
+    req->atom = Atom;
+    res = wine_server_call(req);
+  } SERVER_END_REQ;
+
+  return res;
+}
+
+/****************************************************************
+ *        RtlQueryAtomInAtomTable    [ntdll.@]
+ *
+ * Returns information about an atom in the specified atom table.
+ *
+ * PARAMS:
+ *   Table [I]: The table that the atom's in.
+ *   Atom [I]: The atom to query.
+ *   RefCount [O]: How many times has the atom been added to the table.
+ *   PinCount [O]: How many times has the atom been pinned.
+ *   AtomName [O]: The name of the atom.
+ *   NameLength [O]: The length of the name of the atom.
+ *
+ * RETURNS:
+ *   Status.
+ *
+ * NOTES:
+ *   - NameLength is the length of the string in bytes less the null terminator.
+ *   - NameLength is set to the length of the string copied or if it is too
+ *     short then it is set to the number of bytes required to store the name,
+ *     minus the null terminator.
+ *   - PinCount only realy returns 1 or 0, see note in RtlPinAtomInAtomTable.
+ */
+NTSTATUS WINAPI RtlQueryAtomInAtomTable(IN RTL_ATOM_TABLE Table, IN RTL_ATOM Atom,
+  OUT PULONG RefCount, OUT PULONG PinCount, OUT PWSTR AtomName,
+  IN OUT PULONG NameLength)
+{
+  NTSTATUS res;
+  WCHAR full_name[MAX_ATOM_LEN];
+  static WCHAR IntFormat[] = {'#','%','d',0};
+  ULONG Len, intPin, intRef;
+
+  TRACE("(%p, %x, %p, %p, %p, %p)\n", Table, Atom, RefCount, PinCount, AtomName,
+        NameLength);
+
+  if(!Atom) {
+    *NameLength = 0;
+    return STATUS_INVALID_PARAMETER;
+  }
+
+  if(Atom < MAXINTATOM) {
+    if(RefCount)
+      *RefCount = 1;
+    if(PinCount)
+      *PinCount = 1;
+    if(AtomName && NameLength) {
+      Len = sprintfW(full_name, IntFormat, Atom);
+      if(Len < *NameLength)
+        strcpyW(AtomName, full_name);
+      *NameLength = Len * sizeof(WCHAR);
+    }
+    TRACE("Found atom with pin: 1, ref: 1, name: %s\n", debugstr_w(full_name));
+    return STATUS_SUCCESS;
+  }
+      
+
+  SERVER_START_REQ(query_atom_in_atom_table) {
+    req->table = Table;
+    req->atom = Atom;
+    wine_server_set_reply(req, full_name, sizeof(full_name));
+    res = wine_server_call(req);
+    intPin = reply->pincount;
+    intRef = reply->refcount;
+    if(!res)
+      Len = wine_server_reply_size(reply);
+  } SERVER_END_REQ;
+
+  if(!res) {
+    if(RefCount)
+      *RefCount = intRef;
+    if(PinCount)
+      *PinCount = intPin;
+    full_name[Len / sizeof(WCHAR)] = '\0';
+    if(AtomName && NameLength) {
+      if(Len < *NameLength) strcpyW(AtomName, full_name);
+      else res = STATUS_BUFFER_TOO_SMALL;
+      *NameLength = Len;
+    }
+
+    TRACE("Found atom with pin: %ld, ref: %ld, name: %s\n", intPin, intRef,
+          debugstr_w(full_name));
+  }
+
+  return res;
+}
--- ../cleanwine/server/protocol.def	2003-04-05 08:33:57.000000000 +0200
+++ server/protocol.def	2003-04-07 12:19:38.000000000 +0200
@@ -1478,7 +1478,6 @@
 
 /* Add an atom */
 @REQ(add_atom)
-    int           local;       /* is atom in local process table? */
     VARARG(name,unicode_str);  /* atom name */
 @REPLY
     atom_t        atom;        /* resulting atom */
@@ -1488,32 +1487,87 @@
 /* Delete an atom */
 @REQ(delete_atom)
     atom_t        atom;        /* atom handle */
-    int           local;       /* is atom in local process table? */
 @END
 
 
 /* Find an atom */
 @REQ(find_atom)
-    int          local;        /* is atom in local process table? */
     VARARG(name,unicode_str);  /* atom name */
 @REPLY
     atom_t       atom;         /* atom handle */
 @END
 
 
-/* Get an atom name */
- at REQ(get_atom_name)
-    atom_t       atom;         /* atom handle */
-    int          local;        /* is atom in local process table? */
+/* Get info about a global atom */
+ at REQ(atom_query_information)
+    atom_t       atom;         /* atom to receive info about */
 @REPLY
-    int          count;        /* atom lock count */
-    VARARG(name,unicode_str);  /* atom name */
+    int          refcount;     /* The refcount of the atom */
+    int          pin;          /* Is atom pinned ? */
 @END
 
 
-/* Init the process atom table */
- at REQ(init_atom_table)
+/* Create an atom table */
+ at REQ(create_atom_table)
     int          entries;      /* number of entries */
+ at REPLY
+    void*        table;    /* The atom table */
+ at END
+
+
+/* Destroy an atom table */
+ at REQ(destroy_atom_table)
+    void*        table;        /* The atom table */
+ at END
+
+
+/* Empty an atom table */
+ at REQ(empty_atom_table)
+    void*        table;        /* The atom table */
+    int          delpinned;    /* Also delete pinned atoms ? */
+ at END
+
+
+/* Add an atom to an atom table */
+ at REQ(add_atom_to_atom_table)
+    void*        table;        /* The atom table to add this entry to */
+    VARARG(name,unicode_str);  /* atom name */
+ at REPLY
+    atom_t       atom;         /* The atom */
+ at END
+
+
+/* Delete an atom from an atom table */
+ at REQ(delete_atom_from_atom_table)
+    void*        table;        /* The atom table to delete this atom from */
+    atom_t       atom;         /* Atom to delete */
+ at END
+
+
+/* Find an atom in an atom table */
+ at REQ(lookup_atom_in_atom_table)
+    void*        table;        /* The atom table to lookup these atoms in */
+    VARARG(name,unicode_str);  /* The name of the atom to lookup */
+ at REPLY
+    atom_t       atom;         /* The corrisponding atom */
+ at END
+
+
+/* Pin an atom in an atom table */
+ at REQ(pin_atom_in_atom_table)
+    void*        table;        /* The table to pin the atom in */
+    atom_t       atom;         /* The atom to pin */
+ at END
+
+
+/* Query an atom in an atom table */
+ at REQ(query_atom_in_atom_table)
+    void*        table;        /* The table to query the atom from */
+    atom_t       atom;         /* The atom to query */
+ at REPLY
+    int          refcount;     /* The refcount on the atom */
+    int          pincount;     /* The pincount on the atom */
+    VARARG(name,unicode_str);  /* The name of the atom */
 @END
 
 
--- ../cleanwine/server/atom.c	2003-02-26 14:45:42.000000000 +0200
+++ server/atom.c	2003-04-07 13:18:52.000000000 +0200
@@ -42,12 +42,13 @@
 
 struct atom_entry
 {
-    struct atom_entry *next;   /* hash table list */
-    struct atom_entry *prev;   /* hash table list */
-    int                count;  /* reference count */
-    int                hash;   /* string hash */
-    atom_t             atom;   /* atom handle */
-    WCHAR              str[1]; /* atom string */
+    struct atom_entry *next;     /* hash table list */
+    struct atom_entry *prev;     /* hash table list */
+    int                count;    /* reference count */
+    int                hash;     /* string hash */
+    int                pincount; /* pin count of the atom */
+    atom_t             atom;     /* atom handle */
+    WCHAR              str[1];   /* atom string */
 };
 
 struct atom_table
@@ -184,7 +185,7 @@
     {
         struct atom_entry *entry = table->handles[i];
         if (!entry) continue;
-        fprintf( stderr, "  %04x: ref=%d hash=%d \"", entry->atom, entry->count, entry->hash );
+        fprintf( stderr, "  %04x: ref=%d pin=%d hash=%d \"", entry->atom, entry->count, entry->pincount, entry->hash );
         dump_strW( entry->str, strlenW(entry->str), stderr, "\"\"");
         fprintf( stderr, "\"\n" );
     }
@@ -247,8 +248,9 @@
             entry->prev  = NULL;
             if ((entry->next = table->entries[hash])) entry->next->prev = entry;
             table->entries[hash] = entry;
-            entry->count = 1;
-            entry->hash  = hash;
+            entry->count    = 1;
+            entry->pincount = 0;
+            entry->hash     = hash;
             strcpyW( entry->str, str );
         }
         else free( entry );
@@ -304,7 +306,7 @@
 /* add a global atom */
 DECL_HANDLER(add_atom)
 {
-    struct atom_table **table_ptr = req->local ? &current->process->atom_table : &global_table;
+    struct atom_table **table_ptr = &global_table;
 
     if (!*table_ptr) *table_ptr = create_table(0);
     if (*table_ptr)
@@ -317,7 +319,7 @@
 /* delete a global atom */
 DECL_HANDLER(delete_atom)
 {
-    delete_atom( req->local ? current->process->atom_table : global_table, req->atom );
+    delete_atom( global_table, req->atom );
 }
 
 /* find a global atom */
@@ -325,29 +327,91 @@
 {
     const WCHAR *name = copy_request_name();
     if (name)
-        reply->atom = find_atom( req->local ? current->process->atom_table : global_table, name );
+        reply->atom = find_atom( global_table, name );
 }
 
-/* get global atom name */
-DECL_HANDLER(get_atom_name)
+/* Get info about a global atom */
+DECL_HANDLER(atom_query_information)
 {
     struct atom_entry *entry;
     size_t len = 0;
 
-    reply->count = -1;
-    if ((entry = get_atom_entry( req->local ? current->process->atom_table : global_table,
-                                 req->atom )))
+    if ((entry = get_atom_entry( global_table, req->atom )))
     {
-        reply->count = entry->count;
+        reply->refcount = entry->count;
+        reply->pin = entry->pincount;
         len = strlenW( entry->str ) * sizeof(WCHAR);
         if (len <= get_reply_max_size()) set_reply_data( entry->str, len );
         else set_error( STATUS_BUFFER_OVERFLOW );
     }
 }
 
-/* init the process atom table */
-DECL_HANDLER(init_atom_table)
+/* Create an atom table */
+DECL_HANDLER(create_atom_table)
 {
-    if (!current->process->atom_table)
-        current->process->atom_table = create_table( req->entries );
+    void *table = create_table( req->entries );
+    if (table)
+        reply->table = table;
+}
+
+/* Destroy an atom table */
+DECL_HANDLER(destroy_atom_table)
+{
+    release_object( req->table );
+}
+
+/* Empty an atom table */
+DECL_HANDLER(empty_atom_table)
+{
+    int i;
+    struct atom_entry *entry;
+    struct atom_table *table = req->table;
+
+    for(i = 0; i <= table->last; i++)
+    {
+        entry = table->handles[i];
+        if (entry && (!entry->pincount || req->delpinned))
+            delete_atom( req->table, i + MIN_STR_ATOM );
+    }
+}
+
+DECL_HANDLER(add_atom_to_atom_table)
+{
+    const WCHAR *name = copy_request_name();
+    if (name) reply->atom = add_atom( req->table, name );
+}
+
+DECL_HANDLER(delete_atom_from_atom_table)
+{
+    struct atom_entry *entry = get_atom_entry( req->table, req->atom );
+
+    if (!entry->pincount) delete_atom( req->table, req->atom );
+    else set_error( STATUS_WAS_LOCKED );
+}
+
+DECL_HANDLER(lookup_atom_in_atom_table)
+{
+    const WCHAR *name = copy_request_name();
+    if (name)
+        reply->atom = find_atom( req->table, name );
+}
+
+DECL_HANDLER(pin_atom_in_atom_table)
+{
+    struct atom_entry *entry = get_atom_entry( req->table, req->atom );
+    if (entry && !entry->pincount)
+       entry->pincount++;
+}
+
+DECL_HANDLER(query_atom_in_atom_table)
+{
+    struct atom_entry *entry = get_atom_entry( req->table, req->atom );
+    int len;
+    if (entry) {
+        len = strlenW( entry->str ) * sizeof(WCHAR);
+        reply->refcount = entry->count;
+        reply->pincount = entry->pincount;
+        if (len <= get_reply_max_size()) set_reply_data( entry->str, len );
+        else set_error( STATUS_OBJECT_NAME_NOT_FOUND );
+    }
 }
--- ../cleanwine/memory/atom.c	2002-10-04 19:45:00.000000000 +0200
+++ memory/atom.c	2003-04-07 13:52:07.000000000 +0200
@@ -36,6 +36,7 @@
 #include "windef.h"
 #include "winbase.h"
 #include "winerror.h"
+#include "winternl.h"
 
 #include "wine/server.h"
 #include "wine/unicode.h"
@@ -69,6 +70,10 @@
 } ATOMTABLE;
 
 
+/* The local atom table */
+static RTL_ATOM_TABLE local_table = NULL;
+
+
 /***********************************************************************
  *           ATOM_GetTable
  *
@@ -142,33 +147,6 @@
 
 
 /***********************************************************************
- *           ATOM_IsIntAtomW
- */
-static BOOL ATOM_IsIntAtomW(LPCWSTR atomstr,WORD *atomid)
-{
-    UINT atom = 0;
-    if (!HIWORD(atomstr)) atom = LOWORD(atomstr);
-    else
-    {
-        if (*atomstr++ != '#') return FALSE;
-        while (*atomstr >= '0' && *atomstr <= '9')
-        {
-            atom = atom * 10 + *atomstr - '0';
-            atomstr++;
-        }
-        if (*atomstr) return FALSE;
-    }
-    if (atom >= MAXINTATOM)
-    {
-        SetLastError( ERROR_INVALID_PARAMETER );
-        atom = 0;
-    }
-    *atomid = atom;
-    return TRUE;
-}
-
-
-/***********************************************************************
  *           ATOM_MakePtr
  *
  * Make an ATOMENTRY pointer from a handle (obtained from GetAtomHandle()).
@@ -386,43 +364,29 @@
 
 /***********************************************************************
  *           InitAtomTable   (KERNEL32.@)
+ *
+ * Initialises the local atom table.
+ *
+ * PARAMS:
+ *   entries [I]: Number of has buckets to allocate.  If this parameter is 0
+ *                then the default of 37 will be used.
+ *
+ * RETURNS:
+ *   True: Success
+ *   False: Failure
+ *
+ * NOTES:
+ *   This function need not be called before any local atom management has taken
+ *   place.
  */
 BOOL WINAPI InitAtomTable( DWORD entries )
 {
-    BOOL ret;
-    SERVER_START_REQ( init_atom_table )
-    {
-        req->entries = entries;
-        ret = !wine_server_call_err( req );
-    }
-    SERVER_END_REQ;
-    return ret;
-}
-
-
-static ATOM ATOM_AddAtomA( LPCSTR str, BOOL local )
-{
-    ATOM atom = 0;
-    if (!ATOM_IsIntAtomA( str, &atom ))
-    {
-        WCHAR buffer[MAX_ATOM_LEN];
-
-        DWORD len = MultiByteToWideChar( CP_ACP, 0, str, strlen(str), buffer, MAX_ATOM_LEN );
-        if (!len)
-        {
-            SetLastError( ERROR_INVALID_PARAMETER );
-            return 0;
-        }
-        SERVER_START_REQ( add_atom )
-        {
-            wine_server_add_data( req, buffer, len * sizeof(WCHAR) );
-            req->local = local;
-            if (!wine_server_call_err(req)) atom = reply->atom;
-        }
-        SERVER_END_REQ;
+    NTSTATUS res = STATUS_SUCCESS;
+    if (!local_table) {
+        if ((res = RtlCreateAtomTable( entries, &local_table )))
+            SetLastError( RtlNtStatusToDosError(res) );
     }
-    TRACE( "(%s) %s -> %x\n", local ? "local" : "global", debugstr_a(str), atom );
-    return atom;
+    return !res;
 }
 
 
@@ -438,13 +402,29 @@
  */
 ATOM WINAPI GlobalAddAtomA( LPCSTR str /* [in] Pointer to string to add */ )
 {
-    return ATOM_AddAtomA( str, FALSE );
+    UNICODE_STRING wstr;
+    ATOM atom;
+
+    if(HIWORD(str))
+    {
+        if (!RtlCreateUnicodeStringFromAsciiz( &wstr, str )) {
+            SetLastError( ERROR_NOT_ENOUGH_MEMORY );
+            return 0;
+        }
+
+        atom = GlobalAddAtomW( wstr.Buffer );
+        RtlFreeUnicodeString( &wstr );
+    }
+    else 
+        atom = GlobalAddAtomW( (LPCWSTR)str );
+
+    return atom;
 }
 
 
 /***********************************************************************
  *           AddAtomA   (KERNEL32.@)
- * Adds a string to the atom table and returns the atom identifying the
+ * Adds a string to the local atom table and returns the atom identifying the
  * string.
  *
  * RETURNS
@@ -453,31 +433,23 @@
  */
 ATOM WINAPI AddAtomA( LPCSTR str /* [in] Pointer to string to add */ )
 {
-    return ATOM_AddAtomA( str, TRUE );
-}
+    UNICODE_STRING wstr;
+    ATOM atom;
 
-
-static ATOM ATOM_AddAtomW( LPCWSTR str, BOOL local )
-{
-    ATOM atom = 0;
-    if (!ATOM_IsIntAtomW( str, &atom ))
+    if(HIWORD(str))
     {
-        DWORD len = strlenW(str);
-        if (len > MAX_ATOM_LEN)
-        {
-            SetLastError( ERROR_INVALID_PARAMETER );
+        if (!RtlCreateUnicodeStringFromAsciiz( &wstr, str )) {
+            SetLastError( ERROR_NOT_ENOUGH_MEMORY );
             return 0;
         }
-        SERVER_START_REQ( add_atom )
-        {
-            req->local = local;
-            wine_server_add_data( req, str, len * sizeof(WCHAR) );
-            if (!wine_server_call_err(req)) atom = reply->atom;
-        }
-        SERVER_END_REQ;
+
+        atom = AddAtomW( wstr.Buffer );
+        RtlFreeUnicodeString( &wstr );
     }
-    TRACE( "(%s) %s -> %x\n", local ? "local" : "global", debugstr_w(str), atom );
+    else
+        atom = AddAtomW( (LPCWSTR)str );
     return atom;
+
 }
 
 
@@ -486,7 +458,17 @@
  */
 ATOM WINAPI GlobalAddAtomW( LPCWSTR str )
 {
-    return ATOM_AddAtomW( str, FALSE );
+    NTSTATUS res;
+    ATOM atom;
+
+    /* If a 0 atom is passed in, then we shouldn't set last error */
+    if (!str)
+        return 0;
+
+    if ((res = NtAddAtom( str, &atom )))
+        SetLastError( RtlNtStatusToDosError(res) );
+
+    return res ? 0 : atom;
 }
 
 
@@ -495,24 +477,15 @@
  */
 ATOM WINAPI AddAtomW( LPCWSTR str )
 {
-    return ATOM_AddAtomW( str, TRUE );
-}
+    NTSTATUS res;
+    ATOM atom;
 
+    if (!local_table || !InitAtomTable(0))
+        return 0;
 
-static ATOM ATOM_DeleteAtom( ATOM atom,  BOOL local)
-{
-    TRACE( "(%s) %x\n", local ? "local" : "global", atom );
-    if (atom >= MAXINTATOM)
-    {
-        SERVER_START_REQ( delete_atom )
-        {
-            req->atom = atom;
-            req->local = local;
-            wine_server_call_err( req );
-        }
-        SERVER_END_REQ;
-    }
-    return 0;
+    if ((res = RtlAddAtomToAtomTable(local_table, str, &atom)))
+        SetLastError( RtlNtStatusToDosError(res) );
+    return atom;
 }
 
 
@@ -527,7 +500,12 @@
  */
 ATOM WINAPI GlobalDeleteAtom( ATOM atom /* [in] Atom to delete */ )
 {
-    return ATOM_DeleteAtom( atom, FALSE);
+    NTSTATUS res;
+
+    if ((res = NtDeleteAtom(atom)))
+        SetLastError( RtlNtStatusToDosError(res) );
+
+    return res ? atom : 0;
 }
 
 
@@ -542,33 +520,15 @@
  */
 ATOM WINAPI DeleteAtom( ATOM atom /* [in] Atom to delete */ )
 {
-    return ATOM_DeleteAtom( atom, TRUE );
-}
+    NTSTATUS res;
 
+    if (!local_table || !InitAtomTable(0))
+        return atom;
 
-static ATOM ATOM_FindAtomA( LPCSTR str, BOOL local )
-{
-    ATOM atom = 0;
-    if (!ATOM_IsIntAtomA( str, &atom ))
-    {
-        WCHAR buffer[MAX_ATOM_LEN];
+    if((res = RtlDeleteAtomFromAtomTable(local_table, atom)))
+        SetLastError( RtlNtStatusToDosError(res) );
 
-        DWORD len = MultiByteToWideChar( CP_ACP, 0, str, strlen(str), buffer, MAX_ATOM_LEN );
-        if (!len)
-        {
-            SetLastError( ERROR_INVALID_PARAMETER );
-            return 0;
-        }
-        SERVER_START_REQ( find_atom )
-        {
-            req->local = local;
-            wine_server_add_data( req, buffer, len * sizeof(WCHAR) );
-            if (!wine_server_call_err(req)) atom = reply->atom;
-        }
-        SERVER_END_REQ;
-    }
-    TRACE( "(%s) %s -> %x\n", local ? "local" : "global", debugstr_a(str), atom );
-    return atom;
+    return res ? atom : 0;
 }
 
 
@@ -584,7 +544,17 @@
  */
 ATOM WINAPI GlobalFindAtomA( LPCSTR str /* [in] Pointer to string to search for */ )
 {
-    return ATOM_FindAtomA( str, FALSE );
+    UNICODE_STRING wstr;
+    ATOM atom;
+
+    if (!RtlCreateUnicodeStringFromAsciiz( &wstr, str )) {
+        SetLastError( ERROR_NOT_ENOUGH_MEMORY );
+        return 0;
+    }
+
+    atom = GlobalFindAtomW( wstr.Buffer );
+    RtlFreeUnicodeString( &wstr );
+    return atom;
 }
 
 /***********************************************************************
@@ -598,30 +568,16 @@
  */
 ATOM WINAPI FindAtomA( LPCSTR str /* [in] Pointer to string to find */ )
 {
-    return ATOM_FindAtomA( str, TRUE );
-}
-
+    UNICODE_STRING wstr;
+    ATOM atom;
 
-static ATOM ATOM_FindAtomW( LPCWSTR str, BOOL local )
-{
-    ATOM atom = 0;
-    if (!ATOM_IsIntAtomW( str, &atom ))
-    {
-        DWORD len = strlenW(str);
-        if (len > MAX_ATOM_LEN)
-        {
-            SetLastError( ERROR_INVALID_PARAMETER );
-            return 0;
-        }
-        SERVER_START_REQ( find_atom )
-        {
-            wine_server_add_data( req, str, len * sizeof(WCHAR) );
-            req->local = local;
-            if (!wine_server_call_err( req )) atom = reply->atom;
-        }
-        SERVER_END_REQ;
+    if (!RtlCreateUnicodeStringFromAsciiz( &wstr, str )) {
+        SetLastError( ERROR_NOT_ENOUGH_MEMORY );
+        return 0;
     }
-    TRACE( "(%s) %s -> %x\n", local ? "local" : "global", debugstr_w(str), atom );
+
+    atom = FindAtomW( wstr.Buffer );
+    RtlFreeUnicodeString( &wstr );
     return atom;
 }
 
@@ -631,7 +587,13 @@
  */
 ATOM WINAPI GlobalFindAtomW( LPCWSTR str )
 {
-    return ATOM_FindAtomW( str, FALSE );
+    NTSTATUS res;
+    ATOM atom;
+
+    if ((res = NtFindAtom( str, &atom )))
+        SetLastError( RtlNtStatusToDosError(res) );
+
+    return res ? 0 : atom;
 }
 
 
@@ -640,60 +602,16 @@
  */
 ATOM WINAPI FindAtomW( LPCWSTR str )
 {
-    return ATOM_FindAtomW( str, TRUE );
-}
-
-
-static UINT ATOM_GetAtomNameA( ATOM atom, LPSTR buffer, INT count, BOOL local )
-{
-    INT len;
+    NTSTATUS res;
+    ATOM atom;
 
-    if (count <= 0)
-    {
-        SetLastError( ERROR_MORE_DATA );
-        return 0;
-    }
-    if (atom < MAXINTATOM)
-    {
-        char name[8];
-        if (!atom)
-        {
-            SetLastError( ERROR_INVALID_PARAMETER );
-            return 0;
-        }
-        len = sprintf( name, "#%d", atom );
-        lstrcpynA( buffer, name, count );
-    }
-    else
-    {
-        WCHAR full_name[MAX_ATOM_LEN];
+    if (!local_table || !InitAtomTable(0))
+        return atom;
 
-        len = 0;
-        SERVER_START_REQ( get_atom_name )
-        {
-            req->atom = atom;
-            req->local = local;
-            wine_server_set_reply( req, full_name, sizeof(full_name) );
-            if (!wine_server_call_err( req ))
-            {
-                len = WideCharToMultiByte( CP_ACP, 0, full_name,
-                                           wine_server_reply_size(reply) / sizeof(WCHAR),
-                                           buffer, count - 1, NULL, NULL );
-                if (!len) len = count; /* overflow */
-                else buffer[len] = 0;
-            }
-        }
-        SERVER_END_REQ;
-    }
+    if ((res = RtlLookupAtomInAtomTable( local_table, str, &atom )))
+        SetLastError( RtlNtStatusToDosError(res) );
 
-    if (len && count <= len)
-    {
-        SetLastError( ERROR_MORE_DATA );
-        buffer[count-1] = 0;
-        return 0;
-    }
-    TRACE( "(%s) %x -> %s\n", local ? "local" : "global", atom, debugstr_a(buffer) );
-    return len;
+    return res ? 0 : atom;
 }
 
 
@@ -711,7 +629,27 @@
               LPSTR buffer, /* [out] Pointer to buffer for atom string */
               INT count )   /* [in]  Size of buffer */
 {
-    return ATOM_GetAtomNameA( atom, buffer, count, FALSE );
+    NTSTATUS res;
+    PATOM_BASIC_INFORMATION info;
+    ULONG len = MAX_ATOM_LEN * sizeof(WCHAR) + sizeof(ATOM_BASIC_INFORMATION);
+
+    /* Since WideCharToMultibyte returns to number of bytes required if dstlen
+     * is 0, we check for it here to avoid returning a wrong value */
+    if (!count)
+        return 0;
+
+    info = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len );
+
+    if ((res = NtQueryInformationAtom( atom, AtomBasicInformation, info, len, &len ))) {
+        SetLastError( RtlNtStatusToDosError(res) );
+        HeapFree( GetProcessHeap(), 0, info );
+        return 0;
+    }
+
+    len = WideCharToMultiByte( CP_ACP, 0, info->Name, -1, buffer, count, NULL, NULL ) - 1;
+    TRACE("Returning %ld\n", len);
+    HeapFree( GetProcessHeap(), 0, info );
+    return len;
 }
 
 
@@ -728,54 +666,19 @@
               LPSTR buffer, /* [out] Pointer to string for atom string */
               INT count)    /* [in]  Size of buffer */
 {
-    return ATOM_GetAtomNameA( atom, buffer, count, TRUE );
-}
-
+    NTSTATUS res;
+    WCHAR full_name[MAX_ATOM_LEN];
+    ULONG len = sizeof(WCHAR) * MAX_ATOM_LEN;
 
-static UINT ATOM_GetAtomNameW( ATOM atom, LPWSTR buffer, INT count, BOOL local )
-{
-    INT len;
+    if (!count)
+        return 0;
 
-    if (count <= 0)
-    {
-        SetLastError( ERROR_MORE_DATA );
+    if ((res = RtlQueryAtomInAtomTable( local_table, atom, NULL, NULL, full_name, &len))) {
+        SetLastError( RtlNtStatusToDosError(res) );
         return 0;
     }
-    if (atom < MAXINTATOM)
-    {
-        char name[8];
-        if (!atom)
-        {
-            SetLastError( ERROR_INVALID_PARAMETER );
-            return 0;
-        }
-        sprintf( name, "#%d", atom );
-        len = MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, count );
-        if (!len) buffer[count-1] = 0;  /* overflow */
-    }
-    else
-    {
-        WCHAR full_name[MAX_ATOM_LEN];
 
-        len = 0;
-        SERVER_START_REQ( get_atom_name )
-        {
-            req->atom = atom;
-            req->local = local;
-            wine_server_set_reply( req, full_name, sizeof(full_name) );
-            if (!wine_server_call_err( req ))
-            {
-                len = wine_server_reply_size(reply) / sizeof(WCHAR);
-                if (count > len) count = len + 1;
-                memcpy( buffer, full_name, (count-1) * sizeof(WCHAR) );
-                buffer[count-1] = 0;
-            }
-        }
-        SERVER_END_REQ;
-        if (!len) return 0;
-    }
-    TRACE( "(%s) %x -> %s\n", local ? "local" : "global", atom, debugstr_w(buffer) );
-    return len;
+    return WideCharToMultiByte( CP_ACP, 0, full_name, -1, buffer, count, NULL, NULL );
 }
 
 
@@ -784,7 +687,26 @@
  */
 UINT WINAPI GlobalGetAtomNameW( ATOM atom, LPWSTR buffer, INT count )
 {
-    return ATOM_GetAtomNameW( atom, buffer, count, FALSE);
+    NTSTATUS res;
+    PATOM_BASIC_INFORMATION info;
+    ULONG len = MAX_ATOM_LEN * sizeof(WCHAR) + sizeof(ATOM_BASIC_INFORMATION);
+
+    info = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len );
+
+    if ((res = NtQueryInformationAtom( atom, AtomBasicInformation, info, len, &len ))) {
+        SetLastError( RtlNtStatusToDosError(res) );
+        HeapFree( GetProcessHeap(), 0, info );
+        return 0;
+    }
+    if (info->NameLen > count) {
+        SetLastError( ERROR_BUFFER_OVERFLOW );
+        HeapFree( GetProcessHeap(), 0, info );
+        return 0;
+    }
+    strcpyW(buffer, info->Name);
+    len = info->NameLen;
+    HeapFree( GetProcessHeap(), 0, info );
+    return len;
 }
 
 
@@ -793,5 +715,20 @@
  */
 UINT WINAPI GetAtomNameW( ATOM atom, LPWSTR buffer, INT count )
 {
-    return ATOM_GetAtomNameW( atom, buffer, count, TRUE );
+    NTSTATUS res;
+    WCHAR full_name[MAX_ATOM_LEN];
+    ULONG len = sizeof(WCHAR) * MAX_ATOM_LEN;
+
+    if ((res = RtlQueryAtomInAtomTable( local_table, atom, NULL, NULL, full_name, &len))) {
+        SetLastError( RtlNtStatusToDosError(res) );
+        return 0;
+    }
+
+    if (len > count) {
+        SetLastError( ERROR_BUFFER_OVERFLOW );
+        return 0;
+    }
+    strcpyW( buffer, full_name );
+
+    return len;
 }



More information about the wine-patches mailing list