[ros-diffs] [weiden] 29668: Port RegLoadMUIStringA/W from WINE HEAD and adjust parameter names

weiden at svn.reactos.org weiden at svn.reactos.org
Fri Oct 19 04:40:23 CEST 2007


Author: weiden
Date: Fri Oct 19 06:40:23 2007
New Revision: 29668

URL: http://svn.reactos.org/svn/reactos?rev=29668&view=rev
Log:
Port RegLoadMUIStringA/W from WINE HEAD and adjust parameter names

Modified:
    trunk/reactos/dll/win32/advapi32/reg/reg.c

Modified: trunk/reactos/dll/win32/advapi32/reg/reg.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/advapi32/reg/reg.c?rev=29668&r1=29667&r2=29668&view=diff
==============================================================================
--- trunk/reactos/dll/win32/advapi32/reg/reg.c (original)
+++ trunk/reactos/dll/win32/advapi32/reg/reg.c Fri Oct 19 06:40:23 2007
@@ -4848,11 +4848,53 @@
   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] = L'\0';
+    }
+
+    return cMaxChars;
+}
+
 
 /************************************************************************
  *  RegLoadMUIStringW
  *
- * @unimplemented
+ * @implemented
  */
 LONG STDCALL
 RegLoadMUIStringW(IN HKEY hKey,
@@ -4863,16 +4905,85 @@
                   IN DWORD Flags,
                   IN LPCWSTR pszDirectory  OPTIONAL)
 {
-    FIXME("RegLoadMUIStringW(0x%p, 0x%p, 0x%p, 0x%x, 0x%p, 0x%x, 0x%p) UNIMPLEMENTED!\n",
-          hKey, pszValue, pszOutBuf, cbOutBuf, pcbData, Flags, pszDirectory);
-    return ERROR_CALL_NOT_IMPLEMENTED;
+    DWORD dwValueType, cbData;
+    LPWSTR pwszTempBuffer = NULL, pwszExpandedBuffer = NULL;
+    LONG result;
+
+    /* Parameter sanity checks. */
+    if (!hKey || !pszOutBuf)
+        return ERROR_INVALID_PARAMETER;
+
+    if (pszDirectory && *pszDirectory) {
+        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, pszValue, 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, pszValue, 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 != L'@') { /* '@' is the prefix for resource based string entries. */
+        lstrcpynW(pszOutBuf, pwszExpandedBuffer, cbOutBuf / sizeof(WCHAR));
+    } else {
+        WCHAR *pComma = wcsrchr(pwszExpandedBuffer, L',');
+        UINT uiStringId;
+        HMODULE hModule;
+
+        /* Format of the expanded value is 'path_to_dll,-resId' */
+        if (!pComma || pComma[1] != L'-') {
+            result = ERROR_BADKEY;
+            goto cleanup;
+        }
+ 
+        uiStringId = _wtoi(pComma+2);
+        *pComma = L'\0';
+
+        hModule = LoadLibraryW(pwszExpandedBuffer + 1);
+        if (!hModule || !load_string(hModule, uiStringId, pszOutBuf, cbOutBuf / sizeof(WCHAR)))
+            result = ERROR_BADKEY;
+        FreeLibrary(hModule);
+    }
+ 
+cleanup:
+    HeapFree(GetProcessHeap(), 0, pwszTempBuffer);
+    HeapFree(GetProcessHeap(), 0, pwszExpandedBuffer);
+    return result;
 }
 
 
 /************************************************************************
  *  RegLoadMUIStringA
  *
- * @unimplemented
+ * @implemented
  */
 LONG STDCALL
 RegLoadMUIStringA(IN HKEY hKey,
@@ -4883,9 +4994,35 @@
                   IN DWORD Flags,
                   IN LPCSTR pszDirectory  OPTIONAL)
 {
-    FIXME("RegLoadMUIStringA(0x%p, 0x%p, 0x%p, 0x%x, 0x%p, 0x%x, 0x%p) UNIMPLEMENTED!\n",
-          hKey, pszValue, pszOutBuf, cbOutBuf, pcbData, Flags, pszDirectory);
-    return ERROR_CALL_NOT_IMPLEMENTED;
+    UNICODE_STRING valueW, baseDirW;
+    WCHAR *pwszBuffer;
+    DWORD cbData = cbOutBuf * sizeof(WCHAR);
+    LONG result;
+
+    valueW.Buffer = baseDirW.Buffer = pwszBuffer = NULL;
+    if (!RtlCreateUnicodeStringFromAsciiz(&valueW, pszValue) ||
+        !RtlCreateUnicodeStringFromAsciiz(&baseDirW, pszDirectory) ||
+        !(pwszBuffer = HeapAlloc(GetProcessHeap(), 0, cbData)))
+    {
+        result = ERROR_NOT_ENOUGH_MEMORY;
+        goto cleanup;
+    }
+
+    result = RegLoadMUIStringW(hKey, valueW.Buffer, pwszBuffer, cbData, NULL, Flags, 
+                               baseDirW.Buffer);
+ 
+    if (result == ERROR_SUCCESS) {
+        cbData = WideCharToMultiByte(CP_ACP, 0, pwszBuffer, -1, pszOutBuf, cbOutBuf, NULL, NULL);
+        if (pcbData)
+            *pcbData = cbData;
+    }
+
+cleanup:
+    HeapFree(GetProcessHeap(), 0, pwszBuffer);
+    RtlFreeUnicodeString(&baseDirW);
+    RtlFreeUnicodeString(&valueW);
+ 
+    return result;
 }
 
 




More information about the Ros-diffs mailing list