- Add Wine implementation LoadStringA/W. This is fixed all wine tests for LoadString

svn path=/trunk/; revision=38652
This commit is contained in:
Dmitry Chapyshev 2009-01-08 19:47:29 +00:00
parent 915dfcf6a7
commit c76d2abb9d

View file

@ -20,223 +20,85 @@ typedef DWORD (WINAPI *CMP_UNREGNOTIFY) (ULONG );
static HINSTANCE hSetupApi = NULL; static HINSTANCE hSetupApi = NULL;
BOOL
WINAPI
_InternalLoadString(HINSTANCE hInstance,
UINT uID,
PUNICODE_STRING pwstrDest)
{
HRSRC hrsStringTable;
HGLOBAL hResource;
PWCHAR pStringTable;
unsigned i;
unsigned l = uID % 16; /* (1) */
/* parameter validation */
if (IsBadWritePtr(pwstrDest, sizeof(UNICODE_STRING)))
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
/* /*
find the string table. String tables are created by grouping, 16 by 16, string * @implemented (Synced with Wine 08.01.2009)
resources whose identifiers, divided by 16, have the same integer quotient.
Holes in the numbering are filled with zero-length strings. String table ids
(actual resource ids) start from 1. See (1) and (2)
*/
/* TODO: some sort of cache, here, would be great */
hrsStringTable = FindResourceW((HMODULE)hInstance,
MAKEINTRESOURCEW((uID / 16) + 1), /* (2) */
RT_STRING);
/* failure */
if (hrsStringTable == NULL) return FALSE;
/* load the string table into memory */
hResource = LoadResource((HMODULE)hInstance, hrsStringTable);
/* failure */
if (hResource == NULL) return FALSE;
/* lock the resource into memory */
pStringTable = LockResource(hResource);
/* failure */
if (pStringTable == NULL) return FALSE;
/*
string tables are packed Unicode Pascal strings. The first WCHAR contains the
length, in characters, of the current string. Zero-length strings, if any, are
placeholders for unused slots, and should therefore be considered non-present.
See also (3). Here, we walk all the strings before that of interest
*/
for(i = 0; i < l; ++ i)
{
/* skip the length and the current string */
pStringTable += 1 + (*pStringTable);
}
/* we've reached the string of interest */
if ((*pStringTable) == 0)
{
/* the string is empty (unallocated) */
SetLastError(ERROR_RESOURCE_NAME_NOT_FOUND);
return FALSE; /* 3 */
}
/* string length in bytes */
pwstrDest->Length = pwstrDest->MaximumLength = (*pStringTable) * sizeof(WCHAR);
/* string */
pwstrDest->Buffer = pStringTable + 1;
/* success */
return TRUE;
}
/*
* @implemented
*/ */
int int
WINAPI WINAPI
LoadStringA(HINSTANCE hInstance, LoadStringA(HINSTANCE instance, UINT resource_id, LPSTR buffer, INT buflen)
UINT uID,
LPSTR lpBuffer,
int nBufferMax)
{ {
UNICODE_STRING wstrResStr; HGLOBAL hmem;
ANSI_STRING strBuf; HRSRC hrsrc;
INT retSize; DWORD retval = 0;
/* parameter validation */ if (!buflen) return -1;
if (nBufferMax < 1) /* Use loword (incremented by 1) as resourceid */
if ((hrsrc = FindResourceW( instance, MAKEINTRESOURCEW((LOWORD(resource_id) >> 4) + 1),
(LPWSTR)RT_STRING )) &&
(hmem = LoadResource( instance, hrsrc )))
{ {
return -1; const WCHAR *p = LockResource(hmem);
} unsigned int id = resource_id & 0x000f;
if (IsBadWritePtr(lpBuffer, nBufferMax * sizeof(lpBuffer[0]))) while (id--) p += *p + 1;
{
SetLastError(ERROR_INVALID_PARAMETER); RtlUnicodeToMultiByteN( buffer, buflen - 1, &retval, (PWSTR)(p + 1), *p * sizeof(WCHAR) );
return 0;
}
/* get the UNICODE_STRING descriptor of the in-memory image of the string */
if (!_InternalLoadString(hInstance, uID, &wstrResStr))
{
/* failure */
return 0;
}
/*
convert the string. The Unicode string may be in UTF-16 (multi-byte), so we
don't alter wstrResStr.Length, and let RtlUnicodeStringToAnsiString truncate
it, if necessary
*/
strBuf.Length = 0;
strBuf.MaximumLength = nBufferMax * sizeof(CHAR);
strBuf.Buffer = lpBuffer;
retSize = WideCharToMultiByte(CP_ACP,
0,
wstrResStr.Buffer,
wstrResStr.Length / sizeof(WCHAR),
strBuf.Buffer,
strBuf.MaximumLength,
NULL,
NULL);
if (!retSize)
{
/* failure */
return 0;
}
else
{
strBuf.Length = retSize;
}
/* the ANSI string may not be null-terminated */
if (strBuf.Length >= strBuf.MaximumLength)
{
/* length greater than the buffer? whatever */
int nStringLen = strBuf.MaximumLength / sizeof(CHAR) - 1;
/* zero the last character in the buffer */
strBuf.Buffer[nStringLen] = 0;
/* success */
return nStringLen;
}
else
{
/* zero the last character in the string */
strBuf.Buffer[strBuf.Length / sizeof(CHAR)] = 0;
/* success */
return strBuf.Length / sizeof(CHAR);
} }
buffer[retval] = 0;
return retval;
} }
/* /*
* @implemented * @implemented (Synced with Wine 08.01.2009)
*/ */
int int
WINAPI WINAPI
LoadStringW(HINSTANCE hInstance, LoadStringW(HINSTANCE instance, UINT resource_id, LPWSTR buffer, INT buflen)
UINT uID,
LPWSTR lpBuffer,
int nBufferMax)
{ {
UNICODE_STRING wstrResStr; HGLOBAL hmem;
int nStringLen; HRSRC hrsrc;
WCHAR *p;
int string_num;
int i;
/* parameter validation */ if(buffer == NULL)
if ((nBufferMax < 0) || (lpBuffer == NULL) || return 0;
((nBufferMax > 0) && IsBadWritePtr(lpBuffer, nBufferMax * sizeof(lpBuffer[0]))) ||
/* undocumented: If nBufferMax is 0, LoadStringW will copy a pointer to the /* Use loword (incremented by 1) as resourceid */
in-memory image of the string to the specified buffer and return the length hrsrc = FindResourceW( instance, MAKEINTRESOURCEW((LOWORD(resource_id) >> 4) + 1),
of the string in WCHARs */ (LPWSTR)RT_STRING );
((nBufferMax == 0) && IsBadWritePtr(lpBuffer, sizeof(lpBuffer)))) if (!hrsrc) return 0;
hmem = LoadResource( instance, hrsrc );
if (!hmem) return 0;
p = LockResource(hmem);
string_num = resource_id & 0x000f;
for (i = 0; i < string_num; i++)
p += *p + 1;
/*if buflen == 0, then return a read-only pointer to the resource itself in buffer
it is assumed that buffer is actually a (LPWSTR *) */
if(buflen == 0)
{ {
SetLastError(ERROR_INVALID_PARAMETER); *((LPWSTR *)buffer) = p + 1;
return *p;
}
i = min(buflen - 1, *p);
if (i > 0) {
memcpy(buffer, p + 1, i * sizeof (WCHAR));
buffer[i] = 0;
} else {
if (buflen > 1) {
buffer[0] = 0;
return 0; return 0;
} }
/* get the UNICODE_STRING descriptor of the in-memory image of the string */
if (!_InternalLoadString(hInstance, uID, &wstrResStr))
{
/* failure */
return 0;
} }
/* get the length in characters */ return i;
nStringLen = wstrResStr.Length / sizeof(WCHAR);
if (nBufferMax > 0)
{
/* the buffer must be enough to contain the string and the null terminator */
if (nBufferMax < (nStringLen + 1))
{
/* otherwise, the string is truncated */
nStringLen = nBufferMax - 1;
}
/* copy the string */
memcpy(lpBuffer, wstrResStr.Buffer, nStringLen * sizeof(WCHAR));
/* null-terminate it */
lpBuffer[nStringLen] = 0;
}
else
{
*((LPWSTR*)lpBuffer) = wstrResStr.Buffer;
}
/* success */
return nStringLen;
} }