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
db6db7cb
Commit
db6db7cb
authored
Feb 15, 2005
by
Robert Shearman
Committed by
Alexandre Julliard
Feb 15, 2005
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Make COM use the RPC runtime as the backend for RPC calls. Based on a
patch by Ove Kåven.
parent
a9a1d610
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
350 additions
and
628 deletions
+350
-628
compobj.c
dlls/ole32/compobj.c
+0
-2
compobj_private.h
dlls/ole32/compobj_private.h
+4
-2
marshal.c
dlls/ole32/marshal.c
+3
-0
rpc.c
dlls/ole32/rpc.c
+341
-624
stubmanager.c
dlls/ole32/stubmanager.c
+2
-0
No files found.
dlls/ole32/compobj.c
View file @
db6db7cb
...
...
@@ -32,8 +32,6 @@
* of registered class objects: ISCM::ServerRegisterClsid et al
* - Implement the OXID resolver so we don't need magic pipe names for
* clients and servers to meet up
* - Flip our marshalling on top of the RPC runtime transport API,
* so we no longer use named pipes to communicate
*
* - Make all ole interface marshaling use NDR to be wire compatible with
* native DCOM
...
...
dlls/ole32/compobj_private.h
View file @
db6db7cb
...
...
@@ -197,9 +197,11 @@ IRpcStubBuffer *mid_to_stubbuffer(wine_marshal_id *mid);
void
start_apartment_listener_thread
(
void
);
extern
HRESULT
PIPE_GetNewPipeBuf
(
wine_marshal_id
*
mid
,
IRpcChannelBuffer
**
pipebuf
);
void
RPC_StartLocalServer
(
REFCLSID
clsid
,
IStream
*
stream
);
HRESULT
PIPE_GetNewPipeBuf
(
wine_marshal_id
*
mid
,
IRpcChannelBuffer
**
pipebuf
);
HRESULT
RPC_ExecuteCall
(
RPCOLEMESSAGE
*
msg
,
IRpcStubBuffer
*
stub
);
HRESULT
RPC_RegisterInterface
(
REFIID
riid
);
void
RPC_UnregisterInterface
(
REFIID
riid
);
void
RPC_StartLocalServer
(
REFCLSID
clsid
,
IStream
*
stream
);
/* This function initialize the Running Object Table */
HRESULT
WINAPI
RunningObjectTableImpl_Initialize
(
void
);
...
...
dlls/ole32/marshal.c
View file @
db6db7cb
...
...
@@ -153,6 +153,9 @@ HRESULT register_ifstub(APARTMENT *apt, STDOBJREF *stdobjref, REFIID riid, IUnkn
stub_manager_ext_addref
(
manager
,
1
);
}
/* FIXME: check return value */
RPC_RegisterInterface
(
riid
);
stdobjref
->
ipid
=
ifstub
->
ipid
;
stub_manager_int_release
(
manager
);
...
...
dlls/ole32/rpc.c
View file @
db6db7cb
/*
* (Local) RPC Stuff
*
* Copyright 2001 Ove Kven, TransGaming Technologies
* Copyright 2002 Marcus Meissner
* Copyright 2005 Mike Hearn, Rob Shearman for CodeWeavers
*
...
...
@@ -49,446 +50,449 @@
WINE_DEFAULT_DEBUG_CHANNEL
(
ole
);
#define PIPEPREF "\\\\.\\pipe\\"
#define OLESTUBMGR PIPEPREF"WINE_OLE_StubMgr"
static
void
__RPC_STUB
dispatch_rpc
(
RPC_MESSAGE
*
msg
);
#define REQTYPE_REQUEST 0
#define REQTYPE_RESPONSE 1
/* we only use one function to dispatch calls for all methods - we use the
* RPC_IF_OLE flag to tell the RPC runtime that this is the case */
static
RPC_DISPATCH_FUNCTION
rpc_dispatch_table
[
1
]
=
{
dispatch_rpc
};
/* (RO) */
static
RPC_DISPATCH_TABLE
rpc_dispatch
=
{
1
,
rpc_dispatch_table
};
/* (RO) */
struct
request_header
static
struct
list
registered_interfaces
=
LIST_INIT
(
registered_interfaces
);
/* (CS csRegIf) */
static
CRITICAL_SECTION
csRegIf
;
static
CRITICAL_SECTION_DEBUG
csRegIf_debug
=
{
DWORD
reqid
;
IPID
ipid
;
DWORD
iMethod
;
DWORD
cbBuffer
;
0
,
0
,
&
csRegIf
,
{
&
csRegIf_debug
.
ProcessLocksList
,
&
csRegIf_debug
.
ProcessLocksList
},
0
,
0
,
{
0
,
(
DWORD
)(
__FILE__
": dcom registered server interfaces"
)
}
};
static
CRITICAL_SECTION
csRegIf
=
{
&
csRegIf_debug
,
-
1
,
0
,
0
,
0
,
0
};
static
WCHAR
wszPipeTransport
[]
=
{
'n'
,
'c'
,
'a'
,
'c'
,
'n'
,
'_'
,
'n'
,
'p'
,
0
};
struct
response_header
struct
registered_if
{
DWORD
reqid
;
DWORD
cbBuffer
;
DWORD
retval
;
struct
list
entry
;
DWORD
refs
;
/* ref count */
RPC_SERVER_INTERFACE
If
;
/* interface registered with the RPC runtime */
};
/* get the pipe endpoint specified of the specified apartment */
static
inline
void
get_rpc_endpoint
(
LPWSTR
endpoint
,
const
OXID
*
oxid
)
{
/* FIXME: should get endpoint from rpcss */
static
const
WCHAR
wszEndpointFormat
[]
=
{
'\\'
,
'p'
,
'i'
,
'p'
,
'e'
,
'\\'
,
'O'
,
'L'
,
'E'
,
'_'
,
'%'
,
'0'
,
'8'
,
'l'
,
'x'
,
'%'
,
'0'
,
'8'
,
'l'
,
'x'
,
0
};
wsprintfW
(
endpoint
,
wszEndpointFormat
,
(
DWORD
)(
*
oxid
>>
32
),(
DWORD
)
*
oxid
);
}
#define REQSTATE_START 0
#define REQSTATE_REQ_QUEUED 1
#define REQSTATE_REQ_WAITING_FOR_REPLY 2
#define REQSTATE_REQ_GOT 3
#define REQSTATE_INVOKING 4
#define REQSTATE_RESP_QUEUED 5
#define REQSTATE_RESP_GOT 6
#define REQSTATE_DONE 6
typedef
struct
{
const
IRpcChannelBufferVtbl
*
lpVtbl
;
DWORD
refs
;
}
RpcChannelBuffer
;
struct
rpc
typedef
struct
{
int
state
;
HANDLE
hPipe
;
/* temp copy of handle */
struct
request_header
reqh
;
struct
response_header
resph
;
LPBYTE
Buffer
;
};
RpcChannelBuffer
super
;
/* superclass */
/* fixme: this should have a lock */
static
struct
rpc
**
reqs
=
NULL
;
static
int
nrofreqs
=
0
;
RPC_BINDING_HANDLE
bind
;
/* handle to the remote server */
}
ClientRpcChannelBuffer
;
/* This pipe is _thread_ based, each thread which talks to a remote
* apartment (oxid) has its own pipe. The same structure is used both
* for outgoing and incoming RPCs.
*/
struct
pipe
static
HRESULT
WINAPI
RpcChannelBuffer_QueryInterface
(
LPRPCCHANNELBUFFER
iface
,
REFIID
riid
,
LPVOID
*
ppv
)
{
wine_marshal_id
mid
;
/* target mid */
DWORD
tid
;
/* thread which owns this pipe */
HANDLE
hPipe
;
*
ppv
=
NULL
;
if
(
IsEqualIID
(
riid
,
&
IID_IRpcChannelBuffer
)
||
IsEqualIID
(
riid
,
&
IID_IUnknown
))
{
*
ppv
=
(
LPVOID
)
iface
;
IUnknown_AddRef
(
iface
);
return
S_OK
;
}
return
E_NOINTERFACE
;
}
int
pending
;
HANDLE
hThread
;
CRITICAL_SECTION
crit
;
static
ULONG
WINAPI
RpcChannelBuffer_AddRef
(
LPRPCCHANNELBUFFER
iface
)
{
RpcChannelBuffer
*
This
=
(
RpcChannelBuffer
*
)
iface
;
return
InterlockedIncrement
(
&
This
->
refs
);
}
APARTMENT
*
apt
;
/* apartment of the marshalling thread for the stub dispatch case */
};
static
ULONG
WINAPI
ServerRpcChannelBuffer_Release
(
LPRPCCHANNELBUFFER
iface
)
{
RpcChannelBuffer
*
This
=
(
RpcChannelBuffer
*
)
iface
;
ULONG
ref
;
typedef
struct
_PipeBuf
{
IRpcChannelBufferVtbl
*
lpVtbl
;
DWORD
ref
;
ref
=
InterlockedDecrement
(
&
This
->
refs
);
if
(
ref
)
return
ref
;
wine_marshal_id
mid
;
HANDLE
pipe
;
}
PipeBuf
;
HeapFree
(
GetProcessHeap
(),
0
,
This
)
;
return
0
;
}
static
ULONG
WINAPI
ClientRpcChannelBuffer_Release
(
LPRPCCHANNELBUFFER
iface
)
{
ClientRpcChannelBuffer
*
This
=
(
ClientRpcChannelBuffer
*
)
iface
;
ULONG
ref
;
ref
=
InterlockedDecrement
(
&
This
->
super
.
refs
);
if
(
ref
)
return
ref
;
/* some helper functions */
RpcBindingFree
(
&
This
->
bind
);
HeapFree
(
GetProcessHeap
(),
0
,
This
);
return
0
;
}
static
HRESULT
WINAPI
read_pipe
(
HANDLE
hf
,
LPVOID
ptr
,
DWORD
size
)
static
HRESULT
WINAPI
ServerRpcChannelBuffer_GetBuffer
(
LPRPCCHANNELBUFFER
iface
,
RPCOLEMESSAGE
*
olemsg
,
REFIID
riid
)
{
DWORD
res
;
RpcChannelBuffer
*
This
=
(
RpcChannelBuffer
*
)
iface
;
RPC_MESSAGE
*
msg
=
(
RPC_MESSAGE
*
)
olemsg
;
RPC_STATUS
status
;
if
(
!
ReadFile
(
hf
,
ptr
,
size
,
&
res
,
NULL
))
{
ERR
(
"Failed to read from %p, le is %ld
\n
"
,
hf
,
GetLastError
());
return
E_FAIL
;
}
TRACE
(
"(%p)->(%p,%p)
\n
"
,
This
,
olemsg
,
riid
);
if
(
res
!=
size
)
{
if
(
!
res
)
{
WARN
(
"%p disconnected
\n
"
,
hf
);
return
RPC_E_DISCONNECTED
;
}
ERR
(
"Read only %ld of %ld bytes from %p.
\n
"
,
res
,
size
,
hf
);
return
E_FAIL
;
}
return
S_OK
;
}
status
=
I_RpcGetBuffer
(
msg
);
static
HRESULT
WINAPI
write_pipe
(
HANDLE
hf
,
LPVOID
ptr
,
DWORD
size
)
{
DWORD
res
;
if
(
!
WriteFile
(
hf
,
ptr
,
size
,
&
res
,
NULL
))
{
FIXME
(
"Failed to write to %p, le is %ld
\n
"
,
hf
,
GetLastError
());
return
E_FAIL
;
}
if
(
res
!=
size
)
{
FIXME
(
"Wrote only %ld of %ld bytes to %p.
\n
"
,
res
,
size
,
hf
);
return
E_FAIL
;
}
return
S_OK
;
TRACE
(
"-- %ld
\n
"
,
status
);
return
HRESULT_FROM_WIN32
(
status
);
}
static
H
ANDLE
dupe_handle
(
HANDLE
h
)
static
H
RESULT
WINAPI
ClientRpcChannelBuffer_GetBuffer
(
LPRPCCHANNELBUFFER
iface
,
RPCOLEMESSAGE
*
olemsg
,
REFIID
riid
)
{
HANDLE
h2
;
ClientRpcChannelBuffer
*
This
=
(
ClientRpcChannelBuffer
*
)
iface
;
RPC_MESSAGE
*
msg
=
(
RPC_MESSAGE
*
)
olemsg
;
RPC_CLIENT_INTERFACE
*
cif
;
RPC_STATUS
status
;
if
(
!
DuplicateHandle
(
GetCurrentProcess
(),
h
,
GetCurrentProcess
(),
&
h2
,
0
,
FALSE
,
DUPLICATE_SAME_ACCESS
))
{
ERR
(
"could not duplicate handle: %ld
\n
"
,
GetLastError
());
return
INVALID_HANDLE_VALUE
;
}
TRACE
(
"(%p)->(%p,%p)
\n
"
,
This
,
olemsg
,
riid
);
return
h2
;
}
cif
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
sizeof
(
RPC_CLIENT_INTERFACE
));
if
(
!
cif
)
return
E_OUTOFMEMORY
;
cif
->
Length
=
sizeof
(
RPC_CLIENT_INTERFACE
);
/* RPC interface ID = COM interface ID */
cif
->
InterfaceId
.
SyntaxGUID
=
*
riid
;
/* COM objects always have a version of 0.0 */
cif
->
InterfaceId
.
SyntaxVersion
.
MajorVersion
=
0
;
cif
->
InterfaceId
.
SyntaxVersion
.
MinorVersion
=
0
;
msg
->
RpcInterfaceInformation
=
cif
;
msg
->
Handle
=
This
->
bind
;
status
=
I_RpcGetBuffer
(
msg
);
TRACE
(
"-- %ld
\n
"
,
status
);
static
DWORD
WINAPI
client_dispatch_thread
(
LPVOID
);
return
HRESULT_FROM_WIN32
(
status
);
}
/* FIXME: this all needs to be made thread safe */
static
HRESULT
RPC_GetRequest
(
struct
rpc
**
req
)
static
HRESULT
WINAPI
RpcChannelBuffer_SendReceive
(
LPRPCCHANNELBUFFER
iface
,
RPCOLEMESSAGE
*
olemsg
,
ULONG
*
pstatus
)
{
static
int
reqid
=
0
;
int
i
;
RPC_MESSAGE
*
msg
=
(
RPC_MESSAGE
*
)
olemsg
;
RPC_STATUS
status
;
HRESULT
hr
;
/* try to reuse */
for
(
i
=
0
;
i
<
nrofreqs
;
i
++
)
{
if
(
reqs
[
i
]
->
state
==
REQSTATE_DONE
)
{
TRACE
(
"reusing reqs[%d]
\n
"
,
i
);
TRACE
(
"(%p)
\n
"
,
msg
);
reqs
[
i
]
->
reqh
.
reqid
=
reqid
++
;
reqs
[
i
]
->
resph
.
reqid
=
reqs
[
i
]
->
reqh
.
reqid
;
reqs
[
i
]
->
hPipe
=
INVALID_HANDLE_VALUE
;
reqs
[
i
]
->
state
=
REQSTATE_START
;
*
req
=
reqs
[
i
];
return
S_OK
;
}
}
status
=
I_RpcSendReceive
(
msg
);
TRACE
(
"creating new struct rpc (request)
\n
"
)
;
if
(
pstatus
)
*
pstatus
=
status
;
if
(
reqs
)
reqs
=
(
struct
rpc
**
)
HeapReAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
reqs
,
sizeof
(
struct
rpc
*
)
*
(
nrofreqs
+
1
)
);
if
(
status
==
RPC_S_OK
)
hr
=
S_OK
;
else
if
(
status
==
RPC_S_CALL_FAILED
)
hr
=
*
(
HRESULT
*
)
msg
->
Buffer
;
else
reqs
=
(
struct
rpc
**
)
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
sizeof
(
struct
rpc
*
)
);
if
(
!
reqs
)
return
E_OUTOFMEMORY
;
hr
=
HRESULT_FROM_WIN32
(
status
);
reqs
[
nrofreqs
]
=
(
struct
rpc
*
)
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
sizeof
(
struct
rpc
));
reqs
[
nrofreqs
]
->
reqh
.
reqid
=
reqid
++
;
reqs
[
nrofreqs
]
->
resph
.
reqid
=
reqs
[
nrofreqs
]
->
reqh
.
reqid
;
reqs
[
nrofreqs
]
->
hPipe
=
INVALID_HANDLE_VALUE
;
reqs
[
nrofreqs
]
->
state
=
REQSTATE_START
;
*
req
=
reqs
[
nrofreqs
];
TRACE
(
"-- 0x%08lx
\n
"
,
hr
);
nrofreqs
++
;
return
S_OK
;
return
hr
;
}
static
HRESULT
WINAPI
PipeBuf_QueryInterface
(
LPRPCCHANNELBUFFER
iface
,
REFIID
riid
,
LPVOID
*
ppv
)
{
*
ppv
=
NULL
;
if
(
IsEqualIID
(
riid
,
&
IID_IRpcChannelBuffer
)
||
IsEqualIID
(
riid
,
&
IID_IUnknown
))
{
*
ppv
=
(
LPVOID
)
iface
;
IUnknown_AddRef
(
iface
);
return
S_OK
;
}
return
E_NOINTERFACE
;
}
static
HRESULT
WINAPI
ServerRpcChannelBuffer_FreeBuffer
(
LPRPCCHANNELBUFFER
iface
,
RPCOLEMESSAGE
*
olemsg
)
{
RPC_MESSAGE
*
msg
=
(
RPC_MESSAGE
*
)
olemsg
;
RPC_STATUS
status
;
static
ULONG
WINAPI
PipeBuf_AddRef
(
LPRPCCHANNELBUFFER
iface
)
{
PipeBuf
*
This
=
(
PipeBuf
*
)
iface
;
return
InterlockedIncrement
(
&
This
->
ref
);
}
TRACE
(
"(%p)
\n
"
,
msg
);
static
ULONG
WINAPI
PipeBuf_Release
(
LPRPCCHANNELBUFFER
iface
)
{
PipeBuf
*
This
=
(
PipeBuf
*
)
iface
;
ULONG
ref
;
status
=
I_RpcFreeBuffer
(
msg
);
ref
=
InterlockedDecrement
(
&
This
->
ref
);
if
(
ref
)
return
ref
;
TRACE
(
"-- %ld
\n
"
,
status
);
CloseHandle
(
This
->
pipe
);
HeapFree
(
GetProcessHeap
(),
0
,
This
);
return
0
;
return
HRESULT_FROM_WIN32
(
status
);
}
static
HRESULT
WINAPI
PipeBuf_GetBuffer
(
LPRPCCHANNELBUFFER
iface
,
RPCOLEMESSAGE
*
msg
,
REFIID
riid
)
static
HRESULT
WINAPI
ClientRpcChannelBuffer_FreeBuffer
(
LPRPCCHANNELBUFFER
iface
,
RPCOLEMESSAGE
*
olemsg
)
{
TRACE
(
"(%p,%s)
\n
"
,
msg
,
debugstr_guid
(
riid
));
/* probably reuses IID in real. */
if
(
msg
->
cbBuffer
&&
(
msg
->
Buffer
==
NULL
))
msg
->
Buffer
=
HeapAlloc
(
GetProcessHeap
(),
0
,
msg
->
cbBuffer
);
return
S_OK
;
}
RPC_MESSAGE
*
msg
=
(
RPC_MESSAGE
*
)
olemsg
;
RPC_STATUS
status
;
HRESULT
RPC_ExecuteCall
(
RPCOLEMESSAGE
*
msg
,
IRpcStubBuffer
*
stub
)
{
return
IRpcStubBuffer_Invoke
(
stub
,
msg
,
NULL
);
}
TRACE
(
"(%p)
\n
"
,
msg
);
static
HRESULT
COM_InvokeAndRpcSend
(
struct
rpc
*
req
)
{
IRpcStubBuffer
*
stub
;
APARTMENT
*
apt
;
RPCOLEMESSAGE
msg
;
HRESULT
hres
;
DWORD
reqtype
;
status
=
I_RpcFreeBuffer
(
msg
);
memset
(
&
msg
,
0
,
sizeof
(
msg
));
msg
.
Buffer
=
req
->
Buffer
;
msg
.
iMethod
=
req
->
reqh
.
iMethod
;
msg
.
cbBuffer
=
req
->
reqh
.
cbBuffer
;
msg
.
dataRepresentation
=
NDR_LOCAL_DATA_REPRESENTATION
;
req
->
state
=
REQSTATE_INVOKING
;
HeapFree
(
GetProcessHeap
(),
0
,
msg
->
RpcInterfaceInformation
);
msg
->
RpcInterfaceInformation
=
NULL
;
stub
=
ipid_to_apt_and_stubbuffer
(
&
req
->
reqh
.
ipid
,
&
apt
);
if
(
!
apt
)
/* ipid_to_apt_and_stubbuffer will already have logged the error */
return
RPC_E_DISCONNECTED
;
if
(
!
stub
)
{
/* ipid_to_apt_and_stubbuffer will already have logged the error */
COM_ApartmentRelease
(
apt
);
return
RPC_E_DISCONNECTED
;
}
TRACE
(
"-- %ld
\n
"
,
status
);
/* Note: this is the important difference between STAs and MTAs - we
* always execute RPCs to STAs in the thread that originally created the
* apartment (i.e. the one that pumps messages to the window) */
if
(
apt
->
model
&
COINIT_APARTMENTTHREADED
)
req
->
resph
.
retval
=
SendMessageW
(
apt
->
win
,
DM_EXECUTERPC
,
(
WPARAM
)
&
msg
,
(
LPARAM
)
stub
);
else
req
->
resph
.
retval
=
RPC_ExecuteCall
(
&
msg
,
stub
);
return
HRESULT_FROM_WIN32
(
status
);
}
COM_ApartmentRelease
(
apt
);
IRpcStubBuffer_Release
(
stub
);
static
HRESULT
WINAPI
RpcChannelBuffer_GetDestCtx
(
LPRPCCHANNELBUFFER
iface
,
DWORD
*
pdwDestContext
,
void
**
ppvDestContext
)
{
FIXME
(
"(%p,%p), stub!
\n
"
,
pdwDestContext
,
ppvDestContext
);
return
E_FAIL
;
}
req
->
Buffer
=
msg
.
Buffer
;
req
->
resph
.
cbBuffer
=
msg
.
cbBuffer
;
reqtype
=
REQTYPE_RESPONSE
;
hres
=
write_pipe
(
req
->
hPipe
,
&
reqtype
,
sizeof
(
reqtype
));
if
(
hres
)
return
hres
;
hres
=
write_pipe
(
req
->
hPipe
,
&
(
req
->
resph
),
sizeof
(
req
->
resph
));
if
(
hres
)
return
hres
;
hres
=
write_pipe
(
req
->
hPipe
,
req
->
Buffer
,
req
->
resph
.
cbBuffer
);
if
(
hres
)
return
hres
;
req
->
state
=
REQSTATE_DONE
;
static
HRESULT
WINAPI
RpcChannelBuffer_IsConnected
(
LPRPCCHANNELBUFFER
iface
)
{
TRACE
(
"()
\n
"
);
/* native does nothing too */
return
S_OK
;
}
static
HRESULT
process_incoming_rpc
(
HANDLE
pipe
);
static
const
IRpcChannelBufferVtbl
ClientRpcChannelBufferVtbl
=
{
RpcChannelBuffer_QueryInterface
,
RpcChannelBuffer_AddRef
,
ClientRpcChannelBuffer_Release
,
ClientRpcChannelBuffer_GetBuffer
,
RpcChannelBuffer_SendReceive
,
ClientRpcChannelBuffer_FreeBuffer
,
RpcChannelBuffer_GetDestCtx
,
RpcChannelBuffer_IsConnected
};
static
HRESULT
RPC_QueueRequestAndWait
(
struct
rpc
*
req
,
HANDLE
pipe
)
static
const
IRpcChannelBufferVtbl
ServerRpcChannelBufferVtbl
=
{
int
i
;
struct
rpc
*
xreq
;
HRESULT
hres
;
DWORD
reqtype
;
RpcChannelBuffer_QueryInterface
,
RpcChannelBuffer_AddRef
,
ServerRpcChannelBuffer_Release
,
ServerRpcChannelBuffer_GetBuffer
,
RpcChannelBuffer_SendReceive
,
ServerRpcChannelBuffer_FreeBuffer
,
RpcChannelBuffer_GetDestCtx
,
RpcChannelBuffer_IsConnected
};
req
->
hPipe
=
pipe
;
req
->
state
=
REQSTATE_REQ_WAITING_FOR_REPLY
;
reqtype
=
REQTYPE_REQUEST
;
hres
=
write_pipe
(
req
->
hPipe
,
&
reqtype
,
sizeof
(
reqtype
));
if
(
hres
)
return
hre
s
;
hres
=
write_pipe
(
req
->
hPipe
,
&
(
req
->
reqh
),
sizeof
(
req
->
reqh
))
;
if
(
hres
)
return
hres
;
hres
=
write_pipe
(
req
->
hPipe
,
req
->
Buffer
,
req
->
reqh
.
cbBuffer
)
;
if
(
hres
)
return
hres
;
/* returns a channel buffer for proxies */
/* FIXME: needs renaming and mid removing */
HRESULT
PIPE_GetNewPipeBuf
(
wine_marshal_id
*
mid
,
IRpcChannelBuffer
**
chan
)
{
ClientRpcChannelBuffer
*
Thi
s
;
WCHAR
endpoint
[
200
]
;
RPC_BINDING_HANDLE
bind
;
RPC_STATUS
status
;
LPWSTR
string_binding
;
/* This loop is about allowing re-entrancy. While waiting for the
* response to one RPC we may receive a request starting another. */
while
(
!
hres
)
{
hres
=
process_incoming_rpc
(
pipe
);
if
(
hres
)
break
;
for
(
i
=
0
;
i
<
nrofreqs
;
i
++
)
{
xreq
=
reqs
[
i
];
if
((
xreq
->
state
==
REQSTATE_REQ_GOT
)
&&
(
xreq
->
hPipe
==
req
->
hPipe
))
{
hres
=
COM_InvokeAndRpcSend
(
xreq
);
if
(
hres
)
break
;
}
}
if
(
req
->
state
==
REQSTATE_RESP_GOT
)
return
S_OK
;
/* connect to the apartment listener thread */
get_rpc_endpoint
(
endpoint
,
&
mid
->
oxid
);
TRACE
(
"proxy pipe: connecting to endpoint: %s
\n
"
,
debugstr_w
(
endpoint
));
status
=
RpcStringBindingComposeW
(
NULL
,
wszPipeTransport
,
NULL
,
endpoint
,
NULL
,
&
string_binding
);
if
(
status
==
RPC_S_OK
)
{
status
=
RpcBindingFromStringBindingW
(
string_binding
,
&
bind
);
if
(
status
==
RPC_S_OK
)
{
status
=
RpcBindingSetObject
(
bind
,
&
mid
->
ipid
);
if
(
status
!=
RPC_S_OK
)
RpcBindingFree
(
&
bind
);
}
if
(
FAILED
(
hres
))
WARN
(
"-- 0x%08lx
\n
"
,
hres
);
return
hres
;
}
static
HRESULT
WINAPI
PipeBuf_SendReceive
(
LPRPCCHANNELBUFFER
iface
,
RPCOLEMESSAGE
*
msg
,
ULONG
*
status
)
{
PipeBuf
*
This
=
(
PipeBuf
*
)
iface
;
struct
rpc
*
req
;
HRESULT
hres
;
RpcStringFreeW
(
&
string_binding
);
}
if
(
This
->
mid
.
oxid
==
COM_CurrentApt
()
->
oxid
)
{
ERR
(
"Need to call directly!
\n
"
);
return
E_FAIL
;
if
(
status
!=
RPC_S_OK
)
{
ERR
(
"Couldn't get binding for endpoint %s, status = %ld
\n
"
,
debugstr_w
(
endpoint
),
status
);
return
HRESULT_FROM_WIN32
(
status
);
}
hres
=
RPC_GetRequest
(
&
req
);
if
(
hres
)
return
hres
;
req
->
reqh
.
iMethod
=
msg
->
iMethod
;
req
->
reqh
.
cbBuffer
=
msg
->
cbBuffer
;
req
->
reqh
.
ipid
=
This
->
mid
.
ipid
;
req
->
Buffer
=
msg
->
Buffer
;
TRACE
(
" -> rpc ->
\n
"
);
hres
=
RPC_QueueRequestAndWait
(
req
,
This
->
pipe
);
TRACE
(
" <- response <-
\n
"
);
if
(
hres
)
This
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
This
));
if
(
!
This
)
{
req
->
state
=
REQSTATE_DONE
;
return
hres
;
RpcBindingFree
(
&
bind
)
;
return
E_OUTOFMEMORY
;
}
msg
->
cbBuffer
=
req
->
resph
.
cbBuffer
;
msg
->
Buffer
=
req
->
Buffer
;
*
status
=
req
->
resph
.
retval
;
req
->
state
=
REQSTATE_DONE
;
This
->
super
.
lpVtbl
=
&
ClientRpcChannelBufferVtbl
;
This
->
super
.
refs
=
1
;
This
->
bind
=
bind
;
*
chan
=
(
IRpcChannelBuffer
*
)
This
;
return
S_OK
;
}
static
HRESULT
WINAPI
PipeBuf_FreeBuffer
(
LPRPCCHANNELBUFFER
iface
,
RPCOLEMESSAGE
*
msg
)
HRESULT
RPC_CreateServerChannel
(
IRpcChannelBuffer
**
chan
)
{
TRACE
(
"(%p)
\n
"
,
msg
);
HeapFree
(
GetProcessHeap
(),
0
,
msg
->
Buffer
);
RpcChannelBuffer
*
This
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
This
));
if
(
!
This
)
return
E_OUTOFMEMORY
;
This
->
lpVtbl
=
&
ServerRpcChannelBufferVtbl
;
This
->
refs
=
1
;
*
chan
=
(
IRpcChannelBuffer
*
)
This
;
return
S_OK
;
}
static
HRESULT
WINAPI
PipeBuf_GetDestCtx
(
LPRPCCHANNELBUFFER
iface
,
DWORD
*
pdwDestContext
,
void
**
ppvDestContext
)
HRESULT
RPC_ExecuteCall
(
RPCOLEMESSAGE
*
msg
,
IRpcStubBuffer
*
stub
)
{
FIXME
(
"(%p,%p), stub!
\n
"
,
pdwDestContext
,
ppvDestContext
);
return
E_FAIL
;
/* FIXME: pass server channel buffer, but don't create it every time */
return
IRpcStubBuffer_Invoke
(
stub
,
msg
,
NULL
)
;
}
static
HRESULT
WINAPI
PipeBuf_IsConnected
(
LPRPCCHANNELBUFFER
iface
)
static
void
__RPC_STUB
dispatch_rpc
(
RPC_MESSAGE
*
msg
)
{
FIXME
(
"(), stub!
\n
"
)
;
return
S_OK
;
}
IRpcStubBuffer
*
stub
;
APARTMENT
*
apt
;
IPID
ipid
;
static
IRpcChannelBufferVtbl
pipebufvt
=
{
PipeBuf_QueryInterface
,
PipeBuf_AddRef
,
PipeBuf_Release
,
PipeBuf_GetBuffer
,
PipeBuf_SendReceive
,
PipeBuf_FreeBuffer
,
PipeBuf_GetDestCtx
,
PipeBuf_IsConnected
};
RpcBindingInqObject
(
msg
->
Handle
,
&
ipid
);
/* returns a pipebuf for proxies */
HRESULT
PIPE_GetNewPipeBuf
(
wine_marshal_id
*
mid
,
IRpcChannelBuffer
**
pipebuf
)
{
wine_marshal_id
ourid
;
HANDLE
handle
;
PipeBuf
*
pbuf
;
char
pipefn
[
200
];
stub
=
ipid_to_apt_and_stubbuffer
(
&
ipid
,
&
apt
);
if
(
!
apt
||
!
stub
)
{
if
(
apt
)
COM_ApartmentRelease
(
apt
)
;
/* ipid_to_apt_and_stubbuffer will already have logged the error */
return
RpcRaiseException
(
RPC_E_DISCONNECTED
)
;
}
/* connect to the apartment listener thread */
sprintf
(
pipefn
,
OLESTUBMGR
"_%08lx%08lx"
,(
DWORD
)(
mid
->
oxid
>>
32
),(
DWORD
)
mid
->
oxid
);
/* Note: this is the important difference between STAs and MTAs - we
* always execute RPCs to STAs in the thread that originally created the
* apartment (i.e. the one that pumps messages to the window) */
if
(
apt
->
model
&
COINIT_APARTMENTTHREADED
)
SendMessageW
(
apt
->
win
,
DM_EXECUTERPC
,
(
WPARAM
)
msg
,
(
LPARAM
)
stub
);
else
RPC_ExecuteCall
((
RPCOLEMESSAGE
*
)
msg
,
stub
);
COM_ApartmentRelease
(
apt
);
IRpcStubBuffer_Release
(
stub
);
}
/* stub registration */
HRESULT
RPC_RegisterInterface
(
REFIID
riid
)
{
struct
registered_if
*
rif
;
BOOL
found
=
FALSE
;
HRESULT
hr
=
S_OK
;
TRACE
(
"
proxy pipe: connecting to apartment listener thread: %s
\n
"
,
pipefn
);
TRACE
(
"
(%s)
\n
"
,
debugstr_guid
(
riid
)
);
while
(
TRUE
)
EnterCriticalSection
(
&
csRegIf
);
LIST_FOR_EACH_ENTRY
(
rif
,
&
registered_interfaces
,
struct
registered_if
,
entry
)
{
BOOL
ret
=
WaitNamedPipeA
(
pipefn
,
NMPWAIT_USE_DEFAULT_WAIT
);
if
(
!
ret
)
if
(
IsEqualGUID
(
&
rif
->
If
.
InterfaceId
.
SyntaxGUID
,
riid
))
{
ERR
(
"Could not open named pipe %s, error %ld
\n
"
,
pipefn
,
GetLastError
());
return
RPC_E_SERVER_DIED
;
rif
->
refs
++
;
found
=
TRUE
;
break
;
}
handle
=
CreateFileA
(
pipefn
,
GENERIC_READ
|
GENERIC_WRITE
,
0
,
NULL
,
OPEN_EXISTING
,
0
,
0
);
if
(
handle
==
INVALID_HANDLE_VALUE
)
}
if
(
!
found
)
{
if
(
GetLastError
()
==
ERROR_PIPE_BUSY
)
continue
;
TRACE
(
"Creating new interface
\n
"
)
;
ERR
(
"Could not open named pipe %s, error %ld
\n
"
,
pipefn
,
GetLastError
());
return
RPC_E_SERVER_DIED
;
rif
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
rif
));
if
(
rif
)
{
RPC_STATUS
status
;
rif
->
refs
=
1
;
rif
->
If
.
Length
=
sizeof
(
RPC_SERVER_INTERFACE
);
/* RPC interface ID = COM interface ID */
rif
->
If
.
InterfaceId
.
SyntaxGUID
=
*
riid
;
/* COM objects always have a version of 0.0 */
rif
->
If
.
InterfaceId
.
SyntaxVersion
.
MajorVersion
=
0
;
rif
->
If
.
InterfaceId
.
SyntaxVersion
.
MinorVersion
=
0
;
rif
->
If
.
DispatchTable
=
&
rpc_dispatch
;
status
=
RpcServerRegisterIfEx
(
(
RPC_IF_HANDLE
)
&
rif
->
If
,
NULL
,
NULL
,
RPC_IF_OLE
|
RPC_IF_AUTOLISTEN
,
RPC_C_LISTEN_MAX_CALLS_DEFAULT
,
NULL
);
if
(
status
==
RPC_S_OK
)
list_add_tail
(
&
registered_interfaces
,
&
rif
->
entry
);
else
{
ERR
(
"RpcServerRegisterIfEx failed with error %ld
\n
"
,
status
);
HeapFree
(
GetProcessHeap
(),
0
,
rif
);
hr
=
HRESULT_FROM_WIN32
(
status
);
}
}
else
hr
=
E_OUTOFMEMORY
;
}
LeaveCriticalSection
(
&
csRegIf
);
return
hr
;
}
/* stub unregistration */
void
RPC_UnregisterInterface
(
REFIID
riid
)
{
struct
registered_if
*
rif
;
EnterCriticalSection
(
&
csRegIf
);
LIST_FOR_EACH_ENTRY
(
rif
,
&
registered_interfaces
,
struct
registered_if
,
entry
)
{
if
(
IsEqualGUID
(
&
rif
->
If
.
InterfaceId
.
SyntaxGUID
,
riid
))
{
if
(
!--
rif
->
refs
)
{
#if 0 /* this is a stub in builtin and spams the console with FIXME's */
IID iid = *riid; /* RpcServerUnregisterIf doesn't take const IID */
RpcServerUnregisterIf((RPC_IF_HANDLE)&rif->If, &iid, 0);
#endif
list_remove
(
&
rif
->
entry
);
HeapFree
(
GetProcessHeap
(),
0
,
rif
);
}
break
;
}
}
LeaveCriticalSection
(
&
csRegIf
);
}
memset
(
&
ourid
,
0
,
sizeof
(
ourid
));
ourid
.
oxid
=
COM_CurrentApt
()
->
oxid
;
TRACE
(
"constructing new pipebuf for proxy
\n
"
);
/* FIXME: needs renaming */
void
start_apartment_listener_thread
()
{
APARTMENT
*
apt
=
COM_CurrentApt
();
/* FIXME: pass as parameter */
pbuf
=
(
PipeBuf
*
)
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
sizeof
(
PipeBuf
));
pbuf
->
lpVtbl
=
&
pipebufvt
;
pbuf
->
ref
=
1
;
memcpy
(
&
(
pbuf
->
mid
),
mid
,
sizeof
(
*
mid
));
pbuf
->
pipe
=
dupe_handle
(
handle
);
if
(
!
apt
->
listenertid
)
{
WCHAR
endpoint
[
200
];
RPC_STATUS
status
;
*
pipebuf
=
(
IRpcChannelBuffer
*
)
pbuf
;
get_rpc_endpoint
(
endpoint
,
&
apt
->
oxid
)
;
return
S_OK
;
status
=
RpcServerUseProtseqEpW
(
wszPipeTransport
,
RPC_C_PROTSEQ_MAX_REQS_DEFAULT
,
endpoint
,
NULL
);
if
(
status
!=
RPC_S_OK
)
ERR
(
"Couldn't register endpoint %s
\n
"
,
debugstr_w
(
endpoint
));
apt
->
listenertid
=
TRUE
;
/* FIXME: don't abuse this field and use remunk_exported, by moving remunk exporting into this function */
}
}
static
HRESULT
create_server
(
REFCLSID
rclsid
)
{
...
...
@@ -648,7 +652,9 @@ create_local_service(REFCLSID rclsid)
return
hres
;
}
/* http://msdn.microsoft.com/library/en-us/dnmsj99/html/com0199.asp, Figure 4 */
#define PIPEPREF "\\\\.\\pipe\\"
/* FIXME: should call to rpcss instead */
HRESULT
create_marshalled_proxy
(
REFCLSID
rclsid
,
REFIID
iid
,
LPVOID
*
ppv
)
{
HRESULT
hres
;
...
...
@@ -714,302 +720,13 @@ out:
}
/* this reads an RPC from the given pipe and places it in the global reqs array */
static
HRESULT
process_incoming_rpc
(
HANDLE
pipe
)
{
DWORD
reqtype
;
HRESULT
hres
=
S_OK
;
hres
=
read_pipe
(
pipe
,
&
reqtype
,
sizeof
(
reqtype
));
if
(
hres
)
return
hres
;
/* only received by servers */
if
(
reqtype
==
REQTYPE_REQUEST
)
{
struct
rpc
*
xreq
;
RPC_GetRequest
(
&
xreq
);
xreq
->
hPipe
=
pipe
;
hres
=
read_pipe
(
pipe
,
&
(
xreq
->
reqh
),
sizeof
(
xreq
->
reqh
));
if
(
hres
)
{
xreq
->
state
=
REQSTATE_DONE
;
return
hres
;
}
xreq
->
resph
.
reqid
=
xreq
->
reqh
.
reqid
;
xreq
->
Buffer
=
HeapAlloc
(
GetProcessHeap
(),
0
,
xreq
->
reqh
.
cbBuffer
);
hres
=
read_pipe
(
pipe
,
xreq
->
Buffer
,
xreq
->
reqh
.
cbBuffer
);
if
(
hres
)
goto
end
;
TRACE
(
"received RPC for IPID %s
\n
"
,
debugstr_guid
(
&
xreq
->
reqh
.
ipid
));
xreq
->
state
=
REQSTATE_REQ_GOT
;
goto
end
;
}
else
if
(
reqtype
==
REQTYPE_RESPONSE
)
{
struct
response_header
resph
;
int
i
;
hres
=
read_pipe
(
pipe
,
&
resph
,
sizeof
(
resph
));
if
(
hres
)
goto
end
;
TRACE
(
"read RPC response
\n
"
);
for
(
i
=
nrofreqs
;
i
--
;)
{
struct
rpc
*
xreq
=
reqs
[
i
];
if
(
xreq
->
state
!=
REQSTATE_REQ_WAITING_FOR_REPLY
)
continue
;
if
(
xreq
->
reqh
.
reqid
==
resph
.
reqid
)
{
memcpy
(
&
(
xreq
->
resph
),
&
resph
,
sizeof
(
resph
));
if
(
xreq
->
Buffer
)
xreq
->
Buffer
=
HeapReAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
xreq
->
Buffer
,
xreq
->
resph
.
cbBuffer
);
else
xreq
->
Buffer
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
xreq
->
resph
.
cbBuffer
);
hres
=
read_pipe
(
pipe
,
xreq
->
Buffer
,
xreq
->
resph
.
cbBuffer
);
if
(
hres
)
goto
end
;
TRACE
(
"received response for reqid 0x%lx
\n
"
,
xreq
->
reqh
.
reqid
);
xreq
->
state
=
REQSTATE_RESP_GOT
;
goto
end
;
}
}
ERR
(
"protocol error: did not find request for id %lx
\n
"
,
resph
.
reqid
);
hres
=
E_FAIL
;
goto
end
;
}
ERR
(
"protocol error: unknown reqtype %ld
\n
"
,
reqtype
);
hres
=
E_FAIL
;
end:
return
hres
;
}
struct
stub_dispatch_params
{
struct
apartment
*
apt
;
HANDLE
pipe
;
};
/* This thread listens on the given pipe for requests to any stub manager */
static
DWORD
WINAPI
client_dispatch_thread
(
LPVOID
param
)
{
HANDLE
pipe
=
((
struct
stub_dispatch_params
*
)
param
)
->
pipe
;
struct
apartment
*
apt
=
((
struct
stub_dispatch_params
*
)
param
)
->
apt
;
HRESULT
hres
=
S_OK
;
HANDLE
shutdown_event
=
dupe_handle
(
apt
->
shutdown_event
);
HeapFree
(
GetProcessHeap
(),
0
,
param
);
/* join marshalling apartment. fixme: this stuff is all very wrong, threading needs to work like native */
COM_CurrentInfo
()
->
apt
=
apt
;
while
(
TRUE
)
{
int
i
;
TRACE
(
"waiting for RPC on OXID: %08lx%08lx
\n
"
,
(
DWORD
)(
apt
->
oxid
>>
32
),
(
DWORD
)(
apt
->
oxid
));
/* read a new request into the global array, block if no requests have been sent */
hres
=
process_incoming_rpc
(
pipe
);
if
(
hres
)
break
;
/* do you expect me to talk? */
if
(
WaitForSingleObject
(
shutdown_event
,
0
)
==
WAIT_OBJECT_0
)
{
/* no mr bond, i expect you to die! bwahaha */
CloseHandle
(
shutdown_event
);
break
;
}
TRACE
(
"received RPC on OXID: %08lx%08lx
\n
"
,
(
DWORD
)(
apt
->
oxid
>>
32
),
(
DWORD
)(
apt
->
oxid
));
/* now scan the array looking for the RPC just loaded */
for
(
i
=
nrofreqs
;
i
--
;)
{
struct
rpc
*
req
=
reqs
[
i
];
if
((
req
->
state
==
REQSTATE_REQ_GOT
)
&&
(
req
->
hPipe
==
pipe
))
{
hres
=
COM_InvokeAndRpcSend
(
req
);
if
(
!
hres
)
break
;
}
}
}
TRACE
(
"exiting with hres %lx
\n
"
,
hres
);
/* leave marshalling apartment. fixme: this stuff is all very wrong, threading needs to work like native */
COM_CurrentInfo
()
->
apt
=
NULL
;
DisconnectNamedPipe
(
pipe
);
CloseHandle
(
pipe
);
return
0
;
}
struct
apartment_listener_params
{
APARTMENT
*
apt
;
HANDLE
event
;
};
/* This thread listens on a named pipe for each apartment that exports
* objects. It deals with incoming connection requests. Each time a
* client connects a separate thread is spawned for that particular
* connection.
*
* This architecture is different in native DCOM.
*/
static
DWORD
WINAPI
apartment_listener_thread
(
LPVOID
p
)
{
char
pipefn
[
200
];
HANDLE
listenPipe
,
thread_handle
;
OVERLAPPED
overlapped
;
HANDLE
wait
[
2
];
struct
apartment_listener_params
*
params
=
(
struct
apartment_listener_params
*
)
p
;
struct
apartment
*
apt
=
params
->
apt
;
HANDLE
event
=
params
->
event
;
HANDLE
apt_shutdown_event
=
dupe_handle
(
apt
->
shutdown_event
);
OXID
this_oxid
=
apt
->
oxid
;
/* copy here so we can print it when we shut down */
HeapFree
(
GetProcessHeap
(),
0
,
params
);
overlapped
.
hEvent
=
CreateEventA
(
NULL
,
TRUE
,
FALSE
,
NULL
);
/* we must join the marshalling threads apartment. we already have a ref here */
COM_CurrentInfo
()
->
apt
=
apt
;
sprintf
(
pipefn
,
OLESTUBMGR
"_%08lx%08lx"
,
(
DWORD
)(
apt
->
oxid
>>
32
),
(
DWORD
)(
apt
->
oxid
));
TRACE
(
"Apartment listener thread starting on (%s)
\n
"
,
pipefn
);
while
(
TRUE
)
{
struct
stub_dispatch_params
*
params
;
DWORD
res
;
listenPipe
=
CreateNamedPipeA
(
pipefn
,
PIPE_ACCESS_DUPLEX
|
FILE_FLAG_OVERLAPPED
,
PIPE_TYPE_BYTE
|
PIPE_WAIT
,
PIPE_UNLIMITED_INSTANCES
,
4096
,
4096
,
500
/* 0.5 seconds */
,
NULL
);
/* tell function that started this thread that we have attempted to created the
* named pipe. */
if
(
event
)
{
SetEvent
(
event
);
event
=
NULL
;
}
if
(
listenPipe
==
INVALID_HANDLE_VALUE
)
{
FIXME
(
"pipe creation failed for %s, error %ld
\n
"
,
pipefn
,
GetLastError
());
break
;
/* permanent failure, so quit stubmgr thread */
}
TRACE
(
"waiting for a client ...
\n
"
);
/* an already connected pipe is not an error */
if
(
!
ConnectNamedPipe
(
listenPipe
,
&
overlapped
))
{
DWORD
le
=
GetLastError
();
if
((
le
!=
ERROR_IO_PENDING
)
&&
(
le
!=
ERROR_PIPE_CONNECTED
))
{
ERR
(
"Failure during ConnectNamedPipe %ld!
\n
"
,
GetLastError
());
CloseHandle
(
listenPipe
);
continue
;
}
}
/* wait for action */
wait
[
0
]
=
apt_shutdown_event
;
wait
[
1
]
=
overlapped
.
hEvent
;
res
=
WaitForMultipleObjectsEx
(
2
,
wait
,
FALSE
,
INFINITE
,
FALSE
);
if
(
res
==
WAIT_OBJECT_0
)
break
;
ResetEvent
(
overlapped
.
hEvent
);
/* start the stub dispatch thread for this connection */
TRACE
(
"starting stub dispatch thread for OXID %08lx%08lx
\n
"
,
(
DWORD
)(
apt
->
oxid
>>
32
),
(
DWORD
)(
apt
->
oxid
));
params
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
struct
stub_dispatch_params
));
if
(
!
params
)
{
ERR
(
"out of memory, dropping this client
\n
"
);
CloseHandle
(
listenPipe
);
continue
;
}
params
->
apt
=
apt
;
params
->
pipe
=
listenPipe
;
thread_handle
=
CreateThread
(
NULL
,
0
,
&
client_dispatch_thread
,
params
,
0
,
NULL
);
CloseHandle
(
thread_handle
);
}
TRACE
(
"shutting down: %s
\n
"
,
wine_dbgstr_longlong
(
this_oxid
));
/* we must leave the marshalling threads apartment. we don't have a ref here */
COM_CurrentInfo
()
->
apt
=
NULL
;
DisconnectNamedPipe
(
listenPipe
);
CloseHandle
(
listenPipe
);
CloseHandle
(
overlapped
.
hEvent
);
CloseHandle
(
apt_shutdown_event
);
return
0
;
}
void
start_apartment_listener_thread
()
{
APARTMENT
*
apt
=
COM_CurrentApt
();
assert
(
apt
);
TRACE
(
"apt->listenertid=%ld
\n
"
,
apt
->
listenertid
);
/* apt->listenertid is a hack which needs to die at some point, as
* it leaks information into the apartment structure. in fact,
* this thread isn't quite correct anyway as native RPC doesn't
* use a thread per apartment at all, instead the dispatch thread
* either enters the apartment to perform the RPC (for MTAs, RTAs)
* or does a context switch into it for STAs.
*/
if
(
!
apt
->
listenertid
)
{
HANDLE
thread
;
HANDLE
event
=
CreateEventW
(
NULL
,
TRUE
,
FALSE
,
NULL
);
struct
apartment_listener_params
*
params
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
params
));
params
->
apt
=
apt
;
params
->
event
=
event
;
thread
=
CreateThread
(
NULL
,
0
,
apartment_listener_thread
,
params
,
0
,
&
apt
->
listenertid
);
CloseHandle
(
thread
);
/* wait for pipe to be created before returning, otherwise we
* might try to use it and fail */
WaitForSingleObject
(
event
,
INFINITE
);
CloseHandle
(
event
);
}
}
struct
local_server_params
{
CLSID
clsid
;
IStream
*
stream
;
};
/* FIXME: should call to rpcss instead */
static
DWORD
WINAPI
local_server_thread
(
LPVOID
param
)
{
struct
local_server_params
*
lsp
=
(
struct
local_server_params
*
)
param
;
...
...
dlls/ole32/stubmanager.c
View file @
db6db7cb
...
...
@@ -421,6 +421,8 @@ static void stub_manager_delete_ifstub(struct stub_manager *m, struct ifstub *if
list_remove
(
&
ifstub
->
entry
);
RPC_UnregisterInterface
(
&
ifstub
->
iid
);
IUnknown_Release
(
ifstub
->
stubbuffer
);
IUnknown_Release
(
ifstub
->
iface
);
...
...
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