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