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 <stdarg.h> 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 32 #include "rpc.h" 33 #include "rpcndr.h" 34 #include "excpt.h" 35 36 #include "wine/debug.h" 37 #include "wine/exception.h" 38 39 #include "rpc_server.h" 40 #include "rpc_assoc.h" 41 #include "rpc_message.h" 42 #include "rpc_defs.h" 43 #include "ncastatus.h" 44 #include "secext.h" 45 46 WINE_DEFAULT_DEBUG_CHANNEL(rpc); 47 48 typedef struct _RpcPacket 49 { 50 struct _RpcConnection* conn; 51 RpcPktHdr* hdr; 52 RPC_MESSAGE* msg; 53 unsigned char *auth_data; 54 ULONG auth_length; 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 static struct list server_registered_auth_info = LIST_INIT(server_registered_auth_info); 71 72 static CRITICAL_SECTION server_cs; 73 static CRITICAL_SECTION_DEBUG server_cs_debug = 74 { 75 0, 0, &server_cs, 76 { &server_cs_debug.ProcessLocksList, &server_cs_debug.ProcessLocksList }, 77 0, 0, { (DWORD_PTR)(__FILE__ ": server_cs") } 78 }; 79 static CRITICAL_SECTION server_cs = { &server_cs_debug, -1, 0, 0, 0, 0 }; 80 81 static CRITICAL_SECTION listen_cs; 82 static CRITICAL_SECTION_DEBUG listen_cs_debug = 83 { 84 0, 0, &listen_cs, 85 { &listen_cs_debug.ProcessLocksList, &listen_cs_debug.ProcessLocksList }, 86 0, 0, { (DWORD_PTR)(__FILE__ ": listen_cs") } 87 }; 88 static CRITICAL_SECTION listen_cs = { &listen_cs_debug, -1, 0, 0, 0, 0 }; 89 90 static CRITICAL_SECTION server_auth_info_cs; 91 static CRITICAL_SECTION_DEBUG server_auth_info_cs_debug = 92 { 93 0, 0, &server_auth_info_cs, 94 { &server_auth_info_cs_debug.ProcessLocksList, &server_auth_info_cs_debug.ProcessLocksList }, 95 0, 0, { (DWORD_PTR)(__FILE__ ": server_auth_info_cs") } 96 }; 97 static CRITICAL_SECTION server_auth_info_cs = { &server_auth_info_cs_debug, -1, 0, 0, 0, 0 }; 98 99 /* whether the server is currently listening */ 100 static BOOL std_listen; 101 /* total listeners including auto listeners */ 102 static LONG listen_count; 103 /* event set once all manual listening is finished */ 104 static HANDLE listen_done_event; 105 106 static UUID uuid_nil; 107 108 static inline RpcObjTypeMap *LookupObjTypeMap(UUID *ObjUuid) 109 { 110 RpcObjTypeMap *rslt = RpcObjTypeMaps; 111 RPC_STATUS dummy; 112 113 while (rslt) { 114 if (! UuidCompare(ObjUuid, &rslt->Object, &dummy)) break; 115 rslt = rslt->next; 116 } 117 118 return rslt; 119 } 120 121 static inline UUID *LookupObjType(UUID *ObjUuid) 122 { 123 RpcObjTypeMap *map = LookupObjTypeMap(ObjUuid); 124 if (map) 125 return &map->Type; 126 else 127 return &uuid_nil; 128 } 129 130 static RpcServerInterface* RPCRT4_find_interface(UUID* object, 131 const RPC_SYNTAX_IDENTIFIER *if_id, 132 const RPC_SYNTAX_IDENTIFIER *transfer_syntax, 133 BOOL check_object) 134 { 135 UUID* MgrType = NULL; 136 RpcServerInterface* cif; 137 RPC_STATUS status; 138 139 if (check_object) 140 MgrType = LookupObjType(object); 141 EnterCriticalSection(&server_cs); 142 LIST_FOR_EACH_ENTRY(cif, &server_interfaces, RpcServerInterface, entry) { 143 if (!memcmp(if_id, &cif->If->InterfaceId, sizeof(RPC_SYNTAX_IDENTIFIER)) && 144 (!transfer_syntax || !memcmp(transfer_syntax, &cif->If->TransferSyntax, sizeof(RPC_SYNTAX_IDENTIFIER))) && 145 (check_object == FALSE || UuidEqual(MgrType, &cif->MgrTypeUuid, &status)) && 146 std_listen) { 147 InterlockedIncrement(&cif->CurrentCalls); 148 break; 149 } 150 } 151 LeaveCriticalSection(&server_cs); 152 if (&cif->entry == &server_interfaces) cif = NULL; 153 TRACE("returning %p for object %s, if_id { %d.%d %s }\n", cif, 154 debugstr_guid(object), if_id->SyntaxVersion.MajorVersion, 155 if_id->SyntaxVersion.MinorVersion, debugstr_guid(&if_id->SyntaxGUID)); 156 return cif; 157 } 158 159 static void RPCRT4_release_server_interface(RpcServerInterface *sif) 160 { 161 if (!InterlockedDecrement(&sif->CurrentCalls) && 162 sif->Delete) { 163 /* sif must have been removed from server_interfaces before 164 * CallsCompletedEvent is set */ 165 if (sif->CallsCompletedEvent) 166 SetEvent(sif->CallsCompletedEvent); 167 HeapFree(GetProcessHeap(), 0, sif); 168 } 169 } 170 171 static RpcPktHdr *handle_bind_error(RpcConnection *conn, RPC_STATUS error) 172 { 173 unsigned int reject_reason; 174 switch (error) 175 { 176 case RPC_S_SERVER_TOO_BUSY: 177 reject_reason = REJECT_TEMPORARY_CONGESTION; 178 break; 179 case ERROR_OUTOFMEMORY: 180 case RPC_S_OUT_OF_RESOURCES: 181 reject_reason = REJECT_LOCAL_LIMIT_EXCEEDED; 182 break; 183 case RPC_S_PROTOCOL_ERROR: 184 reject_reason = REJECT_PROTOCOL_VERSION_NOT_SUPPORTED; 185 break; 186 case RPC_S_UNKNOWN_AUTHN_SERVICE: 187 reject_reason = REJECT_UNKNOWN_AUTHN_SERVICE; 188 break; 189 case ERROR_ACCESS_DENIED: 190 reject_reason = REJECT_INVALID_CHECKSUM; 191 break; 192 default: 193 FIXME("unexpected status value %d\n", error); 194 /* fall through */ 195 case RPC_S_INVALID_BOUND: 196 reject_reason = REJECT_REASON_NOT_SPECIFIED; 197 break; 198 } 199 return RPCRT4_BuildBindNackHeader(NDR_LOCAL_DATA_REPRESENTATION, 200 RPC_VER_MAJOR, RPC_VER_MINOR, 201 reject_reason); 202 } 203 204 static RPC_STATUS process_bind_packet_no_send( 205 RpcConnection *conn, RpcPktBindHdr *hdr, RPC_MESSAGE *msg, 206 unsigned char *auth_data, ULONG auth_length, RpcPktHdr **ack_response, 207 unsigned char **auth_data_out, ULONG *auth_length_out) 208 { 209 RPC_STATUS status; 210 RpcContextElement *ctxt_elem; 211 unsigned int i; 212 RpcResult *results; 213 214 /* validate data */ 215 for (i = 0, ctxt_elem = msg->Buffer; 216 i < hdr->num_elements; 217 i++, ctxt_elem = (RpcContextElement *)&ctxt_elem->transfer_syntaxes[ctxt_elem->num_syntaxes]) 218 { 219 if (((char *)ctxt_elem - (char *)msg->Buffer) > msg->BufferLength || 220 ((char *)&ctxt_elem->transfer_syntaxes[ctxt_elem->num_syntaxes] - (char *)msg->Buffer) > msg->BufferLength) 221 { 222 ERR("inconsistent data in packet - packet length %d, num elements %d\n", 223 msg->BufferLength, hdr->num_elements); 224 return RPC_S_INVALID_BOUND; 225 } 226 } 227 228 if (hdr->max_tsize < RPC_MIN_PACKET_SIZE || 229 !UuidIsNil(&conn->ActiveInterface.SyntaxGUID, &status) || 230 conn->server_binding) 231 { 232 TRACE("packet size less than min size, or active interface syntax guid non-null\n"); 233 234 return RPC_S_INVALID_BOUND; 235 } 236 237 results = HeapAlloc(GetProcessHeap(), 0, 238 hdr->num_elements * sizeof(*results)); 239 if (!results) 240 return RPC_S_OUT_OF_RESOURCES; 241 242 for (i = 0, ctxt_elem = (RpcContextElement *)msg->Buffer; 243 i < hdr->num_elements; 244 i++, ctxt_elem = (RpcContextElement *)&ctxt_elem->transfer_syntaxes[ctxt_elem->num_syntaxes]) 245 { 246 RpcServerInterface* sif = NULL; 247 unsigned int j; 248 249 for (j = 0; !sif && j < ctxt_elem->num_syntaxes; j++) 250 { 251 sif = RPCRT4_find_interface(NULL, &ctxt_elem->abstract_syntax, 252 &ctxt_elem->transfer_syntaxes[j], FALSE); 253 if (sif) 254 break; 255 } 256 if (sif) 257 { 258 RPCRT4_release_server_interface(sif); 259 TRACE("accepting bind request on connection %p for %s\n", conn, 260 debugstr_guid(&ctxt_elem->abstract_syntax.SyntaxGUID)); 261 results[i].result = RESULT_ACCEPT; 262 results[i].reason = REASON_NONE; 263 results[i].transfer_syntax = ctxt_elem->transfer_syntaxes[j]; 264 265 /* save the interface for later use */ 266 /* FIXME: save linked list */ 267 conn->ActiveInterface = ctxt_elem->abstract_syntax; 268 } 269 else if ((sif = RPCRT4_find_interface(NULL, &ctxt_elem->abstract_syntax, 270 NULL, FALSE)) != NULL) 271 { 272 RPCRT4_release_server_interface(sif); 273 TRACE("not accepting bind request on connection %p for %s - no transfer syntaxes supported\n", 274 conn, debugstr_guid(&ctxt_elem->abstract_syntax.SyntaxGUID)); 275 results[i].result = RESULT_PROVIDER_REJECTION; 276 results[i].reason = REASON_TRANSFER_SYNTAXES_NOT_SUPPORTED; 277 memset(&results[i].transfer_syntax, 0, sizeof(results[i].transfer_syntax)); 278 } 279 else 280 { 281 TRACE("not accepting bind request on connection %p for %s - abstract syntax not supported\n", 282 conn, debugstr_guid(&ctxt_elem->abstract_syntax.SyntaxGUID)); 283 results[i].result = RESULT_PROVIDER_REJECTION; 284 results[i].reason = REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED; 285 memset(&results[i].transfer_syntax, 0, sizeof(results[i].transfer_syntax)); 286 } 287 } 288 289 /* create temporary binding */ 290 status = RPCRT4_MakeBinding(&conn->server_binding, conn); 291 if (status != RPC_S_OK) 292 { 293 HeapFree(GetProcessHeap(), 0, results); 294 return status; 295 } 296 297 status = RpcServerAssoc_GetAssociation(rpcrt4_conn_get_name(conn), 298 conn->NetworkAddr, conn->Endpoint, 299 conn->NetworkOptions, 300 hdr->assoc_gid, 301 &conn->server_binding->Assoc); 302 if (status != RPC_S_OK) 303 { 304 HeapFree(GetProcessHeap(), 0, results); 305 return status; 306 } 307 308 if (auth_length) 309 { 310 status = RPCRT4_ServerConnectionAuth(conn, TRUE, 311 (RpcAuthVerifier *)auth_data, 312 auth_length, auth_data_out, 313 auth_length_out); 314 if (status != RPC_S_OK) 315 { 316 HeapFree(GetProcessHeap(), 0, results); 317 return status; 318 } 319 } 320 321 *ack_response = RPCRT4_BuildBindAckHeader(NDR_LOCAL_DATA_REPRESENTATION, 322 RPC_MAX_PACKET_SIZE, 323 RPC_MAX_PACKET_SIZE, 324 conn->server_binding->Assoc->assoc_group_id, 325 conn->Endpoint, hdr->num_elements, 326 results); 327 HeapFree(GetProcessHeap(), 0, results); 328 329 if (*ack_response) 330 conn->MaxTransmissionSize = hdr->max_tsize; 331 else 332 status = RPC_S_OUT_OF_RESOURCES; 333 334 return status; 335 } 336 337 static RPC_STATUS process_bind_packet(RpcConnection *conn, RpcPktBindHdr *hdr, 338 RPC_MESSAGE *msg, 339 unsigned char *auth_data, 340 ULONG auth_length) 341 { 342 RPC_STATUS status; 343 RpcPktHdr *response = NULL; 344 unsigned char *auth_data_out = NULL; 345 ULONG auth_length_out = 0; 346 347 status = process_bind_packet_no_send(conn, hdr, msg, auth_data, auth_length, 348 &response, &auth_data_out, 349 &auth_length_out); 350 if (status != RPC_S_OK) 351 response = handle_bind_error(conn, status); 352 if (response) 353 status = RPCRT4_SendWithAuth(conn, response, NULL, 0, auth_data_out, auth_length_out); 354 else 355 status = ERROR_OUTOFMEMORY; 356 RPCRT4_FreeHeader(response); 357 358 return status; 359 } 360 361 362 static RPC_STATUS process_request_packet(RpcConnection *conn, RpcPktRequestHdr *hdr, RPC_MESSAGE *msg) 363 { 364 RPC_STATUS status; 365 RpcPktHdr *response = NULL; 366 RpcServerInterface* sif; 367 RPC_DISPATCH_FUNCTION func; 368 BOOL exception; 369 UUID *object_uuid; 370 NDR_SCONTEXT context_handle; 371 void *buf = msg->Buffer; 372 373 /* fail if the connection isn't bound with an interface */ 374 if (UuidIsNil(&conn->ActiveInterface.SyntaxGUID, &status)) { 375 /* FIXME: should send BindNack instead */ 376 response = RPCRT4_BuildFaultHeader(NDR_LOCAL_DATA_REPRESENTATION, 377 status); 378 379 RPCRT4_Send(conn, response, NULL, 0); 380 RPCRT4_FreeHeader(response); 381 return RPC_S_OK; 382 } 383 384 if (hdr->common.flags & RPC_FLG_OBJECT_UUID) { 385 object_uuid = (UUID*)(hdr + 1); 386 } else { 387 object_uuid = NULL; 388 } 389 390 sif = RPCRT4_find_interface(object_uuid, &conn->ActiveInterface, NULL, TRUE); 391 if (!sif) { 392 WARN("interface %s no longer registered, returning fault packet\n", debugstr_guid(&conn->ActiveInterface.SyntaxGUID)); 393 response = RPCRT4_BuildFaultHeader(NDR_LOCAL_DATA_REPRESENTATION, 394 NCA_S_UNK_IF); 395 396 RPCRT4_Send(conn, response, NULL, 0); 397 RPCRT4_FreeHeader(response); 398 return RPC_S_OK; 399 } 400 msg->RpcInterfaceInformation = sif->If; 401 /* copy the endpoint vector from sif to msg so that midl-generated code will use it */ 402 msg->ManagerEpv = sif->MgrEpv; 403 if (object_uuid != NULL) { 404 RPCRT4_SetBindingObject(msg->Handle, object_uuid); 405 } 406 407 /* find dispatch function */ 408 msg->ProcNum = hdr->opnum; 409 if (sif->Flags & RPC_IF_OLE) { 410 /* native ole32 always gives us a dispatch table with a single entry 411 * (I assume that's a wrapper for IRpcStubBuffer::Invoke) */ 412 func = *sif->If->DispatchTable->DispatchTable; 413 } else { 414 if (msg->ProcNum >= sif->If->DispatchTable->DispatchTableCount) { 415 WARN("invalid procnum (%d/%d)\n", msg->ProcNum, sif->If->DispatchTable->DispatchTableCount); 416 response = RPCRT4_BuildFaultHeader(NDR_LOCAL_DATA_REPRESENTATION, 417 NCA_S_OP_RNG_ERROR); 418 419 RPCRT4_Send(conn, response, NULL, 0); 420 RPCRT4_FreeHeader(response); 421 } 422 func = sif->If->DispatchTable->DispatchTable[msg->ProcNum]; 423 } 424 425 /* put in the drep. FIXME: is this more universally applicable? 426 perhaps we should move this outward... */ 427 msg->DataRepresentation = 428 MAKELONG( MAKEWORD(hdr->common.drep[0], hdr->common.drep[1]), 429 MAKEWORD(hdr->common.drep[2], hdr->common.drep[3])); 430 431 exception = FALSE; 432 433 /* dispatch */ 434 RPCRT4_SetThreadCurrentCallHandle(msg->Handle); 435 __TRY { 436 if (func) func(msg); 437 } __EXCEPT_ALL { 438 WARN("exception caught with code 0x%08x = %d\n", GetExceptionCode(), GetExceptionCode()); 439 exception = TRUE; 440 if (GetExceptionCode() == STATUS_ACCESS_VIOLATION) 441 status = ERROR_NOACCESS; 442 else 443 status = GetExceptionCode(); 444 response = RPCRT4_BuildFaultHeader(msg->DataRepresentation, 445 RPC2NCA_STATUS(status)); 446 } __ENDTRY 447 RPCRT4_SetThreadCurrentCallHandle(NULL); 448 449 /* release any unmarshalled context handles */ 450 while ((context_handle = RPCRT4_PopThreadContextHandle()) != NULL) 451 RpcServerAssoc_ReleaseContextHandle(conn->server_binding->Assoc, context_handle, TRUE); 452 453 if (!exception) 454 response = RPCRT4_BuildResponseHeader(msg->DataRepresentation, 455 msg->BufferLength); 456 457 /* send response packet */ 458 if (response) { 459 status = RPCRT4_Send(conn, response, exception ? NULL : msg->Buffer, 460 exception ? 0 : msg->BufferLength); 461 RPCRT4_FreeHeader(response); 462 } else 463 ERR("out of memory\n"); 464 465 msg->RpcInterfaceInformation = NULL; 466 RPCRT4_release_server_interface(sif); 467 468 if (msg->Buffer == buf) buf = NULL; 469 TRACE("freeing Buffer=%p\n", buf); 470 I_RpcFree(buf); 471 472 return status; 473 } 474 475 static RPC_STATUS process_auth3_packet(RpcConnection *conn, 476 RpcPktCommonHdr *hdr, 477 RPC_MESSAGE *msg, 478 unsigned char *auth_data, 479 ULONG auth_length) 480 { 481 RPC_STATUS status; 482 483 if (UuidIsNil(&conn->ActiveInterface.SyntaxGUID, &status) || 484 !auth_length || msg->BufferLength != 0) 485 status = RPC_S_PROTOCOL_ERROR; 486 else 487 { 488 status = RPCRT4_ServerConnectionAuth(conn, FALSE, 489 (RpcAuthVerifier *)auth_data, 490 auth_length, NULL, NULL); 491 } 492 493 /* FIXME: client doesn't expect a response to this message so must store 494 * status in connection so that fault packet can be returned when next 495 * packet is received */ 496 497 return RPC_S_OK; 498 } 499 500 static void RPCRT4_process_packet(RpcConnection* conn, RpcPktHdr* hdr, 501 RPC_MESSAGE* msg, unsigned char *auth_data, 502 ULONG auth_length) 503 { 504 msg->Handle = (RPC_BINDING_HANDLE)conn->server_binding; 505 506 switch (hdr->common.ptype) { 507 case PKT_BIND: 508 TRACE("got bind packet\n"); 509 process_bind_packet(conn, &hdr->bind, msg, auth_data, auth_length); 510 break; 511 512 case PKT_REQUEST: 513 TRACE("got request packet\n"); 514 process_request_packet(conn, &hdr->request, msg); 515 break; 516 517 case PKT_AUTH3: 518 TRACE("got auth3 packet\n"); 519 process_auth3_packet(conn, &hdr->common, msg, auth_data, auth_length); 520 break; 521 default: 522 FIXME("unhandled packet type %u\n", hdr->common.ptype); 523 break; 524 } 525 526 /* clean up */ 527 I_RpcFree(msg->Buffer); 528 RPCRT4_FreeHeader(hdr); 529 HeapFree(GetProcessHeap(), 0, msg); 530 HeapFree(GetProcessHeap(), 0, auth_data); 531 } 532 533 static DWORD CALLBACK RPCRT4_worker_thread(LPVOID the_arg) 534 { 535 RpcPacket *pkt = the_arg; 536 RPCRT4_process_packet(pkt->conn, pkt->hdr, pkt->msg, pkt->auth_data, 537 pkt->auth_length); 538 RPCRT4_ReleaseConnection(pkt->conn); 539 HeapFree(GetProcessHeap(), 0, pkt); 540 return 0; 541 } 542 543 static DWORD CALLBACK RPCRT4_io_thread(LPVOID the_arg) 544 { 545 RpcConnection* conn = the_arg; 546 RpcPktHdr *hdr; 547 RPC_MESSAGE *msg; 548 RPC_STATUS status; 549 RpcPacket *packet; 550 unsigned char *auth_data; 551 ULONG auth_length; 552 553 TRACE("(%p)\n", conn); 554 555 for (;;) { 556 msg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RPC_MESSAGE)); 557 if (!msg) break; 558 559 status = RPCRT4_ReceiveWithAuth(conn, &hdr, msg, &auth_data, &auth_length); 560 if (status != RPC_S_OK) { 561 WARN("receive failed with error %x\n", status); 562 HeapFree(GetProcessHeap(), 0, msg); 563 break; 564 } 565 566 switch (hdr->common.ptype) { 567 case PKT_BIND: 568 TRACE("got bind packet\n"); 569 570 status = process_bind_packet(conn, &hdr->bind, msg, auth_data, 571 auth_length); 572 break; 573 574 case PKT_REQUEST: 575 TRACE("got request packet\n"); 576 577 packet = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcPacket)); 578 if (!packet) { 579 I_RpcFree(msg->Buffer); 580 RPCRT4_FreeHeader(hdr); 581 HeapFree(GetProcessHeap(), 0, msg); 582 HeapFree(GetProcessHeap(), 0, auth_data); 583 goto exit; 584 } 585 packet->conn = RPCRT4_GrabConnection( conn ); 586 packet->hdr = hdr; 587 packet->msg = msg; 588 packet->auth_data = auth_data; 589 packet->auth_length = auth_length; 590 if (!QueueUserWorkItem(RPCRT4_worker_thread, packet, WT_EXECUTELONGFUNCTION)) { 591 ERR("couldn't queue work item for worker thread, error was %d\n", GetLastError()); 592 HeapFree(GetProcessHeap(), 0, packet); 593 status = RPC_S_OUT_OF_RESOURCES; 594 } else { 595 continue; 596 } 597 break; 598 599 case PKT_AUTH3: 600 TRACE("got auth3 packet\n"); 601 602 status = process_auth3_packet(conn, &hdr->common, msg, auth_data, 603 auth_length); 604 break; 605 default: 606 FIXME("unhandled packet type %u\n", hdr->common.ptype); 607 break; 608 } 609 610 I_RpcFree(msg->Buffer); 611 RPCRT4_FreeHeader(hdr); 612 HeapFree(GetProcessHeap(), 0, msg); 613 HeapFree(GetProcessHeap(), 0, auth_data); 614 615 if (status != RPC_S_OK) { 616 WARN("processing packet failed with error %u\n", status); 617 break; 618 } 619 } 620 exit: 621 RPCRT4_ReleaseConnection(conn); 622 return 0; 623 } 624 625 void RPCRT4_new_client(RpcConnection* conn) 626 { 627 HANDLE thread = CreateThread(NULL, 0, RPCRT4_io_thread, conn, 0, NULL); 628 if (!thread) { 629 DWORD err = GetLastError(); 630 ERR("failed to create thread, error=%08x\n", err); 631 RPCRT4_ReleaseConnection(conn); 632 } 633 /* we could set conn->thread, but then we'd have to make the io_thread wait 634 * for that, otherwise the thread might finish, destroy the connection, and 635 * free the memory we'd write to before we did, causing crashes and stuff - 636 * so let's implement that later, when we really need conn->thread */ 637 638 CloseHandle( thread ); 639 } 640 641 static DWORD CALLBACK RPCRT4_server_thread(LPVOID the_arg) 642 { 643 int res; 644 unsigned int count; 645 void *objs = NULL; 646 RpcServerProtseq* cps = the_arg; 647 RpcConnection* conn; 648 BOOL set_ready_event = FALSE; 649 650 TRACE("(the_arg == ^%p)\n", the_arg); 651 652 for (;;) { 653 objs = cps->ops->get_wait_array(cps, objs, &count); 654 655 if (set_ready_event) 656 { 657 /* signal to function that changed state that we are now sync'ed */ 658 SetEvent(cps->server_ready_event); 659 set_ready_event = FALSE; 660 } 661 662 /* start waiting */ 663 res = cps->ops->wait_for_new_connection(cps, count, objs); 664 665 if (res == -1 || (res == 0 && !std_listen)) 666 { 667 /* cleanup */ 668 cps->ops->free_wait_array(cps, objs); 669 break; 670 } 671 else if (res == 0) 672 set_ready_event = TRUE; 673 } 674 675 TRACE("closing connections\n"); 676 677 EnterCriticalSection(&cps->cs); 678 LIST_FOR_EACH_ENTRY(conn, &cps->listeners, RpcConnection, protseq_entry) 679 RPCRT4_CloseConnection(conn); 680 LIST_FOR_EACH_ENTRY(conn, &cps->connections, RpcConnection, protseq_entry) 681 { 682 RPCRT4_GrabConnection(conn); 683 rpcrt4_conn_close_read(conn); 684 } 685 LeaveCriticalSection(&cps->cs); 686 687 if (res == 0 && !std_listen) 688 SetEvent(cps->server_ready_event); 689 690 TRACE("waiting for active connections to close\n"); 691 692 EnterCriticalSection(&cps->cs); 693 while (!list_empty(&cps->connections)) 694 { 695 conn = LIST_ENTRY(list_head(&cps->connections), RpcConnection, protseq_entry); 696 LeaveCriticalSection(&cps->cs); 697 rpcrt4_conn_release_and_wait(conn); 698 EnterCriticalSection(&cps->cs); 699 } 700 LeaveCriticalSection(&cps->cs); 701 702 TRACE("done\n"); 703 return 0; 704 } 705 706 /* tells the server thread that the state has changed and waits for it to 707 * make the changes */ 708 static void RPCRT4_sync_with_server_thread(RpcServerProtseq *ps) 709 { 710 /* make sure we are the only thread sync'ing the server state, otherwise 711 * there is a race with the server thread setting an older state and setting 712 * the server_ready_event when the new state hasn't yet been applied */ 713 WaitForSingleObject(ps->mgr_mutex, INFINITE); 714 715 ps->ops->signal_state_changed(ps); 716 717 /* wait for server thread to make the requested changes before returning */ 718 WaitForSingleObject(ps->server_ready_event, INFINITE); 719 720 ReleaseMutex(ps->mgr_mutex); 721 } 722 723 static RPC_STATUS RPCRT4_start_listen_protseq(RpcServerProtseq *ps, BOOL auto_listen) 724 { 725 RPC_STATUS status = RPC_S_OK; 726 727 EnterCriticalSection(&listen_cs); 728 if (ps->server_thread) goto done; 729 730 if (!ps->mgr_mutex) ps->mgr_mutex = CreateMutexW(NULL, FALSE, NULL); 731 if (!ps->server_ready_event) ps->server_ready_event = CreateEventW(NULL, FALSE, FALSE, NULL); 732 ps->server_thread = CreateThread(NULL, 0, RPCRT4_server_thread, ps, 0, NULL); 733 if (!ps->server_thread) 734 status = RPC_S_OUT_OF_RESOURCES; 735 736 done: 737 LeaveCriticalSection(&listen_cs); 738 return status; 739 } 740 741 static RPC_STATUS RPCRT4_start_listen(BOOL auto_listen) 742 { 743 RPC_STATUS status = RPC_S_ALREADY_LISTENING; 744 RpcServerProtseq *cps; 745 746 TRACE("\n"); 747 748 EnterCriticalSection(&listen_cs); 749 if (auto_listen || !listen_done_event) 750 { 751 status = RPC_S_OK; 752 if(!auto_listen) 753 listen_done_event = CreateEventW(NULL, TRUE, FALSE, NULL); 754 if (++listen_count == 1) 755 std_listen = TRUE; 756 } 757 LeaveCriticalSection(&listen_cs); 758 if (status) return status; 759 760 if (std_listen) 761 { 762 EnterCriticalSection(&server_cs); 763 LIST_FOR_EACH_ENTRY(cps, &protseqs, RpcServerProtseq, entry) 764 { 765 status = RPCRT4_start_listen_protseq(cps, TRUE); 766 if (status != RPC_S_OK) 767 break; 768 769 /* make sure server is actually listening on the interface before 770 * returning */ 771 RPCRT4_sync_with_server_thread(cps); 772 } 773 LeaveCriticalSection(&server_cs); 774 } 775 776 return status; 777 } 778 779 static RPC_STATUS RPCRT4_stop_listen(BOOL auto_listen) 780 { 781 BOOL stop_listen = FALSE; 782 RPC_STATUS status = RPC_S_OK; 783 784 EnterCriticalSection(&listen_cs); 785 if (!std_listen && (auto_listen || !listen_done_event)) 786 { 787 status = RPC_S_NOT_LISTENING; 788 } 789 else 790 { 791 stop_listen = listen_count != 0 && --listen_count == 0; 792 assert(listen_count >= 0); 793 if (stop_listen) 794 std_listen = FALSE; 795 } 796 LeaveCriticalSection(&listen_cs); 797 798 if (status) return status; 799 800 if (stop_listen) { 801 RpcServerProtseq *cps; 802 EnterCriticalSection(&server_cs); 803 LIST_FOR_EACH_ENTRY(cps, &protseqs, RpcServerProtseq, entry) 804 RPCRT4_sync_with_server_thread(cps); 805 LeaveCriticalSection(&server_cs); 806 } 807 808 if (!auto_listen) 809 { 810 EnterCriticalSection(&listen_cs); 811 SetEvent( listen_done_event ); 812 LeaveCriticalSection(&listen_cs); 813 } 814 return RPC_S_OK; 815 } 816 817 static BOOL RPCRT4_protseq_is_endpoint_registered(RpcServerProtseq *protseq, const char *endpoint) 818 { 819 RpcConnection *conn; 820 BOOL registered = FALSE; 821 EnterCriticalSection(&protseq->cs); 822 LIST_FOR_EACH_ENTRY(conn, &protseq->listeners, RpcConnection, protseq_entry) { 823 if (!endpoint || !strcmp(endpoint, conn->Endpoint)) { 824 registered = TRUE; 825 break; 826 } 827 } 828 LeaveCriticalSection(&protseq->cs); 829 return registered; 830 } 831 832 static RPC_STATUS RPCRT4_use_protseq(RpcServerProtseq* ps, const char *endpoint) 833 { 834 RPC_STATUS status; 835 836 EnterCriticalSection(&ps->cs); 837 838 if (RPCRT4_protseq_is_endpoint_registered(ps, endpoint)) 839 status = RPC_S_OK; 840 else 841 status = ps->ops->open_endpoint(ps, endpoint); 842 843 LeaveCriticalSection(&ps->cs); 844 845 if (status != RPC_S_OK) 846 return status; 847 848 if (std_listen) 849 { 850 status = RPCRT4_start_listen_protseq(ps, FALSE); 851 if (status == RPC_S_OK) 852 RPCRT4_sync_with_server_thread(ps); 853 } 854 855 return status; 856 } 857 858 /*********************************************************************** 859 * RpcServerInqBindings (RPCRT4.@) 860 */ 861 RPC_STATUS WINAPI RpcServerInqBindings( RPC_BINDING_VECTOR** BindingVector ) 862 { 863 RPC_STATUS status; 864 DWORD count; 865 RpcServerProtseq* ps; 866 RpcConnection* conn; 867 868 if (BindingVector) 869 TRACE("(*BindingVector == ^%p)\n", *BindingVector); 870 else 871 ERR("(BindingVector == NULL!!?)\n"); 872 873 EnterCriticalSection(&server_cs); 874 /* count connections */ 875 count = 0; 876 LIST_FOR_EACH_ENTRY(ps, &protseqs, RpcServerProtseq, entry) { 877 EnterCriticalSection(&ps->cs); 878 LIST_FOR_EACH_ENTRY(conn, &ps->listeners, RpcConnection, protseq_entry) 879 count++; 880 LeaveCriticalSection(&ps->cs); 881 } 882 if (count) { 883 /* export bindings */ 884 *BindingVector = HeapAlloc(GetProcessHeap(), 0, 885 sizeof(RPC_BINDING_VECTOR) + 886 sizeof(RPC_BINDING_HANDLE)*(count-1)); 887 (*BindingVector)->Count = count; 888 count = 0; 889 LIST_FOR_EACH_ENTRY(ps, &protseqs, RpcServerProtseq, entry) { 890 EnterCriticalSection(&ps->cs); 891 LIST_FOR_EACH_ENTRY(conn, &ps->listeners, RpcConnection, protseq_entry) { 892 RPCRT4_MakeBinding((RpcBinding**)&(*BindingVector)->BindingH[count], 893 conn); 894 count++; 895 } 896 LeaveCriticalSection(&ps->cs); 897 } 898 status = RPC_S_OK; 899 } else { 900 *BindingVector = NULL; 901 status = RPC_S_NO_BINDINGS; 902 } 903 LeaveCriticalSection(&server_cs); 904 return status; 905 } 906 907 /*********************************************************************** 908 * RpcServerUseProtseqEpA (RPCRT4.@) 909 */ 910 RPC_STATUS WINAPI RpcServerUseProtseqEpA( RPC_CSTR Protseq, UINT MaxCalls, RPC_CSTR Endpoint, LPVOID SecurityDescriptor ) 911 { 912 RPC_POLICY policy; 913 914 TRACE( "(%s,%u,%s,%p)\n", Protseq, MaxCalls, Endpoint, SecurityDescriptor ); 915 916 /* This should provide the default behaviour */ 917 policy.Length = sizeof( policy ); 918 policy.EndpointFlags = 0; 919 policy.NICFlags = 0; 920 921 return RpcServerUseProtseqEpExA( Protseq, MaxCalls, Endpoint, SecurityDescriptor, &policy ); 922 } 923 924 /*********************************************************************** 925 * RpcServerUseProtseqEpW (RPCRT4.@) 926 */ 927 RPC_STATUS WINAPI RpcServerUseProtseqEpW( RPC_WSTR Protseq, UINT MaxCalls, RPC_WSTR Endpoint, LPVOID SecurityDescriptor ) 928 { 929 RPC_POLICY policy; 930 931 TRACE( "(%s,%u,%s,%p)\n", debugstr_w( Protseq ), MaxCalls, debugstr_w( Endpoint ), SecurityDescriptor ); 932 933 /* This should provide the default behaviour */ 934 policy.Length = sizeof( policy ); 935 policy.EndpointFlags = 0; 936 policy.NICFlags = 0; 937 938 return RpcServerUseProtseqEpExW( Protseq, MaxCalls, Endpoint, SecurityDescriptor, &policy ); 939 } 940 941 /*********************************************************************** 942 * alloc_serverprotoseq (internal) 943 * 944 * Must be called with server_cs held. 945 */ 946 static RPC_STATUS alloc_serverprotoseq(UINT MaxCalls, const char *Protseq, RpcServerProtseq **ps) 947 { 948 const struct protseq_ops *ops = rpcrt4_get_protseq_ops(Protseq); 949 950 if (!ops) 951 { 952 FIXME("protseq %s not supported\n", debugstr_a(Protseq)); 953 return RPC_S_PROTSEQ_NOT_SUPPORTED; 954 } 955 956 *ps = ops->alloc(); 957 if (!*ps) 958 return RPC_S_OUT_OF_RESOURCES; 959 (*ps)->MaxCalls = MaxCalls; 960 (*ps)->Protseq = RPCRT4_strdupA(Protseq); 961 (*ps)->ops = ops; 962 list_init(&(*ps)->listeners); 963 list_init(&(*ps)->connections); 964 InitializeCriticalSection(&(*ps)->cs); 965 (*ps)->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": RpcServerProtseq.cs"); 966 967 list_add_head(&protseqs, &(*ps)->entry); 968 969 TRACE("new protseq %p created for %s\n", *ps, Protseq); 970 971 return RPC_S_OK; 972 } 973 974 /* must be called with server_cs held */ 975 static void destroy_serverprotoseq(RpcServerProtseq *ps) 976 { 977 RPCRT4_strfree(ps->Protseq); 978 ps->cs.DebugInfo->Spare[0] = 0; 979 DeleteCriticalSection(&ps->cs); 980 CloseHandle(ps->mgr_mutex); 981 CloseHandle(ps->server_ready_event); 982 list_remove(&ps->entry); 983 HeapFree(GetProcessHeap(), 0, ps); 984 } 985 986 /* Finds a given protseq or creates a new one if one doesn't already exist */ 987 static RPC_STATUS RPCRT4_get_or_create_serverprotseq(UINT MaxCalls, const char *Protseq, RpcServerProtseq **ps) 988 { 989 RPC_STATUS status; 990 RpcServerProtseq *cps; 991 992 EnterCriticalSection(&server_cs); 993 994 LIST_FOR_EACH_ENTRY(cps, &protseqs, RpcServerProtseq, entry) 995 if (!strcmp(cps->Protseq, Protseq)) 996 { 997 TRACE("found existing protseq object for %s\n", Protseq); 998 *ps = cps; 999 LeaveCriticalSection(&server_cs); 1000 return S_OK; 1001 } 1002 1003 status = alloc_serverprotoseq(MaxCalls, Protseq, ps); 1004 1005 LeaveCriticalSection(&server_cs); 1006 1007 return status; 1008 } 1009 1010 /*********************************************************************** 1011 * RpcServerUseProtseqEpExA (RPCRT4.@) 1012 */ 1013 RPC_STATUS WINAPI RpcServerUseProtseqEpExA( RPC_CSTR Protseq, UINT MaxCalls, RPC_CSTR Endpoint, LPVOID SecurityDescriptor, 1014 PRPC_POLICY lpPolicy ) 1015 { 1016 RpcServerProtseq* ps; 1017 RPC_STATUS status; 1018 1019 TRACE("(%s,%u,%s,%p,{%u,%u,%u})\n", debugstr_a((const char *)Protseq), 1020 MaxCalls, debugstr_a((const char *)Endpoint), SecurityDescriptor, 1021 lpPolicy->Length, lpPolicy->EndpointFlags, lpPolicy->NICFlags ); 1022 1023 status = RPCRT4_get_or_create_serverprotseq(MaxCalls, (const char *)Protseq, &ps); 1024 if (status != RPC_S_OK) 1025 return status; 1026 1027 return RPCRT4_use_protseq(ps, (const char *)Endpoint); 1028 } 1029 1030 /*********************************************************************** 1031 * RpcServerUseProtseqEpExW (RPCRT4.@) 1032 */ 1033 RPC_STATUS WINAPI RpcServerUseProtseqEpExW( RPC_WSTR Protseq, UINT MaxCalls, RPC_WSTR Endpoint, LPVOID SecurityDescriptor, 1034 PRPC_POLICY lpPolicy ) 1035 { 1036 RpcServerProtseq* ps; 1037 RPC_STATUS status; 1038 LPSTR ProtseqA; 1039 LPSTR EndpointA; 1040 1041 TRACE("(%s,%u,%s,%p,{%u,%u,%u})\n", debugstr_w( Protseq ), MaxCalls, 1042 debugstr_w( Endpoint ), SecurityDescriptor, 1043 lpPolicy->Length, lpPolicy->EndpointFlags, lpPolicy->NICFlags ); 1044 1045 ProtseqA = RPCRT4_strdupWtoA(Protseq); 1046 status = RPCRT4_get_or_create_serverprotseq(MaxCalls, ProtseqA, &ps); 1047 RPCRT4_strfree(ProtseqA); 1048 if (status != RPC_S_OK) 1049 return status; 1050 1051 EndpointA = RPCRT4_strdupWtoA(Endpoint); 1052 status = RPCRT4_use_protseq(ps, EndpointA); 1053 RPCRT4_strfree(EndpointA); 1054 return status; 1055 } 1056 1057 /*********************************************************************** 1058 * RpcServerUseProtseqA (RPCRT4.@) 1059 */ 1060 RPC_STATUS WINAPI RpcServerUseProtseqA(RPC_CSTR Protseq, unsigned int MaxCalls, void *SecurityDescriptor) 1061 { 1062 RPC_STATUS status; 1063 RpcServerProtseq* ps; 1064 1065 TRACE("(Protseq == %s, MaxCalls == %d, SecurityDescriptor == ^%p)\n", debugstr_a((char*)Protseq), MaxCalls, SecurityDescriptor); 1066 1067 status = RPCRT4_get_or_create_serverprotseq(MaxCalls, (const char *)Protseq, &ps); 1068 if (status != RPC_S_OK) 1069 return status; 1070 1071 return RPCRT4_use_protseq(ps, NULL); 1072 } 1073 1074 /*********************************************************************** 1075 * RpcServerUseProtseqW (RPCRT4.@) 1076 */ 1077 RPC_STATUS WINAPI RpcServerUseProtseqW(RPC_WSTR Protseq, unsigned int MaxCalls, void *SecurityDescriptor) 1078 { 1079 RPC_STATUS status; 1080 RpcServerProtseq* ps; 1081 LPSTR ProtseqA; 1082 1083 TRACE("Protseq == %s, MaxCalls == %d, SecurityDescriptor == ^%p)\n", debugstr_w(Protseq), MaxCalls, SecurityDescriptor); 1084 1085 ProtseqA = RPCRT4_strdupWtoA(Protseq); 1086 status = RPCRT4_get_or_create_serverprotseq(MaxCalls, ProtseqA, &ps); 1087 RPCRT4_strfree(ProtseqA); 1088 if (status != RPC_S_OK) 1089 return status; 1090 1091 return RPCRT4_use_protseq(ps, NULL); 1092 } 1093 1094 void RPCRT4_destroy_all_protseqs(void) 1095 { 1096 RpcServerProtseq *cps, *cursor2; 1097 1098 if (listen_count != 0) 1099 std_listen = FALSE; 1100 1101 EnterCriticalSection(&server_cs); 1102 LIST_FOR_EACH_ENTRY_SAFE(cps, cursor2, &protseqs, RpcServerProtseq, entry) 1103 { 1104 if (listen_count != 0) 1105 RPCRT4_sync_with_server_thread(cps); 1106 destroy_serverprotoseq(cps); 1107 } 1108 LeaveCriticalSection(&server_cs); 1109 DeleteCriticalSection(&server_cs); 1110 DeleteCriticalSection(&listen_cs); 1111 } 1112 1113 /*********************************************************************** 1114 * RpcServerRegisterIf (RPCRT4.@) 1115 */ 1116 RPC_STATUS WINAPI RpcServerRegisterIf( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, RPC_MGR_EPV* MgrEpv ) 1117 { 1118 TRACE("(%p,%s,%p)\n", IfSpec, debugstr_guid(MgrTypeUuid), MgrEpv); 1119 return RpcServerRegisterIf3( IfSpec, MgrTypeUuid, MgrEpv, 0, RPC_C_LISTEN_MAX_CALLS_DEFAULT, (UINT)-1, NULL, NULL ); 1120 } 1121 1122 /*********************************************************************** 1123 * RpcServerRegisterIfEx (RPCRT4.@) 1124 */ 1125 RPC_STATUS WINAPI RpcServerRegisterIfEx( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, RPC_MGR_EPV* MgrEpv, 1126 UINT Flags, UINT MaxCalls, RPC_IF_CALLBACK_FN* IfCallbackFn ) 1127 { 1128 TRACE("(%p,%s,%p,%u,%u,%p)\n", IfSpec, debugstr_guid(MgrTypeUuid), MgrEpv, Flags, MaxCalls, IfCallbackFn); 1129 return RpcServerRegisterIf3( IfSpec, MgrTypeUuid, MgrEpv, Flags, MaxCalls, (UINT)-1, IfCallbackFn, NULL ); 1130 } 1131 1132 /*********************************************************************** 1133 * RpcServerRegisterIf2 (RPCRT4.@) 1134 */ 1135 RPC_STATUS WINAPI RpcServerRegisterIf2( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, RPC_MGR_EPV* MgrEpv, 1136 UINT Flags, UINT MaxCalls, UINT MaxRpcSize, RPC_IF_CALLBACK_FN* IfCallbackFn ) 1137 { 1138 return RpcServerRegisterIf3( IfSpec, MgrTypeUuid, MgrEpv, Flags, MaxCalls, MaxRpcSize, IfCallbackFn, NULL ); 1139 } 1140 1141 /*********************************************************************** 1142 * RpcServerRegisterIf3 (RPCRT4.@) 1143 */ 1144 RPC_STATUS WINAPI RpcServerRegisterIf3( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, RPC_MGR_EPV* MgrEpv, 1145 UINT Flags, UINT MaxCalls, UINT MaxRpcSize, RPC_IF_CALLBACK_FN* IfCallbackFn, void* SecurityDescriptor) 1146 { 1147 PRPC_SERVER_INTERFACE If = IfSpec; 1148 RpcServerInterface* sif; 1149 unsigned int i; 1150 1151 TRACE("(%p,%s,%p,%u,%u,%u,%p,%p)\n", IfSpec, debugstr_guid(MgrTypeUuid), MgrEpv, Flags, MaxCalls, 1152 MaxRpcSize, IfCallbackFn, SecurityDescriptor); 1153 1154 if (SecurityDescriptor) 1155 FIXME("Unsupported SecurityDescriptor argument.\n"); 1156 1157 TRACE(" interface id: %s %d.%d\n", debugstr_guid(&If->InterfaceId.SyntaxGUID), 1158 If->InterfaceId.SyntaxVersion.MajorVersion, 1159 If->InterfaceId.SyntaxVersion.MinorVersion); 1160 TRACE(" transfer syntax: %s %d.%d\n", debugstr_guid(&If->TransferSyntax.SyntaxGUID), 1161 If->TransferSyntax.SyntaxVersion.MajorVersion, 1162 If->TransferSyntax.SyntaxVersion.MinorVersion); 1163 TRACE(" dispatch table: %p\n", If->DispatchTable); 1164 if (If->DispatchTable) { 1165 TRACE(" dispatch table count: %d\n", If->DispatchTable->DispatchTableCount); 1166 for (i=0; i<If->DispatchTable->DispatchTableCount; i++) { 1167 TRACE(" entry %d: %p\n", i, If->DispatchTable->DispatchTable[i]); 1168 } 1169 TRACE(" reserved: %ld\n", If->DispatchTable->Reserved); 1170 } 1171 TRACE(" protseq endpoint count: %d\n", If->RpcProtseqEndpointCount); 1172 TRACE(" default manager epv: %p\n", If->DefaultManagerEpv); 1173 TRACE(" interpreter info: %p\n", If->InterpreterInfo); 1174 1175 sif = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcServerInterface)); 1176 sif->If = If; 1177 if (MgrTypeUuid) { 1178 sif->MgrTypeUuid = *MgrTypeUuid; 1179 sif->MgrEpv = MgrEpv; 1180 } else { 1181 memset(&sif->MgrTypeUuid, 0, sizeof(UUID)); 1182 sif->MgrEpv = If->DefaultManagerEpv; 1183 } 1184 sif->Flags = Flags; 1185 sif->MaxCalls = MaxCalls; 1186 sif->MaxRpcSize = MaxRpcSize; 1187 sif->IfCallbackFn = IfCallbackFn; 1188 1189 EnterCriticalSection(&server_cs); 1190 list_add_head(&server_interfaces, &sif->entry); 1191 LeaveCriticalSection(&server_cs); 1192 1193 if (sif->Flags & RPC_IF_AUTOLISTEN) 1194 RPCRT4_start_listen(TRUE); 1195 1196 return RPC_S_OK; 1197 } 1198 1199 /*********************************************************************** 1200 * RpcServerUnregisterIf (RPCRT4.@) 1201 */ 1202 RPC_STATUS WINAPI RpcServerUnregisterIf( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, UINT WaitForCallsToComplete ) 1203 { 1204 PRPC_SERVER_INTERFACE If = IfSpec; 1205 HANDLE event = NULL; 1206 BOOL found = FALSE; 1207 BOOL completed = TRUE; 1208 RpcServerInterface *cif; 1209 RPC_STATUS status; 1210 1211 TRACE("(IfSpec == (RPC_IF_HANDLE)^%p (%s), MgrTypeUuid == %s, WaitForCallsToComplete == %u)\n", 1212 IfSpec, debugstr_guid(&If->InterfaceId.SyntaxGUID), debugstr_guid(MgrTypeUuid), WaitForCallsToComplete); 1213 1214 EnterCriticalSection(&server_cs); 1215 LIST_FOR_EACH_ENTRY(cif, &server_interfaces, RpcServerInterface, entry) { 1216 if (((!IfSpec && !(cif->Flags & RPC_IF_AUTOLISTEN)) || 1217 (IfSpec && !memcmp(&If->InterfaceId, &cif->If->InterfaceId, sizeof(RPC_SYNTAX_IDENTIFIER)))) && 1218 UuidEqual(MgrTypeUuid, &cif->MgrTypeUuid, &status)) { 1219 list_remove(&cif->entry); 1220 TRACE("unregistering cif %p\n", cif); 1221 if (cif->CurrentCalls) { 1222 completed = FALSE; 1223 cif->Delete = TRUE; 1224 if (WaitForCallsToComplete) 1225 cif->CallsCompletedEvent = event = CreateEventW(NULL, FALSE, FALSE, NULL); 1226 } 1227 found = TRUE; 1228 break; 1229 } 1230 } 1231 LeaveCriticalSection(&server_cs); 1232 1233 if (!found) { 1234 ERR("not found for object %s\n", debugstr_guid(MgrTypeUuid)); 1235 return RPC_S_UNKNOWN_IF; 1236 } 1237 1238 if (completed) 1239 HeapFree(GetProcessHeap(), 0, cif); 1240 else if (event) { 1241 /* sif will be freed when the last call is completed, so be careful not to 1242 * touch that memory here as that could happen before we get here */ 1243 WaitForSingleObject(event, INFINITE); 1244 CloseHandle(event); 1245 } 1246 1247 return RPC_S_OK; 1248 } 1249 1250 /*********************************************************************** 1251 * RpcServerUnregisterIfEx (RPCRT4.@) 1252 */ 1253 RPC_STATUS WINAPI RpcServerUnregisterIfEx( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, int RundownContextHandles ) 1254 { 1255 FIXME("(IfSpec == (RPC_IF_HANDLE)^%p, MgrTypeUuid == %s, RundownContextHandles == %d): stub\n", 1256 IfSpec, debugstr_guid(MgrTypeUuid), RundownContextHandles); 1257 1258 return RPC_S_OK; 1259 } 1260 1261 /*********************************************************************** 1262 * RpcObjectSetType (RPCRT4.@) 1263 * 1264 * PARAMS 1265 * ObjUuid [I] "Object" UUID 1266 * TypeUuid [I] "Type" UUID 1267 * 1268 * RETURNS 1269 * RPC_S_OK The call succeeded 1270 * RPC_S_INVALID_OBJECT The provided object (nil) is not valid 1271 * RPC_S_ALREADY_REGISTERED The provided object is already registered 1272 * 1273 * Maps "Object" UUIDs to "Type" UUIDs. Passing the nil UUID as the type 1274 * resets the mapping for the specified object UUID to nil (the default). 1275 * The nil object is always associated with the nil type and cannot be 1276 * reassigned. Servers can support multiple implementations on the same 1277 * interface by registering different end-point vectors for the different 1278 * types. There's no need to call this if a server only supports the nil 1279 * type, as is typical. 1280 */ 1281 RPC_STATUS WINAPI RpcObjectSetType( UUID* ObjUuid, UUID* TypeUuid ) 1282 { 1283 RpcObjTypeMap *map = RpcObjTypeMaps, *prev = NULL; 1284 RPC_STATUS dummy; 1285 1286 TRACE("(ObjUUID == %s, TypeUuid == %s).\n", debugstr_guid(ObjUuid), debugstr_guid(TypeUuid)); 1287 if ((! ObjUuid) || UuidIsNil(ObjUuid, &dummy)) { 1288 /* nil uuid cannot be remapped */ 1289 return RPC_S_INVALID_OBJECT; 1290 } 1291 1292 /* find the mapping for this object if there is one ... */ 1293 while (map) { 1294 if (! UuidCompare(ObjUuid, &map->Object, &dummy)) break; 1295 prev = map; 1296 map = map->next; 1297 } 1298 if ((! TypeUuid) || UuidIsNil(TypeUuid, &dummy)) { 1299 /* ... and drop it from the list */ 1300 if (map) { 1301 if (prev) 1302 prev->next = map->next; 1303 else 1304 RpcObjTypeMaps = map->next; 1305 HeapFree(GetProcessHeap(), 0, map); 1306 } 1307 } else { 1308 /* ... , fail if we found it ... */ 1309 if (map) 1310 return RPC_S_ALREADY_REGISTERED; 1311 /* ... otherwise create a new one and add it in. */ 1312 map = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcObjTypeMap)); 1313 map->Object = *ObjUuid; 1314 map->Type = *TypeUuid; 1315 map->next = NULL; 1316 if (prev) 1317 prev->next = map; /* prev is the last map in the linklist */ 1318 else 1319 RpcObjTypeMaps = map; 1320 } 1321 1322 return RPC_S_OK; 1323 } 1324 1325 struct rpc_server_registered_auth_info 1326 { 1327 struct list entry; 1328 USHORT auth_type; 1329 WCHAR *package_name; 1330 WCHAR *principal; 1331 ULONG max_token; 1332 }; 1333 1334 static RPC_STATUS find_security_package(ULONG auth_type, SecPkgInfoW **packages_buf, SecPkgInfoW **ret) 1335 { 1336 SECURITY_STATUS sec_status; 1337 SecPkgInfoW *packages; 1338 ULONG package_count; 1339 ULONG i; 1340 1341 sec_status = EnumerateSecurityPackagesW(&package_count, &packages); 1342 if (sec_status != SEC_E_OK) 1343 { 1344 ERR("EnumerateSecurityPackagesW failed with error 0x%08x\n", sec_status); 1345 return RPC_S_SEC_PKG_ERROR; 1346 } 1347 1348 for (i = 0; i < package_count; i++) 1349 if (packages[i].wRPCID == auth_type) 1350 break; 1351 1352 if (i == package_count) 1353 { 1354 WARN("unsupported AuthnSvc %u\n", auth_type); 1355 FreeContextBuffer(packages); 1356 return RPC_S_UNKNOWN_AUTHN_SERVICE; 1357 } 1358 1359 TRACE("found package %s for service %u\n", debugstr_w(packages[i].Name), auth_type); 1360 *packages_buf = packages; 1361 *ret = packages + i; 1362 return RPC_S_OK; 1363 } 1364 1365 RPC_STATUS RPCRT4_ServerGetRegisteredAuthInfo( 1366 USHORT auth_type, CredHandle *cred, TimeStamp *exp, ULONG *max_token) 1367 { 1368 RPC_STATUS status = RPC_S_UNKNOWN_AUTHN_SERVICE; 1369 struct rpc_server_registered_auth_info *auth_info; 1370 SECURITY_STATUS sec_status; 1371 1372 EnterCriticalSection(&server_auth_info_cs); 1373 LIST_FOR_EACH_ENTRY(auth_info, &server_registered_auth_info, struct rpc_server_registered_auth_info, entry) 1374 { 1375 if (auth_info->auth_type == auth_type) 1376 { 1377 sec_status = AcquireCredentialsHandleW((SEC_WCHAR *)auth_info->principal, auth_info->package_name, 1378 SECPKG_CRED_INBOUND, NULL, NULL, NULL, NULL, 1379 cred, exp); 1380 if (sec_status != SEC_E_OK) 1381 { 1382 status = RPC_S_SEC_PKG_ERROR; 1383 break; 1384 } 1385 1386 *max_token = auth_info->max_token; 1387 status = RPC_S_OK; 1388 break; 1389 } 1390 } 1391 LeaveCriticalSection(&server_auth_info_cs); 1392 1393 return status; 1394 } 1395 1396 void RPCRT4_ServerFreeAllRegisteredAuthInfo(void) 1397 { 1398 struct rpc_server_registered_auth_info *auth_info, *cursor2; 1399 1400 EnterCriticalSection(&server_auth_info_cs); 1401 LIST_FOR_EACH_ENTRY_SAFE(auth_info, cursor2, &server_registered_auth_info, struct rpc_server_registered_auth_info, entry) 1402 { 1403 HeapFree(GetProcessHeap(), 0, auth_info->package_name); 1404 HeapFree(GetProcessHeap(), 0, auth_info->principal); 1405 HeapFree(GetProcessHeap(), 0, auth_info); 1406 } 1407 LeaveCriticalSection(&server_auth_info_cs); 1408 DeleteCriticalSection(&server_auth_info_cs); 1409 } 1410 1411 /*********************************************************************** 1412 * RpcServerRegisterAuthInfoA (RPCRT4.@) 1413 */ 1414 RPC_STATUS WINAPI RpcServerRegisterAuthInfoA( RPC_CSTR ServerPrincName, ULONG AuthnSvc, RPC_AUTH_KEY_RETRIEVAL_FN GetKeyFn, 1415 LPVOID Arg ) 1416 { 1417 WCHAR *principal_name = NULL; 1418 RPC_STATUS status; 1419 1420 TRACE("(%s,%u,%p,%p)\n", ServerPrincName, AuthnSvc, GetKeyFn, Arg); 1421 1422 if(ServerPrincName && !(principal_name = RPCRT4_strdupAtoW((const char*)ServerPrincName))) 1423 return RPC_S_OUT_OF_RESOURCES; 1424 1425 status = RpcServerRegisterAuthInfoW(principal_name, AuthnSvc, GetKeyFn, Arg); 1426 1427 HeapFree(GetProcessHeap(), 0, principal_name); 1428 return status; 1429 } 1430 1431 /*********************************************************************** 1432 * RpcServerRegisterAuthInfoW (RPCRT4.@) 1433 */ 1434 RPC_STATUS WINAPI RpcServerRegisterAuthInfoW( RPC_WSTR ServerPrincName, ULONG AuthnSvc, RPC_AUTH_KEY_RETRIEVAL_FN GetKeyFn, 1435 LPVOID Arg ) 1436 { 1437 struct rpc_server_registered_auth_info *auth_info; 1438 SecPkgInfoW *packages, *package; 1439 WCHAR *package_name; 1440 ULONG max_token; 1441 RPC_STATUS status; 1442 1443 TRACE("(%s,%u,%p,%p)\n", debugstr_w(ServerPrincName), AuthnSvc, GetKeyFn, Arg); 1444 1445 status = find_security_package(AuthnSvc, &packages, &package); 1446 if (status != RPC_S_OK) 1447 return status; 1448 1449 package_name = RPCRT4_strdupW(package->Name); 1450 max_token = package->cbMaxToken; 1451 FreeContextBuffer(packages); 1452 if (!package_name) 1453 return RPC_S_OUT_OF_RESOURCES; 1454 1455 auth_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*auth_info)); 1456 if (!auth_info) { 1457 HeapFree(GetProcessHeap(), 0, package_name); 1458 return RPC_S_OUT_OF_RESOURCES; 1459 } 1460 1461 if (ServerPrincName && !(auth_info->principal = RPCRT4_strdupW(ServerPrincName))) { 1462 HeapFree(GetProcessHeap(), 0, package_name); 1463 HeapFree(GetProcessHeap(), 0, auth_info); 1464 return RPC_S_OUT_OF_RESOURCES; 1465 } 1466 1467 auth_info->auth_type = AuthnSvc; 1468 auth_info->package_name = package_name; 1469 auth_info->max_token = max_token; 1470 1471 EnterCriticalSection(&server_auth_info_cs); 1472 list_add_tail(&server_registered_auth_info, &auth_info->entry); 1473 LeaveCriticalSection(&server_auth_info_cs); 1474 1475 return RPC_S_OK; 1476 } 1477 1478 /****************************************************************************** 1479 * RpcServerInqDefaultPrincNameA (rpcrt4.@) 1480 */ 1481 RPC_STATUS RPC_ENTRY RpcServerInqDefaultPrincNameA(ULONG AuthnSvc, RPC_CSTR *PrincName) 1482 { 1483 RPC_STATUS ret; 1484 RPC_WSTR principalW; 1485 1486 TRACE("%u, %p\n", AuthnSvc, PrincName); 1487 1488 if ((ret = RpcServerInqDefaultPrincNameW( AuthnSvc, &principalW )) == RPC_S_OK) 1489 { 1490 if (!(*PrincName = (RPC_CSTR)RPCRT4_strdupWtoA( principalW ))) return RPC_S_OUT_OF_MEMORY; 1491 RpcStringFreeW( &principalW ); 1492 } 1493 return ret; 1494 } 1495 1496 /****************************************************************************** 1497 * RpcServerInqDefaultPrincNameW (rpcrt4.@) 1498 */ 1499 RPC_STATUS RPC_ENTRY RpcServerInqDefaultPrincNameW(ULONG AuthnSvc, RPC_WSTR *PrincName) 1500 { 1501 ULONG len = 0; 1502 1503 FIXME("%u, %p\n", AuthnSvc, PrincName); 1504 1505 if (AuthnSvc != RPC_C_AUTHN_WINNT) return RPC_S_UNKNOWN_AUTHN_SERVICE; 1506 1507 GetUserNameExW( NameSamCompatible, NULL, &len ); 1508 if (GetLastError() != ERROR_MORE_DATA) return RPC_S_INTERNAL_ERROR; 1509 1510 if (!(*PrincName = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) 1511 return RPC_S_OUT_OF_MEMORY; 1512 1513 GetUserNameExW( NameSamCompatible, *PrincName, &len ); 1514 return RPC_S_OK; 1515 } 1516 1517 /*********************************************************************** 1518 * RpcServerListen (RPCRT4.@) 1519 */ 1520 RPC_STATUS WINAPI RpcServerListen( UINT MinimumCallThreads, UINT MaxCalls, UINT DontWait ) 1521 { 1522 RPC_STATUS status = RPC_S_OK; 1523 1524 TRACE("(%u,%u,%u)\n", MinimumCallThreads, MaxCalls, DontWait); 1525 1526 if (list_empty(&protseqs)) 1527 return RPC_S_NO_PROTSEQS_REGISTERED; 1528 1529 status = RPCRT4_start_listen(FALSE); 1530 1531 if (DontWait || (status != RPC_S_OK)) return status; 1532 1533 return RpcMgmtWaitServerListen(); 1534 } 1535 1536 /*********************************************************************** 1537 * RpcMgmtServerWaitListen (RPCRT4.@) 1538 */ 1539 RPC_STATUS WINAPI RpcMgmtWaitServerListen( void ) 1540 { 1541 RpcServerProtseq *protseq; 1542 HANDLE event, wait_thread; 1543 1544 TRACE("()\n"); 1545 1546 EnterCriticalSection(&listen_cs); 1547 event = listen_done_event; 1548 LeaveCriticalSection(&listen_cs); 1549 1550 if (!event) 1551 return RPC_S_NOT_LISTENING; 1552 1553 TRACE( "waiting for server calls to finish\n" ); 1554 WaitForSingleObject( event, INFINITE ); 1555 TRACE( "done waiting\n" ); 1556 1557 EnterCriticalSection(&listen_cs); 1558 /* wait for server threads to finish */ 1559 while(1) 1560 { 1561 if (listen_count) 1562 break; 1563 1564 wait_thread = NULL; 1565 EnterCriticalSection(&server_cs); 1566 LIST_FOR_EACH_ENTRY(protseq, &protseqs, RpcServerProtseq, entry) 1567 { 1568 if ((wait_thread = protseq->server_thread)) 1569 { 1570 protseq->server_thread = NULL; 1571 break; 1572 } 1573 } 1574 LeaveCriticalSection(&server_cs); 1575 if (!wait_thread) 1576 break; 1577 1578 TRACE("waiting for thread %u\n", GetThreadId(wait_thread)); 1579 LeaveCriticalSection(&listen_cs); 1580 WaitForSingleObject(wait_thread, INFINITE); 1581 CloseHandle(wait_thread); 1582 EnterCriticalSection(&listen_cs); 1583 } 1584 if (listen_done_event == event) 1585 { 1586 listen_done_event = NULL; 1587 CloseHandle( event ); 1588 } 1589 LeaveCriticalSection(&listen_cs); 1590 return RPC_S_OK; 1591 } 1592 1593 /*********************************************************************** 1594 * RpcMgmtStopServerListening (RPCRT4.@) 1595 */ 1596 RPC_STATUS WINAPI RpcMgmtStopServerListening ( RPC_BINDING_HANDLE Binding ) 1597 { 1598 TRACE("(Binding == (RPC_BINDING_HANDLE)^%p)\n", Binding); 1599 1600 if (Binding) { 1601 FIXME("client-side invocation not implemented.\n"); 1602 return RPC_S_WRONG_KIND_OF_BINDING; 1603 } 1604 1605 return RPCRT4_stop_listen(FALSE); 1606 } 1607 1608 /*********************************************************************** 1609 * RpcMgmtEnableIdleCleanup (RPCRT4.@) 1610 */ 1611 RPC_STATUS WINAPI RpcMgmtEnableIdleCleanup(void) 1612 { 1613 FIXME("(): stub\n"); 1614 return RPC_S_OK; 1615 } 1616 1617 /*********************************************************************** 1618 * I_RpcServerStartListening (RPCRT4.@) 1619 */ 1620 RPC_STATUS WINAPI I_RpcServerStartListening( HWND hWnd ) 1621 { 1622 FIXME( "(%p): stub\n", hWnd ); 1623 1624 return RPC_S_OK; 1625 } 1626 1627 /*********************************************************************** 1628 * I_RpcServerStopListening (RPCRT4.@) 1629 */ 1630 RPC_STATUS WINAPI I_RpcServerStopListening( void ) 1631 { 1632 FIXME( "(): stub\n" ); 1633 1634 return RPC_S_OK; 1635 } 1636 1637 /*********************************************************************** 1638 * I_RpcWindowProc (RPCRT4.@) 1639 */ 1640 UINT WINAPI I_RpcWindowProc( void *hWnd, UINT Message, UINT wParam, ULONG lParam ) 1641 { 1642 FIXME( "(%p,%08x,%08x,%08x): stub\n", hWnd, Message, wParam, lParam ); 1643 1644 return 0; 1645 } 1646 1647 /*********************************************************************** 1648 * RpcMgmtInqIfIds (RPCRT4.@) 1649 */ 1650 RPC_STATUS WINAPI RpcMgmtInqIfIds(RPC_BINDING_HANDLE Binding, RPC_IF_ID_VECTOR **IfIdVector) 1651 { 1652 FIXME("(%p,%p): stub\n", Binding, IfIdVector); 1653 return RPC_S_INVALID_BINDING; 1654 } 1655 1656 /*********************************************************************** 1657 * RpcMgmtInqStats (RPCRT4.@) 1658 */ 1659 RPC_STATUS WINAPI RpcMgmtInqStats(RPC_BINDING_HANDLE Binding, RPC_STATS_VECTOR **Statistics) 1660 { 1661 RPC_STATS_VECTOR *stats; 1662 1663 FIXME("(%p,%p)\n", Binding, Statistics); 1664 1665 if ((stats = HeapAlloc(GetProcessHeap(), 0, sizeof(RPC_STATS_VECTOR)))) 1666 { 1667 stats->Count = 1; 1668 stats->Stats[0] = 0; 1669 *Statistics = stats; 1670 return RPC_S_OK; 1671 } 1672 return RPC_S_OUT_OF_RESOURCES; 1673 } 1674 1675 /*********************************************************************** 1676 * RpcMgmtStatsVectorFree (RPCRT4.@) 1677 */ 1678 RPC_STATUS WINAPI RpcMgmtStatsVectorFree(RPC_STATS_VECTOR **StatsVector) 1679 { 1680 FIXME("(%p)\n", StatsVector); 1681 1682 if (StatsVector) 1683 { 1684 HeapFree(GetProcessHeap(), 0, *StatsVector); 1685 *StatsVector = NULL; 1686 } 1687 return RPC_S_OK; 1688 } 1689 1690 /*********************************************************************** 1691 * RpcMgmtEpEltInqBegin (RPCRT4.@) 1692 */ 1693 RPC_STATUS WINAPI RpcMgmtEpEltInqBegin(RPC_BINDING_HANDLE Binding, ULONG InquiryType, 1694 RPC_IF_ID *IfId, ULONG VersOption, UUID *ObjectUuid, RPC_EP_INQ_HANDLE* InquiryContext) 1695 { 1696 FIXME("(%p,%u,%p,%u,%p,%p): stub\n", 1697 Binding, InquiryType, IfId, VersOption, ObjectUuid, InquiryContext); 1698 return RPC_S_INVALID_BINDING; 1699 } 1700 1701 /*********************************************************************** 1702 * RpcMgmtIsServerListening (RPCRT4.@) 1703 */ 1704 RPC_STATUS WINAPI RpcMgmtIsServerListening(RPC_BINDING_HANDLE Binding) 1705 { 1706 RPC_STATUS status = RPC_S_NOT_LISTENING; 1707 1708 TRACE("(%p)\n", Binding); 1709 1710 if (Binding) { 1711 RpcBinding *rpc_binding = (RpcBinding*)Binding; 1712 status = RPCRT4_IsServerListening(rpc_binding->Protseq, rpc_binding->Endpoint); 1713 }else { 1714 EnterCriticalSection(&listen_cs); 1715 if (listen_done_event && std_listen) status = RPC_S_OK; 1716 LeaveCriticalSection(&listen_cs); 1717 } 1718 1719 return status; 1720 } 1721 1722 /*********************************************************************** 1723 * RpcMgmtSetAuthorizationFn (RPCRT4.@) 1724 */ 1725 RPC_STATUS WINAPI RpcMgmtSetAuthorizationFn(RPC_MGMT_AUTHORIZATION_FN fn) 1726 { 1727 FIXME("(%p): stub\n", fn); 1728 return RPC_S_OK; 1729 } 1730 1731 /*********************************************************************** 1732 * RpcMgmtSetServerStackSize (RPCRT4.@) 1733 */ 1734 RPC_STATUS WINAPI RpcMgmtSetServerStackSize(ULONG ThreadStackSize) 1735 { 1736 FIXME("(0x%x): stub\n", ThreadStackSize); 1737 return RPC_S_OK; 1738 } 1739 1740 /*********************************************************************** 1741 * I_RpcGetCurrentCallHandle (RPCRT4.@) 1742 */ 1743 RPC_BINDING_HANDLE WINAPI I_RpcGetCurrentCallHandle(void) 1744 { 1745 TRACE("\n"); 1746 return RPCRT4_GetThreadCurrentCallHandle(); 1747 } 1748