Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
48606856
Commit
48606856
authored
Apr 23, 2024
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
rpcrt4: Fix stack alignment and by-value parameters for typelibs on ARM platforms.
parent
d07019e4
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
96 additions
and
60 deletions
+96
-60
ndr_typelib.c
dlls/rpcrt4/ndr_typelib.c
+96
-60
No files found.
dlls/rpcrt4/ndr_typelib.c
View file @
48606856
...
...
@@ -43,6 +43,7 @@ static size_t write_type_tfs(ITypeInfo *typeinfo, unsigned char *str,
do { if ((str)) *((short *)((str) + (len))) = (val); (len) += 2; } while (0)
#define WRITE_INT(str, len, val) \
do { if ((str)) *((int *)((str) + (len))) = (val); (len) += 4; } while (0)
#define ROUND_SIZE(size, alignment) (((size) + ((alignment) - 1)) & ~((alignment) - 1))
extern
const
ExtendedProxyFileInfo
ndr_types_ProxyFileInfo
;
...
...
@@ -145,17 +146,21 @@ static unsigned char get_basetype(ITypeInfo *typeinfo, TYPEDESC *desc)
}
}
static
unsigned
int
type_memsize
(
ITypeInfo
*
typeinfo
,
TYPEDESC
*
desc
)
static
unsigned
int
type_memsize
(
ITypeInfo
*
typeinfo
,
TYPEDESC
*
desc
,
unsigned
int
*
align_ret
)
{
unsigned
int
size
,
align
;
switch
(
desc
->
vt
)
{
case
VT_I1
:
case
VT_UI1
:
return
1
;
size
=
align
=
1
;
break
;
case
VT_I2
:
case
VT_UI2
:
case
VT_BOOL
:
return
2
;
size
=
align
=
2
;
break
;
case
VT_I4
:
case
VT_UI4
:
case
VT_R4
:
...
...
@@ -163,45 +168,52 @@ static unsigned int type_memsize(ITypeInfo *typeinfo, TYPEDESC *desc)
case
VT_UINT
:
case
VT_ERROR
:
case
VT_HRESULT
:
return
4
;
size
=
align
=
4
;
break
;
case
VT_I8
:
case
VT_UI8
:
case
VT_R8
:
case
VT_DATE
:
return
8
;
size
=
align
=
8
;
break
;
case
VT_BSTR
:
case
VT_SAFEARRAY
:
case
VT_PTR
:
case
VT_UNKNOWN
:
case
VT_DISPATCH
:
return
sizeof
(
void
*
);
size
=
align
=
sizeof
(
void
*
);
break
;
case
VT_VARIANT
:
return
sizeof
(
VARIANT
);
align
=
8
;
size
=
sizeof
(
VARIANT
);
break
;
case
VT_CARRAY
:
{
unsigned
int
size
=
type_memsize
(
typeinfo
,
&
desc
->
lpadesc
->
tdescElem
);
unsigned
int
i
;
size
=
type_memsize
(
typeinfo
,
&
desc
->
lpadesc
->
tdescElem
,
&
align
);
for
(
i
=
0
;
i
<
desc
->
lpadesc
->
cDims
;
i
++
)
size
*=
desc
->
lpadesc
->
rgbounds
[
i
].
cElements
;
return
size
;
break
;
}
case
VT_USERDEFINED
:
{
unsigned
int
size
=
0
;
ITypeInfo
*
refinfo
;
TYPEATTR
*
attr
;
ITypeInfo_GetRefTypeInfo
(
typeinfo
,
desc
->
hreftype
,
&
refinfo
);
ITypeInfo_GetTypeAttr
(
refinfo
,
&
attr
);
size
=
attr
->
cbSizeInstance
;
align
=
attr
->
cbAlignment
;
ITypeInfo_ReleaseTypeAttr
(
refinfo
,
attr
);
ITypeInfo_Release
(
refinfo
);
return
size
;
break
;
}
default:
FIXME
(
"unhandled type %u
\n
"
,
desc
->
vt
);
return
0
;
}
if
(
align_ret
)
*
align_ret
=
align
;
return
size
;
}
static
BOOL
type_pointer_is_iface
(
ITypeInfo
*
typeinfo
,
TYPEDESC
*
tdesc
)
...
...
@@ -400,16 +412,9 @@ static void write_struct_members(ITypeInfo *typeinfo, unsigned char *str,
ITypeInfo_GetVarDesc
(
typeinfo
,
i
,
&
desc
);
tdesc
=
&
desc
->
elemdescVar
.
tdesc
;
/* This may not match the intended alignment, but we don't have enough
* information to determine that. This should always give the correct
* layout. */
if
((
struct_offset
&
7
)
&&
!
(
desc
->
oInst
&
7
))
WRITE_CHAR
(
str
,
*
len
,
FC_ALIGNM8
);
else
if
((
struct_offset
&
3
)
&&
!
(
desc
->
oInst
&
3
))
WRITE_CHAR
(
str
,
*
len
,
FC_ALIGNM4
);
else
if
((
struct_offset
&
1
)
&&
!
(
desc
->
oInst
&
1
))
WRITE_CHAR
(
str
,
*
len
,
FC_ALIGNM2
);
struct_offset
=
desc
->
oInst
+
type_memsize
(
typeinfo
,
tdesc
);
if
(
struct_offset
!=
desc
->
oInst
)
WRITE_CHAR
(
str
,
*
len
,
FC_STRUCTPAD1
+
desc
->
oInst
-
struct_offset
-
1
);
struct_offset
=
desc
->
oInst
+
type_memsize
(
typeinfo
,
tdesc
,
NULL
);
if
((
basetype
=
get_basetype
(
typeinfo
,
tdesc
)))
WRITE_CHAR
(
str
,
*
len
,
basetype
);
...
...
@@ -570,7 +575,7 @@ static void write_complex_struct_tfs(ITypeInfo *typeinfo, unsigned char *str,
if
(
struct_offset
!=
desc
->
oInst
)
member_layout
++
;
/* alignment directive */
struct_offset
=
desc
->
oInst
+
type_memsize
(
typeinfo
,
tdesc
);
struct_offset
=
desc
->
oInst
+
type_memsize
(
typeinfo
,
tdesc
,
NULL
);
if
(
get_basetype
(
typeinfo
,
tdesc
))
member_layout
++
;
...
...
@@ -646,7 +651,7 @@ static size_t write_array_tfs(ITypeInfo *typeinfo, unsigned char *str,
}
else
{
size
*=
type_memsize
(
typeinfo
,
&
desc
->
tdescElem
);
size
*=
type_memsize
(
typeinfo
,
&
desc
->
tdescElem
,
NULL
);
WRITE_INT
(
str
,
*
len
,
size
);
}
...
...
@@ -846,15 +851,52 @@ static size_t write_type_tfs(ITypeInfo *typeinfo, unsigned char *str,
return
off
;
}
static
unsigned
short
get_stack_size
(
ITypeInfo
*
typeinfo
,
TYPEDESC
*
desc
)
static
unsigned
int
get_stack_size
(
ITypeInfo
*
typeinfo
,
TYPEDESC
*
desc
,
unsigned
int
*
align
,
int
*
by_value
)
{
#if defined(__i386__) || defined(__arm__)
if
(
desc
->
vt
==
VT_CARRAY
)
return
sizeof
(
void
*
);
return
(
type_memsize
(
typeinfo
,
desc
)
+
3
)
&
~
3
;
#else
return
sizeof
(
void
*
);
unsigned
int
size
=
*
align
=
sizeof
(
void
*
);
int
byval
=
1
;
switch
(
desc
->
vt
)
{
case
VT_R8
:
case
VT_I8
:
case
VT_UI8
:
case
VT_DATE
:
#ifdef __arm__
case
VT_R4
:
*
align
=
8
;
#endif
size
=
8
;
break
;
case
VT_PTR
:
case
VT_UNKNOWN
:
case
VT_DISPATCH
:
case
VT_CARRAY
:
byval
=
0
;
break
;
case
VT_VARIANT
:
case
VT_USERDEFINED
:
size
=
type_memsize
(
typeinfo
,
desc
,
align
);
break
;
default:
break
;
}
#ifdef __i386__
*
align
=
sizeof
(
void
*
);
#endif
if
(
byval
)
{
#ifdef __x86_64__
byval
=
(
size
==
1
||
size
==
2
||
size
==
4
||
size
==
8
);
#elif defined __aarch64__
byval
=
(
size
<=
16
);
#endif
}
if
(
!
byval
)
size
=
*
align
=
sizeof
(
void
*
);
else
if
(
*
align
<
sizeof
(
void
*
))
*
align
=
sizeof
(
void
*
);
if
(
by_value
)
*
by_value
=
byval
;
return
ROUND_SIZE
(
size
,
*
align
);
}
static
const
unsigned
short
MustSize
=
0x0001
;
...
...
@@ -894,7 +936,7 @@ static HRESULT get_param_pointer_info(ITypeInfo *typeinfo, TYPEDESC *tdesc, int
break
;
case
VT_CARRAY
:
*
flags
|=
IsSimpleRef
|
MustFree
;
*
server_size
=
type_memsize
(
typeinfo
,
tdesc
);
*
server_size
=
type_memsize
(
typeinfo
,
tdesc
,
NULL
);
*
tfs_tdesc
=
tdesc
;
break
;
case
VT_USERDEFINED
:
...
...
@@ -937,7 +979,7 @@ static HRESULT get_param_pointer_info(ITypeInfo *typeinfo, TYPEDESC *tdesc, int
*
flags
|=
IsSimpleRef
;
*
tfs_tdesc
=
tdesc
;
if
(
!
is_in
&&
is_out
)
*
server_size
=
type_memsize
(
typeinfo
,
tdesc
);
*
server_size
=
type_memsize
(
typeinfo
,
tdesc
,
NULL
);
if
((
*
basetype
=
get_basetype
(
typeinfo
,
tdesc
)))
*
flags
|=
IsBasetype
;
else
...
...
@@ -949,7 +991,7 @@ static HRESULT get_param_pointer_info(ITypeInfo *typeinfo, TYPEDESC *tdesc, int
}
static
HRESULT
get_param_info
(
ITypeInfo
*
typeinfo
,
TYPEDESC
*
tdesc
,
int
is_in
,
int
is_out
,
unsigned
short
*
server_size
,
unsigned
short
*
flags
,
int
is_out
,
int
by_val
,
unsigned
short
*
server_size
,
unsigned
short
*
flags
,
unsigned
char
*
basetype
,
TYPEDESC
**
tfs_tdesc
)
{
ITypeInfo
*
refinfo
;
...
...
@@ -966,15 +1008,10 @@ static HRESULT get_param_info(ITypeInfo *typeinfo, TYPEDESC *tdesc, int is_in,
switch
(
tdesc
->
vt
)
{
case
VT_VARIANT
:
#if !defined(__i386__) && !defined(__arm__)
*
flags
|=
IsSimpleRef
|
MustFree
;
break
;
#endif
/* otherwise fall through */
case
VT_BSTR
:
case
VT_SAFEARRAY
:
case
VT_CY
:
*
flags
|=
IsByValue
|
MustFree
;
*
flags
|=
(
by_val
?
IsByValue
:
IsSimpleRef
)
|
MustFree
;
break
;
case
VT_UNKNOWN
:
case
VT_DISPATCH
:
...
...
@@ -995,17 +1032,10 @@ static HRESULT get_param_info(ITypeInfo *typeinfo, TYPEDESC *tdesc, int is_in,
*
basetype
=
FC_ENUM32
;
break
;
case
TKIND_RECORD
:
#if defined(__i386__) || defined(__arm__)
*
flags
|=
IsByValue
|
MustFree
;
#else
if
(
attr
->
cbSizeInstance
<=
8
)
*
flags
|=
IsByValue
|
MustFree
;
else
*
flags
|=
IsSimpleRef
|
MustFree
;
#endif
*
flags
|=
(
by_val
?
IsByValue
:
IsSimpleRef
)
|
MustFree
;
break
;
case
TKIND_ALIAS
:
hr
=
get_param_info
(
refinfo
,
&
attr
->
tdescAlias
,
is_in
,
is_out
,
hr
=
get_param_info
(
refinfo
,
&
attr
->
tdescAlias
,
is_in
,
is_out
,
0
,
server_size
,
flags
,
basetype
,
tfs_tdesc
);
break
;
...
...
@@ -1046,7 +1076,8 @@ static HRESULT write_param_fs(ITypeInfo *typeinfo, unsigned char *type,
USHORT
param_flags
=
desc
->
paramdesc
.
wParamFlags
;
TYPEDESC
*
tdesc
=
&
desc
->
tdesc
,
*
tfs_tdesc
;
unsigned
short
server_size
;
unsigned
short
stack_size
=
get_stack_size
(
typeinfo
,
tdesc
);
int
byval
;
unsigned
int
align
,
stack_size
=
get_stack_size
(
typeinfo
,
tdesc
,
&
align
,
&
byval
);
unsigned
char
basetype
;
unsigned
short
flags
;
int
is_in
,
is_out
;
...
...
@@ -1056,7 +1087,7 @@ static HRESULT write_param_fs(ITypeInfo *typeinfo, unsigned char *type,
is_out
=
param_flags
&
PARAMFLAG_FOUT
;
is_in
=
(
param_flags
&
PARAMFLAG_FIN
)
||
(
!
is_out
&&
!
is_return
);
hr
=
get_param_info
(
typeinfo
,
tdesc
,
is_in
,
is_out
,
&
server_size
,
&
flags
,
hr
=
get_param_info
(
typeinfo
,
tdesc
,
is_in
,
is_out
,
byval
,
&
server_size
,
&
flags
,
&
basetype
,
&
tfs_tdesc
);
if
(
is_in
)
flags
|=
IsIn
;
...
...
@@ -1072,6 +1103,8 @@ static HRESULT write_param_fs(ITypeInfo *typeinfo, unsigned char *type,
if
(
SUCCEEDED
(
hr
))
{
*
stack_offset
=
ROUND_SIZE
(
*
stack_offset
,
align
);
WRITE_SHORT
(
proc
,
*
proclen
,
flags
);
WRITE_SHORT
(
proc
,
*
proclen
,
*
stack_offset
);
WRITE_SHORT
(
proc
,
*
proclen
,
basetype
?
basetype
:
off
);
...
...
@@ -1085,18 +1118,23 @@ static HRESULT write_param_fs(ITypeInfo *typeinfo, unsigned char *type,
static
void
write_proc_func_header
(
ITypeInfo
*
typeinfo
,
FUNCDESC
*
desc
,
WORD
proc_idx
,
unsigned
char
*
proc
,
size_t
*
proclen
)
{
unsigned
short
stack_size
=
2
*
sizeof
(
void
*
);
/* This + return
*/
unsigned
int
i
,
align
,
size
,
stack_size
=
sizeof
(
void
*
);
/* This
*/
#ifdef __x86_64__
unsigned
short
float_mask
=
0
;
unsigned
char
basetype
;
#endif
WORD
param_idx
;
for
(
i
=
0
;
i
<
desc
->
cParams
;
i
++
)
{
size
=
get_stack_size
(
typeinfo
,
&
desc
->
lprgelemdescParam
[
i
].
tdesc
,
&
align
,
NULL
);
stack_size
=
ROUND_SIZE
(
stack_size
,
align
);
stack_size
+=
size
;
}
stack_size
+=
sizeof
(
void
*
);
/* return */
WRITE_CHAR
(
proc
,
*
proclen
,
FC_AUTO_HANDLE
);
WRITE_CHAR
(
proc
,
*
proclen
,
Oi_OBJECT_PROC
|
Oi_OBJ_USE_V2_INTERPRETER
);
WRITE_SHORT
(
proc
,
*
proclen
,
proc_idx
);
for
(
param_idx
=
0
;
param_idx
<
desc
->
cParams
;
param_idx
++
)
stack_size
+=
get_stack_size
(
typeinfo
,
&
desc
->
lprgelemdescParam
[
param_idx
].
tdesc
);
WRITE_SHORT
(
proc
,
*
proclen
,
stack_size
);
WRITE_SHORT
(
proc
,
*
proclen
,
0
);
/* constant_client_buffer_size */
...
...
@@ -1113,13 +1151,11 @@ static void write_proc_func_header(ITypeInfo *typeinfo, FUNCDESC *desc,
WRITE_SHORT
(
proc
,
*
proclen
,
0
);
/* ServerCorrHint */
WRITE_SHORT
(
proc
,
*
proclen
,
0
);
/* NotifyIndex */
#ifdef __x86_64__
for
(
param_idx
=
0
;
param_idx
<
desc
->
cParams
&&
param_idx
<
3
;
param_idx
++
)
for
(
i
=
0
;
i
<
desc
->
cParams
&&
i
<
3
;
i
++
)
{
basetype
=
get_basetype
(
typeinfo
,
&
desc
->
lprgelemdescParam
[
param_idx
].
tdesc
);
if
(
basetype
==
FC_FLOAT
)
float_mask
|=
(
1
<<
((
param_idx
+
1
)
*
2
));
else
if
(
basetype
==
FC_DOUBLE
)
float_mask
|=
(
2
<<
((
param_idx
+
1
)
*
2
));
basetype
=
get_basetype
(
typeinfo
,
&
desc
->
lprgelemdescParam
[
i
].
tdesc
);
if
(
basetype
==
FC_FLOAT
)
float_mask
|=
(
1
<<
((
i
+
1
)
*
2
));
else
if
(
basetype
==
FC_DOUBLE
)
float_mask
|=
(
2
<<
((
i
+
1
)
*
2
));
}
WRITE_SHORT
(
proc
,
*
proclen
,
float_mask
);
#endif
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment