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.
--- ../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 */ -@REQ(get_atom_name) - atom_t atom; /* atom handle */ - int local; /* is atom in local process table? */ +/* Get info about a global atom */ +@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 */ -@REQ(init_atom_table) +/* Create an atom table */ +@REQ(create_atom_table) int entries; /* number of entries */ +@REPLY + void* table; /* The atom table */ +@END + + +/* Destroy an atom table */ +@REQ(destroy_atom_table) + void* table; /* The atom table */ +@END + + +/* Empty an atom table */ +@REQ(empty_atom_table) + void* table; /* The atom table */ + int delpinned; /* Also delete pinned atoms ? */ +@END + + +/* Add an atom to an atom table */ +@REQ(add_atom_to_atom_table) + void* table; /* The atom table to add this entry to */ + VARARG(name,unicode_str); /* atom name */ +@REPLY + atom_t atom; /* The atom */ +@END + + +/* Delete an atom from an atom table */ +@REQ(delete_atom_from_atom_table) + void* table; /* The atom table to delete this atom from */ + atom_t atom; /* Atom to delete */ +@END + + +/* Find an atom in an atom table */ +@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 */ +@REPLY + atom_t atom; /* The corrisponding atom */ +@END + + +/* Pin an atom in an atom table */ +@REQ(pin_atom_in_atom_table) + void* table; /* The table to pin the atom in */ + atom_t atom; /* The atom to pin */ +@END + + +/* Query an atom in an atom table */ +@REQ(query_atom_in_atom_table) + void* table; /* The table to query the atom from */ + atom_t atom; /* The atom to query */ +@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 ? ¤t->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; }