Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenrpc_transport.c
Go to the documentation of this file.
00001 /* 00002 * RPC transport layer 00003 * 00004 * Copyright 2001 Ove Kåven, TransGaming Technologies 00005 * Copyright 2003 Mike Hearn 00006 * Copyright 2004 Filip Navara 00007 * Copyright 2006 Mike McCormack 00008 * Copyright 2006 Damjan Jovanovic 00009 * 00010 * This library is free software; you can redistribute it and/or 00011 * modify it under the terms of the GNU Lesser General Public 00012 * License as published by the Free Software Foundation; either 00013 * version 2.1 of the License, or (at your option) any later version. 00014 * 00015 * This library is distributed in the hope that it will be useful, 00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00018 * Lesser General Public License for more details. 00019 * 00020 * You should have received a copy of the GNU Lesser General Public 00021 * License along with this library; if not, write to the Free Software 00022 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00023 * 00024 */ 00025 00026 #include "config.h" 00027 00028 #include <stdarg.h> 00029 #include <stdio.h> 00030 #include <string.h> 00031 #include <assert.h> 00032 #include <stdlib.h> 00033 #include <sys/types.h> 00034 00035 #if defined(__MINGW32__) || defined (_MSC_VER) 00036 # include <ws2tcpip.h> 00037 # ifndef EADDRINUSE 00038 # define EADDRINUSE WSAEADDRINUSE 00039 # endif 00040 # ifndef EAGAIN 00041 # define EAGAIN WSAEWOULDBLOCK 00042 # endif 00043 # undef errno 00044 # define errno WSAGetLastError() 00045 #else 00046 # include <errno.h> 00047 # ifdef HAVE_UNISTD_H 00048 # include <unistd.h> 00049 # endif 00050 # include <fcntl.h> 00051 # ifdef HAVE_SYS_SOCKET_H 00052 # include <sys/socket.h> 00053 # endif 00054 # ifdef HAVE_NETINET_IN_H 00055 # include <netinet/in.h> 00056 # endif 00057 # ifdef HAVE_NETINET_TCP_H 00058 # include <netinet/tcp.h> 00059 # endif 00060 # ifdef HAVE_ARPA_INET_H 00061 # include <arpa/inet.h> 00062 # endif 00063 # ifdef HAVE_NETDB_H 00064 # include <netdb.h> 00065 # endif 00066 # ifdef HAVE_SYS_POLL_H 00067 # include <sys/poll.h> 00068 # endif 00069 # ifdef HAVE_SYS_FILIO_H 00070 # include <sys/filio.h> 00071 # endif 00072 # ifdef HAVE_SYS_IOCTL_H 00073 # include <sys/ioctl.h> 00074 # endif 00075 # define closesocket close 00076 # define ioctlsocket ioctl 00077 #endif /* defined(__MINGW32__) || defined (_MSC_VER) */ 00078 00079 #include "windef.h" 00080 #include "winbase.h" 00081 #include "winnls.h" 00082 #include "winerror.h" 00083 #include "wininet.h" 00084 #include "winternl.h" 00085 #include "wine/unicode.h" 00086 00087 #include "rpc.h" 00088 #include "rpcndr.h" 00089 00090 #include "wine/debug.h" 00091 00092 #include "rpc_binding.h" 00093 #include "rpc_assoc.h" 00094 #include "rpc_message.h" 00095 #include "rpc_server.h" 00096 #include "epm_towers.h" 00097 00098 #ifndef SOL_TCP 00099 # define SOL_TCP IPPROTO_TCP 00100 #endif 00101 00102 #define DEFAULT_NCACN_HTTP_TIMEOUT (60 * 1000) 00103 00104 WINE_DEFAULT_DEBUG_CHANNEL(rpc); 00105 00106 static RPC_STATUS RPCRT4_SpawnConnection(RpcConnection** Connection, RpcConnection* OldConnection); 00107 00108 /**** ncacn_np support ****/ 00109 00110 typedef struct _RpcConnection_np 00111 { 00112 RpcConnection common; 00113 HANDLE pipe; 00114 OVERLAPPED ovl; 00115 BOOL listening; 00116 } RpcConnection_np; 00117 00118 static RpcConnection *rpcrt4_conn_np_alloc(void) 00119 { 00120 RpcConnection_np *npc = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcConnection_np)); 00121 if (npc) 00122 { 00123 npc->pipe = NULL; 00124 memset(&npc->ovl, 0, sizeof(npc->ovl)); 00125 npc->listening = FALSE; 00126 } 00127 return &npc->common; 00128 } 00129 00130 static RPC_STATUS rpcrt4_conn_listen_pipe(RpcConnection_np *npc) 00131 { 00132 if (npc->listening) 00133 return RPC_S_OK; 00134 00135 npc->listening = TRUE; 00136 for (;;) 00137 { 00138 if (ConnectNamedPipe(npc->pipe, &npc->ovl)) 00139 return RPC_S_OK; 00140 00141 switch(GetLastError()) 00142 { 00143 case ERROR_PIPE_CONNECTED: 00144 SetEvent(npc->ovl.hEvent); 00145 return RPC_S_OK; 00146 case ERROR_IO_PENDING: 00147 /* will be completed in rpcrt4_protseq_np_wait_for_new_connection */ 00148 return RPC_S_OK; 00149 case ERROR_NO_DATA_DETECTED: 00150 /* client has disconnected, retry */ 00151 DisconnectNamedPipe( npc->pipe ); 00152 break; 00153 default: 00154 npc->listening = FALSE; 00155 WARN("Couldn't ConnectNamedPipe (error was %d)\n", GetLastError()); 00156 return RPC_S_OUT_OF_RESOURCES; 00157 } 00158 } 00159 } 00160 00161 static RPC_STATUS rpcrt4_conn_create_pipe(RpcConnection *Connection, LPCSTR pname) 00162 { 00163 RpcConnection_np *npc = (RpcConnection_np *) Connection; 00164 TRACE("listening on %s\n", pname); 00165 00166 npc->pipe = CreateNamedPipeA(pname, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, 00167 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, 00168 PIPE_UNLIMITED_INSTANCES, 00169 RPC_MAX_PACKET_SIZE, RPC_MAX_PACKET_SIZE, 5000, NULL); 00170 if (npc->pipe == INVALID_HANDLE_VALUE) { 00171 WARN("CreateNamedPipe failed with error %d\n", GetLastError()); 00172 if (GetLastError() == ERROR_FILE_EXISTS) 00173 return RPC_S_DUPLICATE_ENDPOINT; 00174 else 00175 return RPC_S_CANT_CREATE_ENDPOINT; 00176 } 00177 00178 memset(&npc->ovl, 0, sizeof(npc->ovl)); 00179 npc->ovl.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); 00180 00181 /* Note: we don't call ConnectNamedPipe here because it must be done in the 00182 * server thread as the thread must be alertable */ 00183 return RPC_S_OK; 00184 } 00185 00186 static RPC_STATUS rpcrt4_conn_open_pipe(RpcConnection *Connection, LPCSTR pname, BOOL wait) 00187 { 00188 RpcConnection_np *npc = (RpcConnection_np *) Connection; 00189 HANDLE pipe; 00190 DWORD err, dwMode; 00191 00192 TRACE("connecting to %s\n", pname); 00193 00194 while (TRUE) { 00195 DWORD dwFlags = 0; 00196 if (Connection->QOS) 00197 { 00198 dwFlags = SECURITY_SQOS_PRESENT; 00199 switch (Connection->QOS->qos->ImpersonationType) 00200 { 00201 case RPC_C_IMP_LEVEL_DEFAULT: 00202 /* FIXME: what to do here? */ 00203 break; 00204 case RPC_C_IMP_LEVEL_ANONYMOUS: 00205 dwFlags |= SECURITY_ANONYMOUS; 00206 break; 00207 case RPC_C_IMP_LEVEL_IDENTIFY: 00208 dwFlags |= SECURITY_IDENTIFICATION; 00209 break; 00210 case RPC_C_IMP_LEVEL_IMPERSONATE: 00211 dwFlags |= SECURITY_IMPERSONATION; 00212 break; 00213 case RPC_C_IMP_LEVEL_DELEGATE: 00214 dwFlags |= SECURITY_DELEGATION; 00215 break; 00216 } 00217 if (Connection->QOS->qos->IdentityTracking == RPC_C_QOS_IDENTITY_DYNAMIC) 00218 dwFlags |= SECURITY_CONTEXT_TRACKING; 00219 } 00220 pipe = CreateFileA(pname, GENERIC_READ|GENERIC_WRITE, 0, NULL, 00221 OPEN_EXISTING, dwFlags, 0); 00222 if (pipe != INVALID_HANDLE_VALUE) break; 00223 err = GetLastError(); 00224 if (err == ERROR_PIPE_BUSY) { 00225 TRACE("connection failed, error=%x\n", err); 00226 return RPC_S_SERVER_TOO_BUSY; 00227 } else if (err == ERROR_BAD_NETPATH) { 00228 TRACE("connection failed, error=%x\n", err); 00229 return RPC_S_SERVER_UNAVAILABLE; 00230 } 00231 if (!wait || !WaitNamedPipeA(pname, NMPWAIT_WAIT_FOREVER)) { 00232 err = GetLastError(); 00233 WARN("connection failed, error=%x\n", err); 00234 return RPC_S_SERVER_UNAVAILABLE; 00235 } 00236 } 00237 00238 /* success */ 00239 memset(&npc->ovl, 0, sizeof(npc->ovl)); 00240 /* pipe is connected; change to message-read mode. */ 00241 dwMode = PIPE_READMODE_MESSAGE; 00242 SetNamedPipeHandleState(pipe, &dwMode, NULL, NULL); 00243 npc->ovl.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); 00244 npc->pipe = pipe; 00245 00246 return RPC_S_OK; 00247 } 00248 00249 static RPC_STATUS rpcrt4_ncalrpc_open(RpcConnection* Connection) 00250 { 00251 RpcConnection_np *npc = (RpcConnection_np *) Connection; 00252 static const char prefix[] = "\\\\.\\pipe\\lrpc\\"; 00253 RPC_STATUS r; 00254 LPSTR pname; 00255 00256 /* already connected? */ 00257 if (npc->pipe) 00258 return RPC_S_OK; 00259 00260 /* protseq=ncalrpc: supposed to use NT LPC ports, 00261 * but we'll implement it with named pipes for now */ 00262 pname = I_RpcAllocate(strlen(prefix) + strlen(Connection->Endpoint) + 1); 00263 strcat(strcpy(pname, prefix), Connection->Endpoint); 00264 r = rpcrt4_conn_open_pipe(Connection, pname, TRUE); 00265 I_RpcFree(pname); 00266 00267 return r; 00268 } 00269 00270 static RPC_STATUS rpcrt4_protseq_ncalrpc_open_endpoint(RpcServerProtseq* protseq, const char *endpoint) 00271 { 00272 static const char prefix[] = "\\\\.\\pipe\\lrpc\\"; 00273 RPC_STATUS r; 00274 LPSTR pname; 00275 RpcConnection *Connection; 00276 char generated_endpoint[22]; 00277 00278 if (!endpoint) 00279 { 00280 static LONG lrpc_nameless_id; 00281 DWORD process_id = GetCurrentProcessId(); 00282 ULONG id = InterlockedIncrement(&lrpc_nameless_id); 00283 snprintf(generated_endpoint, sizeof(generated_endpoint), 00284 "LRPC%08x.%08x", process_id, id); 00285 endpoint = generated_endpoint; 00286 } 00287 00288 r = RPCRT4_CreateConnection(&Connection, TRUE, protseq->Protseq, NULL, 00289 endpoint, NULL, NULL, NULL); 00290 if (r != RPC_S_OK) 00291 return r; 00292 00293 /* protseq=ncalrpc: supposed to use NT LPC ports, 00294 * but we'll implement it with named pipes for now */ 00295 pname = I_RpcAllocate(strlen(prefix) + strlen(Connection->Endpoint) + 1); 00296 strcat(strcpy(pname, prefix), Connection->Endpoint); 00297 r = rpcrt4_conn_create_pipe(Connection, pname); 00298 I_RpcFree(pname); 00299 00300 EnterCriticalSection(&protseq->cs); 00301 Connection->Next = protseq->conn; 00302 protseq->conn = Connection; 00303 LeaveCriticalSection(&protseq->cs); 00304 00305 return r; 00306 } 00307 00308 static RPC_STATUS rpcrt4_ncacn_np_open(RpcConnection* Connection) 00309 { 00310 RpcConnection_np *npc = (RpcConnection_np *) Connection; 00311 static const char prefix[] = "\\\\"; 00312 static const char local[] ="."; 00313 RPC_STATUS r; 00314 LPSTR pname; 00315 INT size; 00316 00317 /* already connected? */ 00318 if (npc->pipe) 00319 return RPC_S_OK; 00320 00321 /* protseq=ncacn_np: named pipes */ 00322 size = strlen(prefix); 00323 if (Connection->NetworkAddr == NULL || strlen(Connection->NetworkAddr) == 0) 00324 size += strlen(local); 00325 else 00326 size += strlen(Connection->NetworkAddr); 00327 size += strlen(Connection->Endpoint) + 1; 00328 00329 pname = I_RpcAllocate(size); 00330 strcpy(pname, prefix); 00331 if (Connection->NetworkAddr == NULL || strlen(Connection->NetworkAddr) == 0) 00332 strcat(pname, local); 00333 else 00334 strcat(pname, Connection->NetworkAddr); 00335 strcat(pname, Connection->Endpoint); 00336 r = rpcrt4_conn_open_pipe(Connection, pname, TRUE); 00337 I_RpcFree(pname); 00338 00339 return r; 00340 } 00341 00342 static RPC_STATUS rpcrt4_protseq_ncacn_np_open_endpoint(RpcServerProtseq *protseq, const char *endpoint) 00343 { 00344 static const char prefix[] = "\\\\."; 00345 RPC_STATUS r; 00346 LPSTR pname; 00347 RpcConnection *Connection; 00348 char generated_endpoint[21]; 00349 00350 if (!endpoint) 00351 { 00352 static LONG np_nameless_id; 00353 DWORD process_id = GetCurrentProcessId(); 00354 ULONG id = InterlockedExchangeAdd(&np_nameless_id, 1 ); 00355 snprintf(generated_endpoint, sizeof(generated_endpoint), 00356 "\\\\pipe\\\\%08x.%03x", process_id, id); 00357 endpoint = generated_endpoint; 00358 } 00359 00360 r = RPCRT4_CreateConnection(&Connection, TRUE, protseq->Protseq, NULL, 00361 endpoint, NULL, NULL, NULL); 00362 if (r != RPC_S_OK) 00363 return r; 00364 00365 /* protseq=ncacn_np: named pipes */ 00366 pname = I_RpcAllocate(strlen(prefix) + strlen(Connection->Endpoint) + 1); 00367 strcat(strcpy(pname, prefix), Connection->Endpoint); 00368 r = rpcrt4_conn_create_pipe(Connection, pname); 00369 I_RpcFree(pname); 00370 00371 EnterCriticalSection(&protseq->cs); 00372 Connection->Next = protseq->conn; 00373 protseq->conn = Connection; 00374 LeaveCriticalSection(&protseq->cs); 00375 00376 return r; 00377 } 00378 00379 static void rpcrt4_conn_np_handoff(RpcConnection_np *old_npc, RpcConnection_np *new_npc) 00380 { 00381 /* because of the way named pipes work, we'll transfer the connected pipe 00382 * to the child, then reopen the server binding to continue listening */ 00383 00384 new_npc->pipe = old_npc->pipe; 00385 new_npc->ovl = old_npc->ovl; 00386 old_npc->pipe = 0; 00387 memset(&old_npc->ovl, 0, sizeof(old_npc->ovl)); 00388 old_npc->listening = FALSE; 00389 } 00390 00391 static RPC_STATUS rpcrt4_ncacn_np_handoff(RpcConnection *old_conn, RpcConnection *new_conn) 00392 { 00393 RPC_STATUS status; 00394 LPSTR pname; 00395 static const char prefix[] = "\\\\."; 00396 00397 rpcrt4_conn_np_handoff((RpcConnection_np *)old_conn, (RpcConnection_np *)new_conn); 00398 00399 pname = I_RpcAllocate(strlen(prefix) + strlen(old_conn->Endpoint) + 1); 00400 strcat(strcpy(pname, prefix), old_conn->Endpoint); 00401 status = rpcrt4_conn_create_pipe(old_conn, pname); 00402 I_RpcFree(pname); 00403 00404 return status; 00405 } 00406 00407 static RPC_STATUS rpcrt4_ncalrpc_handoff(RpcConnection *old_conn, RpcConnection *new_conn) 00408 { 00409 RPC_STATUS status; 00410 LPSTR pname; 00411 static const char prefix[] = "\\\\.\\pipe\\lrpc\\"; 00412 00413 TRACE("%s\n", old_conn->Endpoint); 00414 00415 rpcrt4_conn_np_handoff((RpcConnection_np *)old_conn, (RpcConnection_np *)new_conn); 00416 00417 pname = I_RpcAllocate(strlen(prefix) + strlen(old_conn->Endpoint) + 1); 00418 strcat(strcpy(pname, prefix), old_conn->Endpoint); 00419 status = rpcrt4_conn_create_pipe(old_conn, pname); 00420 I_RpcFree(pname); 00421 00422 return status; 00423 } 00424 00425 static int rpcrt4_conn_np_read(RpcConnection *Connection, 00426 void *buffer, unsigned int count) 00427 { 00428 RpcConnection_np *npc = (RpcConnection_np *) Connection; 00429 char *buf = buffer; 00430 BOOL ret = TRUE; 00431 unsigned int bytes_left = count; 00432 OVERLAPPED ovl; 00433 00434 ZeroMemory(&ovl, sizeof(ovl)); 00435 ovl.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); 00436 00437 while (bytes_left) 00438 { 00439 DWORD bytes_read; 00440 ret = ReadFile(npc->pipe, buf, bytes_left, &bytes_read, &ovl); 00441 if ((!ret || !bytes_read) && (GetLastError() != ERROR_IO_PENDING)) 00442 break; 00443 ret = GetOverlappedResult(npc->pipe, &ovl, &bytes_read, TRUE); 00444 if (!ret && (GetLastError() != ERROR_MORE_DATA)) 00445 break; 00446 bytes_left -= bytes_read; 00447 buf += bytes_read; 00448 } 00449 CloseHandle(ovl.hEvent); 00450 return ret ? count : -1; 00451 } 00452 00453 static int rpcrt4_conn_np_write(RpcConnection *Connection, 00454 const void *buffer, unsigned int count) 00455 { 00456 RpcConnection_np *npc = (RpcConnection_np *) Connection; 00457 const char *buf = buffer; 00458 BOOL ret = TRUE; 00459 unsigned int bytes_left = count; 00460 OVERLAPPED ovl; 00461 00462 ZeroMemory(&ovl, sizeof(ovl)); 00463 ovl.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); 00464 00465 while (bytes_left) 00466 { 00467 DWORD bytes_written; 00468 ret = WriteFile(npc->pipe, buf, bytes_left, &bytes_written, &ovl); 00469 if ((!ret || !bytes_written) && (GetLastError() != ERROR_IO_PENDING)) 00470 break; 00471 00472 ret = GetOverlappedResult(npc->pipe, &ovl, &bytes_written, TRUE); 00473 if (!ret && (GetLastError() != ERROR_MORE_DATA)) 00474 break; 00475 bytes_left -= bytes_written; 00476 buf += bytes_written; 00477 } 00478 CloseHandle(ovl.hEvent); 00479 return ret ? count : -1; 00480 } 00481 00482 static int rpcrt4_conn_np_close(RpcConnection *Connection) 00483 { 00484 RpcConnection_np *npc = (RpcConnection_np *) Connection; 00485 if (npc->pipe) { 00486 FlushFileBuffers(npc->pipe); 00487 CloseHandle(npc->pipe); 00488 npc->pipe = 0; 00489 } 00490 if (npc->ovl.hEvent) { 00491 CloseHandle(npc->ovl.hEvent); 00492 npc->ovl.hEvent = 0; 00493 } 00494 return 0; 00495 } 00496 00497 static void rpcrt4_conn_np_cancel_call(RpcConnection *Connection) 00498 { 00499 /* FIXME: implement when named pipe writes use overlapped I/O */ 00500 } 00501 00502 static int rpcrt4_conn_np_wait_for_incoming_data(RpcConnection *Connection) 00503 { 00504 /* FIXME: implement when named pipe writes use overlapped I/O */ 00505 return -1; 00506 } 00507 00508 static size_t rpcrt4_ncacn_np_get_top_of_tower(unsigned char *tower_data, 00509 const char *networkaddr, 00510 const char *endpoint) 00511 { 00512 twr_empty_floor_t *smb_floor; 00513 twr_empty_floor_t *nb_floor; 00514 size_t size; 00515 size_t networkaddr_size; 00516 size_t endpoint_size; 00517 00518 TRACE("(%p, %s, %s)\n", tower_data, networkaddr, endpoint); 00519 00520 networkaddr_size = networkaddr ? strlen(networkaddr) + 1 : 1; 00521 endpoint_size = endpoint ? strlen(endpoint) + 1 : 1; 00522 size = sizeof(*smb_floor) + endpoint_size + sizeof(*nb_floor) + networkaddr_size; 00523 00524 if (!tower_data) 00525 return size; 00526 00527 smb_floor = (twr_empty_floor_t *)tower_data; 00528 00529 tower_data += sizeof(*smb_floor); 00530 00531 smb_floor->count_lhs = sizeof(smb_floor->protid); 00532 smb_floor->protid = EPM_PROTOCOL_SMB; 00533 smb_floor->count_rhs = endpoint_size; 00534 00535 if (endpoint) 00536 memcpy(tower_data, endpoint, endpoint_size); 00537 else 00538 tower_data[0] = 0; 00539 tower_data += endpoint_size; 00540 00541 nb_floor = (twr_empty_floor_t *)tower_data; 00542 00543 tower_data += sizeof(*nb_floor); 00544 00545 nb_floor->count_lhs = sizeof(nb_floor->protid); 00546 nb_floor->protid = EPM_PROTOCOL_NETBIOS; 00547 nb_floor->count_rhs = networkaddr_size; 00548 00549 if (networkaddr) 00550 memcpy(tower_data, networkaddr, networkaddr_size); 00551 else 00552 tower_data[0] = 0; 00553 00554 return size; 00555 } 00556 00557 static RPC_STATUS rpcrt4_ncacn_np_parse_top_of_tower(const unsigned char *tower_data, 00558 size_t tower_size, 00559 char **networkaddr, 00560 char **endpoint) 00561 { 00562 const twr_empty_floor_t *smb_floor = (const twr_empty_floor_t *)tower_data; 00563 const twr_empty_floor_t *nb_floor; 00564 00565 TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint); 00566 00567 if (tower_size < sizeof(*smb_floor)) 00568 return EPT_S_NOT_REGISTERED; 00569 00570 tower_data += sizeof(*smb_floor); 00571 tower_size -= sizeof(*smb_floor); 00572 00573 if ((smb_floor->count_lhs != sizeof(smb_floor->protid)) || 00574 (smb_floor->protid != EPM_PROTOCOL_SMB) || 00575 (smb_floor->count_rhs > tower_size) || 00576 (tower_data[smb_floor->count_rhs - 1] != '\0')) 00577 return EPT_S_NOT_REGISTERED; 00578 00579 if (endpoint) 00580 { 00581 *endpoint = I_RpcAllocate(smb_floor->count_rhs); 00582 if (!*endpoint) 00583 return RPC_S_OUT_OF_RESOURCES; 00584 memcpy(*endpoint, tower_data, smb_floor->count_rhs); 00585 } 00586 tower_data += smb_floor->count_rhs; 00587 tower_size -= smb_floor->count_rhs; 00588 00589 if (tower_size < sizeof(*nb_floor)) 00590 return EPT_S_NOT_REGISTERED; 00591 00592 nb_floor = (const twr_empty_floor_t *)tower_data; 00593 00594 tower_data += sizeof(*nb_floor); 00595 tower_size -= sizeof(*nb_floor); 00596 00597 if ((nb_floor->count_lhs != sizeof(nb_floor->protid)) || 00598 (nb_floor->protid != EPM_PROTOCOL_NETBIOS) || 00599 (nb_floor->count_rhs > tower_size) || 00600 (tower_data[nb_floor->count_rhs - 1] != '\0')) 00601 return EPT_S_NOT_REGISTERED; 00602 00603 if (networkaddr) 00604 { 00605 *networkaddr = I_RpcAllocate(nb_floor->count_rhs); 00606 if (!*networkaddr) 00607 { 00608 if (endpoint) 00609 { 00610 I_RpcFree(*endpoint); 00611 *endpoint = NULL; 00612 } 00613 return RPC_S_OUT_OF_RESOURCES; 00614 } 00615 memcpy(*networkaddr, tower_data, nb_floor->count_rhs); 00616 } 00617 00618 return RPC_S_OK; 00619 } 00620 00621 static RPC_STATUS rpcrt4_conn_np_impersonate_client(RpcConnection *conn) 00622 { 00623 RpcConnection_np *npc = (RpcConnection_np *)conn; 00624 BOOL ret; 00625 00626 TRACE("(%p)\n", conn); 00627 00628 if (conn->AuthInfo && SecIsValidHandle(&conn->ctx)) 00629 return RPCRT4_default_impersonate_client(conn); 00630 00631 ret = ImpersonateNamedPipeClient(npc->pipe); 00632 if (!ret) 00633 { 00634 DWORD error = GetLastError(); 00635 WARN("ImpersonateNamedPipeClient failed with error %u\n", error); 00636 switch (error) 00637 { 00638 case ERROR_CANNOT_IMPERSONATE: 00639 return RPC_S_NO_CONTEXT_AVAILABLE; 00640 } 00641 } 00642 return RPC_S_OK; 00643 } 00644 00645 static RPC_STATUS rpcrt4_conn_np_revert_to_self(RpcConnection *conn) 00646 { 00647 BOOL ret; 00648 00649 TRACE("(%p)\n", conn); 00650 00651 if (conn->AuthInfo && SecIsValidHandle(&conn->ctx)) 00652 return RPCRT4_default_revert_to_self(conn); 00653 00654 ret = RevertToSelf(); 00655 if (!ret) 00656 { 00657 WARN("RevertToSelf failed with error %u\n", GetLastError()); 00658 return RPC_S_NO_CONTEXT_AVAILABLE; 00659 } 00660 return RPC_S_OK; 00661 } 00662 00663 typedef struct _RpcServerProtseq_np 00664 { 00665 RpcServerProtseq common; 00666 HANDLE mgr_event; 00667 } RpcServerProtseq_np; 00668 00669 static RpcServerProtseq *rpcrt4_protseq_np_alloc(void) 00670 { 00671 RpcServerProtseq_np *ps = HeapAlloc(GetProcessHeap(), 0, sizeof(*ps)); 00672 if (ps) 00673 ps->mgr_event = CreateEventW(NULL, FALSE, FALSE, NULL); 00674 return &ps->common; 00675 } 00676 00677 static void rpcrt4_protseq_np_signal_state_changed(RpcServerProtseq *protseq) 00678 { 00679 RpcServerProtseq_np *npps = CONTAINING_RECORD(protseq, RpcServerProtseq_np, common); 00680 SetEvent(npps->mgr_event); 00681 } 00682 00683 static void *rpcrt4_protseq_np_get_wait_array(RpcServerProtseq *protseq, void *prev_array, unsigned int *count) 00684 { 00685 HANDLE *objs = prev_array; 00686 RpcConnection_np *conn; 00687 RpcServerProtseq_np *npps = CONTAINING_RECORD(protseq, RpcServerProtseq_np, common); 00688 00689 EnterCriticalSection(&protseq->cs); 00690 00691 /* open and count connections */ 00692 *count = 1; 00693 conn = CONTAINING_RECORD(protseq->conn, RpcConnection_np, common); 00694 while (conn) { 00695 rpcrt4_conn_listen_pipe(conn); 00696 if (conn->ovl.hEvent) 00697 (*count)++; 00698 conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_np, common); 00699 } 00700 00701 /* make array of connections */ 00702 if (objs) 00703 objs = HeapReAlloc(GetProcessHeap(), 0, objs, *count*sizeof(HANDLE)); 00704 else 00705 objs = HeapAlloc(GetProcessHeap(), 0, *count*sizeof(HANDLE)); 00706 if (!objs) 00707 { 00708 ERR("couldn't allocate objs\n"); 00709 LeaveCriticalSection(&protseq->cs); 00710 return NULL; 00711 } 00712 00713 objs[0] = npps->mgr_event; 00714 *count = 1; 00715 conn = CONTAINING_RECORD(protseq->conn, RpcConnection_np, common); 00716 while (conn) { 00717 if ((objs[*count] = conn->ovl.hEvent)) 00718 (*count)++; 00719 conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_np, common); 00720 } 00721 LeaveCriticalSection(&protseq->cs); 00722 return objs; 00723 } 00724 00725 static void rpcrt4_protseq_np_free_wait_array(RpcServerProtseq *protseq, void *array) 00726 { 00727 HeapFree(GetProcessHeap(), 0, array); 00728 } 00729 00730 static int rpcrt4_protseq_np_wait_for_new_connection(RpcServerProtseq *protseq, unsigned int count, void *wait_array) 00731 { 00732 HANDLE b_handle; 00733 HANDLE *objs = wait_array; 00734 DWORD res; 00735 RpcConnection *cconn; 00736 RpcConnection_np *conn; 00737 00738 if (!objs) 00739 return -1; 00740 00741 do 00742 { 00743 /* an alertable wait isn't strictly necessary, but due to our 00744 * overlapped I/O implementation in Wine we need to free some memory 00745 * by the file user APC being called, even if no completion routine was 00746 * specified at the time of starting the async operation */ 00747 res = WaitForMultipleObjectsEx(count, objs, FALSE, INFINITE, TRUE); 00748 } while (res == WAIT_IO_COMPLETION); 00749 00750 if (res == WAIT_OBJECT_0) 00751 return 0; 00752 else if (res == WAIT_FAILED) 00753 { 00754 ERR("wait failed with error %d\n", GetLastError()); 00755 return -1; 00756 } 00757 else 00758 { 00759 b_handle = objs[res - WAIT_OBJECT_0]; 00760 /* find which connection got a RPC */ 00761 EnterCriticalSection(&protseq->cs); 00762 conn = CONTAINING_RECORD(protseq->conn, RpcConnection_np, common); 00763 while (conn) { 00764 if (b_handle == conn->ovl.hEvent) break; 00765 conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_np, common); 00766 } 00767 cconn = NULL; 00768 if (conn) 00769 RPCRT4_SpawnConnection(&cconn, &conn->common); 00770 else 00771 ERR("failed to locate connection for handle %p\n", b_handle); 00772 LeaveCriticalSection(&protseq->cs); 00773 if (cconn) 00774 { 00775 RPCRT4_new_client(cconn); 00776 return 1; 00777 } 00778 else return -1; 00779 } 00780 } 00781 00782 static size_t rpcrt4_ncalrpc_get_top_of_tower(unsigned char *tower_data, 00783 const char *networkaddr, 00784 const char *endpoint) 00785 { 00786 twr_empty_floor_t *pipe_floor; 00787 size_t size; 00788 size_t endpoint_size; 00789 00790 TRACE("(%p, %s, %s)\n", tower_data, networkaddr, endpoint); 00791 00792 endpoint_size = strlen(endpoint) + 1; 00793 size = sizeof(*pipe_floor) + endpoint_size; 00794 00795 if (!tower_data) 00796 return size; 00797 00798 pipe_floor = (twr_empty_floor_t *)tower_data; 00799 00800 tower_data += sizeof(*pipe_floor); 00801 00802 pipe_floor->count_lhs = sizeof(pipe_floor->protid); 00803 pipe_floor->protid = EPM_PROTOCOL_PIPE; 00804 pipe_floor->count_rhs = endpoint_size; 00805 00806 memcpy(tower_data, endpoint, endpoint_size); 00807 00808 return size; 00809 } 00810 00811 static RPC_STATUS rpcrt4_ncalrpc_parse_top_of_tower(const unsigned char *tower_data, 00812 size_t tower_size, 00813 char **networkaddr, 00814 char **endpoint) 00815 { 00816 const twr_empty_floor_t *pipe_floor = (const twr_empty_floor_t *)tower_data; 00817 00818 TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint); 00819 00820 if (tower_size < sizeof(*pipe_floor)) 00821 return EPT_S_NOT_REGISTERED; 00822 00823 tower_data += sizeof(*pipe_floor); 00824 tower_size -= sizeof(*pipe_floor); 00825 00826 if ((pipe_floor->count_lhs != sizeof(pipe_floor->protid)) || 00827 (pipe_floor->protid != EPM_PROTOCOL_PIPE) || 00828 (pipe_floor->count_rhs > tower_size) || 00829 (tower_data[pipe_floor->count_rhs - 1] != '\0')) 00830 return EPT_S_NOT_REGISTERED; 00831 00832 if (networkaddr) 00833 *networkaddr = NULL; 00834 00835 if (endpoint) 00836 { 00837 *endpoint = I_RpcAllocate(pipe_floor->count_rhs); 00838 if (!*endpoint) 00839 return RPC_S_OUT_OF_RESOURCES; 00840 memcpy(*endpoint, tower_data, pipe_floor->count_rhs); 00841 } 00842 00843 return RPC_S_OK; 00844 } 00845 00846 static BOOL rpcrt4_ncalrpc_is_authorized(RpcConnection *conn) 00847 { 00848 return FALSE; 00849 } 00850 00851 static RPC_STATUS rpcrt4_ncalrpc_authorize(RpcConnection *conn, BOOL first_time, 00852 unsigned char *in_buffer, 00853 unsigned int in_size, 00854 unsigned char *out_buffer, 00855 unsigned int *out_size) 00856 { 00857 /* since this protocol is local to the machine there is no need to 00858 * authenticate the caller */ 00859 *out_size = 0; 00860 return RPC_S_OK; 00861 } 00862 00863 static RPC_STATUS rpcrt4_ncalrpc_secure_packet(RpcConnection *conn, 00864 enum secure_packet_direction dir, 00865 RpcPktHdr *hdr, unsigned int hdr_size, 00866 unsigned char *stub_data, unsigned int stub_data_size, 00867 RpcAuthVerifier *auth_hdr, 00868 unsigned char *auth_value, unsigned int auth_value_size) 00869 { 00870 /* since this protocol is local to the machine there is no need to secure 00871 * the packet */ 00872 return RPC_S_OK; 00873 } 00874 00875 static RPC_STATUS rpcrt4_ncalrpc_inquire_auth_client( 00876 RpcConnection *conn, RPC_AUTHZ_HANDLE *privs, RPC_WSTR *server_princ_name, 00877 ULONG *authn_level, ULONG *authn_svc, ULONG *authz_svc, ULONG flags) 00878 { 00879 TRACE("(%p, %p, %p, %p, %p, %p, 0x%x)\n", conn, privs, 00880 server_princ_name, authn_level, authn_svc, authz_svc, flags); 00881 00882 if (privs) 00883 { 00884 FIXME("privs not implemented\n"); 00885 *privs = NULL; 00886 } 00887 if (server_princ_name) 00888 { 00889 FIXME("server_princ_name not implemented\n"); 00890 *server_princ_name = NULL; 00891 } 00892 if (authn_level) *authn_level = RPC_C_AUTHN_LEVEL_PKT_PRIVACY; 00893 if (authn_svc) *authn_svc = RPC_C_AUTHN_WINNT; 00894 if (authz_svc) 00895 { 00896 FIXME("authorization service not implemented\n"); 00897 *authz_svc = RPC_C_AUTHZ_NONE; 00898 } 00899 if (flags) 00900 FIXME("flags 0x%x not implemented\n", flags); 00901 00902 return RPC_S_OK; 00903 } 00904 00905 /**** ncacn_ip_tcp support ****/ 00906 00907 static size_t rpcrt4_ip_tcp_get_top_of_tower(unsigned char *tower_data, 00908 const char *networkaddr, 00909 unsigned char tcp_protid, 00910 const char *endpoint) 00911 { 00912 twr_tcp_floor_t *tcp_floor; 00913 twr_ipv4_floor_t *ipv4_floor; 00914 struct addrinfo *ai; 00915 struct addrinfo hints; 00916 int ret; 00917 size_t size = sizeof(*tcp_floor) + sizeof(*ipv4_floor); 00918 00919 TRACE("(%p, %s, %s)\n", tower_data, networkaddr, endpoint); 00920 00921 if (!tower_data) 00922 return size; 00923 00924 tcp_floor = (twr_tcp_floor_t *)tower_data; 00925 tower_data += sizeof(*tcp_floor); 00926 00927 ipv4_floor = (twr_ipv4_floor_t *)tower_data; 00928 00929 tcp_floor->count_lhs = sizeof(tcp_floor->protid); 00930 tcp_floor->protid = tcp_protid; 00931 tcp_floor->count_rhs = sizeof(tcp_floor->port); 00932 00933 ipv4_floor->count_lhs = sizeof(ipv4_floor->protid); 00934 ipv4_floor->protid = EPM_PROTOCOL_IP; 00935 ipv4_floor->count_rhs = sizeof(ipv4_floor->ipv4addr); 00936 00937 hints.ai_flags = AI_NUMERICHOST; 00938 /* FIXME: only support IPv4 at the moment. how is IPv6 represented by the EPM? */ 00939 hints.ai_family = PF_INET; 00940 hints.ai_socktype = SOCK_STREAM; 00941 hints.ai_protocol = IPPROTO_TCP; 00942 hints.ai_addrlen = 0; 00943 hints.ai_addr = NULL; 00944 hints.ai_canonname = NULL; 00945 hints.ai_next = NULL; 00946 00947 ret = getaddrinfo(networkaddr, endpoint, &hints, &ai); 00948 if (ret) 00949 { 00950 ret = getaddrinfo("0.0.0.0", endpoint, &hints, &ai); 00951 if (ret) 00952 { 00953 ERR("getaddrinfo failed: %s\n", gai_strerror(ret)); 00954 return 0; 00955 } 00956 } 00957 00958 if (ai->ai_family == PF_INET) 00959 { 00960 const struct sockaddr_in *sin = (const struct sockaddr_in *)ai->ai_addr; 00961 tcp_floor->port = sin->sin_port; 00962 ipv4_floor->ipv4addr = sin->sin_addr.s_addr; 00963 } 00964 else 00965 { 00966 ERR("unexpected protocol family %d\n", ai->ai_family); 00967 return 0; 00968 } 00969 00970 freeaddrinfo(ai); 00971 00972 return size; 00973 } 00974 00975 static RPC_STATUS rpcrt4_ip_tcp_parse_top_of_tower(const unsigned char *tower_data, 00976 size_t tower_size, 00977 char **networkaddr, 00978 unsigned char tcp_protid, 00979 char **endpoint) 00980 { 00981 const twr_tcp_floor_t *tcp_floor = (const twr_tcp_floor_t *)tower_data; 00982 const twr_ipv4_floor_t *ipv4_floor; 00983 struct in_addr in_addr; 00984 00985 TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint); 00986 00987 if (tower_size < sizeof(*tcp_floor)) 00988 return EPT_S_NOT_REGISTERED; 00989 00990 tower_data += sizeof(*tcp_floor); 00991 tower_size -= sizeof(*tcp_floor); 00992 00993 if (tower_size < sizeof(*ipv4_floor)) 00994 return EPT_S_NOT_REGISTERED; 00995 00996 ipv4_floor = (const twr_ipv4_floor_t *)tower_data; 00997 00998 if ((tcp_floor->count_lhs != sizeof(tcp_floor->protid)) || 00999 (tcp_floor->protid != tcp_protid) || 01000 (tcp_floor->count_rhs != sizeof(tcp_floor->port)) || 01001 (ipv4_floor->count_lhs != sizeof(ipv4_floor->protid)) || 01002 (ipv4_floor->protid != EPM_PROTOCOL_IP) || 01003 (ipv4_floor->count_rhs != sizeof(ipv4_floor->ipv4addr))) 01004 return EPT_S_NOT_REGISTERED; 01005 01006 if (endpoint) 01007 { 01008 *endpoint = I_RpcAllocate(6 /* sizeof("65535") + 1 */); 01009 if (!*endpoint) 01010 return RPC_S_OUT_OF_RESOURCES; 01011 sprintf(*endpoint, "%u", ntohs(tcp_floor->port)); 01012 } 01013 01014 if (networkaddr) 01015 { 01016 *networkaddr = I_RpcAllocate(INET_ADDRSTRLEN); 01017 if (!*networkaddr) 01018 { 01019 if (endpoint) 01020 { 01021 I_RpcFree(*endpoint); 01022 *endpoint = NULL; 01023 } 01024 return RPC_S_OUT_OF_RESOURCES; 01025 } 01026 in_addr.s_addr = ipv4_floor->ipv4addr; 01027 if (!inet_ntop(AF_INET, &in_addr, *networkaddr, INET_ADDRSTRLEN)) 01028 { 01029 ERR("inet_ntop: %s\n", strerror(errno)); 01030 I_RpcFree(*networkaddr); 01031 *networkaddr = NULL; 01032 if (endpoint) 01033 { 01034 I_RpcFree(*endpoint); 01035 *endpoint = NULL; 01036 } 01037 return EPT_S_NOT_REGISTERED; 01038 } 01039 } 01040 01041 return RPC_S_OK; 01042 } 01043 01044 typedef struct _RpcConnection_tcp 01045 { 01046 RpcConnection common; 01047 int sock; 01048 #ifdef HAVE_SOCKETPAIR 01049 int cancel_fds[2]; 01050 #else 01051 HANDLE sock_event; 01052 HANDLE cancel_event; 01053 #endif 01054 } RpcConnection_tcp; 01055 01056 #ifdef HAVE_SOCKETPAIR 01057 01058 static BOOL rpcrt4_sock_wait_init(RpcConnection_tcp *tcpc) 01059 { 01060 if (socketpair(PF_UNIX, SOCK_STREAM, 0, tcpc->cancel_fds) < 0) 01061 { 01062 ERR("socketpair() failed: %s\n", strerror(errno)); 01063 return FALSE; 01064 } 01065 return TRUE; 01066 } 01067 01068 static BOOL rpcrt4_sock_wait_for_recv(RpcConnection_tcp *tcpc) 01069 { 01070 struct pollfd pfds[2]; 01071 pfds[0].fd = tcpc->sock; 01072 pfds[0].events = POLLIN; 01073 pfds[1].fd = tcpc->cancel_fds[0]; 01074 pfds[1].events = POLLIN; 01075 if (poll(pfds, 2, -1 /* infinite */) == -1 && errno != EINTR) 01076 { 01077 ERR("poll() failed: %s\n", strerror(errno)); 01078 return FALSE; 01079 } 01080 if (pfds[1].revents & POLLIN) /* canceled */ 01081 { 01082 char dummy; 01083 read(pfds[1].fd, &dummy, sizeof(dummy)); 01084 return FALSE; 01085 } 01086 return TRUE; 01087 } 01088 01089 static BOOL rpcrt4_sock_wait_for_send(RpcConnection_tcp *tcpc) 01090 { 01091 struct pollfd pfd; 01092 pfd.fd = tcpc->sock; 01093 pfd.events = POLLOUT; 01094 if (poll(&pfd, 1, -1 /* infinite */) == -1 && errno != EINTR) 01095 { 01096 ERR("poll() failed: %s\n", strerror(errno)); 01097 return FALSE; 01098 } 01099 return TRUE; 01100 } 01101 01102 static void rpcrt4_sock_wait_cancel(RpcConnection_tcp *tcpc) 01103 { 01104 char dummy = 1; 01105 01106 write(tcpc->cancel_fds[1], &dummy, 1); 01107 } 01108 01109 static void rpcrt4_sock_wait_destroy(RpcConnection_tcp *tcpc) 01110 { 01111 close(tcpc->cancel_fds[0]); 01112 close(tcpc->cancel_fds[1]); 01113 } 01114 01115 #else /* HAVE_SOCKETPAIR */ 01116 01117 static BOOL rpcrt4_sock_wait_init(RpcConnection_tcp *tcpc) 01118 { 01119 static BOOL wsa_inited; 01120 if (!wsa_inited) 01121 { 01122 WSADATA wsadata; 01123 WSAStartup(MAKEWORD(2, 2), &wsadata); 01124 /* Note: WSAStartup can be called more than once so we don't bother with 01125 * making accesses to wsa_inited thread-safe */ 01126 wsa_inited = TRUE; 01127 } 01128 tcpc->sock_event = CreateEventW(NULL, FALSE, FALSE, NULL); 01129 tcpc->cancel_event = CreateEventW(NULL, FALSE, FALSE, NULL); 01130 if (!tcpc->sock_event || !tcpc->cancel_event) 01131 { 01132 ERR("event creation failed\n"); 01133 if (tcpc->sock_event) CloseHandle(tcpc->sock_event); 01134 return FALSE; 01135 } 01136 return TRUE; 01137 } 01138 01139 static BOOL rpcrt4_sock_wait_for_recv(RpcConnection_tcp *tcpc) 01140 { 01141 HANDLE wait_handles[2]; 01142 DWORD res; 01143 if (WSAEventSelect(tcpc->sock, tcpc->sock_event, FD_READ | FD_CLOSE) == SOCKET_ERROR) 01144 { 01145 ERR("WSAEventSelect() failed with error %d\n", WSAGetLastError()); 01146 return FALSE; 01147 } 01148 wait_handles[0] = tcpc->sock_event; 01149 wait_handles[1] = tcpc->cancel_event; 01150 res = WaitForMultipleObjects(2, wait_handles, FALSE, INFINITE); 01151 switch (res) 01152 { 01153 case WAIT_OBJECT_0: 01154 return TRUE; 01155 case WAIT_OBJECT_0 + 1: 01156 return FALSE; 01157 default: 01158 ERR("WaitForMultipleObjects() failed with error %d\n", GetLastError()); 01159 return FALSE; 01160 } 01161 } 01162 01163 static BOOL rpcrt4_sock_wait_for_send(RpcConnection_tcp *tcpc) 01164 { 01165 DWORD res; 01166 if (WSAEventSelect(tcpc->sock, tcpc->sock_event, FD_WRITE | FD_CLOSE) == SOCKET_ERROR) 01167 { 01168 ERR("WSAEventSelect() failed with error %d\n", WSAGetLastError()); 01169 return FALSE; 01170 } 01171 res = WaitForSingleObject(tcpc->sock_event, INFINITE); 01172 switch (res) 01173 { 01174 case WAIT_OBJECT_0: 01175 return TRUE; 01176 default: 01177 ERR("WaitForMultipleObjects() failed with error %d\n", GetLastError()); 01178 return FALSE; 01179 } 01180 } 01181 01182 static void rpcrt4_sock_wait_cancel(RpcConnection_tcp *tcpc) 01183 { 01184 SetEvent(tcpc->cancel_event); 01185 } 01186 01187 static void rpcrt4_sock_wait_destroy(RpcConnection_tcp *tcpc) 01188 { 01189 CloseHandle(tcpc->sock_event); 01190 CloseHandle(tcpc->cancel_event); 01191 } 01192 01193 #endif 01194 01195 static RpcConnection *rpcrt4_conn_tcp_alloc(void) 01196 { 01197 RpcConnection_tcp *tcpc; 01198 tcpc = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcConnection_tcp)); 01199 if (tcpc == NULL) 01200 return NULL; 01201 tcpc->sock = -1; 01202 if (!rpcrt4_sock_wait_init(tcpc)) 01203 { 01204 HeapFree(GetProcessHeap(), 0, tcpc); 01205 return NULL; 01206 } 01207 return &tcpc->common; 01208 } 01209 01210 static RPC_STATUS rpcrt4_ncacn_ip_tcp_open(RpcConnection* Connection) 01211 { 01212 RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection; 01213 int sock; 01214 int ret; 01215 struct addrinfo *ai; 01216 struct addrinfo *ai_cur; 01217 struct addrinfo hints; 01218 01219 TRACE("(%s, %s)\n", Connection->NetworkAddr, Connection->Endpoint); 01220 01221 if (tcpc->sock != -1) 01222 return RPC_S_OK; 01223 01224 hints.ai_flags = 0; 01225 hints.ai_family = PF_UNSPEC; 01226 hints.ai_socktype = SOCK_STREAM; 01227 hints.ai_protocol = IPPROTO_TCP; 01228 hints.ai_addrlen = 0; 01229 hints.ai_addr = NULL; 01230 hints.ai_canonname = NULL; 01231 hints.ai_next = NULL; 01232 01233 ret = getaddrinfo(Connection->NetworkAddr, Connection->Endpoint, &hints, &ai); 01234 if (ret) 01235 { 01236 ERR("getaddrinfo for %s:%s failed: %s\n", Connection->NetworkAddr, 01237 Connection->Endpoint, gai_strerror(ret)); 01238 return RPC_S_SERVER_UNAVAILABLE; 01239 } 01240 01241 for (ai_cur = ai; ai_cur; ai_cur = ai_cur->ai_next) 01242 { 01243 int val; 01244 u_long nonblocking; 01245 01246 if (ai_cur->ai_family != AF_INET && ai_cur->ai_family != AF_INET6) 01247 { 01248 TRACE("skipping non-IP/IPv6 address family\n"); 01249 continue; 01250 } 01251 01252 if (TRACE_ON(rpc)) 01253 { 01254 char host[256]; 01255 char service[256]; 01256 getnameinfo(ai_cur->ai_addr, ai_cur->ai_addrlen, 01257 host, sizeof(host), service, sizeof(service), 01258 NI_NUMERICHOST | NI_NUMERICSERV); 01259 TRACE("trying %s:%s\n", host, service); 01260 } 01261 01262 sock = socket(ai_cur->ai_family, ai_cur->ai_socktype, ai_cur->ai_protocol); 01263 if (sock == -1) 01264 { 01265 WARN("socket() failed: %s\n", strerror(errno)); 01266 continue; 01267 } 01268 01269 if (0>connect(sock, ai_cur->ai_addr, ai_cur->ai_addrlen)) 01270 { 01271 WARN("connect() failed: %s\n", strerror(errno)); 01272 closesocket(sock); 01273 continue; 01274 } 01275 01276 /* RPC depends on having minimal latency so disable the Nagle algorithm */ 01277 val = 1; 01278 setsockopt(sock, SOL_TCP, TCP_NODELAY, (char *)&val, sizeof(val)); 01279 nonblocking = 1; 01280 ioctlsocket(sock, FIONBIO, &nonblocking); 01281 01282 tcpc->sock = sock; 01283 01284 freeaddrinfo(ai); 01285 TRACE("connected\n"); 01286 return RPC_S_OK; 01287 } 01288 01289 freeaddrinfo(ai); 01290 ERR("couldn't connect to %s:%s\n", Connection->NetworkAddr, Connection->Endpoint); 01291 return RPC_S_SERVER_UNAVAILABLE; 01292 } 01293 01294 static RPC_STATUS rpcrt4_protseq_ncacn_ip_tcp_open_endpoint(RpcServerProtseq *protseq, const char *endpoint) 01295 { 01296 RPC_STATUS status = RPC_S_CANT_CREATE_ENDPOINT; 01297 int sock; 01298 int ret; 01299 struct addrinfo *ai; 01300 struct addrinfo *ai_cur; 01301 struct addrinfo hints; 01302 RpcConnection *first_connection = NULL; 01303 01304 TRACE("(%p, %s)\n", protseq, endpoint); 01305 01306 hints.ai_flags = AI_PASSIVE /* for non-localhost addresses */; 01307 hints.ai_family = PF_UNSPEC; 01308 hints.ai_socktype = SOCK_STREAM; 01309 hints.ai_protocol = IPPROTO_TCP; 01310 hints.ai_addrlen = 0; 01311 hints.ai_addr = NULL; 01312 hints.ai_canonname = NULL; 01313 hints.ai_next = NULL; 01314 01315 ret = getaddrinfo(NULL, endpoint ? endpoint : "0", &hints, &ai); 01316 if (ret) 01317 { 01318 ERR("getaddrinfo for port %s failed: %s\n", endpoint, 01319 gai_strerror(ret)); 01320 if ((ret == EAI_SERVICE) || (ret == EAI_NONAME)) 01321 return RPC_S_INVALID_ENDPOINT_FORMAT; 01322 return RPC_S_CANT_CREATE_ENDPOINT; 01323 } 01324 01325 for (ai_cur = ai; ai_cur; ai_cur = ai_cur->ai_next) 01326 { 01327 RpcConnection_tcp *tcpc; 01328 RPC_STATUS create_status; 01329 struct sockaddr_storage sa; 01330 socklen_t sa_len; 01331 char service[NI_MAXSERV]; 01332 u_long nonblocking; 01333 01334 if (ai_cur->ai_family != AF_INET && ai_cur->ai_family != AF_INET6) 01335 { 01336 TRACE("skipping non-IP/IPv6 address family\n"); 01337 continue; 01338 } 01339 01340 if (TRACE_ON(rpc)) 01341 { 01342 char host[256]; 01343 getnameinfo(ai_cur->ai_addr, ai_cur->ai_addrlen, 01344 host, sizeof(host), service, sizeof(service), 01345 NI_NUMERICHOST | NI_NUMERICSERV); 01346 TRACE("trying %s:%s\n", host, service); 01347 } 01348 01349 sock = socket(ai_cur->ai_family, ai_cur->ai_socktype, ai_cur->ai_protocol); 01350 if (sock == -1) 01351 { 01352 WARN("socket() failed: %s\n", strerror(errno)); 01353 status = RPC_S_CANT_CREATE_ENDPOINT; 01354 continue; 01355 } 01356 01357 ret = bind(sock, ai_cur->ai_addr, ai_cur->ai_addrlen); 01358 if (ret < 0) 01359 { 01360 WARN("bind failed: %s\n", strerror(errno)); 01361 closesocket(sock); 01362 if (errno == EADDRINUSE) 01363 status = RPC_S_DUPLICATE_ENDPOINT; 01364 else 01365 status = RPC_S_CANT_CREATE_ENDPOINT; 01366 continue; 01367 } 01368 01369 sa_len = sizeof(sa); 01370 if (getsockname(sock, (struct sockaddr *)&sa, &sa_len)) 01371 { 01372 WARN("getsockname() failed: %s\n", strerror(errno)); 01373 status = RPC_S_CANT_CREATE_ENDPOINT; 01374 continue; 01375 } 01376 01377 ret = getnameinfo((struct sockaddr *)&sa, sa_len, 01378 NULL, 0, service, sizeof(service), 01379 NI_NUMERICSERV); 01380 if (ret) 01381 { 01382 WARN("getnameinfo failed: %s\n", gai_strerror(ret)); 01383 status = RPC_S_CANT_CREATE_ENDPOINT; 01384 continue; 01385 } 01386 01387 create_status = RPCRT4_CreateConnection((RpcConnection **)&tcpc, TRUE, 01388 protseq->Protseq, NULL, 01389 service, NULL, NULL, NULL); 01390 if (create_status != RPC_S_OK) 01391 { 01392 closesocket(sock); 01393 status = create_status; 01394 continue; 01395 } 01396 01397 tcpc->sock = sock; 01398 ret = listen(sock, protseq->MaxCalls); 01399 if (ret < 0) 01400 { 01401 WARN("listen failed: %s\n", strerror(errno)); 01402 RPCRT4_DestroyConnection(&tcpc->common); 01403 status = RPC_S_OUT_OF_RESOURCES; 01404 continue; 01405 } 01406 /* need a non-blocking socket, otherwise accept() has a potential 01407 * race-condition (poll() says it is readable, connection drops, 01408 * and accept() blocks until the next connection comes...) 01409 */ 01410 nonblocking = 1; 01411 ret = ioctlsocket(sock, FIONBIO, &nonblocking); 01412 if (ret < 0) 01413 { 01414 WARN("couldn't make socket non-blocking, error %d\n", ret); 01415 RPCRT4_DestroyConnection(&tcpc->common); 01416 status = RPC_S_OUT_OF_RESOURCES; 01417 continue; 01418 } 01419 01420 tcpc->common.Next = first_connection; 01421 first_connection = &tcpc->common; 01422 01423 /* since IPv4 and IPv6 share the same port space, we only need one 01424 * successful bind to listen for both */ 01425 break; 01426 } 01427 01428 freeaddrinfo(ai); 01429 01430 /* if at least one connection was created for an endpoint then 01431 * return success */ 01432 if (first_connection) 01433 { 01434 RpcConnection *conn; 01435 01436 /* find last element in list */ 01437 for (conn = first_connection; conn->Next; conn = conn->Next) 01438 ; 01439 01440 EnterCriticalSection(&protseq->cs); 01441 conn->Next = protseq->conn; 01442 protseq->conn = first_connection; 01443 LeaveCriticalSection(&protseq->cs); 01444 01445 TRACE("listening on %s\n", endpoint); 01446 return RPC_S_OK; 01447 } 01448 01449 ERR("couldn't listen on port %s\n", endpoint); 01450 return status; 01451 } 01452 01453 static RPC_STATUS rpcrt4_conn_tcp_handoff(RpcConnection *old_conn, RpcConnection *new_conn) 01454 { 01455 int ret; 01456 struct sockaddr_in address; 01457 socklen_t addrsize; 01458 RpcConnection_tcp *server = (RpcConnection_tcp*) old_conn; 01459 RpcConnection_tcp *client = (RpcConnection_tcp*) new_conn; 01460 u_long nonblocking; 01461 01462 addrsize = sizeof(address); 01463 ret = accept(server->sock, (struct sockaddr*) &address, &addrsize); 01464 if (ret < 0) 01465 { 01466 ERR("Failed to accept a TCP connection: error %d\n", ret); 01467 return RPC_S_OUT_OF_RESOURCES; 01468 } 01469 nonblocking = 1; 01470 ioctlsocket(ret, FIONBIO, &nonblocking); 01471 client->sock = ret; 01472 TRACE("Accepted a new TCP connection\n"); 01473 return RPC_S_OK; 01474 } 01475 01476 static int rpcrt4_conn_tcp_read(RpcConnection *Connection, 01477 void *buffer, unsigned int count) 01478 { 01479 RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection; 01480 int bytes_read = 0; 01481 while (bytes_read != count) 01482 { 01483 int r = recv(tcpc->sock, (char *)buffer + bytes_read, count - bytes_read, 0); 01484 if (!r) 01485 return -1; 01486 else if (r > 0) 01487 bytes_read += r; 01488 else if (errno != EAGAIN) 01489 { 01490 WARN("recv() failed: %s\n", strerror(errno)); 01491 return -1; 01492 } 01493 else 01494 { 01495 if (!rpcrt4_sock_wait_for_recv(tcpc)) 01496 return -1; 01497 } 01498 } 01499 TRACE("%d %p %u -> %d\n", tcpc->sock, buffer, count, bytes_read); 01500 return bytes_read; 01501 } 01502 01503 static int rpcrt4_conn_tcp_write(RpcConnection *Connection, 01504 const void *buffer, unsigned int count) 01505 { 01506 RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection; 01507 int bytes_written = 0; 01508 while (bytes_written != count) 01509 { 01510 int r = send(tcpc->sock, (const char *)buffer + bytes_written, count - bytes_written, 0); 01511 if (r >= 0) 01512 bytes_written += r; 01513 else if (errno != EAGAIN) 01514 return -1; 01515 else 01516 { 01517 if (!rpcrt4_sock_wait_for_send(tcpc)) 01518 return -1; 01519 } 01520 } 01521 TRACE("%d %p %u -> %d\n", tcpc->sock, buffer, count, bytes_written); 01522 return bytes_written; 01523 } 01524 01525 static int rpcrt4_conn_tcp_close(RpcConnection *Connection) 01526 { 01527 RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection; 01528 01529 TRACE("%d\n", tcpc->sock); 01530 01531 if (tcpc->sock != -1) 01532 closesocket(tcpc->sock); 01533 tcpc->sock = -1; 01534 rpcrt4_sock_wait_destroy(tcpc); 01535 return 0; 01536 } 01537 01538 static void rpcrt4_conn_tcp_cancel_call(RpcConnection *Connection) 01539 { 01540 RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection; 01541 TRACE("%p\n", Connection); 01542 rpcrt4_sock_wait_cancel(tcpc); 01543 } 01544 01545 static int rpcrt4_conn_tcp_wait_for_incoming_data(RpcConnection *Connection) 01546 { 01547 RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection; 01548 01549 TRACE("%p\n", Connection); 01550 01551 if (!rpcrt4_sock_wait_for_recv(tcpc)) 01552 return -1; 01553 return 0; 01554 } 01555 01556 static size_t rpcrt4_ncacn_ip_tcp_get_top_of_tower(unsigned char *tower_data, 01557 const char *networkaddr, 01558 const char *endpoint) 01559 { 01560 return rpcrt4_ip_tcp_get_top_of_tower(tower_data, networkaddr, 01561 EPM_PROTOCOL_TCP, endpoint); 01562 } 01563 01564 #ifdef HAVE_SOCKETPAIR 01565 01566 typedef struct _RpcServerProtseq_sock 01567 { 01568 RpcServerProtseq common; 01569 int mgr_event_rcv; 01570 int mgr_event_snd; 01571 } RpcServerProtseq_sock; 01572 01573 static RpcServerProtseq *rpcrt4_protseq_sock_alloc(void) 01574 { 01575 RpcServerProtseq_sock *ps = HeapAlloc(GetProcessHeap(), 0, sizeof(*ps)); 01576 if (ps) 01577 { 01578 int fds[2]; 01579 if (!socketpair(PF_UNIX, SOCK_DGRAM, 0, fds)) 01580 { 01581 fcntl(fds[0], F_SETFL, O_NONBLOCK); 01582 fcntl(fds[1], F_SETFL, O_NONBLOCK); 01583 ps->mgr_event_rcv = fds[0]; 01584 ps->mgr_event_snd = fds[1]; 01585 } 01586 else 01587 { 01588 ERR("socketpair failed with error %s\n", strerror(errno)); 01589 HeapFree(GetProcessHeap(), 0, ps); 01590 return NULL; 01591 } 01592 } 01593 return &ps->common; 01594 } 01595 01596 static void rpcrt4_protseq_sock_signal_state_changed(RpcServerProtseq *protseq) 01597 { 01598 RpcServerProtseq_sock *sockps = CONTAINING_RECORD(protseq, RpcServerProtseq_sock, common); 01599 char dummy = 1; 01600 write(sockps->mgr_event_snd, &dummy, sizeof(dummy)); 01601 } 01602 01603 static void *rpcrt4_protseq_sock_get_wait_array(RpcServerProtseq *protseq, void *prev_array, unsigned int *count) 01604 { 01605 struct pollfd *poll_info = prev_array; 01606 RpcConnection_tcp *conn; 01607 RpcServerProtseq_sock *sockps = CONTAINING_RECORD(protseq, RpcServerProtseq_sock, common); 01608 01609 EnterCriticalSection(&protseq->cs); 01610 01611 /* open and count connections */ 01612 *count = 1; 01613 conn = (RpcConnection_tcp *)protseq->conn; 01614 while (conn) { 01615 if (conn->sock != -1) 01616 (*count)++; 01617 conn = (RpcConnection_tcp *)conn->common.Next; 01618 } 01619 01620 /* make array of connections */ 01621 if (poll_info) 01622 poll_info = HeapReAlloc(GetProcessHeap(), 0, poll_info, *count*sizeof(*poll_info)); 01623 else 01624 poll_info = HeapAlloc(GetProcessHeap(), 0, *count*sizeof(*poll_info)); 01625 if (!poll_info) 01626 { 01627 ERR("couldn't allocate poll_info\n"); 01628 LeaveCriticalSection(&protseq->cs); 01629 return NULL; 01630 } 01631 01632 poll_info[0].fd = sockps->mgr_event_rcv; 01633 poll_info[0].events = POLLIN; 01634 *count = 1; 01635 conn = CONTAINING_RECORD(protseq->conn, RpcConnection_tcp, common); 01636 while (conn) { 01637 if (conn->sock != -1) 01638 { 01639 poll_info[*count].fd = conn->sock; 01640 poll_info[*count].events = POLLIN; 01641 (*count)++; 01642 } 01643 conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_tcp, common); 01644 } 01645 LeaveCriticalSection(&protseq->cs); 01646 return poll_info; 01647 } 01648 01649 static void rpcrt4_protseq_sock_free_wait_array(RpcServerProtseq *protseq, void *array) 01650 { 01651 HeapFree(GetProcessHeap(), 0, array); 01652 } 01653 01654 static int rpcrt4_protseq_sock_wait_for_new_connection(RpcServerProtseq *protseq, unsigned int count, void *wait_array) 01655 { 01656 struct pollfd *poll_info = wait_array; 01657 int ret; 01658 unsigned int i; 01659 RpcConnection *cconn; 01660 RpcConnection_tcp *conn; 01661 01662 if (!poll_info) 01663 return -1; 01664 01665 ret = poll(poll_info, count, -1); 01666 if (ret < 0) 01667 { 01668 ERR("poll failed with error %d\n", ret); 01669 return -1; 01670 } 01671 01672 for (i = 0; i < count; i++) 01673 if (poll_info[i].revents & POLLIN) 01674 { 01675 /* RPC server event */ 01676 if (i == 0) 01677 { 01678 char dummy; 01679 read(poll_info[0].fd, &dummy, sizeof(dummy)); 01680 return 0; 01681 } 01682 01683 /* find which connection got a RPC */ 01684 EnterCriticalSection(&protseq->cs); 01685 conn = CONTAINING_RECORD(protseq->conn, RpcConnection_tcp, common); 01686 while (conn) { 01687 if (poll_info[i].fd == conn->sock) break; 01688 conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_tcp, common); 01689 } 01690 cconn = NULL; 01691 if (conn) 01692 RPCRT4_SpawnConnection(&cconn, &conn->common); 01693 else 01694 ERR("failed to locate connection for fd %d\n", poll_info[i].fd); 01695 LeaveCriticalSection(&protseq->cs); 01696 if (cconn) 01697 RPCRT4_new_client(cconn); 01698 else 01699 return -1; 01700 } 01701 01702 return 1; 01703 } 01704 01705 #else /* HAVE_SOCKETPAIR */ 01706 01707 typedef struct _RpcServerProtseq_sock 01708 { 01709 RpcServerProtseq common; 01710 HANDLE mgr_event; 01711 } RpcServerProtseq_sock; 01712 01713 static RpcServerProtseq *rpcrt4_protseq_sock_alloc(void) 01714 { 01715 RpcServerProtseq_sock *ps = HeapAlloc(GetProcessHeap(), 0, sizeof(*ps)); 01716 if (ps) 01717 { 01718 static BOOL wsa_inited; 01719 if (!wsa_inited) 01720 { 01721 WSADATA wsadata; 01722 WSAStartup(MAKEWORD(2, 2), &wsadata); 01723 /* Note: WSAStartup can be called more than once so we don't bother with 01724 * making accesses to wsa_inited thread-safe */ 01725 wsa_inited = TRUE; 01726 } 01727 ps->mgr_event = CreateEventW(NULL, FALSE, FALSE, NULL); 01728 } 01729 return &ps->common; 01730 } 01731 01732 static void rpcrt4_protseq_sock_signal_state_changed(RpcServerProtseq *protseq) 01733 { 01734 RpcServerProtseq_sock *sockps = CONTAINING_RECORD(protseq, RpcServerProtseq_sock, common); 01735 SetEvent(sockps->mgr_event); 01736 } 01737 01738 static void *rpcrt4_protseq_sock_get_wait_array(RpcServerProtseq *protseq, void *prev_array, unsigned int *count) 01739 { 01740 HANDLE *objs = prev_array; 01741 RpcConnection_tcp *conn; 01742 RpcServerProtseq_sock *sockps = CONTAINING_RECORD(protseq, RpcServerProtseq_sock, common); 01743 01744 EnterCriticalSection(&protseq->cs); 01745 01746 /* open and count connections */ 01747 *count = 1; 01748 conn = CONTAINING_RECORD(protseq->conn, RpcConnection_tcp, common); 01749 while (conn) 01750 { 01751 if (conn->sock != -1) 01752 (*count)++; 01753 conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_tcp, common); 01754 } 01755 01756 /* make array of connections */ 01757 if (objs) 01758 objs = HeapReAlloc(GetProcessHeap(), 0, objs, *count*sizeof(HANDLE)); 01759 else 01760 objs = HeapAlloc(GetProcessHeap(), 0, *count*sizeof(HANDLE)); 01761 if (!objs) 01762 { 01763 ERR("couldn't allocate objs\n"); 01764 LeaveCriticalSection(&protseq->cs); 01765 return NULL; 01766 } 01767 01768 objs[0] = sockps->mgr_event; 01769 *count = 1; 01770 conn = CONTAINING_RECORD(protseq->conn, RpcConnection_tcp, common); 01771 while (conn) 01772 { 01773 if (conn->sock != -1) 01774 { 01775 int res = WSAEventSelect(conn->sock, conn->sock_event, FD_ACCEPT); 01776 if (res == SOCKET_ERROR) 01777 ERR("WSAEventSelect() failed with error %d\n", WSAGetLastError()); 01778 else 01779 { 01780 objs[*count] = conn->sock_event; 01781 (*count)++; 01782 } 01783 } 01784 conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_tcp, common); 01785 } 01786 LeaveCriticalSection(&protseq->cs); 01787 return objs; 01788 } 01789 01790 static void rpcrt4_protseq_sock_free_wait_array(RpcServerProtseq *protseq, void *array) 01791 { 01792 HeapFree(GetProcessHeap(), 0, array); 01793 } 01794 01795 static int rpcrt4_protseq_sock_wait_for_new_connection(RpcServerProtseq *protseq, unsigned int count, void *wait_array) 01796 { 01797 HANDLE b_handle; 01798 HANDLE *objs = wait_array; 01799 DWORD res; 01800 RpcConnection *cconn; 01801 RpcConnection_tcp *conn; 01802 01803 if (!objs) 01804 return -1; 01805 01806 do 01807 { 01808 /* an alertable wait isn't strictly necessary, but due to our 01809 * overlapped I/O implementation in Wine we need to free some memory 01810 * by the file user APC being called, even if no completion routine was 01811 * specified at the time of starting the async operation */ 01812 res = WaitForMultipleObjectsEx(count, objs, FALSE, INFINITE, TRUE); 01813 } while (res == WAIT_IO_COMPLETION); 01814 01815 if (res == WAIT_OBJECT_0) 01816 return 0; 01817 else if (res == WAIT_FAILED) 01818 { 01819 ERR("wait failed with error %d\n", GetLastError()); 01820 return -1; 01821 } 01822 else 01823 { 01824 b_handle = objs[res - WAIT_OBJECT_0]; 01825 /* find which connection got a RPC */ 01826 EnterCriticalSection(&protseq->cs); 01827 conn = CONTAINING_RECORD(protseq->conn, RpcConnection_tcp, common); 01828 while (conn) 01829 { 01830 if (b_handle == conn->sock_event) break; 01831 conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_tcp, common); 01832 } 01833 cconn = NULL; 01834 if (conn) 01835 RPCRT4_SpawnConnection(&cconn, &conn->common); 01836 else 01837 ERR("failed to locate connection for handle %p\n", b_handle); 01838 LeaveCriticalSection(&protseq->cs); 01839 if (cconn) 01840 { 01841 RPCRT4_new_client(cconn); 01842 return 1; 01843 } 01844 else return -1; 01845 } 01846 } 01847 01848 #endif /* HAVE_SOCKETPAIR */ 01849 01850 static RPC_STATUS rpcrt4_ncacn_ip_tcp_parse_top_of_tower(const unsigned char *tower_data, 01851 size_t tower_size, 01852 char **networkaddr, 01853 char **endpoint) 01854 { 01855 return rpcrt4_ip_tcp_parse_top_of_tower(tower_data, tower_size, 01856 networkaddr, EPM_PROTOCOL_TCP, 01857 endpoint); 01858 } 01859 01860 /**** ncacn_http support ****/ 01861 01862 /* 60 seconds is the period native uses */ 01863 #define HTTP_IDLE_TIME 60000 01864 01865 /* reference counted to avoid a race between a cancelled call's connection 01866 * being destroyed and the asynchronous InternetReadFileEx call being 01867 * completed */ 01868 typedef struct _RpcHttpAsyncData 01869 { 01870 LONG refs; 01871 HANDLE completion_event; 01872 INTERNET_BUFFERSA inet_buffers; 01873 void *destination_buffer; /* the address that inet_buffers.lpvBuffer will be 01874 * copied into when the call completes */ 01875 CRITICAL_SECTION cs; 01876 } RpcHttpAsyncData; 01877 01878 static ULONG RpcHttpAsyncData_AddRef(RpcHttpAsyncData *data) 01879 { 01880 return InterlockedIncrement(&data->refs); 01881 } 01882 01883 static ULONG RpcHttpAsyncData_Release(RpcHttpAsyncData *data) 01884 { 01885 ULONG refs = InterlockedDecrement(&data->refs); 01886 if (!refs) 01887 { 01888 TRACE("destroying async data %p\n", data); 01889 CloseHandle(data->completion_event); 01890 HeapFree(GetProcessHeap(), 0, data->inet_buffers.lpvBuffer); 01891 DeleteCriticalSection(&data->cs); 01892 HeapFree(GetProcessHeap(), 0, data); 01893 } 01894 return refs; 01895 } 01896 01897 typedef struct _RpcConnection_http 01898 { 01899 RpcConnection common; 01900 HINTERNET app_info; 01901 HINTERNET session; 01902 HINTERNET in_request; 01903 HINTERNET out_request; 01904 HANDLE timer_cancelled; 01905 HANDLE cancel_event; 01906 DWORD last_sent_time; 01907 ULONG bytes_received; 01908 ULONG flow_control_mark; /* send a control packet to the server when this many bytes received */ 01909 ULONG flow_control_increment; /* number of bytes to increment flow_control_mark by */ 01910 UUID connection_uuid; 01911 UUID in_pipe_uuid; 01912 UUID out_pipe_uuid; 01913 RpcHttpAsyncData *async_data; 01914 } RpcConnection_http; 01915 01916 static RpcConnection *rpcrt4_ncacn_http_alloc(void) 01917 { 01918 RpcConnection_http *httpc; 01919 httpc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*httpc)); 01920 if (!httpc) return NULL; 01921 httpc->async_data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcHttpAsyncData)); 01922 if (!httpc->async_data) 01923 { 01924 HeapFree(GetProcessHeap(), 0, httpc); 01925 return NULL; 01926 } 01927 TRACE("async data = %p\n", httpc->async_data); 01928 httpc->cancel_event = CreateEventW(NULL, FALSE, FALSE, NULL); 01929 httpc->async_data->refs = 1; 01930 httpc->async_data->inet_buffers.dwStructSize = sizeof(INTERNET_BUFFERSA); 01931 httpc->async_data->inet_buffers.lpvBuffer = NULL; 01932 httpc->async_data->destination_buffer = NULL; 01933 InitializeCriticalSection(&httpc->async_data->cs); 01934 return &httpc->common; 01935 } 01936 01937 typedef struct _HttpTimerThreadData 01938 { 01939 PVOID timer_param; 01940 DWORD *last_sent_time; 01941 HANDLE timer_cancelled; 01942 } HttpTimerThreadData; 01943 01944 static VOID rpcrt4_http_keep_connection_active_timer_proc(PVOID param, BOOLEAN dummy) 01945 { 01946 HINTERNET in_request = param; 01947 RpcPktHdr *idle_pkt; 01948 01949 idle_pkt = RPCRT4_BuildHttpHeader(NDR_LOCAL_DATA_REPRESENTATION, 0x0001, 01950 0, 0); 01951 if (idle_pkt) 01952 { 01953 DWORD bytes_written; 01954 InternetWriteFile(in_request, idle_pkt, idle_pkt->common.frag_len, &bytes_written); 01955 RPCRT4_FreeHeader(idle_pkt); 01956 } 01957 } 01958 01959 static inline DWORD rpcrt4_http_timer_calc_timeout(DWORD *last_sent_time) 01960 { 01961 DWORD cur_time = GetTickCount(); 01962 DWORD cached_last_sent_time = *last_sent_time; 01963 return HTTP_IDLE_TIME - (cur_time - cached_last_sent_time > HTTP_IDLE_TIME ? 0 : cur_time - cached_last_sent_time); 01964 } 01965 01966 static DWORD CALLBACK rpcrt4_http_timer_thread(PVOID param) 01967 { 01968 HttpTimerThreadData *data_in = param; 01969 HttpTimerThreadData data; 01970 DWORD timeout; 01971 01972 data = *data_in; 01973 HeapFree(GetProcessHeap(), 0, data_in); 01974 01975 for (timeout = HTTP_IDLE_TIME; 01976 WaitForSingleObject(data.timer_cancelled, timeout) == WAIT_TIMEOUT; 01977 timeout = rpcrt4_http_timer_calc_timeout(data.last_sent_time)) 01978 { 01979 /* are we too soon after last send? */ 01980 if (GetTickCount() - HTTP_IDLE_TIME < *data.last_sent_time) 01981 continue; 01982 rpcrt4_http_keep_connection_active_timer_proc(data.timer_param, TRUE); 01983 } 01984 01985 CloseHandle(data.timer_cancelled); 01986 return 0; 01987 } 01988 01989 static VOID WINAPI rpcrt4_http_internet_callback( 01990 HINTERNET hInternet, 01991 DWORD_PTR dwContext, 01992 DWORD dwInternetStatus, 01993 LPVOID lpvStatusInformation, 01994 DWORD dwStatusInformationLength) 01995 { 01996 RpcHttpAsyncData *async_data = (RpcHttpAsyncData *)dwContext; 01997 01998 switch (dwInternetStatus) 01999 { 02000 case INTERNET_STATUS_REQUEST_COMPLETE: 02001 TRACE("INTERNET_STATUS_REQUEST_COMPLETED\n"); 02002 if (async_data) 02003 { 02004 if (async_data->inet_buffers.lpvBuffer) 02005 { 02006 EnterCriticalSection(&async_data->cs); 02007 if (async_data->destination_buffer) 02008 { 02009 memcpy(async_data->destination_buffer, 02010 async_data->inet_buffers.lpvBuffer, 02011 async_data->inet_buffers.dwBufferLength); 02012 async_data->destination_buffer = NULL; 02013 } 02014 LeaveCriticalSection(&async_data->cs); 02015 } 02016 HeapFree(GetProcessHeap(), 0, async_data->inet_buffers.lpvBuffer); 02017 async_data->inet_buffers.lpvBuffer = NULL; 02018 SetEvent(async_data->completion_event); 02019 RpcHttpAsyncData_Release(async_data); 02020 } 02021 break; 02022 } 02023 } 02024 02025 static RPC_STATUS rpcrt4_http_check_response(HINTERNET hor) 02026 { 02027 BOOL ret; 02028 DWORD status_code; 02029 DWORD size; 02030 DWORD index; 02031 WCHAR buf[32]; 02032 WCHAR *status_text = buf; 02033 TRACE("\n"); 02034 02035 index = 0; 02036 size = sizeof(status_code); 02037 ret = HttpQueryInfoW(hor, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &status_code, &size, &index); 02038 if (!ret) 02039 return GetLastError(); 02040 if (status_code < 400) 02041 return RPC_S_OK; 02042 index = 0; 02043 size = sizeof(buf); 02044 ret = HttpQueryInfoW(hor, HTTP_QUERY_STATUS_TEXT, status_text, &size, &index); 02045 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER) 02046 { 02047 status_text = HeapAlloc(GetProcessHeap(), 0, size); 02048 ret = HttpQueryInfoW(hor, HTTP_QUERY_STATUS_TEXT, status_text, &size, &index); 02049 } 02050 02051 ERR("server returned: %d %s\n", status_code, ret ? debugstr_w(status_text) : "<status text unavailable>"); 02052 if(status_text != buf) HeapFree(GetProcessHeap(), 0, status_text); 02053 02054 if (status_code == HTTP_STATUS_DENIED) 02055 return ERROR_ACCESS_DENIED; 02056 return RPC_S_SERVER_UNAVAILABLE; 02057 } 02058 02059 static RPC_STATUS rpcrt4_http_internet_connect(RpcConnection_http *httpc) 02060 { 02061 static const WCHAR wszUserAgent[] = {'M','S','R','P','C',0}; 02062 LPWSTR proxy = NULL; 02063 LPWSTR user = NULL; 02064 LPWSTR password = NULL; 02065 LPWSTR servername = NULL; 02066 const WCHAR *option; 02067 INTERNET_PORT port = INTERNET_INVALID_PORT_NUMBER; /* use default port */ 02068 02069 if (httpc->common.QOS && 02070 (httpc->common.QOS->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)) 02071 { 02072 const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_cred = httpc->common.QOS->qos->u.HttpCredentials; 02073 if (http_cred->TransportCredentials) 02074 { 02075 WCHAR *p; 02076 const SEC_WINNT_AUTH_IDENTITY_W *cred = http_cred->TransportCredentials; 02077 ULONG len = cred->DomainLength + 1 + cred->UserLength; 02078 user = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR)); 02079 if (!user) 02080 return RPC_S_OUT_OF_RESOURCES; 02081 p = user; 02082 if (cred->DomainLength) 02083 { 02084 memcpy(p, cred->Domain, cred->DomainLength * sizeof(WCHAR)); 02085 p += cred->DomainLength; 02086 *p = '\\'; 02087 p++; 02088 } 02089 memcpy(p, cred->User, cred->UserLength * sizeof(WCHAR)); 02090 p[cred->UserLength] = 0; 02091 02092 password = RPCRT4_strndupW(cred->Password, cred->PasswordLength); 02093 } 02094 } 02095 02096 for (option = httpc->common.NetworkOptions; option; 02097 option = (strchrW(option, ',') ? strchrW(option, ',')+1 : NULL)) 02098 { 02099 static const WCHAR wszRpcProxy[] = {'R','p','c','P','r','o','x','y','=',0}; 02100 static const WCHAR wszHttpProxy[] = {'H','t','t','p','P','r','o','x','y','=',0}; 02101 02102 if (!strncmpiW(option, wszRpcProxy, sizeof(wszRpcProxy)/sizeof(wszRpcProxy[0])-1)) 02103 { 02104 const WCHAR *value_start = option + sizeof(wszRpcProxy)/sizeof(wszRpcProxy[0])-1; 02105 const WCHAR *value_end; 02106 const WCHAR *p; 02107 02108 value_end = strchrW(option, ','); 02109 if (!value_end) 02110 value_end = value_start + strlenW(value_start); 02111 for (p = value_start; p < value_end; p++) 02112 if (*p == ':') 02113 { 02114 port = atoiW(p+1); 02115 value_end = p; 02116 break; 02117 } 02118 TRACE("RpcProxy value is %s\n", debugstr_wn(value_start, value_end-value_start)); 02119 servername = RPCRT4_strndupW(value_start, value_end-value_start); 02120 } 02121 else if (!strncmpiW(option, wszHttpProxy, sizeof(wszHttpProxy)/sizeof(wszHttpProxy[0])-1)) 02122 { 02123 const WCHAR *value_start = option + sizeof(wszHttpProxy)/sizeof(wszHttpProxy[0])-1; 02124 const WCHAR *value_end; 02125 02126 value_end = strchrW(option, ','); 02127 if (!value_end) 02128 value_end = value_start + strlenW(value_start); 02129 TRACE("HttpProxy value is %s\n", debugstr_wn(value_start, value_end-value_start)); 02130 proxy = RPCRT4_strndupW(value_start, value_end-value_start); 02131 } 02132 else 02133 FIXME("unhandled option %s\n", debugstr_w(option)); 02134 } 02135 02136 httpc->app_info = InternetOpenW(wszUserAgent, proxy ? INTERNET_OPEN_TYPE_PROXY : INTERNET_OPEN_TYPE_PRECONFIG, 02137 NULL, NULL, INTERNET_FLAG_ASYNC); 02138 if (!httpc->app_info) 02139 { 02140 HeapFree(GetProcessHeap(), 0, password); 02141 HeapFree(GetProcessHeap(), 0, user); 02142 ERR("InternetOpenW failed with error %d\n", GetLastError()); 02143 return RPC_S_SERVER_UNAVAILABLE; 02144 } 02145 InternetSetStatusCallbackW(httpc->app_info, rpcrt4_http_internet_callback); 02146 02147 /* if no RpcProxy option specified, set the HTTP server address to the 02148 * RPC server address */ 02149 if (!servername) 02150 { 02151 servername = HeapAlloc(GetProcessHeap(), 0, (strlen(httpc->common.NetworkAddr) + 1)*sizeof(WCHAR)); 02152 if (!servername) 02153 { 02154 HeapFree(GetProcessHeap(), 0, password); 02155 HeapFree(GetProcessHeap(), 0, user); 02156 return RPC_S_OUT_OF_RESOURCES; 02157 } 02158 MultiByteToWideChar(CP_ACP, 0, httpc->common.NetworkAddr, -1, servername, strlen(httpc->common.NetworkAddr) + 1); 02159 } 02160 02161 httpc->session = InternetConnectW(httpc->app_info, servername, port, user, password, 02162 INTERNET_SERVICE_HTTP, 0, 0); 02163 02164 HeapFree(GetProcessHeap(), 0, password); 02165 HeapFree(GetProcessHeap(), 0, user); 02166 HeapFree(GetProcessHeap(), 0, servername); 02167 02168 if (!httpc->session) 02169 { 02170 ERR("InternetConnectW failed with error %d\n", GetLastError()); 02171 return RPC_S_SERVER_UNAVAILABLE; 02172 } 02173 02174 return RPC_S_OK; 02175 } 02176 02177 /* prepare the in pipe for use by RPC packets */ 02178 static RPC_STATUS rpcrt4_http_prepare_in_pipe(HINTERNET in_request, RpcHttpAsyncData *async_data, 02179 const UUID *connection_uuid, 02180 const UUID *in_pipe_uuid, 02181 const UUID *association_uuid) 02182 { 02183 BYTE packet[44]; 02184 BOOL ret; 02185 RPC_STATUS status; 02186 RpcPktHdr *hdr; 02187 INTERNET_BUFFERSW buffers_in; 02188 DWORD bytes_read, bytes_written; 02189 02190 /* prepare in pipe */ 02191 ResetEvent(async_data->completion_event); 02192 RpcHttpAsyncData_AddRef(async_data); 02193 ret = HttpSendRequestW(in_request, NULL, 0, NULL, 0); 02194 if (!ret) 02195 { 02196 if (GetLastError() == ERROR_IO_PENDING) 02197 WaitForSingleObject(async_data->completion_event, INFINITE); 02198 else 02199 { 02200 RpcHttpAsyncData_Release(async_data); 02201 ERR("HttpSendRequestW failed with error %d\n", GetLastError()); 02202 return RPC_S_SERVER_UNAVAILABLE; 02203 } 02204 } 02205 status = rpcrt4_http_check_response(in_request); 02206 if (status != RPC_S_OK) return status; 02207 02208 InternetReadFile(in_request, packet, 20, &bytes_read); 02209 /* FIXME: do something with retrieved data */ 02210 02211 memset(&buffers_in, 0, sizeof(buffers_in)); 02212 buffers_in.dwStructSize = sizeof(buffers_in); 02213 /* FIXME: get this from the registry */ 02214 buffers_in.dwBufferTotal = 1024 * 1024 * 1024; /* 1Gb */ 02215 ResetEvent(async_data->completion_event); 02216 RpcHttpAsyncData_AddRef(async_data); 02217 ret = HttpSendRequestExW(in_request, &buffers_in, NULL, 0, 0); 02218 if (!ret) 02219 { 02220 if (GetLastError() == ERROR_IO_PENDING) 02221 WaitForSingleObject(async_data->completion_event, INFINITE); 02222 else 02223 { 02224 RpcHttpAsyncData_Release(async_data); 02225 ERR("HttpSendRequestExW failed with error %d\n", GetLastError()); 02226 return RPC_S_SERVER_UNAVAILABLE; 02227 } 02228 } 02229 02230 TRACE("sending HTTP connect header to server\n"); 02231 hdr = RPCRT4_BuildHttpConnectHeader(0, FALSE, connection_uuid, in_pipe_uuid, association_uuid); 02232 if (!hdr) return RPC_S_OUT_OF_RESOURCES; 02233 ret = InternetWriteFile(in_request, hdr, hdr->common.frag_len, &bytes_written); 02234 RPCRT4_FreeHeader(hdr); 02235 if (!ret) 02236 { 02237 ERR("InternetWriteFile failed with error %d\n", GetLastError()); 02238 return RPC_S_SERVER_UNAVAILABLE; 02239 } 02240 02241 return RPC_S_OK; 02242 } 02243 02244 static RPC_STATUS rpcrt4_http_read_http_packet(HINTERNET request, RpcPktHdr *hdr, BYTE **data) 02245 { 02246 BOOL ret; 02247 DWORD bytes_read; 02248 unsigned short data_len; 02249 02250 ret = InternetReadFile(request, hdr, sizeof(hdr->common), &bytes_read); 02251 if (!ret) 02252 return RPC_S_SERVER_UNAVAILABLE; 02253 if (hdr->common.ptype != PKT_HTTP || hdr->common.frag_len < sizeof(hdr->http)) 02254 { 02255 ERR("wrong packet type received %d or wrong frag_len %d\n", 02256 hdr->common.ptype, hdr->common.frag_len); 02257 return RPC_S_PROTOCOL_ERROR; 02258 } 02259 02260 ret = InternetReadFile(request, &hdr->common + 1, sizeof(hdr->http) - sizeof(hdr->common), &bytes_read); 02261 if (!ret) 02262 return RPC_S_SERVER_UNAVAILABLE; 02263 02264 data_len = hdr->common.frag_len - sizeof(hdr->http); 02265 if (data_len) 02266 { 02267 *data = HeapAlloc(GetProcessHeap(), 0, data_len); 02268 if (!*data) 02269 return RPC_S_OUT_OF_RESOURCES; 02270 ret = InternetReadFile(request, *data, data_len, &bytes_read); 02271 if (!ret) 02272 { 02273 HeapFree(GetProcessHeap(), 0, *data); 02274 return RPC_S_SERVER_UNAVAILABLE; 02275 } 02276 } 02277 else 02278 *data = NULL; 02279 02280 if (!RPCRT4_IsValidHttpPacket(hdr, *data, data_len)) 02281 { 02282 ERR("invalid http packet\n"); 02283 return RPC_S_PROTOCOL_ERROR; 02284 } 02285 02286 return RPC_S_OK; 02287 } 02288 02289 /* prepare the out pipe for use by RPC packets */ 02290 static RPC_STATUS rpcrt4_http_prepare_out_pipe(HINTERNET out_request, 02291 RpcHttpAsyncData *async_data, 02292 const UUID *connection_uuid, 02293 const UUID *out_pipe_uuid, 02294 ULONG *flow_control_increment) 02295 { 02296 BYTE packet[20]; 02297 BOOL ret; 02298 RPC_STATUS status; 02299 RpcPktHdr *hdr; 02300 DWORD bytes_read; 02301 BYTE *data_from_server; 02302 RpcPktHdr pkt_from_server; 02303 ULONG field1, field3; 02304 02305 ResetEvent(async_data->completion_event); 02306 RpcHttpAsyncData_AddRef(async_data); 02307 ret = HttpSendRequestW(out_request, NULL, 0, NULL, 0); 02308 if (!ret) 02309 { 02310 if (GetLastError() == ERROR_IO_PENDING) 02311 WaitForSingleObject(async_data->completion_event, INFINITE); 02312 else 02313 { 02314 RpcHttpAsyncData_Release(async_data); 02315 ERR("HttpSendRequestW failed with error %d\n", GetLastError()); 02316 return RPC_S_SERVER_UNAVAILABLE; 02317 } 02318 } 02319 status = rpcrt4_http_check_response(out_request); 02320 if (status != RPC_S_OK) return status; 02321 02322 InternetReadFile(out_request, packet, 20, &bytes_read); 02323 /* FIXME: do something with retrieved data */ 02324 02325 hdr = RPCRT4_BuildHttpConnectHeader(0, TRUE, connection_uuid, out_pipe_uuid, NULL); 02326 if (!hdr) return RPC_S_OUT_OF_RESOURCES; 02327 ResetEvent(async_data->completion_event); 02328 RpcHttpAsyncData_AddRef(async_data); 02329 ret = HttpSendRequestW(out_request, NULL, 0, hdr, hdr->common.frag_len); 02330 if (!ret) 02331 { 02332 if (GetLastError() == ERROR_IO_PENDING) 02333 WaitForSingleObject(async_data->completion_event, INFINITE); 02334 else 02335 { 02336 RpcHttpAsyncData_Release(async_data); 02337 ERR("HttpSendRequestW failed with error %d\n", GetLastError()); 02338 RPCRT4_FreeHeader(hdr); 02339 return RPC_S_SERVER_UNAVAILABLE; 02340 } 02341 } 02342 RPCRT4_FreeHeader(hdr); 02343 status = rpcrt4_http_check_response(out_request); 02344 if (status != RPC_S_OK) return status; 02345 02346 status = rpcrt4_http_read_http_packet(out_request, &pkt_from_server, 02347 &data_from_server); 02348 if (status != RPC_S_OK) return status; 02349 status = RPCRT4_ParseHttpPrepareHeader1(&pkt_from_server, data_from_server, 02350 &field1); 02351 HeapFree(GetProcessHeap(), 0, data_from_server); 02352 if (status != RPC_S_OK) return status; 02353 TRACE("received (%d) from first prepare header\n", field1); 02354 02355 status = rpcrt4_http_read_http_packet(out_request, &pkt_from_server, 02356 &data_from_server); 02357 if (status != RPC_S_OK) return status; 02358 status = RPCRT4_ParseHttpPrepareHeader2(&pkt_from_server, data_from_server, 02359 &field1, flow_control_increment, 02360 &field3); 02361 HeapFree(GetProcessHeap(), 0, data_from_server); 02362 if (status != RPC_S_OK) return status; 02363 TRACE("received (0x%08x 0x%08x %d) from second prepare header\n", field1, *flow_control_increment, field3); 02364 02365 return RPC_S_OK; 02366 } 02367 02368 static RPC_STATUS rpcrt4_ncacn_http_open(RpcConnection* Connection) 02369 { 02370 RpcConnection_http *httpc = (RpcConnection_http *)Connection; 02371 static const WCHAR wszVerbIn[] = {'R','P','C','_','I','N','_','D','A','T','A',0}; 02372 static const WCHAR wszVerbOut[] = {'R','P','C','_','O','U','T','_','D','A','T','A',0}; 02373 static const WCHAR wszRpcProxyPrefix[] = {'/','r','p','c','/','r','p','c','p','r','o','x','y','.','d','l','l','?',0}; 02374 static const WCHAR wszColon[] = {':',0}; 02375 static const WCHAR wszAcceptType[] = {'a','p','p','l','i','c','a','t','i','o','n','/','r','p','c',0}; 02376 LPCWSTR wszAcceptTypes[] = { wszAcceptType, NULL }; 02377 WCHAR *url; 02378 RPC_STATUS status; 02379 BOOL secure; 02380 HttpTimerThreadData *timer_data; 02381 HANDLE thread; 02382 02383 TRACE("(%s, %s)\n", Connection->NetworkAddr, Connection->Endpoint); 02384 02385 if (Connection->server) 02386 { 02387 ERR("ncacn_http servers not supported yet\n"); 02388 return RPC_S_SERVER_UNAVAILABLE; 02389 } 02390 02391 if (httpc->in_request) 02392 return RPC_S_OK; 02393 02394 httpc->async_data->completion_event = CreateEventW(NULL, FALSE, FALSE, NULL); 02395 02396 status = UuidCreate(&httpc->connection_uuid); 02397 status = UuidCreate(&httpc->in_pipe_uuid); 02398 status = UuidCreate(&httpc->out_pipe_uuid); 02399 02400 status = rpcrt4_http_internet_connect(httpc); 02401 if (status != RPC_S_OK) 02402 return status; 02403 02404 url = HeapAlloc(GetProcessHeap(), 0, sizeof(wszRpcProxyPrefix) + (strlen(Connection->NetworkAddr) + 1 + strlen(Connection->Endpoint))*sizeof(WCHAR)); 02405 if (!url) 02406 return RPC_S_OUT_OF_MEMORY; 02407 memcpy(url, wszRpcProxyPrefix, sizeof(wszRpcProxyPrefix)); 02408 MultiByteToWideChar(CP_ACP, 0, Connection->NetworkAddr, -1, url+sizeof(wszRpcProxyPrefix)/sizeof(wszRpcProxyPrefix[0])-1, strlen(Connection->NetworkAddr)+1); 02409 strcatW(url, wszColon); 02410 MultiByteToWideChar(CP_ACP, 0, Connection->Endpoint, -1, url+strlenW(url), strlen(Connection->Endpoint)+1); 02411 02412 secure = httpc->common.QOS && 02413 (httpc->common.QOS->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP) && 02414 (httpc->common.QOS->qos->u.HttpCredentials->Flags & RPC_C_HTTP_FLAG_USE_SSL); 02415 02416 httpc->in_request = HttpOpenRequestW(httpc->session, wszVerbIn, url, NULL, NULL, 02417 wszAcceptTypes, 02418 (secure ? INTERNET_FLAG_SECURE : 0)|INTERNET_FLAG_KEEP_CONNECTION|INTERNET_FLAG_PRAGMA_NOCACHE, 02419 (DWORD_PTR)httpc->async_data); 02420 if (!httpc->in_request) 02421 { 02422 ERR("HttpOpenRequestW failed with error %d\n", GetLastError()); 02423 return RPC_S_SERVER_UNAVAILABLE; 02424 } 02425 httpc->out_request = HttpOpenRequestW(httpc->session, wszVerbOut, url, NULL, NULL, 02426 wszAcceptTypes, 02427 (secure ? INTERNET_FLAG_SECURE : 0)|INTERNET_FLAG_KEEP_CONNECTION|INTERNET_FLAG_PRAGMA_NOCACHE, 02428 (DWORD_PTR)httpc->async_data); 02429 if (!httpc->out_request) 02430 { 02431 ERR("HttpOpenRequestW failed with error %d\n", GetLastError()); 02432 return RPC_S_SERVER_UNAVAILABLE; 02433 } 02434 02435 status = rpcrt4_http_prepare_in_pipe(httpc->in_request, 02436 httpc->async_data, 02437 &httpc->connection_uuid, 02438 &httpc->in_pipe_uuid, 02439 &Connection->assoc->http_uuid); 02440 if (status != RPC_S_OK) 02441 return status; 02442 02443 status = rpcrt4_http_prepare_out_pipe(httpc->out_request, 02444 httpc->async_data, 02445 &httpc->connection_uuid, 02446 &httpc->out_pipe_uuid, 02447 &httpc->flow_control_increment); 02448 if (status != RPC_S_OK) 02449 return status; 02450 02451 httpc->flow_control_mark = httpc->flow_control_increment / 2; 02452 httpc->last_sent_time = GetTickCount(); 02453 httpc->timer_cancelled = CreateEventW(NULL, FALSE, FALSE, NULL); 02454 02455 timer_data = HeapAlloc(GetProcessHeap(), 0, sizeof(*timer_data)); 02456 if (!timer_data) 02457 return ERROR_OUTOFMEMORY; 02458 timer_data->timer_param = httpc->in_request; 02459 timer_data->last_sent_time = &httpc->last_sent_time; 02460 timer_data->timer_cancelled = httpc->timer_cancelled; 02461 /* FIXME: should use CreateTimerQueueTimer when implemented */ 02462 thread = CreateThread(NULL, 0, rpcrt4_http_timer_thread, timer_data, 0, NULL); 02463 if (!thread) 02464 { 02465 HeapFree(GetProcessHeap(), 0, timer_data); 02466 return GetLastError(); 02467 } 02468 CloseHandle(thread); 02469 02470 return RPC_S_OK; 02471 } 02472 02473 static RPC_STATUS rpcrt4_ncacn_http_handoff(RpcConnection *old_conn, RpcConnection *new_conn) 02474 { 02475 assert(0); 02476 return RPC_S_SERVER_UNAVAILABLE; 02477 } 02478 02479 static int rpcrt4_ncacn_http_read(RpcConnection *Connection, 02480 void *buffer, unsigned int count) 02481 { 02482 RpcConnection_http *httpc = (RpcConnection_http *) Connection; 02483 char *buf = buffer; 02484 BOOL ret = TRUE; 02485 unsigned int bytes_left = count; 02486 02487 ResetEvent(httpc->async_data->completion_event); 02488 while (bytes_left) 02489 { 02490 RpcHttpAsyncData_AddRef(httpc->async_data); 02491 httpc->async_data->inet_buffers.dwBufferLength = bytes_left; 02492 httpc->async_data->inet_buffers.lpvBuffer = HeapAlloc(GetProcessHeap(), 0, bytes_left); 02493 httpc->async_data->destination_buffer = buf; 02494 ret = InternetReadFileExA(httpc->out_request, &httpc->async_data->inet_buffers, IRF_ASYNC, 0); 02495 if (ret) 02496 { 02497 /* INTERNET_STATUS_REQUEST_COMPLETED won't be sent, so release our 02498 * async ref now */ 02499 RpcHttpAsyncData_Release(httpc->async_data); 02500 memcpy(buf, httpc->async_data->inet_buffers.lpvBuffer, 02501 httpc->async_data->inet_buffers.dwBufferLength); 02502 HeapFree(GetProcessHeap(), 0, httpc->async_data->inet_buffers.lpvBuffer); 02503 httpc->async_data->inet_buffers.lpvBuffer = NULL; 02504 httpc->async_data->destination_buffer = NULL; 02505 } 02506 else 02507 { 02508 if (GetLastError() == ERROR_IO_PENDING) 02509 { 02510 HANDLE handles[2] = { httpc->async_data->completion_event, httpc->cancel_event }; 02511 DWORD result = WaitForMultipleObjects(2, handles, FALSE, DEFAULT_NCACN_HTTP_TIMEOUT); 02512 if (result == WAIT_OBJECT_0) 02513 ret = TRUE; 02514 else 02515 { 02516 TRACE("call cancelled\n"); 02517 EnterCriticalSection(&httpc->async_data->cs); 02518 httpc->async_data->destination_buffer = NULL; 02519 LeaveCriticalSection(&httpc->async_data->cs); 02520 break; 02521 } 02522 } 02523 else 02524 { 02525 HeapFree(GetProcessHeap(), 0, httpc->async_data->inet_buffers.lpvBuffer); 02526 httpc->async_data->inet_buffers.lpvBuffer = NULL; 02527 httpc->async_data->destination_buffer = NULL; 02528 RpcHttpAsyncData_Release(httpc->async_data); 02529 break; 02530 } 02531 } 02532 if (!httpc->async_data->inet_buffers.dwBufferLength) 02533 break; 02534 bytes_left -= httpc->async_data->inet_buffers.dwBufferLength; 02535 buf += httpc->async_data->inet_buffers.dwBufferLength; 02536 } 02537 TRACE("%p %p %u -> %s\n", httpc->out_request, buffer, count, ret ? "TRUE" : "FALSE"); 02538 return ret ? count : -1; 02539 } 02540 02541 static RPC_STATUS rpcrt4_ncacn_http_receive_fragment(RpcConnection *Connection, RpcPktHdr **Header, void **Payload) 02542 { 02543 RpcConnection_http *httpc = (RpcConnection_http *) Connection; 02544 RPC_STATUS status; 02545 DWORD hdr_length; 02546 LONG dwRead; 02547 RpcPktCommonHdr common_hdr; 02548 02549 *Header = NULL; 02550 02551 TRACE("(%p, %p, %p)\n", Connection, Header, Payload); 02552 02553 again: 02554 /* read packet common header */ 02555 dwRead = rpcrt4_ncacn_http_read(Connection, &common_hdr, sizeof(common_hdr)); 02556 if (dwRead != sizeof(common_hdr)) { 02557 WARN("Short read of header, %d bytes\n", dwRead); 02558 status = RPC_S_PROTOCOL_ERROR; 02559 goto fail; 02560 } 02561 if (!memcmp(&common_hdr, "HTTP/1.1", sizeof("HTTP/1.1")) || 02562 !memcmp(&common_hdr, "HTTP/1.0", sizeof("HTTP/1.0"))) 02563 { 02564 FIXME("server returned %s\n", debugstr_a((const char *)&common_hdr)); 02565 status = RPC_S_PROTOCOL_ERROR; 02566 goto fail; 02567 } 02568 02569 status = RPCRT4_ValidateCommonHeader(&common_hdr); 02570 if (status != RPC_S_OK) goto fail; 02571 02572 hdr_length = RPCRT4_GetHeaderSize((RpcPktHdr*)&common_hdr); 02573 if (hdr_length == 0) { 02574 WARN("header length == 0\n"); 02575 status = RPC_S_PROTOCOL_ERROR; 02576 goto fail; 02577 } 02578 02579 *Header = HeapAlloc(GetProcessHeap(), 0, hdr_length); 02580 if (!*Header) 02581 { 02582 status = RPC_S_OUT_OF_RESOURCES; 02583 goto fail; 02584 } 02585 memcpy(*Header, &common_hdr, sizeof(common_hdr)); 02586 02587 /* read the rest of packet header */ 02588 dwRead = rpcrt4_ncacn_http_read(Connection, &(*Header)->common + 1, hdr_length - sizeof(common_hdr)); 02589 if (dwRead != hdr_length - sizeof(common_hdr)) { 02590 WARN("bad header length, %d bytes, hdr_length %d\n", dwRead, hdr_length); 02591 status = RPC_S_PROTOCOL_ERROR; 02592 goto fail; 02593 } 02594 02595 if (common_hdr.frag_len - hdr_length) 02596 { 02597 *Payload = HeapAlloc(GetProcessHeap(), 0, common_hdr.frag_len - hdr_length); 02598 if (!*Payload) 02599 { 02600 status = RPC_S_OUT_OF_RESOURCES; 02601 goto fail; 02602 } 02603 02604 dwRead = rpcrt4_ncacn_http_read(Connection, *Payload, common_hdr.frag_len - hdr_length); 02605 if (dwRead != common_hdr.frag_len - hdr_length) 02606 { 02607 WARN("bad data length, %d/%d\n", dwRead, common_hdr.frag_len - hdr_length); 02608 status = RPC_S_PROTOCOL_ERROR; 02609 goto fail; 02610 } 02611 } 02612 else 02613 *Payload = NULL; 02614 02615 if ((*Header)->common.ptype == PKT_HTTP) 02616 { 02617 if (!RPCRT4_IsValidHttpPacket(*Header, *Payload, common_hdr.frag_len - hdr_length)) 02618 { 02619 ERR("invalid http packet of length %d bytes\n", (*Header)->common.frag_len); 02620 status = RPC_S_PROTOCOL_ERROR; 02621 goto fail; 02622 } 02623 if ((*Header)->http.flags == 0x0001) 02624 { 02625 TRACE("http idle packet, waiting for real packet\n"); 02626 if ((*Header)->http.num_data_items != 0) 02627 { 02628 ERR("HTTP idle packet should have no data items instead of %d\n", (*Header)->http.num_data_items); 02629 status = RPC_S_PROTOCOL_ERROR; 02630 goto fail; 02631 } 02632 } 02633 else if ((*Header)->http.flags == 0x0002) 02634 { 02635 ULONG bytes_transmitted; 02636 ULONG flow_control_increment; 02637 UUID pipe_uuid; 02638 status = RPCRT4_ParseHttpFlowControlHeader(*Header, *Payload, 02639 Connection->server, 02640 &bytes_transmitted, 02641 &flow_control_increment, 02642 &pipe_uuid); 02643 if (status != RPC_S_OK) 02644 goto fail; 02645 TRACE("received http flow control header (0x%x, 0x%x, %s)\n", 02646 bytes_transmitted, flow_control_increment, debugstr_guid(&pipe_uuid)); 02647 /* FIXME: do something with parsed data */ 02648 } 02649 else 02650 { 02651 FIXME("unrecognised http packet with flags 0x%04x\n", (*Header)->http.flags); 02652 status = RPC_S_PROTOCOL_ERROR; 02653 goto fail; 02654 } 02655 RPCRT4_FreeHeader(*Header); 02656 *Header = NULL; 02657 HeapFree(GetProcessHeap(), 0, *Payload); 02658 *Payload = NULL; 02659 goto again; 02660 } 02661 02662 /* success */ 02663 status = RPC_S_OK; 02664 02665 httpc->bytes_received += common_hdr.frag_len; 02666 02667 TRACE("httpc->bytes_received = 0x%x\n", httpc->bytes_received); 02668 02669 if (httpc->bytes_received > httpc->flow_control_mark) 02670 { 02671 RpcPktHdr *hdr = RPCRT4_BuildHttpFlowControlHeader(httpc->common.server, 02672 httpc->bytes_received, 02673 httpc->flow_control_increment, 02674 &httpc->out_pipe_uuid); 02675 if (hdr) 02676 { 02677 DWORD bytes_written; 02678 BOOL ret2; 02679 TRACE("sending flow control packet at 0x%x\n", httpc->bytes_received); 02680 ret2 = InternetWriteFile(httpc->in_request, hdr, hdr->common.frag_len, &bytes_written); 02681 RPCRT4_FreeHeader(hdr); 02682 if (ret2) 02683 httpc->flow_control_mark = httpc->bytes_received + httpc->flow_control_increment / 2; 02684 } 02685 } 02686 02687 fail: 02688 if (status != RPC_S_OK) { 02689 RPCRT4_FreeHeader(*Header); 02690 *Header = NULL; 02691 HeapFree(GetProcessHeap(), 0, *Payload); 02692 *Payload = NULL; 02693 } 02694 return status; 02695 } 02696 02697 static int rpcrt4_ncacn_http_write(RpcConnection *Connection, 02698 const void *buffer, unsigned int count) 02699 { 02700 RpcConnection_http *httpc = (RpcConnection_http *) Connection; 02701 DWORD bytes_written; 02702 BOOL ret; 02703 02704 httpc->last_sent_time = ~0U; /* disable idle packet sending */ 02705 ret = InternetWriteFile(httpc->in_request, buffer, count, &bytes_written); 02706 httpc->last_sent_time = GetTickCount(); 02707 TRACE("%p %p %u -> %s\n", httpc->in_request, buffer, count, ret ? "TRUE" : "FALSE"); 02708 return ret ? bytes_written : -1; 02709 } 02710 02711 static int rpcrt4_ncacn_http_close(RpcConnection *Connection) 02712 { 02713 RpcConnection_http *httpc = (RpcConnection_http *) Connection; 02714 02715 TRACE("\n"); 02716 02717 SetEvent(httpc->timer_cancelled); 02718 if (httpc->in_request) 02719 InternetCloseHandle(httpc->in_request); 02720 httpc->in_request = NULL; 02721 if (httpc->out_request) 02722 InternetCloseHandle(httpc->out_request); 02723 httpc->out_request = NULL; 02724 if (httpc->app_info) 02725 InternetCloseHandle(httpc->app_info); 02726 httpc->app_info = NULL; 02727 if (httpc->session) 02728 InternetCloseHandle(httpc->session); 02729 httpc->session = NULL; 02730 RpcHttpAsyncData_Release(httpc->async_data); 02731 if (httpc->cancel_event) 02732 CloseHandle(httpc->cancel_event); 02733 02734 return 0; 02735 } 02736 02737 static void rpcrt4_ncacn_http_cancel_call(RpcConnection *Connection) 02738 { 02739 RpcConnection_http *httpc = (RpcConnection_http *) Connection; 02740 02741 SetEvent(httpc->cancel_event); 02742 } 02743 02744 static int rpcrt4_ncacn_http_wait_for_incoming_data(RpcConnection *Connection) 02745 { 02746 BOOL ret; 02747 RpcConnection_http *httpc = (RpcConnection_http *) Connection; 02748 02749 RpcHttpAsyncData_AddRef(httpc->async_data); 02750 ret = InternetQueryDataAvailable(httpc->out_request, 02751 &httpc->async_data->inet_buffers.dwBufferLength, IRF_ASYNC, 0); 02752 if (ret) 02753 { 02754 /* INTERNET_STATUS_REQUEST_COMPLETED won't be sent, so release our 02755 * async ref now */ 02756 RpcHttpAsyncData_Release(httpc->async_data); 02757 } 02758 else 02759 { 02760 if (GetLastError() == ERROR_IO_PENDING) 02761 { 02762 HANDLE handles[2] = { httpc->async_data->completion_event, httpc->cancel_event }; 02763 DWORD result = WaitForMultipleObjects(2, handles, FALSE, DEFAULT_NCACN_HTTP_TIMEOUT); 02764 if (result != WAIT_OBJECT_0) 02765 { 02766 TRACE("call cancelled\n"); 02767 return -1; 02768 } 02769 } 02770 else 02771 { 02772 RpcHttpAsyncData_Release(httpc->async_data); 02773 return -1; 02774 } 02775 } 02776 02777 /* success */ 02778 return 0; 02779 } 02780 02781 static size_t rpcrt4_ncacn_http_get_top_of_tower(unsigned char *tower_data, 02782 const char *networkaddr, 02783 const char *endpoint) 02784 { 02785 return rpcrt4_ip_tcp_get_top_of_tower(tower_data, networkaddr, 02786 EPM_PROTOCOL_HTTP, endpoint); 02787 } 02788 02789 static RPC_STATUS rpcrt4_ncacn_http_parse_top_of_tower(const unsigned char *tower_data, 02790 size_t tower_size, 02791 char **networkaddr, 02792 char **endpoint) 02793 { 02794 return rpcrt4_ip_tcp_parse_top_of_tower(tower_data, tower_size, 02795 networkaddr, EPM_PROTOCOL_HTTP, 02796 endpoint); 02797 } 02798 02799 static const struct connection_ops conn_protseq_list[] = { 02800 { "ncacn_np", 02801 { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_SMB }, 02802 rpcrt4_conn_np_alloc, 02803 rpcrt4_ncacn_np_open, 02804 rpcrt4_ncacn_np_handoff, 02805 rpcrt4_conn_np_read, 02806 rpcrt4_conn_np_write, 02807 rpcrt4_conn_np_close, 02808 rpcrt4_conn_np_cancel_call, 02809 rpcrt4_conn_np_wait_for_incoming_data, 02810 rpcrt4_ncacn_np_get_top_of_tower, 02811 rpcrt4_ncacn_np_parse_top_of_tower, 02812 NULL, 02813 RPCRT4_default_is_authorized, 02814 RPCRT4_default_authorize, 02815 RPCRT4_default_secure_packet, 02816 rpcrt4_conn_np_impersonate_client, 02817 rpcrt4_conn_np_revert_to_self, 02818 RPCRT4_default_inquire_auth_client, 02819 }, 02820 { "ncalrpc", 02821 { EPM_PROTOCOL_NCALRPC, EPM_PROTOCOL_PIPE }, 02822 rpcrt4_conn_np_alloc, 02823 rpcrt4_ncalrpc_open, 02824 rpcrt4_ncalrpc_handoff, 02825 rpcrt4_conn_np_read, 02826 rpcrt4_conn_np_write, 02827 rpcrt4_conn_np_close, 02828 rpcrt4_conn_np_cancel_call, 02829 rpcrt4_conn_np_wait_for_incoming_data, 02830 rpcrt4_ncalrpc_get_top_of_tower, 02831 rpcrt4_ncalrpc_parse_top_of_tower, 02832 NULL, 02833 rpcrt4_ncalrpc_is_authorized, 02834 rpcrt4_ncalrpc_authorize, 02835 rpcrt4_ncalrpc_secure_packet, 02836 rpcrt4_conn_np_impersonate_client, 02837 rpcrt4_conn_np_revert_to_self, 02838 rpcrt4_ncalrpc_inquire_auth_client, 02839 }, 02840 { "ncacn_ip_tcp", 02841 { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_TCP }, 02842 rpcrt4_conn_tcp_alloc, 02843 rpcrt4_ncacn_ip_tcp_open, 02844 rpcrt4_conn_tcp_handoff, 02845 rpcrt4_conn_tcp_read, 02846 rpcrt4_conn_tcp_write, 02847 rpcrt4_conn_tcp_close, 02848 rpcrt4_conn_tcp_cancel_call, 02849 rpcrt4_conn_tcp_wait_for_incoming_data, 02850 rpcrt4_ncacn_ip_tcp_get_top_of_tower, 02851 rpcrt4_ncacn_ip_tcp_parse_top_of_tower, 02852 NULL, 02853 RPCRT4_default_is_authorized, 02854 RPCRT4_default_authorize, 02855 RPCRT4_default_secure_packet, 02856 RPCRT4_default_impersonate_client, 02857 RPCRT4_default_revert_to_self, 02858 RPCRT4_default_inquire_auth_client, 02859 }, 02860 { "ncacn_http", 02861 { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_HTTP }, 02862 rpcrt4_ncacn_http_alloc, 02863 rpcrt4_ncacn_http_open, 02864 rpcrt4_ncacn_http_handoff, 02865 rpcrt4_ncacn_http_read, 02866 rpcrt4_ncacn_http_write, 02867 rpcrt4_ncacn_http_close, 02868 rpcrt4_ncacn_http_cancel_call, 02869 rpcrt4_ncacn_http_wait_for_incoming_data, 02870 rpcrt4_ncacn_http_get_top_of_tower, 02871 rpcrt4_ncacn_http_parse_top_of_tower, 02872 rpcrt4_ncacn_http_receive_fragment, 02873 RPCRT4_default_is_authorized, 02874 RPCRT4_default_authorize, 02875 RPCRT4_default_secure_packet, 02876 RPCRT4_default_impersonate_client, 02877 RPCRT4_default_revert_to_self, 02878 RPCRT4_default_inquire_auth_client, 02879 }, 02880 }; 02881 02882 02883 static const struct protseq_ops protseq_list[] = 02884 { 02885 { 02886 "ncacn_np", 02887 rpcrt4_protseq_np_alloc, 02888 rpcrt4_protseq_np_signal_state_changed, 02889 rpcrt4_protseq_np_get_wait_array, 02890 rpcrt4_protseq_np_free_wait_array, 02891 rpcrt4_protseq_np_wait_for_new_connection, 02892 rpcrt4_protseq_ncacn_np_open_endpoint, 02893 }, 02894 { 02895 "ncalrpc", 02896 rpcrt4_protseq_np_alloc, 02897 rpcrt4_protseq_np_signal_state_changed, 02898 rpcrt4_protseq_np_get_wait_array, 02899 rpcrt4_protseq_np_free_wait_array, 02900 rpcrt4_protseq_np_wait_for_new_connection, 02901 rpcrt4_protseq_ncalrpc_open_endpoint, 02902 }, 02903 { 02904 "ncacn_ip_tcp", 02905 rpcrt4_protseq_sock_alloc, 02906 rpcrt4_protseq_sock_signal_state_changed, 02907 rpcrt4_protseq_sock_get_wait_array, 02908 rpcrt4_protseq_sock_free_wait_array, 02909 rpcrt4_protseq_sock_wait_for_new_connection, 02910 rpcrt4_protseq_ncacn_ip_tcp_open_endpoint, 02911 }, 02912 }; 02913 02914 #define ARRAYSIZE(a) (sizeof((a)) / sizeof((a)[0])) 02915 02916 const struct protseq_ops *rpcrt4_get_protseq_ops(const char *protseq) 02917 { 02918 unsigned int i; 02919 for(i=0; i<ARRAYSIZE(protseq_list); i++) 02920 if (!strcmp(protseq_list[i].name, protseq)) 02921 return &protseq_list[i]; 02922 return NULL; 02923 } 02924 02925 static const struct connection_ops *rpcrt4_get_conn_protseq_ops(const char *protseq) 02926 { 02927 unsigned int i; 02928 for(i=0; i<ARRAYSIZE(conn_protseq_list); i++) 02929 if (!strcmp(conn_protseq_list[i].name, protseq)) 02930 return &conn_protseq_list[i]; 02931 return NULL; 02932 } 02933 02934 /**** interface to rest of code ****/ 02935 02936 RPC_STATUS RPCRT4_OpenClientConnection(RpcConnection* Connection) 02937 { 02938 TRACE("(Connection == ^%p)\n", Connection); 02939 02940 assert(!Connection->server); 02941 return Connection->ops->open_connection_client(Connection); 02942 } 02943 02944 RPC_STATUS RPCRT4_CloseConnection(RpcConnection* Connection) 02945 { 02946 TRACE("(Connection == ^%p)\n", Connection); 02947 if (SecIsValidHandle(&Connection->ctx)) 02948 { 02949 DeleteSecurityContext(&Connection->ctx); 02950 SecInvalidateHandle(&Connection->ctx); 02951 } 02952 rpcrt4_conn_close(Connection); 02953 return RPC_S_OK; 02954 } 02955 02956 RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server, 02957 LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, 02958 LPCWSTR NetworkOptions, RpcAuthInfo* AuthInfo, RpcQualityOfService *QOS) 02959 { 02960 static LONG next_id; 02961 const struct connection_ops *ops; 02962 RpcConnection* NewConnection; 02963 02964 ops = rpcrt4_get_conn_protseq_ops(Protseq); 02965 if (!ops) 02966 { 02967 FIXME("not supported for protseq %s\n", Protseq); 02968 return RPC_S_PROTSEQ_NOT_SUPPORTED; 02969 } 02970 02971 NewConnection = ops->alloc(); 02972 NewConnection->Next = NULL; 02973 NewConnection->server_binding = NULL; 02974 NewConnection->server = server; 02975 NewConnection->ops = ops; 02976 NewConnection->NetworkAddr = RPCRT4_strdupA(NetworkAddr); 02977 NewConnection->Endpoint = RPCRT4_strdupA(Endpoint); 02978 NewConnection->NetworkOptions = RPCRT4_strdupW(NetworkOptions); 02979 NewConnection->MaxTransmissionSize = RPC_MAX_PACKET_SIZE; 02980 memset(&NewConnection->ActiveInterface, 0, sizeof(NewConnection->ActiveInterface)); 02981 NewConnection->NextCallId = 1; 02982 02983 SecInvalidateHandle(&NewConnection->ctx); 02984 memset(&NewConnection->exp, 0, sizeof(NewConnection->exp)); 02985 NewConnection->attr = 0; 02986 if (AuthInfo) RpcAuthInfo_AddRef(AuthInfo); 02987 NewConnection->AuthInfo = AuthInfo; 02988 NewConnection->auth_context_id = InterlockedIncrement( &next_id ); 02989 NewConnection->encryption_auth_len = 0; 02990 NewConnection->signature_auth_len = 0; 02991 if (QOS) RpcQualityOfService_AddRef(QOS); 02992 NewConnection->QOS = QOS; 02993 02994 list_init(&NewConnection->conn_pool_entry); 02995 NewConnection->async_state = NULL; 02996 02997 TRACE("connection: %p\n", NewConnection); 02998 *Connection = NewConnection; 02999 03000 return RPC_S_OK; 03001 } 03002 03003 static RPC_STATUS RPCRT4_SpawnConnection(RpcConnection** Connection, RpcConnection* OldConnection) 03004 { 03005 RPC_STATUS err; 03006 03007 err = RPCRT4_CreateConnection(Connection, OldConnection->server, 03008 rpcrt4_conn_get_name(OldConnection), 03009 OldConnection->NetworkAddr, 03010 OldConnection->Endpoint, NULL, 03011 OldConnection->AuthInfo, OldConnection->QOS); 03012 if (err == RPC_S_OK) 03013 rpcrt4_conn_handoff(OldConnection, *Connection); 03014 return err; 03015 } 03016 03017 RPC_STATUS RPCRT4_DestroyConnection(RpcConnection* Connection) 03018 { 03019 TRACE("connection: %p\n", Connection); 03020 03021 RPCRT4_CloseConnection(Connection); 03022 RPCRT4_strfree(Connection->Endpoint); 03023 RPCRT4_strfree(Connection->NetworkAddr); 03024 HeapFree(GetProcessHeap(), 0, Connection->NetworkOptions); 03025 if (Connection->AuthInfo) RpcAuthInfo_Release(Connection->AuthInfo); 03026 if (Connection->QOS) RpcQualityOfService_Release(Connection->QOS); 03027 03028 /* server-only */ 03029 if (Connection->server_binding) RPCRT4_ReleaseBinding(Connection->server_binding); 03030 03031 HeapFree(GetProcessHeap(), 0, Connection); 03032 return RPC_S_OK; 03033 } 03034 03035 RPC_STATUS RpcTransport_GetTopOfTower(unsigned char *tower_data, 03036 size_t *tower_size, 03037 const char *protseq, 03038 const char *networkaddr, 03039 const char *endpoint) 03040 { 03041 twr_empty_floor_t *protocol_floor; 03042 const struct connection_ops *protseq_ops = rpcrt4_get_conn_protseq_ops(protseq); 03043 03044 *tower_size = 0; 03045 03046 if (!protseq_ops) 03047 return RPC_S_INVALID_RPC_PROTSEQ; 03048 03049 if (!tower_data) 03050 { 03051 *tower_size = sizeof(*protocol_floor); 03052 *tower_size += protseq_ops->get_top_of_tower(NULL, networkaddr, endpoint); 03053 return RPC_S_OK; 03054 } 03055 03056 protocol_floor = (twr_empty_floor_t *)tower_data; 03057 protocol_floor->count_lhs = sizeof(protocol_floor->protid); 03058 protocol_floor->protid = protseq_ops->epm_protocols[0]; 03059 protocol_floor->count_rhs = 0; 03060 03061 tower_data += sizeof(*protocol_floor); 03062 03063 *tower_size = protseq_ops->get_top_of_tower(tower_data, networkaddr, endpoint); 03064 if (!*tower_size) 03065 return EPT_S_NOT_REGISTERED; 03066 03067 *tower_size += sizeof(*protocol_floor); 03068 03069 return RPC_S_OK; 03070 } 03071 03072 RPC_STATUS RpcTransport_ParseTopOfTower(const unsigned char *tower_data, 03073 size_t tower_size, 03074 char **protseq, 03075 char **networkaddr, 03076 char **endpoint) 03077 { 03078 const twr_empty_floor_t *protocol_floor; 03079 const twr_empty_floor_t *floor4; 03080 const struct connection_ops *protseq_ops = NULL; 03081 RPC_STATUS status; 03082 unsigned int i; 03083 03084 if (tower_size < sizeof(*protocol_floor)) 03085 return EPT_S_NOT_REGISTERED; 03086 03087 protocol_floor = (const twr_empty_floor_t *)tower_data; 03088 tower_data += sizeof(*protocol_floor); 03089 tower_size -= sizeof(*protocol_floor); 03090 if ((protocol_floor->count_lhs != sizeof(protocol_floor->protid)) || 03091 (protocol_floor->count_rhs > tower_size)) 03092 return EPT_S_NOT_REGISTERED; 03093 tower_data += protocol_floor->count_rhs; 03094 tower_size -= protocol_floor->count_rhs; 03095 03096 floor4 = (const twr_empty_floor_t *)tower_data; 03097 if ((tower_size < sizeof(*floor4)) || 03098 (floor4->count_lhs != sizeof(floor4->protid))) 03099 return EPT_S_NOT_REGISTERED; 03100 03101 for(i = 0; i < ARRAYSIZE(conn_protseq_list); i++) 03102 if ((protocol_floor->protid == conn_protseq_list[i].epm_protocols[0]) && 03103 (floor4->protid == conn_protseq_list[i].epm_protocols[1])) 03104 { 03105 protseq_ops = &conn_protseq_list[i]; 03106 break; 03107 } 03108 03109 if (!protseq_ops) 03110 return EPT_S_NOT_REGISTERED; 03111 03112 status = protseq_ops->parse_top_of_tower(tower_data, tower_size, networkaddr, endpoint); 03113 03114 if ((status == RPC_S_OK) && protseq) 03115 { 03116 *protseq = I_RpcAllocate(strlen(protseq_ops->name) + 1); 03117 strcpy(*protseq, protseq_ops->name); 03118 } 03119 03120 return status; 03121 } 03122 03123 /*********************************************************************** 03124 * RpcNetworkIsProtseqValidW (RPCRT4.@) 03125 * 03126 * Checks if the given protocol sequence is known by the RPC system. 03127 * If it is, returns RPC_S_OK, otherwise RPC_S_PROTSEQ_NOT_SUPPORTED. 03128 * 03129 */ 03130 RPC_STATUS WINAPI RpcNetworkIsProtseqValidW(RPC_WSTR protseq) 03131 { 03132 char ps[0x10]; 03133 03134 WideCharToMultiByte(CP_ACP, 0, protseq, -1, 03135 ps, sizeof ps, NULL, NULL); 03136 if (rpcrt4_get_conn_protseq_ops(ps)) 03137 return RPC_S_OK; 03138 03139 FIXME("Unknown protseq %s\n", debugstr_w(protseq)); 03140 03141 return RPC_S_INVALID_RPC_PROTSEQ; 03142 } 03143 03144 /*********************************************************************** 03145 * RpcNetworkIsProtseqValidA (RPCRT4.@) 03146 */ 03147 RPC_STATUS WINAPI RpcNetworkIsProtseqValidA(RPC_CSTR protseq) 03148 { 03149 UNICODE_STRING protseqW; 03150 03151 if (RtlCreateUnicodeStringFromAsciiz(&protseqW, (char*)protseq)) 03152 { 03153 RPC_STATUS ret = RpcNetworkIsProtseqValidW(protseqW.Buffer); 03154 RtlFreeUnicodeString(&protseqW); 03155 return ret; 03156 } 03157 return RPC_S_OUT_OF_MEMORY; 03158 } 03159 03160 /*********************************************************************** 03161 * RpcProtseqVectorFreeA (RPCRT4.@) 03162 */ 03163 RPC_STATUS WINAPI RpcProtseqVectorFreeA(RPC_PROTSEQ_VECTORA **protseqs) 03164 { 03165 TRACE("(%p)\n", protseqs); 03166 03167 if (*protseqs) 03168 { 03169 int i; 03170 for (i = 0; i < (*protseqs)->Count; i++) 03171 HeapFree(GetProcessHeap(), 0, (*protseqs)->Protseq[i]); 03172 HeapFree(GetProcessHeap(), 0, *protseqs); 03173 *protseqs = NULL; 03174 } 03175 return RPC_S_OK; 03176 } 03177 03178 /*********************************************************************** 03179 * RpcProtseqVectorFreeW (RPCRT4.@) 03180 */ 03181 RPC_STATUS WINAPI RpcProtseqVectorFreeW(RPC_PROTSEQ_VECTORW **protseqs) 03182 { 03183 TRACE("(%p)\n", protseqs); 03184 03185 if (*protseqs) 03186 { 03187 int i; 03188 for (i = 0; i < (*protseqs)->Count; i++) 03189 HeapFree(GetProcessHeap(), 0, (*protseqs)->Protseq[i]); 03190 HeapFree(GetProcessHeap(), 0, *protseqs); 03191 *protseqs = NULL; 03192 } 03193 return RPC_S_OK; 03194 } 03195 03196 /*********************************************************************** 03197 * RpcNetworkInqProtseqsW (RPCRT4.@) 03198 */ 03199 RPC_STATUS WINAPI RpcNetworkInqProtseqsW( RPC_PROTSEQ_VECTORW** protseqs ) 03200 { 03201 RPC_PROTSEQ_VECTORW *pvector; 03202 int i = 0; 03203 RPC_STATUS status = RPC_S_OUT_OF_MEMORY; 03204 03205 TRACE("(%p)\n", protseqs); 03206 03207 *protseqs = HeapAlloc(GetProcessHeap(), 0, sizeof(RPC_PROTSEQ_VECTORW)+(sizeof(unsigned short*)*ARRAYSIZE(protseq_list))); 03208 if (!*protseqs) 03209 goto end; 03210 pvector = *protseqs; 03211 pvector->Count = 0; 03212 for (i = 0; i < ARRAYSIZE(protseq_list); i++) 03213 { 03214 pvector->Protseq[i] = HeapAlloc(GetProcessHeap(), 0, (strlen(protseq_list[i].name)+1)*sizeof(unsigned short)); 03215 if (pvector->Protseq[i] == NULL) 03216 goto end; 03217 MultiByteToWideChar(CP_ACP, 0, (CHAR*)protseq_list[i].name, -1, 03218 (WCHAR*)pvector->Protseq[i], strlen(protseq_list[i].name) + 1); 03219 pvector->Count++; 03220 } 03221 status = RPC_S_OK; 03222 03223 end: 03224 if (status != RPC_S_OK) 03225 RpcProtseqVectorFreeW(protseqs); 03226 return status; 03227 } 03228 03229 /*********************************************************************** 03230 * RpcNetworkInqProtseqsA (RPCRT4.@) 03231 */ 03232 RPC_STATUS WINAPI RpcNetworkInqProtseqsA(RPC_PROTSEQ_VECTORA** protseqs) 03233 { 03234 RPC_PROTSEQ_VECTORA *pvector; 03235 int i = 0; 03236 RPC_STATUS status = RPC_S_OUT_OF_MEMORY; 03237 03238 TRACE("(%p)\n", protseqs); 03239 03240 *protseqs = HeapAlloc(GetProcessHeap(), 0, sizeof(RPC_PROTSEQ_VECTORW)+(sizeof(unsigned char*)*ARRAYSIZE(protseq_list))); 03241 if (!*protseqs) 03242 goto end; 03243 pvector = *protseqs; 03244 pvector->Count = 0; 03245 for (i = 0; i < ARRAYSIZE(protseq_list); i++) 03246 { 03247 pvector->Protseq[i] = HeapAlloc(GetProcessHeap(), 0, strlen(protseq_list[i].name)+1); 03248 if (pvector->Protseq[i] == NULL) 03249 goto end; 03250 strcpy((char*)pvector->Protseq[i], protseq_list[i].name); 03251 pvector->Count++; 03252 } 03253 status = RPC_S_OK; 03254 03255 end: 03256 if (status != RPC_S_OK) 03257 RpcProtseqVectorFreeA(protseqs); 03258 return status; 03259 } Generated on Sun May 27 2012 04:26:06 for ReactOS by
1.7.6.1
|