[WIN32K]
[reactos.git] / reactos / win32ss / user / ntuser / useratom.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: User Atom helper routines
5 * FILE: subsys/win32k/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
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
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
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 ) RtlPinAtomInAtomTable(gAtomTable, Atom);
76
77 return Atom;
78 }
79
80 /*!
81 * \brief Returns the name of an atom.
82 *
83 * \param atom - The atom to be queried.
84 * \param pustrName - Pointer to an initialized UNICODE_STRING that receives
85 * the name of the atom. The function does not update the
86 Length member. The string is always NULL-terminated.
87 *
88 * \return The length of the name in characters, or 0 if the function fails.
89 *
90 * \note The function does not aquire any global lock, since synchronisation is
91 * handled by the RtlAtom function.
92 */
93 _Success_(return!=0)
94 _At_(pustrName->Buffer, _Out_z_bytecap_post_bytecount_(pustrName->MaximumLength, return*2+2))
95 ULONG
96 APIENTRY
97 NtUserGetAtomName(
98 _In_ ATOM atom,
99 _Inout_ PUNICODE_STRING pustrName)
100 {
101 WCHAR awcBuffer[256];
102 ULONG cjLength;
103
104 /* Retrieve the atom name into a local buffer (max length is 255 chars) */
105 cjLength = IntGetAtomName((RTL_ATOM)atom, awcBuffer, sizeof(awcBuffer));
106 if (cjLength != 0)
107 {
108 _SEH2_TRY
109 {
110 /* Probe the unicode string and the buffer */
111 ProbeForRead(pustrName, sizeof(*pustrName), 1);
112 ProbeForWrite(pustrName->Buffer, pustrName->MaximumLength, 1);
113
114 /* Check if we have enough space to write the NULL termination */
115 if (pustrName->MaximumLength >= sizeof(UNICODE_NULL))
116 {
117 /* Limit the length to the buffer size */
118 cjLength = min(pustrName->MaximumLength - sizeof(UNICODE_NULL),
119 cjLength);
120
121 /* Copy the string and NULL terminate it */
122 RtlCopyMemory(pustrName->Buffer, awcBuffer, cjLength);
123 pustrName->Buffer[cjLength / sizeof(WCHAR)] = L'\0';
124 }
125 else
126 {
127 cjLength = 0;
128 }
129 }
130 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
131 {
132 /* On exception, set last error and fail */
133 SetLastNtError(_SEH2_GetExceptionCode());
134 cjLength = 0;
135 }
136 _SEH2_END
137 }
138
139 /* Return the length in characters */
140 return cjLength / sizeof(WCHAR);
141 }
142
143 /* EOF */