Compare commits

...

13 Commits
v3.12 ... v3.13

Author SHA1 Message Date
Alistair Leslie-Hughes
44aadc3afc Release 3.13 2018-07-21 09:54:00 +10:00
Alistair Leslie-Hughes
18f4be0e03 Updated winepulse-PulseAudio_Support patchset 2018-07-20 08:34:16 +10:00
Alistair Leslie-Hughes
49025c255b Rebase against d265dd88cd93ce6ffe56c9cfd640b064d7c14e29 2018-07-19 09:41:42 +10:00
Alistair Leslie-Hughes
12be01bfc1 Updated winepulse-PulseAudio_Support 2018-07-18 09:47:02 +10:00
Alistair Leslie-Hughes
79f6a17908 Rebase against adb926d5a5032130d55e4d39316efdb11cc1fe1d 2018-07-17 08:25:25 +10:00
Alistair Leslie-Hughes
2b85113f61 Rebase against 414fe80aebe3850fd016da5cb883f4bfeab1c543 2018-07-14 11:41:23 +10:00
Alistair Leslie-Hughes
60e4f489f6 Rebase against 053a7e225c8190fd7416b3f3c3186f1ac230eeb3 2018-07-13 10:59:13 +10:00
Alistair Leslie-Hughes
fd81bd7755 Rebase against acb879c9d2feae69e8b5b1ede28523a29aef1b89 2018-07-12 10:17:14 +10:00
Alistair Leslie-Hughes
292a0e67f4 Added ddraw-Prevent_viewport_crash patchset 2018-07-11 10:57:01 +10:00
Alistair Leslie-Hughes
7993325086 Added wined3d-WINED3DFMT_B8G8R8X8_UNORM patchset 2018-07-11 09:41:05 +10:00
Alistair Leslie-Hughes
77ecb8ba3f Updated kernelbase-PathCchCombineEx patchset 2018-07-11 09:39:32 +10:00
Alistair Leslie-Hughes
d3bb80f8eb Updated xaudio2_7-WMA_support patchset 2018-07-11 09:38:22 +10:00
Alistair Leslie-Hughes
0b4011d95c Rebase against 3d5d8903b89803f5b2ec12a2d20ae9a171047fdc 2018-07-11 08:40:24 +10:00
48 changed files with 2634 additions and 2509 deletions

View File

