Fix some problems found by winapi_check.
[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 <stdio.h>
25 #include <string.h>
26 #include <assert.h>
27
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winerror.h"
31 #include "winreg.h"
32
33 #include "rpc.h"
34
35 #include "wine/debug.h"
36
37 #include "rpc_server.h"
38 #include "rpc_defs.h"
39
40 WINE_DEFAULT_DEBUG_CHANNEL(ole);
41
42 static RpcServerProtseq* protseqs;
43 static RpcServerInterface* ifs;
44
45 static CRITICAL_SECTION server_cs = CRITICAL_SECTION_INIT("RpcServer");
46 static CRITICAL_SECTION listen_cs = CRITICAL_SECTION_INIT("RpcListen");
47 static BOOL std_listen;
48 static LONG listen_count = -1;
49 static HANDLE mgr_event, server_thread;
50
51 static RpcServerInterface* RPCRT4_find_interface(UUID* object, UUID* if_id)
52 {
53   UUID* MgrType = NULL;
54   RpcServerInterface* cif = NULL;
55   RPC_STATUS status;
56
57   /* FIXME: object -> MgrType */
58   EnterCriticalSection(&server_cs);
59   cif = ifs;
60   while (cif) {
61     if (UuidEqual(if_id, &cif->If->InterfaceId.SyntaxGUID, &status) &&
62        UuidEqual(MgrType, &cif->MgrTypeUuid, &status) &&
63        (std_listen || (cif->Flags & RPC_IF_AUTOLISTEN))) break;
64     cif = cif->Next;
65   }
66   LeaveCriticalSection(&server_cs);
67   return cif;
68 }
69
70 static DWORD CALLBACK RPCRT4_io_thread(LPVOID the_arg)
71 {
72   RpcBinding* bind = (RpcBinding*)the_arg;
73   RpcPktHdr hdr;
74   DWORD dwRead;
75   RPC_MESSAGE msg;
76   RpcServerInterface* sif;
77   RPC_DISPATCH_FUNCTION func;
78
79   memset(&msg, 0, sizeof(msg));
80   msg.Handle = (RPC_BINDING_HANDLE)bind;
81
82   for (;;) {
83     /* read packet header */
84 #ifdef OVERLAPPED_WORKS
85     if (!ReadFile(bind->conn, &hdr, sizeof(hdr), &dwRead, &bind->ovl)) {
86       DWORD err = GetLastError();
87       if (err != ERROR_IO_PENDING) {
88         TRACE("connection lost, error=%08lx\n", err);
89         break;
90       }
91       if (!GetOverlappedResult(bind->conn, &bind->ovl, &dwRead, TRUE)) break;
92     }
93 #else
94     if (!ReadFile(bind->conn, &hdr, sizeof(hdr), &dwRead, NULL)) {
95       TRACE("connection lost, error=%08lx\n", GetLastError());
96       break;
97     }
98 #endif
99     if (dwRead != sizeof(hdr)) {
100       if (dwRead) TRACE("protocol error: <hdrsz == %d, dwRead == %lu>\n", sizeof(hdr), dwRead);
101       break;
102     }
103
104     /* read packet body */
105     msg.BufferLength = hdr.len;
106     msg.Buffer = HeapAlloc(GetProcessHeap(), 0, msg.BufferLength);
107 #ifdef OVERLAPPED_WORKS
108     if (!ReadFile(bind->conn, msg.Buffer, msg.BufferLength, &dwRead, &bind->ovl)) {
109       DWORD err = GetLastError();
110       if (err != ERROR_IO_PENDING) {
111         TRACE("connection lost, error=%08lx\n", err);
112         break;
113       }
114       if (!GetOverlappedResult(bind->conn, &bind->ovl, &dwRead, TRUE)) break;
115     }
116 #else
117     if (!ReadFile(bind->conn, msg.Buffer, msg.BufferLength, &dwRead, NULL)) {
118       TRACE("connection lost, error=%08lx\n", GetLastError());
119       break;
120     }
121 #endif
122     if (dwRead != hdr.len) {
123       TRACE("protocol error: <bodylen == %d, dwRead == %lu>\n", hdr.len, dwRead);
124       break;
125     }
126
127     sif = RPCRT4_find_interface(&hdr.object, &hdr.if_id);
128     if (sif) {
129       msg.RpcInterfaceInformation = sif->If;
130       /* associate object with binding (this is a bit of a hack...
131        * a new binding should probably be created for each object) */
132       RPCRT4_SetBindingObject(bind, &hdr.object);
133       /* process packet*/
134       switch (hdr.ptype) {
135       case PKT_REQUEST:
136        /* find dispatch function */
137        msg.ProcNum = hdr.opnum;
138        if (sif->Flags & RPC_IF_OLE) {
139          /* native ole32 always gives us a dispatch table with a single entry
140           * (I assume that's a wrapper for IRpcStubBuffer::Invoke) */
141          func = *sif->If->DispatchTable->DispatchTable;
142        } else {
143          if (msg.ProcNum >= sif->If->DispatchTable->DispatchTableCount) {
144            ERR("invalid procnum\n");
145            func = NULL;
146          }
147          func = sif->If->DispatchTable->DispatchTable[msg.ProcNum];
148        }
149        
150        /* put in the drep. FIXME: is this more universally applicable?
151           perhaps we should move this outward... */
152        msg.DataRepresentation = 
153          MAKELONG( MAKEWORD(hdr.drep[0], hdr.drep[1]),
154                    MAKEWORD(hdr.drep[2], 0));
155
156        /* dispatch */
157        if (func) func(&msg);
158
159        /* prepare response packet */
160        hdr.ptype = PKT_RESPONSE;
161        break;
162       default:
163        ERR("unknown packet type\n");
164        goto no_reply;
165       }
166
167       /* write reply packet */
168       hdr.len = msg.BufferLength;
169       WriteFile(bind->conn, &hdr, sizeof(hdr), NULL, NULL);
170       WriteFile(bind->conn, msg.Buffer, msg.BufferLength, NULL, NULL);
171
172     no_reply:
173       /* un-associate object */
174       RPCRT4_SetBindingObject(bind, NULL);
175       msg.RpcInterfaceInformation = NULL;
176     }
177     else {
178       ERR("got RPC packet to unregistered interface %s\n", debugstr_guid(&hdr.if_id));
179     }
180
181     /* clean up */
182     HeapFree(GetProcessHeap(), 0, msg.Buffer);
183     msg.Buffer = NULL;
184   }
185   if (msg.Buffer) HeapFree(GetProcessHeap(), 0, msg.Buffer);
186   RPCRT4_DestroyBinding(bind);
187   return 0;
188 }
189
190 static void RPCRT4_new_client(RpcBinding* bind)
191 {
192   bind->thread = CreateThread(NULL, 0, RPCRT4_io_thread, bind, 0, NULL);
193 }
194
195 static DWORD CALLBACK RPCRT4_server_thread(LPVOID the_arg)
196 {
197   HANDLE m_event = mgr_event, b_handle;
198   HANDLE *objs = NULL;
199   DWORD count, res;
200   RpcServerProtseq* cps;
201   RpcBinding* bind;
202   RpcBinding* cbind;
203
204   for (;;) {
205     EnterCriticalSection(&server_cs);
206     /* open and count bindings */
207     count = 1;
208     cps = protseqs;
209     while (cps) {
210       bind = cps->bind;
211       while (bind) {
212        RPCRT4_OpenBinding(bind);
213         if (bind->ovl.hEvent) count++;
214         bind = bind->Next;
215       }
216       cps = cps->Next;
217     }
218     /* make array of bindings */
219     objs = HeapReAlloc(GetProcessHeap(), 0, objs, count*sizeof(HANDLE));
220     objs[0] = m_event;
221     count = 1;
222     cps = protseqs;
223     while (cps) {
224       bind = cps->bind;
225       while (bind) {
226         if (bind->ovl.hEvent) objs[count++] = bind->ovl.hEvent;
227         bind = bind->Next;
228       }
229       cps = cps->Next;
230     }
231     LeaveCriticalSection(&server_cs);
232
233     /* start waiting */
234     res = WaitForMultipleObjects(count, objs, FALSE, INFINITE);
235     if (res == WAIT_OBJECT_0) {
236       ResetEvent(m_event);
237       if (!std_listen) break;
238     }
239     else if (res == WAIT_FAILED) {
240       ERR("wait failed\n");
241     }
242     else {
243       b_handle = objs[res - WAIT_OBJECT_0];
244       /* find which binding got a RPC */
245       EnterCriticalSection(&server_cs);
246       bind = NULL;
247       cps = protseqs;
248       while (cps) {
249         bind = cps->bind;
250         while (bind) {
251           if (bind->ovl.hEvent == b_handle) break;
252           bind = bind->Next;
253         }
254         if (bind) break;
255         cps = cps->Next;
256       }
257       cbind = NULL;
258       if (bind) RPCRT4_SpawnBinding(&cbind, bind);
259       LeaveCriticalSection(&server_cs);
260       if (!bind) {
261         ERR("failed to locate binding for handle %p\n", b_handle);
262       }
263       if (cbind) RPCRT4_new_client(cbind);
264     }
265   }
266   HeapFree(GetProcessHeap(), 0, objs);
267   EnterCriticalSection(&server_cs);
268   /* close bindings */
269   cps = protseqs;
270   while (cps) {
271     bind = cps->bind;
272     while (bind) {
273       RPCRT4_CloseBinding(bind);
274       bind = bind->Next;
275     }
276     cps = cps->Next;
277   }
278   LeaveCriticalSection(&server_cs);
279   return 0;
280 }
281
282 static void RPCRT4_start_listen(void)
283 {
284   TRACE("\n");
285
286   EnterCriticalSection(&listen_cs);
287   if (! ++listen_count) {
288     if (!mgr_event) mgr_event = CreateEventA(NULL, TRUE, FALSE, NULL);
289     std_listen = TRUE;
290     server_thread = CreateThread(NULL, 0, RPCRT4_server_thread, NULL, 0, NULL);
291     LeaveCriticalSection(&listen_cs);
292   } else {
293     LeaveCriticalSection(&listen_cs);
294     SetEvent(mgr_event);
295   }
296 }
297
298 static void RPCRT4_stop_listen(void)
299 {
300   EnterCriticalSection(&listen_cs);
301   if (listen_count == -1)
302     LeaveCriticalSection(&listen_cs);
303   else if (--listen_count == -1) {
304     std_listen = FALSE;
305     LeaveCriticalSection(&listen_cs);
306     SetEvent(mgr_event);
307   } else
308     LeaveCriticalSection(&listen_cs);
309   assert(listen_count > -2);
310 }
311
312 static RPC_STATUS RPCRT4_use_protseq(RpcServerProtseq* ps)
313 {
314   RPCRT4_CreateBindingA(&ps->bind, TRUE, ps->Protseq);
315   RPCRT4_CompleteBindingA(ps->bind, NULL, ps->Endpoint, NULL);
316
317   EnterCriticalSection(&server_cs);
318   ps->Next = protseqs;
319   protseqs = ps;
320   LeaveCriticalSection(&server_cs);
321
322   if (std_listen) SetEvent(mgr_event);
323
324   return RPC_S_OK;
325 }
326
327 /***********************************************************************
328  *             RpcServerInqBindings (RPCRT4.@)
329  */
330 RPC_STATUS WINAPI RpcServerInqBindings( RPC_BINDING_VECTOR** BindingVector )
331 {
332   RPC_STATUS status;
333   DWORD count;
334   RpcServerProtseq* ps;
335   RpcBinding* bind;
336
337   if (BindingVector)
338     TRACE("(*BindingVector == ^%p)\n", *BindingVector);
339   else
340     ERR("(BindingVector == ^null!!?)\n");
341
342   EnterCriticalSection(&server_cs);
343   /* count bindings */
344   count = 0;
345   ps = protseqs;
346   while (ps) {
347     bind = ps->bind;
348     while (bind) {
349       count++;
350       bind = bind->Next;
351     }
352     ps = ps->Next;
353   }
354   if (count) {
355     /* export bindings */
356     *BindingVector = HeapAlloc(GetProcessHeap(), 0,
357                               sizeof(RPC_BINDING_VECTOR) +
358                               sizeof(RPC_BINDING_HANDLE)*(count-1));
359     (*BindingVector)->Count = count;
360     count = 0;
361     ps = protseqs;
362     while (ps) {
363       bind = ps->bind;
364       while (bind) {
365        RPCRT4_ExportBinding((RpcBinding**)&(*BindingVector)->BindingH[count],
366                             bind);
367        count++;
368        bind = bind->Next;
369       }
370       ps = ps->Next;
371     }
372     status = RPC_S_OK;
373   } else {
374     *BindingVector = NULL;
375     status = RPC_S_NO_BINDINGS;
376   }
377   LeaveCriticalSection(&server_cs);
378   return status;
379 }
380
381 /***********************************************************************
382  *             RpcServerUseProtseqEpA (RPCRT4.@)
383  */
384 RPC_STATUS WINAPI RpcServerUseProtseqEpA( LPSTR Protseq, UINT MaxCalls, LPSTR Endpoint, LPVOID SecurityDescriptor )
385 {
386   RPC_POLICY policy;
387   
388   TRACE( "(%s,%u,%s,%p)\n", Protseq, MaxCalls, Endpoint, SecurityDescriptor );
389   
390   /* This should provide the default behaviour */
391   policy.Length        = sizeof( policy );
392   policy.EndpointFlags = 0;
393   policy.NICFlags      = 0;
394   
395   return RpcServerUseProtseqEpExA( Protseq, MaxCalls, Endpoint, SecurityDescriptor, &policy );
396 }
397
398 /***********************************************************************
399  *             RpcServerUseProtseqEpW (RPCRT4.@)
400  */
401 RPC_STATUS WINAPI RpcServerUseProtseqEpW( LPWSTR Protseq, UINT MaxCalls, LPWSTR Endpoint, LPVOID SecurityDescriptor )
402 {
403   RPC_POLICY policy;
404   
405   TRACE( "(%s,%u,%s,%p)\n", debugstr_w( Protseq ), MaxCalls, debugstr_w( Endpoint ), SecurityDescriptor );
406   
407   /* This should provide the default behaviour */
408   policy.Length        = sizeof( policy );
409   policy.EndpointFlags = 0;
410   policy.NICFlags      = 0;
411   
412   return RpcServerUseProtseqEpExW( Protseq, MaxCalls, Endpoint, SecurityDescriptor, &policy );
413 }
414
415 /***********************************************************************
416  *             RpcServerUseProtseqEpExA (RPCRT4.@)
417  */
418 RPC_STATUS WINAPI RpcServerUseProtseqEpExA( LPSTR Protseq, UINT MaxCalls, LPSTR Endpoint, LPVOID SecurityDescriptor,
419                                             PRPC_POLICY lpPolicy )
420 {
421   RpcServerProtseq* ps;
422
423   TRACE("(%s,%u,%s,%p,{%u,%lu,%lu})\n", debugstr_a( Protseq ), MaxCalls,
424        debugstr_a( Endpoint ), SecurityDescriptor,
425        lpPolicy->Length, lpPolicy->EndpointFlags, lpPolicy->NICFlags );
426
427   ps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcServerProtseq));
428   ps->MaxCalls = MaxCalls;
429   ps->Protseq = RPCRT4_strdupA(Protseq);
430   ps->Endpoint = RPCRT4_strdupA(Endpoint);
431
432   return RPCRT4_use_protseq(ps);
433 }
434
435 /***********************************************************************
436  *             RpcServerUseProtseqEpExW (RPCRT4.@)
437  */
438 RPC_STATUS WINAPI RpcServerUseProtseqEpExW( LPWSTR Protseq, UINT MaxCalls, LPWSTR Endpoint, LPVOID SecurityDescriptor,
439                                             PRPC_POLICY lpPolicy )
440 {
441   RpcServerProtseq* ps;
442
443   TRACE("(%s,%u,%s,%p,{%u,%lu,%lu})\n", debugstr_w( Protseq ), MaxCalls,
444        debugstr_w( Endpoint ), SecurityDescriptor,
445        lpPolicy->Length, lpPolicy->EndpointFlags, lpPolicy->NICFlags );
446
447   ps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcServerProtseq));
448   ps->MaxCalls = MaxCalls;
449   /* FIXME: Did Ove have these next two as RPCRT4_strdupW for a reason? */
450   ps->Protseq = RPCRT4_strdupWtoA(Protseq);
451   ps->Endpoint = RPCRT4_strdupWtoA(Endpoint);
452
453   return RPCRT4_use_protseq(ps);
454 }
455
456 /***********************************************************************
457  *             RpcServerUseProtseqA (RPCRT4.@)
458  */
459 RPC_STATUS WINAPI RpcServerUseProtseqA(LPSTR Protseq, unsigned int MaxCalls, void *SecurityDescriptor)
460 {
461   TRACE("(Protseq == %s, MaxCalls == %d, SecurityDescriptor == ^%p)", debugstr_a(Protseq), MaxCalls, SecurityDescriptor);
462   return RpcServerUseProtseqEpA(Protseq, MaxCalls, NULL, SecurityDescriptor);
463 }
464
465 /***********************************************************************
466  *             RpcServerUseProtseqW (RPCRT4.@)
467  */
468 RPC_STATUS WINAPI RpcServerUseProtseqW(LPWSTR Protseq, unsigned int MaxCalls, void *SecurityDescriptor)
469 {
470   TRACE("Protseq == %s, MaxCalls == %d, SecurityDescriptor == ^%p)", debugstr_w(Protseq), MaxCalls, SecurityDescriptor);
471   return RpcServerUseProtseqEpW(Protseq, MaxCalls, NULL, SecurityDescriptor);
472 }
473
474 /***********************************************************************
475  *             RpcServerRegisterIf (RPCRT4.@)
476  */
477 RPC_STATUS WINAPI RpcServerRegisterIf( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, RPC_MGR_EPV* MgrEpv )
478 {
479   TRACE("(%p,%s,%p)\n", IfSpec, debugstr_guid(MgrTypeUuid), MgrEpv);
480   return RpcServerRegisterIf2( IfSpec, MgrTypeUuid, MgrEpv, 0, RPC_C_LISTEN_MAX_CALLS_DEFAULT, (UINT)-1, NULL );
481 }
482
483 /***********************************************************************
484  *             RpcServerRegisterIfEx (RPCRT4.@)
485  */
486 RPC_STATUS WINAPI RpcServerRegisterIfEx( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, RPC_MGR_EPV* MgrEpv,
487                        UINT Flags, UINT MaxCalls, RPC_IF_CALLBACK_FN* IfCallbackFn )
488 {
489   TRACE("(%p,%s,%p,%u,%u,%p)\n", IfSpec, debugstr_guid(MgrTypeUuid), MgrEpv, Flags, MaxCalls, IfCallbackFn);
490   return RpcServerRegisterIf2( IfSpec, MgrTypeUuid, MgrEpv, Flags, MaxCalls, (UINT)-1, IfCallbackFn );
491 }
492
493 /***********************************************************************
494  *             RpcServerRegisterIf2 (RPCRT4.@)
495  */
496 RPC_STATUS WINAPI RpcServerRegisterIf2( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, RPC_MGR_EPV* MgrEpv,
497                       UINT Flags, UINT MaxCalls, UINT MaxRpcSize, RPC_IF_CALLBACK_FN* IfCallbackFn )
498 {
499   PRPC_SERVER_INTERFACE If = (PRPC_SERVER_INTERFACE)IfSpec;
500   RpcServerInterface* sif;
501   int i;
502
503   TRACE("(%p,%s,%p,%u,%u,%u,%p)\n", IfSpec, debugstr_guid(MgrTypeUuid), MgrEpv, Flags, MaxCalls,
504          MaxRpcSize, IfCallbackFn);
505   TRACE(" interface id: %s %d.%d\n", debugstr_guid(&If->InterfaceId.SyntaxGUID),
506                                      If->InterfaceId.SyntaxVersion.MajorVersion,
507                                      If->InterfaceId.SyntaxVersion.MinorVersion);
508   TRACE(" transfer syntax: %s %d.%d\n", debugstr_guid(&If->TransferSyntax.SyntaxGUID),
509                                         If->TransferSyntax.SyntaxVersion.MajorVersion,
510                                         If->TransferSyntax.SyntaxVersion.MinorVersion);
511   TRACE(" dispatch table: %p\n", If->DispatchTable);
512   if (If->DispatchTable) {
513     TRACE("  dispatch table count: %d\n", If->DispatchTable->DispatchTableCount);
514     for (i=0; i<If->DispatchTable->DispatchTableCount; i++) {
515       TRACE("   entry %d: %p\n", i, If->DispatchTable->DispatchTable[i]);
516     }
517     TRACE("  reserved: %ld\n", If->DispatchTable->Reserved);
518   }
519   TRACE(" protseq endpoint count: %d\n", If->RpcProtseqEndpointCount);
520   TRACE(" default manager epv: %p\n", If->DefaultManagerEpv);
521   TRACE(" interpreter info: %p\n", If->InterpreterInfo);
522   TRACE(" flags: %08x\n", If->Flags);
523
524   sif = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcServerInterface));
525   sif->If           = If;
526   if (MgrTypeUuid)
527     memcpy(&sif->MgrTypeUuid, MgrTypeUuid, sizeof(UUID));
528   else
529     memset(&sif->MgrTypeUuid, 0, sizeof(UUID));
530   sif->MgrEpv       = MgrEpv;
531   sif->Flags        = Flags;
532   sif->MaxCalls     = MaxCalls;
533   sif->MaxRpcSize   = MaxRpcSize;
534   sif->IfCallbackFn = IfCallbackFn;
535
536   EnterCriticalSection(&server_cs);
537   sif->Next = ifs;
538   ifs = sif;
539   LeaveCriticalSection(&server_cs);
540
541   if (sif->Flags & RPC_IF_AUTOLISTEN) {
542     /* well, start listening, I think... */
543     RPCRT4_start_listen();
544   }
545
546   return RPC_S_OK;
547 }
548
549 /***********************************************************************
550  *             RpcServerUnregisterIf (RPCRT4.@)
551  */
552 RPC_STATUS WINAPI RpcServerUnregisterIf( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, UINT WaitForCallsToComplete )
553 {
554   FIXME("(IfSpec == (RPC_IF_HANDLE)^%p, MgrTypeUuid == %s, WaitForCallsToComplete == %u): stub\n",
555     IfSpec, debugstr_guid(MgrTypeUuid), WaitForCallsToComplete);
556
557   return RPC_S_OK;
558 }
559
560 /***********************************************************************
561  *             RpcServerUnregisterIfEx (RPCRT4.@)
562  */
563 RPC_STATUS WINAPI RpcServerUnregisterIfEx( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, int RundownContextHandles )
564 {
565   FIXME("(IfSpec == (RPC_IF_HANDLE)^%p, MgrTypeUuid == %s, RundownContextHandles == %d): stub\n",
566     IfSpec, debugstr_guid(MgrTypeUuid), RundownContextHandles);
567
568   return RPC_S_OK;
569 }
570
571 /***********************************************************************
572  *             RpcServerRegisterAuthInfoA (RPCRT4.@)
573  */
574 RPC_STATUS WINAPI RpcServerRegisterAuthInfoA( LPSTR ServerPrincName, ULONG AuthnSvc, RPC_AUTH_KEY_RETRIEVAL_FN GetKeyFn,
575                             LPVOID Arg )
576 {
577   FIXME( "(%s,%lu,%p,%p): stub\n", ServerPrincName, AuthnSvc, GetKeyFn, Arg );
578   
579   return RPC_S_UNKNOWN_AUTHN_SERVICE; /* We don't know any authentication services */
580 }
581
582 /***********************************************************************
583  *             RpcServerRegisterAuthInfoW (RPCRT4.@)
584  */
585 RPC_STATUS WINAPI RpcServerRegisterAuthInfoW( LPWSTR ServerPrincName, ULONG AuthnSvc, RPC_AUTH_KEY_RETRIEVAL_FN GetKeyFn,
586                             LPVOID Arg )
587 {
588   FIXME( "(%s,%lu,%p,%p): stub\n", debugstr_w( ServerPrincName ), AuthnSvc, GetKeyFn, Arg );
589   
590   return RPC_S_UNKNOWN_AUTHN_SERVICE; /* We don't know any authentication services */
591 }
592
593 /***********************************************************************
594  *             RpcServerListen (RPCRT4.@)
595  */
596 RPC_STATUS WINAPI RpcServerListen( UINT MinimumCallThreads, UINT MaxCalls, UINT DontWait )
597 {
598   TRACE("(%u,%u,%u)\n", MinimumCallThreads, MaxCalls, DontWait);
599
600   if (!protseqs)
601     return RPC_S_NO_PROTSEQS_REGISTERED;
602
603   EnterCriticalSection(&listen_cs);
604
605   if (std_listen) {
606     LeaveCriticalSection(&listen_cs);
607     return RPC_S_ALREADY_LISTENING;
608   }
609
610   RPCRT4_start_listen();
611
612   LeaveCriticalSection(&listen_cs);
613
614   if (DontWait) return RPC_S_OK;
615
616   return RpcMgmtWaitServerListen();
617 }
618
619 /***********************************************************************
620  *             RpcMgmtServerWaitListen (RPCRT4.@)
621  */
622 RPC_STATUS WINAPI RpcMgmtWaitServerListen( void )
623 {
624   RPC_STATUS rslt = RPC_S_OK;
625
626   TRACE("\n");
627
628   EnterCriticalSection(&listen_cs);
629
630   if (!std_listen)
631     if ( (rslt = RpcServerListen(1, 0, TRUE)) != RPC_S_OK ) {
632       LeaveCriticalSection(&listen_cs);
633       return rslt;
634     }
635   
636   LeaveCriticalSection(&listen_cs);
637
638   while (std_listen) {
639     WaitForSingleObject(mgr_event, INFINITE);
640     if (!std_listen) {
641       Sleep(100); /* don't spin violently */
642       TRACE("spinning.\n");
643     }
644   }
645
646   return rslt;
647 }
648
649 /***********************************************************************
650  *             RpcMgmtStopServerListening (RPCRT4.@)
651  */
652 RPC_STATUS WINAPI RpcMgmtStopServerListening ( RPC_BINDING_HANDLE Binding )
653 {
654   TRACE("(Binding == (RPC_BINDING_HANDLE)^%p)\n", Binding);
655
656   if (Binding) {
657     FIXME("client-side invocation not implemented.\n");
658     return RPC_S_WRONG_KIND_OF_BINDING;
659   }
660   
661   /* hmm... */
662   EnterCriticalSection(&listen_cs);
663   while (std_listen)
664     RPCRT4_stop_listen();
665   LeaveCriticalSection(&listen_cs);
666
667   return RPC_S_OK;
668 }
669
670 /***********************************************************************
671  *             I_RpcServerStartListening (RPCRT4.@)
672  */
673 RPC_STATUS WINAPI I_RpcServerStartListening( void* hWnd )
674 {
675   FIXME( "(%p): stub\n", hWnd );
676
677   return RPC_S_OK;
678 }
679
680 /***********************************************************************
681  *             I_RpcServerStopListening (RPCRT4.@)
682  */
683 RPC_STATUS WINAPI I_RpcServerStopListening( void )
684 {
685   FIXME( "(): stub\n" );
686
687   return RPC_S_OK;
688 }
689
690 /***********************************************************************
691  *             I_RpcWindowProc (RPCRT4.@)
692  */
693 UINT WINAPI I_RpcWindowProc( void *hWnd, UINT Message, UINT wParam, ULONG lParam )
694 {
695   FIXME( "(%p,%08x,%08x,%08lx): stub\n", hWnd, Message, wParam, lParam );
696
697   return 0;
698 }