2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/kernel32/misc/atom.c
5 * PURPOSE: Atom functions
6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
9 /* INCLUDES ******************************************************************/
13 #include "../include/debug.h"
15 /* GLOBALS *******************************************************************/
17 PRTL_ATOM_TABLE BaseLocalAtomTable
= NULL
;
19 /* FUNCTIONS *****************************************************************/
23 InternalInitAtomTable(VOID
)
25 /* Create or return the local table */
26 if (!BaseLocalAtomTable
) RtlCreateAtomTable(0, &BaseLocalAtomTable
);
27 return BaseLocalAtomTable
;
32 InternalAddAtom(BOOLEAN Local
,
37 ANSI_STRING AnsiString
;
38 UNICODE_STRING UnicodeString
;
39 PUNICODE_STRING AtomNameString
;
40 ATOM Atom
= INVALID_ATOM
;
42 /* Check if it's an integer atom */
43 if ((ULONG_PTR
)AtomName
<= 0xFFFF)
45 /* Convert the name to an atom */
46 Atom
= (ATOM
)PtrToShort((PVOID
)AtomName
);
47 if (Atom
>= MAXINTATOM
)
49 /* Fail, atom number too large */
50 SetLastErrorByStatus(STATUS_INVALID_PARAMETER
);
59 /* Check if this is a unicode atom */
62 /* Use a unicode string */
63 AtomNameString
= &UnicodeString
;
64 RtlInitUnicodeString(AtomNameString
, (LPWSTR
)AtomName
);
65 Status
= STATUS_SUCCESS
;
69 /* Use an ansi string */
70 RtlInitAnsiString(&AnsiString
, AtomName
);
72 /* Check if we can abuse the TEB */
73 if (AnsiString
.MaximumLength
> 260)
75 /* We can't, allocate a new string */
76 AtomNameString
= &UnicodeString
;
77 Status
= RtlAnsiStringToUnicodeString(AtomNameString
,
83 /* We can! Use the TEB */
84 AtomNameString
= &NtCurrentTeb()->StaticUnicodeString
;
85 Status
= RtlAnsiStringToUnicodeString(AtomNameString
,
91 /* Check for failure */
92 if (!NT_SUCCESS(Status
))
94 SetLastErrorByStatus(Status
);
99 /* Check if we're doing local add */
103 Status
= RtlAddAtomToAtomTable(InternalInitAtomTable(),
104 AtomNameString
->Buffer
,
109 /* Do a global add */
110 Status
= NtAddAtom(AtomNameString
->Buffer
,
111 AtomNameString
->Length
,
115 /* Check for failure */
116 if (!NT_SUCCESS(Status
)) SetLastErrorByStatus(Status
);
118 /* Check if we were non-static ANSI */
119 if (!(Unicode
) && (AtomNameString
== &UnicodeString
))
121 /* Free the allocated buffer */
122 RtlFreeUnicodeString(AtomNameString
);
125 /* Return the atom */
131 InternalFindAtom(BOOLEAN Local
,
136 ANSI_STRING AnsiString
;
137 UNICODE_STRING UnicodeString
;
138 PUNICODE_STRING AtomNameString
;
139 ATOM Atom
= INVALID_ATOM
;
141 /* Check if it's an integer atom */
142 if ((ULONG_PTR
)AtomName
<= 0xFFFF)
144 /* Convert the name to an atom */
145 Atom
= (ATOM
)PtrToShort((PVOID
)AtomName
);
146 if (Atom
>= MAXINTATOM
)
148 /* Fail, atom number too large */
149 SetLastErrorByStatus(STATUS_INVALID_PARAMETER
);
150 DPRINT1("Invalid atom\n");
158 /* Check if this is a unicode atom */
161 /* Use a unicode string */
162 AtomNameString
= &UnicodeString
;
163 RtlInitUnicodeString(AtomNameString
, (LPWSTR
)AtomName
);
164 Status
= STATUS_SUCCESS
;
168 /* Use an ansi string */
169 RtlInitAnsiString(&AnsiString
, AtomName
);
171 /* Check if we can abuse the TEB */
172 if (AnsiString
.MaximumLength
> 260)
174 /* We can't, allocate a new string */
175 AtomNameString
= &UnicodeString
;
176 Status
= RtlAnsiStringToUnicodeString(AtomNameString
,
182 /* We can! Use the TEB */
183 AtomNameString
= &NtCurrentTeb()->StaticUnicodeString
;
184 Status
= RtlAnsiStringToUnicodeString(AtomNameString
,
190 /* Check for failure */
191 if (!NT_SUCCESS(Status
))
194 SetLastErrorByStatus(Status
);
199 /* Check if we're doing local lookup */
202 /* Do a local lookup */
203 Status
= RtlLookupAtomInAtomTable(InternalInitAtomTable(),
204 AtomNameString
->Buffer
,
209 /* Do a global search */
210 if (!AtomNameString
->Length
)
212 /* This is illegal in win32 */
213 DPRINT1("No name given\n");
214 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
218 /* Call the global function */
219 Status
= NtFindAtom(AtomNameString
->Buffer
,
220 AtomNameString
->Length
,
225 /* Check for failure */
226 if (!NT_SUCCESS(Status
)) SetLastErrorByStatus(Status
);
228 /* Check if we were non-static ANSI */
229 if (!(Unicode
) && (AtomNameString
== &UnicodeString
))
231 /* Free the allocated buffer */
232 RtlFreeUnicodeString(AtomNameString
);
235 /* Return the atom */
241 InternalDeleteAtom(BOOLEAN Local
,
247 if (Atom
>= MAXINTATOM
)
249 /* Check if it's a local delete */
252 /* Delete it locally */
253 Status
= RtlDeleteAtomFromAtomTable(InternalInitAtomTable(), Atom
);
257 /* Delete it globall */
258 Status
= NtDeleteAtom(Atom
);
261 /* Check for success */
262 if (!NT_SUCCESS(Status
))
265 SetLastErrorByStatus(Status
);
276 InternalGetAtomName(BOOLEAN Local
,
284 ANSI_STRING AnsiString
;
285 UNICODE_STRING UnicodeString
;
286 PVOID TempBuffer
= NULL
;
287 PWSTR AtomNameString
;
288 ULONG AtomInfoLength
;
289 ULONG AtomNameLength
;
290 PATOM_BASIC_INFORMATION AtomInfo
;
292 /* Normalize the size as not to overflow */
293 if (!Unicode
&& Size
> 0x7000) Size
= 0x7000;
295 /* Make sure it's valid too */
298 SetLastErrorByStatus(STATUS_BUFFER_OVERFLOW
);
302 /* Check if this is a global query */
305 /* Set the query length */
306 AtomNameLength
= Size
* sizeof(WCHAR
);
308 /* If it's unicode, just keep the name */
311 AtomNameString
= (PWSTR
)AtomName
;
315 /* Allocate memory for the ansi buffer */
316 TempBuffer
= RtlAllocateHeap(RtlGetProcessHeap(),
319 AtomNameString
= TempBuffer
;
323 Status
= RtlQueryAtomInAtomTable(InternalInitAtomTable(),
332 /* We're going to do a global query, so allocate a buffer */
333 AtomInfoLength
= sizeof(ATOM_BASIC_INFORMATION
) +
334 (Size
* sizeof(WCHAR
));
335 AtomInfo
= TempBuffer
= RtlAllocateHeap(RtlGetProcessHeap(),
340 Status
= NtQueryInformationAtom(Atom
,
341 AtomBasicInformation
,
345 if (NT_SUCCESS(Status
))
347 /* Success. Update the length and get the name */
348 AtomNameLength
= (ULONG
)AtomInfo
->NameLength
;
349 AtomNameString
= AtomInfo
->Name
;
353 /* Check for global success */
354 if (NT_SUCCESS(Status
))
356 /* Check if it was unicode */
359 /* We return the length in chars */
360 RetVal
= AtomNameLength
/ sizeof(WCHAR
);
362 /* Copy the memory if this was a global query */
363 if (AtomNameString
!= (PWSTR
)AtomName
)
365 RtlMoveMemory(AtomName
, AtomNameString
, AtomNameLength
);
368 /* And null-terminate it if the buffer was too large */
371 ((PWCHAR
)AtomName
)[RetVal
] = UNICODE_NULL
;
376 /* First create a unicode string with our data */
377 UnicodeString
.Buffer
= AtomNameString
;
378 UnicodeString
.Length
= (USHORT
)AtomNameLength
;
379 UnicodeString
.MaximumLength
= (USHORT
)(UnicodeString
.Length
+
382 /* Now prepare an ansi string for conversion */
383 AnsiString
.Buffer
= AtomName
;
384 AnsiString
.Length
= 0;
385 AnsiString
.MaximumLength
= (USHORT
)Size
;
388 Status
= RtlUnicodeStringToAnsiString(&AnsiString
,
392 /* Return the length */
393 if (NT_SUCCESS(Status
)) RetVal
= AnsiString
.Length
;
397 /* Free the temporary buffer if we have one */
398 if (TempBuffer
) RtlFreeHeap(RtlGetProcessHeap(), 0, TempBuffer
);
400 /* Check for failure */
401 if (!NT_SUCCESS(Status
))
404 DPRINT1("Failed: %lx\n", Status
);
405 SetLastErrorByStatus(Status
);
412 /* FUNCTIONS *****************************************************************/
419 GlobalAddAtomA(LPCSTR lpString
)
421 return InternalAddAtom(FALSE
, FALSE
, lpString
);
429 GlobalAddAtomW(LPCWSTR lpString
)
431 return InternalAddAtom(FALSE
, TRUE
, (LPSTR
)lpString
);
439 GlobalDeleteAtom(ATOM nAtom
)
441 return InternalDeleteAtom(FALSE
, nAtom
);
449 GlobalFindAtomA(LPCSTR lpString
)
451 return InternalFindAtom(FALSE
, FALSE
, lpString
);
459 GlobalFindAtomW(LPCWSTR lpString
)
461 return InternalFindAtom(FALSE
, TRUE
, (LPSTR
)lpString
);
469 GlobalGetAtomNameA(ATOM nAtom
,
473 return InternalGetAtomName(FALSE
, FALSE
, nAtom
, lpBuffer
, (DWORD
)nSize
);
481 GlobalGetAtomNameW(ATOM nAtom
,
485 return InternalGetAtomName(FALSE
,
497 InitAtomTable(DWORD nSize
)
500 if (nSize
< 4 || nSize
> 511) nSize
= 37;
503 return NT_SUCCESS(RtlCreateAtomTable(nSize
, &BaseLocalAtomTable
));
511 AddAtomA(LPCSTR lpString
)
513 return InternalAddAtom(TRUE
, FALSE
, lpString
);
521 AddAtomW(LPCWSTR lpString
)
523 return InternalAddAtom(TRUE
, TRUE
, (LPSTR
)lpString
);
531 DeleteAtom(ATOM nAtom
)
533 return InternalDeleteAtom(TRUE
, nAtom
);
541 FindAtomA(LPCSTR lpString
)
543 return InternalFindAtom(TRUE
, FALSE
, lpString
);
551 FindAtomW(LPCWSTR lpString
)
553 return InternalFindAtom(TRUE
, TRUE
, (LPSTR
)lpString
);
562 GetAtomNameA(ATOM nAtom
,
566 return InternalGetAtomName(TRUE
, FALSE
, nAtom
, lpBuffer
, (DWORD
)nSize
);
574 GetAtomNameW(ATOM nAtom
,
578 return InternalGetAtomName(TRUE
,