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
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.