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

📄 rpc_transport.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * RPC transport layer * * Copyright 2001 Ove K鍁en, TransGaming Technologies * Copyright 2003 Mike Hearn * Copyright 2004 Filip Navara * Copyright 2006 Mike McCormack * Copyright 2006 Damjan Jovanovic * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA * */#include "config.h"#include <stdarg.h>#include <stdio.h>#include <string.h>#include <assert.h>#include <errno.h>#ifdef HAVE_UNISTD_H# include <unistd.h>#endif#include <fcntl.h>#include <stdlib.h>#include <sys/types.h>#ifdef HAVE_SYS_SOCKET_H# include <sys/socket.h>#endif#ifdef HAVE_NETINET_IN_H# include <netinet/in.h>#endif#ifdef HAVE_NETINET_TCP_H# include <netinet/tcp.h>#endif#ifdef HAVE_ARPA_INET_H# include <arpa/inet.h>#endif#ifdef HAVE_NETDB_H#include <netdb.h>#endif#ifdef HAVE_SYS_POLL_H#include <sys/poll.h>#endif#include <winsock2.h>#include <ws2tcpip.h>#include "windef.h"#include "winbase.h"#include "winnls.h"#include "winerror.h"#include "winternl.h"#include "wine/unicode.h"#include "rpc.h"#include "rpcndr.h"#include "wine/debug.h"#include "rpc_binding.h"#include "rpc_message.h"#include "rpc_server.h"#include "epm_towers.h"#include "unix_func.h"#ifndef SOL_TCP# define SOL_TCP IPPROTO_TCP#endifWINE_DEFAULT_DEBUG_CHANNEL(rpc);static CRITICAL_SECTION assoc_list_cs;static CRITICAL_SECTION_DEBUG assoc_list_cs_debug ={    0, 0, &assoc_list_cs,    { &assoc_list_cs_debug.ProcessLocksList, &assoc_list_cs_debug.ProcessLocksList },      0, 0, { (DWORD_PTR)(__FILE__ ": assoc_list_cs") }};static CRITICAL_SECTION assoc_list_cs = { &assoc_list_cs_debug, -1, 0, 0, 0, 0 };static struct list assoc_list = LIST_INIT(assoc_list);/**** ncacn_np support ****/typedef struct _RpcConnection_np{  RpcConnection common;  HANDLE pipe;  OVERLAPPED ovl;  BOOL listening;} RpcConnection_np;static RpcConnection *rpcrt4_conn_np_alloc(void){  RpcConnection_np *npc = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcConnection_np));  if (npc)  {    npc->pipe = NULL;    memset(&npc->ovl, 0, sizeof(npc->ovl));    npc->listening = FALSE;  }  return &npc->common;}static RPC_STATUS rpcrt4_conn_listen_pipe(RpcConnection_np *npc){  if (npc->listening)    return RPC_S_OK;  npc->listening = TRUE;  if (ConnectNamedPipe(npc->pipe, &npc->ovl))    return RPC_S_OK;  if (GetLastError() == ERROR_PIPE_CONNECTED) {    SetEvent(npc->ovl.hEvent);    return RPC_S_OK;  }  if (GetLastError() == ERROR_IO_PENDING) {    /* will be completed in rpcrt4_protseq_np_wait_for_new_connection */    return RPC_S_OK;  }  npc->listening = FALSE;  WARN("Couldn't ConnectNamedPipe (error was %d)\n", GetLastError());  return RPC_S_OUT_OF_RESOURCES;}static RPC_STATUS rpcrt4_conn_create_pipe(RpcConnection *Connection, LPCSTR pname){  RpcConnection_np *npc = (RpcConnection_np *) Connection;  TRACE("listening on %s\n", pname);  npc->pipe = CreateNamedPipeA(pname, PIPE_ACCESS_DUPLEX,                               PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE,                               PIPE_UNLIMITED_INSTANCES,                               RPC_MAX_PACKET_SIZE, RPC_MAX_PACKET_SIZE, 5000, NULL);  if (npc->pipe == INVALID_HANDLE_VALUE) {    WARN("CreateNamedPipe failed with error %d\n", GetLastError());    if (GetLastError() == ERROR_FILE_EXISTS)      return RPC_S_DUPLICATE_ENDPOINT;    else      return RPC_S_CANT_CREATE_ENDPOINT;  }  memset(&npc->ovl, 0, sizeof(npc->ovl));  npc->ovl.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);  /* Note: we don't call ConnectNamedPipe here because it must be done in the   * server thread as the thread must be alertable */  return RPC_S_OK;}static RPC_STATUS rpcrt4_conn_open_pipe(RpcConnection *Connection, LPCSTR pname, BOOL wait){  RpcConnection_np *npc = (RpcConnection_np *) Connection;  HANDLE pipe;  DWORD err, dwMode;  TRACE("connecting to %s\n", pname);  while (TRUE) {    DWORD dwFlags = 0;    if (Connection->QOS)    {        dwFlags = SECURITY_SQOS_PRESENT;        switch (Connection->QOS->qos->ImpersonationType)        {            case RPC_C_IMP_LEVEL_DEFAULT:                /* FIXME: what to do here? */                break;            case RPC_C_IMP_LEVEL_ANONYMOUS:                dwFlags |= SECURITY_ANONYMOUS;                break;            case RPC_C_IMP_LEVEL_IDENTIFY:                dwFlags |= SECURITY_IDENTIFICATION;                break;            case RPC_C_IMP_LEVEL_IMPERSONATE:                dwFlags |= SECURITY_IMPERSONATION;                break;            case RPC_C_IMP_LEVEL_DELEGATE:                dwFlags |= SECURITY_DELEGATION;                break;        }        if (Connection->QOS->qos->IdentityTracking == RPC_C_QOS_IDENTIFY_DYNAMIC)            dwFlags |= SECURITY_CONTEXT_TRACKING;    }    pipe = CreateFileA(pname, GENERIC_READ|GENERIC_WRITE, 0, NULL,                       OPEN_EXISTING, dwFlags, 0);    if (pipe != INVALID_HANDLE_VALUE) break;    err = GetLastError();    if (err == ERROR_PIPE_BUSY) {      TRACE("connection failed, error=%x\n", err);      return RPC_S_SERVER_TOO_BUSY;    }    if (!wait)      return RPC_S_SERVER_UNAVAILABLE;    if (!WaitNamedPipeA(pname, NMPWAIT_WAIT_FOREVER)) {      err = GetLastError();      WARN("connection failed, error=%x\n", err);      return RPC_S_SERVER_UNAVAILABLE;    }  }  /* success */  memset(&npc->ovl, 0, sizeof(npc->ovl));  /* pipe is connected; change to message-read mode. */  dwMode = PIPE_READMODE_MESSAGE;  SetNamedPipeHandleState(pipe, &dwMode, NULL, NULL);  npc->ovl.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);  npc->pipe = pipe;  return RPC_S_OK;}static RPC_STATUS rpcrt4_ncalrpc_open(RpcConnection* Connection){  RpcConnection_np *npc = (RpcConnection_np *) Connection;  static const char prefix[] = "\\\\.\\pipe\\lrpc\\";  RPC_STATUS r;  LPSTR pname;  /* already connected? */  if (npc->pipe)    return RPC_S_OK;  /* protseq=ncalrpc: supposed to use NT LPC ports,   * but we'll implement it with named pipes for now */  pname = I_RpcAllocate(strlen(prefix) + strlen(Connection->Endpoint) + 1);  strcat(strcpy(pname, prefix), Connection->Endpoint);  r = rpcrt4_conn_open_pipe(Connection, pname, TRUE);  I_RpcFree(pname);  return r;}static RPC_STATUS rpcrt4_protseq_ncalrpc_open_endpoint(RpcServerProtseq* protseq, LPSTR endpoint){  static const char prefix[] = "\\\\.\\pipe\\lrpc\\";  RPC_STATUS r;  LPSTR pname;  RpcConnection *Connection;  r = RPCRT4_CreateConnection(&Connection, TRUE, protseq->Protseq, NULL,                              endpoint, NULL, NULL, NULL);  if (r != RPC_S_OK)      return r;  /* protseq=ncalrpc: supposed to use NT LPC ports,   * but we'll implement it with named pipes for now */  pname = I_RpcAllocate(strlen(prefix) + strlen(Connection->Endpoint) + 1);  strcat(strcpy(pname, prefix), Connection->Endpoint);  r = rpcrt4_conn_create_pipe(Connection, pname);  I_RpcFree(pname);  EnterCriticalSection(&protseq->cs);  Connection->Next = protseq->conn;  protseq->conn = Connection;  LeaveCriticalSection(&protseq->cs);  return r;}static RPC_STATUS rpcrt4_ncacn_np_open(RpcConnection* Connection){  RpcConnection_np *npc = (RpcConnection_np *) Connection;  static const char prefix[] = "\\\\.";  RPC_STATUS r;  LPSTR pname;  /* already connected? */  if (npc->pipe)    return RPC_S_OK;  /* protseq=ncacn_np: named pipes */  pname = I_RpcAllocate(strlen(prefix) + strlen(Connection->Endpoint) + 1);  strcat(strcpy(pname, prefix), Connection->Endpoint);  r = rpcrt4_conn_open_pipe(Connection, pname, FALSE);  I_RpcFree(pname);  return r;}static RPC_STATUS rpcrt4_protseq_ncacn_np_open_endpoint(RpcServerProtseq *protseq, LPSTR endpoint){  static const char prefix[] = "\\\\.";  RPC_STATUS r;  LPSTR pname;  RpcConnection *Connection;  r = RPCRT4_CreateConnection(&Connection, TRUE, protseq->Protseq, NULL,                              endpoint, NULL, NULL, NULL);  if (r != RPC_S_OK)    return r;  /* protseq=ncacn_np: named pipes */  pname = I_RpcAllocate(strlen(prefix) + strlen(Connection->Endpoint) + 1);  strcat(strcpy(pname, prefix), Connection->Endpoint);  r = rpcrt4_conn_create_pipe(Connection, pname);  I_RpcFree(pname);  EnterCriticalSection(&protseq->cs);  Connection->Next = protseq->conn;  protseq->conn = Connection;  LeaveCriticalSection(&protseq->cs);  return r;}static void rpcrt4_conn_np_handoff(RpcConnection_np *old_npc, RpcConnection_np *new_npc){      /* because of the way named pipes work, we'll transfer the connected pipe   * to the child, then reopen the server binding to continue listening */  new_npc->pipe = old_npc->pipe;  new_npc->ovl = old_npc->ovl;  old_npc->pipe = 0;  memset(&old_npc->ovl, 0, sizeof(old_npc->ovl));  old_npc->listening = FALSE;}static RPC_STATUS rpcrt4_ncacn_np_handoff(RpcConnection *old_conn, RpcConnection *new_conn){  RPC_STATUS status;  LPSTR pname;  static const char prefix[] = "\\\\.";  rpcrt4_conn_np_handoff((RpcConnection_np *)old_conn, (RpcConnection_np *)new_conn);  pname = I_RpcAllocate(strlen(prefix) + strlen(old_conn->Endpoint) + 1);  strcat(strcpy(pname, prefix), old_conn->Endpoint);  status = rpcrt4_conn_create_pipe(old_conn, pname);  I_RpcFree(pname);  return status;}static RPC_STATUS rpcrt4_ncalrpc_handoff(RpcConnection *old_conn, RpcConnection *new_conn){  RPC_STATUS status;  LPSTR pname;  static const char prefix[] = "\\\\.\\pipe\\lrpc\\";  TRACE("%s\n", old_conn->Endpoint);  rpcrt4_conn_np_handoff((RpcConnection_np *)old_conn, (RpcConnection_np *)new_conn);  pname = I_RpcAllocate(strlen(prefix) + strlen(old_conn->Endpoint) + 1);  strcat(strcpy(pname, prefix), old_conn->Endpoint);  status = rpcrt4_conn_create_pipe(old_conn, pname);  I_RpcFree(pname);      return status;}static int rpcrt4_conn_np_read(RpcConnection *Connection,                        void *buffer, unsigned int count){  RpcConnection_np *npc = (RpcConnection_np *) Connection;  char *buf = buffer;  BOOL ret = TRUE;  unsigned int bytes_left = count;  while (bytes_left)  {    DWORD bytes_read;    ret = ReadFile(npc->pipe, buf, bytes_left, &bytes_read, NULL);    if (!ret || !bytes_read)        break;    bytes_left -= bytes_read;    buf += bytes_read;  }  return ret ? count : -1;}static int rpcrt4_conn_np_write(RpcConnection *Connection,                             const void *buffer, unsigned int count){  RpcConnection_np *npc = (RpcConnection_np *) Connection;  const char *buf = buffer;  BOOL ret = TRUE;  unsigned int bytes_left = count;  while (bytes_left)  {    DWORD bytes_written;    ret = WriteFile(npc->pipe, buf, count, &bytes_written, NULL);    if (!ret || !bytes_written)        break;    bytes_left -= bytes_written;    buf += bytes_written;  }  return ret ? count : -1;}static int rpcrt4_conn_np_close(RpcConnection *Connection){  RpcConnection_np *npc = (RpcConnection_np *) Connection;  if (npc->pipe) {    FlushFileBuffers(npc->pipe);    CloseHandle(npc->pipe);    npc->pipe = 0;  }  if (npc->ovl.hEvent) {    CloseHandle(npc->ovl.hEvent);    npc->ovl.hEvent = 0;  }  return 0;}static size_t rpcrt4_ncacn_np_get_top_of_tower(unsigned char *tower_data,                                               const char *networkaddr,                                               const char *endpoint){    twr_empty_floor_t *smb_floor;    twr_empty_floor_t *nb_floor;    size_t size;    size_t networkaddr_size;    size_t endpoint_size;    TRACE("(%p, %s, %s)\n", tower_data, networkaddr, endpoint);    networkaddr_size = strlen(networkaddr) + 1;    endpoint_size = strlen(endpoint) + 1;    size = sizeof(*smb_floor) + endpoint_size + sizeof(*nb_floor) + networkaddr_size;    if (!tower_data)        return size;

⌨️ 快捷键说明

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