Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
August 2020
- 78 participants
- 1650 messages
Re: [PATCH 2/2] kernel32/tests: Remove registry entry left out during test.
by Zebediah Figura
On 8/31/20 4:38 AM, Carlos Rivera wrote:
> At least in some Windows the previous invokation to
> WritePrivateProfileStringA("section6", NULL, NULL, "winetest.ini")
> creates the entry HKEY_CURRENT_USER/winetest_name1. It seems
> that the IniFileMapping is cached somewhere, even if it has been
> removed from the registry.
>
> Signed-off-by: Carlos Rivera <carlos(a)superkaos.org>
> ---
> dlls/kernel32/tests/profile.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/dlls/kernel32/tests/profile.c b/dlls/kernel32/tests/profile.c
> index c077f8b35b..5f1f4f0fe7 100644
> --- a/dlls/kernel32/tests/profile.c
> +++ b/dlls/kernel32/tests/profile.c
> @@ -1567,6 +1567,8 @@ static void test_registry_mapping(void)
>
> ret = RegDeleteKeyA(HKEY_LOCAL_MACHINE, "Software\\winetest_name2");
> ok(!ret, "got error %u\n", ret);
> + ret = RegDeleteKeyA(HKEY_CURRENT_USER, "winetest_name1");
> + ok(!ret, "got error %u\n", ret);
> ret = RegDeleteKeyA(mapped_key, "");
> ok(!ret, "got error %u\n", ret);
> RegCloseKey(mapped_key);
>
Perhaps a better workaround would be to delete the "name1" value from
mapping_subkey after running the previous section? That one seems to
work for me with Windows 7.
Aug. 31, 2020
Re: [PATCH vkd3d v2 5/5] include: Document struct vkd3d_shader_interface_info.
by Henri Verbeet
On Fri, 28 Aug 2020 at 20:35, Zebediah Figura <z.figura12(a)gmail.com> wrote:
> +/**
> + * Describes the mapping of a range of Direct3D push constants to a constant
> + * buffer in the target environment.
> + *
> + * This structure is used in struct vkd3d_shader_interface_info.
> + */
> struct vkd3d_shader_push_constant_buffer
No, the other way around. In the shader you'd have e.g. "cb0", and on
the Vulkan side you'd have "vkCmdPushConstants(...);". (The Direct3D
12 equivalent would be a D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS
root signature parameter.)
Aug. 31, 2020
Re: [PATCH 1/2] kernel32/tests: Use debugstr_an to show contents of buffer.
by Zebediah Figura
Hello Carlos, thanks for the patch! I just have one comment inlined:
On 8/31/20 4:37 AM, Carlos Rivera wrote:
> In the tests modified the buffer to show is expected to contain
> strings separated by \0. So that passing the buffer to
> the ok macro will only print the first string. Showing the
> whole returned buffer gives more information when the test
> fails.
>
> Signed-off-by: Carlos Rivera <carlos(a)superkaos.org>
> ---
> dlls/kernel32/tests/profile.c | 19 ++++++++++++-------
> 1 file changed, 12 insertions(+), 7 deletions(-)
>
> diff --git a/dlls/kernel32/tests/profile.c b/dlls/kernel32/tests/profile.c
> index 2fba26542f..c077f8b35b 100644
> --- a/dlls/kernel32/tests/profile.c
> +++ b/dlls/kernel32/tests/profile.c
> @@ -591,8 +591,10 @@ static void test_GetPrivateProfileString(const char *content, const char *descri
> buf, MAX_PATH, filename);
> ok(ret == 18, "Expected 18, got %d\n", ret);
> len = lstrlenA("section1") + sizeof(CHAR) + lstrlenA("section2") + 2 * sizeof(CHAR);
> - ok(!memcmp(buf, "section1\0section2\0\0", len),
> - "Expected \"section1\\0section2\\0\\0\", got \"%s\"\n", buf);
> +
> + ok(!memcmp(buf, "section1\0section2\0", len),
> + "Expected \"section1\\x00section2\\x00\\x00\", got %s\n",
> + debugstr_an(buf, (ret + 2 >= MAX_PATH ? MAX_PATH : ret + 1)));
Checking for sanity like this strikes me as overkill; we can probably
expect the result from GetPrivateProfileString() to be sane.
Note also that if you do, encouraging use of sizeof(buf) seems like a
good idea, and you could also the min() macro to simplify the expression.
>
> /* lpAppName is empty */
> memset(buf, 0xc, sizeof(buf));
> @@ -667,7 +669,8 @@ static void test_GetPrivateProfileString(const char *content, const char *descri
> buf, MAX_PATH, filename);
> ok(ret == 18, "Expected 18, got %d\n", ret);
> ok(!memcmp(buf, "name1\0name2\0name4\0", ret + 1),
> - "Expected \"name1\\0name2\\0name4\\0\", got \"%s\"\n", buf);
> + "Expected \"name1\\x00name2\\x00name4\\x00\\x00\", got %s\n",
> + debugstr_an(buf, (ret + 2 >= MAX_PATH ? MAX_PATH : ret + 1)));
>
> /* lpKeyName is empty */
> memset(buf, 0xc,sizeof(buf));
> @@ -794,8 +797,9 @@ static void test_GetPrivateProfileString(const char *content, const char *descri
> ok(ret == 14, "Expected 14, got %d\n", ret);
> len = lstrlenA("section1") + 2 * sizeof(CHAR);
> todo_wine
> - ok(!memcmp(buf, "section1\0secti\0\0", ret + 2),
> - "Expected \"section1\\0secti\\0\\0\", got \"%s\"\n", buf);
> + ok(!memcmp(buf, "section1\0secti\0", ret + 2),
> + "Expected \"section1\\x00secti\\x00\\x00\", got %s\n",
> + debugstr_an(buf, (ret + 2 >= 16 ? 16 : ret + 1)));
>
> /* lpKeyName is NULL, not enough room for final key name */
> memset(buf, 0xc,sizeof(buf));
> @@ -804,8 +808,9 @@ static void test_GetPrivateProfileString(const char *content, const char *descri
> buf, 16, filename);
> ok(ret == 14, "Expected 14, got %d\n", ret);
> todo_wine
> - ok(!memcmp(buf, "name1\0name2\0na\0\0", ret + 2),
> - "Expected \"name1\\0name2\\0na\\0\\0\", got \"%s\"\n", buf);
> + ok(!memcmp(buf, "name1\0name2\0na\0", ret + 2),
> + "Expected \"name1\\x00name2\\x00na\\x00\\x00\", got %s\n",
> + debugstr_an(buf, (ret + 2 >= 16 ? 16 : ret + 1)));
>
> /* key value has quotation marks which are stripped */
> memset(buf, 0xc,sizeof(buf));
>
Aug. 31, 2020
Re: [PATCH v2] winmm: Pass a fullpath to CreateFileA
by Andrew Eikum
On Mon, Aug 31, 2020 at 05:33:58PM +1000, Alistair Leslie-Hughes wrote:
> diff --git a/dlls/winmm/tests/mmio.c b/dlls/winmm/tests/mmio.c
> index e3984fbaf3..0de51a2562 100644
> --- a/dlls/winmm/tests/mmio.c
> +++ b/dlls/winmm/tests/mmio.c
> @@ -478,6 +478,7 @@ static void test_mmioOpen_create(void)
> WCHAR cwd[MAX_PATH], temp_dir[MAX_PATH];
> /* According to docs, filename must be no more than 128 bytes, but it will
> * actually allow longer than that. */
> + WCHAR relpath[] = L"local\\examplefile";
> WCHAR filename[] = L"very_long_filename_"
> L"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
> L"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
> @@ -520,6 +521,14 @@ static void test_mmioOpen_create(void)
>
> DeleteFileW(filename);
>
> + CreateDirectoryA("local", NULL);
> + hmmio = mmioOpenW(relpath, NULL, MMIO_CREATE | MMIO_WRITE | MMIO_EXCLUSIVE);
> + ok(hmmio != NULL, "mmioOpen failed\n");
> + mmioClose(hmmio, 0);
> +
> + DeleteFileW(relpath);
> + RemoveDirectoryA("local");
> +
> SetCurrentDirectoryW(cwd);
> }
>
On my machine, this test passes without your changes to
<dlls/winmm/mmio.c> applied. This is what I'd expect, CreateFile
should find files that are relative to the CWD in the same was as
SearchPath, so your patch is a no-op in this test case. I think you
want to add a test showing that mmioOpen will open files elsewhere in
the system path, or whatever it is that the game is depending on.
Andrew
Aug. 31, 2020
Re: [PATCH v4 1/5] mfplat: Remove fallback media source.
by Derek Lesho
On 8/29/20 1:09 PM, Nikolay Sivov wrote:
>
> On 8/29/20 7:29 PM, Derek Lesho wrote:
>> On 8/29/20 1:30 AM, Nikolay Sivov wrote:
>>
>>> I was thinking we will be keeping this stub until winegstreamer changes
>>> are in and got tested enough. Not sure what the current situation is on
>>> macos, maybe we'll need this stub until we have a bridge to newer
>>> multimedia API, now that quicktime one is deprecated.
>>>
>>>
>> I'm fine with keeping or it or removing it. In my initial patch I
>> preserved it, at the expensive of uglier testing code. However,
>> what's the purpose of the stub in the first place? Do any
>> applications rely on it being present?
>>
> We either keep it until we have something better or remove it only to
> find out what breaks.
>
It seems unlikely that anything will break. I tested Disgaea, which the
hack was written for, and it works fine if lookup of the media source
fails. I think it would take a very strange application to not handle
the failure of creating a media source, yet gracefully handle failure
when interacting with the presentation descriptor. If anything, removing
the stub might improve compatibility.
Aug. 31, 2020
[v2 PATCH] server: Implement inherited handles list.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
Version 2 does not abuse startup info structure to pass handles,
adds tracing for new request data, along with other minor improvements.
dlls/ntdll/unix/process.c | 39 ++++++++++++++++++++++++++++++++++
include/wine/server_protocol.h | 5 +++--
server/handle.c | 38 +++++++++++++++++++++++++--------
server/handle.h | 3 ++-
server/process.c | 27 +++++++++++++++++------
server/process.h | 3 ++-
server/protocol.def | 2 ++
server/request.c | 2 +-
server/request.h | 1 +
server/trace.c | 2 ++
10 files changed, 102 insertions(+), 20 deletions(-)
diff --git a/dlls/ntdll/unix/process.c b/dlls/ntdll/unix/process.c
index 6b41080ceeb..f31a10459ea 100644
--- a/dlls/ntdll/unix/process.c
+++ b/dlls/ntdll/unix/process.c
@@ -774,6 +774,28 @@ done:
return status;
}
+static NTSTATUS alloc_handle_list( const PS_ATTRIBUTE *handles_attr, obj_handle_t **handles, data_size_t *handles_len )
+{
+ SIZE_T count, i;
+ HANDLE *src;
+
+ *handles = NULL;
+ *handles_len = 0;
+
+ if (!handles_attr) return STATUS_SUCCESS;
+
+ count = handles_attr->Size / sizeof(HANDLE);
+
+ if (!(*handles = calloc( sizeof(**handles), count ))) return STATUS_NO_MEMORY;
+
+ src = handles_attr->ValuePtr;
+ for (i = 0; i < count; ++i)
+ (*handles)[i] = wine_server_obj_handle( src[i] );
+
+ *handles_len = count * sizeof(**handles);
+
+ return STATUS_SUCCESS;
+}
/**********************************************************************
* NtCreateUserProcess (NTDLL.@)
@@ -799,6 +821,9 @@ NTSTATUS WINAPI NtCreateUserProcess( HANDLE *process_handle_ptr, HANDLE *thread_
HANDLE parent = 0, debug = 0, token = 0;
UNICODE_STRING path = {0};
SIZE_T i, attr_count = (attr->TotalLength - sizeof(attr->TotalLength)) / sizeof(PS_ATTRIBUTE);
+ const PS_ATTRIBUTE *handles_attr = NULL;
+ data_size_t handles_size;
+ obj_handle_t *handles;
for (i = 0; i < attr_count; i++)
{
@@ -817,6 +842,10 @@ NTSTATUS WINAPI NtCreateUserProcess( HANDLE *process_handle_ptr, HANDLE *thread_
case PS_ATTRIBUTE_TOKEN:
token = attr->Attributes[i].ValuePtr;
break;
+ case PS_ATTRIBUTE_HANDLE_LIST:
+ if (process_flags & PROCESS_CREATE_FLAGS_INHERIT_HANDLES)
+ handles_attr = &attr->Attributes[i];
+ break;
default:
if (attr->Attributes[i].Attribute & PS_ATTRIBUTE_INPUT)
FIXME( "unhandled input attribute %lx\n", attr->Attributes[i].Attribute );
@@ -845,12 +874,19 @@ NTSTATUS WINAPI NtCreateUserProcess( HANDLE *process_handle_ptr, HANDLE *thread_
if ((status = alloc_object_attributes( process_attr, &objattr, &attr_len ))) goto done;
+ if ((status = alloc_handle_list( handles_attr, &handles, &handles_size )))
+ {
+ free( objattr );
+ goto done;
+ }
+
/* create the socket for the new process */
if (socketpair( PF_UNIX, SOCK_STREAM, 0, socketfd ) == -1)
{
status = STATUS_TOO_MANY_OPENED_FILES;
free( objattr );
+ free( handles );
goto done;
}
#ifdef SO_PASSCRED
@@ -876,7 +912,9 @@ NTSTATUS WINAPI NtCreateUserProcess( HANDLE *process_handle_ptr, HANDLE *thread_
req->access = process_access;
req->cpu = pe_info.cpu;
req->info_size = startup_info_size;
+ req->handles_size = handles_size;
wine_server_add_data( req, objattr, attr_len );
+ wine_server_add_data( req, handles, handles_size );
wine_server_add_data( req, startup_info, startup_info_size );
wine_server_add_data( req, params->Environment, env_size );
if (!(status = wine_server_call( req )))
@@ -888,6 +926,7 @@ NTSTATUS WINAPI NtCreateUserProcess( HANDLE *process_handle_ptr, HANDLE *thread_
}
SERVER_END_REQ;
free( objattr );
+ free( handles );
if (status)
{
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index 98e4825439e..8058860a436 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -781,10 +781,11 @@ struct new_process_request
unsigned int access;
client_cpu_t cpu;
data_size_t info_size;
+ data_size_t handles_size;
/* VARARG(objattr,object_attributes); */
+ /* VARARG(handles,uints,handles_size); */
/* VARARG(info,startup_info,info_size); */
/* VARARG(env,unicode_str); */
- char __pad_44[4];
};
struct new_process_reply
{
@@ -6337,7 +6338,7 @@ union generic_reply
/* ### protocol_version begin ### */
-#define SERVER_PROTOCOL_VERSION 640
+#define SERVER_PROTOCOL_VERSION 641
/* ### protocol_version end ### */
diff --git a/server/handle.c b/server/handle.c
index 9ae99cd0c63..3ef7fb1bdb9 100644
--- a/server/handle.c
+++ b/server/handle.c
@@ -355,7 +355,8 @@ static void shrink_handle_table( struct handle_table *table )
/* copy the handle table of the parent process */
/* return 1 if OK, 0 on error */
-struct handle_table *copy_handle_table( struct process *process, struct process *parent )
+struct handle_table *copy_handle_table( struct process *process, struct process *parent,
+ const obj_handle_t *handles, unsigned int handle_count )
{
struct handle_table *parent_table = parent->handles;
struct handle_table *table;
@@ -364,18 +365,37 @@ struct handle_table *copy_handle_table( struct process *process, struct process
assert( parent_table );
assert( parent_table->obj.ops == &handle_table_ops );
- if (!(table = alloc_handle_table( process, parent_table->count )))
+ if (!(table = alloc_handle_table( process, handle_count ? handle_count : parent_table->count )))
return NULL;
- if ((table->last = parent_table->last) >= 0)
+ if (handles)
{
- struct handle_entry *ptr = table->entries;
- memcpy( ptr, parent_table->entries, (table->last + 1) * sizeof(struct handle_entry) );
- for (i = 0; i <= table->last; i++, ptr++)
+ struct handle_entry *dst, *src;
+ int j;
+
+ dst = table->entries;
+ memset( dst, 0, handle_count * sizeof(*dst) );
+
+ for (i = 0, j = 0; i < handle_count; i++)
+ {
+ src = get_handle( parent, handles[i] );
+ if (!src || !(src->access & RESERVED_INHERIT)) continue;
+ grab_object_for_handle( src->ptr );
+ dst[j++] = *src;
+ }
+ }
+ else
+ {
+ if ((table->last = parent_table->last) >= 0)
{
- if (!ptr->ptr) continue;
- if (ptr->access & RESERVED_INHERIT) grab_object_for_handle( ptr->ptr );
- else ptr->ptr = NULL; /* don't inherit this entry */
+ struct handle_entry *ptr = table->entries;
+ memcpy( ptr, parent_table->entries, (table->last + 1) * sizeof(struct handle_entry) );
+ for (i = 0; i <= table->last; i++, ptr++)
+ {
+ if (!ptr->ptr) continue;
+ if (ptr->access & RESERVED_INHERIT) grab_object_for_handle( ptr->ptr );
+ else ptr->ptr = NULL; /* don't inherit this entry */
+ }
}
}
/* attempt to shrink the table */
diff --git a/server/handle.h b/server/handle.h
index f1deb79fb5f..736fd360173 100644
--- a/server/handle.h
+++ b/server/handle.h
@@ -52,7 +52,8 @@ extern obj_handle_t enumerate_handles( struct process *process, const struct obj
unsigned int *index );
extern void close_process_handles( struct process *process );
extern struct handle_table *alloc_handle_table( struct process *process, int count );
-extern struct handle_table *copy_handle_table( struct process *process, struct process *parent );
+extern struct handle_table *copy_handle_table( struct process *process, struct process *parent,
+ const obj_handle_t *handles, unsigned int handle_count );
extern unsigned int get_handle_table_count( struct process *process);
#endif /* __WINE_SERVER_HANDLE_H */
diff --git a/server/process.c b/server/process.c
index c1bdb591f60..8206d8ad322 100644
--- a/server/process.c
+++ b/server/process.c
@@ -500,7 +500,8 @@ static void start_sigkill_timer( struct process *process )
/* create a new process */
/* if the function fails the fd is closed */
struct process *create_process( int fd, struct process *parent, int inherit_all,
- const struct security_descriptor *sd )
+ const struct security_descriptor *sd, const obj_handle_t *handles,
+ unsigned int handle_count )
{
struct process *process;
@@ -573,8 +574,9 @@ struct process *create_process( int fd, struct process *parent, int inherit_all,
else
{
process->parent_id = parent->id;
- process->handles = inherit_all ? copy_handle_table( process, parent )
+ process->handles = inherit_all ? copy_handle_table( process, parent, handles, handle_count )
: alloc_handle_table( process, 0 );
+
/* Note: for security reasons, starting a new process does not attempt
* to use the current impersonation token for the new process */
process->token = token_duplicate( parent->token, TRUE, 0, NULL );
@@ -1098,6 +1100,8 @@ DECL_HANDLER(new_process)
struct process *parent;
struct thread *parent_thread = current;
int socket_fd = thread_get_inflight_fd( current, req->socket_fd );
+ const obj_handle_t *handles = NULL;
+ data_size_t data_size;
if (socket_fd == -1)
{
@@ -1158,8 +1162,18 @@ DECL_HANDLER(new_process)
info->process = NULL;
info->data = NULL;
- info_ptr = get_req_data_after_objattr( objattr, &info->data_size );
- info->info_size = min( req->info_size, info->data_size );
+ info_ptr = get_req_data_after_objattr( objattr, &data_size );
+
+ if (req->handles_size)
+ {
+ if (req->handles_size < data_size)
+ handles = info_ptr;
+ info_ptr = (const char *)info_ptr + req->handles_size;
+ data_size -= req->handles_size;
+ }
+ info->data_size = data_size;
+
+ info->info_size = min( req->info_size, data_size );
if (req->info_size < sizeof(*info->data))
{
@@ -1199,7 +1213,8 @@ DECL_HANDLER(new_process)
#undef FIXUP_LEN
}
- if (!(process = create_process( socket_fd, parent, req->inherit_all, sd ))) goto done;
+ if (!(process = create_process( socket_fd, parent, req->inherit_all, sd, handles, req->handles_size / sizeof(*handles) )))
+ goto done;
process->startup_info = (struct startup_info *)grab_object( info );
@@ -1294,7 +1309,7 @@ DECL_HANDLER(exec_process)
close( socket_fd );
return;
}
- if (!(process = create_process( socket_fd, NULL, 0, NULL ))) return;
+ if (!(process = create_process( socket_fd, NULL, 0, NULL, NULL, 0 ))) return;
create_thread( -1, process, NULL );
release_object( process );
}
diff --git a/server/process.h b/server/process.h
index 0fdf070b78e..7facc4f6dfa 100644
--- a/server/process.h
+++ b/server/process.h
@@ -109,7 +109,8 @@ extern unsigned int alloc_ptid( void *ptr );
extern void free_ptid( unsigned int id );
extern void *get_ptid_entry( unsigned int id );
extern struct process *create_process( int fd, struct process *parent, int inherit_all,
- const struct security_descriptor *sd );
+ const struct security_descriptor *sd, const obj_handle_t *handles,
+ unsigned int handle_count );
extern data_size_t init_process( struct thread *thread );
extern struct thread *get_process_first_thread( struct process *process );
extern struct process *get_process_from_id( process_id_t id );
diff --git a/server/protocol.def b/server/protocol.def
index 6e92f86cc03..68dec5b594b 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -795,7 +795,9 @@ struct rawinput_device
unsigned int access; /* access rights for process object */
client_cpu_t cpu; /* CPU that the new process will use */
data_size_t info_size; /* size of startup info */
+ data_size_t handles_size; /* length of explicit handles list to inherit */
VARARG(objattr,object_attributes); /* object attributes */
+ VARARG(handles,uints,handles_size); /* handles list */
VARARG(info,startup_info,info_size); /* startup information */
VARARG(env,unicode_str); /* environment for new process */
@REPLY
diff --git a/server/request.c b/server/request.c
index 4c1f30a5fe7..8f3bad8701d 100644
--- a/server/request.c
+++ b/server/request.c
@@ -582,7 +582,7 @@ static void master_socket_poll_event( struct fd *fd, int event )
int client = accept( get_unix_fd( master_socket->fd ), (struct sockaddr *) &dummy, &len );
if (client == -1) return;
fcntl( client, F_SETFL, O_NONBLOCK );
- if ((process = create_process( client, NULL, 0, NULL )))
+ if ((process = create_process( client, NULL, 0, NULL, NULL, 0 )))
{
create_thread( -1, process, NULL );
release_object( process );
diff --git a/server/request.h b/server/request.h
index 5a602d3d816..ef52c5e6923 100644
--- a/server/request.h
+++ b/server/request.h
@@ -731,6 +731,7 @@ C_ASSERT( FIELD_OFFSET(struct new_process_request, exe_file) == 28 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, access) == 32 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, cpu) == 36 );
C_ASSERT( FIELD_OFFSET(struct new_process_request, info_size) == 40 );
+C_ASSERT( FIELD_OFFSET(struct new_process_request, handles_size) == 44 );
C_ASSERT( sizeof(struct new_process_request) == 48 );
C_ASSERT( FIELD_OFFSET(struct new_process_reply, info) == 8 );
C_ASSERT( FIELD_OFFSET(struct new_process_reply, pid) == 12 );
diff --git a/server/trace.c b/server/trace.c
index 93e53d2f42d..f973098c6a5 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -1288,7 +1288,9 @@ static void dump_new_process_request( const struct new_process_request *req )
fprintf( stderr, ", access=%08x", req->access );
dump_client_cpu( ", cpu=", &req->cpu );
fprintf( stderr, ", info_size=%u", req->info_size );
+ fprintf( stderr, ", handles_size=%u", req->handles_size );
dump_varargs_object_attributes( ", objattr=", cur_size );
+ dump_varargs_uints( ", handles=", min(cur_size,req->handles_size) );
dump_varargs_startup_info( ", info=", min(cur_size,req->info_size) );
dump_varargs_unicode_str( ", env=", cur_size );
}
--
2.28.0
Aug. 31, 2020
[PATCH 2/2] gdi32/tests: Test extended TTF font names and collisions.
by Rémi Bernon
This shows that although Windows is only matching family names up to
LF_FACESIZE chars, and that it doesn't match against the preferred /
typographic family names and styles, it still keeps the faces separate
when the full names don't match. Wine incorrectly discard one of them.
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
Just stumbled upon this while playing with fonts and fontconfig. Noto
fonts have a lot of collisions because of this, as they have all sorts
of density / weight / slant variations.
I don't have a fix yet, I'm not sure how to do it yet and I'd also like
to take the opportunity to clean the corresponding gdi32 code a bit.
I thought it could be nice to use the typographic / preferred family and
style names to enumerate and match them, as fontconfig does, but that's
not what Windows is doing, sadly.
It could be a host integration and user experience improvement though,
but it will require patching the font data before returning it, to pass
the other tests.
dlls/gdi32/tests/font.c | 70 +++++++++++++++++++
dlls/gdi32/tests/resource.rc | 6 ++
dlls/gdi32/tests/wine_ttfnames.sfd | 85 ++++++++++++++++++++++++
dlls/gdi32/tests/wine_ttfnames.ttf | Bin 0 -> 2232 bytes
dlls/gdi32/tests/wine_ttfnames_bold.sfd | 85 ++++++++++++++++++++++++
dlls/gdi32/tests/wine_ttfnames_bold.ttf | Bin 0 -> 2272 bytes
6 files changed, 246 insertions(+)
create mode 100644 dlls/gdi32/tests/wine_ttfnames.sfd
create mode 100644 dlls/gdi32/tests/wine_ttfnames.ttf
create mode 100644 dlls/gdi32/tests/wine_ttfnames_bold.sfd
create mode 100644 dlls/gdi32/tests/wine_ttfnames_bold.ttf
diff --git a/dlls/gdi32/tests/font.c b/dlls/gdi32/tests/font.c
index ad894dfdcad..a452b362228 100644
--- a/dlls/gdi32/tests/font.c
+++ b/dlls/gdi32/tests/font.c
@@ -6940,6 +6940,75 @@ static void test_long_names(void)
ReleaseDC(NULL, dc);
}
+static void test_ttf_names(void)
+{
+ struct enum_fullname_data efnd;
+ char ttf_name[MAX_PATH], ttf_name_bold[MAX_PATH];
+ LOGFONTA font = {0};
+ HFONT handle_font;
+ int ret;
+ HDC dc;
+
+ if (!write_ttf_file("wine_ttfnames.ttf", ttf_name))
+ {
+ skip("Failed to create ttf file for testing\n");
+ return;
+ }
+
+ if (!write_ttf_file("wine_ttfnames_bold.ttf", ttf_name_bold))
+ {
+ skip("Failed to create ttf file for testing\n");
+ DeleteFileA(ttf_name);
+ return;
+ }
+
+ ret = AddFontResourceExA(ttf_name, FR_PRIVATE, 0);
+ ok(ret, "AddFontResourceEx() failed\n");
+
+ ret = AddFontResourceExA(ttf_name_bold, FR_PRIVATE, 0);
+ ok(ret, "AddFontResourceEx() failed\n");
+
+ dc = GetDC(NULL);
+
+ strcpy(font.lfFaceName, "Wine_TTF_Names_Long_Family1_Con");
+ memset(&efnd, 0, sizeof(efnd));
+ EnumFontFamiliesExA(dc, &font, enum_fullname_data_proc, (LPARAM)&efnd, 0);
+ ok(efnd.total == 0, "EnumFontFamiliesExA must not find font.\n");
+
+ /* Windows doesn't match with Typographic/Preferred Family tags */
+ strcpy(font.lfFaceName, "Wine TTF Names Long Family1");
+ memset(&efnd, 0, sizeof(efnd));
+ EnumFontFamiliesExA(dc, &font, enum_fullname_data_proc, (LPARAM)&efnd, 0);
+ ok(efnd.total == 0, "EnumFontFamiliesExA must not find font.\n");
+
+ strcpy(font.lfFaceName, "Wine TTF Names Long Family1 Ext");
+ memset(&efnd, 0, sizeof(efnd));
+ EnumFontFamiliesExA(dc, &font, enum_fullname_data_proc, (LPARAM)&efnd, 0);
+ todo_wine
+ ok(efnd.total == 2, "EnumFontFamiliesExA found %d fonts, expected 2.\n", efnd.total);
+
+ strcpy(font.lfFaceName, "Wine TTF Names Long Family1 Con");
+ memset(&efnd, 0, sizeof(efnd));
+ EnumFontFamiliesExA(dc, &font, enum_fullname_data_proc, (LPARAM)&efnd, 0);
+ todo_wine
+ ok(efnd.total == 2, "EnumFontFamiliesExA found %d fonts, expected 2.\n", efnd.total);
+
+ handle_font = CreateFontIndirectA(&font);
+ ok(handle_font != NULL, "CreateFontIndirectA failed\n");
+ DeleteObject(handle_font);
+
+ ret = RemoveFontResourceExA(ttf_name_bold, FR_PRIVATE, 0);
+ ok(ret, "RemoveFontResourceEx() failed\n");
+
+ DeleteFileA(ttf_name_bold);
+
+ ret = RemoveFontResourceExA(ttf_name, FR_PRIVATE, 0);
+ ok(ret, "RemoveFontResourceEx() failed\n");
+
+ DeleteFileA(ttf_name);
+ ReleaseDC(NULL, dc);
+}
+
typedef struct
{
USHORT majorVersion;
@@ -7351,6 +7420,7 @@ START_TEST(font)
test_bitmap_font_glyph_index();
test_GetCharWidthI();
test_long_names();
+ test_ttf_names();
test_char_width();
/* These tests should be last test until RemoveFontResource
diff --git a/dlls/gdi32/tests/resource.rc b/dlls/gdi32/tests/resource.rc
index 6dcbd42ab52..b5a6107a987 100644
--- a/dlls/gdi32/tests/resource.rc
+++ b/dlls/gdi32/tests/resource.rc
@@ -31,3 +31,9 @@ vertical.ttf RCDATA vertical.ttf
/* @makedep: wine_longname.ttf */
wine_longname.ttf RCDATA wine_longname.ttf
+
+/* @makedep: wine_ttfnames.ttf */
+wine_ttfnames.ttf RCDATA wine_ttfnames.ttf
+
+/* @makedep: wine_ttfnames_bold.ttf */
+wine_ttfnames_bold.ttf RCDATA wine_ttfnames_bold.ttf
diff --git a/dlls/gdi32/tests/wine_ttfnames.sfd b/dlls/gdi32/tests/wine_ttfnames.sfd
new file mode 100644
index 00000000000..566749d19a7
--- /dev/null
+++ b/dlls/gdi32/tests/wine_ttfnames.sfd
@@ -0,0 +1,85 @@
+SplineFontDB: 3.2
+FontName: Wine_TTF_Names_Long_Family1_Cond_Regular
+FamilyName: Wine_TTF_Names_Long_Family1_Cond
+Weight: Regular
+Copyright: Copyright (c) 2020, Remi Bernon for CodeWeavers
+UComments: "2017-11-17: Created with FontForge (http://fontforge.org)"
+Version: 001.000
+ItalicAngle: 0
+UnderlinePosition: -102
+UnderlineWidth: 51
+Ascent: 819
+Descent: 205
+InvalidEm: 0
+LayerCount: 2
+Layer: 0 0 "Back" 1
+Layer: 1 0 "Fore" 0
+XUID: [1021 48 28337276 3092883]
+OS2Version: 0
+OS2_WeightWidthSlopeOnly: 0
+OS2_UseTypoMetrics: 1
+CreationTime: 1510948643
+ModificationTime: 1598865292
+OS2TypoAscent: 0
+OS2TypoAOffset: 1
+OS2TypoDescent: 0
+OS2TypoDOffset: 1
+OS2TypoLinegap: 0
+OS2WinAscent: 0
+OS2WinAOffset: 1
+OS2WinDescent: 0
+OS2WinDOffset: 1
+HheadAscent: 0
+HheadAOffset: 1
+HheadDescent: 0
+HheadDOffset: 1
+OS2Vendor: 'PfEd'
+MarkAttachClasses: 1
+DEI: 91125
+LangName: 1033 \
+ "" \
+ "Wine TTF Names Long Family1 Cond" \
+ "Regular" \
+ "" \
+ "Wine TTF Names Long Family1 Extremely Long Full Name Condensed" \
+ "" \
+ "" \
+ "" \
+ "" \
+ "" \
+ "" \
+ "" \
+ "" \
+ "" \
+ "" \
+ "" \
+ "Wine TTF Names Long Family1" \
+ "Condensed Regular" \
+
+Encoding: ISO8859-1
+UnicodeInterp: none
+NameList: AGL For New Fonts
+DisplaySize: -48
+AntiAlias: 1
+FitToEm: 0
+WinInfo: 64 16 4
+BeginPrivate: 0
+EndPrivate
+BeginChars: 256 1
+
+StartChar: at
+Encoding: 64 64 0
+Width: 1024
+VWidth: 0
+Flags: HW
+LayerCount: 2
+Fore
+SplineSet
+259 332 m 29
+ 468 664 l 29
+ 514 332 l 29
+ 259 332 l 29
+EndSplineSet
+EndChar
+EndChars
+EndSplineFont
diff --git a/dlls/gdi32/tests/wine_ttfnames.ttf b/dlls/gdi32/tests/wine_ttfnames.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..2eb2ad1f95e7bb384abe41bcf68f64da320fefb9
GIT binary patch
literal 2232
zcmdT`O>7%Q6#iy+?W8oKb_J*AFt|aaC_ft;MWu?6mDHvOQ>qXpJyhK+$@)jKcdfM(
zVhN-kdqAQW1eFk%-YVsgs22{1142S57eGR&px#j_Js>zi%{SwT?exH(xG>i2eDBSB
zZ{FX|8UnzRxCR^R#p22<Z-00-0!BX|cl_n^g(9BDQ>3pc`qkHFv#SaJ4M0>$uWvN`
zCQc;plm3=-abvqJk+H4=_Bi*Qir;E>yR?ka9nzzfdZ+x^-oDHIDbmeq;BTJ%;nphg
zkDT*WG7`s}1Z_=_o~Sn3J7W;flKz}@svd3lcpWR$m!zL)_&ZHpz>D0!Kw5@=BY3zw
z(d9n<cXpdmtKGeac^+Nj{_{|=a(=ygx$B)+_yxxuGJtPhcz8>#-^I-_WB|*uZj&5^
zrMMi_(VQzidCSt4dV9U6qd87rM`;Sp%VS21I25(a)7#%A5L4#;_(a)w~G77iDTp<!KWF@
z&;GbnE^M+sdF1U}H-{_Q6YW!9L_*Lrdd{fz6wJBGyPo65+XYg}@;HSgSBF1E=UF5D
z?0#w_A(Ddwgo;JY;c>*n;f(=S$N$fV?q&9k`kiGgmddfnvH~_nFtaBxyRbjv;6ZjT
znfQKT-?j*`XDfC>vG+%k;<tr;rtm>FmwqPwTrPb&BT_#d99Xx1U(Hx$niIAtvE$xX
zIToi#emNsbqV(vFO5RD_JFE$2v2L(n{k}5T!U(I~tA~yA;$4FsykuQAIDwS)k-<q!
z^6l)&r*O)C%iuK9_Q$G29My+cIeS<jj~fPCyeWP**v55n++YW9in|6UAg%WdPU4dF
zg~2Jz+XaKu$k;crga}P^5Tk|)s%SH+No?Q@*DPE;r-+vkpg|dlMWPrX^+Hl*t}$0-
zXOlZ?oIbX-Obb|wnw_{-skY_h#u=G)v+k5!4jMJN7{p-|%5oITrD!u)3;gXMrotM}
z2&pZ3!>pjl^&;&x$Y~Lm^r;o1qUP36r|)y5)%hVkz*;Q~<jP7>UgSm8lBFoD$fDn<
z)jM-MDWrr7rGhQ0`g9%3L1nA%6BM<Hwq9dOC?~SKI9#shI1gR(jBDPIYhK?q?=jcB
zzH8oNC-<!8=>9Ytd%B-)6r-?RjN(clvoo$dCsjxuL-KS;o(jn`A$ck!&xAnH+}!lp
zX_e-GpUDDt*ab1eS6Ns2J(_owxH@@<bs6M7U<F##`HLzPcG_{!2<jbEoUM9Y7fY8X
z2wMU5S7|1uv6`-lWDQ*AN!3FABn8+lH8zmz&ds>4OU{2?9^FZQC+&ly|5?-iS*!BR
zF%3OPYVRc+>ReTOoiDypriXcBn6E_l4sxUf=h5Mi6qGux*@EAl!IyN5|1;FSvY|A4
Q+WL9-*GHcyjp6U~A6<%D%m4rY
literal 0
HcmV?d00001
diff --git a/dlls/gdi32/tests/wine_ttfnames_bold.sfd b/dlls/gdi32/tests/wine_ttfnames_bold.sfd
new file mode 100644
index 00000000000..b3bf4ddfe90
--- /dev/null
+++ b/dlls/gdi32/tests/wine_ttfnames_bold.sfd
@@ -0,0 +1,85 @@
+SplineFontDB: 3.2
+FontName: Wine_TTF_Names_Long_Family1_Cond_Regular
+FamilyName: Wine_TTF_Names_Long_Family1_Cond
+Weight: Regular
+Copyright: Copyright (c) 2020, Remi Bernon for CodeWeavers
+UComments: "2017-11-17: Created with FontForge (http://fontforge.org)"
+Version: 001.000
+ItalicAngle: 0
+UnderlinePosition: -102
+UnderlineWidth: 51
+Ascent: 819
+Descent: 205
+InvalidEm: 0
+LayerCount: 2
+Layer: 0 0 "Back" 1
+Layer: 1 0 "Fore" 0
+XUID: [1021 48 28337276 3092883]
+OS2Version: 0
+OS2_WeightWidthSlopeOnly: 0
+OS2_UseTypoMetrics: 1
+CreationTime: 1510948643
+ModificationTime: 1598865292
+OS2TypoAscent: 0
+OS2TypoAOffset: 1
+OS2TypoDescent: 0
+OS2TypoDOffset: 1
+OS2TypoLinegap: 0
+OS2WinAscent: 0
+OS2WinAOffset: 1
+OS2WinDescent: 0
+OS2WinDOffset: 1
+HheadAscent: 0
+HheadAOffset: 1
+HheadDescent: 0
+HheadDOffset: 1
+OS2Vendor: 'PfEd'
+MarkAttachClasses: 1
+DEI: 91125
+LangName: 1033 \
+ "" \
+ "Wine TTF Names Long Family1 CondBold" \
+ "Regular" \
+ "" \
+ "Wine TTF Names Long Family1 Extremely Long Full Name Condensed Bold" \
+ "" \
+ "" \
+ "" \
+ "" \
+ "" \
+ "" \
+ "" \
+ "" \
+ "" \
+ "" \
+ "" \
+ "Wine TTF Names Long Family1" \
+ "Condensed Bold Regular" \
+
+Encoding: ISO8859-1
+UnicodeInterp: none
+NameList: AGL For New Fonts
+DisplaySize: -48
+AntiAlias: 1
+FitToEm: 0
+WinInfo: 64 16 4
+BeginPrivate: 0
+EndPrivate
+BeginChars: 256 1
+
+StartChar: at
+Encoding: 64 64 0
+Width: 1024
+VWidth: 0
+Flags: HW
+LayerCount: 2
+Fore
+SplineSet
+259 332 m 29
+ 468 664 l 29
+ 514 332 l 29
+ 259 332 l 29
+EndSplineSet
+EndChar
+EndChars
+EndSplineFont
diff --git a/dlls/gdi32/tests/wine_ttfnames_bold.ttf b/dlls/gdi32/tests/wine_ttfnames_bold.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..919a5ea1310dd95904d882afb56b95aaf94dc9be
GIT binary patch
literal 2272
zcmdT`O>7%Q6#iy+?W7Qqq~hn$9ELQA6eZ5aMxj(bL`h?M2yGRj<WhCB#2eevde>Sz
zA-)v}p&pRvjUpj_)C<ZjR_+`Ci9;?(2v9*iAc0i1g%g~h=9}@vPAY^7;=)+7?|X0F
zn|Xh`V+a6`;R<Z56$;BQzxDp*80i0u(vg?WE)?(t9w+~?;xD{1m0d~suK}V=er>(#
z*D#pAL;hRNx%I7v#He)@ut&J=l>B<F-R92d|B!rtDQs?hzT0xSK0&@#4*cTr+c#E-
z?{dzRDM%f2Qrv5d{8+i#*dBm*hWr=ghr)Q>$E#STy(Irg)!(k+9A4!5Ir1{{tHC>&
z*AuS4$K$`L#q~z}7G`*KgX_;h#mf1{&IcE~!Thgy)S&?Q`uSgODEeJe8^9=FS=J8O
zeppJ%K^rZ()X}#ry;Enc^K`Vt>Dnkup=GnkXcdPl*TC4UcddO&-tJIw2RU(!Ql$7a
zL;2Yq7dIA)xPn>C+PQWPm$WC^r>=^Gpl9@)QR^v~bCq{JM~t_5a%$%hDoIj(a)KgG|o
zM*7+Q)M!Gadj|*=i<*bW5f2Y9^sqYqe?D|Cvv1VzG-I(;jzyLgu+fLiuE12j)#u<|
zb~l~+KHst}LhRZ~oKoUeUt0X0Z!v}Uvbo`>ho8+2pBxoKKkx5bJAbT<S{vL>*kX|#
zcU|RJoFMyUMl6cO`+F*R$8qbRCYZvS!2)BrX|RPpF=()jv*IIz9n4#i!6^(`Um2Xn
zxc!2`LpWhyH+UFN+CQicaa12(=Img>H|(0h7QYngeO5X)u8OA&cJQY7$>0>E)iOAZ
zi`I_(a)4`Ie$Gk6#i_8#UDqlP9DR8T(a)04R+-?)^Un73s=tx;w1#AQb%HrC_zNKh};Hg
zLaO#Da%Gj%$ClQq1M_jMnN&*Uh8$l%C9`hUosdgGwIb(&B#I-s5hrp!E(WWCzZE1j
zSmhZJttG!O%P5eZ=YCa6>cors)DlraODhQJ`!soVenb!ENJCPrR-!;IFBjx_evs;N
zF^)>I;8!bQbDAec#kn}7mI|wcO`7-&14}_^GxP}xdb(a)_E2{n{MS$;%Z(leX~ZhFQ|
z?~t2b*G=yMH@&W#-UBChcFi%ANjCXpH}xpQQKJwir9fsgt~?`ESRTXjbXcAW%QInl
zDlE^0K-Jvz<mpM3(a)_(Pz1#Gh;5{9oTpmKe*1}bqOWd}9t)gfRt>a;0x^`UCAu-!<4
zY7jO}sW!t<mrfTei0VO6c1pIwT@&tI(It{BiOaO9(x{&VR(a)g`t_Ll2TXI$5%<iD<#
zZmx%^LhtB**3W;}y?m)mum4q!J8$ZtmR3#COCMi8)8PlVNqY}DerE*d(V;FeL9LTo
gEO<ZlZrlO>A5rV-MpBj?YyG_W+x<_J#o_z>Pvq`pzyJUM
literal 0
HcmV?d00001
--
2.28.0
Aug. 31, 2020
[PATCH 1/2] gdi32: Only trace new faces when they are added.
by Rémi Bernon
Instead of every time they don't match another face.
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/gdi32/freetype.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c
index f82a8c1641f..38d59e3fd9b 100644
--- a/dlls/gdi32/freetype.c
+++ b/dlls/gdi32/freetype.c
@@ -1574,12 +1574,11 @@ static BOOL insert_face_in_family_list( Face *face, Family *family )
return TRUE;
}
}
- else
- TRACE("Adding new %s\n", debugstr_w(face->file));
if (style_order( face ) < style_order( cursor )) break;
}
+ TRACE("Adding new %s\n", debugstr_w(face->file));
list_add_before( &cursor->entry, &face->entry );
face->family = family;
family->refcount++;
--
2.28.0
Aug. 31, 2020
[PATCH 2/2] msvcrt: Check for NULL type in dump_exception_type().
by Paul Gofman
Signed-off-by: Paul Gofman <pgofman(a)codeweavers.com>
---
dlls/msvcrt/except_x86_64.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/dlls/msvcrt/except_x86_64.c b/dlls/msvcrt/except_x86_64.c
index 09eddfb9793..d201ff59bbd 100644
--- a/dlls/msvcrt/except_x86_64.c
+++ b/dlls/msvcrt/except_x86_64.c
@@ -118,9 +118,17 @@ static inline void dump_type(UINT type_rva, ULONG64 base)
static void dump_exception_type(const cxx_exception_type *type, ULONG64 base)
{
- const cxx_type_info_table *type_info_table = rva_to_ptr(type->type_info_table, base);
+ const cxx_type_info_table *type_info_table;
UINT i;
+ if (!type)
+ {
+ TRACE("NULL type\n");
+ return;
+ }
+
+ type_info_table = rva_to_ptr(type->type_info_table, base);
+
TRACE("flags %x destr %x(%p) handler %x(%p) type info %x(%p)\n",
type->flags, type->destructor, rva_to_ptr(type->destructor, base),
type->custom_handler, rva_to_ptr(type->custom_handler, base),
--
2.26.2
Aug. 31, 2020