diff --git a/README.md b/README.md index 5d2eb995..04e949dc 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ Wine. All those differences are also documented on the Included bug fixes and improvements =================================== -**Bugfixes and features included in the next upcoming release [7]:** +**Bugfixes and features included in the next upcoming release [8]:** * Add stub for D3DXComputeTangentFrameEx ([Wine Bug #31984](https://bugs.winehq.org/show_bug.cgi?id=31984)) * Add stub for D3DXIntersect @@ -46,6 +46,7 @@ Included bug fixes and improvements * GetMonitorInfo returns the same name for all monitors ([Wine Bug #37709](https://bugs.winehq.org/show_bug.cgi?id=37709)) * Implement ID3DXEffect::FindNextValidTechnique ([Wine Bug #34101](https://bugs.winehq.org/show_bug.cgi?id=34101)) * Implement IDXGIOutput::GetDesc +* Support for SLGetWindowsInformationDWORD ([Wine Bug #36709](https://bugs.winehq.org/show_bug.cgi?id=36709)) **Bugs fixed in Wine Staging 1.7.33 [119]:** diff --git a/debian/changelog b/debian/changelog index ef1fc128..ce22df49 100644 --- a/debian/changelog +++ b/debian/changelog @@ -13,6 +13,7 @@ wine-staging (1.7.34) UNRELEASED; urgency=low * Added patch with stub for D3DXComputeTangentFrameEx. * Added patch with stub for D3DXIntersect. * Added test for RtlIpv4StringToAddressExA. + * Added patch for support of SLGetWindowsInformationDWORD. * Removed patch to implement combase HSTRING objects (accepted upstream). * Removed patch to add fake ProductId to registry (accepted upstream). * Removed patch to implement stubs for MFStartup and MFShutdown (accepted upstream). diff --git a/patches/Makefile b/patches/Makefile index fb68e179..c47751a3 100644 --- a/patches/Makefile +++ b/patches/Makefile @@ -109,6 +109,7 @@ PATCHLIST := \ shell32-SHFileOperation.ok \ shlwapi-PathIsDirectoryEmptyW.ok \ shlwapi-UrlCombine.ok \ + slc-SLGetWindowsInformation.ok \ urlmon-CoInternetSetFeatureEnabled.ok \ user32-Dialog_Paint_Event.ok \ user32-DrawTextExW.ok \ @@ -1688,6 +1689,28 @@ shlwapi-UrlCombine.ok: echo '+ { "Sebastian Lackner", "shlwapi: UrlCombineW workaround for relative paths.", 1 },'; \ ) > shlwapi-UrlCombine.ok +# Patchset slc-SLGetWindowsInformation +# | +# | This patchset fixes the following Wine bugs: +# | * [#36709] Support for SLGetWindowsInformationDWORD +# | +# | Modified files: +# | * configure.ac, dlls/ntdll/ntdll.spec, dlls/ntdll/reg.c, dlls/ntdll/tests/reg.c, dlls/slc/slc.c, +# | dlls/slc/tests/Makefile.in, dlls/slc/tests/slc.c, include/slerror.h, include/winternl.h, loader/wine.inf.in +# | +.INTERMEDIATE: slc-SLGetWindowsInformation.ok +slc-SLGetWindowsInformation.ok: + $(call APPLY_FILE,slc-SLGetWindowsInformation/0001-slc-tests-Add-tests-for-SLGetWindowsInformationDWORD.patch) + $(call APPLY_FILE,slc-SLGetWindowsInformation/0002-ntdll-tests-Add-tests-for-NtQueryLicenseKey.patch) + $(call APPLY_FILE,slc-SLGetWindowsInformation/0003-ntdll-Implement-Nt-Zw-QueryLicenseValue.patch) + $(call APPLY_FILE,slc-SLGetWindowsInformation/0004-slc-Implement-SLGetWindowsInformationDWORD.patch) + @( \ + echo '+ { "Sebastian Lackner", "slc/tests: Add tests for SLGetWindowsInformationDWORD.", 1 },'; \ + echo '+ { "Sebastian Lackner", "ntdll/tests: Add tests for NtQueryLicenseKey.", 1 },'; \ + echo '+ { "Sebastian Lackner", "ntdll: Implement [Nt|Zw]QueryLicenseValue.", 1 },'; \ + echo '+ { "Sebastian Lackner", "slc: Implement SLGetWindowsInformationDWORD.", 1 },'; \ + ) > slc-SLGetWindowsInformation.ok + # Patchset urlmon-CoInternetSetFeatureEnabled # | # | This patchset fixes the following Wine bugs: diff --git a/patches/slc-SLGetWindowsInformation/0001-slc-tests-Add-tests-for-SLGetWindowsInformationDWORD.patch b/patches/slc-SLGetWindowsInformation/0001-slc-tests-Add-tests-for-SLGetWindowsInformationDWORD.patch new file mode 100644 index 00000000..2c08a7dd --- /dev/null +++ b/patches/slc-SLGetWindowsInformation/0001-slc-tests-Add-tests-for-SLGetWindowsInformationDWORD.patch @@ -0,0 +1,138 @@ +From 509bb7172754c95f340aacfeae365e6da7007305 Mon Sep 17 00:00:00 2001 +From: Sebastian Lackner +Date: Mon, 22 Dec 2014 07:26:37 +0100 +Subject: slc/tests: Add tests for SLGetWindowsInformationDWORD. + +--- + configure.ac | 1 + + dlls/slc/tests/Makefile.in | 5 +++ + dlls/slc/tests/slc.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++ + include/slerror.h | 1 + + 4 files changed, 87 insertions(+) + create mode 100644 dlls/slc/tests/Makefile.in + create mode 100644 dlls/slc/tests/slc.c + +diff --git a/configure.ac b/configure.ac +index 2fa4dcc..0eaa26e 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -3228,6 +3228,7 @@ WINE_CONFIG_DLL(shlwapi,,[implib,po]) + WINE_CONFIG_TEST(dlls/shlwapi/tests) + WINE_CONFIG_DLL(slbcsp) + WINE_CONFIG_DLL(slc,,[implib]) ++WINE_CONFIG_TEST(dlls/slc/tests) + WINE_CONFIG_DLL(snmpapi,,[implib]) + WINE_CONFIG_TEST(dlls/snmpapi/tests) + WINE_CONFIG_DLL(softpub) +diff --git a/dlls/slc/tests/Makefile.in b/dlls/slc/tests/Makefile.in +new file mode 100644 +index 0000000..51b648c +--- /dev/null ++++ b/dlls/slc/tests/Makefile.in +@@ -0,0 +1,5 @@ ++TESTDLL = slc.dll ++IMPORTS = slc ++ ++C_SRCS = \ ++ slc.c +diff --git a/dlls/slc/tests/slc.c b/dlls/slc/tests/slc.c +new file mode 100644 +index 0000000..723cd4c +--- /dev/null ++++ b/dlls/slc/tests/slc.c +@@ -0,0 +1,80 @@ ++/* ++ * Copyright 2014 Sebastian Lackner ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA ++ */ ++ ++#include ++ ++#include "windef.h" ++#include "winbase.h" ++#include "winerror.h" ++ ++#include "slpublic.h" ++#include "slerror.h" ++ ++#include ++ ++static void test_SLGetWindowsInformationDWORD(void) ++{ ++ static const WCHAR NonexistentLicenseValueW[] = {'N','o','n','e','x','i','s','t','e','n','t','-', ++ 'L','i','c','e','n','s','e','-','V','a','l','u','e',0}; ++ static const WCHAR KernelMUILanguageAllowedW[] = {'K','e','r','n','e','l','-','M','U','I','-', ++ 'L','a','n','g','u','a','g','e','-','A','l','l','o','w','e','d',0}; ++ static const WCHAR KernelMUINumberAllowedW[] = {'K','e','r','n','e','l','-','M','U','I','-', ++ 'N','u','m','b','e','r','-','A','l','l','o','w','e','d',0}; ++ static const WCHAR emptyW[] = {0}; ++ DWORD value; ++ HRESULT res; ++ ++ res = SLGetWindowsInformationDWORD(NonexistentLicenseValueW, NULL); ++ todo_wine ++ ok(res == E_INVALIDARG, "expected E_INVALIDARG, got %08x\n", res); ++ ++ res = SLGetWindowsInformationDWORD(NULL, &value); ++ todo_wine ++ ok(res == E_INVALIDARG, "expected E_INVALIDARG, got %08x\n", res); ++ ++ value = 0xdeadbeef; ++ res = SLGetWindowsInformationDWORD(NonexistentLicenseValueW, &value); ++ todo_wine ++ ok(res == SL_E_VALUE_NOT_FOUND, "expected SL_E_VALUE_NOT_FOUND, got %08x\n", res); ++ ok(value == 0xdeadbeef, "expected value = 0xdeadbeef, got %u\n", value); ++ ++ value = 0xdeadbeef; ++ res = SLGetWindowsInformationDWORD(emptyW, &value); ++ ok(res == SL_E_RIGHT_NOT_GRANTED || broken(res == 0xd000000d) /* Win 8 */, ++ "expected SL_E_RIGHT_NOT_GRANTED, got %08x\n", res); ++ ok(value == 0xdeadbeef, "expected value = 0xdeadbeef, got %u\n", value); ++ ++ value = 0xdeadbeef; ++ res = SLGetWindowsInformationDWORD(KernelMUILanguageAllowedW, &value); ++ todo_wine ++ ok(res == SL_E_DATATYPE_MISMATCHED, "expected SL_E_DATATYPE_MISMATCHED, got %08x\n", res); ++ ok(value == 0xdeadbeef, "expected value = 0xdeadbeef, got %u\n", value); ++ ++ value = 0xdeadbeef; ++ res = SLGetWindowsInformationDWORD(KernelMUINumberAllowedW, &value); ++ todo_wine ++ ok(res == S_OK, "expected S_OK, got %u\n", res); ++ todo_wine ++ ok(value != 0xdeadbeef, "expected value != 0xdeadbeef\n"); ++} ++ ++ ++START_TEST(slc) ++{ ++ test_SLGetWindowsInformationDWORD(); ++} +diff --git a/include/slerror.h b/include/slerror.h +index 9c800f6..8b45d99 100644 +--- a/include/slerror.h ++++ b/include/slerror.h +@@ -19,6 +19,7 @@ + #ifndef __WINE_SLERROR_H + #define __WINE_SLERROR_H + ++#define SL_E_VALUE_NOT_FOUND 0xC004F012 + #define SL_E_RIGHT_NOT_GRANTED 0xC004F013 + #define SL_E_DATATYPE_MISMATCHED 0xC004F01E + +-- +2.2.1 + diff --git a/patches/slc-SLGetWindowsInformation/0002-ntdll-tests-Add-tests-for-NtQueryLicenseKey.patch b/patches/slc-SLGetWindowsInformation/0002-ntdll-tests-Add-tests-for-NtQueryLicenseKey.patch new file mode 100644 index 00000000..638e025e --- /dev/null +++ b/patches/slc-SLGetWindowsInformation/0002-ntdll-tests-Add-tests-for-NtQueryLicenseKey.patch @@ -0,0 +1,224 @@ +From 64499777f47b43e13a280ed64af304a9f85ad15f Mon Sep 17 00:00:00 2001 +From: Sebastian Lackner +Date: Mon, 22 Dec 2014 07:58:10 +0100 +Subject: ntdll/tests: Add tests for NtQueryLicenseKey. + +--- + dlls/ntdll/tests/reg.c | 180 +++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 180 insertions(+) + +diff --git a/dlls/ntdll/tests/reg.c b/dlls/ntdll/tests/reg.c +index 08af73e..968c291 100644 +--- a/dlls/ntdll/tests/reg.c ++++ b/dlls/ntdll/tests/reg.c +@@ -130,6 +130,7 @@ static NTSTATUS (WINAPI * pNtCreateKey)( PHANDLE retkey, ACCESS_MASK access, con + ULONG TitleIndex, const UNICODE_STRING *class, ULONG options, + PULONG dispos ); + static NTSTATUS (WINAPI * pNtQueryKey)(HANDLE,KEY_INFORMATION_CLASS,PVOID,ULONG,PULONG); ++static NTSTATUS (WINAPI * pNtQueryLicenseValue)(const UNICODE_STRING *,ULONG *,PVOID,ULONG,ULONG *); + static NTSTATUS (WINAPI * pNtQueryValueKey)(HANDLE,const UNICODE_STRING *,KEY_VALUE_INFORMATION_CLASS,void *,DWORD,DWORD *); + static NTSTATUS (WINAPI * pNtSetValueKey)(HANDLE, const PUNICODE_STRING, ULONG, + ULONG, const void*, ULONG ); +@@ -191,6 +192,10 @@ static BOOL InitFunctionPtrs(void) + NTDLL_GET_PROC(RtlZeroMemory) + NTDLL_GET_PROC(RtlpNtQueryValueKey) + NTDLL_GET_PROC(RtlOpenCurrentUser) ++ ++ /* optional functions */ ++ pNtQueryLicenseValue = (void *)GetProcAddress(hntdll, "NtQueryLicenseValue"); ++ + return TRUE; + } + #undef NTDLL_GET_PROC +@@ -645,6 +650,180 @@ static void test_NtDeleteKey(void) + ok(status == STATUS_SUCCESS, "NtDeleteKey Failed: 0x%08x\n", status); + } + ++static void test_NtQueryLicenseKey(void) ++{ ++ static const WCHAR emptyW[] = {'E','M','P','T','Y',0}; ++ UNICODE_STRING name; ++ WORD buffer[32]; ++ NTSTATUS status; ++ ULONG type, len; ++ DWORD value; ++ ++ if (!pNtQueryLicenseValue) ++ { ++ skip("NtQueryLicenseValue not found, skipping tests\n"); ++ return; ++ } ++ ++ type = 0xdead; ++ len = 0xbeef; ++ memset(&name, 0, sizeof(name)); ++ status = pNtQueryLicenseValue(&name, &type, buffer, sizeof(buffer), &len); ++ ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status); ++ ok(type == 0xdead, "expected unmodified value for type, got %u\n", type); ++ ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len); ++ ++ /* test with empty key */ ++ pRtlCreateUnicodeStringFromAsciiz(&name, ""); ++ ++ type = 0xdead; ++ len = 0xbeef; ++ status = pNtQueryLicenseValue(NULL, &type, buffer, sizeof(buffer), &len); ++ ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status); ++ ok(type == 0xdead, "expected unmodified value for type, got %u\n", type); ++ ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len); ++ ++ type = 0xdead; ++ status = pNtQueryLicenseValue(&name, &type, buffer, sizeof(buffer), NULL); ++ ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status); ++ ok(type == 0xdead, "expected unmodified value for type, got %u\n", type); ++ ++ len = 0xbeef; ++ status = pNtQueryLicenseValue(&name, NULL, buffer, sizeof(buffer), &len); ++ ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status); ++ ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len); ++ ++ type = 0xdead; ++ len = 0xbeef; ++ status = pNtQueryLicenseValue(&name, &type, buffer, sizeof(buffer), &len); ++ ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status); ++ ok(type == 0xdead, "expected unmodified value for type, got %u\n", type); ++ ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len); ++ ++ pRtlFreeUnicodeString(&name); ++ ++ /* test with nonexistent licence key */ ++ pRtlCreateUnicodeStringFromAsciiz(&name, "Nonexistent-License-Value"); ++ ++ type = 0xdead; ++ len = 0xbeef; ++ status = pNtQueryLicenseValue(NULL, &type, buffer, sizeof(buffer), &len); ++ ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status); ++ ok(type == 0xdead, "expected unmodified value for type, got %u\n", type); ++ ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len); ++ ++ type = 0xdead; ++ status = pNtQueryLicenseValue(&name, &type, buffer, sizeof(buffer), NULL); ++ ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status); ++ ok(type == 0xdead, "expected unmodified value for type, got %u\n", type); ++ ++ len = 0xbeef; ++ status = pNtQueryLicenseValue(&name, NULL, buffer, sizeof(buffer), &len); ++ ok(status == STATUS_OBJECT_NAME_NOT_FOUND, "NtQueryLicenseValue returned %08x, expected STATUS_OBJECT_NAME_NOT_FOUND\n", status); ++ ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len); ++ ++ type = 0xdead; ++ len = 0xbeef; ++ status = pNtQueryLicenseValue(&name, &type, buffer, sizeof(buffer), &len); ++ ok(status == STATUS_OBJECT_NAME_NOT_FOUND, "NtQueryLicenseValue unexpected suceeded\n"); ++ ok(type == 0xdead, "expected unmodified value for type, got %u\n", type); ++ ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len); ++ ++ pRtlFreeUnicodeString(&name); ++ ++ /* test with REG_SZ license key */ ++ pRtlCreateUnicodeStringFromAsciiz(&name, "Kernel-MUI-Language-Allowed"); ++ ++ type = 0xdead; ++ len = 0xbeef; ++ status = pNtQueryLicenseValue(NULL, &type, buffer, sizeof(buffer), &len); ++ ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status); ++ ok(type == 0xdead, "expected unmodified value for type, got %u\n", type); ++ ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len); ++ ++ type = 0xdead; ++ status = pNtQueryLicenseValue(&name, &type, buffer, sizeof(buffer), NULL); ++ ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status); ++ ok(type == 0xdead, "expected unmodified value for type, got %u\n", type); ++ ++ type = 0xdead; ++ len = 0; ++ status = pNtQueryLicenseValue(&name, &type, buffer, 0, &len); ++ ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryLicenseValue returned %08x, expected STATUS_BUFFER_TOO_SMALL\n", status); ++ ok(type == REG_SZ, "expected type = REG_SZ, got %u\n", type); ++ ok(len == sizeof(emptyW), "expected len = %u, got %u\n", sizeof(emptyW), len); ++ ++ len = 0; ++ status = pNtQueryLicenseValue(&name, NULL, buffer, 0, &len); ++ ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryLicenseValue returned %08x, expected STATUS_BUFFER_TOO_SMALL\n", status); ++ ok(len == sizeof(emptyW), "expected len = %u, got %u\n", sizeof(emptyW), len); ++ ++ type = 0xdead; ++ len = 0; ++ memset(buffer, 0x11, sizeof(buffer)); ++ status = pNtQueryLicenseValue(&name, &type, buffer, sizeof(buffer), &len); ++ ok(status == STATUS_SUCCESS, "NtQueryLicenseValue returned %08x, expected STATUS_SUCCESS\n", status); ++ ok(type == REG_SZ, "expected type = REG_SZ, got %u\n", type); ++ ok(len == sizeof(emptyW), "expected len = %u, got %u\n", sizeof(emptyW), len); ++ ok(!memcmp(buffer, emptyW, sizeof(emptyW)), "unexpected buffer content\n"); ++ ++ type = 0xdead; ++ len = 0; ++ memset(buffer, 0x11, sizeof(buffer)); ++ status = pNtQueryLicenseValue(&name, &type, buffer, 2, &len); ++ ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryLicenseValue returned %08x, expected STATUS_BUFFER_TOO_SMALL\n", status); ++ ok(type == REG_SZ, "expected type REG_SZ, got %u\n", type); ++ ok(len == sizeof(emptyW), "expected len = %u, got %u\n", sizeof(emptyW), len); ++ ok(buffer[0] == 0x1111, "expected buffer[0] = 0x1111, got %u\n", buffer[0]); ++ ++ pRtlFreeUnicodeString(&name); ++ ++ /* test with REG_DWORD license key */ ++ pRtlCreateUnicodeStringFromAsciiz(&name, "Kernel-MUI-Number-Allowed"); ++ ++ type = 0xdead; ++ len = 0xbeef; ++ status = pNtQueryLicenseValue(NULL, &type, &value, sizeof(value), &len); ++ ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status); ++ ok(type == 0xdead, "expected unmodified value for type, got %u\n", type); ++ ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len); ++ ++ type = 0xdead; ++ status = pNtQueryLicenseValue(&name, &type, &value, sizeof(value), NULL); ++ ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status); ++ ok(type == 0xdead, "expected unmodified value for type, got %u\n", type); ++ ++ type = 0xdead; ++ len = 0; ++ status = pNtQueryLicenseValue(&name, &type, &value, 0, &len); ++ ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryLicenseValue returned %08x, expected STATUS_BUFFER_TOO_SMALL\n", status); ++ ok(type == REG_DWORD, "expected type = REG_DWORD, got %u\n", type); ++ ok(len == sizeof(value), "expected len = %u, got %u\n", sizeof(value), len); ++ ++ len = 0; ++ status = pNtQueryLicenseValue(&name, NULL, &value, 0, &len); ++ ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryLicenseValue returned %08x, expected STATUS_BUFFER_TOO_SMALL\n", status); ++ ok(len == sizeof(value), "expected len = %u, got %u\n", sizeof(value), len); ++ ++ type = 0xdead; ++ len = 0; ++ value = 0xdeadbeef; ++ status = pNtQueryLicenseValue(&name, &type, &value, sizeof(value), &len); ++ ok(status == STATUS_SUCCESS, "NtQueryLicenseValue returned %08x, expected STATUS_SUCCESS\n", status); ++ ok(type == REG_DWORD, "expected type = REG_DWORD, got %u\n", type); ++ ok(len == sizeof(value), "expected len = %u, got %u\n", sizeof(value), len); ++ ok(value != 0xdeadbeef, "expected value != 0xdeadbeef\n"); ++ ++ type = 0xdead; ++ len = 0; ++ status = pNtQueryLicenseValue(&name, &type, &value, 2, &len); ++ ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryLicenseValue returned %08x, expected STATUS_BUFFER_TOO_SMALL\n", status); ++ ok(type == REG_DWORD, "expected type REG_DWORD, got %u\n", type); ++ ok(len == sizeof(value), "expected len = %u, got %u\n", sizeof(value), len); ++ ++ pRtlFreeUnicodeString(&name); ++} ++ + static void test_RtlpNtQueryValueKey(void) + { + NTSTATUS status; +@@ -1347,6 +1526,7 @@ START_TEST(reg) + test_NtFlushKey(); + test_NtQueryKey(); + test_NtQueryValueKey(); ++ test_NtQueryLicenseKey(); + test_long_value_name(); + test_NtDeleteKey(); + test_symlinks(); +-- +2.2.1 + diff --git a/patches/slc-SLGetWindowsInformation/0003-ntdll-Implement-Nt-Zw-QueryLicenseValue.patch b/patches/slc-SLGetWindowsInformation/0003-ntdll-Implement-Nt-Zw-QueryLicenseValue.patch new file mode 100644 index 00000000..0a831cf3 --- /dev/null +++ b/patches/slc-SLGetWindowsInformation/0003-ntdll-Implement-Nt-Zw-QueryLicenseValue.patch @@ -0,0 +1,195 @@ +From 93534274eab90da6059cdc56d1e58912d2071101 Mon Sep 17 00:00:00 2001 +From: Sebastian Lackner +Date: Mon, 22 Dec 2014 20:01:29 +0100 +Subject: ntdll: Implement [Nt|Zw]QueryLicenseValue. + +--- + dlls/ntdll/ntdll.spec | 2 ++ + dlls/ntdll/reg.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++ + dlls/ntdll/tests/reg.c | 2 +- + include/winternl.h | 1 + + loader/wine.inf.in | 26 ++++++++++++++++---- + 5 files changed, 90 insertions(+), 5 deletions(-) + +diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec +index 51de6e7..da43cf0 100644 +--- a/dlls/ntdll/ntdll.spec ++++ b/dlls/ntdll/ntdll.spec +@@ -255,6 +255,7 @@ + @ stub NtQueryIntervalProfile + @ stdcall NtQueryIoCompletion(long long ptr long ptr) + @ stdcall NtQueryKey (long long ptr long ptr) ++@ stdcall NtQueryLicenseValue(ptr ptr ptr long ptr) + @ stdcall NtQueryMultipleValueKey(long ptr long ptr long ptr) + @ stdcall NtQueryMutant(long long ptr long ptr) + @ stdcall NtQueryObject(long long long long long) +@@ -1134,6 +1135,7 @@ + @ stub ZwQueryIntervalProfile + @ stdcall ZwQueryIoCompletion(long long ptr long ptr) NtQueryIoCompletion + @ stdcall ZwQueryKey(long long ptr long ptr) NtQueryKey ++@ stdcall ZwQueryLicenseValue(ptr ptr ptr long ptr) NtQueryLicenseValue + @ stdcall ZwQueryMultipleValueKey(long ptr long ptr long ptr) NtQueryMultipleValueKey + @ stdcall ZwQueryMutant(long long ptr long ptr) NtQueryMutant + @ stdcall ZwQueryObject(long long long long long) NtQueryObject +diff --git a/dlls/ntdll/reg.c b/dlls/ntdll/reg.c +index cdca88a..a104c2e 100644 +--- a/dlls/ntdll/reg.c ++++ b/dlls/ntdll/reg.c +@@ -1401,3 +1401,67 @@ NTSTATUS WINAPI RtlWriteRegistryValue( ULONG RelativeTo, PCWSTR path, PCWSTR nam + + return status; + } ++ ++/************************************************************************* ++ * NtQueryLicenseValue [NTDLL.@] ++ * ++ * NOTES ++ * On Windows all license properties are stored in a single key, but ++ * unless there is some app which explicitly depends on that, there is ++ * no good reason to reproduce that. ++ */ ++NTSTATUS WINAPI NtQueryLicenseValue( const UNICODE_STRING *name, ULONG *result_type, ++ PVOID data, ULONG length, ULONG *result_len ) ++{ ++ static const WCHAR LicenseInformationW[] = {'M','a','c','h','i','n','e','\\', ++ 'S','o','f','t','w','a','r','e','\\', ++ 'W','i','n','e','\\','L','i','c','e','n','s','e', ++ 'I','n','f','o','r','m','a','t','i','o','n',0}; ++ KEY_VALUE_PARTIAL_INFORMATION *info; ++ NTSTATUS status = STATUS_OBJECT_NAME_NOT_FOUND; ++ DWORD info_length, count; ++ OBJECT_ATTRIBUTES attr; ++ UNICODE_STRING keyW; ++ HANDLE hkey; ++ ++ if (!name || !name->Buffer || !name->Length || !result_len) ++ return STATUS_INVALID_PARAMETER; ++ ++ info_length = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) + length; ++ info = RtlAllocateHeap( GetProcessHeap(), 0, info_length ); ++ if (!info) return STATUS_NO_MEMORY; ++ ++ attr.Length = sizeof(attr); ++ attr.RootDirectory = 0; ++ attr.ObjectName = &keyW; ++ attr.Attributes = 0; ++ attr.SecurityDescriptor = NULL; ++ attr.SecurityQualityOfService = NULL; ++ RtlInitUnicodeString( &keyW, LicenseInformationW ); ++ ++ /* @@ Wine registry key: HKLM\Software\Wine\LicenseInformation */ ++ if (!NtOpenKey( &hkey, KEY_READ, &attr )) ++ { ++ status = NtQueryValueKey( hkey, name, KeyValuePartialInformation, ++ info, info_length, &count ); ++ if (!status || status == STATUS_BUFFER_OVERFLOW) ++ { ++ if (result_type) ++ *result_type = info->Type; ++ ++ *result_len = info->DataLength; ++ ++ if (status == STATUS_BUFFER_OVERFLOW) ++ status = STATUS_BUFFER_TOO_SMALL; ++ else ++ memcpy( data, info->Data, info->DataLength ); ++ } ++ NtClose( hkey ); ++ } ++ ++ if (status == STATUS_OBJECT_NAME_NOT_FOUND) ++ FIXME( "License key %s not found\n", debugstr_w(name->Buffer) ); ++ ++ RtlFreeHeap( GetProcessHeap(), 0, info ); ++ return status; ++} +diff --git a/dlls/ntdll/tests/reg.c b/dlls/ntdll/tests/reg.c +index 968c291..e7596b8 100644 +--- a/dlls/ntdll/tests/reg.c ++++ b/dlls/ntdll/tests/reg.c +@@ -661,7 +661,7 @@ static void test_NtQueryLicenseKey(void) + + if (!pNtQueryLicenseValue) + { +- skip("NtQueryLicenseValue not found, skipping tests\n"); ++ win_skip("NtQueryLicenseValue not found, skipping tests\n"); + return; + } + +diff --git a/include/winternl.h b/include/winternl.h +index 1a694da..c448760 100644 +--- a/include/winternl.h ++++ b/include/winternl.h +@@ -2184,6 +2184,7 @@ NTSYSAPI NTSTATUS WINAPI NtQuerySystemTime(PLARGE_INTEGER); + NTSYSAPI NTSTATUS WINAPI NtQueryTimer(HANDLE,TIMER_INFORMATION_CLASS,PVOID,ULONG,PULONG); + NTSYSAPI NTSTATUS WINAPI NtQueryTimerResolution(PULONG,PULONG,PULONG); + NTSYSAPI NTSTATUS WINAPI NtQueryValueKey(HANDLE,const UNICODE_STRING *,KEY_VALUE_INFORMATION_CLASS,void *,DWORD,DWORD *); ++NTSYSAPI NTSTATUS WINAPI NtQueryLicenseValue(const UNICODE_STRING *,ULONG *,PVOID,ULONG,ULONG *); + NTSYSAPI NTSTATUS WINAPI NtQueryVirtualMemory(HANDLE,LPCVOID,MEMORY_INFORMATION_CLASS,PVOID,SIZE_T,SIZE_T*); + NTSYSAPI NTSTATUS WINAPI NtQueryVolumeInformationFile(HANDLE,PIO_STATUS_BLOCK,PVOID,ULONG,FS_INFORMATION_CLASS); + NTSYSAPI NTSTATUS WINAPI NtRaiseException(PEXCEPTION_RECORD,PCONTEXT,BOOL); +diff --git a/loader/wine.inf.in b/loader/wine.inf.in +index a4548f2..3c401b1 100644 +--- a/loader/wine.inf.in ++++ b/loader/wine.inf.in +@@ -47,7 +47,8 @@ AddReg=\ + Services, \ + SessionMgr,\ + Tapi,\ +- Timezones ++ Timezones,\ ++ LicenseInformation + + [DefaultInstall.NT] + RegisterDlls=RegisterDllsSection +@@ -71,7 +72,8 @@ AddReg=\ + SessionMgr,\ + Tapi,\ + Timezones,\ +- VersionInfo ++ VersionInfo,\ ++ LicenseInformation + + [DefaultInstall.ntamd64] + RegisterDlls=RegisterDllsSection +@@ -97,7 +99,8 @@ AddReg=\ + SessionMgr,\ + Tapi,\ + Timezones,\ +- VersionInfo.ntamd64 ++ VersionInfo.ntamd64,\ ++ LicenseInformation + + [Wow64Install] + RegisterDlls=RegisterDllsSection +@@ -111,7 +114,8 @@ AddReg=\ + MCI,\ + Misc,\ + Tapi,\ +- VersionInfo.ntamd64 ++ VersionInfo.ntamd64,\ ++ LicenseInformation + + [DefaultInstall.Services] + AddService=BITS,0,BITSService +@@ -3140,3 +3144,17 @@ HKLM,Software\Wow6432Node\Microsoft\Windows NT\CurrentVersion\Time Zones,"Symbol + HKLM,Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Time Zones,"SymbolicLinkValue",0x60000,"\Registry\Machine\Software\Microsoft\Windows NT\CurrentVersion\Time Zones" + HKLM,Software\Wow6432Node\Policies,"SymbolicLinkValue",0x60000,"\Registry\Machine\Software\Policies" + HKLM,Software\Wow6432Node\Registered Applications,"SymbolicLinkValue",0x60000,"\Registry\Machine\Software\Registered Applications" ++ ++[LicenseInformation] ++; based on information from http://www.geoffchappell.com/notes/windows/license/install.htm ++HKLM,Software\Wine\LicenseInformation,"Kernel-MUI-Language-Allowed",,"EMPTY" ++HKLM,Software\Wine\LicenseInformation,"Kernel-MUI-Language-Disallowed",,"EMPTY" ++HKLM,Software\Wine\LicenseInformation,"Kernel-MUI-Number-Allowed",0x10001,1000 ++HKLM,Software\Wine\LicenseInformation,"Shell-InBoxGames-FreeCell-EnableGame",0x10001,0x00000001 ++HKLM,Software\Wine\LicenseInformation,"Shell-InBoxGames-Hearts-EnableGame",0x10001,0x00000001 ++HKLM,Software\Wine\LicenseInformation,"Shell-InBoxGames-Minesweeper-EnableGame",0x10001,0x00000001 ++HKLM,Software\Wine\LicenseInformation,"Shell-InBoxGames-PurblePlace-EnableGame",0x10001,0x00000001 ++HKLM,Software\Wine\LicenseInformation,"Shell-InBoxGames-Shanghai-EnableGame",0x10001,0x00000001 ++HKLM,Software\Wine\LicenseInformation,"Shell-InBoxGames-Solitaire-EnableGame",0x10001,0x00000001 ++HKLM,Software\Wine\LicenseInformation,"Shell-InBoxGames-SpiderSolitaire-EnableGame",0x10001,0x00000001 ++HKLM,Software\Wine\LicenseInformation,"Shell-PremiumInBoxGames-Chess-EnableGame",0x10001,0x00000001 +-- +2.2.1 + diff --git a/patches/slc-SLGetWindowsInformation/0004-slc-Implement-SLGetWindowsInformationDWORD.patch b/patches/slc-SLGetWindowsInformation/0004-slc-Implement-SLGetWindowsInformationDWORD.patch new file mode 100644 index 00000000..be51f664 --- /dev/null +++ b/patches/slc-SLGetWindowsInformation/0004-slc-Implement-SLGetWindowsInformationDWORD.patch @@ -0,0 +1,95 @@ +From 03c03be0348f069e83b0817a525e3fcf69b31024 Mon Sep 17 00:00:00 2001 +From: Sebastian Lackner +Date: Mon, 22 Dec 2014 20:27:07 +0100 +Subject: slc: Implement SLGetWindowsInformationDWORD. + +--- + dlls/slc/slc.c | 24 ++++++++++++++++++++++-- + dlls/slc/tests/slc.c | 6 ------ + 2 files changed, 22 insertions(+), 8 deletions(-) + +diff --git a/dlls/slc/slc.c b/dlls/slc/slc.c +index 1b02c9b..26190f4 100644 +--- a/dlls/slc/slc.c ++++ b/dlls/slc/slc.c +@@ -19,8 +19,11 @@ + + #include + ++#include "ntstatus.h" ++#define WIN32_NO_STATUS + #include "windef.h" + #include "winbase.h" ++#include "winternl.h" + #include "wine/debug.h" + + #include "slpublic.h" +@@ -37,9 +40,26 @@ HRESULT WINAPI SLGetWindowsInformation(LPCWSTR name, SLDATATYPE *type, UINT *val + + HRESULT WINAPI SLGetWindowsInformationDWORD(LPCWSTR lpszValueName, LPDWORD pdwValue) + { +- FIXME("(%s) stub\n", debugstr_w(lpszValueName) ); ++ UNICODE_STRING nameW; ++ NTSTATUS status; ++ ULONG type, len; + +- return SL_E_RIGHT_NOT_GRANTED; ++ TRACE("(%s)\n", debugstr_w(lpszValueName) ); ++ ++ if (!lpszValueName || !pdwValue) ++ return E_INVALIDARG; ++ if (!lpszValueName[0]) ++ return SL_E_RIGHT_NOT_GRANTED; ++ ++ RtlInitUnicodeString( &nameW, lpszValueName ); ++ status = NtQueryLicenseValue( &nameW, &type, pdwValue, sizeof(DWORD), &len ); ++ ++ if ((!status || status == STATUS_BUFFER_TOO_SMALL) && (type != REG_DWORD)) ++ return SL_E_DATATYPE_MISMATCHED; ++ if (status == STATUS_OBJECT_NAME_NOT_FOUND) ++ return SL_E_VALUE_NOT_FOUND; ++ ++ return status ? E_FAIL : S_OK; + } + + /*********************************************************************** +diff --git a/dlls/slc/tests/slc.c b/dlls/slc/tests/slc.c +index 723cd4c..b9296b2 100644 +--- a/dlls/slc/tests/slc.c ++++ b/dlls/slc/tests/slc.c +@@ -40,16 +40,13 @@ static void test_SLGetWindowsInformationDWORD(void) + HRESULT res; + + res = SLGetWindowsInformationDWORD(NonexistentLicenseValueW, NULL); +- todo_wine + ok(res == E_INVALIDARG, "expected E_INVALIDARG, got %08x\n", res); + + res = SLGetWindowsInformationDWORD(NULL, &value); +- todo_wine + ok(res == E_INVALIDARG, "expected E_INVALIDARG, got %08x\n", res); + + value = 0xdeadbeef; + res = SLGetWindowsInformationDWORD(NonexistentLicenseValueW, &value); +- todo_wine + ok(res == SL_E_VALUE_NOT_FOUND, "expected SL_E_VALUE_NOT_FOUND, got %08x\n", res); + ok(value == 0xdeadbeef, "expected value = 0xdeadbeef, got %u\n", value); + +@@ -61,15 +58,12 @@ static void test_SLGetWindowsInformationDWORD(void) + + value = 0xdeadbeef; + res = SLGetWindowsInformationDWORD(KernelMUILanguageAllowedW, &value); +- todo_wine + ok(res == SL_E_DATATYPE_MISMATCHED, "expected SL_E_DATATYPE_MISMATCHED, got %08x\n", res); + ok(value == 0xdeadbeef, "expected value = 0xdeadbeef, got %u\n", value); + + value = 0xdeadbeef; + res = SLGetWindowsInformationDWORD(KernelMUINumberAllowedW, &value); +- todo_wine + ok(res == S_OK, "expected S_OK, got %u\n", res); +- todo_wine + ok(value != 0xdeadbeef, "expected value != 0xdeadbeef\n"); + } + +-- +2.2.1 + diff --git a/patches/slc-SLGetWindowsInformation/definition b/patches/slc-SLGetWindowsInformation/definition new file mode 100644 index 00000000..09616431 --- /dev/null +++ b/patches/slc-SLGetWindowsInformation/definition @@ -0,0 +1 @@ +Fixes: [36709] Support for SLGetWindowsInformationDWORD