#define DEFAULT_NCACN_HTTP_TIMEOUT (60 * 1000)
+#undef ARRAYSIZE
#define ARRAYSIZE(a) (sizeof((a)) / sizeof((a)[0]))
WINE_DEFAULT_DEBUG_CHANNEL(rpc);
return RPC_S_OK;
}
+static char *ncalrpc_pipe_name(const char *endpoint)
+{
+ static const char prefix[] = "\\\\.\\pipe\\lrpc\\";
+ char *pipe_name;
+
+ /* protseq=ncalrpc: supposed to use NT LPC ports,
+ * but we'll implement it with named pipes for now */
+ pipe_name = I_RpcAllocate(sizeof(prefix) + strlen(endpoint));
+ strcat(strcpy(pipe_name, prefix), endpoint);
+ return pipe_name;
+}
+
static RPC_STATUS rpcrt4_ncalrpc_open(RpcConnection* Connection)
{
RpcConnection_np *npc = (RpcConnection_np *) Connection;
return r;
}
+static char *ncacn_pipe_name(const char *endpoint)
+{
+ static const char prefix[] = "\\\\.";
+ char *pipe_name;
+
+ /* protseq=ncacn_np: named pipes */
+ pipe_name = I_RpcAllocate(sizeof(prefix) + strlen(endpoint));
+ strcat(strcpy(pipe_name, prefix), endpoint);
+ return pipe_name;
+}
+
static RPC_STATUS rpcrt4_ncacn_np_open(RpcConnection* Connection)
{
RpcConnection_np *npc = (RpcConnection_np *) Connection;
DWORD bufLen = sizeof(ComputerName)/sizeof(ComputerName[0]);
RPC_STATUS r;
LPSTR pname;
+ LPSTR NetworkAddr;
INT size;
/* already connected? */
}
else
{
+ NetworkAddr = Connection->NetworkAddr;
+ if (NetworkAddr[0] == '\\' && NetworkAddr[1] == '\\')
+ NetworkAddr += 2;
+
if (GetComputerNameA(ComputerName, &bufLen))
{
- if (stricmp(ComputerName, Connection->NetworkAddr) == 0)
+ if (stricmp(ComputerName, NetworkAddr) == 0)
{
bUseLocalName = TRUE;
size += strlen(local);
else
{
bUseLocalName = FALSE;
- size += strlen(Connection->NetworkAddr);
+ size += strlen(NetworkAddr);
}
}
else
{
bUseLocalName = FALSE;
- size += strlen(Connection->NetworkAddr);
+ size += strlen(NetworkAddr);
}
}
if (bUseLocalName)
strcat(pname, local);
else
- strcat(pname, Connection->NetworkAddr);
+ strcat(pname, NetworkAddr);
strcat(pname, Connection->Endpoint);
r = rpcrt4_conn_open_pipe(Connection, pname, TRUE);
I_RpcFree(pname);
static RPC_STATUS rpcrt4_ncacn_np_handoff(RpcConnection *old_conn, RpcConnection *new_conn)
{
+ DWORD len = MAX_COMPUTERNAME_LENGTH + 1;
RPC_STATUS status;
LPSTR pname;
static const char prefix[] = "\\\\.";
status = rpcrt4_conn_create_pipe(old_conn, pname);
I_RpcFree(pname);
+ /* Store the local computer name as the NetworkAddr for ncacn_np as long as
+ * we don't support named pipes over the network. */
+ FIXME("Using local computer name as NetworkAddr\n");
+ new_conn->NetworkAddr = HeapAlloc(GetProcessHeap(), 0, len);
+ if (!GetComputerNameA(new_conn->NetworkAddr, &len))
+ {
+ ERR("Failed to retrieve the computer name, error %u\n", GetLastError());
+ return RPC_S_OUT_OF_RESOURCES;
+ }
+
+ return status;
+}
+
+static RPC_STATUS is_pipe_listening(const char *pipe_name)
+{
+ return WaitNamedPipeA(pipe_name, 1) ? RPC_S_OK : RPC_S_NOT_LISTENING;
+}
+
+static RPC_STATUS rpcrt4_ncacn_np_is_server_listening(const char *endpoint)
+{
+ char *pipe_name;
+ RPC_STATUS status;
+
+ pipe_name = ncacn_pipe_name(endpoint);
+ status = is_pipe_listening(pipe_name);
+ I_RpcFree(pipe_name);
+ return status;
+}
+
+static RPC_STATUS rpcrt4_ncalrpc_np_is_server_listening(const char *endpoint)
+{
+ char *pipe_name;
+ RPC_STATUS status;
+
+ pipe_name = ncalrpc_pipe_name(endpoint);
+ status = is_pipe_listening(pipe_name);
+ I_RpcFree(pipe_name);
return status;
}
static RPC_STATUS rpcrt4_ncalrpc_handoff(RpcConnection *old_conn, RpcConnection *new_conn)
{
+ DWORD len = MAX_COMPUTERNAME_LENGTH + 1;
RPC_STATUS status;
LPSTR pname;
static const char prefix[] = "\\\\.\\pipe\\lrpc\\";
strcat(strcpy(pname, prefix), old_conn->Endpoint);
status = rpcrt4_conn_create_pipe(old_conn, pname);
I_RpcFree(pname);
-
+
+ /* Store the local computer name as the NetworkAddr for ncalrpc. */
+ new_conn->NetworkAddr = HeapAlloc(GetProcessHeap(), 0, len);
+ if (!GetComputerNameA(new_conn->NetworkAddr, &len))
+ {
+ ERR("Failed to retrieve the computer name, error %u\n", GetLastError());
+ return RPC_S_OUT_OF_RESOURCES;
+ }
+
return status;
}
else
{
ERR("unexpected protocol family %d\n", ai->ai_family);
+ freeaddrinfo(ai);
return 0;
}
ERR("Failed to accept a TCP connection: error %d\n", ret);
return RPC_S_OUT_OF_RESOURCES;
}
+
nonblocking = 1;
ioctlsocket(ret, FIONBIO, &nonblocking);
client->sock = ret;
- TRACE("Accepted a new TCP connection\n");
+
+ client->common.NetworkAddr = HeapAlloc(GetProcessHeap(), 0, INET6_ADDRSTRLEN);
+ ret = getnameinfo((struct sockaddr*)&address, addrsize, client->common.NetworkAddr, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST);
+ if (ret != 0)
+ {
+ ERR("Failed to retrieve the IP address, error %d\n", ret);
+ return RPC_S_OUT_OF_RESOURCES;
+ }
+
+ TRACE("Accepted a new TCP connection from %s\n", client->common.NetworkAddr);
return RPC_S_OK;
}
return -1;
else if (r > 0)
bytes_read += r;
+ else if (errno == EINTR)
+ continue;
else if (errno != EAGAIN)
{
WARN("recv() failed: %s\n", strerror(errno));
int r = send(tcpc->sock, (const char *)buffer + bytes_written, count - bytes_written, 0);
if (r >= 0)
bytes_written += r;
+ else if (errno == EINTR)
+ continue;
else if (errno != EAGAIN)
return -1;
else
rpcrt4_sock_wait_cancel(tcpc);
}
+static RPC_STATUS rpcrt4_conn_tcp_is_server_listening(const char *endpoint)
+{
+ FIXME("\n");
+ return RPC_S_ACCESS_DENIED;
+}
+
static int rpcrt4_conn_tcp_wait_for_incoming_data(RpcConnection *Connection)
{
RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
LONG refs;
HANDLE completion_event;
WORD async_result;
- INTERNET_BUFFERSA inet_buffers;
+ INTERNET_BUFFERSW inet_buffers;
CRITICAL_SECTION cs;
} RpcHttpAsyncData;
TRACE("async data = %p\n", httpc->async_data);
httpc->cancel_event = CreateEventW(NULL, FALSE, FALSE, NULL);
httpc->async_data->refs = 1;
- httpc->async_data->inet_buffers.dwStructSize = sizeof(INTERNET_BUFFERSA);
+ httpc->async_data->inet_buffers.dwStructSize = sizeof(INTERNET_BUFFERSW);
httpc->async_data->inet_buffers.lpvBuffer = NULL;
InitializeCriticalSection(&httpc->async_data->cs);
httpc->async_data->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": RpcHttpAsyncData.cs");
return RPC_S_OK;
}
+static int rpcrt4_http_async_read(HINTERNET req, RpcHttpAsyncData *async_data, HANDLE cancel_event,
+ void *buffer, unsigned int count)
+{
+ char *buf = buffer;
+ BOOL ret;
+ unsigned int bytes_left = count;
+ RPC_STATUS status = RPC_S_OK;
+
+ async_data->inet_buffers.lpvBuffer = HeapAlloc(GetProcessHeap(), 0, count);
+
+ while (bytes_left)
+ {
+ async_data->inet_buffers.dwBufferLength = bytes_left;
+ prepare_async_request(async_data);
+ ret = InternetReadFileExW(req, &async_data->inet_buffers, IRF_ASYNC, 0);
+ status = wait_async_request(async_data, ret, cancel_event);
+ if (status != RPC_S_OK)
+ {
+ if (status == RPC_S_CALL_CANCELLED)
+ TRACE("call cancelled\n");
+ break;
+ }
+
+ if (!async_data->inet_buffers.dwBufferLength)
+ break;
+ memcpy(buf, async_data->inet_buffers.lpvBuffer,
+ async_data->inet_buffers.dwBufferLength);
+
+ bytes_left -= async_data->inet_buffers.dwBufferLength;
+ buf += async_data->inet_buffers.dwBufferLength;
+ }
+
+ HeapFree(GetProcessHeap(), 0, async_data->inet_buffers.lpvBuffer);
+ async_data->inet_buffers.lpvBuffer = NULL;
+
+ TRACE("%p %p %u -> %u\n", req, buffer, count, status);
+ return status == RPC_S_OK ? count : -1;
+}
+
static RPC_STATUS send_echo_request(HINTERNET req, RpcHttpAsyncData *async_data, HANDLE cancel_event)
{
- DWORD bytes_read;
BYTE buf[20];
BOOL ret;
RPC_STATUS status;
status = rpcrt4_http_check_response(req);
if (status != RPC_S_OK) return status;
- InternetReadFile(req, buf, sizeof(buf), &bytes_read);
+ rpcrt4_http_async_read(req, async_data, cancel_event, buf, sizeof(buf));
/* FIXME: do something with retrieved data */
return RPC_S_OK;
}
+static RPC_STATUS insert_content_length_header(HINTERNET request, DWORD len)
+{
+ static const WCHAR fmtW[] =
+ {'C','o','n','t','e','n','t','-','L','e','n','g','t','h',':',' ','%','u','\r','\n',0};
+ WCHAR header[sizeof(fmtW) / sizeof(fmtW[0]) + 10];
+
+ sprintfW(header, fmtW, len);
+ if ((HttpAddRequestHeadersW(request, header, -1, HTTP_ADDREQ_FLAG_REPLACE | HTTP_ADDREQ_FLAG_ADD))) return RPC_S_OK;
+ return RPC_S_SERVER_UNAVAILABLE;
+}
+
/* prepare the in pipe for use by RPC packets */
static RPC_STATUS rpcrt4_http_prepare_in_pipe(HINTERNET in_request, RpcHttpAsyncData *async_data, HANDLE cancel_event,
const UUID *connection_uuid, const UUID *in_pipe_uuid,
buffers_in.dwStructSize = sizeof(buffers_in);
/* FIXME: get this from the registry */
buffers_in.dwBufferTotal = 1024 * 1024 * 1024; /* 1Gb */
+ status = insert_content_length_header(in_request, buffers_in.dwBufferTotal);
+ if (status != RPC_S_OK) return status;
+
prepare_async_request(async_data);
ret = HttpSendRequestExW(in_request, &buffers_in, NULL, 0, 0);
status = wait_async_request(async_data, ret, cancel_event);
return RPC_S_OK;
}
-static RPC_STATUS rpcrt4_http_read_http_packet(HINTERNET request, RpcPktHdr *hdr, BYTE **data)
+static RPC_STATUS rpcrt4_http_read_http_packet(HINTERNET request, RpcHttpAsyncData *async_data,
+ HANDLE cancel_event, RpcPktHdr *hdr, BYTE **data)
{
- BOOL ret;
- DWORD bytes_read;
unsigned short data_len;
+ unsigned int size;
- ret = InternetReadFile(request, hdr, sizeof(hdr->common), &bytes_read);
- if (!ret)
+ if (rpcrt4_http_async_read(request, async_data, cancel_event, hdr, sizeof(hdr->common)) < 0)
return RPC_S_SERVER_UNAVAILABLE;
if (hdr->common.ptype != PKT_HTTP || hdr->common.frag_len < sizeof(hdr->http))
{
return RPC_S_PROTOCOL_ERROR;
}
- ret = InternetReadFile(request, &hdr->common + 1, sizeof(hdr->http) - sizeof(hdr->common), &bytes_read);
- if (!ret)
+ size = sizeof(hdr->http) - sizeof(hdr->common);
+ if (rpcrt4_http_async_read(request, async_data, cancel_event, &hdr->common + 1, size) < 0)
return RPC_S_SERVER_UNAVAILABLE;
data_len = hdr->common.frag_len - sizeof(hdr->http);
*data = HeapAlloc(GetProcessHeap(), 0, data_len);
if (!*data)
return RPC_S_OUT_OF_RESOURCES;
- ret = InternetReadFile(request, *data, data_len, &bytes_read);
- if (!ret)
+ if (rpcrt4_http_async_read(request, async_data, cancel_event, *data, data_len) < 0)
{
HeapFree(GetProcessHeap(), 0, *data);
return RPC_S_SERVER_UNAVAILABLE;
if (!RPCRT4_IsValidHttpPacket(hdr, *data, data_len))
{
ERR("invalid http packet\n");
+ HeapFree(GetProcessHeap(), 0, *data);
return RPC_S_PROTOCOL_ERROR;
}
BYTE *data_from_server;
RpcPktHdr pkt_from_server;
ULONG field1, field3;
- DWORD bytes_read;
BYTE buf[20];
if (!authorized)
if (status != RPC_S_OK) return status;
}
else
- InternetReadFile(out_request, buf, sizeof(buf), &bytes_read);
+ rpcrt4_http_async_read(out_request, async_data, cancel_event, buf, sizeof(buf));
hdr = RPCRT4_BuildHttpConnectHeader(TRUE, connection_uuid, out_pipe_uuid, NULL);
if (!hdr) return RPC_S_OUT_OF_RESOURCES;
+ status = insert_content_length_header(out_request, hdr->common.frag_len);
+ if (status != RPC_S_OK)
+ {
+ RPCRT4_FreeHeader(hdr);
+ return status;
+ }
+
TRACE("sending HTTP connect header to server\n");
prepare_async_request(async_data);
ret = HttpSendRequestW(out_request, NULL, 0, hdr, hdr->common.frag_len);
status = rpcrt4_http_check_response(out_request);
if (status != RPC_S_OK) return status;
- status = rpcrt4_http_read_http_packet(out_request, &pkt_from_server,
- &data_from_server);
+ status = rpcrt4_http_read_http_packet(out_request, async_data, cancel_event,
+ &pkt_from_server, &data_from_server);
if (status != RPC_S_OK) return status;
status = RPCRT4_ParseHttpPrepareHeader1(&pkt_from_server, data_from_server,
&field1);
for (;;)
{
- status = rpcrt4_http_read_http_packet(out_request, &pkt_from_server,
- &data_from_server);
+ status = rpcrt4_http_read_http_packet(out_request, async_data, cancel_event,
+ &pkt_from_server, &data_from_server);
if (status != RPC_S_OK) return status;
if (pkt_from_server.http.flags != 0x0001) break;
return status;
}
-static void drain_content(HINTERNET request)
+static void drain_content(HINTERNET request, RpcHttpAsyncData *async_data, HANDLE cancel_event)
{
DWORD count, len = 0, size = sizeof(len);
char buf[2048];
for (;;)
{
count = min(sizeof(buf), len);
- if (!InternetReadFile(request, buf, count, &count) || !count) return;
+ if (rpcrt4_http_async_read(request, async_data, cancel_event, buf, count) <= 0) return;
len -= count;
}
}
status = rpcrt4_http_check_response(request);
if (status != RPC_S_OK && status != ERROR_ACCESS_DENIED) break;
- drain_content(request);
+ drain_content(request, httpc->async_data, httpc->cancel_event);
}
if (info->scheme != RPC_C_HTTP_AUTHN_SCHEME_BASIC)
- HttpAddRequestHeadersW(request, authW, -1, HTTP_ADDREQ_FLAG_REPLACE);
+ HttpAddRequestHeadersW(request, authW, -1, HTTP_ADDREQ_FLAG_REPLACE | HTTP_ADDREQ_FLAG_ADD);
destroy_authinfo(info);
return status;
}
-static RPC_STATUS insert_cookie_header(HINTERNET request, const WCHAR *value)
-{
- static const WCHAR cookieW[] = {'C','o','o','k','i','e',':',' '};
- WCHAR *header, *ptr;
- int len;
- RPC_STATUS status = RPC_S_SERVER_UNAVAILABLE;
-
- if (!value) return RPC_S_OK;
-
- len = strlenW(value);
- if ((header = HeapAlloc(GetProcessHeap(), 0, sizeof(cookieW) + (len + 3) * sizeof(WCHAR))))
- {
- memcpy(header, cookieW, sizeof(cookieW));
- ptr = header + sizeof(cookieW) / sizeof(cookieW[0]);
- memcpy(ptr, value, len * sizeof(WCHAR));
- ptr[len++] = '\r';
- ptr[len++] = '\n';
- ptr[len] = 0;
- if ((HttpAddRequestHeadersW(request, header, -1, HTTP_ADDREQ_FLAG_ADD_IF_NEW))) status = RPC_S_OK;
- HeapFree(GetProcessHeap(), 0, header);
- }
- return status;
-}
-
static BOOL has_credentials(RpcConnection_http *httpc)
{
RPC_HTTP_TRANSPORT_CREDENTIALS_W *creds;
(httpc->common.QOS->qos->u.HttpCredentials->Flags & RPC_C_HTTP_FLAG_USE_SSL);
}
+static RPC_STATUS set_auth_cookie(RpcConnection_http *httpc, const WCHAR *value)
+{
+ static WCHAR httpW[] = {'h','t','t','p',0};
+ static WCHAR httpsW[] = {'h','t','t','p','s',0};
+ URL_COMPONENTSW uc;
+ DWORD len;
+ WCHAR *url;
+ BOOL ret;
+
+ if (!value) return RPC_S_OK;
+
+ uc.dwStructSize = sizeof(uc);
+ uc.lpszScheme = is_secure(httpc) ? httpsW : httpW;
+ uc.dwSchemeLength = 0;
+ uc.lpszHostName = httpc->servername;
+ uc.dwHostNameLength = 0;
+ uc.nPort = 0;
+ uc.lpszUserName = NULL;
+ uc.dwUserNameLength = 0;
+ uc.lpszPassword = NULL;
+ uc.dwPasswordLength = 0;
+ uc.lpszUrlPath = NULL;
+ uc.dwUrlPathLength = 0;
+ uc.lpszExtraInfo = NULL;
+ uc.dwExtraInfoLength = 0;
+
+ if (!InternetCreateUrlW(&uc, 0, NULL, &len) && (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
+ return RPC_S_SERVER_UNAVAILABLE;
+
+ if (!(url = HeapAlloc(GetProcessHeap(), 0, len))) return RPC_S_OUT_OF_MEMORY;
+
+ len = len / sizeof(WCHAR) - 1;
+ if (!InternetCreateUrlW(&uc, 0, url, &len))
+ {
+ HeapFree(GetProcessHeap(), 0, url);
+ return RPC_S_SERVER_UNAVAILABLE;
+ }
+
+ ret = InternetSetCookieW(url, NULL, value);
+ HeapFree(GetProcessHeap(), 0, url);
+ if (!ret) return RPC_S_SERVER_UNAVAILABLE;
+
+ return RPC_S_OK;
+}
+
static RPC_STATUS rpcrt4_ncacn_http_open(RpcConnection* Connection)
{
RpcConnection_http *httpc = (RpcConnection_http *)Connection;
httpc->async_data->completion_event = CreateEventW(NULL, FALSE, FALSE, NULL);
- status = UuidCreate(&httpc->connection_uuid);
- status = UuidCreate(&httpc->in_pipe_uuid);
- status = UuidCreate(&httpc->out_pipe_uuid);
+ UuidCreate(&httpc->connection_uuid);
+ UuidCreate(&httpc->in_pipe_uuid);
+ UuidCreate(&httpc->out_pipe_uuid);
status = rpcrt4_http_internet_connect(httpc);
if (status != RPC_S_OK)
if (secure) flags |= INTERNET_FLAG_SECURE;
if (credentials) flags |= INTERNET_FLAG_NO_AUTH;
+ status = set_auth_cookie(httpc, Connection->CookieAuth);
+ if (status != RPC_S_OK)
+ {
+ HeapFree(GetProcessHeap(), 0, url);
+ return status;
+ }
httpc->in_request = HttpOpenRequestW(httpc->session, wszVerbIn, url, NULL, NULL, wszAcceptTypes,
flags, (DWORD_PTR)httpc->async_data);
if (!httpc->in_request)
HeapFree(GetProcessHeap(), 0, url);
return RPC_S_SERVER_UNAVAILABLE;
}
- status = insert_cookie_header(httpc->in_request, Connection->CookieAuth);
- if (status != RPC_S_OK)
- {
- HeapFree(GetProcessHeap(), 0, url);
- return status;
- }
+
if (credentials)
{
status = authorize_request(httpc, httpc->in_request);
HeapFree(GetProcessHeap(), 0, url);
return status;
}
- drain_content(httpc->in_request);
+ drain_content(httpc->in_request, httpc->async_data, httpc->cancel_event);
}
httpc->out_request = HttpOpenRequestW(httpc->session, wszVerbOut, url, NULL, NULL, wszAcceptTypes,
ERR("HttpOpenRequestW failed with error %d\n", GetLastError());
return RPC_S_SERVER_UNAVAILABLE;
}
- status = insert_cookie_header(httpc->out_request, Connection->CookieAuth);
- if (status != RPC_S_OK)
- return status;
if (credentials)
{
void *buffer, unsigned int count)
{
RpcConnection_http *httpc = (RpcConnection_http *) Connection;
- char *buf = buffer;
- BOOL ret;
- unsigned int bytes_left = count;
- RPC_STATUS status = RPC_S_OK;
-
- httpc->async_data->inet_buffers.lpvBuffer = HeapAlloc(GetProcessHeap(), 0, count);
-
- while (bytes_left)
- {
- httpc->async_data->inet_buffers.dwBufferLength = bytes_left;
- prepare_async_request(httpc->async_data);
- ret = InternetReadFileExA(httpc->out_request, &httpc->async_data->inet_buffers, IRF_ASYNC, 0);
- status = wait_async_request(httpc->async_data, ret, httpc->cancel_event);
- if(status != RPC_S_OK) {
- if(status == RPC_S_CALL_CANCELLED)
- TRACE("call cancelled\n");
- break;
- }
-
- if(!httpc->async_data->inet_buffers.dwBufferLength)
- break;
- memcpy(buf, httpc->async_data->inet_buffers.lpvBuffer,
- httpc->async_data->inet_buffers.dwBufferLength);
-
- bytes_left -= httpc->async_data->inet_buffers.dwBufferLength;
- buf += httpc->async_data->inet_buffers.dwBufferLength;
- }
-
- HeapFree(GetProcessHeap(), 0, httpc->async_data->inet_buffers.lpvBuffer);
- httpc->async_data->inet_buffers.lpvBuffer = NULL;
-
- TRACE("%p %p %u -> %u\n", httpc->out_request, buffer, count, status);
- return status == RPC_S_OK ? count : -1;
+ return rpcrt4_http_async_read(httpc->out_request, httpc->async_data, httpc->cancel_event, buffer, count);
}
static RPC_STATUS rpcrt4_ncacn_http_receive_fragment(RpcConnection *Connection, RpcPktHdr **Header, void **Payload)
SetEvent(httpc->cancel_event);
}
+static RPC_STATUS rpcrt4_ncacn_http_is_server_listening(const char *endpoint)
+{
+ FIXME("\n");
+ return RPC_S_ACCESS_DENIED;
+}
+
static int rpcrt4_ncacn_http_wait_for_incoming_data(RpcConnection *Connection)
{
RpcConnection_http *httpc = (RpcConnection_http *) Connection;
rpcrt4_conn_np_write,
rpcrt4_conn_np_close,
rpcrt4_conn_np_cancel_call,
+ rpcrt4_ncacn_np_is_server_listening,
rpcrt4_conn_np_wait_for_incoming_data,
rpcrt4_ncacn_np_get_top_of_tower,
rpcrt4_ncacn_np_parse_top_of_tower,
rpcrt4_conn_np_write,
rpcrt4_conn_np_close,
rpcrt4_conn_np_cancel_call,
+ rpcrt4_ncalrpc_np_is_server_listening,
rpcrt4_conn_np_wait_for_incoming_data,
rpcrt4_ncalrpc_get_top_of_tower,
rpcrt4_ncalrpc_parse_top_of_tower,
rpcrt4_conn_tcp_write,
rpcrt4_conn_tcp_close,
rpcrt4_conn_tcp_cancel_call,
+ rpcrt4_conn_tcp_is_server_listening,
rpcrt4_conn_tcp_wait_for_incoming_data,
rpcrt4_ncacn_ip_tcp_get_top_of_tower,
rpcrt4_ncacn_ip_tcp_parse_top_of_tower,
rpcrt4_ncacn_http_write,
rpcrt4_ncacn_http_close,
rpcrt4_ncacn_http_cancel_call,
+ rpcrt4_ncacn_http_is_server_listening,
rpcrt4_ncacn_http_wait_for_incoming_data,
rpcrt4_ncacn_http_get_top_of_tower,
rpcrt4_ncacn_http_parse_top_of_tower,
return RPC_S_OK;
}
+RPC_STATUS RPCRT4_IsServerListening(const char *protseq, const char *endpoint)
+{
+ const struct connection_ops *ops;
+
+ ops = rpcrt4_get_conn_protseq_ops(protseq);
+ if (!ops)
+ {
+ FIXME("not supported for protseq %s\n", protseq);
+ return RPC_S_INVALID_BINDING;
+ }
+
+ return ops->is_server_listening(endpoint);
+}
+
RPC_STATUS RpcTransport_GetTopOfTower(unsigned char *tower_data,
size_t *tower_size,
const char *protseq,