@@ -1,267 +0,0 @@
From e950724c38a4f81efb97bb9595dc59c5fb925da0 Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Wed, 12 Apr 2017 12:33:31 +0800
Subject: advapi32/tests: Add more tests for performance counters.
---
dlls/advapi32/tests/registry.c | 196 ++++++++++++++++++++++++++++++++++++++++-
include/winreg.h | 2 +
2 files changed, 194 insertions(+), 4 deletions(-)
diff --git a/dlls/advapi32/tests/registry.c b/dlls/advapi32/tests/registry.c
index 846f1c49628..d850f6a3aa7 100644
--- a/dlls/advapi32/tests/registry.c
+++ b/dlls/advapi32/tests/registry.c
@@ -3520,35 +3520,73 @@ static void test_RegNotifyChangeKeyValue(void)
CloseHandle(event);
}
+static const char *dbgstr_longlong(ULONGLONG ll)
+{
+ static char buf[16][64];
+ static int idx;
+
+ idx &= 0x0f;
+
+ if (sizeof(ll) > sizeof(unsigned long) && ll >> 32)
+ sprintf(buf[idx], "0x%lx%08lx", (unsigned long)(ll >> 32), (unsigned long)ll);
+ else
+ sprintf(buf[idx], "0x%08lx", (unsigned long)ll);
+
+ return buf[idx++];
+}
+
+#define cmp_li(a, b, c) cmp_li_real(a, b, c, __LINE__)
+static void cmp_li_real(LARGE_INTEGER *l1, LARGE_INTEGER *l2, LONGLONG slack, int line)
+{
+ LONGLONG diff = l2->QuadPart - l1->QuadPart;
+ if (diff < 0) diff = -diff;
+ ok_(__FILE__, line)(diff <= slack, "values don't match: %s/%s\n",
+ dbgstr_longlong(l1->QuadPart), dbgstr_longlong(l2->QuadPart));
+}
+
static void test_RegQueryValueExPerformanceData(void)
{
- DWORD cbData, len;
+ static const WCHAR globalW[] = { 'G','l','o','b','a','l',0 };
+ static const WCHAR dummyW[5] = { 'd','u','m','m','y' };
+ static const char * const names[] = { NULL, "", "Global", "2" "invalid counter name" };
+ DWORD cbData, len, i, type;
BYTE *value;
DWORD dwret;
LONG limit = 6;
PERF_DATA_BLOCK *pdb;
+ HKEY hkey;
+ BYTE buf[256 + sizeof(PERF_DATA_BLOCK)];
/* Test with data == NULL */
dwret = RegQueryValueExA( HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, NULL, &cbData );
todo_wine ok( dwret == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", dwret );
+ dwret = RegQueryValueExW( HKEY_PERFORMANCE_DATA, globalW, NULL, NULL, NULL, &cbData );
+ todo_wine ok( dwret == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", dwret );
+
/* Test ERROR_MORE_DATA, start with small buffer */
len = 10;
value = HeapAlloc(GetProcessHeap(), 0, len);
cbData = len;
- dwret = RegQueryValueExA( HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, value, &cbData );
+ type = 0xdeadbeef;
+ dwret = RegQueryValueExA( HKEY_PERFORMANCE_DATA, "Global", NULL, &type, value, &cbData );
todo_wine ok( dwret == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", dwret );
+todo_wine
+ ok(type == REG_BINARY, "got %u\n", type);
while( dwret == ERROR_MORE_DATA && limit)
{
len = len * 10;
value = HeapReAlloc( GetProcessHeap(), 0, value, len );
cbData = len;
- dwret = RegQueryValueExA( HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, value, &cbData );
+ type = 0xdeadbeef;
+ dwret = RegQueryValueExA( HKEY_PERFORMANCE_DATA, "Global", NULL, &type, value, &cbData );
limit--;
}
ok(limit > 0, "too many times ERROR_MORE_DATA returned\n");
todo_wine ok(dwret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", dwret);
+todo_wine
+ ok(type == REG_BINARY, "got %u\n", type);
/* Check returned data */
if (dwret == ERROR_SUCCESS)
@@ -3565,8 +3603,158 @@ static void test_RegQueryValueExPerformanceData(void)
}
HeapFree(GetProcessHeap(), 0, value);
-}
+ for (i = 0; i < sizeof(names)/sizeof(names[0]); i++)
+ {
+ cbData = 0xdeadbeef;
+ dwret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, names[i], NULL, NULL, NULL, &cbData);
+todo_wine
+ ok(dwret == ERROR_MORE_DATA, "%u/%s: got %u\n", i, names[i], dwret);
+ ok(cbData == 0, "got %u\n", cbData);
+
+ cbData = 0;
+ dwret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, names[i], NULL, NULL, NULL, &cbData);
+todo_wine
+ ok(dwret == ERROR_MORE_DATA, "%u/%s: got %u\n", i, names[i], dwret);
+ ok(cbData == 0, "got %u\n", cbData);
+
+ cbData = 0xdeadbeef;
+ dwret = RegQueryValueExA(HKEY_PERFORMANCE_TEXT, names[i], NULL, NULL, NULL, &cbData);
+todo_wine
+ ok(dwret == ERROR_MORE_DATA, "%u/%s: got %u\n", i, names[i], dwret);
+ ok(cbData == 0, "got %u\n", cbData);
+
+ cbData = 0;
+ dwret = RegQueryValueExA(HKEY_PERFORMANCE_TEXT, names[i], NULL, NULL, NULL, &cbData);
+todo_wine
+ ok(dwret == ERROR_MORE_DATA, "%u/%s: got %u\n", i, names[i], dwret);
+ ok(cbData == 0, "got %u\n", cbData);
+
+ cbData = 0xdeadbeef;
+ dwret = RegQueryValueExA(HKEY_PERFORMANCE_NLSTEXT, names[i], NULL, NULL, NULL, &cbData);
+todo_wine
+ ok(dwret == ERROR_MORE_DATA, "%u/%s: got %u\n", i, names[i], dwret);
+ ok(cbData == 0, "got %u\n", cbData);
+
+ cbData = 0;
+ dwret = RegQueryValueExA(HKEY_PERFORMANCE_NLSTEXT, names[i], NULL, NULL, NULL, &cbData);
+todo_wine
+ ok(dwret == ERROR_MORE_DATA, "%u/%s: got %u\n", i, names[i], dwret);
+ ok(cbData == 0, "got %u\n", cbData);
+ }
+
+ memset(buf, 0x77, sizeof(buf));
+ type = 0xdeadbeef;
+ cbData = sizeof(buf);
+ dwret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "invalid counter name", NULL, &type, buf, &cbData);
+todo_wine
+ ok(dwret == ERROR_SUCCESS, "got %u\n", dwret);
+todo_wine
+ ok(type == REG_BINARY, "got %u\n", type);
+ if (dwret == ERROR_SUCCESS)
+ {
+ SYSTEMTIME st;
+ WCHAR sysname[MAX_COMPUTERNAME_LENGTH + 1];
+ DWORD sysname_len;
+ LARGE_INTEGER counter, freq, ftime;
+
+ GetSystemTime(&st);
+ GetSystemTimeAsFileTime((FILETIME *)&ftime);
+ QueryPerformanceCounter(&counter);
+ QueryPerformanceFrequency(&freq);
+
+ sysname_len = MAX_COMPUTERNAME_LENGTH + 1;
+ GetComputerNameW(sysname, &sysname_len);
+
+ pdb = (PERF_DATA_BLOCK *)buf;
+ ok(pdb->Signature[0] == 'P', "got '%c'\n", pdb->Signature[0]);
+ ok(pdb->Signature[1] == 'E', "got '%c'\n", pdb->Signature[1]);
+ ok(pdb->Signature[2] == 'R', "got '%c'\n", pdb->Signature[2]);
+ ok(pdb->Signature[3] == 'F', "got '%c'\n", pdb->Signature[3]);
+
+ ok(pdb->LittleEndian == 1, "got %u\n", pdb->LittleEndian);
+ ok(pdb->Version == 1, "got %u\n", pdb->Version);
+ ok(pdb->Revision == 1, "got %u\n", pdb->Revision);
+ len = (sizeof(*pdb) + pdb->SystemNameLength + 7) & ~7;
+ ok(pdb->TotalByteLength == len, "got %u vs %u\n", pdb->TotalByteLength, len);
+ ok(pdb->HeaderLength == pdb->TotalByteLength, "got %u\n", pdb->HeaderLength);
+ ok(pdb->NumObjectTypes == 0, "got %u\n", pdb->NumObjectTypes);
+ ok(pdb->DefaultObject != 0, "got %u\n", pdb->DefaultObject);
+ ok(pdb->SystemTime.wYear == st.wYear, "got %u\n", pdb->SystemTime.wYear);
+ ok(pdb->SystemTime.wMonth == st.wMonth, "got %u\n", pdb->SystemTime.wMonth);
+ ok(pdb->SystemTime.wDayOfWeek == st.wDayOfWeek, "got %u\n", pdb->SystemTime.wDayOfWeek);
+ ok(pdb->SystemTime.wDay == st.wDay, "got %u\n", pdb->SystemTime.wDay);
+ if (U(pdb->PerfTime).LowPart != 0x77777777) /* TestBot is broken */
+ cmp_li(&pdb->PerfTime, &counter, freq.QuadPart);
+ if (U(pdb->PerfFreq).LowPart != 0x77777777) /* TestBot is broken */
+ cmp_li(&pdb->PerfFreq, &freq, 0);
+ cmp_li(&pdb->PerfTime100nSec, &ftime, 200000); /* TestBot needs huge slack value */
+ ok(pdb->SystemNameLength == (sysname_len + 1) * sizeof(WCHAR), "expected %u, got %u\n",
+ (sysname_len + 1) * sizeof(WCHAR), pdb->SystemNameLength);
+ ok(pdb->SystemNameOffset == sizeof(*pdb), "got %u\n", pdb->SystemNameOffset);
+ ok(!lstrcmpW(sysname, (LPCWSTR)(pdb + 1)), "%s != %s\n",
+ wine_dbgstr_w(sysname), wine_dbgstr_w((LPCWSTR)(pdb + 1)));
+
+ len = pdb->TotalByteLength - (sizeof(*pdb) + pdb->SystemNameLength);
+ if (len)
+ {
+ BYTE remainder[8], *p;
+
+ memset(remainder, 0x77, sizeof(remainder));
+ p = buf + sizeof(*pdb) + pdb->SystemNameLength;
+ ok(!memcmp(p, remainder, len), "remainder: %02x,%02x...\n", p[0], p[1]);
+ }
+ }
+
+ dwret = RegOpenKeyA(HKEY_PERFORMANCE_DATA, NULL, &hkey);
+todo_wine
+ ok(dwret == ERROR_INVALID_HANDLE, "got %u\n", dwret);
+
+ dwret = RegOpenKeyA(HKEY_PERFORMANCE_DATA, "Global", &hkey);
+todo_wine
+ ok(dwret == ERROR_INVALID_HANDLE, "got %u\n", dwret);
+
+ dwret = RegOpenKeyExA(HKEY_PERFORMANCE_DATA, "Global", 0, KEY_READ, &hkey);
+todo_wine
+ ok(dwret == ERROR_INVALID_HANDLE, "got %u\n", dwret);
+
+ dwret = RegQueryValueA(HKEY_PERFORMANCE_DATA, "Global", NULL, (LONG *)&cbData);
+todo_wine
+ ok(dwret == ERROR_INVALID_HANDLE, "got %u\n", dwret);
+
+ dwret = RegSetValueA(HKEY_PERFORMANCE_DATA, "Global", REG_SZ, "dummy", 4);
+todo_wine
+ ok(dwret == ERROR_INVALID_HANDLE, "got %u\n", dwret);
+
+ dwret = RegSetValueExA(HKEY_PERFORMANCE_DATA, "Global", 0, REG_SZ, (const BYTE *)"dummy", 40);
+todo_wine
+ ok(dwret == ERROR_INVALID_HANDLE, "got %u\n", dwret);
+
+ cbData = sizeof(buf);
+ dwret = RegEnumKeyA(HKEY_PERFORMANCE_DATA, 0, (LPSTR)buf, cbData);
+todo_wine
+ ok(dwret == ERROR_INVALID_HANDLE, "got %u\n", dwret);
+
+ cbData = sizeof(buf);
+ dwret = RegEnumValueA(HKEY_PERFORMANCE_DATA, 0, (LPSTR)buf, &cbData, NULL, NULL, NULL, NULL);
+todo_wine
+ ok(dwret == ERROR_MORE_DATA, "got %u\n", dwret);
+todo_wine
+ ok(cbData == sizeof(buf), "got %u\n", cbData);
+
+ dwret = RegEnumValueA(HKEY_PERFORMANCE_DATA, 0, NULL, &cbData, NULL, NULL, NULL, NULL);
+ ok(dwret == ERROR_INVALID_PARAMETER, "got %u\n", dwret);
+
+ if (pRegSetKeyValueW)
+ {
+ dwret = pRegSetKeyValueW(HKEY_PERFORMANCE_DATA, NULL, globalW, REG_SZ, dummyW, sizeof(dummyW));
+todo_wine
+ ok(dwret == ERROR_INVALID_HANDLE, "got %u\n", dwret);
+ }
+
+ dwret = RegCloseKey(HKEY_PERFORMANCE_DATA);
+ ok(dwret == ERROR_SUCCESS, "got %u\n", dwret);
+}
START_TEST(registry)
{
diff --git a/include/winreg.h b/include/winreg.h
index 42b77251ae4..ddbd9293783 100644
--- a/include/winreg.h
+++ b/include/winreg.h
@@ -32,6 +32,8 @@ extern "C" {
#define HKEY_PERFORMANCE_DATA ((HKEY)(LONG_PTR)(LONG)0x80000004)
#define HKEY_CURRENT_CONFIG ((HKEY)(LONG_PTR)(LONG)0x80000005)
#define HKEY_DYN_DATA ((HKEY)(LONG_PTR)(LONG)0x80000006)
+#define HKEY_PERFORMANCE_TEXT ((HKEY)(LONG_PTR)(LONG)0x80000050)
+#define HKEY_PERFORMANCE_NLSTEXT ((HKEY)(LONG_PTR)(LONG)0x80000060)
/*
* registry provider structs
--
2.13.1

View File

@@ -1,139 +0,0 @@
From f72de28ee3a7a3cb25165f0aaee0c7e17eb7e6d7 Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Wed, 12 Apr 2017 12:48:29 +0800
Subject: include: Add more definitions for performance counters.
---
include/winperf.h | 113 ++++++++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 97 insertions(+), 16 deletions(-)
diff --git a/include/winperf.h b/include/winperf.h
index dce1a6d648d..113bfbae40f 100644
--- a/include/winperf.h
+++ b/include/winperf.h
@@ -67,25 +67,106 @@
#define PERF_DETAIL_EXPERT 300
#define PERF_DETAIL_WIZARD 400
+#include <pshpack8.h>
+
/* Performance data structure header
* returned in answer to HKEY_PERFORMANCE_DATA request
*/
-typedef struct _PERF_DATA_BLOCK {
- WCHAR Signature[4];
- DWORD LittleEndian;
- DWORD Version;
- DWORD Revision;
- DWORD TotalByteLength;
- DWORD HeaderLength;
- DWORD NumObjectTypes;
- DWORD DefaultObject;
- SYSTEMTIME SystemTime;
- LARGE_INTEGER PerfTime;
- LARGE_INTEGER PerfFreq;
- LARGE_INTEGER PerfTime100nSec;
- DWORD SystemNameLength;
- DWORD SystemNameOffset;
-} PERF_DATA_BLOCK, *PPERF_DATA_BLOCK, *LPPERF_DATA_BLOCK;
+#define PERF_DATA_VERSION 1
+#define PERF_DATA_REVISION 1
+
+typedef struct _PERF_DATA_BLOCK
+{
+ WCHAR Signature[4];
+ DWORD LittleEndian;
+ DWORD Version;
+ DWORD Revision;
+ DWORD TotalByteLength;
+ DWORD HeaderLength;
+ DWORD NumObjectTypes;
+ DWORD DefaultObject;
+ SYSTEMTIME SystemTime;
+ LARGE_INTEGER PerfTime;
+ LARGE_INTEGER PerfFreq;
+ LARGE_INTEGER PerfTime100nSec;
+ DWORD SystemNameLength;
+ DWORD SystemNameOffset;
+} PERF_DATA_BLOCK, *PPERF_DATA_BLOCK;
+
+#define PERF_NO_INSTANCES -1
+
+typedef struct _PERF_OBJECT_TYPE
+{
+ DWORD TotalByteLength;
+ DWORD DefinitionLength;
+ DWORD HeaderLength;
+ DWORD ObjectNameTitleIndex;
+#ifdef _WIN64
+ DWORD ObjectNameTitle;
+#else
+ LPWSTR ObjectNameTitle;
+#endif
+ DWORD ObjectHelpTitleIndex;
+#ifdef _WIN64
+ DWORD ObjectHelpTitle;
+#else
+ LPWSTR ObjectHelpTitle;
+#endif
+ DWORD DetailLevel;
+ DWORD NumCounters;
+ LONG DefaultCounter;
+ LONG NumInstances;
+ DWORD CodePage;
+ LARGE_INTEGER PerfTime;
+ LARGE_INTEGER PerfFreq;
+} PERF_OBJECT_TYPE, *PPERF_OBJECT_TYPE;
+
+typedef struct _PERF_COUNTER_DEFINITION
+{
+ DWORD ByteLength;
+ DWORD CounterNameTitleIndex;
+#ifdef _WIN64
+ DWORD CounterNameTitle;
+#else
+ LPWSTR CounterNameTitle;
+#endif
+ DWORD CounterHelpTitleIndex;
+#ifdef _WIN64
+ DWORD CounterHelpTitle;
+#else
+ LPWSTR CounterHelpTitle;
+#endif
+ LONG DefaultScale;
+ DWORD DetailLevel;
+ DWORD CounterType;
+ DWORD CounterSize;
+ DWORD CounterOffset;
+} PERF_COUNTER_DEFINITION, *PPERF_COUNTER_DEFINITION;
+
+#define PERF_NO_UNIQUE_ID -1
+
+typedef struct _PERF_INSTANCE_DEFINITION
+{
+ DWORD ByteLength;
+ DWORD ParentObjectTitleIndex;
+ DWORD ParentObjectInstance;
+ LONG UniqueID;
+ DWORD NameOffset;
+ DWORD NameLength;
+} PERF_INSTANCE_DEFINITION, *PPERF_INSTANCE_DEFINITION;
+
+typedef struct _PERF_COUNTER_BLOCK
+{
+ DWORD ByteLength;
+} PERF_COUNTER_BLOCK, *PPERF_COUNTER_BLOCK;
+
+
+#include <poppack.h>
+
+typedef DWORD (APIENTRY PM_OPEN_PROC)(LPWSTR);
+typedef DWORD (APIENTRY PM_COLLECT_PROC)(LPWSTR,LPVOID *,LPDWORD,LPDWORD);
+typedef DWORD (APIENTRY PM_CLOSE_PROC)(void);
+typedef DWORD (APIENTRY PM_QUERY_PROC)(LPDWORD,LPVOID *,LPDWORD,LPDWORD);
#endif /* _WINPERF_ */
--
2.13.1

View File

@@ -1,380 +0,0 @@
From 4fc763b4564cf0dc7e9e27826d785255133c8187 Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Wed, 12 Apr 2017 13:59:20 +0800
Subject: advapi32: Add initial support for querying performance counters data.
(v2)
---
dlls/advapi32/registry.c | 244 ++++++++++++++++++++++++++++++++++++++++-
dlls/advapi32/tests/registry.c | 17 +--
2 files changed, 249 insertions(+), 12 deletions(-)
diff --git a/dlls/advapi32/registry.c b/dlls/advapi32/registry.c
index 7a26fffc55e..4dd29d3ba72 100644
--- a/dlls/advapi32/registry.c
+++ b/dlls/advapi32/registry.c
@@ -2,6 +2,7 @@
* Registry management
*
* Copyright (C) 1999 Alexandre Julliard
+ * Copyright (C) 2017 Dmitry Timoshkov
*
* Based on misc/registry.c code
* Copyright (C) 1996 Marcus Meissner
@@ -36,6 +37,7 @@
#include "winreg.h"
#include "winerror.h"
#include "winternl.h"
+#include "winperf.h"
#include "winuser.h"
#include "sddl.h"
#include "advapi32_misc.h"
@@ -1482,6 +1484,234 @@ LONG WINAPI RegSetKeyValueA( HKEY hkey, LPCSTR subkey, LPCSTR name, DWORD type,
return ret;
}
+struct perf_provider
+{
+ HMODULE perflib;
+ PM_OPEN_PROC *pOpen;
+ PM_CLOSE_PROC *pClose;
+ PM_COLLECT_PROC *pCollect;
+};
+
+static void *get_provider_entry(HKEY perf, HMODULE perflib, const char *name)
+{
+ char buf[MAX_PATH];
+ DWORD err, type, len;
+
+ len = sizeof(buf) - 1;
+ err = RegQueryValueExA(perf, name, NULL, &type, (BYTE *)buf, &len);
+ if (err != ERROR_SUCCESS || type != REG_SZ)
+ return NULL;
+
+ buf[len] = 0;
+ TRACE("Loading function pointer for %s: %s\n", name, debugstr_a(buf));
+
+ return GetProcAddress(perflib, buf);
+}
+
+static BOOL load_provider(HKEY root, const WCHAR *name, struct perf_provider *provider)
+{
+ static const WCHAR performanceW[] = { 'P','e','r','f','o','r','m','a','n','c','e',0 };
+ static const WCHAR libraryW[] = { 'L','i','b','r','a','r','y',0 };
+ WCHAR buf[MAX_PATH], buf2[MAX_PATH];
+ DWORD err, type, len;
+ HKEY service, perf;
+
+ err = RegOpenKeyExW(root, name, 0, KEY_READ, &service);
+ if (err != ERROR_SUCCESS)
+ return FALSE;
+
+ err = RegOpenKeyExW(service, performanceW, 0, KEY_READ, &perf);
+ RegCloseKey(service);
+ if (err != ERROR_SUCCESS)
+ return FALSE;
+
+ len = sizeof(buf) - sizeof(WCHAR);
+ err = RegQueryValueExW(perf, libraryW, NULL, &type, (BYTE *)buf, &len);
+ if (err != ERROR_SUCCESS || !(type == REG_SZ || type == REG_EXPAND_SZ))
+ goto error;
+
+ buf[len / sizeof(WCHAR)] = 0;
+ if (type == REG_EXPAND_SZ)
+ {
+ len = ExpandEnvironmentStringsW(buf, buf2, MAX_PATH);
+ if (!len || len > MAX_PATH) goto error;
+ strcpyW(buf, buf2);
+ }
+
+ if (!(provider->perflib = LoadLibraryW(buf)))
+ {
+ WARN("Failed to load %s\n", debugstr_w(buf));
+ goto error;
+ }
+
+ GetModuleFileNameW(provider->perflib, buf, MAX_PATH);
+ TRACE("Loaded provider %s\n", wine_dbgstr_w(buf));
+
+ provider->pOpen = get_provider_entry(perf, provider->perflib, "Open");
+ provider->pClose = get_provider_entry(perf, provider->perflib, "Close");
+ provider->pCollect = get_provider_entry(perf, provider->perflib, "Collect");
+ if (provider->pOpen && provider->pClose && provider->pCollect)
+ {
+ RegCloseKey(perf);
+ return TRUE;
+ }
+
+ TRACE("Provider is missing required exports\n");
+ FreeLibrary(provider->perflib);
+
+error:
+ RegCloseKey(perf);
+ return FALSE;
+}
+
+static DWORD collect_data(struct perf_provider *provider, const WCHAR *query, void **data, DWORD *size, DWORD *obj_count)
+{
+ DWORD err;
+
+ err = provider->pOpen(NULL);
+ if (err != ERROR_SUCCESS)
+ {
+ TRACE("Open error %u (%#x)\n", err, err);
+ return err;
+ }
+
+ *obj_count = 0;
+ err = provider->pCollect((WCHAR *)query, data, size, obj_count);
+ if (err != ERROR_SUCCESS)
+ {
+ TRACE("Collect error %u (%#x)\n", err, err);
+ *obj_count = 0;
+ }
+
+ provider->pClose();
+ return err;
+}
+
+#define MAX_SERVICE_NAME 260
+
+static DWORD query_perf_data(const WCHAR *query, DWORD *type, void *data, DWORD *ret_size)
+{
+ static const WCHAR SZ_SERVICES_KEY[] = { 'S','y','s','t','e','m','\\',
+ 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
+ 'S','e','r','v','i','c','e','s',0 };
+ DWORD err, i, data_size;
+ HKEY root;
+ PERF_DATA_BLOCK *pdb;
+
+ if (!ret_size)
+ return ERROR_INVALID_PARAMETER;
+
+ data_size = *ret_size;
+ *ret_size = 0;
+
+ if (type)
+ *type = REG_BINARY;
+
+ if (!data || data_size < sizeof(*pdb))
+ return ERROR_MORE_DATA;
+
+ pdb = data;
+
+ pdb->Signature[0] = 'P';
+ pdb->Signature[1] = 'E';
+ pdb->Signature[2] = 'R';
+ pdb->Signature[3] = 'F';
+#ifdef WORDS_BIGENDIAN
+ pdb->LittleEndian = FALSE;
+#else
+ pdb->LittleEndian = TRUE;
+#endif
+ pdb->Version = PERF_DATA_VERSION;
+ pdb->Revision = PERF_DATA_REVISION;
+ pdb->TotalByteLength = 0;
+ pdb->HeaderLength = sizeof(*pdb);
+ pdb->NumObjectTypes = 0;
+ pdb->DefaultObject = 0;
+ QueryPerformanceCounter(&pdb->PerfTime);
+ QueryPerformanceFrequency(&pdb->PerfFreq);
+
+ data = pdb + 1;
+ pdb->SystemNameOffset = sizeof(*pdb);
+ pdb->SystemNameLength = (data_size - sizeof(*pdb)) / sizeof(WCHAR);
+ if (!GetComputerNameW(data, &pdb->SystemNameLength))
+ return ERROR_MORE_DATA;
+
+ pdb->SystemNameLength++;
+ pdb->SystemNameLength *= sizeof(WCHAR);
+
+ pdb->HeaderLength += pdb->SystemNameLength;
+
+ /* align to 8 bytes */
+ if (pdb->SystemNameLength & 7)
+ pdb->HeaderLength += 8 - (pdb->SystemNameLength & 7);
+
+ if (data_size < pdb->HeaderLength)
+ return ERROR_MORE_DATA;
+
+ pdb->TotalByteLength = pdb->HeaderLength;
+
+ data_size -= pdb->HeaderLength;
+ data = (char *)data + pdb->HeaderLength;
+
+ err = RegOpenKeyExW(HKEY_LOCAL_MACHINE, SZ_SERVICES_KEY, 0, KEY_READ, &root);
+ if (err != ERROR_SUCCESS)
+ return err;
+
+ i = 0;
+ for (;;)
+ {
+ DWORD collected_size = data_size, obj_count = 0;
+ struct perf_provider provider;
+ WCHAR name[MAX_SERVICE_NAME];
+ void *collected_data = data;
+
+ err = RegEnumKeyW(root, i++, name, MAX_SERVICE_NAME);
+ if (err == ERROR_NO_MORE_ITEMS)
+ {
+ err = ERROR_SUCCESS;
+ break;
+ }
+
+ if (err != ERROR_SUCCESS)
+ continue;
+
+ if (!load_provider(root, name, &provider))
+ continue;
+
+ err = collect_data(&provider, query, &collected_data, &collected_size, &obj_count);
+ FreeLibrary(provider.perflib);
+
+ if (err == ERROR_MORE_DATA)
+ break;
+
+ if (err == ERROR_SUCCESS)
+ {
+ PERF_OBJECT_TYPE *obj = (PERF_OBJECT_TYPE *)data;
+
+ TRACE("Collect: obj->TotalByteLength %u, collected_size %u\n",
+ obj->TotalByteLength, collected_size);
+
+ data_size -= collected_size;
+ data = collected_data;
+
+ pdb->TotalByteLength += collected_size;
+ pdb->NumObjectTypes += obj_count;
+ }
+ }
+
+ RegCloseKey(root);
+
+ if (err == ERROR_SUCCESS)
+ {
+ *ret_size = pdb->TotalByteLength;
+
+ GetSystemTime(&pdb->SystemTime);
+ GetSystemTimeAsFileTime((FILETIME *)&pdb->PerfTime100nSec);
+ }
+
+ return err;
+}
+
/******************************************************************************
* RegQueryValueExW [ADVAPI32.@]
*
@@ -1502,6 +1732,10 @@ LSTATUS WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDW
(count && data) ? *count : 0 );
if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
+
+ if (hkey == HKEY_PERFORMANCE_DATA)
+ return query_perf_data(name, type, data, count);
+
if (!(hkey = get_special_root_hkey( hkey, 0 ))) return ERROR_INVALID_HANDLE;
RtlInitUnicodeString( &name_str, name );
@@ -1592,7 +1826,8 @@ LSTATUS WINAPI DECLSPEC_HOTPATCH RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWO
hkey, debugstr_a(name), reserved, type, data, count, count ? *count : 0 );
if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
- if (!(hkey = get_special_root_hkey( hkey, 0 ))) return ERROR_INVALID_HANDLE;
+ if (hkey != HKEY_PERFORMANCE_DATA && !(hkey = get_special_root_hkey( hkey, 0 )))
+ return ERROR_INVALID_HANDLE;
if (count) datalen = *count;
if (!data && count) *count = 0;
@@ -1604,6 +1839,13 @@ LSTATUS WINAPI DECLSPEC_HOTPATCH RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWO
if ((status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE )))
return RtlNtStatusToDosError(status);
+ if (hkey == HKEY_PERFORMANCE_DATA)
+ {
+ DWORD ret = query_perf_data( nameW.Buffer, type, data, count );
+ RtlFreeUnicodeString( &nameW );
+ return ret;
+ }
+
status = NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation,
buffer, sizeof(buffer), &total_size );
if (status && status != STATUS_BUFFER_OVERFLOW) goto done;
diff --git a/dlls/advapi32/tests/registry.c b/dlls/advapi32/tests/registry.c
index 43599359ac6..9706478a135 100644
--- a/dlls/advapi32/tests/registry.c
+++ b/dlls/advapi32/tests/registry.c
@@ -3520,10 +3520,10 @@ static void test_RegQueryValueExPerformanceData(void)
/* Test with data == NULL */
dwret = RegQueryValueExA( HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, NULL, &cbData );
- todo_wine ok( dwret == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", dwret );
+ ok( dwret == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", dwret );
dwret = RegQueryValueExW( HKEY_PERFORMANCE_DATA, globalW, NULL, NULL, NULL, &cbData );
- todo_wine ok( dwret == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", dwret );
+ ok( dwret == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", dwret );
/* Test ERROR_MORE_DATA, start with small buffer */
len = 10;
@@ -3531,8 +3531,7 @@ static void test_RegQueryValueExPerformanceData(void)
cbData = len;
type = 0xdeadbeef;
dwret = RegQueryValueExA( HKEY_PERFORMANCE_DATA, "Global", NULL, &type, value, &cbData );
- todo_wine ok( dwret == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", dwret );
-todo_wine
+ ok( dwret == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", dwret );
ok(type == REG_BINARY, "got %u\n", type);
while( dwret == ERROR_MORE_DATA && limit)
{
@@ -3545,14 +3544,13 @@ todo_wine
}
ok(limit > 0, "too many times ERROR_MORE_DATA returned\n");
- todo_wine ok(dwret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", dwret);
-todo_wine
+ ok(dwret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", dwret);
ok(type == REG_BINARY, "got %u\n", type);
/* Check returned data */
if (dwret == ERROR_SUCCESS)
{
- todo_wine ok(len >= sizeof(PERF_DATA_BLOCK), "got size %d\n", len);
+ ok(len >= sizeof(PERF_DATA_BLOCK), "got size %d\n", len);
if (len >= sizeof(PERF_DATA_BLOCK)) {
pdb = (PERF_DATA_BLOCK*) value;
ok(pdb->Signature[0] == 'P', "expected Signature[0] = 'P', got 0x%x\n", pdb->Signature[0]);
@@ -3569,13 +3567,11 @@ todo_wine
{
cbData = 0xdeadbeef;
dwret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, names[i], NULL, NULL, NULL, &cbData);
-todo_wine
ok(dwret == ERROR_MORE_DATA, "%u/%s: got %u\n", i, names[i], dwret);
ok(cbData == 0, "got %u\n", cbData);
cbData = 0;
dwret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, names[i], NULL, NULL, NULL, &cbData);
-todo_wine
ok(dwret == ERROR_MORE_DATA, "%u/%s: got %u\n", i, names[i], dwret);
ok(cbData == 0, "got %u\n", cbData);
@@ -3608,9 +3604,7 @@ todo_wine
type = 0xdeadbeef;
cbData = sizeof(buf);
dwret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "invalid counter name", NULL, &type, buf, &cbData);
-todo_wine
ok(dwret == ERROR_SUCCESS, "got %u\n", dwret);
-todo_wine
ok(type == REG_BINARY, "got %u\n", type);
if (dwret == ERROR_SUCCESS)
{
@@ -3640,6 +3634,7 @@ todo_wine
ok(pdb->TotalByteLength == len, "got %u vs %u\n", pdb->TotalByteLength, len);
ok(pdb->HeaderLength == pdb->TotalByteLength, "got %u\n", pdb->HeaderLength);
ok(pdb->NumObjectTypes == 0, "got %u\n", pdb->NumObjectTypes);
+todo_wine
ok(pdb->DefaultObject != 0, "got %u\n", pdb->DefaultObject);
ok(pdb->SystemTime.wYear == st.wYear, "got %u\n", pdb->SystemTime.wYear);
ok(pdb->SystemTime.wMonth == st.wMonth, "got %u\n", pdb->SystemTime.wMonth);
--
2.13.1

View File

@@ -1,93 +0,0 @@
From efdcec40d501c6b27e3f3460ad0ad5fe26643e9d Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Wed, 12 Apr 2017 15:04:03 +0800
Subject: winspool.drv: Add performance counters service stubs.
---
dlls/winspool.drv/info.c | 29 +++++++++++++++++++++++++++++
dlls/winspool.drv/winspool.drv.spec | 6 +++---
loader/wine.inf.in | 7 +++++++
3 files changed, 39 insertions(+), 3 deletions(-)
diff --git a/dlls/winspool.drv/info.c b/dlls/winspool.drv/info.c
index f09745d1e6b..330ce236b45 100644
--- a/dlls/winspool.drv/info.c
+++ b/dlls/winspool.drv/info.c
@@ -8681,3 +8681,32 @@ HRESULT WINAPI UploadPrinterDriverPackageW( LPCWSTR server, LPCWSTR path, LPCWST
flags, hwnd, dst, dstlen);
return E_NOTIMPL;
}
+
+/*****************************************************************************
+ * PerfOpen [WINSPOOL.@]
+ */
+DWORD WINAPI PerfOpen(LPWSTR context)
+{
+ FIXME("%s: stub\n", debugstr_w(context));
+ return ERROR_SUCCESS;
+}
+
+/*****************************************************************************
+ * PerfClose [WINSPOOL.@]
+ */
+DWORD WINAPI PerfClose(void)
+{
+ FIXME("stub\n");
+ return ERROR_SUCCESS;
+}
+
+/*****************************************************************************
+ * PerfCollect [WINSPOOL.@]
+ */
+DWORD WINAPI PerfCollect(LPWSTR query, LPVOID *data, LPDWORD size, LPDWORD obj_count)
+{
+ FIXME("%s,%p,%p,%p: stub\n", debugstr_w(query), data, size, obj_count);
+ *size = 0;
+ *obj_count = 0;
+ return ERROR_SUCCESS;
+}
diff --git a/dlls/winspool.drv/winspool.drv.spec b/dlls/winspool.drv/winspool.drv.spec
index 58dc60bcc9f..a23ea2ced99 100644
--- a/dlls/winspool.drv/winspool.drv.spec
+++ b/dlls/winspool.drv/winspool.drv.spec
@@ -2,9 +2,9 @@
101 stub -noname ClusterSplOpen
102 stub -noname ClusterSplClose
103 stub -noname ClusterSplIsAlive
-104 stub PerfClose
-105 stub PerfCollect
-106 stub PerfOpen
+104 stdcall PerfClose()
+105 stdcall PerfCollect(wstr ptr ptr ptr)
+106 stdcall PerfOpen(wstr)
201 stdcall GetDefaultPrinterA(ptr ptr)
202 stdcall SetDefaultPrinterA(str)
203 stdcall GetDefaultPrinterW(ptr ptr)
diff --git a/loader/wine.inf.in b/loader/wine.inf.in
index 176647b8beb..a83cc209a96 100644
--- a/loader/wine.inf.in
+++ b/loader/wine.inf.in
@@ -3353,6 +3353,7 @@ StartType=3
ErrorControl=1
[SpoolerService]
+AddReg=SpoolerServiceKeys
Description="Loads files to memory for later printing"
DisplayName="Print Spooler"
ServiceBinary="%11%\spoolsv.exe"
@@ -3361,6 +3362,12 @@ StartType=3
ErrorControl=1
LoadOrderGroup="SpoolerGroup"
+[SpoolerServiceKeys]
+HKLM,"System\CurrentControlSet\Services\Spooler\Performance","Library",,"winspool.drv"
+HKLM,"System\CurrentControlSet\Services\Spooler\Performance","Open",,"PerfOpen"
+HKLM,"System\CurrentControlSet\Services\Spooler\Performance","Close",,"PerfClose"
+HKLM,"System\CurrentControlSet\Services\Spooler\Performance","Collect",,"PerfCollect"
+
[TerminalServices]
Description="Remote desktop access"
DisplayName="Terminal Services"
--
2.13.1

View File

@@ -1,72 +0,0 @@
From ea1f7f191b65313ed472e660a10d75e609a31dfc Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Fri, 14 Apr 2017 16:39:21 +0800
Subject: advapi32: Performance providers' Open() expects to see the configured
name as its parameter.
---
dlls/advapi32/registry.c | 23 +++++++++++++++++++++--
1 file changed, 21 insertions(+), 2 deletions(-)
diff --git a/dlls/advapi32/registry.c b/dlls/advapi32/registry.c
index a6e5c7903cf..37462380c40 100644
--- a/dlls/advapi32/registry.c
+++ b/dlls/advapi32/registry.c
@@ -1487,6 +1487,7 @@ LONG WINAPI RegSetKeyValueA( HKEY hkey, LPCSTR subkey, LPCSTR name, DWORD type,
struct perf_provider
{
HMODULE perflib;
+ WCHAR linkage[MAX_PATH];
PM_OPEN_PROC *pOpen;
PM_CLOSE_PROC *pClose;
PM_COLLECT_PROC *pCollect;
@@ -1512,6 +1513,8 @@ static BOOL load_provider(HKEY root, const WCHAR *name, struct perf_provider *pr
{
static const WCHAR performanceW[] = { 'P','e','r','f','o','r','m','a','n','c','e',0 };
static const WCHAR libraryW[] = { 'L','i','b','r','a','r','y',0 };
+ static const WCHAR linkageW[] = { 'L','i','n','k','a','g','e',0 };
+ static const WCHAR exportW[] = { 'E','x','p','o','r','t',0 };
WCHAR buf[MAX_PATH], buf2[MAX_PATH];
DWORD err, type, len;
HKEY service, perf;
@@ -1520,6 +1523,21 @@ static BOOL load_provider(HKEY root, const WCHAR *name, struct perf_provider *pr
if (err != ERROR_SUCCESS)
return FALSE;
+ provider->linkage[0] = 0;
+ err = RegOpenKeyExW(service, linkageW, 0, KEY_READ, &perf);
+ if (err == ERROR_SUCCESS)
+ {
+ len = sizeof(buf) - sizeof(WCHAR);
+ err = RegQueryValueExW(perf, exportW, NULL, &type, (BYTE *)buf, &len);
+ if (err == ERROR_SUCCESS && (type == REG_SZ || type == REG_MULTI_SZ))
+ {
+ memcpy(provider->linkage, buf, len);
+ provider->linkage[len / sizeof(WCHAR)] = 0;
+ TRACE("Export: %s\n", debugstr_w(provider->linkage));
+ }
+ RegCloseKey(perf);
+ }
+
err = RegOpenKeyExW(service, performanceW, 0, KEY_READ, &perf);
RegCloseKey(service);
if (err != ERROR_SUCCESS)
@@ -1563,12 +1581,13 @@ error:
static DWORD collect_data(struct perf_provider *provider, const WCHAR *query, void **data, DWORD *size, DWORD *obj_count)
{
+ WCHAR *linkage = provider->linkage[0] ? provider->linkage : NULL;
DWORD err;
- err = provider->pOpen(NULL);
+ err = provider->pOpen(linkage);
if (err != ERROR_SUCCESS)
{
- TRACE("Open error %u (%#x)\n", err, err);
+ TRACE("Open(%s) error %u (%#x)\n", debugstr_w(linkage), err, err);
return err;
}
--
2.13.1

View File

@@ -1,31 +0,0 @@
From f734e1d94b068a78cc10600c190bb2d527ab4866 Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Fri, 14 Apr 2017 16:40:43 +0800
Subject: advapi32: If the query is not specified the default query is
"Global".
---
dlls/advapi32/registry.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/dlls/advapi32/registry.c b/dlls/advapi32/registry.c
index 37462380c40..0aa38c5b9b3 100644
--- a/dlls/advapi32/registry.c
+++ b/dlls/advapi32/registry.c
@@ -1581,9 +1581,13 @@ error:
static DWORD collect_data(struct perf_provider *provider, const WCHAR *query, void **data, DWORD *size, DWORD *obj_count)
{
+ static const WCHAR globalW[] = { 'G','l','o','b','a','l',0 };
WCHAR *linkage = provider->linkage[0] ? provider->linkage : NULL;
DWORD err;
+ if (!query || !query[0])
+ query = globalW;
+
err = provider->pOpen(linkage);
if (err != ERROR_SUCCESS)
{
--
2.13.1

View File

@@ -1,53 +0,0 @@
From de80831314ecb76ac22b19b249467a600129a9e3 Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Fri, 14 Apr 2017 16:43:31 +0800
Subject: advapi32: Read the configured object list for the performance
provider.
FIXME: it's not currently used, but the queries should be matched
against the configured object lists, and the providers should be
loaded and called only in case of a match.
---
dlls/advapi32/registry.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/dlls/advapi32/registry.c b/dlls/advapi32/registry.c
index 0aa38c5b9b3..5af8128748b 100644
--- a/dlls/advapi32/registry.c
+++ b/dlls/advapi32/registry.c
@@ -1488,6 +1488,7 @@ struct perf_provider
{
HMODULE perflib;
WCHAR linkage[MAX_PATH];
+ WCHAR objects[MAX_PATH];
PM_OPEN_PROC *pOpen;
PM_CLOSE_PROC *pClose;
PM_COLLECT_PROC *pCollect;
@@ -1511,6 +1512,7 @@ static void *get_provider_entry(HKEY perf, HMODULE perflib, const char *name)
static BOOL load_provider(HKEY root, const WCHAR *name, struct perf_provider *provider)
{
+ static const WCHAR object_listW[] = { 'O','b','j','e','c','t',' ','L','i','s','t',0 };
static const WCHAR performanceW[] = { 'P','e','r','f','o','r','m','a','n','c','e',0 };
static const WCHAR libraryW[] = { 'L','i','b','r','a','r','y',0 };
static const WCHAR linkageW[] = { 'L','i','n','k','a','g','e',0 };
@@ -1543,6 +1545,16 @@ static BOOL load_provider(HKEY root, const WCHAR *name, struct perf_provider *pr
if (err != ERROR_SUCCESS)
return FALSE;
+ provider->objects[0] = 0;
+ len = sizeof(buf) - sizeof(WCHAR);
+ err = RegQueryValueExW(perf, object_listW, NULL, &type, (BYTE *)buf, &len);
+ if (err == ERROR_SUCCESS && (type == REG_SZ || type == REG_MULTI_SZ))
+ {
+ memcpy(provider->objects, buf, len);
+ provider->objects[len / sizeof(WCHAR)] = 0;
+ TRACE("Object List: %s\n", debugstr_w(provider->objects));
+ }
+
len = sizeof(buf) - sizeof(WCHAR);
err = RegQueryValueExW(perf, libraryW, NULL, &type, (BYTE *)buf, &len);
if (err != ERROR_SUCCESS || !(type == REG_SZ || type == REG_EXPAND_SZ))
--
2.13.1

View File

@@ -1 +0,0 @@
Fixes: [33037] Add support for querying performance counters data

View File

@@ -1,18 +1,19 @@
From 41147c17b99a8e9c556449613228315e16f067b7 Mon Sep 17 00:00:00 2001
From ee38b7a672771d088ee5c4e58300623259020fb6 Mon Sep 17 00:00:00 2001
From: Maxime Lombard <berillions@gmail.com>
Date: Sun, 10 Jun 2018 14:47:01 +0200
Subject: [PATCH 1/3] bcrypt: Add support for algorithm ECDH P256.
---
dlls/bcrypt/bcrypt_main.c | 3 +++
include/bcrypt.h | 1 +
2 files changed, 4 insertions(+)
dlls/bcrypt/bcrypt_internal.h | 1 +
dlls/bcrypt/bcrypt_main.c | 2 ++
include/bcrypt.h | 1 +
3 files changed, 4 insertions(+)
diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c
index 29a0a785d9..f2f4c93ab8 100644
--- a/dlls/bcrypt/bcrypt_main.c
+++ b/dlls/bcrypt/bcrypt_main.c
@@ -288,6 +288,7 @@ enum alg_id
diff --git a/dlls/bcrypt/bcrypt_internal.h b/dlls/bcrypt/bcrypt_internal.h
index 11c8b30..fd8cc90 100644
--- a/dlls/bcrypt/bcrypt_internal.h
+++ b/dlls/bcrypt/bcrypt_internal.h
@@ -137,6 +137,7 @@ enum alg_id
ALG_ID_SHA256,
ALG_ID_SHA384,
ALG_ID_SHA512,
@@ -20,15 +21,19 @@ index 29a0a785d9..f2f4c93ab8 100644
ALG_ID_ECDSA_P256,
ALG_ID_ECDSA_P384,
};
@@ -322,6 +323,7 @@ alg_props[] =
diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c
index 24065c1..003e8f3 100644
--- a/dlls/bcrypt/bcrypt_main.c
+++ b/dlls/bcrypt/bcrypt_main.c
@@ -114,6 +114,7 @@ alg_props[] =
/* ALG_ID_SHA256 */ { 286, 32, 512, BCRYPT_SHA256_ALGORITHM, FALSE },
/* ALG_ID_SHA384 */ { 382, 48, 1024, BCRYPT_SHA384_ALGORITHM, FALSE },
/* ALG_ID_SHA512 */ { 382, 64, 1024, BCRYPT_SHA512_ALGORITHM, FALSE },
+ /* ALG_ID_ECDH_P256 */ { 0, 0, 0, BCRYPT_ECDH_P256_ALGORITHM, FALSE },
+ /* ALG_ID_ECDH_P256 */ { 0, 0, 0, BCRYPT_ECDH_P256_ALGORITHM, FALSE },
/* ALG_ID_ECDSA_P256 */ { 0, 0, 0, BCRYPT_ECDSA_P256_ALGORITHM, FALSE },
/* ALG_ID_ECDSA_P384 */ { 0, 0, 0, BCRYPT_ECDSA_P384_ALGORITHM, FALSE },
};
@@ -400,6 +402,7 @@ NTSTATUS WINAPI BCryptOpenAlgorithmProvider( BCRYPT_ALG_HANDLE *handle, LPCWSTR
@@ -184,6 +185,7 @@ NTSTATUS WINAPI BCryptOpenAlgorithmProvider( BCRYPT_ALG_HANDLE *handle, LPCWSTR
else if (!strcmpW( id, BCRYPT_SHA256_ALGORITHM )) alg_id = ALG_ID_SHA256;
else if (!strcmpW( id, BCRYPT_SHA384_ALGORITHM )) alg_id = ALG_ID_SHA384;
else if (!strcmpW( id, BCRYPT_SHA512_ALGORITHM )) alg_id = ALG_ID_SHA512;
@@ -37,17 +42,17 @@ index 29a0a785d9..f2f4c93ab8 100644
else if (!strcmpW( id, BCRYPT_ECDSA_P384_ALGORITHM )) alg_id = ALG_ID_ECDSA_P384;
else
diff --git a/include/bcrypt.h b/include/bcrypt.h
index df54f621fa..d39920c3f6 100644
index d3e4b99..676db72 100644
--- a/include/bcrypt.h
+++ b/include/bcrypt.h
@@ -81,6 +81,7 @@ typedef LONG NTSTATUS;
#define BCRYPT_SHA256_ALGORITHM (const WCHAR []){'S','H','A','2','5','6',0}
#define BCRYPT_SHA384_ALGORITHM (const WCHAR []){'S','H','A','3','8','4',0}
#define BCRYPT_SHA512_ALGORITHM (const WCHAR []){'S','H','A','5','1','2',0}
+#define BCRYPT_ECDH_P256_ALGORITHM (const WCHAR []){'E','C','D','H','_','P','2','5','6',0}
+#define BCRYPT_ECDH_P256_ALGORITHM (const WCHAR []){'E','C','D','H','_','P','2','5','6',0}
#define BCRYPT_ECDSA_P256_ALGORITHM (const WCHAR []){'E','C','D','S','A','_','P','2','5','6',0}
#define BCRYPT_ECDSA_P384_ALGORITHM (const WCHAR []){'E','C','D','S','A','_','P','3','8','4',0}
#define BCRYPT_ECDSA_P521_ALGORITHM (const WCHAR []){'E','C','D','S','A','_','P','5','2','1',0}
--
2.17.1
1.9.1

View File

@@ -1,4 +1,4 @@
From 392cf1c3f3ddb6fa7935a6cd1f16d46004667aab Mon Sep 17 00:00:00 2001
From 8ebad635c033bf41392e23ee50494195fdce73b9 Mon Sep 17 00:00:00 2001
From: Maxime Lombard <berillions@gmail.com>
Date: Sun, 10 Jun 2018 14:50:31 +0200
Subject: [PATCH 2/3] bcrypt: Add BCryptGenerateKeyPair stub.
@@ -10,10 +10,10 @@ Subject: [PATCH 2/3] bcrypt: Add BCryptGenerateKeyPair stub.
3 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/dlls/bcrypt/bcrypt.spec b/dlls/bcrypt/bcrypt.spec
index 78824d73b3..ccfec632d6 100644
index f4d9a57..1e81ad1 100644
--- a/dlls/bcrypt/bcrypt.spec
+++ b/dlls/bcrypt/bcrypt.spec
@@ -25,7 +25,7 @@
@@ -26,7 +26,7 @@
@ stdcall BCryptFinishHash(ptr ptr long long)
@ stub BCryptFreeBuffer
@ stdcall BCryptGenRandom(ptr ptr long long)
@@ -23,12 +23,12 @@ index 78824d73b3..ccfec632d6 100644
@ stdcall BCryptGetFipsAlgorithmMode(ptr)
@ stdcall BCryptGetProperty(ptr wstr ptr long ptr long)
diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c
index f2f4c93ab8..b4ac0168e6 100644
index 003e8f3..0d94634 100644
--- a/dlls/bcrypt/bcrypt_main.c
+++ b/dlls/bcrypt/bcrypt_main.c
@@ -336,6 +336,12 @@ struct algorithm
BOOL hmac;
};
@@ -160,6 +160,12 @@ NTSTATUS WINAPI BCryptGenRandom(BCRYPT_ALG_HANDLE handle, UCHAR *buffer, ULONG c
return STATUS_NOT_IMPLEMENTED;
}
+NTSTATUS WINAPI BCryptGenerateKeyPair(BCRYPT_ALG_HANDLE algorithm, BCRYPT_KEY_HANDLE *handle, ULONG input_len, ULONG flags)
+{
@@ -36,14 +36,14 @@ index f2f4c93ab8..b4ac0168e6 100644
+ return STATUS_SUCCESS;
+}
+
NTSTATUS WINAPI BCryptGenRandom(BCRYPT_ALG_HANDLE handle, UCHAR *buffer, ULONG count, ULONG flags)
NTSTATUS WINAPI BCryptOpenAlgorithmProvider( BCRYPT_ALG_HANDLE *handle, LPCWSTR id, LPCWSTR implementation, DWORD flags )
{
const DWORD supported_flags = BCRYPT_USE_SYSTEM_PREFERRED_RNG;
const DWORD supported_flags = BCRYPT_ALG_HANDLE_HMAC_FLAG;
diff --git a/include/bcrypt.h b/include/bcrypt.h
index d39920c3f6..e6b7d4a9ac 100644
index 676db72..ce11685 100644
--- a/include/bcrypt.h
+++ b/include/bcrypt.h
@@ -223,6 +223,7 @@ NTSTATUS WINAPI BCryptDestroyKey(BCRYPT_KEY_HANDLE);
@@ -224,6 +224,7 @@ NTSTATUS WINAPI BCryptDestroyKey(BCRYPT_KEY_HANDLE);
NTSTATUS WINAPI BCryptEncrypt(BCRYPT_KEY_HANDLE, PUCHAR, ULONG, VOID *, PUCHAR, ULONG, PUCHAR, ULONG, ULONG *, ULONG);
NTSTATUS WINAPI BCryptEnumAlgorithms(ULONG, ULONG *, BCRYPT_ALGORITHM_IDENTIFIER **, ULONG);
NTSTATUS WINAPI BCryptFinishHash(BCRYPT_HASH_HANDLE, PUCHAR, ULONG, ULONG);
@@ -52,5 +52,5 @@ index d39920c3f6..e6b7d4a9ac 100644
NTSTATUS WINAPI BCryptGenRandom(BCRYPT_ALG_HANDLE, PUCHAR, ULONG, ULONG);
NTSTATUS WINAPI BCryptGetFipsAlgorithmMode(BOOLEAN *);
--
2.17.1
1.9.1

View File

@@ -1,4 +1,4 @@
From 85e1f780a0d26d6c1e286c944fbcf25e762633b9 Mon Sep 17 00:00:00 2001
From 046863d1eb6db25555743cbbc257260387b31c19 Mon Sep 17 00:00:00 2001
From: Maxime Lombard <berillions@gmail.com>
Date: Sun, 10 Jun 2018 14:52:31 +0200
Subject: [PATCH 3/3] bcrypt: Add BCryptFinalizeKeyPair stub.
@@ -10,10 +10,10 @@ Subject: [PATCH 3/3] bcrypt: Add BCryptFinalizeKeyPair stub.
3 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/dlls/bcrypt/bcrypt.spec b/dlls/bcrypt/bcrypt.spec
index ccfec632d6..891381f2a8 100644
index 1e81ad1..052a099 100644
--- a/dlls/bcrypt/bcrypt.spec
+++ b/dlls/bcrypt/bcrypt.spec
@@ -21,7 +21,7 @@
@@ -22,7 +22,7 @@
@ stub BCryptEnumProviders
@ stub BCryptEnumRegisteredProviders
@ stdcall BCryptExportKey(ptr ptr wstr ptr long ptr long)
@@ -23,12 +23,12 @@ index ccfec632d6..891381f2a8 100644
@ stub BCryptFreeBuffer
@ stdcall BCryptGenRandom(ptr ptr long long)
diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c
index b4ac0168e6..69037971bf 100644
index 0d94634..40a3405 100644
--- a/dlls/bcrypt/bcrypt_main.c
+++ b/dlls/bcrypt/bcrypt_main.c
@@ -336,6 +336,12 @@ struct algorithm
BOOL hmac;
};
@@ -166,6 +166,12 @@ NTSTATUS WINAPI BCryptGenerateKeyPair(BCRYPT_ALG_HANDLE algorithm, BCRYPT_KEY_HA
return STATUS_SUCCESS;
}
+NTSTATUS WINAPI BCryptFinalizeKeyPair(BCRYPT_KEY_HANDLE key, ULONG dwflags)
+{
@@ -36,14 +36,14 @@ index b4ac0168e6..69037971bf 100644
+ return STATUS_SUCCESS;
+}
+
NTSTATUS WINAPI BCryptGenerateKeyPair(BCRYPT_ALG_HANDLE algorithm, BCRYPT_KEY_HANDLE *handle, ULONG input_len, ULONG flags)
NTSTATUS WINAPI BCryptOpenAlgorithmProvider( BCRYPT_ALG_HANDLE *handle, LPCWSTR id, LPCWSTR implementation, DWORD flags )
{
FIXME("%p, %p, %u, %08x - stub\n", algorithm, handle, input_len, flags);
const DWORD supported_flags = BCRYPT_ALG_HANDLE_HMAC_FLAG;
diff --git a/include/bcrypt.h b/include/bcrypt.h
index e6b7d4a9ac..b5844a144d 100644
index ce11685..b8e93a6 100644
--- a/include/bcrypt.h
+++ b/include/bcrypt.h
@@ -222,6 +222,7 @@ NTSTATUS WINAPI BCryptDestroyHash(BCRYPT_HASH_HANDLE);
@@ -223,6 +223,7 @@ NTSTATUS WINAPI BCryptDestroyHash(BCRYPT_HASH_HANDLE);
NTSTATUS WINAPI BCryptDestroyKey(BCRYPT_KEY_HANDLE);
NTSTATUS WINAPI BCryptEncrypt(BCRYPT_KEY_HANDLE, PUCHAR, ULONG, VOID *, PUCHAR, ULONG, PUCHAR, ULONG, ULONG *, ULONG);
NTSTATUS WINAPI BCryptEnumAlgorithms(ULONG, ULONG *, BCRYPT_ALGORITHM_IDENTIFIER **, ULONG);
@@ -52,5 +52,5 @@ index e6b7d4a9ac..b5844a144d 100644
NTSTATUS WINAPI BCryptGenerateKeyPair(BCRYPT_ALG_HANDLE, BCRYPT_KEY_HANDLE *, ULONG, ULONG);
NTSTATUS WINAPI BCryptGenerateSymmetricKey(BCRYPT_ALG_HANDLE, BCRYPT_KEY_HANDLE *, PUCHAR, ULONG, PUCHAR, ULONG, ULONG);
--
2.17.1
1.9.1

View File

@@ -1,53 +0,0 @@
From fe4f06bfdb1a53e0be15aca8f1f8f897f7fef632 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Fri, 27 Feb 2015 17:46:11 +0100
Subject: browseui: Implement IProgressDialog::SetAnimation.
---
dlls/browseui/progressdlg.c | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/dlls/browseui/progressdlg.c b/dlls/browseui/progressdlg.c
index 598197b..a14fa17 100644
--- a/dlls/browseui/progressdlg.c
+++ b/dlls/browseui/progressdlg.c
@@ -175,6 +175,7 @@ static INT_PTR CALLBACK dialog_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM l
case WM_INITDIALOG:
{
struct create_params *params = (struct create_params *)lParam;
+ LONG_PTR style;
/* Note: until we set the hEvent, the object is protected by
* the critical section held by StartProgress */
@@ -191,6 +192,10 @@ static INT_PTR CALLBACK dialog_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM l
if (This->dwFlags & PROGDLG_NOMINIMIZE)
SetWindowLongW(hwnd, GWL_STYLE, GetWindowLongW(hwnd, GWL_STYLE) & (~WS_MINIMIZEBOX));
+ style = GetWindowLongPtrW(GetDlgItem(hwnd, IDC_ANIMATION), GWL_STYLE);
+ style |= ACS_AUTOPLAY | ACS_TRANSPARENT;
+ SetWindowLongPtrW(GetDlgItem(hwnd, IDC_ANIMATION), GWL_STYLE, style);
+
update_dialog(This, 0xffffffff);
This->dwUpdate = 0;
This->isCancelled = FALSE;
@@ -396,7 +401,16 @@ static HRESULT WINAPI ProgressDialog_SetTitle(IProgressDialog *iface, LPCWSTR pw
static HRESULT WINAPI ProgressDialog_SetAnimation(IProgressDialog *iface, HINSTANCE hInstance, UINT uiResourceId)
{
- FIXME("(%p, %p, %d) - stub\n", iface, hInstance, uiResourceId);
+ ProgressDialog *This = impl_from_IProgressDialog(iface);
+
+ TRACE("(%p, %p, %d)\n", iface, hInstance, uiResourceId);
+
+ if (uiResourceId & ~0xFFFF)
+ return S_OK;
+
+ if (!SendDlgItemMessageW(This->hwnd, IDC_ANIMATION, ACM_OPENW, (WPARAM)hInstance, uiResourceId))
+ WARN("Failed to load animation\n");
+
return S_OK;
}
--
2.3.0

View File

@@ -0,0 +1,31 @@
From 1cee10b74621b8d70ff31b6e358ee52bd57e695e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=B3zef=20Kucia?= <jkucia@codeweavers.com>
Date: Sat, 2 Jan 2016 11:48:45 +0100
Subject: [PATCH] ddraw: Prevent division by zero in viewport_activate.
Reply-To: wine-devel <wine-devel@winehq.org>
This just stop the crash, without fixing the actual cause.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=36763
---
dlls/ddraw/viewport.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/dlls/ddraw/viewport.c b/dlls/ddraw/viewport.c
index 5ebc41e..16cdad4 100644
--- a/dlls/ddraw/viewport.c
+++ b/dlls/ddraw/viewport.c
@@ -71,6 +71,10 @@ void viewport_activate(struct d3d_viewport *This, BOOL ignore_lights)
/* And copy the values in the structure used by the device */
if (This->use_vp2)
{
+ if (!This->viewports.vp2.dvMinZ && !This->viewports.vp2.dvMaxZ
+ && !This->viewports.vp2.dvClipWidth && !This->viewports.vp2.dvClipHeight)
+ return;
+
vp.dwX = This->viewports.vp2.dwX;
vp.dwY = This->viewports.vp2.dwY;
vp.dwHeight = This->viewports.vp2.dwHeight;
--
2.4.10

View File

@@ -0,0 +1 @@
Fixes: [36763] Prevent division by zero in viewport_activate

View File

@@ -1,97 +0,0 @@
From 1f4a7bc3ed8ede33a6e623bf49067550cee433d8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Sun, 19 Mar 2017 15:52:42 +0100
Subject: gdi32: Treat lpResults as optional in GetCharacterPlacement.
---
dlls/gdi32/font.c | 13 ++++++++++++-
dlls/gdi32/tests/font.c | 32 ++++++++++++++++++++++++++++++++
2 files changed, 44 insertions(+), 1 deletion(-)
diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c
index ddd0051ab6..fcc24d8645 100644
--- a/dlls/gdi32/font.c
+++ b/dlls/gdi32/font.c
@@ -3201,10 +3201,18 @@ GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
TRACE("%s, %d, %d, 0x%08x\n",
debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
+ lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
+
+ if (!lpResults)
+ {
+ ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, NULL, dwFlags);
+ HeapFree(GetProcessHeap(), 0, lpStringW);
+ return ret;
+ }
+
/* both structs are equal in size */
memcpy(&resultsW, lpResults, sizeof(resultsW));
- lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
if(lpResults->lpOutString)
resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
@@ -3259,6 +3267,9 @@ GetCharacterPlacementW(
TRACE("%s, %d, %d, 0x%08x\n",
debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
+ if (!lpResults)
+ return GetTextExtentPoint32W(hdc, lpString, uCount, &size) ? MAKELONG(size.cx, size.cy) : 0;
+
TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
"lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
diff --git a/dlls/gdi32/tests/font.c b/dlls/gdi32/tests/font.c
index fb27f8e005..974b471462 100644
--- a/dlls/gdi32/tests/font.c
+++ b/dlls/gdi32/tests/font.c
@@ -4910,6 +4910,37 @@ static void test_GetTextMetrics2(const char *fontname, int font_height)
ok(ratio >= 90 && ratio <= 110, "expected width/height ratio 90-110, got %d\n", ratio);
}
+static void test_GetCharacterPlacement(void)
+{
+ GCP_RESULTSA result;
+ DWORD size, size2;
+ WCHAR glyphs[20];
+ HDC hdc;
+
+ hdc = CreateCompatibleDC(0);
+ ok(!!hdc, "CreateCompatibleDC failed\n");
+
+ memset(&result, 0, sizeof(result));
+ result.lStructSize = sizeof(result);
+ result.lpGlyphs = glyphs;
+ result.nGlyphs = 20;
+
+ size = GetCharacterPlacementA(hdc, "Wine Test", 9, 0, &result, 0);
+ ok(size, "GetCharacterPlacementA failed!\n");
+
+ size2 = GetCharacterPlacementA(hdc, "Wine Test", 9, 0, NULL, 0);
+ ok(size2, "GetCharacterPlacementA failed!\n");
+ ok(size == size2, "GetCharacterPlacementA returned different result: %u vs %u\n", size2, size);
+
+ size2 = GetCharacterPlacementA(hdc, "Wine Test", 9, 1024, NULL, GCP_REORDER);
+ ok(size2, "GetCharacterPlacementA failed!\n");
+ ok(size == size2, "GetCharacterPlacementA returned different result: %u vs %u\n", size2, size);
+
+ size = GetCharacterPlacementA(hdc, "Wine Test", 9, 1024, &result, GCP_REORDER);
+ ok(size, "GetCharacterPlacementA failed!\n");
+ ok(size == size2, "GetCharacterPlacementA returned different result: %u vs %u\n", size2, size);
+}
+
static void test_CreateFontIndirect(void)
{
LOGFONTA lf, getobj_lf;
@@ -6682,6 +6713,7 @@ START_TEST(font)
test_GetTextMetrics2("Arial", -11);
test_GetTextMetrics2("Arial", -55);
test_GetTextMetrics2("Arial", -110);
+ test_GetCharacterPlacement();
test_CreateFontIndirect();
test_CreateFontIndirectEx();
test_oemcharset();
--
2.11.0

View File

@@ -1 +0,0 @@
Fixes: [42669] Treat lpResults as optional in gdi32.GetCharacterPlacement

View File

@@ -1 +1 @@
Fixes: [35928] Crash handlers/debuggers fail to display user-interface when invoked for crashing (non-interactive) service processes (inherited Wine service window station/desktop)
#Fixes: [35928] Crash handlers/debuggers fail to display user-interface when invoked for crashing (non-interactive) service processes (inherited Wine service window station/desktop)

View File

@@ -0,0 +1,251 @@
From 0dc009c4320a9cb72dc96bb60bd55970cf6d4345 Mon Sep 17 00:00:00 2001
From: Julien Schueller <schueller@phimeca.com>
Date: Wed, 4 Jul 2018 22:35:16 +0200
Subject: [PATCH] kernelbase: Implement
PathCchRemoveBackslash()/PathCchRemoveBackslashEx().
---
.../api-ms-win-core-path-l1-1-0.spec | 4 +-
dlls/kernelbase/kernelbase.spec | 4 +-
dlls/kernelbase/path.c | 31 +++++
dlls/kernelbase/tests/path.c | 127 ++++++++++++++++++
include/pathcch.h | 2 +
5 files changed, 164 insertions(+), 4 deletions(-)
diff --git a/dlls/api-ms-win-core-path-l1-1-0/api-ms-win-core-path-l1-1-0.spec b/dlls/api-ms-win-core-path-l1-1-0/api-ms-win-core-path-l1-1-0.spec
index 9895b1b8e23..591ee7d882f 100644
--- a/dlls/api-ms-win-core-path-l1-1-0/api-ms-win-core-path-l1-1-0.spec
+++ b/dlls/api-ms-win-core-path-l1-1-0/api-ms-win-core-path-l1-1-0.spec
@@ -11,8 +11,8 @@
@ stdcall PathCchCombineEx(ptr long ptr ptr long) kernelbase.PathCchCombineEx
@ stub PathCchFindExtension
@ stub PathCchIsRoot
-@ stub PathCchRemoveBackslash
-@ stub PathCchRemoveBackslashEx
+@ stdcall PathCchRemoveBackslash(wstr long) kernelbase.PathCchRemoveBackslash
+@ stdcall PathCchRemoveBackslashEx(wstr long ptr ptr) kernelbase.PathCchRemoveBackslashEx
@ stub PathCchRemoveExtension
@ stub PathCchRemoveFileSpec
@ stub PathCchRenameExtension
diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec
index 1f75b080378..c4a75bc1694 100644
--- a/dlls/kernelbase/kernelbase.spec
+++ b/dlls/kernelbase/kernelbase.spec
@@ -1040,8 +1040,8 @@
@ stdcall PathCchCombineEx(ptr long ptr ptr long)
# @ stub PathCchFindExtension
# @ stub PathCchIsRoot
-# @ stub PathCchRemoveBackslash
-# @ stub PathCchRemoveBackslashEx
+@ stdcall PathCchRemoveBackslash(wstr long)
+@ stdcall PathCchRemoveBackslashEx(wstr long ptr ptr)
# @ stub PathCchRemoveExtension
# @ stub PathCchRemoveFileSpec
# @ stub PathCchRenameExtension
diff --git a/dlls/kernelbase/path.c b/dlls/kernelbase/path.c
index 52ef7d97654..3113bfe1255 100644
--- a/dlls/kernelbase/path.c
+++ b/dlls/kernelbase/path.c
@@ -91,3 +91,34 @@ HRESULT WINAPI PathCchCombineEx(WCHAR *out, SIZE_T size, const WCHAR *path1, con
strcpyW(out, result);
return S_OK;
}
+
+HRESULT WINAPI PathCchRemoveBackslash(WCHAR *path, SIZE_T size)
+{
+ return PathCchRemoveBackslashEx(path, size, NULL, NULL);
+}
+
+HRESULT WINAPI PathCchRemoveBackslashEx(WCHAR *path, SIZE_T size, WCHAR **endptr, SIZE_T *remaining)
+{
+ BOOL needs_trim;
+ SIZE_T length;
+
+ TRACE("%s, %lu, %p, %p\n", debugstr_w(path), size, endptr, remaining);
+
+ if (!path) return E_INVALIDARG;
+ length = strlenW(path);
+ needs_trim = size && length && path[length - 1] == '\\';
+
+ if (needs_trim && (length > 1) && path[length - 2] == ':')
+ needs_trim = 0;
+
+ if (needs_trim)
+ {
+ path[length - 1] = 0;
+ --length;
+ }
+
+ if (endptr) *endptr = path + length;
+ if (remaining) *remaining = size - length;
+
+ return needs_trim ? S_OK : S_FALSE;
+}
diff --git a/dlls/kernelbase/tests/path.c b/dlls/kernelbase/tests/path.c
index cdba51bf3f6..20f8852faca 100644
--- a/dlls/kernelbase/tests/path.c
+++ b/dlls/kernelbase/tests/path.c
@@ -31,6 +31,8 @@
HRESULT (WINAPI *pPathCchAddBackslash)(WCHAR *out, SIZE_T size);
HRESULT (WINAPI *pPathCchAddBackslashEx)(WCHAR *out, SIZE_T size, WCHAR **endptr, SIZE_T *remaining);
+HRESULT (WINAPI *pPathCchRemoveBackslash)(WCHAR *out, SIZE_T size);
+HRESULT (WINAPI *pPathCchRemoveBackslashEx)(WCHAR *out, SIZE_T size, WCHAR **endptr, SIZE_T *remaining);
HRESULT (WINAPI *pPathCchCombineEx)(WCHAR *out, SIZE_T size, const WCHAR *path1, const WCHAR *path2, DWORD flags);
static const struct
@@ -245,6 +247,127 @@ static void test_PathCchAddBackslashEx(void)
}
}
+struct removebackslash_test
+{
+ const char *path;
+ const char *result;
+ HRESULT hr;
+ SIZE_T size;
+ SIZE_T remaining;
+};
+
+static const struct removebackslash_test removebackslash_tests[] =
+{
+ { "C:\\", "C:\\", S_FALSE, MAX_PATH, MAX_PATH - 3 },
+ { "a.txt\\", "a.txt", S_OK, MAX_PATH, MAX_PATH - 5 },
+ { "a/b\\", "a/b", S_OK, MAX_PATH, MAX_PATH - 3 },
+ { "C:\\temp\\wine.txt", "C:\\temp\\wine.txt", S_FALSE, MAX_PATH, MAX_PATH - 16 },
+};
+
+static void test_PathCchRemoveBackslash(void)
+{
+ WCHAR pathW[MAX_PATH];
+ unsigned int i;
+ HRESULT hr;
+
+ if (!pPathCchRemoveBackslash)
+ {
+ win_skip("PathCchRemoveBackslash() is not available.\n");
+ return;
+ }
+
+ pathW[0] = 0;
+ hr = pPathCchRemoveBackslash(0, 0);
+ ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+ ok(pathW[0] == 0, "Unexpected path.\n");
+
+ pathW[0] = 0;
+ hr = pPathCchRemoveBackslash(pathW, 1);
+ ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
+ ok(pathW[0] == 0, "Unexpected path.\n");
+
+ pathW[0] = 0;
+ hr = pPathCchRemoveBackslash(pathW, 2);
+ ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
+ ok(pathW[0] == 0, "Unexpected path.\n");
+
+ for (i = 0; i < ARRAY_SIZE(removebackslash_tests); i++)
+ {
+ const struct removebackslash_test *test = &removebackslash_tests[i];
+ char path[MAX_PATH];
+
+ MultiByteToWideChar(CP_ACP, 0, test->path, -1, pathW, ARRAY_SIZE(pathW));
+ hr = pPathCchRemoveBackslash(pathW, test->size);
+ ok(hr == test->hr, "%u: unexpected return value %#x.\n", i, hr);
+
+ WideCharToMultiByte(CP_ACP, 0, pathW, -1, path, ARRAY_SIZE(path), NULL, NULL);
+ ok(!strcmp(path, test->result), "%u: unexpected resulting path %s.\n", i, path);
+ }
+}
+
+static void test_PathCchRemoveBackslashEx(void)
+{
+ WCHAR pathW[MAX_PATH];
+ SIZE_T remaining;
+ unsigned int i;
+ HRESULT hr;
+ WCHAR *ptrW;
+
+ if (!pPathCchRemoveBackslashEx)
+ {
+ win_skip("PathCchRemoveBackslashEx() is not available.\n");
+ return;
+ }
+
+ pathW[0] = 0;
+ hr = pPathCchRemoveBackslashEx(0, 0, NULL, NULL);
+ ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+ ok(pathW[0] == 0, "Unexpected path.\n");
+
+ pathW[0] = 0;
+ ptrW = (void *)0xdeadbeef;
+ remaining = 123;
+ hr = pPathCchRemoveBackslashEx(pathW, 1, &ptrW, &remaining);
+ ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
+ ok(pathW[0] == 0, "Unexpected path.\n");
+ ok(ptrW == pathW, "Unexpected endptr %p.\n", ptrW);
+ ok(remaining == 1, "Unexpected remaining size.\n");
+
+ pathW[0] = 0;
+ hr = pPathCchRemoveBackslashEx(pathW, 2, NULL, NULL);
+ ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
+ ok(pathW[0] == 0, "Unexpected path.\n");
+
+ for (i = 0; i < ARRAY_SIZE(removebackslash_tests); i++)
+ {
+ const struct removebackslash_test *test = &removebackslash_tests[i];
+ char path[MAX_PATH];
+
+ MultiByteToWideChar(CP_ACP, 0, test->path, -1, pathW, ARRAY_SIZE(pathW));
+ hr = pPathCchRemoveBackslashEx(pathW, test->size, NULL, NULL);
+ ok(hr == test->hr, "%u: unexpected return value %#x.\n", i, hr);
+
+ WideCharToMultiByte(CP_ACP, 0, pathW, -1, path, ARRAY_SIZE(path), NULL, NULL);
+ ok(!strcmp(path, test->result), "%u: unexpected resulting path %s.\n", i, path);
+
+ ptrW = (void *)0xdeadbeef;
+ remaining = 123;
+ MultiByteToWideChar(CP_ACP, 0, test->path, -1, pathW, ARRAY_SIZE(pathW));
+ hr = pPathCchRemoveBackslashEx(pathW, test->size, &ptrW, &remaining);
+ ok(hr == test->hr, "%u: unexpected return value %#x.\n", i, hr);
+ if (SUCCEEDED(hr))
+ {
+ ok(ptrW == (pathW + lstrlenW(pathW)), "%u: unexpected end pointer.\n", i);
+ ok(remaining == test->remaining, "%u: unexpected remaining buffer length.\n", i);
+ }
+ else
+ {
+ ok(ptrW == NULL, "%u: unexpecred end pointer.\n", i);
+ ok(remaining == 0, "%u: unexpected remaining buffer length.\n", i);
+ }
+ }
+}
+
START_TEST(path)
{
HMODULE hmod = LoadLibraryA("kernelbase.dll");
@@ -252,8 +375,12 @@ START_TEST(path)
pPathCchCombineEx = (void *)GetProcAddress(hmod, "PathCchCombineEx");
pPathCchAddBackslash = (void *)GetProcAddress(hmod, "PathCchAddBackslash");
pPathCchAddBackslashEx = (void *)GetProcAddress(hmod, "PathCchAddBackslashEx");
+ pPathCchRemoveBackslash = (void *)GetProcAddress(hmod, "PathCchRemoveBackslash");
+ pPathCchRemoveBackslashEx = (void *)GetProcAddress(hmod, "PathCchRemoveBackslashEx");
test_PathCchCombineEx();
test_PathCchAddBackslash();
test_PathCchAddBackslashEx();
+ test_PathCchRemoveBackslash();
+ test_PathCchRemoveBackslashEx();
}
diff --git a/include/pathcch.h b/include/pathcch.h
index 2b2aed4c8f9..c19ed1d9306 100644
--- a/include/pathcch.h
+++ b/include/pathcch.h
@@ -25,4 +25,6 @@
HRESULT WINAPI PathCchAddBackslash(WCHAR *path, SIZE_T size);
HRESULT WINAPI PathCchAddBackslashEx(WCHAR *path, SIZE_T size, WCHAR **end, SIZE_T *remaining);
+HRESULT WINAPI PathCchRemoveBackslash(WCHAR *path, SIZE_T size);
+HRESULT WINAPI PathCchRemoveBackslashEx(WCHAR *path, SIZE_T size, WCHAR **end, SIZE_T *remaining);
HRESULT WINAPI PathCchCombineEx(WCHAR *out, SIZE_T size, const WCHAR *path1, const WCHAR *path2, DWORD flags);
--
2.18.0

View File

@@ -1,333 +0,0 @@
From 7b6d523f37901554bfdb17e301dd25e50a899e22 Mon Sep 17 00:00:00 2001
From: Mark Jansen <learn0more+wine@gmail.com>
Date: Sun, 8 Mar 2015 18:24:50 +0100
Subject: ntdll/tests: Tests for RtlIpv6StringToAddressEx (try 6)
Changes from try5:
-Reformat ipv6 table to be less wide
-Remove _s6_un from memcmp calls
Changes from try4 (all suggestions from stefand in #winehackers):
-Use RtlMultiByteToUnicodeN for A->W conversion
-Fix warning
-Clarify comment / move init_ip6 inside if branch
Changes from try3:
-Also test the W version against the A version
-Test the ip against the non-ex version as suggested by stefand
-Add more testcases
---
dlls/ntdll/tests/rtl.c | 269 ++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 268 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/tests/rtl.c b/dlls/ntdll/tests/rtl.c
index 47acfe9..f5bbbb3 100644
--- a/dlls/ntdll/tests/rtl.c
+++ b/dlls/ntdll/tests/rtl.c
@@ -92,6 +92,8 @@ static NTSTATUS (WINAPI *pRtlIpv4AddressToStringExA)(const IN_ADDR *, USHORT, L
static NTSTATUS (WINAPI *pRtlIpv4StringToAddressA)(PCSTR, BOOLEAN, PCSTR *, IN_ADDR *);
static NTSTATUS (WINAPI *pRtlIpv6StringToAddressA)(PCSTR, PCSTR *, struct in6_addr *);
static NTSTATUS (WINAPI *pRtlIpv6StringToAddressW)(PCWSTR, PCWSTR *, struct in6_addr *);
+static NTSTATUS (WINAPI *pRtlIpv6StringToAddressExA)(PCSTR, struct in6_addr *, PULONG, PUSHORT);
+static NTSTATUS (WINAPI *pRtlIpv6StringToAddressExW)(PCWSTR, struct in6_addr *, PULONG, PUSHORT);
static NTSTATUS (WINAPI *pLdrAddRefDll)(ULONG, HMODULE);
static NTSTATUS (WINAPI *pLdrLockLoaderLock)(ULONG, ULONG*, ULONG_PTR*);
static NTSTATUS (WINAPI *pLdrUnlockLoaderLock)(ULONG, ULONG_PTR);
@@ -146,6 +148,8 @@ static void InitFunctionPtrs(void)
pRtlIpv4StringToAddressA = (void *)GetProcAddress(hntdll, "RtlIpv4StringToAddressA");
pRtlIpv6StringToAddressA = (void *)GetProcAddress(hntdll, "RtlIpv6StringToAddressA");
pRtlIpv6StringToAddressW = (void *)GetProcAddress(hntdll, "RtlIpv6StringToAddressW");
+ pRtlIpv6StringToAddressExA = (void *)GetProcAddress(hntdll, "RtlIpv6StringToAddressExA");
+ pRtlIpv6StringToAddressExW = (void *)GetProcAddress(hntdll, "RtlIpv6StringToAddressExW");
pLdrAddRefDll = (void *)GetProcAddress(hntdll, "LdrAddRefDll");
pLdrLockLoaderLock = (void *)GetProcAddress(hntdll, "LdrLockLoaderLock");
pLdrUnlockLoaderLock = (void *)GetProcAddress(hntdll, "LdrUnlockLoaderLock");
@@ -1783,7 +1787,6 @@ static const struct
};
const unsigned int ipv6_testcount = sizeof(ipv6_tests) / sizeof(ipv6_tests[0]);
-
static void init_ip6(IN6_ADDR* addr, const int src[8])
{
unsigned int j;
@@ -1929,6 +1932,269 @@ static void test_RtlIpv6StringToAddress(void)
}
}
+static void compare_RtlIpv6StringToAddressExW(PCSTR name_a, const struct in6_addr *addr_a, HRESULT res_a, ULONG scope_a, USHORT port_a)
+{
+ WCHAR name[512];
+ NTSTATUS res;
+ IN6_ADDR ip;
+ ULONG scope = 0xbadf00d;
+ USHORT port = 0xbeef;
+
+ if (!pRtlIpv6StringToAddressExW)
+ return;
+
+ pRtlMultiByteToUnicodeN(name, sizeof(name), NULL, name_a, strlen(name_a) + 1);
+
+ init_ip6(&ip, NULL);
+ res = pRtlIpv6StringToAddressExW(name, &ip, &scope, &port);
+
+ ok(res == res_a, "[W:%s] res = 0x%08x, expected 0x%08x\n", name_a, res, res_a);
+ ok(scope == scope_a, "[W:%s] scope = 0x%08x, expected 0x%08x\n", name_a, scope, scope_a);
+ ok(port == port_a, "[W:%s] port = 0x%08x, expected 0x%08x\n", name_a, port, port_a);
+
+ ok(!memcmp(&ip, addr_a, sizeof(ip)),
+ "[W:%s] ip = %x:%x:%x:%x:%x:%x:%x:%x, expected %x:%x:%x:%x:%x:%x:%x:%x\n",
+ name_a,
+ ip.s6_words[0], ip.s6_words[1], ip.s6_words[2], ip.s6_words[3],
+ ip.s6_words[4], ip.s6_words[5], ip.s6_words[6], ip.s6_words[7],
+ addr_a->s6_words[0], addr_a->s6_words[1], addr_a->s6_words[2], addr_a->s6_words[3],
+ addr_a->s6_words[4], addr_a->s6_words[5], addr_a->s6_words[6], addr_a->s6_words[7]);
+}
+
+static void test_RtlIpv6StringToAddressEx(void)
+{
+ NTSTATUS res;
+ IN6_ADDR ip, expected_ip;
+ ULONG scope;
+ USHORT port;
+ static const struct
+ {
+ PCSTR address;
+ NTSTATUS res;
+ ULONG scope;
+ USHORT port;
+ int ip[8];
+ } ipv6_ex_tests[] =
+ {
+ { "[::]", STATUS_SUCCESS, 0, 0,
+ { 0, 0, 0, 0, 0, 0, 0, 0 } },
+ { "[::1]:8080", STATUS_SUCCESS, 0, 0x901f,
+ { 0, 0, 0, 0, 0, 0, 0, 0x100 } },
+ { "[::1]:0x80", STATUS_SUCCESS, 0, 0x8000,
+ { 0, 0, 0, 0, 0, 0, 0, 0x100 } },
+ { "[::1]:0X80", STATUS_SUCCESS, 0, 0x8000,
+ { 0, 0, 0, 0, 0, 0, 0, 0x100 } },
+ { "[::1]:080", STATUS_INVALID_PARAMETER, 0xbadf00d, 0xbeef,
+ { 0, 0, 0, 0, 0, 0, 0, 0x100 } },
+ { "[::1]:800000000080", STATUS_INVALID_PARAMETER, 0xbadf00d, 0xbeef,
+ { 0, 0, 0, 0, 0, 0, 0, 0x100 } },
+ { "[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80", STATUS_SUCCESS, 0, 0x5000,
+ { 0xdcfe, 0x98ba, 0x5476, 0x1032, 0xdcfe, 0x98ba, 0x5476, 0x1032 } },
+ { "[1080:0:0:0:8:800:200C:417A]:1234", STATUS_SUCCESS, 0, 0xd204,
+ { 0x8010, 0, 0, 0, 0x800, 8, 0xc20, 0x7a41 } },
+ { "[3ffe:2a00:100:7031::1]:8080", STATUS_SUCCESS, 0, 0x901f,
+ { 0xfe3f, 0x2a, 1, 0x3170, 0, 0, 0, 0x100 } },
+ { "[ 3ffe:2a00:100:7031::1]:8080", STATUS_INVALID_PARAMETER, 0xbadf00d, 0xbeef,
+ { -1 } },
+ { "[3ffe:2a00:100:7031::1 ]:8080", STATUS_INVALID_PARAMETER, 0xbadf00d, 0xbeef,
+ { 0xfe3f, 0x2a, 1, 0x3170, 0, 0, 0, 0x100 } },
+ { "[3ffe:2a00:100:7031::1].8080", STATUS_INVALID_PARAMETER, 0xbadf00d, 0xbeef,
+ { 0xfe3f, 0x2a, 1, 0x3170, 0, 0, 0, 0x100 } },
+ { "[1080::8:800:200C:417A]:8080", STATUS_SUCCESS, 0, 0x901f,
+ { 0x8010, 0, 0, 0, 0x800, 8, 0xc20, 0x7a41 } },
+ { "[1080::8:800:200C:417A]!8080", STATUS_INVALID_PARAMETER, 0xbadf00d, 0xbeef,
+ { 0x8010, 0, 0, 0, 0x800, 8, 0xc20, 0x7a41 } },
+ { "[::FFFF:129.144.52.38]:80", STATUS_SUCCESS, 0, 0x5000,
+ { 0, 0, 0, 0, 0, 0xffff, 0x9081, 0x2634 } },
+ { "[::FFFF:129.144.52.38]:-80", STATUS_INVALID_PARAMETER, 0xbadf00d, 0xbeef,
+ { 0, 0, 0, 0, 0, 0xffff, 0x9081, 0x2634 } },
+ { "[::FFFF:129.144.52.38]:999999999999", STATUS_INVALID_PARAMETER, 0xbadf00d, 0xbeef,
+ { 0, 0, 0, 0, 0, 0xffff, 0x9081, 0x2634 } },
+ { "[::FFFF:129.144.52.38%-8]:80", STATUS_INVALID_PARAMETER, 0xbadf00d, 0xbeef,
+ { 0, 0, 0, 0, 0, 0xffff, 0x9081, 0x2634 } },
+ { "[::FFFF:129.144.52.38]:80", STATUS_SUCCESS, 0, 0x5000,
+ { 0, 0, 0, 0, 0, 0xffff, 0x9081, 0x2634 } },
+ { "[12345::6:7:8]:80", STATUS_INVALID_PARAMETER, 0xbadf00d, 0xbeef,
+ { -1 } },
+ { "[ff01::8:800:200C:417A%16]:8080", STATUS_SUCCESS, 16, 0x901f,
+ { 0x1ff, 0, 0, 0, 0x800, 8, 0xc20, 0x7a41 } },
+ { "[ff01::8:800:200C:417A%100]:8080", STATUS_SUCCESS, 100, 0x901f,
+ { 0x1ff, 0, 0, 0, 0x800, 8, 0xc20, 0x7a41 } },
+ { "[ff01::8:800:200C:417A%1000]:8080", STATUS_SUCCESS, 1000, 0x901f,
+ { 0x1ff, 0, 0, 0, 0x800, 8, 0xc20, 0x7a41 } },
+ { "[ff01::8:800:200C:417A%10000]:8080", STATUS_SUCCESS, 10000, 0x901f,
+ { 0x1ff, 0, 0, 0, 0x800, 8, 0xc20, 0x7a41 } },
+ { "[ff01::8:800:200C:417A%1000000]:8080", STATUS_SUCCESS, 1000000, 0x901f,
+ { 0x1ff, 0, 0, 0, 0x800, 8, 0xc20, 0x7a41 } },
+ { "[ff01::8:800:200C:417A%4294967295]:8080", STATUS_SUCCESS, 0xffffffff, 0x901f,
+ { 0x1ff, 0, 0, 0, 0x800, 8, 0xc20, 0x7a41 } },
+ { "[ff01::8:800:200C:417A%4294967296]:8080", STATUS_INVALID_PARAMETER, 0xbadf00d, 0xbeef,
+ { 0x1ff, 0, 0, 0, 0x800, 8, 0xc20, 0x7a41 } },
+ { "[ff01::8:800:200C:417A%-1]:8080", STATUS_INVALID_PARAMETER, 0xbadf00d, 0xbeef,
+ { 0x1ff, 0, 0, 0, 0x800, 8, 0xc20, 0x7a41 } },
+ { "[ff01::8:800:200C:417A%0]:8080", STATUS_SUCCESS, 0, 0x901f,
+ { 0x1ff, 0, 0, 0, 0x800, 8, 0xc20, 0x7a41 } },
+ { "[ff01::8:800:200C:417A%1", STATUS_INVALID_PARAMETER, 0xbadf00d, 0xbeef,
+ { 0x1ff, 0, 0, 0, 0x800, 8, 0xc20, 0x7a41 } },
+ { "[ff01::8:800:200C:417A%0x1000]:8080", STATUS_INVALID_PARAMETER, 0xbadf00d, 0xbeef,
+ { 0x1ff, 0, 0, 0, 0x800, 8, 0xc20, 0x7a41 } },
+ { "[ff01::8:800:200C:417A/16]:8080", STATUS_INVALID_PARAMETER, 0xbadf00d, 0xbeef,
+ { 0x1ff, 0, 0, 0, 0x800, 8, 0xc20, 0x7a41 } },
+ };
+ const unsigned int ipv6_ex_testcount = sizeof(ipv6_ex_tests) / sizeof(ipv6_ex_tests[0]);
+ const char *simple_ip = "::";
+ unsigned int i;
+
+ if (!pRtlIpv6StringToAddressExW)
+ {
+ skip("RtlIpv6StringToAddressExW not available\n");
+ /* we can continue, just not test W */
+ }
+
+ if (!pRtlIpv6StringToAddressExA)
+ {
+ skip("RtlIpv6StringToAddressExA not available\n");
+ return;
+ }
+
+ res = pRtlIpv6StringToAddressExA(simple_ip, &ip, &scope, &port);
+ ok(res == STATUS_SUCCESS, "[validate] res = 0x%08x, expected STATUS_SUCCESS\n", res);
+
+ init_ip6(&ip, NULL);
+ init_ip6(&expected_ip, NULL);
+ scope = 0xbadf00d;
+ port = 0xbeef;
+ res = pRtlIpv6StringToAddressExA(NULL, &ip, &scope, &port);
+ ok(res == STATUS_INVALID_PARAMETER,
+ "[null string] res = 0x%08x, expected STATUS_INVALID_PARAMETER\n", res);
+ ok(scope == 0xbadf00d, "[null string] scope = 0x%08x, expected 0xbadf00d\n", scope);
+ ok(port == 0xbeef, "[null string] port = 0x%08x, expected 0xbeef\n", port);
+ ok(!memcmp(&ip, &expected_ip, sizeof(ip)),
+ "[null string] ip is changed, expected it not to change\n");
+
+
+ init_ip6(&ip, NULL);
+ scope = 0xbadf00d;
+ port = 0xbeef;
+ res = pRtlIpv6StringToAddressExA(simple_ip, NULL, &scope, &port);
+ ok(res == STATUS_INVALID_PARAMETER,
+ "[null result] res = 0x%08x, expected STATUS_INVALID_PARAMETER\n", res);
+ ok(scope == 0xbadf00d, "[null result] scope = 0x%08x, expected 0xbadf00d\n", scope);
+ ok(port == 0xbeef, "[null result] port = 0x%08x, expected 0xbeef\n", port);
+ ok(!memcmp(&ip, &expected_ip, sizeof(ip)),
+ "[null result] ip is changed, expected it not to change\n");
+
+ init_ip6(&ip, NULL);
+ scope = 0xbadf00d;
+ port = 0xbeef;
+ res = pRtlIpv6StringToAddressExA(simple_ip, &ip, NULL, &port);
+ ok(res == STATUS_INVALID_PARAMETER,
+ "[null scope] res = 0x%08x, expected STATUS_INVALID_PARAMETER\n", res);
+ ok(scope == 0xbadf00d, "[null scope] scope = 0x%08x, expected 0xbadf00d\n", scope);
+ ok(port == 0xbeef, "[null scope] port = 0x%08x, expected 0xbeef\n", port);
+ ok(!memcmp(&ip, &expected_ip, sizeof(ip)),
+ "[null scope] ip is changed, expected it not to change\n");
+
+ init_ip6(&ip, NULL);
+ scope = 0xbadf00d;
+ port = 0xbeef;
+ res = pRtlIpv6StringToAddressExA(simple_ip, &ip, &scope, NULL);
+ ok(res == STATUS_INVALID_PARAMETER,
+ "[null port] res = 0x%08x, expected STATUS_INVALID_PARAMETER\n", res);
+ ok(scope == 0xbadf00d, "[null port] scope = 0x%08x, expected 0xbadf00d\n", scope);
+ ok(port == 0xbeef, "[null port] port = 0x%08x, expected 0xbeef\n", port);
+ ok(!memcmp(&ip, &expected_ip, sizeof(ip)),
+ "[null port] ip is changed, expected it not to change\n");
+
+ /* sanity check */
+ ok(sizeof(ip) == sizeof(USHORT)* 8, "sizeof(ip)\n");
+
+ /* first we run all ip related tests, to make sure someone didnt accidentally reimplement instead of re-use. */
+ for (i = 0; i < ipv6_testcount; i++)
+ {
+ ULONG scope = 0xbadf00d;
+ USHORT port = 0xbeef;
+ NTSTATUS expect_ret = (ipv6_tests[i].flags & ex_fail_6) ? STATUS_INVALID_PARAMETER : ipv6_tests[i].res;
+
+ if (ipv6_tests[i].flags & ex_skip_6)
+ continue;
+
+ init_ip6(&ip, NULL);
+ res = pRtlIpv6StringToAddressExA(ipv6_tests[i].address, &ip, &scope, &port);
+ compare_RtlIpv6StringToAddressExW(ipv6_tests[i].address, &ip, res, scope, port);
+
+ /* make sure nothing was changed if this function fails. */
+ if (res == STATUS_INVALID_PARAMETER)
+ {
+ ok(scope == 0xbadf00d, "[%s] scope = 0x%08x, expected 0xbadf00d\n",
+ ipv6_tests[i].address, scope);
+ ok(port == 0xbeef, "[%s] port = 0x%08x, expected 0xbeef\n",
+ ipv6_tests[i].address, port);
+ }
+ else
+ {
+ ok(scope != 0xbadf00d, "[%s] scope = 0x%08x, not expected 0xbadf00d\n",
+ ipv6_tests[i].address, scope);
+ ok(port != 0xbeef, "[%s] port = 0x%08x, not expected 0xbeef\n",
+ ipv6_tests[i].address, port);
+ }
+
+ if (ipv6_tests[i].flags & win_broken_6)
+ {
+ ok(res == expect_ret || broken(res == STATUS_INVALID_PARAMETER),
+ "[%s] res = 0x%08x, expected 0x%08x\n", ipv6_tests[i].address, res, expect_ret);
+
+ if (res == STATUS_INVALID_PARAMETER)
+ continue;
+ }
+ else
+ {
+ ok(res == expect_ret, "[%s] res = 0x%08x, expected 0x%08x\n",
+ ipv6_tests[i].address, res, expect_ret);
+ }
+
+ /* If ex fails but non-ex does not we cannot check if the part that is converted
+ before it failed was correct, since there is no data for it in the table. */
+ if (res == expect_ret)
+ {
+ init_ip6(&expected_ip, ipv6_tests[i].ip);
+ ok(!memcmp(&ip, &expected_ip, sizeof(ip)),
+ "[%s] ip = %x:%x:%x:%x:%x:%x:%x:%x, expected %x:%x:%x:%x:%x:%x:%x:%x\n",
+ ipv6_tests[i].address,
+ ip.s6_words[0], ip.s6_words[1], ip.s6_words[2], ip.s6_words[3],
+ ip.s6_words[4], ip.s6_words[5], ip.s6_words[6], ip.s6_words[7],
+ expected_ip.s6_words[0], expected_ip.s6_words[1], expected_ip.s6_words[2], expected_ip.s6_words[3],
+ expected_ip.s6_words[4], expected_ip.s6_words[5], expected_ip.s6_words[6], expected_ip.s6_words[7]);
+ }
+ }
+
+ /* now we run scope / port related tests */
+ for (i = 0; i < ipv6_ex_testcount; i++)
+ {
+ scope = 0xbadf00d;
+ port = 0xbeef;
+ init_ip6(&ip, NULL);
+ res = pRtlIpv6StringToAddressExA(ipv6_ex_tests[i].address, &ip, &scope, &port);
+ compare_RtlIpv6StringToAddressExW(ipv6_ex_tests[i].address, &ip, res, scope, port);
+
+ ok(res == ipv6_ex_tests[i].res, "[%s] res = 0x%08x, expected 0x%08x\n",
+ ipv6_ex_tests[i].address, res, ipv6_ex_tests[i].res);
+ ok(scope == ipv6_ex_tests[i].scope, "[%s] scope = 0x%08x, expected 0x%08x\n",
+ ipv6_ex_tests[i].address, scope, ipv6_ex_tests[i].scope);
+ ok(port == ipv6_ex_tests[i].port, "[%s] port = 0x%08x, expected 0x%08x\n",
+ ipv6_ex_tests[i].address, port, ipv6_ex_tests[i].port);
+
+ init_ip6(&expected_ip, ipv6_ex_tests[i].ip);
+ ok(!memcmp(&ip, &expected_ip, sizeof(ip)),
+ "[%s] ip = %x:%x:%x:%x:%x:%x:%x:%x, expected %x:%x:%x:%x:%x:%x:%x:%x\n",
+ ipv6_ex_tests[i].address,
+ ip.s6_words[0], ip.s6_words[1], ip.s6_words[2], ip.s6_words[3],
+ ip.s6_words[4], ip.s6_words[5], ip.s6_words[6], ip.s6_words[7],
+ expected_ip.s6_words[0], expected_ip.s6_words[1], expected_ip.s6_words[2], expected_ip.s6_words[3],
+ expected_ip.s6_words[4], expected_ip.s6_words[5], expected_ip.s6_words[6], expected_ip.s6_words[7]);
+ }
+}
+
static void test_LdrAddRefDll(void)
{
HMODULE mod, mod2;
@@ -2616,6 +2882,7 @@ START_TEST(rtl)
test_RtlIpv4AddressToStringEx();
test_RtlIpv4StringToAddress();
test_RtlIpv6StringToAddress();
+ test_RtlIpv6StringToAddressEx();
test_LdrAddRefDll();
test_LdrLockLoaderLock();
test_RtlCompressBuffer();
--
2.4.5

View File

@@ -1,364 +0,0 @@
From 9d8678d25267e66aff7134f064fddb4eac5c5641 Mon Sep 17 00:00:00 2001
From: Mark Jansen <learn0more+wine@gmail.com>
Date: Sun, 8 Mar 2015 18:24:48 +0100
Subject: [PATCH] ntdll/tests: Tests for RtlIpv4StringToAddressEx (try 5,
resend)
Changes from try4:
-Remove leftover comments
Changes from try3:
-Test the ip against the non-ex version as suggested by stefand
-Change strict_is_different to a flag
-Add ipv4 init function to avoid code duplication
---
dlls/ntdll/tests/rtl.c | 284 ++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 246 insertions(+), 38 deletions(-)
diff --git a/dlls/ntdll/tests/rtl.c b/dlls/ntdll/tests/rtl.c
index cf14e65..941a92c 100644
--- a/dlls/ntdll/tests/rtl.c
+++ b/dlls/ntdll/tests/rtl.c
@@ -92,6 +92,7 @@ static IMAGE_BASE_RELOCATION *(WINAPI *pLdrProcessRelocationBlock)(void*,UINT,US
static CHAR * (WINAPI *pRtlIpv4AddressToStringA)(const IN_ADDR *, LPSTR);
static NTSTATUS (WINAPI *pRtlIpv4AddressToStringExA)(const IN_ADDR *, USHORT, LPSTR, PULONG);
static NTSTATUS (WINAPI *pRtlIpv4StringToAddressA)(PCSTR, BOOLEAN, PCSTR *, IN_ADDR *);
+static NTSTATUS (WINAPI *pRtlIpv4StringToAddressExA)(PCSTR, BOOLEAN, IN_ADDR *, PUSHORT);
static NTSTATUS (WINAPI *pRtlIpv6StringToAddressA)(PCSTR, PCSTR *, struct in6_addr *);
static NTSTATUS (WINAPI *pRtlIpv6StringToAddressW)(PCWSTR, PCWSTR *, struct in6_addr *);
static NTSTATUS (WINAPI *pRtlIpv6StringToAddressExA)(PCSTR, struct in6_addr *, PULONG, PUSHORT);
@@ -159,6 +160,7 @@ static void InitFunctionPtrs(void)
pRtlIpv4AddressToStringA = (void *)GetProcAddress(hntdll, "RtlIpv4AddressToStringA");
pRtlIpv4AddressToStringExA = (void *)GetProcAddress(hntdll, "RtlIpv4AddressToStringExA");
pRtlIpv4StringToAddressA = (void *)GetProcAddress(hntdll, "RtlIpv4StringToAddressA");
+ pRtlIpv4StringToAddressExA = (void *)GetProcAddress(hntdll, "RtlIpv4StringToAddressExA");
pRtlIpv6StringToAddressA = (void *)GetProcAddress(hntdll, "RtlIpv6StringToAddressA");
pRtlIpv6StringToAddressW = (void *)GetProcAddress(hntdll, "RtlIpv6StringToAddressW");
pRtlIpv6StringToAddressExA = (void *)GetProcAddress(hntdll, "RtlIpv6StringToAddressExA");
@@ -1157,6 +1159,102 @@ static void test_RtlIpv4AddressToStringEx(void)
res, size, buffer);
}
+static struct
+{
+ PCSTR address;
+ NTSTATUS res;
+ int terminator_offset;
+ int ip[4];
+ enum { normal_4, strict_diff_4 = 1, ex_fail_4 = 2 } flags;
+ NTSTATUS res_strict;
+ int terminator_offset_strict;
+ int ip_strict[4];
+} ipv4_tests[] =
+{
+ { "", STATUS_INVALID_PARAMETER, 0, { -1 } },
+ { " ", STATUS_INVALID_PARAMETER, 0, { -1 } },
+ { "1.1.1.1", STATUS_SUCCESS, 7, { 1, 1, 1, 1 } },
+ { "0.0.0.0", STATUS_SUCCESS, 7, { 0, 0, 0, 0 } },
+ { "255.255.255.255", STATUS_SUCCESS, 15, { 255, 255, 255, 255 } },
+ { "255.255.255.255:123", STATUS_SUCCESS, 15, { 255, 255, 255, 255 } },
+ { "255.255.255.256", STATUS_INVALID_PARAMETER, 15, { -1 } },
+ { "255.255.255.4294967295", STATUS_INVALID_PARAMETER, 22, { -1 } },
+ { "255.255.255.4294967296", STATUS_INVALID_PARAMETER, 21, { -1 } },
+ { "255.255.255.4294967297", STATUS_INVALID_PARAMETER, 21, { -1 } },
+ { "a", STATUS_INVALID_PARAMETER, 0, { -1 } },
+ { "1.1.1.0xaA", STATUS_SUCCESS, 10, { 1, 1, 1, 170 }, strict_diff_4,
+ STATUS_INVALID_PARAMETER, 8, { -1 } },
+ { "1.1.1.0XaA", STATUS_SUCCESS, 10, { 1, 1, 1, 170 }, strict_diff_4,
+ STATUS_INVALID_PARAMETER, 8, { -1 } },
+ { "1.1.1.0x", STATUS_INVALID_PARAMETER, 8, { -1 } },
+ { "1.1.1.0xff", STATUS_SUCCESS, 10, { 1, 1, 1, 255 }, strict_diff_4,
+ STATUS_INVALID_PARAMETER, 8, { -1 } },
+ { "1.1.1.0x100", STATUS_INVALID_PARAMETER, 11, { -1 }, strict_diff_4,
+ STATUS_INVALID_PARAMETER, 8, { -1 } },
+ { "1.1.1.0xffffffff", STATUS_INVALID_PARAMETER, 16, { -1 }, strict_diff_4,
+ STATUS_INVALID_PARAMETER, 8, { -1 } },
+ { "1.1.1.0x100000000", STATUS_INVALID_PARAMETER, 16, { -1, 0, 0, 0 }, strict_diff_4,
+ STATUS_INVALID_PARAMETER, 8, { -1 } },
+ { "1.1.1.010", STATUS_SUCCESS, 9, { 1, 1, 1, 8 }, strict_diff_4,
+ STATUS_INVALID_PARAMETER, 7, { -1 } },
+ { "1.1.1.00", STATUS_SUCCESS, 8, { 1, 1, 1, 0 }, strict_diff_4,
+ STATUS_INVALID_PARAMETER, 7, { -1 } },
+ { "1.1.1.007", STATUS_SUCCESS, 9, { 1, 1, 1, 7 }, strict_diff_4,
+ STATUS_INVALID_PARAMETER, 7, { -1 } },
+ { "1.1.1.08", STATUS_INVALID_PARAMETER, 7, { -1 } },
+ { "1.1.1.008", STATUS_SUCCESS, 8, { 1, 1, 1, 0 }, strict_diff_4 | ex_fail_4,
+ STATUS_INVALID_PARAMETER, 7, { -1 } },
+ { "1.1.1.0a", STATUS_SUCCESS, 7, { 1, 1, 1, 0 }, ex_fail_4 },
+ { "1.1.1.0o10", STATUS_SUCCESS, 7, { 1, 1, 1, 0 }, ex_fail_4 },
+ { "1.1.1.0b10", STATUS_SUCCESS, 7, { 1, 1, 1, 0 }, ex_fail_4 },
+ { "1.1.1.-2", STATUS_INVALID_PARAMETER, 6, { -1 } },
+ { "1", STATUS_SUCCESS, 1, { 0, 0, 0, 1 }, strict_diff_4,
+ STATUS_INVALID_PARAMETER, 1, { -1 } },
+ { "-1", STATUS_INVALID_PARAMETER, 0, { -1 } },
+ { "203569230", STATUS_SUCCESS, 9, { 12, 34, 56, 78 }, strict_diff_4,
+ STATUS_INVALID_PARAMETER, 9, { -1 } },
+ { "1.223756", STATUS_SUCCESS, 8, { 1, 3, 106, 12 }, strict_diff_4,
+ STATUS_INVALID_PARAMETER, 8, { -1 } },
+ { "3.4.756", STATUS_SUCCESS, 7, { 3, 4, 2, 244 }, strict_diff_4,
+ STATUS_INVALID_PARAMETER, 7, { -1 } },
+ { "3.4.756.1", STATUS_INVALID_PARAMETER, 9, { -1 } },
+ { "3.4.65536", STATUS_INVALID_PARAMETER, 9, { -1 } },
+ { "3.4.5.6.7", STATUS_INVALID_PARAMETER, 7, { -1 } },
+ { "3.4.5.+6", STATUS_INVALID_PARAMETER, 6, { -1 } },
+ { " 3.4.5.6", STATUS_INVALID_PARAMETER, 0, { -1 } },
+ { "\t3.4.5.6", STATUS_INVALID_PARAMETER, 0, { -1 } },
+ { "3.4.5.6 ", STATUS_SUCCESS, 7, { 3, 4, 5, 6 }, ex_fail_4 },
+ { "3. 4.5.6", STATUS_INVALID_PARAMETER, 2, { -1 } },
+ { ".", STATUS_INVALID_PARAMETER, 1, { -1 } },
+ { "..", STATUS_INVALID_PARAMETER, 1, { -1 } },
+ { "1.", STATUS_INVALID_PARAMETER, 2, { -1 } },
+ { "1..", STATUS_INVALID_PARAMETER, 3, { -1 } },
+ { ".1", STATUS_INVALID_PARAMETER, 1, { -1 } },
+ { ".1.", STATUS_INVALID_PARAMETER, 1, { -1 } },
+ { ".1.2.3", STATUS_INVALID_PARAMETER, 1, { -1 } },
+ { "0.1.2.3", STATUS_SUCCESS, 7, { 0, 1, 2, 3 } },
+ { "0.1.2.3.", STATUS_INVALID_PARAMETER, 7, { -1 } },
+ { "[0.1.2.3]", STATUS_INVALID_PARAMETER, 0, { -1 } },
+ { "::1", STATUS_INVALID_PARAMETER, 0, { -1 } },
+ { ":1", STATUS_INVALID_PARAMETER, 0, { -1 } },
+};
+const unsigned int ipv4_testcount = sizeof(ipv4_tests) / sizeof(ipv4_tests[0]);
+
+static void init_ip4(IN_ADDR* addr, const int src[4])
+{
+ if (!src || src[0] == -1)
+ {
+ addr->S_un.S_addr = 0xabababab;
+ }
+ else
+ {
+ addr->S_un.S_un_b.s_b1 = src[0];
+ addr->S_un.S_un_b.s_b2 = src[1];
+ addr->S_un.S_un_b.s_b3 = src[2];
+ addr->S_un.S_un_b.s_b4 = src[3];
+ }
+}
+
static void test_RtlIpv4StringToAddress(void)
{
NTSTATUS res;
@@ -1270,65 +1368,174 @@ static void test_RtlIpv4StringToAddress(void)
*/
}
- for (i = 0; i < testcount; i++)
+ for (i = 0; i < ipv4_testcount; i++)
{
/* non-strict */
terminator = &dummy;
ip.S_un.S_addr = 0xabababab;
- res = pRtlIpv4StringToAddressA(tests[i].address, FALSE, &terminator, &ip);
- ok(res == tests[i].res,
+ res = pRtlIpv4StringToAddressA(ipv4_tests[i].address, FALSE, &terminator, &ip);
+ ok(res == ipv4_tests[i].res,
"[%s] res = 0x%08x, expected 0x%08x\n",
- tests[i].address, res, tests[i].res);
- ok(terminator == tests[i].address + tests[i].terminator_offset,
+ ipv4_tests[i].address, res, ipv4_tests[i].res);
+ ok(terminator == ipv4_tests[i].address + ipv4_tests[i].terminator_offset,
"[%s] terminator = %p, expected %p\n",
- tests[i].address, terminator, tests[i].address + tests[i].terminator_offset);
- if (tests[i].ip[0] == -1)
- expected_ip.S_un.S_addr = 0xabababab;
- else
- {
- expected_ip.S_un.S_un_b.s_b1 = tests[i].ip[0];
- expected_ip.S_un.S_un_b.s_b2 = tests[i].ip[1];
- expected_ip.S_un.S_un_b.s_b3 = tests[i].ip[2];
- expected_ip.S_un.S_un_b.s_b4 = tests[i].ip[3];
- }
+ ipv4_tests[i].address, terminator, ipv4_tests[i].address + ipv4_tests[i].terminator_offset);
+
+ init_ip4(&expected_ip, ipv4_tests[i].ip);
ok(ip.S_un.S_addr == expected_ip.S_un.S_addr,
"[%s] ip = %08x, expected %08x\n",
- tests[i].address, ip.S_un.S_addr, expected_ip.S_un.S_addr);
+ ipv4_tests[i].address, ip.S_un.S_addr, expected_ip.S_un.S_addr);
- if (!tests[i].strict_is_different)
+ if (!(ipv4_tests[i].flags & strict_diff_4))
{
- tests[i].res_strict = tests[i].res;
- tests[i].terminator_offset_strict = tests[i].terminator_offset;
- tests[i].ip_strict[0] = tests[i].ip[0];
- tests[i].ip_strict[1] = tests[i].ip[1];
- tests[i].ip_strict[2] = tests[i].ip[2];
- tests[i].ip_strict[3] = tests[i].ip[3];
+ ipv4_tests[i].res_strict = ipv4_tests[i].res;
+ ipv4_tests[i].terminator_offset_strict = ipv4_tests[i].terminator_offset;
+ ipv4_tests[i].ip_strict[0] = ipv4_tests[i].ip[0];
+ ipv4_tests[i].ip_strict[1] = ipv4_tests[i].ip[1];
+ ipv4_tests[i].ip_strict[2] = ipv4_tests[i].ip[2];
+ ipv4_tests[i].ip_strict[3] = ipv4_tests[i].ip[3];
}
/* strict */
terminator = &dummy;
ip.S_un.S_addr = 0xabababab;
- res = pRtlIpv4StringToAddressA(tests[i].address, TRUE, &terminator, &ip);
- ok(res == tests[i].res_strict,
+ res = pRtlIpv4StringToAddressA(ipv4_tests[i].address, TRUE, &terminator, &ip);
+ ok(res == ipv4_tests[i].res_strict,
"[%s] res = 0x%08x, expected 0x%08x\n",
- tests[i].address, res, tests[i].res_strict);
- ok(terminator == tests[i].address + tests[i].terminator_offset_strict,
+ ipv4_tests[i].address, res, ipv4_tests[i].res_strict);
+ ok(terminator == ipv4_tests[i].address + ipv4_tests[i].terminator_offset_strict,
"[%s] terminator = %p, expected %p\n",
- tests[i].address, terminator, tests[i].address + tests[i].terminator_offset_strict);
- if (tests[i].ip_strict[0] == -1)
- expected_ip.S_un.S_addr = 0xabababab;
- else
- {
- expected_ip.S_un.S_un_b.s_b1 = tests[i].ip_strict[0];
- expected_ip.S_un.S_un_b.s_b2 = tests[i].ip_strict[1];
- expected_ip.S_un.S_un_b.s_b3 = tests[i].ip_strict[2];
- expected_ip.S_un.S_un_b.s_b4 = tests[i].ip_strict[3];
- }
+ ipv4_tests[i].address, terminator, ipv4_tests[i].address + ipv4_tests[i].terminator_offset_strict);
+
+ init_ip4(&expected_ip, ipv4_tests[i].ip_strict);
ok(ip.S_un.S_addr == expected_ip.S_un.S_addr,
"[%s] ip = %08x, expected %08x\n",
- tests[i].address, ip.S_un.S_addr, expected_ip.S_un.S_addr);
+ ipv4_tests[i].address, ip.S_un.S_addr, expected_ip.S_un.S_addr);
}
}
+static void test_RtlIpv4StringToAddressEx(void)
+{
+ NTSTATUS res;
+ IN_ADDR ip, expected_ip;
+ USHORT port;
+ static const struct
+ {
+ PCSTR address;
+ NTSTATUS res;
+ int ip[4];
+ USHORT port;
+ } ipv4_ex_tests[] =
+ {
+ { "", STATUS_INVALID_PARAMETER, { -1 }, 0xdead },
+ { " ", STATUS_INVALID_PARAMETER, { -1 }, 0xdead },
+ { "1.1.1.1:", STATUS_INVALID_PARAMETER, { 1, 1, 1, 1 }, 0xdead },
+ { "1.1.1.1+", STATUS_INVALID_PARAMETER, { 1, 1, 1, 1 }, 0xdead },
+ { "1.1.1.1:1", STATUS_SUCCESS, { 1, 1, 1, 1 }, 0x100 },
+ { "256.1.1.1:1", STATUS_INVALID_PARAMETER, { -1 }, 0xdead },
+ { "-1.1.1.1:1", STATUS_INVALID_PARAMETER, { -1 }, 0xdead },
+ { "0.0.0.0:0", STATUS_INVALID_PARAMETER, { 0, 0, 0, 0 }, 0xdead },
+ { "0.0.0.0:1", STATUS_SUCCESS, { 0, 0, 0, 0 }, 0x100 },
+ { "1.2.3.4:65535", STATUS_SUCCESS, { 1, 2, 3, 4 }, 65535 },
+ { "1.2.3.4:65536", STATUS_INVALID_PARAMETER, { 1, 2, 3, 4 }, 0xdead },
+ { "1.2.3.4:0xffff", STATUS_SUCCESS, { 1, 2, 3, 4 }, 65535 },
+ { "1.2.3.4:0XfFfF", STATUS_SUCCESS, { 1, 2, 3, 4 }, 65535 },
+ { "1.2.3.4:011064", STATUS_SUCCESS, { 1, 2, 3, 4 }, 0x3412 },
+ { "1.2.3.4:1234a", STATUS_INVALID_PARAMETER, { 1, 2, 3, 4 }, 0xdead },
+ { "1.2.3.4:1234+", STATUS_INVALID_PARAMETER, { 1, 2, 3, 4 }, 0xdead },
+ { "1.2.3.4: 1234", STATUS_INVALID_PARAMETER, { 1, 2, 3, 4 }, 0xdead },
+ { "1.2.3.4:\t1234", STATUS_INVALID_PARAMETER, { 1, 2, 3, 4 }, 0xdead },
+ };
+ const unsigned int ipv4_ex_testcount = sizeof(ipv4_ex_tests) / sizeof(ipv4_ex_tests[0]);
+ unsigned int i;
+ BOOLEAN strict;
+
+ if (!pRtlIpv4StringToAddressExA)
+ {
+ skip("RtlIpv4StringToAddressEx not available\n");
+ return;
+ }
+
+ /* do not crash, and do not touch the ip / port. */
+ ip.S_un.S_addr = 0xabababab;
+ port = 0xdead;
+ res = pRtlIpv4StringToAddressExA(NULL, FALSE, &ip, &port);
+ ok(res == STATUS_INVALID_PARAMETER, "[null address] res = 0x%08x, expected 0x%08x\n",
+ res, STATUS_INVALID_PARAMETER);
+ ok(ip.S_un.S_addr == 0xabababab, "RtlIpv4StringToAddressExA should not touch the ip!, ip == %x\n", ip.S_un.S_addr);
+ ok(port == 0xdead, "RtlIpv4StringToAddressExA should not touch the port!, port == %x\n", port);
+
+ port = 0xdead;
+ res = pRtlIpv4StringToAddressExA("1.1.1.1", FALSE, NULL, &port);
+ ok(res == STATUS_INVALID_PARAMETER, "[null ip] res = 0x%08x, expected 0x%08x\n",
+ res, STATUS_INVALID_PARAMETER);
+ ok(port == 0xdead, "RtlIpv4StringToAddressExA should not touch the port!, port == %x\n", port);
+
+ ip.S_un.S_addr = 0xabababab;
+ port = 0xdead;
+ res = pRtlIpv4StringToAddressExA("1.1.1.1", FALSE, &ip, NULL);
+ ok(res == STATUS_INVALID_PARAMETER, "[null port] res = 0x%08x, expected 0x%08x\n",
+ res, STATUS_INVALID_PARAMETER);
+ ok(ip.S_un.S_addr == 0xabababab, "RtlIpv4StringToAddressExA should not touch the ip!, ip == %x\n", ip.S_un.S_addr);
+ ok(port == 0xdead, "RtlIpv4StringToAddressExA should not touch the port!, port == %x\n", port);
+
+ /* first we run the non-ex testcases on the ex function */
+ for (i = 0; i < ipv4_testcount; i++)
+ {
+ NTSTATUS expect_res = (ipv4_tests[i].flags & ex_fail_4) ? STATUS_INVALID_PARAMETER : ipv4_tests[i].res;
+
+ /* non-strict */
+ port = 0xdead;
+ ip.S_un.S_addr = 0xabababab;
+ res = pRtlIpv4StringToAddressExA(ipv4_tests[i].address, FALSE, &ip, &port);
+ ok(res == expect_res, "[%s] res = 0x%08x, expected 0x%08x\n",
+ ipv4_tests[i].address, res, expect_res);
+
+ init_ip4(&expected_ip, ipv4_tests[i].ip);
+ ok(ip.S_un.S_addr == expected_ip.S_un.S_addr, "[%s] ip = %08x, expected %08x\n",
+ ipv4_tests[i].address, ip.S_un.S_addr, expected_ip.S_un.S_addr);
+
+ if (!(ipv4_tests[i].flags & strict_diff_4))
+ {
+ ipv4_tests[i].res_strict = ipv4_tests[i].res;
+ ipv4_tests[i].terminator_offset_strict = ipv4_tests[i].terminator_offset;
+ ipv4_tests[i].ip_strict[0] = ipv4_tests[i].ip[0];
+ ipv4_tests[i].ip_strict[1] = ipv4_tests[i].ip[1];
+ ipv4_tests[i].ip_strict[2] = ipv4_tests[i].ip[2];
+ ipv4_tests[i].ip_strict[3] = ipv4_tests[i].ip[3];
+ }
+ /* strict */
+ expect_res = (ipv4_tests[i].flags & ex_fail_4) ? STATUS_INVALID_PARAMETER : ipv4_tests[i].res_strict;
+ port = 0xdead;
+ ip.S_un.S_addr = 0xabababab;
+ res = pRtlIpv4StringToAddressExA(ipv4_tests[i].address, TRUE, &ip, &port);
+ ok(res == expect_res, "[%s] res = 0x%08x, expected 0x%08x\n",
+ ipv4_tests[i].address, res, expect_res);
+
+ init_ip4(&expected_ip, ipv4_tests[i].ip_strict);
+ ok(ip.S_un.S_addr == expected_ip.S_un.S_addr, "[%s] ip = %08x, expected %08x\n",
+ ipv4_tests[i].address, ip.S_un.S_addr, expected_ip.S_un.S_addr);
+ }
+
+
+ for (i = 0; i < ipv4_ex_testcount; i++)
+ {
+ /* Strict is only relevant for the ip address, so make sure that it does not influence the port */
+ for (strict = 0; strict < 2; strict++)
+ {
+ ip.S_un.S_addr = 0xabababab;
+ port = 0xdead;
+ res = pRtlIpv4StringToAddressExA(ipv4_ex_tests[i].address, strict, &ip, &port);
+ ok(res == ipv4_ex_tests[i].res, "[%s] res = 0x%08x, expected 0x%08x\n",
+ ipv4_ex_tests[i].address, res, ipv4_ex_tests[i].res);
+
+ init_ip4(&expected_ip, ipv4_ex_tests[i].ip);
+ ok(ip.S_un.S_addr == expected_ip.S_un.S_addr, "[%s] ip = %08x, expected %08x\n",
+ ipv4_ex_tests[i].address, ip.S_un.S_addr, expected_ip.S_un.S_addr);
+ ok(port == ipv4_ex_tests[i].port, "[%s] port = %u, expected %u\n",
+ ipv4_ex_tests[i].address, port, ipv4_ex_tests[i].port);
+ }
+ }
+}
/* ipv6 addresses based on the set from https://github.com/beaugunderson/javascript-ipv6/tree/master/test/data */
static const struct
@@ -3300,6 +3507,7 @@ START_TEST(rtl)
test_RtlIpv4AddressToString();
test_RtlIpv4AddressToStringEx();
test_RtlIpv4StringToAddress();
+ test_RtlIpv4StringToAddressEx();
test_RtlIpv6StringToAddress();
test_RtlIpv6StringToAddressEx();
test_LdrAddRefDll();
--
1.9.1

Some files were not shown because too many files have changed in this diff Show More