Implemented Rtl*ByteSwap() functions, based on a patch by Jon
[wine/multimedia.git] / dlls / rpcrt4 / rpc_server.c
blob4de7c092564f0cf7ab4c13852ded30f92bb6b852
1 /*
2 * RPC server API
4 * Copyright 2001 Ove Kåven, TransGaming Technologies
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.
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.
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
20 * TODO:
21 * - a whole lot
24 #include <stdio.h>
25 #include <string.h>
26 #include <assert.h>
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winerror.h"
31 #include "winreg.h"
33 #include "rpc.h"
35 #include "wine/debug.h"
37 #include "rpc_server.h"
38 #include "rpc_defs.h"
40 #define MAX_THREADS 128
42 WINE_DEFAULT_DEBUG_CHANNEL(ole);
44 typedef struct _RpcPacket
46 struct _RpcPacket* next;
47 struct _RpcConnection* conn;
48 RpcPktHdr hdr;
49 void* buf;
50 } RpcPacket;
52 static RpcServerProtseq* protseqs;
53 static RpcServerInterface* ifs;
55 static CRITICAL_SECTION server_cs = CRITICAL_SECTION_INIT("RpcServer");
56 static CRITICAL_SECTION listen_cs = CRITICAL_SECTION_INIT("RpcListen");
57 static BOOL std_listen;
58 static LONG listen_count = -1;
59 static HANDLE mgr_event, server_thread;
61 static CRITICAL_SECTION spacket_cs = CRITICAL_SECTION_INIT("RpcServerPacket");
62 static RpcPacket* spacket_head;
63 static RpcPacket* spacket_tail;
64 static HANDLE server_sem;
66 static DWORD worker_count, worker_free;
68 static RpcServerInterface* RPCRT4_find_interface(UUID* object, UUID* if_id)
70 UUID* MgrType = NULL;
71 RpcServerInterface* cif = NULL;
72 RPC_STATUS status;
74 /* FIXME: object -> MgrType */
75 EnterCriticalSection(&server_cs);
76 cif = ifs;
77 while (cif) {
78 if (UuidEqual(if_id, &cif->If->InterfaceId.SyntaxGUID, &status) &&
79 UuidEqual(MgrType, &cif->MgrTypeUuid, &status) &&
80 (std_listen || (cif->Flags & RPC_IF_AUTOLISTEN))) break;
81 cif = cif->Next;
83 LeaveCriticalSection(&server_cs);
84 return cif;
87 static void RPCRT4_push_packet(RpcPacket* packet)
89 packet->next = NULL;
90 EnterCriticalSection(&spacket_cs);
91 if (spacket_tail) spacket_tail->next = packet;
92 else {
93 spacket_head = packet;
94 spacket_tail = packet;
96 LeaveCriticalSection(&spacket_cs);
99 static RpcPacket* RPCRT4_pop_packet(void)
101 RpcPacket* packet;
102 EnterCriticalSection(&spacket_cs);
103 packet = spacket_head;
104 if (packet) {
105 spacket_head = packet->next;
106 if (!spacket_head) spacket_tail = NULL;
108 LeaveCriticalSection(&spacket_cs);
109 if (packet) packet->next = NULL;
110 return packet;
113 static void RPCRT4_process_packet(RpcConnection* conn, RpcPktHdr* hdr, void* buf)
115 RpcBinding* pbind;
116 RPC_MESSAGE msg;
117 RpcServerInterface* sif;
118 RPC_DISPATCH_FUNCTION func;
120 memset(&msg, 0, sizeof(msg));
121 msg.BufferLength = hdr->len;
122 msg.Buffer = buf;
123 sif = RPCRT4_find_interface(&hdr->object, &hdr->if_id);
124 if (sif) {
125 TRACE("packet received for interface %s\n", debugstr_guid(&hdr->if_id));
126 msg.RpcInterfaceInformation = sif->If;
127 /* create temporary binding for dispatch */
128 RPCRT4_MakeBinding(&pbind, conn);
129 RPCRT4_SetBindingObject(pbind, &hdr->object);
130 msg.Handle = (RPC_BINDING_HANDLE)pbind;
131 /* process packet */
132 switch (hdr->ptype) {
133 case PKT_REQUEST:
134 /* find dispatch function */
135 msg.ProcNum = hdr->opnum;
136 if (sif->Flags & RPC_IF_OLE) {
137 /* native ole32 always gives us a dispatch table with a single entry
138 * (I assume that's a wrapper for IRpcStubBuffer::Invoke) */
139 func = *sif->If->DispatchTable->DispatchTable;
140 } else {
141 if (msg.ProcNum >= sif->If->DispatchTable->DispatchTableCount) {
142 ERR("invalid procnum\n");
143 func = NULL;
145 func = sif->If->DispatchTable->DispatchTable[msg.ProcNum];
148 /* put in the drep. FIXME: is this more universally applicable?
149 perhaps we should move this outward... */
150 msg.DataRepresentation =
151 MAKELONG( MAKEWORD(hdr->drep[0], hdr->drep[1]),
152 MAKEWORD(hdr->drep[2], 0));
154 /* dispatch */
155 if (func) func(&msg);
157 /* send response packet */
158 I_RpcSend(&msg);
159 break;
160 default:
161 ERR("unknown packet type\n");
162 break;
165 RPCRT4_DestroyBinding(pbind);
166 msg.Handle = 0;
167 msg.RpcInterfaceInformation = NULL;
169 else {
170 ERR("got RPC packet to unregistered interface %s\n", debugstr_guid(&hdr->if_id));
173 /* clean up */
174 HeapFree(GetProcessHeap(), 0, msg.Buffer);
175 msg.Buffer = NULL;
178 static DWORD CALLBACK RPCRT4_worker_thread(LPVOID the_arg)
180 DWORD obj;
181 RpcPacket* pkt;
183 for (;;) {
184 /* idle timeout after 5s */
185 obj = WaitForSingleObject(server_sem, 5000);
186 if (obj == WAIT_TIMEOUT) {
187 /* if another idle thread exist, self-destruct */
188 if (worker_free > 1) break;
189 continue;
191 pkt = RPCRT4_pop_packet();
192 if (!pkt) continue;
193 InterlockedDecrement(&worker_free);
194 for (;;) {
195 RPCRT4_process_packet(pkt->conn, &pkt->hdr, pkt->buf);
196 HeapFree(GetProcessHeap(), 0, pkt);
197 /* try to grab another packet here without waiting
198 * on the semaphore, in case it hits max */
199 pkt = RPCRT4_pop_packet();
200 if (!pkt) break;
201 /* decrement semaphore */
202 WaitForSingleObject(server_sem, 0);
204 InterlockedIncrement(&worker_free);
206 InterlockedDecrement(&worker_free);
207 InterlockedDecrement(&worker_count);
208 return 0;
211 static void RPCRT4_create_worker_if_needed(void)
213 if (!worker_free && worker_count < MAX_THREADS) {
214 HANDLE thread;
215 InterlockedIncrement(&worker_count);
216 InterlockedIncrement(&worker_free);
217 thread = CreateThread(NULL, 0, RPCRT4_worker_thread, NULL, 0, NULL);
218 if (thread) CloseHandle(thread);
219 else {
220 InterlockedDecrement(&worker_free);
221 InterlockedDecrement(&worker_count);
226 static DWORD CALLBACK RPCRT4_io_thread(LPVOID the_arg)
228 RpcConnection* conn = (RpcConnection*)the_arg;
229 RpcPktHdr hdr;
230 DWORD dwRead;
231 void* buf = NULL;
232 RpcPacket* packet;
234 TRACE("(%p)\n", conn);
236 for (;;) {
237 /* read packet header */
238 #ifdef OVERLAPPED_WORKS
239 if (!ReadFile(conn->conn, &hdr, sizeof(hdr), &dwRead, &conn->ovl)) {
240 DWORD err = GetLastError();
241 if (err != ERROR_IO_PENDING) {
242 TRACE("connection lost, error=%08lx\n", err);
243 break;
245 if (!GetOverlappedResult(conn->conn, &conn->ovl, &dwRead, TRUE)) break;
247 #else
248 if (!ReadFile(conn->conn, &hdr, sizeof(hdr), &dwRead, NULL)) {
249 TRACE("connection lost, error=%08lx\n", GetLastError());
250 break;
252 #endif
253 if (dwRead != sizeof(hdr)) {
254 if (dwRead) TRACE("protocol error: <hdrsz == %d, dwRead == %lu>\n", sizeof(hdr), dwRead);
255 break;
258 /* read packet body */
259 buf = HeapAlloc(GetProcessHeap(), 0, hdr.len);
260 TRACE("receiving payload=%d\n", hdr.len);
261 if (!hdr.len) dwRead = 0; else
262 #ifdef OVERLAPPED_WORKS
263 if (!ReadFile(conn->conn, buf, hdr.len, &dwRead, &conn->ovl)) {
264 DWORD err = GetLastError();
265 if (err != ERROR_IO_PENDING) {
266 TRACE("connection lost, error=%08lx\n", err);
267 break;
269 if (!GetOverlappedResult(conn->conn, &conn->ovl, &dwRead, TRUE)) break;
271 #else
272 if (!ReadFile(conn->conn, buf, hdr.len, &dwRead, NULL)) {
273 TRACE("connection lost, error=%08lx\n", GetLastError());
274 break;
276 #endif
277 if (dwRead != hdr.len) {
278 TRACE("protocol error: <bodylen == %d, dwRead == %lu>\n", hdr.len, dwRead);
279 break;
282 #if 0
283 RPCRT4_process_packet(conn, &hdr, buf);
284 #else
285 packet = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcPacket));
286 packet->conn = conn;
287 packet->hdr = hdr;
288 packet->buf = buf;
289 RPCRT4_create_worker_if_needed();
290 RPCRT4_push_packet(packet);
291 ReleaseSemaphore(server_sem, 1, NULL);
292 #endif
293 buf = NULL;
295 if (buf) HeapFree(GetProcessHeap(), 0, buf);
296 RPCRT4_DestroyConnection(conn);
297 return 0;
300 static void RPCRT4_new_client(RpcConnection* conn)
302 conn->thread = CreateThread(NULL, 0, RPCRT4_io_thread, conn, 0, NULL);
303 if (!conn->thread) {
304 DWORD err = GetLastError();
305 ERR("failed to create thread, error=%08lx\n", err);
309 static DWORD CALLBACK RPCRT4_server_thread(LPVOID the_arg)
311 HANDLE m_event = mgr_event, b_handle;
312 HANDLE *objs = NULL;
313 DWORD count, res;
314 RpcServerProtseq* cps;
315 RpcConnection* conn;
316 RpcConnection* cconn;
318 for (;;) {
319 EnterCriticalSection(&server_cs);
320 /* open and count connections */
321 count = 1;
322 cps = protseqs;
323 while (cps) {
324 conn = cps->conn;
325 while (conn) {
326 RPCRT4_OpenConnection(conn);
327 if (conn->ovl.hEvent) count++;
328 conn = conn->Next;
330 cps = cps->Next;
332 /* make array of connings */
333 objs = HeapReAlloc(GetProcessHeap(), 0, objs, count*sizeof(HANDLE));
334 objs[0] = m_event;
335 count = 1;
336 cps = protseqs;
337 while (cps) {
338 conn = cps->conn;
339 while (conn) {
340 if (conn->ovl.hEvent) objs[count++] = conn->ovl.hEvent;
341 conn = conn->Next;
343 cps = cps->Next;
345 LeaveCriticalSection(&server_cs);
347 /* start waiting */
348 res = WaitForMultipleObjects(count, objs, FALSE, INFINITE);
349 if (res == WAIT_OBJECT_0) {
350 ResetEvent(m_event);
351 if (!std_listen) break;
353 else if (res == WAIT_FAILED) {
354 ERR("wait failed\n");
356 else {
357 b_handle = objs[res - WAIT_OBJECT_0];
358 /* find which connection got a RPC */
359 EnterCriticalSection(&server_cs);
360 conn = NULL;
361 cps = protseqs;
362 while (cps) {
363 conn = cps->conn;
364 while (conn) {
365 if (conn->ovl.hEvent == b_handle) break;
366 conn = conn->Next;
368 if (conn) break;
369 cps = cps->Next;
371 cconn = NULL;
372 if (conn) RPCRT4_SpawnConnection(&cconn, conn);
373 LeaveCriticalSection(&server_cs);
374 if (!conn) {
375 ERR("failed to locate connection for handle %p\n", b_handle);
377 if (cconn) RPCRT4_new_client(cconn);
380 HeapFree(GetProcessHeap(), 0, objs);
381 EnterCriticalSection(&server_cs);
382 /* close connections */
383 cps = protseqs;
384 while (cps) {
385 conn = cps->conn;
386 while (conn) {
387 RPCRT4_CloseConnection(conn);
388 conn = conn->Next;
390 cps = cps->Next;
392 LeaveCriticalSection(&server_cs);
393 return 0;
396 static void RPCRT4_start_listen(void)
398 TRACE("\n");
400 EnterCriticalSection(&listen_cs);
401 if (! ++listen_count) {
402 if (!mgr_event) mgr_event = CreateEventA(NULL, TRUE, FALSE, NULL);
403 if (!server_sem) server_sem = CreateSemaphoreA(NULL, 0, MAX_THREADS, NULL);
404 std_listen = TRUE;
405 server_thread = CreateThread(NULL, 0, RPCRT4_server_thread, NULL, 0, NULL);
406 LeaveCriticalSection(&listen_cs);
407 } else {
408 LeaveCriticalSection(&listen_cs);
409 SetEvent(mgr_event);
413 static void RPCRT4_stop_listen(void)
415 EnterCriticalSection(&listen_cs);
416 if (listen_count == -1)
417 LeaveCriticalSection(&listen_cs);
418 else if (--listen_count == -1) {
419 std_listen = FALSE;
420 LeaveCriticalSection(&listen_cs);
421 SetEvent(mgr_event);
422 } else
423 LeaveCriticalSection(&listen_cs);
424 assert(listen_count > -2);
427 static RPC_STATUS RPCRT4_use_protseq(RpcServerProtseq* ps)
429 RPCRT4_CreateConnection(&ps->conn, TRUE, ps->Protseq, NULL, ps->Endpoint, NULL);
431 EnterCriticalSection(&server_cs);
432 ps->Next = protseqs;
433 protseqs = ps;
434 LeaveCriticalSection(&server_cs);
436 if (std_listen) SetEvent(mgr_event);
438 return RPC_S_OK;
441 /***********************************************************************
442 * RpcServerInqBindings (RPCRT4.@)
444 RPC_STATUS WINAPI RpcServerInqBindings( RPC_BINDING_VECTOR** BindingVector )
446 RPC_STATUS status;
447 DWORD count;
448 RpcServerProtseq* ps;
449 RpcConnection* conn;
451 if (BindingVector)
452 TRACE("(*BindingVector == ^%p)\n", *BindingVector);
453 else
454 ERR("(BindingVector == ^null!!?)\n");
456 EnterCriticalSection(&server_cs);
457 /* count connections */
458 count = 0;
459 ps = protseqs;
460 while (ps) {
461 conn = ps->conn;
462 while (conn) {
463 count++;
464 conn = conn->Next;
466 ps = ps->Next;
468 if (count) {
469 /* export bindings */
470 *BindingVector = HeapAlloc(GetProcessHeap(), 0,
471 sizeof(RPC_BINDING_VECTOR) +
472 sizeof(RPC_BINDING_HANDLE)*(count-1));
473 (*BindingVector)->Count = count;
474 count = 0;
475 ps = protseqs;
476 while (ps) {
477 conn = ps->conn;
478 while (conn) {
479 RPCRT4_MakeBinding((RpcBinding**)&(*BindingVector)->BindingH[count],
480 conn);
481 count++;
482 conn = conn->Next;
484 ps = ps->Next;
486 status = RPC_S_OK;
487 } else {
488 *BindingVector = NULL;
489 status = RPC_S_NO_BINDINGS;
491 LeaveCriticalSection(&server_cs);
492 return status;
495 /***********************************************************************
496 * RpcServerUseProtseqEpA (RPCRT4.@)
498 RPC_STATUS WINAPI RpcServerUseProtseqEpA( LPSTR Protseq, UINT MaxCalls, LPSTR Endpoint, LPVOID SecurityDescriptor )
500 RPC_POLICY policy;
502 TRACE( "(%s,%u,%s,%p)\n", Protseq, MaxCalls, Endpoint, SecurityDescriptor );
504 /* This should provide the default behaviour */
505 policy.Length = sizeof( policy );
506 policy.EndpointFlags = 0;
507 policy.NICFlags = 0;
509 return RpcServerUseProtseqEpExA( Protseq, MaxCalls, Endpoint, SecurityDescriptor, &policy );
512 /***********************************************************************
513 * RpcServerUseProtseqEpW (RPCRT4.@)
515 RPC_STATUS WINAPI RpcServerUseProtseqEpW( LPWSTR Protseq, UINT MaxCalls, LPWSTR Endpoint, LPVOID SecurityDescriptor )
517 RPC_POLICY policy;
519 TRACE( "(%s,%u,%s,%p)\n", debugstr_w( Protseq ), MaxCalls, debugstr_w( Endpoint ), SecurityDescriptor );
521 /* This should provide the default behaviour */
522 policy.Length = sizeof( policy );
523 policy.EndpointFlags = 0;
524 policy.NICFlags = 0;
526 return RpcServerUseProtseqEpExW( Protseq, MaxCalls, Endpoint, SecurityDescriptor, &policy );
529 /***********************************************************************
530 * RpcServerUseProtseqEpExA (RPCRT4.@)
532 RPC_STATUS WINAPI RpcServerUseProtseqEpExA( LPSTR Protseq, UINT MaxCalls, LPSTR Endpoint, LPVOID SecurityDescriptor,
533 PRPC_POLICY lpPolicy )
535 RpcServerProtseq* ps;
537 TRACE("(%s,%u,%s,%p,{%u,%lu,%lu})\n", debugstr_a( Protseq ), MaxCalls,
538 debugstr_a( Endpoint ), SecurityDescriptor,
539 lpPolicy->Length, lpPolicy->EndpointFlags, lpPolicy->NICFlags );
541 ps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcServerProtseq));
542 ps->MaxCalls = MaxCalls;
543 ps->Protseq = RPCRT4_strdupA(Protseq);
544 ps->Endpoint = RPCRT4_strdupA(Endpoint);
546 return RPCRT4_use_protseq(ps);
549 /***********************************************************************
550 * RpcServerUseProtseqEpExW (RPCRT4.@)
552 RPC_STATUS WINAPI RpcServerUseProtseqEpExW( LPWSTR Protseq, UINT MaxCalls, LPWSTR Endpoint, LPVOID SecurityDescriptor,
553 PRPC_POLICY lpPolicy )
555 RpcServerProtseq* ps;
557 TRACE("(%s,%u,%s,%p,{%u,%lu,%lu})\n", debugstr_w( Protseq ), MaxCalls,
558 debugstr_w( Endpoint ), SecurityDescriptor,
559 lpPolicy->Length, lpPolicy->EndpointFlags, lpPolicy->NICFlags );
561 ps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcServerProtseq));
562 ps->MaxCalls = MaxCalls;
563 /* FIXME: Did Ove have these next two as RPCRT4_strdupW for a reason? */
564 ps->Protseq = RPCRT4_strdupWtoA(Protseq);
565 ps->Endpoint = RPCRT4_strdupWtoA(Endpoint);
567 return RPCRT4_use_protseq(ps);
570 /***********************************************************************
571 * RpcServerUseProtseqA (RPCRT4.@)
573 RPC_STATUS WINAPI RpcServerUseProtseqA(LPSTR Protseq, unsigned int MaxCalls, void *SecurityDescriptor)
575 TRACE("(Protseq == %s, MaxCalls == %d, SecurityDescriptor == ^%p)", debugstr_a(Protseq), MaxCalls, SecurityDescriptor);
576 return RpcServerUseProtseqEpA(Protseq, MaxCalls, NULL, SecurityDescriptor);
579 /***********************************************************************
580 * RpcServerUseProtseqW (RPCRT4.@)
582 RPC_STATUS WINAPI RpcServerUseProtseqW(LPWSTR Protseq, unsigned int MaxCalls, void *SecurityDescriptor)
584 TRACE("Protseq == %s, MaxCalls == %d, SecurityDescriptor == ^%p)", debugstr_w(Protseq), MaxCalls, SecurityDescriptor);
585 return RpcServerUseProtseqEpW(Protseq, MaxCalls, NULL, SecurityDescriptor);
588 /***********************************************************************
589 * RpcServerRegisterIf (RPCRT4.@)
591 RPC_STATUS WINAPI RpcServerRegisterIf( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, RPC_MGR_EPV* MgrEpv )
593 TRACE("(%p,%s,%p)\n", IfSpec, debugstr_guid(MgrTypeUuid), MgrEpv);
594 return RpcServerRegisterIf2( IfSpec, MgrTypeUuid, MgrEpv, 0, RPC_C_LISTEN_MAX_CALLS_DEFAULT, (UINT)-1, NULL );
597 /***********************************************************************
598 * RpcServerRegisterIfEx (RPCRT4.@)
600 RPC_STATUS WINAPI RpcServerRegisterIfEx( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, RPC_MGR_EPV* MgrEpv,
601 UINT Flags, UINT MaxCalls, RPC_IF_CALLBACK_FN* IfCallbackFn )
603 TRACE("(%p,%s,%p,%u,%u,%p)\n", IfSpec, debugstr_guid(MgrTypeUuid), MgrEpv, Flags, MaxCalls, IfCallbackFn);
604 return RpcServerRegisterIf2( IfSpec, MgrTypeUuid, MgrEpv, Flags, MaxCalls, (UINT)-1, IfCallbackFn );
607 /***********************************************************************
608 * RpcServerRegisterIf2 (RPCRT4.@)
610 RPC_STATUS WINAPI RpcServerRegisterIf2( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, RPC_MGR_EPV* MgrEpv,
611 UINT Flags, UINT MaxCalls, UINT MaxRpcSize, RPC_IF_CALLBACK_FN* IfCallbackFn )
613 PRPC_SERVER_INTERFACE If = (PRPC_SERVER_INTERFACE)IfSpec;
614 RpcServerInterface* sif;
615 int i;
617 TRACE("(%p,%s,%p,%u,%u,%u,%p)\n", IfSpec, debugstr_guid(MgrTypeUuid), MgrEpv, Flags, MaxCalls,
618 MaxRpcSize, IfCallbackFn);
619 TRACE(" interface id: %s %d.%d\n", debugstr_guid(&If->InterfaceId.SyntaxGUID),
620 If->InterfaceId.SyntaxVersion.MajorVersion,
621 If->InterfaceId.SyntaxVersion.MinorVersion);
622 TRACE(" transfer syntax: %s %d.%d\n", debugstr_guid(&If->TransferSyntax.SyntaxGUID),
623 If->TransferSyntax.SyntaxVersion.MajorVersion,
624 If->TransferSyntax.SyntaxVersion.MinorVersion);
625 TRACE(" dispatch table: %p\n", If->DispatchTable);
626 if (If->DispatchTable) {
627 TRACE(" dispatch table count: %d\n", If->DispatchTable->DispatchTableCount);
628 for (i=0; i<If->DispatchTable->DispatchTableCount; i++) {
629 TRACE(" entry %d: %p\n", i, If->DispatchTable->DispatchTable[i]);
631 TRACE(" reserved: %ld\n", If->DispatchTable->Reserved);
633 TRACE(" protseq endpoint count: %d\n", If->RpcProtseqEndpointCount);
634 TRACE(" default manager epv: %p\n", If->DefaultManagerEpv);
635 TRACE(" interpreter info: %p\n", If->InterpreterInfo);
636 TRACE(" flags: %08x\n", If->Flags);
638 sif = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcServerInterface));
639 sif->If = If;
640 if (MgrTypeUuid)
641 memcpy(&sif->MgrTypeUuid, MgrTypeUuid, sizeof(UUID));
642 else
643 memset(&sif->MgrTypeUuid, 0, sizeof(UUID));
644 sif->MgrEpv = MgrEpv;
645 sif->Flags = Flags;
646 sif->MaxCalls = MaxCalls;
647 sif->MaxRpcSize = MaxRpcSize;
648 sif->IfCallbackFn = IfCallbackFn;
650 EnterCriticalSection(&server_cs);
651 sif->Next = ifs;
652 ifs = sif;
653 LeaveCriticalSection(&server_cs);
655 if (sif->Flags & RPC_IF_AUTOLISTEN) {
656 /* well, start listening, I think... */
657 RPCRT4_start_listen();
660 return RPC_S_OK;
663 /***********************************************************************
664 * RpcServerUnregisterIf (RPCRT4.@)
666 RPC_STATUS WINAPI RpcServerUnregisterIf( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, UINT WaitForCallsToComplete )
668 FIXME("(IfSpec == (RPC_IF_HANDLE)^%p, MgrTypeUuid == %s, WaitForCallsToComplete == %u): stub\n",
669 IfSpec, debugstr_guid(MgrTypeUuid), WaitForCallsToComplete);
671 return RPC_S_OK;
674 /***********************************************************************
675 * RpcServerUnregisterIfEx (RPCRT4.@)
677 RPC_STATUS WINAPI RpcServerUnregisterIfEx( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, int RundownContextHandles )
679 FIXME("(IfSpec == (RPC_IF_HANDLE)^%p, MgrTypeUuid == %s, RundownContextHandles == %d): stub\n",
680 IfSpec, debugstr_guid(MgrTypeUuid), RundownContextHandles);
682 return RPC_S_OK;
685 /***********************************************************************
686 * RpcServerRegisterAuthInfoA (RPCRT4.@)
688 RPC_STATUS WINAPI RpcServerRegisterAuthInfoA( LPSTR ServerPrincName, ULONG AuthnSvc, RPC_AUTH_KEY_RETRIEVAL_FN GetKeyFn,
689 LPVOID Arg )
691 FIXME( "(%s,%lu,%p,%p): stub\n", ServerPrincName, AuthnSvc, GetKeyFn, Arg );
693 return RPC_S_UNKNOWN_AUTHN_SERVICE; /* We don't know any authentication services */
696 /***********************************************************************
697 * RpcServerRegisterAuthInfoW (RPCRT4.@)
699 RPC_STATUS WINAPI RpcServerRegisterAuthInfoW( LPWSTR ServerPrincName, ULONG AuthnSvc, RPC_AUTH_KEY_RETRIEVAL_FN GetKeyFn,
700 LPVOID Arg )
702 FIXME( "(%s,%lu,%p,%p): stub\n", debugstr_w( ServerPrincName ), AuthnSvc, GetKeyFn, Arg );
704 return RPC_S_UNKNOWN_AUTHN_SERVICE; /* We don't know any authentication services */
707 /***********************************************************************
708 * RpcServerListen (RPCRT4.@)
710 RPC_STATUS WINAPI RpcServerListen( UINT MinimumCallThreads, UINT MaxCalls, UINT DontWait )
712 TRACE("(%u,%u,%u)\n", MinimumCallThreads, MaxCalls, DontWait);
714 if (!protseqs)
715 return RPC_S_NO_PROTSEQS_REGISTERED;
717 EnterCriticalSection(&listen_cs);
719 if (std_listen) {
720 LeaveCriticalSection(&listen_cs);
721 return RPC_S_ALREADY_LISTENING;
724 RPCRT4_start_listen();
726 LeaveCriticalSection(&listen_cs);
728 if (DontWait) return RPC_S_OK;
730 return RpcMgmtWaitServerListen();
733 /***********************************************************************
734 * RpcMgmtServerWaitListen (RPCRT4.@)
736 RPC_STATUS WINAPI RpcMgmtWaitServerListen( void )
738 RPC_STATUS rslt = RPC_S_OK;
740 TRACE("\n");
742 EnterCriticalSection(&listen_cs);
744 if (!std_listen)
745 if ( (rslt = RpcServerListen(1, 0, TRUE)) != RPC_S_OK ) {
746 LeaveCriticalSection(&listen_cs);
747 return rslt;
750 LeaveCriticalSection(&listen_cs);
752 while (std_listen) {
753 WaitForSingleObject(mgr_event, INFINITE);
754 if (!std_listen) {
755 Sleep(100); /* don't spin violently */
756 TRACE("spinning.\n");
760 return rslt;
763 /***********************************************************************
764 * RpcMgmtStopServerListening (RPCRT4.@)
766 RPC_STATUS WINAPI RpcMgmtStopServerListening ( RPC_BINDING_HANDLE Binding )
768 TRACE("(Binding == (RPC_BINDING_HANDLE)^%p)\n", Binding);
770 if (Binding) {
771 FIXME("client-side invocation not implemented.\n");
772 return RPC_S_WRONG_KIND_OF_BINDING;
775 /* hmm... */
776 EnterCriticalSection(&listen_cs);
777 while (std_listen)
778 RPCRT4_stop_listen();
779 LeaveCriticalSection(&listen_cs);
781 return RPC_S_OK;
784 /***********************************************************************
785 * I_RpcServerStartListening (RPCRT4.@)
787 RPC_STATUS WINAPI I_RpcServerStartListening( void* hWnd )
789 FIXME( "(%p): stub\n", hWnd );
791 return RPC_S_OK;
794 /***********************************************************************
795 * I_RpcServerStopListening (RPCRT4.@)
797 RPC_STATUS WINAPI I_RpcServerStopListening( void )
799 FIXME( "(): stub\n" );
801 return RPC_S_OK;
804 /***********************************************************************
805 * I_RpcWindowProc (RPCRT4.@)
807 UINT WINAPI I_RpcWindowProc( void *hWnd, UINT Message, UINT wParam, ULONG lParam )
809 FIXME( "(%p,%08x,%08x,%08lx): stub\n", hWnd, Message, wParam, lParam );
811 return 0;