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

📄 rpc_message.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 3 页
字号:
        ((*Header)->common.frag_len - hdr_length < header_auth_len)) {      WARN("frag_len %d too small for hdr_length %d and auth_len %d\n",        (*Header)->common.frag_len, hdr_length, header_auth_len);      status = RPC_S_PROTOCOL_ERROR;      goto fail;    }    if ((*Header)->common.auth_len != auth_length) {      WARN("auth_len header field changed from %ld to %d\n",        auth_length, (*Header)->common.auth_len);      status = RPC_S_PROTOCOL_ERROR;      goto fail;    }    if (((*Header)->common.flags & RPC_FLG_FIRST) != first_flag) {      TRACE("invalid packet flags\n");      status = RPC_S_PROTOCOL_ERROR;      goto fail;    }    data_length = (*Header)->common.frag_len - hdr_length - header_auth_len;    if (data_length + buffer_length > pMsg->BufferLength) {      TRACE("allocation hint exceeded, new buffer length = %ld\n",        data_length + buffer_length);      pMsg->BufferLength = data_length + buffer_length;      status = I_RpcReAllocateBuffer(pMsg);      if (status != RPC_S_OK) goto fail;    }    if (data_length == 0) dwRead = 0; else    dwRead = rpcrt4_conn_read(Connection,        (unsigned char *)pMsg->Buffer + buffer_length, data_length);    if (dwRead != data_length) {      WARN("bad data length, %d/%ld\n", dwRead, data_length);      status = RPC_S_PROTOCOL_ERROR;      goto fail;    }    if (header_auth_len) {      if (header_auth_len < sizeof(RpcAuthVerifier)) {        WARN("bad auth verifier length %d\n", header_auth_len);        status = RPC_S_PROTOCOL_ERROR;        goto fail;      }      /* FIXME: we should accumulate authentication data for the bind,       * bind_ack, alter_context and alter_context_response if necessary.       * however, the details of how this is done is very sketchy in the       * DCE/RPC spec. for all other packet types that have authentication       * verifier data then it is just duplicated in all the fragments */      dwRead = rpcrt4_conn_read(Connection, auth_data, header_auth_len);      if (dwRead != header_auth_len) {        WARN("bad authentication data length, %d/%d\n", dwRead,          header_auth_len);        status = RPC_S_PROTOCOL_ERROR;        goto fail;      }      /* these packets are handled specially, not by the generic SecurePacket       * function */      if ((common_hdr.ptype != PKT_BIND) &&          (common_hdr.ptype != PKT_BIND_ACK) &&          (common_hdr.ptype != PKT_AUTH3))        status = RPCRT4_SecurePacket(Connection, SECURE_PACKET_RECEIVE,            *Header, hdr_length,            (unsigned char *)pMsg->Buffer + buffer_length, data_length,            (RpcAuthVerifier *)auth_data,            (unsigned char *)auth_data + sizeof(RpcAuthVerifier),            header_auth_len - sizeof(RpcAuthVerifier));    }    buffer_length += data_length;    if (!((*Header)->common.flags & RPC_FLG_LAST)) {      TRACE("next header\n");      /* read the header of next packet */      dwRead = rpcrt4_conn_read(Connection, *Header, hdr_length);      if (dwRead != hdr_length) {        WARN("invalid packet header size (%d)\n", dwRead);        status = RPC_S_PROTOCOL_ERROR;        goto fail;      }      first_flag = 0;    } else {      break;    }  }  pMsg->BufferLength = buffer_length;  /* respond to authorization request */  if (common_hdr.ptype == PKT_BIND_ACK && auth_length > sizeof(RpcAuthVerifier))  {    status = RPCRT_AuthorizeConnection(Connection,                                       auth_data + sizeof(RpcAuthVerifier),                                       auth_length);    if (status)        goto fail;  }  /* success */  status = RPC_S_OK;fail:  if (status != RPC_S_OK) {    RPCRT4_FreeHeader(*Header);    *Header = NULL;  }  HeapFree(GetProcessHeap(), 0, auth_data);  return status;}/*********************************************************************** *           I_RpcGetBuffer [RPCRT4.@] * * Allocates a buffer for use by I_RpcSend or I_RpcSendReceive and binds to the * server interface. * * PARAMS *  pMsg [I/O] RPC message information. * * RETURNS *  Success: RPC_S_OK. *  Failure: RPC_S_INVALID_BINDING if pMsg->Handle is invalid. *           RPC_S_SERVER_UNAVAILABLE if unable to connect to server. *           ERROR_OUTOFMEMORY if buffer allocation failed. * * NOTES *  The pMsg->BufferLength field determines the size of the buffer to allocate, *  in bytes. * *  Use I_RpcFreeBuffer() to unbind from the server and free the message buffer. * * SEE ALSO *  I_RpcFreeBuffer(), I_RpcSend(), I_RpcReceive(), I_RpcSendReceive(). */RPC_STATUS WINAPI I_RpcGetBuffer(PRPC_MESSAGE pMsg){  TRACE("(%p): BufferLength=%d\n", pMsg, pMsg->BufferLength);  /* FIXME: pfnAllocate? */  pMsg->Buffer = HeapAlloc(GetProcessHeap(), 0, pMsg->BufferLength);  TRACE("Buffer=%p\n", pMsg->Buffer);  /* FIXME: which errors to return? */  return pMsg->Buffer ? S_OK : E_OUTOFMEMORY;}/*********************************************************************** *           I_RpcReAllocateBuffer (internal) */static RPC_STATUS I_RpcReAllocateBuffer(PRPC_MESSAGE pMsg){  TRACE("(%p): BufferLength=%d\n", pMsg, pMsg->BufferLength);  pMsg->Buffer = HeapReAlloc(GetProcessHeap(), 0, pMsg->Buffer, pMsg->BufferLength);  TRACE("Buffer=%p\n", pMsg->Buffer);  return pMsg->Buffer ? RPC_S_OK : RPC_S_OUT_OF_RESOURCES;}/*********************************************************************** *           I_RpcFreeBuffer [RPCRT4.@] * * Frees a buffer allocated by I_RpcGetBuffer or I_RpcReceive and unbinds from * the server interface. * * PARAMS *  pMsg [I/O] RPC message information. * * RETURNS *  RPC_S_OK. * * SEE ALSO *  I_RpcGetBuffer(), I_RpcReceive(). */RPC_STATUS WINAPI I_RpcFreeBuffer(PRPC_MESSAGE pMsg){  TRACE("(%p) Buffer=%p\n", pMsg, pMsg->Buffer);  /* FIXME: pfnFree? */  HeapFree(GetProcessHeap(), 0, pMsg->Buffer);  pMsg->Buffer = NULL;  return S_OK;}/*********************************************************************** *           I_RpcSend [RPCRT4.@] * * Sends a message to the server. * * PARAMS *  pMsg [I/O] RPC message information. * * RETURNS *  Unknown. * * NOTES *  The buffer must have been allocated with I_RpcGetBuffer(). * * SEE ALSO *  I_RpcGetBuffer(), I_RpcReceive(), I_RpcSendReceive(). */RPC_STATUS WINAPI I_RpcSend(PRPC_MESSAGE pMsg){  RpcBinding* bind = (RpcBinding*)pMsg->Handle;  RpcConnection* conn;  RPC_CLIENT_INTERFACE* cif = NULL;  RPC_STATUS status;  RpcPktHdr *hdr;  TRACE("(%p)\n", pMsg);  if (!bind || bind->server) return RPC_S_INVALID_BINDING;  cif = pMsg->RpcInterfaceInformation;  if (!cif) return RPC_S_INTERFACE_NOT_FOUND; /* ? */  if (!bind->Endpoint || !bind->Endpoint[0])  {    TRACE("automatically resolving partially bound binding\n");    status = RpcEpResolveBinding(bind, cif);    if (status != RPC_S_OK) return status;  }  status = RPCRT4_OpenBinding(bind, &conn, &cif->TransferSyntax,                              &cif->InterfaceId);  if (status != RPC_S_OK) return status;  hdr = RPCRT4_BuildRequestHeader(pMsg->DataRepresentation,                                  pMsg->BufferLength, pMsg->ProcNum,                                  &bind->ObjectUuid);  if (!hdr)  {    RPCRT4_CloseBinding(bind, conn);    return ERROR_OUTOFMEMORY;  }  hdr->common.call_id = conn->NextCallId++;  status = RPCRT4_Send(conn, hdr, pMsg->Buffer, pMsg->BufferLength);  RPCRT4_FreeHeader(hdr);  /* save the connection, so the response can be read from it */  pMsg->ReservedForRuntime = conn;  return status;}/* is this status something that the server can't recover from? */static inline BOOL is_hard_error(RPC_STATUS status){    switch (status)    {    case 0: /* user-defined fault */    case ERROR_ACCESS_DENIED:    case ERROR_INVALID_PARAMETER:    case RPC_S_PROTOCOL_ERROR:    case RPC_S_CALL_FAILED:    case RPC_S_CALL_FAILED_DNE:        return TRUE;    default:        return FALSE;    }}/*********************************************************************** *           I_RpcReceive [RPCRT4.@] */RPC_STATUS WINAPI I_RpcReceive(PRPC_MESSAGE pMsg){  RpcBinding* bind = (RpcBinding*)pMsg->Handle;  RpcConnection* conn;  RPC_CLIENT_INTERFACE* cif = NULL;  RPC_SERVER_INTERFACE* sif = NULL;  RPC_STATUS status;  RpcPktHdr *hdr = NULL;  TRACE("(%p)\n", pMsg);  if (!bind) return RPC_S_INVALID_BINDING;  if (pMsg->ReservedForRuntime) {    conn = pMsg->ReservedForRuntime;    pMsg->ReservedForRuntime = NULL;  } else {    if (bind->server) {      sif = pMsg->RpcInterfaceInformation;      if (!sif) return RPC_S_INTERFACE_NOT_FOUND; /* ? */      status = RPCRT4_OpenBinding(bind, &conn, &sif->TransferSyntax,                                  &sif->InterfaceId);    } else {      cif = pMsg->RpcInterfaceInformation;      if (!cif) return RPC_S_INTERFACE_NOT_FOUND; /* ? */      if (!bind->Endpoint || !bind->Endpoint[0])      {        TRACE("automatically resolving partially bound binding\n");        status = RpcEpResolveBinding(bind, cif);        if (status != RPC_S_OK) return status;      }      status = RPCRT4_OpenBinding(bind, &conn, &cif->TransferSyntax,                                  &cif->InterfaceId);    }    if (status != RPC_S_OK) return status;  }  status = RPCRT4_Receive(conn, &hdr, pMsg);  if (status != RPC_S_OK) {    WARN("receive failed with error %lx\n", status);    goto fail;  }  switch (hdr->common.ptype) {  case PKT_RESPONSE:    if (bind->server) {        status = RPC_S_PROTOCOL_ERROR;        goto fail;    }    break;  case PKT_REQUEST:    if (!bind->server) {        status = RPC_S_PROTOCOL_ERROR;        goto fail;    }    break;  case PKT_FAULT:    ERR ("we got fault packet with status 0x%lx\n", hdr->fault.status);    status = NCA2RPC_STATUS(hdr->fault.status);    if (is_hard_error(status))        goto fail;    break;  default:    WARN("bad packet type %d\n", hdr->common.ptype);    status = RPC_S_PROTOCOL_ERROR;    goto fail;  }  /* success */  RPCRT4_CloseBinding(bind, conn);  RPCRT4_FreeHeader(hdr);  return status;fail:  RPCRT4_FreeHeader(hdr);  RPCRT4_DestroyConnection(conn);  return status;}/*********************************************************************** *           I_RpcSendReceive [RPCRT4.@] * * Sends a message to the server and receives the response. * * PARAMS *  pMsg [I/O] RPC message information. * * RETURNS *  Success: RPC_S_OK. *  Failure: Any error code. * * NOTES *  The buffer must have been allocated with I_RpcGetBuffer(). * * SEE ALSO *  I_RpcGetBuffer(), I_RpcSend(), I_RpcReceive(). */RPC_STATUS WINAPI I_RpcSendReceive(PRPC_MESSAGE pMsg){  RPC_STATUS status;  RPC_MESSAGE original_message;  TRACE("(%p)\n", pMsg);  original_message = *pMsg;  status = I_RpcSend(pMsg);  if (status == RPC_S_OK)    status = I_RpcReceive(pMsg);  /* free the buffer replaced by a new buffer in I_RpcReceive */  if (status == RPC_S_OK)    I_RpcFreeBuffer(&original_message);  return status;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -