xref: /reactos/win32ss/user/ntuser/useratom.c (revision c2c66aff)
1 /*
2  * COPYRIGHT:        See COPYING in the top level directory
3  * PROJECT:          ReactOS kernel
4  * PURPOSE:          User Atom helper routines
5  * FILE:             win32ss/user/ntuser/useratom.c
6  * PROGRAMER:        Filip Navara <xnavara@volny.cz>
7  */
8 
9 #include <win32k.h>
10 DBG_DEFAULT_CHANNEL(UserMisc);
11 
12 RTL_ATOM FASTCALL
IntAddAtom(LPWSTR AtomName)13 IntAddAtom(LPWSTR AtomName)
14 {
15     NTSTATUS Status = STATUS_SUCCESS;
16     PTHREADINFO pti;
17     RTL_ATOM Atom;
18 
19     pti = PsGetCurrentThreadWin32Thread();
20     if (pti->rpdesk == NULL)
21     {
22         SetLastNtError(Status);
23         return (RTL_ATOM)0;
24     }
25 
26     Status = RtlAddAtomToAtomTable(gAtomTable, AtomName, &Atom);
27 
28     if (!NT_SUCCESS(Status))
29     {
30         SetLastNtError(Status);
31         return (RTL_ATOM)0;
32     }
33     return Atom;
34 }
35 
36 ULONG FASTCALL
IntGetAtomName(RTL_ATOM nAtom,LPWSTR lpBuffer,ULONG cjBufSize)37 IntGetAtomName(RTL_ATOM nAtom, LPWSTR lpBuffer, ULONG cjBufSize)
38 {
39     NTSTATUS Status = STATUS_SUCCESS;
40     PTHREADINFO pti;
41     ULONG Size = cjBufSize;
42 
43     pti = PsGetCurrentThreadWin32Thread();
44     if (pti->rpdesk == NULL)
45     {
46         SetLastNtError(Status);
47         return 0;
48     }
49 
50     Status = RtlQueryAtomInAtomTable(gAtomTable, nAtom, NULL, NULL, lpBuffer, &Size);
51 
52     if (!NT_SUCCESS(Status))
53     {
54         SetLastNtError(Status);
55         return 0;
56     }
57 
58     return Size;
59 }
60 
61 RTL_ATOM FASTCALL
IntAddGlobalAtom(LPWSTR lpBuffer,BOOL PinAtom)62 IntAddGlobalAtom(LPWSTR lpBuffer, BOOL PinAtom)
63 {
64     RTL_ATOM Atom;
65     NTSTATUS Status = STATUS_SUCCESS;
66 
67     Status = RtlAddAtomToAtomTable(gAtomTable, lpBuffer, &Atom);
68 
69     if (!NT_SUCCESS(Status))
70     {
71         ERR("Error init Global Atom.\n");
72         return 0;
73     }
74 
75     if (Atom && PinAtom)
76         RtlPinAtomInAtomTable(gAtomTable, Atom);
77 
78     return Atom;
79 }
80 
81 /*!
82  * \brief Returns the name of an atom.
83  *
84  * \param atom - The atom to be queried.
85  * \param pustrName - Pointer to an initialized UNICODE_STRING that receives
86  *                    the name of the atom. The function does not update the
87                       Length member. The string is always NULL-terminated.
88  *
89  * \return The length of the name in characters, or 0 if the function fails.
90  *
91  * \note The function does not aquire any global lock, since synchronisation is
92  *       handled by the RtlAtom function.
93  */
94 _Success_(return != 0)
95 _At_(pustrName->Buffer, _Out_z_bytecap_post_bytecount_(pustrName->MaximumLength, return * 2 + 2))
96 ULONG
97 APIENTRY
NtUserGetAtomName(_In_ ATOM atom,_Inout_ PUNICODE_STRING pustrName)98 NtUserGetAtomName(
99     _In_ ATOM atom,
100     _Inout_ PUNICODE_STRING pustrName)
101 {
102     WCHAR awcBuffer[256];
103     ULONG cjLength;
104 
105     /* Retrieve the atom name into a local buffer (max length is 255 chars) */
106     cjLength = IntGetAtomName((RTL_ATOM)atom, awcBuffer, sizeof(awcBuffer));
107     if (cjLength != 0)
108     {
109         _SEH2_TRY
110         {
111             /* Probe the unicode string and the buffer */
112             ProbeForRead(pustrName, sizeof(*pustrName), 1);
113             ProbeForWrite(pustrName->Buffer, pustrName->MaximumLength, 1);
114 
115             /* Check if we have enough space to write the NULL termination */
116             if (pustrName->MaximumLength >= sizeof(UNICODE_NULL))
117             {
118                 /* Limit the length to the buffer size */
119                 cjLength = min(pustrName->MaximumLength - sizeof(UNICODE_NULL),
120                                cjLength);
121 
122                 /* Copy the string and NULL terminate it */
123                 RtlCopyMemory(pustrName->Buffer, awcBuffer, cjLength);
124                 pustrName->Buffer[cjLength / sizeof(WCHAR)] = L'\0';
125             }
126             else
127             {
128                 cjLength = 0;
129             }
130         }
131         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
132         {
133             /* On exception, set last error and fail */
134             SetLastNtError(_SEH2_GetExceptionCode());
135             cjLength = 0;
136         }
137         _SEH2_END
138     }
139 
140     /* Return the length in characters */
141     return cjLength / sizeof(WCHAR);
142 }
143 
144 /* EOF */
145