📄 rpc_server.c
字号:
RPCRT4_DestroyConnection(conn); return 0;}void RPCRT4_new_client(RpcConnection* conn){ HANDLE thread = CreateThread(NULL, 0, RPCRT4_io_thread, conn, 0, NULL); if (!thread) { DWORD err = GetLastError(); ERR("failed to create thread, error=%08x\n", err); RPCRT4_DestroyConnection(conn); } /* we could set conn->thread, but then we'd have to make the io_thread wait * for that, otherwise the thread might finish, destroy the connection, and * free the memory we'd write to before we did, causing crashes and stuff - * so let's implement that later, when we really need conn->thread */ CloseHandle( thread );}static DWORD CALLBACK RPCRT4_server_thread(LPVOID the_arg){ int res; unsigned int count; void *objs = NULL; RpcServerProtseq* cps = the_arg; RpcConnection* conn; BOOL set_ready_event = FALSE; TRACE("(the_arg == ^%p)\n", the_arg); for (;;) { objs = cps->ops->get_wait_array(cps, objs, &count); if (set_ready_event) { /* signal to function that changed state that we are now sync'ed */ SetEvent(cps->server_ready_event); set_ready_event = FALSE; } /* start waiting */ res = cps->ops->wait_for_new_connection(cps, count, objs); if (res == -1) break; else if (res == 0) { if (!std_listen) { SetEvent(cps->server_ready_event); break; } set_ready_event = TRUE; } } cps->ops->free_wait_array(cps, objs); EnterCriticalSection(&cps->cs); /* close connections */ conn = cps->conn; while (conn) { RPCRT4_CloseConnection(conn); conn = conn->Next; } LeaveCriticalSection(&cps->cs); return 0;}/* tells the server thread that the state has changed and waits for it to * make the changes */static void RPCRT4_sync_with_server_thread(RpcServerProtseq *ps){ /* make sure we are the only thread sync'ing the server state, otherwise * there is a race with the server thread setting an older state and setting * the server_ready_event when the new state hasn't yet been applied */ WaitForSingleObject(ps->mgr_mutex, INFINITE); ps->ops->signal_state_changed(ps); /* wait for server thread to make the requested changes before returning */ WaitForSingleObject(ps->server_ready_event, INFINITE); ReleaseMutex(ps->mgr_mutex);}static RPC_STATUS RPCRT4_start_listen_protseq(RpcServerProtseq *ps, BOOL auto_listen){ RPC_STATUS status = RPC_S_OK; HANDLE server_thread; EnterCriticalSection(&listen_cs); if (ps->is_listening) goto done; if (!ps->mgr_mutex) ps->mgr_mutex = CreateMutexW(NULL, FALSE, NULL); if (!ps->server_ready_event) ps->server_ready_event = CreateEventW(NULL, FALSE, FALSE, NULL); server_thread = CreateThread(NULL, 0, RPCRT4_server_thread, ps, 0, NULL); if (!server_thread) { status = RPC_S_OUT_OF_RESOURCES; goto done; } ps->is_listening = TRUE; CloseHandle(server_thread);done: LeaveCriticalSection(&listen_cs); return status;}static RPC_STATUS RPCRT4_start_listen(BOOL auto_listen){ RPC_STATUS status = RPC_S_ALREADY_LISTENING; RpcServerProtseq *cps; TRACE("\n"); EnterCriticalSection(&listen_cs); if (auto_listen || (manual_listen_count++ == 0)) { status = RPC_S_OK; if (++listen_count == 1) std_listen = TRUE; } LeaveCriticalSection(&listen_cs); if (std_listen) { EnterCriticalSection(&server_cs); LIST_FOR_EACH_ENTRY(cps, &protseqs, RpcServerProtseq, entry) { status = RPCRT4_start_listen_protseq(cps, TRUE); if (status != RPC_S_OK) break; /* make sure server is actually listening on the interface before * returning */ RPCRT4_sync_with_server_thread(cps); } LeaveCriticalSection(&server_cs); } return status;}static void RPCRT4_stop_listen(BOOL auto_listen){ EnterCriticalSection(&listen_cs); if (auto_listen || (--manual_listen_count == 0)) { if (listen_count != 0 && --listen_count == 0) { RpcServerProtseq *cps; std_listen = FALSE; LeaveCriticalSection(&listen_cs); LIST_FOR_EACH_ENTRY(cps, &protseqs, RpcServerProtseq, entry) RPCRT4_sync_with_server_thread(cps); return; } assert(listen_count >= 0); } LeaveCriticalSection(&listen_cs);}static RPC_STATUS RPCRT4_use_protseq(RpcServerProtseq* ps, LPSTR endpoint){ RPC_STATUS status; status = ps->ops->open_endpoint(ps, endpoint); if (status != RPC_S_OK) return status; if (std_listen) { status = RPCRT4_start_listen_protseq(ps, FALSE); if (status == RPC_S_OK) RPCRT4_sync_with_server_thread(ps); } return status;}/*********************************************************************** * RpcServerInqBindings (RPCRT4.@) */RPC_STATUS WINAPI RpcServerInqBindings( RPC_BINDING_VECTOR** BindingVector ){ RPC_STATUS status; DWORD count; RpcServerProtseq* ps; RpcConnection* conn; if (BindingVector) TRACE("(*BindingVector == ^%p)\n", *BindingVector); else ERR("(BindingVector == NULL!!?)\n"); EnterCriticalSection(&server_cs); /* count connections */ count = 0; LIST_FOR_EACH_ENTRY(ps, &protseqs, RpcServerProtseq, entry) { EnterCriticalSection(&ps->cs); conn = ps->conn; while (conn) { count++; conn = conn->Next; } LeaveCriticalSection(&ps->cs); } if (count) { /* export bindings */ *BindingVector = HeapAlloc(GetProcessHeap(), 0, sizeof(RPC_BINDING_VECTOR) + sizeof(RPC_BINDING_HANDLE)*(count-1)); (*BindingVector)->Count = count; count = 0; LIST_FOR_EACH_ENTRY(ps, &protseqs, RpcServerProtseq, entry) { EnterCriticalSection(&ps->cs); conn = ps->conn; while (conn) { RPCRT4_MakeBinding((RpcBinding**)&(*BindingVector)->BindingH[count], conn); count++; conn = conn->Next; } LeaveCriticalSection(&ps->cs); } status = RPC_S_OK; } else { *BindingVector = NULL; status = RPC_S_NO_BINDINGS; } LeaveCriticalSection(&server_cs); return status;}/*********************************************************************** * RpcServerUseProtseqEpA (RPCRT4.@) */RPC_STATUS WINAPI RpcServerUseProtseqEpA( RPC_CSTR Protseq, UINT MaxCalls, RPC_CSTR Endpoint, LPVOID SecurityDescriptor ){ RPC_POLICY policy; TRACE( "(%s,%u,%s,%p)\n", Protseq, MaxCalls, Endpoint, SecurityDescriptor ); /* This should provide the default behaviour */ policy.Length = sizeof( policy ); policy.EndpointFlags = 0; policy.NICFlags = 0; return RpcServerUseProtseqEpExA( Protseq, MaxCalls, Endpoint, SecurityDescriptor, &policy );}/*********************************************************************** * RpcServerUseProtseqEpW (RPCRT4.@) */RPC_STATUS WINAPI RpcServerUseProtseqEpW( RPC_WSTR Protseq, UINT MaxCalls, RPC_WSTR Endpoint, LPVOID SecurityDescriptor ){ RPC_POLICY policy; TRACE( "(%s,%u,%s,%p)\n", debugstr_w( Protseq ), MaxCalls, debugstr_w( Endpoint ), SecurityDescriptor ); /* This should provide the default behaviour */ policy.Length = sizeof( policy ); policy.EndpointFlags = 0; policy.NICFlags = 0; return RpcServerUseProtseqEpExW( Protseq, MaxCalls, Endpoint, SecurityDescriptor, &policy );}/*********************************************************************** * alloc_serverprotoseq (internal) * * Must be called with server_cs held. */static RPC_STATUS alloc_serverprotoseq(UINT MaxCalls, char *Protseq, RpcServerProtseq **ps){ const struct protseq_ops *ops = rpcrt4_get_protseq_ops(Protseq); if (!ops) { FIXME("protseq %s not supported\n", debugstr_a(Protseq)); return RPC_S_PROTSEQ_NOT_SUPPORTED; } *ps = ops->alloc(); if (!*ps) return RPC_S_OUT_OF_RESOURCES; (*ps)->MaxCalls = MaxCalls; (*ps)->Protseq = Protseq; (*ps)->ops = ops; (*ps)->MaxCalls = 0; (*ps)->conn = NULL; InitializeCriticalSection(&(*ps)->cs); (*ps)->is_listening = FALSE; (*ps)->mgr_mutex = NULL; (*ps)->server_ready_event = NULL; list_add_head(&protseqs, &(*ps)->entry); TRACE("new protseq %p created for %s\n", *ps, Protseq); return RPC_S_OK;}/* Finds a given protseq or creates a new one if one doesn't already exist */static RPC_STATUS RPCRT4_get_or_create_serverprotseq(UINT MaxCalls, char *Protseq, RpcServerProtseq **ps){ RPC_STATUS status; RpcServerProtseq *cps; EnterCriticalSection(&server_cs); LIST_FOR_EACH_ENTRY(cps, &protseqs, RpcServerProtseq, entry) if (!strcmp(cps->Protseq, Protseq)) { TRACE("found existing protseq object for %s\n", Protseq); *ps = cps; LeaveCriticalSection(&server_cs); return S_OK; } status = alloc_serverprotoseq(MaxCalls, Protseq, ps); LeaveCriticalSection(&server_cs); return status;}/*********************************************************************** * RpcServerUseProtseqEpExA (RPCRT4.@) */RPC_STATUS WINAPI RpcServerUseProtseqEpExA( RPC_CSTR Protseq, UINT MaxCalls, RPC_CSTR Endpoint, LPVOID SecurityDescriptor, PRPC_POLICY lpPolicy ){ char *szps = (char*)Protseq, *szep = (char*)Endpoint; RpcServerProtseq* ps; RPC_STATUS status; TRACE("(%s,%u,%s,%p,{%u,%lu,%lu})\n", debugstr_a(szps), MaxCalls, debugstr_a(szep), SecurityDescriptor, lpPolicy->Length, lpPolicy->EndpointFlags, lpPolicy->NICFlags ); status = RPCRT4_get_or_create_serverprotseq(MaxCalls, RPCRT4_strdupA(szps), &ps); if (status != RPC_S_OK) return status; return RPCRT4_use_protseq(ps, szep);}/*********************************************************************** * RpcServerUseProtseqEpExW (RPCRT4.@) */RPC_STATUS WINAPI RpcServerUseProtseqEpExW( RPC_WSTR Protseq, UINT MaxCalls, RPC_WSTR Endpoint, LPVOID SecurityDescriptor, PRPC_POLICY lpPolicy ){ RpcServerProtseq* ps; RPC_STATUS status; LPSTR EndpointA; TRACE("(%s,%u,%s,%p,{%u,%lu,%lu})\n", debugstr_w( Protseq ), MaxCalls, debugstr_w( Endpoint ), SecurityDescriptor, lpPolicy->Length, lpPolicy->EndpointFlags, lpPolicy->NICFlags ); status = RPCRT4_get_or_create_serverprotseq(MaxCalls, RPCRT4_strdupWtoA(Protseq), &ps); if (status != RPC_S_OK) return status; EndpointA = RPCRT4_strdupWtoA(Endpoint); status = RPCRT4_use_protseq(ps, EndpointA); RPCRT4_strfree(EndpointA); return status;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -