advapi32: Implemented RegLoadMUIString[AW].
This commit is contained in:
parent
53b93af3b9
commit
ac615ce5a0
|
@ -486,6 +486,8 @@
|
||||||
@ stdcall RegGetValueW(long wstr wstr long ptr ptr ptr)
|
@ stdcall RegGetValueW(long wstr wstr long ptr ptr ptr)
|
||||||
@ stdcall RegLoadKeyA(long str str)
|
@ stdcall RegLoadKeyA(long str str)
|
||||||
@ stdcall RegLoadKeyW(long wstr wstr)
|
@ stdcall RegLoadKeyW(long wstr wstr)
|
||||||
|
@ stdcall RegLoadMUIStringA(long str str long ptr long str)
|
||||||
|
@ stdcall RegLoadMUIStringW(long wstr wstr long ptr long wstr)
|
||||||
@ stdcall RegNotifyChangeKeyValue(long long long long long)
|
@ stdcall RegNotifyChangeKeyValue(long long long long long)
|
||||||
@ stdcall RegOpenCurrentUser(long ptr)
|
@ stdcall RegOpenCurrentUser(long ptr)
|
||||||
@ stdcall RegOpenKeyA(long str ptr)
|
@ stdcall RegOpenKeyA(long str ptr)
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include "winreg.h"
|
#include "winreg.h"
|
||||||
#include "winerror.h"
|
#include "winerror.h"
|
||||||
#include "winternl.h"
|
#include "winternl.h"
|
||||||
|
#include "winuser.h"
|
||||||
|
|
||||||
#include "wine/unicode.h"
|
#include "wine/unicode.h"
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
@ -2378,3 +2379,189 @@ LONG WINAPI RegOpenUserClassesRoot(
|
||||||
*phkResult = HKEY_CLASSES_ROOT;
|
*phkResult = HKEY_CLASSES_ROOT;
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* load_string [Internal]
|
||||||
|
*
|
||||||
|
* This is basically a copy of user32/resource.c's LoadStringW. Necessary to
|
||||||
|
* avoid importing user32, which is higher level than advapi32. Helper for
|
||||||
|
* RegLoadMUIString.
|
||||||
|
*/
|
||||||
|
static int load_string(HINSTANCE hModule, UINT resId, LPWSTR pwszBuffer, INT cMaxChars)
|
||||||
|
{
|
||||||
|
HGLOBAL hMemory;
|
||||||
|
HRSRC hResource;
|
||||||
|
WCHAR *pString;
|
||||||
|
int idxString;
|
||||||
|
|
||||||
|
/* Negative values have to be inverted. */
|
||||||
|
if (HIWORD(resId) == 0xffff)
|
||||||
|
resId = (UINT)(-((INT)resId));
|
||||||
|
|
||||||
|
/* Load the resource into memory and get a pointer to it. */
|
||||||
|
hResource = FindResourceW(hModule, MAKEINTRESOURCEW(LOWORD(resId >> 4) + 1), (LPWSTR)RT_STRING);
|
||||||
|
if (!hResource) return 0;
|
||||||
|
hMemory = LoadResource(hModule, hResource);
|
||||||
|
if (!hMemory) return 0;
|
||||||
|
pString = LockResource(hMemory);
|
||||||
|
|
||||||
|
/* Strings are length-prefixed. Lowest nibble of resId is an index. */
|
||||||
|
idxString = resId & 0xf;
|
||||||
|
while (idxString--) pString += *pString + 1;
|
||||||
|
|
||||||
|
/* If no buffer is given, return length of the string. */
|
||||||
|
if (!pwszBuffer) return *pString;
|
||||||
|
|
||||||
|
/* Else copy over the string, respecting the buffer size. */
|
||||||
|
cMaxChars = (*pString < cMaxChars) ? *pString : (cMaxChars - 1);
|
||||||
|
if (cMaxChars >= 0) {
|
||||||
|
memcpy(pwszBuffer, pString+1, cMaxChars * sizeof(WCHAR));
|
||||||
|
pwszBuffer[cMaxChars] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return cMaxChars;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* RegLoadMUIStringW [ADVAPI32.@]
|
||||||
|
*
|
||||||
|
* Load the localized version of a string resource from some PE, respective
|
||||||
|
* id and path of which are given in the registry value in the format
|
||||||
|
* @[path]\dllname,-resourceId
|
||||||
|
*
|
||||||
|
* PARAMS
|
||||||
|
* hKey [I] Key, of which to load the string value from.
|
||||||
|
* pszValue [I] The value to be loaded (Has to be of REG_EXPAND_SZ or REG_SZ type).
|
||||||
|
* pszBuffer [O] Buffer to store the localized string in.
|
||||||
|
* cbBuffer [I] Size of the destination buffer in bytes.
|
||||||
|
* pcbData [O] Number of bytes written to pszBuffer (optional, may be NULL).
|
||||||
|
* dwFlags [I] None supported yet.
|
||||||
|
* pszBaseDir [I] Not supported yet.
|
||||||
|
*
|
||||||
|
* RETURNS
|
||||||
|
* Success: ERROR_SUCCESS,
|
||||||
|
* Failure: nonzero error code from winerror.h
|
||||||
|
*
|
||||||
|
* NOTES
|
||||||
|
* This is an API of Windows Vista, which wasn't available at the time this code
|
||||||
|
* was written. We have to check for the correct behaviour once it's available.
|
||||||
|
*/
|
||||||
|
LONG WINAPI RegLoadMUIStringW(HKEY hKey, LPCWSTR pwszValue, LPWSTR pwszBuffer, DWORD cbBuffer,
|
||||||
|
LPDWORD pcbData, DWORD dwFlags, LPCWSTR pwszBaseDir)
|
||||||
|
{
|
||||||
|
DWORD dwValueType, cbData;
|
||||||
|
LPWSTR pwszTempBuffer = NULL, pwszExpandedBuffer = NULL;
|
||||||
|
LONG result;
|
||||||
|
|
||||||
|
TRACE("(hKey = %p, pwszValue = %s, pwszBuffer = %p, cbBuffer = %ld, pcbData = %p, "
|
||||||
|
"dwFlags = %ld, pwszBaseDir = %s) stub\n", hKey, debugstr_w(pwszValue), pwszBuffer,
|
||||||
|
cbBuffer, pcbData, dwFlags, debugstr_w(pwszBaseDir));
|
||||||
|
|
||||||
|
/* Parameter sanity checks. */
|
||||||
|
if (!hKey || !pwszBuffer)
|
||||||
|
return ERROR_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
if (pwszBaseDir && *pwszBaseDir) {
|
||||||
|
FIXME("BaseDir parameter not yet supported!\n");
|
||||||
|
return ERROR_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for value existence and correctness of it's type, allocate a buffer and load it. */
|
||||||
|
result = RegQueryValueExW(hKey, pwszValue, NULL, &dwValueType, NULL, &cbData);
|
||||||
|
if (result != ERROR_SUCCESS) goto cleanup;
|
||||||
|
if (!(dwValueType == REG_SZ || dwValueType == REG_EXPAND_SZ) || !cbData) {
|
||||||
|
result = ERROR_FILE_NOT_FOUND;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
pwszTempBuffer = HeapAlloc(GetProcessHeap(), 0, cbData);
|
||||||
|
if (!pwszTempBuffer) {
|
||||||
|
result = ERROR_NOT_ENOUGH_MEMORY;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
result = RegQueryValueExW(hKey, pwszValue, NULL, &dwValueType, (LPBYTE)pwszTempBuffer, &cbData);
|
||||||
|
if (result != ERROR_SUCCESS) goto cleanup;
|
||||||
|
|
||||||
|
/* Expand environment variables, if appropriate, or copy the original string over. */
|
||||||
|
if (dwValueType == REG_EXPAND_SZ) {
|
||||||
|
cbData = ExpandEnvironmentStringsW(pwszTempBuffer, NULL, 0) * sizeof(WCHAR);
|
||||||
|
if (!cbData) goto cleanup;
|
||||||
|
pwszExpandedBuffer = HeapAlloc(GetProcessHeap(), 0, cbData);
|
||||||
|
if (!pwszExpandedBuffer) {
|
||||||
|
result = ERROR_NOT_ENOUGH_MEMORY;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
ExpandEnvironmentStringsW(pwszTempBuffer, pwszExpandedBuffer, cbData);
|
||||||
|
} else {
|
||||||
|
pwszExpandedBuffer = HeapAlloc(GetProcessHeap(), 0, cbData);
|
||||||
|
memcpy(pwszExpandedBuffer, pwszTempBuffer, cbData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the value references a resource based string, parse the value and load the string.
|
||||||
|
* Else just copy over the original value. */
|
||||||
|
result = ERROR_SUCCESS;
|
||||||
|
if (*pwszExpandedBuffer != '@') { /* '@' is the prefix for resource based string entries. */
|
||||||
|
lstrcpynW(pwszBuffer, pwszExpandedBuffer, cbBuffer / sizeof(WCHAR));
|
||||||
|
} else {
|
||||||
|
WCHAR *pComma = strrchrW(pwszExpandedBuffer, ',');
|
||||||
|
UINT uiStringId;
|
||||||
|
HMODULE hModule;
|
||||||
|
|
||||||
|
/* Format of the expanded value is 'path_to_dll,-resId' */
|
||||||
|
if (!pComma || pComma[1] != '-') {
|
||||||
|
result = ERROR_BADKEY;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
uiStringId = atoiW(pComma+2);
|
||||||
|
*pComma = '\0';
|
||||||
|
|
||||||
|
hModule = LoadLibraryW(pwszExpandedBuffer + 1);
|
||||||
|
if (!hModule || !load_string(hModule, uiStringId, pwszBuffer, cbBuffer/sizeof(WCHAR)))
|
||||||
|
result = ERROR_BADKEY;
|
||||||
|
FreeLibrary(hModule);
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
HeapFree(GetProcessHeap(), 0, pwszTempBuffer);
|
||||||
|
HeapFree(GetProcessHeap(), 0, pwszExpandedBuffer);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* RegLoadMUIStringA [ADVAPI32.@]
|
||||||
|
*
|
||||||
|
* See RegLoadMUIStringW
|
||||||
|
*/
|
||||||
|
LONG WINAPI RegLoadMUIStringA(HKEY hKey, LPCSTR pszValue, LPSTR pszBuffer, DWORD cbBuffer,
|
||||||
|
LPDWORD pcbData, DWORD dwFlags, LPCSTR pszBaseDir)
|
||||||
|
{
|
||||||
|
UNICODE_STRING valueW, baseDirW;
|
||||||
|
WCHAR *pwszBuffer;
|
||||||
|
DWORD cbData = cbBuffer * sizeof(WCHAR);
|
||||||
|
LONG result;
|
||||||
|
|
||||||
|
valueW.Buffer = baseDirW.Buffer = pwszBuffer = NULL;
|
||||||
|
if (!RtlCreateUnicodeStringFromAsciiz(&valueW, pszValue) ||
|
||||||
|
!RtlCreateUnicodeStringFromAsciiz(&baseDirW, pszBaseDir) ||
|
||||||
|
!(pwszBuffer = HeapAlloc(GetProcessHeap(), 0, cbData)))
|
||||||
|
{
|
||||||
|
result = ERROR_NOT_ENOUGH_MEMORY;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = RegLoadMUIStringW(hKey, valueW.Buffer, pwszBuffer, cbData, NULL, dwFlags,
|
||||||
|
baseDirW.Buffer);
|
||||||
|
|
||||||
|
if (result == ERROR_SUCCESS) {
|
||||||
|
cbData = WideCharToMultiByte(CP_ACP, 0, pwszBuffer, -1, pszBuffer, cbBuffer, NULL, NULL);
|
||||||
|
if (pcbData)
|
||||||
|
*pcbData = cbData;
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
HeapFree(GetProcessHeap(), 0, pwszBuffer);
|
||||||
|
RtlFreeUnicodeString(&baseDirW);
|
||||||
|
RtlFreeUnicodeString(&valueW);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
|
@ -113,6 +113,9 @@ LONG WINAPI RegGetValueW(HKEY,LPCWSTR,LPCWSTR,DWORD,LPDWORD,PVOID,LPDWORD
|
||||||
LONG WINAPI RegLoadKeyA(HKEY,LPCSTR,LPCSTR);
|
LONG WINAPI RegLoadKeyA(HKEY,LPCSTR,LPCSTR);
|
||||||
LONG WINAPI RegLoadKeyW(HKEY,LPCWSTR,LPCWSTR);
|
LONG WINAPI RegLoadKeyW(HKEY,LPCWSTR,LPCWSTR);
|
||||||
#define RegLoadKey WINELIB_NAME_AW(RegLoadKey)
|
#define RegLoadKey WINELIB_NAME_AW(RegLoadKey)
|
||||||
|
LONG WINAPI RegLoadMUIStringA(HKEY,LPCSTR,LPSTR,DWORD,LPDWORD,DWORD,LPCSTR);
|
||||||
|
LONG WINAPI RegLoadMUIStringW(HKEY,LPCWSTR,LPWSTR,DWORD,LPDWORD,DWORD,LPCWSTR);
|
||||||
|
#define RegLoadMUIString WINELIB_NAME_AW(RegLoadMUIString)
|
||||||
LONG WINAPI RegNotifyChangeKeyValue(HKEY,BOOL,DWORD,HANDLE,BOOL);
|
LONG WINAPI RegNotifyChangeKeyValue(HKEY,BOOL,DWORD,HANDLE,BOOL);
|
||||||
DWORD WINAPI RegOpenCurrentUser(REGSAM,PHKEY);
|
DWORD WINAPI RegOpenCurrentUser(REGSAM,PHKEY);
|
||||||
DWORD WINAPI RegOpenKeyExW(HKEY,LPCWSTR,DWORD,REGSAM,PHKEY);
|
DWORD WINAPI RegOpenKeyExW(HKEY,LPCWSTR,DWORD,REGSAM,PHKEY);
|
||||||
|
|
Loading…
Reference in New Issue