📄 rpc_transport.c
字号:
const struct protseq_ops *rpcrt4_get_protseq_ops(const char *protseq){ int i; for(i=0; i<ARRAYSIZE(protseq_list); i++) if (!strcmp(protseq_list[i].name, protseq)) return &protseq_list[i]; return NULL;}static const struct connection_ops *rpcrt4_get_conn_protseq_ops(const char *protseq){ int i; for(i=0; i<ARRAYSIZE(conn_protseq_list); i++) if (!strcmp(conn_protseq_list[i].name, protseq)) return &conn_protseq_list[i]; return NULL;}/**** interface to rest of code ****/RPC_STATUS RPCRT4_OpenClientConnection(RpcConnection* Connection){ TRACE("(Connection == ^%p)\n", Connection); assert(!Connection->server); return Connection->ops->open_connection_client(Connection);}RPC_STATUS RPCRT4_CloseConnection(RpcConnection* Connection){ TRACE("(Connection == ^%p)\n", Connection); if (SecIsValidHandle(&Connection->ctx)) { DeleteSecurityContext(&Connection->ctx); SecInvalidateHandle(&Connection->ctx); } rpcrt4_conn_close(Connection); return RPC_S_OK;}RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server, LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, LPCWSTR NetworkOptions, RpcAuthInfo* AuthInfo, RpcQualityOfService *QOS){ const struct connection_ops *ops; RpcConnection* NewConnection; ops = rpcrt4_get_conn_protseq_ops(Protseq); if (!ops) { FIXME("not supported for protseq %s\n", Protseq); return RPC_S_PROTSEQ_NOT_SUPPORTED; } NewConnection = ops->alloc(); NewConnection->Next = NULL; NewConnection->server = server; NewConnection->ops = ops; NewConnection->NetworkAddr = RPCRT4_strdupA(NetworkAddr); NewConnection->Endpoint = RPCRT4_strdupA(Endpoint); NewConnection->NetworkOptions = RPCRT4_strdupW(NetworkOptions); NewConnection->MaxTransmissionSize = RPC_MAX_PACKET_SIZE; memset(&NewConnection->ActiveInterface, 0, sizeof(NewConnection->ActiveInterface)); NewConnection->NextCallId = 1; SecInvalidateHandle(&NewConnection->ctx); memset(&NewConnection->exp, 0, sizeof(NewConnection->exp)); NewConnection->attr = 0; if (AuthInfo) RpcAuthInfo_AddRef(AuthInfo); NewConnection->AuthInfo = AuthInfo; NewConnection->encryption_auth_len = 0; NewConnection->signature_auth_len = 0; if (QOS) RpcQualityOfService_AddRef(QOS); NewConnection->QOS = QOS; list_init(&NewConnection->conn_pool_entry); TRACE("connection: %p\n", NewConnection); *Connection = NewConnection; return RPC_S_OK;}RPC_STATUS RPCRT4_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, LPCWSTR NetworkOptions, RpcAssoc **assoc_out){ RpcAssoc *assoc; EnterCriticalSection(&assoc_list_cs); LIST_FOR_EACH_ENTRY(assoc, &assoc_list, RpcAssoc, entry) { if (!strcmp(Protseq, assoc->Protseq) && !strcmp(NetworkAddr, assoc->NetworkAddr) && !strcmp(Endpoint, assoc->Endpoint) && ((!assoc->NetworkOptions && !NetworkOptions) || !strcmpW(NetworkOptions, assoc->NetworkOptions))) { assoc->refs++; *assoc_out = assoc; LeaveCriticalSection(&assoc_list_cs); TRACE("using existing assoc %p\n", assoc); return RPC_S_OK; } } assoc = HeapAlloc(GetProcessHeap(), 0, sizeof(*assoc)); if (!assoc) { LeaveCriticalSection(&assoc_list_cs); return RPC_S_OUT_OF_RESOURCES; } assoc->refs = 1; list_init(&assoc->connection_pool); InitializeCriticalSection(&assoc->cs); assoc->Protseq = RPCRT4_strdupA(Protseq); assoc->NetworkAddr = RPCRT4_strdupA(NetworkAddr); assoc->Endpoint = RPCRT4_strdupA(Endpoint); assoc->NetworkOptions = NetworkOptions ? RPCRT4_strdupW(NetworkOptions) : NULL; assoc->assoc_group_id = 0; list_add_head(&assoc_list, &assoc->entry); *assoc_out = assoc; LeaveCriticalSection(&assoc_list_cs); TRACE("new assoc %p\n", assoc); return RPC_S_OK;}ULONG RpcAssoc_Release(RpcAssoc *assoc){ ULONG refs; EnterCriticalSection(&assoc_list_cs); refs = --assoc->refs; if (!refs) list_remove(&assoc->entry); LeaveCriticalSection(&assoc_list_cs); if (!refs) { RpcConnection *Connection, *cursor2; TRACE("destroying assoc %p\n", assoc); LIST_FOR_EACH_ENTRY_SAFE(Connection, cursor2, &assoc->connection_pool, RpcConnection, conn_pool_entry) { list_remove(&Connection->conn_pool_entry); RPCRT4_DestroyConnection(Connection); } HeapFree(GetProcessHeap(), 0, assoc->NetworkOptions); HeapFree(GetProcessHeap(), 0, assoc->Endpoint); HeapFree(GetProcessHeap(), 0, assoc->NetworkAddr); HeapFree(GetProcessHeap(), 0, assoc->Protseq); HeapFree(GetProcessHeap(), 0, assoc); } return refs;}static RPC_STATUS RpcAssoc_BindConnection(RpcAssoc *assoc, RpcConnection *conn, const RPC_SYNTAX_IDENTIFIER *InterfaceId, const RPC_SYNTAX_IDENTIFIER *TransferSyntax){ RpcPktHdr *hdr; RpcPktHdr *response_hdr; RPC_MESSAGE msg; RPC_STATUS status; TRACE("sending bind request to server\n"); hdr = RPCRT4_BuildBindHeader(NDR_LOCAL_DATA_REPRESENTATION, RPC_MAX_PACKET_SIZE, RPC_MAX_PACKET_SIZE, assoc->assoc_group_id, InterfaceId, TransferSyntax); status = RPCRT4_Send(conn, hdr, NULL, 0); RPCRT4_FreeHeader(hdr); if (status != RPC_S_OK) return status; status = RPCRT4_Receive(conn, &response_hdr, &msg); if (status != RPC_S_OK) { ERR("receive failed\n"); return status; } if (response_hdr->common.ptype != PKT_BIND_ACK) { ERR("failed to bind for interface %s, %d.%d\n", debugstr_guid(&InterfaceId->SyntaxGUID), InterfaceId->SyntaxVersion.MajorVersion, InterfaceId->SyntaxVersion.MinorVersion); RPCRT4_FreeHeader(response_hdr); return RPC_S_PROTOCOL_ERROR; } /* FIXME: do more checks? */ conn->assoc_group_id = response_hdr->bind_ack.assoc_gid; conn->MaxTransmissionSize = response_hdr->bind_ack.max_tsize; conn->ActiveInterface = *InterfaceId; RPCRT4_FreeHeader(response_hdr); return RPC_S_OK;}static RpcConnection *RpcAssoc_GetIdleConnection(RpcAssoc *assoc, const RPC_SYNTAX_IDENTIFIER *InterfaceId, const RPC_SYNTAX_IDENTIFIER *TransferSyntax, const RpcAuthInfo *AuthInfo, const RpcQualityOfService *QOS){ RpcConnection *Connection; EnterCriticalSection(&assoc->cs); /* try to find a compatible connection from the connection pool */ LIST_FOR_EACH_ENTRY(Connection, &assoc->connection_pool, RpcConnection, conn_pool_entry) { if (!memcmp(&Connection->ActiveInterface, InterfaceId, sizeof(RPC_SYNTAX_IDENTIFIER)) && RpcAuthInfo_IsEqual(Connection->AuthInfo, AuthInfo) && RpcQualityOfService_IsEqual(Connection->QOS, QOS)) { list_remove(&Connection->conn_pool_entry); LeaveCriticalSection(&assoc->cs); TRACE("got connection from pool %p\n", Connection); return Connection; } } LeaveCriticalSection(&assoc->cs); return NULL;}RPC_STATUS RpcAssoc_GetClientConnection(RpcAssoc *assoc, const RPC_SYNTAX_IDENTIFIER *InterfaceId, const RPC_SYNTAX_IDENTIFIER *TransferSyntax, RpcAuthInfo *AuthInfo, RpcQualityOfService *QOS, RpcConnection **Connection){ RpcConnection *NewConnection; RPC_STATUS status; *Connection = RpcAssoc_GetIdleConnection(assoc, InterfaceId, TransferSyntax, AuthInfo, QOS); if (*Connection) return RPC_S_OK; /* create a new connection */ status = RPCRT4_CreateConnection(&NewConnection, FALSE /* is this a server connection? */, assoc->Protseq, assoc->NetworkAddr, assoc->Endpoint, assoc->NetworkOptions, AuthInfo, QOS); if (status != RPC_S_OK) return status; status = RPCRT4_OpenClientConnection(NewConnection); if (status != RPC_S_OK) { RPCRT4_DestroyConnection(NewConnection); return status; } status = RpcAssoc_BindConnection(assoc, NewConnection, InterfaceId, TransferSyntax); if (status != RPC_S_OK) { RPCRT4_DestroyConnection(NewConnection); return status; } *Connection = NewConnection; return RPC_S_OK;}void RpcAssoc_ReleaseIdleConnection(RpcAssoc *assoc, RpcConnection *Connection){ assert(!Connection->server); EnterCriticalSection(&assoc->cs); if (!assoc->assoc_group_id) assoc->assoc_group_id = Connection->assoc_group_id; list_add_head(&assoc->connection_pool, &Connection->conn_pool_entry); LeaveCriticalSection(&assoc->cs);}RPC_STATUS RPCRT4_SpawnConnection(RpcConnection** Connection, RpcConnection* OldConnection){ RPC_STATUS err; err = RPCRT4_CreateConnection(Connection, OldConnection->server, rpcrt4_conn_get_name(OldConnection), OldConnection->NetworkAddr, OldConnection->Endpoint, NULL, OldConnection->AuthInfo, OldConnection->QOS); if (err == RPC_S_OK) rpcrt4_conn_handoff(OldConnection, *Connection); return err;}RPC_STATUS RPCRT4_DestroyConnection(RpcConnection* Connection){ TRACE("connection: %p\n", Connection); RPCRT4_CloseConnection(Connection); RPCRT4_strfree(Connection->Endpoint); RPCRT4_strfree(Connection->NetworkAddr); HeapFree(GetProcessHeap(), 0, Connection->NetworkOptions); if (Connection->AuthInfo) RpcAuthInfo_Release(Connection->AuthInfo); if (Connection->QOS) RpcQualityOfService_Release(Connection->QOS); HeapFree(GetProcessHeap(), 0, Connection); return RPC_S_OK;}RPC_STATUS RpcTransport_GetTopOfTower(unsigned char *tower_data, size_t *tower_size, const char *protseq, const char *networkaddr, const char *endpoint){ twr_empty_floor_t *protocol_floor; const struct connection_ops *protseq_ops = rpcrt4_get_conn_protseq_ops(protseq); *tower_size = 0; if (!protseq_ops) return RPC_S_INVALID_RPC_PROTSEQ; if (!tower_data) { *tower_size = sizeof(*protocol_floor); *tower_size += protseq_ops->get_top_of_tower(NULL, networkaddr, endpoint); return RPC_S_OK; } protocol_floor = (twr_empty_floor_t *)tower_data; protocol_floor->count_lhs = sizeof(protocol_floor->protid); protocol_floor->protid = protseq_ops->epm_protocols[0]; protocol_floor->count_rhs = 0; tower_data += sizeof(*protocol_floor); *tower_size = protseq_ops->get_top_of_tower(tower_data, networkaddr, endpoint); if (!*tower_size) return EPT_S_NOT_REGISTERED; *tower_size += sizeof(*protocol_floor); return RPC_S_OK;}RPC_STATUS RpcTransport_ParseTopOfTower(const unsigned char *tower_data, size_t tower_size, char **protseq, char **networkaddr, char **endpoint){ const twr_empty_floor_t *protocol_floor; const twr_empty_floor_t *floor4; const struct connection_ops *protseq_ops = NULL; RPC_STATUS status; int i; if (tower_size < sizeof(*protocol_floor)) return EPT_S_NOT_REGISTERED; protocol_floor = (const twr_empty_floor_t *)tower_data; tower_data += sizeof(*protocol_floor); tower_size -= sizeof(*protocol_floor); if ((protocol_floor->count_lhs != sizeof(protocol_floor->protid)) || (protocol_floor->count_rhs > tower_size)) return EPT_S_NOT_REGISTERED; tower_data += protocol_floor->count_rhs; tower_size -= protocol_floor->count_rhs; floor4 = (const twr_empty_floor_t *)tower_data; if ((tower_size < sizeof(*floor4)) || (floor4->count_lhs != sizeof(floor4->protid))) return EPT_S_NOT_REGISTERED; for(i = 0; i < ARRAYSIZE(conn_protseq_list); i++) if ((protocol_floor->protid == conn_protseq_list[i].epm_protocols[0]) && (floor4->protid == conn_protseq_list[i].epm_protocols[1])) { protseq_ops = &conn_protseq_list[i]; break; } if (!protseq_ops) return EPT_S_NOT_REGISTERED; status = protseq_ops->parse_top_of_tower(tower_data, tower_size, networkaddr, endpoint); if ((status == RPC_S_OK) && protseq) { *protseq = I_RpcAllocate(strlen(protseq_ops->name) + 1); strcpy(*protseq, protseq_ops->name); } return status;}/*********************************************************************** * RpcNetworkIsProtseqValidW (RPCRT4.@) * * Checks if the given protocol sequence is known by the RPC system. * If it is, returns RPC_S_OK, otherwise RPC_S_PROTSEQ_NOT_SUPPORTED. * */RPC_STATUS WINAPI RpcNetworkIsProtseqValidW(RPC_WSTR protseq){ char ps[0x10]; WideCharToMultiByte(CP_ACP, 0, protseq, -1, ps, sizeof ps, NULL, NULL); if (rpcrt4_get_conn_protseq_ops(ps)) return RPC_S_OK; FIXME("Unknown protseq %s\n", debugstr_w(protseq)); return RPC_S_INVALID_RPC_PROTSEQ;}/*********************************************************************** * RpcNetworkIsProtseqValidA (RPCRT4.@) */RPC_STATUS WINAPI RpcNetworkIsProtseqValidA(RPC_CSTR protseq){ UNICODE_STRING protseqW; if (RtlCreateUnicodeStringFromAsciiz(&protseqW, (char*)protseq)) { RPC_STATUS ret = RpcNetworkIsProtseqValidW(protseqW.Buffer); RtlFreeUnicodeString(&protseqW); return ret; } return RPC_S_OUT_OF_MEMORY;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -