https://git.reactos.org/?p=reactos.git;a=commitdiff;h=6f8cb05cad142a8679872e695f317dc1f9728d55

commit 6f8cb05cad142a8679872e695f317dc1f9728d55
Author:     Joachim Henze <joachim.he...@reactos.org>
AuthorDate: Mon Dec 17 22:01:49 2018 +0100
Commit:     Joachim Henze <joachim.he...@reactos.org>
CommitDate: Mon Dec 17 22:01:49 2018 +0100

    [DESK][SHELL32] Allow Desk.cpl to run standalone on WinXP/2003 again 
CORE-15412
    
    addendum to 0.4.10-dev-502-g
    d559ca9c982f9766acc5db3ea887ef2bc27acdff
    
    That copy-paste was done once intentionally to keep our imports similar to 
2003.
    It's worth reading the conversation in PR #748: Getequ seems to be ok with 
this.
    
    The ideal solution most likely would be to instead *statically*
    link against RegLoadMUIStringW() from advapi32_vista when WINNT=0x502.
    For now the stuff runs again at least.
    I left the func existing in advapi32_vista.dll.
---
 dll/cpl/desk/CMakeLists.txt      |   6 +-
 dll/cpl/desk/desk.h              |   9 ++
 dll/cpl/desk/muireg.c            | 144 ++++++++++++++++++++++++++
 dll/win32/shell32/CMakeLists.txt |   3 +-
 dll/win32/shell32/vista.c        | 218 +++++++++++++++++++++++++++++++++++++++
 5 files changed, 375 insertions(+), 5 deletions(-)

diff --git a/dll/cpl/desk/CMakeLists.txt b/dll/cpl/desk/CMakeLists.txt
index 24d9bb1e60..ae7fb83825 100644
--- a/dll/cpl/desk/CMakeLists.txt
+++ b/dll/cpl/desk/CMakeLists.txt
@@ -2,9 +2,6 @@
 add_definitions(-D_WIN32)
 spec2def(desk.cpl desk.spec)
 
