/* must be called inside csEpm */ static void delete_registered_ept_entry(struct registered_ept_entry *entry) { I_RpcFree(entry->protseq); I_RpcFree(entry->endpoint); I_RpcFree(entry->address); list_remove(&entry->entry); HeapFree(GetProcessHeap(), 0, entry); }
/*********************************************************************** * I_RpcGetBuffer [RPCRT4.@] * * Allocates a buffer for use by I_RpcSend or I_RpcSendReceive and binds to the * server interface. * * PARAMS * pMsg [I/O] RPC message information. * * RETURNS * Success: RPC_S_OK. * Failure: RPC_S_INVALID_BINDING if pMsg->Handle is invalid. * RPC_S_SERVER_UNAVAILABLE if unable to connect to server. * ERROR_OUTOFMEMORY if buffer allocation failed. * * NOTES * The pMsg->BufferLength field determines the size of the buffer to allocate, * in bytes. * * Use I_RpcFreeBuffer() to unbind from the server and free the message buffer. * * SEE ALSO * I_RpcFreeBuffer(), I_RpcSend(), I_RpcReceive(), I_RpcSendReceive(). */ RPC_STATUS WINAPI I_RpcGetBuffer(PRPC_MESSAGE pMsg) { RPC_STATUS status; RpcBinding* bind = (RpcBinding*)pMsg->Handle; FB_TRACE("> (%p): BufferLength=%d\n", pMsg, pMsg->BufferLength); if (!bind) { FE_ERR("< no binding\n"); return RPC_S_INVALID_BINDING; } pMsg->Buffer = I_RpcAllocate(pMsg->BufferLength); TRACE("Buffer=%p\n", pMsg->Buffer); if (!pMsg->Buffer) return ERROR_OUTOFMEMORY; if (!bind->server) { status = I_RpcNegotiateTransferSyntax(pMsg); if (status != RPC_S_OK) I_RpcFree(pMsg->Buffer); } else status = RPC_S_OK; FE_TRACE("< status:%lu\n",status); return status; }
static RPC_STATUS rpcrt4_protseq_ncacn_np_open_endpoint(RpcServerProtseq *protseq, LPSTR endpoint) { static const char prefix[] = "\\\\."; RPC_STATUS r; LPSTR pname; RpcConnection *Connection; r = RPCRT4_CreateConnection(&Connection, TRUE, protseq->Protseq, NULL, endpoint, NULL, NULL, NULL); if (r != RPC_S_OK) return r; /* protseq=ncacn_np: named pipes */ pname = I_RpcAllocate(strlen(prefix) + strlen(Connection->Endpoint) + 1); strcat(strcpy(pname, prefix), Connection->Endpoint); r = rpcrt4_conn_create_pipe(Connection, pname); I_RpcFree(pname); EnterCriticalSection(&protseq->cs); Connection->Next = protseq->conn; protseq->conn = Connection; LeaveCriticalSection(&protseq->cs); return r; }
static RPC_STATUS rpcrt4_protseq_ncalrpc_open_endpoint(RpcServerProtseq* protseq, LPSTR endpoint) { static const char prefix[] = "\\\\.\\pipe\\lrpc\\"; RPC_STATUS r; LPSTR pname; RpcConnection *Connection; r = RPCRT4_CreateConnection(&Connection, TRUE, protseq->Protseq, NULL, endpoint, NULL, NULL, NULL); if (r != RPC_S_OK) return r; /* protseq=ncalrpc: supposed to use NT LPC ports, * but we'll implement it with named pipes for now */ pname = I_RpcAllocate(strlen(prefix) + strlen(Connection->Endpoint) + 1); strcat(strcpy(pname, prefix), Connection->Endpoint); r = rpcrt4_conn_create_pipe(Connection, pname); I_RpcFree(pname); EnterCriticalSection(&protseq->cs); Connection->Next = protseq->conn; protseq->conn = Connection; LeaveCriticalSection(&protseq->cs); return r; }
void ept_delete(handle_t h, unsigned32 num_ents, ept_entry_t entries[], error_status_t *status) { unsigned32 i; RPC_STATUS rpc_status; *status = RPC_S_OK; WINE_TRACE("(%p, %lu, %p, %p)\n", h, num_ents, entries, status); EnterCriticalSection(&csEpm); for (i = 0; i < num_ents; i++) { struct registered_ept_entry *entry; RPC_SYNTAX_IDENTIFIER iface, syntax; char *protseq; char *endpoint; char *address; rpc_status = TowerExplode(entries[i].tower, &iface, &syntax, &protseq, &endpoint, &address); if (rpc_status != RPC_S_OK) break; entry = find_ept_entry(&iface, &syntax, protseq, endpoint, address, &entries[i].object); if (entry) delete_registered_ept_entry(entry); else { *status = EPT_S_NOT_REGISTERED; break; } I_RpcFree(protseq); I_RpcFree(endpoint); I_RpcFree(address); } LeaveCriticalSection(&csEpm); }
static RPC_STATUS rpcrt4_ncacn_np_handoff(RpcConnection *old_conn, RpcConnection *new_conn) { RPC_STATUS status; LPSTR pname; static const char prefix[] = "\\\\."; rpcrt4_conn_np_handoff((RpcConnection_np *)old_conn, (RpcConnection_np *)new_conn); pname = I_RpcAllocate(strlen(prefix) + strlen(old_conn->Endpoint) + 1); strcat(strcpy(pname, prefix), old_conn->Endpoint); status = rpcrt4_conn_create_pipe(old_conn, pname); I_RpcFree(pname); return status; }
static RPC_STATUS rpcrt4_ncacn_np_open(RpcConnection* Connection) { RpcConnection_np *npc = (RpcConnection_np *) Connection; static const char prefix[] = "\\\\."; RPC_STATUS r; LPSTR pname; /* already connected? */ if (npc->pipe) return RPC_S_OK; /* protseq=ncacn_np: named pipes */ pname = I_RpcAllocate(strlen(prefix) + strlen(Connection->Endpoint) + 1); strcat(strcpy(pname, prefix), Connection->Endpoint); r = rpcrt4_conn_open_pipe(Connection, pname, FALSE); I_RpcFree(pname); return r; }
static RPC_STATUS rpcrt4_ncalrpc_open(RpcConnection* Connection) { RpcConnection_np *npc = (RpcConnection_np *) Connection; static const char prefix[] = "\\\\.\\pipe\\lrpc\\"; RPC_STATUS r; LPSTR pname; /* already connected? */ if (npc->pipe) return RPC_S_OK; /* protseq=ncalrpc: supposed to use NT LPC ports, * but we'll implement it with named pipes for now */ pname = I_RpcAllocate(strlen(prefix) + strlen(Connection->Endpoint) + 1); strcat(strcpy(pname, prefix), Connection->Endpoint); r = rpcrt4_conn_open_pipe(Connection, pname, TRUE); I_RpcFree(pname); return r; }
/*********************************************************************** * I_RpcFreeBuffer [RPCRT4.@] * * Frees a buffer allocated by I_RpcGetBuffer or I_RpcReceive and unbinds from * the server interface. * * PARAMS * pMsg [I/O] RPC message information. * * RETURNS * RPC_S_OK. * * SEE ALSO * I_RpcGetBuffer(), I_RpcReceive(). */ RPC_STATUS WINAPI I_RpcFreeBuffer(PRPC_MESSAGE pMsg) { RpcBinding* bind = (RpcBinding*)pMsg->Handle; FB_TRACE("> (%p) Buffer=%p\n", pMsg, pMsg->Buffer); if (!bind) { FE_ERR("< no binding\n"); return RPC_S_INVALID_BINDING; } if (pMsg->ReservedForRuntime) { RpcConnection *conn = (RpcConnection *)pMsg->ReservedForRuntime; RPCRT4_CloseBinding(bind, conn); RPCRT4_ReleaseBinding(bind); pMsg->ReservedForRuntime = NULL; } I_RpcFree(pMsg->Buffer); FE_TRACE("< \n"); return RPC_S_OK; }
/*********************************************************************** * RpcEpRegisterA (RPCRT4.@) */ RPC_STATUS WINAPI RpcEpRegisterA( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *BindingVector, UUID_VECTOR *UuidVector, RPC_CSTR Annotation ) { PRPC_SERVER_INTERFACE If = IfSpec; ULONG i; RPC_STATUS status = RPC_S_OK; error_status_t status2; ept_entry_t *entries; handle_t handle; TRACE("(%p,%p,%p,%s)\n", IfSpec, BindingVector, UuidVector, debugstr_a((char*)Annotation)); TRACE(" ifid=%s\n", debugstr_guid(&If->InterfaceId.SyntaxGUID)); for (i=0; i<BindingVector->Count; i++) { RpcBinding* bind = BindingVector->BindingH[i]; TRACE(" protseq[%d]=%s\n", i, debugstr_a(bind->Protseq)); TRACE(" endpoint[%d]=%s\n", i, debugstr_a(bind->Endpoint)); } if (UuidVector) { for (i=0; i<UuidVector->Count; i++) TRACE(" obj[%d]=%s\n", i, debugstr_guid(UuidVector->Uuid[i])); } if (!BindingVector->Count) return RPC_S_OK; entries = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*entries) * BindingVector->Count * (UuidVector ? UuidVector->Count : 1)); if (!entries) return RPC_S_OUT_OF_MEMORY; status = get_epm_handle_server(&handle); if (status != RPC_S_OK) { HeapFree(GetProcessHeap(), 0, entries); return status; } for (i = 0; i < BindingVector->Count; i++) { unsigned j; RpcBinding* bind = BindingVector->BindingH[i]; for (j = 0; j < (UuidVector ? UuidVector->Count : 1); j++) { status = TowerConstruct(&If->InterfaceId, &If->TransferSyntax, bind->Protseq, bind->Endpoint, bind->NetworkAddr, &entries[i*(UuidVector ? UuidVector->Count : 1) + j].tower); if (status != RPC_S_OK) break; if (UuidVector) memcpy(&entries[i * UuidVector->Count].object, &UuidVector->Uuid[j], sizeof(GUID)); else memset(&entries[i].object, 0, sizeof(entries[i].object)); if (Annotation) memcpy(entries[i].annotation, Annotation, min(strlen((char *)Annotation) + 1, ept_max_annotation_size)); } } if (status == RPC_S_OK) { while (TRUE) { __TRY { ept_insert(handle, BindingVector->Count * (UuidVector ? UuidVector->Count : 1), entries, TRUE, &status2); } __EXCEPT(rpc_filter) { status2 = GetExceptionCode(); } __ENDTRY if (status2 == RPC_S_SERVER_UNAVAILABLE && is_epm_destination_local(handle)) { if (start_rpcss()) continue; } if (status2 != RPC_S_OK) ERR("ept_insert failed with error %d\n", status2); status = status2; /* FIXME: convert status? */ break; } } RpcBindingFree(&handle); for (i = 0; i < BindingVector->Count; i++) { unsigned j; for (j = 0; j < (UuidVector ? UuidVector->Count : 1); j++) I_RpcFree(entries[i*(UuidVector ? UuidVector->Count : 1) + j].tower); } HeapFree(GetProcessHeap(), 0, entries); return status; }
static RPC_STATUS rpcrt4_ncacn_np_parse_top_of_tower(const unsigned char *tower_data, size_t tower_size, char **networkaddr, char **endpoint) { const twr_empty_floor_t *smb_floor = (const twr_empty_floor_t *)tower_data; const twr_empty_floor_t *nb_floor; TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint); if (tower_size < sizeof(*smb_floor)) return EPT_S_NOT_REGISTERED; tower_data += sizeof(*smb_floor); tower_size -= sizeof(*smb_floor); if ((smb_floor->count_lhs != sizeof(smb_floor->protid)) || (smb_floor->protid != EPM_PROTOCOL_SMB) || (smb_floor->count_rhs > tower_size)) return EPT_S_NOT_REGISTERED; if (endpoint) { *endpoint = I_RpcAllocate(smb_floor->count_rhs); if (!*endpoint) return RPC_S_OUT_OF_RESOURCES; memcpy(*endpoint, tower_data, smb_floor->count_rhs); } tower_data += smb_floor->count_rhs; tower_size -= smb_floor->count_rhs; if (tower_size < sizeof(*nb_floor)) return EPT_S_NOT_REGISTERED; nb_floor = (const twr_empty_floor_t *)tower_data; tower_data += sizeof(*nb_floor); tower_size -= sizeof(*nb_floor); if ((nb_floor->count_lhs != sizeof(nb_floor->protid)) || (nb_floor->protid != EPM_PROTOCOL_NETBIOS) || (nb_floor->count_rhs > tower_size)) return EPT_S_NOT_REGISTERED; if (networkaddr) { *networkaddr = I_RpcAllocate(nb_floor->count_rhs); if (!*networkaddr) { if (endpoint) { I_RpcFree(*endpoint); *endpoint = NULL; } return RPC_S_OUT_OF_RESOURCES; } memcpy(*networkaddr, tower_data, nb_floor->count_rhs); } return RPC_S_OK; }
static RPC_STATUS rpcrt4_ncacn_ip_tcp_parse_top_of_tower(const unsigned char *tower_data, size_t tower_size, char **networkaddr, char **endpoint) { const twr_tcp_floor_t *tcp_floor = (const twr_tcp_floor_t *)tower_data; const twr_ipv4_floor_t *ipv4_floor; struct in_addr in_addr; TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint); if (tower_size < sizeof(*tcp_floor)) return EPT_S_NOT_REGISTERED; tower_data += sizeof(*tcp_floor); tower_size -= sizeof(*tcp_floor); if (tower_size < sizeof(*ipv4_floor)) return EPT_S_NOT_REGISTERED; ipv4_floor = (const twr_ipv4_floor_t *)tower_data; if ((tcp_floor->count_lhs != sizeof(tcp_floor->protid)) || (tcp_floor->protid != EPM_PROTOCOL_TCP) || (tcp_floor->count_rhs != sizeof(tcp_floor->port)) || (ipv4_floor->count_lhs != sizeof(ipv4_floor->protid)) || (ipv4_floor->protid != EPM_PROTOCOL_IP) || (ipv4_floor->count_rhs != sizeof(ipv4_floor->ipv4addr))) return EPT_S_NOT_REGISTERED; if (endpoint) { *endpoint = I_RpcAllocate(6 /* sizeof("65535") + 1 */); if (!*endpoint) return RPC_S_OUT_OF_RESOURCES; sprintf(*endpoint, "%u", ntohs(tcp_floor->port)); } if (networkaddr) { *networkaddr = I_RpcAllocate(INET_ADDRSTRLEN); if (!*networkaddr) { if (endpoint) { I_RpcFree(*endpoint); *endpoint = NULL; } return RPC_S_OUT_OF_RESOURCES; } in_addr.s_addr = ipv4_floor->ipv4addr; if (!inet_ntop(AF_INET, &in_addr, *networkaddr, INET_ADDRSTRLEN)) { ERR("inet_ntop: %s\n", strerror(errno)); I_RpcFree(*networkaddr); *networkaddr = NULL; if (endpoint) { I_RpcFree(*endpoint); *endpoint = NULL; } return EPT_S_NOT_REGISTERED; } } return RPC_S_OK; }
static void test_towers(void) { RPC_STATUS ret; twr_t *tower; static const RPC_SYNTAX_IDENTIFIER mapi_if_id = { { 0xa4f1db00, 0xca47, 0x1067, { 0xb3, 0x1f, 0x00, 0xdd, 0x01, 0x06, 0x62, 0xda } }, { 0, 0 } }; static const RPC_SYNTAX_IDENTIFIER ndr_syntax = { { 0x8a885d04, 0x1ceb, 0x11c9, { 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60 } }, { 2, 0 } }; RPC_SYNTAX_IDENTIFIER object, syntax; char *protseq, *endpoint, *address; BOOL same; ret = TowerConstruct(&mapi_if_id, &ndr_syntax, "ncacn_ip_tcp", "135", "10.0.0.1", &tower); ok(ret == RPC_S_OK || broken(ret == RPC_S_INVALID_RPC_PROTSEQ), /* Vista */ "TowerConstruct failed with error %d\n", ret); if (ret == RPC_S_INVALID_RPC_PROTSEQ) { /* Windows Vista fails with this error and crashes if we continue */ win_skip("TowerConstruct failed, we are most likely on Windows Vista\n"); return; } /* first check we have the right amount of data */ ok(tower->tower_length == sizeof(tower_data_tcp_ip1) || tower->tower_length == sizeof(tower_data_tcp_ip2), "Wrong size of tower %d\n", tower->tower_length); /* then do a byte-by-byte comparison */ same = ((tower->tower_length == sizeof(tower_data_tcp_ip1)) && !memcmp(&tower->tower_octet_string, tower_data_tcp_ip1, sizeof(tower_data_tcp_ip1))) || ((tower->tower_length == sizeof(tower_data_tcp_ip2)) && !memcmp(&tower->tower_octet_string, tower_data_tcp_ip2, sizeof(tower_data_tcp_ip2))); ok(same, "Tower data differs\n"); if (!same) { unsigned32 i; for (i = 0; i < tower->tower_length; i++) { if (i % 8 == 0) printf(" "); printf("0x%02x,", tower->tower_octet_string[i]); if (i % 8 == 7) printf("\n"); } printf("\n"); } ret = TowerExplode(tower, &object, &syntax, &protseq, &endpoint, &address); ok(ret == RPC_S_OK, "TowerExplode failed with error %d\n", ret); ok(!memcmp(&object, &mapi_if_id, sizeof(mapi_if_id)), "object id didn't match\n"); ok(!memcmp(&syntax, &ndr_syntax, sizeof(syntax)), "syntax id didn't match\n"); ok(!strcmp(protseq, "ncacn_ip_tcp"), "protseq was \"%s\" instead of \"ncacn_ip_tcp\"\n", protseq); ok(!strcmp(endpoint, "135"), "endpoint was \"%s\" instead of \"135\"\n", endpoint); ok(!strcmp(address, "10.0.0.1"), "address was \"%s\" instead of \"10.0.0.1\"\n", address); I_RpcFree(protseq); I_RpcFree(endpoint); I_RpcFree(address); ret = TowerExplode(tower, NULL, NULL, NULL, NULL, NULL); ok(ret == RPC_S_OK, "TowerExplode failed with error %d\n", ret); I_RpcFree(tower); /* test the behaviour for ip_tcp with name instead of dotted IP notation */ ret = TowerConstruct(&mapi_if_id, &ndr_syntax, "ncacn_ip_tcp", "135", "localhost", &tower); ok(ret == RPC_S_OK, "TowerConstruct failed with error %d\n", ret); ret = TowerExplode(tower, NULL, NULL, NULL, NULL, &address); ok(ret == RPC_S_OK, "TowerExplode failed with error %d\n", ret); ok(!strcmp(address, "0.0.0.0") || broken(!strcmp(address, "255.255.255.255")), "address was \"%s\" instead of \"0.0.0.0\"\n", address); I_RpcFree(address); I_RpcFree(tower); /* test the behaviour for np with no address */ ret = TowerConstruct(&mapi_if_id, &ndr_syntax, "ncacn_np", "\\pipe\\test", NULL, &tower); ok(ret == RPC_S_OK, "TowerConstruct failed with error %d\n", ret); ret = TowerExplode(tower, NULL, NULL, NULL, NULL, &address); ok(ret == RPC_S_OK || broken(ret != RPC_S_OK), /* win2k, indeterminate */ "TowerExplode failed with error %d\n", ret); /* Windows XP SP3 sets address to NULL */ ok(!address || !strcmp(address, ""), "address was \"%s\" instead of \"\" or NULL (XP SP3)\n", address); I_RpcFree(address); I_RpcFree(tower); }