You've already forked wine-staging
mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2025-04-13 14:42:51 -07:00
Compare commits
22 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
b1b1abafe7 | ||
|
0b57832a15 | ||
|
b080509a3b | ||
|
4d363d04f9 | ||
|
7cbbfd0a9e | ||
|
27ff0169ed | ||
|
32bac8b64c | ||
|
b8de62375f | ||
|
697fe8b5da | ||
|
c6aeba1397 | ||
|
3d74da6622 | ||
|
ecc4fe6d6a | ||
|
35f9449641 | ||
|
f605d79997 | ||
|
ab89820aa5 | ||
|
f85accadd5 | ||
|
533cbe994f | ||
|
9f5a34bcb8 | ||
|
ca3bfa28f9 | ||
|
3dab9e5e6b | ||
|
1edb7d5bc5 | ||
|
0f48c0caac |
@@ -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
|
||||
|
||||
|
@@ -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 );
|
||||
}
|
||||
}
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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 @@
|
||||
|
@@ -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
|
||||
|
@@ -1 +0,0 @@
|
||||
Fixes: [42704] Implement BCryptDeriveKeyPBKDF2
|
File diff suppressed because it is too large
Load Diff
@@ -1 +0,0 @@
|
||||
Fixes: [45312] Fix issue for Assassin's Creed : Syndicate
|
@@ -1,2 +1 @@
|
||||
Fixes: [46564] Add BCryptDestroySecret/BCryptSecretAgreement stubs.
|
||||
Depends: bcrypt-BCryptGenerateKeyPair
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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
|
||||
|
10
patches/ddraw-version-check/definition
Normal file
10
patches/ddraw-version-check/definition
Normal 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
|
@@ -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
|
||||
|
104
patches/gdi32-rotation/0002-gdi32-fix-for-rotated-ellipse.patch
Normal file
104
patches/gdi32-rotation/0002-gdi32-fix-for-rotated-ellipse.patch
Normal 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
|
||||
|
2
patches/gdi32-rotation/definition
Normal file
2
patches/gdi32-rotation/definition
Normal 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
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
Reference in New Issue
Block a user