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