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