mirror of
https://github.com/reactos/reactos.git
synced 2025-08-06 19:43:04 +00:00
undocumented behavior of LoadStringW: If nBufferMax is 0, LoadStringW will copy a pointer to the in-memory image of the string to the specified buffer and return the length of the string in WCHARs.
svn path=/trunk/; revision=26929
This commit is contained in:
parent
a009b642f6
commit
cf5b4c7e99
1 changed files with 99 additions and 77 deletions
|
@ -98,63 +98,71 @@ int STDCALL LoadStringA
|
||||||
int nBufferMax
|
int nBufferMax
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
UNICODE_STRING wstrResStr;
|
UNICODE_STRING wstrResStr;
|
||||||
ANSI_STRING strBuf;
|
ANSI_STRING strBuf;
|
||||||
INT retSize;
|
INT retSize;
|
||||||
|
|
||||||
/* parameter validation */
|
/* parameter validation */
|
||||||
if
|
if
|
||||||
(
|
(
|
||||||
(nBufferMax < 1) ||
|
(nBufferMax < 1) ||
|
||||||
(IsBadWritePtr(lpBuffer, nBufferMax * sizeof(lpBuffer[0])))
|
(IsBadWritePtr(lpBuffer, nBufferMax * sizeof(lpBuffer[0])))
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get the UNICODE_STRING descriptor of the in-memory image of the string */
|
/* get the UNICODE_STRING descriptor of the in-memory image of the string */
|
||||||
if(!_InternalLoadString(hInstance, uID, &wstrResStr))
|
if(!_InternalLoadString(hInstance, uID, &wstrResStr))
|
||||||
/* failure */
|
{
|
||||||
return 0;
|
/* failure */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
convert the string. The Unicode string may be in UTF-16 (multi-byte), so we
|
convert the string. The Unicode string may be in UTF-16 (multi-byte), so we
|
||||||
don't alter wstrResStr.Length, and let RtlUnicodeStringToAnsiString truncate
|
don't alter wstrResStr.Length, and let RtlUnicodeStringToAnsiString truncate
|
||||||
it, if necessary
|
it, if necessary
|
||||||
*/
|
*/
|
||||||
strBuf.Length = 0;
|
strBuf.Length = 0;
|
||||||
strBuf.MaximumLength = nBufferMax * sizeof(CHAR);
|
strBuf.MaximumLength = nBufferMax * sizeof(CHAR);
|
||||||
strBuf.Buffer = lpBuffer;
|
strBuf.Buffer = lpBuffer;
|
||||||
|
|
||||||
retSize = WideCharToMultiByte(CP_ACP, 0, wstrResStr.Buffer, wstrResStr.Length / sizeof(WCHAR), strBuf.Buffer, strBuf.MaximumLength, NULL, NULL);
|
retSize = WideCharToMultiByte(CP_ACP, 0, wstrResStr.Buffer,
|
||||||
|
wstrResStr.Length / sizeof(WCHAR),
|
||||||
|
strBuf.Buffer, strBuf.MaximumLength, NULL, NULL);
|
||||||
|
|
||||||
if(!retSize)
|
if(!retSize)
|
||||||
/* failure */
|
{
|
||||||
return 0;
|
/* failure */
|
||||||
else
|
return 0;
|
||||||
strBuf.Length = retSize;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
strBuf.Length = retSize;
|
||||||
|
}
|
||||||
|
|
||||||
/* the ANSI string may not be null-terminated */
|
/* the ANSI string may not be null-terminated */
|
||||||
if(strBuf.Length >= strBuf.MaximumLength)
|
if(strBuf.Length >= strBuf.MaximumLength)
|
||||||
{
|
{
|
||||||
/* length greater than the buffer? whatever */
|
/* length greater than the buffer? whatever */
|
||||||
int nStringLen = strBuf.MaximumLength / sizeof(CHAR) - 1;
|
int nStringLen = strBuf.MaximumLength / sizeof(CHAR) - 1;
|
||||||
|
|
||||||
/* zero the last character in the buffer */
|
/* zero the last character in the buffer */
|
||||||
strBuf.Buffer[nStringLen] = 0;
|
strBuf.Buffer[nStringLen] = 0;
|
||||||
|
|
||||||
/* success */
|
/* success */
|
||||||
return nStringLen;
|
return nStringLen;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* zero the last character in the string */
|
/* zero the last character in the string */
|
||||||
strBuf.Buffer[strBuf.Length / sizeof(CHAR)] = 0;
|
strBuf.Buffer[strBuf.Length / sizeof(CHAR)] = 0;
|
||||||
|
|
||||||
/* success */
|
/* success */
|
||||||
return strBuf.Length / sizeof(CHAR);
|
return strBuf.Length / sizeof(CHAR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -169,41 +177,55 @@ int STDCALL LoadStringW
|
||||||
int nBufferMax
|
int nBufferMax
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
UNICODE_STRING wstrResStr;
|
UNICODE_STRING wstrResStr;
|
||||||
int nStringLen;
|
int nStringLen;
|
||||||
|
|
||||||
/* parameter validation */
|
/* parameter validation */
|
||||||
if
|
if
|
||||||
(
|
(
|
||||||
(nBufferMax < 1) ||
|
(nBufferMax < 1) ||
|
||||||
(IsBadWritePtr(lpBuffer, nBufferMax * sizeof(lpBuffer[0])))
|
((nBufferMax > 0) && IsBadWritePtr(lpBuffer, nBufferMax * sizeof(lpBuffer[0]))) ||
|
||||||
)
|
/* undocumented: If nBufferMax is 0, LoadStringW will copy a pointer to the
|
||||||
{
|
in-memory image of the string to the specified buffer and return the length
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
of the string in WCHARs */
|
||||||
return 0;
|
((nBufferMax == 0) && IsBadWritePtr(lpBuffer, sizeof(lpBuffer)))
|
||||||
}
|
)
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* get the UNICODE_STRING descriptor of the in-memory image of the string */
|
/* get the UNICODE_STRING descriptor of the in-memory image of the string */
|
||||||
if(!_InternalLoadString(hInstance, uID, &wstrResStr))
|
if(!_InternalLoadString(hInstance, uID, &wstrResStr))
|
||||||
/* failure */
|
{
|
||||||
return 0;
|
/* failure */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* get the length in characters */
|
/* get the length in characters */
|
||||||
nStringLen = wstrResStr.Length / sizeof(WCHAR);
|
nStringLen = wstrResStr.Length / sizeof(WCHAR);
|
||||||
|
|
||||||
/* the buffer must be enough to contain the string and the null terminator */
|
if (nBufferMax > 0)
|
||||||
if(nBufferMax < (nStringLen + 1))
|
{
|
||||||
/* otherwise, the string is truncated */
|
/* the buffer must be enough to contain the string and the null terminator */
|
||||||
nStringLen = nBufferMax - 1;
|
if(nBufferMax < (nStringLen + 1))
|
||||||
|
{
|
||||||
|
/* otherwise, the string is truncated */
|
||||||
|
nStringLen = nBufferMax - 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* copy the string */
|
/* copy the string */
|
||||||
memcpy(lpBuffer, wstrResStr.Buffer, nStringLen * sizeof(WCHAR));
|
memcpy(lpBuffer, wstrResStr.Buffer, nStringLen * sizeof(WCHAR));
|
||||||
|
|
||||||
/* null-terminate it */
|
/* null-terminate it */
|
||||||
lpBuffer[nStringLen] = 0;
|
lpBuffer[nStringLen] = 0;
|
||||||
|
}
|
||||||
/* success */
|
else
|
||||||
return nStringLen;
|
{
|
||||||
|
*((LPWSTR*)lpBuffer) = wstrResStr.Buffer;
|
||||||
|
}
|
||||||
|
/* success */
|
||||||
|
return nStringLen;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue