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:
Timo Kreuzer 2007-05-28 00:35:55 +00:00
parent a009b642f6
commit cf5b4c7e99

View file

@ -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 */