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
bf859fb0
Commit
bf859fb0
authored
Dec 12, 2022
by
Zebediah Figura
Committed by
Alexandre Julliard
Feb 08, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
oleaut32: Manually construct a stub buffer for dispinterfaces.
Wine-Bug:
https://bugs.winehq.org/show_bug.cgi?id=53926
parent
aff181e6
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
127 additions
and
4 deletions
+127
-4
oleaut.c
dlls/oleaut32/oleaut.c
+112
-2
tmarshal.c
dlls/oleaut32/tests/tmarshal.c
+15
-2
No files found.
dlls/oleaut32/oleaut.c
View file @
bf859fb0
...
...
@@ -18,6 +18,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
...
...
@@ -34,6 +35,7 @@
#include "ole2.h"
#include "olectl.h"
#include "oleauto.h"
#include "rpcproxy.h"
#include "initguid.h"
#include "typelib.h"
#include "oleaut32_oaidl.h"
...
...
@@ -999,6 +1001,114 @@ static HRESULT dispatch_create_stub(IUnknown *server, IRpcStubBuffer **stub)
return
hr
;
}
struct
dispinterface_stub
{
CInterfaceStubVtbl
stub_vtbl
;
CStdStubBuffer
stub_buffer
;
};
static
struct
dispinterface_stub
*
impl_from_IRpcStubBuffer
(
IRpcStubBuffer
*
iface
)
{
return
CONTAINING_RECORD
(
&
iface
->
lpVtbl
,
struct
dispinterface_stub
,
stub_buffer
.
lpVtbl
);
}
static
ULONG
WINAPI
dispinterface_stub_Release
(
IRpcStubBuffer
*
iface
)
{
struct
dispinterface_stub
*
stub
=
impl_from_IRpcStubBuffer
(
iface
);
unsigned
int
refcount
=
InterlockedDecrement
(
&
stub
->
stub_buffer
.
RefCount
);
TRACE
(
"%p decreasing refcount to %u.
\n
"
,
stub
,
refcount
);
if
(
!
refcount
)
{
/* Copied from NdrCStdStubBuffer_Release(), but supposedly incorrect
* according to the comment there. */
IRpcStubBuffer_Disconnect
(
iface
);
free
(
stub
);
}
return
refcount
;
}
extern
const
ExtendedProxyFileInfo
oleaut32_oaidl_ProxyFileInfo
;
static
const
CInterfaceStubVtbl
*
find_idispatch_stub_vtbl
(
void
)
{
CInterfaceStubVtbl
*
const
*
vtbl
;
for
(
vtbl
=
oleaut32_oaidl_ProxyFileInfo
.
pStubVtblList
;
*
vtbl
;
++
vtbl
)
{
if
(
IsEqualGUID
((
*
vtbl
)
->
header
.
piid
,
&
IID_IDispatch
))
return
*
vtbl
;
}
assert
(
0
);
return
NULL
;
}
/* Normal dispinterfaces have an IID specified by the IDL compiler as DIID_*,
* but are otherwise identical to IDispatch. Unfortunately, such interfaces may
* not actually support IDispatch in QueryInterface.
*
* This becomes a problem, since CreateStub() was designed such that, for some
* reason, the caller need not actually pass the interface matching "iid". As
* such the standard rpcrt4 implementation will query the server for the
* relevant IID.
*
* This means that we cannot just pass IID_IDispatch with the object, even
* though it is in theory an IDispatch. However, while the standard stub
* constructor is not exported from rpcrt4, all of the vtbl methods are, and
* the type is public, so we *can* manually create it ourselves, bypassing the
* QueryInterface check.
*
* This relies on some rpcrt4 implementation details.
*/
static
HRESULT
dispinterface_create_stub
(
IUnknown
*
server
,
const
GUID
*
iid
,
IRpcStubBuffer
**
stub
)
{
const
CInterfaceStubVtbl
*
stub_vtbl
=
find_idispatch_stub_vtbl
();
struct
dispinterface_stub
*
object
;
void
*
dispatch
;
HRESULT
hr
;
if
(
!
(
object
=
calloc
(
1
,
sizeof
(
*
object
))))
return
E_OUTOFMEMORY
;
/* It's possible we can just assume that "server" is already the
* dispinterface type—we don't have tests for this—but since rpcrt4 queries
* (which we do have tests for) it makes sense for us to match that
* behaviour. */
if
(
FAILED
(
hr
=
IUnknown_QueryInterface
(
server
,
iid
,
&
dispatch
)))
{
ERR
(
"Object does not support interface %s.
\n
"
,
debugstr_guid
(
iid
));
free
(
object
);
return
hr
;
}
object
->
stub_vtbl
.
header
=
stub_vtbl
->
header
;
object
->
stub_vtbl
.
Vtbl
.
QueryInterface
=
CStdStubBuffer_QueryInterface
;
object
->
stub_vtbl
.
Vtbl
.
AddRef
=
CStdStubBuffer_AddRef
;
object
->
stub_vtbl
.
Vtbl
.
Release
=
dispinterface_stub_Release
;
object
->
stub_vtbl
.
Vtbl
.
Connect
=
CStdStubBuffer_Connect
;
object
->
stub_vtbl
.
Vtbl
.
Disconnect
=
CStdStubBuffer_Disconnect
;
object
->
stub_vtbl
.
Vtbl
.
Invoke
=
CStdStubBuffer_Invoke
;
object
->
stub_vtbl
.
Vtbl
.
IsIIDSupported
=
CStdStubBuffer_IsIIDSupported
;
object
->
stub_vtbl
.
Vtbl
.
CountRefs
=
CStdStubBuffer_CountRefs
;
object
->
stub_vtbl
.
Vtbl
.
DebugServerQueryInterface
=
CStdStubBuffer_DebugServerQueryInterface
;
object
->
stub_vtbl
.
Vtbl
.
DebugServerRelease
=
CStdStubBuffer_DebugServerRelease
;
object
->
stub_buffer
.
lpVtbl
=
&
object
->
stub_vtbl
.
Vtbl
;
object
->
stub_buffer
.
RefCount
=
1
;
object
->
stub_buffer
.
pvServerObject
=
dispatch
;
/* rpcrt4 will also fill pPSFactory, but it never uses it except in the
* Release method (which we reimplement). It's only to keep a reference to
* the module to implement NdrDllCanUnloadNow(). We use the default
* DllCanUnloadNow() from winecrt0, which always returns S_FALSE, so don't
* bother filling pPSFactory. */
TRACE
(
"Created stub %p.
\n
"
,
object
);
*
stub
=
(
IRpcStubBuffer
*
)
&
object
->
stub_buffer
.
lpVtbl
;
return
S_OK
;
}
static
HRESULT
WINAPI
dispatch_typelib_ps_CreateStub
(
IPSFactoryBuffer
*
iface
,
REFIID
iid
,
IUnknown
*
server
,
IRpcStubBuffer
**
stub
)
{
...
...
@@ -1022,10 +1132,10 @@ static HRESULT WINAPI dispatch_typelib_ps_CreateStub(IPSFactoryBuffer *iface,
if
(
attr
->
typekind
==
TKIND_INTERFACE
||
(
attr
->
wTypeFlags
&
TYPEFLAG_FDUAL
))
hr
=
CreateStubFromTypeInfo
(
typeinfo
,
iid
,
server
,
stub
);
else
hr
=
disp
atch_create_stub
(
server
,
stub
);
hr
=
disp
interface_create_stub
(
server
,
iid
,
stub
);
if
(
FAILED
(
hr
))
ERR
(
"Failed to create
proxy
, hr %#lx.
\n
"
,
hr
);
ERR
(
"Failed to create
stub
, hr %#lx.
\n
"
,
hr
);
ITypeInfo_ReleaseTypeAttr
(
typeinfo
,
attr
);
ITypeInfo_Release
(
typeinfo
);
...
...
dlls/oleaut32/tests/tmarshal.c
View file @
bf859fb0
...
...
@@ -17,6 +17,7 @@
*
*/
#include <stdbool.h>
#include <math.h>
#define COBJMACROS
...
...
@@ -394,6 +395,7 @@ struct disp_obj
{
ISomethingFromDispatch
ISomethingFromDispatch_iface
;
LONG
ref
;
bool
support_idispatch
;
};
static
inline
struct
disp_obj
*
impl_from_ISomethingFromDispatch
(
ISomethingFromDispatch
*
iface
)
...
...
@@ -403,6 +405,11 @@ static inline struct disp_obj *impl_from_ISomethingFromDispatch(ISomethingFromDi
static
HRESULT
WINAPI
disp_obj_QueryInterface
(
ISomethingFromDispatch
*
iface
,
REFIID
iid
,
void
**
out
)
{
struct
disp_obj
*
obj
=
impl_from_ISomethingFromDispatch
(
iface
);
if
(
!
obj
->
support_idispatch
)
ok
(
!
IsEqualGUID
(
iid
,
&
IID_IDispatch
),
"Expected no query for IDispatch.
\n
"
);
if
(
IsEqualGUID
(
iid
,
&
IID_IUnknown
)
||
IsEqualGUID
(
iid
,
&
IID_IDispatch
)
||
IsEqualGUID
(
iid
,
&
IID_ISomethingFromDispatch
)
||
IsEqualGUID
(
iid
,
&
DIID_ItestIF4
))
...
...
@@ -475,14 +482,20 @@ static const ISomethingFromDispatchVtbl disp_obj_vtbl =
disp_obj_anotherfn
,
};
static
ISomethingFromDispatch
*
create_disp_obj
(
void
)
static
ISomethingFromDispatch
*
create_disp_obj
2
(
bool
support_idispatch
)
{
struct
disp_obj
*
obj
=
CoTaskMemAlloc
(
sizeof
(
*
obj
));
obj
->
ISomethingFromDispatch_iface
.
lpVtbl
=
&
disp_obj_vtbl
;
obj
->
ref
=
1
;
obj
->
support_idispatch
=
support_idispatch
;
return
&
obj
->
ISomethingFromDispatch_iface
;
}
static
ISomethingFromDispatch
*
create_disp_obj
(
void
)
{
return
create_disp_obj2
(
true
);
}
struct
coclass_obj
{
ICoclass1
ICoclass1_iface
;
...
...
@@ -3710,7 +3723,7 @@ static void test_marshal_dispinterface(void)
{
static
const
LARGE_INTEGER
zero
;
ISomethingFromDispatch
*
disp_obj
=
create_disp_obj
(
);
ISomethingFromDispatch
*
disp_obj
=
create_disp_obj
2
(
false
);
ITypeInfo
*
typeinfo
=
NULL
;
IDispatch
*
proxy_disp
;
IStream
*
stream
;
...
...
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