}
ULONG FASTCALL
-IntGetAtomName(RTL_ATOM nAtom, LPWSTR lpBuffer, ULONG nSize)
+IntGetAtomName(RTL_ATOM nAtom, LPWSTR lpBuffer, ULONG cjBufSize)
{
NTSTATUS Status = STATUS_SUCCESS;
PTHREADINFO pti;
- ULONG Size = nSize;
+ ULONG Size = cjBufSize;
pti = PsGetCurrentThreadWin32Thread();
if (pti->rpdesk == NULL)
Status = RtlQueryAtomInAtomTable(gAtomTable, nAtom, NULL, NULL, lpBuffer, &Size);
- if (Size < nSize)
- *(lpBuffer + Size/sizeof(WCHAR)) = 0;
if (!NT_SUCCESS(Status))
{
SetLastNtError(Status);
return 0;
}
+
return Size;
}
return Atom;
}
-DWORD
+/*!
+ * \brief Returns the name of an atom.
+ *
+ * \param atom - The atom to be queried.
+ * \param pustrName - Pointer to an initialized UNICODE_STRING that receives
+ * the name of the atom. The function does not update the
+ Length member. The string is always NULL-terminated.
+ *
+ * \return The length of the name in characters, or 0 if the function fails.
+ *
+ * \note The function does not aquire any global lock, since synchronisation is
+ * handled by the RtlAtom function.
+ */
+_Success_(return!=0)
+_At_(pustrName->Buffer, _Out_z_bytecap_post_bytecount_(pustrName->MaximumLength, return*2+2))
+ULONG
APIENTRY
NtUserGetAtomName(
- ATOM nAtom,
- PUNICODE_STRING pBuffer)
+ _In_ ATOM atom,
+ _Inout_ PUNICODE_STRING pustrName)
{
- DWORD Ret;
- WCHAR Buffer[256];
- UNICODE_STRING CapturedName = {0};
- UserEnterShared();
- CapturedName.Buffer = (LPWSTR)&Buffer;
- CapturedName.MaximumLength = sizeof(Buffer);
- Ret = IntGetAtomName((RTL_ATOM)nAtom, CapturedName.Buffer, (ULONG)CapturedName.Length);
- _SEH2_TRY
- {
- RtlCopyMemory(pBuffer->Buffer, &Buffer, pBuffer->MaximumLength);
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- Ret = 0;
- }
- _SEH2_END
- UserLeave();
- return Ret;
+ WCHAR awcBuffer[256];
+ ULONG cjLength;
+
+ /* Retrieve the atom name into a local buffer (max length is 255 chars) */
+ cjLength = IntGetAtomName((RTL_ATOM)atom, awcBuffer, sizeof(awcBuffer));
+ if (cjLength != 0)
+ {
+ _SEH2_TRY
+ {
+ /* Probe the unicode string and the buffer */
+ ProbeForRead(pustrName, sizeof(*pustrName), 1);
+ ProbeForWrite(pustrName->Buffer, pustrName->MaximumLength, 1);
+
+ /* Check if we have enough space to write the NULL termination */
+ if (pustrName->MaximumLength >= sizeof(UNICODE_NULL))
+ {
+ /* Limit the length to the buffer size */
+ cjLength = min(pustrName->MaximumLength - sizeof(UNICODE_NULL),
+ cjLength);
+
+ /* Copy the string and NULL terminate it */
+ RtlCopyMemory(pustrName->Buffer, awcBuffer, cjLength);
+ pustrName->Buffer[cjLength / sizeof(WCHAR)] = L'\0';
+ }
+ else
+ {
+ cjLength = 0;
+ }
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* On exception, set last error and fail */
+ SetLastNtError(_SEH2_GetExceptionCode());
+ cjLength = 0;
+ }
+ _SEH2_END
+ }
+
+ /* Return the length in characters */
+ return cjLength / sizeof(WCHAR);
}
/* EOF */