Michael Jung : advapi32: Implemented RegLoadMUIString[AW].

Alexandre Julliard julliard at wine.codeweavers.com
Tue Feb 14 07:27:36 CST 2006


Module: wine
Branch: refs/heads/master
Commit: ac615ce5a05299523899da5b7fd790c724691d2a
URL:    http://source.winehq.org/git/?p=wine.git;a=commit;h=ac615ce5a05299523899da5b7fd790c724691d2a

Author: Michael Jung <mjung at iss.tu-darmstadt.de>
Date:   Tue Feb 14 10:41:18 2006 +0100

advapi32: Implemented RegLoadMUIString[AW].

---

 dlls/advapi32/advapi32.spec |    2 
 dlls/advapi32/registry.c    |  187 +++++++++++++++++++++++++++++++++++++++++++
 include/winreg.h            |    3 +
 3 files changed, 192 insertions(+), 0 deletions(-)

diff --git a/dlls/advapi32/advapi32.spec b/dlls/advapi32/advapi32.spec
index 61eb2c9..8fb6592 100644
--- a/dlls/advapi32/advapi32.spec
+++ b/dlls/advapi32/advapi32.spec
@@ -486,6 +486,8 @@
 @ stdcall RegGetValueW(long wstr wstr long ptr ptr ptr)
 @ stdcall RegLoadKeyA(long str str)
 @ 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 RegOpenCurrentUser(long ptr)
 @ stdcall RegOpenKeyA(long str ptr)
diff --git a/dlls/advapi32/registry.c b/dlls/advapi32/registry.c
index df56997..a51e8e9 100644
--- a/dlls/advapi32/registry.c
+++ b/dlls/advapi32/registry.c
@@ -37,6 +37,7 @@
 #include "winreg.h"
 #include "winerror.h"
 #include "winternl.h"
+#include "winuser.h"
 
 #include "wine/unicode.h"
 #include "wine/debug.h"
@@ -2378,3 +2379,189 @@ LONG WINAPI RegOpenUserClassesRoot(
     *phkResult = HKEY_CLASSES_ROOT;
     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;
+}
diff --git a/include/winreg.h b/include/winreg.h
index 85fa2ea..7147150 100644
--- a/include/winreg.h
+++ b/include/winreg.h
@@ -113,6 +113,9 @@ LONG        WINAPI RegGetValueW(HKEY,LPC
 LONG        WINAPI RegLoadKeyA(HKEY,LPCSTR,LPCSTR);
 LONG        WINAPI RegLoadKeyW(HKEY,LPCWSTR,LPCWSTR);
 #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);
 DWORD       WINAPI RegOpenCurrentUser(REGSAM,PHKEY);
 DWORD       WINAPI RegOpenKeyExW(HKEY,LPCWSTR,DWORD,REGSAM,PHKEY);




More information about the wine-cvs mailing list