⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rpc_transport.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
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 + -