A bug about RPC interface unlocking

Questions about Wine on Linux
Post Reply
taobaibai
Newbie
Newbie
Posts: 2
Joined: Wed Jan 31, 2024 10:31 pm

A bug about RPC interface unlocking

Post by taobaibai »

Hello everyone, I am using Wine7.6 to run IE8 to access web pages. A plugin on a page will call to open an Office Word document, which is fine, but it will freeze when I close Word.
I tracked this issue and found that it ultimately locked in rpcrt4--rpc_ server. c -- RpcServerUnregisterIf function,
RPC_STATUS WINAPI RpcServerUnregisterIf( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, UINT WaitForCallsToComplete )
{
......................
EnterCriticalSection(&server_cs);
LIST_FOR_EACH_ENTRY(cif, &server_interfaces, RpcServerInterface, entry) {
if (((!IfSpec && !(cif->Flags & RPC_IF_AUTOLISTEN)) ||
(IfSpec && !memcmp(&If->InterfaceId, &cif->If->InterfaceId, sizeof(RPC_SYNTAX_IDENTIFIER)))) &&
UuidEqual(MgrTypeUuid, &cif->MgrTypeUuid, &status)) {
list_remove(&cif->entry);
TRACE("unregistering cif %p\n", cif);
if (cif->CurrentCalls) { //Judging whether an interface has been called, Counting references like CurrentCalls is crucial
completed = FALSE;
cif->Delete = TRUE;
if (WaitForCallsToComplete)
cif->CallsCompletedEvent = event = CreateEventW(NULL, FALSE, FALSE, NULL);
}
found = TRUE;
break;
}
}
LeaveCriticalSection(&server_cs);
....................
if (completed)
HeapFree(GetProcessHeap(), 0, cif);
else if (event) {
/* sif will be freed when the last call is completed, so be careful not to
* touch that memory here as that could happen before we get here */
FIXME("2\n");
WaitForSingleObject(event, INFINITE); //Always waiting for the event to complete
FIXME("3\n");
CloseHandle(event);
}

return RPC_S_OK;
}

Looking back on this process, I found that IE8 called process while processing RPC_ Request_ Packet, the current calls count will be increased here
static RPC_STATUS process_request_packet(RpcConnection *conn, RpcPktRequestHdr *hdr, RPC_MESSAGE *msg)
{
...............
sif = RPCRT4_find_interface(object_uuid, &conn->ActiveInterface, NULL, TRUE); //increase the CurrentCalls count
...............
__TRY {
if (func) func(msg); //The function here is combase--rpc.c--dispatch_rpc
} __EXCEPT_ALL {
WARN("exception caught with code 0x%08lx = %ld\n", GetExceptionCode(), GetExceptionCode());
exception = TRUE;
if (GetExceptionCode() == STATUS_ACCESS_VIOLATION)
status = ERROR_NOACCESS;
else
status = GetExceptionCode();
response = RPCRT4_BuildFaultHeader(msg->DataRepresentation,
RPC2NCA_STATUS(status));
} __ENDTRY
...............
RPCRT4_release_server_interface(sif); //Reduce CurrentCalls count
................
}

Come to combase--rpc.c--dispatch_rpc function
static void __RPC_STUB dispatch_rpc(RPC_MESSAGE *msg)
{
..................
//There's no problem with anything up there
stub_manager_int_release(stub_manager); //During the process of releasing resources, RpcServerUnregisterIf will be called to unregister the interface
}

This self-locking issue is probably like this. I really hope the author or a kind-hearted person who has dealt with related issues can help me with how to modify or optimize this to make COM RPC smooth.
taobaibai
Newbie
Newbie
Posts: 2
Joined: Wed Jan 31, 2024 10:31 pm

Re: A bug about RPC interface unlocking

Post by taobaibai »

Is anyone here to talk to me? Any suggestions would be great.
Post Reply