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