-remove_definitions(-D_WIN32_WINNT=0x502)
-add_definitions(-D_WIN32_WINNT=0x600)
-
 list(APPEND SOURCE
     advmon.c
     appearance.c
@@ -23,6 +20,7 @@ list(APPEND SOURCE
     general.c
     draw.c
     theme.c
+    muireg.c
     desk.h)
 
 file(GLOB desk_rc_deps resources/*.*)
@@ -36,6 +34,6 @@ add_library(desk SHARED
 
 set_module_type(desk cpl UNICODE)
 target_link_libraries(desk uuid)
-add_importlibs(desk user32 advapi32 advapi32_vista gdi32 comctl32 comdlg32 
ole32 setupapi shell32 shlwapi uxtheme gdiplus msvcrt kernel32 ntdll)
+add_importlibs(desk user32 advapi32 gdi32 comctl32 comdlg32 ole32 setupapi 
shell32 shlwapi uxtheme gdiplus msvcrt kernel32 ntdll)
 add_pch(desk desk.h SOURCE)
 add_cd_file(TARGET desk DESTINATION reactos/system32 FOR all)
diff --git a/dll/cpl/desk/desk.h b/dll/cpl/desk/desk.h
index 3bb02f3a74..3c479251cf 100644
--- a/dll/cpl/desk/desk.h
+++ b/dll/cpl/desk/desk.h
@@ -122,4 +122,13 @@ HPSXA WINAPI 
SHCreatePropSheetExtArrayEx(HKEY,LPCWSTR,UINT,IDataObject*);
 INT_PTR CALLBACK
 AdvGeneralPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
 
+LONG
+RegLoadMUIStringW(IN HKEY hKey,
+                  IN LPCWSTR pszValue  OPTIONAL,
+                  OUT LPWSTR pszOutBuf,
+                  IN DWORD cbOutBuf,
+                  OUT LPDWORD pcbData OPTIONAL,
+                  IN DWORD Flags,
+                  IN LPCWSTR pszDirectory  OPTIONAL);
+
 #endif /* _DESK_H */
diff --git a/dll/cpl/desk/muireg.c b/dll/cpl/desk/muireg.c
new file mode 100644
index 0000000000..8754b43655
--- /dev/null
+++ b/dll/cpl/desk/muireg.c
@@ -0,0 +1,144 @@
+#include "desk.h"
+
+/******************************************************************************
+ * 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
+ *
+ * @implemented
+ */
+LONG
+RegLoadMUIStringW(IN HKEY hKey,
+                  IN LPCWSTR pszValue  OPTIONAL,
+                  OUT LPWSTR pszOutBuf,
+                  IN DWORD cbOutBuf,
+                  OUT LPDWORD pcbData OPTIONAL,
+                  IN DWORD Flags,
+                  IN LPCWSTR pszDirectory  OPTIONAL)
+{
+    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 = LoadLibraryExW(pwszExpandedBuffer + 1, NULL, 
LOAD_LIBRARY_AS_DATAFILE);
+        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;
+}
diff --git a/dll/win32/shell32/CMakeLists.txt b/dll/win32/shell32/CMakeLists.txt
index 08933dda35..78ee1af531 100644
--- a/dll/win32/shell32/CMakeLists.txt
+++ b/dll/win32/shell32/CMakeLists.txt
@@ -102,6 +102,7 @@ add_library(shell32 SHARED
     wine/shellstring.c
     wine/shlmenu.c
     wine/shpolicy.c
+    vista.c
     shell32.rc
     ${CMAKE_CURRENT_BINARY_DIR}/shell32_stubs.c
     ${CMAKE_CURRENT_BINARY_DIR}/shell32.def)
@@ -113,7 +114,7 @@ set_source_files_properties(shell32.rc PROPERTIES 
OBJECT_DEPENDS ${CMAKE_CURRENT
 set_module_type(shell32 win32dll UNICODE)
 target_link_libraries(shell32 shellmenu shelldesktop atlnew wine uuid 
recyclebin)
 add_delay_importlibs(shell32 powrprof shdocvw devmgr winspool.drv winmm mpr 
uxtheme ole32 oleaut32 userenv browseui version fmifs)
-add_importlibs(shell32 advapi32 advapi32_vista gdi32 user32 comctl32 comdlg32 
shlwapi msvcrt kernel32 ntdll)
+add_importlibs(shell32 advapi32 gdi32 user32 comctl32 comdlg32 shlwapi msvcrt 
kernel32 ntdll)
 add_dependencies(shell32 stdole2) # shell32_shldisp.tlb needs stdole2.tlb
 add_pch(shell32 precomp.h SOURCE)
 add_cd_file(TARGET shell32 DESTINATION reactos/system32 FOR all)
diff --git a/dll/win32/shell32/vista.c b/dll/win32/shell32/vista.c
new file mode 100644
index 0000000000..9f1a8335a3
--- /dev/null
+++ b/dll/win32/shell32/vista.c
@@ -0,0 +1,218 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS system libraries
+ * FILE:            Copied from advapi32/reg/reg.c
+ * PURPOSE:         Registry functions
+ * PROGRAMMER:      Ariadne ( aria...@xs4all.nl)
+ *                  Thomas Weidenmueller <w3s...@reactos.com>
+ * UPDATE HISTORY:
+ *                  Created 01/11/98
+ *                  19990309 EA Stubs
+ *                  20050502 Fireball imported some stuff from WINE
+ */
+
+#include <stdarg.h>
+
+#define WIN32_NO_STATUS
+#define _INC_WINDOWS
+#define COM_NO_WINDOWS_H
+
+#include <windef.h>
+#include <winbase.h>
+#include <winreg.h>
+#include <winuser.h>
+#define NTOS_MODE_USER
+#include <ndk/rtlfuncs.h>
+
+#include <wine/debug.h>
+#include <wine/unicode.h>
+
+WINE_DEFAULT_DEBUG_CHANNEL(shell);
+
+/******************************************************************************
+ * 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
+ *
+ * @implemented
+ */
+LONG WINAPI
+RegLoadMUIStringW(IN HKEY hKey,
+                  IN LPCWSTR pszValue  OPTIONAL,
+                  OUT LPWSTR pszOutBuf,
+                  IN DWORD cbOutBuf,
+                  OUT LPDWORD pcbData OPTIONAL,
+                  IN DWORD Flags,
+                  IN LPCWSTR pszDirectory  OPTIONAL)
+{
+    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 = LoadLibraryExW(pwszExpandedBuffer + 1, NULL, 
LOAD_LIBRARY_AS_DATAFILE);
+        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
+ *
+ * @implemented
+ */
+LONG WINAPI
+RegLoadMUIStringA(IN HKEY hKey,
+                  IN LPCSTR pszValue  OPTIONAL,
+                  OUT LPSTR pszOutBuf,
+                  IN DWORD cbOutBuf,
+                  OUT LPDWORD pcbData OPTIONAL,
+                  IN DWORD Flags,
+                  IN LPCSTR pszDirectory  OPTIONAL)
+{
+    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;
+}

Reply via email to