~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/rpcrt4/rpc_server.c

Version: ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  1 /*
  2  * RPC server API
  3  *
  4  * Copyright 2001 Ove Kåven, TransGaming Technologies
  5  * Copyright 2004 Filip Navara
  6  * Copyright 2006-2008 Robert Shearman (for CodeWeavers)
  7  *
  8  * This library is free software; you can redistribute it and/or
  9  * modify it under the terms of the GNU Lesser General Public
 10  * License as published by the Free Software Foundation; either
 11  * version 2.1 of the License, or (at your option) any later version.
 12  *
 13  * This library is distributed in the hope that it will be useful,
 14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 16  * Lesser General Public License for more details.
 17  *
 18  * You should have received a copy of the GNU Lesser General Public
 19  * License along with this library; if not, write to the Free Software
 20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 21  */
 22 
 23 #include "config.h"
 24 #include "wine/port.h"
 25 
 26 #include <stdarg.h>
 27 #include <stdio.h>
 28 #include <string.h>
 29 #include <assert.h>
 30 
 31 #include "windef.h"
 32 #include "winbase.h"
 33 #include "winerror.h"
 34 
 35 #include "rpc.h"
 36 #include "rpcndr.h"
 37 #include "excpt.h"
 38 
 39 #include "wine/debug.h"
 40 #include "wine/exception.h"
 41 
 42 #include "rpc_server.h"
 43 #include "rpc_assoc.h"
 44 #include "rpc_message.h"
 45 #include "rpc_defs.h"
 46 #include "ncastatus.h"
 47 
 48 WINE_DEFAULT_DEBUG_CHANNEL(rpc);
 49 
 50 typedef struct _RpcPacket
 51 {
 52   struct _RpcConnection* conn;
 53   RpcPktHdr* hdr;
 54   RPC_MESSAGE* msg;
 55 } RpcPacket;
 56 
 57 typedef struct _RpcObjTypeMap
 58 {
 59   /* FIXME: a hash table would be better. */
 60   struct _RpcObjTypeMap *next;
 61   UUID Object;
 62   UUID Type;
 63 } RpcObjTypeMap;
 64 
 65 static RpcObjTypeMap *RpcObjTypeMaps;
 66 
 67 /* list of type RpcServerProtseq */
 68 static struct list protseqs = LIST_INIT(protseqs);
 69 static struct list server_interfaces = LIST_INIT(server_interfaces);
 70 
 71 static CRITICAL_SECTION server_cs;
 72 static CRITICAL_SECTION_DEBUG server_cs_debug =
 73 {
 74     0, 0, &server_cs,
 75     { &server_cs_debug.ProcessLocksList, &server_cs_debug.ProcessLocksList },
 76       0, 0, { (DWORD_PTR)(__FILE__ ": server_cs") }
 77 };
 78 static CRITICAL_SECTION server_cs = { &server_cs_debug, -1, 0, 0, 0, 0 };
 79 
 80 static CRITICAL_SECTION listen_cs;
 81 static CRITICAL_SECTION_DEBUG listen_cs_debug =
 82 {
 83     0, 0, &listen_cs,
 84     { &listen_cs_debug.ProcessLocksList, &listen_cs_debug.ProcessLocksList },
 85       0, 0, { (DWORD_PTR)(__FILE__ ": listen_cs") }
 86 };
 87 static CRITICAL_SECTION listen_cs = { &listen_cs_debug, -1, 0, 0, 0, 0 };
 88 
 89 /* whether the server is currently listening */
 90 static BOOL std_listen;
 91 /* number of manual listeners (calls to RpcServerListen) */
 92 static LONG manual_listen_count;
 93 /* total listeners including auto listeners */
 94 static LONG listen_count;
 95 
 96 static UUID uuid_nil;
 97 
 98 static inline RpcObjTypeMap *LookupObjTypeMap(UUID *ObjUuid)
 99 {
100   RpcObjTypeMap *rslt = RpcObjTypeMaps;
101   RPC_STATUS dummy;
102 
103   while (rslt) {
104     if (! UuidCompare(ObjUuid, &rslt->Object, &dummy)) break;
105     rslt = rslt->next;
106   }
107 
108   return rslt;
109 }
110 
111 static inline UUID *LookupObjType(UUID *ObjUuid)
112 {
113   RpcObjTypeMap *map = LookupObjTypeMap(ObjUuid);
114   if (map)
115     return &map->Type;
116   else
117     return &uuid_nil;
118 }
119 
120 static RpcServerInterface* RPCRT4_find_interface(UUID* object,
121                                                  const RPC_SYNTAX_IDENTIFIER *if_id,
122                                                  const RPC_SYNTAX_IDENTIFIER *transfer_syntax,
123                                                  BOOL check_object)
124 {
125   UUID* MgrType = NULL;
126   RpcServerInterface* cif;
127   RPC_STATUS status;
128 
129   if (check_object)
130     MgrType = LookupObjType(object);
131   EnterCriticalSection(&server_cs);
132   LIST_FOR_EACH_ENTRY(cif, &server_interfaces, RpcServerInterface, entry) {
133     if (!memcmp(if_id, &cif->If->InterfaceId, sizeof(RPC_SYNTAX_IDENTIFIER)) &&
134         (!transfer_syntax || !memcmp(transfer_syntax, &cif->If->TransferSyntax, sizeof(RPC_SYNTAX_IDENTIFIER))) &&
135         (check_object == FALSE || UuidEqual(MgrType, &cif->MgrTypeUuid, &status)) &&
136         std_listen) {
137       InterlockedIncrement(&cif->CurrentCalls);
138       break;
139     }
140   }
141   LeaveCriticalSection(&server_cs);
142   if (&cif->entry == &server_interfaces) cif = NULL;
143   TRACE("returning %p for object %s, if_id { %d.%d %s }\n", cif,
144     debugstr_guid(object), if_id->SyntaxVersion.MajorVersion,
145     if_id->SyntaxVersion.MinorVersion, debugstr_guid(&if_id->SyntaxGUID));
146   return cif;
147 }
148 
149 static void RPCRT4_release_server_interface(RpcServerInterface *sif)
150 {
151   if (!InterlockedDecrement(&sif->CurrentCalls) &&
152       sif->Delete) {
153     /* sif must have been removed from server_interfaces before
154      * CallsCompletedEvent is set */
155     if (sif->CallsCompletedEvent)
156       SetEvent(sif->CallsCompletedEvent);
157     HeapFree(GetProcessHeap(), 0, sif);
158   }
159 }
160 
161 static RPC_STATUS process_bind_packet(RpcConnection *conn, RpcPktBindHdr *hdr, RPC_MESSAGE *msg)
162 {
163   RPC_STATUS status;
164   RpcPktHdr *response;
165   RpcContextElement *ctxt_elem;
166   unsigned int i;
167 
168   for (i = 0, ctxt_elem = msg->Buffer;
169        i < hdr->num_elements;
170        i++, ctxt_elem = (RpcContextElement *)&ctxt_elem->transfer_syntaxes[ctxt_elem->num_syntaxes])
171   {
172       if (((char *)ctxt_elem - (char *)msg->Buffer) > msg->BufferLength ||
173           ((char *)&ctxt_elem->transfer_syntaxes[ctxt_elem->num_syntaxes] - (char *)msg->Buffer) > msg->BufferLength)
174       {
175           ERR("inconsistent data in packet - packet length %d, num elements %d\n",
176               msg->BufferLength, hdr->num_elements);
177           /* Report failure to client. */
178           response = RPCRT4_BuildBindNackHeader(NDR_LOCAL_DATA_REPRESENTATION,
179                                                 RPC_VER_MAJOR, RPC_VER_MINOR,
180                                                 REJECT_REASON_NOT_SPECIFIED);
181           goto send;
182       }
183   }
184 
185   if (hdr->max_tsize < RPC_MIN_PACKET_SIZE ||
186       !UuidIsNil(&conn->ActiveInterface.SyntaxGUID, &status) ||
187       conn->server_binding)
188   {
189     TRACE("packet size less than min size, or active interface syntax guid non-null\n");
190 
191     /* Report failure to client. */
192     response = RPCRT4_BuildBindNackHeader(NDR_LOCAL_DATA_REPRESENTATION,
193                                           RPC_VER_MAJOR, RPC_VER_MINOR,
194                                           REJECT_REASON_NOT_SPECIFIED);
195   }
196   else
197   {
198     RpcResult *results = HeapAlloc(GetProcessHeap(), 0,
199                                    hdr->num_elements * sizeof(*results));
200     if (!results)
201     {
202         /* Report failure to client. */
203         response = RPCRT4_BuildBindNackHeader(NDR_LOCAL_DATA_REPRESENTATION,
204                                               RPC_VER_MAJOR, RPC_VER_MINOR,
205                                               REJECT_LOCAL_LIMIT_EXCEEDED);
206     }
207 
208     for (i = 0, ctxt_elem = (RpcContextElement *)msg->Buffer;
209          i < hdr->num_elements;
210          i++, ctxt_elem = (RpcContextElement *)&ctxt_elem->transfer_syntaxes[ctxt_elem->num_syntaxes])
211     {
212         RpcServerInterface* sif = NULL;
213         unsigned int j;
214 
215         for (j = 0; !sif && j < ctxt_elem->num_syntaxes; j++)
216         {
217             sif = RPCRT4_find_interface(NULL, &ctxt_elem->abstract_syntax,
218                                         &ctxt_elem->transfer_syntaxes[j], FALSE);
219             if (sif)
220                 break;
221         }
222 
223         if (sif)
224         {
225             RPCRT4_release_server_interface(sif);
226             TRACE("accepting bind request on connection %p for %s\n", conn,
227                   debugstr_guid(&ctxt_elem->abstract_syntax.SyntaxGUID));
228             results[i].result = RESULT_ACCEPT;
229             results[i].reason = REASON_NONE;
230             results[i].transfer_syntax = ctxt_elem->transfer_syntaxes[j];
231 
232             /* save the interface for later use */
233             /* FIXME: save linked list */
234             conn->ActiveInterface = ctxt_elem->abstract_syntax;
235         }
236         else if ((sif = RPCRT4_find_interface(NULL, &ctxt_elem->abstract_syntax,
237                                               NULL, FALSE)) != NULL)
238         {
239             RPCRT4_release_server_interface(sif);
240             TRACE("not accepting bind request on connection %p for %s - no transfer syntaxes supported\n",
241                   conn, debugstr_guid(&ctxt_elem->abstract_syntax.SyntaxGUID));
242             results[i].result = RESULT_PROVIDER_REJECTION;
243             results[i].reason = REASON_TRANSFER_SYNTAXES_NOT_SUPPORTED;
244             memset(&results[i].transfer_syntax, 0, sizeof(results[i].transfer_syntax));
245         }
246         else
247         {
248             TRACE("not accepting bind request on connection %p for %s - abstract syntax not supported\n",
249                   conn, debugstr_guid(&ctxt_elem->abstract_syntax.SyntaxGUID));
250             results[i].result = RESULT_PROVIDER_REJECTION;
251             results[i].reason = REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
252             memset(&results[i].transfer_syntax, 0, sizeof(results[i].transfer_syntax));
253         }
254     }
255 
256     /* create temporary binding */
257     if (RPCRT4_MakeBinding(&conn->server_binding, conn) == RPC_S_OK &&
258         RpcServerAssoc_GetAssociation(rpcrt4_conn_get_name(conn),
259                                       conn->NetworkAddr, conn->Endpoint,
260                                       conn->NetworkOptions,
261                                       hdr->assoc_gid,
262                                       &conn->server_binding->Assoc) == RPC_S_OK)
263     {
264         response = RPCRT4_BuildBindAckHeader(NDR_LOCAL_DATA_REPRESENTATION,
265                                              RPC_MAX_PACKET_SIZE,
266                                              RPC_MAX_PACKET_SIZE,
267                                              conn->server_binding->Assoc->assoc_group_id,
268                                              conn->Endpoint, hdr->num_elements,
269                                              results);
270 
271         conn->MaxTransmissionSize = hdr->max_tsize;
272     }
273     else
274     {
275         /* Report failure to client. */
276         response = RPCRT4_BuildBindNackHeader(NDR_LOCAL_DATA_REPRESENTATION,
277                                               RPC_VER_MAJOR, RPC_VER_MINOR,
278                                               REJECT_LOCAL_LIMIT_EXCEEDED);
279     }
280     HeapFree(GetProcessHeap(), 0, results);
281   }
282 
283 send:
284   if (response)
285     status = RPCRT4_Send(conn, response, NULL, 0);
286   else
287     status = ERROR_OUTOFMEMORY;
288   RPCRT4_FreeHeader(response);
289 
290   return status;
291 }
292 
293 static RPC_STATUS process_request_packet(RpcConnection *conn, RpcPktRequestHdr *hdr, RPC_MESSAGE *msg)
294 {
295   RPC_STATUS status;
296   RpcPktHdr *response = NULL;
297   RpcServerInterface* sif;
298   RPC_DISPATCH_FUNCTION func;
299   BOOL exception;
300   UUID *object_uuid;
301   NDR_SCONTEXT context_handle;
302   void *buf = msg->Buffer;
303 
304   /* fail if the connection isn't bound with an interface */
305   if (UuidIsNil(&conn->ActiveInterface.SyntaxGUID, &status)) {
306     /* FIXME: should send BindNack instead */
307     response = RPCRT4_BuildFaultHeader(NDR_LOCAL_DATA_REPRESENTATION,
308                                        status);
309 
310     RPCRT4_Send(conn, response, NULL, 0);
311     RPCRT4_FreeHeader(response);
312     return RPC_S_OK;
313   }
314 
315   if (hdr->common.flags & RPC_FLG_OBJECT_UUID) {
316     object_uuid = (UUID*)(hdr + 1);
317   } else {
318     object_uuid = NULL;
319   }
320 
321   sif = RPCRT4_find_interface(object_uuid, &conn->ActiveInterface, NULL, TRUE);
322   if (!sif) {
323     WARN("interface %s no longer registered, returning fault packet\n", debugstr_guid(&conn->ActiveInterface.SyntaxGUID));
324     response = RPCRT4_BuildFaultHeader(NDR_LOCAL_DATA_REPRESENTATION,
325                                        NCA_S_UNK_IF);
326 
327     RPCRT4_Send(conn, response, NULL, 0);
328     RPCRT4_FreeHeader(response);
329     return RPC_S_OK;
330   }
331   msg->RpcInterfaceInformation = sif->If;
332   /* copy the endpoint vector from sif to msg so that midl-generated code will use it */
333   msg->ManagerEpv = sif->MgrEpv;
334   if (object_uuid != NULL) {
335     RPCRT4_SetBindingObject(msg->Handle, object_uuid);
336   }
337 
338   /* find dispatch function */
339   msg->ProcNum = hdr->opnum;
340   if (sif->Flags & RPC_IF_OLE) {
341     /* native ole32 always gives us a dispatch table with a single entry
342     * (I assume that's a wrapper for IRpcStubBuffer::Invoke) */
343     func = *sif->If->DispatchTable->DispatchTable;
344   } else {
345     if (msg->ProcNum >= sif->If->DispatchTable->DispatchTableCount) {
346       WARN("invalid procnum (%d/%d)\n", msg->ProcNum, sif->If->DispatchTable->DispatchTableCount);
347       response = RPCRT4_BuildFaultHeader(NDR_LOCAL_DATA_REPRESENTATION,
348                                          NCA_S_OP_RNG_ERROR);
349 
350       RPCRT4_Send(conn, response, NULL, 0);
351       RPCRT4_FreeHeader(response);
352     }
353     func = sif->If->DispatchTable->DispatchTable[msg->ProcNum];
354   }
355 
356   /* put in the drep. FIXME: is this more universally applicable?
357     perhaps we should move this outward... */
358   msg->DataRepresentation =
359     MAKELONG( MAKEWORD(hdr->common.drep[0], hdr->common.drep[1]),
360               MAKEWORD(hdr->common.drep[2], hdr->common.drep[3]));
361 
362   exception = FALSE;
363 
364   /* dispatch */
365   RPCRT4_SetThreadCurrentCallHandle(msg->Handle);
366   __TRY {
367     if (func) func(msg);
368   } __EXCEPT_ALL {
369     WARN("exception caught with code 0x%08x = %d\n", GetExceptionCode(), GetExceptionCode());
370     exception = TRUE;
371     if (GetExceptionCode() == STATUS_ACCESS_VIOLATION)
372       status = ERROR_NOACCESS;
373     else
374       status = GetExceptionCode();
375     response = RPCRT4_BuildFaultHeader(msg->DataRepresentation,
376                                        RPC2NCA_STATUS(status));
377   } __ENDTRY
378     RPCRT4_SetThreadCurrentCallHandle(NULL);
379 
380   /* release any unmarshalled context handles */
381   while ((context_handle = RPCRT4_PopThreadContextHandle()) != NULL)
382     RpcServerAssoc_ReleaseContextHandle(conn->server_binding->Assoc, context_handle, TRUE);
383 
384   if (!exception)
385     response = RPCRT4_BuildResponseHeader(msg->DataRepresentation,
386                                           msg->BufferLength);
387 
388   /* send response packet */
389   if (response) {
390     status = RPCRT4_Send(conn, response, exception ? NULL : msg->Buffer,
391                          exception ? 0 : msg->BufferLength);
392     RPCRT4_FreeHeader(response);
393   } else
394     ERR("out of memory\n");
395 
396   msg->RpcInterfaceInformation = NULL;
397   RPCRT4_release_server_interface(sif);
398 
399   if (msg->Buffer == buf) buf = NULL;
400   TRACE("freeing Buffer=%p\n", buf);
401   I_RpcFree(buf);
402 
403   return status;
404 }
405 
406 static void RPCRT4_process_packet(RpcConnection* conn, RpcPktHdr* hdr, RPC_MESSAGE* msg)
407 {
408   RPC_STATUS status;
409 
410   msg->Handle = (RPC_BINDING_HANDLE)conn->server_binding;
411 
412   switch (hdr->common.ptype) {
413     case PKT_BIND:
414       TRACE("got bind packet\n");
415 
416       status = process_bind_packet(conn, &hdr->bind, msg);
417       break;
418 
419     case PKT_REQUEST:
420       TRACE("got request packet\n");
421 
422       status = process_request_packet(conn, &hdr->request, msg);
423       break;
424 
425     default:
426       FIXME("unhandled packet type %u\n", hdr->common.ptype);
427       break;
428   }
429 
430   /* clean up */
431   I_RpcFree(msg->Buffer);
432   RPCRT4_FreeHeader(hdr);
433   HeapFree(GetProcessHeap(), 0, msg);
434 }
435 
436 static DWORD CALLBACK RPCRT4_worker_thread(LPVOID the_arg)
437 {
438   RpcPacket *pkt = the_arg;
439   RPCRT4_process_packet(pkt->conn, pkt->hdr, pkt->msg);
440   HeapFree(GetProcessHeap(), 0, pkt);
441   return 0;
442 }
443 
444 static DWORD CALLBACK RPCRT4_io_thread(LPVOID the_arg)
445 {
446   RpcConnection* conn = the_arg;
447   RpcPktHdr *hdr;
448   RPC_MESSAGE *msg;
449   RPC_STATUS status;
450   RpcPacket *packet;
451 
452   TRACE("(%p)\n", conn);
453 
454   for (;;) {
455     msg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RPC_MESSAGE));
456 
457     status = RPCRT4_Receive(conn, &hdr, msg);
458     if (status != RPC_S_OK) {
459       WARN("receive failed with error %x\n", status);
460       HeapFree(GetProcessHeap(), 0, msg);
461       break;
462     }
463 
464     packet = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcPacket));
465     if (!packet) {
466       I_RpcFree(msg->Buffer);
467       RPCRT4_FreeHeader(hdr);
468       HeapFree(GetProcessHeap(), 0, msg);
469       break;
470     }
471     packet->conn = conn;
472     packet->hdr = hdr;
473     packet->msg = msg;
474     if (!QueueUserWorkItem(RPCRT4_worker_thread, packet, WT_EXECUTELONGFUNCTION)) {
475       ERR("couldn't queue work item for worker thread, error was %d\n", GetLastError());
476       I_RpcFree(msg->Buffer);
477       RPCRT4_FreeHeader(hdr);
478       HeapFree(GetProcessHeap(), 0, msg);
479       HeapFree(GetProcessHeap(), 0, packet);
480       break;
481     }
482 
483     msg = NULL;
484   }
485   RPCRT4_DestroyConnection(conn);
486   return 0;
487 }
488 
489 void RPCRT4_new_client(RpcConnection* conn)
490 {
491   HANDLE thread = CreateThread(NULL, 0, RPCRT4_io_thread, conn, 0, NULL);
492   if (!thread) {
493     DWORD err = GetLastError();
494     ERR("failed to create thread, error=%08x\n", err);
495     RPCRT4_DestroyConnection(conn);
496   }
497   /* we could set conn->thread, but then we'd have to make the io_thread wait
498    * for that, otherwise the thread might finish, destroy the connection, and
499    * free the memory we'd write to before we did, causing crashes and stuff -
500    * so let's implement that later, when we really need conn->thread */
501 
502   CloseHandle( thread );
503 }
504 
505 static DWORD CALLBACK RPCRT4_server_thread(LPVOID the_arg)
506 {
507   int res;
508   unsigned int count;
509   void *objs = NULL;
510   RpcServerProtseq* cps = the_arg;
511   RpcConnection* conn;
512   BOOL set_ready_event = FALSE;
513 
514   TRACE("(the_arg == ^%p)\n", the_arg);
515 
516   for (;;) {
517     objs = cps->ops->get_wait_array(cps, objs, &count);
518 
519     if (set_ready_event)
520     {
521         /* signal to function that changed state that we are now sync'ed */
522         SetEvent(cps->server_ready_event);
523         set_ready_event = FALSE;
524     }
525 
526     /* start waiting */
527     res = cps->ops->wait_for_new_connection(cps, count, objs);
528 
529     if (res == -1 || (res == 0 && !std_listen))
530     {
531       /* cleanup */
532       cps->ops->free_wait_array(cps, objs);
533       EnterCriticalSection(&cps->cs);
534       for (conn = cps->conn; conn; conn = conn->Next)
535         RPCRT4_CloseConnection(conn);
536       LeaveCriticalSection(&cps->cs);
537 
538       if (res == 0 && !std_listen)
539         SetEvent(cps->server_ready_event);
540       break;
541     }
542     else if (res == 0)
543       set_ready_event = TRUE;
544   }
545   return 0;
546 }
547 
548 /* tells the server thread that the state has changed and waits for it to
549  * make the changes */
550 static void RPCRT4_sync_with_server_thread(RpcServerProtseq *ps)
551 {
552   /* make sure we are the only thread sync'ing the server state, otherwise
553    * there is a race with the server thread setting an older state and setting
554    * the server_ready_event when the new state hasn't yet been applied */
555   WaitForSingleObject(ps->mgr_mutex, INFINITE);
556 
557   ps->ops->signal_state_changed(ps);
558 
559   /* wait for server thread to make the requested changes before returning */
560   WaitForSingleObject(ps->server_ready_event, INFINITE);
561 
562   ReleaseMutex(ps->mgr_mutex);
563 }
564 
565 static RPC_STATUS RPCRT4_start_listen_protseq(RpcServerProtseq *ps, BOOL auto_listen)
566 {
567   RPC_STATUS status = RPC_S_OK;
568   HANDLE server_thread;
569 
570   EnterCriticalSection(&listen_cs);
571   if (ps->is_listening) goto done;
572 
573   if (!ps->mgr_mutex) ps->mgr_mutex = CreateMutexW(NULL, FALSE, NULL);
574   if (!ps->server_ready_event) ps->server_ready_event = CreateEventW(NULL, FALSE, FALSE, NULL);
575   server_thread = CreateThread(NULL, 0, RPCRT4_server_thread, ps, 0, NULL);
576   if (!server_thread)
577   {
578     status = RPC_S_OUT_OF_RESOURCES;
579     goto done;
580   }
581   ps->is_listening = TRUE;
582   CloseHandle(server_thread);
583 
584 done:
585   LeaveCriticalSection(&listen_cs);
586   return status;
587 }
588 
589 static RPC_STATUS RPCRT4_start_listen(BOOL auto_listen)
590 {
591   RPC_STATUS status = RPC_S_ALREADY_LISTENING;
592   RpcServerProtseq *cps;
593 
594   TRACE("\n");
595 
596   EnterCriticalSection(&listen_cs);
597   if (auto_listen || (manual_listen_count++ == 0))
598   {
599     status = RPC_S_OK;
600     if (++listen_count == 1)
601       std_listen = TRUE;
602   }
603   LeaveCriticalSection(&listen_cs);
604 
605   if (std_listen)
606   {
607     EnterCriticalSection(&server_cs);
608     LIST_FOR_EACH_ENTRY(cps, &protseqs, RpcServerProtseq, entry)
609     {
610       status = RPCRT4_start_listen_protseq(cps, TRUE);
611       if (status != RPC_S_OK)
612         break;
613       
614       /* make sure server is actually listening on the interface before
615        * returning */
616       RPCRT4_sync_with_server_thread(cps);
617     }
618     LeaveCriticalSection(&server_cs);
619   }
620 
621   return status;
622 }
623 
624 static void RPCRT4_stop_listen(BOOL auto_listen)
625 {
626   EnterCriticalSection(&listen_cs);
627   if (auto_listen || (--manual_listen_count == 0))
628   {
629     if (listen_count != 0 && --listen_count == 0) {
630       RpcServerProtseq *cps;
631 
632       std_listen = FALSE;
633       LeaveCriticalSection(&listen_cs);
634 
635       LIST_FOR_EACH_ENTRY(cps, &protseqs, RpcServerProtseq, entry)
636         RPCRT4_sync_with_server_thread(cps);
637 
638       return;
639     }
640     assert(listen_count >= 0);
641   }
642   LeaveCriticalSection(&listen_cs);
643 }
644 
645 static BOOL RPCRT4_protseq_is_endpoint_registered(RpcServerProtseq *protseq, const char *endpoint)
646 {
647   RpcConnection *conn;
648   EnterCriticalSection(&protseq->cs);
649   for (conn = protseq->conn; conn; conn = conn->Next)
650   {
651     if (!endpoint || !strcmp(endpoint, conn->Endpoint))
652       break;
653   }
654   LeaveCriticalSection(&protseq->cs);
655   return (conn != NULL);
656 }
657 
658 static RPC_STATUS RPCRT4_use_protseq(RpcServerProtseq* ps, const char *endpoint)
659 {
660   RPC_STATUS status;
661 
662   EnterCriticalSection(&ps->cs);
663 
664   if (RPCRT4_protseq_is_endpoint_registered(ps, endpoint))
665     status = RPC_S_OK;
666   else
667     status = ps->ops->open_endpoint(ps, endpoint);
668 
669   LeaveCriticalSection(&ps->cs);
670 
671   if (status != RPC_S_OK)
672     return status;
673 
674   if (std_listen)
675   {
676     status = RPCRT4_start_listen_protseq(ps, FALSE);
677     if (status == RPC_S_OK)
678       RPCRT4_sync_with_server_thread(ps);
679   }
680 
681   return status;
682 }
683 
684 /***********************************************************************
685  *             RpcServerInqBindings (RPCRT4.@)
686  */
687 RPC_STATUS WINAPI RpcServerInqBindings( RPC_BINDING_VECTOR** BindingVector )
688 {
689   RPC_STATUS status;
690   DWORD count;
691   RpcServerProtseq* ps;
692   RpcConnection* conn;
693 
694   if (BindingVector)
695     TRACE("(*BindingVector == ^%p)\n", *BindingVector);
696   else
697     ERR("(BindingVector == NULL!!?)\n");
698 
699   EnterCriticalSection(&server_cs);
700   /* count connections */
701   count = 0;
702   LIST_FOR_EACH_ENTRY(ps, &protseqs, RpcServerProtseq, entry) {
703     EnterCriticalSection(&ps->cs);
704     for (conn = ps->conn; conn; conn = conn->Next)
705       count++;
706     LeaveCriticalSection(&ps->cs);
707   }
708   if (count) {
709     /* export bindings */
710     *BindingVector = HeapAlloc(GetProcessHeap(), 0,
711                               sizeof(RPC_BINDING_VECTOR) +
712                               sizeof(RPC_BINDING_HANDLE)*(count-1));
713     (*BindingVector)->Count = count;
714     count = 0;
715     LIST_FOR_EACH_ENTRY(ps, &protseqs, RpcServerProtseq, entry) {
716       EnterCriticalSection(&ps->cs);
717       for (conn = ps->conn; conn; conn = conn->Next) {
718        RPCRT4_MakeBinding((RpcBinding**)&(*BindingVector)->BindingH[count],
719                           conn);
720        count++;
721       }
722       LeaveCriticalSection(&ps->cs);
723     }
724     status = RPC_S_OK;
725   } else {
726     *BindingVector = NULL;
727     status = RPC_S_NO_BINDINGS;
728   }
729   LeaveCriticalSection(&server_cs);
730   return status;
731 }
732 
733 /***********************************************************************
734  *             RpcServerUseProtseqEpA (RPCRT4.@)
735  */
736 RPC_STATUS WINAPI RpcServerUseProtseqEpA( RPC_CSTR Protseq, UINT MaxCalls, RPC_CSTR Endpoint, LPVOID SecurityDescriptor )
737 {
738   RPC_POLICY policy;
739   
740   TRACE( "(%s,%u,%s,%p)\n", Protseq, MaxCalls, Endpoint, SecurityDescriptor );
741   
742   /* This should provide the default behaviour */
743   policy.Length        = sizeof( policy );
744   policy.EndpointFlags = 0;
745   policy.NICFlags      = 0;
746   
747   return RpcServerUseProtseqEpExA( Protseq, MaxCalls, Endpoint, SecurityDescriptor, &policy );
748 }
749 
750 /***********************************************************************
751  *             RpcServerUseProtseqEpW (RPCRT4.@)
752  */
753 RPC_STATUS WINAPI RpcServerUseProtseqEpW( RPC_WSTR Protseq, UINT MaxCalls, RPC_WSTR Endpoint, LPVOID SecurityDescriptor )
754 {
755   RPC_POLICY policy;
756   
757   TRACE( "(%s,%u,%s,%p)\n", debugstr_w( Protseq ), MaxCalls, debugstr_w( Endpoint ), SecurityDescriptor );
758   
759   /* This should provide the default behaviour */
760   policy.Length        = sizeof( policy );
761   policy.EndpointFlags = 0;
762   policy.NICFlags      = 0;
763   
764   return RpcServerUseProtseqEpExW( Protseq, MaxCalls, Endpoint, SecurityDescriptor, &policy );
765 }
766 
767 /***********************************************************************
768  *             alloc_serverprotoseq (internal)
769  *
770  * Must be called with server_cs held.
771  */
772 static RPC_STATUS alloc_serverprotoseq(UINT MaxCalls, const char *Protseq, RpcServerProtseq **ps)
773 {
774   const struct protseq_ops *ops = rpcrt4_get_protseq_ops(Protseq);
775 
776   if (!ops)
777   {
778     FIXME("protseq %s not supported\n", debugstr_a(Protseq));
779     return RPC_S_PROTSEQ_NOT_SUPPORTED;
780   }
781 
782   *ps = ops->alloc();
783   if (!*ps)
784     return RPC_S_OUT_OF_RESOURCES;
785   (*ps)->MaxCalls = MaxCalls;
786   (*ps)->Protseq = RPCRT4_strdupA(Protseq);
787   (*ps)->ops = ops;
788   (*ps)->MaxCalls = 0;
789   (*ps)->conn = NULL;
790   InitializeCriticalSection(&(*ps)->cs);
791   (*ps)->is_listening = FALSE;
792   (*ps)->mgr_mutex = NULL;
793   (*ps)->server_ready_event = NULL;
794 
795   list_add_head(&protseqs, &(*ps)->entry);
796 
797   TRACE("new protseq %p created for %s\n", *ps, Protseq);
798 
799   return RPC_S_OK;
800 }
801 
802 /* must be called with server_cs held */
803 static void destroy_serverprotoseq(RpcServerProtseq *ps)
804 {
805     RPCRT4_strfree(ps->Protseq);
806     DeleteCriticalSection(&ps->cs);
807     CloseHandle(ps->mgr_mutex);
808     CloseHandle(ps->server_ready_event);
809     list_remove(&ps->entry);
810     HeapFree(GetProcessHeap(), 0, ps);
811 }
812 
813 /* Finds a given protseq or creates a new one if one doesn't already exist */
814 static RPC_STATUS RPCRT4_get_or_create_serverprotseq(UINT MaxCalls, const char *Protseq, RpcServerProtseq **ps)
815 {
816     RPC_STATUS status;
817     RpcServerProtseq *cps;
818 
819     EnterCriticalSection(&server_cs);
820 
821     LIST_FOR_EACH_ENTRY(cps, &protseqs, RpcServerProtseq, entry)
822         if (!strcmp(cps->Protseq, Protseq))
823         {
824             TRACE("found existing protseq object for %s\n", Protseq);
825             *ps = cps;
826             LeaveCriticalSection(&server_cs);
827             return S_OK;
828         }
829 
830     status = alloc_serverprotoseq(MaxCalls, Protseq, ps);
831 
832     LeaveCriticalSection(&server_cs);
833 
834     return status;
835 }
836 
837 /***********************************************************************
838  *             RpcServerUseProtseqEpExA (RPCRT4.@)
839  */
840 RPC_STATUS WINAPI RpcServerUseProtseqEpExA( RPC_CSTR Protseq, UINT MaxCalls, RPC_CSTR Endpoint, LPVOID SecurityDescriptor,
841                                             PRPC_POLICY lpPolicy )
842 {
843   RpcServerProtseq* ps;
844   RPC_STATUS status;
845 
846   TRACE("(%s,%u,%s,%p,{%u,%u,%u})\n", debugstr_a((const char *)Protseq),
847        MaxCalls, debugstr_a((const char *)Endpoint), SecurityDescriptor,
848        lpPolicy->Length, lpPolicy->EndpointFlags, lpPolicy->NICFlags );
849 
850   status = RPCRT4_get_or_create_serverprotseq(MaxCalls, (const char *)Protseq, &ps);
851   if (status != RPC_S_OK)
852     return status;
853 
854   return RPCRT4_use_protseq(ps, (const char *)Endpoint);
855 }
856 
857 /***********************************************************************
858  *             RpcServerUseProtseqEpExW (RPCRT4.@)
859  */
860 RPC_STATUS WINAPI RpcServerUseProtseqEpExW( RPC_WSTR Protseq, UINT MaxCalls, RPC_WSTR Endpoint, LPVOID SecurityDescriptor,
861                                             PRPC_POLICY lpPolicy )
862 {
863   RpcServerProtseq* ps;
864   RPC_STATUS status;
865   LPSTR ProtseqA;
866   LPSTR EndpointA;
867 
868   TRACE("(%s,%u,%s,%p,{%u,%u,%u})\n", debugstr_w( Protseq ), MaxCalls,
869        debugstr_w( Endpoint ), SecurityDescriptor,
870        lpPolicy->Length, lpPolicy->EndpointFlags, lpPolicy->NICFlags );
871 
872   ProtseqA = RPCRT4_strdupWtoA(Protseq);
873   status = RPCRT4_get_or_create_serverprotseq(MaxCalls, ProtseqA, &ps);
874   RPCRT4_strfree(ProtseqA);
875   if (status != RPC_S_OK)
876     return status;
877 
878   EndpointA = RPCRT4_strdupWtoA(Endpoint);
879   status = RPCRT4_use_protseq(ps, EndpointA);
880   RPCRT4_strfree(EndpointA);
881   return status;
882 }
883 
884 /***********************************************************************
885  *             RpcServerUseProtseqA (RPCRT4.@)
886  */
887 RPC_STATUS WINAPI RpcServerUseProtseqA(RPC_CSTR Protseq, unsigned int MaxCalls, void *SecurityDescriptor)
888 {
889   RPC_STATUS status;
890   RpcServerProtseq* ps;
891 
892   TRACE("(Protseq == %s, MaxCalls == %d, SecurityDescriptor == ^%p)\n", debugstr_a((char*)Protseq), MaxCalls, SecurityDescriptor);
893 
894   status = RPCRT4_get_or_create_serverprotseq(MaxCalls, (const char *)Protseq, &ps);
895   if (status != RPC_S_OK)
896     return status;
897 
898   return RPCRT4_use_protseq(ps, NULL);
899 }
900 
901 /***********************************************************************
902  *             RpcServerUseProtseqW (RPCRT4.@)
903  */
904 RPC_STATUS WINAPI RpcServerUseProtseqW(RPC_WSTR Protseq, unsigned int MaxCalls, void *SecurityDescriptor)
905 {
906   RPC_STATUS status;
907   RpcServerProtseq* ps;
908   LPSTR ProtseqA;
909 
910   TRACE("Protseq == %s, MaxCalls == %d, SecurityDescriptor == ^%p)\n", debugstr_w(Protseq), MaxCalls, SecurityDescriptor);
911 
912   ProtseqA = RPCRT4_strdupWtoA(Protseq);
913   status = RPCRT4_get_or_create_serverprotseq(MaxCalls, ProtseqA, &ps);
914   RPCRT4_strfree(ProtseqA);
915   if (status != RPC_S_OK)
916     return status;
917 
918   return RPCRT4_use_protseq(ps, NULL);
919 }
920 
921 void RPCRT4_destroy_all_protseqs(void)
922 {
923     RpcServerProtseq *cps, *cursor2;
924 
925     if (listen_count != 0)
926         std_listen = FALSE;
927 
928     EnterCriticalSection(&server_cs);
929     LIST_FOR_EACH_ENTRY_SAFE(cps, cursor2, &protseqs, RpcServerProtseq, entry)
930     {
931         if (listen_count != 0)
932             RPCRT4_sync_with_server_thread(cps);
933         destroy_serverprotoseq(cps);
934     }
935     LeaveCriticalSection(&server_cs);
936 }
937 
938 /***********************************************************************
939  *             RpcServerRegisterIf (RPCRT4.@)
940  */
941 RPC_STATUS WINAPI RpcServerRegisterIf( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, RPC_MGR_EPV* MgrEpv )
942 {
943   TRACE("(%p,%s,%p)\n", IfSpec, debugstr_guid(MgrTypeUuid), MgrEpv);
944   return RpcServerRegisterIf2( IfSpec, MgrTypeUuid, MgrEpv, 0, RPC_C_LISTEN_MAX_CALLS_DEFAULT, (UINT)-1, NULL );
945 }
946 
947 /***********************************************************************
948  *             RpcServerRegisterIfEx (RPCRT4.@)
949  */
950 RPC_STATUS WINAPI RpcServerRegisterIfEx( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, RPC_MGR_EPV* MgrEpv,
951                        UINT Flags, UINT MaxCalls, RPC_IF_CALLBACK_FN* IfCallbackFn )
952 {
953   TRACE("(%p,%s,%p,%u,%u,%p)\n", IfSpec, debugstr_guid(MgrTypeUuid), MgrEpv, Flags, MaxCalls, IfCallbackFn);
954   return RpcServerRegisterIf2( IfSpec, MgrTypeUuid, MgrEpv, Flags, MaxCalls, (UINT)-1, IfCallbackFn );
955 }
956 
957 /***********************************************************************
958  *             RpcServerRegisterIf2 (RPCRT4.@)
959  */
960 RPC_STATUS WINAPI RpcServerRegisterIf2( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, RPC_MGR_EPV* MgrEpv,
961                       UINT Flags, UINT MaxCalls, UINT MaxRpcSize, RPC_IF_CALLBACK_FN* IfCallbackFn )
962 {
963   PRPC_SERVER_INTERFACE If = IfSpec;
964   RpcServerInterface* sif;
965   unsigned int i;
966 
967   TRACE("(%p,%s,%p,%u,%u,%u,%p)\n", IfSpec, debugstr_guid(MgrTypeUuid), MgrEpv, Flags, MaxCalls,
968          MaxRpcSize, IfCallbackFn);
969   TRACE(" interface id: %s %d.%d\n", debugstr_guid(&If->InterfaceId.SyntaxGUID),
970                                      If->InterfaceId.SyntaxVersion.MajorVersion,
971                                      If->InterfaceId.SyntaxVersion.MinorVersion);
972   TRACE(" transfer syntax: %s %d.%d\n", debugstr_guid(&If->TransferSyntax.SyntaxGUID),
973                                         If->TransferSyntax.SyntaxVersion.MajorVersion,
974                                         If->TransferSyntax.SyntaxVersion.MinorVersion);
975   TRACE(" dispatch table: %p\n", If->DispatchTable);
976   if (If->DispatchTable) {
977     TRACE("  dispatch table count: %d\n", If->DispatchTable->DispatchTableCount);
978     for (i=0; i<If->DispatchTable->DispatchTableCount; i++) {
979       TRACE("   entry %d: %p\n", i, If->DispatchTable->DispatchTable[i]);
980     }
981     TRACE("  reserved: %ld\n", If->DispatchTable->Reserved);
982   }
983   TRACE(" protseq endpoint count: %d\n", If->RpcProtseqEndpointCount);
984   TRACE(" default manager epv: %p\n", If->DefaultManagerEpv);
985   TRACE(" interpreter info: %p\n", If->InterpreterInfo);
986 
987   sif = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcServerInterface));
988   sif->If           = If;
989   if (MgrTypeUuid) {
990     sif->MgrTypeUuid = *MgrTypeUuid;
991     sif->MgrEpv       = MgrEpv;
992   } else {
993     memset(&sif->MgrTypeUuid, 0, sizeof(UUID));
994     sif->MgrEpv       = If->DefaultManagerEpv;
995   }
996   sif->Flags        = Flags;
997   sif->MaxCalls     = MaxCalls;
998   sif->MaxRpcSize   = MaxRpcSize;
999   sif->IfCallbackFn = IfCallbackFn;
1000 
1001   EnterCriticalSection(&server_cs);
1002   list_add_head(&server_interfaces, &sif->entry);
1003   LeaveCriticalSection(&server_cs);
1004 
1005   if (sif->Flags & RPC_IF_AUTOLISTEN)
1006       RPCRT4_start_listen(TRUE);
1007 
1008   return RPC_S_OK;
1009 }
1010 
1011 /***********************************************************************
1012  *             RpcServerUnregisterIf (RPCRT4.@)
1013  */
1014 RPC_STATUS WINAPI RpcServerUnregisterIf( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, UINT WaitForCallsToComplete )
1015 {
1016   PRPC_SERVER_INTERFACE If = IfSpec;
1017   HANDLE event = NULL;
1018   BOOL found = FALSE;
1019   BOOL completed = TRUE;
1020   RpcServerInterface *cif;
1021   RPC_STATUS status;
1022 
1023   TRACE("(IfSpec == (RPC_IF_HANDLE)^%p (%s), MgrTypeUuid == %s, WaitForCallsToComplete == %u)\n",
1024     IfSpec, debugstr_guid(&If->InterfaceId.SyntaxGUID), debugstr_guid(MgrTypeUuid), WaitForCallsToComplete);
1025 
1026   EnterCriticalSection(&server_cs);
1027   LIST_FOR_EACH_ENTRY(cif, &server_interfaces, RpcServerInterface, entry) {
1028     if ((!IfSpec || !memcmp(&If->InterfaceId, &cif->If->InterfaceId, sizeof(RPC_SYNTAX_IDENTIFIER))) &&
1029         UuidEqual(MgrTypeUuid, &cif->MgrTypeUuid, &status)) {
1030       list_remove(&cif->entry);
1031       TRACE("unregistering cif %p\n", cif);
1032       if (cif->CurrentCalls) {
1033         completed = FALSE;
1034         cif->Delete = TRUE;
1035         if (WaitForCallsToComplete)
1036           cif->CallsCompletedEvent = event = CreateEventW(NULL, FALSE, FALSE, NULL);
1037       }
1038       found = TRUE;
1039       break;
1040     }
1041   }
1042   LeaveCriticalSection(&server_cs);
1043 
1044   if (!found) {
1045     ERR("not found for object %s\n", debugstr_guid(MgrTypeUuid));
1046     return RPC_S_UNKNOWN_IF;
1047   }
1048 
1049   if (completed)
1050     HeapFree(GetProcessHeap(), 0, cif);
1051   else if (event) {
1052     /* sif will be freed when the last call is completed, so be careful not to
1053      * touch that memory here as that could happen before we get here */
1054     WaitForSingleObject(event, INFINITE);
1055     CloseHandle(event);
1056   }
1057 
1058   return RPC_S_OK;
1059 }
1060 
1061 /***********************************************************************
1062  *             RpcServerUnregisterIfEx (RPCRT4.@)
1063  */
1064 RPC_STATUS WINAPI RpcServerUnregisterIfEx( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, int RundownContextHandles )
1065 {
1066   FIXME("(IfSpec == (RPC_IF_HANDLE)^%p, MgrTypeUuid == %s, RundownContextHandles == %d): stub\n",
1067     IfSpec, debugstr_guid(MgrTypeUuid), RundownContextHandles);
1068 
1069   return RPC_S_OK;
1070 }
1071 
1072 /***********************************************************************
1073  *             RpcObjectSetType (RPCRT4.@)
1074  *
1075  * PARAMS
1076  *   ObjUuid  [I] "Object" UUID
1077  *   TypeUuid [I] "Type" UUID
1078  *
1079  * RETURNS
1080  *   RPC_S_OK                 The call succeeded
1081  *   RPC_S_INVALID_OBJECT     The provided object (nil) is not valid
1082  *   RPC_S_ALREADY_REGISTERED The provided object is already registered
1083  *
1084  * Maps "Object" UUIDs to "Type" UUID's.  Passing the nil UUID as the type
1085  * resets the mapping for the specified object UUID to nil (the default).
1086  * The nil object is always associated with the nil type and cannot be
1087  * reassigned.  Servers can support multiple implementations on the same
1088  * interface by registering different end-point vectors for the different
1089  * types.  There's no need to call this if a server only supports the nil
1090  * type, as is typical.
1091  */
1092 RPC_STATUS WINAPI RpcObjectSetType( UUID* ObjUuid, UUID* TypeUuid )
1093 {
1094   RpcObjTypeMap *map = RpcObjTypeMaps, *prev = NULL;
1095   RPC_STATUS dummy;
1096 
1097   TRACE("(ObjUUID == %s, TypeUuid == %s).\n", debugstr_guid(ObjUuid), debugstr_guid(TypeUuid));
1098   if ((! ObjUuid) || UuidIsNil(ObjUuid, &dummy)) {
1099     /* nil uuid cannot be remapped */
1100     return RPC_S_INVALID_OBJECT;
1101   }
1102 
1103   /* find the mapping for this object if there is one ... */
1104   while (map) {
1105     if (! UuidCompare(ObjUuid, &map->Object, &dummy)) break;
1106     prev = map;
1107     map = map->next;
1108   }
1109   if ((! TypeUuid) || UuidIsNil(TypeUuid, &dummy)) {
1110     /* ... and drop it from the list */
1111     if (map) {
1112       if (prev) 
1113         prev->next = map->next;
1114       else
1115         RpcObjTypeMaps = map->next;
1116       HeapFree(GetProcessHeap(), 0, map);
1117     }
1118   } else {
1119     /* ... , fail if we found it ... */
1120     if (map)
1121       return RPC_S_ALREADY_REGISTERED;
1122     /* ... otherwise create a new one and add it in. */
1123     map = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcObjTypeMap));
1124     map->Object = *ObjUuid;
1125     map->Type = *TypeUuid;
1126     map->next = NULL;
1127     if (prev)
1128       prev->next = map; /* prev is the last map in the linklist */
1129     else
1130       RpcObjTypeMaps = map;
1131   }
1132 
1133   return RPC_S_OK;
1134 }
1135 
1136 /***********************************************************************
1137  *             RpcServerRegisterAuthInfoA (RPCRT4.@)
1138  */
1139 RPC_STATUS WINAPI RpcServerRegisterAuthInfoA( RPC_CSTR ServerPrincName, ULONG AuthnSvc, RPC_AUTH_KEY_RETRIEVAL_FN GetKeyFn,
1140                             LPVOID Arg )
1141 {
1142   FIXME( "(%s,%u,%p,%p): stub\n", ServerPrincName, AuthnSvc, GetKeyFn, Arg );
1143   
1144   return RPC_S_UNKNOWN_AUTHN_SERVICE; /* We don't know any authentication services */
1145 }
1146 
1147 /***********************************************************************
1148  *             RpcServerRegisterAuthInfoW (RPCRT4.@)
1149  */
1150 RPC_STATUS WINAPI RpcServerRegisterAuthInfoW( RPC_WSTR ServerPrincName, ULONG AuthnSvc, RPC_AUTH_KEY_RETRIEVAL_FN GetKeyFn,
1151                             LPVOID Arg )
1152 {
1153   FIXME( "(%s,%u,%p,%p): stub\n", debugstr_w( ServerPrincName ), AuthnSvc, GetKeyFn, Arg );
1154   
1155   return RPC_S_UNKNOWN_AUTHN_SERVICE; /* We don't know any authentication services */
1156 }
1157 
1158 /***********************************************************************
1159  *             RpcServerListen (RPCRT4.@)
1160  */
1161 RPC_STATUS WINAPI RpcServerListen( UINT MinimumCallThreads, UINT MaxCalls, UINT DontWait )
1162 {
1163   RPC_STATUS status = RPC_S_OK;
1164 
1165   TRACE("(%u,%u,%u)\n", MinimumCallThreads, MaxCalls, DontWait);
1166 
1167   if (list_empty(&protseqs))
1168     return RPC_S_NO_PROTSEQS_REGISTERED;
1169 
1170   status = RPCRT4_start_listen(FALSE);
1171 
1172   if (DontWait || (status != RPC_S_OK)) return status;
1173 
1174   return RpcMgmtWaitServerListen();
1175 }
1176 
1177 /***********************************************************************
1178  *             RpcMgmtServerWaitListen (RPCRT4.@)
1179  */
1180 RPC_STATUS WINAPI RpcMgmtWaitServerListen( void )
1181 {
1182   TRACE("()\n");
1183 
1184   EnterCriticalSection(&listen_cs);
1185 
1186   if (!std_listen) {
1187     LeaveCriticalSection(&listen_cs);
1188     return RPC_S_NOT_LISTENING;
1189   }
1190   
1191   LeaveCriticalSection(&listen_cs);
1192 
1193   FIXME("not waiting for server calls to finish\n");
1194 
1195   return RPC_S_OK;
1196 }
1197 
1198 /***********************************************************************
1199  *             RpcMgmtStopServerListening (RPCRT4.@)
1200  */
1201 RPC_STATUS WINAPI RpcMgmtStopServerListening ( RPC_BINDING_HANDLE Binding )
1202 {
1203   TRACE("(Binding == (RPC_BINDING_HANDLE)^%p)\n", Binding);
1204 
1205   if (Binding) {
1206     FIXME("client-side invocation not implemented.\n");
1207     return RPC_S_WRONG_KIND_OF_BINDING;
1208   }
1209   
1210   RPCRT4_stop_listen(FALSE);
1211 
1212   return RPC_S_OK;
1213 }
1214 
1215 /***********************************************************************
1216  *             RpcMgmtEnableIdleCleanup (RPCRT4.@)
1217  */
1218 RPC_STATUS WINAPI RpcMgmtEnableIdleCleanup(void)
1219 {
1220     FIXME("(): stub\n");
1221     return RPC_S_OK;
1222 }
1223 
1224 /***********************************************************************
1225  *             I_RpcServerStartListening (RPCRT4.@)
1226  */
1227 RPC_STATUS WINAPI I_RpcServerStartListening( HWND hWnd )
1228 {
1229   FIXME( "(%p): stub\n", hWnd );
1230 
1231   return RPC_S_OK;
1232 }
1233 
1234 /***********************************************************************
1235  *             I_RpcServerStopListening (RPCRT4.@)
1236  */
1237 RPC_STATUS WINAPI I_RpcServerStopListening( void )
1238 {
1239   FIXME( "(): stub\n" );
1240 
1241   return RPC_S_OK;
1242 }
1243 
1244 /***********************************************************************
1245  *             I_RpcWindowProc (RPCRT4.@)
1246  */
1247 UINT WINAPI I_RpcWindowProc( void *hWnd, UINT Message, UINT wParam, ULONG lParam )
1248 {
1249   FIXME( "(%p,%08x,%08x,%08x): stub\n", hWnd, Message, wParam, lParam );
1250 
1251   return 0;
1252 }
1253 
1254 /***********************************************************************
1255  *             RpcMgmtInqIfIds (RPCRT4.@)
1256  */
1257 RPC_STATUS WINAPI RpcMgmtInqIfIds(RPC_BINDING_HANDLE Binding, RPC_IF_ID_VECTOR **IfIdVector)
1258 {
1259   FIXME("(%p,%p): stub\n", Binding, IfIdVector);
1260   return RPC_S_INVALID_BINDING;
1261 }
1262 
1263 /***********************************************************************
1264  *             RpcMgmtInqStats (RPCRT4.@)
1265  */
1266 RPC_STATUS WINAPI RpcMgmtInqStats(RPC_BINDING_HANDLE Binding, RPC_STATS_VECTOR **Statistics)
1267 {
1268   RPC_STATS_VECTOR *stats;
1269 
1270   FIXME("(%p,%p)\n", Binding, Statistics);
1271 
1272   if ((stats = HeapAlloc(GetProcessHeap(), 0, sizeof(RPC_STATS_VECTOR))))
1273   {
1274     stats->Count = 1;
1275     stats->Stats[0] = 0;
1276     *Statistics = stats;
1277     return RPC_S_OK;
1278   }
1279   return RPC_S_OUT_OF_RESOURCES;
1280 }
1281 
1282 /***********************************************************************
1283  *             RpcMgmtStatsVectorFree (RPCRT4.@)
1284  */
1285 RPC_STATUS WINAPI RpcMgmtStatsVectorFree(RPC_STATS_VECTOR **StatsVector)
1286 {
1287   FIXME("(%p)\n", StatsVector);
1288 
1289   if (StatsVector)
1290   {
1291     HeapFree(GetProcessHeap(), 0, *StatsVector);
1292     *StatsVector = NULL;
1293   }
1294   return RPC_S_OK;
1295 }
1296 
1297 /***********************************************************************
1298  *             RpcMgmtEpEltInqBegin (RPCRT4.@)
1299  */
1300 RPC_STATUS WINAPI RpcMgmtEpEltInqBegin(RPC_BINDING_HANDLE Binding, ULONG InquiryType,
1301     RPC_IF_ID *IfId, ULONG VersOption, UUID *ObjectUuid, RPC_EP_INQ_HANDLE* InquiryContext)
1302 {
1303   FIXME("(%p,%u,%p,%u,%p,%p): stub\n",
1304         Binding, InquiryType, IfId, VersOption, ObjectUuid, InquiryContext);
1305   return RPC_S_INVALID_BINDING;
1306 }
1307 
1308 /***********************************************************************
1309  *             RpcMgmtIsServerListening (RPCRT4.@)
1310  */
1311 RPC_STATUS WINAPI RpcMgmtIsServerListening(RPC_BINDING_HANDLE Binding)
1312 {
1313   FIXME("(%p): stub\n", Binding);
1314   return RPC_S_INVALID_BINDING;
1315 }
1316 
1317 /***********************************************************************
1318  *             RpcMgmtSetServerStackSize (RPCRT4.@)
1319  */
1320 RPC_STATUS WINAPI RpcMgmtSetServerStackSize(ULONG ThreadStackSize)
1321 {
1322   FIXME("(0x%x): stub\n", ThreadStackSize);
1323   return RPC_S_OK;
1324 }
1325 
1326 /***********************************************************************
1327  *             I_RpcGetCurrentCallHandle (RPCRT4.@)
1328  */
1329 RPC_BINDING_HANDLE WINAPI I_RpcGetCurrentCallHandle(void)
1330 {
1331     TRACE("\n");
1332     return RPCRT4_GetThreadCurrentCallHandle();
1333 }
1334 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.