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

📄 rpc_server.c

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