mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 22:16:04 +00:00
[WIN32K]
- Rewrite NtUserGetAtomName, make it return the length in WCHARs instead of bytes, as it is supposed to be. Fix a buffer overrun, when the caller passes a too large UNICODE_STRING buffer. Probe the output buffers before accessing them. Makes sure the target string is always NULL terminated, even if the buffer is too small for the whole name. - Remove NULL termination code from IntGetAtomName, since that is already done by RtlQueryAtomInAtomTable svn path=/trunk/; revision=57970
This commit is contained in:
parent
d2351c0d6e
commit
3655610069
2 changed files with 67 additions and 29 deletions
|
@ -1893,11 +1893,13 @@ NTAPI
|
|||
NtUserGetAsyncKeyState(
|
||||
INT Key);
|
||||
|
||||
DWORD
|
||||
NTAPI
|
||||
_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);
|
||||
|
||||
UINT
|
||||
NTAPI
|
||||
|
|
|
@ -34,11 +34,11 @@ IntAddAtom(LPWSTR AtomName)
|
|||
}
|
||||
|
||||
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)
|
||||
|
@ -49,13 +49,12 @@ IntGetAtomName(RTL_ATOM nAtom, LPWSTR lpBuffer, ULONG nSize)
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -78,30 +77,67 @@ IntAddGlobalAtom(LPWSTR lpBuffer, BOOL PinAtom)
|
|||
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 */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue