ReactOS 0.4.15-dev-7846-g8ba6c66
atom.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Kernel
3 * COPYRIGHT: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/ex/atom.c
5 * PURPOSE: Executive Atom Functions
6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
7 * Gunnar Dalsnes
8 */
9
10/* INCLUDES *****************************************************************/
11
12#include <ntoskrnl.h>
13#define NDEBUG
14#include <debug.h>
15
16/* GLOBALS ****************************************************************/
17
18/*
19 * FIXME: this is WRONG! The global atom table should live in the WinSta struct
20 * and accessed through a win32k callout (received in PsEstablishWin32Callouts)
21 * NOTE: There is a session/win32k global atom table also, but its private to
22 * win32k. Its used for RegisterWindowMessage() and for window classes.
23 * -Gunnar
24 */
26
27/* PRIVATE FUNCTIONS *********************************************************/
28
29/*++
30 * @name ExpGetGlobalAtomTable
31 *
32 * Gets pointer to a global atom table, creates it if not already created
33 *
34 * @return Pointer to the RTL_ATOM_TABLE, or NULL if it's impossible
35 * to create atom table
36 *
37 * @remarks Internal function
38 *
39 *--*/
43{
45
46 /* Return it if we have one */
48
49 /* Create it */
51
52 /* If we couldn't create it, return NULL */
53 if (!NT_SUCCESS(Status)) return NULL;
54
55 /* Return the newly created one */
56 return GlobalAtomTable;
57}
58
59/* FUNCTIONS ****************************************************************/
60
61/*++
62 * @name NtAddAtom
63 * @implemented
64 *
65 * Function NtAddAtom creates new Atom in Global Atom Table. If Atom
66 * with the same name already exist, internal Atom counter is incremented.
67 * See: http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/Atoms/NtAddAtom.html
68 *
69 * @param AtomName
70 * Atom name in Unicode
71 *
72 * @param AtomNameLength
73 * Length of the atom name
74 *
75 * @param Atom
76 * Pointer to RTL_ATOM
77 *
78 * @return STATUS_SUCCESS in case of success, proper error code
79 * otherwise.
80 *
81 * @remarks None
82 *
83 *--*/
87 IN ULONG AtomNameLength,
89{
93 LPWSTR CapturedName;
94 ULONG CapturedSize;
95 RTL_ATOM SafeAtom;
96 PAGED_CODE();
97
98 /* Check for the table */
99 if (AtomTable == NULL) return STATUS_ACCESS_DENIED;
100
101 /* Check for valid name */
102 if (AtomNameLength > (RTL_MAXIMUM_ATOM_LENGTH * sizeof(WCHAR)))
103 {
104 /* Fail */
105 DPRINT1("Atom name too long\n");
107 }
108
109 /* Check if we're called from user-mode or kernel-mode */
111 {
112 /* Re-use the given name if kernel mode */
113 CapturedName = AtomName;
114 }
115 else
116 {
117 /* Check if we have a name */
118 if (AtomName)
119 {
120 /* Allocate an aligned buffer + the null char */
121 CapturedSize = ((AtomNameLength + sizeof(WCHAR)) &
122 ~(sizeof(WCHAR) -1));
123 CapturedName = ExAllocatePoolWithTag(PagedPool,
124 CapturedSize,
125 TAG_ATOM);
126
127 if (!CapturedName)
128 {
129 /* Fail the call */
131 }
132
133 /* Enter SEH */
135 {
136 /* Probe the atom */
137 ProbeForRead(AtomName, AtomNameLength, sizeof(WCHAR));
138
139 /* Copy the name and null-terminate it */
140 RtlCopyMemory(CapturedName, AtomName, AtomNameLength);
141 CapturedName[AtomNameLength / sizeof(WCHAR)] = UNICODE_NULL;
142
143 /* Probe the atom too */
145 }
147 {
148 /* Return the exception code */
150 }
151 _SEH2_END;
152 }
153 else
154 {
155 /* No name */
156 CapturedName = NULL;
157 }
158 }
159
160 /* Call the runtime function */
161 Status = RtlAddAtomToAtomTable(AtomTable, CapturedName, &SafeAtom);
162 if (NT_SUCCESS(Status) && (Atom))
163 {
164 /* Success and caller wants the atom back.. .enter SEH */
166 {
167 /* Return the atom */
168 *Atom = SafeAtom;
169 }
171 {
172 /* Get the exception code */
174 }
175 _SEH2_END;
176 }
177
178 /* If we captured anything, free it */
179 if ((CapturedName != NULL) && (CapturedName != AtomName))
180 ExFreePoolWithTag(CapturedName, TAG_ATOM);
181
182 /* Return to caller */
183 return Status;
184}
185
186/*++
187 * @name NtDeleteAtom
188 * @implemented
189 *
190 * Removes Atom from Global Atom Table. If Atom's reference counter
191 * is greater then 1, function decrements this counter, but Atom
192 * stayed in Global Atom Table.
193 * See: http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/Atoms/NtDeleteAtom.html
194 *
195 * @param Atom
196 * Atom identifier
197 *
198 * @return STATUS_SUCCESS in case of success, proper error code
199 * otherwise.
200 *
201 * @remarks None
202 *
203 *--*/
205NTAPI
207{
209 PAGED_CODE();
210
211 /* Check for valid table */
212 if (AtomTable == NULL) return STATUS_ACCESS_DENIED;
213
214 /* Call worker function */
215 return RtlDeleteAtomFromAtomTable(AtomTable, Atom);
216}
217
218/*++
219 * @name NtFindAtom
220 * @implemented
221 *
222 * Retrieves existing Atom's identifier without incrementing Atom's
223 * internal counter
224 * See: http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/Atoms/NtFindAtom.html
225 *
226 * @param AtomName
227 * Atom name in Unicode
228 *
229 * @param AtomNameLength
230 * Length of the atom name
231 *
232 * @param Atom
233 * Pointer to RTL_ATOM
234 *
235 * @return STATUS_SUCCESS in case of success, proper error code
236 * otherwise.
237 *
238 * @remarks None
239 *
240 *--*/
242NTAPI
244 IN ULONG AtomNameLength,
246{
250 _SEH2_VOLATILE LPWSTR CapturedName;
251 ULONG CapturedSize;
252 RTL_ATOM SafeAtom;
253 PAGED_CODE();
254
255 /* Check for the table */
256 if (AtomTable == NULL) return STATUS_ACCESS_DENIED;
257
258 /* Check for valid name */
259 if (AtomNameLength > (RTL_MAXIMUM_ATOM_LENGTH * sizeof(WCHAR)))
260 {
261 /* Fail */
262 DPRINT1("Atom name too long\n");
264 }
265
266 /* Re-use the given name if kernel mode or no atom name */
267 CapturedName = AtomName;
268
269 /* Check if we're called from user-mode*/
271 {
272 /* Enter SEH */
274 {
275 /* Check if we have a name */
276 if (AtomName)
277 {
278 /* Probe the atom */
279 ProbeForRead(AtomName, AtomNameLength, sizeof(WCHAR));
280
281 /* Allocate an aligned buffer + the null char */
282 CapturedSize = ((AtomNameLength + sizeof(WCHAR)) &~
283 (sizeof(WCHAR) -1));
285 CapturedSize,
286 TAG_ATOM);
287 /* Copy the name and null-terminate it */
288 RtlCopyMemory(CapturedName, AtomName, AtomNameLength);
289 CapturedName[AtomNameLength / sizeof(WCHAR)] = UNICODE_NULL;
290
291 /* Probe the atom too */
293 }
294 }
296 {
297 if (CapturedName != AtomName)
298 {
299 ExFreePoolWithTag(CapturedName, TAG_ATOM);
300 }
301
302 /* Return the exception code */
304 }
305 _SEH2_END;
306 }
307
308 /* Call the runtime function */
309 Status = RtlLookupAtomInAtomTable(AtomTable, CapturedName, &SafeAtom);
310 if (NT_SUCCESS(Status) && (Atom))
311 {
312 /* Success and caller wants the atom back... enter SEH */
314 {
315 /* Return the atom */
316 *Atom = SafeAtom;
317 }
319 {
321 }
322 _SEH2_END;
323 }
324
325 /* If we captured anything, free it */
326 if ((CapturedName) && (CapturedName != AtomName))
327 ExFreePoolWithTag(CapturedName, TAG_ATOM);
328
329 /* Return to caller */
330 return Status;
331}
332
333/*++
334 * @name NtQueryInformationAtom
335 * @implemented
336 *
337 * Gets single Atom properties or reads Global Atom Table
338 * See: http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/Atoms/NtQueryInformationAtom.html
339 *
340 * @param Atom
341 * Atom to query. If AtomInformationClass parameter is
342 * AtomTableInformation, Atom parameter is not used.
343 *
344 * @param AtomInformationClass
345 * See ATOM_INFORMATION_CLASS enumeration type for details
346 *
347 * @param AtomInformation
348 * Result of call - pointer to user's allocated buffer for data
349 *
350 * @param AtomInformationLength
351 * Size of AtomInformation buffer, in bytes
352 *
353 * @param ReturnLength
354 * Pointer to ULONG value containing required AtomInformation
355 * buffer size
356 *
357 * @return STATUS_SUCCESS in case of success, proper error code
358 * otherwise.
359 *
360 * @remarks None
361 *
362 *--*/
364NTAPI
366 ATOM_INFORMATION_CLASS AtomInformationClass,
367 PVOID AtomInformation,
368 ULONG AtomInformationLength,
370{
372 PATOM_BASIC_INFORMATION BasicInformation = AtomInformation;
373 PATOM_TABLE_INFORMATION TableInformation = AtomInformation;
375 ULONG Flags, UsageCount, NameLength, RequiredLength = 0;
377
378 PAGED_CODE();
379
380 /* Check for valid table */
381 if (AtomTable == NULL) return STATUS_ACCESS_DENIED;
382
384
386 {
387 /* Probe the parameters */
389 {
390 ProbeForWrite(AtomInformation,
391 AtomInformationLength,
392 sizeof(ULONG));
393
394 if (ReturnLength != NULL)
395 {
397 }
398 }
399
400 /* Choose class */
401 switch (AtomInformationClass)
402 {
403 /* Caller requested info about an atom */
405
406 /* Size check */
408 if (RequiredLength > AtomInformationLength)
409 {
410 /* Fail */
411 DPRINT1("Buffer too small\n");
414 }
415
416 /* Prepare query */
417 UsageCount = 0;
418 NameLength = AtomInformationLength - RequiredLength;
419 BasicInformation->Name[0] = UNICODE_NULL;
420
421 /* Query the data */
423 Atom,
424 &UsageCount,
425 &Flags,
426 BasicInformation->Name,
427 &NameLength);
428 if (NT_SUCCESS(Status))
429 {
430 /* Return data */
431 BasicInformation->UsageCount = (USHORT)UsageCount;
432 BasicInformation->Flags = (USHORT)Flags;
433 BasicInformation->NameLength = (USHORT)NameLength;
434 RequiredLength += NameLength + sizeof(WCHAR);
435 }
436 break;
437
438 /* Caller requested info about an Atom Table */
440
441 /* Size check */
443 if (RequiredLength > AtomInformationLength)
444 {
445 /* Fail */
446 DPRINT1("Buffer too small\n");
449 }
450
451 /* Query the data */
453 (AtomInformationLength - RequiredLength) /
454 sizeof(RTL_ATOM),
455 &TableInformation->NumberOfAtoms,
456 TableInformation->Atoms);
457 if (NT_SUCCESS(Status))
458 {
459 /* Update the return length */
460 RequiredLength += TableInformation->NumberOfAtoms * sizeof(RTL_ATOM);
461 }
462 break;
463
464 /* Caller was on crack */
465 default:
466
467 /* Unrecognized class */
469 break;
470 }
471
472 /* Return the required size */
473 if (ReturnLength != NULL)
474 {
476 }
477 }
479 {
481 }
482 _SEH2_END;
483
484 /* Return to caller */
485 return Status;
486}
487
488/* EOF */
#define PAGED_CODE()
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
_Out_ RTL_ATOM * Atom
Definition: class.h:54
#define NULL
Definition: types.h:112
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
IN CINT OUT PVOID IN ULONG OUT PULONG ReturnLength
Definition: dumpinfo.c:43
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define PagedPool
Definition: env_spec_w32.h:308
#define ExGetPreviousMode
Definition: ex.h:140
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
#define _SEH2_LEAVE
Definition: filesup.c:20
Status
Definition: gdiplustypes.h:25
LONG NTAPI ExSystemExceptionFilter(VOID)
Definition: harderr.c:349
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
unsigned short RTL_ATOM
Definition: atom.c:42
unsigned short * PRTL_ATOM
Definition: atom.c:42
struct atom_table ** PRTL_ATOM_TABLE
Definition: atom.c:43
#define KernelMode
Definition: asm.h:34
enum _ATOM_INFORMATION_CLASS ATOM_INFORMATION_CLASS
@ AtomBasicInformation
Definition: extypes.h:332
@ AtomTableInformation
Definition: extypes.h:333
NTSYSAPI NTSTATUS NTAPI RtlAddAtomToAtomTable(_In_ PRTL_ATOM_TABLE AtomTable, _In_ PWSTR AtomName, _Out_ PRTL_ATOM Atom)
NTSYSAPI NTSTATUS NTAPI RtlLookupAtomInAtomTable(_In_ PRTL_ATOM_TABLE AtomTable, _In_ PWSTR AtomName, _Out_ PRTL_ATOM Atom)
NTSYSAPI NTSTATUS NTAPI RtlCreateAtomTable(_In_ ULONG TableSize, _Inout_ PRTL_ATOM_TABLE *AtomTable)
NTSYSAPI NTSTATUS NTAPI RtlDeleteAtomFromAtomTable(_In_ PRTL_ATOM_TABLE AtomTable, _In_ RTL_ATOM Atom)
NTSYSAPI NTSTATUS NTAPI RtlQueryAtomInAtomTable(_In_ PRTL_ATOM_TABLE AtomTable, _In_ RTL_ATOM Atom, _Out_opt_ PULONG RefCount, _Out_opt_ PULONG PinCount, _Out_opt_z_bytecap_(*NameLength) PWSTR AtomName, _Inout_opt_ PULONG NameLength)
#define RTL_MAXIMUM_ATOM_LENGTH
Definition: rtltypes.h:36
#define UNICODE_NULL
NTSTATUS NTAPI NtQueryInformationAtom(RTL_ATOM Atom, ATOM_INFORMATION_CLASS AtomInformationClass, PVOID AtomInformation, ULONG AtomInformationLength, PULONG ReturnLength)
Definition: atom.c:365
PRTL_ATOM_TABLE GlobalAtomTable
Definition: atom.c:25
PRTL_ATOM_TABLE NTAPI ExpGetGlobalAtomTable(VOID)
Definition: atom.c:42
NTSTATUS NTAPI NtDeleteAtom(IN RTL_ATOM Atom)
Definition: atom.c:206
NTSTATUS NTAPI NtAddAtom(IN PWSTR AtomName, IN ULONG AtomNameLength, OUT PRTL_ATOM Atom)
Definition: atom.c:86
NTSTATUS NTAPI NtFindAtom(IN PWSTR AtomName, IN ULONG AtomNameLength, OUT PRTL_ATOM Atom)
Definition: atom.c:243
NTSTATUS NTAPI RtlQueryAtomListInAtomTable(IN PRTL_ATOM_TABLE AtomTable, IN ULONG MaxAtomCount, OUT ULONG *AtomCount, OUT RTL_ATOM *AtomList)
Definition: atom.c:704
#define STATUS_INVALID_INFO_CLASS
Definition: ntstatus.h:240
unsigned short USHORT
Definition: pedump.c:61
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
#define _SEH2_VOLATILE
Definition: pseh2_64.h:163
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:162
#define ProbeForWriteUshort(Ptr)
Definition: probe.h:34
#define ProbeForWriteUlong(Ptr)
Definition: probe.h:36
#define STATUS_SUCCESS
Definition: shellext.h:65
#define TAG_ATOM
Definition: tag.h:29
uint16_t * PWSTR
Definition: typedefs.h:56
uint32_t * PULONG
Definition: typedefs.h:59
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define NTAPI
Definition: typedefs.h:36
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ ULONG _Out_opt_ PULONG RequiredLength
Definition: wmifuncs.h:30
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define ExAllocatePoolWithQuotaTag(a, b, c)
Definition: exfuncs.h:530
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184