Ensure MSSTYLES_SetActiveTheme fails properly when theme is invalid.
[wine] / dlls / rpcrt4 / rpc_server.c
1 /*
2  * RPC server API
3  *
4  * Copyright 2001 Ove Kåven, TransGaming Technologies
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  * TODO:
21  *  - a whole lot
22  */
23
24 #include "config.h"
25 #include "wine/port.h"
26
27 #include <stdarg.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <assert.h>
31
32 #include "windef.h"
33 #include "winbase.h"
34 #include "winerror.h"
35 #include "winreg.h"
36 #include "ntstatus.h"
37
38 #include "rpc.h"
39 #include "excpt.h"
40
41 #include "wine/debug.h"
42 #include "wine/exception.h"
43
44 #include "rpc_server.h"
45 #include "rpc_misc.h"
46 #include "rpc_defs.h"
47
48 #define MAX_THREADS 128
49
50 WINE_DEFAULT_DEBUG_CHANNEL(ole);
51
52 typedef struct _RpcPacket
53 {
54   struct _RpcPacket* next;
55   struct _RpcConnection* conn;
56   RpcPktHdr hdr;
57   void* buf;
58 } RpcPacket;
59
60 typedef struct _RpcObjTypeMap
61 {
62   /* FIXME: a hash table would be better. */
63   struct _RpcObjTypeMap *next;
64   UUID Object;
65   UUID Type;
66 } RpcObjTypeMap;
67
68 static RpcObjTypeMap *RpcObjTypeMaps;
69
70 static RpcServerProtseq* protseqs;
71 static RpcServerInterface* ifs;
72
73 static CRITICAL_SECTION server_cs;
74 static CRITICAL_SECTION_DEBUG server_cs_debug =
75 {
76     0, 0, &server_cs,
77     { &server_cs_debug.ProcessLocksList, &server_cs_debug.ProcessLocksList },
78       0, 0, { 0, (DWORD)(__FILE__ ": server_cs") }
79 };
80 static CRITICAL_SECTION server_cs = { &server_cs_debug, -1, 0, 0, 0, 0 };
81
82 static CRITICAL_SECTION listen_cs;
83 static CRITICAL_SECTION_DEBUG listen_cs_debug =
84 {
85     0, 0, &listen_cs,
86     { &listen_cs_debug.ProcessLocksList, &listen_cs_debug.ProcessLocksList },
87       0, 0, { 0, (DWORD)(__FILE__ ": listen_cs") }
88 };
89 static CRITICAL_SECTION listen_cs = { &listen_cs_debug, -1, 0, 0, 0, 0 };
90
91 static BOOL std_listen;
92 static LONG listen_count = -1;
93 static HANDLE mgr_event, server_thread;
94
95 static CRITICAL_SECTION spacket_cs;
96 static CRITICAL_SECTION_DEBUG spacket_cs_debug =
97 {
98     0, 0, &spacket_cs,
99     { &spacket_cs_debug.ProcessLocksList, &spacket_cs_debug.ProcessLocksList },
100       0, 0, { 0, (DWORD)(__FILE__ ": spacket_cs") }
101 };
102 static CRITICAL_SECTION spacket_cs = { &spacket_cs_debug, -1, 0, 0, 0, 0 };
103
104 static RpcPacket* spacket_head;
105 static RpcPacket* spacket_tail;
106 static HANDLE server_sem;
107
108 static DWORD worker_count, worker_free, worker_tls;
109
110 static UUID uuid_nil;
111
112 inline static RpcObjTypeMap *LookupObjTypeMap(UUID *ObjUuid)
113 {
114   RpcObjTypeMap *rslt = RpcObjTypeMaps;
115   RPC_STATUS dummy;
116
117   while (rslt) {
118     if (! UuidCompare(ObjUuid, &rslt->Object, &dummy)) break;
119     rslt = rslt->next;
120   }
121
122   return rslt;
123 }
124
125 inline static UUID *LookupObjType(UUID *ObjUuid)
126 {
127   RpcObjTypeMap *map = LookupObjTypeMap(ObjUuid);
128   if (map)
129     return &map->Type;
130   else
131     return &uuid_nil;
132 }
133
134 static RpcServerInterface* RPCRT4_find_interface(UUID* object, UUID* if_id)
135 {
136   UUID* MgrType = NULL;
137   RpcServerInterface* cif = NULL;
138   RPC_STATUS status;
139
140   MgrType = LookupObjType(object);
141   EnterCriticalSection(&server_cs);
142   cif = ifs;
143   while (cif) {
144     if (UuidEqual(if_id, &cif->If->InterfaceId.SyntaxGUID, &status) &&
145        UuidEqual(MgrType, &cif->MgrTypeUuid, &status) &&
146        (std_listen || (cif->Flags & RPC_IF_AUTOLISTEN))) break;
147     cif = cif->Next;
148   }
149   LeaveCriticalSection(&server_cs);
150   return cif;
151 }
152
153 static void RPCRT4_push_packet(RpcPacket* packet)
154 {
155   packet->next = NULL;
156   EnterCriticalSection(&spacket_cs);
157   if (spacket_tail) {
158     spacket_tail->next = packet;
159     spacket_tail = packet;
160   } else {
161     spacket_head = packet;
162     spacket_tail = packet;
163   }
164   LeaveCriticalSection(&spacket_cs);
165 }
166
167 static RpcPacket* RPCRT4_pop_packet(void)
168 {
169   RpcPacket* packet;
170   EnterCriticalSection(&spacket_cs);
171   packet = spacket_head;
172   if (packet) {
173     spacket_head = packet->next;
174     if (!spacket_head) spacket_tail = NULL;
175   }
176   LeaveCriticalSection(&spacket_cs);
177   if (packet) packet->next = NULL;
178   return packet;
179 }
180
181 typedef struct {
182   PRPC_MESSAGE msg;
183   void* buf;
184 } packet_state;
185
186 static WINE_EXCEPTION_FILTER(rpc_filter)
187 {
188   packet_state* state;
189   PRPC_MESSAGE msg;
190   state = TlsGetValue(worker_tls);
191   msg = state->msg;
192   if (msg->Buffer != state->buf) I_RpcFreeBuffer(msg);
193   msg->RpcFlags |= WINE_RPCFLAG_EXCEPTION;
194   msg->BufferLength = sizeof(DWORD);
195   I_RpcGetBuffer(msg);
196   *(DWORD*)msg->Buffer = GetExceptionCode();
197   return EXCEPTION_EXECUTE_HANDLER;
198 }
199
200 static void RPCRT4_process_packet(RpcConnection* conn, RpcPktHdr* hdr, void* buf)
201 {
202   RpcBinding* pbind;
203   RPC_MESSAGE msg;
204   RpcServerInterface* sif;
205   RPC_DISPATCH_FUNCTION func;
206   packet_state state;
207
208   state.msg = &msg;
209   state.buf = buf;
210   TlsSetValue(worker_tls, &state);
211   memset(&msg, 0, sizeof(msg));
212   msg.BufferLength = hdr->len;
213   msg.Buffer = buf;
214   sif = RPCRT4_find_interface(&hdr->object, &hdr->if_id);
215   if (sif) {
216     TRACE("packet received for interface %s\n", debugstr_guid(&hdr->if_id));
217     msg.RpcInterfaceInformation = sif->If;
218     /* copy the endpoint vector from sif to msg so that midl-generated code will use it */
219     msg.ManagerEpv = sif->MgrEpv;
220     /* create temporary binding for dispatch */
221     RPCRT4_MakeBinding(&pbind, conn);
222     RPCRT4_SetBindingObject(pbind, &hdr->object);
223     msg.Handle = (RPC_BINDING_HANDLE)pbind;
224     /* process packet */
225     switch (hdr->ptype) {
226     case PKT_REQUEST:
227       /* find dispatch function */
228       msg.ProcNum = hdr->opnum;
229       if (sif->Flags & RPC_IF_OLE) {
230         /* native ole32 always gives us a dispatch table with a single entry
231          * (I assume that's a wrapper for IRpcStubBuffer::Invoke) */
232         func = *sif->If->DispatchTable->DispatchTable;
233       } else {
234         if (msg.ProcNum >= sif->If->DispatchTable->DispatchTableCount) {
235           ERR("invalid procnum\n");
236           func = NULL;
237         }
238         func = sif->If->DispatchTable->DispatchTable[msg.ProcNum];
239       }
240
241       /* put in the drep. FIXME: is this more universally applicable?
242          perhaps we should move this outward... */
243       msg.DataRepresentation = 
244         MAKELONG( MAKEWORD(hdr->drep[0], hdr->drep[1]),
245                   MAKEWORD(hdr->drep[2], 0));
246
247       /* dispatch */
248       __TRY {
249         if (func) func(&msg);
250       } __EXCEPT(rpc_filter) {
251         /* failure packet was created in rpc_filter */
252         TRACE("exception caught, returning failure packet\n");
253       } __ENDTRY
254
255       /* send response packet */
256       I_RpcSend(&msg);
257       break;
258     default:
259       ERR("unknown packet type\n");
260       break;
261     }
262
263     RPCRT4_DestroyBinding(pbind);
264     msg.Handle = 0;
265     msg.RpcInterfaceInformation = NULL;
266   }
267   else {
268     ERR("got RPC packet to unregistered interface %s\n", debugstr_guid(&hdr->if_id));
269   }
270
271   /* clean up */
272   if (msg.Buffer == buf) msg.Buffer = NULL;
273   TRACE("freeing Buffer=%p\n", buf);
274   HeapFree(GetProcessHeap(), 0, buf);
275   I_RpcFreeBuffer(&msg);
276   msg.Buffer = NULL;
277   TlsSetValue(worker_tls, NULL);
278 }
279
280 static DWORD CALLBACK RPCRT4_worker_thread(LPVOID the_arg)
281 {
282   DWORD obj;
283   RpcPacket* pkt;
284
285   for (;;) {
286     /* idle timeout after 5s */
287     obj = WaitForSingleObject(server_sem, 5000);
288     if (obj == WAIT_TIMEOUT) {
289       /* if another idle thread exist, self-destruct */
290       if (worker_free > 1) break;
291       continue;
292     }
293     pkt = RPCRT4_pop_packet();
294     if (!pkt) continue;
295     InterlockedDecrement(&worker_free);
296     for (;;) {
297       RPCRT4_process_packet(pkt->conn, &pkt->hdr, pkt->buf);
298       HeapFree(GetProcessHeap(), 0, pkt);
299       /* try to grab another packet here without waiting
300        * on the semaphore, in case it hits max */
301       pkt = RPCRT4_pop_packet();
302       if (!pkt) break;
303       /* decrement semaphore */
304       WaitForSingleObject(server_sem, 0);
305     }
306     InterlockedIncrement(&worker_free);
307   }
308   InterlockedDecrement(&worker_free);
309   InterlockedDecrement(&worker_count);
310   return 0;
311 }
312
313 static void RPCRT4_create_worker_if_needed(void)
314 {
315   if (!worker_free && worker_count < MAX_THREADS) {
316     HANDLE thread;
317     InterlockedIncrement(&worker_count);
318     InterlockedIncrement(&worker_free);
319     thread = CreateThread(NULL, 0, RPCRT4_worker_thread, NULL, 0, NULL);
320     if (thread) CloseHandle(thread);
321     else {
322       InterlockedDecrement(&worker_free);
323       InterlockedDecrement(&worker_count);
324     }
325   }
326 }
327
328 static DWORD CALLBACK RPCRT4_io_thread(LPVOID the_arg)
329 {
330   RpcConnection* conn = (RpcConnection*)the_arg;
331   RpcPktHdr hdr;
332   DWORD dwRead;
333   void* buf = NULL;
334   RpcPacket* packet;
335
336   TRACE("(%p)\n", conn);
337
338   for (;;) {
339     /* read packet header */
340 #ifdef OVERLAPPED_WORKS
341     if (!ReadFile(conn->conn, &hdr, sizeof(hdr), &dwRead, &conn->ovl)) {
342       DWORD err = GetLastError();
343       if (err != ERROR_IO_PENDING) {
344         TRACE("connection lost, error=%08lx\n", err);
345         break;
346       }
347       if (!GetOverlappedResult(conn->conn, &conn->ovl, &dwRead, TRUE)) break;
348     }
349 #else
350     if (!ReadFile(conn->conn, &hdr, sizeof(hdr), &dwRead, NULL)) {
351       TRACE("connection lost, error=%08lx\n", GetLastError());
352       break;
353     }
354 #endif
355     if (dwRead != sizeof(hdr)) {
356       if (dwRead) TRACE("protocol error: <hdrsz == %d, dwRead == %lu>\n", sizeof(hdr), dwRead);
357       break;
358     }
359
360     /* read packet body */
361     buf = HeapAlloc(GetProcessHeap(), 0, hdr.len);
362     TRACE("receiving payload=%d\n", hdr.len);
363     if (!hdr.len) dwRead = 0; else
364 #ifdef OVERLAPPED_WORKS
365     if (!ReadFile(conn->conn, buf, hdr.len, &dwRead, &conn->ovl)) {
366       DWORD err = GetLastError();
367       if (err != ERROR_IO_PENDING) {
368         TRACE("connection lost, error=%08lx\n", err);
369         break;
370       }
371       if (!GetOverlappedResult(conn->conn, &conn->ovl, &dwRead, TRUE)) break;
372     }
373 #else
374     if (!ReadFile(conn->conn, buf, hdr.len, &dwRead, NULL)) {
375       TRACE("connection lost, error=%08lx\n", GetLastError());
376       break;
377     }
378 #endif
379     if (dwRead != hdr.len) {
380       TRACE("protocol error: <bodylen == %d, dwRead == %lu>\n", hdr.len, dwRead);
381       break;
382     }
383
384 #if 0
385     RPCRT4_process_packet(conn, &hdr, buf);
386 #else
387     packet = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcPacket));
388     packet->conn = conn;
389     packet->hdr = hdr;
390     packet->buf = buf;
391     RPCRT4_create_worker_if_needed();
392     RPCRT4_push_packet(packet);
393     ReleaseSemaphore(server_sem, 1, NULL);
394 #endif
395     buf = NULL;
396   }
397   if (buf) HeapFree(GetProcessHeap(), 0, buf);
398   RPCRT4_DestroyConnection(conn);
399   return 0;
400 }
401
402 static void RPCRT4_new_client(RpcConnection* conn)
403 {
404   HANDLE thread = CreateThread(NULL, 0, RPCRT4_io_thread, conn, 0, NULL);
405   if (!thread) {
406     DWORD err = GetLastError();
407     ERR("failed to create thread, error=%08lx\n", err);
408     RPCRT4_DestroyConnection(conn);
409   }
410   /* we could set conn->thread, but then we'd have to make the io_thread wait
411    * for that, otherwise the thread might finish, destroy the connection, and
412    * free the memory we'd write to before we did, causing crashes and stuff -
413    * so let's implement that later, when we really need conn->thread */
414
415   CloseHandle( thread );
416 }
417
418 static DWORD CALLBACK RPCRT4_server_thread(LPVOID the_arg)
419 {
420   HANDLE m_event = mgr_event, b_handle;
421   HANDLE *objs = NULL;
422   DWORD count, res;
423   RpcServerProtseq* cps;
424   RpcConnection* conn;
425   RpcConnection* cconn;
426
427   TRACE("(the_arg == ^%p)\n", the_arg);
428
429   for (;;) {
430     EnterCriticalSection(&server_cs);
431     /* open and count connections */
432     count = 1;
433     cps = protseqs;
434     while (cps) {
435       conn = cps->conn;
436       while (conn) {
437         RPCRT4_OpenConnection(conn);
438         if (conn->ovl.hEvent) count++;
439         conn = conn->Next;
440       }
441       cps = cps->Next;
442     }
443     /* make array of connections */
444     if (objs)
445         objs = HeapReAlloc(GetProcessHeap(), 0, objs, count*sizeof(HANDLE));
446     else
447         objs = HeapAlloc(GetProcessHeap(), 0, count*sizeof(HANDLE));
448
449     objs[0] = m_event;
450     count = 1;
451     cps = protseqs;
452     while (cps) {
453       conn = cps->conn;
454       while (conn) {
455         if (conn->ovl.hEvent) objs[count++] = conn->ovl.hEvent;
456         conn = conn->Next;
457       }
458       cps = cps->Next;
459     }
460     LeaveCriticalSection(&server_cs);
461
462     /* start waiting */
463     res = WaitForMultipleObjects(count, objs, FALSE, INFINITE);
464     if (res == WAIT_OBJECT_0) {
465       ResetEvent(m_event);
466       if (!std_listen) break;
467     }
468     else if (res == WAIT_FAILED) {
469       ERR("wait failed\n");
470     }
471     else {
472       b_handle = objs[res - WAIT_OBJECT_0];
473       /* find which connection got a RPC */
474       EnterCriticalSection(&server_cs);
475       conn = NULL;
476       cps = protseqs;
477       while (cps) {
478         conn = cps->conn;
479         while (conn) {
480           if (conn->ovl.hEvent == b_handle) break;
481           conn = conn->Next;
482         }
483         if (conn) break;
484         cps = cps->Next;
485       }
486       cconn = NULL;
487       if (conn) RPCRT4_SpawnConnection(&cconn, conn);
488       LeaveCriticalSection(&server_cs);
489       if (!conn) {
490         ERR("failed to locate connection for handle %p\n", b_handle);
491       }
492       if (cconn) RPCRT4_new_client(cconn);
493     }
494   }
495   HeapFree(GetProcessHeap(), 0, objs);
496   EnterCriticalSection(&server_cs);
497   /* close connections */
498   cps = protseqs;
499   while (cps) {
500     conn = cps->conn;
501     while (conn) {
502       RPCRT4_CloseConnection(conn);
503       conn = conn->Next;
504     }
505     cps = cps->Next;
506   }
507   LeaveCriticalSection(&server_cs);
508   return 0;
509 }
510
511 static void RPCRT4_start_listen(void)
512 {
513   TRACE("\n");
514
515   EnterCriticalSection(&listen_cs);
516   if (! ++listen_count) {
517     if (!mgr_event) mgr_event = CreateEventA(NULL, TRUE, FALSE, NULL);
518     if (!server_sem) server_sem = CreateSemaphoreA(NULL, 0, MAX_THREADS, NULL);
519     if (!worker_tls) worker_tls = TlsAlloc();
520     std_listen = TRUE;
521     server_thread = CreateThread(NULL, 0, RPCRT4_server_thread, NULL, 0, NULL);
522     LeaveCriticalSection(&listen_cs);
523   } else {
524     LeaveCriticalSection(&listen_cs);
525     SetEvent(mgr_event);
526   }
527 }
528
529 static void RPCRT4_stop_listen(void)
530 {
531   EnterCriticalSection(&listen_cs);
532   if (listen_count == -1)
533     LeaveCriticalSection(&listen_cs);
534   else if (--listen_count == -1) {
535     std_listen = FALSE;
536     LeaveCriticalSection(&listen_cs);
537     SetEvent(mgr_event);
538   } else
539     LeaveCriticalSection(&listen_cs);
540   assert(listen_count > -2);
541 }
542
543 static RPC_STATUS RPCRT4_use_protseq(RpcServerProtseq* ps)
544 {
545   RPCRT4_CreateConnection(&ps->conn, TRUE, ps->Protseq, NULL, ps->Endpoint, NULL, NULL);
546
547   EnterCriticalSection(&server_cs);
548   ps->Next = protseqs;
549   protseqs = ps;
550   LeaveCriticalSection(&server_cs);
551
552   if (std_listen) SetEvent(mgr_event);
553
554   return RPC_S_OK;
555 }
556
557 /***********************************************************************
558  *             RpcServerInqBindings (RPCRT4.@)
559  */
560 RPC_STATUS WINAPI RpcServerInqBindings( RPC_BINDING_VECTOR** BindingVector )
561 {
562   RPC_STATUS status;
563   DWORD count;
564   RpcServerProtseq* ps;
565   RpcConnection* conn;
566
567   if (BindingVector)
568     TRACE("(*BindingVector == ^%p)\n", *BindingVector);
569   else
570     ERR("(BindingVector == NULL!!?)\n");
571
572   EnterCriticalSection(&server_cs);
573   /* count connections */
574   count = 0;
575   ps = protseqs;
576   while (ps) {
577     conn = ps->conn;
578     while (conn) {
579       count++;
580       conn = conn->Next;
581     }
582     ps = ps->Next;
583   }
584   if (count) {
585     /* export bindings */
586     *BindingVector = HeapAlloc(GetProcessHeap(), 0,
587                               sizeof(RPC_BINDING_VECTOR) +
588                               sizeof(RPC_BINDING_HANDLE)*(count-1));
589     (*BindingVector)->Count = count;
590     count = 0;
591     ps = protseqs;
592     while (ps) {
593       conn = ps->conn;
594       while (conn) {
595        RPCRT4_MakeBinding((RpcBinding**)&(*BindingVector)->BindingH[count],
596                           conn);
597        count++;
598        conn = conn->Next;
599       }
600       ps = ps->Next;
601     }
602     status = RPC_S_OK;
603   } else {
604     *BindingVector = NULL;
605     status = RPC_S_NO_BINDINGS;
606   }
607   LeaveCriticalSection(&server_cs);
608   return status;
609 }
610
611 /***********************************************************************
612  *             RpcServerUseProtseqEpA (RPCRT4.@)
613  */
614 RPC_STATUS WINAPI RpcServerUseProtseqEpA( LPSTR Protseq, UINT MaxCalls, LPSTR Endpoint, LPVOID SecurityDescriptor )
615 {
616   RPC_POLICY policy;
617   
618   TRACE( "(%s,%u,%s,%p)\n", Protseq, MaxCalls, Endpoint, SecurityDescriptor );
619   
620   /* This should provide the default behaviour */
621   policy.Length        = sizeof( policy );
622   policy.EndpointFlags = 0;
623   policy.NICFlags      = 0;
624   
625   return RpcServerUseProtseqEpExA( Protseq, MaxCalls, Endpoint, SecurityDescriptor, &policy );
626 }
627
628 /***********************************************************************
629  *             RpcServerUseProtseqEpW (RPCRT4.@)
630  */
631 RPC_STATUS WINAPI RpcServerUseProtseqEpW( LPWSTR Protseq, UINT MaxCalls, LPWSTR Endpoint, LPVOID SecurityDescriptor )
632 {
633   RPC_POLICY policy;
634   
635   TRACE( "(%s,%u,%s,%p)\n", debugstr_w( Protseq ), MaxCalls, debugstr_w( Endpoint ), SecurityDescriptor );
636   
637   /* This should provide the default behaviour */
638   policy.Length        = sizeof( policy );
639   policy.EndpointFlags = 0;
640   policy.NICFlags      = 0;
641   
642   return RpcServerUseProtseqEpExW( Protseq, MaxCalls, Endpoint, SecurityDescriptor, &policy );
643 }
644
645 /***********************************************************************
646  *             RpcServerUseProtseqEpExA (RPCRT4.@)
647  */
648 RPC_STATUS WINAPI RpcServerUseProtseqEpExA( LPSTR Protseq, UINT MaxCalls, LPSTR Endpoint, LPVOID SecurityDescriptor,
649                                             PRPC_POLICY lpPolicy )
650 {
651   RpcServerProtseq* ps;
652
653   TRACE("(%s,%u,%s,%p,{%u,%lu,%lu})\n", debugstr_a( Protseq ), MaxCalls,
654        debugstr_a( Endpoint ), SecurityDescriptor,
655        lpPolicy->Length, lpPolicy->EndpointFlags, lpPolicy->NICFlags );
656
657   ps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcServerProtseq));
658   ps->MaxCalls = MaxCalls;
659   ps->Protseq = RPCRT4_strdupA(Protseq);
660   ps->Endpoint = RPCRT4_strdupA(Endpoint);
661
662   return RPCRT4_use_protseq(ps);
663 }
664
665 /***********************************************************************
666  *             RpcServerUseProtseqEpExW (RPCRT4.@)
667  */
668 RPC_STATUS WINAPI RpcServerUseProtseqEpExW( LPWSTR Protseq, UINT MaxCalls, LPWSTR Endpoint, LPVOID SecurityDescriptor,
669                                             PRPC_POLICY lpPolicy )
670 {
671   RpcServerProtseq* ps;
672
673   TRACE("(%s,%u,%s,%p,{%u,%lu,%lu})\n", debugstr_w( Protseq ), MaxCalls,
674        debugstr_w( Endpoint ), SecurityDescriptor,
675        lpPolicy->Length, lpPolicy->EndpointFlags, lpPolicy->NICFlags );
676
677   ps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcServerProtseq));
678   ps->MaxCalls = MaxCalls;
679   ps->Protseq = RPCRT4_strdupWtoA(Protseq);
680   ps->Endpoint = RPCRT4_strdupWtoA(Endpoint);
681
682   return RPCRT4_use_protseq(ps);
683 }
684
685 /***********************************************************************
686  *             RpcServerUseProtseqA (RPCRT4.@)
687  */
688 RPC_STATUS WINAPI RpcServerUseProtseqA(LPSTR Protseq, unsigned int MaxCalls, void *SecurityDescriptor)
689 {
690   TRACE("(Protseq == %s, MaxCalls == %d, SecurityDescriptor == ^%p)", debugstr_a(Protseq), MaxCalls, SecurityDescriptor);
691   return RpcServerUseProtseqEpA(Protseq, MaxCalls, NULL, SecurityDescriptor);
692 }
693
694 /***********************************************************************
695  *             RpcServerUseProtseqW (RPCRT4.@)
696  */
697 RPC_STATUS WINAPI RpcServerUseProtseqW(LPWSTR Protseq, unsigned int MaxCalls, void *SecurityDescriptor)
698 {
699   TRACE("Protseq == %s, MaxCalls == %d, SecurityDescriptor == ^%p)", debugstr_w(Protseq), MaxCalls, SecurityDescriptor);
700   return RpcServerUseProtseqEpW(Protseq, MaxCalls, NULL, SecurityDescriptor);
701 }
702
703 /***********************************************************************
704  *             RpcServerRegisterIf (RPCRT4.@)
705  */
706 RPC_STATUS WINAPI RpcServerRegisterIf( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, RPC_MGR_EPV* MgrEpv )
707 {
708   TRACE("(%p,%s,%p)\n", IfSpec, debugstr_guid(MgrTypeUuid), MgrEpv);
709   return RpcServerRegisterIf2( IfSpec, MgrTypeUuid, MgrEpv, 0, RPC_C_LISTEN_MAX_CALLS_DEFAULT, (UINT)-1, NULL );
710 }
711
712 /***********************************************************************
713  *             RpcServerRegisterIfEx (RPCRT4.@)
714  */
715 RPC_STATUS WINAPI RpcServerRegisterIfEx( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, RPC_MGR_EPV* MgrEpv,
716                        UINT Flags, UINT MaxCalls, RPC_IF_CALLBACK_FN* IfCallbackFn )
717 {
718   TRACE("(%p,%s,%p,%u,%u,%p)\n", IfSpec, debugstr_guid(MgrTypeUuid), MgrEpv, Flags, MaxCalls, IfCallbackFn);
719   return RpcServerRegisterIf2( IfSpec, MgrTypeUuid, MgrEpv, Flags, MaxCalls, (UINT)-1, IfCallbackFn );
720 }
721
722 /***********************************************************************
723  *             RpcServerRegisterIf2 (RPCRT4.@)
724  */
725 RPC_STATUS WINAPI RpcServerRegisterIf2( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, RPC_MGR_EPV* MgrEpv,
726                       UINT Flags, UINT MaxCalls, UINT MaxRpcSize, RPC_IF_CALLBACK_FN* IfCallbackFn )
727 {
728   PRPC_SERVER_INTERFACE If = (PRPC_SERVER_INTERFACE)IfSpec;
729   RpcServerInterface* sif;
730   int i;
731
732   TRACE("(%p,%s,%p,%u,%u,%u,%p)\n", IfSpec, debugstr_guid(MgrTypeUuid), MgrEpv, Flags, MaxCalls,
733          MaxRpcSize, IfCallbackFn);
734   TRACE(" interface id: %s %d.%d\n", debugstr_guid(&If->InterfaceId.SyntaxGUID),
735                                      If->InterfaceId.SyntaxVersion.MajorVersion,
736                                      If->InterfaceId.SyntaxVersion.MinorVersion);
737   TRACE(" transfer syntax: %s %d.%d\n", debugstr_guid(&If->TransferSyntax.SyntaxGUID),
738                                         If->TransferSyntax.SyntaxVersion.MajorVersion,
739                                         If->TransferSyntax.SyntaxVersion.MinorVersion);
740   TRACE(" dispatch table: %p\n", If->DispatchTable);
741   if (If->DispatchTable) {
742     TRACE("  dispatch table count: %d\n", If->DispatchTable->DispatchTableCount);
743     for (i=0; i<If->DispatchTable->DispatchTableCount; i++) {
744       TRACE("   entry %d: %p\n", i, If->DispatchTable->DispatchTable[i]);
745     }
746     TRACE("  reserved: %ld\n", If->DispatchTable->Reserved);
747   }
748   TRACE(" protseq endpoint count: %d\n", If->RpcProtseqEndpointCount);
749   TRACE(" default manager epv: %p\n", If->DefaultManagerEpv);
750   TRACE(" interpreter info: %p\n", If->InterpreterInfo);
751   TRACE(" flags: %08x\n", If->Flags);
752
753   sif = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcServerInterface));
754   sif->If           = If;
755   if (MgrTypeUuid) {
756     memcpy(&sif->MgrTypeUuid, MgrTypeUuid, sizeof(UUID));
757     sif->MgrEpv       = MgrEpv;
758   } else {
759     memset(&sif->MgrTypeUuid, 0, sizeof(UUID));
760     sif->MgrEpv       = If->DefaultManagerEpv;
761   }
762   sif->Flags        = Flags;
763   sif->MaxCalls     = MaxCalls;
764   sif->MaxRpcSize   = MaxRpcSize;
765   sif->IfCallbackFn = IfCallbackFn;
766
767   EnterCriticalSection(&server_cs);
768   sif->Next = ifs;
769   ifs = sif;
770   LeaveCriticalSection(&server_cs);
771
772   if (sif->Flags & RPC_IF_AUTOLISTEN) {
773     /* well, start listening, I think... */
774     RPCRT4_start_listen();
775   }
776
777   return RPC_S_OK;
778 }
779
780 /***********************************************************************
781  *             RpcServerUnregisterIf (RPCRT4.@)
782  */
783 RPC_STATUS WINAPI RpcServerUnregisterIf( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, UINT WaitForCallsToComplete )
784 {
785   FIXME("(IfSpec == (RPC_IF_HANDLE)^%p, MgrTypeUuid == %s, WaitForCallsToComplete == %u): stub\n",
786     IfSpec, debugstr_guid(MgrTypeUuid), WaitForCallsToComplete);
787
788   return RPC_S_OK;
789 }
790
791 /***********************************************************************
792  *             RpcServerUnregisterIfEx (RPCRT4.@)
793  */
794 RPC_STATUS WINAPI RpcServerUnregisterIfEx( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, int RundownContextHandles )
795 {
796   FIXME("(IfSpec == (RPC_IF_HANDLE)^%p, MgrTypeUuid == %s, RundownContextHandles == %d): stub\n",
797     IfSpec, debugstr_guid(MgrTypeUuid), RundownContextHandles);
798
799   return RPC_S_OK;
800 }
801
802 /***********************************************************************
803  *             RpcObjectSetType (RPCRT4.@)
804  *
805  * PARAMS
806  *   ObjUuid  [I] "Object" UUID
807  *   TypeUuid [I] "Type" UUID
808  *
809  * RETURNS
810  *   RPC_S_OK                 The call succeeded
811  *   RPC_S_INVALID_OBJECT     The provided object (nil) is not valid
812  *   RPC_S_ALREADY_REGISTERED The provided object is already registered
813  *
814  * Maps "Object" UUIDs to "Type" UUID's.  Passing the nil UUID as the type
815  * resets the mapping for the specified object UUID to nil (the default).
816  * The nil object is always associated with the nil type and cannot be
817  * reassigned.  Servers can support multiple implementations on the same
818  * interface by registering different end-point vectors for the different
819  * types.  There's no need to call this if a server only supports the nil
820  * type, as is typical.
821  */
822 RPC_STATUS WINAPI RpcObjectSetType( UUID* ObjUuid, UUID* TypeUuid )
823 {
824   RpcObjTypeMap *map = RpcObjTypeMaps, *prev = NULL;
825   RPC_STATUS dummy;
826
827   TRACE("(ObjUUID == %s, TypeUuid == %s).\n", debugstr_guid(ObjUuid), debugstr_guid(TypeUuid));
828   if ((! ObjUuid) || UuidIsNil(ObjUuid, &dummy)) {
829     /* nil uuid cannot be remapped */
830     return RPC_S_INVALID_OBJECT;
831   }
832
833   /* find the mapping for this object if there is one ... */
834   while (map) {
835     if (! UuidCompare(ObjUuid, &map->Object, &dummy)) break;
836     prev = map;
837     map = map->next;
838   }
839   if ((! TypeUuid) || UuidIsNil(TypeUuid, &dummy)) {
840     /* ... and drop it from the list */
841     if (map) {
842       if (prev) 
843         prev->next = map->next;
844       else
845         RpcObjTypeMaps = map->next;
846       HeapFree(GetProcessHeap(), 0, map);
847     }
848   } else {
849     /* ... , fail if we found it ... */
850     if (map)
851       return RPC_S_ALREADY_REGISTERED;
852     /* ... otherwise create a new one and add it in. */
853     map = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcObjTypeMap));
854     memcpy(&map->Object, ObjUuid, sizeof(UUID));
855     memcpy(&map->Type, TypeUuid, sizeof(UUID));
856     map->next = NULL;
857     if (prev)
858       prev->next = map; /* prev is the last map in the linklist */
859     else
860       RpcObjTypeMaps = map;
861   }
862
863   return RPC_S_OK;
864 }
865
866 /***********************************************************************
867  *             RpcServerRegisterAuthInfoA (RPCRT4.@)
868  */
869 RPC_STATUS WINAPI RpcServerRegisterAuthInfoA( LPSTR ServerPrincName, ULONG AuthnSvc, RPC_AUTH_KEY_RETRIEVAL_FN GetKeyFn,
870                             LPVOID Arg )
871 {
872   FIXME( "(%s,%lu,%p,%p): stub\n", ServerPrincName, AuthnSvc, GetKeyFn, Arg );
873   
874   return RPC_S_UNKNOWN_AUTHN_SERVICE; /* We don't know any authentication services */
875 }
876
877 /***********************************************************************
878  *             RpcServerRegisterAuthInfoW (RPCRT4.@)
879  */
880 RPC_STATUS WINAPI RpcServerRegisterAuthInfoW( LPWSTR ServerPrincName, ULONG AuthnSvc, RPC_AUTH_KEY_RETRIEVAL_FN GetKeyFn,
881                             LPVOID Arg )
882 {
883   FIXME( "(%s,%lu,%p,%p): stub\n", debugstr_w( ServerPrincName ), AuthnSvc, GetKeyFn, Arg );
884   
885   return RPC_S_UNKNOWN_AUTHN_SERVICE; /* We don't know any authentication services */
886 }
887
888 /***********************************************************************
889  *             RpcServerListen (RPCRT4.@)
890  */
891 RPC_STATUS WINAPI RpcServerListen( UINT MinimumCallThreads, UINT MaxCalls, UINT DontWait )
892 {
893   TRACE("(%u,%u,%u)\n", MinimumCallThreads, MaxCalls, DontWait);
894
895   if (!protseqs)
896     return RPC_S_NO_PROTSEQS_REGISTERED;
897
898   EnterCriticalSection(&listen_cs);
899
900   if (std_listen) {
901     LeaveCriticalSection(&listen_cs);
902     return RPC_S_ALREADY_LISTENING;
903   }
904
905   RPCRT4_start_listen();
906
907   LeaveCriticalSection(&listen_cs);
908
909   if (DontWait) return RPC_S_OK;
910
911   return RpcMgmtWaitServerListen();
912 }
913
914 /***********************************************************************
915  *             RpcMgmtServerWaitListen (RPCRT4.@)
916  */
917 RPC_STATUS WINAPI RpcMgmtWaitServerListen( void )
918 {
919   RPC_STATUS rslt = RPC_S_OK;
920
921   TRACE("\n");
922
923   EnterCriticalSection(&listen_cs);
924
925   if (!std_listen)
926     if ( (rslt = RpcServerListen(1, 0, TRUE)) != RPC_S_OK ) {
927       LeaveCriticalSection(&listen_cs);
928       return rslt;
929     }
930   
931   LeaveCriticalSection(&listen_cs);
932
933   while (std_listen) {
934     WaitForSingleObject(mgr_event, INFINITE);
935     if (!std_listen) {
936       Sleep(100); /* don't spin violently */
937       TRACE("spinning.\n");
938     }
939   }
940
941   return rslt;
942 }
943
944 /***********************************************************************
945  *             RpcMgmtStopServerListening (RPCRT4.@)
946  */
947 RPC_STATUS WINAPI RpcMgmtStopServerListening ( RPC_BINDING_HANDLE Binding )
948 {
949   TRACE("(Binding == (RPC_BINDING_HANDLE)^%p)\n", Binding);
950
951   if (Binding) {
952     FIXME("client-side invocation not implemented.\n");
953     return RPC_S_WRONG_KIND_OF_BINDING;
954   }
955   
956   /* hmm... */
957   EnterCriticalSection(&listen_cs);
958   while (std_listen)
959     RPCRT4_stop_listen();
960   LeaveCriticalSection(&listen_cs);
961
962   return RPC_S_OK;
963 }
964
965 /***********************************************************************
966  *             I_RpcServerStartListening (RPCRT4.@)
967  */
968 RPC_STATUS WINAPI I_RpcServerStartListening( void* hWnd )
969 {
970   FIXME( "(%p): stub\n", hWnd );
971
972   return RPC_S_OK;
973 }
974
975 /***********************************************************************
976  *             I_RpcServerStopListening (RPCRT4.@)
977  */
978 RPC_STATUS WINAPI I_RpcServerStopListening( void )
979 {
980   FIXME( "(): stub\n" );
981
982   return RPC_S_OK;
983 }
984
985 /***********************************************************************
986  *             I_RpcWindowProc (RPCRT4.@)
987  */
988 UINT WINAPI I_RpcWindowProc( void *hWnd, UINT Message, UINT wParam, ULONG lParam )
989 {
990   FIXME( "(%p,%08x,%08x,%08lx): stub\n", hWnd, Message, wParam, lParam );
991
992   return 0;
993 }