Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
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-cw
Commits
963ac3f0
Commit
963ac3f0
authored
Jan 26, 2005
by
Robert Shearman
Committed by
Alexandre Julliard
Jan 26, 2005
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
- Implement IRemUnknown.
- Use IRemUnknown for life-cycle management instead of the current hacks.
parent
407d863a
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
321 additions
and
6 deletions
+321
-6
marshal.c
dlls/ole32/marshal.c
+104
-4
rpc.c
dlls/ole32/rpc.c
+5
-1
stubmanager.c
dlls/ole32/stubmanager.c
+207
-0
marshal.c
dlls/ole32/tests/marshal.c
+5
-1
No files found.
dlls/ole32/marshal.c
View file @
963ac3f0
...
...
@@ -168,6 +168,7 @@ HRESULT register_ifstub(APARTMENT *apt, STDOBJREF *stdobjref, REFIID riid, IUnkn
/* Client-side identity of the server object */
static
HRESULT
proxy_manager_get_remunknown
(
struct
proxy_manager
*
This
,
IRemUnknown
**
remunk
);
static
void
proxy_manager_destroy
(
struct
proxy_manager
*
This
);
static
HRESULT
proxy_manager_find_ifproxy
(
struct
proxy_manager
*
This
,
REFIID
riid
,
struct
ifproxy
**
ifproxy_found
);
...
...
@@ -236,6 +237,9 @@ static const IInternalUnknownVtbl ClientIdentity_Vtbl =
static
HRESULT
ifproxy_get_public_ref
(
struct
ifproxy
*
This
)
{
/* FIXME: as this call could possibly be going over the network, we
* are going to spend a long time in this CS. We might want to replace
* this with a mutex */
EnterCriticalSection
(
&
This
->
parent
->
cs
);
if
(
This
->
refs
==
0
)
{
...
...
@@ -269,20 +273,40 @@ static HRESULT ifproxy_get_public_ref(struct ifproxy * This)
static
HRESULT
ifproxy_release_public_refs
(
struct
ifproxy
*
This
)
{
HRESULT
hr
=
S_OK
;
/* FIXME: as this call could possibly be going over the network, we
* are going to spend a long time in this CS. We might want to replace
* this with a mutex */
EnterCriticalSection
(
&
This
->
parent
->
cs
);
/*
if
(
This
->
refs
>
0
)
{
// FIXME: call IRemUnknown::RemRelease
IRemUnknown
*
remunk
=
NULL
;
TRACE
(
"releasing %ld refs
\n
"
,
This
->
refs
);
hr
=
proxy_manager_get_remunknown
(
This
->
parent
,
&
remunk
);
if
(
hr
==
S_OK
)
{
REMINTERFACEREF
rif
;
rif
.
ipid
=
This
->
ipid
;
rif
.
cPublicRefs
=
This
->
refs
;
rif
.
cPrivateRefs
=
0
;
hr
=
IRemUnknown_RemRelease
(
remunk
,
1
,
&
rif
);
if
(
hr
==
S_OK
)
This
->
refs
=
0
;
else
ERR
(
"IRemUnknown_RemRelease failed with error 0x%08lx
\n
"
,
hr
);
}
}
*/
LeaveCriticalSection
(
&
This
->
parent
->
cs
);
return
S_OK
;
return
hr
;
}
static
void
ifproxy_disconnect
(
struct
ifproxy
*
This
)
{
ifproxy_release_public_refs
(
This
);
IRpcProxyBuffer_Disconnect
(
This
->
proxy
);
}
...
...
@@ -327,12 +351,23 @@ static HRESULT proxy_manager_construct(
This
->
refs
=
1
;
This
->
sorflags
=
sorflags
;
/* the DCOM draft specification states that the SORF_NOPING flag is
* proxy manager specific, not ifproxy specific, so this implies that we
* should store the STDOBJREF flags in the proxy manager. */
This
->
sorflags
=
sorflags
;
This
->
chan
=
channel
;
/* FIXME: we should take the binding strings and construct the channel in this function */
/* we create the IRemUnknown proxy on demand */
This
->
remunk
=
NULL
;
EnterCriticalSection
(
&
apt
->
cs
);
list_add_head
(
&
apt
->
proxies
,
&
This
->
entry
);
LeaveCriticalSection
(
&
apt
->
cs
);
TRACE
(
"%p created for OXID %s, OID %s
\n
"
,
This
,
wine_dbgstr_longlong
(
oxid
),
wine_dbgstr_longlong
(
oid
));
*
proxy_manager
=
This
;
return
S_OK
;
}
...
...
@@ -442,10 +477,65 @@ static void proxy_manager_disconnect(struct proxy_manager * This)
LeaveCriticalSection
(
&
This
->
cs
);
}
static
HRESULT
proxy_manager_get_remunknown
(
struct
proxy_manager
*
This
,
IRemUnknown
**
remunk
)
{
HRESULT
hr
=
S_OK
;
/* we don't want to try and unmarshal or use IRemUnknown if we don't want
* lifetime management */
if
(
This
->
sorflags
&
SORFP_NOLIFETIMEMGMT
)
return
S_FALSE
;
EnterCriticalSection
(
&
This
->
cs
);
if
(
This
->
remunk
)
/* already created - return existing object */
*
remunk
=
This
->
remunk
;
else
if
(
!
This
->
parent
)
/* disconnected - we can't create IRemUnknown */
hr
=
S_FALSE
;
else
{
STDOBJREF
stdobjref
;
/* Don't want IRemUnknown lifetime management as this is IRemUnknown!
* We also don't care about whether or not the stub is still alive */
stdobjref
.
flags
=
SORFP_NOLIFETIMEMGMT
|
SORF_NOPING
;
stdobjref
.
cPublicRefs
=
1
;
/* oxid of destination object */
stdobjref
.
oxid
=
This
->
oxid
;
/* FIXME: what should be used for the oid? The DCOM draft doesn't say */
stdobjref
.
oid
=
(
OID
)
-
1
;
/* FIXME: this is a hack around not having an OXID resolver yet -
* the OXID resolver should give us the IPID of the IRemUnknown
* interface */
stdobjref
.
ipid
.
Data1
=
0xffffffff
;
stdobjref
.
ipid
.
Data2
=
0xffff
;
stdobjref
.
ipid
.
Data3
=
0xffff
;
assert
(
sizeof
(
stdobjref
.
ipid
.
Data4
)
==
sizeof
(
stdobjref
.
oxid
));
memcpy
(
&
stdobjref
.
ipid
.
Data4
,
&
stdobjref
.
oxid
,
sizeof
(
OXID
));
/* do the unmarshal */
hr
=
unmarshal_object
(
&
stdobjref
,
This
->
parent
,
&
IID_IRemUnknown
,
(
void
**
)
&
This
->
remunk
);
if
(
hr
==
S_OK
)
*
remunk
=
This
->
remunk
;
}
LeaveCriticalSection
(
&
This
->
cs
);
TRACE
(
"got IRemUnknown* pointer %p, hr = 0x%08lx
\n
"
,
*
remunk
,
hr
);
return
hr
;
}
/* destroys a proxy manager, freeing the memory it used.
* Note: this function should not be called from a list iteration in the
* apartment, due to the fact that it removes itself from the apartment and
* it could add a proxy to IRemUnknown into the apartment. */
static
void
proxy_manager_destroy
(
struct
proxy_manager
*
This
)
{
struct
list
*
cursor
;
TRACE
(
"oxid = %s, oid = %s
\n
"
,
wine_dbgstr_longlong
(
This
->
oxid
),
wine_dbgstr_longlong
(
This
->
oid
));
if
(
This
->
parent
)
{
EnterCriticalSection
(
&
This
->
parent
->
cs
);
...
...
@@ -470,6 +560,7 @@ static void proxy_manager_destroy(struct proxy_manager * This)
ifproxy_destroy
(
ifproxy
);
}
if
(
This
->
remunk
)
IRemUnknown_Release
(
This
->
remunk
);
if
(
This
->
chan
)
IRpcChannelBuffer_Release
(
This
->
chan
);
DeleteCriticalSection
(
&
This
->
cs
);
...
...
@@ -593,6 +684,7 @@ StdMarshalImpl_MarshalInterface(
}
start_apartment_listener_thread
();
/* just to be sure we have one running. */
start_apartment_remote_unknown
();
IUnknown_QueryInterface
((
LPUNKNOWN
)
pv
,
riid
,
(
LPVOID
*
)
&
pUnk
);
...
...
@@ -630,6 +722,14 @@ static HRESULT unmarshal_object(const STDOBJREF *stdobjref, APARTMENT *apt, REFI
struct
proxy_manager
*
proxy_manager
=
NULL
;
HRESULT
hr
=
S_OK
;
assert
(
apt
);
TRACE
(
"stdobjref:
\n\t
flags = %04lx
\n\t
cPublicRefs = %ld
\n\t
oxid = %s
\n\t
oid = %s
\n\t
ipid = %s
\n
"
,
stdobjref
->
flags
,
stdobjref
->
cPublicRefs
,
wine_dbgstr_longlong
(
stdobjref
->
oxid
),
wine_dbgstr_longlong
(
stdobjref
->
oid
),
debugstr_guid
(
&
stdobjref
->
ipid
));
/* create an a new proxy manager if one doesn't already exist for the
* object */
if
(
!
find_proxy_manager
(
apt
,
stdobjref
->
oxid
,
stdobjref
->
oid
,
&
proxy_manager
))
...
...
dlls/ole32/rpc.c
View file @
963ac3f0
...
...
@@ -291,15 +291,18 @@ static ULONG WINAPI
PipeBuf_Release
(
LPRPCCHANNELBUFFER
iface
)
{
PipeBuf
*
This
=
(
PipeBuf
*
)
iface
;
ULONG
ref
;
#if 0
struct disconnect_header header;
HANDLE pipe;
DWORD reqtype = REQTYPE_DISCONNECT;
DWORD magic;
#endif
ref
=
InterlockedDecrement
(
&
This
->
ref
);
if
(
ref
)
return
ref
;
#if 0 /* no longer needed now we've got IRemUnknown ref counting */
memcpy(&header.mid, &This->mid, sizeof(wine_marshal_id));
pipe = PIPE_FindByMID(&This->mid);
...
...
@@ -313,7 +316,8 @@ PipeBuf_Release(LPRPCCHANNELBUFFER iface) {
* necessary for real dcom but the test suite needs it */
read_pipe(pipe, &magic, sizeof(magic));
if
(
magic
!=
0xcafebabe
)
ERR
(
"bad disconnection magic: expecting 0xcafebabe but got 0x%lx"
,
magic
);
if (magic != 0xcafebabe) ERR("bad disconnection magic: expecting 0xcafebabe but got 0x%lx\n", magic);
#endif
HeapFree
(
GetProcessHeap
(),
0
,
This
);
return
0
;
...
...
dlls/ole32/stubmanager.c
View file @
963ac3f0
...
...
@@ -458,4 +458,211 @@ BOOL stub_manager_is_table_marshaled(struct stub_manager *m, const IPID *ipid)
return
ret
;
}
/*****************************************************************************
*
* IRemUnknown implementation
*
*
* Note: this object is not related to the lifetime of a stub_manager, but it
* interacts with stub managers.
*/
const
IID
IID_IRemUnknown
=
{
0x00000131
,
0
,
0
,
{
0xc0
,
0
,
0
,
0
,
0
,
0
,
0
,
0x46
}
};
typedef
struct
rem_unknown
{
const
IRemUnknownVtbl
*
lpVtbl
;
ULONG
refs
;
}
RemUnknown
;
static
const
IRemUnknownVtbl
RemUnknown_Vtbl
;
/* construct an IRemUnknown object with one outstanding reference */
static
HRESULT
RemUnknown_Construct
(
IRemUnknown
**
ppRemUnknown
)
{
RemUnknown
*
This
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
This
));
if
(
!
This
)
return
E_OUTOFMEMORY
;
This
->
lpVtbl
=
&
RemUnknown_Vtbl
;
This
->
refs
=
1
;
*
ppRemUnknown
=
(
IRemUnknown
*
)
This
;
return
S_OK
;
}
static
HRESULT
WINAPI
RemUnknown_QueryInterface
(
IRemUnknown
*
iface
,
REFIID
riid
,
void
**
ppv
)
{
TRACE
(
"(%p)->(%s, %p)
\n
"
,
iface
,
debugstr_guid
(
riid
),
ppv
);
if
(
IsEqualIID
(
riid
,
&
IID_IUnknown
)
||
IsEqualIID
(
riid
,
&
IID_IRemUnknown
))
{
*
ppv
=
(
LPVOID
)
iface
;
IRemUnknown_AddRef
(
iface
);
return
S_OK
;
}
FIXME
(
"No interface for iid %s
\n
"
,
debugstr_guid
(
riid
));
*
ppv
=
NULL
;
return
E_NOINTERFACE
;
}
static
ULONG
WINAPI
RemUnknown_AddRef
(
IRemUnknown
*
iface
)
{
ULONG
refs
;
RemUnknown
*
This
=
(
RemUnknown
*
)
iface
;
refs
=
InterlockedIncrement
(
&
This
->
refs
);
TRACE
(
"%p before: %ld
\n
"
,
iface
,
refs
-
1
);
return
refs
;
}
static
ULONG
WINAPI
RemUnknown_Release
(
IRemUnknown
*
iface
)
{
ULONG
refs
;
RemUnknown
*
This
=
(
RemUnknown
*
)
iface
;
refs
=
InterlockedDecrement
(
&
This
->
refs
);
if
(
!
refs
)
HeapFree
(
GetProcessHeap
(),
0
,
This
);
TRACE
(
"%p after: %ld
\n
"
,
iface
,
refs
);
return
refs
;
}
static
HRESULT
WINAPI
RemUnknown_RemQueryInterface
(
IRemUnknown
*
iface
,
REFIPID
ripid
,
ULONG
cRefs
,
USHORT
cIids
,
IID
*
iids
/* [size_is(cIids)] */
,
REMQIRESULT
**
ppQIResults
/* [size_is(,cIids)] */
)
{
HRESULT
hr
;
USHORT
i
;
APARTMENT
*
apt
;
struct
stub_manager
*
stubmgr
;
TRACE
(
"(%p)->(%s, %ld, %d, %p, %p)
\n
"
,
iface
,
debugstr_guid
(
ripid
),
cRefs
,
cIids
,
iids
,
ppQIResults
);
hr
=
ipid_to_stub_manager
(
ripid
,
&
apt
,
&
stubmgr
);
if
(
hr
!=
S_OK
)
return
hr
;
*
ppQIResults
=
CoTaskMemAlloc
(
sizeof
(
REMQIRESULT
)
*
cIids
);
for
(
i
=
0
;
i
<
cIids
;
i
++
)
{
(
*
ppQIResults
)[
i
].
hResult
=
register_ifstub
(
apt
,
&
(
*
ppQIResults
)[
i
].
std
,
&
iids
[
i
],
stubmgr
->
object
,
MSHLFLAGS_NORMAL
);
}
stub_manager_int_release
(
stubmgr
);
COM_ApartmentRelease
(
apt
);
return
hr
;
}
static
HRESULT
WINAPI
RemUnknown_RemAddRef
(
IRemUnknown
*
iface
,
USHORT
cInterfaceRefs
,
REMINTERFACEREF
*
InterfaceRefs
/* [size_is(cInterfaceRefs)] */
,
HRESULT
*
pResults
/* [size_is(cInterfaceRefs)] */
)
{
HRESULT
hr
=
S_OK
;
USHORT
i
;
TRACE
(
"(%p)->(%d, %p, %p)
\n
"
,
iface
,
cInterfaceRefs
,
InterfaceRefs
,
pResults
);
for
(
i
=
0
;
i
<
cInterfaceRefs
;
i
++
)
{
APARTMENT
*
apt
;
struct
stub_manager
*
stubmgr
;
pResults
[
i
]
=
ipid_to_stub_manager
(
&
InterfaceRefs
[
i
].
ipid
,
&
apt
,
&
stubmgr
);
if
(
pResults
[
i
]
!=
S_OK
)
{
hr
=
S_FALSE
;
continue
;
}
stub_manager_ext_addref
(
stubmgr
,
InterfaceRefs
[
i
].
cPublicRefs
);
if
(
InterfaceRefs
[
i
].
cPrivateRefs
)
FIXME
(
"Adding %ld refs securely not implemented
\n
"
,
InterfaceRefs
[
i
].
cPrivateRefs
);
stub_manager_int_release
(
stubmgr
);
COM_ApartmentRelease
(
apt
);
}
return
hr
;
}
static
HRESULT
WINAPI
RemUnknown_RemRelease
(
IRemUnknown
*
iface
,
USHORT
cInterfaceRefs
,
REMINTERFACEREF
*
InterfaceRefs
/* [size_is(cInterfaceRefs)] */
)
{
HRESULT
hr
=
S_OK
;
USHORT
i
;
TRACE
(
"(%p)->(%d, %p)
\n
"
,
iface
,
cInterfaceRefs
,
InterfaceRefs
);
for
(
i
=
0
;
i
<
cInterfaceRefs
;
i
++
)
{
APARTMENT
*
apt
;
struct
stub_manager
*
stubmgr
;
hr
=
ipid_to_stub_manager
(
&
InterfaceRefs
[
i
].
ipid
,
&
apt
,
&
stubmgr
);
if
(
hr
!=
S_OK
)
{
hr
=
E_INVALIDARG
;
/* FIXME: we should undo any changes already made in this function */
break
;
}
stub_manager_ext_release
(
stubmgr
,
InterfaceRefs
[
i
].
cPublicRefs
);
if
(
InterfaceRefs
[
i
].
cPrivateRefs
)
FIXME
(
"Releasing %ld refs securely not implemented
\n
"
,
InterfaceRefs
[
i
].
cPrivateRefs
);
stub_manager_int_release
(
stubmgr
);
COM_ApartmentRelease
(
apt
);
}
return
hr
;
}
static
const
IRemUnknownVtbl
RemUnknown_Vtbl
=
{
RemUnknown_QueryInterface
,
RemUnknown_AddRef
,
RemUnknown_Release
,
RemUnknown_RemQueryInterface
,
RemUnknown_RemAddRef
,
RemUnknown_RemRelease
};
/* starts the IRemUnknown listener for the current apartment */
HRESULT
start_apartment_remote_unknown
()
{
IRemUnknown
*
pRemUnknown
;
HRESULT
hr
=
S_OK
;
APARTMENT
*
apt
=
COM_CurrentApt
();
EnterCriticalSection
(
&
apt
->
cs
);
if
(
!
apt
->
remunk_exported
)
{
/* create the IRemUnknown object */
hr
=
RemUnknown_Construct
(
&
pRemUnknown
);
if
(
hr
==
S_OK
)
{
STDOBJREF
stdobjref
;
/* dummy - not used */
/* register it with the stub manager */
hr
=
register_ifstub
(
COM_CurrentApt
(),
&
stdobjref
,
&
IID_IRemUnknown
,
(
IUnknown
*
)
pRemUnknown
,
MSHLFLAGS_NORMAL
);
/* release our reference to the object as the stub manager will manage the life cycle for us */
IRemUnknown_Release
(
pRemUnknown
);
if
(
hr
==
S_OK
)
apt
->
remunk_exported
=
TRUE
;
}
}
LeaveCriticalSection
(
&
apt
->
cs
);
return
hr
;
}
dlls/ole32/tests/marshal.c
View file @
963ac3f0
...
...
@@ -65,6 +65,7 @@ static HRESULT WINAPI Test_IUnknown_QueryInterface(
return
S_OK
;
}
*
ppvObj
=
NULL
;
return
E_NOINTERFACE
;
}
...
...
@@ -105,6 +106,7 @@ static HRESULT WINAPI Test_IClassFactory_QueryInterface(
return
S_OK
;
}
*
ppvObj
=
NULL
;
return
E_NOINTERFACE
;
}
...
...
@@ -801,7 +803,9 @@ static void test_message_filter()
IClassFactory_Release
(
cf
);
ok_no_locks
();
/* FIXME: this is a regression caused by the fact that I faked the
* IUnknown unmarshaling too much and didn't give it its own ifstub. */
todo_wine
{
ok_no_locks
();
}
end_host_object
(
tid
,
thread
);
}
...
...
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