Compare commits

...

22 Commits
v4.1 ... v4.2

Author SHA1 Message Date
Alistair Leslie-Hughes
b1b1abafe7 Release v4.2 2019-02-17 15:44:00 +11:00
Zebediah Figura
0b57832a15 ddraw-version-check: Correct author. 2019-02-16 13:39:46 -06:00
Zebediah Figura
b080509a3b actually add the patches 2019-02-16 08:36:04 -06:00
Zebediah Figura
4d363d04f9 Add ddraw-version-check and gdi32-rotation. 2019-02-15 19:34:50 -06:00
Alistair Leslie-Hughes
7cbbfd0a9e Rebase against 3fc1180623b9a0c9fc9e16abf358b179f2eff49b 2019-02-15 11:18:02 +11:00
Alistair Leslie-Hughes
27ff0169ed Updated uxtheme-GTK_Theming patch 2019-02-15 08:39:48 +11:00
Alistair Leslie-Hughes
32bac8b64c Rebase against 7907ccfdcb39b30dc49c96c411332534525b6ea9 2019-02-14 11:08:02 +11:00
Alistair Leslie-Hughes
b8de62375f Rebase against 9781b5433cd4b708c0f537aa0b5608ff4157f04c 2019-02-13 11:01:29 +11:00
Alistair Leslie-Hughes
697fe8b5da Rebase against d0727decdedb5aba250038458e0a28dec5687e50 2019-02-12 10:01:26 +11:00
Zebediah Figura
c6aeba1397 ntdll-DllRedirects: Remove patch set.
This patch has caused a disproportionate amount of annoyance during
rebases, and this is only likely to increase. On top of this it is not
an especially good way to structure things; switching between
interfaces is something best done within one DLL.
2019-02-09 17:15:09 -06:00
Zebediah Figura
3d74da6622 uxtheme-GTK_Theming: Rework to avoid "DLL redirects".
Instead we have an alternate code path for the appropriate API entry
points in uxtheme.dll.

This is not the best organizational structure. We should probably have
HTHEME handles resolve to an object with its own function table, so
then we have an MSSTYLES backend and a GTK backend and what have
you. It would also be better to avoid having GTK controlled with its
own registry key like this but rather to have it be selectable using
EnumThemes()/ApplyTheme() [presumably through a fake theme file, as
was used in the original implementation], so that we don't have to
have special handling for those functions and everything can just be
part of the HTHEME backend. However, time is currently of the essence,
and this will have to do for the moment.
2019-02-09 17:15:09 -06:00
Zebediah Figura
ecc4fe6d6a Rebase against f7b3120991df02ecaa975c18c6421fedb48ae731. 2019-02-08 21:57:06 -06:00
Zebediah Figura
35f9449641 ntdll-Purist_Mode: Remove patch set.
This is redundant and not especially useful.
2019-02-08 21:37:09 -06:00
Zebediah Figura
f605d79997 ntdll-DllOverrides_WOW64: Remove patchset.
This was always a no-op; HKCU/Software does not reflect.
2019-02-08 21:35:26 -06:00
Alistair Leslie-Hughes
ab89820aa5 Added secur32-compile-fix 2019-02-08 11:08:27 +11:00
Alistair Leslie-Hughes
f85accadd5 Rebase against 957a1f0216995c14c3a3fe737358578a506af707 2019-02-08 10:49:30 +11:00
Alistair Leslie-Hughes
533cbe994f Updated bcrypt-BCryptGenerateKeyPair patchset
Fixes FreeBSD build and --without-gnutls option.
2019-02-08 08:31:23 +11:00
Alistair Leslie-Hughes
9f5a34bcb8 Updated uxtheme-GTK_Theming patchset
Fixes
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46587
2019-02-07 14:45:37 +11:00
Zebediah Figura
ca3bfa28f9 Rebase against c3ac646a8ded3ef3ebc743a7fdda01b0691a427a. 2019-02-06 19:44:16 -06:00
Alistair Leslie-Hughes
3dab9e5e6b Rebase against 6b76648a8b773838ecde00719ca54a433edf5ce6 2019-02-06 14:27:30 +11:00
Alistair Leslie-Hughes
1edb7d5bc5 Updated bcrypt-BCryptGenerateKeyPair patchset
Fix for Debian 8.0 and xUbuntu_16.04.
2019-02-06 07:16:21 +11:00
Alistair Leslie-Hughes
0f48c0caac Updated bcrypt-BCryptGenerateKeyPair patchset
This is to fix the macos build.
2019-02-05 13:46:27 +11:00
95 changed files with 3022 additions and 13911 deletions

View File

@@ -1,8 +1,8 @@
From 42dbdf9479e2e09734fa183b854d5ddfe987f203 Mon Sep 17 00:00:00 2001
From 494fc3abe1eddabcf7cede677ee907284e89eea8 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Tue, 22 Mar 2016 23:08:30 +0100
Subject: [PATCH] include: Check element type in CONTAINING_RECORD and
similar macros.
Subject: [PATCH] include: Check element type in CONTAINING_RECORD and similar
macros.
---
include/wine/list.h | 10 ++++++++--
@@ -11,7 +11,7 @@ Subject: [PATCH] include: Check element type in CONTAINING_RECORD and
3 files changed, 24 insertions(+), 6 deletions(-)
diff --git a/include/wine/list.h b/include/wine/list.h
index b4d681f..287ad39 100644
index b4d681fe..287ad394 100644
--- a/include/wine/list.h
+++ b/include/wine/list.h
@@ -228,7 +228,13 @@ static inline void list_move_head( struct list *dst, struct list *src )
@@ -31,7 +31,7 @@ index b4d681f..287ad39 100644
#endif /* __WINE_SERVER_LIST_H */
diff --git a/include/wine/rbtree.h b/include/wine/rbtree.h
index dc50b5e..8130deb 100644
index dc50b5e7..8130deb5 100644
--- a/include/wine/rbtree.h
+++ b/include/wine/rbtree.h
@@ -23,8 +23,14 @@
@@ -52,12 +52,12 @@ index dc50b5e..8130deb 100644
struct wine_rb_entry
{
diff --git a/include/winnt.h b/include/winnt.h
index 7f822c4..ccfe73b 100644
index 2b489382..a156efc4 100644
--- a/include/winnt.h
+++ b/include/winnt.h
@@ -756,8 +756,14 @@ typedef struct _MEMORY_BASIC_INFORMATION
#define FIELD_OFFSET(type, field) ((LONG)offsetof(type, field))
@@ -760,8 +760,14 @@ typedef struct _MEMORY_BASIC_INFORMATION
#define RTL_FIELD_SIZE(type, field) (sizeof(((type *)0)->field))
#define RTL_SIZEOF_THROUGH_FIELD(type, field) (FIELD_OFFSET(type, field) + RTL_FIELD_SIZE(type, field))
-#define CONTAINING_RECORD(address, type, field) \
- ((type *)((PCHAR)(address) - offsetof(type, field)))
@@ -73,5 +73,5 @@ index 7f822c4..ccfe73b 100644
#ifdef __WINESRC__
# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
--
1.9.1
2.20.1

View File

@@ -1,4 +1,4 @@
From d67d7293a17592b580d284fa68881a613e61f591 Mon Sep 17 00:00:00 2001
From f94296129eb249a04ccb012a10f50b79fb0a631a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Sat, 5 Aug 2017 01:45:29 +0200
Subject: [PATCH] ntdll: Add function to create new tokens for elevation
@@ -14,10 +14,10 @@ Subject: [PATCH] ntdll: Add function to create new tokens for elevation
6 files changed, 117 insertions(+)
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index dbead5e..586b504 100644
index 969cee7..008abb7 100644
--- a/dlls/ntdll/ntdll.spec
+++ b/dlls/ntdll/ntdll.spec
@@ -1482,6 +1482,9 @@
@@ -1508,6 +1508,9 @@
# Virtual memory
@ cdecl __wine_locked_recvmsg(long ptr long)
@@ -28,12 +28,12 @@ index dbead5e..586b504 100644
@ cdecl wine_get_version() NTDLL_wine_get_version
@ cdecl wine_get_patches() NTDLL_wine_get_patches
diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h
index 8a64338..137a22d 100644
index 5a93ede..cb02bd1 100644
--- a/dlls/ntdll/ntdll_misc.h
+++ b/dlls/ntdll/ntdll_misc.h
@@ -80,6 +80,9 @@ extern void virtual_init_threading(void) DECLSPEC_HIDDEN;
extern void fill_cpu_info(void) DECLSPEC_HIDDEN;
extern void heap_set_debug_flags( HANDLE handle ) DECLSPEC_HIDDEN;
@@ -83,6 +83,9 @@ extern void heap_set_debug_flags( HANDLE handle ) DECLSPEC_HIDDEN;
extern void init_user_process_params( SIZE_T data_size ) DECLSPEC_HIDDEN;
extern void update_user_process_params( const UNICODE_STRING *image ) DECLSPEC_HIDDEN;
+/* token */
+extern HANDLE CDECL __wine_create_default_token(BOOL admin);
@@ -42,10 +42,10 @@ index 8a64338..137a22d 100644
extern timeout_t server_start_time DECLSPEC_HIDDEN;
extern unsigned int server_cpus DECLSPEC_HIDDEN;
diff --git a/dlls/ntdll/process.c b/dlls/ntdll/process.c
index 40034b4..1ebbb79 100644
index 2ff8610..bb4a171 100644
--- a/dlls/ntdll/process.c
+++ b/dlls/ntdll/process.c
@@ -99,6 +99,24 @@ HANDLE CDECL __wine_make_process_system(void)
@@ -118,6 +118,24 @@ HANDLE CDECL __wine_make_process_system(void)
return ret;
}
@@ -71,10 +71,10 @@ index 40034b4..1ebbb79 100644
#define UNIMPLEMENTED_INFO_CLASS(c) \
diff --git a/server/protocol.def b/server/protocol.def
index 0bb04cd..f2deca6 100644
index 493100b..071f740 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -3641,6 +3641,14 @@ struct handle_info
@@ -3666,6 +3666,14 @@ struct handle_info
@END
@@ -102,7 +102,7 @@ index 6c33714..21e90cc 100644
/* token functions */
diff --git a/server/token.c b/server/token.c
index 7776cbe..64ab565 100644
index 4c37c67..e449e61 100644
--- a/server/token.c
+++ b/server/token.c
@@ -79,6 +79,7 @@ static const SID anonymous_logon_sid = { SID_REVISION, 1, { SECURITY_NT_AUTHORIT
@@ -121,7 +121,7 @@ index 7776cbe..64ab565 100644
static luid_t prev_luid_value = { 1000, 0 };
@@ -901,6 +903,64 @@ struct token *token_create_admin( void )
@@ -908,6 +910,64 @@ struct token *token_create_admin( void )
return token;
}
@@ -186,7 +186,7 @@ index 7776cbe..64ab565 100644
static struct privilege *token_find_privilege( struct token *token, const LUID *luid, int enabled_only )
{
struct privilege *privilege;
@@ -1718,3 +1778,27 @@ DECL_HANDLER(set_token_default_dacl)
@@ -1713,3 +1773,27 @@ DECL_HANDLER(set_token_default_dacl)
release_object( token );
}
}

View File

@@ -1,25 +1,24 @@
From 3ff546b9cbde1d0f5ea43c5cbb92ac8dc2028676 Mon Sep 17 00:00:00 2001
From dd6544561d6432555f14a9004e107e6b87564949 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Sat, 5 Aug 2017 03:39:55 +0200
Subject: [PATCH] ntdll: Implement process token elevation through manifests.
---
dlls/ntdll/loader.c | 37 +++++++++++++++++++++++++++++++++++++
dlls/ntdll/loader.c | 40 ++++++++++++++++++++++++++++++++++++++--
server/process.c | 8 ++++++++
server/process.h | 1 +
server/protocol.def | 7 +++++++
server/token.c | 14 ++++++++++++++
5 files changed, 67 insertions(+)
5 files changed, 68 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
index 3fcbbf77a5..2399f1246e 100644
index d7dbe57..7588d5a 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -3054,6 +3054,32 @@ NTSTATUS attach_dlls( CONTEXT *context )
}
@@ -3321,6 +3321,32 @@ void WINAPI LdrInitializeThunk( CONTEXT *context, void **entry, ULONG_PTR unknow
+/***********************************************************************
/***********************************************************************
+ * elevate_process
+ */
+static void elevate_process( void )
@@ -45,19 +44,37 @@ index 3fcbbf77a5..2399f1246e 100644
+}
+
+
/***********************************************************************
+/***********************************************************************
* load_global_options
*/
@@ -3115,6 +3141,7 @@ void WINAPI LdrInitializeThunk( void *kernel_start, ULONG_PTR unknown2,
ULONG_PTR unknown3, ULONG_PTR unknown4 )
static void load_global_options(void)
@@ -3373,6 +3399,7 @@ static void load_global_options(void)
}
+
/***********************************************************************
* RtlImageDirectoryEntryToData (NTDLL.@)
*/
@@ -3408,7 +3435,6 @@ PVOID WINAPI RtlImageDirectoryEntryToData( HMODULE module, BOOL image, WORD dir,
return RtlImageRvaToVa( nt, module, addr, NULL );
}
-
/***********************************************************************
* RtlImageRvaToSection (NTDLL.@)
*/
@@ -3505,7 +3531,7 @@ void __wine_process_init(void)
{
static const WCHAR kernel32W[] = {'k','e','r','n','e','l','3','2','.','d','l','l',0};
static const WCHAR globalflagW[] = {'G','l','o','b','a','l','F','l','a','g',0};
-
+ ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION runlevel;
NTSTATUS status;
WINE_MODREF *wm;
PEB *peb = NtCurrentTeb()->Peb;
@@ -3142,6 +3169,16 @@ void WINAPI LdrInitializeThunk( void *kernel_start, ULONG_PTR unknown2,
REG_DWORD, &peb->NtGlobalFlag, sizeof(peb->NtGlobalFlag), NULL );
NTSTATUS status;
ANSI_STRING func_name;
@@ -3556,6 +3582,16 @@ void __wine_process_init(void)
&NtCurrentTeb()->Peb->NtGlobalFlag, sizeof(DWORD), NULL );
heap_set_debug_flags( GetProcessHeap() );
+ /* elevate process if necessary */
@@ -72,12 +89,12 @@ index 3fcbbf77a5..2399f1246e 100644
+
/* the main exe needs to be the first in the load order list */
RemoveEntryList( &wm->ldr.InLoadOrderModuleList );
InsertHeadList( &peb->LdrData->InLoadOrderModuleList, &wm->ldr.InLoadOrderModuleList );
InsertHeadList( &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList, &wm->ldr.InLoadOrderModuleList );
diff --git a/server/process.c b/server/process.c
index ee85249bd4..81cea2f1ba 100644
index 0a25f44..3988b52 100644
--- a/server/process.c
+++ b/server/process.c
@@ -1133,6 +1133,14 @@ struct process_snapshot *process_snap( int *count )
@@ -1109,6 +1109,14 @@ struct process_snapshot *process_snap( int *count )
return snapshot;
}
@@ -93,10 +110,10 @@ index ee85249bd4..81cea2f1ba 100644
DECL_HANDLER(new_process)
{
diff --git a/server/process.h b/server/process.h
index f22c128f07..78e88ec350 100644
index 4566a04..029b328 100644
--- a/server/process.h
+++ b/server/process.h
@@ -136,6 +136,7 @@ extern void break_process( struct process *process );
@@ -138,6 +138,7 @@ extern void break_process( struct process *process );
extern void detach_debugged_processes( struct thread *debugger );
extern struct process_snapshot *process_snap( int *count );
extern void enum_processes( int (*cb)(struct process*, void*), void *user);
@@ -105,10 +122,10 @@ index f22c128f07..78e88ec350 100644
/* console functions */
extern void inherit_console(struct thread *parent_thread, struct process *process, obj_handle_t hconin);
diff --git a/server/protocol.def b/server/protocol.def
index 0abd1683f0..5fb6e38ea5 100644
index 071f740..cc44503 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -3654,6 +3654,13 @@ struct handle_info
@@ -3674,6 +3674,13 @@ struct handle_info
@END
@@ -123,10 +140,10 @@ index 0abd1683f0..5fb6e38ea5 100644
@REQ(create_completion)
unsigned int access; /* desired access to a port */
diff --git a/server/token.c b/server/token.c
index 64ab565a95..52fa10d52e 100644
index e449e61..961fbe7 100644
--- a/server/token.c
+++ b/server/token.c
@@ -1802,3 +1802,17 @@ DECL_HANDLER(create_token)
@@ -1797,3 +1797,17 @@ DECL_HANDLER(create_token)
release_object( token );
}
}
@@ -145,5 +162,5 @@ index 64ab565a95..52fa10d52e 100644
+ }
+}
--
2.16.1
1.9.1

View File

@@ -1,4 +1,4 @@
From ab6be2f28c6a3501a056e890a41b44d49c1e2eb0 Mon Sep 17 00:00:00 2001
From 9a67b4c62e5a575a38081114d4434f274355020e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Tue, 12 Apr 2016 01:02:34 +0200
Subject: [PATCH] uiautomationcore: Add dll and stub some functions.
@@ -9,17 +9,18 @@ Subject: [PATCH] uiautomationcore: Add dll and stub some functions.
2 files changed, 48 insertions(+), 6 deletions(-)
diff --git a/dlls/uiautomationcore/Makefile.in b/dlls/uiautomationcore/Makefile.in
index 78d6254..029fc2e 100644
index 5221450..5173f23 100644
--- a/dlls/uiautomationcore/Makefile.in
+++ b/dlls/uiautomationcore/Makefile.in
@@ -1,4 +1,5 @@
@@ -1,5 +1,6 @@
MODULE = uiautomationcore.dll
IMPORTLIB = uiautomationcore
+IMPORTS = uuid
C_SRCS = \
uia_main.c
diff --git a/dlls/uiautomationcore/uia_main.c b/dlls/uiautomationcore/uia_main.c
index 31b7d3e..cc4831e 100644
index f0d8247..b9c24b4 100644
--- a/dlls/uiautomationcore/uia_main.c
+++ b/dlls/uiautomationcore/uia_main.c
@@ -1,4 +1,5 @@

View File

@@ -1,351 +0,0 @@
From ff1967f048d2b32ad98e91b4f39edba0c425a8a9 Mon Sep 17 00:00:00 2001
From: Jack Grigg <me@jackgrigg.com>
Date: Sat, 17 Mar 2018 21:14:05 +1100
Subject: [PATCH] bcrypt: Implement BCryptDeriveKeyPBKDF2 and add test vectors.
Fixes https://bugs.winehq.org/show_bug.cgi?id=42704
Tested on Ubuntu 16.04.2 LTS.
v2 - Removed C++ comment
- Removed all warnings.
- Use heap_* functions
- Formatting changes.
Signed-off-by: Jack Grigg <me@jackgrigg.com>
---
dlls/bcrypt/bcrypt.spec | 1 +
dlls/bcrypt/bcrypt_main.c | 163 +++++++++++++++++++++++++++++++++++++++++++++
dlls/bcrypt/tests/bcrypt.c | 83 +++++++++++++++++++++++
dlls/ncrypt/ncrypt.spec | 2 +-
include/bcrypt.h | 1 +
5 files changed, 249 insertions(+), 1 deletion(-)
diff --git a/dlls/bcrypt/bcrypt.spec b/dlls/bcrypt/bcrypt.spec
index 78824d7..f4d9a57 100644
--- a/dlls/bcrypt/bcrypt.spec
+++ b/dlls/bcrypt/bcrypt.spec
@@ -8,6 +8,7 @@
@ stdcall BCryptDecrypt(ptr ptr long ptr ptr long ptr long ptr long)
@ stub BCryptDeleteContext
@ stub BCryptDeriveKey
+@ stdcall BCryptDeriveKeyPBKDF2(ptr ptr long ptr long int64 ptr long long)
@ stdcall BCryptDestroyHash(ptr)
@ stdcall BCryptDestroyKey(ptr)
@ stub BCryptDestroySecret
diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c
index 2b9ae0b..49ccb13 100644
--- a/dlls/bcrypt/bcrypt_main.c
+++ b/dlls/bcrypt/bcrypt_main.c
@@ -1316,6 +1316,169 @@ NTSTATUS WINAPI BCryptSetProperty( BCRYPT_HANDLE handle, const WCHAR *prop, UCHA
}
}
+NTSTATUS PBKDF2_F( BCRYPT_ALG_HANDLE algorithm,
+ UCHAR *password, ULONG password_length,
+ UCHAR *salt, ULONG salt_length,
+ ULONGLONG iterations, int i,
+ UCHAR *res, int hash_length )
+{
+ BCRYPT_HASH_HANDLE handle;
+ NTSTATUS status = STATUS_NOT_SUPPORTED;
+ UCHAR bytes[4];
+ UCHAR *tmp;
+ int j;
+ int k;
+
+ if (!(tmp = heap_alloc( hash_length )))
+ {
+ return STATUS_NO_MEMORY;
+ }
+
+ for (j = 0; j < iterations; j++)
+ {
+ status = BCryptCreateHash( algorithm, &handle, NULL, 0,
+ password, password_length, 0 );
+ if (status != STATUS_SUCCESS)
+ goto done;
+
+ if (j == 0)
+ {
+ /* Use salt || INT(i) */
+ status = BCryptHashData( handle, salt, salt_length, 0 );
+ if (status != STATUS_SUCCESS)
+ goto done;
+ bytes[0] = (i >> 24) & 0xFF;
+ bytes[1] = (i >> 16) & 0xFF;
+ bytes[2] = (i >> 8) & 0xFF;
+ bytes[3] = i & 0xFF;
+ status = BCryptHashData( handle, bytes, 4, 0 );
+ }
+ else
+ {
+ /* Use U_j */
+ status = BCryptHashData( handle, tmp, hash_length, 0 );
+ }
+ if (status != STATUS_SUCCESS)
+ goto done;
+
+ status = BCryptFinishHash( handle, tmp, hash_length, 0 );
+ if (status != STATUS_SUCCESS)
+ goto done;
+
+ status = BCryptDestroyHash( handle );
+ if (status != STATUS_SUCCESS)
+ goto done;
+
+ handle = NULL;
+
+ if (j == 0)
+ {
+ /* Copy into res */
+ memcpy( res, tmp, hash_length );
+ }
+ else
+ {
+ /* XOR into res */
+ for (k = 0; k < hash_length; k++)
+ res[k] ^= tmp[k];
+ }
+ }
+
+done:
+ TRACE("<- status 0x%08x\n", status);
+ if(handle)
+ BCryptDestroyHash( handle );
+ heap_free( tmp );
+ return status;
+}
+
+/************************************************************
+ * BCryptDeriveKeyPBKDF2 (BCRYPT.@)
+ *
+ * Derive a key from a password using the PBKDF2 function
+ * (RFC 2898).
+ *
+ * PARAMS
+ * handle [I] Pointer to the PRF provider
+ * password [I] Optional pointer to the beginning of the password
+ * password_length [I] Length of the password
+ * salt [I] Optional pointer to the beginning of the salt
+ * salt_length [I] Length of the salt
+ * iterations [I] Iteration count
+ * dk [O] Pointer to the beginning of the buffer to store the
+ * derived key in, at least dklen in size
+ * dklen [I] Intended length of the derived key, at most
+ * (2^32 - 1) * (output length of PRF)
+ * flags [I] Reserved, must be zero
+ *
+ * RETURNS
+ * Success: STATUS_SUCCESS.
+ * Failure: - STATUS_INVALID_HANDLE
+ * - STATUS_INVALID_PARAMETER
+ * - STATUS_NO_MEMORY
+ */
+NTSTATUS WINAPI BCryptDeriveKeyPBKDF2( BCRYPT_ALG_HANDLE handle,
+ PUCHAR password, ULONG password_length,
+ PUCHAR salt, ULONG salt_length,
+ ULONGLONG iterations,
+ PUCHAR dk, ULONG dklen,
+ ULONG flags )
+{
+ struct algorithm *alg = handle;
+ int hlen = alg_props[alg->id].hash_length;
+ UCHAR *partial;
+ NTSTATUS status;
+ int l;
+ int r;
+ int i;
+
+ TRACE( "%p, %p, %u, %p, %u, %s, %p, %u, %08x - stub\n",
+ handle, password, password_length, salt, salt_length,
+ wine_dbgstr_longlong(iterations), dk, dklen, flags );
+
+ if (dklen <= 0 || dklen > ((((ULONGLONG) 1) << 32) - 1) * hlen)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ l = 1 + ((dklen - 1) / hlen); /* ceil(dklen/hlen) */
+ r = dklen - (l - 1) * hlen;
+
+ /* Full blocks */
+ for (i = 1; i < l; i++)
+ {
+ status = PBKDF2_F( handle,
+ password, password_length,
+ salt, salt_length,
+ iterations, i,
+ dk + ((i - 1) * hlen), hlen );
+ if (status != STATUS_SUCCESS)
+ {
+ return status;
+ }
+ }
+
+ /* Final partial block */
+ if (!(partial = heap_alloc( hlen )))
+ {
+ return STATUS_NO_MEMORY;
+ }
+ status = PBKDF2_F( handle,
+ password, password_length,
+ salt, salt_length,
+ iterations, l,
+ partial, hlen );
+ if (status != STATUS_SUCCESS)
+ {
+ heap_free( partial );
+ return status;
+ }
+ memcpy( dk + ((l - 1) * hlen), partial, r );
+ heap_free( partial );
+
+ return STATUS_SUCCESS;
+}
+
BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
{
switch (reason)
diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c
index 6865e87..5c4df6a 100644
--- a/dlls/bcrypt/tests/bcrypt.c
+++ b/dlls/bcrypt/tests/bcrypt.c
@@ -36,6 +36,8 @@ static NTSTATUS (WINAPI *pBCryptHashData)(BCRYPT_HASH_HANDLE, PUCHAR, ULONG, ULO
static NTSTATUS (WINAPI *pBCryptDuplicateHash)(BCRYPT_HASH_HANDLE, BCRYPT_HASH_HANDLE *, UCHAR *, ULONG, ULONG);
static NTSTATUS (WINAPI *pBCryptFinishHash)(BCRYPT_HASH_HANDLE, PUCHAR, ULONG, ULONG);
static NTSTATUS (WINAPI *pBCryptDestroyHash)(BCRYPT_HASH_HANDLE);
+static NTSTATUS (WINAPI *pBCryptDeriveKeyPBKDF2)(BCRYPT_ALG_HANDLE, PUCHAR, ULONG, PUCHAR, ULONG,
+ ULONGLONG, PUCHAR, ULONG, ULONG);
static NTSTATUS (WINAPI *pBCryptGenRandom)(BCRYPT_ALG_HANDLE, PUCHAR, ULONG, ULONG);
static NTSTATUS (WINAPI *pBCryptGetProperty)(BCRYPT_HANDLE, LPCWSTR, PUCHAR, ULONG, ULONG *, ULONG);
static NTSTATUS (WINAPI *pBCryptSetProperty)(BCRYPT_HANDLE, LPCWSTR, PUCHAR, ULONG, ULONG);
@@ -396,6 +398,81 @@ static void test_BcryptHash(void)
ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
}
+/* Test vectors from RFC 6070 */
+static UCHAR password[] = "password";
+static UCHAR salt[] = "salt";
+static UCHAR long_password[] =
+ "passwordPASSWORDpassword";
+static UCHAR long_salt[] =
+ "saltSALTsaltSALTsaltSALTsaltSALTsalt";
+static UCHAR password_NUL[] = "pass\0word";
+static UCHAR salt_NUL[] = "sa\0lt";
+
+static UCHAR dk1[] =
+ "0c60c80f961f0e71f3a9b524af6012062fe037a6";
+static UCHAR dk2[] =
+ "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957";
+static UCHAR dk3[] =
+ "4b007901b765489abead49d926f721d065a429c1";
+static UCHAR dk4[] =
+ "eefe3d61cd4da4e4e9945b3d6ba2158c2634e984";
+static UCHAR dk5[] =
+ "3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038";
+static UCHAR dk6[] =
+ "56fa6aa75548099dcc37d7f03425e0c3";
+
+static const struct {
+ ULONG password_length;
+ ULONG salt_length;
+ ULONGLONG iterations;
+ ULONG dklen;
+ UCHAR *password;
+ UCHAR *salt;
+ const UCHAR *dk;
+} rfc6070[] = {
+ { 8, 4, 1, 20, password, salt, dk1 },
+ { 8, 4, 2, 20, password, salt, dk2 },
+ { 8, 4, 4096, 20, password, salt, dk3 },
+ { 8, 4, 16777216, 20, password, salt, dk4 },
+ { 24, 36, 4096, 25, long_password, long_salt, dk5 },
+ { 9, 5, 4096, 16, password_NUL, salt_NUL, dk6 }
+};
+
+static void test_BcryptDeriveKeyPBKDF2(void)
+{
+ BCRYPT_ALG_HANDLE alg;
+ UCHAR dk[25];
+ char str[51];
+ NTSTATUS ret;
+ int i;
+
+ alg = NULL;
+ ret = pBCryptOpenAlgorithmProvider(&alg, BCRYPT_SHA1_ALGORITHM, MS_PRIMITIVE_PROVIDER,
+ BCRYPT_ALG_HANDLE_HMAC_FLAG);
+ ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
+ ok(alg != NULL, "alg not set\n");
+
+ test_hash_length(alg, 20);
+ test_alg_name(alg, "SHA1");
+
+ for (i = 0; i < ARRAY_SIZE(rfc6070); i++)
+ {
+ memset(dk, 0, sizeof(dk));
+ ret = pBCryptDeriveKeyPBKDF2(alg,
+ rfc6070[i].password, rfc6070[i].password_length,
+ rfc6070[i].salt, rfc6070[i].salt_length,
+ rfc6070[i].iterations,
+ dk, rfc6070[i].dklen,
+ 0);
+ ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
+ format_hash( dk, rfc6070[i].dklen, str );
+ ok(!memcmp(str, rfc6070[i].dk, rfc6070[i].dklen), "got %s\n", str);
+ }
+
+ ret = pBCryptCloseAlgorithmProvider(alg, 0);
+ ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
+}
+
static void test_rng(void)
{
BCRYPT_ALG_HANDLE alg;
@@ -1630,6 +1707,7 @@ START_TEST(bcrypt)
pBCryptDuplicateHash = (void *)GetProcAddress(module, "BCryptDuplicateHash");
pBCryptFinishHash = (void *)GetProcAddress(module, "BCryptFinishHash");
pBCryptDestroyHash = (void *)GetProcAddress(module, "BCryptDestroyHash");
+ pBCryptDeriveKeyPBKDF2 = (void *)GetProcAddress(module, "BCryptDeriveKeyPBKDF2");
pBCryptGenRandom = (void *)GetProcAddress(module, "BCryptGenRandom");
pBCryptGetProperty = (void *)GetProcAddress(module, "BCryptGetProperty");
pBCryptSetProperty = (void *)GetProcAddress(module, "BCryptSetProperty");
@@ -1660,5 +1738,10 @@ START_TEST(bcrypt)
else
win_skip("BCryptHash is not available\n");
+ if (pBCryptDeriveKeyPBKDF2) /* >= Win 7 */
+ test_BcryptDeriveKeyPBKDF2();
+ else
+ win_skip("BCryptDeriveKeyPBKDF2 is not available\n");
+
FreeLibrary(module);
}
diff --git a/dlls/ncrypt/ncrypt.spec b/dlls/ncrypt/ncrypt.spec
index e7b12e0..adc0999 100644
--- a/dlls/ncrypt/ncrypt.spec
+++ b/dlls/ncrypt/ncrypt.spec
@@ -9,7 +9,7 @@
@ stub BCryptDeleteContext
@ stub BCryptDeriveKey
@ stub BCryptDeriveKeyCapi
-@ stub BCryptDeriveKeyPBKDF2
+@ stdcall BCryptDeriveKeyPBKDF2(ptr ptr long ptr long int64 ptr long long) bcrypt.BCryptDeriveKeyPBKDF2
@ stdcall BCryptDestroyHash(ptr) bcrypt.BCryptDestroyHash
@ stdcall BCryptDestroyKey(ptr) bcrypt.BCryptDestroyKey
@ stub BCryptDestroySecret
diff --git a/include/bcrypt.h b/include/bcrypt.h
index df54f62..d3e4b99 100644
--- a/include/bcrypt.h
+++ b/include/bcrypt.h
@@ -217,6 +217,7 @@ typedef PVOID BCRYPT_HASH_HANDLE;
NTSTATUS WINAPI BCryptCloseAlgorithmProvider(BCRYPT_ALG_HANDLE, ULONG);
NTSTATUS WINAPI BCryptCreateHash(BCRYPT_ALG_HANDLE, BCRYPT_HASH_HANDLE *, PUCHAR, ULONG, PUCHAR, ULONG, ULONG);
NTSTATUS WINAPI BCryptDecrypt(BCRYPT_KEY_HANDLE, PUCHAR, ULONG, VOID *, PUCHAR, ULONG, PUCHAR, ULONG, ULONG *, ULONG);
+NTSTATUS WINAPI BCryptDeriveKeyPBKDF2(BCRYPT_ALG_HANDLE, PUCHAR, ULONG, PUCHAR, ULONG, ULONGLONG, PUCHAR, ULONG, ULONG);
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);
--
1.9.1

View File

@@ -1 +0,0 @@
Fixes: [42704] Implement BCryptDeriveKeyPBKDF2

View File

@@ -1 +0,0 @@
Fixes: [45312] Fix issue for Assassin's Creed : Syndicate

View File

@@ -1,2 +1 @@
Fixes: [46564] Add BCryptDestroySecret/BCryptSecretAgreement stubs.
Depends: bcrypt-BCryptGenerateKeyPair

View File

@@ -1,7 +1,7 @@
From 2af2d1c51ec73862a156850d702dcb4608d73558 Mon Sep 17 00:00:00 2001
From 30d0aa2712dbdfe8f532118f9829c7999c0326a7 Mon Sep 17 00:00:00 2001
From: Lucian Poston <lucian.poston@gmail.com>
Date: Thu, 3 May 2018 00:38:06 -0700
Subject: d2d1: Use ID2D1Factory1 in d2d_geometry
Subject: [PATCH] d2d1: Use ID2D1Factory1 in d2d_geometry
https://bugs.winehq.org/show_bug.cgi?id=44052
@@ -13,10 +13,10 @@ Signed-off-by: Lucian Poston <lucian.poston@gmail.com>
3 files changed, 28 insertions(+), 16 deletions(-)
diff --git a/dlls/d2d1/d2d1_private.h b/dlls/d2d1/d2d1_private.h
index 21e2b88..0bb0112 100644
index 70b841df8cb..85c56524de4 100644
--- a/dlls/d2d1/d2d1_private.h
+++ b/dlls/d2d1/d2d1_private.h
@@ -406,7 +406,7 @@ struct d2d_geometry
@@ -424,7 +424,7 @@ struct d2d_geometry
ID2D1Geometry ID2D1Geometry_iface;
LONG refcount;
@@ -25,7 +25,7 @@ index 21e2b88..0bb0112 100644
D2D_MATRIX_3X2_F transform;
@@ -470,10 +470,10 @@ struct d2d_geometry
@@ -494,10 +494,10 @@ struct d2d_geometry
} u;
};
@@ -37,13 +37,13 @@ index 21e2b88..0bb0112 100644
+ ID2D1Factory1 *factory, const D2D1_RECT_F *rect) DECLSPEC_HIDDEN;
+void d2d_transformed_geometry_init(struct d2d_geometry *geometry, ID2D1Factory1 *factory,
ID2D1Geometry *src_geometry, const D2D_MATRIX_3X2_F *transform) DECLSPEC_HIDDEN;
struct d2d_geometry *unsafe_impl_from_ID2D1Geometry(ID2D1Geometry *iface) DECLSPEC_HIDDEN;
HRESULT d2d_geometry_group_init(struct d2d_geometry *geometry, ID2D1Factory *factory,
D2D1_FILL_MODE fill_mode, ID2D1Geometry **src_geometries, unsigned int geometry_count) DECLSPEC_HIDDEN;
diff --git a/dlls/d2d1/factory.c b/dlls/d2d1/factory.c
index 7810e95..2a1a536 100644
index c2a0405abdd..33c2d173596 100644
--- a/dlls/d2d1/factory.c
+++ b/dlls/d2d1/factory.c
@@ -140,7 +140,7 @@ static HRESULT STDMETHODCALLTYPE d2d_factory_CreateRectangleGeometry(ID2D1Factor
@@ -141,7 +141,7 @@ static HRESULT STDMETHODCALLTYPE d2d_factory_CreateRectangleGeometry(ID2D1Factor
if (!(object = heap_alloc_zero(sizeof(*object))))
return E_OUTOFMEMORY;
@@ -52,7 +52,7 @@ index 7810e95..2a1a536 100644
{
WARN("Failed to initialize rectangle geometry, hr %#x.\n", hr);
heap_free(object);
@@ -190,7 +190,7 @@ static HRESULT STDMETHODCALLTYPE d2d_factory_CreateTransformedGeometry(ID2D1Fact
@@ -207,7 +207,7 @@ static HRESULT STDMETHODCALLTYPE d2d_factory_CreateTransformedGeometry(ID2D1Fact
if (!(object = heap_alloc_zero(sizeof(*object))))
return E_OUTOFMEMORY;
@@ -61,7 +61,7 @@ index 7810e95..2a1a536 100644
TRACE("Created transformed geometry %p.\n", object);
*transformed_geometry = (ID2D1TransformedGeometry *)&object->ID2D1Geometry_iface;
@@ -207,7 +207,7 @@ static HRESULT STDMETHODCALLTYPE d2d_factory_CreatePathGeometry(ID2D1Factory1 *i
@@ -224,7 +224,7 @@ static HRESULT STDMETHODCALLTYPE d2d_factory_CreatePathGeometry(ID2D1Factory2 *i
if (!(object = heap_alloc_zero(sizeof(*object))))
return E_OUTOFMEMORY;
@@ -71,7 +71,7 @@ index 7810e95..2a1a536 100644
TRACE("Created path geometry %p.\n", object);
*geometry = (ID2D1PathGeometry *)&object->ID2D1Geometry_iface;
diff --git a/dlls/d2d1/geometry.c b/dlls/d2d1/geometry.c
index d716fb1..5bf63f6 100644
index 250ff0c5535..7b67e247f7a 100644
--- a/dlls/d2d1/geometry.c
+++ b/dlls/d2d1/geometry.c
@@ -2343,15 +2343,15 @@ static void d2d_geometry_cleanup(struct d2d_geometry *geometry)
@@ -134,7 +134,7 @@ index d716fb1..5bf63f6 100644
}
static HRESULT STDMETHODCALLTYPE d2d_rectangle_geometry_GetBounds(ID2D1RectangleGeometry *iface,
@@ -3780,7 +3788,7 @@ static const struct ID2D1RectangleGeometryVtbl d2d_rectangle_geometry_vtbl =
@@ -3779,7 +3787,7 @@ static const struct ID2D1RectangleGeometryVtbl d2d_rectangle_geometry_vtbl =
d2d_rectangle_geometry_GetRect,
};
@@ -143,7 +143,7 @@ index d716fb1..5bf63f6 100644
{
struct d2d_face *f;
D2D1_POINT_2F *v;
@@ -3901,10 +3909,14 @@ static void STDMETHODCALLTYPE d2d_transformed_geometry_GetFactory(ID2D1Transform
@@ -3900,10 +3908,14 @@ static void STDMETHODCALLTYPE d2d_transformed_geometry_GetFactory(ID2D1Transform
ID2D1Factory **factory)
{
struct d2d_geometry *geometry = impl_from_ID2D1TransformedGeometry(iface);
@@ -159,7 +159,7 @@ index d716fb1..5bf63f6 100644
}
static HRESULT STDMETHODCALLTYPE d2d_transformed_geometry_GetBounds(ID2D1TransformedGeometry *iface,
@@ -4098,7 +4110,7 @@ static const struct ID2D1TransformedGeometryVtbl d2d_transformed_geometry_vtbl =
@@ -4096,7 +4108,7 @@ static const struct ID2D1TransformedGeometryVtbl d2d_transformed_geometry_vtbl =
d2d_transformed_geometry_GetTransform,
};
@@ -169,5 +169,5 @@ index d716fb1..5bf63f6 100644
{
struct d2d_geometry *src_impl;
--
2.7.4
2.20.1

View File

@@ -1,151 +0,0 @@
From 577b48296711a6ad2bd507687a05f3aac9d7a54a Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sat, 14 Jan 2017 07:50:36 +0100
Subject: [PATCH] d3d8: Improve ValidateVertexShader stub.
---
dlls/d3d8/d3d8_main.c | 39 ++++++++++++++++++++++-----------------
dlls/d3d8/tests/device.c | 40 +++++++++++++++++++++++++---------------
2 files changed, 47 insertions(+), 32 deletions(-)
diff --git a/dlls/d3d8/d3d8_main.c b/dlls/d3d8/d3d8_main.c
index 5fbd165..c48b397 100644
--- a/dlls/d3d8/d3d8_main.c
+++ b/dlls/d3d8/d3d8_main.c
@@ -64,33 +64,38 @@ IDirect3D8 * WINAPI DECLSPEC_HOTPATCH Direct3DCreate8(UINT sdk_version)
* boolean seems always passed as 0 or 1, but other values work as well...
* toto result?
*/
-HRESULT WINAPI ValidateVertexShader(DWORD* vertexshader, DWORD* reserved1, DWORD* reserved2, BOOL boolean, DWORD* toto)
+HRESULT WINAPI ValidateVertexShader(DWORD *vertexshader, DWORD *reserved1, DWORD *reserved2,
+ BOOL return_error, char **errors)
{
- HRESULT ret;
- static BOOL warned;
+ const char *message = "";
+ HRESULT hr = E_FAIL;
- if (TRACE_ON(d3d8) || !warned) {
- FIXME("(%p %p %p %d %p): stub\n", vertexshader, reserved1, reserved2, boolean, toto);
- warned = TRUE;
- }
+ TRACE("(%p %p %p %d %p): semi-stub\n", vertexshader, reserved1, reserved2, return_error, errors);
- if (!vertexshader)
- return E_FAIL;
-
- if (reserved1 || reserved2)
- return E_FAIL;
+ if (!vertexshader)
+ {
+ message = "(Global Validation Error) Version Token: Code pointer cannot be NULL.\n";
+ goto done;
+ }
- switch(*vertexshader) {
+ switch (*vertexshader)
+ {
case 0xFFFE0101:
case 0xFFFE0100:
- ret=S_OK;
+ hr = S_OK;
break;
+
default:
WARN("Invalid shader version token %#x.\n", *vertexshader);
- ret=E_FAIL;
- }
+ message = "(Global Validation Error) Version Token: Unsupported vertex shader version.\n";
+ }
- return ret;
+done:
+ if (!return_error) message = "";
+ if (errors && (*errors = HeapAlloc(GetProcessHeap(), 0, strlen(message) + 1)))
+ strcpy(*errors, message);
+
+ return hr;
}
/***********************************************************************
diff --git a/dlls/d3d8/tests/device.c b/dlls/d3d8/tests/device.c
index 884cdb1..6b9e70d 100644
--- a/dlls/d3d8/tests/device.c
+++ b/dlls/d3d8/tests/device.c
@@ -51,7 +51,7 @@ struct device_desc
static DEVMODEW registry_mode;
-static HRESULT (WINAPI *ValidateVertexShader)(DWORD *, DWORD *, DWORD *, int, DWORD *);
+static HRESULT (WINAPI *ValidateVertexShader)(DWORD *, DWORD *, DWORD *, BOOL, char **);
static HRESULT (WINAPI *ValidatePixelShader)(DWORD *, DWORD *, int, DWORD *);
static BOOL (WINAPI *pGetCursorInfo)(PCURSORINFO);
@@ -4369,18 +4369,31 @@ static void test_validate_vs(void)
0x00000009, 0xc0080000, 0x90e40000, 0xa0e40003, /* dp4 oPos.w, v0, c3 */
0x0000ffff, /* end */
};
+ char *errors;
HRESULT hr;
hr = ValidateVertexShader(0, 0, 0, 0, 0);
ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
hr = ValidateVertexShader(0, 0, 0, 1, 0);
ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
+
+ errors = (void *)0xdeadbeef;
+ hr = ValidateVertexShader(0, 0, 0, 0, &errors);
+ ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
+ ok(!strcmp(errors, ""), "Got unexpected string '%s'.\n", errors);
+ HeapFree(GetProcessHeap(), 0, errors);
+
+ errors = (void *)0xdeadbeef;
+ hr = ValidateVertexShader(0, 0, 0, 1, &errors);
+ ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
+ ok(strstr(errors, "Validation Error") != NULL, "Got unexpected string '%s'.\n", errors);
+ HeapFree(GetProcessHeap(), 0, errors);
+
hr = ValidateVertexShader(vs, 0, 0, 0, 0);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
-
hr = ValidateVertexShader(vs, 0, 0, 1, 0);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
- /* Seems to do some version checking. */
+
*vs = 0xfffe0100; /* vs_1_0 */
hr = ValidateVertexShader(vs, 0, 0, 0, 0);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
@@ -4388,21 +4401,18 @@ static void test_validate_vs(void)
*vs = 0xfffe0102; /* bogus version */
hr = ValidateVertexShader(vs, 0, 0, 1, 0);
ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
- /* I've seen that applications always pass the 2nd and 3rd parameter as 0.
- * Simple test with non-zero parameters. */
- *vs = 0xfffe0101; /* vs_1_1 */
- hr = ValidateVertexShader(vs, vs, 0, 1, 0);
+
+ errors = (void *)0xdeadbeef;
+ hr = ValidateVertexShader(vs, 0, 0, 0, &errors);
ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
+ ok(!strcmp(errors, ""), "Got unexpected string '%s'.\n", errors);
+ HeapFree(GetProcessHeap(), 0, errors);
- hr = ValidateVertexShader(vs, 0, vs, 1, 0);
+ errors = (void *)0xdeadbeef;
+ hr = ValidateVertexShader(vs, 0, 0, 1, &errors);
ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
- /* I've seen the 4th parameter always passed as either 0 or 1, but passing
- * other values doesn't seem to hurt. */
- hr = ValidateVertexShader(vs, 0, 0, 12345, 0);
- ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
- /* What is the 5th parameter? The following seems to work ok. */
- hr = ValidateVertexShader(vs, 0, 0, 1, vs);
- ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
+ ok(strstr(errors, "Validation Error") != NULL, "Got unexpected string '%s'.\n", errors);
+ HeapFree(GetProcessHeap(), 0, errors);
}
static void test_validate_ps(void)
--
1.9.1

View File

@@ -1,4 +1,4 @@
From f13fda7095a5fa275232f7440d7737a54c1f1c6c Mon Sep 17 00:00:00 2001
From a26d43a10fb5de70732970b20a29ce4437b33076 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sat, 14 Jan 2017 07:54:39 +0100
Subject: [PATCH] d3d8: Improve ValidatePixelShader stub.
@@ -9,10 +9,10 @@ Subject: [PATCH] d3d8: Improve ValidatePixelShader stub.
2 files changed, 37 insertions(+), 34 deletions(-)
diff --git a/dlls/d3d8/d3d8_main.c b/dlls/d3d8/d3d8_main.c
index c48b397..6feb8e5 100644
index 17f35c90..7b28bdf1 100644
--- a/dlls/d3d8/d3d8_main.c
+++ b/dlls/d3d8/d3d8_main.c
@@ -100,39 +100,36 @@ done:
@@ -105,39 +105,36 @@ done:
/***********************************************************************
* ValidatePixelShader (D3D8.@)
@@ -70,19 +70,19 @@ index c48b397..6feb8e5 100644
void d3d8_resource_cleanup(struct d3d8_resource *resource)
diff --git a/dlls/d3d8/tests/device.c b/dlls/d3d8/tests/device.c
index 6b9e70d..4a4c0e5 100644
index 315640d3..6f8354f4 100644
--- a/dlls/d3d8/tests/device.c
+++ b/dlls/d3d8/tests/device.c
@@ -52,7 +52,7 @@ struct device_desc
@@ -53,7 +53,7 @@ struct device_desc
static DEVMODEW registry_mode;
static HRESULT (WINAPI *ValidateVertexShader)(DWORD *, DWORD *, DWORD *, BOOL, char **);
static HRESULT (WINAPI *ValidateVertexShader)(const DWORD *, const DWORD *, const D3DCAPS8 *, BOOL, char **);
-static HRESULT (WINAPI *ValidatePixelShader)(DWORD *, DWORD *, int, DWORD *);
+static HRESULT (WINAPI *ValidatePixelShader)(DWORD *, DWORD *, BOOL, char **);
static BOOL (WINAPI *pGetCursorInfo)(PCURSORINFO);
@@ -4427,33 +4427,39 @@ static void test_validate_ps(void)
@@ -4474,33 +4474,39 @@ static void test_validate_ps(void)
0x00000005, 0x800f0000, 0xb0e40000, 0x80e40000, /* mul r0, t0, r0 */
0x0000ffff, /* end */
};
@@ -116,12 +116,6 @@ index 6b9e70d..4a4c0e5 100644
+
+ errors = (void *)0xdeadbeef;
+ hr = ValidatePixelShader(ps, 0, 0, &errors);
+ ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
+ ok(!strcmp(errors, ""), "Got unexpected string '%s'.\n", errors);
+ HeapFree(GetProcessHeap(), 0, errors);
+
+ errors = (void *)0xdeadbeef;
+ hr = ValidatePixelShader(ps, 0, 1, &errors);
ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
- /* I've seen the 3rd parameter always passed as either 0 or 1, but passing
- * other values doesn't seem to hurt. */
@@ -130,11 +124,17 @@ index 6b9e70d..4a4c0e5 100644
- /* What is the 4th parameter? The following seems to work ok. */
- hr = ValidatePixelShader(ps, 0, 1, ps);
- ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
+ ok(!strcmp(errors, ""), "Got unexpected string '%s'.\n", errors);
+ HeapFree(GetProcessHeap(), 0, errors);
+
+ errors = (void *)0xdeadbeef;
+ hr = ValidatePixelShader(ps, 0, 1, &errors);
+ ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
+ ok(strstr(errors, "Validation Error") != NULL, "Got unexpected string '%s'.\n", errors);
+ HeapFree(GetProcessHeap(), 0, errors);
}
static void test_volume_get_container(void)
--
1.9.1
2.20.1

View File

@@ -0,0 +1,345 @@
From 88412e5d16a242a1d0fed2db46ffd7ad7eb87ca8 Mon Sep 17 00:00:00 2001
From: Andrew D'Addesio <andrew@fatbag.net>
Date: Fri, 8 Feb 2019 18:48:33 -1000
Subject: [PATCH] ddraw: Return correct devices based off requested DirectX
version.
---
dlls/ddraw/ddraw.c | 230 +++++++++++++++++++++++++--------------------
1 file changed, 129 insertions(+), 101 deletions(-)
diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c
index 8a1d0a4f..274a0907 100644
--- a/dlls/ddraw/ddraw.c
+++ b/dlls/ddraw/ddraw.c
@@ -47,37 +47,80 @@ static const DDDEVICEIDENTIFIER2 deviceidentifier =
0
};
+#define D3D_VERSION(x) (1 << (x))
+
static struct enum_device_entry
{
- char interface_name[100];
+ unsigned int version_mask;
+ /* Some games (Motoracer 2 demo) have the bad idea to modify the device
+ * name/description strings. Let's put the strings in sufficiently sized
+ * arrays in static-lifetime writable memory. */
+ char device_desc[100];
char device_name[100];
const GUID *device_guid;
DWORD remove_caps;
-} device_list7[] =
+} device_list[] =
{
- /* T&L HAL device */
+ /* Ramp Emulation (D3D 1&2 only) */
{
- "WINE Direct3D7 Hardware Transform and Lighting acceleration using WineD3D",
- "Wine D3D7 T&L HAL",
- &IID_IDirect3DTnLHalDevice,
+ D3D_VERSION(1)|D3D_VERSION(2),
+ "WineD3D Ramp Software Emulation",
+ "Ramp Emulation",
+ &IID_IDirect3DRampDevice,
0,
},
- /* HAL device */
+ /* RGB Emulation (D3D 1-7) */
{
- "WINE Direct3D7 Hardware acceleration using WineD3D",
+ D3D_VERSION(1)|D3D_VERSION(2)|D3D_VERSION(3)|D3D_VERSION(7),
+ "WineD3D RGB Software Emulation",
+ "RGB Emulation",
+ &IID_IDirect3DRGBDevice,
+ D3DDEVCAPS_HWTRANSFORMANDLIGHT,
+ },
+
+ /* Direct3D HAL (D3D 1-7) */
+ {
+ D3D_VERSION(1)|D3D_VERSION(2)|D3D_VERSION(3)|D3D_VERSION(7),
+ "WineD3D Hardware Acceleration",
"Direct3D HAL",
&IID_IDirect3DHALDevice,
0,
},
- /* RGB device */
+ /* MMX Emulation (D3D2 only) */
{
- "WINE Direct3D7 RGB Software Emulation using WineD3D",
- "Wine D3D7 RGB",
- &IID_IDirect3DRGBDevice,
- D3DDEVCAPS_HWTRANSFORMANDLIGHT,
+ D3D_VERSION(2),
+ "WineD3D MMX Software Emulation",
+ "MMX Emulation",
+ &IID_IDirect3DMMXDevice,
+ 0,
+ },
+
+ /* Direct3D T&L HAL (D3D7 only) */
+ {
+ D3D_VERSION(7),
+ "WineD3D Hardware Transform and Lighting Acceleration",
+ "Direct3D T&L HAL",
+ &IID_IDirect3DTnLHalDevice,
+ 0,
},
+
+ /* In the future, we may wish to add the "Reference Rasterizer" and
+ * "Null device", which are only available in DX6-8 and must be explicitly
+ * enabled by the registry values:
+ * * EnumReference
+ * * EnumNullDevice,
+ * which are DWORD values which must be created under
+ * HKLM\Software\Microsoft\Direct3D\Drivers and set to any nonzero value.
+ * (Refer to enablerefrast.reg/disablerefrast.reg in the DX6/7 SDKs and
+ * KB249579 for more information.)
+ *
+ * DirectX 9.0 and higher appear to no longer recognize these settings,
+ * so apparently these devices were removed starting with DX9.
+ *
+ * Some games (AvP, Motoracer 2) break if these devices are enumerated.
+ */
};
static void STDMETHODCALLTYPE ddraw_null_wined3d_object_destroyed(void *parent) {}
@@ -1396,15 +1439,6 @@ HRESULT ddraw_get_d3dcaps(const struct ddraw *ddraw, D3DDEVICEDESC7 *caps)
D3DPTADDRESSCAPS_WRAP | D3DPTADDRESSCAPS_MIRROR | D3DPTADDRESSCAPS_CLAMP |
D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_INDEPENDENTUV);
- if (!(caps->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2))
- {
- /* DirectX7 always has the np2 flag set, no matter what the card
- * supports. Some old games (Rollcage) check the caps incorrectly.
- * If wined3d supports nonpow2 textures it also has np2 conditional
- * support. */
- caps->dpcLineCaps.dwTextureCaps |= D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL;
- }
-
/* Fill the missing members, and do some fixup */
caps->dpcLineCaps.dwSize = sizeof(caps->dpcLineCaps);
caps->dpcLineCaps.dwTextureBlendCaps = D3DPTBLENDCAPS_ADD
@@ -1547,6 +1581,8 @@ static HRESULT WINAPI ddraw7_GetCaps(IDirectDraw7 *iface, DDCAPS *DriverCaps, DD
IDirect3D7_EnumZBufferFormats(&ddraw->IDirect3D7_iface, &IID_IDirect3DHALDevice, enum_zbuffer, &caps);
+ caps.ddsOldCaps.dwCaps = caps.ddsCaps.dwCaps;
+
if(DriverCaps)
{
DD_STRUCT_COPY_BYSIZE(DriverCaps, &caps);
@@ -3669,8 +3705,7 @@ static HRESULT WINAPI ddraw1_DuplicateSurface(IDirectDraw *iface, IDirectDrawSur
/*****************************************************************************
* IDirect3D7::EnumDevices
*
- * The EnumDevices method for IDirect3D7. It enumerates all supported
- * D3D7 devices. Currently the T&L, HAL and RGB devices are enumerated.
+ * The EnumDevices method for IDirect3D7. It enumerates all D3D7 devices.
*
* Params:
* callback: Function to call for each enumerated device
@@ -3703,14 +3738,14 @@ static HRESULT WINAPI d3d7_EnumDevices(IDirect3D7 *iface, LPD3DENUMDEVICESCALLBA
dev_caps = device_desc7.dwDevCaps;
- for (i = 0; i < ARRAY_SIZE(device_list7); i++)
+ for (i = 0; i < ARRAY_SIZE(device_list); i++)
{
HRESULT ret;
- device_desc7.deviceGUID = *device_list7[i].device_guid;
- device_desc7.dwDevCaps = dev_caps & ~device_list7[i].remove_caps;
+ device_desc7.deviceGUID = *device_list[i].device_guid;
+ device_desc7.dwDevCaps = dev_caps & ~device_list[i].remove_caps;
- ret = callback(device_list7[i].interface_name, device_list7[i].device_name, &device_desc7, context);
+ ret = callback(device_list[i].device_name, device_list[i].device_name, &device_desc7, context);
if (ret != DDENUMRET_OK)
{
TRACE("Application cancelled the enumeration.\n");
@@ -3726,11 +3761,21 @@ static HRESULT WINAPI d3d7_EnumDevices(IDirect3D7 *iface, LPD3DENUMDEVICESCALLBA
return D3D_OK;
}
+static void clear_device_desc(D3DDEVICEDESC *device_desc)
+{
+ memset(device_desc, 0, sizeof(*device_desc));
+ device_desc->dwSize = sizeof(*device_desc);
+ device_desc->dtcTransformCaps.dwSize = sizeof(device_desc->dtcTransformCaps);
+ device_desc->dlcLightingCaps.dwSize = sizeof(device_desc->dlcLightingCaps);
+ device_desc->dpcLineCaps.dwSize = sizeof(device_desc->dpcLineCaps);
+ device_desc->dpcTriCaps.dwSize = sizeof(device_desc->dpcTriCaps);
+}
+
/*****************************************************************************
* IDirect3D3::EnumDevices
*
- * Enumerates all supported Direct3DDevice interfaces. This is the
- * implementation for Direct3D 1 to Direc3D 3, Version 7 has its own.
+ * Enumerates all Direct3DDevice interfaces. This is the implementation for
+ * Direct3D 1 to Direct3D 3; Version 7 has its own.
*
* Versions 1, 2 and 3
*
@@ -3745,18 +3790,18 @@ static HRESULT WINAPI d3d7_EnumDevices(IDirect3D7 *iface, LPD3DENUMDEVICESCALLBA
*****************************************************************************/
static HRESULT WINAPI d3d3_EnumDevices(IDirect3D3 *iface, LPD3DENUMDEVICESCALLBACK callback, void *context)
{
- static CHAR wined3d_description[] = "Wine D3DDevice using WineD3D and OpenGL";
-
+/* Size of D3DDEVICEDESC in Direct3D 1-3 */
+enum {
+ D3D1_DESC_SIZE = FIELD_OFFSET(D3DDEVICEDESC, dwMinTextureWidth), /* 172 */
+ D3D2_DESC_SIZE = FIELD_OFFSET(D3DDEVICEDESC, dwMaxTextureRepeat), /* 204 */
+ D3D3_DESC_SIZE = sizeof(D3DDEVICEDESC) /* 252 */
+};
struct ddraw *ddraw = impl_from_IDirect3D3(iface);
- D3DDEVICEDESC device_desc1, hal_desc, hel_desc;
+ DWORD desc_size;
+ D3DDEVICEDESC device_desc1, empty_desc1, hal_desc, hel_desc;
D3DDEVICEDESC7 device_desc7;
HRESULT hr;
-
- /* Some games (Motoracer 2 demo) have the bad idea to modify the device
- * name string. Let's put the string in a sufficiently sized array in
- * writable memory. */
- char device_name[50];
- strcpy(device_name,"Direct3D HEL");
+ size_t i;
TRACE("iface %p, callback %p, context %p.\n", iface, callback, context);
@@ -3765,52 +3810,58 @@ static HRESULT WINAPI d3d3_EnumDevices(IDirect3D3 *iface, LPD3DENUMDEVICESCALLBA
wined3d_mutex_lock();
+ switch (ddraw->d3dversion)
+ {
+ case 1: desc_size = D3D1_DESC_SIZE; break;
+ case 2: desc_size = D3D2_DESC_SIZE; break;
+ default: desc_size = D3D3_DESC_SIZE; break;
+ }
+
if (FAILED(hr = ddraw_get_d3dcaps(ddraw, &device_desc7)))
{
wined3d_mutex_unlock();
return hr;
}
+
ddraw_d3dcaps1_from_7(&device_desc1, &device_desc7);
+ device_desc1.dwSize = desc_size;
- /* Do I have to enumerate the reference id? Note from old d3d7:
- * "It seems that enumerating the reference IID on Direct3D 1 games
- * (AvP / Motoracer2) breaks them". So do not enumerate this iid in V1
- *
- * There's a registry key HKLM\Software\Microsoft\Direct3D\Drivers,
- * EnumReference which enables / disables enumerating the reference
- * rasterizer. It's a DWORD, 0 means disabled, 2 means enabled. The
- * enablerefrast.reg and disablerefrast.reg files in the DirectX 7.0 sdk
- * demo directory suggest this.
- *
- * Some games(GTA 2) seem to use the second enumerated device, so I have
- * to enumerate at least 2 devices. So enumerate the reference device to
- * have 2 devices.
- *
- * Other games (Rollcage) tell emulation and hal device apart by certain
- * flags. Rollcage expects D3DPTEXTURECAPS_POW2 to be set (yeah, it is a
- * limitation flag), and it refuses all devices that have the perspective
- * flag set. This way it refuses the emulation device, and HAL devices
- * never have POW2 unset in d3d7 on windows. */
- if (ddraw->d3dversion != 1)
- {
- static CHAR reference_description[] = "RGB Direct3D emulation";
-
- TRACE("Enumerating WineD3D D3DDevice interface.\n");
- hal_desc = device_desc1;
- hel_desc = device_desc1;
- /* The rgb device has the pow2 flag set in the hel caps, but not in the hal caps. */
- hal_desc.dpcLineCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2
- | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE);
- hal_desc.dpcTriCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2
- | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE);
- /* RGB, RAMP and MMX devices have a HAL dcmColorModel of 0 */
- hal_desc.dcmColorModel = 0;
- /* RGB, RAMP and MMX devices cannot report HAL hardware flags */
- hal_desc.dwFlags = 0;
-
- hr = callback((GUID *)&IID_IDirect3DRGBDevice, reference_description,
- device_name, &hal_desc, &hel_desc, context);
- if (hr != D3DENUMRET_OK)
+ clear_device_desc(&empty_desc1);
+ empty_desc1.dwSize = desc_size;
+
+ for (i = 0; i < ARRAY_SIZE(device_list); i++)
+ {
+ if (!(device_list[i].version_mask & D3D_VERSION(ddraw->d3dversion)))
+ continue;
+
+ if (IsEqualGUID(&IID_IDirect3DHALDevice, device_list[i].device_guid))
+ {
+ hal_desc = device_desc1;
+
+ /* The HAL device's hel_desc is almost empty -- but not completely */
+ hel_desc = empty_desc1;
+ hel_desc.dwFlags = D3DDD_COLORMODEL | D3DDD_DEVCAPS | D3DDD_TRANSFORMCAPS
+ | D3DDD_LIGHTINGCAPS | D3DDD_BCLIPPING;
+ hel_desc.dcmColorModel = 0;
+ hel_desc.dwDevCaps = D3DDEVCAPS_FLOATTLVERTEX;
+ hel_desc.dtcTransformCaps.dwCaps = hal_desc.dtcTransformCaps.dwCaps;
+ hel_desc.dlcLightingCaps = hal_desc.dlcLightingCaps;
+ hel_desc.bClipping = hal_desc.bClipping;
+ hel_desc.dwMaxVertexCount = hal_desc.dwMaxVertexCount;
+ }
+ else
+ {
+ hal_desc = empty_desc1;
+
+ hel_desc = device_desc1;
+ /* Ramp device supports grayscale only */
+ if (IsEqualGUID(&IID_IDirect3DRampDevice, device_list[i].device_guid))
+ hel_desc.dcmColorModel = D3DCOLOR_MONO;
+ }
+
+ hr = callback((GUID *)device_list[i].device_guid, device_list[i].device_desc,
+ device_list[i].device_name, &hal_desc, &hel_desc, context);
+ if (hr != DDENUMRET_OK)
{
TRACE("Application cancelled the enumeration.\n");
wined3d_mutex_unlock();
@@ -3818,29 +3869,6 @@ static HRESULT WINAPI d3d3_EnumDevices(IDirect3D3 *iface, LPD3DENUMDEVICESCALLBA
}
}
- strcpy(device_name,"Direct3D HAL");
-
- TRACE("Enumerating HAL Direct3D device.\n");
- hal_desc = device_desc1;
- hel_desc = device_desc1;
-
- /* The hal device does not have the pow2 flag set in hel, but in hal. */
- hel_desc.dpcLineCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2
- | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE);
- hel_desc.dpcTriCaps.dwTextureCaps &= ~(D3DPTEXTURECAPS_POW2
- | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE);
- /* HAL devices have a HEL dcmColorModel of 0 */
- hel_desc.dcmColorModel = 0;
-
- hr = callback((GUID *)&IID_IDirect3DHALDevice, wined3d_description,
- device_name, &hal_desc, &hel_desc, context);
- if (hr != D3DENUMRET_OK)
- {
- TRACE("Application cancelled the enumeration.\n");
- wined3d_mutex_unlock();
- return D3D_OK;
- }
-
TRACE("End of enumeration.\n");
wined3d_mutex_unlock();
--
2.20.1

View File

@@ -0,0 +1,10 @@
# Games from code comments
# Rollcage
# GTA 2
# Motoracer 2 demo
# Games that require testing from the bug report.
# Resident Evil
# Carmageddon 2 demo
# The Sims Online
Fixes: [19153] https://bugs.winehq.org/show_bug.cgi?id=19153
Depends: ddraw-Device_Caps

View File

@@ -0,0 +1,132 @@
From 8a91b7a88d96f735f7236afeed90c376a18f0eea Mon Sep 17 00:00:00 2001
From: Daniel Wendt <daniel.wendt@linux.com>
Date: Fri, 15 Nov 2013 12:52:37 +0100
Subject: [PATCH] gdi32: fix for rotated Arc, ArcTo, Chord and Pie drawing
problem
Wine-Bug: http://bugs.winehq.org/show_bug.cgi?id=34579
---
dlls/gdi32/dibdrv/graphics.c | 80 ++++++++++++++++++++++++++++++++++++++++++++
dlls/gdi32/gdi_private.h | 3 ++
2 files changed, 83 insertions(+)
diff --git a/dlls/gdi32/dibdrv/graphics.c b/dlls/gdi32/dibdrv/graphics.c
index 7d71fbb..d269cc1 100644
--- a/dlls/gdi32/dibdrv/graphics.c
+++ b/dlls/gdi32/dibdrv/graphics.c
@@ -313,6 +313,60 @@ static int get_arc_points( int arc_dir, const RECT *rect, POINT start, POINT end
return pos - count;
}
+/*
+ Check if matrix has uniform scale and shear and contains a rotation.
+*/
+BOOL xform_has_rotate_and_uniform_scale_and_shear( const XFORM *xform )
+{
+ return xform->eM21 != 0 && xform->eM11 == xform->eM22 && -xform->eM21 == xform->eM12;
+}
+
+/*
+ Decompose rotation and translation from matrix xform.
+
+ If parameter rotation_and_translation is != NULL, save rotation and translation into it.
+
+ Note: The current implementation only works on matrixes with uniform scale and shear,
+ which has to be checked by a call to xform_has_rotate_and_uniform_scale_and_shear().
+ Hints how to get unique values for non-uniform matrixes are welcome.
+*/
+BOOL xform_decompose_rotation_and_translation( XFORM *xform, XFORM *rotation_and_translation )
+{
+ XFORM inverse_matrix_scale;
+ XFORM origin_matrix = *xform;
+ double determinant = 0;
+
+ /* xform = xfrom-transposed * xform */
+ xform->eM11 = sqrt( xform->eM11 * xform->eM11 + xform->eM21 * xform->eM21 );
+ xform->eM22 = sqrt( xform->eM12 * xform->eM12 + xform->eM22 * xform->eM22 );
+ xform->eM12 = 0;
+ xform->eM21 = 0;
+ xform->eDx = 0;
+ xform->eDy = 0;
+
+ if ( rotation_and_translation == NULL )
+ return TRUE;
+
+ if ( xform->eM11 == 0 || xform->eM22 == 0 )
+ return FALSE;
+
+ determinant = xform->eM11 * xform->eM22;
+
+ inverse_matrix_scale.eM11 = xform->eM22 / determinant;
+ inverse_matrix_scale.eM12 = 0;
+ inverse_matrix_scale.eM21 = 0;
+ inverse_matrix_scale.eM22 = xform->eM11 / determinant;
+
+ /* calculate the rotation matrix */
+ rotation_and_translation->eM11 = inverse_matrix_scale.eM11 * origin_matrix.eM11;
+ rotation_and_translation->eM12 = inverse_matrix_scale.eM11 * origin_matrix.eM12;
+ rotation_and_translation->eM21 = inverse_matrix_scale.eM22 * origin_matrix.eM12 * -1;
+ rotation_and_translation->eM22 = inverse_matrix_scale.eM22 * origin_matrix.eM22;
+ rotation_and_translation->eDx = origin_matrix.eDx;
+ rotation_and_translation->eDy = origin_matrix.eDy;
+ return TRUE;
+}
+
/* backend for arc functions; extra_lines is -1 for ArcTo, 0 for Arc, 1 for Chord, 2 for Pie */
static BOOL draw_arc( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
INT start_x, INT start_y, INT end_x, INT end_y, INT extra_lines )
@@ -325,6 +379,22 @@ static BOOL draw_arc( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
BOOL ret = TRUE;
HRGN outline = 0, interior = 0;
+ BOOL exclude_rotation = FALSE;
+ XFORM old;
+ XFORM rotation_and_translation;
+ if (GetGraphicsMode( pdev->dev.hdc ) == GM_ADVANCED)
+ {
+ XFORM xf;
+ GetWorldTransform( pdev->dev.hdc, &old );
+ xf = old;
+ if (xform_has_rotate_and_uniform_scale_and_shear( &xf ) &&
+ xform_decompose_rotation_and_translation( &xf, &rotation_and_translation ))
+ {
+ SetWorldTransform( pdev->dev.hdc, &xf );
+ exclude_rotation = TRUE;
+ }
+ }
+
if (!get_pen_device_rect( dc, pdev, &rect, left, top, right, bottom )) return TRUE;
width = rect.right - rect.left;
@@ -358,6 +428,16 @@ static BOOL draw_arc( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
points[count].y = rect.top + height / 2;
count++;
}
+
+ if (exclude_rotation == TRUE)
+ {
+ SetWorldTransform( pdev->dev.hdc, &rotation_and_translation );
+ /* apply rotation and translation to calculated points */
+ LPtoDP( dev->hdc, points, count );
+ /* restore origin matrix */
+ SetWorldTransform( pdev->dev.hdc, &old );
+ }
+
if (count < 2)
{
HeapFree( GetProcessHeap(), 0, points );
diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h
index 920cd1e..4949187 100644
--- a/dlls/gdi32/gdi_private.h
+++ b/dlls/gdi32/gdi_private.h
@@ -608,4 +608,7 @@ extern void free_heap_bits( struct gdi_image_bits *bits ) DECLSPEC_HIDDEN;
extern HMODULE gdi32_module DECLSPEC_HIDDEN;
+BOOL xform_has_rotate_and_uniform_scale_and_shear( const XFORM *xform ) DECLSPEC_HIDDEN;
+BOOL xform_decompose_rotation_and_translation( XFORM *xform, XFORM *rotation_and_translation ) DECLSPEC_HIDDEN;
+
#endif /* __WINE_GDI_PRIVATE_H */
--
1.9.1

View File

@@ -0,0 +1,104 @@
From b278711b2c76680e6e26a114f74d7f7c26ff6328 Mon Sep 17 00:00:00 2001
From: Daniel Wendt <daniel.wendt@linux.com>
Date: Tue, 10 Dec 2013 14:55:32 +0100
Subject: [PATCH] gdi32: fix for rotated ellipse
Bug: http://bugs.winehq.org/show_bug.cgi?id=35331
---
dlls/gdi32/dibdrv/graphics.c | 60 +++++++++++++++++++++++++++++++-------------
1 file changed, 42 insertions(+), 18 deletions(-)
diff --git a/dlls/gdi32/dibdrv/graphics.c b/dlls/gdi32/dibdrv/graphics.c
index d269cc1..447aab5 100644
--- a/dlls/gdi32/dibdrv/graphics.c
+++ b/dlls/gdi32/dibdrv/graphics.c
@@ -1555,6 +1555,23 @@ BOOL dibdrv_RoundRect( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
BOOL ret = TRUE;
HRGN outline = 0, interior = 0;
+ BOOL exclude_rotation_translation = FALSE;
+ XFORM old;
+ XFORM rotation_and_translation;
+
+ if (GetGraphicsMode( pdev->dev.hdc ) == GM_ADVANCED)
+ {
+ XFORM xf;
+ GetWorldTransform( pdev->dev.hdc, &old );
+ xf = old;
+ if (xform_has_rotate_and_uniform_scale_and_shear( &xf ) &&
+ xform_decompose_rotation_and_translation( &xf, &rotation_and_translation ))
+ {
+ SetWorldTransform( pdev->dev.hdc, &xf );
+ exclude_rotation_translation = TRUE;
+ }
+ }
+
if (!get_pen_device_rect( dc, pdev, &rect, left, top, right, bottom )) return TRUE;
pt[0].x = pt[0].y = 0;
@@ -1575,23 +1592,6 @@ BOOL dibdrv_RoundRect( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
return FALSE;
}
- if (pdev->brush.style != BS_NULL &&
- !(interior = CreateRoundRectRgn( rect.left, rect.top, rect.right + 1, rect.bottom + 1,
- ellipse_width, ellipse_height )))
- {
- HeapFree( GetProcessHeap(), 0, points );
- if (outline) DeleteObject( outline );
- return FALSE;
- }
-
- /* if not using a region, paint the interior first so the outline can overlap it */
- if (interior && !outline)
- {
- ret = brush_region( pdev, interior );
- DeleteObject( interior );
- interior = 0;
- }
-
count = ellipse_first_quadrant( ellipse_width, ellipse_height, points );
if (dc->ArcDirection == AD_CLOCKWISE)
@@ -1635,13 +1635,37 @@ BOOL dibdrv_RoundRect( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
}
count = end + 1;
+ if (exclude_rotation_translation == TRUE)
+ {
+ SetWorldTransform( pdev->dev.hdc, &rotation_and_translation );
+ /* apply rotation and translation to calculated points */
+ LPtoDP( dev->hdc, points, count );
+ /* restore origin matrix */
+ SetWorldTransform( pdev->dev.hdc, &old );
+ }
+
+ if (pdev->brush.style != BS_NULL &&
+ !(interior = CreatePolygonRgn(points, count, ALTERNATE)))
+ {
+ HeapFree( GetProcessHeap(), 0, points );
+ if (outline) DeleteObject( outline );
+ return FALSE;
+ }
+
+ /* if not using a region, paint the interior first so the outline can overlap it */
+ if (interior && !outline)
+ {
+ ret = brush_region( pdev, interior );
+ DeleteObject( interior );
+ interior = 0;
+ }
+
reset_dash_origin( pdev );
pdev->pen_lines( pdev, count, points, TRUE, outline );
add_pen_lines_bounds( pdev, count, points, outline );
if (interior)
{
- CombineRgn( interior, interior, outline, RGN_DIFF );
ret = brush_region( pdev, interior );
DeleteObject( interior );
}
--
1.9.1

View File

@@ -0,0 +1,2 @@
Fixes: [34579] gdi32: fix for rotated Arc, ArcTo, Chord and Pie drawing problem
Fixes: [35331] gdi32: fix for rotated ellipse

View File

@@ -1,488 +0,0 @@
From c19686947741c4035d22337e3004ce7c0ee51039 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sergio=20G=C3=B3mez=20Del=20Real?=
<sdelreal@codeweavers.com>
Date: Wed, 4 Apr 2018 10:49:39 -0500
Subject: [PATCH 1/4] tools/make_unicode: Implement full Unicode character
decomposition.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Sergio GĂłmez Del Real <sdelreal@codeweavers.com>
---
libs/port/mbtowc.c | 14 +--
tools/make_unicode | 333 +++++++++++++++++++++++++++++++++++++++++++----------
2 files changed, 279 insertions(+), 68 deletions(-)
diff --git a/libs/port/mbtowc.c b/libs/port/mbtowc.c
index 4977c82..6976f89 100644
--- a/libs/port/mbtowc.c
+++ b/libs/port/mbtowc.c
@@ -22,7 +22,7 @@
#include "wine/unicode.h"
-extern unsigned int wine_decompose( WCHAR ch, WCHAR *dst, unsigned int dstlen ) DECLSPEC_HIDDEN;
+extern int wine_unicode_decompose_string( int compat, const WCHAR *src, int srclen, WCHAR *dst, int dstlen );
/* check the code whether it is in Unicode Private Use Area (PUA). */
/* MB_ERR_INVALID_CHARS raises an error converting from 1-byte character to PUA. */
@@ -101,19 +101,19 @@ static int mbstowcs_sbcs_decompose( const struct sbcs_table *table, int flags,
WCHAR *dst, unsigned int dstlen )
{
const WCHAR * const cp2uni = (flags & MB_USEGLYPHCHARS) ? table->cp2uni_glyphs : table->cp2uni;
- unsigned int len;
+ int len;
if (!dstlen) /* compute length */
{
WCHAR dummy[4]; /* no decomposition is larger than 4 chars */
for (len = 0; srclen; srclen--, src++)
- len += wine_decompose( cp2uni[*src], dummy, 4 );
+ len += wine_unicode_decompose_string( 0, &cp2uni[*src], 1, dummy, 4 );
return len;
}
for (len = dstlen; srclen && len; srclen--, src++)
{
- unsigned int res = wine_decompose( cp2uni[*src], dst, len );
+ int res = wine_unicode_decompose_string( 0, &cp2uni[*src], 1, dst, len );
if (!res) break;
len -= res;
dst += res;
@@ -203,7 +203,7 @@ static int mbstowcs_dbcs_decompose( const struct dbcs_table *table,
{
const WCHAR * const cp2uni = table->cp2uni;
const unsigned char * const cp2uni_lb = table->cp2uni_leadbytes;
- unsigned int len, res;
+ int len, res;
WCHAR ch;
if (!dstlen) /* compute length */
@@ -219,7 +219,7 @@ static int mbstowcs_dbcs_decompose( const struct dbcs_table *table,
ch = cp2uni[(off << 8) + *src];
}
else ch = cp2uni[*src];
- len += wine_decompose( ch, dummy, 4 );
+ len += wine_unicode_decompose_string( 0, &ch, 1, dummy, 4 );
}
return len;
}
@@ -234,7 +234,7 @@ static int mbstowcs_dbcs_decompose( const struct dbcs_table *table,
ch = cp2uni[(off << 8) + *src];
}
else ch = cp2uni[*src];
- if (!(res = wine_decompose( ch, dst, len ))) break;
+ if (!(res = wine_unicode_decompose_string( 0, &ch, 1, dst, len ))) break;
dst += res;
len -= res;
}
diff --git a/tools/make_unicode b/tools/make_unicode
index 56d1905..2aa063b 100755
--- a/tools/make_unicode
+++ b/tools/make_unicode
@@ -472,6 +472,28 @@ sub READ_DEFAULTS($)
next if $decomp eq ""; # no decomposition, skip it
+ # store decomposition table
+ if ($decomp =~ /^<([a-zA-Z]+)>(\s+[0-9a-fA-F]+)+$/)
+ {
+ my @seq = ();
+ for my $ch (split /\s+/, (split /\s+/, $decomp, 2)[1])
+ {
+ push @seq, (hex $ch);
+ }
+ $decomp_table[$src] = [1, \@seq];
+ }
+ elsif ($decomp =~ /^([0-9a-fA-F]+)(\s+([0-9a-fA-F]+))*$/)
+ {
+ my @seq = ();
+ for my $ch (split /\s+/, $decomp)
+ {
+ # we don't support surrogates at the moment
+ next if hex $ch > 0xffff;
+ push @seq, (hex $ch);
+ }
+ $decomp_table[$src] = [0, \@seq];
+ }
+
if ($decomp =~ /^<([a-zA-Z]+)>\s+([0-9a-fA-F]+)$/)
{
# decomposition of the form "<foo> 1234" -> use char if type is known
@@ -506,16 +528,13 @@ sub READ_DEFAULTS($)
# decomposition contains only char values without prefix -> use first char
$dst = hex $1;
$category_table[$src] |= $category_table[$dst] if defined $category_table[$dst];
- # store decomposition if it contains two chars
if ($decomp =~ /^([0-9a-fA-F]+)\s+([0-9a-fA-F]+)$/)
{
- $decomp_table[$src] = [ hex $1, hex $2 ];
push @compose_table, [ hex $1, hex $2, $src ];
}
elsif ($decomp =~ /^(<[a-z]+>\s)*([0-9a-fA-F]+)$/ &&
(($src >= 0xf900 && $src < 0xfb00) || ($src >= 0xfe30 && $src < 0xfffd)))
{
- # Single char decomposition in the compatibility range
$compatmap_table[$src] = hex $2;
}
}
@@ -2264,6 +2283,51 @@ EOF
save_file($filename);
}
+sub do_decomp
+{
+ my ($char, $table_ref, $compat) = @_;
+
+ return ($char) unless defined $table_ref->[$char];
+ my $data = $table_ref->[$char];
+ return ($char) if $data->[0] && !$compat;
+ my @mapping = ();
+ for my $ch (@{$data->[1]})
+ {
+ push @mapping, $ch;
+ }
+ return @mapping;
+}
+
+sub expand_pairs
+{
+ my @data = @_;
+ my @result = ();
+
+ for my $ch (@data)
+ {
+ if ($ch <= 0xFFFF)
+ {
+ push @result, $ch;
+ }
+ elsif ($ch >= 2097152) # 2**21
+ {
+ die sprintf "Invalid Unicode character %04x\n", $ch;
+ }
+ else
+ {
+ my $hx = $ch & 0xFFFF;
+ my $hu = ($ch >> 16) & ((1 << 5) - 1);
+ my $hw = ($hu - 1) & 0xFFFF;
+ my $hi = 0xD800 | ($hw << 6) | ($hx >> 10);
+ my $lx = $ch & 0xFFFF;
+ my $lo = (0xDC00 | ($lx & ((1 << 10) - 1))) & 0xFFFF;
+ push @result, $hi;
+ push @result, $lo;
+ }
+ }
+ return @result;
+}
+
################################################################
# dump the char decomposition table
sub dump_decompose_table($)
@@ -2272,98 +2336,245 @@ sub dump_decompose_table($)
open OUTPUT,">$filename.new" or die "Cannot create $filename";
print "Building $filename\n";
- print OUTPUT "/* Unicode char composition */\n";
+ print OUTPUT "/* Unicode char decomposition */\n";
print OUTPUT "/* generated from $UNIDATA/UnicodeData.txt */\n";
print OUTPUT "/* DO NOT EDIT!! */\n\n";
print OUTPUT "#include \"wine/unicode.h\"\n\n";
- # first determine all the 16-char subsets that contain something
+ # limit code points to BMP
+ my $utflim = 65536;
+ my %nfd_lookup = ();
+ my %nfkd_lookup = ();
+ my %decomp_lookup = ();
+ my @decomp_data = (0);
+ my $pos = 1;
+ my $lastchar_decomp;
- my @filled = (0) x 4096;
- my $pos = 16*2; # for the null subset
- for (my $i = 0; $i < 65536; $i++)
+ for (my $i = 0; $i < $utflim; $i++)
{
next unless defined $decomp_table[$i];
- $filled[$i >> 4] = $pos;
- $pos += 16*2;
- $i |= 15;
+
+ if (defined $decomp_table[$i])
+ {
+ $lastchar_decomp = $i;
+ # fully expand input and mappings
+
+ my @char;
+ push @char, $i;
+ push @char, 0;
+ my $char = pack "n*", @char;
+
+ my @nfd = do_decomp( $i, \@decomp_table, 0 );
+ push @nfd, 0;
+ my $nfd = pack "n*", @nfd;
+
+ my @nfkd = do_decomp( $i, \@decomp_table, 1 );
+ push @nfkd, 0;
+ my $nfkd = pack "n*", @nfkd;
+
+ # lookup or add mappings
+
+ if ($nfd eq $char)
+ {
+ $nfd = undef;
+ }
+ elsif (exists $decomp_lookup{$nfd})
+ {
+ $nfd_lookup{$i} = $decomp_lookup{$nfd};
+ }
+ else
+ {
+ push @decomp_data, @nfd;
+ $decomp_lookup{$nfd} = $pos;
+ $nfd_lookup{$i} = $pos;
+ $pos += @nfd;
+ }
+
+ if ($nfkd eq $char)
+ {
+ $nfkd = undef;
+ }
+ elsif (exists $decomp_lookup{$nfkd})
+ {
+ $nfkd_lookup{$i} = $decomp_lookup{$nfkd};
+ }
+ else
+ {
+ push @decomp_data, @nfkd;
+ $decomp_lookup{$nfkd} = $pos;
+ $nfkd_lookup{$i} = $pos;
+ $pos += @nfkd;
+ }
+ }
}
- my $total = $pos;
- # now count the 256-char subsets that contain something
+ printf OUTPUT "static const UINT last_decomposable = 0x%x;\n\n", $lastchar_decomp;
- my @filled_idx = (256) x 256;
- $pos = 256 + 16;
- for (my $i = 0; $i < 4096; $i++)
+ # dump decomposition data
+
+ printf OUTPUT "static const WCHAR data_decomp[%d] =\n", $pos;
+ print OUTPUT "{\n";
+ printf OUTPUT "%s", DUMP_ARRAY( "0x%04x", 0, @decomp_data );
+ print OUTPUT "\n};\n\n";
+
+ # find 256-char subsets that contain something
+
+ my $filled_pos = 1;
+ my $filled_lim = ($lastchar_decomp >> 8) + 1;
+ my @filled = (0) x $filled_lim;
+ for (my $i = 0; $i < $utflim; $i++)
+ {
+ last if $i > $lastchar_decomp;
+ next unless exists $nfd_lookup{$i} || exists $nfkd_lookup{$i};
+ $filled[$i >> 8] = $filled_pos++;
+ $i |= 255;
+ }
+
+ # dump index of 256-char subsets
+
+ printf OUTPUT "static const BYTE idx1_decomp[%d] =\n", $filled_lim;
+ print OUTPUT "{\n";
+ printf OUTPUT "%s", DUMP_ARRAY( "0x%02x", 0, @filled );
+ print OUTPUT "\n};\n\n";
+
+ # for 256-char subsets, find non-empty 16-char subsets
+
+ my $sub_filled_pos = 1;
+ my %sub_filled = ();
+ for (my $i = 0; $i < $filled_lim; $i++)
{
next unless $filled[$i];
- $filled_idx[$i >> 4] = $pos;
- $pos += 16;
- $i |= 15;
+ for (my $j = 0; $j < 256; $j++)
+ {
+ my $idx = ($i << 8) | $j;
+ next unless exists $nfd_lookup{$idx} || exists $nfkd_lookup{$idx};
+ $sub_filled{$idx >> 4} = $sub_filled_pos++;
+ $j |= 15;
+ }
}
- my $null_offset = $pos; # null mapping
- $total += $pos;
- # add the index offsets to the subsets positions
+ # dump index of 16-char subsets
- for (my $i = 0; $i < 4096; $i++)
+ printf OUTPUT "static const USHORT idx2_decomp[%d] =\n", $filled_pos * 16;
+ print OUTPUT "{\n";
+ my @null_idx = (0) x 16;
+ print OUTPUT " /* null sub-index */\n";
+ printf OUTPUT "%s", DUMP_ARRAY( "0x%04x", 0, @null_idx );
+ for (my $i = 0; $i < $filled_lim; $i++)
{
next unless $filled[$i];
- $filled[$i] += $null_offset;
+ printf OUTPUT ",\n /* sub-index 0x%02x */\n", $filled[$i];
+
+ my @sub_idx;
+ for (my $j = 0; $j < 16; $j++)
+ {
+ my $idx = ($i << 4) | $j;
+ $sub_idx[$j] = $sub_filled{$idx} || 0;
+ }
+ printf OUTPUT "%s", DUMP_ARRAY( "0x%04x", 0, @sub_idx );
}
+ print OUTPUT "\n};\n\n";
- # dump the main index
+ # dump the 16-char subsets
- printf OUTPUT "static const WCHAR table[%d] =\n", $total;
- printf OUTPUT "{\n /* index */\n";
- printf OUTPUT "%s", DUMP_ARRAY( "0x%04x", 0, @filled_idx );
- printf OUTPUT ",\n /* null sub-index */\n%s", DUMP_ARRAY( "0x%04x", 0, ($null_offset) x 16 );
+ printf OUTPUT "static const USHORT offsets_decomp[%d] =\n", 32 * $sub_filled_pos;
+ print OUTPUT "{\n";
+ print OUTPUT " /* (nfd, nfkd) x 16 */\n";
+ my @null_table = (0) x 32;
+ print OUTPUT " /* no decomposition */\n";
+ printf OUTPUT "%s", DUMP_ARRAY( "0x%04x", 0, @null_table );
+ for my $key (sort {$a <=> $b} keys %sub_filled)
+ {
+ printf OUTPUT ",\n /* 0x%03x0 .. 0x%03xf */\n", $key, $key;
+ my @sub_table;
+ for (my $j = 0; $j < 16; $j++)
+ {
+ my $idx = ($key << 4) | $j;
+ $sub_table[2 * $j] = $nfd_lookup{$idx} || 0;
+ $sub_table[2 * $j + 1] = $nfkd_lookup{$idx} || 0;
+ }
+ printf OUTPUT "%s", DUMP_ARRAY( "0x%04x", 0, @sub_table );
+ }
+ print OUTPUT "\n};\n\n";
- # dump the second-level indexes
+ print OUTPUT <<"EOF";
+static const WCHAR *unicode_table_lookup( UINT cp, int compat, const BYTE *idx1, UINT scale_idx1,
+ const USHORT *idx2, UINT scale_idx2, const USHORT *offsets,
+ UINT scale_off, const WCHAR *data, UINT scale_data )
+{
+ USHORT a, b, c, d;
- for (my $i = 0; $i < 256; $i++)
+ a = idx1[cp >> scale_idx1];
+ b = idx2[(a << scale_idx2) + ((cp >> scale_idx2) & 0xf)];
+ c = (b << scale_off) + ((cp & 0xf) << scale_data);
+ if (compat) ++c;
+ d = offsets[c];
+
+ return &data[d];
+}
+
+static int decompose_char_recursive( int compat, UINT ch, WCHAR *dst, int dstlen )
+{
+ int total_decomp = 0;
+ int size_decomp;
+ const WCHAR *map;
+
+ if (ch < 0xa0) /* fast path */
{
- next unless ($filled_idx[$i] > 256);
- my @table = @filled[($i<<4)..($i<<4)+15];
- for (my $j = 0; $j < 16; $j++) { $table[$j] ||= $null_offset; }
- printf OUTPUT ",\n /* sub-index %02x */\n", $i;
- printf OUTPUT "%s", DUMP_ARRAY( "0x%04x", 0, @table );
+ if (dstlen) *dst = (WCHAR)ch;
+ return 1;
+ }
+ else if (ch > last_decomposable ||
+ !*(map = unicode_table_lookup( ch, compat, idx1_decomp, 8,
+ idx2_decomp, 4, offsets_decomp, 5, data_decomp, 1 )))
+ {
+ if (dstlen) *dst = (WCHAR)ch;
+ return 1;
}
+ else {
+ while (*map)
+ {
+ size_decomp = decompose_char_recursive( compat, *map, dst, dstlen );
+ dstlen -= size_decomp;
+ if (dstlen < 0) dstlen = 0;
+ dst += size_decomp;
+ map++;
+ total_decomp += size_decomp;
+ }
+ return total_decomp;
+ }
+}
- # dump the 16-char subsets
+int wine_unicode_decompose_string( int compat, const WCHAR *src,
+ int srclen, WCHAR *dst, int dstlen )
+{
+ UINT ch;
+ int srcpos = 0, dstpos = 0;
+ int decomp_len;
- printf OUTPUT ",\n /* null mapping */\n";
- printf OUTPUT "%s", DUMP_ARRAY( "0x%04x", 0, (0) x 32 );
+ if (dstlen < 0) dstlen = 0;
- for (my $i = 0; $i < 4096; $i++)
+ while (srcpos < srclen)
{
- next unless $filled[$i];
- my @table = (0) x 32;
- for (my $j = 0; $j < 16; $j++)
+ ch = src[srcpos];
+
+ decomp_len = decompose_char_recursive( compat, ch, dst+dstpos, dstlen );
+ dstpos += decomp_len;
+
+ if (dstlen > 0)
{
- if (defined $decomp_table[($i<<4) + $j])
+ dstlen -= decomp_len;
+ while (dstlen < 0)
{
- $table[2 * $j] = ${$decomp_table[($i << 4) + $j]}[0];
- $table[2 * $j + 1] = ${$decomp_table[($i << 4) + $j]}[1];
+ dstpos--;
+ dstlen++;
}
}
- printf OUTPUT ",\n /* 0x%03x0 .. 0x%03xf */\n", $i, $i;
- printf OUTPUT "%s", DUMP_ARRAY( "0x%04x", 0, @table );
+
+ ++srcpos;
}
- printf OUTPUT "\n};\n\n";
- print OUTPUT <<"EOF";
-unsigned int DECLSPEC_HIDDEN wine_decompose( WCHAR ch, WCHAR *dst, unsigned int dstlen )
-{
- const WCHAR *ptr = table + table[table[ch >> 8] + ((ch >> 4) & 0x0f)] + 2 * (ch & 0xf);
- unsigned int res;
-
- *dst = ch;
- if (!*ptr) return 1;
- if (dstlen <= 1) return 0;
- /* apply the decomposition recursively to the first char */
- if ((res = wine_decompose( *ptr, dst, dstlen-1 ))) dst[res++] = ptr[1];
- return res;
+ return dstpos;
}
EOF
close OUTPUT;
--
1.9.1

View File

@@ -1,400 +0,0 @@
From 1f362267f8196f6017e4e08a9dd4dca589c494d1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sergio=20G=C3=B3mez=20Del=20Real?=
<sdelreal@codeweavers.com>
Date: Tue, 27 Mar 2018 07:28:02 -0500
Subject: [PATCH 2/4] tools/make_unicode: Implement canonical composition for
use in normalization.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Sergio GĂłmez Del Real <sdelreal@codeweavers.com>
---
tools/make_unicode | 302 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 301 insertions(+), 1 deletion(-)
diff --git a/tools/make_unicode b/tools/make_unicode
index 2aa063b..4b1c46f 100755
--- a/tools/make_unicode
+++ b/tools/make_unicode
@@ -360,6 +360,8 @@ my @joining_table = ();
my @direction_table = ();
my @decomp_table = ();
my @compose_table = ();
+my @comb_class_table = ();
+my @full_comp_table = ();
my $default_char;
my $default_wchar;
@@ -470,6 +472,11 @@ sub READ_DEFAULTS($)
}
}
+ if ($comb != 0)
+ {
+ $comb_class_table[$src] = (hex $comb);
+ }
+
next if $decomp eq ""; # no decomposition, skip it
# store decomposition table
@@ -562,6 +569,25 @@ sub READ_DEFAULTS($)
my $flag = $ctype{$cat};
foreach my $i (@{$special_categories{$cat}}) { $category_table[$i] |= $flag; }
}
+
+ my $UNICODE_DERIVED = open_data_file( $UNIDATA, "DerivedNormalizationProps.txt" );
+ while (<$UNICODE_DERIVED>)
+ {
+ next unless (/^([0-9a-fA-F.]+)\s+;\s+Full_Composition_Exclusion/);
+ my ($first, $last) = split /\.\./,$1;
+ $first = hex $first;
+ if (defined $last)
+ {
+ $last = hex $last;
+ while ($last gt $first)
+ {
+ $full_comp_table[$last] = 1;
+ $last--;
+ }
+ }
+ $full_comp_table[$first] = 1;
+ }
+ close $UNICODE_DERIVED;
}
@@ -2255,6 +2281,8 @@ sub dump_compose_table($)
}
print OUTPUT "\n};\n\n";
print OUTPUT <<"EOF";
+#include "decompose.c"
+
static inline int binary_search( WCHAR ch, int low, int high )
{
while (low <= high)
@@ -2278,6 +2306,59 @@ WCHAR DECLSPEC_HIDDEN wine_compose( const WCHAR *str )
count = table[2 * pos + 3];
}
}
+
+static inline int is_blocked(WCHAR *ptr1, WCHAR *ptr2)
+{
+ if (ptr1 >= ptr2) return -1;
+
+ while (++ptr1 < ptr2)
+ {
+ const WCHAR *map1, *map2;
+ map1 = unicode_table_lookup( *ptr1, 0, idx1_comb, 8, idx2_comb, 4,
+ offsets_comb, 4, data_comb, 0 );
+ map2 = unicode_table_lookup( *ptr2, 0, idx1_comb, 8, idx2_comb, 4,
+ offsets_comb, 4, data_comb, 0 );
+ if (*map1 == 0 || *map2 <= *map1) return 1;
+ }
+ return 0;
+}
+
+static inline int is_fullexcl(WCHAR ch)
+{
+ const WCHAR *map = unicode_table_lookup( ch, 0, idx1_fullcomp, 8, idx2_fullcomp,
+ 4, offsets_fullcomp, 4, data_fullcomp, 0 );
+ return (int)*map;
+}
+
+int unicode_canonical_composition( WCHAR *str, int strlen )
+{
+ int i, j;
+ WCHAR dum[3] = {0};
+
+ if (strlen == 0) strlen = strlenW( str );
+
+ for (i = 1; i < strlen; i++)
+ {
+ WCHAR *ptr_comp = str+i-1, comp;
+ if (str[i] == 0) break;
+ while (ptr_comp - str > 0)
+ {
+ if (is_starter( *ptr_comp )) break;
+ --ptr_comp;
+ }
+ if (!is_starter( *ptr_comp ) || is_blocked( ptr_comp, str+i )) continue;
+ dum[0] = *ptr_comp;
+ dum[1] = str[i];
+ comp = wine_compose( dum );
+ if (!comp || is_fullexcl( comp )) continue;
+ *ptr_comp = comp;
+ for (j = i; j < strlen-1; j++) str[j] = str[j+1];
+ strlen--;
+ i--;
+ }
+
+ return strlen;
+}
EOF
close OUTPUT;
save_file($filename);
@@ -2346,13 +2427,21 @@ sub dump_decompose_table($)
my %nfd_lookup = ();
my %nfkd_lookup = ();
my %decomp_lookup = ();
+ my %comb_lookup = ();
+ my %fullcomp_lookup = ();
my @decomp_data = (0);
+ my @comb_data = (0);
+ my @full_comp_data = (0);
my $pos = 1;
+ my $pos_comb = 1;
+ my $pos_fullcomp = 1;
my $lastchar_decomp;
+ my $lastchar_comb;
+ my $lastchar_fullcomp;
for (my $i = 0; $i < $utflim; $i++)
{
- next unless defined $decomp_table[$i];
+ next unless defined $decomp_table[$i] || defined $comb_class_table[$i] || defined $full_comp_table[$i];
if (defined $decomp_table[$i])
{
@@ -2406,6 +2495,20 @@ sub dump_decompose_table($)
$pos += @nfkd;
}
}
+ if (defined $comb_class_table[$i])
+ {
+ push @comb_data, $comb_class_table[$i];
+ $lastchar_comb = $i;
+ $comb_lookup{$i} = $pos_comb;
+ $pos_comb++;
+ }
+ if (defined $full_comp_table[$i])
+ {
+ push @full_comp_data, $full_comp_table[$i];
+ $lastchar_fullcomp = $i;
+ $fullcomp_lookup{$i} = $pos_fullcomp;
+ $pos_fullcomp++;
+ }
}
printf OUTPUT "static const UINT last_decomposable = 0x%x;\n\n", $lastchar_decomp;
@@ -2497,6 +2600,154 @@ sub dump_decompose_table($)
}
print OUTPUT "\n};\n\n";
+ # now for Compatibility Class
+
+ printf OUTPUT "static const WCHAR data_comb[%d] =\n", $pos_comb;
+ print OUTPUT "{\n";
+ printf OUTPUT "%s", DUMP_ARRAY( "0x%04x", 0, @comb_data );
+ print OUTPUT "\n};\n\n";
+
+ my $comb_pos = 1;
+ my $comb_lim = ($lastchar_comb >> 8) + 1;
+ my @comb_filled = (0) x $comb_lim;
+ for (my $i = 0; $i < $utflim; $i++)
+ {
+ last if $i > $lastchar_comb;
+ next unless defined $comb_class_table[$i];
+ $comb_filled[$i >> 8] = $comb_pos++;
+ $i |= 255;
+ }
+ printf OUTPUT "static const BYTE idx1_comb[%d] =\n", $comb_lim;
+ print OUTPUT "{\n";
+ printf OUTPUT "%s", DUMP_ARRAY( "0x%02x", 0, @comb_filled );
+ print OUTPUT "\n};\n\n";
+
+ my $sub_comb_filled_pos = 1;
+ my %sub_comb_filled = ();
+ for (my $i = 0; $i < $comb_lim; $i++)
+ {
+ next unless $comb_filled[$i];
+ for (my $j = 0; $j < 256; $j++)
+ {
+ my $idx = ($i << 8) | $j;
+ next unless defined $comb_class_table[$idx];
+ $sub_comb_filled{$idx >> 4} = $sub_comb_filled_pos++;
+ $j |= 15;
+ }
+ }
+
+ printf OUTPUT "static const USHORT idx2_comb[%d] =\n", $comb_pos * 16;
+ print OUTPUT "{\n";
+ @null_idx = (0) x 16;
+ print OUTPUT " /* all-zero 256-char blocks get mapped to here */\n";
+ printf OUTPUT "%s", DUMP_ARRAY( "0x%04x", 0, @null_idx );
+ for (my $i = 0; $i < $comb_lim; $i++)
+ {
+ next unless $comb_filled[$i];
+ printf OUTPUT ",\n /* sub-index 0x%02x */\n", $comb_filled[$i];
+
+ my @sub_idx;
+ for (my $j = 0; $j < 16; $j++)
+ {
+ my $idx = ($i << 4) | $j;
+ $sub_idx[$j] = $sub_comb_filled{$idx} || 0;
+ }
+ printf OUTPUT "%s", DUMP_ARRAY( "0x%04x", 0, @sub_idx );
+ }
+ print OUTPUT "\n};\n\n";
+
+ printf OUTPUT "static const USHORT offsets_comb[%d] =\n", 16 * $sub_comb_filled_pos;
+ print OUTPUT "{\n";
+ @null_table = (0) x 16;
+ print OUTPUT " /* all-zero 16-char blocks get mapped to here */\n";
+ printf OUTPUT "%s", DUMP_ARRAY( "0x%04x", 0, @null_table );
+ for my $key (sort {$a <=> $b} keys %sub_comb_filled)
+ {
+ printf OUTPUT ",\n /* 0x%03x0 .. 0x%03xf */\n", $key, $key;
+ my @sub_table;
+ for (my $j = 0; $j < 16; $j++)
+ {
+ my $idx = ($key << 4) | $j;
+ $sub_table[$j] = $comb_lookup{$idx} || 0;
+ }
+ printf OUTPUT "%s", DUMP_ARRAY( "0x%04x", 0, @sub_table );
+ }
+ print OUTPUT "\n};\n\n";
+
+ # now for Full Composition Exclusion
+
+ printf OUTPUT "const WCHAR data_fullcomp[%d] =\n", $pos_fullcomp;
+ print OUTPUT "{\n";
+ printf OUTPUT "%s", DUMP_ARRAY( "0x%04x", 0, @full_comp_data );
+ print OUTPUT "\n};\n\n";
+
+ my $fullcomp_pos = 1;
+ my $fullcomp_lim = ($lastchar_fullcomp >> 8) + 1;
+ my @fullcomp_filled = (0) x $fullcomp_lim;
+ for (my $i = 0; $i < $utflim; $i++)
+ {
+ last if $i > $lastchar_fullcomp;
+ next unless defined $full_comp_table[$i];
+ $fullcomp_filled[$i >> 8] = $fullcomp_pos++;
+ $i |= 255;
+ }
+ printf OUTPUT "const BYTE idx1_fullcomp[%d] =\n", $fullcomp_lim;
+ print OUTPUT "{\n";
+ printf OUTPUT "%s", DUMP_ARRAY( "0x%02x", 0, @fullcomp_filled );
+ print OUTPUT "\n};\n\n";
+
+ my $sub_fullcomp_filled_pos = 1;
+ my %sub_fullcomp_filled = ();
+ for (my $i = 0; $i < $fullcomp_lim; $i++)
+ {
+ next unless $fullcomp_filled[$i];
+ for (my $j = 0; $j < 256; $j++)
+ {
+ my $idx = ($i << 8) | $j;
+ next unless defined $full_comp_table[$idx];
+ $sub_fullcomp_filled{$idx >> 4} = $sub_fullcomp_filled_pos++;
+ $j |= 15;
+ }
+ }
+
+ printf OUTPUT "const USHORT idx2_fullcomp[%d] =\n", $fullcomp_pos * 16;
+ print OUTPUT "{\n";
+ @null_idx = (0) x 16;
+ print OUTPUT " /* all-zero 256-char blocks get mapped to here */\n";
+ printf OUTPUT "%s", DUMP_ARRAY( "0x%04x", 0, @null_idx );
+ for (my $i = 0; $i < $fullcomp_lim; $i++)
+ {
+ next unless $fullcomp_filled[$i];
+ printf OUTPUT ",\n /* sub-index 0x%02x */\n", $fullcomp_filled[$i];
+
+ my @sub_idx;
+ for (my $j = 0; $j < 16; $j++)
+ {
+ my $idx = ($i << 4) | $j;
+ $sub_idx[$j] = $sub_fullcomp_filled{$idx} || 0;
+ }
+ printf OUTPUT "%s", DUMP_ARRAY( "0x%04x", 0, @sub_idx );
+ }
+ print OUTPUT "\n};\n\n";
+
+ printf OUTPUT "const USHORT offsets_fullcomp[%d] =\n", 16 * $sub_fullcomp_filled_pos;
+ print OUTPUT "{\n";
+ @null_table = (0) x 16;
+ print OUTPUT " /* all-zero 16-char blocks get mapped to here */\n";
+ printf OUTPUT "%s", DUMP_ARRAY( "0x%04x", 0, @null_table );
+ for my $key (sort {$a <=> $b} keys %sub_fullcomp_filled)
+ {
+ printf OUTPUT ",\n /* 0x%03x0 .. 0x%03xf */\n", $key, $key;
+ my @sub_table;
+ for (my $j = 0; $j < 16; $j++)
+ {
+ my $idx = ($key << 4) | $j;
+ $sub_table[$j] = $fullcomp_lookup{$idx} || 0;
+ }
+ printf OUTPUT "%s", DUMP_ARRAY( "0x%04x", 0, @sub_table );
+ }
+ print OUTPUT "\n};\n\n";
+
print OUTPUT <<"EOF";
static const WCHAR *unicode_table_lookup( UINT cp, int compat, const BYTE *idx1, UINT scale_idx1,
const USHORT *idx2, UINT scale_idx2, const USHORT *offsets,
@@ -2513,6 +2764,20 @@ static const WCHAR *unicode_table_lookup( UINT cp, int compat, const BYTE *idx1,
return &data[d];
}
+static inline int reorderable_pair( WCHAR ch1, WCHAR ch2 )
+{
+ const WCHAR *cc1, *cc2;
+
+ if (ch1 == 0 || ch2 == 0) return 0;
+
+ cc1 = unicode_table_lookup( ch1, 0, idx1_comb, 8, idx2_comb, 4,
+ offsets_comb, 4, data_comb, 0 );
+ cc2 = unicode_table_lookup( ch2, 0, idx1_comb, 8, idx2_comb, 4,
+ offsets_comb, 4, data_comb, 0 );
+ if (*cc2 < *cc1) return 1;
+ else return 0;
+}
+
static int decompose_char_recursive( int compat, UINT ch, WCHAR *dst, int dstlen )
{
int total_decomp = 0;
@@ -2576,6 +2841,41 @@ int wine_unicode_decompose_string( int compat, const WCHAR *src,
return dstpos;
}
+
+int is_starter( WCHAR ch )
+{
+ const WCHAR *map = unicode_table_lookup( ch, 0, idx1_comb, 8, idx2_comb, 4,
+ offsets_comb, 4, data_comb, 0 );
+ return (*map == 0) ? 1 : 0;
+}
+
+void unicode_canon_order( WCHAR *str, int strlen )
+{
+ int i, j, m;
+ int sublen = 0, tot_sublen = 0;
+ WCHAR *substr = str;
+
+ for (m = 1; m <= strlen; m++)
+ {
+ if (m == strlen || is_starter( str[m] )) sublen = m - tot_sublen;
+ else continue;
+
+ for (i = 0; i < sublen; i++)
+ {
+ for (j = 1; j < sublen; j++)
+ {
+ if (reorderable_pair( substr[j-1], substr[j] ))
+ {
+ WCHAR swp = substr[j-1];
+ substr[j-1] = substr[j];
+ substr[j] = swp;
+ }
+ }
+ }
+ tot_sublen += m;
+ substr = str+m;
+ }
+}
EOF
close OUTPUT;
save_file($filename);
--
1.9.1

View File

@@ -1,183 +0,0 @@
From 91113cf4d4b65f961d9209d9508226094acad3ae Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sergio=20G=C3=B3mez=20Del=20Real?=
<sdelreal@codeweavers.com>
Date: Fri, 6 Apr 2018 10:29:39 -0500
Subject: [PATCH 3/4] kernel32: Implement NormalizeString API function.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Sergio GĂłmez Del Real <sdelreal@codeweavers.com>
---
dlls/kernel32/locale.c | 88 +++++++++++++++++++++++++++++++++++++++++---
dlls/kernel32/tests/locale.c | 44 ++++++++++------------
2 files changed, 103 insertions(+), 29 deletions(-)
diff --git a/dlls/kernel32/locale.c b/dlls/kernel32/locale.c
index 4d1eac6..607008f 100644
--- a/dlls/kernel32/locale.c
+++ b/dlls/kernel32/locale.c
@@ -5358,15 +5358,93 @@ INT WINAPI GetUserDefaultLocaleName(LPWSTR localename, int buffersize)
return LCIDToLocaleName(userlcid, localename, buffersize, 0);
}
+static inline int is_valid_norm(NORM_FORM norm)
+{
+ if (norm == NormalizationC || norm == NormalizationD ||
+ norm == NormalizationKC || norm == NormalizationKD)
+ return 1;
+ else
+ return 0;
+}
+
/******************************************************************************
* NormalizeString (KERNEL32.@)
+ *
+ * Normalizes a string according to a Unicode Normalization Form.
+ *
+ * PARAMS
+ * norm [I] Normalization Form
+ * src [I] Source string to normalize
+ * srclen [I] Length of source string (if -1, source string is null-terminated)
+ * dst [O] Buffer to write normalized source string (can be NULL)
+ * dstlen [I] Length of dst string (can be 0)
+ *
+ * RETURNS
+ * Success: If dstlen is 0, return size needed, else return size of normalized string.
+ * Failure: ret <= 0. Use GetLastError to determine error.
*/
-INT WINAPI NormalizeString(NORM_FORM NormForm, LPCWSTR lpSrcString, INT cwSrcLength,
- LPWSTR lpDstString, INT cwDstLength)
+INT WINAPI NormalizeString(NORM_FORM norm, LPCWSTR src, INT srclen,
+ LPWSTR dst, INT dstlen)
{
- FIXME("%x %p %d %p %d\n", NormForm, lpSrcString, cwSrcLength, lpDstString, cwDstLength);
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return 0;
+ extern int wine_unicode_decompose_string( int compat, const WCHAR *src,
+ int srclen, WCHAR *dst, int dstlen );
+ extern int unicode_canonical_composition( WCHAR *str, UINT strlen );
+ extern void unicode_canon_order( WCHAR *str, int strlen );
+
+ WCHAR *decomp = NULL;
+ INT compat = 0;
+ INT needed_len;
+
+ if (src == NULL || !is_valid_norm( norm ))
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return 0;
+ }
+
+ if (norm == NormalizationKC || norm == NormalizationKD) compat++;
+
+ if (srclen == -1) srclen = strlenW( src ) + 1;
+
+ needed_len = wine_unicode_decompose_string( compat, src, srclen, NULL, 0 );
+
+ if (needed_len < 0)
+ {
+ SetLastError(ERROR_NO_UNICODE_TRANSLATION);
+ return needed_len;
+ }
+
+ if (norm == NormalizationC || norm == NormalizationKC)
+ {
+ decomp = HeapAlloc( GetProcessHeap(), 0, needed_len * sizeof( WCHAR ) );
+ wine_unicode_decompose_string( compat, src, srclen, decomp, needed_len );
+ unicode_canon_order( decomp, needed_len );
+ needed_len = unicode_canonical_composition( decomp, needed_len );
+ }
+
+ if (dstlen < needed_len && dstlen > 0)
+ {
+ if (decomp) HeapFree(GetProcessHeap(), 0, decomp);
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ return -1;
+ }
+ else if (dstlen <= 0)
+ {
+ if (decomp) HeapFree(GetProcessHeap(), 0, decomp);
+ return needed_len;
+ }
+
+ if (norm == NormalizationC || norm == NormalizationKC)
+ {
+ memcpy( dst, decomp, sizeof(WCHAR) * needed_len );
+ HeapFree(GetProcessHeap(), 0, decomp);
+ return needed_len;
+ }
+ else
+ {
+ int decomp_len = wine_unicode_decompose_string( compat, src, srclen, dst, needed_len );
+ unicode_canon_order( dst, needed_len );
+ return decomp_len;
+ }
}
/******************************************************************************
diff --git a/dlls/kernel32/tests/locale.c b/dlls/kernel32/tests/locale.c
index d3eb2ec..50c3f07 100644
--- a/dlls/kernel32/tests/locale.c
+++ b/dlls/kernel32/tests/locale.c
@@ -5656,10 +5656,8 @@ static void test_NormalizeString(void)
return;
}
- todo_wine {
- dstlen = pNormalizeString( NormalizationD, ptest->str, -1, dst, 1 );
- ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Should have failed with ERROR_INSUFFICIENT_BUFFER\n");
- }
+ dstlen = pNormalizeString( NormalizationD, ptest->str, -1, dst, 1 );
+ ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Should have failed with ERROR_INSUFFICIENT_BUFFER");
/*
* For each string, first test passing -1 as srclen to NormalizeString,
@@ -5673,26 +5671,24 @@ static void test_NormalizeString(void)
for (i = 0; i < 4; i++)
{
- todo_wine {
- dstlen = pNormalizeString( norm_forms[i], ptest->str, -1, NULL, 0 );
- if (dstlen)
- {
- dstlen = pNormalizeString( norm_forms[i], ptest->str, -1, dst, dstlen );
- ok(dstlen == strlenW( ptest->expected[i] )+1, "Copied length differed: was %d, should be %d\n",
- dstlen, strlenW( ptest->expected[i] )+1);
- str_cmp = strncmpW( ptest->expected[i], dst, dstlen+1 );
- ok( str_cmp == 0, "test failed: returned value was %d\n", str_cmp );
- }
-
- dstlen = pNormalizeString( norm_forms[i], ptest->str, strlenW(ptest->str), NULL, 0 );
- if (dstlen)
- {
- dstlen = pNormalizeString( norm_forms[i], ptest->str, strlenW(ptest->str), dst, dstlen );
- ok(dstlen == strlenW( ptest->expected[i] ), "Copied length differed: was %d, should be %d\n",
- dstlen, strlenW( ptest->expected[i] ));
- str_cmp = strncmpW( ptest->expected[i], dst, dstlen );
- ok( str_cmp == 0, "test failed: returned value was %d\n", str_cmp );
- }
+ dstlen = pNormalizeString( norm_forms[i], ptest->str, -1, NULL, 0 );
+ if (dstlen)
+ {
+ dstlen = pNormalizeString( norm_forms[i], ptest->str, -1, dst, dstlen );
+ ok(dstlen == strlenW( ptest->expected[i] )+1, "Copied length differed: was %d, should be %d\n",
+ dstlen, strlenW( ptest->expected[i] )+1);
+ str_cmp = strncmpW( ptest->expected[i], dst, dstlen+1 );
+ ok( str_cmp == 0, "test failed: returned value was %d\n", str_cmp );
+ }
+
+ dstlen = pNormalizeString( norm_forms[i], ptest->str, strlenW(ptest->str), NULL, 0 );
+ if (dstlen)
+ {
+ dstlen = pNormalizeString( norm_forms[i], ptest->str, strlenW(ptest->str), dst, dstlen );
+ ok(dstlen == strlenW( ptest->expected[i] ), "Copied length differed: was %d, should be %d\n",
+ dstlen, strlenW( ptest->expected[i] ));
+ str_cmp = strncmpW( ptest->expected[i], dst, dstlen );
+ ok( str_cmp == 0, "test failed: returned value was %d\n", str_cmp );
}
}
ptest++;
--
1.9.1

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