ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

rpc_server.c
Go to the documentation of this file.
00001 /*
00002  * RPC server API
00003  *
00004  * Copyright 2001 Ove Kåven, TransGaming Technologies
00005  * Copyright 2004 Filip Navara
00006  * Copyright 2006-2008 Robert Shearman (for CodeWeavers)
00007  *
00008  * This library is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU Lesser General Public
00010  * License as published by the Free Software Foundation; either
00011  * version 2.1 of the License, or (at your option) any later version.
00012  *
00013  * This library is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  * Lesser General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU Lesser General Public
00019  * License along with this library; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00021  */
00022 
00023 #include "config.h"
00024 #include "wine/port.h"
00025 
00026 #include <stdarg.h>
00027 #include <stdio.h>
00028 #include <string.h>
00029 #include <assert.h>
00030 
00031 #include "windef.h"
00032 #include "winbase.h"
00033 #include "winerror.h"
00034 
00035 #include "rpc.h"
00036 #include "rpcndr.h"
00037 #include "excpt.h"
00038 
00039 #include "wine/debug.h"
00040 #include "wine/exception.h"
00041 
00042 #include "rpc_server.h"
00043 #include "rpc_assoc.h"
00044 #include "rpc_message.h"
00045 #include "rpc_defs.h"
00046 #include "ncastatus.h"
00047 
00048 WINE_DEFAULT_DEBUG_CHANNEL(rpc);
00049 
00050 typedef struct _RpcPacket
00051 {
00052   struct _RpcConnection* conn;
00053   RpcPktHdr* hdr;
00054   RPC_MESSAGE* msg;
00055   unsigned char *auth_data;
00056   ULONG auth_length;
00057 } RpcPacket;
00058 
00059 typedef struct _RpcObjTypeMap
00060 {
00061   /* FIXME: a hash table would be better. */
00062   struct _RpcObjTypeMap *next;
00063   UUID Object;
00064   UUID Type;
00065 } RpcObjTypeMap;
00066 
00067 static RpcObjTypeMap *RpcObjTypeMaps;
00068 
00069 /* list of type RpcServerProtseq */
00070 static struct list protseqs = LIST_INIT(protseqs);
00071 static struct list server_interfaces = LIST_INIT(server_interfaces);
00072 static struct list server_registered_auth_info = LIST_INIT(server_registered_auth_info);
00073 
00074 static CRITICAL_SECTION server_cs;
00075 static CRITICAL_SECTION_DEBUG server_cs_debug =
00076 {
00077     0, 0, &server_cs,
00078     { &server_cs_debug.ProcessLocksList, &server_cs_debug.ProcessLocksList },
00079       0, 0, { (DWORD_PTR)(__FILE__ ": server_cs") }
00080 };
00081 static CRITICAL_SECTION server_cs = { &server_cs_debug, -1, 0, 0, 0, 0 };
00082 
00083 static CRITICAL_SECTION listen_cs;
00084 static CRITICAL_SECTION_DEBUG listen_cs_debug =
00085 {
00086     0, 0, &listen_cs,
00087     { &listen_cs_debug.ProcessLocksList, &listen_cs_debug.ProcessLocksList },
00088       0, 0, { (DWORD_PTR)(__FILE__ ": listen_cs") }
00089 };
00090 static CRITICAL_SECTION listen_cs = { &listen_cs_debug, -1, 0, 0, 0, 0 };
00091 
00092 static CRITICAL_SECTION server_auth_info_cs;
00093 static CRITICAL_SECTION_DEBUG server_auth_info_cs_debug =
00094 {
00095     0, 0, &server_auth_info_cs,
00096     { &server_auth_info_cs_debug.ProcessLocksList, &server_auth_info_cs_debug.ProcessLocksList },
00097       0, 0, { (DWORD_PTR)(__FILE__ ": server_auth_info_cs") }
00098 };
00099 static CRITICAL_SECTION server_auth_info_cs = { &server_auth_info_cs_debug, -1, 0, 0, 0, 0 };
00100 
00101 /* whether the server is currently listening */
00102 static BOOL std_listen;
00103 /* number of manual listeners (calls to RpcServerListen) */
00104 static LONG manual_listen_count;
00105 /* total listeners including auto listeners */
00106 static LONG listen_count;
00107 /* event set once all listening is finished */
00108 static HANDLE listen_done_event;
00109 
00110 static UUID uuid_nil;
00111 
00112 static inline RpcObjTypeMap *LookupObjTypeMap(UUID *ObjUuid)
00113 {
00114   RpcObjTypeMap *rslt = RpcObjTypeMaps;
00115   RPC_STATUS dummy;
00116 
00117   while (rslt) {
00118     if (! UuidCompare(ObjUuid, &rslt->Object, &dummy)) break;
00119     rslt = rslt->next;
00120   }
00121 
00122   return rslt;
00123 }
00124 
00125 static inline UUID *LookupObjType(UUID *ObjUuid)
00126 {
00127   RpcObjTypeMap *map = LookupObjTypeMap(ObjUuid);
00128   if (map)
00129     return &map->Type;
00130   else
00131     return &uuid_nil;
00132 }
00133 
00134 static RpcServerInterface* RPCRT4_find_interface(UUID* object,
00135                                                  const RPC_SYNTAX_IDENTIFIER *if_id,
00136                                                  const RPC_SYNTAX_IDENTIFIER *transfer_syntax,
00137                                                  BOOL check_object)
00138 {
00139   UUID* MgrType = NULL;
00140   RpcServerInterface* cif;
00141   RPC_STATUS status;
00142 
00143   if (check_object)
00144     MgrType = LookupObjType(object);
00145   EnterCriticalSection(&server_cs);
00146   LIST_FOR_EACH_ENTRY(cif, &server_interfaces, RpcServerInterface, entry) {
00147     if (!memcmp(if_id, &cif->If->InterfaceId, sizeof(RPC_SYNTAX_IDENTIFIER)) &&
00148         (!transfer_syntax || !memcmp(transfer_syntax, &cif->If->TransferSyntax, sizeof(RPC_SYNTAX_IDENTIFIER))) &&
00149         (check_object == FALSE || UuidEqual(MgrType, &cif->MgrTypeUuid, &status)) &&
00150         std_listen) {
00151       InterlockedIncrement(&cif->CurrentCalls);
00152       break;
00153     }
00154   }
00155   LeaveCriticalSection(&server_cs);
00156   if (&cif->entry == &server_interfaces) cif = NULL;
00157   TRACE("returning %p for object %s, if_id { %d.%d %s }\n", cif,
00158     debugstr_guid(object), if_id->SyntaxVersion.MajorVersion,
00159     if_id->SyntaxVersion.MinorVersion, debugstr_guid(&if_id->SyntaxGUID));
00160   return cif;
00161 }
00162 
00163 static void RPCRT4_release_server_interface(RpcServerInterface *sif)
00164 {
00165   if (!InterlockedDecrement(&sif->CurrentCalls) &&
00166       sif->Delete) {
00167     /* sif must have been removed from server_interfaces before
00168      * CallsCompletedEvent is set */
00169     if (sif->CallsCompletedEvent)
00170       SetEvent(sif->CallsCompletedEvent);
00171     HeapFree(GetProcessHeap(), 0, sif);
00172   }
00173 }
00174 
00175 static RpcPktHdr *handle_bind_error(RpcConnection *conn, RPC_STATUS error)
00176 {
00177     unsigned int reject_reason;
00178     switch (error)
00179     {
00180     case RPC_S_SERVER_TOO_BUSY:
00181         reject_reason = REJECT_TEMPORARY_CONGESTION;
00182         break;
00183     case ERROR_OUTOFMEMORY:
00184     case RPC_S_OUT_OF_RESOURCES:
00185         reject_reason = REJECT_LOCAL_LIMIT_EXCEEDED;
00186         break;
00187     case RPC_S_PROTOCOL_ERROR:
00188         reject_reason = REJECT_PROTOCOL_VERSION_NOT_SUPPORTED;
00189         break;
00190     case RPC_S_UNKNOWN_AUTHN_SERVICE:
00191         reject_reason = REJECT_UNKNOWN_AUTHN_SERVICE;
00192         break;
00193     case ERROR_ACCESS_DENIED:
00194         reject_reason = REJECT_INVALID_CHECKSUM;
00195         break;
00196     default:
00197         FIXME("unexpected status value %d\n", error);
00198         /* fall through */
00199     case RPC_S_INVALID_BOUND:
00200         reject_reason = REJECT_REASON_NOT_SPECIFIED;
00201         break;
00202     }
00203     return RPCRT4_BuildBindNackHeader(NDR_LOCAL_DATA_REPRESENTATION,
00204                                       RPC_VER_MAJOR, RPC_VER_MINOR,
00205                                       reject_reason);
00206 }
00207 
00208 static RPC_STATUS process_bind_packet_no_send(
00209     RpcConnection *conn, RpcPktBindHdr *hdr, RPC_MESSAGE *msg,
00210     unsigned char *auth_data, ULONG auth_length, RpcPktHdr **ack_response,
00211     unsigned char **auth_data_out, ULONG *auth_length_out)
00212 {
00213   RPC_STATUS status;
00214   RpcContextElement *ctxt_elem;
00215   unsigned int i;
00216   RpcResult *results;
00217 
00218   /* validate data */
00219   for (i = 0, ctxt_elem = msg->Buffer;
00220        i < hdr->num_elements;
00221        i++, ctxt_elem = (RpcContextElement *)&ctxt_elem->transfer_syntaxes[ctxt_elem->num_syntaxes])
00222   {
00223       if (((char *)ctxt_elem - (char *)msg->Buffer) > msg->BufferLength ||
00224           ((char *)&ctxt_elem->transfer_syntaxes[ctxt_elem->num_syntaxes] - (char *)msg->Buffer) > msg->BufferLength)
00225       {
00226           ERR("inconsistent data in packet - packet length %d, num elements %d\n",
00227               msg->BufferLength, hdr->num_elements);
00228           return RPC_S_INVALID_BOUND;
00229       }
00230   }
00231 
00232   if (hdr->max_tsize < RPC_MIN_PACKET_SIZE ||
00233       !UuidIsNil(&conn->ActiveInterface.SyntaxGUID, &status) ||
00234       conn->server_binding)
00235   {
00236     TRACE("packet size less than min size, or active interface syntax guid non-null\n");
00237 
00238     return RPC_S_INVALID_BOUND;
00239   }
00240 
00241   results = HeapAlloc(GetProcessHeap(), 0,
00242                       hdr->num_elements * sizeof(*results));
00243   if (!results)
00244     return RPC_S_OUT_OF_RESOURCES;
00245 
00246   for (i = 0, ctxt_elem = (RpcContextElement *)msg->Buffer;
00247        i < hdr->num_elements;
00248        i++, ctxt_elem = (RpcContextElement *)&ctxt_elem->transfer_syntaxes[ctxt_elem->num_syntaxes])
00249   {
00250       RpcServerInterface* sif = NULL;
00251       unsigned int j;
00252 
00253       for (j = 0; !sif && j < ctxt_elem->num_syntaxes; j++)
00254       {
00255           sif = RPCRT4_find_interface(NULL, &ctxt_elem->abstract_syntax,
00256                                       &ctxt_elem->transfer_syntaxes[j], FALSE);
00257           if (sif)
00258               break;
00259       }
00260       if (sif)
00261       {
00262           RPCRT4_release_server_interface(sif);
00263           TRACE("accepting bind request on connection %p for %s\n", conn,
00264                 debugstr_guid(&ctxt_elem->abstract_syntax.SyntaxGUID));
00265           results[i].result = RESULT_ACCEPT;
00266           results[i].reason = REASON_NONE;
00267           results[i].transfer_syntax = ctxt_elem->transfer_syntaxes[j];
00268 
00269           /* save the interface for later use */
00270           /* FIXME: save linked list */
00271           conn->ActiveInterface = ctxt_elem->abstract_syntax;
00272       }
00273       else if ((sif = RPCRT4_find_interface(NULL, &ctxt_elem->abstract_syntax,
00274                                             NULL, FALSE)) != NULL)
00275       {
00276           RPCRT4_release_server_interface(sif);
00277           TRACE("not accepting bind request on connection %p for %s - no transfer syntaxes supported\n",
00278                 conn, debugstr_guid(&ctxt_elem->abstract_syntax.SyntaxGUID));
00279           results[i].result = RESULT_PROVIDER_REJECTION;
00280           results[i].reason = REASON_TRANSFER_SYNTAXES_NOT_SUPPORTED;
00281           memset(&results[i].transfer_syntax, 0, sizeof(results[i].transfer_syntax));
00282       }
00283       else
00284       {
00285           TRACE("not accepting bind request on connection %p for %s - abstract syntax not supported\n",
00286                 conn, debugstr_guid(&ctxt_elem->abstract_syntax.SyntaxGUID));
00287           results[i].result = RESULT_PROVIDER_REJECTION;
00288           results[i].reason = REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
00289           memset(&results[i].transfer_syntax, 0, sizeof(results[i].transfer_syntax));
00290       }
00291   }
00292 
00293   /* create temporary binding */
00294   status = RPCRT4_MakeBinding(&conn->server_binding, conn);
00295   if (status != RPC_S_OK)
00296   {
00297       HeapFree(GetProcessHeap(), 0, results);
00298       return status;
00299   }
00300 
00301   status = RpcServerAssoc_GetAssociation(rpcrt4_conn_get_name(conn),
00302                                          conn->NetworkAddr, conn->Endpoint,
00303                                          conn->NetworkOptions,
00304                                          hdr->assoc_gid,
00305                                          &conn->server_binding->Assoc);
00306   if (status != RPC_S_OK)
00307   {
00308       HeapFree(GetProcessHeap(), 0, results);
00309       return status;
00310   }
00311 
00312   if (auth_length)
00313   {
00314       status = RPCRT4_ServerConnectionAuth(conn, TRUE,
00315                                            (RpcAuthVerifier *)auth_data,
00316                                            auth_length, auth_data_out,
00317                                            auth_length_out);
00318       if (status != RPC_S_OK)
00319       {
00320           HeapFree(GetProcessHeap(), 0, results);
00321           return status;
00322       }
00323   }
00324 
00325   *ack_response = RPCRT4_BuildBindAckHeader(NDR_LOCAL_DATA_REPRESENTATION,
00326                                             RPC_MAX_PACKET_SIZE,
00327                                             RPC_MAX_PACKET_SIZE,
00328                                             conn->server_binding->Assoc->assoc_group_id,
00329                                             conn->Endpoint, hdr->num_elements,
00330                                             results);
00331   HeapFree(GetProcessHeap(), 0, results);
00332 
00333   if (*ack_response)
00334       conn->MaxTransmissionSize = hdr->max_tsize;
00335   else
00336       status = RPC_S_OUT_OF_RESOURCES;
00337 
00338   return status;
00339 }
00340 
00341 static RPC_STATUS process_bind_packet(RpcConnection *conn, RpcPktBindHdr *hdr,
00342                                       RPC_MESSAGE *msg,
00343                                       unsigned char *auth_data,
00344                                       ULONG auth_length)
00345 {
00346     RPC_STATUS status;
00347     RpcPktHdr *response = NULL;
00348     unsigned char *auth_data_out = NULL;
00349     ULONG auth_length_out = 0;
00350 
00351     status = process_bind_packet_no_send(conn, hdr, msg, auth_data, auth_length,
00352                                          &response, &auth_data_out,
00353                                          &auth_length_out);
00354     if (status != RPC_S_OK)
00355         response = handle_bind_error(conn, status);
00356     if (response)
00357         status = RPCRT4_SendWithAuth(conn, response, NULL, 0, auth_data_out, auth_length_out);
00358     else
00359         status = ERROR_OUTOFMEMORY;
00360     RPCRT4_FreeHeader(response);
00361 
00362     return status;
00363 }
00364 
00365 
00366 static RPC_STATUS process_request_packet(RpcConnection *conn, RpcPktRequestHdr *hdr, RPC_MESSAGE *msg)
00367 {
00368   RPC_STATUS status;
00369   RpcPktHdr *response = NULL;
00370   RpcServerInterface* sif;
00371   RPC_DISPATCH_FUNCTION func;
00372   BOOL exception;
00373   UUID *object_uuid;
00374   NDR_SCONTEXT context_handle;
00375   void *buf = msg->Buffer;
00376 
00377   /* fail if the connection isn't bound with an interface */
00378   if (UuidIsNil(&conn->ActiveInterface.SyntaxGUID, &status)) {
00379     /* FIXME: should send BindNack instead */
00380     response = RPCRT4_BuildFaultHeader(NDR_LOCAL_DATA_REPRESENTATION,
00381                                        status);
00382 
00383     RPCRT4_Send(conn, response, NULL, 0);
00384     RPCRT4_FreeHeader(response);
00385     return RPC_S_OK;
00386   }
00387 
00388   if (hdr->common.flags & RPC_FLG_OBJECT_UUID) {
00389     object_uuid = (UUID*)(hdr + 1);
00390   } else {
00391     object_uuid = NULL;
00392   }
00393 
00394   sif = RPCRT4_find_interface(object_uuid, &conn->ActiveInterface, NULL, TRUE);
00395   if (!sif) {
00396     WARN("interface %s no longer registered, returning fault packet\n", debugstr_guid(&conn->ActiveInterface.SyntaxGUID));
00397     response = RPCRT4_BuildFaultHeader(NDR_LOCAL_DATA_REPRESENTATION,
00398                                        NCA_S_UNK_IF);
00399 
00400     RPCRT4_Send(conn, response, NULL, 0);
00401     RPCRT4_FreeHeader(response);
00402     return RPC_S_OK;
00403   }
00404   msg->RpcInterfaceInformation = sif->If;
00405   /* copy the endpoint vector from sif to msg so that midl-generated code will use it */
00406   msg->ManagerEpv = sif->MgrEpv;
00407   if (object_uuid != NULL) {
00408     RPCRT4_SetBindingObject(msg->Handle, object_uuid);
00409   }
00410 
00411   /* find dispatch function */
00412   msg->ProcNum = hdr->opnum;
00413   if (sif->Flags & RPC_IF_OLE) {
00414     /* native ole32 always gives us a dispatch table with a single entry
00415     * (I assume that's a wrapper for IRpcStubBuffer::Invoke) */
00416     func = *sif->If->DispatchTable->DispatchTable;
00417   } else {
00418     if (msg->ProcNum >= sif->If->DispatchTable->DispatchTableCount) {
00419       WARN("invalid procnum (%d/%d)\n", msg->ProcNum, sif->If->DispatchTable->DispatchTableCount);
00420       response = RPCRT4_BuildFaultHeader(NDR_LOCAL_DATA_REPRESENTATION,
00421                                          NCA_S_OP_RNG_ERROR);
00422 
00423       RPCRT4_Send(conn, response, NULL, 0);
00424       RPCRT4_FreeHeader(response);
00425     }
00426     func = sif->If->DispatchTable->DispatchTable[msg->ProcNum];
00427   }
00428 
00429   /* put in the drep. FIXME: is this more universally applicable?
00430     perhaps we should move this outward... */
00431   msg->DataRepresentation =
00432     MAKELONG( MAKEWORD(hdr->common.drep[0], hdr->common.drep[1]),
00433               MAKEWORD(hdr->common.drep[2], hdr->common.drep[3]));
00434 
00435   exception = FALSE;
00436 
00437   /* dispatch */
00438   RPCRT4_SetThreadCurrentCallHandle(msg->Handle);
00439   __TRY {
00440     if (func) func(msg);
00441   } __EXCEPT_ALL {
00442     WARN("exception caught with code 0x%08x = %d\n", GetExceptionCode(), GetExceptionCode());
00443     exception = TRUE;
00444     if (GetExceptionCode() == STATUS_ACCESS_VIOLATION)
00445       status = ERROR_NOACCESS;
00446     else
00447       status = GetExceptionCode();
00448     response = RPCRT4_BuildFaultHeader(msg->DataRepresentation,
00449                                        RPC2NCA_STATUS(status));
00450   } __ENDTRY
00451     RPCRT4_SetThreadCurrentCallHandle(NULL);
00452 
00453   /* release any unmarshalled context handles */
00454   while ((context_handle = RPCRT4_PopThreadContextHandle()) != NULL)
00455     RpcServerAssoc_ReleaseContextHandle(conn->server_binding->Assoc, context_handle, TRUE);
00456 
00457   if (!exception)
00458     response = RPCRT4_BuildResponseHeader(msg->DataRepresentation,
00459                                           msg->BufferLength);
00460 
00461   /* send response packet */
00462   if (response) {
00463     status = RPCRT4_Send(conn, response, exception ? NULL : msg->Buffer,
00464                          exception ? 0 : msg->BufferLength);
00465     RPCRT4_FreeHeader(response);
00466   } else
00467     ERR("out of memory\n");
00468 
00469   msg->RpcInterfaceInformation = NULL;
00470   RPCRT4_release_server_interface(sif);
00471 
00472   if (msg->Buffer == buf) buf = NULL;
00473   TRACE("freeing Buffer=%p\n", buf);
00474   I_RpcFree(buf);
00475 
00476   return status;
00477 }
00478 
00479 static RPC_STATUS process_auth3_packet(RpcConnection *conn,
00480                                        RpcPktCommonHdr *hdr,
00481                                        RPC_MESSAGE *msg,
00482                                        unsigned char *auth_data,
00483                                        ULONG auth_length)
00484 {
00485     RPC_STATUS status;
00486 
00487     if (UuidIsNil(&conn->ActiveInterface.SyntaxGUID, &status) ||
00488         !auth_length || msg->BufferLength != 0)
00489         status = RPC_S_PROTOCOL_ERROR;
00490     else
00491     {
00492         status = RPCRT4_ServerConnectionAuth(conn, FALSE,
00493                                              (RpcAuthVerifier *)auth_data,
00494                                              auth_length, NULL, NULL);
00495     }
00496 
00497     /* FIXME: client doesn't expect a response to this message so must store
00498      * status in connection so that fault packet can be returned when next
00499      * packet is received */
00500 
00501     return RPC_S_OK;
00502 }
00503 
00504 static void RPCRT4_process_packet(RpcConnection* conn, RpcPktHdr* hdr,
00505                                   RPC_MESSAGE* msg, unsigned char *auth_data,
00506                                   ULONG auth_length)
00507 {
00508   msg->Handle = (RPC_BINDING_HANDLE)conn->server_binding;
00509 
00510   switch (hdr->common.ptype) {
00511     case PKT_BIND:
00512       TRACE("got bind packet\n");
00513       process_bind_packet(conn, &hdr->bind, msg, auth_data, auth_length);
00514       break;
00515 
00516     case PKT_REQUEST:
00517       TRACE("got request packet\n");
00518       process_request_packet(conn, &hdr->request, msg);
00519       break;
00520 
00521     case PKT_AUTH3:
00522       TRACE("got auth3 packet\n");
00523       process_auth3_packet(conn, &hdr->common, msg, auth_data, auth_length);
00524       break;
00525     default:
00526       FIXME("unhandled packet type %u\n", hdr->common.ptype);
00527       break;
00528   }
00529 
00530   /* clean up */
00531   I_RpcFree(msg->Buffer);
00532   RPCRT4_FreeHeader(hdr);
00533   HeapFree(GetProcessHeap(), 0, msg);
00534   HeapFree(GetProcessHeap(), 0, auth_data);
00535 }
00536 
00537 static DWORD CALLBACK RPCRT4_worker_thread(LPVOID the_arg)
00538 {
00539   RpcPacket *pkt = the_arg;
00540   RPCRT4_process_packet(pkt->conn, pkt->hdr, pkt->msg, pkt->auth_data,
00541                         pkt->auth_length);
00542   HeapFree(GetProcessHeap(), 0, pkt);
00543   return 0;
00544 }
00545 
00546 static DWORD CALLBACK RPCRT4_io_thread(LPVOID the_arg)
00547 {
00548   RpcConnection* conn = the_arg;
00549   RpcPktHdr *hdr;
00550   RPC_MESSAGE *msg;
00551   RPC_STATUS status;
00552   RpcPacket *packet;
00553   unsigned char *auth_data;
00554   ULONG auth_length;
00555 
00556   TRACE("(%p)\n", conn);
00557 
00558   for (;;) {
00559     msg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RPC_MESSAGE));
00560     if (!msg) break;
00561 
00562     status = RPCRT4_ReceiveWithAuth(conn, &hdr, msg, &auth_data, &auth_length);
00563     if (status != RPC_S_OK) {
00564       WARN("receive failed with error %x\n", status);
00565       HeapFree(GetProcessHeap(), 0, msg);
00566       break;
00567     }
00568 
00569     switch (hdr->common.ptype) {
00570     case PKT_BIND:
00571       TRACE("got bind packet\n");
00572 
00573       status = process_bind_packet(conn, &hdr->bind, msg, auth_data,
00574                                    auth_length);
00575       break;
00576 
00577     case PKT_REQUEST:
00578       TRACE("got request packet\n");
00579 
00580       packet = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcPacket));
00581       if (!packet) {
00582         I_RpcFree(msg->Buffer);
00583         RPCRT4_FreeHeader(hdr);
00584         HeapFree(GetProcessHeap(), 0, msg);
00585         HeapFree(GetProcessHeap(), 0, auth_data);
00586         goto exit;
00587       }
00588       packet->conn = conn;
00589       packet->hdr = hdr;
00590       packet->msg = msg;
00591       packet->auth_data = auth_data;
00592       packet->auth_length = auth_length;
00593       if (!QueueUserWorkItem(RPCRT4_worker_thread, packet, WT_EXECUTELONGFUNCTION)) {
00594         ERR("couldn't queue work item for worker thread, error was %d\n", GetLastError());
00595         HeapFree(GetProcessHeap(), 0, packet);
00596         status = RPC_S_OUT_OF_RESOURCES;
00597       } else {
00598         continue;
00599       }
00600       break;
00601 
00602     case PKT_AUTH3:
00603       TRACE("got auth3 packet\n");
00604 
00605       status = process_auth3_packet(conn, &hdr->common, msg, auth_data,
00606                                     auth_length);
00607       break;
00608     default:
00609       FIXME("unhandled packet type %u\n", hdr->common.ptype);
00610       break;
00611     }
00612 
00613     I_RpcFree(msg->Buffer);
00614     RPCRT4_FreeHeader(hdr);
00615     HeapFree(GetProcessHeap(), 0, msg);
00616     HeapFree(GetProcessHeap(), 0, auth_data);
00617 
00618     if (status != RPC_S_OK) {
00619       WARN("processing packet failed with error %u\n", status);
00620       break;
00621     }
00622   }
00623 exit:
00624   RPCRT4_DestroyConnection(conn);
00625   return 0;
00626 }
00627 
00628 void RPCRT4_new_client(RpcConnection* conn)
00629 {
00630   HANDLE thread = CreateThread(NULL, 0, RPCRT4_io_thread, conn, 0, NULL);
00631   if (!thread) {
00632     DWORD err = GetLastError();
00633     ERR("failed to create thread, error=%08x\n", err);
00634     RPCRT4_DestroyConnection(conn);
00635   }
00636   /* we could set conn->thread, but then we'd have to make the io_thread wait
00637    * for that, otherwise the thread might finish, destroy the connection, and
00638    * free the memory we'd write to before we did, causing crashes and stuff -
00639    * so let's implement that later, when we really need conn->thread */
00640 
00641   CloseHandle( thread );
00642 }
00643 
00644 static DWORD CALLBACK RPCRT4_server_thread(LPVOID the_arg)
00645 {
00646   int res;
00647   unsigned int count;
00648   void *objs = NULL;
00649   RpcServerProtseq* cps = the_arg;
00650   RpcConnection* conn;
00651   BOOL set_ready_event = FALSE;
00652 
00653   TRACE("(the_arg == ^%p)\n", the_arg);
00654 
00655   for (;;) {
00656     objs = cps->ops->get_wait_array(cps, objs, &count);
00657 
00658     if (set_ready_event)
00659     {
00660         /* signal to function that changed state that we are now sync'ed */
00661         SetEvent(cps->server_ready_event);
00662         set_ready_event = FALSE;
00663     }
00664 
00665     /* start waiting */
00666     res = cps->ops->wait_for_new_connection(cps, count, objs);
00667 
00668     if (res == -1 || (res == 0 && !std_listen))
00669     {
00670       /* cleanup */
00671       cps->ops->free_wait_array(cps, objs);
00672       EnterCriticalSection(&cps->cs);
00673       for (conn = cps->conn; conn; conn = conn->Next)
00674         RPCRT4_CloseConnection(conn);
00675       LeaveCriticalSection(&cps->cs);
00676 
00677       if (res == 0 && !std_listen)
00678         SetEvent(cps->server_ready_event);
00679       break;
00680     }
00681     else if (res == 0)
00682       set_ready_event = TRUE;
00683   }
00684   return 0;
00685 }
00686 
00687 /* tells the server thread that the state has changed and waits for it to
00688  * make the changes */
00689 static void RPCRT4_sync_with_server_thread(RpcServerProtseq *ps)
00690 {
00691   /* make sure we are the only thread sync'ing the server state, otherwise
00692    * there is a race with the server thread setting an older state and setting
00693    * the server_ready_event when the new state hasn't yet been applied */
00694   WaitForSingleObject(ps->mgr_mutex, INFINITE);
00695 
00696   ps->ops->signal_state_changed(ps);
00697 
00698   /* wait for server thread to make the requested changes before returning */
00699   WaitForSingleObject(ps->server_ready_event, INFINITE);
00700 
00701   ReleaseMutex(ps->mgr_mutex);
00702 }
00703 
00704 static RPC_STATUS RPCRT4_start_listen_protseq(RpcServerProtseq *ps, BOOL auto_listen)
00705 {
00706   RPC_STATUS status = RPC_S_OK;
00707   HANDLE server_thread;
00708 
00709   EnterCriticalSection(&listen_cs);
00710   if (ps->is_listening) goto done;
00711 
00712   if (!ps->mgr_mutex) ps->mgr_mutex = CreateMutexW(NULL, FALSE, NULL);
00713   if (!ps->server_ready_event) ps->server_ready_event = CreateEventW(NULL, FALSE, FALSE, NULL);
00714   server_thread = CreateThread(NULL, 0, RPCRT4_server_thread, ps, 0, NULL);
00715   if (!server_thread)
00716   {
00717     status = RPC_S_OUT_OF_RESOURCES;
00718     goto done;
00719   }
00720   ps->is_listening = TRUE;
00721   CloseHandle(server_thread);
00722 
00723 done:
00724   LeaveCriticalSection(&listen_cs);
00725   return status;
00726 }
00727 
00728 static RPC_STATUS RPCRT4_start_listen(BOOL auto_listen)
00729 {
00730   RPC_STATUS status = RPC_S_ALREADY_LISTENING;
00731   RpcServerProtseq *cps;
00732 
00733   TRACE("\n");
00734 
00735   EnterCriticalSection(&listen_cs);
00736   if (auto_listen || (manual_listen_count++ == 0))
00737   {
00738     status = RPC_S_OK;
00739     if (++listen_count == 1)
00740       std_listen = TRUE;
00741   }
00742   LeaveCriticalSection(&listen_cs);
00743 
00744   if (std_listen)
00745   {
00746     EnterCriticalSection(&server_cs);
00747     LIST_FOR_EACH_ENTRY(cps, &protseqs, RpcServerProtseq, entry)
00748     {
00749       status = RPCRT4_start_listen_protseq(cps, TRUE);
00750       if (status != RPC_S_OK)
00751         break;
00752       
00753       /* make sure server is actually listening on the interface before
00754        * returning */
00755       RPCRT4_sync_with_server_thread(cps);
00756     }
00757     LeaveCriticalSection(&server_cs);
00758   }
00759 
00760   return status;
00761 }
00762 
00763 static void RPCRT4_stop_listen(BOOL auto_listen)
00764 {
00765   EnterCriticalSection(&listen_cs);
00766   if (auto_listen || (--manual_listen_count == 0))
00767   {
00768     if (listen_count != 0 && --listen_count == 0) {
00769       RpcServerProtseq *cps;
00770 
00771       std_listen = FALSE;
00772       LeaveCriticalSection(&listen_cs);
00773 
00774       LIST_FOR_EACH_ENTRY(cps, &protseqs, RpcServerProtseq, entry)
00775         RPCRT4_sync_with_server_thread(cps);
00776 
00777       EnterCriticalSection(&listen_cs);
00778       if (listen_done_event) SetEvent( listen_done_event );
00779       listen_done_event = 0;
00780       LeaveCriticalSection(&listen_cs);
00781       return;
00782     }
00783     assert(listen_count >= 0);
00784   }
00785   LeaveCriticalSection(&listen_cs);
00786 }
00787 
00788 static BOOL RPCRT4_protseq_is_endpoint_registered(RpcServerProtseq *protseq, const char *endpoint)
00789 {
00790   RpcConnection *conn;
00791   EnterCriticalSection(&protseq->cs);
00792   for (conn = protseq->conn; conn; conn = conn->Next)
00793   {
00794     if (!endpoint || !strcmp(endpoint, conn->Endpoint))
00795       break;
00796   }
00797   LeaveCriticalSection(&protseq->cs);
00798   return (conn != NULL);
00799 }
00800 
00801 static RPC_STATUS RPCRT4_use_protseq(RpcServerProtseq* ps, const char *endpoint)
00802 {
00803   RPC_STATUS status;
00804 
00805   EnterCriticalSection(&ps->cs);
00806 
00807   if (RPCRT4_protseq_is_endpoint_registered(ps, endpoint))
00808     status = RPC_S_OK;
00809   else
00810     status = ps->ops->open_endpoint(ps, endpoint);
00811 
00812   LeaveCriticalSection(&ps->cs);
00813 
00814   if (status != RPC_S_OK)
00815     return status;
00816 
00817   if (std_listen)
00818   {
00819     status = RPCRT4_start_listen_protseq(ps, FALSE);
00820     if (status == RPC_S_OK)
00821       RPCRT4_sync_with_server_thread(ps);
00822   }
00823 
00824   return status;
00825 }
00826 
00827 /***********************************************************************
00828  *             RpcServerInqBindings (RPCRT4.@)
00829  */
00830 RPC_STATUS WINAPI RpcServerInqBindings( RPC_BINDING_VECTOR** BindingVector )
00831 {
00832   RPC_STATUS status;
00833   DWORD count;
00834   RpcServerProtseq* ps;
00835   RpcConnection* conn;
00836 
00837   if (BindingVector)
00838     TRACE("(*BindingVector == ^%p)\n", *BindingVector);
00839   else
00840     ERR("(BindingVector == NULL!!?)\n");
00841 
00842   EnterCriticalSection(&server_cs);
00843   /* count connections */
00844   count = 0;
00845   LIST_FOR_EACH_ENTRY(ps, &protseqs, RpcServerProtseq, entry) {
00846     EnterCriticalSection(&ps->cs);
00847     for (conn = ps->conn; conn; conn = conn->Next)
00848       count++;
00849     LeaveCriticalSection(&ps->cs);
00850   }
00851   if (count) {
00852     /* export bindings */
00853     *BindingVector = HeapAlloc(GetProcessHeap(), 0,
00854                               sizeof(RPC_BINDING_VECTOR) +
00855                               sizeof(RPC_BINDING_HANDLE)*(count-1));
00856     (*BindingVector)->Count = count;
00857     count = 0;
00858     LIST_FOR_EACH_ENTRY(ps, &protseqs, RpcServerProtseq, entry) {
00859       EnterCriticalSection(&ps->cs);
00860       for (conn = ps->conn; conn; conn = conn->Next) {
00861        RPCRT4_MakeBinding((RpcBinding**)&(*BindingVector)->BindingH[count],
00862                           conn);
00863        count++;
00864       }
00865       LeaveCriticalSection(&ps->cs);
00866     }
00867     status = RPC_S_OK;
00868   } else {
00869     *BindingVector = NULL;
00870     status = RPC_S_NO_BINDINGS;
00871   }
00872   LeaveCriticalSection(&server_cs);
00873   return status;
00874 }
00875 
00876 /***********************************************************************
00877  *             RpcServerUseProtseqEpA (RPCRT4.@)
00878  */
00879 RPC_STATUS WINAPI RpcServerUseProtseqEpA( RPC_CSTR Protseq, UINT MaxCalls, RPC_CSTR Endpoint, LPVOID SecurityDescriptor )
00880 {
00881   RPC_POLICY policy;
00882   
00883   TRACE( "(%s,%u,%s,%p)\n", Protseq, MaxCalls, Endpoint, SecurityDescriptor );
00884   
00885   /* This should provide the default behaviour */
00886   policy.Length        = sizeof( policy );
00887   policy.EndpointFlags = 0;
00888   policy.NICFlags      = 0;
00889   
00890   return RpcServerUseProtseqEpExA( Protseq, MaxCalls, Endpoint, SecurityDescriptor, &policy );
00891 }
00892 
00893 /***********************************************************************
00894  *             RpcServerUseProtseqEpW (RPCRT4.@)
00895  */
00896 RPC_STATUS WINAPI RpcServerUseProtseqEpW( RPC_WSTR Protseq, UINT MaxCalls, RPC_WSTR Endpoint, LPVOID SecurityDescriptor )
00897 {
00898   RPC_POLICY policy;
00899   
00900   TRACE( "(%s,%u,%s,%p)\n", debugstr_w( Protseq ), MaxCalls, debugstr_w( Endpoint ), SecurityDescriptor );
00901   
00902   /* This should provide the default behaviour */
00903   policy.Length        = sizeof( policy );
00904   policy.EndpointFlags = 0;
00905   policy.NICFlags      = 0;
00906   
00907   return RpcServerUseProtseqEpExW( Protseq, MaxCalls, Endpoint, SecurityDescriptor, &policy );
00908 }
00909 
00910 /***********************************************************************
00911  *             alloc_serverprotoseq (internal)
00912  *
00913  * Must be called with server_cs held.
00914  */
00915 static RPC_STATUS alloc_serverprotoseq(UINT MaxCalls, const char *Protseq, RpcServerProtseq **ps)
00916 {
00917   const struct protseq_ops *ops = rpcrt4_get_protseq_ops(Protseq);
00918 
00919   if (!ops)
00920   {
00921     FIXME("protseq %s not supported\n", debugstr_a(Protseq));
00922     return RPC_S_PROTSEQ_NOT_SUPPORTED;
00923   }
00924 
00925   *ps = ops->alloc();
00926   if (!*ps)
00927     return RPC_S_OUT_OF_RESOURCES;
00928   (*ps)->MaxCalls = MaxCalls;
00929   (*ps)->Protseq = RPCRT4_strdupA(Protseq);
00930   (*ps)->ops = ops;
00931   (*ps)->MaxCalls = 0;
00932   (*ps)->conn = NULL;
00933   InitializeCriticalSection(&(*ps)->cs);
00934   (*ps)->is_listening = FALSE;
00935   (*ps)->mgr_mutex = NULL;
00936   (*ps)->server_ready_event = NULL;
00937 
00938   list_add_head(&protseqs, &(*ps)->entry);
00939 
00940   TRACE("new protseq %p created for %s\n", *ps, Protseq);
00941 
00942   return RPC_S_OK;
00943 }
00944 
00945 /* must be called with server_cs held */
00946 static void destroy_serverprotoseq(RpcServerProtseq *ps)
00947 {
00948     RPCRT4_strfree(ps->Protseq);
00949     DeleteCriticalSection(&ps->cs);
00950     CloseHandle(ps->mgr_mutex);
00951     CloseHandle(ps->server_ready_event);
00952     list_remove(&ps->entry);
00953     HeapFree(GetProcessHeap(), 0, ps);
00954 }
00955 
00956 /* Finds a given protseq or creates a new one if one doesn't already exist */
00957 static RPC_STATUS RPCRT4_get_or_create_serverprotseq(UINT MaxCalls, const char *Protseq, RpcServerProtseq **ps)
00958 {
00959     RPC_STATUS status;
00960     RpcServerProtseq *cps;
00961 
00962     EnterCriticalSection(&server_cs);
00963 
00964     LIST_FOR_EACH_ENTRY(cps, &protseqs, RpcServerProtseq, entry)
00965         if (!strcmp(cps->Protseq, Protseq))
00966         {
00967             TRACE("found existing protseq object for %s\n", Protseq);
00968             *ps = cps;
00969             LeaveCriticalSection(&server_cs);
00970             return S_OK;
00971         }
00972 
00973     status = alloc_serverprotoseq(MaxCalls, Protseq, ps);
00974 
00975     LeaveCriticalSection(&server_cs);
00976 
00977     return status;
00978 }
00979 
00980 /***********************************************************************
00981  *             RpcServerUseProtseqEpExA (RPCRT4.@)
00982  */
00983 RPC_STATUS WINAPI RpcServerUseProtseqEpExA( RPC_CSTR Protseq, UINT MaxCalls, RPC_CSTR Endpoint, LPVOID SecurityDescriptor,
00984                                             PRPC_POLICY lpPolicy )
00985 {
00986   RpcServerProtseq* ps;
00987   RPC_STATUS status;
00988 
00989   TRACE("(%s,%u,%s,%p,{%u,%u,%u})\n", debugstr_a((const char *)Protseq),
00990        MaxCalls, debugstr_a((const char *)Endpoint), SecurityDescriptor,
00991        lpPolicy->Length, lpPolicy->EndpointFlags, lpPolicy->NICFlags );
00992 
00993   status = RPCRT4_get_or_create_serverprotseq(MaxCalls, (const char *)Protseq, &ps);
00994   if (status != RPC_S_OK)
00995     return status;
00996 
00997   return RPCRT4_use_protseq(ps, (const char *)Endpoint);
00998 }
00999 
01000 /***********************************************************************
01001  *             RpcServerUseProtseqEpExW (RPCRT4.@)
01002  */
01003 RPC_STATUS WINAPI RpcServerUseProtseqEpExW( RPC_WSTR Protseq, UINT MaxCalls, RPC_WSTR Endpoint, LPVOID SecurityDescriptor,
01004                                             PRPC_POLICY lpPolicy )
01005 {
01006   RpcServerProtseq* ps;
01007   RPC_STATUS status;
01008   LPSTR ProtseqA;
01009   LPSTR EndpointA;
01010 
01011   TRACE("(%s,%u,%s,%p,{%u,%u,%u})\n", debugstr_w( Protseq ), MaxCalls,
01012        debugstr_w( Endpoint ), SecurityDescriptor,
01013        lpPolicy->Length, lpPolicy->EndpointFlags, lpPolicy->NICFlags );
01014 
01015   ProtseqA = RPCRT4_strdupWtoA(Protseq);
01016   status = RPCRT4_get_or_create_serverprotseq(MaxCalls, ProtseqA, &ps);
01017   RPCRT4_strfree(ProtseqA);
01018   if (status != RPC_S_OK)
01019     return status;
01020 
01021   EndpointA = RPCRT4_strdupWtoA(Endpoint);
01022   status = RPCRT4_use_protseq(ps, EndpointA);
01023   RPCRT4_strfree(EndpointA);
01024   return status;
01025 }
01026 
01027 /***********************************************************************
01028  *             RpcServerUseProtseqA (RPCRT4.@)
01029  */
01030 RPC_STATUS WINAPI RpcServerUseProtseqA(RPC_CSTR Protseq, unsigned int MaxCalls, void *SecurityDescriptor)
01031 {
01032   RPC_STATUS status;
01033   RpcServerProtseq* ps;
01034 
01035   TRACE("(Protseq == %s, MaxCalls == %d, SecurityDescriptor == ^%p)\n", debugstr_a((char*)Protseq), MaxCalls, SecurityDescriptor);
01036 
01037   status = RPCRT4_get_or_create_serverprotseq(MaxCalls, (const char *)Protseq, &ps);
01038   if (status != RPC_S_OK)
01039     return status;
01040 
01041   return RPCRT4_use_protseq(ps, NULL);
01042 }
01043 
01044 /***********************************************************************
01045  *             RpcServerUseProtseqW (RPCRT4.@)
01046  */
01047 RPC_STATUS WINAPI RpcServerUseProtseqW(RPC_WSTR Protseq, unsigned int MaxCalls, void *SecurityDescriptor)
01048 {
01049   RPC_STATUS status;
01050   RpcServerProtseq* ps;
01051   LPSTR ProtseqA;
01052 
01053   TRACE("Protseq == %s, MaxCalls == %d, SecurityDescriptor == ^%p)\n", debugstr_w(Protseq), MaxCalls, SecurityDescriptor);
01054 
01055   ProtseqA = RPCRT4_strdupWtoA(Protseq);
01056   status = RPCRT4_get_or_create_serverprotseq(MaxCalls, ProtseqA, &ps);
01057   RPCRT4_strfree(ProtseqA);
01058   if (status != RPC_S_OK)
01059     return status;
01060 
01061   return RPCRT4_use_protseq(ps, NULL);
01062 }
01063 
01064 void RPCRT4_destroy_all_protseqs(void)
01065 {
01066     RpcServerProtseq *cps, *cursor2;
01067 
01068     if (listen_count != 0)
01069         std_listen = FALSE;
01070 
01071     EnterCriticalSection(&server_cs);
01072     LIST_FOR_EACH_ENTRY_SAFE(cps, cursor2, &protseqs, RpcServerProtseq, entry)
01073     {
01074         destroy_serverprotoseq(cps);
01075     }
01076     LeaveCriticalSection(&server_cs);
01077 }
01078 
01079 /***********************************************************************
01080  *             RpcServerRegisterIf (RPCRT4.@)
01081  */
01082 RPC_STATUS WINAPI RpcServerRegisterIf( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, RPC_MGR_EPV* MgrEpv )
01083 {
01084   TRACE("(%p,%s,%p)\n", IfSpec, debugstr_guid(MgrTypeUuid), MgrEpv);
01085   return RpcServerRegisterIf2( IfSpec, MgrTypeUuid, MgrEpv, 0, RPC_C_LISTEN_MAX_CALLS_DEFAULT, (UINT)-1, NULL );
01086 }
01087 
01088 /***********************************************************************
01089  *             RpcServerRegisterIfEx (RPCRT4.@)
01090  */
01091 RPC_STATUS WINAPI RpcServerRegisterIfEx( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, RPC_MGR_EPV* MgrEpv,
01092                        UINT Flags, UINT MaxCalls, RPC_IF_CALLBACK_FN* IfCallbackFn )
01093 {
01094   TRACE("(%p,%s,%p,%u,%u,%p)\n", IfSpec, debugstr_guid(MgrTypeUuid), MgrEpv, Flags, MaxCalls, IfCallbackFn);
01095   return RpcServerRegisterIf2( IfSpec, MgrTypeUuid, MgrEpv, Flags, MaxCalls, (UINT)-1, IfCallbackFn );
01096 }
01097 
01098 /***********************************************************************
01099  *             RpcServerRegisterIf2 (RPCRT4.@)
01100  */
01101 RPC_STATUS WINAPI RpcServerRegisterIf2( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, RPC_MGR_EPV* MgrEpv,
01102                       UINT Flags, UINT MaxCalls, UINT MaxRpcSize, RPC_IF_CALLBACK_FN* IfCallbackFn )
01103 {
01104   PRPC_SERVER_INTERFACE If = IfSpec;
01105   RpcServerInterface* sif;
01106   unsigned int i;
01107 
01108   TRACE("(%p,%s,%p,%u,%u,%u,%p)\n", IfSpec, debugstr_guid(MgrTypeUuid), MgrEpv, Flags, MaxCalls,
01109          MaxRpcSize, IfCallbackFn);
01110   TRACE(" interface id: %s %d.%d\n", debugstr_guid(&If->InterfaceId.SyntaxGUID),
01111                                      If->InterfaceId.SyntaxVersion.MajorVersion,
01112                                      If->InterfaceId.SyntaxVersion.MinorVersion);
01113   TRACE(" transfer syntax: %s %d.%d\n", debugstr_guid(&If->TransferSyntax.SyntaxGUID),
01114                                         If->TransferSyntax.SyntaxVersion.MajorVersion,
01115                                         If->TransferSyntax.SyntaxVersion.MinorVersion);
01116   TRACE(" dispatch table: %p\n", If->DispatchTable);
01117   if (If->DispatchTable) {
01118     TRACE("  dispatch table count: %d\n", If->DispatchTable->DispatchTableCount);
01119     for (i=0; i<If->DispatchTable->DispatchTableCount; i++) {
01120       TRACE("   entry %d: %p\n", i, If->DispatchTable->DispatchTable[i]);
01121     }
01122     TRACE("  reserved: %ld\n", If->DispatchTable->Reserved);
01123   }
01124   TRACE(" protseq endpoint count: %d\n", If->RpcProtseqEndpointCount);
01125   TRACE(" default manager epv: %p\n", If->DefaultManagerEpv);
01126   TRACE(" interpreter info: %p\n", If->InterpreterInfo);
01127 
01128   sif = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcServerInterface));
01129   sif->If           = If;
01130   if (MgrTypeUuid) {
01131     sif->MgrTypeUuid = *MgrTypeUuid;
01132     sif->MgrEpv       = MgrEpv;
01133   } else {
01134     memset(&sif->MgrTypeUuid, 0, sizeof(UUID));
01135     sif->MgrEpv       = If->DefaultManagerEpv;
01136   }
01137   sif->Flags        = Flags;
01138   sif->MaxCalls     = MaxCalls;
01139   sif->MaxRpcSize   = MaxRpcSize;
01140   sif->IfCallbackFn = IfCallbackFn;
01141 
01142   EnterCriticalSection(&server_cs);
01143   list_add_head(&server_interfaces, &sif->entry);
01144   LeaveCriticalSection(&server_cs);
01145 
01146   if (sif->Flags & RPC_IF_AUTOLISTEN)
01147       RPCRT4_start_listen(TRUE);
01148 
01149   return RPC_S_OK;
01150 }
01151 
01152 /***********************************************************************
01153  *             RpcServerUnregisterIf (RPCRT4.@)
01154  */
01155 RPC_STATUS WINAPI RpcServerUnregisterIf( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, UINT WaitForCallsToComplete )
01156 {
01157   PRPC_SERVER_INTERFACE If = IfSpec;
01158   HANDLE event = NULL;
01159   BOOL found = FALSE;
01160   BOOL completed = TRUE;
01161   RpcServerInterface *cif;
01162   RPC_STATUS status;
01163 
01164   TRACE("(IfSpec == (RPC_IF_HANDLE)^%p (%s), MgrTypeUuid == %s, WaitForCallsToComplete == %u)\n",
01165     IfSpec, debugstr_guid(&If->InterfaceId.SyntaxGUID), debugstr_guid(MgrTypeUuid), WaitForCallsToComplete);
01166 
01167   EnterCriticalSection(&server_cs);
01168   LIST_FOR_EACH_ENTRY(cif, &server_interfaces, RpcServerInterface, entry) {
01169     if ((!IfSpec || !memcmp(&If->InterfaceId, &cif->If->InterfaceId, sizeof(RPC_SYNTAX_IDENTIFIER))) &&
01170         UuidEqual(MgrTypeUuid, &cif->MgrTypeUuid, &status)) {
01171       list_remove(&cif->entry);
01172       TRACE("unregistering cif %p\n", cif);
01173       if (cif->CurrentCalls) {
01174         completed = FALSE;
01175         cif->Delete = TRUE;
01176         if (WaitForCallsToComplete)
01177           cif->CallsCompletedEvent = event = CreateEventW(NULL, FALSE, FALSE, NULL);
01178       }
01179       found = TRUE;
01180       break;
01181     }
01182   }
01183   LeaveCriticalSection(&server_cs);
01184 
01185   if (!found) {
01186     ERR("not found for object %s\n", debugstr_guid(MgrTypeUuid));
01187     return RPC_S_UNKNOWN_IF;
01188   }
01189 
01190   if (completed)
01191     HeapFree(GetProcessHeap(), 0, cif);
01192   else if (event) {
01193     /* sif will be freed when the last call is completed, so be careful not to
01194      * touch that memory here as that could happen before we get here */
01195     WaitForSingleObject(event, INFINITE);
01196     CloseHandle(event);
01197   }
01198 
01199   return RPC_S_OK;
01200 }
01201 
01202 /***********************************************************************
01203  *             RpcServerUnregisterIfEx (RPCRT4.@)
01204  */
01205 RPC_STATUS WINAPI RpcServerUnregisterIfEx( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, int RundownContextHandles )
01206 {
01207   FIXME("(IfSpec == (RPC_IF_HANDLE)^%p, MgrTypeUuid == %s, RundownContextHandles == %d): stub\n",
01208     IfSpec, debugstr_guid(MgrTypeUuid), RundownContextHandles);
01209 
01210   return RPC_S_OK;
01211 }
01212 
01213 /***********************************************************************
01214  *             RpcObjectSetType (RPCRT4.@)
01215  *
01216  * PARAMS
01217  *   ObjUuid  [I] "Object" UUID
01218  *   TypeUuid [I] "Type" UUID
01219  *
01220  * RETURNS
01221  *   RPC_S_OK                 The call succeeded
01222  *   RPC_S_INVALID_OBJECT     The provided object (nil) is not valid
01223  *   RPC_S_ALREADY_REGISTERED The provided object is already registered
01224  *
01225  * Maps "Object" UUIDs to "Type" UUIDs.  Passing the nil UUID as the type
01226  * resets the mapping for the specified object UUID to nil (the default).
01227  * The nil object is always associated with the nil type and cannot be
01228  * reassigned.  Servers can support multiple implementations on the same
01229  * interface by registering different end-point vectors for the different
01230  * types.  There's no need to call this if a server only supports the nil
01231  * type, as is typical.
01232  */
01233 RPC_STATUS WINAPI RpcObjectSetType( UUID* ObjUuid, UUID* TypeUuid )
01234 {
01235   RpcObjTypeMap *map = RpcObjTypeMaps, *prev = NULL;
01236   RPC_STATUS dummy;
01237 
01238   TRACE("(ObjUUID == %s, TypeUuid == %s).\n", debugstr_guid(ObjUuid), debugstr_guid(TypeUuid));
01239   if ((! ObjUuid) || UuidIsNil(ObjUuid, &dummy)) {
01240     /* nil uuid cannot be remapped */
01241     return RPC_S_INVALID_OBJECT;
01242   }
01243 
01244   /* find the mapping for this object if there is one ... */
01245   while (map) {
01246     if (! UuidCompare(ObjUuid, &map->Object, &dummy)) break;
01247     prev = map;
01248     map = map->next;
01249   }
01250   if ((! TypeUuid) || UuidIsNil(TypeUuid, &dummy)) {
01251     /* ... and drop it from the list */
01252     if (map) {
01253       if (prev) 
01254         prev->next = map->next;
01255       else
01256         RpcObjTypeMaps = map->next;
01257       HeapFree(GetProcessHeap(), 0, map);
01258     }
01259   } else {
01260     /* ... , fail if we found it ... */
01261     if (map)
01262       return RPC_S_ALREADY_REGISTERED;
01263     /* ... otherwise create a new one and add it in. */
01264     map = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcObjTypeMap));
01265     map->Object = *ObjUuid;
01266     map->Type = *TypeUuid;
01267     map->next = NULL;
01268     if (prev)
01269       prev->next = map; /* prev is the last map in the linklist */
01270     else
01271       RpcObjTypeMaps = map;
01272   }
01273 
01274   return RPC_S_OK;
01275 }
01276 
01277 struct rpc_server_registered_auth_info
01278 {
01279     struct list entry;
01280     TimeStamp exp;
01281     CredHandle cred;
01282     ULONG max_token;
01283     USHORT auth_type;
01284 };
01285 
01286 RPC_STATUS RPCRT4_ServerGetRegisteredAuthInfo(
01287     USHORT auth_type, CredHandle *cred, TimeStamp *exp, ULONG *max_token)
01288 {
01289     RPC_STATUS status = RPC_S_UNKNOWN_AUTHN_SERVICE;
01290     struct rpc_server_registered_auth_info *auth_info;
01291 
01292     EnterCriticalSection(&server_auth_info_cs);
01293     LIST_FOR_EACH_ENTRY(auth_info, &server_registered_auth_info, struct rpc_server_registered_auth_info, entry)
01294     {
01295         if (auth_info->auth_type == auth_type)
01296         {
01297             *cred = auth_info->cred;
01298             *exp = auth_info->exp;
01299             *max_token = auth_info->max_token;
01300             status = RPC_S_OK;
01301             break;
01302         }
01303     }
01304     LeaveCriticalSection(&server_auth_info_cs);
01305 
01306     return status;
01307 }
01308 
01309 void RPCRT4_ServerFreeAllRegisteredAuthInfo(void)
01310 {
01311     struct rpc_server_registered_auth_info *auth_info, *cursor2;
01312 
01313     EnterCriticalSection(&server_auth_info_cs);
01314     LIST_FOR_EACH_ENTRY_SAFE(auth_info, cursor2, &server_registered_auth_info, struct rpc_server_registered_auth_info, entry)
01315     {
01316         FreeCredentialsHandle(&auth_info->cred);
01317         HeapFree(GetProcessHeap(), 0, auth_info);
01318     }
01319     LeaveCriticalSection(&server_auth_info_cs);
01320 }
01321 
01322 /***********************************************************************
01323  *             RpcServerRegisterAuthInfoA (RPCRT4.@)
01324  */
01325 RPC_STATUS WINAPI RpcServerRegisterAuthInfoA( RPC_CSTR ServerPrincName, ULONG AuthnSvc, RPC_AUTH_KEY_RETRIEVAL_FN GetKeyFn,
01326                             LPVOID Arg )
01327 {
01328     SECURITY_STATUS sec_status;
01329     CredHandle cred;
01330     TimeStamp exp;
01331     ULONG package_count;
01332     ULONG i;
01333     PSecPkgInfoA packages;
01334     ULONG max_token;
01335     struct rpc_server_registered_auth_info *auth_info;
01336 
01337     TRACE("(%s,%u,%p,%p)\n", ServerPrincName, AuthnSvc, GetKeyFn, Arg);
01338 
01339     sec_status = EnumerateSecurityPackagesA(&package_count, &packages);
01340     if (sec_status != SEC_E_OK)
01341     {
01342         ERR("EnumerateSecurityPackagesA failed with error 0x%08x\n",
01343             sec_status);
01344         return RPC_S_SEC_PKG_ERROR;
01345     }
01346 
01347     for (i = 0; i < package_count; i++)
01348         if (packages[i].wRPCID == AuthnSvc)
01349             break;
01350 
01351     if (i == package_count)
01352     {
01353         WARN("unsupported AuthnSvc %u\n", AuthnSvc);
01354         FreeContextBuffer(packages);
01355         return RPC_S_UNKNOWN_AUTHN_SERVICE;
01356     }
01357     TRACE("found package %s for service %u\n", packages[i].Name,
01358           AuthnSvc);
01359     sec_status = AcquireCredentialsHandleA((SEC_CHAR *)ServerPrincName,
01360                                            packages[i].Name,
01361                                            SECPKG_CRED_INBOUND, NULL, NULL,
01362                                            NULL, NULL, &cred, &exp);
01363     max_token = packages[i].cbMaxToken;
01364     FreeContextBuffer(packages);
01365     if (sec_status != SEC_E_OK)
01366         return RPC_S_SEC_PKG_ERROR;
01367 
01368     auth_info = HeapAlloc(GetProcessHeap(), 0, sizeof(*auth_info));
01369     if (!auth_info)
01370     {
01371         FreeCredentialsHandle(&cred);
01372         return RPC_S_OUT_OF_RESOURCES;
01373     }
01374 
01375     auth_info->exp = exp;
01376     auth_info->cred = cred;
01377     auth_info->max_token = max_token;
01378     auth_info->auth_type = AuthnSvc;
01379 
01380     EnterCriticalSection(&server_auth_info_cs);
01381     list_add_tail(&server_registered_auth_info, &auth_info->entry);
01382     LeaveCriticalSection(&server_auth_info_cs);
01383 
01384     return RPC_S_OK;
01385 }
01386 
01387 /***********************************************************************
01388  *             RpcServerRegisterAuthInfoW (RPCRT4.@)
01389  */
01390 RPC_STATUS WINAPI RpcServerRegisterAuthInfoW( RPC_WSTR ServerPrincName, ULONG AuthnSvc, RPC_AUTH_KEY_RETRIEVAL_FN GetKeyFn,
01391                             LPVOID Arg )
01392 {
01393     SECURITY_STATUS sec_status;
01394     CredHandle cred;
01395     TimeStamp exp;
01396     ULONG package_count;
01397     ULONG i;
01398     PSecPkgInfoW packages;
01399     ULONG max_token;
01400     struct rpc_server_registered_auth_info *auth_info;
01401 
01402     TRACE("(%s,%u,%p,%p)\n", debugstr_w(ServerPrincName), AuthnSvc, GetKeyFn, Arg);
01403 
01404     sec_status = EnumerateSecurityPackagesW(&package_count, &packages);
01405     if (sec_status != SEC_E_OK)
01406     {
01407         ERR("EnumerateSecurityPackagesW failed with error 0x%08x\n",
01408             sec_status);
01409         return RPC_S_SEC_PKG_ERROR;
01410     }
01411 
01412     for (i = 0; i < package_count; i++)
01413         if (packages[i].wRPCID == AuthnSvc)
01414             break;
01415 
01416     if (i == package_count)
01417     {
01418         WARN("unsupported AuthnSvc %u\n", AuthnSvc);
01419         FreeContextBuffer(packages);
01420         return RPC_S_UNKNOWN_AUTHN_SERVICE;
01421     }
01422     TRACE("found package %s for service %u\n", debugstr_w(packages[i].Name),
01423           AuthnSvc);
01424     sec_status = AcquireCredentialsHandleW((SEC_WCHAR *)ServerPrincName,
01425                                            packages[i].Name,
01426                                            SECPKG_CRED_INBOUND, NULL, NULL,
01427                                            NULL, NULL, &cred, &exp);
01428     max_token = packages[i].cbMaxToken;
01429     FreeContextBuffer(packages);
01430     if (sec_status != SEC_E_OK)
01431         return RPC_S_SEC_PKG_ERROR;
01432 
01433     auth_info = HeapAlloc(GetProcessHeap(), 0, sizeof(*auth_info));
01434     if (!auth_info)
01435     {
01436         FreeCredentialsHandle(&cred);
01437         return RPC_S_OUT_OF_RESOURCES;
01438     }
01439 
01440     auth_info->exp = exp;
01441     auth_info->cred = cred;
01442     auth_info->max_token = max_token;
01443     auth_info->auth_type = AuthnSvc;
01444 
01445     EnterCriticalSection(&server_auth_info_cs);
01446     list_add_tail(&server_registered_auth_info, &auth_info->entry);
01447     LeaveCriticalSection(&server_auth_info_cs);
01448 
01449     return RPC_S_OK;
01450 }
01451 
01452 /***********************************************************************
01453  *             RpcServerListen (RPCRT4.@)
01454  */
01455 RPC_STATUS WINAPI RpcServerListen( UINT MinimumCallThreads, UINT MaxCalls, UINT DontWait )
01456 {
01457   RPC_STATUS status = RPC_S_OK;
01458 
01459   TRACE("(%u,%u,%u)\n", MinimumCallThreads, MaxCalls, DontWait);
01460 
01461   if (list_empty(&protseqs))
01462     return RPC_S_NO_PROTSEQS_REGISTERED;
01463 
01464   status = RPCRT4_start_listen(FALSE);
01465 
01466   if (DontWait || (status != RPC_S_OK)) return status;
01467 
01468   return RpcMgmtWaitServerListen();
01469 }
01470 
01471 /***********************************************************************
01472  *             RpcMgmtServerWaitListen (RPCRT4.@)
01473  */
01474 RPC_STATUS WINAPI RpcMgmtWaitServerListen( void )
01475 {
01476   HANDLE event;
01477 
01478   TRACE("()\n");
01479 
01480   EnterCriticalSection(&listen_cs);
01481 
01482   if (!std_listen) {
01483     LeaveCriticalSection(&listen_cs);
01484     return RPC_S_NOT_LISTENING;
01485   }
01486   if (listen_done_event) {
01487     LeaveCriticalSection(&listen_cs);
01488     return RPC_S_ALREADY_LISTENING;
01489   }
01490   event = CreateEventW( NULL, TRUE, FALSE, NULL );
01491   listen_done_event = event;
01492 
01493   LeaveCriticalSection(&listen_cs);
01494 
01495   TRACE( "waiting for server calls to finish\n" );
01496   WaitForSingleObject( event, INFINITE );
01497   TRACE( "done waiting\n" );
01498 
01499   CloseHandle( event );
01500   return RPC_S_OK;
01501 }
01502 
01503 /***********************************************************************
01504  *             RpcMgmtStopServerListening (RPCRT4.@)
01505  */
01506 RPC_STATUS WINAPI RpcMgmtStopServerListening ( RPC_BINDING_HANDLE Binding )
01507 {
01508   TRACE("(Binding == (RPC_BINDING_HANDLE)^%p)\n", Binding);
01509 
01510   if (Binding) {
01511     FIXME("client-side invocation not implemented.\n");
01512     return RPC_S_WRONG_KIND_OF_BINDING;
01513   }
01514   
01515   RPCRT4_stop_listen(FALSE);
01516 
01517   return RPC_S_OK;
01518 }
01519 
01520 /***********************************************************************
01521  *             RpcMgmtEnableIdleCleanup (RPCRT4.@)
01522  */
01523 RPC_STATUS WINAPI RpcMgmtEnableIdleCleanup(void)
01524 {
01525     FIXME("(): stub\n");
01526     return RPC_S_OK;
01527 }
01528 
01529 /***********************************************************************
01530  *             I_RpcServerStartListening (RPCRT4.@)
01531  */
01532 RPC_STATUS WINAPI I_RpcServerStartListening( HWND hWnd )
01533 {
01534   FIXME( "(%p): stub\n", hWnd );
01535 
01536   return RPC_S_OK;
01537 }
01538 
01539 /***********************************************************************
01540  *             I_RpcServerStopListening (RPCRT4.@)
01541  */
01542 RPC_STATUS WINAPI I_RpcServerStopListening( void )
01543 {
01544   FIXME( "(): stub\n" );
01545 
01546   return RPC_S_OK;
01547 }
01548 
01549 /***********************************************************************
01550  *             I_RpcWindowProc (RPCRT4.@)
01551  */
01552 UINT WINAPI I_RpcWindowProc( void *hWnd, UINT Message, UINT wParam, ULONG lParam )
01553 {
01554   FIXME( "(%p,%08x,%08x,%08x): stub\n", hWnd, Message, wParam, lParam );
01555 
01556   return 0;
01557 }
01558 
01559 /***********************************************************************
01560  *             RpcMgmtInqIfIds (RPCRT4.@)
01561  */
01562 RPC_STATUS WINAPI RpcMgmtInqIfIds(RPC_BINDING_HANDLE Binding, RPC_IF_ID_VECTOR **IfIdVector)
01563 {
01564   FIXME("(%p,%p): stub\n", Binding, IfIdVector);
01565   return RPC_S_INVALID_BINDING;
01566 }
01567 
01568 /***********************************************************************
01569  *             RpcMgmtInqStats (RPCRT4.@)
01570  */
01571 RPC_STATUS WINAPI RpcMgmtInqStats(RPC_BINDING_HANDLE Binding, RPC_STATS_VECTOR **Statistics)
01572 {
01573   RPC_STATS_VECTOR *stats;
01574 
01575   FIXME("(%p,%p)\n", Binding, Statistics);
01576 
01577   if ((stats = HeapAlloc(GetProcessHeap(), 0, sizeof(RPC_STATS_VECTOR))))
01578   {
01579     stats->Count = 1;
01580     stats->Stats[0] = 0;
01581     *Statistics = stats;
01582     return RPC_S_OK;
01583   }
01584   return RPC_S_OUT_OF_RESOURCES;
01585 }
01586 
01587 /***********************************************************************
01588  *             RpcMgmtStatsVectorFree (RPCRT4.@)
01589  */
01590 RPC_STATUS WINAPI RpcMgmtStatsVectorFree(RPC_STATS_VECTOR **StatsVector)
01591 {
01592   FIXME("(%p)\n", StatsVector);
01593 
01594   if (StatsVector)
01595   {
01596     HeapFree(GetProcessHeap(), 0, *StatsVector);
01597     *StatsVector = NULL;
01598   }
01599   return RPC_S_OK;
01600 }
01601 
01602 /***********************************************************************
01603  *             RpcMgmtEpEltInqBegin (RPCRT4.@)
01604  */
01605 RPC_STATUS WINAPI RpcMgmtEpEltInqBegin(RPC_BINDING_HANDLE Binding, ULONG InquiryType,
01606     RPC_IF_ID *IfId, ULONG VersOption, UUID *ObjectUuid, RPC_EP_INQ_HANDLE* InquiryContext)
01607 {
01608   FIXME("(%p,%u,%p,%u,%p,%p): stub\n",
01609         Binding, InquiryType, IfId, VersOption, ObjectUuid, InquiryContext);
01610   return RPC_S_INVALID_BINDING;
01611 }
01612 
01613 /***********************************************************************
01614  *             RpcMgmtIsServerListening (RPCRT4.@)
01615  */
01616 RPC_STATUS WINAPI RpcMgmtIsServerListening(RPC_BINDING_HANDLE Binding)
01617 {
01618   FIXME("(%p): stub\n", Binding);
01619   return RPC_S_INVALID_BINDING;
01620 }
01621 
01622 /***********************************************************************
01623  *             RpcMgmtSetAuthorizationFn (RPCRT4.@)
01624  */
01625 RPC_STATUS WINAPI RpcMgmtSetAuthorizationFn(RPC_MGMT_AUTHORIZATION_FN fn)
01626 {
01627   FIXME("(%p): stub\n", fn);
01628   return RPC_S_OK;
01629 }
01630 
01631 /***********************************************************************
01632  *             RpcMgmtSetServerStackSize (RPCRT4.@)
01633  */
01634 RPC_STATUS WINAPI RpcMgmtSetServerStackSize(ULONG ThreadStackSize)
01635 {
01636   FIXME("(0x%x): stub\n", ThreadStackSize);
01637   return RPC_S_OK;
01638 }
01639 
01640 /***********************************************************************
01641  *             I_RpcGetCurrentCallHandle (RPCRT4.@)
01642  */
01643 RPC_BINDING_HANDLE WINAPI I_RpcGetCurrentCallHandle(void)
01644 {
01645     TRACE("\n");
01646     return RPCRT4_GetThreadCurrentCallHandle();
01647 }

Generated on Sun May 27 2012 04:26:05 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.