diff --git a/reactos/dll/win32/user32/misc/resources.c b/reactos/dll/win32/user32/misc/resources.c index 27b3cff1d2c..ca704434427 100644 --- a/reactos/dll/win32/user32/misc/resources.c +++ b/reactos/dll/win32/user32/misc/resources.c @@ -20,223 +20,85 @@ typedef DWORD (WINAPI *CMP_UNREGNOTIFY) (ULONG ); static HINSTANCE hSetupApi = NULL; -BOOL + +/* + * @implemented (Synced with Wine 08.01.2009) + */ +int WINAPI -_InternalLoadString(HINSTANCE hInstance, - UINT uID, - PUNICODE_STRING pwstrDest) +LoadStringA(HINSTANCE instance, UINT resource_id, LPSTR buffer, INT buflen) { - HRSRC hrsStringTable; - HGLOBAL hResource; - PWCHAR pStringTable; - unsigned i; - unsigned l = uID % 16; /* (1) */ + HGLOBAL hmem; + HRSRC hrsrc; + DWORD retval = 0; - /* parameter validation */ - if (IsBadWritePtr(pwstrDest, sizeof(UNICODE_STRING))) + if (!buflen) return -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 ))) { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; + const WCHAR *p = LockResource(hmem); + unsigned int id = resource_id & 0x000f; + + while (id--) p += *p + 1; + + RtlUnicodeToMultiByteN( buffer, buflen - 1, &retval, (PWSTR)(p + 1), *p * sizeof(WCHAR) ); } - - /* - find the string table. String tables are created by grouping, 16 by 16, string - 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; + buffer[retval] = 0; + return retval; } /* - * @implemented + * @implemented (Synced with Wine 08.01.2009) */ int WINAPI -LoadStringA(HINSTANCE hInstance, - UINT uID, - LPSTR lpBuffer, - int nBufferMax) +LoadStringW(HINSTANCE instance, UINT resource_id, LPWSTR buffer, INT buflen) { - UNICODE_STRING wstrResStr; - ANSI_STRING strBuf; - INT retSize; + HGLOBAL hmem; + HRSRC hrsrc; + WCHAR *p; + int string_num; + int i; - /* parameter validation */ + if(buffer == NULL) + return 0; - if (nBufferMax < 1) + /* Use loword (incremented by 1) as resourceid */ + hrsrc = FindResourceW( instance, MAKEINTRESOURCEW((LOWORD(resource_id) >> 4) + 1), + (LPWSTR)RT_STRING ); + 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) { - return -1; + *((LPWSTR *)buffer) = p + 1; + return *p; } - if (IsBadWritePtr(lpBuffer, nBufferMax * sizeof(lpBuffer[0]))) - { - SetLastError(ERROR_INVALID_PARAMETER); + 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; } - - /* 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); - } -} - - -/* - * @implemented - */ -int -WINAPI -LoadStringW(HINSTANCE hInstance, - UINT uID, - LPWSTR lpBuffer, - int nBufferMax) -{ - UNICODE_STRING wstrResStr; - int nStringLen; - - /* parameter validation */ - if ((nBufferMax < 0) || (lpBuffer == NULL) || - ((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 - of the string in WCHARs */ - ((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 */ - if (!_InternalLoadString(hInstance, uID, &wstrResStr)) - { - /* failure */ - return 0; - } - - /* get the length in characters */ - 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; + return i; }