2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: dll/win32/kernel32/client/atom.c
5 * PURPOSE: Atom functions
6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
9 /* INCLUDES ******************************************************************/
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 BaseSetLastNTError(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! Get the TEB String */
84 AtomNameString
= &NtCurrentTeb()->StaticUnicodeString
;
86 /* Convert it into the TEB */
87 Status
= RtlAnsiStringToUnicodeString(AtomNameString
,
93 /* Check for failure */
94 if (!NT_SUCCESS(Status
))
96 BaseSetLastNTError(Status
);
101 /* Check if we're doing local add */
105 Status
= RtlAddAtomToAtomTable(InternalInitAtomTable(),
106 AtomNameString
->Buffer
,
111 /* Do a global add */
112 Status
= NtAddAtom(AtomNameString
->Buffer
,
113 AtomNameString
->Length
,
117 /* Check for failure */
118 if (!NT_SUCCESS(Status
)) BaseSetLastNTError(Status
);
120 /* Check if we were non-static ANSI */
121 if (!(Unicode
) && (AtomNameString
== &UnicodeString
))
123 /* Free the allocated buffer */
124 RtlFreeUnicodeString(AtomNameString
);
127 /* Return the atom */
133 InternalFindAtom(BOOLEAN Local
,
138 ANSI_STRING AnsiString
;
139 UNICODE_STRING UnicodeString
;
140 PUNICODE_STRING AtomNameString
;
141 ATOM Atom
= INVALID_ATOM
;
143 /* Check if it's an integer atom */
144 if ((ULONG_PTR
)AtomName
<= 0xFFFF)
146 /* Convert the name to an atom */
147 Atom
= (ATOM
)PtrToShort((PVOID
)AtomName
);
148 if (Atom
>= MAXINTATOM
)
150 /* Fail, atom number too large */
151 BaseSetLastNTError(STATUS_INVALID_PARAMETER
);
152 DPRINT1("Invalid atom\n");
160 /* Check if this is a unicode atom */
163 /* Use a unicode string */
164 AtomNameString
= &UnicodeString
;
165 RtlInitUnicodeString(AtomNameString
, (LPWSTR
)AtomName
);
166 Status
= STATUS_SUCCESS
;
170 /* Use an ansi string */
171 RtlInitAnsiString(&AnsiString
, AtomName
);
173 /* Check if we can abuse the TEB */
174 if (AnsiString
.MaximumLength
> 260)
176 /* We can't, allocate a new string */
177 AtomNameString
= &UnicodeString
;
178 Status
= RtlAnsiStringToUnicodeString(AtomNameString
,
184 /* We can! Get the TEB String */
185 AtomNameString
= &NtCurrentTeb()->StaticUnicodeString
;
187 /* Convert it into the TEB */
188 Status
= RtlAnsiStringToUnicodeString(AtomNameString
,
194 /* Check for failure */
195 if (!NT_SUCCESS(Status
))
198 BaseSetLastNTError(Status
);
203 /* Check if we're doing local lookup */
206 /* Do a local lookup */
207 Status
= RtlLookupAtomInAtomTable(InternalInitAtomTable(),
208 AtomNameString
->Buffer
,
213 /* Do a global search */
214 if (!AtomNameString
->Length
)
216 /* This is illegal in win32 */
217 DPRINT1("No name given\n");
218 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
222 /* Call the global function */
223 Status
= NtFindAtom(AtomNameString
->Buffer
,
224 AtomNameString
->Length
,
229 /* Check for failure */
230 if (!NT_SUCCESS(Status
)) BaseSetLastNTError(Status
);
232 /* Check if we were non-static ANSI */
233 if (!(Unicode
) && (AtomNameString
== &UnicodeString
))
235 /* Free the allocated buffer */
236 RtlFreeUnicodeString(AtomNameString
);
239 /* Return the atom */
245 InternalDeleteAtom(BOOLEAN Local
,
251 if (Atom
>= MAXINTATOM
)
253 /* Check if it's a local delete */
256 /* Delete it locally */
257 Status
= RtlDeleteAtomFromAtomTable(InternalInitAtomTable(), Atom
);
261 /* Delete it globall */
262 Status
= NtDeleteAtom(Atom
);
265 /* Check for success */
266 if (!NT_SUCCESS(Status
))
269 BaseSetLastNTError(Status
);
280 InternalGetAtomName(BOOLEAN Local
,
288 ANSI_STRING AnsiString
;
289 UNICODE_STRING UnicodeString
;
290 PVOID TempBuffer
= NULL
;
291 PWSTR AtomNameString
;
292 ULONG AtomInfoLength
;
293 ULONG AtomNameLength
;
294 PATOM_BASIC_INFORMATION AtomInfo
;
296 /* Normalize the size as not to overflow */
297 if (!Unicode
&& Size
> 0x7000) Size
= 0x7000;
299 /* Make sure it's valid too */
302 BaseSetLastNTError(STATUS_BUFFER_OVERFLOW
);
307 BaseSetLastNTError(STATUS_INVALID_PARAMETER
);
311 /* Check if this is a global query */
314 /* Set the query length */
315 AtomNameLength
= Size
* sizeof(WCHAR
);
317 /* If it's unicode, just keep the name */
320 AtomNameString
= (PWSTR
)AtomName
;
324 /* Allocate memory for the ansi buffer */
325 TempBuffer
= RtlAllocateHeap(RtlGetProcessHeap(),
328 AtomNameString
= TempBuffer
;
332 Status
= RtlQueryAtomInAtomTable(InternalInitAtomTable(),
341 /* We're going to do a global query, so allocate a buffer */
342 AtomInfoLength
= sizeof(ATOM_BASIC_INFORMATION
) +
343 (Size
* sizeof(WCHAR
));
344 AtomInfo
= TempBuffer
= RtlAllocateHeap(RtlGetProcessHeap(),
350 BaseSetLastNTError(STATUS_NO_MEMORY
);
355 Status
= NtQueryInformationAtom(Atom
,
356 AtomBasicInformation
,
360 if (NT_SUCCESS(Status
))
362 /* Success. Update the length and get the name */
363 AtomNameLength
= (ULONG
)AtomInfo
->NameLength
;
364 AtomNameString
= AtomInfo
->Name
;
368 /* Check for global success */
369 if (NT_SUCCESS(Status
))
371 /* Check if it was unicode */
374 /* We return the length in chars */
375 RetVal
= AtomNameLength
/ sizeof(WCHAR
);
377 /* Copy the memory if this was a global query */
378 if (AtomNameString
!= (PWSTR
)AtomName
)
380 RtlMoveMemory(AtomName
, AtomNameString
, AtomNameLength
);
383 /* And null-terminate it if the buffer was too large */
386 ((PWCHAR
)AtomName
)[RetVal
] = UNICODE_NULL
;
391 /* First create a unicode string with our data */
392 UnicodeString
.Buffer
= AtomNameString
;
393 UnicodeString
.Length
= (USHORT
)AtomNameLength
;
394 UnicodeString
.MaximumLength
= (USHORT
)(UnicodeString
.Length
+
397 /* Now prepare an ansi string for conversion */
398 AnsiString
.Buffer
= AtomName
;
399 AnsiString
.Length
= 0;
400 AnsiString
.MaximumLength
= (USHORT
)Size
;
403 Status
= RtlUnicodeStringToAnsiString(&AnsiString
,
407 /* Return the length */
408 if (NT_SUCCESS(Status
)) RetVal
= AnsiString
.Length
;
412 /* Free the temporary buffer if we have one */
413 if (TempBuffer
) RtlFreeHeap(RtlGetProcessHeap(), 0, TempBuffer
);
415 /* Check for failure */
416 if (!NT_SUCCESS(Status
))
419 DPRINT("Failed: %lx\n", Status
);
420 BaseSetLastNTError(Status
);
427 /* FUNCTIONS *****************************************************************/
434 GlobalAddAtomA(LPCSTR lpString
)
436 return InternalAddAtom(FALSE
, FALSE
, lpString
);
444 GlobalAddAtomW(LPCWSTR lpString
)
446 return InternalAddAtom(FALSE
, TRUE
, (LPSTR
)lpString
);
454 GlobalDeleteAtom(ATOM nAtom
)
456 return InternalDeleteAtom(FALSE
, nAtom
);
464 GlobalFindAtomA(LPCSTR lpString
)
466 return InternalFindAtom(FALSE
, FALSE
, lpString
);
474 GlobalFindAtomW(LPCWSTR lpString
)
476 return InternalFindAtom(FALSE
, TRUE
, (LPSTR
)lpString
);
484 GlobalGetAtomNameA(ATOM nAtom
,
488 return InternalGetAtomName(FALSE
, FALSE
, nAtom
, lpBuffer
, (DWORD
)nSize
);
496 GlobalGetAtomNameW(ATOM nAtom
,
500 return InternalGetAtomName(FALSE
,
512 InitAtomTable(DWORD nSize
)
515 if (nSize
< 4 || nSize
> 511) nSize
= 37;
518 return NT_SUCCESS(RtlCreateAtomTable(nSize
, &BaseLocalAtomTable
));
526 AddAtomA(LPCSTR lpString
)
528 return InternalAddAtom(TRUE
, FALSE
, lpString
);
536 AddAtomW(LPCWSTR lpString
)
538 return InternalAddAtom(TRUE
, TRUE
, (LPSTR
)lpString
);
546 DeleteAtom(ATOM nAtom
)
548 return InternalDeleteAtom(TRUE
, nAtom
);
556 FindAtomA(LPCSTR lpString
)
558 return InternalFindAtom(TRUE
, FALSE
, lpString
);
566 FindAtomW(LPCWSTR lpString
)
568 return InternalFindAtom(TRUE
, TRUE
, (LPSTR
)lpString
);
577 GetAtomNameA(ATOM nAtom
,
581 return InternalGetAtomName(TRUE
, FALSE
, nAtom
, lpBuffer
, (DWORD
)nSize
);
589 GetAtomNameW(ATOM nAtom
,
593 return InternalGetAtomName(TRUE
,