2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ex/atom.c
5 * PURPOSE: Executive Atom Functions
6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
10 /* INCLUDES *****************************************************************/
14 #include <internal/debug.h>
16 #define TAG_ATOM TAG('A', 't', 'o', 'm')
18 /* GLOBALS ****************************************************************/
21 * FIXME: this is WRONG! The global atom table should live in the WinSta struct
22 * and accessed through a win32k callout (received in PsEstablishWin32Callouts)
23 * NOTE: There is a session/win32k global atom table also, but its private to
24 * win32k. Its used for RegisterWindowMessage() and for window classes.
27 PRTL_ATOM_TABLE GlobalAtomTable
;
29 /* PRIVATE FUNCTIONS *********************************************************/
33 ExpGetGlobalAtomTable(VOID
)
37 /* Return it if we have one */
38 if (GlobalAtomTable
) return GlobalAtomTable
;
41 Status
= RtlCreateAtomTable(37, &GlobalAtomTable
);
43 /* If we couldn't create it, return NULL */
44 if (!NT_SUCCESS(Status
)) return NULL
;
46 /* Return the newly created one */
47 return GlobalAtomTable
;
50 /* FUNCTIONS ****************************************************************/
57 NtAddAtom(IN PWSTR AtomName
,
58 IN ULONG AtomNameLength
,
61 PRTL_ATOM_TABLE AtomTable
= ExpGetGlobalAtomTable();
62 NTSTATUS Status
= STATUS_SUCCESS
;
63 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
64 LPWSTR CapturedName
= NULL
;
69 /* Check for the table */
70 if (AtomTable
== NULL
) return STATUS_ACCESS_DENIED
;
72 /* Check for valid name */
73 if (AtomNameLength
> (RTL_MAXIMUM_ATOM_LENGTH
* sizeof(WCHAR
)))
76 DPRINT1("Atom name too long\n");
77 return STATUS_INVALID_PARAMETER
;
80 /* Check if we're called from user-mode*/
81 if (PreviousMode
!= KernelMode
)
86 /* Check if we have a name */
90 ProbeForRead(AtomName
, AtomNameLength
, sizeof(WCHAR
));
92 /* Allocate an aligned buffer + the null char */
93 CapturedSize
= ((AtomNameLength
+ sizeof(WCHAR
)) &~
95 CapturedName
= ExAllocatePoolWithTag(PagedPool
,
101 Status
= STATUS_INSUFFICIENT_RESOURCES
;
105 /* Copy the name and null-terminate it */
106 RtlMoveMemory(CapturedName
, AtomName
, AtomNameLength
);
107 CapturedName
[AtomNameLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
110 /* Probe the atom too */
111 if (Atom
) ProbeForWriteUshort(Atom
);
114 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
)
116 Status
= _SEH_GetExceptionCode();
122 /* Simplify code and re-use one variable */
123 if (AtomName
) CapturedName
= AtomName
;
126 /* Make sure probe worked */
127 if (NT_SUCCESS(Status
))
129 /* Call the runtime function */
130 Status
= RtlAddAtomToAtomTable(AtomTable
, CapturedName
, &SafeAtom
);
131 if (NT_SUCCESS(Status
) && (Atom
))
133 /* Success and caller wants the atom back.. .enter SEH */
136 /* Return the atom */
139 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
)
141 Status
= _SEH_GetExceptionCode();
147 /* If we captured anything, free it */
148 if ((CapturedName
) && (CapturedName
!= AtomName
)) ExFreePool(CapturedName
);
150 /* Return to caller */
159 NtDeleteAtom(IN RTL_ATOM Atom
)
161 PRTL_ATOM_TABLE AtomTable
= ExpGetGlobalAtomTable();
164 /* Check for valid table */
165 if (AtomTable
== NULL
) return STATUS_ACCESS_DENIED
;
167 /* Call worker function */
168 return RtlDeleteAtomFromAtomTable(AtomTable
, Atom
);
176 NtFindAtom(IN PWSTR AtomName
,
177 IN ULONG AtomNameLength
,
180 PRTL_ATOM_TABLE AtomTable
= ExpGetGlobalAtomTable();
181 NTSTATUS Status
= STATUS_SUCCESS
;
182 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
183 LPWSTR CapturedName
= NULL
;
188 /* Check for the table */
189 if (AtomTable
== NULL
) return STATUS_ACCESS_DENIED
;
191 /* Check for valid name */
192 if (AtomNameLength
> (RTL_MAXIMUM_ATOM_LENGTH
* sizeof(WCHAR
)))
195 DPRINT1("Atom name too long\n");
196 return STATUS_INVALID_PARAMETER
;
199 /* Check if we're called from user-mode*/
200 if (PreviousMode
!= KernelMode
)
205 /* Check if we have a name */
209 ProbeForRead(AtomName
, AtomNameLength
, sizeof(WCHAR
));
211 /* Allocate an aligned buffer + the null char */
212 CapturedSize
= ((AtomNameLength
+ sizeof(WCHAR
)) &~
214 CapturedName
= ExAllocatePoolWithTag(PagedPool
,
220 Status
= STATUS_INSUFFICIENT_RESOURCES
;
224 /* Copy the name and null-terminate it */
225 RtlMoveMemory(CapturedName
, AtomName
, AtomNameLength
);
226 CapturedName
[AtomNameLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
229 /* Probe the atom too */
230 if (Atom
) ProbeForWriteUshort(Atom
);
233 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
)
235 Status
= _SEH_GetExceptionCode();
241 /* Simplify code and re-use one variable */
242 if (AtomName
) CapturedName
= AtomName
;
245 /* Make sure probe worked */
246 if (NT_SUCCESS(Status
))
248 /* Call the runtime function */
249 Status
= RtlLookupAtomInAtomTable(AtomTable
, CapturedName
, &SafeAtom
);
250 if (NT_SUCCESS(Status
) && (Atom
))
252 /* Success and caller wants the atom back.. .enter SEH */
255 /* Return the atom */
258 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
)
260 Status
= _SEH_GetExceptionCode();
266 /* If we captured anything, free it */
267 if ((CapturedName
) && (CapturedName
!= AtomName
)) ExFreePool(CapturedName
);
269 /* Return to caller */
278 NtQueryInformationAtom(RTL_ATOM Atom
,
279 ATOM_INFORMATION_CLASS AtomInformationClass
,
280 PVOID AtomInformation
,
281 ULONG AtomInformationLength
,
284 PRTL_ATOM_TABLE AtomTable
= ExpGetGlobalAtomTable();
285 PATOM_BASIC_INFORMATION BasicInformation
= AtomInformation
;
286 PATOM_TABLE_INFORMATION TableInformation
= AtomInformation
;
288 ULONG Flags
, UsageCount
, NameLength
;
290 /* Check for valid table */
291 if (AtomTable
== NULL
) return STATUS_ACCESS_DENIED
;
296 switch (AtomInformationClass
)
298 /* Caller requested info about an atom */
299 case AtomBasicInformation
:
302 *ReturnLength
= FIELD_OFFSET(ATOM_BASIC_INFORMATION
, Name
);
303 if (*ReturnLength
> AtomInformationLength
)
306 DPRINT1("Buffer too small\n");
307 return STATUS_INFO_LENGTH_MISMATCH
;
312 NameLength
= AtomInformationLength
- *ReturnLength
;
313 BasicInformation
->Name
[0] = UNICODE_NULL
;
316 Status
= RtlQueryAtomInAtomTable(AtomTable
,
320 BasicInformation
->Name
,
322 if (NT_SUCCESS(Status
))
325 BasicInformation
->UsageCount
= (USHORT
)UsageCount
;
326 BasicInformation
->Flags
= (USHORT
)Flags
;
327 BasicInformation
->NameLength
= (USHORT
)NameLength
;
328 *ReturnLength
+= NameLength
+ sizeof(WCHAR
);
332 /* Caller requested info about an Atom Table */
333 case AtomTableInformation
:
336 *ReturnLength
= FIELD_OFFSET(ATOM_TABLE_INFORMATION
, Atoms
);
337 if (*ReturnLength
> AtomInformationLength
)
340 DPRINT1("Buffer too small\n");
341 return STATUS_INFO_LENGTH_MISMATCH
;
345 Status
= RtlQueryAtomListInAtomTable(AtomTable
,
346 (AtomInformationLength
- *ReturnLength
) /
348 &TableInformation
->NumberOfAtoms
,
349 TableInformation
->Atoms
);
350 if (NT_SUCCESS(Status
))
352 /* Update the return length */
353 *ReturnLength
+= TableInformation
->NumberOfAtoms
*
358 /* Caller was on crack */
361 /* Unrecognized class */
362 Status
= STATUS_INVALID_INFO_CLASS
;
365 /* Return to caller */