From e2aa2958fa4bfd70bddba437bcb6623b1d6e5a74 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Tue, 26 Jan 2010 04:20:06 +0000 Subject: [PATCH 01/24] - Define OSKIT so we can use special oskit functions - Implement oskit buffer functions to track references and allocate buffers - Remove unneeded mbuf freeing hacks now that we track references (fixes random crashes would occur when an mbuf was freed inside ip_output) - Remove the "ACK hack" that we used to hack around our loopback implementation - Remove unneeded mbuf pool initialization - Remove unused code in sleep.c svn path=/branches/aicom-network-branch/; revision=45257 --- .../include/freebsd/src/sys/sys/malloc.h | 3 +- .../include/freebsd/src/sys/sys/proc.h | 4 ++ lib/drivers/oskittcp/include/osenv.h | 14 ++++++ lib/drivers/oskittcp/oskittcp.rbuild | 2 + lib/drivers/oskittcp/oskittcp/interface.c | 2 - lib/drivers/oskittcp/oskittcp/ip_output.c | 2 + lib/drivers/oskittcp/oskittcp/osenv.c | 45 +++++++++++++++++ lib/drivers/oskittcp/oskittcp/sleep.c | 50 ------------------- lib/drivers/oskittcp/oskittcp/tcp_output.c | 30 ----------- lib/drivers/oskittcp/oskittcp/tcp_subr.c | 13 ----- lib/drivers/oskittcp/oskittcp/uipc_mbuf.c | 2 +- 11 files changed, 69 insertions(+), 98 deletions(-) create mode 100644 lib/drivers/oskittcp/include/osenv.h create mode 100644 lib/drivers/oskittcp/oskittcp/osenv.c diff --git a/lib/drivers/oskittcp/include/freebsd/src/sys/sys/malloc.h b/lib/drivers/oskittcp/include/freebsd/src/sys/sys/malloc.h index ae4a946ed5b..bde211cd137 100644 --- a/lib/drivers/oskittcp/include/freebsd/src/sys/sys/malloc.h +++ b/lib/drivers/oskittcp/include/freebsd/src/sys/sys/malloc.h @@ -36,7 +36,7 @@ #ifndef _SYS_MALLOC_H_ #define _SYS_MALLOC_H_ -#ifndef OSKIT +#if !defined(OSKIT) || defined(__REACTOS__) #define KMEMSTATS #endif @@ -288,7 +288,6 @@ struct kmembuckets { #define MALLOC(space, cast, size, type, flags) \ (space) = (cast)fbsd_malloc((u_long)(size), __FILE__, __LINE__, type, flags) #define FREE(addr, type) fbsd_free((caddr_t)(addr), __FILE__, __LINE__, type) - #else /* do not collect statistics */ #define MALLOC(space, cast, size, type, flags) { \ register struct kmembuckets *kbp = &bucket[BUCKETINDX(size)]; \ diff --git a/lib/drivers/oskittcp/include/freebsd/src/sys/sys/proc.h b/lib/drivers/oskittcp/include/freebsd/src/sys/sys/proc.h index 1032408c394..087d2dd6664 100644 --- a/lib/drivers/oskittcp/include/freebsd/src/sys/sys/proc.h +++ b/lib/drivers/oskittcp/include/freebsd/src/sys/sys/proc.h @@ -65,7 +65,11 @@ #include #ifdef OSKIT +#ifndef __REACTOS__ #include +#else +#include +#endif #endif /* diff --git a/lib/drivers/oskittcp/include/osenv.h b/lib/drivers/oskittcp/include/osenv.h new file mode 100644 index 00000000000..bb5dca2de7b --- /dev/null +++ b/lib/drivers/oskittcp/include/osenv.h @@ -0,0 +1,14 @@ +#ifndef OSENV_H +#define OSENV_H + +static __inline void osenv_intr_enable(void) {} +static __inline void osenv_intr_disable(void) {} + +void oskit_bufio_addref(void *buf); +void oskit_bufio_release(void *buf); +void* oskit_bufio_create(int len); +void oskit_bufio_map(void *srcbuf, void**dstbuf, int off, int len); + +#define osenv_sleeprec_t void* + +#endif diff --git a/lib/drivers/oskittcp/oskittcp.rbuild b/lib/drivers/oskittcp/oskittcp.rbuild index f67e415b006..c6332f252d7 100644 --- a/lib/drivers/oskittcp/oskittcp.rbuild +++ b/lib/drivers/oskittcp/oskittcp.rbuild @@ -3,6 +3,7 @@ + include/freebsd include/freebsd/sys/include include/freebsd/src/sys @@ -22,6 +23,7 @@ ip_output.c kern_clock.c kern_subr.c + osenv.c param.c radix.c random.c diff --git a/lib/drivers/oskittcp/oskittcp/interface.c b/lib/drivers/oskittcp/oskittcp/interface.c index 315f6ff96aa..1dab951b0a2 100644 --- a/lib/drivers/oskittcp/oskittcp/interface.c +++ b/lib/drivers/oskittcp/oskittcp/interface.c @@ -48,8 +48,6 @@ void fbsd_free( void *data, char *file, unsigned line, ... ) { void InitOskitTCP() { OS_DbgPrint(OSK_MID_TRACE,("Init Called\n")); KeInitializeSpinLock(&OSKLock); - OS_DbgPrint(OSK_MID_TRACE,("MB Init\n")); - mbinit(); OS_DbgPrint(OSK_MID_TRACE,("Rawip Init\n")); rip_init(); raw_init(); diff --git a/lib/drivers/oskittcp/oskittcp/ip_output.c b/lib/drivers/oskittcp/oskittcp/ip_output.c index bca8fb0e04d..25f8be98fe3 100644 --- a/lib/drivers/oskittcp/oskittcp/ip_output.c +++ b/lib/drivers/oskittcp/oskittcp/ip_output.c @@ -393,6 +393,7 @@ sendit: error = OtcpEvent.PacketSend( OtcpEvent.ClientData, (OSK_PCHAR)new_m->m_data, new_m->m_len ); m_free( new_m ); + m_freem( m ); goto done; } #else @@ -532,6 +533,7 @@ sendorfree: error = OtcpEvent.PacketSend( OtcpEvent.ClientData, (OSK_PCHAR)new_m->m_data, new_m->m_len ); m_free( new_m ); + m_freem( m ); } OS_DbgPrint(OSK_MID_TRACE,("Error from upper layer: %d\n", error)); diff --git a/lib/drivers/oskittcp/oskittcp/osenv.c b/lib/drivers/oskittcp/oskittcp/osenv.c new file mode 100644 index 00000000000..d29fa5fa239 --- /dev/null +++ b/lib/drivers/oskittcp/oskittcp/osenv.c @@ -0,0 +1,45 @@ +#include "oskittcp.h" + +unsigned oskit_freebsd_cpl; + +/* We have to store a reference count somewhere so we + * don't free a buffer being referenced in another mbuf. + * I just decided to add an extra char to the beginning of + * the buffer and store the reference count there. I doubt the ref count + * will ever even get close to 0xFF so we should be ok. Remember that + * only one thread can ever be inside oskit due to OSKLock so this should + * be safe. + */ + +void oskit_bufio_addref(void *buf) +{ + unsigned char* fullbuf = ((unsigned char*)buf) - sizeof(char); + +#if DBG + if (fullbuf[0] == 0xFF) + panic("oskit_bufio_addref: ref count overflow"); +#endif + + fullbuf[0]++; +} +void oskit_bufio_release(void *buf) +{ + unsigned char* fullbuf = ((unsigned char*)buf) - sizeof(char); + + if (--fullbuf[0] == 0) + free(fullbuf, 0); +} +void* oskit_bufio_create(int len) +{ + unsigned char* fullbuf = malloc(len + sizeof(char), __FILE__, __LINE__); + if (fullbuf == NULL) + return NULL; + + fullbuf[0] = 1; + + return (void*)(fullbuf + sizeof(char)); +} +void oskit_bufio_map(void *srcbuf, void**dstbuf, int off, int len) +{ + *dstbuf = srcbuf; +} diff --git a/lib/drivers/oskittcp/oskittcp/sleep.c b/lib/drivers/oskittcp/oskittcp/sleep.c index 5cfcdb4af56..e6779fd6675 100644 --- a/lib/drivers/oskittcp/oskittcp/sleep.c +++ b/lib/drivers/oskittcp/oskittcp/sleep.c @@ -91,53 +91,3 @@ void clock_init() /* Start a clock we can use for timeouts */ } - -extern unsigned bio_imask; /* group of interrupts masked with splbio() */ -extern unsigned cpl; /* current priority level mask */ -extern volatile unsigned idelayed; /* interrupts to become pending */ -extern volatile unsigned ipending; /* active interrupts masked by cpl */ -extern unsigned net_imask; /* group of interrupts masked with splimp() */ -extern unsigned stat_imask; /* interrupts masked with splstatclock() */ -extern unsigned tty_imask; /* group of interrupts masked with spltty() */ - -/* - * ipending has to be volatile so that it is read every time it is accessed - * in splx() and spl0(), but we don't want it to be read nonatomically when - * it is changed. Pretending that ipending is a plain int happens to give - * suitable atomic code for "ipending |= constant;". - */ -#define setdelayed() (*(unsigned *)&ipending |= loadandclear(&idelayed)) -#define setsoftast() (*(unsigned *)&ipending |= SWI_AST_PENDING) -#define setsoftclock() (*(unsigned *)&ipending |= SWI_CLOCK_PENDING) -#define setsoftnet() (*(unsigned *)&ipending |= SWI_NET_PENDING) -#define setsofttty() (*(unsigned *)&ipending |= SWI_TTY_PENDING) - -#define schedsofttty() (*(unsigned *)&idelayed |= SWI_TTY_PENDING) - -#define GENSPL(name, set_cpl) \ -static __inline int name(void) \ -{ \ - unsigned x; \ - \ - __asm __volatile("" : : : "memory"); \ - x = cpl; \ - set_cpl; \ - return (x); \ -} - -void splz(void) { - OS_DbgPrint(OSK_MID_TRACE,("Called SPLZ\n")); -} - -/* - * functions to save and restore the current cpl - */ -void save_cpl(unsigned *x) -{ - *x = cpl; -} - -void restore_cpl(unsigned x) -{ - cpl = x; -} diff --git a/lib/drivers/oskittcp/oskittcp/tcp_output.c b/lib/drivers/oskittcp/oskittcp/tcp_output.c index 422306b509d..1e9e4318983 100644 --- a/lib/drivers/oskittcp/oskittcp/tcp_output.c +++ b/lib/drivers/oskittcp/oskittcp/tcp_output.c @@ -707,39 +707,9 @@ send: && !(rt->rt_rmx.rmx_locks & RTV_MTU)) { ((struct ip *)ti)->ip_off |= IP_DF; } -#endif - /* - * XXX: It seems that osktittcp expects that packets are - * synchronously processed. The current implementation feeds - * oskittcp with the packets asynchronously. That's not a - * problem normally when the packets are transfered over - * network, but it starts to be a problem when it comes to - * loopback packets. - * The ACK bits are set in tcp_input which calls tcp_output and - * expects them to be cleared before further processing. - * Instead tcp_output calls ip_output which produces a packet - * and ends up in tcp_input and we're stuck in infinite loop. - * Normally the flags are masked out at the end of this function - * and the incomming packets are processed then, but since - * currently the loopback packet is delivered during the - * ip_output call, the function end is never reached... - */ -#ifdef __REACTOS__ - tp->t_flags &= ~(TF_ACKNOW|TF_DELACK); #endif error = ip_output(m, tp->t_inpcb->inp_options, &tp->t_inpcb->inp_route, so->so_options & SO_DONTROUTE, 0); -#ifdef __REACTOS__ - /* We allocated m, so we are responsible for freeing it. If the mbuf - contains a pointer to an external datablock, we (or rather, m_copy) - didn't allocate it but pointed it to the data to send. So we have - to cheat a little bit and keep M_FREE from freeing the external - data block */ - while (NULL != m) { - m->m_flags &= ~M_EXT; - m = m_free(m); - } -#endif } if (error) { out: diff --git a/lib/drivers/oskittcp/oskittcp/tcp_subr.c b/lib/drivers/oskittcp/oskittcp/tcp_subr.c index e3557eea13e..4632b688ef1 100644 --- a/lib/drivers/oskittcp/oskittcp/tcp_subr.c +++ b/lib/drivers/oskittcp/oskittcp/tcp_subr.c @@ -163,7 +163,6 @@ tcp_respond(tp, ti, m, ack, seq, flags) tcp_seq ack, seq; int flags; { - struct mbuf *n; register int tlen; int win = 0; struct route *ro = 0; @@ -222,18 +221,6 @@ tcp_respond(tp, ti, m, ack, seq, flags) tcp_trace(TA_OUTPUT, 0, tp, ti, 0); #endif (void) ip_output(m, NULL, ro, 0, NULL); -#ifdef __REACTOS__ - /* We allocated m, so we are responsible for freeing it. If the mbuf - contains a pointer to an external datablock, we (or rather, m_copy) - didn't allocate it but pointed it to the data to send. So we have - to cheat a little bit and keep M_FREE from freeing the external - data block */ - while (NULL != m) { - m->m_flags &= ~M_EXT; - MFREE(m, n); - m = n; - } -#endif } /* diff --git a/lib/drivers/oskittcp/oskittcp/uipc_mbuf.c b/lib/drivers/oskittcp/oskittcp/uipc_mbuf.c index 082dd0bf6c5..e05d4ee6101 100644 --- a/lib/drivers/oskittcp/oskittcp/uipc_mbuf.c +++ b/lib/drivers/oskittcp/oskittcp/uipc_mbuf.c @@ -663,7 +663,7 @@ extpacket: return (n); } -#ifndef OSKIT +#if !defined(OSKIT) || defined(__REACTOS__) /* currently not OS Kit approved, and shouldn't be needed in the first place */ /* From 79c35d419a394169716c2abc33d3b80f8c52c837 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Wed, 27 Jan 2010 07:44:42 +0000 Subject: [PATCH 02/24] - Handle the case where a socket sends an event notification without being accepted first svn path=/branches/aicom-network-branch/; revision=45283 --- lib/drivers/ip/transport/tcp/event.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/drivers/ip/transport/tcp/event.c b/lib/drivers/ip/transport/tcp/event.c index 5146325a620..9badd7bcd97 100644 --- a/lib/drivers/ip/transport/tcp/event.c +++ b/lib/drivers/ip/transport/tcp/event.c @@ -24,7 +24,14 @@ int TCPSocketState(void *ClientData, NewState & SEL_ACCEPT ? 'A' : 'a', NewState & SEL_WRITE ? 'W' : 'w')); - ASSERT(Connection); + /* If this socket is missing its socket context, that means that it + * has been created as a new connection in sonewconn but not accepted + * yet. We can safely ignore event notifications on these sockets. + * Once they are accepted, they will get a socket context and we will + * be able to process them. + */ + if (!Connection) + return 0; TI_DbgPrint(DEBUG_TCP,("Called: NewState %x (Conn %x) (Change %x)\n", NewState, Connection, From 57b3f4582a8d360ac4d46dab0e6eb809746073f6 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Wed, 27 Jan 2010 08:49:48 +0000 Subject: [PATCH 03/24] - Fix a potential buffer overrun and null pointer dereference svn path=/branches/aicom-network-branch/; revision=45284 --- lib/drivers/oskittcp/oskittcp/interface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/drivers/oskittcp/oskittcp/interface.c b/lib/drivers/oskittcp/oskittcp/interface.c index 1dab951b0a2..3c589e7b255 100644 --- a/lib/drivers/oskittcp/oskittcp/interface.c +++ b/lib/drivers/oskittcp/oskittcp/interface.c @@ -401,7 +401,7 @@ int OskitTCPAccept( void *socket, so->so_state |= SS_NBIO | SS_ISCONNECTED; so->so_q = so->so_q0 = NULL; - so->so_qlen = 0; + so->so_qlen = so->so_q0len = 0; so->so_head = 0; so->so_connection = context; From a0090f038dfca79a393f706bf14781a537ba581e Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sat, 30 Jan 2010 15:18:21 +0000 Subject: [PATCH 04/24] - ovbcopy is used when the source address and destination address overlap so defining it to memcpy was a horrible idea svn path=/branches/aicom-network-branch/; revision=45347 --- lib/drivers/oskittcp/include/oskitfreebsd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/drivers/oskittcp/include/oskitfreebsd.h b/lib/drivers/oskittcp/include/oskitfreebsd.h index 354e7e6db8d..f7d48504d5f 100644 --- a/lib/drivers/oskittcp/include/oskitfreebsd.h +++ b/lib/drivers/oskittcp/include/oskitfreebsd.h @@ -14,7 +14,7 @@ extern void oskittcp_die(const char *file, int line); #define printf DbgPrint #define vprintf DbgVPrint -#define ovbcopy(x,y,z) bcopy(x,y,z) +#define ovbcopy(src,dst,n) memmove(dst,src,n) #define bzero(x,y) memset(x,0,y) #define bcopy(src,dst,n) memcpy(dst,src,n) #ifdef _MSC_VER From 29589c0449888e1a6da3f26040fa5c58b9562f16 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sat, 30 Jan 2010 16:45:22 +0000 Subject: [PATCH 05/24] - Remove some unused junk code svn path=/branches/aicom-network-branch/; revision=45349 --- .../include/freebsd/src/sys/sys/mbuf.h | 28 ------------------- lib/drivers/oskittcp/oskittcp/uipc_mbuf.c | 6 ---- 2 files changed, 34 deletions(-) diff --git a/lib/drivers/oskittcp/include/freebsd/src/sys/sys/mbuf.h b/lib/drivers/oskittcp/include/freebsd/src/sys/sys/mbuf.h index b3226e9155e..7a6b0f07f19 100644 --- a/lib/drivers/oskittcp/include/freebsd/src/sys/sys/mbuf.h +++ b/lib/drivers/oskittcp/include/freebsd/src/sys/sys/mbuf.h @@ -57,13 +57,6 @@ #include #endif -#ifndef OSKIT -#ifdef __REACTOS__ -/* #define OSKIT */ -#define LOCAL_OSKIT_DEFINED -#endif -#endif - /* * Mbufs are of a single size, MSIZE (machine/machparam.h), which * includes overhead. An mbuf may add a single "mbuf cluster" of size @@ -301,21 +294,6 @@ union mcluster { } \ ) -#ifdef __REACTOS__ -#define MCLGET(m, how) { \ - OS_DbgPrint(OSK_MID_TRACE,("(MCLGET) m = %x\n", m)); \ - (m)->m_ext.ext_buf = malloc(MCLBYTES,__FILE__,__LINE__); \ - if ((m)->m_ext.ext_buf != NULL) { \ - (m)->m_data = (m)->m_ext.ext_buf; \ - (m)->m_flags |= M_EXT; \ - (m)->m_ext.ext_size = MCLBYTES; \ - } \ - } - -#define MCLFREE(p) { \ - free( (p), 0 ); \ - } -#else #define MCLGET(m, how) \ { MCLALLOC((m)->m_ext.ext_buf, (how)); \ OS_DbgPrint(OSK_MID_TRACE,("(MCLGET) m = %x\n", m)); \ @@ -335,7 +313,6 @@ union mcluster { mbstat.m_clfree++; \ } \ ) -#endif #else #define MCLGET(m, how) \ { (m)->m_ext.ext_bufio = oskit_bufio_create(MCLBYTES); \ @@ -557,9 +534,4 @@ int mbtypes[] = { /* XXX */ #endif #endif -#ifdef LOCAL_OSKIT_DEFINED -#undef LOCAL_OSKIT_DEFINED -#undef OSKIT -#endif - #endif /* !_SYS_MBUF_H_ */ diff --git a/lib/drivers/oskittcp/oskittcp/uipc_mbuf.c b/lib/drivers/oskittcp/oskittcp/uipc_mbuf.c index e05d4ee6101..ee86ffc4889 100644 --- a/lib/drivers/oskittcp/oskittcp/uipc_mbuf.c +++ b/lib/drivers/oskittcp/oskittcp/uipc_mbuf.c @@ -365,9 +365,7 @@ m_copym(m, off0, len, wait) #ifdef OSKIT oskit_bufio_addref(m->m_ext.ext_bufio); #else -#ifndef __REACTOS__ mclrefcnt[mtocl(m->m_ext.ext_buf)]++; -#endif #endif /* OSKIT */ n->m_ext = m->m_ext; n->m_flags |= M_EXT; @@ -729,11 +727,7 @@ m_devget(buf, totlen, off0, ifp, copy) if (copy) copy(cp, mtod(m, caddr_t), (unsigned)len); else -#ifdef __REACTOS__ - memcpy(mtod(m, caddr_t), cp, len); -#else bcopy(cp, mtod(m, caddr_t), (unsigned)len); -#endif cp += len; *mp = m; mp = &m->m_next; From bd7ffd61fdad5daabafb2034b2e7bc7122291ebf Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Wed, 3 Feb 2010 20:02:39 +0000 Subject: [PATCH 06/24] [AFD] - Add more cases to TdiAddressSizeFromType - Return STATUS_INVALID_PARAMETER instead of bugchecking if somebody gives us a bad address type - Fixes Steam (confirmed by Geoz) - Will also be merged to trunk soon svn path=/branches/aicom-network-branch/; revision=45400 --- drivers/network/afd/afd/bind.c | 11 +++--- drivers/network/afd/afd/connect.c | 13 ++++--- drivers/network/afd/afd/listen.c | 64 ++++++++++++------------------- drivers/network/afd/afd/main.c | 2 +- drivers/network/afd/afd/tdiconn.c | 25 ++++++++++-- drivers/network/afd/afd/write.c | 12 +++--- 6 files changed, 66 insertions(+), 61 deletions(-) diff --git a/drivers/network/afd/afd/bind.c b/drivers/network/afd/afd/bind.c index f2c2f4d4418..8144d035030 100644 --- a/drivers/network/afd/afd/bind.c +++ b/drivers/network/afd/afd/bind.c @@ -71,15 +71,16 @@ AfdBindSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp, FCB->LocalAddress = TaCopyTransportAddress( &BindReq->Address ); if( FCB->LocalAddress ) - TdiBuildConnectionInfo( &FCB->AddressFrom, - FCB->LocalAddress ); + Status = TdiBuildConnectionInfo( &FCB->AddressFrom, + FCB->LocalAddress ); - if( FCB->AddressFrom ) + if( NT_SUCCESS(Status) ) Status = WarmSocketForBind( FCB ); - else return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0); - AFD_DbgPrint(MID_TRACE,("FCB->Flags %x\n", FCB->Flags)); + if( !NT_SUCCESS(Status) ) + return UnlockAndMaybeComplete(FCB, Status, Irp, 0); + if( FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS ) { AFD_DbgPrint(MID_TRACE,("Calling TdiReceiveDatagram\n")); diff --git a/drivers/network/afd/afd/connect.c b/drivers/network/afd/afd/connect.c index c49e6518243..567fca91bc8 100644 --- a/drivers/network/afd/afd/connect.c +++ b/drivers/network/afd/afd/connect.c @@ -423,16 +423,17 @@ AfdStreamSocketConnect(PDEVICE_OBJECT DeviceObject, PIRP Irp, if( !NT_SUCCESS(Status) ) break; - TdiBuildConnectionInfo + Status = TdiBuildConnectionInfo ( &FCB->ConnectInfo, &ConnectReq->RemoteAddress ); - if( FCB->ConnectInfo ) - TdiBuildConnectionInfo(&TargetAddress, - &ConnectReq->RemoteAddress); + if( NT_SUCCESS(Status) ) + Status = TdiBuildConnectionInfo(&TargetAddress, + &ConnectReq->RemoteAddress); + else break; - if( TargetAddress ) { + if( NT_SUCCESS(Status) ) { TargetAddress->UserData = FCB->ConnectData; TargetAddress->UserDataLength = FCB->ConnectDataSize; TargetAddress->Options = FCB->ConnectOptions; @@ -454,7 +455,7 @@ AfdStreamSocketConnect(PDEVICE_OBJECT DeviceObject, PIRP Irp, FCB->State = SOCKET_STATE_CONNECTING; return LeaveIrpUntilLater( FCB, Irp, FUNCTION_CONNECT ); } - } else Status = STATUS_NO_MEMORY; + } break; default: diff --git a/drivers/network/afd/afd/listen.c b/drivers/network/afd/afd/listen.c index d16550e47e4..5a1b8f55bbb 100644 --- a/drivers/network/afd/afd/listen.c +++ b/drivers/network/afd/afd/listen.c @@ -156,13 +156,13 @@ static NTSTATUS NTAPI ListenComplete FCB->ListenIrp. ConnectionReturnInfo->RemoteAddress)); - TdiBuildNullConnectionInfo( &Qelt->ConnInfo, AddressType ); - if( Qelt->ConnInfo ) { + Status = TdiBuildNullConnectionInfo( &Qelt->ConnInfo, AddressType ); + if( NT_SUCCESS(Status) ) { TaCopyTransportAddressInPlace ( Qelt->ConnInfo->RemoteAddress, FCB->ListenIrp.ConnectionReturnInfo->RemoteAddress ); InsertTailList( &FCB->PendingConnections, &Qelt->ListEntry ); - } else Status = STATUS_NO_MEMORY; + } } /* Satisfy a pre-accept request if one is available */ @@ -235,28 +235,21 @@ NTSTATUS AfdListenSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp, if( !NT_SUCCESS(Status) ) return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); - TdiBuildNullConnectionInfo + Status = TdiBuildNullConnectionInfo ( &FCB->ListenIrp.ConnectionCallInfo, FCB->LocalAddress->Address[0].AddressType ); - TdiBuildNullConnectionInfo + + if (!NT_SUCCESS(Status)) return UnlockAndMaybeComplete(FCB, Status, Irp, 0); + + Status = TdiBuildNullConnectionInfo ( &FCB->ListenIrp.ConnectionReturnInfo, FCB->LocalAddress->Address[0].AddressType ); - if( !FCB->ListenIrp.ConnectionReturnInfo || !FCB->ListenIrp.ConnectionCallInfo ) + if (!NT_SUCCESS(Status)) { - if (FCB->ListenIrp.ConnectionReturnInfo) - { - ExFreePool(FCB->ListenIrp.ConnectionReturnInfo); - FCB->ListenIrp.ConnectionReturnInfo = NULL; - } - - if (FCB->ListenIrp.ConnectionCallInfo) - { - ExFreePool(FCB->ListenIrp.ConnectionCallInfo); - FCB->ListenIrp.ConnectionCallInfo = NULL; - } - - return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, Irp, 0 ); + ExFreePool(FCB->ListenIrp.ConnectionCallInfo); + FCB->ListenIrp.ConnectionCallInfo = NULL; + return UnlockAndMaybeComplete(FCB, Status, Irp, 0); } FCB->State = SOCKET_STATE_LISTENING; @@ -337,29 +330,22 @@ NTSTATUS AfdAccept( PDEVICE_OBJECT DeviceObject, PIRP Irp, Status = WarmSocketForConnection( FCB ); if( Status == STATUS_SUCCESS ) { - TdiBuildNullConnectionInfo - ( &FCB->ListenIrp.ConnectionCallInfo, - FCB->LocalAddress->Address[0].AddressType ); - TdiBuildNullConnectionInfo - ( &FCB->ListenIrp.ConnectionReturnInfo, - FCB->LocalAddress->Address[0].AddressType ); + Status = TdiBuildNullConnectionInfo + ( &FCB->ListenIrp.ConnectionCallInfo, + FCB->LocalAddress->Address[0].AddressType ); - if( !FCB->ListenIrp.ConnectionReturnInfo || !FCB->ListenIrp.ConnectionCallInfo ) - { - if (FCB->ListenIrp.ConnectionReturnInfo) - { - ExFreePool(FCB->ListenIrp.ConnectionReturnInfo); - FCB->ListenIrp.ConnectionReturnInfo = NULL; - } + if (!NT_SUCCESS(Status)) return UnlockAndMaybeComplete(FCB, Status, Irp, 0); - if (FCB->ListenIrp.ConnectionCallInfo) - { - ExFreePool(FCB->ListenIrp.ConnectionCallInfo); - FCB->ListenIrp.ConnectionCallInfo = NULL; - } + Status = TdiBuildNullConnectionInfo + ( &FCB->ListenIrp.ConnectionReturnInfo, + FCB->LocalAddress->Address[0].AddressType ); - return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, Irp, 0 ); - } + if (!NT_SUCCESS(Status)) + { + ExFreePool(FCB->ListenIrp.ConnectionCallInfo); + FCB->ListenIrp.ConnectionCallInfo = NULL; + return UnlockAndMaybeComplete(FCB, Status, Irp, 0); + } Status = TdiListen( &FCB->ListenIrp.InFlightRequest, FCB->Connection.Object, diff --git a/drivers/network/afd/afd/main.c b/drivers/network/afd/afd/main.c index 80fead13cc7..bcbb2f56603 100644 --- a/drivers/network/afd/afd/main.c +++ b/drivers/network/afd/afd/main.c @@ -498,7 +498,7 @@ AfdDisconnect(PDEVICE_OBJECT DeviceObject, PIRP Irp, ( &ConnectionReturnInfo, FCB->RemoteAddress->Address[0].AddressType ); if( !NT_SUCCESS(Status) ) - return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, + return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); if( DisReq->DisconnectType & AFD_DISCONNECT_SEND ) diff --git a/drivers/network/afd/afd/tdiconn.c b/drivers/network/afd/afd/tdiconn.c index 72418b199d3..c95ed3bd423 100644 --- a/drivers/network/afd/afd/tdiconn.c +++ b/drivers/network/afd/afd/tdiconn.c @@ -14,13 +14,21 @@ UINT TdiAddressSizeFromType( UINT AddressType ) { switch( AddressType ) { - case AF_INET: + case TDI_ADDRESS_TYPE_IP: return sizeof(TA_IP_ADDRESS); + case TDI_ADDRESS_TYPE_APPLETALK: + return sizeof(TA_APPLETALK_ADDRESS); + case TDI_ADDRESS_TYPE_NETBIOS: + return sizeof(TA_NETBIOS_ADDRESS); + /* case TDI_ADDRESS_TYPE_NS: */ + case TDI_ADDRESS_TYPE_IPX: + return sizeof(TA_IPX_ADDRESS); + case TDI_ADDRESS_TYPE_VNS: + return sizeof(TA_VNS_ADDRESS); default: - AFD_DbgPrint(MID_TRACE,("TdiAddressSizeFromType - invalid type: %x\n", AddressType)); - KeBugCheck( 0 ); + DbgPrint("TdiAddressSizeFromType - invalid type: %x\n", AddressType); + return 0; } - return 0; } UINT TaLengthOfAddress( PTA_ADDRESS Addr ) { @@ -85,6 +93,8 @@ static NTSTATUS TdiBuildNullConnectionInfoInPlace PTRANSPORT_ADDRESS TransportAddress; TdiAddressSize = TdiAddressSizeFromType(Type); + if (!TdiAddressSize) + return STATUS_INVALID_PARAMETER; RtlZeroMemory(ConnInfo, sizeof(TDI_CONNECTION_INFORMATION) + @@ -118,6 +128,10 @@ NTSTATUS TdiBuildNullConnectionInfo NTSTATUS Status; TdiAddressSize = TdiAddressSizeFromType(Type); + if (!TdiAddressSize) { + *ConnectionInfo = NULL; + return STATUS_INVALID_PARAMETER; + } ConnInfo = (PTDI_CONNECTION_INFORMATION) ExAllocatePool(NonPagedPool, @@ -199,6 +213,9 @@ TdiBuildConnectionInfoPair /* FIXME: Get from socket information */ TdiAddressSize = TdiAddressSizeFromType(From->Address[0].AddressType); + if (!TdiAddressSize) + return STATUS_INVALID_PARAMETER; + SizeOfEntry = TdiAddressSize + sizeof(TDI_CONNECTION_INFORMATION); LayoutFrame = (PCHAR)ExAllocatePool(NonPagedPool, 2 * SizeOfEntry); diff --git a/drivers/network/afd/afd/write.c b/drivers/network/afd/afd/write.c index 427dd01d83f..a23036161de 100644 --- a/drivers/network/afd/afd/write.c +++ b/drivers/network/afd/afd/write.c @@ -247,9 +247,9 @@ AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp, Irp, 0 ); } - TdiBuildConnectionInfo( &TargetAddress, FCB->RemoteAddress ); + Status = TdiBuildConnectionInfo( &TargetAddress, FCB->RemoteAddress ); - if( TargetAddress ) { + if( NT_SUCCESS(Status) ) { Status = TdiSendDatagram ( &FCB->SendIrp.InFlightRequest, FCB->AddressFile.Object, @@ -261,7 +261,7 @@ AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp, FCB ); ExFreePool( TargetAddress ); - } else Status = STATUS_NO_MEMORY; + } if( Status == STATUS_PENDING ) Status = STATUS_SUCCESS; @@ -419,12 +419,12 @@ AfdPacketSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp, ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress)-> Address[0].AddressType)); - TdiBuildConnectionInfo( &TargetAddress, + Status = TdiBuildConnectionInfo( &TargetAddress, ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress) ); /* Check the size of the Address given ... */ - if( TargetAddress ) { + if( NT_SUCCESS(Status) ) { Status = TdiSendDatagram ( &FCB->SendIrp.InFlightRequest, FCB->AddressFile.Object, @@ -436,7 +436,7 @@ AfdPacketSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp, FCB ); ExFreePool( TargetAddress ); - } else Status = STATUS_NO_MEMORY; + } if( Status == STATUS_PENDING ) Status = STATUS_SUCCESS; From 833baf171555d943332f3273b4b06e4daaa0add1 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Fri, 5 Feb 2010 07:16:50 +0000 Subject: [PATCH 07/24] [PSDK, MSAFD] - Fix a typo [NETSTAT] - Uncomment and fix displaying successful fragmentation data - Fix a typo svn path=/branches/aicom-network-branch/; revision=45435 --- base/applications/network/netstat/netstat.c | 2 +- dll/win32/msafd/include/helpers.h | 2 +- dll/win32/msafd/misc/helpers.c | 2 +- include/psdk/wsahelp.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/base/applications/network/netstat/netstat.c b/base/applications/network/netstat/netstat.c index 45ff2fd7fa4..b225a879fab 100644 --- a/base/applications/network/netstat/netstat.c +++ b/base/applications/network/netstat/netstat.c @@ -274,7 +274,7 @@ VOID ShowIpStatistics() _tprintf(_T(" %-34s = %lu\n"), _T("Reassembly Required"), pIpStats->dwReasmReqds); _tprintf(_T(" %-34s = %lu\n"), _T("Reassembly Succesful"), pIpStats->dwReasmOks); _tprintf(_T(" %-34s = %lu\n"), _T("Reassembly Failures"), pIpStats->dwReasmFails); - // _tprintf(_T(" %-34s = %lu\n"), _T("Datagrams succesfully fragmented"), NULL); /* FIXME: what is this one? */ + _tprintf(_T(" %-34s = %lu\n"), _T("Datagrams succesfully fragmented"), pIpStats->dwFragOks); _tprintf(_T(" %-34s = %lu\n"), _T("Datagrams Failing Fragmentation"), pIpStats->dwFragFails); _tprintf(_T(" %-34s = %lu\n"), _T("Fragments Created"), pIpStats->dwFragCreates); } diff --git a/dll/win32/msafd/include/helpers.h b/dll/win32/msafd/include/helpers.h index 1b73c669df5..7fa8e0c2627 100644 --- a/dll/win32/msafd/include/helpers.h +++ b/dll/win32/msafd/include/helpers.h @@ -26,7 +26,7 @@ typedef struct _HELPER_DATA { PWSH_GET_SOCKET_INFORMATION WSHGetSocketInformation; PWSH_SET_SOCKET_INFORMATION WSHSetSocketInformation; PWSH_GET_SOCKADDR_TYPE WSHGetSockaddrType; - PWSH_GET_WILDCARD_SOCKEADDR WSHGetWildcardSockaddr; + PWSH_GET_WILDCARD_SOCKADDR WSHGetWildcardSockaddr; PWSH_GET_BROADCAST_SOCKADDR WSHGetBroadcastSockaddr; PWSH_ADDRESS_TO_STRING WSHAddressToString; PWSH_STRING_TO_ADDRESS WSHStringToAddress; diff --git a/dll/win32/msafd/misc/helpers.c b/dll/win32/msafd/misc/helpers.c index f0bb6a9d5f0..89b1d6ac869 100644 --- a/dll/win32/msafd/misc/helpers.c +++ b/dll/win32/msafd/misc/helpers.c @@ -454,7 +454,7 @@ SockLoadHelperDll( HelperData->WSHGetSockaddrType = (PWSH_GET_SOCKADDR_TYPE) GetProcAddress(HelperData->hInstance, "WSHGetSockaddrType"); - HelperData->WSHGetWildcardSockaddr = (PWSH_GET_WILDCARD_SOCKEADDR) + HelperData->WSHGetWildcardSockaddr = (PWSH_GET_WILDCARD_SOCKADDR) GetProcAddress(HelperData->hInstance, "WSHGetWildcardSockaddr"); HelperData->WSHGetBroadcastSockaddr = (PWSH_GET_BROADCAST_SOCKADDR) diff --git a/include/psdk/wsahelp.h b/include/psdk/wsahelp.h index 132261e0668..2e128a98b5b 100644 --- a/include/psdk/wsahelp.h +++ b/include/psdk/wsahelp.h @@ -70,7 +70,7 @@ typedef INT (WINAPI *PWSH_GET_BROADCAST_SOCKADDR)(PVOID,PSOCKADDR,PINT); typedef INT (WINAPI *PWSH_GET_PROVIDER_GUID)(LPWSTR,LPGUID); typedef INT (WINAPI *PWSH_GET_SOCKADDR_TYPE)(PSOCKADDR,DWORD,PSOCKADDR_INFO); typedef INT (WINAPI *PWSH_GET_SOCKET_INFORMATION)(PVOID,SOCKET,HANDLE,HANDLE,INT,INT,PCHAR,LPINT); -typedef INT (WINAPI *PWSH_GET_WILDCARD_SOCKEADDR)(PVOID,PSOCKADDR,PINT); +typedef INT (WINAPI *PWSH_GET_WILDCARD_SOCKADDR)(PVOID,PSOCKADDR,PINT); typedef DWORD (WINAPI *PWSH_GET_WINSOCK_MAPPING)(PWINSOCK_MAPPING,DWORD); typedef INT (WINAPI *PWSH_GET_WSAPROTOCOL_INFO)(LPWSTR,LPWSAPROTOCOL_INFOW*,LPDWORD); typedef INT (WINAPI *PWSH_IOCTL)(PVOID,SOCKET,HANDLE,HANDLE,DWORD,LPVOID,DWORD, From fdd91bc7e8928425633cb021591bac2d26f1a206 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Fri, 5 Feb 2010 07:35:04 +0000 Subject: [PATCH 08/24] [NDIS] - Fix buffer length passed to KeRegisterBugCheckCallback svn path=/branches/aicom-network-branch/; revision=45436 --- drivers/network/ndis/ndis/miniport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/network/ndis/ndis/miniport.c b/drivers/network/ndis/ndis/miniport.c index 5c72c100751..2a0c1b66b0e 100644 --- a/drivers/network/ndis/ndis/miniport.c +++ b/drivers/network/ndis/ndis/miniport.c @@ -1511,7 +1511,7 @@ NdisMRegisterAdapterShutdownHandler( KeInitializeCallbackRecord(BugcheckContext->CallbackRecord); KeRegisterBugCheckCallback(BugcheckContext->CallbackRecord, NdisIBugcheckCallback, - BugcheckContext, sizeof(BugcheckContext), (PUCHAR)"Ndis Miniport"); + BugcheckContext, sizeof(*BugcheckContext), (PUCHAR)"Ndis Miniport"); IoRegisterShutdownNotification(Adapter->NdisMiniportBlock.DeviceObject); } From 166bc10af9e5769e87b8a128db656b155a7e5f13 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Fri, 5 Feb 2010 08:33:48 +0000 Subject: [PATCH 09/24] - Fix some epic fail in NdisMRegisterMiniport - We were checking to see if there were valid NDIS 5.1-specific characteristics if 5.1 was specified as the version but we didn't actually copy them into our local buffer - Now NdisCancelPackets will actually do something if the miniport implements a MiniportCancelSendPackets handler and PnP event notifications will get through to the miniport if it implements a MiniportPnPEventNotify handler svn path=/branches/aicom-network-branch/; revision=45437 --- drivers/network/ndis/ndis/miniport.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/network/ndis/ndis/miniport.c b/drivers/network/ndis/ndis/miniport.c index 2a0c1b66b0e..1fc3e41ffe7 100644 --- a/drivers/network/ndis/ndis/miniport.c +++ b/drivers/network/ndis/ndis/miniport.c @@ -2325,7 +2325,20 @@ NdisMRegisterMiniport( break; case 0x05: - MinSize = sizeof(NDIS50_MINIPORT_CHARACTERISTICS); + switch (MiniportCharacteristics->MinorNdisVersion) + { + case 0x00: + MinSize = sizeof(NDIS50_MINIPORT_CHARACTERISTICS); + break; + + case 0x01: + MinSize = sizeof(NDIS51_MINIPORT_CHARACTERISTICS); + break; + + default: + NDIS_DbgPrint(MIN_TRACE, ("Bad minor miniport characteristics version.\n")); + return NDIS_STATUS_BAD_VERSION; + } break; default: From ff2d0c4e3a73cbde5dbad77a186e4665c84d3216 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sat, 6 Feb 2010 02:32:13 +0000 Subject: [PATCH 10/24] - New winsock (part 1 of x) - Remove the old ws2_32 svn path=/branches/aicom-network-branch/; revision=45448 --- dll/win32/ws2_32/include/catalog.h | 58 - dll/win32/ws2_32/include/debug.h | 66 - dll/win32/ws2_32/include/handle.h | 48 - dll/win32/ws2_32/include/upcall.h | 104 -- dll/win32/ws2_32/include/ws2_32.h | 123 -- dll/win32/ws2_32/misc/async.c | 706 --------- dll/win32/ws2_32/misc/bsd.c | 55 - dll/win32/ws2_32/misc/catalog.c | 355 ----- dll/win32/ws2_32/misc/dllmain.c | 896 ----------- dll/win32/ws2_32/misc/event.c | 244 --- dll/win32/ws2_32/misc/handle.c | 297 ---- dll/win32/ws2_32/misc/ns.c | 1547 ------------------- dll/win32/ws2_32/misc/sndrcv.c | 417 ----- dll/win32/ws2_32/misc/stubs.c | 938 ----------- dll/win32/ws2_32/misc/upcall.c | 237 --- dll/win32/ws2_32/tests/setup.c | 13 - dll/win32/ws2_32/tests/stubs.tst | 19 - dll/win32/ws2_32/tests/tests/WinsockEvent.c | 83 - dll/win32/ws2_32/ws2_32.rbuild | 29 - dll/win32/ws2_32/ws2_32.rc | 7 - dll/win32/ws2_32/ws2_32.spec | 119 -- 21 files changed, 6361 deletions(-) delete mode 100644 dll/win32/ws2_32/include/catalog.h delete mode 100644 dll/win32/ws2_32/include/debug.h delete mode 100644 dll/win32/ws2_32/include/handle.h delete mode 100644 dll/win32/ws2_32/include/upcall.h delete mode 100644 dll/win32/ws2_32/include/ws2_32.h delete mode 100644 dll/win32/ws2_32/misc/async.c delete mode 100644 dll/win32/ws2_32/misc/bsd.c delete mode 100644 dll/win32/ws2_32/misc/catalog.c delete mode 100644 dll/win32/ws2_32/misc/dllmain.c delete mode 100644 dll/win32/ws2_32/misc/event.c delete mode 100644 dll/win32/ws2_32/misc/handle.c delete mode 100644 dll/win32/ws2_32/misc/ns.c delete mode 100644 dll/win32/ws2_32/misc/sndrcv.c delete mode 100644 dll/win32/ws2_32/misc/stubs.c delete mode 100644 dll/win32/ws2_32/misc/upcall.c delete mode 100644 dll/win32/ws2_32/tests/setup.c delete mode 100644 dll/win32/ws2_32/tests/stubs.tst delete mode 100644 dll/win32/ws2_32/tests/tests/WinsockEvent.c delete mode 100644 dll/win32/ws2_32/ws2_32.rbuild delete mode 100644 dll/win32/ws2_32/ws2_32.rc delete mode 100644 dll/win32/ws2_32/ws2_32.spec diff --git a/dll/win32/ws2_32/include/catalog.h b/dll/win32/ws2_32/include/catalog.h deleted file mode 100644 index f36513e3a86..00000000000 --- a/dll/win32/ws2_32/include/catalog.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS WinSock 2 DLL - * FILE: include/catalog.h - * PURPOSE: Service Provider Catalog definitions - */ -#ifndef __CATALOG_H -#define __CATALOG_H - -typedef struct _CATALOG_ENTRY -{ - LIST_ENTRY ListEntry; - ULONG ReferenceCount; - CRITICAL_SECTION Lock; - UNICODE_STRING LibraryName; - HMODULE hModule; - WSAPROTOCOL_INFOW ProtocolInfo; - PWINSOCK_MAPPING Mapping; - LPWSPSTARTUP WSPStartup; - WSPDATA WSPData; - WSPPROC_TABLE ProcTable; -} CATALOG_ENTRY, *PCATALOG_ENTRY; - -extern LIST_ENTRY Catalog; - - -VOID ReferenceProviderByPointer( - PCATALOG_ENTRY Provider); - -VOID DereferenceProviderByPointer( - PCATALOG_ENTRY Provider); - -PCATALOG_ENTRY CreateCatalogEntry( - LPWSTR LibraryName); - -INT DestroyCatalogEntry( - PCATALOG_ENTRY Provider); - -PCATALOG_ENTRY LocateProvider( - LPWSAPROTOCOL_INFOW lpProtocolInfo); - -PCATALOG_ENTRY LocateProviderById( - DWORD CatalogEntryId); - -INT LoadProvider( - PCATALOG_ENTRY Provider, - LPWSAPROTOCOL_INFOW lpProtocolInfo); - -INT UnloadProvider( - PCATALOG_ENTRY Provider); - -VOID CreateCatalog(VOID); - -VOID DestroyCatalog(VOID); - -#endif /* __CATALOG_H */ - -/* EOF */ diff --git a/dll/win32/ws2_32/include/debug.h b/dll/win32/ws2_32/include/debug.h deleted file mode 100644 index 369aa289d94..00000000000 --- a/dll/win32/ws2_32/include/debug.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS WinSock 2 DLL - * FILE: include/debug.h - * PURPOSE: Debugging support macros - * DEFINES: DBG - Enable debug output - * NASSERT - Disable assertions - */ -#ifndef __DEBUG_H -#define __DEBUG_H - -#define NORMAL_MASK 0x000000FF -#define SPECIAL_MASK 0xFFFFFF00 -#define MIN_TRACE 0x00000001 -#define MID_TRACE 0x00000002 -#define MAX_TRACE 0x00000003 - -#define DEBUG_CHECK 0x00000100 -#define DEBUG_ULTRA 0xFFFFFFFF - -#ifdef ASSERT -#undef ASSERT -#endif - -#if DBG - -extern DWORD DebugTraceLevel; - -#define WS_DbgPrint(_t_, _x_) \ - if (((DebugTraceLevel & NORMAL_MASK) >= _t_) || \ - ((DebugTraceLevel & _t_) > NORMAL_MASK)) { \ - DbgPrint("(%hS:%d)(%hS) ", __FILE__, __LINE__, __FUNCTION__); \ - DbgPrint _x_; \ - } - -#ifdef NASSERT -#define ASSERT(x) -#else /* NASSERT */ -#define ASSERT(x) if (!(x)) { WS_DbgPrint(MIN_TRACE, ("Assertion "#x" failed at %s:%d\n", __FILE__, __LINE__)); ExitProcess(0); } -#endif /* NASSERT */ - -#else /* DBG */ - -#define WS_DbgPrint(_t_, _x_) - -#define ASSERT_IRQL(x) -#define ASSERT(x) - -#endif /* DBG */ - - -#define assert(x) ASSERT(x) -#define assert_irql(x) ASSERT_IRQL(x) - - -#define UNIMPLEMENTED \ - WS_DbgPrint(MIN_TRACE, ("is unimplemented, please try again later.\n")); - -#define CHECKPOINT \ - WS_DbgPrint(DEBUG_CHECK, ("\n")); - -#define CP CHECKPOINT - -#endif /* __DEBUG_H */ - -/* EOF */ diff --git a/dll/win32/ws2_32/include/handle.h b/dll/win32/ws2_32/include/handle.h deleted file mode 100644 index 95fb03a9b3b..00000000000 --- a/dll/win32/ws2_32/include/handle.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS WinSock 2 DLL - * FILE: include/handle.h - * PURPOSE: Provider handle definitions - */ -#ifndef __HANDLE_H -#define __HANDLE_H - -#include - -typedef struct _PROVIDER_HANDLE -{ - HANDLE Handle; - PCATALOG_ENTRY Provider; -} PROVIDER_HANDLE, *PPROVIDER_HANDLE; - -#define HANDLE_BLOCK_ENTRIES ((1024-sizeof(LIST_ENTRY))/sizeof(PROVIDER_HANDLE)) - -typedef struct _PROVIDER_HANDLE_BLOCK -{ - LIST_ENTRY Entry; - PROVIDER_HANDLE Handles[HANDLE_BLOCK_ENTRIES]; -} PROVIDER_HANDLE_BLOCK, *PPROVIDER_HANDLE_BLOCK; - -extern PPROVIDER_HANDLE_BLOCK ProviderHandleTable; - - -HANDLE -CreateProviderHandle(HANDLE Handle, - PCATALOG_ENTRY Provider); - -BOOL -ReferenceProviderByHandle(HANDLE Handle, - PCATALOG_ENTRY* Provider); - -BOOL -CloseProviderHandle(HANDLE Handle); - -BOOL -InitProviderHandleTable(VOID); - -VOID -FreeProviderHandleTable(VOID); - -#endif /* __HANDLE_H */ - -/* EOF */ diff --git a/dll/win32/ws2_32/include/upcall.h b/dll/win32/ws2_32/include/upcall.h deleted file mode 100644 index 16ec65ad58b..00000000000 --- a/dll/win32/ws2_32/include/upcall.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS WinSock 2 DLL - * FILE: include/upcall.h - * PURPOSE: Upcall function defintions - */ -#ifndef __UPCALL_H -#define __UPCALL_H - -BOOL -WSPAPI -WPUCloseEvent( - IN WSAEVENT hEvent, - OUT LPINT lpErrno); - -INT -WSPAPI -WPUCloseSocketHandle( - IN SOCKET s, - OUT LPINT lpErrno); - -INT -WSPAPI -WPUCloseThread( - IN LPWSATHREADID lpThreadId, - OUT LPINT lpErrno); - -WSAEVENT -WSPAPI -WPUCreateEvent( - OUT LPINT lpErrno); - -SOCKET -WSPAPI -WPUCreateSocketHandle( - IN DWORD dwCatalogEntryId, - IN DWORD dwContext, - OUT LPINT lpErrno); - -int -WSPAPI -WPUFDIsSet( - IN SOCKET s, - IN LPFD_SET set); - -INT -WSPAPI -WPUGetProviderPath( - IN LPGUID lpProviderId, - OUT LPWSTR lpszProviderDllPath, - IN OUT LPINT lpProviderDllPathLen, - OUT LPINT lpErrno); - -SOCKET -WSPAPI -WPUModifyIFSHandle( - IN DWORD dwCatalogEntryId, - IN SOCKET ProposedHandle, - OUT LPINT lpErrno); - -INT -WSPAPI -WPUOpenCurrentThread( - OUT LPWSATHREADID lpThreadId, - OUT LPINT lpErrno); - -INT -WSPAPI -WPUQueryBlockingCallback( - IN DWORD dwCatalogEntryId, - OUT LPBLOCKINGCALLBACK FAR* lplpfnCallback, - OUT LPDWORD lpdwContext, - OUT LPINT lpErrno); - -INT -WSPAPI -WPUQuerySocketHandleContext( - IN SOCKET s, - OUT LPDWORD lpContext, - OUT LPINT lpErrno); - -INT -WSPAPI -WPUQueueApc( - IN LPWSATHREADID lpThreadId, - IN LPWSAUSERAPC lpfnUserApc, - IN DWORD dwContext, - OUT LPINT lpErrno); - -BOOL -WSPAPI -WPUResetEvent( - IN WSAEVENT hEvent, - OUT LPINT lpErrno); - -BOOL -WSPAPI -WPUSetEvent( - IN WSAEVENT hEvent, - OUT LPINT lpErrno); - -#endif /* __UPCALL_H */ - -/* EOF */ diff --git a/dll/win32/ws2_32/include/ws2_32.h b/dll/win32/ws2_32/include/ws2_32.h deleted file mode 100644 index 7272a14098a..00000000000 --- a/dll/win32/ws2_32/include/ws2_32.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS WinSock 2 DLL - * FILE: include/ws2_32.h - * PURPOSE: WinSock 2 DLL header - */ -#ifndef __WS2_32_H -#define __WS2_32_H - -#include - -#define WIN32_NO_STATUS -#include -#include -#include -#include -#define NTOS_MODE_USER -#include - -#include - -#undef assert -#include -#include // DNS_A_DATA - -#define EXPORT WINAPI - -extern HINSTANCE g_hInstDll; -extern HANDLE GlobalHeap; -extern BOOL WsaInitialized; /* TRUE if WSAStartup() has been successfully called */ -extern WSPUPCALLTABLE UpcallTable; - -#define WS2_INTERNAL_MAX_ALIAS 16 - -typedef struct _WINSOCK_GETSERVBYNAME_CACHE -{ - UINT Size; - SERVENT ServerEntry; - PCHAR Aliases[WS2_INTERNAL_MAX_ALIAS]; - CHAR Data[1]; -} WINSOCK_GETSERVBYNAME_CACHE, *PWINSOCK_GETSERVBYNAME_CACHE; - -typedef struct _WINSOCK_GETSERVBYPORT_CACHE -{ - UINT Size; - SERVENT ServerEntry; - PCHAR Aliases[WS2_INTERNAL_MAX_ALIAS]; - CHAR Data[1]; -} WINSOCK_GETSERVBYPORT_CACHE, *PWINSOCK_GETSERVBYPORT_CACHE; - -typedef struct _WINSOCK_THREAD_BLOCK -{ - INT LastErrorValue; /* Error value from last function that failed */ - CHAR Intoa[16]; /* Buffer for inet_ntoa() */ - PWINSOCK_GETSERVBYNAME_CACHE - Getservbyname; /* Buffer used by getservbyname */ - PWINSOCK_GETSERVBYPORT_CACHE - Getservbyport; /* Buffer used by getservbyname */ - struct hostent* Hostent; -} WINSOCK_THREAD_BLOCK, *PWINSOCK_THREAD_BLOCK; - - -/* Macros */ - -#define WSAINITIALIZED (WsaInitialized) - -#define WSASETINITIALIZED (WsaInitialized = TRUE) - -/* ws2_32 internal Functions */ -void check_hostent(struct hostent **he); -void populate_hostent(struct hostent *he, char* name, DNS_A_DATA addr); -void free_hostent(struct hostent *he); -void free_servent(struct servent* s); - -#ifdef LE - -/* DWORD network to host byte order conversion for little endian machines */ -#define DN2H(dw) \ - ((((dw) & 0xFF000000L) >> 24) | \ - (((dw) & 0x00FF0000L) >> 8) | \ - (((dw) & 0x0000FF00L) << 8) | \ - (((dw) & 0x000000FFL) << 24)) - -/* DWORD host to network byte order conversion for little endian machines */ -#define DH2N(dw) \ - ((((dw) & 0xFF000000L) >> 24) | \ - (((dw) & 0x00FF0000L) >> 8) | \ - (((dw) & 0x0000FF00L) << 8) | \ - (((dw) & 0x000000FFL) << 24)) - -/* WORD network to host order conversion for little endian machines */ -#define WN2H(w) \ - ((((w) & 0xFF00) >> 8) | \ - (((w) & 0x00FF) << 8)) - -/* WORD host to network byte order conversion for little endian machines */ -#define WH2N(w) \ - ((((w) & 0xFF00) >> 8) | \ - (((w) & 0x00FF) << 8)) - -#else /* LE */ - -/* DWORD network to host byte order conversion for big endian machines */ -#define DN2H(dw) \ - (dw) - -/* DWORD host to network byte order conversion big endian machines */ -#define DH2N(dw) \ - (dw) - -/* WORD network to host order conversion for big endian machines */ -#define WN2H(w) \ - (w) - -/* WORD host to network byte order conversion for big endian machines */ -#define WH2N(w) \ - (w) - -#endif /* LE */ - -#endif /* __WS2_32_H */ - -/* EOF */ diff --git a/dll/win32/ws2_32/misc/async.c b/dll/win32/ws2_32/misc/async.c deleted file mode 100644 index 558960caea0..00000000000 --- a/dll/win32/ws2_32/misc/async.c +++ /dev/null @@ -1,706 +0,0 @@ -/* Async WINSOCK DNS services - * - * Copyright (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka. - * Copyright (C) 1999 Marcus Meissner - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - * - * NOTE: If you make any changes to fix a particular app, make sure - * they don't break something else like Netscape or telnet and ftp - * clients and servers (www.winsite.com got a lot of those). - * - * FIXME: - * - Add WSACancel* and correct handle management. (works rather well for - * now without it.) - * - Verify & Check all calls for correctness - * (currently only WSAGetHostByName*, WSAGetServByPort* calls) - * - Check error returns. - * - mirc/mirc32 Finger @linux.kernel.org sometimes fails in threaded mode. - * (not sure why) - * - This implementation did ignore the "NOTE:" section above (since the - * whole stuff did not work anyway to other changes). - */ - -#include -#include - -#define WS_FD_SETSIZE FD_SETSIZE -#define HAVE_GETPROTOBYNAME -#define HAVE_GETPROTOBYNUMBER -#define HAVE_GETSERVBYPORT -typedef struct hostent WS_hostent; -typedef struct servent WS_servent; -typedef struct protoent WS_protoent; - -#include "wine/config.h" -#include "wine/port.h" - -#ifndef __REACTOS__ -#include -#include -#include -#ifdef HAVE_SYS_IPC_H -# include -#endif -#ifdef HAVE_SYS_IOCTL_H -# include -#endif -#ifdef HAVE_SYS_FILIO_H -# include -#endif -#if defined(__svr4__) -#include -#ifdef HAVE_SYS_SOCKIO_H -# include -#endif -#endif - -#if defined(__EMX__) -# include -#endif - -#ifdef HAVE_SYS_PARAM_H -# include -#endif - -#ifdef HAVE_SYS_MSG_H -# include -#endif -#ifdef HAVE_SYS_WAIT_H -#include -#endif -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -#ifdef HAVE_NETINET_IN_H -# include -#endif -#ifdef HAVE_ARPA_INET_H -# include -#endif -#include -#include -#include -#ifdef HAVE_SYS_ERRNO_H -#include -#endif -#ifdef HAVE_NETDB_H -#include -#endif -#ifdef HAVE_UNISTD_H -# include -#endif -#include -#ifdef HAVE_ARPA_NAMESER_H -# include -#endif -#ifdef HAVE_RESOLV_H -# include -#endif -#endif - -#define CALLBACK __stdcall - -#include "wine/winbase16.h" -#include "windef.h" -#include "winbase.h" -#include "wingdi.h" -#include "winuser.h" -#include "winsock2.h" -#include "ws2spi.h" -#include "wownt32.h" -#include "wine/winsock16.h" -#include "winnt.h" - -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(winsock); - - -/* protoptypes of some functions in socket.c - */ - -#define AQ_WIN16 0x00 -#define AQ_WIN32 0x04 -#define HB_WIN32(hb) (hb->flags & AQ_WIN32) -#define AQ_NUMBER 0x00 -#define AQ_NAME 0x08 -#define AQ_COPYPTR1 0x10 -#define AQ_DUPLOWPTR1 0x20 -#define AQ_MASKPTR1 0x30 -#define AQ_COPYPTR2 0x40 -#define AQ_DUPLOWPTR2 0x80 -#define AQ_MASKPTR2 0xC0 - -#define AQ_GETHOST 0 -#define AQ_GETPROTO 1 -#define AQ_GETSERV 2 -#define AQ_GETMASK 3 - -/* The handles used are pseudo-handles that can be simply casted. */ -/* 16-bit values are used internally (to be sure handle comparison works right in 16-bit apps). */ -#define WSA_H32(h16) ((HANDLE)(ULONG_PTR)(h16)) - -/* ----------------------------------- helper functions - */ - -static int list_size(char** l, int item_size) -{ - int i,j = 0; - if(l) - { for(i=0;l[i];i++) - j += (item_size) ? item_size : strlen(l[i]) + 1; - j += (i + 1) * sizeof(char*); } - return j; -} - -static int list_dup(char** l_src, char* ref, char* base, int item_size) -{ - /* base is either either equal to ref or 0 or SEGPTR */ - - char* p = ref; - char** l_to = (char**)ref; - int i,j,k; - - for(j=0;l_src[j];j++) ; - p += (j + 1) * sizeof(char*); - for(i=0;ih_name) + 1; - size += list_size(p_he->h_aliases, 0); - size += list_size(p_he->h_addr_list, p_he->h_length ); } - return size; -} - -/* Copy hostent to p_to, fix up inside pointers using p_base (different for - * Win16 (linear vs. segmented). Return -neededsize on overrun. - */ -static int WS_copy_he(char *p_to,char *p_base,int t_size,struct hostent* p_he, int flag) -{ - char* p_name,*p_aliases,*p_addr,*p; - struct ws_hostent16 *p_to16 = (struct ws_hostent16*)p_to; - WS_hostent *p_to32 = (WS_hostent*)p_to; - int size = hostent_size(p_he) + - ( - (flag & AQ_WIN16) ? sizeof(struct ws_hostent16) : sizeof(WS_hostent) - - sizeof(struct hostent) - ); - - if (t_size < size) - return -size; - p = p_to; - p += (flag & AQ_WIN16) ? - sizeof(struct ws_hostent16) : sizeof(WS_hostent); - p_name = p; - strcpy(p, p_he->h_name); p += strlen(p) + 1; - p_aliases = p; - p += list_dup(p_he->h_aliases, p, p_base + (p - (char*)p_to), 0); - p_addr = p; - list_dup(p_he->h_addr_list, p, p_base + (p - (char*)p_to), p_he->h_length); - - if (flag & AQ_WIN16) - { - p_to16->h_addrtype = (INT16)p_he->h_addrtype; - p_to16->h_length = (INT16)p_he->h_length; - p_to16->h_name = (SEGPTR)(p_base + (p_name - p_to)); - p_to16->h_aliases = (SEGPTR)(p_base + (p_aliases - p_to)); - p_to16->h_addr_list = (SEGPTR)(p_base + (p_addr - p_to)); - } - else - { - p_to32->h_addrtype = p_he->h_addrtype; - p_to32->h_length = p_he->h_length; - p_to32->h_name = (p_base + (p_name - p_to)); - p_to32->h_aliases = (char **)(p_base + (p_aliases - p_to)); - p_to32->h_addr_list = (char **)(p_base + (p_addr - p_to)); - } - - return size; -} - -/* ----- protoent */ - -static int protoent_size(struct protoent* p_pe) -{ - int size = 0; - if( p_pe ) - { size = sizeof(struct protoent); - size += strlen(p_pe->p_name) + 1; - size += list_size(p_pe->p_aliases, 0); } - return size; -} - -/* Copy protoent to p_to, fix up inside pointers using p_base (different for - * Win16 (linear vs. segmented). Return -neededsize on overrun. - */ -static int WS_copy_pe(char *p_to,char *p_base,int t_size,struct protoent* p_pe, int flag) -{ - char* p_name,*p_aliases,*p; - struct ws_protoent16 *p_to16 = (struct ws_protoent16*)p_to; - WS_protoent *p_to32 = (WS_protoent*)p_to; - int size = protoent_size(p_pe) + - ( - (flag & AQ_WIN16) ? sizeof(struct ws_protoent16) : sizeof(WS_protoent) - - sizeof(struct protoent) - ); - - if (t_size < size) - return -size; - p = p_to; - p += (flag & AQ_WIN16) ? - sizeof(struct ws_protoent16) : sizeof(WS_protoent); - p_name = p; - strcpy(p, p_pe->p_name); p += strlen(p) + 1; - p_aliases = p; - list_dup(p_pe->p_aliases, p, p_base + (p - (char*)p_to), 0); - - if (flag & AQ_WIN16) - { - p_to16->p_proto = (INT16)p_pe->p_proto; - p_to16->p_name = (SEGPTR)(p_base) + (p_name - p_to); - p_to16->p_aliases = (SEGPTR)((p_base) + (p_aliases - p_to)); - } - else - { - p_to32->p_proto = p_pe->p_proto; - p_to32->p_name = (p_base) + (p_name - p_to); - p_to32->p_aliases = (char **)((p_base) + (p_aliases - p_to)); - } - - return size; -} - -/* ----- servent */ - -static int servent_size(struct servent* p_se) -{ - int size = 0; - if( p_se ) { - size += sizeof(struct servent); - size += strlen(p_se->s_proto) + strlen(p_se->s_name) + 2; - size += list_size(p_se->s_aliases, 0); - } - return size; -} - -/* Copy servent to p_to, fix up inside pointers using p_base (different for - * Win16 (linear vs. segmented). Return -neededsize on overrun. - * Take care of different Win16/Win32 servent structs (packing !) - */ -static int WS_copy_se(char *p_to,char *p_base,int t_size,struct servent* p_se, int flag) -{ - char* p_name,*p_aliases,*p_proto,*p; - struct ws_servent16 *p_to16 = (struct ws_servent16*)p_to; - WS_servent *p_to32 = (WS_servent*)p_to; - int size = servent_size(p_se) + - ( - (flag & AQ_WIN16) ? sizeof(struct ws_servent16) : sizeof(WS_servent) - - sizeof(struct servent) - ); - - if (t_size < size) - return -size; - p = p_to; - p += (flag & AQ_WIN16) ? - sizeof(struct ws_servent16) : sizeof(WS_servent); - p_name = p; - strcpy(p, p_se->s_name); p += strlen(p) + 1; - p_proto = p; - strcpy(p, p_se->s_proto); p += strlen(p) + 1; - p_aliases = p; - list_dup(p_se->s_aliases, p, p_base + (p - p_to), 0); - - if (flag & AQ_WIN16) - { - p_to16->s_port = (INT16)p_se->s_port; - p_to16->s_name = (SEGPTR)(p_base + (p_name - p_to)); - p_to16->s_proto = (SEGPTR)(p_base + (p_proto - p_to)); - p_to16->s_aliases = (SEGPTR)(p_base + (p_aliases - p_to)); - } - else - { - p_to32->s_port = p_se->s_port; - p_to32->s_name = (p_base + (p_name - p_to)); - p_to32->s_proto = (p_base + (p_proto - p_to)); - p_to32->s_aliases = (char **)(p_base + (p_aliases - p_to)); - } - - return size; -} - -static HANDLE16 __ws_async_handle = 0xdead; - -/* Generic async query struct. we use symbolic names for the different queries - * for readability. - */ -typedef struct _async_query { - HWND16 hWnd; - UINT16 uMsg; - LPCSTR ptr1; -#define host_name ptr1 -#define host_addr ptr1 -#define serv_name ptr1 -#define proto_name ptr1 - LPCSTR ptr2; -#define serv_proto ptr2 - int int1; -#define host_len int1 -#define proto_number int1 -#define serv_port int1 - int int2; -#define host_type int2 - SEGPTR sbuf; - INT16 sbuflen; - - HANDLE16 async_handle; - int flags; - int qt; - char xbuf[1]; -} async_query; - - -/**************************************************************************** - * The async query function. - * - * It is either called as a thread startup routine or directly. It has - * to free the passed arg from the process heap and PostMessageA the async - * result or the error code. - * - * FIXME: - * - errorhandling not verified. - */ -static DWORD WINAPI _async_queryfun(LPVOID arg) { - async_query *aq = (async_query*)arg; - int size = 0; - WORD fail = 0; - char *targetptr = (HB_WIN32(aq)?(char*)aq->sbuf:0/*(char*)MapSL(aq->sbuf)*/); - - switch (aq->flags & AQ_GETMASK) { - case AQ_GETHOST: { - struct hostent *he; - char *copy_hostent = targetptr; - char buf[100]; - if( !(aq->host_name)) { - aq->host_name = buf; - if( gethostname( buf, 100) == -1) { - fail = WSAENOBUFS; /* appropriate ? */ - break; - } - } - he = (aq->flags & AQ_NAME) ? - gethostbyname(aq->host_name): - gethostbyaddr(aq->host_addr,aq->host_len,aq->host_type); - if (!he) fail = WSAGetLastError(); - if (he) { - size = WS_copy_he(copy_hostent,(char*)aq->sbuf,aq->sbuflen,he,aq->flags); - if (size < 0) { - fail = WSAENOBUFS; - size = -size; - } - } - } - break; - case AQ_GETPROTO: { -#if defined(HAVE_GETPROTOBYNAME) && defined(HAVE_GETPROTOBYNUMBER) - struct protoent *pe; - char *copy_protoent = targetptr; - pe = (aq->flags & AQ_NAME)? - getprotobyname(aq->proto_name) : - getprotobynumber(aq->proto_number); - if (pe) { - size = WS_copy_pe(copy_protoent,(char*)aq->sbuf,aq->sbuflen,pe,aq->flags); - if (size < 0) { - fail = WSAENOBUFS; - size = -size; - } - } else { - if (aq->flags & AQ_NAME) - MESSAGE("protocol %s not found; You might want to add " - "this to /etc/protocols\n", debugstr_a(aq->proto_name) ); - else - MESSAGE("protocol number %d not found; You might want to add " - "this to /etc/protocols\n", aq->proto_number ); - fail = WSANO_DATA; - } -#else - fail = WSANO_DATA; -#endif - } - break; - case AQ_GETSERV: { - struct servent *se; - char *copy_servent = targetptr; - se = (aq->flags & AQ_NAME)? - getservbyname(aq->serv_name,aq->serv_proto) : -#ifdef HAVE_GETSERVBYPORT - getservbyport(aq->serv_port,aq->serv_proto); -#else - NULL; -#endif - if (se) { - size = WS_copy_se(copy_servent,(char*)aq->sbuf,aq->sbuflen,se,aq->flags); - if (size < 0) { - fail = WSAENOBUFS; - size = -size; - } - } else { - if (aq->flags & AQ_NAME) - MESSAGE("service %s protocol %s not found; You might want to add " - "this to /etc/services\n", debugstr_a(aq->serv_name) , - aq->serv_proto ? debugstr_a(aq->serv_proto ):"*"); - else - MESSAGE("service on port %d protocol %s not found; You might want to add " - "this to /etc/services\n", aq->serv_port, - aq->serv_proto ? debugstr_a(aq->serv_proto ):"*"); - fail = WSANO_DATA; - } - } - break; - } - PostMessageA(HWND_32(aq->hWnd),aq->uMsg,(WPARAM) aq->async_handle,size|(fail<<16)); - HeapFree(GetProcessHeap(),0,arg); - return 0; -} - -/**************************************************************************** - * The main async help function. - * - * It either starts a thread or just calls the function directly for platforms - * with no thread support. This relies on the fact that PostMessage() does - * not actually call the windowproc before the function returns. - */ -static HANDLE16 __WSAsyncDBQuery( - HWND hWnd, UINT uMsg,INT int1,LPCSTR ptr1, INT int2, LPCSTR ptr2, - void *sbuf, INT sbuflen, UINT flags -) -{ - async_query* aq; - char* pto; - LPCSTR pfm; - int xbuflen = 0; - - /* allocate buffer to copy protocol- and service name to */ - /* note: this is done in the calling thread so we can return */ - /* a decent error code if the Alloc fails */ - - switch (flags & AQ_MASKPTR1) { - case 0: break; - case AQ_COPYPTR1: xbuflen += int1; break; - case AQ_DUPLOWPTR1: xbuflen += strlen(ptr1) + 1; break; - } - - switch (flags & AQ_MASKPTR2) { - case 0: break; - case AQ_COPYPTR2: xbuflen += int2; break; - case AQ_DUPLOWPTR2: xbuflen += strlen(ptr2) + 1; break; - } - - if(!(aq = HeapAlloc(GetProcessHeap(),0,sizeof(async_query) + xbuflen))) { - SetLastError(WSAEWOULDBLOCK); /* insufficient resources */ - return 0; - } - - pto = aq->xbuf; - if (ptr1) switch (flags & AQ_MASKPTR1) { - case 0: break; - case AQ_COPYPTR1: memcpy(pto, ptr1, int1); ptr1 = pto; pto += int1; break; - case AQ_DUPLOWPTR1: pfm = ptr1; ptr1 = pto; do *pto++ = tolower(*pfm); while (*pfm++); break; - } - if (ptr2) switch (flags & AQ_MASKPTR2) { - case 0: break; - case AQ_COPYPTR2: memcpy(pto, ptr2, int2); ptr2 = pto; pto += int2; break; - case AQ_DUPLOWPTR2: pfm = ptr2; ptr2 = pto; do *pto++ = tolower(*pfm); while (*pfm++); break; - } - - aq->hWnd = HWND_16(hWnd); - aq->uMsg = uMsg; - aq->int1 = int1; - aq->ptr1 = ptr1; - aq->int2 = int2; - aq->ptr2 = ptr2; - /* avoid async_handle = 0 */ - aq->async_handle = (++__ws_async_handle ? __ws_async_handle : ++__ws_async_handle); - aq->flags = flags; - aq->sbuf = (SEGPTR)sbuf; - aq->sbuflen = sbuflen; - -#if 1 - if (CreateThread(NULL,0,_async_queryfun,aq,0,NULL) == INVALID_HANDLE_VALUE) -#endif - _async_queryfun(aq); - return __ws_async_handle; -} - - -/*********************************************************************** - * WSAAsyncGetHostByAddr (WINSOCK.102) - */ -HANDLE16 WINAPI WSAAsyncGetHostByAddr16(HWND16 hWnd, UINT16 uMsg, LPCSTR addr, - INT16 len, INT16 type, SEGPTR sbuf, INT16 buflen) -{ - TRACE("hwnd %04x, msg %04x, addr %08x[%i]\n", - hWnd, uMsg, (unsigned)addr , len ); - return __WSAsyncDBQuery(HWND_32(hWnd),uMsg,len,addr,type,NULL, - (void*)sbuf,buflen, - AQ_NUMBER|AQ_COPYPTR1|AQ_WIN16|AQ_GETHOST); -} - -/*********************************************************************** - * WSAAsyncGetHostByAddr (WS2_32.102) - */ -HANDLE WINAPI WSAAsyncGetHostByAddr(HWND hWnd, UINT uMsg, LPCSTR addr, - INT len, INT type, LPSTR sbuf, INT buflen) -{ - TRACE("hwnd %p, msg %04x, addr %08x[%i]\n", - hWnd, uMsg, (unsigned)addr , len ); - return WSA_H32( __WSAsyncDBQuery(hWnd,uMsg,len,addr,type,NULL,sbuf,buflen, - AQ_NUMBER|AQ_COPYPTR1|AQ_WIN32|AQ_GETHOST)); -} - -/*********************************************************************** - * WSAAsyncGetHostByName (WINSOCK.103) - */ -HANDLE16 WINAPI WSAAsyncGetHostByName16(HWND16 hWnd, UINT16 uMsg, LPCSTR name, - SEGPTR sbuf, INT16 buflen) -{ - TRACE("hwnd %04x, msg %04x, host %s, buffer %i\n", - hWnd, uMsg, (name)?name:"", (int)buflen ); - return __WSAsyncDBQuery(HWND_32(hWnd),uMsg,0,name,0,NULL, - (void*)sbuf,buflen, - AQ_NAME|AQ_DUPLOWPTR1|AQ_WIN16|AQ_GETHOST); -} - -/*********************************************************************** - * WSAAsyncGetHostByName (WS2_32.103) - */ -HANDLE WINAPI WSAAsyncGetHostByName(HWND hWnd, UINT uMsg, LPCSTR name, - LPSTR sbuf, INT buflen) -{ - TRACE("hwnd %p, msg %08x, host %s, buffer %i\n", - hWnd, uMsg, (name)?name:"", (int)buflen ); - return WSA_H32( __WSAsyncDBQuery(hWnd,uMsg,0,name,0,NULL,sbuf,buflen, - AQ_NAME|AQ_DUPLOWPTR1|AQ_WIN32|AQ_GETHOST)); -} - -/*********************************************************************** - * WSAAsyncGetProtoByName (WINSOCK.105) - */ -HANDLE16 WINAPI WSAAsyncGetProtoByName16(HWND16 hWnd, UINT16 uMsg, LPCSTR name, - SEGPTR sbuf, INT16 buflen) -{ - TRACE("hwnd %04x, msg %08x, protocol %s\n", - hWnd, uMsg, (name)?name:"" ); - return __WSAsyncDBQuery(HWND_32(hWnd),uMsg,0,name,0,NULL, - (void*)sbuf,buflen, - AQ_NAME|AQ_DUPLOWPTR1|AQ_WIN16|AQ_GETPROTO); -} - -/*********************************************************************** - * WSAAsyncGetProtoByName (WS2_32.105) - */ -HANDLE WINAPI WSAAsyncGetProtoByName(HWND hWnd, UINT uMsg, LPCSTR name, - LPSTR sbuf, INT buflen) -{ - TRACE("hwnd %p, msg %08x, protocol %s\n", - hWnd, uMsg, (name)?name:"" ); - return WSA_H32( __WSAsyncDBQuery(hWnd,uMsg,0,name,0,NULL,sbuf,buflen, - AQ_NAME|AQ_DUPLOWPTR1|AQ_WIN32|AQ_GETPROTO)); -} - - -/*********************************************************************** - * WSAAsyncGetProtoByNumber (WINSOCK.104) - */ -HANDLE16 WINAPI WSAAsyncGetProtoByNumber16(HWND16 hWnd,UINT16 uMsg,INT16 number, - SEGPTR sbuf, INT16 buflen) -{ - TRACE("hwnd %04x, msg %04x, num %i\n", hWnd, uMsg, number ); - return __WSAsyncDBQuery(HWND_32(hWnd),uMsg,number,NULL,0,NULL, - (void*)sbuf,buflen, - AQ_GETPROTO|AQ_NUMBER|AQ_WIN16); -} - -/*********************************************************************** - * WSAAsyncGetProtoByNumber (WS2_32.104) - */ -HANDLE WINAPI WSAAsyncGetProtoByNumber(HWND hWnd, UINT uMsg, INT number, - LPSTR sbuf, INT buflen) -{ - TRACE("hwnd %p, msg %04x, num %i\n", hWnd, uMsg, number ); - return WSA_H32( __WSAsyncDBQuery(hWnd,uMsg,number,NULL,0,NULL,sbuf,buflen, - AQ_GETPROTO|AQ_NUMBER|AQ_WIN32)); -} - -/*********************************************************************** - * WSAAsyncGetServByName (WINSOCK.107) - */ -HANDLE16 WINAPI WSAAsyncGetServByName16(HWND16 hWnd, UINT16 uMsg, LPCSTR name, - LPCSTR proto, SEGPTR sbuf, INT16 buflen) -{ - TRACE("hwnd %04x, msg %04x, name %s, proto %s\n", - hWnd, uMsg, (name)?name:"", (proto)?proto:""); - return __WSAsyncDBQuery(HWND_32(hWnd),uMsg,0,name,0,proto, - (void*)sbuf,buflen, - AQ_GETSERV|AQ_NAME|AQ_DUPLOWPTR1|AQ_DUPLOWPTR2|AQ_WIN16); -} - -/*********************************************************************** - * WSAAsyncGetServByName (WS2_32.107) - */ -HANDLE WINAPI WSAAsyncGetServByName(HWND hWnd, UINT uMsg, LPCSTR name, - LPCSTR proto, LPSTR sbuf, INT buflen) -{ - TRACE("hwnd %p, msg %04x, name %s, proto %s\n", - hWnd, uMsg, (name)?name:"", (proto)?proto:""); - return WSA_H32( __WSAsyncDBQuery(hWnd,uMsg,0,name,0,proto,sbuf,buflen, - AQ_GETSERV|AQ_NAME|AQ_DUPLOWPTR1|AQ_DUPLOWPTR2|AQ_WIN32)); -} - -/*********************************************************************** - * WSAAsyncGetServByPort (WINSOCK.106) - */ -HANDLE16 WINAPI WSAAsyncGetServByPort16(HWND16 hWnd, UINT16 uMsg, INT16 port, - LPCSTR proto, SEGPTR sbuf, INT16 buflen) -{ - TRACE("hwnd %04x, msg %04x, port %i, proto %s\n", - hWnd, uMsg, port, (proto)?proto:"" ); - return __WSAsyncDBQuery(HWND_32(hWnd),uMsg,port,NULL,0,proto, - (void*)sbuf,buflen, - AQ_GETSERV|AQ_NUMBER|AQ_DUPLOWPTR2|AQ_WIN16); -} - -/*********************************************************************** - * WSAAsyncGetServByPort (WS2_32.106) - */ -HANDLE WINAPI WSAAsyncGetServByPort(HWND hWnd, UINT uMsg, INT port, - LPCSTR proto, LPSTR sbuf, INT buflen) -{ - TRACE("hwnd %p, msg %04x, port %i, proto %s\n", - hWnd, uMsg, port, (proto)?proto:"" ); - return WSA_H32( __WSAsyncDBQuery(hWnd,uMsg,port,NULL,0,proto,sbuf,buflen, - AQ_GETSERV|AQ_NUMBER|AQ_DUPLOWPTR2|AQ_WIN32)); -} diff --git a/dll/win32/ws2_32/misc/bsd.c b/dll/win32/ws2_32/misc/bsd.c deleted file mode 100644 index 2e39c24b5e9..00000000000 --- a/dll/win32/ws2_32/misc/bsd.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS WinSock 2 DLL - * FILE: misc/bsd.c - * PURPOSE: Legacy BSD sockets APIs - * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) - * REVISIONS: - * CSH 15/06-2001 Created - */ -#include - -/* - * @implemented - */ -ULONG -EXPORT -htonl(IN ULONG hostlong) -{ - return DH2N(hostlong); -} - - -/* - * @implemented - */ -USHORT -EXPORT -htons(IN USHORT hostshort) -{ - return WH2N(hostshort); -} - - -/* - * @implemented - */ -ULONG -EXPORT -ntohl(IN ULONG netlong) -{ - return DN2H(netlong); -} - - -/* - * @implemented - */ -USHORT -EXPORT -ntohs(IN USHORT netshort) -{ - return WN2H(netshort); -} - -/* EOF */ diff --git a/dll/win32/ws2_32/misc/catalog.c b/dll/win32/ws2_32/misc/catalog.c deleted file mode 100644 index 0dc13c41de3..00000000000 --- a/dll/win32/ws2_32/misc/catalog.c +++ /dev/null @@ -1,355 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS WinSock 2 DLL - * FILE: misc/catalog.c - * PURPOSE: Service Provider Catalog - * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) - * REVISIONS: - * CSH 01/09-2000 Created - */ -#include -#include - - -LIST_ENTRY CatalogListHead; -CRITICAL_SECTION CatalogLock; - -VOID -ReferenceProviderByPointer(PCATALOG_ENTRY Provider) -{ - WS_DbgPrint(MAX_TRACE, ("Provider (0x%X).\n", Provider)); - - //EnterCriticalSection(&Provider->Lock); - Provider->ReferenceCount++; - //LeaveCriticalSection(&Provider->Lock); - - WS_DbgPrint(MAX_TRACE, ("Leaving\n")); -} - - -VOID -DereferenceProviderByPointer(PCATALOG_ENTRY Provider) -{ - WS_DbgPrint(MAX_TRACE, ("Provider (0x%X).\n", Provider)); - -#if DBG - if (Provider->ReferenceCount <= 0) - { - WS_DbgPrint(MIN_TRACE, ("Provider at 0x%X has invalid reference count (%ld).\n", - Provider, Provider->ReferenceCount)); - } -#endif - - //EnterCriticalSection(&Provider->Lock); - Provider->ReferenceCount--; - //LeaveCriticalSection(&Provider->Lock); - - if (Provider->ReferenceCount == 0) - { - WS_DbgPrint(MAX_TRACE, ("Provider at 0x%X has reference count 0 (unloading).\n", - Provider)); - - DestroyCatalogEntry(Provider); - } -} - - -PCATALOG_ENTRY -CreateCatalogEntry(LPWSTR LibraryName) -{ - PCATALOG_ENTRY Provider; - - WS_DbgPrint(MAX_TRACE, ("LibraryName (%S).\n", LibraryName)); - - Provider = HeapAlloc(GlobalHeap, 0, sizeof(CATALOG_ENTRY)); - if (!Provider) - return NULL; - - ZeroMemory(Provider, sizeof(CATALOG_ENTRY)); - - if (!RtlCreateUnicodeString(&Provider->LibraryName, LibraryName)) - { - RtlFreeHeap(GlobalHeap, 0, Provider); - return NULL; - } - - Provider->ReferenceCount = 1; - - InitializeCriticalSection(&Provider->Lock); - Provider->hModule = NULL; - - Provider->Mapping = NULL; - - //EnterCriticalSection(&CatalogLock); - - InsertTailList(&CatalogListHead, &Provider->ListEntry); - - //LeaveCriticalSection(&CatalogLock); - - return Provider; -} - - -INT -DestroyCatalogEntry(PCATALOG_ENTRY Provider) -{ - INT Status; - - WS_DbgPrint(MAX_TRACE, ("Provider (0x%X).\n", Provider)); - - //EnterCriticalSection(&CatalogLock); - RemoveEntryList(&Provider->ListEntry); - //LeaveCriticalSection(&CatalogLock); - - HeapFree(GlobalHeap, 0, Provider->Mapping); - - if (NULL != Provider->hModule) - { - Status = UnloadProvider(Provider); - } - else - { - Status = NO_ERROR; - } - - //DeleteCriticalSection(&Provider->Lock); - - HeapFree(GlobalHeap, 0, Provider); - - return Status; -} - - -PCATALOG_ENTRY -LocateProvider(LPWSAPROTOCOL_INFOW lpProtocolInfo) -{ - PLIST_ENTRY CurrentEntry; - PCATALOG_ENTRY Provider; - UINT i; - - WS_DbgPrint(MAX_TRACE, ("lpProtocolInfo (0x%X).\n", lpProtocolInfo)); - - //EnterCriticalSection(&CatalogLock); - - CurrentEntry = CatalogListHead.Flink; - while (CurrentEntry != &CatalogListHead) - { - Provider = CONTAINING_RECORD(CurrentEntry, - CATALOG_ENTRY, - ListEntry); - - for (i = 0; i < Provider->Mapping->Rows; i++) - { - if ((lpProtocolInfo->iAddressFamily == (INT) Provider->Mapping->Mapping[i].AddressFamily) && - (lpProtocolInfo->iSocketType == (INT) Provider->Mapping->Mapping[i].SocketType) && - ((lpProtocolInfo->iProtocol == (INT) Provider->Mapping->Mapping[i].Protocol) || - (lpProtocolInfo->iSocketType == SOCK_RAW))) - { - //LeaveCriticalSection(&CatalogLock); - WS_DbgPrint(MID_TRACE, ("Returning provider at (0x%X).\n", Provider)); - return Provider; - } - } - - CurrentEntry = CurrentEntry->Flink; - } - - //LeaveCriticalSection(&CatalogLock); - - return NULL; -} - - -PCATALOG_ENTRY -LocateProviderById(DWORD CatalogEntryId) -{ - PLIST_ENTRY CurrentEntry; - PCATALOG_ENTRY Provider; - - WS_DbgPrint(MAX_TRACE, ("CatalogEntryId (%d).\n", CatalogEntryId)); - - //EnterCriticalSection(&CatalogLock); - CurrentEntry = CatalogListHead.Flink; - while (CurrentEntry != &CatalogListHead) - { - Provider = CONTAINING_RECORD(CurrentEntry, - CATALOG_ENTRY, - ListEntry); - - if (Provider->ProtocolInfo.dwCatalogEntryId == CatalogEntryId) - { - //LeaveCriticalSection(&CatalogLock); - WS_DbgPrint(MID_TRACE, ("Returning provider at (0x%X) Name (%wZ).\n", - Provider, &Provider->LibraryName)); - return Provider; - } - - CurrentEntry = CurrentEntry->Flink; - } - //LeaveCriticalSection(&CatalogLock); - - WS_DbgPrint(MID_TRACE, ("Provider was not found.\n")); - - return NULL; -} - - -INT -LoadProvider(PCATALOG_ENTRY Provider, - LPWSAPROTOCOL_INFOW lpProtocolInfo) -{ - INT Status; - - WS_DbgPrint(MID_TRACE, ("Loading provider at (0x%X) Name (%wZ).\n", - Provider, &Provider->LibraryName)); - - if (NULL == Provider->hModule) - { - /* DLL is not loaded so load it now - * UNICODE_STRING objects are not null-terminated, but LoadLibraryW - * expects a null-terminated string - */ - Provider->LibraryName.Buffer[Provider->LibraryName.Length / sizeof(WCHAR)] = L'\0'; - Provider->hModule = LoadLibraryW(Provider->LibraryName.Buffer); - if (NULL != Provider->hModule) - { - Provider->WSPStartup = (LPWSPSTARTUP)GetProcAddress(Provider->hModule, - "WSPStartup"); - if (Provider->WSPStartup) - { - WS_DbgPrint(MAX_TRACE, ("Calling WSPStartup at (0x%X).\n", - Provider->WSPStartup)); - Status = Provider->WSPStartup(MAKEWORD(2, 2), - &Provider->WSPData, - lpProtocolInfo, - UpcallTable, - &Provider->ProcTable); - - /* FIXME: Validate the procedure table */ - } - else - Status = ERROR_BAD_PROVIDER; - } - else - Status = ERROR_DLL_NOT_FOUND; - } - else - Status = NO_ERROR; - - WS_DbgPrint(MID_TRACE, ("Status (%d).\n", Status)); - - return Status; -} - - -INT -UnloadProvider(PCATALOG_ENTRY Provider) -{ - INT Status = NO_ERROR; - - WS_DbgPrint(MAX_TRACE, ("Unloading provider at (0x%X)\n", Provider)); - - if (NULL != Provider->hModule) - { - WS_DbgPrint(MAX_TRACE, ("Calling WSPCleanup at (0x%X).\n", - Provider->ProcTable.lpWSPCleanup)); - Provider->ProcTable.lpWSPCleanup(&Status); - - WS_DbgPrint(MAX_TRACE, ("Calling FreeLibrary(0x%X).\n", Provider->hModule)); - if (!FreeLibrary(Provider->hModule)) - { - WS_DbgPrint(MIN_TRACE, ("Could not free library at (0x%X).\n", Provider->hModule)); - Status = GetLastError(); - } - - Provider->hModule = NULL; - } - - WS_DbgPrint(MAX_TRACE, ("Status (%d).\n", Status)); - - return Status; -} - - -VOID -CreateCatalog(VOID) -{ - PCATALOG_ENTRY Provider; - - InitializeCriticalSection(&CatalogLock); - - InitializeListHead(&CatalogListHead); - - /* FIXME: Read service provider catalog from registry - - Catalog info is saved somewhere under - HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\WinSock2 - */ - -#if 1 - Provider = CreateCatalogEntry(L"msafd.dll"); - if (!Provider) - { - WS_DbgPrint(MIN_TRACE, ("Could not create catalog entry.\n")); - return; - } - - /* Assume one Service Provider with id 1 */ - Provider->ProtocolInfo.dwCatalogEntryId = 1; - - Provider->Mapping = HeapAlloc(GlobalHeap, - 0, - 6 * sizeof(WINSOCK_MAPPING) + 3 * sizeof(DWORD)); - if (!Provider->Mapping) - return; - - Provider->Mapping->Rows = 6; - Provider->Mapping->Columns = 3; - - Provider->Mapping->Mapping[0].AddressFamily = AF_INET; - Provider->Mapping->Mapping[0].SocketType = SOCK_STREAM; - Provider->Mapping->Mapping[0].Protocol = 0; - - Provider->Mapping->Mapping[1].AddressFamily = AF_INET; - Provider->Mapping->Mapping[1].SocketType = SOCK_STREAM; - Provider->Mapping->Mapping[1].Protocol = IPPROTO_TCP; - - Provider->Mapping->Mapping[2].AddressFamily = AF_INET; - Provider->Mapping->Mapping[2].SocketType = SOCK_DGRAM; - Provider->Mapping->Mapping[2].Protocol = 0; - - Provider->Mapping->Mapping[3].AddressFamily = AF_INET; - Provider->Mapping->Mapping[3].SocketType = SOCK_DGRAM; - Provider->Mapping->Mapping[3].Protocol = IPPROTO_UDP; - - Provider->Mapping->Mapping[4].AddressFamily = AF_INET; - Provider->Mapping->Mapping[4].SocketType = SOCK_RAW; - Provider->Mapping->Mapping[4].Protocol = IPPROTO_ICMP; - - Provider->Mapping->Mapping[5].AddressFamily = AF_INET; - Provider->Mapping->Mapping[5].SocketType = SOCK_RAW; - Provider->Mapping->Mapping[5].Protocol = 0; -#endif -} - - -VOID DestroyCatalog(VOID) -{ - PLIST_ENTRY CurrentEntry; - PLIST_ENTRY NextEntry; - PCATALOG_ENTRY Provider; - - CurrentEntry = CatalogListHead.Flink; - while (CurrentEntry != &CatalogListHead) - { - NextEntry = CurrentEntry->Flink; - Provider = CONTAINING_RECORD(CurrentEntry, - CATALOG_ENTRY, - ListEntry); - DestroyCatalogEntry(Provider); - CurrentEntry = NextEntry; - } - //DeleteCriticalSection(&CatalogLock); -} - -/* EOF */ diff --git a/dll/win32/ws2_32/misc/dllmain.c b/dll/win32/ws2_32/misc/dllmain.c deleted file mode 100644 index 78793cbd87c..00000000000 --- a/dll/win32/ws2_32/misc/dllmain.c +++ /dev/null @@ -1,896 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS WinSock 2 DLL - * FILE: misc/dllmain.c - * PURPOSE: DLL entry point - * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) - * REVISIONS: - * CSH 01/09-2000 Created - */ - -#include -#include -#include -#include -#include - -#if DBG - -/* See debug.h for debug/trace constants */ -//DWORD DebugTraceLevel = MIN_TRACE; -//DWORD DebugTraceLevel = MAX_TRACE; -//DWORD DebugTraceLevel = DEBUG_ULTRA; -DWORD DebugTraceLevel = 0; -#endif /* DBG */ - -/* To make the linker happy */ -VOID WINAPI KeBugCheck (ULONG BugCheckCode) {} - -HINSTANCE g_hInstDll; -HANDLE GlobalHeap; -BOOL WsaInitialized = FALSE; /* TRUE if WSAStartup() has been successfully called */ -WSPUPCALLTABLE UpcallTable; - - -/* - * @implemented - */ -INT -EXPORT -WSAGetLastError(VOID) -{ - return GetLastError(); -} - - -/* - * @implemented - */ -VOID -EXPORT -WSASetLastError(IN INT iError) -{ - SetLastError(iError); -} - - -/* - * @implemented - */ -INT -EXPORT -WSAStartup(IN WORD wVersionRequested, - OUT LPWSADATA lpWSAData) -{ - BYTE Low, High; - - WS_DbgPrint(MAX_TRACE, ("WSAStartup of ws2_32.dll\n")); - - if (!g_hInstDll) - return WSASYSNOTREADY; - - if (lpWSAData == NULL) - return WSAEFAULT; - - Low = LOBYTE(wVersionRequested); - High = HIBYTE(wVersionRequested); - - if (Low < 1) - { - WS_DbgPrint(MAX_TRACE, ("Bad winsock version requested, %d,%d", Low, High)); - return WSAVERNOTSUPPORTED; - } - - if (Low == 1) - { - if (High == 0) - { - lpWSAData->wVersion = wVersionRequested; - } - else - { - lpWSAData->wVersion = MAKEWORD(1, 1); - } - } - else if (Low == 2) - { - if (High <= 2) - { - lpWSAData->wVersion = MAKEWORD(2, High); - } - else - { - lpWSAData->wVersion = MAKEWORD(2, 2); - } - } - else - { - lpWSAData->wVersion = MAKEWORD(2, 2); - } - - lpWSAData->wVersion = wVersionRequested; - lpWSAData->wHighVersion = MAKEWORD(2,2); - lstrcpyA(lpWSAData->szDescription, "WinSock 2.2"); - lstrcpyA(lpWSAData->szSystemStatus, "Running"); - lpWSAData->iMaxSockets = 0; - lpWSAData->iMaxUdpDg = 0; - lpWSAData->lpVendorInfo = NULL; - - /*FIXME: increment internal counter */ - - WSASETINITIALIZED; - - return NO_ERROR; -} - - -/* - * @implemented - */ -INT -EXPORT -WSACleanup(VOID) -{ - WS_DbgPrint(MAX_TRACE, ("WSACleanup of ws2_32.dll\n")); - - if (!WSAINITIALIZED) - { - WSASetLastError(WSANOTINITIALISED); - return WSANOTINITIALISED; - } - - return NO_ERROR; -} - - -/* - * @implemented - */ -SOCKET -EXPORT -socket(IN INT af, - IN INT type, - IN INT protocol) -{ - return WSASocketW(af, - type, - protocol, - NULL, - 0, - 0); -} - - -/* - * @implemented - */ -SOCKET -EXPORT -WSASocketA(IN INT af, - IN INT type, - IN INT protocol, - IN LPWSAPROTOCOL_INFOA lpProtocolInfo, - IN GROUP g, - IN DWORD dwFlags) -/* - * FUNCTION: Creates a new socket - */ -{ - WSAPROTOCOL_INFOW ProtocolInfoW; - LPWSAPROTOCOL_INFOW p; - UNICODE_STRING StringU; - ANSI_STRING StringA; - - WS_DbgPrint(MAX_TRACE, ("af (%d) type (%d) protocol (%d).\n", - af, type, protocol)); - - if (lpProtocolInfo) - { - memcpy(&ProtocolInfoW, - lpProtocolInfo, - sizeof(WSAPROTOCOL_INFOA) - sizeof(CHAR) * (WSAPROTOCOL_LEN + 1)); - RtlInitAnsiString(&StringA, (LPSTR)lpProtocolInfo->szProtocol); - RtlInitUnicodeString(&StringU, (LPWSTR)&ProtocolInfoW.szProtocol); - RtlAnsiStringToUnicodeString(&StringU, &StringA, FALSE); - p = &ProtocolInfoW; - } - else - { - p = NULL; - } - - return WSASocketW(af, - type, - protocol, - p, - g, - dwFlags); -} - - -/* - * @implemented - */ -SOCKET -EXPORT -WSASocketW(IN INT af, - IN INT type, - IN INT protocol, - IN LPWSAPROTOCOL_INFOW lpProtocolInfo, - IN GROUP g, - IN DWORD dwFlags) -/* - * FUNCTION: Creates a new socket descriptor - * ARGUMENTS: - * af = Address family - * type = Socket type - * protocol = Protocol type - * lpProtocolInfo = Pointer to protocol information - * g = Reserved - * dwFlags = Socket flags - * RETURNS: - * Created socket descriptor, or INVALID_SOCKET if it could not be created - */ -{ - INT Status; - SOCKET Socket; - PCATALOG_ENTRY Provider; - WSAPROTOCOL_INFOW ProtocolInfo; - - WS_DbgPrint(MAX_TRACE, ("af (%d) type (%d) protocol (%d).\n", - af, type, protocol)); - - if (!WSAINITIALIZED) - { - WS_DbgPrint(MAX_TRACE, ("af (%d) type (%d) protocol (%d) = WSANOTINITIALISED.\n", - af, type, protocol)); - WSASetLastError(WSANOTINITIALISED); - return INVALID_SOCKET; - } - - if (!lpProtocolInfo) - { - lpProtocolInfo = &ProtocolInfo; - ZeroMemory(&ProtocolInfo, sizeof(WSAPROTOCOL_INFOW)); - - ProtocolInfo.iAddressFamily = af; - ProtocolInfo.iSocketType = type; - ProtocolInfo.iProtocol = protocol; - } - - Provider = LocateProvider(lpProtocolInfo); - if (!Provider) - { - WS_DbgPrint(MAX_TRACE, ("af (%d) type (%d) protocol (%d) = WSAEAFNOSUPPORT.\n", - af, type, protocol)); - WSASetLastError(WSAEAFNOSUPPORT); - return INVALID_SOCKET; - } - - Status = LoadProvider(Provider, lpProtocolInfo); - if (Status != NO_ERROR) - { - WS_DbgPrint(MAX_TRACE, ("af (%d) type (%d) protocol (%d) = %d.\n", - af, type, protocol, Status)); - WSASetLastError(Status); - return INVALID_SOCKET; - } - - WS_DbgPrint(MAX_TRACE, ("Calling WSPSocket at (0x%X).\n", - Provider->ProcTable.lpWSPSocket)); - - assert(Provider->ProcTable.lpWSPSocket); - - WS_DbgPrint(MAX_TRACE,("About to call provider socket fn\n")); - - Socket = Provider->ProcTable.lpWSPSocket(af, - type, - protocol, - lpProtocolInfo, - g, - dwFlags, - &Status); - - WS_DbgPrint(MAX_TRACE,("Socket: %x, Status: %x\n", Socket, Status)); - - if (Status != NO_ERROR) - { - WSASetLastError(Status); - return INVALID_SOCKET; - } - - WS_DbgPrint(MAX_TRACE,("Status: %x\n", Status)); - - return Socket; -} - - -/* - * @implemented - */ -INT -EXPORT -closesocket(IN SOCKET s) -/* - * FUNCTION: Closes a socket descriptor - * ARGUMENTS: - * s = Socket descriptor - * RETURNS: - * 0, or SOCKET_ERROR if an error ocurred - */ -{ - PCATALOG_ENTRY Provider; - INT Status; - INT Errno; - - WS_DbgPrint(MAX_TRACE, ("s (0x%X).\n", s)); - - if (!WSAINITIALIZED) - { - WSASetLastError(WSANOTINITIALISED); - return SOCKET_ERROR; - } - - if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) - { - WSASetLastError(WSAENOTSOCK); - return SOCKET_ERROR; - } - - CloseProviderHandle((HANDLE)s); - - WS_DbgPrint(MAX_TRACE,("DereferenceProviderByHandle\n")); - - DereferenceProviderByPointer(Provider); - - WS_DbgPrint(MAX_TRACE,("DereferenceProviderByHandle Done\n")); - - Status = Provider->ProcTable.lpWSPCloseSocket(s, &Errno); - - WS_DbgPrint(MAX_TRACE,("Provider Close Done\n")); - - if (Status == SOCKET_ERROR) - WSASetLastError(Errno); - - WS_DbgPrint(MAX_TRACE,("Returning success\n")); - - return 0; -} - - -/* - * @implemented - */ -INT -EXPORT -select(IN INT nfds, - IN OUT LPFD_SET readfds, - IN OUT LPFD_SET writefds, - IN OUT LPFD_SET exceptfds, - IN CONST struct timeval *timeout) -/* - * FUNCTION: Returns status of one or more sockets - * ARGUMENTS: - * nfds = Always ignored - * readfds = Pointer to socket set to be checked for readability (optional) - * writefds = Pointer to socket set to be checked for writability (optional) - * exceptfds = Pointer to socket set to be checked for errors (optional) - * timeout = Pointer to a TIMEVAL structure indicating maximum wait time - * (NULL means wait forever) - * RETURNS: - * Number of ready socket descriptors, or SOCKET_ERROR if an error ocurred - */ -{ - PCATALOG_ENTRY Provider = NULL; - INT Count; - INT Errno; - - WS_DbgPrint(MAX_TRACE, ("readfds (0x%X) writefds (0x%X) exceptfds (0x%X).\n", - readfds, writefds, exceptfds)); - - if (!WSAINITIALIZED) - { - WSASetLastError(WSANOTINITIALISED); - WS_DbgPrint(MID_TRACE,("Not initialized\n")); - return SOCKET_ERROR; - } - - /* FIXME: Sockets in FD_SETs should be sorted by their provider */ - - /* FIXME: For now, assume only one service provider */ - if ((readfds != NULL) && (readfds->fd_count > 0)) - { - if (!ReferenceProviderByHandle((HANDLE)readfds->fd_array[0], - &Provider)) - { - WSASetLastError(WSAENOTSOCK); - WS_DbgPrint(MID_TRACE,("No provider (read)\n")); - return SOCKET_ERROR; - } - } - else if ((writefds != NULL) && (writefds->fd_count > 0)) - { - if (!ReferenceProviderByHandle((HANDLE)writefds->fd_array[0], - &Provider)) - { - WSASetLastError(WSAENOTSOCK); - WS_DbgPrint(MID_TRACE,("No provider (write)\n")); - return SOCKET_ERROR; - } - } - else if ((exceptfds != NULL) && (exceptfds->fd_count > 0)) - { - if (!ReferenceProviderByHandle((HANDLE)exceptfds->fd_array[0], &Provider)) - { - WSASetLastError(WSAENOTSOCK); - WS_DbgPrint(MID_TRACE,("No provider (err)\n")); - return SOCKET_ERROR; - } -#if 0 /* XXX empty select is not an error */ - } - else - { - WSASetLastError(WSAEINVAL); - return SOCKET_ERROR; -#endif - } - - if ( !Provider ) - { - if ( timeout ) - { - WS_DbgPrint(MID_TRACE,("Select: used as timer\n")); - Sleep( timeout->tv_sec * 1000 + (timeout->tv_usec / 1000) ); - } - return 0; - } - else if (Provider->ProcTable.lpWSPSelect) - { - WS_DbgPrint(MID_TRACE,("Calling WSPSelect:%x\n", Provider->ProcTable.lpWSPSelect)); - Count = Provider->ProcTable.lpWSPSelect(nfds, - readfds, - writefds, - exceptfds, - (LPTIMEVAL)timeout, - &Errno); - - WS_DbgPrint(MAX_TRACE, ("[%x] Select: Count %d Errno %x\n", - Provider, Count, Errno)); - - DereferenceProviderByPointer(Provider); - - if (Errno != NO_ERROR) - { - WSASetLastError(Errno); - return SOCKET_ERROR; - } - } - else - { - WSASetLastError(WSAEINVAL); - return SOCKET_ERROR; - } - - return Count; -} - - -/* - * @implemented - */ -INT -EXPORT -bind(IN SOCKET s, - IN CONST struct sockaddr *name, - IN INT namelen) -{ - PCATALOG_ENTRY Provider; - INT Status; - INT Errno; - - if (!WSAINITIALIZED) - { - WSASetLastError(WSANOTINITIALISED); - return SOCKET_ERROR; - } - - if (!ReferenceProviderByHandle((HANDLE)s, - &Provider)) - { - WSASetLastError(WSAENOTSOCK); - return SOCKET_ERROR; - } - -#if (__W32API_MAJOR_VERSION < 2 || __W32API_MINOR_VERSION < 5) - Status = Provider->ProcTable.lpWSPBind(s, - (CONST LPSOCKADDR)name, - namelen, - &Errno); -#else - Status = Provider->ProcTable.lpWSPBind(s, - name, - namelen, - &Errno); -#endif /* __W32API_MAJOR_VERSION < 2 || __W32API_MINOR_VERSION < 5 */ - - DereferenceProviderByPointer(Provider); - - if (Status == SOCKET_ERROR) - WSASetLastError(Errno); - - return Status; -} - - -/* - * @implemented - */ -INT -EXPORT -listen(IN SOCKET s, - IN INT backlog) -{ - PCATALOG_ENTRY Provider; - INT Status; - INT Errno; - - if (!WSAINITIALIZED) - { - WSASetLastError(WSANOTINITIALISED); - return SOCKET_ERROR; - } - - if (!ReferenceProviderByHandle((HANDLE)s, - &Provider)) - { - WSASetLastError(WSAENOTSOCK); - return SOCKET_ERROR; - } - - Status = Provider->ProcTable.lpWSPListen(s, - backlog, - &Errno); - - DereferenceProviderByPointer(Provider); - - if (Status == SOCKET_ERROR) - WSASetLastError(Errno); - - return Status; -} - - -/* - * @implemented - */ -SOCKET -EXPORT -accept(IN SOCKET s, - OUT LPSOCKADDR addr, - OUT INT FAR* addrlen) -{ - return WSAAccept(s, - addr, - addrlen, - NULL, - 0); -} - - -/* - * @implemented - */ -INT -EXPORT -ioctlsocket(IN SOCKET s, - IN LONG cmd, - IN OUT ULONG FAR* argp) -{ - return WSAIoctl(s, - cmd, - argp, - sizeof(ULONG), - argp, - sizeof(ULONG), - argp, - 0, - 0); -} - - -/* - * @implemented - */ -SOCKET -EXPORT -WSAAccept(IN SOCKET s, - OUT LPSOCKADDR addr, - IN OUT LPINT addrlen, - IN LPCONDITIONPROC lpfnCondition, - IN DWORD dwCallbackData) -{ - PCATALOG_ENTRY Provider; - SOCKET Socket; - INT Errno; - - if (!WSAINITIALIZED) - { - WSASetLastError(WSANOTINITIALISED); - return SOCKET_ERROR; - } - - if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) - { - WSASetLastError(WSAENOTSOCK); - return SOCKET_ERROR; - } - - WS_DbgPrint(MAX_TRACE,("Calling provider accept\n")); - - Socket = Provider->ProcTable.lpWSPAccept(s, - addr, - addrlen, - lpfnCondition, - dwCallbackData, - &Errno); - - WS_DbgPrint(MAX_TRACE,("Calling provider accept -> Socket %x, Errno %x\n", - Socket, Errno)); - - DereferenceProviderByPointer(Provider); - - if (Socket == INVALID_SOCKET) - WSASetLastError(Errno); - - if ( addr ) - { -#if DBG - LPSOCKADDR_IN sa = (LPSOCKADDR_IN)addr; - WS_DbgPrint(MAX_TRACE,("Returned address: %d %s:%d (len %d)\n", - sa->sin_family, - inet_ntoa(sa->sin_addr), - ntohs(sa->sin_port), - *addrlen)); -#endif - } - - return Socket; -} - - -/* - * @implemented - */ -INT -EXPORT -connect(IN SOCKET s, - IN CONST struct sockaddr *name, - IN INT namelen) -{ - return WSAConnect(s, - name, - namelen, - NULL, - NULL, - NULL, - NULL); -} - - -/* - * @implemented - */ -INT -EXPORT -WSAConnect(IN SOCKET s, - IN CONST struct sockaddr *name, - IN INT namelen, - IN LPWSABUF lpCallerData, - OUT LPWSABUF lpCalleeData, - IN LPQOS lpSQOS, - IN LPQOS lpGQOS) -{ - PCATALOG_ENTRY Provider; - INT Status; - INT Errno; - - if (!WSAINITIALIZED) - { - WSASetLastError(WSANOTINITIALISED); - return SOCKET_ERROR; - } - - if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) - { - WSASetLastError(WSAENOTSOCK); - return SOCKET_ERROR; - } - -#if (__W32API_MAJOR_VERSION < 2 || __W32API_MINOR_VERSION < 5) - Status = Provider->ProcTable.lpWSPConnect(s, - (CONST LPSOCKADDR)name, - namelen, - lpCallerData, - lpCalleeData, - lpSQOS, - lpGQOS, - &Errno); -#else - Status = Provider->ProcTable.lpWSPConnect(s, - name, - namelen, - lpCallerData, - lpCalleeData, - lpSQOS, - lpGQOS, - &Errno); -#endif - - DereferenceProviderByPointer(Provider); - - if (Status == SOCKET_ERROR) - WSASetLastError(Errno); - - return Status; -} - - -/* - * @implemented - */ -INT -EXPORT -WSAIoctl(IN SOCKET s, - IN DWORD dwIoControlCode, - IN LPVOID lpvInBuffer, - IN DWORD cbInBuffer, - OUT LPVOID lpvOutBuffer, - IN DWORD cbOutBuffer, - OUT LPDWORD lpcbBytesReturned, - IN LPWSAOVERLAPPED lpOverlapped, - IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) -{ - PCATALOG_ENTRY Provider; - INT Status; - INT Errno; - - if (!WSAINITIALIZED) - { - WSASetLastError(WSANOTINITIALISED); - return SOCKET_ERROR; - } - - if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) - { - WSASetLastError(WSAENOTSOCK); - return SOCKET_ERROR; - } - - Status = Provider->ProcTable.lpWSPIoctl(s, - dwIoControlCode, - lpvInBuffer, - cbInBuffer, - lpvOutBuffer, - cbOutBuffer, - lpcbBytesReturned, - lpOverlapped, - lpCompletionRoutine, - NULL /* lpThreadId */, - &Errno); - - DereferenceProviderByPointer(Provider); - - if (Status == SOCKET_ERROR) - WSASetLastError(Errno); - - return Status; -} - -/* - * @implemented - */ -INT -EXPORT -__WSAFDIsSet(SOCKET s, LPFD_SET set) -{ - unsigned int i; - - for ( i = 0; i < set->fd_count; i++ ) - if ( set->fd_array[i] == s ) return TRUE; - - return FALSE; -} - -void free_winsock_thread_block(PWINSOCK_THREAD_BLOCK p) -{ - if (p) - { - if (p->Hostent) { free_hostent(p->Hostent); p->Hostent = 0; } - if (p->Getservbyname){} - if (p->Getservbyport) {} - } -} - -BOOL -WINAPI -DllMain(HANDLE hInstDll, - ULONG dwReason, - LPVOID lpReserved) -{ - PWINSOCK_THREAD_BLOCK p; - - WS_DbgPrint(MAX_TRACE, ("DllMain of ws2_32.dll.\n")); - - switch (dwReason) - { - case DLL_PROCESS_ATTACH: - { - GlobalHeap = GetProcessHeap(); - - g_hInstDll = hInstDll; - - CreateCatalog(); - - InitProviderHandleTable(); - - UpcallTable.lpWPUCloseEvent = WPUCloseEvent; - UpcallTable.lpWPUCloseSocketHandle = WPUCloseSocketHandle; - UpcallTable.lpWPUCreateEvent = WPUCreateEvent; - UpcallTable.lpWPUCreateSocketHandle = WPUCreateSocketHandle; - UpcallTable.lpWPUFDIsSet = WPUFDIsSet; - UpcallTable.lpWPUGetProviderPath = WPUGetProviderPath; - UpcallTable.lpWPUModifyIFSHandle = WPUModifyIFSHandle; - UpcallTable.lpWPUPostMessage = PostMessageW; - UpcallTable.lpWPUQueryBlockingCallback = WPUQueryBlockingCallback; - UpcallTable.lpWPUQuerySocketHandleContext = WPUQuerySocketHandleContext; - UpcallTable.lpWPUQueueApc = WPUQueueApc; - UpcallTable.lpWPUResetEvent = WPUResetEvent; - UpcallTable.lpWPUSetEvent = WPUSetEvent; - UpcallTable.lpWPUOpenCurrentThread = WPUOpenCurrentThread; - UpcallTable.lpWPUCloseThread = WPUCloseThread; - - /* Fall through to thread attachment handler */ - } - case DLL_THREAD_ATTACH: - { - p = HeapAlloc(GlobalHeap, 0, sizeof(WINSOCK_THREAD_BLOCK)); - - WS_DbgPrint(MAX_TRACE, ("Thread block at 0x%X.\n", p)); - - if (!p) { - return FALSE; - } - - p->Hostent = NULL; - p->LastErrorValue = NO_ERROR; - p->Getservbyname = NULL; - p->Getservbyport = NULL; - - NtCurrentTeb()->WinSockData = p; - } - break; - - case DLL_PROCESS_DETACH: - { - DestroyCatalog(); - - FreeProviderHandleTable(); - } - break; - - case DLL_THREAD_DETACH: - { - p = NtCurrentTeb()->WinSockData; - - if (p) - HeapFree(GlobalHeap, 0, p); - } - break; - } - - WS_DbgPrint(MAX_TRACE, ("DllMain of ws2_32.dll. Leaving.\n")); - - return TRUE; -} - -/* EOF */ diff --git a/dll/win32/ws2_32/misc/event.c b/dll/win32/ws2_32/misc/event.c deleted file mode 100644 index dcc541682d1..00000000000 --- a/dll/win32/ws2_32/misc/event.c +++ /dev/null @@ -1,244 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS WinSock 2 DLL - * FILE: misc/event.c - * PURPOSE: Event handling - * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) - * REVISIONS: - * CSH 01/09-2000 Created - */ -#include -#include - - -/* - * @implemented - */ -BOOL -EXPORT -WSACloseEvent(IN WSAEVENT hEvent) -{ - BOOL Success; - - if (!WSAINITIALIZED) - { - WSASetLastError(WSANOTINITIALISED); - return FALSE; - } - - Success = CloseHandle((HANDLE)hEvent); - - if (!Success) - WSASetLastError(WSA_INVALID_HANDLE); - - return Success; -} - - -/* - * @implemented - */ -WSAEVENT -EXPORT -WSACreateEvent(VOID) -{ - HANDLE Event; - - if (!WSAINITIALIZED) - { - WSASetLastError(WSANOTINITIALISED); - return FALSE; - } - - Event = CreateEventW(NULL, TRUE, FALSE, NULL); - - if (Event == INVALID_HANDLE_VALUE) - WSASetLastError(WSA_INVALID_HANDLE); - - return (WSAEVENT)Event; -} - - -/* - * @implemented - */ -BOOL -EXPORT -WSAResetEvent(IN WSAEVENT hEvent) -{ - BOOL Success; - - if (!WSAINITIALIZED) - { - WSASetLastError(WSANOTINITIALISED); - return FALSE; - } - - Success = ResetEvent((HANDLE)hEvent); - - if (!Success) - WSASetLastError(WSA_INVALID_HANDLE); - - return Success; -} - - -/* - * @implemented - */ -BOOL -EXPORT -WSASetEvent(IN WSAEVENT hEvent) -{ - BOOL Success; - - if (!WSAINITIALIZED) - { - WSASetLastError(WSANOTINITIALISED); - return FALSE; - } - - Success = SetEvent((HANDLE)hEvent); - - if (!Success) - WSASetLastError(WSA_INVALID_HANDLE); - - return Success; -} - - -/* - * @implemented - */ -DWORD -EXPORT -WSAWaitForMultipleEvents(IN DWORD cEvents, - IN CONST WSAEVENT FAR* lphEvents, - IN BOOL fWaitAll, - IN DWORD dwTimeout, - IN BOOL fAlertable) -{ - DWORD Status; - - if (!WSAINITIALIZED) - { - WSASetLastError(WSANOTINITIALISED); - return FALSE; - } - - Status = WaitForMultipleObjectsEx(cEvents, - lphEvents, - fWaitAll, - dwTimeout, - fAlertable); - if (Status == WAIT_FAILED) - { - Status = GetLastError(); - - if (Status == ERROR_NOT_ENOUGH_MEMORY) - WSASetLastError(WSA_NOT_ENOUGH_MEMORY); - else if (Status == ERROR_INVALID_HANDLE) - WSASetLastError(WSA_INVALID_HANDLE); - else - WSASetLastError(WSA_INVALID_PARAMETER); - - return WSA_WAIT_FAILED; - } - - return Status; -} - - -/* - * @implemented - */ -INT -EXPORT -WSAEnumNetworkEvents(IN SOCKET s, - IN WSAEVENT hEventObject, - OUT LPWSANETWORKEVENTS lpNetworkEvents) -{ - PCATALOG_ENTRY Provider; - INT Status; - INT Errno; - - WS_DbgPrint(MID_TRACE,("Called (Socket %x, hEventObject %x, " - "lpNetworkEvents %x)\n", - s, - hEventObject, - lpNetworkEvents)); - - if (!lpNetworkEvents) - { - WSASetLastError(WSAEINVAL); - return SOCKET_ERROR; - } - - if (!WSAINITIALIZED) - { - WSASetLastError(WSANOTINITIALISED); - return SOCKET_ERROR; - } - - if (!ReferenceProviderByHandle((HANDLE)s, - &Provider)) - { - WSASetLastError(WSAENOTSOCK); - return SOCKET_ERROR; - } - - Status = Provider->ProcTable.lpWSPEnumNetworkEvents(s, - hEventObject, - lpNetworkEvents, - &Errno); - - DereferenceProviderByPointer(Provider); - - if (Status == SOCKET_ERROR) - WSASetLastError(Errno); - - WS_DbgPrint(MID_TRACE,("Leaving %x\n", Status)); - - return Status; -} - - -/* - * @implemented - */ -INT -EXPORT -WSAEventSelect(IN SOCKET s, - IN WSAEVENT hEventObject, - IN LONG lNetworkEvents) -{ - PCATALOG_ENTRY Provider; - INT Status; - INT Errno; - - if (!WSAINITIALIZED) - { - WSASetLastError(WSANOTINITIALISED); - return SOCKET_ERROR; - } - - if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) - { - WSASetLastError(WSAENOTSOCK); - return SOCKET_ERROR; - } - - Status = Provider->ProcTable.lpWSPEventSelect(s, - hEventObject, - lNetworkEvents, - &Errno); - - DereferenceProviderByPointer(Provider); - - if (Status == SOCKET_ERROR) - WSASetLastError(Errno); - - return Status; -} - -/* EOF */ diff --git a/dll/win32/ws2_32/misc/handle.c b/dll/win32/ws2_32/misc/handle.c deleted file mode 100644 index d5b54e3fb28..00000000000 --- a/dll/win32/ws2_32/misc/handle.c +++ /dev/null @@ -1,297 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS WinSock 2 DLL - * FILE: misc/handle.c - * PURPOSE: Provider handle management - * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) - * REVISIONS: - * CSH 01/09-2000 Created - */ -#include -#include -#include - -PPROVIDER_HANDLE_BLOCK ProviderHandleTable; -CRITICAL_SECTION ProviderHandleTableLock; - -PPROVIDER_HANDLE -GetProviderByHandle(PPROVIDER_HANDLE_BLOCK HandleTable, - HANDLE Handle) -/* - * FUNCTION: Get the data structure for a handle - * ARGUMENTS: - * HandleTable = Pointer to handle table - * Handle = Handle to get data structure for - * RETURNS: - * Pointer to the data structure identified by the handle on success, - * NULL on failure - */ -{ - PPROVIDER_HANDLE_BLOCK Current; - PLIST_ENTRY CurrentEntry; - ULONG i; - - WS_DbgPrint(MAX_TRACE, ("HandleTable (0x%X) Handle (0x%X).\n", HandleTable, Handle)); - - CurrentEntry = HandleTable->Entry.Flink; - - while (CurrentEntry != &HandleTable->Entry) - { - Current = CONTAINING_RECORD(CurrentEntry, PROVIDER_HANDLE_BLOCK, Entry); - - for (i = 0; i < HANDLE_BLOCK_ENTRIES; i++) - { - if ((Current->Handles[i].Provider != NULL) && - (Current->Handles[i].Handle == Handle)) - { - return &Current->Handles[i]; - } - } - CurrentEntry = CurrentEntry->Flink; - } - - return NULL; -} - - -VOID -CloseAllHandles(PPROVIDER_HANDLE_BLOCK HandleTable) -{ - PPROVIDER_HANDLE_BLOCK Current; - PLIST_ENTRY CurrentEntry; - PCATALOG_ENTRY Provider; - ULONG i; - - WS_DbgPrint(MAX_TRACE, ("HandleTable (0x%X).\n", HandleTable)); - - CurrentEntry = HandleTable->Entry.Flink; - - while (CurrentEntry != &HandleTable->Entry) - { - Current = CONTAINING_RECORD(CurrentEntry, PROVIDER_HANDLE_BLOCK, Entry); - - for (i = 0; i < HANDLE_BLOCK_ENTRIES; i++) - { - Provider = Current->Handles[i].Provider; - if (Provider != NULL) - { - DereferenceProviderByPointer(Provider); - Current->Handles[i].Handle = (HANDLE)0; - Current->Handles[i].Provider = NULL; - } - } - CurrentEntry = CurrentEntry->Flink; - } -} - - -VOID -DeleteHandleTable(PPROVIDER_HANDLE_BLOCK HandleTable) -{ - PPROVIDER_HANDLE_BLOCK Current; - PLIST_ENTRY CurrentEntry; - - CloseAllHandles(HandleTable); - - CurrentEntry = RemoveHeadList(&HandleTable->Entry); - - while (CurrentEntry != &HandleTable->Entry) - { - Current = CONTAINING_RECORD(CurrentEntry, - PROVIDER_HANDLE_BLOCK, - Entry); - - HeapFree(GlobalHeap, 0, Current); - - CurrentEntry = RemoveHeadList(&HandleTable->Entry); - } -} - - -PCATALOG_ENTRY -DeleteProviderHandle(PPROVIDER_HANDLE_BLOCK HandleTable, - HANDLE Handle) -{ - PPROVIDER_HANDLE Entry; - PCATALOG_ENTRY Provider; - - WS_DbgPrint(MAX_TRACE, ("HandleTable (0x%X) Handle (0x%X).\n", HandleTable, Handle)); - - Entry = GetProviderByHandle(HandleTable, Handle); - if (!Entry) - return NULL; - - Provider = Entry->Provider; - Entry->Handle = (HANDLE)0; - Entry->Provider = NULL; - - return Provider; -} - - -HANDLE -CreateProviderHandleTable(PPROVIDER_HANDLE_BLOCK HandleTable, - HANDLE Handle, - PCATALOG_ENTRY Provider) -{ - PPROVIDER_HANDLE_BLOCK NewBlock; - PLIST_ENTRY CurrentEntry; - ULONG i; - - WS_DbgPrint(MAX_TRACE, ("HandleTable (0x%X) Handle (0x%X) Provider (0x%X).\n", - HandleTable, Handle, Provider)); - - /* Scan through the currently allocated handle blocks looking for a free slot */ - CurrentEntry = HandleTable->Entry.Flink; - while (CurrentEntry != &HandleTable->Entry) - { - PPROVIDER_HANDLE_BLOCK Block = CONTAINING_RECORD(CurrentEntry, - PROVIDER_HANDLE_BLOCK, - Entry); - - for (i = 0; i < HANDLE_BLOCK_ENTRIES; i++) - { - WS_DbgPrint(MAX_TRACE, ("Considering slot %ld containing 0x%X.\n", - i, - Block->Handles[i].Provider)); - if (Block->Handles[i].Provider == NULL) - { - Block->Handles[i].Handle = Handle; - Block->Handles[i].Provider = Provider; - return Handle; - } - } - CurrentEntry = CurrentEntry->Flink; - } - - /* Add a new handle block to the end of the list */ - NewBlock = (PPROVIDER_HANDLE_BLOCK)HeapAlloc(GlobalHeap, - 0, - sizeof(PROVIDER_HANDLE_BLOCK)); - - WS_DbgPrint(MID_TRACE,("using table entry %x\n", NewBlock)); - - if (!NewBlock) - return (HANDLE)0; - - ZeroMemory(NewBlock, sizeof(PROVIDER_HANDLE_BLOCK)); - InsertTailList(&HandleTable->Entry, - &NewBlock->Entry); - - NewBlock->Handles[0].Handle = Handle; - NewBlock->Handles[0].Provider = Provider; - - return Handle; -} - - -HANDLE -CreateProviderHandle(HANDLE Handle, - PCATALOG_ENTRY Provider) -{ - HANDLE h; - - EnterCriticalSection(&ProviderHandleTableLock); - - h = CreateProviderHandleTable(ProviderHandleTable, - Handle, - Provider); - - LeaveCriticalSection(&ProviderHandleTableLock); - - if (h != NULL) - ReferenceProviderByPointer(Provider); - - return h; -} - - -BOOL -ReferenceProviderByHandle(HANDLE Handle, - PCATALOG_ENTRY* Provider) -/* - * FUNCTION: Increments the reference count for a provider and returns a pointer to it - * ARGUMENTS: - * Handle = Handle for the provider - * Provider = Address of buffer to place pointer to provider - * RETURNS: - * TRUE if handle was valid, FALSE if not - */ -{ - PPROVIDER_HANDLE ProviderHandle; - - WS_DbgPrint(MID_TRACE, ("Handle (0x%X) Provider (0x%X).\n", Handle, Provider)); - - EnterCriticalSection(&ProviderHandleTableLock); - - ProviderHandle = GetProviderByHandle(ProviderHandleTable, - Handle); - - WS_DbgPrint(MID_TRACE, ("ProviderHandle is %x\n", ProviderHandle)); - - LeaveCriticalSection(&ProviderHandleTableLock); - - if (ProviderHandle) - { - ReferenceProviderByPointer(ProviderHandle->Provider); - *Provider = ProviderHandle->Provider; - } - - return (ProviderHandle != NULL); -} - - -BOOL -CloseProviderHandle(HANDLE Handle) -{ - PCATALOG_ENTRY Provider; - - WS_DbgPrint(MAX_TRACE, ("Handle (0x%X).\n", Handle)); - - EnterCriticalSection(&ProviderHandleTableLock); - - Provider = DeleteProviderHandle(ProviderHandleTable, - Handle); - if (!Provider) - return FALSE; - - LeaveCriticalSection(&ProviderHandleTableLock); - - DereferenceProviderByPointer(Provider); - - return TRUE; -} - - -BOOL -InitProviderHandleTable(VOID) -{ - ProviderHandleTable = - (PPROVIDER_HANDLE_BLOCK)HeapAlloc(GlobalHeap, - 0, - sizeof(PROVIDER_HANDLE_BLOCK)); - if (!ProviderHandleTable) - return FALSE; - - WS_DbgPrint(MID_TRACE,("Called\n")); - - ZeroMemory(ProviderHandleTable, - sizeof(PROVIDER_HANDLE_BLOCK)); - - InitializeListHead(&ProviderHandleTable->Entry); - - InitializeCriticalSection(&ProviderHandleTableLock); - - return TRUE; -} - - -VOID -FreeProviderHandleTable(VOID) -{ - DeleteHandleTable(ProviderHandleTable); - - DeleteCriticalSection(&ProviderHandleTableLock); -} - -/* EOF */ diff --git a/dll/win32/ws2_32/misc/ns.c b/dll/win32/ws2_32/misc/ns.c deleted file mode 100644 index bb89eadfb0d..00000000000 --- a/dll/win32/ws2_32/misc/ns.c +++ /dev/null @@ -1,1547 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS WinSock 2 DLL - * FILE: misc/ns.c - * PURPOSE: Namespace APIs - * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) - * REVISIONS: - * CSH 01/09-2000 Created - */ -#include -#include -#include - -#ifndef BUFSIZ -#define BUFSIZ 1024 -#endif/*BUFSIZ*/ - -#ifndef MAX_HOSTNAME_LEN -#define MAX_HOSTNAME_LEN 256 -#endif - -/* Name resolution APIs */ - -/* - * @unimplemented - */ -INT -EXPORT -WSAAddressToStringA(IN LPSOCKADDR lpsaAddress, - IN DWORD dwAddressLength, - IN LPWSAPROTOCOL_INFOA lpProtocolInfo, - OUT LPSTR lpszAddressString, - IN OUT LPDWORD lpdwAddressStringLength) -{ - UNIMPLEMENTED - - WSASetLastError(WSASYSCALLFAILURE); - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -INT -EXPORT -WSAAddressToStringW(IN LPSOCKADDR lpsaAddress, - IN DWORD dwAddressLength, - IN LPWSAPROTOCOL_INFOW lpProtocolInfo, - OUT LPWSTR lpszAddressString, - IN OUT LPDWORD lpdwAddressStringLength) -{ - UNIMPLEMENTED - - WSASetLastError(WSASYSCALLFAILURE); - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -INT -EXPORT -WSAEnumNameSpaceProvidersA(IN OUT LPDWORD lpdwBufferLength, - OUT LPWSANAMESPACE_INFOA lpnspBuffer) -{ - UNIMPLEMENTED - - WSASetLastError(WSASYSCALLFAILURE); - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -INT -EXPORT -WSAEnumNameSpaceProvidersW(IN OUT LPDWORD lpdwBufferLength, - OUT LPWSANAMESPACE_INFOW lpnspBuffer) -{ - UNIMPLEMENTED - - WSASetLastError(WSASYSCALLFAILURE); - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -INT -EXPORT -WSAGetServiceClassInfoA(IN LPGUID lpProviderId, - IN LPGUID lpServiceClassId, - IN OUT LPDWORD lpdwBufferLength, - OUT LPWSASERVICECLASSINFOA lpServiceClassInfo) -{ - UNIMPLEMENTED - - WSASetLastError(WSASYSCALLFAILURE); - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -INT -EXPORT -WSAGetServiceClassInfoW(IN LPGUID lpProviderId, - IN LPGUID lpServiceClassId, - IN OUT LPDWORD lpdwBufferLength, - OUT LPWSASERVICECLASSINFOW lpServiceClassInfo) -{ - UNIMPLEMENTED - - WSASetLastError(WSASYSCALLFAILURE); - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -INT -EXPORT -WSAGetServiceClassNameByClassIdA(IN LPGUID lpServiceClassId, - OUT LPSTR lpszServiceClassName, - IN OUT LPDWORD lpdwBufferLength) -{ - UNIMPLEMENTED - - WSASetLastError(WSASYSCALLFAILURE); - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -INT -EXPORT -WSAGetServiceClassNameByClassIdW(IN LPGUID lpServiceClassId, - OUT LPWSTR lpszServiceClassName, - IN OUT LPDWORD lpdwBufferLength) -{ - UNIMPLEMENTED - - WSASetLastError(WSASYSCALLFAILURE); - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -INT -EXPORT -WSAInstallServiceClassA(IN LPWSASERVICECLASSINFOA lpServiceClassInfo) -{ - UNIMPLEMENTED - - WSASetLastError(WSASYSCALLFAILURE); - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -INT -EXPORT -WSAInstallServiceClassW(IN LPWSASERVICECLASSINFOW lpServiceClassInfo) -{ - UNIMPLEMENTED - - WSASetLastError(WSASYSCALLFAILURE); - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -INT -EXPORT -WSALookupServiceBeginA(IN LPWSAQUERYSETA lpqsRestrictions, - IN DWORD dwControlFlags, - OUT LPHANDLE lphLookup) -{ - UNIMPLEMENTED - - WSASetLastError(WSASYSCALLFAILURE); - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -INT -EXPORT -WSALookupServiceBeginW(IN LPWSAQUERYSETW lpqsRestrictions, - IN DWORD dwControlFlags, - OUT LPHANDLE lphLookup) -{ - UNIMPLEMENTED - - WSASetLastError(WSASYSCALLFAILURE); - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -INT -EXPORT -WSALookupServiceEnd(IN HANDLE hLookup) -{ - UNIMPLEMENTED - - WSASetLastError(WSASYSCALLFAILURE); - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -INT -EXPORT -WSALookupServiceNextA(IN HANDLE hLookup, - IN DWORD dwControlFlags, - IN OUT LPDWORD lpdwBufferLength, - OUT LPWSAQUERYSETA lpqsResults) -{ - UNIMPLEMENTED - - WSASetLastError(WSASYSCALLFAILURE); - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -INT -EXPORT -WSALookupServiceNextW(IN HANDLE hLookup, - IN DWORD dwControlFlags, - IN OUT LPDWORD lpdwBufferLength, - OUT LPWSAQUERYSETW lpqsResults) -{ - UNIMPLEMENTED - - WSASetLastError(WSASYSCALLFAILURE); - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -INT -EXPORT -WSARemoveServiceClass(IN LPGUID lpServiceClassId) -{ - UNIMPLEMENTED - - WSASetLastError(WSASYSCALLFAILURE); - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -INT -EXPORT -WSASetServiceA(IN LPWSAQUERYSETA lpqsRegInfo, - IN WSAESETSERVICEOP essOperation, - IN DWORD dwControlFlags) -{ - UNIMPLEMENTED - - WSASetLastError(WSASYSCALLFAILURE); - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -INT -EXPORT -WSASetServiceW(IN LPWSAQUERYSETW lpqsRegInfo, - IN WSAESETSERVICEOP essOperation, - IN DWORD dwControlFlags) -{ - UNIMPLEMENTED - - WSASetLastError(WSASYSCALLFAILURE); - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -INT -EXPORT -WSAStringToAddressA(IN LPSTR AddressString, - IN INT AddressFamily, - IN LPWSAPROTOCOL_INFOA lpProtocolInfo, - OUT LPSOCKADDR lpAddress, - IN OUT LPINT lpAddressLength) -{ - INT ret, len; - LPWSTR szTemp; - LPWSAPROTOCOL_INFOW lpProtoInfoW = NULL; - - len = MultiByteToWideChar(CP_ACP, - 0, - AddressString, - -1, - NULL, - 0); - - szTemp = HeapAlloc(GetProcessHeap(), - 0, - len * sizeof(WCHAR)); - - MultiByteToWideChar(CP_ACP, - 0, - AddressString, - -1, - szTemp, - len); - - if (lpProtocolInfo) - { - len = WSAPROTOCOL_LEN+1; - lpProtoInfoW = HeapAlloc(GetProcessHeap(), - 0, - len * sizeof(WCHAR) ); - - memcpy(lpProtoInfoW, - lpProtocolInfo, - sizeof(LPWSAPROTOCOL_INFOA)); - - MultiByteToWideChar(CP_ACP, - 0, - lpProtocolInfo->szProtocol, - -1, - lpProtoInfoW->szProtocol, - len); - } - - ret = WSAStringToAddressW(szTemp, - AddressFamily, - lpProtoInfoW, - lpAddress, - lpAddressLength); - - HeapFree(GetProcessHeap(), - 0, - szTemp ); - - if (lpProtocolInfo) - HeapFree(GetProcessHeap(), - 0, - lpProtoInfoW); - - WSASetLastError(ret); - return ret; -} - - - -/* - * @implemented - */ -INT -EXPORT -WSAStringToAddressW(IN LPWSTR AddressString, - IN INT AddressFamily, - IN LPWSAPROTOCOL_INFOW lpProtocolInfo, - OUT LPSOCKADDR lpAddress, - IN OUT LPINT lpAddressLength) -{ - int pos=0; - int res=0; - LONG inetaddr = 0; - LPWSTR *bp=NULL; - SOCKADDR_IN *sockaddr; - - if (!lpAddressLength || !lpAddress || !AddressString) - { - WSASetLastError(WSAEINVAL); - return SOCKET_ERROR; - } - - sockaddr = (SOCKADDR_IN *) lpAddress; - - /* Set right adress family */ - if (lpProtocolInfo!=NULL) - sockaddr->sin_family = lpProtocolInfo->iAddressFamily; - - else sockaddr->sin_family = AddressFamily; - - /* Report size */ - if (AddressFamily == AF_INET) - { - if (*lpAddressLength < (INT)sizeof(SOCKADDR_IN)) - { - *lpAddressLength = sizeof(SOCKADDR_IN); - res = WSAEFAULT; - } - else - { - // translate ip string to ip - - /* rest sockaddr.sin_addr.s_addr - for we need to be sure it is zero when we come to while */ - memset(lpAddress,0,sizeof(SOCKADDR_IN)); - - /* Set right adress family */ - sockaddr->sin_family = AF_INET; - - /* Get port number */ - pos = wcscspn(AddressString,L":") + 1; - - if (pos < (int)wcslen(AddressString)) - sockaddr->sin_port = wcstol(&AddressString[pos], - bp, - 10); - - else - sockaddr->sin_port = 0; - - /* Get ip number */ - pos=0; - inetaddr=0; - - while (pos < (int)wcslen(AddressString)) - { - inetaddr = (inetaddr<<8) + ((UCHAR)wcstol(&AddressString[pos], - bp, - 10)); - pos += wcscspn( &AddressString[pos],L".") +1 ; - } - - res = 0; - sockaddr->sin_addr.s_addr = inetaddr; - - } - } - - WSASetLastError(res); - if (!res) return 0; - return SOCKET_ERROR; -} - -void check_hostent(struct hostent **he) -{ - struct hostent *new_he; - - WS_DbgPrint(MID_TRACE,("*he: %x\n",*he)); - - if(!*he) - { - new_he = HeapAlloc(GlobalHeap, - 0, - sizeof(struct hostent) + MAX_HOSTNAME_LEN + 1); - - new_he->h_name = (PCHAR)(new_he + 1); - new_he->h_aliases = 0; - new_he->h_addrtype = 0; // AF_INET - new_he->h_length = 0; // sizeof(in_addr) - new_he->h_addr_list = HeapAlloc(GlobalHeap, - 0, - sizeof(char *) * 2); - - RtlZeroMemory(new_he->h_addr_list, - sizeof(char *) * 2); - *he = new_he; - } -} - -void populate_hostent(struct hostent *he, char* name, DNS_A_DATA addr) -{ - ASSERT(he); - - //he = HeapAlloc(GlobalHeap, 0, sizeof(struct hostent)); - //he->h_name = HeapAlloc(GlobalHeap, 0, MAX_HOSTNAME_LEN+1); - - strncpy(he->h_name, - name, - MAX_HOSTNAME_LEN); - - if( !he->h_aliases ) { - he->h_aliases = HeapAlloc(GlobalHeap, 0, sizeof(char *)); - he->h_aliases[0] = 0; - } - he->h_addrtype = AF_INET; - he->h_length = sizeof(IN_ADDR); //sizeof(struct in_addr); - - if( he->h_addr_list[0] ) - { - HeapFree(GlobalHeap, - 0, - he->h_addr_list[0]); - } - - he->h_addr_list[0] = HeapAlloc(GlobalHeap, - 0, - MAX_HOSTNAME_LEN + 1); - - WS_DbgPrint(MID_TRACE,("he->h_addr_list[0] %x\n", he->h_addr_list[0])); - - RtlCopyMemory(he->h_addr_list[0], - (char*)&addr.IpAddress, - sizeof(addr.IpAddress)); - - he->h_addr_list[1] = 0; -} - - -#define HFREE(x) if(x) { HeapFree(GlobalHeap, 0, (x)); x=0; } -void free_hostent(struct hostent *he) -{ - if(he) - { - char *next = 0; - HFREE(he->h_name); - if(he->h_aliases) - { - next = he->h_aliases[0]; - while(next) { HFREE(next); next++; } - } - if(he->h_addr_list) - { - next = he->h_addr_list[0]; - while(next) { HFREE(next); next++; } - } - HFREE(he->h_addr_list); - HFREE(he->h_aliases); - HFREE(he); - } -} - -/* WinSock 1.1 compatible name resolution APIs */ - -/* - * @unimplemented - */ -LPHOSTENT -EXPORT -gethostbyaddr(IN CONST CHAR FAR* addr, - IN INT len, - IN INT type) -{ - UNIMPLEMENTED - - return (LPHOSTENT)NULL; -} - -/* - Assumes rfc 1123 - adam * - addr[1] = 0; - addr[0] = inet_addr(name); - strcpy( hostname, name ); - if(addr[0] == 0xffffffff) return NULL; - he.h_addr_list = (void *)addr; - he.h_name = hostname; - he.h_aliases = NULL; - he.h_addrtype = AF_INET; - he.h_length = sizeof(addr); - return &he; - - -From the MSDN Platform SDK: Windows Sockets 2 -"The gethostbyname function cannot resolve IP address strings passed to it. -Such a request is treated exactly as if an unknown host name were passed." - - -Defferring to the the documented behaviour, rather than the unix behaviour -What if the hostname is in the HOSTS file? see getservbyname - - * @implemented - */ - -/* DnsQuery -- lib/dnsapi/dnsapi/query.c */ - /* see ws2_32.h, winsock2.h*/ - /*getnetworkparameters - iphlp api */ -/* -REFERENCES - -servent -- w32api/include/winsock2.h -PWINSOCK_THREAD_BLOCK -- ws2_32.h -dllmain.c -- threadlocal memory allocation / deallocation -lib/dnsapi - - -*/ - /* lib/adns/src/adns.h XXX */ - - -/* -struct hostent { - char *h_name; - char **h_aliases; - short h_addrtype; - short h_length; - char **h_addr_list; -#define h_addr h_addr_list[0] -}; -struct servent { - char *s_name; - char **s_aliases; - short s_port; - char *s_proto; -}; - - -struct hostent defined in w32api/include/winsock2.h -*/ - -void free_servent(struct servent* s) -{ - char* next; - HFREE(s->s_name); - next = s->s_aliases[0]; - while(next) { HFREE(next); next++; } - s->s_port = 0; - HFREE(s->s_proto); - HFREE(s); -} - - - -LPHOSTENT -EXPORT -gethostbyname(IN CONST CHAR FAR* name) -{ - enum addr_type - { - GH_INVALID, - GH_IPV6, - GH_IPV4, - GH_RFC1123_DNS - }; - typedef enum addr_type addr_type; - addr_type addr; - int ret = 0; - char* found = 0; - DNS_STATUS dns_status = {0}; - /* include/WinDNS.h -- look up DNS_RECORD on MSDN */ - PDNS_RECORD dp = 0; - PWINSOCK_THREAD_BLOCK p; - - addr = GH_INVALID; - - p = NtCurrentTeb()->WinSockData; - - if( !p ) - { - WSASetLastError( WSANOTINITIALISED ); - return NULL; - } - - check_hostent(&p->Hostent); /*XXX alloc_hostent*/ - - /* Hostname NULL - behave like gethostname */ - if(name == NULL) - { - ret = gethostname(p->Hostent->h_name, MAX_HOSTNAME_LEN); - return p->Hostent; - } - - if(ret) - { - WSASetLastError( WSAHOST_NOT_FOUND ); //WSANO_DATA ?? - return NULL; - } - - /* Is it an IPv6 address? */ - found = strstr(name, ":"); - if( found != NULL ) - { - addr = GH_IPV6; - goto act; - } - - /* Is it an IPv4 address? */ - if (!isalpha(name[0])) - { - addr = GH_IPV4; - goto act; - } - - addr = GH_RFC1123_DNS; - - /* Broken out in case we want to get fancy later */ - act: - switch(addr) - { - case GH_IPV6: - WSASetLastError(STATUS_NOT_IMPLEMENTED); - return NULL; - break; - - case GH_INVALID: - WSASetLastError(WSAEFAULT); - return NULL; - break; - - /* Note: If passed an IP address, MSDN says that gethostbyname() - treats it as an unknown host. - This is different from the unix implementation. Use inet_addr() - */ - case GH_IPV4: - case GH_RFC1123_DNS: - /* DNS_TYPE_A: include/WinDNS.h */ - /* DnsQuery -- lib/dnsapi/dnsapi/query.c */ - dns_status = DnsQuery_A(name, - DNS_TYPE_A, - DNS_QUERY_STANDARD, - 0, - /* extra dns servers */ &dp, - 0); - - if(dns_status == 0) - { - //ASSERT(dp->wType == DNS_TYPE_A); - //ASSERT(dp->wDataLength == sizeof(DNS_A_DATA)); - PDNS_RECORD curr; - for(curr=dp; - curr != NULL && curr->wType != DNS_TYPE_A; - curr = curr->pNext ) - { - WS_DbgPrint(MID_TRACE,("wType: %i\n", curr->wType)); - /*empty */ - } - - if(curr) - { - WS_DbgPrint(MID_TRACE,("populating hostent\n")); - WS_DbgPrint(MID_TRACE,("pName is (%s)\n", curr->pName)); - populate_hostent(p->Hostent, (PCHAR)curr->pName, curr->Data.A); - DnsRecordListFree(dp, DnsFreeRecordList); - return p->Hostent; - } - else - { - DnsRecordListFree(dp, DnsFreeRecordList); - } - } - - WS_DbgPrint(MID_TRACE,("Called DnsQuery, but host not found. Err: %i\n", - dns_status)); - WSASetLastError(WSAHOST_NOT_FOUND); - return NULL; - - break; - - default: - WSASetLastError(WSANO_RECOVERY); - return NULL; - break; - } - - WSASetLastError(WSANO_RECOVERY); - return NULL; -} - -/* - * @implemented - */ -INT -EXPORT -gethostname(OUT CHAR FAR* name, - IN INT namelen) -{ - DWORD size = namelen; - - int ret = GetComputerNameExA(ComputerNameDnsHostname, - name, - &size); - if(ret == 0) - { - WSASetLastError(WSAEFAULT); - return SOCKET_ERROR; - } - else - { - name[namelen-1] = '\0'; - return 0; - } -} - - -/* - * XXX arty -- Partial implementation pending a better one. This one will - * do for normal purposes.#include - * - * Return the address of a static LPPROTOENT corresponding to the named - * protocol. These structs aren't very interesting, so I'm not too ashamed - * to have this function work on builtins for now. - * - * @unimplemented - */ - -static CHAR *no_aliases = 0; -static PROTOENT protocols[] = -{ - {"icmp",&no_aliases, IPPROTO_ICMP}, - {"tcp", &no_aliases, IPPROTO_TCP}, - {"udp", &no_aliases, IPPROTO_UDP}, - {NULL, NULL, 0} -}; - -LPPROTOENT -EXPORT -getprotobyname(IN CONST CHAR FAR* name) -{ - UINT i; - for (i = 0; protocols[i].p_name; i++) - { - if (_stricmp(protocols[i].p_name, name) == 0) - return &protocols[i]; - } - return NULL; -} - -/* - * @unimplemented - */ -LPPROTOENT -EXPORT -getprotobynumber(IN INT number) -{ - UINT i; - for (i = 0; protocols[i].p_name; i++) - { - if (protocols[i].p_proto == number) - return &protocols[i]; - } - return NULL; -} - -#define SKIPWS(ptr,act) \ -{while(*ptr && isspace(*ptr)) ptr++; if(!*ptr) act;} -#define SKIPANDMARKSTR(ptr,act) \ -{while(*ptr && !isspace(*ptr)) ptr++; \ - if(!*ptr) {act;} else { *ptr = 0; ptr++; }} - - -static BOOL -DecodeServEntFromString(IN PCHAR ServiceString, - OUT PCHAR *ServiceName, - OUT PCHAR *PortNumberStr, - OUT PCHAR *ProtocolStr, - IN PCHAR *Aliases, - IN DWORD MaxAlias) -{ - UINT NAliases = 0; - - WS_DbgPrint(MAX_TRACE, ("Parsing service ent [%s]\n", ServiceString)); - - SKIPWS(ServiceString, return FALSE); - *ServiceName = ServiceString; - SKIPANDMARKSTR(ServiceString, return FALSE); - SKIPWS(ServiceString, return FALSE); - *PortNumberStr = ServiceString; - SKIPANDMARKSTR(ServiceString, ;); - - while( *ServiceString && NAliases < MaxAlias - 1 ) - { - SKIPWS(ServiceString, break); - if( *ServiceString ) - { - SKIPANDMARKSTR(ServiceString, ;); - if( strlen(ServiceString) ) - { - WS_DbgPrint(MAX_TRACE, ("Alias: %s\n", ServiceString)); - *Aliases++ = ServiceString; - NAliases++; - } - } - } - *Aliases = NULL; - - *ProtocolStr = strchr(*PortNumberStr,'/'); - if( !*ProtocolStr ) return FALSE; - **ProtocolStr = 0; (*ProtocolStr)++; - - WS_DbgPrint(MAX_TRACE, ("Parsing done: %s %s %s %d\n", - *ServiceName, *ProtocolStr, *PortNumberStr, - NAliases)); - - return TRUE; -} - -#define ADJ_PTR(p,b1,b2) p = (p - b1) + b2 - -/* - * @implemented - */ -LPSERVENT -EXPORT -getservbyname(IN CONST CHAR FAR* name, - IN CONST CHAR FAR* proto) -{ - BOOL Found = FALSE; - HANDLE ServicesFile; - CHAR ServiceDBData[BUFSIZ] = { 0 }; - PCHAR SystemDirectory = ServiceDBData; /* Reuse this stack space */ - PCHAR ServicesFileLocation = "\\drivers\\etc\\services"; - PCHAR ThisLine = 0, NextLine = 0, ServiceName = 0, PortNumberStr = 0, - ProtocolStr = 0, Comment = 0; - PCHAR Aliases[WS2_INTERNAL_MAX_ALIAS] = { 0 }; - UINT i,SizeNeeded = 0, - SystemDirSize = sizeof(ServiceDBData) - 1; - DWORD ReadSize = 0, ValidData = 0; - PWINSOCK_THREAD_BLOCK p = NtCurrentTeb()->WinSockData; - - if( !p ) - { - WSASetLastError( WSANOTINITIALISED ); - return NULL; - } - - if( !name ) - { - WSASetLastError( WSANO_RECOVERY ); - return NULL; - } - - if( !GetSystemDirectoryA( SystemDirectory, SystemDirSize ) ) - { - WSASetLastError( WSANO_RECOVERY ); - WS_DbgPrint(MIN_TRACE, ("Could not get windows system directory.\n")); - return NULL; /* Can't get system directory */ - } - - strncat(SystemDirectory, - ServicesFileLocation, - SystemDirSize ); - - ServicesFile = CreateFileA(SystemDirectory, - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, - NULL ); - - if( ServicesFile == INVALID_HANDLE_VALUE ) - { - WSASetLastError( WSANO_RECOVERY ); - return NULL; - } - - /* Scan the services file ... - * - * We will read up to BUFSIZ bytes per pass, until the buffer does not - * contain a full line, then we will try to read more. - * - * We fall from the loop if the buffer does not have a line terminator. - */ - - /* Initial Read */ - while(!Found && - ReadFile(ServicesFile, - ServiceDBData + ValidData, - sizeof( ServiceDBData ) - ValidData, - &ReadSize, - NULL)) - { - ValidData += ReadSize; - ReadSize = 0; - NextLine = ThisLine = ServiceDBData; - - /* Find the beginning of the next line */ - while(NextLine < ServiceDBData + ValidData && - *NextLine != '\r' && *NextLine != '\n' ) - { - NextLine++; - } - - /* Zero and skip, so we can treat what we have as a string */ - if( NextLine >= ServiceDBData + ValidData ) - break; - - *NextLine = 0; NextLine++; - - Comment = strchr( ThisLine, '#' ); - if( Comment ) *Comment = 0; /* Terminate at comment start */ - - if(DecodeServEntFromString(ThisLine, - &ServiceName, - &PortNumberStr, - &ProtocolStr, - Aliases, - WS2_INTERNAL_MAX_ALIAS) && - !strcmp( ServiceName, name ) && - (proto ? !strcmp( ProtocolStr, proto ) : TRUE) ) - { - - WS_DbgPrint(MAX_TRACE,("Found the service entry.\n")); - Found = TRUE; - SizeNeeded = sizeof(WINSOCK_GETSERVBYNAME_CACHE) + - (NextLine - ThisLine); - break; - } - - /* Get rid of everything we read so far */ - while( NextLine <= ServiceDBData + ValidData && - isspace( *NextLine ) ) - { - NextLine++; - } - - WS_DbgPrint(MAX_TRACE,("About to move %d chars\n", - ServiceDBData + ValidData - NextLine)); - - memmove(ServiceDBData, - NextLine, - ServiceDBData + ValidData - NextLine ); - ValidData -= NextLine - ServiceDBData; - WS_DbgPrint(MAX_TRACE,("Valid bytes: %d\n", ValidData)); - } - - /* This we'll do no matter what */ - CloseHandle( ServicesFile ); - - if( !Found ) - { - WS_DbgPrint(MAX_TRACE,("Not found\n")); - WSASetLastError( WSANO_DATA ); - return NULL; - } - - if( !p->Getservbyname || p->Getservbyname->Size < SizeNeeded ) - { - /* Free previous getservbyname buffer, allocate bigger */ - if( p->Getservbyname ) - HeapFree(GlobalHeap, 0, p->Getservbyname); - p->Getservbyname = HeapAlloc(GlobalHeap, 0, SizeNeeded); - if( !p->Getservbyname ) - { - WS_DbgPrint(MIN_TRACE,("Couldn't allocate %d bytes\n", - SizeNeeded)); - WSASetLastError( WSATRY_AGAIN ); - return NULL; - } - p->Getservbyname->Size = SizeNeeded; - } - - /* Copy the data */ - memmove(p->Getservbyname->Data, - ThisLine, - NextLine - ThisLine ); - - ADJ_PTR(ServiceName,ThisLine,p->Getservbyname->Data); - ADJ_PTR(ProtocolStr,ThisLine,p->Getservbyname->Data); - WS_DbgPrint(MAX_TRACE, ("ServiceName: %s, Protocol: %s\n", - ServiceName, - ProtocolStr)); - - for( i = 0; Aliases[i]; i++ ) - { - ADJ_PTR(Aliases[i],ThisLine,p->Getservbyname->Data); - WS_DbgPrint(MAX_TRACE,("Aliase %d: %s\n", i, Aliases[i])); - } - - memcpy(p->Getservbyname, - Aliases, - sizeof(Aliases)); - - /* Create the struct proper */ - p->Getservbyname->ServerEntry.s_name = ServiceName; - p->Getservbyname->ServerEntry.s_aliases = p->Getservbyname->Aliases; - p->Getservbyname->ServerEntry.s_port = htons(atoi(PortNumberStr)); - p->Getservbyname->ServerEntry.s_proto = ProtocolStr; - - return &p->Getservbyname->ServerEntry; -} - - -/* - * @implemented - */ -LPSERVENT -EXPORT -getservbyport(IN INT port, - IN CONST CHAR FAR* proto) -{ - BOOL Found = FALSE; - HANDLE ServicesFile; - CHAR ServiceDBData[BUFSIZ] = { 0 }; - PCHAR SystemDirectory = ServiceDBData; /* Reuse this stack space */ - PCHAR ServicesFileLocation = "\\drivers\\etc\\services"; - PCHAR ThisLine = 0, NextLine = 0, ServiceName = 0, PortNumberStr = 0, - ProtocolStr = 0, Comment = 0; - PCHAR Aliases[WS2_INTERNAL_MAX_ALIAS] = { 0 }; - UINT i,SizeNeeded = 0, - SystemDirSize = sizeof(ServiceDBData) - 1; - DWORD ReadSize = 0, ValidData = 0; - PWINSOCK_THREAD_BLOCK p = NtCurrentTeb()->WinSockData; - - if( !p ) - { - WSASetLastError( WSANOTINITIALISED ); - return NULL; - } - - if ( !port ) - { - WSASetLastError( WSANO_RECOVERY ); - return NULL; - } - - if( !GetSystemDirectoryA( SystemDirectory, SystemDirSize ) ) - { - WSASetLastError( WSANO_RECOVERY ); - WS_DbgPrint(MIN_TRACE, ("Could not get windows system directory.\n")); - return NULL; /* Can't get system directory */ - } - - strncat(SystemDirectory, - ServicesFileLocation, - SystemDirSize ); - - ServicesFile = CreateFileA(SystemDirectory, - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, - NULL ); - - if( ServicesFile == INVALID_HANDLE_VALUE ) - { - WSASetLastError( WSANO_RECOVERY ); - return NULL; - } - - /* Scan the services file ... - * - * We will read up to BUFSIZ bytes per pass, until the buffer does not - * contain a full line, then we will try to read more. - * - * We fall from the loop if the buffer does not have a line terminator. - */ - - /* Initial Read */ - while(!Found && - ReadFile(ServicesFile, - ServiceDBData + ValidData, - sizeof( ServiceDBData ) - ValidData, - &ReadSize, NULL ) ) - { - ValidData += ReadSize; - ReadSize = 0; - NextLine = ThisLine = ServiceDBData; - - /* Find the beginning of the next line */ - while( NextLine < ServiceDBData + ValidData && - *NextLine != '\r' && *NextLine != '\n' ) NextLine++; - - /* Zero and skip, so we can treat what we have as a string */ - if( NextLine >= ServiceDBData + ValidData ) - break; - - *NextLine = 0; NextLine++; - - Comment = strchr( ThisLine, '#' ); - if( Comment ) *Comment = 0; /* Terminate at comment start */ - - if(DecodeServEntFromString(ThisLine, - &ServiceName, - &PortNumberStr, - &ProtocolStr, - Aliases, - WS2_INTERNAL_MAX_ALIAS ) && - (htons(atoi( PortNumberStr )) == port ) && - (proto ? !strcmp( ProtocolStr, proto ) : TRUE) ) - { - - WS_DbgPrint(MAX_TRACE,("Found the port entry.\n")); - - Found = TRUE; - SizeNeeded = sizeof(WINSOCK_GETSERVBYPORT_CACHE) + - (NextLine - ThisLine); - break; - } - - /* Get rid of everything we read so far */ - while( NextLine <= ServiceDBData + ValidData && - isspace( *NextLine ) ) - { - NextLine++; - } - - WS_DbgPrint(MAX_TRACE,("About to move %d chars\n", - ServiceDBData + ValidData - NextLine)); - - memmove(ServiceDBData, - NextLine, - ServiceDBData + ValidData - NextLine ); - ValidData -= NextLine - ServiceDBData; - WS_DbgPrint(MAX_TRACE,("Valid bytes: %d\n", ValidData)); - } - - /* This we'll do no matter what */ - CloseHandle( ServicesFile ); - - if( !Found ) - { - WS_DbgPrint(MAX_TRACE,("Not found\n")); - WSASetLastError( WSANO_DATA ); - return NULL; - } - - if( !p->Getservbyport || p->Getservbyport->Size < SizeNeeded ) - { - /* Free previous getservbyport buffer, allocate bigger */ - if( p->Getservbyport ) - HeapFree(GlobalHeap, 0, p->Getservbyport); - p->Getservbyport = HeapAlloc(GlobalHeap, - 0, - SizeNeeded); - if( !p->Getservbyport ) - { - WS_DbgPrint(MIN_TRACE,("Couldn't allocate %d bytes\n", - SizeNeeded)); - WSASetLastError( WSATRY_AGAIN ); - return NULL; - } - p->Getservbyport->Size = SizeNeeded; - } - /* Copy the data */ - memmove(p->Getservbyport->Data, - ThisLine, - NextLine - ThisLine ); - - ADJ_PTR(PortNumberStr,ThisLine,p->Getservbyport->Data); - ADJ_PTR(ProtocolStr,ThisLine,p->Getservbyport->Data); - WS_DbgPrint(MAX_TRACE, ("Port Number: %s, Protocol: %s\n", - PortNumberStr, ProtocolStr)); - - for( i = 0; Aliases[i]; i++ ) - { - ADJ_PTR(Aliases[i],ThisLine,p->Getservbyport->Data); - WS_DbgPrint(MAX_TRACE,("Aliases %d: %s\n", i, Aliases[i])); - } - - memcpy(p->Getservbyport,Aliases,sizeof(Aliases)); - - /* Create the struct proper */ - p->Getservbyport->ServerEntry.s_name = ServiceName; - p->Getservbyport->ServerEntry.s_aliases = p->Getservbyport->Aliases; - p->Getservbyport->ServerEntry.s_port = port; - p->Getservbyport->ServerEntry.s_proto = ProtocolStr; - - WS_DbgPrint(MID_TRACE,("s_name: %s\n", ServiceName)); - - return &p->Getservbyport->ServerEntry; - -} - - -/* - * @implemented - */ -ULONG -EXPORT -inet_addr(IN CONST CHAR FAR* cp) -/* - * FUNCTION: Converts a string containing an IPv4 address to an unsigned long - * ARGUMENTS: - * cp = Pointer to string with address to convert - * RETURNS: - * Binary representation of IPv4 address, or INADDR_NONE - */ -{ - UINT i; - PCHAR p; - ULONG u = 0; - - p = (PCHAR)cp; - - if (!p) - { - WSASetLastError(WSAEFAULT); - return INADDR_NONE; - } - - if (strlen(p) == 0) - return INADDR_NONE; - - if (strcmp(p, " ") == 0) - return 0; - - for (i = 0; i <= 3; i++) - { - u += (strtoul(p, &p, 0) << (i * 8)); - - if (strlen(p) == 0) - return u; - - if (p[0] != '.') - return INADDR_NONE; - - p++; - } - - return u; -} - - -/* - * @implemented - */ -CHAR FAR* -EXPORT -inet_ntoa(IN IN_ADDR in) -{ - CHAR b[10]; - PCHAR p; - - p = ((PWINSOCK_THREAD_BLOCK)NtCurrentTeb()->WinSockData)->Intoa; - _itoa(in.S_un.S_addr & 0xFF, b, 10); - strcpy(p, b); - _itoa((in.S_un.S_addr >> 8) & 0xFF, b, 10); - strcat(p, "."); - strcat(p, b); - _itoa((in.S_un.S_addr >> 16) & 0xFF, b, 10); - strcat(p, "."); - strcat(p, b); - _itoa((in.S_un.S_addr >> 24) & 0xFF, b, 10); - strcat(p, "."); - strcat(p, b); - - return (CHAR FAR*)p; -} - - -/* - * @implemented - */ -VOID -EXPORT -freeaddrinfo(struct addrinfo *pAddrInfo) -{ - struct addrinfo *next, *cur; - cur = pAddrInfo; - while (cur) - { - next = cur->ai_next; - if (cur->ai_addr) - HeapFree(GetProcessHeap(), 0, cur->ai_addr); - if (cur->ai_canonname) - HeapFree(GetProcessHeap(), 0, cur->ai_canonname); - HeapFree(GetProcessHeap(), 0, cur); - cur = next; - } -} - - -struct addrinfo * -new_addrinfo(struct addrinfo *prev) -{ - struct addrinfo *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct addrinfo)); - if (prev) - prev->ai_next = ret; - return ret; -} - -/* - * @implemented - */ -INT -EXPORT -getaddrinfo(const char FAR * nodename, - const char FAR * servname, - const struct addrinfo FAR * hints, - struct addrinfo FAR * FAR * res) -{ - struct addrinfo *ret = NULL, *ai; - ULONG addr; - USHORT port; - struct servent *se; - char *proto; - LPPROTOENT pent; - DNS_STATUS dns_status; - PDNS_RECORD dp, currdns; - struct sockaddr_in *sin; - - if (res == NULL) - return WSAEINVAL; - if (nodename == NULL && servname == NULL) - return WSAHOST_NOT_FOUND; - - if (!WSAINITIALIZED) - return WSANOTINITIALISED; - - if (servname) - { - /* converting port number */ - port = strtoul(servname, NULL, 10); - /* service name was specified? */ - if (port == 0) - { - /* protocol was specified? */ - if (hints && hints->ai_protocol) - { - pent = getprotobynumber(hints->ai_protocol); - if (pent == NULL) - return WSAEINVAL; - proto = pent->p_name; - } - else - proto = NULL; - se = getservbyname(servname, proto); - if (se == NULL) - return WSATYPE_NOT_FOUND; - port = se->s_port; - } - else - port = htons(port); - } - else - port = 0; - - if (nodename) - { - /* Is it an IPv6 address? */ - if (strstr(nodename, ":")) - return WSAHOST_NOT_FOUND; - - /* Is it an IPv4 address? */ - addr = inet_addr(nodename); - if (addr != INADDR_NONE) - { - ai = new_addrinfo(NULL); - ai->ai_family = PF_INET; - ai->ai_addrlen = sizeof(struct sockaddr_in); - ai->ai_addr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ai->ai_addrlen); - sin = (struct sockaddr_in *)ai->ai_addr; - sin->sin_family = AF_INET; - sin->sin_port = port; - RtlCopyMemory(&sin->sin_addr, &addr, sizeof(sin->sin_addr)); - if (hints) - { - if (ai->ai_socktype == 0) - ai->ai_socktype = hints->ai_socktype; - if (ai->ai_protocol == 0) - ai->ai_protocol = hints->ai_protocol; - } - ret = ai; - } - else - { - /* resolving host name */ - dns_status = DnsQuery_A(nodename, - DNS_TYPE_A, - DNS_QUERY_STANDARD, - 0, - /* extra dns servers */ &dp, - 0); - - if (dns_status == 0) - { - ai = NULL; - for (currdns = dp; currdns; currdns = currdns->pNext ) - { - /* accept only A records */ - if (currdns->wType != DNS_TYPE_A) continue; - - ai = new_addrinfo(ai); - if (ret == NULL) - ret = ai; - ai->ai_family = PF_INET; - ai->ai_addrlen = sizeof(struct sockaddr_in); - ai->ai_addr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ai->ai_addrlen); - sin = (struct sockaddr_in *)ret->ai_addr; - sin->sin_family = AF_INET; - sin->sin_port = port; - RtlCopyMemory(&sin->sin_addr, &currdns->Data.A.IpAddress, sizeof(sin->sin_addr)); - if (hints) - { - if (ai->ai_socktype == 0) - ai->ai_socktype = hints->ai_socktype; - if (ai->ai_protocol == 0) - ai->ai_protocol = hints->ai_protocol; - } - } - DnsRecordListFree(dp, DnsFreeRecordList); - } - } - } - else - { - ai = new_addrinfo(NULL); - ai->ai_family = PF_INET; - ai->ai_addrlen = sizeof(struct sockaddr_in); - ai->ai_addr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ai->ai_addrlen); - sin = (struct sockaddr_in *)ai->ai_addr; - sin->sin_family = AF_INET; - sin->sin_port = port; - if (hints) - { - if (!(hints->ai_flags & AI_PASSIVE)) - { - sin->sin_addr.S_un.S_un_b.s_b1 = 127; - sin->sin_addr.S_un.S_un_b.s_b2 = 0; - sin->sin_addr.S_un.S_un_b.s_b3 = 0; - sin->sin_addr.S_un.S_un_b.s_b4 = 1; - } - if (ai->ai_socktype == 0) - ai->ai_socktype = hints->ai_socktype; - if (ai->ai_protocol == 0) - ai->ai_protocol = hints->ai_protocol; - } - ret = ai; - } - - if (ret == NULL) - return WSAHOST_NOT_FOUND; - - if (hints && hints->ai_family != PF_UNSPEC && hints->ai_family != PF_INET) - { - freeaddrinfo(ret); - return WSAEAFNOSUPPORT; - } - - *res = ret; - return 0; -} - -/* EOF */ diff --git a/dll/win32/ws2_32/misc/sndrcv.c b/dll/win32/ws2_32/misc/sndrcv.c deleted file mode 100644 index f1b68feb158..00000000000 --- a/dll/win32/ws2_32/misc/sndrcv.c +++ /dev/null @@ -1,417 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS WinSock 2 DLL - * FILE: misc/sndrcv.c - * PURPOSE: Send/receive functions - * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) - * REVISIONS: - * CSH 01/09-2000 Created - */ - -#include -#include -#include -#include - - -/* - * @implemented - */ -INT -EXPORT -recv(IN SOCKET s, - OUT CHAR FAR* buf, - IN INT len, - IN INT flags) -{ - DWORD Error; - DWORD BytesReceived; - WSABUF WSABuf; - - WS_DbgPrint(MAX_TRACE, ("s (0x%X) buf (0x%X) len (0x%X) flags (0x%X).\n", - s, - buf, - len, - flags)); - - WSABuf.len = len; - WSABuf.buf = (CHAR FAR*)buf; - - Error = WSARecv(s, - &WSABuf, - 1, - &BytesReceived, - (LPDWORD)&flags, - NULL, - NULL); - - if( Error ) - return -1; - else - return BytesReceived; -} - - -/* - * @implemented - */ -INT -EXPORT -recvfrom(IN SOCKET s, - OUT CHAR FAR* buf, - IN INT len, - IN INT flags, - OUT LPSOCKADDR from, - IN OUT INT FAR* fromlen) -{ - DWORD Error; - DWORD BytesReceived; - WSABUF WSABuf; - - WS_DbgPrint(MAX_TRACE, ("s (0x%X) buf (0x%X) len (0x%X) flags (0x%X).\n", - s, - buf, - len, - flags)); - - WSABuf.len = len; - WSABuf.buf = (CHAR FAR*)buf; - - Error = WSARecvFrom(s, - &WSABuf, - 1, - &BytesReceived, - (LPDWORD)&flags, - from, - fromlen, - NULL, - NULL); - - if( Error ) - return -1; - else - return BytesReceived; -} - - -/* - * @implemented - */ -INT -EXPORT -send(IN SOCKET s, - IN CONST CHAR FAR* buf, - IN INT len, - IN INT flags) -{ - DWORD BytesSent; - DWORD Error; - WSABUF WSABuf; - - WS_DbgPrint(MAX_TRACE, ("s (0x%X) buf (0x%X) len (0x%X) flags (0x%X).\n", - s, - buf, - len, - flags)); - - WSABuf.len = len; - WSABuf.buf = (CHAR FAR*)buf; - - Error = WSASend(s, - &WSABuf, - 1, - &BytesSent, - flags, - NULL, - NULL); - - if( Error ) - { - WS_DbgPrint(MAX_TRACE,("Reporting error %d\n", Error)); - return -1; - } - else - { - WS_DbgPrint(MAX_TRACE,("Read %d bytes\n", BytesSent)); - return BytesSent; - } -} - - -/* - * @implemented - */ -INT -EXPORT -sendto(IN SOCKET s, - IN CONST CHAR FAR* buf, - IN INT len, - IN INT flags, - IN CONST struct sockaddr *to, - IN INT tolen) -{ - DWORD Error; - DWORD BytesSent; - WSABUF WSABuf; - - WS_DbgPrint(MAX_TRACE, ("s (0x%X) buf (0x%X) len (0x%X) flags (0x%X).\n", - s, - buf, - len, - flags)); - - WSABuf.len = len; - WSABuf.buf = (CHAR FAR*)buf; - - Error = WSASendTo(s, - &WSABuf, - 1, - &BytesSent, - flags, - to, - tolen, - NULL, - NULL); - - if( Error ) - return -1; - else - return BytesSent; -} - - -/* - * @implemented - */ -INT -EXPORT -WSARecv(IN SOCKET s, - IN OUT LPWSABUF lpBuffers, - IN DWORD dwBufferCount, - OUT LPDWORD lpNumberOfBytesRecvd, - IN OUT LPDWORD lpFlags, - IN LPWSAOVERLAPPED lpOverlapped, - IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) -{ - PCATALOG_ENTRY Provider; - INT Errno; - INT Code; - - WS_DbgPrint(MAX_TRACE, ("Called.\n")); - - if (!ReferenceProviderByHandle((HANDLE)s, - &Provider)) - { - WSASetLastError(WSAENOTSOCK); - return SOCKET_ERROR; - } - - assert(Provider->ProcTable.lpWSPRecv); - - Code = Provider->ProcTable.lpWSPRecv(s, - lpBuffers, - dwBufferCount, - lpNumberOfBytesRecvd, - lpFlags, - lpOverlapped, - lpCompletionRoutine, - NULL /* lpThreadId */, - &Errno); - - DereferenceProviderByPointer(Provider); - - if (Code == SOCKET_ERROR) - WSASetLastError(Errno); - - return Code; -} - - -/* - * @unimplemented - */ -INT -EXPORT -WSARecvDisconnect(IN SOCKET s, - OUT LPWSABUF lpInboundDisconnectData) -{ - UNIMPLEMENTED - - return 0; -} - - -/* - * @implemented - */ -INT -EXPORT -WSARecvFrom(IN SOCKET s, - IN OUT LPWSABUF lpBuffers, - IN DWORD dwBufferCount, - OUT LPDWORD lpNumberOfBytesRecvd, - IN OUT LPDWORD lpFlags, - OUT LPSOCKADDR lpFrom, - IN OUT LPINT lpFromlen, - IN LPWSAOVERLAPPED lpOverlapped, - IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) -{ - PCATALOG_ENTRY Provider; - INT Errno; - INT Code; - - WS_DbgPrint(MAX_TRACE, ("Called.\n")); - - if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) - { - WSASetLastError(WSAENOTSOCK); - return SOCKET_ERROR; - } - - assert(Provider->ProcTable.lpWSPRecvFrom); - - Code = Provider->ProcTable.lpWSPRecvFrom(s, - lpBuffers, - dwBufferCount, - lpNumberOfBytesRecvd, - lpFlags, - lpFrom, - lpFromlen, - lpOverlapped, - lpCompletionRoutine, - NULL /* lpThreadId */, - &Errno); - - DereferenceProviderByPointer(Provider); - - if (Code == SOCKET_ERROR) - WSASetLastError(Errno); - - return Code; -} - - -/* - * @implemented - */ -INT -EXPORT -WSASend(IN SOCKET s, - IN LPWSABUF lpBuffers, - IN DWORD dwBufferCount, - OUT LPDWORD lpNumberOfBytesSent, - IN DWORD dwFlags, - IN LPWSAOVERLAPPED lpOverlapped, - IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) -{ - PCATALOG_ENTRY Provider; - INT Errno; - INT Code; - - WS_DbgPrint(MAX_TRACE, ("Called.\n")); - - if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) - { - WSASetLastError(WSAENOTSOCK); - return SOCKET_ERROR; - } - - assert(Provider->ProcTable.lpWSPSend); - - Code = Provider->ProcTable.lpWSPSend(s, - lpBuffers, - dwBufferCount, - lpNumberOfBytesSent, - dwFlags, - lpOverlapped, - lpCompletionRoutine, - NULL /* lpThreadId */, - &Errno); - - DereferenceProviderByPointer(Provider); - - if (Code == SOCKET_ERROR) - WSASetLastError(Errno); - - return Code; -} - - -/* - * @unimplemented - */ -INT -EXPORT -WSASendDisconnect(IN SOCKET s, - IN LPWSABUF lpOutboundDisconnectData) -{ - UNIMPLEMENTED - - return 0; -} - - -/* - * @implemented - */ -INT -EXPORT -WSASendTo(IN SOCKET s, - IN LPWSABUF lpBuffers, - IN DWORD dwBufferCount, - OUT LPDWORD lpNumberOfBytesSent, - IN DWORD dwFlags, - IN CONST struct sockaddr *lpTo, - IN INT iToLen, - IN LPWSAOVERLAPPED lpOverlapped, - IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) -{ - PCATALOG_ENTRY Provider; - INT Errno; - INT Code; - - WS_DbgPrint(MAX_TRACE, ("Called.\n")); - - if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) - { - WSASetLastError(WSAENOTSOCK); - return SOCKET_ERROR; - } - - assert(Provider->ProcTable.lpWSPSendTo); - -#if (__W32API_MAJOR_VERSION < 2 || __W32API_MINOR_VERSION < 5) - Code = Provider->ProcTable.lpWSPSendTo(s, - lpBuffers, - dwBufferCount, - lpNumberOfBytesSent, - dwFlags, - (CONST LPSOCKADDR)lpTo, - iToLen, - lpOverlapped, - lpCompletionRoutine, - NULL /* lpThreadId */, - &Errno); -#else - Code = Provider->ProcTable.lpWSPSendTo(s, - lpBuffers, - dwBufferCount, - lpNumberOfBytesSent, - dwFlags, - lpTo, - iToLen, - lpOverlapped, - lpCompletionRoutine, - NULL /* lpThreadId */, - &Errno); -#endif /* __W32API_MAJOR_VERSION < 2 || __W32API_MINOR_VERSION < 5 */ - - DereferenceProviderByPointer(Provider); - - if (Code == SOCKET_ERROR) - WSASetLastError(Errno); - - return Code; -} - -/* EOF */ diff --git a/dll/win32/ws2_32/misc/stubs.c b/dll/win32/ws2_32/misc/stubs.c deleted file mode 100644 index 408f28294a6..00000000000 --- a/dll/win32/ws2_32/misc/stubs.c +++ /dev/null @@ -1,938 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS WinSock 2 DLL - * FILE: misc/stubs.c - * PURPOSE: Stubs - * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) - * REVISIONS: - * CSH 01/09-2000 Created - */ -#include -#include -#include - -/* - * @implemented - */ -INT -EXPORT -getpeername(IN SOCKET s, - OUT LPSOCKADDR name, - IN OUT INT FAR* namelen) -{ - int Error; - INT Errno; - PCATALOG_ENTRY Provider; - - if (!WSAINITIALIZED) - { - WSASetLastError(WSANOTINITIALISED); - return SOCKET_ERROR; - } - - if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) - { - WSASetLastError(WSAENOTSOCK); - return SOCKET_ERROR; - } - - Error = Provider->ProcTable.lpWSPGetPeerName(s, - name, - namelen, - &Errno); - - DereferenceProviderByPointer(Provider); - - if (Error == SOCKET_ERROR) - { - WSASetLastError(Errno); - } - - return Error; -} - - - -/* - * @implemented - */ -INT -EXPORT -getsockname(IN SOCKET s, - OUT LPSOCKADDR name, - IN OUT INT FAR* namelen) -{ - int Error; - INT Errno; - PCATALOG_ENTRY Provider; - - if (!WSAINITIALIZED) - { - WSASetLastError(WSANOTINITIALISED); - return SOCKET_ERROR; - } - - if (!ReferenceProviderByHandle((HANDLE)s, - &Provider)) - { - WSASetLastError(WSAENOTSOCK); - return SOCKET_ERROR; - } - - Error = Provider->ProcTable.lpWSPGetSockName(s, - name, - namelen, - &Errno); - - DereferenceProviderByPointer(Provider); - - if (Error == SOCKET_ERROR) - { - WSASetLastError(Errno); - } - - return Error; -} - - -/* - * @implemented - */ -INT -EXPORT -getsockopt(IN SOCKET s, - IN INT level, - IN INT optname, - OUT CHAR FAR* optval, - IN OUT INT FAR* optlen) -{ - PCATALOG_ENTRY Provider; - INT Errno; - int Error; - - if (!WSAINITIALIZED) - { - WSASetLastError(WSANOTINITIALISED); - return SOCKET_ERROR; - } - - if (!ReferenceProviderByHandle((HANDLE)s, - &Provider)) - { - WSASetLastError(WSAENOTSOCK); - return SOCKET_ERROR; - } - - Error = Provider->ProcTable.lpWSPGetSockOpt(s, - level, - optname, - optval, - optlen, - &Errno); - - DereferenceProviderByPointer(Provider); - - if (Error == SOCKET_ERROR) - { - WSASetLastError(Errno); - } - - return Error; -} - - -/* - * @implemented - */ -INT -EXPORT __stdcall -setsockopt(IN SOCKET s, - IN INT level, - IN INT optname, - IN CONST CHAR FAR* optval, - IN INT optlen) -{ - PCATALOG_ENTRY Provider; - INT Errno; - int Error; - - if (!WSAINITIALIZED) - { - WSASetLastError(WSANOTINITIALISED); - return SOCKET_ERROR; - } - - if(IS_INTRESOURCE(optval)) - { - SetLastError(WSAEFAULT); - return SOCKET_ERROR; - } - - if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) - { - WSASetLastError(WSAENOTSOCK); - return SOCKET_ERROR; - } - - Error = Provider->ProcTable.lpWSPSetSockOpt(s, - level, - optname, - optval, - optlen, - &Errno); - - DereferenceProviderByPointer(Provider); - - if (Error == SOCKET_ERROR) - { - WSASetLastError(Errno); - } - - return Error; -} - - -/* - * @implemented - */ -INT -EXPORT -shutdown(IN SOCKET s, - IN INT how) -{ - PCATALOG_ENTRY Provider; - INT Errno; - int Error; - - if (!WSAINITIALIZED) - { - WSASetLastError(WSANOTINITIALISED); - return SOCKET_ERROR; - } - - if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) - { - WSASetLastError(WSAENOTSOCK); - return SOCKET_ERROR; - } - - Error = Provider->ProcTable.lpWSPShutdown(s, - how, - &Errno); - - DereferenceProviderByPointer(Provider); - - if (Error == SOCKET_ERROR) - { - WSASetLastError(Errno); - } - - return Error; -} - - -/* - * @implemented - */ -INT -EXPORT -WSAAsyncSelect(IN SOCKET s, - IN HWND hWnd, - IN UINT wMsg, - IN LONG lEvent) -{ - PCATALOG_ENTRY Provider; - INT Errno; - int Error; - - if (!WSAINITIALIZED) - { - WSASetLastError(WSANOTINITIALISED); - return SOCKET_ERROR; - } - - if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) - { - WSASetLastError(WSAENOTSOCK); - return SOCKET_ERROR; - } - - Error = Provider->ProcTable.lpWSPAsyncSelect(s, - hWnd, - wMsg, - lEvent, - &Errno); - - DereferenceProviderByPointer(Provider); - - if (Error == SOCKET_ERROR) - { - WSASetLastError(Errno); - } - - return Error; -} - - -/* - * @unimplemented - */ -INT -EXPORT -WSACancelBlockingCall(VOID) -{ -#if 0 - INT Errno; - int Error; - PCATALOG_ENTRY Provider; - - if (!WSAINITIALIZED) - { - WSASetLastError(WSANOTINITIALISED); - return SOCKET_ERROR; - } - - if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) - { - WSASetLastError(WSAENOTSOCK); - return SOCKET_ERROR; - } - - Error = Provider->ProcTable.lpWSPCancelBlockingCall(&Errno); - - DereferenceProviderByPointer(Provider); - - if (Error == SOCKET_ERROR) - { - WSASetLastError(Errno); - } - - return Error; -#endif - - UNIMPLEMENTED - - WSASetLastError(WSASYSCALLFAILURE); - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -INT -EXPORT -WSADuplicateSocketA(IN SOCKET s, - IN DWORD dwProcessId, - OUT LPWSAPROTOCOL_INFOA lpProtocolInfo) -{ -#if 0 - WSAPROTOCOL_INFOA ProtocolInfoU; - - Error = WSADuplicateSocketW(s, - dwProcessId, - &ProtocolInfoU); - - if (Error == NO_ERROR) - { - UnicodeToAnsi(lpProtocolInfo, - ProtocolInfoU, - sizeof( - - } - - return Error; -#endif - - UNIMPLEMENTED - - WSASetLastError(WSASYSCALLFAILURE); - return SOCKET_ERROR; -} - - - -/* - * @implemented - */ -INT -EXPORT -WSADuplicateSocketW(IN SOCKET s, - IN DWORD dwProcessId, - OUT LPWSAPROTOCOL_INFOW lpProtocolInfo) -{ - INT Errno; - int Error; - PCATALOG_ENTRY Provider; - - if (!WSAINITIALIZED) - { - WSASetLastError(WSANOTINITIALISED); - return SOCKET_ERROR; - } - - if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) - { - WSASetLastError(WSAENOTSOCK); - return SOCKET_ERROR; - } - - Error = Provider->ProcTable.lpWSPDuplicateSocket(s, - dwProcessId, - lpProtocolInfo, - &Errno); - DereferenceProviderByPointer(Provider); - - if (Error == SOCKET_ERROR) - { - WSASetLastError(Errno); - } - - return Error; -} - - -/* - * @unimplemented - */ -INT -EXPORT -WSAEnumProtocolsA(IN LPINT lpiProtocols, - OUT LPWSAPROTOCOL_INFOA lpProtocolBuffer, - IN OUT LPDWORD lpdwBufferLength) -{ - UNIMPLEMENTED - - WSASetLastError(WSASYSCALLFAILURE); - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -INT -EXPORT -WSAEnumProtocolsW(IN LPINT lpiProtocols, - OUT LPWSAPROTOCOL_INFOW lpProtocolBuffer, - IN OUT LPDWORD lpdwBufferLength) -{ - UNIMPLEMENTED - - WSASetLastError(WSASYSCALLFAILURE); - return SOCKET_ERROR; -} - - -/* - * @implemented - */ -BOOL -EXPORT -WSAGetOverlappedResult(IN SOCKET s, - IN LPWSAOVERLAPPED lpOverlapped, - OUT LPDWORD lpcbTransfer, - IN BOOL fWait, - OUT LPDWORD lpdwFlags) -{ - INT Errno; - BOOL Success; - PCATALOG_ENTRY Provider; - - if (!WSAINITIALIZED) - { - WSASetLastError(WSANOTINITIALISED); - return SOCKET_ERROR; - } - - if (!ReferenceProviderByHandle((HANDLE)s, &Provider)) - { - WSASetLastError(WSAENOTSOCK); - return SOCKET_ERROR; - } - - Success = Provider->ProcTable.lpWSPGetOverlappedResult(s, - lpOverlapped, - lpcbTransfer, - fWait, - lpdwFlags, - &Errno); - DereferenceProviderByPointer(Provider); - - if (Success == FALSE) - { - WSASetLastError(Errno); - } - - return Success; -} - - -/* - * @unimplemented - */ -BOOL -EXPORT -WSAGetQOSByName(IN SOCKET s, - IN OUT LPWSABUF lpQOSName, - OUT LPQOS lpQOS) -{ - UNIMPLEMENTED - - WSASetLastError(WSASYSCALLFAILURE); - return FALSE; -} - - -/* - * @unimplemented - */ -INT -EXPORT -WSAHtonl(IN SOCKET s, - IN ULONG hostLONG, - OUT ULONG FAR* lpnetlong) -{ - UNIMPLEMENTED - - WSASetLastError(WSASYSCALLFAILURE); - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -INT -EXPORT -WSAHtons(IN SOCKET s, - IN USHORT hostshort, - OUT USHORT FAR* lpnetshort) -{ - PCATALOG_ENTRY provider; - if (!WSAINITIALIZED) - { - WSASetLastError(WSANOTINITIALISED); - return SOCKET_ERROR; - } - - if (!ReferenceProviderByHandle((HANDLE)s, &provider)) - { - WSASetLastError(WSAENOTSOCK); - return SOCKET_ERROR; - } - - switch (provider->ProtocolInfo.iNetworkByteOrder) - { - case BIGENDIAN: - *lpnetshort = htons(hostshort); - break; - case LITTLEENDIAN: -#ifdef LE - *lpnetshort = hostshort; -#else - *lpnetshort = (((hostshort & 0xFF00) >> 8) | ((hostshort & 0x00FF) << 8)); -#endif - break; - } - return 0; -} - - -/* - * @unimplemented - */ -BOOL -EXPORT -WSAIsBlocking(VOID) -{ - UNIMPLEMENTED - - return FALSE; -} - - -/* - * @unimplemented - */ -SOCKET -EXPORT -WSAJoinLeaf(IN SOCKET s, - IN CONST struct sockaddr *name, - IN INT namelen, - IN LPWSABUF lpCallerData, - OUT LPWSABUF lpCalleeData, - IN LPQOS lpSQOS, - IN LPQOS lpGQOS, - IN DWORD dwFlags) -{ - UNIMPLEMENTED - - WSASetLastError(WSASYSCALLFAILURE); - return INVALID_SOCKET; -} - - -/* - * @unimplemented - */ -INT -EXPORT -WSANtohl(IN SOCKET s, - IN ULONG netlong, - OUT ULONG FAR* lphostlong) -{ - UNIMPLEMENTED - - WSASetLastError(WSASYSCALLFAILURE); - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -INT -EXPORT -WSANtohs(IN SOCKET s, - IN USHORT netshort, - OUT USHORT FAR* lphostshort) -{ - PCATALOG_ENTRY provider; - if (!WSAINITIALIZED) - { - WSASetLastError(WSANOTINITIALISED); - return SOCKET_ERROR; - } - - if (!ReferenceProviderByHandle((HANDLE)s, &provider)) - { - WSASetLastError(WSAENOTSOCK); - return SOCKET_ERROR; - } - - switch (provider->ProtocolInfo.iNetworkByteOrder) - { - case BIGENDIAN: - *lphostshort = ntohs(netshort); - break; - case LITTLEENDIAN: -#ifdef LE - *lphostshort = netshort; -#else - *lphostshort = (((netshort & 0xFF00) >> 8) | ((netshort & 0x00FF) << 8)); -#endif - break; - } - return 0; -} - - -/* - * @unimplemented - */ -FARPROC -EXPORT -WSASetBlockingHook(IN FARPROC lpBlockFunc) -{ - UNIMPLEMENTED - - return (FARPROC)0; -} - - -/* - * @unimplemented - */ -INT -EXPORT -WSAUnhookBlockingHook(VOID) -{ - UNIMPLEMENTED - - return 0; -} - - -/* - * @unimplemented - */ -INT -EXPORT -WSAProviderConfigChange(IN OUT LPHANDLE lpNotificationHandle, - IN LPWSAOVERLAPPED lpOverlapped, - IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) -{ - UNIMPLEMENTED - - WSASetLastError(WSASYSCALLFAILURE); - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -INT -EXPORT -WSACancelAsyncRequest(IN HANDLE hAsyncTaskHandle) -{ - UNIMPLEMENTED - - WSASetLastError(WSASYSCALLFAILURE); - return SOCKET_ERROR; -} - -/* WinSock Service Provider support functions */ - -/* - * @unimplemented - */ -INT -EXPORT -WPUCompleteOverlappedRequest(IN SOCKET s, - IN LPWSAOVERLAPPED lpOverlapped, - IN DWORD dwError, - IN DWORD cbTransferred, - OUT LPINT lpErrno) -{ - UNIMPLEMENTED - - WSASetLastError(WSASYSCALLFAILURE); - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -INT -EXPORT -WSCDeinstallProvider(IN LPGUID lpProviderId, - OUT LPINT lpErrno) -{ - UNIMPLEMENTED - - WSASetLastError(WSASYSCALLFAILURE); - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -INT -EXPORT -WSCEnumProtocols(IN LPINT lpiProtocols, - OUT LPWSAPROTOCOL_INFOW lpProtocolBuffer, - IN OUT LPDWORD lpdwBufferLength, - OUT LPINT lpErrno) -{ - UNIMPLEMENTED - - WSASetLastError(WSASYSCALLFAILURE); - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -INT -EXPORT -WSCGetProviderPath(IN LPGUID lpProviderId, - OUT LPWSTR lpszProviderDllPath, - IN OUT LPINT lpProviderDllPathLen, - OUT LPINT lpErrno) -{ - UNIMPLEMENTED - - WSASetLastError(WSASYSCALLFAILURE); - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -INT -EXPORT -WSCInstallProvider(IN LPGUID lpProviderId, - IN CONST WCHAR* lpszProviderDllPath, - IN CONST LPWSAPROTOCOL_INFOW lpProtocolInfoList, - IN DWORD dwNumberOfEntries, - OUT LPINT lpErrno) -{ - UNIMPLEMENTED - - WSASetLastError(WSASYSCALLFAILURE); - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -INT -EXPORT -WSCEnableNSProvider(IN LPGUID lpProviderId, - IN BOOL fEnable) -{ - UNIMPLEMENTED - - WSASetLastError(WSASYSCALLFAILURE); - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -INT -EXPORT -WSCInstallNameSpace(IN LPWSTR lpszIdentifier, - IN LPWSTR lpszPathName, - IN DWORD dwNameSpace, - IN DWORD dwVersion, - IN LPGUID lpProviderId) -{ - UNIMPLEMENTED - - WSASetLastError(WSASYSCALLFAILURE); - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -INT -EXPORT -WSCUnInstallNameSpace(IN LPGUID lpProviderId) -{ - UNIMPLEMENTED - - WSASetLastError(WSASYSCALLFAILURE); - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -INT -EXPORT -WSCWriteProviderOrder(IN LPDWORD lpwdCatalogEntryId, - IN DWORD dwNumberOfEntries) -{ - UNIMPLEMENTED - - return WSASYSCALLFAILURE; -} - -/* - * @unimplemented - */ -INT -EXPORT -WSANSPIoctl(HANDLE hLookup, - DWORD dwControlCode, - LPVOID lpvInBuffer, - DWORD cbInBuffer, - LPVOID lpvOutBuffer, - DWORD cbOutBuffer, - LPDWORD lpcbBytesReturned, - LPWSACOMPLETION lpCompletion) -{ - UNIMPLEMENTED - - WSASetLastError(WSASYSCALLFAILURE); - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -INT -EXPORT -WSCUpdateProvider(LPGUID lpProviderId, - const WCHAR FAR * lpszProviderDllPath, - const LPWSAPROTOCOL_INFOW lpProtocolInfoList, - DWORD dwNumberOfEntries, - LPINT lpErrno) -{ - UNIMPLEMENTED - - WSASetLastError(WSASYSCALLFAILURE); - return SOCKET_ERROR; -} - -/* - * @unimplemented - */ -INT -EXPORT -WSCWriteNameSpaceOrder(LPGUID lpProviderId, - DWORD dwNumberOfEntries) -{ - UNIMPLEMENTED - - return WSASYSCALLFAILURE; -} - -/* - * @unimplemented - */ -INT -EXPORT -getnameinfo(const struct sockaddr FAR * sa, - socklen_t salen, - char FAR * host, - DWORD hostlen, - char FAR * serv, - DWORD servlen, - INT flags) -{ - UNIMPLEMENTED - - WSASetLastError(WSASYSCALLFAILURE); - return SOCKET_ERROR; -} - -/* - * @unimplemented - */ -VOID EXPORT WEP() -{ - UNIMPLEMENTED -} - -/* - * @unimplemented - */ -BOOL EXPORT WSApSetPostRoutine(PVOID Routine) -{ - UNIMPLEMENTED - - return FALSE; -} - -/* - * @unimplemented - */ -INT -EXPORT -GetAddrInfoW(IN PCWSTR pszNodeName, - IN PCWSTR pszServiceName, - IN const ADDRINFOW *ptHints, - OUT PADDRINFOW *pptResult) -{ - UNIMPLEMENTED - - WSASetLastError(EAI_FAIL); - return EAI_FAIL; -} - - -/* EOF */ diff --git a/dll/win32/ws2_32/misc/upcall.c b/dll/win32/ws2_32/misc/upcall.c deleted file mode 100644 index 3ba3b410431..00000000000 --- a/dll/win32/ws2_32/misc/upcall.c +++ /dev/null @@ -1,237 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS WinSock 2 DLL - * FILE: misc/upcall.c - * PURPOSE: Upcall functions - * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) - * REVISIONS: - * CSH 01/09-2000 Created - */ -#include -#include -#include - -/* - * @implemented - */ -BOOL -WSPAPI -WPUCloseEvent(IN WSAEVENT hEvent, - OUT LPINT lpErrno) -{ - UNIMPLEMENTED - - return FALSE; -} - - -/* - * @unimplemented - */ -INT -WSPAPI -WPUCloseSocketHandle(IN SOCKET s, - OUT LPINT lpErrno) -{ - UNIMPLEMENTED - - return 0; -} - - -/* - * @unimplemented - */ -INT -WSPAPI -WPUCloseThread(IN LPWSATHREADID lpThreadId, - OUT LPINT lpErrno) -{ - UNIMPLEMENTED - - return 0; -} - - -/* - * @unimplemented - */ -WSAEVENT -WSPAPI -WPUCreateEvent(OUT LPINT lpErrno) -{ - UNIMPLEMENTED - - return (WSAEVENT)0; -} - - -/* - * @unimplemented - */ -SOCKET -WSPAPI -WPUCreateSocketHandle(IN DWORD dwCatalogEntryId, - IN DWORD dwContext, - OUT LPINT lpErrno) -{ - UNIMPLEMENTED - - return (SOCKET)0; -} - - -/* - * @unimplemented - */ -int -WSPAPI -WPUFDIsSet(IN SOCKET s, - IN LPFD_SET set) -{ - UNIMPLEMENTED - - return (SOCKET)0; -} - - -/* - * @unimplemented - */ -INT -WSPAPI -WPUGetProviderPath(IN LPGUID lpProviderId, - OUT LPWSTR lpszProviderDllPath, - IN OUT LPINT lpProviderDllPathLen, - OUT LPINT lpErrno) -{ - UNIMPLEMENTED - - return 0; -} - - -/* - * @implemented - */ -SOCKET -WSPAPI -WPUModifyIFSHandle(IN DWORD dwCatalogEntryId, - IN SOCKET ProposedHandle, - OUT LPINT lpErrno) -{ - PCATALOG_ENTRY Provider; - SOCKET Socket; - - WS_DbgPrint(MID_TRACE, ("dwCatalogEntryId (%d) ProposedHandle (0x%X).\n", - dwCatalogEntryId, ProposedHandle)); - - Provider = LocateProviderById(dwCatalogEntryId); - if (!Provider) - { - WS_DbgPrint(MIN_TRACE, ("Provider with catalog entry id (%d) was not found.\n", - dwCatalogEntryId)); - if( lpErrno ) *lpErrno = WSAEINVAL; - WS_DbgPrint(MID_TRACE, ("Returning invalid socket\n")); - return INVALID_SOCKET; - } - - Socket = (SOCKET)CreateProviderHandle((HANDLE)ProposedHandle, - Provider); - - if( lpErrno ) *lpErrno = NO_ERROR; - - WS_DbgPrint(MID_TRACE, ("Socket: %x\n", Socket)); - return Socket; -} - - -/* - * @unimplemented - */ -INT -WSPAPI -WPUOpenCurrentThread(OUT LPWSATHREADID lpThreadId, - OUT LPINT lpErrno) -{ - UNIMPLEMENTED - - return 0; -} - - -/* - * @unimplemented - */ -INT -WSPAPI -WPUQueryBlockingCallback(IN DWORD dwCatalogEntryId, - OUT LPBLOCKINGCALLBACK FAR* lplpfnCallback, - OUT LPDWORD lpdwContext, - OUT LPINT lpErrno) -{ - UNIMPLEMENTED - - return 0; -} - - -/* - * @unimplemented - */ -INT -WSPAPI -WPUQuerySocketHandleContext(IN SOCKET s, - OUT LPDWORD lpContext, - OUT LPINT lpErrno) -{ - UNIMPLEMENTED - - return 0; -} - - -/* - * @unimplemented - */ -INT -WSPAPI -WPUQueueApc(IN LPWSATHREADID lpThreadId, - IN LPWSAUSERAPC lpfnUserApc, - IN DWORD dwContext, - OUT LPINT lpErrno) -{ - UNIMPLEMENTED - - return 0; -} - - -/* - * @unimplemented - */ -BOOL -WSPAPI -WPUResetEvent(IN WSAEVENT hEvent, - OUT LPINT lpErrno) -{ - UNIMPLEMENTED - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WSPAPI -WPUSetEvent(IN WSAEVENT hEvent, - OUT LPINT lpErrno) -{ - UNIMPLEMENTED - - return FALSE; -} - -/* EOF */ diff --git a/dll/win32/ws2_32/tests/setup.c b/dll/win32/ws2_32/tests/setup.c deleted file mode 100644 index 9a715f66cb8..00000000000 --- a/dll/win32/ws2_32/tests/setup.c +++ /dev/null @@ -1,13 +0,0 @@ -#include -#include "regtests.h" - -extern BOOL -WINAPI -DllMain(HANDLE hInstDll, - ULONG dwReason, - LPVOID lpReserved); - -_SetupOnce() -{ - DllMain(NULL, DLL_PROCESS_ATTACH, NULL); -} diff --git a/dll/win32/ws2_32/tests/stubs.tst b/dll/win32/ws2_32/tests/stubs.tst deleted file mode 100644 index d94069db53e..00000000000 --- a/dll/win32/ws2_32/tests/stubs.tst +++ /dev/null @@ -1,19 +0,0 @@ -kernel32.dll CreateEventW@16 -kernel32.dll InitializeCriticalSection@4 -kernel32.dll DeleteCriticalSection@4 -kernel32.dll EnterCriticalSection@4 -kernel32.dll ExitProcess@4 -kernel32.dll FreeLibrary@4 -kernel32.dll GetLastError@0 -kernel32.dll GetProcAddress@8 -kernel32.dll GetProcessHeap@0 -ntdll.dll HeapAlloc@12=RtlAllocateHeap -ntdll.dll HeapFree@12=RtlFreeHeap -kernel32.dll LeaveCriticalSection@4 -kernel32.dll LoadLibraryW@4 -kernel32.dll lstrcpyA@8 -ntdll.dll ResetEvent@4 -ntdll.dll SetEvent@4 -kernel32.dll Sleep@4 -ntdll.dll WaitForMultipleObjectsEx@20 -kernel32.dll CloseHandle@4 diff --git a/dll/win32/ws2_32/tests/tests/WinsockEvent.c b/dll/win32/ws2_32/tests/tests/WinsockEvent.c deleted file mode 100644 index 63bad7598e3..00000000000 --- a/dll/win32/ws2_32/tests/tests/WinsockEvent.c +++ /dev/null @@ -1,83 +0,0 @@ -#include -#include -#include "regtests.h" - -#define TestHandle (HANDLE) 1 - -static BOOL CloseHandleSuccessCalled = FALSE; - -static BOOL WINAPI -MockCloseHandleSuccess(HANDLE hObject) -{ - CloseHandleSuccessCalled = TRUE; - _AssertEqualValue(TestHandle, hObject); - return TRUE; -} - -static HOOK HooksSuccess[] = -{ - {"CloseHandle", MockCloseHandleSuccess}, - {NULL, NULL} -}; - -static void -TestWSACloseEventSuccess() -{ - BOOL result; - - _SetHooks(HooksSuccess); - result = WSACloseEvent(TestHandle); - _AssertTrue(result); - _AssertEqualValue(NO_ERROR, WSAGetLastError()); - _AssertTrue(CloseHandleSuccessCalled); - _UnsetAllHooks(); -} - - -static BOOL CloseHandleFailureCalled = FALSE; - -static BOOL WINAPI -MockCloseHandleFailure(HANDLE hObject) -{ - CloseHandleFailureCalled = TRUE; - return FALSE; -} - -static HOOK HooksFailure[] = -{ - {"CloseHandle", MockCloseHandleFailure}, - {NULL, NULL} -}; - -static void -TestWSACloseEventFailure() -{ - BOOL result; - - _SetHooks(HooksFailure); - result = WSACloseEvent(TestHandle); - _AssertFalse(result); - _AssertEqualValue(WSA_INVALID_HANDLE, WSAGetLastError()); - _AssertTrue(CloseHandleFailureCalled); - _UnsetAllHooks(); -} - - -static void -TestWSACloseEvent() -{ - TestWSACloseEventSuccess(); - TestWSACloseEventFailure(); -} - -static void -RunTest() -{ - WSADATA WSAData; - - WSAStartup(MAKEWORD(2, 0), &WSAData); - TestWSACloseEvent(); - WSACleanup(); -} - -_Dispatcher(WinsockeventTest, "Winsock 2 event") diff --git a/dll/win32/ws2_32/ws2_32.rbuild b/dll/win32/ws2_32/ws2_32.rbuild deleted file mode 100644 index 849ed1c88e0..00000000000 --- a/dll/win32/ws2_32/ws2_32.rbuild +++ /dev/null @@ -1,29 +0,0 @@ - - - include - include/reactos/wine - - wine - ntdll - kernel32 - user32 - advapi32 - dnsapi - - ws2_32.h - - - bsd.c - catalog.c - dllmain.c - event.c - handle.c - ns.c - sndrcv.c - stubs.c - upcall.c - async.c - - ws2_32.rc - - diff --git a/dll/win32/ws2_32/ws2_32.rc b/dll/win32/ws2_32/ws2_32.rc deleted file mode 100644 index cb16cfa3cba..00000000000 --- a/dll/win32/ws2_32/ws2_32.rc +++ /dev/null @@ -1,7 +0,0 @@ -/* $Id$ */ - -#define REACTOS_VERSION_DLL -#define REACTOS_STR_FILE_DESCRIPTION "Windows Sockets 2 DLL\0" -#define REACTOS_STR_INTERNAL_NAME "ws2_32\0" -#define REACTOS_STR_ORIGINAL_FILENAME "ws2_32.dll\0" -#include diff --git a/dll/win32/ws2_32/ws2_32.spec b/dll/win32/ws2_32/ws2_32.spec deleted file mode 100644 index f36ddcafd46..00000000000 --- a/dll/win32/ws2_32/ws2_32.spec +++ /dev/null @@ -1,119 +0,0 @@ -1 stdcall accept(long ptr ptr) -2 stdcall bind(long ptr long) -3 stdcall closesocket(long) -4 stdcall connect(long ptr long) -5 stdcall getpeername(long ptr ptr) -6 stdcall getsockname(long ptr ptr) -7 stdcall getsockopt(long long long ptr ptr) -8 stdcall htonl(long) -9 stdcall htons(long) -10 stdcall ioctlsocket(long long ptr) -11 stdcall inet_addr(str) -12 stdcall inet_ntoa(ptr) -13 stdcall listen(long long) -14 stdcall ntohl(long) -15 stdcall ntohs(long) -16 stdcall recv(long ptr long long) -17 stdcall recvfrom(long ptr long long ptr ptr) -18 stdcall select(long ptr ptr ptr ptr) -19 stdcall send(long ptr long long) -20 stdcall sendto(long ptr long long ptr long) -21 stdcall setsockopt(long long long ptr long) -22 stdcall shutdown(long long) -23 stdcall socket(long long long) -51 stdcall gethostbyaddr(ptr long long) -52 stdcall gethostbyname(str) -53 stdcall getprotobyname(str) -54 stdcall getprotobynumber(long) -55 stdcall getservbyname(str str) -56 stdcall getservbyport(long str) -57 stdcall gethostname(ptr long) - -101 stdcall WSAAsyncSelect(long long long long) -102 stdcall WSAAsyncGetHostByAddr(long long ptr long long ptr long) -103 stdcall WSAAsyncGetHostByName(long long str ptr long) -104 stdcall WSAAsyncGetProtoByNumber(long long long ptr long) -105 stdcall WSAAsyncGetProtoByName(long long str ptr long) -106 stdcall WSAAsyncGetServByPort(long long long str ptr long) -107 stdcall WSAAsyncGetServByName(long long str str ptr long) -108 stdcall WSACancelAsyncRequest(long) -109 stdcall WSASetBlockingHook(ptr) -110 stdcall WSAUnhookBlockingHook() -111 stdcall WSAGetLastError() -112 stdcall WSASetLastError(long) -113 stdcall WSACancelBlockingCall() -114 stdcall WSAIsBlocking() -115 stdcall WSAStartup(long ptr) -116 stdcall WSACleanup() - -151 stdcall __WSAFDIsSet(long ptr) - -500 stub WEP - -@ stdcall GetAddrInfoW(wstr wstr ptr ptr) -@ stdcall WSApSetPostRoutine(ptr) -@ stdcall WPUCompleteOverlappedRequest(long ptr long long ptr) -@ stdcall WSAAccept(long ptr ptr ptr long) -@ stdcall WSAAddressToStringA(ptr long ptr ptr ptr) -@ stdcall WSAAddressToStringW(ptr long ptr ptr ptr) -@ stdcall WSACloseEvent(long) -@ stdcall WSAConnect(long ptr long ptr ptr ptr ptr) -@ stdcall WSACreateEvent () -@ stdcall WSADuplicateSocketA(long long ptr) -@ stdcall WSADuplicateSocketW(long long ptr) -@ stdcall WSAEnumNameSpaceProvidersA(ptr ptr) -@ stdcall WSAEnumNameSpaceProvidersW(ptr ptr) -@ stdcall WSAEnumNetworkEvents(long long ptr) -@ stdcall WSAEnumProtocolsA(ptr ptr ptr) -@ stdcall WSAEnumProtocolsW(ptr ptr ptr) -@ stdcall WSAEventSelect(long long long) -@ stdcall WSAGetOverlappedResult(long ptr ptr long ptr) -@ stdcall WSAGetQOSByName(long ptr ptr) -@ stdcall WSAGetServiceClassInfoA(ptr ptr ptr ptr) -@ stdcall WSAGetServiceClassInfoW(ptr ptr ptr ptr) -@ stdcall WSAGetServiceClassNameByClassIdA(ptr ptr ptr) -@ stdcall WSAGetServiceClassNameByClassIdW(ptr ptr ptr) -@ stdcall WSAHtonl(long long ptr) -@ stdcall WSAHtons(long long ptr) -@ stdcall WSAInstallServiceClassA(ptr) -@ stdcall WSAInstallServiceClassW(ptr) -@ stdcall WSAIoctl(long long ptr long ptr long ptr ptr ptr) -@ stdcall WSAJoinLeaf(long ptr long ptr ptr ptr ptr long) -@ stdcall WSALookupServiceBeginA(ptr long ptr) -@ stdcall WSALookupServiceBeginW(ptr long ptr) -@ stdcall WSALookupServiceEnd(long) -@ stdcall WSALookupServiceNextA(long long ptr ptr) -@ stdcall WSALookupServiceNextW(long long ptr ptr) -@ stub WSANSPIoctl -@ stdcall WSANtohl(long long ptr) -@ stdcall WSANtohs(long long ptr) -@ stdcall WSAProviderConfigChange(ptr ptr ptr) -@ stdcall WSARecv(long ptr long ptr ptr ptr ptr) -@ stdcall WSARecvDisconnect(long ptr) -@ stdcall WSARecvFrom(long ptr long ptr ptr ptr ptr ptr ptr ) -@ stdcall WSARemoveServiceClass(ptr) -@ stdcall WSAResetEvent(long) kernel32.ResetEvent -@ stdcall WSASend(long ptr long ptr long ptr ptr) -@ stdcall WSASendDisconnect(long ptr) -@ stdcall WSASendTo(long ptr long ptr long ptr long ptr ptr) -@ stdcall WSASetEvent(long) kernel32.SetEvent -@ stdcall WSASetServiceA(ptr long long) -@ stdcall WSASetServiceW(ptr long long) -@ stdcall WSASocketA(long long long ptr long long) -@ stdcall WSASocketW(long long long ptr long long) -@ stdcall WSAStringToAddressA(str long ptr ptr ptr) -@ stdcall WSAStringToAddressW(wstr long ptr ptr ptr) -@ stdcall WSAWaitForMultipleEvents(long ptr long long long) kernel32.WaitForMultipleObjectsEx -@ stdcall WSCDeinstallProvider(ptr ptr) -@ stdcall WSCEnableNSProvider(ptr long) -@ stdcall WSCEnumProtocols(ptr ptr ptr ptr) -@ stdcall WSCGetProviderPath(ptr ptr ptr ptr) -@ stdcall WSCInstallNameSpace(wstr wstr long long ptr) -@ stdcall WSCInstallProvider(ptr wstr ptr long ptr) -@ stdcall WSCUnInstallNameSpace(ptr) -@ stub WSCUpdateProvider -@ stub WSCWriteNameSpaceOrder -@ stdcall WSCWriteProviderOrder(ptr long) -@ stdcall freeaddrinfo(ptr) -@ stdcall getaddrinfo(str str ptr ptr) -@ stdcall getnameinfo(ptr long ptr long ptr long long) From fd2b0ac47d768af0f04f843980fcbe9f5a255cfe Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sat, 6 Feb 2010 02:40:26 +0000 Subject: [PATCH 11/24] - New winsock (part 2 of x) - Replace the old mswsock with the new one svn path=/branches/aicom-network-branch/; revision=45449 --- dll/win32/mswsock/dns/addr.c | 260 ++ dll/win32/mswsock/dns/debug.c | 56 + dll/win32/mswsock/dns/dnsaddr.c | 800 +++++ dll/win32/mswsock/dns/dnsutil.c | 56 + dll/win32/mswsock/dns/flatbuf.c | 464 +++ dll/win32/mswsock/dns/hostent.c | 388 +++ dll/win32/mswsock/dns/inc/dnslib.h | 144 + dll/win32/mswsock/dns/inc/dnslibp.h | 2058 ++++++++++++ dll/win32/mswsock/dns/inc/windnsp.h | 168 + dll/win32/mswsock/dns/ip6.c | 56 + dll/win32/mswsock/dns/memory.c | 264 ++ dll/win32/mswsock/dns/name.c | 56 + dll/win32/mswsock/dns/print.c | 56 + dll/win32/mswsock/dns/record.c | 56 + dll/win32/mswsock/dns/rrprint.c | 56 + dll/win32/mswsock/dns/sablob.c | 2580 ++++++++++++++ dll/win32/mswsock/dns/straddr.c | 1848 ++++++++++ dll/win32/mswsock/dns/string.c | 1028 ++++++ dll/win32/mswsock/dns/table.c | 56 + dll/win32/mswsock/dns/utf8.c | 56 + dll/win32/mswsock/extensions.c | 54 - dll/win32/mswsock/msafd/accept.c | 3900 ++++++++++++++++++++++ dll/win32/mswsock/msafd/addrconv.c | 152 + dll/win32/mswsock/msafd/afdsan.c | 56 + dll/win32/mswsock/msafd/async.c | 792 +++++ dll/win32/mswsock/msafd/bind.c | 852 +++++ dll/win32/mswsock/msafd/connect.c | 2712 +++++++++++++++ dll/win32/mswsock/msafd/eventsel.c | 1708 ++++++++++ dll/win32/mswsock/msafd/getname.c | 980 ++++++ dll/win32/mswsock/msafd/helper.c | 2780 ++++++++++++++++ dll/win32/mswsock/msafd/listen.c | 564 ++++ dll/win32/mswsock/msafd/nspeprot.c | 328 ++ dll/win32/mswsock/msafd/proc.c | 4632 ++++++++++++++++++++++++++ dll/win32/mswsock/msafd/recv.c | 2248 +++++++++++++ dll/win32/mswsock/msafd/sanaccpt.c | 56 + dll/win32/mswsock/msafd/sanconn.c | 56 + dll/win32/mswsock/msafd/sanflow.c | 56 + dll/win32/mswsock/msafd/sanlistn.c | 56 + dll/win32/mswsock/msafd/sanprov.c | 240 ++ dll/win32/mswsock/msafd/sanrdma.c | 56 + dll/win32/mswsock/msafd/sanrecv.c | 56 + dll/win32/mswsock/msafd/sansend.c | 56 + dll/win32/mswsock/msafd/sanshutd.c | 56 + dll/win32/mswsock/msafd/sansock.c | 56 + dll/win32/mswsock/msafd/santf.c | 56 + dll/win32/mswsock/msafd/sanutil.c | 56 + dll/win32/mswsock/msafd/select.c | 3952 ++++++++++++++++++++++ dll/win32/mswsock/msafd/send.c | 2340 +++++++++++++ dll/win32/mswsock/msafd/shutdown.c | 696 ++++ dll/win32/mswsock/msafd/sockerr.c | 552 +++ dll/win32/mswsock/msafd/socket.c | 3196 ++++++++++++++++++ dll/win32/mswsock/msafd/sockopt.c | 2356 +++++++++++++ dll/win32/mswsock/msafd/spi.c | 884 +++++ dll/win32/mswsock/msafd/tpackets.c | 56 + dll/win32/mswsock/msafd/tranfile.c | 56 + dll/win32/mswsock/msafd/wspmisc.c | 352 ++ dll/win32/mswsock/mswsock.rbuild | 101 +- dll/win32/mswsock/mswsock/init.c | 816 +++++ dll/win32/mswsock/mswsock/msext.c | 208 ++ dll/win32/mswsock/mswsock/nspgaddr.c | 56 + dll/win32/mswsock/mswsock/nspmisc.c | 56 + dll/win32/mswsock/mswsock/nspsvc.c | 56 + dll/win32/mswsock/mswsock/nsptcpip.c | 56 + dll/win32/mswsock/mswsock/nsputil.c | 56 + dll/win32/mswsock/mswsock/proc.c | 456 +++ dll/win32/mswsock/mswsock/recvex.c | 56 + dll/win32/mswsock/mswsock/setup.c | 56 + dll/win32/mswsock/mswsock/stubs.c | 1388 ++++++++ dll/win32/mswsock/rnr20/context.c | 648 ++++ dll/win32/mswsock/rnr20/getserv.c | 40 + dll/win32/mswsock/rnr20/init.c | 356 ++ dll/win32/mswsock/rnr20/logit.c | 40 + dll/win32/mswsock/rnr20/lookup.c | 1436 ++++++++ dll/win32/mswsock/rnr20/nbt.c | 56 + dll/win32/mswsock/rnr20/nsp.c | 3776 +++++++++++++++++++++ dll/win32/mswsock/rnr20/oldutil.c | 884 +++++ dll/win32/mswsock/rnr20/proc.c | 176 + dll/win32/mswsock/rnr20/r_comp.c | 40 + dll/win32/mswsock/rnr20/util.c | 128 + dll/win32/mswsock/stubs.c | 517 --- dll/win32/mswsock/wsmobile/lpc.c | 64 + dll/win32/mswsock/wsmobile/nsp.c | 112 + dll/win32/mswsock/wsmobile/service.c | 56 + dll/win32/mswsock/wsmobile/update.c | 56 + 84 files changed, 58730 insertions(+), 576 deletions(-) create mode 100644 dll/win32/mswsock/dns/addr.c create mode 100644 dll/win32/mswsock/dns/debug.c create mode 100644 dll/win32/mswsock/dns/dnsaddr.c create mode 100644 dll/win32/mswsock/dns/dnsutil.c create mode 100644 dll/win32/mswsock/dns/flatbuf.c create mode 100644 dll/win32/mswsock/dns/hostent.c create mode 100644 dll/win32/mswsock/dns/inc/dnslib.h create mode 100644 dll/win32/mswsock/dns/inc/dnslibp.h create mode 100644 dll/win32/mswsock/dns/inc/windnsp.h create mode 100644 dll/win32/mswsock/dns/ip6.c create mode 100644 dll/win32/mswsock/dns/memory.c create mode 100644 dll/win32/mswsock/dns/name.c create mode 100644 dll/win32/mswsock/dns/print.c create mode 100644 dll/win32/mswsock/dns/record.c create mode 100644 dll/win32/mswsock/dns/rrprint.c create mode 100644 dll/win32/mswsock/dns/sablob.c create mode 100644 dll/win32/mswsock/dns/straddr.c create mode 100644 dll/win32/mswsock/dns/string.c create mode 100644 dll/win32/mswsock/dns/table.c create mode 100644 dll/win32/mswsock/dns/utf8.c delete mode 100644 dll/win32/mswsock/extensions.c create mode 100644 dll/win32/mswsock/msafd/accept.c create mode 100644 dll/win32/mswsock/msafd/addrconv.c create mode 100644 dll/win32/mswsock/msafd/afdsan.c create mode 100644 dll/win32/mswsock/msafd/async.c create mode 100644 dll/win32/mswsock/msafd/bind.c create mode 100644 dll/win32/mswsock/msafd/connect.c create mode 100644 dll/win32/mswsock/msafd/eventsel.c create mode 100644 dll/win32/mswsock/msafd/getname.c create mode 100644 dll/win32/mswsock/msafd/helper.c create mode 100644 dll/win32/mswsock/msafd/listen.c create mode 100644 dll/win32/mswsock/msafd/nspeprot.c create mode 100644 dll/win32/mswsock/msafd/proc.c create mode 100644 dll/win32/mswsock/msafd/recv.c create mode 100644 dll/win32/mswsock/msafd/sanaccpt.c create mode 100644 dll/win32/mswsock/msafd/sanconn.c create mode 100644 dll/win32/mswsock/msafd/sanflow.c create mode 100644 dll/win32/mswsock/msafd/sanlistn.c create mode 100644 dll/win32/mswsock/msafd/sanprov.c create mode 100644 dll/win32/mswsock/msafd/sanrdma.c create mode 100644 dll/win32/mswsock/msafd/sanrecv.c create mode 100644 dll/win32/mswsock/msafd/sansend.c create mode 100644 dll/win32/mswsock/msafd/sanshutd.c create mode 100644 dll/win32/mswsock/msafd/sansock.c create mode 100644 dll/win32/mswsock/msafd/santf.c create mode 100644 dll/win32/mswsock/msafd/sanutil.c create mode 100644 dll/win32/mswsock/msafd/select.c create mode 100644 dll/win32/mswsock/msafd/send.c create mode 100644 dll/win32/mswsock/msafd/shutdown.c create mode 100644 dll/win32/mswsock/msafd/sockerr.c create mode 100644 dll/win32/mswsock/msafd/socket.c create mode 100644 dll/win32/mswsock/msafd/sockopt.c create mode 100644 dll/win32/mswsock/msafd/spi.c create mode 100644 dll/win32/mswsock/msafd/tpackets.c create mode 100644 dll/win32/mswsock/msafd/tranfile.c create mode 100644 dll/win32/mswsock/msafd/wspmisc.c create mode 100644 dll/win32/mswsock/mswsock/init.c create mode 100644 dll/win32/mswsock/mswsock/msext.c create mode 100644 dll/win32/mswsock/mswsock/nspgaddr.c create mode 100644 dll/win32/mswsock/mswsock/nspmisc.c create mode 100644 dll/win32/mswsock/mswsock/nspsvc.c create mode 100644 dll/win32/mswsock/mswsock/nsptcpip.c create mode 100644 dll/win32/mswsock/mswsock/nsputil.c create mode 100644 dll/win32/mswsock/mswsock/proc.c create mode 100644 dll/win32/mswsock/mswsock/recvex.c create mode 100644 dll/win32/mswsock/mswsock/setup.c create mode 100644 dll/win32/mswsock/mswsock/stubs.c create mode 100644 dll/win32/mswsock/rnr20/context.c create mode 100644 dll/win32/mswsock/rnr20/getserv.c create mode 100644 dll/win32/mswsock/rnr20/init.c create mode 100644 dll/win32/mswsock/rnr20/logit.c create mode 100644 dll/win32/mswsock/rnr20/lookup.c create mode 100644 dll/win32/mswsock/rnr20/nbt.c create mode 100644 dll/win32/mswsock/rnr20/nsp.c create mode 100644 dll/win32/mswsock/rnr20/oldutil.c create mode 100644 dll/win32/mswsock/rnr20/proc.c create mode 100644 dll/win32/mswsock/rnr20/r_comp.c create mode 100644 dll/win32/mswsock/rnr20/util.c delete mode 100644 dll/win32/mswsock/stubs.c create mode 100644 dll/win32/mswsock/wsmobile/lpc.c create mode 100644 dll/win32/mswsock/wsmobile/nsp.c create mode 100644 dll/win32/mswsock/wsmobile/service.c create mode 100644 dll/win32/mswsock/wsmobile/update.c diff --git a/dll/win32/mswsock/dns/addr.c b/dll/win32/mswsock/dns/addr.c new file mode 100644 index 00000000000..8742b3050cd --- /dev/null +++ b/dll/win32/mswsock/dns/addr.c @@ -0,0 +1,260 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/addr.c + * PURPOSE: Contains the Address Family Information Tables + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +DNS_FAMILY_INFO AddrFamilyTable[3] = +{ + { + AF_INET, + DNS_TYPE_A, + sizeof(IP4_ADDRESS), + sizeof(SOCKADDR_IN), + FIELD_OFFSET(SOCKADDR_IN, sin_addr) + }, + { + AF_INET6, + DNS_TYPE_AAAA, + sizeof(IP6_ADDRESS), + sizeof(SOCKADDR_IN6), + FIELD_OFFSET(SOCKADDR_IN6, sin6_addr) + }, + { + AF_ATM, + DNS_TYPE_ATMA, + sizeof(ATM_ADDRESS), + sizeof(SOCKADDR_ATM), + FIELD_OFFSET(SOCKADDR_ATM, satm_number) + } +}; + +/* FUNCTIONS *****************************************************************/ + +PDNS_FAMILY_INFO +WINAPI +FamilyInfo_GetForFamily(IN WORD AddressFamily) +{ + /* Check which family this is */ + switch (AddressFamily) + { + case AF_INET: + /* Return IPv4 Family Info */ + return &AddrFamilyTable[0]; + + case AF_INET6: + /* Return IPv6 Family Info */ + return &AddrFamilyTable[1]; + + case AF_ATM: + /* Return ATM Family Info */ + return &AddrFamilyTable[2]; + + default: + /* Invalid family */ + return NULL; + } + +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/addr.c + * PURPOSE: Contains the Address Family Information Tables + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +DNS_FAMILY_INFO AddrFamilyTable[3] = +{ + { + AF_INET, + DNS_TYPE_A, + sizeof(IP4_ADDRESS), + sizeof(SOCKADDR_IN), + FIELD_OFFSET(SOCKADDR_IN, sin_addr) + }, + { + AF_INET6, + DNS_TYPE_AAAA, + sizeof(IP6_ADDRESS), + sizeof(SOCKADDR_IN6), + FIELD_OFFSET(SOCKADDR_IN6, sin6_addr) + }, + { + AF_ATM, + DNS_TYPE_ATMA, + sizeof(ATM_ADDRESS), + sizeof(SOCKADDR_ATM), + FIELD_OFFSET(SOCKADDR_ATM, satm_number) + } +}; + +/* FUNCTIONS *****************************************************************/ + +PDNS_FAMILY_INFO +WINAPI +FamilyInfo_GetForFamily(IN WORD AddressFamily) +{ + /* Check which family this is */ + switch (AddressFamily) + { + case AF_INET: + /* Return IPv4 Family Info */ + return &AddrFamilyTable[0]; + + case AF_INET6: + /* Return IPv6 Family Info */ + return &AddrFamilyTable[1]; + + case AF_ATM: + /* Return ATM Family Info */ + return &AddrFamilyTable[2]; + + default: + /* Invalid family */ + return NULL; + } + +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/addr.c + * PURPOSE: Contains the Address Family Information Tables + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +DNS_FAMILY_INFO AddrFamilyTable[3] = +{ + { + AF_INET, + DNS_TYPE_A, + sizeof(IP4_ADDRESS), + sizeof(SOCKADDR_IN), + FIELD_OFFSET(SOCKADDR_IN, sin_addr) + }, + { + AF_INET6, + DNS_TYPE_AAAA, + sizeof(IP6_ADDRESS), + sizeof(SOCKADDR_IN6), + FIELD_OFFSET(SOCKADDR_IN6, sin6_addr) + }, + { + AF_ATM, + DNS_TYPE_ATMA, + sizeof(ATM_ADDRESS), + sizeof(SOCKADDR_ATM), + FIELD_OFFSET(SOCKADDR_ATM, satm_number) + } +}; + +/* FUNCTIONS *****************************************************************/ + +PDNS_FAMILY_INFO +WINAPI +FamilyInfo_GetForFamily(IN WORD AddressFamily) +{ + /* Check which family this is */ + switch (AddressFamily) + { + case AF_INET: + /* Return IPv4 Family Info */ + return &AddrFamilyTable[0]; + + case AF_INET6: + /* Return IPv6 Family Info */ + return &AddrFamilyTable[1]; + + case AF_ATM: + /* Return ATM Family Info */ + return &AddrFamilyTable[2]; + + default: + /* Invalid family */ + return NULL; + } + +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/addr.c + * PURPOSE: Contains the Address Family Information Tables + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +DNS_FAMILY_INFO AddrFamilyTable[3] = +{ + { + AF_INET, + DNS_TYPE_A, + sizeof(IP4_ADDRESS), + sizeof(SOCKADDR_IN), + FIELD_OFFSET(SOCKADDR_IN, sin_addr) + }, + { + AF_INET6, + DNS_TYPE_AAAA, + sizeof(IP6_ADDRESS), + sizeof(SOCKADDR_IN6), + FIELD_OFFSET(SOCKADDR_IN6, sin6_addr) + }, + { + AF_ATM, + DNS_TYPE_ATMA, + sizeof(ATM_ADDRESS), + sizeof(SOCKADDR_ATM), + FIELD_OFFSET(SOCKADDR_ATM, satm_number) + } +}; + +/* FUNCTIONS *****************************************************************/ + +PDNS_FAMILY_INFO +WINAPI +FamilyInfo_GetForFamily(IN WORD AddressFamily) +{ + /* Check which family this is */ + switch (AddressFamily) + { + case AF_INET: + /* Return IPv4 Family Info */ + return &AddrFamilyTable[0]; + + case AF_INET6: + /* Return IPv6 Family Info */ + return &AddrFamilyTable[1]; + + case AF_ATM: + /* Return ATM Family Info */ + return &AddrFamilyTable[2]; + + default: + /* Invalid family */ + return NULL; + } + +} + diff --git a/dll/win32/mswsock/dns/debug.c b/dll/win32/mswsock/dns/debug.c new file mode 100644 index 00000000000..f194e1e9632 --- /dev/null +++ b/dll/win32/mswsock/dns/debug.c @@ -0,0 +1,56 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/debug.c + * PURPOSE: Contains helpful debugging functions for DNSLIB structures. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/debug.c + * PURPOSE: Contains helpful debugging functions for DNSLIB structures. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/debug.c + * PURPOSE: Contains helpful debugging functions for DNSLIB structures. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/debug.c + * PURPOSE: Contains helpful debugging functions for DNSLIB structures. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + diff --git a/dll/win32/mswsock/dns/dnsaddr.c b/dll/win32/mswsock/dns/dnsaddr.c new file mode 100644 index 00000000000..20ebe48b28f --- /dev/null +++ b/dll/win32/mswsock/dns/dnsaddr.c @@ -0,0 +1,800 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/dnsaddr.c + * PURPOSE: Functions dealing with DNS_ADDRESS and DNS_ARRAY addresses. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +PDNS_ARRAY +WINAPI +DnsAddrArray_Create(ULONG Count) +{ + PDNS_ARRAY DnsAddrArray; + + /* Allocate space for the array and the addresses within it */ + DnsAddrArray = Dns_AllocZero(sizeof(DNS_ARRAY) + + (Count * sizeof(DNS_ADDRESS))); + + /* Write the allocated address count */ + if (DnsAddrArray) DnsAddrArray->AllocatedAddresses = Count; + + /* Return it */ + return DnsAddrArray; +} + +VOID +WINAPI +DnsAddrArray_Free(IN PDNS_ARRAY DnsAddrArray) +{ + /* Just free the entire array */ + Dns_Free(DnsAddrArray); +} + +BOOL +WINAPI +DnsAddrArray_AddIp4(IN PDNS_ARRAY DnsAddrArray, + IN IN_ADDR Address, + IN DWORD AddressType) +{ + DNS_ADDRESS DnsAddress; + + /* Build the DNS Address */ + DnsAddr_BuildFromIp4(&DnsAddress, Address, 0); + + /* Add it to the array */ + return DnsAddrArray_AddAddr(DnsAddrArray, &DnsAddress, 0, AddressType); +} + +BOOL +WINAPI +DnsAddrArray_AddAddr(IN PDNS_ARRAY DnsAddrArray, + IN PDNS_ADDRESS DnsAddress, + IN WORD AddressFamily OPTIONAL, + IN DWORD AddressType OPTIONAL) +{ + /* Make sure we have an array */ + if (!DnsAddrArray) return FALSE; + + /* Check if we should validate the Address Family */ + if (AddressFamily) + { + /* Validate it */ + if (AddressFamily != DnsAddress->AddressFamily) return TRUE; + } + + /* Check if we should validate the Address Type */ + if (AddressType) + { + /* Make sure that this array contains this type of addresses */ + if (!DnsAddrArray_ContainsAddr(DnsAddrArray, DnsAddress, AddressType)) + { + /* Won't be adding it */ + return TRUE; + } + } + + /* Make sure we have space in the array */ + if (DnsAddrArray->AllocatedAddresses < DnsAddrArray->UsedAddresses) + { + return FALSE; + } + + /* Now add the address */ + RtlCopyMemory(&DnsAddrArray->Addresses[DnsAddrArray->UsedAddresses], + DnsAddress, + sizeof(DNS_ADDRESS)); + + /* Return success */ + return TRUE; +} + +VOID +WINAPI +DnsAddr_BuildFromIp4(IN PDNS_ADDRESS DnsAddress, + IN IN_ADDR Address, + IN WORD Port) +{ + /* Clear the address */ + RtlZeroMemory(DnsAddress, sizeof(DNS_ADDRESS)); + + /* Write data */ + DnsAddress->Ip4Address.sin_family = AF_INET; + DnsAddress->Ip4Address.sin_port = Port; + DnsAddress->Ip4Address.sin_addr = Address; + DnsAddress->AddressLength = sizeof(SOCKADDR_IN); +} + +VOID +WINAPI +DnsAddr_BuildFromIp6(IN PDNS_ADDRESS DnsAddress, + IN PIN6_ADDR Address, + IN ULONG ScopeId, + IN WORD Port) +{ + /* Clear the address */ + RtlZeroMemory(DnsAddress, sizeof(DNS_ADDRESS)); + + /* Write data */ + DnsAddress->Ip6Address.sin6_family = AF_INET6; + DnsAddress->Ip6Address.sin6_port = Port; + DnsAddress->Ip6Address.sin6_addr = *Address; + DnsAddress->Ip6Address.sin6_scope_id = ScopeId; + DnsAddress->AddressLength = sizeof(SOCKADDR_IN6); +} + +VOID +WINAPI +DnsAddr_BuildFromAtm(IN PDNS_ADDRESS DnsAddress, + IN DWORD AddressType, + IN PVOID AddressData) +{ + ATM_ADDRESS Address; + + /* Clear the address */ + RtlZeroMemory(DnsAddress, sizeof(DNS_ADDRESS)); + + /* Build an ATM Address */ + Address.AddressType = AddressType; + Address.NumofDigits = DNS_ATMA_MAX_ADDR_LENGTH; + RtlCopyMemory(&Address.Addr, AddressData, DNS_ATMA_MAX_ADDR_LENGTH); + + /* Write data */ + DnsAddress->AtmAddress = Address; + DnsAddress->AddressLength = sizeof(ATM_ADDRESS); +} + +BOOLEAN +WINAPI +DnsAddr_BuildFromDnsRecord(IN PDNS_RECORD DnsRecord, + OUT PDNS_ADDRESS DnsAddr) +{ + /* Check what kind of record this is */ + switch(DnsRecord->wType) + { + /* IPv4 */ + case DNS_TYPE_A: + /* Create the DNS Address */ + DnsAddr_BuildFromIp4(DnsAddr, + *(PIN_ADDR)&DnsRecord->Data.A.IpAddress, + 0); + break; + + /* IPv6 */ + case DNS_TYPE_AAAA: + /* Create the DNS Address */ + DnsAddr_BuildFromIp6(DnsAddr, + (PIN6_ADDR)&DnsRecord->Data.AAAA.Ip6Address, + DnsRecord->dwReserved, + 0); + break; + + /* ATM */ + case DNS_TYPE_ATMA: + /* Create the DNS Address */ + DnsAddr_BuildFromAtm(DnsAddr, + DnsRecord->Data.Atma.AddressType, + &DnsRecord->Data.Atma.Address); + break; + } + + /* Done! */ + return TRUE; +} + +BOOL +WINAPI +DnsAddrArray_ContainsAddr(IN PDNS_ARRAY DnsAddrArray, + IN PDNS_ADDRESS DnsAddress, + IN DWORD AddressType) +{ + /* FIXME */ + return TRUE; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/dnsaddr.c + * PURPOSE: Functions dealing with DNS_ADDRESS and DNS_ARRAY addresses. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +PDNS_ARRAY +WINAPI +DnsAddrArray_Create(ULONG Count) +{ + PDNS_ARRAY DnsAddrArray; + + /* Allocate space for the array and the addresses within it */ + DnsAddrArray = Dns_AllocZero(sizeof(DNS_ARRAY) + + (Count * sizeof(DNS_ADDRESS))); + + /* Write the allocated address count */ + if (DnsAddrArray) DnsAddrArray->AllocatedAddresses = Count; + + /* Return it */ + return DnsAddrArray; +} + +VOID +WINAPI +DnsAddrArray_Free(IN PDNS_ARRAY DnsAddrArray) +{ + /* Just free the entire array */ + Dns_Free(DnsAddrArray); +} + +BOOL +WINAPI +DnsAddrArray_AddIp4(IN PDNS_ARRAY DnsAddrArray, + IN IN_ADDR Address, + IN DWORD AddressType) +{ + DNS_ADDRESS DnsAddress; + + /* Build the DNS Address */ + DnsAddr_BuildFromIp4(&DnsAddress, Address, 0); + + /* Add it to the array */ + return DnsAddrArray_AddAddr(DnsAddrArray, &DnsAddress, 0, AddressType); +} + +BOOL +WINAPI +DnsAddrArray_AddAddr(IN PDNS_ARRAY DnsAddrArray, + IN PDNS_ADDRESS DnsAddress, + IN WORD AddressFamily OPTIONAL, + IN DWORD AddressType OPTIONAL) +{ + /* Make sure we have an array */ + if (!DnsAddrArray) return FALSE; + + /* Check if we should validate the Address Family */ + if (AddressFamily) + { + /* Validate it */ + if (AddressFamily != DnsAddress->AddressFamily) return TRUE; + } + + /* Check if we should validate the Address Type */ + if (AddressType) + { + /* Make sure that this array contains this type of addresses */ + if (!DnsAddrArray_ContainsAddr(DnsAddrArray, DnsAddress, AddressType)) + { + /* Won't be adding it */ + return TRUE; + } + } + + /* Make sure we have space in the array */ + if (DnsAddrArray->AllocatedAddresses < DnsAddrArray->UsedAddresses) + { + return FALSE; + } + + /* Now add the address */ + RtlCopyMemory(&DnsAddrArray->Addresses[DnsAddrArray->UsedAddresses], + DnsAddress, + sizeof(DNS_ADDRESS)); + + /* Return success */ + return TRUE; +} + +VOID +WINAPI +DnsAddr_BuildFromIp4(IN PDNS_ADDRESS DnsAddress, + IN IN_ADDR Address, + IN WORD Port) +{ + /* Clear the address */ + RtlZeroMemory(DnsAddress, sizeof(DNS_ADDRESS)); + + /* Write data */ + DnsAddress->Ip4Address.sin_family = AF_INET; + DnsAddress->Ip4Address.sin_port = Port; + DnsAddress->Ip4Address.sin_addr = Address; + DnsAddress->AddressLength = sizeof(SOCKADDR_IN); +} + +VOID +WINAPI +DnsAddr_BuildFromIp6(IN PDNS_ADDRESS DnsAddress, + IN PIN6_ADDR Address, + IN ULONG ScopeId, + IN WORD Port) +{ + /* Clear the address */ + RtlZeroMemory(DnsAddress, sizeof(DNS_ADDRESS)); + + /* Write data */ + DnsAddress->Ip6Address.sin6_family = AF_INET6; + DnsAddress->Ip6Address.sin6_port = Port; + DnsAddress->Ip6Address.sin6_addr = *Address; + DnsAddress->Ip6Address.sin6_scope_id = ScopeId; + DnsAddress->AddressLength = sizeof(SOCKADDR_IN6); +} + +VOID +WINAPI +DnsAddr_BuildFromAtm(IN PDNS_ADDRESS DnsAddress, + IN DWORD AddressType, + IN PVOID AddressData) +{ + ATM_ADDRESS Address; + + /* Clear the address */ + RtlZeroMemory(DnsAddress, sizeof(DNS_ADDRESS)); + + /* Build an ATM Address */ + Address.AddressType = AddressType; + Address.NumofDigits = DNS_ATMA_MAX_ADDR_LENGTH; + RtlCopyMemory(&Address.Addr, AddressData, DNS_ATMA_MAX_ADDR_LENGTH); + + /* Write data */ + DnsAddress->AtmAddress = Address; + DnsAddress->AddressLength = sizeof(ATM_ADDRESS); +} + +BOOLEAN +WINAPI +DnsAddr_BuildFromDnsRecord(IN PDNS_RECORD DnsRecord, + OUT PDNS_ADDRESS DnsAddr) +{ + /* Check what kind of record this is */ + switch(DnsRecord->wType) + { + /* IPv4 */ + case DNS_TYPE_A: + /* Create the DNS Address */ + DnsAddr_BuildFromIp4(DnsAddr, + *(PIN_ADDR)&DnsRecord->Data.A.IpAddress, + 0); + break; + + /* IPv6 */ + case DNS_TYPE_AAAA: + /* Create the DNS Address */ + DnsAddr_BuildFromIp6(DnsAddr, + (PIN6_ADDR)&DnsRecord->Data.AAAA.Ip6Address, + DnsRecord->dwReserved, + 0); + break; + + /* ATM */ + case DNS_TYPE_ATMA: + /* Create the DNS Address */ + DnsAddr_BuildFromAtm(DnsAddr, + DnsRecord->Data.Atma.AddressType, + &DnsRecord->Data.Atma.Address); + break; + } + + /* Done! */ + return TRUE; +} + +BOOL +WINAPI +DnsAddrArray_ContainsAddr(IN PDNS_ARRAY DnsAddrArray, + IN PDNS_ADDRESS DnsAddress, + IN DWORD AddressType) +{ + /* FIXME */ + return TRUE; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/dnsaddr.c + * PURPOSE: Functions dealing with DNS_ADDRESS and DNS_ARRAY addresses. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +PDNS_ARRAY +WINAPI +DnsAddrArray_Create(ULONG Count) +{ + PDNS_ARRAY DnsAddrArray; + + /* Allocate space for the array and the addresses within it */ + DnsAddrArray = Dns_AllocZero(sizeof(DNS_ARRAY) + + (Count * sizeof(DNS_ADDRESS))); + + /* Write the allocated address count */ + if (DnsAddrArray) DnsAddrArray->AllocatedAddresses = Count; + + /* Return it */ + return DnsAddrArray; +} + +VOID +WINAPI +DnsAddrArray_Free(IN PDNS_ARRAY DnsAddrArray) +{ + /* Just free the entire array */ + Dns_Free(DnsAddrArray); +} + +BOOL +WINAPI +DnsAddrArray_AddIp4(IN PDNS_ARRAY DnsAddrArray, + IN IN_ADDR Address, + IN DWORD AddressType) +{ + DNS_ADDRESS DnsAddress; + + /* Build the DNS Address */ + DnsAddr_BuildFromIp4(&DnsAddress, Address, 0); + + /* Add it to the array */ + return DnsAddrArray_AddAddr(DnsAddrArray, &DnsAddress, 0, AddressType); +} + +BOOL +WINAPI +DnsAddrArray_AddAddr(IN PDNS_ARRAY DnsAddrArray, + IN PDNS_ADDRESS DnsAddress, + IN WORD AddressFamily OPTIONAL, + IN DWORD AddressType OPTIONAL) +{ + /* Make sure we have an array */ + if (!DnsAddrArray) return FALSE; + + /* Check if we should validate the Address Family */ + if (AddressFamily) + { + /* Validate it */ + if (AddressFamily != DnsAddress->AddressFamily) return TRUE; + } + + /* Check if we should validate the Address Type */ + if (AddressType) + { + /* Make sure that this array contains this type of addresses */ + if (!DnsAddrArray_ContainsAddr(DnsAddrArray, DnsAddress, AddressType)) + { + /* Won't be adding it */ + return TRUE; + } + } + + /* Make sure we have space in the array */ + if (DnsAddrArray->AllocatedAddresses < DnsAddrArray->UsedAddresses) + { + return FALSE; + } + + /* Now add the address */ + RtlCopyMemory(&DnsAddrArray->Addresses[DnsAddrArray->UsedAddresses], + DnsAddress, + sizeof(DNS_ADDRESS)); + + /* Return success */ + return TRUE; +} + +VOID +WINAPI +DnsAddr_BuildFromIp4(IN PDNS_ADDRESS DnsAddress, + IN IN_ADDR Address, + IN WORD Port) +{ + /* Clear the address */ + RtlZeroMemory(DnsAddress, sizeof(DNS_ADDRESS)); + + /* Write data */ + DnsAddress->Ip4Address.sin_family = AF_INET; + DnsAddress->Ip4Address.sin_port = Port; + DnsAddress->Ip4Address.sin_addr = Address; + DnsAddress->AddressLength = sizeof(SOCKADDR_IN); +} + +VOID +WINAPI +DnsAddr_BuildFromIp6(IN PDNS_ADDRESS DnsAddress, + IN PIN6_ADDR Address, + IN ULONG ScopeId, + IN WORD Port) +{ + /* Clear the address */ + RtlZeroMemory(DnsAddress, sizeof(DNS_ADDRESS)); + + /* Write data */ + DnsAddress->Ip6Address.sin6_family = AF_INET6; + DnsAddress->Ip6Address.sin6_port = Port; + DnsAddress->Ip6Address.sin6_addr = *Address; + DnsAddress->Ip6Address.sin6_scope_id = ScopeId; + DnsAddress->AddressLength = sizeof(SOCKADDR_IN6); +} + +VOID +WINAPI +DnsAddr_BuildFromAtm(IN PDNS_ADDRESS DnsAddress, + IN DWORD AddressType, + IN PVOID AddressData) +{ + ATM_ADDRESS Address; + + /* Clear the address */ + RtlZeroMemory(DnsAddress, sizeof(DNS_ADDRESS)); + + /* Build an ATM Address */ + Address.AddressType = AddressType; + Address.NumofDigits = DNS_ATMA_MAX_ADDR_LENGTH; + RtlCopyMemory(&Address.Addr, AddressData, DNS_ATMA_MAX_ADDR_LENGTH); + + /* Write data */ + DnsAddress->AtmAddress = Address; + DnsAddress->AddressLength = sizeof(ATM_ADDRESS); +} + +BOOLEAN +WINAPI +DnsAddr_BuildFromDnsRecord(IN PDNS_RECORD DnsRecord, + OUT PDNS_ADDRESS DnsAddr) +{ + /* Check what kind of record this is */ + switch(DnsRecord->wType) + { + /* IPv4 */ + case DNS_TYPE_A: + /* Create the DNS Address */ + DnsAddr_BuildFromIp4(DnsAddr, + *(PIN_ADDR)&DnsRecord->Data.A.IpAddress, + 0); + break; + + /* IPv6 */ + case DNS_TYPE_AAAA: + /* Create the DNS Address */ + DnsAddr_BuildFromIp6(DnsAddr, + (PIN6_ADDR)&DnsRecord->Data.AAAA.Ip6Address, + DnsRecord->dwReserved, + 0); + break; + + /* ATM */ + case DNS_TYPE_ATMA: + /* Create the DNS Address */ + DnsAddr_BuildFromAtm(DnsAddr, + DnsRecord->Data.Atma.AddressType, + &DnsRecord->Data.Atma.Address); + break; + } + + /* Done! */ + return TRUE; +} + +BOOL +WINAPI +DnsAddrArray_ContainsAddr(IN PDNS_ARRAY DnsAddrArray, + IN PDNS_ADDRESS DnsAddress, + IN DWORD AddressType) +{ + /* FIXME */ + return TRUE; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/dnsaddr.c + * PURPOSE: Functions dealing with DNS_ADDRESS and DNS_ARRAY addresses. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +PDNS_ARRAY +WINAPI +DnsAddrArray_Create(ULONG Count) +{ + PDNS_ARRAY DnsAddrArray; + + /* Allocate space for the array and the addresses within it */ + DnsAddrArray = Dns_AllocZero(sizeof(DNS_ARRAY) + + (Count * sizeof(DNS_ADDRESS))); + + /* Write the allocated address count */ + if (DnsAddrArray) DnsAddrArray->AllocatedAddresses = Count; + + /* Return it */ + return DnsAddrArray; +} + +VOID +WINAPI +DnsAddrArray_Free(IN PDNS_ARRAY DnsAddrArray) +{ + /* Just free the entire array */ + Dns_Free(DnsAddrArray); +} + +BOOL +WINAPI +DnsAddrArray_AddIp4(IN PDNS_ARRAY DnsAddrArray, + IN IN_ADDR Address, + IN DWORD AddressType) +{ + DNS_ADDRESS DnsAddress; + + /* Build the DNS Address */ + DnsAddr_BuildFromIp4(&DnsAddress, Address, 0); + + /* Add it to the array */ + return DnsAddrArray_AddAddr(DnsAddrArray, &DnsAddress, 0, AddressType); +} + +BOOL +WINAPI +DnsAddrArray_AddAddr(IN PDNS_ARRAY DnsAddrArray, + IN PDNS_ADDRESS DnsAddress, + IN WORD AddressFamily OPTIONAL, + IN DWORD AddressType OPTIONAL) +{ + /* Make sure we have an array */ + if (!DnsAddrArray) return FALSE; + + /* Check if we should validate the Address Family */ + if (AddressFamily) + { + /* Validate it */ + if (AddressFamily != DnsAddress->AddressFamily) return TRUE; + } + + /* Check if we should validate the Address Type */ + if (AddressType) + { + /* Make sure that this array contains this type of addresses */ + if (!DnsAddrArray_ContainsAddr(DnsAddrArray, DnsAddress, AddressType)) + { + /* Won't be adding it */ + return TRUE; + } + } + + /* Make sure we have space in the array */ + if (DnsAddrArray->AllocatedAddresses < DnsAddrArray->UsedAddresses) + { + return FALSE; + } + + /* Now add the address */ + RtlCopyMemory(&DnsAddrArray->Addresses[DnsAddrArray->UsedAddresses], + DnsAddress, + sizeof(DNS_ADDRESS)); + + /* Return success */ + return TRUE; +} + +VOID +WINAPI +DnsAddr_BuildFromIp4(IN PDNS_ADDRESS DnsAddress, + IN IN_ADDR Address, + IN WORD Port) +{ + /* Clear the address */ + RtlZeroMemory(DnsAddress, sizeof(DNS_ADDRESS)); + + /* Write data */ + DnsAddress->Ip4Address.sin_family = AF_INET; + DnsAddress->Ip4Address.sin_port = Port; + DnsAddress->Ip4Address.sin_addr = Address; + DnsAddress->AddressLength = sizeof(SOCKADDR_IN); +} + +VOID +WINAPI +DnsAddr_BuildFromIp6(IN PDNS_ADDRESS DnsAddress, + IN PIN6_ADDR Address, + IN ULONG ScopeId, + IN WORD Port) +{ + /* Clear the address */ + RtlZeroMemory(DnsAddress, sizeof(DNS_ADDRESS)); + + /* Write data */ + DnsAddress->Ip6Address.sin6_family = AF_INET6; + DnsAddress->Ip6Address.sin6_port = Port; + DnsAddress->Ip6Address.sin6_addr = *Address; + DnsAddress->Ip6Address.sin6_scope_id = ScopeId; + DnsAddress->AddressLength = sizeof(SOCKADDR_IN6); +} + +VOID +WINAPI +DnsAddr_BuildFromAtm(IN PDNS_ADDRESS DnsAddress, + IN DWORD AddressType, + IN PVOID AddressData) +{ + ATM_ADDRESS Address; + + /* Clear the address */ + RtlZeroMemory(DnsAddress, sizeof(DNS_ADDRESS)); + + /* Build an ATM Address */ + Address.AddressType = AddressType; + Address.NumofDigits = DNS_ATMA_MAX_ADDR_LENGTH; + RtlCopyMemory(&Address.Addr, AddressData, DNS_ATMA_MAX_ADDR_LENGTH); + + /* Write data */ + DnsAddress->AtmAddress = Address; + DnsAddress->AddressLength = sizeof(ATM_ADDRESS); +} + +BOOLEAN +WINAPI +DnsAddr_BuildFromDnsRecord(IN PDNS_RECORD DnsRecord, + OUT PDNS_ADDRESS DnsAddr) +{ + /* Check what kind of record this is */ + switch(DnsRecord->wType) + { + /* IPv4 */ + case DNS_TYPE_A: + /* Create the DNS Address */ + DnsAddr_BuildFromIp4(DnsAddr, + *(PIN_ADDR)&DnsRecord->Data.A.IpAddress, + 0); + break; + + /* IPv6 */ + case DNS_TYPE_AAAA: + /* Create the DNS Address */ + DnsAddr_BuildFromIp6(DnsAddr, + (PIN6_ADDR)&DnsRecord->Data.AAAA.Ip6Address, + DnsRecord->dwReserved, + 0); + break; + + /* ATM */ + case DNS_TYPE_ATMA: + /* Create the DNS Address */ + DnsAddr_BuildFromAtm(DnsAddr, + DnsRecord->Data.Atma.AddressType, + &DnsRecord->Data.Atma.Address); + break; + } + + /* Done! */ + return TRUE; +} + +BOOL +WINAPI +DnsAddrArray_ContainsAddr(IN PDNS_ARRAY DnsAddrArray, + IN PDNS_ADDRESS DnsAddress, + IN DWORD AddressType) +{ + /* FIXME */ + return TRUE; +} + diff --git a/dll/win32/mswsock/dns/dnsutil.c b/dll/win32/mswsock/dns/dnsutil.c new file mode 100644 index 00000000000..0830457b586 --- /dev/null +++ b/dll/win32/mswsock/dns/dnsutil.c @@ -0,0 +1,56 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/dnsutil.c + * PURPOSE: Contains misc. DNS utility functions, like DNS_STATUS->String. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/dnsutil.c + * PURPOSE: Contains misc. DNS utility functions, like DNS_STATUS->String. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/dnsutil.c + * PURPOSE: Contains misc. DNS utility functions, like DNS_STATUS->String. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/dnsutil.c + * PURPOSE: Contains misc. DNS utility functions, like DNS_STATUS->String. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + diff --git a/dll/win32/mswsock/dns/flatbuf.c b/dll/win32/mswsock/dns/flatbuf.c new file mode 100644 index 00000000000..6d33b21f71e --- /dev/null +++ b/dll/win32/mswsock/dns/flatbuf.c @@ -0,0 +1,464 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/flatbuf.c + * PURPOSE: Functions for managing the Flat Buffer Implementation (FLATBUF) + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +VOID +WINAPI +FlatBuf_Init(IN PFLATBUFF FlatBuffer, + IN PVOID Buffer, + IN SIZE_T Size) +{ + /* Set up the Flat Buffer start, current and ending position */ + FlatBuffer->Buffer = Buffer; + FlatBuffer->BufferPos = (ULONG_PTR)Buffer; + FlatBuffer->BufferEnd = (PVOID)(FlatBuffer->BufferPos + Size); + + /* Setup the current size and the available size */ + FlatBuffer->BufferSize = FlatBuffer->BufferFreeSize = Size; +} + +PVOID +WINAPI +FlatBuf_Arg_Reserve(IN OUT PULONG_PTR Position, + IN OUT PSIZE_T FreeSize, + IN SIZE_T Size, + IN ULONG Align) +{ + ULONG_PTR NewPosition, OldPosition = *Position; + SIZE_T NewFreeSize = *FreeSize; + + /* Start by aligning our position */ + if (Align) OldPosition += (Align - 1) & ~Align; + + /* Update it */ + NewPosition = OldPosition + Size; + + /* Update Free Size */ + NewFreeSize += (OldPosition - NewPosition); + + /* Save new values */ + *Position = NewPosition; + *FreeSize = NewFreeSize; + + /* Check if we're out of space or not */ + if (NewFreeSize > 0) return (PVOID)OldPosition; + return NULL; +} + +PVOID +WINAPI +FlatBuf_Arg_CopyMemory(IN OUT PULONG_PTR Position, + IN OUT PSIZE_T FreeSize, + IN PVOID Buffer, + IN SIZE_T Size, + IN ULONG Align) +{ + PVOID Destination; + + /* First reserve the memory */ + Destination = FlatBuf_Arg_Reserve(Position, FreeSize, Size, Align); + if (Destination) + { + /* We have space, do the copy */ + RtlCopyMemory(Destination, Buffer, Size); + } + + /* Return the pointer to the data */ + return Destination; +} + +PVOID +WINAPI +FlatBuf_Arg_WriteString(IN OUT PULONG_PTR Position, + IN OUT PSIZE_T FreeSize, + IN PVOID String, + IN BOOLEAN IsUnicode) +{ + PVOID Destination; + SIZE_T StringLength; + ULONG Align; + + /* Calculate the string length */ + if (IsUnicode) + { + /* Get the length in bytes and use WCHAR alignment */ + StringLength = (wcslen((LPWSTR)String) + 1) * sizeof(WCHAR); + Align = sizeof(WCHAR); + } + else + { + /* Get the length in bytes and use CHAR alignment */ + StringLength = strlen((LPSTR)String) + 1; + Align = sizeof(CHAR); + } + + /* Now reserve the memory */ + Destination = FlatBuf_Arg_Reserve(Position, FreeSize, StringLength, Align); + if (Destination) + { + /* We have space, do the copy */ + RtlCopyMemory(Destination, String, StringLength); + } + + /* Return the pointer to the data */ + return Destination; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/flatbuf.c + * PURPOSE: Functions for managing the Flat Buffer Implementation (FLATBUF) + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +VOID +WINAPI +FlatBuf_Init(IN PFLATBUFF FlatBuffer, + IN PVOID Buffer, + IN SIZE_T Size) +{ + /* Set up the Flat Buffer start, current and ending position */ + FlatBuffer->Buffer = Buffer; + FlatBuffer->BufferPos = (ULONG_PTR)Buffer; + FlatBuffer->BufferEnd = (PVOID)(FlatBuffer->BufferPos + Size); + + /* Setup the current size and the available size */ + FlatBuffer->BufferSize = FlatBuffer->BufferFreeSize = Size; +} + +PVOID +WINAPI +FlatBuf_Arg_Reserve(IN OUT PULONG_PTR Position, + IN OUT PSIZE_T FreeSize, + IN SIZE_T Size, + IN ULONG Align) +{ + ULONG_PTR NewPosition, OldPosition = *Position; + SIZE_T NewFreeSize = *FreeSize; + + /* Start by aligning our position */ + if (Align) OldPosition += (Align - 1) & ~Align; + + /* Update it */ + NewPosition = OldPosition + Size; + + /* Update Free Size */ + NewFreeSize += (OldPosition - NewPosition); + + /* Save new values */ + *Position = NewPosition; + *FreeSize = NewFreeSize; + + /* Check if we're out of space or not */ + if (NewFreeSize > 0) return (PVOID)OldPosition; + return NULL; +} + +PVOID +WINAPI +FlatBuf_Arg_CopyMemory(IN OUT PULONG_PTR Position, + IN OUT PSIZE_T FreeSize, + IN PVOID Buffer, + IN SIZE_T Size, + IN ULONG Align) +{ + PVOID Destination; + + /* First reserve the memory */ + Destination = FlatBuf_Arg_Reserve(Position, FreeSize, Size, Align); + if (Destination) + { + /* We have space, do the copy */ + RtlCopyMemory(Destination, Buffer, Size); + } + + /* Return the pointer to the data */ + return Destination; +} + +PVOID +WINAPI +FlatBuf_Arg_WriteString(IN OUT PULONG_PTR Position, + IN OUT PSIZE_T FreeSize, + IN PVOID String, + IN BOOLEAN IsUnicode) +{ + PVOID Destination; + SIZE_T StringLength; + ULONG Align; + + /* Calculate the string length */ + if (IsUnicode) + { + /* Get the length in bytes and use WCHAR alignment */ + StringLength = (wcslen((LPWSTR)String) + 1) * sizeof(WCHAR); + Align = sizeof(WCHAR); + } + else + { + /* Get the length in bytes and use CHAR alignment */ + StringLength = strlen((LPSTR)String) + 1; + Align = sizeof(CHAR); + } + + /* Now reserve the memory */ + Destination = FlatBuf_Arg_Reserve(Position, FreeSize, StringLength, Align); + if (Destination) + { + /* We have space, do the copy */ + RtlCopyMemory(Destination, String, StringLength); + } + + /* Return the pointer to the data */ + return Destination; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/flatbuf.c + * PURPOSE: Functions for managing the Flat Buffer Implementation (FLATBUF) + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +VOID +WINAPI +FlatBuf_Init(IN PFLATBUFF FlatBuffer, + IN PVOID Buffer, + IN SIZE_T Size) +{ + /* Set up the Flat Buffer start, current and ending position */ + FlatBuffer->Buffer = Buffer; + FlatBuffer->BufferPos = (ULONG_PTR)Buffer; + FlatBuffer->BufferEnd = (PVOID)(FlatBuffer->BufferPos + Size); + + /* Setup the current size and the available size */ + FlatBuffer->BufferSize = FlatBuffer->BufferFreeSize = Size; +} + +PVOID +WINAPI +FlatBuf_Arg_Reserve(IN OUT PULONG_PTR Position, + IN OUT PSIZE_T FreeSize, + IN SIZE_T Size, + IN ULONG Align) +{ + ULONG_PTR NewPosition, OldPosition = *Position; + SIZE_T NewFreeSize = *FreeSize; + + /* Start by aligning our position */ + if (Align) OldPosition += (Align - 1) & ~Align; + + /* Update it */ + NewPosition = OldPosition + Size; + + /* Update Free Size */ + NewFreeSize += (OldPosition - NewPosition); + + /* Save new values */ + *Position = NewPosition; + *FreeSize = NewFreeSize; + + /* Check if we're out of space or not */ + if (NewFreeSize > 0) return (PVOID)OldPosition; + return NULL; +} + +PVOID +WINAPI +FlatBuf_Arg_CopyMemory(IN OUT PULONG_PTR Position, + IN OUT PSIZE_T FreeSize, + IN PVOID Buffer, + IN SIZE_T Size, + IN ULONG Align) +{ + PVOID Destination; + + /* First reserve the memory */ + Destination = FlatBuf_Arg_Reserve(Position, FreeSize, Size, Align); + if (Destination) + { + /* We have space, do the copy */ + RtlCopyMemory(Destination, Buffer, Size); + } + + /* Return the pointer to the data */ + return Destination; +} + +PVOID +WINAPI +FlatBuf_Arg_WriteString(IN OUT PULONG_PTR Position, + IN OUT PSIZE_T FreeSize, + IN PVOID String, + IN BOOLEAN IsUnicode) +{ + PVOID Destination; + SIZE_T StringLength; + ULONG Align; + + /* Calculate the string length */ + if (IsUnicode) + { + /* Get the length in bytes and use WCHAR alignment */ + StringLength = (wcslen((LPWSTR)String) + 1) * sizeof(WCHAR); + Align = sizeof(WCHAR); + } + else + { + /* Get the length in bytes and use CHAR alignment */ + StringLength = strlen((LPSTR)String) + 1; + Align = sizeof(CHAR); + } + + /* Now reserve the memory */ + Destination = FlatBuf_Arg_Reserve(Position, FreeSize, StringLength, Align); + if (Destination) + { + /* We have space, do the copy */ + RtlCopyMemory(Destination, String, StringLength); + } + + /* Return the pointer to the data */ + return Destination; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/flatbuf.c + * PURPOSE: Functions for managing the Flat Buffer Implementation (FLATBUF) + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +VOID +WINAPI +FlatBuf_Init(IN PFLATBUFF FlatBuffer, + IN PVOID Buffer, + IN SIZE_T Size) +{ + /* Set up the Flat Buffer start, current and ending position */ + FlatBuffer->Buffer = Buffer; + FlatBuffer->BufferPos = (ULONG_PTR)Buffer; + FlatBuffer->BufferEnd = (PVOID)(FlatBuffer->BufferPos + Size); + + /* Setup the current size and the available size */ + FlatBuffer->BufferSize = FlatBuffer->BufferFreeSize = Size; +} + +PVOID +WINAPI +FlatBuf_Arg_Reserve(IN OUT PULONG_PTR Position, + IN OUT PSIZE_T FreeSize, + IN SIZE_T Size, + IN ULONG Align) +{ + ULONG_PTR NewPosition, OldPosition = *Position; + SIZE_T NewFreeSize = *FreeSize; + + /* Start by aligning our position */ + if (Align) OldPosition += (Align - 1) & ~Align; + + /* Update it */ + NewPosition = OldPosition + Size; + + /* Update Free Size */ + NewFreeSize += (OldPosition - NewPosition); + + /* Save new values */ + *Position = NewPosition; + *FreeSize = NewFreeSize; + + /* Check if we're out of space or not */ + if (NewFreeSize > 0) return (PVOID)OldPosition; + return NULL; +} + +PVOID +WINAPI +FlatBuf_Arg_CopyMemory(IN OUT PULONG_PTR Position, + IN OUT PSIZE_T FreeSize, + IN PVOID Buffer, + IN SIZE_T Size, + IN ULONG Align) +{ + PVOID Destination; + + /* First reserve the memory */ + Destination = FlatBuf_Arg_Reserve(Position, FreeSize, Size, Align); + if (Destination) + { + /* We have space, do the copy */ + RtlCopyMemory(Destination, Buffer, Size); + } + + /* Return the pointer to the data */ + return Destination; +} + +PVOID +WINAPI +FlatBuf_Arg_WriteString(IN OUT PULONG_PTR Position, + IN OUT PSIZE_T FreeSize, + IN PVOID String, + IN BOOLEAN IsUnicode) +{ + PVOID Destination; + SIZE_T StringLength; + ULONG Align; + + /* Calculate the string length */ + if (IsUnicode) + { + /* Get the length in bytes and use WCHAR alignment */ + StringLength = (wcslen((LPWSTR)String) + 1) * sizeof(WCHAR); + Align = sizeof(WCHAR); + } + else + { + /* Get the length in bytes and use CHAR alignment */ + StringLength = strlen((LPSTR)String) + 1; + Align = sizeof(CHAR); + } + + /* Now reserve the memory */ + Destination = FlatBuf_Arg_Reserve(Position, FreeSize, StringLength, Align); + if (Destination) + { + /* We have space, do the copy */ + RtlCopyMemory(Destination, String, StringLength); + } + + /* Return the pointer to the data */ + return Destination; +} + diff --git a/dll/win32/mswsock/dns/hostent.c b/dll/win32/mswsock/dns/hostent.c new file mode 100644 index 00000000000..c444ac28940 --- /dev/null +++ b/dll/win32/mswsock/dns/hostent.c @@ -0,0 +1,388 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/hostent.c + * PURPOSE: Functions for dealing with Host Entry structures + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +PHOSTENT +WINAPI +Hostent_Init(IN PVOID *Buffer, + IN WORD AddressFamily, + IN ULONG AddressSize, + IN ULONG AddressCount, + IN ULONG AliasCount) +{ + PHOSTENT Hostent; + ULONG_PTR BufferPosition = (ULONG_PTR)*Buffer; + + /* Align the hostent on the buffer's 4 byte boundary */ + BufferPosition += 3 & ~3; + + /* Set up the basic data */ + Hostent = (PHOSTENT)BufferPosition; + Hostent->h_length = (WORD)AddressSize; + Hostent->h_addrtype = AddressFamily; + + /* Put aliases after Hostent */ + Hostent->h_aliases = (PCHAR*)((ULONG_PTR)(Hostent + 1) & ~3); + + /* Zero it out */ + RtlZeroMemory(Hostent->h_aliases, AliasCount * sizeof(PCHAR)); + + /* Put addresses after aliases */ + Hostent->h_addr_list = (PCHAR*) + ((ULONG_PTR)Hostent->h_aliases + + (AliasCount * sizeof(PCHAR)) + sizeof(PCHAR)); + + /* Update the location */ + BufferPosition = (ULONG_PTR)Hostent->h_addr_list + + ((AddressCount * sizeof(PCHAR)) + sizeof(PCHAR)); + + /* Send it back */ + *Buffer = (PVOID)BufferPosition; + + /* Return the hostent */ + return Hostent; +} + +VOID +WINAPI +Dns_PtrArrayToOffsetArray(PCHAR *List, + ULONG_PTR Base) +{ + /* Loop every pointer in the list */ + do + { + /* Update the pointer */ + *List = (PCHAR)((ULONG_PTR)*List - Base); + } while(*List++); +} + +VOID +WINAPI +Hostent_ConvertToOffsets(IN PHOSTENT Hostent) +{ + /* Do we have a name? */ + if (Hostent->h_name) + { + /* Update it */ + Hostent->h_name -= (ULONG_PTR)Hostent; + } + + /* Do we have aliases? */ + if (Hostent->h_aliases) + { + /* Update the pointer */ + Hostent->h_aliases -= (ULONG_PTR)Hostent; + + /* Fix them up */ + Dns_PtrArrayToOffsetArray(Hostent->h_aliases, (ULONG_PTR)Hostent); + } + + /* Do we have addresses? */ + if (Hostent->h_addr_list) + { + /* Fix them up */ + Dns_PtrArrayToOffsetArray(Hostent->h_addr_list, (ULONG_PTR)Hostent); + } +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/hostent.c + * PURPOSE: Functions for dealing with Host Entry structures + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +PHOSTENT +WINAPI +Hostent_Init(IN PVOID *Buffer, + IN WORD AddressFamily, + IN ULONG AddressSize, + IN ULONG AddressCount, + IN ULONG AliasCount) +{ + PHOSTENT Hostent; + ULONG_PTR BufferPosition = (ULONG_PTR)*Buffer; + + /* Align the hostent on the buffer's 4 byte boundary */ + BufferPosition += 3 & ~3; + + /* Set up the basic data */ + Hostent = (PHOSTENT)BufferPosition; + Hostent->h_length = (WORD)AddressSize; + Hostent->h_addrtype = AddressFamily; + + /* Put aliases after Hostent */ + Hostent->h_aliases = (PCHAR*)((ULONG_PTR)(Hostent + 1) & ~3); + + /* Zero it out */ + RtlZeroMemory(Hostent->h_aliases, AliasCount * sizeof(PCHAR)); + + /* Put addresses after aliases */ + Hostent->h_addr_list = (PCHAR*) + ((ULONG_PTR)Hostent->h_aliases + + (AliasCount * sizeof(PCHAR)) + sizeof(PCHAR)); + + /* Update the location */ + BufferPosition = (ULONG_PTR)Hostent->h_addr_list + + ((AddressCount * sizeof(PCHAR)) + sizeof(PCHAR)); + + /* Send it back */ + *Buffer = (PVOID)BufferPosition; + + /* Return the hostent */ + return Hostent; +} + +VOID +WINAPI +Dns_PtrArrayToOffsetArray(PCHAR *List, + ULONG_PTR Base) +{ + /* Loop every pointer in the list */ + do + { + /* Update the pointer */ + *List = (PCHAR)((ULONG_PTR)*List - Base); + } while(*List++); +} + +VOID +WINAPI +Hostent_ConvertToOffsets(IN PHOSTENT Hostent) +{ + /* Do we have a name? */ + if (Hostent->h_name) + { + /* Update it */ + Hostent->h_name -= (ULONG_PTR)Hostent; + } + + /* Do we have aliases? */ + if (Hostent->h_aliases) + { + /* Update the pointer */ + Hostent->h_aliases -= (ULONG_PTR)Hostent; + + /* Fix them up */ + Dns_PtrArrayToOffsetArray(Hostent->h_aliases, (ULONG_PTR)Hostent); + } + + /* Do we have addresses? */ + if (Hostent->h_addr_list) + { + /* Fix them up */ + Dns_PtrArrayToOffsetArray(Hostent->h_addr_list, (ULONG_PTR)Hostent); + } +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/hostent.c + * PURPOSE: Functions for dealing with Host Entry structures + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +PHOSTENT +WINAPI +Hostent_Init(IN PVOID *Buffer, + IN WORD AddressFamily, + IN ULONG AddressSize, + IN ULONG AddressCount, + IN ULONG AliasCount) +{ + PHOSTENT Hostent; + ULONG_PTR BufferPosition = (ULONG_PTR)*Buffer; + + /* Align the hostent on the buffer's 4 byte boundary */ + BufferPosition += 3 & ~3; + + /* Set up the basic data */ + Hostent = (PHOSTENT)BufferPosition; + Hostent->h_length = (WORD)AddressSize; + Hostent->h_addrtype = AddressFamily; + + /* Put aliases after Hostent */ + Hostent->h_aliases = (PCHAR*)((ULONG_PTR)(Hostent + 1) & ~3); + + /* Zero it out */ + RtlZeroMemory(Hostent->h_aliases, AliasCount * sizeof(PCHAR)); + + /* Put addresses after aliases */ + Hostent->h_addr_list = (PCHAR*) + ((ULONG_PTR)Hostent->h_aliases + + (AliasCount * sizeof(PCHAR)) + sizeof(PCHAR)); + + /* Update the location */ + BufferPosition = (ULONG_PTR)Hostent->h_addr_list + + ((AddressCount * sizeof(PCHAR)) + sizeof(PCHAR)); + + /* Send it back */ + *Buffer = (PVOID)BufferPosition; + + /* Return the hostent */ + return Hostent; +} + +VOID +WINAPI +Dns_PtrArrayToOffsetArray(PCHAR *List, + ULONG_PTR Base) +{ + /* Loop every pointer in the list */ + do + { + /* Update the pointer */ + *List = (PCHAR)((ULONG_PTR)*List - Base); + } while(*List++); +} + +VOID +WINAPI +Hostent_ConvertToOffsets(IN PHOSTENT Hostent) +{ + /* Do we have a name? */ + if (Hostent->h_name) + { + /* Update it */ + Hostent->h_name -= (ULONG_PTR)Hostent; + } + + /* Do we have aliases? */ + if (Hostent->h_aliases) + { + /* Update the pointer */ + Hostent->h_aliases -= (ULONG_PTR)Hostent; + + /* Fix them up */ + Dns_PtrArrayToOffsetArray(Hostent->h_aliases, (ULONG_PTR)Hostent); + } + + /* Do we have addresses? */ + if (Hostent->h_addr_list) + { + /* Fix them up */ + Dns_PtrArrayToOffsetArray(Hostent->h_addr_list, (ULONG_PTR)Hostent); + } +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/hostent.c + * PURPOSE: Functions for dealing with Host Entry structures + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +PHOSTENT +WINAPI +Hostent_Init(IN PVOID *Buffer, + IN WORD AddressFamily, + IN ULONG AddressSize, + IN ULONG AddressCount, + IN ULONG AliasCount) +{ + PHOSTENT Hostent; + ULONG_PTR BufferPosition = (ULONG_PTR)*Buffer; + + /* Align the hostent on the buffer's 4 byte boundary */ + BufferPosition += 3 & ~3; + + /* Set up the basic data */ + Hostent = (PHOSTENT)BufferPosition; + Hostent->h_length = (WORD)AddressSize; + Hostent->h_addrtype = AddressFamily; + + /* Put aliases after Hostent */ + Hostent->h_aliases = (PCHAR*)((ULONG_PTR)(Hostent + 1) & ~3); + + /* Zero it out */ + RtlZeroMemory(Hostent->h_aliases, AliasCount * sizeof(PCHAR)); + + /* Put addresses after aliases */ + Hostent->h_addr_list = (PCHAR*) + ((ULONG_PTR)Hostent->h_aliases + + (AliasCount * sizeof(PCHAR)) + sizeof(PCHAR)); + + /* Update the location */ + BufferPosition = (ULONG_PTR)Hostent->h_addr_list + + ((AddressCount * sizeof(PCHAR)) + sizeof(PCHAR)); + + /* Send it back */ + *Buffer = (PVOID)BufferPosition; + + /* Return the hostent */ + return Hostent; +} + +VOID +WINAPI +Dns_PtrArrayToOffsetArray(PCHAR *List, + ULONG_PTR Base) +{ + /* Loop every pointer in the list */ + do + { + /* Update the pointer */ + *List = (PCHAR)((ULONG_PTR)*List - Base); + } while(*List++); +} + +VOID +WINAPI +Hostent_ConvertToOffsets(IN PHOSTENT Hostent) +{ + /* Do we have a name? */ + if (Hostent->h_name) + { + /* Update it */ + Hostent->h_name -= (ULONG_PTR)Hostent; + } + + /* Do we have aliases? */ + if (Hostent->h_aliases) + { + /* Update the pointer */ + Hostent->h_aliases -= (ULONG_PTR)Hostent; + + /* Fix them up */ + Dns_PtrArrayToOffsetArray(Hostent->h_aliases, (ULONG_PTR)Hostent); + } + + /* Do we have addresses? */ + if (Hostent->h_addr_list) + { + /* Fix them up */ + Dns_PtrArrayToOffsetArray(Hostent->h_addr_list, (ULONG_PTR)Hostent); + } +} + diff --git a/dll/win32/mswsock/dns/inc/dnslib.h b/dll/win32/mswsock/dns/inc/dnslib.h new file mode 100644 index 00000000000..b19220f6ad0 --- /dev/null +++ b/dll/win32/mswsock/dns/inc/dnslib.h @@ -0,0 +1,144 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/precomp.h + * PURPOSE: DNSLIB Precompiled Header + */ + +#define _CRT_SECURE_NO_DEPRECATE +#define _WIN32_WINNT 0x502 +#define WIN32_NO_STATUS + +/* PSDK Headers */ +#include +#include +#include + +/* DNSLIB and DNSAPI Headers */ +#include +#include + +/* NDK */ +#include + +/* EOF */ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/precomp.h + * PURPOSE: DNSLIB Precompiled Header + */ + +#define _CRT_SECURE_NO_DEPRECATE +#define _WIN32_WINNT 0x502 +#define WIN32_NO_STATUS + +/* PSDK Headers */ +#include +#include +#include + +/* DNSLIB and DNSAPI Headers */ +#include +#include + +/* NDK */ +#include + +/* EOF */ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/precomp.h + * PURPOSE: DNSLIB Precompiled Header + */ + +#define _CRT_SECURE_NO_DEPRECATE +#define _WIN32_WINNT 0x502 +#define WIN32_NO_STATUS + +/* PSDK Headers */ +#include +#include +#include + +/* DNSLIB and DNSAPI Headers */ +#include +#include + +/* NDK */ +#include + +/* EOF */ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/precomp.h + * PURPOSE: DNSLIB Precompiled Header + */ + +#define _CRT_SECURE_NO_DEPRECATE +#define _WIN32_WINNT 0x502 +#define WIN32_NO_STATUS + +/* PSDK Headers */ +#include +#include +#include + +/* DNSLIB and DNSAPI Headers */ +#include +#include + +/* NDK */ +#include + +/* EOF */ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/precomp.h + * PURPOSE: DNSLIB Precompiled Header + */ + +#define _CRT_SECURE_NO_DEPRECATE +#define _WIN32_WINNT 0x502 +#define WIN32_NO_STATUS + +/* PSDK Headers */ +#include +#include +#include + +/* DNSLIB and DNSAPI Headers */ +#include +#include + +/* NDK */ +#include + +/* EOF */ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/precomp.h + * PURPOSE: DNSLIB Precompiled Header + */ + +#define _CRT_SECURE_NO_DEPRECATE +#define _WIN32_WINNT 0x502 +#define WIN32_NO_STATUS + +/* PSDK Headers */ +#include +#include +#include + +/* DNSLIB and DNSAPI Headers */ +#include +#include + +/* NDK */ +#include + +/* EOF */ diff --git a/dll/win32/mswsock/dns/inc/dnslibp.h b/dll/win32/mswsock/dns/inc/dnslibp.h new file mode 100644 index 00000000000..86359ae9172 --- /dev/null +++ b/dll/win32/mswsock/dns/inc/dnslibp.h @@ -0,0 +1,2058 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Ancillary Function Driver DLL + * FILE: include/mswsock.h + * PURPOSE: Ancillary Function Driver DLL header + */ +#ifndef __DNSLIB_H +#define __DNSLIB_H + +/* INCLUDES ******************************************************************/ +#include + +/* ENUMERATIONS **************************************************************/ + +typedef enum _DNS_STRING_TYPE +{ + UnicodeString = 1, + Utf8String, + AnsiString, +} DNS_STRING_TYPE; + +#define IpV4Address 3 + +/* TYPES *********************************************************************/ + +typedef struct _DNS_IPV6_ADDRESS +{ + ULONG Unknown; + ULONG Unknown2; + IP6_ADDRESS Address; + ULONG Unknown3; + ULONG Unknown4; + DWORD Reserved; + ULONG Unknown5; +} DNS_IPV6_ADDRESS, *PDNS_IPV6_ADDRESS; + +typedef struct _DNS_ADDRESS +{ + union + { + struct + { + WORD AddressFamily; + WORD Port; + ATM_ADDRESS AtmAddress; + }; + SOCKADDR_IN Ip4Address; + SOCKADDR_IN6 Ip6Address; + }; + ULONG AddressLength; + DWORD Sub; + ULONG Flag; +} DNS_ADDRESS, *PDNS_ADDRESS; + +typedef struct _DNS_ARRAY +{ + ULONG AllocatedAddresses; + ULONG UsedAddresses; + ULONG Unknown[0x6]; + DNS_ADDRESS Addresses[1]; +} DNS_ARRAY, *PDNS_ARRAY; + +typedef struct _DNS_BLOB +{ + LPWSTR Name; + PDNS_ARRAY DnsAddrArray; + PHOSTENT Hostent; + ULONG AliasCount; + ULONG Unknown; + LPWSTR Aliases[8]; +} DNS_BLOB, *PDNS_BLOB; + +typedef struct _DNS_FAMILY_INFO +{ + WORD AddrType; + WORD DnsType; + DWORD AddressSize; + DWORD SockaddrSize; + DWORD AddressOffset; +} DNS_FAMILY_INFO, *PDNS_FAMILY_INFO; + +typedef struct _FLATBUFF +{ + PVOID Buffer; + PVOID BufferEnd; + ULONG_PTR BufferPos; + SIZE_T BufferSize; + SIZE_T BufferFreeSize; +} FLATBUFF, *PFLATBUFF; + +/* + * memory.c + */ +VOID +WINAPI +Dns_Free(IN PVOID Address); + +PVOID +WINAPI +Dns_AllocZero(IN SIZE_T Size); + +/* + * addr.c + */ +PDNS_FAMILY_INFO +WINAPI +FamilyInfo_GetForFamily(IN WORD AddressFamily); + +/* + * dnsaddr.c + */ +VOID +WINAPI +DnsAddr_BuildFromIp4( + IN PDNS_ADDRESS DnsAddress, + IN IN_ADDR Address, + IN WORD Unknown +); + +VOID +WINAPI +DnsAddr_BuildFromIp6( + IN PDNS_ADDRESS DnsAddress, + IN PIN6_ADDR Address, + IN ULONG ScopeId, + IN WORD Port +); + +PDNS_ARRAY +WINAPI +DnsAddrArray_Create(ULONG Count); + +BOOL +WINAPI +DnsAddrArray_AddAddr( + IN PDNS_ARRAY DnsAddrArray, + IN PDNS_ADDRESS DnsAddress, + IN WORD AddressFamily OPTIONAL, + IN DWORD AddressType OPTIONAL +); + +VOID +WINAPI +DnsAddrArray_Free(IN PDNS_ARRAY DnsAddrArray); + +BOOL +WINAPI +DnsAddrArray_AddIp4( + IN PDNS_ARRAY DnsAddrArray, + IN IN_ADDR Address, + IN DWORD AddressType +); + +BOOL +WINAPI +DnsAddrArray_ContainsAddr( + IN PDNS_ARRAY DnsAddrArray, + IN PDNS_ADDRESS DnsAddress, + IN DWORD AddressType +); + +BOOLEAN +WINAPI +DnsAddr_BuildFromDnsRecord( + IN PDNS_RECORD DnsRecord, + OUT PDNS_ADDRESS DnsAddr +); + +/* + * hostent.c + */ +PHOSTENT +WINAPI +Hostent_Init( + IN PVOID *Buffer, + IN WORD AddressFamily, + IN ULONG AddressSize, + IN ULONG AddressCount, + IN ULONG AliasCount +); + +VOID +WINAPI +Hostent_ConvertToOffsets(IN PHOSTENT Hostent); + +/* + * flatbuf.c + */ +VOID +WINAPI +FlatBuf_Init( + IN PFLATBUFF FlatBuffer, + IN PVOID Buffer, + IN SIZE_T Size +); + +PVOID +WINAPI +FlatBuf_Arg_CopyMemory( + IN OUT PULONG_PTR Position, + IN OUT PSIZE_T FreeSize, + IN PVOID Buffer, + IN SIZE_T Size, + IN ULONG Align +); + +PVOID +WINAPI +FlatBuf_Arg_Reserve( + IN OUT PULONG_PTR Position, + IN OUT PSIZE_T FreeSize, + IN SIZE_T Size, + IN ULONG Align +); + +PVOID +WINAPI +FlatBuf_Arg_WriteString( + IN OUT PULONG_PTR Position, + IN OUT PSIZE_T FreeSize, + IN PVOID String, + IN BOOLEAN IsUnicode +); + +/* + * sablob.c + */ +PDNS_BLOB +WINAPI +SaBlob_Create( + IN ULONG Count +); + +PDNS_BLOB +WINAPI +SaBlob_CreateFromIp4( + IN LPWSTR Name, + IN ULONG Count, + IN PIN_ADDR AddressArray +); + +VOID +WINAPI +SaBlob_Free(IN PDNS_BLOB Blob); + +PHOSTENT +WINAPI +SaBlob_CreateHostent( + IN OUT PULONG_PTR BufferPosition, + IN OUT PSIZE_T RemainingBufferSpace, + IN OUT PSIZE_T HostEntrySize, + IN PDNS_BLOB Blob, + IN DWORD StringType, + IN BOOLEAN Relative, + IN BOOLEAN BufferAllocated +); + +INT +WINAPI +SaBlob_WriteNameOrAlias( + IN PDNS_BLOB Blob, + IN LPWSTR String, + IN BOOLEAN IsAlias +); + +PDNS_BLOB +WINAPI +SaBlob_Query( + IN LPWSTR Name, + IN WORD DnsType, + IN ULONG Flags, + IN PVOID *Reserved, + IN DWORD AddressFamily +); + +/* + * string.c + */ +ULONG +WINAPI +Dns_StringCopy( + OUT PVOID Destination, + IN OUT PULONG DestinationSize, + IN PVOID String, + IN ULONG StringSize OPTIONAL, + IN DWORD InputType, + IN DWORD OutputType +); + +LPWSTR +WINAPI +Dns_CreateStringCopy_W(IN LPWSTR Name); + +ULONG +WINAPI +Dns_GetBufferLengthForStringCopy( + IN PVOID String, + IN ULONG Size OPTIONAL, + IN DWORD InputType, + IN DWORD OutputType +); + +/* + * straddr.c + */ +BOOLEAN +WINAPI +Dns_StringToAddressW( + OUT PVOID Address, + IN OUT PULONG AddressSize, + IN LPWSTR AddressName, + IN OUT PDWORD AddressFamily +); + +LPWSTR +WINAPI +Dns_Ip4AddressToReverseName_W( + OUT LPWSTR Name, + IN IN_ADDR Address +); + +LPWSTR +WINAPI +Dns_Ip6AddressToReverseName_W( + OUT LPWSTR Name, + IN IN6_ADDR Address +); + +BOOLEAN +WINAPI +Dns_ReverseNameToDnsAddr_W( + OUT PDNS_ADDRESS DnsAddr, + IN LPWSTR Name +); + +BOOLEAN +WINAPI +Dns_Ip4ReverseNameToAddress_W( + OUT PIN_ADDR Address, + IN LPWSTR Name +); + +#endif +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Ancillary Function Driver DLL + * FILE: include/mswsock.h + * PURPOSE: Ancillary Function Driver DLL header + */ +#ifndef __DNSLIB_H +#define __DNSLIB_H + +/* INCLUDES ******************************************************************/ +#include + +/* ENUMERATIONS **************************************************************/ + +typedef enum _DNS_STRING_TYPE +{ + UnicodeString = 1, + Utf8String, + AnsiString, +} DNS_STRING_TYPE; + +#define IpV4Address 3 + +/* TYPES *********************************************************************/ + +typedef struct _DNS_IPV6_ADDRESS +{ + ULONG Unknown; + ULONG Unknown2; + IP6_ADDRESS Address; + ULONG Unknown3; + ULONG Unknown4; + DWORD Reserved; + ULONG Unknown5; +} DNS_IPV6_ADDRESS, *PDNS_IPV6_ADDRESS; + +typedef struct _DNS_ADDRESS +{ + union + { + struct + { + WORD AddressFamily; + WORD Port; + ATM_ADDRESS AtmAddress; + }; + SOCKADDR_IN Ip4Address; + SOCKADDR_IN6 Ip6Address; + }; + ULONG AddressLength; + DWORD Sub; + ULONG Flag; +} DNS_ADDRESS, *PDNS_ADDRESS; + +typedef struct _DNS_ARRAY +{ + ULONG AllocatedAddresses; + ULONG UsedAddresses; + ULONG Unknown[0x6]; + DNS_ADDRESS Addresses[1]; +} DNS_ARRAY, *PDNS_ARRAY; + +typedef struct _DNS_BLOB +{ + LPWSTR Name; + PDNS_ARRAY DnsAddrArray; + PHOSTENT Hostent; + ULONG AliasCount; + ULONG Unknown; + LPWSTR Aliases[8]; +} DNS_BLOB, *PDNS_BLOB; + +typedef struct _DNS_FAMILY_INFO +{ + WORD AddrType; + WORD DnsType; + DWORD AddressSize; + DWORD SockaddrSize; + DWORD AddressOffset; +} DNS_FAMILY_INFO, *PDNS_FAMILY_INFO; + +typedef struct _FLATBUFF +{ + PVOID Buffer; + PVOID BufferEnd; + ULONG_PTR BufferPos; + SIZE_T BufferSize; + SIZE_T BufferFreeSize; +} FLATBUFF, *PFLATBUFF; + +/* + * memory.c + */ +VOID +WINAPI +Dns_Free(IN PVOID Address); + +PVOID +WINAPI +Dns_AllocZero(IN SIZE_T Size); + +/* + * addr.c + */ +PDNS_FAMILY_INFO +WINAPI +FamilyInfo_GetForFamily(IN WORD AddressFamily); + +/* + * dnsaddr.c + */ +VOID +WINAPI +DnsAddr_BuildFromIp4( + IN PDNS_ADDRESS DnsAddress, + IN IN_ADDR Address, + IN WORD Unknown +); + +VOID +WINAPI +DnsAddr_BuildFromIp6( + IN PDNS_ADDRESS DnsAddress, + IN PIN6_ADDR Address, + IN ULONG ScopeId, + IN WORD Port +); + +PDNS_ARRAY +WINAPI +DnsAddrArray_Create(ULONG Count); + +BOOL +WINAPI +DnsAddrArray_AddAddr( + IN PDNS_ARRAY DnsAddrArray, + IN PDNS_ADDRESS DnsAddress, + IN WORD AddressFamily OPTIONAL, + IN DWORD AddressType OPTIONAL +); + +VOID +WINAPI +DnsAddrArray_Free(IN PDNS_ARRAY DnsAddrArray); + +BOOL +WINAPI +DnsAddrArray_AddIp4( + IN PDNS_ARRAY DnsAddrArray, + IN IN_ADDR Address, + IN DWORD AddressType +); + +BOOL +WINAPI +DnsAddrArray_ContainsAddr( + IN PDNS_ARRAY DnsAddrArray, + IN PDNS_ADDRESS DnsAddress, + IN DWORD AddressType +); + +BOOLEAN +WINAPI +DnsAddr_BuildFromDnsRecord( + IN PDNS_RECORD DnsRecord, + OUT PDNS_ADDRESS DnsAddr +); + +/* + * hostent.c + */ +PHOSTENT +WINAPI +Hostent_Init( + IN PVOID *Buffer, + IN WORD AddressFamily, + IN ULONG AddressSize, + IN ULONG AddressCount, + IN ULONG AliasCount +); + +VOID +WINAPI +Hostent_ConvertToOffsets(IN PHOSTENT Hostent); + +/* + * flatbuf.c + */ +VOID +WINAPI +FlatBuf_Init( + IN PFLATBUFF FlatBuffer, + IN PVOID Buffer, + IN SIZE_T Size +); + +PVOID +WINAPI +FlatBuf_Arg_CopyMemory( + IN OUT PULONG_PTR Position, + IN OUT PSIZE_T FreeSize, + IN PVOID Buffer, + IN SIZE_T Size, + IN ULONG Align +); + +PVOID +WINAPI +FlatBuf_Arg_Reserve( + IN OUT PULONG_PTR Position, + IN OUT PSIZE_T FreeSize, + IN SIZE_T Size, + IN ULONG Align +); + +PVOID +WINAPI +FlatBuf_Arg_WriteString( + IN OUT PULONG_PTR Position, + IN OUT PSIZE_T FreeSize, + IN PVOID String, + IN BOOLEAN IsUnicode +); + +/* + * sablob.c + */ +PDNS_BLOB +WINAPI +SaBlob_Create( + IN ULONG Count +); + +PDNS_BLOB +WINAPI +SaBlob_CreateFromIp4( + IN LPWSTR Name, + IN ULONG Count, + IN PIN_ADDR AddressArray +); + +VOID +WINAPI +SaBlob_Free(IN PDNS_BLOB Blob); + +PHOSTENT +WINAPI +SaBlob_CreateHostent( + IN OUT PULONG_PTR BufferPosition, + IN OUT PSIZE_T RemainingBufferSpace, + IN OUT PSIZE_T HostEntrySize, + IN PDNS_BLOB Blob, + IN DWORD StringType, + IN BOOLEAN Relative, + IN BOOLEAN BufferAllocated +); + +INT +WINAPI +SaBlob_WriteNameOrAlias( + IN PDNS_BLOB Blob, + IN LPWSTR String, + IN BOOLEAN IsAlias +); + +PDNS_BLOB +WINAPI +SaBlob_Query( + IN LPWSTR Name, + IN WORD DnsType, + IN ULONG Flags, + IN PVOID *Reserved, + IN DWORD AddressFamily +); + +/* + * string.c + */ +ULONG +WINAPI +Dns_StringCopy( + OUT PVOID Destination, + IN OUT PULONG DestinationSize, + IN PVOID String, + IN ULONG StringSize OPTIONAL, + IN DWORD InputType, + IN DWORD OutputType +); + +LPWSTR +WINAPI +Dns_CreateStringCopy_W(IN LPWSTR Name); + +ULONG +WINAPI +Dns_GetBufferLengthForStringCopy( + IN PVOID String, + IN ULONG Size OPTIONAL, + IN DWORD InputType, + IN DWORD OutputType +); + +/* + * straddr.c + */ +BOOLEAN +WINAPI +Dns_StringToAddressW( + OUT PVOID Address, + IN OUT PULONG AddressSize, + IN LPWSTR AddressName, + IN OUT PDWORD AddressFamily +); + +LPWSTR +WINAPI +Dns_Ip4AddressToReverseName_W( + OUT LPWSTR Name, + IN IN_ADDR Address +); + +LPWSTR +WINAPI +Dns_Ip6AddressToReverseName_W( + OUT LPWSTR Name, + IN IN6_ADDR Address +); + +BOOLEAN +WINAPI +Dns_ReverseNameToDnsAddr_W( + OUT PDNS_ADDRESS DnsAddr, + IN LPWSTR Name +); + +BOOLEAN +WINAPI +Dns_Ip4ReverseNameToAddress_W( + OUT PIN_ADDR Address, + IN LPWSTR Name +); + +#endif +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Ancillary Function Driver DLL + * FILE: include/mswsock.h + * PURPOSE: Ancillary Function Driver DLL header + */ +#ifndef __DNSLIB_H +#define __DNSLIB_H + +/* INCLUDES ******************************************************************/ +#include + +/* ENUMERATIONS **************************************************************/ + +typedef enum _DNS_STRING_TYPE +{ + UnicodeString = 1, + Utf8String, + AnsiString, +} DNS_STRING_TYPE; + +#define IpV4Address 3 + +/* TYPES *********************************************************************/ + +typedef struct _DNS_IPV6_ADDRESS +{ + ULONG Unknown; + ULONG Unknown2; + IP6_ADDRESS Address; + ULONG Unknown3; + ULONG Unknown4; + DWORD Reserved; + ULONG Unknown5; +} DNS_IPV6_ADDRESS, *PDNS_IPV6_ADDRESS; + +typedef struct _DNS_ADDRESS +{ + union + { + struct + { + WORD AddressFamily; + WORD Port; + ATM_ADDRESS AtmAddress; + }; + SOCKADDR_IN Ip4Address; + SOCKADDR_IN6 Ip6Address; + }; + ULONG AddressLength; + DWORD Sub; + ULONG Flag; +} DNS_ADDRESS, *PDNS_ADDRESS; + +typedef struct _DNS_ARRAY +{ + ULONG AllocatedAddresses; + ULONG UsedAddresses; + ULONG Unknown[0x6]; + DNS_ADDRESS Addresses[1]; +} DNS_ARRAY, *PDNS_ARRAY; + +typedef struct _DNS_BLOB +{ + LPWSTR Name; + PDNS_ARRAY DnsAddrArray; + PHOSTENT Hostent; + ULONG AliasCount; + ULONG Unknown; + LPWSTR Aliases[8]; +} DNS_BLOB, *PDNS_BLOB; + +typedef struct _DNS_FAMILY_INFO +{ + WORD AddrType; + WORD DnsType; + DWORD AddressSize; + DWORD SockaddrSize; + DWORD AddressOffset; +} DNS_FAMILY_INFO, *PDNS_FAMILY_INFO; + +typedef struct _FLATBUFF +{ + PVOID Buffer; + PVOID BufferEnd; + ULONG_PTR BufferPos; + SIZE_T BufferSize; + SIZE_T BufferFreeSize; +} FLATBUFF, *PFLATBUFF; + +/* + * memory.c + */ +VOID +WINAPI +Dns_Free(IN PVOID Address); + +PVOID +WINAPI +Dns_AllocZero(IN SIZE_T Size); + +/* + * addr.c + */ +PDNS_FAMILY_INFO +WINAPI +FamilyInfo_GetForFamily(IN WORD AddressFamily); + +/* + * dnsaddr.c + */ +VOID +WINAPI +DnsAddr_BuildFromIp4( + IN PDNS_ADDRESS DnsAddress, + IN IN_ADDR Address, + IN WORD Unknown +); + +VOID +WINAPI +DnsAddr_BuildFromIp6( + IN PDNS_ADDRESS DnsAddress, + IN PIN6_ADDR Address, + IN ULONG ScopeId, + IN WORD Port +); + +PDNS_ARRAY +WINAPI +DnsAddrArray_Create(ULONG Count); + +BOOL +WINAPI +DnsAddrArray_AddAddr( + IN PDNS_ARRAY DnsAddrArray, + IN PDNS_ADDRESS DnsAddress, + IN WORD AddressFamily OPTIONAL, + IN DWORD AddressType OPTIONAL +); + +VOID +WINAPI +DnsAddrArray_Free(IN PDNS_ARRAY DnsAddrArray); + +BOOL +WINAPI +DnsAddrArray_AddIp4( + IN PDNS_ARRAY DnsAddrArray, + IN IN_ADDR Address, + IN DWORD AddressType +); + +BOOL +WINAPI +DnsAddrArray_ContainsAddr( + IN PDNS_ARRAY DnsAddrArray, + IN PDNS_ADDRESS DnsAddress, + IN DWORD AddressType +); + +BOOLEAN +WINAPI +DnsAddr_BuildFromDnsRecord( + IN PDNS_RECORD DnsRecord, + OUT PDNS_ADDRESS DnsAddr +); + +/* + * hostent.c + */ +PHOSTENT +WINAPI +Hostent_Init( + IN PVOID *Buffer, + IN WORD AddressFamily, + IN ULONG AddressSize, + IN ULONG AddressCount, + IN ULONG AliasCount +); + +VOID +WINAPI +Hostent_ConvertToOffsets(IN PHOSTENT Hostent); + +/* + * flatbuf.c + */ +VOID +WINAPI +FlatBuf_Init( + IN PFLATBUFF FlatBuffer, + IN PVOID Buffer, + IN SIZE_T Size +); + +PVOID +WINAPI +FlatBuf_Arg_CopyMemory( + IN OUT PULONG_PTR Position, + IN OUT PSIZE_T FreeSize, + IN PVOID Buffer, + IN SIZE_T Size, + IN ULONG Align +); + +PVOID +WINAPI +FlatBuf_Arg_Reserve( + IN OUT PULONG_PTR Position, + IN OUT PSIZE_T FreeSize, + IN SIZE_T Size, + IN ULONG Align +); + +PVOID +WINAPI +FlatBuf_Arg_WriteString( + IN OUT PULONG_PTR Position, + IN OUT PSIZE_T FreeSize, + IN PVOID String, + IN BOOLEAN IsUnicode +); + +/* + * sablob.c + */ +PDNS_BLOB +WINAPI +SaBlob_Create( + IN ULONG Count +); + +PDNS_BLOB +WINAPI +SaBlob_CreateFromIp4( + IN LPWSTR Name, + IN ULONG Count, + IN PIN_ADDR AddressArray +); + +VOID +WINAPI +SaBlob_Free(IN PDNS_BLOB Blob); + +PHOSTENT +WINAPI +SaBlob_CreateHostent( + IN OUT PULONG_PTR BufferPosition, + IN OUT PSIZE_T RemainingBufferSpace, + IN OUT PSIZE_T HostEntrySize, + IN PDNS_BLOB Blob, + IN DWORD StringType, + IN BOOLEAN Relative, + IN BOOLEAN BufferAllocated +); + +INT +WINAPI +SaBlob_WriteNameOrAlias( + IN PDNS_BLOB Blob, + IN LPWSTR String, + IN BOOLEAN IsAlias +); + +PDNS_BLOB +WINAPI +SaBlob_Query( + IN LPWSTR Name, + IN WORD DnsType, + IN ULONG Flags, + IN PVOID *Reserved, + IN DWORD AddressFamily +); + +/* + * string.c + */ +ULONG +WINAPI +Dns_StringCopy( + OUT PVOID Destination, + IN OUT PULONG DestinationSize, + IN PVOID String, + IN ULONG StringSize OPTIONAL, + IN DWORD InputType, + IN DWORD OutputType +); + +LPWSTR +WINAPI +Dns_CreateStringCopy_W(IN LPWSTR Name); + +ULONG +WINAPI +Dns_GetBufferLengthForStringCopy( + IN PVOID String, + IN ULONG Size OPTIONAL, + IN DWORD InputType, + IN DWORD OutputType +); + +/* + * straddr.c + */ +BOOLEAN +WINAPI +Dns_StringToAddressW( + OUT PVOID Address, + IN OUT PULONG AddressSize, + IN LPWSTR AddressName, + IN OUT PDWORD AddressFamily +); + +LPWSTR +WINAPI +Dns_Ip4AddressToReverseName_W( + OUT LPWSTR Name, + IN IN_ADDR Address +); + +LPWSTR +WINAPI +Dns_Ip6AddressToReverseName_W( + OUT LPWSTR Name, + IN IN6_ADDR Address +); + +BOOLEAN +WINAPI +Dns_ReverseNameToDnsAddr_W( + OUT PDNS_ADDRESS DnsAddr, + IN LPWSTR Name +); + +BOOLEAN +WINAPI +Dns_Ip4ReverseNameToAddress_W( + OUT PIN_ADDR Address, + IN LPWSTR Name +); + +#endif +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Ancillary Function Driver DLL + * FILE: include/mswsock.h + * PURPOSE: Ancillary Function Driver DLL header + */ +#ifndef __DNSLIB_H +#define __DNSLIB_H + +/* INCLUDES ******************************************************************/ +#include + +/* ENUMERATIONS **************************************************************/ + +typedef enum _DNS_STRING_TYPE +{ + UnicodeString = 1, + Utf8String, + AnsiString, +} DNS_STRING_TYPE; + +#define IpV4Address 3 + +/* TYPES *********************************************************************/ + +typedef struct _DNS_IPV6_ADDRESS +{ + ULONG Unknown; + ULONG Unknown2; + IP6_ADDRESS Address; + ULONG Unknown3; + ULONG Unknown4; + DWORD Reserved; + ULONG Unknown5; +} DNS_IPV6_ADDRESS, *PDNS_IPV6_ADDRESS; + +typedef struct _DNS_ADDRESS +{ + union + { + struct + { + WORD AddressFamily; + WORD Port; + ATM_ADDRESS AtmAddress; + }; + SOCKADDR_IN Ip4Address; + SOCKADDR_IN6 Ip6Address; + }; + ULONG AddressLength; + DWORD Sub; + ULONG Flag; +} DNS_ADDRESS, *PDNS_ADDRESS; + +typedef struct _DNS_ARRAY +{ + ULONG AllocatedAddresses; + ULONG UsedAddresses; + ULONG Unknown[0x6]; + DNS_ADDRESS Addresses[1]; +} DNS_ARRAY, *PDNS_ARRAY; + +typedef struct _DNS_BLOB +{ + LPWSTR Name; + PDNS_ARRAY DnsAddrArray; + PHOSTENT Hostent; + ULONG AliasCount; + ULONG Unknown; + LPWSTR Aliases[8]; +} DNS_BLOB, *PDNS_BLOB; + +typedef struct _DNS_FAMILY_INFO +{ + WORD AddrType; + WORD DnsType; + DWORD AddressSize; + DWORD SockaddrSize; + DWORD AddressOffset; +} DNS_FAMILY_INFO, *PDNS_FAMILY_INFO; + +typedef struct _FLATBUFF +{ + PVOID Buffer; + PVOID BufferEnd; + ULONG_PTR BufferPos; + SIZE_T BufferSize; + SIZE_T BufferFreeSize; +} FLATBUFF, *PFLATBUFF; + +/* + * memory.c + */ +VOID +WINAPI +Dns_Free(IN PVOID Address); + +PVOID +WINAPI +Dns_AllocZero(IN SIZE_T Size); + +/* + * addr.c + */ +PDNS_FAMILY_INFO +WINAPI +FamilyInfo_GetForFamily(IN WORD AddressFamily); + +/* + * dnsaddr.c + */ +VOID +WINAPI +DnsAddr_BuildFromIp4( + IN PDNS_ADDRESS DnsAddress, + IN IN_ADDR Address, + IN WORD Unknown +); + +VOID +WINAPI +DnsAddr_BuildFromIp6( + IN PDNS_ADDRESS DnsAddress, + IN PIN6_ADDR Address, + IN ULONG ScopeId, + IN WORD Port +); + +PDNS_ARRAY +WINAPI +DnsAddrArray_Create(ULONG Count); + +BOOL +WINAPI +DnsAddrArray_AddAddr( + IN PDNS_ARRAY DnsAddrArray, + IN PDNS_ADDRESS DnsAddress, + IN WORD AddressFamily OPTIONAL, + IN DWORD AddressType OPTIONAL +); + +VOID +WINAPI +DnsAddrArray_Free(IN PDNS_ARRAY DnsAddrArray); + +BOOL +WINAPI +DnsAddrArray_AddIp4( + IN PDNS_ARRAY DnsAddrArray, + IN IN_ADDR Address, + IN DWORD AddressType +); + +BOOL +WINAPI +DnsAddrArray_ContainsAddr( + IN PDNS_ARRAY DnsAddrArray, + IN PDNS_ADDRESS DnsAddress, + IN DWORD AddressType +); + +BOOLEAN +WINAPI +DnsAddr_BuildFromDnsRecord( + IN PDNS_RECORD DnsRecord, + OUT PDNS_ADDRESS DnsAddr +); + +/* + * hostent.c + */ +PHOSTENT +WINAPI +Hostent_Init( + IN PVOID *Buffer, + IN WORD AddressFamily, + IN ULONG AddressSize, + IN ULONG AddressCount, + IN ULONG AliasCount +); + +VOID +WINAPI +Hostent_ConvertToOffsets(IN PHOSTENT Hostent); + +/* + * flatbuf.c + */ +VOID +WINAPI +FlatBuf_Init( + IN PFLATBUFF FlatBuffer, + IN PVOID Buffer, + IN SIZE_T Size +); + +PVOID +WINAPI +FlatBuf_Arg_CopyMemory( + IN OUT PULONG_PTR Position, + IN OUT PSIZE_T FreeSize, + IN PVOID Buffer, + IN SIZE_T Size, + IN ULONG Align +); + +PVOID +WINAPI +FlatBuf_Arg_Reserve( + IN OUT PULONG_PTR Position, + IN OUT PSIZE_T FreeSize, + IN SIZE_T Size, + IN ULONG Align +); + +PVOID +WINAPI +FlatBuf_Arg_WriteString( + IN OUT PULONG_PTR Position, + IN OUT PSIZE_T FreeSize, + IN PVOID String, + IN BOOLEAN IsUnicode +); + +/* + * sablob.c + */ +PDNS_BLOB +WINAPI +SaBlob_Create( + IN ULONG Count +); + +PDNS_BLOB +WINAPI +SaBlob_CreateFromIp4( + IN LPWSTR Name, + IN ULONG Count, + IN PIN_ADDR AddressArray +); + +VOID +WINAPI +SaBlob_Free(IN PDNS_BLOB Blob); + +PHOSTENT +WINAPI +SaBlob_CreateHostent( + IN OUT PULONG_PTR BufferPosition, + IN OUT PSIZE_T RemainingBufferSpace, + IN OUT PSIZE_T HostEntrySize, + IN PDNS_BLOB Blob, + IN DWORD StringType, + IN BOOLEAN Relative, + IN BOOLEAN BufferAllocated +); + +INT +WINAPI +SaBlob_WriteNameOrAlias( + IN PDNS_BLOB Blob, + IN LPWSTR String, + IN BOOLEAN IsAlias +); + +PDNS_BLOB +WINAPI +SaBlob_Query( + IN LPWSTR Name, + IN WORD DnsType, + IN ULONG Flags, + IN PVOID *Reserved, + IN DWORD AddressFamily +); + +/* + * string.c + */ +ULONG +WINAPI +Dns_StringCopy( + OUT PVOID Destination, + IN OUT PULONG DestinationSize, + IN PVOID String, + IN ULONG StringSize OPTIONAL, + IN DWORD InputType, + IN DWORD OutputType +); + +LPWSTR +WINAPI +Dns_CreateStringCopy_W(IN LPWSTR Name); + +ULONG +WINAPI +Dns_GetBufferLengthForStringCopy( + IN PVOID String, + IN ULONG Size OPTIONAL, + IN DWORD InputType, + IN DWORD OutputType +); + +/* + * straddr.c + */ +BOOLEAN +WINAPI +Dns_StringToAddressW( + OUT PVOID Address, + IN OUT PULONG AddressSize, + IN LPWSTR AddressName, + IN OUT PDWORD AddressFamily +); + +LPWSTR +WINAPI +Dns_Ip4AddressToReverseName_W( + OUT LPWSTR Name, + IN IN_ADDR Address +); + +LPWSTR +WINAPI +Dns_Ip6AddressToReverseName_W( + OUT LPWSTR Name, + IN IN6_ADDR Address +); + +BOOLEAN +WINAPI +Dns_ReverseNameToDnsAddr_W( + OUT PDNS_ADDRESS DnsAddr, + IN LPWSTR Name +); + +BOOLEAN +WINAPI +Dns_Ip4ReverseNameToAddress_W( + OUT PIN_ADDR Address, + IN LPWSTR Name +); + +#endif +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Ancillary Function Driver DLL + * FILE: include/mswsock.h + * PURPOSE: Ancillary Function Driver DLL header + */ +#ifndef __DNSLIB_H +#define __DNSLIB_H + +/* INCLUDES ******************************************************************/ +#include + +/* ENUMERATIONS **************************************************************/ + +typedef enum _DNS_STRING_TYPE +{ + UnicodeString = 1, + Utf8String, + AnsiString, +} DNS_STRING_TYPE; + +#define IpV4Address 3 + +/* TYPES *********************************************************************/ + +typedef struct _DNS_IPV6_ADDRESS +{ + ULONG Unknown; + ULONG Unknown2; + IP6_ADDRESS Address; + ULONG Unknown3; + ULONG Unknown4; + DWORD Reserved; + ULONG Unknown5; +} DNS_IPV6_ADDRESS, *PDNS_IPV6_ADDRESS; + +typedef struct _DNS_ADDRESS +{ + union + { + struct + { + WORD AddressFamily; + WORD Port; + ATM_ADDRESS AtmAddress; + }; + SOCKADDR_IN Ip4Address; + SOCKADDR_IN6 Ip6Address; + }; + ULONG AddressLength; + DWORD Sub; + ULONG Flag; +} DNS_ADDRESS, *PDNS_ADDRESS; + +typedef struct _DNS_ARRAY +{ + ULONG AllocatedAddresses; + ULONG UsedAddresses; + ULONG Unknown[0x6]; + DNS_ADDRESS Addresses[1]; +} DNS_ARRAY, *PDNS_ARRAY; + +typedef struct _DNS_BLOB +{ + LPWSTR Name; + PDNS_ARRAY DnsAddrArray; + PHOSTENT Hostent; + ULONG AliasCount; + ULONG Unknown; + LPWSTR Aliases[8]; +} DNS_BLOB, *PDNS_BLOB; + +typedef struct _DNS_FAMILY_INFO +{ + WORD AddrType; + WORD DnsType; + DWORD AddressSize; + DWORD SockaddrSize; + DWORD AddressOffset; +} DNS_FAMILY_INFO, *PDNS_FAMILY_INFO; + +typedef struct _FLATBUFF +{ + PVOID Buffer; + PVOID BufferEnd; + ULONG_PTR BufferPos; + SIZE_T BufferSize; + SIZE_T BufferFreeSize; +} FLATBUFF, *PFLATBUFF; + +/* + * memory.c + */ +VOID +WINAPI +Dns_Free(IN PVOID Address); + +PVOID +WINAPI +Dns_AllocZero(IN SIZE_T Size); + +/* + * addr.c + */ +PDNS_FAMILY_INFO +WINAPI +FamilyInfo_GetForFamily(IN WORD AddressFamily); + +/* + * dnsaddr.c + */ +VOID +WINAPI +DnsAddr_BuildFromIp4( + IN PDNS_ADDRESS DnsAddress, + IN IN_ADDR Address, + IN WORD Unknown +); + +VOID +WINAPI +DnsAddr_BuildFromIp6( + IN PDNS_ADDRESS DnsAddress, + IN PIN6_ADDR Address, + IN ULONG ScopeId, + IN WORD Port +); + +PDNS_ARRAY +WINAPI +DnsAddrArray_Create(ULONG Count); + +BOOL +WINAPI +DnsAddrArray_AddAddr( + IN PDNS_ARRAY DnsAddrArray, + IN PDNS_ADDRESS DnsAddress, + IN WORD AddressFamily OPTIONAL, + IN DWORD AddressType OPTIONAL +); + +VOID +WINAPI +DnsAddrArray_Free(IN PDNS_ARRAY DnsAddrArray); + +BOOL +WINAPI +DnsAddrArray_AddIp4( + IN PDNS_ARRAY DnsAddrArray, + IN IN_ADDR Address, + IN DWORD AddressType +); + +BOOL +WINAPI +DnsAddrArray_ContainsAddr( + IN PDNS_ARRAY DnsAddrArray, + IN PDNS_ADDRESS DnsAddress, + IN DWORD AddressType +); + +BOOLEAN +WINAPI +DnsAddr_BuildFromDnsRecord( + IN PDNS_RECORD DnsRecord, + OUT PDNS_ADDRESS DnsAddr +); + +/* + * hostent.c + */ +PHOSTENT +WINAPI +Hostent_Init( + IN PVOID *Buffer, + IN WORD AddressFamily, + IN ULONG AddressSize, + IN ULONG AddressCount, + IN ULONG AliasCount +); + +VOID +WINAPI +Hostent_ConvertToOffsets(IN PHOSTENT Hostent); + +/* + * flatbuf.c + */ +VOID +WINAPI +FlatBuf_Init( + IN PFLATBUFF FlatBuffer, + IN PVOID Buffer, + IN SIZE_T Size +); + +PVOID +WINAPI +FlatBuf_Arg_CopyMemory( + IN OUT PULONG_PTR Position, + IN OUT PSIZE_T FreeSize, + IN PVOID Buffer, + IN SIZE_T Size, + IN ULONG Align +); + +PVOID +WINAPI +FlatBuf_Arg_Reserve( + IN OUT PULONG_PTR Position, + IN OUT PSIZE_T FreeSize, + IN SIZE_T Size, + IN ULONG Align +); + +PVOID +WINAPI +FlatBuf_Arg_WriteString( + IN OUT PULONG_PTR Position, + IN OUT PSIZE_T FreeSize, + IN PVOID String, + IN BOOLEAN IsUnicode +); + +/* + * sablob.c + */ +PDNS_BLOB +WINAPI +SaBlob_Create( + IN ULONG Count +); + +PDNS_BLOB +WINAPI +SaBlob_CreateFromIp4( + IN LPWSTR Name, + IN ULONG Count, + IN PIN_ADDR AddressArray +); + +VOID +WINAPI +SaBlob_Free(IN PDNS_BLOB Blob); + +PHOSTENT +WINAPI +SaBlob_CreateHostent( + IN OUT PULONG_PTR BufferPosition, + IN OUT PSIZE_T RemainingBufferSpace, + IN OUT PSIZE_T HostEntrySize, + IN PDNS_BLOB Blob, + IN DWORD StringType, + IN BOOLEAN Relative, + IN BOOLEAN BufferAllocated +); + +INT +WINAPI +SaBlob_WriteNameOrAlias( + IN PDNS_BLOB Blob, + IN LPWSTR String, + IN BOOLEAN IsAlias +); + +PDNS_BLOB +WINAPI +SaBlob_Query( + IN LPWSTR Name, + IN WORD DnsType, + IN ULONG Flags, + IN PVOID *Reserved, + IN DWORD AddressFamily +); + +/* + * string.c + */ +ULONG +WINAPI +Dns_StringCopy( + OUT PVOID Destination, + IN OUT PULONG DestinationSize, + IN PVOID String, + IN ULONG StringSize OPTIONAL, + IN DWORD InputType, + IN DWORD OutputType +); + +LPWSTR +WINAPI +Dns_CreateStringCopy_W(IN LPWSTR Name); + +ULONG +WINAPI +Dns_GetBufferLengthForStringCopy( + IN PVOID String, + IN ULONG Size OPTIONAL, + IN DWORD InputType, + IN DWORD OutputType +); + +/* + * straddr.c + */ +BOOLEAN +WINAPI +Dns_StringToAddressW( + OUT PVOID Address, + IN OUT PULONG AddressSize, + IN LPWSTR AddressName, + IN OUT PDWORD AddressFamily +); + +LPWSTR +WINAPI +Dns_Ip4AddressToReverseName_W( + OUT LPWSTR Name, + IN IN_ADDR Address +); + +LPWSTR +WINAPI +Dns_Ip6AddressToReverseName_W( + OUT LPWSTR Name, + IN IN6_ADDR Address +); + +BOOLEAN +WINAPI +Dns_ReverseNameToDnsAddr_W( + OUT PDNS_ADDRESS DnsAddr, + IN LPWSTR Name +); + +BOOLEAN +WINAPI +Dns_Ip4ReverseNameToAddress_W( + OUT PIN_ADDR Address, + IN LPWSTR Name +); + +#endif +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Ancillary Function Driver DLL + * FILE: include/mswsock.h + * PURPOSE: Ancillary Function Driver DLL header + */ +#ifndef __DNSLIB_H +#define __DNSLIB_H + +/* INCLUDES ******************************************************************/ +#include + +/* ENUMERATIONS **************************************************************/ + +typedef enum _DNS_STRING_TYPE +{ + UnicodeString = 1, + Utf8String, + AnsiString, +} DNS_STRING_TYPE; + +#define IpV4Address 3 + +/* TYPES *********************************************************************/ + +typedef struct _DNS_IPV6_ADDRESS +{ + ULONG Unknown; + ULONG Unknown2; + IP6_ADDRESS Address; + ULONG Unknown3; + ULONG Unknown4; + DWORD Reserved; + ULONG Unknown5; +} DNS_IPV6_ADDRESS, *PDNS_IPV6_ADDRESS; + +typedef struct _DNS_ADDRESS +{ + union + { + struct + { + WORD AddressFamily; + WORD Port; + ATM_ADDRESS AtmAddress; + }; + SOCKADDR_IN Ip4Address; + SOCKADDR_IN6 Ip6Address; + }; + ULONG AddressLength; + DWORD Sub; + ULONG Flag; +} DNS_ADDRESS, *PDNS_ADDRESS; + +typedef struct _DNS_ARRAY +{ + ULONG AllocatedAddresses; + ULONG UsedAddresses; + ULONG Unknown[0x6]; + DNS_ADDRESS Addresses[1]; +} DNS_ARRAY, *PDNS_ARRAY; + +typedef struct _DNS_BLOB +{ + LPWSTR Name; + PDNS_ARRAY DnsAddrArray; + PHOSTENT Hostent; + ULONG AliasCount; + ULONG Unknown; + LPWSTR Aliases[8]; +} DNS_BLOB, *PDNS_BLOB; + +typedef struct _DNS_FAMILY_INFO +{ + WORD AddrType; + WORD DnsType; + DWORD AddressSize; + DWORD SockaddrSize; + DWORD AddressOffset; +} DNS_FAMILY_INFO, *PDNS_FAMILY_INFO; + +typedef struct _FLATBUFF +{ + PVOID Buffer; + PVOID BufferEnd; + ULONG_PTR BufferPos; + SIZE_T BufferSize; + SIZE_T BufferFreeSize; +} FLATBUFF, *PFLATBUFF; + +/* + * memory.c + */ +VOID +WINAPI +Dns_Free(IN PVOID Address); + +PVOID +WINAPI +Dns_AllocZero(IN SIZE_T Size); + +/* + * addr.c + */ +PDNS_FAMILY_INFO +WINAPI +FamilyInfo_GetForFamily(IN WORD AddressFamily); + +/* + * dnsaddr.c + */ +VOID +WINAPI +DnsAddr_BuildFromIp4( + IN PDNS_ADDRESS DnsAddress, + IN IN_ADDR Address, + IN WORD Unknown +); + +VOID +WINAPI +DnsAddr_BuildFromIp6( + IN PDNS_ADDRESS DnsAddress, + IN PIN6_ADDR Address, + IN ULONG ScopeId, + IN WORD Port +); + +PDNS_ARRAY +WINAPI +DnsAddrArray_Create(ULONG Count); + +BOOL +WINAPI +DnsAddrArray_AddAddr( + IN PDNS_ARRAY DnsAddrArray, + IN PDNS_ADDRESS DnsAddress, + IN WORD AddressFamily OPTIONAL, + IN DWORD AddressType OPTIONAL +); + +VOID +WINAPI +DnsAddrArray_Free(IN PDNS_ARRAY DnsAddrArray); + +BOOL +WINAPI +DnsAddrArray_AddIp4( + IN PDNS_ARRAY DnsAddrArray, + IN IN_ADDR Address, + IN DWORD AddressType +); + +BOOL +WINAPI +DnsAddrArray_ContainsAddr( + IN PDNS_ARRAY DnsAddrArray, + IN PDNS_ADDRESS DnsAddress, + IN DWORD AddressType +); + +BOOLEAN +WINAPI +DnsAddr_BuildFromDnsRecord( + IN PDNS_RECORD DnsRecord, + OUT PDNS_ADDRESS DnsAddr +); + +/* + * hostent.c + */ +PHOSTENT +WINAPI +Hostent_Init( + IN PVOID *Buffer, + IN WORD AddressFamily, + IN ULONG AddressSize, + IN ULONG AddressCount, + IN ULONG AliasCount +); + +VOID +WINAPI +Hostent_ConvertToOffsets(IN PHOSTENT Hostent); + +/* + * flatbuf.c + */ +VOID +WINAPI +FlatBuf_Init( + IN PFLATBUFF FlatBuffer, + IN PVOID Buffer, + IN SIZE_T Size +); + +PVOID +WINAPI +FlatBuf_Arg_CopyMemory( + IN OUT PULONG_PTR Position, + IN OUT PSIZE_T FreeSize, + IN PVOID Buffer, + IN SIZE_T Size, + IN ULONG Align +); + +PVOID +WINAPI +FlatBuf_Arg_Reserve( + IN OUT PULONG_PTR Position, + IN OUT PSIZE_T FreeSize, + IN SIZE_T Size, + IN ULONG Align +); + +PVOID +WINAPI +FlatBuf_Arg_WriteString( + IN OUT PULONG_PTR Position, + IN OUT PSIZE_T FreeSize, + IN PVOID String, + IN BOOLEAN IsUnicode +); + +/* + * sablob.c + */ +PDNS_BLOB +WINAPI +SaBlob_Create( + IN ULONG Count +); + +PDNS_BLOB +WINAPI +SaBlob_CreateFromIp4( + IN LPWSTR Name, + IN ULONG Count, + IN PIN_ADDR AddressArray +); + +VOID +WINAPI +SaBlob_Free(IN PDNS_BLOB Blob); + +PHOSTENT +WINAPI +SaBlob_CreateHostent( + IN OUT PULONG_PTR BufferPosition, + IN OUT PSIZE_T RemainingBufferSpace, + IN OUT PSIZE_T HostEntrySize, + IN PDNS_BLOB Blob, + IN DWORD StringType, + IN BOOLEAN Relative, + IN BOOLEAN BufferAllocated +); + +INT +WINAPI +SaBlob_WriteNameOrAlias( + IN PDNS_BLOB Blob, + IN LPWSTR String, + IN BOOLEAN IsAlias +); + +PDNS_BLOB +WINAPI +SaBlob_Query( + IN LPWSTR Name, + IN WORD DnsType, + IN ULONG Flags, + IN PVOID *Reserved, + IN DWORD AddressFamily +); + +/* + * string.c + */ +ULONG +WINAPI +Dns_StringCopy( + OUT PVOID Destination, + IN OUT PULONG DestinationSize, + IN PVOID String, + IN ULONG StringSize OPTIONAL, + IN DWORD InputType, + IN DWORD OutputType +); + +LPWSTR +WINAPI +Dns_CreateStringCopy_W(IN LPWSTR Name); + +ULONG +WINAPI +Dns_GetBufferLengthForStringCopy( + IN PVOID String, + IN ULONG Size OPTIONAL, + IN DWORD InputType, + IN DWORD OutputType +); + +/* + * straddr.c + */ +BOOLEAN +WINAPI +Dns_StringToAddressW( + OUT PVOID Address, + IN OUT PULONG AddressSize, + IN LPWSTR AddressName, + IN OUT PDWORD AddressFamily +); + +LPWSTR +WINAPI +Dns_Ip4AddressToReverseName_W( + OUT LPWSTR Name, + IN IN_ADDR Address +); + +LPWSTR +WINAPI +Dns_Ip6AddressToReverseName_W( + OUT LPWSTR Name, + IN IN6_ADDR Address +); + +BOOLEAN +WINAPI +Dns_ReverseNameToDnsAddr_W( + OUT PDNS_ADDRESS DnsAddr, + IN LPWSTR Name +); + +BOOLEAN +WINAPI +Dns_Ip4ReverseNameToAddress_W( + OUT PIN_ADDR Address, + IN LPWSTR Name +); + +#endif diff --git a/dll/win32/mswsock/dns/inc/windnsp.h b/dll/win32/mswsock/dns/inc/windnsp.h new file mode 100644 index 00000000000..66cfbd83a12 --- /dev/null +++ b/dll/win32/mswsock/dns/inc/windnsp.h @@ -0,0 +1,168 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNSAPI Header + * FILE: include/libs/dns/windnsp.h + * PURPOSE: DNSLIB Precompiled Header + */ + +PVOID +WINAPI +DnsApiAlloc( + IN DWORD Size +); + +PVOID +WINAPI +DnsQueryConfigAllocEx( + IN DNS_CONFIG_TYPE Config, + OUT PVOID pBuffer, + IN OUT PDWORD pBufferLength +); + +VOID +WINAPI +DnsApiFree( + IN PVOID pBuffer +); + +/* EOF */ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNSAPI Header + * FILE: include/libs/dns/windnsp.h + * PURPOSE: DNSLIB Precompiled Header + */ + +PVOID +WINAPI +DnsApiAlloc( + IN DWORD Size +); + +PVOID +WINAPI +DnsQueryConfigAllocEx( + IN DNS_CONFIG_TYPE Config, + OUT PVOID pBuffer, + IN OUT PDWORD pBufferLength +); + +VOID +WINAPI +DnsApiFree( + IN PVOID pBuffer +); + +/* EOF */ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNSAPI Header + * FILE: include/libs/dns/windnsp.h + * PURPOSE: DNSLIB Precompiled Header + */ + +PVOID +WINAPI +DnsApiAlloc( + IN DWORD Size +); + +PVOID +WINAPI +DnsQueryConfigAllocEx( + IN DNS_CONFIG_TYPE Config, + OUT PVOID pBuffer, + IN OUT PDWORD pBufferLength +); + +VOID +WINAPI +DnsApiFree( + IN PVOID pBuffer +); + +/* EOF */ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNSAPI Header + * FILE: include/libs/dns/windnsp.h + * PURPOSE: DNSLIB Precompiled Header + */ + +PVOID +WINAPI +DnsApiAlloc( + IN DWORD Size +); + +PVOID +WINAPI +DnsQueryConfigAllocEx( + IN DNS_CONFIG_TYPE Config, + OUT PVOID pBuffer, + IN OUT PDWORD pBufferLength +); + +VOID +WINAPI +DnsApiFree( + IN PVOID pBuffer +); + +/* EOF */ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNSAPI Header + * FILE: include/libs/dns/windnsp.h + * PURPOSE: DNSLIB Precompiled Header + */ + +PVOID +WINAPI +DnsApiAlloc( + IN DWORD Size +); + +PVOID +WINAPI +DnsQueryConfigAllocEx( + IN DNS_CONFIG_TYPE Config, + OUT PVOID pBuffer, + IN OUT PDWORD pBufferLength +); + +VOID +WINAPI +DnsApiFree( + IN PVOID pBuffer +); + +/* EOF */ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNSAPI Header + * FILE: include/libs/dns/windnsp.h + * PURPOSE: DNSLIB Precompiled Header + */ + +PVOID +WINAPI +DnsApiAlloc( + IN DWORD Size +); + +PVOID +WINAPI +DnsQueryConfigAllocEx( + IN DNS_CONFIG_TYPE Config, + OUT PVOID pBuffer, + IN OUT PDWORD pBufferLength +); + +VOID +WINAPI +DnsApiFree( + IN PVOID pBuffer +); + +/* EOF */ diff --git a/dll/win32/mswsock/dns/ip6.c b/dll/win32/mswsock/dns/ip6.c new file mode 100644 index 00000000000..11486427020 --- /dev/null +++ b/dll/win32/mswsock/dns/ip6.c @@ -0,0 +1,56 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/ip6.c + * PURPOSE: Functions for dealing with IPv6 Specific issues. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/ip6.c + * PURPOSE: Functions for dealing with IPv6 Specific issues. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/ip6.c + * PURPOSE: Functions for dealing with IPv6 Specific issues. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/ip6.c + * PURPOSE: Functions for dealing with IPv6 Specific issues. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + diff --git a/dll/win32/mswsock/dns/memory.c b/dll/win32/mswsock/dns/memory.c new file mode 100644 index 00000000000..8db2f0abbb5 --- /dev/null +++ b/dll/win32/mswsock/dns/memory.c @@ -0,0 +1,264 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/memory.c + * PURPOSE: DNS Memory Manager Implementation and Heap. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +typedef PVOID +(WINAPI *PDNS_ALLOC_FUNCTION)(IN SIZE_T Size); +typedef VOID +(WINAPI *PDNS_FREE_FUNCTION)(IN PVOID Buffer); + +PDNS_ALLOC_FUNCTION pDnsAllocFunction; +PDNS_FREE_FUNCTION pDnsFreeFunction; + +/* FUNCTIONS *****************************************************************/ + +VOID +WINAPI +Dns_Free(IN PVOID Address) +{ + /* Check if whoever imported us specified a special free function */ + if (pDnsFreeFunction) + { + /* Use it */ + pDnsFreeFunction(Address); + } + else + { + /* Use our own */ + LocalFree(Address); + } +} + +PVOID +WINAPI +Dns_AllocZero(IN SIZE_T Size) +{ + PVOID Buffer; + + /* Check if whoever imported us specified a special allocation function */ + if (pDnsAllocFunction) + { + /* Use it to allocate the memory */ + Buffer = pDnsAllocFunction(Size); + if (Buffer) + { + /* Zero it out */ + RtlZeroMemory(Buffer, Size); + } + } + else + { + /* Use our default */ + Buffer = LocalAlloc(LMEM_ZEROINIT, Size); + } + + /* Return the allocate pointer */ + return Buffer; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/memory.c + * PURPOSE: DNS Memory Manager Implementation and Heap. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +typedef PVOID +(WINAPI *PDNS_ALLOC_FUNCTION)(IN SIZE_T Size); +typedef VOID +(WINAPI *PDNS_FREE_FUNCTION)(IN PVOID Buffer); + +PDNS_ALLOC_FUNCTION pDnsAllocFunction; +PDNS_FREE_FUNCTION pDnsFreeFunction; + +/* FUNCTIONS *****************************************************************/ + +VOID +WINAPI +Dns_Free(IN PVOID Address) +{ + /* Check if whoever imported us specified a special free function */ + if (pDnsFreeFunction) + { + /* Use it */ + pDnsFreeFunction(Address); + } + else + { + /* Use our own */ + LocalFree(Address); + } +} + +PVOID +WINAPI +Dns_AllocZero(IN SIZE_T Size) +{ + PVOID Buffer; + + /* Check if whoever imported us specified a special allocation function */ + if (pDnsAllocFunction) + { + /* Use it to allocate the memory */ + Buffer = pDnsAllocFunction(Size); + if (Buffer) + { + /* Zero it out */ + RtlZeroMemory(Buffer, Size); + } + } + else + { + /* Use our default */ + Buffer = LocalAlloc(LMEM_ZEROINIT, Size); + } + + /* Return the allocate pointer */ + return Buffer; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/memory.c + * PURPOSE: DNS Memory Manager Implementation and Heap. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +typedef PVOID +(WINAPI *PDNS_ALLOC_FUNCTION)(IN SIZE_T Size); +typedef VOID +(WINAPI *PDNS_FREE_FUNCTION)(IN PVOID Buffer); + +PDNS_ALLOC_FUNCTION pDnsAllocFunction; +PDNS_FREE_FUNCTION pDnsFreeFunction; + +/* FUNCTIONS *****************************************************************/ + +VOID +WINAPI +Dns_Free(IN PVOID Address) +{ + /* Check if whoever imported us specified a special free function */ + if (pDnsFreeFunction) + { + /* Use it */ + pDnsFreeFunction(Address); + } + else + { + /* Use our own */ + LocalFree(Address); + } +} + +PVOID +WINAPI +Dns_AllocZero(IN SIZE_T Size) +{ + PVOID Buffer; + + /* Check if whoever imported us specified a special allocation function */ + if (pDnsAllocFunction) + { + /* Use it to allocate the memory */ + Buffer = pDnsAllocFunction(Size); + if (Buffer) + { + /* Zero it out */ + RtlZeroMemory(Buffer, Size); + } + } + else + { + /* Use our default */ + Buffer = LocalAlloc(LMEM_ZEROINIT, Size); + } + + /* Return the allocate pointer */ + return Buffer; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/memory.c + * PURPOSE: DNS Memory Manager Implementation and Heap. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +typedef PVOID +(WINAPI *PDNS_ALLOC_FUNCTION)(IN SIZE_T Size); +typedef VOID +(WINAPI *PDNS_FREE_FUNCTION)(IN PVOID Buffer); + +PDNS_ALLOC_FUNCTION pDnsAllocFunction; +PDNS_FREE_FUNCTION pDnsFreeFunction; + +/* FUNCTIONS *****************************************************************/ + +VOID +WINAPI +Dns_Free(IN PVOID Address) +{ + /* Check if whoever imported us specified a special free function */ + if (pDnsFreeFunction) + { + /* Use it */ + pDnsFreeFunction(Address); + } + else + { + /* Use our own */ + LocalFree(Address); + } +} + +PVOID +WINAPI +Dns_AllocZero(IN SIZE_T Size) +{ + PVOID Buffer; + + /* Check if whoever imported us specified a special allocation function */ + if (pDnsAllocFunction) + { + /* Use it to allocate the memory */ + Buffer = pDnsAllocFunction(Size); + if (Buffer) + { + /* Zero it out */ + RtlZeroMemory(Buffer, Size); + } + } + else + { + /* Use our default */ + Buffer = LocalAlloc(LMEM_ZEROINIT, Size); + } + + /* Return the allocate pointer */ + return Buffer; +} + diff --git a/dll/win32/mswsock/dns/name.c b/dll/win32/mswsock/dns/name.c new file mode 100644 index 00000000000..75fdbc925a5 --- /dev/null +++ b/dll/win32/mswsock/dns/name.c @@ -0,0 +1,56 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/name.c + * PURPOSE: Functions dealing with DNS (Canonical, FQDN, Host) Names + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/name.c + * PURPOSE: Functions dealing with DNS (Canonical, FQDN, Host) Names + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/name.c + * PURPOSE: Functions dealing with DNS (Canonical, FQDN, Host) Names + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/name.c + * PURPOSE: Functions dealing with DNS (Canonical, FQDN, Host) Names + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + diff --git a/dll/win32/mswsock/dns/print.c b/dll/win32/mswsock/dns/print.c new file mode 100644 index 00000000000..956c4eaa03d --- /dev/null +++ b/dll/win32/mswsock/dns/print.c @@ -0,0 +1,56 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/print.c + * PURPOSE: Callback Functions for printing a variety of DNSLIB Structures + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/print.c + * PURPOSE: Callback Functions for printing a variety of DNSLIB Structures + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/print.c + * PURPOSE: Callback Functions for printing a variety of DNSLIB Structures + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/print.c + * PURPOSE: Callback Functions for printing a variety of DNSLIB Structures + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + diff --git a/dll/win32/mswsock/dns/record.c b/dll/win32/mswsock/dns/record.c new file mode 100644 index 00000000000..62f577d65e3 --- /dev/null +++ b/dll/win32/mswsock/dns/record.c @@ -0,0 +1,56 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/record.c + * PURPOSE: Functions for managing DNS Record structures. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/record.c + * PURPOSE: Functions for managing DNS Record structures. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/record.c + * PURPOSE: Functions for managing DNS Record structures. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/record.c + * PURPOSE: Functions for managing DNS Record structures. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + diff --git a/dll/win32/mswsock/dns/rrprint.c b/dll/win32/mswsock/dns/rrprint.c new file mode 100644 index 00000000000..1e302d4395e --- /dev/null +++ b/dll/win32/mswsock/dns/rrprint.c @@ -0,0 +1,56 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/rrprint.c + * PURPOSE: Callback functions for printing RR Structures for each Record. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/rrprint.c + * PURPOSE: Callback functions for printing RR Structures for each Record. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/rrprint.c + * PURPOSE: Callback functions for printing RR Structures for each Record. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/rrprint.c + * PURPOSE: Callback functions for printing RR Structures for each Record. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + diff --git a/dll/win32/mswsock/dns/sablob.c b/dll/win32/mswsock/dns/sablob.c new file mode 100644 index 00000000000..ff1a9bac9f0 --- /dev/null +++ b/dll/win32/mswsock/dns/sablob.c @@ -0,0 +1,2580 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/sablob.c + * PURPOSE: Functions for the Saved Answer Blob Implementation + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +PVOID +WINAPI +FlatBuf_Arg_ReserveAlignPointer(IN PVOID Position, + IN PSIZE_T FreeSize, + IN SIZE_T Size) +{ + /* Just a little helper that we use */ + return FlatBuf_Arg_Reserve(Position, FreeSize, Size, sizeof(PVOID)); +} + +PDNS_BLOB +WINAPI +SaBlob_Create(IN ULONG Count) +{ + PDNS_BLOB Blob; + PDNS_ARRAY DnsAddrArray; + + /* Allocate the blob */ + Blob = Dns_AllocZero(sizeof(DNS_BLOB)); + if (Blob) + { + /* Check if it'll hold any addresses */ + if (Count) + { + /* Create the DNS Address Array */ + DnsAddrArray = DnsAddrArray_Create(Count); + if (!DnsAddrArray) + { + /* Failure, free the blob */ + SaBlob_Free(Blob); + SetLastError(ERROR_OUTOFMEMORY); + } + else + { + /* Link it with the blob */ + Blob->DnsAddrArray = DnsAddrArray; + } + } + } + + /* Return the blob */ + return Blob; +} + +PDNS_BLOB +WINAPI +SaBlob_CreateFromIp4(IN LPWSTR Name, + IN ULONG Count, + IN PIN_ADDR AddressArray) +{ + PDNS_BLOB Blob; + LPWSTR NameCopy; + ULONG i; + + /* Create the blob */ + Blob = SaBlob_Create(Count); + if (!Blob) goto Quickie; + + /* If we have a name */ + if (Name) + { + /* Create a copy of it */ + NameCopy = Dns_CreateStringCopy_W(Name); + if (!NameCopy) goto Quickie; + + /* Save the pointer to the name */ + Blob->Name = NameCopy; + } + + /* Loop all the addresses */ + for (i = 0; i < Count; i++) + { + /* Add an entry for this address */ + DnsAddrArray_AddIp4(Blob->DnsAddrArray, AddressArray[i], IpV4Address); + } + + /* Return the blob */ + return Blob; + +Quickie: + /* Free the blob, set error and fail */ + SaBlob_Free(Blob); + SetLastError(ERROR_OUTOFMEMORY); + return NULL; +} + +VOID +WINAPI +SaBlob_Free(IN PDNS_BLOB Blob) +{ + /* Make sure we got a blob */ + if (Blob) + { + /* Free the name */ + Dns_Free(Blob->Name); + + /* Loop the aliases */ + while (Blob->AliasCount) + { + /* Free the alias */ + Dns_Free(Blob->Aliases[Blob->AliasCount]); + + /* Decrease number of aliases */ + Blob->AliasCount--; + } + + /* Free the DNS Address Array */ + DnsAddrArray_Free(Blob->DnsAddrArray); + + /* Free the blob itself */ + Dns_Free(Blob); + } +} + +PHOSTENT +WINAPI +SaBlob_CreateHostent(IN OUT PULONG_PTR BufferPosition, + IN OUT PSIZE_T FreeBufferSpace, + IN OUT PSIZE_T HostEntrySize, + IN PDNS_BLOB Blob, + IN DWORD StringType, + IN BOOLEAN Relative, + IN BOOLEAN BufferAllocated) +{ + PDNS_ARRAY DnsAddrArray = Blob->DnsAddrArray; + ULONG AliasCount = Blob->AliasCount; + WORD AddressFamily = AF_UNSPEC; + ULONG AddressCount = 0, AddressSize = 0, TotalSize, NamePointerSize; + ULONG AliasPointerSize; + PDNS_FAMILY_INFO FamilyInfo = NULL; + ULONG StringLength = 0; + ULONG i; + ULONG HostentSize = 0; + PHOSTENT Hostent = NULL; + ULONG_PTR HostentPtr; + PVOID CurrentAddress; + + /* Check if we actually have any addresses */ + if (DnsAddrArray) + { + /* Get the address family */ + AddressFamily = DnsAddrArray->Addresses[0].AddressFamily; + + /* Get family information */ + FamilyInfo = FamilyInfo_GetForFamily(AddressFamily); + + /* Save the current address count and their size */ + AddressCount = DnsAddrArray->UsedAddresses; + AddressSize = FamilyInfo->AddressSize; + } + + /* Calculate total size for all the addresses, and their pointers */ + TotalSize = AddressSize * AddressCount; + NamePointerSize = AddressCount * sizeof(PVOID) + sizeof(PVOID); + + /* Check if we have a name */ + if (Blob->Name) + { + /* Find out the size we'll need for a copy */ + StringLength = (Dns_GetBufferLengthForStringCopy(Blob->Name, + 0, + UnicodeString, + StringType) + 1) & ~1; + } + + /* Now do the same for the aliases */ + for (i = AliasCount; i; i--) + { + /* Find out the size we'll need for a copy */ + HostentSize += (Dns_GetBufferLengthForStringCopy(Blob->Aliases[i], + 0, + UnicodeString, + StringType) + 1) & ~1; + } + + /* Find out how much the pointers will take */ + AliasPointerSize = AliasCount * sizeof(PVOID) + sizeof(PVOID); + + /* Calculate Hostent Size */ + HostentSize += TotalSize + + NamePointerSize + + AliasPointerSize + + StringLength + + sizeof(HOSTENT); + + /* Check if we already have a buffer */ + if (!BufferAllocated) + { + /* We don't, allocate space ourselves */ + HostentPtr = (ULONG_PTR)Dns_AllocZero(HostentSize); + } + else + { + /* We do, so allocate space in the buffer */ + HostentPtr = (ULONG_PTR)FlatBuf_Arg_ReserveAlignPointer(BufferPosition, + FreeBufferSpace, + HostentSize); + } + + /* Make sure we got space */ + if (HostentPtr) + { + /* Initialize it */ + Hostent = Hostent_Init((PVOID)&HostentPtr, + AddressFamily, + AddressSize, + AddressCount, + AliasCount); + } + + /* Loop the addresses */ + for (i = 0; i < AddressCount; i++) + { + /* Get the pointer of the current address */ + CurrentAddress = (PVOID)((ULONG_PTR)&DnsAddrArray->Addresses[i] + + FamilyInfo->AddressOffset); + + /* Write the pointer */ + Hostent->h_addr_list[i] = (PCHAR)HostentPtr; + + /* Copy the address */ + RtlCopyMemory((PVOID)HostentPtr, CurrentAddress, AddressSize); + + /* Advance the buffer */ + HostentPtr += AddressSize; + } + + /* Check if we have a name */ + if (Blob->Name) + { + /* Align our current position */ + HostentPtr += 1 & ~1; + + /* Save our name here */ + Hostent->h_name = (LPSTR)HostentPtr; + + /* Now copy it in the blob */ + HostentPtr += Dns_StringCopy((PVOID)HostentPtr, + NULL, + Blob->Name, + 0, + UnicodeString, + StringType); + } + + /* Loop the Aliases */ + for (i = AliasCount; i; i--) + { + /* Align our current position */ + HostentPtr += 1 & ~1; + + /* Save our alias here */ + Hostent->h_aliases[i] = (LPSTR)HostentPtr; + + /* Now copy it in the blob */ + HostentPtr += Dns_StringCopy((PVOID)HostentPtr, + NULL, + Blob->Aliases[i], + 0, + UnicodeString, + StringType); + } + + /* Check if the caller didn't have a buffer */ + if (!BufferAllocated) + { + /* Return the size; not needed if we had a blob, since it's internal */ + *HostEntrySize = *BufferPosition - (ULONG_PTR)HostentPtr; + } + + /* Convert to Offsets if requested */ + if(Relative) Hostent_ConvertToOffsets(Hostent); + + /* Return the full, complete, hostent */ + return Hostent; +} + +INT +WINAPI +SaBlob_WriteNameOrAlias(IN PDNS_BLOB Blob, + IN LPWSTR String, + IN BOOLEAN IsAlias) +{ + /* Check if this is an alias */ + if (!IsAlias) + { + /* It's not. Simply create a copy of the string */ + Blob->Name = Dns_CreateStringCopy_W(String); + if (!Blob->Name) return GetLastError(); + } + else + { + /* Does it have a name, and less then 8 aliases? */ + if ((Blob->Name) && (Blob->AliasCount <= 8)) + { + /* Yup, create a copy of the string and increase the alias count */ + Blob->Aliases[Blob->AliasCount] = Dns_CreateStringCopy_W(String); + Blob->AliasCount++; + } + else + { + /* Invalid request! */ + return ERROR_MORE_DATA; + } + } + + /* Return Success */ + return ERROR_SUCCESS; +} + +INT +WINAPI +SaBlob_WriteAddress(IN PDNS_BLOB Blob, + OUT PDNS_ADDRESS DnsAddr) +{ + /* Check if we have an array yet */ + if (!Blob->DnsAddrArray) + { + /* Allocate one! */ + Blob->DnsAddrArray = DnsAddrArray_Create(1); + if (!Blob->DnsAddrArray) return ERROR_OUTOFMEMORY; + } + + /* Add this address */ + return DnsAddrArray_AddAddr(Blob->DnsAddrArray, DnsAddr, AF_UNSPEC, 0) ? + ERROR_SUCCESS: + ERROR_MORE_DATA; +} + +BOOLEAN +WINAPI +SaBlob_IsSupportedAddrType(WORD DnsType) +{ + /* Check for valid Types that we support */ + return (DnsType == DNS_TYPE_A || + DnsType == DNS_TYPE_ATMA || + DnsType == DNS_TYPE_AAAA); +} + +INT +WINAPI +SaBlob_WriteRecords(OUT PDNS_BLOB Blob, + IN PDNS_RECORD DnsRecord, + IN BOOLEAN DoAlias) +{ + DNS_ADDRESS DnsAddress; + INT ErrorCode = STATUS_INVALID_PARAMETER; + BOOLEAN WroteOnce = FALSE; + + /* Zero out the Address */ + RtlZeroMemory(&DnsAddress, sizeof(DnsAddress)); + + /* Loop through all the Records */ + while (DnsRecord) + { + /* Is this not an answer? */ + if (DnsRecord->Flags.S.Section != DNSREC_ANSWER) + { + /* Then simply move on to the next DNS Record */ + DnsRecord = DnsRecord->pNext; + continue; + } + + /* Check the type of thsi record */ + switch(DnsRecord->wType) + { + /* Regular IPv4, v6 or ATM Record */ + case DNS_TYPE_A: + case DNS_TYPE_AAAA: + case DNS_TYPE_ATMA: + + /* Create a DNS Address from the record */ + DnsAddr_BuildFromDnsRecord(DnsRecord, &DnsAddress); + + /* Add it to the DNS Blob */ + ErrorCode = SaBlob_WriteAddress(Blob, &DnsAddress); + + /* Add the name, if needed */ + if ((DoAlias) && + (!WroteOnce) && + (!Blob->Name) && + (DnsRecord->pName)) + { + /* Write the name from the DNS Record */ + ErrorCode = SaBlob_WriteNameOrAlias(Blob, + DnsRecord->pName, + FALSE); + WroteOnce = TRUE; + } + break; + + case DNS_TYPE_CNAME: + + /* Just write the alias name */ + ErrorCode = SaBlob_WriteNameOrAlias(Blob, + DnsRecord->pName, + TRUE); + break; + + case DNS_TYPE_PTR: + + /* Check if we already have a name */ + if (Blob->Name) + { + /* We don't, so add this as a name */ + ErrorCode = SaBlob_WriteNameOrAlias(Blob, + DnsRecord->pName, + FALSE); + } + else + { + /* We do, so add it as an alias */ + ErrorCode = SaBlob_WriteNameOrAlias(Blob, + DnsRecord->pName, + TRUE); + } + break; + default: + break; + } + + /* Next record */ + DnsRecord = DnsRecord->pNext; + } + + /* Return error code */ + return ErrorCode; +} + +PDNS_BLOB +WINAPI +SaBlob_CreateFromRecords(IN PDNS_RECORD DnsRecord, + IN BOOLEAN DoAliases, + IN DWORD DnsType) +{ + PDNS_RECORD LocalDnsRecord; + ULONG ProcessedCount = 0; + PDNS_BLOB DnsBlob; + INT ErrorCode; + DNS_ADDRESS DnsAddress; + + /* Find out how many DNS Addresses to allocate */ + LocalDnsRecord = DnsRecord; + while (LocalDnsRecord) + { + /* Make sure this record is an answer */ + if ((LocalDnsRecord->Flags.S.Section == DNSREC_ANSWER) && + (SaBlob_IsSupportedAddrType(LocalDnsRecord->wType))) + { + /* Increase number of records to process */ + ProcessedCount++; + } + + /* Move to the next record */ + LocalDnsRecord = LocalDnsRecord->pNext; + } + + /* Create the DNS Blob */ + DnsBlob = SaBlob_Create(ProcessedCount); + if (!DnsBlob) + { + /* Fail */ + ErrorCode = GetLastError(); + goto Quickie; + } + + /* Write the record to the DNS Blob */ + ErrorCode = SaBlob_WriteRecords(DnsBlob, DnsRecord, TRUE); + if (ErrorCode != NO_ERROR) + { + /* We failed... but do we still have valid data? */ + if ((DnsBlob->Name) || (DnsBlob->AliasCount)) + { + /* We'll just assume success then */ + ErrorCode = NO_ERROR; + } + else + { + /* Ok, last chance..do you have a DNS Address Array? */ + if ((DnsBlob->DnsAddrArray) && + (DnsBlob->DnsAddrArray->UsedAddresses)) + { + /* Boy are you lucky! */ + ErrorCode = NO_ERROR; + } + } + + /* Buh-bye! */ + goto Quickie; + } + + /* Check if this is a PTR record */ + if ((DnsRecord->wType == DNS_TYPE_PTR) || + ((DnsType == DNS_TYPE_PTR) && + (DnsRecord->wType == DNS_TYPE_CNAME) && + (DnsRecord->Flags.S.Section == DNSREC_ANSWER))) + { + /* Get a DNS Address Structure */ + if (Dns_ReverseNameToDnsAddr_W(&DnsAddress, DnsRecord->pName)) + { + /* Add it to the Blob */ + if (SaBlob_WriteAddress(DnsBlob, &DnsAddress)) ErrorCode = NO_ERROR; + } + } + + /* Ok...do we still not have a name? */ + if (!(DnsBlob->Name) && (DoAliases) && (LocalDnsRecord)) + { + /* We have an local DNS Record, so just use it to write the name */ + ErrorCode = SaBlob_WriteNameOrAlias(DnsBlob, + LocalDnsRecord->pName, + FALSE); + } + +Quickie: + /* Check error code */ + if (ErrorCode != NO_ERROR) + { + /* Free the blob and set the error */ + SaBlob_Free(DnsBlob); + DnsBlob = NULL; + SetLastError(ErrorCode); + } + + /* Return */ + return DnsBlob; +} + +PDNS_BLOB +WINAPI +SaBlob_Query(IN LPWSTR Name, + IN WORD DnsType, + IN ULONG Flags, + IN PVOID *Reserved, + IN DWORD AddressFamily) +{ + PDNS_RECORD DnsRecord = NULL; + INT ErrorCode; + PDNS_BLOB DnsBlob = NULL; + LPWSTR LocalName, LocalNameCopy; + + /* If they want reserved data back, clear it out in case we fail */ + if (Reserved) *Reserved = NULL; + + /* Query DNS */ + ErrorCode = DnsQuery_W(Name, + DnsType, + Flags, + NULL, + &DnsRecord, + Reserved); + if (ErrorCode != ERROR_SUCCESS) + { + /* We failed... did the caller use reserved data? */ + if (Reserved && *Reserved) + { + /* He did, and it was valid. Free it */ + DnsApiFree(*Reserved); + *Reserved = NULL; + } + + /* Normalize error code */ + if (ErrorCode == RPC_S_SERVER_UNAVAILABLE) ErrorCode = WSATRY_AGAIN; + goto Quickie; + } + + /* Now create the Blob from the DNS Records */ + DnsBlob = SaBlob_CreateFromRecords(DnsRecord, TRUE, DnsType); + if (!DnsBlob) + { + /* Failed, get error code */ + ErrorCode = GetLastError(); + goto Quickie; + } + + /* Make sure it has a name */ + if (!DnsBlob->Name) + { + /* It doesn't, fail */ + ErrorCode = DNS_INFO_NO_RECORDS; + goto Quickie; + } + + /* Check if the name is local or loopback */ + if (!(DnsNameCompare_W(DnsBlob->Name, L"localhost")) && + !(DnsNameCompare_W(DnsBlob->Name, L"loopback"))) + { + /* Nothing left to do, exit! */ + goto Quickie; + } + + /* This is a local name...query it */ + DnsQueryConfig(DnsConfigFullHostName_W, + DNS_CONFIG_FLAG_ALLOC, + NULL, + NULL, + &LocalName, + 0); + if (LocalName) + { + /* Create a copy for the caller */ + LocalNameCopy = Dns_CreateStringCopy_W(LocalName); + if (LocalNameCopy) + { + /* Overwrite the one in the blob */ + DnsBlob->Name = LocalNameCopy; + } + else + { + /* We failed to make a copy, free memory */ + DnsApiFree(LocalName); + } + } + +Quickie: + /* Free the DNS Record if we have one */ + if (DnsRecord) DnsRecordListFree(DnsRecord, DnsFreeRecordList); + + /* Check if this is a failure path with an active blob */ + if ((ErrorCode != ERROR_SUCCESS) && (DnsBlob)) + { + /* Free the blob */ + SaBlob_Free(DnsBlob); + DnsBlob = NULL; + } + + /* Set the last error and return */ + SetLastError(ErrorCode); + return DnsBlob; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/sablob.c + * PURPOSE: Functions for the Saved Answer Blob Implementation + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +PVOID +WINAPI +FlatBuf_Arg_ReserveAlignPointer(IN PVOID Position, + IN PSIZE_T FreeSize, + IN SIZE_T Size) +{ + /* Just a little helper that we use */ + return FlatBuf_Arg_Reserve(Position, FreeSize, Size, sizeof(PVOID)); +} + +PDNS_BLOB +WINAPI +SaBlob_Create(IN ULONG Count) +{ + PDNS_BLOB Blob; + PDNS_ARRAY DnsAddrArray; + + /* Allocate the blob */ + Blob = Dns_AllocZero(sizeof(DNS_BLOB)); + if (Blob) + { + /* Check if it'll hold any addresses */ + if (Count) + { + /* Create the DNS Address Array */ + DnsAddrArray = DnsAddrArray_Create(Count); + if (!DnsAddrArray) + { + /* Failure, free the blob */ + SaBlob_Free(Blob); + SetLastError(ERROR_OUTOFMEMORY); + } + else + { + /* Link it with the blob */ + Blob->DnsAddrArray = DnsAddrArray; + } + } + } + + /* Return the blob */ + return Blob; +} + +PDNS_BLOB +WINAPI +SaBlob_CreateFromIp4(IN LPWSTR Name, + IN ULONG Count, + IN PIN_ADDR AddressArray) +{ + PDNS_BLOB Blob; + LPWSTR NameCopy; + ULONG i; + + /* Create the blob */ + Blob = SaBlob_Create(Count); + if (!Blob) goto Quickie; + + /* If we have a name */ + if (Name) + { + /* Create a copy of it */ + NameCopy = Dns_CreateStringCopy_W(Name); + if (!NameCopy) goto Quickie; + + /* Save the pointer to the name */ + Blob->Name = NameCopy; + } + + /* Loop all the addresses */ + for (i = 0; i < Count; i++) + { + /* Add an entry for this address */ + DnsAddrArray_AddIp4(Blob->DnsAddrArray, AddressArray[i], IpV4Address); + } + + /* Return the blob */ + return Blob; + +Quickie: + /* Free the blob, set error and fail */ + SaBlob_Free(Blob); + SetLastError(ERROR_OUTOFMEMORY); + return NULL; +} + +VOID +WINAPI +SaBlob_Free(IN PDNS_BLOB Blob) +{ + /* Make sure we got a blob */ + if (Blob) + { + /* Free the name */ + Dns_Free(Blob->Name); + + /* Loop the aliases */ + while (Blob->AliasCount) + { + /* Free the alias */ + Dns_Free(Blob->Aliases[Blob->AliasCount]); + + /* Decrease number of aliases */ + Blob->AliasCount--; + } + + /* Free the DNS Address Array */ + DnsAddrArray_Free(Blob->DnsAddrArray); + + /* Free the blob itself */ + Dns_Free(Blob); + } +} + +PHOSTENT +WINAPI +SaBlob_CreateHostent(IN OUT PULONG_PTR BufferPosition, + IN OUT PSIZE_T FreeBufferSpace, + IN OUT PSIZE_T HostEntrySize, + IN PDNS_BLOB Blob, + IN DWORD StringType, + IN BOOLEAN Relative, + IN BOOLEAN BufferAllocated) +{ + PDNS_ARRAY DnsAddrArray = Blob->DnsAddrArray; + ULONG AliasCount = Blob->AliasCount; + WORD AddressFamily = AF_UNSPEC; + ULONG AddressCount = 0, AddressSize = 0, TotalSize, NamePointerSize; + ULONG AliasPointerSize; + PDNS_FAMILY_INFO FamilyInfo = NULL; + ULONG StringLength = 0; + ULONG i; + ULONG HostentSize = 0; + PHOSTENT Hostent = NULL; + ULONG_PTR HostentPtr; + PVOID CurrentAddress; + + /* Check if we actually have any addresses */ + if (DnsAddrArray) + { + /* Get the address family */ + AddressFamily = DnsAddrArray->Addresses[0].AddressFamily; + + /* Get family information */ + FamilyInfo = FamilyInfo_GetForFamily(AddressFamily); + + /* Save the current address count and their size */ + AddressCount = DnsAddrArray->UsedAddresses; + AddressSize = FamilyInfo->AddressSize; + } + + /* Calculate total size for all the addresses, and their pointers */ + TotalSize = AddressSize * AddressCount; + NamePointerSize = AddressCount * sizeof(PVOID) + sizeof(PVOID); + + /* Check if we have a name */ + if (Blob->Name) + { + /* Find out the size we'll need for a copy */ + StringLength = (Dns_GetBufferLengthForStringCopy(Blob->Name, + 0, + UnicodeString, + StringType) + 1) & ~1; + } + + /* Now do the same for the aliases */ + for (i = AliasCount; i; i--) + { + /* Find out the size we'll need for a copy */ + HostentSize += (Dns_GetBufferLengthForStringCopy(Blob->Aliases[i], + 0, + UnicodeString, + StringType) + 1) & ~1; + } + + /* Find out how much the pointers will take */ + AliasPointerSize = AliasCount * sizeof(PVOID) + sizeof(PVOID); + + /* Calculate Hostent Size */ + HostentSize += TotalSize + + NamePointerSize + + AliasPointerSize + + StringLength + + sizeof(HOSTENT); + + /* Check if we already have a buffer */ + if (!BufferAllocated) + { + /* We don't, allocate space ourselves */ + HostentPtr = (ULONG_PTR)Dns_AllocZero(HostentSize); + } + else + { + /* We do, so allocate space in the buffer */ + HostentPtr = (ULONG_PTR)FlatBuf_Arg_ReserveAlignPointer(BufferPosition, + FreeBufferSpace, + HostentSize); + } + + /* Make sure we got space */ + if (HostentPtr) + { + /* Initialize it */ + Hostent = Hostent_Init((PVOID)&HostentPtr, + AddressFamily, + AddressSize, + AddressCount, + AliasCount); + } + + /* Loop the addresses */ + for (i = 0; i < AddressCount; i++) + { + /* Get the pointer of the current address */ + CurrentAddress = (PVOID)((ULONG_PTR)&DnsAddrArray->Addresses[i] + + FamilyInfo->AddressOffset); + + /* Write the pointer */ + Hostent->h_addr_list[i] = (PCHAR)HostentPtr; + + /* Copy the address */ + RtlCopyMemory((PVOID)HostentPtr, CurrentAddress, AddressSize); + + /* Advance the buffer */ + HostentPtr += AddressSize; + } + + /* Check if we have a name */ + if (Blob->Name) + { + /* Align our current position */ + HostentPtr += 1 & ~1; + + /* Save our name here */ + Hostent->h_name = (LPSTR)HostentPtr; + + /* Now copy it in the blob */ + HostentPtr += Dns_StringCopy((PVOID)HostentPtr, + NULL, + Blob->Name, + 0, + UnicodeString, + StringType); + } + + /* Loop the Aliases */ + for (i = AliasCount; i; i--) + { + /* Align our current position */ + HostentPtr += 1 & ~1; + + /* Save our alias here */ + Hostent->h_aliases[i] = (LPSTR)HostentPtr; + + /* Now copy it in the blob */ + HostentPtr += Dns_StringCopy((PVOID)HostentPtr, + NULL, + Blob->Aliases[i], + 0, + UnicodeString, + StringType); + } + + /* Check if the caller didn't have a buffer */ + if (!BufferAllocated) + { + /* Return the size; not needed if we had a blob, since it's internal */ + *HostEntrySize = *BufferPosition - (ULONG_PTR)HostentPtr; + } + + /* Convert to Offsets if requested */ + if(Relative) Hostent_ConvertToOffsets(Hostent); + + /* Return the full, complete, hostent */ + return Hostent; +} + +INT +WINAPI +SaBlob_WriteNameOrAlias(IN PDNS_BLOB Blob, + IN LPWSTR String, + IN BOOLEAN IsAlias) +{ + /* Check if this is an alias */ + if (!IsAlias) + { + /* It's not. Simply create a copy of the string */ + Blob->Name = Dns_CreateStringCopy_W(String); + if (!Blob->Name) return GetLastError(); + } + else + { + /* Does it have a name, and less then 8 aliases? */ + if ((Blob->Name) && (Blob->AliasCount <= 8)) + { + /* Yup, create a copy of the string and increase the alias count */ + Blob->Aliases[Blob->AliasCount] = Dns_CreateStringCopy_W(String); + Blob->AliasCount++; + } + else + { + /* Invalid request! */ + return ERROR_MORE_DATA; + } + } + + /* Return Success */ + return ERROR_SUCCESS; +} + +INT +WINAPI +SaBlob_WriteAddress(IN PDNS_BLOB Blob, + OUT PDNS_ADDRESS DnsAddr) +{ + /* Check if we have an array yet */ + if (!Blob->DnsAddrArray) + { + /* Allocate one! */ + Blob->DnsAddrArray = DnsAddrArray_Create(1); + if (!Blob->DnsAddrArray) return ERROR_OUTOFMEMORY; + } + + /* Add this address */ + return DnsAddrArray_AddAddr(Blob->DnsAddrArray, DnsAddr, AF_UNSPEC, 0) ? + ERROR_SUCCESS: + ERROR_MORE_DATA; +} + +BOOLEAN +WINAPI +SaBlob_IsSupportedAddrType(WORD DnsType) +{ + /* Check for valid Types that we support */ + return (DnsType == DNS_TYPE_A || + DnsType == DNS_TYPE_ATMA || + DnsType == DNS_TYPE_AAAA); +} + +INT +WINAPI +SaBlob_WriteRecords(OUT PDNS_BLOB Blob, + IN PDNS_RECORD DnsRecord, + IN BOOLEAN DoAlias) +{ + DNS_ADDRESS DnsAddress; + INT ErrorCode = STATUS_INVALID_PARAMETER; + BOOLEAN WroteOnce = FALSE; + + /* Zero out the Address */ + RtlZeroMemory(&DnsAddress, sizeof(DnsAddress)); + + /* Loop through all the Records */ + while (DnsRecord) + { + /* Is this not an answer? */ + if (DnsRecord->Flags.S.Section != DNSREC_ANSWER) + { + /* Then simply move on to the next DNS Record */ + DnsRecord = DnsRecord->pNext; + continue; + } + + /* Check the type of thsi record */ + switch(DnsRecord->wType) + { + /* Regular IPv4, v6 or ATM Record */ + case DNS_TYPE_A: + case DNS_TYPE_AAAA: + case DNS_TYPE_ATMA: + + /* Create a DNS Address from the record */ + DnsAddr_BuildFromDnsRecord(DnsRecord, &DnsAddress); + + /* Add it to the DNS Blob */ + ErrorCode = SaBlob_WriteAddress(Blob, &DnsAddress); + + /* Add the name, if needed */ + if ((DoAlias) && + (!WroteOnce) && + (!Blob->Name) && + (DnsRecord->pName)) + { + /* Write the name from the DNS Record */ + ErrorCode = SaBlob_WriteNameOrAlias(Blob, + DnsRecord->pName, + FALSE); + WroteOnce = TRUE; + } + break; + + case DNS_TYPE_CNAME: + + /* Just write the alias name */ + ErrorCode = SaBlob_WriteNameOrAlias(Blob, + DnsRecord->pName, + TRUE); + break; + + case DNS_TYPE_PTR: + + /* Check if we already have a name */ + if (Blob->Name) + { + /* We don't, so add this as a name */ + ErrorCode = SaBlob_WriteNameOrAlias(Blob, + DnsRecord->pName, + FALSE); + } + else + { + /* We do, so add it as an alias */ + ErrorCode = SaBlob_WriteNameOrAlias(Blob, + DnsRecord->pName, + TRUE); + } + break; + default: + break; + } + + /* Next record */ + DnsRecord = DnsRecord->pNext; + } + + /* Return error code */ + return ErrorCode; +} + +PDNS_BLOB +WINAPI +SaBlob_CreateFromRecords(IN PDNS_RECORD DnsRecord, + IN BOOLEAN DoAliases, + IN DWORD DnsType) +{ + PDNS_RECORD LocalDnsRecord; + ULONG ProcessedCount = 0; + PDNS_BLOB DnsBlob; + INT ErrorCode; + DNS_ADDRESS DnsAddress; + + /* Find out how many DNS Addresses to allocate */ + LocalDnsRecord = DnsRecord; + while (LocalDnsRecord) + { + /* Make sure this record is an answer */ + if ((LocalDnsRecord->Flags.S.Section == DNSREC_ANSWER) && + (SaBlob_IsSupportedAddrType(LocalDnsRecord->wType))) + { + /* Increase number of records to process */ + ProcessedCount++; + } + + /* Move to the next record */ + LocalDnsRecord = LocalDnsRecord->pNext; + } + + /* Create the DNS Blob */ + DnsBlob = SaBlob_Create(ProcessedCount); + if (!DnsBlob) + { + /* Fail */ + ErrorCode = GetLastError(); + goto Quickie; + } + + /* Write the record to the DNS Blob */ + ErrorCode = SaBlob_WriteRecords(DnsBlob, DnsRecord, TRUE); + if (ErrorCode != NO_ERROR) + { + /* We failed... but do we still have valid data? */ + if ((DnsBlob->Name) || (DnsBlob->AliasCount)) + { + /* We'll just assume success then */ + ErrorCode = NO_ERROR; + } + else + { + /* Ok, last chance..do you have a DNS Address Array? */ + if ((DnsBlob->DnsAddrArray) && + (DnsBlob->DnsAddrArray->UsedAddresses)) + { + /* Boy are you lucky! */ + ErrorCode = NO_ERROR; + } + } + + /* Buh-bye! */ + goto Quickie; + } + + /* Check if this is a PTR record */ + if ((DnsRecord->wType == DNS_TYPE_PTR) || + ((DnsType == DNS_TYPE_PTR) && + (DnsRecord->wType == DNS_TYPE_CNAME) && + (DnsRecord->Flags.S.Section == DNSREC_ANSWER))) + { + /* Get a DNS Address Structure */ + if (Dns_ReverseNameToDnsAddr_W(&DnsAddress, DnsRecord->pName)) + { + /* Add it to the Blob */ + if (SaBlob_WriteAddress(DnsBlob, &DnsAddress)) ErrorCode = NO_ERROR; + } + } + + /* Ok...do we still not have a name? */ + if (!(DnsBlob->Name) && (DoAliases) && (LocalDnsRecord)) + { + /* We have an local DNS Record, so just use it to write the name */ + ErrorCode = SaBlob_WriteNameOrAlias(DnsBlob, + LocalDnsRecord->pName, + FALSE); + } + +Quickie: + /* Check error code */ + if (ErrorCode != NO_ERROR) + { + /* Free the blob and set the error */ + SaBlob_Free(DnsBlob); + DnsBlob = NULL; + SetLastError(ErrorCode); + } + + /* Return */ + return DnsBlob; +} + +PDNS_BLOB +WINAPI +SaBlob_Query(IN LPWSTR Name, + IN WORD DnsType, + IN ULONG Flags, + IN PVOID *Reserved, + IN DWORD AddressFamily) +{ + PDNS_RECORD DnsRecord = NULL; + INT ErrorCode; + PDNS_BLOB DnsBlob = NULL; + LPWSTR LocalName, LocalNameCopy; + + /* If they want reserved data back, clear it out in case we fail */ + if (Reserved) *Reserved = NULL; + + /* Query DNS */ + ErrorCode = DnsQuery_W(Name, + DnsType, + Flags, + NULL, + &DnsRecord, + Reserved); + if (ErrorCode != ERROR_SUCCESS) + { + /* We failed... did the caller use reserved data? */ + if (Reserved && *Reserved) + { + /* He did, and it was valid. Free it */ + DnsApiFree(*Reserved); + *Reserved = NULL; + } + + /* Normalize error code */ + if (ErrorCode == RPC_S_SERVER_UNAVAILABLE) ErrorCode = WSATRY_AGAIN; + goto Quickie; + } + + /* Now create the Blob from the DNS Records */ + DnsBlob = SaBlob_CreateFromRecords(DnsRecord, TRUE, DnsType); + if (!DnsBlob) + { + /* Failed, get error code */ + ErrorCode = GetLastError(); + goto Quickie; + } + + /* Make sure it has a name */ + if (!DnsBlob->Name) + { + /* It doesn't, fail */ + ErrorCode = DNS_INFO_NO_RECORDS; + goto Quickie; + } + + /* Check if the name is local or loopback */ + if (!(DnsNameCompare_W(DnsBlob->Name, L"localhost")) && + !(DnsNameCompare_W(DnsBlob->Name, L"loopback"))) + { + /* Nothing left to do, exit! */ + goto Quickie; + } + + /* This is a local name...query it */ + DnsQueryConfig(DnsConfigFullHostName_W, + DNS_CONFIG_FLAG_ALLOC, + NULL, + NULL, + &LocalName, + 0); + if (LocalName) + { + /* Create a copy for the caller */ + LocalNameCopy = Dns_CreateStringCopy_W(LocalName); + if (LocalNameCopy) + { + /* Overwrite the one in the blob */ + DnsBlob->Name = LocalNameCopy; + } + else + { + /* We failed to make a copy, free memory */ + DnsApiFree(LocalName); + } + } + +Quickie: + /* Free the DNS Record if we have one */ + if (DnsRecord) DnsRecordListFree(DnsRecord, DnsFreeRecordList); + + /* Check if this is a failure path with an active blob */ + if ((ErrorCode != ERROR_SUCCESS) && (DnsBlob)) + { + /* Free the blob */ + SaBlob_Free(DnsBlob); + DnsBlob = NULL; + } + + /* Set the last error and return */ + SetLastError(ErrorCode); + return DnsBlob; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/sablob.c + * PURPOSE: Functions for the Saved Answer Blob Implementation + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +PVOID +WINAPI +FlatBuf_Arg_ReserveAlignPointer(IN PVOID Position, + IN PSIZE_T FreeSize, + IN SIZE_T Size) +{ + /* Just a little helper that we use */ + return FlatBuf_Arg_Reserve(Position, FreeSize, Size, sizeof(PVOID)); +} + +PDNS_BLOB +WINAPI +SaBlob_Create(IN ULONG Count) +{ + PDNS_BLOB Blob; + PDNS_ARRAY DnsAddrArray; + + /* Allocate the blob */ + Blob = Dns_AllocZero(sizeof(DNS_BLOB)); + if (Blob) + { + /* Check if it'll hold any addresses */ + if (Count) + { + /* Create the DNS Address Array */ + DnsAddrArray = DnsAddrArray_Create(Count); + if (!DnsAddrArray) + { + /* Failure, free the blob */ + SaBlob_Free(Blob); + SetLastError(ERROR_OUTOFMEMORY); + } + else + { + /* Link it with the blob */ + Blob->DnsAddrArray = DnsAddrArray; + } + } + } + + /* Return the blob */ + return Blob; +} + +PDNS_BLOB +WINAPI +SaBlob_CreateFromIp4(IN LPWSTR Name, + IN ULONG Count, + IN PIN_ADDR AddressArray) +{ + PDNS_BLOB Blob; + LPWSTR NameCopy; + ULONG i; + + /* Create the blob */ + Blob = SaBlob_Create(Count); + if (!Blob) goto Quickie; + + /* If we have a name */ + if (Name) + { + /* Create a copy of it */ + NameCopy = Dns_CreateStringCopy_W(Name); + if (!NameCopy) goto Quickie; + + /* Save the pointer to the name */ + Blob->Name = NameCopy; + } + + /* Loop all the addresses */ + for (i = 0; i < Count; i++) + { + /* Add an entry for this address */ + DnsAddrArray_AddIp4(Blob->DnsAddrArray, AddressArray[i], IpV4Address); + } + + /* Return the blob */ + return Blob; + +Quickie: + /* Free the blob, set error and fail */ + SaBlob_Free(Blob); + SetLastError(ERROR_OUTOFMEMORY); + return NULL; +} + +VOID +WINAPI +SaBlob_Free(IN PDNS_BLOB Blob) +{ + /* Make sure we got a blob */ + if (Blob) + { + /* Free the name */ + Dns_Free(Blob->Name); + + /* Loop the aliases */ + while (Blob->AliasCount) + { + /* Free the alias */ + Dns_Free(Blob->Aliases[Blob->AliasCount]); + + /* Decrease number of aliases */ + Blob->AliasCount--; + } + + /* Free the DNS Address Array */ + DnsAddrArray_Free(Blob->DnsAddrArray); + + /* Free the blob itself */ + Dns_Free(Blob); + } +} + +PHOSTENT +WINAPI +SaBlob_CreateHostent(IN OUT PULONG_PTR BufferPosition, + IN OUT PSIZE_T FreeBufferSpace, + IN OUT PSIZE_T HostEntrySize, + IN PDNS_BLOB Blob, + IN DWORD StringType, + IN BOOLEAN Relative, + IN BOOLEAN BufferAllocated) +{ + PDNS_ARRAY DnsAddrArray = Blob->DnsAddrArray; + ULONG AliasCount = Blob->AliasCount; + WORD AddressFamily = AF_UNSPEC; + ULONG AddressCount = 0, AddressSize = 0, TotalSize, NamePointerSize; + ULONG AliasPointerSize; + PDNS_FAMILY_INFO FamilyInfo = NULL; + ULONG StringLength = 0; + ULONG i; + ULONG HostentSize = 0; + PHOSTENT Hostent = NULL; + ULONG_PTR HostentPtr; + PVOID CurrentAddress; + + /* Check if we actually have any addresses */ + if (DnsAddrArray) + { + /* Get the address family */ + AddressFamily = DnsAddrArray->Addresses[0].AddressFamily; + + /* Get family information */ + FamilyInfo = FamilyInfo_GetForFamily(AddressFamily); + + /* Save the current address count and their size */ + AddressCount = DnsAddrArray->UsedAddresses; + AddressSize = FamilyInfo->AddressSize; + } + + /* Calculate total size for all the addresses, and their pointers */ + TotalSize = AddressSize * AddressCount; + NamePointerSize = AddressCount * sizeof(PVOID) + sizeof(PVOID); + + /* Check if we have a name */ + if (Blob->Name) + { + /* Find out the size we'll need for a copy */ + StringLength = (Dns_GetBufferLengthForStringCopy(Blob->Name, + 0, + UnicodeString, + StringType) + 1) & ~1; + } + + /* Now do the same for the aliases */ + for (i = AliasCount; i; i--) + { + /* Find out the size we'll need for a copy */ + HostentSize += (Dns_GetBufferLengthForStringCopy(Blob->Aliases[i], + 0, + UnicodeString, + StringType) + 1) & ~1; + } + + /* Find out how much the pointers will take */ + AliasPointerSize = AliasCount * sizeof(PVOID) + sizeof(PVOID); + + /* Calculate Hostent Size */ + HostentSize += TotalSize + + NamePointerSize + + AliasPointerSize + + StringLength + + sizeof(HOSTENT); + + /* Check if we already have a buffer */ + if (!BufferAllocated) + { + /* We don't, allocate space ourselves */ + HostentPtr = (ULONG_PTR)Dns_AllocZero(HostentSize); + } + else + { + /* We do, so allocate space in the buffer */ + HostentPtr = (ULONG_PTR)FlatBuf_Arg_ReserveAlignPointer(BufferPosition, + FreeBufferSpace, + HostentSize); + } + + /* Make sure we got space */ + if (HostentPtr) + { + /* Initialize it */ + Hostent = Hostent_Init((PVOID)&HostentPtr, + AddressFamily, + AddressSize, + AddressCount, + AliasCount); + } + + /* Loop the addresses */ + for (i = 0; i < AddressCount; i++) + { + /* Get the pointer of the current address */ + CurrentAddress = (PVOID)((ULONG_PTR)&DnsAddrArray->Addresses[i] + + FamilyInfo->AddressOffset); + + /* Write the pointer */ + Hostent->h_addr_list[i] = (PCHAR)HostentPtr; + + /* Copy the address */ + RtlCopyMemory((PVOID)HostentPtr, CurrentAddress, AddressSize); + + /* Advance the buffer */ + HostentPtr += AddressSize; + } + + /* Check if we have a name */ + if (Blob->Name) + { + /* Align our current position */ + HostentPtr += 1 & ~1; + + /* Save our name here */ + Hostent->h_name = (LPSTR)HostentPtr; + + /* Now copy it in the blob */ + HostentPtr += Dns_StringCopy((PVOID)HostentPtr, + NULL, + Blob->Name, + 0, + UnicodeString, + StringType); + } + + /* Loop the Aliases */ + for (i = AliasCount; i; i--) + { + /* Align our current position */ + HostentPtr += 1 & ~1; + + /* Save our alias here */ + Hostent->h_aliases[i] = (LPSTR)HostentPtr; + + /* Now copy it in the blob */ + HostentPtr += Dns_StringCopy((PVOID)HostentPtr, + NULL, + Blob->Aliases[i], + 0, + UnicodeString, + StringType); + } + + /* Check if the caller didn't have a buffer */ + if (!BufferAllocated) + { + /* Return the size; not needed if we had a blob, since it's internal */ + *HostEntrySize = *BufferPosition - (ULONG_PTR)HostentPtr; + } + + /* Convert to Offsets if requested */ + if(Relative) Hostent_ConvertToOffsets(Hostent); + + /* Return the full, complete, hostent */ + return Hostent; +} + +INT +WINAPI +SaBlob_WriteNameOrAlias(IN PDNS_BLOB Blob, + IN LPWSTR String, + IN BOOLEAN IsAlias) +{ + /* Check if this is an alias */ + if (!IsAlias) + { + /* It's not. Simply create a copy of the string */ + Blob->Name = Dns_CreateStringCopy_W(String); + if (!Blob->Name) return GetLastError(); + } + else + { + /* Does it have a name, and less then 8 aliases? */ + if ((Blob->Name) && (Blob->AliasCount <= 8)) + { + /* Yup, create a copy of the string and increase the alias count */ + Blob->Aliases[Blob->AliasCount] = Dns_CreateStringCopy_W(String); + Blob->AliasCount++; + } + else + { + /* Invalid request! */ + return ERROR_MORE_DATA; + } + } + + /* Return Success */ + return ERROR_SUCCESS; +} + +INT +WINAPI +SaBlob_WriteAddress(IN PDNS_BLOB Blob, + OUT PDNS_ADDRESS DnsAddr) +{ + /* Check if we have an array yet */ + if (!Blob->DnsAddrArray) + { + /* Allocate one! */ + Blob->DnsAddrArray = DnsAddrArray_Create(1); + if (!Blob->DnsAddrArray) return ERROR_OUTOFMEMORY; + } + + /* Add this address */ + return DnsAddrArray_AddAddr(Blob->DnsAddrArray, DnsAddr, AF_UNSPEC, 0) ? + ERROR_SUCCESS: + ERROR_MORE_DATA; +} + +BOOLEAN +WINAPI +SaBlob_IsSupportedAddrType(WORD DnsType) +{ + /* Check for valid Types that we support */ + return (DnsType == DNS_TYPE_A || + DnsType == DNS_TYPE_ATMA || + DnsType == DNS_TYPE_AAAA); +} + +INT +WINAPI +SaBlob_WriteRecords(OUT PDNS_BLOB Blob, + IN PDNS_RECORD DnsRecord, + IN BOOLEAN DoAlias) +{ + DNS_ADDRESS DnsAddress; + INT ErrorCode = STATUS_INVALID_PARAMETER; + BOOLEAN WroteOnce = FALSE; + + /* Zero out the Address */ + RtlZeroMemory(&DnsAddress, sizeof(DnsAddress)); + + /* Loop through all the Records */ + while (DnsRecord) + { + /* Is this not an answer? */ + if (DnsRecord->Flags.S.Section != DNSREC_ANSWER) + { + /* Then simply move on to the next DNS Record */ + DnsRecord = DnsRecord->pNext; + continue; + } + + /* Check the type of thsi record */ + switch(DnsRecord->wType) + { + /* Regular IPv4, v6 or ATM Record */ + case DNS_TYPE_A: + case DNS_TYPE_AAAA: + case DNS_TYPE_ATMA: + + /* Create a DNS Address from the record */ + DnsAddr_BuildFromDnsRecord(DnsRecord, &DnsAddress); + + /* Add it to the DNS Blob */ + ErrorCode = SaBlob_WriteAddress(Blob, &DnsAddress); + + /* Add the name, if needed */ + if ((DoAlias) && + (!WroteOnce) && + (!Blob->Name) && + (DnsRecord->pName)) + { + /* Write the name from the DNS Record */ + ErrorCode = SaBlob_WriteNameOrAlias(Blob, + DnsRecord->pName, + FALSE); + WroteOnce = TRUE; + } + break; + + case DNS_TYPE_CNAME: + + /* Just write the alias name */ + ErrorCode = SaBlob_WriteNameOrAlias(Blob, + DnsRecord->pName, + TRUE); + break; + + case DNS_TYPE_PTR: + + /* Check if we already have a name */ + if (Blob->Name) + { + /* We don't, so add this as a name */ + ErrorCode = SaBlob_WriteNameOrAlias(Blob, + DnsRecord->pName, + FALSE); + } + else + { + /* We do, so add it as an alias */ + ErrorCode = SaBlob_WriteNameOrAlias(Blob, + DnsRecord->pName, + TRUE); + } + break; + default: + break; + } + + /* Next record */ + DnsRecord = DnsRecord->pNext; + } + + /* Return error code */ + return ErrorCode; +} + +PDNS_BLOB +WINAPI +SaBlob_CreateFromRecords(IN PDNS_RECORD DnsRecord, + IN BOOLEAN DoAliases, + IN DWORD DnsType) +{ + PDNS_RECORD LocalDnsRecord; + ULONG ProcessedCount = 0; + PDNS_BLOB DnsBlob; + INT ErrorCode; + DNS_ADDRESS DnsAddress; + + /* Find out how many DNS Addresses to allocate */ + LocalDnsRecord = DnsRecord; + while (LocalDnsRecord) + { + /* Make sure this record is an answer */ + if ((LocalDnsRecord->Flags.S.Section == DNSREC_ANSWER) && + (SaBlob_IsSupportedAddrType(LocalDnsRecord->wType))) + { + /* Increase number of records to process */ + ProcessedCount++; + } + + /* Move to the next record */ + LocalDnsRecord = LocalDnsRecord->pNext; + } + + /* Create the DNS Blob */ + DnsBlob = SaBlob_Create(ProcessedCount); + if (!DnsBlob) + { + /* Fail */ + ErrorCode = GetLastError(); + goto Quickie; + } + + /* Write the record to the DNS Blob */ + ErrorCode = SaBlob_WriteRecords(DnsBlob, DnsRecord, TRUE); + if (ErrorCode != NO_ERROR) + { + /* We failed... but do we still have valid data? */ + if ((DnsBlob->Name) || (DnsBlob->AliasCount)) + { + /* We'll just assume success then */ + ErrorCode = NO_ERROR; + } + else + { + /* Ok, last chance..do you have a DNS Address Array? */ + if ((DnsBlob->DnsAddrArray) && + (DnsBlob->DnsAddrArray->UsedAddresses)) + { + /* Boy are you lucky! */ + ErrorCode = NO_ERROR; + } + } + + /* Buh-bye! */ + goto Quickie; + } + + /* Check if this is a PTR record */ + if ((DnsRecord->wType == DNS_TYPE_PTR) || + ((DnsType == DNS_TYPE_PTR) && + (DnsRecord->wType == DNS_TYPE_CNAME) && + (DnsRecord->Flags.S.Section == DNSREC_ANSWER))) + { + /* Get a DNS Address Structure */ + if (Dns_ReverseNameToDnsAddr_W(&DnsAddress, DnsRecord->pName)) + { + /* Add it to the Blob */ + if (SaBlob_WriteAddress(DnsBlob, &DnsAddress)) ErrorCode = NO_ERROR; + } + } + + /* Ok...do we still not have a name? */ + if (!(DnsBlob->Name) && (DoAliases) && (LocalDnsRecord)) + { + /* We have an local DNS Record, so just use it to write the name */ + ErrorCode = SaBlob_WriteNameOrAlias(DnsBlob, + LocalDnsRecord->pName, + FALSE); + } + +Quickie: + /* Check error code */ + if (ErrorCode != NO_ERROR) + { + /* Free the blob and set the error */ + SaBlob_Free(DnsBlob); + DnsBlob = NULL; + SetLastError(ErrorCode); + } + + /* Return */ + return DnsBlob; +} + +PDNS_BLOB +WINAPI +SaBlob_Query(IN LPWSTR Name, + IN WORD DnsType, + IN ULONG Flags, + IN PVOID *Reserved, + IN DWORD AddressFamily) +{ + PDNS_RECORD DnsRecord = NULL; + INT ErrorCode; + PDNS_BLOB DnsBlob = NULL; + LPWSTR LocalName, LocalNameCopy; + + /* If they want reserved data back, clear it out in case we fail */ + if (Reserved) *Reserved = NULL; + + /* Query DNS */ + ErrorCode = DnsQuery_W(Name, + DnsType, + Flags, + NULL, + &DnsRecord, + Reserved); + if (ErrorCode != ERROR_SUCCESS) + { + /* We failed... did the caller use reserved data? */ + if (Reserved && *Reserved) + { + /* He did, and it was valid. Free it */ + DnsApiFree(*Reserved); + *Reserved = NULL; + } + + /* Normalize error code */ + if (ErrorCode == RPC_S_SERVER_UNAVAILABLE) ErrorCode = WSATRY_AGAIN; + goto Quickie; + } + + /* Now create the Blob from the DNS Records */ + DnsBlob = SaBlob_CreateFromRecords(DnsRecord, TRUE, DnsType); + if (!DnsBlob) + { + /* Failed, get error code */ + ErrorCode = GetLastError(); + goto Quickie; + } + + /* Make sure it has a name */ + if (!DnsBlob->Name) + { + /* It doesn't, fail */ + ErrorCode = DNS_INFO_NO_RECORDS; + goto Quickie; + } + + /* Check if the name is local or loopback */ + if (!(DnsNameCompare_W(DnsBlob->Name, L"localhost")) && + !(DnsNameCompare_W(DnsBlob->Name, L"loopback"))) + { + /* Nothing left to do, exit! */ + goto Quickie; + } + + /* This is a local name...query it */ + DnsQueryConfig(DnsConfigFullHostName_W, + DNS_CONFIG_FLAG_ALLOC, + NULL, + NULL, + &LocalName, + 0); + if (LocalName) + { + /* Create a copy for the caller */ + LocalNameCopy = Dns_CreateStringCopy_W(LocalName); + if (LocalNameCopy) + { + /* Overwrite the one in the blob */ + DnsBlob->Name = LocalNameCopy; + } + else + { + /* We failed to make a copy, free memory */ + DnsApiFree(LocalName); + } + } + +Quickie: + /* Free the DNS Record if we have one */ + if (DnsRecord) DnsRecordListFree(DnsRecord, DnsFreeRecordList); + + /* Check if this is a failure path with an active blob */ + if ((ErrorCode != ERROR_SUCCESS) && (DnsBlob)) + { + /* Free the blob */ + SaBlob_Free(DnsBlob); + DnsBlob = NULL; + } + + /* Set the last error and return */ + SetLastError(ErrorCode); + return DnsBlob; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/sablob.c + * PURPOSE: Functions for the Saved Answer Blob Implementation + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +PVOID +WINAPI +FlatBuf_Arg_ReserveAlignPointer(IN PVOID Position, + IN PSIZE_T FreeSize, + IN SIZE_T Size) +{ + /* Just a little helper that we use */ + return FlatBuf_Arg_Reserve(Position, FreeSize, Size, sizeof(PVOID)); +} + +PDNS_BLOB +WINAPI +SaBlob_Create(IN ULONG Count) +{ + PDNS_BLOB Blob; + PDNS_ARRAY DnsAddrArray; + + /* Allocate the blob */ + Blob = Dns_AllocZero(sizeof(DNS_BLOB)); + if (Blob) + { + /* Check if it'll hold any addresses */ + if (Count) + { + /* Create the DNS Address Array */ + DnsAddrArray = DnsAddrArray_Create(Count); + if (!DnsAddrArray) + { + /* Failure, free the blob */ + SaBlob_Free(Blob); + SetLastError(ERROR_OUTOFMEMORY); + } + else + { + /* Link it with the blob */ + Blob->DnsAddrArray = DnsAddrArray; + } + } + } + + /* Return the blob */ + return Blob; +} + +PDNS_BLOB +WINAPI +SaBlob_CreateFromIp4(IN LPWSTR Name, + IN ULONG Count, + IN PIN_ADDR AddressArray) +{ + PDNS_BLOB Blob; + LPWSTR NameCopy; + ULONG i; + + /* Create the blob */ + Blob = SaBlob_Create(Count); + if (!Blob) goto Quickie; + + /* If we have a name */ + if (Name) + { + /* Create a copy of it */ + NameCopy = Dns_CreateStringCopy_W(Name); + if (!NameCopy) goto Quickie; + + /* Save the pointer to the name */ + Blob->Name = NameCopy; + } + + /* Loop all the addresses */ + for (i = 0; i < Count; i++) + { + /* Add an entry for this address */ + DnsAddrArray_AddIp4(Blob->DnsAddrArray, AddressArray[i], IpV4Address); + } + + /* Return the blob */ + return Blob; + +Quickie: + /* Free the blob, set error and fail */ + SaBlob_Free(Blob); + SetLastError(ERROR_OUTOFMEMORY); + return NULL; +} + +VOID +WINAPI +SaBlob_Free(IN PDNS_BLOB Blob) +{ + /* Make sure we got a blob */ + if (Blob) + { + /* Free the name */ + Dns_Free(Blob->Name); + + /* Loop the aliases */ + while (Blob->AliasCount) + { + /* Free the alias */ + Dns_Free(Blob->Aliases[Blob->AliasCount]); + + /* Decrease number of aliases */ + Blob->AliasCount--; + } + + /* Free the DNS Address Array */ + DnsAddrArray_Free(Blob->DnsAddrArray); + + /* Free the blob itself */ + Dns_Free(Blob); + } +} + +PHOSTENT +WINAPI +SaBlob_CreateHostent(IN OUT PULONG_PTR BufferPosition, + IN OUT PSIZE_T FreeBufferSpace, + IN OUT PSIZE_T HostEntrySize, + IN PDNS_BLOB Blob, + IN DWORD StringType, + IN BOOLEAN Relative, + IN BOOLEAN BufferAllocated) +{ + PDNS_ARRAY DnsAddrArray = Blob->DnsAddrArray; + ULONG AliasCount = Blob->AliasCount; + WORD AddressFamily = AF_UNSPEC; + ULONG AddressCount = 0, AddressSize = 0, TotalSize, NamePointerSize; + ULONG AliasPointerSize; + PDNS_FAMILY_INFO FamilyInfo = NULL; + ULONG StringLength = 0; + ULONG i; + ULONG HostentSize = 0; + PHOSTENT Hostent = NULL; + ULONG_PTR HostentPtr; + PVOID CurrentAddress; + + /* Check if we actually have any addresses */ + if (DnsAddrArray) + { + /* Get the address family */ + AddressFamily = DnsAddrArray->Addresses[0].AddressFamily; + + /* Get family information */ + FamilyInfo = FamilyInfo_GetForFamily(AddressFamily); + + /* Save the current address count and their size */ + AddressCount = DnsAddrArray->UsedAddresses; + AddressSize = FamilyInfo->AddressSize; + } + + /* Calculate total size for all the addresses, and their pointers */ + TotalSize = AddressSize * AddressCount; + NamePointerSize = AddressCount * sizeof(PVOID) + sizeof(PVOID); + + /* Check if we have a name */ + if (Blob->Name) + { + /* Find out the size we'll need for a copy */ + StringLength = (Dns_GetBufferLengthForStringCopy(Blob->Name, + 0, + UnicodeString, + StringType) + 1) & ~1; + } + + /* Now do the same for the aliases */ + for (i = AliasCount; i; i--) + { + /* Find out the size we'll need for a copy */ + HostentSize += (Dns_GetBufferLengthForStringCopy(Blob->Aliases[i], + 0, + UnicodeString, + StringType) + 1) & ~1; + } + + /* Find out how much the pointers will take */ + AliasPointerSize = AliasCount * sizeof(PVOID) + sizeof(PVOID); + + /* Calculate Hostent Size */ + HostentSize += TotalSize + + NamePointerSize + + AliasPointerSize + + StringLength + + sizeof(HOSTENT); + + /* Check if we already have a buffer */ + if (!BufferAllocated) + { + /* We don't, allocate space ourselves */ + HostentPtr = (ULONG_PTR)Dns_AllocZero(HostentSize); + } + else + { + /* We do, so allocate space in the buffer */ + HostentPtr = (ULONG_PTR)FlatBuf_Arg_ReserveAlignPointer(BufferPosition, + FreeBufferSpace, + HostentSize); + } + + /* Make sure we got space */ + if (HostentPtr) + { + /* Initialize it */ + Hostent = Hostent_Init((PVOID)&HostentPtr, + AddressFamily, + AddressSize, + AddressCount, + AliasCount); + } + + /* Loop the addresses */ + for (i = 0; i < AddressCount; i++) + { + /* Get the pointer of the current address */ + CurrentAddress = (PVOID)((ULONG_PTR)&DnsAddrArray->Addresses[i] + + FamilyInfo->AddressOffset); + + /* Write the pointer */ + Hostent->h_addr_list[i] = (PCHAR)HostentPtr; + + /* Copy the address */ + RtlCopyMemory((PVOID)HostentPtr, CurrentAddress, AddressSize); + + /* Advance the buffer */ + HostentPtr += AddressSize; + } + + /* Check if we have a name */ + if (Blob->Name) + { + /* Align our current position */ + HostentPtr += 1 & ~1; + + /* Save our name here */ + Hostent->h_name = (LPSTR)HostentPtr; + + /* Now copy it in the blob */ + HostentPtr += Dns_StringCopy((PVOID)HostentPtr, + NULL, + Blob->Name, + 0, + UnicodeString, + StringType); + } + + /* Loop the Aliases */ + for (i = AliasCount; i; i--) + { + /* Align our current position */ + HostentPtr += 1 & ~1; + + /* Save our alias here */ + Hostent->h_aliases[i] = (LPSTR)HostentPtr; + + /* Now copy it in the blob */ + HostentPtr += Dns_StringCopy((PVOID)HostentPtr, + NULL, + Blob->Aliases[i], + 0, + UnicodeString, + StringType); + } + + /* Check if the caller didn't have a buffer */ + if (!BufferAllocated) + { + /* Return the size; not needed if we had a blob, since it's internal */ + *HostEntrySize = *BufferPosition - (ULONG_PTR)HostentPtr; + } + + /* Convert to Offsets if requested */ + if(Relative) Hostent_ConvertToOffsets(Hostent); + + /* Return the full, complete, hostent */ + return Hostent; +} + +INT +WINAPI +SaBlob_WriteNameOrAlias(IN PDNS_BLOB Blob, + IN LPWSTR String, + IN BOOLEAN IsAlias) +{ + /* Check if this is an alias */ + if (!IsAlias) + { + /* It's not. Simply create a copy of the string */ + Blob->Name = Dns_CreateStringCopy_W(String); + if (!Blob->Name) return GetLastError(); + } + else + { + /* Does it have a name, and less then 8 aliases? */ + if ((Blob->Name) && (Blob->AliasCount <= 8)) + { + /* Yup, create a copy of the string and increase the alias count */ + Blob->Aliases[Blob->AliasCount] = Dns_CreateStringCopy_W(String); + Blob->AliasCount++; + } + else + { + /* Invalid request! */ + return ERROR_MORE_DATA; + } + } + + /* Return Success */ + return ERROR_SUCCESS; +} + +INT +WINAPI +SaBlob_WriteAddress(IN PDNS_BLOB Blob, + OUT PDNS_ADDRESS DnsAddr) +{ + /* Check if we have an array yet */ + if (!Blob->DnsAddrArray) + { + /* Allocate one! */ + Blob->DnsAddrArray = DnsAddrArray_Create(1); + if (!Blob->DnsAddrArray) return ERROR_OUTOFMEMORY; + } + + /* Add this address */ + return DnsAddrArray_AddAddr(Blob->DnsAddrArray, DnsAddr, AF_UNSPEC, 0) ? + ERROR_SUCCESS: + ERROR_MORE_DATA; +} + +BOOLEAN +WINAPI +SaBlob_IsSupportedAddrType(WORD DnsType) +{ + /* Check for valid Types that we support */ + return (DnsType == DNS_TYPE_A || + DnsType == DNS_TYPE_ATMA || + DnsType == DNS_TYPE_AAAA); +} + +INT +WINAPI +SaBlob_WriteRecords(OUT PDNS_BLOB Blob, + IN PDNS_RECORD DnsRecord, + IN BOOLEAN DoAlias) +{ + DNS_ADDRESS DnsAddress; + INT ErrorCode = STATUS_INVALID_PARAMETER; + BOOLEAN WroteOnce = FALSE; + + /* Zero out the Address */ + RtlZeroMemory(&DnsAddress, sizeof(DnsAddress)); + + /* Loop through all the Records */ + while (DnsRecord) + { + /* Is this not an answer? */ + if (DnsRecord->Flags.S.Section != DNSREC_ANSWER) + { + /* Then simply move on to the next DNS Record */ + DnsRecord = DnsRecord->pNext; + continue; + } + + /* Check the type of thsi record */ + switch(DnsRecord->wType) + { + /* Regular IPv4, v6 or ATM Record */ + case DNS_TYPE_A: + case DNS_TYPE_AAAA: + case DNS_TYPE_ATMA: + + /* Create a DNS Address from the record */ + DnsAddr_BuildFromDnsRecord(DnsRecord, &DnsAddress); + + /* Add it to the DNS Blob */ + ErrorCode = SaBlob_WriteAddress(Blob, &DnsAddress); + + /* Add the name, if needed */ + if ((DoAlias) && + (!WroteOnce) && + (!Blob->Name) && + (DnsRecord->pName)) + { + /* Write the name from the DNS Record */ + ErrorCode = SaBlob_WriteNameOrAlias(Blob, + DnsRecord->pName, + FALSE); + WroteOnce = TRUE; + } + break; + + case DNS_TYPE_CNAME: + + /* Just write the alias name */ + ErrorCode = SaBlob_WriteNameOrAlias(Blob, + DnsRecord->pName, + TRUE); + break; + + case DNS_TYPE_PTR: + + /* Check if we already have a name */ + if (Blob->Name) + { + /* We don't, so add this as a name */ + ErrorCode = SaBlob_WriteNameOrAlias(Blob, + DnsRecord->pName, + FALSE); + } + else + { + /* We do, so add it as an alias */ + ErrorCode = SaBlob_WriteNameOrAlias(Blob, + DnsRecord->pName, + TRUE); + } + break; + default: + break; + } + + /* Next record */ + DnsRecord = DnsRecord->pNext; + } + + /* Return error code */ + return ErrorCode; +} + +PDNS_BLOB +WINAPI +SaBlob_CreateFromRecords(IN PDNS_RECORD DnsRecord, + IN BOOLEAN DoAliases, + IN DWORD DnsType) +{ + PDNS_RECORD LocalDnsRecord; + ULONG ProcessedCount = 0; + PDNS_BLOB DnsBlob; + INT ErrorCode; + DNS_ADDRESS DnsAddress; + + /* Find out how many DNS Addresses to allocate */ + LocalDnsRecord = DnsRecord; + while (LocalDnsRecord) + { + /* Make sure this record is an answer */ + if ((LocalDnsRecord->Flags.S.Section == DNSREC_ANSWER) && + (SaBlob_IsSupportedAddrType(LocalDnsRecord->wType))) + { + /* Increase number of records to process */ + ProcessedCount++; + } + + /* Move to the next record */ + LocalDnsRecord = LocalDnsRecord->pNext; + } + + /* Create the DNS Blob */ + DnsBlob = SaBlob_Create(ProcessedCount); + if (!DnsBlob) + { + /* Fail */ + ErrorCode = GetLastError(); + goto Quickie; + } + + /* Write the record to the DNS Blob */ + ErrorCode = SaBlob_WriteRecords(DnsBlob, DnsRecord, TRUE); + if (ErrorCode != NO_ERROR) + { + /* We failed... but do we still have valid data? */ + if ((DnsBlob->Name) || (DnsBlob->AliasCount)) + { + /* We'll just assume success then */ + ErrorCode = NO_ERROR; + } + else + { + /* Ok, last chance..do you have a DNS Address Array? */ + if ((DnsBlob->DnsAddrArray) && + (DnsBlob->DnsAddrArray->UsedAddresses)) + { + /* Boy are you lucky! */ + ErrorCode = NO_ERROR; + } + } + + /* Buh-bye! */ + goto Quickie; + } + + /* Check if this is a PTR record */ + if ((DnsRecord->wType == DNS_TYPE_PTR) || + ((DnsType == DNS_TYPE_PTR) && + (DnsRecord->wType == DNS_TYPE_CNAME) && + (DnsRecord->Flags.S.Section == DNSREC_ANSWER))) + { + /* Get a DNS Address Structure */ + if (Dns_ReverseNameToDnsAddr_W(&DnsAddress, DnsRecord->pName)) + { + /* Add it to the Blob */ + if (SaBlob_WriteAddress(DnsBlob, &DnsAddress)) ErrorCode = NO_ERROR; + } + } + + /* Ok...do we still not have a name? */ + if (!(DnsBlob->Name) && (DoAliases) && (LocalDnsRecord)) + { + /* We have an local DNS Record, so just use it to write the name */ + ErrorCode = SaBlob_WriteNameOrAlias(DnsBlob, + LocalDnsRecord->pName, + FALSE); + } + +Quickie: + /* Check error code */ + if (ErrorCode != NO_ERROR) + { + /* Free the blob and set the error */ + SaBlob_Free(DnsBlob); + DnsBlob = NULL; + SetLastError(ErrorCode); + } + + /* Return */ + return DnsBlob; +} + +PDNS_BLOB +WINAPI +SaBlob_Query(IN LPWSTR Name, + IN WORD DnsType, + IN ULONG Flags, + IN PVOID *Reserved, + IN DWORD AddressFamily) +{ + PDNS_RECORD DnsRecord = NULL; + INT ErrorCode; + PDNS_BLOB DnsBlob = NULL; + LPWSTR LocalName, LocalNameCopy; + + /* If they want reserved data back, clear it out in case we fail */ + if (Reserved) *Reserved = NULL; + + /* Query DNS */ + ErrorCode = DnsQuery_W(Name, + DnsType, + Flags, + NULL, + &DnsRecord, + Reserved); + if (ErrorCode != ERROR_SUCCESS) + { + /* We failed... did the caller use reserved data? */ + if (Reserved && *Reserved) + { + /* He did, and it was valid. Free it */ + DnsApiFree(*Reserved); + *Reserved = NULL; + } + + /* Normalize error code */ + if (ErrorCode == RPC_S_SERVER_UNAVAILABLE) ErrorCode = WSATRY_AGAIN; + goto Quickie; + } + + /* Now create the Blob from the DNS Records */ + DnsBlob = SaBlob_CreateFromRecords(DnsRecord, TRUE, DnsType); + if (!DnsBlob) + { + /* Failed, get error code */ + ErrorCode = GetLastError(); + goto Quickie; + } + + /* Make sure it has a name */ + if (!DnsBlob->Name) + { + /* It doesn't, fail */ + ErrorCode = DNS_INFO_NO_RECORDS; + goto Quickie; + } + + /* Check if the name is local or loopback */ + if (!(DnsNameCompare_W(DnsBlob->Name, L"localhost")) && + !(DnsNameCompare_W(DnsBlob->Name, L"loopback"))) + { + /* Nothing left to do, exit! */ + goto Quickie; + } + + /* This is a local name...query it */ + DnsQueryConfig(DnsConfigFullHostName_W, + DNS_CONFIG_FLAG_ALLOC, + NULL, + NULL, + &LocalName, + 0); + if (LocalName) + { + /* Create a copy for the caller */ + LocalNameCopy = Dns_CreateStringCopy_W(LocalName); + if (LocalNameCopy) + { + /* Overwrite the one in the blob */ + DnsBlob->Name = LocalNameCopy; + } + else + { + /* We failed to make a copy, free memory */ + DnsApiFree(LocalName); + } + } + +Quickie: + /* Free the DNS Record if we have one */ + if (DnsRecord) DnsRecordListFree(DnsRecord, DnsFreeRecordList); + + /* Check if this is a failure path with an active blob */ + if ((ErrorCode != ERROR_SUCCESS) && (DnsBlob)) + { + /* Free the blob */ + SaBlob_Free(DnsBlob); + DnsBlob = NULL; + } + + /* Set the last error and return */ + SetLastError(ErrorCode); + return DnsBlob; +} + diff --git a/dll/win32/mswsock/dns/straddr.c b/dll/win32/mswsock/dns/straddr.c new file mode 100644 index 00000000000..4bf80f51b8b --- /dev/null +++ b/dll/win32/mswsock/dns/straddr.c @@ -0,0 +1,1848 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/straddr.c + * PURPOSE: Functions for address<->string conversion. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +LPWSTR +WINAPI +Dns_Ip6AddressToReverseName_W(OUT LPWSTR Name, + IN IN6_ADDR Address) +{ + /* FIXME */ + return NULL; +} + +LPWSTR +WINAPI +Dns_Ip4AddressToReverseName_W(OUT LPWSTR Name, + IN IN_ADDR Address) +{ + /* Simply append the ARPA string */ + return Name + (wsprintfW(Name, + L"%u.%u.%u.%u.in-addr.arpa.", + Address.S_un.S_addr >> 24, + Address.S_un.S_addr >> 10, + Address.S_un.S_addr >> 8, + Address.S_un.S_addr) * sizeof(WCHAR)); +} + +BOOLEAN +WINAPI +Dns_Ip4ReverseNameToAddress_A(OUT PIN_ADDR Address, + IN LPSTR Name) +{ + /* FIXME */ + return FALSE; +} + +BOOLEAN +WINAPI +Dns_Ip6ReverseNameToAddress_A(OUT PIN6_ADDR Address, + IN LPSTR Name) +{ + /* FIXME */ + return FALSE; +} + +BOOLEAN +WINAPI +Dns_Ip6StringToAddress_A(OUT PIN6_ADDR Address, + IN LPSTR Name) +{ + PCHAR Terminator; + NTSTATUS Status; + + /* Let RTL Do it for us */ + Status = RtlIpv6StringToAddressA(Name, &Terminator, Address); + if (NT_SUCCESS(Status)) return TRUE; + + /* We failed */ + return FALSE; +} + +BOOLEAN +WINAPI +Dns_Ip6StringToAddress_W(OUT PIN6_ADDR Address, + IN LPWSTR Name) +{ + PCHAR Terminator; + NTSTATUS Status; + + /* Let RTL Do it for us */ + Status = RtlIpv6StringToAddressW(Name, &Terminator, Address); + if (NT_SUCCESS(Status)) return TRUE; + + /* We failed */ + return FALSE; +} + +BOOLEAN +WINAPI +Dns_Ip4StringToAddress_A(OUT PIN_ADDR Address, + IN LPSTR Name) +{ + ULONG Addr; + + /* Use inet_addr to convert it... */ + Addr = inet_addr(Name); + if (Addr == -1) + { + /* Check if it's the wildcard (which is ok...) */ + if (strcmp("255.255.255.255", Name)) return FALSE; + } + + /* If we got here, then we suceeded... return the address */ + Address->S_un.S_addr = Addr; + return TRUE; +} + +BOOLEAN +WINAPI +Dns_Ip4StringToAddress_W(OUT PIN_ADDR Address, + IN LPWSTR Name) +{ + CHAR AnsiName[16]; + ULONG Size = sizeof(AnsiName); + INT ErrorCode; + + /* Make a copy of the name in ANSI */ + ErrorCode = Dns_StringCopy(&AnsiName, + &Size, + Name, + 0, + UnicodeString, + AnsiString); + if (ErrorCode) + { + /* Copy made sucesfully, now convert it */ + ErrorCode = Dns_Ip4StringToAddress_A(Address, AnsiName); + } + + /* Return either 0 bytes copied (failure == false) or conversion status */ + return ErrorCode; +} + +BOOLEAN +WINAPI +Dns_Ip4ReverseNameToAddress_W(OUT PIN_ADDR Address, + IN LPWSTR Name) +{ + CHAR AnsiName[32]; + ULONG Size = sizeof(AnsiName); + INT ErrorCode; + + /* Make a copy of the name in ANSI */ + ErrorCode = Dns_StringCopy(&AnsiName, + &Size, + Name, + 0, + UnicodeString, + AnsiString); + if (ErrorCode) + { + /* Copy made sucesfully, now convert it */ + ErrorCode = Dns_Ip4ReverseNameToAddress_A(Address, AnsiName); + } + + /* Return either 0 bytes copied (failure == false) or conversion status */ + return ErrorCode; +} + +BOOLEAN +WINAPI +Dns_StringToAddressEx(OUT PVOID Address, + IN OUT PULONG AddressSize, + IN PVOID AddressName, + IN OUT PDWORD AddressFamily, + IN BOOLEAN Unicode, + IN BOOLEAN Reverse) +{ + DWORD Af = *AddressFamily; + ULONG AddrSize = *AddressSize; + IN6_ADDR Addr; + BOOLEAN Return; + INT ErrorCode; + CHAR AnsiName[INET6_ADDRSTRLEN + sizeof("ip6.arpa.")]; + ULONG Size = sizeof(AnsiName); + + /* First check if this is a reverse address string */ + if (Reverse) + { + /* Convert it right now to ANSI as an optimization */ + Dns_StringCopy(AnsiName, + &Size, + AddressName, + 0, + UnicodeString, + AnsiString); + + /* Use the ANSI Name instead */ + AddressName = AnsiName; + } + + /* + * If the caller doesn't know what the family is, we'll assume IPv4 and + * check if we failed or not. If the caller told us it's IPv4, then just + * do IPv4... + */ + if ((Af == AF_UNSPEC) || (Af == AF_INET)) + { + /* Now check if the caller gave us the reverse name or not */ + if (Reverse) + { + /* Get the Address */ + Return = Dns_Ip4ReverseNameToAddress_A((PIN_ADDR)&Addr, AddressName); + } + else + { + /* Check if the caller gave us unicode or not */ + if (Unicode) + { + /* Get the Address */ + Return = Dns_Ip4StringToAddress_W((PIN_ADDR)&Addr, AddressName); + } + else + { + /* Get the Address */ + Return = Dns_Ip4StringToAddress_A((PIN_ADDR)&Addr, AddressName); + } + } + + /* Check if we suceeded */ + if (Return) + { + /* Save address family */ + Af = AF_INET; + + /* Check if the address size matches */ + if (AddrSize < sizeof(IN_ADDR)) + { + /* Invalid match, set error code */ + ErrorCode = ERROR_MORE_DATA; + } + else + { + /* It matches, save the address! */ + *(PIN_ADDR)Address = *(PIN_ADDR)&Addr; + } + } + } + + /* If we are here, either AF_INET6 was specified or IPv4 failed */ + if ((Af == AF_UNSPEC) || (Af == AF_INET6)) + { + /* Now check if the caller gave us the reverse name or not */ + if (Reverse) + { + /* Get the Address */ + Return = Dns_Ip6ReverseNameToAddress_A(&Addr, AddressName); + } + else + { + /* Check if the caller gave us unicode or not */ + if (Unicode) + { + /* Get the Address */ + Return = Dns_Ip6StringToAddress_W(&Addr, AddressName); + } + else + { + /* Get the Address */ + Return = Dns_Ip6StringToAddress_A(&Addr, AddressName); + } + } + + /* Check if we suceeded */ + if (Return) + { + /* Save address family */ + Af = AF_INET6; + + /* Check if the address size matches */ + if (AddrSize < sizeof(IN6_ADDR)) + { + /* Invalid match, set error code */ + ErrorCode = ERROR_MORE_DATA; + } + else + { + /* It matches, save the address! */ + *(PIN6_ADDR)Address = Addr; + } + } + } + else if (Af != AF_INET) + { + /* You're like.. ATM or something? Get outta here! */ + Af = AF_UNSPEC; + ErrorCode = WSA_INVALID_PARAMETER; + } + + /* Set error if we had one */ + if (ErrorCode) SetLastError(ErrorCode); + + /* Return the address family and size */ + *AddressFamily = Af; + *AddressSize = AddrSize; + + /* Return success or failure */ + return (ErrorCode == ERROR_SUCCESS); +} + +BOOLEAN +WINAPI +Dns_StringToAddressW(OUT PVOID Address, + IN OUT PULONG AddressSize, + IN LPWSTR AddressName, + IN OUT PDWORD AddressFamily) +{ + /* Call the common API */ + return Dns_StringToAddressEx(Address, + AddressSize, + AddressName, + AddressFamily, + TRUE, + FALSE); +} + +BOOLEAN +WINAPI +Dns_StringToDnsAddrEx(OUT PDNS_ADDRESS DnsAddr, + IN PVOID AddressName, + IN DWORD AddressFamily, + IN BOOLEAN Unicode, + IN BOOLEAN Reverse) +{ + IN6_ADDR Addr; + BOOLEAN Return; + INT ErrorCode = ERROR_SUCCESS; + CHAR AnsiName[INET6_ADDRSTRLEN + sizeof("ip6.arpa.")]; + ULONG Size = sizeof(AnsiName); + + /* First check if this is a reverse address string */ + if ((Reverse) && (Unicode)) + { + /* Convert it right now to ANSI as an optimization */ + Dns_StringCopy(AnsiName, + &Size, + AddressName, + 0, + UnicodeString, + AnsiString); + + /* Use the ANSI Name instead */ + AddressName = AnsiName; + } + + /* + * If the caller doesn't know what the family is, we'll assume IPv4 and + * check if we failed or not. If the caller told us it's IPv4, then just + * do IPv4... + */ + if ((AddressFamily == AF_UNSPEC) || (AddressFamily == AF_INET)) + { + /* Now check if the caller gave us the reverse name or not */ + if (Reverse) + { + /* Get the Address */ + Return = Dns_Ip4ReverseNameToAddress_A((PIN_ADDR)&Addr, AddressName); + } + else + { + /* Check if the caller gave us unicode or not */ + if (Unicode) + { + /* Get the Address */ + Return = Dns_Ip4StringToAddress_W((PIN_ADDR)&Addr, AddressName); + } + else + { + /* Get the Address */ + Return = Dns_Ip4StringToAddress_A((PIN_ADDR)&Addr, AddressName); + } + } + + /* Check if we suceeded */ + if (Return) + { + /* Build the IPv4 Address */ + DnsAddr_BuildFromIp4(DnsAddr, *(PIN_ADDR)&Addr, 0); + + /* So we don't go in the code below... */ + AddressFamily = AF_INET; + } + } + + /* If we are here, either AF_INET6 was specified or IPv4 failed */ + if ((AddressFamily == AF_UNSPEC) || (AddressFamily == AF_INET6)) + { + /* Now check if the caller gave us the reverse name or not */ + if (Reverse) + { + /* Get the Address */ + Return = Dns_Ip6ReverseNameToAddress_A(&Addr, AddressName); + if (Return) + { + /* Build the IPv6 Address */ + DnsAddr_BuildFromIp6(DnsAddr, &Addr, 0, 0); + } + else + { + goto Quickie; + } + } + else + { + /* Check if the caller gave us unicode or not */ + if (Unicode) + { + /* Get the Address */ + if (NT_SUCCESS(RtlIpv6StringToAddressExW(AddressName, + &DnsAddr->Ip6Address.sin6_addr, + &DnsAddr->Ip6Address.sin6_scope_id, + &DnsAddr->Ip6Address.sin6_port))) + Return = TRUE; + else + Return = FALSE; + } + else + { + /* Get the Address */ + if (NT_SUCCESS(RtlIpv6StringToAddressExA(AddressName, + &DnsAddr->Ip6Address.sin6_addr, + &DnsAddr->Ip6Address.sin6_scope_id, + &DnsAddr->Ip6Address.sin6_port))) + Return = TRUE; + else + Return = FALSE; + } + } + + /* Check if we suceeded */ + if (Return) + { + /* Finish setting up the structure */ + DnsAddr->Ip6Address.sin6_family = AF_INET6; + DnsAddr->AddressLength = sizeof(SOCKADDR_IN6); + } + } + else if (AddressFamily != AF_INET) + { + /* You're like.. ATM or something? Get outta here! */ + RtlZeroMemory(DnsAddr, sizeof(DNS_ADDRESS)); + SetLastError(WSA_INVALID_PARAMETER); + } + +Quickie: + /* Return success or failure */ + return (ErrorCode == ERROR_SUCCESS); +} + +BOOLEAN +WINAPI +Dns_ReverseNameToDnsAddr_W(OUT PDNS_ADDRESS DnsAddr, + IN LPWSTR Name) +{ + /* Call the common API */ + return Dns_StringToDnsAddrEx(DnsAddr, + Name, + AF_UNSPEC, + TRUE, + TRUE); +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/straddr.c + * PURPOSE: Functions for address<->string conversion. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +LPWSTR +WINAPI +Dns_Ip6AddressToReverseName_W(OUT LPWSTR Name, + IN IN6_ADDR Address) +{ + /* FIXME */ + return NULL; +} + +LPWSTR +WINAPI +Dns_Ip4AddressToReverseName_W(OUT LPWSTR Name, + IN IN_ADDR Address) +{ + /* Simply append the ARPA string */ + return Name + (wsprintfW(Name, + L"%u.%u.%u.%u.in-addr.arpa.", + Address.S_un.S_addr >> 24, + Address.S_un.S_addr >> 10, + Address.S_un.S_addr >> 8, + Address.S_un.S_addr) * sizeof(WCHAR)); +} + +BOOLEAN +WINAPI +Dns_Ip4ReverseNameToAddress_A(OUT PIN_ADDR Address, + IN LPSTR Name) +{ + /* FIXME */ + return FALSE; +} + +BOOLEAN +WINAPI +Dns_Ip6ReverseNameToAddress_A(OUT PIN6_ADDR Address, + IN LPSTR Name) +{ + /* FIXME */ + return FALSE; +} + +BOOLEAN +WINAPI +Dns_Ip6StringToAddress_A(OUT PIN6_ADDR Address, + IN LPSTR Name) +{ + PCHAR Terminator; + NTSTATUS Status; + + /* Let RTL Do it for us */ + Status = RtlIpv6StringToAddressA(Name, &Terminator, Address); + if (NT_SUCCESS(Status)) return TRUE; + + /* We failed */ + return FALSE; +} + +BOOLEAN +WINAPI +Dns_Ip6StringToAddress_W(OUT PIN6_ADDR Address, + IN LPWSTR Name) +{ + PCHAR Terminator; + NTSTATUS Status; + + /* Let RTL Do it for us */ + Status = RtlIpv6StringToAddressW(Name, &Terminator, Address); + if (NT_SUCCESS(Status)) return TRUE; + + /* We failed */ + return FALSE; +} + +BOOLEAN +WINAPI +Dns_Ip4StringToAddress_A(OUT PIN_ADDR Address, + IN LPSTR Name) +{ + ULONG Addr; + + /* Use inet_addr to convert it... */ + Addr = inet_addr(Name); + if (Addr == -1) + { + /* Check if it's the wildcard (which is ok...) */ + if (strcmp("255.255.255.255", Name)) return FALSE; + } + + /* If we got here, then we suceeded... return the address */ + Address->S_un.S_addr = Addr; + return TRUE; +} + +BOOLEAN +WINAPI +Dns_Ip4StringToAddress_W(OUT PIN_ADDR Address, + IN LPWSTR Name) +{ + CHAR AnsiName[16]; + ULONG Size = sizeof(AnsiName); + INT ErrorCode; + + /* Make a copy of the name in ANSI */ + ErrorCode = Dns_StringCopy(&AnsiName, + &Size, + Name, + 0, + UnicodeString, + AnsiString); + if (ErrorCode) + { + /* Copy made sucesfully, now convert it */ + ErrorCode = Dns_Ip4StringToAddress_A(Address, AnsiName); + } + + /* Return either 0 bytes copied (failure == false) or conversion status */ + return ErrorCode; +} + +BOOLEAN +WINAPI +Dns_Ip4ReverseNameToAddress_W(OUT PIN_ADDR Address, + IN LPWSTR Name) +{ + CHAR AnsiName[32]; + ULONG Size = sizeof(AnsiName); + INT ErrorCode; + + /* Make a copy of the name in ANSI */ + ErrorCode = Dns_StringCopy(&AnsiName, + &Size, + Name, + 0, + UnicodeString, + AnsiString); + if (ErrorCode) + { + /* Copy made sucesfully, now convert it */ + ErrorCode = Dns_Ip4ReverseNameToAddress_A(Address, AnsiName); + } + + /* Return either 0 bytes copied (failure == false) or conversion status */ + return ErrorCode; +} + +BOOLEAN +WINAPI +Dns_StringToAddressEx(OUT PVOID Address, + IN OUT PULONG AddressSize, + IN PVOID AddressName, + IN OUT PDWORD AddressFamily, + IN BOOLEAN Unicode, + IN BOOLEAN Reverse) +{ + DWORD Af = *AddressFamily; + ULONG AddrSize = *AddressSize; + IN6_ADDR Addr; + BOOLEAN Return; + INT ErrorCode; + CHAR AnsiName[INET6_ADDRSTRLEN + sizeof("ip6.arpa.")]; + ULONG Size = sizeof(AnsiName); + + /* First check if this is a reverse address string */ + if (Reverse) + { + /* Convert it right now to ANSI as an optimization */ + Dns_StringCopy(AnsiName, + &Size, + AddressName, + 0, + UnicodeString, + AnsiString); + + /* Use the ANSI Name instead */ + AddressName = AnsiName; + } + + /* + * If the caller doesn't know what the family is, we'll assume IPv4 and + * check if we failed or not. If the caller told us it's IPv4, then just + * do IPv4... + */ + if ((Af == AF_UNSPEC) || (Af == AF_INET)) + { + /* Now check if the caller gave us the reverse name or not */ + if (Reverse) + { + /* Get the Address */ + Return = Dns_Ip4ReverseNameToAddress_A((PIN_ADDR)&Addr, AddressName); + } + else + { + /* Check if the caller gave us unicode or not */ + if (Unicode) + { + /* Get the Address */ + Return = Dns_Ip4StringToAddress_W((PIN_ADDR)&Addr, AddressName); + } + else + { + /* Get the Address */ + Return = Dns_Ip4StringToAddress_A((PIN_ADDR)&Addr, AddressName); + } + } + + /* Check if we suceeded */ + if (Return) + { + /* Save address family */ + Af = AF_INET; + + /* Check if the address size matches */ + if (AddrSize < sizeof(IN_ADDR)) + { + /* Invalid match, set error code */ + ErrorCode = ERROR_MORE_DATA; + } + else + { + /* It matches, save the address! */ + *(PIN_ADDR)Address = *(PIN_ADDR)&Addr; + } + } + } + + /* If we are here, either AF_INET6 was specified or IPv4 failed */ + if ((Af == AF_UNSPEC) || (Af == AF_INET6)) + { + /* Now check if the caller gave us the reverse name or not */ + if (Reverse) + { + /* Get the Address */ + Return = Dns_Ip6ReverseNameToAddress_A(&Addr, AddressName); + } + else + { + /* Check if the caller gave us unicode or not */ + if (Unicode) + { + /* Get the Address */ + Return = Dns_Ip6StringToAddress_W(&Addr, AddressName); + } + else + { + /* Get the Address */ + Return = Dns_Ip6StringToAddress_A(&Addr, AddressName); + } + } + + /* Check if we suceeded */ + if (Return) + { + /* Save address family */ + Af = AF_INET6; + + /* Check if the address size matches */ + if (AddrSize < sizeof(IN6_ADDR)) + { + /* Invalid match, set error code */ + ErrorCode = ERROR_MORE_DATA; + } + else + { + /* It matches, save the address! */ + *(PIN6_ADDR)Address = Addr; + } + } + } + else if (Af != AF_INET) + { + /* You're like.. ATM or something? Get outta here! */ + Af = AF_UNSPEC; + ErrorCode = WSA_INVALID_PARAMETER; + } + + /* Set error if we had one */ + if (ErrorCode) SetLastError(ErrorCode); + + /* Return the address family and size */ + *AddressFamily = Af; + *AddressSize = AddrSize; + + /* Return success or failure */ + return (ErrorCode == ERROR_SUCCESS); +} + +BOOLEAN +WINAPI +Dns_StringToAddressW(OUT PVOID Address, + IN OUT PULONG AddressSize, + IN LPWSTR AddressName, + IN OUT PDWORD AddressFamily) +{ + /* Call the common API */ + return Dns_StringToAddressEx(Address, + AddressSize, + AddressName, + AddressFamily, + TRUE, + FALSE); +} + +BOOLEAN +WINAPI +Dns_StringToDnsAddrEx(OUT PDNS_ADDRESS DnsAddr, + IN PVOID AddressName, + IN DWORD AddressFamily, + IN BOOLEAN Unicode, + IN BOOLEAN Reverse) +{ + IN6_ADDR Addr; + BOOLEAN Return; + INT ErrorCode = ERROR_SUCCESS; + CHAR AnsiName[INET6_ADDRSTRLEN + sizeof("ip6.arpa.")]; + ULONG Size = sizeof(AnsiName); + + /* First check if this is a reverse address string */ + if ((Reverse) && (Unicode)) + { + /* Convert it right now to ANSI as an optimization */ + Dns_StringCopy(AnsiName, + &Size, + AddressName, + 0, + UnicodeString, + AnsiString); + + /* Use the ANSI Name instead */ + AddressName = AnsiName; + } + + /* + * If the caller doesn't know what the family is, we'll assume IPv4 and + * check if we failed or not. If the caller told us it's IPv4, then just + * do IPv4... + */ + if ((AddressFamily == AF_UNSPEC) || (AddressFamily == AF_INET)) + { + /* Now check if the caller gave us the reverse name or not */ + if (Reverse) + { + /* Get the Address */ + Return = Dns_Ip4ReverseNameToAddress_A((PIN_ADDR)&Addr, AddressName); + } + else + { + /* Check if the caller gave us unicode or not */ + if (Unicode) + { + /* Get the Address */ + Return = Dns_Ip4StringToAddress_W((PIN_ADDR)&Addr, AddressName); + } + else + { + /* Get the Address */ + Return = Dns_Ip4StringToAddress_A((PIN_ADDR)&Addr, AddressName); + } + } + + /* Check if we suceeded */ + if (Return) + { + /* Build the IPv4 Address */ + DnsAddr_BuildFromIp4(DnsAddr, *(PIN_ADDR)&Addr, 0); + + /* So we don't go in the code below... */ + AddressFamily = AF_INET; + } + } + + /* If we are here, either AF_INET6 was specified or IPv4 failed */ + if ((AddressFamily == AF_UNSPEC) || (AddressFamily == AF_INET6)) + { + /* Now check if the caller gave us the reverse name or not */ + if (Reverse) + { + /* Get the Address */ + Return = Dns_Ip6ReverseNameToAddress_A(&Addr, AddressName); + if (Return) + { + /* Build the IPv6 Address */ + DnsAddr_BuildFromIp6(DnsAddr, &Addr, 0, 0); + } + else + { + goto Quickie; + } + } + else + { + /* Check if the caller gave us unicode or not */ + if (Unicode) + { + /* Get the Address */ + if (NT_SUCCESS(RtlIpv6StringToAddressExW(AddressName, + &DnsAddr->Ip6Address.sin6_addr, + &DnsAddr->Ip6Address.sin6_scope_id, + &DnsAddr->Ip6Address.sin6_port))) + Return = TRUE; + else + Return = FALSE; + } + else + { + /* Get the Address */ + if (NT_SUCCESS(RtlIpv6StringToAddressExA(AddressName, + &DnsAddr->Ip6Address.sin6_addr, + &DnsAddr->Ip6Address.sin6_scope_id, + &DnsAddr->Ip6Address.sin6_port))) + Return = TRUE; + else + Return = FALSE; + } + } + + /* Check if we suceeded */ + if (Return) + { + /* Finish setting up the structure */ + DnsAddr->Ip6Address.sin6_family = AF_INET6; + DnsAddr->AddressLength = sizeof(SOCKADDR_IN6); + } + } + else if (AddressFamily != AF_INET) + { + /* You're like.. ATM or something? Get outta here! */ + RtlZeroMemory(DnsAddr, sizeof(DNS_ADDRESS)); + SetLastError(WSA_INVALID_PARAMETER); + } + +Quickie: + /* Return success or failure */ + return (ErrorCode == ERROR_SUCCESS); +} + +BOOLEAN +WINAPI +Dns_ReverseNameToDnsAddr_W(OUT PDNS_ADDRESS DnsAddr, + IN LPWSTR Name) +{ + /* Call the common API */ + return Dns_StringToDnsAddrEx(DnsAddr, + Name, + AF_UNSPEC, + TRUE, + TRUE); +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/straddr.c + * PURPOSE: Functions for address<->string conversion. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +LPWSTR +WINAPI +Dns_Ip6AddressToReverseName_W(OUT LPWSTR Name, + IN IN6_ADDR Address) +{ + /* FIXME */ + return NULL; +} + +LPWSTR +WINAPI +Dns_Ip4AddressToReverseName_W(OUT LPWSTR Name, + IN IN_ADDR Address) +{ + /* Simply append the ARPA string */ + return Name + (wsprintfW(Name, + L"%u.%u.%u.%u.in-addr.arpa.", + Address.S_un.S_addr >> 24, + Address.S_un.S_addr >> 10, + Address.S_un.S_addr >> 8, + Address.S_un.S_addr) * sizeof(WCHAR)); +} + +BOOLEAN +WINAPI +Dns_Ip4ReverseNameToAddress_A(OUT PIN_ADDR Address, + IN LPSTR Name) +{ + /* FIXME */ + return FALSE; +} + +BOOLEAN +WINAPI +Dns_Ip6ReverseNameToAddress_A(OUT PIN6_ADDR Address, + IN LPSTR Name) +{ + /* FIXME */ + return FALSE; +} + +BOOLEAN +WINAPI +Dns_Ip6StringToAddress_A(OUT PIN6_ADDR Address, + IN LPSTR Name) +{ + PCHAR Terminator; + NTSTATUS Status; + + /* Let RTL Do it for us */ + Status = RtlIpv6StringToAddressA(Name, &Terminator, Address); + if (NT_SUCCESS(Status)) return TRUE; + + /* We failed */ + return FALSE; +} + +BOOLEAN +WINAPI +Dns_Ip6StringToAddress_W(OUT PIN6_ADDR Address, + IN LPWSTR Name) +{ + PCHAR Terminator; + NTSTATUS Status; + + /* Let RTL Do it for us */ + Status = RtlIpv6StringToAddressW(Name, &Terminator, Address); + if (NT_SUCCESS(Status)) return TRUE; + + /* We failed */ + return FALSE; +} + +BOOLEAN +WINAPI +Dns_Ip4StringToAddress_A(OUT PIN_ADDR Address, + IN LPSTR Name) +{ + ULONG Addr; + + /* Use inet_addr to convert it... */ + Addr = inet_addr(Name); + if (Addr == -1) + { + /* Check if it's the wildcard (which is ok...) */ + if (strcmp("255.255.255.255", Name)) return FALSE; + } + + /* If we got here, then we suceeded... return the address */ + Address->S_un.S_addr = Addr; + return TRUE; +} + +BOOLEAN +WINAPI +Dns_Ip4StringToAddress_W(OUT PIN_ADDR Address, + IN LPWSTR Name) +{ + CHAR AnsiName[16]; + ULONG Size = sizeof(AnsiName); + INT ErrorCode; + + /* Make a copy of the name in ANSI */ + ErrorCode = Dns_StringCopy(&AnsiName, + &Size, + Name, + 0, + UnicodeString, + AnsiString); + if (ErrorCode) + { + /* Copy made sucesfully, now convert it */ + ErrorCode = Dns_Ip4StringToAddress_A(Address, AnsiName); + } + + /* Return either 0 bytes copied (failure == false) or conversion status */ + return ErrorCode; +} + +BOOLEAN +WINAPI +Dns_Ip4ReverseNameToAddress_W(OUT PIN_ADDR Address, + IN LPWSTR Name) +{ + CHAR AnsiName[32]; + ULONG Size = sizeof(AnsiName); + INT ErrorCode; + + /* Make a copy of the name in ANSI */ + ErrorCode = Dns_StringCopy(&AnsiName, + &Size, + Name, + 0, + UnicodeString, + AnsiString); + if (ErrorCode) + { + /* Copy made sucesfully, now convert it */ + ErrorCode = Dns_Ip4ReverseNameToAddress_A(Address, AnsiName); + } + + /* Return either 0 bytes copied (failure == false) or conversion status */ + return ErrorCode; +} + +BOOLEAN +WINAPI +Dns_StringToAddressEx(OUT PVOID Address, + IN OUT PULONG AddressSize, + IN PVOID AddressName, + IN OUT PDWORD AddressFamily, + IN BOOLEAN Unicode, + IN BOOLEAN Reverse) +{ + DWORD Af = *AddressFamily; + ULONG AddrSize = *AddressSize; + IN6_ADDR Addr; + BOOLEAN Return; + INT ErrorCode; + CHAR AnsiName[INET6_ADDRSTRLEN + sizeof("ip6.arpa.")]; + ULONG Size = sizeof(AnsiName); + + /* First check if this is a reverse address string */ + if (Reverse) + { + /* Convert it right now to ANSI as an optimization */ + Dns_StringCopy(AnsiName, + &Size, + AddressName, + 0, + UnicodeString, + AnsiString); + + /* Use the ANSI Name instead */ + AddressName = AnsiName; + } + + /* + * If the caller doesn't know what the family is, we'll assume IPv4 and + * check if we failed or not. If the caller told us it's IPv4, then just + * do IPv4... + */ + if ((Af == AF_UNSPEC) || (Af == AF_INET)) + { + /* Now check if the caller gave us the reverse name or not */ + if (Reverse) + { + /* Get the Address */ + Return = Dns_Ip4ReverseNameToAddress_A((PIN_ADDR)&Addr, AddressName); + } + else + { + /* Check if the caller gave us unicode or not */ + if (Unicode) + { + /* Get the Address */ + Return = Dns_Ip4StringToAddress_W((PIN_ADDR)&Addr, AddressName); + } + else + { + /* Get the Address */ + Return = Dns_Ip4StringToAddress_A((PIN_ADDR)&Addr, AddressName); + } + } + + /* Check if we suceeded */ + if (Return) + { + /* Save address family */ + Af = AF_INET; + + /* Check if the address size matches */ + if (AddrSize < sizeof(IN_ADDR)) + { + /* Invalid match, set error code */ + ErrorCode = ERROR_MORE_DATA; + } + else + { + /* It matches, save the address! */ + *(PIN_ADDR)Address = *(PIN_ADDR)&Addr; + } + } + } + + /* If we are here, either AF_INET6 was specified or IPv4 failed */ + if ((Af == AF_UNSPEC) || (Af == AF_INET6)) + { + /* Now check if the caller gave us the reverse name or not */ + if (Reverse) + { + /* Get the Address */ + Return = Dns_Ip6ReverseNameToAddress_A(&Addr, AddressName); + } + else + { + /* Check if the caller gave us unicode or not */ + if (Unicode) + { + /* Get the Address */ + Return = Dns_Ip6StringToAddress_W(&Addr, AddressName); + } + else + { + /* Get the Address */ + Return = Dns_Ip6StringToAddress_A(&Addr, AddressName); + } + } + + /* Check if we suceeded */ + if (Return) + { + /* Save address family */ + Af = AF_INET6; + + /* Check if the address size matches */ + if (AddrSize < sizeof(IN6_ADDR)) + { + /* Invalid match, set error code */ + ErrorCode = ERROR_MORE_DATA; + } + else + { + /* It matches, save the address! */ + *(PIN6_ADDR)Address = Addr; + } + } + } + else if (Af != AF_INET) + { + /* You're like.. ATM or something? Get outta here! */ + Af = AF_UNSPEC; + ErrorCode = WSA_INVALID_PARAMETER; + } + + /* Set error if we had one */ + if (ErrorCode) SetLastError(ErrorCode); + + /* Return the address family and size */ + *AddressFamily = Af; + *AddressSize = AddrSize; + + /* Return success or failure */ + return (ErrorCode == ERROR_SUCCESS); +} + +BOOLEAN +WINAPI +Dns_StringToAddressW(OUT PVOID Address, + IN OUT PULONG AddressSize, + IN LPWSTR AddressName, + IN OUT PDWORD AddressFamily) +{ + /* Call the common API */ + return Dns_StringToAddressEx(Address, + AddressSize, + AddressName, + AddressFamily, + TRUE, + FALSE); +} + +BOOLEAN +WINAPI +Dns_StringToDnsAddrEx(OUT PDNS_ADDRESS DnsAddr, + IN PVOID AddressName, + IN DWORD AddressFamily, + IN BOOLEAN Unicode, + IN BOOLEAN Reverse) +{ + IN6_ADDR Addr; + BOOLEAN Return; + INT ErrorCode = ERROR_SUCCESS; + CHAR AnsiName[INET6_ADDRSTRLEN + sizeof("ip6.arpa.")]; + ULONG Size = sizeof(AnsiName); + + /* First check if this is a reverse address string */ + if ((Reverse) && (Unicode)) + { + /* Convert it right now to ANSI as an optimization */ + Dns_StringCopy(AnsiName, + &Size, + AddressName, + 0, + UnicodeString, + AnsiString); + + /* Use the ANSI Name instead */ + AddressName = AnsiName; + } + + /* + * If the caller doesn't know what the family is, we'll assume IPv4 and + * check if we failed or not. If the caller told us it's IPv4, then just + * do IPv4... + */ + if ((AddressFamily == AF_UNSPEC) || (AddressFamily == AF_INET)) + { + /* Now check if the caller gave us the reverse name or not */ + if (Reverse) + { + /* Get the Address */ + Return = Dns_Ip4ReverseNameToAddress_A((PIN_ADDR)&Addr, AddressName); + } + else + { + /* Check if the caller gave us unicode or not */ + if (Unicode) + { + /* Get the Address */ + Return = Dns_Ip4StringToAddress_W((PIN_ADDR)&Addr, AddressName); + } + else + { + /* Get the Address */ + Return = Dns_Ip4StringToAddress_A((PIN_ADDR)&Addr, AddressName); + } + } + + /* Check if we suceeded */ + if (Return) + { + /* Build the IPv4 Address */ + DnsAddr_BuildFromIp4(DnsAddr, *(PIN_ADDR)&Addr, 0); + + /* So we don't go in the code below... */ + AddressFamily = AF_INET; + } + } + + /* If we are here, either AF_INET6 was specified or IPv4 failed */ + if ((AddressFamily == AF_UNSPEC) || (AddressFamily == AF_INET6)) + { + /* Now check if the caller gave us the reverse name or not */ + if (Reverse) + { + /* Get the Address */ + Return = Dns_Ip6ReverseNameToAddress_A(&Addr, AddressName); + if (Return) + { + /* Build the IPv6 Address */ + DnsAddr_BuildFromIp6(DnsAddr, &Addr, 0, 0); + } + else + { + goto Quickie; + } + } + else + { + /* Check if the caller gave us unicode or not */ + if (Unicode) + { + /* Get the Address */ + if (NT_SUCCESS(RtlIpv6StringToAddressExW(AddressName, + &DnsAddr->Ip6Address.sin6_addr, + &DnsAddr->Ip6Address.sin6_scope_id, + &DnsAddr->Ip6Address.sin6_port))) + Return = TRUE; + else + Return = FALSE; + } + else + { + /* Get the Address */ + if (NT_SUCCESS(RtlIpv6StringToAddressExA(AddressName, + &DnsAddr->Ip6Address.sin6_addr, + &DnsAddr->Ip6Address.sin6_scope_id, + &DnsAddr->Ip6Address.sin6_port))) + Return = TRUE; + else + Return = FALSE; + } + } + + /* Check if we suceeded */ + if (Return) + { + /* Finish setting up the structure */ + DnsAddr->Ip6Address.sin6_family = AF_INET6; + DnsAddr->AddressLength = sizeof(SOCKADDR_IN6); + } + } + else if (AddressFamily != AF_INET) + { + /* You're like.. ATM or something? Get outta here! */ + RtlZeroMemory(DnsAddr, sizeof(DNS_ADDRESS)); + SetLastError(WSA_INVALID_PARAMETER); + } + +Quickie: + /* Return success or failure */ + return (ErrorCode == ERROR_SUCCESS); +} + +BOOLEAN +WINAPI +Dns_ReverseNameToDnsAddr_W(OUT PDNS_ADDRESS DnsAddr, + IN LPWSTR Name) +{ + /* Call the common API */ + return Dns_StringToDnsAddrEx(DnsAddr, + Name, + AF_UNSPEC, + TRUE, + TRUE); +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/straddr.c + * PURPOSE: Functions for address<->string conversion. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +LPWSTR +WINAPI +Dns_Ip6AddressToReverseName_W(OUT LPWSTR Name, + IN IN6_ADDR Address) +{ + /* FIXME */ + return NULL; +} + +LPWSTR +WINAPI +Dns_Ip4AddressToReverseName_W(OUT LPWSTR Name, + IN IN_ADDR Address) +{ + /* Simply append the ARPA string */ + return Name + (wsprintfW(Name, + L"%u.%u.%u.%u.in-addr.arpa.", + Address.S_un.S_addr >> 24, + Address.S_un.S_addr >> 10, + Address.S_un.S_addr >> 8, + Address.S_un.S_addr) * sizeof(WCHAR)); +} + +BOOLEAN +WINAPI +Dns_Ip4ReverseNameToAddress_A(OUT PIN_ADDR Address, + IN LPSTR Name) +{ + /* FIXME */ + return FALSE; +} + +BOOLEAN +WINAPI +Dns_Ip6ReverseNameToAddress_A(OUT PIN6_ADDR Address, + IN LPSTR Name) +{ + /* FIXME */ + return FALSE; +} + +BOOLEAN +WINAPI +Dns_Ip6StringToAddress_A(OUT PIN6_ADDR Address, + IN LPSTR Name) +{ + PCHAR Terminator; + NTSTATUS Status; + + /* Let RTL Do it for us */ + Status = RtlIpv6StringToAddressA(Name, &Terminator, Address); + if (NT_SUCCESS(Status)) return TRUE; + + /* We failed */ + return FALSE; +} + +BOOLEAN +WINAPI +Dns_Ip6StringToAddress_W(OUT PIN6_ADDR Address, + IN LPWSTR Name) +{ + PCHAR Terminator; + NTSTATUS Status; + + /* Let RTL Do it for us */ + Status = RtlIpv6StringToAddressW(Name, &Terminator, Address); + if (NT_SUCCESS(Status)) return TRUE; + + /* We failed */ + return FALSE; +} + +BOOLEAN +WINAPI +Dns_Ip4StringToAddress_A(OUT PIN_ADDR Address, + IN LPSTR Name) +{ + ULONG Addr; + + /* Use inet_addr to convert it... */ + Addr = inet_addr(Name); + if (Addr == -1) + { + /* Check if it's the wildcard (which is ok...) */ + if (strcmp("255.255.255.255", Name)) return FALSE; + } + + /* If we got here, then we suceeded... return the address */ + Address->S_un.S_addr = Addr; + return TRUE; +} + +BOOLEAN +WINAPI +Dns_Ip4StringToAddress_W(OUT PIN_ADDR Address, + IN LPWSTR Name) +{ + CHAR AnsiName[16]; + ULONG Size = sizeof(AnsiName); + INT ErrorCode; + + /* Make a copy of the name in ANSI */ + ErrorCode = Dns_StringCopy(&AnsiName, + &Size, + Name, + 0, + UnicodeString, + AnsiString); + if (ErrorCode) + { + /* Copy made sucesfully, now convert it */ + ErrorCode = Dns_Ip4StringToAddress_A(Address, AnsiName); + } + + /* Return either 0 bytes copied (failure == false) or conversion status */ + return ErrorCode; +} + +BOOLEAN +WINAPI +Dns_Ip4ReverseNameToAddress_W(OUT PIN_ADDR Address, + IN LPWSTR Name) +{ + CHAR AnsiName[32]; + ULONG Size = sizeof(AnsiName); + INT ErrorCode; + + /* Make a copy of the name in ANSI */ + ErrorCode = Dns_StringCopy(&AnsiName, + &Size, + Name, + 0, + UnicodeString, + AnsiString); + if (ErrorCode) + { + /* Copy made sucesfully, now convert it */ + ErrorCode = Dns_Ip4ReverseNameToAddress_A(Address, AnsiName); + } + + /* Return either 0 bytes copied (failure == false) or conversion status */ + return ErrorCode; +} + +BOOLEAN +WINAPI +Dns_StringToAddressEx(OUT PVOID Address, + IN OUT PULONG AddressSize, + IN PVOID AddressName, + IN OUT PDWORD AddressFamily, + IN BOOLEAN Unicode, + IN BOOLEAN Reverse) +{ + DWORD Af = *AddressFamily; + ULONG AddrSize = *AddressSize; + IN6_ADDR Addr; + BOOLEAN Return; + INT ErrorCode; + CHAR AnsiName[INET6_ADDRSTRLEN + sizeof("ip6.arpa.")]; + ULONG Size = sizeof(AnsiName); + + /* First check if this is a reverse address string */ + if (Reverse) + { + /* Convert it right now to ANSI as an optimization */ + Dns_StringCopy(AnsiName, + &Size, + AddressName, + 0, + UnicodeString, + AnsiString); + + /* Use the ANSI Name instead */ + AddressName = AnsiName; + } + + /* + * If the caller doesn't know what the family is, we'll assume IPv4 and + * check if we failed or not. If the caller told us it's IPv4, then just + * do IPv4... + */ + if ((Af == AF_UNSPEC) || (Af == AF_INET)) + { + /* Now check if the caller gave us the reverse name or not */ + if (Reverse) + { + /* Get the Address */ + Return = Dns_Ip4ReverseNameToAddress_A((PIN_ADDR)&Addr, AddressName); + } + else + { + /* Check if the caller gave us unicode or not */ + if (Unicode) + { + /* Get the Address */ + Return = Dns_Ip4StringToAddress_W((PIN_ADDR)&Addr, AddressName); + } + else + { + /* Get the Address */ + Return = Dns_Ip4StringToAddress_A((PIN_ADDR)&Addr, AddressName); + } + } + + /* Check if we suceeded */ + if (Return) + { + /* Save address family */ + Af = AF_INET; + + /* Check if the address size matches */ + if (AddrSize < sizeof(IN_ADDR)) + { + /* Invalid match, set error code */ + ErrorCode = ERROR_MORE_DATA; + } + else + { + /* It matches, save the address! */ + *(PIN_ADDR)Address = *(PIN_ADDR)&Addr; + } + } + } + + /* If we are here, either AF_INET6 was specified or IPv4 failed */ + if ((Af == AF_UNSPEC) || (Af == AF_INET6)) + { + /* Now check if the caller gave us the reverse name or not */ + if (Reverse) + { + /* Get the Address */ + Return = Dns_Ip6ReverseNameToAddress_A(&Addr, AddressName); + } + else + { + /* Check if the caller gave us unicode or not */ + if (Unicode) + { + /* Get the Address */ + Return = Dns_Ip6StringToAddress_W(&Addr, AddressName); + } + else + { + /* Get the Address */ + Return = Dns_Ip6StringToAddress_A(&Addr, AddressName); + } + } + + /* Check if we suceeded */ + if (Return) + { + /* Save address family */ + Af = AF_INET6; + + /* Check if the address size matches */ + if (AddrSize < sizeof(IN6_ADDR)) + { + /* Invalid match, set error code */ + ErrorCode = ERROR_MORE_DATA; + } + else + { + /* It matches, save the address! */ + *(PIN6_ADDR)Address = Addr; + } + } + } + else if (Af != AF_INET) + { + /* You're like.. ATM or something? Get outta here! */ + Af = AF_UNSPEC; + ErrorCode = WSA_INVALID_PARAMETER; + } + + /* Set error if we had one */ + if (ErrorCode) SetLastError(ErrorCode); + + /* Return the address family and size */ + *AddressFamily = Af; + *AddressSize = AddrSize; + + /* Return success or failure */ + return (ErrorCode == ERROR_SUCCESS); +} + +BOOLEAN +WINAPI +Dns_StringToAddressW(OUT PVOID Address, + IN OUT PULONG AddressSize, + IN LPWSTR AddressName, + IN OUT PDWORD AddressFamily) +{ + /* Call the common API */ + return Dns_StringToAddressEx(Address, + AddressSize, + AddressName, + AddressFamily, + TRUE, + FALSE); +} + +BOOLEAN +WINAPI +Dns_StringToDnsAddrEx(OUT PDNS_ADDRESS DnsAddr, + IN PVOID AddressName, + IN DWORD AddressFamily, + IN BOOLEAN Unicode, + IN BOOLEAN Reverse) +{ + IN6_ADDR Addr; + BOOLEAN Return; + INT ErrorCode = ERROR_SUCCESS; + CHAR AnsiName[INET6_ADDRSTRLEN + sizeof("ip6.arpa.")]; + ULONG Size = sizeof(AnsiName); + + /* First check if this is a reverse address string */ + if ((Reverse) && (Unicode)) + { + /* Convert it right now to ANSI as an optimization */ + Dns_StringCopy(AnsiName, + &Size, + AddressName, + 0, + UnicodeString, + AnsiString); + + /* Use the ANSI Name instead */ + AddressName = AnsiName; + } + + /* + * If the caller doesn't know what the family is, we'll assume IPv4 and + * check if we failed or not. If the caller told us it's IPv4, then just + * do IPv4... + */ + if ((AddressFamily == AF_UNSPEC) || (AddressFamily == AF_INET)) + { + /* Now check if the caller gave us the reverse name or not */ + if (Reverse) + { + /* Get the Address */ + Return = Dns_Ip4ReverseNameToAddress_A((PIN_ADDR)&Addr, AddressName); + } + else + { + /* Check if the caller gave us unicode or not */ + if (Unicode) + { + /* Get the Address */ + Return = Dns_Ip4StringToAddress_W((PIN_ADDR)&Addr, AddressName); + } + else + { + /* Get the Address */ + Return = Dns_Ip4StringToAddress_A((PIN_ADDR)&Addr, AddressName); + } + } + + /* Check if we suceeded */ + if (Return) + { + /* Build the IPv4 Address */ + DnsAddr_BuildFromIp4(DnsAddr, *(PIN_ADDR)&Addr, 0); + + /* So we don't go in the code below... */ + AddressFamily = AF_INET; + } + } + + /* If we are here, either AF_INET6 was specified or IPv4 failed */ + if ((AddressFamily == AF_UNSPEC) || (AddressFamily == AF_INET6)) + { + /* Now check if the caller gave us the reverse name or not */ + if (Reverse) + { + /* Get the Address */ + Return = Dns_Ip6ReverseNameToAddress_A(&Addr, AddressName); + if (Return) + { + /* Build the IPv6 Address */ + DnsAddr_BuildFromIp6(DnsAddr, &Addr, 0, 0); + } + else + { + goto Quickie; + } + } + else + { + /* Check if the caller gave us unicode or not */ + if (Unicode) + { + /* Get the Address */ + if (NT_SUCCESS(RtlIpv6StringToAddressExW(AddressName, + &DnsAddr->Ip6Address.sin6_addr, + &DnsAddr->Ip6Address.sin6_scope_id, + &DnsAddr->Ip6Address.sin6_port))) + Return = TRUE; + else + Return = FALSE; + } + else + { + /* Get the Address */ + if (NT_SUCCESS(RtlIpv6StringToAddressExA(AddressName, + &DnsAddr->Ip6Address.sin6_addr, + &DnsAddr->Ip6Address.sin6_scope_id, + &DnsAddr->Ip6Address.sin6_port))) + Return = TRUE; + else + Return = FALSE; + } + } + + /* Check if we suceeded */ + if (Return) + { + /* Finish setting up the structure */ + DnsAddr->Ip6Address.sin6_family = AF_INET6; + DnsAddr->AddressLength = sizeof(SOCKADDR_IN6); + } + } + else if (AddressFamily != AF_INET) + { + /* You're like.. ATM or something? Get outta here! */ + RtlZeroMemory(DnsAddr, sizeof(DNS_ADDRESS)); + SetLastError(WSA_INVALID_PARAMETER); + } + +Quickie: + /* Return success or failure */ + return (ErrorCode == ERROR_SUCCESS); +} + +BOOLEAN +WINAPI +Dns_ReverseNameToDnsAddr_W(OUT PDNS_ADDRESS DnsAddr, + IN LPWSTR Name) +{ + /* Call the common API */ + return Dns_StringToDnsAddrEx(DnsAddr, + Name, + AF_UNSPEC, + TRUE, + TRUE); +} + diff --git a/dll/win32/mswsock/dns/string.c b/dll/win32/mswsock/dns/string.c new file mode 100644 index 00000000000..d15e4e0d443 --- /dev/null +++ b/dll/win32/mswsock/dns/string.c @@ -0,0 +1,1028 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/string.c + * PURPOSE: functions for string manipulation and conversion. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +ULONG +WINAPI +Dns_StringCopy(OUT PVOID Destination, + IN OUT PULONG DestinationSize, + IN PVOID String, + IN ULONG StringSize OPTIONAL, + IN DWORD InputType, + IN DWORD OutputType) +{ + ULONG DestSize; + ULONG OutputSize = 0; + + /* Check if the caller already gave us the string size */ + if (!StringSize) + { + /* He didn't, get the input type */ + if (InputType == UnicodeString) + { + /* Unicode string, calculate the size */ + StringSize = (ULONG)wcslen((LPWSTR)String); + } + else + { + /* ANSI or UTF-8 sting, get the size */ + StringSize = (ULONG)strlen((LPSTR)String); + } + } + + /* Check if we have a limit on the desination size */ + if (DestinationSize) + { + /* Make sure that we can respect it */ + DestSize = Dns_GetBufferLengthForStringCopy(String, + StringSize, + InputType, + OutputType); + if (*DestinationSize < DestSize) + { + /* Fail due to missing buffer space */ + SetLastError(ERROR_MORE_DATA); + + /* Return how much data we actually need */ + *DestinationSize = DestSize; + return 0; + } + else if (!DestSize) + { + /* Fail due to invalid data */ + SetLastError(ERROR_INVALID_DATA); + return 0; + } + + /* Return how much data we actually need */ + *DestinationSize = DestSize; + } + + /* Now check if this is a Unicode String as input */ + if (InputType == UnicodeString) + { + /* Check if the output is ANSI */ + if (OutputType == AnsiString) + { + /* Convert and return the final desination size */ + OutputSize = WideCharToMultiByte(CP_ACP, + 0, + String, + StringSize, + Destination, + -1, + NULL, + NULL) + 1; + } + else if (OutputType == UnicodeString) + { + /* Copy the string */ + StringSize = StringSize * sizeof(WCHAR); + RtlMoveMemory(Destination, String, StringSize); + + /* Return output length */ + OutputSize = StringSize + 2; + } + else if (OutputType == Utf8String) + { + /* FIXME */ + OutputSize = 0; + } + } + else if (InputType == AnsiString) + { + /* It's ANSI, is the output ansi too? */ + if (OutputType == AnsiString) + { + /* Copy the string */ + RtlMoveMemory(Destination, String, StringSize); + + /* Return output length */ + OutputSize = StringSize + 1; + } + else if (OutputType == UnicodeString) + { + /* Convert to Unicode and return size */ + OutputSize = MultiByteToWideChar(CP_ACP, + 0, + String, + StringSize, + Destination, + -1) * sizeof(WCHAR) + 2; + } + else if (OutputType == Utf8String) + { + /* FIXME */ + OutputSize = 0; + } + } + else if (InputType == Utf8String) + { + /* FIXME */ + OutputSize = 0; + } + + /* Return the output size */ + return OutputSize; +} + +LPWSTR +WINAPI +Dns_CreateStringCopy_W(IN LPWSTR Name) +{ + SIZE_T StringLength; + LPWSTR NameCopy; + + /* Make sure that we have a name */ + if (!Name) + { + /* Fail */ + SetLastError(ERROR_INVALID_PARAMETER); + return NULL; + } + + /* Find out the size of the string */ + StringLength = (wcslen(Name) + 1) * sizeof(WCHAR); + + /* Allocate space for the copy */ + NameCopy = Dns_AllocZero(StringLength); + if (NameCopy) + { + /* Copy it */ + RtlCopyMemory(NameCopy, Name, StringLength); + } + else + { + /* Fail */ + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + } + + /* Return the copy */ + return NameCopy; +} + +ULONG +WINAPI +Dns_GetBufferLengthForStringCopy(IN PVOID String, + IN ULONG Size OPTIONAL, + IN DWORD InputType, + IN DWORD OutputType) +{ + ULONG OutputSize = 0; + + /* Check what kind of string this is */ + if (InputType == UnicodeString) + { + /* Check if we have a size */ + if (!Size) + { + /* Get it ourselves */ + Size = (ULONG)wcslen(String); + } + + /* Check the output type */ + if (OutputType == UnicodeString) + { + /* Convert the size to bytes */ + OutputSize = (Size + 1) * sizeof(WCHAR); + } + else if (OutputType == Utf8String) + { + /* FIXME */ + OutputSize = 0; + } + else + { + /* Find out how much it will be in ANSI bytes */ + OutputSize = WideCharToMultiByte(CP_ACP, + 0, + String, + Size, + NULL, + 0, + NULL, + NULL) + 1; + } + } + else if (InputType == AnsiString) + { + /* Check if we have a size */ + if (!Size) + { + /* Get it ourselves */ + Size = (ULONG)strlen(String); + } + + /* Check the output type */ + if (OutputType == AnsiString) + { + /* Just add a byte for the null char */ + OutputSize = Size + 1; + } + else if (OutputType == UnicodeString) + { + /* Calculate the bytes for a Unicode string */ + OutputSize = (MultiByteToWideChar(CP_ACP, + 0, + String, + Size, + NULL, + 0) + 1) * sizeof(WCHAR); + } + else if (OutputType == Utf8String) + { + /* FIXME */ + OutputSize = 0; + } + } + else if (InputType == Utf8String) + { + /* FIXME */ + OutputSize = 0; + } + + /* Return the size required */ + return OutputSize; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/string.c + * PURPOSE: functions for string manipulation and conversion. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +ULONG +WINAPI +Dns_StringCopy(OUT PVOID Destination, + IN OUT PULONG DestinationSize, + IN PVOID String, + IN ULONG StringSize OPTIONAL, + IN DWORD InputType, + IN DWORD OutputType) +{ + ULONG DestSize; + ULONG OutputSize = 0; + + /* Check if the caller already gave us the string size */ + if (!StringSize) + { + /* He didn't, get the input type */ + if (InputType == UnicodeString) + { + /* Unicode string, calculate the size */ + StringSize = (ULONG)wcslen((LPWSTR)String); + } + else + { + /* ANSI or UTF-8 sting, get the size */ + StringSize = (ULONG)strlen((LPSTR)String); + } + } + + /* Check if we have a limit on the desination size */ + if (DestinationSize) + { + /* Make sure that we can respect it */ + DestSize = Dns_GetBufferLengthForStringCopy(String, + StringSize, + InputType, + OutputType); + if (*DestinationSize < DestSize) + { + /* Fail due to missing buffer space */ + SetLastError(ERROR_MORE_DATA); + + /* Return how much data we actually need */ + *DestinationSize = DestSize; + return 0; + } + else if (!DestSize) + { + /* Fail due to invalid data */ + SetLastError(ERROR_INVALID_DATA); + return 0; + } + + /* Return how much data we actually need */ + *DestinationSize = DestSize; + } + + /* Now check if this is a Unicode String as input */ + if (InputType == UnicodeString) + { + /* Check if the output is ANSI */ + if (OutputType == AnsiString) + { + /* Convert and return the final desination size */ + OutputSize = WideCharToMultiByte(CP_ACP, + 0, + String, + StringSize, + Destination, + -1, + NULL, + NULL) + 1; + } + else if (OutputType == UnicodeString) + { + /* Copy the string */ + StringSize = StringSize * sizeof(WCHAR); + RtlMoveMemory(Destination, String, StringSize); + + /* Return output length */ + OutputSize = StringSize + 2; + } + else if (OutputType == Utf8String) + { + /* FIXME */ + OutputSize = 0; + } + } + else if (InputType == AnsiString) + { + /* It's ANSI, is the output ansi too? */ + if (OutputType == AnsiString) + { + /* Copy the string */ + RtlMoveMemory(Destination, String, StringSize); + + /* Return output length */ + OutputSize = StringSize + 1; + } + else if (OutputType == UnicodeString) + { + /* Convert to Unicode and return size */ + OutputSize = MultiByteToWideChar(CP_ACP, + 0, + String, + StringSize, + Destination, + -1) * sizeof(WCHAR) + 2; + } + else if (OutputType == Utf8String) + { + /* FIXME */ + OutputSize = 0; + } + } + else if (InputType == Utf8String) + { + /* FIXME */ + OutputSize = 0; + } + + /* Return the output size */ + return OutputSize; +} + +LPWSTR +WINAPI +Dns_CreateStringCopy_W(IN LPWSTR Name) +{ + SIZE_T StringLength; + LPWSTR NameCopy; + + /* Make sure that we have a name */ + if (!Name) + { + /* Fail */ + SetLastError(ERROR_INVALID_PARAMETER); + return NULL; + } + + /* Find out the size of the string */ + StringLength = (wcslen(Name) + 1) * sizeof(WCHAR); + + /* Allocate space for the copy */ + NameCopy = Dns_AllocZero(StringLength); + if (NameCopy) + { + /* Copy it */ + RtlCopyMemory(NameCopy, Name, StringLength); + } + else + { + /* Fail */ + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + } + + /* Return the copy */ + return NameCopy; +} + +ULONG +WINAPI +Dns_GetBufferLengthForStringCopy(IN PVOID String, + IN ULONG Size OPTIONAL, + IN DWORD InputType, + IN DWORD OutputType) +{ + ULONG OutputSize = 0; + + /* Check what kind of string this is */ + if (InputType == UnicodeString) + { + /* Check if we have a size */ + if (!Size) + { + /* Get it ourselves */ + Size = (ULONG)wcslen(String); + } + + /* Check the output type */ + if (OutputType == UnicodeString) + { + /* Convert the size to bytes */ + OutputSize = (Size + 1) * sizeof(WCHAR); + } + else if (OutputType == Utf8String) + { + /* FIXME */ + OutputSize = 0; + } + else + { + /* Find out how much it will be in ANSI bytes */ + OutputSize = WideCharToMultiByte(CP_ACP, + 0, + String, + Size, + NULL, + 0, + NULL, + NULL) + 1; + } + } + else if (InputType == AnsiString) + { + /* Check if we have a size */ + if (!Size) + { + /* Get it ourselves */ + Size = (ULONG)strlen(String); + } + + /* Check the output type */ + if (OutputType == AnsiString) + { + /* Just add a byte for the null char */ + OutputSize = Size + 1; + } + else if (OutputType == UnicodeString) + { + /* Calculate the bytes for a Unicode string */ + OutputSize = (MultiByteToWideChar(CP_ACP, + 0, + String, + Size, + NULL, + 0) + 1) * sizeof(WCHAR); + } + else if (OutputType == Utf8String) + { + /* FIXME */ + OutputSize = 0; + } + } + else if (InputType == Utf8String) + { + /* FIXME */ + OutputSize = 0; + } + + /* Return the size required */ + return OutputSize; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/string.c + * PURPOSE: functions for string manipulation and conversion. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +ULONG +WINAPI +Dns_StringCopy(OUT PVOID Destination, + IN OUT PULONG DestinationSize, + IN PVOID String, + IN ULONG StringSize OPTIONAL, + IN DWORD InputType, + IN DWORD OutputType) +{ + ULONG DestSize; + ULONG OutputSize = 0; + + /* Check if the caller already gave us the string size */ + if (!StringSize) + { + /* He didn't, get the input type */ + if (InputType == UnicodeString) + { + /* Unicode string, calculate the size */ + StringSize = (ULONG)wcslen((LPWSTR)String); + } + else + { + /* ANSI or UTF-8 sting, get the size */ + StringSize = (ULONG)strlen((LPSTR)String); + } + } + + /* Check if we have a limit on the desination size */ + if (DestinationSize) + { + /* Make sure that we can respect it */ + DestSize = Dns_GetBufferLengthForStringCopy(String, + StringSize, + InputType, + OutputType); + if (*DestinationSize < DestSize) + { + /* Fail due to missing buffer space */ + SetLastError(ERROR_MORE_DATA); + + /* Return how much data we actually need */ + *DestinationSize = DestSize; + return 0; + } + else if (!DestSize) + { + /* Fail due to invalid data */ + SetLastError(ERROR_INVALID_DATA); + return 0; + } + + /* Return how much data we actually need */ + *DestinationSize = DestSize; + } + + /* Now check if this is a Unicode String as input */ + if (InputType == UnicodeString) + { + /* Check if the output is ANSI */ + if (OutputType == AnsiString) + { + /* Convert and return the final desination size */ + OutputSize = WideCharToMultiByte(CP_ACP, + 0, + String, + StringSize, + Destination, + -1, + NULL, + NULL) + 1; + } + else if (OutputType == UnicodeString) + { + /* Copy the string */ + StringSize = StringSize * sizeof(WCHAR); + RtlMoveMemory(Destination, String, StringSize); + + /* Return output length */ + OutputSize = StringSize + 2; + } + else if (OutputType == Utf8String) + { + /* FIXME */ + OutputSize = 0; + } + } + else if (InputType == AnsiString) + { + /* It's ANSI, is the output ansi too? */ + if (OutputType == AnsiString) + { + /* Copy the string */ + RtlMoveMemory(Destination, String, StringSize); + + /* Return output length */ + OutputSize = StringSize + 1; + } + else if (OutputType == UnicodeString) + { + /* Convert to Unicode and return size */ + OutputSize = MultiByteToWideChar(CP_ACP, + 0, + String, + StringSize, + Destination, + -1) * sizeof(WCHAR) + 2; + } + else if (OutputType == Utf8String) + { + /* FIXME */ + OutputSize = 0; + } + } + else if (InputType == Utf8String) + { + /* FIXME */ + OutputSize = 0; + } + + /* Return the output size */ + return OutputSize; +} + +LPWSTR +WINAPI +Dns_CreateStringCopy_W(IN LPWSTR Name) +{ + SIZE_T StringLength; + LPWSTR NameCopy; + + /* Make sure that we have a name */ + if (!Name) + { + /* Fail */ + SetLastError(ERROR_INVALID_PARAMETER); + return NULL; + } + + /* Find out the size of the string */ + StringLength = (wcslen(Name) + 1) * sizeof(WCHAR); + + /* Allocate space for the copy */ + NameCopy = Dns_AllocZero(StringLength); + if (NameCopy) + { + /* Copy it */ + RtlCopyMemory(NameCopy, Name, StringLength); + } + else + { + /* Fail */ + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + } + + /* Return the copy */ + return NameCopy; +} + +ULONG +WINAPI +Dns_GetBufferLengthForStringCopy(IN PVOID String, + IN ULONG Size OPTIONAL, + IN DWORD InputType, + IN DWORD OutputType) +{ + ULONG OutputSize = 0; + + /* Check what kind of string this is */ + if (InputType == UnicodeString) + { + /* Check if we have a size */ + if (!Size) + { + /* Get it ourselves */ + Size = (ULONG)wcslen(String); + } + + /* Check the output type */ + if (OutputType == UnicodeString) + { + /* Convert the size to bytes */ + OutputSize = (Size + 1) * sizeof(WCHAR); + } + else if (OutputType == Utf8String) + { + /* FIXME */ + OutputSize = 0; + } + else + { + /* Find out how much it will be in ANSI bytes */ + OutputSize = WideCharToMultiByte(CP_ACP, + 0, + String, + Size, + NULL, + 0, + NULL, + NULL) + 1; + } + } + else if (InputType == AnsiString) + { + /* Check if we have a size */ + if (!Size) + { + /* Get it ourselves */ + Size = (ULONG)strlen(String); + } + + /* Check the output type */ + if (OutputType == AnsiString) + { + /* Just add a byte for the null char */ + OutputSize = Size + 1; + } + else if (OutputType == UnicodeString) + { + /* Calculate the bytes for a Unicode string */ + OutputSize = (MultiByteToWideChar(CP_ACP, + 0, + String, + Size, + NULL, + 0) + 1) * sizeof(WCHAR); + } + else if (OutputType == Utf8String) + { + /* FIXME */ + OutputSize = 0; + } + } + else if (InputType == Utf8String) + { + /* FIXME */ + OutputSize = 0; + } + + /* Return the size required */ + return OutputSize; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/string.c + * PURPOSE: functions for string manipulation and conversion. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +ULONG +WINAPI +Dns_StringCopy(OUT PVOID Destination, + IN OUT PULONG DestinationSize, + IN PVOID String, + IN ULONG StringSize OPTIONAL, + IN DWORD InputType, + IN DWORD OutputType) +{ + ULONG DestSize; + ULONG OutputSize = 0; + + /* Check if the caller already gave us the string size */ + if (!StringSize) + { + /* He didn't, get the input type */ + if (InputType == UnicodeString) + { + /* Unicode string, calculate the size */ + StringSize = (ULONG)wcslen((LPWSTR)String); + } + else + { + /* ANSI or UTF-8 sting, get the size */ + StringSize = (ULONG)strlen((LPSTR)String); + } + } + + /* Check if we have a limit on the desination size */ + if (DestinationSize) + { + /* Make sure that we can respect it */ + DestSize = Dns_GetBufferLengthForStringCopy(String, + StringSize, + InputType, + OutputType); + if (*DestinationSize < DestSize) + { + /* Fail due to missing buffer space */ + SetLastError(ERROR_MORE_DATA); + + /* Return how much data we actually need */ + *DestinationSize = DestSize; + return 0; + } + else if (!DestSize) + { + /* Fail due to invalid data */ + SetLastError(ERROR_INVALID_DATA); + return 0; + } + + /* Return how much data we actually need */ + *DestinationSize = DestSize; + } + + /* Now check if this is a Unicode String as input */ + if (InputType == UnicodeString) + { + /* Check if the output is ANSI */ + if (OutputType == AnsiString) + { + /* Convert and return the final desination size */ + OutputSize = WideCharToMultiByte(CP_ACP, + 0, + String, + StringSize, + Destination, + -1, + NULL, + NULL) + 1; + } + else if (OutputType == UnicodeString) + { + /* Copy the string */ + StringSize = StringSize * sizeof(WCHAR); + RtlMoveMemory(Destination, String, StringSize); + + /* Return output length */ + OutputSize = StringSize + 2; + } + else if (OutputType == Utf8String) + { + /* FIXME */ + OutputSize = 0; + } + } + else if (InputType == AnsiString) + { + /* It's ANSI, is the output ansi too? */ + if (OutputType == AnsiString) + { + /* Copy the string */ + RtlMoveMemory(Destination, String, StringSize); + + /* Return output length */ + OutputSize = StringSize + 1; + } + else if (OutputType == UnicodeString) + { + /* Convert to Unicode and return size */ + OutputSize = MultiByteToWideChar(CP_ACP, + 0, + String, + StringSize, + Destination, + -1) * sizeof(WCHAR) + 2; + } + else if (OutputType == Utf8String) + { + /* FIXME */ + OutputSize = 0; + } + } + else if (InputType == Utf8String) + { + /* FIXME */ + OutputSize = 0; + } + + /* Return the output size */ + return OutputSize; +} + +LPWSTR +WINAPI +Dns_CreateStringCopy_W(IN LPWSTR Name) +{ + SIZE_T StringLength; + LPWSTR NameCopy; + + /* Make sure that we have a name */ + if (!Name) + { + /* Fail */ + SetLastError(ERROR_INVALID_PARAMETER); + return NULL; + } + + /* Find out the size of the string */ + StringLength = (wcslen(Name) + 1) * sizeof(WCHAR); + + /* Allocate space for the copy */ + NameCopy = Dns_AllocZero(StringLength); + if (NameCopy) + { + /* Copy it */ + RtlCopyMemory(NameCopy, Name, StringLength); + } + else + { + /* Fail */ + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + } + + /* Return the copy */ + return NameCopy; +} + +ULONG +WINAPI +Dns_GetBufferLengthForStringCopy(IN PVOID String, + IN ULONG Size OPTIONAL, + IN DWORD InputType, + IN DWORD OutputType) +{ + ULONG OutputSize = 0; + + /* Check what kind of string this is */ + if (InputType == UnicodeString) + { + /* Check if we have a size */ + if (!Size) + { + /* Get it ourselves */ + Size = (ULONG)wcslen(String); + } + + /* Check the output type */ + if (OutputType == UnicodeString) + { + /* Convert the size to bytes */ + OutputSize = (Size + 1) * sizeof(WCHAR); + } + else if (OutputType == Utf8String) + { + /* FIXME */ + OutputSize = 0; + } + else + { + /* Find out how much it will be in ANSI bytes */ + OutputSize = WideCharToMultiByte(CP_ACP, + 0, + String, + Size, + NULL, + 0, + NULL, + NULL) + 1; + } + } + else if (InputType == AnsiString) + { + /* Check if we have a size */ + if (!Size) + { + /* Get it ourselves */ + Size = (ULONG)strlen(String); + } + + /* Check the output type */ + if (OutputType == AnsiString) + { + /* Just add a byte for the null char */ + OutputSize = Size + 1; + } + else if (OutputType == UnicodeString) + { + /* Calculate the bytes for a Unicode string */ + OutputSize = (MultiByteToWideChar(CP_ACP, + 0, + String, + Size, + NULL, + 0) + 1) * sizeof(WCHAR); + } + else if (OutputType == Utf8String) + { + /* FIXME */ + OutputSize = 0; + } + } + else if (InputType == Utf8String) + { + /* FIXME */ + OutputSize = 0; + } + + /* Return the size required */ + return OutputSize; +} + diff --git a/dll/win32/mswsock/dns/table.c b/dll/win32/mswsock/dns/table.c new file mode 100644 index 00000000000..7660cae281c --- /dev/null +++ b/dll/win32/mswsock/dns/table.c @@ -0,0 +1,56 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/table.c + * PURPOSE: Functions for doing Table lookups, such as LUP Flags. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/table.c + * PURPOSE: Functions for doing Table lookups, such as LUP Flags. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/table.c + * PURPOSE: Functions for doing Table lookups, such as LUP Flags. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/table.c + * PURPOSE: Functions for doing Table lookups, such as LUP Flags. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + diff --git a/dll/win32/mswsock/dns/utf8.c b/dll/win32/mswsock/dns/utf8.c new file mode 100644 index 00000000000..55d218bfede --- /dev/null +++ b/dll/win32/mswsock/dns/utf8.c @@ -0,0 +1,56 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/utf8.c + * PURPOSE: Functions for doing UTF8 string conversion and manipulation. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/utf8.c + * PURPOSE: Functions for doing UTF8 string conversion and manipulation. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/utf8.c + * PURPOSE: Functions for doing UTF8 string conversion and manipulation. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/utf8.c + * PURPOSE: Functions for doing UTF8 string conversion and manipulation. + */ + +/* INCLUDES ******************************************************************/ +#include "precomp.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + diff --git a/dll/win32/mswsock/extensions.c b/dll/win32/mswsock/extensions.c deleted file mode 100644 index 8271656bdda..00000000000 --- a/dll/win32/mswsock/extensions.c +++ /dev/null @@ -1,54 +0,0 @@ -/* $Id: stubs.c 12852 2005-01-06 13:58:04Z mf $ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS WinSock DLL - * FILE: stubs.c - * PURPOSE: WSAIoctl wrappers for Microsoft extensions to Winsock - * PROGRAMMERS: KJK::Hyperion - * REVISIONS: - */ - -#include -#include -#include - -/* - * @implemented - */ -BOOL -WINAPI -TransmitFile(SOCKET Socket, - HANDLE File, - DWORD NumberOfBytesToWrite, - DWORD NumberOfBytesPerSend, - LPOVERLAPPED Overlapped, - LPTRANSMIT_FILE_BUFFERS TransmitBuffers, - DWORD Flags) -{ - static GUID TransmitFileGUID = WSAID_TRANSMITFILE; - LPFN_TRANSMITFILE pfnTransmitFile; - DWORD cbBytesReturned; - - if (WSAIoctl(Socket, - SIO_GET_EXTENSION_FUNCTION_POINTER, - &TransmitFileGUID, - sizeof(TransmitFileGUID), - &pfnTransmitFile, - sizeof(pfnTransmitFile), - &cbBytesReturned, - NULL, - NULL) == SOCKET_ERROR) - { - return FALSE; - } - - return pfnTransmitFile(Socket, - File, - NumberOfBytesToWrite, - NumberOfBytesPerSend, - Overlapped, - TransmitBuffers, - Flags); -} - -/* EOF */ diff --git a/dll/win32/mswsock/msafd/accept.c b/dll/win32/mswsock/msafd/accept.c new file mode 100644 index 00000000000..83789067c92 --- /dev/null +++ b/dll/win32/mswsock/msafd/accept.c @@ -0,0 +1,3900 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +SockCoreAccept(IN PSOCKET_INFORMATION Socket, + IN PSOCKET_INFORMATION AcceptedSocket) +{ + INT ErrorCode, ReturnValue; + BOOLEAN BlockMode = Socket->SharedData.NonBlocking; + BOOLEAN Oob = Socket->SharedData.OobInline; + INT HelperContextSize; + PVOID HelperContext = NULL; + HWND hWnd = 0; + UINT wMsg = 0; + HANDLE EventObject = NULL; + ULONG AsyncEvents = 0, NetworkEvents = 0; + CHAR HelperBuffer[256]; + + /* Set the new state */ + AcceptedSocket->SharedData.State = SocketConnected; + + /* Copy some of the settings */ + AcceptedSocket->SharedData.LingerData = Socket->SharedData.LingerData; + AcceptedSocket->SharedData.SizeOfRecvBuffer = Socket->SharedData.SizeOfRecvBuffer; + AcceptedSocket->SharedData.SizeOfSendBuffer = Socket->SharedData.SizeOfSendBuffer; + AcceptedSocket->SharedData.Broadcast = Socket->SharedData.Broadcast; + AcceptedSocket->SharedData.Debug = Socket->SharedData.Debug; + AcceptedSocket->SharedData.OobInline = Socket->SharedData.OobInline; + AcceptedSocket->SharedData.ReuseAddresses = Socket->SharedData.ReuseAddresses; + AcceptedSocket->SharedData.SendTimeout = Socket->SharedData.SendTimeout; + AcceptedSocket->SharedData.RecvTimeout = Socket->SharedData.RecvTimeout; + + /* Check if the old socket had async select */ + if (Socket->SharedData.AsyncEvents) + { + /* Copy the data while we're still under the lock */ + AsyncEvents = Socket->SharedData.AsyncEvents; + hWnd = Socket->SharedData.hWnd; + wMsg = Socket->SharedData.wMsg; + } + else if (Socket->NetworkEvents) + { + /* Copy the data while we're still under the lock */ + NetworkEvents = Socket->NetworkEvents; + EventObject = Socket->EventObject; + } + + /* Check how much space is needed for the context */ + ReturnValue = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, + Socket->Handle, + Socket->TdiAddressHandle, + Socket->TdiConnectionHandle, + SOL_INTERNAL, + SO_CONTEXT, + NULL, + &HelperContextSize); + if (ReturnValue == NO_ERROR) + { + /* Check if our stack buffer is large enough to hold it */ + if (HelperContextSize <= sizeof(HelperBuffer)) + { + /* Use it */ + HelperContext = (PVOID)HelperBuffer; + } + else + { + /* Allocate from the heap instead */ + HelperContext = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + HelperContextSize); + if (!HelperContext) + { + /* Unlock the socket and fail */ + LeaveCriticalSection(&Socket->Lock); + return WSAENOBUFS; + } + } + + /* Get the context */ + ReturnValue = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, + Socket->Handle, + Socket->TdiAddressHandle, + Socket->TdiConnectionHandle, + SOL_INTERNAL, + SO_CONTEXT, + HelperContext, + &HelperContextSize); + } + + /* We're done with the old socket, so we can release the lock */ + LeaveCriticalSection(&Socket->Lock); + + /* Get the TDI Handles for the new socket */ + ErrorCode = SockGetTdiHandles(AcceptedSocket); + + /* Check if we have the handles and the context */ + if ((ErrorCode == NO_ERROR) && (ReturnValue == NO_ERROR)) + { + /* Set the context */ + AcceptedSocket->HelperData->WSHGetSocketInformation(AcceptedSocket->HelperContext, + AcceptedSocket->Handle, + AcceptedSocket->TdiAddressHandle, + AcceptedSocket->TdiConnectionHandle, + SOL_INTERNAL, + SO_CONTEXT, + HelperContext, + &HelperContextSize); + } + + /* Check if we should free from heap */ + if (HelperContext && (HelperContext != (PVOID)HelperBuffer)) + { + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, HelperContext); + } + + /* Check if the old socket was non-blocking */ + if (BlockMode) + { + /* Set the new one like that too */ + ErrorCode = SockSetInformation(AcceptedSocket, + AFD_INFO_BLOCKING_MODE, + &BlockMode, + NULL, + NULL); + if (ErrorCode != NO_ERROR) return ErrorCode; + } + + /* Set it internally as well */ + AcceptedSocket->SharedData.NonBlocking = Socket->SharedData.NonBlocking; + + /* Check if inlined OOB was enabled */ + if (Oob) + { + /* Set the new one like that too */ + ErrorCode = SockSetInformation(AcceptedSocket, + AFD_INFO_INLINING_MODE, + &Oob, + NULL, + NULL); + if (ErrorCode != NO_ERROR) return ErrorCode; + } + + /* Set it internally as well */ + AcceptedSocket->SharedData.OobInline = Socket->SharedData.OobInline; + + /* Update the Window Sizes */ + ErrorCode = SockUpdateWindowSizes(AcceptedSocket, FALSE); + if (ErrorCode != NO_ERROR) return ErrorCode; + + /* Check if async select was enabled */ + if (AsyncEvents) + { + /* Call WSPAsyncSelect on the accepted socket too */ + ErrorCode = SockAsyncSelectHelper(AcceptedSocket, + hWnd, + wMsg, + AsyncEvents); + } + else if (NetworkEvents) + { + /* WSPEventSelect was enabled instead, call it on the new socket */ + ErrorCode = SockEventSelectHelper(AcceptedSocket, + EventObject, + NetworkEvents); + } + + /* Check for failure */ + if (ErrorCode != NO_ERROR) return ErrorCode; + + /* Set the new context in AFD */ + ErrorCode = SockSetHandleContext(AcceptedSocket); + if (ErrorCode != NO_ERROR) return ErrorCode; + + /* Return success*/ + return NO_ERROR; +} + +SOCKET +WSPAPI +WSPAccept(SOCKET Handle, + SOCKADDR FAR * SocketAddress, + LPINT SocketAddressLength, + LPCONDITIONPROC lpfnCondition, + DWORD_PTR dwCallbackData, + LPINT lpErrno) +{ + INT ErrorCode, ReturnValue; + PSOCKET_INFORMATION Socket, AcceptedSocket = NULL; + PWINSOCK_TEB_DATA ThreadData; + CHAR AfdAcceptBuffer[32]; + PAFD_RECEIVED_ACCEPT_DATA ReceivedAcceptData = NULL; + ULONG ReceiveBufferSize; + FD_SET ReadFds; + TIMEVAL Timeout; + NTSTATUS Status; + IO_STATUS_BLOCK IoStatusBlock; + ULONG AddressBufferSize; + CHAR AddressBuffer[sizeof(SOCKADDR)]; + PVOID SockAddress; + ULONG ConnectDataSize; + PVOID ConnectData = NULL; + AFD_PENDING_ACCEPT_DATA PendingAcceptData; + INT AddressSize; + PVOID CalleeDataBuffer = NULL; + WSABUF CallerId, CalleeId, CallerData, CalleeData; + GROUP GroupId; + LPQOS Qos = NULL, GroupQos = NULL; + BOOLEAN ValidGroup = TRUE; + AFD_DEFER_ACCEPT_DATA DeferData; + ULONG BytesReturned; + SOCKET AcceptedHandle = INVALID_SOCKET; + AFD_ACCEPT_DATA AcceptData; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* Invalid for datagram sockets */ + if (MSAFD_IS_DGRAM_SOCK(Socket)) + { + /* Fail */ + ErrorCode = WSAEOPNOTSUPP; + goto error; + } + + /* Only valid if the socket is listening */ + if (!Socket->SharedData.Listening) + { + /* Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Validate address length */ + if (SocketAddressLength && + (Socket->HelperData->MinWSAddressLength > *SocketAddressLength)) + { + /* Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Calculate how much space we'll need for the Receive Buffer */ + ReceiveBufferSize = sizeof(AFD_RECEIVED_ACCEPT_DATA) + + sizeof(TRANSPORT_ADDRESS) + + Socket->HelperData->MaxTDIAddressLength; + + /* Check if our stack buffer is large enough */ + if (ReceiveBufferSize <= sizeof(AfdAcceptBuffer)) + { + /* Use the stack */ + ReceivedAcceptData = (PVOID)AfdAcceptBuffer; + } + else + { + /* Allocate from heap */ + ReceivedAcceptData = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + ReceiveBufferSize); + if (!ReceivedAcceptData) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + } + + /* If this is non-blocking, make sure there's something for us to accept */ + if (Socket->SharedData.NonBlocking) + { + /* Set up a nonblocking select */ + FD_ZERO(&ReadFds); + FD_SET(Handle, &ReadFds); + Timeout.tv_sec = 0; + Timeout.tv_usec = 0; + + /* See if there's any data */ + ReturnValue = WSPSelect(1, + &ReadFds, + NULL, + NULL, + &Timeout, + lpErrno); + if (ReturnValue == SOCKET_ERROR) + { + /* Fail */ + ErrorCode = *lpErrno; + goto error; + } + + /* Make sure we got a read back */ + if (!FD_ISSET(Handle, &ReadFds)) + { + /* Fail */ + ErrorCode = WSAEWOULDBLOCK; + goto error; + } + } + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_WAIT_FOR_LISTEN, + NULL, + 0, + ReceivedAcceptData, + ReceiveBufferSize); + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion outside the lock */ + LeaveCriticalSection(&Socket->Lock); + SockWaitForSingleObject(ThreadData->EventHandle, + Handle, + MAYBE_BLOCKING_HOOK, + NO_TIMEOUT); + EnterCriticalSection(&Socket->Lock); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* Check if we got a condition callback */ + if (lpfnCondition) + { + /* Find out how much space we'll need for the address */ + AddressBufferSize = Socket->HelperData->MaxWSAddressLength; + + /* Check if our local buffer is enough */ + if (AddressBufferSize <= sizeof(AddressBuffer)) + { + /* It is, use the stack */ + SockAddress = (PVOID)AddressBuffer; + } + else + { + /* Allocate from heap */ + SockAddress = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + AddressBufferSize); + if (!SockAddress) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + } + + /* Assume no connect data */ + ConnectDataSize = 0; + + /* Make sure we support connect data */ + if ((Socket->SharedData.ServiceFlags1 & XP1_CONNECT_DATA)) + { + /* Find out how much data is pending */ + PendingAcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber; + PendingAcceptData.ReturnSize = TRUE; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_GET_PENDING_CONNECT_DATA, + &PendingAcceptData, + sizeof(PendingAcceptData), + &PendingAcceptData, + sizeof(PendingAcceptData)); + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + SockWaitForSingleObject(ThreadData->EventHandle, + Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* How much data to allocate */ + ConnectDataSize = PtrToUlong(IoStatusBlock.Information); + if (ConnectDataSize) + { + /* Allocate needed space */ + ConnectData = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + ConnectDataSize); + if (!ConnectData) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + + /* Setup the structure to actually get the data now */ + PendingAcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber; + PendingAcceptData.ReturnSize = FALSE; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_GET_PENDING_CONNECT_DATA, + &PendingAcceptData, + sizeof(PendingAcceptData), + ConnectData, + ConnectDataSize); + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + SockWaitForSingleObject(ThreadData->EventHandle, + Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + } + } + + if ((Socket->SharedData.ServiceFlags1 & XP1_QOS_SUPPORTED)) + { + /* Set the accept data */ + AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber; + AcceptData.ListenHandle = Socket->WshContext.Handle; + + /* Save it in the TEB */ + ThreadData->AcceptData = &AcceptData; + + /* Send the IOCTL to get QOS Size */ + BytesReturned = 0; + ReturnValue = WSPIoctl(Handle, + SIO_GET_QOS, + NULL, + 0, + NULL, + 0, + &BytesReturned, + NULL, + NULL, + NULL, + &ErrorCode); + + /* Check if it failed (it should) */ + if (ReturnValue == SOCKET_ERROR) + { + /* Check if it failed because it had no buffer (it should) */ + if (ErrorCode == WSAEFAULT) + { + /* Make sure it told us how many bytes it needed */ + if (BytesReturned) + { + /* Allocate memory for it */ + Qos = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + BytesReturned); + if (!Qos) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + + /* Save the accept data and set the QoS */ + ThreadData->AcceptData = &AcceptData; + ReturnValue = WSPIoctl(Handle, + SIO_GET_QOS, + NULL, + 0, + Qos, + BytesReturned, + &BytesReturned, + NULL, + NULL, + NULL, + &ErrorCode); + } + } + else + { + /* We got some other weird, error, fail. */ + goto error; + } + } + + /* Save the accept in the TEB */ + ThreadData->AcceptData = &AcceptData; + + /* Send the IOCTL to get Group QOS Size */ + BytesReturned = 0; + ReturnValue = WSPIoctl(Handle, + SIO_GET_GROUP_QOS, + NULL, + 0, + NULL, + 0, + &BytesReturned, + NULL, + NULL, + NULL, + &ErrorCode); + + /* Check if it failed (it should) */ + if (ReturnValue == SOCKET_ERROR) + { + /* Check if it failed because it had no buffer (it should) */ + if (ErrorCode == WSAEFAULT) + { + /* Make sure it told us how many bytes it needed */ + if (BytesReturned) + { + /* Allocate memory for it */ + GroupQos = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + BytesReturned); + if (!GroupQos) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + + /* Save the accept data and set the QoS */ + ThreadData->AcceptData = &AcceptData; + ReturnValue = WSPIoctl(Handle, + SIO_GET_QOS, + NULL, + 0, + GroupQos, + BytesReturned, + &BytesReturned, + NULL, + NULL, + NULL, + &ErrorCode); + } + } + else + { + /* We got some other weird, error, fail. */ + goto error; + } + } + } + + /* Build Callee ID */ + CalleeId.buf = (PVOID)Socket->LocalAddress; + CalleeId.len = Socket->SharedData.SizeOfLocalAddress; + + /* Set up Address in SOCKADDR Format */ + SockBuildSockaddr((PSOCKADDR)SockAddress, + &AddressSize, + &ReceivedAcceptData->Address); + + /* Build Caller ID */ + CallerId.buf = (PVOID)SockAddress; + CallerId.len = AddressSize; + + /* Build Caller Data */ + CallerData.buf = ConnectData; + CallerData.len = ConnectDataSize; + + /* Check if socket supports Conditional Accept */ + if (Socket->SharedData.UseDelayedAcceptance) + { + /* Allocate Buffer for Callee Data */ + CalleeDataBuffer = SockAllocateHeapRoutine(SockPrivateHeap, 0, 4096); + if (CalleeDataBuffer) + { + /* Fill the structure */ + CalleeData.buf = CalleeDataBuffer; + CalleeData.len = 4096; + } + else + { + /* Don't fail, just don't use this... */ + CalleeData.len = 0; + } + } + else + { + /* Nothing */ + CalleeData.buf = NULL; + CalleeData.len = 0; + } + + /* Call the Condition Function */ + ReturnValue = (lpfnCondition)(&CallerId, + !CallerData.buf ? NULL : & CallerData, + NULL, + NULL, + &CalleeId, + !CalleeData.buf ? NULL: & CalleeData, + &GroupId, + dwCallbackData); + + if ((ReturnValue == CF_ACCEPT) && + (GroupId) && + (GroupId != SG_UNCONSTRAINED_GROUP) && + (GroupId != SG_CONSTRAINED_GROUP)) + { + /* Check for validity */ + ErrorCode = SockIsAddressConsistentWithConstrainedGroup(Socket, + GroupId, + SockAddress, + AddressSize); + ValidGroup = (ErrorCode == NO_ERROR); + } + + /* Check if the address was from the heap */ + if (SockAddress != AddressBuffer) + { + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, SockAddress); + } + + /* Check if it was accepted */ + if (ReturnValue == CF_ACCEPT) + { + /* Check if the group is invalid, however */ + if (!ValidGroup) goto error; + + /* Now check if QOS is supported */ + if ((Socket->SharedData.ServiceFlags1 & XP1_QOS_SUPPORTED)) + { + /* Check if we had Qos */ + if (Qos) + { + /* Set the accept data */ + AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber; + AcceptData.ListenHandle = Socket->WshContext.Handle; + + /* Save it in the TEB */ + ThreadData->AcceptData = &AcceptData; + + /* Send the IOCTL */ + BytesReturned = 0; + ReturnValue = WSPIoctl(Handle, + SIO_SET_QOS, + Qos, + sizeof(*Qos), + NULL, + 0, + &BytesReturned, + NULL, + NULL, + NULL, + &ErrorCode); + if (ReturnValue == SOCKET_ERROR) goto error; + } + + /* Check if we had Group Qos */ + if (GroupQos) + { + /* Set the accept data */ + AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber; + AcceptData.ListenHandle = Socket->WshContext.Handle; + + /* Save it in the TEB */ + ThreadData->AcceptData = &AcceptData; + + /* Send the IOCTL */ + ReturnValue = WSPIoctl(Handle, + SIO_SET_GROUP_QOS, + GroupQos, + sizeof(*GroupQos), + NULL, + 0, + &BytesReturned, + NULL, + NULL, + NULL, + &ErrorCode); + if (ReturnValue == SOCKET_ERROR) goto error; + } + } + + /* Check if delayed acceptance is used and we have callee data */ + if ((Socket->HelperData->UseDelayedAcceptance) && (CalleeData.len)) + { + /* Save the accept data in the TEB */ + ThreadData->AcceptData = &AcceptData; + + /* Set the connect data */ + ErrorCode = SockGetConnectData(Socket, + IOCTL_AFD_SET_CONNECT_DATA, + CalleeData.buf, + CalleeData.len, + NULL); + if (ErrorCode == SOCKET_ERROR) goto error; + } + } + else + { + /* Callback rejected. Build Defer Structure */ + DeferData.SequenceNumber = ReceivedAcceptData->SequenceNumber; + DeferData.RejectConnection = (ReturnValue == CF_REJECT); + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_DEFER_ACCEPT, + &DeferData, + sizeof(DeferData), + NULL, + 0); + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + if (ReturnValue == CF_REJECT) + { + /* The connection was refused */ + ErrorCode = WSAECONNREFUSED; + } + else + { + /* The connection was deferred */ + ErrorCode = WSATRY_AGAIN; + } + + /* Fail */ + goto error; + } + } + + /* Create a new Socket */ + ErrorCode = SockSocket(Socket->SharedData.AddressFamily, + Socket->SharedData.SocketType, + Socket->SharedData.Protocol, + &Socket->ProviderId, + GroupId, + Socket->SharedData.CreateFlags, + Socket->SharedData.ProviderFlags, + Socket->SharedData.ServiceFlags1, + Socket->SharedData.CatalogEntryId, + &AcceptedSocket); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + goto error; + } + + /* Set up the Accept Structure */ + AcceptData.ListenHandle = AcceptedSocket->WshContext.Handle; + AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber; + + /* Build the socket address */ + SockBuildSockaddr(AcceptedSocket->RemoteAddress, + &AcceptedSocket->SharedData.SizeOfRemoteAddress, + &ReceivedAcceptData->Address); + + /* Copy the local address */ + RtlCopyMemory(AcceptedSocket->LocalAddress, + Socket->LocalAddress, + Socket->SharedData.SizeOfLocalAddress); + AcceptedSocket->SharedData.SizeOfLocalAddress = Socket->SharedData.SizeOfLocalAddress; + + /* We can release the accepted socket's lock now */ + LeaveCriticalSection(&AcceptedSocket->Lock); + + /* Send IOCTL to Accept */ + AcceptData.UseSAN = SockSanEnabled; + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_ACCEPT, + &AcceptData, + sizeof(AcceptData), + NULL, + 0); + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion outside the lock */ + LeaveCriticalSection(&Socket->Lock); + SockWaitForSingleObject(ThreadData->EventHandle, + Handle, + MAYBE_BLOCKING_HOOK, + NO_TIMEOUT); + EnterCriticalSection(&Socket->Lock); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* Notify the helper DLL */ + ErrorCode = SockNotifyHelperDll(AcceptedSocket, WSH_NOTIFY_ACCEPT); + if (ErrorCode != NO_ERROR) goto error; + + /* If the caller sent a socket address pointer and length */ + if (SocketAddress && SocketAddressLength) + { + /* Return the address in its buffer */ + ErrorCode = SockBuildSockaddr(SocketAddress, + SocketAddressLength, + &ReceivedAcceptData->Address); + if (ErrorCode != NO_ERROR) goto error; + } + + /* Check if async select was active */ + if (SockAsyncSelectCalled) + { + /* Re-enable the regular accept event */ + SockReenableAsyncSelectEvent(Socket, FD_ACCEPT); + } + + /* Finally, do the internal core accept code */ + ErrorCode = SockCoreAccept(Socket, AcceptedSocket); + if (ErrorCode != NO_ERROR) goto error; + + /* Call WPU to tell it about the new handle */ + AcceptedHandle = SockUpcallTable->lpWPUModifyIFSHandle(AcceptedSocket->SharedData.CatalogEntryId, + (SOCKET)AcceptedSocket->WshContext.Handle, + &ErrorCode); + + /* Dereference the socket and clear its pointer for error code logic */ + SockDereferenceSocket(Socket); + Socket = NULL; + +error: + + /* Check if we have a socket here */ + if (Socket) + { + /* Check if async select was active */ + if (SockAsyncSelectCalled) + { + /* Re-enable the regular accept event */ + SockReenableAsyncSelectEvent(Socket, FD_ACCEPT); + } + + /* Unlock and dereference it */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + } + + /* Check if we got the accepted socket */ + if (AcceptedSocket) + { + /* Check if the accepted socket also has a handle */ + if (ErrorCode == NO_ERROR) + { + /* Close the socket */ + SockCloseSocket(AcceptedSocket); + } + + /* Dereference it */ + SockDereferenceSocket(AcceptedSocket); + } + + /* Check if the accept buffer was from the heap */ + if (ReceivedAcceptData && (ReceivedAcceptData != (PVOID)AfdAcceptBuffer)) + { + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, ReceivedAcceptData); + } + + /* Check if we have a connect data buffer */ + if (ConnectData) + { + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, ConnectData); + } + + /* Check if we have a callee data buffer */ + if (CalleeDataBuffer) + { + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, CalleeDataBuffer); + } + + /* Check if we have allocated QOS structures */ + if (Qos) + { + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, Qos); + } + if (GroupQos) + { + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, GroupQos); + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return INVALID_SOCKET; + } + + /* Return the new handle */ + return AcceptedHandle; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +SockCoreAccept(IN PSOCKET_INFORMATION Socket, + IN PSOCKET_INFORMATION AcceptedSocket) +{ + INT ErrorCode, ReturnValue; + BOOLEAN BlockMode = Socket->SharedData.NonBlocking; + BOOLEAN Oob = Socket->SharedData.OobInline; + INT HelperContextSize; + PVOID HelperContext = NULL; + HWND hWnd = 0; + UINT wMsg = 0; + HANDLE EventObject = NULL; + ULONG AsyncEvents = 0, NetworkEvents = 0; + CHAR HelperBuffer[256]; + + /* Set the new state */ + AcceptedSocket->SharedData.State = SocketConnected; + + /* Copy some of the settings */ + AcceptedSocket->SharedData.LingerData = Socket->SharedData.LingerData; + AcceptedSocket->SharedData.SizeOfRecvBuffer = Socket->SharedData.SizeOfRecvBuffer; + AcceptedSocket->SharedData.SizeOfSendBuffer = Socket->SharedData.SizeOfSendBuffer; + AcceptedSocket->SharedData.Broadcast = Socket->SharedData.Broadcast; + AcceptedSocket->SharedData.Debug = Socket->SharedData.Debug; + AcceptedSocket->SharedData.OobInline = Socket->SharedData.OobInline; + AcceptedSocket->SharedData.ReuseAddresses = Socket->SharedData.ReuseAddresses; + AcceptedSocket->SharedData.SendTimeout = Socket->SharedData.SendTimeout; + AcceptedSocket->SharedData.RecvTimeout = Socket->SharedData.RecvTimeout; + + /* Check if the old socket had async select */ + if (Socket->SharedData.AsyncEvents) + { + /* Copy the data while we're still under the lock */ + AsyncEvents = Socket->SharedData.AsyncEvents; + hWnd = Socket->SharedData.hWnd; + wMsg = Socket->SharedData.wMsg; + } + else if (Socket->NetworkEvents) + { + /* Copy the data while we're still under the lock */ + NetworkEvents = Socket->NetworkEvents; + EventObject = Socket->EventObject; + } + + /* Check how much space is needed for the context */ + ReturnValue = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, + Socket->Handle, + Socket->TdiAddressHandle, + Socket->TdiConnectionHandle, + SOL_INTERNAL, + SO_CONTEXT, + NULL, + &HelperContextSize); + if (ReturnValue == NO_ERROR) + { + /* Check if our stack buffer is large enough to hold it */ + if (HelperContextSize <= sizeof(HelperBuffer)) + { + /* Use it */ + HelperContext = (PVOID)HelperBuffer; + } + else + { + /* Allocate from the heap instead */ + HelperContext = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + HelperContextSize); + if (!HelperContext) + { + /* Unlock the socket and fail */ + LeaveCriticalSection(&Socket->Lock); + return WSAENOBUFS; + } + } + + /* Get the context */ + ReturnValue = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, + Socket->Handle, + Socket->TdiAddressHandle, + Socket->TdiConnectionHandle, + SOL_INTERNAL, + SO_CONTEXT, + HelperContext, + &HelperContextSize); + } + + /* We're done with the old socket, so we can release the lock */ + LeaveCriticalSection(&Socket->Lock); + + /* Get the TDI Handles for the new socket */ + ErrorCode = SockGetTdiHandles(AcceptedSocket); + + /* Check if we have the handles and the context */ + if ((ErrorCode == NO_ERROR) && (ReturnValue == NO_ERROR)) + { + /* Set the context */ + AcceptedSocket->HelperData->WSHGetSocketInformation(AcceptedSocket->HelperContext, + AcceptedSocket->Handle, + AcceptedSocket->TdiAddressHandle, + AcceptedSocket->TdiConnectionHandle, + SOL_INTERNAL, + SO_CONTEXT, + HelperContext, + &HelperContextSize); + } + + /* Check if we should free from heap */ + if (HelperContext && (HelperContext != (PVOID)HelperBuffer)) + { + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, HelperContext); + } + + /* Check if the old socket was non-blocking */ + if (BlockMode) + { + /* Set the new one like that too */ + ErrorCode = SockSetInformation(AcceptedSocket, + AFD_INFO_BLOCKING_MODE, + &BlockMode, + NULL, + NULL); + if (ErrorCode != NO_ERROR) return ErrorCode; + } + + /* Set it internally as well */ + AcceptedSocket->SharedData.NonBlocking = Socket->SharedData.NonBlocking; + + /* Check if inlined OOB was enabled */ + if (Oob) + { + /* Set the new one like that too */ + ErrorCode = SockSetInformation(AcceptedSocket, + AFD_INFO_INLINING_MODE, + &Oob, + NULL, + NULL); + if (ErrorCode != NO_ERROR) return ErrorCode; + } + + /* Set it internally as well */ + AcceptedSocket->SharedData.OobInline = Socket->SharedData.OobInline; + + /* Update the Window Sizes */ + ErrorCode = SockUpdateWindowSizes(AcceptedSocket, FALSE); + if (ErrorCode != NO_ERROR) return ErrorCode; + + /* Check if async select was enabled */ + if (AsyncEvents) + { + /* Call WSPAsyncSelect on the accepted socket too */ + ErrorCode = SockAsyncSelectHelper(AcceptedSocket, + hWnd, + wMsg, + AsyncEvents); + } + else if (NetworkEvents) + { + /* WSPEventSelect was enabled instead, call it on the new socket */ + ErrorCode = SockEventSelectHelper(AcceptedSocket, + EventObject, + NetworkEvents); + } + + /* Check for failure */ + if (ErrorCode != NO_ERROR) return ErrorCode; + + /* Set the new context in AFD */ + ErrorCode = SockSetHandleContext(AcceptedSocket); + if (ErrorCode != NO_ERROR) return ErrorCode; + + /* Return success*/ + return NO_ERROR; +} + +SOCKET +WSPAPI +WSPAccept(SOCKET Handle, + SOCKADDR FAR * SocketAddress, + LPINT SocketAddressLength, + LPCONDITIONPROC lpfnCondition, + DWORD_PTR dwCallbackData, + LPINT lpErrno) +{ + INT ErrorCode, ReturnValue; + PSOCKET_INFORMATION Socket, AcceptedSocket = NULL; + PWINSOCK_TEB_DATA ThreadData; + CHAR AfdAcceptBuffer[32]; + PAFD_RECEIVED_ACCEPT_DATA ReceivedAcceptData = NULL; + ULONG ReceiveBufferSize; + FD_SET ReadFds; + TIMEVAL Timeout; + NTSTATUS Status; + IO_STATUS_BLOCK IoStatusBlock; + ULONG AddressBufferSize; + CHAR AddressBuffer[sizeof(SOCKADDR)]; + PVOID SockAddress; + ULONG ConnectDataSize; + PVOID ConnectData = NULL; + AFD_PENDING_ACCEPT_DATA PendingAcceptData; + INT AddressSize; + PVOID CalleeDataBuffer = NULL; + WSABUF CallerId, CalleeId, CallerData, CalleeData; + GROUP GroupId; + LPQOS Qos = NULL, GroupQos = NULL; + BOOLEAN ValidGroup = TRUE; + AFD_DEFER_ACCEPT_DATA DeferData; + ULONG BytesReturned; + SOCKET AcceptedHandle = INVALID_SOCKET; + AFD_ACCEPT_DATA AcceptData; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* Invalid for datagram sockets */ + if (MSAFD_IS_DGRAM_SOCK(Socket)) + { + /* Fail */ + ErrorCode = WSAEOPNOTSUPP; + goto error; + } + + /* Only valid if the socket is listening */ + if (!Socket->SharedData.Listening) + { + /* Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Validate address length */ + if (SocketAddressLength && + (Socket->HelperData->MinWSAddressLength > *SocketAddressLength)) + { + /* Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Calculate how much space we'll need for the Receive Buffer */ + ReceiveBufferSize = sizeof(AFD_RECEIVED_ACCEPT_DATA) + + sizeof(TRANSPORT_ADDRESS) + + Socket->HelperData->MaxTDIAddressLength; + + /* Check if our stack buffer is large enough */ + if (ReceiveBufferSize <= sizeof(AfdAcceptBuffer)) + { + /* Use the stack */ + ReceivedAcceptData = (PVOID)AfdAcceptBuffer; + } + else + { + /* Allocate from heap */ + ReceivedAcceptData = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + ReceiveBufferSize); + if (!ReceivedAcceptData) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + } + + /* If this is non-blocking, make sure there's something for us to accept */ + if (Socket->SharedData.NonBlocking) + { + /* Set up a nonblocking select */ + FD_ZERO(&ReadFds); + FD_SET(Handle, &ReadFds); + Timeout.tv_sec = 0; + Timeout.tv_usec = 0; + + /* See if there's any data */ + ReturnValue = WSPSelect(1, + &ReadFds, + NULL, + NULL, + &Timeout, + lpErrno); + if (ReturnValue == SOCKET_ERROR) + { + /* Fail */ + ErrorCode = *lpErrno; + goto error; + } + + /* Make sure we got a read back */ + if (!FD_ISSET(Handle, &ReadFds)) + { + /* Fail */ + ErrorCode = WSAEWOULDBLOCK; + goto error; + } + } + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_WAIT_FOR_LISTEN, + NULL, + 0, + ReceivedAcceptData, + ReceiveBufferSize); + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion outside the lock */ + LeaveCriticalSection(&Socket->Lock); + SockWaitForSingleObject(ThreadData->EventHandle, + Handle, + MAYBE_BLOCKING_HOOK, + NO_TIMEOUT); + EnterCriticalSection(&Socket->Lock); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* Check if we got a condition callback */ + if (lpfnCondition) + { + /* Find out how much space we'll need for the address */ + AddressBufferSize = Socket->HelperData->MaxWSAddressLength; + + /* Check if our local buffer is enough */ + if (AddressBufferSize <= sizeof(AddressBuffer)) + { + /* It is, use the stack */ + SockAddress = (PVOID)AddressBuffer; + } + else + { + /* Allocate from heap */ + SockAddress = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + AddressBufferSize); + if (!SockAddress) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + } + + /* Assume no connect data */ + ConnectDataSize = 0; + + /* Make sure we support connect data */ + if ((Socket->SharedData.ServiceFlags1 & XP1_CONNECT_DATA)) + { + /* Find out how much data is pending */ + PendingAcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber; + PendingAcceptData.ReturnSize = TRUE; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_GET_PENDING_CONNECT_DATA, + &PendingAcceptData, + sizeof(PendingAcceptData), + &PendingAcceptData, + sizeof(PendingAcceptData)); + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + SockWaitForSingleObject(ThreadData->EventHandle, + Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* How much data to allocate */ + ConnectDataSize = PtrToUlong(IoStatusBlock.Information); + if (ConnectDataSize) + { + /* Allocate needed space */ + ConnectData = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + ConnectDataSize); + if (!ConnectData) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + + /* Setup the structure to actually get the data now */ + PendingAcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber; + PendingAcceptData.ReturnSize = FALSE; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_GET_PENDING_CONNECT_DATA, + &PendingAcceptData, + sizeof(PendingAcceptData), + ConnectData, + ConnectDataSize); + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + SockWaitForSingleObject(ThreadData->EventHandle, + Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + } + } + + if ((Socket->SharedData.ServiceFlags1 & XP1_QOS_SUPPORTED)) + { + /* Set the accept data */ + AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber; + AcceptData.ListenHandle = Socket->WshContext.Handle; + + /* Save it in the TEB */ + ThreadData->AcceptData = &AcceptData; + + /* Send the IOCTL to get QOS Size */ + BytesReturned = 0; + ReturnValue = WSPIoctl(Handle, + SIO_GET_QOS, + NULL, + 0, + NULL, + 0, + &BytesReturned, + NULL, + NULL, + NULL, + &ErrorCode); + + /* Check if it failed (it should) */ + if (ReturnValue == SOCKET_ERROR) + { + /* Check if it failed because it had no buffer (it should) */ + if (ErrorCode == WSAEFAULT) + { + /* Make sure it told us how many bytes it needed */ + if (BytesReturned) + { + /* Allocate memory for it */ + Qos = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + BytesReturned); + if (!Qos) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + + /* Save the accept data and set the QoS */ + ThreadData->AcceptData = &AcceptData; + ReturnValue = WSPIoctl(Handle, + SIO_GET_QOS, + NULL, + 0, + Qos, + BytesReturned, + &BytesReturned, + NULL, + NULL, + NULL, + &ErrorCode); + } + } + else + { + /* We got some other weird, error, fail. */ + goto error; + } + } + + /* Save the accept in the TEB */ + ThreadData->AcceptData = &AcceptData; + + /* Send the IOCTL to get Group QOS Size */ + BytesReturned = 0; + ReturnValue = WSPIoctl(Handle, + SIO_GET_GROUP_QOS, + NULL, + 0, + NULL, + 0, + &BytesReturned, + NULL, + NULL, + NULL, + &ErrorCode); + + /* Check if it failed (it should) */ + if (ReturnValue == SOCKET_ERROR) + { + /* Check if it failed because it had no buffer (it should) */ + if (ErrorCode == WSAEFAULT) + { + /* Make sure it told us how many bytes it needed */ + if (BytesReturned) + { + /* Allocate memory for it */ + GroupQos = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + BytesReturned); + if (!GroupQos) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + + /* Save the accept data and set the QoS */ + ThreadData->AcceptData = &AcceptData; + ReturnValue = WSPIoctl(Handle, + SIO_GET_QOS, + NULL, + 0, + GroupQos, + BytesReturned, + &BytesReturned, + NULL, + NULL, + NULL, + &ErrorCode); + } + } + else + { + /* We got some other weird, error, fail. */ + goto error; + } + } + } + + /* Build Callee ID */ + CalleeId.buf = (PVOID)Socket->LocalAddress; + CalleeId.len = Socket->SharedData.SizeOfLocalAddress; + + /* Set up Address in SOCKADDR Format */ + SockBuildSockaddr((PSOCKADDR)SockAddress, + &AddressSize, + &ReceivedAcceptData->Address); + + /* Build Caller ID */ + CallerId.buf = (PVOID)SockAddress; + CallerId.len = AddressSize; + + /* Build Caller Data */ + CallerData.buf = ConnectData; + CallerData.len = ConnectDataSize; + + /* Check if socket supports Conditional Accept */ + if (Socket->SharedData.UseDelayedAcceptance) + { + /* Allocate Buffer for Callee Data */ + CalleeDataBuffer = SockAllocateHeapRoutine(SockPrivateHeap, 0, 4096); + if (CalleeDataBuffer) + { + /* Fill the structure */ + CalleeData.buf = CalleeDataBuffer; + CalleeData.len = 4096; + } + else + { + /* Don't fail, just don't use this... */ + CalleeData.len = 0; + } + } + else + { + /* Nothing */ + CalleeData.buf = NULL; + CalleeData.len = 0; + } + + /* Call the Condition Function */ + ReturnValue = (lpfnCondition)(&CallerId, + !CallerData.buf ? NULL : & CallerData, + NULL, + NULL, + &CalleeId, + !CalleeData.buf ? NULL: & CalleeData, + &GroupId, + dwCallbackData); + + if ((ReturnValue == CF_ACCEPT) && + (GroupId) && + (GroupId != SG_UNCONSTRAINED_GROUP) && + (GroupId != SG_CONSTRAINED_GROUP)) + { + /* Check for validity */ + ErrorCode = SockIsAddressConsistentWithConstrainedGroup(Socket, + GroupId, + SockAddress, + AddressSize); + ValidGroup = (ErrorCode == NO_ERROR); + } + + /* Check if the address was from the heap */ + if (SockAddress != AddressBuffer) + { + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, SockAddress); + } + + /* Check if it was accepted */ + if (ReturnValue == CF_ACCEPT) + { + /* Check if the group is invalid, however */ + if (!ValidGroup) goto error; + + /* Now check if QOS is supported */ + if ((Socket->SharedData.ServiceFlags1 & XP1_QOS_SUPPORTED)) + { + /* Check if we had Qos */ + if (Qos) + { + /* Set the accept data */ + AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber; + AcceptData.ListenHandle = Socket->WshContext.Handle; + + /* Save it in the TEB */ + ThreadData->AcceptData = &AcceptData; + + /* Send the IOCTL */ + BytesReturned = 0; + ReturnValue = WSPIoctl(Handle, + SIO_SET_QOS, + Qos, + sizeof(*Qos), + NULL, + 0, + &BytesReturned, + NULL, + NULL, + NULL, + &ErrorCode); + if (ReturnValue == SOCKET_ERROR) goto error; + } + + /* Check if we had Group Qos */ + if (GroupQos) + { + /* Set the accept data */ + AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber; + AcceptData.ListenHandle = Socket->WshContext.Handle; + + /* Save it in the TEB */ + ThreadData->AcceptData = &AcceptData; + + /* Send the IOCTL */ + ReturnValue = WSPIoctl(Handle, + SIO_SET_GROUP_QOS, + GroupQos, + sizeof(*GroupQos), + NULL, + 0, + &BytesReturned, + NULL, + NULL, + NULL, + &ErrorCode); + if (ReturnValue == SOCKET_ERROR) goto error; + } + } + + /* Check if delayed acceptance is used and we have callee data */ + if ((Socket->HelperData->UseDelayedAcceptance) && (CalleeData.len)) + { + /* Save the accept data in the TEB */ + ThreadData->AcceptData = &AcceptData; + + /* Set the connect data */ + ErrorCode = SockGetConnectData(Socket, + IOCTL_AFD_SET_CONNECT_DATA, + CalleeData.buf, + CalleeData.len, + NULL); + if (ErrorCode == SOCKET_ERROR) goto error; + } + } + else + { + /* Callback rejected. Build Defer Structure */ + DeferData.SequenceNumber = ReceivedAcceptData->SequenceNumber; + DeferData.RejectConnection = (ReturnValue == CF_REJECT); + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_DEFER_ACCEPT, + &DeferData, + sizeof(DeferData), + NULL, + 0); + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + if (ReturnValue == CF_REJECT) + { + /* The connection was refused */ + ErrorCode = WSAECONNREFUSED; + } + else + { + /* The connection was deferred */ + ErrorCode = WSATRY_AGAIN; + } + + /* Fail */ + goto error; + } + } + + /* Create a new Socket */ + ErrorCode = SockSocket(Socket->SharedData.AddressFamily, + Socket->SharedData.SocketType, + Socket->SharedData.Protocol, + &Socket->ProviderId, + GroupId, + Socket->SharedData.CreateFlags, + Socket->SharedData.ProviderFlags, + Socket->SharedData.ServiceFlags1, + Socket->SharedData.CatalogEntryId, + &AcceptedSocket); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + goto error; + } + + /* Set up the Accept Structure */ + AcceptData.ListenHandle = AcceptedSocket->WshContext.Handle; + AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber; + + /* Build the socket address */ + SockBuildSockaddr(AcceptedSocket->RemoteAddress, + &AcceptedSocket->SharedData.SizeOfRemoteAddress, + &ReceivedAcceptData->Address); + + /* Copy the local address */ + RtlCopyMemory(AcceptedSocket->LocalAddress, + Socket->LocalAddress, + Socket->SharedData.SizeOfLocalAddress); + AcceptedSocket->SharedData.SizeOfLocalAddress = Socket->SharedData.SizeOfLocalAddress; + + /* We can release the accepted socket's lock now */ + LeaveCriticalSection(&AcceptedSocket->Lock); + + /* Send IOCTL to Accept */ + AcceptData.UseSAN = SockSanEnabled; + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_ACCEPT, + &AcceptData, + sizeof(AcceptData), + NULL, + 0); + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion outside the lock */ + LeaveCriticalSection(&Socket->Lock); + SockWaitForSingleObject(ThreadData->EventHandle, + Handle, + MAYBE_BLOCKING_HOOK, + NO_TIMEOUT); + EnterCriticalSection(&Socket->Lock); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* Notify the helper DLL */ + ErrorCode = SockNotifyHelperDll(AcceptedSocket, WSH_NOTIFY_ACCEPT); + if (ErrorCode != NO_ERROR) goto error; + + /* If the caller sent a socket address pointer and length */ + if (SocketAddress && SocketAddressLength) + { + /* Return the address in its buffer */ + ErrorCode = SockBuildSockaddr(SocketAddress, + SocketAddressLength, + &ReceivedAcceptData->Address); + if (ErrorCode != NO_ERROR) goto error; + } + + /* Check if async select was active */ + if (SockAsyncSelectCalled) + { + /* Re-enable the regular accept event */ + SockReenableAsyncSelectEvent(Socket, FD_ACCEPT); + } + + /* Finally, do the internal core accept code */ + ErrorCode = SockCoreAccept(Socket, AcceptedSocket); + if (ErrorCode != NO_ERROR) goto error; + + /* Call WPU to tell it about the new handle */ + AcceptedHandle = SockUpcallTable->lpWPUModifyIFSHandle(AcceptedSocket->SharedData.CatalogEntryId, + (SOCKET)AcceptedSocket->WshContext.Handle, + &ErrorCode); + + /* Dereference the socket and clear its pointer for error code logic */ + SockDereferenceSocket(Socket); + Socket = NULL; + +error: + + /* Check if we have a socket here */ + if (Socket) + { + /* Check if async select was active */ + if (SockAsyncSelectCalled) + { + /* Re-enable the regular accept event */ + SockReenableAsyncSelectEvent(Socket, FD_ACCEPT); + } + + /* Unlock and dereference it */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + } + + /* Check if we got the accepted socket */ + if (AcceptedSocket) + { + /* Check if the accepted socket also has a handle */ + if (ErrorCode == NO_ERROR) + { + /* Close the socket */ + SockCloseSocket(AcceptedSocket); + } + + /* Dereference it */ + SockDereferenceSocket(AcceptedSocket); + } + + /* Check if the accept buffer was from the heap */ + if (ReceivedAcceptData && (ReceivedAcceptData != (PVOID)AfdAcceptBuffer)) + { + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, ReceivedAcceptData); + } + + /* Check if we have a connect data buffer */ + if (ConnectData) + { + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, ConnectData); + } + + /* Check if we have a callee data buffer */ + if (CalleeDataBuffer) + { + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, CalleeDataBuffer); + } + + /* Check if we have allocated QOS structures */ + if (Qos) + { + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, Qos); + } + if (GroupQos) + { + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, GroupQos); + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return INVALID_SOCKET; + } + + /* Return the new handle */ + return AcceptedHandle; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +SockCoreAccept(IN PSOCKET_INFORMATION Socket, + IN PSOCKET_INFORMATION AcceptedSocket) +{ + INT ErrorCode, ReturnValue; + BOOLEAN BlockMode = Socket->SharedData.NonBlocking; + BOOLEAN Oob = Socket->SharedData.OobInline; + INT HelperContextSize; + PVOID HelperContext = NULL; + HWND hWnd = 0; + UINT wMsg = 0; + HANDLE EventObject = NULL; + ULONG AsyncEvents = 0, NetworkEvents = 0; + CHAR HelperBuffer[256]; + + /* Set the new state */ + AcceptedSocket->SharedData.State = SocketConnected; + + /* Copy some of the settings */ + AcceptedSocket->SharedData.LingerData = Socket->SharedData.LingerData; + AcceptedSocket->SharedData.SizeOfRecvBuffer = Socket->SharedData.SizeOfRecvBuffer; + AcceptedSocket->SharedData.SizeOfSendBuffer = Socket->SharedData.SizeOfSendBuffer; + AcceptedSocket->SharedData.Broadcast = Socket->SharedData.Broadcast; + AcceptedSocket->SharedData.Debug = Socket->SharedData.Debug; + AcceptedSocket->SharedData.OobInline = Socket->SharedData.OobInline; + AcceptedSocket->SharedData.ReuseAddresses = Socket->SharedData.ReuseAddresses; + AcceptedSocket->SharedData.SendTimeout = Socket->SharedData.SendTimeout; + AcceptedSocket->SharedData.RecvTimeout = Socket->SharedData.RecvTimeout; + + /* Check if the old socket had async select */ + if (Socket->SharedData.AsyncEvents) + { + /* Copy the data while we're still under the lock */ + AsyncEvents = Socket->SharedData.AsyncEvents; + hWnd = Socket->SharedData.hWnd; + wMsg = Socket->SharedData.wMsg; + } + else if (Socket->NetworkEvents) + { + /* Copy the data while we're still under the lock */ + NetworkEvents = Socket->NetworkEvents; + EventObject = Socket->EventObject; + } + + /* Check how much space is needed for the context */ + ReturnValue = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, + Socket->Handle, + Socket->TdiAddressHandle, + Socket->TdiConnectionHandle, + SOL_INTERNAL, + SO_CONTEXT, + NULL, + &HelperContextSize); + if (ReturnValue == NO_ERROR) + { + /* Check if our stack buffer is large enough to hold it */ + if (HelperContextSize <= sizeof(HelperBuffer)) + { + /* Use it */ + HelperContext = (PVOID)HelperBuffer; + } + else + { + /* Allocate from the heap instead */ + HelperContext = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + HelperContextSize); + if (!HelperContext) + { + /* Unlock the socket and fail */ + LeaveCriticalSection(&Socket->Lock); + return WSAENOBUFS; + } + } + + /* Get the context */ + ReturnValue = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, + Socket->Handle, + Socket->TdiAddressHandle, + Socket->TdiConnectionHandle, + SOL_INTERNAL, + SO_CONTEXT, + HelperContext, + &HelperContextSize); + } + + /* We're done with the old socket, so we can release the lock */ + LeaveCriticalSection(&Socket->Lock); + + /* Get the TDI Handles for the new socket */ + ErrorCode = SockGetTdiHandles(AcceptedSocket); + + /* Check if we have the handles and the context */ + if ((ErrorCode == NO_ERROR) && (ReturnValue == NO_ERROR)) + { + /* Set the context */ + AcceptedSocket->HelperData->WSHGetSocketInformation(AcceptedSocket->HelperContext, + AcceptedSocket->Handle, + AcceptedSocket->TdiAddressHandle, + AcceptedSocket->TdiConnectionHandle, + SOL_INTERNAL, + SO_CONTEXT, + HelperContext, + &HelperContextSize); + } + + /* Check if we should free from heap */ + if (HelperContext && (HelperContext != (PVOID)HelperBuffer)) + { + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, HelperContext); + } + + /* Check if the old socket was non-blocking */ + if (BlockMode) + { + /* Set the new one like that too */ + ErrorCode = SockSetInformation(AcceptedSocket, + AFD_INFO_BLOCKING_MODE, + &BlockMode, + NULL, + NULL); + if (ErrorCode != NO_ERROR) return ErrorCode; + } + + /* Set it internally as well */ + AcceptedSocket->SharedData.NonBlocking = Socket->SharedData.NonBlocking; + + /* Check if inlined OOB was enabled */ + if (Oob) + { + /* Set the new one like that too */ + ErrorCode = SockSetInformation(AcceptedSocket, + AFD_INFO_INLINING_MODE, + &Oob, + NULL, + NULL); + if (ErrorCode != NO_ERROR) return ErrorCode; + } + + /* Set it internally as well */ + AcceptedSocket->SharedData.OobInline = Socket->SharedData.OobInline; + + /* Update the Window Sizes */ + ErrorCode = SockUpdateWindowSizes(AcceptedSocket, FALSE); + if (ErrorCode != NO_ERROR) return ErrorCode; + + /* Check if async select was enabled */ + if (AsyncEvents) + { + /* Call WSPAsyncSelect on the accepted socket too */ + ErrorCode = SockAsyncSelectHelper(AcceptedSocket, + hWnd, + wMsg, + AsyncEvents); + } + else if (NetworkEvents) + { + /* WSPEventSelect was enabled instead, call it on the new socket */ + ErrorCode = SockEventSelectHelper(AcceptedSocket, + EventObject, + NetworkEvents); + } + + /* Check for failure */ + if (ErrorCode != NO_ERROR) return ErrorCode; + + /* Set the new context in AFD */ + ErrorCode = SockSetHandleContext(AcceptedSocket); + if (ErrorCode != NO_ERROR) return ErrorCode; + + /* Return success*/ + return NO_ERROR; +} + +SOCKET +WSPAPI +WSPAccept(SOCKET Handle, + SOCKADDR FAR * SocketAddress, + LPINT SocketAddressLength, + LPCONDITIONPROC lpfnCondition, + DWORD_PTR dwCallbackData, + LPINT lpErrno) +{ + INT ErrorCode, ReturnValue; + PSOCKET_INFORMATION Socket, AcceptedSocket = NULL; + PWINSOCK_TEB_DATA ThreadData; + CHAR AfdAcceptBuffer[32]; + PAFD_RECEIVED_ACCEPT_DATA ReceivedAcceptData = NULL; + ULONG ReceiveBufferSize; + FD_SET ReadFds; + TIMEVAL Timeout; + NTSTATUS Status; + IO_STATUS_BLOCK IoStatusBlock; + ULONG AddressBufferSize; + CHAR AddressBuffer[sizeof(SOCKADDR)]; + PVOID SockAddress; + ULONG ConnectDataSize; + PVOID ConnectData = NULL; + AFD_PENDING_ACCEPT_DATA PendingAcceptData; + INT AddressSize; + PVOID CalleeDataBuffer = NULL; + WSABUF CallerId, CalleeId, CallerData, CalleeData; + GROUP GroupId; + LPQOS Qos = NULL, GroupQos = NULL; + BOOLEAN ValidGroup = TRUE; + AFD_DEFER_ACCEPT_DATA DeferData; + ULONG BytesReturned; + SOCKET AcceptedHandle = INVALID_SOCKET; + AFD_ACCEPT_DATA AcceptData; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* Invalid for datagram sockets */ + if (MSAFD_IS_DGRAM_SOCK(Socket)) + { + /* Fail */ + ErrorCode = WSAEOPNOTSUPP; + goto error; + } + + /* Only valid if the socket is listening */ + if (!Socket->SharedData.Listening) + { + /* Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Validate address length */ + if (SocketAddressLength && + (Socket->HelperData->MinWSAddressLength > *SocketAddressLength)) + { + /* Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Calculate how much space we'll need for the Receive Buffer */ + ReceiveBufferSize = sizeof(AFD_RECEIVED_ACCEPT_DATA) + + sizeof(TRANSPORT_ADDRESS) + + Socket->HelperData->MaxTDIAddressLength; + + /* Check if our stack buffer is large enough */ + if (ReceiveBufferSize <= sizeof(AfdAcceptBuffer)) + { + /* Use the stack */ + ReceivedAcceptData = (PVOID)AfdAcceptBuffer; + } + else + { + /* Allocate from heap */ + ReceivedAcceptData = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + ReceiveBufferSize); + if (!ReceivedAcceptData) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + } + + /* If this is non-blocking, make sure there's something for us to accept */ + if (Socket->SharedData.NonBlocking) + { + /* Set up a nonblocking select */ + FD_ZERO(&ReadFds); + FD_SET(Handle, &ReadFds); + Timeout.tv_sec = 0; + Timeout.tv_usec = 0; + + /* See if there's any data */ + ReturnValue = WSPSelect(1, + &ReadFds, + NULL, + NULL, + &Timeout, + lpErrno); + if (ReturnValue == SOCKET_ERROR) + { + /* Fail */ + ErrorCode = *lpErrno; + goto error; + } + + /* Make sure we got a read back */ + if (!FD_ISSET(Handle, &ReadFds)) + { + /* Fail */ + ErrorCode = WSAEWOULDBLOCK; + goto error; + } + } + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_WAIT_FOR_LISTEN, + NULL, + 0, + ReceivedAcceptData, + ReceiveBufferSize); + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion outside the lock */ + LeaveCriticalSection(&Socket->Lock); + SockWaitForSingleObject(ThreadData->EventHandle, + Handle, + MAYBE_BLOCKING_HOOK, + NO_TIMEOUT); + EnterCriticalSection(&Socket->Lock); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* Check if we got a condition callback */ + if (lpfnCondition) + { + /* Find out how much space we'll need for the address */ + AddressBufferSize = Socket->HelperData->MaxWSAddressLength; + + /* Check if our local buffer is enough */ + if (AddressBufferSize <= sizeof(AddressBuffer)) + { + /* It is, use the stack */ + SockAddress = (PVOID)AddressBuffer; + } + else + { + /* Allocate from heap */ + SockAddress = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + AddressBufferSize); + if (!SockAddress) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + } + + /* Assume no connect data */ + ConnectDataSize = 0; + + /* Make sure we support connect data */ + if ((Socket->SharedData.ServiceFlags1 & XP1_CONNECT_DATA)) + { + /* Find out how much data is pending */ + PendingAcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber; + PendingAcceptData.ReturnSize = TRUE; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_GET_PENDING_CONNECT_DATA, + &PendingAcceptData, + sizeof(PendingAcceptData), + &PendingAcceptData, + sizeof(PendingAcceptData)); + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + SockWaitForSingleObject(ThreadData->EventHandle, + Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* How much data to allocate */ + ConnectDataSize = PtrToUlong(IoStatusBlock.Information); + if (ConnectDataSize) + { + /* Allocate needed space */ + ConnectData = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + ConnectDataSize); + if (!ConnectData) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + + /* Setup the structure to actually get the data now */ + PendingAcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber; + PendingAcceptData.ReturnSize = FALSE; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_GET_PENDING_CONNECT_DATA, + &PendingAcceptData, + sizeof(PendingAcceptData), + ConnectData, + ConnectDataSize); + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + SockWaitForSingleObject(ThreadData->EventHandle, + Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + } + } + + if ((Socket->SharedData.ServiceFlags1 & XP1_QOS_SUPPORTED)) + { + /* Set the accept data */ + AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber; + AcceptData.ListenHandle = Socket->WshContext.Handle; + + /* Save it in the TEB */ + ThreadData->AcceptData = &AcceptData; + + /* Send the IOCTL to get QOS Size */ + BytesReturned = 0; + ReturnValue = WSPIoctl(Handle, + SIO_GET_QOS, + NULL, + 0, + NULL, + 0, + &BytesReturned, + NULL, + NULL, + NULL, + &ErrorCode); + + /* Check if it failed (it should) */ + if (ReturnValue == SOCKET_ERROR) + { + /* Check if it failed because it had no buffer (it should) */ + if (ErrorCode == WSAEFAULT) + { + /* Make sure it told us how many bytes it needed */ + if (BytesReturned) + { + /* Allocate memory for it */ + Qos = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + BytesReturned); + if (!Qos) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + + /* Save the accept data and set the QoS */ + ThreadData->AcceptData = &AcceptData; + ReturnValue = WSPIoctl(Handle, + SIO_GET_QOS, + NULL, + 0, + Qos, + BytesReturned, + &BytesReturned, + NULL, + NULL, + NULL, + &ErrorCode); + } + } + else + { + /* We got some other weird, error, fail. */ + goto error; + } + } + + /* Save the accept in the TEB */ + ThreadData->AcceptData = &AcceptData; + + /* Send the IOCTL to get Group QOS Size */ + BytesReturned = 0; + ReturnValue = WSPIoctl(Handle, + SIO_GET_GROUP_QOS, + NULL, + 0, + NULL, + 0, + &BytesReturned, + NULL, + NULL, + NULL, + &ErrorCode); + + /* Check if it failed (it should) */ + if (ReturnValue == SOCKET_ERROR) + { + /* Check if it failed because it had no buffer (it should) */ + if (ErrorCode == WSAEFAULT) + { + /* Make sure it told us how many bytes it needed */ + if (BytesReturned) + { + /* Allocate memory for it */ + GroupQos = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + BytesReturned); + if (!GroupQos) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + + /* Save the accept data and set the QoS */ + ThreadData->AcceptData = &AcceptData; + ReturnValue = WSPIoctl(Handle, + SIO_GET_QOS, + NULL, + 0, + GroupQos, + BytesReturned, + &BytesReturned, + NULL, + NULL, + NULL, + &ErrorCode); + } + } + else + { + /* We got some other weird, error, fail. */ + goto error; + } + } + } + + /* Build Callee ID */ + CalleeId.buf = (PVOID)Socket->LocalAddress; + CalleeId.len = Socket->SharedData.SizeOfLocalAddress; + + /* Set up Address in SOCKADDR Format */ + SockBuildSockaddr((PSOCKADDR)SockAddress, + &AddressSize, + &ReceivedAcceptData->Address); + + /* Build Caller ID */ + CallerId.buf = (PVOID)SockAddress; + CallerId.len = AddressSize; + + /* Build Caller Data */ + CallerData.buf = ConnectData; + CallerData.len = ConnectDataSize; + + /* Check if socket supports Conditional Accept */ + if (Socket->SharedData.UseDelayedAcceptance) + { + /* Allocate Buffer for Callee Data */ + CalleeDataBuffer = SockAllocateHeapRoutine(SockPrivateHeap, 0, 4096); + if (CalleeDataBuffer) + { + /* Fill the structure */ + CalleeData.buf = CalleeDataBuffer; + CalleeData.len = 4096; + } + else + { + /* Don't fail, just don't use this... */ + CalleeData.len = 0; + } + } + else + { + /* Nothing */ + CalleeData.buf = NULL; + CalleeData.len = 0; + } + + /* Call the Condition Function */ + ReturnValue = (lpfnCondition)(&CallerId, + !CallerData.buf ? NULL : & CallerData, + NULL, + NULL, + &CalleeId, + !CalleeData.buf ? NULL: & CalleeData, + &GroupId, + dwCallbackData); + + if ((ReturnValue == CF_ACCEPT) && + (GroupId) && + (GroupId != SG_UNCONSTRAINED_GROUP) && + (GroupId != SG_CONSTRAINED_GROUP)) + { + /* Check for validity */ + ErrorCode = SockIsAddressConsistentWithConstrainedGroup(Socket, + GroupId, + SockAddress, + AddressSize); + ValidGroup = (ErrorCode == NO_ERROR); + } + + /* Check if the address was from the heap */ + if (SockAddress != AddressBuffer) + { + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, SockAddress); + } + + /* Check if it was accepted */ + if (ReturnValue == CF_ACCEPT) + { + /* Check if the group is invalid, however */ + if (!ValidGroup) goto error; + + /* Now check if QOS is supported */ + if ((Socket->SharedData.ServiceFlags1 & XP1_QOS_SUPPORTED)) + { + /* Check if we had Qos */ + if (Qos) + { + /* Set the accept data */ + AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber; + AcceptData.ListenHandle = Socket->WshContext.Handle; + + /* Save it in the TEB */ + ThreadData->AcceptData = &AcceptData; + + /* Send the IOCTL */ + BytesReturned = 0; + ReturnValue = WSPIoctl(Handle, + SIO_SET_QOS, + Qos, + sizeof(*Qos), + NULL, + 0, + &BytesReturned, + NULL, + NULL, + NULL, + &ErrorCode); + if (ReturnValue == SOCKET_ERROR) goto error; + } + + /* Check if we had Group Qos */ + if (GroupQos) + { + /* Set the accept data */ + AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber; + AcceptData.ListenHandle = Socket->WshContext.Handle; + + /* Save it in the TEB */ + ThreadData->AcceptData = &AcceptData; + + /* Send the IOCTL */ + ReturnValue = WSPIoctl(Handle, + SIO_SET_GROUP_QOS, + GroupQos, + sizeof(*GroupQos), + NULL, + 0, + &BytesReturned, + NULL, + NULL, + NULL, + &ErrorCode); + if (ReturnValue == SOCKET_ERROR) goto error; + } + } + + /* Check if delayed acceptance is used and we have callee data */ + if ((Socket->HelperData->UseDelayedAcceptance) && (CalleeData.len)) + { + /* Save the accept data in the TEB */ + ThreadData->AcceptData = &AcceptData; + + /* Set the connect data */ + ErrorCode = SockGetConnectData(Socket, + IOCTL_AFD_SET_CONNECT_DATA, + CalleeData.buf, + CalleeData.len, + NULL); + if (ErrorCode == SOCKET_ERROR) goto error; + } + } + else + { + /* Callback rejected. Build Defer Structure */ + DeferData.SequenceNumber = ReceivedAcceptData->SequenceNumber; + DeferData.RejectConnection = (ReturnValue == CF_REJECT); + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_DEFER_ACCEPT, + &DeferData, + sizeof(DeferData), + NULL, + 0); + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + if (ReturnValue == CF_REJECT) + { + /* The connection was refused */ + ErrorCode = WSAECONNREFUSED; + } + else + { + /* The connection was deferred */ + ErrorCode = WSATRY_AGAIN; + } + + /* Fail */ + goto error; + } + } + + /* Create a new Socket */ + ErrorCode = SockSocket(Socket->SharedData.AddressFamily, + Socket->SharedData.SocketType, + Socket->SharedData.Protocol, + &Socket->ProviderId, + GroupId, + Socket->SharedData.CreateFlags, + Socket->SharedData.ProviderFlags, + Socket->SharedData.ServiceFlags1, + Socket->SharedData.CatalogEntryId, + &AcceptedSocket); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + goto error; + } + + /* Set up the Accept Structure */ + AcceptData.ListenHandle = AcceptedSocket->WshContext.Handle; + AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber; + + /* Build the socket address */ + SockBuildSockaddr(AcceptedSocket->RemoteAddress, + &AcceptedSocket->SharedData.SizeOfRemoteAddress, + &ReceivedAcceptData->Address); + + /* Copy the local address */ + RtlCopyMemory(AcceptedSocket->LocalAddress, + Socket->LocalAddress, + Socket->SharedData.SizeOfLocalAddress); + AcceptedSocket->SharedData.SizeOfLocalAddress = Socket->SharedData.SizeOfLocalAddress; + + /* We can release the accepted socket's lock now */ + LeaveCriticalSection(&AcceptedSocket->Lock); + + /* Send IOCTL to Accept */ + AcceptData.UseSAN = SockSanEnabled; + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_ACCEPT, + &AcceptData, + sizeof(AcceptData), + NULL, + 0); + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion outside the lock */ + LeaveCriticalSection(&Socket->Lock); + SockWaitForSingleObject(ThreadData->EventHandle, + Handle, + MAYBE_BLOCKING_HOOK, + NO_TIMEOUT); + EnterCriticalSection(&Socket->Lock); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* Notify the helper DLL */ + ErrorCode = SockNotifyHelperDll(AcceptedSocket, WSH_NOTIFY_ACCEPT); + if (ErrorCode != NO_ERROR) goto error; + + /* If the caller sent a socket address pointer and length */ + if (SocketAddress && SocketAddressLength) + { + /* Return the address in its buffer */ + ErrorCode = SockBuildSockaddr(SocketAddress, + SocketAddressLength, + &ReceivedAcceptData->Address); + if (ErrorCode != NO_ERROR) goto error; + } + + /* Check if async select was active */ + if (SockAsyncSelectCalled) + { + /* Re-enable the regular accept event */ + SockReenableAsyncSelectEvent(Socket, FD_ACCEPT); + } + + /* Finally, do the internal core accept code */ + ErrorCode = SockCoreAccept(Socket, AcceptedSocket); + if (ErrorCode != NO_ERROR) goto error; + + /* Call WPU to tell it about the new handle */ + AcceptedHandle = SockUpcallTable->lpWPUModifyIFSHandle(AcceptedSocket->SharedData.CatalogEntryId, + (SOCKET)AcceptedSocket->WshContext.Handle, + &ErrorCode); + + /* Dereference the socket and clear its pointer for error code logic */ + SockDereferenceSocket(Socket); + Socket = NULL; + +error: + + /* Check if we have a socket here */ + if (Socket) + { + /* Check if async select was active */ + if (SockAsyncSelectCalled) + { + /* Re-enable the regular accept event */ + SockReenableAsyncSelectEvent(Socket, FD_ACCEPT); + } + + /* Unlock and dereference it */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + } + + /* Check if we got the accepted socket */ + if (AcceptedSocket) + { + /* Check if the accepted socket also has a handle */ + if (ErrorCode == NO_ERROR) + { + /* Close the socket */ + SockCloseSocket(AcceptedSocket); + } + + /* Dereference it */ + SockDereferenceSocket(AcceptedSocket); + } + + /* Check if the accept buffer was from the heap */ + if (ReceivedAcceptData && (ReceivedAcceptData != (PVOID)AfdAcceptBuffer)) + { + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, ReceivedAcceptData); + } + + /* Check if we have a connect data buffer */ + if (ConnectData) + { + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, ConnectData); + } + + /* Check if we have a callee data buffer */ + if (CalleeDataBuffer) + { + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, CalleeDataBuffer); + } + + /* Check if we have allocated QOS structures */ + if (Qos) + { + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, Qos); + } + if (GroupQos) + { + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, GroupQos); + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return INVALID_SOCKET; + } + + /* Return the new handle */ + return AcceptedHandle; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +SockCoreAccept(IN PSOCKET_INFORMATION Socket, + IN PSOCKET_INFORMATION AcceptedSocket) +{ + INT ErrorCode, ReturnValue; + BOOLEAN BlockMode = Socket->SharedData.NonBlocking; + BOOLEAN Oob = Socket->SharedData.OobInline; + INT HelperContextSize; + PVOID HelperContext = NULL; + HWND hWnd = 0; + UINT wMsg = 0; + HANDLE EventObject = NULL; + ULONG AsyncEvents = 0, NetworkEvents = 0; + CHAR HelperBuffer[256]; + + /* Set the new state */ + AcceptedSocket->SharedData.State = SocketConnected; + + /* Copy some of the settings */ + AcceptedSocket->SharedData.LingerData = Socket->SharedData.LingerData; + AcceptedSocket->SharedData.SizeOfRecvBuffer = Socket->SharedData.SizeOfRecvBuffer; + AcceptedSocket->SharedData.SizeOfSendBuffer = Socket->SharedData.SizeOfSendBuffer; + AcceptedSocket->SharedData.Broadcast = Socket->SharedData.Broadcast; + AcceptedSocket->SharedData.Debug = Socket->SharedData.Debug; + AcceptedSocket->SharedData.OobInline = Socket->SharedData.OobInline; + AcceptedSocket->SharedData.ReuseAddresses = Socket->SharedData.ReuseAddresses; + AcceptedSocket->SharedData.SendTimeout = Socket->SharedData.SendTimeout; + AcceptedSocket->SharedData.RecvTimeout = Socket->SharedData.RecvTimeout; + + /* Check if the old socket had async select */ + if (Socket->SharedData.AsyncEvents) + { + /* Copy the data while we're still under the lock */ + AsyncEvents = Socket->SharedData.AsyncEvents; + hWnd = Socket->SharedData.hWnd; + wMsg = Socket->SharedData.wMsg; + } + else if (Socket->NetworkEvents) + { + /* Copy the data while we're still under the lock */ + NetworkEvents = Socket->NetworkEvents; + EventObject = Socket->EventObject; + } + + /* Check how much space is needed for the context */ + ReturnValue = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, + Socket->Handle, + Socket->TdiAddressHandle, + Socket->TdiConnectionHandle, + SOL_INTERNAL, + SO_CONTEXT, + NULL, + &HelperContextSize); + if (ReturnValue == NO_ERROR) + { + /* Check if our stack buffer is large enough to hold it */ + if (HelperContextSize <= sizeof(HelperBuffer)) + { + /* Use it */ + HelperContext = (PVOID)HelperBuffer; + } + else + { + /* Allocate from the heap instead */ + HelperContext = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + HelperContextSize); + if (!HelperContext) + { + /* Unlock the socket and fail */ + LeaveCriticalSection(&Socket->Lock); + return WSAENOBUFS; + } + } + + /* Get the context */ + ReturnValue = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, + Socket->Handle, + Socket->TdiAddressHandle, + Socket->TdiConnectionHandle, + SOL_INTERNAL, + SO_CONTEXT, + HelperContext, + &HelperContextSize); + } + + /* We're done with the old socket, so we can release the lock */ + LeaveCriticalSection(&Socket->Lock); + + /* Get the TDI Handles for the new socket */ + ErrorCode = SockGetTdiHandles(AcceptedSocket); + + /* Check if we have the handles and the context */ + if ((ErrorCode == NO_ERROR) && (ReturnValue == NO_ERROR)) + { + /* Set the context */ + AcceptedSocket->HelperData->WSHGetSocketInformation(AcceptedSocket->HelperContext, + AcceptedSocket->Handle, + AcceptedSocket->TdiAddressHandle, + AcceptedSocket->TdiConnectionHandle, + SOL_INTERNAL, + SO_CONTEXT, + HelperContext, + &HelperContextSize); + } + + /* Check if we should free from heap */ + if (HelperContext && (HelperContext != (PVOID)HelperBuffer)) + { + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, HelperContext); + } + + /* Check if the old socket was non-blocking */ + if (BlockMode) + { + /* Set the new one like that too */ + ErrorCode = SockSetInformation(AcceptedSocket, + AFD_INFO_BLOCKING_MODE, + &BlockMode, + NULL, + NULL); + if (ErrorCode != NO_ERROR) return ErrorCode; + } + + /* Set it internally as well */ + AcceptedSocket->SharedData.NonBlocking = Socket->SharedData.NonBlocking; + + /* Check if inlined OOB was enabled */ + if (Oob) + { + /* Set the new one like that too */ + ErrorCode = SockSetInformation(AcceptedSocket, + AFD_INFO_INLINING_MODE, + &Oob, + NULL, + NULL); + if (ErrorCode != NO_ERROR) return ErrorCode; + } + + /* Set it internally as well */ + AcceptedSocket->SharedData.OobInline = Socket->SharedData.OobInline; + + /* Update the Window Sizes */ + ErrorCode = SockUpdateWindowSizes(AcceptedSocket, FALSE); + if (ErrorCode != NO_ERROR) return ErrorCode; + + /* Check if async select was enabled */ + if (AsyncEvents) + { + /* Call WSPAsyncSelect on the accepted socket too */ + ErrorCode = SockAsyncSelectHelper(AcceptedSocket, + hWnd, + wMsg, + AsyncEvents); + } + else if (NetworkEvents) + { + /* WSPEventSelect was enabled instead, call it on the new socket */ + ErrorCode = SockEventSelectHelper(AcceptedSocket, + EventObject, + NetworkEvents); + } + + /* Check for failure */ + if (ErrorCode != NO_ERROR) return ErrorCode; + + /* Set the new context in AFD */ + ErrorCode = SockSetHandleContext(AcceptedSocket); + if (ErrorCode != NO_ERROR) return ErrorCode; + + /* Return success*/ + return NO_ERROR; +} + +SOCKET +WSPAPI +WSPAccept(SOCKET Handle, + SOCKADDR FAR * SocketAddress, + LPINT SocketAddressLength, + LPCONDITIONPROC lpfnCondition, + DWORD_PTR dwCallbackData, + LPINT lpErrno) +{ + INT ErrorCode, ReturnValue; + PSOCKET_INFORMATION Socket, AcceptedSocket = NULL; + PWINSOCK_TEB_DATA ThreadData; + CHAR AfdAcceptBuffer[32]; + PAFD_RECEIVED_ACCEPT_DATA ReceivedAcceptData = NULL; + ULONG ReceiveBufferSize; + FD_SET ReadFds; + TIMEVAL Timeout; + NTSTATUS Status; + IO_STATUS_BLOCK IoStatusBlock; + ULONG AddressBufferSize; + CHAR AddressBuffer[sizeof(SOCKADDR)]; + PVOID SockAddress; + ULONG ConnectDataSize; + PVOID ConnectData = NULL; + AFD_PENDING_ACCEPT_DATA PendingAcceptData; + INT AddressSize; + PVOID CalleeDataBuffer = NULL; + WSABUF CallerId, CalleeId, CallerData, CalleeData; + GROUP GroupId; + LPQOS Qos = NULL, GroupQos = NULL; + BOOLEAN ValidGroup = TRUE; + AFD_DEFER_ACCEPT_DATA DeferData; + ULONG BytesReturned; + SOCKET AcceptedHandle = INVALID_SOCKET; + AFD_ACCEPT_DATA AcceptData; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* Invalid for datagram sockets */ + if (MSAFD_IS_DGRAM_SOCK(Socket)) + { + /* Fail */ + ErrorCode = WSAEOPNOTSUPP; + goto error; + } + + /* Only valid if the socket is listening */ + if (!Socket->SharedData.Listening) + { + /* Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Validate address length */ + if (SocketAddressLength && + (Socket->HelperData->MinWSAddressLength > *SocketAddressLength)) + { + /* Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Calculate how much space we'll need for the Receive Buffer */ + ReceiveBufferSize = sizeof(AFD_RECEIVED_ACCEPT_DATA) + + sizeof(TRANSPORT_ADDRESS) + + Socket->HelperData->MaxTDIAddressLength; + + /* Check if our stack buffer is large enough */ + if (ReceiveBufferSize <= sizeof(AfdAcceptBuffer)) + { + /* Use the stack */ + ReceivedAcceptData = (PVOID)AfdAcceptBuffer; + } + else + { + /* Allocate from heap */ + ReceivedAcceptData = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + ReceiveBufferSize); + if (!ReceivedAcceptData) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + } + + /* If this is non-blocking, make sure there's something for us to accept */ + if (Socket->SharedData.NonBlocking) + { + /* Set up a nonblocking select */ + FD_ZERO(&ReadFds); + FD_SET(Handle, &ReadFds); + Timeout.tv_sec = 0; + Timeout.tv_usec = 0; + + /* See if there's any data */ + ReturnValue = WSPSelect(1, + &ReadFds, + NULL, + NULL, + &Timeout, + lpErrno); + if (ReturnValue == SOCKET_ERROR) + { + /* Fail */ + ErrorCode = *lpErrno; + goto error; + } + + /* Make sure we got a read back */ + if (!FD_ISSET(Handle, &ReadFds)) + { + /* Fail */ + ErrorCode = WSAEWOULDBLOCK; + goto error; + } + } + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_WAIT_FOR_LISTEN, + NULL, + 0, + ReceivedAcceptData, + ReceiveBufferSize); + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion outside the lock */ + LeaveCriticalSection(&Socket->Lock); + SockWaitForSingleObject(ThreadData->EventHandle, + Handle, + MAYBE_BLOCKING_HOOK, + NO_TIMEOUT); + EnterCriticalSection(&Socket->Lock); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* Check if we got a condition callback */ + if (lpfnCondition) + { + /* Find out how much space we'll need for the address */ + AddressBufferSize = Socket->HelperData->MaxWSAddressLength; + + /* Check if our local buffer is enough */ + if (AddressBufferSize <= sizeof(AddressBuffer)) + { + /* It is, use the stack */ + SockAddress = (PVOID)AddressBuffer; + } + else + { + /* Allocate from heap */ + SockAddress = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + AddressBufferSize); + if (!SockAddress) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + } + + /* Assume no connect data */ + ConnectDataSize = 0; + + /* Make sure we support connect data */ + if ((Socket->SharedData.ServiceFlags1 & XP1_CONNECT_DATA)) + { + /* Find out how much data is pending */ + PendingAcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber; + PendingAcceptData.ReturnSize = TRUE; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_GET_PENDING_CONNECT_DATA, + &PendingAcceptData, + sizeof(PendingAcceptData), + &PendingAcceptData, + sizeof(PendingAcceptData)); + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + SockWaitForSingleObject(ThreadData->EventHandle, + Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* How much data to allocate */ + ConnectDataSize = PtrToUlong(IoStatusBlock.Information); + if (ConnectDataSize) + { + /* Allocate needed space */ + ConnectData = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + ConnectDataSize); + if (!ConnectData) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + + /* Setup the structure to actually get the data now */ + PendingAcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber; + PendingAcceptData.ReturnSize = FALSE; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_GET_PENDING_CONNECT_DATA, + &PendingAcceptData, + sizeof(PendingAcceptData), + ConnectData, + ConnectDataSize); + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + SockWaitForSingleObject(ThreadData->EventHandle, + Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + } + } + + if ((Socket->SharedData.ServiceFlags1 & XP1_QOS_SUPPORTED)) + { + /* Set the accept data */ + AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber; + AcceptData.ListenHandle = Socket->WshContext.Handle; + + /* Save it in the TEB */ + ThreadData->AcceptData = &AcceptData; + + /* Send the IOCTL to get QOS Size */ + BytesReturned = 0; + ReturnValue = WSPIoctl(Handle, + SIO_GET_QOS, + NULL, + 0, + NULL, + 0, + &BytesReturned, + NULL, + NULL, + NULL, + &ErrorCode); + + /* Check if it failed (it should) */ + if (ReturnValue == SOCKET_ERROR) + { + /* Check if it failed because it had no buffer (it should) */ + if (ErrorCode == WSAEFAULT) + { + /* Make sure it told us how many bytes it needed */ + if (BytesReturned) + { + /* Allocate memory for it */ + Qos = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + BytesReturned); + if (!Qos) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + + /* Save the accept data and set the QoS */ + ThreadData->AcceptData = &AcceptData; + ReturnValue = WSPIoctl(Handle, + SIO_GET_QOS, + NULL, + 0, + Qos, + BytesReturned, + &BytesReturned, + NULL, + NULL, + NULL, + &ErrorCode); + } + } + else + { + /* We got some other weird, error, fail. */ + goto error; + } + } + + /* Save the accept in the TEB */ + ThreadData->AcceptData = &AcceptData; + + /* Send the IOCTL to get Group QOS Size */ + BytesReturned = 0; + ReturnValue = WSPIoctl(Handle, + SIO_GET_GROUP_QOS, + NULL, + 0, + NULL, + 0, + &BytesReturned, + NULL, + NULL, + NULL, + &ErrorCode); + + /* Check if it failed (it should) */ + if (ReturnValue == SOCKET_ERROR) + { + /* Check if it failed because it had no buffer (it should) */ + if (ErrorCode == WSAEFAULT) + { + /* Make sure it told us how many bytes it needed */ + if (BytesReturned) + { + /* Allocate memory for it */ + GroupQos = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + BytesReturned); + if (!GroupQos) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + + /* Save the accept data and set the QoS */ + ThreadData->AcceptData = &AcceptData; + ReturnValue = WSPIoctl(Handle, + SIO_GET_QOS, + NULL, + 0, + GroupQos, + BytesReturned, + &BytesReturned, + NULL, + NULL, + NULL, + &ErrorCode); + } + } + else + { + /* We got some other weird, error, fail. */ + goto error; + } + } + } + + /* Build Callee ID */ + CalleeId.buf = (PVOID)Socket->LocalAddress; + CalleeId.len = Socket->SharedData.SizeOfLocalAddress; + + /* Set up Address in SOCKADDR Format */ + SockBuildSockaddr((PSOCKADDR)SockAddress, + &AddressSize, + &ReceivedAcceptData->Address); + + /* Build Caller ID */ + CallerId.buf = (PVOID)SockAddress; + CallerId.len = AddressSize; + + /* Build Caller Data */ + CallerData.buf = ConnectData; + CallerData.len = ConnectDataSize; + + /* Check if socket supports Conditional Accept */ + if (Socket->SharedData.UseDelayedAcceptance) + { + /* Allocate Buffer for Callee Data */ + CalleeDataBuffer = SockAllocateHeapRoutine(SockPrivateHeap, 0, 4096); + if (CalleeDataBuffer) + { + /* Fill the structure */ + CalleeData.buf = CalleeDataBuffer; + CalleeData.len = 4096; + } + else + { + /* Don't fail, just don't use this... */ + CalleeData.len = 0; + } + } + else + { + /* Nothing */ + CalleeData.buf = NULL; + CalleeData.len = 0; + } + + /* Call the Condition Function */ + ReturnValue = (lpfnCondition)(&CallerId, + !CallerData.buf ? NULL : & CallerData, + NULL, + NULL, + &CalleeId, + !CalleeData.buf ? NULL: & CalleeData, + &GroupId, + dwCallbackData); + + if ((ReturnValue == CF_ACCEPT) && + (GroupId) && + (GroupId != SG_UNCONSTRAINED_GROUP) && + (GroupId != SG_CONSTRAINED_GROUP)) + { + /* Check for validity */ + ErrorCode = SockIsAddressConsistentWithConstrainedGroup(Socket, + GroupId, + SockAddress, + AddressSize); + ValidGroup = (ErrorCode == NO_ERROR); + } + + /* Check if the address was from the heap */ + if (SockAddress != AddressBuffer) + { + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, SockAddress); + } + + /* Check if it was accepted */ + if (ReturnValue == CF_ACCEPT) + { + /* Check if the group is invalid, however */ + if (!ValidGroup) goto error; + + /* Now check if QOS is supported */ + if ((Socket->SharedData.ServiceFlags1 & XP1_QOS_SUPPORTED)) + { + /* Check if we had Qos */ + if (Qos) + { + /* Set the accept data */ + AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber; + AcceptData.ListenHandle = Socket->WshContext.Handle; + + /* Save it in the TEB */ + ThreadData->AcceptData = &AcceptData; + + /* Send the IOCTL */ + BytesReturned = 0; + ReturnValue = WSPIoctl(Handle, + SIO_SET_QOS, + Qos, + sizeof(*Qos), + NULL, + 0, + &BytesReturned, + NULL, + NULL, + NULL, + &ErrorCode); + if (ReturnValue == SOCKET_ERROR) goto error; + } + + /* Check if we had Group Qos */ + if (GroupQos) + { + /* Set the accept data */ + AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber; + AcceptData.ListenHandle = Socket->WshContext.Handle; + + /* Save it in the TEB */ + ThreadData->AcceptData = &AcceptData; + + /* Send the IOCTL */ + ReturnValue = WSPIoctl(Handle, + SIO_SET_GROUP_QOS, + GroupQos, + sizeof(*GroupQos), + NULL, + 0, + &BytesReturned, + NULL, + NULL, + NULL, + &ErrorCode); + if (ReturnValue == SOCKET_ERROR) goto error; + } + } + + /* Check if delayed acceptance is used and we have callee data */ + if ((Socket->HelperData->UseDelayedAcceptance) && (CalleeData.len)) + { + /* Save the accept data in the TEB */ + ThreadData->AcceptData = &AcceptData; + + /* Set the connect data */ + ErrorCode = SockGetConnectData(Socket, + IOCTL_AFD_SET_CONNECT_DATA, + CalleeData.buf, + CalleeData.len, + NULL); + if (ErrorCode == SOCKET_ERROR) goto error; + } + } + else + { + /* Callback rejected. Build Defer Structure */ + DeferData.SequenceNumber = ReceivedAcceptData->SequenceNumber; + DeferData.RejectConnection = (ReturnValue == CF_REJECT); + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_DEFER_ACCEPT, + &DeferData, + sizeof(DeferData), + NULL, + 0); + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + if (ReturnValue == CF_REJECT) + { + /* The connection was refused */ + ErrorCode = WSAECONNREFUSED; + } + else + { + /* The connection was deferred */ + ErrorCode = WSATRY_AGAIN; + } + + /* Fail */ + goto error; + } + } + + /* Create a new Socket */ + ErrorCode = SockSocket(Socket->SharedData.AddressFamily, + Socket->SharedData.SocketType, + Socket->SharedData.Protocol, + &Socket->ProviderId, + GroupId, + Socket->SharedData.CreateFlags, + Socket->SharedData.ProviderFlags, + Socket->SharedData.ServiceFlags1, + Socket->SharedData.CatalogEntryId, + &AcceptedSocket); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + goto error; + } + + /* Set up the Accept Structure */ + AcceptData.ListenHandle = AcceptedSocket->WshContext.Handle; + AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber; + + /* Build the socket address */ + SockBuildSockaddr(AcceptedSocket->RemoteAddress, + &AcceptedSocket->SharedData.SizeOfRemoteAddress, + &ReceivedAcceptData->Address); + + /* Copy the local address */ + RtlCopyMemory(AcceptedSocket->LocalAddress, + Socket->LocalAddress, + Socket->SharedData.SizeOfLocalAddress); + AcceptedSocket->SharedData.SizeOfLocalAddress = Socket->SharedData.SizeOfLocalAddress; + + /* We can release the accepted socket's lock now */ + LeaveCriticalSection(&AcceptedSocket->Lock); + + /* Send IOCTL to Accept */ + AcceptData.UseSAN = SockSanEnabled; + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_ACCEPT, + &AcceptData, + sizeof(AcceptData), + NULL, + 0); + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion outside the lock */ + LeaveCriticalSection(&Socket->Lock); + SockWaitForSingleObject(ThreadData->EventHandle, + Handle, + MAYBE_BLOCKING_HOOK, + NO_TIMEOUT); + EnterCriticalSection(&Socket->Lock); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* Notify the helper DLL */ + ErrorCode = SockNotifyHelperDll(AcceptedSocket, WSH_NOTIFY_ACCEPT); + if (ErrorCode != NO_ERROR) goto error; + + /* If the caller sent a socket address pointer and length */ + if (SocketAddress && SocketAddressLength) + { + /* Return the address in its buffer */ + ErrorCode = SockBuildSockaddr(SocketAddress, + SocketAddressLength, + &ReceivedAcceptData->Address); + if (ErrorCode != NO_ERROR) goto error; + } + + /* Check if async select was active */ + if (SockAsyncSelectCalled) + { + /* Re-enable the regular accept event */ + SockReenableAsyncSelectEvent(Socket, FD_ACCEPT); + } + + /* Finally, do the internal core accept code */ + ErrorCode = SockCoreAccept(Socket, AcceptedSocket); + if (ErrorCode != NO_ERROR) goto error; + + /* Call WPU to tell it about the new handle */ + AcceptedHandle = SockUpcallTable->lpWPUModifyIFSHandle(AcceptedSocket->SharedData.CatalogEntryId, + (SOCKET)AcceptedSocket->WshContext.Handle, + &ErrorCode); + + /* Dereference the socket and clear its pointer for error code logic */ + SockDereferenceSocket(Socket); + Socket = NULL; + +error: + + /* Check if we have a socket here */ + if (Socket) + { + /* Check if async select was active */ + if (SockAsyncSelectCalled) + { + /* Re-enable the regular accept event */ + SockReenableAsyncSelectEvent(Socket, FD_ACCEPT); + } + + /* Unlock and dereference it */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + } + + /* Check if we got the accepted socket */ + if (AcceptedSocket) + { + /* Check if the accepted socket also has a handle */ + if (ErrorCode == NO_ERROR) + { + /* Close the socket */ + SockCloseSocket(AcceptedSocket); + } + + /* Dereference it */ + SockDereferenceSocket(AcceptedSocket); + } + + /* Check if the accept buffer was from the heap */ + if (ReceivedAcceptData && (ReceivedAcceptData != (PVOID)AfdAcceptBuffer)) + { + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, ReceivedAcceptData); + } + + /* Check if we have a connect data buffer */ + if (ConnectData) + { + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, ConnectData); + } + + /* Check if we have a callee data buffer */ + if (CalleeDataBuffer) + { + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, CalleeDataBuffer); + } + + /* Check if we have allocated QOS structures */ + if (Qos) + { + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, Qos); + } + if (GroupQos) + { + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, GroupQos); + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return INVALID_SOCKET; + } + + /* Return the new handle */ + return AcceptedHandle; +} + diff --git a/dll/win32/mswsock/msafd/addrconv.c b/dll/win32/mswsock/msafd/addrconv.c new file mode 100644 index 00000000000..896ccab8748 --- /dev/null +++ b/dll/win32/mswsock/msafd/addrconv.c @@ -0,0 +1,152 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +WSPAddressToString(IN LPSOCKADDR lpsaAddress, + IN DWORD dwAddressLength, + IN LPWSAPROTOCOL_INFOW lpProtocolInfo, + OUT LPWSTR lpszAddressString, + IN OUT LPDWORD lpdwAddressStringLength, + OUT LPINT lpErrno) +{ + return 0; +} + +INT +WSPAPI +WSPStringToAddress(IN LPWSTR AddressString, + IN INT AddressFamily, + IN LPWSAPROTOCOL_INFOW lpProtocolInfo, + OUT LPSOCKADDR lpAddress, + IN OUT LPINT lpAddressLength, + OUT LPINT lpErrno) +{ + return 0; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +WSPAddressToString(IN LPSOCKADDR lpsaAddress, + IN DWORD dwAddressLength, + IN LPWSAPROTOCOL_INFOW lpProtocolInfo, + OUT LPWSTR lpszAddressString, + IN OUT LPDWORD lpdwAddressStringLength, + OUT LPINT lpErrno) +{ + return 0; +} + +INT +WSPAPI +WSPStringToAddress(IN LPWSTR AddressString, + IN INT AddressFamily, + IN LPWSAPROTOCOL_INFOW lpProtocolInfo, + OUT LPSOCKADDR lpAddress, + IN OUT LPINT lpAddressLength, + OUT LPINT lpErrno) +{ + return 0; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +WSPAddressToString(IN LPSOCKADDR lpsaAddress, + IN DWORD dwAddressLength, + IN LPWSAPROTOCOL_INFOW lpProtocolInfo, + OUT LPWSTR lpszAddressString, + IN OUT LPDWORD lpdwAddressStringLength, + OUT LPINT lpErrno) +{ + return 0; +} + +INT +WSPAPI +WSPStringToAddress(IN LPWSTR AddressString, + IN INT AddressFamily, + IN LPWSAPROTOCOL_INFOW lpProtocolInfo, + OUT LPSOCKADDR lpAddress, + IN OUT LPINT lpAddressLength, + OUT LPINT lpErrno) +{ + return 0; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +WSPAddressToString(IN LPSOCKADDR lpsaAddress, + IN DWORD dwAddressLength, + IN LPWSAPROTOCOL_INFOW lpProtocolInfo, + OUT LPWSTR lpszAddressString, + IN OUT LPDWORD lpdwAddressStringLength, + OUT LPINT lpErrno) +{ + return 0; +} + +INT +WSPAPI +WSPStringToAddress(IN LPWSTR AddressString, + IN INT AddressFamily, + IN LPWSAPROTOCOL_INFOW lpProtocolInfo, + OUT LPSOCKADDR lpAddress, + IN OUT LPINT lpAddressLength, + OUT LPINT lpErrno) +{ + return 0; +} + diff --git a/dll/win32/mswsock/msafd/afdsan.c b/dll/win32/mswsock/msafd/afdsan.c new file mode 100644 index 00000000000..3e062e90d63 --- /dev/null +++ b/dll/win32/mswsock/msafd/afdsan.c @@ -0,0 +1,56 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + diff --git a/dll/win32/mswsock/msafd/async.c b/dll/win32/mswsock/msafd/async.c new file mode 100644 index 00000000000..1f4635f34eb --- /dev/null +++ b/dll/win32/mswsock/msafd/async.c @@ -0,0 +1,792 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +HANDLE SockAsyncQueuePort; +LONG SockAsyncThreadReferenceCount; + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +SockCreateAsyncQueuePort(VOID) +{ + NTSTATUS Status; + OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags; + + /* Create the port */ + Status = NtCreateIoCompletion(&SockAsyncQueuePort, + IO_COMPLETION_ALL_ACCESS, + NULL, + -1); + + /* Protect Handle */ + HandleFlags.ProtectFromClose = TRUE; + HandleFlags.Inherit = FALSE; + Status = NtSetInformationObject(SockAsyncQueuePort, + ObjectHandleFlagInformation, + &HandleFlags, + sizeof(HandleFlags)); + + /* Return */ + return NO_ERROR; +} + +VOID +WSPAPI +SockHandleAsyncIndication(IN PASYNC_COMPLETION_ROUTINE Callback, + IN PVOID Context, + IN PIO_STATUS_BLOCK IoStatusBlock) +{ + /* Call the completion routine */ + (*Callback)(Context, IoStatusBlock); +} + +BOOLEAN +WSPAPI +SockCheckAndReferenceAsyncThread(VOID) +{ + LONG Count; + HANDLE hAsyncThread; + DWORD AsyncThreadId; + HANDLE AsyncEvent; + NTSTATUS Status; + INT ErrorCode; + HINSTANCE hInstance; + PWINSOCK_TEB_DATA ThreadData; + + /* Loop while trying to increase the reference count */ + do + { + /* Get the count, and check if it's already been started */ + Count = SockAsyncThreadReferenceCount; + if ((Count > 0) && (InterlockedCompareExchange(&SockAsyncThreadReferenceCount, + Count + 1, + Count) == Count)) + { + /* Simply return */ + return TRUE; + } + } while (Count > 0); + + /* Acquire the lock */ + SockAcquireRwLockExclusive(&SocketGlobalLock); + + /* Check if no completion port exists already and create it */ + if (!SockAsyncQueuePort) SockCreateAsyncQueuePort(); + + /* Create an extra reference so the thread stays alive */ + ErrorCode = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, + (LPCTSTR)WSPStartup, + &hInstance); + + /* Create the Async Event */ + Status = NtCreateEvent(&AsyncEvent, + EVENT_ALL_ACCESS, + NULL, + NotificationEvent, + FALSE); + + /* Allocate the TEB Block */ + ThreadData = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(*ThreadData)); + if (!ThreadData) + { + /* Release the lock, close the event, free extra reference and fail */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + NtClose(AsyncEvent); + FreeLibrary(hInstance); + return FALSE; + } + + /* Initialize thread data */ + RtlZeroMemory(ThreadData, sizeof(*ThreadData)); + ThreadData->EventHandle = AsyncEvent; + ThreadData->SocketHandle = (SOCKET)hInstance; + + /* Create the Async Thread */ + hAsyncThread = CreateThread(NULL, + 0, + (LPTHREAD_START_ROUTINE)SockAsyncThread, + ThreadData, + 0, + &AsyncThreadId); + + /* Close the Handle */ + NtClose(hAsyncThread); + + /* Increase the Reference Count */ + InterlockedExchangeAdd(&SockAsyncThreadReferenceCount, 2); + + /* Release lock and return success */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + return TRUE; +} + +INT +WSPAPI +SockAsyncThread(PVOID Context) +{ + PVOID AsyncContext; + PASYNC_COMPLETION_ROUTINE AsyncCompletionRoutine; + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + LARGE_INTEGER Timeout; + PWINSOCK_TEB_DATA ThreadData = (PWINSOCK_TEB_DATA)Context; + HINSTANCE hInstance = (HINSTANCE)ThreadData->SocketHandle; + + /* Return the socket handle back to its unhacked value */ + ThreadData->SocketHandle = INVALID_SOCKET; + + /* Setup the Thread Data pointer */ + NtCurrentTeb()->WinSockData = ThreadData; + + /* Make the Thread Higher Priority */ + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL); + + /* Setup timeout */ + Timeout.QuadPart = Int32x32To64(300, 10000000); + + /* Do a KQUEUE/WorkItem Style Loop, thanks to IoCompletion Ports */ + do { + /* Get the next completion item */ + Status = NtRemoveIoCompletion(SockAsyncQueuePort, + (PVOID*)&AsyncCompletionRoutine, + &AsyncContext, + &IoStatusBlock, + &Timeout); + /* Check for success */ + if (NT_SUCCESS(Status)) + { + /* Check if this isn't the termination command */ + if (AsyncCompletionRoutine != (PVOID)-1) + { + /* Call the routine */ + SockHandleAsyncIndication(AsyncCompletionRoutine, + Context, + &IoStatusBlock); + } + else + { + /* We have to terminate, fake a timeout */ + Status = STATUS_TIMEOUT; + InterlockedDecrement(&SockAsyncThreadReferenceCount); + } + } + else if ((SockAsyncThreadReferenceCount > 1) && (NT_ERROR(Status))) + { + /* It Failed, sleep for a second */ + Sleep(1000); + } + } while (((Status != STATUS_TIMEOUT) && + (SockWspStartupCount > 0)) || + InterlockedCompareExchange(&SockAsyncThreadReferenceCount, 0, 1) != 1); + + /* Release the lock */ + SockReleaseRwLockShared(&SocketGlobalLock); + + /* Remove our extra reference */ + FreeLibraryAndExitThread(hInstance, NO_ERROR); +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +HANDLE SockAsyncQueuePort; +LONG SockAsyncThreadReferenceCount; + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +SockCreateAsyncQueuePort(VOID) +{ + NTSTATUS Status; + OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags; + + /* Create the port */ + Status = NtCreateIoCompletion(&SockAsyncQueuePort, + IO_COMPLETION_ALL_ACCESS, + NULL, + -1); + + /* Protect Handle */ + HandleFlags.ProtectFromClose = TRUE; + HandleFlags.Inherit = FALSE; + Status = NtSetInformationObject(SockAsyncQueuePort, + ObjectHandleFlagInformation, + &HandleFlags, + sizeof(HandleFlags)); + + /* Return */ + return NO_ERROR; +} + +VOID +WSPAPI +SockHandleAsyncIndication(IN PASYNC_COMPLETION_ROUTINE Callback, + IN PVOID Context, + IN PIO_STATUS_BLOCK IoStatusBlock) +{ + /* Call the completion routine */ + (*Callback)(Context, IoStatusBlock); +} + +BOOLEAN +WSPAPI +SockCheckAndReferenceAsyncThread(VOID) +{ + LONG Count; + HANDLE hAsyncThread; + DWORD AsyncThreadId; + HANDLE AsyncEvent; + NTSTATUS Status; + INT ErrorCode; + HINSTANCE hInstance; + PWINSOCK_TEB_DATA ThreadData; + + /* Loop while trying to increase the reference count */ + do + { + /* Get the count, and check if it's already been started */ + Count = SockAsyncThreadReferenceCount; + if ((Count > 0) && (InterlockedCompareExchange(&SockAsyncThreadReferenceCount, + Count + 1, + Count) == Count)) + { + /* Simply return */ + return TRUE; + } + } while (Count > 0); + + /* Acquire the lock */ + SockAcquireRwLockExclusive(&SocketGlobalLock); + + /* Check if no completion port exists already and create it */ + if (!SockAsyncQueuePort) SockCreateAsyncQueuePort(); + + /* Create an extra reference so the thread stays alive */ + ErrorCode = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, + (LPCTSTR)WSPStartup, + &hInstance); + + /* Create the Async Event */ + Status = NtCreateEvent(&AsyncEvent, + EVENT_ALL_ACCESS, + NULL, + NotificationEvent, + FALSE); + + /* Allocate the TEB Block */ + ThreadData = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(*ThreadData)); + if (!ThreadData) + { + /* Release the lock, close the event, free extra reference and fail */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + NtClose(AsyncEvent); + FreeLibrary(hInstance); + return FALSE; + } + + /* Initialize thread data */ + RtlZeroMemory(ThreadData, sizeof(*ThreadData)); + ThreadData->EventHandle = AsyncEvent; + ThreadData->SocketHandle = (SOCKET)hInstance; + + /* Create the Async Thread */ + hAsyncThread = CreateThread(NULL, + 0, + (LPTHREAD_START_ROUTINE)SockAsyncThread, + ThreadData, + 0, + &AsyncThreadId); + + /* Close the Handle */ + NtClose(hAsyncThread); + + /* Increase the Reference Count */ + InterlockedExchangeAdd(&SockAsyncThreadReferenceCount, 2); + + /* Release lock and return success */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + return TRUE; +} + +INT +WSPAPI +SockAsyncThread(PVOID Context) +{ + PVOID AsyncContext; + PASYNC_COMPLETION_ROUTINE AsyncCompletionRoutine; + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + LARGE_INTEGER Timeout; + PWINSOCK_TEB_DATA ThreadData = (PWINSOCK_TEB_DATA)Context; + HINSTANCE hInstance = (HINSTANCE)ThreadData->SocketHandle; + + /* Return the socket handle back to its unhacked value */ + ThreadData->SocketHandle = INVALID_SOCKET; + + /* Setup the Thread Data pointer */ + NtCurrentTeb()->WinSockData = ThreadData; + + /* Make the Thread Higher Priority */ + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL); + + /* Setup timeout */ + Timeout.QuadPart = Int32x32To64(300, 10000000); + + /* Do a KQUEUE/WorkItem Style Loop, thanks to IoCompletion Ports */ + do { + /* Get the next completion item */ + Status = NtRemoveIoCompletion(SockAsyncQueuePort, + (PVOID*)&AsyncCompletionRoutine, + &AsyncContext, + &IoStatusBlock, + &Timeout); + /* Check for success */ + if (NT_SUCCESS(Status)) + { + /* Check if this isn't the termination command */ + if (AsyncCompletionRoutine != (PVOID)-1) + { + /* Call the routine */ + SockHandleAsyncIndication(AsyncCompletionRoutine, + Context, + &IoStatusBlock); + } + else + { + /* We have to terminate, fake a timeout */ + Status = STATUS_TIMEOUT; + InterlockedDecrement(&SockAsyncThreadReferenceCount); + } + } + else if ((SockAsyncThreadReferenceCount > 1) && (NT_ERROR(Status))) + { + /* It Failed, sleep for a second */ + Sleep(1000); + } + } while (((Status != STATUS_TIMEOUT) && + (SockWspStartupCount > 0)) || + InterlockedCompareExchange(&SockAsyncThreadReferenceCount, 0, 1) != 1); + + /* Release the lock */ + SockReleaseRwLockShared(&SocketGlobalLock); + + /* Remove our extra reference */ + FreeLibraryAndExitThread(hInstance, NO_ERROR); +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +HANDLE SockAsyncQueuePort; +LONG SockAsyncThreadReferenceCount; + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +SockCreateAsyncQueuePort(VOID) +{ + NTSTATUS Status; + OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags; + + /* Create the port */ + Status = NtCreateIoCompletion(&SockAsyncQueuePort, + IO_COMPLETION_ALL_ACCESS, + NULL, + -1); + + /* Protect Handle */ + HandleFlags.ProtectFromClose = TRUE; + HandleFlags.Inherit = FALSE; + Status = NtSetInformationObject(SockAsyncQueuePort, + ObjectHandleFlagInformation, + &HandleFlags, + sizeof(HandleFlags)); + + /* Return */ + return NO_ERROR; +} + +VOID +WSPAPI +SockHandleAsyncIndication(IN PASYNC_COMPLETION_ROUTINE Callback, + IN PVOID Context, + IN PIO_STATUS_BLOCK IoStatusBlock) +{ + /* Call the completion routine */ + (*Callback)(Context, IoStatusBlock); +} + +BOOLEAN +WSPAPI +SockCheckAndReferenceAsyncThread(VOID) +{ + LONG Count; + HANDLE hAsyncThread; + DWORD AsyncThreadId; + HANDLE AsyncEvent; + NTSTATUS Status; + INT ErrorCode; + HINSTANCE hInstance; + PWINSOCK_TEB_DATA ThreadData; + + /* Loop while trying to increase the reference count */ + do + { + /* Get the count, and check if it's already been started */ + Count = SockAsyncThreadReferenceCount; + if ((Count > 0) && (InterlockedCompareExchange(&SockAsyncThreadReferenceCount, + Count + 1, + Count) == Count)) + { + /* Simply return */ + return TRUE; + } + } while (Count > 0); + + /* Acquire the lock */ + SockAcquireRwLockExclusive(&SocketGlobalLock); + + /* Check if no completion port exists already and create it */ + if (!SockAsyncQueuePort) SockCreateAsyncQueuePort(); + + /* Create an extra reference so the thread stays alive */ + ErrorCode = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, + (LPCTSTR)WSPStartup, + &hInstance); + + /* Create the Async Event */ + Status = NtCreateEvent(&AsyncEvent, + EVENT_ALL_ACCESS, + NULL, + NotificationEvent, + FALSE); + + /* Allocate the TEB Block */ + ThreadData = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(*ThreadData)); + if (!ThreadData) + { + /* Release the lock, close the event, free extra reference and fail */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + NtClose(AsyncEvent); + FreeLibrary(hInstance); + return FALSE; + } + + /* Initialize thread data */ + RtlZeroMemory(ThreadData, sizeof(*ThreadData)); + ThreadData->EventHandle = AsyncEvent; + ThreadData->SocketHandle = (SOCKET)hInstance; + + /* Create the Async Thread */ + hAsyncThread = CreateThread(NULL, + 0, + (LPTHREAD_START_ROUTINE)SockAsyncThread, + ThreadData, + 0, + &AsyncThreadId); + + /* Close the Handle */ + NtClose(hAsyncThread); + + /* Increase the Reference Count */ + InterlockedExchangeAdd(&SockAsyncThreadReferenceCount, 2); + + /* Release lock and return success */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + return TRUE; +} + +INT +WSPAPI +SockAsyncThread(PVOID Context) +{ + PVOID AsyncContext; + PASYNC_COMPLETION_ROUTINE AsyncCompletionRoutine; + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + LARGE_INTEGER Timeout; + PWINSOCK_TEB_DATA ThreadData = (PWINSOCK_TEB_DATA)Context; + HINSTANCE hInstance = (HINSTANCE)ThreadData->SocketHandle; + + /* Return the socket handle back to its unhacked value */ + ThreadData->SocketHandle = INVALID_SOCKET; + + /* Setup the Thread Data pointer */ + NtCurrentTeb()->WinSockData = ThreadData; + + /* Make the Thread Higher Priority */ + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL); + + /* Setup timeout */ + Timeout.QuadPart = Int32x32To64(300, 10000000); + + /* Do a KQUEUE/WorkItem Style Loop, thanks to IoCompletion Ports */ + do { + /* Get the next completion item */ + Status = NtRemoveIoCompletion(SockAsyncQueuePort, + (PVOID*)&AsyncCompletionRoutine, + &AsyncContext, + &IoStatusBlock, + &Timeout); + /* Check for success */ + if (NT_SUCCESS(Status)) + { + /* Check if this isn't the termination command */ + if (AsyncCompletionRoutine != (PVOID)-1) + { + /* Call the routine */ + SockHandleAsyncIndication(AsyncCompletionRoutine, + Context, + &IoStatusBlock); + } + else + { + /* We have to terminate, fake a timeout */ + Status = STATUS_TIMEOUT; + InterlockedDecrement(&SockAsyncThreadReferenceCount); + } + } + else if ((SockAsyncThreadReferenceCount > 1) && (NT_ERROR(Status))) + { + /* It Failed, sleep for a second */ + Sleep(1000); + } + } while (((Status != STATUS_TIMEOUT) && + (SockWspStartupCount > 0)) || + InterlockedCompareExchange(&SockAsyncThreadReferenceCount, 0, 1) != 1); + + /* Release the lock */ + SockReleaseRwLockShared(&SocketGlobalLock); + + /* Remove our extra reference */ + FreeLibraryAndExitThread(hInstance, NO_ERROR); +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +HANDLE SockAsyncQueuePort; +LONG SockAsyncThreadReferenceCount; + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +SockCreateAsyncQueuePort(VOID) +{ + NTSTATUS Status; + OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags; + + /* Create the port */ + Status = NtCreateIoCompletion(&SockAsyncQueuePort, + IO_COMPLETION_ALL_ACCESS, + NULL, + -1); + + /* Protect Handle */ + HandleFlags.ProtectFromClose = TRUE; + HandleFlags.Inherit = FALSE; + Status = NtSetInformationObject(SockAsyncQueuePort, + ObjectHandleFlagInformation, + &HandleFlags, + sizeof(HandleFlags)); + + /* Return */ + return NO_ERROR; +} + +VOID +WSPAPI +SockHandleAsyncIndication(IN PASYNC_COMPLETION_ROUTINE Callback, + IN PVOID Context, + IN PIO_STATUS_BLOCK IoStatusBlock) +{ + /* Call the completion routine */ + (*Callback)(Context, IoStatusBlock); +} + +BOOLEAN +WSPAPI +SockCheckAndReferenceAsyncThread(VOID) +{ + LONG Count; + HANDLE hAsyncThread; + DWORD AsyncThreadId; + HANDLE AsyncEvent; + NTSTATUS Status; + INT ErrorCode; + HINSTANCE hInstance; + PWINSOCK_TEB_DATA ThreadData; + + /* Loop while trying to increase the reference count */ + do + { + /* Get the count, and check if it's already been started */ + Count = SockAsyncThreadReferenceCount; + if ((Count > 0) && (InterlockedCompareExchange(&SockAsyncThreadReferenceCount, + Count + 1, + Count) == Count)) + { + /* Simply return */ + return TRUE; + } + } while (Count > 0); + + /* Acquire the lock */ + SockAcquireRwLockExclusive(&SocketGlobalLock); + + /* Check if no completion port exists already and create it */ + if (!SockAsyncQueuePort) SockCreateAsyncQueuePort(); + + /* Create an extra reference so the thread stays alive */ + ErrorCode = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, + (LPCTSTR)WSPStartup, + &hInstance); + + /* Create the Async Event */ + Status = NtCreateEvent(&AsyncEvent, + EVENT_ALL_ACCESS, + NULL, + NotificationEvent, + FALSE); + + /* Allocate the TEB Block */ + ThreadData = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(*ThreadData)); + if (!ThreadData) + { + /* Release the lock, close the event, free extra reference and fail */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + NtClose(AsyncEvent); + FreeLibrary(hInstance); + return FALSE; + } + + /* Initialize thread data */ + RtlZeroMemory(ThreadData, sizeof(*ThreadData)); + ThreadData->EventHandle = AsyncEvent; + ThreadData->SocketHandle = (SOCKET)hInstance; + + /* Create the Async Thread */ + hAsyncThread = CreateThread(NULL, + 0, + (LPTHREAD_START_ROUTINE)SockAsyncThread, + ThreadData, + 0, + &AsyncThreadId); + + /* Close the Handle */ + NtClose(hAsyncThread); + + /* Increase the Reference Count */ + InterlockedExchangeAdd(&SockAsyncThreadReferenceCount, 2); + + /* Release lock and return success */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + return TRUE; +} + +INT +WSPAPI +SockAsyncThread(PVOID Context) +{ + PVOID AsyncContext; + PASYNC_COMPLETION_ROUTINE AsyncCompletionRoutine; + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + LARGE_INTEGER Timeout; + PWINSOCK_TEB_DATA ThreadData = (PWINSOCK_TEB_DATA)Context; + HINSTANCE hInstance = (HINSTANCE)ThreadData->SocketHandle; + + /* Return the socket handle back to its unhacked value */ + ThreadData->SocketHandle = INVALID_SOCKET; + + /* Setup the Thread Data pointer */ + NtCurrentTeb()->WinSockData = ThreadData; + + /* Make the Thread Higher Priority */ + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL); + + /* Setup timeout */ + Timeout.QuadPart = Int32x32To64(300, 10000000); + + /* Do a KQUEUE/WorkItem Style Loop, thanks to IoCompletion Ports */ + do { + /* Get the next completion item */ + Status = NtRemoveIoCompletion(SockAsyncQueuePort, + (PVOID*)&AsyncCompletionRoutine, + &AsyncContext, + &IoStatusBlock, + &Timeout); + /* Check for success */ + if (NT_SUCCESS(Status)) + { + /* Check if this isn't the termination command */ + if (AsyncCompletionRoutine != (PVOID)-1) + { + /* Call the routine */ + SockHandleAsyncIndication(AsyncCompletionRoutine, + Context, + &IoStatusBlock); + } + else + { + /* We have to terminate, fake a timeout */ + Status = STATUS_TIMEOUT; + InterlockedDecrement(&SockAsyncThreadReferenceCount); + } + } + else if ((SockAsyncThreadReferenceCount > 1) && (NT_ERROR(Status))) + { + /* It Failed, sleep for a second */ + Sleep(1000); + } + } while (((Status != STATUS_TIMEOUT) && + (SockWspStartupCount > 0)) || + InterlockedCompareExchange(&SockAsyncThreadReferenceCount, 0, 1) != 1); + + /* Release the lock */ + SockReleaseRwLockShared(&SocketGlobalLock); + + /* Remove our extra reference */ + FreeLibraryAndExitThread(hInstance, NO_ERROR); +} + diff --git a/dll/win32/mswsock/msafd/bind.c b/dll/win32/mswsock/msafd/bind.c new file mode 100644 index 00000000000..a2325c24fce --- /dev/null +++ b/dll/win32/mswsock/msafd/bind.c @@ -0,0 +1,852 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +WSPBind(SOCKET Handle, + const SOCKADDR *SocketAddress, + INT SocketAddressLength, + LPINT lpErrno) +{ + INT ErrorCode; + IO_STATUS_BLOCK IoStatusBlock; + PAFD_BIND_DATA BindData; + PSOCKET_INFORMATION Socket; + NTSTATUS Status; + PTDI_ADDRESS_INFO TdiAddress = NULL; + SOCKADDR_INFO SocketInfo; + PWINSOCK_TEB_DATA ThreadData; + CHAR AddressBuffer[FIELD_OFFSET(TDI_ADDRESS_INFO, Address) + + MAX_TDI_ADDRESS_LENGTH]; + ULONG BindDataLength, TdiAddressLength; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* If the socket is already bound, fail */ + if (Socket->SharedData.State != SocketOpen) + { + /* Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Normalize address size */ + if (SocketAddressLength > Socket->HelperData->MaxWSAddressLength) + { + /* Don't go beyond the maximum */ + SocketAddressLength = Socket->HelperData->MaxWSAddressLength; + } + + /* Get Address Information */ + ErrorCode = Socket->HelperData->WSHGetSockaddrType((PSOCKADDR)SocketAddress, + SocketAddressLength, + &SocketInfo); + if (ErrorCode != NO_ERROR) goto error; + + /* Check how big the Bind and TDI Address Data will be */ + BindDataLength = Socket->HelperData->MaxTDIAddressLength + + FIELD_OFFSET(AFD_BIND_DATA, Address); + TdiAddressLength = Socket->HelperData->MaxTDIAddressLength + + FIELD_OFFSET(TDI_ADDRESS_INFO, Address); + + /* Check if we can fit it in the stack */ + if ((TdiAddressLength <= sizeof(AddressBuffer)) && + (BindDataLength <= sizeof(AddressBuffer))) + { + /* Use the stack */ + TdiAddress = (PVOID)AddressBuffer; + BindData = (PAFD_BIND_DATA)AddressBuffer; + } + else + { + /* Allocate from the heap */ + TdiAddress = SockAllocateHeapRoutine(SockPrivateHeap, 0, TdiAddressLength); + if (!TdiAddress) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + BindData = (PAFD_BIND_DATA)TdiAddress; + } + + /* Set the Share Type */ + if (Socket->SharedData.ExclusiveAddressUse) + { + BindData->ShareType = AFD_SHARE_EXCLUSIVE; + } + else if (SocketInfo.EndpointInfo == SockaddrEndpointInfoWildcard) + { + BindData->ShareType = AFD_SHARE_WILDCARD; + } + else if (Socket->SharedData.ReuseAddresses) + { + BindData->ShareType = AFD_SHARE_REUSE; + } + else + { + BindData->ShareType = AFD_SHARE_UNIQUE; + } + + /* Build the TDI Address */ + ErrorCode = SockBuildTdiAddress(&BindData->Address, + (PSOCKADDR)SocketAddress, + SocketAddressLength); + if (ErrorCode != NO_ERROR) goto error; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_BIND, + BindData, + BindDataLength, + TdiAddress, + TdiAddressLength); + + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion outside the lock */ + LeaveCriticalSection(&Socket->Lock); + SockWaitForSingleObject(ThreadData->EventHandle, + Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + EnterCriticalSection(&Socket->Lock); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* Save the TDI Address handle */ + Socket->TdiAddressHandle = (HANDLE)IoStatusBlock.Information; + + /* Notify the helper DLL */ + ErrorCode = SockNotifyHelperDll(Socket, WSH_NOTIFY_BIND); + if (ErrorCode != NO_ERROR) goto error; + + /* Re-create Sockaddr format */ + ErrorCode = SockBuildSockaddr(Socket->LocalAddress, + &SocketAddressLength, + &TdiAddress->Address); + if (ErrorCode != NO_ERROR) goto error; + + /* Set us as bound */ + Socket->SharedData.State = SocketBound; + + /* Send the new data to AFD */ + ErrorCode = SockSetHandleContext(Socket); + if (ErrorCode != NO_ERROR) goto error; + + /* Update the window sizes */ + ErrorCode = SockUpdateWindowSizes(Socket, FALSE); + if (ErrorCode != NO_ERROR) goto error; + +error: + /* Check if we have a socket here */ + if (Socket) + { + /* Release the lock and dereference */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + } + + /* Check if we should free the TDI address */ + if ((TdiAddress) && (TdiAddress != (PVOID)AddressBuffer)) + { + /* Free the Buffer */ + RtlFreeHeap(SockPrivateHeap, 0, TdiAddress); + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +WSPBind(SOCKET Handle, + const SOCKADDR *SocketAddress, + INT SocketAddressLength, + LPINT lpErrno) +{ + INT ErrorCode; + IO_STATUS_BLOCK IoStatusBlock; + PAFD_BIND_DATA BindData; + PSOCKET_INFORMATION Socket; + NTSTATUS Status; + PTDI_ADDRESS_INFO TdiAddress = NULL; + SOCKADDR_INFO SocketInfo; + PWINSOCK_TEB_DATA ThreadData; + CHAR AddressBuffer[FIELD_OFFSET(TDI_ADDRESS_INFO, Address) + + MAX_TDI_ADDRESS_LENGTH]; + ULONG BindDataLength, TdiAddressLength; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* If the socket is already bound, fail */ + if (Socket->SharedData.State != SocketOpen) + { + /* Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Normalize address size */ + if (SocketAddressLength > Socket->HelperData->MaxWSAddressLength) + { + /* Don't go beyond the maximum */ + SocketAddressLength = Socket->HelperData->MaxWSAddressLength; + } + + /* Get Address Information */ + ErrorCode = Socket->HelperData->WSHGetSockaddrType((PSOCKADDR)SocketAddress, + SocketAddressLength, + &SocketInfo); + if (ErrorCode != NO_ERROR) goto error; + + /* Check how big the Bind and TDI Address Data will be */ + BindDataLength = Socket->HelperData->MaxTDIAddressLength + + FIELD_OFFSET(AFD_BIND_DATA, Address); + TdiAddressLength = Socket->HelperData->MaxTDIAddressLength + + FIELD_OFFSET(TDI_ADDRESS_INFO, Address); + + /* Check if we can fit it in the stack */ + if ((TdiAddressLength <= sizeof(AddressBuffer)) && + (BindDataLength <= sizeof(AddressBuffer))) + { + /* Use the stack */ + TdiAddress = (PVOID)AddressBuffer; + BindData = (PAFD_BIND_DATA)AddressBuffer; + } + else + { + /* Allocate from the heap */ + TdiAddress = SockAllocateHeapRoutine(SockPrivateHeap, 0, TdiAddressLength); + if (!TdiAddress) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + BindData = (PAFD_BIND_DATA)TdiAddress; + } + + /* Set the Share Type */ + if (Socket->SharedData.ExclusiveAddressUse) + { + BindData->ShareType = AFD_SHARE_EXCLUSIVE; + } + else if (SocketInfo.EndpointInfo == SockaddrEndpointInfoWildcard) + { + BindData->ShareType = AFD_SHARE_WILDCARD; + } + else if (Socket->SharedData.ReuseAddresses) + { + BindData->ShareType = AFD_SHARE_REUSE; + } + else + { + BindData->ShareType = AFD_SHARE_UNIQUE; + } + + /* Build the TDI Address */ + ErrorCode = SockBuildTdiAddress(&BindData->Address, + (PSOCKADDR)SocketAddress, + SocketAddressLength); + if (ErrorCode != NO_ERROR) goto error; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_BIND, + BindData, + BindDataLength, + TdiAddress, + TdiAddressLength); + + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion outside the lock */ + LeaveCriticalSection(&Socket->Lock); + SockWaitForSingleObject(ThreadData->EventHandle, + Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + EnterCriticalSection(&Socket->Lock); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* Save the TDI Address handle */ + Socket->TdiAddressHandle = (HANDLE)IoStatusBlock.Information; + + /* Notify the helper DLL */ + ErrorCode = SockNotifyHelperDll(Socket, WSH_NOTIFY_BIND); + if (ErrorCode != NO_ERROR) goto error; + + /* Re-create Sockaddr format */ + ErrorCode = SockBuildSockaddr(Socket->LocalAddress, + &SocketAddressLength, + &TdiAddress->Address); + if (ErrorCode != NO_ERROR) goto error; + + /* Set us as bound */ + Socket->SharedData.State = SocketBound; + + /* Send the new data to AFD */ + ErrorCode = SockSetHandleContext(Socket); + if (ErrorCode != NO_ERROR) goto error; + + /* Update the window sizes */ + ErrorCode = SockUpdateWindowSizes(Socket, FALSE); + if (ErrorCode != NO_ERROR) goto error; + +error: + /* Check if we have a socket here */ + if (Socket) + { + /* Release the lock and dereference */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + } + + /* Check if we should free the TDI address */ + if ((TdiAddress) && (TdiAddress != (PVOID)AddressBuffer)) + { + /* Free the Buffer */ + RtlFreeHeap(SockPrivateHeap, 0, TdiAddress); + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +WSPBind(SOCKET Handle, + const SOCKADDR *SocketAddress, + INT SocketAddressLength, + LPINT lpErrno) +{ + INT ErrorCode; + IO_STATUS_BLOCK IoStatusBlock; + PAFD_BIND_DATA BindData; + PSOCKET_INFORMATION Socket; + NTSTATUS Status; + PTDI_ADDRESS_INFO TdiAddress = NULL; + SOCKADDR_INFO SocketInfo; + PWINSOCK_TEB_DATA ThreadData; + CHAR AddressBuffer[FIELD_OFFSET(TDI_ADDRESS_INFO, Address) + + MAX_TDI_ADDRESS_LENGTH]; + ULONG BindDataLength, TdiAddressLength; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* If the socket is already bound, fail */ + if (Socket->SharedData.State != SocketOpen) + { + /* Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Normalize address size */ + if (SocketAddressLength > Socket->HelperData->MaxWSAddressLength) + { + /* Don't go beyond the maximum */ + SocketAddressLength = Socket->HelperData->MaxWSAddressLength; + } + + /* Get Address Information */ + ErrorCode = Socket->HelperData->WSHGetSockaddrType((PSOCKADDR)SocketAddress, + SocketAddressLength, + &SocketInfo); + if (ErrorCode != NO_ERROR) goto error; + + /* Check how big the Bind and TDI Address Data will be */ + BindDataLength = Socket->HelperData->MaxTDIAddressLength + + FIELD_OFFSET(AFD_BIND_DATA, Address); + TdiAddressLength = Socket->HelperData->MaxTDIAddressLength + + FIELD_OFFSET(TDI_ADDRESS_INFO, Address); + + /* Check if we can fit it in the stack */ + if ((TdiAddressLength <= sizeof(AddressBuffer)) && + (BindDataLength <= sizeof(AddressBuffer))) + { + /* Use the stack */ + TdiAddress = (PVOID)AddressBuffer; + BindData = (PAFD_BIND_DATA)AddressBuffer; + } + else + { + /* Allocate from the heap */ + TdiAddress = SockAllocateHeapRoutine(SockPrivateHeap, 0, TdiAddressLength); + if (!TdiAddress) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + BindData = (PAFD_BIND_DATA)TdiAddress; + } + + /* Set the Share Type */ + if (Socket->SharedData.ExclusiveAddressUse) + { + BindData->ShareType = AFD_SHARE_EXCLUSIVE; + } + else if (SocketInfo.EndpointInfo == SockaddrEndpointInfoWildcard) + { + BindData->ShareType = AFD_SHARE_WILDCARD; + } + else if (Socket->SharedData.ReuseAddresses) + { + BindData->ShareType = AFD_SHARE_REUSE; + } + else + { + BindData->ShareType = AFD_SHARE_UNIQUE; + } + + /* Build the TDI Address */ + ErrorCode = SockBuildTdiAddress(&BindData->Address, + (PSOCKADDR)SocketAddress, + SocketAddressLength); + if (ErrorCode != NO_ERROR) goto error; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_BIND, + BindData, + BindDataLength, + TdiAddress, + TdiAddressLength); + + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion outside the lock */ + LeaveCriticalSection(&Socket->Lock); + SockWaitForSingleObject(ThreadData->EventHandle, + Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + EnterCriticalSection(&Socket->Lock); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* Save the TDI Address handle */ + Socket->TdiAddressHandle = (HANDLE)IoStatusBlock.Information; + + /* Notify the helper DLL */ + ErrorCode = SockNotifyHelperDll(Socket, WSH_NOTIFY_BIND); + if (ErrorCode != NO_ERROR) goto error; + + /* Re-create Sockaddr format */ + ErrorCode = SockBuildSockaddr(Socket->LocalAddress, + &SocketAddressLength, + &TdiAddress->Address); + if (ErrorCode != NO_ERROR) goto error; + + /* Set us as bound */ + Socket->SharedData.State = SocketBound; + + /* Send the new data to AFD */ + ErrorCode = SockSetHandleContext(Socket); + if (ErrorCode != NO_ERROR) goto error; + + /* Update the window sizes */ + ErrorCode = SockUpdateWindowSizes(Socket, FALSE); + if (ErrorCode != NO_ERROR) goto error; + +error: + /* Check if we have a socket here */ + if (Socket) + { + /* Release the lock and dereference */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + } + + /* Check if we should free the TDI address */ + if ((TdiAddress) && (TdiAddress != (PVOID)AddressBuffer)) + { + /* Free the Buffer */ + RtlFreeHeap(SockPrivateHeap, 0, TdiAddress); + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +WSPBind(SOCKET Handle, + const SOCKADDR *SocketAddress, + INT SocketAddressLength, + LPINT lpErrno) +{ + INT ErrorCode; + IO_STATUS_BLOCK IoStatusBlock; + PAFD_BIND_DATA BindData; + PSOCKET_INFORMATION Socket; + NTSTATUS Status; + PTDI_ADDRESS_INFO TdiAddress = NULL; + SOCKADDR_INFO SocketInfo; + PWINSOCK_TEB_DATA ThreadData; + CHAR AddressBuffer[FIELD_OFFSET(TDI_ADDRESS_INFO, Address) + + MAX_TDI_ADDRESS_LENGTH]; + ULONG BindDataLength, TdiAddressLength; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* If the socket is already bound, fail */ + if (Socket->SharedData.State != SocketOpen) + { + /* Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Normalize address size */ + if (SocketAddressLength > Socket->HelperData->MaxWSAddressLength) + { + /* Don't go beyond the maximum */ + SocketAddressLength = Socket->HelperData->MaxWSAddressLength; + } + + /* Get Address Information */ + ErrorCode = Socket->HelperData->WSHGetSockaddrType((PSOCKADDR)SocketAddress, + SocketAddressLength, + &SocketInfo); + if (ErrorCode != NO_ERROR) goto error; + + /* Check how big the Bind and TDI Address Data will be */ + BindDataLength = Socket->HelperData->MaxTDIAddressLength + + FIELD_OFFSET(AFD_BIND_DATA, Address); + TdiAddressLength = Socket->HelperData->MaxTDIAddressLength + + FIELD_OFFSET(TDI_ADDRESS_INFO, Address); + + /* Check if we can fit it in the stack */ + if ((TdiAddressLength <= sizeof(AddressBuffer)) && + (BindDataLength <= sizeof(AddressBuffer))) + { + /* Use the stack */ + TdiAddress = (PVOID)AddressBuffer; + BindData = (PAFD_BIND_DATA)AddressBuffer; + } + else + { + /* Allocate from the heap */ + TdiAddress = SockAllocateHeapRoutine(SockPrivateHeap, 0, TdiAddressLength); + if (!TdiAddress) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + BindData = (PAFD_BIND_DATA)TdiAddress; + } + + /* Set the Share Type */ + if (Socket->SharedData.ExclusiveAddressUse) + { + BindData->ShareType = AFD_SHARE_EXCLUSIVE; + } + else if (SocketInfo.EndpointInfo == SockaddrEndpointInfoWildcard) + { + BindData->ShareType = AFD_SHARE_WILDCARD; + } + else if (Socket->SharedData.ReuseAddresses) + { + BindData->ShareType = AFD_SHARE_REUSE; + } + else + { + BindData->ShareType = AFD_SHARE_UNIQUE; + } + + /* Build the TDI Address */ + ErrorCode = SockBuildTdiAddress(&BindData->Address, + (PSOCKADDR)SocketAddress, + SocketAddressLength); + if (ErrorCode != NO_ERROR) goto error; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_BIND, + BindData, + BindDataLength, + TdiAddress, + TdiAddressLength); + + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion outside the lock */ + LeaveCriticalSection(&Socket->Lock); + SockWaitForSingleObject(ThreadData->EventHandle, + Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + EnterCriticalSection(&Socket->Lock); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* Save the TDI Address handle */ + Socket->TdiAddressHandle = (HANDLE)IoStatusBlock.Information; + + /* Notify the helper DLL */ + ErrorCode = SockNotifyHelperDll(Socket, WSH_NOTIFY_BIND); + if (ErrorCode != NO_ERROR) goto error; + + /* Re-create Sockaddr format */ + ErrorCode = SockBuildSockaddr(Socket->LocalAddress, + &SocketAddressLength, + &TdiAddress->Address); + if (ErrorCode != NO_ERROR) goto error; + + /* Set us as bound */ + Socket->SharedData.State = SocketBound; + + /* Send the new data to AFD */ + ErrorCode = SockSetHandleContext(Socket); + if (ErrorCode != NO_ERROR) goto error; + + /* Update the window sizes */ + ErrorCode = SockUpdateWindowSizes(Socket, FALSE); + if (ErrorCode != NO_ERROR) goto error; + +error: + /* Check if we have a socket here */ + if (Socket) + { + /* Release the lock and dereference */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + } + + /* Check if we should free the TDI address */ + if ((TdiAddress) && (TdiAddress != (PVOID)AddressBuffer)) + { + /* Free the Buffer */ + RtlFreeHeap(SockPrivateHeap, 0, TdiAddress); + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + diff --git a/dll/win32/mswsock/msafd/connect.c b/dll/win32/mswsock/msafd/connect.c new file mode 100644 index 00000000000..a2f0fc46750 --- /dev/null +++ b/dll/win32/mswsock/msafd/connect.c @@ -0,0 +1,2712 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +BOOLEAN +WSPAPI +IsSockaddrEqualToZero(IN const struct sockaddr* SocketAddress, + IN INT SocketAddressLength) +{ + INT i; + + for (i = 0; i < SocketAddressLength; i++) + { + /* Make sure it's 0 */ + if (*(PULONG)SocketAddress + i)return FALSE; + } + + /* All zeroes, succees! */ + return TRUE; +} + +INT +WSPAPI +UnconnectDatagramSocket(IN PSOCKET_INFORMATION Socket) +{ + NTSTATUS Status; + INT ErrorCode; + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + AFD_DISCONNECT_INFO DisconnectInfo; + IO_STATUS_BLOCK IoStatusBlock; + + /* Set up the disconnect information */ + DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(-1); + DisconnectInfo.DisconnectType = AFD_DISCONNECT_DATAGRAM; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_DISCONNECT, + &DisconnectInfo, + sizeof(DisconnectInfo), + NULL, + 0); + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion outside the lock */ + LeaveCriticalSection(&Socket->Lock); + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + EnterCriticalSection(&Socket->Lock); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Convert error code */ + ErrorCode = NtStatusToSocketError(Status); + } + else + { + /* Set us as disconnected (back to bound) */ + Socket->SharedData.State = SocketBound; + ErrorCode = NO_ERROR; + } + + /* Return to caller */ + return ErrorCode; +} + +INT +WSPAPI +SockPostProcessConnect(IN PSOCKET_INFORMATION Socket) +{ + INT ErrorCode; + + /* Notify the helper DLL */ + ErrorCode = SockNotifyHelperDll(Socket, WSH_NOTIFY_CONNECT); + if (ErrorCode != NO_ERROR) return ErrorCode; + + /* Set the new state and update the context in AFD */ + Socket->SharedData.State = SocketConnected; + ErrorCode = SockSetHandleContext(Socket); + if (ErrorCode != NO_ERROR) return ErrorCode; + + /* Update the window sizes */ + ErrorCode = SockUpdateWindowSizes(Socket, FALSE); + + /* Return to caller */ + return ErrorCode; +} + +INT +WSPAPI +SockDoConnectReal(IN PSOCKET_INFORMATION Socket, + IN const struct sockaddr *SocketAddress, + IN INT SocketAddressLength, + IN LPWSABUF lpCalleeData, + IN BOOLEAN UseSan) +{ + INT ErrorCode; + NTSTATUS Status; + DWORD ConnectDataLength; + IO_STATUS_BLOCK IoStatusBlock; + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + CHAR ConnectBuffer[FIELD_OFFSET(AFD_CONNECT_INFO, RemoteAddress) + + MAX_TDI_ADDRESS_LENGTH]; + PAFD_CONNECT_INFO ConnectInfo; + ULONG ConnectInfoLength; + + /* Check if someone is waiting for FD_CONNECT */ + if (Socket->SharedData.AsyncEvents & FD_CONNECT) + { + /* + * Disable FD_WRITE and FD_CONNECT + * The latter fixes a race condition where the FD_CONNECT is re-enabled + * at the end of this function right after the Async Thread disables it. + * This should only happen at the *next* WSPConnect + */ + Socket->SharedData.AsyncDisabledEvents |= FD_CONNECT | FD_WRITE; + } + + /* Calculate how much the connection structure will take */ + ConnectInfoLength = FIELD_OFFSET(AFD_CONNECT_INFO, RemoteAddress) + + Socket->HelperData->MaxTDIAddressLength; + + /* Check if our stack buffer is enough */ + if (ConnectInfoLength <= sizeof(ConnectBuffer)) + { + /* Use the stack */ + ConnectInfo = (PVOID)ConnectBuffer; + } + else + { + /* Allocate from heap */ + ConnectInfo = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + ConnectInfoLength); + if (!ConnectInfo) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + } + + /* Create the TDI Address */ + ErrorCode = SockBuildTdiAddress(&ConnectInfo->RemoteAddress, + (PSOCKADDR)SocketAddress, + SocketAddressLength); + if (ErrorCode != NO_ERROR) goto error; + + /* Set the SAN State */ + ConnectInfo->UseSAN = SockSanEnabled; + + /* Check if this is a non-blocking streaming socket */ + if ((Socket->SharedData.NonBlocking) && !(MSAFD_IS_DGRAM_SOCK(Socket))) + { + /* Create the Async Thread if Needed */ + if (!SockCheckAndReferenceAsyncThread()) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + + Status = 0; + } + else + { + /* Start the connect loop */ + do + { + /* Send IOCTL */ + IoStatusBlock.Status = STATUS_PENDING; + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_CONNECT, + ConnectInfo, + ConnectInfoLength, + NULL, + 0); + + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion outside the lock */ + LeaveCriticalSection(&Socket->Lock); + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + EnterCriticalSection(&Socket->Lock); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Make sure we're not closed */ + if (Socket->SharedData.State == SocketClosed) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Check if we failed */ + if (!NT_SUCCESS(Status)) + { + /* Tell the helper DLL */ + ErrorCode = SockNotifyHelperDll(Socket, WSH_NOTIFY_CONNECT_ERROR); + } + + /* Keep looping if the Helper DLL wants us to */ + } while (ErrorCode == WSATRY_AGAIN); + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* Now do post-processing */ + ErrorCode = SockPostProcessConnect(Socket); + if (ErrorCode != NO_ERROR) goto error; + + /* Check if we had callee data */ + if ((lpCalleeData) && (lpCalleeData->buf) && (lpCalleeData->len > 0)) + { + /* Set it */ + ErrorCode = SockGetConnectData(Socket, + IOCTL_AFD_SET_CONNECT_DATA_SIZE, + lpCalleeData->buf, + ConnectDataLength, + &ConnectDataLength); + if (ErrorCode == NO_ERROR) + { + /* If we didn't get any data, then assume the buffer is empty */ + if (!lpCalleeData->len) lpCalleeData->buf = NULL; + } + else + { + /* This isn't fatal, assume we didn't get anything instead */ + lpCalleeData->len = 0; + lpCalleeData->buf = NULL; + } + + /* Assume success */ + ErrorCode = NO_ERROR; + } + +error: + + /* Check if we need to free the connect info from the heap */ + if (ConnectInfo && (ConnectInfo != (PVOID)ConnectBuffer)) + { + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, ConnectInfo); + } + + /* Check if this the success path */ + if (ErrorCode == NO_ERROR) + { + /* Check if FD_WRITE is being select()ed */ + if (Socket->SharedData.AsyncEvents & FD_WRITE) + { + /* Re-enable it */ + SockReenableAsyncSelectEvent(Socket, FD_WRITE); + } + } + + /* Return the error */ + return ErrorCode; +} + +INT +WSPAPI +SockDoConnect(SOCKET Handle, + const struct sockaddr *SocketAddress, + INT SocketAddressLength, + LPWSABUF lpCallerData, + LPWSABUF lpCalleeData, + LPQOS lpSQOS, + LPQOS lpGQOS) +{ + PSOCKET_INFORMATION Socket; + SOCKADDR_INFO SocketInfo; + PSOCKADDR Sockaddr; + PWINSOCK_TEB_DATA ThreadData; + INT SockaddrLength; + INT ErrorCode, ReturnValue; + DWORD ConnectDataLength; + DWORD BytesReturned; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) return ErrorCode; + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* Make sure we're not already connected unless we are a datagram socket */ + if ((Socket->SharedData.State == SocketConnected) && + !(MSAFD_IS_DGRAM_SOCK(Socket))) + { + /* Fail */ + ErrorCode = WSAEISCONN; + goto error; + } + + /* Check if async connect was in progress */ + if (Socket->AsyncData) + { + /* We have to clean it up */ + SockIsSocketConnected(Socket); + + /* Check again */ + if (Socket->AsyncData) + { + /* Can't do anything but fail now */ + ErrorCode = WSAEALREADY; + goto error; + } + } + + /* Make sure we're either unbound, bound, or connected */ + if ((Socket->SharedData.State != SocketOpen) && + (Socket->SharedData.State != SocketBound) && + (Socket->SharedData.State != SocketConnected)) + { + /* Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Normalize the address length */ + SocketAddressLength = min(SocketAddressLength, + Socket->HelperData->MaxWSAddressLength); + + /* Also make sure it's not too small */ + if (SocketAddressLength < Socket->HelperData->MinWSAddressLength) + { + /* Fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* + * If this is a connected socket, and the address is null (0.0.0.0), + * then do a partial disconnect if this is a datagram socket. + */ + if ((Socket->SharedData.State == SocketConnected) && + (MSAFD_IS_DGRAM_SOCK(Socket)) && + (IsSockaddrEqualToZero(SocketAddress, SocketAddressLength))) + { + /* Disconnect the socket and return */ + return UnconnectDatagramSocket(Socket); + } + + /* Make sure the Address Family is valid */ + if (Socket->SharedData.AddressFamily != SocketAddress->sa_family) + { + /* Fail */ + ErrorCode = WSAEAFNOSUPPORT; + goto error; + } + + /* If this is a non-broadcast datagram socket */ + if ((MSAFD_IS_DGRAM_SOCK(Socket) && !(Socket->SharedData.Broadcast))) + { + /* Find out what kind of address this is */ + ErrorCode = Socket->HelperData->WSHGetSockaddrType((PSOCKADDR)SocketAddress, + SocketAddressLength, + &SocketInfo); + if (ErrorCode != NO_ERROR) + { + /* Find out if this is a broadcast address */ + if (SocketInfo.AddressInfo == SockaddrAddressInfoBroadcast) + { + /* Fail: SO_BROADCAST must be set first in WinSock 2.0+ */ + ErrorCode = WSAEACCES; + } + } + + /* A failure here isn't fatal */ + ErrorCode = NO_ERROR; + } + + /* Check if this is a constrained group */ + if (Socket->SharedData.GroupType == SG_CONSTRAINED_GROUP) + { + /* Validate the address and fail if it's not consistent */ + ErrorCode = SockIsAddressConsistentWithConstrainedGroup(Socket, + Socket->SharedData.GroupID, + (PSOCKADDR)SocketAddress, + SocketAddressLength); + if (ErrorCode != NO_ERROR) goto error; + } + + /* Check if this socket isn't bound yet */ + if (Socket->SharedData.State == SocketOpen) + { + /* Check if we can request the wildcard address */ + if (Socket->HelperData->WSHGetWildcardSockaddr) + { + /* Allocate a new Sockaddr */ + SockaddrLength = Socket->HelperData->MaxWSAddressLength; + Sockaddr = SockAllocateHeapRoutine(SockPrivateHeap, 0, SockaddrLength); + if (!Sockaddr) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + + /* Get the wildcard sockaddr */ + ErrorCode = Socket->HelperData->WSHGetWildcardSockaddr(Socket->HelperContext, + Sockaddr, + &SockaddrLength); + if (ErrorCode != NO_ERROR) + { + /* Free memory and fail */ + RtlFreeHeap(SockPrivateHeap, 0, Sockaddr); + goto error; + } + + /* Bind it */ + ReturnValue = WSPBind(Handle, + Sockaddr, + SockaddrLength, + &ErrorCode); + + /* Free memory */ + RtlFreeHeap(SockPrivateHeap, 0, Sockaddr); + + /* Check if we failed */ + if (ReturnValue == SOCKET_ERROR) goto error; + } + else + { + /* Unbound socket, but can't get the wildcard. Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + } + + /* Check if we have caller data */ + if ((lpCallerData) && (lpCallerData->buf) && (lpCallerData->len > 0)) + { + /* Set it */ + ConnectDataLength = lpCallerData->len; + ErrorCode = SockGetConnectData(Socket, + IOCTL_AFD_SET_CONNECT_DATA, + lpCallerData->buf, + ConnectDataLength, + &ConnectDataLength); + if (ErrorCode != NO_ERROR) goto error; + } + + /* Now check if QOS is supported */ + if ((Socket->SharedData.ServiceFlags1 & XP1_QOS_SUPPORTED)) + { + /* Check if we have QoS data */ + if (lpSQOS) + { + /* Send the IOCTL */ + ReturnValue = WSPIoctl(Handle, + SIO_SET_QOS, + lpSQOS, + sizeof(*lpSQOS), + NULL, + 0, + &BytesReturned, + NULL, + NULL, + NULL, + &ErrorCode); + if (ReturnValue == SOCKET_ERROR) goto error; + } + + /* Check if we have Group QoS data */ + if (lpGQOS) + { + /* Send the IOCTL */ + ReturnValue = WSPIoctl(Handle, + SIO_SET_QOS, + lpGQOS, + sizeof(*lpGQOS), + NULL, + 0, + &BytesReturned, + NULL, + NULL, + NULL, + &ErrorCode); + if (ReturnValue == SOCKET_ERROR) goto error; + } + } + + /* Save the address */ + RtlCopyMemory(Socket->RemoteAddress, SocketAddress, SocketAddressLength); + Socket->SharedData.SizeOfRemoteAddress = SocketAddressLength; + + /* Check if we have callee data */ + if ((lpCalleeData) && (lpCalleeData->buf) && (lpCalleeData->len > 0)) + { + /* Set it */ + ConnectDataLength = lpCalleeData->len; + ErrorCode = SockGetConnectData(Socket, + IOCTL_AFD_SET_CONNECT_DATA_SIZE, + lpCalleeData->buf, + ConnectDataLength, + &ConnectDataLength); + if (ErrorCode != NO_ERROR) goto error; + } + + /* Do the actual connect operation */ + ErrorCode = SockDoConnectReal(Socket, + SocketAddress, + SocketAddressLength, + lpCalleeData, + TRUE); + +error: + + /* Check if we had a socket yet */ + if (Socket) + { + /* Release the lock and dereference the socket */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + } + + /* Return to caller */ + return ErrorCode; +} + +INT +WSPAPI +WSPConnect(SOCKET Handle, + const struct sockaddr * SocketAddress, + INT SocketAddressLength, + LPWSABUF lpCallerData, + LPWSABUF lpCalleeData, + LPQOS lpSQOS, + LPQOS lpGQOS, + LPINT lpErrno) +{ + INT ErrorCode; + + /* Check for caller data */ + if (lpCallerData) + { + /* Validate it */ + if ((IsBadReadPtr(lpCallerData, sizeof(WSABUF))) || + (IsBadReadPtr(lpCallerData->buf, lpCallerData->len))) + { + /* The pointers are invalid, fail */ + ErrorCode = WSAEFAULT; + goto error; + } + } + + /* Check for callee data */ + if (lpCalleeData) + { + /* Validate it */ + if ((IsBadReadPtr(lpCalleeData, sizeof(WSABUF))) || + (IsBadReadPtr(lpCalleeData->buf, lpCalleeData->len))) + { + /* The pointers are invalid, fail */ + ErrorCode = WSAEFAULT; + goto error; + } + } + + /* Check for QoS */ + if (lpSQOS) + { + /* Validate it */ + if ((IsBadReadPtr(lpSQOS, sizeof(QOS))) || + ((lpSQOS->ProviderSpecific.buf) && + (lpSQOS->ProviderSpecific.len) && + (IsBadReadPtr(lpSQOS->ProviderSpecific.buf, + lpSQOS->ProviderSpecific.len)))) + { + /* The pointers are invalid, fail */ + ErrorCode = WSAEFAULT; + goto error; + } + } + + /* Check for Group QoS */ + if (lpGQOS) + { + /* Validate it */ + if ((IsBadReadPtr(lpGQOS, sizeof(QOS))) || + ((lpGQOS->ProviderSpecific.buf) && + (lpGQOS->ProviderSpecific.len) && + (IsBadReadPtr(lpGQOS->ProviderSpecific.buf, + lpGQOS->ProviderSpecific.len)))) + { + /* The pointers are invalid, fail */ + ErrorCode = WSAEFAULT; + goto error; + } + } + + /* Do the actual connect */ + ErrorCode = SockDoConnect(Handle, + SocketAddress, + SocketAddressLength, + lpCallerData, + lpCalleeData, + lpSQOS, + lpGQOS); + +error: + /* Check if this was an error */ + if (ErrorCode != NO_ERROR) + { + /* Return error */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +SOCKET +WSPAPI +WSPJoinLeaf(IN SOCKET s, + IN CONST SOCKADDR *name, + IN INT namelen, + IN LPWSABUF lpCallerData, + OUT LPWSABUF lpCalleeData, + IN LPQOS lpSQOS, + IN LPQOS lpGQOS, + IN DWORD dwFlags, + OUT LPINT lpErrno) +{ + return (SOCKET)0; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +BOOLEAN +WSPAPI +IsSockaddrEqualToZero(IN const struct sockaddr* SocketAddress, + IN INT SocketAddressLength) +{ + INT i; + + for (i = 0; i < SocketAddressLength; i++) + { + /* Make sure it's 0 */ + if (*(PULONG)SocketAddress + i)return FALSE; + } + + /* All zeroes, succees! */ + return TRUE; +} + +INT +WSPAPI +UnconnectDatagramSocket(IN PSOCKET_INFORMATION Socket) +{ + NTSTATUS Status; + INT ErrorCode; + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + AFD_DISCONNECT_INFO DisconnectInfo; + IO_STATUS_BLOCK IoStatusBlock; + + /* Set up the disconnect information */ + DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(-1); + DisconnectInfo.DisconnectType = AFD_DISCONNECT_DATAGRAM; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_DISCONNECT, + &DisconnectInfo, + sizeof(DisconnectInfo), + NULL, + 0); + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion outside the lock */ + LeaveCriticalSection(&Socket->Lock); + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + EnterCriticalSection(&Socket->Lock); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Convert error code */ + ErrorCode = NtStatusToSocketError(Status); + } + else + { + /* Set us as disconnected (back to bound) */ + Socket->SharedData.State = SocketBound; + ErrorCode = NO_ERROR; + } + + /* Return to caller */ + return ErrorCode; +} + +INT +WSPAPI +SockPostProcessConnect(IN PSOCKET_INFORMATION Socket) +{ + INT ErrorCode; + + /* Notify the helper DLL */ + ErrorCode = SockNotifyHelperDll(Socket, WSH_NOTIFY_CONNECT); + if (ErrorCode != NO_ERROR) return ErrorCode; + + /* Set the new state and update the context in AFD */ + Socket->SharedData.State = SocketConnected; + ErrorCode = SockSetHandleContext(Socket); + if (ErrorCode != NO_ERROR) return ErrorCode; + + /* Update the window sizes */ + ErrorCode = SockUpdateWindowSizes(Socket, FALSE); + + /* Return to caller */ + return ErrorCode; +} + +INT +WSPAPI +SockDoConnectReal(IN PSOCKET_INFORMATION Socket, + IN const struct sockaddr *SocketAddress, + IN INT SocketAddressLength, + IN LPWSABUF lpCalleeData, + IN BOOLEAN UseSan) +{ + INT ErrorCode; + NTSTATUS Status; + DWORD ConnectDataLength; + IO_STATUS_BLOCK IoStatusBlock; + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + CHAR ConnectBuffer[FIELD_OFFSET(AFD_CONNECT_INFO, RemoteAddress) + + MAX_TDI_ADDRESS_LENGTH]; + PAFD_CONNECT_INFO ConnectInfo; + ULONG ConnectInfoLength; + + /* Check if someone is waiting for FD_CONNECT */ + if (Socket->SharedData.AsyncEvents & FD_CONNECT) + { + /* + * Disable FD_WRITE and FD_CONNECT + * The latter fixes a race condition where the FD_CONNECT is re-enabled + * at the end of this function right after the Async Thread disables it. + * This should only happen at the *next* WSPConnect + */ + Socket->SharedData.AsyncDisabledEvents |= FD_CONNECT | FD_WRITE; + } + + /* Calculate how much the connection structure will take */ + ConnectInfoLength = FIELD_OFFSET(AFD_CONNECT_INFO, RemoteAddress) + + Socket->HelperData->MaxTDIAddressLength; + + /* Check if our stack buffer is enough */ + if (ConnectInfoLength <= sizeof(ConnectBuffer)) + { + /* Use the stack */ + ConnectInfo = (PVOID)ConnectBuffer; + } + else + { + /* Allocate from heap */ + ConnectInfo = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + ConnectInfoLength); + if (!ConnectInfo) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + } + + /* Create the TDI Address */ + ErrorCode = SockBuildTdiAddress(&ConnectInfo->RemoteAddress, + (PSOCKADDR)SocketAddress, + SocketAddressLength); + if (ErrorCode != NO_ERROR) goto error; + + /* Set the SAN State */ + ConnectInfo->UseSAN = SockSanEnabled; + + /* Check if this is a non-blocking streaming socket */ + if ((Socket->SharedData.NonBlocking) && !(MSAFD_IS_DGRAM_SOCK(Socket))) + { + /* Create the Async Thread if Needed */ + if (!SockCheckAndReferenceAsyncThread()) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + + Status = 0; + } + else + { + /* Start the connect loop */ + do + { + /* Send IOCTL */ + IoStatusBlock.Status = STATUS_PENDING; + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_CONNECT, + ConnectInfo, + ConnectInfoLength, + NULL, + 0); + + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion outside the lock */ + LeaveCriticalSection(&Socket->Lock); + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + EnterCriticalSection(&Socket->Lock); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Make sure we're not closed */ + if (Socket->SharedData.State == SocketClosed) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Check if we failed */ + if (!NT_SUCCESS(Status)) + { + /* Tell the helper DLL */ + ErrorCode = SockNotifyHelperDll(Socket, WSH_NOTIFY_CONNECT_ERROR); + } + + /* Keep looping if the Helper DLL wants us to */ + } while (ErrorCode == WSATRY_AGAIN); + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* Now do post-processing */ + ErrorCode = SockPostProcessConnect(Socket); + if (ErrorCode != NO_ERROR) goto error; + + /* Check if we had callee data */ + if ((lpCalleeData) && (lpCalleeData->buf) && (lpCalleeData->len > 0)) + { + /* Set it */ + ErrorCode = SockGetConnectData(Socket, + IOCTL_AFD_SET_CONNECT_DATA_SIZE, + lpCalleeData->buf, + ConnectDataLength, + &ConnectDataLength); + if (ErrorCode == NO_ERROR) + { + /* If we didn't get any data, then assume the buffer is empty */ + if (!lpCalleeData->len) lpCalleeData->buf = NULL; + } + else + { + /* This isn't fatal, assume we didn't get anything instead */ + lpCalleeData->len = 0; + lpCalleeData->buf = NULL; + } + + /* Assume success */ + ErrorCode = NO_ERROR; + } + +error: + + /* Check if we need to free the connect info from the heap */ + if (ConnectInfo && (ConnectInfo != (PVOID)ConnectBuffer)) + { + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, ConnectInfo); + } + + /* Check if this the success path */ + if (ErrorCode == NO_ERROR) + { + /* Check if FD_WRITE is being select()ed */ + if (Socket->SharedData.AsyncEvents & FD_WRITE) + { + /* Re-enable it */ + SockReenableAsyncSelectEvent(Socket, FD_WRITE); + } + } + + /* Return the error */ + return ErrorCode; +} + +INT +WSPAPI +SockDoConnect(SOCKET Handle, + const struct sockaddr *SocketAddress, + INT SocketAddressLength, + LPWSABUF lpCallerData, + LPWSABUF lpCalleeData, + LPQOS lpSQOS, + LPQOS lpGQOS) +{ + PSOCKET_INFORMATION Socket; + SOCKADDR_INFO SocketInfo; + PSOCKADDR Sockaddr; + PWINSOCK_TEB_DATA ThreadData; + INT SockaddrLength; + INT ErrorCode, ReturnValue; + DWORD ConnectDataLength; + DWORD BytesReturned; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) return ErrorCode; + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* Make sure we're not already connected unless we are a datagram socket */ + if ((Socket->SharedData.State == SocketConnected) && + !(MSAFD_IS_DGRAM_SOCK(Socket))) + { + /* Fail */ + ErrorCode = WSAEISCONN; + goto error; + } + + /* Check if async connect was in progress */ + if (Socket->AsyncData) + { + /* We have to clean it up */ + SockIsSocketConnected(Socket); + + /* Check again */ + if (Socket->AsyncData) + { + /* Can't do anything but fail now */ + ErrorCode = WSAEALREADY; + goto error; + } + } + + /* Make sure we're either unbound, bound, or connected */ + if ((Socket->SharedData.State != SocketOpen) && + (Socket->SharedData.State != SocketBound) && + (Socket->SharedData.State != SocketConnected)) + { + /* Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Normalize the address length */ + SocketAddressLength = min(SocketAddressLength, + Socket->HelperData->MaxWSAddressLength); + + /* Also make sure it's not too small */ + if (SocketAddressLength < Socket->HelperData->MinWSAddressLength) + { + /* Fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* + * If this is a connected socket, and the address is null (0.0.0.0), + * then do a partial disconnect if this is a datagram socket. + */ + if ((Socket->SharedData.State == SocketConnected) && + (MSAFD_IS_DGRAM_SOCK(Socket)) && + (IsSockaddrEqualToZero(SocketAddress, SocketAddressLength))) + { + /* Disconnect the socket and return */ + return UnconnectDatagramSocket(Socket); + } + + /* Make sure the Address Family is valid */ + if (Socket->SharedData.AddressFamily != SocketAddress->sa_family) + { + /* Fail */ + ErrorCode = WSAEAFNOSUPPORT; + goto error; + } + + /* If this is a non-broadcast datagram socket */ + if ((MSAFD_IS_DGRAM_SOCK(Socket) && !(Socket->SharedData.Broadcast))) + { + /* Find out what kind of address this is */ + ErrorCode = Socket->HelperData->WSHGetSockaddrType((PSOCKADDR)SocketAddress, + SocketAddressLength, + &SocketInfo); + if (ErrorCode != NO_ERROR) + { + /* Find out if this is a broadcast address */ + if (SocketInfo.AddressInfo == SockaddrAddressInfoBroadcast) + { + /* Fail: SO_BROADCAST must be set first in WinSock 2.0+ */ + ErrorCode = WSAEACCES; + } + } + + /* A failure here isn't fatal */ + ErrorCode = NO_ERROR; + } + + /* Check if this is a constrained group */ + if (Socket->SharedData.GroupType == SG_CONSTRAINED_GROUP) + { + /* Validate the address and fail if it's not consistent */ + ErrorCode = SockIsAddressConsistentWithConstrainedGroup(Socket, + Socket->SharedData.GroupID, + (PSOCKADDR)SocketAddress, + SocketAddressLength); + if (ErrorCode != NO_ERROR) goto error; + } + + /* Check if this socket isn't bound yet */ + if (Socket->SharedData.State == SocketOpen) + { + /* Check if we can request the wildcard address */ + if (Socket->HelperData->WSHGetWildcardSockaddr) + { + /* Allocate a new Sockaddr */ + SockaddrLength = Socket->HelperData->MaxWSAddressLength; + Sockaddr = SockAllocateHeapRoutine(SockPrivateHeap, 0, SockaddrLength); + if (!Sockaddr) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + + /* Get the wildcard sockaddr */ + ErrorCode = Socket->HelperData->WSHGetWildcardSockaddr(Socket->HelperContext, + Sockaddr, + &SockaddrLength); + if (ErrorCode != NO_ERROR) + { + /* Free memory and fail */ + RtlFreeHeap(SockPrivateHeap, 0, Sockaddr); + goto error; + } + + /* Bind it */ + ReturnValue = WSPBind(Handle, + Sockaddr, + SockaddrLength, + &ErrorCode); + + /* Free memory */ + RtlFreeHeap(SockPrivateHeap, 0, Sockaddr); + + /* Check if we failed */ + if (ReturnValue == SOCKET_ERROR) goto error; + } + else + { + /* Unbound socket, but can't get the wildcard. Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + } + + /* Check if we have caller data */ + if ((lpCallerData) && (lpCallerData->buf) && (lpCallerData->len > 0)) + { + /* Set it */ + ConnectDataLength = lpCallerData->len; + ErrorCode = SockGetConnectData(Socket, + IOCTL_AFD_SET_CONNECT_DATA, + lpCallerData->buf, + ConnectDataLength, + &ConnectDataLength); + if (ErrorCode != NO_ERROR) goto error; + } + + /* Now check if QOS is supported */ + if ((Socket->SharedData.ServiceFlags1 & XP1_QOS_SUPPORTED)) + { + /* Check if we have QoS data */ + if (lpSQOS) + { + /* Send the IOCTL */ + ReturnValue = WSPIoctl(Handle, + SIO_SET_QOS, + lpSQOS, + sizeof(*lpSQOS), + NULL, + 0, + &BytesReturned, + NULL, + NULL, + NULL, + &ErrorCode); + if (ReturnValue == SOCKET_ERROR) goto error; + } + + /* Check if we have Group QoS data */ + if (lpGQOS) + { + /* Send the IOCTL */ + ReturnValue = WSPIoctl(Handle, + SIO_SET_QOS, + lpGQOS, + sizeof(*lpGQOS), + NULL, + 0, + &BytesReturned, + NULL, + NULL, + NULL, + &ErrorCode); + if (ReturnValue == SOCKET_ERROR) goto error; + } + } + + /* Save the address */ + RtlCopyMemory(Socket->RemoteAddress, SocketAddress, SocketAddressLength); + Socket->SharedData.SizeOfRemoteAddress = SocketAddressLength; + + /* Check if we have callee data */ + if ((lpCalleeData) && (lpCalleeData->buf) && (lpCalleeData->len > 0)) + { + /* Set it */ + ConnectDataLength = lpCalleeData->len; + ErrorCode = SockGetConnectData(Socket, + IOCTL_AFD_SET_CONNECT_DATA_SIZE, + lpCalleeData->buf, + ConnectDataLength, + &ConnectDataLength); + if (ErrorCode != NO_ERROR) goto error; + } + + /* Do the actual connect operation */ + ErrorCode = SockDoConnectReal(Socket, + SocketAddress, + SocketAddressLength, + lpCalleeData, + TRUE); + +error: + + /* Check if we had a socket yet */ + if (Socket) + { + /* Release the lock and dereference the socket */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + } + + /* Return to caller */ + return ErrorCode; +} + +INT +WSPAPI +WSPConnect(SOCKET Handle, + const struct sockaddr * SocketAddress, + INT SocketAddressLength, + LPWSABUF lpCallerData, + LPWSABUF lpCalleeData, + LPQOS lpSQOS, + LPQOS lpGQOS, + LPINT lpErrno) +{ + INT ErrorCode; + + /* Check for caller data */ + if (lpCallerData) + { + /* Validate it */ + if ((IsBadReadPtr(lpCallerData, sizeof(WSABUF))) || + (IsBadReadPtr(lpCallerData->buf, lpCallerData->len))) + { + /* The pointers are invalid, fail */ + ErrorCode = WSAEFAULT; + goto error; + } + } + + /* Check for callee data */ + if (lpCalleeData) + { + /* Validate it */ + if ((IsBadReadPtr(lpCalleeData, sizeof(WSABUF))) || + (IsBadReadPtr(lpCalleeData->buf, lpCalleeData->len))) + { + /* The pointers are invalid, fail */ + ErrorCode = WSAEFAULT; + goto error; + } + } + + /* Check for QoS */ + if (lpSQOS) + { + /* Validate it */ + if ((IsBadReadPtr(lpSQOS, sizeof(QOS))) || + ((lpSQOS->ProviderSpecific.buf) && + (lpSQOS->ProviderSpecific.len) && + (IsBadReadPtr(lpSQOS->ProviderSpecific.buf, + lpSQOS->ProviderSpecific.len)))) + { + /* The pointers are invalid, fail */ + ErrorCode = WSAEFAULT; + goto error; + } + } + + /* Check for Group QoS */ + if (lpGQOS) + { + /* Validate it */ + if ((IsBadReadPtr(lpGQOS, sizeof(QOS))) || + ((lpGQOS->ProviderSpecific.buf) && + (lpGQOS->ProviderSpecific.len) && + (IsBadReadPtr(lpGQOS->ProviderSpecific.buf, + lpGQOS->ProviderSpecific.len)))) + { + /* The pointers are invalid, fail */ + ErrorCode = WSAEFAULT; + goto error; + } + } + + /* Do the actual connect */ + ErrorCode = SockDoConnect(Handle, + SocketAddress, + SocketAddressLength, + lpCallerData, + lpCalleeData, + lpSQOS, + lpGQOS); + +error: + /* Check if this was an error */ + if (ErrorCode != NO_ERROR) + { + /* Return error */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +SOCKET +WSPAPI +WSPJoinLeaf(IN SOCKET s, + IN CONST SOCKADDR *name, + IN INT namelen, + IN LPWSABUF lpCallerData, + OUT LPWSABUF lpCalleeData, + IN LPQOS lpSQOS, + IN LPQOS lpGQOS, + IN DWORD dwFlags, + OUT LPINT lpErrno) +{ + return (SOCKET)0; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +BOOLEAN +WSPAPI +IsSockaddrEqualToZero(IN const struct sockaddr* SocketAddress, + IN INT SocketAddressLength) +{ + INT i; + + for (i = 0; i < SocketAddressLength; i++) + { + /* Make sure it's 0 */ + if (*(PULONG)SocketAddress + i)return FALSE; + } + + /* All zeroes, succees! */ + return TRUE; +} + +INT +WSPAPI +UnconnectDatagramSocket(IN PSOCKET_INFORMATION Socket) +{ + NTSTATUS Status; + INT ErrorCode; + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + AFD_DISCONNECT_INFO DisconnectInfo; + IO_STATUS_BLOCK IoStatusBlock; + + /* Set up the disconnect information */ + DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(-1); + DisconnectInfo.DisconnectType = AFD_DISCONNECT_DATAGRAM; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_DISCONNECT, + &DisconnectInfo, + sizeof(DisconnectInfo), + NULL, + 0); + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion outside the lock */ + LeaveCriticalSection(&Socket->Lock); + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + EnterCriticalSection(&Socket->Lock); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Convert error code */ + ErrorCode = NtStatusToSocketError(Status); + } + else + { + /* Set us as disconnected (back to bound) */ + Socket->SharedData.State = SocketBound; + ErrorCode = NO_ERROR; + } + + /* Return to caller */ + return ErrorCode; +} + +INT +WSPAPI +SockPostProcessConnect(IN PSOCKET_INFORMATION Socket) +{ + INT ErrorCode; + + /* Notify the helper DLL */ + ErrorCode = SockNotifyHelperDll(Socket, WSH_NOTIFY_CONNECT); + if (ErrorCode != NO_ERROR) return ErrorCode; + + /* Set the new state and update the context in AFD */ + Socket->SharedData.State = SocketConnected; + ErrorCode = SockSetHandleContext(Socket); + if (ErrorCode != NO_ERROR) return ErrorCode; + + /* Update the window sizes */ + ErrorCode = SockUpdateWindowSizes(Socket, FALSE); + + /* Return to caller */ + return ErrorCode; +} + +INT +WSPAPI +SockDoConnectReal(IN PSOCKET_INFORMATION Socket, + IN const struct sockaddr *SocketAddress, + IN INT SocketAddressLength, + IN LPWSABUF lpCalleeData, + IN BOOLEAN UseSan) +{ + INT ErrorCode; + NTSTATUS Status; + DWORD ConnectDataLength; + IO_STATUS_BLOCK IoStatusBlock; + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + CHAR ConnectBuffer[FIELD_OFFSET(AFD_CONNECT_INFO, RemoteAddress) + + MAX_TDI_ADDRESS_LENGTH]; + PAFD_CONNECT_INFO ConnectInfo; + ULONG ConnectInfoLength; + + /* Check if someone is waiting for FD_CONNECT */ + if (Socket->SharedData.AsyncEvents & FD_CONNECT) + { + /* + * Disable FD_WRITE and FD_CONNECT + * The latter fixes a race condition where the FD_CONNECT is re-enabled + * at the end of this function right after the Async Thread disables it. + * This should only happen at the *next* WSPConnect + */ + Socket->SharedData.AsyncDisabledEvents |= FD_CONNECT | FD_WRITE; + } + + /* Calculate how much the connection structure will take */ + ConnectInfoLength = FIELD_OFFSET(AFD_CONNECT_INFO, RemoteAddress) + + Socket->HelperData->MaxTDIAddressLength; + + /* Check if our stack buffer is enough */ + if (ConnectInfoLength <= sizeof(ConnectBuffer)) + { + /* Use the stack */ + ConnectInfo = (PVOID)ConnectBuffer; + } + else + { + /* Allocate from heap */ + ConnectInfo = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + ConnectInfoLength); + if (!ConnectInfo) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + } + + /* Create the TDI Address */ + ErrorCode = SockBuildTdiAddress(&ConnectInfo->RemoteAddress, + (PSOCKADDR)SocketAddress, + SocketAddressLength); + if (ErrorCode != NO_ERROR) goto error; + + /* Set the SAN State */ + ConnectInfo->UseSAN = SockSanEnabled; + + /* Check if this is a non-blocking streaming socket */ + if ((Socket->SharedData.NonBlocking) && !(MSAFD_IS_DGRAM_SOCK(Socket))) + { + /* Create the Async Thread if Needed */ + if (!SockCheckAndReferenceAsyncThread()) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + + Status = 0; + } + else + { + /* Start the connect loop */ + do + { + /* Send IOCTL */ + IoStatusBlock.Status = STATUS_PENDING; + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_CONNECT, + ConnectInfo, + ConnectInfoLength, + NULL, + 0); + + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion outside the lock */ + LeaveCriticalSection(&Socket->Lock); + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + EnterCriticalSection(&Socket->Lock); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Make sure we're not closed */ + if (Socket->SharedData.State == SocketClosed) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Check if we failed */ + if (!NT_SUCCESS(Status)) + { + /* Tell the helper DLL */ + ErrorCode = SockNotifyHelperDll(Socket, WSH_NOTIFY_CONNECT_ERROR); + } + + /* Keep looping if the Helper DLL wants us to */ + } while (ErrorCode == WSATRY_AGAIN); + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* Now do post-processing */ + ErrorCode = SockPostProcessConnect(Socket); + if (ErrorCode != NO_ERROR) goto error; + + /* Check if we had callee data */ + if ((lpCalleeData) && (lpCalleeData->buf) && (lpCalleeData->len > 0)) + { + /* Set it */ + ErrorCode = SockGetConnectData(Socket, + IOCTL_AFD_SET_CONNECT_DATA_SIZE, + lpCalleeData->buf, + ConnectDataLength, + &ConnectDataLength); + if (ErrorCode == NO_ERROR) + { + /* If we didn't get any data, then assume the buffer is empty */ + if (!lpCalleeData->len) lpCalleeData->buf = NULL; + } + else + { + /* This isn't fatal, assume we didn't get anything instead */ + lpCalleeData->len = 0; + lpCalleeData->buf = NULL; + } + + /* Assume success */ + ErrorCode = NO_ERROR; + } + +error: + + /* Check if we need to free the connect info from the heap */ + if (ConnectInfo && (ConnectInfo != (PVOID)ConnectBuffer)) + { + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, ConnectInfo); + } + + /* Check if this the success path */ + if (ErrorCode == NO_ERROR) + { + /* Check if FD_WRITE is being select()ed */ + if (Socket->SharedData.AsyncEvents & FD_WRITE) + { + /* Re-enable it */ + SockReenableAsyncSelectEvent(Socket, FD_WRITE); + } + } + + /* Return the error */ + return ErrorCode; +} + +INT +WSPAPI +SockDoConnect(SOCKET Handle, + const struct sockaddr *SocketAddress, + INT SocketAddressLength, + LPWSABUF lpCallerData, + LPWSABUF lpCalleeData, + LPQOS lpSQOS, + LPQOS lpGQOS) +{ + PSOCKET_INFORMATION Socket; + SOCKADDR_INFO SocketInfo; + PSOCKADDR Sockaddr; + PWINSOCK_TEB_DATA ThreadData; + INT SockaddrLength; + INT ErrorCode, ReturnValue; + DWORD ConnectDataLength; + DWORD BytesReturned; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) return ErrorCode; + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* Make sure we're not already connected unless we are a datagram socket */ + if ((Socket->SharedData.State == SocketConnected) && + !(MSAFD_IS_DGRAM_SOCK(Socket))) + { + /* Fail */ + ErrorCode = WSAEISCONN; + goto error; + } + + /* Check if async connect was in progress */ + if (Socket->AsyncData) + { + /* We have to clean it up */ + SockIsSocketConnected(Socket); + + /* Check again */ + if (Socket->AsyncData) + { + /* Can't do anything but fail now */ + ErrorCode = WSAEALREADY; + goto error; + } + } + + /* Make sure we're either unbound, bound, or connected */ + if ((Socket->SharedData.State != SocketOpen) && + (Socket->SharedData.State != SocketBound) && + (Socket->SharedData.State != SocketConnected)) + { + /* Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Normalize the address length */ + SocketAddressLength = min(SocketAddressLength, + Socket->HelperData->MaxWSAddressLength); + + /* Also make sure it's not too small */ + if (SocketAddressLength < Socket->HelperData->MinWSAddressLength) + { + /* Fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* + * If this is a connected socket, and the address is null (0.0.0.0), + * then do a partial disconnect if this is a datagram socket. + */ + if ((Socket->SharedData.State == SocketConnected) && + (MSAFD_IS_DGRAM_SOCK(Socket)) && + (IsSockaddrEqualToZero(SocketAddress, SocketAddressLength))) + { + /* Disconnect the socket and return */ + return UnconnectDatagramSocket(Socket); + } + + /* Make sure the Address Family is valid */ + if (Socket->SharedData.AddressFamily != SocketAddress->sa_family) + { + /* Fail */ + ErrorCode = WSAEAFNOSUPPORT; + goto error; + } + + /* If this is a non-broadcast datagram socket */ + if ((MSAFD_IS_DGRAM_SOCK(Socket) && !(Socket->SharedData.Broadcast))) + { + /* Find out what kind of address this is */ + ErrorCode = Socket->HelperData->WSHGetSockaddrType((PSOCKADDR)SocketAddress, + SocketAddressLength, + &SocketInfo); + if (ErrorCode != NO_ERROR) + { + /* Find out if this is a broadcast address */ + if (SocketInfo.AddressInfo == SockaddrAddressInfoBroadcast) + { + /* Fail: SO_BROADCAST must be set first in WinSock 2.0+ */ + ErrorCode = WSAEACCES; + } + } + + /* A failure here isn't fatal */ + ErrorCode = NO_ERROR; + } + + /* Check if this is a constrained group */ + if (Socket->SharedData.GroupType == SG_CONSTRAINED_GROUP) + { + /* Validate the address and fail if it's not consistent */ + ErrorCode = SockIsAddressConsistentWithConstrainedGroup(Socket, + Socket->SharedData.GroupID, + (PSOCKADDR)SocketAddress, + SocketAddressLength); + if (ErrorCode != NO_ERROR) goto error; + } + + /* Check if this socket isn't bound yet */ + if (Socket->SharedData.State == SocketOpen) + { + /* Check if we can request the wildcard address */ + if (Socket->HelperData->WSHGetWildcardSockaddr) + { + /* Allocate a new Sockaddr */ + SockaddrLength = Socket->HelperData->MaxWSAddressLength; + Sockaddr = SockAllocateHeapRoutine(SockPrivateHeap, 0, SockaddrLength); + if (!Sockaddr) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + + /* Get the wildcard sockaddr */ + ErrorCode = Socket->HelperData->WSHGetWildcardSockaddr(Socket->HelperContext, + Sockaddr, + &SockaddrLength); + if (ErrorCode != NO_ERROR) + { + /* Free memory and fail */ + RtlFreeHeap(SockPrivateHeap, 0, Sockaddr); + goto error; + } + + /* Bind it */ + ReturnValue = WSPBind(Handle, + Sockaddr, + SockaddrLength, + &ErrorCode); + + /* Free memory */ + RtlFreeHeap(SockPrivateHeap, 0, Sockaddr); + + /* Check if we failed */ + if (ReturnValue == SOCKET_ERROR) goto error; + } + else + { + /* Unbound socket, but can't get the wildcard. Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + } + + /* Check if we have caller data */ + if ((lpCallerData) && (lpCallerData->buf) && (lpCallerData->len > 0)) + { + /* Set it */ + ConnectDataLength = lpCallerData->len; + ErrorCode = SockGetConnectData(Socket, + IOCTL_AFD_SET_CONNECT_DATA, + lpCallerData->buf, + ConnectDataLength, + &ConnectDataLength); + if (ErrorCode != NO_ERROR) goto error; + } + + /* Now check if QOS is supported */ + if ((Socket->SharedData.ServiceFlags1 & XP1_QOS_SUPPORTED)) + { + /* Check if we have QoS data */ + if (lpSQOS) + { + /* Send the IOCTL */ + ReturnValue = WSPIoctl(Handle, + SIO_SET_QOS, + lpSQOS, + sizeof(*lpSQOS), + NULL, + 0, + &BytesReturned, + NULL, + NULL, + NULL, + &ErrorCode); + if (ReturnValue == SOCKET_ERROR) goto error; + } + + /* Check if we have Group QoS data */ + if (lpGQOS) + { + /* Send the IOCTL */ + ReturnValue = WSPIoctl(Handle, + SIO_SET_QOS, + lpGQOS, + sizeof(*lpGQOS), + NULL, + 0, + &BytesReturned, + NULL, + NULL, + NULL, + &ErrorCode); + if (ReturnValue == SOCKET_ERROR) goto error; + } + } + + /* Save the address */ + RtlCopyMemory(Socket->RemoteAddress, SocketAddress, SocketAddressLength); + Socket->SharedData.SizeOfRemoteAddress = SocketAddressLength; + + /* Check if we have callee data */ + if ((lpCalleeData) && (lpCalleeData->buf) && (lpCalleeData->len > 0)) + { + /* Set it */ + ConnectDataLength = lpCalleeData->len; + ErrorCode = SockGetConnectData(Socket, + IOCTL_AFD_SET_CONNECT_DATA_SIZE, + lpCalleeData->buf, + ConnectDataLength, + &ConnectDataLength); + if (ErrorCode != NO_ERROR) goto error; + } + + /* Do the actual connect operation */ + ErrorCode = SockDoConnectReal(Socket, + SocketAddress, + SocketAddressLength, + lpCalleeData, + TRUE); + +error: + + /* Check if we had a socket yet */ + if (Socket) + { + /* Release the lock and dereference the socket */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + } + + /* Return to caller */ + return ErrorCode; +} + +INT +WSPAPI +WSPConnect(SOCKET Handle, + const struct sockaddr * SocketAddress, + INT SocketAddressLength, + LPWSABUF lpCallerData, + LPWSABUF lpCalleeData, + LPQOS lpSQOS, + LPQOS lpGQOS, + LPINT lpErrno) +{ + INT ErrorCode; + + /* Check for caller data */ + if (lpCallerData) + { + /* Validate it */ + if ((IsBadReadPtr(lpCallerData, sizeof(WSABUF))) || + (IsBadReadPtr(lpCallerData->buf, lpCallerData->len))) + { + /* The pointers are invalid, fail */ + ErrorCode = WSAEFAULT; + goto error; + } + } + + /* Check for callee data */ + if (lpCalleeData) + { + /* Validate it */ + if ((IsBadReadPtr(lpCalleeData, sizeof(WSABUF))) || + (IsBadReadPtr(lpCalleeData->buf, lpCalleeData->len))) + { + /* The pointers are invalid, fail */ + ErrorCode = WSAEFAULT; + goto error; + } + } + + /* Check for QoS */ + if (lpSQOS) + { + /* Validate it */ + if ((IsBadReadPtr(lpSQOS, sizeof(QOS))) || + ((lpSQOS->ProviderSpecific.buf) && + (lpSQOS->ProviderSpecific.len) && + (IsBadReadPtr(lpSQOS->ProviderSpecific.buf, + lpSQOS->ProviderSpecific.len)))) + { + /* The pointers are invalid, fail */ + ErrorCode = WSAEFAULT; + goto error; + } + } + + /* Check for Group QoS */ + if (lpGQOS) + { + /* Validate it */ + if ((IsBadReadPtr(lpGQOS, sizeof(QOS))) || + ((lpGQOS->ProviderSpecific.buf) && + (lpGQOS->ProviderSpecific.len) && + (IsBadReadPtr(lpGQOS->ProviderSpecific.buf, + lpGQOS->ProviderSpecific.len)))) + { + /* The pointers are invalid, fail */ + ErrorCode = WSAEFAULT; + goto error; + } + } + + /* Do the actual connect */ + ErrorCode = SockDoConnect(Handle, + SocketAddress, + SocketAddressLength, + lpCallerData, + lpCalleeData, + lpSQOS, + lpGQOS); + +error: + /* Check if this was an error */ + if (ErrorCode != NO_ERROR) + { + /* Return error */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +SOCKET +WSPAPI +WSPJoinLeaf(IN SOCKET s, + IN CONST SOCKADDR *name, + IN INT namelen, + IN LPWSABUF lpCallerData, + OUT LPWSABUF lpCalleeData, + IN LPQOS lpSQOS, + IN LPQOS lpGQOS, + IN DWORD dwFlags, + OUT LPINT lpErrno) +{ + return (SOCKET)0; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +BOOLEAN +WSPAPI +IsSockaddrEqualToZero(IN const struct sockaddr* SocketAddress, + IN INT SocketAddressLength) +{ + INT i; + + for (i = 0; i < SocketAddressLength; i++) + { + /* Make sure it's 0 */ + if (*(PULONG)SocketAddress + i)return FALSE; + } + + /* All zeroes, succees! */ + return TRUE; +} + +INT +WSPAPI +UnconnectDatagramSocket(IN PSOCKET_INFORMATION Socket) +{ + NTSTATUS Status; + INT ErrorCode; + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + AFD_DISCONNECT_INFO DisconnectInfo; + IO_STATUS_BLOCK IoStatusBlock; + + /* Set up the disconnect information */ + DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(-1); + DisconnectInfo.DisconnectType = AFD_DISCONNECT_DATAGRAM; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_DISCONNECT, + &DisconnectInfo, + sizeof(DisconnectInfo), + NULL, + 0); + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion outside the lock */ + LeaveCriticalSection(&Socket->Lock); + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + EnterCriticalSection(&Socket->Lock); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Convert error code */ + ErrorCode = NtStatusToSocketError(Status); + } + else + { + /* Set us as disconnected (back to bound) */ + Socket->SharedData.State = SocketBound; + ErrorCode = NO_ERROR; + } + + /* Return to caller */ + return ErrorCode; +} + +INT +WSPAPI +SockPostProcessConnect(IN PSOCKET_INFORMATION Socket) +{ + INT ErrorCode; + + /* Notify the helper DLL */ + ErrorCode = SockNotifyHelperDll(Socket, WSH_NOTIFY_CONNECT); + if (ErrorCode != NO_ERROR) return ErrorCode; + + /* Set the new state and update the context in AFD */ + Socket->SharedData.State = SocketConnected; + ErrorCode = SockSetHandleContext(Socket); + if (ErrorCode != NO_ERROR) return ErrorCode; + + /* Update the window sizes */ + ErrorCode = SockUpdateWindowSizes(Socket, FALSE); + + /* Return to caller */ + return ErrorCode; +} + +INT +WSPAPI +SockDoConnectReal(IN PSOCKET_INFORMATION Socket, + IN const struct sockaddr *SocketAddress, + IN INT SocketAddressLength, + IN LPWSABUF lpCalleeData, + IN BOOLEAN UseSan) +{ + INT ErrorCode; + NTSTATUS Status; + DWORD ConnectDataLength; + IO_STATUS_BLOCK IoStatusBlock; + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + CHAR ConnectBuffer[FIELD_OFFSET(AFD_CONNECT_INFO, RemoteAddress) + + MAX_TDI_ADDRESS_LENGTH]; + PAFD_CONNECT_INFO ConnectInfo; + ULONG ConnectInfoLength; + + /* Check if someone is waiting for FD_CONNECT */ + if (Socket->SharedData.AsyncEvents & FD_CONNECT) + { + /* + * Disable FD_WRITE and FD_CONNECT + * The latter fixes a race condition where the FD_CONNECT is re-enabled + * at the end of this function right after the Async Thread disables it. + * This should only happen at the *next* WSPConnect + */ + Socket->SharedData.AsyncDisabledEvents |= FD_CONNECT | FD_WRITE; + } + + /* Calculate how much the connection structure will take */ + ConnectInfoLength = FIELD_OFFSET(AFD_CONNECT_INFO, RemoteAddress) + + Socket->HelperData->MaxTDIAddressLength; + + /* Check if our stack buffer is enough */ + if (ConnectInfoLength <= sizeof(ConnectBuffer)) + { + /* Use the stack */ + ConnectInfo = (PVOID)ConnectBuffer; + } + else + { + /* Allocate from heap */ + ConnectInfo = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + ConnectInfoLength); + if (!ConnectInfo) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + } + + /* Create the TDI Address */ + ErrorCode = SockBuildTdiAddress(&ConnectInfo->RemoteAddress, + (PSOCKADDR)SocketAddress, + SocketAddressLength); + if (ErrorCode != NO_ERROR) goto error; + + /* Set the SAN State */ + ConnectInfo->UseSAN = SockSanEnabled; + + /* Check if this is a non-blocking streaming socket */ + if ((Socket->SharedData.NonBlocking) && !(MSAFD_IS_DGRAM_SOCK(Socket))) + { + /* Create the Async Thread if Needed */ + if (!SockCheckAndReferenceAsyncThread()) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + + Status = 0; + } + else + { + /* Start the connect loop */ + do + { + /* Send IOCTL */ + IoStatusBlock.Status = STATUS_PENDING; + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_CONNECT, + ConnectInfo, + ConnectInfoLength, + NULL, + 0); + + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion outside the lock */ + LeaveCriticalSection(&Socket->Lock); + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + EnterCriticalSection(&Socket->Lock); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Make sure we're not closed */ + if (Socket->SharedData.State == SocketClosed) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Check if we failed */ + if (!NT_SUCCESS(Status)) + { + /* Tell the helper DLL */ + ErrorCode = SockNotifyHelperDll(Socket, WSH_NOTIFY_CONNECT_ERROR); + } + + /* Keep looping if the Helper DLL wants us to */ + } while (ErrorCode == WSATRY_AGAIN); + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* Now do post-processing */ + ErrorCode = SockPostProcessConnect(Socket); + if (ErrorCode != NO_ERROR) goto error; + + /* Check if we had callee data */ + if ((lpCalleeData) && (lpCalleeData->buf) && (lpCalleeData->len > 0)) + { + /* Set it */ + ErrorCode = SockGetConnectData(Socket, + IOCTL_AFD_SET_CONNECT_DATA_SIZE, + lpCalleeData->buf, + ConnectDataLength, + &ConnectDataLength); + if (ErrorCode == NO_ERROR) + { + /* If we didn't get any data, then assume the buffer is empty */ + if (!lpCalleeData->len) lpCalleeData->buf = NULL; + } + else + { + /* This isn't fatal, assume we didn't get anything instead */ + lpCalleeData->len = 0; + lpCalleeData->buf = NULL; + } + + /* Assume success */ + ErrorCode = NO_ERROR; + } + +error: + + /* Check if we need to free the connect info from the heap */ + if (ConnectInfo && (ConnectInfo != (PVOID)ConnectBuffer)) + { + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, ConnectInfo); + } + + /* Check if this the success path */ + if (ErrorCode == NO_ERROR) + { + /* Check if FD_WRITE is being select()ed */ + if (Socket->SharedData.AsyncEvents & FD_WRITE) + { + /* Re-enable it */ + SockReenableAsyncSelectEvent(Socket, FD_WRITE); + } + } + + /* Return the error */ + return ErrorCode; +} + +INT +WSPAPI +SockDoConnect(SOCKET Handle, + const struct sockaddr *SocketAddress, + INT SocketAddressLength, + LPWSABUF lpCallerData, + LPWSABUF lpCalleeData, + LPQOS lpSQOS, + LPQOS lpGQOS) +{ + PSOCKET_INFORMATION Socket; + SOCKADDR_INFO SocketInfo; + PSOCKADDR Sockaddr; + PWINSOCK_TEB_DATA ThreadData; + INT SockaddrLength; + INT ErrorCode, ReturnValue; + DWORD ConnectDataLength; + DWORD BytesReturned; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) return ErrorCode; + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* Make sure we're not already connected unless we are a datagram socket */ + if ((Socket->SharedData.State == SocketConnected) && + !(MSAFD_IS_DGRAM_SOCK(Socket))) + { + /* Fail */ + ErrorCode = WSAEISCONN; + goto error; + } + + /* Check if async connect was in progress */ + if (Socket->AsyncData) + { + /* We have to clean it up */ + SockIsSocketConnected(Socket); + + /* Check again */ + if (Socket->AsyncData) + { + /* Can't do anything but fail now */ + ErrorCode = WSAEALREADY; + goto error; + } + } + + /* Make sure we're either unbound, bound, or connected */ + if ((Socket->SharedData.State != SocketOpen) && + (Socket->SharedData.State != SocketBound) && + (Socket->SharedData.State != SocketConnected)) + { + /* Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Normalize the address length */ + SocketAddressLength = min(SocketAddressLength, + Socket->HelperData->MaxWSAddressLength); + + /* Also make sure it's not too small */ + if (SocketAddressLength < Socket->HelperData->MinWSAddressLength) + { + /* Fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* + * If this is a connected socket, and the address is null (0.0.0.0), + * then do a partial disconnect if this is a datagram socket. + */ + if ((Socket->SharedData.State == SocketConnected) && + (MSAFD_IS_DGRAM_SOCK(Socket)) && + (IsSockaddrEqualToZero(SocketAddress, SocketAddressLength))) + { + /* Disconnect the socket and return */ + return UnconnectDatagramSocket(Socket); + } + + /* Make sure the Address Family is valid */ + if (Socket->SharedData.AddressFamily != SocketAddress->sa_family) + { + /* Fail */ + ErrorCode = WSAEAFNOSUPPORT; + goto error; + } + + /* If this is a non-broadcast datagram socket */ + if ((MSAFD_IS_DGRAM_SOCK(Socket) && !(Socket->SharedData.Broadcast))) + { + /* Find out what kind of address this is */ + ErrorCode = Socket->HelperData->WSHGetSockaddrType((PSOCKADDR)SocketAddress, + SocketAddressLength, + &SocketInfo); + if (ErrorCode != NO_ERROR) + { + /* Find out if this is a broadcast address */ + if (SocketInfo.AddressInfo == SockaddrAddressInfoBroadcast) + { + /* Fail: SO_BROADCAST must be set first in WinSock 2.0+ */ + ErrorCode = WSAEACCES; + } + } + + /* A failure here isn't fatal */ + ErrorCode = NO_ERROR; + } + + /* Check if this is a constrained group */ + if (Socket->SharedData.GroupType == SG_CONSTRAINED_GROUP) + { + /* Validate the address and fail if it's not consistent */ + ErrorCode = SockIsAddressConsistentWithConstrainedGroup(Socket, + Socket->SharedData.GroupID, + (PSOCKADDR)SocketAddress, + SocketAddressLength); + if (ErrorCode != NO_ERROR) goto error; + } + + /* Check if this socket isn't bound yet */ + if (Socket->SharedData.State == SocketOpen) + { + /* Check if we can request the wildcard address */ + if (Socket->HelperData->WSHGetWildcardSockaddr) + { + /* Allocate a new Sockaddr */ + SockaddrLength = Socket->HelperData->MaxWSAddressLength; + Sockaddr = SockAllocateHeapRoutine(SockPrivateHeap, 0, SockaddrLength); + if (!Sockaddr) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + + /* Get the wildcard sockaddr */ + ErrorCode = Socket->HelperData->WSHGetWildcardSockaddr(Socket->HelperContext, + Sockaddr, + &SockaddrLength); + if (ErrorCode != NO_ERROR) + { + /* Free memory and fail */ + RtlFreeHeap(SockPrivateHeap, 0, Sockaddr); + goto error; + } + + /* Bind it */ + ReturnValue = WSPBind(Handle, + Sockaddr, + SockaddrLength, + &ErrorCode); + + /* Free memory */ + RtlFreeHeap(SockPrivateHeap, 0, Sockaddr); + + /* Check if we failed */ + if (ReturnValue == SOCKET_ERROR) goto error; + } + else + { + /* Unbound socket, but can't get the wildcard. Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + } + + /* Check if we have caller data */ + if ((lpCallerData) && (lpCallerData->buf) && (lpCallerData->len > 0)) + { + /* Set it */ + ConnectDataLength = lpCallerData->len; + ErrorCode = SockGetConnectData(Socket, + IOCTL_AFD_SET_CONNECT_DATA, + lpCallerData->buf, + ConnectDataLength, + &ConnectDataLength); + if (ErrorCode != NO_ERROR) goto error; + } + + /* Now check if QOS is supported */ + if ((Socket->SharedData.ServiceFlags1 & XP1_QOS_SUPPORTED)) + { + /* Check if we have QoS data */ + if (lpSQOS) + { + /* Send the IOCTL */ + ReturnValue = WSPIoctl(Handle, + SIO_SET_QOS, + lpSQOS, + sizeof(*lpSQOS), + NULL, + 0, + &BytesReturned, + NULL, + NULL, + NULL, + &ErrorCode); + if (ReturnValue == SOCKET_ERROR) goto error; + } + + /* Check if we have Group QoS data */ + if (lpGQOS) + { + /* Send the IOCTL */ + ReturnValue = WSPIoctl(Handle, + SIO_SET_QOS, + lpGQOS, + sizeof(*lpGQOS), + NULL, + 0, + &BytesReturned, + NULL, + NULL, + NULL, + &ErrorCode); + if (ReturnValue == SOCKET_ERROR) goto error; + } + } + + /* Save the address */ + RtlCopyMemory(Socket->RemoteAddress, SocketAddress, SocketAddressLength); + Socket->SharedData.SizeOfRemoteAddress = SocketAddressLength; + + /* Check if we have callee data */ + if ((lpCalleeData) && (lpCalleeData->buf) && (lpCalleeData->len > 0)) + { + /* Set it */ + ConnectDataLength = lpCalleeData->len; + ErrorCode = SockGetConnectData(Socket, + IOCTL_AFD_SET_CONNECT_DATA_SIZE, + lpCalleeData->buf, + ConnectDataLength, + &ConnectDataLength); + if (ErrorCode != NO_ERROR) goto error; + } + + /* Do the actual connect operation */ + ErrorCode = SockDoConnectReal(Socket, + SocketAddress, + SocketAddressLength, + lpCalleeData, + TRUE); + +error: + + /* Check if we had a socket yet */ + if (Socket) + { + /* Release the lock and dereference the socket */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + } + + /* Return to caller */ + return ErrorCode; +} + +INT +WSPAPI +WSPConnect(SOCKET Handle, + const struct sockaddr * SocketAddress, + INT SocketAddressLength, + LPWSABUF lpCallerData, + LPWSABUF lpCalleeData, + LPQOS lpSQOS, + LPQOS lpGQOS, + LPINT lpErrno) +{ + INT ErrorCode; + + /* Check for caller data */ + if (lpCallerData) + { + /* Validate it */ + if ((IsBadReadPtr(lpCallerData, sizeof(WSABUF))) || + (IsBadReadPtr(lpCallerData->buf, lpCallerData->len))) + { + /* The pointers are invalid, fail */ + ErrorCode = WSAEFAULT; + goto error; + } + } + + /* Check for callee data */ + if (lpCalleeData) + { + /* Validate it */ + if ((IsBadReadPtr(lpCalleeData, sizeof(WSABUF))) || + (IsBadReadPtr(lpCalleeData->buf, lpCalleeData->len))) + { + /* The pointers are invalid, fail */ + ErrorCode = WSAEFAULT; + goto error; + } + } + + /* Check for QoS */ + if (lpSQOS) + { + /* Validate it */ + if ((IsBadReadPtr(lpSQOS, sizeof(QOS))) || + ((lpSQOS->ProviderSpecific.buf) && + (lpSQOS->ProviderSpecific.len) && + (IsBadReadPtr(lpSQOS->ProviderSpecific.buf, + lpSQOS->ProviderSpecific.len)))) + { + /* The pointers are invalid, fail */ + ErrorCode = WSAEFAULT; + goto error; + } + } + + /* Check for Group QoS */ + if (lpGQOS) + { + /* Validate it */ + if ((IsBadReadPtr(lpGQOS, sizeof(QOS))) || + ((lpGQOS->ProviderSpecific.buf) && + (lpGQOS->ProviderSpecific.len) && + (IsBadReadPtr(lpGQOS->ProviderSpecific.buf, + lpGQOS->ProviderSpecific.len)))) + { + /* The pointers are invalid, fail */ + ErrorCode = WSAEFAULT; + goto error; + } + } + + /* Do the actual connect */ + ErrorCode = SockDoConnect(Handle, + SocketAddress, + SocketAddressLength, + lpCallerData, + lpCalleeData, + lpSQOS, + lpGQOS); + +error: + /* Check if this was an error */ + if (ErrorCode != NO_ERROR) + { + /* Return error */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +SOCKET +WSPAPI +WSPJoinLeaf(IN SOCKET s, + IN CONST SOCKADDR *name, + IN INT namelen, + IN LPWSABUF lpCallerData, + OUT LPWSABUF lpCalleeData, + IN LPQOS lpSQOS, + IN LPQOS lpGQOS, + IN DWORD dwFlags, + OUT LPINT lpErrno) +{ + return (SOCKET)0; +} + diff --git a/dll/win32/mswsock/msafd/eventsel.c b/dll/win32/mswsock/msafd/eventsel.c new file mode 100644 index 00000000000..ff379a43460 --- /dev/null +++ b/dll/win32/mswsock/msafd/eventsel.c @@ -0,0 +1,1708 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +typedef struct _SOCK_EVENT_MAPPING +{ + ULONG AfdBit; + ULONG WinsockBit; +} SOCK_EVENT_MAPPING, *PSOCK_EVENT_MAPPING; + +SOCK_EVENT_MAPPING PollEventMapping[] = + { + {AFD_EVENT_RECEIVE_BIT, FD_READ_BIT}, + {AFD_EVENT_SEND_BIT, FD_WRITE_BIT}, + {AFD_EVENT_OOB_RECEIVE_BIT, FD_OOB_BIT}, + {AFD_EVENT_ACCEPT_BIT, FD_ACCEPT_BIT}, + {AFD_EVENT_QOS_BIT, FD_QOS_BIT}, + {AFD_EVENT_GROUP_QOS_BIT, FD_GROUP_QOS_BIT}, + {AFD_EVENT_ROUTING_INTERFACE_CHANGE_BIT, FD_ROUTING_INTERFACE_CHANGE_BIT}, + {AFD_EVENT_ADDRESS_LIST_CHANGE_BIT, FD_ADDRESS_LIST_CHANGE_BIT} +}; + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +SockEventSelectHelper(IN PSOCKET_INFORMATION Socket, + IN WSAEVENT EventObject, + IN LONG Events) +{ + IO_STATUS_BLOCK IoStatusBlock; + AFD_EVENT_SELECT_INFO PollInfo; + NTSTATUS Status; + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + + /* Acquire the lock */ + EnterCriticalSection(&Socket->Lock); + + /* Set Structure Info */ + PollInfo.EventObject = EventObject; + PollInfo.Events = 0; + + /* Set receive event */ + if (Events & FD_READ) PollInfo.Events |= AFD_EVENT_RECEIVE; + + /* Set write event */ + if (Events & FD_WRITE) PollInfo.Events |= AFD_EVENT_SEND; + + /* Set out-of-band (OOB) receive event */ + if (Events & FD_OOB) PollInfo.Events |= AFD_EVENT_OOB_RECEIVE; + + /* Set accept event */ + if (Events & FD_ACCEPT) PollInfo.Events |= AFD_EVENT_ACCEPT; + + /* Send Quality-of-Service (QOS) event */ + if (Events & FD_QOS) PollInfo.Events |= AFD_EVENT_QOS; + + /* Send Group Quality-of-Service (QOS) event */ + if (Events & FD_GROUP_QOS) PollInfo.Events |= AFD_EVENT_GROUP_QOS; + + /* Send connect event. Note, this also includes connect failures */ + if (Events & FD_CONNECT) PollInfo.Events |= AFD_EVENT_CONNECT | + AFD_EVENT_CONNECT_FAIL; + + /* Send close event. Note, this includes both aborts and disconnects */ + if (Events & FD_CLOSE) PollInfo.Events |= AFD_EVENT_DISCONNECT | + AFD_EVENT_ABORT; + + /* Send PnP events related to live network hardware changes */ + if (Events & FD_ROUTING_INTERFACE_CHANGE) + { + PollInfo.Events |= AFD_EVENT_ROUTING_INTERFACE_CHANGE; + } + if (Events & FD_ADDRESS_LIST_CHANGE) + { + PollInfo.Events |= AFD_EVENT_ADDRESS_LIST_CHANGE; + } + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_EVENT_SELECT, + &PollInfo, + sizeof(PollInfo), + NULL, + 0); + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + LeaveCriticalSection(&Socket->Lock); + return NtStatusToSocketError(Status); + } + + /* Set Socket Data*/ + Socket->EventObject = EventObject; + Socket->NetworkEvents = Events; + + /* Release lock and return success */ + LeaveCriticalSection(&Socket->Lock); + return NO_ERROR; +} + +INT +WSPAPI +WSPEventSelect(SOCKET Handle, + WSAEVENT hEventObject, + LONG lNetworkEvents, + LPINT lpErrno) +{ + PSOCKET_INFORMATION Socket; + PWINSOCK_TEB_DATA ThreadData; + INT ErrorCode; + BOOLEAN BlockMode; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Set Socket to Non-Blocking */ + BlockMode = TRUE; + ErrorCode = SockSetInformation(Socket, + AFD_INFO_BLOCKING_MODE, + &BlockMode, + NULL, + NULL); + if (ErrorCode != NO_ERROR) goto error; + + /* AFD was notified, set it locally as well */ + Socket->SharedData.NonBlocking = TRUE; + + /* Check if there is an async select in progress */ + if (Socket->EventObject) + { + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* Erase all data */ + Socket->SharedData.hWnd = NULL; + Socket->SharedData.wMsg = 0; + Socket->SharedData.AsyncEvents = 0; + + /* Unbalance the sequence number so the request will fail */ + Socket->SharedData.SequenceNumber++; + + /* Give socket access back */ + LeaveCriticalSection(&Socket->Lock); + } + + /* Make sure the flags are valid */ + if ((lNetworkEvents & ~FD_ALL_EVENTS)) + { + /* More then the possible combination, fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Call the helper */ + ErrorCode = SockEventSelectHelper(Socket, hEventObject, lNetworkEvents); + +error: + /* Dereference the socket, if we have one here */ + if (Socket) SockDereferenceSocket(Socket); + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +INT +WSPAPI +WSPEnumNetworkEvents(IN SOCKET Handle, + IN WSAEVENT hEventObject, + OUT LPWSANETWORKEVENTS lpNetworkEvents, + OUT LPINT lpErrno) +{ + AFD_ENUM_NETWORK_EVENTS_INFO EventInfo; + IO_STATUS_BLOCK IoStatusBlock; + PSOCKET_INFORMATION Socket; + PWINSOCK_TEB_DATA ThreadData; + INT ErrorCode; + NTSTATUS Status, EventStatus; + PSOCK_EVENT_MAPPING EventMapping; + ULONG i; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Make sure we got a pointer */ + if (!lpNetworkEvents) + { + /* Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* Send IOCTL */ + Status = NtDeviceIoControlFile((HANDLE)Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_ENUM_NETWORK_EVENTS, + hEventObject, + 0, + &EventInfo, + sizeof(EventInfo)); + + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* Set Events to wait for */ + lpNetworkEvents->lNetworkEvents = 0; + + /* Set our Event Mapping structure */ + EventMapping = PollEventMapping; + + /* Loop it */ + for (i = 0; i < (sizeof(PollEventMapping) / 2 * sizeof(ULONG)); i++) + { + /* First check if we have a match for this bit */ + if (EventInfo.PollEvents & (1 << EventMapping->AfdBit)) + { + /* Match found, write the equivalent bit */ + lpNetworkEvents->lNetworkEvents |= (1 << EventMapping->WinsockBit); + + /* Now get the status */ + EventStatus = EventInfo.EventStatus[EventMapping->AfdBit]; + + /* Check if it failed */ + if (!NT_SUCCESS(Status)) + { + /* Write the Winsock status code directly */ + lpNetworkEvents->iErrorCode[EventMapping->WinsockBit] = NtStatusToSocketError(EventStatus); + } + else + { + /* Write success */ + lpNetworkEvents->iErrorCode[EventMapping->WinsockBit] = NO_ERROR; + } + + /* Move to the next mapping array */ + EventMapping++; + } + + /* Handle the special cases with two flags. Start with connect */ + if (EventInfo.PollEvents & AFD_EVENT_CONNECT) + { + /* Set the equivalent bit */ + lpNetworkEvents->lNetworkEvents |= FD_CONNECT; + + /* Now get the status */ + EventStatus = EventInfo.EventStatus[AFD_EVENT_CONNECT_BIT]; + + /* Check if it failed */ + if (!NT_SUCCESS(Status)) + { + /* Write the Winsock status code directly */ + lpNetworkEvents->iErrorCode[FD_CONNECT_BIT] = NtStatusToSocketError(EventStatus); + } + else + { + /* Write success */ + lpNetworkEvents->iErrorCode[FD_CONNECT_BIT] = NO_ERROR; + } + } + else if (EventInfo.PollEvents & AFD_EVENT_CONNECT_FAIL) + { + /* Do the same thing, but for the failure */ + lpNetworkEvents->lNetworkEvents |= FD_CONNECT; + + /* Now get the status */ + EventStatus = EventInfo.EventStatus[AFD_EVENT_CONNECT_FAIL_BIT]; + + /* Check if it failed */ + if (!NT_SUCCESS(Status)) + { + /* Write the Winsock status code directly */ + lpNetworkEvents->iErrorCode[FD_CONNECT_BIT] = NtStatusToSocketError(EventStatus); + } + else + { + /* Write success */ + lpNetworkEvents->iErrorCode[FD_CONNECT_BIT] = NO_ERROR; + } + } + + /* Now handle Abort/Disconnect */ + if (EventInfo.PollEvents & AFD_EVENT_ABORT) + { + /* Set the equivalent bit */ + lpNetworkEvents->lNetworkEvents |= FD_CLOSE; + + /* Now get the status */ + EventStatus = EventInfo.EventStatus[AFD_EVENT_ABORT_BIT]; + + /* Check if it failed */ + if (!NT_SUCCESS(Status)) + { + /* Write the Winsock status code directly */ + lpNetworkEvents->iErrorCode[FD_CLOSE_BIT] = NtStatusToSocketError(EventStatus); + } + else + { + /* Write success */ + lpNetworkEvents->iErrorCode[FD_CLOSE_BIT] = NO_ERROR; + } + } + else if (EventInfo.PollEvents & AFD_EVENT_DISCONNECT) + { + /* Do the same thing, but for the failure */ + lpNetworkEvents->lNetworkEvents |= FD_CLOSE; + + /* Now get the status */ + EventStatus = EventInfo.EventStatus[AFD_EVENT_DISCONNECT_BIT]; + + /* Check if it failed */ + if (!NT_SUCCESS(Status)) + { + /* Write the Winsock status code directly */ + lpNetworkEvents->iErrorCode[FD_CLOSE_BIT] = NtStatusToSocketError(EventStatus); + } + else + { + /* Write success */ + lpNetworkEvents->iErrorCode[FD_CLOSE_BIT] = NO_ERROR; + } + } + } + +error: + /* Dereference the socket, if we have one here */ + if (Socket) SockDereferenceSocket(Socket); + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +typedef struct _SOCK_EVENT_MAPPING +{ + ULONG AfdBit; + ULONG WinsockBit; +} SOCK_EVENT_MAPPING, *PSOCK_EVENT_MAPPING; + +SOCK_EVENT_MAPPING PollEventMapping[] = + { + {AFD_EVENT_RECEIVE_BIT, FD_READ_BIT}, + {AFD_EVENT_SEND_BIT, FD_WRITE_BIT}, + {AFD_EVENT_OOB_RECEIVE_BIT, FD_OOB_BIT}, + {AFD_EVENT_ACCEPT_BIT, FD_ACCEPT_BIT}, + {AFD_EVENT_QOS_BIT, FD_QOS_BIT}, + {AFD_EVENT_GROUP_QOS_BIT, FD_GROUP_QOS_BIT}, + {AFD_EVENT_ROUTING_INTERFACE_CHANGE_BIT, FD_ROUTING_INTERFACE_CHANGE_BIT}, + {AFD_EVENT_ADDRESS_LIST_CHANGE_BIT, FD_ADDRESS_LIST_CHANGE_BIT} +}; + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +SockEventSelectHelper(IN PSOCKET_INFORMATION Socket, + IN WSAEVENT EventObject, + IN LONG Events) +{ + IO_STATUS_BLOCK IoStatusBlock; + AFD_EVENT_SELECT_INFO PollInfo; + NTSTATUS Status; + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + + /* Acquire the lock */ + EnterCriticalSection(&Socket->Lock); + + /* Set Structure Info */ + PollInfo.EventObject = EventObject; + PollInfo.Events = 0; + + /* Set receive event */ + if (Events & FD_READ) PollInfo.Events |= AFD_EVENT_RECEIVE; + + /* Set write event */ + if (Events & FD_WRITE) PollInfo.Events |= AFD_EVENT_SEND; + + /* Set out-of-band (OOB) receive event */ + if (Events & FD_OOB) PollInfo.Events |= AFD_EVENT_OOB_RECEIVE; + + /* Set accept event */ + if (Events & FD_ACCEPT) PollInfo.Events |= AFD_EVENT_ACCEPT; + + /* Send Quality-of-Service (QOS) event */ + if (Events & FD_QOS) PollInfo.Events |= AFD_EVENT_QOS; + + /* Send Group Quality-of-Service (QOS) event */ + if (Events & FD_GROUP_QOS) PollInfo.Events |= AFD_EVENT_GROUP_QOS; + + /* Send connect event. Note, this also includes connect failures */ + if (Events & FD_CONNECT) PollInfo.Events |= AFD_EVENT_CONNECT | + AFD_EVENT_CONNECT_FAIL; + + /* Send close event. Note, this includes both aborts and disconnects */ + if (Events & FD_CLOSE) PollInfo.Events |= AFD_EVENT_DISCONNECT | + AFD_EVENT_ABORT; + + /* Send PnP events related to live network hardware changes */ + if (Events & FD_ROUTING_INTERFACE_CHANGE) + { + PollInfo.Events |= AFD_EVENT_ROUTING_INTERFACE_CHANGE; + } + if (Events & FD_ADDRESS_LIST_CHANGE) + { + PollInfo.Events |= AFD_EVENT_ADDRESS_LIST_CHANGE; + } + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_EVENT_SELECT, + &PollInfo, + sizeof(PollInfo), + NULL, + 0); + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + LeaveCriticalSection(&Socket->Lock); + return NtStatusToSocketError(Status); + } + + /* Set Socket Data*/ + Socket->EventObject = EventObject; + Socket->NetworkEvents = Events; + + /* Release lock and return success */ + LeaveCriticalSection(&Socket->Lock); + return NO_ERROR; +} + +INT +WSPAPI +WSPEventSelect(SOCKET Handle, + WSAEVENT hEventObject, + LONG lNetworkEvents, + LPINT lpErrno) +{ + PSOCKET_INFORMATION Socket; + PWINSOCK_TEB_DATA ThreadData; + INT ErrorCode; + BOOLEAN BlockMode; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Set Socket to Non-Blocking */ + BlockMode = TRUE; + ErrorCode = SockSetInformation(Socket, + AFD_INFO_BLOCKING_MODE, + &BlockMode, + NULL, + NULL); + if (ErrorCode != NO_ERROR) goto error; + + /* AFD was notified, set it locally as well */ + Socket->SharedData.NonBlocking = TRUE; + + /* Check if there is an async select in progress */ + if (Socket->EventObject) + { + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* Erase all data */ + Socket->SharedData.hWnd = NULL; + Socket->SharedData.wMsg = 0; + Socket->SharedData.AsyncEvents = 0; + + /* Unbalance the sequence number so the request will fail */ + Socket->SharedData.SequenceNumber++; + + /* Give socket access back */ + LeaveCriticalSection(&Socket->Lock); + } + + /* Make sure the flags are valid */ + if ((lNetworkEvents & ~FD_ALL_EVENTS)) + { + /* More then the possible combination, fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Call the helper */ + ErrorCode = SockEventSelectHelper(Socket, hEventObject, lNetworkEvents); + +error: + /* Dereference the socket, if we have one here */ + if (Socket) SockDereferenceSocket(Socket); + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +INT +WSPAPI +WSPEnumNetworkEvents(IN SOCKET Handle, + IN WSAEVENT hEventObject, + OUT LPWSANETWORKEVENTS lpNetworkEvents, + OUT LPINT lpErrno) +{ + AFD_ENUM_NETWORK_EVENTS_INFO EventInfo; + IO_STATUS_BLOCK IoStatusBlock; + PSOCKET_INFORMATION Socket; + PWINSOCK_TEB_DATA ThreadData; + INT ErrorCode; + NTSTATUS Status, EventStatus; + PSOCK_EVENT_MAPPING EventMapping; + ULONG i; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Make sure we got a pointer */ + if (!lpNetworkEvents) + { + /* Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* Send IOCTL */ + Status = NtDeviceIoControlFile((HANDLE)Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_ENUM_NETWORK_EVENTS, + hEventObject, + 0, + &EventInfo, + sizeof(EventInfo)); + + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* Set Events to wait for */ + lpNetworkEvents->lNetworkEvents = 0; + + /* Set our Event Mapping structure */ + EventMapping = PollEventMapping; + + /* Loop it */ + for (i = 0; i < (sizeof(PollEventMapping) / 2 * sizeof(ULONG)); i++) + { + /* First check if we have a match for this bit */ + if (EventInfo.PollEvents & (1 << EventMapping->AfdBit)) + { + /* Match found, write the equivalent bit */ + lpNetworkEvents->lNetworkEvents |= (1 << EventMapping->WinsockBit); + + /* Now get the status */ + EventStatus = EventInfo.EventStatus[EventMapping->AfdBit]; + + /* Check if it failed */ + if (!NT_SUCCESS(Status)) + { + /* Write the Winsock status code directly */ + lpNetworkEvents->iErrorCode[EventMapping->WinsockBit] = NtStatusToSocketError(EventStatus); + } + else + { + /* Write success */ + lpNetworkEvents->iErrorCode[EventMapping->WinsockBit] = NO_ERROR; + } + + /* Move to the next mapping array */ + EventMapping++; + } + + /* Handle the special cases with two flags. Start with connect */ + if (EventInfo.PollEvents & AFD_EVENT_CONNECT) + { + /* Set the equivalent bit */ + lpNetworkEvents->lNetworkEvents |= FD_CONNECT; + + /* Now get the status */ + EventStatus = EventInfo.EventStatus[AFD_EVENT_CONNECT_BIT]; + + /* Check if it failed */ + if (!NT_SUCCESS(Status)) + { + /* Write the Winsock status code directly */ + lpNetworkEvents->iErrorCode[FD_CONNECT_BIT] = NtStatusToSocketError(EventStatus); + } + else + { + /* Write success */ + lpNetworkEvents->iErrorCode[FD_CONNECT_BIT] = NO_ERROR; + } + } + else if (EventInfo.PollEvents & AFD_EVENT_CONNECT_FAIL) + { + /* Do the same thing, but for the failure */ + lpNetworkEvents->lNetworkEvents |= FD_CONNECT; + + /* Now get the status */ + EventStatus = EventInfo.EventStatus[AFD_EVENT_CONNECT_FAIL_BIT]; + + /* Check if it failed */ + if (!NT_SUCCESS(Status)) + { + /* Write the Winsock status code directly */ + lpNetworkEvents->iErrorCode[FD_CONNECT_BIT] = NtStatusToSocketError(EventStatus); + } + else + { + /* Write success */ + lpNetworkEvents->iErrorCode[FD_CONNECT_BIT] = NO_ERROR; + } + } + + /* Now handle Abort/Disconnect */ + if (EventInfo.PollEvents & AFD_EVENT_ABORT) + { + /* Set the equivalent bit */ + lpNetworkEvents->lNetworkEvents |= FD_CLOSE; + + /* Now get the status */ + EventStatus = EventInfo.EventStatus[AFD_EVENT_ABORT_BIT]; + + /* Check if it failed */ + if (!NT_SUCCESS(Status)) + { + /* Write the Winsock status code directly */ + lpNetworkEvents->iErrorCode[FD_CLOSE_BIT] = NtStatusToSocketError(EventStatus); + } + else + { + /* Write success */ + lpNetworkEvents->iErrorCode[FD_CLOSE_BIT] = NO_ERROR; + } + } + else if (EventInfo.PollEvents & AFD_EVENT_DISCONNECT) + { + /* Do the same thing, but for the failure */ + lpNetworkEvents->lNetworkEvents |= FD_CLOSE; + + /* Now get the status */ + EventStatus = EventInfo.EventStatus[AFD_EVENT_DISCONNECT_BIT]; + + /* Check if it failed */ + if (!NT_SUCCESS(Status)) + { + /* Write the Winsock status code directly */ + lpNetworkEvents->iErrorCode[FD_CLOSE_BIT] = NtStatusToSocketError(EventStatus); + } + else + { + /* Write success */ + lpNetworkEvents->iErrorCode[FD_CLOSE_BIT] = NO_ERROR; + } + } + } + +error: + /* Dereference the socket, if we have one here */ + if (Socket) SockDereferenceSocket(Socket); + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +typedef struct _SOCK_EVENT_MAPPING +{ + ULONG AfdBit; + ULONG WinsockBit; +} SOCK_EVENT_MAPPING, *PSOCK_EVENT_MAPPING; + +SOCK_EVENT_MAPPING PollEventMapping[] = + { + {AFD_EVENT_RECEIVE_BIT, FD_READ_BIT}, + {AFD_EVENT_SEND_BIT, FD_WRITE_BIT}, + {AFD_EVENT_OOB_RECEIVE_BIT, FD_OOB_BIT}, + {AFD_EVENT_ACCEPT_BIT, FD_ACCEPT_BIT}, + {AFD_EVENT_QOS_BIT, FD_QOS_BIT}, + {AFD_EVENT_GROUP_QOS_BIT, FD_GROUP_QOS_BIT}, + {AFD_EVENT_ROUTING_INTERFACE_CHANGE_BIT, FD_ROUTING_INTERFACE_CHANGE_BIT}, + {AFD_EVENT_ADDRESS_LIST_CHANGE_BIT, FD_ADDRESS_LIST_CHANGE_BIT} +}; + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +SockEventSelectHelper(IN PSOCKET_INFORMATION Socket, + IN WSAEVENT EventObject, + IN LONG Events) +{ + IO_STATUS_BLOCK IoStatusBlock; + AFD_EVENT_SELECT_INFO PollInfo; + NTSTATUS Status; + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + + /* Acquire the lock */ + EnterCriticalSection(&Socket->Lock); + + /* Set Structure Info */ + PollInfo.EventObject = EventObject; + PollInfo.Events = 0; + + /* Set receive event */ + if (Events & FD_READ) PollInfo.Events |= AFD_EVENT_RECEIVE; + + /* Set write event */ + if (Events & FD_WRITE) PollInfo.Events |= AFD_EVENT_SEND; + + /* Set out-of-band (OOB) receive event */ + if (Events & FD_OOB) PollInfo.Events |= AFD_EVENT_OOB_RECEIVE; + + /* Set accept event */ + if (Events & FD_ACCEPT) PollInfo.Events |= AFD_EVENT_ACCEPT; + + /* Send Quality-of-Service (QOS) event */ + if (Events & FD_QOS) PollInfo.Events |= AFD_EVENT_QOS; + + /* Send Group Quality-of-Service (QOS) event */ + if (Events & FD_GROUP_QOS) PollInfo.Events |= AFD_EVENT_GROUP_QOS; + + /* Send connect event. Note, this also includes connect failures */ + if (Events & FD_CONNECT) PollInfo.Events |= AFD_EVENT_CONNECT | + AFD_EVENT_CONNECT_FAIL; + + /* Send close event. Note, this includes both aborts and disconnects */ + if (Events & FD_CLOSE) PollInfo.Events |= AFD_EVENT_DISCONNECT | + AFD_EVENT_ABORT; + + /* Send PnP events related to live network hardware changes */ + if (Events & FD_ROUTING_INTERFACE_CHANGE) + { + PollInfo.Events |= AFD_EVENT_ROUTING_INTERFACE_CHANGE; + } + if (Events & FD_ADDRESS_LIST_CHANGE) + { + PollInfo.Events |= AFD_EVENT_ADDRESS_LIST_CHANGE; + } + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_EVENT_SELECT, + &PollInfo, + sizeof(PollInfo), + NULL, + 0); + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + LeaveCriticalSection(&Socket->Lock); + return NtStatusToSocketError(Status); + } + + /* Set Socket Data*/ + Socket->EventObject = EventObject; + Socket->NetworkEvents = Events; + + /* Release lock and return success */ + LeaveCriticalSection(&Socket->Lock); + return NO_ERROR; +} + +INT +WSPAPI +WSPEventSelect(SOCKET Handle, + WSAEVENT hEventObject, + LONG lNetworkEvents, + LPINT lpErrno) +{ + PSOCKET_INFORMATION Socket; + PWINSOCK_TEB_DATA ThreadData; + INT ErrorCode; + BOOLEAN BlockMode; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Set Socket to Non-Blocking */ + BlockMode = TRUE; + ErrorCode = SockSetInformation(Socket, + AFD_INFO_BLOCKING_MODE, + &BlockMode, + NULL, + NULL); + if (ErrorCode != NO_ERROR) goto error; + + /* AFD was notified, set it locally as well */ + Socket->SharedData.NonBlocking = TRUE; + + /* Check if there is an async select in progress */ + if (Socket->EventObject) + { + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* Erase all data */ + Socket->SharedData.hWnd = NULL; + Socket->SharedData.wMsg = 0; + Socket->SharedData.AsyncEvents = 0; + + /* Unbalance the sequence number so the request will fail */ + Socket->SharedData.SequenceNumber++; + + /* Give socket access back */ + LeaveCriticalSection(&Socket->Lock); + } + + /* Make sure the flags are valid */ + if ((lNetworkEvents & ~FD_ALL_EVENTS)) + { + /* More then the possible combination, fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Call the helper */ + ErrorCode = SockEventSelectHelper(Socket, hEventObject, lNetworkEvents); + +error: + /* Dereference the socket, if we have one here */ + if (Socket) SockDereferenceSocket(Socket); + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +INT +WSPAPI +WSPEnumNetworkEvents(IN SOCKET Handle, + IN WSAEVENT hEventObject, + OUT LPWSANETWORKEVENTS lpNetworkEvents, + OUT LPINT lpErrno) +{ + AFD_ENUM_NETWORK_EVENTS_INFO EventInfo; + IO_STATUS_BLOCK IoStatusBlock; + PSOCKET_INFORMATION Socket; + PWINSOCK_TEB_DATA ThreadData; + INT ErrorCode; + NTSTATUS Status, EventStatus; + PSOCK_EVENT_MAPPING EventMapping; + ULONG i; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Make sure we got a pointer */ + if (!lpNetworkEvents) + { + /* Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* Send IOCTL */ + Status = NtDeviceIoControlFile((HANDLE)Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_ENUM_NETWORK_EVENTS, + hEventObject, + 0, + &EventInfo, + sizeof(EventInfo)); + + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* Set Events to wait for */ + lpNetworkEvents->lNetworkEvents = 0; + + /* Set our Event Mapping structure */ + EventMapping = PollEventMapping; + + /* Loop it */ + for (i = 0; i < (sizeof(PollEventMapping) / 2 * sizeof(ULONG)); i++) + { + /* First check if we have a match for this bit */ + if (EventInfo.PollEvents & (1 << EventMapping->AfdBit)) + { + /* Match found, write the equivalent bit */ + lpNetworkEvents->lNetworkEvents |= (1 << EventMapping->WinsockBit); + + /* Now get the status */ + EventStatus = EventInfo.EventStatus[EventMapping->AfdBit]; + + /* Check if it failed */ + if (!NT_SUCCESS(Status)) + { + /* Write the Winsock status code directly */ + lpNetworkEvents->iErrorCode[EventMapping->WinsockBit] = NtStatusToSocketError(EventStatus); + } + else + { + /* Write success */ + lpNetworkEvents->iErrorCode[EventMapping->WinsockBit] = NO_ERROR; + } + + /* Move to the next mapping array */ + EventMapping++; + } + + /* Handle the special cases with two flags. Start with connect */ + if (EventInfo.PollEvents & AFD_EVENT_CONNECT) + { + /* Set the equivalent bit */ + lpNetworkEvents->lNetworkEvents |= FD_CONNECT; + + /* Now get the status */ + EventStatus = EventInfo.EventStatus[AFD_EVENT_CONNECT_BIT]; + + /* Check if it failed */ + if (!NT_SUCCESS(Status)) + { + /* Write the Winsock status code directly */ + lpNetworkEvents->iErrorCode[FD_CONNECT_BIT] = NtStatusToSocketError(EventStatus); + } + else + { + /* Write success */ + lpNetworkEvents->iErrorCode[FD_CONNECT_BIT] = NO_ERROR; + } + } + else if (EventInfo.PollEvents & AFD_EVENT_CONNECT_FAIL) + { + /* Do the same thing, but for the failure */ + lpNetworkEvents->lNetworkEvents |= FD_CONNECT; + + /* Now get the status */ + EventStatus = EventInfo.EventStatus[AFD_EVENT_CONNECT_FAIL_BIT]; + + /* Check if it failed */ + if (!NT_SUCCESS(Status)) + { + /* Write the Winsock status code directly */ + lpNetworkEvents->iErrorCode[FD_CONNECT_BIT] = NtStatusToSocketError(EventStatus); + } + else + { + /* Write success */ + lpNetworkEvents->iErrorCode[FD_CONNECT_BIT] = NO_ERROR; + } + } + + /* Now handle Abort/Disconnect */ + if (EventInfo.PollEvents & AFD_EVENT_ABORT) + { + /* Set the equivalent bit */ + lpNetworkEvents->lNetworkEvents |= FD_CLOSE; + + /* Now get the status */ + EventStatus = EventInfo.EventStatus[AFD_EVENT_ABORT_BIT]; + + /* Check if it failed */ + if (!NT_SUCCESS(Status)) + { + /* Write the Winsock status code directly */ + lpNetworkEvents->iErrorCode[FD_CLOSE_BIT] = NtStatusToSocketError(EventStatus); + } + else + { + /* Write success */ + lpNetworkEvents->iErrorCode[FD_CLOSE_BIT] = NO_ERROR; + } + } + else if (EventInfo.PollEvents & AFD_EVENT_DISCONNECT) + { + /* Do the same thing, but for the failure */ + lpNetworkEvents->lNetworkEvents |= FD_CLOSE; + + /* Now get the status */ + EventStatus = EventInfo.EventStatus[AFD_EVENT_DISCONNECT_BIT]; + + /* Check if it failed */ + if (!NT_SUCCESS(Status)) + { + /* Write the Winsock status code directly */ + lpNetworkEvents->iErrorCode[FD_CLOSE_BIT] = NtStatusToSocketError(EventStatus); + } + else + { + /* Write success */ + lpNetworkEvents->iErrorCode[FD_CLOSE_BIT] = NO_ERROR; + } + } + } + +error: + /* Dereference the socket, if we have one here */ + if (Socket) SockDereferenceSocket(Socket); + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +typedef struct _SOCK_EVENT_MAPPING +{ + ULONG AfdBit; + ULONG WinsockBit; +} SOCK_EVENT_MAPPING, *PSOCK_EVENT_MAPPING; + +SOCK_EVENT_MAPPING PollEventMapping[] = + { + {AFD_EVENT_RECEIVE_BIT, FD_READ_BIT}, + {AFD_EVENT_SEND_BIT, FD_WRITE_BIT}, + {AFD_EVENT_OOB_RECEIVE_BIT, FD_OOB_BIT}, + {AFD_EVENT_ACCEPT_BIT, FD_ACCEPT_BIT}, + {AFD_EVENT_QOS_BIT, FD_QOS_BIT}, + {AFD_EVENT_GROUP_QOS_BIT, FD_GROUP_QOS_BIT}, + {AFD_EVENT_ROUTING_INTERFACE_CHANGE_BIT, FD_ROUTING_INTERFACE_CHANGE_BIT}, + {AFD_EVENT_ADDRESS_LIST_CHANGE_BIT, FD_ADDRESS_LIST_CHANGE_BIT} +}; + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +SockEventSelectHelper(IN PSOCKET_INFORMATION Socket, + IN WSAEVENT EventObject, + IN LONG Events) +{ + IO_STATUS_BLOCK IoStatusBlock; + AFD_EVENT_SELECT_INFO PollInfo; + NTSTATUS Status; + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + + /* Acquire the lock */ + EnterCriticalSection(&Socket->Lock); + + /* Set Structure Info */ + PollInfo.EventObject = EventObject; + PollInfo.Events = 0; + + /* Set receive event */ + if (Events & FD_READ) PollInfo.Events |= AFD_EVENT_RECEIVE; + + /* Set write event */ + if (Events & FD_WRITE) PollInfo.Events |= AFD_EVENT_SEND; + + /* Set out-of-band (OOB) receive event */ + if (Events & FD_OOB) PollInfo.Events |= AFD_EVENT_OOB_RECEIVE; + + /* Set accept event */ + if (Events & FD_ACCEPT) PollInfo.Events |= AFD_EVENT_ACCEPT; + + /* Send Quality-of-Service (QOS) event */ + if (Events & FD_QOS) PollInfo.Events |= AFD_EVENT_QOS; + + /* Send Group Quality-of-Service (QOS) event */ + if (Events & FD_GROUP_QOS) PollInfo.Events |= AFD_EVENT_GROUP_QOS; + + /* Send connect event. Note, this also includes connect failures */ + if (Events & FD_CONNECT) PollInfo.Events |= AFD_EVENT_CONNECT | + AFD_EVENT_CONNECT_FAIL; + + /* Send close event. Note, this includes both aborts and disconnects */ + if (Events & FD_CLOSE) PollInfo.Events |= AFD_EVENT_DISCONNECT | + AFD_EVENT_ABORT; + + /* Send PnP events related to live network hardware changes */ + if (Events & FD_ROUTING_INTERFACE_CHANGE) + { + PollInfo.Events |= AFD_EVENT_ROUTING_INTERFACE_CHANGE; + } + if (Events & FD_ADDRESS_LIST_CHANGE) + { + PollInfo.Events |= AFD_EVENT_ADDRESS_LIST_CHANGE; + } + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_EVENT_SELECT, + &PollInfo, + sizeof(PollInfo), + NULL, + 0); + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + LeaveCriticalSection(&Socket->Lock); + return NtStatusToSocketError(Status); + } + + /* Set Socket Data*/ + Socket->EventObject = EventObject; + Socket->NetworkEvents = Events; + + /* Release lock and return success */ + LeaveCriticalSection(&Socket->Lock); + return NO_ERROR; +} + +INT +WSPAPI +WSPEventSelect(SOCKET Handle, + WSAEVENT hEventObject, + LONG lNetworkEvents, + LPINT lpErrno) +{ + PSOCKET_INFORMATION Socket; + PWINSOCK_TEB_DATA ThreadData; + INT ErrorCode; + BOOLEAN BlockMode; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Set Socket to Non-Blocking */ + BlockMode = TRUE; + ErrorCode = SockSetInformation(Socket, + AFD_INFO_BLOCKING_MODE, + &BlockMode, + NULL, + NULL); + if (ErrorCode != NO_ERROR) goto error; + + /* AFD was notified, set it locally as well */ + Socket->SharedData.NonBlocking = TRUE; + + /* Check if there is an async select in progress */ + if (Socket->EventObject) + { + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* Erase all data */ + Socket->SharedData.hWnd = NULL; + Socket->SharedData.wMsg = 0; + Socket->SharedData.AsyncEvents = 0; + + /* Unbalance the sequence number so the request will fail */ + Socket->SharedData.SequenceNumber++; + + /* Give socket access back */ + LeaveCriticalSection(&Socket->Lock); + } + + /* Make sure the flags are valid */ + if ((lNetworkEvents & ~FD_ALL_EVENTS)) + { + /* More then the possible combination, fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Call the helper */ + ErrorCode = SockEventSelectHelper(Socket, hEventObject, lNetworkEvents); + +error: + /* Dereference the socket, if we have one here */ + if (Socket) SockDereferenceSocket(Socket); + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +INT +WSPAPI +WSPEnumNetworkEvents(IN SOCKET Handle, + IN WSAEVENT hEventObject, + OUT LPWSANETWORKEVENTS lpNetworkEvents, + OUT LPINT lpErrno) +{ + AFD_ENUM_NETWORK_EVENTS_INFO EventInfo; + IO_STATUS_BLOCK IoStatusBlock; + PSOCKET_INFORMATION Socket; + PWINSOCK_TEB_DATA ThreadData; + INT ErrorCode; + NTSTATUS Status, EventStatus; + PSOCK_EVENT_MAPPING EventMapping; + ULONG i; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Make sure we got a pointer */ + if (!lpNetworkEvents) + { + /* Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* Send IOCTL */ + Status = NtDeviceIoControlFile((HANDLE)Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_ENUM_NETWORK_EVENTS, + hEventObject, + 0, + &EventInfo, + sizeof(EventInfo)); + + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* Set Events to wait for */ + lpNetworkEvents->lNetworkEvents = 0; + + /* Set our Event Mapping structure */ + EventMapping = PollEventMapping; + + /* Loop it */ + for (i = 0; i < (sizeof(PollEventMapping) / 2 * sizeof(ULONG)); i++) + { + /* First check if we have a match for this bit */ + if (EventInfo.PollEvents & (1 << EventMapping->AfdBit)) + { + /* Match found, write the equivalent bit */ + lpNetworkEvents->lNetworkEvents |= (1 << EventMapping->WinsockBit); + + /* Now get the status */ + EventStatus = EventInfo.EventStatus[EventMapping->AfdBit]; + + /* Check if it failed */ + if (!NT_SUCCESS(Status)) + { + /* Write the Winsock status code directly */ + lpNetworkEvents->iErrorCode[EventMapping->WinsockBit] = NtStatusToSocketError(EventStatus); + } + else + { + /* Write success */ + lpNetworkEvents->iErrorCode[EventMapping->WinsockBit] = NO_ERROR; + } + + /* Move to the next mapping array */ + EventMapping++; + } + + /* Handle the special cases with two flags. Start with connect */ + if (EventInfo.PollEvents & AFD_EVENT_CONNECT) + { + /* Set the equivalent bit */ + lpNetworkEvents->lNetworkEvents |= FD_CONNECT; + + /* Now get the status */ + EventStatus = EventInfo.EventStatus[AFD_EVENT_CONNECT_BIT]; + + /* Check if it failed */ + if (!NT_SUCCESS(Status)) + { + /* Write the Winsock status code directly */ + lpNetworkEvents->iErrorCode[FD_CONNECT_BIT] = NtStatusToSocketError(EventStatus); + } + else + { + /* Write success */ + lpNetworkEvents->iErrorCode[FD_CONNECT_BIT] = NO_ERROR; + } + } + else if (EventInfo.PollEvents & AFD_EVENT_CONNECT_FAIL) + { + /* Do the same thing, but for the failure */ + lpNetworkEvents->lNetworkEvents |= FD_CONNECT; + + /* Now get the status */ + EventStatus = EventInfo.EventStatus[AFD_EVENT_CONNECT_FAIL_BIT]; + + /* Check if it failed */ + if (!NT_SUCCESS(Status)) + { + /* Write the Winsock status code directly */ + lpNetworkEvents->iErrorCode[FD_CONNECT_BIT] = NtStatusToSocketError(EventStatus); + } + else + { + /* Write success */ + lpNetworkEvents->iErrorCode[FD_CONNECT_BIT] = NO_ERROR; + } + } + + /* Now handle Abort/Disconnect */ + if (EventInfo.PollEvents & AFD_EVENT_ABORT) + { + /* Set the equivalent bit */ + lpNetworkEvents->lNetworkEvents |= FD_CLOSE; + + /* Now get the status */ + EventStatus = EventInfo.EventStatus[AFD_EVENT_ABORT_BIT]; + + /* Check if it failed */ + if (!NT_SUCCESS(Status)) + { + /* Write the Winsock status code directly */ + lpNetworkEvents->iErrorCode[FD_CLOSE_BIT] = NtStatusToSocketError(EventStatus); + } + else + { + /* Write success */ + lpNetworkEvents->iErrorCode[FD_CLOSE_BIT] = NO_ERROR; + } + } + else if (EventInfo.PollEvents & AFD_EVENT_DISCONNECT) + { + /* Do the same thing, but for the failure */ + lpNetworkEvents->lNetworkEvents |= FD_CLOSE; + + /* Now get the status */ + EventStatus = EventInfo.EventStatus[AFD_EVENT_DISCONNECT_BIT]; + + /* Check if it failed */ + if (!NT_SUCCESS(Status)) + { + /* Write the Winsock status code directly */ + lpNetworkEvents->iErrorCode[FD_CLOSE_BIT] = NtStatusToSocketError(EventStatus); + } + else + { + /* Write success */ + lpNetworkEvents->iErrorCode[FD_CLOSE_BIT] = NO_ERROR; + } + } + } + +error: + /* Dereference the socket, if we have one here */ + if (Socket) SockDereferenceSocket(Socket); + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + diff --git a/dll/win32/mswsock/msafd/getname.c b/dll/win32/mswsock/msafd/getname.c new file mode 100644 index 00000000000..8cbaed96e5d --- /dev/null +++ b/dll/win32/mswsock/msafd/getname.c @@ -0,0 +1,980 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +WSPGetSockName(IN SOCKET Handle, + OUT LPSOCKADDR Name, + IN OUT LPINT NameLength, + OUT LPINT lpErrno) +{ + IO_STATUS_BLOCK IoStatusBlock; + ULONG TdiAddressSize; + INT ErrorCode; + PTDI_ADDRESS_INFO TdiAddress = NULL; + PSOCKET_INFORMATION Socket; + NTSTATUS Status; + PWINSOCK_TEB_DATA ThreadData; + CHAR AddressBuffer[FIELD_OFFSET(TDI_ADDRESS_INFO, Address) + + MAX_TDI_ADDRESS_LENGTH]; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* If the socket isn't bound, fail */ + if (Socket->SharedData.State == SocketOpen) + { + /* Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Check how long the TDI Address is */ + TdiAddressSize = FIELD_OFFSET(TDI_ADDRESS_INFO, Address) + + Socket->HelperData->MaxTDIAddressLength; + + /* See if it can fit in the stack */ + if (TdiAddressSize <= sizeof(AddressBuffer)) + { + /* Use the stack */ + TdiAddress = (PVOID)AddressBuffer; + } + else + { + /* Allocate from heap */ + TdiAddress = SockAllocateHeapRoutine(SockPrivateHeap, 0, TdiAddressSize); + if (!TdiAddress) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + } + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_GET_SOCK_NAME, + NULL, + 0, + TdiAddress, + TdiAddressSize); + + /* Check if it's pending */ + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + LeaveCriticalSection(&Socket->Lock); + SockWaitForSingleObject(ThreadData->EventHandle, + Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + EnterCriticalSection(&Socket->Lock); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* Convert to Sockaddr format */ + SockBuildSockaddr(Socket->LocalAddress, + &Socket->SharedData.SizeOfLocalAddress, + &TdiAddress->Address); + + /* Check for valid length */ + if (Socket->SharedData.SizeOfLocalAddress > *NameLength) + { + /* Fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* Write the Address */ + RtlCopyMemory(Name, + Socket->LocalAddress, + Socket->SharedData.SizeOfLocalAddress); + + /* Return the Name Length */ + *NameLength = Socket->SharedData.SizeOfLocalAddress; + +error: + + /* Check if we have a socket here */ + if (Socket) + { + /* Release the lock and dereference */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + } + + /* Check if we should free the TDI address */ + if ((TdiAddress) && (TdiAddress != (PVOID)AddressBuffer)) + { + /* Free the Buffer */ + RtlFreeHeap(SockPrivateHeap, 0, TdiAddress); + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +INT +WSPAPI +WSPGetPeerName(IN SOCKET Handle, + OUT LPSOCKADDR Name, + IN OUT LPINT NameLength, + OUT LPINT lpErrno) +{ + INT ErrorCode; + PSOCKET_INFORMATION Socket; + PWINSOCK_TEB_DATA ThreadData; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* If the socket isn't connected, then fail */ + if (!(SockIsSocketConnected(Socket)) && !(Socket->AsyncData)) + { + /* Fail */ + ErrorCode = WSAENOTCONN; + goto error; + } + + /* Check for valid length */ + if (Socket->SharedData.SizeOfRemoteAddress > *NameLength) + { + /* Fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* Write the Address */ + RtlCopyMemory(Name, + Socket->RemoteAddress, + Socket->SharedData.SizeOfRemoteAddress); + + /* Return the Name Length */ + *NameLength = Socket->SharedData.SizeOfRemoteAddress; + +error: + + /* Check if we have a socket here */ + if (Socket) + { + /* Release the lock and dereference */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +WSPGetSockName(IN SOCKET Handle, + OUT LPSOCKADDR Name, + IN OUT LPINT NameLength, + OUT LPINT lpErrno) +{ + IO_STATUS_BLOCK IoStatusBlock; + ULONG TdiAddressSize; + INT ErrorCode; + PTDI_ADDRESS_INFO TdiAddress = NULL; + PSOCKET_INFORMATION Socket; + NTSTATUS Status; + PWINSOCK_TEB_DATA ThreadData; + CHAR AddressBuffer[FIELD_OFFSET(TDI_ADDRESS_INFO, Address) + + MAX_TDI_ADDRESS_LENGTH]; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* If the socket isn't bound, fail */ + if (Socket->SharedData.State == SocketOpen) + { + /* Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Check how long the TDI Address is */ + TdiAddressSize = FIELD_OFFSET(TDI_ADDRESS_INFO, Address) + + Socket->HelperData->MaxTDIAddressLength; + + /* See if it can fit in the stack */ + if (TdiAddressSize <= sizeof(AddressBuffer)) + { + /* Use the stack */ + TdiAddress = (PVOID)AddressBuffer; + } + else + { + /* Allocate from heap */ + TdiAddress = SockAllocateHeapRoutine(SockPrivateHeap, 0, TdiAddressSize); + if (!TdiAddress) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + } + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_GET_SOCK_NAME, + NULL, + 0, + TdiAddress, + TdiAddressSize); + + /* Check if it's pending */ + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + LeaveCriticalSection(&Socket->Lock); + SockWaitForSingleObject(ThreadData->EventHandle, + Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + EnterCriticalSection(&Socket->Lock); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* Convert to Sockaddr format */ + SockBuildSockaddr(Socket->LocalAddress, + &Socket->SharedData.SizeOfLocalAddress, + &TdiAddress->Address); + + /* Check for valid length */ + if (Socket->SharedData.SizeOfLocalAddress > *NameLength) + { + /* Fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* Write the Address */ + RtlCopyMemory(Name, + Socket->LocalAddress, + Socket->SharedData.SizeOfLocalAddress); + + /* Return the Name Length */ + *NameLength = Socket->SharedData.SizeOfLocalAddress; + +error: + + /* Check if we have a socket here */ + if (Socket) + { + /* Release the lock and dereference */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + } + + /* Check if we should free the TDI address */ + if ((TdiAddress) && (TdiAddress != (PVOID)AddressBuffer)) + { + /* Free the Buffer */ + RtlFreeHeap(SockPrivateHeap, 0, TdiAddress); + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +INT +WSPAPI +WSPGetPeerName(IN SOCKET Handle, + OUT LPSOCKADDR Name, + IN OUT LPINT NameLength, + OUT LPINT lpErrno) +{ + INT ErrorCode; + PSOCKET_INFORMATION Socket; + PWINSOCK_TEB_DATA ThreadData; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* If the socket isn't connected, then fail */ + if (!(SockIsSocketConnected(Socket)) && !(Socket->AsyncData)) + { + /* Fail */ + ErrorCode = WSAENOTCONN; + goto error; + } + + /* Check for valid length */ + if (Socket->SharedData.SizeOfRemoteAddress > *NameLength) + { + /* Fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* Write the Address */ + RtlCopyMemory(Name, + Socket->RemoteAddress, + Socket->SharedData.SizeOfRemoteAddress); + + /* Return the Name Length */ + *NameLength = Socket->SharedData.SizeOfRemoteAddress; + +error: + + /* Check if we have a socket here */ + if (Socket) + { + /* Release the lock and dereference */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +WSPGetSockName(IN SOCKET Handle, + OUT LPSOCKADDR Name, + IN OUT LPINT NameLength, + OUT LPINT lpErrno) +{ + IO_STATUS_BLOCK IoStatusBlock; + ULONG TdiAddressSize; + INT ErrorCode; + PTDI_ADDRESS_INFO TdiAddress = NULL; + PSOCKET_INFORMATION Socket; + NTSTATUS Status; + PWINSOCK_TEB_DATA ThreadData; + CHAR AddressBuffer[FIELD_OFFSET(TDI_ADDRESS_INFO, Address) + + MAX_TDI_ADDRESS_LENGTH]; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* If the socket isn't bound, fail */ + if (Socket->SharedData.State == SocketOpen) + { + /* Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Check how long the TDI Address is */ + TdiAddressSize = FIELD_OFFSET(TDI_ADDRESS_INFO, Address) + + Socket->HelperData->MaxTDIAddressLength; + + /* See if it can fit in the stack */ + if (TdiAddressSize <= sizeof(AddressBuffer)) + { + /* Use the stack */ + TdiAddress = (PVOID)AddressBuffer; + } + else + { + /* Allocate from heap */ + TdiAddress = SockAllocateHeapRoutine(SockPrivateHeap, 0, TdiAddressSize); + if (!TdiAddress) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + } + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_GET_SOCK_NAME, + NULL, + 0, + TdiAddress, + TdiAddressSize); + + /* Check if it's pending */ + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + LeaveCriticalSection(&Socket->Lock); + SockWaitForSingleObject(ThreadData->EventHandle, + Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + EnterCriticalSection(&Socket->Lock); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* Convert to Sockaddr format */ + SockBuildSockaddr(Socket->LocalAddress, + &Socket->SharedData.SizeOfLocalAddress, + &TdiAddress->Address); + + /* Check for valid length */ + if (Socket->SharedData.SizeOfLocalAddress > *NameLength) + { + /* Fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* Write the Address */ + RtlCopyMemory(Name, + Socket->LocalAddress, + Socket->SharedData.SizeOfLocalAddress); + + /* Return the Name Length */ + *NameLength = Socket->SharedData.SizeOfLocalAddress; + +error: + + /* Check if we have a socket here */ + if (Socket) + { + /* Release the lock and dereference */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + } + + /* Check if we should free the TDI address */ + if ((TdiAddress) && (TdiAddress != (PVOID)AddressBuffer)) + { + /* Free the Buffer */ + RtlFreeHeap(SockPrivateHeap, 0, TdiAddress); + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +INT +WSPAPI +WSPGetPeerName(IN SOCKET Handle, + OUT LPSOCKADDR Name, + IN OUT LPINT NameLength, + OUT LPINT lpErrno) +{ + INT ErrorCode; + PSOCKET_INFORMATION Socket; + PWINSOCK_TEB_DATA ThreadData; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* If the socket isn't connected, then fail */ + if (!(SockIsSocketConnected(Socket)) && !(Socket->AsyncData)) + { + /* Fail */ + ErrorCode = WSAENOTCONN; + goto error; + } + + /* Check for valid length */ + if (Socket->SharedData.SizeOfRemoteAddress > *NameLength) + { + /* Fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* Write the Address */ + RtlCopyMemory(Name, + Socket->RemoteAddress, + Socket->SharedData.SizeOfRemoteAddress); + + /* Return the Name Length */ + *NameLength = Socket->SharedData.SizeOfRemoteAddress; + +error: + + /* Check if we have a socket here */ + if (Socket) + { + /* Release the lock and dereference */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +WSPGetSockName(IN SOCKET Handle, + OUT LPSOCKADDR Name, + IN OUT LPINT NameLength, + OUT LPINT lpErrno) +{ + IO_STATUS_BLOCK IoStatusBlock; + ULONG TdiAddressSize; + INT ErrorCode; + PTDI_ADDRESS_INFO TdiAddress = NULL; + PSOCKET_INFORMATION Socket; + NTSTATUS Status; + PWINSOCK_TEB_DATA ThreadData; + CHAR AddressBuffer[FIELD_OFFSET(TDI_ADDRESS_INFO, Address) + + MAX_TDI_ADDRESS_LENGTH]; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* If the socket isn't bound, fail */ + if (Socket->SharedData.State == SocketOpen) + { + /* Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Check how long the TDI Address is */ + TdiAddressSize = FIELD_OFFSET(TDI_ADDRESS_INFO, Address) + + Socket->HelperData->MaxTDIAddressLength; + + /* See if it can fit in the stack */ + if (TdiAddressSize <= sizeof(AddressBuffer)) + { + /* Use the stack */ + TdiAddress = (PVOID)AddressBuffer; + } + else + { + /* Allocate from heap */ + TdiAddress = SockAllocateHeapRoutine(SockPrivateHeap, 0, TdiAddressSize); + if (!TdiAddress) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + } + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_GET_SOCK_NAME, + NULL, + 0, + TdiAddress, + TdiAddressSize); + + /* Check if it's pending */ + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + LeaveCriticalSection(&Socket->Lock); + SockWaitForSingleObject(ThreadData->EventHandle, + Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + EnterCriticalSection(&Socket->Lock); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* Convert to Sockaddr format */ + SockBuildSockaddr(Socket->LocalAddress, + &Socket->SharedData.SizeOfLocalAddress, + &TdiAddress->Address); + + /* Check for valid length */ + if (Socket->SharedData.SizeOfLocalAddress > *NameLength) + { + /* Fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* Write the Address */ + RtlCopyMemory(Name, + Socket->LocalAddress, + Socket->SharedData.SizeOfLocalAddress); + + /* Return the Name Length */ + *NameLength = Socket->SharedData.SizeOfLocalAddress; + +error: + + /* Check if we have a socket here */ + if (Socket) + { + /* Release the lock and dereference */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + } + + /* Check if we should free the TDI address */ + if ((TdiAddress) && (TdiAddress != (PVOID)AddressBuffer)) + { + /* Free the Buffer */ + RtlFreeHeap(SockPrivateHeap, 0, TdiAddress); + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +INT +WSPAPI +WSPGetPeerName(IN SOCKET Handle, + OUT LPSOCKADDR Name, + IN OUT LPINT NameLength, + OUT LPINT lpErrno) +{ + INT ErrorCode; + PSOCKET_INFORMATION Socket; + PWINSOCK_TEB_DATA ThreadData; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* If the socket isn't connected, then fail */ + if (!(SockIsSocketConnected(Socket)) && !(Socket->AsyncData)) + { + /* Fail */ + ErrorCode = WSAENOTCONN; + goto error; + } + + /* Check for valid length */ + if (Socket->SharedData.SizeOfRemoteAddress > *NameLength) + { + /* Fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* Write the Address */ + RtlCopyMemory(Name, + Socket->RemoteAddress, + Socket->SharedData.SizeOfRemoteAddress); + + /* Return the Name Length */ + *NameLength = Socket->SharedData.SizeOfRemoteAddress; + +error: + + /* Check if we have a socket here */ + if (Socket) + { + /* Release the lock and dereference */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + diff --git a/dll/win32/mswsock/msafd/helper.c b/dll/win32/mswsock/msafd/helper.c new file mode 100644 index 00000000000..e506d24937f --- /dev/null +++ b/dll/win32/mswsock/msafd/helper.c @@ -0,0 +1,2780 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +LIST_ENTRY SockHelperDllListHead; + +/* FUNCTIONS *****************************************************************/ + +VOID +WSPAPI +SockFreeHelperDll(IN PHELPER_DATA Helper) +{ + /* Free the DLL */ + FreeLibrary(Helper->hInstance); + + /* Free the mapping */ + RtlFreeHeap(SockPrivateHeap, 0, Helper->Mapping); + + /* Free the DLL Structure itself */ + RtlFreeHeap(SockPrivateHeap, 0, Helper); +} + +INT +WSPAPI +SockGetTdiName(PINT AddressFamily, + PINT SocketType, + PINT Protocol, + LPGUID ProviderId, + GROUP Group, + DWORD Flags, + PUNICODE_STRING TransportName, + PVOID *HelperDllContext, + PHELPER_DATA *HelperDllData, + PDWORD Events) +{ + PHELPER_DATA HelperData; + PWSTR Transports; + PWSTR Transport; + PWINSOCK_MAPPING Mapping; + PLIST_ENTRY Helpers; + BOOLEAN SharedLock = TRUE; + INT ErrorCode; + BOOLEAN AfMatch = FALSE, ProtoMatch = FALSE, SocketMatch = FALSE; + + /* Acquire global lock */ + SockAcquireRwLockShared(&SocketGlobalLock); + +TryAgain: + /* Check in our Current Loaded Helpers */ + for (Helpers = SockHelperDllListHead.Flink; + Helpers != &SockHelperDllListHead; + Helpers = Helpers->Flink) + { + /* Get the current helper */ + HelperData = CONTAINING_RECORD(Helpers, HELPER_DATA, Helpers); + + /* See if this Mapping works for us */ + if (SockIsTripleInMapping(HelperData->Mapping, + *AddressFamily, + &AfMatch, + *SocketType, + &SocketMatch, + *Protocol, + &ProtoMatch)) + { + /* Call the Helper Dll function get the Transport Name */ + if (!HelperData->WSHOpenSocket2) + { + if (!(Flags & WSA_FLAG_MULTIPOINT_ALL)) + { + /* DLL Doesn't support WSHOpenSocket2, call the old one */ + ErrorCode = HelperData->WSHOpenSocket(AddressFamily, + SocketType, + Protocol, + TransportName, + HelperDllContext, + Events); + } + else + { + /* Invalid flag */ + ErrorCode = WSAEINVAL; + } + } + else + { + /* Call the new WSHOpenSocket */ + ErrorCode = HelperData->WSHOpenSocket2(AddressFamily, + SocketType, + Protocol, + Group, + Flags, + TransportName, + HelperDllContext, + Events); + } + + /* Check for success */ + if (ErrorCode == NO_ERROR) + { + /* Reference the helper */ + InterlockedIncrement(&HelperData->RefCount); + + /* Check which lock we acquired */ + if (SharedLock) + { + /* Release the shared lock */ + SockReleaseRwLockShared(&SocketGlobalLock); + } + else + { + /* Release the acquired lock */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + } + + /* Return the Helper Pointers */ + *HelperDllData = HelperData; + return NO_ERROR; + } + + /* Check if we don't need a transport name */ + if ((*SocketType == SOCK_RAW) && (TransportName->Buffer)) + { + /* Free it */ + RtlFreeHeap(RtlGetProcessHeap(), 0, TransportName->Buffer); + TransportName->Buffer = NULL; + } + } + } + + /* We didn't find a match: try again with RW access */ + if (SharedLock) + { + /* Switch locks */ + SockReleaseRwLockShared(&SocketGlobalLock); + SockAcquireRwLockExclusive(&SocketGlobalLock); + + /* Parse the list again */ + SharedLock = FALSE; + goto TryAgain; + } + + /* Get the Transports available */ + ErrorCode = SockLoadTransportList(&Transports); + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + return ErrorCode; + } + + /* Loop through each transport until we find one that can satisfy us */ + for (Transport = Transports; *Transport; Transport += wcslen(Transport) + 1) + { + /* See what mapping this Transport supports */ + ErrorCode = SockLoadTransportMapping(Transport, &Mapping); + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Try the next one */ + continue; + } + + /* See if this Mapping works for us */ + if (SockIsTripleInMapping(Mapping, + *AddressFamily, + &AfMatch, + *SocketType, + &SocketMatch, + *Protocol, + &ProtoMatch)) + { + /* It does, so load the DLL associated with it */ + ErrorCode = SockLoadHelperDll(Transport, Mapping, &HelperData); + + /* Check for success */ + if (ErrorCode == NO_ERROR) + { + /* Call the Helper Dll function get the Transport Name */ + if (!HelperData->WSHOpenSocket2) + { + /* Check for invalid flag combo */ + if (!(Flags & WSA_FLAG_MULTIPOINT_ALL)) + { + /* DLL Doesn't support WSHOpenSocket2, call the old one */ + ErrorCode = HelperData->WSHOpenSocket(AddressFamily, + SocketType, + Protocol, + TransportName, + HelperDllContext, + Events); + } + else + { + /* Fail */ + ErrorCode = WSAEINVAL; + } + } + else + { + /* Call the newer function */ + ErrorCode = HelperData->WSHOpenSocket2(AddressFamily, + SocketType, + Protocol, + Group, + Flags, + TransportName, + HelperDllContext, + Events); + } + + /* Check for success */ + if (ErrorCode == NO_ERROR) + { + /* Reference the helper */ + InterlockedIncrement(&HelperData->RefCount); + + /* Release the lock and free the transports */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + RtlFreeHeap(SockPrivateHeap, 0, Transports); + + /* Return the Helper Pointer */ + *HelperDllData = HelperData; + return NO_ERROR; + } + + /* Check if we don't need a transport name */ + if ((*SocketType == SOCK_RAW) && (TransportName->Buffer)) + { + /* Free it */ + RtlFreeHeap(RtlGetProcessHeap(), 0, TransportName->Buffer); + TransportName->Buffer = NULL; + } + + /* Try again */ + continue; + } + } + + /* Free the mapping and continue */ + RtlFreeHeap(SockPrivateHeap, 0, Mapping); + } + + /* Release the lock and free the transport list */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + RtlFreeHeap(SockPrivateHeap, 0, Transports); + + /* Check why we didn't find a match */ + if (!AfMatch) return WSAEAFNOSUPPORT; + if (!ProtoMatch) return WSAEPROTONOSUPPORT; + if (!SocketMatch) return WSAESOCKTNOSUPPORT; + + /* The comination itself was invalid */ + return WSAEINVAL; +} + +INT +WSPAPI +SockLoadTransportMapping(IN PWSTR TransportName, + OUT PWINSOCK_MAPPING *Mapping) +{ + PWSTR TransportKey; + HKEY KeyHandle; + INT ErrorCode; + ULONG MappingSize = 0; + + /* Allocate a Buffer */ + TransportKey = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + MAX_PATH * sizeof(WCHAR)); + /* Check for error */ + if (!TransportKey) return ERROR_NOT_ENOUGH_MEMORY; + + /* Generate the right key name */ + wcscpy(TransportKey, L"System\\CurrentControlSet\\Services\\"); + wcscat(TransportKey, TransportName); + wcscat(TransportKey, L"\\Parameters\\Winsock"); + + /* Open the Key */ + ErrorCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE, + TransportKey, + 0, + KEY_READ, + &KeyHandle); + + /* We don't need the Transport Key anymore */ + RtlFreeHeap(SockPrivateHeap, 0, TransportKey); + + /* Check for error */ + if ((ErrorCode != ERROR_MORE_DATA) && (ErrorCode != NO_ERROR)) + { + /* Close key and fail */ + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Find out how much space we need for the Mapping */ + ErrorCode = RegQueryValueExW(KeyHandle, + L"Mapping", + NULL, + NULL, + NULL, + &MappingSize); + + /* Check for error */ + if ((ErrorCode != ERROR_MORE_DATA) && (ErrorCode != NO_ERROR)) + { + /* Close key and fail */ + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Allocate Memory for the Mapping */ + *Mapping = SockAllocateHeapRoutine(SockPrivateHeap, 0, MappingSize); + + /* Check for error */ + if (!(*Mapping)) + { + /* Close key and fail */ + RegCloseKey(KeyHandle); + return ERROR_NOT_ENOUGH_MEMORY; + } + + /* Read the Mapping */ + ErrorCode = RegQueryValueExW(KeyHandle, + L"Mapping", + NULL, + NULL, + (LPBYTE)*Mapping, + &MappingSize); + + /* Check for error */ + if ((ErrorCode != ERROR_MORE_DATA) && (ErrorCode != NO_ERROR)) + { + /* Close key and fail */ + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Close key and return */ + RegCloseKey(KeyHandle); + return NO_ERROR; +} + +INT +WSPAPI +SockLoadHelperDll(PWSTR TransportName, + PWINSOCK_MAPPING Mapping, + PHELPER_DATA *HelperDllData) +{ + PHELPER_DATA HelperData; + PWSTR HelperDllName; + PWSTR FullHelperDllName; + ULONG HelperDllNameSize; + PWSTR HelperKey; + HKEY KeyHandle; + ULONG DataSize; + INT ErrorCode; + PLIST_ENTRY Entry; + + /* Allocate space for the Helper Structure and TransportName */ + HelperData = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + sizeof(*HelperData) + + (DWORD)(wcslen(TransportName) + 1) * + sizeof(WCHAR)); + + /* Check for error */ + if (!HelperData) return ERROR_NOT_ENOUGH_MEMORY; + + /* Allocate Space for the Helper DLL Key */ + HelperKey = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + MAX_PATH * sizeof(WCHAR)); + + /* Check for error */ + if (!HelperKey) + { + RtlFreeHeap(SockPrivateHeap, 0, HelperData); + return ERROR_NOT_ENOUGH_MEMORY; + } + + /* Generate the right key name */ + wcscpy(HelperKey, L"System\\CurrentControlSet\\Services\\"); + wcscat(HelperKey, TransportName); + wcscat(HelperKey, L"\\Parameters\\Winsock"); + + /* Open the Key */ + ErrorCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE, + HelperKey, + 0, + KEY_READ, + &KeyHandle); + + /* Free Buffer */ + RtlFreeHeap(SockPrivateHeap, 0, HelperKey); + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Free the helper data and fail */ + RtlFreeHeap(SockPrivateHeap, 0, HelperData); + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Read Minimum size of Sockaddr Structures */ + DataSize = sizeof(HelperData->MinWSAddressLength); + RegQueryValueExW(KeyHandle, + L"MinSockaddrLength", + NULL, + NULL, + (LPBYTE)&HelperData->MinWSAddressLength, + &DataSize); + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Free the helper data and fail */ + RtlFreeHeap(SockPrivateHeap, 0, HelperData); + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Read Maximum size of Sockaddr Structures */ + DataSize = sizeof(HelperData->MinWSAddressLength); + RegQueryValueExW(KeyHandle, + L"MaxSockaddrLength", + NULL, + NULL, + (LPBYTE)&HelperData->MaxWSAddressLength, + &DataSize); + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Free the helper data and fail */ + RtlFreeHeap(SockPrivateHeap, 0, HelperData); + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Size of TDI Structures */ + HelperData->MinTDIAddressLength = HelperData->MinWSAddressLength + 6; + HelperData->MaxTDIAddressLength = HelperData->MaxWSAddressLength + 6; + + /* Read Delayed Acceptance Setting */ + DataSize = sizeof(DWORD); + ErrorCode = RegQueryValueExW(KeyHandle, + L"UseDelayedAcceptance", + NULL, + NULL, + (LPBYTE)&HelperData->UseDelayedAcceptance, + &DataSize); + + /* Use defalt if we failed */ + if (ErrorCode != NO_ERROR) HelperData->UseDelayedAcceptance = -1; + + /* Allocate Space for the Helper DLL Names */ + HelperDllName = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + MAX_PATH * sizeof(WCHAR)); + + /* Check for error */ + if (!HelperDllName) + { + /* Free the helper data and fail */ + RtlFreeHeap(SockPrivateHeap, 0, HelperData); + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Allocate space for the expanded version */ + FullHelperDllName = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + MAX_PATH * sizeof(WCHAR)); + + /* Check for error */ + if (!FullHelperDllName) + { + /* Free the helper data and fail */ + RtlFreeHeap(SockPrivateHeap, 0, HelperData); + RtlFreeHeap(SockPrivateHeap, 0, HelperDllName); + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Get the name of the Helper DLL*/ + DataSize = 512; + ErrorCode = RegQueryValueExW(KeyHandle, + L"HelperDllName", + NULL, + NULL, + (LPBYTE)HelperDllName, + &DataSize); + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Free the helper data and fail */ + RtlFreeHeap(SockPrivateHeap, 0, HelperData); + RtlFreeHeap(SockPrivateHeap, 0, HelperDllName); + RtlFreeHeap(SockPrivateHeap, 0, FullHelperDllName); + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Get the Full name, expanding Environment Strings */ + HelperDllNameSize = ExpandEnvironmentStringsW(HelperDllName, + FullHelperDllName, + MAX_PATH); + + /* Load the DLL */ + HelperData->hInstance = LoadLibraryW(FullHelperDllName); + + /* Free Buffers */ + RtlFreeHeap(SockPrivateHeap, 0, HelperDllName); + RtlFreeHeap(SockPrivateHeap, 0, FullHelperDllName); + + /* Return if we didn't Load it Properly */ + if (!HelperData->hInstance) + { + /* Free memory and fail */ + RtlFreeHeap(SockPrivateHeap, 0, HelperData); + RegCloseKey(KeyHandle); + return GetLastError(); + } + + /* Close Key */ + RegCloseKey(KeyHandle); + + /* Get the Pointers to the Helper Routines */ + HelperData->WSHOpenSocket = (PWSH_OPEN_SOCKET) + GetProcAddress(HelperData->hInstance, + "WSHOpenSocket"); + HelperData->WSHOpenSocket2 = (PWSH_OPEN_SOCKET2) + GetProcAddress(HelperData->hInstance, + "WSHOpenSocket2"); + HelperData->WSHJoinLeaf = (PWSH_JOIN_LEAF) + GetProcAddress(HelperData->hInstance, + "WSHJoinLeaf"); + HelperData->WSHNotify = (PWSH_NOTIFY) + GetProcAddress(HelperData->hInstance, "WSHNotify"); + HelperData->WSHGetSocketInformation = (PWSH_GET_SOCKET_INFORMATION) + GetProcAddress(HelperData->hInstance, + "WSHGetSocketInformation"); + HelperData->WSHSetSocketInformation = (PWSH_SET_SOCKET_INFORMATION) + GetProcAddress(HelperData->hInstance, + "WSHSetSocketInformation"); + HelperData->WSHGetSockaddrType = (PWSH_GET_SOCKADDR_TYPE) + GetProcAddress(HelperData->hInstance, + "WSHGetSockaddrType"); + HelperData->WSHGetWildcardSockaddr = (PWSH_GET_WILDCARD_SOCKADDR) + GetProcAddress(HelperData->hInstance, + "WSHGetWildcardSockaddr"); + HelperData->WSHGetBroadcastSockaddr = (PWSH_GET_BROADCAST_SOCKADDR) + GetProcAddress(HelperData->hInstance, + "WSHGetBroadcastSockaddr"); + HelperData->WSHAddressToString = (PWSH_ADDRESS_TO_STRING) + GetProcAddress(HelperData->hInstance, + "WSHAddressToString"); + HelperData->WSHStringToAddress = (PWSH_STRING_TO_ADDRESS) + GetProcAddress(HelperData->hInstance, + "WSHStringToAddress"); + HelperData->WSHIoctl = (PWSH_IOCTL) + GetProcAddress(HelperData->hInstance, "WSHIoctl"); + + /* Save the Mapping Structure and transport name */ + HelperData->Mapping = Mapping; + wcscpy(HelperData->TransportName, TransportName); + + /* Increment Reference Count */ + HelperData->RefCount = 1; + + /* Add it to our list */ + InsertHeadList(&SockHelperDllListHead, &HelperData->Helpers); + + /* Return Pointers */ + *HelperDllData = HelperData; + + /* Check if this one was already load it */ + Entry = HelperData->Helpers.Flink; + while (Entry != &SockHelperDllListHead) + { + /* Get the entry */ + HelperData = CONTAINING_RECORD(Entry, HELPER_DATA, Helpers); + + /* Move to the next one */ + Entry = Entry->Flink; + + /* Check if the names match */ + if (!wcscmp(HelperData->TransportName, (*HelperDllData)->TransportName)) + { + /* Remove this one */ + RemoveEntryList(&HelperData->Helpers); + SockDereferenceHelperDll(HelperData); + } + } + + /* Return success */ + return NO_ERROR; +} + +BOOL +WSPAPI +SockIsTripleInMapping(IN PWINSOCK_MAPPING Mapping, + IN INT AddressFamily, + OUT PBOOLEAN AfMatch, + IN INT SocketType, + OUT PBOOLEAN SockMatch, + IN INT Protocol, + OUT PBOOLEAN ProtoMatch) +{ + ULONG Row; + BOOLEAN FoundAf = FALSE, FoundProto = FALSE, FoundSocket = FALSE; + + /* Loop through Mapping to Find a matching one */ + for (Row = 0; Row < Mapping->Rows; Row++) + { + /* Check Address Family */ + if ((INT)Mapping->Mapping[Row].AddressFamily == AddressFamily) + { + /* Remember that we found it */ + FoundAf = TRUE; + } + + /* Check Socket Type */ + if ((INT)Mapping->Mapping[Row].SocketType == SocketType) + { + /* Remember that we found it */ + FoundSocket = TRUE; + } + + /* Check Protocol (SOCK_RAW and AF_NETBIOS can skip this check) */ + if (((INT)Mapping->Mapping[Row].SocketType == SocketType) || + (AddressFamily == AF_NETBIOS) || (SocketType == SOCK_RAW)) + { + /* Remember that we found it */ + FoundProto = TRUE; + } + + /* Check of all three values Match */ + if (FoundProto && FoundSocket && FoundAf) + { + /* Return success */ + *AfMatch = *SockMatch = *ProtoMatch = TRUE; + return TRUE; + } + } + + /* Return whatever we found */ + if (FoundAf) *AfMatch = TRUE; + if (FoundSocket) *SockMatch = TRUE; + if (FoundProto) *ProtoMatch = TRUE; + + /* Fail */ + return FALSE; +} + +INT +WSPAPI +SockNotifyHelperDll(IN PSOCKET_INFORMATION Socket, + IN DWORD Event) +{ + INT ErrorCode; + + /* See if this event matters */ + if (!(Socket->HelperEvents & Event)) return NO_ERROR; + + /* See if we have a helper... */ + if (!(Socket->HelperData)) return NO_ERROR; + + /* Get TDI handles */ + ErrorCode = SockGetTdiHandles(Socket); + if (ErrorCode != NO_ERROR) return ErrorCode; + + /* Call the notification */ + return Socket->HelperData->WSHNotify(Socket->HelperContext, + Socket->Handle, + Socket->TdiAddressHandle, + Socket->TdiConnectionHandle, + Event); +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +LIST_ENTRY SockHelperDllListHead; + +/* FUNCTIONS *****************************************************************/ + +VOID +WSPAPI +SockFreeHelperDll(IN PHELPER_DATA Helper) +{ + /* Free the DLL */ + FreeLibrary(Helper->hInstance); + + /* Free the mapping */ + RtlFreeHeap(SockPrivateHeap, 0, Helper->Mapping); + + /* Free the DLL Structure itself */ + RtlFreeHeap(SockPrivateHeap, 0, Helper); +} + +INT +WSPAPI +SockGetTdiName(PINT AddressFamily, + PINT SocketType, + PINT Protocol, + LPGUID ProviderId, + GROUP Group, + DWORD Flags, + PUNICODE_STRING TransportName, + PVOID *HelperDllContext, + PHELPER_DATA *HelperDllData, + PDWORD Events) +{ + PHELPER_DATA HelperData; + PWSTR Transports; + PWSTR Transport; + PWINSOCK_MAPPING Mapping; + PLIST_ENTRY Helpers; + BOOLEAN SharedLock = TRUE; + INT ErrorCode; + BOOLEAN AfMatch = FALSE, ProtoMatch = FALSE, SocketMatch = FALSE; + + /* Acquire global lock */ + SockAcquireRwLockShared(&SocketGlobalLock); + +TryAgain: + /* Check in our Current Loaded Helpers */ + for (Helpers = SockHelperDllListHead.Flink; + Helpers != &SockHelperDllListHead; + Helpers = Helpers->Flink) + { + /* Get the current helper */ + HelperData = CONTAINING_RECORD(Helpers, HELPER_DATA, Helpers); + + /* See if this Mapping works for us */ + if (SockIsTripleInMapping(HelperData->Mapping, + *AddressFamily, + &AfMatch, + *SocketType, + &SocketMatch, + *Protocol, + &ProtoMatch)) + { + /* Call the Helper Dll function get the Transport Name */ + if (!HelperData->WSHOpenSocket2) + { + if (!(Flags & WSA_FLAG_MULTIPOINT_ALL)) + { + /* DLL Doesn't support WSHOpenSocket2, call the old one */ + ErrorCode = HelperData->WSHOpenSocket(AddressFamily, + SocketType, + Protocol, + TransportName, + HelperDllContext, + Events); + } + else + { + /* Invalid flag */ + ErrorCode = WSAEINVAL; + } + } + else + { + /* Call the new WSHOpenSocket */ + ErrorCode = HelperData->WSHOpenSocket2(AddressFamily, + SocketType, + Protocol, + Group, + Flags, + TransportName, + HelperDllContext, + Events); + } + + /* Check for success */ + if (ErrorCode == NO_ERROR) + { + /* Reference the helper */ + InterlockedIncrement(&HelperData->RefCount); + + /* Check which lock we acquired */ + if (SharedLock) + { + /* Release the shared lock */ + SockReleaseRwLockShared(&SocketGlobalLock); + } + else + { + /* Release the acquired lock */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + } + + /* Return the Helper Pointers */ + *HelperDllData = HelperData; + return NO_ERROR; + } + + /* Check if we don't need a transport name */ + if ((*SocketType == SOCK_RAW) && (TransportName->Buffer)) + { + /* Free it */ + RtlFreeHeap(RtlGetProcessHeap(), 0, TransportName->Buffer); + TransportName->Buffer = NULL; + } + } + } + + /* We didn't find a match: try again with RW access */ + if (SharedLock) + { + /* Switch locks */ + SockReleaseRwLockShared(&SocketGlobalLock); + SockAcquireRwLockExclusive(&SocketGlobalLock); + + /* Parse the list again */ + SharedLock = FALSE; + goto TryAgain; + } + + /* Get the Transports available */ + ErrorCode = SockLoadTransportList(&Transports); + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + return ErrorCode; + } + + /* Loop through each transport until we find one that can satisfy us */ + for (Transport = Transports; *Transport; Transport += wcslen(Transport) + 1) + { + /* See what mapping this Transport supports */ + ErrorCode = SockLoadTransportMapping(Transport, &Mapping); + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Try the next one */ + continue; + } + + /* See if this Mapping works for us */ + if (SockIsTripleInMapping(Mapping, + *AddressFamily, + &AfMatch, + *SocketType, + &SocketMatch, + *Protocol, + &ProtoMatch)) + { + /* It does, so load the DLL associated with it */ + ErrorCode = SockLoadHelperDll(Transport, Mapping, &HelperData); + + /* Check for success */ + if (ErrorCode == NO_ERROR) + { + /* Call the Helper Dll function get the Transport Name */ + if (!HelperData->WSHOpenSocket2) + { + /* Check for invalid flag combo */ + if (!(Flags & WSA_FLAG_MULTIPOINT_ALL)) + { + /* DLL Doesn't support WSHOpenSocket2, call the old one */ + ErrorCode = HelperData->WSHOpenSocket(AddressFamily, + SocketType, + Protocol, + TransportName, + HelperDllContext, + Events); + } + else + { + /* Fail */ + ErrorCode = WSAEINVAL; + } + } + else + { + /* Call the newer function */ + ErrorCode = HelperData->WSHOpenSocket2(AddressFamily, + SocketType, + Protocol, + Group, + Flags, + TransportName, + HelperDllContext, + Events); + } + + /* Check for success */ + if (ErrorCode == NO_ERROR) + { + /* Reference the helper */ + InterlockedIncrement(&HelperData->RefCount); + + /* Release the lock and free the transports */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + RtlFreeHeap(SockPrivateHeap, 0, Transports); + + /* Return the Helper Pointer */ + *HelperDllData = HelperData; + return NO_ERROR; + } + + /* Check if we don't need a transport name */ + if ((*SocketType == SOCK_RAW) && (TransportName->Buffer)) + { + /* Free it */ + RtlFreeHeap(RtlGetProcessHeap(), 0, TransportName->Buffer); + TransportName->Buffer = NULL; + } + + /* Try again */ + continue; + } + } + + /* Free the mapping and continue */ + RtlFreeHeap(SockPrivateHeap, 0, Mapping); + } + + /* Release the lock and free the transport list */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + RtlFreeHeap(SockPrivateHeap, 0, Transports); + + /* Check why we didn't find a match */ + if (!AfMatch) return WSAEAFNOSUPPORT; + if (!ProtoMatch) return WSAEPROTONOSUPPORT; + if (!SocketMatch) return WSAESOCKTNOSUPPORT; + + /* The comination itself was invalid */ + return WSAEINVAL; +} + +INT +WSPAPI +SockLoadTransportMapping(IN PWSTR TransportName, + OUT PWINSOCK_MAPPING *Mapping) +{ + PWSTR TransportKey; + HKEY KeyHandle; + INT ErrorCode; + ULONG MappingSize = 0; + + /* Allocate a Buffer */ + TransportKey = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + MAX_PATH * sizeof(WCHAR)); + /* Check for error */ + if (!TransportKey) return ERROR_NOT_ENOUGH_MEMORY; + + /* Generate the right key name */ + wcscpy(TransportKey, L"System\\CurrentControlSet\\Services\\"); + wcscat(TransportKey, TransportName); + wcscat(TransportKey, L"\\Parameters\\Winsock"); + + /* Open the Key */ + ErrorCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE, + TransportKey, + 0, + KEY_READ, + &KeyHandle); + + /* We don't need the Transport Key anymore */ + RtlFreeHeap(SockPrivateHeap, 0, TransportKey); + + /* Check for error */ + if ((ErrorCode != ERROR_MORE_DATA) && (ErrorCode != NO_ERROR)) + { + /* Close key and fail */ + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Find out how much space we need for the Mapping */ + ErrorCode = RegQueryValueExW(KeyHandle, + L"Mapping", + NULL, + NULL, + NULL, + &MappingSize); + + /* Check for error */ + if ((ErrorCode != ERROR_MORE_DATA) && (ErrorCode != NO_ERROR)) + { + /* Close key and fail */ + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Allocate Memory for the Mapping */ + *Mapping = SockAllocateHeapRoutine(SockPrivateHeap, 0, MappingSize); + + /* Check for error */ + if (!(*Mapping)) + { + /* Close key and fail */ + RegCloseKey(KeyHandle); + return ERROR_NOT_ENOUGH_MEMORY; + } + + /* Read the Mapping */ + ErrorCode = RegQueryValueExW(KeyHandle, + L"Mapping", + NULL, + NULL, + (LPBYTE)*Mapping, + &MappingSize); + + /* Check for error */ + if ((ErrorCode != ERROR_MORE_DATA) && (ErrorCode != NO_ERROR)) + { + /* Close key and fail */ + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Close key and return */ + RegCloseKey(KeyHandle); + return NO_ERROR; +} + +INT +WSPAPI +SockLoadHelperDll(PWSTR TransportName, + PWINSOCK_MAPPING Mapping, + PHELPER_DATA *HelperDllData) +{ + PHELPER_DATA HelperData; + PWSTR HelperDllName; + PWSTR FullHelperDllName; + ULONG HelperDllNameSize; + PWSTR HelperKey; + HKEY KeyHandle; + ULONG DataSize; + INT ErrorCode; + PLIST_ENTRY Entry; + + /* Allocate space for the Helper Structure and TransportName */ + HelperData = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + sizeof(*HelperData) + + (DWORD)(wcslen(TransportName) + 1) * + sizeof(WCHAR)); + + /* Check for error */ + if (!HelperData) return ERROR_NOT_ENOUGH_MEMORY; + + /* Allocate Space for the Helper DLL Key */ + HelperKey = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + MAX_PATH * sizeof(WCHAR)); + + /* Check for error */ + if (!HelperKey) + { + RtlFreeHeap(SockPrivateHeap, 0, HelperData); + return ERROR_NOT_ENOUGH_MEMORY; + } + + /* Generate the right key name */ + wcscpy(HelperKey, L"System\\CurrentControlSet\\Services\\"); + wcscat(HelperKey, TransportName); + wcscat(HelperKey, L"\\Parameters\\Winsock"); + + /* Open the Key */ + ErrorCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE, + HelperKey, + 0, + KEY_READ, + &KeyHandle); + + /* Free Buffer */ + RtlFreeHeap(SockPrivateHeap, 0, HelperKey); + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Free the helper data and fail */ + RtlFreeHeap(SockPrivateHeap, 0, HelperData); + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Read Minimum size of Sockaddr Structures */ + DataSize = sizeof(HelperData->MinWSAddressLength); + RegQueryValueExW(KeyHandle, + L"MinSockaddrLength", + NULL, + NULL, + (LPBYTE)&HelperData->MinWSAddressLength, + &DataSize); + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Free the helper data and fail */ + RtlFreeHeap(SockPrivateHeap, 0, HelperData); + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Read Maximum size of Sockaddr Structures */ + DataSize = sizeof(HelperData->MinWSAddressLength); + RegQueryValueExW(KeyHandle, + L"MaxSockaddrLength", + NULL, + NULL, + (LPBYTE)&HelperData->MaxWSAddressLength, + &DataSize); + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Free the helper data and fail */ + RtlFreeHeap(SockPrivateHeap, 0, HelperData); + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Size of TDI Structures */ + HelperData->MinTDIAddressLength = HelperData->MinWSAddressLength + 6; + HelperData->MaxTDIAddressLength = HelperData->MaxWSAddressLength + 6; + + /* Read Delayed Acceptance Setting */ + DataSize = sizeof(DWORD); + ErrorCode = RegQueryValueExW(KeyHandle, + L"UseDelayedAcceptance", + NULL, + NULL, + (LPBYTE)&HelperData->UseDelayedAcceptance, + &DataSize); + + /* Use defalt if we failed */ + if (ErrorCode != NO_ERROR) HelperData->UseDelayedAcceptance = -1; + + /* Allocate Space for the Helper DLL Names */ + HelperDllName = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + MAX_PATH * sizeof(WCHAR)); + + /* Check for error */ + if (!HelperDllName) + { + /* Free the helper data and fail */ + RtlFreeHeap(SockPrivateHeap, 0, HelperData); + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Allocate space for the expanded version */ + FullHelperDllName = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + MAX_PATH * sizeof(WCHAR)); + + /* Check for error */ + if (!FullHelperDllName) + { + /* Free the helper data and fail */ + RtlFreeHeap(SockPrivateHeap, 0, HelperData); + RtlFreeHeap(SockPrivateHeap, 0, HelperDllName); + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Get the name of the Helper DLL*/ + DataSize = 512; + ErrorCode = RegQueryValueExW(KeyHandle, + L"HelperDllName", + NULL, + NULL, + (LPBYTE)HelperDllName, + &DataSize); + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Free the helper data and fail */ + RtlFreeHeap(SockPrivateHeap, 0, HelperData); + RtlFreeHeap(SockPrivateHeap, 0, HelperDllName); + RtlFreeHeap(SockPrivateHeap, 0, FullHelperDllName); + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Get the Full name, expanding Environment Strings */ + HelperDllNameSize = ExpandEnvironmentStringsW(HelperDllName, + FullHelperDllName, + MAX_PATH); + + /* Load the DLL */ + HelperData->hInstance = LoadLibraryW(FullHelperDllName); + + /* Free Buffers */ + RtlFreeHeap(SockPrivateHeap, 0, HelperDllName); + RtlFreeHeap(SockPrivateHeap, 0, FullHelperDllName); + + /* Return if we didn't Load it Properly */ + if (!HelperData->hInstance) + { + /* Free memory and fail */ + RtlFreeHeap(SockPrivateHeap, 0, HelperData); + RegCloseKey(KeyHandle); + return GetLastError(); + } + + /* Close Key */ + RegCloseKey(KeyHandle); + + /* Get the Pointers to the Helper Routines */ + HelperData->WSHOpenSocket = (PWSH_OPEN_SOCKET) + GetProcAddress(HelperData->hInstance, + "WSHOpenSocket"); + HelperData->WSHOpenSocket2 = (PWSH_OPEN_SOCKET2) + GetProcAddress(HelperData->hInstance, + "WSHOpenSocket2"); + HelperData->WSHJoinLeaf = (PWSH_JOIN_LEAF) + GetProcAddress(HelperData->hInstance, + "WSHJoinLeaf"); + HelperData->WSHNotify = (PWSH_NOTIFY) + GetProcAddress(HelperData->hInstance, "WSHNotify"); + HelperData->WSHGetSocketInformation = (PWSH_GET_SOCKET_INFORMATION) + GetProcAddress(HelperData->hInstance, + "WSHGetSocketInformation"); + HelperData->WSHSetSocketInformation = (PWSH_SET_SOCKET_INFORMATION) + GetProcAddress(HelperData->hInstance, + "WSHSetSocketInformation"); + HelperData->WSHGetSockaddrType = (PWSH_GET_SOCKADDR_TYPE) + GetProcAddress(HelperData->hInstance, + "WSHGetSockaddrType"); + HelperData->WSHGetWildcardSockaddr = (PWSH_GET_WILDCARD_SOCKADDR) + GetProcAddress(HelperData->hInstance, + "WSHGetWildcardSockaddr"); + HelperData->WSHGetBroadcastSockaddr = (PWSH_GET_BROADCAST_SOCKADDR) + GetProcAddress(HelperData->hInstance, + "WSHGetBroadcastSockaddr"); + HelperData->WSHAddressToString = (PWSH_ADDRESS_TO_STRING) + GetProcAddress(HelperData->hInstance, + "WSHAddressToString"); + HelperData->WSHStringToAddress = (PWSH_STRING_TO_ADDRESS) + GetProcAddress(HelperData->hInstance, + "WSHStringToAddress"); + HelperData->WSHIoctl = (PWSH_IOCTL) + GetProcAddress(HelperData->hInstance, "WSHIoctl"); + + /* Save the Mapping Structure and transport name */ + HelperData->Mapping = Mapping; + wcscpy(HelperData->TransportName, TransportName); + + /* Increment Reference Count */ + HelperData->RefCount = 1; + + /* Add it to our list */ + InsertHeadList(&SockHelperDllListHead, &HelperData->Helpers); + + /* Return Pointers */ + *HelperDllData = HelperData; + + /* Check if this one was already load it */ + Entry = HelperData->Helpers.Flink; + while (Entry != &SockHelperDllListHead) + { + /* Get the entry */ + HelperData = CONTAINING_RECORD(Entry, HELPER_DATA, Helpers); + + /* Move to the next one */ + Entry = Entry->Flink; + + /* Check if the names match */ + if (!wcscmp(HelperData->TransportName, (*HelperDllData)->TransportName)) + { + /* Remove this one */ + RemoveEntryList(&HelperData->Helpers); + SockDereferenceHelperDll(HelperData); + } + } + + /* Return success */ + return NO_ERROR; +} + +BOOL +WSPAPI +SockIsTripleInMapping(IN PWINSOCK_MAPPING Mapping, + IN INT AddressFamily, + OUT PBOOLEAN AfMatch, + IN INT SocketType, + OUT PBOOLEAN SockMatch, + IN INT Protocol, + OUT PBOOLEAN ProtoMatch) +{ + ULONG Row; + BOOLEAN FoundAf = FALSE, FoundProto = FALSE, FoundSocket = FALSE; + + /* Loop through Mapping to Find a matching one */ + for (Row = 0; Row < Mapping->Rows; Row++) + { + /* Check Address Family */ + if ((INT)Mapping->Mapping[Row].AddressFamily == AddressFamily) + { + /* Remember that we found it */ + FoundAf = TRUE; + } + + /* Check Socket Type */ + if ((INT)Mapping->Mapping[Row].SocketType == SocketType) + { + /* Remember that we found it */ + FoundSocket = TRUE; + } + + /* Check Protocol (SOCK_RAW and AF_NETBIOS can skip this check) */ + if (((INT)Mapping->Mapping[Row].SocketType == SocketType) || + (AddressFamily == AF_NETBIOS) || (SocketType == SOCK_RAW)) + { + /* Remember that we found it */ + FoundProto = TRUE; + } + + /* Check of all three values Match */ + if (FoundProto && FoundSocket && FoundAf) + { + /* Return success */ + *AfMatch = *SockMatch = *ProtoMatch = TRUE; + return TRUE; + } + } + + /* Return whatever we found */ + if (FoundAf) *AfMatch = TRUE; + if (FoundSocket) *SockMatch = TRUE; + if (FoundProto) *ProtoMatch = TRUE; + + /* Fail */ + return FALSE; +} + +INT +WSPAPI +SockNotifyHelperDll(IN PSOCKET_INFORMATION Socket, + IN DWORD Event) +{ + INT ErrorCode; + + /* See if this event matters */ + if (!(Socket->HelperEvents & Event)) return NO_ERROR; + + /* See if we have a helper... */ + if (!(Socket->HelperData)) return NO_ERROR; + + /* Get TDI handles */ + ErrorCode = SockGetTdiHandles(Socket); + if (ErrorCode != NO_ERROR) return ErrorCode; + + /* Call the notification */ + return Socket->HelperData->WSHNotify(Socket->HelperContext, + Socket->Handle, + Socket->TdiAddressHandle, + Socket->TdiConnectionHandle, + Event); +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +LIST_ENTRY SockHelperDllListHead; + +/* FUNCTIONS *****************************************************************/ + +VOID +WSPAPI +SockFreeHelperDll(IN PHELPER_DATA Helper) +{ + /* Free the DLL */ + FreeLibrary(Helper->hInstance); + + /* Free the mapping */ + RtlFreeHeap(SockPrivateHeap, 0, Helper->Mapping); + + /* Free the DLL Structure itself */ + RtlFreeHeap(SockPrivateHeap, 0, Helper); +} + +INT +WSPAPI +SockGetTdiName(PINT AddressFamily, + PINT SocketType, + PINT Protocol, + LPGUID ProviderId, + GROUP Group, + DWORD Flags, + PUNICODE_STRING TransportName, + PVOID *HelperDllContext, + PHELPER_DATA *HelperDllData, + PDWORD Events) +{ + PHELPER_DATA HelperData; + PWSTR Transports; + PWSTR Transport; + PWINSOCK_MAPPING Mapping; + PLIST_ENTRY Helpers; + BOOLEAN SharedLock = TRUE; + INT ErrorCode; + BOOLEAN AfMatch = FALSE, ProtoMatch = FALSE, SocketMatch = FALSE; + + /* Acquire global lock */ + SockAcquireRwLockShared(&SocketGlobalLock); + +TryAgain: + /* Check in our Current Loaded Helpers */ + for (Helpers = SockHelperDllListHead.Flink; + Helpers != &SockHelperDllListHead; + Helpers = Helpers->Flink) + { + /* Get the current helper */ + HelperData = CONTAINING_RECORD(Helpers, HELPER_DATA, Helpers); + + /* See if this Mapping works for us */ + if (SockIsTripleInMapping(HelperData->Mapping, + *AddressFamily, + &AfMatch, + *SocketType, + &SocketMatch, + *Protocol, + &ProtoMatch)) + { + /* Call the Helper Dll function get the Transport Name */ + if (!HelperData->WSHOpenSocket2) + { + if (!(Flags & WSA_FLAG_MULTIPOINT_ALL)) + { + /* DLL Doesn't support WSHOpenSocket2, call the old one */ + ErrorCode = HelperData->WSHOpenSocket(AddressFamily, + SocketType, + Protocol, + TransportName, + HelperDllContext, + Events); + } + else + { + /* Invalid flag */ + ErrorCode = WSAEINVAL; + } + } + else + { + /* Call the new WSHOpenSocket */ + ErrorCode = HelperData->WSHOpenSocket2(AddressFamily, + SocketType, + Protocol, + Group, + Flags, + TransportName, + HelperDllContext, + Events); + } + + /* Check for success */ + if (ErrorCode == NO_ERROR) + { + /* Reference the helper */ + InterlockedIncrement(&HelperData->RefCount); + + /* Check which lock we acquired */ + if (SharedLock) + { + /* Release the shared lock */ + SockReleaseRwLockShared(&SocketGlobalLock); + } + else + { + /* Release the acquired lock */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + } + + /* Return the Helper Pointers */ + *HelperDllData = HelperData; + return NO_ERROR; + } + + /* Check if we don't need a transport name */ + if ((*SocketType == SOCK_RAW) && (TransportName->Buffer)) + { + /* Free it */ + RtlFreeHeap(RtlGetProcessHeap(), 0, TransportName->Buffer); + TransportName->Buffer = NULL; + } + } + } + + /* We didn't find a match: try again with RW access */ + if (SharedLock) + { + /* Switch locks */ + SockReleaseRwLockShared(&SocketGlobalLock); + SockAcquireRwLockExclusive(&SocketGlobalLock); + + /* Parse the list again */ + SharedLock = FALSE; + goto TryAgain; + } + + /* Get the Transports available */ + ErrorCode = SockLoadTransportList(&Transports); + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + return ErrorCode; + } + + /* Loop through each transport until we find one that can satisfy us */ + for (Transport = Transports; *Transport; Transport += wcslen(Transport) + 1) + { + /* See what mapping this Transport supports */ + ErrorCode = SockLoadTransportMapping(Transport, &Mapping); + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Try the next one */ + continue; + } + + /* See if this Mapping works for us */ + if (SockIsTripleInMapping(Mapping, + *AddressFamily, + &AfMatch, + *SocketType, + &SocketMatch, + *Protocol, + &ProtoMatch)) + { + /* It does, so load the DLL associated with it */ + ErrorCode = SockLoadHelperDll(Transport, Mapping, &HelperData); + + /* Check for success */ + if (ErrorCode == NO_ERROR) + { + /* Call the Helper Dll function get the Transport Name */ + if (!HelperData->WSHOpenSocket2) + { + /* Check for invalid flag combo */ + if (!(Flags & WSA_FLAG_MULTIPOINT_ALL)) + { + /* DLL Doesn't support WSHOpenSocket2, call the old one */ + ErrorCode = HelperData->WSHOpenSocket(AddressFamily, + SocketType, + Protocol, + TransportName, + HelperDllContext, + Events); + } + else + { + /* Fail */ + ErrorCode = WSAEINVAL; + } + } + else + { + /* Call the newer function */ + ErrorCode = HelperData->WSHOpenSocket2(AddressFamily, + SocketType, + Protocol, + Group, + Flags, + TransportName, + HelperDllContext, + Events); + } + + /* Check for success */ + if (ErrorCode == NO_ERROR) + { + /* Reference the helper */ + InterlockedIncrement(&HelperData->RefCount); + + /* Release the lock and free the transports */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + RtlFreeHeap(SockPrivateHeap, 0, Transports); + + /* Return the Helper Pointer */ + *HelperDllData = HelperData; + return NO_ERROR; + } + + /* Check if we don't need a transport name */ + if ((*SocketType == SOCK_RAW) && (TransportName->Buffer)) + { + /* Free it */ + RtlFreeHeap(RtlGetProcessHeap(), 0, TransportName->Buffer); + TransportName->Buffer = NULL; + } + + /* Try again */ + continue; + } + } + + /* Free the mapping and continue */ + RtlFreeHeap(SockPrivateHeap, 0, Mapping); + } + + /* Release the lock and free the transport list */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + RtlFreeHeap(SockPrivateHeap, 0, Transports); + + /* Check why we didn't find a match */ + if (!AfMatch) return WSAEAFNOSUPPORT; + if (!ProtoMatch) return WSAEPROTONOSUPPORT; + if (!SocketMatch) return WSAESOCKTNOSUPPORT; + + /* The comination itself was invalid */ + return WSAEINVAL; +} + +INT +WSPAPI +SockLoadTransportMapping(IN PWSTR TransportName, + OUT PWINSOCK_MAPPING *Mapping) +{ + PWSTR TransportKey; + HKEY KeyHandle; + INT ErrorCode; + ULONG MappingSize = 0; + + /* Allocate a Buffer */ + TransportKey = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + MAX_PATH * sizeof(WCHAR)); + /* Check for error */ + if (!TransportKey) return ERROR_NOT_ENOUGH_MEMORY; + + /* Generate the right key name */ + wcscpy(TransportKey, L"System\\CurrentControlSet\\Services\\"); + wcscat(TransportKey, TransportName); + wcscat(TransportKey, L"\\Parameters\\Winsock"); + + /* Open the Key */ + ErrorCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE, + TransportKey, + 0, + KEY_READ, + &KeyHandle); + + /* We don't need the Transport Key anymore */ + RtlFreeHeap(SockPrivateHeap, 0, TransportKey); + + /* Check for error */ + if ((ErrorCode != ERROR_MORE_DATA) && (ErrorCode != NO_ERROR)) + { + /* Close key and fail */ + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Find out how much space we need for the Mapping */ + ErrorCode = RegQueryValueExW(KeyHandle, + L"Mapping", + NULL, + NULL, + NULL, + &MappingSize); + + /* Check for error */ + if ((ErrorCode != ERROR_MORE_DATA) && (ErrorCode != NO_ERROR)) + { + /* Close key and fail */ + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Allocate Memory for the Mapping */ + *Mapping = SockAllocateHeapRoutine(SockPrivateHeap, 0, MappingSize); + + /* Check for error */ + if (!(*Mapping)) + { + /* Close key and fail */ + RegCloseKey(KeyHandle); + return ERROR_NOT_ENOUGH_MEMORY; + } + + /* Read the Mapping */ + ErrorCode = RegQueryValueExW(KeyHandle, + L"Mapping", + NULL, + NULL, + (LPBYTE)*Mapping, + &MappingSize); + + /* Check for error */ + if ((ErrorCode != ERROR_MORE_DATA) && (ErrorCode != NO_ERROR)) + { + /* Close key and fail */ + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Close key and return */ + RegCloseKey(KeyHandle); + return NO_ERROR; +} + +INT +WSPAPI +SockLoadHelperDll(PWSTR TransportName, + PWINSOCK_MAPPING Mapping, + PHELPER_DATA *HelperDllData) +{ + PHELPER_DATA HelperData; + PWSTR HelperDllName; + PWSTR FullHelperDllName; + ULONG HelperDllNameSize; + PWSTR HelperKey; + HKEY KeyHandle; + ULONG DataSize; + INT ErrorCode; + PLIST_ENTRY Entry; + + /* Allocate space for the Helper Structure and TransportName */ + HelperData = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + sizeof(*HelperData) + + (DWORD)(wcslen(TransportName) + 1) * + sizeof(WCHAR)); + + /* Check for error */ + if (!HelperData) return ERROR_NOT_ENOUGH_MEMORY; + + /* Allocate Space for the Helper DLL Key */ + HelperKey = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + MAX_PATH * sizeof(WCHAR)); + + /* Check for error */ + if (!HelperKey) + { + RtlFreeHeap(SockPrivateHeap, 0, HelperData); + return ERROR_NOT_ENOUGH_MEMORY; + } + + /* Generate the right key name */ + wcscpy(HelperKey, L"System\\CurrentControlSet\\Services\\"); + wcscat(HelperKey, TransportName); + wcscat(HelperKey, L"\\Parameters\\Winsock"); + + /* Open the Key */ + ErrorCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE, + HelperKey, + 0, + KEY_READ, + &KeyHandle); + + /* Free Buffer */ + RtlFreeHeap(SockPrivateHeap, 0, HelperKey); + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Free the helper data and fail */ + RtlFreeHeap(SockPrivateHeap, 0, HelperData); + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Read Minimum size of Sockaddr Structures */ + DataSize = sizeof(HelperData->MinWSAddressLength); + RegQueryValueExW(KeyHandle, + L"MinSockaddrLength", + NULL, + NULL, + (LPBYTE)&HelperData->MinWSAddressLength, + &DataSize); + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Free the helper data and fail */ + RtlFreeHeap(SockPrivateHeap, 0, HelperData); + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Read Maximum size of Sockaddr Structures */ + DataSize = sizeof(HelperData->MinWSAddressLength); + RegQueryValueExW(KeyHandle, + L"MaxSockaddrLength", + NULL, + NULL, + (LPBYTE)&HelperData->MaxWSAddressLength, + &DataSize); + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Free the helper data and fail */ + RtlFreeHeap(SockPrivateHeap, 0, HelperData); + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Size of TDI Structures */ + HelperData->MinTDIAddressLength = HelperData->MinWSAddressLength + 6; + HelperData->MaxTDIAddressLength = HelperData->MaxWSAddressLength + 6; + + /* Read Delayed Acceptance Setting */ + DataSize = sizeof(DWORD); + ErrorCode = RegQueryValueExW(KeyHandle, + L"UseDelayedAcceptance", + NULL, + NULL, + (LPBYTE)&HelperData->UseDelayedAcceptance, + &DataSize); + + /* Use defalt if we failed */ + if (ErrorCode != NO_ERROR) HelperData->UseDelayedAcceptance = -1; + + /* Allocate Space for the Helper DLL Names */ + HelperDllName = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + MAX_PATH * sizeof(WCHAR)); + + /* Check for error */ + if (!HelperDllName) + { + /* Free the helper data and fail */ + RtlFreeHeap(SockPrivateHeap, 0, HelperData); + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Allocate space for the expanded version */ + FullHelperDllName = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + MAX_PATH * sizeof(WCHAR)); + + /* Check for error */ + if (!FullHelperDllName) + { + /* Free the helper data and fail */ + RtlFreeHeap(SockPrivateHeap, 0, HelperData); + RtlFreeHeap(SockPrivateHeap, 0, HelperDllName); + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Get the name of the Helper DLL*/ + DataSize = 512; + ErrorCode = RegQueryValueExW(KeyHandle, + L"HelperDllName", + NULL, + NULL, + (LPBYTE)HelperDllName, + &DataSize); + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Free the helper data and fail */ + RtlFreeHeap(SockPrivateHeap, 0, HelperData); + RtlFreeHeap(SockPrivateHeap, 0, HelperDllName); + RtlFreeHeap(SockPrivateHeap, 0, FullHelperDllName); + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Get the Full name, expanding Environment Strings */ + HelperDllNameSize = ExpandEnvironmentStringsW(HelperDllName, + FullHelperDllName, + MAX_PATH); + + /* Load the DLL */ + HelperData->hInstance = LoadLibraryW(FullHelperDllName); + + /* Free Buffers */ + RtlFreeHeap(SockPrivateHeap, 0, HelperDllName); + RtlFreeHeap(SockPrivateHeap, 0, FullHelperDllName); + + /* Return if we didn't Load it Properly */ + if (!HelperData->hInstance) + { + /* Free memory and fail */ + RtlFreeHeap(SockPrivateHeap, 0, HelperData); + RegCloseKey(KeyHandle); + return GetLastError(); + } + + /* Close Key */ + RegCloseKey(KeyHandle); + + /* Get the Pointers to the Helper Routines */ + HelperData->WSHOpenSocket = (PWSH_OPEN_SOCKET) + GetProcAddress(HelperData->hInstance, + "WSHOpenSocket"); + HelperData->WSHOpenSocket2 = (PWSH_OPEN_SOCKET2) + GetProcAddress(HelperData->hInstance, + "WSHOpenSocket2"); + HelperData->WSHJoinLeaf = (PWSH_JOIN_LEAF) + GetProcAddress(HelperData->hInstance, + "WSHJoinLeaf"); + HelperData->WSHNotify = (PWSH_NOTIFY) + GetProcAddress(HelperData->hInstance, "WSHNotify"); + HelperData->WSHGetSocketInformation = (PWSH_GET_SOCKET_INFORMATION) + GetProcAddress(HelperData->hInstance, + "WSHGetSocketInformation"); + HelperData->WSHSetSocketInformation = (PWSH_SET_SOCKET_INFORMATION) + GetProcAddress(HelperData->hInstance, + "WSHSetSocketInformation"); + HelperData->WSHGetSockaddrType = (PWSH_GET_SOCKADDR_TYPE) + GetProcAddress(HelperData->hInstance, + "WSHGetSockaddrType"); + HelperData->WSHGetWildcardSockaddr = (PWSH_GET_WILDCARD_SOCKADDR) + GetProcAddress(HelperData->hInstance, + "WSHGetWildcardSockaddr"); + HelperData->WSHGetBroadcastSockaddr = (PWSH_GET_BROADCAST_SOCKADDR) + GetProcAddress(HelperData->hInstance, + "WSHGetBroadcastSockaddr"); + HelperData->WSHAddressToString = (PWSH_ADDRESS_TO_STRING) + GetProcAddress(HelperData->hInstance, + "WSHAddressToString"); + HelperData->WSHStringToAddress = (PWSH_STRING_TO_ADDRESS) + GetProcAddress(HelperData->hInstance, + "WSHStringToAddress"); + HelperData->WSHIoctl = (PWSH_IOCTL) + GetProcAddress(HelperData->hInstance, "WSHIoctl"); + + /* Save the Mapping Structure and transport name */ + HelperData->Mapping = Mapping; + wcscpy(HelperData->TransportName, TransportName); + + /* Increment Reference Count */ + HelperData->RefCount = 1; + + /* Add it to our list */ + InsertHeadList(&SockHelperDllListHead, &HelperData->Helpers); + + /* Return Pointers */ + *HelperDllData = HelperData; + + /* Check if this one was already load it */ + Entry = HelperData->Helpers.Flink; + while (Entry != &SockHelperDllListHead) + { + /* Get the entry */ + HelperData = CONTAINING_RECORD(Entry, HELPER_DATA, Helpers); + + /* Move to the next one */ + Entry = Entry->Flink; + + /* Check if the names match */ + if (!wcscmp(HelperData->TransportName, (*HelperDllData)->TransportName)) + { + /* Remove this one */ + RemoveEntryList(&HelperData->Helpers); + SockDereferenceHelperDll(HelperData); + } + } + + /* Return success */ + return NO_ERROR; +} + +BOOL +WSPAPI +SockIsTripleInMapping(IN PWINSOCK_MAPPING Mapping, + IN INT AddressFamily, + OUT PBOOLEAN AfMatch, + IN INT SocketType, + OUT PBOOLEAN SockMatch, + IN INT Protocol, + OUT PBOOLEAN ProtoMatch) +{ + ULONG Row; + BOOLEAN FoundAf = FALSE, FoundProto = FALSE, FoundSocket = FALSE; + + /* Loop through Mapping to Find a matching one */ + for (Row = 0; Row < Mapping->Rows; Row++) + { + /* Check Address Family */ + if ((INT)Mapping->Mapping[Row].AddressFamily == AddressFamily) + { + /* Remember that we found it */ + FoundAf = TRUE; + } + + /* Check Socket Type */ + if ((INT)Mapping->Mapping[Row].SocketType == SocketType) + { + /* Remember that we found it */ + FoundSocket = TRUE; + } + + /* Check Protocol (SOCK_RAW and AF_NETBIOS can skip this check) */ + if (((INT)Mapping->Mapping[Row].SocketType == SocketType) || + (AddressFamily == AF_NETBIOS) || (SocketType == SOCK_RAW)) + { + /* Remember that we found it */ + FoundProto = TRUE; + } + + /* Check of all three values Match */ + if (FoundProto && FoundSocket && FoundAf) + { + /* Return success */ + *AfMatch = *SockMatch = *ProtoMatch = TRUE; + return TRUE; + } + } + + /* Return whatever we found */ + if (FoundAf) *AfMatch = TRUE; + if (FoundSocket) *SockMatch = TRUE; + if (FoundProto) *ProtoMatch = TRUE; + + /* Fail */ + return FALSE; +} + +INT +WSPAPI +SockNotifyHelperDll(IN PSOCKET_INFORMATION Socket, + IN DWORD Event) +{ + INT ErrorCode; + + /* See if this event matters */ + if (!(Socket->HelperEvents & Event)) return NO_ERROR; + + /* See if we have a helper... */ + if (!(Socket->HelperData)) return NO_ERROR; + + /* Get TDI handles */ + ErrorCode = SockGetTdiHandles(Socket); + if (ErrorCode != NO_ERROR) return ErrorCode; + + /* Call the notification */ + return Socket->HelperData->WSHNotify(Socket->HelperContext, + Socket->Handle, + Socket->TdiAddressHandle, + Socket->TdiConnectionHandle, + Event); +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +LIST_ENTRY SockHelperDllListHead; + +/* FUNCTIONS *****************************************************************/ + +VOID +WSPAPI +SockFreeHelperDll(IN PHELPER_DATA Helper) +{ + /* Free the DLL */ + FreeLibrary(Helper->hInstance); + + /* Free the mapping */ + RtlFreeHeap(SockPrivateHeap, 0, Helper->Mapping); + + /* Free the DLL Structure itself */ + RtlFreeHeap(SockPrivateHeap, 0, Helper); +} + +INT +WSPAPI +SockGetTdiName(PINT AddressFamily, + PINT SocketType, + PINT Protocol, + LPGUID ProviderId, + GROUP Group, + DWORD Flags, + PUNICODE_STRING TransportName, + PVOID *HelperDllContext, + PHELPER_DATA *HelperDllData, + PDWORD Events) +{ + PHELPER_DATA HelperData; + PWSTR Transports; + PWSTR Transport; + PWINSOCK_MAPPING Mapping; + PLIST_ENTRY Helpers; + BOOLEAN SharedLock = TRUE; + INT ErrorCode; + BOOLEAN AfMatch = FALSE, ProtoMatch = FALSE, SocketMatch = FALSE; + + /* Acquire global lock */ + SockAcquireRwLockShared(&SocketGlobalLock); + +TryAgain: + /* Check in our Current Loaded Helpers */ + for (Helpers = SockHelperDllListHead.Flink; + Helpers != &SockHelperDllListHead; + Helpers = Helpers->Flink) + { + /* Get the current helper */ + HelperData = CONTAINING_RECORD(Helpers, HELPER_DATA, Helpers); + + /* See if this Mapping works for us */ + if (SockIsTripleInMapping(HelperData->Mapping, + *AddressFamily, + &AfMatch, + *SocketType, + &SocketMatch, + *Protocol, + &ProtoMatch)) + { + /* Call the Helper Dll function get the Transport Name */ + if (!HelperData->WSHOpenSocket2) + { + if (!(Flags & WSA_FLAG_MULTIPOINT_ALL)) + { + /* DLL Doesn't support WSHOpenSocket2, call the old one */ + ErrorCode = HelperData->WSHOpenSocket(AddressFamily, + SocketType, + Protocol, + TransportName, + HelperDllContext, + Events); + } + else + { + /* Invalid flag */ + ErrorCode = WSAEINVAL; + } + } + else + { + /* Call the new WSHOpenSocket */ + ErrorCode = HelperData->WSHOpenSocket2(AddressFamily, + SocketType, + Protocol, + Group, + Flags, + TransportName, + HelperDllContext, + Events); + } + + /* Check for success */ + if (ErrorCode == NO_ERROR) + { + /* Reference the helper */ + InterlockedIncrement(&HelperData->RefCount); + + /* Check which lock we acquired */ + if (SharedLock) + { + /* Release the shared lock */ + SockReleaseRwLockShared(&SocketGlobalLock); + } + else + { + /* Release the acquired lock */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + } + + /* Return the Helper Pointers */ + *HelperDllData = HelperData; + return NO_ERROR; + } + + /* Check if we don't need a transport name */ + if ((*SocketType == SOCK_RAW) && (TransportName->Buffer)) + { + /* Free it */ + RtlFreeHeap(RtlGetProcessHeap(), 0, TransportName->Buffer); + TransportName->Buffer = NULL; + } + } + } + + /* We didn't find a match: try again with RW access */ + if (SharedLock) + { + /* Switch locks */ + SockReleaseRwLockShared(&SocketGlobalLock); + SockAcquireRwLockExclusive(&SocketGlobalLock); + + /* Parse the list again */ + SharedLock = FALSE; + goto TryAgain; + } + + /* Get the Transports available */ + ErrorCode = SockLoadTransportList(&Transports); + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + return ErrorCode; + } + + /* Loop through each transport until we find one that can satisfy us */ + for (Transport = Transports; *Transport; Transport += wcslen(Transport) + 1) + { + /* See what mapping this Transport supports */ + ErrorCode = SockLoadTransportMapping(Transport, &Mapping); + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Try the next one */ + continue; + } + + /* See if this Mapping works for us */ + if (SockIsTripleInMapping(Mapping, + *AddressFamily, + &AfMatch, + *SocketType, + &SocketMatch, + *Protocol, + &ProtoMatch)) + { + /* It does, so load the DLL associated with it */ + ErrorCode = SockLoadHelperDll(Transport, Mapping, &HelperData); + + /* Check for success */ + if (ErrorCode == NO_ERROR) + { + /* Call the Helper Dll function get the Transport Name */ + if (!HelperData->WSHOpenSocket2) + { + /* Check for invalid flag combo */ + if (!(Flags & WSA_FLAG_MULTIPOINT_ALL)) + { + /* DLL Doesn't support WSHOpenSocket2, call the old one */ + ErrorCode = HelperData->WSHOpenSocket(AddressFamily, + SocketType, + Protocol, + TransportName, + HelperDllContext, + Events); + } + else + { + /* Fail */ + ErrorCode = WSAEINVAL; + } + } + else + { + /* Call the newer function */ + ErrorCode = HelperData->WSHOpenSocket2(AddressFamily, + SocketType, + Protocol, + Group, + Flags, + TransportName, + HelperDllContext, + Events); + } + + /* Check for success */ + if (ErrorCode == NO_ERROR) + { + /* Reference the helper */ + InterlockedIncrement(&HelperData->RefCount); + + /* Release the lock and free the transports */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + RtlFreeHeap(SockPrivateHeap, 0, Transports); + + /* Return the Helper Pointer */ + *HelperDllData = HelperData; + return NO_ERROR; + } + + /* Check if we don't need a transport name */ + if ((*SocketType == SOCK_RAW) && (TransportName->Buffer)) + { + /* Free it */ + RtlFreeHeap(RtlGetProcessHeap(), 0, TransportName->Buffer); + TransportName->Buffer = NULL; + } + + /* Try again */ + continue; + } + } + + /* Free the mapping and continue */ + RtlFreeHeap(SockPrivateHeap, 0, Mapping); + } + + /* Release the lock and free the transport list */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + RtlFreeHeap(SockPrivateHeap, 0, Transports); + + /* Check why we didn't find a match */ + if (!AfMatch) return WSAEAFNOSUPPORT; + if (!ProtoMatch) return WSAEPROTONOSUPPORT; + if (!SocketMatch) return WSAESOCKTNOSUPPORT; + + /* The comination itself was invalid */ + return WSAEINVAL; +} + +INT +WSPAPI +SockLoadTransportMapping(IN PWSTR TransportName, + OUT PWINSOCK_MAPPING *Mapping) +{ + PWSTR TransportKey; + HKEY KeyHandle; + INT ErrorCode; + ULONG MappingSize = 0; + + /* Allocate a Buffer */ + TransportKey = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + MAX_PATH * sizeof(WCHAR)); + /* Check for error */ + if (!TransportKey) return ERROR_NOT_ENOUGH_MEMORY; + + /* Generate the right key name */ + wcscpy(TransportKey, L"System\\CurrentControlSet\\Services\\"); + wcscat(TransportKey, TransportName); + wcscat(TransportKey, L"\\Parameters\\Winsock"); + + /* Open the Key */ + ErrorCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE, + TransportKey, + 0, + KEY_READ, + &KeyHandle); + + /* We don't need the Transport Key anymore */ + RtlFreeHeap(SockPrivateHeap, 0, TransportKey); + + /* Check for error */ + if ((ErrorCode != ERROR_MORE_DATA) && (ErrorCode != NO_ERROR)) + { + /* Close key and fail */ + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Find out how much space we need for the Mapping */ + ErrorCode = RegQueryValueExW(KeyHandle, + L"Mapping", + NULL, + NULL, + NULL, + &MappingSize); + + /* Check for error */ + if ((ErrorCode != ERROR_MORE_DATA) && (ErrorCode != NO_ERROR)) + { + /* Close key and fail */ + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Allocate Memory for the Mapping */ + *Mapping = SockAllocateHeapRoutine(SockPrivateHeap, 0, MappingSize); + + /* Check for error */ + if (!(*Mapping)) + { + /* Close key and fail */ + RegCloseKey(KeyHandle); + return ERROR_NOT_ENOUGH_MEMORY; + } + + /* Read the Mapping */ + ErrorCode = RegQueryValueExW(KeyHandle, + L"Mapping", + NULL, + NULL, + (LPBYTE)*Mapping, + &MappingSize); + + /* Check for error */ + if ((ErrorCode != ERROR_MORE_DATA) && (ErrorCode != NO_ERROR)) + { + /* Close key and fail */ + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Close key and return */ + RegCloseKey(KeyHandle); + return NO_ERROR; +} + +INT +WSPAPI +SockLoadHelperDll(PWSTR TransportName, + PWINSOCK_MAPPING Mapping, + PHELPER_DATA *HelperDllData) +{ + PHELPER_DATA HelperData; + PWSTR HelperDllName; + PWSTR FullHelperDllName; + ULONG HelperDllNameSize; + PWSTR HelperKey; + HKEY KeyHandle; + ULONG DataSize; + INT ErrorCode; + PLIST_ENTRY Entry; + + /* Allocate space for the Helper Structure and TransportName */ + HelperData = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + sizeof(*HelperData) + + (DWORD)(wcslen(TransportName) + 1) * + sizeof(WCHAR)); + + /* Check for error */ + if (!HelperData) return ERROR_NOT_ENOUGH_MEMORY; + + /* Allocate Space for the Helper DLL Key */ + HelperKey = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + MAX_PATH * sizeof(WCHAR)); + + /* Check for error */ + if (!HelperKey) + { + RtlFreeHeap(SockPrivateHeap, 0, HelperData); + return ERROR_NOT_ENOUGH_MEMORY; + } + + /* Generate the right key name */ + wcscpy(HelperKey, L"System\\CurrentControlSet\\Services\\"); + wcscat(HelperKey, TransportName); + wcscat(HelperKey, L"\\Parameters\\Winsock"); + + /* Open the Key */ + ErrorCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE, + HelperKey, + 0, + KEY_READ, + &KeyHandle); + + /* Free Buffer */ + RtlFreeHeap(SockPrivateHeap, 0, HelperKey); + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Free the helper data and fail */ + RtlFreeHeap(SockPrivateHeap, 0, HelperData); + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Read Minimum size of Sockaddr Structures */ + DataSize = sizeof(HelperData->MinWSAddressLength); + RegQueryValueExW(KeyHandle, + L"MinSockaddrLength", + NULL, + NULL, + (LPBYTE)&HelperData->MinWSAddressLength, + &DataSize); + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Free the helper data and fail */ + RtlFreeHeap(SockPrivateHeap, 0, HelperData); + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Read Maximum size of Sockaddr Structures */ + DataSize = sizeof(HelperData->MinWSAddressLength); + RegQueryValueExW(KeyHandle, + L"MaxSockaddrLength", + NULL, + NULL, + (LPBYTE)&HelperData->MaxWSAddressLength, + &DataSize); + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Free the helper data and fail */ + RtlFreeHeap(SockPrivateHeap, 0, HelperData); + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Size of TDI Structures */ + HelperData->MinTDIAddressLength = HelperData->MinWSAddressLength + 6; + HelperData->MaxTDIAddressLength = HelperData->MaxWSAddressLength + 6; + + /* Read Delayed Acceptance Setting */ + DataSize = sizeof(DWORD); + ErrorCode = RegQueryValueExW(KeyHandle, + L"UseDelayedAcceptance", + NULL, + NULL, + (LPBYTE)&HelperData->UseDelayedAcceptance, + &DataSize); + + /* Use defalt if we failed */ + if (ErrorCode != NO_ERROR) HelperData->UseDelayedAcceptance = -1; + + /* Allocate Space for the Helper DLL Names */ + HelperDllName = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + MAX_PATH * sizeof(WCHAR)); + + /* Check for error */ + if (!HelperDllName) + { + /* Free the helper data and fail */ + RtlFreeHeap(SockPrivateHeap, 0, HelperData); + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Allocate space for the expanded version */ + FullHelperDllName = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + MAX_PATH * sizeof(WCHAR)); + + /* Check for error */ + if (!FullHelperDllName) + { + /* Free the helper data and fail */ + RtlFreeHeap(SockPrivateHeap, 0, HelperData); + RtlFreeHeap(SockPrivateHeap, 0, HelperDllName); + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Get the name of the Helper DLL*/ + DataSize = 512; + ErrorCode = RegQueryValueExW(KeyHandle, + L"HelperDllName", + NULL, + NULL, + (LPBYTE)HelperDllName, + &DataSize); + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Free the helper data and fail */ + RtlFreeHeap(SockPrivateHeap, 0, HelperData); + RtlFreeHeap(SockPrivateHeap, 0, HelperDllName); + RtlFreeHeap(SockPrivateHeap, 0, FullHelperDllName); + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Get the Full name, expanding Environment Strings */ + HelperDllNameSize = ExpandEnvironmentStringsW(HelperDllName, + FullHelperDllName, + MAX_PATH); + + /* Load the DLL */ + HelperData->hInstance = LoadLibraryW(FullHelperDllName); + + /* Free Buffers */ + RtlFreeHeap(SockPrivateHeap, 0, HelperDllName); + RtlFreeHeap(SockPrivateHeap, 0, FullHelperDllName); + + /* Return if we didn't Load it Properly */ + if (!HelperData->hInstance) + { + /* Free memory and fail */ + RtlFreeHeap(SockPrivateHeap, 0, HelperData); + RegCloseKey(KeyHandle); + return GetLastError(); + } + + /* Close Key */ + RegCloseKey(KeyHandle); + + /* Get the Pointers to the Helper Routines */ + HelperData->WSHOpenSocket = (PWSH_OPEN_SOCKET) + GetProcAddress(HelperData->hInstance, + "WSHOpenSocket"); + HelperData->WSHOpenSocket2 = (PWSH_OPEN_SOCKET2) + GetProcAddress(HelperData->hInstance, + "WSHOpenSocket2"); + HelperData->WSHJoinLeaf = (PWSH_JOIN_LEAF) + GetProcAddress(HelperData->hInstance, + "WSHJoinLeaf"); + HelperData->WSHNotify = (PWSH_NOTIFY) + GetProcAddress(HelperData->hInstance, "WSHNotify"); + HelperData->WSHGetSocketInformation = (PWSH_GET_SOCKET_INFORMATION) + GetProcAddress(HelperData->hInstance, + "WSHGetSocketInformation"); + HelperData->WSHSetSocketInformation = (PWSH_SET_SOCKET_INFORMATION) + GetProcAddress(HelperData->hInstance, + "WSHSetSocketInformation"); + HelperData->WSHGetSockaddrType = (PWSH_GET_SOCKADDR_TYPE) + GetProcAddress(HelperData->hInstance, + "WSHGetSockaddrType"); + HelperData->WSHGetWildcardSockaddr = (PWSH_GET_WILDCARD_SOCKADDR) + GetProcAddress(HelperData->hInstance, + "WSHGetWildcardSockaddr"); + HelperData->WSHGetBroadcastSockaddr = (PWSH_GET_BROADCAST_SOCKADDR) + GetProcAddress(HelperData->hInstance, + "WSHGetBroadcastSockaddr"); + HelperData->WSHAddressToString = (PWSH_ADDRESS_TO_STRING) + GetProcAddress(HelperData->hInstance, + "WSHAddressToString"); + HelperData->WSHStringToAddress = (PWSH_STRING_TO_ADDRESS) + GetProcAddress(HelperData->hInstance, + "WSHStringToAddress"); + HelperData->WSHIoctl = (PWSH_IOCTL) + GetProcAddress(HelperData->hInstance, "WSHIoctl"); + + /* Save the Mapping Structure and transport name */ + HelperData->Mapping = Mapping; + wcscpy(HelperData->TransportName, TransportName); + + /* Increment Reference Count */ + HelperData->RefCount = 1; + + /* Add it to our list */ + InsertHeadList(&SockHelperDllListHead, &HelperData->Helpers); + + /* Return Pointers */ + *HelperDllData = HelperData; + + /* Check if this one was already load it */ + Entry = HelperData->Helpers.Flink; + while (Entry != &SockHelperDllListHead) + { + /* Get the entry */ + HelperData = CONTAINING_RECORD(Entry, HELPER_DATA, Helpers); + + /* Move to the next one */ + Entry = Entry->Flink; + + /* Check if the names match */ + if (!wcscmp(HelperData->TransportName, (*HelperDllData)->TransportName)) + { + /* Remove this one */ + RemoveEntryList(&HelperData->Helpers); + SockDereferenceHelperDll(HelperData); + } + } + + /* Return success */ + return NO_ERROR; +} + +BOOL +WSPAPI +SockIsTripleInMapping(IN PWINSOCK_MAPPING Mapping, + IN INT AddressFamily, + OUT PBOOLEAN AfMatch, + IN INT SocketType, + OUT PBOOLEAN SockMatch, + IN INT Protocol, + OUT PBOOLEAN ProtoMatch) +{ + ULONG Row; + BOOLEAN FoundAf = FALSE, FoundProto = FALSE, FoundSocket = FALSE; + + /* Loop through Mapping to Find a matching one */ + for (Row = 0; Row < Mapping->Rows; Row++) + { + /* Check Address Family */ + if ((INT)Mapping->Mapping[Row].AddressFamily == AddressFamily) + { + /* Remember that we found it */ + FoundAf = TRUE; + } + + /* Check Socket Type */ + if ((INT)Mapping->Mapping[Row].SocketType == SocketType) + { + /* Remember that we found it */ + FoundSocket = TRUE; + } + + /* Check Protocol (SOCK_RAW and AF_NETBIOS can skip this check) */ + if (((INT)Mapping->Mapping[Row].SocketType == SocketType) || + (AddressFamily == AF_NETBIOS) || (SocketType == SOCK_RAW)) + { + /* Remember that we found it */ + FoundProto = TRUE; + } + + /* Check of all three values Match */ + if (FoundProto && FoundSocket && FoundAf) + { + /* Return success */ + *AfMatch = *SockMatch = *ProtoMatch = TRUE; + return TRUE; + } + } + + /* Return whatever we found */ + if (FoundAf) *AfMatch = TRUE; + if (FoundSocket) *SockMatch = TRUE; + if (FoundProto) *ProtoMatch = TRUE; + + /* Fail */ + return FALSE; +} + +INT +WSPAPI +SockNotifyHelperDll(IN PSOCKET_INFORMATION Socket, + IN DWORD Event) +{ + INT ErrorCode; + + /* See if this event matters */ + if (!(Socket->HelperEvents & Event)) return NO_ERROR; + + /* See if we have a helper... */ + if (!(Socket->HelperData)) return NO_ERROR; + + /* Get TDI handles */ + ErrorCode = SockGetTdiHandles(Socket); + if (ErrorCode != NO_ERROR) return ErrorCode; + + /* Call the notification */ + return Socket->HelperData->WSHNotify(Socket->HelperContext, + Socket->Handle, + Socket->TdiAddressHandle, + Socket->TdiConnectionHandle, + Event); +} + diff --git a/dll/win32/mswsock/msafd/listen.c b/dll/win32/mswsock/msafd/listen.c new file mode 100644 index 00000000000..ec37ae80613 --- /dev/null +++ b/dll/win32/mswsock/msafd/listen.c @@ -0,0 +1,564 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +WSPListen(SOCKET Handle, + INT Backlog, + LPINT lpErrno) +{ + IO_STATUS_BLOCK IoStatusBlock; + AFD_LISTEN_DATA ListenData; + PSOCKET_INFORMATION Socket; + PWINSOCK_TEB_DATA ThreadData; + INT ErrorCode; + NTSTATUS Status; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* If the socket is connection-less, fail */ + if (MSAFD_IS_DGRAM_SOCK(Socket)); + { + /* Fail */ + ErrorCode = WSAEOPNOTSUPP; + goto error; + } + + /* If the socket is already listening, do nothing */ + if (Socket->SharedData.Listening) + { + /* Return happily */ + ErrorCode = NO_ERROR; + goto error; + } + else if (Socket->SharedData.State != SocketConnected) + { + /* If we're not connected, fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Set Up Listen Structure */ + ListenData.UseSAN = SockSanEnabled; + ListenData.UseDelayedAcceptance = Socket->SharedData.UseDelayedAcceptance; + ListenData.Backlog = Backlog; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_START_LISTEN, + &ListenData, + sizeof(ListenData), + NULL, + 0); + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion outside the lock */ + LeaveCriticalSection(&Socket->Lock); + SockWaitForSingleObject(ThreadData->EventHandle, + Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + EnterCriticalSection(&Socket->Lock); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* Notify helper DLL */ + ErrorCode = SockNotifyHelperDll(Socket, WSH_NOTIFY_LISTEN); + if (ErrorCode != NO_ERROR) goto error; + + /* Set to Listening */ + Socket->SharedData.Listening = TRUE; + + /* Update context with AFD */ + ErrorCode = SockSetHandleContext(Socket); + if (ErrorCode != NO_ERROR) goto error; + +error: + /* Check if we have a socket here */ + if (Socket) + { + /* Release the lock and dereference */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +WSPListen(SOCKET Handle, + INT Backlog, + LPINT lpErrno) +{ + IO_STATUS_BLOCK IoStatusBlock; + AFD_LISTEN_DATA ListenData; + PSOCKET_INFORMATION Socket; + PWINSOCK_TEB_DATA ThreadData; + INT ErrorCode; + NTSTATUS Status; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* If the socket is connection-less, fail */ + if (MSAFD_IS_DGRAM_SOCK(Socket)); + { + /* Fail */ + ErrorCode = WSAEOPNOTSUPP; + goto error; + } + + /* If the socket is already listening, do nothing */ + if (Socket->SharedData.Listening) + { + /* Return happily */ + ErrorCode = NO_ERROR; + goto error; + } + else if (Socket->SharedData.State != SocketConnected) + { + /* If we're not connected, fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Set Up Listen Structure */ + ListenData.UseSAN = SockSanEnabled; + ListenData.UseDelayedAcceptance = Socket->SharedData.UseDelayedAcceptance; + ListenData.Backlog = Backlog; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_START_LISTEN, + &ListenData, + sizeof(ListenData), + NULL, + 0); + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion outside the lock */ + LeaveCriticalSection(&Socket->Lock); + SockWaitForSingleObject(ThreadData->EventHandle, + Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + EnterCriticalSection(&Socket->Lock); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* Notify helper DLL */ + ErrorCode = SockNotifyHelperDll(Socket, WSH_NOTIFY_LISTEN); + if (ErrorCode != NO_ERROR) goto error; + + /* Set to Listening */ + Socket->SharedData.Listening = TRUE; + + /* Update context with AFD */ + ErrorCode = SockSetHandleContext(Socket); + if (ErrorCode != NO_ERROR) goto error; + +error: + /* Check if we have a socket here */ + if (Socket) + { + /* Release the lock and dereference */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +WSPListen(SOCKET Handle, + INT Backlog, + LPINT lpErrno) +{ + IO_STATUS_BLOCK IoStatusBlock; + AFD_LISTEN_DATA ListenData; + PSOCKET_INFORMATION Socket; + PWINSOCK_TEB_DATA ThreadData; + INT ErrorCode; + NTSTATUS Status; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* If the socket is connection-less, fail */ + if (MSAFD_IS_DGRAM_SOCK(Socket)); + { + /* Fail */ + ErrorCode = WSAEOPNOTSUPP; + goto error; + } + + /* If the socket is already listening, do nothing */ + if (Socket->SharedData.Listening) + { + /* Return happily */ + ErrorCode = NO_ERROR; + goto error; + } + else if (Socket->SharedData.State != SocketConnected) + { + /* If we're not connected, fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Set Up Listen Structure */ + ListenData.UseSAN = SockSanEnabled; + ListenData.UseDelayedAcceptance = Socket->SharedData.UseDelayedAcceptance; + ListenData.Backlog = Backlog; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_START_LISTEN, + &ListenData, + sizeof(ListenData), + NULL, + 0); + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion outside the lock */ + LeaveCriticalSection(&Socket->Lock); + SockWaitForSingleObject(ThreadData->EventHandle, + Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + EnterCriticalSection(&Socket->Lock); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* Notify helper DLL */ + ErrorCode = SockNotifyHelperDll(Socket, WSH_NOTIFY_LISTEN); + if (ErrorCode != NO_ERROR) goto error; + + /* Set to Listening */ + Socket->SharedData.Listening = TRUE; + + /* Update context with AFD */ + ErrorCode = SockSetHandleContext(Socket); + if (ErrorCode != NO_ERROR) goto error; + +error: + /* Check if we have a socket here */ + if (Socket) + { + /* Release the lock and dereference */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +WSPListen(SOCKET Handle, + INT Backlog, + LPINT lpErrno) +{ + IO_STATUS_BLOCK IoStatusBlock; + AFD_LISTEN_DATA ListenData; + PSOCKET_INFORMATION Socket; + PWINSOCK_TEB_DATA ThreadData; + INT ErrorCode; + NTSTATUS Status; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* If the socket is connection-less, fail */ + if (MSAFD_IS_DGRAM_SOCK(Socket)); + { + /* Fail */ + ErrorCode = WSAEOPNOTSUPP; + goto error; + } + + /* If the socket is already listening, do nothing */ + if (Socket->SharedData.Listening) + { + /* Return happily */ + ErrorCode = NO_ERROR; + goto error; + } + else if (Socket->SharedData.State != SocketConnected) + { + /* If we're not connected, fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Set Up Listen Structure */ + ListenData.UseSAN = SockSanEnabled; + ListenData.UseDelayedAcceptance = Socket->SharedData.UseDelayedAcceptance; + ListenData.Backlog = Backlog; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_START_LISTEN, + &ListenData, + sizeof(ListenData), + NULL, + 0); + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion outside the lock */ + LeaveCriticalSection(&Socket->Lock); + SockWaitForSingleObject(ThreadData->EventHandle, + Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + EnterCriticalSection(&Socket->Lock); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* Notify helper DLL */ + ErrorCode = SockNotifyHelperDll(Socket, WSH_NOTIFY_LISTEN); + if (ErrorCode != NO_ERROR) goto error; + + /* Set to Listening */ + Socket->SharedData.Listening = TRUE; + + /* Update context with AFD */ + ErrorCode = SockSetHandleContext(Socket); + if (ErrorCode != NO_ERROR) goto error; + +error: + /* Check if we have a socket here */ + if (Socket) + { + /* Release the lock and dereference */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + diff --git a/dll/win32/mswsock/msafd/nspeprot.c b/dll/win32/mswsock/msafd/nspeprot.c new file mode 100644 index 00000000000..77b3205c368 --- /dev/null +++ b/dll/win32/mswsock/msafd/nspeprot.c @@ -0,0 +1,328 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +SockLoadTransportList(PWSTR *TransportList) +{ + ULONG TransportListSize = 0; + HKEY KeyHandle; + INT ErrorCode; + + /* Open the Transports Key */ + ErrorCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE, + L"SYSTEM\\CurrentControlSet\\Services\\Winsock\\Parameters", + 0, + KEY_READ, + &KeyHandle); + + /* Check for error */ + if (ErrorCode != NO_ERROR) return ErrorCode; + + /* Get the Transport List Size */ + ErrorCode = RegQueryValueExW(KeyHandle, + L"Transports", + NULL, + NULL, + NULL, + &TransportListSize); + + /* Check for error */ + if ((ErrorCode != ERROR_MORE_DATA) && (ErrorCode != NO_ERROR)) + { + /* Close key and fail */ + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Allocate Memory for the Transport List */ + *TransportList = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + TransportListSize); + + /* Check for error */ + if (!(*TransportList)) + { + /* Close key and fail */ + RegCloseKey(KeyHandle); + return ERROR_NOT_ENOUGH_MEMORY; + } + + /* Get the Transports */ + ErrorCode = RegQueryValueExW(KeyHandle, + L"Transports", + NULL, + NULL, + (LPBYTE)*TransportList, + &TransportListSize); + + /* Check for error */ + if ((ErrorCode != ERROR_MORE_DATA) && (ErrorCode != NO_ERROR)) + { + /* Close key and fail */ + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Close key and return */ + RegCloseKey(KeyHandle); + return NO_ERROR; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +SockLoadTransportList(PWSTR *TransportList) +{ + ULONG TransportListSize = 0; + HKEY KeyHandle; + INT ErrorCode; + + /* Open the Transports Key */ + ErrorCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE, + L"SYSTEM\\CurrentControlSet\\Services\\Winsock\\Parameters", + 0, + KEY_READ, + &KeyHandle); + + /* Check for error */ + if (ErrorCode != NO_ERROR) return ErrorCode; + + /* Get the Transport List Size */ + ErrorCode = RegQueryValueExW(KeyHandle, + L"Transports", + NULL, + NULL, + NULL, + &TransportListSize); + + /* Check for error */ + if ((ErrorCode != ERROR_MORE_DATA) && (ErrorCode != NO_ERROR)) + { + /* Close key and fail */ + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Allocate Memory for the Transport List */ + *TransportList = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + TransportListSize); + + /* Check for error */ + if (!(*TransportList)) + { + /* Close key and fail */ + RegCloseKey(KeyHandle); + return ERROR_NOT_ENOUGH_MEMORY; + } + + /* Get the Transports */ + ErrorCode = RegQueryValueExW(KeyHandle, + L"Transports", + NULL, + NULL, + (LPBYTE)*TransportList, + &TransportListSize); + + /* Check for error */ + if ((ErrorCode != ERROR_MORE_DATA) && (ErrorCode != NO_ERROR)) + { + /* Close key and fail */ + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Close key and return */ + RegCloseKey(KeyHandle); + return NO_ERROR; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +SockLoadTransportList(PWSTR *TransportList) +{ + ULONG TransportListSize = 0; + HKEY KeyHandle; + INT ErrorCode; + + /* Open the Transports Key */ + ErrorCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE, + L"SYSTEM\\CurrentControlSet\\Services\\Winsock\\Parameters", + 0, + KEY_READ, + &KeyHandle); + + /* Check for error */ + if (ErrorCode != NO_ERROR) return ErrorCode; + + /* Get the Transport List Size */ + ErrorCode = RegQueryValueExW(KeyHandle, + L"Transports", + NULL, + NULL, + NULL, + &TransportListSize); + + /* Check for error */ + if ((ErrorCode != ERROR_MORE_DATA) && (ErrorCode != NO_ERROR)) + { + /* Close key and fail */ + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Allocate Memory for the Transport List */ + *TransportList = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + TransportListSize); + + /* Check for error */ + if (!(*TransportList)) + { + /* Close key and fail */ + RegCloseKey(KeyHandle); + return ERROR_NOT_ENOUGH_MEMORY; + } + + /* Get the Transports */ + ErrorCode = RegQueryValueExW(KeyHandle, + L"Transports", + NULL, + NULL, + (LPBYTE)*TransportList, + &TransportListSize); + + /* Check for error */ + if ((ErrorCode != ERROR_MORE_DATA) && (ErrorCode != NO_ERROR)) + { + /* Close key and fail */ + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Close key and return */ + RegCloseKey(KeyHandle); + return NO_ERROR; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +SockLoadTransportList(PWSTR *TransportList) +{ + ULONG TransportListSize = 0; + HKEY KeyHandle; + INT ErrorCode; + + /* Open the Transports Key */ + ErrorCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE, + L"SYSTEM\\CurrentControlSet\\Services\\Winsock\\Parameters", + 0, + KEY_READ, + &KeyHandle); + + /* Check for error */ + if (ErrorCode != NO_ERROR) return ErrorCode; + + /* Get the Transport List Size */ + ErrorCode = RegQueryValueExW(KeyHandle, + L"Transports", + NULL, + NULL, + NULL, + &TransportListSize); + + /* Check for error */ + if ((ErrorCode != ERROR_MORE_DATA) && (ErrorCode != NO_ERROR)) + { + /* Close key and fail */ + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Allocate Memory for the Transport List */ + *TransportList = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + TransportListSize); + + /* Check for error */ + if (!(*TransportList)) + { + /* Close key and fail */ + RegCloseKey(KeyHandle); + return ERROR_NOT_ENOUGH_MEMORY; + } + + /* Get the Transports */ + ErrorCode = RegQueryValueExW(KeyHandle, + L"Transports", + NULL, + NULL, + (LPBYTE)*TransportList, + &TransportListSize); + + /* Check for error */ + if ((ErrorCode != ERROR_MORE_DATA) && (ErrorCode != NO_ERROR)) + { + /* Close key and fail */ + RegCloseKey(KeyHandle); + return ErrorCode; + } + + /* Close key and return */ + RegCloseKey(KeyHandle); + return NO_ERROR; +} + diff --git a/dll/win32/mswsock/msafd/proc.c b/dll/win32/mswsock/msafd/proc.c new file mode 100644 index 00000000000..3621f195071 --- /dev/null +++ b/dll/win32/mswsock/msafd/proc.c @@ -0,0 +1,4632 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +SOCK_RW_LOCK SocketGlobalLock; + +/* FUNCTIONS *****************************************************************/ + +VOID +WSPAPI +SockDestroySocket(PSOCKET_INFORMATION Socket) +{ + /* Dereference its helper DLL */ + SockDereferenceHelperDll(Socket->HelperData); + + /* Delete the lock */ + DeleteCriticalSection(&Socket->Lock); + + /* Free the socket */ + RtlFreeHeap(SockPrivateHeap, 0, Socket); +} + +VOID +__inline +WSPAPI +SockDereferenceSocket(IN PSOCKET_INFORMATION Socket) +{ + /* Dereference and see if it's the last count */ + if (!InterlockedDecrement(&Socket->WshContext.RefCount)) + { + /* Destroy the socket */ + SockDestroySocket(Socket); + } +} + +PSOCKET_INFORMATION +WSPAPI +SockImportHandle(IN SOCKET Handle) +{ + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + PWAH_HANDLE WahHandle; + NTSTATUS Status; + ULONG ContextSize; + IO_STATUS_BLOCK IoStatusBlock; + PSOCKET_INFORMATION ImportedSocket = NULL; + UNICODE_STRING TransportName; + + /* Acquire the global lock */ + SockAcquireRwLockExclusive(&SocketGlobalLock); + + /* Make sure that the handle is still invalid */ + WahHandle = WahReferenceContextByHandle(SockContextTable, (HANDLE)Handle); + if (WahHandle) + { + /* Some other thread imported it by now, release the lock and return */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + return (PSOCKET_INFORMATION)WahHandle; + } + + /* Setup the NULL name for possible cleanup later */ + RtlInitUnicodeString(&TransportName, NULL); + + /* Call AFD to get the context size */ + Status = NtDeviceIoControlFile((HANDLE)Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_GET_CONTEXT_SIZE, + NULL, + 0, + &ContextSize, + sizeof(ContextSize)); + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + SockWaitForSingleObject(ThreadData->EventHandle, + Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Make sure we didn't fail, and that this is a valid context */ + if (!NT_SUCCESS(Status) || (ContextSize < sizeof(SOCK_SHARED_INFO))) + { + /* Fail (the error handler will convert to Win32 Status) */ + goto error; + } + +error: + /* Release the lock */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + + return ImportedSocket; +} + +INT +WSPAPI +SockSetInformation(IN PSOCKET_INFORMATION Socket, + IN ULONG AfdInformationClass, + IN PBOOLEAN Boolean OPTIONAL, + IN PULONG Ulong OPTIONAL, + IN PLARGE_INTEGER LargeInteger OPTIONAL) +{ + IO_STATUS_BLOCK IoStatusBlock; + AFD_INFO AfdInfo; + NTSTATUS Status; + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + + /* Set Info Class */ + AfdInfo.InformationClass = AfdInformationClass; + + /* Set Information */ + if (Boolean) + { + AfdInfo.Information.Boolean = *Boolean; + } + else if (Ulong) + { + AfdInfo.Information.Ulong = *Ulong; + } + else + { + AfdInfo.Information.LargeInteger = *LargeInteger; + } + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_GET_INFO, + &AfdInfo, + sizeof(AfdInfo), + NULL, + 0); + /* Check if we have to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for the operation to finish */ + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Handle failure */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + return NtStatusToSocketError(Status); + } + + /* Return to caller */ + return NO_ERROR; +} + +INT +WSPAPI +SockGetInformation(IN PSOCKET_INFORMATION Socket, + IN ULONG AfdInformationClass, + IN PVOID ExtraData OPTIONAL, + IN ULONG ExtraDataSize, + IN OUT PBOOLEAN Boolean OPTIONAL, + IN OUT PULONG Ulong OPTIONAL, + IN OUT PLARGE_INTEGER LargeInteger OPTIONAL) +{ + ULONG InfoLength; + IO_STATUS_BLOCK IoStatusBlock; + PAFD_INFO AfdInfo; + AFD_INFO InfoData; + NTSTATUS Status; + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + + /* Check if extra data is there */ + if (ExtraData && ExtraDataSize) + { + /* Allocate space for it */ + InfoLength = sizeof(InfoData) + ExtraDataSize; + AfdInfo = (PAFD_INFO)SockAllocateHeapRoutine(SockPrivateHeap, + 0, + InfoLength); + if (!AfdInfo) return WSAENOBUFS; + + /* Copy the extra data */ + RtlCopyMemory(AfdInfo + 1, ExtraData, ExtraDataSize); + } + else + { + /* Use local buffer */ + AfdInfo = &InfoData; + InfoLength = sizeof(InfoData); + } + + /* Set Info Class */ + AfdInfo->InformationClass = AfdInformationClass; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_GET_INFO, + &InfoData, + InfoLength, + &InfoData, + sizeof(InfoData)); + /* Check if we have to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for the operation to finish */ + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Handle failure */ + if (!NT_SUCCESS(Status)) + { + /* Check if we have to free the data */ + if (AfdInfo != &InfoData) RtlFreeHeap(SockPrivateHeap, 0, AfdInfo); + + /* Fail */ + return NtStatusToSocketError(Status); + } + + /* Return Information */ + if (Boolean) + { + *Boolean = AfdInfo->Information.Boolean; + } + else if (Ulong) + { + *Ulong = AfdInfo->Information.Ulong; + } + else + { + *LargeInteger = AfdInfo->Information.LargeInteger; + } + + /* Check if we have to free the data */ + if (AfdInfo != &InfoData) RtlFreeHeap(SockPrivateHeap, 0, AfdInfo); + + /* Return to caller */ + return NO_ERROR; +} + +INT +WSPAPI +SockSetHandleContext(IN PSOCKET_INFORMATION Socket) +{ + IO_STATUS_BLOCK IoStatusBlock; + CHAR ContextData[256]; + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + PVOID Context; + ULONG_PTR ContextPos; + ULONG ContextLength; + INT HelperContextLength; + INT ErrorCode; + NTSTATUS Status; + + /* Find out how big the helper DLL context is */ + ErrorCode = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, + Socket->Handle, + Socket->TdiAddressHandle, + Socket->TdiConnectionHandle, + SOL_INTERNAL, + SO_CONTEXT, + NULL, + &HelperContextLength); + + /* Calculate the total space needed */ + ContextLength = sizeof(SOCK_SHARED_INFO) + + 2 * Socket->HelperData->MaxWSAddressLength + + sizeof(ULONG) + HelperContextLength; + + /* See if our stack can hold it */ + if (ContextLength <= sizeof(ContextData)) + { + /* Use our stack */ + Context = ContextData; + } + else + { + /* Allocate from heap */ + Context = SockAllocateHeapRoutine(SockPrivateHeap, 0, ContextLength); + if (!Context) return WSAENOBUFS; + } + + /* + * Create Context, this includes: + * Shared Socket Data, Helper Context Length, Local and Remote Addresses + * and finally the actual helper context. + */ + ContextPos = (ULONG_PTR)Context; + RtlCopyMemory((PVOID)ContextPos, + &Socket->SharedData, + sizeof(SOCK_SHARED_INFO)); + ContextPos += sizeof(SOCK_SHARED_INFO); + *(PULONG)ContextPos = HelperContextLength; + ContextPos += sizeof(ULONG); + RtlCopyMemory((PVOID)ContextPos, + Socket->LocalAddress, + Socket->HelperData->MaxWSAddressLength); + ContextPos += Socket->HelperData->MaxWSAddressLength; + RtlCopyMemory((PVOID)ContextPos, + Socket->RemoteAddress, + Socket->HelperData->MaxWSAddressLength); + ContextPos += Socket->HelperData->MaxWSAddressLength; + + /* Now get the helper context */ + ErrorCode = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, + Socket->Handle, + Socket->TdiAddressHandle, + Socket->TdiConnectionHandle, + SOL_INTERNAL, + SO_CONTEXT, + (PVOID)ContextPos, + &HelperContextLength); + /* Now give it to AFD */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_SET_CONTEXT, + Context, + ContextLength, + NULL, + 0); + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check if we need to free from heap */ + if (Context != ContextData) RtlFreeHeap(SockPrivateHeap, 0, Context); + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Convert and return error code */ + ErrorCode = NtStatusToSocketError(Status); + return ErrorCode; + } + + /* Return success */ + return NO_ERROR; +} + +INT +WSPAPI +SockIsAddressConsistentWithConstrainedGroup(IN PSOCKET_INFORMATION Socket, + IN GROUP Group, + IN PSOCKADDR SocketAddress, + IN INT SocketAddressLength) +{ + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + INT ErrorCode; + PAFD_VALIDATE_GROUP_DATA ValidateGroupData; + NTSTATUS Status; + IO_STATUS_BLOCK IoStatusBlock; + ULONG ValidateGroupSize; + CHAR ValidateBuffer[sizeof(AFD_VALIDATE_GROUP_DATA) + MAX_TDI_ADDRESS_LENGTH]; + + /* Calculate the length of the buffer */ + ValidateGroupSize = sizeof(AFD_VALIDATE_GROUP_DATA) + + sizeof(TRANSPORT_ADDRESS) + + Socket->HelperData->MaxTDIAddressLength; + + /* Check if our stack buffer is large enough */ + if (ValidateGroupSize <= sizeof(ValidateBuffer)) + { + /* Use the stack */ + ValidateGroupData = (PVOID)ValidateBuffer; + } + else + { + /* Allocate from heap */ + ValidateGroupData = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + ValidateGroupSize); + if (!ValidateGroupData) return WSAENOBUFS; + } + + /* Convert the address to TDI format */ + ErrorCode = SockBuildTdiAddress(&ValidateGroupData->Address, + SocketAddress, + SocketAddressLength); + if (ErrorCode != NO_ERROR) return ErrorCode; + + /* Tell AFD which group to check, and let AFD validate it */ + ValidateGroupData->GroupId = Group; + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_VALIDATE_GROUP, + ValidateGroupData, + ValidateGroupSize, + NULL, + 0); + + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check if we need to free the data from heap */ + if (ValidateGroupData != (PVOID)ValidateBuffer) + { + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, ValidateGroupData); + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + return NtStatusToSocketError(Status); + } + + /* Return success */ + return NO_ERROR; +} + + +INT +WSPAPI +SockGetTdiHandles(IN PSOCKET_INFORMATION Socket) +{ + AFD_TDI_HANDLE_DATA TdiHandleInfo; + NTSTATUS Status; + IO_STATUS_BLOCK IoStatusBlock; + ULONG InfoType = 0; + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + + /* See which handle(s) we need */ + if (!Socket->TdiAddressHandle) InfoType |= AFD_ADDRESS_HANDLE; + if (!Socket->TdiConnectionHandle) InfoType |= AFD_CONNECTION_HANDLE; + + /* Make sure we need one */ + if (!InfoType) return NO_ERROR; + + /* Call AFD */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_GET_TDI_HANDLES, + &InfoType, + sizeof(InfoType), + &TdiHandleInfo, + sizeof(TdiHandleInfo)); + /* Check if we shoudl wait */ + if (Status == STATUS_PENDING) + { + /* Wait on it */ + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + + /* Update status */ + Status = IoStatusBlock.Status; + } + + /* Check for success */ + if (!NT_SUCCESS(Status)) return NtStatusToSocketError(Status); + + /* Return handles */ + if (!Socket->TdiAddressHandle) + { + Socket->TdiAddressHandle = TdiHandleInfo.TdiAddressHandle; + } + if (!Socket->TdiConnectionHandle) + { + Socket->TdiConnectionHandle = TdiHandleInfo.TdiConnectionHandle; + } + + /* Return */ + return NO_ERROR; +} + +BOOL +WSPAPI +SockWaitForSingleObject(IN HANDLE Handle, + IN SOCKET SocketHandle, + IN DWORD BlockingFlags, + IN DWORD TimeoutFlags) +{ + LARGE_INTEGER Timeout, CurrentTime, DueTime; + NTSTATUS Status; + PSOCKET_INFORMATION Socket = NULL; + BOOLEAN CallHook, UseTimeout; + LPBLOCKINGCALLBACK BlockingHook; + DWORD_PTR Context; + INT ErrorCode; + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + + /* Start with a simple 0.5 second wait */ + Timeout.QuadPart = Int32x32To64(-10000, 500); + Status = NtWaitForSingleObject(Handle, TRUE, &Timeout); + if (Status == STATUS_SUCCESS) return TRUE; + + /* Check if our flags require the socket structure */ + if ((BlockingFlags == MAYBE_BLOCKING_HOOK) || + (BlockingFlags == ALWAYS_BLOCKING_HOOK) || + (TimeoutFlags == SEND_TIMEOUT) || + (TimeoutFlags == RECV_TIMEOUT)) + { + /* Get the socket */ + Socket = SockFindAndReferenceSocket(SocketHandle, FALSE); + if (!Socket) + { + /* We must be waiting on a non-socket for some reason? */ + NtWaitForSingleObject(Handle, TRUE, NULL); + return TRUE; + } + } + + /* Check the blocking flags */ + if (BlockingFlags == ALWAYS_BLOCKING_HOOK) + { + /* Always call it */ + CallHook = TRUE; + } + else if (BlockingFlags == MAYBE_BLOCKING_HOOK) + { + /* Check if we have to call it */ + CallHook = !Socket->SharedData.NonBlocking; + } + else if (BlockingFlags == NO_BLOCKING_HOOK) + { + /* Never call it*/ + CallHook = FALSE; + } + else + { + if (Socket) SockDereferenceSocket(Socket); + return FALSE; + } + + /* Check if we call it */ + if (CallHook) + { + /* Check if it actually exists */ + SockUpcallTable->lpWPUQueryBlockingCallback(Socket->SharedData.CatalogEntryId, + &BlockingHook, + &Context, + &ErrorCode); + + /* See if we'll call it */ + CallHook = (BlockingHook != NULL); + } + + /* Now check the timeout flags */ + if (TimeoutFlags == NO_TIMEOUT) + { + /* None at all */ + UseTimeout = FALSE; + } + else if (TimeoutFlags == SEND_TIMEOUT) + { + /* See if there's a Send Timeout */ + if (Socket->SharedData.SendTimeout) + { + /* Use it */ + UseTimeout = TRUE; + Timeout = RtlEnlargedIntegerMultiply(Socket->SharedData.SendTimeout, + 10 * 1000); + } + else + { + /* There isn't any */ + UseTimeout = FALSE; + } + } + else if (TimeoutFlags == RECV_TIMEOUT) + { + /* See if there's a Receive Timeout */ + if (Socket->SharedData.RecvTimeout) + { + /* Use it */ + UseTimeout = TRUE; + Timeout = RtlEnlargedIntegerMultiply(Socket->SharedData.RecvTimeout, + 10 * 1000); + } + else + { + /* There isn't any */ + UseTimeout = FALSE; + } + } + else + { + if (Socket) SockDereferenceSocket(Socket); + return FALSE; + } + + /* We don't need the socket anymore */ + if (Socket) SockDereferenceSocket(Socket); + + /* Check for timeout */ + if (UseTimeout) + { + /* Calculate the absolute time when the wait ends */ + Status = NtQuerySystemTime(&CurrentTime); + DueTime.QuadPart = CurrentTime.QuadPart + Timeout.QuadPart; + } + else + { + /* Infinite wait */ + DueTime.LowPart = -1; + DueTime.HighPart = 0x7FFFFFFF; + } + + /* Check for blocking hook call */ + if (CallHook) + { + /* We're calling it, so we won't actually be waiting */ + Timeout.LowPart = -1; + Timeout.HighPart = -1; + } + else + { + /* We'll be waiting till the Due Time */ + Timeout = DueTime; + } + + /* Now write data to the TEB so we'll know what's going on */ + ThreadData->CancelIo = FALSE; + ThreadData->SocketHandle = SocketHandle; + + /* Start wait loop */ + do + { + /* Call the hook */ + if (CallHook) (BlockingHook(Context)); + + /* Check if we were cancelled */ + if (ThreadData->CancelIo) + { + /* Infinite timeout and wait for official cancel */ + Timeout.LowPart = -1; + Timeout.HighPart = 0x7FFFFFFF; + } + else + { + /* Check if we're due */ + Status = NtQuerySystemTime(&CurrentTime); + if (CurrentTime.QuadPart > DueTime.QuadPart) + { + /* We're out */ + Status = STATUS_TIMEOUT; + break; + } + } + + /* Do the actual wait */ + Status = NtWaitForSingleObject(Handle, TRUE, &Timeout); + } while ((Status == STATUS_USER_APC) || + (Status == STATUS_ALERTED) || + (Status == STATUS_TIMEOUT)); + + /* Reset thread data */ + ThreadData->SocketHandle = INVALID_SOCKET; + + /* Return to caller */ + if (Status == STATUS_SUCCESS) return TRUE; + return FALSE; +} + +PSOCKET_INFORMATION +WSPAPI +SockFindAndReferenceSocket(IN SOCKET Handle, + IN BOOLEAN Import) +{ + PWAH_HANDLE WahHandle; + + /* Get it from our table and return it */ + WahHandle = WahReferenceContextByHandle(SockContextTable, (HANDLE)Handle); + if (WahHandle) return (PSOCKET_INFORMATION)WahHandle; + + /* Couldn't find it, shoudl we import it? */ + if (Import) return SockImportHandle(Handle); + + /* Nothing found */ + return NULL; +} + +INT +WSPAPI +SockBuildTdiAddress(OUT PTRANSPORT_ADDRESS TdiAddress, + IN PSOCKADDR Sockaddr, + IN INT SockaddrLength) +{ + /* Setup the TDI Address */ + TdiAddress->TAAddressCount = 1; + TdiAddress->Address[0].AddressLength = (USHORT)SockaddrLength - + sizeof(Sockaddr->sa_family); + + /* Copy it */ + RtlCopyMemory(&TdiAddress->Address[0].AddressType, Sockaddr, SockaddrLength); + + /* Return */ + return NO_ERROR; +} + +INT +WSPAPI +SockBuildSockaddr(OUT PSOCKADDR Sockaddr, + OUT PINT SockaddrLength, + IN PTRANSPORT_ADDRESS TdiAddress) +{ + /* Calculate the length it will take */ + *SockaddrLength = TdiAddress->Address[0].AddressLength + + sizeof(Sockaddr->sa_family); + + /* Copy it */ + RtlCopyMemory(Sockaddr, &TdiAddress->Address[0].AddressType, *SockaddrLength); + + /* Return */ + return NO_ERROR; +} + +BOOLEAN +WSPAPI +SockIsSocketConnected(IN PSOCKET_INFORMATION Socket) +{ + LARGE_INTEGER Timeout; + PVOID Context; + PVOID AsyncCallback; + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + + /* Check if there is an async connect in progress, but still unprocessed */ + while ((Socket->AsyncData) && + (Socket->AsyncData->IoStatusBlock.Status != STATUS_PENDING)) + { + /* The socket will be locked, release it */ + LeaveCriticalSection(&Socket->Lock); + + /* Setup the timeout and wait on completion */ + Timeout.QuadPart = 0; + Status = NtRemoveIoCompletion(SockAsyncQueuePort, + &AsyncCallback, + &Context, + &IoStatusBlock, + &Timeout); + + /* Check for success */ + if (Status == STATUS_SUCCESS) + { + /* Check if we're supposed to terminate */ + if (AsyncCallback != (PVOID)-1) + { + /* Handle the Async */ + SockHandleAsyncIndication(AsyncCallback, Context, &IoStatusBlock); + } + else + { + /* Terminate it */ + Status = NtSetIoCompletion(SockAsyncQueuePort, + (PVOID)-1, + (PVOID)-1, + 0, + 0); + + /* Acquire the lock and break out */ + EnterCriticalSection(&Socket->Lock); + break; + } + } + + /* Acquire the socket lock again */ + EnterCriticalSection(&Socket->Lock); + } + + /* Check if it's already connected */ + if (Socket->SharedData.State == SocketConnected) return TRUE; + return FALSE; +} + +VOID +WSPAPI +SockCancelIo(IN SOCKET Handle) +{ + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + + /* Cancel the I/O */ + Status = NtCancelIoFile((HANDLE)Handle, &IoStatusBlock); +} + +VOID +WSPAPI +SockIoCompletion(IN PVOID ApcContext, + IN PIO_STATUS_BLOCK IoStatusBlock, + DWORD Reserved) +{ + LPWSAOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine = ApcContext; + INT ErrorCode; + DWORD BytesSent; + DWORD Flags = 0; + LPWSAOVERLAPPED lpOverlapped; + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + + /* Check if this was an error */ + if (NT_ERROR(IoStatusBlock->Status)) + { + /* Check if it was anything but a simple cancel */ + if (IoStatusBlock->Status != STATUS_CANCELLED) + { + /* Convert it */ + ErrorCode = NtStatusToSocketError(IoStatusBlock->Status); + } + else + { + /* Use the right error */ + ErrorCode = WSA_OPERATION_ABORTED; + } + + /* Either ways, nothing was done */ + BytesSent = 0; + } + else + { + /* No error and check how many bytes were sent */ + ErrorCode = NO_ERROR; + BytesSent = PtrToUlong(IoStatusBlock->Information); + + /* Check the status */ + if (IoStatusBlock->Status == STATUS_BUFFER_OVERFLOW) + { + /* This was an error */ + ErrorCode = WSAEMSGSIZE; + } + else if (IoStatusBlock->Status == STATUS_RECEIVE_PARTIAL) + { + /* Partial receive */ + Flags = MSG_PARTIAL; + } + else if (IoStatusBlock->Status == STATUS_RECEIVE_EXPEDITED) + { + /* OOB receive */ + Flags = MSG_OOB; + } + else if (IoStatusBlock->Status == STATUS_RECEIVE_PARTIAL_EXPEDITED) + { + /* Partial OOB receive */ + Flags = MSG_OOB | MSG_PARTIAL; + } + } + + /* Get the overlapped structure */ + lpOverlapped = CONTAINING_RECORD(IoStatusBlock, WSAOVERLAPPED, Internal); + + /* Call it */ + CompletionRoutine(ErrorCode, BytesSent, lpOverlapped, Flags); + + /* Decrease pending APCs */ + ThreadData->PendingAPCs--; + InterlockedDecrement(&SockProcessPendingAPCCount); +} + +VOID +WSPAPI +SockpWaitForReaderCount(IN PSOCK_RW_LOCK Lock) +{ + NTSTATUS Status; + LARGE_INTEGER Timeout; + + /* Switch threads to see if the lock gets released that way */ + Timeout.QuadPart = 0; + NtDelayExecution(FALSE, &Timeout); + if (Lock->ReaderCount == -2) return; + + /* Either the thread isn't executing (priority inversion) or it's a hog */ + if (!Lock->WriterWaitEvent) + { + /* We don't have an event to wait on yet, allocate it */ + Status = NtCreateEvent(&Lock->WriterWaitEvent, + EVENT_ALL_ACCESS, + NULL, + SynchronizationEvent, + FALSE); + if (!NT_SUCCESS(Status)) + { + /* We can't get an event, do a manual loop */ + Timeout.QuadPart = Int32x32To64(1000, -100); + while (Lock->ReaderCount != -2) NtDelayExecution(FALSE, &Timeout); + } + } + + /* We have en event, now increment the reader count to signal them */ + if (InterlockedIncrement(&Lock->ReaderCount) != -1) + { + /* Wait for them to signal us */ + NtWaitForSingleObject(&Lock->WriterWaitEvent, FALSE, NULL); + } + + /* Finally it's free */ + Lock->ReaderCount = -2; +} + +NTSTATUS +WSPAPI +SockInitializeRwLockAndSpinCount(IN PSOCK_RW_LOCK Lock, + IN ULONG SpinCount) +{ + NTSTATUS Status; + + /* check if this is a special event create request */ + if (SpinCount & 0x80000000) + { + /* Create the event */ + Status = NtCreateEvent(&Lock->WriterWaitEvent, + EVENT_ALL_ACCESS, + NULL, + SynchronizationEvent, + FALSE); + if (!NT_SUCCESS(Status)) return Status; + } + + /* Initialize the lock */ + Status = RtlInitializeCriticalSectionAndSpinCount(&Lock->Lock, SpinCount); + if (NT_SUCCESS(Status)) + { + /* Initialize our structure */ + Lock->ReaderCount = 0; + } + else if (Lock->WriterWaitEvent) + { + /* We failed, close the event if we had one */ + NtClose(Lock->WriterWaitEvent); + Lock->WriterWaitEvent = NULL; + } + + /* Return status */ + return Status; +} + +VOID +WSPAPI +SockAcquireRwLockExclusive(IN PSOCK_RW_LOCK Lock) +{ + LONG Count, NewCount; + ULONG_PTR SpinCount; + + /* Acquire the lock */ + RtlEnterCriticalSection(&Lock->Lock); + + /* Check for ReaderCount */ + if (Lock->ReaderCount >= 0) + { + /* Loop while trying to change the count */ + do + { + /* Get the reader count */ + Count = Lock->ReaderCount; + + /* Modify the count so ReaderCount know that a writer is waiting */ + NewCount = -Count - 2; + } while (InterlockedCompareExchange(&Lock->ReaderCount, + NewCount, + Count) != Count); + + /* Check if some ReaderCount are still active */ + if (NewCount != -2) + { + /* Get the spincount of the CS */ + SpinCount = Lock->Lock.SpinCount; + + /* Loop until they are done */ + while (Lock->ReaderCount != -2) + { + /* Check if the CS has a spin count */ + if (SpinCount) + { + /* Spin on it */ + SpinCount--; + } + else + { + /* Do a full wait for ReaderCount */ + SockpWaitForReaderCount(Lock); + break; + } + } + } + } + else + { + /* Acquiring it again, decrement the count to handle this */ + Lock->ReaderCount--; + } +} + +VOID +WSPAPI +SockAcquireRwLockShared(IN PSOCK_RW_LOCK Lock) +{ + BOOL GotLock = FALSE; + LONG Count, NewCount; + + /* Start acquire loop */ + do + { + /* Get the current count */ + Count = Lock->ReaderCount; + + /* Check if a writer is active */ + if (Count < 0) + { + /* Acquire the lock (this will wait for the writer) */ + RtlEnterCriticalSection(&Lock->Lock); + GotLock = TRUE; + + /* Get the counter again */ + Count = Lock->ReaderCount; + if (Count < 0) + { + /* It's still below 0, so this is a recursive acquire */ + NewCount = Count - 1; + } + else + { + /* Increase the count since the writer has finished */ + NewCount = Count + 1; + } + } + else + { + /* No writers are active, increase count */ + NewCount = Count + 1; + } + + /* Update the count */ + NewCount = InterlockedCompareExchange(&Lock->ReaderCount, + NewCount, + Count); + + /* Check if we got the lock */ + if (GotLock) + { + /* Release it */ + RtlLeaveCriticalSection(&Lock->Lock); + GotLock = FALSE; + } + } while (NewCount != Count); +} + +VOID +WSPAPI +SockReleaseRwLockExclusive(IN PSOCK_RW_LOCK Lock) +{ + /* Increase the reader count and check if it's a recursive acquire */ + if (++Lock->ReaderCount == -1) + { + /* This release is the final one, so unhack the reader count */ + Lock->ReaderCount = 0; + } + + /* Leave the RTL CS */ + RtlLeaveCriticalSection(&Lock->Lock); +} + +VOID +WSPAPI +SockReleaseRwLockShared(IN PSOCK_RW_LOCK Lock) +{ + LONG NewCount, Count = Lock->ReaderCount; + + /* Start release loop */ + while (TRUE) + { + /* Check if writers are using the lock */ + if (Count > 0) + { + /* Lock is free, decrement the count */ + NewCount = Count - 1; + } + else + { + /* Lock is busy, increment the count */ + NewCount = Count + 1; + } + + /* Update the count */ + if (InterlockedCompareExchange(&Lock->ReaderCount, NewCount, Count) == Count) + { + /* Count changed sucesfully, was this the last reader? */ + if (NewCount == -1) + { + /* It was, we need to tell the writer about it */ + NtSetEvent(Lock->WriterWaitEvent, NULL); + } + break; + } + } +} + +NTSTATUS +WSPAPI +SockDeleteRwLock(IN PSOCK_RW_LOCK Lock) +{ + /* Check if there's an event */ + if (Lock->WriterWaitEvent) + { + /* Close it */ + NtClose(Lock->WriterWaitEvent); + Lock->WriterWaitEvent = NULL; + } + + /* Free the Crtitical Section */ + return RtlDeleteCriticalSection(&Lock->Lock); +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +SOCK_RW_LOCK SocketGlobalLock; + +/* FUNCTIONS *****************************************************************/ + +VOID +WSPAPI +SockDestroySocket(PSOCKET_INFORMATION Socket) +{ + /* Dereference its helper DLL */ + SockDereferenceHelperDll(Socket->HelperData); + + /* Delete the lock */ + DeleteCriticalSection(&Socket->Lock); + + /* Free the socket */ + RtlFreeHeap(SockPrivateHeap, 0, Socket); +} + +VOID +__inline +WSPAPI +SockDereferenceSocket(IN PSOCKET_INFORMATION Socket) +{ + /* Dereference and see if it's the last count */ + if (!InterlockedDecrement(&Socket->WshContext.RefCount)) + { + /* Destroy the socket */ + SockDestroySocket(Socket); + } +} + +PSOCKET_INFORMATION +WSPAPI +SockImportHandle(IN SOCKET Handle) +{ + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + PWAH_HANDLE WahHandle; + NTSTATUS Status; + ULONG ContextSize; + IO_STATUS_BLOCK IoStatusBlock; + PSOCKET_INFORMATION ImportedSocket = NULL; + UNICODE_STRING TransportName; + + /* Acquire the global lock */ + SockAcquireRwLockExclusive(&SocketGlobalLock); + + /* Make sure that the handle is still invalid */ + WahHandle = WahReferenceContextByHandle(SockContextTable, (HANDLE)Handle); + if (WahHandle) + { + /* Some other thread imported it by now, release the lock and return */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + return (PSOCKET_INFORMATION)WahHandle; + } + + /* Setup the NULL name for possible cleanup later */ + RtlInitUnicodeString(&TransportName, NULL); + + /* Call AFD to get the context size */ + Status = NtDeviceIoControlFile((HANDLE)Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_GET_CONTEXT_SIZE, + NULL, + 0, + &ContextSize, + sizeof(ContextSize)); + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + SockWaitForSingleObject(ThreadData->EventHandle, + Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Make sure we didn't fail, and that this is a valid context */ + if (!NT_SUCCESS(Status) || (ContextSize < sizeof(SOCK_SHARED_INFO))) + { + /* Fail (the error handler will convert to Win32 Status) */ + goto error; + } + +error: + /* Release the lock */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + + return ImportedSocket; +} + +INT +WSPAPI +SockSetInformation(IN PSOCKET_INFORMATION Socket, + IN ULONG AfdInformationClass, + IN PBOOLEAN Boolean OPTIONAL, + IN PULONG Ulong OPTIONAL, + IN PLARGE_INTEGER LargeInteger OPTIONAL) +{ + IO_STATUS_BLOCK IoStatusBlock; + AFD_INFO AfdInfo; + NTSTATUS Status; + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + + /* Set Info Class */ + AfdInfo.InformationClass = AfdInformationClass; + + /* Set Information */ + if (Boolean) + { + AfdInfo.Information.Boolean = *Boolean; + } + else if (Ulong) + { + AfdInfo.Information.Ulong = *Ulong; + } + else + { + AfdInfo.Information.LargeInteger = *LargeInteger; + } + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_GET_INFO, + &AfdInfo, + sizeof(AfdInfo), + NULL, + 0); + /* Check if we have to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for the operation to finish */ + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Handle failure */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + return NtStatusToSocketError(Status); + } + + /* Return to caller */ + return NO_ERROR; +} + +INT +WSPAPI +SockGetInformation(IN PSOCKET_INFORMATION Socket, + IN ULONG AfdInformationClass, + IN PVOID ExtraData OPTIONAL, + IN ULONG ExtraDataSize, + IN OUT PBOOLEAN Boolean OPTIONAL, + IN OUT PULONG Ulong OPTIONAL, + IN OUT PLARGE_INTEGER LargeInteger OPTIONAL) +{ + ULONG InfoLength; + IO_STATUS_BLOCK IoStatusBlock; + PAFD_INFO AfdInfo; + AFD_INFO InfoData; + NTSTATUS Status; + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + + /* Check if extra data is there */ + if (ExtraData && ExtraDataSize) + { + /* Allocate space for it */ + InfoLength = sizeof(InfoData) + ExtraDataSize; + AfdInfo = (PAFD_INFO)SockAllocateHeapRoutine(SockPrivateHeap, + 0, + InfoLength); + if (!AfdInfo) return WSAENOBUFS; + + /* Copy the extra data */ + RtlCopyMemory(AfdInfo + 1, ExtraData, ExtraDataSize); + } + else + { + /* Use local buffer */ + AfdInfo = &InfoData; + InfoLength = sizeof(InfoData); + } + + /* Set Info Class */ + AfdInfo->InformationClass = AfdInformationClass; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_GET_INFO, + &InfoData, + InfoLength, + &InfoData, + sizeof(InfoData)); + /* Check if we have to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for the operation to finish */ + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Handle failure */ + if (!NT_SUCCESS(Status)) + { + /* Check if we have to free the data */ + if (AfdInfo != &InfoData) RtlFreeHeap(SockPrivateHeap, 0, AfdInfo); + + /* Fail */ + return NtStatusToSocketError(Status); + } + + /* Return Information */ + if (Boolean) + { + *Boolean = AfdInfo->Information.Boolean; + } + else if (Ulong) + { + *Ulong = AfdInfo->Information.Ulong; + } + else + { + *LargeInteger = AfdInfo->Information.LargeInteger; + } + + /* Check if we have to free the data */ + if (AfdInfo != &InfoData) RtlFreeHeap(SockPrivateHeap, 0, AfdInfo); + + /* Return to caller */ + return NO_ERROR; +} + +INT +WSPAPI +SockSetHandleContext(IN PSOCKET_INFORMATION Socket) +{ + IO_STATUS_BLOCK IoStatusBlock; + CHAR ContextData[256]; + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + PVOID Context; + ULONG_PTR ContextPos; + ULONG ContextLength; + INT HelperContextLength; + INT ErrorCode; + NTSTATUS Status; + + /* Find out how big the helper DLL context is */ + ErrorCode = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, + Socket->Handle, + Socket->TdiAddressHandle, + Socket->TdiConnectionHandle, + SOL_INTERNAL, + SO_CONTEXT, + NULL, + &HelperContextLength); + + /* Calculate the total space needed */ + ContextLength = sizeof(SOCK_SHARED_INFO) + + 2 * Socket->HelperData->MaxWSAddressLength + + sizeof(ULONG) + HelperContextLength; + + /* See if our stack can hold it */ + if (ContextLength <= sizeof(ContextData)) + { + /* Use our stack */ + Context = ContextData; + } + else + { + /* Allocate from heap */ + Context = SockAllocateHeapRoutine(SockPrivateHeap, 0, ContextLength); + if (!Context) return WSAENOBUFS; + } + + /* + * Create Context, this includes: + * Shared Socket Data, Helper Context Length, Local and Remote Addresses + * and finally the actual helper context. + */ + ContextPos = (ULONG_PTR)Context; + RtlCopyMemory((PVOID)ContextPos, + &Socket->SharedData, + sizeof(SOCK_SHARED_INFO)); + ContextPos += sizeof(SOCK_SHARED_INFO); + *(PULONG)ContextPos = HelperContextLength; + ContextPos += sizeof(ULONG); + RtlCopyMemory((PVOID)ContextPos, + Socket->LocalAddress, + Socket->HelperData->MaxWSAddressLength); + ContextPos += Socket->HelperData->MaxWSAddressLength; + RtlCopyMemory((PVOID)ContextPos, + Socket->RemoteAddress, + Socket->HelperData->MaxWSAddressLength); + ContextPos += Socket->HelperData->MaxWSAddressLength; + + /* Now get the helper context */ + ErrorCode = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, + Socket->Handle, + Socket->TdiAddressHandle, + Socket->TdiConnectionHandle, + SOL_INTERNAL, + SO_CONTEXT, + (PVOID)ContextPos, + &HelperContextLength); + /* Now give it to AFD */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_SET_CONTEXT, + Context, + ContextLength, + NULL, + 0); + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check if we need to free from heap */ + if (Context != ContextData) RtlFreeHeap(SockPrivateHeap, 0, Context); + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Convert and return error code */ + ErrorCode = NtStatusToSocketError(Status); + return ErrorCode; + } + + /* Return success */ + return NO_ERROR; +} + +INT +WSPAPI +SockIsAddressConsistentWithConstrainedGroup(IN PSOCKET_INFORMATION Socket, + IN GROUP Group, + IN PSOCKADDR SocketAddress, + IN INT SocketAddressLength) +{ + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + INT ErrorCode; + PAFD_VALIDATE_GROUP_DATA ValidateGroupData; + NTSTATUS Status; + IO_STATUS_BLOCK IoStatusBlock; + ULONG ValidateGroupSize; + CHAR ValidateBuffer[sizeof(AFD_VALIDATE_GROUP_DATA) + MAX_TDI_ADDRESS_LENGTH]; + + /* Calculate the length of the buffer */ + ValidateGroupSize = sizeof(AFD_VALIDATE_GROUP_DATA) + + sizeof(TRANSPORT_ADDRESS) + + Socket->HelperData->MaxTDIAddressLength; + + /* Check if our stack buffer is large enough */ + if (ValidateGroupSize <= sizeof(ValidateBuffer)) + { + /* Use the stack */ + ValidateGroupData = (PVOID)ValidateBuffer; + } + else + { + /* Allocate from heap */ + ValidateGroupData = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + ValidateGroupSize); + if (!ValidateGroupData) return WSAENOBUFS; + } + + /* Convert the address to TDI format */ + ErrorCode = SockBuildTdiAddress(&ValidateGroupData->Address, + SocketAddress, + SocketAddressLength); + if (ErrorCode != NO_ERROR) return ErrorCode; + + /* Tell AFD which group to check, and let AFD validate it */ + ValidateGroupData->GroupId = Group; + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_VALIDATE_GROUP, + ValidateGroupData, + ValidateGroupSize, + NULL, + 0); + + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check if we need to free the data from heap */ + if (ValidateGroupData != (PVOID)ValidateBuffer) + { + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, ValidateGroupData); + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + return NtStatusToSocketError(Status); + } + + /* Return success */ + return NO_ERROR; +} + + +INT +WSPAPI +SockGetTdiHandles(IN PSOCKET_INFORMATION Socket) +{ + AFD_TDI_HANDLE_DATA TdiHandleInfo; + NTSTATUS Status; + IO_STATUS_BLOCK IoStatusBlock; + ULONG InfoType = 0; + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + + /* See which handle(s) we need */ + if (!Socket->TdiAddressHandle) InfoType |= AFD_ADDRESS_HANDLE; + if (!Socket->TdiConnectionHandle) InfoType |= AFD_CONNECTION_HANDLE; + + /* Make sure we need one */ + if (!InfoType) return NO_ERROR; + + /* Call AFD */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_GET_TDI_HANDLES, + &InfoType, + sizeof(InfoType), + &TdiHandleInfo, + sizeof(TdiHandleInfo)); + /* Check if we shoudl wait */ + if (Status == STATUS_PENDING) + { + /* Wait on it */ + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + + /* Update status */ + Status = IoStatusBlock.Status; + } + + /* Check for success */ + if (!NT_SUCCESS(Status)) return NtStatusToSocketError(Status); + + /* Return handles */ + if (!Socket->TdiAddressHandle) + { + Socket->TdiAddressHandle = TdiHandleInfo.TdiAddressHandle; + } + if (!Socket->TdiConnectionHandle) + { + Socket->TdiConnectionHandle = TdiHandleInfo.TdiConnectionHandle; + } + + /* Return */ + return NO_ERROR; +} + +BOOL +WSPAPI +SockWaitForSingleObject(IN HANDLE Handle, + IN SOCKET SocketHandle, + IN DWORD BlockingFlags, + IN DWORD TimeoutFlags) +{ + LARGE_INTEGER Timeout, CurrentTime, DueTime; + NTSTATUS Status; + PSOCKET_INFORMATION Socket = NULL; + BOOLEAN CallHook, UseTimeout; + LPBLOCKINGCALLBACK BlockingHook; + DWORD_PTR Context; + INT ErrorCode; + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + + /* Start with a simple 0.5 second wait */ + Timeout.QuadPart = Int32x32To64(-10000, 500); + Status = NtWaitForSingleObject(Handle, TRUE, &Timeout); + if (Status == STATUS_SUCCESS) return TRUE; + + /* Check if our flags require the socket structure */ + if ((BlockingFlags == MAYBE_BLOCKING_HOOK) || + (BlockingFlags == ALWAYS_BLOCKING_HOOK) || + (TimeoutFlags == SEND_TIMEOUT) || + (TimeoutFlags == RECV_TIMEOUT)) + { + /* Get the socket */ + Socket = SockFindAndReferenceSocket(SocketHandle, FALSE); + if (!Socket) + { + /* We must be waiting on a non-socket for some reason? */ + NtWaitForSingleObject(Handle, TRUE, NULL); + return TRUE; + } + } + + /* Check the blocking flags */ + if (BlockingFlags == ALWAYS_BLOCKING_HOOK) + { + /* Always call it */ + CallHook = TRUE; + } + else if (BlockingFlags == MAYBE_BLOCKING_HOOK) + { + /* Check if we have to call it */ + CallHook = !Socket->SharedData.NonBlocking; + } + else if (BlockingFlags == NO_BLOCKING_HOOK) + { + /* Never call it*/ + CallHook = FALSE; + } + else + { + if (Socket) SockDereferenceSocket(Socket); + return FALSE; + } + + /* Check if we call it */ + if (CallHook) + { + /* Check if it actually exists */ + SockUpcallTable->lpWPUQueryBlockingCallback(Socket->SharedData.CatalogEntryId, + &BlockingHook, + &Context, + &ErrorCode); + + /* See if we'll call it */ + CallHook = (BlockingHook != NULL); + } + + /* Now check the timeout flags */ + if (TimeoutFlags == NO_TIMEOUT) + { + /* None at all */ + UseTimeout = FALSE; + } + else if (TimeoutFlags == SEND_TIMEOUT) + { + /* See if there's a Send Timeout */ + if (Socket->SharedData.SendTimeout) + { + /* Use it */ + UseTimeout = TRUE; + Timeout = RtlEnlargedIntegerMultiply(Socket->SharedData.SendTimeout, + 10 * 1000); + } + else + { + /* There isn't any */ + UseTimeout = FALSE; + } + } + else if (TimeoutFlags == RECV_TIMEOUT) + { + /* See if there's a Receive Timeout */ + if (Socket->SharedData.RecvTimeout) + { + /* Use it */ + UseTimeout = TRUE; + Timeout = RtlEnlargedIntegerMultiply(Socket->SharedData.RecvTimeout, + 10 * 1000); + } + else + { + /* There isn't any */ + UseTimeout = FALSE; + } + } + else + { + if (Socket) SockDereferenceSocket(Socket); + return FALSE; + } + + /* We don't need the socket anymore */ + if (Socket) SockDereferenceSocket(Socket); + + /* Check for timeout */ + if (UseTimeout) + { + /* Calculate the absolute time when the wait ends */ + Status = NtQuerySystemTime(&CurrentTime); + DueTime.QuadPart = CurrentTime.QuadPart + Timeout.QuadPart; + } + else + { + /* Infinite wait */ + DueTime.LowPart = -1; + DueTime.HighPart = 0x7FFFFFFF; + } + + /* Check for blocking hook call */ + if (CallHook) + { + /* We're calling it, so we won't actually be waiting */ + Timeout.LowPart = -1; + Timeout.HighPart = -1; + } + else + { + /* We'll be waiting till the Due Time */ + Timeout = DueTime; + } + + /* Now write data to the TEB so we'll know what's going on */ + ThreadData->CancelIo = FALSE; + ThreadData->SocketHandle = SocketHandle; + + /* Start wait loop */ + do + { + /* Call the hook */ + if (CallHook) (BlockingHook(Context)); + + /* Check if we were cancelled */ + if (ThreadData->CancelIo) + { + /* Infinite timeout and wait for official cancel */ + Timeout.LowPart = -1; + Timeout.HighPart = 0x7FFFFFFF; + } + else + { + /* Check if we're due */ + Status = NtQuerySystemTime(&CurrentTime); + if (CurrentTime.QuadPart > DueTime.QuadPart) + { + /* We're out */ + Status = STATUS_TIMEOUT; + break; + } + } + + /* Do the actual wait */ + Status = NtWaitForSingleObject(Handle, TRUE, &Timeout); + } while ((Status == STATUS_USER_APC) || + (Status == STATUS_ALERTED) || + (Status == STATUS_TIMEOUT)); + + /* Reset thread data */ + ThreadData->SocketHandle = INVALID_SOCKET; + + /* Return to caller */ + if (Status == STATUS_SUCCESS) return TRUE; + return FALSE; +} + +PSOCKET_INFORMATION +WSPAPI +SockFindAndReferenceSocket(IN SOCKET Handle, + IN BOOLEAN Import) +{ + PWAH_HANDLE WahHandle; + + /* Get it from our table and return it */ + WahHandle = WahReferenceContextByHandle(SockContextTable, (HANDLE)Handle); + if (WahHandle) return (PSOCKET_INFORMATION)WahHandle; + + /* Couldn't find it, shoudl we import it? */ + if (Import) return SockImportHandle(Handle); + + /* Nothing found */ + return NULL; +} + +INT +WSPAPI +SockBuildTdiAddress(OUT PTRANSPORT_ADDRESS TdiAddress, + IN PSOCKADDR Sockaddr, + IN INT SockaddrLength) +{ + /* Setup the TDI Address */ + TdiAddress->TAAddressCount = 1; + TdiAddress->Address[0].AddressLength = (USHORT)SockaddrLength - + sizeof(Sockaddr->sa_family); + + /* Copy it */ + RtlCopyMemory(&TdiAddress->Address[0].AddressType, Sockaddr, SockaddrLength); + + /* Return */ + return NO_ERROR; +} + +INT +WSPAPI +SockBuildSockaddr(OUT PSOCKADDR Sockaddr, + OUT PINT SockaddrLength, + IN PTRANSPORT_ADDRESS TdiAddress) +{ + /* Calculate the length it will take */ + *SockaddrLength = TdiAddress->Address[0].AddressLength + + sizeof(Sockaddr->sa_family); + + /* Copy it */ + RtlCopyMemory(Sockaddr, &TdiAddress->Address[0].AddressType, *SockaddrLength); + + /* Return */ + return NO_ERROR; +} + +BOOLEAN +WSPAPI +SockIsSocketConnected(IN PSOCKET_INFORMATION Socket) +{ + LARGE_INTEGER Timeout; + PVOID Context; + PVOID AsyncCallback; + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + + /* Check if there is an async connect in progress, but still unprocessed */ + while ((Socket->AsyncData) && + (Socket->AsyncData->IoStatusBlock.Status != STATUS_PENDING)) + { + /* The socket will be locked, release it */ + LeaveCriticalSection(&Socket->Lock); + + /* Setup the timeout and wait on completion */ + Timeout.QuadPart = 0; + Status = NtRemoveIoCompletion(SockAsyncQueuePort, + &AsyncCallback, + &Context, + &IoStatusBlock, + &Timeout); + + /* Check for success */ + if (Status == STATUS_SUCCESS) + { + /* Check if we're supposed to terminate */ + if (AsyncCallback != (PVOID)-1) + { + /* Handle the Async */ + SockHandleAsyncIndication(AsyncCallback, Context, &IoStatusBlock); + } + else + { + /* Terminate it */ + Status = NtSetIoCompletion(SockAsyncQueuePort, + (PVOID)-1, + (PVOID)-1, + 0, + 0); + + /* Acquire the lock and break out */ + EnterCriticalSection(&Socket->Lock); + break; + } + } + + /* Acquire the socket lock again */ + EnterCriticalSection(&Socket->Lock); + } + + /* Check if it's already connected */ + if (Socket->SharedData.State == SocketConnected) return TRUE; + return FALSE; +} + +VOID +WSPAPI +SockCancelIo(IN SOCKET Handle) +{ + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + + /* Cancel the I/O */ + Status = NtCancelIoFile((HANDLE)Handle, &IoStatusBlock); +} + +VOID +WSPAPI +SockIoCompletion(IN PVOID ApcContext, + IN PIO_STATUS_BLOCK IoStatusBlock, + DWORD Reserved) +{ + LPWSAOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine = ApcContext; + INT ErrorCode; + DWORD BytesSent; + DWORD Flags = 0; + LPWSAOVERLAPPED lpOverlapped; + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + + /* Check if this was an error */ + if (NT_ERROR(IoStatusBlock->Status)) + { + /* Check if it was anything but a simple cancel */ + if (IoStatusBlock->Status != STATUS_CANCELLED) + { + /* Convert it */ + ErrorCode = NtStatusToSocketError(IoStatusBlock->Status); + } + else + { + /* Use the right error */ + ErrorCode = WSA_OPERATION_ABORTED; + } + + /* Either ways, nothing was done */ + BytesSent = 0; + } + else + { + /* No error and check how many bytes were sent */ + ErrorCode = NO_ERROR; + BytesSent = PtrToUlong(IoStatusBlock->Information); + + /* Check the status */ + if (IoStatusBlock->Status == STATUS_BUFFER_OVERFLOW) + { + /* This was an error */ + ErrorCode = WSAEMSGSIZE; + } + else if (IoStatusBlock->Status == STATUS_RECEIVE_PARTIAL) + { + /* Partial receive */ + Flags = MSG_PARTIAL; + } + else if (IoStatusBlock->Status == STATUS_RECEIVE_EXPEDITED) + { + /* OOB receive */ + Flags = MSG_OOB; + } + else if (IoStatusBlock->Status == STATUS_RECEIVE_PARTIAL_EXPEDITED) + { + /* Partial OOB receive */ + Flags = MSG_OOB | MSG_PARTIAL; + } + } + + /* Get the overlapped structure */ + lpOverlapped = CONTAINING_RECORD(IoStatusBlock, WSAOVERLAPPED, Internal); + + /* Call it */ + CompletionRoutine(ErrorCode, BytesSent, lpOverlapped, Flags); + + /* Decrease pending APCs */ + ThreadData->PendingAPCs--; + InterlockedDecrement(&SockProcessPendingAPCCount); +} + +VOID +WSPAPI +SockpWaitForReaderCount(IN PSOCK_RW_LOCK Lock) +{ + NTSTATUS Status; + LARGE_INTEGER Timeout; + + /* Switch threads to see if the lock gets released that way */ + Timeout.QuadPart = 0; + NtDelayExecution(FALSE, &Timeout); + if (Lock->ReaderCount == -2) return; + + /* Either the thread isn't executing (priority inversion) or it's a hog */ + if (!Lock->WriterWaitEvent) + { + /* We don't have an event to wait on yet, allocate it */ + Status = NtCreateEvent(&Lock->WriterWaitEvent, + EVENT_ALL_ACCESS, + NULL, + SynchronizationEvent, + FALSE); + if (!NT_SUCCESS(Status)) + { + /* We can't get an event, do a manual loop */ + Timeout.QuadPart = Int32x32To64(1000, -100); + while (Lock->ReaderCount != -2) NtDelayExecution(FALSE, &Timeout); + } + } + + /* We have en event, now increment the reader count to signal them */ + if (InterlockedIncrement(&Lock->ReaderCount) != -1) + { + /* Wait for them to signal us */ + NtWaitForSingleObject(&Lock->WriterWaitEvent, FALSE, NULL); + } + + /* Finally it's free */ + Lock->ReaderCount = -2; +} + +NTSTATUS +WSPAPI +SockInitializeRwLockAndSpinCount(IN PSOCK_RW_LOCK Lock, + IN ULONG SpinCount) +{ + NTSTATUS Status; + + /* check if this is a special event create request */ + if (SpinCount & 0x80000000) + { + /* Create the event */ + Status = NtCreateEvent(&Lock->WriterWaitEvent, + EVENT_ALL_ACCESS, + NULL, + SynchronizationEvent, + FALSE); + if (!NT_SUCCESS(Status)) return Status; + } + + /* Initialize the lock */ + Status = RtlInitializeCriticalSectionAndSpinCount(&Lock->Lock, SpinCount); + if (NT_SUCCESS(Status)) + { + /* Initialize our structure */ + Lock->ReaderCount = 0; + } + else if (Lock->WriterWaitEvent) + { + /* We failed, close the event if we had one */ + NtClose(Lock->WriterWaitEvent); + Lock->WriterWaitEvent = NULL; + } + + /* Return status */ + return Status; +} + +VOID +WSPAPI +SockAcquireRwLockExclusive(IN PSOCK_RW_LOCK Lock) +{ + LONG Count, NewCount; + ULONG_PTR SpinCount; + + /* Acquire the lock */ + RtlEnterCriticalSection(&Lock->Lock); + + /* Check for ReaderCount */ + if (Lock->ReaderCount >= 0) + { + /* Loop while trying to change the count */ + do + { + /* Get the reader count */ + Count = Lock->ReaderCount; + + /* Modify the count so ReaderCount know that a writer is waiting */ + NewCount = -Count - 2; + } while (InterlockedCompareExchange(&Lock->ReaderCount, + NewCount, + Count) != Count); + + /* Check if some ReaderCount are still active */ + if (NewCount != -2) + { + /* Get the spincount of the CS */ + SpinCount = Lock->Lock.SpinCount; + + /* Loop until they are done */ + while (Lock->ReaderCount != -2) + { + /* Check if the CS has a spin count */ + if (SpinCount) + { + /* Spin on it */ + SpinCount--; + } + else + { + /* Do a full wait for ReaderCount */ + SockpWaitForReaderCount(Lock); + break; + } + } + } + } + else + { + /* Acquiring it again, decrement the count to handle this */ + Lock->ReaderCount--; + } +} + +VOID +WSPAPI +SockAcquireRwLockShared(IN PSOCK_RW_LOCK Lock) +{ + BOOL GotLock = FALSE; + LONG Count, NewCount; + + /* Start acquire loop */ + do + { + /* Get the current count */ + Count = Lock->ReaderCount; + + /* Check if a writer is active */ + if (Count < 0) + { + /* Acquire the lock (this will wait for the writer) */ + RtlEnterCriticalSection(&Lock->Lock); + GotLock = TRUE; + + /* Get the counter again */ + Count = Lock->ReaderCount; + if (Count < 0) + { + /* It's still below 0, so this is a recursive acquire */ + NewCount = Count - 1; + } + else + { + /* Increase the count since the writer has finished */ + NewCount = Count + 1; + } + } + else + { + /* No writers are active, increase count */ + NewCount = Count + 1; + } + + /* Update the count */ + NewCount = InterlockedCompareExchange(&Lock->ReaderCount, + NewCount, + Count); + + /* Check if we got the lock */ + if (GotLock) + { + /* Release it */ + RtlLeaveCriticalSection(&Lock->Lock); + GotLock = FALSE; + } + } while (NewCount != Count); +} + +VOID +WSPAPI +SockReleaseRwLockExclusive(IN PSOCK_RW_LOCK Lock) +{ + /* Increase the reader count and check if it's a recursive acquire */ + if (++Lock->ReaderCount == -1) + { + /* This release is the final one, so unhack the reader count */ + Lock->ReaderCount = 0; + } + + /* Leave the RTL CS */ + RtlLeaveCriticalSection(&Lock->Lock); +} + +VOID +WSPAPI +SockReleaseRwLockShared(IN PSOCK_RW_LOCK Lock) +{ + LONG NewCount, Count = Lock->ReaderCount; + + /* Start release loop */ + while (TRUE) + { + /* Check if writers are using the lock */ + if (Count > 0) + { + /* Lock is free, decrement the count */ + NewCount = Count - 1; + } + else + { + /* Lock is busy, increment the count */ + NewCount = Count + 1; + } + + /* Update the count */ + if (InterlockedCompareExchange(&Lock->ReaderCount, NewCount, Count) == Count) + { + /* Count changed sucesfully, was this the last reader? */ + if (NewCount == -1) + { + /* It was, we need to tell the writer about it */ + NtSetEvent(Lock->WriterWaitEvent, NULL); + } + break; + } + } +} + +NTSTATUS +WSPAPI +SockDeleteRwLock(IN PSOCK_RW_LOCK Lock) +{ + /* Check if there's an event */ + if (Lock->WriterWaitEvent) + { + /* Close it */ + NtClose(Lock->WriterWaitEvent); + Lock->WriterWaitEvent = NULL; + } + + /* Free the Crtitical Section */ + return RtlDeleteCriticalSection(&Lock->Lock); +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +SOCK_RW_LOCK SocketGlobalLock; + +/* FUNCTIONS *****************************************************************/ + +VOID +WSPAPI +SockDestroySocket(PSOCKET_INFORMATION Socket) +{ + /* Dereference its helper DLL */ + SockDereferenceHelperDll(Socket->HelperData); + + /* Delete the lock */ + DeleteCriticalSection(&Socket->Lock); + + /* Free the socket */ + RtlFreeHeap(SockPrivateHeap, 0, Socket); +} + +VOID +__inline +WSPAPI +SockDereferenceSocket(IN PSOCKET_INFORMATION Socket) +{ + /* Dereference and see if it's the last count */ + if (!InterlockedDecrement(&Socket->WshContext.RefCount)) + { + /* Destroy the socket */ + SockDestroySocket(Socket); + } +} + +PSOCKET_INFORMATION +WSPAPI +SockImportHandle(IN SOCKET Handle) +{ + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + PWAH_HANDLE WahHandle; + NTSTATUS Status; + ULONG ContextSize; + IO_STATUS_BLOCK IoStatusBlock; + PSOCKET_INFORMATION ImportedSocket = NULL; + UNICODE_STRING TransportName; + + /* Acquire the global lock */ + SockAcquireRwLockExclusive(&SocketGlobalLock); + + /* Make sure that the handle is still invalid */ + WahHandle = WahReferenceContextByHandle(SockContextTable, (HANDLE)Handle); + if (WahHandle) + { + /* Some other thread imported it by now, release the lock and return */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + return (PSOCKET_INFORMATION)WahHandle; + } + + /* Setup the NULL name for possible cleanup later */ + RtlInitUnicodeString(&TransportName, NULL); + + /* Call AFD to get the context size */ + Status = NtDeviceIoControlFile((HANDLE)Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_GET_CONTEXT_SIZE, + NULL, + 0, + &ContextSize, + sizeof(ContextSize)); + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + SockWaitForSingleObject(ThreadData->EventHandle, + Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Make sure we didn't fail, and that this is a valid context */ + if (!NT_SUCCESS(Status) || (ContextSize < sizeof(SOCK_SHARED_INFO))) + { + /* Fail (the error handler will convert to Win32 Status) */ + goto error; + } + +error: + /* Release the lock */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + + return ImportedSocket; +} + +INT +WSPAPI +SockSetInformation(IN PSOCKET_INFORMATION Socket, + IN ULONG AfdInformationClass, + IN PBOOLEAN Boolean OPTIONAL, + IN PULONG Ulong OPTIONAL, + IN PLARGE_INTEGER LargeInteger OPTIONAL) +{ + IO_STATUS_BLOCK IoStatusBlock; + AFD_INFO AfdInfo; + NTSTATUS Status; + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + + /* Set Info Class */ + AfdInfo.InformationClass = AfdInformationClass; + + /* Set Information */ + if (Boolean) + { + AfdInfo.Information.Boolean = *Boolean; + } + else if (Ulong) + { + AfdInfo.Information.Ulong = *Ulong; + } + else + { + AfdInfo.Information.LargeInteger = *LargeInteger; + } + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_GET_INFO, + &AfdInfo, + sizeof(AfdInfo), + NULL, + 0); + /* Check if we have to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for the operation to finish */ + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Handle failure */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + return NtStatusToSocketError(Status); + } + + /* Return to caller */ + return NO_ERROR; +} + +INT +WSPAPI +SockGetInformation(IN PSOCKET_INFORMATION Socket, + IN ULONG AfdInformationClass, + IN PVOID ExtraData OPTIONAL, + IN ULONG ExtraDataSize, + IN OUT PBOOLEAN Boolean OPTIONAL, + IN OUT PULONG Ulong OPTIONAL, + IN OUT PLARGE_INTEGER LargeInteger OPTIONAL) +{ + ULONG InfoLength; + IO_STATUS_BLOCK IoStatusBlock; + PAFD_INFO AfdInfo; + AFD_INFO InfoData; + NTSTATUS Status; + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + + /* Check if extra data is there */ + if (ExtraData && ExtraDataSize) + { + /* Allocate space for it */ + InfoLength = sizeof(InfoData) + ExtraDataSize; + AfdInfo = (PAFD_INFO)SockAllocateHeapRoutine(SockPrivateHeap, + 0, + InfoLength); + if (!AfdInfo) return WSAENOBUFS; + + /* Copy the extra data */ + RtlCopyMemory(AfdInfo + 1, ExtraData, ExtraDataSize); + } + else + { + /* Use local buffer */ + AfdInfo = &InfoData; + InfoLength = sizeof(InfoData); + } + + /* Set Info Class */ + AfdInfo->InformationClass = AfdInformationClass; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_GET_INFO, + &InfoData, + InfoLength, + &InfoData, + sizeof(InfoData)); + /* Check if we have to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for the operation to finish */ + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Handle failure */ + if (!NT_SUCCESS(Status)) + { + /* Check if we have to free the data */ + if (AfdInfo != &InfoData) RtlFreeHeap(SockPrivateHeap, 0, AfdInfo); + + /* Fail */ + return NtStatusToSocketError(Status); + } + + /* Return Information */ + if (Boolean) + { + *Boolean = AfdInfo->Information.Boolean; + } + else if (Ulong) + { + *Ulong = AfdInfo->Information.Ulong; + } + else + { + *LargeInteger = AfdInfo->Information.LargeInteger; + } + + /* Check if we have to free the data */ + if (AfdInfo != &InfoData) RtlFreeHeap(SockPrivateHeap, 0, AfdInfo); + + /* Return to caller */ + return NO_ERROR; +} + +INT +WSPAPI +SockSetHandleContext(IN PSOCKET_INFORMATION Socket) +{ + IO_STATUS_BLOCK IoStatusBlock; + CHAR ContextData[256]; + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + PVOID Context; + ULONG_PTR ContextPos; + ULONG ContextLength; + INT HelperContextLength; + INT ErrorCode; + NTSTATUS Status; + + /* Find out how big the helper DLL context is */ + ErrorCode = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, + Socket->Handle, + Socket->TdiAddressHandle, + Socket->TdiConnectionHandle, + SOL_INTERNAL, + SO_CONTEXT, + NULL, + &HelperContextLength); + + /* Calculate the total space needed */ + ContextLength = sizeof(SOCK_SHARED_INFO) + + 2 * Socket->HelperData->MaxWSAddressLength + + sizeof(ULONG) + HelperContextLength; + + /* See if our stack can hold it */ + if (ContextLength <= sizeof(ContextData)) + { + /* Use our stack */ + Context = ContextData; + } + else + { + /* Allocate from heap */ + Context = SockAllocateHeapRoutine(SockPrivateHeap, 0, ContextLength); + if (!Context) return WSAENOBUFS; + } + + /* + * Create Context, this includes: + * Shared Socket Data, Helper Context Length, Local and Remote Addresses + * and finally the actual helper context. + */ + ContextPos = (ULONG_PTR)Context; + RtlCopyMemory((PVOID)ContextPos, + &Socket->SharedData, + sizeof(SOCK_SHARED_INFO)); + ContextPos += sizeof(SOCK_SHARED_INFO); + *(PULONG)ContextPos = HelperContextLength; + ContextPos += sizeof(ULONG); + RtlCopyMemory((PVOID)ContextPos, + Socket->LocalAddress, + Socket->HelperData->MaxWSAddressLength); + ContextPos += Socket->HelperData->MaxWSAddressLength; + RtlCopyMemory((PVOID)ContextPos, + Socket->RemoteAddress, + Socket->HelperData->MaxWSAddressLength); + ContextPos += Socket->HelperData->MaxWSAddressLength; + + /* Now get the helper context */ + ErrorCode = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, + Socket->Handle, + Socket->TdiAddressHandle, + Socket->TdiConnectionHandle, + SOL_INTERNAL, + SO_CONTEXT, + (PVOID)ContextPos, + &HelperContextLength); + /* Now give it to AFD */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_SET_CONTEXT, + Context, + ContextLength, + NULL, + 0); + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check if we need to free from heap */ + if (Context != ContextData) RtlFreeHeap(SockPrivateHeap, 0, Context); + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Convert and return error code */ + ErrorCode = NtStatusToSocketError(Status); + return ErrorCode; + } + + /* Return success */ + return NO_ERROR; +} + +INT +WSPAPI +SockIsAddressConsistentWithConstrainedGroup(IN PSOCKET_INFORMATION Socket, + IN GROUP Group, + IN PSOCKADDR SocketAddress, + IN INT SocketAddressLength) +{ + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + INT ErrorCode; + PAFD_VALIDATE_GROUP_DATA ValidateGroupData; + NTSTATUS Status; + IO_STATUS_BLOCK IoStatusBlock; + ULONG ValidateGroupSize; + CHAR ValidateBuffer[sizeof(AFD_VALIDATE_GROUP_DATA) + MAX_TDI_ADDRESS_LENGTH]; + + /* Calculate the length of the buffer */ + ValidateGroupSize = sizeof(AFD_VALIDATE_GROUP_DATA) + + sizeof(TRANSPORT_ADDRESS) + + Socket->HelperData->MaxTDIAddressLength; + + /* Check if our stack buffer is large enough */ + if (ValidateGroupSize <= sizeof(ValidateBuffer)) + { + /* Use the stack */ + ValidateGroupData = (PVOID)ValidateBuffer; + } + else + { + /* Allocate from heap */ + ValidateGroupData = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + ValidateGroupSize); + if (!ValidateGroupData) return WSAENOBUFS; + } + + /* Convert the address to TDI format */ + ErrorCode = SockBuildTdiAddress(&ValidateGroupData->Address, + SocketAddress, + SocketAddressLength); + if (ErrorCode != NO_ERROR) return ErrorCode; + + /* Tell AFD which group to check, and let AFD validate it */ + ValidateGroupData->GroupId = Group; + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_VALIDATE_GROUP, + ValidateGroupData, + ValidateGroupSize, + NULL, + 0); + + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check if we need to free the data from heap */ + if (ValidateGroupData != (PVOID)ValidateBuffer) + { + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, ValidateGroupData); + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + return NtStatusToSocketError(Status); + } + + /* Return success */ + return NO_ERROR; +} + + +INT +WSPAPI +SockGetTdiHandles(IN PSOCKET_INFORMATION Socket) +{ + AFD_TDI_HANDLE_DATA TdiHandleInfo; + NTSTATUS Status; + IO_STATUS_BLOCK IoStatusBlock; + ULONG InfoType = 0; + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + + /* See which handle(s) we need */ + if (!Socket->TdiAddressHandle) InfoType |= AFD_ADDRESS_HANDLE; + if (!Socket->TdiConnectionHandle) InfoType |= AFD_CONNECTION_HANDLE; + + /* Make sure we need one */ + if (!InfoType) return NO_ERROR; + + /* Call AFD */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_GET_TDI_HANDLES, + &InfoType, + sizeof(InfoType), + &TdiHandleInfo, + sizeof(TdiHandleInfo)); + /* Check if we shoudl wait */ + if (Status == STATUS_PENDING) + { + /* Wait on it */ + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + + /* Update status */ + Status = IoStatusBlock.Status; + } + + /* Check for success */ + if (!NT_SUCCESS(Status)) return NtStatusToSocketError(Status); + + /* Return handles */ + if (!Socket->TdiAddressHandle) + { + Socket->TdiAddressHandle = TdiHandleInfo.TdiAddressHandle; + } + if (!Socket->TdiConnectionHandle) + { + Socket->TdiConnectionHandle = TdiHandleInfo.TdiConnectionHandle; + } + + /* Return */ + return NO_ERROR; +} + +BOOL +WSPAPI +SockWaitForSingleObject(IN HANDLE Handle, + IN SOCKET SocketHandle, + IN DWORD BlockingFlags, + IN DWORD TimeoutFlags) +{ + LARGE_INTEGER Timeout, CurrentTime, DueTime; + NTSTATUS Status; + PSOCKET_INFORMATION Socket = NULL; + BOOLEAN CallHook, UseTimeout; + LPBLOCKINGCALLBACK BlockingHook; + DWORD_PTR Context; + INT ErrorCode; + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + + /* Start with a simple 0.5 second wait */ + Timeout.QuadPart = Int32x32To64(-10000, 500); + Status = NtWaitForSingleObject(Handle, TRUE, &Timeout); + if (Status == STATUS_SUCCESS) return TRUE; + + /* Check if our flags require the socket structure */ + if ((BlockingFlags == MAYBE_BLOCKING_HOOK) || + (BlockingFlags == ALWAYS_BLOCKING_HOOK) || + (TimeoutFlags == SEND_TIMEOUT) || + (TimeoutFlags == RECV_TIMEOUT)) + { + /* Get the socket */ + Socket = SockFindAndReferenceSocket(SocketHandle, FALSE); + if (!Socket) + { + /* We must be waiting on a non-socket for some reason? */ + NtWaitForSingleObject(Handle, TRUE, NULL); + return TRUE; + } + } + + /* Check the blocking flags */ + if (BlockingFlags == ALWAYS_BLOCKING_HOOK) + { + /* Always call it */ + CallHook = TRUE; + } + else if (BlockingFlags == MAYBE_BLOCKING_HOOK) + { + /* Check if we have to call it */ + CallHook = !Socket->SharedData.NonBlocking; + } + else if (BlockingFlags == NO_BLOCKING_HOOK) + { + /* Never call it*/ + CallHook = FALSE; + } + else + { + if (Socket) SockDereferenceSocket(Socket); + return FALSE; + } + + /* Check if we call it */ + if (CallHook) + { + /* Check if it actually exists */ + SockUpcallTable->lpWPUQueryBlockingCallback(Socket->SharedData.CatalogEntryId, + &BlockingHook, + &Context, + &ErrorCode); + + /* See if we'll call it */ + CallHook = (BlockingHook != NULL); + } + + /* Now check the timeout flags */ + if (TimeoutFlags == NO_TIMEOUT) + { + /* None at all */ + UseTimeout = FALSE; + } + else if (TimeoutFlags == SEND_TIMEOUT) + { + /* See if there's a Send Timeout */ + if (Socket->SharedData.SendTimeout) + { + /* Use it */ + UseTimeout = TRUE; + Timeout = RtlEnlargedIntegerMultiply(Socket->SharedData.SendTimeout, + 10 * 1000); + } + else + { + /* There isn't any */ + UseTimeout = FALSE; + } + } + else if (TimeoutFlags == RECV_TIMEOUT) + { + /* See if there's a Receive Timeout */ + if (Socket->SharedData.RecvTimeout) + { + /* Use it */ + UseTimeout = TRUE; + Timeout = RtlEnlargedIntegerMultiply(Socket->SharedData.RecvTimeout, + 10 * 1000); + } + else + { + /* There isn't any */ + UseTimeout = FALSE; + } + } + else + { + if (Socket) SockDereferenceSocket(Socket); + return FALSE; + } + + /* We don't need the socket anymore */ + if (Socket) SockDereferenceSocket(Socket); + + /* Check for timeout */ + if (UseTimeout) + { + /* Calculate the absolute time when the wait ends */ + Status = NtQuerySystemTime(&CurrentTime); + DueTime.QuadPart = CurrentTime.QuadPart + Timeout.QuadPart; + } + else + { + /* Infinite wait */ + DueTime.LowPart = -1; + DueTime.HighPart = 0x7FFFFFFF; + } + + /* Check for blocking hook call */ + if (CallHook) + { + /* We're calling it, so we won't actually be waiting */ + Timeout.LowPart = -1; + Timeout.HighPart = -1; + } + else + { + /* We'll be waiting till the Due Time */ + Timeout = DueTime; + } + + /* Now write data to the TEB so we'll know what's going on */ + ThreadData->CancelIo = FALSE; + ThreadData->SocketHandle = SocketHandle; + + /* Start wait loop */ + do + { + /* Call the hook */ + if (CallHook) (BlockingHook(Context)); + + /* Check if we were cancelled */ + if (ThreadData->CancelIo) + { + /* Infinite timeout and wait for official cancel */ + Timeout.LowPart = -1; + Timeout.HighPart = 0x7FFFFFFF; + } + else + { + /* Check if we're due */ + Status = NtQuerySystemTime(&CurrentTime); + if (CurrentTime.QuadPart > DueTime.QuadPart) + { + /* We're out */ + Status = STATUS_TIMEOUT; + break; + } + } + + /* Do the actual wait */ + Status = NtWaitForSingleObject(Handle, TRUE, &Timeout); + } while ((Status == STATUS_USER_APC) || + (Status == STATUS_ALERTED) || + (Status == STATUS_TIMEOUT)); + + /* Reset thread data */ + ThreadData->SocketHandle = INVALID_SOCKET; + + /* Return to caller */ + if (Status == STATUS_SUCCESS) return TRUE; + return FALSE; +} + +PSOCKET_INFORMATION +WSPAPI +SockFindAndReferenceSocket(IN SOCKET Handle, + IN BOOLEAN Import) +{ + PWAH_HANDLE WahHandle; + + /* Get it from our table and return it */ + WahHandle = WahReferenceContextByHandle(SockContextTable, (HANDLE)Handle); + if (WahHandle) return (PSOCKET_INFORMATION)WahHandle; + + /* Couldn't find it, shoudl we import it? */ + if (Import) return SockImportHandle(Handle); + + /* Nothing found */ + return NULL; +} + +INT +WSPAPI +SockBuildTdiAddress(OUT PTRANSPORT_ADDRESS TdiAddress, + IN PSOCKADDR Sockaddr, + IN INT SockaddrLength) +{ + /* Setup the TDI Address */ + TdiAddress->TAAddressCount = 1; + TdiAddress->Address[0].AddressLength = (USHORT)SockaddrLength - + sizeof(Sockaddr->sa_family); + + /* Copy it */ + RtlCopyMemory(&TdiAddress->Address[0].AddressType, Sockaddr, SockaddrLength); + + /* Return */ + return NO_ERROR; +} + +INT +WSPAPI +SockBuildSockaddr(OUT PSOCKADDR Sockaddr, + OUT PINT SockaddrLength, + IN PTRANSPORT_ADDRESS TdiAddress) +{ + /* Calculate the length it will take */ + *SockaddrLength = TdiAddress->Address[0].AddressLength + + sizeof(Sockaddr->sa_family); + + /* Copy it */ + RtlCopyMemory(Sockaddr, &TdiAddress->Address[0].AddressType, *SockaddrLength); + + /* Return */ + return NO_ERROR; +} + +BOOLEAN +WSPAPI +SockIsSocketConnected(IN PSOCKET_INFORMATION Socket) +{ + LARGE_INTEGER Timeout; + PVOID Context; + PVOID AsyncCallback; + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + + /* Check if there is an async connect in progress, but still unprocessed */ + while ((Socket->AsyncData) && + (Socket->AsyncData->IoStatusBlock.Status != STATUS_PENDING)) + { + /* The socket will be locked, release it */ + LeaveCriticalSection(&Socket->Lock); + + /* Setup the timeout and wait on completion */ + Timeout.QuadPart = 0; + Status = NtRemoveIoCompletion(SockAsyncQueuePort, + &AsyncCallback, + &Context, + &IoStatusBlock, + &Timeout); + + /* Check for success */ + if (Status == STATUS_SUCCESS) + { + /* Check if we're supposed to terminate */ + if (AsyncCallback != (PVOID)-1) + { + /* Handle the Async */ + SockHandleAsyncIndication(AsyncCallback, Context, &IoStatusBlock); + } + else + { + /* Terminate it */ + Status = NtSetIoCompletion(SockAsyncQueuePort, + (PVOID)-1, + (PVOID)-1, + 0, + 0); + + /* Acquire the lock and break out */ + EnterCriticalSection(&Socket->Lock); + break; + } + } + + /* Acquire the socket lock again */ + EnterCriticalSection(&Socket->Lock); + } + + /* Check if it's already connected */ + if (Socket->SharedData.State == SocketConnected) return TRUE; + return FALSE; +} + +VOID +WSPAPI +SockCancelIo(IN SOCKET Handle) +{ + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + + /* Cancel the I/O */ + Status = NtCancelIoFile((HANDLE)Handle, &IoStatusBlock); +} + +VOID +WSPAPI +SockIoCompletion(IN PVOID ApcContext, + IN PIO_STATUS_BLOCK IoStatusBlock, + DWORD Reserved) +{ + LPWSAOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine = ApcContext; + INT ErrorCode; + DWORD BytesSent; + DWORD Flags = 0; + LPWSAOVERLAPPED lpOverlapped; + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + + /* Check if this was an error */ + if (NT_ERROR(IoStatusBlock->Status)) + { + /* Check if it was anything but a simple cancel */ + if (IoStatusBlock->Status != STATUS_CANCELLED) + { + /* Convert it */ + ErrorCode = NtStatusToSocketError(IoStatusBlock->Status); + } + else + { + /* Use the right error */ + ErrorCode = WSA_OPERATION_ABORTED; + } + + /* Either ways, nothing was done */ + BytesSent = 0; + } + else + { + /* No error and check how many bytes were sent */ + ErrorCode = NO_ERROR; + BytesSent = PtrToUlong(IoStatusBlock->Information); + + /* Check the status */ + if (IoStatusBlock->Status == STATUS_BUFFER_OVERFLOW) + { + /* This was an error */ + ErrorCode = WSAEMSGSIZE; + } + else if (IoStatusBlock->Status == STATUS_RECEIVE_PARTIAL) + { + /* Partial receive */ + Flags = MSG_PARTIAL; + } + else if (IoStatusBlock->Status == STATUS_RECEIVE_EXPEDITED) + { + /* OOB receive */ + Flags = MSG_OOB; + } + else if (IoStatusBlock->Status == STATUS_RECEIVE_PARTIAL_EXPEDITED) + { + /* Partial OOB receive */ + Flags = MSG_OOB | MSG_PARTIAL; + } + } + + /* Get the overlapped structure */ + lpOverlapped = CONTAINING_RECORD(IoStatusBlock, WSAOVERLAPPED, Internal); + + /* Call it */ + CompletionRoutine(ErrorCode, BytesSent, lpOverlapped, Flags); + + /* Decrease pending APCs */ + ThreadData->PendingAPCs--; + InterlockedDecrement(&SockProcessPendingAPCCount); +} + +VOID +WSPAPI +SockpWaitForReaderCount(IN PSOCK_RW_LOCK Lock) +{ + NTSTATUS Status; + LARGE_INTEGER Timeout; + + /* Switch threads to see if the lock gets released that way */ + Timeout.QuadPart = 0; + NtDelayExecution(FALSE, &Timeout); + if (Lock->ReaderCount == -2) return; + + /* Either the thread isn't executing (priority inversion) or it's a hog */ + if (!Lock->WriterWaitEvent) + { + /* We don't have an event to wait on yet, allocate it */ + Status = NtCreateEvent(&Lock->WriterWaitEvent, + EVENT_ALL_ACCESS, + NULL, + SynchronizationEvent, + FALSE); + if (!NT_SUCCESS(Status)) + { + /* We can't get an event, do a manual loop */ + Timeout.QuadPart = Int32x32To64(1000, -100); + while (Lock->ReaderCount != -2) NtDelayExecution(FALSE, &Timeout); + } + } + + /* We have en event, now increment the reader count to signal them */ + if (InterlockedIncrement(&Lock->ReaderCount) != -1) + { + /* Wait for them to signal us */ + NtWaitForSingleObject(&Lock->WriterWaitEvent, FALSE, NULL); + } + + /* Finally it's free */ + Lock->ReaderCount = -2; +} + +NTSTATUS +WSPAPI +SockInitializeRwLockAndSpinCount(IN PSOCK_RW_LOCK Lock, + IN ULONG SpinCount) +{ + NTSTATUS Status; + + /* check if this is a special event create request */ + if (SpinCount & 0x80000000) + { + /* Create the event */ + Status = NtCreateEvent(&Lock->WriterWaitEvent, + EVENT_ALL_ACCESS, + NULL, + SynchronizationEvent, + FALSE); + if (!NT_SUCCESS(Status)) return Status; + } + + /* Initialize the lock */ + Status = RtlInitializeCriticalSectionAndSpinCount(&Lock->Lock, SpinCount); + if (NT_SUCCESS(Status)) + { + /* Initialize our structure */ + Lock->ReaderCount = 0; + } + else if (Lock->WriterWaitEvent) + { + /* We failed, close the event if we had one */ + NtClose(Lock->WriterWaitEvent); + Lock->WriterWaitEvent = NULL; + } + + /* Return status */ + return Status; +} + +VOID +WSPAPI +SockAcquireRwLockExclusive(IN PSOCK_RW_LOCK Lock) +{ + LONG Count, NewCount; + ULONG_PTR SpinCount; + + /* Acquire the lock */ + RtlEnterCriticalSection(&Lock->Lock); + + /* Check for ReaderCount */ + if (Lock->ReaderCount >= 0) + { + /* Loop while trying to change the count */ + do + { + /* Get the reader count */ + Count = Lock->ReaderCount; + + /* Modify the count so ReaderCount know that a writer is waiting */ + NewCount = -Count - 2; + } while (InterlockedCompareExchange(&Lock->ReaderCount, + NewCount, + Count) != Count); + + /* Check if some ReaderCount are still active */ + if (NewCount != -2) + { + /* Get the spincount of the CS */ + SpinCount = Lock->Lock.SpinCount; + + /* Loop until they are done */ + while (Lock->ReaderCount != -2) + { + /* Check if the CS has a spin count */ + if (SpinCount) + { + /* Spin on it */ + SpinCount--; + } + else + { + /* Do a full wait for ReaderCount */ + SockpWaitForReaderCount(Lock); + break; + } + } + } + } + else + { + /* Acquiring it again, decrement the count to handle this */ + Lock->ReaderCount--; + } +} + +VOID +WSPAPI +SockAcquireRwLockShared(IN PSOCK_RW_LOCK Lock) +{ + BOOL GotLock = FALSE; + LONG Count, NewCount; + + /* Start acquire loop */ + do + { + /* Get the current count */ + Count = Lock->ReaderCount; + + /* Check if a writer is active */ + if (Count < 0) + { + /* Acquire the lock (this will wait for the writer) */ + RtlEnterCriticalSection(&Lock->Lock); + GotLock = TRUE; + + /* Get the counter again */ + Count = Lock->ReaderCount; + if (Count < 0) + { + /* It's still below 0, so this is a recursive acquire */ + NewCount = Count - 1; + } + else + { + /* Increase the count since the writer has finished */ + NewCount = Count + 1; + } + } + else + { + /* No writers are active, increase count */ + NewCount = Count + 1; + } + + /* Update the count */ + NewCount = InterlockedCompareExchange(&Lock->ReaderCount, + NewCount, + Count); + + /* Check if we got the lock */ + if (GotLock) + { + /* Release it */ + RtlLeaveCriticalSection(&Lock->Lock); + GotLock = FALSE; + } + } while (NewCount != Count); +} + +VOID +WSPAPI +SockReleaseRwLockExclusive(IN PSOCK_RW_LOCK Lock) +{ + /* Increase the reader count and check if it's a recursive acquire */ + if (++Lock->ReaderCount == -1) + { + /* This release is the final one, so unhack the reader count */ + Lock->ReaderCount = 0; + } + + /* Leave the RTL CS */ + RtlLeaveCriticalSection(&Lock->Lock); +} + +VOID +WSPAPI +SockReleaseRwLockShared(IN PSOCK_RW_LOCK Lock) +{ + LONG NewCount, Count = Lock->ReaderCount; + + /* Start release loop */ + while (TRUE) + { + /* Check if writers are using the lock */ + if (Count > 0) + { + /* Lock is free, decrement the count */ + NewCount = Count - 1; + } + else + { + /* Lock is busy, increment the count */ + NewCount = Count + 1; + } + + /* Update the count */ + if (InterlockedCompareExchange(&Lock->ReaderCount, NewCount, Count) == Count) + { + /* Count changed sucesfully, was this the last reader? */ + if (NewCount == -1) + { + /* It was, we need to tell the writer about it */ + NtSetEvent(Lock->WriterWaitEvent, NULL); + } + break; + } + } +} + +NTSTATUS +WSPAPI +SockDeleteRwLock(IN PSOCK_RW_LOCK Lock) +{ + /* Check if there's an event */ + if (Lock->WriterWaitEvent) + { + /* Close it */ + NtClose(Lock->WriterWaitEvent); + Lock->WriterWaitEvent = NULL; + } + + /* Free the Crtitical Section */ + return RtlDeleteCriticalSection(&Lock->Lock); +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +SOCK_RW_LOCK SocketGlobalLock; + +/* FUNCTIONS *****************************************************************/ + +VOID +WSPAPI +SockDestroySocket(PSOCKET_INFORMATION Socket) +{ + /* Dereference its helper DLL */ + SockDereferenceHelperDll(Socket->HelperData); + + /* Delete the lock */ + DeleteCriticalSection(&Socket->Lock); + + /* Free the socket */ + RtlFreeHeap(SockPrivateHeap, 0, Socket); +} + +VOID +__inline +WSPAPI +SockDereferenceSocket(IN PSOCKET_INFORMATION Socket) +{ + /* Dereference and see if it's the last count */ + if (!InterlockedDecrement(&Socket->WshContext.RefCount)) + { + /* Destroy the socket */ + SockDestroySocket(Socket); + } +} + +PSOCKET_INFORMATION +WSPAPI +SockImportHandle(IN SOCKET Handle) +{ + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + PWAH_HANDLE WahHandle; + NTSTATUS Status; + ULONG ContextSize; + IO_STATUS_BLOCK IoStatusBlock; + PSOCKET_INFORMATION ImportedSocket = NULL; + UNICODE_STRING TransportName; + + /* Acquire the global lock */ + SockAcquireRwLockExclusive(&SocketGlobalLock); + + /* Make sure that the handle is still invalid */ + WahHandle = WahReferenceContextByHandle(SockContextTable, (HANDLE)Handle); + if (WahHandle) + { + /* Some other thread imported it by now, release the lock and return */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + return (PSOCKET_INFORMATION)WahHandle; + } + + /* Setup the NULL name for possible cleanup later */ + RtlInitUnicodeString(&TransportName, NULL); + + /* Call AFD to get the context size */ + Status = NtDeviceIoControlFile((HANDLE)Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_GET_CONTEXT_SIZE, + NULL, + 0, + &ContextSize, + sizeof(ContextSize)); + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + SockWaitForSingleObject(ThreadData->EventHandle, + Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Make sure we didn't fail, and that this is a valid context */ + if (!NT_SUCCESS(Status) || (ContextSize < sizeof(SOCK_SHARED_INFO))) + { + /* Fail (the error handler will convert to Win32 Status) */ + goto error; + } + +error: + /* Release the lock */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + + return ImportedSocket; +} + +INT +WSPAPI +SockSetInformation(IN PSOCKET_INFORMATION Socket, + IN ULONG AfdInformationClass, + IN PBOOLEAN Boolean OPTIONAL, + IN PULONG Ulong OPTIONAL, + IN PLARGE_INTEGER LargeInteger OPTIONAL) +{ + IO_STATUS_BLOCK IoStatusBlock; + AFD_INFO AfdInfo; + NTSTATUS Status; + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + + /* Set Info Class */ + AfdInfo.InformationClass = AfdInformationClass; + + /* Set Information */ + if (Boolean) + { + AfdInfo.Information.Boolean = *Boolean; + } + else if (Ulong) + { + AfdInfo.Information.Ulong = *Ulong; + } + else + { + AfdInfo.Information.LargeInteger = *LargeInteger; + } + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_GET_INFO, + &AfdInfo, + sizeof(AfdInfo), + NULL, + 0); + /* Check if we have to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for the operation to finish */ + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Handle failure */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + return NtStatusToSocketError(Status); + } + + /* Return to caller */ + return NO_ERROR; +} + +INT +WSPAPI +SockGetInformation(IN PSOCKET_INFORMATION Socket, + IN ULONG AfdInformationClass, + IN PVOID ExtraData OPTIONAL, + IN ULONG ExtraDataSize, + IN OUT PBOOLEAN Boolean OPTIONAL, + IN OUT PULONG Ulong OPTIONAL, + IN OUT PLARGE_INTEGER LargeInteger OPTIONAL) +{ + ULONG InfoLength; + IO_STATUS_BLOCK IoStatusBlock; + PAFD_INFO AfdInfo; + AFD_INFO InfoData; + NTSTATUS Status; + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + + /* Check if extra data is there */ + if (ExtraData && ExtraDataSize) + { + /* Allocate space for it */ + InfoLength = sizeof(InfoData) + ExtraDataSize; + AfdInfo = (PAFD_INFO)SockAllocateHeapRoutine(SockPrivateHeap, + 0, + InfoLength); + if (!AfdInfo) return WSAENOBUFS; + + /* Copy the extra data */ + RtlCopyMemory(AfdInfo + 1, ExtraData, ExtraDataSize); + } + else + { + /* Use local buffer */ + AfdInfo = &InfoData; + InfoLength = sizeof(InfoData); + } + + /* Set Info Class */ + AfdInfo->InformationClass = AfdInformationClass; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_GET_INFO, + &InfoData, + InfoLength, + &InfoData, + sizeof(InfoData)); + /* Check if we have to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for the operation to finish */ + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Handle failure */ + if (!NT_SUCCESS(Status)) + { + /* Check if we have to free the data */ + if (AfdInfo != &InfoData) RtlFreeHeap(SockPrivateHeap, 0, AfdInfo); + + /* Fail */ + return NtStatusToSocketError(Status); + } + + /* Return Information */ + if (Boolean) + { + *Boolean = AfdInfo->Information.Boolean; + } + else if (Ulong) + { + *Ulong = AfdInfo->Information.Ulong; + } + else + { + *LargeInteger = AfdInfo->Information.LargeInteger; + } + + /* Check if we have to free the data */ + if (AfdInfo != &InfoData) RtlFreeHeap(SockPrivateHeap, 0, AfdInfo); + + /* Return to caller */ + return NO_ERROR; +} + +INT +WSPAPI +SockSetHandleContext(IN PSOCKET_INFORMATION Socket) +{ + IO_STATUS_BLOCK IoStatusBlock; + CHAR ContextData[256]; + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + PVOID Context; + ULONG_PTR ContextPos; + ULONG ContextLength; + INT HelperContextLength; + INT ErrorCode; + NTSTATUS Status; + + /* Find out how big the helper DLL context is */ + ErrorCode = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, + Socket->Handle, + Socket->TdiAddressHandle, + Socket->TdiConnectionHandle, + SOL_INTERNAL, + SO_CONTEXT, + NULL, + &HelperContextLength); + + /* Calculate the total space needed */ + ContextLength = sizeof(SOCK_SHARED_INFO) + + 2 * Socket->HelperData->MaxWSAddressLength + + sizeof(ULONG) + HelperContextLength; + + /* See if our stack can hold it */ + if (ContextLength <= sizeof(ContextData)) + { + /* Use our stack */ + Context = ContextData; + } + else + { + /* Allocate from heap */ + Context = SockAllocateHeapRoutine(SockPrivateHeap, 0, ContextLength); + if (!Context) return WSAENOBUFS; + } + + /* + * Create Context, this includes: + * Shared Socket Data, Helper Context Length, Local and Remote Addresses + * and finally the actual helper context. + */ + ContextPos = (ULONG_PTR)Context; + RtlCopyMemory((PVOID)ContextPos, + &Socket->SharedData, + sizeof(SOCK_SHARED_INFO)); + ContextPos += sizeof(SOCK_SHARED_INFO); + *(PULONG)ContextPos = HelperContextLength; + ContextPos += sizeof(ULONG); + RtlCopyMemory((PVOID)ContextPos, + Socket->LocalAddress, + Socket->HelperData->MaxWSAddressLength); + ContextPos += Socket->HelperData->MaxWSAddressLength; + RtlCopyMemory((PVOID)ContextPos, + Socket->RemoteAddress, + Socket->HelperData->MaxWSAddressLength); + ContextPos += Socket->HelperData->MaxWSAddressLength; + + /* Now get the helper context */ + ErrorCode = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, + Socket->Handle, + Socket->TdiAddressHandle, + Socket->TdiConnectionHandle, + SOL_INTERNAL, + SO_CONTEXT, + (PVOID)ContextPos, + &HelperContextLength); + /* Now give it to AFD */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_SET_CONTEXT, + Context, + ContextLength, + NULL, + 0); + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check if we need to free from heap */ + if (Context != ContextData) RtlFreeHeap(SockPrivateHeap, 0, Context); + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Convert and return error code */ + ErrorCode = NtStatusToSocketError(Status); + return ErrorCode; + } + + /* Return success */ + return NO_ERROR; +} + +INT +WSPAPI +SockIsAddressConsistentWithConstrainedGroup(IN PSOCKET_INFORMATION Socket, + IN GROUP Group, + IN PSOCKADDR SocketAddress, + IN INT SocketAddressLength) +{ + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + INT ErrorCode; + PAFD_VALIDATE_GROUP_DATA ValidateGroupData; + NTSTATUS Status; + IO_STATUS_BLOCK IoStatusBlock; + ULONG ValidateGroupSize; + CHAR ValidateBuffer[sizeof(AFD_VALIDATE_GROUP_DATA) + MAX_TDI_ADDRESS_LENGTH]; + + /* Calculate the length of the buffer */ + ValidateGroupSize = sizeof(AFD_VALIDATE_GROUP_DATA) + + sizeof(TRANSPORT_ADDRESS) + + Socket->HelperData->MaxTDIAddressLength; + + /* Check if our stack buffer is large enough */ + if (ValidateGroupSize <= sizeof(ValidateBuffer)) + { + /* Use the stack */ + ValidateGroupData = (PVOID)ValidateBuffer; + } + else + { + /* Allocate from heap */ + ValidateGroupData = SockAllocateHeapRoutine(SockPrivateHeap, + 0, + ValidateGroupSize); + if (!ValidateGroupData) return WSAENOBUFS; + } + + /* Convert the address to TDI format */ + ErrorCode = SockBuildTdiAddress(&ValidateGroupData->Address, + SocketAddress, + SocketAddressLength); + if (ErrorCode != NO_ERROR) return ErrorCode; + + /* Tell AFD which group to check, and let AFD validate it */ + ValidateGroupData->GroupId = Group; + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_VALIDATE_GROUP, + ValidateGroupData, + ValidateGroupSize, + NULL, + 0); + + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check if we need to free the data from heap */ + if (ValidateGroupData != (PVOID)ValidateBuffer) + { + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, ValidateGroupData); + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + return NtStatusToSocketError(Status); + } + + /* Return success */ + return NO_ERROR; +} + + +INT +WSPAPI +SockGetTdiHandles(IN PSOCKET_INFORMATION Socket) +{ + AFD_TDI_HANDLE_DATA TdiHandleInfo; + NTSTATUS Status; + IO_STATUS_BLOCK IoStatusBlock; + ULONG InfoType = 0; + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + + /* See which handle(s) we need */ + if (!Socket->TdiAddressHandle) InfoType |= AFD_ADDRESS_HANDLE; + if (!Socket->TdiConnectionHandle) InfoType |= AFD_CONNECTION_HANDLE; + + /* Make sure we need one */ + if (!InfoType) return NO_ERROR; + + /* Call AFD */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_GET_TDI_HANDLES, + &InfoType, + sizeof(InfoType), + &TdiHandleInfo, + sizeof(TdiHandleInfo)); + /* Check if we shoudl wait */ + if (Status == STATUS_PENDING) + { + /* Wait on it */ + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + + /* Update status */ + Status = IoStatusBlock.Status; + } + + /* Check for success */ + if (!NT_SUCCESS(Status)) return NtStatusToSocketError(Status); + + /* Return handles */ + if (!Socket->TdiAddressHandle) + { + Socket->TdiAddressHandle = TdiHandleInfo.TdiAddressHandle; + } + if (!Socket->TdiConnectionHandle) + { + Socket->TdiConnectionHandle = TdiHandleInfo.TdiConnectionHandle; + } + + /* Return */ + return NO_ERROR; +} + +BOOL +WSPAPI +SockWaitForSingleObject(IN HANDLE Handle, + IN SOCKET SocketHandle, + IN DWORD BlockingFlags, + IN DWORD TimeoutFlags) +{ + LARGE_INTEGER Timeout, CurrentTime, DueTime; + NTSTATUS Status; + PSOCKET_INFORMATION Socket = NULL; + BOOLEAN CallHook, UseTimeout; + LPBLOCKINGCALLBACK BlockingHook; + DWORD_PTR Context; + INT ErrorCode; + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + + /* Start with a simple 0.5 second wait */ + Timeout.QuadPart = Int32x32To64(-10000, 500); + Status = NtWaitForSingleObject(Handle, TRUE, &Timeout); + if (Status == STATUS_SUCCESS) return TRUE; + + /* Check if our flags require the socket structure */ + if ((BlockingFlags == MAYBE_BLOCKING_HOOK) || + (BlockingFlags == ALWAYS_BLOCKING_HOOK) || + (TimeoutFlags == SEND_TIMEOUT) || + (TimeoutFlags == RECV_TIMEOUT)) + { + /* Get the socket */ + Socket = SockFindAndReferenceSocket(SocketHandle, FALSE); + if (!Socket) + { + /* We must be waiting on a non-socket for some reason? */ + NtWaitForSingleObject(Handle, TRUE, NULL); + return TRUE; + } + } + + /* Check the blocking flags */ + if (BlockingFlags == ALWAYS_BLOCKING_HOOK) + { + /* Always call it */ + CallHook = TRUE; + } + else if (BlockingFlags == MAYBE_BLOCKING_HOOK) + { + /* Check if we have to call it */ + CallHook = !Socket->SharedData.NonBlocking; + } + else if (BlockingFlags == NO_BLOCKING_HOOK) + { + /* Never call it*/ + CallHook = FALSE; + } + else + { + if (Socket) SockDereferenceSocket(Socket); + return FALSE; + } + + /* Check if we call it */ + if (CallHook) + { + /* Check if it actually exists */ + SockUpcallTable->lpWPUQueryBlockingCallback(Socket->SharedData.CatalogEntryId, + &BlockingHook, + &Context, + &ErrorCode); + + /* See if we'll call it */ + CallHook = (BlockingHook != NULL); + } + + /* Now check the timeout flags */ + if (TimeoutFlags == NO_TIMEOUT) + { + /* None at all */ + UseTimeout = FALSE; + } + else if (TimeoutFlags == SEND_TIMEOUT) + { + /* See if there's a Send Timeout */ + if (Socket->SharedData.SendTimeout) + { + /* Use it */ + UseTimeout = TRUE; + Timeout = RtlEnlargedIntegerMultiply(Socket->SharedData.SendTimeout, + 10 * 1000); + } + else + { + /* There isn't any */ + UseTimeout = FALSE; + } + } + else if (TimeoutFlags == RECV_TIMEOUT) + { + /* See if there's a Receive Timeout */ + if (Socket->SharedData.RecvTimeout) + { + /* Use it */ + UseTimeout = TRUE; + Timeout = RtlEnlargedIntegerMultiply(Socket->SharedData.RecvTimeout, + 10 * 1000); + } + else + { + /* There isn't any */ + UseTimeout = FALSE; + } + } + else + { + if (Socket) SockDereferenceSocket(Socket); + return FALSE; + } + + /* We don't need the socket anymore */ + if (Socket) SockDereferenceSocket(Socket); + + /* Check for timeout */ + if (UseTimeout) + { + /* Calculate the absolute time when the wait ends */ + Status = NtQuerySystemTime(&CurrentTime); + DueTime.QuadPart = CurrentTime.QuadPart + Timeout.QuadPart; + } + else + { + /* Infinite wait */ + DueTime.LowPart = -1; + DueTime.HighPart = 0x7FFFFFFF; + } + + /* Check for blocking hook call */ + if (CallHook) + { + /* We're calling it, so we won't actually be waiting */ + Timeout.LowPart = -1; + Timeout.HighPart = -1; + } + else + { + /* We'll be waiting till the Due Time */ + Timeout = DueTime; + } + + /* Now write data to the TEB so we'll know what's going on */ + ThreadData->CancelIo = FALSE; + ThreadData->SocketHandle = SocketHandle; + + /* Start wait loop */ + do + { + /* Call the hook */ + if (CallHook) (BlockingHook(Context)); + + /* Check if we were cancelled */ + if (ThreadData->CancelIo) + { + /* Infinite timeout and wait for official cancel */ + Timeout.LowPart = -1; + Timeout.HighPart = 0x7FFFFFFF; + } + else + { + /* Check if we're due */ + Status = NtQuerySystemTime(&CurrentTime); + if (CurrentTime.QuadPart > DueTime.QuadPart) + { + /* We're out */ + Status = STATUS_TIMEOUT; + break; + } + } + + /* Do the actual wait */ + Status = NtWaitForSingleObject(Handle, TRUE, &Timeout); + } while ((Status == STATUS_USER_APC) || + (Status == STATUS_ALERTED) || + (Status == STATUS_TIMEOUT)); + + /* Reset thread data */ + ThreadData->SocketHandle = INVALID_SOCKET; + + /* Return to caller */ + if (Status == STATUS_SUCCESS) return TRUE; + return FALSE; +} + +PSOCKET_INFORMATION +WSPAPI +SockFindAndReferenceSocket(IN SOCKET Handle, + IN BOOLEAN Import) +{ + PWAH_HANDLE WahHandle; + + /* Get it from our table and return it */ + WahHandle = WahReferenceContextByHandle(SockContextTable, (HANDLE)Handle); + if (WahHandle) return (PSOCKET_INFORMATION)WahHandle; + + /* Couldn't find it, shoudl we import it? */ + if (Import) return SockImportHandle(Handle); + + /* Nothing found */ + return NULL; +} + +INT +WSPAPI +SockBuildTdiAddress(OUT PTRANSPORT_ADDRESS TdiAddress, + IN PSOCKADDR Sockaddr, + IN INT SockaddrLength) +{ + /* Setup the TDI Address */ + TdiAddress->TAAddressCount = 1; + TdiAddress->Address[0].AddressLength = (USHORT)SockaddrLength - + sizeof(Sockaddr->sa_family); + + /* Copy it */ + RtlCopyMemory(&TdiAddress->Address[0].AddressType, Sockaddr, SockaddrLength); + + /* Return */ + return NO_ERROR; +} + +INT +WSPAPI +SockBuildSockaddr(OUT PSOCKADDR Sockaddr, + OUT PINT SockaddrLength, + IN PTRANSPORT_ADDRESS TdiAddress) +{ + /* Calculate the length it will take */ + *SockaddrLength = TdiAddress->Address[0].AddressLength + + sizeof(Sockaddr->sa_family); + + /* Copy it */ + RtlCopyMemory(Sockaddr, &TdiAddress->Address[0].AddressType, *SockaddrLength); + + /* Return */ + return NO_ERROR; +} + +BOOLEAN +WSPAPI +SockIsSocketConnected(IN PSOCKET_INFORMATION Socket) +{ + LARGE_INTEGER Timeout; + PVOID Context; + PVOID AsyncCallback; + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + + /* Check if there is an async connect in progress, but still unprocessed */ + while ((Socket->AsyncData) && + (Socket->AsyncData->IoStatusBlock.Status != STATUS_PENDING)) + { + /* The socket will be locked, release it */ + LeaveCriticalSection(&Socket->Lock); + + /* Setup the timeout and wait on completion */ + Timeout.QuadPart = 0; + Status = NtRemoveIoCompletion(SockAsyncQueuePort, + &AsyncCallback, + &Context, + &IoStatusBlock, + &Timeout); + + /* Check for success */ + if (Status == STATUS_SUCCESS) + { + /* Check if we're supposed to terminate */ + if (AsyncCallback != (PVOID)-1) + { + /* Handle the Async */ + SockHandleAsyncIndication(AsyncCallback, Context, &IoStatusBlock); + } + else + { + /* Terminate it */ + Status = NtSetIoCompletion(SockAsyncQueuePort, + (PVOID)-1, + (PVOID)-1, + 0, + 0); + + /* Acquire the lock and break out */ + EnterCriticalSection(&Socket->Lock); + break; + } + } + + /* Acquire the socket lock again */ + EnterCriticalSection(&Socket->Lock); + } + + /* Check if it's already connected */ + if (Socket->SharedData.State == SocketConnected) return TRUE; + return FALSE; +} + +VOID +WSPAPI +SockCancelIo(IN SOCKET Handle) +{ + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + + /* Cancel the I/O */ + Status = NtCancelIoFile((HANDLE)Handle, &IoStatusBlock); +} + +VOID +WSPAPI +SockIoCompletion(IN PVOID ApcContext, + IN PIO_STATUS_BLOCK IoStatusBlock, + DWORD Reserved) +{ + LPWSAOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine = ApcContext; + INT ErrorCode; + DWORD BytesSent; + DWORD Flags = 0; + LPWSAOVERLAPPED lpOverlapped; + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + + /* Check if this was an error */ + if (NT_ERROR(IoStatusBlock->Status)) + { + /* Check if it was anything but a simple cancel */ + if (IoStatusBlock->Status != STATUS_CANCELLED) + { + /* Convert it */ + ErrorCode = NtStatusToSocketError(IoStatusBlock->Status); + } + else + { + /* Use the right error */ + ErrorCode = WSA_OPERATION_ABORTED; + } + + /* Either ways, nothing was done */ + BytesSent = 0; + } + else + { + /* No error and check how many bytes were sent */ + ErrorCode = NO_ERROR; + BytesSent = PtrToUlong(IoStatusBlock->Information); + + /* Check the status */ + if (IoStatusBlock->Status == STATUS_BUFFER_OVERFLOW) + { + /* This was an error */ + ErrorCode = WSAEMSGSIZE; + } + else if (IoStatusBlock->Status == STATUS_RECEIVE_PARTIAL) + { + /* Partial receive */ + Flags = MSG_PARTIAL; + } + else if (IoStatusBlock->Status == STATUS_RECEIVE_EXPEDITED) + { + /* OOB receive */ + Flags = MSG_OOB; + } + else if (IoStatusBlock->Status == STATUS_RECEIVE_PARTIAL_EXPEDITED) + { + /* Partial OOB receive */ + Flags = MSG_OOB | MSG_PARTIAL; + } + } + + /* Get the overlapped structure */ + lpOverlapped = CONTAINING_RECORD(IoStatusBlock, WSAOVERLAPPED, Internal); + + /* Call it */ + CompletionRoutine(ErrorCode, BytesSent, lpOverlapped, Flags); + + /* Decrease pending APCs */ + ThreadData->PendingAPCs--; + InterlockedDecrement(&SockProcessPendingAPCCount); +} + +VOID +WSPAPI +SockpWaitForReaderCount(IN PSOCK_RW_LOCK Lock) +{ + NTSTATUS Status; + LARGE_INTEGER Timeout; + + /* Switch threads to see if the lock gets released that way */ + Timeout.QuadPart = 0; + NtDelayExecution(FALSE, &Timeout); + if (Lock->ReaderCount == -2) return; + + /* Either the thread isn't executing (priority inversion) or it's a hog */ + if (!Lock->WriterWaitEvent) + { + /* We don't have an event to wait on yet, allocate it */ + Status = NtCreateEvent(&Lock->WriterWaitEvent, + EVENT_ALL_ACCESS, + NULL, + SynchronizationEvent, + FALSE); + if (!NT_SUCCESS(Status)) + { + /* We can't get an event, do a manual loop */ + Timeout.QuadPart = Int32x32To64(1000, -100); + while (Lock->ReaderCount != -2) NtDelayExecution(FALSE, &Timeout); + } + } + + /* We have en event, now increment the reader count to signal them */ + if (InterlockedIncrement(&Lock->ReaderCount) != -1) + { + /* Wait for them to signal us */ + NtWaitForSingleObject(&Lock->WriterWaitEvent, FALSE, NULL); + } + + /* Finally it's free */ + Lock->ReaderCount = -2; +} + +NTSTATUS +WSPAPI +SockInitializeRwLockAndSpinCount(IN PSOCK_RW_LOCK Lock, + IN ULONG SpinCount) +{ + NTSTATUS Status; + + /* check if this is a special event create request */ + if (SpinCount & 0x80000000) + { + /* Create the event */ + Status = NtCreateEvent(&Lock->WriterWaitEvent, + EVENT_ALL_ACCESS, + NULL, + SynchronizationEvent, + FALSE); + if (!NT_SUCCESS(Status)) return Status; + } + + /* Initialize the lock */ + Status = RtlInitializeCriticalSectionAndSpinCount(&Lock->Lock, SpinCount); + if (NT_SUCCESS(Status)) + { + /* Initialize our structure */ + Lock->ReaderCount = 0; + } + else if (Lock->WriterWaitEvent) + { + /* We failed, close the event if we had one */ + NtClose(Lock->WriterWaitEvent); + Lock->WriterWaitEvent = NULL; + } + + /* Return status */ + return Status; +} + +VOID +WSPAPI +SockAcquireRwLockExclusive(IN PSOCK_RW_LOCK Lock) +{ + LONG Count, NewCount; + ULONG_PTR SpinCount; + + /* Acquire the lock */ + RtlEnterCriticalSection(&Lock->Lock); + + /* Check for ReaderCount */ + if (Lock->ReaderCount >= 0) + { + /* Loop while trying to change the count */ + do + { + /* Get the reader count */ + Count = Lock->ReaderCount; + + /* Modify the count so ReaderCount know that a writer is waiting */ + NewCount = -Count - 2; + } while (InterlockedCompareExchange(&Lock->ReaderCount, + NewCount, + Count) != Count); + + /* Check if some ReaderCount are still active */ + if (NewCount != -2) + { + /* Get the spincount of the CS */ + SpinCount = Lock->Lock.SpinCount; + + /* Loop until they are done */ + while (Lock->ReaderCount != -2) + { + /* Check if the CS has a spin count */ + if (SpinCount) + { + /* Spin on it */ + SpinCount--; + } + else + { + /* Do a full wait for ReaderCount */ + SockpWaitForReaderCount(Lock); + break; + } + } + } + } + else + { + /* Acquiring it again, decrement the count to handle this */ + Lock->ReaderCount--; + } +} + +VOID +WSPAPI +SockAcquireRwLockShared(IN PSOCK_RW_LOCK Lock) +{ + BOOL GotLock = FALSE; + LONG Count, NewCount; + + /* Start acquire loop */ + do + { + /* Get the current count */ + Count = Lock->ReaderCount; + + /* Check if a writer is active */ + if (Count < 0) + { + /* Acquire the lock (this will wait for the writer) */ + RtlEnterCriticalSection(&Lock->Lock); + GotLock = TRUE; + + /* Get the counter again */ + Count = Lock->ReaderCount; + if (Count < 0) + { + /* It's still below 0, so this is a recursive acquire */ + NewCount = Count - 1; + } + else + { + /* Increase the count since the writer has finished */ + NewCount = Count + 1; + } + } + else + { + /* No writers are active, increase count */ + NewCount = Count + 1; + } + + /* Update the count */ + NewCount = InterlockedCompareExchange(&Lock->ReaderCount, + NewCount, + Count); + + /* Check if we got the lock */ + if (GotLock) + { + /* Release it */ + RtlLeaveCriticalSection(&Lock->Lock); + GotLock = FALSE; + } + } while (NewCount != Count); +} + +VOID +WSPAPI +SockReleaseRwLockExclusive(IN PSOCK_RW_LOCK Lock) +{ + /* Increase the reader count and check if it's a recursive acquire */ + if (++Lock->ReaderCount == -1) + { + /* This release is the final one, so unhack the reader count */ + Lock->ReaderCount = 0; + } + + /* Leave the RTL CS */ + RtlLeaveCriticalSection(&Lock->Lock); +} + +VOID +WSPAPI +SockReleaseRwLockShared(IN PSOCK_RW_LOCK Lock) +{ + LONG NewCount, Count = Lock->ReaderCount; + + /* Start release loop */ + while (TRUE) + { + /* Check if writers are using the lock */ + if (Count > 0) + { + /* Lock is free, decrement the count */ + NewCount = Count - 1; + } + else + { + /* Lock is busy, increment the count */ + NewCount = Count + 1; + } + + /* Update the count */ + if (InterlockedCompareExchange(&Lock->ReaderCount, NewCount, Count) == Count) + { + /* Count changed sucesfully, was this the last reader? */ + if (NewCount == -1) + { + /* It was, we need to tell the writer about it */ + NtSetEvent(Lock->WriterWaitEvent, NULL); + } + break; + } + } +} + +NTSTATUS +WSPAPI +SockDeleteRwLock(IN PSOCK_RW_LOCK Lock) +{ + /* Check if there's an event */ + if (Lock->WriterWaitEvent) + { + /* Close it */ + NtClose(Lock->WriterWaitEvent); + Lock->WriterWaitEvent = NULL; + } + + /* Free the Crtitical Section */ + return RtlDeleteCriticalSection(&Lock->Lock); +} + diff --git a/dll/win32/mswsock/msafd/recv.c b/dll/win32/mswsock/msafd/recv.c new file mode 100644 index 00000000000..f85d7dfa42c --- /dev/null +++ b/dll/win32/mswsock/msafd/recv.c @@ -0,0 +1,2248 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +WSPRecv(SOCKET Handle, + LPWSABUF lpBuffers, + DWORD dwBufferCount, + LPDWORD lpNumberOfBytesRead, + LPDWORD ReceiveFlags, + LPWSAOVERLAPPED lpOverlapped, + LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + LPWSATHREADID lpThreadId, + LPINT lpErrno) +{ + PIO_STATUS_BLOCK IoStatusBlock; + IO_STATUS_BLOCK DummyIoStatusBlock; + AFD_RECV_INFO RecvInfo; + NTSTATUS Status; + PVOID APCContext; + PVOID ApcFunction; + HANDLE Event; + PWINSOCK_TEB_DATA ThreadData; + PSOCKET_INFORMATION Socket; + INT ErrorCode; + BOOLEAN ReturnValue; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Set up the Receive Structure */ + RecvInfo.BufferArray = (PAFD_WSABUF)lpBuffers; + RecvInfo.BufferCount = dwBufferCount; + RecvInfo.TdiFlags = 0; + RecvInfo.AfdFlags = 0; + + /* Set the TDI Flags */ + if (!(*ReceiveFlags)) + { + /* Use normal TDI Receive */ + RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL; + } + else + { + /* Check for valid flags */ + if ((*ReceiveFlags & ~(MSG_OOB | MSG_PEEK | MSG_PARTIAL))) + { + /* Fail */ + ErrorCode = WSAEOPNOTSUPP; + goto error; + } + + /* Check if OOB is being used */ + if (*ReceiveFlags & MSG_OOB) + { + /* Use Expedited Receive for OOB */ + RecvInfo.TdiFlags |= TDI_RECEIVE_EXPEDITED; + } + else + { + /* Use normal receive */ + RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL; + } + + /* Use Peek Receive if enabled */ + if (*ReceiveFlags & MSG_PEEK) RecvInfo.TdiFlags |= TDI_RECEIVE_PEEK; + + /* Use Partial Receive if enabled */ + if (*ReceiveFlags & MSG_PARTIAL) RecvInfo.TdiFlags |= TDI_RECEIVE_PARTIAL; + } + + /* Verifiy if we should use APC */ + if (!lpOverlapped) + { + /* Not using Overlapped structure, so use normal blocking on event */ + APCContext = NULL; + ApcFunction = NULL; + Event = ThreadData->EventHandle; + IoStatusBlock = &DummyIoStatusBlock; + } + else + { + /* Using apc, check if we have a completion routine */ + if (!lpCompletionRoutine) + { + /* No need for APC */ + APCContext = lpOverlapped; + ApcFunction = NULL; + Event = lpOverlapped->hEvent; + } + else + { + /* Use APC */ + ApcFunction = SockIoCompletion; + APCContext = lpCompletionRoutine; + Event = NULL; + + /* Skip Fast I/O */ + RecvInfo.AfdFlags = AFD_SKIP_FIO; + } + + /* Use the overlapped's structure buffer for the I/O Status Block */ + IoStatusBlock = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; + + /* Make this an overlapped I/O in AFD */ + RecvInfo.AfdFlags |= AFD_OVERLAPPED; + } + + /* Set is as Pending for now */ + IoStatusBlock->Status = STATUS_PENDING; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile((HANDLE)Handle, + Event, + ApcFunction, + APCContext, + IoStatusBlock, + IOCTL_AFD_RECV, + &RecvInfo, + sizeof(RecvInfo), + NULL, + 0); + + /* Increase the pending APC Count if we're using an APC */ + if (!NT_ERROR(Status) && ApcFunction) + { + ThreadData->PendingAPCs++; + InterlockedIncrement(&SockProcessPendingAPCCount); + } + + /* Wait for completition if not overlapped */ + if ((Status == STATUS_PENDING) && !(lpOverlapped)) + { + /* Wait for completion */ + ReturnValue = SockWaitForSingleObject(Event, + Handle, + MAYBE_BLOCKING_HOOK, + RECV_TIMEOUT); + + /* Check if the wait was successful */ + if (ReturnValue) + { + /* Get new status */ + Status = IoStatusBlock->Status; + } + else + { + /* Cancel the I/O */ + SockCancelIo(Handle); + + /* Get new status and normalize */ + Status = IoStatusBlock->Status; + if (Status == STATUS_CANCELLED) Status = STATUS_IO_TIMEOUT; + } + } + + /* Return the Flags */ + *ReceiveFlags = 0; + switch (Status) + { + /* Success */ + case STATUS_SUCCESS: + break; + + /* Pending I/O */ + case STATUS_PENDING: + ErrorCode = WSA_IO_PENDING; + goto error; + + /* Buffer Overflow */ + case STATUS_BUFFER_OVERFLOW: + /* Check if this was overlapped */ + if (lpOverlapped) + { + /* Return without bytes read */ + ErrorCode = WSA_IO_PENDING; + goto error; + } + + /* Return failure with bytes read */ + ErrorCode = WSAEMSGSIZE; + break; + + /* OOB Receive */ + case STATUS_RECEIVE_EXPEDITED: + *ReceiveFlags = MSG_OOB; + break; + + /* Partial OOB Receive */ + case STATUS_RECEIVE_PARTIAL_EXPEDITED: + *ReceiveFlags = MSG_PARTIAL | MSG_OOB; + break; + + /* Parial Receive */ + case STATUS_RECEIVE_PARTIAL: + *ReceiveFlags = MSG_PARTIAL; + break; + + /* Other NT Error */ + default: + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + break; + } + + /* Return the number of bytes read */ + *lpNumberOfBytesRead = PtrToUlong(IoStatusBlock->Information); + +error: + + /* Check if async select was active */ + if (SockAsyncSelectCalled) + { + /* Get the socket */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (Socket) + { + /* Lock it */ + EnterCriticalSection(&Socket->Lock); + + /* Check which event to re-enable */ + if (RecvInfo.TdiFlags & TDI_RECEIVE_EXPEDITED) + { + /* Re-enable the OOB event */ + SockReenableAsyncSelectEvent(Socket, FD_OOB); + } + else + { + /* Re-enable the regular read event */ + SockReenableAsyncSelectEvent(Socket, FD_READ); + } + + /* Unlock and dereference socket */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + } + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +INT +WSPAPI +WSPRecvFrom(SOCKET Handle, + LPWSABUF lpBuffers, + DWORD dwBufferCount, + LPDWORD lpNumberOfBytesRead, + LPDWORD ReceiveFlags, + PSOCKADDR SocketAddress, + PINT SocketAddressLength, + LPWSAOVERLAPPED lpOverlapped, + LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + LPWSATHREADID lpThreadId, + LPINT lpErrno) +{ + PIO_STATUS_BLOCK IoStatusBlock; + IO_STATUS_BLOCK DummyIoStatusBlock; + AFD_RECV_INFO_UDP RecvInfo; + NTSTATUS Status; + PVOID APCContext; + PVOID ApcFunction; + HANDLE Event; + PWINSOCK_TEB_DATA ThreadData; + PSOCKET_INFORMATION Socket; + INT ErrorCode; + BOOLEAN ReturnValue; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Fail if the socket isn't bound */ + if (Socket->SharedData.State == SocketOpen) + { + /* Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* If this is an unconnected or non datagram socket */ + if (!(MSAFD_IS_DGRAM_SOCK(Socket)) || + (!SocketAddress && !SocketAddressLength)) + { + /* Call WSP Recv */ + SockDereferenceSocket(Socket); + return WSPRecv(Handle, + lpBuffers, + dwBufferCount, + lpNumberOfBytesRead, + ReceiveFlags, + lpOverlapped, + lpCompletionRoutine, + lpThreadId, + lpErrno); + } + + /* If receive shutdown is enabled, fail */ + if (Socket->SharedData.ReceiveShutdown) + { + /* Fail */ + ErrorCode = WSAESHUTDOWN; + goto error; + } + + /* Check for valid Socket Address (Length) flags */ + if (!(SocketAddress) ^ (!SocketAddressLength || !(*SocketAddressLength))) + { + /* Fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* Check for valid flags */ + if ((*ReceiveFlags & ~(MSG_PEEK | MSG_PARTIAL))) + { + /* Fail */ + ErrorCode = WSAEOPNOTSUPP; + goto error; + } + + /* Check that the length is respected */ + if (SocketAddressLength && + (*SocketAddressLength < Socket->HelperData->MinWSAddressLength)) + { + /* Fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* Set up the Receive Structure */ + RecvInfo.BufferArray = (PAFD_WSABUF)lpBuffers; + RecvInfo.BufferCount = dwBufferCount; + RecvInfo.TdiFlags = TDI_RECEIVE_NORMAL; + RecvInfo.AfdFlags = 0; + RecvInfo.Address = SocketAddress; + RecvInfo.AddressLength = SocketAddressLength; + + /* Use Peek Receive if enabled */ + if (*ReceiveFlags & MSG_PEEK) RecvInfo.TdiFlags |= TDI_RECEIVE_PEEK; + + /* Use Partial Receive if enabled */ + if (*ReceiveFlags & MSG_PARTIAL) RecvInfo.TdiFlags |= TDI_RECEIVE_PARTIAL; + + /* Verifiy if we should use APC */ + if (!lpOverlapped) + { + /* Not using Overlapped structure, so use normal blocking on event */ + APCContext = NULL; + ApcFunction = NULL; + Event = ThreadData->EventHandle; + IoStatusBlock = &DummyIoStatusBlock; + } + else + { + /* Using apc, check if we have a completion routine */ + if (!lpCompletionRoutine) + { + /* No need for APC */ + APCContext = lpOverlapped; + ApcFunction = NULL; + Event = lpOverlapped->hEvent; + } + else + { + /* Use APC */ + ApcFunction = SockIoCompletion; + APCContext = lpCompletionRoutine; + Event = NULL; + + /* Skip Fast I/O */ + RecvInfo.AfdFlags = AFD_SKIP_FIO; + } + + /* Use the overlapped's structure buffer for the I/O Status Block */ + IoStatusBlock = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; + + /* Make this an overlapped I/O in AFD */ + RecvInfo.AfdFlags |= AFD_OVERLAPPED; + } + + /* Set is as Pending for now */ + IoStatusBlock->Status = STATUS_PENDING; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + Event, + ApcFunction, + APCContext, + IoStatusBlock, + IOCTL_AFD_RECV_DATAGRAM, + &RecvInfo, + sizeof(RecvInfo), + NULL, + 0); + + /* Increase the pending APC Count if we're using an APC */ + if (!NT_ERROR(Status) && ApcFunction) + { + ThreadData->PendingAPCs++; + InterlockedIncrement(&SockProcessPendingAPCCount); + } + + /* Wait for completition if not overlapped */ + if ((Status == STATUS_PENDING) && !(lpOverlapped)) + { + /* Wait for completion */ + ReturnValue = SockWaitForSingleObject(Event, + Handle, + MAYBE_BLOCKING_HOOK, + RECV_TIMEOUT); + + /* Check if the wait was successful */ + if (ReturnValue) + { + /* Get new status */ + Status = IoStatusBlock->Status; + } + else + { + /* Cancel the I/O */ + SockCancelIo(Handle); + + /* Get new status and normalize */ + Status = IoStatusBlock->Status; + if (Status == STATUS_CANCELLED) Status = STATUS_IO_TIMEOUT; + } + } + + /* Return the Flags */ + *ReceiveFlags = 0; + switch (Status) + { + /* Success */ + case STATUS_SUCCESS: + break; + + /* Pending I/O */ + case STATUS_PENDING: + ErrorCode = WSA_IO_PENDING; + goto error; + + /* Buffer Overflow */ + case STATUS_BUFFER_OVERFLOW: + /* Check if this was overlapped */ + if (lpOverlapped) + { + /* Return without bytes read */ + ErrorCode = WSA_IO_PENDING; + goto error; + } + + /* Return failure with bytes read */ + ErrorCode = WSAEMSGSIZE; + break; + + /* OOB Receive */ + case STATUS_RECEIVE_EXPEDITED: + *ReceiveFlags = MSG_OOB; + break; + + /* Partial OOB Receive */ + case STATUS_RECEIVE_PARTIAL_EXPEDITED: + *ReceiveFlags = MSG_PARTIAL | MSG_OOB; + break; + + /* Parial Receive */ + case STATUS_RECEIVE_PARTIAL: + *ReceiveFlags = MSG_PARTIAL; + break; + + /* Other NT Error */ + default: + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + break; + } + + /* Return the number of bytes read */ + *lpNumberOfBytesRead = PtrToUlong(IoStatusBlock->Information); + +error: + + /* Check if we have a socket here */ + if (Socket) + { + /* Check if async select was active */ + if (SockAsyncSelectCalled) + { + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* Re-enable the regular read event */ + SockReenableAsyncSelectEvent(Socket, FD_READ); + + /* Unlock socket */ + LeaveCriticalSection(&Socket->Lock); + } + + /* Dereference it */ + SockDereferenceSocket(Socket); + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +WSPRecv(SOCKET Handle, + LPWSABUF lpBuffers, + DWORD dwBufferCount, + LPDWORD lpNumberOfBytesRead, + LPDWORD ReceiveFlags, + LPWSAOVERLAPPED lpOverlapped, + LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + LPWSATHREADID lpThreadId, + LPINT lpErrno) +{ + PIO_STATUS_BLOCK IoStatusBlock; + IO_STATUS_BLOCK DummyIoStatusBlock; + AFD_RECV_INFO RecvInfo; + NTSTATUS Status; + PVOID APCContext; + PVOID ApcFunction; + HANDLE Event; + PWINSOCK_TEB_DATA ThreadData; + PSOCKET_INFORMATION Socket; + INT ErrorCode; + BOOLEAN ReturnValue; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Set up the Receive Structure */ + RecvInfo.BufferArray = (PAFD_WSABUF)lpBuffers; + RecvInfo.BufferCount = dwBufferCount; + RecvInfo.TdiFlags = 0; + RecvInfo.AfdFlags = 0; + + /* Set the TDI Flags */ + if (!(*ReceiveFlags)) + { + /* Use normal TDI Receive */ + RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL; + } + else + { + /* Check for valid flags */ + if ((*ReceiveFlags & ~(MSG_OOB | MSG_PEEK | MSG_PARTIAL))) + { + /* Fail */ + ErrorCode = WSAEOPNOTSUPP; + goto error; + } + + /* Check if OOB is being used */ + if (*ReceiveFlags & MSG_OOB) + { + /* Use Expedited Receive for OOB */ + RecvInfo.TdiFlags |= TDI_RECEIVE_EXPEDITED; + } + else + { + /* Use normal receive */ + RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL; + } + + /* Use Peek Receive if enabled */ + if (*ReceiveFlags & MSG_PEEK) RecvInfo.TdiFlags |= TDI_RECEIVE_PEEK; + + /* Use Partial Receive if enabled */ + if (*ReceiveFlags & MSG_PARTIAL) RecvInfo.TdiFlags |= TDI_RECEIVE_PARTIAL; + } + + /* Verifiy if we should use APC */ + if (!lpOverlapped) + { + /* Not using Overlapped structure, so use normal blocking on event */ + APCContext = NULL; + ApcFunction = NULL; + Event = ThreadData->EventHandle; + IoStatusBlock = &DummyIoStatusBlock; + } + else + { + /* Using apc, check if we have a completion routine */ + if (!lpCompletionRoutine) + { + /* No need for APC */ + APCContext = lpOverlapped; + ApcFunction = NULL; + Event = lpOverlapped->hEvent; + } + else + { + /* Use APC */ + ApcFunction = SockIoCompletion; + APCContext = lpCompletionRoutine; + Event = NULL; + + /* Skip Fast I/O */ + RecvInfo.AfdFlags = AFD_SKIP_FIO; + } + + /* Use the overlapped's structure buffer for the I/O Status Block */ + IoStatusBlock = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; + + /* Make this an overlapped I/O in AFD */ + RecvInfo.AfdFlags |= AFD_OVERLAPPED; + } + + /* Set is as Pending for now */ + IoStatusBlock->Status = STATUS_PENDING; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile((HANDLE)Handle, + Event, + ApcFunction, + APCContext, + IoStatusBlock, + IOCTL_AFD_RECV, + &RecvInfo, + sizeof(RecvInfo), + NULL, + 0); + + /* Increase the pending APC Count if we're using an APC */ + if (!NT_ERROR(Status) && ApcFunction) + { + ThreadData->PendingAPCs++; + InterlockedIncrement(&SockProcessPendingAPCCount); + } + + /* Wait for completition if not overlapped */ + if ((Status == STATUS_PENDING) && !(lpOverlapped)) + { + /* Wait for completion */ + ReturnValue = SockWaitForSingleObject(Event, + Handle, + MAYBE_BLOCKING_HOOK, + RECV_TIMEOUT); + + /* Check if the wait was successful */ + if (ReturnValue) + { + /* Get new status */ + Status = IoStatusBlock->Status; + } + else + { + /* Cancel the I/O */ + SockCancelIo(Handle); + + /* Get new status and normalize */ + Status = IoStatusBlock->Status; + if (Status == STATUS_CANCELLED) Status = STATUS_IO_TIMEOUT; + } + } + + /* Return the Flags */ + *ReceiveFlags = 0; + switch (Status) + { + /* Success */ + case STATUS_SUCCESS: + break; + + /* Pending I/O */ + case STATUS_PENDING: + ErrorCode = WSA_IO_PENDING; + goto error; + + /* Buffer Overflow */ + case STATUS_BUFFER_OVERFLOW: + /* Check if this was overlapped */ + if (lpOverlapped) + { + /* Return without bytes read */ + ErrorCode = WSA_IO_PENDING; + goto error; + } + + /* Return failure with bytes read */ + ErrorCode = WSAEMSGSIZE; + break; + + /* OOB Receive */ + case STATUS_RECEIVE_EXPEDITED: + *ReceiveFlags = MSG_OOB; + break; + + /* Partial OOB Receive */ + case STATUS_RECEIVE_PARTIAL_EXPEDITED: + *ReceiveFlags = MSG_PARTIAL | MSG_OOB; + break; + + /* Parial Receive */ + case STATUS_RECEIVE_PARTIAL: + *ReceiveFlags = MSG_PARTIAL; + break; + + /* Other NT Error */ + default: + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + break; + } + + /* Return the number of bytes read */ + *lpNumberOfBytesRead = PtrToUlong(IoStatusBlock->Information); + +error: + + /* Check if async select was active */ + if (SockAsyncSelectCalled) + { + /* Get the socket */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (Socket) + { + /* Lock it */ + EnterCriticalSection(&Socket->Lock); + + /* Check which event to re-enable */ + if (RecvInfo.TdiFlags & TDI_RECEIVE_EXPEDITED) + { + /* Re-enable the OOB event */ + SockReenableAsyncSelectEvent(Socket, FD_OOB); + } + else + { + /* Re-enable the regular read event */ + SockReenableAsyncSelectEvent(Socket, FD_READ); + } + + /* Unlock and dereference socket */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + } + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +INT +WSPAPI +WSPRecvFrom(SOCKET Handle, + LPWSABUF lpBuffers, + DWORD dwBufferCount, + LPDWORD lpNumberOfBytesRead, + LPDWORD ReceiveFlags, + PSOCKADDR SocketAddress, + PINT SocketAddressLength, + LPWSAOVERLAPPED lpOverlapped, + LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + LPWSATHREADID lpThreadId, + LPINT lpErrno) +{ + PIO_STATUS_BLOCK IoStatusBlock; + IO_STATUS_BLOCK DummyIoStatusBlock; + AFD_RECV_INFO_UDP RecvInfo; + NTSTATUS Status; + PVOID APCContext; + PVOID ApcFunction; + HANDLE Event; + PWINSOCK_TEB_DATA ThreadData; + PSOCKET_INFORMATION Socket; + INT ErrorCode; + BOOLEAN ReturnValue; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Fail if the socket isn't bound */ + if (Socket->SharedData.State == SocketOpen) + { + /* Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* If this is an unconnected or non datagram socket */ + if (!(MSAFD_IS_DGRAM_SOCK(Socket)) || + (!SocketAddress && !SocketAddressLength)) + { + /* Call WSP Recv */ + SockDereferenceSocket(Socket); + return WSPRecv(Handle, + lpBuffers, + dwBufferCount, + lpNumberOfBytesRead, + ReceiveFlags, + lpOverlapped, + lpCompletionRoutine, + lpThreadId, + lpErrno); + } + + /* If receive shutdown is enabled, fail */ + if (Socket->SharedData.ReceiveShutdown) + { + /* Fail */ + ErrorCode = WSAESHUTDOWN; + goto error; + } + + /* Check for valid Socket Address (Length) flags */ + if (!(SocketAddress) ^ (!SocketAddressLength || !(*SocketAddressLength))) + { + /* Fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* Check for valid flags */ + if ((*ReceiveFlags & ~(MSG_PEEK | MSG_PARTIAL))) + { + /* Fail */ + ErrorCode = WSAEOPNOTSUPP; + goto error; + } + + /* Check that the length is respected */ + if (SocketAddressLength && + (*SocketAddressLength < Socket->HelperData->MinWSAddressLength)) + { + /* Fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* Set up the Receive Structure */ + RecvInfo.BufferArray = (PAFD_WSABUF)lpBuffers; + RecvInfo.BufferCount = dwBufferCount; + RecvInfo.TdiFlags = TDI_RECEIVE_NORMAL; + RecvInfo.AfdFlags = 0; + RecvInfo.Address = SocketAddress; + RecvInfo.AddressLength = SocketAddressLength; + + /* Use Peek Receive if enabled */ + if (*ReceiveFlags & MSG_PEEK) RecvInfo.TdiFlags |= TDI_RECEIVE_PEEK; + + /* Use Partial Receive if enabled */ + if (*ReceiveFlags & MSG_PARTIAL) RecvInfo.TdiFlags |= TDI_RECEIVE_PARTIAL; + + /* Verifiy if we should use APC */ + if (!lpOverlapped) + { + /* Not using Overlapped structure, so use normal blocking on event */ + APCContext = NULL; + ApcFunction = NULL; + Event = ThreadData->EventHandle; + IoStatusBlock = &DummyIoStatusBlock; + } + else + { + /* Using apc, check if we have a completion routine */ + if (!lpCompletionRoutine) + { + /* No need for APC */ + APCContext = lpOverlapped; + ApcFunction = NULL; + Event = lpOverlapped->hEvent; + } + else + { + /* Use APC */ + ApcFunction = SockIoCompletion; + APCContext = lpCompletionRoutine; + Event = NULL; + + /* Skip Fast I/O */ + RecvInfo.AfdFlags = AFD_SKIP_FIO; + } + + /* Use the overlapped's structure buffer for the I/O Status Block */ + IoStatusBlock = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; + + /* Make this an overlapped I/O in AFD */ + RecvInfo.AfdFlags |= AFD_OVERLAPPED; + } + + /* Set is as Pending for now */ + IoStatusBlock->Status = STATUS_PENDING; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + Event, + ApcFunction, + APCContext, + IoStatusBlock, + IOCTL_AFD_RECV_DATAGRAM, + &RecvInfo, + sizeof(RecvInfo), + NULL, + 0); + + /* Increase the pending APC Count if we're using an APC */ + if (!NT_ERROR(Status) && ApcFunction) + { + ThreadData->PendingAPCs++; + InterlockedIncrement(&SockProcessPendingAPCCount); + } + + /* Wait for completition if not overlapped */ + if ((Status == STATUS_PENDING) && !(lpOverlapped)) + { + /* Wait for completion */ + ReturnValue = SockWaitForSingleObject(Event, + Handle, + MAYBE_BLOCKING_HOOK, + RECV_TIMEOUT); + + /* Check if the wait was successful */ + if (ReturnValue) + { + /* Get new status */ + Status = IoStatusBlock->Status; + } + else + { + /* Cancel the I/O */ + SockCancelIo(Handle); + + /* Get new status and normalize */ + Status = IoStatusBlock->Status; + if (Status == STATUS_CANCELLED) Status = STATUS_IO_TIMEOUT; + } + } + + /* Return the Flags */ + *ReceiveFlags = 0; + switch (Status) + { + /* Success */ + case STATUS_SUCCESS: + break; + + /* Pending I/O */ + case STATUS_PENDING: + ErrorCode = WSA_IO_PENDING; + goto error; + + /* Buffer Overflow */ + case STATUS_BUFFER_OVERFLOW: + /* Check if this was overlapped */ + if (lpOverlapped) + { + /* Return without bytes read */ + ErrorCode = WSA_IO_PENDING; + goto error; + } + + /* Return failure with bytes read */ + ErrorCode = WSAEMSGSIZE; + break; + + /* OOB Receive */ + case STATUS_RECEIVE_EXPEDITED: + *ReceiveFlags = MSG_OOB; + break; + + /* Partial OOB Receive */ + case STATUS_RECEIVE_PARTIAL_EXPEDITED: + *ReceiveFlags = MSG_PARTIAL | MSG_OOB; + break; + + /* Parial Receive */ + case STATUS_RECEIVE_PARTIAL: + *ReceiveFlags = MSG_PARTIAL; + break; + + /* Other NT Error */ + default: + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + break; + } + + /* Return the number of bytes read */ + *lpNumberOfBytesRead = PtrToUlong(IoStatusBlock->Information); + +error: + + /* Check if we have a socket here */ + if (Socket) + { + /* Check if async select was active */ + if (SockAsyncSelectCalled) + { + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* Re-enable the regular read event */ + SockReenableAsyncSelectEvent(Socket, FD_READ); + + /* Unlock socket */ + LeaveCriticalSection(&Socket->Lock); + } + + /* Dereference it */ + SockDereferenceSocket(Socket); + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +WSPRecv(SOCKET Handle, + LPWSABUF lpBuffers, + DWORD dwBufferCount, + LPDWORD lpNumberOfBytesRead, + LPDWORD ReceiveFlags, + LPWSAOVERLAPPED lpOverlapped, + LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + LPWSATHREADID lpThreadId, + LPINT lpErrno) +{ + PIO_STATUS_BLOCK IoStatusBlock; + IO_STATUS_BLOCK DummyIoStatusBlock; + AFD_RECV_INFO RecvInfo; + NTSTATUS Status; + PVOID APCContext; + PVOID ApcFunction; + HANDLE Event; + PWINSOCK_TEB_DATA ThreadData; + PSOCKET_INFORMATION Socket; + INT ErrorCode; + BOOLEAN ReturnValue; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Set up the Receive Structure */ + RecvInfo.BufferArray = (PAFD_WSABUF)lpBuffers; + RecvInfo.BufferCount = dwBufferCount; + RecvInfo.TdiFlags = 0; + RecvInfo.AfdFlags = 0; + + /* Set the TDI Flags */ + if (!(*ReceiveFlags)) + { + /* Use normal TDI Receive */ + RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL; + } + else + { + /* Check for valid flags */ + if ((*ReceiveFlags & ~(MSG_OOB | MSG_PEEK | MSG_PARTIAL))) + { + /* Fail */ + ErrorCode = WSAEOPNOTSUPP; + goto error; + } + + /* Check if OOB is being used */ + if (*ReceiveFlags & MSG_OOB) + { + /* Use Expedited Receive for OOB */ + RecvInfo.TdiFlags |= TDI_RECEIVE_EXPEDITED; + } + else + { + /* Use normal receive */ + RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL; + } + + /* Use Peek Receive if enabled */ + if (*ReceiveFlags & MSG_PEEK) RecvInfo.TdiFlags |= TDI_RECEIVE_PEEK; + + /* Use Partial Receive if enabled */ + if (*ReceiveFlags & MSG_PARTIAL) RecvInfo.TdiFlags |= TDI_RECEIVE_PARTIAL; + } + + /* Verifiy if we should use APC */ + if (!lpOverlapped) + { + /* Not using Overlapped structure, so use normal blocking on event */ + APCContext = NULL; + ApcFunction = NULL; + Event = ThreadData->EventHandle; + IoStatusBlock = &DummyIoStatusBlock; + } + else + { + /* Using apc, check if we have a completion routine */ + if (!lpCompletionRoutine) + { + /* No need for APC */ + APCContext = lpOverlapped; + ApcFunction = NULL; + Event = lpOverlapped->hEvent; + } + else + { + /* Use APC */ + ApcFunction = SockIoCompletion; + APCContext = lpCompletionRoutine; + Event = NULL; + + /* Skip Fast I/O */ + RecvInfo.AfdFlags = AFD_SKIP_FIO; + } + + /* Use the overlapped's structure buffer for the I/O Status Block */ + IoStatusBlock = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; + + /* Make this an overlapped I/O in AFD */ + RecvInfo.AfdFlags |= AFD_OVERLAPPED; + } + + /* Set is as Pending for now */ + IoStatusBlock->Status = STATUS_PENDING; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile((HANDLE)Handle, + Event, + ApcFunction, + APCContext, + IoStatusBlock, + IOCTL_AFD_RECV, + &RecvInfo, + sizeof(RecvInfo), + NULL, + 0); + + /* Increase the pending APC Count if we're using an APC */ + if (!NT_ERROR(Status) && ApcFunction) + { + ThreadData->PendingAPCs++; + InterlockedIncrement(&SockProcessPendingAPCCount); + } + + /* Wait for completition if not overlapped */ + if ((Status == STATUS_PENDING) && !(lpOverlapped)) + { + /* Wait for completion */ + ReturnValue = SockWaitForSingleObject(Event, + Handle, + MAYBE_BLOCKING_HOOK, + RECV_TIMEOUT); + + /* Check if the wait was successful */ + if (ReturnValue) + { + /* Get new status */ + Status = IoStatusBlock->Status; + } + else + { + /* Cancel the I/O */ + SockCancelIo(Handle); + + /* Get new status and normalize */ + Status = IoStatusBlock->Status; + if (Status == STATUS_CANCELLED) Status = STATUS_IO_TIMEOUT; + } + } + + /* Return the Flags */ + *ReceiveFlags = 0; + switch (Status) + { + /* Success */ + case STATUS_SUCCESS: + break; + + /* Pending I/O */ + case STATUS_PENDING: + ErrorCode = WSA_IO_PENDING; + goto error; + + /* Buffer Overflow */ + case STATUS_BUFFER_OVERFLOW: + /* Check if this was overlapped */ + if (lpOverlapped) + { + /* Return without bytes read */ + ErrorCode = WSA_IO_PENDING; + goto error; + } + + /* Return failure with bytes read */ + ErrorCode = WSAEMSGSIZE; + break; + + /* OOB Receive */ + case STATUS_RECEIVE_EXPEDITED: + *ReceiveFlags = MSG_OOB; + break; + + /* Partial OOB Receive */ + case STATUS_RECEIVE_PARTIAL_EXPEDITED: + *ReceiveFlags = MSG_PARTIAL | MSG_OOB; + break; + + /* Parial Receive */ + case STATUS_RECEIVE_PARTIAL: + *ReceiveFlags = MSG_PARTIAL; + break; + + /* Other NT Error */ + default: + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + break; + } + + /* Return the number of bytes read */ + *lpNumberOfBytesRead = PtrToUlong(IoStatusBlock->Information); + +error: + + /* Check if async select was active */ + if (SockAsyncSelectCalled) + { + /* Get the socket */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (Socket) + { + /* Lock it */ + EnterCriticalSection(&Socket->Lock); + + /* Check which event to re-enable */ + if (RecvInfo.TdiFlags & TDI_RECEIVE_EXPEDITED) + { + /* Re-enable the OOB event */ + SockReenableAsyncSelectEvent(Socket, FD_OOB); + } + else + { + /* Re-enable the regular read event */ + SockReenableAsyncSelectEvent(Socket, FD_READ); + } + + /* Unlock and dereference socket */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + } + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +INT +WSPAPI +WSPRecvFrom(SOCKET Handle, + LPWSABUF lpBuffers, + DWORD dwBufferCount, + LPDWORD lpNumberOfBytesRead, + LPDWORD ReceiveFlags, + PSOCKADDR SocketAddress, + PINT SocketAddressLength, + LPWSAOVERLAPPED lpOverlapped, + LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + LPWSATHREADID lpThreadId, + LPINT lpErrno) +{ + PIO_STATUS_BLOCK IoStatusBlock; + IO_STATUS_BLOCK DummyIoStatusBlock; + AFD_RECV_INFO_UDP RecvInfo; + NTSTATUS Status; + PVOID APCContext; + PVOID ApcFunction; + HANDLE Event; + PWINSOCK_TEB_DATA ThreadData; + PSOCKET_INFORMATION Socket; + INT ErrorCode; + BOOLEAN ReturnValue; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Fail if the socket isn't bound */ + if (Socket->SharedData.State == SocketOpen) + { + /* Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* If this is an unconnected or non datagram socket */ + if (!(MSAFD_IS_DGRAM_SOCK(Socket)) || + (!SocketAddress && !SocketAddressLength)) + { + /* Call WSP Recv */ + SockDereferenceSocket(Socket); + return WSPRecv(Handle, + lpBuffers, + dwBufferCount, + lpNumberOfBytesRead, + ReceiveFlags, + lpOverlapped, + lpCompletionRoutine, + lpThreadId, + lpErrno); + } + + /* If receive shutdown is enabled, fail */ + if (Socket->SharedData.ReceiveShutdown) + { + /* Fail */ + ErrorCode = WSAESHUTDOWN; + goto error; + } + + /* Check for valid Socket Address (Length) flags */ + if (!(SocketAddress) ^ (!SocketAddressLength || !(*SocketAddressLength))) + { + /* Fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* Check for valid flags */ + if ((*ReceiveFlags & ~(MSG_PEEK | MSG_PARTIAL))) + { + /* Fail */ + ErrorCode = WSAEOPNOTSUPP; + goto error; + } + + /* Check that the length is respected */ + if (SocketAddressLength && + (*SocketAddressLength < Socket->HelperData->MinWSAddressLength)) + { + /* Fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* Set up the Receive Structure */ + RecvInfo.BufferArray = (PAFD_WSABUF)lpBuffers; + RecvInfo.BufferCount = dwBufferCount; + RecvInfo.TdiFlags = TDI_RECEIVE_NORMAL; + RecvInfo.AfdFlags = 0; + RecvInfo.Address = SocketAddress; + RecvInfo.AddressLength = SocketAddressLength; + + /* Use Peek Receive if enabled */ + if (*ReceiveFlags & MSG_PEEK) RecvInfo.TdiFlags |= TDI_RECEIVE_PEEK; + + /* Use Partial Receive if enabled */ + if (*ReceiveFlags & MSG_PARTIAL) RecvInfo.TdiFlags |= TDI_RECEIVE_PARTIAL; + + /* Verifiy if we should use APC */ + if (!lpOverlapped) + { + /* Not using Overlapped structure, so use normal blocking on event */ + APCContext = NULL; + ApcFunction = NULL; + Event = ThreadData->EventHandle; + IoStatusBlock = &DummyIoStatusBlock; + } + else + { + /* Using apc, check if we have a completion routine */ + if (!lpCompletionRoutine) + { + /* No need for APC */ + APCContext = lpOverlapped; + ApcFunction = NULL; + Event = lpOverlapped->hEvent; + } + else + { + /* Use APC */ + ApcFunction = SockIoCompletion; + APCContext = lpCompletionRoutine; + Event = NULL; + + /* Skip Fast I/O */ + RecvInfo.AfdFlags = AFD_SKIP_FIO; + } + + /* Use the overlapped's structure buffer for the I/O Status Block */ + IoStatusBlock = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; + + /* Make this an overlapped I/O in AFD */ + RecvInfo.AfdFlags |= AFD_OVERLAPPED; + } + + /* Set is as Pending for now */ + IoStatusBlock->Status = STATUS_PENDING; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + Event, + ApcFunction, + APCContext, + IoStatusBlock, + IOCTL_AFD_RECV_DATAGRAM, + &RecvInfo, + sizeof(RecvInfo), + NULL, + 0); + + /* Increase the pending APC Count if we're using an APC */ + if (!NT_ERROR(Status) && ApcFunction) + { + ThreadData->PendingAPCs++; + InterlockedIncrement(&SockProcessPendingAPCCount); + } + + /* Wait for completition if not overlapped */ + if ((Status == STATUS_PENDING) && !(lpOverlapped)) + { + /* Wait for completion */ + ReturnValue = SockWaitForSingleObject(Event, + Handle, + MAYBE_BLOCKING_HOOK, + RECV_TIMEOUT); + + /* Check if the wait was successful */ + if (ReturnValue) + { + /* Get new status */ + Status = IoStatusBlock->Status; + } + else + { + /* Cancel the I/O */ + SockCancelIo(Handle); + + /* Get new status and normalize */ + Status = IoStatusBlock->Status; + if (Status == STATUS_CANCELLED) Status = STATUS_IO_TIMEOUT; + } + } + + /* Return the Flags */ + *ReceiveFlags = 0; + switch (Status) + { + /* Success */ + case STATUS_SUCCESS: + break; + + /* Pending I/O */ + case STATUS_PENDING: + ErrorCode = WSA_IO_PENDING; + goto error; + + /* Buffer Overflow */ + case STATUS_BUFFER_OVERFLOW: + /* Check if this was overlapped */ + if (lpOverlapped) + { + /* Return without bytes read */ + ErrorCode = WSA_IO_PENDING; + goto error; + } + + /* Return failure with bytes read */ + ErrorCode = WSAEMSGSIZE; + break; + + /* OOB Receive */ + case STATUS_RECEIVE_EXPEDITED: + *ReceiveFlags = MSG_OOB; + break; + + /* Partial OOB Receive */ + case STATUS_RECEIVE_PARTIAL_EXPEDITED: + *ReceiveFlags = MSG_PARTIAL | MSG_OOB; + break; + + /* Parial Receive */ + case STATUS_RECEIVE_PARTIAL: + *ReceiveFlags = MSG_PARTIAL; + break; + + /* Other NT Error */ + default: + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + break; + } + + /* Return the number of bytes read */ + *lpNumberOfBytesRead = PtrToUlong(IoStatusBlock->Information); + +error: + + /* Check if we have a socket here */ + if (Socket) + { + /* Check if async select was active */ + if (SockAsyncSelectCalled) + { + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* Re-enable the regular read event */ + SockReenableAsyncSelectEvent(Socket, FD_READ); + + /* Unlock socket */ + LeaveCriticalSection(&Socket->Lock); + } + + /* Dereference it */ + SockDereferenceSocket(Socket); + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +WSPRecv(SOCKET Handle, + LPWSABUF lpBuffers, + DWORD dwBufferCount, + LPDWORD lpNumberOfBytesRead, + LPDWORD ReceiveFlags, + LPWSAOVERLAPPED lpOverlapped, + LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + LPWSATHREADID lpThreadId, + LPINT lpErrno) +{ + PIO_STATUS_BLOCK IoStatusBlock; + IO_STATUS_BLOCK DummyIoStatusBlock; + AFD_RECV_INFO RecvInfo; + NTSTATUS Status; + PVOID APCContext; + PVOID ApcFunction; + HANDLE Event; + PWINSOCK_TEB_DATA ThreadData; + PSOCKET_INFORMATION Socket; + INT ErrorCode; + BOOLEAN ReturnValue; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Set up the Receive Structure */ + RecvInfo.BufferArray = (PAFD_WSABUF)lpBuffers; + RecvInfo.BufferCount = dwBufferCount; + RecvInfo.TdiFlags = 0; + RecvInfo.AfdFlags = 0; + + /* Set the TDI Flags */ + if (!(*ReceiveFlags)) + { + /* Use normal TDI Receive */ + RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL; + } + else + { + /* Check for valid flags */ + if ((*ReceiveFlags & ~(MSG_OOB | MSG_PEEK | MSG_PARTIAL))) + { + /* Fail */ + ErrorCode = WSAEOPNOTSUPP; + goto error; + } + + /* Check if OOB is being used */ + if (*ReceiveFlags & MSG_OOB) + { + /* Use Expedited Receive for OOB */ + RecvInfo.TdiFlags |= TDI_RECEIVE_EXPEDITED; + } + else + { + /* Use normal receive */ + RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL; + } + + /* Use Peek Receive if enabled */ + if (*ReceiveFlags & MSG_PEEK) RecvInfo.TdiFlags |= TDI_RECEIVE_PEEK; + + /* Use Partial Receive if enabled */ + if (*ReceiveFlags & MSG_PARTIAL) RecvInfo.TdiFlags |= TDI_RECEIVE_PARTIAL; + } + + /* Verifiy if we should use APC */ + if (!lpOverlapped) + { + /* Not using Overlapped structure, so use normal blocking on event */ + APCContext = NULL; + ApcFunction = NULL; + Event = ThreadData->EventHandle; + IoStatusBlock = &DummyIoStatusBlock; + } + else + { + /* Using apc, check if we have a completion routine */ + if (!lpCompletionRoutine) + { + /* No need for APC */ + APCContext = lpOverlapped; + ApcFunction = NULL; + Event = lpOverlapped->hEvent; + } + else + { + /* Use APC */ + ApcFunction = SockIoCompletion; + APCContext = lpCompletionRoutine; + Event = NULL; + + /* Skip Fast I/O */ + RecvInfo.AfdFlags = AFD_SKIP_FIO; + } + + /* Use the overlapped's structure buffer for the I/O Status Block */ + IoStatusBlock = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; + + /* Make this an overlapped I/O in AFD */ + RecvInfo.AfdFlags |= AFD_OVERLAPPED; + } + + /* Set is as Pending for now */ + IoStatusBlock->Status = STATUS_PENDING; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile((HANDLE)Handle, + Event, + ApcFunction, + APCContext, + IoStatusBlock, + IOCTL_AFD_RECV, + &RecvInfo, + sizeof(RecvInfo), + NULL, + 0); + + /* Increase the pending APC Count if we're using an APC */ + if (!NT_ERROR(Status) && ApcFunction) + { + ThreadData->PendingAPCs++; + InterlockedIncrement(&SockProcessPendingAPCCount); + } + + /* Wait for completition if not overlapped */ + if ((Status == STATUS_PENDING) && !(lpOverlapped)) + { + /* Wait for completion */ + ReturnValue = SockWaitForSingleObject(Event, + Handle, + MAYBE_BLOCKING_HOOK, + RECV_TIMEOUT); + + /* Check if the wait was successful */ + if (ReturnValue) + { + /* Get new status */ + Status = IoStatusBlock->Status; + } + else + { + /* Cancel the I/O */ + SockCancelIo(Handle); + + /* Get new status and normalize */ + Status = IoStatusBlock->Status; + if (Status == STATUS_CANCELLED) Status = STATUS_IO_TIMEOUT; + } + } + + /* Return the Flags */ + *ReceiveFlags = 0; + switch (Status) + { + /* Success */ + case STATUS_SUCCESS: + break; + + /* Pending I/O */ + case STATUS_PENDING: + ErrorCode = WSA_IO_PENDING; + goto error; + + /* Buffer Overflow */ + case STATUS_BUFFER_OVERFLOW: + /* Check if this was overlapped */ + if (lpOverlapped) + { + /* Return without bytes read */ + ErrorCode = WSA_IO_PENDING; + goto error; + } + + /* Return failure with bytes read */ + ErrorCode = WSAEMSGSIZE; + break; + + /* OOB Receive */ + case STATUS_RECEIVE_EXPEDITED: + *ReceiveFlags = MSG_OOB; + break; + + /* Partial OOB Receive */ + case STATUS_RECEIVE_PARTIAL_EXPEDITED: + *ReceiveFlags = MSG_PARTIAL | MSG_OOB; + break; + + /* Parial Receive */ + case STATUS_RECEIVE_PARTIAL: + *ReceiveFlags = MSG_PARTIAL; + break; + + /* Other NT Error */ + default: + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + break; + } + + /* Return the number of bytes read */ + *lpNumberOfBytesRead = PtrToUlong(IoStatusBlock->Information); + +error: + + /* Check if async select was active */ + if (SockAsyncSelectCalled) + { + /* Get the socket */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (Socket) + { + /* Lock it */ + EnterCriticalSection(&Socket->Lock); + + /* Check which event to re-enable */ + if (RecvInfo.TdiFlags & TDI_RECEIVE_EXPEDITED) + { + /* Re-enable the OOB event */ + SockReenableAsyncSelectEvent(Socket, FD_OOB); + } + else + { + /* Re-enable the regular read event */ + SockReenableAsyncSelectEvent(Socket, FD_READ); + } + + /* Unlock and dereference socket */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + } + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +INT +WSPAPI +WSPRecvFrom(SOCKET Handle, + LPWSABUF lpBuffers, + DWORD dwBufferCount, + LPDWORD lpNumberOfBytesRead, + LPDWORD ReceiveFlags, + PSOCKADDR SocketAddress, + PINT SocketAddressLength, + LPWSAOVERLAPPED lpOverlapped, + LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + LPWSATHREADID lpThreadId, + LPINT lpErrno) +{ + PIO_STATUS_BLOCK IoStatusBlock; + IO_STATUS_BLOCK DummyIoStatusBlock; + AFD_RECV_INFO_UDP RecvInfo; + NTSTATUS Status; + PVOID APCContext; + PVOID ApcFunction; + HANDLE Event; + PWINSOCK_TEB_DATA ThreadData; + PSOCKET_INFORMATION Socket; + INT ErrorCode; + BOOLEAN ReturnValue; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Fail if the socket isn't bound */ + if (Socket->SharedData.State == SocketOpen) + { + /* Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* If this is an unconnected or non datagram socket */ + if (!(MSAFD_IS_DGRAM_SOCK(Socket)) || + (!SocketAddress && !SocketAddressLength)) + { + /* Call WSP Recv */ + SockDereferenceSocket(Socket); + return WSPRecv(Handle, + lpBuffers, + dwBufferCount, + lpNumberOfBytesRead, + ReceiveFlags, + lpOverlapped, + lpCompletionRoutine, + lpThreadId, + lpErrno); + } + + /* If receive shutdown is enabled, fail */ + if (Socket->SharedData.ReceiveShutdown) + { + /* Fail */ + ErrorCode = WSAESHUTDOWN; + goto error; + } + + /* Check for valid Socket Address (Length) flags */ + if (!(SocketAddress) ^ (!SocketAddressLength || !(*SocketAddressLength))) + { + /* Fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* Check for valid flags */ + if ((*ReceiveFlags & ~(MSG_PEEK | MSG_PARTIAL))) + { + /* Fail */ + ErrorCode = WSAEOPNOTSUPP; + goto error; + } + + /* Check that the length is respected */ + if (SocketAddressLength && + (*SocketAddressLength < Socket->HelperData->MinWSAddressLength)) + { + /* Fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* Set up the Receive Structure */ + RecvInfo.BufferArray = (PAFD_WSABUF)lpBuffers; + RecvInfo.BufferCount = dwBufferCount; + RecvInfo.TdiFlags = TDI_RECEIVE_NORMAL; + RecvInfo.AfdFlags = 0; + RecvInfo.Address = SocketAddress; + RecvInfo.AddressLength = SocketAddressLength; + + /* Use Peek Receive if enabled */ + if (*ReceiveFlags & MSG_PEEK) RecvInfo.TdiFlags |= TDI_RECEIVE_PEEK; + + /* Use Partial Receive if enabled */ + if (*ReceiveFlags & MSG_PARTIAL) RecvInfo.TdiFlags |= TDI_RECEIVE_PARTIAL; + + /* Verifiy if we should use APC */ + if (!lpOverlapped) + { + /* Not using Overlapped structure, so use normal blocking on event */ + APCContext = NULL; + ApcFunction = NULL; + Event = ThreadData->EventHandle; + IoStatusBlock = &DummyIoStatusBlock; + } + else + { + /* Using apc, check if we have a completion routine */ + if (!lpCompletionRoutine) + { + /* No need for APC */ + APCContext = lpOverlapped; + ApcFunction = NULL; + Event = lpOverlapped->hEvent; + } + else + { + /* Use APC */ + ApcFunction = SockIoCompletion; + APCContext = lpCompletionRoutine; + Event = NULL; + + /* Skip Fast I/O */ + RecvInfo.AfdFlags = AFD_SKIP_FIO; + } + + /* Use the overlapped's structure buffer for the I/O Status Block */ + IoStatusBlock = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; + + /* Make this an overlapped I/O in AFD */ + RecvInfo.AfdFlags |= AFD_OVERLAPPED; + } + + /* Set is as Pending for now */ + IoStatusBlock->Status = STATUS_PENDING; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + Event, + ApcFunction, + APCContext, + IoStatusBlock, + IOCTL_AFD_RECV_DATAGRAM, + &RecvInfo, + sizeof(RecvInfo), + NULL, + 0); + + /* Increase the pending APC Count if we're using an APC */ + if (!NT_ERROR(Status) && ApcFunction) + { + ThreadData->PendingAPCs++; + InterlockedIncrement(&SockProcessPendingAPCCount); + } + + /* Wait for completition if not overlapped */ + if ((Status == STATUS_PENDING) && !(lpOverlapped)) + { + /* Wait for completion */ + ReturnValue = SockWaitForSingleObject(Event, + Handle, + MAYBE_BLOCKING_HOOK, + RECV_TIMEOUT); + + /* Check if the wait was successful */ + if (ReturnValue) + { + /* Get new status */ + Status = IoStatusBlock->Status; + } + else + { + /* Cancel the I/O */ + SockCancelIo(Handle); + + /* Get new status and normalize */ + Status = IoStatusBlock->Status; + if (Status == STATUS_CANCELLED) Status = STATUS_IO_TIMEOUT; + } + } + + /* Return the Flags */ + *ReceiveFlags = 0; + switch (Status) + { + /* Success */ + case STATUS_SUCCESS: + break; + + /* Pending I/O */ + case STATUS_PENDING: + ErrorCode = WSA_IO_PENDING; + goto error; + + /* Buffer Overflow */ + case STATUS_BUFFER_OVERFLOW: + /* Check if this was overlapped */ + if (lpOverlapped) + { + /* Return without bytes read */ + ErrorCode = WSA_IO_PENDING; + goto error; + } + + /* Return failure with bytes read */ + ErrorCode = WSAEMSGSIZE; + break; + + /* OOB Receive */ + case STATUS_RECEIVE_EXPEDITED: + *ReceiveFlags = MSG_OOB; + break; + + /* Partial OOB Receive */ + case STATUS_RECEIVE_PARTIAL_EXPEDITED: + *ReceiveFlags = MSG_PARTIAL | MSG_OOB; + break; + + /* Parial Receive */ + case STATUS_RECEIVE_PARTIAL: + *ReceiveFlags = MSG_PARTIAL; + break; + + /* Other NT Error */ + default: + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + break; + } + + /* Return the number of bytes read */ + *lpNumberOfBytesRead = PtrToUlong(IoStatusBlock->Information); + +error: + + /* Check if we have a socket here */ + if (Socket) + { + /* Check if async select was active */ + if (SockAsyncSelectCalled) + { + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* Re-enable the regular read event */ + SockReenableAsyncSelectEvent(Socket, FD_READ); + + /* Unlock socket */ + LeaveCriticalSection(&Socket->Lock); + } + + /* Dereference it */ + SockDereferenceSocket(Socket); + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + diff --git a/dll/win32/mswsock/msafd/sanaccpt.c b/dll/win32/mswsock/msafd/sanaccpt.c new file mode 100644 index 00000000000..3e062e90d63 --- /dev/null +++ b/dll/win32/mswsock/msafd/sanaccpt.c @@ -0,0 +1,56 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + diff --git a/dll/win32/mswsock/msafd/sanconn.c b/dll/win32/mswsock/msafd/sanconn.c new file mode 100644 index 00000000000..3e062e90d63 --- /dev/null +++ b/dll/win32/mswsock/msafd/sanconn.c @@ -0,0 +1,56 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + diff --git a/dll/win32/mswsock/msafd/sanflow.c b/dll/win32/mswsock/msafd/sanflow.c new file mode 100644 index 00000000000..3e062e90d63 --- /dev/null +++ b/dll/win32/mswsock/msafd/sanflow.c @@ -0,0 +1,56 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + diff --git a/dll/win32/mswsock/msafd/sanlistn.c b/dll/win32/mswsock/msafd/sanlistn.c new file mode 100644 index 00000000000..3e062e90d63 --- /dev/null +++ b/dll/win32/mswsock/msafd/sanlistn.c @@ -0,0 +1,56 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + diff --git a/dll/win32/mswsock/msafd/sanprov.c b/dll/win32/mswsock/msafd/sanprov.c new file mode 100644 index 00000000000..ed15fb9f046 --- /dev/null +++ b/dll/win32/mswsock/msafd/sanprov.c @@ -0,0 +1,240 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +HANDLE SockSanCleanUpCompleteEvent; +BOOLEAN SockSanEnabled; + +WSAPROTOCOL_INFOW SockTcpProviderInfo = +{ + XP1_GUARANTEED_DELIVERY | + XP1_GUARANTEED_ORDER | + XP1_GRACEFUL_CLOSE | + XP1_EXPEDITED_DATA | + XP1_IFS_HANDLES, + 0, + 0, + 0, + PFL_MATCHES_PROTOCOL_ZERO, + { + 0xe70f1aa0, + 0xab8b, + 0x11cf, + {0x8c, 0xa3, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92} + }, + 0, + { + BASE_PROTOCOL, + { 0, 0, 0, 0, 0, 0, 0 } + }, + 2, + AF_INET, + sizeof(SOCKADDR_IN), + sizeof(SOCKADDR_IN), + SOCK_STREAM, + IPPROTO_TCP, + 0, + BIGENDIAN, + SECURITY_PROTOCOL_NONE, + 0, + 0, + L"MSAFD Tcpip [TCP/IP]" +}; + +/* FUNCTIONS *****************************************************************/ + +VOID +WSPAPI +SockSanInitialize(VOID) +{ + +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +HANDLE SockSanCleanUpCompleteEvent; +BOOLEAN SockSanEnabled; + +WSAPROTOCOL_INFOW SockTcpProviderInfo = +{ + XP1_GUARANTEED_DELIVERY | + XP1_GUARANTEED_ORDER | + XP1_GRACEFUL_CLOSE | + XP1_EXPEDITED_DATA | + XP1_IFS_HANDLES, + 0, + 0, + 0, + PFL_MATCHES_PROTOCOL_ZERO, + { + 0xe70f1aa0, + 0xab8b, + 0x11cf, + {0x8c, 0xa3, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92} + }, + 0, + { + BASE_PROTOCOL, + { 0, 0, 0, 0, 0, 0, 0 } + }, + 2, + AF_INET, + sizeof(SOCKADDR_IN), + sizeof(SOCKADDR_IN), + SOCK_STREAM, + IPPROTO_TCP, + 0, + BIGENDIAN, + SECURITY_PROTOCOL_NONE, + 0, + 0, + L"MSAFD Tcpip [TCP/IP]" +}; + +/* FUNCTIONS *****************************************************************/ + +VOID +WSPAPI +SockSanInitialize(VOID) +{ + +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +HANDLE SockSanCleanUpCompleteEvent; +BOOLEAN SockSanEnabled; + +WSAPROTOCOL_INFOW SockTcpProviderInfo = +{ + XP1_GUARANTEED_DELIVERY | + XP1_GUARANTEED_ORDER | + XP1_GRACEFUL_CLOSE | + XP1_EXPEDITED_DATA | + XP1_IFS_HANDLES, + 0, + 0, + 0, + PFL_MATCHES_PROTOCOL_ZERO, + { + 0xe70f1aa0, + 0xab8b, + 0x11cf, + {0x8c, 0xa3, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92} + }, + 0, + { + BASE_PROTOCOL, + { 0, 0, 0, 0, 0, 0, 0 } + }, + 2, + AF_INET, + sizeof(SOCKADDR_IN), + sizeof(SOCKADDR_IN), + SOCK_STREAM, + IPPROTO_TCP, + 0, + BIGENDIAN, + SECURITY_PROTOCOL_NONE, + 0, + 0, + L"MSAFD Tcpip [TCP/IP]" +}; + +/* FUNCTIONS *****************************************************************/ + +VOID +WSPAPI +SockSanInitialize(VOID) +{ + +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +HANDLE SockSanCleanUpCompleteEvent; +BOOLEAN SockSanEnabled; + +WSAPROTOCOL_INFOW SockTcpProviderInfo = +{ + XP1_GUARANTEED_DELIVERY | + XP1_GUARANTEED_ORDER | + XP1_GRACEFUL_CLOSE | + XP1_EXPEDITED_DATA | + XP1_IFS_HANDLES, + 0, + 0, + 0, + PFL_MATCHES_PROTOCOL_ZERO, + { + 0xe70f1aa0, + 0xab8b, + 0x11cf, + {0x8c, 0xa3, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92} + }, + 0, + { + BASE_PROTOCOL, + { 0, 0, 0, 0, 0, 0, 0 } + }, + 2, + AF_INET, + sizeof(SOCKADDR_IN), + sizeof(SOCKADDR_IN), + SOCK_STREAM, + IPPROTO_TCP, + 0, + BIGENDIAN, + SECURITY_PROTOCOL_NONE, + 0, + 0, + L"MSAFD Tcpip [TCP/IP]" +}; + +/* FUNCTIONS *****************************************************************/ + +VOID +WSPAPI +SockSanInitialize(VOID) +{ + +} + diff --git a/dll/win32/mswsock/msafd/sanrdma.c b/dll/win32/mswsock/msafd/sanrdma.c new file mode 100644 index 00000000000..3e062e90d63 --- /dev/null +++ b/dll/win32/mswsock/msafd/sanrdma.c @@ -0,0 +1,56 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + diff --git a/dll/win32/mswsock/msafd/sanrecv.c b/dll/win32/mswsock/msafd/sanrecv.c new file mode 100644 index 00000000000..3e062e90d63 --- /dev/null +++ b/dll/win32/mswsock/msafd/sanrecv.c @@ -0,0 +1,56 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + diff --git a/dll/win32/mswsock/msafd/sansend.c b/dll/win32/mswsock/msafd/sansend.c new file mode 100644 index 00000000000..3e062e90d63 --- /dev/null +++ b/dll/win32/mswsock/msafd/sansend.c @@ -0,0 +1,56 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + diff --git a/dll/win32/mswsock/msafd/sanshutd.c b/dll/win32/mswsock/msafd/sanshutd.c new file mode 100644 index 00000000000..3e062e90d63 --- /dev/null +++ b/dll/win32/mswsock/msafd/sanshutd.c @@ -0,0 +1,56 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + diff --git a/dll/win32/mswsock/msafd/sansock.c b/dll/win32/mswsock/msafd/sansock.c new file mode 100644 index 00000000000..3e062e90d63 --- /dev/null +++ b/dll/win32/mswsock/msafd/sansock.c @@ -0,0 +1,56 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + diff --git a/dll/win32/mswsock/msafd/santf.c b/dll/win32/mswsock/msafd/santf.c new file mode 100644 index 00000000000..3e062e90d63 --- /dev/null +++ b/dll/win32/mswsock/msafd/santf.c @@ -0,0 +1,56 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + diff --git a/dll/win32/mswsock/msafd/sanutil.c b/dll/win32/mswsock/msafd/sanutil.c new file mode 100644 index 00000000000..3e062e90d63 --- /dev/null +++ b/dll/win32/mswsock/msafd/sanutil.c @@ -0,0 +1,56 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + diff --git a/dll/win32/mswsock/msafd/select.c b/dll/win32/mswsock/msafd/select.c new file mode 100644 index 00000000000..39f4d505c85 --- /dev/null +++ b/dll/win32/mswsock/msafd/select.c @@ -0,0 +1,3952 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +#define MSAFD_CHECK_EVENT(e, s) \ + (!(s->SharedData.AsyncDisabledEvents & e) && \ + (s->SharedData.AsyncEvents & e)) + +#define HANDLES_IN_SET(s) \ + s == NULL ? 0 : (s->fd_count & 0xFFFF) + +/* DATA **********************************************************************/ + +HANDLE SockAsyncSelectHelperHandle; +BOOLEAN SockAsyncSelectCalled; + +/* FUNCTIONS *****************************************************************/ + +BOOLEAN +WSPAPI +SockCheckAndInitAsyncSelectHelper(VOID) +{ + UNICODE_STRING AfdHelper; + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + FILE_COMPLETION_INFORMATION CompletionInfo; + OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags; + + /* First, make sure we're not already intialized */ + if (SockAsyncSelectHelperHandle) return TRUE; + + /* Acquire the global lock */ + SockAcquireRwLockExclusive(&SocketGlobalLock); + + /* Check again, under the lock */ + if (SockAsyncSelectHelperHandle) + { + /* Return without lock */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + return TRUE; + } + + /* Set up Handle Name and Object */ + RtlInitUnicodeString(&AfdHelper, L"\\Device\\Afd\\AsyncSelectHlp" ); + InitializeObjectAttributes(&ObjectAttributes, + &AfdHelper, + OBJ_INHERIT | OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + /* Open the Handle to AFD */ + Status = NtCreateFile(&SockAsyncSelectHelperHandle, + GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, + &ObjectAttributes, + &IoStatusBlock, + NULL, + 0, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_OPEN_IF, + 0, + NULL, + 0); + if (!NT_SUCCESS(Status)) + { + /* Return without lock */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + return TRUE; + } + + /* Check if the port exists, and if not, create it */ + if (SockAsyncQueuePort) SockCreateAsyncQueuePort(); + + /* + * Now Set up the Completion Port Information + * This means that whenever a Poll is finished, the routine will be executed + */ + CompletionInfo.Port = SockAsyncQueuePort; + CompletionInfo.Key = SockAsyncSelectCompletion; + Status = NtSetInformationFile(SockAsyncSelectHelperHandle, + &IoStatusBlock, + &CompletionInfo, + sizeof(CompletionInfo), + FileCompletionInformation); + + /* Protect the Handle */ + HandleFlags.ProtectFromClose = TRUE; + HandleFlags.Inherit = FALSE; + Status = NtSetInformationObject(SockAsyncQueuePort, + ObjectHandleFlagInformation, + &HandleFlags, + sizeof(HandleFlags)); + + /* + * Set this variable to true so that Send/Recv/Accept will know whether + * to renable disabled events + */ + SockAsyncSelectCalled = TRUE; + + /* Release lock and return */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + return TRUE; +} + +VOID +WSPAPI +SockAsyncSelectCompletion(PVOID Context, + PIO_STATUS_BLOCK IoStatusBlock) +{ + PASYNC_DATA AsyncData = Context; + PSOCKET_INFORMATION Socket = AsyncData->ParentSocket; + ULONG Events; + INT ErrorCode; + + /* Acquire the socket lock */ + EnterCriticalSection(&Socket->Lock); + + /* Check if the socket was closed or the I/O cancelled */ + if ((Socket->SharedData.State == SocketClosed) || + (IoStatusBlock->Status == STATUS_CANCELLED)) + { + /* Return */ + LeaveCriticalSection(&Socket->Lock); + goto error; + } + + /* Check if the Sequence Number Changed behind our back */ + if (AsyncData->SequenceNumber != Socket->SharedData.SequenceNumber) + { + /* Return */ + LeaveCriticalSection(&Socket->Lock); + goto error; + } + + /* Check we were manually called b/c of a failure */ + if (!NT_SUCCESS(IoStatusBlock->Status)) + { + /* Get the error and tell WPU about it */ + ErrorCode = NtStatusToSocketError(IoStatusBlock->Status); + SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, + Socket->SharedData.wMsg, + Socket->Handle, + WSAMAKESELECTREPLY(0, ErrorCode)); + + /* Return */ + LeaveCriticalSection(&Socket->Lock); + goto error; + } + + /* Select the event bits */ + Events = AsyncData->AsyncSelectInfo.Handles[0].Events; + + /* Check for receive event */ + if (MSAFD_CHECK_EVENT(FD_READ, Socket) && (Events & AFD_EVENT_RECEIVE)) + { + /* Make the Notifcation */ + SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, + Socket->SharedData.wMsg, + Socket->Handle, + WSAMAKESELECTREPLY(FD_READ, 0)); + + /* Disable this event until the next read(); */ + Socket->SharedData.AsyncDisabledEvents |= FD_READ; + } + + /* Check for oob receive event */ + if (MSAFD_CHECK_EVENT(FD_OOB, Socket) && (Events & AFD_EVENT_OOB_RECEIVE)) + { + /* Make the Notifcation */ + SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, + Socket->SharedData.wMsg, + Socket->Handle, + WSAMAKESELECTREPLY(FD_OOB, 0)); + + /* Disable this event until the next read(); */ + Socket->SharedData.AsyncDisabledEvents |= FD_OOB; + } + + /* Check for write event */ + if (MSAFD_CHECK_EVENT(FD_WRITE, Socket) && (Events & AFD_EVENT_SEND)) + { + /* Make the Notifcation */ + SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, + Socket->SharedData.wMsg, + Socket->Handle, + WSAMAKESELECTREPLY(FD_WRITE, 0)); + + /* Disable this event until the next read(); */ + Socket->SharedData.AsyncDisabledEvents |= FD_WRITE; + } + + /* Check for accept event */ + if (MSAFD_CHECK_EVENT(FD_ACCEPT, Socket) && (Events & AFD_EVENT_ACCEPT)) + { + /* Make the Notifcation */ + SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, + Socket->SharedData.wMsg, + Socket->Handle, + WSAMAKESELECTREPLY(FD_ACCEPT, 0)); + + /* Disable this event until the next read(); */ + Socket->SharedData.AsyncDisabledEvents |= FD_ACCEPT; + } + + /* Check for close events */ + if (MSAFD_CHECK_EVENT(FD_CLOSE, Socket) && ((Events & AFD_EVENT_ACCEPT) || + (Events & AFD_EVENT_ABORT) || + (Events & AFD_EVENT_CLOSE))) + { + /* Make the Notifcation */ + SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, + Socket->SharedData.wMsg, + Socket->Handle, + WSAMAKESELECTREPLY(FD_CLOSE, 0)); + + /* Disable this event until the next read(); */ + Socket->SharedData.AsyncDisabledEvents |= FD_CLOSE; + } + + /* Check for QOS event */ + if (MSAFD_CHECK_EVENT(FD_QOS, Socket) && (Events & AFD_EVENT_QOS)) + { + /* Make the Notifcation */ + SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, + Socket->SharedData.wMsg, + Socket->Handle, + WSAMAKESELECTREPLY(FD_QOS, 0)); + + /* Disable this event until the next read(); */ + Socket->SharedData.AsyncDisabledEvents |= FD_QOS; + } + + /* Check for Group QOS event */ + if (MSAFD_CHECK_EVENT(FD_GROUP_QOS, Socket) && (Events & AFD_EVENT_GROUP_QOS)) + { + /* Make the Notifcation */ + SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, + Socket->SharedData.wMsg, + Socket->Handle, + WSAMAKESELECTREPLY(FD_GROUP_QOS, 0)); + + /* Disable this event until the next read(); */ + Socket->SharedData.AsyncDisabledEvents |= FD_GROUP_QOS; + } + + /* Check for Routing Interface Change event */ + if (MSAFD_CHECK_EVENT(FD_ROUTING_INTERFACE_CHANGE, Socket) && + (Events & AFD_EVENT_ROUTING_INTERFACE_CHANGE)) + { + /* Make the Notifcation */ + SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, + Socket->SharedData.wMsg, + Socket->Handle, + WSAMAKESELECTREPLY(FD_ROUTING_INTERFACE_CHANGE, 0)); + + /* Disable this event until the next read(); */ + Socket->SharedData.AsyncDisabledEvents |= FD_ROUTING_INTERFACE_CHANGE; + } + + /* Check for Address List Change event */ + if (MSAFD_CHECK_EVENT(FD_ADDRESS_LIST_CHANGE, Socket) && + (Events & AFD_EVENT_ADDRESS_LIST_CHANGE)) + { + /* Make the Notifcation */ + SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, + Socket->SharedData.wMsg, + Socket->Handle, + WSAMAKESELECTREPLY(FD_ADDRESS_LIST_CHANGE, 0)); + + /* Disable this event until the next read(); */ + Socket->SharedData.AsyncDisabledEvents |= FD_ADDRESS_LIST_CHANGE; + } + + /* Check if there are any events left for us to check */ + if (!((Socket->SharedData.AsyncEvents) & + (~Socket->SharedData.AsyncDisabledEvents))) + { + /* Nothing left, release lock and return */ + LeaveCriticalSection(&Socket->Lock); + goto error; + } + + /* Keep Polling */ + SockProcessAsyncSelect(Socket, AsyncData); + + /* Leave lock and return */ + LeaveCriticalSection(&Socket->Lock); + return; + +error: + /* Dereference the socket and free the Async Data */ + SockDereferenceSocket(Socket); + RtlFreeHeap(SockPrivateHeap, 0, AsyncData); + + /* Dereference this thread and return */ + InterlockedDecrement(&SockAsyncThreadReferenceCount); + return; +} + +VOID +WSPAPI +SockProcessAsyncSelect(PSOCKET_INFORMATION Socket, + PASYNC_DATA AsyncData) +{ + ULONG lNetworkEvents; + NTSTATUS Status; + + /* Set up the Async Data Event Info */ + AsyncData->AsyncSelectInfo.Timeout.HighPart = 0x7FFFFFFF; + AsyncData->AsyncSelectInfo.Timeout.LowPart = 0xFFFFFFFF; + AsyncData->AsyncSelectInfo.HandleCount = 1; + AsyncData->AsyncSelectInfo.Exclusive = TRUE; + AsyncData->AsyncSelectInfo.Handles[0].Handle = (SOCKET)Socket->WshContext.Handle; + AsyncData->AsyncSelectInfo.Handles[0].Events = 0; + + /* Remove unwanted events */ + lNetworkEvents = Socket->SharedData.AsyncEvents & + (~Socket->SharedData.AsyncDisabledEvents); + + /* Set Events to wait for */ + if (lNetworkEvents & FD_READ) + { + AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_RECEIVE; + } + if (lNetworkEvents & FD_WRITE) + { + AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_SEND; + } + if (lNetworkEvents & FD_OOB) + { + AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_OOB_RECEIVE; + } + if (lNetworkEvents & FD_ACCEPT) + { + AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_ACCEPT; + } + if (lNetworkEvents & FD_CLOSE) + { + AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_DISCONNECT | + AFD_EVENT_ABORT | + AFD_EVENT_CLOSE; + } + if (lNetworkEvents & FD_QOS) + { + AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_QOS; + } + if (lNetworkEvents & FD_GROUP_QOS) + { + AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_GROUP_QOS; + } + if (lNetworkEvents & FD_ROUTING_INTERFACE_CHANGE) + { + AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_ROUTING_INTERFACE_CHANGE; + } + if (lNetworkEvents & FD_ADDRESS_LIST_CHANGE) + { + AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_ADDRESS_LIST_CHANGE; + } + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(SockAsyncSelectHelperHandle, + NULL, + NULL, + AsyncData, + &AsyncData->IoStatusBlock, + IOCTL_AFD_SELECT, + &AsyncData->AsyncSelectInfo, + sizeof(AsyncData->AsyncSelectInfo), + &AsyncData->AsyncSelectInfo, + sizeof(AsyncData->AsyncSelectInfo)); + /* Check for failure */ + if (NT_ERROR(Status)) + { + /* I/O Manager Won't call the completion routine; do it manually */ + AsyncData->IoStatusBlock.Status = Status; + SockAsyncSelectCompletion(AsyncData, &AsyncData->IoStatusBlock); + } +} + +VOID +WSPAPI +SockProcessQueuedAsyncSelect(PVOID Context, + PIO_STATUS_BLOCK IoStatusBlock) +{ + PASYNC_DATA AsyncData = Context; + PSOCKET_INFORMATION Socket = AsyncData->ParentSocket; + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* Make sure it's not closed */ + if (Socket->SharedData.State == SocketClosed) + { + /* Return */ + LeaveCriticalSection(&Socket->Lock); + goto error; + } + + /* Check if the Sequence Number changed by now */ + if (AsyncData->SequenceNumber != Socket->SharedData.SequenceNumber) + { + /* Return */ + LeaveCriticalSection(&Socket->Lock); + goto error; + } + + /* Check if select is needed */ + if (!((Socket->SharedData.AsyncEvents & + ~Socket->SharedData.AsyncDisabledEvents))) + { + /* Return */ + LeaveCriticalSection(&Socket->Lock); + goto error; + } + + /* Do the actual select */ + SockProcessAsyncSelect(Socket, AsyncData); + + /* Return */ + LeaveCriticalSection(&Socket->Lock); + return; + +error: + /* Dereference the socket and free the async data */ + SockDereferenceSocket(Socket); + RtlFreeHeap(SockPrivateHeap, 0, AsyncData); + + /* Dereference this thread */ + InterlockedDecrement(&SockAsyncThreadReferenceCount); +} + +INT +WSPAPI +SockReenableAsyncSelectEvent(IN PSOCKET_INFORMATION Socket, + IN ULONG Event) +{ + PASYNC_DATA AsyncData; + NTSTATUS Status; + + /* Make sure the event is actually disabled */ + if (!(Socket->SharedData.AsyncDisabledEvents & Event)) return NO_ERROR; + + /* Make sure we're not closed */ + if (Socket->SharedData.State == SocketClosed) return NO_ERROR; + + /* Re-enable it */ + Socket->SharedData.AsyncDisabledEvents &= ~Event; + + /* Return if no more events are being polled */ + if (!((Socket->SharedData.AsyncEvents & + ~Socket->SharedData.AsyncDisabledEvents))) + { + return NO_ERROR; + } + + /* Allocate Async Data */ + AsyncData = SockAllocateHeapRoutine(SockPrivateHeap, 0, sizeof(ASYNC_DATA)); + + /* Increase the sequence number to stop anything else */ + Socket->SharedData.SequenceNumber++; + + /* Set up the Async Data */ + AsyncData->ParentSocket = Socket; + AsyncData->SequenceNumber = Socket->SharedData.SequenceNumber; + + /* Begin Async Select by using I/O Completion */ + Status = NtSetIoCompletion(SockAsyncQueuePort, + (PVOID)&SockProcessQueuedAsyncSelect, + AsyncData, + 0, + 0); + if (!NT_SUCCESS(Status)) + { + /* Dereference the socket and fail */ + SockDereferenceSocket(Socket); + RtlFreeHeap(SockPrivateHeap, 0, AsyncData); + return NtStatusToSocketError(Status); + } + + /* All done */ + return NO_ERROR; +} + +INT +WSPAPI +SockAsyncSelectHelper(IN PSOCKET_INFORMATION Socket, + IN HWND hWnd, + IN UINT wMsg, + IN LONG lEvent) +{ + PASYNC_DATA AsyncData = NULL; + BOOLEAN BlockMode; + NTSTATUS Status; + INT ErrorCode; + + /* Allocate the Async Data Structure to pass on to the Thread later */ + AsyncData = SockAllocateHeapRoutine(SockPrivateHeap, 0, sizeof(*AsyncData)); + if (!AsyncData) return WSAENOBUFS; + + /* Acquire socket lock */ + EnterCriticalSection(&Socket->Lock); + + /* Is there an active WSPEventSelect? */ + if (Socket->SharedData.AsyncEvents) + { + /* Call the helper to process it */ + ErrorCode = SockEventSelectHelper(Socket, NULL, 0); + if (ErrorCode != NO_ERROR) goto error; + } + + /* Set Socket to Non-Blocking */ + BlockMode = TRUE; + ErrorCode = SockSetInformation(Socket, + AFD_INFO_BLOCKING_MODE, + &BlockMode, + NULL, + NULL); + if (ErrorCode != NO_ERROR) goto error; + + /* AFD was notified, set it locally as well */ + Socket->SharedData.NonBlocking = TRUE; + + /* Store Socket Data */ + Socket->SharedData.hWnd = hWnd; + Socket->SharedData.wMsg = wMsg; + Socket->SharedData.AsyncEvents = lEvent; + Socket->SharedData.AsyncDisabledEvents = 0; + + /* Check if the socket is not connected and not a datagram socket */ + if ((!SockIsSocketConnected(Socket)) && !MSAFD_IS_DGRAM_SOCK(Socket)) + { + /* Disable FD_WRITE for now, so we don't get it before FD_CONNECT */ + Socket->SharedData.AsyncDisabledEvents |= FD_WRITE; + } + + /* Increase the sequence number */ + Socket->SharedData.SequenceNumber++; + + /* Return if there are no more Events */ + if (!(Socket->SharedData.AsyncEvents & + (~Socket->SharedData.AsyncDisabledEvents))) + { + /* Release the lock, dereference the async thread and the socket */ + LeaveCriticalSection(&Socket->Lock); + InterlockedDecrement(&SockAsyncThreadReferenceCount); + SockDereferenceSocket(Socket); + + /* Free the Async Data */ + RtlFreeHeap(SockPrivateHeap, 0, AsyncData); + return NO_ERROR; + } + + /* Set up the Async Data */ + AsyncData->ParentSocket = Socket; + AsyncData->SequenceNumber = Socket->SharedData.SequenceNumber; + + /* Release the lock now */ + LeaveCriticalSection(&Socket->Lock); + + /* Begin Async Select by using I/O Completion */ + Status = NtSetIoCompletion(SockAsyncQueuePort, + (PVOID)&SockProcessQueuedAsyncSelect, + AsyncData, + 0, + 0); + if (!NT_SUCCESS(Status)) + { + /* Dereference the async thread and fail */ + InterlockedDecrement(&SockAsyncThreadReferenceCount); + ErrorCode = NtStatusToSocketError(Status); + } + +error: + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Free the async data */ + RtlFreeHeap(SockPrivateHeap, 0, AsyncData); + + /* Fail */ + return SOCKET_ERROR; + } + + /* Increment the socket reference */ + InterlockedIncrement(&Socket->RefCount); + + /* Return success */ + return NO_ERROR; +} + +INT +WSPAPI +WSPAsyncSelect(IN SOCKET Handle, + IN HWND hWnd, + IN UINT wMsg, + IN LONG lEvent, + OUT LPINT lpErrno) +{ + PSOCKET_INFORMATION Socket; + INT ErrorCode; + PWINSOCK_TEB_DATA ThreadData; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Check for valid events */ + if (lEvent & ~FD_ALL_EVENTS) + { + /* Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Check for valid window handle */ + if (!IsWindow(hWnd)) + { + /* Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Create the Asynch Thread if Needed */ + if (!SockCheckAndReferenceAsyncThread()) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + + /* Open a Handle to AFD's Async Helper */ + if (!SockCheckAndInitAsyncSelectHelper()) + { + /* Dereference async thread and fail */ + InterlockedDecrement(&SockAsyncThreadReferenceCount); + ErrorCode = WSAENOBUFS; + goto error; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Call the helper to do the work */ + ErrorCode = SockAsyncSelectHelper(Socket, + hWnd, + wMsg, + lEvent); + + /* Dereference the socket */ + SockDereferenceSocket(Socket); + +error: + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +INT +WSPAPI +WSPSelect(INT nfds, + PFD_SET readfds, + PFD_SET writefds, + PFD_SET exceptfds, + CONST LPTIMEVAL timeout, + LPINT lpErrno) +{ + IO_STATUS_BLOCK IoStatusBlock; + PAFD_POLL_INFO PollInfo = NULL; + NTSTATUS Status; + CHAR PollBuffer[sizeof(AFD_POLL_INFO) + 3 * sizeof(AFD_HANDLE)]; + PAFD_HANDLE HandleArray; + ULONG HandleCount, OutCount = 0; + ULONG PollBufferSize; + ULONG i; + PWINSOCK_TEB_DATA ThreadData; + LARGE_INTEGER uSec; + ULONG BlockType; + INT ErrorCode; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* How many sockets will we check? */ + HandleCount = HANDLES_IN_SET(readfds) + + HANDLES_IN_SET(writefds) + + HANDLES_IN_SET(exceptfds); + + /* Leave if none are */ + if (!HandleCount) return NO_ERROR; + + /* How much space will they require? */ + PollBufferSize = sizeof(*PollInfo) + (HandleCount * sizeof(AFD_HANDLE)); + + /* Check if our stack is big enough to hold it */ + if (PollBufferSize <= sizeof(PollBuffer)) + { + /* Use the stack */ + PollInfo = (PVOID)PollBuffer; + } + else + { + /* Allocate from heap instead */ + PollInfo = SockAllocateHeapRoutine(SockPrivateHeap, 0, PollBufferSize); + if (!PollInfo) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + } + + /* Number of handles for AFD to Check */ + PollInfo->HandleCount = HandleCount; + PollInfo->Exclusive = FALSE; + HandleArray = PollInfo->Handles; + + /* Select the Read Events */ + for (i = 0; readfds && i < (readfds->fd_count & 0xFFFF); i++) + { + /* Fill out handle info */ + HandleArray->Handle = (SOCKET)readfds->fd_array[i]; + HandleArray->Events = AFD_EVENT_RECEIVE | + AFD_EVENT_DISCONNECT | + AFD_EVENT_ABORT; + + /* Move to the next one */ + HandleArray++; + } + for (i = 0; writefds && i < (writefds->fd_count & 0xFFFF); i++) + { + /* Fill out handle info */ + HandleArray->Handle = (SOCKET)writefds->fd_array[i]; + HandleArray->Events = AFD_EVENT_SEND; + + /* Move to the next one */ + HandleArray++; + } + for (i = 0; exceptfds && i < (exceptfds->fd_count & 0xFFFF); i++) + { + /* Fill out handle info */ + HandleArray->Handle = (SOCKET)exceptfds->fd_array[i]; + HandleArray->Events = AFD_EVENT_OOB_RECEIVE | AFD_EVENT_CONNECT_FAIL; + + /* Move to the next one */ + HandleArray++; + } + + /* Check if a timeout was given */ + if (timeout) + { + /* Inifinte Timeout */ + PollInfo->Timeout.u.LowPart = -1; + PollInfo->Timeout.u.HighPart = 0x7FFFFFFF; + } + else + { + /* Calculate microseconds */ + uSec = RtlEnlargedIntegerMultiply(timeout->tv_usec, -10); + + /* Calculate seconds */ + PollInfo->Timeout = RtlEnlargedIntegerMultiply(timeout->tv_sec, + -1 * 1000 * 1000 * 10); + + /* Add microseconds */ + PollInfo->Timeout.QuadPart += uSec.QuadPart; + } + + /* Send IOCTL */ + Status = NtDeviceIoControlFile((HANDLE)PollInfo->Handles[0].Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_SELECT, + PollInfo, + PollBufferSize, + PollInfo, + PollBufferSize); + + /* Check if we have to wait */ + if (Status == STATUS_PENDING) + { + /* Check if we'll call the blocking hook */ + if (!PollInfo->Timeout.QuadPart) BlockType = NO_BLOCKING_HOOK; + + /* Wait for completion */ + SockWaitForSingleObject(ThreadData->EventHandle, + (SOCKET)PollInfo->Handles[0].Handle, + BlockType, + NO_TIMEOUT); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for failure */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* Clear the Structures */ + if(readfds) FD_ZERO(readfds); + if(writefds) FD_ZERO(writefds); + if(exceptfds) FD_ZERO(exceptfds); + + /* Get the handle info again */ + HandleCount = PollInfo->HandleCount; + HandleArray = PollInfo->Handles; + + /* Loop the Handles that got an event */ + for (i = 0; i < HandleCount; i++) + { + /* Check for a match */ + if (HandleArray->Events & AFD_EVENT_RECEIVE) + { + /* Check if it's not already set */ + if (!FD_ISSET((SOCKET)HandleArray->Handle, readfds)) + { + /* Increase Handles with an Event */ + OutCount++; + + /* Set this handle */ + FD_SET((SOCKET)HandleArray->Handle, readfds); + } + } + /* Check for a match */ + if (HandleArray->Events & AFD_EVENT_SEND) + { + /* Check if it's not already set */ + if (!FD_ISSET((SOCKET)HandleArray->Handle, writefds)) + { + /* Increase Handles with an Event */ + OutCount++; + + /* Set this handle */ + FD_SET((SOCKET)HandleArray->Handle, writefds); + } + } + /* Check for a match */ + if (HandleArray->Events & AFD_EVENT_OOB_RECEIVE) + { + /* Check if it's not already set */ + if (!FD_ISSET((SOCKET)HandleArray->Handle, exceptfds)) + { + /* Increase Handles with an Event */ + OutCount++; + + /* Set this handle */ + FD_SET((SOCKET)HandleArray->Handle, exceptfds); + } + } + /* Check for a match */ + if (HandleArray->Events & AFD_EVENT_ACCEPT) + { + /* Check if it's not already set */ + if (!FD_ISSET((SOCKET)HandleArray->Handle, readfds)) + { + /* Increase Handles with an Event */ + OutCount++; + + /* Set this handle */ + FD_SET((SOCKET)HandleArray->Handle, readfds); + } + } + /* Check for a match */ + if (HandleArray->Events & AFD_EVENT_CONNECT) + { + /* Check if it's not already set */ + if (!FD_ISSET((SOCKET)HandleArray->Handle, writefds)) + { + /* Increase Handles with an Event */ + OutCount++; + + /* Set this handle */ + FD_SET((SOCKET)HandleArray->Handle, writefds); + } + } + /* Check for a match */ + if (HandleArray->Events & AFD_EVENT_CONNECT_FAIL) + { + /* Check if it's not already set */ + if (!FD_ISSET((SOCKET)HandleArray->Handle, exceptfds)) + { + /* Increase Handles with an Event */ + OutCount++; + + /* Set this handle */ + FD_SET((SOCKET)HandleArray->Handle, exceptfds); + } + } + /* Check for a match */ + if (HandleArray->Events & AFD_EVENT_DISCONNECT) + { + /* Check if it's not already set */ + if (!FD_ISSET((SOCKET)HandleArray->Handle, readfds)) + { + /* Increase Handles with an Event */ + OutCount++; + + /* Set this handle */ + FD_SET((SOCKET)HandleArray->Handle, readfds); + } + } + /* Check for a match */ + if (HandleArray->Events & AFD_EVENT_ABORT) + { + /* Check if it's not already set */ + if (!FD_ISSET((SOCKET)HandleArray->Handle, readfds)) + { + /* Increase Handles with an Event */ + OutCount++; + + /* Set this handle */ + FD_SET((SOCKET)HandleArray->Handle, readfds); + } + } + /* Check for a match */ + if (HandleArray->Events & AFD_EVENT_CLOSE) + { + /* Check if it's not already set */ + if (!FD_ISSET((SOCKET)HandleArray->Handle, readfds)) + { + /* Increase Handles with an Event */ + OutCount++; + + /* Set this handle */ + FD_SET((SOCKET)HandleArray->Handle, readfds); + } + } + + /* Move to next entry */ + HandleArray++; + } + +error: + + /* Check if we should free the buffer */ + if (PollInfo && (PollInfo != (PVOID)PollBuffer)) + { + /* Free it from the heap */ + RtlFreeHeap(SockPrivateHeap, 0, PollInfo); + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Return error */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return the number of handles */ + return OutCount; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +#define MSAFD_CHECK_EVENT(e, s) \ + (!(s->SharedData.AsyncDisabledEvents & e) && \ + (s->SharedData.AsyncEvents & e)) + +#define HANDLES_IN_SET(s) \ + s == NULL ? 0 : (s->fd_count & 0xFFFF) + +/* DATA **********************************************************************/ + +HANDLE SockAsyncSelectHelperHandle; +BOOLEAN SockAsyncSelectCalled; + +/* FUNCTIONS *****************************************************************/ + +BOOLEAN +WSPAPI +SockCheckAndInitAsyncSelectHelper(VOID) +{ + UNICODE_STRING AfdHelper; + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + FILE_COMPLETION_INFORMATION CompletionInfo; + OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags; + + /* First, make sure we're not already intialized */ + if (SockAsyncSelectHelperHandle) return TRUE; + + /* Acquire the global lock */ + SockAcquireRwLockExclusive(&SocketGlobalLock); + + /* Check again, under the lock */ + if (SockAsyncSelectHelperHandle) + { + /* Return without lock */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + return TRUE; + } + + /* Set up Handle Name and Object */ + RtlInitUnicodeString(&AfdHelper, L"\\Device\\Afd\\AsyncSelectHlp" ); + InitializeObjectAttributes(&ObjectAttributes, + &AfdHelper, + OBJ_INHERIT | OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + /* Open the Handle to AFD */ + Status = NtCreateFile(&SockAsyncSelectHelperHandle, + GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, + &ObjectAttributes, + &IoStatusBlock, + NULL, + 0, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_OPEN_IF, + 0, + NULL, + 0); + if (!NT_SUCCESS(Status)) + { + /* Return without lock */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + return TRUE; + } + + /* Check if the port exists, and if not, create it */ + if (SockAsyncQueuePort) SockCreateAsyncQueuePort(); + + /* + * Now Set up the Completion Port Information + * This means that whenever a Poll is finished, the routine will be executed + */ + CompletionInfo.Port = SockAsyncQueuePort; + CompletionInfo.Key = SockAsyncSelectCompletion; + Status = NtSetInformationFile(SockAsyncSelectHelperHandle, + &IoStatusBlock, + &CompletionInfo, + sizeof(CompletionInfo), + FileCompletionInformation); + + /* Protect the Handle */ + HandleFlags.ProtectFromClose = TRUE; + HandleFlags.Inherit = FALSE; + Status = NtSetInformationObject(SockAsyncQueuePort, + ObjectHandleFlagInformation, + &HandleFlags, + sizeof(HandleFlags)); + + /* + * Set this variable to true so that Send/Recv/Accept will know whether + * to renable disabled events + */ + SockAsyncSelectCalled = TRUE; + + /* Release lock and return */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + return TRUE; +} + +VOID +WSPAPI +SockAsyncSelectCompletion(PVOID Context, + PIO_STATUS_BLOCK IoStatusBlock) +{ + PASYNC_DATA AsyncData = Context; + PSOCKET_INFORMATION Socket = AsyncData->ParentSocket; + ULONG Events; + INT ErrorCode; + + /* Acquire the socket lock */ + EnterCriticalSection(&Socket->Lock); + + /* Check if the socket was closed or the I/O cancelled */ + if ((Socket->SharedData.State == SocketClosed) || + (IoStatusBlock->Status == STATUS_CANCELLED)) + { + /* Return */ + LeaveCriticalSection(&Socket->Lock); + goto error; + } + + /* Check if the Sequence Number Changed behind our back */ + if (AsyncData->SequenceNumber != Socket->SharedData.SequenceNumber) + { + /* Return */ + LeaveCriticalSection(&Socket->Lock); + goto error; + } + + /* Check we were manually called b/c of a failure */ + if (!NT_SUCCESS(IoStatusBlock->Status)) + { + /* Get the error and tell WPU about it */ + ErrorCode = NtStatusToSocketError(IoStatusBlock->Status); + SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, + Socket->SharedData.wMsg, + Socket->Handle, + WSAMAKESELECTREPLY(0, ErrorCode)); + + /* Return */ + LeaveCriticalSection(&Socket->Lock); + goto error; + } + + /* Select the event bits */ + Events = AsyncData->AsyncSelectInfo.Handles[0].Events; + + /* Check for receive event */ + if (MSAFD_CHECK_EVENT(FD_READ, Socket) && (Events & AFD_EVENT_RECEIVE)) + { + /* Make the Notifcation */ + SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, + Socket->SharedData.wMsg, + Socket->Handle, + WSAMAKESELECTREPLY(FD_READ, 0)); + + /* Disable this event until the next read(); */ + Socket->SharedData.AsyncDisabledEvents |= FD_READ; + } + + /* Check for oob receive event */ + if (MSAFD_CHECK_EVENT(FD_OOB, Socket) && (Events & AFD_EVENT_OOB_RECEIVE)) + { + /* Make the Notifcation */ + SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, + Socket->SharedData.wMsg, + Socket->Handle, + WSAMAKESELECTREPLY(FD_OOB, 0)); + + /* Disable this event until the next read(); */ + Socket->SharedData.AsyncDisabledEvents |= FD_OOB; + } + + /* Check for write event */ + if (MSAFD_CHECK_EVENT(FD_WRITE, Socket) && (Events & AFD_EVENT_SEND)) + { + /* Make the Notifcation */ + SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, + Socket->SharedData.wMsg, + Socket->Handle, + WSAMAKESELECTREPLY(FD_WRITE, 0)); + + /* Disable this event until the next read(); */ + Socket->SharedData.AsyncDisabledEvents |= FD_WRITE; + } + + /* Check for accept event */ + if (MSAFD_CHECK_EVENT(FD_ACCEPT, Socket) && (Events & AFD_EVENT_ACCEPT)) + { + /* Make the Notifcation */ + SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, + Socket->SharedData.wMsg, + Socket->Handle, + WSAMAKESELECTREPLY(FD_ACCEPT, 0)); + + /* Disable this event until the next read(); */ + Socket->SharedData.AsyncDisabledEvents |= FD_ACCEPT; + } + + /* Check for close events */ + if (MSAFD_CHECK_EVENT(FD_CLOSE, Socket) && ((Events & AFD_EVENT_ACCEPT) || + (Events & AFD_EVENT_ABORT) || + (Events & AFD_EVENT_CLOSE))) + { + /* Make the Notifcation */ + SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, + Socket->SharedData.wMsg, + Socket->Handle, + WSAMAKESELECTREPLY(FD_CLOSE, 0)); + + /* Disable this event until the next read(); */ + Socket->SharedData.AsyncDisabledEvents |= FD_CLOSE; + } + + /* Check for QOS event */ + if (MSAFD_CHECK_EVENT(FD_QOS, Socket) && (Events & AFD_EVENT_QOS)) + { + /* Make the Notifcation */ + SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, + Socket->SharedData.wMsg, + Socket->Handle, + WSAMAKESELECTREPLY(FD_QOS, 0)); + + /* Disable this event until the next read(); */ + Socket->SharedData.AsyncDisabledEvents |= FD_QOS; + } + + /* Check for Group QOS event */ + if (MSAFD_CHECK_EVENT(FD_GROUP_QOS, Socket) && (Events & AFD_EVENT_GROUP_QOS)) + { + /* Make the Notifcation */ + SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, + Socket->SharedData.wMsg, + Socket->Handle, + WSAMAKESELECTREPLY(FD_GROUP_QOS, 0)); + + /* Disable this event until the next read(); */ + Socket->SharedData.AsyncDisabledEvents |= FD_GROUP_QOS; + } + + /* Check for Routing Interface Change event */ + if (MSAFD_CHECK_EVENT(FD_ROUTING_INTERFACE_CHANGE, Socket) && + (Events & AFD_EVENT_ROUTING_INTERFACE_CHANGE)) + { + /* Make the Notifcation */ + SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, + Socket->SharedData.wMsg, + Socket->Handle, + WSAMAKESELECTREPLY(FD_ROUTING_INTERFACE_CHANGE, 0)); + + /* Disable this event until the next read(); */ + Socket->SharedData.AsyncDisabledEvents |= FD_ROUTING_INTERFACE_CHANGE; + } + + /* Check for Address List Change event */ + if (MSAFD_CHECK_EVENT(FD_ADDRESS_LIST_CHANGE, Socket) && + (Events & AFD_EVENT_ADDRESS_LIST_CHANGE)) + { + /* Make the Notifcation */ + SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, + Socket->SharedData.wMsg, + Socket->Handle, + WSAMAKESELECTREPLY(FD_ADDRESS_LIST_CHANGE, 0)); + + /* Disable this event until the next read(); */ + Socket->SharedData.AsyncDisabledEvents |= FD_ADDRESS_LIST_CHANGE; + } + + /* Check if there are any events left for us to check */ + if (!((Socket->SharedData.AsyncEvents) & + (~Socket->SharedData.AsyncDisabledEvents))) + { + /* Nothing left, release lock and return */ + LeaveCriticalSection(&Socket->Lock); + goto error; + } + + /* Keep Polling */ + SockProcessAsyncSelect(Socket, AsyncData); + + /* Leave lock and return */ + LeaveCriticalSection(&Socket->Lock); + return; + +error: + /* Dereference the socket and free the Async Data */ + SockDereferenceSocket(Socket); + RtlFreeHeap(SockPrivateHeap, 0, AsyncData); + + /* Dereference this thread and return */ + InterlockedDecrement(&SockAsyncThreadReferenceCount); + return; +} + +VOID +WSPAPI +SockProcessAsyncSelect(PSOCKET_INFORMATION Socket, + PASYNC_DATA AsyncData) +{ + ULONG lNetworkEvents; + NTSTATUS Status; + + /* Set up the Async Data Event Info */ + AsyncData->AsyncSelectInfo.Timeout.HighPart = 0x7FFFFFFF; + AsyncData->AsyncSelectInfo.Timeout.LowPart = 0xFFFFFFFF; + AsyncData->AsyncSelectInfo.HandleCount = 1; + AsyncData->AsyncSelectInfo.Exclusive = TRUE; + AsyncData->AsyncSelectInfo.Handles[0].Handle = (SOCKET)Socket->WshContext.Handle; + AsyncData->AsyncSelectInfo.Handles[0].Events = 0; + + /* Remove unwanted events */ + lNetworkEvents = Socket->SharedData.AsyncEvents & + (~Socket->SharedData.AsyncDisabledEvents); + + /* Set Events to wait for */ + if (lNetworkEvents & FD_READ) + { + AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_RECEIVE; + } + if (lNetworkEvents & FD_WRITE) + { + AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_SEND; + } + if (lNetworkEvents & FD_OOB) + { + AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_OOB_RECEIVE; + } + if (lNetworkEvents & FD_ACCEPT) + { + AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_ACCEPT; + } + if (lNetworkEvents & FD_CLOSE) + { + AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_DISCONNECT | + AFD_EVENT_ABORT | + AFD_EVENT_CLOSE; + } + if (lNetworkEvents & FD_QOS) + { + AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_QOS; + } + if (lNetworkEvents & FD_GROUP_QOS) + { + AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_GROUP_QOS; + } + if (lNetworkEvents & FD_ROUTING_INTERFACE_CHANGE) + { + AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_ROUTING_INTERFACE_CHANGE; + } + if (lNetworkEvents & FD_ADDRESS_LIST_CHANGE) + { + AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_ADDRESS_LIST_CHANGE; + } + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(SockAsyncSelectHelperHandle, + NULL, + NULL, + AsyncData, + &AsyncData->IoStatusBlock, + IOCTL_AFD_SELECT, + &AsyncData->AsyncSelectInfo, + sizeof(AsyncData->AsyncSelectInfo), + &AsyncData->AsyncSelectInfo, + sizeof(AsyncData->AsyncSelectInfo)); + /* Check for failure */ + if (NT_ERROR(Status)) + { + /* I/O Manager Won't call the completion routine; do it manually */ + AsyncData->IoStatusBlock.Status = Status; + SockAsyncSelectCompletion(AsyncData, &AsyncData->IoStatusBlock); + } +} + +VOID +WSPAPI +SockProcessQueuedAsyncSelect(PVOID Context, + PIO_STATUS_BLOCK IoStatusBlock) +{ + PASYNC_DATA AsyncData = Context; + PSOCKET_INFORMATION Socket = AsyncData->ParentSocket; + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* Make sure it's not closed */ + if (Socket->SharedData.State == SocketClosed) + { + /* Return */ + LeaveCriticalSection(&Socket->Lock); + goto error; + } + + /* Check if the Sequence Number changed by now */ + if (AsyncData->SequenceNumber != Socket->SharedData.SequenceNumber) + { + /* Return */ + LeaveCriticalSection(&Socket->Lock); + goto error; + } + + /* Check if select is needed */ + if (!((Socket->SharedData.AsyncEvents & + ~Socket->SharedData.AsyncDisabledEvents))) + { + /* Return */ + LeaveCriticalSection(&Socket->Lock); + goto error; + } + + /* Do the actual select */ + SockProcessAsyncSelect(Socket, AsyncData); + + /* Return */ + LeaveCriticalSection(&Socket->Lock); + return; + +error: + /* Dereference the socket and free the async data */ + SockDereferenceSocket(Socket); + RtlFreeHeap(SockPrivateHeap, 0, AsyncData); + + /* Dereference this thread */ + InterlockedDecrement(&SockAsyncThreadReferenceCount); +} + +INT +WSPAPI +SockReenableAsyncSelectEvent(IN PSOCKET_INFORMATION Socket, + IN ULONG Event) +{ + PASYNC_DATA AsyncData; + NTSTATUS Status; + + /* Make sure the event is actually disabled */ + if (!(Socket->SharedData.AsyncDisabledEvents & Event)) return NO_ERROR; + + /* Make sure we're not closed */ + if (Socket->SharedData.State == SocketClosed) return NO_ERROR; + + /* Re-enable it */ + Socket->SharedData.AsyncDisabledEvents &= ~Event; + + /* Return if no more events are being polled */ + if (!((Socket->SharedData.AsyncEvents & + ~Socket->SharedData.AsyncDisabledEvents))) + { + return NO_ERROR; + } + + /* Allocate Async Data */ + AsyncData = SockAllocateHeapRoutine(SockPrivateHeap, 0, sizeof(ASYNC_DATA)); + + /* Increase the sequence number to stop anything else */ + Socket->SharedData.SequenceNumber++; + + /* Set up the Async Data */ + AsyncData->ParentSocket = Socket; + AsyncData->SequenceNumber = Socket->SharedData.SequenceNumber; + + /* Begin Async Select by using I/O Completion */ + Status = NtSetIoCompletion(SockAsyncQueuePort, + (PVOID)&SockProcessQueuedAsyncSelect, + AsyncData, + 0, + 0); + if (!NT_SUCCESS(Status)) + { + /* Dereference the socket and fail */ + SockDereferenceSocket(Socket); + RtlFreeHeap(SockPrivateHeap, 0, AsyncData); + return NtStatusToSocketError(Status); + } + + /* All done */ + return NO_ERROR; +} + +INT +WSPAPI +SockAsyncSelectHelper(IN PSOCKET_INFORMATION Socket, + IN HWND hWnd, + IN UINT wMsg, + IN LONG lEvent) +{ + PASYNC_DATA AsyncData = NULL; + BOOLEAN BlockMode; + NTSTATUS Status; + INT ErrorCode; + + /* Allocate the Async Data Structure to pass on to the Thread later */ + AsyncData = SockAllocateHeapRoutine(SockPrivateHeap, 0, sizeof(*AsyncData)); + if (!AsyncData) return WSAENOBUFS; + + /* Acquire socket lock */ + EnterCriticalSection(&Socket->Lock); + + /* Is there an active WSPEventSelect? */ + if (Socket->SharedData.AsyncEvents) + { + /* Call the helper to process it */ + ErrorCode = SockEventSelectHelper(Socket, NULL, 0); + if (ErrorCode != NO_ERROR) goto error; + } + + /* Set Socket to Non-Blocking */ + BlockMode = TRUE; + ErrorCode = SockSetInformation(Socket, + AFD_INFO_BLOCKING_MODE, + &BlockMode, + NULL, + NULL); + if (ErrorCode != NO_ERROR) goto error; + + /* AFD was notified, set it locally as well */ + Socket->SharedData.NonBlocking = TRUE; + + /* Store Socket Data */ + Socket->SharedData.hWnd = hWnd; + Socket->SharedData.wMsg = wMsg; + Socket->SharedData.AsyncEvents = lEvent; + Socket->SharedData.AsyncDisabledEvents = 0; + + /* Check if the socket is not connected and not a datagram socket */ + if ((!SockIsSocketConnected(Socket)) && !MSAFD_IS_DGRAM_SOCK(Socket)) + { + /* Disable FD_WRITE for now, so we don't get it before FD_CONNECT */ + Socket->SharedData.AsyncDisabledEvents |= FD_WRITE; + } + + /* Increase the sequence number */ + Socket->SharedData.SequenceNumber++; + + /* Return if there are no more Events */ + if (!(Socket->SharedData.AsyncEvents & + (~Socket->SharedData.AsyncDisabledEvents))) + { + /* Release the lock, dereference the async thread and the socket */ + LeaveCriticalSection(&Socket->Lock); + InterlockedDecrement(&SockAsyncThreadReferenceCount); + SockDereferenceSocket(Socket); + + /* Free the Async Data */ + RtlFreeHeap(SockPrivateHeap, 0, AsyncData); + return NO_ERROR; + } + + /* Set up the Async Data */ + AsyncData->ParentSocket = Socket; + AsyncData->SequenceNumber = Socket->SharedData.SequenceNumber; + + /* Release the lock now */ + LeaveCriticalSection(&Socket->Lock); + + /* Begin Async Select by using I/O Completion */ + Status = NtSetIoCompletion(SockAsyncQueuePort, + (PVOID)&SockProcessQueuedAsyncSelect, + AsyncData, + 0, + 0); + if (!NT_SUCCESS(Status)) + { + /* Dereference the async thread and fail */ + InterlockedDecrement(&SockAsyncThreadReferenceCount); + ErrorCode = NtStatusToSocketError(Status); + } + +error: + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Free the async data */ + RtlFreeHeap(SockPrivateHeap, 0, AsyncData); + + /* Fail */ + return SOCKET_ERROR; + } + + /* Increment the socket reference */ + InterlockedIncrement(&Socket->RefCount); + + /* Return success */ + return NO_ERROR; +} + +INT +WSPAPI +WSPAsyncSelect(IN SOCKET Handle, + IN HWND hWnd, + IN UINT wMsg, + IN LONG lEvent, + OUT LPINT lpErrno) +{ + PSOCKET_INFORMATION Socket; + INT ErrorCode; + PWINSOCK_TEB_DATA ThreadData; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Check for valid events */ + if (lEvent & ~FD_ALL_EVENTS) + { + /* Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Check for valid window handle */ + if (!IsWindow(hWnd)) + { + /* Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Create the Asynch Thread if Needed */ + if (!SockCheckAndReferenceAsyncThread()) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + + /* Open a Handle to AFD's Async Helper */ + if (!SockCheckAndInitAsyncSelectHelper()) + { + /* Dereference async thread and fail */ + InterlockedDecrement(&SockAsyncThreadReferenceCount); + ErrorCode = WSAENOBUFS; + goto error; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Call the helper to do the work */ + ErrorCode = SockAsyncSelectHelper(Socket, + hWnd, + wMsg, + lEvent); + + /* Dereference the socket */ + SockDereferenceSocket(Socket); + +error: + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +INT +WSPAPI +WSPSelect(INT nfds, + PFD_SET readfds, + PFD_SET writefds, + PFD_SET exceptfds, + CONST LPTIMEVAL timeout, + LPINT lpErrno) +{ + IO_STATUS_BLOCK IoStatusBlock; + PAFD_POLL_INFO PollInfo = NULL; + NTSTATUS Status; + CHAR PollBuffer[sizeof(AFD_POLL_INFO) + 3 * sizeof(AFD_HANDLE)]; + PAFD_HANDLE HandleArray; + ULONG HandleCount, OutCount = 0; + ULONG PollBufferSize; + ULONG i; + PWINSOCK_TEB_DATA ThreadData; + LARGE_INTEGER uSec; + ULONG BlockType; + INT ErrorCode; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* How many sockets will we check? */ + HandleCount = HANDLES_IN_SET(readfds) + + HANDLES_IN_SET(writefds) + + HANDLES_IN_SET(exceptfds); + + /* Leave if none are */ + if (!HandleCount) return NO_ERROR; + + /* How much space will they require? */ + PollBufferSize = sizeof(*PollInfo) + (HandleCount * sizeof(AFD_HANDLE)); + + /* Check if our stack is big enough to hold it */ + if (PollBufferSize <= sizeof(PollBuffer)) + { + /* Use the stack */ + PollInfo = (PVOID)PollBuffer; + } + else + { + /* Allocate from heap instead */ + PollInfo = SockAllocateHeapRoutine(SockPrivateHeap, 0, PollBufferSize); + if (!PollInfo) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + } + + /* Number of handles for AFD to Check */ + PollInfo->HandleCount = HandleCount; + PollInfo->Exclusive = FALSE; + HandleArray = PollInfo->Handles; + + /* Select the Read Events */ + for (i = 0; readfds && i < (readfds->fd_count & 0xFFFF); i++) + { + /* Fill out handle info */ + HandleArray->Handle = (SOCKET)readfds->fd_array[i]; + HandleArray->Events = AFD_EVENT_RECEIVE | + AFD_EVENT_DISCONNECT | + AFD_EVENT_ABORT; + + /* Move to the next one */ + HandleArray++; + } + for (i = 0; writefds && i < (writefds->fd_count & 0xFFFF); i++) + { + /* Fill out handle info */ + HandleArray->Handle = (SOCKET)writefds->fd_array[i]; + HandleArray->Events = AFD_EVENT_SEND; + + /* Move to the next one */ + HandleArray++; + } + for (i = 0; exceptfds && i < (exceptfds->fd_count & 0xFFFF); i++) + { + /* Fill out handle info */ + HandleArray->Handle = (SOCKET)exceptfds->fd_array[i]; + HandleArray->Events = AFD_EVENT_OOB_RECEIVE | AFD_EVENT_CONNECT_FAIL; + + /* Move to the next one */ + HandleArray++; + } + + /* Check if a timeout was given */ + if (timeout) + { + /* Inifinte Timeout */ + PollInfo->Timeout.u.LowPart = -1; + PollInfo->Timeout.u.HighPart = 0x7FFFFFFF; + } + else + { + /* Calculate microseconds */ + uSec = RtlEnlargedIntegerMultiply(timeout->tv_usec, -10); + + /* Calculate seconds */ + PollInfo->Timeout = RtlEnlargedIntegerMultiply(timeout->tv_sec, + -1 * 1000 * 1000 * 10); + + /* Add microseconds */ + PollInfo->Timeout.QuadPart += uSec.QuadPart; + } + + /* Send IOCTL */ + Status = NtDeviceIoControlFile((HANDLE)PollInfo->Handles[0].Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_SELECT, + PollInfo, + PollBufferSize, + PollInfo, + PollBufferSize); + + /* Check if we have to wait */ + if (Status == STATUS_PENDING) + { + /* Check if we'll call the blocking hook */ + if (!PollInfo->Timeout.QuadPart) BlockType = NO_BLOCKING_HOOK; + + /* Wait for completion */ + SockWaitForSingleObject(ThreadData->EventHandle, + (SOCKET)PollInfo->Handles[0].Handle, + BlockType, + NO_TIMEOUT); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for failure */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* Clear the Structures */ + if(readfds) FD_ZERO(readfds); + if(writefds) FD_ZERO(writefds); + if(exceptfds) FD_ZERO(exceptfds); + + /* Get the handle info again */ + HandleCount = PollInfo->HandleCount; + HandleArray = PollInfo->Handles; + + /* Loop the Handles that got an event */ + for (i = 0; i < HandleCount; i++) + { + /* Check for a match */ + if (HandleArray->Events & AFD_EVENT_RECEIVE) + { + /* Check if it's not already set */ + if (!FD_ISSET((SOCKET)HandleArray->Handle, readfds)) + { + /* Increase Handles with an Event */ + OutCount++; + + /* Set this handle */ + FD_SET((SOCKET)HandleArray->Handle, readfds); + } + } + /* Check for a match */ + if (HandleArray->Events & AFD_EVENT_SEND) + { + /* Check if it's not already set */ + if (!FD_ISSET((SOCKET)HandleArray->Handle, writefds)) + { + /* Increase Handles with an Event */ + OutCount++; + + /* Set this handle */ + FD_SET((SOCKET)HandleArray->Handle, writefds); + } + } + /* Check for a match */ + if (HandleArray->Events & AFD_EVENT_OOB_RECEIVE) + { + /* Check if it's not already set */ + if (!FD_ISSET((SOCKET)HandleArray->Handle, exceptfds)) + { + /* Increase Handles with an Event */ + OutCount++; + + /* Set this handle */ + FD_SET((SOCKET)HandleArray->Handle, exceptfds); + } + } + /* Check for a match */ + if (HandleArray->Events & AFD_EVENT_ACCEPT) + { + /* Check if it's not already set */ + if (!FD_ISSET((SOCKET)HandleArray->Handle, readfds)) + { + /* Increase Handles with an Event */ + OutCount++; + + /* Set this handle */ + FD_SET((SOCKET)HandleArray->Handle, readfds); + } + } + /* Check for a match */ + if (HandleArray->Events & AFD_EVENT_CONNECT) + { + /* Check if it's not already set */ + if (!FD_ISSET((SOCKET)HandleArray->Handle, writefds)) + { + /* Increase Handles with an Event */ + OutCount++; + + /* Set this handle */ + FD_SET((SOCKET)HandleArray->Handle, writefds); + } + } + /* Check for a match */ + if (HandleArray->Events & AFD_EVENT_CONNECT_FAIL) + { + /* Check if it's not already set */ + if (!FD_ISSET((SOCKET)HandleArray->Handle, exceptfds)) + { + /* Increase Handles with an Event */ + OutCount++; + + /* Set this handle */ + FD_SET((SOCKET)HandleArray->Handle, exceptfds); + } + } + /* Check for a match */ + if (HandleArray->Events & AFD_EVENT_DISCONNECT) + { + /* Check if it's not already set */ + if (!FD_ISSET((SOCKET)HandleArray->Handle, readfds)) + { + /* Increase Handles with an Event */ + OutCount++; + + /* Set this handle */ + FD_SET((SOCKET)HandleArray->Handle, readfds); + } + } + /* Check for a match */ + if (HandleArray->Events & AFD_EVENT_ABORT) + { + /* Check if it's not already set */ + if (!FD_ISSET((SOCKET)HandleArray->Handle, readfds)) + { + /* Increase Handles with an Event */ + OutCount++; + + /* Set this handle */ + FD_SET((SOCKET)HandleArray->Handle, readfds); + } + } + /* Check for a match */ + if (HandleArray->Events & AFD_EVENT_CLOSE) + { + /* Check if it's not already set */ + if (!FD_ISSET((SOCKET)HandleArray->Handle, readfds)) + { + /* Increase Handles with an Event */ + OutCount++; + + /* Set this handle */ + FD_SET((SOCKET)HandleArray->Handle, readfds); + } + } + + /* Move to next entry */ + HandleArray++; + } + +error: + + /* Check if we should free the buffer */ + if (PollInfo && (PollInfo != (PVOID)PollBuffer)) + { + /* Free it from the heap */ + RtlFreeHeap(SockPrivateHeap, 0, PollInfo); + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Return error */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return the number of handles */ + return OutCount; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +#define MSAFD_CHECK_EVENT(e, s) \ + (!(s->SharedData.AsyncDisabledEvents & e) && \ + (s->SharedData.AsyncEvents & e)) + +#define HANDLES_IN_SET(s) \ + s == NULL ? 0 : (s->fd_count & 0xFFFF) + +/* DATA **********************************************************************/ + +HANDLE SockAsyncSelectHelperHandle; +BOOLEAN SockAsyncSelectCalled; + +/* FUNCTIONS *****************************************************************/ + +BOOLEAN +WSPAPI +SockCheckAndInitAsyncSelectHelper(VOID) +{ + UNICODE_STRING AfdHelper; + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + FILE_COMPLETION_INFORMATION CompletionInfo; + OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags; + + /* First, make sure we're not already intialized */ + if (SockAsyncSelectHelperHandle) return TRUE; + + /* Acquire the global lock */ + SockAcquireRwLockExclusive(&SocketGlobalLock); + + /* Check again, under the lock */ + if (SockAsyncSelectHelperHandle) + { + /* Return without lock */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + return TRUE; + } + + /* Set up Handle Name and Object */ + RtlInitUnicodeString(&AfdHelper, L"\\Device\\Afd\\AsyncSelectHlp" ); + InitializeObjectAttributes(&ObjectAttributes, + &AfdHelper, + OBJ_INHERIT | OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + /* Open the Handle to AFD */ + Status = NtCreateFile(&SockAsyncSelectHelperHandle, + GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, + &ObjectAttributes, + &IoStatusBlock, + NULL, + 0, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_OPEN_IF, + 0, + NULL, + 0); + if (!NT_SUCCESS(Status)) + { + /* Return without lock */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + return TRUE; + } + + /* Check if the port exists, and if not, create it */ + if (SockAsyncQueuePort) SockCreateAsyncQueuePort(); + + /* + * Now Set up the Completion Port Information + * This means that whenever a Poll is finished, the routine will be executed + */ + CompletionInfo.Port = SockAsyncQueuePort; + CompletionInfo.Key = SockAsyncSelectCompletion; + Status = NtSetInformationFile(SockAsyncSelectHelperHandle, + &IoStatusBlock, + &CompletionInfo, + sizeof(CompletionInfo), + FileCompletionInformation); + + /* Protect the Handle */ + HandleFlags.ProtectFromClose = TRUE; + HandleFlags.Inherit = FALSE; + Status = NtSetInformationObject(SockAsyncQueuePort, + ObjectHandleFlagInformation, + &HandleFlags, + sizeof(HandleFlags)); + + /* + * Set this variable to true so that Send/Recv/Accept will know whether + * to renable disabled events + */ + SockAsyncSelectCalled = TRUE; + + /* Release lock and return */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + return TRUE; +} + +VOID +WSPAPI +SockAsyncSelectCompletion(PVOID Context, + PIO_STATUS_BLOCK IoStatusBlock) +{ + PASYNC_DATA AsyncData = Context; + PSOCKET_INFORMATION Socket = AsyncData->ParentSocket; + ULONG Events; + INT ErrorCode; + + /* Acquire the socket lock */ + EnterCriticalSection(&Socket->Lock); + + /* Check if the socket was closed or the I/O cancelled */ + if ((Socket->SharedData.State == SocketClosed) || + (IoStatusBlock->Status == STATUS_CANCELLED)) + { + /* Return */ + LeaveCriticalSection(&Socket->Lock); + goto error; + } + + /* Check if the Sequence Number Changed behind our back */ + if (AsyncData->SequenceNumber != Socket->SharedData.SequenceNumber) + { + /* Return */ + LeaveCriticalSection(&Socket->Lock); + goto error; + } + + /* Check we were manually called b/c of a failure */ + if (!NT_SUCCESS(IoStatusBlock->Status)) + { + /* Get the error and tell WPU about it */ + ErrorCode = NtStatusToSocketError(IoStatusBlock->Status); + SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, + Socket->SharedData.wMsg, + Socket->Handle, + WSAMAKESELECTREPLY(0, ErrorCode)); + + /* Return */ + LeaveCriticalSection(&Socket->Lock); + goto error; + } + + /* Select the event bits */ + Events = AsyncData->AsyncSelectInfo.Handles[0].Events; + + /* Check for receive event */ + if (MSAFD_CHECK_EVENT(FD_READ, Socket) && (Events & AFD_EVENT_RECEIVE)) + { + /* Make the Notifcation */ + SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, + Socket->SharedData.wMsg, + Socket->Handle, + WSAMAKESELECTREPLY(FD_READ, 0)); + + /* Disable this event until the next read(); */ + Socket->SharedData.AsyncDisabledEvents |= FD_READ; + } + + /* Check for oob receive event */ + if (MSAFD_CHECK_EVENT(FD_OOB, Socket) && (Events & AFD_EVENT_OOB_RECEIVE)) + { + /* Make the Notifcation */ + SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, + Socket->SharedData.wMsg, + Socket->Handle, + WSAMAKESELECTREPLY(FD_OOB, 0)); + + /* Disable this event until the next read(); */ + Socket->SharedData.AsyncDisabledEvents |= FD_OOB; + } + + /* Check for write event */ + if (MSAFD_CHECK_EVENT(FD_WRITE, Socket) && (Events & AFD_EVENT_SEND)) + { + /* Make the Notifcation */ + SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, + Socket->SharedData.wMsg, + Socket->Handle, + WSAMAKESELECTREPLY(FD_WRITE, 0)); + + /* Disable this event until the next read(); */ + Socket->SharedData.AsyncDisabledEvents |= FD_WRITE; + } + + /* Check for accept event */ + if (MSAFD_CHECK_EVENT(FD_ACCEPT, Socket) && (Events & AFD_EVENT_ACCEPT)) + { + /* Make the Notifcation */ + SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, + Socket->SharedData.wMsg, + Socket->Handle, + WSAMAKESELECTREPLY(FD_ACCEPT, 0)); + + /* Disable this event until the next read(); */ + Socket->SharedData.AsyncDisabledEvents |= FD_ACCEPT; + } + + /* Check for close events */ + if (MSAFD_CHECK_EVENT(FD_CLOSE, Socket) && ((Events & AFD_EVENT_ACCEPT) || + (Events & AFD_EVENT_ABORT) || + (Events & AFD_EVENT_CLOSE))) + { + /* Make the Notifcation */ + SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, + Socket->SharedData.wMsg, + Socket->Handle, + WSAMAKESELECTREPLY(FD_CLOSE, 0)); + + /* Disable this event until the next read(); */ + Socket->SharedData.AsyncDisabledEvents |= FD_CLOSE; + } + + /* Check for QOS event */ + if (MSAFD_CHECK_EVENT(FD_QOS, Socket) && (Events & AFD_EVENT_QOS)) + { + /* Make the Notifcation */ + SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, + Socket->SharedData.wMsg, + Socket->Handle, + WSAMAKESELECTREPLY(FD_QOS, 0)); + + /* Disable this event until the next read(); */ + Socket->SharedData.AsyncDisabledEvents |= FD_QOS; + } + + /* Check for Group QOS event */ + if (MSAFD_CHECK_EVENT(FD_GROUP_QOS, Socket) && (Events & AFD_EVENT_GROUP_QOS)) + { + /* Make the Notifcation */ + SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, + Socket->SharedData.wMsg, + Socket->Handle, + WSAMAKESELECTREPLY(FD_GROUP_QOS, 0)); + + /* Disable this event until the next read(); */ + Socket->SharedData.AsyncDisabledEvents |= FD_GROUP_QOS; + } + + /* Check for Routing Interface Change event */ + if (MSAFD_CHECK_EVENT(FD_ROUTING_INTERFACE_CHANGE, Socket) && + (Events & AFD_EVENT_ROUTING_INTERFACE_CHANGE)) + { + /* Make the Notifcation */ + SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, + Socket->SharedData.wMsg, + Socket->Handle, + WSAMAKESELECTREPLY(FD_ROUTING_INTERFACE_CHANGE, 0)); + + /* Disable this event until the next read(); */ + Socket->SharedData.AsyncDisabledEvents |= FD_ROUTING_INTERFACE_CHANGE; + } + + /* Check for Address List Change event */ + if (MSAFD_CHECK_EVENT(FD_ADDRESS_LIST_CHANGE, Socket) && + (Events & AFD_EVENT_ADDRESS_LIST_CHANGE)) + { + /* Make the Notifcation */ + SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, + Socket->SharedData.wMsg, + Socket->Handle, + WSAMAKESELECTREPLY(FD_ADDRESS_LIST_CHANGE, 0)); + + /* Disable this event until the next read(); */ + Socket->SharedData.AsyncDisabledEvents |= FD_ADDRESS_LIST_CHANGE; + } + + /* Check if there are any events left for us to check */ + if (!((Socket->SharedData.AsyncEvents) & + (~Socket->SharedData.AsyncDisabledEvents))) + { + /* Nothing left, release lock and return */ + LeaveCriticalSection(&Socket->Lock); + goto error; + } + + /* Keep Polling */ + SockProcessAsyncSelect(Socket, AsyncData); + + /* Leave lock and return */ + LeaveCriticalSection(&Socket->Lock); + return; + +error: + /* Dereference the socket and free the Async Data */ + SockDereferenceSocket(Socket); + RtlFreeHeap(SockPrivateHeap, 0, AsyncData); + + /* Dereference this thread and return */ + InterlockedDecrement(&SockAsyncThreadReferenceCount); + return; +} + +VOID +WSPAPI +SockProcessAsyncSelect(PSOCKET_INFORMATION Socket, + PASYNC_DATA AsyncData) +{ + ULONG lNetworkEvents; + NTSTATUS Status; + + /* Set up the Async Data Event Info */ + AsyncData->AsyncSelectInfo.Timeout.HighPart = 0x7FFFFFFF; + AsyncData->AsyncSelectInfo.Timeout.LowPart = 0xFFFFFFFF; + AsyncData->AsyncSelectInfo.HandleCount = 1; + AsyncData->AsyncSelectInfo.Exclusive = TRUE; + AsyncData->AsyncSelectInfo.Handles[0].Handle = (SOCKET)Socket->WshContext.Handle; + AsyncData->AsyncSelectInfo.Handles[0].Events = 0; + + /* Remove unwanted events */ + lNetworkEvents = Socket->SharedData.AsyncEvents & + (~Socket->SharedData.AsyncDisabledEvents); + + /* Set Events to wait for */ + if (lNetworkEvents & FD_READ) + { + AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_RECEIVE; + } + if (lNetworkEvents & FD_WRITE) + { + AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_SEND; + } + if (lNetworkEvents & FD_OOB) + { + AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_OOB_RECEIVE; + } + if (lNetworkEvents & FD_ACCEPT) + { + AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_ACCEPT; + } + if (lNetworkEvents & FD_CLOSE) + { + AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_DISCONNECT | + AFD_EVENT_ABORT | + AFD_EVENT_CLOSE; + } + if (lNetworkEvents & FD_QOS) + { + AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_QOS; + } + if (lNetworkEvents & FD_GROUP_QOS) + { + AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_GROUP_QOS; + } + if (lNetworkEvents & FD_ROUTING_INTERFACE_CHANGE) + { + AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_ROUTING_INTERFACE_CHANGE; + } + if (lNetworkEvents & FD_ADDRESS_LIST_CHANGE) + { + AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_ADDRESS_LIST_CHANGE; + } + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(SockAsyncSelectHelperHandle, + NULL, + NULL, + AsyncData, + &AsyncData->IoStatusBlock, + IOCTL_AFD_SELECT, + &AsyncData->AsyncSelectInfo, + sizeof(AsyncData->AsyncSelectInfo), + &AsyncData->AsyncSelectInfo, + sizeof(AsyncData->AsyncSelectInfo)); + /* Check for failure */ + if (NT_ERROR(Status)) + { + /* I/O Manager Won't call the completion routine; do it manually */ + AsyncData->IoStatusBlock.Status = Status; + SockAsyncSelectCompletion(AsyncData, &AsyncData->IoStatusBlock); + } +} + +VOID +WSPAPI +SockProcessQueuedAsyncSelect(PVOID Context, + PIO_STATUS_BLOCK IoStatusBlock) +{ + PASYNC_DATA AsyncData = Context; + PSOCKET_INFORMATION Socket = AsyncData->ParentSocket; + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* Make sure it's not closed */ + if (Socket->SharedData.State == SocketClosed) + { + /* Return */ + LeaveCriticalSection(&Socket->Lock); + goto error; + } + + /* Check if the Sequence Number changed by now */ + if (AsyncData->SequenceNumber != Socket->SharedData.SequenceNumber) + { + /* Return */ + LeaveCriticalSection(&Socket->Lock); + goto error; + } + + /* Check if select is needed */ + if (!((Socket->SharedData.AsyncEvents & + ~Socket->SharedData.AsyncDisabledEvents))) + { + /* Return */ + LeaveCriticalSection(&Socket->Lock); + goto error; + } + + /* Do the actual select */ + SockProcessAsyncSelect(Socket, AsyncData); + + /* Return */ + LeaveCriticalSection(&Socket->Lock); + return; + +error: + /* Dereference the socket and free the async data */ + SockDereferenceSocket(Socket); + RtlFreeHeap(SockPrivateHeap, 0, AsyncData); + + /* Dereference this thread */ + InterlockedDecrement(&SockAsyncThreadReferenceCount); +} + +INT +WSPAPI +SockReenableAsyncSelectEvent(IN PSOCKET_INFORMATION Socket, + IN ULONG Event) +{ + PASYNC_DATA AsyncData; + NTSTATUS Status; + + /* Make sure the event is actually disabled */ + if (!(Socket->SharedData.AsyncDisabledEvents & Event)) return NO_ERROR; + + /* Make sure we're not closed */ + if (Socket->SharedData.State == SocketClosed) return NO_ERROR; + + /* Re-enable it */ + Socket->SharedData.AsyncDisabledEvents &= ~Event; + + /* Return if no more events are being polled */ + if (!((Socket->SharedData.AsyncEvents & + ~Socket->SharedData.AsyncDisabledEvents))) + { + return NO_ERROR; + } + + /* Allocate Async Data */ + AsyncData = SockAllocateHeapRoutine(SockPrivateHeap, 0, sizeof(ASYNC_DATA)); + + /* Increase the sequence number to stop anything else */ + Socket->SharedData.SequenceNumber++; + + /* Set up the Async Data */ + AsyncData->ParentSocket = Socket; + AsyncData->SequenceNumber = Socket->SharedData.SequenceNumber; + + /* Begin Async Select by using I/O Completion */ + Status = NtSetIoCompletion(SockAsyncQueuePort, + (PVOID)&SockProcessQueuedAsyncSelect, + AsyncData, + 0, + 0); + if (!NT_SUCCESS(Status)) + { + /* Dereference the socket and fail */ + SockDereferenceSocket(Socket); + RtlFreeHeap(SockPrivateHeap, 0, AsyncData); + return NtStatusToSocketError(Status); + } + + /* All done */ + return NO_ERROR; +} + +INT +WSPAPI +SockAsyncSelectHelper(IN PSOCKET_INFORMATION Socket, + IN HWND hWnd, + IN UINT wMsg, + IN LONG lEvent) +{ + PASYNC_DATA AsyncData = NULL; + BOOLEAN BlockMode; + NTSTATUS Status; + INT ErrorCode; + + /* Allocate the Async Data Structure to pass on to the Thread later */ + AsyncData = SockAllocateHeapRoutine(SockPrivateHeap, 0, sizeof(*AsyncData)); + if (!AsyncData) return WSAENOBUFS; + + /* Acquire socket lock */ + EnterCriticalSection(&Socket->Lock); + + /* Is there an active WSPEventSelect? */ + if (Socket->SharedData.AsyncEvents) + { + /* Call the helper to process it */ + ErrorCode = SockEventSelectHelper(Socket, NULL, 0); + if (ErrorCode != NO_ERROR) goto error; + } + + /* Set Socket to Non-Blocking */ + BlockMode = TRUE; + ErrorCode = SockSetInformation(Socket, + AFD_INFO_BLOCKING_MODE, + &BlockMode, + NULL, + NULL); + if (ErrorCode != NO_ERROR) goto error; + + /* AFD was notified, set it locally as well */ + Socket->SharedData.NonBlocking = TRUE; + + /* Store Socket Data */ + Socket->SharedData.hWnd = hWnd; + Socket->SharedData.wMsg = wMsg; + Socket->SharedData.AsyncEvents = lEvent; + Socket->SharedData.AsyncDisabledEvents = 0; + + /* Check if the socket is not connected and not a datagram socket */ + if ((!SockIsSocketConnected(Socket)) && !MSAFD_IS_DGRAM_SOCK(Socket)) + { + /* Disable FD_WRITE for now, so we don't get it before FD_CONNECT */ + Socket->SharedData.AsyncDisabledEvents |= FD_WRITE; + } + + /* Increase the sequence number */ + Socket->SharedData.SequenceNumber++; + + /* Return if there are no more Events */ + if (!(Socket->SharedData.AsyncEvents & + (~Socket->SharedData.AsyncDisabledEvents))) + { + /* Release the lock, dereference the async thread and the socket */ + LeaveCriticalSection(&Socket->Lock); + InterlockedDecrement(&SockAsyncThreadReferenceCount); + SockDereferenceSocket(Socket); + + /* Free the Async Data */ + RtlFreeHeap(SockPrivateHeap, 0, AsyncData); + return NO_ERROR; + } + + /* Set up the Async Data */ + AsyncData->ParentSocket = Socket; + AsyncData->SequenceNumber = Socket->SharedData.SequenceNumber; + + /* Release the lock now */ + LeaveCriticalSection(&Socket->Lock); + + /* Begin Async Select by using I/O Completion */ + Status = NtSetIoCompletion(SockAsyncQueuePort, + (PVOID)&SockProcessQueuedAsyncSelect, + AsyncData, + 0, + 0); + if (!NT_SUCCESS(Status)) + { + /* Dereference the async thread and fail */ + InterlockedDecrement(&SockAsyncThreadReferenceCount); + ErrorCode = NtStatusToSocketError(Status); + } + +error: + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Free the async data */ + RtlFreeHeap(SockPrivateHeap, 0, AsyncData); + + /* Fail */ + return SOCKET_ERROR; + } + + /* Increment the socket reference */ + InterlockedIncrement(&Socket->RefCount); + + /* Return success */ + return NO_ERROR; +} + +INT +WSPAPI +WSPAsyncSelect(IN SOCKET Handle, + IN HWND hWnd, + IN UINT wMsg, + IN LONG lEvent, + OUT LPINT lpErrno) +{ + PSOCKET_INFORMATION Socket; + INT ErrorCode; + PWINSOCK_TEB_DATA ThreadData; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Check for valid events */ + if (lEvent & ~FD_ALL_EVENTS) + { + /* Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Check for valid window handle */ + if (!IsWindow(hWnd)) + { + /* Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Create the Asynch Thread if Needed */ + if (!SockCheckAndReferenceAsyncThread()) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + + /* Open a Handle to AFD's Async Helper */ + if (!SockCheckAndInitAsyncSelectHelper()) + { + /* Dereference async thread and fail */ + InterlockedDecrement(&SockAsyncThreadReferenceCount); + ErrorCode = WSAENOBUFS; + goto error; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Call the helper to do the work */ + ErrorCode = SockAsyncSelectHelper(Socket, + hWnd, + wMsg, + lEvent); + + /* Dereference the socket */ + SockDereferenceSocket(Socket); + +error: + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +INT +WSPAPI +WSPSelect(INT nfds, + PFD_SET readfds, + PFD_SET writefds, + PFD_SET exceptfds, + CONST LPTIMEVAL timeout, + LPINT lpErrno) +{ + IO_STATUS_BLOCK IoStatusBlock; + PAFD_POLL_INFO PollInfo = NULL; + NTSTATUS Status; + CHAR PollBuffer[sizeof(AFD_POLL_INFO) + 3 * sizeof(AFD_HANDLE)]; + PAFD_HANDLE HandleArray; + ULONG HandleCount, OutCount = 0; + ULONG PollBufferSize; + ULONG i; + PWINSOCK_TEB_DATA ThreadData; + LARGE_INTEGER uSec; + ULONG BlockType; + INT ErrorCode; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* How many sockets will we check? */ + HandleCount = HANDLES_IN_SET(readfds) + + HANDLES_IN_SET(writefds) + + HANDLES_IN_SET(exceptfds); + + /* Leave if none are */ + if (!HandleCount) return NO_ERROR; + + /* How much space will they require? */ + PollBufferSize = sizeof(*PollInfo) + (HandleCount * sizeof(AFD_HANDLE)); + + /* Check if our stack is big enough to hold it */ + if (PollBufferSize <= sizeof(PollBuffer)) + { + /* Use the stack */ + PollInfo = (PVOID)PollBuffer; + } + else + { + /* Allocate from heap instead */ + PollInfo = SockAllocateHeapRoutine(SockPrivateHeap, 0, PollBufferSize); + if (!PollInfo) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + } + + /* Number of handles for AFD to Check */ + PollInfo->HandleCount = HandleCount; + PollInfo->Exclusive = FALSE; + HandleArray = PollInfo->Handles; + + /* Select the Read Events */ + for (i = 0; readfds && i < (readfds->fd_count & 0xFFFF); i++) + { + /* Fill out handle info */ + HandleArray->Handle = (SOCKET)readfds->fd_array[i]; + HandleArray->Events = AFD_EVENT_RECEIVE | + AFD_EVENT_DISCONNECT | + AFD_EVENT_ABORT; + + /* Move to the next one */ + HandleArray++; + } + for (i = 0; writefds && i < (writefds->fd_count & 0xFFFF); i++) + { + /* Fill out handle info */ + HandleArray->Handle = (SOCKET)writefds->fd_array[i]; + HandleArray->Events = AFD_EVENT_SEND; + + /* Move to the next one */ + HandleArray++; + } + for (i = 0; exceptfds && i < (exceptfds->fd_count & 0xFFFF); i++) + { + /* Fill out handle info */ + HandleArray->Handle = (SOCKET)exceptfds->fd_array[i]; + HandleArray->Events = AFD_EVENT_OOB_RECEIVE | AFD_EVENT_CONNECT_FAIL; + + /* Move to the next one */ + HandleArray++; + } + + /* Check if a timeout was given */ + if (timeout) + { + /* Inifinte Timeout */ + PollInfo->Timeout.u.LowPart = -1; + PollInfo->Timeout.u.HighPart = 0x7FFFFFFF; + } + else + { + /* Calculate microseconds */ + uSec = RtlEnlargedIntegerMultiply(timeout->tv_usec, -10); + + /* Calculate seconds */ + PollInfo->Timeout = RtlEnlargedIntegerMultiply(timeout->tv_sec, + -1 * 1000 * 1000 * 10); + + /* Add microseconds */ + PollInfo->Timeout.QuadPart += uSec.QuadPart; + } + + /* Send IOCTL */ + Status = NtDeviceIoControlFile((HANDLE)PollInfo->Handles[0].Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_SELECT, + PollInfo, + PollBufferSize, + PollInfo, + PollBufferSize); + + /* Check if we have to wait */ + if (Status == STATUS_PENDING) + { + /* Check if we'll call the blocking hook */ + if (!PollInfo->Timeout.QuadPart) BlockType = NO_BLOCKING_HOOK; + + /* Wait for completion */ + SockWaitForSingleObject(ThreadData->EventHandle, + (SOCKET)PollInfo->Handles[0].Handle, + BlockType, + NO_TIMEOUT); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for failure */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* Clear the Structures */ + if(readfds) FD_ZERO(readfds); + if(writefds) FD_ZERO(writefds); + if(exceptfds) FD_ZERO(exceptfds); + + /* Get the handle info again */ + HandleCount = PollInfo->HandleCount; + HandleArray = PollInfo->Handles; + + /* Loop the Handles that got an event */ + for (i = 0; i < HandleCount; i++) + { + /* Check for a match */ + if (HandleArray->Events & AFD_EVENT_RECEIVE) + { + /* Check if it's not already set */ + if (!FD_ISSET((SOCKET)HandleArray->Handle, readfds)) + { + /* Increase Handles with an Event */ + OutCount++; + + /* Set this handle */ + FD_SET((SOCKET)HandleArray->Handle, readfds); + } + } + /* Check for a match */ + if (HandleArray->Events & AFD_EVENT_SEND) + { + /* Check if it's not already set */ + if (!FD_ISSET((SOCKET)HandleArray->Handle, writefds)) + { + /* Increase Handles with an Event */ + OutCount++; + + /* Set this handle */ + FD_SET((SOCKET)HandleArray->Handle, writefds); + } + } + /* Check for a match */ + if (HandleArray->Events & AFD_EVENT_OOB_RECEIVE) + { + /* Check if it's not already set */ + if (!FD_ISSET((SOCKET)HandleArray->Handle, exceptfds)) + { + /* Increase Handles with an Event */ + OutCount++; + + /* Set this handle */ + FD_SET((SOCKET)HandleArray->Handle, exceptfds); + } + } + /* Check for a match */ + if (HandleArray->Events & AFD_EVENT_ACCEPT) + { + /* Check if it's not already set */ + if (!FD_ISSET((SOCKET)HandleArray->Handle, readfds)) + { + /* Increase Handles with an Event */ + OutCount++; + + /* Set this handle */ + FD_SET((SOCKET)HandleArray->Handle, readfds); + } + } + /* Check for a match */ + if (HandleArray->Events & AFD_EVENT_CONNECT) + { + /* Check if it's not already set */ + if (!FD_ISSET((SOCKET)HandleArray->Handle, writefds)) + { + /* Increase Handles with an Event */ + OutCount++; + + /* Set this handle */ + FD_SET((SOCKET)HandleArray->Handle, writefds); + } + } + /* Check for a match */ + if (HandleArray->Events & AFD_EVENT_CONNECT_FAIL) + { + /* Check if it's not already set */ + if (!FD_ISSET((SOCKET)HandleArray->Handle, exceptfds)) + { + /* Increase Handles with an Event */ + OutCount++; + + /* Set this handle */ + FD_SET((SOCKET)HandleArray->Handle, exceptfds); + } + } + /* Check for a match */ + if (HandleArray->Events & AFD_EVENT_DISCONNECT) + { + /* Check if it's not already set */ + if (!FD_ISSET((SOCKET)HandleArray->Handle, readfds)) + { + /* Increase Handles with an Event */ + OutCount++; + + /* Set this handle */ + FD_SET((SOCKET)HandleArray->Handle, readfds); + } + } + /* Check for a match */ + if (HandleArray->Events & AFD_EVENT_ABORT) + { + /* Check if it's not already set */ + if (!FD_ISSET((SOCKET)HandleArray->Handle, readfds)) + { + /* Increase Handles with an Event */ + OutCount++; + + /* Set this handle */ + FD_SET((SOCKET)HandleArray->Handle, readfds); + } + } + /* Check for a match */ + if (HandleArray->Events & AFD_EVENT_CLOSE) + { + /* Check if it's not already set */ + if (!FD_ISSET((SOCKET)HandleArray->Handle, readfds)) + { + /* Increase Handles with an Event */ + OutCount++; + + /* Set this handle */ + FD_SET((SOCKET)HandleArray->Handle, readfds); + } + } + + /* Move to next entry */ + HandleArray++; + } + +error: + + /* Check if we should free the buffer */ + if (PollInfo && (PollInfo != (PVOID)PollBuffer)) + { + /* Free it from the heap */ + RtlFreeHeap(SockPrivateHeap, 0, PollInfo); + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Return error */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return the number of handles */ + return OutCount; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +#define MSAFD_CHECK_EVENT(e, s) \ + (!(s->SharedData.AsyncDisabledEvents & e) && \ + (s->SharedData.AsyncEvents & e)) + +#define HANDLES_IN_SET(s) \ + s == NULL ? 0 : (s->fd_count & 0xFFFF) + +/* DATA **********************************************************************/ + +HANDLE SockAsyncSelectHelperHandle; +BOOLEAN SockAsyncSelectCalled; + +/* FUNCTIONS *****************************************************************/ + +BOOLEAN +WSPAPI +SockCheckAndInitAsyncSelectHelper(VOID) +{ + UNICODE_STRING AfdHelper; + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + FILE_COMPLETION_INFORMATION CompletionInfo; + OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags; + + /* First, make sure we're not already intialized */ + if (SockAsyncSelectHelperHandle) return TRUE; + + /* Acquire the global lock */ + SockAcquireRwLockExclusive(&SocketGlobalLock); + + /* Check again, under the lock */ + if (SockAsyncSelectHelperHandle) + { + /* Return without lock */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + return TRUE; + } + + /* Set up Handle Name and Object */ + RtlInitUnicodeString(&AfdHelper, L"\\Device\\Afd\\AsyncSelectHlp" ); + InitializeObjectAttributes(&ObjectAttributes, + &AfdHelper, + OBJ_INHERIT | OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + /* Open the Handle to AFD */ + Status = NtCreateFile(&SockAsyncSelectHelperHandle, + GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, + &ObjectAttributes, + &IoStatusBlock, + NULL, + 0, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_OPEN_IF, + 0, + NULL, + 0); + if (!NT_SUCCESS(Status)) + { + /* Return without lock */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + return TRUE; + } + + /* Check if the port exists, and if not, create it */ + if (SockAsyncQueuePort) SockCreateAsyncQueuePort(); + + /* + * Now Set up the Completion Port Information + * This means that whenever a Poll is finished, the routine will be executed + */ + CompletionInfo.Port = SockAsyncQueuePort; + CompletionInfo.Key = SockAsyncSelectCompletion; + Status = NtSetInformationFile(SockAsyncSelectHelperHandle, + &IoStatusBlock, + &CompletionInfo, + sizeof(CompletionInfo), + FileCompletionInformation); + + /* Protect the Handle */ + HandleFlags.ProtectFromClose = TRUE; + HandleFlags.Inherit = FALSE; + Status = NtSetInformationObject(SockAsyncQueuePort, + ObjectHandleFlagInformation, + &HandleFlags, + sizeof(HandleFlags)); + + /* + * Set this variable to true so that Send/Recv/Accept will know whether + * to renable disabled events + */ + SockAsyncSelectCalled = TRUE; + + /* Release lock and return */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + return TRUE; +} + +VOID +WSPAPI +SockAsyncSelectCompletion(PVOID Context, + PIO_STATUS_BLOCK IoStatusBlock) +{ + PASYNC_DATA AsyncData = Context; + PSOCKET_INFORMATION Socket = AsyncData->ParentSocket; + ULONG Events; + INT ErrorCode; + + /* Acquire the socket lock */ + EnterCriticalSection(&Socket->Lock); + + /* Check if the socket was closed or the I/O cancelled */ + if ((Socket->SharedData.State == SocketClosed) || + (IoStatusBlock->Status == STATUS_CANCELLED)) + { + /* Return */ + LeaveCriticalSection(&Socket->Lock); + goto error; + } + + /* Check if the Sequence Number Changed behind our back */ + if (AsyncData->SequenceNumber != Socket->SharedData.SequenceNumber) + { + /* Return */ + LeaveCriticalSection(&Socket->Lock); + goto error; + } + + /* Check we were manually called b/c of a failure */ + if (!NT_SUCCESS(IoStatusBlock->Status)) + { + /* Get the error and tell WPU about it */ + ErrorCode = NtStatusToSocketError(IoStatusBlock->Status); + SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, + Socket->SharedData.wMsg, + Socket->Handle, + WSAMAKESELECTREPLY(0, ErrorCode)); + + /* Return */ + LeaveCriticalSection(&Socket->Lock); + goto error; + } + + /* Select the event bits */ + Events = AsyncData->AsyncSelectInfo.Handles[0].Events; + + /* Check for receive event */ + if (MSAFD_CHECK_EVENT(FD_READ, Socket) && (Events & AFD_EVENT_RECEIVE)) + { + /* Make the Notifcation */ + SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, + Socket->SharedData.wMsg, + Socket->Handle, + WSAMAKESELECTREPLY(FD_READ, 0)); + + /* Disable this event until the next read(); */ + Socket->SharedData.AsyncDisabledEvents |= FD_READ; + } + + /* Check for oob receive event */ + if (MSAFD_CHECK_EVENT(FD_OOB, Socket) && (Events & AFD_EVENT_OOB_RECEIVE)) + { + /* Make the Notifcation */ + SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, + Socket->SharedData.wMsg, + Socket->Handle, + WSAMAKESELECTREPLY(FD_OOB, 0)); + + /* Disable this event until the next read(); */ + Socket->SharedData.AsyncDisabledEvents |= FD_OOB; + } + + /* Check for write event */ + if (MSAFD_CHECK_EVENT(FD_WRITE, Socket) && (Events & AFD_EVENT_SEND)) + { + /* Make the Notifcation */ + SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, + Socket->SharedData.wMsg, + Socket->Handle, + WSAMAKESELECTREPLY(FD_WRITE, 0)); + + /* Disable this event until the next read(); */ + Socket->SharedData.AsyncDisabledEvents |= FD_WRITE; + } + + /* Check for accept event */ + if (MSAFD_CHECK_EVENT(FD_ACCEPT, Socket) && (Events & AFD_EVENT_ACCEPT)) + { + /* Make the Notifcation */ + SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, + Socket->SharedData.wMsg, + Socket->Handle, + WSAMAKESELECTREPLY(FD_ACCEPT, 0)); + + /* Disable this event until the next read(); */ + Socket->SharedData.AsyncDisabledEvents |= FD_ACCEPT; + } + + /* Check for close events */ + if (MSAFD_CHECK_EVENT(FD_CLOSE, Socket) && ((Events & AFD_EVENT_ACCEPT) || + (Events & AFD_EVENT_ABORT) || + (Events & AFD_EVENT_CLOSE))) + { + /* Make the Notifcation */ + SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, + Socket->SharedData.wMsg, + Socket->Handle, + WSAMAKESELECTREPLY(FD_CLOSE, 0)); + + /* Disable this event until the next read(); */ + Socket->SharedData.AsyncDisabledEvents |= FD_CLOSE; + } + + /* Check for QOS event */ + if (MSAFD_CHECK_EVENT(FD_QOS, Socket) && (Events & AFD_EVENT_QOS)) + { + /* Make the Notifcation */ + SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, + Socket->SharedData.wMsg, + Socket->Handle, + WSAMAKESELECTREPLY(FD_QOS, 0)); + + /* Disable this event until the next read(); */ + Socket->SharedData.AsyncDisabledEvents |= FD_QOS; + } + + /* Check for Group QOS event */ + if (MSAFD_CHECK_EVENT(FD_GROUP_QOS, Socket) && (Events & AFD_EVENT_GROUP_QOS)) + { + /* Make the Notifcation */ + SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, + Socket->SharedData.wMsg, + Socket->Handle, + WSAMAKESELECTREPLY(FD_GROUP_QOS, 0)); + + /* Disable this event until the next read(); */ + Socket->SharedData.AsyncDisabledEvents |= FD_GROUP_QOS; + } + + /* Check for Routing Interface Change event */ + if (MSAFD_CHECK_EVENT(FD_ROUTING_INTERFACE_CHANGE, Socket) && + (Events & AFD_EVENT_ROUTING_INTERFACE_CHANGE)) + { + /* Make the Notifcation */ + SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, + Socket->SharedData.wMsg, + Socket->Handle, + WSAMAKESELECTREPLY(FD_ROUTING_INTERFACE_CHANGE, 0)); + + /* Disable this event until the next read(); */ + Socket->SharedData.AsyncDisabledEvents |= FD_ROUTING_INTERFACE_CHANGE; + } + + /* Check for Address List Change event */ + if (MSAFD_CHECK_EVENT(FD_ADDRESS_LIST_CHANGE, Socket) && + (Events & AFD_EVENT_ADDRESS_LIST_CHANGE)) + { + /* Make the Notifcation */ + SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, + Socket->SharedData.wMsg, + Socket->Handle, + WSAMAKESELECTREPLY(FD_ADDRESS_LIST_CHANGE, 0)); + + /* Disable this event until the next read(); */ + Socket->SharedData.AsyncDisabledEvents |= FD_ADDRESS_LIST_CHANGE; + } + + /* Check if there are any events left for us to check */ + if (!((Socket->SharedData.AsyncEvents) & + (~Socket->SharedData.AsyncDisabledEvents))) + { + /* Nothing left, release lock and return */ + LeaveCriticalSection(&Socket->Lock); + goto error; + } + + /* Keep Polling */ + SockProcessAsyncSelect(Socket, AsyncData); + + /* Leave lock and return */ + LeaveCriticalSection(&Socket->Lock); + return; + +error: + /* Dereference the socket and free the Async Data */ + SockDereferenceSocket(Socket); + RtlFreeHeap(SockPrivateHeap, 0, AsyncData); + + /* Dereference this thread and return */ + InterlockedDecrement(&SockAsyncThreadReferenceCount); + return; +} + +VOID +WSPAPI +SockProcessAsyncSelect(PSOCKET_INFORMATION Socket, + PASYNC_DATA AsyncData) +{ + ULONG lNetworkEvents; + NTSTATUS Status; + + /* Set up the Async Data Event Info */ + AsyncData->AsyncSelectInfo.Timeout.HighPart = 0x7FFFFFFF; + AsyncData->AsyncSelectInfo.Timeout.LowPart = 0xFFFFFFFF; + AsyncData->AsyncSelectInfo.HandleCount = 1; + AsyncData->AsyncSelectInfo.Exclusive = TRUE; + AsyncData->AsyncSelectInfo.Handles[0].Handle = (SOCKET)Socket->WshContext.Handle; + AsyncData->AsyncSelectInfo.Handles[0].Events = 0; + + /* Remove unwanted events */ + lNetworkEvents = Socket->SharedData.AsyncEvents & + (~Socket->SharedData.AsyncDisabledEvents); + + /* Set Events to wait for */ + if (lNetworkEvents & FD_READ) + { + AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_RECEIVE; + } + if (lNetworkEvents & FD_WRITE) + { + AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_SEND; + } + if (lNetworkEvents & FD_OOB) + { + AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_OOB_RECEIVE; + } + if (lNetworkEvents & FD_ACCEPT) + { + AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_ACCEPT; + } + if (lNetworkEvents & FD_CLOSE) + { + AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_DISCONNECT | + AFD_EVENT_ABORT | + AFD_EVENT_CLOSE; + } + if (lNetworkEvents & FD_QOS) + { + AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_QOS; + } + if (lNetworkEvents & FD_GROUP_QOS) + { + AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_GROUP_QOS; + } + if (lNetworkEvents & FD_ROUTING_INTERFACE_CHANGE) + { + AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_ROUTING_INTERFACE_CHANGE; + } + if (lNetworkEvents & FD_ADDRESS_LIST_CHANGE) + { + AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_ADDRESS_LIST_CHANGE; + } + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(SockAsyncSelectHelperHandle, + NULL, + NULL, + AsyncData, + &AsyncData->IoStatusBlock, + IOCTL_AFD_SELECT, + &AsyncData->AsyncSelectInfo, + sizeof(AsyncData->AsyncSelectInfo), + &AsyncData->AsyncSelectInfo, + sizeof(AsyncData->AsyncSelectInfo)); + /* Check for failure */ + if (NT_ERROR(Status)) + { + /* I/O Manager Won't call the completion routine; do it manually */ + AsyncData->IoStatusBlock.Status = Status; + SockAsyncSelectCompletion(AsyncData, &AsyncData->IoStatusBlock); + } +} + +VOID +WSPAPI +SockProcessQueuedAsyncSelect(PVOID Context, + PIO_STATUS_BLOCK IoStatusBlock) +{ + PASYNC_DATA AsyncData = Context; + PSOCKET_INFORMATION Socket = AsyncData->ParentSocket; + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* Make sure it's not closed */ + if (Socket->SharedData.State == SocketClosed) + { + /* Return */ + LeaveCriticalSection(&Socket->Lock); + goto error; + } + + /* Check if the Sequence Number changed by now */ + if (AsyncData->SequenceNumber != Socket->SharedData.SequenceNumber) + { + /* Return */ + LeaveCriticalSection(&Socket->Lock); + goto error; + } + + /* Check if select is needed */ + if (!((Socket->SharedData.AsyncEvents & + ~Socket->SharedData.AsyncDisabledEvents))) + { + /* Return */ + LeaveCriticalSection(&Socket->Lock); + goto error; + } + + /* Do the actual select */ + SockProcessAsyncSelect(Socket, AsyncData); + + /* Return */ + LeaveCriticalSection(&Socket->Lock); + return; + +error: + /* Dereference the socket and free the async data */ + SockDereferenceSocket(Socket); + RtlFreeHeap(SockPrivateHeap, 0, AsyncData); + + /* Dereference this thread */ + InterlockedDecrement(&SockAsyncThreadReferenceCount); +} + +INT +WSPAPI +SockReenableAsyncSelectEvent(IN PSOCKET_INFORMATION Socket, + IN ULONG Event) +{ + PASYNC_DATA AsyncData; + NTSTATUS Status; + + /* Make sure the event is actually disabled */ + if (!(Socket->SharedData.AsyncDisabledEvents & Event)) return NO_ERROR; + + /* Make sure we're not closed */ + if (Socket->SharedData.State == SocketClosed) return NO_ERROR; + + /* Re-enable it */ + Socket->SharedData.AsyncDisabledEvents &= ~Event; + + /* Return if no more events are being polled */ + if (!((Socket->SharedData.AsyncEvents & + ~Socket->SharedData.AsyncDisabledEvents))) + { + return NO_ERROR; + } + + /* Allocate Async Data */ + AsyncData = SockAllocateHeapRoutine(SockPrivateHeap, 0, sizeof(ASYNC_DATA)); + + /* Increase the sequence number to stop anything else */ + Socket->SharedData.SequenceNumber++; + + /* Set up the Async Data */ + AsyncData->ParentSocket = Socket; + AsyncData->SequenceNumber = Socket->SharedData.SequenceNumber; + + /* Begin Async Select by using I/O Completion */ + Status = NtSetIoCompletion(SockAsyncQueuePort, + (PVOID)&SockProcessQueuedAsyncSelect, + AsyncData, + 0, + 0); + if (!NT_SUCCESS(Status)) + { + /* Dereference the socket and fail */ + SockDereferenceSocket(Socket); + RtlFreeHeap(SockPrivateHeap, 0, AsyncData); + return NtStatusToSocketError(Status); + } + + /* All done */ + return NO_ERROR; +} + +INT +WSPAPI +SockAsyncSelectHelper(IN PSOCKET_INFORMATION Socket, + IN HWND hWnd, + IN UINT wMsg, + IN LONG lEvent) +{ + PASYNC_DATA AsyncData = NULL; + BOOLEAN BlockMode; + NTSTATUS Status; + INT ErrorCode; + + /* Allocate the Async Data Structure to pass on to the Thread later */ + AsyncData = SockAllocateHeapRoutine(SockPrivateHeap, 0, sizeof(*AsyncData)); + if (!AsyncData) return WSAENOBUFS; + + /* Acquire socket lock */ + EnterCriticalSection(&Socket->Lock); + + /* Is there an active WSPEventSelect? */ + if (Socket->SharedData.AsyncEvents) + { + /* Call the helper to process it */ + ErrorCode = SockEventSelectHelper(Socket, NULL, 0); + if (ErrorCode != NO_ERROR) goto error; + } + + /* Set Socket to Non-Blocking */ + BlockMode = TRUE; + ErrorCode = SockSetInformation(Socket, + AFD_INFO_BLOCKING_MODE, + &BlockMode, + NULL, + NULL); + if (ErrorCode != NO_ERROR) goto error; + + /* AFD was notified, set it locally as well */ + Socket->SharedData.NonBlocking = TRUE; + + /* Store Socket Data */ + Socket->SharedData.hWnd = hWnd; + Socket->SharedData.wMsg = wMsg; + Socket->SharedData.AsyncEvents = lEvent; + Socket->SharedData.AsyncDisabledEvents = 0; + + /* Check if the socket is not connected and not a datagram socket */ + if ((!SockIsSocketConnected(Socket)) && !MSAFD_IS_DGRAM_SOCK(Socket)) + { + /* Disable FD_WRITE for now, so we don't get it before FD_CONNECT */ + Socket->SharedData.AsyncDisabledEvents |= FD_WRITE; + } + + /* Increase the sequence number */ + Socket->SharedData.SequenceNumber++; + + /* Return if there are no more Events */ + if (!(Socket->SharedData.AsyncEvents & + (~Socket->SharedData.AsyncDisabledEvents))) + { + /* Release the lock, dereference the async thread and the socket */ + LeaveCriticalSection(&Socket->Lock); + InterlockedDecrement(&SockAsyncThreadReferenceCount); + SockDereferenceSocket(Socket); + + /* Free the Async Data */ + RtlFreeHeap(SockPrivateHeap, 0, AsyncData); + return NO_ERROR; + } + + /* Set up the Async Data */ + AsyncData->ParentSocket = Socket; + AsyncData->SequenceNumber = Socket->SharedData.SequenceNumber; + + /* Release the lock now */ + LeaveCriticalSection(&Socket->Lock); + + /* Begin Async Select by using I/O Completion */ + Status = NtSetIoCompletion(SockAsyncQueuePort, + (PVOID)&SockProcessQueuedAsyncSelect, + AsyncData, + 0, + 0); + if (!NT_SUCCESS(Status)) + { + /* Dereference the async thread and fail */ + InterlockedDecrement(&SockAsyncThreadReferenceCount); + ErrorCode = NtStatusToSocketError(Status); + } + +error: + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Free the async data */ + RtlFreeHeap(SockPrivateHeap, 0, AsyncData); + + /* Fail */ + return SOCKET_ERROR; + } + + /* Increment the socket reference */ + InterlockedIncrement(&Socket->RefCount); + + /* Return success */ + return NO_ERROR; +} + +INT +WSPAPI +WSPAsyncSelect(IN SOCKET Handle, + IN HWND hWnd, + IN UINT wMsg, + IN LONG lEvent, + OUT LPINT lpErrno) +{ + PSOCKET_INFORMATION Socket; + INT ErrorCode; + PWINSOCK_TEB_DATA ThreadData; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Check for valid events */ + if (lEvent & ~FD_ALL_EVENTS) + { + /* Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Check for valid window handle */ + if (!IsWindow(hWnd)) + { + /* Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Create the Asynch Thread if Needed */ + if (!SockCheckAndReferenceAsyncThread()) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + + /* Open a Handle to AFD's Async Helper */ + if (!SockCheckAndInitAsyncSelectHelper()) + { + /* Dereference async thread and fail */ + InterlockedDecrement(&SockAsyncThreadReferenceCount); + ErrorCode = WSAENOBUFS; + goto error; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Call the helper to do the work */ + ErrorCode = SockAsyncSelectHelper(Socket, + hWnd, + wMsg, + lEvent); + + /* Dereference the socket */ + SockDereferenceSocket(Socket); + +error: + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +INT +WSPAPI +WSPSelect(INT nfds, + PFD_SET readfds, + PFD_SET writefds, + PFD_SET exceptfds, + CONST LPTIMEVAL timeout, + LPINT lpErrno) +{ + IO_STATUS_BLOCK IoStatusBlock; + PAFD_POLL_INFO PollInfo = NULL; + NTSTATUS Status; + CHAR PollBuffer[sizeof(AFD_POLL_INFO) + 3 * sizeof(AFD_HANDLE)]; + PAFD_HANDLE HandleArray; + ULONG HandleCount, OutCount = 0; + ULONG PollBufferSize; + ULONG i; + PWINSOCK_TEB_DATA ThreadData; + LARGE_INTEGER uSec; + ULONG BlockType; + INT ErrorCode; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* How many sockets will we check? */ + HandleCount = HANDLES_IN_SET(readfds) + + HANDLES_IN_SET(writefds) + + HANDLES_IN_SET(exceptfds); + + /* Leave if none are */ + if (!HandleCount) return NO_ERROR; + + /* How much space will they require? */ + PollBufferSize = sizeof(*PollInfo) + (HandleCount * sizeof(AFD_HANDLE)); + + /* Check if our stack is big enough to hold it */ + if (PollBufferSize <= sizeof(PollBuffer)) + { + /* Use the stack */ + PollInfo = (PVOID)PollBuffer; + } + else + { + /* Allocate from heap instead */ + PollInfo = SockAllocateHeapRoutine(SockPrivateHeap, 0, PollBufferSize); + if (!PollInfo) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + } + + /* Number of handles for AFD to Check */ + PollInfo->HandleCount = HandleCount; + PollInfo->Exclusive = FALSE; + HandleArray = PollInfo->Handles; + + /* Select the Read Events */ + for (i = 0; readfds && i < (readfds->fd_count & 0xFFFF); i++) + { + /* Fill out handle info */ + HandleArray->Handle = (SOCKET)readfds->fd_array[i]; + HandleArray->Events = AFD_EVENT_RECEIVE | + AFD_EVENT_DISCONNECT | + AFD_EVENT_ABORT; + + /* Move to the next one */ + HandleArray++; + } + for (i = 0; writefds && i < (writefds->fd_count & 0xFFFF); i++) + { + /* Fill out handle info */ + HandleArray->Handle = (SOCKET)writefds->fd_array[i]; + HandleArray->Events = AFD_EVENT_SEND; + + /* Move to the next one */ + HandleArray++; + } + for (i = 0; exceptfds && i < (exceptfds->fd_count & 0xFFFF); i++) + { + /* Fill out handle info */ + HandleArray->Handle = (SOCKET)exceptfds->fd_array[i]; + HandleArray->Events = AFD_EVENT_OOB_RECEIVE | AFD_EVENT_CONNECT_FAIL; + + /* Move to the next one */ + HandleArray++; + } + + /* Check if a timeout was given */ + if (timeout) + { + /* Inifinte Timeout */ + PollInfo->Timeout.u.LowPart = -1; + PollInfo->Timeout.u.HighPart = 0x7FFFFFFF; + } + else + { + /* Calculate microseconds */ + uSec = RtlEnlargedIntegerMultiply(timeout->tv_usec, -10); + + /* Calculate seconds */ + PollInfo->Timeout = RtlEnlargedIntegerMultiply(timeout->tv_sec, + -1 * 1000 * 1000 * 10); + + /* Add microseconds */ + PollInfo->Timeout.QuadPart += uSec.QuadPart; + } + + /* Send IOCTL */ + Status = NtDeviceIoControlFile((HANDLE)PollInfo->Handles[0].Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_SELECT, + PollInfo, + PollBufferSize, + PollInfo, + PollBufferSize); + + /* Check if we have to wait */ + if (Status == STATUS_PENDING) + { + /* Check if we'll call the blocking hook */ + if (!PollInfo->Timeout.QuadPart) BlockType = NO_BLOCKING_HOOK; + + /* Wait for completion */ + SockWaitForSingleObject(ThreadData->EventHandle, + (SOCKET)PollInfo->Handles[0].Handle, + BlockType, + NO_TIMEOUT); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for failure */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* Clear the Structures */ + if(readfds) FD_ZERO(readfds); + if(writefds) FD_ZERO(writefds); + if(exceptfds) FD_ZERO(exceptfds); + + /* Get the handle info again */ + HandleCount = PollInfo->HandleCount; + HandleArray = PollInfo->Handles; + + /* Loop the Handles that got an event */ + for (i = 0; i < HandleCount; i++) + { + /* Check for a match */ + if (HandleArray->Events & AFD_EVENT_RECEIVE) + { + /* Check if it's not already set */ + if (!FD_ISSET((SOCKET)HandleArray->Handle, readfds)) + { + /* Increase Handles with an Event */ + OutCount++; + + /* Set this handle */ + FD_SET((SOCKET)HandleArray->Handle, readfds); + } + } + /* Check for a match */ + if (HandleArray->Events & AFD_EVENT_SEND) + { + /* Check if it's not already set */ + if (!FD_ISSET((SOCKET)HandleArray->Handle, writefds)) + { + /* Increase Handles with an Event */ + OutCount++; + + /* Set this handle */ + FD_SET((SOCKET)HandleArray->Handle, writefds); + } + } + /* Check for a match */ + if (HandleArray->Events & AFD_EVENT_OOB_RECEIVE) + { + /* Check if it's not already set */ + if (!FD_ISSET((SOCKET)HandleArray->Handle, exceptfds)) + { + /* Increase Handles with an Event */ + OutCount++; + + /* Set this handle */ + FD_SET((SOCKET)HandleArray->Handle, exceptfds); + } + } + /* Check for a match */ + if (HandleArray->Events & AFD_EVENT_ACCEPT) + { + /* Check if it's not already set */ + if (!FD_ISSET((SOCKET)HandleArray->Handle, readfds)) + { + /* Increase Handles with an Event */ + OutCount++; + + /* Set this handle */ + FD_SET((SOCKET)HandleArray->Handle, readfds); + } + } + /* Check for a match */ + if (HandleArray->Events & AFD_EVENT_CONNECT) + { + /* Check if it's not already set */ + if (!FD_ISSET((SOCKET)HandleArray->Handle, writefds)) + { + /* Increase Handles with an Event */ + OutCount++; + + /* Set this handle */ + FD_SET((SOCKET)HandleArray->Handle, writefds); + } + } + /* Check for a match */ + if (HandleArray->Events & AFD_EVENT_CONNECT_FAIL) + { + /* Check if it's not already set */ + if (!FD_ISSET((SOCKET)HandleArray->Handle, exceptfds)) + { + /* Increase Handles with an Event */ + OutCount++; + + /* Set this handle */ + FD_SET((SOCKET)HandleArray->Handle, exceptfds); + } + } + /* Check for a match */ + if (HandleArray->Events & AFD_EVENT_DISCONNECT) + { + /* Check if it's not already set */ + if (!FD_ISSET((SOCKET)HandleArray->Handle, readfds)) + { + /* Increase Handles with an Event */ + OutCount++; + + /* Set this handle */ + FD_SET((SOCKET)HandleArray->Handle, readfds); + } + } + /* Check for a match */ + if (HandleArray->Events & AFD_EVENT_ABORT) + { + /* Check if it's not already set */ + if (!FD_ISSET((SOCKET)HandleArray->Handle, readfds)) + { + /* Increase Handles with an Event */ + OutCount++; + + /* Set this handle */ + FD_SET((SOCKET)HandleArray->Handle, readfds); + } + } + /* Check for a match */ + if (HandleArray->Events & AFD_EVENT_CLOSE) + { + /* Check if it's not already set */ + if (!FD_ISSET((SOCKET)HandleArray->Handle, readfds)) + { + /* Increase Handles with an Event */ + OutCount++; + + /* Set this handle */ + FD_SET((SOCKET)HandleArray->Handle, readfds); + } + } + + /* Move to next entry */ + HandleArray++; + } + +error: + + /* Check if we should free the buffer */ + if (PollInfo && (PollInfo != (PVOID)PollBuffer)) + { + /* Free it from the heap */ + RtlFreeHeap(SockPrivateHeap, 0, PollInfo); + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Return error */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return the number of handles */ + return OutCount; +} + diff --git a/dll/win32/mswsock/msafd/send.c b/dll/win32/mswsock/msafd/send.c new file mode 100644 index 00000000000..60f377998be --- /dev/null +++ b/dll/win32/mswsock/msafd/send.c @@ -0,0 +1,2340 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +WSPSend(SOCKET Handle, + LPWSABUF lpBuffers, + DWORD dwBufferCount, + LPDWORD lpNumberOfBytesSent, + DWORD iFlags, + LPWSAOVERLAPPED lpOverlapped, + LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + LPWSATHREADID lpThreadId, + LPINT lpErrno) +{ + PIO_STATUS_BLOCK IoStatusBlock; + IO_STATUS_BLOCK DummyIoStatusBlock; + AFD_SEND_INFO SendInfo; + NTSTATUS Status; + PVOID APCContext; + PVOID ApcFunction; + HANDLE Event; + PWINSOCK_TEB_DATA ThreadData; + PSOCKET_INFORMATION Socket; + INT ErrorCode; + BOOLEAN ReturnValue; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Set up the Receive Structure */ + SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers; + SendInfo.BufferCount = dwBufferCount; + SendInfo.TdiFlags = 0; + SendInfo.AfdFlags = 0; + + /* Set the TDI Flags */ + if (iFlags) + { + /* Check for valid flags */ + if ((iFlags & ~(MSG_OOB | MSG_DONTROUTE | MSG_PARTIAL))) + { + /* Fail */ + ErrorCode = WSAEOPNOTSUPP; + goto error; + } + + /* Check if OOB is being used */ + if (iFlags & MSG_OOB) + { + /* Use Expedited Send for OOB */ + SendInfo.TdiFlags |= TDI_SEND_EXPEDITED; + } + + /* Use Partial Send if enabled */ + if (iFlags & MSG_PARTIAL) SendInfo.TdiFlags |= TDI_SEND_PARTIAL; + } + + /* Verifiy if we should use APC */ + if (!lpOverlapped) + { + /* Not using Overlapped structure, so use normal blocking on event */ + APCContext = NULL; + ApcFunction = NULL; + Event = ThreadData->EventHandle; + IoStatusBlock = &DummyIoStatusBlock; + } + else + { + /* Using apc, check if we have a completion routine */ + if (!lpCompletionRoutine) + { + /* No need for APC */ + APCContext = lpOverlapped; + ApcFunction = NULL; + Event = lpOverlapped->hEvent; + } + else + { + /* Use APC */ + ApcFunction = SockIoCompletion; + APCContext = lpCompletionRoutine; + Event = NULL; + + /* Skip Fast I/O */ + SendInfo.AfdFlags = AFD_SKIP_FIO; + } + + /* Use the overlapped's structure buffer for the I/O Status Block */ + IoStatusBlock = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; + + /* Make this an overlapped I/O in AFD */ + SendInfo.AfdFlags |= AFD_OVERLAPPED; + } + + /* Set is as Pending for now */ + IoStatusBlock->Status = STATUS_PENDING; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile((HANDLE)Handle, + Event, + ApcFunction, + APCContext, + IoStatusBlock, + IOCTL_AFD_SEND, + &SendInfo, + sizeof(SendInfo), + NULL, + 0); + + /* Increase the pending APC Count if we're using an APC */ + if (!NT_ERROR(Status) && ApcFunction) + { + ThreadData->PendingAPCs++; + InterlockedIncrement(&SockProcessPendingAPCCount); + } + + /* Wait for completition if not overlapped */ + if ((Status == STATUS_PENDING) && !(lpOverlapped)) + { + /* Wait for completion */ + ReturnValue = SockWaitForSingleObject(Event, + Handle, + MAYBE_BLOCKING_HOOK, + SEND_TIMEOUT); + + /* Check if the wait was successful */ + if (ReturnValue) + { + /* Get new status */ + Status = IoStatusBlock->Status; + } + else + { + /* Cancel the I/O */ + SockCancelIo(Handle); + Status = STATUS_IO_TIMEOUT; + } + } + + /* Check status */ + switch (Status) + { + /* Success */ + case STATUS_SUCCESS: + break; + + /* Pending I/O */ + case STATUS_PENDING: + ErrorCode = WSA_IO_PENDING; + goto error; + + /* Other NT Error */ + default: + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + break; + } + + /* Return the number of bytes sent */ + *lpNumberOfBytesSent = PtrToUlong(IoStatusBlock->Information); + +error: + + /* Check if async select was active and this blocked */ + if (SockAsyncSelectCalled && (ErrorCode == WSAEWOULDBLOCK)) + { + /* Get the socket */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (Socket) + { + /* Lock it */ + EnterCriticalSection(&Socket->Lock); + + /* Re-enable the regular write event */ + SockReenableAsyncSelectEvent(Socket, FD_WRITE); + + /* Unlock and dereference socket */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + } + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +INT +WSPAPI +WSPSendTo(SOCKET Handle, + LPWSABUF lpBuffers, + DWORD dwBufferCount, + LPDWORD lpNumberOfBytesSent, + DWORD iFlags, + const struct sockaddr *SocketAddress, + INT SocketAddressLength, + LPWSAOVERLAPPED lpOverlapped, + LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + LPWSATHREADID lpThreadId, + LPINT lpErrno) +{ + PIO_STATUS_BLOCK IoStatusBlock; + IO_STATUS_BLOCK DummyIoStatusBlock; + AFD_SEND_INFO_UDP SendInfo; + NTSTATUS Status; + PVOID APCContext; + PVOID ApcFunction; + HANDLE Event; + PWINSOCK_TEB_DATA ThreadData; + PSOCKET_INFORMATION Socket; + INT ErrorCode; + INT ReturnValue; + CHAR AddressBuffer[FIELD_OFFSET(TDI_ADDRESS_INFO, Address) + + MAX_TDI_ADDRESS_LENGTH]; + PTRANSPORT_ADDRESS TdiAddress = (PTRANSPORT_ADDRESS)AddressBuffer; + ULONG TdiAddressSize; + INT SockaddrLength; + PSOCKADDR Sockaddr; + SOCKADDR_INFO SocketInfo; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* + * Check if this isn't a datagram socket or if it's a connected socket + * without an address + */ + if (!MSAFD_IS_DGRAM_SOCK(Socket) || + ((Socket->SharedData.State == SocketConnected) && + (!SocketAddress || !SocketAddressLength))) + { + /* Call WSPSend instead */ + SockDereferenceSocket(Socket); + return WSPSend(Handle, + lpBuffers, + dwBufferCount, + lpNumberOfBytesSent, + iFlags, + lpOverlapped, + lpCompletionRoutine, + lpThreadId, + lpErrno); + } + + /* If the socket isn't connected, we need an address*/ + if ((Socket->SharedData.State != SocketConnected) && (!SocketAddress)) + { + /* Fail */ + ErrorCode = WSAENOTCONN; + goto error; + } + + /* Validate length */ + if (SocketAddressLength < Socket->HelperData->MaxWSAddressLength) + { + /* Fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* Verify flags */ + if (iFlags & ~MSG_DONTROUTE) + { + /* Fail */ + ErrorCode = WSAEOPNOTSUPP; + goto error; + } + + /* Make sure send shutdown isn't active */ + if (Socket->SharedData.SendShutdown) + { + /* Fail */ + ErrorCode = WSAESHUTDOWN; + goto error; + } + + /* Make sure address families match */ + if (Socket->SharedData.AddressFamily != SocketAddress->sa_family) + { + /* Fail */ + ErrorCode = WSAEOPNOTSUPP; + goto error; + } + + /* Check if broadcast is enabled */ + if (!Socket->SharedData.Broadcast) + { + /* The caller might want to enable it; get the Sockaddr type */ + ErrorCode = Socket->HelperData->WSHGetSockaddrType((PSOCKADDR)SocketAddress, + SocketAddressLength, + &SocketInfo); + if (ErrorCode != NO_ERROR) goto error; + + /* Check if this is a broadcast attempt */ + if (SocketInfo.AddressInfo == SockaddrAddressInfoBroadcast) + { + /* The socket won't allow it */ + ErrorCode = WSAEACCES; + goto error; + } + } + + /* Check if this socket isn't bound yet */ + if (Socket->SharedData.State == SocketOpen) + { + /* Check if we can request the wildcard address */ + if (Socket->HelperData->WSHGetWildcardSockaddr) + { + /* Allocate a new Sockaddr */ + SockaddrLength = Socket->HelperData->MaxWSAddressLength; + Sockaddr = SockAllocateHeapRoutine(SockPrivateHeap, 0, SockaddrLength); + if (!Sockaddr) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + + /* Get the wildcard sockaddr */ + ErrorCode = Socket->HelperData->WSHGetWildcardSockaddr(Socket->HelperContext, + Sockaddr, + &SockaddrLength); + if (ErrorCode != NO_ERROR) + { + /* Free memory and fail */ + RtlFreeHeap(SockPrivateHeap, 0, Sockaddr); + goto error; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* Make sure it's still unbound */ + if (Socket->SharedData.State == SocketOpen) + { + /* Bind it */ + ReturnValue = WSPBind(Handle, + Sockaddr, + SockaddrLength, + &ErrorCode); + } + else + { + /* It's bound now, fake success */ + ReturnValue = NO_ERROR; + } + + /* Release the lock and free memory */ + LeaveCriticalSection(&Socket->Lock); + RtlFreeHeap(SockPrivateHeap, 0, Sockaddr); + + /* Check if we failed */ + if (ReturnValue == SOCKET_ERROR) goto error; + } + else + { + /* Unbound socket, but can't get the wildcard. Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + } + + /* Check how long the TDI Address is */ + TdiAddressSize = Socket->HelperData->MaxTDIAddressLength; + + /* See if it can fit in the stack */ + if (TdiAddressSize > sizeof(AddressBuffer)) + { + /* Allocate from heap */ + TdiAddress = SockAllocateHeapRoutine(SockPrivateHeap, 0, TdiAddressSize); + if (!TdiAddress) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + } + + /* Build the TDI Address */ + ErrorCode = SockBuildTdiAddress(TdiAddress, + (PSOCKADDR)SocketAddress, + min(SocketAddressLength, + Socket->HelperData->MaxWSAddressLength)); + if (ErrorCode != NO_ERROR) goto error; + + /* Set up the Send Structure */ + SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers; + SendInfo.BufferCount = dwBufferCount; + SendInfo.AfdFlags = 0; + SendInfo.TdiConnection.RemoteAddress = TdiAddress; + SendInfo.TdiConnection.RemoteAddressLength = TdiAddressSize; + + /* Verifiy if we should use APC */ + if (!lpOverlapped) + { + /* Not using Overlapped structure, so use normal blocking on event */ + APCContext = NULL; + ApcFunction = NULL; + Event = ThreadData->EventHandle; + IoStatusBlock = &DummyIoStatusBlock; + } + else + { + /* Using apc, check if we have a completion routine */ + if (!lpCompletionRoutine) + { + /* No need for APC */ + APCContext = lpOverlapped; + ApcFunction = NULL; + Event = lpOverlapped->hEvent; + } + else + { + /* Use APC */ + ApcFunction = SockIoCompletion; + APCContext = lpCompletionRoutine; + Event = NULL; + + /* Skip Fast I/O */ + SendInfo.AfdFlags = AFD_SKIP_FIO; + } + + /* Use the overlapped's structure buffer for the I/O Status Block */ + IoStatusBlock = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; + + /* Make this an overlapped I/O in AFD */ + SendInfo.AfdFlags |= AFD_OVERLAPPED; + } + + /* Set is as Pending for now */ + IoStatusBlock->Status = STATUS_PENDING; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + Event, + ApcFunction, + APCContext, + IoStatusBlock, + IOCTL_AFD_SEND_DATAGRAM, + &SendInfo, + sizeof(SendInfo), + NULL, + 0); + + /* Increase the pending APC Count if we're using an APC */ + if (!NT_ERROR(Status) && ApcFunction) + { + ThreadData->PendingAPCs++; + InterlockedIncrement(&SockProcessPendingAPCCount); + } + + /* Wait for completition if not overlapped */ + if ((Status == STATUS_PENDING) && !(lpOverlapped)) + { + /* Wait for completion */ + ReturnValue = SockWaitForSingleObject(Event, + Handle, + MAYBE_BLOCKING_HOOK, + SEND_TIMEOUT); + + /* Check if the wait was successful */ + if (ReturnValue) + { + /* Get new status */ + Status = IoStatusBlock->Status; + } + else + { + /* Cancel the I/O */ + SockCancelIo(Handle); + Status = STATUS_IO_TIMEOUT; + } + } + + /* Check status */ + switch (Status) + { + /* Success */ + case STATUS_SUCCESS: + break; + + /* Pending I/O */ + case STATUS_PENDING: + ErrorCode = WSA_IO_PENDING; + goto error; + + /* Other NT Error */ + default: + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + break; + } + + /* Return the number of bytes sent */ + *lpNumberOfBytesSent = PtrToUlong(IoStatusBlock->Information); + +error: + + /* Check if we have a socket */ + if (Socket) + { + /* Check if async select was active and this blocked */ + if (SockAsyncSelectCalled && (ErrorCode == WSAEWOULDBLOCK)) + { + /* Lock it */ + EnterCriticalSection(&Socket->Lock); + + /* Re-enable the regular write event */ + SockReenableAsyncSelectEvent(Socket, FD_WRITE); + + /* Unlock socket */ + LeaveCriticalSection(&Socket->Lock); + } + + /* Dereference socket */ + SockDereferenceSocket(Socket); + } + + /* Check if we should free the TDI Address */ + if (TdiAddress && (TdiAddress != (PVOID)AddressBuffer)) + { + /* Free it from the heap */ + RtlFreeHeap(SockPrivateHeap, 0, TdiAddress); + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +WSPSend(SOCKET Handle, + LPWSABUF lpBuffers, + DWORD dwBufferCount, + LPDWORD lpNumberOfBytesSent, + DWORD iFlags, + LPWSAOVERLAPPED lpOverlapped, + LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + LPWSATHREADID lpThreadId, + LPINT lpErrno) +{ + PIO_STATUS_BLOCK IoStatusBlock; + IO_STATUS_BLOCK DummyIoStatusBlock; + AFD_SEND_INFO SendInfo; + NTSTATUS Status; + PVOID APCContext; + PVOID ApcFunction; + HANDLE Event; + PWINSOCK_TEB_DATA ThreadData; + PSOCKET_INFORMATION Socket; + INT ErrorCode; + BOOLEAN ReturnValue; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Set up the Receive Structure */ + SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers; + SendInfo.BufferCount = dwBufferCount; + SendInfo.TdiFlags = 0; + SendInfo.AfdFlags = 0; + + /* Set the TDI Flags */ + if (iFlags) + { + /* Check for valid flags */ + if ((iFlags & ~(MSG_OOB | MSG_DONTROUTE | MSG_PARTIAL))) + { + /* Fail */ + ErrorCode = WSAEOPNOTSUPP; + goto error; + } + + /* Check if OOB is being used */ + if (iFlags & MSG_OOB) + { + /* Use Expedited Send for OOB */ + SendInfo.TdiFlags |= TDI_SEND_EXPEDITED; + } + + /* Use Partial Send if enabled */ + if (iFlags & MSG_PARTIAL) SendInfo.TdiFlags |= TDI_SEND_PARTIAL; + } + + /* Verifiy if we should use APC */ + if (!lpOverlapped) + { + /* Not using Overlapped structure, so use normal blocking on event */ + APCContext = NULL; + ApcFunction = NULL; + Event = ThreadData->EventHandle; + IoStatusBlock = &DummyIoStatusBlock; + } + else + { + /* Using apc, check if we have a completion routine */ + if (!lpCompletionRoutine) + { + /* No need for APC */ + APCContext = lpOverlapped; + ApcFunction = NULL; + Event = lpOverlapped->hEvent; + } + else + { + /* Use APC */ + ApcFunction = SockIoCompletion; + APCContext = lpCompletionRoutine; + Event = NULL; + + /* Skip Fast I/O */ + SendInfo.AfdFlags = AFD_SKIP_FIO; + } + + /* Use the overlapped's structure buffer for the I/O Status Block */ + IoStatusBlock = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; + + /* Make this an overlapped I/O in AFD */ + SendInfo.AfdFlags |= AFD_OVERLAPPED; + } + + /* Set is as Pending for now */ + IoStatusBlock->Status = STATUS_PENDING; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile((HANDLE)Handle, + Event, + ApcFunction, + APCContext, + IoStatusBlock, + IOCTL_AFD_SEND, + &SendInfo, + sizeof(SendInfo), + NULL, + 0); + + /* Increase the pending APC Count if we're using an APC */ + if (!NT_ERROR(Status) && ApcFunction) + { + ThreadData->PendingAPCs++; + InterlockedIncrement(&SockProcessPendingAPCCount); + } + + /* Wait for completition if not overlapped */ + if ((Status == STATUS_PENDING) && !(lpOverlapped)) + { + /* Wait for completion */ + ReturnValue = SockWaitForSingleObject(Event, + Handle, + MAYBE_BLOCKING_HOOK, + SEND_TIMEOUT); + + /* Check if the wait was successful */ + if (ReturnValue) + { + /* Get new status */ + Status = IoStatusBlock->Status; + } + else + { + /* Cancel the I/O */ + SockCancelIo(Handle); + Status = STATUS_IO_TIMEOUT; + } + } + + /* Check status */ + switch (Status) + { + /* Success */ + case STATUS_SUCCESS: + break; + + /* Pending I/O */ + case STATUS_PENDING: + ErrorCode = WSA_IO_PENDING; + goto error; + + /* Other NT Error */ + default: + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + break; + } + + /* Return the number of bytes sent */ + *lpNumberOfBytesSent = PtrToUlong(IoStatusBlock->Information); + +error: + + /* Check if async select was active and this blocked */ + if (SockAsyncSelectCalled && (ErrorCode == WSAEWOULDBLOCK)) + { + /* Get the socket */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (Socket) + { + /* Lock it */ + EnterCriticalSection(&Socket->Lock); + + /* Re-enable the regular write event */ + SockReenableAsyncSelectEvent(Socket, FD_WRITE); + + /* Unlock and dereference socket */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + } + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +INT +WSPAPI +WSPSendTo(SOCKET Handle, + LPWSABUF lpBuffers, + DWORD dwBufferCount, + LPDWORD lpNumberOfBytesSent, + DWORD iFlags, + const struct sockaddr *SocketAddress, + INT SocketAddressLength, + LPWSAOVERLAPPED lpOverlapped, + LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + LPWSATHREADID lpThreadId, + LPINT lpErrno) +{ + PIO_STATUS_BLOCK IoStatusBlock; + IO_STATUS_BLOCK DummyIoStatusBlock; + AFD_SEND_INFO_UDP SendInfo; + NTSTATUS Status; + PVOID APCContext; + PVOID ApcFunction; + HANDLE Event; + PWINSOCK_TEB_DATA ThreadData; + PSOCKET_INFORMATION Socket; + INT ErrorCode; + INT ReturnValue; + CHAR AddressBuffer[FIELD_OFFSET(TDI_ADDRESS_INFO, Address) + + MAX_TDI_ADDRESS_LENGTH]; + PTRANSPORT_ADDRESS TdiAddress = (PTRANSPORT_ADDRESS)AddressBuffer; + ULONG TdiAddressSize; + INT SockaddrLength; + PSOCKADDR Sockaddr; + SOCKADDR_INFO SocketInfo; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* + * Check if this isn't a datagram socket or if it's a connected socket + * without an address + */ + if (!MSAFD_IS_DGRAM_SOCK(Socket) || + ((Socket->SharedData.State == SocketConnected) && + (!SocketAddress || !SocketAddressLength))) + { + /* Call WSPSend instead */ + SockDereferenceSocket(Socket); + return WSPSend(Handle, + lpBuffers, + dwBufferCount, + lpNumberOfBytesSent, + iFlags, + lpOverlapped, + lpCompletionRoutine, + lpThreadId, + lpErrno); + } + + /* If the socket isn't connected, we need an address*/ + if ((Socket->SharedData.State != SocketConnected) && (!SocketAddress)) + { + /* Fail */ + ErrorCode = WSAENOTCONN; + goto error; + } + + /* Validate length */ + if (SocketAddressLength < Socket->HelperData->MaxWSAddressLength) + { + /* Fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* Verify flags */ + if (iFlags & ~MSG_DONTROUTE) + { + /* Fail */ + ErrorCode = WSAEOPNOTSUPP; + goto error; + } + + /* Make sure send shutdown isn't active */ + if (Socket->SharedData.SendShutdown) + { + /* Fail */ + ErrorCode = WSAESHUTDOWN; + goto error; + } + + /* Make sure address families match */ + if (Socket->SharedData.AddressFamily != SocketAddress->sa_family) + { + /* Fail */ + ErrorCode = WSAEOPNOTSUPP; + goto error; + } + + /* Check if broadcast is enabled */ + if (!Socket->SharedData.Broadcast) + { + /* The caller might want to enable it; get the Sockaddr type */ + ErrorCode = Socket->HelperData->WSHGetSockaddrType((PSOCKADDR)SocketAddress, + SocketAddressLength, + &SocketInfo); + if (ErrorCode != NO_ERROR) goto error; + + /* Check if this is a broadcast attempt */ + if (SocketInfo.AddressInfo == SockaddrAddressInfoBroadcast) + { + /* The socket won't allow it */ + ErrorCode = WSAEACCES; + goto error; + } + } + + /* Check if this socket isn't bound yet */ + if (Socket->SharedData.State == SocketOpen) + { + /* Check if we can request the wildcard address */ + if (Socket->HelperData->WSHGetWildcardSockaddr) + { + /* Allocate a new Sockaddr */ + SockaddrLength = Socket->HelperData->MaxWSAddressLength; + Sockaddr = SockAllocateHeapRoutine(SockPrivateHeap, 0, SockaddrLength); + if (!Sockaddr) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + + /* Get the wildcard sockaddr */ + ErrorCode = Socket->HelperData->WSHGetWildcardSockaddr(Socket->HelperContext, + Sockaddr, + &SockaddrLength); + if (ErrorCode != NO_ERROR) + { + /* Free memory and fail */ + RtlFreeHeap(SockPrivateHeap, 0, Sockaddr); + goto error; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* Make sure it's still unbound */ + if (Socket->SharedData.State == SocketOpen) + { + /* Bind it */ + ReturnValue = WSPBind(Handle, + Sockaddr, + SockaddrLength, + &ErrorCode); + } + else + { + /* It's bound now, fake success */ + ReturnValue = NO_ERROR; + } + + /* Release the lock and free memory */ + LeaveCriticalSection(&Socket->Lock); + RtlFreeHeap(SockPrivateHeap, 0, Sockaddr); + + /* Check if we failed */ + if (ReturnValue == SOCKET_ERROR) goto error; + } + else + { + /* Unbound socket, but can't get the wildcard. Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + } + + /* Check how long the TDI Address is */ + TdiAddressSize = Socket->HelperData->MaxTDIAddressLength; + + /* See if it can fit in the stack */ + if (TdiAddressSize > sizeof(AddressBuffer)) + { + /* Allocate from heap */ + TdiAddress = SockAllocateHeapRoutine(SockPrivateHeap, 0, TdiAddressSize); + if (!TdiAddress) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + } + + /* Build the TDI Address */ + ErrorCode = SockBuildTdiAddress(TdiAddress, + (PSOCKADDR)SocketAddress, + min(SocketAddressLength, + Socket->HelperData->MaxWSAddressLength)); + if (ErrorCode != NO_ERROR) goto error; + + /* Set up the Send Structure */ + SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers; + SendInfo.BufferCount = dwBufferCount; + SendInfo.AfdFlags = 0; + SendInfo.TdiConnection.RemoteAddress = TdiAddress; + SendInfo.TdiConnection.RemoteAddressLength = TdiAddressSize; + + /* Verifiy if we should use APC */ + if (!lpOverlapped) + { + /* Not using Overlapped structure, so use normal blocking on event */ + APCContext = NULL; + ApcFunction = NULL; + Event = ThreadData->EventHandle; + IoStatusBlock = &DummyIoStatusBlock; + } + else + { + /* Using apc, check if we have a completion routine */ + if (!lpCompletionRoutine) + { + /* No need for APC */ + APCContext = lpOverlapped; + ApcFunction = NULL; + Event = lpOverlapped->hEvent; + } + else + { + /* Use APC */ + ApcFunction = SockIoCompletion; + APCContext = lpCompletionRoutine; + Event = NULL; + + /* Skip Fast I/O */ + SendInfo.AfdFlags = AFD_SKIP_FIO; + } + + /* Use the overlapped's structure buffer for the I/O Status Block */ + IoStatusBlock = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; + + /* Make this an overlapped I/O in AFD */ + SendInfo.AfdFlags |= AFD_OVERLAPPED; + } + + /* Set is as Pending for now */ + IoStatusBlock->Status = STATUS_PENDING; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + Event, + ApcFunction, + APCContext, + IoStatusBlock, + IOCTL_AFD_SEND_DATAGRAM, + &SendInfo, + sizeof(SendInfo), + NULL, + 0); + + /* Increase the pending APC Count if we're using an APC */ + if (!NT_ERROR(Status) && ApcFunction) + { + ThreadData->PendingAPCs++; + InterlockedIncrement(&SockProcessPendingAPCCount); + } + + /* Wait for completition if not overlapped */ + if ((Status == STATUS_PENDING) && !(lpOverlapped)) + { + /* Wait for completion */ + ReturnValue = SockWaitForSingleObject(Event, + Handle, + MAYBE_BLOCKING_HOOK, + SEND_TIMEOUT); + + /* Check if the wait was successful */ + if (ReturnValue) + { + /* Get new status */ + Status = IoStatusBlock->Status; + } + else + { + /* Cancel the I/O */ + SockCancelIo(Handle); + Status = STATUS_IO_TIMEOUT; + } + } + + /* Check status */ + switch (Status) + { + /* Success */ + case STATUS_SUCCESS: + break; + + /* Pending I/O */ + case STATUS_PENDING: + ErrorCode = WSA_IO_PENDING; + goto error; + + /* Other NT Error */ + default: + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + break; + } + + /* Return the number of bytes sent */ + *lpNumberOfBytesSent = PtrToUlong(IoStatusBlock->Information); + +error: + + /* Check if we have a socket */ + if (Socket) + { + /* Check if async select was active and this blocked */ + if (SockAsyncSelectCalled && (ErrorCode == WSAEWOULDBLOCK)) + { + /* Lock it */ + EnterCriticalSection(&Socket->Lock); + + /* Re-enable the regular write event */ + SockReenableAsyncSelectEvent(Socket, FD_WRITE); + + /* Unlock socket */ + LeaveCriticalSection(&Socket->Lock); + } + + /* Dereference socket */ + SockDereferenceSocket(Socket); + } + + /* Check if we should free the TDI Address */ + if (TdiAddress && (TdiAddress != (PVOID)AddressBuffer)) + { + /* Free it from the heap */ + RtlFreeHeap(SockPrivateHeap, 0, TdiAddress); + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +WSPSend(SOCKET Handle, + LPWSABUF lpBuffers, + DWORD dwBufferCount, + LPDWORD lpNumberOfBytesSent, + DWORD iFlags, + LPWSAOVERLAPPED lpOverlapped, + LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + LPWSATHREADID lpThreadId, + LPINT lpErrno) +{ + PIO_STATUS_BLOCK IoStatusBlock; + IO_STATUS_BLOCK DummyIoStatusBlock; + AFD_SEND_INFO SendInfo; + NTSTATUS Status; + PVOID APCContext; + PVOID ApcFunction; + HANDLE Event; + PWINSOCK_TEB_DATA ThreadData; + PSOCKET_INFORMATION Socket; + INT ErrorCode; + BOOLEAN ReturnValue; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Set up the Receive Structure */ + SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers; + SendInfo.BufferCount = dwBufferCount; + SendInfo.TdiFlags = 0; + SendInfo.AfdFlags = 0; + + /* Set the TDI Flags */ + if (iFlags) + { + /* Check for valid flags */ + if ((iFlags & ~(MSG_OOB | MSG_DONTROUTE | MSG_PARTIAL))) + { + /* Fail */ + ErrorCode = WSAEOPNOTSUPP; + goto error; + } + + /* Check if OOB is being used */ + if (iFlags & MSG_OOB) + { + /* Use Expedited Send for OOB */ + SendInfo.TdiFlags |= TDI_SEND_EXPEDITED; + } + + /* Use Partial Send if enabled */ + if (iFlags & MSG_PARTIAL) SendInfo.TdiFlags |= TDI_SEND_PARTIAL; + } + + /* Verifiy if we should use APC */ + if (!lpOverlapped) + { + /* Not using Overlapped structure, so use normal blocking on event */ + APCContext = NULL; + ApcFunction = NULL; + Event = ThreadData->EventHandle; + IoStatusBlock = &DummyIoStatusBlock; + } + else + { + /* Using apc, check if we have a completion routine */ + if (!lpCompletionRoutine) + { + /* No need for APC */ + APCContext = lpOverlapped; + ApcFunction = NULL; + Event = lpOverlapped->hEvent; + } + else + { + /* Use APC */ + ApcFunction = SockIoCompletion; + APCContext = lpCompletionRoutine; + Event = NULL; + + /* Skip Fast I/O */ + SendInfo.AfdFlags = AFD_SKIP_FIO; + } + + /* Use the overlapped's structure buffer for the I/O Status Block */ + IoStatusBlock = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; + + /* Make this an overlapped I/O in AFD */ + SendInfo.AfdFlags |= AFD_OVERLAPPED; + } + + /* Set is as Pending for now */ + IoStatusBlock->Status = STATUS_PENDING; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile((HANDLE)Handle, + Event, + ApcFunction, + APCContext, + IoStatusBlock, + IOCTL_AFD_SEND, + &SendInfo, + sizeof(SendInfo), + NULL, + 0); + + /* Increase the pending APC Count if we're using an APC */ + if (!NT_ERROR(Status) && ApcFunction) + { + ThreadData->PendingAPCs++; + InterlockedIncrement(&SockProcessPendingAPCCount); + } + + /* Wait for completition if not overlapped */ + if ((Status == STATUS_PENDING) && !(lpOverlapped)) + { + /* Wait for completion */ + ReturnValue = SockWaitForSingleObject(Event, + Handle, + MAYBE_BLOCKING_HOOK, + SEND_TIMEOUT); + + /* Check if the wait was successful */ + if (ReturnValue) + { + /* Get new status */ + Status = IoStatusBlock->Status; + } + else + { + /* Cancel the I/O */ + SockCancelIo(Handle); + Status = STATUS_IO_TIMEOUT; + } + } + + /* Check status */ + switch (Status) + { + /* Success */ + case STATUS_SUCCESS: + break; + + /* Pending I/O */ + case STATUS_PENDING: + ErrorCode = WSA_IO_PENDING; + goto error; + + /* Other NT Error */ + default: + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + break; + } + + /* Return the number of bytes sent */ + *lpNumberOfBytesSent = PtrToUlong(IoStatusBlock->Information); + +error: + + /* Check if async select was active and this blocked */ + if (SockAsyncSelectCalled && (ErrorCode == WSAEWOULDBLOCK)) + { + /* Get the socket */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (Socket) + { + /* Lock it */ + EnterCriticalSection(&Socket->Lock); + + /* Re-enable the regular write event */ + SockReenableAsyncSelectEvent(Socket, FD_WRITE); + + /* Unlock and dereference socket */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + } + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +INT +WSPAPI +WSPSendTo(SOCKET Handle, + LPWSABUF lpBuffers, + DWORD dwBufferCount, + LPDWORD lpNumberOfBytesSent, + DWORD iFlags, + const struct sockaddr *SocketAddress, + INT SocketAddressLength, + LPWSAOVERLAPPED lpOverlapped, + LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + LPWSATHREADID lpThreadId, + LPINT lpErrno) +{ + PIO_STATUS_BLOCK IoStatusBlock; + IO_STATUS_BLOCK DummyIoStatusBlock; + AFD_SEND_INFO_UDP SendInfo; + NTSTATUS Status; + PVOID APCContext; + PVOID ApcFunction; + HANDLE Event; + PWINSOCK_TEB_DATA ThreadData; + PSOCKET_INFORMATION Socket; + INT ErrorCode; + INT ReturnValue; + CHAR AddressBuffer[FIELD_OFFSET(TDI_ADDRESS_INFO, Address) + + MAX_TDI_ADDRESS_LENGTH]; + PTRANSPORT_ADDRESS TdiAddress = (PTRANSPORT_ADDRESS)AddressBuffer; + ULONG TdiAddressSize; + INT SockaddrLength; + PSOCKADDR Sockaddr; + SOCKADDR_INFO SocketInfo; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* + * Check if this isn't a datagram socket or if it's a connected socket + * without an address + */ + if (!MSAFD_IS_DGRAM_SOCK(Socket) || + ((Socket->SharedData.State == SocketConnected) && + (!SocketAddress || !SocketAddressLength))) + { + /* Call WSPSend instead */ + SockDereferenceSocket(Socket); + return WSPSend(Handle, + lpBuffers, + dwBufferCount, + lpNumberOfBytesSent, + iFlags, + lpOverlapped, + lpCompletionRoutine, + lpThreadId, + lpErrno); + } + + /* If the socket isn't connected, we need an address*/ + if ((Socket->SharedData.State != SocketConnected) && (!SocketAddress)) + { + /* Fail */ + ErrorCode = WSAENOTCONN; + goto error; + } + + /* Validate length */ + if (SocketAddressLength < Socket->HelperData->MaxWSAddressLength) + { + /* Fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* Verify flags */ + if (iFlags & ~MSG_DONTROUTE) + { + /* Fail */ + ErrorCode = WSAEOPNOTSUPP; + goto error; + } + + /* Make sure send shutdown isn't active */ + if (Socket->SharedData.SendShutdown) + { + /* Fail */ + ErrorCode = WSAESHUTDOWN; + goto error; + } + + /* Make sure address families match */ + if (Socket->SharedData.AddressFamily != SocketAddress->sa_family) + { + /* Fail */ + ErrorCode = WSAEOPNOTSUPP; + goto error; + } + + /* Check if broadcast is enabled */ + if (!Socket->SharedData.Broadcast) + { + /* The caller might want to enable it; get the Sockaddr type */ + ErrorCode = Socket->HelperData->WSHGetSockaddrType((PSOCKADDR)SocketAddress, + SocketAddressLength, + &SocketInfo); + if (ErrorCode != NO_ERROR) goto error; + + /* Check if this is a broadcast attempt */ + if (SocketInfo.AddressInfo == SockaddrAddressInfoBroadcast) + { + /* The socket won't allow it */ + ErrorCode = WSAEACCES; + goto error; + } + } + + /* Check if this socket isn't bound yet */ + if (Socket->SharedData.State == SocketOpen) + { + /* Check if we can request the wildcard address */ + if (Socket->HelperData->WSHGetWildcardSockaddr) + { + /* Allocate a new Sockaddr */ + SockaddrLength = Socket->HelperData->MaxWSAddressLength; + Sockaddr = SockAllocateHeapRoutine(SockPrivateHeap, 0, SockaddrLength); + if (!Sockaddr) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + + /* Get the wildcard sockaddr */ + ErrorCode = Socket->HelperData->WSHGetWildcardSockaddr(Socket->HelperContext, + Sockaddr, + &SockaddrLength); + if (ErrorCode != NO_ERROR) + { + /* Free memory and fail */ + RtlFreeHeap(SockPrivateHeap, 0, Sockaddr); + goto error; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* Make sure it's still unbound */ + if (Socket->SharedData.State == SocketOpen) + { + /* Bind it */ + ReturnValue = WSPBind(Handle, + Sockaddr, + SockaddrLength, + &ErrorCode); + } + else + { + /* It's bound now, fake success */ + ReturnValue = NO_ERROR; + } + + /* Release the lock and free memory */ + LeaveCriticalSection(&Socket->Lock); + RtlFreeHeap(SockPrivateHeap, 0, Sockaddr); + + /* Check if we failed */ + if (ReturnValue == SOCKET_ERROR) goto error; + } + else + { + /* Unbound socket, but can't get the wildcard. Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + } + + /* Check how long the TDI Address is */ + TdiAddressSize = Socket->HelperData->MaxTDIAddressLength; + + /* See if it can fit in the stack */ + if (TdiAddressSize > sizeof(AddressBuffer)) + { + /* Allocate from heap */ + TdiAddress = SockAllocateHeapRoutine(SockPrivateHeap, 0, TdiAddressSize); + if (!TdiAddress) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + } + + /* Build the TDI Address */ + ErrorCode = SockBuildTdiAddress(TdiAddress, + (PSOCKADDR)SocketAddress, + min(SocketAddressLength, + Socket->HelperData->MaxWSAddressLength)); + if (ErrorCode != NO_ERROR) goto error; + + /* Set up the Send Structure */ + SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers; + SendInfo.BufferCount = dwBufferCount; + SendInfo.AfdFlags = 0; + SendInfo.TdiConnection.RemoteAddress = TdiAddress; + SendInfo.TdiConnection.RemoteAddressLength = TdiAddressSize; + + /* Verifiy if we should use APC */ + if (!lpOverlapped) + { + /* Not using Overlapped structure, so use normal blocking on event */ + APCContext = NULL; + ApcFunction = NULL; + Event = ThreadData->EventHandle; + IoStatusBlock = &DummyIoStatusBlock; + } + else + { + /* Using apc, check if we have a completion routine */ + if (!lpCompletionRoutine) + { + /* No need for APC */ + APCContext = lpOverlapped; + ApcFunction = NULL; + Event = lpOverlapped->hEvent; + } + else + { + /* Use APC */ + ApcFunction = SockIoCompletion; + APCContext = lpCompletionRoutine; + Event = NULL; + + /* Skip Fast I/O */ + SendInfo.AfdFlags = AFD_SKIP_FIO; + } + + /* Use the overlapped's structure buffer for the I/O Status Block */ + IoStatusBlock = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; + + /* Make this an overlapped I/O in AFD */ + SendInfo.AfdFlags |= AFD_OVERLAPPED; + } + + /* Set is as Pending for now */ + IoStatusBlock->Status = STATUS_PENDING; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + Event, + ApcFunction, + APCContext, + IoStatusBlock, + IOCTL_AFD_SEND_DATAGRAM, + &SendInfo, + sizeof(SendInfo), + NULL, + 0); + + /* Increase the pending APC Count if we're using an APC */ + if (!NT_ERROR(Status) && ApcFunction) + { + ThreadData->PendingAPCs++; + InterlockedIncrement(&SockProcessPendingAPCCount); + } + + /* Wait for completition if not overlapped */ + if ((Status == STATUS_PENDING) && !(lpOverlapped)) + { + /* Wait for completion */ + ReturnValue = SockWaitForSingleObject(Event, + Handle, + MAYBE_BLOCKING_HOOK, + SEND_TIMEOUT); + + /* Check if the wait was successful */ + if (ReturnValue) + { + /* Get new status */ + Status = IoStatusBlock->Status; + } + else + { + /* Cancel the I/O */ + SockCancelIo(Handle); + Status = STATUS_IO_TIMEOUT; + } + } + + /* Check status */ + switch (Status) + { + /* Success */ + case STATUS_SUCCESS: + break; + + /* Pending I/O */ + case STATUS_PENDING: + ErrorCode = WSA_IO_PENDING; + goto error; + + /* Other NT Error */ + default: + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + break; + } + + /* Return the number of bytes sent */ + *lpNumberOfBytesSent = PtrToUlong(IoStatusBlock->Information); + +error: + + /* Check if we have a socket */ + if (Socket) + { + /* Check if async select was active and this blocked */ + if (SockAsyncSelectCalled && (ErrorCode == WSAEWOULDBLOCK)) + { + /* Lock it */ + EnterCriticalSection(&Socket->Lock); + + /* Re-enable the regular write event */ + SockReenableAsyncSelectEvent(Socket, FD_WRITE); + + /* Unlock socket */ + LeaveCriticalSection(&Socket->Lock); + } + + /* Dereference socket */ + SockDereferenceSocket(Socket); + } + + /* Check if we should free the TDI Address */ + if (TdiAddress && (TdiAddress != (PVOID)AddressBuffer)) + { + /* Free it from the heap */ + RtlFreeHeap(SockPrivateHeap, 0, TdiAddress); + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +WSPSend(SOCKET Handle, + LPWSABUF lpBuffers, + DWORD dwBufferCount, + LPDWORD lpNumberOfBytesSent, + DWORD iFlags, + LPWSAOVERLAPPED lpOverlapped, + LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + LPWSATHREADID lpThreadId, + LPINT lpErrno) +{ + PIO_STATUS_BLOCK IoStatusBlock; + IO_STATUS_BLOCK DummyIoStatusBlock; + AFD_SEND_INFO SendInfo; + NTSTATUS Status; + PVOID APCContext; + PVOID ApcFunction; + HANDLE Event; + PWINSOCK_TEB_DATA ThreadData; + PSOCKET_INFORMATION Socket; + INT ErrorCode; + BOOLEAN ReturnValue; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Set up the Receive Structure */ + SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers; + SendInfo.BufferCount = dwBufferCount; + SendInfo.TdiFlags = 0; + SendInfo.AfdFlags = 0; + + /* Set the TDI Flags */ + if (iFlags) + { + /* Check for valid flags */ + if ((iFlags & ~(MSG_OOB | MSG_DONTROUTE | MSG_PARTIAL))) + { + /* Fail */ + ErrorCode = WSAEOPNOTSUPP; + goto error; + } + + /* Check if OOB is being used */ + if (iFlags & MSG_OOB) + { + /* Use Expedited Send for OOB */ + SendInfo.TdiFlags |= TDI_SEND_EXPEDITED; + } + + /* Use Partial Send if enabled */ + if (iFlags & MSG_PARTIAL) SendInfo.TdiFlags |= TDI_SEND_PARTIAL; + } + + /* Verifiy if we should use APC */ + if (!lpOverlapped) + { + /* Not using Overlapped structure, so use normal blocking on event */ + APCContext = NULL; + ApcFunction = NULL; + Event = ThreadData->EventHandle; + IoStatusBlock = &DummyIoStatusBlock; + } + else + { + /* Using apc, check if we have a completion routine */ + if (!lpCompletionRoutine) + { + /* No need for APC */ + APCContext = lpOverlapped; + ApcFunction = NULL; + Event = lpOverlapped->hEvent; + } + else + { + /* Use APC */ + ApcFunction = SockIoCompletion; + APCContext = lpCompletionRoutine; + Event = NULL; + + /* Skip Fast I/O */ + SendInfo.AfdFlags = AFD_SKIP_FIO; + } + + /* Use the overlapped's structure buffer for the I/O Status Block */ + IoStatusBlock = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; + + /* Make this an overlapped I/O in AFD */ + SendInfo.AfdFlags |= AFD_OVERLAPPED; + } + + /* Set is as Pending for now */ + IoStatusBlock->Status = STATUS_PENDING; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile((HANDLE)Handle, + Event, + ApcFunction, + APCContext, + IoStatusBlock, + IOCTL_AFD_SEND, + &SendInfo, + sizeof(SendInfo), + NULL, + 0); + + /* Increase the pending APC Count if we're using an APC */ + if (!NT_ERROR(Status) && ApcFunction) + { + ThreadData->PendingAPCs++; + InterlockedIncrement(&SockProcessPendingAPCCount); + } + + /* Wait for completition if not overlapped */ + if ((Status == STATUS_PENDING) && !(lpOverlapped)) + { + /* Wait for completion */ + ReturnValue = SockWaitForSingleObject(Event, + Handle, + MAYBE_BLOCKING_HOOK, + SEND_TIMEOUT); + + /* Check if the wait was successful */ + if (ReturnValue) + { + /* Get new status */ + Status = IoStatusBlock->Status; + } + else + { + /* Cancel the I/O */ + SockCancelIo(Handle); + Status = STATUS_IO_TIMEOUT; + } + } + + /* Check status */ + switch (Status) + { + /* Success */ + case STATUS_SUCCESS: + break; + + /* Pending I/O */ + case STATUS_PENDING: + ErrorCode = WSA_IO_PENDING; + goto error; + + /* Other NT Error */ + default: + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + break; + } + + /* Return the number of bytes sent */ + *lpNumberOfBytesSent = PtrToUlong(IoStatusBlock->Information); + +error: + + /* Check if async select was active and this blocked */ + if (SockAsyncSelectCalled && (ErrorCode == WSAEWOULDBLOCK)) + { + /* Get the socket */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (Socket) + { + /* Lock it */ + EnterCriticalSection(&Socket->Lock); + + /* Re-enable the regular write event */ + SockReenableAsyncSelectEvent(Socket, FD_WRITE); + + /* Unlock and dereference socket */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + } + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +INT +WSPAPI +WSPSendTo(SOCKET Handle, + LPWSABUF lpBuffers, + DWORD dwBufferCount, + LPDWORD lpNumberOfBytesSent, + DWORD iFlags, + const struct sockaddr *SocketAddress, + INT SocketAddressLength, + LPWSAOVERLAPPED lpOverlapped, + LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + LPWSATHREADID lpThreadId, + LPINT lpErrno) +{ + PIO_STATUS_BLOCK IoStatusBlock; + IO_STATUS_BLOCK DummyIoStatusBlock; + AFD_SEND_INFO_UDP SendInfo; + NTSTATUS Status; + PVOID APCContext; + PVOID ApcFunction; + HANDLE Event; + PWINSOCK_TEB_DATA ThreadData; + PSOCKET_INFORMATION Socket; + INT ErrorCode; + INT ReturnValue; + CHAR AddressBuffer[FIELD_OFFSET(TDI_ADDRESS_INFO, Address) + + MAX_TDI_ADDRESS_LENGTH]; + PTRANSPORT_ADDRESS TdiAddress = (PTRANSPORT_ADDRESS)AddressBuffer; + ULONG TdiAddressSize; + INT SockaddrLength; + PSOCKADDR Sockaddr; + SOCKADDR_INFO SocketInfo; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* + * Check if this isn't a datagram socket or if it's a connected socket + * without an address + */ + if (!MSAFD_IS_DGRAM_SOCK(Socket) || + ((Socket->SharedData.State == SocketConnected) && + (!SocketAddress || !SocketAddressLength))) + { + /* Call WSPSend instead */ + SockDereferenceSocket(Socket); + return WSPSend(Handle, + lpBuffers, + dwBufferCount, + lpNumberOfBytesSent, + iFlags, + lpOverlapped, + lpCompletionRoutine, + lpThreadId, + lpErrno); + } + + /* If the socket isn't connected, we need an address*/ + if ((Socket->SharedData.State != SocketConnected) && (!SocketAddress)) + { + /* Fail */ + ErrorCode = WSAENOTCONN; + goto error; + } + + /* Validate length */ + if (SocketAddressLength < Socket->HelperData->MaxWSAddressLength) + { + /* Fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* Verify flags */ + if (iFlags & ~MSG_DONTROUTE) + { + /* Fail */ + ErrorCode = WSAEOPNOTSUPP; + goto error; + } + + /* Make sure send shutdown isn't active */ + if (Socket->SharedData.SendShutdown) + { + /* Fail */ + ErrorCode = WSAESHUTDOWN; + goto error; + } + + /* Make sure address families match */ + if (Socket->SharedData.AddressFamily != SocketAddress->sa_family) + { + /* Fail */ + ErrorCode = WSAEOPNOTSUPP; + goto error; + } + + /* Check if broadcast is enabled */ + if (!Socket->SharedData.Broadcast) + { + /* The caller might want to enable it; get the Sockaddr type */ + ErrorCode = Socket->HelperData->WSHGetSockaddrType((PSOCKADDR)SocketAddress, + SocketAddressLength, + &SocketInfo); + if (ErrorCode != NO_ERROR) goto error; + + /* Check if this is a broadcast attempt */ + if (SocketInfo.AddressInfo == SockaddrAddressInfoBroadcast) + { + /* The socket won't allow it */ + ErrorCode = WSAEACCES; + goto error; + } + } + + /* Check if this socket isn't bound yet */ + if (Socket->SharedData.State == SocketOpen) + { + /* Check if we can request the wildcard address */ + if (Socket->HelperData->WSHGetWildcardSockaddr) + { + /* Allocate a new Sockaddr */ + SockaddrLength = Socket->HelperData->MaxWSAddressLength; + Sockaddr = SockAllocateHeapRoutine(SockPrivateHeap, 0, SockaddrLength); + if (!Sockaddr) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + + /* Get the wildcard sockaddr */ + ErrorCode = Socket->HelperData->WSHGetWildcardSockaddr(Socket->HelperContext, + Sockaddr, + &SockaddrLength); + if (ErrorCode != NO_ERROR) + { + /* Free memory and fail */ + RtlFreeHeap(SockPrivateHeap, 0, Sockaddr); + goto error; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* Make sure it's still unbound */ + if (Socket->SharedData.State == SocketOpen) + { + /* Bind it */ + ReturnValue = WSPBind(Handle, + Sockaddr, + SockaddrLength, + &ErrorCode); + } + else + { + /* It's bound now, fake success */ + ReturnValue = NO_ERROR; + } + + /* Release the lock and free memory */ + LeaveCriticalSection(&Socket->Lock); + RtlFreeHeap(SockPrivateHeap, 0, Sockaddr); + + /* Check if we failed */ + if (ReturnValue == SOCKET_ERROR) goto error; + } + else + { + /* Unbound socket, but can't get the wildcard. Fail */ + ErrorCode = WSAEINVAL; + goto error; + } + } + + /* Check how long the TDI Address is */ + TdiAddressSize = Socket->HelperData->MaxTDIAddressLength; + + /* See if it can fit in the stack */ + if (TdiAddressSize > sizeof(AddressBuffer)) + { + /* Allocate from heap */ + TdiAddress = SockAllocateHeapRoutine(SockPrivateHeap, 0, TdiAddressSize); + if (!TdiAddress) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + } + + /* Build the TDI Address */ + ErrorCode = SockBuildTdiAddress(TdiAddress, + (PSOCKADDR)SocketAddress, + min(SocketAddressLength, + Socket->HelperData->MaxWSAddressLength)); + if (ErrorCode != NO_ERROR) goto error; + + /* Set up the Send Structure */ + SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers; + SendInfo.BufferCount = dwBufferCount; + SendInfo.AfdFlags = 0; + SendInfo.TdiConnection.RemoteAddress = TdiAddress; + SendInfo.TdiConnection.RemoteAddressLength = TdiAddressSize; + + /* Verifiy if we should use APC */ + if (!lpOverlapped) + { + /* Not using Overlapped structure, so use normal blocking on event */ + APCContext = NULL; + ApcFunction = NULL; + Event = ThreadData->EventHandle; + IoStatusBlock = &DummyIoStatusBlock; + } + else + { + /* Using apc, check if we have a completion routine */ + if (!lpCompletionRoutine) + { + /* No need for APC */ + APCContext = lpOverlapped; + ApcFunction = NULL; + Event = lpOverlapped->hEvent; + } + else + { + /* Use APC */ + ApcFunction = SockIoCompletion; + APCContext = lpCompletionRoutine; + Event = NULL; + + /* Skip Fast I/O */ + SendInfo.AfdFlags = AFD_SKIP_FIO; + } + + /* Use the overlapped's structure buffer for the I/O Status Block */ + IoStatusBlock = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; + + /* Make this an overlapped I/O in AFD */ + SendInfo.AfdFlags |= AFD_OVERLAPPED; + } + + /* Set is as Pending for now */ + IoStatusBlock->Status = STATUS_PENDING; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + Event, + ApcFunction, + APCContext, + IoStatusBlock, + IOCTL_AFD_SEND_DATAGRAM, + &SendInfo, + sizeof(SendInfo), + NULL, + 0); + + /* Increase the pending APC Count if we're using an APC */ + if (!NT_ERROR(Status) && ApcFunction) + { + ThreadData->PendingAPCs++; + InterlockedIncrement(&SockProcessPendingAPCCount); + } + + /* Wait for completition if not overlapped */ + if ((Status == STATUS_PENDING) && !(lpOverlapped)) + { + /* Wait for completion */ + ReturnValue = SockWaitForSingleObject(Event, + Handle, + MAYBE_BLOCKING_HOOK, + SEND_TIMEOUT); + + /* Check if the wait was successful */ + if (ReturnValue) + { + /* Get new status */ + Status = IoStatusBlock->Status; + } + else + { + /* Cancel the I/O */ + SockCancelIo(Handle); + Status = STATUS_IO_TIMEOUT; + } + } + + /* Check status */ + switch (Status) + { + /* Success */ + case STATUS_SUCCESS: + break; + + /* Pending I/O */ + case STATUS_PENDING: + ErrorCode = WSA_IO_PENDING; + goto error; + + /* Other NT Error */ + default: + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + break; + } + + /* Return the number of bytes sent */ + *lpNumberOfBytesSent = PtrToUlong(IoStatusBlock->Information); + +error: + + /* Check if we have a socket */ + if (Socket) + { + /* Check if async select was active and this blocked */ + if (SockAsyncSelectCalled && (ErrorCode == WSAEWOULDBLOCK)) + { + /* Lock it */ + EnterCriticalSection(&Socket->Lock); + + /* Re-enable the regular write event */ + SockReenableAsyncSelectEvent(Socket, FD_WRITE); + + /* Unlock socket */ + LeaveCriticalSection(&Socket->Lock); + } + + /* Dereference socket */ + SockDereferenceSocket(Socket); + } + + /* Check if we should free the TDI Address */ + if (TdiAddress && (TdiAddress != (PVOID)AddressBuffer)) + { + /* Free it from the heap */ + RtlFreeHeap(SockPrivateHeap, 0, TdiAddress); + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + diff --git a/dll/win32/mswsock/msafd/shutdown.c b/dll/win32/mswsock/msafd/shutdown.c new file mode 100644 index 00000000000..3d24ea4e66d --- /dev/null +++ b/dll/win32/mswsock/msafd/shutdown.c @@ -0,0 +1,696 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +WSPRecvDisconnect(IN SOCKET s, + OUT LPWSABUF lpInboundDisconnectData, + OUT LPINT lpErrno) +{ + return 0; +} + +INT +WSPAPI +WSPSendDisconnect(IN SOCKET s, + IN LPWSABUF lpOutboundDisconnectData, + OUT LPINT lpErrno) +{ + return 0; +} + +INT +WSPAPI +WSPShutdown(SOCKET Handle, + INT HowTo, + LPINT lpErrno) + +{ + IO_STATUS_BLOCK IoStatusBlock; + AFD_DISCONNECT_INFO DisconnectInfo; + PSOCKET_INFORMATION Socket; + PWINSOCK_TEB_DATA ThreadData; + DWORD HelperEvent; + INT ErrorCode; + NTSTATUS Status; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* If the socket is not connection-less, fail if it's not connected */ + if ((MSAFD_IS_DGRAM_SOCK(Socket)) && !(SockIsSocketConnected(Socket))) + { + /* Fail */ + ErrorCode = WSAENOTCONN; + goto error; + } + + /* Set AFD Disconnect Type and WSH Notification Type */ + switch (HowTo) + { + case SD_RECEIVE: + /* Set receive disconnect */ + DisconnectInfo.DisconnectType = AFD_DISCONNECT_RECV; + HelperEvent = WSH_NOTIFY_SHUTDOWN_RECEIVE; + + /* Save it for ourselves */ + Socket->SharedData.ReceiveShutdown = TRUE; + break; + + case SD_SEND: + /* Set receive disconnect */ + DisconnectInfo.DisconnectType = AFD_DISCONNECT_SEND; + HelperEvent = WSH_NOTIFY_SHUTDOWN_SEND; + + /* Save it for ourselves */ + Socket->SharedData.SendShutdown = TRUE; + break; + + case SD_BOTH: + /* Set both */ + DisconnectInfo.DisconnectType = AFD_DISCONNECT_RECV | AFD_DISCONNECT_SEND; + HelperEvent = WSH_NOTIFY_SHUTDOWN_ALL; + + /* Save it for ourselves */ + Socket->SharedData.ReceiveShutdown = Socket->SharedData.SendShutdown = TRUE; + break; + + default: + /* Fail, invalid type */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Inifite Timeout */ + DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(-1); + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_DISCONNECT, + &DisconnectInfo, + sizeof(DisconnectInfo), + NULL, + 0); + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion outside the lock */ + LeaveCriticalSection(&Socket->Lock); + SockWaitForSingleObject(ThreadData->EventHandle, + Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + EnterCriticalSection(&Socket->Lock); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* Notify helper DLL */ + ErrorCode = SockNotifyHelperDll(Socket, HelperEvent); + if (ErrorCode != NO_ERROR) goto error; + +error: + /* Check if we have a socket here */ + if (Socket) + { + /* Release the lock and dereference */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +WSPRecvDisconnect(IN SOCKET s, + OUT LPWSABUF lpInboundDisconnectData, + OUT LPINT lpErrno) +{ + return 0; +} + +INT +WSPAPI +WSPSendDisconnect(IN SOCKET s, + IN LPWSABUF lpOutboundDisconnectData, + OUT LPINT lpErrno) +{ + return 0; +} + +INT +WSPAPI +WSPShutdown(SOCKET Handle, + INT HowTo, + LPINT lpErrno) + +{ + IO_STATUS_BLOCK IoStatusBlock; + AFD_DISCONNECT_INFO DisconnectInfo; + PSOCKET_INFORMATION Socket; + PWINSOCK_TEB_DATA ThreadData; + DWORD HelperEvent; + INT ErrorCode; + NTSTATUS Status; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* If the socket is not connection-less, fail if it's not connected */ + if ((MSAFD_IS_DGRAM_SOCK(Socket)) && !(SockIsSocketConnected(Socket))) + { + /* Fail */ + ErrorCode = WSAENOTCONN; + goto error; + } + + /* Set AFD Disconnect Type and WSH Notification Type */ + switch (HowTo) + { + case SD_RECEIVE: + /* Set receive disconnect */ + DisconnectInfo.DisconnectType = AFD_DISCONNECT_RECV; + HelperEvent = WSH_NOTIFY_SHUTDOWN_RECEIVE; + + /* Save it for ourselves */ + Socket->SharedData.ReceiveShutdown = TRUE; + break; + + case SD_SEND: + /* Set receive disconnect */ + DisconnectInfo.DisconnectType = AFD_DISCONNECT_SEND; + HelperEvent = WSH_NOTIFY_SHUTDOWN_SEND; + + /* Save it for ourselves */ + Socket->SharedData.SendShutdown = TRUE; + break; + + case SD_BOTH: + /* Set both */ + DisconnectInfo.DisconnectType = AFD_DISCONNECT_RECV | AFD_DISCONNECT_SEND; + HelperEvent = WSH_NOTIFY_SHUTDOWN_ALL; + + /* Save it for ourselves */ + Socket->SharedData.ReceiveShutdown = Socket->SharedData.SendShutdown = TRUE; + break; + + default: + /* Fail, invalid type */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Inifite Timeout */ + DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(-1); + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_DISCONNECT, + &DisconnectInfo, + sizeof(DisconnectInfo), + NULL, + 0); + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion outside the lock */ + LeaveCriticalSection(&Socket->Lock); + SockWaitForSingleObject(ThreadData->EventHandle, + Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + EnterCriticalSection(&Socket->Lock); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* Notify helper DLL */ + ErrorCode = SockNotifyHelperDll(Socket, HelperEvent); + if (ErrorCode != NO_ERROR) goto error; + +error: + /* Check if we have a socket here */ + if (Socket) + { + /* Release the lock and dereference */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +WSPRecvDisconnect(IN SOCKET s, + OUT LPWSABUF lpInboundDisconnectData, + OUT LPINT lpErrno) +{ + return 0; +} + +INT +WSPAPI +WSPSendDisconnect(IN SOCKET s, + IN LPWSABUF lpOutboundDisconnectData, + OUT LPINT lpErrno) +{ + return 0; +} + +INT +WSPAPI +WSPShutdown(SOCKET Handle, + INT HowTo, + LPINT lpErrno) + +{ + IO_STATUS_BLOCK IoStatusBlock; + AFD_DISCONNECT_INFO DisconnectInfo; + PSOCKET_INFORMATION Socket; + PWINSOCK_TEB_DATA ThreadData; + DWORD HelperEvent; + INT ErrorCode; + NTSTATUS Status; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* If the socket is not connection-less, fail if it's not connected */ + if ((MSAFD_IS_DGRAM_SOCK(Socket)) && !(SockIsSocketConnected(Socket))) + { + /* Fail */ + ErrorCode = WSAENOTCONN; + goto error; + } + + /* Set AFD Disconnect Type and WSH Notification Type */ + switch (HowTo) + { + case SD_RECEIVE: + /* Set receive disconnect */ + DisconnectInfo.DisconnectType = AFD_DISCONNECT_RECV; + HelperEvent = WSH_NOTIFY_SHUTDOWN_RECEIVE; + + /* Save it for ourselves */ + Socket->SharedData.ReceiveShutdown = TRUE; + break; + + case SD_SEND: + /* Set receive disconnect */ + DisconnectInfo.DisconnectType = AFD_DISCONNECT_SEND; + HelperEvent = WSH_NOTIFY_SHUTDOWN_SEND; + + /* Save it for ourselves */ + Socket->SharedData.SendShutdown = TRUE; + break; + + case SD_BOTH: + /* Set both */ + DisconnectInfo.DisconnectType = AFD_DISCONNECT_RECV | AFD_DISCONNECT_SEND; + HelperEvent = WSH_NOTIFY_SHUTDOWN_ALL; + + /* Save it for ourselves */ + Socket->SharedData.ReceiveShutdown = Socket->SharedData.SendShutdown = TRUE; + break; + + default: + /* Fail, invalid type */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Inifite Timeout */ + DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(-1); + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_DISCONNECT, + &DisconnectInfo, + sizeof(DisconnectInfo), + NULL, + 0); + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion outside the lock */ + LeaveCriticalSection(&Socket->Lock); + SockWaitForSingleObject(ThreadData->EventHandle, + Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + EnterCriticalSection(&Socket->Lock); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* Notify helper DLL */ + ErrorCode = SockNotifyHelperDll(Socket, HelperEvent); + if (ErrorCode != NO_ERROR) goto error; + +error: + /* Check if we have a socket here */ + if (Socket) + { + /* Release the lock and dereference */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +WSPRecvDisconnect(IN SOCKET s, + OUT LPWSABUF lpInboundDisconnectData, + OUT LPINT lpErrno) +{ + return 0; +} + +INT +WSPAPI +WSPSendDisconnect(IN SOCKET s, + IN LPWSABUF lpOutboundDisconnectData, + OUT LPINT lpErrno) +{ + return 0; +} + +INT +WSPAPI +WSPShutdown(SOCKET Handle, + INT HowTo, + LPINT lpErrno) + +{ + IO_STATUS_BLOCK IoStatusBlock; + AFD_DISCONNECT_INFO DisconnectInfo; + PSOCKET_INFORMATION Socket; + PWINSOCK_TEB_DATA ThreadData; + DWORD HelperEvent; + INT ErrorCode; + NTSTATUS Status; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* If the socket is not connection-less, fail if it's not connected */ + if ((MSAFD_IS_DGRAM_SOCK(Socket)) && !(SockIsSocketConnected(Socket))) + { + /* Fail */ + ErrorCode = WSAENOTCONN; + goto error; + } + + /* Set AFD Disconnect Type and WSH Notification Type */ + switch (HowTo) + { + case SD_RECEIVE: + /* Set receive disconnect */ + DisconnectInfo.DisconnectType = AFD_DISCONNECT_RECV; + HelperEvent = WSH_NOTIFY_SHUTDOWN_RECEIVE; + + /* Save it for ourselves */ + Socket->SharedData.ReceiveShutdown = TRUE; + break; + + case SD_SEND: + /* Set receive disconnect */ + DisconnectInfo.DisconnectType = AFD_DISCONNECT_SEND; + HelperEvent = WSH_NOTIFY_SHUTDOWN_SEND; + + /* Save it for ourselves */ + Socket->SharedData.SendShutdown = TRUE; + break; + + case SD_BOTH: + /* Set both */ + DisconnectInfo.DisconnectType = AFD_DISCONNECT_RECV | AFD_DISCONNECT_SEND; + HelperEvent = WSH_NOTIFY_SHUTDOWN_ALL; + + /* Save it for ourselves */ + Socket->SharedData.ReceiveShutdown = Socket->SharedData.SendShutdown = TRUE; + break; + + default: + /* Fail, invalid type */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Inifite Timeout */ + DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(-1); + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_DISCONNECT, + &DisconnectInfo, + sizeof(DisconnectInfo), + NULL, + 0); + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion outside the lock */ + LeaveCriticalSection(&Socket->Lock); + SockWaitForSingleObject(ThreadData->EventHandle, + Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + EnterCriticalSection(&Socket->Lock); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* Notify helper DLL */ + ErrorCode = SockNotifyHelperDll(Socket, HelperEvent); + if (ErrorCode != NO_ERROR) goto error; + +error: + /* Check if we have a socket here */ + if (Socket) + { + /* Release the lock and dereference */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + diff --git a/dll/win32/mswsock/msafd/sockerr.c b/dll/win32/mswsock/msafd/sockerr.c new file mode 100644 index 00000000000..83430cc0062 --- /dev/null +++ b/dll/win32/mswsock/msafd/sockerr.c @@ -0,0 +1,552 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +NtStatusToSocketError(IN NTSTATUS Status) +{ + switch (Status) + { + case STATUS_PENDING: + return ERROR_IO_PENDING; + + case STATUS_INVALID_HANDLE: + case STATUS_OBJECT_TYPE_MISMATCH: + return WSAENOTSOCK; + + case STATUS_INSUFFICIENT_RESOURCES: + case STATUS_PAGEFILE_QUOTA: + case STATUS_COMMITMENT_LIMIT: + case STATUS_WORKING_SET_QUOTA: + case STATUS_NO_MEMORY: + case STATUS_CONFLICTING_ADDRESSES: + case STATUS_QUOTA_EXCEEDED: + case STATUS_TOO_MANY_PAGING_FILES: + case STATUS_REMOTE_RESOURCES: + case STATUS_TOO_MANY_ADDRESSES: + return WSAENOBUFS; + + case STATUS_SHARING_VIOLATION: + case STATUS_ADDRESS_ALREADY_EXISTS: + return WSAEADDRINUSE; + + case STATUS_LINK_TIMEOUT: + case STATUS_IO_TIMEOUT: + case STATUS_TIMEOUT: + return WSAETIMEDOUT; + + case STATUS_GRACEFUL_DISCONNECT: + return WSAEDISCON; + + case STATUS_REMOTE_DISCONNECT: + case STATUS_CONNECTION_RESET: + case STATUS_LINK_FAILED: + case STATUS_CONNECTION_DISCONNECTED: + case STATUS_PORT_UNREACHABLE: + return WSAECONNRESET; + + case STATUS_LOCAL_DISCONNECT: + case STATUS_TRANSACTION_ABORTED: + case STATUS_CONNECTION_ABORTED: + return WSAECONNABORTED; + + case STATUS_BAD_NETWORK_PATH: + case STATUS_NETWORK_UNREACHABLE: + case STATUS_PROTOCOL_UNREACHABLE: + return WSAENETUNREACH; + + case STATUS_HOST_UNREACHABLE: + return WSAEHOSTUNREACH; + + case STATUS_CANCELLED: + case STATUS_REQUEST_ABORTED: + return WSAEINTR; + + case STATUS_BUFFER_OVERFLOW: + case STATUS_INVALID_BUFFER_SIZE: + return WSAEMSGSIZE; + + case STATUS_BUFFER_TOO_SMALL: + case STATUS_ACCESS_VIOLATION: + return WSAEFAULT; + + case STATUS_DEVICE_NOT_READY: + case STATUS_REQUEST_NOT_ACCEPTED: + return WSAEWOULDBLOCK; + + case STATUS_INVALID_NETWORK_RESPONSE: + case STATUS_NETWORK_BUSY: + case STATUS_NO_SUCH_DEVICE: + case STATUS_NO_SUCH_FILE: + case STATUS_OBJECT_PATH_NOT_FOUND: + case STATUS_OBJECT_NAME_NOT_FOUND: + case STATUS_UNEXPECTED_NETWORK_ERROR: + return WSAENETDOWN; + + case STATUS_INVALID_CONNECTION: + return WSAENOTCONN; + + case STATUS_REMOTE_NOT_LISTENING: + case STATUS_CONNECTION_REFUSED: + return WSAECONNREFUSED; + + case STATUS_PIPE_DISCONNECTED: + return WSAESHUTDOWN; + + case STATUS_INVALID_ADDRESS: + case STATUS_INVALID_ADDRESS_COMPONENT: + return WSAEADDRNOTAVAIL; + + case STATUS_NOT_SUPPORTED: + case STATUS_NOT_IMPLEMENTED: + return WSAEOPNOTSUPP; + + case STATUS_ACCESS_DENIED: + return WSAEACCES; + + default: + + if ( NT_SUCCESS(Status) ) { + + return NO_ERROR; + } + + + case STATUS_UNSUCCESSFUL: + case STATUS_INVALID_PARAMETER: + case STATUS_ADDRESS_CLOSED: + case STATUS_CONNECTION_INVALID: + case STATUS_ADDRESS_ALREADY_ASSOCIATED: + case STATUS_ADDRESS_NOT_ASSOCIATED: + case STATUS_CONNECTION_ACTIVE: + case STATUS_INVALID_DEVICE_STATE: + case STATUS_INVALID_DEVICE_REQUEST: + return WSAEINVAL; + } +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +NtStatusToSocketError(IN NTSTATUS Status) +{ + switch (Status) + { + case STATUS_PENDING: + return ERROR_IO_PENDING; + + case STATUS_INVALID_HANDLE: + case STATUS_OBJECT_TYPE_MISMATCH: + return WSAENOTSOCK; + + case STATUS_INSUFFICIENT_RESOURCES: + case STATUS_PAGEFILE_QUOTA: + case STATUS_COMMITMENT_LIMIT: + case STATUS_WORKING_SET_QUOTA: + case STATUS_NO_MEMORY: + case STATUS_CONFLICTING_ADDRESSES: + case STATUS_QUOTA_EXCEEDED: + case STATUS_TOO_MANY_PAGING_FILES: + case STATUS_REMOTE_RESOURCES: + case STATUS_TOO_MANY_ADDRESSES: + return WSAENOBUFS; + + case STATUS_SHARING_VIOLATION: + case STATUS_ADDRESS_ALREADY_EXISTS: + return WSAEADDRINUSE; + + case STATUS_LINK_TIMEOUT: + case STATUS_IO_TIMEOUT: + case STATUS_TIMEOUT: + return WSAETIMEDOUT; + + case STATUS_GRACEFUL_DISCONNECT: + return WSAEDISCON; + + case STATUS_REMOTE_DISCONNECT: + case STATUS_CONNECTION_RESET: + case STATUS_LINK_FAILED: + case STATUS_CONNECTION_DISCONNECTED: + case STATUS_PORT_UNREACHABLE: + return WSAECONNRESET; + + case STATUS_LOCAL_DISCONNECT: + case STATUS_TRANSACTION_ABORTED: + case STATUS_CONNECTION_ABORTED: + return WSAECONNABORTED; + + case STATUS_BAD_NETWORK_PATH: + case STATUS_NETWORK_UNREACHABLE: + case STATUS_PROTOCOL_UNREACHABLE: + return WSAENETUNREACH; + + case STATUS_HOST_UNREACHABLE: + return WSAEHOSTUNREACH; + + case STATUS_CANCELLED: + case STATUS_REQUEST_ABORTED: + return WSAEINTR; + + case STATUS_BUFFER_OVERFLOW: + case STATUS_INVALID_BUFFER_SIZE: + return WSAEMSGSIZE; + + case STATUS_BUFFER_TOO_SMALL: + case STATUS_ACCESS_VIOLATION: + return WSAEFAULT; + + case STATUS_DEVICE_NOT_READY: + case STATUS_REQUEST_NOT_ACCEPTED: + return WSAEWOULDBLOCK; + + case STATUS_INVALID_NETWORK_RESPONSE: + case STATUS_NETWORK_BUSY: + case STATUS_NO_SUCH_DEVICE: + case STATUS_NO_SUCH_FILE: + case STATUS_OBJECT_PATH_NOT_FOUND: + case STATUS_OBJECT_NAME_NOT_FOUND: + case STATUS_UNEXPECTED_NETWORK_ERROR: + return WSAENETDOWN; + + case STATUS_INVALID_CONNECTION: + return WSAENOTCONN; + + case STATUS_REMOTE_NOT_LISTENING: + case STATUS_CONNECTION_REFUSED: + return WSAECONNREFUSED; + + case STATUS_PIPE_DISCONNECTED: + return WSAESHUTDOWN; + + case STATUS_INVALID_ADDRESS: + case STATUS_INVALID_ADDRESS_COMPONENT: + return WSAEADDRNOTAVAIL; + + case STATUS_NOT_SUPPORTED: + case STATUS_NOT_IMPLEMENTED: + return WSAEOPNOTSUPP; + + case STATUS_ACCESS_DENIED: + return WSAEACCES; + + default: + + if ( NT_SUCCESS(Status) ) { + + return NO_ERROR; + } + + + case STATUS_UNSUCCESSFUL: + case STATUS_INVALID_PARAMETER: + case STATUS_ADDRESS_CLOSED: + case STATUS_CONNECTION_INVALID: + case STATUS_ADDRESS_ALREADY_ASSOCIATED: + case STATUS_ADDRESS_NOT_ASSOCIATED: + case STATUS_CONNECTION_ACTIVE: + case STATUS_INVALID_DEVICE_STATE: + case STATUS_INVALID_DEVICE_REQUEST: + return WSAEINVAL; + } +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +NtStatusToSocketError(IN NTSTATUS Status) +{ + switch (Status) + { + case STATUS_PENDING: + return ERROR_IO_PENDING; + + case STATUS_INVALID_HANDLE: + case STATUS_OBJECT_TYPE_MISMATCH: + return WSAENOTSOCK; + + case STATUS_INSUFFICIENT_RESOURCES: + case STATUS_PAGEFILE_QUOTA: + case STATUS_COMMITMENT_LIMIT: + case STATUS_WORKING_SET_QUOTA: + case STATUS_NO_MEMORY: + case STATUS_CONFLICTING_ADDRESSES: + case STATUS_QUOTA_EXCEEDED: + case STATUS_TOO_MANY_PAGING_FILES: + case STATUS_REMOTE_RESOURCES: + case STATUS_TOO_MANY_ADDRESSES: + return WSAENOBUFS; + + case STATUS_SHARING_VIOLATION: + case STATUS_ADDRESS_ALREADY_EXISTS: + return WSAEADDRINUSE; + + case STATUS_LINK_TIMEOUT: + case STATUS_IO_TIMEOUT: + case STATUS_TIMEOUT: + return WSAETIMEDOUT; + + case STATUS_GRACEFUL_DISCONNECT: + return WSAEDISCON; + + case STATUS_REMOTE_DISCONNECT: + case STATUS_CONNECTION_RESET: + case STATUS_LINK_FAILED: + case STATUS_CONNECTION_DISCONNECTED: + case STATUS_PORT_UNREACHABLE: + return WSAECONNRESET; + + case STATUS_LOCAL_DISCONNECT: + case STATUS_TRANSACTION_ABORTED: + case STATUS_CONNECTION_ABORTED: + return WSAECONNABORTED; + + case STATUS_BAD_NETWORK_PATH: + case STATUS_NETWORK_UNREACHABLE: + case STATUS_PROTOCOL_UNREACHABLE: + return WSAENETUNREACH; + + case STATUS_HOST_UNREACHABLE: + return WSAEHOSTUNREACH; + + case STATUS_CANCELLED: + case STATUS_REQUEST_ABORTED: + return WSAEINTR; + + case STATUS_BUFFER_OVERFLOW: + case STATUS_INVALID_BUFFER_SIZE: + return WSAEMSGSIZE; + + case STATUS_BUFFER_TOO_SMALL: + case STATUS_ACCESS_VIOLATION: + return WSAEFAULT; + + case STATUS_DEVICE_NOT_READY: + case STATUS_REQUEST_NOT_ACCEPTED: + return WSAEWOULDBLOCK; + + case STATUS_INVALID_NETWORK_RESPONSE: + case STATUS_NETWORK_BUSY: + case STATUS_NO_SUCH_DEVICE: + case STATUS_NO_SUCH_FILE: + case STATUS_OBJECT_PATH_NOT_FOUND: + case STATUS_OBJECT_NAME_NOT_FOUND: + case STATUS_UNEXPECTED_NETWORK_ERROR: + return WSAENETDOWN; + + case STATUS_INVALID_CONNECTION: + return WSAENOTCONN; + + case STATUS_REMOTE_NOT_LISTENING: + case STATUS_CONNECTION_REFUSED: + return WSAECONNREFUSED; + + case STATUS_PIPE_DISCONNECTED: + return WSAESHUTDOWN; + + case STATUS_INVALID_ADDRESS: + case STATUS_INVALID_ADDRESS_COMPONENT: + return WSAEADDRNOTAVAIL; + + case STATUS_NOT_SUPPORTED: + case STATUS_NOT_IMPLEMENTED: + return WSAEOPNOTSUPP; + + case STATUS_ACCESS_DENIED: + return WSAEACCES; + + default: + + if ( NT_SUCCESS(Status) ) { + + return NO_ERROR; + } + + + case STATUS_UNSUCCESSFUL: + case STATUS_INVALID_PARAMETER: + case STATUS_ADDRESS_CLOSED: + case STATUS_CONNECTION_INVALID: + case STATUS_ADDRESS_ALREADY_ASSOCIATED: + case STATUS_ADDRESS_NOT_ASSOCIATED: + case STATUS_CONNECTION_ACTIVE: + case STATUS_INVALID_DEVICE_STATE: + case STATUS_INVALID_DEVICE_REQUEST: + return WSAEINVAL; + } +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +NtStatusToSocketError(IN NTSTATUS Status) +{ + switch (Status) + { + case STATUS_PENDING: + return ERROR_IO_PENDING; + + case STATUS_INVALID_HANDLE: + case STATUS_OBJECT_TYPE_MISMATCH: + return WSAENOTSOCK; + + case STATUS_INSUFFICIENT_RESOURCES: + case STATUS_PAGEFILE_QUOTA: + case STATUS_COMMITMENT_LIMIT: + case STATUS_WORKING_SET_QUOTA: + case STATUS_NO_MEMORY: + case STATUS_CONFLICTING_ADDRESSES: + case STATUS_QUOTA_EXCEEDED: + case STATUS_TOO_MANY_PAGING_FILES: + case STATUS_REMOTE_RESOURCES: + case STATUS_TOO_MANY_ADDRESSES: + return WSAENOBUFS; + + case STATUS_SHARING_VIOLATION: + case STATUS_ADDRESS_ALREADY_EXISTS: + return WSAEADDRINUSE; + + case STATUS_LINK_TIMEOUT: + case STATUS_IO_TIMEOUT: + case STATUS_TIMEOUT: + return WSAETIMEDOUT; + + case STATUS_GRACEFUL_DISCONNECT: + return WSAEDISCON; + + case STATUS_REMOTE_DISCONNECT: + case STATUS_CONNECTION_RESET: + case STATUS_LINK_FAILED: + case STATUS_CONNECTION_DISCONNECTED: + case STATUS_PORT_UNREACHABLE: + return WSAECONNRESET; + + case STATUS_LOCAL_DISCONNECT: + case STATUS_TRANSACTION_ABORTED: + case STATUS_CONNECTION_ABORTED: + return WSAECONNABORTED; + + case STATUS_BAD_NETWORK_PATH: + case STATUS_NETWORK_UNREACHABLE: + case STATUS_PROTOCOL_UNREACHABLE: + return WSAENETUNREACH; + + case STATUS_HOST_UNREACHABLE: + return WSAEHOSTUNREACH; + + case STATUS_CANCELLED: + case STATUS_REQUEST_ABORTED: + return WSAEINTR; + + case STATUS_BUFFER_OVERFLOW: + case STATUS_INVALID_BUFFER_SIZE: + return WSAEMSGSIZE; + + case STATUS_BUFFER_TOO_SMALL: + case STATUS_ACCESS_VIOLATION: + return WSAEFAULT; + + case STATUS_DEVICE_NOT_READY: + case STATUS_REQUEST_NOT_ACCEPTED: + return WSAEWOULDBLOCK; + + case STATUS_INVALID_NETWORK_RESPONSE: + case STATUS_NETWORK_BUSY: + case STATUS_NO_SUCH_DEVICE: + case STATUS_NO_SUCH_FILE: + case STATUS_OBJECT_PATH_NOT_FOUND: + case STATUS_OBJECT_NAME_NOT_FOUND: + case STATUS_UNEXPECTED_NETWORK_ERROR: + return WSAENETDOWN; + + case STATUS_INVALID_CONNECTION: + return WSAENOTCONN; + + case STATUS_REMOTE_NOT_LISTENING: + case STATUS_CONNECTION_REFUSED: + return WSAECONNREFUSED; + + case STATUS_PIPE_DISCONNECTED: + return WSAESHUTDOWN; + + case STATUS_INVALID_ADDRESS: + case STATUS_INVALID_ADDRESS_COMPONENT: + return WSAEADDRNOTAVAIL; + + case STATUS_NOT_SUPPORTED: + case STATUS_NOT_IMPLEMENTED: + return WSAEOPNOTSUPP; + + case STATUS_ACCESS_DENIED: + return WSAEACCES; + + default: + + if ( NT_SUCCESS(Status) ) { + + return NO_ERROR; + } + + + case STATUS_UNSUCCESSFUL: + case STATUS_INVALID_PARAMETER: + case STATUS_ADDRESS_CLOSED: + case STATUS_CONNECTION_INVALID: + case STATUS_ADDRESS_ALREADY_ASSOCIATED: + case STATUS_ADDRESS_NOT_ASSOCIATED: + case STATUS_CONNECTION_ACTIVE: + case STATUS_INVALID_DEVICE_STATE: + case STATUS_INVALID_DEVICE_REQUEST: + return WSAEINVAL; + } +} + diff --git a/dll/win32/mswsock/msafd/socket.c b/dll/win32/mswsock/msafd/socket.c new file mode 100644 index 00000000000..61e491d57e0 --- /dev/null +++ b/dll/win32/mswsock/msafd/socket.c @@ -0,0 +1,3196 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +SockSocket(INT AddressFamily, + INT SocketType, + INT Protocol, + LPGUID ProviderId, + GROUP g, + DWORD dwFlags, + DWORD ProviderFlags, + DWORD ServiceFlags, + DWORD CatalogEntryId, + PSOCKET_INFORMATION *NewSocket) +{ + INT ErrorCode; + UNICODE_STRING TransportName; + PVOID HelperDllContext; + PHELPER_DATA HelperData = NULL; + DWORD HelperEvents; + PFILE_FULL_EA_INFORMATION Ea = NULL; + PAFD_CREATE_PACKET AfdPacket; + SOCKET Handle = INVALID_SOCKET; + PSOCKET_INFORMATION Socket = NULL; + BOOLEAN LockInit = FALSE; + USHORT SizeOfPacket; + DWORD SizeOfEa, SocketLength; + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING DevName; + LARGE_INTEGER GroupData; + DWORD CreateOptions = 0; + IO_STATUS_BLOCK IoStatusBlock; + PWAH_HANDLE WahHandle; + NTSTATUS Status; + CHAR AfdPacketBuffer[96]; + + /* Initialize the transport name */ + RtlInitUnicodeString(&TransportName, NULL); + + /* Get Helper Data and Transport */ + ErrorCode = SockGetTdiName(&AddressFamily, + &SocketType, + &Protocol, + ProviderId, + g, + dwFlags, + &TransportName, + &HelperDllContext, + &HelperData, + &HelperEvents); + + /* Check for error */ + if (ErrorCode != NO_ERROR) goto error; + + /* Figure out the socket context structure size */ + SocketLength = sizeof(*Socket) + (HelperData->MinWSAddressLength * 2); + + /* Allocate a socket */ + Socket = SockAllocateHeapRoutine(SockPrivateHeap, 0, SocketLength); + if (!Socket) + { + /* Couldn't create it; we need to tell WSH so it can cleanup */ + if (HelperEvents & WSH_NOTIFY_CLOSE) + { + HelperData->WSHNotify(HelperDllContext, + INVALID_SOCKET, + NULL, + NULL, + WSH_NOTIFY_CLOSE); + } + + /* Fail and return */ + ErrorCode = WSAENOBUFS; + goto error; + } + + /* Initialize it */ + RtlZeroMemory(Socket, SocketLength); + Socket->RefCount = 2; + Socket->Handle = INVALID_SOCKET; + Socket->SharedData.State = SocketUndefined; + Socket->SharedData.AddressFamily = AddressFamily; + Socket->SharedData.SocketType = SocketType; + Socket->SharedData.Protocol = Protocol; + Socket->ProviderId = *ProviderId; + Socket->HelperContext = HelperDllContext; + Socket->HelperData = HelperData; + Socket->HelperEvents = HelperEvents; + Socket->LocalAddress = (PVOID)(Socket + 1); + Socket->SharedData.SizeOfLocalAddress = HelperData->MaxWSAddressLength; + Socket->RemoteAddress = (PVOID)((ULONG_PTR)Socket->LocalAddress + + HelperData->MaxWSAddressLength); + Socket->SharedData.SizeOfRemoteAddress = HelperData->MaxWSAddressLength; + Socket->SharedData.UseDelayedAcceptance = HelperData->UseDelayedAcceptance; + Socket->SharedData.CreateFlags = dwFlags; + Socket->SharedData.CatalogEntryId = CatalogEntryId; + Socket->SharedData.ServiceFlags1 = ServiceFlags; + Socket->SharedData.ProviderFlags = ProviderFlags; + Socket->SharedData.GroupID = g; + Socket->SharedData.GroupType = 0; + Socket->SharedData.UseSAN = FALSE; + Socket->SanData = NULL; + Socket->DontUseSan = FALSE; + + /* Initialize the socket lock */ + InitializeCriticalSection(&Socket->Lock); + LockInit = TRUE; + + /* Packet Size */ + SizeOfPacket = TransportName.Length + sizeof(*AfdPacket) + sizeof(WCHAR); + + /* EA Size */ + SizeOfEa = SizeOfPacket + sizeof(*Ea) + AFD_PACKET_COMMAND_LENGTH; + + /* See if our stack buffer is big enough to hold it */ + if (SizeOfEa <= sizeof(AfdPacketBuffer)) + { + /* Use our stack */ + Ea = (PFILE_FULL_EA_INFORMATION)AfdPacketBuffer; + } + else + { + /* Allocate from heap */ + Ea = SockAllocateHeapRoutine(SockPrivateHeap, 0, SizeOfEa); + if (!Ea) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + } + + /* Set up EA */ + Ea->NextEntryOffset = 0; + Ea->Flags = 0; + Ea->EaNameLength = AFD_PACKET_COMMAND_LENGTH; + RtlCopyMemory(Ea->EaName, AfdCommand, AFD_PACKET_COMMAND_LENGTH + 1); + Ea->EaValueLength = SizeOfPacket; + + /* Set up AFD Packet */ + AfdPacket = (PAFD_CREATE_PACKET)(Ea->EaName + Ea->EaNameLength + 1); + AfdPacket->SizeOfTransportName = TransportName.Length; + RtlCopyMemory(AfdPacket->TransportName, + TransportName.Buffer, + TransportName.Length + sizeof(WCHAR)); + AfdPacket->EndpointFlags = 0; + + /* Set up Endpoint Flags */ + if ((Socket->SharedData.ServiceFlags1 & XP1_CONNECTIONLESS)) + { + /* Check the Socket Type */ + if ((SocketType != SOCK_DGRAM) && (SocketType != SOCK_RAW)) + { + /* Only RAW or UDP can be Connectionless */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Set the flag for AFD */ + AfdPacket->EndpointFlags |= AFD_ENDPOINT_CONNECTIONLESS; + } + + if ((Socket->SharedData.ServiceFlags1 & XP1_MESSAGE_ORIENTED)) + { + /* Check if this is a Stream Socket */ + if (SocketType == SOCK_STREAM) + { + /* Check if we actually support this */ + if (!(Socket->SharedData.ServiceFlags1 & XP1_PSEUDO_STREAM)) + { + /* The Provider doesn't support Message Oriented Streams */ + ErrorCode = WSAEINVAL; + goto error; + } + } + + /* Set the flag for AFD */ + AfdPacket->EndpointFlags |= AFD_ENDPOINT_MESSAGE_ORIENTED; + } + + /* If this is a Raw Socket, let AFD know */ + if (SocketType == SOCK_RAW) AfdPacket->EndpointFlags |= AFD_ENDPOINT_RAW; + + /* Check if we are a Multipoint Control/Data Root or Leaf */ + if (dwFlags & (WSA_FLAG_MULTIPOINT_C_ROOT | + WSA_FLAG_MULTIPOINT_C_LEAF | + WSA_FLAG_MULTIPOINT_D_ROOT | + WSA_FLAG_MULTIPOINT_D_LEAF)) + { + /* First make sure we support Multipoint */ + if (!(Socket->SharedData.ServiceFlags1 & XP1_SUPPORT_MULTIPOINT)) + { + /* The Provider doesn't actually support Multipoint */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Set the flag for AFD */ + AfdPacket->EndpointFlags |= AFD_ENDPOINT_MULTIPOINT; + + /* Check if we are a Control Plane Root */ + if (dwFlags & WSA_FLAG_MULTIPOINT_C_ROOT) + { + /* Check if we actually support this or if we're already a leaf */ + if ((!(Socket->SharedData.ServiceFlags1 & + XP1_MULTIPOINT_CONTROL_PLANE)) || + ((dwFlags & WSA_FLAG_MULTIPOINT_C_LEAF))) + { + ErrorCode = WSAEINVAL; + goto error; + } + + /* Set the flag for AFD */ + AfdPacket->EndpointFlags |= AFD_ENDPOINT_C_ROOT; + } + + /* Check if we a Data Plane Root */ + if (dwFlags & WSA_FLAG_MULTIPOINT_D_ROOT) + { + /* Check if we actually support this or if we're already a leaf */ + if ((!(Socket->SharedData.ServiceFlags1 & + XP1_MULTIPOINT_DATA_PLANE)) || + ((dwFlags & WSA_FLAG_MULTIPOINT_D_LEAF))) + { + ErrorCode = WSAEINVAL; + goto error; + } + + /* Set the flag for AFD */ + AfdPacket->EndpointFlags |= AFD_ENDPOINT_D_ROOT; + } + } + + /* Set the group ID */ + AfdPacket->GroupID = g; + + /* Set up Object Attributes */ + RtlInitUnicodeString(&DevName, L"\\Device\\Afd\\Endpoint"); + InitializeObjectAttributes(&ObjectAttributes, + &DevName, + OBJ_CASE_INSENSITIVE | OBJ_INHERIT, + NULL, + NULL); + + /* Check if we're not using Overlapped I/O */ + if (!(dwFlags & WSA_FLAG_OVERLAPPED)) + { + /* Set Synchronous I/O */ + CreateOptions = FILE_SYNCHRONOUS_IO_NONALERT; + } + + /* Acquire the global lock */ + SockAcquireRwLockShared(&SocketGlobalLock); + + /* Create the Socket */ + Status = NtCreateFile((PHANDLE)&Handle, + GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, + &ObjectAttributes, + &IoStatusBlock, + NULL, + 0, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_OPEN_IF, + CreateOptions, + Ea, + SizeOfEa); + if (!NT_SUCCESS(Status)) + { + /* Release the lock and fail */ + SockReleaseRwLockShared(&SocketGlobalLock); + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* Save Handle */ + Socket->Handle = Handle; + + /* Check if a group was given */ + if (g != 0) + { + /* Get Group Id and Type */ + ErrorCode = SockGetInformation(Socket, + AFD_INFO_GROUP_ID_TYPE, + NULL, + 0, + NULL, + NULL, + &GroupData); + + /* Save them */ + Socket->SharedData.GroupID = GroupData.u.LowPart; + Socket->SharedData.GroupType = GroupData.u.HighPart; + } + + /* Check if we need to get the window sizes */ + if (!SockSendBufferWindow) + { + /* Get send window size */ + SockGetInformation(Socket, + AFD_INFO_SEND_WINDOW_SIZE, + NULL, + 0, + NULL, + &SockSendBufferWindow, + NULL); + + /* Get receive window size */ + SockGetInformation(Socket, + AFD_INFO_RECEIVE_WINDOW_SIZE, + NULL, + 0, + NULL, + &SockReceiveBufferWindow, + NULL); + } + + /* Save window sizes */ + Socket->SharedData.SizeOfRecvBuffer = SockReceiveBufferWindow; + Socket->SharedData.SizeOfSendBuffer = SockSendBufferWindow; + + /* Insert it into our table */ + WahHandle = WahInsertHandleContext(SockContextTable, &Socket->WshContext); + + /* We can release the lock now */ + SockReleaseRwLockShared(&SocketGlobalLock); + + /* Check if the handles don't match for some reason */ + if (WahHandle != &Socket->WshContext) + { + /* Do they not match? */ + if (WahHandle) + { + /* They don't... someone must've used CloseHandle */ + SockDereferenceSocket((PSOCKET_INFORMATION)WahHandle); + + /* Use the correct handle now */ + WahHandle = &Socket->WshContext; + } + else + { + /* It's not that they don't match: we don't have one at all! */ + ErrorCode = WSAENOBUFS; + goto error; + } + } + +error: + /* Check if we can free the transport name */ + if ((SocketType == SOCK_RAW) && (TransportName.Buffer)) + { + /* Free it */ + RtlFreeHeap(RtlGetProcessHeap(), 0, TransportName.Buffer); + } + + /* Check if we have the EA from the heap */ + if ((Ea) && (Ea != (PVOID)AfdPacketBuffer)) + { + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, Ea); + } + + /* Check if this is actually success */ + if (ErrorCode != NO_ERROR) + { + /* Check if we have a socket by now */ + if (Socket) + { + /* Tell the Helper DLL we're closing it */ + SockNotifyHelperDll(Socket, WSH_NOTIFY_CLOSE); + + /* Close its handle if it's valid */ + if (Socket->WshContext.Handle != INVALID_HANDLE_VALUE) + { + NtClose(Socket->WshContext.Handle); + } + + /* Delete its lock */ + if (LockInit) DeleteCriticalSection(&Socket->Lock); + + /* Remove our socket reference */ + SockDereferenceSocket(Socket); + + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, Socket); + } + } + + /* Return Socket and error code */ + *NewSocket = Socket; + return ErrorCode; +} + +INT +WSPAPI +SockCloseSocket(IN PSOCKET_INFORMATION Socket) +{ + INT ErrorCode; + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + AFD_DISCONNECT_INFO DisconnectInfo; + SOCKET_STATE OldState; + ULONG LingerWait; + ULONG SendsInProgress; + ULONG SleepWait; + BOOLEAN ActiveConnect; + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* If a Close is already in Process... */ + if (Socket->SharedData.State == SocketClosed) + { + /* Release lock and fail */ + LeaveCriticalSection(&Socket->Lock); + return WSAENOTSOCK; + } + + /* Save the old state and set the new one to closed */ + OldState = Socket->SharedData.State; + Socket->SharedData.State = SocketClosed; + + /* Check if the socket has an active async data */ + ActiveConnect = (Socket->AsyncData != NULL); + + /* We're done with the socket, release the lock */ + LeaveCriticalSection(&Socket->Lock); + + /* + * If SO_LINGER is ON and the Socket was connected or had an active async + * connect context, then we'll disconnect it. Note that we won't do this + * for connection-less (UDP/RAW) sockets or if a send shutdown is active. + */ + if ((OldState == SocketConnected || ActiveConnect) && + !(Socket->SharedData.SendShutdown) && + !MSAFD_IS_DGRAM_SOCK(Socket) && + (Socket->SharedData.LingerData.l_onoff)) + { + /* We need to respect the timeout */ + SleepWait = 100; + LingerWait = Socket->SharedData.LingerData.l_linger * 1000; + + /* Loop until no more sends are pending, within the timeout */ + while (LingerWait) + { + /* Find out how many Sends are in Progress */ + if (SockGetInformation(Socket, + AFD_INFO_SENDS_IN_PROGRESS, + NULL, + 0, + NULL, + &SendsInProgress, + NULL)) + { + /* Bail out if anything but NO_ERROR */ + LingerWait = 0; + break; + } + + /* Bail out if no more sends are pending */ + if (!SendsInProgress) break; + + /* + * We have to execute a sleep, so it's kind of like + * a block. If the socket is Nonblock, we cannot + * go on since asyncronous operation is expected + * and we cannot offer it + */ + if (Socket->SharedData.NonBlocking) + { + /* Acquire the socket lock */ + EnterCriticalSection(&Socket->Lock); + + /* Restore the socket state */ + Socket->SharedData.State = OldState; + + /* Release the lock again */ + LeaveCriticalSection(&Socket->Lock); + + /* Fail with error code */ + return WSAEWOULDBLOCK; + } + + /* Now we can sleep, and decrement the linger wait */ + /* + * FIXME: It seems Windows does some funky acceleration + * since the waiting seems to be longer and longer. I + * don't think this improves performance so much, so we + * wait a fixed time instead. + */ + Sleep(SleepWait); + LingerWait -= SleepWait; + } + + /* + * We have reached the timeout or sends are over. + * Disconnect if the timeout has been reached. + */ + if (LingerWait <= 0) + { + /* There is no timeout, and this is an abortive disconnect */ + DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(0); + DisconnectInfo.DisconnectType = AFD_DISCONNECT_ABORT; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_DISCONNECT, + &DisconnectInfo, + sizeof(DisconnectInfo), + NULL, + 0); + /* Check if the operation is pending */ + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + !Socket->SharedData.LingerData.l_onoff ? + NO_BLOCKING_HOOK : ALWAYS_BLOCKING_HOOK, + NO_TIMEOUT); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* We actually accept errors, unless the driver wasn't ready */ + if (Status == STATUS_DEVICE_NOT_READY) + { + /* This is the equivalent of a WOULDBLOCK, which we fail */ + /* Acquire the socket lock */ + EnterCriticalSection(&Socket->Lock); + + /* Restore the socket state */ + Socket->SharedData.State = OldState; + + /* Release the lock again */ + LeaveCriticalSection(&Socket->Lock); + + /* Fail with error code */ + return WSAEWOULDBLOCK; + } + } + } + + /* Acquire the global lock to protect the handle table */ + SockAcquireRwLockShared(&SocketGlobalLock); + + /* Protect the socket too */ + EnterCriticalSection(&Socket->Lock); + + /* Notify the Helper DLL of Socket Closure */ + ErrorCode = SockNotifyHelperDll(Socket, WSH_NOTIFY_CLOSE); + + /* Cleanup Time! */ + Socket->HelperContext = NULL; + Socket->SharedData.AsyncDisabledEvents = -1; + if (Socket->TdiAddressHandle) + { + /* Close and forget the handle */ + NtClose(Socket->TdiAddressHandle); + Socket->TdiAddressHandle = NULL; + } + if (Socket->TdiConnectionHandle) + { + /* Close and forget the handle */ + NtClose(Socket->TdiConnectionHandle); + Socket->TdiConnectionHandle = NULL; + } + + /* Remove the handle from the table */ + ErrorCode = WahRemoveHandleContext(SockContextTable, &Socket->WshContext); + if (ErrorCode == NO_ERROR) + { + /* Close the socket's handle */ + NtClose(Socket->WshContext.Handle); + + /* Dereference the socket */ + SockDereferenceSocket(Socket); + } + else + { + /* This isn't a socket anymore, or something */ + ErrorCode = WSAENOTSOCK; + } + + /* Release both locks */ + LeaveCriticalSection(&Socket->Lock); + SockReleaseRwLockShared(&SocketGlobalLock); + + /* Return success */ + return ErrorCode; +} + +SOCKET +WSPAPI +WSPSocket(INT AddressFamily, + INT SocketType, + INT Protocol, + LPWSAPROTOCOL_INFOW lpProtocolInfo, + GROUP g, + DWORD dwFlags, + LPINT lpErrno) +{ + DWORD CatalogId; + SOCKET Handle = INVALID_SOCKET; + INT ErrorCode; + DWORD ServiceFlags, ProviderFlags; + PWINSOCK_TEB_DATA ThreadData; + PSOCKET_INFORMATION Socket; + GUID ProviderId; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return INVALID_SOCKET; + } + + /* Get the catalog ID */ + CatalogId = lpProtocolInfo->dwCatalogEntryId; + + /* Check if this is a duplication */ + if(lpProtocolInfo->dwProviderReserved) + { + /* Get the duplicate handle */ + Handle = (SOCKET)lpProtocolInfo->dwProviderReserved; + + /* Get our structure for it */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if(Socket) + { + /* Tell Winsock about it */ + Socket->Handle = SockUpcallTable->lpWPUModifyIFSHandle(CatalogId, + Handle, + &ErrorCode); + /* Check if we got an invalid handle back */ + if(Socket->Handle == INVALID_SOCKET) + { + /* Restore it for the error path */ + Socket->Handle = Handle; + } + } + else + { + /* The duplicate handle is invalid */ + ErrorCode = WSAEINVAL; + } + + /* Fail */ + goto error; + } + + /* See if the address family should be recovered from the protocl info */ + if (!AddressFamily || AddressFamily == FROM_PROTOCOL_INFO) + { + /* Use protocol info data */ + AddressFamily = lpProtocolInfo->iAddressFamily; + } + + /* See if the address family should be recovered from the protocl info */ + if(!SocketType || SocketType == FROM_PROTOCOL_INFO ) + { + /* Use protocol info data */ + SocketType = lpProtocolInfo->iSocketType; + } + + /* See if the address family should be recovered from the protocl info */ + if(Protocol == FROM_PROTOCOL_INFO) + { + /* Use protocol info data */ + Protocol = lpProtocolInfo->iProtocol; + } + + /* Save the service, provider flags and provider ID */ + ServiceFlags = lpProtocolInfo->dwServiceFlags1; + ProviderFlags = lpProtocolInfo->dwProviderFlags; + ProviderId = lpProtocolInfo->ProviderId; + + /* Create the actual socket */ + ErrorCode = SockSocket(AddressFamily, + SocketType, + Protocol, + &ProviderId, + g, + dwFlags, + ProviderFlags, + ServiceFlags, + CatalogId, + &Socket); + if (ErrorCode == ERROR_SUCCESS) + { + /* Acquire the socket lock */ + EnterCriticalSection(&Socket->Lock); + + /* Set status to opened */ + Socket->SharedData.State = SocketOpen; + + /* Create the Socket Context */ + ErrorCode = SockSetHandleContext(Socket); + if (ErrorCode != NO_ERROR) + { + /* Release the lock, close the socket and fail */ + LeaveCriticalSection(&Socket->Lock); + SockCloseSocket(Socket); + goto error; + } + + /* Notify Winsock */ + Handle = SockUpcallTable->lpWPUModifyIFSHandle(Socket->SharedData.CatalogEntryId, + (SOCKET)Socket->WshContext.Handle, + &ErrorCode); + + /* Does Winsock not like it? */ + if (Handle == INVALID_SOCKET) + { + /* Release the lock, close the socket and fail */ + LeaveCriticalSection(&Socket->Lock); + SockCloseSocket(Socket); + goto error; + } + + /* Release the lock */ + LeaveCriticalSection(&Socket->Lock); + } + +error: + /* Write return code */ + *lpErrno = ErrorCode; + + /* Check if we have a socket and dereference it */ + if (Socket) SockDereferenceSocket(Socket); + + /* Return handle */ + return Handle; +} + +INT +WSPAPI +WSPCloseSocket(IN SOCKET Handle, + OUT LPINT lpErrno) +{ + INT ErrorCode; + PSOCKET_INFORMATION Socket; + PWINSOCK_TEB_DATA ThreadData; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + *lpErrno = WSAENOTSOCK; + return SOCKET_ERROR; + } + + /* Close it */ + ErrorCode = SockCloseSocket(Socket); + + /* Remove the final reference */ + SockDereferenceSocket(Socket); + + /* Check if we got here by error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +SockSocket(INT AddressFamily, + INT SocketType, + INT Protocol, + LPGUID ProviderId, + GROUP g, + DWORD dwFlags, + DWORD ProviderFlags, + DWORD ServiceFlags, + DWORD CatalogEntryId, + PSOCKET_INFORMATION *NewSocket) +{ + INT ErrorCode; + UNICODE_STRING TransportName; + PVOID HelperDllContext; + PHELPER_DATA HelperData = NULL; + DWORD HelperEvents; + PFILE_FULL_EA_INFORMATION Ea = NULL; + PAFD_CREATE_PACKET AfdPacket; + SOCKET Handle = INVALID_SOCKET; + PSOCKET_INFORMATION Socket = NULL; + BOOLEAN LockInit = FALSE; + USHORT SizeOfPacket; + DWORD SizeOfEa, SocketLength; + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING DevName; + LARGE_INTEGER GroupData; + DWORD CreateOptions = 0; + IO_STATUS_BLOCK IoStatusBlock; + PWAH_HANDLE WahHandle; + NTSTATUS Status; + CHAR AfdPacketBuffer[96]; + + /* Initialize the transport name */ + RtlInitUnicodeString(&TransportName, NULL); + + /* Get Helper Data and Transport */ + ErrorCode = SockGetTdiName(&AddressFamily, + &SocketType, + &Protocol, + ProviderId, + g, + dwFlags, + &TransportName, + &HelperDllContext, + &HelperData, + &HelperEvents); + + /* Check for error */ + if (ErrorCode != NO_ERROR) goto error; + + /* Figure out the socket context structure size */ + SocketLength = sizeof(*Socket) + (HelperData->MinWSAddressLength * 2); + + /* Allocate a socket */ + Socket = SockAllocateHeapRoutine(SockPrivateHeap, 0, SocketLength); + if (!Socket) + { + /* Couldn't create it; we need to tell WSH so it can cleanup */ + if (HelperEvents & WSH_NOTIFY_CLOSE) + { + HelperData->WSHNotify(HelperDllContext, + INVALID_SOCKET, + NULL, + NULL, + WSH_NOTIFY_CLOSE); + } + + /* Fail and return */ + ErrorCode = WSAENOBUFS; + goto error; + } + + /* Initialize it */ + RtlZeroMemory(Socket, SocketLength); + Socket->RefCount = 2; + Socket->Handle = INVALID_SOCKET; + Socket->SharedData.State = SocketUndefined; + Socket->SharedData.AddressFamily = AddressFamily; + Socket->SharedData.SocketType = SocketType; + Socket->SharedData.Protocol = Protocol; + Socket->ProviderId = *ProviderId; + Socket->HelperContext = HelperDllContext; + Socket->HelperData = HelperData; + Socket->HelperEvents = HelperEvents; + Socket->LocalAddress = (PVOID)(Socket + 1); + Socket->SharedData.SizeOfLocalAddress = HelperData->MaxWSAddressLength; + Socket->RemoteAddress = (PVOID)((ULONG_PTR)Socket->LocalAddress + + HelperData->MaxWSAddressLength); + Socket->SharedData.SizeOfRemoteAddress = HelperData->MaxWSAddressLength; + Socket->SharedData.UseDelayedAcceptance = HelperData->UseDelayedAcceptance; + Socket->SharedData.CreateFlags = dwFlags; + Socket->SharedData.CatalogEntryId = CatalogEntryId; + Socket->SharedData.ServiceFlags1 = ServiceFlags; + Socket->SharedData.ProviderFlags = ProviderFlags; + Socket->SharedData.GroupID = g; + Socket->SharedData.GroupType = 0; + Socket->SharedData.UseSAN = FALSE; + Socket->SanData = NULL; + Socket->DontUseSan = FALSE; + + /* Initialize the socket lock */ + InitializeCriticalSection(&Socket->Lock); + LockInit = TRUE; + + /* Packet Size */ + SizeOfPacket = TransportName.Length + sizeof(*AfdPacket) + sizeof(WCHAR); + + /* EA Size */ + SizeOfEa = SizeOfPacket + sizeof(*Ea) + AFD_PACKET_COMMAND_LENGTH; + + /* See if our stack buffer is big enough to hold it */ + if (SizeOfEa <= sizeof(AfdPacketBuffer)) + { + /* Use our stack */ + Ea = (PFILE_FULL_EA_INFORMATION)AfdPacketBuffer; + } + else + { + /* Allocate from heap */ + Ea = SockAllocateHeapRoutine(SockPrivateHeap, 0, SizeOfEa); + if (!Ea) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + } + + /* Set up EA */ + Ea->NextEntryOffset = 0; + Ea->Flags = 0; + Ea->EaNameLength = AFD_PACKET_COMMAND_LENGTH; + RtlCopyMemory(Ea->EaName, AfdCommand, AFD_PACKET_COMMAND_LENGTH + 1); + Ea->EaValueLength = SizeOfPacket; + + /* Set up AFD Packet */ + AfdPacket = (PAFD_CREATE_PACKET)(Ea->EaName + Ea->EaNameLength + 1); + AfdPacket->SizeOfTransportName = TransportName.Length; + RtlCopyMemory(AfdPacket->TransportName, + TransportName.Buffer, + TransportName.Length + sizeof(WCHAR)); + AfdPacket->EndpointFlags = 0; + + /* Set up Endpoint Flags */ + if ((Socket->SharedData.ServiceFlags1 & XP1_CONNECTIONLESS)) + { + /* Check the Socket Type */ + if ((SocketType != SOCK_DGRAM) && (SocketType != SOCK_RAW)) + { + /* Only RAW or UDP can be Connectionless */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Set the flag for AFD */ + AfdPacket->EndpointFlags |= AFD_ENDPOINT_CONNECTIONLESS; + } + + if ((Socket->SharedData.ServiceFlags1 & XP1_MESSAGE_ORIENTED)) + { + /* Check if this is a Stream Socket */ + if (SocketType == SOCK_STREAM) + { + /* Check if we actually support this */ + if (!(Socket->SharedData.ServiceFlags1 & XP1_PSEUDO_STREAM)) + { + /* The Provider doesn't support Message Oriented Streams */ + ErrorCode = WSAEINVAL; + goto error; + } + } + + /* Set the flag for AFD */ + AfdPacket->EndpointFlags |= AFD_ENDPOINT_MESSAGE_ORIENTED; + } + + /* If this is a Raw Socket, let AFD know */ + if (SocketType == SOCK_RAW) AfdPacket->EndpointFlags |= AFD_ENDPOINT_RAW; + + /* Check if we are a Multipoint Control/Data Root or Leaf */ + if (dwFlags & (WSA_FLAG_MULTIPOINT_C_ROOT | + WSA_FLAG_MULTIPOINT_C_LEAF | + WSA_FLAG_MULTIPOINT_D_ROOT | + WSA_FLAG_MULTIPOINT_D_LEAF)) + { + /* First make sure we support Multipoint */ + if (!(Socket->SharedData.ServiceFlags1 & XP1_SUPPORT_MULTIPOINT)) + { + /* The Provider doesn't actually support Multipoint */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Set the flag for AFD */ + AfdPacket->EndpointFlags |= AFD_ENDPOINT_MULTIPOINT; + + /* Check if we are a Control Plane Root */ + if (dwFlags & WSA_FLAG_MULTIPOINT_C_ROOT) + { + /* Check if we actually support this or if we're already a leaf */ + if ((!(Socket->SharedData.ServiceFlags1 & + XP1_MULTIPOINT_CONTROL_PLANE)) || + ((dwFlags & WSA_FLAG_MULTIPOINT_C_LEAF))) + { + ErrorCode = WSAEINVAL; + goto error; + } + + /* Set the flag for AFD */ + AfdPacket->EndpointFlags |= AFD_ENDPOINT_C_ROOT; + } + + /* Check if we a Data Plane Root */ + if (dwFlags & WSA_FLAG_MULTIPOINT_D_ROOT) + { + /* Check if we actually support this or if we're already a leaf */ + if ((!(Socket->SharedData.ServiceFlags1 & + XP1_MULTIPOINT_DATA_PLANE)) || + ((dwFlags & WSA_FLAG_MULTIPOINT_D_LEAF))) + { + ErrorCode = WSAEINVAL; + goto error; + } + + /* Set the flag for AFD */ + AfdPacket->EndpointFlags |= AFD_ENDPOINT_D_ROOT; + } + } + + /* Set the group ID */ + AfdPacket->GroupID = g; + + /* Set up Object Attributes */ + RtlInitUnicodeString(&DevName, L"\\Device\\Afd\\Endpoint"); + InitializeObjectAttributes(&ObjectAttributes, + &DevName, + OBJ_CASE_INSENSITIVE | OBJ_INHERIT, + NULL, + NULL); + + /* Check if we're not using Overlapped I/O */ + if (!(dwFlags & WSA_FLAG_OVERLAPPED)) + { + /* Set Synchronous I/O */ + CreateOptions = FILE_SYNCHRONOUS_IO_NONALERT; + } + + /* Acquire the global lock */ + SockAcquireRwLockShared(&SocketGlobalLock); + + /* Create the Socket */ + Status = NtCreateFile((PHANDLE)&Handle, + GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, + &ObjectAttributes, + &IoStatusBlock, + NULL, + 0, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_OPEN_IF, + CreateOptions, + Ea, + SizeOfEa); + if (!NT_SUCCESS(Status)) + { + /* Release the lock and fail */ + SockReleaseRwLockShared(&SocketGlobalLock); + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* Save Handle */ + Socket->Handle = Handle; + + /* Check if a group was given */ + if (g != 0) + { + /* Get Group Id and Type */ + ErrorCode = SockGetInformation(Socket, + AFD_INFO_GROUP_ID_TYPE, + NULL, + 0, + NULL, + NULL, + &GroupData); + + /* Save them */ + Socket->SharedData.GroupID = GroupData.u.LowPart; + Socket->SharedData.GroupType = GroupData.u.HighPart; + } + + /* Check if we need to get the window sizes */ + if (!SockSendBufferWindow) + { + /* Get send window size */ + SockGetInformation(Socket, + AFD_INFO_SEND_WINDOW_SIZE, + NULL, + 0, + NULL, + &SockSendBufferWindow, + NULL); + + /* Get receive window size */ + SockGetInformation(Socket, + AFD_INFO_RECEIVE_WINDOW_SIZE, + NULL, + 0, + NULL, + &SockReceiveBufferWindow, + NULL); + } + + /* Save window sizes */ + Socket->SharedData.SizeOfRecvBuffer = SockReceiveBufferWindow; + Socket->SharedData.SizeOfSendBuffer = SockSendBufferWindow; + + /* Insert it into our table */ + WahHandle = WahInsertHandleContext(SockContextTable, &Socket->WshContext); + + /* We can release the lock now */ + SockReleaseRwLockShared(&SocketGlobalLock); + + /* Check if the handles don't match for some reason */ + if (WahHandle != &Socket->WshContext) + { + /* Do they not match? */ + if (WahHandle) + { + /* They don't... someone must've used CloseHandle */ + SockDereferenceSocket((PSOCKET_INFORMATION)WahHandle); + + /* Use the correct handle now */ + WahHandle = &Socket->WshContext; + } + else + { + /* It's not that they don't match: we don't have one at all! */ + ErrorCode = WSAENOBUFS; + goto error; + } + } + +error: + /* Check if we can free the transport name */ + if ((SocketType == SOCK_RAW) && (TransportName.Buffer)) + { + /* Free it */ + RtlFreeHeap(RtlGetProcessHeap(), 0, TransportName.Buffer); + } + + /* Check if we have the EA from the heap */ + if ((Ea) && (Ea != (PVOID)AfdPacketBuffer)) + { + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, Ea); + } + + /* Check if this is actually success */ + if (ErrorCode != NO_ERROR) + { + /* Check if we have a socket by now */ + if (Socket) + { + /* Tell the Helper DLL we're closing it */ + SockNotifyHelperDll(Socket, WSH_NOTIFY_CLOSE); + + /* Close its handle if it's valid */ + if (Socket->WshContext.Handle != INVALID_HANDLE_VALUE) + { + NtClose(Socket->WshContext.Handle); + } + + /* Delete its lock */ + if (LockInit) DeleteCriticalSection(&Socket->Lock); + + /* Remove our socket reference */ + SockDereferenceSocket(Socket); + + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, Socket); + } + } + + /* Return Socket and error code */ + *NewSocket = Socket; + return ErrorCode; +} + +INT +WSPAPI +SockCloseSocket(IN PSOCKET_INFORMATION Socket) +{ + INT ErrorCode; + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + AFD_DISCONNECT_INFO DisconnectInfo; + SOCKET_STATE OldState; + ULONG LingerWait; + ULONG SendsInProgress; + ULONG SleepWait; + BOOLEAN ActiveConnect; + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* If a Close is already in Process... */ + if (Socket->SharedData.State == SocketClosed) + { + /* Release lock and fail */ + LeaveCriticalSection(&Socket->Lock); + return WSAENOTSOCK; + } + + /* Save the old state and set the new one to closed */ + OldState = Socket->SharedData.State; + Socket->SharedData.State = SocketClosed; + + /* Check if the socket has an active async data */ + ActiveConnect = (Socket->AsyncData != NULL); + + /* We're done with the socket, release the lock */ + LeaveCriticalSection(&Socket->Lock); + + /* + * If SO_LINGER is ON and the Socket was connected or had an active async + * connect context, then we'll disconnect it. Note that we won't do this + * for connection-less (UDP/RAW) sockets or if a send shutdown is active. + */ + if ((OldState == SocketConnected || ActiveConnect) && + !(Socket->SharedData.SendShutdown) && + !MSAFD_IS_DGRAM_SOCK(Socket) && + (Socket->SharedData.LingerData.l_onoff)) + { + /* We need to respect the timeout */ + SleepWait = 100; + LingerWait = Socket->SharedData.LingerData.l_linger * 1000; + + /* Loop until no more sends are pending, within the timeout */ + while (LingerWait) + { + /* Find out how many Sends are in Progress */ + if (SockGetInformation(Socket, + AFD_INFO_SENDS_IN_PROGRESS, + NULL, + 0, + NULL, + &SendsInProgress, + NULL)) + { + /* Bail out if anything but NO_ERROR */ + LingerWait = 0; + break; + } + + /* Bail out if no more sends are pending */ + if (!SendsInProgress) break; + + /* + * We have to execute a sleep, so it's kind of like + * a block. If the socket is Nonblock, we cannot + * go on since asyncronous operation is expected + * and we cannot offer it + */ + if (Socket->SharedData.NonBlocking) + { + /* Acquire the socket lock */ + EnterCriticalSection(&Socket->Lock); + + /* Restore the socket state */ + Socket->SharedData.State = OldState; + + /* Release the lock again */ + LeaveCriticalSection(&Socket->Lock); + + /* Fail with error code */ + return WSAEWOULDBLOCK; + } + + /* Now we can sleep, and decrement the linger wait */ + /* + * FIXME: It seems Windows does some funky acceleration + * since the waiting seems to be longer and longer. I + * don't think this improves performance so much, so we + * wait a fixed time instead. + */ + Sleep(SleepWait); + LingerWait -= SleepWait; + } + + /* + * We have reached the timeout or sends are over. + * Disconnect if the timeout has been reached. + */ + if (LingerWait <= 0) + { + /* There is no timeout, and this is an abortive disconnect */ + DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(0); + DisconnectInfo.DisconnectType = AFD_DISCONNECT_ABORT; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_DISCONNECT, + &DisconnectInfo, + sizeof(DisconnectInfo), + NULL, + 0); + /* Check if the operation is pending */ + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + !Socket->SharedData.LingerData.l_onoff ? + NO_BLOCKING_HOOK : ALWAYS_BLOCKING_HOOK, + NO_TIMEOUT); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* We actually accept errors, unless the driver wasn't ready */ + if (Status == STATUS_DEVICE_NOT_READY) + { + /* This is the equivalent of a WOULDBLOCK, which we fail */ + /* Acquire the socket lock */ + EnterCriticalSection(&Socket->Lock); + + /* Restore the socket state */ + Socket->SharedData.State = OldState; + + /* Release the lock again */ + LeaveCriticalSection(&Socket->Lock); + + /* Fail with error code */ + return WSAEWOULDBLOCK; + } + } + } + + /* Acquire the global lock to protect the handle table */ + SockAcquireRwLockShared(&SocketGlobalLock); + + /* Protect the socket too */ + EnterCriticalSection(&Socket->Lock); + + /* Notify the Helper DLL of Socket Closure */ + ErrorCode = SockNotifyHelperDll(Socket, WSH_NOTIFY_CLOSE); + + /* Cleanup Time! */ + Socket->HelperContext = NULL; + Socket->SharedData.AsyncDisabledEvents = -1; + if (Socket->TdiAddressHandle) + { + /* Close and forget the handle */ + NtClose(Socket->TdiAddressHandle); + Socket->TdiAddressHandle = NULL; + } + if (Socket->TdiConnectionHandle) + { + /* Close and forget the handle */ + NtClose(Socket->TdiConnectionHandle); + Socket->TdiConnectionHandle = NULL; + } + + /* Remove the handle from the table */ + ErrorCode = WahRemoveHandleContext(SockContextTable, &Socket->WshContext); + if (ErrorCode == NO_ERROR) + { + /* Close the socket's handle */ + NtClose(Socket->WshContext.Handle); + + /* Dereference the socket */ + SockDereferenceSocket(Socket); + } + else + { + /* This isn't a socket anymore, or something */ + ErrorCode = WSAENOTSOCK; + } + + /* Release both locks */ + LeaveCriticalSection(&Socket->Lock); + SockReleaseRwLockShared(&SocketGlobalLock); + + /* Return success */ + return ErrorCode; +} + +SOCKET +WSPAPI +WSPSocket(INT AddressFamily, + INT SocketType, + INT Protocol, + LPWSAPROTOCOL_INFOW lpProtocolInfo, + GROUP g, + DWORD dwFlags, + LPINT lpErrno) +{ + DWORD CatalogId; + SOCKET Handle = INVALID_SOCKET; + INT ErrorCode; + DWORD ServiceFlags, ProviderFlags; + PWINSOCK_TEB_DATA ThreadData; + PSOCKET_INFORMATION Socket; + GUID ProviderId; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return INVALID_SOCKET; + } + + /* Get the catalog ID */ + CatalogId = lpProtocolInfo->dwCatalogEntryId; + + /* Check if this is a duplication */ + if(lpProtocolInfo->dwProviderReserved) + { + /* Get the duplicate handle */ + Handle = (SOCKET)lpProtocolInfo->dwProviderReserved; + + /* Get our structure for it */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if(Socket) + { + /* Tell Winsock about it */ + Socket->Handle = SockUpcallTable->lpWPUModifyIFSHandle(CatalogId, + Handle, + &ErrorCode); + /* Check if we got an invalid handle back */ + if(Socket->Handle == INVALID_SOCKET) + { + /* Restore it for the error path */ + Socket->Handle = Handle; + } + } + else + { + /* The duplicate handle is invalid */ + ErrorCode = WSAEINVAL; + } + + /* Fail */ + goto error; + } + + /* See if the address family should be recovered from the protocl info */ + if (!AddressFamily || AddressFamily == FROM_PROTOCOL_INFO) + { + /* Use protocol info data */ + AddressFamily = lpProtocolInfo->iAddressFamily; + } + + /* See if the address family should be recovered from the protocl info */ + if(!SocketType || SocketType == FROM_PROTOCOL_INFO ) + { + /* Use protocol info data */ + SocketType = lpProtocolInfo->iSocketType; + } + + /* See if the address family should be recovered from the protocl info */ + if(Protocol == FROM_PROTOCOL_INFO) + { + /* Use protocol info data */ + Protocol = lpProtocolInfo->iProtocol; + } + + /* Save the service, provider flags and provider ID */ + ServiceFlags = lpProtocolInfo->dwServiceFlags1; + ProviderFlags = lpProtocolInfo->dwProviderFlags; + ProviderId = lpProtocolInfo->ProviderId; + + /* Create the actual socket */ + ErrorCode = SockSocket(AddressFamily, + SocketType, + Protocol, + &ProviderId, + g, + dwFlags, + ProviderFlags, + ServiceFlags, + CatalogId, + &Socket); + if (ErrorCode == ERROR_SUCCESS) + { + /* Acquire the socket lock */ + EnterCriticalSection(&Socket->Lock); + + /* Set status to opened */ + Socket->SharedData.State = SocketOpen; + + /* Create the Socket Context */ + ErrorCode = SockSetHandleContext(Socket); + if (ErrorCode != NO_ERROR) + { + /* Release the lock, close the socket and fail */ + LeaveCriticalSection(&Socket->Lock); + SockCloseSocket(Socket); + goto error; + } + + /* Notify Winsock */ + Handle = SockUpcallTable->lpWPUModifyIFSHandle(Socket->SharedData.CatalogEntryId, + (SOCKET)Socket->WshContext.Handle, + &ErrorCode); + + /* Does Winsock not like it? */ + if (Handle == INVALID_SOCKET) + { + /* Release the lock, close the socket and fail */ + LeaveCriticalSection(&Socket->Lock); + SockCloseSocket(Socket); + goto error; + } + + /* Release the lock */ + LeaveCriticalSection(&Socket->Lock); + } + +error: + /* Write return code */ + *lpErrno = ErrorCode; + + /* Check if we have a socket and dereference it */ + if (Socket) SockDereferenceSocket(Socket); + + /* Return handle */ + return Handle; +} + +INT +WSPAPI +WSPCloseSocket(IN SOCKET Handle, + OUT LPINT lpErrno) +{ + INT ErrorCode; + PSOCKET_INFORMATION Socket; + PWINSOCK_TEB_DATA ThreadData; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + *lpErrno = WSAENOTSOCK; + return SOCKET_ERROR; + } + + /* Close it */ + ErrorCode = SockCloseSocket(Socket); + + /* Remove the final reference */ + SockDereferenceSocket(Socket); + + /* Check if we got here by error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +SockSocket(INT AddressFamily, + INT SocketType, + INT Protocol, + LPGUID ProviderId, + GROUP g, + DWORD dwFlags, + DWORD ProviderFlags, + DWORD ServiceFlags, + DWORD CatalogEntryId, + PSOCKET_INFORMATION *NewSocket) +{ + INT ErrorCode; + UNICODE_STRING TransportName; + PVOID HelperDllContext; + PHELPER_DATA HelperData = NULL; + DWORD HelperEvents; + PFILE_FULL_EA_INFORMATION Ea = NULL; + PAFD_CREATE_PACKET AfdPacket; + SOCKET Handle = INVALID_SOCKET; + PSOCKET_INFORMATION Socket = NULL; + BOOLEAN LockInit = FALSE; + USHORT SizeOfPacket; + DWORD SizeOfEa, SocketLength; + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING DevName; + LARGE_INTEGER GroupData; + DWORD CreateOptions = 0; + IO_STATUS_BLOCK IoStatusBlock; + PWAH_HANDLE WahHandle; + NTSTATUS Status; + CHAR AfdPacketBuffer[96]; + + /* Initialize the transport name */ + RtlInitUnicodeString(&TransportName, NULL); + + /* Get Helper Data and Transport */ + ErrorCode = SockGetTdiName(&AddressFamily, + &SocketType, + &Protocol, + ProviderId, + g, + dwFlags, + &TransportName, + &HelperDllContext, + &HelperData, + &HelperEvents); + + /* Check for error */ + if (ErrorCode != NO_ERROR) goto error; + + /* Figure out the socket context structure size */ + SocketLength = sizeof(*Socket) + (HelperData->MinWSAddressLength * 2); + + /* Allocate a socket */ + Socket = SockAllocateHeapRoutine(SockPrivateHeap, 0, SocketLength); + if (!Socket) + { + /* Couldn't create it; we need to tell WSH so it can cleanup */ + if (HelperEvents & WSH_NOTIFY_CLOSE) + { + HelperData->WSHNotify(HelperDllContext, + INVALID_SOCKET, + NULL, + NULL, + WSH_NOTIFY_CLOSE); + } + + /* Fail and return */ + ErrorCode = WSAENOBUFS; + goto error; + } + + /* Initialize it */ + RtlZeroMemory(Socket, SocketLength); + Socket->RefCount = 2; + Socket->Handle = INVALID_SOCKET; + Socket->SharedData.State = SocketUndefined; + Socket->SharedData.AddressFamily = AddressFamily; + Socket->SharedData.SocketType = SocketType; + Socket->SharedData.Protocol = Protocol; + Socket->ProviderId = *ProviderId; + Socket->HelperContext = HelperDllContext; + Socket->HelperData = HelperData; + Socket->HelperEvents = HelperEvents; + Socket->LocalAddress = (PVOID)(Socket + 1); + Socket->SharedData.SizeOfLocalAddress = HelperData->MaxWSAddressLength; + Socket->RemoteAddress = (PVOID)((ULONG_PTR)Socket->LocalAddress + + HelperData->MaxWSAddressLength); + Socket->SharedData.SizeOfRemoteAddress = HelperData->MaxWSAddressLength; + Socket->SharedData.UseDelayedAcceptance = HelperData->UseDelayedAcceptance; + Socket->SharedData.CreateFlags = dwFlags; + Socket->SharedData.CatalogEntryId = CatalogEntryId; + Socket->SharedData.ServiceFlags1 = ServiceFlags; + Socket->SharedData.ProviderFlags = ProviderFlags; + Socket->SharedData.GroupID = g; + Socket->SharedData.GroupType = 0; + Socket->SharedData.UseSAN = FALSE; + Socket->SanData = NULL; + Socket->DontUseSan = FALSE; + + /* Initialize the socket lock */ + InitializeCriticalSection(&Socket->Lock); + LockInit = TRUE; + + /* Packet Size */ + SizeOfPacket = TransportName.Length + sizeof(*AfdPacket) + sizeof(WCHAR); + + /* EA Size */ + SizeOfEa = SizeOfPacket + sizeof(*Ea) + AFD_PACKET_COMMAND_LENGTH; + + /* See if our stack buffer is big enough to hold it */ + if (SizeOfEa <= sizeof(AfdPacketBuffer)) + { + /* Use our stack */ + Ea = (PFILE_FULL_EA_INFORMATION)AfdPacketBuffer; + } + else + { + /* Allocate from heap */ + Ea = SockAllocateHeapRoutine(SockPrivateHeap, 0, SizeOfEa); + if (!Ea) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + } + + /* Set up EA */ + Ea->NextEntryOffset = 0; + Ea->Flags = 0; + Ea->EaNameLength = AFD_PACKET_COMMAND_LENGTH; + RtlCopyMemory(Ea->EaName, AfdCommand, AFD_PACKET_COMMAND_LENGTH + 1); + Ea->EaValueLength = SizeOfPacket; + + /* Set up AFD Packet */ + AfdPacket = (PAFD_CREATE_PACKET)(Ea->EaName + Ea->EaNameLength + 1); + AfdPacket->SizeOfTransportName = TransportName.Length; + RtlCopyMemory(AfdPacket->TransportName, + TransportName.Buffer, + TransportName.Length + sizeof(WCHAR)); + AfdPacket->EndpointFlags = 0; + + /* Set up Endpoint Flags */ + if ((Socket->SharedData.ServiceFlags1 & XP1_CONNECTIONLESS)) + { + /* Check the Socket Type */ + if ((SocketType != SOCK_DGRAM) && (SocketType != SOCK_RAW)) + { + /* Only RAW or UDP can be Connectionless */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Set the flag for AFD */ + AfdPacket->EndpointFlags |= AFD_ENDPOINT_CONNECTIONLESS; + } + + if ((Socket->SharedData.ServiceFlags1 & XP1_MESSAGE_ORIENTED)) + { + /* Check if this is a Stream Socket */ + if (SocketType == SOCK_STREAM) + { + /* Check if we actually support this */ + if (!(Socket->SharedData.ServiceFlags1 & XP1_PSEUDO_STREAM)) + { + /* The Provider doesn't support Message Oriented Streams */ + ErrorCode = WSAEINVAL; + goto error; + } + } + + /* Set the flag for AFD */ + AfdPacket->EndpointFlags |= AFD_ENDPOINT_MESSAGE_ORIENTED; + } + + /* If this is a Raw Socket, let AFD know */ + if (SocketType == SOCK_RAW) AfdPacket->EndpointFlags |= AFD_ENDPOINT_RAW; + + /* Check if we are a Multipoint Control/Data Root or Leaf */ + if (dwFlags & (WSA_FLAG_MULTIPOINT_C_ROOT | + WSA_FLAG_MULTIPOINT_C_LEAF | + WSA_FLAG_MULTIPOINT_D_ROOT | + WSA_FLAG_MULTIPOINT_D_LEAF)) + { + /* First make sure we support Multipoint */ + if (!(Socket->SharedData.ServiceFlags1 & XP1_SUPPORT_MULTIPOINT)) + { + /* The Provider doesn't actually support Multipoint */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Set the flag for AFD */ + AfdPacket->EndpointFlags |= AFD_ENDPOINT_MULTIPOINT; + + /* Check if we are a Control Plane Root */ + if (dwFlags & WSA_FLAG_MULTIPOINT_C_ROOT) + { + /* Check if we actually support this or if we're already a leaf */ + if ((!(Socket->SharedData.ServiceFlags1 & + XP1_MULTIPOINT_CONTROL_PLANE)) || + ((dwFlags & WSA_FLAG_MULTIPOINT_C_LEAF))) + { + ErrorCode = WSAEINVAL; + goto error; + } + + /* Set the flag for AFD */ + AfdPacket->EndpointFlags |= AFD_ENDPOINT_C_ROOT; + } + + /* Check if we a Data Plane Root */ + if (dwFlags & WSA_FLAG_MULTIPOINT_D_ROOT) + { + /* Check if we actually support this or if we're already a leaf */ + if ((!(Socket->SharedData.ServiceFlags1 & + XP1_MULTIPOINT_DATA_PLANE)) || + ((dwFlags & WSA_FLAG_MULTIPOINT_D_LEAF))) + { + ErrorCode = WSAEINVAL; + goto error; + } + + /* Set the flag for AFD */ + AfdPacket->EndpointFlags |= AFD_ENDPOINT_D_ROOT; + } + } + + /* Set the group ID */ + AfdPacket->GroupID = g; + + /* Set up Object Attributes */ + RtlInitUnicodeString(&DevName, L"\\Device\\Afd\\Endpoint"); + InitializeObjectAttributes(&ObjectAttributes, + &DevName, + OBJ_CASE_INSENSITIVE | OBJ_INHERIT, + NULL, + NULL); + + /* Check if we're not using Overlapped I/O */ + if (!(dwFlags & WSA_FLAG_OVERLAPPED)) + { + /* Set Synchronous I/O */ + CreateOptions = FILE_SYNCHRONOUS_IO_NONALERT; + } + + /* Acquire the global lock */ + SockAcquireRwLockShared(&SocketGlobalLock); + + /* Create the Socket */ + Status = NtCreateFile((PHANDLE)&Handle, + GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, + &ObjectAttributes, + &IoStatusBlock, + NULL, + 0, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_OPEN_IF, + CreateOptions, + Ea, + SizeOfEa); + if (!NT_SUCCESS(Status)) + { + /* Release the lock and fail */ + SockReleaseRwLockShared(&SocketGlobalLock); + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* Save Handle */ + Socket->Handle = Handle; + + /* Check if a group was given */ + if (g != 0) + { + /* Get Group Id and Type */ + ErrorCode = SockGetInformation(Socket, + AFD_INFO_GROUP_ID_TYPE, + NULL, + 0, + NULL, + NULL, + &GroupData); + + /* Save them */ + Socket->SharedData.GroupID = GroupData.u.LowPart; + Socket->SharedData.GroupType = GroupData.u.HighPart; + } + + /* Check if we need to get the window sizes */ + if (!SockSendBufferWindow) + { + /* Get send window size */ + SockGetInformation(Socket, + AFD_INFO_SEND_WINDOW_SIZE, + NULL, + 0, + NULL, + &SockSendBufferWindow, + NULL); + + /* Get receive window size */ + SockGetInformation(Socket, + AFD_INFO_RECEIVE_WINDOW_SIZE, + NULL, + 0, + NULL, + &SockReceiveBufferWindow, + NULL); + } + + /* Save window sizes */ + Socket->SharedData.SizeOfRecvBuffer = SockReceiveBufferWindow; + Socket->SharedData.SizeOfSendBuffer = SockSendBufferWindow; + + /* Insert it into our table */ + WahHandle = WahInsertHandleContext(SockContextTable, &Socket->WshContext); + + /* We can release the lock now */ + SockReleaseRwLockShared(&SocketGlobalLock); + + /* Check if the handles don't match for some reason */ + if (WahHandle != &Socket->WshContext) + { + /* Do they not match? */ + if (WahHandle) + { + /* They don't... someone must've used CloseHandle */ + SockDereferenceSocket((PSOCKET_INFORMATION)WahHandle); + + /* Use the correct handle now */ + WahHandle = &Socket->WshContext; + } + else + { + /* It's not that they don't match: we don't have one at all! */ + ErrorCode = WSAENOBUFS; + goto error; + } + } + +error: + /* Check if we can free the transport name */ + if ((SocketType == SOCK_RAW) && (TransportName.Buffer)) + { + /* Free it */ + RtlFreeHeap(RtlGetProcessHeap(), 0, TransportName.Buffer); + } + + /* Check if we have the EA from the heap */ + if ((Ea) && (Ea != (PVOID)AfdPacketBuffer)) + { + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, Ea); + } + + /* Check if this is actually success */ + if (ErrorCode != NO_ERROR) + { + /* Check if we have a socket by now */ + if (Socket) + { + /* Tell the Helper DLL we're closing it */ + SockNotifyHelperDll(Socket, WSH_NOTIFY_CLOSE); + + /* Close its handle if it's valid */ + if (Socket->WshContext.Handle != INVALID_HANDLE_VALUE) + { + NtClose(Socket->WshContext.Handle); + } + + /* Delete its lock */ + if (LockInit) DeleteCriticalSection(&Socket->Lock); + + /* Remove our socket reference */ + SockDereferenceSocket(Socket); + + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, Socket); + } + } + + /* Return Socket and error code */ + *NewSocket = Socket; + return ErrorCode; +} + +INT +WSPAPI +SockCloseSocket(IN PSOCKET_INFORMATION Socket) +{ + INT ErrorCode; + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + AFD_DISCONNECT_INFO DisconnectInfo; + SOCKET_STATE OldState; + ULONG LingerWait; + ULONG SendsInProgress; + ULONG SleepWait; + BOOLEAN ActiveConnect; + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* If a Close is already in Process... */ + if (Socket->SharedData.State == SocketClosed) + { + /* Release lock and fail */ + LeaveCriticalSection(&Socket->Lock); + return WSAENOTSOCK; + } + + /* Save the old state and set the new one to closed */ + OldState = Socket->SharedData.State; + Socket->SharedData.State = SocketClosed; + + /* Check if the socket has an active async data */ + ActiveConnect = (Socket->AsyncData != NULL); + + /* We're done with the socket, release the lock */ + LeaveCriticalSection(&Socket->Lock); + + /* + * If SO_LINGER is ON and the Socket was connected or had an active async + * connect context, then we'll disconnect it. Note that we won't do this + * for connection-less (UDP/RAW) sockets or if a send shutdown is active. + */ + if ((OldState == SocketConnected || ActiveConnect) && + !(Socket->SharedData.SendShutdown) && + !MSAFD_IS_DGRAM_SOCK(Socket) && + (Socket->SharedData.LingerData.l_onoff)) + { + /* We need to respect the timeout */ + SleepWait = 100; + LingerWait = Socket->SharedData.LingerData.l_linger * 1000; + + /* Loop until no more sends are pending, within the timeout */ + while (LingerWait) + { + /* Find out how many Sends are in Progress */ + if (SockGetInformation(Socket, + AFD_INFO_SENDS_IN_PROGRESS, + NULL, + 0, + NULL, + &SendsInProgress, + NULL)) + { + /* Bail out if anything but NO_ERROR */ + LingerWait = 0; + break; + } + + /* Bail out if no more sends are pending */ + if (!SendsInProgress) break; + + /* + * We have to execute a sleep, so it's kind of like + * a block. If the socket is Nonblock, we cannot + * go on since asyncronous operation is expected + * and we cannot offer it + */ + if (Socket->SharedData.NonBlocking) + { + /* Acquire the socket lock */ + EnterCriticalSection(&Socket->Lock); + + /* Restore the socket state */ + Socket->SharedData.State = OldState; + + /* Release the lock again */ + LeaveCriticalSection(&Socket->Lock); + + /* Fail with error code */ + return WSAEWOULDBLOCK; + } + + /* Now we can sleep, and decrement the linger wait */ + /* + * FIXME: It seems Windows does some funky acceleration + * since the waiting seems to be longer and longer. I + * don't think this improves performance so much, so we + * wait a fixed time instead. + */ + Sleep(SleepWait); + LingerWait -= SleepWait; + } + + /* + * We have reached the timeout or sends are over. + * Disconnect if the timeout has been reached. + */ + if (LingerWait <= 0) + { + /* There is no timeout, and this is an abortive disconnect */ + DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(0); + DisconnectInfo.DisconnectType = AFD_DISCONNECT_ABORT; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_DISCONNECT, + &DisconnectInfo, + sizeof(DisconnectInfo), + NULL, + 0); + /* Check if the operation is pending */ + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + !Socket->SharedData.LingerData.l_onoff ? + NO_BLOCKING_HOOK : ALWAYS_BLOCKING_HOOK, + NO_TIMEOUT); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* We actually accept errors, unless the driver wasn't ready */ + if (Status == STATUS_DEVICE_NOT_READY) + { + /* This is the equivalent of a WOULDBLOCK, which we fail */ + /* Acquire the socket lock */ + EnterCriticalSection(&Socket->Lock); + + /* Restore the socket state */ + Socket->SharedData.State = OldState; + + /* Release the lock again */ + LeaveCriticalSection(&Socket->Lock); + + /* Fail with error code */ + return WSAEWOULDBLOCK; + } + } + } + + /* Acquire the global lock to protect the handle table */ + SockAcquireRwLockShared(&SocketGlobalLock); + + /* Protect the socket too */ + EnterCriticalSection(&Socket->Lock); + + /* Notify the Helper DLL of Socket Closure */ + ErrorCode = SockNotifyHelperDll(Socket, WSH_NOTIFY_CLOSE); + + /* Cleanup Time! */ + Socket->HelperContext = NULL; + Socket->SharedData.AsyncDisabledEvents = -1; + if (Socket->TdiAddressHandle) + { + /* Close and forget the handle */ + NtClose(Socket->TdiAddressHandle); + Socket->TdiAddressHandle = NULL; + } + if (Socket->TdiConnectionHandle) + { + /* Close and forget the handle */ + NtClose(Socket->TdiConnectionHandle); + Socket->TdiConnectionHandle = NULL; + } + + /* Remove the handle from the table */ + ErrorCode = WahRemoveHandleContext(SockContextTable, &Socket->WshContext); + if (ErrorCode == NO_ERROR) + { + /* Close the socket's handle */ + NtClose(Socket->WshContext.Handle); + + /* Dereference the socket */ + SockDereferenceSocket(Socket); + } + else + { + /* This isn't a socket anymore, or something */ + ErrorCode = WSAENOTSOCK; + } + + /* Release both locks */ + LeaveCriticalSection(&Socket->Lock); + SockReleaseRwLockShared(&SocketGlobalLock); + + /* Return success */ + return ErrorCode; +} + +SOCKET +WSPAPI +WSPSocket(INT AddressFamily, + INT SocketType, + INT Protocol, + LPWSAPROTOCOL_INFOW lpProtocolInfo, + GROUP g, + DWORD dwFlags, + LPINT lpErrno) +{ + DWORD CatalogId; + SOCKET Handle = INVALID_SOCKET; + INT ErrorCode; + DWORD ServiceFlags, ProviderFlags; + PWINSOCK_TEB_DATA ThreadData; + PSOCKET_INFORMATION Socket; + GUID ProviderId; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return INVALID_SOCKET; + } + + /* Get the catalog ID */ + CatalogId = lpProtocolInfo->dwCatalogEntryId; + + /* Check if this is a duplication */ + if(lpProtocolInfo->dwProviderReserved) + { + /* Get the duplicate handle */ + Handle = (SOCKET)lpProtocolInfo->dwProviderReserved; + + /* Get our structure for it */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if(Socket) + { + /* Tell Winsock about it */ + Socket->Handle = SockUpcallTable->lpWPUModifyIFSHandle(CatalogId, + Handle, + &ErrorCode); + /* Check if we got an invalid handle back */ + if(Socket->Handle == INVALID_SOCKET) + { + /* Restore it for the error path */ + Socket->Handle = Handle; + } + } + else + { + /* The duplicate handle is invalid */ + ErrorCode = WSAEINVAL; + } + + /* Fail */ + goto error; + } + + /* See if the address family should be recovered from the protocl info */ + if (!AddressFamily || AddressFamily == FROM_PROTOCOL_INFO) + { + /* Use protocol info data */ + AddressFamily = lpProtocolInfo->iAddressFamily; + } + + /* See if the address family should be recovered from the protocl info */ + if(!SocketType || SocketType == FROM_PROTOCOL_INFO ) + { + /* Use protocol info data */ + SocketType = lpProtocolInfo->iSocketType; + } + + /* See if the address family should be recovered from the protocl info */ + if(Protocol == FROM_PROTOCOL_INFO) + { + /* Use protocol info data */ + Protocol = lpProtocolInfo->iProtocol; + } + + /* Save the service, provider flags and provider ID */ + ServiceFlags = lpProtocolInfo->dwServiceFlags1; + ProviderFlags = lpProtocolInfo->dwProviderFlags; + ProviderId = lpProtocolInfo->ProviderId; + + /* Create the actual socket */ + ErrorCode = SockSocket(AddressFamily, + SocketType, + Protocol, + &ProviderId, + g, + dwFlags, + ProviderFlags, + ServiceFlags, + CatalogId, + &Socket); + if (ErrorCode == ERROR_SUCCESS) + { + /* Acquire the socket lock */ + EnterCriticalSection(&Socket->Lock); + + /* Set status to opened */ + Socket->SharedData.State = SocketOpen; + + /* Create the Socket Context */ + ErrorCode = SockSetHandleContext(Socket); + if (ErrorCode != NO_ERROR) + { + /* Release the lock, close the socket and fail */ + LeaveCriticalSection(&Socket->Lock); + SockCloseSocket(Socket); + goto error; + } + + /* Notify Winsock */ + Handle = SockUpcallTable->lpWPUModifyIFSHandle(Socket->SharedData.CatalogEntryId, + (SOCKET)Socket->WshContext.Handle, + &ErrorCode); + + /* Does Winsock not like it? */ + if (Handle == INVALID_SOCKET) + { + /* Release the lock, close the socket and fail */ + LeaveCriticalSection(&Socket->Lock); + SockCloseSocket(Socket); + goto error; + } + + /* Release the lock */ + LeaveCriticalSection(&Socket->Lock); + } + +error: + /* Write return code */ + *lpErrno = ErrorCode; + + /* Check if we have a socket and dereference it */ + if (Socket) SockDereferenceSocket(Socket); + + /* Return handle */ + return Handle; +} + +INT +WSPAPI +WSPCloseSocket(IN SOCKET Handle, + OUT LPINT lpErrno) +{ + INT ErrorCode; + PSOCKET_INFORMATION Socket; + PWINSOCK_TEB_DATA ThreadData; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + *lpErrno = WSAENOTSOCK; + return SOCKET_ERROR; + } + + /* Close it */ + ErrorCode = SockCloseSocket(Socket); + + /* Remove the final reference */ + SockDereferenceSocket(Socket); + + /* Check if we got here by error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +SockSocket(INT AddressFamily, + INT SocketType, + INT Protocol, + LPGUID ProviderId, + GROUP g, + DWORD dwFlags, + DWORD ProviderFlags, + DWORD ServiceFlags, + DWORD CatalogEntryId, + PSOCKET_INFORMATION *NewSocket) +{ + INT ErrorCode; + UNICODE_STRING TransportName; + PVOID HelperDllContext; + PHELPER_DATA HelperData = NULL; + DWORD HelperEvents; + PFILE_FULL_EA_INFORMATION Ea = NULL; + PAFD_CREATE_PACKET AfdPacket; + SOCKET Handle = INVALID_SOCKET; + PSOCKET_INFORMATION Socket = NULL; + BOOLEAN LockInit = FALSE; + USHORT SizeOfPacket; + DWORD SizeOfEa, SocketLength; + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING DevName; + LARGE_INTEGER GroupData; + DWORD CreateOptions = 0; + IO_STATUS_BLOCK IoStatusBlock; + PWAH_HANDLE WahHandle; + NTSTATUS Status; + CHAR AfdPacketBuffer[96]; + + /* Initialize the transport name */ + RtlInitUnicodeString(&TransportName, NULL); + + /* Get Helper Data and Transport */ + ErrorCode = SockGetTdiName(&AddressFamily, + &SocketType, + &Protocol, + ProviderId, + g, + dwFlags, + &TransportName, + &HelperDllContext, + &HelperData, + &HelperEvents); + + /* Check for error */ + if (ErrorCode != NO_ERROR) goto error; + + /* Figure out the socket context structure size */ + SocketLength = sizeof(*Socket) + (HelperData->MinWSAddressLength * 2); + + /* Allocate a socket */ + Socket = SockAllocateHeapRoutine(SockPrivateHeap, 0, SocketLength); + if (!Socket) + { + /* Couldn't create it; we need to tell WSH so it can cleanup */ + if (HelperEvents & WSH_NOTIFY_CLOSE) + { + HelperData->WSHNotify(HelperDllContext, + INVALID_SOCKET, + NULL, + NULL, + WSH_NOTIFY_CLOSE); + } + + /* Fail and return */ + ErrorCode = WSAENOBUFS; + goto error; + } + + /* Initialize it */ + RtlZeroMemory(Socket, SocketLength); + Socket->RefCount = 2; + Socket->Handle = INVALID_SOCKET; + Socket->SharedData.State = SocketUndefined; + Socket->SharedData.AddressFamily = AddressFamily; + Socket->SharedData.SocketType = SocketType; + Socket->SharedData.Protocol = Protocol; + Socket->ProviderId = *ProviderId; + Socket->HelperContext = HelperDllContext; + Socket->HelperData = HelperData; + Socket->HelperEvents = HelperEvents; + Socket->LocalAddress = (PVOID)(Socket + 1); + Socket->SharedData.SizeOfLocalAddress = HelperData->MaxWSAddressLength; + Socket->RemoteAddress = (PVOID)((ULONG_PTR)Socket->LocalAddress + + HelperData->MaxWSAddressLength); + Socket->SharedData.SizeOfRemoteAddress = HelperData->MaxWSAddressLength; + Socket->SharedData.UseDelayedAcceptance = HelperData->UseDelayedAcceptance; + Socket->SharedData.CreateFlags = dwFlags; + Socket->SharedData.CatalogEntryId = CatalogEntryId; + Socket->SharedData.ServiceFlags1 = ServiceFlags; + Socket->SharedData.ProviderFlags = ProviderFlags; + Socket->SharedData.GroupID = g; + Socket->SharedData.GroupType = 0; + Socket->SharedData.UseSAN = FALSE; + Socket->SanData = NULL; + Socket->DontUseSan = FALSE; + + /* Initialize the socket lock */ + InitializeCriticalSection(&Socket->Lock); + LockInit = TRUE; + + /* Packet Size */ + SizeOfPacket = TransportName.Length + sizeof(*AfdPacket) + sizeof(WCHAR); + + /* EA Size */ + SizeOfEa = SizeOfPacket + sizeof(*Ea) + AFD_PACKET_COMMAND_LENGTH; + + /* See if our stack buffer is big enough to hold it */ + if (SizeOfEa <= sizeof(AfdPacketBuffer)) + { + /* Use our stack */ + Ea = (PFILE_FULL_EA_INFORMATION)AfdPacketBuffer; + } + else + { + /* Allocate from heap */ + Ea = SockAllocateHeapRoutine(SockPrivateHeap, 0, SizeOfEa); + if (!Ea) + { + /* Fail */ + ErrorCode = WSAENOBUFS; + goto error; + } + } + + /* Set up EA */ + Ea->NextEntryOffset = 0; + Ea->Flags = 0; + Ea->EaNameLength = AFD_PACKET_COMMAND_LENGTH; + RtlCopyMemory(Ea->EaName, AfdCommand, AFD_PACKET_COMMAND_LENGTH + 1); + Ea->EaValueLength = SizeOfPacket; + + /* Set up AFD Packet */ + AfdPacket = (PAFD_CREATE_PACKET)(Ea->EaName + Ea->EaNameLength + 1); + AfdPacket->SizeOfTransportName = TransportName.Length; + RtlCopyMemory(AfdPacket->TransportName, + TransportName.Buffer, + TransportName.Length + sizeof(WCHAR)); + AfdPacket->EndpointFlags = 0; + + /* Set up Endpoint Flags */ + if ((Socket->SharedData.ServiceFlags1 & XP1_CONNECTIONLESS)) + { + /* Check the Socket Type */ + if ((SocketType != SOCK_DGRAM) && (SocketType != SOCK_RAW)) + { + /* Only RAW or UDP can be Connectionless */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Set the flag for AFD */ + AfdPacket->EndpointFlags |= AFD_ENDPOINT_CONNECTIONLESS; + } + + if ((Socket->SharedData.ServiceFlags1 & XP1_MESSAGE_ORIENTED)) + { + /* Check if this is a Stream Socket */ + if (SocketType == SOCK_STREAM) + { + /* Check if we actually support this */ + if (!(Socket->SharedData.ServiceFlags1 & XP1_PSEUDO_STREAM)) + { + /* The Provider doesn't support Message Oriented Streams */ + ErrorCode = WSAEINVAL; + goto error; + } + } + + /* Set the flag for AFD */ + AfdPacket->EndpointFlags |= AFD_ENDPOINT_MESSAGE_ORIENTED; + } + + /* If this is a Raw Socket, let AFD know */ + if (SocketType == SOCK_RAW) AfdPacket->EndpointFlags |= AFD_ENDPOINT_RAW; + + /* Check if we are a Multipoint Control/Data Root or Leaf */ + if (dwFlags & (WSA_FLAG_MULTIPOINT_C_ROOT | + WSA_FLAG_MULTIPOINT_C_LEAF | + WSA_FLAG_MULTIPOINT_D_ROOT | + WSA_FLAG_MULTIPOINT_D_LEAF)) + { + /* First make sure we support Multipoint */ + if (!(Socket->SharedData.ServiceFlags1 & XP1_SUPPORT_MULTIPOINT)) + { + /* The Provider doesn't actually support Multipoint */ + ErrorCode = WSAEINVAL; + goto error; + } + + /* Set the flag for AFD */ + AfdPacket->EndpointFlags |= AFD_ENDPOINT_MULTIPOINT; + + /* Check if we are a Control Plane Root */ + if (dwFlags & WSA_FLAG_MULTIPOINT_C_ROOT) + { + /* Check if we actually support this or if we're already a leaf */ + if ((!(Socket->SharedData.ServiceFlags1 & + XP1_MULTIPOINT_CONTROL_PLANE)) || + ((dwFlags & WSA_FLAG_MULTIPOINT_C_LEAF))) + { + ErrorCode = WSAEINVAL; + goto error; + } + + /* Set the flag for AFD */ + AfdPacket->EndpointFlags |= AFD_ENDPOINT_C_ROOT; + } + + /* Check if we a Data Plane Root */ + if (dwFlags & WSA_FLAG_MULTIPOINT_D_ROOT) + { + /* Check if we actually support this or if we're already a leaf */ + if ((!(Socket->SharedData.ServiceFlags1 & + XP1_MULTIPOINT_DATA_PLANE)) || + ((dwFlags & WSA_FLAG_MULTIPOINT_D_LEAF))) + { + ErrorCode = WSAEINVAL; + goto error; + } + + /* Set the flag for AFD */ + AfdPacket->EndpointFlags |= AFD_ENDPOINT_D_ROOT; + } + } + + /* Set the group ID */ + AfdPacket->GroupID = g; + + /* Set up Object Attributes */ + RtlInitUnicodeString(&DevName, L"\\Device\\Afd\\Endpoint"); + InitializeObjectAttributes(&ObjectAttributes, + &DevName, + OBJ_CASE_INSENSITIVE | OBJ_INHERIT, + NULL, + NULL); + + /* Check if we're not using Overlapped I/O */ + if (!(dwFlags & WSA_FLAG_OVERLAPPED)) + { + /* Set Synchronous I/O */ + CreateOptions = FILE_SYNCHRONOUS_IO_NONALERT; + } + + /* Acquire the global lock */ + SockAcquireRwLockShared(&SocketGlobalLock); + + /* Create the Socket */ + Status = NtCreateFile((PHANDLE)&Handle, + GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, + &ObjectAttributes, + &IoStatusBlock, + NULL, + 0, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_OPEN_IF, + CreateOptions, + Ea, + SizeOfEa); + if (!NT_SUCCESS(Status)) + { + /* Release the lock and fail */ + SockReleaseRwLockShared(&SocketGlobalLock); + ErrorCode = NtStatusToSocketError(Status); + goto error; + } + + /* Save Handle */ + Socket->Handle = Handle; + + /* Check if a group was given */ + if (g != 0) + { + /* Get Group Id and Type */ + ErrorCode = SockGetInformation(Socket, + AFD_INFO_GROUP_ID_TYPE, + NULL, + 0, + NULL, + NULL, + &GroupData); + + /* Save them */ + Socket->SharedData.GroupID = GroupData.u.LowPart; + Socket->SharedData.GroupType = GroupData.u.HighPart; + } + + /* Check if we need to get the window sizes */ + if (!SockSendBufferWindow) + { + /* Get send window size */ + SockGetInformation(Socket, + AFD_INFO_SEND_WINDOW_SIZE, + NULL, + 0, + NULL, + &SockSendBufferWindow, + NULL); + + /* Get receive window size */ + SockGetInformation(Socket, + AFD_INFO_RECEIVE_WINDOW_SIZE, + NULL, + 0, + NULL, + &SockReceiveBufferWindow, + NULL); + } + + /* Save window sizes */ + Socket->SharedData.SizeOfRecvBuffer = SockReceiveBufferWindow; + Socket->SharedData.SizeOfSendBuffer = SockSendBufferWindow; + + /* Insert it into our table */ + WahHandle = WahInsertHandleContext(SockContextTable, &Socket->WshContext); + + /* We can release the lock now */ + SockReleaseRwLockShared(&SocketGlobalLock); + + /* Check if the handles don't match for some reason */ + if (WahHandle != &Socket->WshContext) + { + /* Do they not match? */ + if (WahHandle) + { + /* They don't... someone must've used CloseHandle */ + SockDereferenceSocket((PSOCKET_INFORMATION)WahHandle); + + /* Use the correct handle now */ + WahHandle = &Socket->WshContext; + } + else + { + /* It's not that they don't match: we don't have one at all! */ + ErrorCode = WSAENOBUFS; + goto error; + } + } + +error: + /* Check if we can free the transport name */ + if ((SocketType == SOCK_RAW) && (TransportName.Buffer)) + { + /* Free it */ + RtlFreeHeap(RtlGetProcessHeap(), 0, TransportName.Buffer); + } + + /* Check if we have the EA from the heap */ + if ((Ea) && (Ea != (PVOID)AfdPacketBuffer)) + { + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, Ea); + } + + /* Check if this is actually success */ + if (ErrorCode != NO_ERROR) + { + /* Check if we have a socket by now */ + if (Socket) + { + /* Tell the Helper DLL we're closing it */ + SockNotifyHelperDll(Socket, WSH_NOTIFY_CLOSE); + + /* Close its handle if it's valid */ + if (Socket->WshContext.Handle != INVALID_HANDLE_VALUE) + { + NtClose(Socket->WshContext.Handle); + } + + /* Delete its lock */ + if (LockInit) DeleteCriticalSection(&Socket->Lock); + + /* Remove our socket reference */ + SockDereferenceSocket(Socket); + + /* Free it */ + RtlFreeHeap(SockPrivateHeap, 0, Socket); + } + } + + /* Return Socket and error code */ + *NewSocket = Socket; + return ErrorCode; +} + +INT +WSPAPI +SockCloseSocket(IN PSOCKET_INFORMATION Socket) +{ + INT ErrorCode; + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + AFD_DISCONNECT_INFO DisconnectInfo; + SOCKET_STATE OldState; + ULONG LingerWait; + ULONG SendsInProgress; + ULONG SleepWait; + BOOLEAN ActiveConnect; + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* If a Close is already in Process... */ + if (Socket->SharedData.State == SocketClosed) + { + /* Release lock and fail */ + LeaveCriticalSection(&Socket->Lock); + return WSAENOTSOCK; + } + + /* Save the old state and set the new one to closed */ + OldState = Socket->SharedData.State; + Socket->SharedData.State = SocketClosed; + + /* Check if the socket has an active async data */ + ActiveConnect = (Socket->AsyncData != NULL); + + /* We're done with the socket, release the lock */ + LeaveCriticalSection(&Socket->Lock); + + /* + * If SO_LINGER is ON and the Socket was connected or had an active async + * connect context, then we'll disconnect it. Note that we won't do this + * for connection-less (UDP/RAW) sockets or if a send shutdown is active. + */ + if ((OldState == SocketConnected || ActiveConnect) && + !(Socket->SharedData.SendShutdown) && + !MSAFD_IS_DGRAM_SOCK(Socket) && + (Socket->SharedData.LingerData.l_onoff)) + { + /* We need to respect the timeout */ + SleepWait = 100; + LingerWait = Socket->SharedData.LingerData.l_linger * 1000; + + /* Loop until no more sends are pending, within the timeout */ + while (LingerWait) + { + /* Find out how many Sends are in Progress */ + if (SockGetInformation(Socket, + AFD_INFO_SENDS_IN_PROGRESS, + NULL, + 0, + NULL, + &SendsInProgress, + NULL)) + { + /* Bail out if anything but NO_ERROR */ + LingerWait = 0; + break; + } + + /* Bail out if no more sends are pending */ + if (!SendsInProgress) break; + + /* + * We have to execute a sleep, so it's kind of like + * a block. If the socket is Nonblock, we cannot + * go on since asyncronous operation is expected + * and we cannot offer it + */ + if (Socket->SharedData.NonBlocking) + { + /* Acquire the socket lock */ + EnterCriticalSection(&Socket->Lock); + + /* Restore the socket state */ + Socket->SharedData.State = OldState; + + /* Release the lock again */ + LeaveCriticalSection(&Socket->Lock); + + /* Fail with error code */ + return WSAEWOULDBLOCK; + } + + /* Now we can sleep, and decrement the linger wait */ + /* + * FIXME: It seems Windows does some funky acceleration + * since the waiting seems to be longer and longer. I + * don't think this improves performance so much, so we + * wait a fixed time instead. + */ + Sleep(SleepWait); + LingerWait -= SleepWait; + } + + /* + * We have reached the timeout or sends are over. + * Disconnect if the timeout has been reached. + */ + if (LingerWait <= 0) + { + /* There is no timeout, and this is an abortive disconnect */ + DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(0); + DisconnectInfo.DisconnectType = AFD_DISCONNECT_ABORT; + + /* Send IOCTL */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + NULL, + &IoStatusBlock, + IOCTL_AFD_DISCONNECT, + &DisconnectInfo, + sizeof(DisconnectInfo), + NULL, + 0); + /* Check if the operation is pending */ + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + !Socket->SharedData.LingerData.l_onoff ? + NO_BLOCKING_HOOK : ALWAYS_BLOCKING_HOOK, + NO_TIMEOUT); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* We actually accept errors, unless the driver wasn't ready */ + if (Status == STATUS_DEVICE_NOT_READY) + { + /* This is the equivalent of a WOULDBLOCK, which we fail */ + /* Acquire the socket lock */ + EnterCriticalSection(&Socket->Lock); + + /* Restore the socket state */ + Socket->SharedData.State = OldState; + + /* Release the lock again */ + LeaveCriticalSection(&Socket->Lock); + + /* Fail with error code */ + return WSAEWOULDBLOCK; + } + } + } + + /* Acquire the global lock to protect the handle table */ + SockAcquireRwLockShared(&SocketGlobalLock); + + /* Protect the socket too */ + EnterCriticalSection(&Socket->Lock); + + /* Notify the Helper DLL of Socket Closure */ + ErrorCode = SockNotifyHelperDll(Socket, WSH_NOTIFY_CLOSE); + + /* Cleanup Time! */ + Socket->HelperContext = NULL; + Socket->SharedData.AsyncDisabledEvents = -1; + if (Socket->TdiAddressHandle) + { + /* Close and forget the handle */ + NtClose(Socket->TdiAddressHandle); + Socket->TdiAddressHandle = NULL; + } + if (Socket->TdiConnectionHandle) + { + /* Close and forget the handle */ + NtClose(Socket->TdiConnectionHandle); + Socket->TdiConnectionHandle = NULL; + } + + /* Remove the handle from the table */ + ErrorCode = WahRemoveHandleContext(SockContextTable, &Socket->WshContext); + if (ErrorCode == NO_ERROR) + { + /* Close the socket's handle */ + NtClose(Socket->WshContext.Handle); + + /* Dereference the socket */ + SockDereferenceSocket(Socket); + } + else + { + /* This isn't a socket anymore, or something */ + ErrorCode = WSAENOTSOCK; + } + + /* Release both locks */ + LeaveCriticalSection(&Socket->Lock); + SockReleaseRwLockShared(&SocketGlobalLock); + + /* Return success */ + return ErrorCode; +} + +SOCKET +WSPAPI +WSPSocket(INT AddressFamily, + INT SocketType, + INT Protocol, + LPWSAPROTOCOL_INFOW lpProtocolInfo, + GROUP g, + DWORD dwFlags, + LPINT lpErrno) +{ + DWORD CatalogId; + SOCKET Handle = INVALID_SOCKET; + INT ErrorCode; + DWORD ServiceFlags, ProviderFlags; + PWINSOCK_TEB_DATA ThreadData; + PSOCKET_INFORMATION Socket; + GUID ProviderId; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return INVALID_SOCKET; + } + + /* Get the catalog ID */ + CatalogId = lpProtocolInfo->dwCatalogEntryId; + + /* Check if this is a duplication */ + if(lpProtocolInfo->dwProviderReserved) + { + /* Get the duplicate handle */ + Handle = (SOCKET)lpProtocolInfo->dwProviderReserved; + + /* Get our structure for it */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if(Socket) + { + /* Tell Winsock about it */ + Socket->Handle = SockUpcallTable->lpWPUModifyIFSHandle(CatalogId, + Handle, + &ErrorCode); + /* Check if we got an invalid handle back */ + if(Socket->Handle == INVALID_SOCKET) + { + /* Restore it for the error path */ + Socket->Handle = Handle; + } + } + else + { + /* The duplicate handle is invalid */ + ErrorCode = WSAEINVAL; + } + + /* Fail */ + goto error; + } + + /* See if the address family should be recovered from the protocl info */ + if (!AddressFamily || AddressFamily == FROM_PROTOCOL_INFO) + { + /* Use protocol info data */ + AddressFamily = lpProtocolInfo->iAddressFamily; + } + + /* See if the address family should be recovered from the protocl info */ + if(!SocketType || SocketType == FROM_PROTOCOL_INFO ) + { + /* Use protocol info data */ + SocketType = lpProtocolInfo->iSocketType; + } + + /* See if the address family should be recovered from the protocl info */ + if(Protocol == FROM_PROTOCOL_INFO) + { + /* Use protocol info data */ + Protocol = lpProtocolInfo->iProtocol; + } + + /* Save the service, provider flags and provider ID */ + ServiceFlags = lpProtocolInfo->dwServiceFlags1; + ProviderFlags = lpProtocolInfo->dwProviderFlags; + ProviderId = lpProtocolInfo->ProviderId; + + /* Create the actual socket */ + ErrorCode = SockSocket(AddressFamily, + SocketType, + Protocol, + &ProviderId, + g, + dwFlags, + ProviderFlags, + ServiceFlags, + CatalogId, + &Socket); + if (ErrorCode == ERROR_SUCCESS) + { + /* Acquire the socket lock */ + EnterCriticalSection(&Socket->Lock); + + /* Set status to opened */ + Socket->SharedData.State = SocketOpen; + + /* Create the Socket Context */ + ErrorCode = SockSetHandleContext(Socket); + if (ErrorCode != NO_ERROR) + { + /* Release the lock, close the socket and fail */ + LeaveCriticalSection(&Socket->Lock); + SockCloseSocket(Socket); + goto error; + } + + /* Notify Winsock */ + Handle = SockUpcallTable->lpWPUModifyIFSHandle(Socket->SharedData.CatalogEntryId, + (SOCKET)Socket->WshContext.Handle, + &ErrorCode); + + /* Does Winsock not like it? */ + if (Handle == INVALID_SOCKET) + { + /* Release the lock, close the socket and fail */ + LeaveCriticalSection(&Socket->Lock); + SockCloseSocket(Socket); + goto error; + } + + /* Release the lock */ + LeaveCriticalSection(&Socket->Lock); + } + +error: + /* Write return code */ + *lpErrno = ErrorCode; + + /* Check if we have a socket and dereference it */ + if (Socket) SockDereferenceSocket(Socket); + + /* Return handle */ + return Handle; +} + +INT +WSPAPI +WSPCloseSocket(IN SOCKET Handle, + OUT LPINT lpErrno) +{ + INT ErrorCode; + PSOCKET_INFORMATION Socket; + PWINSOCK_TEB_DATA ThreadData; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + *lpErrno = WSAENOTSOCK; + return SOCKET_ERROR; + } + + /* Close it */ + ErrorCode = SockCloseSocket(Socket); + + /* Remove the final reference */ + SockDereferenceSocket(Socket); + + /* Check if we got here by error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + diff --git a/dll/win32/mswsock/msafd/sockopt.c b/dll/win32/mswsock/msafd/sockopt.c new file mode 100644 index 00000000000..b2692ffbc8a --- /dev/null +++ b/dll/win32/mswsock/msafd/sockopt.c @@ -0,0 +1,2356 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +DWORD SockSendBufferWindow; +DWORD SockReceiveBufferWindow; + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +SockUpdateWindowSizes(IN PSOCKET_INFORMATION Socket, + IN BOOLEAN Force) +{ + INT ErrorCode; + + /* Check if this is a connection-less socket */ + if (Socket->SharedData.ServiceFlags1 & XP1_CONNECTIONLESS) + { + /* It must be bound */ + if (Socket->SharedData.State == SocketOpen) return NO_ERROR; + } + else + { + /* It must be connected */ + if (Socket->SharedData.State == SocketConnected) return NO_ERROR; + + /* Get the TDI handles for it */ + ErrorCode = SockGetTdiHandles(Socket); + if (ErrorCode != NO_ERROR) return ErrorCode; + + /* Tell WSH the new size */ + ErrorCode = Socket->HelperData->WSHSetSocketInformation(Socket->HelperContext, + Socket->Handle, + Socket->TdiAddressHandle, + Socket->TdiConnectionHandle, + SOL_SOCKET, + SO_RCVBUF, + (PVOID)&Socket->SharedData.SizeOfRecvBuffer, + sizeof(DWORD)); + } + + /* Check if the buffer changed, or if this is a force */ + if ((Socket->SharedData.SizeOfRecvBuffer != SockReceiveBufferWindow) || + (Force)) + { + /* Set the information in AFD */ + ErrorCode = SockSetInformation(Socket, + AFD_INFO_RECEIVE_WINDOW_SIZE, + NULL, + &Socket->SharedData.SizeOfRecvBuffer, + NULL); + if (ErrorCode != NO_ERROR) return ErrorCode; + } + + /* Do the same thing for the send buffer */ + if ((Socket->SharedData.SizeOfSendBuffer != SockSendBufferWindow) || + (Force)) + { + /* Set the information in AFD */ + ErrorCode = SockSetInformation(Socket, + AFD_INFO_SEND_WINDOW_SIZE, + NULL, + &Socket->SharedData.SizeOfSendBuffer, + NULL); + if (ErrorCode != NO_ERROR) return ErrorCode; + } + + /* Return to caller */ + return NO_ERROR; +} + +BOOLEAN +WSPAPI +IsValidOptionForSocket(IN PSOCKET_INFORMATION Socket, + IN INT Level, + IN INT OptionName) +{ + /* SOL_INTERNAL is always illegal when external, of course */ + if (Level == SOL_INTERNAL) return FALSE; + + /* Anything else but SOL_SOCKET we can't handle, so assume it's legal */ + if (Level != SOL_SOCKET) return TRUE; + + /* Check the option name */ + switch (OptionName) + { + case SO_DONTLINGER: + case SO_KEEPALIVE: + case SO_LINGER: + case SO_OOBINLINE: + case SO_ACCEPTCONN: + /* Only valid on stream sockets */ + if (MSAFD_IS_DGRAM_SOCK(Socket)) return FALSE; + + /* It is one, suceed */ + return TRUE; + + case SO_BROADCAST: + /* Only valid on datagram sockets */ + if (MSAFD_IS_DGRAM_SOCK(Socket)) return TRUE; + + /* It isn't one, fail */ + return FALSE; + + case SO_PROTOCOL_INFOA: + /* Winsock 2 has a hack for this, we should get the W version */ + return FALSE; + + default: + /* Anything else is always valid */ + return TRUE; + } +} + +INT +WSPAPI +SockGetConnectData(IN PSOCKET_INFORMATION Socket, + IN ULONG Ioctl, + IN PVOID Buffer, + IN ULONG BufferLength, + OUT PULONG BufferReturned) +{ + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + NTSTATUS Status; + IO_STATUS_BLOCK IoStatusBlock; + AFD_PENDING_ACCEPT_DATA ConnectData; + + /* Make sure we have Accept Info in the TEB for this Socket */ + if ((ThreadData->AcceptData) && + (ThreadData->AcceptData->ListenHandle == Socket->WshContext.Handle)) + { + /* Set the connect data structure */ + ConnectData.SequenceNumber = ThreadData->AcceptData->SequenceNumber; + ConnectData.ReturnSize = FALSE; + + /* Send it to AFD */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + 0, + &IoStatusBlock, + Ioctl, + &ConnectData, + sizeof(ConnectData), + Buffer, + BufferLength); + } + else + { + /* Request it from AFD */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + 0, + &IoStatusBlock, + Ioctl, + NULL, + 0, + Buffer, + BufferLength); + } + + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + return NtStatusToSocketError(Status); + } + + /* Return the length */ + if (BufferReturned) *BufferReturned = PtrToUlong(IoStatusBlock.Information); + + /* Return success */ + return NO_ERROR; +} + +INT +WSPAPI +WSPIoctl(IN SOCKET Handle, + IN DWORD dwIoControlCode, + IN LPVOID lpvInBuffer, + IN DWORD cbInBuffer, + OUT LPVOID lpvOutBuffer, + IN DWORD cbOutBuffer, + OUT LPDWORD lpcbBytesReturned, + IN LPWSAOVERLAPPED lpOverlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + IN LPWSATHREADID lpThreadId, + OUT LPINT lpErrno) +{ + PSOCKET_INFORMATION Socket; + INT ErrorCode; + PWINSOCK_TEB_DATA ThreadData; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + switch(dwIoControlCode) { + + case FIONBIO: + + /* Check if the Buffer is OK */ + if(cbInBuffer < sizeof(ULONG)) + { + /* Fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + return 0; + + default: + + /* Unsupported for now */ + *lpErrno = WSAEINVAL; + return SOCKET_ERROR; + } + +error: + /* Check if we had a socket */ + if (Socket) + { + /* Release lock and dereference it */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Return error */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return to caller */ + return NO_ERROR; +} + + +INT +WSPAPI +WSPGetSockOpt(IN SOCKET Handle, + IN INT Level, + IN INT OptionName, + OUT CHAR FAR* OptionValue, + IN OUT LPINT OptionLength, + OUT LPINT lpErrno) +{ + PSOCKET_INFORMATION Socket; + INT ErrorCode; + PWINSOCK_TEB_DATA ThreadData; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + *lpErrno = WSAENOTSOCK; + return SOCKET_ERROR; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* Make sure we're not closed */ + if (Socket->SharedData.State == SocketClosed) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Validate the pointer and length */ + if (!(OptionValue) || + !(OptionLength) || + (*OptionLength < sizeof(CHAR)) || + (*OptionLength & 0x80000000)) + { + /* Fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* Validate option */ + if (!IsValidOptionForSocket(Socket, Level, OptionName)) + { + /* Fail */ + ErrorCode = WSAENOPROTOOPT; + goto error; + } + + /* If it's one of the recognized options */ + if (Level == SOL_SOCKET && + (OptionName == SO_BROADCAST || + OptionName == SO_DEBUG || + OptionName == SO_DONTLINGER || + OptionName == SO_LINGER || + OptionName == SO_OOBINLINE || + OptionName == SO_RCVBUF || + OptionName == SO_REUSEADDR || + OptionName == SO_EXCLUSIVEADDRUSE || + OptionName == SO_CONDITIONAL_ACCEPT || + OptionName == SO_SNDBUF || + OptionName == SO_TYPE || + OptionName == SO_ACCEPTCONN || + OptionName == SO_ERROR)) + { + /* Clear the buffer first */ + RtlZeroMemory(OptionValue, *OptionLength); + } + + + /* Check the Level first */ + switch (Level) + { + /* Handle SOL_SOCKET */ + case SOL_SOCKET: + + /* Now check the Option */ + switch (OptionName) + { + case SO_TYPE: + + /* Validate the size */ + if (*OptionLength < sizeof(INT)) + { + /* Size is too small, fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* Return the data */ + *OptionValue = Socket->SharedData.SocketType; + *OptionLength = sizeof(INT); + break; + + case SO_RCVBUF: + + /* Validate the size */ + if (*OptionLength < sizeof(INT)) + { + /* Size is too small, fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* Return the data */ + *(PINT)OptionValue = Socket->SharedData.SizeOfRecvBuffer; + *OptionLength = sizeof(INT); + break; + + case SO_SNDBUF: + + /* Validate the size */ + if (*OptionLength < sizeof(INT)) + { + /* Size is too small, fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* Return the data */ + *(PINT)OptionValue = Socket->SharedData.SizeOfSendBuffer; + *OptionLength = sizeof(INT); + break; + + case SO_ACCEPTCONN: + + /* Return the data */ + *OptionValue = Socket->SharedData.Listening; + *OptionLength = sizeof(BOOLEAN); + break; + + case SO_BROADCAST: + + /* Return the data */ + *OptionValue = Socket->SharedData.Broadcast; + *OptionLength = sizeof(BOOLEAN); + break; + + case SO_DEBUG: + + /* Return the data */ + *OptionValue = Socket->SharedData.Debug; + *OptionLength = sizeof(BOOLEAN); + break; + + case SO_CONDITIONAL_ACCEPT: + case SO_DONTLINGER: + case SO_DONTROUTE: + case SO_ERROR: + case SO_GROUP_ID: + case SO_GROUP_PRIORITY: + case SO_KEEPALIVE: + case SO_LINGER: + case SO_MAX_MSG_SIZE: + case SO_OOBINLINE: + case SO_PROTOCOL_INFO: + case SO_REUSEADDR: + + /* Unsupported */ + + default: + + /* Unsupported by us, give it to the helper */ + ErrorCode = SockGetTdiHandles(Socket); + if (ErrorCode != NO_ERROR) goto error; + + /* Call the helper */ + ErrorCode = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, + Handle, + Socket->TdiAddressHandle, + Socket->TdiConnectionHandle, + Level, + OptionName, + OptionValue, + OptionLength); + if (ErrorCode != NO_ERROR) goto error; + break; + } + + default: + + /* Unsupported by us, give it to the helper */ + ErrorCode = SockGetTdiHandles(Socket); + if (ErrorCode != NO_ERROR) goto error; + + /* Call the helper */ + ErrorCode = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, + Handle, + Socket->TdiAddressHandle, + Socket->TdiConnectionHandle, + Level, + OptionName, + OptionValue, + OptionLength); + if (ErrorCode != NO_ERROR) goto error; + break; + } + +error: + /* Release the lock and dereference the socket */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + + /* Handle error case */ + if (ErrorCode != NO_ERROR) + { + /* Return error */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +INT +WSPAPI +WSPSetSockOpt(IN SOCKET Handle, + IN INT Level, + IN INT OptionName, + IN CONST CHAR FAR *OptionValue, + IN INT OptionLength, + OUT LPINT lpErrno) +{ + PSOCKET_INFORMATION Socket; + INT ErrorCode; + PWINSOCK_TEB_DATA ThreadData; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + *lpErrno = WSAENOTSOCK; + return SOCKET_ERROR; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* Make sure we're not closed */ + if (Socket->SharedData.State == SocketClosed) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Validate the pointer */ + if (!OptionValue) + { + /* Fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* Validate option */ + if (!IsValidOptionForSocket(Socket, Level, OptionName)) + { + /* Fail */ + ErrorCode = WSAENOPROTOOPT; + goto error; + } + + /* FIXME: Write code */ + +error: + + /* Check if this is the failure path */ + if (ErrorCode != NO_ERROR) + { + /* Dereference and unlock the socket */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + + /* Return error */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Update the socket's state in AFD */ + ErrorCode = SockSetHandleContext(Socket); + if (ErrorCode != NO_ERROR) goto error; + + /* Return success */ + return NO_ERROR; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +DWORD SockSendBufferWindow; +DWORD SockReceiveBufferWindow; + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +SockUpdateWindowSizes(IN PSOCKET_INFORMATION Socket, + IN BOOLEAN Force) +{ + INT ErrorCode; + + /* Check if this is a connection-less socket */ + if (Socket->SharedData.ServiceFlags1 & XP1_CONNECTIONLESS) + { + /* It must be bound */ + if (Socket->SharedData.State == SocketOpen) return NO_ERROR; + } + else + { + /* It must be connected */ + if (Socket->SharedData.State == SocketConnected) return NO_ERROR; + + /* Get the TDI handles for it */ + ErrorCode = SockGetTdiHandles(Socket); + if (ErrorCode != NO_ERROR) return ErrorCode; + + /* Tell WSH the new size */ + ErrorCode = Socket->HelperData->WSHSetSocketInformation(Socket->HelperContext, + Socket->Handle, + Socket->TdiAddressHandle, + Socket->TdiConnectionHandle, + SOL_SOCKET, + SO_RCVBUF, + (PVOID)&Socket->SharedData.SizeOfRecvBuffer, + sizeof(DWORD)); + } + + /* Check if the buffer changed, or if this is a force */ + if ((Socket->SharedData.SizeOfRecvBuffer != SockReceiveBufferWindow) || + (Force)) + { + /* Set the information in AFD */ + ErrorCode = SockSetInformation(Socket, + AFD_INFO_RECEIVE_WINDOW_SIZE, + NULL, + &Socket->SharedData.SizeOfRecvBuffer, + NULL); + if (ErrorCode != NO_ERROR) return ErrorCode; + } + + /* Do the same thing for the send buffer */ + if ((Socket->SharedData.SizeOfSendBuffer != SockSendBufferWindow) || + (Force)) + { + /* Set the information in AFD */ + ErrorCode = SockSetInformation(Socket, + AFD_INFO_SEND_WINDOW_SIZE, + NULL, + &Socket->SharedData.SizeOfSendBuffer, + NULL); + if (ErrorCode != NO_ERROR) return ErrorCode; + } + + /* Return to caller */ + return NO_ERROR; +} + +BOOLEAN +WSPAPI +IsValidOptionForSocket(IN PSOCKET_INFORMATION Socket, + IN INT Level, + IN INT OptionName) +{ + /* SOL_INTERNAL is always illegal when external, of course */ + if (Level == SOL_INTERNAL) return FALSE; + + /* Anything else but SOL_SOCKET we can't handle, so assume it's legal */ + if (Level != SOL_SOCKET) return TRUE; + + /* Check the option name */ + switch (OptionName) + { + case SO_DONTLINGER: + case SO_KEEPALIVE: + case SO_LINGER: + case SO_OOBINLINE: + case SO_ACCEPTCONN: + /* Only valid on stream sockets */ + if (MSAFD_IS_DGRAM_SOCK(Socket)) return FALSE; + + /* It is one, suceed */ + return TRUE; + + case SO_BROADCAST: + /* Only valid on datagram sockets */ + if (MSAFD_IS_DGRAM_SOCK(Socket)) return TRUE; + + /* It isn't one, fail */ + return FALSE; + + case SO_PROTOCOL_INFOA: + /* Winsock 2 has a hack for this, we should get the W version */ + return FALSE; + + default: + /* Anything else is always valid */ + return TRUE; + } +} + +INT +WSPAPI +SockGetConnectData(IN PSOCKET_INFORMATION Socket, + IN ULONG Ioctl, + IN PVOID Buffer, + IN ULONG BufferLength, + OUT PULONG BufferReturned) +{ + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + NTSTATUS Status; + IO_STATUS_BLOCK IoStatusBlock; + AFD_PENDING_ACCEPT_DATA ConnectData; + + /* Make sure we have Accept Info in the TEB for this Socket */ + if ((ThreadData->AcceptData) && + (ThreadData->AcceptData->ListenHandle == Socket->WshContext.Handle)) + { + /* Set the connect data structure */ + ConnectData.SequenceNumber = ThreadData->AcceptData->SequenceNumber; + ConnectData.ReturnSize = FALSE; + + /* Send it to AFD */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + 0, + &IoStatusBlock, + Ioctl, + &ConnectData, + sizeof(ConnectData), + Buffer, + BufferLength); + } + else + { + /* Request it from AFD */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + 0, + &IoStatusBlock, + Ioctl, + NULL, + 0, + Buffer, + BufferLength); + } + + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + return NtStatusToSocketError(Status); + } + + /* Return the length */ + if (BufferReturned) *BufferReturned = PtrToUlong(IoStatusBlock.Information); + + /* Return success */ + return NO_ERROR; +} + +INT +WSPAPI +WSPIoctl(IN SOCKET Handle, + IN DWORD dwIoControlCode, + IN LPVOID lpvInBuffer, + IN DWORD cbInBuffer, + OUT LPVOID lpvOutBuffer, + IN DWORD cbOutBuffer, + OUT LPDWORD lpcbBytesReturned, + IN LPWSAOVERLAPPED lpOverlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + IN LPWSATHREADID lpThreadId, + OUT LPINT lpErrno) +{ + PSOCKET_INFORMATION Socket; + INT ErrorCode; + PWINSOCK_TEB_DATA ThreadData; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + switch(dwIoControlCode) { + + case FIONBIO: + + /* Check if the Buffer is OK */ + if(cbInBuffer < sizeof(ULONG)) + { + /* Fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + return 0; + + default: + + /* Unsupported for now */ + *lpErrno = WSAEINVAL; + return SOCKET_ERROR; + } + +error: + /* Check if we had a socket */ + if (Socket) + { + /* Release lock and dereference it */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Return error */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return to caller */ + return NO_ERROR; +} + + +INT +WSPAPI +WSPGetSockOpt(IN SOCKET Handle, + IN INT Level, + IN INT OptionName, + OUT CHAR FAR* OptionValue, + IN OUT LPINT OptionLength, + OUT LPINT lpErrno) +{ + PSOCKET_INFORMATION Socket; + INT ErrorCode; + PWINSOCK_TEB_DATA ThreadData; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + *lpErrno = WSAENOTSOCK; + return SOCKET_ERROR; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* Make sure we're not closed */ + if (Socket->SharedData.State == SocketClosed) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Validate the pointer and length */ + if (!(OptionValue) || + !(OptionLength) || + (*OptionLength < sizeof(CHAR)) || + (*OptionLength & 0x80000000)) + { + /* Fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* Validate option */ + if (!IsValidOptionForSocket(Socket, Level, OptionName)) + { + /* Fail */ + ErrorCode = WSAENOPROTOOPT; + goto error; + } + + /* If it's one of the recognized options */ + if (Level == SOL_SOCKET && + (OptionName == SO_BROADCAST || + OptionName == SO_DEBUG || + OptionName == SO_DONTLINGER || + OptionName == SO_LINGER || + OptionName == SO_OOBINLINE || + OptionName == SO_RCVBUF || + OptionName == SO_REUSEADDR || + OptionName == SO_EXCLUSIVEADDRUSE || + OptionName == SO_CONDITIONAL_ACCEPT || + OptionName == SO_SNDBUF || + OptionName == SO_TYPE || + OptionName == SO_ACCEPTCONN || + OptionName == SO_ERROR)) + { + /* Clear the buffer first */ + RtlZeroMemory(OptionValue, *OptionLength); + } + + + /* Check the Level first */ + switch (Level) + { + /* Handle SOL_SOCKET */ + case SOL_SOCKET: + + /* Now check the Option */ + switch (OptionName) + { + case SO_TYPE: + + /* Validate the size */ + if (*OptionLength < sizeof(INT)) + { + /* Size is too small, fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* Return the data */ + *OptionValue = Socket->SharedData.SocketType; + *OptionLength = sizeof(INT); + break; + + case SO_RCVBUF: + + /* Validate the size */ + if (*OptionLength < sizeof(INT)) + { + /* Size is too small, fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* Return the data */ + *(PINT)OptionValue = Socket->SharedData.SizeOfRecvBuffer; + *OptionLength = sizeof(INT); + break; + + case SO_SNDBUF: + + /* Validate the size */ + if (*OptionLength < sizeof(INT)) + { + /* Size is too small, fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* Return the data */ + *(PINT)OptionValue = Socket->SharedData.SizeOfSendBuffer; + *OptionLength = sizeof(INT); + break; + + case SO_ACCEPTCONN: + + /* Return the data */ + *OptionValue = Socket->SharedData.Listening; + *OptionLength = sizeof(BOOLEAN); + break; + + case SO_BROADCAST: + + /* Return the data */ + *OptionValue = Socket->SharedData.Broadcast; + *OptionLength = sizeof(BOOLEAN); + break; + + case SO_DEBUG: + + /* Return the data */ + *OptionValue = Socket->SharedData.Debug; + *OptionLength = sizeof(BOOLEAN); + break; + + case SO_CONDITIONAL_ACCEPT: + case SO_DONTLINGER: + case SO_DONTROUTE: + case SO_ERROR: + case SO_GROUP_ID: + case SO_GROUP_PRIORITY: + case SO_KEEPALIVE: + case SO_LINGER: + case SO_MAX_MSG_SIZE: + case SO_OOBINLINE: + case SO_PROTOCOL_INFO: + case SO_REUSEADDR: + + /* Unsupported */ + + default: + + /* Unsupported by us, give it to the helper */ + ErrorCode = SockGetTdiHandles(Socket); + if (ErrorCode != NO_ERROR) goto error; + + /* Call the helper */ + ErrorCode = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, + Handle, + Socket->TdiAddressHandle, + Socket->TdiConnectionHandle, + Level, + OptionName, + OptionValue, + OptionLength); + if (ErrorCode != NO_ERROR) goto error; + break; + } + + default: + + /* Unsupported by us, give it to the helper */ + ErrorCode = SockGetTdiHandles(Socket); + if (ErrorCode != NO_ERROR) goto error; + + /* Call the helper */ + ErrorCode = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, + Handle, + Socket->TdiAddressHandle, + Socket->TdiConnectionHandle, + Level, + OptionName, + OptionValue, + OptionLength); + if (ErrorCode != NO_ERROR) goto error; + break; + } + +error: + /* Release the lock and dereference the socket */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + + /* Handle error case */ + if (ErrorCode != NO_ERROR) + { + /* Return error */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +INT +WSPAPI +WSPSetSockOpt(IN SOCKET Handle, + IN INT Level, + IN INT OptionName, + IN CONST CHAR FAR *OptionValue, + IN INT OptionLength, + OUT LPINT lpErrno) +{ + PSOCKET_INFORMATION Socket; + INT ErrorCode; + PWINSOCK_TEB_DATA ThreadData; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + *lpErrno = WSAENOTSOCK; + return SOCKET_ERROR; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* Make sure we're not closed */ + if (Socket->SharedData.State == SocketClosed) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Validate the pointer */ + if (!OptionValue) + { + /* Fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* Validate option */ + if (!IsValidOptionForSocket(Socket, Level, OptionName)) + { + /* Fail */ + ErrorCode = WSAENOPROTOOPT; + goto error; + } + + /* FIXME: Write code */ + +error: + + /* Check if this is the failure path */ + if (ErrorCode != NO_ERROR) + { + /* Dereference and unlock the socket */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + + /* Return error */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Update the socket's state in AFD */ + ErrorCode = SockSetHandleContext(Socket); + if (ErrorCode != NO_ERROR) goto error; + + /* Return success */ + return NO_ERROR; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +DWORD SockSendBufferWindow; +DWORD SockReceiveBufferWindow; + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +SockUpdateWindowSizes(IN PSOCKET_INFORMATION Socket, + IN BOOLEAN Force) +{ + INT ErrorCode; + + /* Check if this is a connection-less socket */ + if (Socket->SharedData.ServiceFlags1 & XP1_CONNECTIONLESS) + { + /* It must be bound */ + if (Socket->SharedData.State == SocketOpen) return NO_ERROR; + } + else + { + /* It must be connected */ + if (Socket->SharedData.State == SocketConnected) return NO_ERROR; + + /* Get the TDI handles for it */ + ErrorCode = SockGetTdiHandles(Socket); + if (ErrorCode != NO_ERROR) return ErrorCode; + + /* Tell WSH the new size */ + ErrorCode = Socket->HelperData->WSHSetSocketInformation(Socket->HelperContext, + Socket->Handle, + Socket->TdiAddressHandle, + Socket->TdiConnectionHandle, + SOL_SOCKET, + SO_RCVBUF, + (PVOID)&Socket->SharedData.SizeOfRecvBuffer, + sizeof(DWORD)); + } + + /* Check if the buffer changed, or if this is a force */ + if ((Socket->SharedData.SizeOfRecvBuffer != SockReceiveBufferWindow) || + (Force)) + { + /* Set the information in AFD */ + ErrorCode = SockSetInformation(Socket, + AFD_INFO_RECEIVE_WINDOW_SIZE, + NULL, + &Socket->SharedData.SizeOfRecvBuffer, + NULL); + if (ErrorCode != NO_ERROR) return ErrorCode; + } + + /* Do the same thing for the send buffer */ + if ((Socket->SharedData.SizeOfSendBuffer != SockSendBufferWindow) || + (Force)) + { + /* Set the information in AFD */ + ErrorCode = SockSetInformation(Socket, + AFD_INFO_SEND_WINDOW_SIZE, + NULL, + &Socket->SharedData.SizeOfSendBuffer, + NULL); + if (ErrorCode != NO_ERROR) return ErrorCode; + } + + /* Return to caller */ + return NO_ERROR; +} + +BOOLEAN +WSPAPI +IsValidOptionForSocket(IN PSOCKET_INFORMATION Socket, + IN INT Level, + IN INT OptionName) +{ + /* SOL_INTERNAL is always illegal when external, of course */ + if (Level == SOL_INTERNAL) return FALSE; + + /* Anything else but SOL_SOCKET we can't handle, so assume it's legal */ + if (Level != SOL_SOCKET) return TRUE; + + /* Check the option name */ + switch (OptionName) + { + case SO_DONTLINGER: + case SO_KEEPALIVE: + case SO_LINGER: + case SO_OOBINLINE: + case SO_ACCEPTCONN: + /* Only valid on stream sockets */ + if (MSAFD_IS_DGRAM_SOCK(Socket)) return FALSE; + + /* It is one, suceed */ + return TRUE; + + case SO_BROADCAST: + /* Only valid on datagram sockets */ + if (MSAFD_IS_DGRAM_SOCK(Socket)) return TRUE; + + /* It isn't one, fail */ + return FALSE; + + case SO_PROTOCOL_INFOA: + /* Winsock 2 has a hack for this, we should get the W version */ + return FALSE; + + default: + /* Anything else is always valid */ + return TRUE; + } +} + +INT +WSPAPI +SockGetConnectData(IN PSOCKET_INFORMATION Socket, + IN ULONG Ioctl, + IN PVOID Buffer, + IN ULONG BufferLength, + OUT PULONG BufferReturned) +{ + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + NTSTATUS Status; + IO_STATUS_BLOCK IoStatusBlock; + AFD_PENDING_ACCEPT_DATA ConnectData; + + /* Make sure we have Accept Info in the TEB for this Socket */ + if ((ThreadData->AcceptData) && + (ThreadData->AcceptData->ListenHandle == Socket->WshContext.Handle)) + { + /* Set the connect data structure */ + ConnectData.SequenceNumber = ThreadData->AcceptData->SequenceNumber; + ConnectData.ReturnSize = FALSE; + + /* Send it to AFD */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + 0, + &IoStatusBlock, + Ioctl, + &ConnectData, + sizeof(ConnectData), + Buffer, + BufferLength); + } + else + { + /* Request it from AFD */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + 0, + &IoStatusBlock, + Ioctl, + NULL, + 0, + Buffer, + BufferLength); + } + + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + return NtStatusToSocketError(Status); + } + + /* Return the length */ + if (BufferReturned) *BufferReturned = PtrToUlong(IoStatusBlock.Information); + + /* Return success */ + return NO_ERROR; +} + +INT +WSPAPI +WSPIoctl(IN SOCKET Handle, + IN DWORD dwIoControlCode, + IN LPVOID lpvInBuffer, + IN DWORD cbInBuffer, + OUT LPVOID lpvOutBuffer, + IN DWORD cbOutBuffer, + OUT LPDWORD lpcbBytesReturned, + IN LPWSAOVERLAPPED lpOverlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + IN LPWSATHREADID lpThreadId, + OUT LPINT lpErrno) +{ + PSOCKET_INFORMATION Socket; + INT ErrorCode; + PWINSOCK_TEB_DATA ThreadData; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + switch(dwIoControlCode) { + + case FIONBIO: + + /* Check if the Buffer is OK */ + if(cbInBuffer < sizeof(ULONG)) + { + /* Fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + return 0; + + default: + + /* Unsupported for now */ + *lpErrno = WSAEINVAL; + return SOCKET_ERROR; + } + +error: + /* Check if we had a socket */ + if (Socket) + { + /* Release lock and dereference it */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Return error */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return to caller */ + return NO_ERROR; +} + + +INT +WSPAPI +WSPGetSockOpt(IN SOCKET Handle, + IN INT Level, + IN INT OptionName, + OUT CHAR FAR* OptionValue, + IN OUT LPINT OptionLength, + OUT LPINT lpErrno) +{ + PSOCKET_INFORMATION Socket; + INT ErrorCode; + PWINSOCK_TEB_DATA ThreadData; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + *lpErrno = WSAENOTSOCK; + return SOCKET_ERROR; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* Make sure we're not closed */ + if (Socket->SharedData.State == SocketClosed) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Validate the pointer and length */ + if (!(OptionValue) || + !(OptionLength) || + (*OptionLength < sizeof(CHAR)) || + (*OptionLength & 0x80000000)) + { + /* Fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* Validate option */ + if (!IsValidOptionForSocket(Socket, Level, OptionName)) + { + /* Fail */ + ErrorCode = WSAENOPROTOOPT; + goto error; + } + + /* If it's one of the recognized options */ + if (Level == SOL_SOCKET && + (OptionName == SO_BROADCAST || + OptionName == SO_DEBUG || + OptionName == SO_DONTLINGER || + OptionName == SO_LINGER || + OptionName == SO_OOBINLINE || + OptionName == SO_RCVBUF || + OptionName == SO_REUSEADDR || + OptionName == SO_EXCLUSIVEADDRUSE || + OptionName == SO_CONDITIONAL_ACCEPT || + OptionName == SO_SNDBUF || + OptionName == SO_TYPE || + OptionName == SO_ACCEPTCONN || + OptionName == SO_ERROR)) + { + /* Clear the buffer first */ + RtlZeroMemory(OptionValue, *OptionLength); + } + + + /* Check the Level first */ + switch (Level) + { + /* Handle SOL_SOCKET */ + case SOL_SOCKET: + + /* Now check the Option */ + switch (OptionName) + { + case SO_TYPE: + + /* Validate the size */ + if (*OptionLength < sizeof(INT)) + { + /* Size is too small, fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* Return the data */ + *OptionValue = Socket->SharedData.SocketType; + *OptionLength = sizeof(INT); + break; + + case SO_RCVBUF: + + /* Validate the size */ + if (*OptionLength < sizeof(INT)) + { + /* Size is too small, fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* Return the data */ + *(PINT)OptionValue = Socket->SharedData.SizeOfRecvBuffer; + *OptionLength = sizeof(INT); + break; + + case SO_SNDBUF: + + /* Validate the size */ + if (*OptionLength < sizeof(INT)) + { + /* Size is too small, fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* Return the data */ + *(PINT)OptionValue = Socket->SharedData.SizeOfSendBuffer; + *OptionLength = sizeof(INT); + break; + + case SO_ACCEPTCONN: + + /* Return the data */ + *OptionValue = Socket->SharedData.Listening; + *OptionLength = sizeof(BOOLEAN); + break; + + case SO_BROADCAST: + + /* Return the data */ + *OptionValue = Socket->SharedData.Broadcast; + *OptionLength = sizeof(BOOLEAN); + break; + + case SO_DEBUG: + + /* Return the data */ + *OptionValue = Socket->SharedData.Debug; + *OptionLength = sizeof(BOOLEAN); + break; + + case SO_CONDITIONAL_ACCEPT: + case SO_DONTLINGER: + case SO_DONTROUTE: + case SO_ERROR: + case SO_GROUP_ID: + case SO_GROUP_PRIORITY: + case SO_KEEPALIVE: + case SO_LINGER: + case SO_MAX_MSG_SIZE: + case SO_OOBINLINE: + case SO_PROTOCOL_INFO: + case SO_REUSEADDR: + + /* Unsupported */ + + default: + + /* Unsupported by us, give it to the helper */ + ErrorCode = SockGetTdiHandles(Socket); + if (ErrorCode != NO_ERROR) goto error; + + /* Call the helper */ + ErrorCode = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, + Handle, + Socket->TdiAddressHandle, + Socket->TdiConnectionHandle, + Level, + OptionName, + OptionValue, + OptionLength); + if (ErrorCode != NO_ERROR) goto error; + break; + } + + default: + + /* Unsupported by us, give it to the helper */ + ErrorCode = SockGetTdiHandles(Socket); + if (ErrorCode != NO_ERROR) goto error; + + /* Call the helper */ + ErrorCode = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, + Handle, + Socket->TdiAddressHandle, + Socket->TdiConnectionHandle, + Level, + OptionName, + OptionValue, + OptionLength); + if (ErrorCode != NO_ERROR) goto error; + break; + } + +error: + /* Release the lock and dereference the socket */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + + /* Handle error case */ + if (ErrorCode != NO_ERROR) + { + /* Return error */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +INT +WSPAPI +WSPSetSockOpt(IN SOCKET Handle, + IN INT Level, + IN INT OptionName, + IN CONST CHAR FAR *OptionValue, + IN INT OptionLength, + OUT LPINT lpErrno) +{ + PSOCKET_INFORMATION Socket; + INT ErrorCode; + PWINSOCK_TEB_DATA ThreadData; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + *lpErrno = WSAENOTSOCK; + return SOCKET_ERROR; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* Make sure we're not closed */ + if (Socket->SharedData.State == SocketClosed) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Validate the pointer */ + if (!OptionValue) + { + /* Fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* Validate option */ + if (!IsValidOptionForSocket(Socket, Level, OptionName)) + { + /* Fail */ + ErrorCode = WSAENOPROTOOPT; + goto error; + } + + /* FIXME: Write code */ + +error: + + /* Check if this is the failure path */ + if (ErrorCode != NO_ERROR) + { + /* Dereference and unlock the socket */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + + /* Return error */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Update the socket's state in AFD */ + ErrorCode = SockSetHandleContext(Socket); + if (ErrorCode != NO_ERROR) goto error; + + /* Return success */ + return NO_ERROR; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +DWORD SockSendBufferWindow; +DWORD SockReceiveBufferWindow; + +/* FUNCTIONS *****************************************************************/ + +INT +WSPAPI +SockUpdateWindowSizes(IN PSOCKET_INFORMATION Socket, + IN BOOLEAN Force) +{ + INT ErrorCode; + + /* Check if this is a connection-less socket */ + if (Socket->SharedData.ServiceFlags1 & XP1_CONNECTIONLESS) + { + /* It must be bound */ + if (Socket->SharedData.State == SocketOpen) return NO_ERROR; + } + else + { + /* It must be connected */ + if (Socket->SharedData.State == SocketConnected) return NO_ERROR; + + /* Get the TDI handles for it */ + ErrorCode = SockGetTdiHandles(Socket); + if (ErrorCode != NO_ERROR) return ErrorCode; + + /* Tell WSH the new size */ + ErrorCode = Socket->HelperData->WSHSetSocketInformation(Socket->HelperContext, + Socket->Handle, + Socket->TdiAddressHandle, + Socket->TdiConnectionHandle, + SOL_SOCKET, + SO_RCVBUF, + (PVOID)&Socket->SharedData.SizeOfRecvBuffer, + sizeof(DWORD)); + } + + /* Check if the buffer changed, or if this is a force */ + if ((Socket->SharedData.SizeOfRecvBuffer != SockReceiveBufferWindow) || + (Force)) + { + /* Set the information in AFD */ + ErrorCode = SockSetInformation(Socket, + AFD_INFO_RECEIVE_WINDOW_SIZE, + NULL, + &Socket->SharedData.SizeOfRecvBuffer, + NULL); + if (ErrorCode != NO_ERROR) return ErrorCode; + } + + /* Do the same thing for the send buffer */ + if ((Socket->SharedData.SizeOfSendBuffer != SockSendBufferWindow) || + (Force)) + { + /* Set the information in AFD */ + ErrorCode = SockSetInformation(Socket, + AFD_INFO_SEND_WINDOW_SIZE, + NULL, + &Socket->SharedData.SizeOfSendBuffer, + NULL); + if (ErrorCode != NO_ERROR) return ErrorCode; + } + + /* Return to caller */ + return NO_ERROR; +} + +BOOLEAN +WSPAPI +IsValidOptionForSocket(IN PSOCKET_INFORMATION Socket, + IN INT Level, + IN INT OptionName) +{ + /* SOL_INTERNAL is always illegal when external, of course */ + if (Level == SOL_INTERNAL) return FALSE; + + /* Anything else but SOL_SOCKET we can't handle, so assume it's legal */ + if (Level != SOL_SOCKET) return TRUE; + + /* Check the option name */ + switch (OptionName) + { + case SO_DONTLINGER: + case SO_KEEPALIVE: + case SO_LINGER: + case SO_OOBINLINE: + case SO_ACCEPTCONN: + /* Only valid on stream sockets */ + if (MSAFD_IS_DGRAM_SOCK(Socket)) return FALSE; + + /* It is one, suceed */ + return TRUE; + + case SO_BROADCAST: + /* Only valid on datagram sockets */ + if (MSAFD_IS_DGRAM_SOCK(Socket)) return TRUE; + + /* It isn't one, fail */ + return FALSE; + + case SO_PROTOCOL_INFOA: + /* Winsock 2 has a hack for this, we should get the W version */ + return FALSE; + + default: + /* Anything else is always valid */ + return TRUE; + } +} + +INT +WSPAPI +SockGetConnectData(IN PSOCKET_INFORMATION Socket, + IN ULONG Ioctl, + IN PVOID Buffer, + IN ULONG BufferLength, + OUT PULONG BufferReturned) +{ + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + NTSTATUS Status; + IO_STATUS_BLOCK IoStatusBlock; + AFD_PENDING_ACCEPT_DATA ConnectData; + + /* Make sure we have Accept Info in the TEB for this Socket */ + if ((ThreadData->AcceptData) && + (ThreadData->AcceptData->ListenHandle == Socket->WshContext.Handle)) + { + /* Set the connect data structure */ + ConnectData.SequenceNumber = ThreadData->AcceptData->SequenceNumber; + ConnectData.ReturnSize = FALSE; + + /* Send it to AFD */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + 0, + &IoStatusBlock, + Ioctl, + &ConnectData, + sizeof(ConnectData), + Buffer, + BufferLength); + } + else + { + /* Request it from AFD */ + Status = NtDeviceIoControlFile(Socket->WshContext.Handle, + ThreadData->EventHandle, + NULL, + 0, + &IoStatusBlock, + Ioctl, + NULL, + 0, + Buffer, + BufferLength); + } + + /* Check if we need to wait */ + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + SockWaitForSingleObject(ThreadData->EventHandle, + Socket->Handle, + NO_BLOCKING_HOOK, + NO_TIMEOUT); + + /* Get new status */ + Status = IoStatusBlock.Status; + } + + /* Check for error */ + if (!NT_SUCCESS(Status)) + { + /* Fail */ + return NtStatusToSocketError(Status); + } + + /* Return the length */ + if (BufferReturned) *BufferReturned = PtrToUlong(IoStatusBlock.Information); + + /* Return success */ + return NO_ERROR; +} + +INT +WSPAPI +WSPIoctl(IN SOCKET Handle, + IN DWORD dwIoControlCode, + IN LPVOID lpvInBuffer, + IN DWORD cbInBuffer, + OUT LPVOID lpvOutBuffer, + IN DWORD cbOutBuffer, + OUT LPDWORD lpcbBytesReturned, + IN LPWSAOVERLAPPED lpOverlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + IN LPWSATHREADID lpThreadId, + OUT LPINT lpErrno) +{ + PSOCKET_INFORMATION Socket; + INT ErrorCode; + PWINSOCK_TEB_DATA ThreadData; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + switch(dwIoControlCode) { + + case FIONBIO: + + /* Check if the Buffer is OK */ + if(cbInBuffer < sizeof(ULONG)) + { + /* Fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + return 0; + + default: + + /* Unsupported for now */ + *lpErrno = WSAEINVAL; + return SOCKET_ERROR; + } + +error: + /* Check if we had a socket */ + if (Socket) + { + /* Release lock and dereference it */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + } + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Return error */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return to caller */ + return NO_ERROR; +} + + +INT +WSPAPI +WSPGetSockOpt(IN SOCKET Handle, + IN INT Level, + IN INT OptionName, + OUT CHAR FAR* OptionValue, + IN OUT LPINT OptionLength, + OUT LPINT lpErrno) +{ + PSOCKET_INFORMATION Socket; + INT ErrorCode; + PWINSOCK_TEB_DATA ThreadData; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + *lpErrno = WSAENOTSOCK; + return SOCKET_ERROR; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* Make sure we're not closed */ + if (Socket->SharedData.State == SocketClosed) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Validate the pointer and length */ + if (!(OptionValue) || + !(OptionLength) || + (*OptionLength < sizeof(CHAR)) || + (*OptionLength & 0x80000000)) + { + /* Fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* Validate option */ + if (!IsValidOptionForSocket(Socket, Level, OptionName)) + { + /* Fail */ + ErrorCode = WSAENOPROTOOPT; + goto error; + } + + /* If it's one of the recognized options */ + if (Level == SOL_SOCKET && + (OptionName == SO_BROADCAST || + OptionName == SO_DEBUG || + OptionName == SO_DONTLINGER || + OptionName == SO_LINGER || + OptionName == SO_OOBINLINE || + OptionName == SO_RCVBUF || + OptionName == SO_REUSEADDR || + OptionName == SO_EXCLUSIVEADDRUSE || + OptionName == SO_CONDITIONAL_ACCEPT || + OptionName == SO_SNDBUF || + OptionName == SO_TYPE || + OptionName == SO_ACCEPTCONN || + OptionName == SO_ERROR)) + { + /* Clear the buffer first */ + RtlZeroMemory(OptionValue, *OptionLength); + } + + + /* Check the Level first */ + switch (Level) + { + /* Handle SOL_SOCKET */ + case SOL_SOCKET: + + /* Now check the Option */ + switch (OptionName) + { + case SO_TYPE: + + /* Validate the size */ + if (*OptionLength < sizeof(INT)) + { + /* Size is too small, fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* Return the data */ + *OptionValue = Socket->SharedData.SocketType; + *OptionLength = sizeof(INT); + break; + + case SO_RCVBUF: + + /* Validate the size */ + if (*OptionLength < sizeof(INT)) + { + /* Size is too small, fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* Return the data */ + *(PINT)OptionValue = Socket->SharedData.SizeOfRecvBuffer; + *OptionLength = sizeof(INT); + break; + + case SO_SNDBUF: + + /* Validate the size */ + if (*OptionLength < sizeof(INT)) + { + /* Size is too small, fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* Return the data */ + *(PINT)OptionValue = Socket->SharedData.SizeOfSendBuffer; + *OptionLength = sizeof(INT); + break; + + case SO_ACCEPTCONN: + + /* Return the data */ + *OptionValue = Socket->SharedData.Listening; + *OptionLength = sizeof(BOOLEAN); + break; + + case SO_BROADCAST: + + /* Return the data */ + *OptionValue = Socket->SharedData.Broadcast; + *OptionLength = sizeof(BOOLEAN); + break; + + case SO_DEBUG: + + /* Return the data */ + *OptionValue = Socket->SharedData.Debug; + *OptionLength = sizeof(BOOLEAN); + break; + + case SO_CONDITIONAL_ACCEPT: + case SO_DONTLINGER: + case SO_DONTROUTE: + case SO_ERROR: + case SO_GROUP_ID: + case SO_GROUP_PRIORITY: + case SO_KEEPALIVE: + case SO_LINGER: + case SO_MAX_MSG_SIZE: + case SO_OOBINLINE: + case SO_PROTOCOL_INFO: + case SO_REUSEADDR: + + /* Unsupported */ + + default: + + /* Unsupported by us, give it to the helper */ + ErrorCode = SockGetTdiHandles(Socket); + if (ErrorCode != NO_ERROR) goto error; + + /* Call the helper */ + ErrorCode = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, + Handle, + Socket->TdiAddressHandle, + Socket->TdiConnectionHandle, + Level, + OptionName, + OptionValue, + OptionLength); + if (ErrorCode != NO_ERROR) goto error; + break; + } + + default: + + /* Unsupported by us, give it to the helper */ + ErrorCode = SockGetTdiHandles(Socket); + if (ErrorCode != NO_ERROR) goto error; + + /* Call the helper */ + ErrorCode = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, + Handle, + Socket->TdiAddressHandle, + Socket->TdiConnectionHandle, + Level, + OptionName, + OptionValue, + OptionLength); + if (ErrorCode != NO_ERROR) goto error; + break; + } + +error: + /* Release the lock and dereference the socket */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + + /* Handle error case */ + if (ErrorCode != NO_ERROR) + { + /* Return error */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Return success */ + return NO_ERROR; +} + +INT +WSPAPI +WSPSetSockOpt(IN SOCKET Handle, + IN INT Level, + IN INT OptionName, + IN CONST CHAR FAR *OptionValue, + IN INT OptionLength, + OUT LPINT lpErrno) +{ + PSOCKET_INFORMATION Socket; + INT ErrorCode; + PWINSOCK_TEB_DATA ThreadData; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Get the socket structure */ + Socket = SockFindAndReferenceSocket(Handle, TRUE); + if (!Socket) + { + /* Fail */ + *lpErrno = WSAENOTSOCK; + return SOCKET_ERROR; + } + + /* Lock the socket */ + EnterCriticalSection(&Socket->Lock); + + /* Make sure we're not closed */ + if (Socket->SharedData.State == SocketClosed) + { + /* Fail */ + ErrorCode = WSAENOTSOCK; + goto error; + } + + /* Validate the pointer */ + if (!OptionValue) + { + /* Fail */ + ErrorCode = WSAEFAULT; + goto error; + } + + /* Validate option */ + if (!IsValidOptionForSocket(Socket, Level, OptionName)) + { + /* Fail */ + ErrorCode = WSAENOPROTOOPT; + goto error; + } + + /* FIXME: Write code */ + +error: + + /* Check if this is the failure path */ + if (ErrorCode != NO_ERROR) + { + /* Dereference and unlock the socket */ + LeaveCriticalSection(&Socket->Lock); + SockDereferenceSocket(Socket); + + /* Return error */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Update the socket's state in AFD */ + ErrorCode = SockSetHandleContext(Socket); + if (ErrorCode != NO_ERROR) goto error; + + /* Return success */ + return NO_ERROR; +} + diff --git a/dll/win32/mswsock/msafd/spi.c b/dll/win32/mswsock/msafd/spi.c new file mode 100644 index 00000000000..eadc7194da5 --- /dev/null +++ b/dll/win32/mswsock/msafd/spi.c @@ -0,0 +1,884 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +PVOID pfnIcfOpenPort; +PICF_CONNECT pfnIcfConnect; +PVOID pfnIcfDisconnect; +HINSTANCE IcfDllHandle; + +WSPPROC_TABLE SockProcTable = +{ + &WSPAccept, + &WSPAddressToString, + &WSPAsyncSelect, + &WSPBind, + &WSPCancelBlockingCall, + &WSPCleanup, + &WSPCloseSocket, + &WSPConnect, + &WSPDuplicateSocket, + &WSPEnumNetworkEvents, + &WSPEventSelect, + &WSPGetOverlappedResult, + &WSPGetPeerName, + &WSPGetSockName, + &WSPGetSockOpt, + &WSPGetQOSByName, + &WSPIoctl, + &WSPJoinLeaf, + &WSPListen, + &WSPRecv, + &WSPRecvDisconnect, + &WSPRecvFrom, + &WSPSelect, + &WSPSend, + &WSPSendDisconnect, + &WSPSendTo, + &WSPSetSockOpt, + &WSPShutdown, + &WSPSocket, + &WSPStringToAddress +}; + +LONG SockWspStartupCount; +WSPUPCALLTABLE SockUpcallTableHack; +LPWSPUPCALLTABLE SockUpcallTable; + +/* FUNCTIONS *****************************************************************/ + +VOID +WSPAPI +NewIcfConnection(IN PSOCK_ICF_DATA IcfData) +{ + /* Load the ICF DLL */ + IcfData->DllHandle = LoadLibraryW(L"hhnetcfg.dll"); + if (IcfData->DllHandle) + { + /* Get the entrypoints */ + IcfData->IcfOpenDynamicFwPort = GetProcAddress(IcfData->DllHandle, + "IcfOpenDynamicFwPort"); + IcfData->IcfConnect = (PICF_CONNECT)GetProcAddress(IcfData->DllHandle, + "IcfConnect"); + IcfData->IcfDisconnect = GetProcAddress(IcfData->DllHandle, + "IcfDisconnect"); + + /* Now call IcfConnect */ + if (!IcfData->IcfConnect(IcfData)) + { + /* We failed, release the library */ + FreeLibrary(IcfData->DllHandle); + } + } +} + +VOID +WSPAPI +InitializeIcfConnection(IN PSOCK_ICF_DATA IcfData) +{ + /* Make sure we have an ICF Handle */ + if (IcfData->IcfHandle) + { + /* Save the function pointers and dll handle */ + IcfDllHandle = IcfData->DllHandle; + pfnIcfOpenPort = IcfData->IcfOpenDynamicFwPort; + pfnIcfConnect = IcfData->IcfConnect; + pfnIcfDisconnect = IcfData->IcfDisconnect; + } +} + +VOID +WSPAPI +CloseIcfConnection(IN PSOCK_ICF_DATA IcfData) +{ + /* Make sure we have an ICF Handle */ + if (IcfData->IcfHandle) + { + /* Call IcfDisconnect */ + IcfData->IcfConnect(IcfData); + + /* Release the library */ + FreeLibrary(IcfData->DllHandle); + } +} + +INT +WSPAPI +WSPStartup(IN WORD wVersionRequested, + OUT LPWSPDATA lpWSPData, + IN LPWSAPROTOCOL_INFOW lpProtocolInfo, + IN WSPUPCALLTABLE UpcallTable, + OUT LPWSPPROC_TABLE lpProcTable) +{ + CHAR DllPath[MAX_PATH]; + HINSTANCE DllHandle; + SOCK_ICF_DATA IcfData; + NT_PRODUCT_TYPE ProductType; + + /* Call the generic mswsock initialization routine */ + if (!MSWSOCK_Initialize()) return WSAENOBUFS; + + /* Check if we have TEB data yet */ + if (!NtCurrentTeb()->WinSockData) + { + /* We don't have thread data yet, initialize it */ + if (!MSAFD_SockThreadInitialize()) return WSAENOBUFS; + } + + /* Check the version number */ + if (wVersionRequested != MAKEWORD(2,2)) return WSAVERNOTSUPPORTED; + + /* Get ICF entrypoints */ + NewIcfConnection(&IcfData); + + /* Acquire the global lock */ + SockAcquireRwLockExclusive(&SocketGlobalLock); + + /* Check if we've never initialized before */ + if (!SockWspStartupCount) + { + /* Check if we have a context table by now */ + if (!SockContextTable) + { + /* Create it */ + if (WahCreateHandleContextTable(&SockContextTable) != NO_ERROR) + { + /* Fail */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + CloseIcfConnection(&IcfData); + return WSASYSCALLFAILURE; + } + } + + /* Bias our load count so we won't be killed with pending APCs */ + GetModuleFileNameA(SockModuleHandle, DllPath, MAX_PATH); + DllHandle = LoadLibraryA(DllPath); + if (!DllHandle) + { + /* Weird error, release and return */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + CloseIcfConnection(&IcfData); + return WSASYSCALLFAILURE; + } + + /* Initialize ICF */ + InitializeIcfConnection(&IcfData); + + /* Set our Upcall Table */ + SockUpcallTableHack = UpcallTable; + SockUpcallTable = &SockUpcallTableHack; + } + + /* Increase startup count */ + SockWspStartupCount++; + + /* Return our version */ + lpWSPData->wVersion = MAKEWORD(2, 2); + lpWSPData->wHighVersion = MAKEWORD(2, 2); + wcscpy(lpWSPData->szDescription, L"Microsoft Windows Sockets Version 2."); + + /* Return our Internal Table */ + *lpProcTable = SockProcTable; + + /* Check if this is a SAN GUID */ + if (IsEqualGUID(&lpProtocolInfo->ProviderId, &SockTcpProviderInfo.ProviderId)) + { + /* Get the product type and check if this is a server OS */ + RtlGetNtProductType(&ProductType); + if (ProductType != NtProductWinNt) + { + /* Get the SAN TCP/IP Catalog ID */ + /* FIXME: SockSanGetTcpipCatalogId(); */ + + /* Initialize SAN if it's enabled */ + if (SockSanEnabled) SockSanInitialize(); + } + } + + /* Release the lock and return */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + + /* Return to caller */ + return NO_ERROR; +} + +INT +WSPAPI +WSPCleanup(OUT LPINT lpErrno) +{ + /* FIXME: Clean up */ + *lpErrno = NO_ERROR; + return 0; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +PVOID pfnIcfOpenPort; +PICF_CONNECT pfnIcfConnect; +PVOID pfnIcfDisconnect; +HINSTANCE IcfDllHandle; + +WSPPROC_TABLE SockProcTable = +{ + &WSPAccept, + &WSPAddressToString, + &WSPAsyncSelect, + &WSPBind, + &WSPCancelBlockingCall, + &WSPCleanup, + &WSPCloseSocket, + &WSPConnect, + &WSPDuplicateSocket, + &WSPEnumNetworkEvents, + &WSPEventSelect, + &WSPGetOverlappedResult, + &WSPGetPeerName, + &WSPGetSockName, + &WSPGetSockOpt, + &WSPGetQOSByName, + &WSPIoctl, + &WSPJoinLeaf, + &WSPListen, + &WSPRecv, + &WSPRecvDisconnect, + &WSPRecvFrom, + &WSPSelect, + &WSPSend, + &WSPSendDisconnect, + &WSPSendTo, + &WSPSetSockOpt, + &WSPShutdown, + &WSPSocket, + &WSPStringToAddress +}; + +LONG SockWspStartupCount; +WSPUPCALLTABLE SockUpcallTableHack; +LPWSPUPCALLTABLE SockUpcallTable; + +/* FUNCTIONS *****************************************************************/ + +VOID +WSPAPI +NewIcfConnection(IN PSOCK_ICF_DATA IcfData) +{ + /* Load the ICF DLL */ + IcfData->DllHandle = LoadLibraryW(L"hhnetcfg.dll"); + if (IcfData->DllHandle) + { + /* Get the entrypoints */ + IcfData->IcfOpenDynamicFwPort = GetProcAddress(IcfData->DllHandle, + "IcfOpenDynamicFwPort"); + IcfData->IcfConnect = (PICF_CONNECT)GetProcAddress(IcfData->DllHandle, + "IcfConnect"); + IcfData->IcfDisconnect = GetProcAddress(IcfData->DllHandle, + "IcfDisconnect"); + + /* Now call IcfConnect */ + if (!IcfData->IcfConnect(IcfData)) + { + /* We failed, release the library */ + FreeLibrary(IcfData->DllHandle); + } + } +} + +VOID +WSPAPI +InitializeIcfConnection(IN PSOCK_ICF_DATA IcfData) +{ + /* Make sure we have an ICF Handle */ + if (IcfData->IcfHandle) + { + /* Save the function pointers and dll handle */ + IcfDllHandle = IcfData->DllHandle; + pfnIcfOpenPort = IcfData->IcfOpenDynamicFwPort; + pfnIcfConnect = IcfData->IcfConnect; + pfnIcfDisconnect = IcfData->IcfDisconnect; + } +} + +VOID +WSPAPI +CloseIcfConnection(IN PSOCK_ICF_DATA IcfData) +{ + /* Make sure we have an ICF Handle */ + if (IcfData->IcfHandle) + { + /* Call IcfDisconnect */ + IcfData->IcfConnect(IcfData); + + /* Release the library */ + FreeLibrary(IcfData->DllHandle); + } +} + +INT +WSPAPI +WSPStartup(IN WORD wVersionRequested, + OUT LPWSPDATA lpWSPData, + IN LPWSAPROTOCOL_INFOW lpProtocolInfo, + IN WSPUPCALLTABLE UpcallTable, + OUT LPWSPPROC_TABLE lpProcTable) +{ + CHAR DllPath[MAX_PATH]; + HINSTANCE DllHandle; + SOCK_ICF_DATA IcfData; + NT_PRODUCT_TYPE ProductType; + + /* Call the generic mswsock initialization routine */ + if (!MSWSOCK_Initialize()) return WSAENOBUFS; + + /* Check if we have TEB data yet */ + if (!NtCurrentTeb()->WinSockData) + { + /* We don't have thread data yet, initialize it */ + if (!MSAFD_SockThreadInitialize()) return WSAENOBUFS; + } + + /* Check the version number */ + if (wVersionRequested != MAKEWORD(2,2)) return WSAVERNOTSUPPORTED; + + /* Get ICF entrypoints */ + NewIcfConnection(&IcfData); + + /* Acquire the global lock */ + SockAcquireRwLockExclusive(&SocketGlobalLock); + + /* Check if we've never initialized before */ + if (!SockWspStartupCount) + { + /* Check if we have a context table by now */ + if (!SockContextTable) + { + /* Create it */ + if (WahCreateHandleContextTable(&SockContextTable) != NO_ERROR) + { + /* Fail */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + CloseIcfConnection(&IcfData); + return WSASYSCALLFAILURE; + } + } + + /* Bias our load count so we won't be killed with pending APCs */ + GetModuleFileNameA(SockModuleHandle, DllPath, MAX_PATH); + DllHandle = LoadLibraryA(DllPath); + if (!DllHandle) + { + /* Weird error, release and return */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + CloseIcfConnection(&IcfData); + return WSASYSCALLFAILURE; + } + + /* Initialize ICF */ + InitializeIcfConnection(&IcfData); + + /* Set our Upcall Table */ + SockUpcallTableHack = UpcallTable; + SockUpcallTable = &SockUpcallTableHack; + } + + /* Increase startup count */ + SockWspStartupCount++; + + /* Return our version */ + lpWSPData->wVersion = MAKEWORD(2, 2); + lpWSPData->wHighVersion = MAKEWORD(2, 2); + wcscpy(lpWSPData->szDescription, L"Microsoft Windows Sockets Version 2."); + + /* Return our Internal Table */ + *lpProcTable = SockProcTable; + + /* Check if this is a SAN GUID */ + if (IsEqualGUID(&lpProtocolInfo->ProviderId, &SockTcpProviderInfo.ProviderId)) + { + /* Get the product type and check if this is a server OS */ + RtlGetNtProductType(&ProductType); + if (ProductType != NtProductWinNt) + { + /* Get the SAN TCP/IP Catalog ID */ + /* FIXME: SockSanGetTcpipCatalogId(); */ + + /* Initialize SAN if it's enabled */ + if (SockSanEnabled) SockSanInitialize(); + } + } + + /* Release the lock and return */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + + /* Return to caller */ + return NO_ERROR; +} + +INT +WSPAPI +WSPCleanup(OUT LPINT lpErrno) +{ + /* FIXME: Clean up */ + *lpErrno = NO_ERROR; + return 0; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +PVOID pfnIcfOpenPort; +PICF_CONNECT pfnIcfConnect; +PVOID pfnIcfDisconnect; +HINSTANCE IcfDllHandle; + +WSPPROC_TABLE SockProcTable = +{ + &WSPAccept, + &WSPAddressToString, + &WSPAsyncSelect, + &WSPBind, + &WSPCancelBlockingCall, + &WSPCleanup, + &WSPCloseSocket, + &WSPConnect, + &WSPDuplicateSocket, + &WSPEnumNetworkEvents, + &WSPEventSelect, + &WSPGetOverlappedResult, + &WSPGetPeerName, + &WSPGetSockName, + &WSPGetSockOpt, + &WSPGetQOSByName, + &WSPIoctl, + &WSPJoinLeaf, + &WSPListen, + &WSPRecv, + &WSPRecvDisconnect, + &WSPRecvFrom, + &WSPSelect, + &WSPSend, + &WSPSendDisconnect, + &WSPSendTo, + &WSPSetSockOpt, + &WSPShutdown, + &WSPSocket, + &WSPStringToAddress +}; + +LONG SockWspStartupCount; +WSPUPCALLTABLE SockUpcallTableHack; +LPWSPUPCALLTABLE SockUpcallTable; + +/* FUNCTIONS *****************************************************************/ + +VOID +WSPAPI +NewIcfConnection(IN PSOCK_ICF_DATA IcfData) +{ + /* Load the ICF DLL */ + IcfData->DllHandle = LoadLibraryW(L"hhnetcfg.dll"); + if (IcfData->DllHandle) + { + /* Get the entrypoints */ + IcfData->IcfOpenDynamicFwPort = GetProcAddress(IcfData->DllHandle, + "IcfOpenDynamicFwPort"); + IcfData->IcfConnect = (PICF_CONNECT)GetProcAddress(IcfData->DllHandle, + "IcfConnect"); + IcfData->IcfDisconnect = GetProcAddress(IcfData->DllHandle, + "IcfDisconnect"); + + /* Now call IcfConnect */ + if (!IcfData->IcfConnect(IcfData)) + { + /* We failed, release the library */ + FreeLibrary(IcfData->DllHandle); + } + } +} + +VOID +WSPAPI +InitializeIcfConnection(IN PSOCK_ICF_DATA IcfData) +{ + /* Make sure we have an ICF Handle */ + if (IcfData->IcfHandle) + { + /* Save the function pointers and dll handle */ + IcfDllHandle = IcfData->DllHandle; + pfnIcfOpenPort = IcfData->IcfOpenDynamicFwPort; + pfnIcfConnect = IcfData->IcfConnect; + pfnIcfDisconnect = IcfData->IcfDisconnect; + } +} + +VOID +WSPAPI +CloseIcfConnection(IN PSOCK_ICF_DATA IcfData) +{ + /* Make sure we have an ICF Handle */ + if (IcfData->IcfHandle) + { + /* Call IcfDisconnect */ + IcfData->IcfConnect(IcfData); + + /* Release the library */ + FreeLibrary(IcfData->DllHandle); + } +} + +INT +WSPAPI +WSPStartup(IN WORD wVersionRequested, + OUT LPWSPDATA lpWSPData, + IN LPWSAPROTOCOL_INFOW lpProtocolInfo, + IN WSPUPCALLTABLE UpcallTable, + OUT LPWSPPROC_TABLE lpProcTable) +{ + CHAR DllPath[MAX_PATH]; + HINSTANCE DllHandle; + SOCK_ICF_DATA IcfData; + NT_PRODUCT_TYPE ProductType; + + /* Call the generic mswsock initialization routine */ + if (!MSWSOCK_Initialize()) return WSAENOBUFS; + + /* Check if we have TEB data yet */ + if (!NtCurrentTeb()->WinSockData) + { + /* We don't have thread data yet, initialize it */ + if (!MSAFD_SockThreadInitialize()) return WSAENOBUFS; + } + + /* Check the version number */ + if (wVersionRequested != MAKEWORD(2,2)) return WSAVERNOTSUPPORTED; + + /* Get ICF entrypoints */ + NewIcfConnection(&IcfData); + + /* Acquire the global lock */ + SockAcquireRwLockExclusive(&SocketGlobalLock); + + /* Check if we've never initialized before */ + if (!SockWspStartupCount) + { + /* Check if we have a context table by now */ + if (!SockContextTable) + { + /* Create it */ + if (WahCreateHandleContextTable(&SockContextTable) != NO_ERROR) + { + /* Fail */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + CloseIcfConnection(&IcfData); + return WSASYSCALLFAILURE; + } + } + + /* Bias our load count so we won't be killed with pending APCs */ + GetModuleFileNameA(SockModuleHandle, DllPath, MAX_PATH); + DllHandle = LoadLibraryA(DllPath); + if (!DllHandle) + { + /* Weird error, release and return */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + CloseIcfConnection(&IcfData); + return WSASYSCALLFAILURE; + } + + /* Initialize ICF */ + InitializeIcfConnection(&IcfData); + + /* Set our Upcall Table */ + SockUpcallTableHack = UpcallTable; + SockUpcallTable = &SockUpcallTableHack; + } + + /* Increase startup count */ + SockWspStartupCount++; + + /* Return our version */ + lpWSPData->wVersion = MAKEWORD(2, 2); + lpWSPData->wHighVersion = MAKEWORD(2, 2); + wcscpy(lpWSPData->szDescription, L"Microsoft Windows Sockets Version 2."); + + /* Return our Internal Table */ + *lpProcTable = SockProcTable; + + /* Check if this is a SAN GUID */ + if (IsEqualGUID(&lpProtocolInfo->ProviderId, &SockTcpProviderInfo.ProviderId)) + { + /* Get the product type and check if this is a server OS */ + RtlGetNtProductType(&ProductType); + if (ProductType != NtProductWinNt) + { + /* Get the SAN TCP/IP Catalog ID */ + /* FIXME: SockSanGetTcpipCatalogId(); */ + + /* Initialize SAN if it's enabled */ + if (SockSanEnabled) SockSanInitialize(); + } + } + + /* Release the lock and return */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + + /* Return to caller */ + return NO_ERROR; +} + +INT +WSPAPI +WSPCleanup(OUT LPINT lpErrno) +{ + /* FIXME: Clean up */ + *lpErrno = NO_ERROR; + return 0; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +PVOID pfnIcfOpenPort; +PICF_CONNECT pfnIcfConnect; +PVOID pfnIcfDisconnect; +HINSTANCE IcfDllHandle; + +WSPPROC_TABLE SockProcTable = +{ + &WSPAccept, + &WSPAddressToString, + &WSPAsyncSelect, + &WSPBind, + &WSPCancelBlockingCall, + &WSPCleanup, + &WSPCloseSocket, + &WSPConnect, + &WSPDuplicateSocket, + &WSPEnumNetworkEvents, + &WSPEventSelect, + &WSPGetOverlappedResult, + &WSPGetPeerName, + &WSPGetSockName, + &WSPGetSockOpt, + &WSPGetQOSByName, + &WSPIoctl, + &WSPJoinLeaf, + &WSPListen, + &WSPRecv, + &WSPRecvDisconnect, + &WSPRecvFrom, + &WSPSelect, + &WSPSend, + &WSPSendDisconnect, + &WSPSendTo, + &WSPSetSockOpt, + &WSPShutdown, + &WSPSocket, + &WSPStringToAddress +}; + +LONG SockWspStartupCount; +WSPUPCALLTABLE SockUpcallTableHack; +LPWSPUPCALLTABLE SockUpcallTable; + +/* FUNCTIONS *****************************************************************/ + +VOID +WSPAPI +NewIcfConnection(IN PSOCK_ICF_DATA IcfData) +{ + /* Load the ICF DLL */ + IcfData->DllHandle = LoadLibraryW(L"hhnetcfg.dll"); + if (IcfData->DllHandle) + { + /* Get the entrypoints */ + IcfData->IcfOpenDynamicFwPort = GetProcAddress(IcfData->DllHandle, + "IcfOpenDynamicFwPort"); + IcfData->IcfConnect = (PICF_CONNECT)GetProcAddress(IcfData->DllHandle, + "IcfConnect"); + IcfData->IcfDisconnect = GetProcAddress(IcfData->DllHandle, + "IcfDisconnect"); + + /* Now call IcfConnect */ + if (!IcfData->IcfConnect(IcfData)) + { + /* We failed, release the library */ + FreeLibrary(IcfData->DllHandle); + } + } +} + +VOID +WSPAPI +InitializeIcfConnection(IN PSOCK_ICF_DATA IcfData) +{ + /* Make sure we have an ICF Handle */ + if (IcfData->IcfHandle) + { + /* Save the function pointers and dll handle */ + IcfDllHandle = IcfData->DllHandle; + pfnIcfOpenPort = IcfData->IcfOpenDynamicFwPort; + pfnIcfConnect = IcfData->IcfConnect; + pfnIcfDisconnect = IcfData->IcfDisconnect; + } +} + +VOID +WSPAPI +CloseIcfConnection(IN PSOCK_ICF_DATA IcfData) +{ + /* Make sure we have an ICF Handle */ + if (IcfData->IcfHandle) + { + /* Call IcfDisconnect */ + IcfData->IcfConnect(IcfData); + + /* Release the library */ + FreeLibrary(IcfData->DllHandle); + } +} + +INT +WSPAPI +WSPStartup(IN WORD wVersionRequested, + OUT LPWSPDATA lpWSPData, + IN LPWSAPROTOCOL_INFOW lpProtocolInfo, + IN WSPUPCALLTABLE UpcallTable, + OUT LPWSPPROC_TABLE lpProcTable) +{ + CHAR DllPath[MAX_PATH]; + HINSTANCE DllHandle; + SOCK_ICF_DATA IcfData; + NT_PRODUCT_TYPE ProductType; + + /* Call the generic mswsock initialization routine */ + if (!MSWSOCK_Initialize()) return WSAENOBUFS; + + /* Check if we have TEB data yet */ + if (!NtCurrentTeb()->WinSockData) + { + /* We don't have thread data yet, initialize it */ + if (!MSAFD_SockThreadInitialize()) return WSAENOBUFS; + } + + /* Check the version number */ + if (wVersionRequested != MAKEWORD(2,2)) return WSAVERNOTSUPPORTED; + + /* Get ICF entrypoints */ + NewIcfConnection(&IcfData); + + /* Acquire the global lock */ + SockAcquireRwLockExclusive(&SocketGlobalLock); + + /* Check if we've never initialized before */ + if (!SockWspStartupCount) + { + /* Check if we have a context table by now */ + if (!SockContextTable) + { + /* Create it */ + if (WahCreateHandleContextTable(&SockContextTable) != NO_ERROR) + { + /* Fail */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + CloseIcfConnection(&IcfData); + return WSASYSCALLFAILURE; + } + } + + /* Bias our load count so we won't be killed with pending APCs */ + GetModuleFileNameA(SockModuleHandle, DllPath, MAX_PATH); + DllHandle = LoadLibraryA(DllPath); + if (!DllHandle) + { + /* Weird error, release and return */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + CloseIcfConnection(&IcfData); + return WSASYSCALLFAILURE; + } + + /* Initialize ICF */ + InitializeIcfConnection(&IcfData); + + /* Set our Upcall Table */ + SockUpcallTableHack = UpcallTable; + SockUpcallTable = &SockUpcallTableHack; + } + + /* Increase startup count */ + SockWspStartupCount++; + + /* Return our version */ + lpWSPData->wVersion = MAKEWORD(2, 2); + lpWSPData->wHighVersion = MAKEWORD(2, 2); + wcscpy(lpWSPData->szDescription, L"Microsoft Windows Sockets Version 2."); + + /* Return our Internal Table */ + *lpProcTable = SockProcTable; + + /* Check if this is a SAN GUID */ + if (IsEqualGUID(&lpProtocolInfo->ProviderId, &SockTcpProviderInfo.ProviderId)) + { + /* Get the product type and check if this is a server OS */ + RtlGetNtProductType(&ProductType); + if (ProductType != NtProductWinNt) + { + /* Get the SAN TCP/IP Catalog ID */ + /* FIXME: SockSanGetTcpipCatalogId(); */ + + /* Initialize SAN if it's enabled */ + if (SockSanEnabled) SockSanInitialize(); + } + } + + /* Release the lock and return */ + SockReleaseRwLockExclusive(&SocketGlobalLock); + + /* Return to caller */ + return NO_ERROR; +} + +INT +WSPAPI +WSPCleanup(OUT LPINT lpErrno) +{ + /* FIXME: Clean up */ + *lpErrno = NO_ERROR; + return 0; +} + diff --git a/dll/win32/mswsock/msafd/tpackets.c b/dll/win32/mswsock/msafd/tpackets.c new file mode 100644 index 00000000000..3e062e90d63 --- /dev/null +++ b/dll/win32/mswsock/msafd/tpackets.c @@ -0,0 +1,56 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + diff --git a/dll/win32/mswsock/msafd/tranfile.c b/dll/win32/mswsock/msafd/tranfile.c new file mode 100644 index 00000000000..3e062e90d63 --- /dev/null +++ b/dll/win32/mswsock/msafd/tranfile.c @@ -0,0 +1,56 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + diff --git a/dll/win32/mswsock/msafd/wspmisc.c b/dll/win32/mswsock/msafd/wspmisc.c new file mode 100644 index 00000000000..0acd28256eb --- /dev/null +++ b/dll/win32/mswsock/msafd/wspmisc.c @@ -0,0 +1,352 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +BOOL +WSPAPI +WSPGetQOSByName(IN SOCKET Handle, + IN OUT LPWSABUF lpQOSName, + OUT LPQOS lpQOS, + OUT LPINT lpErrno) +{ + PWINSOCK_TEB_DATA ThreadData; + INT ErrorCode; + DWORD BytesReturned; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Call WSPIoctl for the job */ + WSPIoctl(Handle, + SIO_GET_QOS, + NULL, + 0, + lpQOS, + sizeof(QOS), + &BytesReturned, + NULL, + NULL, + NULL, + &ErrorCode); + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return FALSE; + } + + /* Success */ + return TRUE; +} + +INT +WSPAPI +WSPCancelBlockingCall(OUT LPINT lpErrno) +{ + return 0; +} + +BOOL +WSPAPI +WSPGetOverlappedResult(IN SOCKET s, + IN LPWSAOVERLAPPED lpOverlapped, + OUT LPDWORD lpcbTransfer, + IN BOOL fWait, + OUT LPDWORD lpdwFlags, + OUT LPINT lpErrno) +{ + return FALSE; +} + +INT +WSPAPI +WSPDuplicateSocket(IN SOCKET s, + IN DWORD dwProcessId, + OUT LPWSAPROTOCOL_INFOW lpProtocolInfo, + OUT LPINT lpErrno) +{ + return 0; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +BOOL +WSPAPI +WSPGetQOSByName(IN SOCKET Handle, + IN OUT LPWSABUF lpQOSName, + OUT LPQOS lpQOS, + OUT LPINT lpErrno) +{ + PWINSOCK_TEB_DATA ThreadData; + INT ErrorCode; + DWORD BytesReturned; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Call WSPIoctl for the job */ + WSPIoctl(Handle, + SIO_GET_QOS, + NULL, + 0, + lpQOS, + sizeof(QOS), + &BytesReturned, + NULL, + NULL, + NULL, + &ErrorCode); + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return FALSE; + } + + /* Success */ + return TRUE; +} + +INT +WSPAPI +WSPCancelBlockingCall(OUT LPINT lpErrno) +{ + return 0; +} + +BOOL +WSPAPI +WSPGetOverlappedResult(IN SOCKET s, + IN LPWSAOVERLAPPED lpOverlapped, + OUT LPDWORD lpcbTransfer, + IN BOOL fWait, + OUT LPDWORD lpdwFlags, + OUT LPINT lpErrno) +{ + return FALSE; +} + +INT +WSPAPI +WSPDuplicateSocket(IN SOCKET s, + IN DWORD dwProcessId, + OUT LPWSAPROTOCOL_INFOW lpProtocolInfo, + OUT LPINT lpErrno) +{ + return 0; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +BOOL +WSPAPI +WSPGetQOSByName(IN SOCKET Handle, + IN OUT LPWSABUF lpQOSName, + OUT LPQOS lpQOS, + OUT LPINT lpErrno) +{ + PWINSOCK_TEB_DATA ThreadData; + INT ErrorCode; + DWORD BytesReturned; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Call WSPIoctl for the job */ + WSPIoctl(Handle, + SIO_GET_QOS, + NULL, + 0, + lpQOS, + sizeof(QOS), + &BytesReturned, + NULL, + NULL, + NULL, + &ErrorCode); + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return FALSE; + } + + /* Success */ + return TRUE; +} + +INT +WSPAPI +WSPCancelBlockingCall(OUT LPINT lpErrno) +{ + return 0; +} + +BOOL +WSPAPI +WSPGetOverlappedResult(IN SOCKET s, + IN LPWSAOVERLAPPED lpOverlapped, + OUT LPDWORD lpcbTransfer, + IN BOOL fWait, + OUT LPDWORD lpdwFlags, + OUT LPINT lpErrno) +{ + return FALSE; +} + +INT +WSPAPI +WSPDuplicateSocket(IN SOCKET s, + IN DWORD dwProcessId, + OUT LPWSAPROTOCOL_INFOW lpProtocolInfo, + OUT LPINT lpErrno) +{ + return 0; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +BOOL +WSPAPI +WSPGetQOSByName(IN SOCKET Handle, + IN OUT LPWSABUF lpQOSName, + OUT LPQOS lpQOS, + OUT LPINT lpErrno) +{ + PWINSOCK_TEB_DATA ThreadData; + INT ErrorCode; + DWORD BytesReturned; + + /* Enter prolog */ + ErrorCode = SockEnterApiFast(&ThreadData); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return SOCKET_ERROR; + } + + /* Call WSPIoctl for the job */ + WSPIoctl(Handle, + SIO_GET_QOS, + NULL, + 0, + lpQOS, + sizeof(QOS), + &BytesReturned, + NULL, + NULL, + NULL, + &ErrorCode); + + /* Check for error */ + if (ErrorCode != NO_ERROR) + { + /* Fail */ + *lpErrno = ErrorCode; + return FALSE; + } + + /* Success */ + return TRUE; +} + +INT +WSPAPI +WSPCancelBlockingCall(OUT LPINT lpErrno) +{ + return 0; +} + +BOOL +WSPAPI +WSPGetOverlappedResult(IN SOCKET s, + IN LPWSAOVERLAPPED lpOverlapped, + OUT LPDWORD lpcbTransfer, + IN BOOL fWait, + OUT LPDWORD lpdwFlags, + OUT LPINT lpErrno) +{ + return FALSE; +} + +INT +WSPAPI +WSPDuplicateSocket(IN SOCKET s, + IN DWORD dwProcessId, + OUT LPWSAPROTOCOL_INFOW lpProtocolInfo, + OUT LPINT lpErrno) +{ + return 0; +} + diff --git a/dll/win32/mswsock/mswsock.rbuild b/dll/win32/mswsock/mswsock.rbuild index b5ee00af8a1..473eac1689e 100644 --- a/dll/win32/mswsock/mswsock.rbuild +++ b/dll/win32/mswsock/mswsock.rbuild @@ -1,9 +1,100 @@ - - - kernel32 + + include/reactos/winsock + dnslib/inc + include/reactos/drivers + ntdll + advapi32 + user32 + ws2help ws2_32 - extensions.c - stubs.c + dnsapi + + init.c + msext.c + nspgaddr.c + nspsvc.c + nsptcpip.c + nsputil.c + proc.c + recvex.c + setup.c + stubs.c + + + addr.c + debug.c + dnsaddr.c + dnsutil.c + flatbuf.c + hostent.c + ip6.c + memory.c + name.c + print.c + record.c + rrprint.c + sablob.c + straddr.c + string.c + table.c + utf8.c + + + accept.c + addrconv.c + afdsan.c + async.c + bind.c + connect.c + eventsel.c + getname.c + helper.c + listen.c + nspeprot.c + proc.c + recv.c + sanaccpt.c + sanconn.c + sanflow.c + sanlistn.c + sanprov.c + sanrdma.c + sanrecv.c + sansend.c + sanshutd.c + sansock.c + santf.c + sanutil.c + select.c + send.c + shutdown.c + sockerr.c + socket.c + sockopt.c + spi.c + tpackets.c + tranfile.c + wspmisc.c + + + context.c + getserv.c + init.c + logit.c + lookup.c + nbt.c + nsp.c + oldutil.c + proc.c + r_comp.c + util.c + + + lpc.c + nsp.c + service.c + update.c + mswsock.rc diff --git a/dll/win32/mswsock/mswsock/init.c b/dll/win32/mswsock/mswsock/init.c new file mode 100644 index 00000000000..2a8bc65e9e7 --- /dev/null +++ b/dll/win32/mswsock/mswsock/init.c @@ -0,0 +1,816 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +BOOL SockProcessTerminating; +LONG SockProcessPendingAPCCount; +HINSTANCE SockModuleHandle; + +/* FUNCTIONS *****************************************************************/ + +BOOL +WSPAPI +MSWSOCK_Initialize(VOID) +{ + SYSTEM_INFO SystemInfo; + + /* If our heap is already initialized, we can skip everything */ + if (SockAllocateHeapRoutine) return TRUE; + + /* Make sure nobody thinks we're terminating */ + SockProcessTerminating = FALSE; + + /* Get the system information */ + GetSystemInfo(&SystemInfo); + + /* Check if this is an MP machine */ + if (SystemInfo.dwNumberOfProcessors > 1) + { + /* Use our own heap on MP, to reduce locks */ + SockAllocateHeapRoutine = SockInitializeHeap; + SockPrivateHeap = NULL; + } + else + { + /* Use process heap */ + SockAllocateHeapRoutine = RtlAllocateHeap; + SockPrivateHeap = RtlGetProcessHeap(); + } + + /* Initialize WSM data */ + gWSM_NSPStartupRef = -1; + gWSM_NSPCallRef = 0; + + /* Initialize the helper listhead */ + InitializeListHead(&SockHelperDllListHead); + + /* Initialize the global lock */ + SockInitializeRwLockAndSpinCount(&SocketGlobalLock, 1000); + + /* Initialize the socket lock */ + InitializeCriticalSection(&MSWSOCK_SocketLock); + + /* Initialize RnR locks and other RnR data */ + Rnr_ProcessInit(); + + /* Return success */ + return TRUE; +} + +BOOL +APIENTRY +DllMain(HANDLE hModule, + DWORD dwReason, + LPVOID lpReserved) +{ + OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo; + PWINSOCK_TEB_DATA ThreadData; + + /* Check what's going on */ + switch (dwReason) + { + /* Process attaching */ + case DLL_PROCESS_ATTACH: + + /* Save module handles */ + SockModuleHandle = hModule; + NlsMsgSourcemModuleHandle = hModule; + + /* Initialize us */ + MSWSOCK_Initialize(); + break; + + /* Detaching */ + case DLL_PROCESS_DETACH: + + /* Did we initialize yet? */ + if (!SockAllocateHeapRoutine) break; + + /* Fail all future calls */ + SockProcessTerminating = TRUE; + + /* Is this a FreeLibrary? */ + if (!lpReserved) + { + /* Cleanup RNR */ + Rnr_ProcessCleanup(); + + /* Delete the socket lock */ + DeleteCriticalSection(&MSWSOCK_SocketLock); + + /* Check if we have an Async Queue Port */ + if (SockAsyncQueuePort) + { + /* Unprotect the handle */ + HandleInfo.ProtectFromClose = FALSE; + HandleInfo.Inherit = FALSE; + NtSetInformationObject(SockAsyncQueuePort, + ObjectHandleFlagInformation, + &HandleInfo, + sizeof(HandleInfo)); + + /* Close it, and clear the port */ + NtClose(SockAsyncQueuePort); + SockAsyncQueuePort = NULL; + } + + /* Check if we have a context table */ + if (SockContextTable) + { + /* Destroy it */ + WahDestroyHandleContextTable(SockContextTable); + SockContextTable = NULL; + } + + /* Delete the global lock as well */ + SockDeleteRwLock(&SocketGlobalLock); + + /* Check if we have a buffer keytable */ + if (SockBufferKeyTable) + { + /* Free it */ + VirtualFree(SockBufferKeyTable, 0, MEM_RELEASE); + } + } + + /* Check if we have to a SAN cleanup event */ + if (SockSanCleanUpCompleteEvent) + { + /* Close the event handle */ + CloseHandle(SockSanCleanUpCompleteEvent); + } + + /* Thread detaching */ + case DLL_THREAD_DETACH: + + /* Set the context to NULL for thread detach */ + if (dwReason == DLL_THREAD_DETACH) lpReserved = NULL; + + /* Check if this is a normal thread detach */ + if (!lpReserved) + { + /* Do RnR Thread cleanup */ + Rnr_ThreadCleanup(); + + /* Get thread data */ + ThreadData = NtCurrentTeb()->WinSockData; + if (ThreadData) + { + /* Check if any APCs are pending */ + if (ThreadData->PendingAPCs) + { + /* Save the value */ + InterlockedExchangeAdd(&SockProcessPendingAPCCount, + -(ThreadData->PendingAPCs)); + + /* Close the evnet handle */ + NtClose(ThreadData->EventHandle); + + /* Free the thread data and set it to null */ + RtlFreeHeap(GetProcessHeap(), 0, (PVOID)ThreadData); + NtCurrentTeb()->WinSockData = NULL; + } + } + } + + /* Check if this is a process detach fallthrough */ + if (dwReason == DLL_PROCESS_DETACH && !lpReserved) + { + /* Check if we're using a private heap */ + if (SockPrivateHeap != RtlGetProcessHeap()) + { + /* Destroy it */ + RtlDestroyHeap(SockPrivateHeap); + } + SockAllocateHeapRoutine = NULL; + } + break; + + case DLL_THREAD_ATTACH: + break; + } + + /* Return */ + return TRUE; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +BOOL SockProcessTerminating; +LONG SockProcessPendingAPCCount; +HINSTANCE SockModuleHandle; + +/* FUNCTIONS *****************************************************************/ + +BOOL +WSPAPI +MSWSOCK_Initialize(VOID) +{ + SYSTEM_INFO SystemInfo; + + /* If our heap is already initialized, we can skip everything */ + if (SockAllocateHeapRoutine) return TRUE; + + /* Make sure nobody thinks we're terminating */ + SockProcessTerminating = FALSE; + + /* Get the system information */ + GetSystemInfo(&SystemInfo); + + /* Check if this is an MP machine */ + if (SystemInfo.dwNumberOfProcessors > 1) + { + /* Use our own heap on MP, to reduce locks */ + SockAllocateHeapRoutine = SockInitializeHeap; + SockPrivateHeap = NULL; + } + else + { + /* Use process heap */ + SockAllocateHeapRoutine = RtlAllocateHeap; + SockPrivateHeap = RtlGetProcessHeap(); + } + + /* Initialize WSM data */ + gWSM_NSPStartupRef = -1; + gWSM_NSPCallRef = 0; + + /* Initialize the helper listhead */ + InitializeListHead(&SockHelperDllListHead); + + /* Initialize the global lock */ + SockInitializeRwLockAndSpinCount(&SocketGlobalLock, 1000); + + /* Initialize the socket lock */ + InitializeCriticalSection(&MSWSOCK_SocketLock); + + /* Initialize RnR locks and other RnR data */ + Rnr_ProcessInit(); + + /* Return success */ + return TRUE; +} + +BOOL +APIENTRY +DllMain(HANDLE hModule, + DWORD dwReason, + LPVOID lpReserved) +{ + OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo; + PWINSOCK_TEB_DATA ThreadData; + + /* Check what's going on */ + switch (dwReason) + { + /* Process attaching */ + case DLL_PROCESS_ATTACH: + + /* Save module handles */ + SockModuleHandle = hModule; + NlsMsgSourcemModuleHandle = hModule; + + /* Initialize us */ + MSWSOCK_Initialize(); + break; + + /* Detaching */ + case DLL_PROCESS_DETACH: + + /* Did we initialize yet? */ + if (!SockAllocateHeapRoutine) break; + + /* Fail all future calls */ + SockProcessTerminating = TRUE; + + /* Is this a FreeLibrary? */ + if (!lpReserved) + { + /* Cleanup RNR */ + Rnr_ProcessCleanup(); + + /* Delete the socket lock */ + DeleteCriticalSection(&MSWSOCK_SocketLock); + + /* Check if we have an Async Queue Port */ + if (SockAsyncQueuePort) + { + /* Unprotect the handle */ + HandleInfo.ProtectFromClose = FALSE; + HandleInfo.Inherit = FALSE; + NtSetInformationObject(SockAsyncQueuePort, + ObjectHandleFlagInformation, + &HandleInfo, + sizeof(HandleInfo)); + + /* Close it, and clear the port */ + NtClose(SockAsyncQueuePort); + SockAsyncQueuePort = NULL; + } + + /* Check if we have a context table */ + if (SockContextTable) + { + /* Destroy it */ + WahDestroyHandleContextTable(SockContextTable); + SockContextTable = NULL; + } + + /* Delete the global lock as well */ + SockDeleteRwLock(&SocketGlobalLock); + + /* Check if we have a buffer keytable */ + if (SockBufferKeyTable) + { + /* Free it */ + VirtualFree(SockBufferKeyTable, 0, MEM_RELEASE); + } + } + + /* Check if we have to a SAN cleanup event */ + if (SockSanCleanUpCompleteEvent) + { + /* Close the event handle */ + CloseHandle(SockSanCleanUpCompleteEvent); + } + + /* Thread detaching */ + case DLL_THREAD_DETACH: + + /* Set the context to NULL for thread detach */ + if (dwReason == DLL_THREAD_DETACH) lpReserved = NULL; + + /* Check if this is a normal thread detach */ + if (!lpReserved) + { + /* Do RnR Thread cleanup */ + Rnr_ThreadCleanup(); + + /* Get thread data */ + ThreadData = NtCurrentTeb()->WinSockData; + if (ThreadData) + { + /* Check if any APCs are pending */ + if (ThreadData->PendingAPCs) + { + /* Save the value */ + InterlockedExchangeAdd(&SockProcessPendingAPCCount, + -(ThreadData->PendingAPCs)); + + /* Close the evnet handle */ + NtClose(ThreadData->EventHandle); + + /* Free the thread data and set it to null */ + RtlFreeHeap(GetProcessHeap(), 0, (PVOID)ThreadData); + NtCurrentTeb()->WinSockData = NULL; + } + } + } + + /* Check if this is a process detach fallthrough */ + if (dwReason == DLL_PROCESS_DETACH && !lpReserved) + { + /* Check if we're using a private heap */ + if (SockPrivateHeap != RtlGetProcessHeap()) + { + /* Destroy it */ + RtlDestroyHeap(SockPrivateHeap); + } + SockAllocateHeapRoutine = NULL; + } + break; + + case DLL_THREAD_ATTACH: + break; + } + + /* Return */ + return TRUE; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +BOOL SockProcessTerminating; +LONG SockProcessPendingAPCCount; +HINSTANCE SockModuleHandle; + +/* FUNCTIONS *****************************************************************/ + +BOOL +WSPAPI +MSWSOCK_Initialize(VOID) +{ + SYSTEM_INFO SystemInfo; + + /* If our heap is already initialized, we can skip everything */ + if (SockAllocateHeapRoutine) return TRUE; + + /* Make sure nobody thinks we're terminating */ + SockProcessTerminating = FALSE; + + /* Get the system information */ + GetSystemInfo(&SystemInfo); + + /* Check if this is an MP machine */ + if (SystemInfo.dwNumberOfProcessors > 1) + { + /* Use our own heap on MP, to reduce locks */ + SockAllocateHeapRoutine = SockInitializeHeap; + SockPrivateHeap = NULL; + } + else + { + /* Use process heap */ + SockAllocateHeapRoutine = RtlAllocateHeap; + SockPrivateHeap = RtlGetProcessHeap(); + } + + /* Initialize WSM data */ + gWSM_NSPStartupRef = -1; + gWSM_NSPCallRef = 0; + + /* Initialize the helper listhead */ + InitializeListHead(&SockHelperDllListHead); + + /* Initialize the global lock */ + SockInitializeRwLockAndSpinCount(&SocketGlobalLock, 1000); + + /* Initialize the socket lock */ + InitializeCriticalSection(&MSWSOCK_SocketLock); + + /* Initialize RnR locks and other RnR data */ + Rnr_ProcessInit(); + + /* Return success */ + return TRUE; +} + +BOOL +APIENTRY +DllMain(HANDLE hModule, + DWORD dwReason, + LPVOID lpReserved) +{ + OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo; + PWINSOCK_TEB_DATA ThreadData; + + /* Check what's going on */ + switch (dwReason) + { + /* Process attaching */ + case DLL_PROCESS_ATTACH: + + /* Save module handles */ + SockModuleHandle = hModule; + NlsMsgSourcemModuleHandle = hModule; + + /* Initialize us */ + MSWSOCK_Initialize(); + break; + + /* Detaching */ + case DLL_PROCESS_DETACH: + + /* Did we initialize yet? */ + if (!SockAllocateHeapRoutine) break; + + /* Fail all future calls */ + SockProcessTerminating = TRUE; + + /* Is this a FreeLibrary? */ + if (!lpReserved) + { + /* Cleanup RNR */ + Rnr_ProcessCleanup(); + + /* Delete the socket lock */ + DeleteCriticalSection(&MSWSOCK_SocketLock); + + /* Check if we have an Async Queue Port */ + if (SockAsyncQueuePort) + { + /* Unprotect the handle */ + HandleInfo.ProtectFromClose = FALSE; + HandleInfo.Inherit = FALSE; + NtSetInformationObject(SockAsyncQueuePort, + ObjectHandleFlagInformation, + &HandleInfo, + sizeof(HandleInfo)); + + /* Close it, and clear the port */ + NtClose(SockAsyncQueuePort); + SockAsyncQueuePort = NULL; + } + + /* Check if we have a context table */ + if (SockContextTable) + { + /* Destroy it */ + WahDestroyHandleContextTable(SockContextTable); + SockContextTable = NULL; + } + + /* Delete the global lock as well */ + SockDeleteRwLock(&SocketGlobalLock); + + /* Check if we have a buffer keytable */ + if (SockBufferKeyTable) + { + /* Free it */ + VirtualFree(SockBufferKeyTable, 0, MEM_RELEASE); + } + } + + /* Check if we have to a SAN cleanup event */ + if (SockSanCleanUpCompleteEvent) + { + /* Close the event handle */ + CloseHandle(SockSanCleanUpCompleteEvent); + } + + /* Thread detaching */ + case DLL_THREAD_DETACH: + + /* Set the context to NULL for thread detach */ + if (dwReason == DLL_THREAD_DETACH) lpReserved = NULL; + + /* Check if this is a normal thread detach */ + if (!lpReserved) + { + /* Do RnR Thread cleanup */ + Rnr_ThreadCleanup(); + + /* Get thread data */ + ThreadData = NtCurrentTeb()->WinSockData; + if (ThreadData) + { + /* Check if any APCs are pending */ + if (ThreadData->PendingAPCs) + { + /* Save the value */ + InterlockedExchangeAdd(&SockProcessPendingAPCCount, + -(ThreadData->PendingAPCs)); + + /* Close the evnet handle */ + NtClose(ThreadData->EventHandle); + + /* Free the thread data and set it to null */ + RtlFreeHeap(GetProcessHeap(), 0, (PVOID)ThreadData); + NtCurrentTeb()->WinSockData = NULL; + } + } + } + + /* Check if this is a process detach fallthrough */ + if (dwReason == DLL_PROCESS_DETACH && !lpReserved) + { + /* Check if we're using a private heap */ + if (SockPrivateHeap != RtlGetProcessHeap()) + { + /* Destroy it */ + RtlDestroyHeap(SockPrivateHeap); + } + SockAllocateHeapRoutine = NULL; + } + break; + + case DLL_THREAD_ATTACH: + break; + } + + /* Return */ + return TRUE; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +BOOL SockProcessTerminating; +LONG SockProcessPendingAPCCount; +HINSTANCE SockModuleHandle; + +/* FUNCTIONS *****************************************************************/ + +BOOL +WSPAPI +MSWSOCK_Initialize(VOID) +{ + SYSTEM_INFO SystemInfo; + + /* If our heap is already initialized, we can skip everything */ + if (SockAllocateHeapRoutine) return TRUE; + + /* Make sure nobody thinks we're terminating */ + SockProcessTerminating = FALSE; + + /* Get the system information */ + GetSystemInfo(&SystemInfo); + + /* Check if this is an MP machine */ + if (SystemInfo.dwNumberOfProcessors > 1) + { + /* Use our own heap on MP, to reduce locks */ + SockAllocateHeapRoutine = SockInitializeHeap; + SockPrivateHeap = NULL; + } + else + { + /* Use process heap */ + SockAllocateHeapRoutine = RtlAllocateHeap; + SockPrivateHeap = RtlGetProcessHeap(); + } + + /* Initialize WSM data */ + gWSM_NSPStartupRef = -1; + gWSM_NSPCallRef = 0; + + /* Initialize the helper listhead */ + InitializeListHead(&SockHelperDllListHead); + + /* Initialize the global lock */ + SockInitializeRwLockAndSpinCount(&SocketGlobalLock, 1000); + + /* Initialize the socket lock */ + InitializeCriticalSection(&MSWSOCK_SocketLock); + + /* Initialize RnR locks and other RnR data */ + Rnr_ProcessInit(); + + /* Return success */ + return TRUE; +} + +BOOL +APIENTRY +DllMain(HANDLE hModule, + DWORD dwReason, + LPVOID lpReserved) +{ + OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo; + PWINSOCK_TEB_DATA ThreadData; + + /* Check what's going on */ + switch (dwReason) + { + /* Process attaching */ + case DLL_PROCESS_ATTACH: + + /* Save module handles */ + SockModuleHandle = hModule; + NlsMsgSourcemModuleHandle = hModule; + + /* Initialize us */ + MSWSOCK_Initialize(); + break; + + /* Detaching */ + case DLL_PROCESS_DETACH: + + /* Did we initialize yet? */ + if (!SockAllocateHeapRoutine) break; + + /* Fail all future calls */ + SockProcessTerminating = TRUE; + + /* Is this a FreeLibrary? */ + if (!lpReserved) + { + /* Cleanup RNR */ + Rnr_ProcessCleanup(); + + /* Delete the socket lock */ + DeleteCriticalSection(&MSWSOCK_SocketLock); + + /* Check if we have an Async Queue Port */ + if (SockAsyncQueuePort) + { + /* Unprotect the handle */ + HandleInfo.ProtectFromClose = FALSE; + HandleInfo.Inherit = FALSE; + NtSetInformationObject(SockAsyncQueuePort, + ObjectHandleFlagInformation, + &HandleInfo, + sizeof(HandleInfo)); + + /* Close it, and clear the port */ + NtClose(SockAsyncQueuePort); + SockAsyncQueuePort = NULL; + } + + /* Check if we have a context table */ + if (SockContextTable) + { + /* Destroy it */ + WahDestroyHandleContextTable(SockContextTable); + SockContextTable = NULL; + } + + /* Delete the global lock as well */ + SockDeleteRwLock(&SocketGlobalLock); + + /* Check if we have a buffer keytable */ + if (SockBufferKeyTable) + { + /* Free it */ + VirtualFree(SockBufferKeyTable, 0, MEM_RELEASE); + } + } + + /* Check if we have to a SAN cleanup event */ + if (SockSanCleanUpCompleteEvent) + { + /* Close the event handle */ + CloseHandle(SockSanCleanUpCompleteEvent); + } + + /* Thread detaching */ + case DLL_THREAD_DETACH: + + /* Set the context to NULL for thread detach */ + if (dwReason == DLL_THREAD_DETACH) lpReserved = NULL; + + /* Check if this is a normal thread detach */ + if (!lpReserved) + { + /* Do RnR Thread cleanup */ + Rnr_ThreadCleanup(); + + /* Get thread data */ + ThreadData = NtCurrentTeb()->WinSockData; + if (ThreadData) + { + /* Check if any APCs are pending */ + if (ThreadData->PendingAPCs) + { + /* Save the value */ + InterlockedExchangeAdd(&SockProcessPendingAPCCount, + -(ThreadData->PendingAPCs)); + + /* Close the evnet handle */ + NtClose(ThreadData->EventHandle); + + /* Free the thread data and set it to null */ + RtlFreeHeap(GetProcessHeap(), 0, (PVOID)ThreadData); + NtCurrentTeb()->WinSockData = NULL; + } + } + } + + /* Check if this is a process detach fallthrough */ + if (dwReason == DLL_PROCESS_DETACH && !lpReserved) + { + /* Check if we're using a private heap */ + if (SockPrivateHeap != RtlGetProcessHeap()) + { + /* Destroy it */ + RtlDestroyHeap(SockPrivateHeap); + } + SockAllocateHeapRoutine = NULL; + } + break; + + case DLL_THREAD_ATTACH: + break; + } + + /* Return */ + return TRUE; +} + diff --git a/dll/win32/mswsock/mswsock/msext.c b/dll/win32/mswsock/mswsock/msext.c new file mode 100644 index 00000000000..a67b63389a3 --- /dev/null +++ b/dll/win32/mswsock/mswsock/msext.c @@ -0,0 +1,208 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +PVOID SockBufferKeyTable; +ULONG SockBufferKeyTableSize; + +/* FUNCTIONS *****************************************************************/ +BOOL +WINAPI +TransmitFile(SOCKET Socket, + HANDLE File, + DWORD NumberOfBytesToWrite, + DWORD NumberOfBytesPerSend, + LPOVERLAPPED Overlapped, + LPTRANSMIT_FILE_BUFFERS TransmitBuffers, + DWORD Flags) +{ + static GUID TransmitFileGUID = WSAID_TRANSMITFILE; + LPFN_TRANSMITFILE pfnTransmitFile; + DWORD cbBytesReturned; + + if (WSAIoctl(Socket, + SIO_GET_EXTENSION_FUNCTION_POINTER, + &TransmitFileGUID, + sizeof(TransmitFileGUID), + &pfnTransmitFile, + sizeof(pfnTransmitFile), + &cbBytesReturned, + NULL, + NULL) == SOCKET_ERROR) + { + return FALSE; + } + + return pfnTransmitFile(Socket, + File, + NumberOfBytesToWrite, + NumberOfBytesPerSend, + Overlapped, + TransmitBuffers, + Flags); +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +PVOID SockBufferKeyTable; +ULONG SockBufferKeyTableSize; + +/* FUNCTIONS *****************************************************************/ +BOOL +WINAPI +TransmitFile(SOCKET Socket, + HANDLE File, + DWORD NumberOfBytesToWrite, + DWORD NumberOfBytesPerSend, + LPOVERLAPPED Overlapped, + LPTRANSMIT_FILE_BUFFERS TransmitBuffers, + DWORD Flags) +{ + static GUID TransmitFileGUID = WSAID_TRANSMITFILE; + LPFN_TRANSMITFILE pfnTransmitFile; + DWORD cbBytesReturned; + + if (WSAIoctl(Socket, + SIO_GET_EXTENSION_FUNCTION_POINTER, + &TransmitFileGUID, + sizeof(TransmitFileGUID), + &pfnTransmitFile, + sizeof(pfnTransmitFile), + &cbBytesReturned, + NULL, + NULL) == SOCKET_ERROR) + { + return FALSE; + } + + return pfnTransmitFile(Socket, + File, + NumberOfBytesToWrite, + NumberOfBytesPerSend, + Overlapped, + TransmitBuffers, + Flags); +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +PVOID SockBufferKeyTable; +ULONG SockBufferKeyTableSize; + +/* FUNCTIONS *****************************************************************/ +BOOL +WINAPI +TransmitFile(SOCKET Socket, + HANDLE File, + DWORD NumberOfBytesToWrite, + DWORD NumberOfBytesPerSend, + LPOVERLAPPED Overlapped, + LPTRANSMIT_FILE_BUFFERS TransmitBuffers, + DWORD Flags) +{ + static GUID TransmitFileGUID = WSAID_TRANSMITFILE; + LPFN_TRANSMITFILE pfnTransmitFile; + DWORD cbBytesReturned; + + if (WSAIoctl(Socket, + SIO_GET_EXTENSION_FUNCTION_POINTER, + &TransmitFileGUID, + sizeof(TransmitFileGUID), + &pfnTransmitFile, + sizeof(pfnTransmitFile), + &cbBytesReturned, + NULL, + NULL) == SOCKET_ERROR) + { + return FALSE; + } + + return pfnTransmitFile(Socket, + File, + NumberOfBytesToWrite, + NumberOfBytesPerSend, + Overlapped, + TransmitBuffers, + Flags); +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +PVOID SockBufferKeyTable; +ULONG SockBufferKeyTableSize; + +/* FUNCTIONS *****************************************************************/ +BOOL +WINAPI +TransmitFile(SOCKET Socket, + HANDLE File, + DWORD NumberOfBytesToWrite, + DWORD NumberOfBytesPerSend, + LPOVERLAPPED Overlapped, + LPTRANSMIT_FILE_BUFFERS TransmitBuffers, + DWORD Flags) +{ + static GUID TransmitFileGUID = WSAID_TRANSMITFILE; + LPFN_TRANSMITFILE pfnTransmitFile; + DWORD cbBytesReturned; + + if (WSAIoctl(Socket, + SIO_GET_EXTENSION_FUNCTION_POINTER, + &TransmitFileGUID, + sizeof(TransmitFileGUID), + &pfnTransmitFile, + sizeof(pfnTransmitFile), + &cbBytesReturned, + NULL, + NULL) == SOCKET_ERROR) + { + return FALSE; + } + + return pfnTransmitFile(Socket, + File, + NumberOfBytesToWrite, + NumberOfBytesPerSend, + Overlapped, + TransmitBuffers, + Flags); +} + diff --git a/dll/win32/mswsock/mswsock/nspgaddr.c b/dll/win32/mswsock/mswsock/nspgaddr.c new file mode 100644 index 00000000000..3e062e90d63 --- /dev/null +++ b/dll/win32/mswsock/mswsock/nspgaddr.c @@ -0,0 +1,56 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + diff --git a/dll/win32/mswsock/mswsock/nspmisc.c b/dll/win32/mswsock/mswsock/nspmisc.c new file mode 100644 index 00000000000..3e062e90d63 --- /dev/null +++ b/dll/win32/mswsock/mswsock/nspmisc.c @@ -0,0 +1,56 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + diff --git a/dll/win32/mswsock/mswsock/nspsvc.c b/dll/win32/mswsock/mswsock/nspsvc.c new file mode 100644 index 00000000000..3e062e90d63 --- /dev/null +++ b/dll/win32/mswsock/mswsock/nspsvc.c @@ -0,0 +1,56 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + diff --git a/dll/win32/mswsock/mswsock/nsptcpip.c b/dll/win32/mswsock/mswsock/nsptcpip.c new file mode 100644 index 00000000000..3e062e90d63 --- /dev/null +++ b/dll/win32/mswsock/mswsock/nsptcpip.c @@ -0,0 +1,56 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + diff --git a/dll/win32/mswsock/mswsock/nsputil.c b/dll/win32/mswsock/mswsock/nsputil.c new file mode 100644 index 00000000000..3e062e90d63 --- /dev/null +++ b/dll/win32/mswsock/mswsock/nsputil.c @@ -0,0 +1,56 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + diff --git a/dll/win32/mswsock/mswsock/proc.c b/dll/win32/mswsock/mswsock/proc.c new file mode 100644 index 00000000000..6b45b5b8f85 --- /dev/null +++ b/dll/win32/mswsock/mswsock/proc.c @@ -0,0 +1,456 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +PRTL_HEAP_ALLOCATE SockAllocateHeapRoutine; +HANDLE SockPrivateHeap; +CRITICAL_SECTION MSWSOCK_SocketLock; +PWAH_HANDLE_TABLE SockContextTable; + +/* FUNCTIONS *****************************************************************/ + +PVOID +WSPAPI +SockInitializeHeap(IN HANDLE Heap, + IN ULONG Flags, + IN ULONG Size) +{ + /* Create the heap */ + Heap = RtlCreateHeap(HEAP_GROWABLE, + NULL, + 0, + 0, + NULL, + NULL); + + /* Check if we created it successfully */ + if (Heap) + { + /* Write its pointer */ + if (InterlockedCompareExchangePointer(&SockPrivateHeap, Heap, NULL)) + { + /* Someone already allocated it, destroy ours */ + RtlDestroyHeap(Heap); + } + } + else + { + /* Write the default heap */ + (void)InterlockedCompareExchangePointer(&SockPrivateHeap, + RtlGetProcessHeap(), + NULL); + } + + /* Set the reap heap routine now */ + SockAllocateHeapRoutine = RtlAllocateHeap; + + /* Call it */ + return SockAllocateHeapRoutine(SockPrivateHeap, Flags, Size); +} + +INT +WSPAPI +SockEnterApiSlow(OUT PWINSOCK_TEB_DATA *ThreadData) +{ + /* Check again if we're terminating */ + if (SockProcessTerminating) return WSANOTINITIALISED; + + /* Check if WSPStartup wasn't called */ + if (SockWspStartupCount <= 0) return WSANOTINITIALISED; + + /* Get the thread data */ + *ThreadData = NtCurrentTeb()->WinSockData; + if (!(*ThreadData)) + { + /* Try to initialize the thread */ + if (!MSAFD_SockThreadInitialize()) return WSAENOBUFS; + + /* Get the thread data again */ + *ThreadData = NtCurrentTeb()->WinSockData; + } + + /* Return */ + return NO_ERROR; +} + +BOOL +WSPAPI +MSAFD_SockThreadInitialize(VOID) +{ + NTSTATUS Status; + HANDLE EventHandle; + PWINSOCK_TEB_DATA TebData; + + /* Initialize the event handle */ + Status = NtCreateEvent(&EventHandle, + EVENT_ALL_ACCESS, + NULL, + NotificationEvent, + FALSE); + if (!NT_SUCCESS(Status)) return FALSE; + + /* Allocate the thread data */ + TebData = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(WINSOCK_TEB_DATA)); + if (!TebData) return FALSE; + + /* Set it and zero its contents */ + NtCurrentTeb()->WinSockData = TebData; + RtlZeroMemory(TebData, sizeof(WINSOCK_TEB_DATA)); + + /* Set the event handle */ + TebData->EventHandle = EventHandle; + + /* Return success */ + return TRUE; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +PRTL_HEAP_ALLOCATE SockAllocateHeapRoutine; +HANDLE SockPrivateHeap; +CRITICAL_SECTION MSWSOCK_SocketLock; +PWAH_HANDLE_TABLE SockContextTable; + +/* FUNCTIONS *****************************************************************/ + +PVOID +WSPAPI +SockInitializeHeap(IN HANDLE Heap, + IN ULONG Flags, + IN ULONG Size) +{ + /* Create the heap */ + Heap = RtlCreateHeap(HEAP_GROWABLE, + NULL, + 0, + 0, + NULL, + NULL); + + /* Check if we created it successfully */ + if (Heap) + { + /* Write its pointer */ + if (InterlockedCompareExchangePointer(&SockPrivateHeap, Heap, NULL)) + { + /* Someone already allocated it, destroy ours */ + RtlDestroyHeap(Heap); + } + } + else + { + /* Write the default heap */ + (void)InterlockedCompareExchangePointer(&SockPrivateHeap, + RtlGetProcessHeap(), + NULL); + } + + /* Set the reap heap routine now */ + SockAllocateHeapRoutine = RtlAllocateHeap; + + /* Call it */ + return SockAllocateHeapRoutine(SockPrivateHeap, Flags, Size); +} + +INT +WSPAPI +SockEnterApiSlow(OUT PWINSOCK_TEB_DATA *ThreadData) +{ + /* Check again if we're terminating */ + if (SockProcessTerminating) return WSANOTINITIALISED; + + /* Check if WSPStartup wasn't called */ + if (SockWspStartupCount <= 0) return WSANOTINITIALISED; + + /* Get the thread data */ + *ThreadData = NtCurrentTeb()->WinSockData; + if (!(*ThreadData)) + { + /* Try to initialize the thread */ + if (!MSAFD_SockThreadInitialize()) return WSAENOBUFS; + + /* Get the thread data again */ + *ThreadData = NtCurrentTeb()->WinSockData; + } + + /* Return */ + return NO_ERROR; +} + +BOOL +WSPAPI +MSAFD_SockThreadInitialize(VOID) +{ + NTSTATUS Status; + HANDLE EventHandle; + PWINSOCK_TEB_DATA TebData; + + /* Initialize the event handle */ + Status = NtCreateEvent(&EventHandle, + EVENT_ALL_ACCESS, + NULL, + NotificationEvent, + FALSE); + if (!NT_SUCCESS(Status)) return FALSE; + + /* Allocate the thread data */ + TebData = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(WINSOCK_TEB_DATA)); + if (!TebData) return FALSE; + + /* Set it and zero its contents */ + NtCurrentTeb()->WinSockData = TebData; + RtlZeroMemory(TebData, sizeof(WINSOCK_TEB_DATA)); + + /* Set the event handle */ + TebData->EventHandle = EventHandle; + + /* Return success */ + return TRUE; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +PRTL_HEAP_ALLOCATE SockAllocateHeapRoutine; +HANDLE SockPrivateHeap; +CRITICAL_SECTION MSWSOCK_SocketLock; +PWAH_HANDLE_TABLE SockContextTable; + +/* FUNCTIONS *****************************************************************/ + +PVOID +WSPAPI +SockInitializeHeap(IN HANDLE Heap, + IN ULONG Flags, + IN ULONG Size) +{ + /* Create the heap */ + Heap = RtlCreateHeap(HEAP_GROWABLE, + NULL, + 0, + 0, + NULL, + NULL); + + /* Check if we created it successfully */ + if (Heap) + { + /* Write its pointer */ + if (InterlockedCompareExchangePointer(&SockPrivateHeap, Heap, NULL)) + { + /* Someone already allocated it, destroy ours */ + RtlDestroyHeap(Heap); + } + } + else + { + /* Write the default heap */ + (void)InterlockedCompareExchangePointer(&SockPrivateHeap, + RtlGetProcessHeap(), + NULL); + } + + /* Set the reap heap routine now */ + SockAllocateHeapRoutine = RtlAllocateHeap; + + /* Call it */ + return SockAllocateHeapRoutine(SockPrivateHeap, Flags, Size); +} + +INT +WSPAPI +SockEnterApiSlow(OUT PWINSOCK_TEB_DATA *ThreadData) +{ + /* Check again if we're terminating */ + if (SockProcessTerminating) return WSANOTINITIALISED; + + /* Check if WSPStartup wasn't called */ + if (SockWspStartupCount <= 0) return WSANOTINITIALISED; + + /* Get the thread data */ + *ThreadData = NtCurrentTeb()->WinSockData; + if (!(*ThreadData)) + { + /* Try to initialize the thread */ + if (!MSAFD_SockThreadInitialize()) return WSAENOBUFS; + + /* Get the thread data again */ + *ThreadData = NtCurrentTeb()->WinSockData; + } + + /* Return */ + return NO_ERROR; +} + +BOOL +WSPAPI +MSAFD_SockThreadInitialize(VOID) +{ + NTSTATUS Status; + HANDLE EventHandle; + PWINSOCK_TEB_DATA TebData; + + /* Initialize the event handle */ + Status = NtCreateEvent(&EventHandle, + EVENT_ALL_ACCESS, + NULL, + NotificationEvent, + FALSE); + if (!NT_SUCCESS(Status)) return FALSE; + + /* Allocate the thread data */ + TebData = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(WINSOCK_TEB_DATA)); + if (!TebData) return FALSE; + + /* Set it and zero its contents */ + NtCurrentTeb()->WinSockData = TebData; + RtlZeroMemory(TebData, sizeof(WINSOCK_TEB_DATA)); + + /* Set the event handle */ + TebData->EventHandle = EventHandle; + + /* Return success */ + return TRUE; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +PRTL_HEAP_ALLOCATE SockAllocateHeapRoutine; +HANDLE SockPrivateHeap; +CRITICAL_SECTION MSWSOCK_SocketLock; +PWAH_HANDLE_TABLE SockContextTable; + +/* FUNCTIONS *****************************************************************/ + +PVOID +WSPAPI +SockInitializeHeap(IN HANDLE Heap, + IN ULONG Flags, + IN ULONG Size) +{ + /* Create the heap */ + Heap = RtlCreateHeap(HEAP_GROWABLE, + NULL, + 0, + 0, + NULL, + NULL); + + /* Check if we created it successfully */ + if (Heap) + { + /* Write its pointer */ + if (InterlockedCompareExchangePointer(&SockPrivateHeap, Heap, NULL)) + { + /* Someone already allocated it, destroy ours */ + RtlDestroyHeap(Heap); + } + } + else + { + /* Write the default heap */ + (void)InterlockedCompareExchangePointer(&SockPrivateHeap, + RtlGetProcessHeap(), + NULL); + } + + /* Set the reap heap routine now */ + SockAllocateHeapRoutine = RtlAllocateHeap; + + /* Call it */ + return SockAllocateHeapRoutine(SockPrivateHeap, Flags, Size); +} + +INT +WSPAPI +SockEnterApiSlow(OUT PWINSOCK_TEB_DATA *ThreadData) +{ + /* Check again if we're terminating */ + if (SockProcessTerminating) return WSANOTINITIALISED; + + /* Check if WSPStartup wasn't called */ + if (SockWspStartupCount <= 0) return WSANOTINITIALISED; + + /* Get the thread data */ + *ThreadData = NtCurrentTeb()->WinSockData; + if (!(*ThreadData)) + { + /* Try to initialize the thread */ + if (!MSAFD_SockThreadInitialize()) return WSAENOBUFS; + + /* Get the thread data again */ + *ThreadData = NtCurrentTeb()->WinSockData; + } + + /* Return */ + return NO_ERROR; +} + +BOOL +WSPAPI +MSAFD_SockThreadInitialize(VOID) +{ + NTSTATUS Status; + HANDLE EventHandle; + PWINSOCK_TEB_DATA TebData; + + /* Initialize the event handle */ + Status = NtCreateEvent(&EventHandle, + EVENT_ALL_ACCESS, + NULL, + NotificationEvent, + FALSE); + if (!NT_SUCCESS(Status)) return FALSE; + + /* Allocate the thread data */ + TebData = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(WINSOCK_TEB_DATA)); + if (!TebData) return FALSE; + + /* Set it and zero its contents */ + NtCurrentTeb()->WinSockData = TebData; + RtlZeroMemory(TebData, sizeof(WINSOCK_TEB_DATA)); + + /* Set the event handle */ + TebData->EventHandle = EventHandle; + + /* Return success */ + return TRUE; +} + diff --git a/dll/win32/mswsock/mswsock/recvex.c b/dll/win32/mswsock/mswsock/recvex.c new file mode 100644 index 00000000000..3e062e90d63 --- /dev/null +++ b/dll/win32/mswsock/mswsock/recvex.c @@ -0,0 +1,56 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + diff --git a/dll/win32/mswsock/mswsock/setup.c b/dll/win32/mswsock/mswsock/setup.c new file mode 100644 index 00000000000..3e062e90d63 --- /dev/null +++ b/dll/win32/mswsock/mswsock/setup.c @@ -0,0 +1,56 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + diff --git a/dll/win32/mswsock/mswsock/stubs.c b/dll/win32/mswsock/mswsock/stubs.c new file mode 100644 index 00000000000..ad110552d1e --- /dev/null +++ b/dll/win32/mswsock/mswsock/stubs.c @@ -0,0 +1,1388 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +BOOL +WINAPI +AcceptEx(SOCKET ListenSocket, + SOCKET AcceptSocket, + PVOID OutputBuffer, + DWORD ReceiveDataLength, + DWORD LocalAddressLength, + DWORD RemoteAddressLength, + LPDWORD BytesReceived, + LPOVERLAPPED Overlapped) +{ + OutputDebugStringW(L"AcceptEx is UNIMPLEMENTED\n"); + + return FALSE; +} + +VOID +WINAPI +GetAcceptExSockaddrs(PVOID OutputBuffer, + DWORD ReceiveDataLength, + DWORD LocalAddressLength, + DWORD RemoteAddressLength, + LPSOCKADDR* LocalSockaddr, + LPINT LocalSockaddrLength, + LPSOCKADDR* RemoteSockaddr, + LPINT RemoteSockaddrLength) +{ + OutputDebugStringW(L"GetAcceptExSockaddrs is UNIMPLEMENTED\n"); +} + +INT +WINAPI +GetAddressByNameA(DWORD NameSpace, + LPGUID ServiceType, + LPSTR ServiceName, + LPINT Protocols, + DWORD Resolution, + LPSERVICE_ASYNC_INFO ServiceAsyncInfo, + LPVOID CsaddrBuffer, + LPDWORD BufferLength, + LPSTR AliasBuffer, + LPDWORD AliasBufferLength) +{ + OutputDebugStringW(L"GetAddressByNameA is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +GetAddressByNameW(DWORD NameSpace, + LPGUID ServiceType, + LPWSTR ServiceName, + LPINT Protocols, + DWORD Resolution, + LPSERVICE_ASYNC_INFO ServiceAsyncInfo, + LPVOID CsaddrBuffer, + LPDWORD BufferLength, + LPWSTR AliasBuffer, + LPDWORD AliasBufferLength) +{ + OutputDebugStringW(L"GetAddressByNameW is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +GetServiceA(DWORD NameSpace, + LPGUID Guid, + LPSTR ServiceName, + DWORD Properties, + LPVOID Buffer, + LPDWORD BufferSize, + LPSERVICE_ASYNC_INFO ServiceAsyncInfo) +{ + OutputDebugStringW(L"GetServiceA is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +GetServiceW(DWORD NameSpace, + LPGUID Guid, + LPWSTR ServiceName, + DWORD Properties, + LPVOID Buffer, + LPDWORD BufferSize, + LPSERVICE_ASYNC_INFO ServiceAsyncInfo) +{ + OutputDebugStringW(L"GetServiceW is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +GetTypeByNameA(LPSTR ServiceName, + LPGUID ServiceType) +{ + OutputDebugStringW(L"GetTypeByNameA is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +GetTypeByNameW(LPWSTR ServiceName, + LPGUID ServiceType) +{ + OutputDebugStringW(L"GetTypeByNameW is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +MigrateWinsockConfiguration(DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + OutputDebugStringW(L"MigrateWinsockConfiguration is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +SetServiceA(DWORD NameSpace, + DWORD Operation, + DWORD Flags, + LPSERVICE_INFOA ServiceInfo, + LPSERVICE_ASYNC_INFO ServiceAsyncInfo, + LPDWORD dwStatusFlags) +{ + OutputDebugStringW(L"SetServiceA is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +SetServiceW(DWORD NameSpace, + DWORD Operation, + DWORD Flags, + LPSERVICE_INFOW ServiceInfo, + LPSERVICE_ASYNC_INFO ServiceAsyncInfo, + LPDWORD dwStatusFlags) +{ + OutputDebugStringW(L"SetServiceW is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +int +WINAPI +WSARecvEx(SOCKET Sock, + char *Buf, + int Len, + int *Flags) +{ + OutputDebugStringW(L"WSARecvEx is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +int +WINAPI +dn_expand(unsigned char *MessagePtr, + unsigned char *EndofMesOrig, + unsigned char *CompDomNam, + unsigned char *ExpandDomNam, + int Length) +{ + OutputDebugStringW(L"dn_expand is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +struct netent * +WINAPI +getnetbyname(const char *name) +{ + OutputDebugStringW(L"getnetbyname is UNIMPLEMENTED\n"); + + return NULL; +} + +UINT +WINAPI +inet_network(const char *cp) +{ + OutputDebugStringW(L"inet_network is UNIMPLEMENTED\n"); + + return INADDR_NONE; +} + +SOCKET +WINAPI +rcmd(char **AHost, + USHORT InPort, + char *LocUser, + char *RemUser, + char *Cmd, + int *Fd2p) +{ + OutputDebugStringW(L"rcmd is UNIMPLEMENTED\n"); + + return INVALID_SOCKET; +} + +SOCKET +WINAPI +rexec(char **AHost, + int InPort, + char *User, + char *Passwd, + char *Cmd, + int *Fd2p) +{ + OutputDebugStringW(L"rexec is UNIMPLEMENTED\n"); + + return INVALID_SOCKET; +} + +SOCKET +WINAPI +rresvport(int *port) +{ + OutputDebugStringW(L"rresvport is UNIMPLEMENTED\n"); + + return INVALID_SOCKET; +} + +void +WINAPI +s_perror(const char *str) +{ + OutputDebugStringW(L"s_perror is UNIMPLEMENTED\n"); +} + +int +WINAPI +sethostname(char *Name, int NameLen) +{ + OutputDebugStringW(L"sethostname is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +GetNameByTypeA(LPGUID lpServiceType, LPSTR lpServiceName, DWORD dwNameLength) +{ + OutputDebugStringW(L"GetNameByTypeA is UNIMPLEMENTED\n"); + + return 0; +} + +INT +WINAPI +GetNameByTypeW(LPGUID lpServiceType, LPWSTR lpServiceName, DWORD dwNameLength) +{ + OutputDebugStringW(L"GetNameByTypeW is UNIMPLEMENTED\n"); + + return 0; +} + +VOID +WINAPI +StartWsdpService() +{ + OutputDebugStringW(L"StartWsdpService is UNIMPLEMENTED\n"); +} + +VOID +WINAPI +StopWsdpService() +{ + OutputDebugStringW(L"StopWsdpService is UNIMPLEMENTED\n"); +} + +DWORD +WINAPI +SvchostPushServiceGlobals(DWORD Value) +{ + OutputDebugStringW(L"SvchostPushServiceGlobals is UNIMPLEMENTED\n"); + + return 0; +} + +VOID +WINAPI +ServiceMain(DWORD Unknown1, DWORD Unknown2) +{ + OutputDebugStringW(L"ServiceMain is UNIMPLEMENTED\n"); +} + +INT +WINAPI +EnumProtocolsA(LPINT ProtocolCount, + LPVOID ProtocolBuffer, + LPDWORD BufferLength) +{ + OutputDebugStringW(L"EnumProtocolsA is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +EnumProtocolsW(LPINT ProtocolCount, + LPVOID ProtocolBuffer, + LPDWORD BufferLength) +{ + OutputDebugStringW(L"EnumProtocolsW is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +NPLoadNameSpaces( + IN OUT LPDWORD lpdwVersion, + IN OUT LPNS_ROUTINE nsrBuffer, + IN OUT LPDWORD lpdwBufferLength) +{ + OutputDebugStringW(L"NPLoadNameSpaces is UNIMPLEMENTED\n"); + + return 0; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +BOOL +WINAPI +AcceptEx(SOCKET ListenSocket, + SOCKET AcceptSocket, + PVOID OutputBuffer, + DWORD ReceiveDataLength, + DWORD LocalAddressLength, + DWORD RemoteAddressLength, + LPDWORD BytesReceived, + LPOVERLAPPED Overlapped) +{ + OutputDebugStringW(L"AcceptEx is UNIMPLEMENTED\n"); + + return FALSE; +} + +VOID +WINAPI +GetAcceptExSockaddrs(PVOID OutputBuffer, + DWORD ReceiveDataLength, + DWORD LocalAddressLength, + DWORD RemoteAddressLength, + LPSOCKADDR* LocalSockaddr, + LPINT LocalSockaddrLength, + LPSOCKADDR* RemoteSockaddr, + LPINT RemoteSockaddrLength) +{ + OutputDebugStringW(L"GetAcceptExSockaddrs is UNIMPLEMENTED\n"); +} + +INT +WINAPI +GetAddressByNameA(DWORD NameSpace, + LPGUID ServiceType, + LPSTR ServiceName, + LPINT Protocols, + DWORD Resolution, + LPSERVICE_ASYNC_INFO ServiceAsyncInfo, + LPVOID CsaddrBuffer, + LPDWORD BufferLength, + LPSTR AliasBuffer, + LPDWORD AliasBufferLength) +{ + OutputDebugStringW(L"GetAddressByNameA is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +GetAddressByNameW(DWORD NameSpace, + LPGUID ServiceType, + LPWSTR ServiceName, + LPINT Protocols, + DWORD Resolution, + LPSERVICE_ASYNC_INFO ServiceAsyncInfo, + LPVOID CsaddrBuffer, + LPDWORD BufferLength, + LPWSTR AliasBuffer, + LPDWORD AliasBufferLength) +{ + OutputDebugStringW(L"GetAddressByNameW is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +GetServiceA(DWORD NameSpace, + LPGUID Guid, + LPSTR ServiceName, + DWORD Properties, + LPVOID Buffer, + LPDWORD BufferSize, + LPSERVICE_ASYNC_INFO ServiceAsyncInfo) +{ + OutputDebugStringW(L"GetServiceA is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +GetServiceW(DWORD NameSpace, + LPGUID Guid, + LPWSTR ServiceName, + DWORD Properties, + LPVOID Buffer, + LPDWORD BufferSize, + LPSERVICE_ASYNC_INFO ServiceAsyncInfo) +{ + OutputDebugStringW(L"GetServiceW is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +GetTypeByNameA(LPSTR ServiceName, + LPGUID ServiceType) +{ + OutputDebugStringW(L"GetTypeByNameA is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +GetTypeByNameW(LPWSTR ServiceName, + LPGUID ServiceType) +{ + OutputDebugStringW(L"GetTypeByNameW is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +MigrateWinsockConfiguration(DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + OutputDebugStringW(L"MigrateWinsockConfiguration is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +SetServiceA(DWORD NameSpace, + DWORD Operation, + DWORD Flags, + LPSERVICE_INFOA ServiceInfo, + LPSERVICE_ASYNC_INFO ServiceAsyncInfo, + LPDWORD dwStatusFlags) +{ + OutputDebugStringW(L"SetServiceA is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +SetServiceW(DWORD NameSpace, + DWORD Operation, + DWORD Flags, + LPSERVICE_INFOW ServiceInfo, + LPSERVICE_ASYNC_INFO ServiceAsyncInfo, + LPDWORD dwStatusFlags) +{ + OutputDebugStringW(L"SetServiceW is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +int +WINAPI +WSARecvEx(SOCKET Sock, + char *Buf, + int Len, + int *Flags) +{ + OutputDebugStringW(L"WSARecvEx is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +int +WINAPI +dn_expand(unsigned char *MessagePtr, + unsigned char *EndofMesOrig, + unsigned char *CompDomNam, + unsigned char *ExpandDomNam, + int Length) +{ + OutputDebugStringW(L"dn_expand is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +struct netent * +WINAPI +getnetbyname(const char *name) +{ + OutputDebugStringW(L"getnetbyname is UNIMPLEMENTED\n"); + + return NULL; +} + +UINT +WINAPI +inet_network(const char *cp) +{ + OutputDebugStringW(L"inet_network is UNIMPLEMENTED\n"); + + return INADDR_NONE; +} + +SOCKET +WINAPI +rcmd(char **AHost, + USHORT InPort, + char *LocUser, + char *RemUser, + char *Cmd, + int *Fd2p) +{ + OutputDebugStringW(L"rcmd is UNIMPLEMENTED\n"); + + return INVALID_SOCKET; +} + +SOCKET +WINAPI +rexec(char **AHost, + int InPort, + char *User, + char *Passwd, + char *Cmd, + int *Fd2p) +{ + OutputDebugStringW(L"rexec is UNIMPLEMENTED\n"); + + return INVALID_SOCKET; +} + +SOCKET +WINAPI +rresvport(int *port) +{ + OutputDebugStringW(L"rresvport is UNIMPLEMENTED\n"); + + return INVALID_SOCKET; +} + +void +WINAPI +s_perror(const char *str) +{ + OutputDebugStringW(L"s_perror is UNIMPLEMENTED\n"); +} + +int +WINAPI +sethostname(char *Name, int NameLen) +{ + OutputDebugStringW(L"sethostname is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +GetNameByTypeA(LPGUID lpServiceType, LPSTR lpServiceName, DWORD dwNameLength) +{ + OutputDebugStringW(L"GetNameByTypeA is UNIMPLEMENTED\n"); + + return 0; +} + +INT +WINAPI +GetNameByTypeW(LPGUID lpServiceType, LPWSTR lpServiceName, DWORD dwNameLength) +{ + OutputDebugStringW(L"GetNameByTypeW is UNIMPLEMENTED\n"); + + return 0; +} + +VOID +WINAPI +StartWsdpService() +{ + OutputDebugStringW(L"StartWsdpService is UNIMPLEMENTED\n"); +} + +VOID +WINAPI +StopWsdpService() +{ + OutputDebugStringW(L"StopWsdpService is UNIMPLEMENTED\n"); +} + +DWORD +WINAPI +SvchostPushServiceGlobals(DWORD Value) +{ + OutputDebugStringW(L"SvchostPushServiceGlobals is UNIMPLEMENTED\n"); + + return 0; +} + +VOID +WINAPI +ServiceMain(DWORD Unknown1, DWORD Unknown2) +{ + OutputDebugStringW(L"ServiceMain is UNIMPLEMENTED\n"); +} + +INT +WINAPI +EnumProtocolsA(LPINT ProtocolCount, + LPVOID ProtocolBuffer, + LPDWORD BufferLength) +{ + OutputDebugStringW(L"EnumProtocolsA is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +EnumProtocolsW(LPINT ProtocolCount, + LPVOID ProtocolBuffer, + LPDWORD BufferLength) +{ + OutputDebugStringW(L"EnumProtocolsW is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +NPLoadNameSpaces( + IN OUT LPDWORD lpdwVersion, + IN OUT LPNS_ROUTINE nsrBuffer, + IN OUT LPDWORD lpdwBufferLength) +{ + OutputDebugStringW(L"NPLoadNameSpaces is UNIMPLEMENTED\n"); + + return 0; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +BOOL +WINAPI +AcceptEx(SOCKET ListenSocket, + SOCKET AcceptSocket, + PVOID OutputBuffer, + DWORD ReceiveDataLength, + DWORD LocalAddressLength, + DWORD RemoteAddressLength, + LPDWORD BytesReceived, + LPOVERLAPPED Overlapped) +{ + OutputDebugStringW(L"AcceptEx is UNIMPLEMENTED\n"); + + return FALSE; +} + +VOID +WINAPI +GetAcceptExSockaddrs(PVOID OutputBuffer, + DWORD ReceiveDataLength, + DWORD LocalAddressLength, + DWORD RemoteAddressLength, + LPSOCKADDR* LocalSockaddr, + LPINT LocalSockaddrLength, + LPSOCKADDR* RemoteSockaddr, + LPINT RemoteSockaddrLength) +{ + OutputDebugStringW(L"GetAcceptExSockaddrs is UNIMPLEMENTED\n"); +} + +INT +WINAPI +GetAddressByNameA(DWORD NameSpace, + LPGUID ServiceType, + LPSTR ServiceName, + LPINT Protocols, + DWORD Resolution, + LPSERVICE_ASYNC_INFO ServiceAsyncInfo, + LPVOID CsaddrBuffer, + LPDWORD BufferLength, + LPSTR AliasBuffer, + LPDWORD AliasBufferLength) +{ + OutputDebugStringW(L"GetAddressByNameA is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +GetAddressByNameW(DWORD NameSpace, + LPGUID ServiceType, + LPWSTR ServiceName, + LPINT Protocols, + DWORD Resolution, + LPSERVICE_ASYNC_INFO ServiceAsyncInfo, + LPVOID CsaddrBuffer, + LPDWORD BufferLength, + LPWSTR AliasBuffer, + LPDWORD AliasBufferLength) +{ + OutputDebugStringW(L"GetAddressByNameW is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +GetServiceA(DWORD NameSpace, + LPGUID Guid, + LPSTR ServiceName, + DWORD Properties, + LPVOID Buffer, + LPDWORD BufferSize, + LPSERVICE_ASYNC_INFO ServiceAsyncInfo) +{ + OutputDebugStringW(L"GetServiceA is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +GetServiceW(DWORD NameSpace, + LPGUID Guid, + LPWSTR ServiceName, + DWORD Properties, + LPVOID Buffer, + LPDWORD BufferSize, + LPSERVICE_ASYNC_INFO ServiceAsyncInfo) +{ + OutputDebugStringW(L"GetServiceW is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +GetTypeByNameA(LPSTR ServiceName, + LPGUID ServiceType) +{ + OutputDebugStringW(L"GetTypeByNameA is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +GetTypeByNameW(LPWSTR ServiceName, + LPGUID ServiceType) +{ + OutputDebugStringW(L"GetTypeByNameW is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +MigrateWinsockConfiguration(DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + OutputDebugStringW(L"MigrateWinsockConfiguration is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +SetServiceA(DWORD NameSpace, + DWORD Operation, + DWORD Flags, + LPSERVICE_INFOA ServiceInfo, + LPSERVICE_ASYNC_INFO ServiceAsyncInfo, + LPDWORD dwStatusFlags) +{ + OutputDebugStringW(L"SetServiceA is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +SetServiceW(DWORD NameSpace, + DWORD Operation, + DWORD Flags, + LPSERVICE_INFOW ServiceInfo, + LPSERVICE_ASYNC_INFO ServiceAsyncInfo, + LPDWORD dwStatusFlags) +{ + OutputDebugStringW(L"SetServiceW is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +int +WINAPI +WSARecvEx(SOCKET Sock, + char *Buf, + int Len, + int *Flags) +{ + OutputDebugStringW(L"WSARecvEx is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +int +WINAPI +dn_expand(unsigned char *MessagePtr, + unsigned char *EndofMesOrig, + unsigned char *CompDomNam, + unsigned char *ExpandDomNam, + int Length) +{ + OutputDebugStringW(L"dn_expand is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +struct netent * +WINAPI +getnetbyname(const char *name) +{ + OutputDebugStringW(L"getnetbyname is UNIMPLEMENTED\n"); + + return NULL; +} + +UINT +WINAPI +inet_network(const char *cp) +{ + OutputDebugStringW(L"inet_network is UNIMPLEMENTED\n"); + + return INADDR_NONE; +} + +SOCKET +WINAPI +rcmd(char **AHost, + USHORT InPort, + char *LocUser, + char *RemUser, + char *Cmd, + int *Fd2p) +{ + OutputDebugStringW(L"rcmd is UNIMPLEMENTED\n"); + + return INVALID_SOCKET; +} + +SOCKET +WINAPI +rexec(char **AHost, + int InPort, + char *User, + char *Passwd, + char *Cmd, + int *Fd2p) +{ + OutputDebugStringW(L"rexec is UNIMPLEMENTED\n"); + + return INVALID_SOCKET; +} + +SOCKET +WINAPI +rresvport(int *port) +{ + OutputDebugStringW(L"rresvport is UNIMPLEMENTED\n"); + + return INVALID_SOCKET; +} + +void +WINAPI +s_perror(const char *str) +{ + OutputDebugStringW(L"s_perror is UNIMPLEMENTED\n"); +} + +int +WINAPI +sethostname(char *Name, int NameLen) +{ + OutputDebugStringW(L"sethostname is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +GetNameByTypeA(LPGUID lpServiceType, LPSTR lpServiceName, DWORD dwNameLength) +{ + OutputDebugStringW(L"GetNameByTypeA is UNIMPLEMENTED\n"); + + return 0; +} + +INT +WINAPI +GetNameByTypeW(LPGUID lpServiceType, LPWSTR lpServiceName, DWORD dwNameLength) +{ + OutputDebugStringW(L"GetNameByTypeW is UNIMPLEMENTED\n"); + + return 0; +} + +VOID +WINAPI +StartWsdpService() +{ + OutputDebugStringW(L"StartWsdpService is UNIMPLEMENTED\n"); +} + +VOID +WINAPI +StopWsdpService() +{ + OutputDebugStringW(L"StopWsdpService is UNIMPLEMENTED\n"); +} + +DWORD +WINAPI +SvchostPushServiceGlobals(DWORD Value) +{ + OutputDebugStringW(L"SvchostPushServiceGlobals is UNIMPLEMENTED\n"); + + return 0; +} + +VOID +WINAPI +ServiceMain(DWORD Unknown1, DWORD Unknown2) +{ + OutputDebugStringW(L"ServiceMain is UNIMPLEMENTED\n"); +} + +INT +WINAPI +EnumProtocolsA(LPINT ProtocolCount, + LPVOID ProtocolBuffer, + LPDWORD BufferLength) +{ + OutputDebugStringW(L"EnumProtocolsA is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +EnumProtocolsW(LPINT ProtocolCount, + LPVOID ProtocolBuffer, + LPDWORD BufferLength) +{ + OutputDebugStringW(L"EnumProtocolsW is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +NPLoadNameSpaces( + IN OUT LPDWORD lpdwVersion, + IN OUT LPNS_ROUTINE nsrBuffer, + IN OUT LPDWORD lpdwBufferLength) +{ + OutputDebugStringW(L"NPLoadNameSpaces is UNIMPLEMENTED\n"); + + return 0; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +BOOL +WINAPI +AcceptEx(SOCKET ListenSocket, + SOCKET AcceptSocket, + PVOID OutputBuffer, + DWORD ReceiveDataLength, + DWORD LocalAddressLength, + DWORD RemoteAddressLength, + LPDWORD BytesReceived, + LPOVERLAPPED Overlapped) +{ + OutputDebugStringW(L"AcceptEx is UNIMPLEMENTED\n"); + + return FALSE; +} + +VOID +WINAPI +GetAcceptExSockaddrs(PVOID OutputBuffer, + DWORD ReceiveDataLength, + DWORD LocalAddressLength, + DWORD RemoteAddressLength, + LPSOCKADDR* LocalSockaddr, + LPINT LocalSockaddrLength, + LPSOCKADDR* RemoteSockaddr, + LPINT RemoteSockaddrLength) +{ + OutputDebugStringW(L"GetAcceptExSockaddrs is UNIMPLEMENTED\n"); +} + +INT +WINAPI +GetAddressByNameA(DWORD NameSpace, + LPGUID ServiceType, + LPSTR ServiceName, + LPINT Protocols, + DWORD Resolution, + LPSERVICE_ASYNC_INFO ServiceAsyncInfo, + LPVOID CsaddrBuffer, + LPDWORD BufferLength, + LPSTR AliasBuffer, + LPDWORD AliasBufferLength) +{ + OutputDebugStringW(L"GetAddressByNameA is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +GetAddressByNameW(DWORD NameSpace, + LPGUID ServiceType, + LPWSTR ServiceName, + LPINT Protocols, + DWORD Resolution, + LPSERVICE_ASYNC_INFO ServiceAsyncInfo, + LPVOID CsaddrBuffer, + LPDWORD BufferLength, + LPWSTR AliasBuffer, + LPDWORD AliasBufferLength) +{ + OutputDebugStringW(L"GetAddressByNameW is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +GetServiceA(DWORD NameSpace, + LPGUID Guid, + LPSTR ServiceName, + DWORD Properties, + LPVOID Buffer, + LPDWORD BufferSize, + LPSERVICE_ASYNC_INFO ServiceAsyncInfo) +{ + OutputDebugStringW(L"GetServiceA is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +GetServiceW(DWORD NameSpace, + LPGUID Guid, + LPWSTR ServiceName, + DWORD Properties, + LPVOID Buffer, + LPDWORD BufferSize, + LPSERVICE_ASYNC_INFO ServiceAsyncInfo) +{ + OutputDebugStringW(L"GetServiceW is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +GetTypeByNameA(LPSTR ServiceName, + LPGUID ServiceType) +{ + OutputDebugStringW(L"GetTypeByNameA is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +GetTypeByNameW(LPWSTR ServiceName, + LPGUID ServiceType) +{ + OutputDebugStringW(L"GetTypeByNameW is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +MigrateWinsockConfiguration(DWORD Unknown1, + DWORD Unknown2, + DWORD Unknown3) +{ + OutputDebugStringW(L"MigrateWinsockConfiguration is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +SetServiceA(DWORD NameSpace, + DWORD Operation, + DWORD Flags, + LPSERVICE_INFOA ServiceInfo, + LPSERVICE_ASYNC_INFO ServiceAsyncInfo, + LPDWORD dwStatusFlags) +{ + OutputDebugStringW(L"SetServiceA is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +SetServiceW(DWORD NameSpace, + DWORD Operation, + DWORD Flags, + LPSERVICE_INFOW ServiceInfo, + LPSERVICE_ASYNC_INFO ServiceAsyncInfo, + LPDWORD dwStatusFlags) +{ + OutputDebugStringW(L"SetServiceW is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +int +WINAPI +WSARecvEx(SOCKET Sock, + char *Buf, + int Len, + int *Flags) +{ + OutputDebugStringW(L"WSARecvEx is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +int +WINAPI +dn_expand(unsigned char *MessagePtr, + unsigned char *EndofMesOrig, + unsigned char *CompDomNam, + unsigned char *ExpandDomNam, + int Length) +{ + OutputDebugStringW(L"dn_expand is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +struct netent * +WINAPI +getnetbyname(const char *name) +{ + OutputDebugStringW(L"getnetbyname is UNIMPLEMENTED\n"); + + return NULL; +} + +UINT +WINAPI +inet_network(const char *cp) +{ + OutputDebugStringW(L"inet_network is UNIMPLEMENTED\n"); + + return INADDR_NONE; +} + +SOCKET +WINAPI +rcmd(char **AHost, + USHORT InPort, + char *LocUser, + char *RemUser, + char *Cmd, + int *Fd2p) +{ + OutputDebugStringW(L"rcmd is UNIMPLEMENTED\n"); + + return INVALID_SOCKET; +} + +SOCKET +WINAPI +rexec(char **AHost, + int InPort, + char *User, + char *Passwd, + char *Cmd, + int *Fd2p) +{ + OutputDebugStringW(L"rexec is UNIMPLEMENTED\n"); + + return INVALID_SOCKET; +} + +SOCKET +WINAPI +rresvport(int *port) +{ + OutputDebugStringW(L"rresvport is UNIMPLEMENTED\n"); + + return INVALID_SOCKET; +} + +void +WINAPI +s_perror(const char *str) +{ + OutputDebugStringW(L"s_perror is UNIMPLEMENTED\n"); +} + +int +WINAPI +sethostname(char *Name, int NameLen) +{ + OutputDebugStringW(L"sethostname is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +GetNameByTypeA(LPGUID lpServiceType, LPSTR lpServiceName, DWORD dwNameLength) +{ + OutputDebugStringW(L"GetNameByTypeA is UNIMPLEMENTED\n"); + + return 0; +} + +INT +WINAPI +GetNameByTypeW(LPGUID lpServiceType, LPWSTR lpServiceName, DWORD dwNameLength) +{ + OutputDebugStringW(L"GetNameByTypeW is UNIMPLEMENTED\n"); + + return 0; +} + +VOID +WINAPI +StartWsdpService() +{ + OutputDebugStringW(L"StartWsdpService is UNIMPLEMENTED\n"); +} + +VOID +WINAPI +StopWsdpService() +{ + OutputDebugStringW(L"StopWsdpService is UNIMPLEMENTED\n"); +} + +DWORD +WINAPI +SvchostPushServiceGlobals(DWORD Value) +{ + OutputDebugStringW(L"SvchostPushServiceGlobals is UNIMPLEMENTED\n"); + + return 0; +} + +VOID +WINAPI +ServiceMain(DWORD Unknown1, DWORD Unknown2) +{ + OutputDebugStringW(L"ServiceMain is UNIMPLEMENTED\n"); +} + +INT +WINAPI +EnumProtocolsA(LPINT ProtocolCount, + LPVOID ProtocolBuffer, + LPDWORD BufferLength) +{ + OutputDebugStringW(L"EnumProtocolsA is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +EnumProtocolsW(LPINT ProtocolCount, + LPVOID ProtocolBuffer, + LPDWORD BufferLength) +{ + OutputDebugStringW(L"EnumProtocolsW is UNIMPLEMENTED\n"); + + return SOCKET_ERROR; +} + +INT +WINAPI +NPLoadNameSpaces( + IN OUT LPDWORD lpdwVersion, + IN OUT LPNS_ROUTINE nsrBuffer, + IN OUT LPDWORD lpdwBufferLength) +{ + OutputDebugStringW(L"NPLoadNameSpaces is UNIMPLEMENTED\n"); + + return 0; +} + diff --git a/dll/win32/mswsock/rnr20/context.c b/dll/win32/mswsock/rnr20/context.c new file mode 100644 index 00000000000..dfb5c79dde3 --- /dev/null +++ b/dll/win32/mswsock/rnr20/context.c @@ -0,0 +1,648 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +LIST_ENTRY ListAnchor; +BOOLEAN g_fRnrLockInit; +CRITICAL_SECTION g_RnrLock; + +#define AcquireRnR2Lock() EnterCriticalSection(&g_RnrLock); +#define ReleaseRnR2Lock() LeaveCriticalSection(&g_RnrLock); + +/* FUNCTIONS *****************************************************************/ + +PRNR_CONTEXT +WSPAPI +RnrCtx_Create(IN HANDLE LookupHandle, + IN LPWSTR ServiceName) +{ + PRNR_CONTEXT RnrContext; + SIZE_T StringSize = 0; + + /* Get the size of the string */ + if (ServiceName) StringSize = wcslen(ServiceName); + + /* Allocate the Context */ + RnrContext = Temp_AllocZero(sizeof(RNR_CONTEXT) + (DWORD)StringSize); + + /* Check that we got one */ + if (RnrContext) + { + /* Set it up */ + RnrContext->RefCount = 2; + RnrContext->Handle = (LookupHandle ? LookupHandle : (HANDLE)RnrContext); + RnrContext->Instance = -1; + RnrContext->Signature = 0xaabbccdd; + wcscpy(RnrContext->ServiceName, ServiceName); + + /* Insert it into the list */ + AcquireRnR2Lock(); + InsertHeadList(&ListAnchor, &RnrContext->ListEntry); + ReleaseRnR2Lock(); + } + + /* Return it */ + return RnrContext; +} + +VOID +WSPAPI +RnrCtx_Release(PRNR_CONTEXT RnrContext) +{ + /* Acquire the lock */ + AcquireRnR2Lock(); + + /* Decrease reference count and check if it's still in use */ + if(!(--RnrContext->RefCount)) + { + /* Remove it from the List */ + RemoveEntryList(&RnrContext->ListEntry); + + /* Release the lock */ + ReleaseRnR2Lock(); + + /* Deallocated any cached Hostent */ + if(RnrContext->CachedSaBlob) SaBlob_Free(RnrContext->CachedSaBlob); + + /* Deallocate the Blob */ + if(RnrContext->CachedBlob.pBlobData) + { + DnsApiFree(RnrContext->CachedBlob.pBlobData); + } + + /* Deallocate the actual context itself */ + DnsApiFree(RnrContext); + } + else + { + /* Release the lock */ + ReleaseRnR2Lock(); + } +} + +PRNR_CONTEXT +WSPAPI +RnrCtx_Get(HANDLE LookupHandle, + DWORD dwControlFlags, + PLONG Instance) +{ + PLIST_ENTRY Entry; + PRNR_CONTEXT RnRContext = NULL; + + /* Acquire the lock */ + AcquireRnR2Lock(); + + /* Loop the RNR Context List */ + for(Entry = ListAnchor.Flink; Entry != &ListAnchor; Entry = Entry->Flink) + { + /* Get the Current RNR Context */ + RnRContext = CONTAINING_RECORD(Entry, RNR_CONTEXT, ListEntry); + + /* Check if it matches the one we got */ + if(RnRContext == (PRNR_CONTEXT)LookupHandle) break; + } + + /* If we found it, mark it in use */ + if(RnRContext) RnRContext->RefCount++; + + /* Increase the Instance and return it */ + *Instance = ++RnRContext->Instance; + + /* If we're flushing the previous one, then bias the Instance by one */ + if(dwControlFlags & LUP_FLUSHPREVIOUS) *Instance = ++RnRContext->Instance; + + /* Release the lock */ + ReleaseRnR2Lock(); + + /* Return the Context */ + return RnRContext; +} + +VOID +WSPAPI +RnrCtx_DecInstance(IN PRNR_CONTEXT RnrContext) +{ + /* Acquire the lock */ + AcquireRnR2Lock(); + + /* Decrease instance count */ + RnrContext->Instance--; + + /* Release the lock */ + ReleaseRnR2Lock(); +} + +VOID +WSPAPI +RnrCtx_ListCleanup(VOID) +{ + PLIST_ENTRY Entry; + + /* Acquire RnR Lock */ + AcquireRnR2Lock(); + + /* Loop the contexts */ + while ((Entry = ListAnchor.Flink) != &ListAnchor) + { + /* Release this context */ + RnrCtx_Release(CONTAINING_RECORD(Entry, RNR_CONTEXT, ListEntry)); + } + + /* Release lock */ + ReleaseRnR2Lock(); +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +LIST_ENTRY ListAnchor; +BOOLEAN g_fRnrLockInit; +CRITICAL_SECTION g_RnrLock; + +#define AcquireRnR2Lock() EnterCriticalSection(&g_RnrLock); +#define ReleaseRnR2Lock() LeaveCriticalSection(&g_RnrLock); + +/* FUNCTIONS *****************************************************************/ + +PRNR_CONTEXT +WSPAPI +RnrCtx_Create(IN HANDLE LookupHandle, + IN LPWSTR ServiceName) +{ + PRNR_CONTEXT RnrContext; + SIZE_T StringSize = 0; + + /* Get the size of the string */ + if (ServiceName) StringSize = wcslen(ServiceName); + + /* Allocate the Context */ + RnrContext = Temp_AllocZero(sizeof(RNR_CONTEXT) + (DWORD)StringSize); + + /* Check that we got one */ + if (RnrContext) + { + /* Set it up */ + RnrContext->RefCount = 2; + RnrContext->Handle = (LookupHandle ? LookupHandle : (HANDLE)RnrContext); + RnrContext->Instance = -1; + RnrContext->Signature = 0xaabbccdd; + wcscpy(RnrContext->ServiceName, ServiceName); + + /* Insert it into the list */ + AcquireRnR2Lock(); + InsertHeadList(&ListAnchor, &RnrContext->ListEntry); + ReleaseRnR2Lock(); + } + + /* Return it */ + return RnrContext; +} + +VOID +WSPAPI +RnrCtx_Release(PRNR_CONTEXT RnrContext) +{ + /* Acquire the lock */ + AcquireRnR2Lock(); + + /* Decrease reference count and check if it's still in use */ + if(!(--RnrContext->RefCount)) + { + /* Remove it from the List */ + RemoveEntryList(&RnrContext->ListEntry); + + /* Release the lock */ + ReleaseRnR2Lock(); + + /* Deallocated any cached Hostent */ + if(RnrContext->CachedSaBlob) SaBlob_Free(RnrContext->CachedSaBlob); + + /* Deallocate the Blob */ + if(RnrContext->CachedBlob.pBlobData) + { + DnsApiFree(RnrContext->CachedBlob.pBlobData); + } + + /* Deallocate the actual context itself */ + DnsApiFree(RnrContext); + } + else + { + /* Release the lock */ + ReleaseRnR2Lock(); + } +} + +PRNR_CONTEXT +WSPAPI +RnrCtx_Get(HANDLE LookupHandle, + DWORD dwControlFlags, + PLONG Instance) +{ + PLIST_ENTRY Entry; + PRNR_CONTEXT RnRContext = NULL; + + /* Acquire the lock */ + AcquireRnR2Lock(); + + /* Loop the RNR Context List */ + for(Entry = ListAnchor.Flink; Entry != &ListAnchor; Entry = Entry->Flink) + { + /* Get the Current RNR Context */ + RnRContext = CONTAINING_RECORD(Entry, RNR_CONTEXT, ListEntry); + + /* Check if it matches the one we got */ + if(RnRContext == (PRNR_CONTEXT)LookupHandle) break; + } + + /* If we found it, mark it in use */ + if(RnRContext) RnRContext->RefCount++; + + /* Increase the Instance and return it */ + *Instance = ++RnRContext->Instance; + + /* If we're flushing the previous one, then bias the Instance by one */ + if(dwControlFlags & LUP_FLUSHPREVIOUS) *Instance = ++RnRContext->Instance; + + /* Release the lock */ + ReleaseRnR2Lock(); + + /* Return the Context */ + return RnRContext; +} + +VOID +WSPAPI +RnrCtx_DecInstance(IN PRNR_CONTEXT RnrContext) +{ + /* Acquire the lock */ + AcquireRnR2Lock(); + + /* Decrease instance count */ + RnrContext->Instance--; + + /* Release the lock */ + ReleaseRnR2Lock(); +} + +VOID +WSPAPI +RnrCtx_ListCleanup(VOID) +{ + PLIST_ENTRY Entry; + + /* Acquire RnR Lock */ + AcquireRnR2Lock(); + + /* Loop the contexts */ + while ((Entry = ListAnchor.Flink) != &ListAnchor) + { + /* Release this context */ + RnrCtx_Release(CONTAINING_RECORD(Entry, RNR_CONTEXT, ListEntry)); + } + + /* Release lock */ + ReleaseRnR2Lock(); +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +LIST_ENTRY ListAnchor; +BOOLEAN g_fRnrLockInit; +CRITICAL_SECTION g_RnrLock; + +#define AcquireRnR2Lock() EnterCriticalSection(&g_RnrLock); +#define ReleaseRnR2Lock() LeaveCriticalSection(&g_RnrLock); + +/* FUNCTIONS *****************************************************************/ + +PRNR_CONTEXT +WSPAPI +RnrCtx_Create(IN HANDLE LookupHandle, + IN LPWSTR ServiceName) +{ + PRNR_CONTEXT RnrContext; + SIZE_T StringSize = 0; + + /* Get the size of the string */ + if (ServiceName) StringSize = wcslen(ServiceName); + + /* Allocate the Context */ + RnrContext = Temp_AllocZero(sizeof(RNR_CONTEXT) + (DWORD)StringSize); + + /* Check that we got one */ + if (RnrContext) + { + /* Set it up */ + RnrContext->RefCount = 2; + RnrContext->Handle = (LookupHandle ? LookupHandle : (HANDLE)RnrContext); + RnrContext->Instance = -1; + RnrContext->Signature = 0xaabbccdd; + wcscpy(RnrContext->ServiceName, ServiceName); + + /* Insert it into the list */ + AcquireRnR2Lock(); + InsertHeadList(&ListAnchor, &RnrContext->ListEntry); + ReleaseRnR2Lock(); + } + + /* Return it */ + return RnrContext; +} + +VOID +WSPAPI +RnrCtx_Release(PRNR_CONTEXT RnrContext) +{ + /* Acquire the lock */ + AcquireRnR2Lock(); + + /* Decrease reference count and check if it's still in use */ + if(!(--RnrContext->RefCount)) + { + /* Remove it from the List */ + RemoveEntryList(&RnrContext->ListEntry); + + /* Release the lock */ + ReleaseRnR2Lock(); + + /* Deallocated any cached Hostent */ + if(RnrContext->CachedSaBlob) SaBlob_Free(RnrContext->CachedSaBlob); + + /* Deallocate the Blob */ + if(RnrContext->CachedBlob.pBlobData) + { + DnsApiFree(RnrContext->CachedBlob.pBlobData); + } + + /* Deallocate the actual context itself */ + DnsApiFree(RnrContext); + } + else + { + /* Release the lock */ + ReleaseRnR2Lock(); + } +} + +PRNR_CONTEXT +WSPAPI +RnrCtx_Get(HANDLE LookupHandle, + DWORD dwControlFlags, + PLONG Instance) +{ + PLIST_ENTRY Entry; + PRNR_CONTEXT RnRContext = NULL; + + /* Acquire the lock */ + AcquireRnR2Lock(); + + /* Loop the RNR Context List */ + for(Entry = ListAnchor.Flink; Entry != &ListAnchor; Entry = Entry->Flink) + { + /* Get the Current RNR Context */ + RnRContext = CONTAINING_RECORD(Entry, RNR_CONTEXT, ListEntry); + + /* Check if it matches the one we got */ + if(RnRContext == (PRNR_CONTEXT)LookupHandle) break; + } + + /* If we found it, mark it in use */ + if(RnRContext) RnRContext->RefCount++; + + /* Increase the Instance and return it */ + *Instance = ++RnRContext->Instance; + + /* If we're flushing the previous one, then bias the Instance by one */ + if(dwControlFlags & LUP_FLUSHPREVIOUS) *Instance = ++RnRContext->Instance; + + /* Release the lock */ + ReleaseRnR2Lock(); + + /* Return the Context */ + return RnRContext; +} + +VOID +WSPAPI +RnrCtx_DecInstance(IN PRNR_CONTEXT RnrContext) +{ + /* Acquire the lock */ + AcquireRnR2Lock(); + + /* Decrease instance count */ + RnrContext->Instance--; + + /* Release the lock */ + ReleaseRnR2Lock(); +} + +VOID +WSPAPI +RnrCtx_ListCleanup(VOID) +{ + PLIST_ENTRY Entry; + + /* Acquire RnR Lock */ + AcquireRnR2Lock(); + + /* Loop the contexts */ + while ((Entry = ListAnchor.Flink) != &ListAnchor) + { + /* Release this context */ + RnrCtx_Release(CONTAINING_RECORD(Entry, RNR_CONTEXT, ListEntry)); + } + + /* Release lock */ + ReleaseRnR2Lock(); +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +LIST_ENTRY ListAnchor; +BOOLEAN g_fRnrLockInit; +CRITICAL_SECTION g_RnrLock; + +#define AcquireRnR2Lock() EnterCriticalSection(&g_RnrLock); +#define ReleaseRnR2Lock() LeaveCriticalSection(&g_RnrLock); + +/* FUNCTIONS *****************************************************************/ + +PRNR_CONTEXT +WSPAPI +RnrCtx_Create(IN HANDLE LookupHandle, + IN LPWSTR ServiceName) +{ + PRNR_CONTEXT RnrContext; + SIZE_T StringSize = 0; + + /* Get the size of the string */ + if (ServiceName) StringSize = wcslen(ServiceName); + + /* Allocate the Context */ + RnrContext = Temp_AllocZero(sizeof(RNR_CONTEXT) + (DWORD)StringSize); + + /* Check that we got one */ + if (RnrContext) + { + /* Set it up */ + RnrContext->RefCount = 2; + RnrContext->Handle = (LookupHandle ? LookupHandle : (HANDLE)RnrContext); + RnrContext->Instance = -1; + RnrContext->Signature = 0xaabbccdd; + wcscpy(RnrContext->ServiceName, ServiceName); + + /* Insert it into the list */ + AcquireRnR2Lock(); + InsertHeadList(&ListAnchor, &RnrContext->ListEntry); + ReleaseRnR2Lock(); + } + + /* Return it */ + return RnrContext; +} + +VOID +WSPAPI +RnrCtx_Release(PRNR_CONTEXT RnrContext) +{ + /* Acquire the lock */ + AcquireRnR2Lock(); + + /* Decrease reference count and check if it's still in use */ + if(!(--RnrContext->RefCount)) + { + /* Remove it from the List */ + RemoveEntryList(&RnrContext->ListEntry); + + /* Release the lock */ + ReleaseRnR2Lock(); + + /* Deallocated any cached Hostent */ + if(RnrContext->CachedSaBlob) SaBlob_Free(RnrContext->CachedSaBlob); + + /* Deallocate the Blob */ + if(RnrContext->CachedBlob.pBlobData) + { + DnsApiFree(RnrContext->CachedBlob.pBlobData); + } + + /* Deallocate the actual context itself */ + DnsApiFree(RnrContext); + } + else + { + /* Release the lock */ + ReleaseRnR2Lock(); + } +} + +PRNR_CONTEXT +WSPAPI +RnrCtx_Get(HANDLE LookupHandle, + DWORD dwControlFlags, + PLONG Instance) +{ + PLIST_ENTRY Entry; + PRNR_CONTEXT RnRContext = NULL; + + /* Acquire the lock */ + AcquireRnR2Lock(); + + /* Loop the RNR Context List */ + for(Entry = ListAnchor.Flink; Entry != &ListAnchor; Entry = Entry->Flink) + { + /* Get the Current RNR Context */ + RnRContext = CONTAINING_RECORD(Entry, RNR_CONTEXT, ListEntry); + + /* Check if it matches the one we got */ + if(RnRContext == (PRNR_CONTEXT)LookupHandle) break; + } + + /* If we found it, mark it in use */ + if(RnRContext) RnRContext->RefCount++; + + /* Increase the Instance and return it */ + *Instance = ++RnRContext->Instance; + + /* If we're flushing the previous one, then bias the Instance by one */ + if(dwControlFlags & LUP_FLUSHPREVIOUS) *Instance = ++RnRContext->Instance; + + /* Release the lock */ + ReleaseRnR2Lock(); + + /* Return the Context */ + return RnRContext; +} + +VOID +WSPAPI +RnrCtx_DecInstance(IN PRNR_CONTEXT RnrContext) +{ + /* Acquire the lock */ + AcquireRnR2Lock(); + + /* Decrease instance count */ + RnrContext->Instance--; + + /* Release the lock */ + ReleaseRnR2Lock(); +} + +VOID +WSPAPI +RnrCtx_ListCleanup(VOID) +{ + PLIST_ENTRY Entry; + + /* Acquire RnR Lock */ + AcquireRnR2Lock(); + + /* Loop the contexts */ + while ((Entry = ListAnchor.Flink) != &ListAnchor) + { + /* Release this context */ + RnrCtx_Release(CONTAINING_RECORD(Entry, RNR_CONTEXT, ListEntry)); + } + + /* Release lock */ + ReleaseRnR2Lock(); +} + diff --git a/dll/win32/mswsock/rnr20/getserv.c b/dll/win32/mswsock/rnr20/getserv.c new file mode 100644 index 00000000000..40d1f1bccaf --- /dev/null +++ b/dll/win32/mswsock/rnr20/getserv.c @@ -0,0 +1,40 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + diff --git a/dll/win32/mswsock/rnr20/init.c b/dll/win32/mswsock/rnr20/init.c new file mode 100644 index 00000000000..e313bd18021 --- /dev/null +++ b/dll/win32/mswsock/rnr20/init.c @@ -0,0 +1,356 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +BOOLEAN g_fSocketLockInit; +CRITICAL_SECTION RNRPROV_SocketLock; + +/* FUNCTIONS *****************************************************************/ + +VOID +WSPAPI +Rnr_ProcessInit(VOID) +{ + /* Initialize the RnR Locks */ + InitializeCriticalSection(&RNRPROV_SocketLock); + g_fSocketLockInit = TRUE; + InitializeCriticalSection(&g_RnrLock); + g_fRnrLockInit = TRUE; +} + +BOOLEAN +WSPAPI +Rnr_ThreadInit(VOID) +{ + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + PRNR_TEB_DATA RnrThreadData; + + /* Check if we have Thread Data */ + if (!ThreadData) + { + /* Initialize the entire DLL */ + if (!MSAFD_SockThreadInitialize()) return FALSE; + } + + /* Allocate the thread data */ + RnrThreadData = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + sizeof(RNR_TEB_DATA)); + if (RnrThreadData) + { + /* Zero it out */ + RtlZeroMemory(RnrThreadData, sizeof(RNR_TEB_DATA)); + + /* Link it */ + ThreadData->RnrThreadData = RnrThreadData; + + /* Return success */ + return TRUE; + } + + /* If we got here, we failed */ + return FALSE; +} + +VOID +WSPAPI +Rnr_ProcessCleanup(VOID) +{ + /* Check if the RnR Lock is initalized */ + if (g_fRnrLockInit) + { + /* It is, so do NSP cleanup */ + Nsp_GlobalCleanup(); + + /* Free the lock if it's still there */ + if (g_fSocketLockInit) DeleteCriticalSection(&g_RnrLock); + g_fRnrLockInit = FALSE; + } + + /* Free the socket lock if it's there */ + if (g_fSocketLockInit) DeleteCriticalSection(&RNRPROV_SocketLock); + g_fRnrLockInit = FALSE; +} + +VOID +WSPAPI +Rnr_ThreadCleanup(VOID) +{ + /* Clean something in the TEB.. */ +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +BOOLEAN g_fSocketLockInit; +CRITICAL_SECTION RNRPROV_SocketLock; + +/* FUNCTIONS *****************************************************************/ + +VOID +WSPAPI +Rnr_ProcessInit(VOID) +{ + /* Initialize the RnR Locks */ + InitializeCriticalSection(&RNRPROV_SocketLock); + g_fSocketLockInit = TRUE; + InitializeCriticalSection(&g_RnrLock); + g_fRnrLockInit = TRUE; +} + +BOOLEAN +WSPAPI +Rnr_ThreadInit(VOID) +{ + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + PRNR_TEB_DATA RnrThreadData; + + /* Check if we have Thread Data */ + if (!ThreadData) + { + /* Initialize the entire DLL */ + if (!MSAFD_SockThreadInitialize()) return FALSE; + } + + /* Allocate the thread data */ + RnrThreadData = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + sizeof(RNR_TEB_DATA)); + if (RnrThreadData) + { + /* Zero it out */ + RtlZeroMemory(RnrThreadData, sizeof(RNR_TEB_DATA)); + + /* Link it */ + ThreadData->RnrThreadData = RnrThreadData; + + /* Return success */ + return TRUE; + } + + /* If we got here, we failed */ + return FALSE; +} + +VOID +WSPAPI +Rnr_ProcessCleanup(VOID) +{ + /* Check if the RnR Lock is initalized */ + if (g_fRnrLockInit) + { + /* It is, so do NSP cleanup */ + Nsp_GlobalCleanup(); + + /* Free the lock if it's still there */ + if (g_fSocketLockInit) DeleteCriticalSection(&g_RnrLock); + g_fRnrLockInit = FALSE; + } + + /* Free the socket lock if it's there */ + if (g_fSocketLockInit) DeleteCriticalSection(&RNRPROV_SocketLock); + g_fRnrLockInit = FALSE; +} + +VOID +WSPAPI +Rnr_ThreadCleanup(VOID) +{ + /* Clean something in the TEB.. */ +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +BOOLEAN g_fSocketLockInit; +CRITICAL_SECTION RNRPROV_SocketLock; + +/* FUNCTIONS *****************************************************************/ + +VOID +WSPAPI +Rnr_ProcessInit(VOID) +{ + /* Initialize the RnR Locks */ + InitializeCriticalSection(&RNRPROV_SocketLock); + g_fSocketLockInit = TRUE; + InitializeCriticalSection(&g_RnrLock); + g_fRnrLockInit = TRUE; +} + +BOOLEAN +WSPAPI +Rnr_ThreadInit(VOID) +{ + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + PRNR_TEB_DATA RnrThreadData; + + /* Check if we have Thread Data */ + if (!ThreadData) + { + /* Initialize the entire DLL */ + if (!MSAFD_SockThreadInitialize()) return FALSE; + } + + /* Allocate the thread data */ + RnrThreadData = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + sizeof(RNR_TEB_DATA)); + if (RnrThreadData) + { + /* Zero it out */ + RtlZeroMemory(RnrThreadData, sizeof(RNR_TEB_DATA)); + + /* Link it */ + ThreadData->RnrThreadData = RnrThreadData; + + /* Return success */ + return TRUE; + } + + /* If we got here, we failed */ + return FALSE; +} + +VOID +WSPAPI +Rnr_ProcessCleanup(VOID) +{ + /* Check if the RnR Lock is initalized */ + if (g_fRnrLockInit) + { + /* It is, so do NSP cleanup */ + Nsp_GlobalCleanup(); + + /* Free the lock if it's still there */ + if (g_fSocketLockInit) DeleteCriticalSection(&g_RnrLock); + g_fRnrLockInit = FALSE; + } + + /* Free the socket lock if it's there */ + if (g_fSocketLockInit) DeleteCriticalSection(&RNRPROV_SocketLock); + g_fRnrLockInit = FALSE; +} + +VOID +WSPAPI +Rnr_ThreadCleanup(VOID) +{ + /* Clean something in the TEB.. */ +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +BOOLEAN g_fSocketLockInit; +CRITICAL_SECTION RNRPROV_SocketLock; + +/* FUNCTIONS *****************************************************************/ + +VOID +WSPAPI +Rnr_ProcessInit(VOID) +{ + /* Initialize the RnR Locks */ + InitializeCriticalSection(&RNRPROV_SocketLock); + g_fSocketLockInit = TRUE; + InitializeCriticalSection(&g_RnrLock); + g_fRnrLockInit = TRUE; +} + +BOOLEAN +WSPAPI +Rnr_ThreadInit(VOID) +{ + PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; + PRNR_TEB_DATA RnrThreadData; + + /* Check if we have Thread Data */ + if (!ThreadData) + { + /* Initialize the entire DLL */ + if (!MSAFD_SockThreadInitialize()) return FALSE; + } + + /* Allocate the thread data */ + RnrThreadData = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + sizeof(RNR_TEB_DATA)); + if (RnrThreadData) + { + /* Zero it out */ + RtlZeroMemory(RnrThreadData, sizeof(RNR_TEB_DATA)); + + /* Link it */ + ThreadData->RnrThreadData = RnrThreadData; + + /* Return success */ + return TRUE; + } + + /* If we got here, we failed */ + return FALSE; +} + +VOID +WSPAPI +Rnr_ProcessCleanup(VOID) +{ + /* Check if the RnR Lock is initalized */ + if (g_fRnrLockInit) + { + /* It is, so do NSP cleanup */ + Nsp_GlobalCleanup(); + + /* Free the lock if it's still there */ + if (g_fSocketLockInit) DeleteCriticalSection(&g_RnrLock); + g_fRnrLockInit = FALSE; + } + + /* Free the socket lock if it's there */ + if (g_fSocketLockInit) DeleteCriticalSection(&RNRPROV_SocketLock); + g_fRnrLockInit = FALSE; +} + +VOID +WSPAPI +Rnr_ThreadCleanup(VOID) +{ + /* Clean something in the TEB.. */ +} + diff --git a/dll/win32/mswsock/rnr20/logit.c b/dll/win32/mswsock/rnr20/logit.c new file mode 100644 index 00000000000..40d1f1bccaf --- /dev/null +++ b/dll/win32/mswsock/rnr20/logit.c @@ -0,0 +1,40 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + diff --git a/dll/win32/mswsock/rnr20/lookup.c b/dll/win32/mswsock/rnr20/lookup.c new file mode 100644 index 00000000000..3f8e7198a6f --- /dev/null +++ b/dll/win32/mswsock/rnr20/lookup.c @@ -0,0 +1,1436 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +extern DWORD MaskOfGuids; +extern GUID NbtProviderId; + +/* FUNCTIONS *****************************************************************/ + +PDNS_BLOB +WINAPI +Rnr_DoHostnameLookup(IN PRNR_CONTEXT RnrContext) +{ + INT ErrorCode; + LPWSTR LocalName; + PDNS_BLOB Blob = NULL; + + /* Query the Local Hostname */ + DnsQueryConfig(DnsConfigHostName_W, + DNS_CONFIG_FLAG_ALLOC, + NULL, + NULL, + &LocalName, + 0); + if (!LocalName) + { + /* Set error code if we got "Success" */ + ErrorCode = GetLastError(); + if (ErrorCode == NO_ERROR) ErrorCode = ERROR_OUTOFMEMORY; + goto Fail; + } + + /* Create a Blob */ + Blob = SaBlob_Create(0); + if (!Blob) + { + /* Set error code if we got "Success" */ + ErrorCode = GetLastError(); + if (ErrorCode == NO_ERROR) ErrorCode = ERROR_OUTOFMEMORY; + goto Fail; + } + + /* Write the name */ + ErrorCode = SaBlob_WriteNameOrAlias(Blob, LocalName, FALSE); + if (ErrorCode != NO_ERROR) goto Fail; + + /* Free the name and return the blob */ + DnsApiFree(LocalName); + return Blob; + +Fail: + /* Some kind of failure... delete the blob first */ + if (Blob) SaBlob_Free(Blob); + + /* Free the name */ + DnsApiFree(LocalName); + + /* Set the error and fail */ + SetLastError(ErrorCode); + return NULL; +} + +PDNS_BLOB +WINAPI +Rnr_GetHostByAddr(IN PRNR_CONTEXT RnrContext) +{ + BOOLEAN Prolog; + PDNS_BLOB Blob = NULL; + INT ErrorCode = ERROR_SUCCESS; + DWORD ControlFlags = RnrContext->dwControlFlags; + IN6_ADDR Address; + ULONG AddressSize = sizeof(IN6_ADDR); + DWORD AddressFamily = AF_UNSPEC; + WCHAR ReverseAddress[256]; + + /* Enter the RNR Prolog */ + Prolog = RNRPROV_SockEnterApi(); + if (!Prolog) return NULL; + + /* Get an Address */ + Dns_StringToAddressW(&Address, + &AddressSize, + RnrContext->ServiceName, + &AddressFamily); + + /* Check the address family */ + if (AddressFamily == AF_INET) + { + /* Convert it to the IPv4 Reverse Name */ + Dns_Ip4AddressToReverseName_W(ReverseAddress, *(PIN_ADDR)&Address); + } + else if (AddressFamily == AF_INET6) + { + /* Convert it to the IPv6 Reverse Name */ + Dns_Ip6AddressToReverseName_W(ReverseAddress, Address); + } + + /* Do the DNS Lookup */ + Blob = SaBlob_Query(ReverseAddress, + DNS_TYPE_PTR, + (ControlFlags & LUP_FLUSHCACHE) ? + DNS_QUERY_BYPASS_CACHE : + DNS_QUERY_STANDARD, + NULL, + AddressFamily); + if (!Blob) + { + /* If this is IPv4... */ + if (AddressFamily == AF_INET) + { + /* Can we try NBT? */ + if (Rnr_CheckIfUseNbt(RnrContext)) + { + /* Do NBT Resolution */ + Blob = Rnr_NbtResolveAddr(*(PIN_ADDR)&Address); + } + } + + /* Do we still not have a blob? */ + if (!Blob) ErrorCode = WSANO_DATA; + } + + /* Set the error code and return */ + SetLastError(ErrorCode); + return Blob; +} + +PDNS_BLOB +WINAPI +Rnr_DoDnsLookup(IN PRNR_CONTEXT RnrContext) +{ + LPWSTR Name = RnrContext->ServiceName; + LPGUID Guid = &RnrContext->lpServiceClassId; + WORD DnsType; + PVOID ReservedData = NULL; + PVOID *Reserved = NULL; + BOOL DoDnsQuery = TRUE; + BOOL DoNbtQuery = TRUE; + DWORD DnsFlags; + PDNS_BLOB Blob; + IN_ADDR Addr; + + /* Get the DNS Query Type */ + DnsType = GetDnsQueryTypeFromGuid(Guid); + + /* Check the request type */ + if ((DnsType != DNS_TYPE_A) || + (DnsType != DNS_TYPE_ATMA) || + (DnsType != DNS_TYPE_AAAA) || + (DnsType != DNS_TYPE_PTR)) + { + /* Not a sockaddr request, so read the raw data */ + Reserved = &ReservedData; + } + + /* Check the NS request type */ + switch (RnrContext->dwNameSpace) + { + /* Set the DNS flags for a TCP/IP Local Namespace */ + case NS_TCPIP_LOCAL: + DnsFlags = DNS_QUERY_NO_HOSTS_FILE | DNS_QUERY_NO_WIRE_QUERY; + break; + + /* Set the DNS flags for a TCP/IP Hosts Namespace */ + case NS_TCPIP_HOSTS: + DnsFlags = DNS_QUERY_NO_LOCAL_NAME | + DNS_QUERY_NO_WIRE_QUERY | + DNS_QUERY_BYPASS_CACHE; + break; + + /* Default flags for default, DNS or WINS Namespaces */ + case NS_DNS: + case NS_WINS: + default: + DnsFlags = 0; + break; + } + + /* Check if this is a DNS Server lookup or normal host lookup */ + if (!(Name) && + (DnsType != DNS_TYPE_A) && + ((RnrContext->UdpPort == 53) || (RnrContext->TcpPort == 53))) + { + /* This is actually a DNS Server lookup */ + Name = L"..DnsServers"; + DnsFlags = DNS_QUERY_NO_HOSTS_FILE | + DNS_QUERY_NO_WIRE_QUERY | + DNS_QUERY_BYPASS_CACHE; + } + else + { + /* Normal name lookup */ + DnsFlags |= 0x4000000; + + /* Check which Rr Type this request is */ + if (RnrContext->RrType == 0x10000002) + { + /* + * Check if the previous value should be flushed or if this + * is a local lookup. + */ + if ((RnrContext->dwControlFlags & LUP_FLUSHPREVIOUS) && + (RnrContext->LookupFlags & LOCAL)) + { + /* Tell DNS not to use the Hosts file */ + DnsFlags |= DNS_QUERY_NO_HOSTS_FILE; + } + + /* Tell DNS that this is a ... request */ + DnsFlags |= 0x10000000; + } + } + + /* Check if flushing is enabled */ + if (RnrContext->dwControlFlags & LUP_FLUSHCACHE) + { + /* Bypass the Cache */ + DnsFlags |= DNS_QUERY_BYPASS_CACHE; + } + + /* Make sure we are going to to a DNS Query */ + if (DoDnsQuery) + { + /* Do the DNS Query */ + Blob = SaBlob_Query(Name, + DnsType, + DnsFlags, + Reserved, + 0); + + /* Check if we had reserved data */ + if (Reserved == &ReservedData) + { + /* Check if we need to use it */ + if (RnrContext->RnrId) + { + /* FIXME */ + //SaveAnswer( + } + + /* Free it */ + DnsApiFree(ReservedData); + } + } + + /* Ok, did we get a blob? */ + if (Blob) + { + /* We did..does it have not have name yet? */ + if (!Blob->Name) + { + /* It doesn't... was this a Hostname GUID? */ + if (!memcmp(Guid, &HostnameGuid, sizeof(GUID))) + { + /* Did we not get a name? */ + if (Name || *Name) + { + /* Then we must fail this request */ + SaBlob_Free(Blob); + Blob = NULL; + } + } + } + } + else if (DoNbtQuery) + { + /* Is this an IPv4 record? */ + if (DnsType == DNS_TYPE_A) + { + /* Check if we can use NBT, and use NBT to resolve it */ + if (Rnr_CheckIfUseNbt(RnrContext)) Blob = Rnr_NbtResolveName(Name); + } + else if (DnsType == DNS_TYPE_PTR) + { + /* IPv4 reverse address. Convert it */ + if (Dns_Ip4ReverseNameToAddress_W(&Addr, Name)) + { + /* Resolve it */ + Blob = Rnr_NbtResolveAddr(Addr); + } + } + } + + /* Do we not have a blob? Set the error code */ + if (!Blob) SetLastError(WSANO_ADDRESS); + + /* Return the blob */ + return Blob; +} + +BOOLEAN +WINAPI +Rnr_CheckIfUseNbt(PRNR_CONTEXT RnrContext) +{ + /* If an Rr ID was specified, don't use NBT */ + if (RnrContext->RrType) return FALSE; + + /* Check if we have more then one GUID */ + if (MaskOfGuids) + { + /* Compare this guy's GUID with the NBT Provider GUID */ + if (memcmp(&RnrContext->lpProviderId, + &NbtProviderId, + sizeof(GUID))) + { + /* Not NBT Guid */ + return FALSE; + } + } + + /* Is the DNS Namespace valid for NBT? */ + if ((RnrContext->dwNameSpace == NS_ALL) || + (RnrContext->dwNameSpace == NS_NETBT) || + (RnrContext->dwNameSpace == NS_WINS)) + { + /* Use NBT */ + return TRUE; + } + + /* Don't use NBT */ + return FALSE; +} + +PDNS_BLOB +WINAPI +Rnr_NbtResolveName(IN LPWSTR Name) +{ + /* + * Heh...right...NBT lookups...as if! + * Seriously, don't bother -- MS is considering to deprecate this + * in Vista SP1 or Blackcomb. If someone complains about this, please + * instruct them to deposit a very large check in my bank account... + * - AI 03/12/05 + */ + return NULL; +} + +PDNS_BLOB +WINAPI +Rnr_NbtResolveAddr(IN IN_ADDR Address) +{ + /* + * Heh...right...NBT lookups...as if! + * Seriously, don't bother -- MS is considering to deprecate this + * in Vista SP1 or Blackcomb. If someone complains about this, please + * instruct them to deposit a very large check in my bank account... + * - AI 03/12/05 + */ + return NULL; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +extern DWORD MaskOfGuids; +extern GUID NbtProviderId; + +/* FUNCTIONS *****************************************************************/ + +PDNS_BLOB +WINAPI +Rnr_DoHostnameLookup(IN PRNR_CONTEXT RnrContext) +{ + INT ErrorCode; + LPWSTR LocalName; + PDNS_BLOB Blob = NULL; + + /* Query the Local Hostname */ + DnsQueryConfig(DnsConfigHostName_W, + DNS_CONFIG_FLAG_ALLOC, + NULL, + NULL, + &LocalName, + 0); + if (!LocalName) + { + /* Set error code if we got "Success" */ + ErrorCode = GetLastError(); + if (ErrorCode == NO_ERROR) ErrorCode = ERROR_OUTOFMEMORY; + goto Fail; + } + + /* Create a Blob */ + Blob = SaBlob_Create(0); + if (!Blob) + { + /* Set error code if we got "Success" */ + ErrorCode = GetLastError(); + if (ErrorCode == NO_ERROR) ErrorCode = ERROR_OUTOFMEMORY; + goto Fail; + } + + /* Write the name */ + ErrorCode = SaBlob_WriteNameOrAlias(Blob, LocalName, FALSE); + if (ErrorCode != NO_ERROR) goto Fail; + + /* Free the name and return the blob */ + DnsApiFree(LocalName); + return Blob; + +Fail: + /* Some kind of failure... delete the blob first */ + if (Blob) SaBlob_Free(Blob); + + /* Free the name */ + DnsApiFree(LocalName); + + /* Set the error and fail */ + SetLastError(ErrorCode); + return NULL; +} + +PDNS_BLOB +WINAPI +Rnr_GetHostByAddr(IN PRNR_CONTEXT RnrContext) +{ + BOOLEAN Prolog; + PDNS_BLOB Blob = NULL; + INT ErrorCode = ERROR_SUCCESS; + DWORD ControlFlags = RnrContext->dwControlFlags; + IN6_ADDR Address; + ULONG AddressSize = sizeof(IN6_ADDR); + DWORD AddressFamily = AF_UNSPEC; + WCHAR ReverseAddress[256]; + + /* Enter the RNR Prolog */ + Prolog = RNRPROV_SockEnterApi(); + if (!Prolog) return NULL; + + /* Get an Address */ + Dns_StringToAddressW(&Address, + &AddressSize, + RnrContext->ServiceName, + &AddressFamily); + + /* Check the address family */ + if (AddressFamily == AF_INET) + { + /* Convert it to the IPv4 Reverse Name */ + Dns_Ip4AddressToReverseName_W(ReverseAddress, *(PIN_ADDR)&Address); + } + else if (AddressFamily == AF_INET6) + { + /* Convert it to the IPv6 Reverse Name */ + Dns_Ip6AddressToReverseName_W(ReverseAddress, Address); + } + + /* Do the DNS Lookup */ + Blob = SaBlob_Query(ReverseAddress, + DNS_TYPE_PTR, + (ControlFlags & LUP_FLUSHCACHE) ? + DNS_QUERY_BYPASS_CACHE : + DNS_QUERY_STANDARD, + NULL, + AddressFamily); + if (!Blob) + { + /* If this is IPv4... */ + if (AddressFamily == AF_INET) + { + /* Can we try NBT? */ + if (Rnr_CheckIfUseNbt(RnrContext)) + { + /* Do NBT Resolution */ + Blob = Rnr_NbtResolveAddr(*(PIN_ADDR)&Address); + } + } + + /* Do we still not have a blob? */ + if (!Blob) ErrorCode = WSANO_DATA; + } + + /* Set the error code and return */ + SetLastError(ErrorCode); + return Blob; +} + +PDNS_BLOB +WINAPI +Rnr_DoDnsLookup(IN PRNR_CONTEXT RnrContext) +{ + LPWSTR Name = RnrContext->ServiceName; + LPGUID Guid = &RnrContext->lpServiceClassId; + WORD DnsType; + PVOID ReservedData = NULL; + PVOID *Reserved = NULL; + BOOL DoDnsQuery = TRUE; + BOOL DoNbtQuery = TRUE; + DWORD DnsFlags; + PDNS_BLOB Blob; + IN_ADDR Addr; + + /* Get the DNS Query Type */ + DnsType = GetDnsQueryTypeFromGuid(Guid); + + /* Check the request type */ + if ((DnsType != DNS_TYPE_A) || + (DnsType != DNS_TYPE_ATMA) || + (DnsType != DNS_TYPE_AAAA) || + (DnsType != DNS_TYPE_PTR)) + { + /* Not a sockaddr request, so read the raw data */ + Reserved = &ReservedData; + } + + /* Check the NS request type */ + switch (RnrContext->dwNameSpace) + { + /* Set the DNS flags for a TCP/IP Local Namespace */ + case NS_TCPIP_LOCAL: + DnsFlags = DNS_QUERY_NO_HOSTS_FILE | DNS_QUERY_NO_WIRE_QUERY; + break; + + /* Set the DNS flags for a TCP/IP Hosts Namespace */ + case NS_TCPIP_HOSTS: + DnsFlags = DNS_QUERY_NO_LOCAL_NAME | + DNS_QUERY_NO_WIRE_QUERY | + DNS_QUERY_BYPASS_CACHE; + break; + + /* Default flags for default, DNS or WINS Namespaces */ + case NS_DNS: + case NS_WINS: + default: + DnsFlags = 0; + break; + } + + /* Check if this is a DNS Server lookup or normal host lookup */ + if (!(Name) && + (DnsType != DNS_TYPE_A) && + ((RnrContext->UdpPort == 53) || (RnrContext->TcpPort == 53))) + { + /* This is actually a DNS Server lookup */ + Name = L"..DnsServers"; + DnsFlags = DNS_QUERY_NO_HOSTS_FILE | + DNS_QUERY_NO_WIRE_QUERY | + DNS_QUERY_BYPASS_CACHE; + } + else + { + /* Normal name lookup */ + DnsFlags |= 0x4000000; + + /* Check which Rr Type this request is */ + if (RnrContext->RrType == 0x10000002) + { + /* + * Check if the previous value should be flushed or if this + * is a local lookup. + */ + if ((RnrContext->dwControlFlags & LUP_FLUSHPREVIOUS) && + (RnrContext->LookupFlags & LOCAL)) + { + /* Tell DNS not to use the Hosts file */ + DnsFlags |= DNS_QUERY_NO_HOSTS_FILE; + } + + /* Tell DNS that this is a ... request */ + DnsFlags |= 0x10000000; + } + } + + /* Check if flushing is enabled */ + if (RnrContext->dwControlFlags & LUP_FLUSHCACHE) + { + /* Bypass the Cache */ + DnsFlags |= DNS_QUERY_BYPASS_CACHE; + } + + /* Make sure we are going to to a DNS Query */ + if (DoDnsQuery) + { + /* Do the DNS Query */ + Blob = SaBlob_Query(Name, + DnsType, + DnsFlags, + Reserved, + 0); + + /* Check if we had reserved data */ + if (Reserved == &ReservedData) + { + /* Check if we need to use it */ + if (RnrContext->RnrId) + { + /* FIXME */ + //SaveAnswer( + } + + /* Free it */ + DnsApiFree(ReservedData); + } + } + + /* Ok, did we get a blob? */ + if (Blob) + { + /* We did..does it have not have name yet? */ + if (!Blob->Name) + { + /* It doesn't... was this a Hostname GUID? */ + if (!memcmp(Guid, &HostnameGuid, sizeof(GUID))) + { + /* Did we not get a name? */ + if (Name || *Name) + { + /* Then we must fail this request */ + SaBlob_Free(Blob); + Blob = NULL; + } + } + } + } + else if (DoNbtQuery) + { + /* Is this an IPv4 record? */ + if (DnsType == DNS_TYPE_A) + { + /* Check if we can use NBT, and use NBT to resolve it */ + if (Rnr_CheckIfUseNbt(RnrContext)) Blob = Rnr_NbtResolveName(Name); + } + else if (DnsType == DNS_TYPE_PTR) + { + /* IPv4 reverse address. Convert it */ + if (Dns_Ip4ReverseNameToAddress_W(&Addr, Name)) + { + /* Resolve it */ + Blob = Rnr_NbtResolveAddr(Addr); + } + } + } + + /* Do we not have a blob? Set the error code */ + if (!Blob) SetLastError(WSANO_ADDRESS); + + /* Return the blob */ + return Blob; +} + +BOOLEAN +WINAPI +Rnr_CheckIfUseNbt(PRNR_CONTEXT RnrContext) +{ + /* If an Rr ID was specified, don't use NBT */ + if (RnrContext->RrType) return FALSE; + + /* Check if we have more then one GUID */ + if (MaskOfGuids) + { + /* Compare this guy's GUID with the NBT Provider GUID */ + if (memcmp(&RnrContext->lpProviderId, + &NbtProviderId, + sizeof(GUID))) + { + /* Not NBT Guid */ + return FALSE; + } + } + + /* Is the DNS Namespace valid for NBT? */ + if ((RnrContext->dwNameSpace == NS_ALL) || + (RnrContext->dwNameSpace == NS_NETBT) || + (RnrContext->dwNameSpace == NS_WINS)) + { + /* Use NBT */ + return TRUE; + } + + /* Don't use NBT */ + return FALSE; +} + +PDNS_BLOB +WINAPI +Rnr_NbtResolveName(IN LPWSTR Name) +{ + /* + * Heh...right...NBT lookups...as if! + * Seriously, don't bother -- MS is considering to deprecate this + * in Vista SP1 or Blackcomb. If someone complains about this, please + * instruct them to deposit a very large check in my bank account... + * - AI 03/12/05 + */ + return NULL; +} + +PDNS_BLOB +WINAPI +Rnr_NbtResolveAddr(IN IN_ADDR Address) +{ + /* + * Heh...right...NBT lookups...as if! + * Seriously, don't bother -- MS is considering to deprecate this + * in Vista SP1 or Blackcomb. If someone complains about this, please + * instruct them to deposit a very large check in my bank account... + * - AI 03/12/05 + */ + return NULL; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +extern DWORD MaskOfGuids; +extern GUID NbtProviderId; + +/* FUNCTIONS *****************************************************************/ + +PDNS_BLOB +WINAPI +Rnr_DoHostnameLookup(IN PRNR_CONTEXT RnrContext) +{ + INT ErrorCode; + LPWSTR LocalName; + PDNS_BLOB Blob = NULL; + + /* Query the Local Hostname */ + DnsQueryConfig(DnsConfigHostName_W, + DNS_CONFIG_FLAG_ALLOC, + NULL, + NULL, + &LocalName, + 0); + if (!LocalName) + { + /* Set error code if we got "Success" */ + ErrorCode = GetLastError(); + if (ErrorCode == NO_ERROR) ErrorCode = ERROR_OUTOFMEMORY; + goto Fail; + } + + /* Create a Blob */ + Blob = SaBlob_Create(0); + if (!Blob) + { + /* Set error code if we got "Success" */ + ErrorCode = GetLastError(); + if (ErrorCode == NO_ERROR) ErrorCode = ERROR_OUTOFMEMORY; + goto Fail; + } + + /* Write the name */ + ErrorCode = SaBlob_WriteNameOrAlias(Blob, LocalName, FALSE); + if (ErrorCode != NO_ERROR) goto Fail; + + /* Free the name and return the blob */ + DnsApiFree(LocalName); + return Blob; + +Fail: + /* Some kind of failure... delete the blob first */ + if (Blob) SaBlob_Free(Blob); + + /* Free the name */ + DnsApiFree(LocalName); + + /* Set the error and fail */ + SetLastError(ErrorCode); + return NULL; +} + +PDNS_BLOB +WINAPI +Rnr_GetHostByAddr(IN PRNR_CONTEXT RnrContext) +{ + BOOLEAN Prolog; + PDNS_BLOB Blob = NULL; + INT ErrorCode = ERROR_SUCCESS; + DWORD ControlFlags = RnrContext->dwControlFlags; + IN6_ADDR Address; + ULONG AddressSize = sizeof(IN6_ADDR); + DWORD AddressFamily = AF_UNSPEC; + WCHAR ReverseAddress[256]; + + /* Enter the RNR Prolog */ + Prolog = RNRPROV_SockEnterApi(); + if (!Prolog) return NULL; + + /* Get an Address */ + Dns_StringToAddressW(&Address, + &AddressSize, + RnrContext->ServiceName, + &AddressFamily); + + /* Check the address family */ + if (AddressFamily == AF_INET) + { + /* Convert it to the IPv4 Reverse Name */ + Dns_Ip4AddressToReverseName_W(ReverseAddress, *(PIN_ADDR)&Address); + } + else if (AddressFamily == AF_INET6) + { + /* Convert it to the IPv6 Reverse Name */ + Dns_Ip6AddressToReverseName_W(ReverseAddress, Address); + } + + /* Do the DNS Lookup */ + Blob = SaBlob_Query(ReverseAddress, + DNS_TYPE_PTR, + (ControlFlags & LUP_FLUSHCACHE) ? + DNS_QUERY_BYPASS_CACHE : + DNS_QUERY_STANDARD, + NULL, + AddressFamily); + if (!Blob) + { + /* If this is IPv4... */ + if (AddressFamily == AF_INET) + { + /* Can we try NBT? */ + if (Rnr_CheckIfUseNbt(RnrContext)) + { + /* Do NBT Resolution */ + Blob = Rnr_NbtResolveAddr(*(PIN_ADDR)&Address); + } + } + + /* Do we still not have a blob? */ + if (!Blob) ErrorCode = WSANO_DATA; + } + + /* Set the error code and return */ + SetLastError(ErrorCode); + return Blob; +} + +PDNS_BLOB +WINAPI +Rnr_DoDnsLookup(IN PRNR_CONTEXT RnrContext) +{ + LPWSTR Name = RnrContext->ServiceName; + LPGUID Guid = &RnrContext->lpServiceClassId; + WORD DnsType; + PVOID ReservedData = NULL; + PVOID *Reserved = NULL; + BOOL DoDnsQuery = TRUE; + BOOL DoNbtQuery = TRUE; + DWORD DnsFlags; + PDNS_BLOB Blob; + IN_ADDR Addr; + + /* Get the DNS Query Type */ + DnsType = GetDnsQueryTypeFromGuid(Guid); + + /* Check the request type */ + if ((DnsType != DNS_TYPE_A) || + (DnsType != DNS_TYPE_ATMA) || + (DnsType != DNS_TYPE_AAAA) || + (DnsType != DNS_TYPE_PTR)) + { + /* Not a sockaddr request, so read the raw data */ + Reserved = &ReservedData; + } + + /* Check the NS request type */ + switch (RnrContext->dwNameSpace) + { + /* Set the DNS flags for a TCP/IP Local Namespace */ + case NS_TCPIP_LOCAL: + DnsFlags = DNS_QUERY_NO_HOSTS_FILE | DNS_QUERY_NO_WIRE_QUERY; + break; + + /* Set the DNS flags for a TCP/IP Hosts Namespace */ + case NS_TCPIP_HOSTS: + DnsFlags = DNS_QUERY_NO_LOCAL_NAME | + DNS_QUERY_NO_WIRE_QUERY | + DNS_QUERY_BYPASS_CACHE; + break; + + /* Default flags for default, DNS or WINS Namespaces */ + case NS_DNS: + case NS_WINS: + default: + DnsFlags = 0; + break; + } + + /* Check if this is a DNS Server lookup or normal host lookup */ + if (!(Name) && + (DnsType != DNS_TYPE_A) && + ((RnrContext->UdpPort == 53) || (RnrContext->TcpPort == 53))) + { + /* This is actually a DNS Server lookup */ + Name = L"..DnsServers"; + DnsFlags = DNS_QUERY_NO_HOSTS_FILE | + DNS_QUERY_NO_WIRE_QUERY | + DNS_QUERY_BYPASS_CACHE; + } + else + { + /* Normal name lookup */ + DnsFlags |= 0x4000000; + + /* Check which Rr Type this request is */ + if (RnrContext->RrType == 0x10000002) + { + /* + * Check if the previous value should be flushed or if this + * is a local lookup. + */ + if ((RnrContext->dwControlFlags & LUP_FLUSHPREVIOUS) && + (RnrContext->LookupFlags & LOCAL)) + { + /* Tell DNS not to use the Hosts file */ + DnsFlags |= DNS_QUERY_NO_HOSTS_FILE; + } + + /* Tell DNS that this is a ... request */ + DnsFlags |= 0x10000000; + } + } + + /* Check if flushing is enabled */ + if (RnrContext->dwControlFlags & LUP_FLUSHCACHE) + { + /* Bypass the Cache */ + DnsFlags |= DNS_QUERY_BYPASS_CACHE; + } + + /* Make sure we are going to to a DNS Query */ + if (DoDnsQuery) + { + /* Do the DNS Query */ + Blob = SaBlob_Query(Name, + DnsType, + DnsFlags, + Reserved, + 0); + + /* Check if we had reserved data */ + if (Reserved == &ReservedData) + { + /* Check if we need to use it */ + if (RnrContext->RnrId) + { + /* FIXME */ + //SaveAnswer( + } + + /* Free it */ + DnsApiFree(ReservedData); + } + } + + /* Ok, did we get a blob? */ + if (Blob) + { + /* We did..does it have not have name yet? */ + if (!Blob->Name) + { + /* It doesn't... was this a Hostname GUID? */ + if (!memcmp(Guid, &HostnameGuid, sizeof(GUID))) + { + /* Did we not get a name? */ + if (Name || *Name) + { + /* Then we must fail this request */ + SaBlob_Free(Blob); + Blob = NULL; + } + } + } + } + else if (DoNbtQuery) + { + /* Is this an IPv4 record? */ + if (DnsType == DNS_TYPE_A) + { + /* Check if we can use NBT, and use NBT to resolve it */ + if (Rnr_CheckIfUseNbt(RnrContext)) Blob = Rnr_NbtResolveName(Name); + } + else if (DnsType == DNS_TYPE_PTR) + { + /* IPv4 reverse address. Convert it */ + if (Dns_Ip4ReverseNameToAddress_W(&Addr, Name)) + { + /* Resolve it */ + Blob = Rnr_NbtResolveAddr(Addr); + } + } + } + + /* Do we not have a blob? Set the error code */ + if (!Blob) SetLastError(WSANO_ADDRESS); + + /* Return the blob */ + return Blob; +} + +BOOLEAN +WINAPI +Rnr_CheckIfUseNbt(PRNR_CONTEXT RnrContext) +{ + /* If an Rr ID was specified, don't use NBT */ + if (RnrContext->RrType) return FALSE; + + /* Check if we have more then one GUID */ + if (MaskOfGuids) + { + /* Compare this guy's GUID with the NBT Provider GUID */ + if (memcmp(&RnrContext->lpProviderId, + &NbtProviderId, + sizeof(GUID))) + { + /* Not NBT Guid */ + return FALSE; + } + } + + /* Is the DNS Namespace valid for NBT? */ + if ((RnrContext->dwNameSpace == NS_ALL) || + (RnrContext->dwNameSpace == NS_NETBT) || + (RnrContext->dwNameSpace == NS_WINS)) + { + /* Use NBT */ + return TRUE; + } + + /* Don't use NBT */ + return FALSE; +} + +PDNS_BLOB +WINAPI +Rnr_NbtResolveName(IN LPWSTR Name) +{ + /* + * Heh...right...NBT lookups...as if! + * Seriously, don't bother -- MS is considering to deprecate this + * in Vista SP1 or Blackcomb. If someone complains about this, please + * instruct them to deposit a very large check in my bank account... + * - AI 03/12/05 + */ + return NULL; +} + +PDNS_BLOB +WINAPI +Rnr_NbtResolveAddr(IN IN_ADDR Address) +{ + /* + * Heh...right...NBT lookups...as if! + * Seriously, don't bother -- MS is considering to deprecate this + * in Vista SP1 or Blackcomb. If someone complains about this, please + * instruct them to deposit a very large check in my bank account... + * - AI 03/12/05 + */ + return NULL; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +extern DWORD MaskOfGuids; +extern GUID NbtProviderId; + +/* FUNCTIONS *****************************************************************/ + +PDNS_BLOB +WINAPI +Rnr_DoHostnameLookup(IN PRNR_CONTEXT RnrContext) +{ + INT ErrorCode; + LPWSTR LocalName; + PDNS_BLOB Blob = NULL; + + /* Query the Local Hostname */ + DnsQueryConfig(DnsConfigHostName_W, + DNS_CONFIG_FLAG_ALLOC, + NULL, + NULL, + &LocalName, + 0); + if (!LocalName) + { + /* Set error code if we got "Success" */ + ErrorCode = GetLastError(); + if (ErrorCode == NO_ERROR) ErrorCode = ERROR_OUTOFMEMORY; + goto Fail; + } + + /* Create a Blob */ + Blob = SaBlob_Create(0); + if (!Blob) + { + /* Set error code if we got "Success" */ + ErrorCode = GetLastError(); + if (ErrorCode == NO_ERROR) ErrorCode = ERROR_OUTOFMEMORY; + goto Fail; + } + + /* Write the name */ + ErrorCode = SaBlob_WriteNameOrAlias(Blob, LocalName, FALSE); + if (ErrorCode != NO_ERROR) goto Fail; + + /* Free the name and return the blob */ + DnsApiFree(LocalName); + return Blob; + +Fail: + /* Some kind of failure... delete the blob first */ + if (Blob) SaBlob_Free(Blob); + + /* Free the name */ + DnsApiFree(LocalName); + + /* Set the error and fail */ + SetLastError(ErrorCode); + return NULL; +} + +PDNS_BLOB +WINAPI +Rnr_GetHostByAddr(IN PRNR_CONTEXT RnrContext) +{ + BOOLEAN Prolog; + PDNS_BLOB Blob = NULL; + INT ErrorCode = ERROR_SUCCESS; + DWORD ControlFlags = RnrContext->dwControlFlags; + IN6_ADDR Address; + ULONG AddressSize = sizeof(IN6_ADDR); + DWORD AddressFamily = AF_UNSPEC; + WCHAR ReverseAddress[256]; + + /* Enter the RNR Prolog */ + Prolog = RNRPROV_SockEnterApi(); + if (!Prolog) return NULL; + + /* Get an Address */ + Dns_StringToAddressW(&Address, + &AddressSize, + RnrContext->ServiceName, + &AddressFamily); + + /* Check the address family */ + if (AddressFamily == AF_INET) + { + /* Convert it to the IPv4 Reverse Name */ + Dns_Ip4AddressToReverseName_W(ReverseAddress, *(PIN_ADDR)&Address); + } + else if (AddressFamily == AF_INET6) + { + /* Convert it to the IPv6 Reverse Name */ + Dns_Ip6AddressToReverseName_W(ReverseAddress, Address); + } + + /* Do the DNS Lookup */ + Blob = SaBlob_Query(ReverseAddress, + DNS_TYPE_PTR, + (ControlFlags & LUP_FLUSHCACHE) ? + DNS_QUERY_BYPASS_CACHE : + DNS_QUERY_STANDARD, + NULL, + AddressFamily); + if (!Blob) + { + /* If this is IPv4... */ + if (AddressFamily == AF_INET) + { + /* Can we try NBT? */ + if (Rnr_CheckIfUseNbt(RnrContext)) + { + /* Do NBT Resolution */ + Blob = Rnr_NbtResolveAddr(*(PIN_ADDR)&Address); + } + } + + /* Do we still not have a blob? */ + if (!Blob) ErrorCode = WSANO_DATA; + } + + /* Set the error code and return */ + SetLastError(ErrorCode); + return Blob; +} + +PDNS_BLOB +WINAPI +Rnr_DoDnsLookup(IN PRNR_CONTEXT RnrContext) +{ + LPWSTR Name = RnrContext->ServiceName; + LPGUID Guid = &RnrContext->lpServiceClassId; + WORD DnsType; + PVOID ReservedData = NULL; + PVOID *Reserved = NULL; + BOOL DoDnsQuery = TRUE; + BOOL DoNbtQuery = TRUE; + DWORD DnsFlags; + PDNS_BLOB Blob; + IN_ADDR Addr; + + /* Get the DNS Query Type */ + DnsType = GetDnsQueryTypeFromGuid(Guid); + + /* Check the request type */ + if ((DnsType != DNS_TYPE_A) || + (DnsType != DNS_TYPE_ATMA) || + (DnsType != DNS_TYPE_AAAA) || + (DnsType != DNS_TYPE_PTR)) + { + /* Not a sockaddr request, so read the raw data */ + Reserved = &ReservedData; + } + + /* Check the NS request type */ + switch (RnrContext->dwNameSpace) + { + /* Set the DNS flags for a TCP/IP Local Namespace */ + case NS_TCPIP_LOCAL: + DnsFlags = DNS_QUERY_NO_HOSTS_FILE | DNS_QUERY_NO_WIRE_QUERY; + break; + + /* Set the DNS flags for a TCP/IP Hosts Namespace */ + case NS_TCPIP_HOSTS: + DnsFlags = DNS_QUERY_NO_LOCAL_NAME | + DNS_QUERY_NO_WIRE_QUERY | + DNS_QUERY_BYPASS_CACHE; + break; + + /* Default flags for default, DNS or WINS Namespaces */ + case NS_DNS: + case NS_WINS: + default: + DnsFlags = 0; + break; + } + + /* Check if this is a DNS Server lookup or normal host lookup */ + if (!(Name) && + (DnsType != DNS_TYPE_A) && + ((RnrContext->UdpPort == 53) || (RnrContext->TcpPort == 53))) + { + /* This is actually a DNS Server lookup */ + Name = L"..DnsServers"; + DnsFlags = DNS_QUERY_NO_HOSTS_FILE | + DNS_QUERY_NO_WIRE_QUERY | + DNS_QUERY_BYPASS_CACHE; + } + else + { + /* Normal name lookup */ + DnsFlags |= 0x4000000; + + /* Check which Rr Type this request is */ + if (RnrContext->RrType == 0x10000002) + { + /* + * Check if the previous value should be flushed or if this + * is a local lookup. + */ + if ((RnrContext->dwControlFlags & LUP_FLUSHPREVIOUS) && + (RnrContext->LookupFlags & LOCAL)) + { + /* Tell DNS not to use the Hosts file */ + DnsFlags |= DNS_QUERY_NO_HOSTS_FILE; + } + + /* Tell DNS that this is a ... request */ + DnsFlags |= 0x10000000; + } + } + + /* Check if flushing is enabled */ + if (RnrContext->dwControlFlags & LUP_FLUSHCACHE) + { + /* Bypass the Cache */ + DnsFlags |= DNS_QUERY_BYPASS_CACHE; + } + + /* Make sure we are going to to a DNS Query */ + if (DoDnsQuery) + { + /* Do the DNS Query */ + Blob = SaBlob_Query(Name, + DnsType, + DnsFlags, + Reserved, + 0); + + /* Check if we had reserved data */ + if (Reserved == &ReservedData) + { + /* Check if we need to use it */ + if (RnrContext->RnrId) + { + /* FIXME */ + //SaveAnswer( + } + + /* Free it */ + DnsApiFree(ReservedData); + } + } + + /* Ok, did we get a blob? */ + if (Blob) + { + /* We did..does it have not have name yet? */ + if (!Blob->Name) + { + /* It doesn't... was this a Hostname GUID? */ + if (!memcmp(Guid, &HostnameGuid, sizeof(GUID))) + { + /* Did we not get a name? */ + if (Name || *Name) + { + /* Then we must fail this request */ + SaBlob_Free(Blob); + Blob = NULL; + } + } + } + } + else if (DoNbtQuery) + { + /* Is this an IPv4 record? */ + if (DnsType == DNS_TYPE_A) + { + /* Check if we can use NBT, and use NBT to resolve it */ + if (Rnr_CheckIfUseNbt(RnrContext)) Blob = Rnr_NbtResolveName(Name); + } + else if (DnsType == DNS_TYPE_PTR) + { + /* IPv4 reverse address. Convert it */ + if (Dns_Ip4ReverseNameToAddress_W(&Addr, Name)) + { + /* Resolve it */ + Blob = Rnr_NbtResolveAddr(Addr); + } + } + } + + /* Do we not have a blob? Set the error code */ + if (!Blob) SetLastError(WSANO_ADDRESS); + + /* Return the blob */ + return Blob; +} + +BOOLEAN +WINAPI +Rnr_CheckIfUseNbt(PRNR_CONTEXT RnrContext) +{ + /* If an Rr ID was specified, don't use NBT */ + if (RnrContext->RrType) return FALSE; + + /* Check if we have more then one GUID */ + if (MaskOfGuids) + { + /* Compare this guy's GUID with the NBT Provider GUID */ + if (memcmp(&RnrContext->lpProviderId, + &NbtProviderId, + sizeof(GUID))) + { + /* Not NBT Guid */ + return FALSE; + } + } + + /* Is the DNS Namespace valid for NBT? */ + if ((RnrContext->dwNameSpace == NS_ALL) || + (RnrContext->dwNameSpace == NS_NETBT) || + (RnrContext->dwNameSpace == NS_WINS)) + { + /* Use NBT */ + return TRUE; + } + + /* Don't use NBT */ + return FALSE; +} + +PDNS_BLOB +WINAPI +Rnr_NbtResolveName(IN LPWSTR Name) +{ + /* + * Heh...right...NBT lookups...as if! + * Seriously, don't bother -- MS is considering to deprecate this + * in Vista SP1 or Blackcomb. If someone complains about this, please + * instruct them to deposit a very large check in my bank account... + * - AI 03/12/05 + */ + return NULL; +} + +PDNS_BLOB +WINAPI +Rnr_NbtResolveAddr(IN IN_ADDR Address) +{ + /* + * Heh...right...NBT lookups...as if! + * Seriously, don't bother -- MS is considering to deprecate this + * in Vista SP1 or Blackcomb. If someone complains about this, please + * instruct them to deposit a very large check in my bank account... + * - AI 03/12/05 + */ + return NULL; +} + diff --git a/dll/win32/mswsock/rnr20/nbt.c b/dll/win32/mswsock/rnr20/nbt.c new file mode 100644 index 00000000000..3e062e90d63 --- /dev/null +++ b/dll/win32/mswsock/rnr20/nbt.c @@ -0,0 +1,56 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + diff --git a/dll/win32/mswsock/rnr20/nsp.c b/dll/win32/mswsock/rnr20/nsp.c new file mode 100644 index 00000000000..7c39fdad843 --- /dev/null +++ b/dll/win32/mswsock/rnr20/nsp.c @@ -0,0 +1,3776 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +#define ALL_LUP_FLAGS (0x0BFFF) + +/* DATA **********************************************************************/ + +LPWSTR g_pszHostName; +LPWSTR g_pszHostFqdn; +LONG g_NspRefCount; +GUID NbtProviderId = {0}; +GUID DNSProviderId = {0}; +DWORD MaskOfGuids; + +NSP_ROUTINE g_NspVector = {sizeof(NSP_ROUTINE), + 1, + 1, + Dns_NSPCleanup, + Dns_NSPLookupServiceBegin, + Dns_NSPLookupServiceNext, + Dns_NSPLookupServiceEnd, + Dns_NSPSetService, + Dns_NSPInstallServiceClass, + Dns_NSPRemoveServiceClass, + Dns_NSPGetServiceClassInfo}; + +/* FUNCTIONS *****************************************************************/ + +INT +WINAPI +Dns_NSPStartup(IN LPGUID lpProviderId, + IN OUT LPNSP_ROUTINE lpsnpRoutines) +{ + INT ErrorCode; + BOOLEAN Prolog; + + /* Validate the size */ + if (lpsnpRoutines->cbSize != sizeof(NSP_ROUTINE)) + { + /* Fail */ + SetLastError(WSAEINVALIDPROCTABLE); + return SOCKET_ERROR; + } + + /* Enter the prolog */ + Prolog = RNRPROV_SockEnterApi(); + if (Prolog) + { + /* Increase our reference count */ + InterlockedIncrement(&g_NspRefCount); + + /* Check if we don't have the hostname */ + if (!g_pszHostName) + { + /* Query it from DNS */ + DnsQueryConfig(DnsConfigHostName_W, + DNS_CONFIG_FLAG_ALLOC, + NULL, + NULL, + &g_pszHostName, + 0); + } + + /* Check if we have a hostname now, but not a Fully-Qualified Domain */ + if (g_pszHostName && !(g_pszHostFqdn)) + { + /* Get the domain from DNS */ + DnsQueryConfig(DnsConfigFullHostName_W, + DNS_CONFIG_FLAG_ALLOC, + NULL, + NULL, + &g_pszHostFqdn, + 0); + } + + /* If we don't have both of them, then set error */ + if (!(g_pszHostName) || !(g_pszHostFqdn)) ErrorCode = SOCKET_ERROR; + } + + /* Check if the Prolog or DNS Local Queries failed */ + if (!(Prolog) || (ErrorCode != NO_ERROR)) + { + /* Fail */ + SetLastError(WSASYSNOTREADY); + return SOCKET_ERROR; + } + + /* Copy the Routines */ + RtlMoveMemory(lpsnpRoutines, &g_NspVector, sizeof(NSP_ROUTINE)); + + /* Check if this is NBT or DNS */ + if (!memcmp(lpProviderId, &NbtProviderId, sizeof(GUID))) + { + /* Enable the NBT Mask */ + MaskOfGuids |= NBT_MASK; + } + else if (!memcmp(lpProviderId, &DNSProviderId, sizeof(GUID))) + { + /* Enable the DNS Mask */ + MaskOfGuids |= DNS_MASK; + } + + /* Return success */ + return NO_ERROR; +} + +VOID +WSPAPI +Nsp_GlobalCleanup(VOID) +{ + /* Cleanup the RnR Contexts */ + RnrCtx_ListCleanup(); + + /* Free the hostnames, if we have them */ + if (g_pszHostName) DnsApiFree(g_pszHostName); + if (g_pszHostFqdn) DnsApiFree(g_pszHostFqdn); + g_pszHostFqdn = g_pszHostName = NULL; +} + +INT +WINAPI +NSPStartup(IN LPGUID lpProviderId, + IN OUT LPNSP_ROUTINE lpsnpRoutines) +{ + INT ErrorCode; + + /* Initialize the DLL */ + ErrorCode = MSWSOCK_Initialize(); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + SetLastError(WSANOTINITIALISED); + return SOCKET_ERROR; + } + + /* Check if this is Winsock Mobile or DNS */ + if (!memcmp(lpProviderId, &gNLANamespaceGuid, sizeof(GUID))) + { + /* Initialize WSM */ + return WSM_NSPStartup(lpProviderId, lpsnpRoutines); + } + + /* Initialize DNS */ + return Dns_NSPStartup(lpProviderId, lpsnpRoutines); +} + +INT +WINAPI +Dns_NSPCleanup(IN LPGUID lpProviderId) +{ + /* Decrement our reference count and do global cleanup if it's reached 0 */ + if (!(InterlockedDecrement(&g_NspRefCount))) Nsp_GlobalCleanup(); + + /* Return success */ + return NO_ERROR; +} + +INT +WINAPI +Dns_NSPSetService(IN LPGUID lpProviderId, + IN LPWSASERVICECLASSINFOW lpServiceClassInfo, + IN LPWSAQUERYSETW lpqsRegInfo, + IN WSAESETSERVICEOP essOperation, + IN DWORD dwControlFlags) +{ + /* Unlike NLA, DNS Services cannot be dynmically modified */ + SetLastError(ERROR_NOT_SUPPORTED); + return SOCKET_ERROR; +} + +INT +WINAPI +Dns_NSPInstallServiceClass(IN LPGUID lpProviderId, + IN LPWSASERVICECLASSINFOW lpServiceClassInfo) +{ + /* Unlike NLA, DNS Services cannot be dynmically modified */ + SetLastError(WSAEOPNOTSUPP); + return SOCKET_ERROR; +}; + +INT +WINAPI +Dns_NSPRemoveServiceClass(IN LPGUID lpProviderId, + IN LPGUID lpServiceCallId) +{ + /* Unlike NLA, DNS Services cannot be dynmically modified */ + SetLastError(WSAEOPNOTSUPP); + return SOCKET_ERROR; +} +INT +WINAPI +Dns_NSPGetServiceClassInfo(IN LPGUID lpProviderId, + IN OUT LPDWORD lpdwBufSize, + IN OUT LPWSASERVICECLASSINFOW lpServiceClassInfo) +{ + /* Unlike NLA, DNS Services cannot be dynmically modified */ + SetLastError(WSAEOPNOTSUPP); + return SOCKET_ERROR; +} + +INT +WINAPI +Dns_NSPLookupServiceEnd(IN HANDLE hLookup) +{ + PRNR_CONTEXT RnrContext; + + /* Get this handle's context */ + RnrContext = RnrCtx_Get(hLookup, 0, NULL); + + /* Mark it as completed */ + RnrContext->LookupFlags |= DONE; + + /* Dereference it once for our _Get */ + RnrCtx_Release(RnrContext); + + /* And once last to delete it */ + RnrCtx_Release(RnrContext); + + /* return */ + return NO_ERROR; +} + +INT +WINAPI +rnr_IdForGuid(IN LPGUID Guid) +{ + + if (memcmp(Guid, &InetHostName, sizeof(GUID))) return 0x10000002; + if (memcmp(Guid, &Ipv6Guid, sizeof(GUID))) return 0x10000023; + if (memcmp(Guid, &HostnameGuid, sizeof(GUID))) return 0x1; + if (memcmp(Guid, &AddressGuid, sizeof(GUID))) return 0x80000000; + if (memcmp(Guid, &IANAGuid, sizeof(GUID))) return 0x2; + if IS_SVCID_DNS(Guid) return 0x5000000; + if IS_SVCID_TCP(Guid) return 0x1000000; + if IS_SVCID_UDP(Guid) return 0x2000000; + return 0; +} + +PVOID +WSPAPI +FlatBuf_ReserveAlignDword(IN PFLATBUFF FlatBuffer, + IN ULONG Size) +{ + /* Let DNSLIB do the grunt work */ + return FlatBuf_Arg_Reserve((PVOID)FlatBuffer->BufferPos, + &FlatBuffer->BufferFreeSize, + Size, + sizeof(PVOID)); +} + +PVOID +WSPAPI +FlatBuf_WriteString(IN PFLATBUFF FlatBuffer, + IN PVOID String, + IN BOOLEAN IsUnicode) +{ + /* Let DNSLIB do the grunt work */ + return FlatBuf_Arg_WriteString((PVOID)FlatBuffer->BufferPos, + &FlatBuffer->BufferFreeSize, + String, + IsUnicode); +} + +PVOID +WSPAPI +FlatBuf_CopyMemory(IN PFLATBUFF FlatBuffer, + IN PVOID Buffer, + IN ULONG Size, + IN ULONG Align) +{ + /* Let DNSLIB do the grunt work */ + return FlatBuf_Arg_CopyMemory((PVOID)FlatBuffer->BufferPos, + &FlatBuffer->BufferFreeSize, + Buffer, + Size, + Align); +} + +INT +WINAPI +Dns_NSPLookupServiceBegin(LPGUID lpProviderId, + LPWSAQUERYSETW lpqsRestrictions, + LPWSASERVICECLASSINFOW lpServiceClassInfo, + DWORD dwControlFlags, + LPHANDLE lphLookup) +{ + INT ErrorCode = SOCKET_ERROR; + PWCHAR ServiceName = lpqsRestrictions->lpszServiceInstanceName; + LPGUID ServiceClassId; + INT RnrId; + ULONG LookupFlags = 0; + BOOL NameRequested = FALSE; + WCHAR StringBuffer[48]; + ULONG i; + DWORD LocalProtocols; + ULONG ProtocolFlags; + PSERVENT LookupServent; + DWORD UdpPort, TcpPort; + PRNR_CONTEXT RnrContext; + PSOCKADDR_IN ReverseSock; + + /* Check if the Size isn't weird */ + if(lpqsRestrictions->dwSize < sizeof(WSAQUERYSETW)) + { + ErrorCode = WSAEFAULT; + goto Quickie; + } + + /* Get the GUID */ + ServiceClassId = lpqsRestrictions->lpServiceClassId; + if(!ServiceClassId) + { + /* No GUID, fail */ + ErrorCode = WSA_INVALID_PARAMETER; + goto Quickie; + } + + /* Get the RNR ID */ + RnrId = rnr_IdForGuid(ServiceClassId); + + /* Make sure that the control flags are valid */ + if ((dwControlFlags & ~ALL_LUP_FLAGS) || + ((dwControlFlags & (LUP_CONTAINERS | LUP_NOCONTAINERS)) == + (LUP_CONTAINERS | LUP_NOCONTAINERS))) + { + /* Either non-recognized flags or invalid combos were passed */ + ErrorCode = WSA_INVALID_PARAMETER; + goto Quickie; + } + + /* Make sure that we have no context, and that LUP_CONTAINERS is not on */ + if(((lpqsRestrictions->lpszContext) && + (*lpqsRestrictions->lpszContext) && + (wcscmp(lpqsRestrictions->lpszContext, L"\\"))) || + (dwControlFlags & LUP_CONTAINERS)) + { + /* We don't support contexts or LUP_CONTAINERS */ + ErrorCode = WSANO_DATA; + goto Quickie; + } + + /* Is this a Reverse Lookup? */ + if (RnrId == 0x80000000) + { + /* Remember for later */ + LookupFlags = REVERSE; + } + else + { + /* Is this a IANA Lookup? */ + if (RnrId == 0x2) + { + /* Mask out this flag since it's of no use now */ + dwControlFlags &= ~(LUP_RETURN_ADDR); + + /* This is a IANA lookup, remember for later */ + LookupFlags |= IANA; + } + + /* Check if we need a name or not */ + if ((RnrId == 0x1) || + (RnrId == 0x10000002) || + (RnrId == 0x10000023) || + (RnrId == 0x10000022)) + { + /* We do */ + NameRequested = TRUE; + } + } + + /* Final check to make sure if we need a name or not */ + if (RnrId & 0x3000000) NameRequested = TRUE; + + /* No Service Name was specified */ + if(!(ServiceName) || !(*ServiceName)) + { + /* + * A name was requested but no Service Name was given, + * so this is a local lookup + */ + if(NameRequested) + { + /* A local Lookup */ + LookupFlags |= LOCAL; + ServiceName = L""; + } + else if((LookupFlags & REVERSE) && + (lpqsRestrictions->lpcsaBuffer) && + (lpqsRestrictions->dwNumberOfCsAddrs == 1)) + { + /* Reverse lookup, make sure a CS Address is there */ + ReverseSock = (struct sockaddr_in*) + lpqsRestrictions->lpcsaBuffer->RemoteAddr.lpSockaddr; + + /* Convert address to Unicode */ + MultiByteToWideChar(CP_ACP, + 0, + inet_ntoa(ReverseSock->sin_addr), + -1, + StringBuffer, + 16); + + /* Set it as the new name */ + ServiceName = StringBuffer; + } + else + { + /* We can't do anything without a service name at this point */ + ErrorCode = WSA_INVALID_PARAMETER; + goto Quickie; + } + } + else if(NameRequested) + { + /* Check for meaningful DNS Names */ + if (DnsNameCompare_W(ServiceName, L"localhost") || + DnsNameCompare_W(ServiceName, L"loopback")) + { + /* This is the local and/or loopback DNS name */ + LookupFlags |= (LOCAL | LOOPBACK); + } + else if (DnsNameCompare_W(ServiceName, g_pszHostName) || + DnsNameCompare_W(ServiceName, g_pszHostFqdn)) + { + /* This is the local name of the computer */ + LookupFlags |= LOCAL; + } + } + + /* Check if any restrictions were made on the protocols */ + if(lpqsRestrictions->lpafpProtocols) + { + /* Save our local copy to speed up the loop */ + LocalProtocols = lpqsRestrictions->dwNumberOfProtocols; + ProtocolFlags = 0; + + /* Loop the protocols */ + for(i = 0; LocalProtocols--;) + { + /* Make sure it's a family that we recognize */ + if ((lpqsRestrictions->lpafpProtocols[i].iAddressFamily == AF_INET) || + (lpqsRestrictions->lpafpProtocols[i].iAddressFamily == AF_INET6) || + (lpqsRestrictions->lpafpProtocols[i].iAddressFamily == AF_UNSPEC) || + (lpqsRestrictions->lpafpProtocols[i].iAddressFamily == AF_ATM)) + { + /* Find which one is used */ + switch(lpqsRestrictions->lpafpProtocols[i].iProtocol) + { + case IPPROTO_UDP: + ProtocolFlags |= UDP; + break; + case IPPROTO_TCP: + ProtocolFlags |= TCP; + break; + case PF_ATM: + ProtocolFlags |= ATM; + break; + default: + break; + } + } + } + /* Make sure we have at least a valid protocol */ + if (!ProtocolFlags) + { + /* Fail */ + ErrorCode = WSANO_DATA; + goto Quickie; + } + } + else + { + /* No restrictions, assume TCP/UDP */ + ProtocolFlags = (TCP | UDP); + } + + /* Create the Servent from the Service String */ + UdpPort = TcpPort = -1; + ProtocolFlags |= GetServerAndProtocolsFromString(lpqsRestrictions->lpszQueryString, + ServiceClassId, + &LookupServent); + + /* Extract the port numbers */ + if(LookupServent) + { + /* Are we using UDP? */ + if(ProtocolFlags & UDP) + { + /* Get the UDP Port, disable the TCP Port */ + UdpPort = ntohs(LookupServent->s_port); + TcpPort = -1; + } + else if(ProtocolFlags & TCP) + { + /* Get the TCP Port, disable the UDP Port */ + TcpPort = ntohs(LookupServent->s_port); + UdpPort = -1; + } + } + else + { + /* No servent, so use the Service ID to check */ + if(ProtocolFlags & UDP) + { + /* Get the Port from the Service ID */ + UdpPort = FetchPortFromClassInfo(UDP, + ServiceClassId, + lpServiceClassInfo); + } + else + { + /* No UDP */ + UdpPort = -1; + } + + /* No servent, so use the Service ID to check */ + if(ProtocolFlags & TCP) + { + /* Get the Port from the Service ID */ + UdpPort = FetchPortFromClassInfo(TCP, + ServiceClassId, + lpServiceClassInfo); + } + else + { + /* No TCP */ + TcpPort = -1; + } + } + + /* Check if we still don't have a valid port by now */ + if((TcpPort == -1) && (UdpPort == -1)) + { + /* Check if this is TCP */ + if ((ProtocolFlags & TCP) || !(ProtocolFlags & UDP)) + { + /* Set the UDP Port to 0 */ + UdpPort = 0; + } + else + { + /* Set the TCP Port to 0 */ + TcpPort = 0; + } + } + + /* Allocate a Context for this Query */ + RnrContext = RnrCtx_Create(NULL, ServiceName); + RnrContext->lpServiceClassId = *ServiceClassId; + RnrContext->RnrId = RnrId; + RnrContext->dwControlFlags = dwControlFlags; + RnrContext->TcpPort = TcpPort; + RnrContext->UdpPort = UdpPort; + RnrContext->LookupFlags = LookupFlags; + RnrContext->lpProviderId = *lpProviderId; + RnrContext->dwNameSpace = lpqsRestrictions->dwNameSpace; + RnrCtx_Release(RnrContext); + + /* Return the context as a handle */ + *lphLookup = (HANDLE)RnrContext; + + /* Check if this was a TCP, UDP or DNS Query */ + if(RnrId & 0x3000000) + { + /* Get the RR Type from the Service ID */ + RnrContext->RrType = RR_FROM_SVCID(ServiceClassId); + } + + /* Return Success */ + ErrorCode = ERROR_SUCCESS; + +Quickie: + /* Check if we got here through a failure path */ + if (ErrorCode != ERROR_SUCCESS) + { + /* Set the last error and fail */ + SetLastError(ErrorCode); + return SOCKET_ERROR; + } + + /* Return success */ + return ERROR_SUCCESS; +} + +INT +WSPAPI +BuildCsAddr(IN LPWSAQUERYSETW QuerySet, + IN PFLATBUFF FlatBuffer, + IN PDNS_BLOB Blob, + IN DWORD UdpPort, + IN DWORD TcpPort, + IN BOOLEAN ReverseLookup) +{ + return WSANO_DATA; +} + +INT +WINAPI +Dns_NSPLookupServiceNext(IN HANDLE hLookup, + IN DWORD dwControlFlags, + IN OUT LPDWORD lpdwBufferLength, + OUT LPWSAQUERYSETW lpqsResults) +{ + INT ErrorCode; + WSAQUERYSETW LocalResults; + LONG Instance; + PRNR_CONTEXT RnrContext = NULL; + FLATBUFF FlatBuffer; + PVOID Name; + PDNS_BLOB Blob = NULL; + DWORD PortNumber; + PSERVENT ServEntry = NULL; + PDNS_ARRAY DnsArray; + BOOLEAN IsUnicode = TRUE; + SIZE_T FreeSize; + ULONG BlobSize; + ULONG_PTR Position; + PVOID BlobData = NULL; + ULONG StringLength; + LPWSTR UnicodeName; + + /* Make sure that the control flags are valid */ + if ((dwControlFlags & ~ALL_LUP_FLAGS) || + ((dwControlFlags & (LUP_CONTAINERS | LUP_NOCONTAINERS)) == + (LUP_CONTAINERS | LUP_NOCONTAINERS))) + { + /* Either non-recognized flags or invalid combos were passed */ + ErrorCode = WSA_INVALID_PARAMETER; + goto Quickie; + } + + /* Get the Context */ + RnrContext = RnrCtx_Get(hLookup, dwControlFlags, &Instance); + if (!RnrContext) + { + /* This lookup handle must be invalid */ + SetLastError(WSA_INVALID_HANDLE); + return SOCKET_ERROR; + } + + /* Assume success for now */ + SetLastError(NO_ERROR); + + /* Validate the query set size */ + if (*lpdwBufferLength < sizeof(WSAQUERYSETW)) + { + /* Windows doesn't fail, but sets up a local QS for you... */ + lpqsResults = &LocalResults; + ErrorCode = WSAEFAULT; + } + + /* Zero out the buffer and fill out basic data */ + RtlZeroMemory(lpqsResults, sizeof(WSAQUERYSETW)); + lpqsResults->dwNameSpace = NS_DNS; + lpqsResults->dwSize = sizeof(WSAQUERYSETW); + + /* Initialize the Buffer */ + FlatBuf_Init(&FlatBuffer, + lpqsResults + 1, + (ULONG)(*lpdwBufferLength - sizeof(WSAQUERYSETW))); + + /* Check if this is an IANA Lookup */ + if(RnrContext->LookupFlags & IANA) + { + /* Service Lookup */ + GetServerAndProtocolsFromString(RnrContext->ServiceName, + (LPGUID)&HostnameGuid, + &ServEntry); + + /* Get the Port */ + PortNumber = ntohs(ServEntry->s_port); + + /* Use this as the name */ + Name = ServEntry->s_name; + IsUnicode = FALSE; + + /* Override some parts of the Context and check for TCP/UDP */ + if(!_stricmp("tcp", ServEntry->s_proto)) + { + /* Set the TCP Guid */ + SET_TCP_SVCID(&RnrContext->lpServiceClassId, PortNumber); + RnrContext->TcpPort = PortNumber; + RnrContext->UdpPort = -1; + } + else + { + /* Set the UDP Guid */ + SET_UDP_SVCID(&RnrContext->lpServiceClassId, PortNumber); + RnrContext->UdpPort = PortNumber; + RnrContext->TcpPort = -1; + } + } + else + { + /* Check if the caller requested for RES_SERVICE */ + if(RnrContext->dwControlFlags & LUP_RES_SERVICE) + { + /* Make sure that this is the first instance */ + if (Instance) + { + /* Fail */ + ErrorCode = WSA_E_NO_MORE; + goto Quickie; + } + +#if 0 + /* Create the blob */ + DnsArray = NULL; + Blob = SaBlob_CreateFromIp4(RnrContext->ServiceName, + 1, + &DnsArray); +#else + /* FIXME */ + Blob = NULL; + DnsArray = NULL; + ErrorCode = WSAEFAULT; + goto Quickie; +#endif + } + else if(!(Blob = RnrContext->CachedSaBlob)) + { + /* An actual Host Lookup, but we don't have a cached HostEntry yet */ + if (!memcmp(&RnrContext->lpServiceClassId, + &HostnameGuid, + sizeof(GUID)) && !(RnrContext->ServiceName)) + { + /* Do a Regular DNS Lookup */ + Blob = Rnr_DoHostnameLookup(RnrContext); + } + else if (RnrContext->LookupFlags & REVERSE) + { + /* Do a Reverse DNS Lookup */ + Blob = Rnr_GetHostByAddr(RnrContext); + } + else + { + /* Do a Hostname Lookup */ + Blob = Rnr_DoDnsLookup(RnrContext); + } + + /* Check if we got a blob, and cache it */ + if (Blob) RnrContext->CachedSaBlob = Blob; + } + + /* We should have a blob by now */ + if (!Blob) + { + /* We dont, fail */ + if (ErrorCode == NO_ERROR) + { + /* Supposedly no error, so find it out */ + ErrorCode = GetLastError(); + if (ErrorCode == NO_ERROR) ErrorCode = WSASERVICE_NOT_FOUND; + } + + /* Fail */ + goto Quickie; + } + } + + /* Check if this is the first instance or not */ + if(!RnrContext->Instance) + { + /* It is, get the name from the blob */ + Name = Blob->Name; + } + else + { + /* Only accept this scenario if the caller wanted Aliases */ + if((RnrContext->dwControlFlags & LUP_RETURN_ALIASES) && + (Blob->AliasCount > RnrContext->Instance)) + { + /* Get the name from the Alias */ + Name = Blob->Aliases[RnrContext->Instance]; + + /* Let the caller know that this is an Alias */ + /* lpqsResults->dwOutputFlags |= RESULT_IS_ALIAS; */ + } + else + { + /* Fail */ + ErrorCode = WSA_E_NO_MORE; + goto Quickie; + } + } + + /* Lookups are complete... time to return the right stuff! */ + lpqsResults->dwNameSpace = NS_DNS; + + /* Caller wants the Type back */ + if(RnrContext->dwControlFlags & LUP_RETURN_TYPE) + { + /* Copy into the flat buffer and point to it */ + lpqsResults->lpServiceClassId = FlatBuf_CopyMemory(&FlatBuffer, + &RnrContext->lpServiceClassId, + sizeof(GUID), + sizeof(PVOID)); + } + + /* Caller wants the Addreses Back */ + if((RnrContext->dwControlFlags & LUP_RETURN_ADDR) && (Blob)) + { + /* Build the CS Addr for the caller */ + ErrorCode = BuildCsAddr(lpqsResults, + &FlatBuffer, + Blob, + RnrContext->UdpPort, + RnrContext->TcpPort, + (RnrContext->LookupFlags & REVERSE) == 1); + } + + /* Caller wants a Blob */ + if(RnrContext->dwControlFlags & LUP_RETURN_BLOB) + { + /* Save the current size and position */ + FreeSize = FlatBuffer.BufferFreeSize; + Position = FlatBuffer.BufferPos; + + /* Allocate some space for the Public Blob */ + lpqsResults->lpBlob = FlatBuf_ReserveAlignDword(&FlatBuffer, + sizeof(BLOB)); + + /* Check for a Cached Blob */ + if((RnrContext->RrType) && (RnrContext->CachedBlob.pBlobData)) + { + /* We have a Cached Blob, use it */ + BlobSize = RnrContext->CachedBlob.cbSize; + BlobData = FlatBuf_ReserveAlignDword(&FlatBuffer, BlobSize); + + /* Copy into the blob */ + RtlCopyMemory(RnrContext->CachedBlob.pBlobData, + BlobData, + BlobSize); + } + else if (!Blob) + { + /* Create an ANSI Host Entry */ + BlobData = SaBlob_CreateHostent(&FlatBuffer.BufferPos, + &FlatBuffer.BufferFreeSize, + &BlobSize, + Blob, + AnsiString, + TRUE, + FALSE); + } + else if ((RnrContext->LookupFlags & IANA) && (ServEntry)) + { + /* Get Servent */ + BlobData = CopyServEntry(ServEntry, + &FlatBuffer.BufferPos, + &FlatBuffer.BufferFreeSize, + &BlobSize, + TRUE); + + /* Manually update the buffer (no SaBlob function for servents) */ + FlatBuffer.BufferPos += BlobSize; + FlatBuffer.BufferFreeSize -= BlobSize; + } + else + { + /* We have nothing to return! */ + BlobSize = 0; + lpqsResults->lpBlob = NULL; + FlatBuffer.BufferPos = Position; + FlatBuffer.BufferFreeSize = FreeSize; + } + + /* Make sure we have a blob by here */ + if (Blob) + { + /* Set it */ + lpqsResults->lpBlob->pBlobData = BlobData; + lpqsResults->lpBlob->cbSize = BlobSize; + } + else + { + /* Set the error code */ + ErrorCode = WSAEFAULT; + } + } + + /* Caller wants a name, and we have one */ + if((RnrContext->dwControlFlags & LUP_RETURN_NAME) && (Name)) + { + /* Check if we have an ANSI name */ + if (!IsUnicode) + { + /* Convert it */ + StringLength = 512; + Dns_StringCopy(&UnicodeName, + &StringLength, + Name, + 0, + AnsiString, + UnicodeString); + } + else + { + /* Keep the name as is */ + UnicodeName = (LPWSTR)Name; + } + + /* Write it to the buffer */ + Name = FlatBuf_WriteString(&FlatBuffer, UnicodeName, TRUE); + + /* Return it to the caller */ + lpqsResults->lpszServiceInstanceName = Name; + } + +Quickie: + /* Check which path got us here */ + if (ErrorCode != NO_ERROR) + { + /* Set error */ + SetLastError(ErrorCode); + + /* Check if was a memory error */ + if (ErrorCode == WSAEFAULT) + { + /* Update buffer length */ + *lpdwBufferLength -= (DWORD)FlatBuffer.BufferFreeSize; + + /* Decrease an instance */ + RnrCtx_DecInstance(RnrContext); + } + + /* Set the normalized error code */ + ErrorCode = SOCKET_ERROR; + } + + /* Release the RnR Context */ + RnrCtx_Release(RnrContext); + + /* Return error code */ + return ErrorCode; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +#define ALL_LUP_FLAGS (0x0BFFF) + +/* DATA **********************************************************************/ + +LPWSTR g_pszHostName; +LPWSTR g_pszHostFqdn; +LONG g_NspRefCount; +GUID NbtProviderId = {0}; +GUID DNSProviderId = {0}; +DWORD MaskOfGuids; + +NSP_ROUTINE g_NspVector = {sizeof(NSP_ROUTINE), + 1, + 1, + Dns_NSPCleanup, + Dns_NSPLookupServiceBegin, + Dns_NSPLookupServiceNext, + Dns_NSPLookupServiceEnd, + Dns_NSPSetService, + Dns_NSPInstallServiceClass, + Dns_NSPRemoveServiceClass, + Dns_NSPGetServiceClassInfo}; + +/* FUNCTIONS *****************************************************************/ + +INT +WINAPI +Dns_NSPStartup(IN LPGUID lpProviderId, + IN OUT LPNSP_ROUTINE lpsnpRoutines) +{ + INT ErrorCode; + BOOLEAN Prolog; + + /* Validate the size */ + if (lpsnpRoutines->cbSize != sizeof(NSP_ROUTINE)) + { + /* Fail */ + SetLastError(WSAEINVALIDPROCTABLE); + return SOCKET_ERROR; + } + + /* Enter the prolog */ + Prolog = RNRPROV_SockEnterApi(); + if (Prolog) + { + /* Increase our reference count */ + InterlockedIncrement(&g_NspRefCount); + + /* Check if we don't have the hostname */ + if (!g_pszHostName) + { + /* Query it from DNS */ + DnsQueryConfig(DnsConfigHostName_W, + DNS_CONFIG_FLAG_ALLOC, + NULL, + NULL, + &g_pszHostName, + 0); + } + + /* Check if we have a hostname now, but not a Fully-Qualified Domain */ + if (g_pszHostName && !(g_pszHostFqdn)) + { + /* Get the domain from DNS */ + DnsQueryConfig(DnsConfigFullHostName_W, + DNS_CONFIG_FLAG_ALLOC, + NULL, + NULL, + &g_pszHostFqdn, + 0); + } + + /* If we don't have both of them, then set error */ + if (!(g_pszHostName) || !(g_pszHostFqdn)) ErrorCode = SOCKET_ERROR; + } + + /* Check if the Prolog or DNS Local Queries failed */ + if (!(Prolog) || (ErrorCode != NO_ERROR)) + { + /* Fail */ + SetLastError(WSASYSNOTREADY); + return SOCKET_ERROR; + } + + /* Copy the Routines */ + RtlMoveMemory(lpsnpRoutines, &g_NspVector, sizeof(NSP_ROUTINE)); + + /* Check if this is NBT or DNS */ + if (!memcmp(lpProviderId, &NbtProviderId, sizeof(GUID))) + { + /* Enable the NBT Mask */ + MaskOfGuids |= NBT_MASK; + } + else if (!memcmp(lpProviderId, &DNSProviderId, sizeof(GUID))) + { + /* Enable the DNS Mask */ + MaskOfGuids |= DNS_MASK; + } + + /* Return success */ + return NO_ERROR; +} + +VOID +WSPAPI +Nsp_GlobalCleanup(VOID) +{ + /* Cleanup the RnR Contexts */ + RnrCtx_ListCleanup(); + + /* Free the hostnames, if we have them */ + if (g_pszHostName) DnsApiFree(g_pszHostName); + if (g_pszHostFqdn) DnsApiFree(g_pszHostFqdn); + g_pszHostFqdn = g_pszHostName = NULL; +} + +INT +WINAPI +NSPStartup(IN LPGUID lpProviderId, + IN OUT LPNSP_ROUTINE lpsnpRoutines) +{ + INT ErrorCode; + + /* Initialize the DLL */ + ErrorCode = MSWSOCK_Initialize(); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + SetLastError(WSANOTINITIALISED); + return SOCKET_ERROR; + } + + /* Check if this is Winsock Mobile or DNS */ + if (!memcmp(lpProviderId, &gNLANamespaceGuid, sizeof(GUID))) + { + /* Initialize WSM */ + return WSM_NSPStartup(lpProviderId, lpsnpRoutines); + } + + /* Initialize DNS */ + return Dns_NSPStartup(lpProviderId, lpsnpRoutines); +} + +INT +WINAPI +Dns_NSPCleanup(IN LPGUID lpProviderId) +{ + /* Decrement our reference count and do global cleanup if it's reached 0 */ + if (!(InterlockedDecrement(&g_NspRefCount))) Nsp_GlobalCleanup(); + + /* Return success */ + return NO_ERROR; +} + +INT +WINAPI +Dns_NSPSetService(IN LPGUID lpProviderId, + IN LPWSASERVICECLASSINFOW lpServiceClassInfo, + IN LPWSAQUERYSETW lpqsRegInfo, + IN WSAESETSERVICEOP essOperation, + IN DWORD dwControlFlags) +{ + /* Unlike NLA, DNS Services cannot be dynmically modified */ + SetLastError(ERROR_NOT_SUPPORTED); + return SOCKET_ERROR; +} + +INT +WINAPI +Dns_NSPInstallServiceClass(IN LPGUID lpProviderId, + IN LPWSASERVICECLASSINFOW lpServiceClassInfo) +{ + /* Unlike NLA, DNS Services cannot be dynmically modified */ + SetLastError(WSAEOPNOTSUPP); + return SOCKET_ERROR; +}; + +INT +WINAPI +Dns_NSPRemoveServiceClass(IN LPGUID lpProviderId, + IN LPGUID lpServiceCallId) +{ + /* Unlike NLA, DNS Services cannot be dynmically modified */ + SetLastError(WSAEOPNOTSUPP); + return SOCKET_ERROR; +} +INT +WINAPI +Dns_NSPGetServiceClassInfo(IN LPGUID lpProviderId, + IN OUT LPDWORD lpdwBufSize, + IN OUT LPWSASERVICECLASSINFOW lpServiceClassInfo) +{ + /* Unlike NLA, DNS Services cannot be dynmically modified */ + SetLastError(WSAEOPNOTSUPP); + return SOCKET_ERROR; +} + +INT +WINAPI +Dns_NSPLookupServiceEnd(IN HANDLE hLookup) +{ + PRNR_CONTEXT RnrContext; + + /* Get this handle's context */ + RnrContext = RnrCtx_Get(hLookup, 0, NULL); + + /* Mark it as completed */ + RnrContext->LookupFlags |= DONE; + + /* Dereference it once for our _Get */ + RnrCtx_Release(RnrContext); + + /* And once last to delete it */ + RnrCtx_Release(RnrContext); + + /* return */ + return NO_ERROR; +} + +INT +WINAPI +rnr_IdForGuid(IN LPGUID Guid) +{ + + if (memcmp(Guid, &InetHostName, sizeof(GUID))) return 0x10000002; + if (memcmp(Guid, &Ipv6Guid, sizeof(GUID))) return 0x10000023; + if (memcmp(Guid, &HostnameGuid, sizeof(GUID))) return 0x1; + if (memcmp(Guid, &AddressGuid, sizeof(GUID))) return 0x80000000; + if (memcmp(Guid, &IANAGuid, sizeof(GUID))) return 0x2; + if IS_SVCID_DNS(Guid) return 0x5000000; + if IS_SVCID_TCP(Guid) return 0x1000000; + if IS_SVCID_UDP(Guid) return 0x2000000; + return 0; +} + +PVOID +WSPAPI +FlatBuf_ReserveAlignDword(IN PFLATBUFF FlatBuffer, + IN ULONG Size) +{ + /* Let DNSLIB do the grunt work */ + return FlatBuf_Arg_Reserve((PVOID)FlatBuffer->BufferPos, + &FlatBuffer->BufferFreeSize, + Size, + sizeof(PVOID)); +} + +PVOID +WSPAPI +FlatBuf_WriteString(IN PFLATBUFF FlatBuffer, + IN PVOID String, + IN BOOLEAN IsUnicode) +{ + /* Let DNSLIB do the grunt work */ + return FlatBuf_Arg_WriteString((PVOID)FlatBuffer->BufferPos, + &FlatBuffer->BufferFreeSize, + String, + IsUnicode); +} + +PVOID +WSPAPI +FlatBuf_CopyMemory(IN PFLATBUFF FlatBuffer, + IN PVOID Buffer, + IN ULONG Size, + IN ULONG Align) +{ + /* Let DNSLIB do the grunt work */ + return FlatBuf_Arg_CopyMemory((PVOID)FlatBuffer->BufferPos, + &FlatBuffer->BufferFreeSize, + Buffer, + Size, + Align); +} + +INT +WINAPI +Dns_NSPLookupServiceBegin(LPGUID lpProviderId, + LPWSAQUERYSETW lpqsRestrictions, + LPWSASERVICECLASSINFOW lpServiceClassInfo, + DWORD dwControlFlags, + LPHANDLE lphLookup) +{ + INT ErrorCode = SOCKET_ERROR; + PWCHAR ServiceName = lpqsRestrictions->lpszServiceInstanceName; + LPGUID ServiceClassId; + INT RnrId; + ULONG LookupFlags = 0; + BOOL NameRequested = FALSE; + WCHAR StringBuffer[48]; + ULONG i; + DWORD LocalProtocols; + ULONG ProtocolFlags; + PSERVENT LookupServent; + DWORD UdpPort, TcpPort; + PRNR_CONTEXT RnrContext; + PSOCKADDR_IN ReverseSock; + + /* Check if the Size isn't weird */ + if(lpqsRestrictions->dwSize < sizeof(WSAQUERYSETW)) + { + ErrorCode = WSAEFAULT; + goto Quickie; + } + + /* Get the GUID */ + ServiceClassId = lpqsRestrictions->lpServiceClassId; + if(!ServiceClassId) + { + /* No GUID, fail */ + ErrorCode = WSA_INVALID_PARAMETER; + goto Quickie; + } + + /* Get the RNR ID */ + RnrId = rnr_IdForGuid(ServiceClassId); + + /* Make sure that the control flags are valid */ + if ((dwControlFlags & ~ALL_LUP_FLAGS) || + ((dwControlFlags & (LUP_CONTAINERS | LUP_NOCONTAINERS)) == + (LUP_CONTAINERS | LUP_NOCONTAINERS))) + { + /* Either non-recognized flags or invalid combos were passed */ + ErrorCode = WSA_INVALID_PARAMETER; + goto Quickie; + } + + /* Make sure that we have no context, and that LUP_CONTAINERS is not on */ + if(((lpqsRestrictions->lpszContext) && + (*lpqsRestrictions->lpszContext) && + (wcscmp(lpqsRestrictions->lpszContext, L"\\"))) || + (dwControlFlags & LUP_CONTAINERS)) + { + /* We don't support contexts or LUP_CONTAINERS */ + ErrorCode = WSANO_DATA; + goto Quickie; + } + + /* Is this a Reverse Lookup? */ + if (RnrId == 0x80000000) + { + /* Remember for later */ + LookupFlags = REVERSE; + } + else + { + /* Is this a IANA Lookup? */ + if (RnrId == 0x2) + { + /* Mask out this flag since it's of no use now */ + dwControlFlags &= ~(LUP_RETURN_ADDR); + + /* This is a IANA lookup, remember for later */ + LookupFlags |= IANA; + } + + /* Check if we need a name or not */ + if ((RnrId == 0x1) || + (RnrId == 0x10000002) || + (RnrId == 0x10000023) || + (RnrId == 0x10000022)) + { + /* We do */ + NameRequested = TRUE; + } + } + + /* Final check to make sure if we need a name or not */ + if (RnrId & 0x3000000) NameRequested = TRUE; + + /* No Service Name was specified */ + if(!(ServiceName) || !(*ServiceName)) + { + /* + * A name was requested but no Service Name was given, + * so this is a local lookup + */ + if(NameRequested) + { + /* A local Lookup */ + LookupFlags |= LOCAL; + ServiceName = L""; + } + else if((LookupFlags & REVERSE) && + (lpqsRestrictions->lpcsaBuffer) && + (lpqsRestrictions->dwNumberOfCsAddrs == 1)) + { + /* Reverse lookup, make sure a CS Address is there */ + ReverseSock = (struct sockaddr_in*) + lpqsRestrictions->lpcsaBuffer->RemoteAddr.lpSockaddr; + + /* Convert address to Unicode */ + MultiByteToWideChar(CP_ACP, + 0, + inet_ntoa(ReverseSock->sin_addr), + -1, + StringBuffer, + 16); + + /* Set it as the new name */ + ServiceName = StringBuffer; + } + else + { + /* We can't do anything without a service name at this point */ + ErrorCode = WSA_INVALID_PARAMETER; + goto Quickie; + } + } + else if(NameRequested) + { + /* Check for meaningful DNS Names */ + if (DnsNameCompare_W(ServiceName, L"localhost") || + DnsNameCompare_W(ServiceName, L"loopback")) + { + /* This is the local and/or loopback DNS name */ + LookupFlags |= (LOCAL | LOOPBACK); + } + else if (DnsNameCompare_W(ServiceName, g_pszHostName) || + DnsNameCompare_W(ServiceName, g_pszHostFqdn)) + { + /* This is the local name of the computer */ + LookupFlags |= LOCAL; + } + } + + /* Check if any restrictions were made on the protocols */ + if(lpqsRestrictions->lpafpProtocols) + { + /* Save our local copy to speed up the loop */ + LocalProtocols = lpqsRestrictions->dwNumberOfProtocols; + ProtocolFlags = 0; + + /* Loop the protocols */ + for(i = 0; LocalProtocols--;) + { + /* Make sure it's a family that we recognize */ + if ((lpqsRestrictions->lpafpProtocols[i].iAddressFamily == AF_INET) || + (lpqsRestrictions->lpafpProtocols[i].iAddressFamily == AF_INET6) || + (lpqsRestrictions->lpafpProtocols[i].iAddressFamily == AF_UNSPEC) || + (lpqsRestrictions->lpafpProtocols[i].iAddressFamily == AF_ATM)) + { + /* Find which one is used */ + switch(lpqsRestrictions->lpafpProtocols[i].iProtocol) + { + case IPPROTO_UDP: + ProtocolFlags |= UDP; + break; + case IPPROTO_TCP: + ProtocolFlags |= TCP; + break; + case PF_ATM: + ProtocolFlags |= ATM; + break; + default: + break; + } + } + } + /* Make sure we have at least a valid protocol */ + if (!ProtocolFlags) + { + /* Fail */ + ErrorCode = WSANO_DATA; + goto Quickie; + } + } + else + { + /* No restrictions, assume TCP/UDP */ + ProtocolFlags = (TCP | UDP); + } + + /* Create the Servent from the Service String */ + UdpPort = TcpPort = -1; + ProtocolFlags |= GetServerAndProtocolsFromString(lpqsRestrictions->lpszQueryString, + ServiceClassId, + &LookupServent); + + /* Extract the port numbers */ + if(LookupServent) + { + /* Are we using UDP? */ + if(ProtocolFlags & UDP) + { + /* Get the UDP Port, disable the TCP Port */ + UdpPort = ntohs(LookupServent->s_port); + TcpPort = -1; + } + else if(ProtocolFlags & TCP) + { + /* Get the TCP Port, disable the UDP Port */ + TcpPort = ntohs(LookupServent->s_port); + UdpPort = -1; + } + } + else + { + /* No servent, so use the Service ID to check */ + if(ProtocolFlags & UDP) + { + /* Get the Port from the Service ID */ + UdpPort = FetchPortFromClassInfo(UDP, + ServiceClassId, + lpServiceClassInfo); + } + else + { + /* No UDP */ + UdpPort = -1; + } + + /* No servent, so use the Service ID to check */ + if(ProtocolFlags & TCP) + { + /* Get the Port from the Service ID */ + UdpPort = FetchPortFromClassInfo(TCP, + ServiceClassId, + lpServiceClassInfo); + } + else + { + /* No TCP */ + TcpPort = -1; + } + } + + /* Check if we still don't have a valid port by now */ + if((TcpPort == -1) && (UdpPort == -1)) + { + /* Check if this is TCP */ + if ((ProtocolFlags & TCP) || !(ProtocolFlags & UDP)) + { + /* Set the UDP Port to 0 */ + UdpPort = 0; + } + else + { + /* Set the TCP Port to 0 */ + TcpPort = 0; + } + } + + /* Allocate a Context for this Query */ + RnrContext = RnrCtx_Create(NULL, ServiceName); + RnrContext->lpServiceClassId = *ServiceClassId; + RnrContext->RnrId = RnrId; + RnrContext->dwControlFlags = dwControlFlags; + RnrContext->TcpPort = TcpPort; + RnrContext->UdpPort = UdpPort; + RnrContext->LookupFlags = LookupFlags; + RnrContext->lpProviderId = *lpProviderId; + RnrContext->dwNameSpace = lpqsRestrictions->dwNameSpace; + RnrCtx_Release(RnrContext); + + /* Return the context as a handle */ + *lphLookup = (HANDLE)RnrContext; + + /* Check if this was a TCP, UDP or DNS Query */ + if(RnrId & 0x3000000) + { + /* Get the RR Type from the Service ID */ + RnrContext->RrType = RR_FROM_SVCID(ServiceClassId); + } + + /* Return Success */ + ErrorCode = ERROR_SUCCESS; + +Quickie: + /* Check if we got here through a failure path */ + if (ErrorCode != ERROR_SUCCESS) + { + /* Set the last error and fail */ + SetLastError(ErrorCode); + return SOCKET_ERROR; + } + + /* Return success */ + return ERROR_SUCCESS; +} + +INT +WSPAPI +BuildCsAddr(IN LPWSAQUERYSETW QuerySet, + IN PFLATBUFF FlatBuffer, + IN PDNS_BLOB Blob, + IN DWORD UdpPort, + IN DWORD TcpPort, + IN BOOLEAN ReverseLookup) +{ + return WSANO_DATA; +} + +INT +WINAPI +Dns_NSPLookupServiceNext(IN HANDLE hLookup, + IN DWORD dwControlFlags, + IN OUT LPDWORD lpdwBufferLength, + OUT LPWSAQUERYSETW lpqsResults) +{ + INT ErrorCode; + WSAQUERYSETW LocalResults; + LONG Instance; + PRNR_CONTEXT RnrContext = NULL; + FLATBUFF FlatBuffer; + PVOID Name; + PDNS_BLOB Blob = NULL; + DWORD PortNumber; + PSERVENT ServEntry = NULL; + PDNS_ARRAY DnsArray; + BOOLEAN IsUnicode = TRUE; + SIZE_T FreeSize; + ULONG BlobSize; + ULONG_PTR Position; + PVOID BlobData = NULL; + ULONG StringLength; + LPWSTR UnicodeName; + + /* Make sure that the control flags are valid */ + if ((dwControlFlags & ~ALL_LUP_FLAGS) || + ((dwControlFlags & (LUP_CONTAINERS | LUP_NOCONTAINERS)) == + (LUP_CONTAINERS | LUP_NOCONTAINERS))) + { + /* Either non-recognized flags or invalid combos were passed */ + ErrorCode = WSA_INVALID_PARAMETER; + goto Quickie; + } + + /* Get the Context */ + RnrContext = RnrCtx_Get(hLookup, dwControlFlags, &Instance); + if (!RnrContext) + { + /* This lookup handle must be invalid */ + SetLastError(WSA_INVALID_HANDLE); + return SOCKET_ERROR; + } + + /* Assume success for now */ + SetLastError(NO_ERROR); + + /* Validate the query set size */ + if (*lpdwBufferLength < sizeof(WSAQUERYSETW)) + { + /* Windows doesn't fail, but sets up a local QS for you... */ + lpqsResults = &LocalResults; + ErrorCode = WSAEFAULT; + } + + /* Zero out the buffer and fill out basic data */ + RtlZeroMemory(lpqsResults, sizeof(WSAQUERYSETW)); + lpqsResults->dwNameSpace = NS_DNS; + lpqsResults->dwSize = sizeof(WSAQUERYSETW); + + /* Initialize the Buffer */ + FlatBuf_Init(&FlatBuffer, + lpqsResults + 1, + (ULONG)(*lpdwBufferLength - sizeof(WSAQUERYSETW))); + + /* Check if this is an IANA Lookup */ + if(RnrContext->LookupFlags & IANA) + { + /* Service Lookup */ + GetServerAndProtocolsFromString(RnrContext->ServiceName, + (LPGUID)&HostnameGuid, + &ServEntry); + + /* Get the Port */ + PortNumber = ntohs(ServEntry->s_port); + + /* Use this as the name */ + Name = ServEntry->s_name; + IsUnicode = FALSE; + + /* Override some parts of the Context and check for TCP/UDP */ + if(!_stricmp("tcp", ServEntry->s_proto)) + { + /* Set the TCP Guid */ + SET_TCP_SVCID(&RnrContext->lpServiceClassId, PortNumber); + RnrContext->TcpPort = PortNumber; + RnrContext->UdpPort = -1; + } + else + { + /* Set the UDP Guid */ + SET_UDP_SVCID(&RnrContext->lpServiceClassId, PortNumber); + RnrContext->UdpPort = PortNumber; + RnrContext->TcpPort = -1; + } + } + else + { + /* Check if the caller requested for RES_SERVICE */ + if(RnrContext->dwControlFlags & LUP_RES_SERVICE) + { + /* Make sure that this is the first instance */ + if (Instance) + { + /* Fail */ + ErrorCode = WSA_E_NO_MORE; + goto Quickie; + } + +#if 0 + /* Create the blob */ + DnsArray = NULL; + Blob = SaBlob_CreateFromIp4(RnrContext->ServiceName, + 1, + &DnsArray); +#else + /* FIXME */ + Blob = NULL; + DnsArray = NULL; + ErrorCode = WSAEFAULT; + goto Quickie; +#endif + } + else if(!(Blob = RnrContext->CachedSaBlob)) + { + /* An actual Host Lookup, but we don't have a cached HostEntry yet */ + if (!memcmp(&RnrContext->lpServiceClassId, + &HostnameGuid, + sizeof(GUID)) && !(RnrContext->ServiceName)) + { + /* Do a Regular DNS Lookup */ + Blob = Rnr_DoHostnameLookup(RnrContext); + } + else if (RnrContext->LookupFlags & REVERSE) + { + /* Do a Reverse DNS Lookup */ + Blob = Rnr_GetHostByAddr(RnrContext); + } + else + { + /* Do a Hostname Lookup */ + Blob = Rnr_DoDnsLookup(RnrContext); + } + + /* Check if we got a blob, and cache it */ + if (Blob) RnrContext->CachedSaBlob = Blob; + } + + /* We should have a blob by now */ + if (!Blob) + { + /* We dont, fail */ + if (ErrorCode == NO_ERROR) + { + /* Supposedly no error, so find it out */ + ErrorCode = GetLastError(); + if (ErrorCode == NO_ERROR) ErrorCode = WSASERVICE_NOT_FOUND; + } + + /* Fail */ + goto Quickie; + } + } + + /* Check if this is the first instance or not */ + if(!RnrContext->Instance) + { + /* It is, get the name from the blob */ + Name = Blob->Name; + } + else + { + /* Only accept this scenario if the caller wanted Aliases */ + if((RnrContext->dwControlFlags & LUP_RETURN_ALIASES) && + (Blob->AliasCount > RnrContext->Instance)) + { + /* Get the name from the Alias */ + Name = Blob->Aliases[RnrContext->Instance]; + + /* Let the caller know that this is an Alias */ + /* lpqsResults->dwOutputFlags |= RESULT_IS_ALIAS; */ + } + else + { + /* Fail */ + ErrorCode = WSA_E_NO_MORE; + goto Quickie; + } + } + + /* Lookups are complete... time to return the right stuff! */ + lpqsResults->dwNameSpace = NS_DNS; + + /* Caller wants the Type back */ + if(RnrContext->dwControlFlags & LUP_RETURN_TYPE) + { + /* Copy into the flat buffer and point to it */ + lpqsResults->lpServiceClassId = FlatBuf_CopyMemory(&FlatBuffer, + &RnrContext->lpServiceClassId, + sizeof(GUID), + sizeof(PVOID)); + } + + /* Caller wants the Addreses Back */ + if((RnrContext->dwControlFlags & LUP_RETURN_ADDR) && (Blob)) + { + /* Build the CS Addr for the caller */ + ErrorCode = BuildCsAddr(lpqsResults, + &FlatBuffer, + Blob, + RnrContext->UdpPort, + RnrContext->TcpPort, + (RnrContext->LookupFlags & REVERSE) == 1); + } + + /* Caller wants a Blob */ + if(RnrContext->dwControlFlags & LUP_RETURN_BLOB) + { + /* Save the current size and position */ + FreeSize = FlatBuffer.BufferFreeSize; + Position = FlatBuffer.BufferPos; + + /* Allocate some space for the Public Blob */ + lpqsResults->lpBlob = FlatBuf_ReserveAlignDword(&FlatBuffer, + sizeof(BLOB)); + + /* Check for a Cached Blob */ + if((RnrContext->RrType) && (RnrContext->CachedBlob.pBlobData)) + { + /* We have a Cached Blob, use it */ + BlobSize = RnrContext->CachedBlob.cbSize; + BlobData = FlatBuf_ReserveAlignDword(&FlatBuffer, BlobSize); + + /* Copy into the blob */ + RtlCopyMemory(RnrContext->CachedBlob.pBlobData, + BlobData, + BlobSize); + } + else if (!Blob) + { + /* Create an ANSI Host Entry */ + BlobData = SaBlob_CreateHostent(&FlatBuffer.BufferPos, + &FlatBuffer.BufferFreeSize, + &BlobSize, + Blob, + AnsiString, + TRUE, + FALSE); + } + else if ((RnrContext->LookupFlags & IANA) && (ServEntry)) + { + /* Get Servent */ + BlobData = CopyServEntry(ServEntry, + &FlatBuffer.BufferPos, + &FlatBuffer.BufferFreeSize, + &BlobSize, + TRUE); + + /* Manually update the buffer (no SaBlob function for servents) */ + FlatBuffer.BufferPos += BlobSize; + FlatBuffer.BufferFreeSize -= BlobSize; + } + else + { + /* We have nothing to return! */ + BlobSize = 0; + lpqsResults->lpBlob = NULL; + FlatBuffer.BufferPos = Position; + FlatBuffer.BufferFreeSize = FreeSize; + } + + /* Make sure we have a blob by here */ + if (Blob) + { + /* Set it */ + lpqsResults->lpBlob->pBlobData = BlobData; + lpqsResults->lpBlob->cbSize = BlobSize; + } + else + { + /* Set the error code */ + ErrorCode = WSAEFAULT; + } + } + + /* Caller wants a name, and we have one */ + if((RnrContext->dwControlFlags & LUP_RETURN_NAME) && (Name)) + { + /* Check if we have an ANSI name */ + if (!IsUnicode) + { + /* Convert it */ + StringLength = 512; + Dns_StringCopy(&UnicodeName, + &StringLength, + Name, + 0, + AnsiString, + UnicodeString); + } + else + { + /* Keep the name as is */ + UnicodeName = (LPWSTR)Name; + } + + /* Write it to the buffer */ + Name = FlatBuf_WriteString(&FlatBuffer, UnicodeName, TRUE); + + /* Return it to the caller */ + lpqsResults->lpszServiceInstanceName = Name; + } + +Quickie: + /* Check which path got us here */ + if (ErrorCode != NO_ERROR) + { + /* Set error */ + SetLastError(ErrorCode); + + /* Check if was a memory error */ + if (ErrorCode == WSAEFAULT) + { + /* Update buffer length */ + *lpdwBufferLength -= (DWORD)FlatBuffer.BufferFreeSize; + + /* Decrease an instance */ + RnrCtx_DecInstance(RnrContext); + } + + /* Set the normalized error code */ + ErrorCode = SOCKET_ERROR; + } + + /* Release the RnR Context */ + RnrCtx_Release(RnrContext); + + /* Return error code */ + return ErrorCode; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +#define ALL_LUP_FLAGS (0x0BFFF) + +/* DATA **********************************************************************/ + +LPWSTR g_pszHostName; +LPWSTR g_pszHostFqdn; +LONG g_NspRefCount; +GUID NbtProviderId = {0}; +GUID DNSProviderId = {0}; +DWORD MaskOfGuids; + +NSP_ROUTINE g_NspVector = {sizeof(NSP_ROUTINE), + 1, + 1, + Dns_NSPCleanup, + Dns_NSPLookupServiceBegin, + Dns_NSPLookupServiceNext, + Dns_NSPLookupServiceEnd, + Dns_NSPSetService, + Dns_NSPInstallServiceClass, + Dns_NSPRemoveServiceClass, + Dns_NSPGetServiceClassInfo}; + +/* FUNCTIONS *****************************************************************/ + +INT +WINAPI +Dns_NSPStartup(IN LPGUID lpProviderId, + IN OUT LPNSP_ROUTINE lpsnpRoutines) +{ + INT ErrorCode; + BOOLEAN Prolog; + + /* Validate the size */ + if (lpsnpRoutines->cbSize != sizeof(NSP_ROUTINE)) + { + /* Fail */ + SetLastError(WSAEINVALIDPROCTABLE); + return SOCKET_ERROR; + } + + /* Enter the prolog */ + Prolog = RNRPROV_SockEnterApi(); + if (Prolog) + { + /* Increase our reference count */ + InterlockedIncrement(&g_NspRefCount); + + /* Check if we don't have the hostname */ + if (!g_pszHostName) + { + /* Query it from DNS */ + DnsQueryConfig(DnsConfigHostName_W, + DNS_CONFIG_FLAG_ALLOC, + NULL, + NULL, + &g_pszHostName, + 0); + } + + /* Check if we have a hostname now, but not a Fully-Qualified Domain */ + if (g_pszHostName && !(g_pszHostFqdn)) + { + /* Get the domain from DNS */ + DnsQueryConfig(DnsConfigFullHostName_W, + DNS_CONFIG_FLAG_ALLOC, + NULL, + NULL, + &g_pszHostFqdn, + 0); + } + + /* If we don't have both of them, then set error */ + if (!(g_pszHostName) || !(g_pszHostFqdn)) ErrorCode = SOCKET_ERROR; + } + + /* Check if the Prolog or DNS Local Queries failed */ + if (!(Prolog) || (ErrorCode != NO_ERROR)) + { + /* Fail */ + SetLastError(WSASYSNOTREADY); + return SOCKET_ERROR; + } + + /* Copy the Routines */ + RtlMoveMemory(lpsnpRoutines, &g_NspVector, sizeof(NSP_ROUTINE)); + + /* Check if this is NBT or DNS */ + if (!memcmp(lpProviderId, &NbtProviderId, sizeof(GUID))) + { + /* Enable the NBT Mask */ + MaskOfGuids |= NBT_MASK; + } + else if (!memcmp(lpProviderId, &DNSProviderId, sizeof(GUID))) + { + /* Enable the DNS Mask */ + MaskOfGuids |= DNS_MASK; + } + + /* Return success */ + return NO_ERROR; +} + +VOID +WSPAPI +Nsp_GlobalCleanup(VOID) +{ + /* Cleanup the RnR Contexts */ + RnrCtx_ListCleanup(); + + /* Free the hostnames, if we have them */ + if (g_pszHostName) DnsApiFree(g_pszHostName); + if (g_pszHostFqdn) DnsApiFree(g_pszHostFqdn); + g_pszHostFqdn = g_pszHostName = NULL; +} + +INT +WINAPI +NSPStartup(IN LPGUID lpProviderId, + IN OUT LPNSP_ROUTINE lpsnpRoutines) +{ + INT ErrorCode; + + /* Initialize the DLL */ + ErrorCode = MSWSOCK_Initialize(); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + SetLastError(WSANOTINITIALISED); + return SOCKET_ERROR; + } + + /* Check if this is Winsock Mobile or DNS */ + if (!memcmp(lpProviderId, &gNLANamespaceGuid, sizeof(GUID))) + { + /* Initialize WSM */ + return WSM_NSPStartup(lpProviderId, lpsnpRoutines); + } + + /* Initialize DNS */ + return Dns_NSPStartup(lpProviderId, lpsnpRoutines); +} + +INT +WINAPI +Dns_NSPCleanup(IN LPGUID lpProviderId) +{ + /* Decrement our reference count and do global cleanup if it's reached 0 */ + if (!(InterlockedDecrement(&g_NspRefCount))) Nsp_GlobalCleanup(); + + /* Return success */ + return NO_ERROR; +} + +INT +WINAPI +Dns_NSPSetService(IN LPGUID lpProviderId, + IN LPWSASERVICECLASSINFOW lpServiceClassInfo, + IN LPWSAQUERYSETW lpqsRegInfo, + IN WSAESETSERVICEOP essOperation, + IN DWORD dwControlFlags) +{ + /* Unlike NLA, DNS Services cannot be dynmically modified */ + SetLastError(ERROR_NOT_SUPPORTED); + return SOCKET_ERROR; +} + +INT +WINAPI +Dns_NSPInstallServiceClass(IN LPGUID lpProviderId, + IN LPWSASERVICECLASSINFOW lpServiceClassInfo) +{ + /* Unlike NLA, DNS Services cannot be dynmically modified */ + SetLastError(WSAEOPNOTSUPP); + return SOCKET_ERROR; +}; + +INT +WINAPI +Dns_NSPRemoveServiceClass(IN LPGUID lpProviderId, + IN LPGUID lpServiceCallId) +{ + /* Unlike NLA, DNS Services cannot be dynmically modified */ + SetLastError(WSAEOPNOTSUPP); + return SOCKET_ERROR; +} +INT +WINAPI +Dns_NSPGetServiceClassInfo(IN LPGUID lpProviderId, + IN OUT LPDWORD lpdwBufSize, + IN OUT LPWSASERVICECLASSINFOW lpServiceClassInfo) +{ + /* Unlike NLA, DNS Services cannot be dynmically modified */ + SetLastError(WSAEOPNOTSUPP); + return SOCKET_ERROR; +} + +INT +WINAPI +Dns_NSPLookupServiceEnd(IN HANDLE hLookup) +{ + PRNR_CONTEXT RnrContext; + + /* Get this handle's context */ + RnrContext = RnrCtx_Get(hLookup, 0, NULL); + + /* Mark it as completed */ + RnrContext->LookupFlags |= DONE; + + /* Dereference it once for our _Get */ + RnrCtx_Release(RnrContext); + + /* And once last to delete it */ + RnrCtx_Release(RnrContext); + + /* return */ + return NO_ERROR; +} + +INT +WINAPI +rnr_IdForGuid(IN LPGUID Guid) +{ + + if (memcmp(Guid, &InetHostName, sizeof(GUID))) return 0x10000002; + if (memcmp(Guid, &Ipv6Guid, sizeof(GUID))) return 0x10000023; + if (memcmp(Guid, &HostnameGuid, sizeof(GUID))) return 0x1; + if (memcmp(Guid, &AddressGuid, sizeof(GUID))) return 0x80000000; + if (memcmp(Guid, &IANAGuid, sizeof(GUID))) return 0x2; + if IS_SVCID_DNS(Guid) return 0x5000000; + if IS_SVCID_TCP(Guid) return 0x1000000; + if IS_SVCID_UDP(Guid) return 0x2000000; + return 0; +} + +PVOID +WSPAPI +FlatBuf_ReserveAlignDword(IN PFLATBUFF FlatBuffer, + IN ULONG Size) +{ + /* Let DNSLIB do the grunt work */ + return FlatBuf_Arg_Reserve((PVOID)FlatBuffer->BufferPos, + &FlatBuffer->BufferFreeSize, + Size, + sizeof(PVOID)); +} + +PVOID +WSPAPI +FlatBuf_WriteString(IN PFLATBUFF FlatBuffer, + IN PVOID String, + IN BOOLEAN IsUnicode) +{ + /* Let DNSLIB do the grunt work */ + return FlatBuf_Arg_WriteString((PVOID)FlatBuffer->BufferPos, + &FlatBuffer->BufferFreeSize, + String, + IsUnicode); +} + +PVOID +WSPAPI +FlatBuf_CopyMemory(IN PFLATBUFF FlatBuffer, + IN PVOID Buffer, + IN ULONG Size, + IN ULONG Align) +{ + /* Let DNSLIB do the grunt work */ + return FlatBuf_Arg_CopyMemory((PVOID)FlatBuffer->BufferPos, + &FlatBuffer->BufferFreeSize, + Buffer, + Size, + Align); +} + +INT +WINAPI +Dns_NSPLookupServiceBegin(LPGUID lpProviderId, + LPWSAQUERYSETW lpqsRestrictions, + LPWSASERVICECLASSINFOW lpServiceClassInfo, + DWORD dwControlFlags, + LPHANDLE lphLookup) +{ + INT ErrorCode = SOCKET_ERROR; + PWCHAR ServiceName = lpqsRestrictions->lpszServiceInstanceName; + LPGUID ServiceClassId; + INT RnrId; + ULONG LookupFlags = 0; + BOOL NameRequested = FALSE; + WCHAR StringBuffer[48]; + ULONG i; + DWORD LocalProtocols; + ULONG ProtocolFlags; + PSERVENT LookupServent; + DWORD UdpPort, TcpPort; + PRNR_CONTEXT RnrContext; + PSOCKADDR_IN ReverseSock; + + /* Check if the Size isn't weird */ + if(lpqsRestrictions->dwSize < sizeof(WSAQUERYSETW)) + { + ErrorCode = WSAEFAULT; + goto Quickie; + } + + /* Get the GUID */ + ServiceClassId = lpqsRestrictions->lpServiceClassId; + if(!ServiceClassId) + { + /* No GUID, fail */ + ErrorCode = WSA_INVALID_PARAMETER; + goto Quickie; + } + + /* Get the RNR ID */ + RnrId = rnr_IdForGuid(ServiceClassId); + + /* Make sure that the control flags are valid */ + if ((dwControlFlags & ~ALL_LUP_FLAGS) || + ((dwControlFlags & (LUP_CONTAINERS | LUP_NOCONTAINERS)) == + (LUP_CONTAINERS | LUP_NOCONTAINERS))) + { + /* Either non-recognized flags or invalid combos were passed */ + ErrorCode = WSA_INVALID_PARAMETER; + goto Quickie; + } + + /* Make sure that we have no context, and that LUP_CONTAINERS is not on */ + if(((lpqsRestrictions->lpszContext) && + (*lpqsRestrictions->lpszContext) && + (wcscmp(lpqsRestrictions->lpszContext, L"\\"))) || + (dwControlFlags & LUP_CONTAINERS)) + { + /* We don't support contexts or LUP_CONTAINERS */ + ErrorCode = WSANO_DATA; + goto Quickie; + } + + /* Is this a Reverse Lookup? */ + if (RnrId == 0x80000000) + { + /* Remember for later */ + LookupFlags = REVERSE; + } + else + { + /* Is this a IANA Lookup? */ + if (RnrId == 0x2) + { + /* Mask out this flag since it's of no use now */ + dwControlFlags &= ~(LUP_RETURN_ADDR); + + /* This is a IANA lookup, remember for later */ + LookupFlags |= IANA; + } + + /* Check if we need a name or not */ + if ((RnrId == 0x1) || + (RnrId == 0x10000002) || + (RnrId == 0x10000023) || + (RnrId == 0x10000022)) + { + /* We do */ + NameRequested = TRUE; + } + } + + /* Final check to make sure if we need a name or not */ + if (RnrId & 0x3000000) NameRequested = TRUE; + + /* No Service Name was specified */ + if(!(ServiceName) || !(*ServiceName)) + { + /* + * A name was requested but no Service Name was given, + * so this is a local lookup + */ + if(NameRequested) + { + /* A local Lookup */ + LookupFlags |= LOCAL; + ServiceName = L""; + } + else if((LookupFlags & REVERSE) && + (lpqsRestrictions->lpcsaBuffer) && + (lpqsRestrictions->dwNumberOfCsAddrs == 1)) + { + /* Reverse lookup, make sure a CS Address is there */ + ReverseSock = (struct sockaddr_in*) + lpqsRestrictions->lpcsaBuffer->RemoteAddr.lpSockaddr; + + /* Convert address to Unicode */ + MultiByteToWideChar(CP_ACP, + 0, + inet_ntoa(ReverseSock->sin_addr), + -1, + StringBuffer, + 16); + + /* Set it as the new name */ + ServiceName = StringBuffer; + } + else + { + /* We can't do anything without a service name at this point */ + ErrorCode = WSA_INVALID_PARAMETER; + goto Quickie; + } + } + else if(NameRequested) + { + /* Check for meaningful DNS Names */ + if (DnsNameCompare_W(ServiceName, L"localhost") || + DnsNameCompare_W(ServiceName, L"loopback")) + { + /* This is the local and/or loopback DNS name */ + LookupFlags |= (LOCAL | LOOPBACK); + } + else if (DnsNameCompare_W(ServiceName, g_pszHostName) || + DnsNameCompare_W(ServiceName, g_pszHostFqdn)) + { + /* This is the local name of the computer */ + LookupFlags |= LOCAL; + } + } + + /* Check if any restrictions were made on the protocols */ + if(lpqsRestrictions->lpafpProtocols) + { + /* Save our local copy to speed up the loop */ + LocalProtocols = lpqsRestrictions->dwNumberOfProtocols; + ProtocolFlags = 0; + + /* Loop the protocols */ + for(i = 0; LocalProtocols--;) + { + /* Make sure it's a family that we recognize */ + if ((lpqsRestrictions->lpafpProtocols[i].iAddressFamily == AF_INET) || + (lpqsRestrictions->lpafpProtocols[i].iAddressFamily == AF_INET6) || + (lpqsRestrictions->lpafpProtocols[i].iAddressFamily == AF_UNSPEC) || + (lpqsRestrictions->lpafpProtocols[i].iAddressFamily == AF_ATM)) + { + /* Find which one is used */ + switch(lpqsRestrictions->lpafpProtocols[i].iProtocol) + { + case IPPROTO_UDP: + ProtocolFlags |= UDP; + break; + case IPPROTO_TCP: + ProtocolFlags |= TCP; + break; + case PF_ATM: + ProtocolFlags |= ATM; + break; + default: + break; + } + } + } + /* Make sure we have at least a valid protocol */ + if (!ProtocolFlags) + { + /* Fail */ + ErrorCode = WSANO_DATA; + goto Quickie; + } + } + else + { + /* No restrictions, assume TCP/UDP */ + ProtocolFlags = (TCP | UDP); + } + + /* Create the Servent from the Service String */ + UdpPort = TcpPort = -1; + ProtocolFlags |= GetServerAndProtocolsFromString(lpqsRestrictions->lpszQueryString, + ServiceClassId, + &LookupServent); + + /* Extract the port numbers */ + if(LookupServent) + { + /* Are we using UDP? */ + if(ProtocolFlags & UDP) + { + /* Get the UDP Port, disable the TCP Port */ + UdpPort = ntohs(LookupServent->s_port); + TcpPort = -1; + } + else if(ProtocolFlags & TCP) + { + /* Get the TCP Port, disable the UDP Port */ + TcpPort = ntohs(LookupServent->s_port); + UdpPort = -1; + } + } + else + { + /* No servent, so use the Service ID to check */ + if(ProtocolFlags & UDP) + { + /* Get the Port from the Service ID */ + UdpPort = FetchPortFromClassInfo(UDP, + ServiceClassId, + lpServiceClassInfo); + } + else + { + /* No UDP */ + UdpPort = -1; + } + + /* No servent, so use the Service ID to check */ + if(ProtocolFlags & TCP) + { + /* Get the Port from the Service ID */ + UdpPort = FetchPortFromClassInfo(TCP, + ServiceClassId, + lpServiceClassInfo); + } + else + { + /* No TCP */ + TcpPort = -1; + } + } + + /* Check if we still don't have a valid port by now */ + if((TcpPort == -1) && (UdpPort == -1)) + { + /* Check if this is TCP */ + if ((ProtocolFlags & TCP) || !(ProtocolFlags & UDP)) + { + /* Set the UDP Port to 0 */ + UdpPort = 0; + } + else + { + /* Set the TCP Port to 0 */ + TcpPort = 0; + } + } + + /* Allocate a Context for this Query */ + RnrContext = RnrCtx_Create(NULL, ServiceName); + RnrContext->lpServiceClassId = *ServiceClassId; + RnrContext->RnrId = RnrId; + RnrContext->dwControlFlags = dwControlFlags; + RnrContext->TcpPort = TcpPort; + RnrContext->UdpPort = UdpPort; + RnrContext->LookupFlags = LookupFlags; + RnrContext->lpProviderId = *lpProviderId; + RnrContext->dwNameSpace = lpqsRestrictions->dwNameSpace; + RnrCtx_Release(RnrContext); + + /* Return the context as a handle */ + *lphLookup = (HANDLE)RnrContext; + + /* Check if this was a TCP, UDP or DNS Query */ + if(RnrId & 0x3000000) + { + /* Get the RR Type from the Service ID */ + RnrContext->RrType = RR_FROM_SVCID(ServiceClassId); + } + + /* Return Success */ + ErrorCode = ERROR_SUCCESS; + +Quickie: + /* Check if we got here through a failure path */ + if (ErrorCode != ERROR_SUCCESS) + { + /* Set the last error and fail */ + SetLastError(ErrorCode); + return SOCKET_ERROR; + } + + /* Return success */ + return ERROR_SUCCESS; +} + +INT +WSPAPI +BuildCsAddr(IN LPWSAQUERYSETW QuerySet, + IN PFLATBUFF FlatBuffer, + IN PDNS_BLOB Blob, + IN DWORD UdpPort, + IN DWORD TcpPort, + IN BOOLEAN ReverseLookup) +{ + return WSANO_DATA; +} + +INT +WINAPI +Dns_NSPLookupServiceNext(IN HANDLE hLookup, + IN DWORD dwControlFlags, + IN OUT LPDWORD lpdwBufferLength, + OUT LPWSAQUERYSETW lpqsResults) +{ + INT ErrorCode; + WSAQUERYSETW LocalResults; + LONG Instance; + PRNR_CONTEXT RnrContext = NULL; + FLATBUFF FlatBuffer; + PVOID Name; + PDNS_BLOB Blob = NULL; + DWORD PortNumber; + PSERVENT ServEntry = NULL; + PDNS_ARRAY DnsArray; + BOOLEAN IsUnicode = TRUE; + SIZE_T FreeSize; + ULONG BlobSize; + ULONG_PTR Position; + PVOID BlobData = NULL; + ULONG StringLength; + LPWSTR UnicodeName; + + /* Make sure that the control flags are valid */ + if ((dwControlFlags & ~ALL_LUP_FLAGS) || + ((dwControlFlags & (LUP_CONTAINERS | LUP_NOCONTAINERS)) == + (LUP_CONTAINERS | LUP_NOCONTAINERS))) + { + /* Either non-recognized flags or invalid combos were passed */ + ErrorCode = WSA_INVALID_PARAMETER; + goto Quickie; + } + + /* Get the Context */ + RnrContext = RnrCtx_Get(hLookup, dwControlFlags, &Instance); + if (!RnrContext) + { + /* This lookup handle must be invalid */ + SetLastError(WSA_INVALID_HANDLE); + return SOCKET_ERROR; + } + + /* Assume success for now */ + SetLastError(NO_ERROR); + + /* Validate the query set size */ + if (*lpdwBufferLength < sizeof(WSAQUERYSETW)) + { + /* Windows doesn't fail, but sets up a local QS for you... */ + lpqsResults = &LocalResults; + ErrorCode = WSAEFAULT; + } + + /* Zero out the buffer and fill out basic data */ + RtlZeroMemory(lpqsResults, sizeof(WSAQUERYSETW)); + lpqsResults->dwNameSpace = NS_DNS; + lpqsResults->dwSize = sizeof(WSAQUERYSETW); + + /* Initialize the Buffer */ + FlatBuf_Init(&FlatBuffer, + lpqsResults + 1, + (ULONG)(*lpdwBufferLength - sizeof(WSAQUERYSETW))); + + /* Check if this is an IANA Lookup */ + if(RnrContext->LookupFlags & IANA) + { + /* Service Lookup */ + GetServerAndProtocolsFromString(RnrContext->ServiceName, + (LPGUID)&HostnameGuid, + &ServEntry); + + /* Get the Port */ + PortNumber = ntohs(ServEntry->s_port); + + /* Use this as the name */ + Name = ServEntry->s_name; + IsUnicode = FALSE; + + /* Override some parts of the Context and check for TCP/UDP */ + if(!_stricmp("tcp", ServEntry->s_proto)) + { + /* Set the TCP Guid */ + SET_TCP_SVCID(&RnrContext->lpServiceClassId, PortNumber); + RnrContext->TcpPort = PortNumber; + RnrContext->UdpPort = -1; + } + else + { + /* Set the UDP Guid */ + SET_UDP_SVCID(&RnrContext->lpServiceClassId, PortNumber); + RnrContext->UdpPort = PortNumber; + RnrContext->TcpPort = -1; + } + } + else + { + /* Check if the caller requested for RES_SERVICE */ + if(RnrContext->dwControlFlags & LUP_RES_SERVICE) + { + /* Make sure that this is the first instance */ + if (Instance) + { + /* Fail */ + ErrorCode = WSA_E_NO_MORE; + goto Quickie; + } + +#if 0 + /* Create the blob */ + DnsArray = NULL; + Blob = SaBlob_CreateFromIp4(RnrContext->ServiceName, + 1, + &DnsArray); +#else + /* FIXME */ + Blob = NULL; + DnsArray = NULL; + ErrorCode = WSAEFAULT; + goto Quickie; +#endif + } + else if(!(Blob = RnrContext->CachedSaBlob)) + { + /* An actual Host Lookup, but we don't have a cached HostEntry yet */ + if (!memcmp(&RnrContext->lpServiceClassId, + &HostnameGuid, + sizeof(GUID)) && !(RnrContext->ServiceName)) + { + /* Do a Regular DNS Lookup */ + Blob = Rnr_DoHostnameLookup(RnrContext); + } + else if (RnrContext->LookupFlags & REVERSE) + { + /* Do a Reverse DNS Lookup */ + Blob = Rnr_GetHostByAddr(RnrContext); + } + else + { + /* Do a Hostname Lookup */ + Blob = Rnr_DoDnsLookup(RnrContext); + } + + /* Check if we got a blob, and cache it */ + if (Blob) RnrContext->CachedSaBlob = Blob; + } + + /* We should have a blob by now */ + if (!Blob) + { + /* We dont, fail */ + if (ErrorCode == NO_ERROR) + { + /* Supposedly no error, so find it out */ + ErrorCode = GetLastError(); + if (ErrorCode == NO_ERROR) ErrorCode = WSASERVICE_NOT_FOUND; + } + + /* Fail */ + goto Quickie; + } + } + + /* Check if this is the first instance or not */ + if(!RnrContext->Instance) + { + /* It is, get the name from the blob */ + Name = Blob->Name; + } + else + { + /* Only accept this scenario if the caller wanted Aliases */ + if((RnrContext->dwControlFlags & LUP_RETURN_ALIASES) && + (Blob->AliasCount > RnrContext->Instance)) + { + /* Get the name from the Alias */ + Name = Blob->Aliases[RnrContext->Instance]; + + /* Let the caller know that this is an Alias */ + /* lpqsResults->dwOutputFlags |= RESULT_IS_ALIAS; */ + } + else + { + /* Fail */ + ErrorCode = WSA_E_NO_MORE; + goto Quickie; + } + } + + /* Lookups are complete... time to return the right stuff! */ + lpqsResults->dwNameSpace = NS_DNS; + + /* Caller wants the Type back */ + if(RnrContext->dwControlFlags & LUP_RETURN_TYPE) + { + /* Copy into the flat buffer and point to it */ + lpqsResults->lpServiceClassId = FlatBuf_CopyMemory(&FlatBuffer, + &RnrContext->lpServiceClassId, + sizeof(GUID), + sizeof(PVOID)); + } + + /* Caller wants the Addreses Back */ + if((RnrContext->dwControlFlags & LUP_RETURN_ADDR) && (Blob)) + { + /* Build the CS Addr for the caller */ + ErrorCode = BuildCsAddr(lpqsResults, + &FlatBuffer, + Blob, + RnrContext->UdpPort, + RnrContext->TcpPort, + (RnrContext->LookupFlags & REVERSE) == 1); + } + + /* Caller wants a Blob */ + if(RnrContext->dwControlFlags & LUP_RETURN_BLOB) + { + /* Save the current size and position */ + FreeSize = FlatBuffer.BufferFreeSize; + Position = FlatBuffer.BufferPos; + + /* Allocate some space for the Public Blob */ + lpqsResults->lpBlob = FlatBuf_ReserveAlignDword(&FlatBuffer, + sizeof(BLOB)); + + /* Check for a Cached Blob */ + if((RnrContext->RrType) && (RnrContext->CachedBlob.pBlobData)) + { + /* We have a Cached Blob, use it */ + BlobSize = RnrContext->CachedBlob.cbSize; + BlobData = FlatBuf_ReserveAlignDword(&FlatBuffer, BlobSize); + + /* Copy into the blob */ + RtlCopyMemory(RnrContext->CachedBlob.pBlobData, + BlobData, + BlobSize); + } + else if (!Blob) + { + /* Create an ANSI Host Entry */ + BlobData = SaBlob_CreateHostent(&FlatBuffer.BufferPos, + &FlatBuffer.BufferFreeSize, + &BlobSize, + Blob, + AnsiString, + TRUE, + FALSE); + } + else if ((RnrContext->LookupFlags & IANA) && (ServEntry)) + { + /* Get Servent */ + BlobData = CopyServEntry(ServEntry, + &FlatBuffer.BufferPos, + &FlatBuffer.BufferFreeSize, + &BlobSize, + TRUE); + + /* Manually update the buffer (no SaBlob function for servents) */ + FlatBuffer.BufferPos += BlobSize; + FlatBuffer.BufferFreeSize -= BlobSize; + } + else + { + /* We have nothing to return! */ + BlobSize = 0; + lpqsResults->lpBlob = NULL; + FlatBuffer.BufferPos = Position; + FlatBuffer.BufferFreeSize = FreeSize; + } + + /* Make sure we have a blob by here */ + if (Blob) + { + /* Set it */ + lpqsResults->lpBlob->pBlobData = BlobData; + lpqsResults->lpBlob->cbSize = BlobSize; + } + else + { + /* Set the error code */ + ErrorCode = WSAEFAULT; + } + } + + /* Caller wants a name, and we have one */ + if((RnrContext->dwControlFlags & LUP_RETURN_NAME) && (Name)) + { + /* Check if we have an ANSI name */ + if (!IsUnicode) + { + /* Convert it */ + StringLength = 512; + Dns_StringCopy(&UnicodeName, + &StringLength, + Name, + 0, + AnsiString, + UnicodeString); + } + else + { + /* Keep the name as is */ + UnicodeName = (LPWSTR)Name; + } + + /* Write it to the buffer */ + Name = FlatBuf_WriteString(&FlatBuffer, UnicodeName, TRUE); + + /* Return it to the caller */ + lpqsResults->lpszServiceInstanceName = Name; + } + +Quickie: + /* Check which path got us here */ + if (ErrorCode != NO_ERROR) + { + /* Set error */ + SetLastError(ErrorCode); + + /* Check if was a memory error */ + if (ErrorCode == WSAEFAULT) + { + /* Update buffer length */ + *lpdwBufferLength -= (DWORD)FlatBuffer.BufferFreeSize; + + /* Decrease an instance */ + RnrCtx_DecInstance(RnrContext); + } + + /* Set the normalized error code */ + ErrorCode = SOCKET_ERROR; + } + + /* Release the RnR Context */ + RnrCtx_Release(RnrContext); + + /* Return error code */ + return ErrorCode; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +#define ALL_LUP_FLAGS (0x0BFFF) + +/* DATA **********************************************************************/ + +LPWSTR g_pszHostName; +LPWSTR g_pszHostFqdn; +LONG g_NspRefCount; +GUID NbtProviderId = {0}; +GUID DNSProviderId = {0}; +DWORD MaskOfGuids; + +NSP_ROUTINE g_NspVector = {sizeof(NSP_ROUTINE), + 1, + 1, + Dns_NSPCleanup, + Dns_NSPLookupServiceBegin, + Dns_NSPLookupServiceNext, + Dns_NSPLookupServiceEnd, + Dns_NSPSetService, + Dns_NSPInstallServiceClass, + Dns_NSPRemoveServiceClass, + Dns_NSPGetServiceClassInfo}; + +/* FUNCTIONS *****************************************************************/ + +INT +WINAPI +Dns_NSPStartup(IN LPGUID lpProviderId, + IN OUT LPNSP_ROUTINE lpsnpRoutines) +{ + INT ErrorCode; + BOOLEAN Prolog; + + /* Validate the size */ + if (lpsnpRoutines->cbSize != sizeof(NSP_ROUTINE)) + { + /* Fail */ + SetLastError(WSAEINVALIDPROCTABLE); + return SOCKET_ERROR; + } + + /* Enter the prolog */ + Prolog = RNRPROV_SockEnterApi(); + if (Prolog) + { + /* Increase our reference count */ + InterlockedIncrement(&g_NspRefCount); + + /* Check if we don't have the hostname */ + if (!g_pszHostName) + { + /* Query it from DNS */ + DnsQueryConfig(DnsConfigHostName_W, + DNS_CONFIG_FLAG_ALLOC, + NULL, + NULL, + &g_pszHostName, + 0); + } + + /* Check if we have a hostname now, but not a Fully-Qualified Domain */ + if (g_pszHostName && !(g_pszHostFqdn)) + { + /* Get the domain from DNS */ + DnsQueryConfig(DnsConfigFullHostName_W, + DNS_CONFIG_FLAG_ALLOC, + NULL, + NULL, + &g_pszHostFqdn, + 0); + } + + /* If we don't have both of them, then set error */ + if (!(g_pszHostName) || !(g_pszHostFqdn)) ErrorCode = SOCKET_ERROR; + } + + /* Check if the Prolog or DNS Local Queries failed */ + if (!(Prolog) || (ErrorCode != NO_ERROR)) + { + /* Fail */ + SetLastError(WSASYSNOTREADY); + return SOCKET_ERROR; + } + + /* Copy the Routines */ + RtlMoveMemory(lpsnpRoutines, &g_NspVector, sizeof(NSP_ROUTINE)); + + /* Check if this is NBT or DNS */ + if (!memcmp(lpProviderId, &NbtProviderId, sizeof(GUID))) + { + /* Enable the NBT Mask */ + MaskOfGuids |= NBT_MASK; + } + else if (!memcmp(lpProviderId, &DNSProviderId, sizeof(GUID))) + { + /* Enable the DNS Mask */ + MaskOfGuids |= DNS_MASK; + } + + /* Return success */ + return NO_ERROR; +} + +VOID +WSPAPI +Nsp_GlobalCleanup(VOID) +{ + /* Cleanup the RnR Contexts */ + RnrCtx_ListCleanup(); + + /* Free the hostnames, if we have them */ + if (g_pszHostName) DnsApiFree(g_pszHostName); + if (g_pszHostFqdn) DnsApiFree(g_pszHostFqdn); + g_pszHostFqdn = g_pszHostName = NULL; +} + +INT +WINAPI +NSPStartup(IN LPGUID lpProviderId, + IN OUT LPNSP_ROUTINE lpsnpRoutines) +{ + INT ErrorCode; + + /* Initialize the DLL */ + ErrorCode = MSWSOCK_Initialize(); + if (ErrorCode != NO_ERROR) + { + /* Fail */ + SetLastError(WSANOTINITIALISED); + return SOCKET_ERROR; + } + + /* Check if this is Winsock Mobile or DNS */ + if (!memcmp(lpProviderId, &gNLANamespaceGuid, sizeof(GUID))) + { + /* Initialize WSM */ + return WSM_NSPStartup(lpProviderId, lpsnpRoutines); + } + + /* Initialize DNS */ + return Dns_NSPStartup(lpProviderId, lpsnpRoutines); +} + +INT +WINAPI +Dns_NSPCleanup(IN LPGUID lpProviderId) +{ + /* Decrement our reference count and do global cleanup if it's reached 0 */ + if (!(InterlockedDecrement(&g_NspRefCount))) Nsp_GlobalCleanup(); + + /* Return success */ + return NO_ERROR; +} + +INT +WINAPI +Dns_NSPSetService(IN LPGUID lpProviderId, + IN LPWSASERVICECLASSINFOW lpServiceClassInfo, + IN LPWSAQUERYSETW lpqsRegInfo, + IN WSAESETSERVICEOP essOperation, + IN DWORD dwControlFlags) +{ + /* Unlike NLA, DNS Services cannot be dynmically modified */ + SetLastError(ERROR_NOT_SUPPORTED); + return SOCKET_ERROR; +} + +INT +WINAPI +Dns_NSPInstallServiceClass(IN LPGUID lpProviderId, + IN LPWSASERVICECLASSINFOW lpServiceClassInfo) +{ + /* Unlike NLA, DNS Services cannot be dynmically modified */ + SetLastError(WSAEOPNOTSUPP); + return SOCKET_ERROR; +}; + +INT +WINAPI +Dns_NSPRemoveServiceClass(IN LPGUID lpProviderId, + IN LPGUID lpServiceCallId) +{ + /* Unlike NLA, DNS Services cannot be dynmically modified */ + SetLastError(WSAEOPNOTSUPP); + return SOCKET_ERROR; +} +INT +WINAPI +Dns_NSPGetServiceClassInfo(IN LPGUID lpProviderId, + IN OUT LPDWORD lpdwBufSize, + IN OUT LPWSASERVICECLASSINFOW lpServiceClassInfo) +{ + /* Unlike NLA, DNS Services cannot be dynmically modified */ + SetLastError(WSAEOPNOTSUPP); + return SOCKET_ERROR; +} + +INT +WINAPI +Dns_NSPLookupServiceEnd(IN HANDLE hLookup) +{ + PRNR_CONTEXT RnrContext; + + /* Get this handle's context */ + RnrContext = RnrCtx_Get(hLookup, 0, NULL); + + /* Mark it as completed */ + RnrContext->LookupFlags |= DONE; + + /* Dereference it once for our _Get */ + RnrCtx_Release(RnrContext); + + /* And once last to delete it */ + RnrCtx_Release(RnrContext); + + /* return */ + return NO_ERROR; +} + +INT +WINAPI +rnr_IdForGuid(IN LPGUID Guid) +{ + + if (memcmp(Guid, &InetHostName, sizeof(GUID))) return 0x10000002; + if (memcmp(Guid, &Ipv6Guid, sizeof(GUID))) return 0x10000023; + if (memcmp(Guid, &HostnameGuid, sizeof(GUID))) return 0x1; + if (memcmp(Guid, &AddressGuid, sizeof(GUID))) return 0x80000000; + if (memcmp(Guid, &IANAGuid, sizeof(GUID))) return 0x2; + if IS_SVCID_DNS(Guid) return 0x5000000; + if IS_SVCID_TCP(Guid) return 0x1000000; + if IS_SVCID_UDP(Guid) return 0x2000000; + return 0; +} + +PVOID +WSPAPI +FlatBuf_ReserveAlignDword(IN PFLATBUFF FlatBuffer, + IN ULONG Size) +{ + /* Let DNSLIB do the grunt work */ + return FlatBuf_Arg_Reserve((PVOID)FlatBuffer->BufferPos, + &FlatBuffer->BufferFreeSize, + Size, + sizeof(PVOID)); +} + +PVOID +WSPAPI +FlatBuf_WriteString(IN PFLATBUFF FlatBuffer, + IN PVOID String, + IN BOOLEAN IsUnicode) +{ + /* Let DNSLIB do the grunt work */ + return FlatBuf_Arg_WriteString((PVOID)FlatBuffer->BufferPos, + &FlatBuffer->BufferFreeSize, + String, + IsUnicode); +} + +PVOID +WSPAPI +FlatBuf_CopyMemory(IN PFLATBUFF FlatBuffer, + IN PVOID Buffer, + IN ULONG Size, + IN ULONG Align) +{ + /* Let DNSLIB do the grunt work */ + return FlatBuf_Arg_CopyMemory((PVOID)FlatBuffer->BufferPos, + &FlatBuffer->BufferFreeSize, + Buffer, + Size, + Align); +} + +INT +WINAPI +Dns_NSPLookupServiceBegin(LPGUID lpProviderId, + LPWSAQUERYSETW lpqsRestrictions, + LPWSASERVICECLASSINFOW lpServiceClassInfo, + DWORD dwControlFlags, + LPHANDLE lphLookup) +{ + INT ErrorCode = SOCKET_ERROR; + PWCHAR ServiceName = lpqsRestrictions->lpszServiceInstanceName; + LPGUID ServiceClassId; + INT RnrId; + ULONG LookupFlags = 0; + BOOL NameRequested = FALSE; + WCHAR StringBuffer[48]; + ULONG i; + DWORD LocalProtocols; + ULONG ProtocolFlags; + PSERVENT LookupServent; + DWORD UdpPort, TcpPort; + PRNR_CONTEXT RnrContext; + PSOCKADDR_IN ReverseSock; + + /* Check if the Size isn't weird */ + if(lpqsRestrictions->dwSize < sizeof(WSAQUERYSETW)) + { + ErrorCode = WSAEFAULT; + goto Quickie; + } + + /* Get the GUID */ + ServiceClassId = lpqsRestrictions->lpServiceClassId; + if(!ServiceClassId) + { + /* No GUID, fail */ + ErrorCode = WSA_INVALID_PARAMETER; + goto Quickie; + } + + /* Get the RNR ID */ + RnrId = rnr_IdForGuid(ServiceClassId); + + /* Make sure that the control flags are valid */ + if ((dwControlFlags & ~ALL_LUP_FLAGS) || + ((dwControlFlags & (LUP_CONTAINERS | LUP_NOCONTAINERS)) == + (LUP_CONTAINERS | LUP_NOCONTAINERS))) + { + /* Either non-recognized flags or invalid combos were passed */ + ErrorCode = WSA_INVALID_PARAMETER; + goto Quickie; + } + + /* Make sure that we have no context, and that LUP_CONTAINERS is not on */ + if(((lpqsRestrictions->lpszContext) && + (*lpqsRestrictions->lpszContext) && + (wcscmp(lpqsRestrictions->lpszContext, L"\\"))) || + (dwControlFlags & LUP_CONTAINERS)) + { + /* We don't support contexts or LUP_CONTAINERS */ + ErrorCode = WSANO_DATA; + goto Quickie; + } + + /* Is this a Reverse Lookup? */ + if (RnrId == 0x80000000) + { + /* Remember for later */ + LookupFlags = REVERSE; + } + else + { + /* Is this a IANA Lookup? */ + if (RnrId == 0x2) + { + /* Mask out this flag since it's of no use now */ + dwControlFlags &= ~(LUP_RETURN_ADDR); + + /* This is a IANA lookup, remember for later */ + LookupFlags |= IANA; + } + + /* Check if we need a name or not */ + if ((RnrId == 0x1) || + (RnrId == 0x10000002) || + (RnrId == 0x10000023) || + (RnrId == 0x10000022)) + { + /* We do */ + NameRequested = TRUE; + } + } + + /* Final check to make sure if we need a name or not */ + if (RnrId & 0x3000000) NameRequested = TRUE; + + /* No Service Name was specified */ + if(!(ServiceName) || !(*ServiceName)) + { + /* + * A name was requested but no Service Name was given, + * so this is a local lookup + */ + if(NameRequested) + { + /* A local Lookup */ + LookupFlags |= LOCAL; + ServiceName = L""; + } + else if((LookupFlags & REVERSE) && + (lpqsRestrictions->lpcsaBuffer) && + (lpqsRestrictions->dwNumberOfCsAddrs == 1)) + { + /* Reverse lookup, make sure a CS Address is there */ + ReverseSock = (struct sockaddr_in*) + lpqsRestrictions->lpcsaBuffer->RemoteAddr.lpSockaddr; + + /* Convert address to Unicode */ + MultiByteToWideChar(CP_ACP, + 0, + inet_ntoa(ReverseSock->sin_addr), + -1, + StringBuffer, + 16); + + /* Set it as the new name */ + ServiceName = StringBuffer; + } + else + { + /* We can't do anything without a service name at this point */ + ErrorCode = WSA_INVALID_PARAMETER; + goto Quickie; + } + } + else if(NameRequested) + { + /* Check for meaningful DNS Names */ + if (DnsNameCompare_W(ServiceName, L"localhost") || + DnsNameCompare_W(ServiceName, L"loopback")) + { + /* This is the local and/or loopback DNS name */ + LookupFlags |= (LOCAL | LOOPBACK); + } + else if (DnsNameCompare_W(ServiceName, g_pszHostName) || + DnsNameCompare_W(ServiceName, g_pszHostFqdn)) + { + /* This is the local name of the computer */ + LookupFlags |= LOCAL; + } + } + + /* Check if any restrictions were made on the protocols */ + if(lpqsRestrictions->lpafpProtocols) + { + /* Save our local copy to speed up the loop */ + LocalProtocols = lpqsRestrictions->dwNumberOfProtocols; + ProtocolFlags = 0; + + /* Loop the protocols */ + for(i = 0; LocalProtocols--;) + { + /* Make sure it's a family that we recognize */ + if ((lpqsRestrictions->lpafpProtocols[i].iAddressFamily == AF_INET) || + (lpqsRestrictions->lpafpProtocols[i].iAddressFamily == AF_INET6) || + (lpqsRestrictions->lpafpProtocols[i].iAddressFamily == AF_UNSPEC) || + (lpqsRestrictions->lpafpProtocols[i].iAddressFamily == AF_ATM)) + { + /* Find which one is used */ + switch(lpqsRestrictions->lpafpProtocols[i].iProtocol) + { + case IPPROTO_UDP: + ProtocolFlags |= UDP; + break; + case IPPROTO_TCP: + ProtocolFlags |= TCP; + break; + case PF_ATM: + ProtocolFlags |= ATM; + break; + default: + break; + } + } + } + /* Make sure we have at least a valid protocol */ + if (!ProtocolFlags) + { + /* Fail */ + ErrorCode = WSANO_DATA; + goto Quickie; + } + } + else + { + /* No restrictions, assume TCP/UDP */ + ProtocolFlags = (TCP | UDP); + } + + /* Create the Servent from the Service String */ + UdpPort = TcpPort = -1; + ProtocolFlags |= GetServerAndProtocolsFromString(lpqsRestrictions->lpszQueryString, + ServiceClassId, + &LookupServent); + + /* Extract the port numbers */ + if(LookupServent) + { + /* Are we using UDP? */ + if(ProtocolFlags & UDP) + { + /* Get the UDP Port, disable the TCP Port */ + UdpPort = ntohs(LookupServent->s_port); + TcpPort = -1; + } + else if(ProtocolFlags & TCP) + { + /* Get the TCP Port, disable the UDP Port */ + TcpPort = ntohs(LookupServent->s_port); + UdpPort = -1; + } + } + else + { + /* No servent, so use the Service ID to check */ + if(ProtocolFlags & UDP) + { + /* Get the Port from the Service ID */ + UdpPort = FetchPortFromClassInfo(UDP, + ServiceClassId, + lpServiceClassInfo); + } + else + { + /* No UDP */ + UdpPort = -1; + } + + /* No servent, so use the Service ID to check */ + if(ProtocolFlags & TCP) + { + /* Get the Port from the Service ID */ + UdpPort = FetchPortFromClassInfo(TCP, + ServiceClassId, + lpServiceClassInfo); + } + else + { + /* No TCP */ + TcpPort = -1; + } + } + + /* Check if we still don't have a valid port by now */ + if((TcpPort == -1) && (UdpPort == -1)) + { + /* Check if this is TCP */ + if ((ProtocolFlags & TCP) || !(ProtocolFlags & UDP)) + { + /* Set the UDP Port to 0 */ + UdpPort = 0; + } + else + { + /* Set the TCP Port to 0 */ + TcpPort = 0; + } + } + + /* Allocate a Context for this Query */ + RnrContext = RnrCtx_Create(NULL, ServiceName); + RnrContext->lpServiceClassId = *ServiceClassId; + RnrContext->RnrId = RnrId; + RnrContext->dwControlFlags = dwControlFlags; + RnrContext->TcpPort = TcpPort; + RnrContext->UdpPort = UdpPort; + RnrContext->LookupFlags = LookupFlags; + RnrContext->lpProviderId = *lpProviderId; + RnrContext->dwNameSpace = lpqsRestrictions->dwNameSpace; + RnrCtx_Release(RnrContext); + + /* Return the context as a handle */ + *lphLookup = (HANDLE)RnrContext; + + /* Check if this was a TCP, UDP or DNS Query */ + if(RnrId & 0x3000000) + { + /* Get the RR Type from the Service ID */ + RnrContext->RrType = RR_FROM_SVCID(ServiceClassId); + } + + /* Return Success */ + ErrorCode = ERROR_SUCCESS; + +Quickie: + /* Check if we got here through a failure path */ + if (ErrorCode != ERROR_SUCCESS) + { + /* Set the last error and fail */ + SetLastError(ErrorCode); + return SOCKET_ERROR; + } + + /* Return success */ + return ERROR_SUCCESS; +} + +INT +WSPAPI +BuildCsAddr(IN LPWSAQUERYSETW QuerySet, + IN PFLATBUFF FlatBuffer, + IN PDNS_BLOB Blob, + IN DWORD UdpPort, + IN DWORD TcpPort, + IN BOOLEAN ReverseLookup) +{ + return WSANO_DATA; +} + +INT +WINAPI +Dns_NSPLookupServiceNext(IN HANDLE hLookup, + IN DWORD dwControlFlags, + IN OUT LPDWORD lpdwBufferLength, + OUT LPWSAQUERYSETW lpqsResults) +{ + INT ErrorCode; + WSAQUERYSETW LocalResults; + LONG Instance; + PRNR_CONTEXT RnrContext = NULL; + FLATBUFF FlatBuffer; + PVOID Name; + PDNS_BLOB Blob = NULL; + DWORD PortNumber; + PSERVENT ServEntry = NULL; + PDNS_ARRAY DnsArray; + BOOLEAN IsUnicode = TRUE; + SIZE_T FreeSize; + ULONG BlobSize; + ULONG_PTR Position; + PVOID BlobData = NULL; + ULONG StringLength; + LPWSTR UnicodeName; + + /* Make sure that the control flags are valid */ + if ((dwControlFlags & ~ALL_LUP_FLAGS) || + ((dwControlFlags & (LUP_CONTAINERS | LUP_NOCONTAINERS)) == + (LUP_CONTAINERS | LUP_NOCONTAINERS))) + { + /* Either non-recognized flags or invalid combos were passed */ + ErrorCode = WSA_INVALID_PARAMETER; + goto Quickie; + } + + /* Get the Context */ + RnrContext = RnrCtx_Get(hLookup, dwControlFlags, &Instance); + if (!RnrContext) + { + /* This lookup handle must be invalid */ + SetLastError(WSA_INVALID_HANDLE); + return SOCKET_ERROR; + } + + /* Assume success for now */ + SetLastError(NO_ERROR); + + /* Validate the query set size */ + if (*lpdwBufferLength < sizeof(WSAQUERYSETW)) + { + /* Windows doesn't fail, but sets up a local QS for you... */ + lpqsResults = &LocalResults; + ErrorCode = WSAEFAULT; + } + + /* Zero out the buffer and fill out basic data */ + RtlZeroMemory(lpqsResults, sizeof(WSAQUERYSETW)); + lpqsResults->dwNameSpace = NS_DNS; + lpqsResults->dwSize = sizeof(WSAQUERYSETW); + + /* Initialize the Buffer */ + FlatBuf_Init(&FlatBuffer, + lpqsResults + 1, + (ULONG)(*lpdwBufferLength - sizeof(WSAQUERYSETW))); + + /* Check if this is an IANA Lookup */ + if(RnrContext->LookupFlags & IANA) + { + /* Service Lookup */ + GetServerAndProtocolsFromString(RnrContext->ServiceName, + (LPGUID)&HostnameGuid, + &ServEntry); + + /* Get the Port */ + PortNumber = ntohs(ServEntry->s_port); + + /* Use this as the name */ + Name = ServEntry->s_name; + IsUnicode = FALSE; + + /* Override some parts of the Context and check for TCP/UDP */ + if(!_stricmp("tcp", ServEntry->s_proto)) + { + /* Set the TCP Guid */ + SET_TCP_SVCID(&RnrContext->lpServiceClassId, PortNumber); + RnrContext->TcpPort = PortNumber; + RnrContext->UdpPort = -1; + } + else + { + /* Set the UDP Guid */ + SET_UDP_SVCID(&RnrContext->lpServiceClassId, PortNumber); + RnrContext->UdpPort = PortNumber; + RnrContext->TcpPort = -1; + } + } + else + { + /* Check if the caller requested for RES_SERVICE */ + if(RnrContext->dwControlFlags & LUP_RES_SERVICE) + { + /* Make sure that this is the first instance */ + if (Instance) + { + /* Fail */ + ErrorCode = WSA_E_NO_MORE; + goto Quickie; + } + +#if 0 + /* Create the blob */ + DnsArray = NULL; + Blob = SaBlob_CreateFromIp4(RnrContext->ServiceName, + 1, + &DnsArray); +#else + /* FIXME */ + Blob = NULL; + DnsArray = NULL; + ErrorCode = WSAEFAULT; + goto Quickie; +#endif + } + else if(!(Blob = RnrContext->CachedSaBlob)) + { + /* An actual Host Lookup, but we don't have a cached HostEntry yet */ + if (!memcmp(&RnrContext->lpServiceClassId, + &HostnameGuid, + sizeof(GUID)) && !(RnrContext->ServiceName)) + { + /* Do a Regular DNS Lookup */ + Blob = Rnr_DoHostnameLookup(RnrContext); + } + else if (RnrContext->LookupFlags & REVERSE) + { + /* Do a Reverse DNS Lookup */ + Blob = Rnr_GetHostByAddr(RnrContext); + } + else + { + /* Do a Hostname Lookup */ + Blob = Rnr_DoDnsLookup(RnrContext); + } + + /* Check if we got a blob, and cache it */ + if (Blob) RnrContext->CachedSaBlob = Blob; + } + + /* We should have a blob by now */ + if (!Blob) + { + /* We dont, fail */ + if (ErrorCode == NO_ERROR) + { + /* Supposedly no error, so find it out */ + ErrorCode = GetLastError(); + if (ErrorCode == NO_ERROR) ErrorCode = WSASERVICE_NOT_FOUND; + } + + /* Fail */ + goto Quickie; + } + } + + /* Check if this is the first instance or not */ + if(!RnrContext->Instance) + { + /* It is, get the name from the blob */ + Name = Blob->Name; + } + else + { + /* Only accept this scenario if the caller wanted Aliases */ + if((RnrContext->dwControlFlags & LUP_RETURN_ALIASES) && + (Blob->AliasCount > RnrContext->Instance)) + { + /* Get the name from the Alias */ + Name = Blob->Aliases[RnrContext->Instance]; + + /* Let the caller know that this is an Alias */ + /* lpqsResults->dwOutputFlags |= RESULT_IS_ALIAS; */ + } + else + { + /* Fail */ + ErrorCode = WSA_E_NO_MORE; + goto Quickie; + } + } + + /* Lookups are complete... time to return the right stuff! */ + lpqsResults->dwNameSpace = NS_DNS; + + /* Caller wants the Type back */ + if(RnrContext->dwControlFlags & LUP_RETURN_TYPE) + { + /* Copy into the flat buffer and point to it */ + lpqsResults->lpServiceClassId = FlatBuf_CopyMemory(&FlatBuffer, + &RnrContext->lpServiceClassId, + sizeof(GUID), + sizeof(PVOID)); + } + + /* Caller wants the Addreses Back */ + if((RnrContext->dwControlFlags & LUP_RETURN_ADDR) && (Blob)) + { + /* Build the CS Addr for the caller */ + ErrorCode = BuildCsAddr(lpqsResults, + &FlatBuffer, + Blob, + RnrContext->UdpPort, + RnrContext->TcpPort, + (RnrContext->LookupFlags & REVERSE) == 1); + } + + /* Caller wants a Blob */ + if(RnrContext->dwControlFlags & LUP_RETURN_BLOB) + { + /* Save the current size and position */ + FreeSize = FlatBuffer.BufferFreeSize; + Position = FlatBuffer.BufferPos; + + /* Allocate some space for the Public Blob */ + lpqsResults->lpBlob = FlatBuf_ReserveAlignDword(&FlatBuffer, + sizeof(BLOB)); + + /* Check for a Cached Blob */ + if((RnrContext->RrType) && (RnrContext->CachedBlob.pBlobData)) + { + /* We have a Cached Blob, use it */ + BlobSize = RnrContext->CachedBlob.cbSize; + BlobData = FlatBuf_ReserveAlignDword(&FlatBuffer, BlobSize); + + /* Copy into the blob */ + RtlCopyMemory(RnrContext->CachedBlob.pBlobData, + BlobData, + BlobSize); + } + else if (!Blob) + { + /* Create an ANSI Host Entry */ + BlobData = SaBlob_CreateHostent(&FlatBuffer.BufferPos, + &FlatBuffer.BufferFreeSize, + &BlobSize, + Blob, + AnsiString, + TRUE, + FALSE); + } + else if ((RnrContext->LookupFlags & IANA) && (ServEntry)) + { + /* Get Servent */ + BlobData = CopyServEntry(ServEntry, + &FlatBuffer.BufferPos, + &FlatBuffer.BufferFreeSize, + &BlobSize, + TRUE); + + /* Manually update the buffer (no SaBlob function for servents) */ + FlatBuffer.BufferPos += BlobSize; + FlatBuffer.BufferFreeSize -= BlobSize; + } + else + { + /* We have nothing to return! */ + BlobSize = 0; + lpqsResults->lpBlob = NULL; + FlatBuffer.BufferPos = Position; + FlatBuffer.BufferFreeSize = FreeSize; + } + + /* Make sure we have a blob by here */ + if (Blob) + { + /* Set it */ + lpqsResults->lpBlob->pBlobData = BlobData; + lpqsResults->lpBlob->cbSize = BlobSize; + } + else + { + /* Set the error code */ + ErrorCode = WSAEFAULT; + } + } + + /* Caller wants a name, and we have one */ + if((RnrContext->dwControlFlags & LUP_RETURN_NAME) && (Name)) + { + /* Check if we have an ANSI name */ + if (!IsUnicode) + { + /* Convert it */ + StringLength = 512; + Dns_StringCopy(&UnicodeName, + &StringLength, + Name, + 0, + AnsiString, + UnicodeString); + } + else + { + /* Keep the name as is */ + UnicodeName = (LPWSTR)Name; + } + + /* Write it to the buffer */ + Name = FlatBuf_WriteString(&FlatBuffer, UnicodeName, TRUE); + + /* Return it to the caller */ + lpqsResults->lpszServiceInstanceName = Name; + } + +Quickie: + /* Check which path got us here */ + if (ErrorCode != NO_ERROR) + { + /* Set error */ + SetLastError(ErrorCode); + + /* Check if was a memory error */ + if (ErrorCode == WSAEFAULT) + { + /* Update buffer length */ + *lpdwBufferLength -= (DWORD)FlatBuffer.BufferFreeSize; + + /* Decrease an instance */ + RnrCtx_DecInstance(RnrContext); + } + + /* Set the normalized error code */ + ErrorCode = SOCKET_ERROR; + } + + /* Release the RnR Context */ + RnrCtx_Release(RnrContext); + + /* Return error code */ + return ErrorCode; +} + diff --git a/dll/win32/mswsock/rnr20/oldutil.c b/dll/win32/mswsock/rnr20/oldutil.c new file mode 100644 index 00000000000..83a78e5d1e0 --- /dev/null +++ b/dll/win32/mswsock/rnr20/oldutil.c @@ -0,0 +1,884 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + + +/* FUNCTIONS *****************************************************************/ + +DWORD +WINAPI +FetchPortFromClassInfo(IN DWORD Type, + IN LPGUID Guid, + IN LPWSASERVICECLASSINFOW ServiceClassInfo) +{ + DWORD Port; + + if (Type == UDP) + { + if (IS_SVCID_UDP(Guid)) + { + /* Get the Port from the Service ID */ + Port = PORT_FROM_SVCID_UDP(Guid); + } + else + { + /* No UDP */ + Port = -1; + } + } + else if (Type == TCP) + { + if (IS_SVCID_TCP(Guid)) + { + /* Get the Port from the Service ID */ + Port = PORT_FROM_SVCID_TCP(Guid); + } + else + { + /* No TCP */ + Port = -1; + } + } + else + { + /* Invalid */ + Port = -1; + } + + /* Return it */ + return Port; +} + +WORD +WINAPI +GetDnsQueryTypeFromGuid(IN LPGUID Guid) +{ + WORD DnsType = DNS_TYPE_A; + + /* Check if this is is a DNS GUID and get the type from it */ + if (IS_SVCID_DNS(Guid)) DnsType = RR_FROM_SVCID(Guid); + + /* Return the DNS Type */ + return DnsType; +} + +LPSTR +WINAPI +GetAnsiNameRnR(IN LPWSTR UnicodeName, + IN LPSTR Domain, + OUT PBOOL Result) +{ + SIZE_T Length = 0; + LPSTR AnsiName; + + /* Check if we have a domain */ + if (Domain) Length = strlen(Domain); + + /* Calculate length needed and allocate it */ + Length += ((wcslen(UnicodeName) + 1) * sizeof(WCHAR) * 2); + AnsiName = DnsApiAlloc((DWORD)Length); + + /* Convert the string */ + WideCharToMultiByte(CP_ACP, + 0, + UnicodeName, + -1, + AnsiName, + (DWORD)Length, + 0, + Result); + + /* Add the domain, if needed */ + if (Domain) strcat(AnsiName, Domain); + + /* Return the ANSI name */ + return AnsiName; +} + +DWORD +WINAPI +GetServerAndProtocolsFromString(PWCHAR ServiceString, + LPGUID ServiceType, + PSERVENT *ReverseServent) +{ + PSERVENT LocalServent = NULL; + DWORD ProtocolFlags = 0; + PWCHAR ProtocolString; + PWCHAR ServiceName; + PCHAR AnsiServiceName; + PCHAR AnsiProtocolName; + PCHAR TempString; + ULONG ServiceNameLength; + ULONG PortNumber = 0; + + /* Make sure that this is valid for a Servent lookup */ + if ((ServiceString) && + (ServiceType) && + (memcmp(ServiceType, &HostnameGuid, sizeof(GUID))) && + (memcmp(ServiceType, &InetHostName, sizeof(GUID)))) + { + /* Extract the Protocol */ + ProtocolString = wcschr(ServiceString, L'/'); + if (!ProtocolString) ProtocolString = wcschr(ProtocolString, L'\0'); + + /* Find out the length of the service name */ + ServiceNameLength = (ULONG)(ProtocolString - ServiceString) * sizeof(WCHAR); + + /* Allocate it */ + ServiceName = DnsApiAlloc(ServiceNameLength + sizeof(UNICODE_NULL)); + + /* Copy it and null-terminate */ + RtlMoveMemory(ServiceName, ServiceString, ServiceNameLength); + ServiceName[ServiceNameLength] = UNICODE_NULL; + + /* Get the Ansi Service Name */ + AnsiServiceName = GetAnsiNameRnR(ServiceName, 0, NULL); + DnsApiFree(ServiceName); + if (AnsiServiceName) + { + /* If we only have a port number, convert it */ + for (TempString = AnsiServiceName; + *TempString && isdigit(*TempString); + TempString++); + + /* Convert to Port Number */ + if (!*TempString) PortNumber = atoi(AnsiServiceName); + + /* Check if we have a Protocol Name, and set it */ + if (!(*ProtocolString) || !(*++ProtocolString)) + { + /* No protocol string, so won't have it in ANSI either */ + AnsiProtocolName = NULL; + } + else + { + /* Get it in ANSI */ + AnsiProtocolName = GetAnsiNameRnR(ProtocolString, 0, NULL); + } + + /* Now do the actual operation */ + if (PortNumber) + { + /* FIXME: Get Servent by Port */ + } + else + { + /* FIXME: Get Servent by Name */ + } + + /* Free the ansi names if we had them */ + if (AnsiProtocolName) DnsApiFree(AnsiProtocolName); + if (AnsiServiceName) DnsApiFree(AnsiProtocolName); + } + } + + /* Return Servent */ + if (ReverseServent) *ReverseServent = LocalServent; + + /* Return Protocol */ + if (LocalServent) + { + /* Check if it was UDP */ + if (_stricmp("udp", LocalServent->s_proto)) + { + /* Return UDP */ + ProtocolFlags = UDP; + } + else + { + /* Return TCP */ + ProtocolFlags = TCP; + } + } + else + { + /* Return both, no restrictions */ + ProtocolFlags = (TCP | UDP); + } + + /* Return the flags */ + return ProtocolFlags; +} + +PSERVENT +WSPAPI +CopyServEntry(IN PSERVENT Servent, + IN OUT PULONG_PTR BufferPos, + IN OUT PULONG BufferFreeSize, + IN OUT PULONG BlobSize, + IN BOOLEAN Relative) +{ + return NULL; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + + +/* FUNCTIONS *****************************************************************/ + +DWORD +WINAPI +FetchPortFromClassInfo(IN DWORD Type, + IN LPGUID Guid, + IN LPWSASERVICECLASSINFOW ServiceClassInfo) +{ + DWORD Port; + + if (Type == UDP) + { + if (IS_SVCID_UDP(Guid)) + { + /* Get the Port from the Service ID */ + Port = PORT_FROM_SVCID_UDP(Guid); + } + else + { + /* No UDP */ + Port = -1; + } + } + else if (Type == TCP) + { + if (IS_SVCID_TCP(Guid)) + { + /* Get the Port from the Service ID */ + Port = PORT_FROM_SVCID_TCP(Guid); + } + else + { + /* No TCP */ + Port = -1; + } + } + else + { + /* Invalid */ + Port = -1; + } + + /* Return it */ + return Port; +} + +WORD +WINAPI +GetDnsQueryTypeFromGuid(IN LPGUID Guid) +{ + WORD DnsType = DNS_TYPE_A; + + /* Check if this is is a DNS GUID and get the type from it */ + if (IS_SVCID_DNS(Guid)) DnsType = RR_FROM_SVCID(Guid); + + /* Return the DNS Type */ + return DnsType; +} + +LPSTR +WINAPI +GetAnsiNameRnR(IN LPWSTR UnicodeName, + IN LPSTR Domain, + OUT PBOOL Result) +{ + SIZE_T Length = 0; + LPSTR AnsiName; + + /* Check if we have a domain */ + if (Domain) Length = strlen(Domain); + + /* Calculate length needed and allocate it */ + Length += ((wcslen(UnicodeName) + 1) * sizeof(WCHAR) * 2); + AnsiName = DnsApiAlloc((DWORD)Length); + + /* Convert the string */ + WideCharToMultiByte(CP_ACP, + 0, + UnicodeName, + -1, + AnsiName, + (DWORD)Length, + 0, + Result); + + /* Add the domain, if needed */ + if (Domain) strcat(AnsiName, Domain); + + /* Return the ANSI name */ + return AnsiName; +} + +DWORD +WINAPI +GetServerAndProtocolsFromString(PWCHAR ServiceString, + LPGUID ServiceType, + PSERVENT *ReverseServent) +{ + PSERVENT LocalServent = NULL; + DWORD ProtocolFlags = 0; + PWCHAR ProtocolString; + PWCHAR ServiceName; + PCHAR AnsiServiceName; + PCHAR AnsiProtocolName; + PCHAR TempString; + ULONG ServiceNameLength; + ULONG PortNumber = 0; + + /* Make sure that this is valid for a Servent lookup */ + if ((ServiceString) && + (ServiceType) && + (memcmp(ServiceType, &HostnameGuid, sizeof(GUID))) && + (memcmp(ServiceType, &InetHostName, sizeof(GUID)))) + { + /* Extract the Protocol */ + ProtocolString = wcschr(ServiceString, L'/'); + if (!ProtocolString) ProtocolString = wcschr(ProtocolString, L'\0'); + + /* Find out the length of the service name */ + ServiceNameLength = (ULONG)(ProtocolString - ServiceString) * sizeof(WCHAR); + + /* Allocate it */ + ServiceName = DnsApiAlloc(ServiceNameLength + sizeof(UNICODE_NULL)); + + /* Copy it and null-terminate */ + RtlMoveMemory(ServiceName, ServiceString, ServiceNameLength); + ServiceName[ServiceNameLength] = UNICODE_NULL; + + /* Get the Ansi Service Name */ + AnsiServiceName = GetAnsiNameRnR(ServiceName, 0, NULL); + DnsApiFree(ServiceName); + if (AnsiServiceName) + { + /* If we only have a port number, convert it */ + for (TempString = AnsiServiceName; + *TempString && isdigit(*TempString); + TempString++); + + /* Convert to Port Number */ + if (!*TempString) PortNumber = atoi(AnsiServiceName); + + /* Check if we have a Protocol Name, and set it */ + if (!(*ProtocolString) || !(*++ProtocolString)) + { + /* No protocol string, so won't have it in ANSI either */ + AnsiProtocolName = NULL; + } + else + { + /* Get it in ANSI */ + AnsiProtocolName = GetAnsiNameRnR(ProtocolString, 0, NULL); + } + + /* Now do the actual operation */ + if (PortNumber) + { + /* FIXME: Get Servent by Port */ + } + else + { + /* FIXME: Get Servent by Name */ + } + + /* Free the ansi names if we had them */ + if (AnsiProtocolName) DnsApiFree(AnsiProtocolName); + if (AnsiServiceName) DnsApiFree(AnsiProtocolName); + } + } + + /* Return Servent */ + if (ReverseServent) *ReverseServent = LocalServent; + + /* Return Protocol */ + if (LocalServent) + { + /* Check if it was UDP */ + if (_stricmp("udp", LocalServent->s_proto)) + { + /* Return UDP */ + ProtocolFlags = UDP; + } + else + { + /* Return TCP */ + ProtocolFlags = TCP; + } + } + else + { + /* Return both, no restrictions */ + ProtocolFlags = (TCP | UDP); + } + + /* Return the flags */ + return ProtocolFlags; +} + +PSERVENT +WSPAPI +CopyServEntry(IN PSERVENT Servent, + IN OUT PULONG_PTR BufferPos, + IN OUT PULONG BufferFreeSize, + IN OUT PULONG BlobSize, + IN BOOLEAN Relative) +{ + return NULL; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + + +/* FUNCTIONS *****************************************************************/ + +DWORD +WINAPI +FetchPortFromClassInfo(IN DWORD Type, + IN LPGUID Guid, + IN LPWSASERVICECLASSINFOW ServiceClassInfo) +{ + DWORD Port; + + if (Type == UDP) + { + if (IS_SVCID_UDP(Guid)) + { + /* Get the Port from the Service ID */ + Port = PORT_FROM_SVCID_UDP(Guid); + } + else + { + /* No UDP */ + Port = -1; + } + } + else if (Type == TCP) + { + if (IS_SVCID_TCP(Guid)) + { + /* Get the Port from the Service ID */ + Port = PORT_FROM_SVCID_TCP(Guid); + } + else + { + /* No TCP */ + Port = -1; + } + } + else + { + /* Invalid */ + Port = -1; + } + + /* Return it */ + return Port; +} + +WORD +WINAPI +GetDnsQueryTypeFromGuid(IN LPGUID Guid) +{ + WORD DnsType = DNS_TYPE_A; + + /* Check if this is is a DNS GUID and get the type from it */ + if (IS_SVCID_DNS(Guid)) DnsType = RR_FROM_SVCID(Guid); + + /* Return the DNS Type */ + return DnsType; +} + +LPSTR +WINAPI +GetAnsiNameRnR(IN LPWSTR UnicodeName, + IN LPSTR Domain, + OUT PBOOL Result) +{ + SIZE_T Length = 0; + LPSTR AnsiName; + + /* Check if we have a domain */ + if (Domain) Length = strlen(Domain); + + /* Calculate length needed and allocate it */ + Length += ((wcslen(UnicodeName) + 1) * sizeof(WCHAR) * 2); + AnsiName = DnsApiAlloc((DWORD)Length); + + /* Convert the string */ + WideCharToMultiByte(CP_ACP, + 0, + UnicodeName, + -1, + AnsiName, + (DWORD)Length, + 0, + Result); + + /* Add the domain, if needed */ + if (Domain) strcat(AnsiName, Domain); + + /* Return the ANSI name */ + return AnsiName; +} + +DWORD +WINAPI +GetServerAndProtocolsFromString(PWCHAR ServiceString, + LPGUID ServiceType, + PSERVENT *ReverseServent) +{ + PSERVENT LocalServent = NULL; + DWORD ProtocolFlags = 0; + PWCHAR ProtocolString; + PWCHAR ServiceName; + PCHAR AnsiServiceName; + PCHAR AnsiProtocolName; + PCHAR TempString; + ULONG ServiceNameLength; + ULONG PortNumber = 0; + + /* Make sure that this is valid for a Servent lookup */ + if ((ServiceString) && + (ServiceType) && + (memcmp(ServiceType, &HostnameGuid, sizeof(GUID))) && + (memcmp(ServiceType, &InetHostName, sizeof(GUID)))) + { + /* Extract the Protocol */ + ProtocolString = wcschr(ServiceString, L'/'); + if (!ProtocolString) ProtocolString = wcschr(ProtocolString, L'\0'); + + /* Find out the length of the service name */ + ServiceNameLength = (ULONG)(ProtocolString - ServiceString) * sizeof(WCHAR); + + /* Allocate it */ + ServiceName = DnsApiAlloc(ServiceNameLength + sizeof(UNICODE_NULL)); + + /* Copy it and null-terminate */ + RtlMoveMemory(ServiceName, ServiceString, ServiceNameLength); + ServiceName[ServiceNameLength] = UNICODE_NULL; + + /* Get the Ansi Service Name */ + AnsiServiceName = GetAnsiNameRnR(ServiceName, 0, NULL); + DnsApiFree(ServiceName); + if (AnsiServiceName) + { + /* If we only have a port number, convert it */ + for (TempString = AnsiServiceName; + *TempString && isdigit(*TempString); + TempString++); + + /* Convert to Port Number */ + if (!*TempString) PortNumber = atoi(AnsiServiceName); + + /* Check if we have a Protocol Name, and set it */ + if (!(*ProtocolString) || !(*++ProtocolString)) + { + /* No protocol string, so won't have it in ANSI either */ + AnsiProtocolName = NULL; + } + else + { + /* Get it in ANSI */ + AnsiProtocolName = GetAnsiNameRnR(ProtocolString, 0, NULL); + } + + /* Now do the actual operation */ + if (PortNumber) + { + /* FIXME: Get Servent by Port */ + } + else + { + /* FIXME: Get Servent by Name */ + } + + /* Free the ansi names if we had them */ + if (AnsiProtocolName) DnsApiFree(AnsiProtocolName); + if (AnsiServiceName) DnsApiFree(AnsiProtocolName); + } + } + + /* Return Servent */ + if (ReverseServent) *ReverseServent = LocalServent; + + /* Return Protocol */ + if (LocalServent) + { + /* Check if it was UDP */ + if (_stricmp("udp", LocalServent->s_proto)) + { + /* Return UDP */ + ProtocolFlags = UDP; + } + else + { + /* Return TCP */ + ProtocolFlags = TCP; + } + } + else + { + /* Return both, no restrictions */ + ProtocolFlags = (TCP | UDP); + } + + /* Return the flags */ + return ProtocolFlags; +} + +PSERVENT +WSPAPI +CopyServEntry(IN PSERVENT Servent, + IN OUT PULONG_PTR BufferPos, + IN OUT PULONG BufferFreeSize, + IN OUT PULONG BlobSize, + IN BOOLEAN Relative) +{ + return NULL; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + + +/* FUNCTIONS *****************************************************************/ + +DWORD +WINAPI +FetchPortFromClassInfo(IN DWORD Type, + IN LPGUID Guid, + IN LPWSASERVICECLASSINFOW ServiceClassInfo) +{ + DWORD Port; + + if (Type == UDP) + { + if (IS_SVCID_UDP(Guid)) + { + /* Get the Port from the Service ID */ + Port = PORT_FROM_SVCID_UDP(Guid); + } + else + { + /* No UDP */ + Port = -1; + } + } + else if (Type == TCP) + { + if (IS_SVCID_TCP(Guid)) + { + /* Get the Port from the Service ID */ + Port = PORT_FROM_SVCID_TCP(Guid); + } + else + { + /* No TCP */ + Port = -1; + } + } + else + { + /* Invalid */ + Port = -1; + } + + /* Return it */ + return Port; +} + +WORD +WINAPI +GetDnsQueryTypeFromGuid(IN LPGUID Guid) +{ + WORD DnsType = DNS_TYPE_A; + + /* Check if this is is a DNS GUID and get the type from it */ + if (IS_SVCID_DNS(Guid)) DnsType = RR_FROM_SVCID(Guid); + + /* Return the DNS Type */ + return DnsType; +} + +LPSTR +WINAPI +GetAnsiNameRnR(IN LPWSTR UnicodeName, + IN LPSTR Domain, + OUT PBOOL Result) +{ + SIZE_T Length = 0; + LPSTR AnsiName; + + /* Check if we have a domain */ + if (Domain) Length = strlen(Domain); + + /* Calculate length needed and allocate it */ + Length += ((wcslen(UnicodeName) + 1) * sizeof(WCHAR) * 2); + AnsiName = DnsApiAlloc((DWORD)Length); + + /* Convert the string */ + WideCharToMultiByte(CP_ACP, + 0, + UnicodeName, + -1, + AnsiName, + (DWORD)Length, + 0, + Result); + + /* Add the domain, if needed */ + if (Domain) strcat(AnsiName, Domain); + + /* Return the ANSI name */ + return AnsiName; +} + +DWORD +WINAPI +GetServerAndProtocolsFromString(PWCHAR ServiceString, + LPGUID ServiceType, + PSERVENT *ReverseServent) +{ + PSERVENT LocalServent = NULL; + DWORD ProtocolFlags = 0; + PWCHAR ProtocolString; + PWCHAR ServiceName; + PCHAR AnsiServiceName; + PCHAR AnsiProtocolName; + PCHAR TempString; + ULONG ServiceNameLength; + ULONG PortNumber = 0; + + /* Make sure that this is valid for a Servent lookup */ + if ((ServiceString) && + (ServiceType) && + (memcmp(ServiceType, &HostnameGuid, sizeof(GUID))) && + (memcmp(ServiceType, &InetHostName, sizeof(GUID)))) + { + /* Extract the Protocol */ + ProtocolString = wcschr(ServiceString, L'/'); + if (!ProtocolString) ProtocolString = wcschr(ProtocolString, L'\0'); + + /* Find out the length of the service name */ + ServiceNameLength = (ULONG)(ProtocolString - ServiceString) * sizeof(WCHAR); + + /* Allocate it */ + ServiceName = DnsApiAlloc(ServiceNameLength + sizeof(UNICODE_NULL)); + + /* Copy it and null-terminate */ + RtlMoveMemory(ServiceName, ServiceString, ServiceNameLength); + ServiceName[ServiceNameLength] = UNICODE_NULL; + + /* Get the Ansi Service Name */ + AnsiServiceName = GetAnsiNameRnR(ServiceName, 0, NULL); + DnsApiFree(ServiceName); + if (AnsiServiceName) + { + /* If we only have a port number, convert it */ + for (TempString = AnsiServiceName; + *TempString && isdigit(*TempString); + TempString++); + + /* Convert to Port Number */ + if (!*TempString) PortNumber = atoi(AnsiServiceName); + + /* Check if we have a Protocol Name, and set it */ + if (!(*ProtocolString) || !(*++ProtocolString)) + { + /* No protocol string, so won't have it in ANSI either */ + AnsiProtocolName = NULL; + } + else + { + /* Get it in ANSI */ + AnsiProtocolName = GetAnsiNameRnR(ProtocolString, 0, NULL); + } + + /* Now do the actual operation */ + if (PortNumber) + { + /* FIXME: Get Servent by Port */ + } + else + { + /* FIXME: Get Servent by Name */ + } + + /* Free the ansi names if we had them */ + if (AnsiProtocolName) DnsApiFree(AnsiProtocolName); + if (AnsiServiceName) DnsApiFree(AnsiProtocolName); + } + } + + /* Return Servent */ + if (ReverseServent) *ReverseServent = LocalServent; + + /* Return Protocol */ + if (LocalServent) + { + /* Check if it was UDP */ + if (_stricmp("udp", LocalServent->s_proto)) + { + /* Return UDP */ + ProtocolFlags = UDP; + } + else + { + /* Return TCP */ + ProtocolFlags = TCP; + } + } + else + { + /* Return both, no restrictions */ + ProtocolFlags = (TCP | UDP); + } + + /* Return the flags */ + return ProtocolFlags; +} + +PSERVENT +WSPAPI +CopyServEntry(IN PSERVENT Servent, + IN OUT PULONG_PTR BufferPos, + IN OUT PULONG BufferFreeSize, + IN OUT PULONG BlobSize, + IN BOOLEAN Relative) +{ + return NULL; +} + diff --git a/dll/win32/mswsock/rnr20/proc.c b/dll/win32/mswsock/rnr20/proc.c new file mode 100644 index 00000000000..7336526a34b --- /dev/null +++ b/dll/win32/mswsock/rnr20/proc.c @@ -0,0 +1,176 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +BOOLEAN +WINAPI +RNRPROV_SockEnterApi(VOID) +{ + PWINSOCK_TEB_DATA ThreadData; + + /* Make sure we're not terminating */ + if (SockProcessTerminating) + { + SetLastError(WSANOTINITIALISED); + return FALSE; + } + + /* Check if we already intialized */ + ThreadData = NtCurrentTeb()->WinSockData; + if (!(ThreadData) || !(ThreadData->RnrThreadData)) + { + /* Initialize the thread */ + if (!Rnr_ThreadInit()) + { + /* Fail */ + SetLastError(WSAENOBUFS); + return FALSE; + } + } + + /* Return success */ + return TRUE; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +BOOLEAN +WINAPI +RNRPROV_SockEnterApi(VOID) +{ + PWINSOCK_TEB_DATA ThreadData; + + /* Make sure we're not terminating */ + if (SockProcessTerminating) + { + SetLastError(WSANOTINITIALISED); + return FALSE; + } + + /* Check if we already intialized */ + ThreadData = NtCurrentTeb()->WinSockData; + if (!(ThreadData) || !(ThreadData->RnrThreadData)) + { + /* Initialize the thread */ + if (!Rnr_ThreadInit()) + { + /* Fail */ + SetLastError(WSAENOBUFS); + return FALSE; + } + } + + /* Return success */ + return TRUE; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +BOOLEAN +WINAPI +RNRPROV_SockEnterApi(VOID) +{ + PWINSOCK_TEB_DATA ThreadData; + + /* Make sure we're not terminating */ + if (SockProcessTerminating) + { + SetLastError(WSANOTINITIALISED); + return FALSE; + } + + /* Check if we already intialized */ + ThreadData = NtCurrentTeb()->WinSockData; + if (!(ThreadData) || !(ThreadData->RnrThreadData)) + { + /* Initialize the thread */ + if (!Rnr_ThreadInit()) + { + /* Fail */ + SetLastError(WSAENOBUFS); + return FALSE; + } + } + + /* Return success */ + return TRUE; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +BOOLEAN +WINAPI +RNRPROV_SockEnterApi(VOID) +{ + PWINSOCK_TEB_DATA ThreadData; + + /* Make sure we're not terminating */ + if (SockProcessTerminating) + { + SetLastError(WSANOTINITIALISED); + return FALSE; + } + + /* Check if we already intialized */ + ThreadData = NtCurrentTeb()->WinSockData; + if (!(ThreadData) || !(ThreadData->RnrThreadData)) + { + /* Initialize the thread */ + if (!Rnr_ThreadInit()) + { + /* Fail */ + SetLastError(WSAENOBUFS); + return FALSE; + } + } + + /* Return success */ + return TRUE; +} + diff --git a/dll/win32/mswsock/rnr20/r_comp.c b/dll/win32/mswsock/rnr20/r_comp.c new file mode 100644 index 00000000000..40d1f1bccaf --- /dev/null +++ b/dll/win32/mswsock/rnr20/r_comp.c @@ -0,0 +1,40 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + diff --git a/dll/win32/mswsock/rnr20/util.c b/dll/win32/mswsock/rnr20/util.c new file mode 100644 index 00000000000..258edf6fc9c --- /dev/null +++ b/dll/win32/mswsock/rnr20/util.c @@ -0,0 +1,128 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +PVOID +WSPAPI +Temp_AllocZero(IN DWORD Size) +{ + PVOID Data; + + /* Allocate the memory */ + Data = DnsApiAlloc(Size); + if (Data) + { + /* Zero it out */ + RtlZeroMemory(Data, Size); + } + + /* Return it */ + return Data; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +PVOID +WSPAPI +Temp_AllocZero(IN DWORD Size) +{ + PVOID Data; + + /* Allocate the memory */ + Data = DnsApiAlloc(Size); + if (Data) + { + /* Zero it out */ + RtlZeroMemory(Data, Size); + } + + /* Return it */ + return Data; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +PVOID +WSPAPI +Temp_AllocZero(IN DWORD Size) +{ + PVOID Data; + + /* Allocate the memory */ + Data = DnsApiAlloc(Size); + if (Data) + { + /* Zero it out */ + RtlZeroMemory(Data, Size); + } + + /* Return it */ + return Data; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +PVOID +WSPAPI +Temp_AllocZero(IN DWORD Size) +{ + PVOID Data; + + /* Allocate the memory */ + Data = DnsApiAlloc(Size); + if (Data) + { + /* Zero it out */ + RtlZeroMemory(Data, Size); + } + + /* Return it */ + return Data; +} + diff --git a/dll/win32/mswsock/stubs.c b/dll/win32/mswsock/stubs.c deleted file mode 100644 index fd449c695d2..00000000000 --- a/dll/win32/mswsock/stubs.c +++ /dev/null @@ -1,517 +0,0 @@ -/* $Id$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS WinSock DLL - * FILE: stubs.c - * PURPOSE: Stub functions - * PROGRAMMERS: Ge van Geldorp (ge@gse.nl) - * REVISIONS: - */ - -#include -#include -#include -#include -#include -#include - -typedef DWORD (* LPFN_NSPAPI)(VOID); -typedef struct _NS_ROUTINE { - DWORD dwFunctionCount; - LPFN_NSPAPI *alpfnFunctions; - DWORD dwNameSpace; - DWORD dwPriority; -} NS_ROUTINE, *PNS_ROUTINE, * FAR LPNS_ROUTINE; - -/* - * @unimplemented - */ -BOOL -WINAPI -AcceptEx(SOCKET ListenSocket, - SOCKET AcceptSocket, - PVOID OutputBuffer, - DWORD ReceiveDataLength, - DWORD LocalAddressLength, - DWORD RemoteAddressLength, - LPDWORD BytesReceived, - LPOVERLAPPED Overlapped) -{ - OutputDebugStringW(L"w32sock AcceptEx stub called\n"); - - return FALSE; -} - - -/* - * @unimplemented - */ -INT -WINAPI -EnumProtocolsA(LPINT ProtocolCount, - LPVOID ProtocolBuffer, - LPDWORD BufferLength) -{ - OutputDebugStringW(L"w32sock EnumProtocolsA stub called\n"); - - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -INT -WINAPI -EnumProtocolsW(LPINT ProtocolCount, - LPVOID ProtocolBuffer, - LPDWORD BufferLength) -{ - OutputDebugStringW(L"w32sock EnumProtocolsW stub called\n"); - - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -VOID -WINAPI -GetAcceptExSockaddrs(PVOID OutputBuffer, - DWORD ReceiveDataLength, - DWORD LocalAddressLength, - DWORD RemoteAddressLength, - LPSOCKADDR* LocalSockaddr, - LPINT LocalSockaddrLength, - LPSOCKADDR* RemoteSockaddr, - LPINT RemoteSockaddrLength) -{ - OutputDebugStringW(L"w32sock GetAcceptExSockaddrs stub called\n"); -} - - -/* - * @unimplemented - */ -INT -WINAPI -GetAddressByNameA(DWORD NameSpace, - LPGUID ServiceType, - LPSTR ServiceName, - LPINT Protocols, - DWORD Resolution, - LPSERVICE_ASYNC_INFO ServiceAsyncInfo, - LPVOID CsaddrBuffer, - LPDWORD BufferLength, - LPSTR AliasBuffer, - LPDWORD AliasBufferLength) -{ - OutputDebugStringW(L"w32sock GetAddressByNameA stub called\n"); - - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -INT -WINAPI -GetAddressByNameW(DWORD NameSpace, - LPGUID ServiceType, - LPWSTR ServiceName, - LPINT Protocols, - DWORD Resolution, - LPSERVICE_ASYNC_INFO ServiceAsyncInfo, - LPVOID CsaddrBuffer, - LPDWORD BufferLength, - LPWSTR AliasBuffer, - LPDWORD AliasBufferLength) -{ - OutputDebugStringW(L"w32sock GetAddressByNameW stub called\n"); - - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -INT -WINAPI -GetServiceA(DWORD NameSpace, - LPGUID Guid, - LPSTR ServiceName, - DWORD Properties, - LPVOID Buffer, - LPDWORD BufferSize, - LPSERVICE_ASYNC_INFO ServiceAsyncInfo) -{ - OutputDebugStringW(L"w32sock GetServiceA stub called\n"); - - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -INT -WINAPI -GetServiceW(DWORD NameSpace, - LPGUID Guid, - LPWSTR ServiceName, - DWORD Properties, - LPVOID Buffer, - LPDWORD BufferSize, - LPSERVICE_ASYNC_INFO ServiceAsyncInfo) -{ - OutputDebugStringW(L"w32sock GetServiceW stub called\n"); - - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -INT -WINAPI -GetTypeByNameA(LPSTR ServiceName, - LPGUID ServiceType) -{ - OutputDebugStringW(L"w32sock GetTypeByNameA stub called\n"); - - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -INT -WINAPI -GetTypeByNameW(LPWSTR ServiceName, - LPGUID ServiceType) -{ - OutputDebugStringW(L"w32sock GetTypeByNameW stub called\n"); - - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -INT -WINAPI -MigrateWinsockConfiguration(DWORD Unknown1, - DWORD Unknown2, - DWORD Unknown3) -{ - OutputDebugStringW(L"w32sock MigrateWinsockConfiguration stub called\n"); - - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -INT -WINAPI -SetServiceA(DWORD NameSpace, - DWORD Operation, - DWORD Flags, - LPSERVICE_INFOA ServiceInfo, - LPSERVICE_ASYNC_INFO ServiceAsyncInfo, - LPDWORD dwStatusFlags) -{ - OutputDebugStringW(L"w32sock SetServiceA stub called\n"); - - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -INT -WINAPI -SetServiceW(DWORD NameSpace, - DWORD Operation, - DWORD Flags, - LPSERVICE_INFOW ServiceInfo, - LPSERVICE_ASYNC_INFO ServiceAsyncInfo, - LPDWORD dwStatusFlags) -{ - OutputDebugStringW(L"w32sock SetServiceW stub called\n"); - - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -int -WINAPI -WSARecvEx(SOCKET Sock, - char *Buf, - int Len, - int *Flags) -{ - OutputDebugStringW(L"w32sock WSARecvEx stub called\n"); - - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -int -WINAPI -dn_expand(unsigned char *MessagePtr, - unsigned char *EndofMesOrig, - unsigned char *CompDomNam, - unsigned char *ExpandDomNam, - int Length) -{ - OutputDebugStringW(L"w32sock dn_expand stub called\n"); - - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -struct netent * -WINAPI -getnetbyname(const char *name) -{ - OutputDebugStringW(L"w32sock getnetbyname stub called\n"); - - return NULL; -} - - -/* - * @unimplemented - */ -UINT -WINAPI -inet_network(const char *cp) -{ - OutputDebugStringW(L"w32sock inet_network stub called\n"); - - return INADDR_NONE; -} - - -/* - * @unimplemented - */ -SOCKET -WINAPI -rcmd(char **AHost, - USHORT InPort, - char *LocUser, - char *RemUser, - char *Cmd, - int *Fd2p) -{ - OutputDebugStringW(L"w32sock rcmd stub called\n"); - - return INVALID_SOCKET; -} - - -/* - * @unimplemented - */ -SOCKET -WINAPI -rexec(char **AHost, - int InPort, - char *User, - char *Passwd, - char *Cmd, - int *Fd2p) -{ - OutputDebugStringW(L"w32sock rexec stub called\n"); - - return INVALID_SOCKET; -} - - -/* - * @unimplemented - */ -SOCKET -WINAPI -rresvport(int *port) -{ - OutputDebugStringW(L"w32sock rresvport stub called\n"); - - return INVALID_SOCKET; -} - - -/* - * @unimplemented - */ -void -WINAPI -s_perror(const char *str) -{ - OutputDebugStringW(L"w32sock s_perror stub called\n"); -} - - -/* - * @unimplemented - */ -int -WINAPI -sethostname(char *Name, int NameLen) -{ - OutputDebugStringW(L"w32sock sethostname stub called\n"); - - return SOCKET_ERROR; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -DllMain(HINSTANCE InstDLL, - DWORD Reason, - LPVOID Reserved) -{ - return TRUE; -} - - -/* - * @unimplemented - */ -INT -WINAPI -GetNameByTypeA(LPGUID lpServiceType,LPSTR lpServiceName,DWORD dwNameLength) -{ - OutputDebugStringW(L"w32sock GetNameByTypeA stub called\n"); - return TRUE; -} - - -/* - * @unimplemented - */ -INT -WINAPI -GetNameByTypeW(LPGUID lpServiceType,LPWSTR lpServiceName,DWORD dwNameLength) -{ - OutputDebugStringW(L"w32sock GetNameByTypeW stub called\n"); - return TRUE; -} - - -/* - * @unimplemented - */ -INT -WINAPI -NSPStartup( - LPGUID lpProviderId, - LPNSP_ROUTINE lpnspRoutines - ) -{ - return TRUE; -} - - -/* - * @unimplemented - */ -int -WINAPI -WSPStartup( - IN WORD wVersionRequested, - OUT LPWSPDATA lpWSPData, - IN LPWSAPROTOCOL_INFOW lpProtocolInfo, - IN WSPUPCALLTABLE UpcallTable, - OUT LPWSPPROC_TABLE lpProcTable - ) -{ - return TRUE; -} - - -/* - * @unimplemented - */ -INT -WINAPI -NPLoadNameSpaces( - IN OUT LPDWORD lpdwVersion, - IN OUT LPNS_ROUTINE nsrBuffer, - IN OUT LPDWORD lpdwBufferLength - ) -{ - OutputDebugStringW(L"mswsock NPLoadNameSpaces stub called\n"); - - *lpdwVersion = 1; - - return TRUE; -} - - -/* - * @unimplemented - */ -VOID -WINAPI -StartWsdpService() -{ - OutputDebugStringW(L"mswsock StartWsdpService stub called\n"); -} - - -/* - * @unimplemented - */ -VOID -WINAPI -StopWsdpService() -{ - OutputDebugStringW(L"mswsock StopWsdpService stub called\n"); -} - - -/* - * @unimplemented - */ -DWORD -WINAPI -SvchostPushServiceGlobals(DWORD Value) -{ - OutputDebugStringW(L"mswsock SvchostPushServiceGlobals stub called\n"); - - return 0; -} - - -/* - * @unimplemented - */ -VOID -WINAPI -ServiceMain(DWORD Unknown1, DWORD Unknown2) -{ - OutputDebugStringW(L"mswsock ServiceMain stub called\n"); -} diff --git a/dll/win32/mswsock/wsmobile/lpc.c b/dll/win32/mswsock/wsmobile/lpc.c new file mode 100644 index 00000000000..67c2fe25130 --- /dev/null +++ b/dll/win32/mswsock/wsmobile/lpc.c @@ -0,0 +1,64 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +HINSTANCE NlsMsgSourcemModuleHandle; + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +HINSTANCE NlsMsgSourcemModuleHandle; + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +HINSTANCE NlsMsgSourcemModuleHandle; + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +HINSTANCE NlsMsgSourcemModuleHandle; + +/* FUNCTIONS *****************************************************************/ + diff --git a/dll/win32/mswsock/wsmobile/nsp.c b/dll/win32/mswsock/wsmobile/nsp.c new file mode 100644 index 00000000000..70d21f483d6 --- /dev/null +++ b/dll/win32/mswsock/wsmobile/nsp.c @@ -0,0 +1,112 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +LONG gWSM_NSPStartupRef; +LONG gWSM_NSPCallRef; +GUID gNLANamespaceGuid = NLA_NAMESPACE_GUID; + +/* FUNCTIONS *****************************************************************/ + +INT +WINAPI +WSM_NSPStartup(IN LPGUID lpProviderId, + IN OUT LPNSP_ROUTINE lpsnpRoutines) +{ + /* Go away */ + SetLastError(WSAEINVAL); + return SOCKET_ERROR; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +LONG gWSM_NSPStartupRef; +LONG gWSM_NSPCallRef; +GUID gNLANamespaceGuid = NLA_NAMESPACE_GUID; + +/* FUNCTIONS *****************************************************************/ + +INT +WINAPI +WSM_NSPStartup(IN LPGUID lpProviderId, + IN OUT LPNSP_ROUTINE lpsnpRoutines) +{ + /* Go away */ + SetLastError(WSAEINVAL); + return SOCKET_ERROR; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +LONG gWSM_NSPStartupRef; +LONG gWSM_NSPCallRef; +GUID gNLANamespaceGuid = NLA_NAMESPACE_GUID; + +/* FUNCTIONS *****************************************************************/ + +INT +WINAPI +WSM_NSPStartup(IN LPGUID lpProviderId, + IN OUT LPNSP_ROUTINE lpsnpRoutines) +{ + /* Go away */ + SetLastError(WSAEINVAL); + return SOCKET_ERROR; +} + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +LONG gWSM_NSPStartupRef; +LONG gWSM_NSPCallRef; +GUID gNLANamespaceGuid = NLA_NAMESPACE_GUID; + +/* FUNCTIONS *****************************************************************/ + +INT +WINAPI +WSM_NSPStartup(IN LPGUID lpProviderId, + IN OUT LPNSP_ROUTINE lpsnpRoutines) +{ + /* Go away */ + SetLastError(WSAEINVAL); + return SOCKET_ERROR; +} + diff --git a/dll/win32/mswsock/wsmobile/service.c b/dll/win32/mswsock/wsmobile/service.c new file mode 100644 index 00000000000..3e062e90d63 --- /dev/null +++ b/dll/win32/mswsock/wsmobile/service.c @@ -0,0 +1,56 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + diff --git a/dll/win32/mswsock/wsmobile/update.c b/dll/win32/mswsock/wsmobile/update.c new file mode 100644 index 00000000000..3e062e90d63 --- /dev/null +++ b/dll/win32/mswsock/wsmobile/update.c @@ -0,0 +1,56 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Winsock 2 SPI + * FILE: lib/mswsock/lib/init.c + * PURPOSE: DLL Initialization + */ + +/* INCLUDES ******************************************************************/ +#include "msafd.h" + +/* DATA **********************************************************************/ + +/* FUNCTIONS *****************************************************************/ + From f21110d99f56365e17b42d7bdc66d05102c2f06d Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sat, 6 Feb 2010 02:56:20 +0000 Subject: [PATCH 12/24] - New winsock (part 3 of x) - Implement DnsApiAlloc and DnsApiFree svn path=/branches/aicom-network-branch/; revision=45450 --- dll/win32/dnsapi/dnsapi.rbuild | 2 +- dll/win32/dnsapi/dnsapi.spec | 2 + dll/win32/dnsapi/dnsapi/free.c | 41 ---------- dll/win32/dnsapi/dnsapi/memory.c | 128 +++++++++++++++++++++++++++++++ 4 files changed, 131 insertions(+), 42 deletions(-) delete mode 100644 dll/win32/dnsapi/dnsapi/free.c create mode 100644 dll/win32/dnsapi/dnsapi/memory.c diff --git a/dll/win32/dnsapi/dnsapi.rbuild b/dll/win32/dnsapi/dnsapi.rbuild index 08acd54a22a..524492d1687 100644 --- a/dll/win32/dnsapi/dnsapi.rbuild +++ b/dll/win32/dnsapi/dnsapi.rbuild @@ -13,7 +13,7 @@ adns.c context.c - free.c + memory.c names.c query.c stubs.c diff --git a/dll/win32/dnsapi/dnsapi.spec b/dll/win32/dnsapi/dnsapi.spec index a89730f4755..91ca7214c8f 100644 --- a/dll/win32/dnsapi/dnsapi.spec +++ b/dll/win32/dnsapi/dnsapi.spec @@ -6,6 +6,8 @@ @ stub DnsAddRecordSet_W @ stub DnsAllocateRecord @ stub DnsApiHeapReset +@ stdcall DnsApiAlloc(long) +@ stdcall DnsApiFree(ptr) @ stub DnsAsyncRegisterHostAddrs_A @ stub DnsAsyncRegisterHostAddrs_UTF8 @ stub DnsAsyncRegisterHostAddrs_W diff --git a/dll/win32/dnsapi/dnsapi/free.c b/dll/win32/dnsapi/dnsapi/free.c deleted file mode 100644 index 27ac7ddcea7..00000000000 --- a/dll/win32/dnsapi/dnsapi/free.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/dnsapi/dnsapi/free.c - * PURPOSE: DNSAPI functions built on the ADNS library. - * PROGRAMER: Art Yerkes - * UPDATE HISTORY: - * 12/15/03 -- Created - */ - -#include "precomp.h" - -#define NDEBUG -#include - -VOID WINAPI -DnsFree(PVOID Data, - DNS_FREE_TYPE FreeType) -{ - switch(FreeType) - { - case DnsFreeFlat: - RtlFreeHeap( RtlGetProcessHeap(), 0, Data ); - break; - - case DnsFreeRecordList: - DnsIntFreeRecordList( (PDNS_RECORD)Data ); - break; - - case DnsFreeParsedMessageFields: - /* assert( FALSE ); XXX arty not yet implemented. */ - break; - } -} - -VOID WINAPI -DnsRecordListFree(PDNS_RECORD Data, - DNS_FREE_TYPE FreeType) -{ - DnsFree(Data, FreeType); -} diff --git a/dll/win32/dnsapi/dnsapi/memory.c b/dll/win32/dnsapi/dnsapi/memory.c new file mode 100644 index 00000000000..6be36d3ad97 --- /dev/null +++ b/dll/win32/dnsapi/dnsapi/memory.c @@ -0,0 +1,128 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/dnsapi/dnsapi/memory.c + * PURPOSE: DNSAPI functions built on the ADNS library. + * PROGRAMER: Art Yerkes + * UPDATE HISTORY: + * 12/15/03 -- Created + */ + +#include "precomp.h" + +#define NDEBUG +#include + +VOID +WINAPI +DnsApiFree(IN PVOID Data) +{ + RtlFreeHeap(RtlGetProcessHeap(), 0, Data); +} + +PVOID +WINAPI +DnsApiAlloc(IN DWORD Size) +{ + return RtlAllocateHeap(RtlGetProcessHeap(), 0, Size); +} + +PVOID +WINAPI +DnsQueryConfigAllocEx(IN DNS_CONFIG_TYPE Config, + OUT PVOID pBuffer, + IN OUT PDWORD pBufferLength) +{ + return NULL; +} + +VOID WINAPI +DnsFree(PVOID Data, + DNS_FREE_TYPE FreeType) +{ + switch(FreeType) + { + case DnsFreeFlat: + RtlFreeHeap( RtlGetProcessHeap(), 0, Data ); + break; + + case DnsFreeRecordList: + DnsIntFreeRecordList( (PDNS_RECORD)Data ); + break; + + case DnsFreeParsedMessageFields: + /* assert( FALSE ); XXX arty not yet implemented. */ + break; + } +} + +VOID WINAPI +DnsRecordListFree(PDNS_RECORD Data, + DNS_FREE_TYPE FreeType) +{ + DnsFree(Data, FreeType); +} +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/dnsapi/dnsapi/free.c + * PURPOSE: DNSAPI functions built on the ADNS library. + * PROGRAMER: Art Yerkes + * UPDATE HISTORY: + * 12/15/03 -- Created + */ + +#include "precomp.h" + +#define NDEBUG +#include + +VOID +WINAPI +DnsApiFree(IN PVOID Data) +{ + RtlFreeHeap(RtlGetProcessHeap(), 0, Data); +} + +PVOID +WINAPI +DnsApiAlloc(IN DWORD Size) +{ + return RtlAllocateHeap(RtlGetProcessHeap(), 0, Size); +} + +PVOID +WINAPI +DnsQueryConfigAllocEx(IN DNS_CONFIG_TYPE Config, + OUT PVOID pBuffer, + IN OUT PDWORD pBufferLength) +{ + return NULL; +} + +VOID WINAPI +DnsFree(PVOID Data, + DNS_FREE_TYPE FreeType) +{ + switch(FreeType) + { + case DnsFreeFlat: + RtlFreeHeap( RtlGetProcessHeap(), 0, Data ); + break; + + case DnsFreeRecordList: + DnsIntFreeRecordList( (PDNS_RECORD)Data ); + break; + + case DnsFreeParsedMessageFields: + /* assert( FALSE ); XXX arty not yet implemented. */ + break; + } +} + +VOID WINAPI +DnsRecordListFree(PDNS_RECORD Data, + DNS_FREE_TYPE FreeType) +{ + DnsFree(Data, FreeType); +} From d5fa02d2c30f64a1e2c37c3d2f1f224eacf3b62d Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sat, 6 Feb 2010 02:58:47 +0000 Subject: [PATCH 13/24] - New winsock (part 4 of x) - Rename ws2_32_new to ws2_32 svn path=/branches/aicom-network-branch/; revision=45451 --- dll/win32/{ws2_32_new => ws2_32}/inc/ws2_32.h | 0 dll/win32/{ws2_32_new => ws2_32}/inc/ws2_32p.h | 0 dll/win32/{ws2_32_new => ws2_32}/src/addrconv.c | 0 dll/win32/{ws2_32_new => ws2_32}/src/addrinfo.c | 0 dll/win32/{ws2_32_new => ws2_32}/src/async.c | 0 dll/win32/{ws2_32_new => ws2_32}/src/bhook.c | 0 dll/win32/{ws2_32_new => ws2_32}/src/dcatalog.c | 0 dll/win32/{ws2_32_new => ws2_32}/src/dcatitem.c | 0 dll/win32/{ws2_32_new => ws2_32}/src/dllmain.c | 0 dll/win32/{ws2_32_new => ws2_32}/src/dprocess.c | 0 dll/win32/{ws2_32_new => ws2_32}/src/dprovide.c | 0 dll/win32/{ws2_32_new => ws2_32}/src/dsocket.c | 0 dll/win32/{ws2_32_new => ws2_32}/src/dthread.c | 0 dll/win32/{ws2_32_new => ws2_32}/src/dupsock.c | 0 dll/win32/{ws2_32_new => ws2_32}/src/enumprot.c | 0 dll/win32/{ws2_32_new => ws2_32}/src/event.c | 0 dll/win32/{ws2_32_new => ws2_32}/src/getproto.c | 0 dll/win32/{ws2_32_new => ws2_32}/src/getxbyxx.c | 0 dll/win32/{ws2_32_new => ws2_32}/src/ioctl.c | 0 dll/win32/{ws2_32_new => ws2_32}/src/nscatalo.c | 0 dll/win32/{ws2_32_new => ws2_32}/src/nscatent.c | 0 dll/win32/{ws2_32_new => ws2_32}/src/nspinstl.c | 0 dll/win32/{ws2_32_new => ws2_32}/src/nsprovid.c | 0 dll/win32/{ws2_32_new => ws2_32}/src/nsquery.c | 0 dll/win32/{ws2_32_new => ws2_32}/src/qos.c | 0 dll/win32/{ws2_32_new => ws2_32}/src/qshelpr.c | 0 dll/win32/{ws2_32_new => ws2_32}/src/rasdial.c | 0 dll/win32/{ws2_32_new => ws2_32}/src/recv.c | 0 dll/win32/{ws2_32_new => ws2_32}/src/rnr.c | 0 dll/win32/{ws2_32_new => ws2_32}/src/scihlpr.c | 0 dll/win32/{ws2_32_new => ws2_32}/src/select.c | 0 dll/win32/{ws2_32_new => ws2_32}/src/send.c | 0 dll/win32/{ws2_32_new => ws2_32}/src/sockctrl.c | 0 dll/win32/{ws2_32_new => ws2_32}/src/socklife.c | 0 dll/win32/{ws2_32_new => ws2_32}/src/spinstal.c | 0 dll/win32/{ws2_32_new => ws2_32}/src/sputil.c | 0 dll/win32/{ws2_32_new => ws2_32}/src/startup.c | 0 dll/win32/{ws2_32_new => ws2_32}/src/wsautil.c | 0 dll/win32/{ws2_32_new => ws2_32}/ws2_32.rbuild | 4 ++-- dll/win32/{ws2_32_new => ws2_32}/ws2_32.rc | 0 dll/win32/{ws2_32_new => ws2_32}/ws2_32.spec | 0 41 files changed, 2 insertions(+), 2 deletions(-) rename dll/win32/{ws2_32_new => ws2_32}/inc/ws2_32.h (100%) rename dll/win32/{ws2_32_new => ws2_32}/inc/ws2_32p.h (100%) rename dll/win32/{ws2_32_new => ws2_32}/src/addrconv.c (100%) rename dll/win32/{ws2_32_new => ws2_32}/src/addrinfo.c (100%) rename dll/win32/{ws2_32_new => ws2_32}/src/async.c (100%) rename dll/win32/{ws2_32_new => ws2_32}/src/bhook.c (100%) rename dll/win32/{ws2_32_new => ws2_32}/src/dcatalog.c (100%) rename dll/win32/{ws2_32_new => ws2_32}/src/dcatitem.c (100%) rename dll/win32/{ws2_32_new => ws2_32}/src/dllmain.c (100%) rename dll/win32/{ws2_32_new => ws2_32}/src/dprocess.c (100%) rename dll/win32/{ws2_32_new => ws2_32}/src/dprovide.c (100%) rename dll/win32/{ws2_32_new => ws2_32}/src/dsocket.c (100%) rename dll/win32/{ws2_32_new => ws2_32}/src/dthread.c (100%) rename dll/win32/{ws2_32_new => ws2_32}/src/dupsock.c (100%) rename dll/win32/{ws2_32_new => ws2_32}/src/enumprot.c (100%) rename dll/win32/{ws2_32_new => ws2_32}/src/event.c (100%) rename dll/win32/{ws2_32_new => ws2_32}/src/getproto.c (100%) rename dll/win32/{ws2_32_new => ws2_32}/src/getxbyxx.c (100%) rename dll/win32/{ws2_32_new => ws2_32}/src/ioctl.c (100%) rename dll/win32/{ws2_32_new => ws2_32}/src/nscatalo.c (100%) rename dll/win32/{ws2_32_new => ws2_32}/src/nscatent.c (100%) rename dll/win32/{ws2_32_new => ws2_32}/src/nspinstl.c (100%) rename dll/win32/{ws2_32_new => ws2_32}/src/nsprovid.c (100%) rename dll/win32/{ws2_32_new => ws2_32}/src/nsquery.c (100%) rename dll/win32/{ws2_32_new => ws2_32}/src/qos.c (100%) rename dll/win32/{ws2_32_new => ws2_32}/src/qshelpr.c (100%) rename dll/win32/{ws2_32_new => ws2_32}/src/rasdial.c (100%) rename dll/win32/{ws2_32_new => ws2_32}/src/recv.c (100%) rename dll/win32/{ws2_32_new => ws2_32}/src/rnr.c (100%) rename dll/win32/{ws2_32_new => ws2_32}/src/scihlpr.c (100%) rename dll/win32/{ws2_32_new => ws2_32}/src/select.c (100%) rename dll/win32/{ws2_32_new => ws2_32}/src/send.c (100%) rename dll/win32/{ws2_32_new => ws2_32}/src/sockctrl.c (100%) rename dll/win32/{ws2_32_new => ws2_32}/src/socklife.c (100%) rename dll/win32/{ws2_32_new => ws2_32}/src/spinstal.c (100%) rename dll/win32/{ws2_32_new => ws2_32}/src/sputil.c (100%) rename dll/win32/{ws2_32_new => ws2_32}/src/startup.c (100%) rename dll/win32/{ws2_32_new => ws2_32}/src/wsautil.c (100%) rename dll/win32/{ws2_32_new => ws2_32}/ws2_32.rbuild (88%) rename dll/win32/{ws2_32_new => ws2_32}/ws2_32.rc (100%) rename dll/win32/{ws2_32_new => ws2_32}/ws2_32.spec (100%) diff --git a/dll/win32/ws2_32_new/inc/ws2_32.h b/dll/win32/ws2_32/inc/ws2_32.h similarity index 100% rename from dll/win32/ws2_32_new/inc/ws2_32.h rename to dll/win32/ws2_32/inc/ws2_32.h diff --git a/dll/win32/ws2_32_new/inc/ws2_32p.h b/dll/win32/ws2_32/inc/ws2_32p.h similarity index 100% rename from dll/win32/ws2_32_new/inc/ws2_32p.h rename to dll/win32/ws2_32/inc/ws2_32p.h diff --git a/dll/win32/ws2_32_new/src/addrconv.c b/dll/win32/ws2_32/src/addrconv.c similarity index 100% rename from dll/win32/ws2_32_new/src/addrconv.c rename to dll/win32/ws2_32/src/addrconv.c diff --git a/dll/win32/ws2_32_new/src/addrinfo.c b/dll/win32/ws2_32/src/addrinfo.c similarity index 100% rename from dll/win32/ws2_32_new/src/addrinfo.c rename to dll/win32/ws2_32/src/addrinfo.c diff --git a/dll/win32/ws2_32_new/src/async.c b/dll/win32/ws2_32/src/async.c similarity index 100% rename from dll/win32/ws2_32_new/src/async.c rename to dll/win32/ws2_32/src/async.c diff --git a/dll/win32/ws2_32_new/src/bhook.c b/dll/win32/ws2_32/src/bhook.c similarity index 100% rename from dll/win32/ws2_32_new/src/bhook.c rename to dll/win32/ws2_32/src/bhook.c diff --git a/dll/win32/ws2_32_new/src/dcatalog.c b/dll/win32/ws2_32/src/dcatalog.c similarity index 100% rename from dll/win32/ws2_32_new/src/dcatalog.c rename to dll/win32/ws2_32/src/dcatalog.c diff --git a/dll/win32/ws2_32_new/src/dcatitem.c b/dll/win32/ws2_32/src/dcatitem.c similarity index 100% rename from dll/win32/ws2_32_new/src/dcatitem.c rename to dll/win32/ws2_32/src/dcatitem.c diff --git a/dll/win32/ws2_32_new/src/dllmain.c b/dll/win32/ws2_32/src/dllmain.c similarity index 100% rename from dll/win32/ws2_32_new/src/dllmain.c rename to dll/win32/ws2_32/src/dllmain.c diff --git a/dll/win32/ws2_32_new/src/dprocess.c b/dll/win32/ws2_32/src/dprocess.c similarity index 100% rename from dll/win32/ws2_32_new/src/dprocess.c rename to dll/win32/ws2_32/src/dprocess.c diff --git a/dll/win32/ws2_32_new/src/dprovide.c b/dll/win32/ws2_32/src/dprovide.c similarity index 100% rename from dll/win32/ws2_32_new/src/dprovide.c rename to dll/win32/ws2_32/src/dprovide.c diff --git a/dll/win32/ws2_32_new/src/dsocket.c b/dll/win32/ws2_32/src/dsocket.c similarity index 100% rename from dll/win32/ws2_32_new/src/dsocket.c rename to dll/win32/ws2_32/src/dsocket.c diff --git a/dll/win32/ws2_32_new/src/dthread.c b/dll/win32/ws2_32/src/dthread.c similarity index 100% rename from dll/win32/ws2_32_new/src/dthread.c rename to dll/win32/ws2_32/src/dthread.c diff --git a/dll/win32/ws2_32_new/src/dupsock.c b/dll/win32/ws2_32/src/dupsock.c similarity index 100% rename from dll/win32/ws2_32_new/src/dupsock.c rename to dll/win32/ws2_32/src/dupsock.c diff --git a/dll/win32/ws2_32_new/src/enumprot.c b/dll/win32/ws2_32/src/enumprot.c similarity index 100% rename from dll/win32/ws2_32_new/src/enumprot.c rename to dll/win32/ws2_32/src/enumprot.c diff --git a/dll/win32/ws2_32_new/src/event.c b/dll/win32/ws2_32/src/event.c similarity index 100% rename from dll/win32/ws2_32_new/src/event.c rename to dll/win32/ws2_32/src/event.c diff --git a/dll/win32/ws2_32_new/src/getproto.c b/dll/win32/ws2_32/src/getproto.c similarity index 100% rename from dll/win32/ws2_32_new/src/getproto.c rename to dll/win32/ws2_32/src/getproto.c diff --git a/dll/win32/ws2_32_new/src/getxbyxx.c b/dll/win32/ws2_32/src/getxbyxx.c similarity index 100% rename from dll/win32/ws2_32_new/src/getxbyxx.c rename to dll/win32/ws2_32/src/getxbyxx.c diff --git a/dll/win32/ws2_32_new/src/ioctl.c b/dll/win32/ws2_32/src/ioctl.c similarity index 100% rename from dll/win32/ws2_32_new/src/ioctl.c rename to dll/win32/ws2_32/src/ioctl.c diff --git a/dll/win32/ws2_32_new/src/nscatalo.c b/dll/win32/ws2_32/src/nscatalo.c similarity index 100% rename from dll/win32/ws2_32_new/src/nscatalo.c rename to dll/win32/ws2_32/src/nscatalo.c diff --git a/dll/win32/ws2_32_new/src/nscatent.c b/dll/win32/ws2_32/src/nscatent.c similarity index 100% rename from dll/win32/ws2_32_new/src/nscatent.c rename to dll/win32/ws2_32/src/nscatent.c diff --git a/dll/win32/ws2_32_new/src/nspinstl.c b/dll/win32/ws2_32/src/nspinstl.c similarity index 100% rename from dll/win32/ws2_32_new/src/nspinstl.c rename to dll/win32/ws2_32/src/nspinstl.c diff --git a/dll/win32/ws2_32_new/src/nsprovid.c b/dll/win32/ws2_32/src/nsprovid.c similarity index 100% rename from dll/win32/ws2_32_new/src/nsprovid.c rename to dll/win32/ws2_32/src/nsprovid.c diff --git a/dll/win32/ws2_32_new/src/nsquery.c b/dll/win32/ws2_32/src/nsquery.c similarity index 100% rename from dll/win32/ws2_32_new/src/nsquery.c rename to dll/win32/ws2_32/src/nsquery.c diff --git a/dll/win32/ws2_32_new/src/qos.c b/dll/win32/ws2_32/src/qos.c similarity index 100% rename from dll/win32/ws2_32_new/src/qos.c rename to dll/win32/ws2_32/src/qos.c diff --git a/dll/win32/ws2_32_new/src/qshelpr.c b/dll/win32/ws2_32/src/qshelpr.c similarity index 100% rename from dll/win32/ws2_32_new/src/qshelpr.c rename to dll/win32/ws2_32/src/qshelpr.c diff --git a/dll/win32/ws2_32_new/src/rasdial.c b/dll/win32/ws2_32/src/rasdial.c similarity index 100% rename from dll/win32/ws2_32_new/src/rasdial.c rename to dll/win32/ws2_32/src/rasdial.c diff --git a/dll/win32/ws2_32_new/src/recv.c b/dll/win32/ws2_32/src/recv.c similarity index 100% rename from dll/win32/ws2_32_new/src/recv.c rename to dll/win32/ws2_32/src/recv.c diff --git a/dll/win32/ws2_32_new/src/rnr.c b/dll/win32/ws2_32/src/rnr.c similarity index 100% rename from dll/win32/ws2_32_new/src/rnr.c rename to dll/win32/ws2_32/src/rnr.c diff --git a/dll/win32/ws2_32_new/src/scihlpr.c b/dll/win32/ws2_32/src/scihlpr.c similarity index 100% rename from dll/win32/ws2_32_new/src/scihlpr.c rename to dll/win32/ws2_32/src/scihlpr.c diff --git a/dll/win32/ws2_32_new/src/select.c b/dll/win32/ws2_32/src/select.c similarity index 100% rename from dll/win32/ws2_32_new/src/select.c rename to dll/win32/ws2_32/src/select.c diff --git a/dll/win32/ws2_32_new/src/send.c b/dll/win32/ws2_32/src/send.c similarity index 100% rename from dll/win32/ws2_32_new/src/send.c rename to dll/win32/ws2_32/src/send.c diff --git a/dll/win32/ws2_32_new/src/sockctrl.c b/dll/win32/ws2_32/src/sockctrl.c similarity index 100% rename from dll/win32/ws2_32_new/src/sockctrl.c rename to dll/win32/ws2_32/src/sockctrl.c diff --git a/dll/win32/ws2_32_new/src/socklife.c b/dll/win32/ws2_32/src/socklife.c similarity index 100% rename from dll/win32/ws2_32_new/src/socklife.c rename to dll/win32/ws2_32/src/socklife.c diff --git a/dll/win32/ws2_32_new/src/spinstal.c b/dll/win32/ws2_32/src/spinstal.c similarity index 100% rename from dll/win32/ws2_32_new/src/spinstal.c rename to dll/win32/ws2_32/src/spinstal.c diff --git a/dll/win32/ws2_32_new/src/sputil.c b/dll/win32/ws2_32/src/sputil.c similarity index 100% rename from dll/win32/ws2_32_new/src/sputil.c rename to dll/win32/ws2_32/src/sputil.c diff --git a/dll/win32/ws2_32_new/src/startup.c b/dll/win32/ws2_32/src/startup.c similarity index 100% rename from dll/win32/ws2_32_new/src/startup.c rename to dll/win32/ws2_32/src/startup.c diff --git a/dll/win32/ws2_32_new/src/wsautil.c b/dll/win32/ws2_32/src/wsautil.c similarity index 100% rename from dll/win32/ws2_32_new/src/wsautil.c rename to dll/win32/ws2_32/src/wsautil.c diff --git a/dll/win32/ws2_32_new/ws2_32.rbuild b/dll/win32/ws2_32/ws2_32.rbuild similarity index 88% rename from dll/win32/ws2_32_new/ws2_32.rbuild rename to dll/win32/ws2_32/ws2_32.rbuild index 88bce90550f..0f61e41be8e 100644 --- a/dll/win32/ws2_32_new/ws2_32.rbuild +++ b/dll/win32/ws2_32/ws2_32.rbuild @@ -1,6 +1,6 @@ - + - inc + inc include/reactos/winsock wine diff --git a/dll/win32/ws2_32_new/ws2_32.rc b/dll/win32/ws2_32/ws2_32.rc similarity index 100% rename from dll/win32/ws2_32_new/ws2_32.rc rename to dll/win32/ws2_32/ws2_32.rc diff --git a/dll/win32/ws2_32_new/ws2_32.spec b/dll/win32/ws2_32/ws2_32.spec similarity index 100% rename from dll/win32/ws2_32_new/ws2_32.spec rename to dll/win32/ws2_32/ws2_32.spec From eb3569ff5b5406170bac2811a2df00fc839b013d Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sat, 6 Feb 2010 03:00:31 +0000 Subject: [PATCH 14/24] - New winsock (part 5 of x) - Add winsock headers svn path=/branches/aicom-network-branch/; revision=45452 --- include/reactos/winsock/msafd.h | 104 ++ include/reactos/winsock/msafdlib.h | 1656 +++++++++++++++++++++++++++ include/reactos/winsock/mswinsock.h | 38 + include/reactos/winsock/rnr20lib.h | 530 +++++++++ include/reactos/winsock/wsmobile.h | 168 +++ 5 files changed, 2496 insertions(+) create mode 100644 include/reactos/winsock/msafd.h create mode 100644 include/reactos/winsock/msafdlib.h create mode 100644 include/reactos/winsock/mswinsock.h create mode 100644 include/reactos/winsock/rnr20lib.h create mode 100644 include/reactos/winsock/wsmobile.h diff --git a/include/reactos/winsock/msafd.h b/include/reactos/winsock/msafd.h new file mode 100644 index 00000000000..1d94bab7f42 --- /dev/null +++ b/include/reactos/winsock/msafd.h @@ -0,0 +1,104 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Ancillary Function Driver DLL + * FILE: include/msafd.h + * PURPOSE: Ancillary Function Driver DLL header + */ + +#define NTOS_MODE_USER +#define WIN32_NO_STATUS +#define _CRT_SECURE_NO_DEPRECATE +#define _WIN32_WINNT 0x502 + +/* Winsock Headers */ +#include +#include +#include +#include +#include +#include +#include + +/* NDK */ +#include +#include +#include +#include +#include + +/* Shared NSP Header */ +#include + +/* Winsock 2 API Helper Header */ +#include + +/* Winsock Helper Header */ +#include + +/* AFD/TDI Headers */ +#include +#include + +/* DNSLIB/API Header */ +#include +#include + +/* Library Headers */ +#include "msafdlib.h" +#include "rnr20lib.h" +#include "wsmobile.h" +#include "mswinsock.h" + +/* EOF */ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Ancillary Function Driver DLL + * FILE: include/msafd.h + * PURPOSE: Ancillary Function Driver DLL header + */ + +#define NTOS_MODE_USER +#define WIN32_NO_STATUS +#define _CRT_SECURE_NO_DEPRECATE +#define _WIN32_WINNT 0x502 + +/* Winsock Headers */ +#include +#include +#include +#include +#include +#include +#include + +/* NDK */ +#include +#include +#include +#include +#include + +/* Shared NSP Header */ +#include + +/* Winsock 2 API Helper Header */ +#include + +/* Winsock Helper Header */ +#include + +/* AFD/TDI Headers */ +#include +#include + +/* DNSLIB/API Header */ +#include +#include + +/* Library Headers */ +#include "msafdlib.h" +#include "rnr20lib.h" +#include "wsmobile.h" +#include "mswinsock.h" + +/* EOF */ diff --git a/include/reactos/winsock/msafdlib.h b/include/reactos/winsock/msafdlib.h new file mode 100644 index 00000000000..2c5548b8af6 --- /dev/null +++ b/include/reactos/winsock/msafdlib.h @@ -0,0 +1,1656 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS WinSock 2 NSP + * FILE: lib/mswsock/sock.h + * PURPOSE: Winsock 2 SPI Utility Header + */ + +#define NO_BLOCKING_HOOK 0 +#define MAYBE_BLOCKING_HOOK 1 +#define ALWAYS_BLOCKING_HOOK 2 + +#define NO_TIMEOUT 0 +#define SEND_TIMEOUT 1 +#define RECV_TIMEOUT 2 + +#define MAX_TDI_ADDRESS_LENGTH 32 + +#define WSA_FLAG_MULTIPOINT_ALL (WSA_FLAG_MULTIPOINT_C_ROOT |\ + WSA_FLAG_MULTIPOINT_C_LEAF |\ + WSA_FLAG_MULTIPOINT_D_ROOT |\ + WSA_FLAG_MULTIPOINT_D_LEAF) + + +/* Socket State */ +typedef enum _SOCKET_STATE +{ + SocketUndefined = -1, + SocketOpen, + SocketBound, + SocketBoundUdp, + SocketConnected, + SocketClosed +} SOCKET_STATE, *PSOCKET_STATE; + +/* + * Shared Socket Information. + * It's called shared because we send it to Kernel-Mode for safekeeping + */ +typedef struct _SOCK_SHARED_INFO { + SOCKET_STATE State; + INT AddressFamily; + INT SocketType; + INT Protocol; + INT SizeOfLocalAddress; + INT SizeOfRemoteAddress; + struct linger LingerData; + ULONG SendTimeout; + ULONG RecvTimeout; + ULONG SizeOfRecvBuffer; + ULONG SizeOfSendBuffer; + struct { + BOOLEAN Listening:1; + BOOLEAN Broadcast:1; + BOOLEAN Debug:1; + BOOLEAN OobInline:1; + BOOLEAN ReuseAddresses:1; + BOOLEAN ExclusiveAddressUse:1; + BOOLEAN NonBlocking:1; + BOOLEAN DontUseWildcard:1; + BOOLEAN ReceiveShutdown:1; + BOOLEAN SendShutdown:1; + BOOLEAN UseDelayedAcceptance:1; + BOOLEAN UseSAN:1; + }; // Flags + DWORD CreateFlags; + DWORD CatalogEntryId; + DWORD ServiceFlags1; + DWORD ProviderFlags; + GROUP GroupID; + DWORD GroupType; + INT GroupPriority; + INT SocketLastError; + HWND hWnd; + LONG Unknown; + DWORD SequenceNumber; + UINT wMsg; + LONG AsyncEvents; + LONG AsyncDisabledEvents; +} SOCK_SHARED_INFO, *PSOCK_SHARED_INFO; + +/* Socket Helper Data. Holds information about the WSH Libraries */ +typedef struct _HELPER_DATA { + LIST_ENTRY Helpers; + LONG RefCount; + HANDLE hInstance; + INT MinWSAddressLength; + INT MaxWSAddressLength; + INT MinTDIAddressLength; + INT MaxTDIAddressLength; + BOOLEAN UseDelayedAcceptance; + PWINSOCK_MAPPING Mapping; + PWSH_OPEN_SOCKET WSHOpenSocket; + PWSH_OPEN_SOCKET2 WSHOpenSocket2; + PWSH_JOIN_LEAF WSHJoinLeaf; + PWSH_NOTIFY WSHNotify; + PWSH_GET_SOCKET_INFORMATION WSHGetSocketInformation; + PWSH_SET_SOCKET_INFORMATION WSHSetSocketInformation; + PWSH_GET_SOCKADDR_TYPE WSHGetSockaddrType; + PWSH_GET_WILDCARD_SOCKADDR WSHGetWildcardSockaddr; + PWSH_GET_BROADCAST_SOCKADDR WSHGetBroadcastSockaddr; + PWSH_ADDRESS_TO_STRING WSHAddressToString; + PWSH_STRING_TO_ADDRESS WSHStringToAddress; + PWSH_IOCTL WSHIoctl; + WCHAR TransportName[1]; +} HELPER_DATA, *PHELPER_DATA; + +typedef struct _ASYNC_DATA +{ + struct _SOCKET_INFORMATION *ParentSocket; + DWORD SequenceNumber; + IO_STATUS_BLOCK IoStatusBlock; + AFD_POLL_INFO AsyncSelectInfo; +} ASYNC_DATA, *PASYNC_DATA; + +/* The actual Socket Structure represented by a handle. Internal to us */ +typedef struct _SOCKET_INFORMATION { + union { + WSH_HANDLE WshContext; + struct { + LONG RefCount; + SOCKET Handle; + }; + }; + SOCK_SHARED_INFO SharedData; + GUID ProviderId; + DWORD HelperEvents; + PHELPER_DATA HelperData; + PVOID HelperContext; + PSOCKADDR LocalAddress; + PSOCKADDR RemoteAddress; + HANDLE TdiAddressHandle; + HANDLE TdiConnectionHandle; + PASYNC_DATA AsyncData; + HANDLE EventObject; + LONG NetworkEvents; + CRITICAL_SECTION Lock; + BOOL DontUseSan; + PVOID SanData; +} SOCKET_INFORMATION, *PSOCKET_INFORMATION; + +/* The blob of data we send to Kernel-Mode for safekeeping */ +typedef struct _SOCKET_CONTEXT { + SOCK_SHARED_INFO SharedData; + ULONG SizeOfHelperData; + ULONG Padding; + SOCKADDR LocalAddress; + SOCKADDR RemoteAddress; + /* Plus Helper Data */ +} SOCKET_CONTEXT, *PSOCKET_CONTEXT; + +typedef struct _SOCK_RW_LOCK +{ + volatile LONG ReaderCount; + HANDLE WriterWaitEvent; + RTL_CRITICAL_SECTION Lock; +} SOCK_RW_LOCK, *PSOCK_RW_LOCK; + +typedef struct _WINSOCK_TEB_DATA +{ + HANDLE EventHandle; + SOCKET SocketHandle; + PAFD_ACCEPT_DATA AcceptData; + LONG PendingAPCs; + BOOLEAN CancelIo; + ULONG Unknown; + PVOID RnrThreadData; +} WINSOCK_TEB_DATA, *PWINSOCK_TEB_DATA; + +typedef INT +(WINAPI *PICF_CONNECT)(PVOID IcfData); + +typedef struct _SOCK_ICF_DATA +{ + HANDLE IcfHandle; + PVOID IcfOpenDynamicFwPort; + PICF_CONNECT IcfConnect; + PVOID IcfDisconnect; + HINSTANCE DllHandle; +} SOCK_ICF_DATA, *PSOCK_ICF_DATA; + +typedef PVOID +(NTAPI *PRTL_HEAP_ALLOCATE)( + IN HANDLE Heap, + IN ULONG Flags, + IN ULONG Size +); + +extern HANDLE SockPrivateHeap; +extern PRTL_HEAP_ALLOCATE SockAllocateHeapRoutine; +extern SOCK_RW_LOCK SocketGlobalLock; +extern PWAH_HANDLE_TABLE SockContextTable; +extern LPWSPUPCALLTABLE SockUpcallTable; +extern BOOL SockProcessTerminating; +extern LONG SockWspStartupCount; +extern DWORD SockSendBufferWindow; +extern DWORD SockReceiveBufferWindow; +extern HANDLE SockAsyncQueuePort; +extern BOOLEAN SockAsyncSelectCalled; +extern LONG SockProcessPendingAPCCount; +extern HINSTANCE SockModuleHandle; +extern LONG gWSM_NSPStartupRef; +extern LONG gWSM_NSPCallRef; +extern LIST_ENTRY SockHelperDllListHead; +extern CRITICAL_SECTION MSWSOCK_SocketLock; +extern HINSTANCE NlsMsgSourcemModuleHandle; +extern PVOID SockBufferKeyTable; +extern ULONG SockBufferKeyTableSize; +extern LONG SockAsyncThreadReferenceCount; +extern BOOLEAN g_fRnrLockInit; +extern CRITICAL_SECTION g_RnrLock; + +BOOL +WSPAPI +MSWSOCK_Initialize(VOID); + +BOOL +WSPAPI +MSAFD_SockThreadInitialize(VOID); + +INT +WSPAPI +SockCreateAsyncQueuePort(VOID); + +PVOID +WSPAPI +SockInitializeHeap(IN HANDLE Heap, + IN ULONG Flags, + IN ULONG Size); + +NTSTATUS +WSPAPI +SockInitializeRwLockAndSpinCount( + IN PSOCK_RW_LOCK Lock, + IN ULONG SpinCount +); + +VOID +WSPAPI +SockAcquireRwLockExclusive(IN PSOCK_RW_LOCK Lock); + +VOID +WSPAPI +SockAcquireRwLockShared(IN PSOCK_RW_LOCK Lock); + +VOID +WSPAPI +SockReleaseRwLockExclusive(IN PSOCK_RW_LOCK Lock); + +VOID +WSPAPI +SockReleaseRwLockShared(IN PSOCK_RW_LOCK Lock); + +NTSTATUS +WSPAPI +SockDeleteRwLock(IN PSOCK_RW_LOCK Lock); + +INT +WSPAPI +SockGetConnectData(IN PSOCKET_INFORMATION Socket, + IN ULONG Ioctl, + IN PVOID Buffer, + IN ULONG BufferLength, + OUT PULONG BufferReturned); + +INT +WSPAPI +SockIsAddressConsistentWithConstrainedGroup(IN PSOCKET_INFORMATION Socket, + IN GROUP Group, + IN PSOCKADDR SocketAddress, + IN INT SocketAddressLength); + +BOOL +WSPAPI +SockWaitForSingleObject(IN HANDLE Handle, + IN SOCKET SocketHandle, + IN DWORD BlockingFlags, + IN DWORD TimeoutFlags); + +BOOLEAN +WSPAPI +SockIsSocketConnected(IN PSOCKET_INFORMATION Socket); + +INT +WSPAPI +SockNotifyHelperDll(IN PSOCKET_INFORMATION Socket, + IN DWORD Event); + +INT +WSPAPI +SockUpdateWindowSizes(IN PSOCKET_INFORMATION Socket, + IN BOOLEAN Force); + +INT +WSPAPI +SockBuildTdiAddress(OUT PTRANSPORT_ADDRESS TdiAddress, + IN PSOCKADDR Sockaddr, + IN INT SockaddrLength); + +INT +WSPAPI +SockBuildSockaddr(OUT PSOCKADDR Sockaddr, + OUT PINT SockaddrLength, + IN PTRANSPORT_ADDRESS TdiAddress); + +INT +WSPAPI +SockGetTdiHandles(IN PSOCKET_INFORMATION Socket); + +VOID +WSPAPI +SockIoCompletion(IN PVOID ApcContext, + IN PIO_STATUS_BLOCK IoStatusBlock, + DWORD Reserved); + +VOID +WSPAPI +SockCancelIo(IN SOCKET Handle); + +INT +WSPAPI +SockGetInformation(IN PSOCKET_INFORMATION Socket, + IN ULONG AfdInformationClass, + IN PVOID ExtraData OPTIONAL, + IN ULONG ExtraDataSize, + IN OUT PBOOLEAN Boolean OPTIONAL, + IN OUT PULONG Ulong OPTIONAL, + IN OUT PLARGE_INTEGER LargeInteger OPTIONAL); + +INT +WSPAPI +SockSetInformation(IN PSOCKET_INFORMATION Socket, + IN ULONG AfdInformationClass, + IN PBOOLEAN Boolean OPTIONAL, + IN PULONG Ulong OPTIONAL, + IN PLARGE_INTEGER LargeInteger OPTIONAL); + +INT +WSPAPI +SockSetHandleContext(IN PSOCKET_INFORMATION Socket); + +VOID +WSPAPI +SockDereferenceSocket(IN PSOCKET_INFORMATION Socket); + +VOID +WSPAPI +SockFreeHelperDll(IN PHELPER_DATA Helper); + +PSOCKET_INFORMATION +WSPAPI +SockFindAndReferenceSocket(IN SOCKET Handle, + IN BOOLEAN Import); + +INT +WSPAPI +SockEnterApiSlow(OUT PWINSOCK_TEB_DATA *ThreadData); + +VOID +WSPAPI +SockSanInitialize(VOID); + +VOID +WSPAPI +SockSanGetTcpipCatalogId(VOID); + +VOID +WSPAPI +CloseIcfConnection(IN PSOCK_ICF_DATA IcfData); + +VOID +WSPAPI +InitializeIcfConnection(IN PSOCK_ICF_DATA IcfData); + +VOID +WSPAPI +NewIcfConnection(IN PSOCK_ICF_DATA IcfData); + +INT +WSPAPI +NtStatusToSocketError(IN NTSTATUS Status); + +INT +WSPAPI +SockSocket(INT AddressFamily, + INT SocketType, + INT Protocol, + LPGUID ProviderId, + GROUP g, + DWORD dwFlags, + DWORD ProviderFlags, + DWORD ServiceFlags, + DWORD CatalogEntryId, + PSOCKET_INFORMATION *NewSocket); + +INT +WSPAPI +SockCloseSocket(IN PSOCKET_INFORMATION Socket); + +FORCEINLINE +INT +WSPAPI +SockEnterApiFast(OUT PWINSOCK_TEB_DATA *ThreadData) +{ + /* Make sure we aren't terminating and get our thread data */ + if (!(SockProcessTerminating) && + (SockWspStartupCount > 0) && + ((*ThreadData == NtCurrentTeb()->WinSockData))) + { + /* Everything is good, return */ + return NO_ERROR; + } + + /* Something didn't work out, use the slow path */ + return SockEnterApiSlow(ThreadData); +} + +FORCEINLINE +VOID +WSPAPI +SockDereferenceHelperDll(IN PHELPER_DATA Helper) +{ + /* Dereference and see if it's the last count */ + if (!InterlockedDecrement(&Helper->RefCount)) + { + /* Destroy the Helper DLL */ + SockFreeHelperDll(Helper); + } +} + +#define MSAFD_IS_DGRAM_SOCK(s) \ + (s->SharedData.ServiceFlags1 & XP1_CONNECTIONLESS) + +/* Global data that we want to share access with */ +extern HANDLE SockSanCleanUpCompleteEvent; +extern BOOLEAN SockSanEnabled; +extern WSAPROTOCOL_INFOW SockTcpProviderInfo; + +typedef VOID +(WSPAPI *PASYNC_COMPLETION_ROUTINE)( + PVOID Context, + PIO_STATUS_BLOCK IoStatusBlock +); + +/* Internal Helper Functions */ +INT +WSPAPI +SockLoadHelperDll( + PWSTR TransportName, + PWINSOCK_MAPPING Mapping, + PHELPER_DATA *HelperDllData +); + +INT +WSPAPI +SockLoadTransportMapping( + PWSTR TransportName, + PWINSOCK_MAPPING *Mapping +); + +INT +WSPAPI +SockLoadTransportList( + PWSTR *TransportList +); + +BOOL +WSPAPI +SockIsTripleInMapping(IN PWINSOCK_MAPPING Mapping, + IN INT AddressFamily, + OUT PBOOLEAN AfMatch, + IN INT SocketType, + OUT PBOOLEAN SockMatch, + IN INT Protocol, + OUT PBOOLEAN ProtoMatch); + +INT +WSPAPI +SockAsyncSelectHelper(IN PSOCKET_INFORMATION Socket, + IN HWND hWnd, + IN UINT wMsg, + IN LONG Events); + +INT +WSPAPI +SockEventSelectHelper(IN PSOCKET_INFORMATION Socket, + IN WSAEVENT EventObject, + IN LONG Events); + +BOOLEAN +WSPAPI +SockCheckAndReferenceAsyncThread(VOID); + +BOOLEAN +WSPAPI +SockCheckAndInitAsyncSelectHelper(VOID); + +INT +WSPAPI +SockGetTdiName(PINT AddressFamily, + PINT SocketType, + PINT Protocol, + LPGUID ProviderId, + GROUP Group, + DWORD Flags, + PUNICODE_STRING TransportName, + PVOID *HelperDllContext, + PHELPER_DATA *HelperDllData, + PDWORD Events); + +INT +WSPAPI +SockAsyncThread( + PVOID ThreadParam +); + +VOID +WSPAPI +SockProcessAsyncSelect(PSOCKET_INFORMATION Socket, + PASYNC_DATA AsyncData); + +VOID +WSPAPI +SockHandleAsyncIndication(IN PASYNC_COMPLETION_ROUTINE Callback, + IN PVOID Context, + IN PIO_STATUS_BLOCK IoStatusBlock); + +INT +WSPAPI +SockReenableAsyncSelectEvent(IN PSOCKET_INFORMATION Socket, + IN ULONG Event); + +VOID +WSPAPI +SockProcessQueuedAsyncSelect(PVOID Context, + PIO_STATUS_BLOCK IoStatusBlock); + +VOID +WSPAPI +SockAsyncSelectCompletion( + PVOID Context, + PIO_STATUS_BLOCK IoStatusBlock +); + +/* Public functions, but not exported! */ +SOCKET +WSPAPI +WSPAccept( + IN SOCKET s, + OUT LPSOCKADDR addr, + IN OUT LPINT addrlen, + IN LPCONDITIONPROC lpfnCondition, + IN DWORD dwCallbackData, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPAddressToString( + IN LPSOCKADDR lpsaAddress, + IN DWORD dwAddressLength, + IN LPWSAPROTOCOL_INFOW lpProtocolInfo, + OUT LPWSTR lpszAddressString, + IN OUT LPDWORD lpdwAddressStringLength, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPAsyncSelect( + IN SOCKET s, + IN HWND hWnd, + IN UINT wMsg, + IN LONG lEvent, + OUT LPINT lpErrno); + +INT +WSPAPI WSPBind( + IN SOCKET s, + IN CONST SOCKADDR *name, + IN INT namelen, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPCancelBlockingCall( + OUT LPINT lpErrno); + +INT +WSPAPI +WSPCleanup( + OUT LPINT lpErrno); + +INT +WSPAPI +WSPCloseSocket( + IN SOCKET s, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPConnect( + IN SOCKET s, + IN CONST SOCKADDR *name, + IN INT namelen, + IN LPWSABUF lpCallerData, + OUT LPWSABUF lpCalleeData, + IN LPQOS lpSQOS, + IN LPQOS lpGQOS, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPDuplicateSocket( + IN SOCKET s, + IN DWORD dwProcessId, + OUT LPWSAPROTOCOL_INFOW lpProtocolInfo, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPEnumNetworkEvents( + IN SOCKET s, + IN WSAEVENT hEventObject, + OUT LPWSANETWORKEVENTS lpNetworkEvents, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPEventSelect( + IN SOCKET s, + IN WSAEVENT hEventObject, + IN LONG lNetworkEvents, + OUT LPINT lpErrno); + +BOOL +WSPAPI +WSPGetOverlappedResult( + IN SOCKET s, + IN LPWSAOVERLAPPED lpOverlapped, + OUT LPDWORD lpcbTransfer, + IN BOOL fWait, + OUT LPDWORD lpdwFlags, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPGetPeerName( + IN SOCKET s, + OUT LPSOCKADDR name, + IN OUT LPINT namelen, + OUT LPINT lpErrno); + +BOOL +WSPAPI +WSPGetQOSByName( + IN SOCKET s, + IN OUT LPWSABUF lpQOSName, + OUT LPQOS lpQOS, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPGetSockName( + IN SOCKET s, + OUT LPSOCKADDR name, + IN OUT LPINT namelen, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPGetSockOpt( + IN SOCKET s, + IN INT level, + IN INT optname, + OUT CHAR FAR* optval, + IN OUT LPINT optlen, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPIoctl( + IN SOCKET s, + IN DWORD dwIoControlCode, + IN LPVOID lpvInBuffer, + IN DWORD cbInBuffer, + OUT LPVOID lpvOutBuffer, + IN DWORD cbOutBuffer, + OUT LPDWORD lpcbBytesReturned, + IN LPWSAOVERLAPPED lpOverlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + IN LPWSATHREADID lpThreadId, + OUT LPINT lpErrno); + +SOCKET +WSPAPI +WSPJoinLeaf( + IN SOCKET s, + IN CONST SOCKADDR *name, + IN INT namelen, + IN LPWSABUF lpCallerData, + OUT LPWSABUF lpCalleeData, + IN LPQOS lpSQOS, + IN LPQOS lpGQOS, + IN DWORD dwFlags, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPListen( + IN SOCKET s, + IN INT backlog, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPRecv( + IN SOCKET s, + IN OUT LPWSABUF lpBuffers, + IN DWORD dwBufferCount, + OUT LPDWORD lpNumberOfBytesRecvd, + IN OUT LPDWORD lpFlags, + IN LPWSAOVERLAPPED lpOverlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + IN LPWSATHREADID lpThreadId, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPRecvDisconnect( + IN SOCKET s, + OUT LPWSABUF lpInboundDisconnectData, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPRecvFrom( + IN SOCKET s, + IN OUT LPWSABUF lpBuffers, + IN DWORD dwBufferCount, + OUT LPDWORD lpNumberOfBytesRecvd, + IN OUT LPDWORD lpFlags, + OUT LPSOCKADDR lpFrom, + IN OUT LPINT lpFromlen, + IN LPWSAOVERLAPPED lpOverlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + IN LPWSATHREADID lpThreadId, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPSelect( + IN INT nfds, + IN OUT LPFD_SET readfds, + IN OUT LPFD_SET writefds, + IN OUT LPFD_SET exceptfds, + IN CONST LPTIMEVAL timeout, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPSend( + IN SOCKET s, + IN LPWSABUF lpBuffers, + IN DWORD dwBufferCount, + OUT LPDWORD lpNumberOfBytesSent, + IN DWORD dwFlags, + IN LPWSAOVERLAPPED lpOverlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + IN LPWSATHREADID lpThreadId, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPSendDisconnect( + IN SOCKET s, + IN LPWSABUF lpOutboundDisconnectData, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPSendTo( + IN SOCKET s, + IN LPWSABUF lpBuffers, + IN DWORD dwBufferCount, + OUT LPDWORD lpNumberOfBytesSent, + IN DWORD dwFlags, + IN CONST SOCKADDR *lpTo, + IN INT iTolen, + IN LPWSAOVERLAPPED lpOverlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + IN LPWSATHREADID lpThreadId, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPSetSockOpt( + IN SOCKET s, + IN INT level, + IN INT optname, + IN CONST CHAR FAR* optval, + IN INT optlen, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPShutdown( + IN SOCKET s, + IN INT how, + OUT LPINT lpErrno); + +SOCKET +WSPAPI +WSPSocket( + IN INT af, + IN INT type, + IN INT protocol, + IN LPWSAPROTOCOL_INFOW lpProtocolInfo, + IN GROUP g, + IN DWORD dwFlags, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPStringToAddress( + IN LPWSTR AddressString, + IN INT AddressFamily, + IN LPWSAPROTOCOL_INFOW lpProtocolInfo, + OUT LPSOCKADDR lpAddress, + IN OUT LPINT lpAddressLength, + OUT LPINT lpErrno); +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS WinSock 2 NSP + * FILE: lib/mswsock/sock.h + * PURPOSE: Winsock 2 SPI Utility Header + */ + +#define NO_BLOCKING_HOOK 0 +#define MAYBE_BLOCKING_HOOK 1 +#define ALWAYS_BLOCKING_HOOK 2 + +#define NO_TIMEOUT 0 +#define SEND_TIMEOUT 1 +#define RECV_TIMEOUT 2 + +#define MAX_TDI_ADDRESS_LENGTH 32 + +#define WSA_FLAG_MULTIPOINT_ALL (WSA_FLAG_MULTIPOINT_C_ROOT |\ + WSA_FLAG_MULTIPOINT_C_LEAF |\ + WSA_FLAG_MULTIPOINT_D_ROOT |\ + WSA_FLAG_MULTIPOINT_D_LEAF) + + +/* Socket State */ +typedef enum _SOCKET_STATE +{ + SocketUndefined = -1, + SocketOpen, + SocketBound, + SocketBoundUdp, + SocketConnected, + SocketClosed +} SOCKET_STATE, *PSOCKET_STATE; + +/* + * Shared Socket Information. + * It's called shared because we send it to Kernel-Mode for safekeeping + */ +typedef struct _SOCK_SHARED_INFO { + SOCKET_STATE State; + INT AddressFamily; + INT SocketType; + INT Protocol; + INT SizeOfLocalAddress; + INT SizeOfRemoteAddress; + struct linger LingerData; + ULONG SendTimeout; + ULONG RecvTimeout; + ULONG SizeOfRecvBuffer; + ULONG SizeOfSendBuffer; + struct { + BOOLEAN Listening:1; + BOOLEAN Broadcast:1; + BOOLEAN Debug:1; + BOOLEAN OobInline:1; + BOOLEAN ReuseAddresses:1; + BOOLEAN ExclusiveAddressUse:1; + BOOLEAN NonBlocking:1; + BOOLEAN DontUseWildcard:1; + BOOLEAN ReceiveShutdown:1; + BOOLEAN SendShutdown:1; + BOOLEAN UseDelayedAcceptance:1; + BOOLEAN UseSAN:1; + }; // Flags + DWORD CreateFlags; + DWORD CatalogEntryId; + DWORD ServiceFlags1; + DWORD ProviderFlags; + GROUP GroupID; + DWORD GroupType; + INT GroupPriority; + INT SocketLastError; + HWND hWnd; + LONG Unknown; + DWORD SequenceNumber; + UINT wMsg; + LONG AsyncEvents; + LONG AsyncDisabledEvents; +} SOCK_SHARED_INFO, *PSOCK_SHARED_INFO; + +/* Socket Helper Data. Holds information about the WSH Libraries */ +typedef struct _HELPER_DATA { + LIST_ENTRY Helpers; + LONG RefCount; + HANDLE hInstance; + INT MinWSAddressLength; + INT MaxWSAddressLength; + INT MinTDIAddressLength; + INT MaxTDIAddressLength; + BOOLEAN UseDelayedAcceptance; + PWINSOCK_MAPPING Mapping; + PWSH_OPEN_SOCKET WSHOpenSocket; + PWSH_OPEN_SOCKET2 WSHOpenSocket2; + PWSH_JOIN_LEAF WSHJoinLeaf; + PWSH_NOTIFY WSHNotify; + PWSH_GET_SOCKET_INFORMATION WSHGetSocketInformation; + PWSH_SET_SOCKET_INFORMATION WSHSetSocketInformation; + PWSH_GET_SOCKADDR_TYPE WSHGetSockaddrType; + PWSH_GET_WILDCARD_SOCKADDR WSHGetWildcardSockaddr; + PWSH_GET_BROADCAST_SOCKADDR WSHGetBroadcastSockaddr; + PWSH_ADDRESS_TO_STRING WSHAddressToString; + PWSH_STRING_TO_ADDRESS WSHStringToAddress; + PWSH_IOCTL WSHIoctl; + WCHAR TransportName[1]; +} HELPER_DATA, *PHELPER_DATA; + +typedef struct _ASYNC_DATA +{ + struct _SOCKET_INFORMATION *ParentSocket; + DWORD SequenceNumber; + IO_STATUS_BLOCK IoStatusBlock; + AFD_POLL_INFO AsyncSelectInfo; +} ASYNC_DATA, *PASYNC_DATA; + +/* The actual Socket Structure represented by a handle. Internal to us */ +typedef struct _SOCKET_INFORMATION { + union { + WSH_HANDLE WshContext; + struct { + LONG RefCount; + SOCKET Handle; + }; + }; + SOCK_SHARED_INFO SharedData; + GUID ProviderId; + DWORD HelperEvents; + PHELPER_DATA HelperData; + PVOID HelperContext; + PSOCKADDR LocalAddress; + PSOCKADDR RemoteAddress; + HANDLE TdiAddressHandle; + HANDLE TdiConnectionHandle; + PASYNC_DATA AsyncData; + HANDLE EventObject; + LONG NetworkEvents; + CRITICAL_SECTION Lock; + BOOL DontUseSan; + PVOID SanData; +} SOCKET_INFORMATION, *PSOCKET_INFORMATION; + +/* The blob of data we send to Kernel-Mode for safekeeping */ +typedef struct _SOCKET_CONTEXT { + SOCK_SHARED_INFO SharedData; + ULONG SizeOfHelperData; + ULONG Padding; + SOCKADDR LocalAddress; + SOCKADDR RemoteAddress; + /* Plus Helper Data */ +} SOCKET_CONTEXT, *PSOCKET_CONTEXT; + +typedef struct _SOCK_RW_LOCK +{ + volatile LONG ReaderCount; + HANDLE WriterWaitEvent; + RTL_CRITICAL_SECTION Lock; +} SOCK_RW_LOCK, *PSOCK_RW_LOCK; + +typedef struct _WINSOCK_TEB_DATA +{ + HANDLE EventHandle; + SOCKET SocketHandle; + PAFD_ACCEPT_DATA AcceptData; + LONG PendingAPCs; + BOOLEAN CancelIo; + ULONG Unknown; + PVOID RnrThreadData; +} WINSOCK_TEB_DATA, *PWINSOCK_TEB_DATA; + +typedef INT +(WINAPI *PICF_CONNECT)(PVOID IcfData); + +typedef struct _SOCK_ICF_DATA +{ + HANDLE IcfHandle; + PVOID IcfOpenDynamicFwPort; + PICF_CONNECT IcfConnect; + PVOID IcfDisconnect; + HINSTANCE DllHandle; +} SOCK_ICF_DATA, *PSOCK_ICF_DATA; + +typedef PVOID +(NTAPI *PRTL_HEAP_ALLOCATE)( + IN HANDLE Heap, + IN ULONG Flags, + IN ULONG Size +); + +extern HANDLE SockPrivateHeap; +extern PRTL_HEAP_ALLOCATE SockAllocateHeapRoutine; +extern SOCK_RW_LOCK SocketGlobalLock; +extern PWAH_HANDLE_TABLE SockContextTable; +extern LPWSPUPCALLTABLE SockUpcallTable; +extern BOOL SockProcessTerminating; +extern LONG SockWspStartupCount; +extern DWORD SockSendBufferWindow; +extern DWORD SockReceiveBufferWindow; +extern HANDLE SockAsyncQueuePort; +extern BOOLEAN SockAsyncSelectCalled; +extern LONG SockProcessPendingAPCCount; +extern HINSTANCE SockModuleHandle; +extern LONG gWSM_NSPStartupRef; +extern LONG gWSM_NSPCallRef; +extern LIST_ENTRY SockHelperDllListHead; +extern CRITICAL_SECTION MSWSOCK_SocketLock; +extern HINSTANCE NlsMsgSourcemModuleHandle; +extern PVOID SockBufferKeyTable; +extern ULONG SockBufferKeyTableSize; +extern LONG SockAsyncThreadReferenceCount; +extern BOOLEAN g_fRnrLockInit; +extern CRITICAL_SECTION g_RnrLock; + +BOOL +WSPAPI +MSWSOCK_Initialize(VOID); + +BOOL +WSPAPI +MSAFD_SockThreadInitialize(VOID); + +INT +WSPAPI +SockCreateAsyncQueuePort(VOID); + +PVOID +WSPAPI +SockInitializeHeap(IN HANDLE Heap, + IN ULONG Flags, + IN ULONG Size); + +NTSTATUS +WSPAPI +SockInitializeRwLockAndSpinCount( + IN PSOCK_RW_LOCK Lock, + IN ULONG SpinCount +); + +VOID +WSPAPI +SockAcquireRwLockExclusive(IN PSOCK_RW_LOCK Lock); + +VOID +WSPAPI +SockAcquireRwLockShared(IN PSOCK_RW_LOCK Lock); + +VOID +WSPAPI +SockReleaseRwLockExclusive(IN PSOCK_RW_LOCK Lock); + +VOID +WSPAPI +SockReleaseRwLockShared(IN PSOCK_RW_LOCK Lock); + +NTSTATUS +WSPAPI +SockDeleteRwLock(IN PSOCK_RW_LOCK Lock); + +INT +WSPAPI +SockGetConnectData(IN PSOCKET_INFORMATION Socket, + IN ULONG Ioctl, + IN PVOID Buffer, + IN ULONG BufferLength, + OUT PULONG BufferReturned); + +INT +WSPAPI +SockIsAddressConsistentWithConstrainedGroup(IN PSOCKET_INFORMATION Socket, + IN GROUP Group, + IN PSOCKADDR SocketAddress, + IN INT SocketAddressLength); + +BOOL +WSPAPI +SockWaitForSingleObject(IN HANDLE Handle, + IN SOCKET SocketHandle, + IN DWORD BlockingFlags, + IN DWORD TimeoutFlags); + +BOOLEAN +WSPAPI +SockIsSocketConnected(IN PSOCKET_INFORMATION Socket); + +INT +WSPAPI +SockNotifyHelperDll(IN PSOCKET_INFORMATION Socket, + IN DWORD Event); + +INT +WSPAPI +SockUpdateWindowSizes(IN PSOCKET_INFORMATION Socket, + IN BOOLEAN Force); + +INT +WSPAPI +SockBuildTdiAddress(OUT PTRANSPORT_ADDRESS TdiAddress, + IN PSOCKADDR Sockaddr, + IN INT SockaddrLength); + +INT +WSPAPI +SockBuildSockaddr(OUT PSOCKADDR Sockaddr, + OUT PINT SockaddrLength, + IN PTRANSPORT_ADDRESS TdiAddress); + +INT +WSPAPI +SockGetTdiHandles(IN PSOCKET_INFORMATION Socket); + +VOID +WSPAPI +SockIoCompletion(IN PVOID ApcContext, + IN PIO_STATUS_BLOCK IoStatusBlock, + DWORD Reserved); + +VOID +WSPAPI +SockCancelIo(IN SOCKET Handle); + +INT +WSPAPI +SockGetInformation(IN PSOCKET_INFORMATION Socket, + IN ULONG AfdInformationClass, + IN PVOID ExtraData OPTIONAL, + IN ULONG ExtraDataSize, + IN OUT PBOOLEAN Boolean OPTIONAL, + IN OUT PULONG Ulong OPTIONAL, + IN OUT PLARGE_INTEGER LargeInteger OPTIONAL); + +INT +WSPAPI +SockSetInformation(IN PSOCKET_INFORMATION Socket, + IN ULONG AfdInformationClass, + IN PBOOLEAN Boolean OPTIONAL, + IN PULONG Ulong OPTIONAL, + IN PLARGE_INTEGER LargeInteger OPTIONAL); + +INT +WSPAPI +SockSetHandleContext(IN PSOCKET_INFORMATION Socket); + +VOID +WSPAPI +SockDereferenceSocket(IN PSOCKET_INFORMATION Socket); + +VOID +WSPAPI +SockFreeHelperDll(IN PHELPER_DATA Helper); + +PSOCKET_INFORMATION +WSPAPI +SockFindAndReferenceSocket(IN SOCKET Handle, + IN BOOLEAN Import); + +INT +WSPAPI +SockEnterApiSlow(OUT PWINSOCK_TEB_DATA *ThreadData); + +VOID +WSPAPI +SockSanInitialize(VOID); + +VOID +WSPAPI +SockSanGetTcpipCatalogId(VOID); + +VOID +WSPAPI +CloseIcfConnection(IN PSOCK_ICF_DATA IcfData); + +VOID +WSPAPI +InitializeIcfConnection(IN PSOCK_ICF_DATA IcfData); + +VOID +WSPAPI +NewIcfConnection(IN PSOCK_ICF_DATA IcfData); + +INT +WSPAPI +NtStatusToSocketError(IN NTSTATUS Status); + +INT +WSPAPI +SockSocket(INT AddressFamily, + INT SocketType, + INT Protocol, + LPGUID ProviderId, + GROUP g, + DWORD dwFlags, + DWORD ProviderFlags, + DWORD ServiceFlags, + DWORD CatalogEntryId, + PSOCKET_INFORMATION *NewSocket); + +INT +WSPAPI +SockCloseSocket(IN PSOCKET_INFORMATION Socket); + +FORCEINLINE +INT +WSPAPI +SockEnterApiFast(OUT PWINSOCK_TEB_DATA *ThreadData) +{ + /* Make sure we aren't terminating and get our thread data */ + if (!(SockProcessTerminating) && + (SockWspStartupCount > 0) && + ((*ThreadData == NtCurrentTeb()->WinSockData))) + { + /* Everything is good, return */ + return NO_ERROR; + } + + /* Something didn't work out, use the slow path */ + return SockEnterApiSlow(ThreadData); +} + +FORCEINLINE +VOID +WSPAPI +SockDereferenceHelperDll(IN PHELPER_DATA Helper) +{ + /* Dereference and see if it's the last count */ + if (!InterlockedDecrement(&Helper->RefCount)) + { + /* Destroy the Helper DLL */ + SockFreeHelperDll(Helper); + } +} + +#define MSAFD_IS_DGRAM_SOCK(s) \ + (s->SharedData.ServiceFlags1 & XP1_CONNECTIONLESS) + +/* Global data that we want to share access with */ +extern HANDLE SockSanCleanUpCompleteEvent; +extern BOOLEAN SockSanEnabled; +extern WSAPROTOCOL_INFOW SockTcpProviderInfo; + +typedef VOID +(WSPAPI *PASYNC_COMPLETION_ROUTINE)( + PVOID Context, + PIO_STATUS_BLOCK IoStatusBlock +); + +/* Internal Helper Functions */ +INT +WSPAPI +SockLoadHelperDll( + PWSTR TransportName, + PWINSOCK_MAPPING Mapping, + PHELPER_DATA *HelperDllData +); + +INT +WSPAPI +SockLoadTransportMapping( + PWSTR TransportName, + PWINSOCK_MAPPING *Mapping +); + +INT +WSPAPI +SockLoadTransportList( + PWSTR *TransportList +); + +BOOL +WSPAPI +SockIsTripleInMapping(IN PWINSOCK_MAPPING Mapping, + IN INT AddressFamily, + OUT PBOOLEAN AfMatch, + IN INT SocketType, + OUT PBOOLEAN SockMatch, + IN INT Protocol, + OUT PBOOLEAN ProtoMatch); + +INT +WSPAPI +SockAsyncSelectHelper(IN PSOCKET_INFORMATION Socket, + IN HWND hWnd, + IN UINT wMsg, + IN LONG Events); + +INT +WSPAPI +SockEventSelectHelper(IN PSOCKET_INFORMATION Socket, + IN WSAEVENT EventObject, + IN LONG Events); + +BOOLEAN +WSPAPI +SockCheckAndReferenceAsyncThread(VOID); + +BOOLEAN +WSPAPI +SockCheckAndInitAsyncSelectHelper(VOID); + +INT +WSPAPI +SockGetTdiName(PINT AddressFamily, + PINT SocketType, + PINT Protocol, + LPGUID ProviderId, + GROUP Group, + DWORD Flags, + PUNICODE_STRING TransportName, + PVOID *HelperDllContext, + PHELPER_DATA *HelperDllData, + PDWORD Events); + +INT +WSPAPI +SockAsyncThread( + PVOID ThreadParam +); + +VOID +WSPAPI +SockProcessAsyncSelect(PSOCKET_INFORMATION Socket, + PASYNC_DATA AsyncData); + +VOID +WSPAPI +SockHandleAsyncIndication(IN PASYNC_COMPLETION_ROUTINE Callback, + IN PVOID Context, + IN PIO_STATUS_BLOCK IoStatusBlock); + +INT +WSPAPI +SockReenableAsyncSelectEvent(IN PSOCKET_INFORMATION Socket, + IN ULONG Event); + +VOID +WSPAPI +SockProcessQueuedAsyncSelect(PVOID Context, + PIO_STATUS_BLOCK IoStatusBlock); + +VOID +WSPAPI +SockAsyncSelectCompletion( + PVOID Context, + PIO_STATUS_BLOCK IoStatusBlock +); + +/* Public functions, but not exported! */ +SOCKET +WSPAPI +WSPAccept( + IN SOCKET s, + OUT LPSOCKADDR addr, + IN OUT LPINT addrlen, + IN LPCONDITIONPROC lpfnCondition, + IN DWORD dwCallbackData, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPAddressToString( + IN LPSOCKADDR lpsaAddress, + IN DWORD dwAddressLength, + IN LPWSAPROTOCOL_INFOW lpProtocolInfo, + OUT LPWSTR lpszAddressString, + IN OUT LPDWORD lpdwAddressStringLength, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPAsyncSelect( + IN SOCKET s, + IN HWND hWnd, + IN UINT wMsg, + IN LONG lEvent, + OUT LPINT lpErrno); + +INT +WSPAPI WSPBind( + IN SOCKET s, + IN CONST SOCKADDR *name, + IN INT namelen, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPCancelBlockingCall( + OUT LPINT lpErrno); + +INT +WSPAPI +WSPCleanup( + OUT LPINT lpErrno); + +INT +WSPAPI +WSPCloseSocket( + IN SOCKET s, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPConnect( + IN SOCKET s, + IN CONST SOCKADDR *name, + IN INT namelen, + IN LPWSABUF lpCallerData, + OUT LPWSABUF lpCalleeData, + IN LPQOS lpSQOS, + IN LPQOS lpGQOS, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPDuplicateSocket( + IN SOCKET s, + IN DWORD dwProcessId, + OUT LPWSAPROTOCOL_INFOW lpProtocolInfo, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPEnumNetworkEvents( + IN SOCKET s, + IN WSAEVENT hEventObject, + OUT LPWSANETWORKEVENTS lpNetworkEvents, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPEventSelect( + IN SOCKET s, + IN WSAEVENT hEventObject, + IN LONG lNetworkEvents, + OUT LPINT lpErrno); + +BOOL +WSPAPI +WSPGetOverlappedResult( + IN SOCKET s, + IN LPWSAOVERLAPPED lpOverlapped, + OUT LPDWORD lpcbTransfer, + IN BOOL fWait, + OUT LPDWORD lpdwFlags, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPGetPeerName( + IN SOCKET s, + OUT LPSOCKADDR name, + IN OUT LPINT namelen, + OUT LPINT lpErrno); + +BOOL +WSPAPI +WSPGetQOSByName( + IN SOCKET s, + IN OUT LPWSABUF lpQOSName, + OUT LPQOS lpQOS, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPGetSockName( + IN SOCKET s, + OUT LPSOCKADDR name, + IN OUT LPINT namelen, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPGetSockOpt( + IN SOCKET s, + IN INT level, + IN INT optname, + OUT CHAR FAR* optval, + IN OUT LPINT optlen, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPIoctl( + IN SOCKET s, + IN DWORD dwIoControlCode, + IN LPVOID lpvInBuffer, + IN DWORD cbInBuffer, + OUT LPVOID lpvOutBuffer, + IN DWORD cbOutBuffer, + OUT LPDWORD lpcbBytesReturned, + IN LPWSAOVERLAPPED lpOverlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + IN LPWSATHREADID lpThreadId, + OUT LPINT lpErrno); + +SOCKET +WSPAPI +WSPJoinLeaf( + IN SOCKET s, + IN CONST SOCKADDR *name, + IN INT namelen, + IN LPWSABUF lpCallerData, + OUT LPWSABUF lpCalleeData, + IN LPQOS lpSQOS, + IN LPQOS lpGQOS, + IN DWORD dwFlags, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPListen( + IN SOCKET s, + IN INT backlog, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPRecv( + IN SOCKET s, + IN OUT LPWSABUF lpBuffers, + IN DWORD dwBufferCount, + OUT LPDWORD lpNumberOfBytesRecvd, + IN OUT LPDWORD lpFlags, + IN LPWSAOVERLAPPED lpOverlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + IN LPWSATHREADID lpThreadId, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPRecvDisconnect( + IN SOCKET s, + OUT LPWSABUF lpInboundDisconnectData, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPRecvFrom( + IN SOCKET s, + IN OUT LPWSABUF lpBuffers, + IN DWORD dwBufferCount, + OUT LPDWORD lpNumberOfBytesRecvd, + IN OUT LPDWORD lpFlags, + OUT LPSOCKADDR lpFrom, + IN OUT LPINT lpFromlen, + IN LPWSAOVERLAPPED lpOverlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + IN LPWSATHREADID lpThreadId, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPSelect( + IN INT nfds, + IN OUT LPFD_SET readfds, + IN OUT LPFD_SET writefds, + IN OUT LPFD_SET exceptfds, + IN CONST LPTIMEVAL timeout, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPSend( + IN SOCKET s, + IN LPWSABUF lpBuffers, + IN DWORD dwBufferCount, + OUT LPDWORD lpNumberOfBytesSent, + IN DWORD dwFlags, + IN LPWSAOVERLAPPED lpOverlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + IN LPWSATHREADID lpThreadId, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPSendDisconnect( + IN SOCKET s, + IN LPWSABUF lpOutboundDisconnectData, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPSendTo( + IN SOCKET s, + IN LPWSABUF lpBuffers, + IN DWORD dwBufferCount, + OUT LPDWORD lpNumberOfBytesSent, + IN DWORD dwFlags, + IN CONST SOCKADDR *lpTo, + IN INT iTolen, + IN LPWSAOVERLAPPED lpOverlapped, + IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, + IN LPWSATHREADID lpThreadId, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPSetSockOpt( + IN SOCKET s, + IN INT level, + IN INT optname, + IN CONST CHAR FAR* optval, + IN INT optlen, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPShutdown( + IN SOCKET s, + IN INT how, + OUT LPINT lpErrno); + +SOCKET +WSPAPI +WSPSocket( + IN INT af, + IN INT type, + IN INT protocol, + IN LPWSAPROTOCOL_INFOW lpProtocolInfo, + IN GROUP g, + IN DWORD dwFlags, + OUT LPINT lpErrno); + +INT +WSPAPI +WSPStringToAddress( + IN LPWSTR AddressString, + IN INT AddressFamily, + IN LPWSAPROTOCOL_INFOW lpProtocolInfo, + OUT LPSOCKADDR lpAddress, + IN OUT LPINT lpAddressLength, + OUT LPINT lpErrno); diff --git a/include/reactos/winsock/mswinsock.h b/include/reactos/winsock/mswinsock.h new file mode 100644 index 00000000000..403b5ea3550 --- /dev/null +++ b/include/reactos/winsock/mswinsock.h @@ -0,0 +1,38 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Ancillary Function Driver DLL + * FILE: include/mswsock.h + * PURPOSE: Ancillary Function Driver DLL header + */ +#ifndef __MSWINSOCK_H +#define __MSWINSOCK_H + +typedef DWORD (* LPFN_NSPAPI)(VOID); +typedef struct _NS_ROUTINE { + DWORD dwFunctionCount; + LPFN_NSPAPI *alpfnFunctions; + DWORD dwNameSpace; + DWORD dwPriority; +} NS_ROUTINE, *PNS_ROUTINE, * FAR LPNS_ROUTINE; + +#endif + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Ancillary Function Driver DLL + * FILE: include/mswsock.h + * PURPOSE: Ancillary Function Driver DLL header + */ +#ifndef __MSWINSOCK_H +#define __MSWINSOCK_H + +typedef DWORD (* LPFN_NSPAPI)(VOID); +typedef struct _NS_ROUTINE { + DWORD dwFunctionCount; + LPFN_NSPAPI *alpfnFunctions; + DWORD dwNameSpace; + DWORD dwPriority; +} NS_ROUTINE, *PNS_ROUTINE, * FAR LPNS_ROUTINE; + +#endif + diff --git a/include/reactos/winsock/rnr20lib.h b/include/reactos/winsock/rnr20lib.h new file mode 100644 index 00000000000..d44793345fa --- /dev/null +++ b/include/reactos/winsock/rnr20lib.h @@ -0,0 +1,530 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS WinSock 2 NSP + * FILE: include/nsp_dns.h + * PURPOSE: WinSock 2 NSP Header + */ + +#ifndef __NSP_H +#define __NSP_H + +/* DEFINES *******************************************************************/ + +/* Lookup Flags */ +#define DONE 0x01 +#define REVERSE 0x02 +#define LOCAL 0x04 +#define IANA 0x10 +#define LOOPBACK 0x20 + +/* Protocol Flags */ +#define UDP 0x01 +#define TCP 0x02 +#define ATM 0x04 + +/* GUID Masks */ +#define NBT_MASK 0x01 +#define DNS_MASK 0x02 + +/* TYPES *********************************************************************/ + +typedef struct _RNR_CONTEXT +{ + LIST_ENTRY ListEntry; + HANDLE Handle; + PDNS_BLOB CachedSaBlob; + DWORD Signature; + DWORD RefCount; + DWORD Instance; + DWORD LookupFlags; + DWORD RnrId; + DWORD dwNameSpace; + DWORD RrType; + DWORD dwControlFlags; + DWORD UdpPort; + DWORD TcpPort; + DWORD ProtocolFlags; + BLOB CachedBlob; + GUID lpServiceClassId; + GUID lpProviderId; + WCHAR ServiceName[1]; +} RNR_CONTEXT, *PRNR_CONTEXT; + +typedef struct _RNR_TEB_DATA +{ + ULONG Foo; +} RNR_TEB_DATA, *PRNR_TEB_DATA; + +/* PROTOTYPES ****************************************************************/ + +/* + * proc.c + */ +BOOLEAN +WINAPI +RNRPROV_SockEnterApi(VOID); + +/* + * oldutil.c + */ +DWORD +WINAPI +GetServerAndProtocolsFromString( + PWCHAR ServiceString, + LPGUID ServiceType, + PSERVENT *ReverseServent +); + +DWORD +WINAPI +FetchPortFromClassInfo( + IN DWORD Type, + IN LPGUID Guid, + IN LPWSASERVICECLASSINFOW ServiceClassInfo +); + +PSERVENT +WSPAPI +CopyServEntry( + IN PSERVENT Servent, + IN OUT PULONG_PTR BufferPos, + IN OUT PULONG BufferFreeSize, + IN OUT PULONG BlobSize, + IN BOOLEAN Relative +); + +WORD +WINAPI +GetDnsQueryTypeFromGuid( + IN LPGUID Guid +); + +/* + * context.c + */ +VOID +WSPAPI +RnrCtx_ListCleanup(VOID); + +VOID +WSPAPI +RnrCtx_Release(PRNR_CONTEXT RnrContext); + +PRNR_CONTEXT +WSPAPI +RnrCtx_Get( + HANDLE LookupHandle, + DWORD dwControlFlags, + PLONG Instance +); + +PRNR_CONTEXT +WSPAPI +RnrCtx_Create( + IN HANDLE LookupHandle, + IN LPWSTR ServiceName +); + +VOID +WSPAPI +RnrCtx_DecInstance(IN PRNR_CONTEXT RnrContext); + +/* + * util.c + */ +PVOID +WSPAPI +Temp_AllocZero(IN DWORD Size); + +/* + * lookup.c + */ +PDNS_BLOB +WSPAPI +Rnr_DoHostnameLookup(IN PRNR_CONTEXT Context); + +PDNS_BLOB +WSPAPI +Rnr_GetHostByAddr(IN PRNR_CONTEXT Context); + +PDNS_BLOB +WSPAPI +Rnr_DoDnsLookup(IN PRNR_CONTEXT Context); + +BOOLEAN +WINAPI +Rnr_CheckIfUseNbt(PRNR_CONTEXT RnrContext); + +PDNS_BLOB +WINAPI +Rnr_NbtResolveAddr(IN IN_ADDR Address); + +PDNS_BLOB +WINAPI +Rnr_NbtResolveName(IN LPWSTR Name); + +/* + * init.c + */ +VOID +WSPAPI +Rnr_ProcessInit(VOID); + +VOID +WSPAPI +Rnr_ProcessCleanup(VOID); + +BOOLEAN +WSPAPI +Rnr_ThreadInit(VOID); + +VOID +WSPAPI +Rnr_ThreadCleanup(VOID); + +/* + * nsp.c + */ +VOID +WSPAPI +Nsp_GlobalCleanup(VOID); + +INT +WINAPI +Dns_NSPCleanup(IN LPGUID lpProviderId); + +INT +WINAPI +Dns_NSPSetService( + IN LPGUID lpProviderId, + IN LPWSASERVICECLASSINFOW lpServiceClassInfo, + IN LPWSAQUERYSETW lpqsRegInfo, + IN WSAESETSERVICEOP essOperation, + IN DWORD dwControlFlags +); + +INT +WINAPI +Dns_NSPInstallServiceClass( + IN LPGUID lpProviderId, + IN LPWSASERVICECLASSINFOW lpServiceClassInfo +); + +INT +WINAPI +Dns_NSPRemoveServiceClass( + IN LPGUID lpProviderId, + IN LPGUID lpServiceCallId +); + +INT +WINAPI +Dns_NSPGetServiceClassInfo( + IN LPGUID lpProviderId, + IN OUT LPDWORD lpdwBufSize, + IN OUT LPWSASERVICECLASSINFOW lpServiceClassInfo +); + +INT +WINAPI +Dns_NSPLookupServiceBegin( + LPGUID lpProviderId, + LPWSAQUERYSETW lpqsRestrictions, + LPWSASERVICECLASSINFOW lpServiceClassInfo, + DWORD dwControlFlags, + LPHANDLE lphLookup +); + +INT +WINAPI +Dns_NSPLookupServiceNext( + IN HANDLE hLookup, + IN DWORD dwControlFlags, + IN OUT LPDWORD lpdwBufferLength, + OUT LPWSAQUERYSETW lpqsResults +); + +INT +WINAPI +Dns_NSPLookupServiceEnd(IN HANDLE hLookup); + +INT +WINAPI +Dns_NSPStartup( + IN LPGUID lpProviderId, + IN OUT LPNSP_ROUTINE lpsnpRoutines +); + +/* Unchecked yet */ +#define ATM_ADDRESS_LENGTH 20 +#define WS2_INTERNAL_MAX_ALIAS 16 +#define MAX_HOSTNAME_LEN 256 +#define MAXADDRS 16 + +#endif + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS WinSock 2 NSP + * FILE: include/nsp_dns.h + * PURPOSE: WinSock 2 NSP Header + */ + +#ifndef __NSP_H +#define __NSP_H + +/* DEFINES *******************************************************************/ + +/* Lookup Flags */ +#define DONE 0x01 +#define REVERSE 0x02 +#define LOCAL 0x04 +#define IANA 0x10 +#define LOOPBACK 0x20 + +/* Protocol Flags */ +#define UDP 0x01 +#define TCP 0x02 +#define ATM 0x04 + +/* GUID Masks */ +#define NBT_MASK 0x01 +#define DNS_MASK 0x02 + +/* TYPES *********************************************************************/ + +typedef struct _RNR_CONTEXT +{ + LIST_ENTRY ListEntry; + HANDLE Handle; + PDNS_BLOB CachedSaBlob; + DWORD Signature; + DWORD RefCount; + DWORD Instance; + DWORD LookupFlags; + DWORD RnrId; + DWORD dwNameSpace; + DWORD RrType; + DWORD dwControlFlags; + DWORD UdpPort; + DWORD TcpPort; + DWORD ProtocolFlags; + BLOB CachedBlob; + GUID lpServiceClassId; + GUID lpProviderId; + WCHAR ServiceName[1]; +} RNR_CONTEXT, *PRNR_CONTEXT; + +typedef struct _RNR_TEB_DATA +{ + ULONG Foo; +} RNR_TEB_DATA, *PRNR_TEB_DATA; + +/* PROTOTYPES ****************************************************************/ + +/* + * proc.c + */ +BOOLEAN +WINAPI +RNRPROV_SockEnterApi(VOID); + +/* + * oldutil.c + */ +DWORD +WINAPI +GetServerAndProtocolsFromString( + PWCHAR ServiceString, + LPGUID ServiceType, + PSERVENT *ReverseServent +); + +DWORD +WINAPI +FetchPortFromClassInfo( + IN DWORD Type, + IN LPGUID Guid, + IN LPWSASERVICECLASSINFOW ServiceClassInfo +); + +PSERVENT +WSPAPI +CopyServEntry( + IN PSERVENT Servent, + IN OUT PULONG_PTR BufferPos, + IN OUT PULONG BufferFreeSize, + IN OUT PULONG BlobSize, + IN BOOLEAN Relative +); + +WORD +WINAPI +GetDnsQueryTypeFromGuid( + IN LPGUID Guid +); + +/* + * context.c + */ +VOID +WSPAPI +RnrCtx_ListCleanup(VOID); + +VOID +WSPAPI +RnrCtx_Release(PRNR_CONTEXT RnrContext); + +PRNR_CONTEXT +WSPAPI +RnrCtx_Get( + HANDLE LookupHandle, + DWORD dwControlFlags, + PLONG Instance +); + +PRNR_CONTEXT +WSPAPI +RnrCtx_Create( + IN HANDLE LookupHandle, + IN LPWSTR ServiceName +); + +VOID +WSPAPI +RnrCtx_DecInstance(IN PRNR_CONTEXT RnrContext); + +/* + * util.c + */ +PVOID +WSPAPI +Temp_AllocZero(IN DWORD Size); + +/* + * lookup.c + */ +PDNS_BLOB +WSPAPI +Rnr_DoHostnameLookup(IN PRNR_CONTEXT Context); + +PDNS_BLOB +WSPAPI +Rnr_GetHostByAddr(IN PRNR_CONTEXT Context); + +PDNS_BLOB +WSPAPI +Rnr_DoDnsLookup(IN PRNR_CONTEXT Context); + +BOOLEAN +WINAPI +Rnr_CheckIfUseNbt(PRNR_CONTEXT RnrContext); + +PDNS_BLOB +WINAPI +Rnr_NbtResolveAddr(IN IN_ADDR Address); + +PDNS_BLOB +WINAPI +Rnr_NbtResolveName(IN LPWSTR Name); + +/* + * init.c + */ +VOID +WSPAPI +Rnr_ProcessInit(VOID); + +VOID +WSPAPI +Rnr_ProcessCleanup(VOID); + +BOOLEAN +WSPAPI +Rnr_ThreadInit(VOID); + +VOID +WSPAPI +Rnr_ThreadCleanup(VOID); + +/* + * nsp.c + */ +VOID +WSPAPI +Nsp_GlobalCleanup(VOID); + +INT +WINAPI +Dns_NSPCleanup(IN LPGUID lpProviderId); + +INT +WINAPI +Dns_NSPSetService( + IN LPGUID lpProviderId, + IN LPWSASERVICECLASSINFOW lpServiceClassInfo, + IN LPWSAQUERYSETW lpqsRegInfo, + IN WSAESETSERVICEOP essOperation, + IN DWORD dwControlFlags +); + +INT +WINAPI +Dns_NSPInstallServiceClass( + IN LPGUID lpProviderId, + IN LPWSASERVICECLASSINFOW lpServiceClassInfo +); + +INT +WINAPI +Dns_NSPRemoveServiceClass( + IN LPGUID lpProviderId, + IN LPGUID lpServiceCallId +); + +INT +WINAPI +Dns_NSPGetServiceClassInfo( + IN LPGUID lpProviderId, + IN OUT LPDWORD lpdwBufSize, + IN OUT LPWSASERVICECLASSINFOW lpServiceClassInfo +); + +INT +WINAPI +Dns_NSPLookupServiceBegin( + LPGUID lpProviderId, + LPWSAQUERYSETW lpqsRestrictions, + LPWSASERVICECLASSINFOW lpServiceClassInfo, + DWORD dwControlFlags, + LPHANDLE lphLookup +); + +INT +WINAPI +Dns_NSPLookupServiceNext( + IN HANDLE hLookup, + IN DWORD dwControlFlags, + IN OUT LPDWORD lpdwBufferLength, + OUT LPWSAQUERYSETW lpqsResults +); + +INT +WINAPI +Dns_NSPLookupServiceEnd(IN HANDLE hLookup); + +INT +WINAPI +Dns_NSPStartup( + IN LPGUID lpProviderId, + IN OUT LPNSP_ROUTINE lpsnpRoutines +); + +/* Unchecked yet */ +#define ATM_ADDRESS_LENGTH 20 +#define WS2_INTERNAL_MAX_ALIAS 16 +#define MAX_HOSTNAME_LEN 256 +#define MAXADDRS 16 + +#endif + diff --git a/include/reactos/winsock/wsmobile.h b/include/reactos/winsock/wsmobile.h new file mode 100644 index 00000000000..3bfce930837 --- /dev/null +++ b/include/reactos/winsock/wsmobile.h @@ -0,0 +1,168 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS WinSock 2 NSP + * FILE: include/nsp_dns.h + * PURPOSE: WinSock 2 NSP Header + */ + +#ifndef __WSM_H +#define __WSM_H + +/* nsp.cpp */ +extern GUID gNLANamespaceGuid; + +/* + * nsp.cpp + */ +INT +WINAPI +WSM_NSPCleanup(IN LPGUID lpProviderId); + +INT +WINAPI +WSM_NSPSetService( + IN LPGUID lpProviderId, + IN LPWSASERVICECLASSINFOW lpServiceClassInfo, + IN LPWSAQUERYSETW lpqsRegInfo, + IN WSAESETSERVICEOP essOperation, + IN DWORD dwControlFlags +); + +INT +WINAPI +WSM_NSPInstallServiceClass( + IN LPGUID lpProviderId, + IN LPWSASERVICECLASSINFOW lpServiceClassInfo +); + +INT +WINAPI +WSM_NSPRemoveServiceClass( + IN LPGUID lpProviderId, + IN LPGUID lpServiceCallId +); + +INT +WINAPI +WSM_NSPGetServiceClassInfo( + IN LPGUID lpProviderId, + IN OUT LPDWORD lpdwBufSize, + IN OUT LPWSASERVICECLASSINFOW lpServiceClassInfo +); + +INT +WINAPI +WSM_NSPLookupServiceBegin( + LPGUID lpProviderId, + LPWSAQUERYSETW lpqsRestrictions, + LPWSASERVICECLASSINFOW lpServiceClassInfo, + DWORD dwControlFlags, + LPHANDLE lphLookup +); + +INT +WINAPI +WSM_NSPLookupServiceNext( + IN HANDLE hLookup, + IN DWORD dwControlFlags, + IN OUT LPDWORD lpdwBufferLength, + OUT LPWSAQUERYSETW lpqsResults +); + +INT +WINAPI +WSM_NSPLookupServiceEnd(IN HANDLE hLookup); + +INT +WINAPI +WSM_NSPStartup( + IN LPGUID lpProviderId, + IN OUT LPNSP_ROUTINE lpsnpRoutines +); + +#endif + +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS WinSock 2 NSP + * FILE: include/nsp_dns.h + * PURPOSE: WinSock 2 NSP Header + */ + +#ifndef __WSM_H +#define __WSM_H + +/* nsp.cpp */ +extern GUID gNLANamespaceGuid; + +/* + * nsp.cpp + */ +INT +WINAPI +WSM_NSPCleanup(IN LPGUID lpProviderId); + +INT +WINAPI +WSM_NSPSetService( + IN LPGUID lpProviderId, + IN LPWSASERVICECLASSINFOW lpServiceClassInfo, + IN LPWSAQUERYSETW lpqsRegInfo, + IN WSAESETSERVICEOP essOperation, + IN DWORD dwControlFlags +); + +INT +WINAPI +WSM_NSPInstallServiceClass( + IN LPGUID lpProviderId, + IN LPWSASERVICECLASSINFOW lpServiceClassInfo +); + +INT +WINAPI +WSM_NSPRemoveServiceClass( + IN LPGUID lpProviderId, + IN LPGUID lpServiceCallId +); + +INT +WINAPI +WSM_NSPGetServiceClassInfo( + IN LPGUID lpProviderId, + IN OUT LPDWORD lpdwBufSize, + IN OUT LPWSASERVICECLASSINFOW lpServiceClassInfo +); + +INT +WINAPI +WSM_NSPLookupServiceBegin( + LPGUID lpProviderId, + LPWSAQUERYSETW lpqsRestrictions, + LPWSASERVICECLASSINFOW lpServiceClassInfo, + DWORD dwControlFlags, + LPHANDLE lphLookup +); + +INT +WINAPI +WSM_NSPLookupServiceNext( + IN HANDLE hLookup, + IN DWORD dwControlFlags, + IN OUT LPDWORD lpdwBufferLength, + OUT LPWSAQUERYSETW lpqsResults +); + +INT +WINAPI +WSM_NSPLookupServiceEnd(IN HANDLE hLookup); + +INT +WINAPI +WSM_NSPStartup( + IN LPGUID lpProviderId, + IN OUT LPNSP_ROUTINE lpsnpRoutines +); + +#endif + From 503fdfb05966308e56f9eb4521113f4aeb4c9878 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sat, 6 Feb 2010 03:01:51 +0000 Subject: [PATCH 15/24] - New winsock (part 6 of x) - Remove old dnslib svn path=/branches/aicom-network-branch/; revision=45453 --- lib/dnslib/addr.c | 65 ---- lib/dnslib/debug.c | 14 - lib/dnslib/dnsaddr.c | 200 ------------ lib/dnslib/dnslib.rbuild | 22 -- lib/dnslib/dnsutil.c | 14 - lib/dnslib/flatbuf.c | 116 ------- lib/dnslib/hostent.c | 97 ------ lib/dnslib/inc/dnslib.h | 343 --------------------- lib/dnslib/inc/precomp.h | 24 -- lib/dnslib/inc/windnsp.h | 28 -- lib/dnslib/ip6.c | 14 - lib/dnslib/memory.c | 66 ---- lib/dnslib/name.c | 14 - lib/dnslib/print.c | 14 - lib/dnslib/record.c | 14 - lib/dnslib/rrprint.c | 14 - lib/dnslib/sablob.c | 640 --------------------------------------- lib/dnslib/straddr.c | 462 ---------------------------- lib/dnslib/string.c | 257 ---------------- lib/dnslib/table.c | 14 - lib/dnslib/utf8.c | 14 - lib/lib.rbuild | 3 - 22 files changed, 2449 deletions(-) delete mode 100644 lib/dnslib/addr.c delete mode 100644 lib/dnslib/debug.c delete mode 100644 lib/dnslib/dnsaddr.c delete mode 100644 lib/dnslib/dnslib.rbuild delete mode 100644 lib/dnslib/dnsutil.c delete mode 100644 lib/dnslib/flatbuf.c delete mode 100644 lib/dnslib/hostent.c delete mode 100644 lib/dnslib/inc/dnslib.h delete mode 100644 lib/dnslib/inc/precomp.h delete mode 100644 lib/dnslib/inc/windnsp.h delete mode 100644 lib/dnslib/ip6.c delete mode 100644 lib/dnslib/memory.c delete mode 100644 lib/dnslib/name.c delete mode 100644 lib/dnslib/print.c delete mode 100644 lib/dnslib/record.c delete mode 100644 lib/dnslib/rrprint.c delete mode 100644 lib/dnslib/sablob.c delete mode 100644 lib/dnslib/straddr.c delete mode 100644 lib/dnslib/string.c delete mode 100644 lib/dnslib/table.c delete mode 100644 lib/dnslib/utf8.c diff --git a/lib/dnslib/addr.c b/lib/dnslib/addr.c deleted file mode 100644 index b91c532e49a..00000000000 --- a/lib/dnslib/addr.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/addr.c - * PURPOSE: Contains the Address Family Information Tables - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -DNS_FAMILY_INFO AddrFamilyTable[3] = -{ - { - AF_INET, - DNS_TYPE_A, - sizeof(IP4_ADDRESS), - sizeof(SOCKADDR_IN), - FIELD_OFFSET(SOCKADDR_IN, sin_addr) - }, - { - AF_INET6, - DNS_TYPE_AAAA, - sizeof(IP6_ADDRESS), - sizeof(SOCKADDR_IN6), - FIELD_OFFSET(SOCKADDR_IN6, sin6_addr) - }, - { - AF_ATM, - DNS_TYPE_ATMA, - sizeof(ATM_ADDRESS), - sizeof(SOCKADDR_ATM), - FIELD_OFFSET(SOCKADDR_ATM, satm_number) - } -}; - -/* FUNCTIONS *****************************************************************/ - -PDNS_FAMILY_INFO -WINAPI -FamilyInfo_GetForFamily(IN WORD AddressFamily) -{ - /* Check which family this is */ - switch (AddressFamily) - { - case AF_INET: - /* Return IPv4 Family Info */ - return &AddrFamilyTable[0]; - - case AF_INET6: - /* Return IPv6 Family Info */ - return &AddrFamilyTable[1]; - - case AF_ATM: - /* Return ATM Family Info */ - return &AddrFamilyTable[2]; - - default: - /* Invalid family */ - return NULL; - } - -} - diff --git a/lib/dnslib/debug.c b/lib/dnslib/debug.c deleted file mode 100644 index 7ec359759b5..00000000000 --- a/lib/dnslib/debug.c +++ /dev/null @@ -1,14 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/debug.c - * PURPOSE: Contains helpful debugging functions for DNSLIB structures. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - diff --git a/lib/dnslib/dnsaddr.c b/lib/dnslib/dnsaddr.c deleted file mode 100644 index 310a0966f8b..00000000000 --- a/lib/dnslib/dnsaddr.c +++ /dev/null @@ -1,200 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/dnsaddr.c - * PURPOSE: Functions dealing with DNS_ADDRESS and DNS_ARRAY addresses. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -PDNS_ARRAY -WINAPI -DnsAddrArray_Create(ULONG Count) -{ - PDNS_ARRAY DnsAddrArray; - - /* Allocate space for the array and the addresses within it */ - DnsAddrArray = Dns_AllocZero(sizeof(DNS_ARRAY) + - (Count * sizeof(DNS_ADDRESS))); - - /* Write the allocated address count */ - if (DnsAddrArray) DnsAddrArray->AllocatedAddresses = Count; - - /* Return it */ - return DnsAddrArray; -} - -VOID -WINAPI -DnsAddrArray_Free(IN PDNS_ARRAY DnsAddrArray) -{ - /* Just free the entire array */ - Dns_Free(DnsAddrArray); -} - -BOOL -WINAPI -DnsAddrArray_AddIp4(IN PDNS_ARRAY DnsAddrArray, - IN IN_ADDR Address, - IN DWORD AddressType) -{ - DNS_ADDRESS DnsAddress; - - /* Build the DNS Address */ - DnsAddr_BuildFromIp4(&DnsAddress, Address, 0); - - /* Add it to the array */ - return DnsAddrArray_AddAddr(DnsAddrArray, &DnsAddress, 0, AddressType); -} - -BOOL -WINAPI -DnsAddrArray_AddAddr(IN PDNS_ARRAY DnsAddrArray, - IN PDNS_ADDRESS DnsAddress, - IN WORD AddressFamily OPTIONAL, - IN DWORD AddressType OPTIONAL) -{ - /* Make sure we have an array */ - if (!DnsAddrArray) return FALSE; - - /* Check if we should validate the Address Family */ - if (AddressFamily) - { - /* Validate it */ - if (AddressFamily != DnsAddress->AddressFamily) return TRUE; - } - - /* Check if we should validate the Address Type */ - if (AddressType) - { - /* Make sure that this array contains this type of addresses */ - if (!DnsAddrArray_ContainsAddr(DnsAddrArray, DnsAddress, AddressType)) - { - /* Won't be adding it */ - return TRUE; - } - } - - /* Make sure we have space in the array */ - if (DnsAddrArray->AllocatedAddresses < DnsAddrArray->UsedAddresses) - { - return FALSE; - } - - /* Now add the address */ - RtlCopyMemory(&DnsAddrArray->Addresses[DnsAddrArray->UsedAddresses], - DnsAddress, - sizeof(DNS_ADDRESS)); - - /* Return success */ - return TRUE; -} - -VOID -WINAPI -DnsAddr_BuildFromIp4(IN PDNS_ADDRESS DnsAddress, - IN IN_ADDR Address, - IN WORD Port) -{ - /* Clear the address */ - RtlZeroMemory(DnsAddress, sizeof(DNS_ADDRESS)); - - /* Write data */ - DnsAddress->Ip4Address.sin_family = AF_INET; - DnsAddress->Ip4Address.sin_port = Port; - DnsAddress->Ip4Address.sin_addr = Address; - DnsAddress->AddressLength = sizeof(SOCKADDR_IN); -} - -VOID -WINAPI -DnsAddr_BuildFromIp6(IN PDNS_ADDRESS DnsAddress, - IN PIN6_ADDR Address, - IN ULONG ScopeId, - IN WORD Port) -{ - /* Clear the address */ - RtlZeroMemory(DnsAddress, sizeof(DNS_ADDRESS)); - - /* Write data */ - DnsAddress->Ip6Address.sin6_family = AF_INET6; - DnsAddress->Ip6Address.sin6_port = Port; - DnsAddress->Ip6Address.sin6_addr = *Address; - DnsAddress->Ip6Address.sin6_scope_id = ScopeId; - DnsAddress->AddressLength = sizeof(SOCKADDR_IN6); -} - -VOID -WINAPI -DnsAddr_BuildFromAtm(IN PDNS_ADDRESS DnsAddress, - IN DWORD AddressType, - IN PVOID AddressData) -{ - ATM_ADDRESS Address; - - /* Clear the address */ - RtlZeroMemory(DnsAddress, sizeof(DNS_ADDRESS)); - - /* Build an ATM Address */ - Address.AddressType = AddressType; - Address.NumofDigits = DNS_ATMA_MAX_ADDR_LENGTH; - RtlCopyMemory(&Address.Addr, AddressData, DNS_ATMA_MAX_ADDR_LENGTH); - - /* Write data */ - DnsAddress->AtmAddress = Address; - DnsAddress->AddressLength = sizeof(ATM_ADDRESS); -} - -BOOLEAN -WINAPI -DnsAddr_BuildFromDnsRecord(IN PDNS_RECORD DnsRecord, - OUT PDNS_ADDRESS DnsAddr) -{ - /* Check what kind of record this is */ - switch(DnsRecord->wType) - { - /* IPv4 */ - case DNS_TYPE_A: - /* Create the DNS Address */ - DnsAddr_BuildFromIp4(DnsAddr, - *(PIN_ADDR)&DnsRecord->Data.A.IpAddress, - 0); - break; - - /* IPv6 */ - case DNS_TYPE_AAAA: - /* Create the DNS Address */ - DnsAddr_BuildFromIp6(DnsAddr, - (PIN6_ADDR)&DnsRecord->Data.AAAA.Ip6Address, - DnsRecord->dwReserved, - 0); - break; - - /* ATM */ - case DNS_TYPE_ATMA: - /* Create the DNS Address */ - DnsAddr_BuildFromAtm(DnsAddr, - DnsRecord->Data.Atma.AddressType, - &DnsRecord->Data.Atma.Address); - break; - } - - /* Done! */ - return TRUE; -} - -BOOL -WINAPI -DnsAddrArray_ContainsAddr(IN PDNS_ARRAY DnsAddrArray, - IN PDNS_ADDRESS DnsAddress, - IN DWORD AddressType) -{ - /* FIXME */ - return TRUE; -} - diff --git a/lib/dnslib/dnslib.rbuild b/lib/dnslib/dnslib.rbuild deleted file mode 100644 index 77806231ca6..00000000000 --- a/lib/dnslib/dnslib.rbuild +++ /dev/null @@ -1,22 +0,0 @@ - - - - inc - addr.c - debug.c - dnsaddr.c - dnsutil.c - flatbuf.c - hostent.c - ip6.c - memory.c - name.c - print.c - record.c - rrprint.c - sablob.c - straddr.c - string.c - table.c - utf8.c - diff --git a/lib/dnslib/dnsutil.c b/lib/dnslib/dnsutil.c deleted file mode 100644 index 1d0e814d911..00000000000 --- a/lib/dnslib/dnsutil.c +++ /dev/null @@ -1,14 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/dnsutil.c - * PURPOSE: Contains misc. DNS utility functions, like DNS_STATUS->String. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - diff --git a/lib/dnslib/flatbuf.c b/lib/dnslib/flatbuf.c deleted file mode 100644 index dfceb3e82a3..00000000000 --- a/lib/dnslib/flatbuf.c +++ /dev/null @@ -1,116 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/flatbuf.c - * PURPOSE: Functions for managing the Flat Buffer Implementation (FLATBUF) - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -VOID -WINAPI -FlatBuf_Init(IN PFLATBUFF FlatBuffer, - IN PVOID Buffer, - IN SIZE_T Size) -{ - /* Set up the Flat Buffer start, current and ending position */ - FlatBuffer->Buffer = Buffer; - FlatBuffer->BufferPos = (ULONG_PTR)Buffer; - FlatBuffer->BufferEnd = (PVOID)(FlatBuffer->BufferPos + Size); - - /* Setup the current size and the available size */ - FlatBuffer->BufferSize = FlatBuffer->BufferFreeSize = Size; -} - -PVOID -WINAPI -FlatBuf_Arg_Reserve(IN OUT PULONG_PTR Position, - IN OUT PSIZE_T FreeSize, - IN SIZE_T Size, - IN ULONG Align) -{ - ULONG_PTR NewPosition, OldPosition = *Position; - SIZE_T NewFreeSize = *FreeSize; - - /* Start by aligning our position */ - if (Align) OldPosition += (Align - 1) & ~Align; - - /* Update it */ - NewPosition = OldPosition + Size; - - /* Update Free Size */ - NewFreeSize += (OldPosition - NewPosition); - - /* Save new values */ - *Position = NewPosition; - *FreeSize = NewFreeSize; - - /* Check if we're out of space or not */ - if (NewFreeSize > 0) return (PVOID)OldPosition; - return NULL; -} - -PVOID -WINAPI -FlatBuf_Arg_CopyMemory(IN OUT PULONG_PTR Position, - IN OUT PSIZE_T FreeSize, - IN PVOID Buffer, - IN SIZE_T Size, - IN ULONG Align) -{ - PVOID Destination; - - /* First reserve the memory */ - Destination = FlatBuf_Arg_Reserve(Position, FreeSize, Size, Align); - if (Destination) - { - /* We have space, do the copy */ - RtlCopyMemory(Destination, Buffer, Size); - } - - /* Return the pointer to the data */ - return Destination; -} - -PVOID -WINAPI -FlatBuf_Arg_WriteString(IN OUT PULONG_PTR Position, - IN OUT PSIZE_T FreeSize, - IN PVOID String, - IN BOOLEAN IsUnicode) -{ - PVOID Destination; - SIZE_T StringLength; - ULONG Align; - - /* Calculate the string length */ - if (IsUnicode) - { - /* Get the length in bytes and use WCHAR alignment */ - StringLength = (wcslen((LPWSTR)String) + 1) * sizeof(WCHAR); - Align = sizeof(WCHAR); - } - else - { - /* Get the length in bytes and use CHAR alignment */ - StringLength = strlen((LPSTR)String) + 1; - Align = sizeof(CHAR); - } - - /* Now reserve the memory */ - Destination = FlatBuf_Arg_Reserve(Position, FreeSize, StringLength, Align); - if (Destination) - { - /* We have space, do the copy */ - RtlCopyMemory(Destination, String, StringLength); - } - - /* Return the pointer to the data */ - return Destination; -} - diff --git a/lib/dnslib/hostent.c b/lib/dnslib/hostent.c deleted file mode 100644 index f7c9e64bb39..00000000000 --- a/lib/dnslib/hostent.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/hostent.c - * PURPOSE: Functions for dealing with Host Entry structures - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -PHOSTENT -WINAPI -Hostent_Init(IN PVOID *Buffer, - IN WORD AddressFamily, - IN ULONG AddressSize, - IN ULONG AddressCount, - IN ULONG AliasCount) -{ - PHOSTENT Hostent; - ULONG_PTR BufferPosition = (ULONG_PTR)*Buffer; - - /* Align the hostent on the buffer's 4 byte boundary */ - BufferPosition += 3 & ~3; - - /* Set up the basic data */ - Hostent = (PHOSTENT)BufferPosition; - Hostent->h_length = (WORD)AddressSize; - Hostent->h_addrtype = AddressFamily; - - /* Put aliases after Hostent */ - Hostent->h_aliases = (PCHAR*)((ULONG_PTR)(Hostent + 1) & ~3); - - /* Zero it out */ - RtlZeroMemory(Hostent->h_aliases, AliasCount * sizeof(PCHAR)); - - /* Put addresses after aliases */ - Hostent->h_addr_list = (PCHAR*) - ((ULONG_PTR)Hostent->h_aliases + - (AliasCount * sizeof(PCHAR)) + sizeof(PCHAR)); - - /* Update the location */ - BufferPosition = (ULONG_PTR)Hostent->h_addr_list + - ((AddressCount * sizeof(PCHAR)) + sizeof(PCHAR)); - - /* Send it back */ - *Buffer = (PVOID)BufferPosition; - - /* Return the hostent */ - return Hostent; -} - -VOID -WINAPI -Dns_PtrArrayToOffsetArray(PCHAR *List, - ULONG_PTR Base) -{ - /* Loop every pointer in the list */ - do - { - /* Update the pointer */ - *List = (PCHAR)((ULONG_PTR)*List - Base); - } while(*List++); -} - -VOID -WINAPI -Hostent_ConvertToOffsets(IN PHOSTENT Hostent) -{ - /* Do we have a name? */ - if (Hostent->h_name) - { - /* Update it */ - Hostent->h_name -= (ULONG_PTR)Hostent; - } - - /* Do we have aliases? */ - if (Hostent->h_aliases) - { - /* Update the pointer */ - Hostent->h_aliases -= (ULONG_PTR)Hostent; - - /* Fix them up */ - Dns_PtrArrayToOffsetArray(Hostent->h_aliases, (ULONG_PTR)Hostent); - } - - /* Do we have addresses? */ - if (Hostent->h_addr_list) - { - /* Fix them up */ - Dns_PtrArrayToOffsetArray(Hostent->h_addr_list, (ULONG_PTR)Hostent); - } -} - diff --git a/lib/dnslib/inc/dnslib.h b/lib/dnslib/inc/dnslib.h deleted file mode 100644 index 4c187f15b37..00000000000 --- a/lib/dnslib/inc/dnslib.h +++ /dev/null @@ -1,343 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Ancillary Function Driver DLL - * FILE: include/mswsock.h - * PURPOSE: Ancillary Function Driver DLL header - */ -#ifndef __DNSLIB_H -#define __DNSLIB_H - -/* INCLUDES ******************************************************************/ -#include - -/* ENUMERATIONS **************************************************************/ - -typedef enum _DNS_STRING_TYPE -{ - UnicodeString = 1, - Utf8String, - AnsiString, -} DNS_STRING_TYPE; - -#define IpV4Address 3 - -/* TYPES *********************************************************************/ - -typedef struct _DNS_IPV6_ADDRESS -{ - ULONG Unknown; - ULONG Unknown2; - IP6_ADDRESS Address; - ULONG Unknown3; - ULONG Unknown4; - DWORD Reserved; - ULONG Unknown5; -} DNS_IPV6_ADDRESS, *PDNS_IPV6_ADDRESS; - -typedef struct _DNS_ADDRESS -{ - union - { - struct - { - WORD AddressFamily; - WORD Port; - ATM_ADDRESS AtmAddress; - }; - SOCKADDR_IN Ip4Address; - SOCKADDR_IN6 Ip6Address; - }; - ULONG AddressLength; - DWORD Sub; - ULONG Flag; -} DNS_ADDRESS, *PDNS_ADDRESS; - -typedef struct _DNS_ARRAY -{ - ULONG AllocatedAddresses; - ULONG UsedAddresses; - ULONG Unknown[0x6]; - DNS_ADDRESS Addresses[1]; -} DNS_ARRAY, *PDNS_ARRAY; - -typedef struct _DNS_BLOB -{ - LPWSTR Name; - PDNS_ARRAY DnsAddrArray; - PHOSTENT Hostent; - ULONG AliasCount; - ULONG Unknown; - LPWSTR Aliases[8]; -} DNS_BLOB, *PDNS_BLOB; - -typedef struct _DNS_FAMILY_INFO -{ - WORD AddrType; - WORD DnsType; - DWORD AddressSize; - DWORD SockaddrSize; - DWORD AddressOffset; -} DNS_FAMILY_INFO, *PDNS_FAMILY_INFO; - -typedef struct _FLATBUFF -{ - PVOID Buffer; - PVOID BufferEnd; - ULONG_PTR BufferPos; - SIZE_T BufferSize; - SIZE_T BufferFreeSize; -} FLATBUFF, *PFLATBUFF; - -/* - * memory.c - */ -VOID -WINAPI -Dns_Free(IN PVOID Address); - -PVOID -WINAPI -Dns_AllocZero(IN SIZE_T Size); - -/* - * addr.c - */ -PDNS_FAMILY_INFO -WINAPI -FamilyInfo_GetForFamily(IN WORD AddressFamily); - -/* - * dnsaddr.c - */ -VOID -WINAPI -DnsAddr_BuildFromIp4( - IN PDNS_ADDRESS DnsAddress, - IN IN_ADDR Address, - IN WORD Unknown -); - -VOID -WINAPI -DnsAddr_BuildFromIp6( - IN PDNS_ADDRESS DnsAddress, - IN PIN6_ADDR Address, - IN ULONG ScopeId, - IN WORD Port -); - -PDNS_ARRAY -WINAPI -DnsAddrArray_Create(ULONG Count); - -BOOL -WINAPI -DnsAddrArray_AddAddr( - IN PDNS_ARRAY DnsAddrArray, - IN PDNS_ADDRESS DnsAddress, - IN WORD AddressFamily OPTIONAL, - IN DWORD AddressType OPTIONAL -); - -VOID -WINAPI -DnsAddrArray_Free(IN PDNS_ARRAY DnsAddrArray); - -BOOL -WINAPI -DnsAddrArray_AddIp4( - IN PDNS_ARRAY DnsAddrArray, - IN IN_ADDR Address, - IN DWORD AddressType -); - -BOOL -WINAPI -DnsAddrArray_ContainsAddr( - IN PDNS_ARRAY DnsAddrArray, - IN PDNS_ADDRESS DnsAddress, - IN DWORD AddressType -); - -BOOLEAN -WINAPI -DnsAddr_BuildFromDnsRecord( - IN PDNS_RECORD DnsRecord, - OUT PDNS_ADDRESS DnsAddr -); - -/* - * hostent.c - */ -PHOSTENT -WINAPI -Hostent_Init( - IN PVOID *Buffer, - IN WORD AddressFamily, - IN ULONG AddressSize, - IN ULONG AddressCount, - IN ULONG AliasCount -); - -VOID -WINAPI -Hostent_ConvertToOffsets(IN PHOSTENT Hostent); - -/* - * flatbuf.c - */ -VOID -WINAPI -FlatBuf_Init( - IN PFLATBUFF FlatBuffer, - IN PVOID Buffer, - IN SIZE_T Size -); - -PVOID -WINAPI -FlatBuf_Arg_CopyMemory( - IN OUT PULONG_PTR Position, - IN OUT PSIZE_T FreeSize, - IN PVOID Buffer, - IN SIZE_T Size, - IN ULONG Align -); - -PVOID -WINAPI -FlatBuf_Arg_Reserve( - IN OUT PULONG_PTR Position, - IN OUT PSIZE_T FreeSize, - IN SIZE_T Size, - IN ULONG Align -); - -PVOID -WINAPI -FlatBuf_Arg_WriteString( - IN OUT PULONG_PTR Position, - IN OUT PSIZE_T FreeSize, - IN PVOID String, - IN BOOLEAN IsUnicode -); - -/* - * sablob.c - */ -PDNS_BLOB -WINAPI -SaBlob_Create( - IN ULONG Count -); - -PDNS_BLOB -WINAPI -SaBlob_CreateFromIp4( - IN LPWSTR Name, - IN ULONG Count, - IN PIN_ADDR AddressArray -); - -VOID -WINAPI -SaBlob_Free(IN PDNS_BLOB Blob); - -PHOSTENT -WINAPI -SaBlob_CreateHostent( - IN OUT PULONG_PTR BufferPosition, - IN OUT PSIZE_T RemainingBufferSpace, - IN OUT PSIZE_T HostEntrySize, - IN PDNS_BLOB Blob, - IN DWORD StringType, - IN BOOLEAN Relative, - IN BOOLEAN BufferAllocated -); - -INT -WINAPI -SaBlob_WriteNameOrAlias( - IN PDNS_BLOB Blob, - IN LPWSTR String, - IN BOOLEAN IsAlias -); - -PDNS_BLOB -WINAPI -SaBlob_Query( - IN LPWSTR Name, - IN WORD DnsType, - IN ULONG Flags, - IN PVOID *Reserved, - IN DWORD AddressFamily -); - -/* - * string.c - */ -ULONG -WINAPI -Dns_StringCopy( - OUT PVOID Destination, - IN OUT PULONG DestinationSize, - IN PVOID String, - IN ULONG StringSize OPTIONAL, - IN DWORD InputType, - IN DWORD OutputType -); - -LPWSTR -WINAPI -Dns_CreateStringCopy_W(IN LPWSTR Name); - -ULONG -WINAPI -Dns_GetBufferLengthForStringCopy( - IN PVOID String, - IN ULONG Size OPTIONAL, - IN DWORD InputType, - IN DWORD OutputType -); - -/* - * straddr.c - */ -BOOLEAN -WINAPI -Dns_StringToAddressW( - OUT PVOID Address, - IN OUT PULONG AddressSize, - IN LPWSTR AddressName, - IN OUT PDWORD AddressFamily -); - -LPWSTR -WINAPI -Dns_Ip4AddressToReverseName_W( - OUT LPWSTR Name, - IN IN_ADDR Address -); - -LPWSTR -WINAPI -Dns_Ip6AddressToReverseName_W( - OUT LPWSTR Name, - IN IN6_ADDR Address -); - -BOOLEAN -WINAPI -Dns_ReverseNameToDnsAddr_W( - OUT PDNS_ADDRESS DnsAddr, - IN LPWSTR Name -); - -BOOLEAN -WINAPI -Dns_Ip4ReverseNameToAddress_W( - OUT PIN_ADDR Address, - IN LPWSTR Name -); - -#endif diff --git a/lib/dnslib/inc/precomp.h b/lib/dnslib/inc/precomp.h deleted file mode 100644 index b30cb072d00..00000000000 --- a/lib/dnslib/inc/precomp.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/precomp.h - * PURPOSE: DNSLIB Precompiled Header - */ - -#define _CRT_SECURE_NO_DEPRECATE -#define _WIN32_WINNT 0x502 -#define WIN32_NO_STATUS - -/* PSDK Headers */ -#include -#include -#include - -/* DNSLIB and DNSAPI Headers */ -#include -#include - -/* NDK */ -#include - -/* EOF */ diff --git a/lib/dnslib/inc/windnsp.h b/lib/dnslib/inc/windnsp.h deleted file mode 100644 index 48087eb134b..00000000000 --- a/lib/dnslib/inc/windnsp.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNSAPI Header - * FILE: include/libs/dns/windnsp.h - * PURPOSE: DNSLIB Precompiled Header - */ - -PVOID -WINAPI -DnsApiAlloc( - IN DWORD Size -); - -PVOID -WINAPI -DnsQueryConfigAllocEx( - IN DNS_CONFIG_TYPE Config, - OUT PVOID pBuffer, - IN OUT PDWORD pBufferLength -); - -PVOID -WINAPI -DnsApiFree( - IN PVOID pBuffer -); - -/* EOF */ diff --git a/lib/dnslib/ip6.c b/lib/dnslib/ip6.c deleted file mode 100644 index 921fef41175..00000000000 --- a/lib/dnslib/ip6.c +++ /dev/null @@ -1,14 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/ip6.c - * PURPOSE: Functions for dealing with IPv6 Specific issues. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - diff --git a/lib/dnslib/memory.c b/lib/dnslib/memory.c deleted file mode 100644 index 183088c86b7..00000000000 --- a/lib/dnslib/memory.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/memory.c - * PURPOSE: DNS Memory Manager Implementation and Heap. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -typedef PVOID -(WINAPI *PDNS_ALLOC_FUNCTION)(IN SIZE_T Size); -typedef VOID -(WINAPI *PDNS_FREE_FUNCTION)(IN PVOID Buffer); - -PDNS_ALLOC_FUNCTION pDnsAllocFunction; -PDNS_FREE_FUNCTION pDnsFreeFunction; - -/* FUNCTIONS *****************************************************************/ - -VOID -WINAPI -Dns_Free(IN PVOID Address) -{ - /* Check if whoever imported us specified a special free function */ - if (pDnsFreeFunction) - { - /* Use it */ - pDnsFreeFunction(Address); - } - else - { - /* Use our own */ - LocalFree(Address); - } -} - -PVOID -WINAPI -Dns_AllocZero(IN SIZE_T Size) -{ - PVOID Buffer; - - /* Check if whoever imported us specified a special allocation function */ - if (pDnsAllocFunction) - { - /* Use it to allocate the memory */ - Buffer = pDnsAllocFunction(Size); - if (Buffer) - { - /* Zero it out */ - RtlZeroMemory(Buffer, Size); - } - } - else - { - /* Use our default */ - Buffer = LocalAlloc(LMEM_ZEROINIT, Size); - } - - /* Return the allocate pointer */ - return Buffer; -} - diff --git a/lib/dnslib/name.c b/lib/dnslib/name.c deleted file mode 100644 index 4004912315e..00000000000 --- a/lib/dnslib/name.c +++ /dev/null @@ -1,14 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/name.c - * PURPOSE: Functions dealing with DNS (Canonical, FQDN, Host) Names - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - diff --git a/lib/dnslib/print.c b/lib/dnslib/print.c deleted file mode 100644 index bead765eb3c..00000000000 --- a/lib/dnslib/print.c +++ /dev/null @@ -1,14 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/print.c - * PURPOSE: Callback Functions for printing a variety of DNSLIB Structures - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - diff --git a/lib/dnslib/record.c b/lib/dnslib/record.c deleted file mode 100644 index c0325a9b850..00000000000 --- a/lib/dnslib/record.c +++ /dev/null @@ -1,14 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/record.c - * PURPOSE: Functions for managing DNS Record structures. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - diff --git a/lib/dnslib/rrprint.c b/lib/dnslib/rrprint.c deleted file mode 100644 index 29a58ff86ed..00000000000 --- a/lib/dnslib/rrprint.c +++ /dev/null @@ -1,14 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/rrprint.c - * PURPOSE: Callback functions for printing RR Structures for each Record. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - diff --git a/lib/dnslib/sablob.c b/lib/dnslib/sablob.c deleted file mode 100644 index 1d720d2bb16..00000000000 --- a/lib/dnslib/sablob.c +++ /dev/null @@ -1,640 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/sablob.c - * PURPOSE: Functions for the Saved Answer Blob Implementation - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -PVOID -WINAPI -FlatBuf_Arg_ReserveAlignPointer(IN PVOID Position, - IN PSIZE_T FreeSize, - IN SIZE_T Size) -{ - /* Just a little helper that we use */ - return FlatBuf_Arg_Reserve(Position, FreeSize, Size, sizeof(PVOID)); -} - -PDNS_BLOB -WINAPI -SaBlob_Create(IN ULONG Count) -{ - PDNS_BLOB Blob; - PDNS_ARRAY DnsAddrArray; - - /* Allocate the blob */ - Blob = Dns_AllocZero(sizeof(DNS_BLOB)); - if (Blob) - { - /* Check if it'll hold any addresses */ - if (Count) - { - /* Create the DNS Address Array */ - DnsAddrArray = DnsAddrArray_Create(Count); - if (!DnsAddrArray) - { - /* Failure, free the blob */ - SaBlob_Free(Blob); - SetLastError(ERROR_OUTOFMEMORY); - } - else - { - /* Link it with the blob */ - Blob->DnsAddrArray = DnsAddrArray; - } - } - } - - /* Return the blob */ - return Blob; -} - -PDNS_BLOB -WINAPI -SaBlob_CreateFromIp4(IN LPWSTR Name, - IN ULONG Count, - IN PIN_ADDR AddressArray) -{ - PDNS_BLOB Blob; - LPWSTR NameCopy; - ULONG i; - - /* Create the blob */ - Blob = SaBlob_Create(Count); - if (!Blob) goto Quickie; - - /* If we have a name */ - if (Name) - { - /* Create a copy of it */ - NameCopy = Dns_CreateStringCopy_W(Name); - if (!NameCopy) goto Quickie; - - /* Save the pointer to the name */ - Blob->Name = NameCopy; - } - - /* Loop all the addresses */ - for (i = 0; i < Count; i++) - { - /* Add an entry for this address */ - DnsAddrArray_AddIp4(Blob->DnsAddrArray, AddressArray[i], IpV4Address); - } - - /* Return the blob */ - return Blob; - -Quickie: - /* Free the blob, set error and fail */ - SaBlob_Free(Blob); - SetLastError(ERROR_OUTOFMEMORY); - return NULL; -} - -VOID -WINAPI -SaBlob_Free(IN PDNS_BLOB Blob) -{ - /* Make sure we got a blob */ - if (Blob) - { - /* Free the name */ - Dns_Free(Blob->Name); - - /* Loop the aliases */ - while (Blob->AliasCount) - { - /* Free the alias */ - Dns_Free(Blob->Aliases[Blob->AliasCount]); - - /* Decrease number of aliases */ - Blob->AliasCount--; - } - - /* Free the DNS Address Array */ - DnsAddrArray_Free(Blob->DnsAddrArray); - - /* Free the blob itself */ - Dns_Free(Blob); - } -} - -PHOSTENT -WINAPI -SaBlob_CreateHostent(IN OUT PULONG_PTR BufferPosition, - IN OUT PSIZE_T FreeBufferSpace, - IN OUT PSIZE_T HostEntrySize, - IN PDNS_BLOB Blob, - IN DWORD StringType, - IN BOOLEAN Relative, - IN BOOLEAN BufferAllocated) -{ - PDNS_ARRAY DnsAddrArray = Blob->DnsAddrArray; - ULONG AliasCount = Blob->AliasCount; - WORD AddressFamily = AF_UNSPEC; - ULONG AddressCount = 0, AddressSize = 0, TotalSize, NamePointerSize; - ULONG AliasPointerSize; - PDNS_FAMILY_INFO FamilyInfo = NULL; - ULONG StringLength = 0; - ULONG i; - ULONG HostentSize = 0; - PHOSTENT Hostent = NULL; - ULONG_PTR HostentPtr; - PVOID CurrentAddress; - - /* Check if we actually have any addresses */ - if (DnsAddrArray) - { - /* Get the address family */ - AddressFamily = DnsAddrArray->Addresses[0].AddressFamily; - - /* Get family information */ - FamilyInfo = FamilyInfo_GetForFamily(AddressFamily); - - /* Save the current address count and their size */ - AddressCount = DnsAddrArray->UsedAddresses; - AddressSize = FamilyInfo->AddressSize; - } - - /* Calculate total size for all the addresses, and their pointers */ - TotalSize = AddressSize * AddressCount; - NamePointerSize = AddressCount * sizeof(PVOID) + sizeof(PVOID); - - /* Check if we have a name */ - if (Blob->Name) - { - /* Find out the size we'll need for a copy */ - StringLength = (Dns_GetBufferLengthForStringCopy(Blob->Name, - 0, - UnicodeString, - StringType) + 1) & ~1; - } - - /* Now do the same for the aliases */ - for (i = AliasCount; i; i--) - { - /* Find out the size we'll need for a copy */ - HostentSize += (Dns_GetBufferLengthForStringCopy(Blob->Aliases[i], - 0, - UnicodeString, - StringType) + 1) & ~1; - } - - /* Find out how much the pointers will take */ - AliasPointerSize = AliasCount * sizeof(PVOID) + sizeof(PVOID); - - /* Calculate Hostent Size */ - HostentSize += TotalSize + - NamePointerSize + - AliasPointerSize + - StringLength + - sizeof(HOSTENT); - - /* Check if we already have a buffer */ - if (!BufferAllocated) - { - /* We don't, allocate space ourselves */ - HostentPtr = (ULONG_PTR)Dns_AllocZero(HostentSize); - } - else - { - /* We do, so allocate space in the buffer */ - HostentPtr = (ULONG_PTR)FlatBuf_Arg_ReserveAlignPointer(BufferPosition, - FreeBufferSpace, - HostentSize); - } - - /* Make sure we got space */ - if (HostentPtr) - { - /* Initialize it */ - Hostent = Hostent_Init((PVOID)&HostentPtr, - AddressFamily, - AddressSize, - AddressCount, - AliasCount); - } - - /* Loop the addresses */ - for (i = 0; i < AddressCount; i++) - { - /* Get the pointer of the current address */ - CurrentAddress = (PVOID)((ULONG_PTR)&DnsAddrArray->Addresses[i] + - FamilyInfo->AddressOffset); - - /* Write the pointer */ - Hostent->h_addr_list[i] = (PCHAR)HostentPtr; - - /* Copy the address */ - RtlCopyMemory((PVOID)HostentPtr, CurrentAddress, AddressSize); - - /* Advance the buffer */ - HostentPtr += AddressSize; - } - - /* Check if we have a name */ - if (Blob->Name) - { - /* Align our current position */ - HostentPtr += 1 & ~1; - - /* Save our name here */ - Hostent->h_name = (LPSTR)HostentPtr; - - /* Now copy it in the blob */ - HostentPtr += Dns_StringCopy((PVOID)HostentPtr, - NULL, - Blob->Name, - 0, - UnicodeString, - StringType); - } - - /* Loop the Aliases */ - for (i = AliasCount; i; i--) - { - /* Align our current position */ - HostentPtr += 1 & ~1; - - /* Save our alias here */ - Hostent->h_aliases[i] = (LPSTR)HostentPtr; - - /* Now copy it in the blob */ - HostentPtr += Dns_StringCopy((PVOID)HostentPtr, - NULL, - Blob->Aliases[i], - 0, - UnicodeString, - StringType); - } - - /* Check if the caller didn't have a buffer */ - if (!BufferAllocated) - { - /* Return the size; not needed if we had a blob, since it's internal */ - *HostEntrySize = *BufferPosition - (ULONG_PTR)HostentPtr; - } - - /* Convert to Offsets if requested */ - if(Relative) Hostent_ConvertToOffsets(Hostent); - - /* Return the full, complete, hostent */ - return Hostent; -} - -INT -WINAPI -SaBlob_WriteNameOrAlias(IN PDNS_BLOB Blob, - IN LPWSTR String, - IN BOOLEAN IsAlias) -{ - /* Check if this is an alias */ - if (!IsAlias) - { - /* It's not. Simply create a copy of the string */ - Blob->Name = Dns_CreateStringCopy_W(String); - if (!Blob->Name) return GetLastError(); - } - else - { - /* Does it have a name, and less then 8 aliases? */ - if ((Blob->Name) && (Blob->AliasCount <= 8)) - { - /* Yup, create a copy of the string and increase the alias count */ - Blob->Aliases[Blob->AliasCount] = Dns_CreateStringCopy_W(String); - Blob->AliasCount++; - } - else - { - /* Invalid request! */ - return ERROR_MORE_DATA; - } - } - - /* Return Success */ - return ERROR_SUCCESS; -} - -INT -WINAPI -SaBlob_WriteAddress(IN PDNS_BLOB Blob, - OUT PDNS_ADDRESS DnsAddr) -{ - /* Check if we have an array yet */ - if (!Blob->DnsAddrArray) - { - /* Allocate one! */ - Blob->DnsAddrArray = DnsAddrArray_Create(1); - if (!Blob->DnsAddrArray) return ERROR_OUTOFMEMORY; - } - - /* Add this address */ - return DnsAddrArray_AddAddr(Blob->DnsAddrArray, DnsAddr, AF_UNSPEC, 0) ? - ERROR_SUCCESS: - ERROR_MORE_DATA; -} - -BOOLEAN -WINAPI -SaBlob_IsSupportedAddrType(WORD DnsType) -{ - /* Check for valid Types that we support */ - return (DnsType == DNS_TYPE_A || - DnsType == DNS_TYPE_ATMA || - DnsType == DNS_TYPE_AAAA); -} - -INT -WINAPI -SaBlob_WriteRecords(OUT PDNS_BLOB Blob, - IN PDNS_RECORD DnsRecord, - IN BOOLEAN DoAlias) -{ - DNS_ADDRESS DnsAddress; - INT ErrorCode = STATUS_INVALID_PARAMETER; - BOOLEAN WroteOnce = FALSE; - - /* Zero out the Address */ - RtlZeroMemory(&DnsAddress, sizeof(DnsAddress)); - - /* Loop through all the Records */ - while (DnsRecord) - { - /* Is this not an answer? */ - if (DnsRecord->Flags.S.Section != DNSREC_ANSWER) - { - /* Then simply move on to the next DNS Record */ - DnsRecord = DnsRecord->pNext; - continue; - } - - /* Check the type of thsi record */ - switch(DnsRecord->wType) - { - /* Regular IPv4, v6 or ATM Record */ - case DNS_TYPE_A: - case DNS_TYPE_AAAA: - case DNS_TYPE_ATMA: - - /* Create a DNS Address from the record */ - DnsAddr_BuildFromDnsRecord(DnsRecord, &DnsAddress); - - /* Add it to the DNS Blob */ - ErrorCode = SaBlob_WriteAddress(Blob, &DnsAddress); - - /* Add the name, if needed */ - if ((DoAlias) && - (!WroteOnce) && - (!Blob->Name) && - (DnsRecord->pName)) - { - /* Write the name from the DNS Record */ - ErrorCode = SaBlob_WriteNameOrAlias(Blob, - DnsRecord->pName, - FALSE); - WroteOnce = TRUE; - } - break; - - case DNS_TYPE_CNAME: - - /* Just write the alias name */ - ErrorCode = SaBlob_WriteNameOrAlias(Blob, - DnsRecord->pName, - TRUE); - break; - - case DNS_TYPE_PTR: - - /* Check if we already have a name */ - if (Blob->Name) - { - /* We don't, so add this as a name */ - ErrorCode = SaBlob_WriteNameOrAlias(Blob, - DnsRecord->pName, - FALSE); - } - else - { - /* We do, so add it as an alias */ - ErrorCode = SaBlob_WriteNameOrAlias(Blob, - DnsRecord->pName, - TRUE); - } - break; - default: - break; - } - - /* Next record */ - DnsRecord = DnsRecord->pNext; - } - - /* Return error code */ - return ErrorCode; -} - -PDNS_BLOB -WINAPI -SaBlob_CreateFromRecords(IN PDNS_RECORD DnsRecord, - IN BOOLEAN DoAliases, - IN DWORD DnsType) -{ - PDNS_RECORD LocalDnsRecord; - ULONG ProcessedCount = 0; - PDNS_BLOB DnsBlob; - INT ErrorCode; - DNS_ADDRESS DnsAddress; - - /* Find out how many DNS Addresses to allocate */ - LocalDnsRecord = DnsRecord; - while (LocalDnsRecord) - { - /* Make sure this record is an answer */ - if ((LocalDnsRecord->Flags.S.Section == DNSREC_ANSWER) && - (SaBlob_IsSupportedAddrType(LocalDnsRecord->wType))) - { - /* Increase number of records to process */ - ProcessedCount++; - } - - /* Move to the next record */ - LocalDnsRecord = LocalDnsRecord->pNext; - } - - /* Create the DNS Blob */ - DnsBlob = SaBlob_Create(ProcessedCount); - if (!DnsBlob) - { - /* Fail */ - ErrorCode = GetLastError(); - goto Quickie; - } - - /* Write the record to the DNS Blob */ - ErrorCode = SaBlob_WriteRecords(DnsBlob, DnsRecord, TRUE); - if (ErrorCode != NO_ERROR) - { - /* We failed... but do we still have valid data? */ - if ((DnsBlob->Name) || (DnsBlob->AliasCount)) - { - /* We'll just assume success then */ - ErrorCode = NO_ERROR; - } - else - { - /* Ok, last chance..do you have a DNS Address Array? */ - if ((DnsBlob->DnsAddrArray) && - (DnsBlob->DnsAddrArray->UsedAddresses)) - { - /* Boy are you lucky! */ - ErrorCode = NO_ERROR; - } - } - - /* Buh-bye! */ - goto Quickie; - } - - /* Check if this is a PTR record */ - if ((DnsRecord->wType == DNS_TYPE_PTR) || - ((DnsType == DNS_TYPE_PTR) && - (DnsRecord->wType == DNS_TYPE_CNAME) && - (DnsRecord->Flags.S.Section == DNSREC_ANSWER))) - { - /* Get a DNS Address Structure */ - if (Dns_ReverseNameToDnsAddr_W(&DnsAddress, DnsRecord->pName)) - { - /* Add it to the Blob */ - if (SaBlob_WriteAddress(DnsBlob, &DnsAddress)) ErrorCode = NO_ERROR; - } - } - - /* Ok...do we still not have a name? */ - if (!(DnsBlob->Name) && (DoAliases) && (LocalDnsRecord)) - { - /* We have an local DNS Record, so just use it to write the name */ - ErrorCode = SaBlob_WriteNameOrAlias(DnsBlob, - LocalDnsRecord->pName, - FALSE); - } - -Quickie: - /* Check error code */ - if (ErrorCode != NO_ERROR) - { - /* Free the blob and set the error */ - SaBlob_Free(DnsBlob); - DnsBlob = NULL; - SetLastError(ErrorCode); - } - - /* Return */ - return DnsBlob; -} - -PDNS_BLOB -WINAPI -SaBlob_Query(IN LPWSTR Name, - IN WORD DnsType, - IN ULONG Flags, - IN PVOID *Reserved, - IN DWORD AddressFamily) -{ - PDNS_RECORD DnsRecord = NULL; - INT ErrorCode; - PDNS_BLOB DnsBlob = NULL; - LPWSTR LocalName, LocalNameCopy; - - /* If they want reserved data back, clear it out in case we fail */ - if (Reserved) *Reserved = NULL; - - /* Query DNS */ - ErrorCode = DnsQuery_W(Name, - DnsType, - Flags, - NULL, - &DnsRecord, - Reserved); - if (ErrorCode != ERROR_SUCCESS) - { - /* We failed... did the caller use reserved data? */ - if (Reserved && *Reserved) - { - /* He did, and it was valid. Free it */ - DnsApiFree(*Reserved); - *Reserved = NULL; - } - - /* Normalize error code */ - if (ErrorCode == RPC_S_SERVER_UNAVAILABLE) ErrorCode = WSATRY_AGAIN; - goto Quickie; - } - - /* Now create the Blob from the DNS Records */ - DnsBlob = SaBlob_CreateFromRecords(DnsRecord, TRUE, DnsType); - if (!DnsBlob) - { - /* Failed, get error code */ - ErrorCode = GetLastError(); - goto Quickie; - } - - /* Make sure it has a name */ - if (!DnsBlob->Name) - { - /* It doesn't, fail */ - ErrorCode = DNS_INFO_NO_RECORDS; - goto Quickie; - } - - /* Check if the name is local or loopback */ - if (!(DnsNameCompare_W(DnsBlob->Name, L"localhost")) && - !(DnsNameCompare_W(DnsBlob->Name, L"loopback"))) - { - /* Nothing left to do, exit! */ - goto Quickie; - } - - /* This is a local name...query it */ - LocalName = DnsQueryConfigAllocEx(DnsConfigFullHostName_W, NULL, NULL); - if (LocalName) - { - /* Create a copy for the caller */ - LocalNameCopy = Dns_CreateStringCopy_W(LocalName); - if (LocalNameCopy) - { - /* Overwrite the one in the blob */ - DnsBlob->Name = LocalNameCopy; - } - else - { - /* We failed to make a copy, free memory */ - DnsApiFree(LocalName); - } - } - -Quickie: - /* Free the DNS Record if we have one */ - if (DnsRecord) DnsRecordListFree(DnsRecord, DnsFreeRecordList); - - /* Check if this is a failure path with an active blob */ - if ((ErrorCode != ERROR_SUCCESS) && (DnsBlob)) - { - /* Free the blob */ - SaBlob_Free(DnsBlob); - DnsBlob = NULL; - } - - /* Set the last error and return */ - SetLastError(ErrorCode); - return DnsBlob; -} - diff --git a/lib/dnslib/straddr.c b/lib/dnslib/straddr.c deleted file mode 100644 index 4215a80dbf0..00000000000 --- a/lib/dnslib/straddr.c +++ /dev/null @@ -1,462 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/straddr.c - * PURPOSE: Functions for address<->string conversion. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -LPWSTR -WINAPI -Dns_Ip6AddressToReverseName_W(OUT LPWSTR Name, - IN IN6_ADDR Address) -{ - /* FIXME */ - return NULL; -} - -LPWSTR -WINAPI -Dns_Ip4AddressToReverseName_W(OUT LPWSTR Name, - IN IN_ADDR Address) -{ - /* Simply append the ARPA string */ - return Name + (wsprintfW(Name, - L"%u.%u.%u.%u.in-addr.arpa.", - Address.S_un.S_addr >> 24, - Address.S_un.S_addr >> 10, - Address.S_un.S_addr >> 8, - Address.S_un.S_addr) * sizeof(WCHAR)); -} - -BOOLEAN -WINAPI -Dns_Ip4ReverseNameToAddress_A(OUT PIN_ADDR Address, - IN LPSTR Name) -{ - /* FIXME */ - return FALSE; -} - -BOOLEAN -WINAPI -Dns_Ip6ReverseNameToAddress_A(OUT PIN6_ADDR Address, - IN LPSTR Name) -{ - /* FIXME */ - return FALSE; -} - -BOOLEAN -WINAPI -Dns_Ip6StringToAddress_A(OUT PIN6_ADDR Address, - IN LPSTR Name) -{ - PCHAR Terminator; - NTSTATUS Status; - - /* Let RTL Do it for us */ - Status = RtlIpv6StringToAddressA(Name, &Terminator, Address); - if (NT_SUCCESS(Status)) return TRUE; - - /* We failed */ - return FALSE; -} - -BOOLEAN -WINAPI -Dns_Ip6StringToAddress_W(OUT PIN6_ADDR Address, - IN LPWSTR Name) -{ - PCHAR Terminator; - NTSTATUS Status; - - /* Let RTL Do it for us */ - Status = RtlIpv6StringToAddressW(Name, &Terminator, Address); - if (NT_SUCCESS(Status)) return TRUE; - - /* We failed */ - return FALSE; -} - -BOOLEAN -WINAPI -Dns_Ip4StringToAddress_A(OUT PIN_ADDR Address, - IN LPSTR Name) -{ - ULONG Addr; - - /* Use inet_addr to convert it... */ - Addr = inet_addr(Name); - if (Addr == -1) - { - /* Check if it's the wildcard (which is ok...) */ - if (strcmp("255.255.255.255", Name)) return FALSE; - } - - /* If we got here, then we suceeded... return the address */ - Address->S_un.S_addr = Addr; - return TRUE; -} - -BOOLEAN -WINAPI -Dns_Ip4StringToAddress_W(OUT PIN_ADDR Address, - IN LPWSTR Name) -{ - CHAR AnsiName[16]; - ULONG Size = sizeof(AnsiName); - INT ErrorCode; - - /* Make a copy of the name in ANSI */ - ErrorCode = Dns_StringCopy(&AnsiName, - &Size, - Name, - 0, - UnicodeString, - AnsiString); - if (ErrorCode) - { - /* Copy made sucesfully, now convert it */ - ErrorCode = Dns_Ip4StringToAddress_A(Address, AnsiName); - } - - /* Return either 0 bytes copied (failure == false) or conversion status */ - return ErrorCode; -} - -BOOLEAN -WINAPI -Dns_Ip4ReverseNameToAddress_W(OUT PIN_ADDR Address, - IN LPWSTR Name) -{ - CHAR AnsiName[32]; - ULONG Size = sizeof(AnsiName); - INT ErrorCode; - - /* Make a copy of the name in ANSI */ - ErrorCode = Dns_StringCopy(&AnsiName, - &Size, - Name, - 0, - UnicodeString, - AnsiString); - if (ErrorCode) - { - /* Copy made sucesfully, now convert it */ - ErrorCode = Dns_Ip4ReverseNameToAddress_A(Address, AnsiName); - } - - /* Return either 0 bytes copied (failure == false) or conversion status */ - return ErrorCode; -} - -BOOLEAN -WINAPI -Dns_StringToAddressEx(OUT PVOID Address, - IN OUT PULONG AddressSize, - IN PVOID AddressName, - IN OUT PDWORD AddressFamily, - IN BOOLEAN Unicode, - IN BOOLEAN Reverse) -{ - DWORD Af = *AddressFamily; - ULONG AddrSize = *AddressSize; - IN6_ADDR Addr; - BOOLEAN Return; - INT ErrorCode; - CHAR AnsiName[INET6_ADDRSTRLEN + sizeof("ip6.arpa.")]; - ULONG Size = sizeof(AnsiName); - - /* First check if this is a reverse address string */ - if (Reverse) - { - /* Convert it right now to ANSI as an optimization */ - Dns_StringCopy(AnsiName, - &Size, - AddressName, - 0, - UnicodeString, - AnsiString); - - /* Use the ANSI Name instead */ - AddressName = AnsiName; - } - - /* - * If the caller doesn't know what the family is, we'll assume IPv4 and - * check if we failed or not. If the caller told us it's IPv4, then just - * do IPv4... - */ - if ((Af == AF_UNSPEC) || (Af == AF_INET)) - { - /* Now check if the caller gave us the reverse name or not */ - if (Reverse) - { - /* Get the Address */ - Return = Dns_Ip4ReverseNameToAddress_A((PIN_ADDR)&Addr, AddressName); - } - else - { - /* Check if the caller gave us unicode or not */ - if (Unicode) - { - /* Get the Address */ - Return = Dns_Ip4StringToAddress_W((PIN_ADDR)&Addr, AddressName); - } - else - { - /* Get the Address */ - Return = Dns_Ip4StringToAddress_A((PIN_ADDR)&Addr, AddressName); - } - } - - /* Check if we suceeded */ - if (Return) - { - /* Save address family */ - Af = AF_INET; - - /* Check if the address size matches */ - if (AddrSize < sizeof(IN_ADDR)) - { - /* Invalid match, set error code */ - ErrorCode = ERROR_MORE_DATA; - } - else - { - /* It matches, save the address! */ - *(PIN_ADDR)Address = *(PIN_ADDR)&Addr; - } - } - } - - /* If we are here, either AF_INET6 was specified or IPv4 failed */ - if ((Af == AF_UNSPEC) || (Af == AF_INET6)) - { - /* Now check if the caller gave us the reverse name or not */ - if (Reverse) - { - /* Get the Address */ - Return = Dns_Ip6ReverseNameToAddress_A(&Addr, AddressName); - } - else - { - /* Check if the caller gave us unicode or not */ - if (Unicode) - { - /* Get the Address */ - Return = Dns_Ip6StringToAddress_W(&Addr, AddressName); - } - else - { - /* Get the Address */ - Return = Dns_Ip6StringToAddress_A(&Addr, AddressName); - } - } - - /* Check if we suceeded */ - if (Return) - { - /* Save address family */ - Af = AF_INET6; - - /* Check if the address size matches */ - if (AddrSize < sizeof(IN6_ADDR)) - { - /* Invalid match, set error code */ - ErrorCode = ERROR_MORE_DATA; - } - else - { - /* It matches, save the address! */ - *(PIN6_ADDR)Address = Addr; - } - } - } - else if (Af != AF_INET) - { - /* You're like.. ATM or something? Get outta here! */ - Af = AF_UNSPEC; - ErrorCode = WSA_INVALID_PARAMETER; - } - - /* Set error if we had one */ - if (ErrorCode) SetLastError(ErrorCode); - - /* Return the address family and size */ - *AddressFamily = Af; - *AddressSize = AddrSize; - - /* Return success or failure */ - return (ErrorCode == ERROR_SUCCESS); -} - -BOOLEAN -WINAPI -Dns_StringToAddressW(OUT PVOID Address, - IN OUT PULONG AddressSize, - IN LPWSTR AddressName, - IN OUT PDWORD AddressFamily) -{ - /* Call the common API */ - return Dns_StringToAddressEx(Address, - AddressSize, - AddressName, - AddressFamily, - TRUE, - FALSE); -} - -BOOLEAN -WINAPI -Dns_StringToDnsAddrEx(OUT PDNS_ADDRESS DnsAddr, - IN PVOID AddressName, - IN DWORD AddressFamily, - IN BOOLEAN Unicode, - IN BOOLEAN Reverse) -{ - IN6_ADDR Addr; - BOOLEAN Return; - INT ErrorCode = ERROR_SUCCESS; - CHAR AnsiName[INET6_ADDRSTRLEN + sizeof("ip6.arpa.")]; - ULONG Size = sizeof(AnsiName); - - /* First check if this is a reverse address string */ - if ((Reverse) && (Unicode)) - { - /* Convert it right now to ANSI as an optimization */ - Dns_StringCopy(AnsiName, - &Size, - AddressName, - 0, - UnicodeString, - AnsiString); - - /* Use the ANSI Name instead */ - AddressName = AnsiName; - } - - /* - * If the caller doesn't know what the family is, we'll assume IPv4 and - * check if we failed or not. If the caller told us it's IPv4, then just - * do IPv4... - */ - if ((AddressFamily == AF_UNSPEC) || (AddressFamily == AF_INET)) - { - /* Now check if the caller gave us the reverse name or not */ - if (Reverse) - { - /* Get the Address */ - Return = Dns_Ip4ReverseNameToAddress_A((PIN_ADDR)&Addr, AddressName); - } - else - { - /* Check if the caller gave us unicode or not */ - if (Unicode) - { - /* Get the Address */ - Return = Dns_Ip4StringToAddress_W((PIN_ADDR)&Addr, AddressName); - } - else - { - /* Get the Address */ - Return = Dns_Ip4StringToAddress_A((PIN_ADDR)&Addr, AddressName); - } - } - - /* Check if we suceeded */ - if (Return) - { - /* Build the IPv4 Address */ - DnsAddr_BuildFromIp4(DnsAddr, *(PIN_ADDR)&Addr, 0); - - /* So we don't go in the code below... */ - AddressFamily = AF_INET; - } - } - - /* If we are here, either AF_INET6 was specified or IPv4 failed */ - if ((AddressFamily == AF_UNSPEC) || (AddressFamily == AF_INET6)) - { - /* Now check if the caller gave us the reverse name or not */ - if (Reverse) - { - /* Get the Address */ - Return = Dns_Ip6ReverseNameToAddress_A(&Addr, AddressName); - if (Return) - { - /* Build the IPv6 Address */ - DnsAddr_BuildFromIp6(DnsAddr, &Addr, 0, 0); - } - else - { - goto Quickie; - } - } - else - { - /* Check if the caller gave us unicode or not */ - if (Unicode) - { - /* Get the Address */ - if (NT_SUCCESS(RtlIpv6StringToAddressExW(AddressName, - &DnsAddr->Ip6Address.sin6_addr, - &DnsAddr->Ip6Address.sin6_scope_id, - &DnsAddr->Ip6Address.sin6_port))) - Return = TRUE; - else - Return = FALSE; - } - else - { - /* Get the Address */ - if (NT_SUCCESS(RtlIpv6StringToAddressExA(AddressName, - &DnsAddr->Ip6Address.sin6_addr, - &DnsAddr->Ip6Address.sin6_scope_id, - &DnsAddr->Ip6Address.sin6_port))) - Return = TRUE; - else - Return = FALSE; - } - } - - /* Check if we suceeded */ - if (Return) - { - /* Finish setting up the structure */ - DnsAddr->Ip6Address.sin6_family = AF_INET6; - DnsAddr->AddressLength = sizeof(SOCKADDR_IN6); - } - } - else if (AddressFamily != AF_INET) - { - /* You're like.. ATM or something? Get outta here! */ - RtlZeroMemory(DnsAddr, sizeof(DNS_ADDRESS)); - SetLastError(WSA_INVALID_PARAMETER); - } - -Quickie: - /* Return success or failure */ - return (ErrorCode == ERROR_SUCCESS); -} - -BOOLEAN -WINAPI -Dns_ReverseNameToDnsAddr_W(OUT PDNS_ADDRESS DnsAddr, - IN LPWSTR Name) -{ - /* Call the common API */ - return Dns_StringToDnsAddrEx(DnsAddr, - Name, - AF_UNSPEC, - TRUE, - TRUE); -} - diff --git a/lib/dnslib/string.c b/lib/dnslib/string.c deleted file mode 100644 index e5ec0cfa935..00000000000 --- a/lib/dnslib/string.c +++ /dev/null @@ -1,257 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/string.c - * PURPOSE: functions for string manipulation and conversion. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -ULONG -WINAPI -Dns_StringCopy(OUT PVOID Destination, - IN OUT PULONG DestinationSize, - IN PVOID String, - IN ULONG StringSize OPTIONAL, - IN DWORD InputType, - IN DWORD OutputType) -{ - ULONG DestSize; - ULONG OutputSize = 0; - - /* Check if the caller already gave us the string size */ - if (!StringSize) - { - /* He didn't, get the input type */ - if (InputType == UnicodeString) - { - /* Unicode string, calculate the size */ - StringSize = (ULONG)wcslen((LPWSTR)String); - } - else - { - /* ANSI or UTF-8 sting, get the size */ - StringSize = (ULONG)strlen((LPSTR)String); - } - } - - /* Check if we have a limit on the desination size */ - if (DestinationSize) - { - /* Make sure that we can respect it */ - DestSize = Dns_GetBufferLengthForStringCopy(String, - StringSize, - InputType, - OutputType); - if (*DestinationSize < DestSize) - { - /* Fail due to missing buffer space */ - SetLastError(ERROR_MORE_DATA); - - /* Return how much data we actually need */ - *DestinationSize = DestSize; - return 0; - } - else if (!DestSize) - { - /* Fail due to invalid data */ - SetLastError(ERROR_INVALID_DATA); - return 0; - } - - /* Return how much data we actually need */ - *DestinationSize = DestSize; - } - - /* Now check if this is a Unicode String as input */ - if (InputType == UnicodeString) - { - /* Check if the output is ANSI */ - if (OutputType == AnsiString) - { - /* Convert and return the final desination size */ - OutputSize = WideCharToMultiByte(CP_ACP, - 0, - String, - StringSize, - Destination, - -1, - NULL, - NULL) + 1; - } - else if (OutputType == UnicodeString) - { - /* Copy the string */ - StringSize = StringSize * sizeof(WCHAR); - RtlMoveMemory(Destination, String, StringSize); - - /* Return output length */ - OutputSize = StringSize + 2; - } - else if (OutputType == Utf8String) - { - /* FIXME */ - OutputSize = 0; - } - } - else if (InputType == AnsiString) - { - /* It's ANSI, is the output ansi too? */ - if (OutputType == AnsiString) - { - /* Copy the string */ - RtlMoveMemory(Destination, String, StringSize); - - /* Return output length */ - OutputSize = StringSize + 1; - } - else if (OutputType == UnicodeString) - { - /* Convert to Unicode and return size */ - OutputSize = MultiByteToWideChar(CP_ACP, - 0, - String, - StringSize, - Destination, - -1) * sizeof(WCHAR) + 2; - } - else if (OutputType == Utf8String) - { - /* FIXME */ - OutputSize = 0; - } - } - else if (InputType == Utf8String) - { - /* FIXME */ - OutputSize = 0; - } - - /* Return the output size */ - return OutputSize; -} - -LPWSTR -WINAPI -Dns_CreateStringCopy_W(IN LPWSTR Name) -{ - SIZE_T StringLength; - LPWSTR NameCopy; - - /* Make sure that we have a name */ - if (!Name) - { - /* Fail */ - SetLastError(ERROR_INVALID_PARAMETER); - return NULL; - } - - /* Find out the size of the string */ - StringLength = (wcslen(Name) + 1) * sizeof(WCHAR); - - /* Allocate space for the copy */ - NameCopy = Dns_AllocZero(StringLength); - if (NameCopy) - { - /* Copy it */ - RtlCopyMemory(NameCopy, Name, StringLength); - } - else - { - /* Fail */ - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - } - - /* Return the copy */ - return NameCopy; -} - -ULONG -WINAPI -Dns_GetBufferLengthForStringCopy(IN PVOID String, - IN ULONG Size OPTIONAL, - IN DWORD InputType, - IN DWORD OutputType) -{ - ULONG OutputSize = 0; - - /* Check what kind of string this is */ - if (InputType == UnicodeString) - { - /* Check if we have a size */ - if (!Size) - { - /* Get it ourselves */ - Size = (ULONG)wcslen(String); - } - - /* Check the output type */ - if (OutputType == UnicodeString) - { - /* Convert the size to bytes */ - OutputSize = (Size + 1) * sizeof(WCHAR); - } - else if (OutputType == Utf8String) - { - /* FIXME */ - OutputSize = 0; - } - else - { - /* Find out how much it will be in ANSI bytes */ - OutputSize = WideCharToMultiByte(CP_ACP, - 0, - String, - Size, - NULL, - 0, - NULL, - NULL) + 1; - } - } - else if (InputType == AnsiString) - { - /* Check if we have a size */ - if (!Size) - { - /* Get it ourselves */ - Size = (ULONG)strlen(String); - } - - /* Check the output type */ - if (OutputType == AnsiString) - { - /* Just add a byte for the null char */ - OutputSize = Size + 1; - } - else if (OutputType == UnicodeString) - { - /* Calculate the bytes for a Unicode string */ - OutputSize = (MultiByteToWideChar(CP_ACP, - 0, - String, - Size, - NULL, - 0) + 1) * sizeof(WCHAR); - } - else if (OutputType == Utf8String) - { - /* FIXME */ - OutputSize = 0; - } - } - else if (InputType == Utf8String) - { - /* FIXME */ - OutputSize = 0; - } - - /* Return the size required */ - return OutputSize; -} - diff --git a/lib/dnslib/table.c b/lib/dnslib/table.c deleted file mode 100644 index 266c81b7296..00000000000 --- a/lib/dnslib/table.c +++ /dev/null @@ -1,14 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/table.c - * PURPOSE: Functions for doing Table lookups, such as LUP Flags. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - diff --git a/lib/dnslib/utf8.c b/lib/dnslib/utf8.c deleted file mode 100644 index 1cb6aa8bd59..00000000000 --- a/lib/dnslib/utf8.c +++ /dev/null @@ -1,14 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/utf8.c - * PURPOSE: Functions for doing UTF8 string conversion and manipulation. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - diff --git a/lib/lib.rbuild b/lib/lib.rbuild index 98b2380a67a..67fc9077ee7 100644 --- a/lib/lib.rbuild +++ b/lib/lib.rbuild @@ -16,9 +16,6 @@ - - - From 9b6310f09a9a4deaf610f85228b6f0d797e0cc36 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sat, 6 Feb 2010 03:10:25 +0000 Subject: [PATCH 16/24] - Forgot this file svn path=/branches/aicom-network-branch/; revision=45454 --- dll/win32/win32.rbuild | 3 --- 1 file changed, 3 deletions(-) diff --git a/dll/win32/win32.rbuild b/dll/win32/win32.rbuild index c68742612de..b1edbd85318 100644 --- a/dll/win32/win32.rbuild +++ b/dll/win32/win32.rbuild @@ -625,9 +625,6 @@ - - - From f57e5b6562d0a64da379809863ed464147398f86 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sat, 6 Feb 2010 14:24:55 +0000 Subject: [PATCH 17/24] - Build fixes - For some reason when I applied the patch from my other WC to this one, I ended up with 2-3 copies of the same code in each file svn path=/branches/aicom-network-branch/; revision=45460 --- dll/win32/dnsapi/dnsapi/memory.c | 64 - dll/win32/mswsock/dns/addr.c | 195 -- dll/win32/mswsock/dns/debug.c | 42 - dll/win32/mswsock/dns/dnsaddr.c | 600 ----- dll/win32/mswsock/dns/dnsutil.c | 42 - dll/win32/mswsock/dns/flatbuf.c | 348 --- dll/win32/mswsock/dns/hostent.c | 291 --- dll/win32/mswsock/dns/inc/dnslib.h | 421 +++- dll/win32/mswsock/dns/inc/dnslibp.h | 2058 --------------- dll/win32/mswsock/dns/inc/windnsp.h | 140 -- dll/win32/mswsock/dns/ip6.c | 42 - dll/win32/mswsock/dns/memory.c | 198 -- dll/win32/mswsock/dns/name.c | 42 - dll/win32/mswsock/dns/print.c | 42 - dll/win32/mswsock/dns/record.c | 42 - dll/win32/mswsock/dns/rrprint.c | 42 - dll/win32/mswsock/dns/sablob.c | 1935 -------------- dll/win32/mswsock/dns/straddr.c | 1386 ---------- dll/win32/mswsock/dns/string.c | 771 ------ dll/win32/mswsock/dns/table.c | 42 - dll/win32/mswsock/dns/utf8.c | 42 - dll/win32/mswsock/msafd/accept.c | 2925 ---------------------- dll/win32/mswsock/msafd/addrconv.c | 114 - dll/win32/mswsock/msafd/afdsan.c | 42 - dll/win32/mswsock/msafd/async.c | 594 ----- dll/win32/mswsock/msafd/bind.c | 639 ----- dll/win32/mswsock/msafd/connect.c | 2034 --------------- dll/win32/mswsock/msafd/eventsel.c | 1281 ---------- dll/win32/mswsock/msafd/getname.c | 735 ------ dll/win32/mswsock/msafd/helper.c | 2085 ---------------- dll/win32/mswsock/msafd/listen.c | 423 ---- dll/win32/mswsock/msafd/nspeprot.c | 246 -- dll/win32/mswsock/msafd/proc.c | 3474 -------------------------- dll/win32/mswsock/msafd/recv.c | 1686 ------------- dll/win32/mswsock/msafd/sanaccpt.c | 42 - dll/win32/mswsock/msafd/sanconn.c | 42 - dll/win32/mswsock/msafd/sanflow.c | 42 - dll/win32/mswsock/msafd/sanlistn.c | 42 - dll/win32/mswsock/msafd/sanprov.c | 180 -- dll/win32/mswsock/msafd/sanrdma.c | 42 - dll/win32/mswsock/msafd/sanrecv.c | 42 - dll/win32/mswsock/msafd/sansend.c | 42 - dll/win32/mswsock/msafd/sanshutd.c | 42 - dll/win32/mswsock/msafd/sansock.c | 42 - dll/win32/mswsock/msafd/santf.c | 42 - dll/win32/mswsock/msafd/sanutil.c | 42 - dll/win32/mswsock/msafd/select.c | 2964 ---------------------- dll/win32/mswsock/msafd/send.c | 1755 ------------- dll/win32/mswsock/msafd/shutdown.c | 522 ---- dll/win32/mswsock/msafd/sockerr.c | 414 --- dll/win32/mswsock/msafd/socket.c | 2397 ------------------ dll/win32/mswsock/msafd/sockopt.c | 1767 ------------- dll/win32/mswsock/msafd/spi.c | 663 ----- dll/win32/mswsock/msafd/tpackets.c | 42 - dll/win32/mswsock/msafd/tranfile.c | 42 - dll/win32/mswsock/msafd/wspmisc.c | 264 -- dll/win32/mswsock/mswsock.rbuild | 2 +- dll/win32/mswsock/mswsock/init.c | 612 ----- dll/win32/mswsock/mswsock/msext.c | 156 -- dll/win32/mswsock/mswsock/nspgaddr.c | 42 - dll/win32/mswsock/mswsock/nspmisc.c | 42 - dll/win32/mswsock/mswsock/nspsvc.c | 42 - dll/win32/mswsock/mswsock/nsptcpip.c | 42 - dll/win32/mswsock/mswsock/nsputil.c | 42 - dll/win32/mswsock/mswsock/proc.c | 342 --- dll/win32/mswsock/mswsock/recvex.c | 42 - dll/win32/mswsock/mswsock/setup.c | 42 - dll/win32/mswsock/mswsock/stubs.c | 1041 -------- dll/win32/mswsock/rnr20/context.c | 486 ---- dll/win32/mswsock/rnr20/getserv.c | 30 - dll/win32/mswsock/rnr20/init.c | 267 -- dll/win32/mswsock/rnr20/logit.c | 30 - dll/win32/mswsock/rnr20/lookup.c | 1077 -------- dll/win32/mswsock/rnr20/nbt.c | 42 - dll/win32/mswsock/rnr20/nsp.c | 2832 --------------------- dll/win32/mswsock/rnr20/oldutil.c | 663 ----- dll/win32/mswsock/rnr20/proc.c | 132 - dll/win32/mswsock/rnr20/r_comp.c | 30 - dll/win32/mswsock/rnr20/util.c | 96 - dll/win32/mswsock/wsmobile/lpc.c | 48 - dll/win32/mswsock/wsmobile/nsp.c | 84 - dll/win32/mswsock/wsmobile/service.c | 42 - dll/win32/mswsock/wsmobile/update.c | 42 - include/reactos/winsock/msafd.h | 52 - include/reactos/winsock/msafdlib.h | 828 ------ include/reactos/winsock/mswinsock.h | 19 - include/reactos/winsock/rnr20lib.h | 265 -- include/reactos/winsock/wsmobile.h | 84 - 88 files changed, 311 insertions(+), 45820 deletions(-) delete mode 100644 dll/win32/mswsock/dns/inc/dnslibp.h diff --git a/dll/win32/dnsapi/dnsapi/memory.c b/dll/win32/dnsapi/dnsapi/memory.c index 6be36d3ad97..18c957c794c 100644 --- a/dll/win32/dnsapi/dnsapi/memory.c +++ b/dll/win32/dnsapi/dnsapi/memory.c @@ -62,67 +62,3 @@ DnsRecordListFree(PDNS_RECORD Data, { DnsFree(Data, FreeType); } -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS system libraries - * FILE: lib/dnsapi/dnsapi/free.c - * PURPOSE: DNSAPI functions built on the ADNS library. - * PROGRAMER: Art Yerkes - * UPDATE HISTORY: - * 12/15/03 -- Created - */ - -#include "precomp.h" - -#define NDEBUG -#include - -VOID -WINAPI -DnsApiFree(IN PVOID Data) -{ - RtlFreeHeap(RtlGetProcessHeap(), 0, Data); -} - -PVOID -WINAPI -DnsApiAlloc(IN DWORD Size) -{ - return RtlAllocateHeap(RtlGetProcessHeap(), 0, Size); -} - -PVOID -WINAPI -DnsQueryConfigAllocEx(IN DNS_CONFIG_TYPE Config, - OUT PVOID pBuffer, - IN OUT PDWORD pBufferLength) -{ - return NULL; -} - -VOID WINAPI -DnsFree(PVOID Data, - DNS_FREE_TYPE FreeType) -{ - switch(FreeType) - { - case DnsFreeFlat: - RtlFreeHeap( RtlGetProcessHeap(), 0, Data ); - break; - - case DnsFreeRecordList: - DnsIntFreeRecordList( (PDNS_RECORD)Data ); - break; - - case DnsFreeParsedMessageFields: - /* assert( FALSE ); XXX arty not yet implemented. */ - break; - } -} - -VOID WINAPI -DnsRecordListFree(PDNS_RECORD Data, - DNS_FREE_TYPE FreeType) -{ - DnsFree(Data, FreeType); -} diff --git a/dll/win32/mswsock/dns/addr.c b/dll/win32/mswsock/dns/addr.c index 8742b3050cd..b91c532e49a 100644 --- a/dll/win32/mswsock/dns/addr.c +++ b/dll/win32/mswsock/dns/addr.c @@ -63,198 +63,3 @@ FamilyInfo_GetForFamily(IN WORD AddressFamily) } -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/addr.c - * PURPOSE: Contains the Address Family Information Tables - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -DNS_FAMILY_INFO AddrFamilyTable[3] = -{ - { - AF_INET, - DNS_TYPE_A, - sizeof(IP4_ADDRESS), - sizeof(SOCKADDR_IN), - FIELD_OFFSET(SOCKADDR_IN, sin_addr) - }, - { - AF_INET6, - DNS_TYPE_AAAA, - sizeof(IP6_ADDRESS), - sizeof(SOCKADDR_IN6), - FIELD_OFFSET(SOCKADDR_IN6, sin6_addr) - }, - { - AF_ATM, - DNS_TYPE_ATMA, - sizeof(ATM_ADDRESS), - sizeof(SOCKADDR_ATM), - FIELD_OFFSET(SOCKADDR_ATM, satm_number) - } -}; - -/* FUNCTIONS *****************************************************************/ - -PDNS_FAMILY_INFO -WINAPI -FamilyInfo_GetForFamily(IN WORD AddressFamily) -{ - /* Check which family this is */ - switch (AddressFamily) - { - case AF_INET: - /* Return IPv4 Family Info */ - return &AddrFamilyTable[0]; - - case AF_INET6: - /* Return IPv6 Family Info */ - return &AddrFamilyTable[1]; - - case AF_ATM: - /* Return ATM Family Info */ - return &AddrFamilyTable[2]; - - default: - /* Invalid family */ - return NULL; - } - -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/addr.c - * PURPOSE: Contains the Address Family Information Tables - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -DNS_FAMILY_INFO AddrFamilyTable[3] = -{ - { - AF_INET, - DNS_TYPE_A, - sizeof(IP4_ADDRESS), - sizeof(SOCKADDR_IN), - FIELD_OFFSET(SOCKADDR_IN, sin_addr) - }, - { - AF_INET6, - DNS_TYPE_AAAA, - sizeof(IP6_ADDRESS), - sizeof(SOCKADDR_IN6), - FIELD_OFFSET(SOCKADDR_IN6, sin6_addr) - }, - { - AF_ATM, - DNS_TYPE_ATMA, - sizeof(ATM_ADDRESS), - sizeof(SOCKADDR_ATM), - FIELD_OFFSET(SOCKADDR_ATM, satm_number) - } -}; - -/* FUNCTIONS *****************************************************************/ - -PDNS_FAMILY_INFO -WINAPI -FamilyInfo_GetForFamily(IN WORD AddressFamily) -{ - /* Check which family this is */ - switch (AddressFamily) - { - case AF_INET: - /* Return IPv4 Family Info */ - return &AddrFamilyTable[0]; - - case AF_INET6: - /* Return IPv6 Family Info */ - return &AddrFamilyTable[1]; - - case AF_ATM: - /* Return ATM Family Info */ - return &AddrFamilyTable[2]; - - default: - /* Invalid family */ - return NULL; - } - -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/addr.c - * PURPOSE: Contains the Address Family Information Tables - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -DNS_FAMILY_INFO AddrFamilyTable[3] = -{ - { - AF_INET, - DNS_TYPE_A, - sizeof(IP4_ADDRESS), - sizeof(SOCKADDR_IN), - FIELD_OFFSET(SOCKADDR_IN, sin_addr) - }, - { - AF_INET6, - DNS_TYPE_AAAA, - sizeof(IP6_ADDRESS), - sizeof(SOCKADDR_IN6), - FIELD_OFFSET(SOCKADDR_IN6, sin6_addr) - }, - { - AF_ATM, - DNS_TYPE_ATMA, - sizeof(ATM_ADDRESS), - sizeof(SOCKADDR_ATM), - FIELD_OFFSET(SOCKADDR_ATM, satm_number) - } -}; - -/* FUNCTIONS *****************************************************************/ - -PDNS_FAMILY_INFO -WINAPI -FamilyInfo_GetForFamily(IN WORD AddressFamily) -{ - /* Check which family this is */ - switch (AddressFamily) - { - case AF_INET: - /* Return IPv4 Family Info */ - return &AddrFamilyTable[0]; - - case AF_INET6: - /* Return IPv6 Family Info */ - return &AddrFamilyTable[1]; - - case AF_ATM: - /* Return ATM Family Info */ - return &AddrFamilyTable[2]; - - default: - /* Invalid family */ - return NULL; - } - -} - diff --git a/dll/win32/mswsock/dns/debug.c b/dll/win32/mswsock/dns/debug.c index f194e1e9632..7ec359759b5 100644 --- a/dll/win32/mswsock/dns/debug.c +++ b/dll/win32/mswsock/dns/debug.c @@ -12,45 +12,3 @@ /* FUNCTIONS *****************************************************************/ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/debug.c - * PURPOSE: Contains helpful debugging functions for DNSLIB structures. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/debug.c - * PURPOSE: Contains helpful debugging functions for DNSLIB structures. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/debug.c - * PURPOSE: Contains helpful debugging functions for DNSLIB structures. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - diff --git a/dll/win32/mswsock/dns/dnsaddr.c b/dll/win32/mswsock/dns/dnsaddr.c index 20ebe48b28f..310a0966f8b 100644 --- a/dll/win32/mswsock/dns/dnsaddr.c +++ b/dll/win32/mswsock/dns/dnsaddr.c @@ -198,603 +198,3 @@ DnsAddrArray_ContainsAddr(IN PDNS_ARRAY DnsAddrArray, return TRUE; } -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/dnsaddr.c - * PURPOSE: Functions dealing with DNS_ADDRESS and DNS_ARRAY addresses. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -PDNS_ARRAY -WINAPI -DnsAddrArray_Create(ULONG Count) -{ - PDNS_ARRAY DnsAddrArray; - - /* Allocate space for the array and the addresses within it */ - DnsAddrArray = Dns_AllocZero(sizeof(DNS_ARRAY) + - (Count * sizeof(DNS_ADDRESS))); - - /* Write the allocated address count */ - if (DnsAddrArray) DnsAddrArray->AllocatedAddresses = Count; - - /* Return it */ - return DnsAddrArray; -} - -VOID -WINAPI -DnsAddrArray_Free(IN PDNS_ARRAY DnsAddrArray) -{ - /* Just free the entire array */ - Dns_Free(DnsAddrArray); -} - -BOOL -WINAPI -DnsAddrArray_AddIp4(IN PDNS_ARRAY DnsAddrArray, - IN IN_ADDR Address, - IN DWORD AddressType) -{ - DNS_ADDRESS DnsAddress; - - /* Build the DNS Address */ - DnsAddr_BuildFromIp4(&DnsAddress, Address, 0); - - /* Add it to the array */ - return DnsAddrArray_AddAddr(DnsAddrArray, &DnsAddress, 0, AddressType); -} - -BOOL -WINAPI -DnsAddrArray_AddAddr(IN PDNS_ARRAY DnsAddrArray, - IN PDNS_ADDRESS DnsAddress, - IN WORD AddressFamily OPTIONAL, - IN DWORD AddressType OPTIONAL) -{ - /* Make sure we have an array */ - if (!DnsAddrArray) return FALSE; - - /* Check if we should validate the Address Family */ - if (AddressFamily) - { - /* Validate it */ - if (AddressFamily != DnsAddress->AddressFamily) return TRUE; - } - - /* Check if we should validate the Address Type */ - if (AddressType) - { - /* Make sure that this array contains this type of addresses */ - if (!DnsAddrArray_ContainsAddr(DnsAddrArray, DnsAddress, AddressType)) - { - /* Won't be adding it */ - return TRUE; - } - } - - /* Make sure we have space in the array */ - if (DnsAddrArray->AllocatedAddresses < DnsAddrArray->UsedAddresses) - { - return FALSE; - } - - /* Now add the address */ - RtlCopyMemory(&DnsAddrArray->Addresses[DnsAddrArray->UsedAddresses], - DnsAddress, - sizeof(DNS_ADDRESS)); - - /* Return success */ - return TRUE; -} - -VOID -WINAPI -DnsAddr_BuildFromIp4(IN PDNS_ADDRESS DnsAddress, - IN IN_ADDR Address, - IN WORD Port) -{ - /* Clear the address */ - RtlZeroMemory(DnsAddress, sizeof(DNS_ADDRESS)); - - /* Write data */ - DnsAddress->Ip4Address.sin_family = AF_INET; - DnsAddress->Ip4Address.sin_port = Port; - DnsAddress->Ip4Address.sin_addr = Address; - DnsAddress->AddressLength = sizeof(SOCKADDR_IN); -} - -VOID -WINAPI -DnsAddr_BuildFromIp6(IN PDNS_ADDRESS DnsAddress, - IN PIN6_ADDR Address, - IN ULONG ScopeId, - IN WORD Port) -{ - /* Clear the address */ - RtlZeroMemory(DnsAddress, sizeof(DNS_ADDRESS)); - - /* Write data */ - DnsAddress->Ip6Address.sin6_family = AF_INET6; - DnsAddress->Ip6Address.sin6_port = Port; - DnsAddress->Ip6Address.sin6_addr = *Address; - DnsAddress->Ip6Address.sin6_scope_id = ScopeId; - DnsAddress->AddressLength = sizeof(SOCKADDR_IN6); -} - -VOID -WINAPI -DnsAddr_BuildFromAtm(IN PDNS_ADDRESS DnsAddress, - IN DWORD AddressType, - IN PVOID AddressData) -{ - ATM_ADDRESS Address; - - /* Clear the address */ - RtlZeroMemory(DnsAddress, sizeof(DNS_ADDRESS)); - - /* Build an ATM Address */ - Address.AddressType = AddressType; - Address.NumofDigits = DNS_ATMA_MAX_ADDR_LENGTH; - RtlCopyMemory(&Address.Addr, AddressData, DNS_ATMA_MAX_ADDR_LENGTH); - - /* Write data */ - DnsAddress->AtmAddress = Address; - DnsAddress->AddressLength = sizeof(ATM_ADDRESS); -} - -BOOLEAN -WINAPI -DnsAddr_BuildFromDnsRecord(IN PDNS_RECORD DnsRecord, - OUT PDNS_ADDRESS DnsAddr) -{ - /* Check what kind of record this is */ - switch(DnsRecord->wType) - { - /* IPv4 */ - case DNS_TYPE_A: - /* Create the DNS Address */ - DnsAddr_BuildFromIp4(DnsAddr, - *(PIN_ADDR)&DnsRecord->Data.A.IpAddress, - 0); - break; - - /* IPv6 */ - case DNS_TYPE_AAAA: - /* Create the DNS Address */ - DnsAddr_BuildFromIp6(DnsAddr, - (PIN6_ADDR)&DnsRecord->Data.AAAA.Ip6Address, - DnsRecord->dwReserved, - 0); - break; - - /* ATM */ - case DNS_TYPE_ATMA: - /* Create the DNS Address */ - DnsAddr_BuildFromAtm(DnsAddr, - DnsRecord->Data.Atma.AddressType, - &DnsRecord->Data.Atma.Address); - break; - } - - /* Done! */ - return TRUE; -} - -BOOL -WINAPI -DnsAddrArray_ContainsAddr(IN PDNS_ARRAY DnsAddrArray, - IN PDNS_ADDRESS DnsAddress, - IN DWORD AddressType) -{ - /* FIXME */ - return TRUE; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/dnsaddr.c - * PURPOSE: Functions dealing with DNS_ADDRESS and DNS_ARRAY addresses. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -PDNS_ARRAY -WINAPI -DnsAddrArray_Create(ULONG Count) -{ - PDNS_ARRAY DnsAddrArray; - - /* Allocate space for the array and the addresses within it */ - DnsAddrArray = Dns_AllocZero(sizeof(DNS_ARRAY) + - (Count * sizeof(DNS_ADDRESS))); - - /* Write the allocated address count */ - if (DnsAddrArray) DnsAddrArray->AllocatedAddresses = Count; - - /* Return it */ - return DnsAddrArray; -} - -VOID -WINAPI -DnsAddrArray_Free(IN PDNS_ARRAY DnsAddrArray) -{ - /* Just free the entire array */ - Dns_Free(DnsAddrArray); -} - -BOOL -WINAPI -DnsAddrArray_AddIp4(IN PDNS_ARRAY DnsAddrArray, - IN IN_ADDR Address, - IN DWORD AddressType) -{ - DNS_ADDRESS DnsAddress; - - /* Build the DNS Address */ - DnsAddr_BuildFromIp4(&DnsAddress, Address, 0); - - /* Add it to the array */ - return DnsAddrArray_AddAddr(DnsAddrArray, &DnsAddress, 0, AddressType); -} - -BOOL -WINAPI -DnsAddrArray_AddAddr(IN PDNS_ARRAY DnsAddrArray, - IN PDNS_ADDRESS DnsAddress, - IN WORD AddressFamily OPTIONAL, - IN DWORD AddressType OPTIONAL) -{ - /* Make sure we have an array */ - if (!DnsAddrArray) return FALSE; - - /* Check if we should validate the Address Family */ - if (AddressFamily) - { - /* Validate it */ - if (AddressFamily != DnsAddress->AddressFamily) return TRUE; - } - - /* Check if we should validate the Address Type */ - if (AddressType) - { - /* Make sure that this array contains this type of addresses */ - if (!DnsAddrArray_ContainsAddr(DnsAddrArray, DnsAddress, AddressType)) - { - /* Won't be adding it */ - return TRUE; - } - } - - /* Make sure we have space in the array */ - if (DnsAddrArray->AllocatedAddresses < DnsAddrArray->UsedAddresses) - { - return FALSE; - } - - /* Now add the address */ - RtlCopyMemory(&DnsAddrArray->Addresses[DnsAddrArray->UsedAddresses], - DnsAddress, - sizeof(DNS_ADDRESS)); - - /* Return success */ - return TRUE; -} - -VOID -WINAPI -DnsAddr_BuildFromIp4(IN PDNS_ADDRESS DnsAddress, - IN IN_ADDR Address, - IN WORD Port) -{ - /* Clear the address */ - RtlZeroMemory(DnsAddress, sizeof(DNS_ADDRESS)); - - /* Write data */ - DnsAddress->Ip4Address.sin_family = AF_INET; - DnsAddress->Ip4Address.sin_port = Port; - DnsAddress->Ip4Address.sin_addr = Address; - DnsAddress->AddressLength = sizeof(SOCKADDR_IN); -} - -VOID -WINAPI -DnsAddr_BuildFromIp6(IN PDNS_ADDRESS DnsAddress, - IN PIN6_ADDR Address, - IN ULONG ScopeId, - IN WORD Port) -{ - /* Clear the address */ - RtlZeroMemory(DnsAddress, sizeof(DNS_ADDRESS)); - - /* Write data */ - DnsAddress->Ip6Address.sin6_family = AF_INET6; - DnsAddress->Ip6Address.sin6_port = Port; - DnsAddress->Ip6Address.sin6_addr = *Address; - DnsAddress->Ip6Address.sin6_scope_id = ScopeId; - DnsAddress->AddressLength = sizeof(SOCKADDR_IN6); -} - -VOID -WINAPI -DnsAddr_BuildFromAtm(IN PDNS_ADDRESS DnsAddress, - IN DWORD AddressType, - IN PVOID AddressData) -{ - ATM_ADDRESS Address; - - /* Clear the address */ - RtlZeroMemory(DnsAddress, sizeof(DNS_ADDRESS)); - - /* Build an ATM Address */ - Address.AddressType = AddressType; - Address.NumofDigits = DNS_ATMA_MAX_ADDR_LENGTH; - RtlCopyMemory(&Address.Addr, AddressData, DNS_ATMA_MAX_ADDR_LENGTH); - - /* Write data */ - DnsAddress->AtmAddress = Address; - DnsAddress->AddressLength = sizeof(ATM_ADDRESS); -} - -BOOLEAN -WINAPI -DnsAddr_BuildFromDnsRecord(IN PDNS_RECORD DnsRecord, - OUT PDNS_ADDRESS DnsAddr) -{ - /* Check what kind of record this is */ - switch(DnsRecord->wType) - { - /* IPv4 */ - case DNS_TYPE_A: - /* Create the DNS Address */ - DnsAddr_BuildFromIp4(DnsAddr, - *(PIN_ADDR)&DnsRecord->Data.A.IpAddress, - 0); - break; - - /* IPv6 */ - case DNS_TYPE_AAAA: - /* Create the DNS Address */ - DnsAddr_BuildFromIp6(DnsAddr, - (PIN6_ADDR)&DnsRecord->Data.AAAA.Ip6Address, - DnsRecord->dwReserved, - 0); - break; - - /* ATM */ - case DNS_TYPE_ATMA: - /* Create the DNS Address */ - DnsAddr_BuildFromAtm(DnsAddr, - DnsRecord->Data.Atma.AddressType, - &DnsRecord->Data.Atma.Address); - break; - } - - /* Done! */ - return TRUE; -} - -BOOL -WINAPI -DnsAddrArray_ContainsAddr(IN PDNS_ARRAY DnsAddrArray, - IN PDNS_ADDRESS DnsAddress, - IN DWORD AddressType) -{ - /* FIXME */ - return TRUE; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/dnsaddr.c - * PURPOSE: Functions dealing with DNS_ADDRESS and DNS_ARRAY addresses. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -PDNS_ARRAY -WINAPI -DnsAddrArray_Create(ULONG Count) -{ - PDNS_ARRAY DnsAddrArray; - - /* Allocate space for the array and the addresses within it */ - DnsAddrArray = Dns_AllocZero(sizeof(DNS_ARRAY) + - (Count * sizeof(DNS_ADDRESS))); - - /* Write the allocated address count */ - if (DnsAddrArray) DnsAddrArray->AllocatedAddresses = Count; - - /* Return it */ - return DnsAddrArray; -} - -VOID -WINAPI -DnsAddrArray_Free(IN PDNS_ARRAY DnsAddrArray) -{ - /* Just free the entire array */ - Dns_Free(DnsAddrArray); -} - -BOOL -WINAPI -DnsAddrArray_AddIp4(IN PDNS_ARRAY DnsAddrArray, - IN IN_ADDR Address, - IN DWORD AddressType) -{ - DNS_ADDRESS DnsAddress; - - /* Build the DNS Address */ - DnsAddr_BuildFromIp4(&DnsAddress, Address, 0); - - /* Add it to the array */ - return DnsAddrArray_AddAddr(DnsAddrArray, &DnsAddress, 0, AddressType); -} - -BOOL -WINAPI -DnsAddrArray_AddAddr(IN PDNS_ARRAY DnsAddrArray, - IN PDNS_ADDRESS DnsAddress, - IN WORD AddressFamily OPTIONAL, - IN DWORD AddressType OPTIONAL) -{ - /* Make sure we have an array */ - if (!DnsAddrArray) return FALSE; - - /* Check if we should validate the Address Family */ - if (AddressFamily) - { - /* Validate it */ - if (AddressFamily != DnsAddress->AddressFamily) return TRUE; - } - - /* Check if we should validate the Address Type */ - if (AddressType) - { - /* Make sure that this array contains this type of addresses */ - if (!DnsAddrArray_ContainsAddr(DnsAddrArray, DnsAddress, AddressType)) - { - /* Won't be adding it */ - return TRUE; - } - } - - /* Make sure we have space in the array */ - if (DnsAddrArray->AllocatedAddresses < DnsAddrArray->UsedAddresses) - { - return FALSE; - } - - /* Now add the address */ - RtlCopyMemory(&DnsAddrArray->Addresses[DnsAddrArray->UsedAddresses], - DnsAddress, - sizeof(DNS_ADDRESS)); - - /* Return success */ - return TRUE; -} - -VOID -WINAPI -DnsAddr_BuildFromIp4(IN PDNS_ADDRESS DnsAddress, - IN IN_ADDR Address, - IN WORD Port) -{ - /* Clear the address */ - RtlZeroMemory(DnsAddress, sizeof(DNS_ADDRESS)); - - /* Write data */ - DnsAddress->Ip4Address.sin_family = AF_INET; - DnsAddress->Ip4Address.sin_port = Port; - DnsAddress->Ip4Address.sin_addr = Address; - DnsAddress->AddressLength = sizeof(SOCKADDR_IN); -} - -VOID -WINAPI -DnsAddr_BuildFromIp6(IN PDNS_ADDRESS DnsAddress, - IN PIN6_ADDR Address, - IN ULONG ScopeId, - IN WORD Port) -{ - /* Clear the address */ - RtlZeroMemory(DnsAddress, sizeof(DNS_ADDRESS)); - - /* Write data */ - DnsAddress->Ip6Address.sin6_family = AF_INET6; - DnsAddress->Ip6Address.sin6_port = Port; - DnsAddress->Ip6Address.sin6_addr = *Address; - DnsAddress->Ip6Address.sin6_scope_id = ScopeId; - DnsAddress->AddressLength = sizeof(SOCKADDR_IN6); -} - -VOID -WINAPI -DnsAddr_BuildFromAtm(IN PDNS_ADDRESS DnsAddress, - IN DWORD AddressType, - IN PVOID AddressData) -{ - ATM_ADDRESS Address; - - /* Clear the address */ - RtlZeroMemory(DnsAddress, sizeof(DNS_ADDRESS)); - - /* Build an ATM Address */ - Address.AddressType = AddressType; - Address.NumofDigits = DNS_ATMA_MAX_ADDR_LENGTH; - RtlCopyMemory(&Address.Addr, AddressData, DNS_ATMA_MAX_ADDR_LENGTH); - - /* Write data */ - DnsAddress->AtmAddress = Address; - DnsAddress->AddressLength = sizeof(ATM_ADDRESS); -} - -BOOLEAN -WINAPI -DnsAddr_BuildFromDnsRecord(IN PDNS_RECORD DnsRecord, - OUT PDNS_ADDRESS DnsAddr) -{ - /* Check what kind of record this is */ - switch(DnsRecord->wType) - { - /* IPv4 */ - case DNS_TYPE_A: - /* Create the DNS Address */ - DnsAddr_BuildFromIp4(DnsAddr, - *(PIN_ADDR)&DnsRecord->Data.A.IpAddress, - 0); - break; - - /* IPv6 */ - case DNS_TYPE_AAAA: - /* Create the DNS Address */ - DnsAddr_BuildFromIp6(DnsAddr, - (PIN6_ADDR)&DnsRecord->Data.AAAA.Ip6Address, - DnsRecord->dwReserved, - 0); - break; - - /* ATM */ - case DNS_TYPE_ATMA: - /* Create the DNS Address */ - DnsAddr_BuildFromAtm(DnsAddr, - DnsRecord->Data.Atma.AddressType, - &DnsRecord->Data.Atma.Address); - break; - } - - /* Done! */ - return TRUE; -} - -BOOL -WINAPI -DnsAddrArray_ContainsAddr(IN PDNS_ARRAY DnsAddrArray, - IN PDNS_ADDRESS DnsAddress, - IN DWORD AddressType) -{ - /* FIXME */ - return TRUE; -} - diff --git a/dll/win32/mswsock/dns/dnsutil.c b/dll/win32/mswsock/dns/dnsutil.c index 0830457b586..1d0e814d911 100644 --- a/dll/win32/mswsock/dns/dnsutil.c +++ b/dll/win32/mswsock/dns/dnsutil.c @@ -12,45 +12,3 @@ /* FUNCTIONS *****************************************************************/ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/dnsutil.c - * PURPOSE: Contains misc. DNS utility functions, like DNS_STATUS->String. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/dnsutil.c - * PURPOSE: Contains misc. DNS utility functions, like DNS_STATUS->String. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/dnsutil.c - * PURPOSE: Contains misc. DNS utility functions, like DNS_STATUS->String. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - diff --git a/dll/win32/mswsock/dns/flatbuf.c b/dll/win32/mswsock/dns/flatbuf.c index 6d33b21f71e..dfceb3e82a3 100644 --- a/dll/win32/mswsock/dns/flatbuf.c +++ b/dll/win32/mswsock/dns/flatbuf.c @@ -114,351 +114,3 @@ FlatBuf_Arg_WriteString(IN OUT PULONG_PTR Position, return Destination; } -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/flatbuf.c - * PURPOSE: Functions for managing the Flat Buffer Implementation (FLATBUF) - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -VOID -WINAPI -FlatBuf_Init(IN PFLATBUFF FlatBuffer, - IN PVOID Buffer, - IN SIZE_T Size) -{ - /* Set up the Flat Buffer start, current and ending position */ - FlatBuffer->Buffer = Buffer; - FlatBuffer->BufferPos = (ULONG_PTR)Buffer; - FlatBuffer->BufferEnd = (PVOID)(FlatBuffer->BufferPos + Size); - - /* Setup the current size and the available size */ - FlatBuffer->BufferSize = FlatBuffer->BufferFreeSize = Size; -} - -PVOID -WINAPI -FlatBuf_Arg_Reserve(IN OUT PULONG_PTR Position, - IN OUT PSIZE_T FreeSize, - IN SIZE_T Size, - IN ULONG Align) -{ - ULONG_PTR NewPosition, OldPosition = *Position; - SIZE_T NewFreeSize = *FreeSize; - - /* Start by aligning our position */ - if (Align) OldPosition += (Align - 1) & ~Align; - - /* Update it */ - NewPosition = OldPosition + Size; - - /* Update Free Size */ - NewFreeSize += (OldPosition - NewPosition); - - /* Save new values */ - *Position = NewPosition; - *FreeSize = NewFreeSize; - - /* Check if we're out of space or not */ - if (NewFreeSize > 0) return (PVOID)OldPosition; - return NULL; -} - -PVOID -WINAPI -FlatBuf_Arg_CopyMemory(IN OUT PULONG_PTR Position, - IN OUT PSIZE_T FreeSize, - IN PVOID Buffer, - IN SIZE_T Size, - IN ULONG Align) -{ - PVOID Destination; - - /* First reserve the memory */ - Destination = FlatBuf_Arg_Reserve(Position, FreeSize, Size, Align); - if (Destination) - { - /* We have space, do the copy */ - RtlCopyMemory(Destination, Buffer, Size); - } - - /* Return the pointer to the data */ - return Destination; -} - -PVOID -WINAPI -FlatBuf_Arg_WriteString(IN OUT PULONG_PTR Position, - IN OUT PSIZE_T FreeSize, - IN PVOID String, - IN BOOLEAN IsUnicode) -{ - PVOID Destination; - SIZE_T StringLength; - ULONG Align; - - /* Calculate the string length */ - if (IsUnicode) - { - /* Get the length in bytes and use WCHAR alignment */ - StringLength = (wcslen((LPWSTR)String) + 1) * sizeof(WCHAR); - Align = sizeof(WCHAR); - } - else - { - /* Get the length in bytes and use CHAR alignment */ - StringLength = strlen((LPSTR)String) + 1; - Align = sizeof(CHAR); - } - - /* Now reserve the memory */ - Destination = FlatBuf_Arg_Reserve(Position, FreeSize, StringLength, Align); - if (Destination) - { - /* We have space, do the copy */ - RtlCopyMemory(Destination, String, StringLength); - } - - /* Return the pointer to the data */ - return Destination; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/flatbuf.c - * PURPOSE: Functions for managing the Flat Buffer Implementation (FLATBUF) - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -VOID -WINAPI -FlatBuf_Init(IN PFLATBUFF FlatBuffer, - IN PVOID Buffer, - IN SIZE_T Size) -{ - /* Set up the Flat Buffer start, current and ending position */ - FlatBuffer->Buffer = Buffer; - FlatBuffer->BufferPos = (ULONG_PTR)Buffer; - FlatBuffer->BufferEnd = (PVOID)(FlatBuffer->BufferPos + Size); - - /* Setup the current size and the available size */ - FlatBuffer->BufferSize = FlatBuffer->BufferFreeSize = Size; -} - -PVOID -WINAPI -FlatBuf_Arg_Reserve(IN OUT PULONG_PTR Position, - IN OUT PSIZE_T FreeSize, - IN SIZE_T Size, - IN ULONG Align) -{ - ULONG_PTR NewPosition, OldPosition = *Position; - SIZE_T NewFreeSize = *FreeSize; - - /* Start by aligning our position */ - if (Align) OldPosition += (Align - 1) & ~Align; - - /* Update it */ - NewPosition = OldPosition + Size; - - /* Update Free Size */ - NewFreeSize += (OldPosition - NewPosition); - - /* Save new values */ - *Position = NewPosition; - *FreeSize = NewFreeSize; - - /* Check if we're out of space or not */ - if (NewFreeSize > 0) return (PVOID)OldPosition; - return NULL; -} - -PVOID -WINAPI -FlatBuf_Arg_CopyMemory(IN OUT PULONG_PTR Position, - IN OUT PSIZE_T FreeSize, - IN PVOID Buffer, - IN SIZE_T Size, - IN ULONG Align) -{ - PVOID Destination; - - /* First reserve the memory */ - Destination = FlatBuf_Arg_Reserve(Position, FreeSize, Size, Align); - if (Destination) - { - /* We have space, do the copy */ - RtlCopyMemory(Destination, Buffer, Size); - } - - /* Return the pointer to the data */ - return Destination; -} - -PVOID -WINAPI -FlatBuf_Arg_WriteString(IN OUT PULONG_PTR Position, - IN OUT PSIZE_T FreeSize, - IN PVOID String, - IN BOOLEAN IsUnicode) -{ - PVOID Destination; - SIZE_T StringLength; - ULONG Align; - - /* Calculate the string length */ - if (IsUnicode) - { - /* Get the length in bytes and use WCHAR alignment */ - StringLength = (wcslen((LPWSTR)String) + 1) * sizeof(WCHAR); - Align = sizeof(WCHAR); - } - else - { - /* Get the length in bytes and use CHAR alignment */ - StringLength = strlen((LPSTR)String) + 1; - Align = sizeof(CHAR); - } - - /* Now reserve the memory */ - Destination = FlatBuf_Arg_Reserve(Position, FreeSize, StringLength, Align); - if (Destination) - { - /* We have space, do the copy */ - RtlCopyMemory(Destination, String, StringLength); - } - - /* Return the pointer to the data */ - return Destination; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/flatbuf.c - * PURPOSE: Functions for managing the Flat Buffer Implementation (FLATBUF) - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -VOID -WINAPI -FlatBuf_Init(IN PFLATBUFF FlatBuffer, - IN PVOID Buffer, - IN SIZE_T Size) -{ - /* Set up the Flat Buffer start, current and ending position */ - FlatBuffer->Buffer = Buffer; - FlatBuffer->BufferPos = (ULONG_PTR)Buffer; - FlatBuffer->BufferEnd = (PVOID)(FlatBuffer->BufferPos + Size); - - /* Setup the current size and the available size */ - FlatBuffer->BufferSize = FlatBuffer->BufferFreeSize = Size; -} - -PVOID -WINAPI -FlatBuf_Arg_Reserve(IN OUT PULONG_PTR Position, - IN OUT PSIZE_T FreeSize, - IN SIZE_T Size, - IN ULONG Align) -{ - ULONG_PTR NewPosition, OldPosition = *Position; - SIZE_T NewFreeSize = *FreeSize; - - /* Start by aligning our position */ - if (Align) OldPosition += (Align - 1) & ~Align; - - /* Update it */ - NewPosition = OldPosition + Size; - - /* Update Free Size */ - NewFreeSize += (OldPosition - NewPosition); - - /* Save new values */ - *Position = NewPosition; - *FreeSize = NewFreeSize; - - /* Check if we're out of space or not */ - if (NewFreeSize > 0) return (PVOID)OldPosition; - return NULL; -} - -PVOID -WINAPI -FlatBuf_Arg_CopyMemory(IN OUT PULONG_PTR Position, - IN OUT PSIZE_T FreeSize, - IN PVOID Buffer, - IN SIZE_T Size, - IN ULONG Align) -{ - PVOID Destination; - - /* First reserve the memory */ - Destination = FlatBuf_Arg_Reserve(Position, FreeSize, Size, Align); - if (Destination) - { - /* We have space, do the copy */ - RtlCopyMemory(Destination, Buffer, Size); - } - - /* Return the pointer to the data */ - return Destination; -} - -PVOID -WINAPI -FlatBuf_Arg_WriteString(IN OUT PULONG_PTR Position, - IN OUT PSIZE_T FreeSize, - IN PVOID String, - IN BOOLEAN IsUnicode) -{ - PVOID Destination; - SIZE_T StringLength; - ULONG Align; - - /* Calculate the string length */ - if (IsUnicode) - { - /* Get the length in bytes and use WCHAR alignment */ - StringLength = (wcslen((LPWSTR)String) + 1) * sizeof(WCHAR); - Align = sizeof(WCHAR); - } - else - { - /* Get the length in bytes and use CHAR alignment */ - StringLength = strlen((LPSTR)String) + 1; - Align = sizeof(CHAR); - } - - /* Now reserve the memory */ - Destination = FlatBuf_Arg_Reserve(Position, FreeSize, StringLength, Align); - if (Destination) - { - /* We have space, do the copy */ - RtlCopyMemory(Destination, String, StringLength); - } - - /* Return the pointer to the data */ - return Destination; -} - diff --git a/dll/win32/mswsock/dns/hostent.c b/dll/win32/mswsock/dns/hostent.c index c444ac28940..f7c9e64bb39 100644 --- a/dll/win32/mswsock/dns/hostent.c +++ b/dll/win32/mswsock/dns/hostent.c @@ -95,294 +95,3 @@ Hostent_ConvertToOffsets(IN PHOSTENT Hostent) } } -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/hostent.c - * PURPOSE: Functions for dealing with Host Entry structures - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -PHOSTENT -WINAPI -Hostent_Init(IN PVOID *Buffer, - IN WORD AddressFamily, - IN ULONG AddressSize, - IN ULONG AddressCount, - IN ULONG AliasCount) -{ - PHOSTENT Hostent; - ULONG_PTR BufferPosition = (ULONG_PTR)*Buffer; - - /* Align the hostent on the buffer's 4 byte boundary */ - BufferPosition += 3 & ~3; - - /* Set up the basic data */ - Hostent = (PHOSTENT)BufferPosition; - Hostent->h_length = (WORD)AddressSize; - Hostent->h_addrtype = AddressFamily; - - /* Put aliases after Hostent */ - Hostent->h_aliases = (PCHAR*)((ULONG_PTR)(Hostent + 1) & ~3); - - /* Zero it out */ - RtlZeroMemory(Hostent->h_aliases, AliasCount * sizeof(PCHAR)); - - /* Put addresses after aliases */ - Hostent->h_addr_list = (PCHAR*) - ((ULONG_PTR)Hostent->h_aliases + - (AliasCount * sizeof(PCHAR)) + sizeof(PCHAR)); - - /* Update the location */ - BufferPosition = (ULONG_PTR)Hostent->h_addr_list + - ((AddressCount * sizeof(PCHAR)) + sizeof(PCHAR)); - - /* Send it back */ - *Buffer = (PVOID)BufferPosition; - - /* Return the hostent */ - return Hostent; -} - -VOID -WINAPI -Dns_PtrArrayToOffsetArray(PCHAR *List, - ULONG_PTR Base) -{ - /* Loop every pointer in the list */ - do - { - /* Update the pointer */ - *List = (PCHAR)((ULONG_PTR)*List - Base); - } while(*List++); -} - -VOID -WINAPI -Hostent_ConvertToOffsets(IN PHOSTENT Hostent) -{ - /* Do we have a name? */ - if (Hostent->h_name) - { - /* Update it */ - Hostent->h_name -= (ULONG_PTR)Hostent; - } - - /* Do we have aliases? */ - if (Hostent->h_aliases) - { - /* Update the pointer */ - Hostent->h_aliases -= (ULONG_PTR)Hostent; - - /* Fix them up */ - Dns_PtrArrayToOffsetArray(Hostent->h_aliases, (ULONG_PTR)Hostent); - } - - /* Do we have addresses? */ - if (Hostent->h_addr_list) - { - /* Fix them up */ - Dns_PtrArrayToOffsetArray(Hostent->h_addr_list, (ULONG_PTR)Hostent); - } -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/hostent.c - * PURPOSE: Functions for dealing with Host Entry structures - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -PHOSTENT -WINAPI -Hostent_Init(IN PVOID *Buffer, - IN WORD AddressFamily, - IN ULONG AddressSize, - IN ULONG AddressCount, - IN ULONG AliasCount) -{ - PHOSTENT Hostent; - ULONG_PTR BufferPosition = (ULONG_PTR)*Buffer; - - /* Align the hostent on the buffer's 4 byte boundary */ - BufferPosition += 3 & ~3; - - /* Set up the basic data */ - Hostent = (PHOSTENT)BufferPosition; - Hostent->h_length = (WORD)AddressSize; - Hostent->h_addrtype = AddressFamily; - - /* Put aliases after Hostent */ - Hostent->h_aliases = (PCHAR*)((ULONG_PTR)(Hostent + 1) & ~3); - - /* Zero it out */ - RtlZeroMemory(Hostent->h_aliases, AliasCount * sizeof(PCHAR)); - - /* Put addresses after aliases */ - Hostent->h_addr_list = (PCHAR*) - ((ULONG_PTR)Hostent->h_aliases + - (AliasCount * sizeof(PCHAR)) + sizeof(PCHAR)); - - /* Update the location */ - BufferPosition = (ULONG_PTR)Hostent->h_addr_list + - ((AddressCount * sizeof(PCHAR)) + sizeof(PCHAR)); - - /* Send it back */ - *Buffer = (PVOID)BufferPosition; - - /* Return the hostent */ - return Hostent; -} - -VOID -WINAPI -Dns_PtrArrayToOffsetArray(PCHAR *List, - ULONG_PTR Base) -{ - /* Loop every pointer in the list */ - do - { - /* Update the pointer */ - *List = (PCHAR)((ULONG_PTR)*List - Base); - } while(*List++); -} - -VOID -WINAPI -Hostent_ConvertToOffsets(IN PHOSTENT Hostent) -{ - /* Do we have a name? */ - if (Hostent->h_name) - { - /* Update it */ - Hostent->h_name -= (ULONG_PTR)Hostent; - } - - /* Do we have aliases? */ - if (Hostent->h_aliases) - { - /* Update the pointer */ - Hostent->h_aliases -= (ULONG_PTR)Hostent; - - /* Fix them up */ - Dns_PtrArrayToOffsetArray(Hostent->h_aliases, (ULONG_PTR)Hostent); - } - - /* Do we have addresses? */ - if (Hostent->h_addr_list) - { - /* Fix them up */ - Dns_PtrArrayToOffsetArray(Hostent->h_addr_list, (ULONG_PTR)Hostent); - } -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/hostent.c - * PURPOSE: Functions for dealing with Host Entry structures - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -PHOSTENT -WINAPI -Hostent_Init(IN PVOID *Buffer, - IN WORD AddressFamily, - IN ULONG AddressSize, - IN ULONG AddressCount, - IN ULONG AliasCount) -{ - PHOSTENT Hostent; - ULONG_PTR BufferPosition = (ULONG_PTR)*Buffer; - - /* Align the hostent on the buffer's 4 byte boundary */ - BufferPosition += 3 & ~3; - - /* Set up the basic data */ - Hostent = (PHOSTENT)BufferPosition; - Hostent->h_length = (WORD)AddressSize; - Hostent->h_addrtype = AddressFamily; - - /* Put aliases after Hostent */ - Hostent->h_aliases = (PCHAR*)((ULONG_PTR)(Hostent + 1) & ~3); - - /* Zero it out */ - RtlZeroMemory(Hostent->h_aliases, AliasCount * sizeof(PCHAR)); - - /* Put addresses after aliases */ - Hostent->h_addr_list = (PCHAR*) - ((ULONG_PTR)Hostent->h_aliases + - (AliasCount * sizeof(PCHAR)) + sizeof(PCHAR)); - - /* Update the location */ - BufferPosition = (ULONG_PTR)Hostent->h_addr_list + - ((AddressCount * sizeof(PCHAR)) + sizeof(PCHAR)); - - /* Send it back */ - *Buffer = (PVOID)BufferPosition; - - /* Return the hostent */ - return Hostent; -} - -VOID -WINAPI -Dns_PtrArrayToOffsetArray(PCHAR *List, - ULONG_PTR Base) -{ - /* Loop every pointer in the list */ - do - { - /* Update the pointer */ - *List = (PCHAR)((ULONG_PTR)*List - Base); - } while(*List++); -} - -VOID -WINAPI -Hostent_ConvertToOffsets(IN PHOSTENT Hostent) -{ - /* Do we have a name? */ - if (Hostent->h_name) - { - /* Update it */ - Hostent->h_name -= (ULONG_PTR)Hostent; - } - - /* Do we have aliases? */ - if (Hostent->h_aliases) - { - /* Update the pointer */ - Hostent->h_aliases -= (ULONG_PTR)Hostent; - - /* Fix them up */ - Dns_PtrArrayToOffsetArray(Hostent->h_aliases, (ULONG_PTR)Hostent); - } - - /* Do we have addresses? */ - if (Hostent->h_addr_list) - { - /* Fix them up */ - Dns_PtrArrayToOffsetArray(Hostent->h_addr_list, (ULONG_PTR)Hostent); - } -} - diff --git a/dll/win32/mswsock/dns/inc/dnslib.h b/dll/win32/mswsock/dns/inc/dnslib.h index b19220f6ad0..4c187f15b37 100644 --- a/dll/win32/mswsock/dns/inc/dnslib.h +++ b/dll/win32/mswsock/dns/inc/dnslib.h @@ -1,144 +1,343 @@ /* * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/precomp.h - * PURPOSE: DNSLIB Precompiled Header + * PROJECT: ReactOS Ancillary Function Driver DLL + * FILE: include/mswsock.h + * PURPOSE: Ancillary Function Driver DLL header */ +#ifndef __DNSLIB_H +#define __DNSLIB_H -#define _CRT_SECURE_NO_DEPRECATE -#define _WIN32_WINNT 0x502 -#define WIN32_NO_STATUS +/* INCLUDES ******************************************************************/ +#include -/* PSDK Headers */ -#include -#include -#include +/* ENUMERATIONS **************************************************************/ -/* DNSLIB and DNSAPI Headers */ -#include -#include +typedef enum _DNS_STRING_TYPE +{ + UnicodeString = 1, + Utf8String, + AnsiString, +} DNS_STRING_TYPE; -/* NDK */ -#include +#define IpV4Address 3 + +/* TYPES *********************************************************************/ + +typedef struct _DNS_IPV6_ADDRESS +{ + ULONG Unknown; + ULONG Unknown2; + IP6_ADDRESS Address; + ULONG Unknown3; + ULONG Unknown4; + DWORD Reserved; + ULONG Unknown5; +} DNS_IPV6_ADDRESS, *PDNS_IPV6_ADDRESS; + +typedef struct _DNS_ADDRESS +{ + union + { + struct + { + WORD AddressFamily; + WORD Port; + ATM_ADDRESS AtmAddress; + }; + SOCKADDR_IN Ip4Address; + SOCKADDR_IN6 Ip6Address; + }; + ULONG AddressLength; + DWORD Sub; + ULONG Flag; +} DNS_ADDRESS, *PDNS_ADDRESS; + +typedef struct _DNS_ARRAY +{ + ULONG AllocatedAddresses; + ULONG UsedAddresses; + ULONG Unknown[0x6]; + DNS_ADDRESS Addresses[1]; +} DNS_ARRAY, *PDNS_ARRAY; + +typedef struct _DNS_BLOB +{ + LPWSTR Name; + PDNS_ARRAY DnsAddrArray; + PHOSTENT Hostent; + ULONG AliasCount; + ULONG Unknown; + LPWSTR Aliases[8]; +} DNS_BLOB, *PDNS_BLOB; + +typedef struct _DNS_FAMILY_INFO +{ + WORD AddrType; + WORD DnsType; + DWORD AddressSize; + DWORD SockaddrSize; + DWORD AddressOffset; +} DNS_FAMILY_INFO, *PDNS_FAMILY_INFO; + +typedef struct _FLATBUFF +{ + PVOID Buffer; + PVOID BufferEnd; + ULONG_PTR BufferPos; + SIZE_T BufferSize; + SIZE_T BufferFreeSize; +} FLATBUFF, *PFLATBUFF; -/* EOF */ /* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/precomp.h - * PURPOSE: DNSLIB Precompiled Header + * memory.c */ +VOID +WINAPI +Dns_Free(IN PVOID Address); -#define _CRT_SECURE_NO_DEPRECATE -#define _WIN32_WINNT 0x502 -#define WIN32_NO_STATUS +PVOID +WINAPI +Dns_AllocZero(IN SIZE_T Size); -/* PSDK Headers */ -#include -#include -#include - -/* DNSLIB and DNSAPI Headers */ -#include -#include - -/* NDK */ -#include - -/* EOF */ /* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/precomp.h - * PURPOSE: DNSLIB Precompiled Header + * addr.c */ +PDNS_FAMILY_INFO +WINAPI +FamilyInfo_GetForFamily(IN WORD AddressFamily); -#define _CRT_SECURE_NO_DEPRECATE -#define _WIN32_WINNT 0x502 -#define WIN32_NO_STATUS - -/* PSDK Headers */ -#include -#include -#include - -/* DNSLIB and DNSAPI Headers */ -#include -#include - -/* NDK */ -#include - -/* EOF */ /* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/precomp.h - * PURPOSE: DNSLIB Precompiled Header + * dnsaddr.c */ +VOID +WINAPI +DnsAddr_BuildFromIp4( + IN PDNS_ADDRESS DnsAddress, + IN IN_ADDR Address, + IN WORD Unknown +); -#define _CRT_SECURE_NO_DEPRECATE -#define _WIN32_WINNT 0x502 -#define WIN32_NO_STATUS +VOID +WINAPI +DnsAddr_BuildFromIp6( + IN PDNS_ADDRESS DnsAddress, + IN PIN6_ADDR Address, + IN ULONG ScopeId, + IN WORD Port +); -/* PSDK Headers */ -#include -#include -#include +PDNS_ARRAY +WINAPI +DnsAddrArray_Create(ULONG Count); -/* DNSLIB and DNSAPI Headers */ -#include -#include +BOOL +WINAPI +DnsAddrArray_AddAddr( + IN PDNS_ARRAY DnsAddrArray, + IN PDNS_ADDRESS DnsAddress, + IN WORD AddressFamily OPTIONAL, + IN DWORD AddressType OPTIONAL +); -/* NDK */ -#include +VOID +WINAPI +DnsAddrArray_Free(IN PDNS_ARRAY DnsAddrArray); + +BOOL +WINAPI +DnsAddrArray_AddIp4( + IN PDNS_ARRAY DnsAddrArray, + IN IN_ADDR Address, + IN DWORD AddressType +); + +BOOL +WINAPI +DnsAddrArray_ContainsAddr( + IN PDNS_ARRAY DnsAddrArray, + IN PDNS_ADDRESS DnsAddress, + IN DWORD AddressType +); + +BOOLEAN +WINAPI +DnsAddr_BuildFromDnsRecord( + IN PDNS_RECORD DnsRecord, + OUT PDNS_ADDRESS DnsAddr +); -/* EOF */ /* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/precomp.h - * PURPOSE: DNSLIB Precompiled Header + * hostent.c */ +PHOSTENT +WINAPI +Hostent_Init( + IN PVOID *Buffer, + IN WORD AddressFamily, + IN ULONG AddressSize, + IN ULONG AddressCount, + IN ULONG AliasCount +); -#define _CRT_SECURE_NO_DEPRECATE -#define _WIN32_WINNT 0x502 -#define WIN32_NO_STATUS +VOID +WINAPI +Hostent_ConvertToOffsets(IN PHOSTENT Hostent); -/* PSDK Headers */ -#include -#include -#include - -/* DNSLIB and DNSAPI Headers */ -#include -#include - -/* NDK */ -#include - -/* EOF */ /* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/precomp.h - * PURPOSE: DNSLIB Precompiled Header + * flatbuf.c */ +VOID +WINAPI +FlatBuf_Init( + IN PFLATBUFF FlatBuffer, + IN PVOID Buffer, + IN SIZE_T Size +); -#define _CRT_SECURE_NO_DEPRECATE -#define _WIN32_WINNT 0x502 -#define WIN32_NO_STATUS +PVOID +WINAPI +FlatBuf_Arg_CopyMemory( + IN OUT PULONG_PTR Position, + IN OUT PSIZE_T FreeSize, + IN PVOID Buffer, + IN SIZE_T Size, + IN ULONG Align +); -/* PSDK Headers */ -#include -#include -#include +PVOID +WINAPI +FlatBuf_Arg_Reserve( + IN OUT PULONG_PTR Position, + IN OUT PSIZE_T FreeSize, + IN SIZE_T Size, + IN ULONG Align +); -/* DNSLIB and DNSAPI Headers */ -#include -#include +PVOID +WINAPI +FlatBuf_Arg_WriteString( + IN OUT PULONG_PTR Position, + IN OUT PSIZE_T FreeSize, + IN PVOID String, + IN BOOLEAN IsUnicode +); -/* NDK */ -#include +/* + * sablob.c + */ +PDNS_BLOB +WINAPI +SaBlob_Create( + IN ULONG Count +); -/* EOF */ +PDNS_BLOB +WINAPI +SaBlob_CreateFromIp4( + IN LPWSTR Name, + IN ULONG Count, + IN PIN_ADDR AddressArray +); + +VOID +WINAPI +SaBlob_Free(IN PDNS_BLOB Blob); + +PHOSTENT +WINAPI +SaBlob_CreateHostent( + IN OUT PULONG_PTR BufferPosition, + IN OUT PSIZE_T RemainingBufferSpace, + IN OUT PSIZE_T HostEntrySize, + IN PDNS_BLOB Blob, + IN DWORD StringType, + IN BOOLEAN Relative, + IN BOOLEAN BufferAllocated +); + +INT +WINAPI +SaBlob_WriteNameOrAlias( + IN PDNS_BLOB Blob, + IN LPWSTR String, + IN BOOLEAN IsAlias +); + +PDNS_BLOB +WINAPI +SaBlob_Query( + IN LPWSTR Name, + IN WORD DnsType, + IN ULONG Flags, + IN PVOID *Reserved, + IN DWORD AddressFamily +); + +/* + * string.c + */ +ULONG +WINAPI +Dns_StringCopy( + OUT PVOID Destination, + IN OUT PULONG DestinationSize, + IN PVOID String, + IN ULONG StringSize OPTIONAL, + IN DWORD InputType, + IN DWORD OutputType +); + +LPWSTR +WINAPI +Dns_CreateStringCopy_W(IN LPWSTR Name); + +ULONG +WINAPI +Dns_GetBufferLengthForStringCopy( + IN PVOID String, + IN ULONG Size OPTIONAL, + IN DWORD InputType, + IN DWORD OutputType +); + +/* + * straddr.c + */ +BOOLEAN +WINAPI +Dns_StringToAddressW( + OUT PVOID Address, + IN OUT PULONG AddressSize, + IN LPWSTR AddressName, + IN OUT PDWORD AddressFamily +); + +LPWSTR +WINAPI +Dns_Ip4AddressToReverseName_W( + OUT LPWSTR Name, + IN IN_ADDR Address +); + +LPWSTR +WINAPI +Dns_Ip6AddressToReverseName_W( + OUT LPWSTR Name, + IN IN6_ADDR Address +); + +BOOLEAN +WINAPI +Dns_ReverseNameToDnsAddr_W( + OUT PDNS_ADDRESS DnsAddr, + IN LPWSTR Name +); + +BOOLEAN +WINAPI +Dns_Ip4ReverseNameToAddress_W( + OUT PIN_ADDR Address, + IN LPWSTR Name +); + +#endif diff --git a/dll/win32/mswsock/dns/inc/dnslibp.h b/dll/win32/mswsock/dns/inc/dnslibp.h deleted file mode 100644 index 86359ae9172..00000000000 --- a/dll/win32/mswsock/dns/inc/dnslibp.h +++ /dev/null @@ -1,2058 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Ancillary Function Driver DLL - * FILE: include/mswsock.h - * PURPOSE: Ancillary Function Driver DLL header - */ -#ifndef __DNSLIB_H -#define __DNSLIB_H - -/* INCLUDES ******************************************************************/ -#include - -/* ENUMERATIONS **************************************************************/ - -typedef enum _DNS_STRING_TYPE -{ - UnicodeString = 1, - Utf8String, - AnsiString, -} DNS_STRING_TYPE; - -#define IpV4Address 3 - -/* TYPES *********************************************************************/ - -typedef struct _DNS_IPV6_ADDRESS -{ - ULONG Unknown; - ULONG Unknown2; - IP6_ADDRESS Address; - ULONG Unknown3; - ULONG Unknown4; - DWORD Reserved; - ULONG Unknown5; -} DNS_IPV6_ADDRESS, *PDNS_IPV6_ADDRESS; - -typedef struct _DNS_ADDRESS -{ - union - { - struct - { - WORD AddressFamily; - WORD Port; - ATM_ADDRESS AtmAddress; - }; - SOCKADDR_IN Ip4Address; - SOCKADDR_IN6 Ip6Address; - }; - ULONG AddressLength; - DWORD Sub; - ULONG Flag; -} DNS_ADDRESS, *PDNS_ADDRESS; - -typedef struct _DNS_ARRAY -{ - ULONG AllocatedAddresses; - ULONG UsedAddresses; - ULONG Unknown[0x6]; - DNS_ADDRESS Addresses[1]; -} DNS_ARRAY, *PDNS_ARRAY; - -typedef struct _DNS_BLOB -{ - LPWSTR Name; - PDNS_ARRAY DnsAddrArray; - PHOSTENT Hostent; - ULONG AliasCount; - ULONG Unknown; - LPWSTR Aliases[8]; -} DNS_BLOB, *PDNS_BLOB; - -typedef struct _DNS_FAMILY_INFO -{ - WORD AddrType; - WORD DnsType; - DWORD AddressSize; - DWORD SockaddrSize; - DWORD AddressOffset; -} DNS_FAMILY_INFO, *PDNS_FAMILY_INFO; - -typedef struct _FLATBUFF -{ - PVOID Buffer; - PVOID BufferEnd; - ULONG_PTR BufferPos; - SIZE_T BufferSize; - SIZE_T BufferFreeSize; -} FLATBUFF, *PFLATBUFF; - -/* - * memory.c - */ -VOID -WINAPI -Dns_Free(IN PVOID Address); - -PVOID -WINAPI -Dns_AllocZero(IN SIZE_T Size); - -/* - * addr.c - */ -PDNS_FAMILY_INFO -WINAPI -FamilyInfo_GetForFamily(IN WORD AddressFamily); - -/* - * dnsaddr.c - */ -VOID -WINAPI -DnsAddr_BuildFromIp4( - IN PDNS_ADDRESS DnsAddress, - IN IN_ADDR Address, - IN WORD Unknown -); - -VOID -WINAPI -DnsAddr_BuildFromIp6( - IN PDNS_ADDRESS DnsAddress, - IN PIN6_ADDR Address, - IN ULONG ScopeId, - IN WORD Port -); - -PDNS_ARRAY -WINAPI -DnsAddrArray_Create(ULONG Count); - -BOOL -WINAPI -DnsAddrArray_AddAddr( - IN PDNS_ARRAY DnsAddrArray, - IN PDNS_ADDRESS DnsAddress, - IN WORD AddressFamily OPTIONAL, - IN DWORD AddressType OPTIONAL -); - -VOID -WINAPI -DnsAddrArray_Free(IN PDNS_ARRAY DnsAddrArray); - -BOOL -WINAPI -DnsAddrArray_AddIp4( - IN PDNS_ARRAY DnsAddrArray, - IN IN_ADDR Address, - IN DWORD AddressType -); - -BOOL -WINAPI -DnsAddrArray_ContainsAddr( - IN PDNS_ARRAY DnsAddrArray, - IN PDNS_ADDRESS DnsAddress, - IN DWORD AddressType -); - -BOOLEAN -WINAPI -DnsAddr_BuildFromDnsRecord( - IN PDNS_RECORD DnsRecord, - OUT PDNS_ADDRESS DnsAddr -); - -/* - * hostent.c - */ -PHOSTENT -WINAPI -Hostent_Init( - IN PVOID *Buffer, - IN WORD AddressFamily, - IN ULONG AddressSize, - IN ULONG AddressCount, - IN ULONG AliasCount -); - -VOID -WINAPI -Hostent_ConvertToOffsets(IN PHOSTENT Hostent); - -/* - * flatbuf.c - */ -VOID -WINAPI -FlatBuf_Init( - IN PFLATBUFF FlatBuffer, - IN PVOID Buffer, - IN SIZE_T Size -); - -PVOID -WINAPI -FlatBuf_Arg_CopyMemory( - IN OUT PULONG_PTR Position, - IN OUT PSIZE_T FreeSize, - IN PVOID Buffer, - IN SIZE_T Size, - IN ULONG Align -); - -PVOID -WINAPI -FlatBuf_Arg_Reserve( - IN OUT PULONG_PTR Position, - IN OUT PSIZE_T FreeSize, - IN SIZE_T Size, - IN ULONG Align -); - -PVOID -WINAPI -FlatBuf_Arg_WriteString( - IN OUT PULONG_PTR Position, - IN OUT PSIZE_T FreeSize, - IN PVOID String, - IN BOOLEAN IsUnicode -); - -/* - * sablob.c - */ -PDNS_BLOB -WINAPI -SaBlob_Create( - IN ULONG Count -); - -PDNS_BLOB -WINAPI -SaBlob_CreateFromIp4( - IN LPWSTR Name, - IN ULONG Count, - IN PIN_ADDR AddressArray -); - -VOID -WINAPI -SaBlob_Free(IN PDNS_BLOB Blob); - -PHOSTENT -WINAPI -SaBlob_CreateHostent( - IN OUT PULONG_PTR BufferPosition, - IN OUT PSIZE_T RemainingBufferSpace, - IN OUT PSIZE_T HostEntrySize, - IN PDNS_BLOB Blob, - IN DWORD StringType, - IN BOOLEAN Relative, - IN BOOLEAN BufferAllocated -); - -INT -WINAPI -SaBlob_WriteNameOrAlias( - IN PDNS_BLOB Blob, - IN LPWSTR String, - IN BOOLEAN IsAlias -); - -PDNS_BLOB -WINAPI -SaBlob_Query( - IN LPWSTR Name, - IN WORD DnsType, - IN ULONG Flags, - IN PVOID *Reserved, - IN DWORD AddressFamily -); - -/* - * string.c - */ -ULONG -WINAPI -Dns_StringCopy( - OUT PVOID Destination, - IN OUT PULONG DestinationSize, - IN PVOID String, - IN ULONG StringSize OPTIONAL, - IN DWORD InputType, - IN DWORD OutputType -); - -LPWSTR -WINAPI -Dns_CreateStringCopy_W(IN LPWSTR Name); - -ULONG -WINAPI -Dns_GetBufferLengthForStringCopy( - IN PVOID String, - IN ULONG Size OPTIONAL, - IN DWORD InputType, - IN DWORD OutputType -); - -/* - * straddr.c - */ -BOOLEAN -WINAPI -Dns_StringToAddressW( - OUT PVOID Address, - IN OUT PULONG AddressSize, - IN LPWSTR AddressName, - IN OUT PDWORD AddressFamily -); - -LPWSTR -WINAPI -Dns_Ip4AddressToReverseName_W( - OUT LPWSTR Name, - IN IN_ADDR Address -); - -LPWSTR -WINAPI -Dns_Ip6AddressToReverseName_W( - OUT LPWSTR Name, - IN IN6_ADDR Address -); - -BOOLEAN -WINAPI -Dns_ReverseNameToDnsAddr_W( - OUT PDNS_ADDRESS DnsAddr, - IN LPWSTR Name -); - -BOOLEAN -WINAPI -Dns_Ip4ReverseNameToAddress_W( - OUT PIN_ADDR Address, - IN LPWSTR Name -); - -#endif -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Ancillary Function Driver DLL - * FILE: include/mswsock.h - * PURPOSE: Ancillary Function Driver DLL header - */ -#ifndef __DNSLIB_H -#define __DNSLIB_H - -/* INCLUDES ******************************************************************/ -#include - -/* ENUMERATIONS **************************************************************/ - -typedef enum _DNS_STRING_TYPE -{ - UnicodeString = 1, - Utf8String, - AnsiString, -} DNS_STRING_TYPE; - -#define IpV4Address 3 - -/* TYPES *********************************************************************/ - -typedef struct _DNS_IPV6_ADDRESS -{ - ULONG Unknown; - ULONG Unknown2; - IP6_ADDRESS Address; - ULONG Unknown3; - ULONG Unknown4; - DWORD Reserved; - ULONG Unknown5; -} DNS_IPV6_ADDRESS, *PDNS_IPV6_ADDRESS; - -typedef struct _DNS_ADDRESS -{ - union - { - struct - { - WORD AddressFamily; - WORD Port; - ATM_ADDRESS AtmAddress; - }; - SOCKADDR_IN Ip4Address; - SOCKADDR_IN6 Ip6Address; - }; - ULONG AddressLength; - DWORD Sub; - ULONG Flag; -} DNS_ADDRESS, *PDNS_ADDRESS; - -typedef struct _DNS_ARRAY -{ - ULONG AllocatedAddresses; - ULONG UsedAddresses; - ULONG Unknown[0x6]; - DNS_ADDRESS Addresses[1]; -} DNS_ARRAY, *PDNS_ARRAY; - -typedef struct _DNS_BLOB -{ - LPWSTR Name; - PDNS_ARRAY DnsAddrArray; - PHOSTENT Hostent; - ULONG AliasCount; - ULONG Unknown; - LPWSTR Aliases[8]; -} DNS_BLOB, *PDNS_BLOB; - -typedef struct _DNS_FAMILY_INFO -{ - WORD AddrType; - WORD DnsType; - DWORD AddressSize; - DWORD SockaddrSize; - DWORD AddressOffset; -} DNS_FAMILY_INFO, *PDNS_FAMILY_INFO; - -typedef struct _FLATBUFF -{ - PVOID Buffer; - PVOID BufferEnd; - ULONG_PTR BufferPos; - SIZE_T BufferSize; - SIZE_T BufferFreeSize; -} FLATBUFF, *PFLATBUFF; - -/* - * memory.c - */ -VOID -WINAPI -Dns_Free(IN PVOID Address); - -PVOID -WINAPI -Dns_AllocZero(IN SIZE_T Size); - -/* - * addr.c - */ -PDNS_FAMILY_INFO -WINAPI -FamilyInfo_GetForFamily(IN WORD AddressFamily); - -/* - * dnsaddr.c - */ -VOID -WINAPI -DnsAddr_BuildFromIp4( - IN PDNS_ADDRESS DnsAddress, - IN IN_ADDR Address, - IN WORD Unknown -); - -VOID -WINAPI -DnsAddr_BuildFromIp6( - IN PDNS_ADDRESS DnsAddress, - IN PIN6_ADDR Address, - IN ULONG ScopeId, - IN WORD Port -); - -PDNS_ARRAY -WINAPI -DnsAddrArray_Create(ULONG Count); - -BOOL -WINAPI -DnsAddrArray_AddAddr( - IN PDNS_ARRAY DnsAddrArray, - IN PDNS_ADDRESS DnsAddress, - IN WORD AddressFamily OPTIONAL, - IN DWORD AddressType OPTIONAL -); - -VOID -WINAPI -DnsAddrArray_Free(IN PDNS_ARRAY DnsAddrArray); - -BOOL -WINAPI -DnsAddrArray_AddIp4( - IN PDNS_ARRAY DnsAddrArray, - IN IN_ADDR Address, - IN DWORD AddressType -); - -BOOL -WINAPI -DnsAddrArray_ContainsAddr( - IN PDNS_ARRAY DnsAddrArray, - IN PDNS_ADDRESS DnsAddress, - IN DWORD AddressType -); - -BOOLEAN -WINAPI -DnsAddr_BuildFromDnsRecord( - IN PDNS_RECORD DnsRecord, - OUT PDNS_ADDRESS DnsAddr -); - -/* - * hostent.c - */ -PHOSTENT -WINAPI -Hostent_Init( - IN PVOID *Buffer, - IN WORD AddressFamily, - IN ULONG AddressSize, - IN ULONG AddressCount, - IN ULONG AliasCount -); - -VOID -WINAPI -Hostent_ConvertToOffsets(IN PHOSTENT Hostent); - -/* - * flatbuf.c - */ -VOID -WINAPI -FlatBuf_Init( - IN PFLATBUFF FlatBuffer, - IN PVOID Buffer, - IN SIZE_T Size -); - -PVOID -WINAPI -FlatBuf_Arg_CopyMemory( - IN OUT PULONG_PTR Position, - IN OUT PSIZE_T FreeSize, - IN PVOID Buffer, - IN SIZE_T Size, - IN ULONG Align -); - -PVOID -WINAPI -FlatBuf_Arg_Reserve( - IN OUT PULONG_PTR Position, - IN OUT PSIZE_T FreeSize, - IN SIZE_T Size, - IN ULONG Align -); - -PVOID -WINAPI -FlatBuf_Arg_WriteString( - IN OUT PULONG_PTR Position, - IN OUT PSIZE_T FreeSize, - IN PVOID String, - IN BOOLEAN IsUnicode -); - -/* - * sablob.c - */ -PDNS_BLOB -WINAPI -SaBlob_Create( - IN ULONG Count -); - -PDNS_BLOB -WINAPI -SaBlob_CreateFromIp4( - IN LPWSTR Name, - IN ULONG Count, - IN PIN_ADDR AddressArray -); - -VOID -WINAPI -SaBlob_Free(IN PDNS_BLOB Blob); - -PHOSTENT -WINAPI -SaBlob_CreateHostent( - IN OUT PULONG_PTR BufferPosition, - IN OUT PSIZE_T RemainingBufferSpace, - IN OUT PSIZE_T HostEntrySize, - IN PDNS_BLOB Blob, - IN DWORD StringType, - IN BOOLEAN Relative, - IN BOOLEAN BufferAllocated -); - -INT -WINAPI -SaBlob_WriteNameOrAlias( - IN PDNS_BLOB Blob, - IN LPWSTR String, - IN BOOLEAN IsAlias -); - -PDNS_BLOB -WINAPI -SaBlob_Query( - IN LPWSTR Name, - IN WORD DnsType, - IN ULONG Flags, - IN PVOID *Reserved, - IN DWORD AddressFamily -); - -/* - * string.c - */ -ULONG -WINAPI -Dns_StringCopy( - OUT PVOID Destination, - IN OUT PULONG DestinationSize, - IN PVOID String, - IN ULONG StringSize OPTIONAL, - IN DWORD InputType, - IN DWORD OutputType -); - -LPWSTR -WINAPI -Dns_CreateStringCopy_W(IN LPWSTR Name); - -ULONG -WINAPI -Dns_GetBufferLengthForStringCopy( - IN PVOID String, - IN ULONG Size OPTIONAL, - IN DWORD InputType, - IN DWORD OutputType -); - -/* - * straddr.c - */ -BOOLEAN -WINAPI -Dns_StringToAddressW( - OUT PVOID Address, - IN OUT PULONG AddressSize, - IN LPWSTR AddressName, - IN OUT PDWORD AddressFamily -); - -LPWSTR -WINAPI -Dns_Ip4AddressToReverseName_W( - OUT LPWSTR Name, - IN IN_ADDR Address -); - -LPWSTR -WINAPI -Dns_Ip6AddressToReverseName_W( - OUT LPWSTR Name, - IN IN6_ADDR Address -); - -BOOLEAN -WINAPI -Dns_ReverseNameToDnsAddr_W( - OUT PDNS_ADDRESS DnsAddr, - IN LPWSTR Name -); - -BOOLEAN -WINAPI -Dns_Ip4ReverseNameToAddress_W( - OUT PIN_ADDR Address, - IN LPWSTR Name -); - -#endif -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Ancillary Function Driver DLL - * FILE: include/mswsock.h - * PURPOSE: Ancillary Function Driver DLL header - */ -#ifndef __DNSLIB_H -#define __DNSLIB_H - -/* INCLUDES ******************************************************************/ -#include - -/* ENUMERATIONS **************************************************************/ - -typedef enum _DNS_STRING_TYPE -{ - UnicodeString = 1, - Utf8String, - AnsiString, -} DNS_STRING_TYPE; - -#define IpV4Address 3 - -/* TYPES *********************************************************************/ - -typedef struct _DNS_IPV6_ADDRESS -{ - ULONG Unknown; - ULONG Unknown2; - IP6_ADDRESS Address; - ULONG Unknown3; - ULONG Unknown4; - DWORD Reserved; - ULONG Unknown5; -} DNS_IPV6_ADDRESS, *PDNS_IPV6_ADDRESS; - -typedef struct _DNS_ADDRESS -{ - union - { - struct - { - WORD AddressFamily; - WORD Port; - ATM_ADDRESS AtmAddress; - }; - SOCKADDR_IN Ip4Address; - SOCKADDR_IN6 Ip6Address; - }; - ULONG AddressLength; - DWORD Sub; - ULONG Flag; -} DNS_ADDRESS, *PDNS_ADDRESS; - -typedef struct _DNS_ARRAY -{ - ULONG AllocatedAddresses; - ULONG UsedAddresses; - ULONG Unknown[0x6]; - DNS_ADDRESS Addresses[1]; -} DNS_ARRAY, *PDNS_ARRAY; - -typedef struct _DNS_BLOB -{ - LPWSTR Name; - PDNS_ARRAY DnsAddrArray; - PHOSTENT Hostent; - ULONG AliasCount; - ULONG Unknown; - LPWSTR Aliases[8]; -} DNS_BLOB, *PDNS_BLOB; - -typedef struct _DNS_FAMILY_INFO -{ - WORD AddrType; - WORD DnsType; - DWORD AddressSize; - DWORD SockaddrSize; - DWORD AddressOffset; -} DNS_FAMILY_INFO, *PDNS_FAMILY_INFO; - -typedef struct _FLATBUFF -{ - PVOID Buffer; - PVOID BufferEnd; - ULONG_PTR BufferPos; - SIZE_T BufferSize; - SIZE_T BufferFreeSize; -} FLATBUFF, *PFLATBUFF; - -/* - * memory.c - */ -VOID -WINAPI -Dns_Free(IN PVOID Address); - -PVOID -WINAPI -Dns_AllocZero(IN SIZE_T Size); - -/* - * addr.c - */ -PDNS_FAMILY_INFO -WINAPI -FamilyInfo_GetForFamily(IN WORD AddressFamily); - -/* - * dnsaddr.c - */ -VOID -WINAPI -DnsAddr_BuildFromIp4( - IN PDNS_ADDRESS DnsAddress, - IN IN_ADDR Address, - IN WORD Unknown -); - -VOID -WINAPI -DnsAddr_BuildFromIp6( - IN PDNS_ADDRESS DnsAddress, - IN PIN6_ADDR Address, - IN ULONG ScopeId, - IN WORD Port -); - -PDNS_ARRAY -WINAPI -DnsAddrArray_Create(ULONG Count); - -BOOL -WINAPI -DnsAddrArray_AddAddr( - IN PDNS_ARRAY DnsAddrArray, - IN PDNS_ADDRESS DnsAddress, - IN WORD AddressFamily OPTIONAL, - IN DWORD AddressType OPTIONAL -); - -VOID -WINAPI -DnsAddrArray_Free(IN PDNS_ARRAY DnsAddrArray); - -BOOL -WINAPI -DnsAddrArray_AddIp4( - IN PDNS_ARRAY DnsAddrArray, - IN IN_ADDR Address, - IN DWORD AddressType -); - -BOOL -WINAPI -DnsAddrArray_ContainsAddr( - IN PDNS_ARRAY DnsAddrArray, - IN PDNS_ADDRESS DnsAddress, - IN DWORD AddressType -); - -BOOLEAN -WINAPI -DnsAddr_BuildFromDnsRecord( - IN PDNS_RECORD DnsRecord, - OUT PDNS_ADDRESS DnsAddr -); - -/* - * hostent.c - */ -PHOSTENT -WINAPI -Hostent_Init( - IN PVOID *Buffer, - IN WORD AddressFamily, - IN ULONG AddressSize, - IN ULONG AddressCount, - IN ULONG AliasCount -); - -VOID -WINAPI -Hostent_ConvertToOffsets(IN PHOSTENT Hostent); - -/* - * flatbuf.c - */ -VOID -WINAPI -FlatBuf_Init( - IN PFLATBUFF FlatBuffer, - IN PVOID Buffer, - IN SIZE_T Size -); - -PVOID -WINAPI -FlatBuf_Arg_CopyMemory( - IN OUT PULONG_PTR Position, - IN OUT PSIZE_T FreeSize, - IN PVOID Buffer, - IN SIZE_T Size, - IN ULONG Align -); - -PVOID -WINAPI -FlatBuf_Arg_Reserve( - IN OUT PULONG_PTR Position, - IN OUT PSIZE_T FreeSize, - IN SIZE_T Size, - IN ULONG Align -); - -PVOID -WINAPI -FlatBuf_Arg_WriteString( - IN OUT PULONG_PTR Position, - IN OUT PSIZE_T FreeSize, - IN PVOID String, - IN BOOLEAN IsUnicode -); - -/* - * sablob.c - */ -PDNS_BLOB -WINAPI -SaBlob_Create( - IN ULONG Count -); - -PDNS_BLOB -WINAPI -SaBlob_CreateFromIp4( - IN LPWSTR Name, - IN ULONG Count, - IN PIN_ADDR AddressArray -); - -VOID -WINAPI -SaBlob_Free(IN PDNS_BLOB Blob); - -PHOSTENT -WINAPI -SaBlob_CreateHostent( - IN OUT PULONG_PTR BufferPosition, - IN OUT PSIZE_T RemainingBufferSpace, - IN OUT PSIZE_T HostEntrySize, - IN PDNS_BLOB Blob, - IN DWORD StringType, - IN BOOLEAN Relative, - IN BOOLEAN BufferAllocated -); - -INT -WINAPI -SaBlob_WriteNameOrAlias( - IN PDNS_BLOB Blob, - IN LPWSTR String, - IN BOOLEAN IsAlias -); - -PDNS_BLOB -WINAPI -SaBlob_Query( - IN LPWSTR Name, - IN WORD DnsType, - IN ULONG Flags, - IN PVOID *Reserved, - IN DWORD AddressFamily -); - -/* - * string.c - */ -ULONG -WINAPI -Dns_StringCopy( - OUT PVOID Destination, - IN OUT PULONG DestinationSize, - IN PVOID String, - IN ULONG StringSize OPTIONAL, - IN DWORD InputType, - IN DWORD OutputType -); - -LPWSTR -WINAPI -Dns_CreateStringCopy_W(IN LPWSTR Name); - -ULONG -WINAPI -Dns_GetBufferLengthForStringCopy( - IN PVOID String, - IN ULONG Size OPTIONAL, - IN DWORD InputType, - IN DWORD OutputType -); - -/* - * straddr.c - */ -BOOLEAN -WINAPI -Dns_StringToAddressW( - OUT PVOID Address, - IN OUT PULONG AddressSize, - IN LPWSTR AddressName, - IN OUT PDWORD AddressFamily -); - -LPWSTR -WINAPI -Dns_Ip4AddressToReverseName_W( - OUT LPWSTR Name, - IN IN_ADDR Address -); - -LPWSTR -WINAPI -Dns_Ip6AddressToReverseName_W( - OUT LPWSTR Name, - IN IN6_ADDR Address -); - -BOOLEAN -WINAPI -Dns_ReverseNameToDnsAddr_W( - OUT PDNS_ADDRESS DnsAddr, - IN LPWSTR Name -); - -BOOLEAN -WINAPI -Dns_Ip4ReverseNameToAddress_W( - OUT PIN_ADDR Address, - IN LPWSTR Name -); - -#endif -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Ancillary Function Driver DLL - * FILE: include/mswsock.h - * PURPOSE: Ancillary Function Driver DLL header - */ -#ifndef __DNSLIB_H -#define __DNSLIB_H - -/* INCLUDES ******************************************************************/ -#include - -/* ENUMERATIONS **************************************************************/ - -typedef enum _DNS_STRING_TYPE -{ - UnicodeString = 1, - Utf8String, - AnsiString, -} DNS_STRING_TYPE; - -#define IpV4Address 3 - -/* TYPES *********************************************************************/ - -typedef struct _DNS_IPV6_ADDRESS -{ - ULONG Unknown; - ULONG Unknown2; - IP6_ADDRESS Address; - ULONG Unknown3; - ULONG Unknown4; - DWORD Reserved; - ULONG Unknown5; -} DNS_IPV6_ADDRESS, *PDNS_IPV6_ADDRESS; - -typedef struct _DNS_ADDRESS -{ - union - { - struct - { - WORD AddressFamily; - WORD Port; - ATM_ADDRESS AtmAddress; - }; - SOCKADDR_IN Ip4Address; - SOCKADDR_IN6 Ip6Address; - }; - ULONG AddressLength; - DWORD Sub; - ULONG Flag; -} DNS_ADDRESS, *PDNS_ADDRESS; - -typedef struct _DNS_ARRAY -{ - ULONG AllocatedAddresses; - ULONG UsedAddresses; - ULONG Unknown[0x6]; - DNS_ADDRESS Addresses[1]; -} DNS_ARRAY, *PDNS_ARRAY; - -typedef struct _DNS_BLOB -{ - LPWSTR Name; - PDNS_ARRAY DnsAddrArray; - PHOSTENT Hostent; - ULONG AliasCount; - ULONG Unknown; - LPWSTR Aliases[8]; -} DNS_BLOB, *PDNS_BLOB; - -typedef struct _DNS_FAMILY_INFO -{ - WORD AddrType; - WORD DnsType; - DWORD AddressSize; - DWORD SockaddrSize; - DWORD AddressOffset; -} DNS_FAMILY_INFO, *PDNS_FAMILY_INFO; - -typedef struct _FLATBUFF -{ - PVOID Buffer; - PVOID BufferEnd; - ULONG_PTR BufferPos; - SIZE_T BufferSize; - SIZE_T BufferFreeSize; -} FLATBUFF, *PFLATBUFF; - -/* - * memory.c - */ -VOID -WINAPI -Dns_Free(IN PVOID Address); - -PVOID -WINAPI -Dns_AllocZero(IN SIZE_T Size); - -/* - * addr.c - */ -PDNS_FAMILY_INFO -WINAPI -FamilyInfo_GetForFamily(IN WORD AddressFamily); - -/* - * dnsaddr.c - */ -VOID -WINAPI -DnsAddr_BuildFromIp4( - IN PDNS_ADDRESS DnsAddress, - IN IN_ADDR Address, - IN WORD Unknown -); - -VOID -WINAPI -DnsAddr_BuildFromIp6( - IN PDNS_ADDRESS DnsAddress, - IN PIN6_ADDR Address, - IN ULONG ScopeId, - IN WORD Port -); - -PDNS_ARRAY -WINAPI -DnsAddrArray_Create(ULONG Count); - -BOOL -WINAPI -DnsAddrArray_AddAddr( - IN PDNS_ARRAY DnsAddrArray, - IN PDNS_ADDRESS DnsAddress, - IN WORD AddressFamily OPTIONAL, - IN DWORD AddressType OPTIONAL -); - -VOID -WINAPI -DnsAddrArray_Free(IN PDNS_ARRAY DnsAddrArray); - -BOOL -WINAPI -DnsAddrArray_AddIp4( - IN PDNS_ARRAY DnsAddrArray, - IN IN_ADDR Address, - IN DWORD AddressType -); - -BOOL -WINAPI -DnsAddrArray_ContainsAddr( - IN PDNS_ARRAY DnsAddrArray, - IN PDNS_ADDRESS DnsAddress, - IN DWORD AddressType -); - -BOOLEAN -WINAPI -DnsAddr_BuildFromDnsRecord( - IN PDNS_RECORD DnsRecord, - OUT PDNS_ADDRESS DnsAddr -); - -/* - * hostent.c - */ -PHOSTENT -WINAPI -Hostent_Init( - IN PVOID *Buffer, - IN WORD AddressFamily, - IN ULONG AddressSize, - IN ULONG AddressCount, - IN ULONG AliasCount -); - -VOID -WINAPI -Hostent_ConvertToOffsets(IN PHOSTENT Hostent); - -/* - * flatbuf.c - */ -VOID -WINAPI -FlatBuf_Init( - IN PFLATBUFF FlatBuffer, - IN PVOID Buffer, - IN SIZE_T Size -); - -PVOID -WINAPI -FlatBuf_Arg_CopyMemory( - IN OUT PULONG_PTR Position, - IN OUT PSIZE_T FreeSize, - IN PVOID Buffer, - IN SIZE_T Size, - IN ULONG Align -); - -PVOID -WINAPI -FlatBuf_Arg_Reserve( - IN OUT PULONG_PTR Position, - IN OUT PSIZE_T FreeSize, - IN SIZE_T Size, - IN ULONG Align -); - -PVOID -WINAPI -FlatBuf_Arg_WriteString( - IN OUT PULONG_PTR Position, - IN OUT PSIZE_T FreeSize, - IN PVOID String, - IN BOOLEAN IsUnicode -); - -/* - * sablob.c - */ -PDNS_BLOB -WINAPI -SaBlob_Create( - IN ULONG Count -); - -PDNS_BLOB -WINAPI -SaBlob_CreateFromIp4( - IN LPWSTR Name, - IN ULONG Count, - IN PIN_ADDR AddressArray -); - -VOID -WINAPI -SaBlob_Free(IN PDNS_BLOB Blob); - -PHOSTENT -WINAPI -SaBlob_CreateHostent( - IN OUT PULONG_PTR BufferPosition, - IN OUT PSIZE_T RemainingBufferSpace, - IN OUT PSIZE_T HostEntrySize, - IN PDNS_BLOB Blob, - IN DWORD StringType, - IN BOOLEAN Relative, - IN BOOLEAN BufferAllocated -); - -INT -WINAPI -SaBlob_WriteNameOrAlias( - IN PDNS_BLOB Blob, - IN LPWSTR String, - IN BOOLEAN IsAlias -); - -PDNS_BLOB -WINAPI -SaBlob_Query( - IN LPWSTR Name, - IN WORD DnsType, - IN ULONG Flags, - IN PVOID *Reserved, - IN DWORD AddressFamily -); - -/* - * string.c - */ -ULONG -WINAPI -Dns_StringCopy( - OUT PVOID Destination, - IN OUT PULONG DestinationSize, - IN PVOID String, - IN ULONG StringSize OPTIONAL, - IN DWORD InputType, - IN DWORD OutputType -); - -LPWSTR -WINAPI -Dns_CreateStringCopy_W(IN LPWSTR Name); - -ULONG -WINAPI -Dns_GetBufferLengthForStringCopy( - IN PVOID String, - IN ULONG Size OPTIONAL, - IN DWORD InputType, - IN DWORD OutputType -); - -/* - * straddr.c - */ -BOOLEAN -WINAPI -Dns_StringToAddressW( - OUT PVOID Address, - IN OUT PULONG AddressSize, - IN LPWSTR AddressName, - IN OUT PDWORD AddressFamily -); - -LPWSTR -WINAPI -Dns_Ip4AddressToReverseName_W( - OUT LPWSTR Name, - IN IN_ADDR Address -); - -LPWSTR -WINAPI -Dns_Ip6AddressToReverseName_W( - OUT LPWSTR Name, - IN IN6_ADDR Address -); - -BOOLEAN -WINAPI -Dns_ReverseNameToDnsAddr_W( - OUT PDNS_ADDRESS DnsAddr, - IN LPWSTR Name -); - -BOOLEAN -WINAPI -Dns_Ip4ReverseNameToAddress_W( - OUT PIN_ADDR Address, - IN LPWSTR Name -); - -#endif -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Ancillary Function Driver DLL - * FILE: include/mswsock.h - * PURPOSE: Ancillary Function Driver DLL header - */ -#ifndef __DNSLIB_H -#define __DNSLIB_H - -/* INCLUDES ******************************************************************/ -#include - -/* ENUMERATIONS **************************************************************/ - -typedef enum _DNS_STRING_TYPE -{ - UnicodeString = 1, - Utf8String, - AnsiString, -} DNS_STRING_TYPE; - -#define IpV4Address 3 - -/* TYPES *********************************************************************/ - -typedef struct _DNS_IPV6_ADDRESS -{ - ULONG Unknown; - ULONG Unknown2; - IP6_ADDRESS Address; - ULONG Unknown3; - ULONG Unknown4; - DWORD Reserved; - ULONG Unknown5; -} DNS_IPV6_ADDRESS, *PDNS_IPV6_ADDRESS; - -typedef struct _DNS_ADDRESS -{ - union - { - struct - { - WORD AddressFamily; - WORD Port; - ATM_ADDRESS AtmAddress; - }; - SOCKADDR_IN Ip4Address; - SOCKADDR_IN6 Ip6Address; - }; - ULONG AddressLength; - DWORD Sub; - ULONG Flag; -} DNS_ADDRESS, *PDNS_ADDRESS; - -typedef struct _DNS_ARRAY -{ - ULONG AllocatedAddresses; - ULONG UsedAddresses; - ULONG Unknown[0x6]; - DNS_ADDRESS Addresses[1]; -} DNS_ARRAY, *PDNS_ARRAY; - -typedef struct _DNS_BLOB -{ - LPWSTR Name; - PDNS_ARRAY DnsAddrArray; - PHOSTENT Hostent; - ULONG AliasCount; - ULONG Unknown; - LPWSTR Aliases[8]; -} DNS_BLOB, *PDNS_BLOB; - -typedef struct _DNS_FAMILY_INFO -{ - WORD AddrType; - WORD DnsType; - DWORD AddressSize; - DWORD SockaddrSize; - DWORD AddressOffset; -} DNS_FAMILY_INFO, *PDNS_FAMILY_INFO; - -typedef struct _FLATBUFF -{ - PVOID Buffer; - PVOID BufferEnd; - ULONG_PTR BufferPos; - SIZE_T BufferSize; - SIZE_T BufferFreeSize; -} FLATBUFF, *PFLATBUFF; - -/* - * memory.c - */ -VOID -WINAPI -Dns_Free(IN PVOID Address); - -PVOID -WINAPI -Dns_AllocZero(IN SIZE_T Size); - -/* - * addr.c - */ -PDNS_FAMILY_INFO -WINAPI -FamilyInfo_GetForFamily(IN WORD AddressFamily); - -/* - * dnsaddr.c - */ -VOID -WINAPI -DnsAddr_BuildFromIp4( - IN PDNS_ADDRESS DnsAddress, - IN IN_ADDR Address, - IN WORD Unknown -); - -VOID -WINAPI -DnsAddr_BuildFromIp6( - IN PDNS_ADDRESS DnsAddress, - IN PIN6_ADDR Address, - IN ULONG ScopeId, - IN WORD Port -); - -PDNS_ARRAY -WINAPI -DnsAddrArray_Create(ULONG Count); - -BOOL -WINAPI -DnsAddrArray_AddAddr( - IN PDNS_ARRAY DnsAddrArray, - IN PDNS_ADDRESS DnsAddress, - IN WORD AddressFamily OPTIONAL, - IN DWORD AddressType OPTIONAL -); - -VOID -WINAPI -DnsAddrArray_Free(IN PDNS_ARRAY DnsAddrArray); - -BOOL -WINAPI -DnsAddrArray_AddIp4( - IN PDNS_ARRAY DnsAddrArray, - IN IN_ADDR Address, - IN DWORD AddressType -); - -BOOL -WINAPI -DnsAddrArray_ContainsAddr( - IN PDNS_ARRAY DnsAddrArray, - IN PDNS_ADDRESS DnsAddress, - IN DWORD AddressType -); - -BOOLEAN -WINAPI -DnsAddr_BuildFromDnsRecord( - IN PDNS_RECORD DnsRecord, - OUT PDNS_ADDRESS DnsAddr -); - -/* - * hostent.c - */ -PHOSTENT -WINAPI -Hostent_Init( - IN PVOID *Buffer, - IN WORD AddressFamily, - IN ULONG AddressSize, - IN ULONG AddressCount, - IN ULONG AliasCount -); - -VOID -WINAPI -Hostent_ConvertToOffsets(IN PHOSTENT Hostent); - -/* - * flatbuf.c - */ -VOID -WINAPI -FlatBuf_Init( - IN PFLATBUFF FlatBuffer, - IN PVOID Buffer, - IN SIZE_T Size -); - -PVOID -WINAPI -FlatBuf_Arg_CopyMemory( - IN OUT PULONG_PTR Position, - IN OUT PSIZE_T FreeSize, - IN PVOID Buffer, - IN SIZE_T Size, - IN ULONG Align -); - -PVOID -WINAPI -FlatBuf_Arg_Reserve( - IN OUT PULONG_PTR Position, - IN OUT PSIZE_T FreeSize, - IN SIZE_T Size, - IN ULONG Align -); - -PVOID -WINAPI -FlatBuf_Arg_WriteString( - IN OUT PULONG_PTR Position, - IN OUT PSIZE_T FreeSize, - IN PVOID String, - IN BOOLEAN IsUnicode -); - -/* - * sablob.c - */ -PDNS_BLOB -WINAPI -SaBlob_Create( - IN ULONG Count -); - -PDNS_BLOB -WINAPI -SaBlob_CreateFromIp4( - IN LPWSTR Name, - IN ULONG Count, - IN PIN_ADDR AddressArray -); - -VOID -WINAPI -SaBlob_Free(IN PDNS_BLOB Blob); - -PHOSTENT -WINAPI -SaBlob_CreateHostent( - IN OUT PULONG_PTR BufferPosition, - IN OUT PSIZE_T RemainingBufferSpace, - IN OUT PSIZE_T HostEntrySize, - IN PDNS_BLOB Blob, - IN DWORD StringType, - IN BOOLEAN Relative, - IN BOOLEAN BufferAllocated -); - -INT -WINAPI -SaBlob_WriteNameOrAlias( - IN PDNS_BLOB Blob, - IN LPWSTR String, - IN BOOLEAN IsAlias -); - -PDNS_BLOB -WINAPI -SaBlob_Query( - IN LPWSTR Name, - IN WORD DnsType, - IN ULONG Flags, - IN PVOID *Reserved, - IN DWORD AddressFamily -); - -/* - * string.c - */ -ULONG -WINAPI -Dns_StringCopy( - OUT PVOID Destination, - IN OUT PULONG DestinationSize, - IN PVOID String, - IN ULONG StringSize OPTIONAL, - IN DWORD InputType, - IN DWORD OutputType -); - -LPWSTR -WINAPI -Dns_CreateStringCopy_W(IN LPWSTR Name); - -ULONG -WINAPI -Dns_GetBufferLengthForStringCopy( - IN PVOID String, - IN ULONG Size OPTIONAL, - IN DWORD InputType, - IN DWORD OutputType -); - -/* - * straddr.c - */ -BOOLEAN -WINAPI -Dns_StringToAddressW( - OUT PVOID Address, - IN OUT PULONG AddressSize, - IN LPWSTR AddressName, - IN OUT PDWORD AddressFamily -); - -LPWSTR -WINAPI -Dns_Ip4AddressToReverseName_W( - OUT LPWSTR Name, - IN IN_ADDR Address -); - -LPWSTR -WINAPI -Dns_Ip6AddressToReverseName_W( - OUT LPWSTR Name, - IN IN6_ADDR Address -); - -BOOLEAN -WINAPI -Dns_ReverseNameToDnsAddr_W( - OUT PDNS_ADDRESS DnsAddr, - IN LPWSTR Name -); - -BOOLEAN -WINAPI -Dns_Ip4ReverseNameToAddress_W( - OUT PIN_ADDR Address, - IN LPWSTR Name -); - -#endif -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Ancillary Function Driver DLL - * FILE: include/mswsock.h - * PURPOSE: Ancillary Function Driver DLL header - */ -#ifndef __DNSLIB_H -#define __DNSLIB_H - -/* INCLUDES ******************************************************************/ -#include - -/* ENUMERATIONS **************************************************************/ - -typedef enum _DNS_STRING_TYPE -{ - UnicodeString = 1, - Utf8String, - AnsiString, -} DNS_STRING_TYPE; - -#define IpV4Address 3 - -/* TYPES *********************************************************************/ - -typedef struct _DNS_IPV6_ADDRESS -{ - ULONG Unknown; - ULONG Unknown2; - IP6_ADDRESS Address; - ULONG Unknown3; - ULONG Unknown4; - DWORD Reserved; - ULONG Unknown5; -} DNS_IPV6_ADDRESS, *PDNS_IPV6_ADDRESS; - -typedef struct _DNS_ADDRESS -{ - union - { - struct - { - WORD AddressFamily; - WORD Port; - ATM_ADDRESS AtmAddress; - }; - SOCKADDR_IN Ip4Address; - SOCKADDR_IN6 Ip6Address; - }; - ULONG AddressLength; - DWORD Sub; - ULONG Flag; -} DNS_ADDRESS, *PDNS_ADDRESS; - -typedef struct _DNS_ARRAY -{ - ULONG AllocatedAddresses; - ULONG UsedAddresses; - ULONG Unknown[0x6]; - DNS_ADDRESS Addresses[1]; -} DNS_ARRAY, *PDNS_ARRAY; - -typedef struct _DNS_BLOB -{ - LPWSTR Name; - PDNS_ARRAY DnsAddrArray; - PHOSTENT Hostent; - ULONG AliasCount; - ULONG Unknown; - LPWSTR Aliases[8]; -} DNS_BLOB, *PDNS_BLOB; - -typedef struct _DNS_FAMILY_INFO -{ - WORD AddrType; - WORD DnsType; - DWORD AddressSize; - DWORD SockaddrSize; - DWORD AddressOffset; -} DNS_FAMILY_INFO, *PDNS_FAMILY_INFO; - -typedef struct _FLATBUFF -{ - PVOID Buffer; - PVOID BufferEnd; - ULONG_PTR BufferPos; - SIZE_T BufferSize; - SIZE_T BufferFreeSize; -} FLATBUFF, *PFLATBUFF; - -/* - * memory.c - */ -VOID -WINAPI -Dns_Free(IN PVOID Address); - -PVOID -WINAPI -Dns_AllocZero(IN SIZE_T Size); - -/* - * addr.c - */ -PDNS_FAMILY_INFO -WINAPI -FamilyInfo_GetForFamily(IN WORD AddressFamily); - -/* - * dnsaddr.c - */ -VOID -WINAPI -DnsAddr_BuildFromIp4( - IN PDNS_ADDRESS DnsAddress, - IN IN_ADDR Address, - IN WORD Unknown -); - -VOID -WINAPI -DnsAddr_BuildFromIp6( - IN PDNS_ADDRESS DnsAddress, - IN PIN6_ADDR Address, - IN ULONG ScopeId, - IN WORD Port -); - -PDNS_ARRAY -WINAPI -DnsAddrArray_Create(ULONG Count); - -BOOL -WINAPI -DnsAddrArray_AddAddr( - IN PDNS_ARRAY DnsAddrArray, - IN PDNS_ADDRESS DnsAddress, - IN WORD AddressFamily OPTIONAL, - IN DWORD AddressType OPTIONAL -); - -VOID -WINAPI -DnsAddrArray_Free(IN PDNS_ARRAY DnsAddrArray); - -BOOL -WINAPI -DnsAddrArray_AddIp4( - IN PDNS_ARRAY DnsAddrArray, - IN IN_ADDR Address, - IN DWORD AddressType -); - -BOOL -WINAPI -DnsAddrArray_ContainsAddr( - IN PDNS_ARRAY DnsAddrArray, - IN PDNS_ADDRESS DnsAddress, - IN DWORD AddressType -); - -BOOLEAN -WINAPI -DnsAddr_BuildFromDnsRecord( - IN PDNS_RECORD DnsRecord, - OUT PDNS_ADDRESS DnsAddr -); - -/* - * hostent.c - */ -PHOSTENT -WINAPI -Hostent_Init( - IN PVOID *Buffer, - IN WORD AddressFamily, - IN ULONG AddressSize, - IN ULONG AddressCount, - IN ULONG AliasCount -); - -VOID -WINAPI -Hostent_ConvertToOffsets(IN PHOSTENT Hostent); - -/* - * flatbuf.c - */ -VOID -WINAPI -FlatBuf_Init( - IN PFLATBUFF FlatBuffer, - IN PVOID Buffer, - IN SIZE_T Size -); - -PVOID -WINAPI -FlatBuf_Arg_CopyMemory( - IN OUT PULONG_PTR Position, - IN OUT PSIZE_T FreeSize, - IN PVOID Buffer, - IN SIZE_T Size, - IN ULONG Align -); - -PVOID -WINAPI -FlatBuf_Arg_Reserve( - IN OUT PULONG_PTR Position, - IN OUT PSIZE_T FreeSize, - IN SIZE_T Size, - IN ULONG Align -); - -PVOID -WINAPI -FlatBuf_Arg_WriteString( - IN OUT PULONG_PTR Position, - IN OUT PSIZE_T FreeSize, - IN PVOID String, - IN BOOLEAN IsUnicode -); - -/* - * sablob.c - */ -PDNS_BLOB -WINAPI -SaBlob_Create( - IN ULONG Count -); - -PDNS_BLOB -WINAPI -SaBlob_CreateFromIp4( - IN LPWSTR Name, - IN ULONG Count, - IN PIN_ADDR AddressArray -); - -VOID -WINAPI -SaBlob_Free(IN PDNS_BLOB Blob); - -PHOSTENT -WINAPI -SaBlob_CreateHostent( - IN OUT PULONG_PTR BufferPosition, - IN OUT PSIZE_T RemainingBufferSpace, - IN OUT PSIZE_T HostEntrySize, - IN PDNS_BLOB Blob, - IN DWORD StringType, - IN BOOLEAN Relative, - IN BOOLEAN BufferAllocated -); - -INT -WINAPI -SaBlob_WriteNameOrAlias( - IN PDNS_BLOB Blob, - IN LPWSTR String, - IN BOOLEAN IsAlias -); - -PDNS_BLOB -WINAPI -SaBlob_Query( - IN LPWSTR Name, - IN WORD DnsType, - IN ULONG Flags, - IN PVOID *Reserved, - IN DWORD AddressFamily -); - -/* - * string.c - */ -ULONG -WINAPI -Dns_StringCopy( - OUT PVOID Destination, - IN OUT PULONG DestinationSize, - IN PVOID String, - IN ULONG StringSize OPTIONAL, - IN DWORD InputType, - IN DWORD OutputType -); - -LPWSTR -WINAPI -Dns_CreateStringCopy_W(IN LPWSTR Name); - -ULONG -WINAPI -Dns_GetBufferLengthForStringCopy( - IN PVOID String, - IN ULONG Size OPTIONAL, - IN DWORD InputType, - IN DWORD OutputType -); - -/* - * straddr.c - */ -BOOLEAN -WINAPI -Dns_StringToAddressW( - OUT PVOID Address, - IN OUT PULONG AddressSize, - IN LPWSTR AddressName, - IN OUT PDWORD AddressFamily -); - -LPWSTR -WINAPI -Dns_Ip4AddressToReverseName_W( - OUT LPWSTR Name, - IN IN_ADDR Address -); - -LPWSTR -WINAPI -Dns_Ip6AddressToReverseName_W( - OUT LPWSTR Name, - IN IN6_ADDR Address -); - -BOOLEAN -WINAPI -Dns_ReverseNameToDnsAddr_W( - OUT PDNS_ADDRESS DnsAddr, - IN LPWSTR Name -); - -BOOLEAN -WINAPI -Dns_Ip4ReverseNameToAddress_W( - OUT PIN_ADDR Address, - IN LPWSTR Name -); - -#endif diff --git a/dll/win32/mswsock/dns/inc/windnsp.h b/dll/win32/mswsock/dns/inc/windnsp.h index 66cfbd83a12..d67855e56ab 100644 --- a/dll/win32/mswsock/dns/inc/windnsp.h +++ b/dll/win32/mswsock/dns/inc/windnsp.h @@ -26,143 +26,3 @@ DnsApiFree( ); /* EOF */ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNSAPI Header - * FILE: include/libs/dns/windnsp.h - * PURPOSE: DNSLIB Precompiled Header - */ - -PVOID -WINAPI -DnsApiAlloc( - IN DWORD Size -); - -PVOID -WINAPI -DnsQueryConfigAllocEx( - IN DNS_CONFIG_TYPE Config, - OUT PVOID pBuffer, - IN OUT PDWORD pBufferLength -); - -VOID -WINAPI -DnsApiFree( - IN PVOID pBuffer -); - -/* EOF */ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNSAPI Header - * FILE: include/libs/dns/windnsp.h - * PURPOSE: DNSLIB Precompiled Header - */ - -PVOID -WINAPI -DnsApiAlloc( - IN DWORD Size -); - -PVOID -WINAPI -DnsQueryConfigAllocEx( - IN DNS_CONFIG_TYPE Config, - OUT PVOID pBuffer, - IN OUT PDWORD pBufferLength -); - -VOID -WINAPI -DnsApiFree( - IN PVOID pBuffer -); - -/* EOF */ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNSAPI Header - * FILE: include/libs/dns/windnsp.h - * PURPOSE: DNSLIB Precompiled Header - */ - -PVOID -WINAPI -DnsApiAlloc( - IN DWORD Size -); - -PVOID -WINAPI -DnsQueryConfigAllocEx( - IN DNS_CONFIG_TYPE Config, - OUT PVOID pBuffer, - IN OUT PDWORD pBufferLength -); - -VOID -WINAPI -DnsApiFree( - IN PVOID pBuffer -); - -/* EOF */ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNSAPI Header - * FILE: include/libs/dns/windnsp.h - * PURPOSE: DNSLIB Precompiled Header - */ - -PVOID -WINAPI -DnsApiAlloc( - IN DWORD Size -); - -PVOID -WINAPI -DnsQueryConfigAllocEx( - IN DNS_CONFIG_TYPE Config, - OUT PVOID pBuffer, - IN OUT PDWORD pBufferLength -); - -VOID -WINAPI -DnsApiFree( - IN PVOID pBuffer -); - -/* EOF */ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNSAPI Header - * FILE: include/libs/dns/windnsp.h - * PURPOSE: DNSLIB Precompiled Header - */ - -PVOID -WINAPI -DnsApiAlloc( - IN DWORD Size -); - -PVOID -WINAPI -DnsQueryConfigAllocEx( - IN DNS_CONFIG_TYPE Config, - OUT PVOID pBuffer, - IN OUT PDWORD pBufferLength -); - -VOID -WINAPI -DnsApiFree( - IN PVOID pBuffer -); - -/* EOF */ diff --git a/dll/win32/mswsock/dns/ip6.c b/dll/win32/mswsock/dns/ip6.c index 11486427020..921fef41175 100644 --- a/dll/win32/mswsock/dns/ip6.c +++ b/dll/win32/mswsock/dns/ip6.c @@ -12,45 +12,3 @@ /* FUNCTIONS *****************************************************************/ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/ip6.c - * PURPOSE: Functions for dealing with IPv6 Specific issues. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/ip6.c - * PURPOSE: Functions for dealing with IPv6 Specific issues. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/ip6.c - * PURPOSE: Functions for dealing with IPv6 Specific issues. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - diff --git a/dll/win32/mswsock/dns/memory.c b/dll/win32/mswsock/dns/memory.c index 8db2f0abbb5..183088c86b7 100644 --- a/dll/win32/mswsock/dns/memory.c +++ b/dll/win32/mswsock/dns/memory.c @@ -64,201 +64,3 @@ Dns_AllocZero(IN SIZE_T Size) return Buffer; } -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/memory.c - * PURPOSE: DNS Memory Manager Implementation and Heap. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -typedef PVOID -(WINAPI *PDNS_ALLOC_FUNCTION)(IN SIZE_T Size); -typedef VOID -(WINAPI *PDNS_FREE_FUNCTION)(IN PVOID Buffer); - -PDNS_ALLOC_FUNCTION pDnsAllocFunction; -PDNS_FREE_FUNCTION pDnsFreeFunction; - -/* FUNCTIONS *****************************************************************/ - -VOID -WINAPI -Dns_Free(IN PVOID Address) -{ - /* Check if whoever imported us specified a special free function */ - if (pDnsFreeFunction) - { - /* Use it */ - pDnsFreeFunction(Address); - } - else - { - /* Use our own */ - LocalFree(Address); - } -} - -PVOID -WINAPI -Dns_AllocZero(IN SIZE_T Size) -{ - PVOID Buffer; - - /* Check if whoever imported us specified a special allocation function */ - if (pDnsAllocFunction) - { - /* Use it to allocate the memory */ - Buffer = pDnsAllocFunction(Size); - if (Buffer) - { - /* Zero it out */ - RtlZeroMemory(Buffer, Size); - } - } - else - { - /* Use our default */ - Buffer = LocalAlloc(LMEM_ZEROINIT, Size); - } - - /* Return the allocate pointer */ - return Buffer; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/memory.c - * PURPOSE: DNS Memory Manager Implementation and Heap. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -typedef PVOID -(WINAPI *PDNS_ALLOC_FUNCTION)(IN SIZE_T Size); -typedef VOID -(WINAPI *PDNS_FREE_FUNCTION)(IN PVOID Buffer); - -PDNS_ALLOC_FUNCTION pDnsAllocFunction; -PDNS_FREE_FUNCTION pDnsFreeFunction; - -/* FUNCTIONS *****************************************************************/ - -VOID -WINAPI -Dns_Free(IN PVOID Address) -{ - /* Check if whoever imported us specified a special free function */ - if (pDnsFreeFunction) - { - /* Use it */ - pDnsFreeFunction(Address); - } - else - { - /* Use our own */ - LocalFree(Address); - } -} - -PVOID -WINAPI -Dns_AllocZero(IN SIZE_T Size) -{ - PVOID Buffer; - - /* Check if whoever imported us specified a special allocation function */ - if (pDnsAllocFunction) - { - /* Use it to allocate the memory */ - Buffer = pDnsAllocFunction(Size); - if (Buffer) - { - /* Zero it out */ - RtlZeroMemory(Buffer, Size); - } - } - else - { - /* Use our default */ - Buffer = LocalAlloc(LMEM_ZEROINIT, Size); - } - - /* Return the allocate pointer */ - return Buffer; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/memory.c - * PURPOSE: DNS Memory Manager Implementation and Heap. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -typedef PVOID -(WINAPI *PDNS_ALLOC_FUNCTION)(IN SIZE_T Size); -typedef VOID -(WINAPI *PDNS_FREE_FUNCTION)(IN PVOID Buffer); - -PDNS_ALLOC_FUNCTION pDnsAllocFunction; -PDNS_FREE_FUNCTION pDnsFreeFunction; - -/* FUNCTIONS *****************************************************************/ - -VOID -WINAPI -Dns_Free(IN PVOID Address) -{ - /* Check if whoever imported us specified a special free function */ - if (pDnsFreeFunction) - { - /* Use it */ - pDnsFreeFunction(Address); - } - else - { - /* Use our own */ - LocalFree(Address); - } -} - -PVOID -WINAPI -Dns_AllocZero(IN SIZE_T Size) -{ - PVOID Buffer; - - /* Check if whoever imported us specified a special allocation function */ - if (pDnsAllocFunction) - { - /* Use it to allocate the memory */ - Buffer = pDnsAllocFunction(Size); - if (Buffer) - { - /* Zero it out */ - RtlZeroMemory(Buffer, Size); - } - } - else - { - /* Use our default */ - Buffer = LocalAlloc(LMEM_ZEROINIT, Size); - } - - /* Return the allocate pointer */ - return Buffer; -} - diff --git a/dll/win32/mswsock/dns/name.c b/dll/win32/mswsock/dns/name.c index 75fdbc925a5..4004912315e 100644 --- a/dll/win32/mswsock/dns/name.c +++ b/dll/win32/mswsock/dns/name.c @@ -12,45 +12,3 @@ /* FUNCTIONS *****************************************************************/ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/name.c - * PURPOSE: Functions dealing with DNS (Canonical, FQDN, Host) Names - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/name.c - * PURPOSE: Functions dealing with DNS (Canonical, FQDN, Host) Names - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/name.c - * PURPOSE: Functions dealing with DNS (Canonical, FQDN, Host) Names - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - diff --git a/dll/win32/mswsock/dns/print.c b/dll/win32/mswsock/dns/print.c index 956c4eaa03d..bead765eb3c 100644 --- a/dll/win32/mswsock/dns/print.c +++ b/dll/win32/mswsock/dns/print.c @@ -12,45 +12,3 @@ /* FUNCTIONS *****************************************************************/ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/print.c - * PURPOSE: Callback Functions for printing a variety of DNSLIB Structures - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/print.c - * PURPOSE: Callback Functions for printing a variety of DNSLIB Structures - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/print.c - * PURPOSE: Callback Functions for printing a variety of DNSLIB Structures - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - diff --git a/dll/win32/mswsock/dns/record.c b/dll/win32/mswsock/dns/record.c index 62f577d65e3..c0325a9b850 100644 --- a/dll/win32/mswsock/dns/record.c +++ b/dll/win32/mswsock/dns/record.c @@ -12,45 +12,3 @@ /* FUNCTIONS *****************************************************************/ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/record.c - * PURPOSE: Functions for managing DNS Record structures. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/record.c - * PURPOSE: Functions for managing DNS Record structures. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/record.c - * PURPOSE: Functions for managing DNS Record structures. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - diff --git a/dll/win32/mswsock/dns/rrprint.c b/dll/win32/mswsock/dns/rrprint.c index 1e302d4395e..29a58ff86ed 100644 --- a/dll/win32/mswsock/dns/rrprint.c +++ b/dll/win32/mswsock/dns/rrprint.c @@ -12,45 +12,3 @@ /* FUNCTIONS *****************************************************************/ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/rrprint.c - * PURPOSE: Callback functions for printing RR Structures for each Record. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/rrprint.c - * PURPOSE: Callback functions for printing RR Structures for each Record. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/rrprint.c - * PURPOSE: Callback functions for printing RR Structures for each Record. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - diff --git a/dll/win32/mswsock/dns/sablob.c b/dll/win32/mswsock/dns/sablob.c index ff1a9bac9f0..1e9b1845937 100644 --- a/dll/win32/mswsock/dns/sablob.c +++ b/dll/win32/mswsock/dns/sablob.c @@ -643,1938 +643,3 @@ Quickie: return DnsBlob; } -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/sablob.c - * PURPOSE: Functions for the Saved Answer Blob Implementation - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -PVOID -WINAPI -FlatBuf_Arg_ReserveAlignPointer(IN PVOID Position, - IN PSIZE_T FreeSize, - IN SIZE_T Size) -{ - /* Just a little helper that we use */ - return FlatBuf_Arg_Reserve(Position, FreeSize, Size, sizeof(PVOID)); -} - -PDNS_BLOB -WINAPI -SaBlob_Create(IN ULONG Count) -{ - PDNS_BLOB Blob; - PDNS_ARRAY DnsAddrArray; - - /* Allocate the blob */ - Blob = Dns_AllocZero(sizeof(DNS_BLOB)); - if (Blob) - { - /* Check if it'll hold any addresses */ - if (Count) - { - /* Create the DNS Address Array */ - DnsAddrArray = DnsAddrArray_Create(Count); - if (!DnsAddrArray) - { - /* Failure, free the blob */ - SaBlob_Free(Blob); - SetLastError(ERROR_OUTOFMEMORY); - } - else - { - /* Link it with the blob */ - Blob->DnsAddrArray = DnsAddrArray; - } - } - } - - /* Return the blob */ - return Blob; -} - -PDNS_BLOB -WINAPI -SaBlob_CreateFromIp4(IN LPWSTR Name, - IN ULONG Count, - IN PIN_ADDR AddressArray) -{ - PDNS_BLOB Blob; - LPWSTR NameCopy; - ULONG i; - - /* Create the blob */ - Blob = SaBlob_Create(Count); - if (!Blob) goto Quickie; - - /* If we have a name */ - if (Name) - { - /* Create a copy of it */ - NameCopy = Dns_CreateStringCopy_W(Name); - if (!NameCopy) goto Quickie; - - /* Save the pointer to the name */ - Blob->Name = NameCopy; - } - - /* Loop all the addresses */ - for (i = 0; i < Count; i++) - { - /* Add an entry for this address */ - DnsAddrArray_AddIp4(Blob->DnsAddrArray, AddressArray[i], IpV4Address); - } - - /* Return the blob */ - return Blob; - -Quickie: - /* Free the blob, set error and fail */ - SaBlob_Free(Blob); - SetLastError(ERROR_OUTOFMEMORY); - return NULL; -} - -VOID -WINAPI -SaBlob_Free(IN PDNS_BLOB Blob) -{ - /* Make sure we got a blob */ - if (Blob) - { - /* Free the name */ - Dns_Free(Blob->Name); - - /* Loop the aliases */ - while (Blob->AliasCount) - { - /* Free the alias */ - Dns_Free(Blob->Aliases[Blob->AliasCount]); - - /* Decrease number of aliases */ - Blob->AliasCount--; - } - - /* Free the DNS Address Array */ - DnsAddrArray_Free(Blob->DnsAddrArray); - - /* Free the blob itself */ - Dns_Free(Blob); - } -} - -PHOSTENT -WINAPI -SaBlob_CreateHostent(IN OUT PULONG_PTR BufferPosition, - IN OUT PSIZE_T FreeBufferSpace, - IN OUT PSIZE_T HostEntrySize, - IN PDNS_BLOB Blob, - IN DWORD StringType, - IN BOOLEAN Relative, - IN BOOLEAN BufferAllocated) -{ - PDNS_ARRAY DnsAddrArray = Blob->DnsAddrArray; - ULONG AliasCount = Blob->AliasCount; - WORD AddressFamily = AF_UNSPEC; - ULONG AddressCount = 0, AddressSize = 0, TotalSize, NamePointerSize; - ULONG AliasPointerSize; - PDNS_FAMILY_INFO FamilyInfo = NULL; - ULONG StringLength = 0; - ULONG i; - ULONG HostentSize = 0; - PHOSTENT Hostent = NULL; - ULONG_PTR HostentPtr; - PVOID CurrentAddress; - - /* Check if we actually have any addresses */ - if (DnsAddrArray) - { - /* Get the address family */ - AddressFamily = DnsAddrArray->Addresses[0].AddressFamily; - - /* Get family information */ - FamilyInfo = FamilyInfo_GetForFamily(AddressFamily); - - /* Save the current address count and their size */ - AddressCount = DnsAddrArray->UsedAddresses; - AddressSize = FamilyInfo->AddressSize; - } - - /* Calculate total size for all the addresses, and their pointers */ - TotalSize = AddressSize * AddressCount; - NamePointerSize = AddressCount * sizeof(PVOID) + sizeof(PVOID); - - /* Check if we have a name */ - if (Blob->Name) - { - /* Find out the size we'll need for a copy */ - StringLength = (Dns_GetBufferLengthForStringCopy(Blob->Name, - 0, - UnicodeString, - StringType) + 1) & ~1; - } - - /* Now do the same for the aliases */ - for (i = AliasCount; i; i--) - { - /* Find out the size we'll need for a copy */ - HostentSize += (Dns_GetBufferLengthForStringCopy(Blob->Aliases[i], - 0, - UnicodeString, - StringType) + 1) & ~1; - } - - /* Find out how much the pointers will take */ - AliasPointerSize = AliasCount * sizeof(PVOID) + sizeof(PVOID); - - /* Calculate Hostent Size */ - HostentSize += TotalSize + - NamePointerSize + - AliasPointerSize + - StringLength + - sizeof(HOSTENT); - - /* Check if we already have a buffer */ - if (!BufferAllocated) - { - /* We don't, allocate space ourselves */ - HostentPtr = (ULONG_PTR)Dns_AllocZero(HostentSize); - } - else - { - /* We do, so allocate space in the buffer */ - HostentPtr = (ULONG_PTR)FlatBuf_Arg_ReserveAlignPointer(BufferPosition, - FreeBufferSpace, - HostentSize); - } - - /* Make sure we got space */ - if (HostentPtr) - { - /* Initialize it */ - Hostent = Hostent_Init((PVOID)&HostentPtr, - AddressFamily, - AddressSize, - AddressCount, - AliasCount); - } - - /* Loop the addresses */ - for (i = 0; i < AddressCount; i++) - { - /* Get the pointer of the current address */ - CurrentAddress = (PVOID)((ULONG_PTR)&DnsAddrArray->Addresses[i] + - FamilyInfo->AddressOffset); - - /* Write the pointer */ - Hostent->h_addr_list[i] = (PCHAR)HostentPtr; - - /* Copy the address */ - RtlCopyMemory((PVOID)HostentPtr, CurrentAddress, AddressSize); - - /* Advance the buffer */ - HostentPtr += AddressSize; - } - - /* Check if we have a name */ - if (Blob->Name) - { - /* Align our current position */ - HostentPtr += 1 & ~1; - - /* Save our name here */ - Hostent->h_name = (LPSTR)HostentPtr; - - /* Now copy it in the blob */ - HostentPtr += Dns_StringCopy((PVOID)HostentPtr, - NULL, - Blob->Name, - 0, - UnicodeString, - StringType); - } - - /* Loop the Aliases */ - for (i = AliasCount; i; i--) - { - /* Align our current position */ - HostentPtr += 1 & ~1; - - /* Save our alias here */ - Hostent->h_aliases[i] = (LPSTR)HostentPtr; - - /* Now copy it in the blob */ - HostentPtr += Dns_StringCopy((PVOID)HostentPtr, - NULL, - Blob->Aliases[i], - 0, - UnicodeString, - StringType); - } - - /* Check if the caller didn't have a buffer */ - if (!BufferAllocated) - { - /* Return the size; not needed if we had a blob, since it's internal */ - *HostEntrySize = *BufferPosition - (ULONG_PTR)HostentPtr; - } - - /* Convert to Offsets if requested */ - if(Relative) Hostent_ConvertToOffsets(Hostent); - - /* Return the full, complete, hostent */ - return Hostent; -} - -INT -WINAPI -SaBlob_WriteNameOrAlias(IN PDNS_BLOB Blob, - IN LPWSTR String, - IN BOOLEAN IsAlias) -{ - /* Check if this is an alias */ - if (!IsAlias) - { - /* It's not. Simply create a copy of the string */ - Blob->Name = Dns_CreateStringCopy_W(String); - if (!Blob->Name) return GetLastError(); - } - else - { - /* Does it have a name, and less then 8 aliases? */ - if ((Blob->Name) && (Blob->AliasCount <= 8)) - { - /* Yup, create a copy of the string and increase the alias count */ - Blob->Aliases[Blob->AliasCount] = Dns_CreateStringCopy_W(String); - Blob->AliasCount++; - } - else - { - /* Invalid request! */ - return ERROR_MORE_DATA; - } - } - - /* Return Success */ - return ERROR_SUCCESS; -} - -INT -WINAPI -SaBlob_WriteAddress(IN PDNS_BLOB Blob, - OUT PDNS_ADDRESS DnsAddr) -{ - /* Check if we have an array yet */ - if (!Blob->DnsAddrArray) - { - /* Allocate one! */ - Blob->DnsAddrArray = DnsAddrArray_Create(1); - if (!Blob->DnsAddrArray) return ERROR_OUTOFMEMORY; - } - - /* Add this address */ - return DnsAddrArray_AddAddr(Blob->DnsAddrArray, DnsAddr, AF_UNSPEC, 0) ? - ERROR_SUCCESS: - ERROR_MORE_DATA; -} - -BOOLEAN -WINAPI -SaBlob_IsSupportedAddrType(WORD DnsType) -{ - /* Check for valid Types that we support */ - return (DnsType == DNS_TYPE_A || - DnsType == DNS_TYPE_ATMA || - DnsType == DNS_TYPE_AAAA); -} - -INT -WINAPI -SaBlob_WriteRecords(OUT PDNS_BLOB Blob, - IN PDNS_RECORD DnsRecord, - IN BOOLEAN DoAlias) -{ - DNS_ADDRESS DnsAddress; - INT ErrorCode = STATUS_INVALID_PARAMETER; - BOOLEAN WroteOnce = FALSE; - - /* Zero out the Address */ - RtlZeroMemory(&DnsAddress, sizeof(DnsAddress)); - - /* Loop through all the Records */ - while (DnsRecord) - { - /* Is this not an answer? */ - if (DnsRecord->Flags.S.Section != DNSREC_ANSWER) - { - /* Then simply move on to the next DNS Record */ - DnsRecord = DnsRecord->pNext; - continue; - } - - /* Check the type of thsi record */ - switch(DnsRecord->wType) - { - /* Regular IPv4, v6 or ATM Record */ - case DNS_TYPE_A: - case DNS_TYPE_AAAA: - case DNS_TYPE_ATMA: - - /* Create a DNS Address from the record */ - DnsAddr_BuildFromDnsRecord(DnsRecord, &DnsAddress); - - /* Add it to the DNS Blob */ - ErrorCode = SaBlob_WriteAddress(Blob, &DnsAddress); - - /* Add the name, if needed */ - if ((DoAlias) && - (!WroteOnce) && - (!Blob->Name) && - (DnsRecord->pName)) - { - /* Write the name from the DNS Record */ - ErrorCode = SaBlob_WriteNameOrAlias(Blob, - DnsRecord->pName, - FALSE); - WroteOnce = TRUE; - } - break; - - case DNS_TYPE_CNAME: - - /* Just write the alias name */ - ErrorCode = SaBlob_WriteNameOrAlias(Blob, - DnsRecord->pName, - TRUE); - break; - - case DNS_TYPE_PTR: - - /* Check if we already have a name */ - if (Blob->Name) - { - /* We don't, so add this as a name */ - ErrorCode = SaBlob_WriteNameOrAlias(Blob, - DnsRecord->pName, - FALSE); - } - else - { - /* We do, so add it as an alias */ - ErrorCode = SaBlob_WriteNameOrAlias(Blob, - DnsRecord->pName, - TRUE); - } - break; - default: - break; - } - - /* Next record */ - DnsRecord = DnsRecord->pNext; - } - - /* Return error code */ - return ErrorCode; -} - -PDNS_BLOB -WINAPI -SaBlob_CreateFromRecords(IN PDNS_RECORD DnsRecord, - IN BOOLEAN DoAliases, - IN DWORD DnsType) -{ - PDNS_RECORD LocalDnsRecord; - ULONG ProcessedCount = 0; - PDNS_BLOB DnsBlob; - INT ErrorCode; - DNS_ADDRESS DnsAddress; - - /* Find out how many DNS Addresses to allocate */ - LocalDnsRecord = DnsRecord; - while (LocalDnsRecord) - { - /* Make sure this record is an answer */ - if ((LocalDnsRecord->Flags.S.Section == DNSREC_ANSWER) && - (SaBlob_IsSupportedAddrType(LocalDnsRecord->wType))) - { - /* Increase number of records to process */ - ProcessedCount++; - } - - /* Move to the next record */ - LocalDnsRecord = LocalDnsRecord->pNext; - } - - /* Create the DNS Blob */ - DnsBlob = SaBlob_Create(ProcessedCount); - if (!DnsBlob) - { - /* Fail */ - ErrorCode = GetLastError(); - goto Quickie; - } - - /* Write the record to the DNS Blob */ - ErrorCode = SaBlob_WriteRecords(DnsBlob, DnsRecord, TRUE); - if (ErrorCode != NO_ERROR) - { - /* We failed... but do we still have valid data? */ - if ((DnsBlob->Name) || (DnsBlob->AliasCount)) - { - /* We'll just assume success then */ - ErrorCode = NO_ERROR; - } - else - { - /* Ok, last chance..do you have a DNS Address Array? */ - if ((DnsBlob->DnsAddrArray) && - (DnsBlob->DnsAddrArray->UsedAddresses)) - { - /* Boy are you lucky! */ - ErrorCode = NO_ERROR; - } - } - - /* Buh-bye! */ - goto Quickie; - } - - /* Check if this is a PTR record */ - if ((DnsRecord->wType == DNS_TYPE_PTR) || - ((DnsType == DNS_TYPE_PTR) && - (DnsRecord->wType == DNS_TYPE_CNAME) && - (DnsRecord->Flags.S.Section == DNSREC_ANSWER))) - { - /* Get a DNS Address Structure */ - if (Dns_ReverseNameToDnsAddr_W(&DnsAddress, DnsRecord->pName)) - { - /* Add it to the Blob */ - if (SaBlob_WriteAddress(DnsBlob, &DnsAddress)) ErrorCode = NO_ERROR; - } - } - - /* Ok...do we still not have a name? */ - if (!(DnsBlob->Name) && (DoAliases) && (LocalDnsRecord)) - { - /* We have an local DNS Record, so just use it to write the name */ - ErrorCode = SaBlob_WriteNameOrAlias(DnsBlob, - LocalDnsRecord->pName, - FALSE); - } - -Quickie: - /* Check error code */ - if (ErrorCode != NO_ERROR) - { - /* Free the blob and set the error */ - SaBlob_Free(DnsBlob); - DnsBlob = NULL; - SetLastError(ErrorCode); - } - - /* Return */ - return DnsBlob; -} - -PDNS_BLOB -WINAPI -SaBlob_Query(IN LPWSTR Name, - IN WORD DnsType, - IN ULONG Flags, - IN PVOID *Reserved, - IN DWORD AddressFamily) -{ - PDNS_RECORD DnsRecord = NULL; - INT ErrorCode; - PDNS_BLOB DnsBlob = NULL; - LPWSTR LocalName, LocalNameCopy; - - /* If they want reserved data back, clear it out in case we fail */ - if (Reserved) *Reserved = NULL; - - /* Query DNS */ - ErrorCode = DnsQuery_W(Name, - DnsType, - Flags, - NULL, - &DnsRecord, - Reserved); - if (ErrorCode != ERROR_SUCCESS) - { - /* We failed... did the caller use reserved data? */ - if (Reserved && *Reserved) - { - /* He did, and it was valid. Free it */ - DnsApiFree(*Reserved); - *Reserved = NULL; - } - - /* Normalize error code */ - if (ErrorCode == RPC_S_SERVER_UNAVAILABLE) ErrorCode = WSATRY_AGAIN; - goto Quickie; - } - - /* Now create the Blob from the DNS Records */ - DnsBlob = SaBlob_CreateFromRecords(DnsRecord, TRUE, DnsType); - if (!DnsBlob) - { - /* Failed, get error code */ - ErrorCode = GetLastError(); - goto Quickie; - } - - /* Make sure it has a name */ - if (!DnsBlob->Name) - { - /* It doesn't, fail */ - ErrorCode = DNS_INFO_NO_RECORDS; - goto Quickie; - } - - /* Check if the name is local or loopback */ - if (!(DnsNameCompare_W(DnsBlob->Name, L"localhost")) && - !(DnsNameCompare_W(DnsBlob->Name, L"loopback"))) - { - /* Nothing left to do, exit! */ - goto Quickie; - } - - /* This is a local name...query it */ - DnsQueryConfig(DnsConfigFullHostName_W, - DNS_CONFIG_FLAG_ALLOC, - NULL, - NULL, - &LocalName, - 0); - if (LocalName) - { - /* Create a copy for the caller */ - LocalNameCopy = Dns_CreateStringCopy_W(LocalName); - if (LocalNameCopy) - { - /* Overwrite the one in the blob */ - DnsBlob->Name = LocalNameCopy; - } - else - { - /* We failed to make a copy, free memory */ - DnsApiFree(LocalName); - } - } - -Quickie: - /* Free the DNS Record if we have one */ - if (DnsRecord) DnsRecordListFree(DnsRecord, DnsFreeRecordList); - - /* Check if this is a failure path with an active blob */ - if ((ErrorCode != ERROR_SUCCESS) && (DnsBlob)) - { - /* Free the blob */ - SaBlob_Free(DnsBlob); - DnsBlob = NULL; - } - - /* Set the last error and return */ - SetLastError(ErrorCode); - return DnsBlob; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/sablob.c - * PURPOSE: Functions for the Saved Answer Blob Implementation - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -PVOID -WINAPI -FlatBuf_Arg_ReserveAlignPointer(IN PVOID Position, - IN PSIZE_T FreeSize, - IN SIZE_T Size) -{ - /* Just a little helper that we use */ - return FlatBuf_Arg_Reserve(Position, FreeSize, Size, sizeof(PVOID)); -} - -PDNS_BLOB -WINAPI -SaBlob_Create(IN ULONG Count) -{ - PDNS_BLOB Blob; - PDNS_ARRAY DnsAddrArray; - - /* Allocate the blob */ - Blob = Dns_AllocZero(sizeof(DNS_BLOB)); - if (Blob) - { - /* Check if it'll hold any addresses */ - if (Count) - { - /* Create the DNS Address Array */ - DnsAddrArray = DnsAddrArray_Create(Count); - if (!DnsAddrArray) - { - /* Failure, free the blob */ - SaBlob_Free(Blob); - SetLastError(ERROR_OUTOFMEMORY); - } - else - { - /* Link it with the blob */ - Blob->DnsAddrArray = DnsAddrArray; - } - } - } - - /* Return the blob */ - return Blob; -} - -PDNS_BLOB -WINAPI -SaBlob_CreateFromIp4(IN LPWSTR Name, - IN ULONG Count, - IN PIN_ADDR AddressArray) -{ - PDNS_BLOB Blob; - LPWSTR NameCopy; - ULONG i; - - /* Create the blob */ - Blob = SaBlob_Create(Count); - if (!Blob) goto Quickie; - - /* If we have a name */ - if (Name) - { - /* Create a copy of it */ - NameCopy = Dns_CreateStringCopy_W(Name); - if (!NameCopy) goto Quickie; - - /* Save the pointer to the name */ - Blob->Name = NameCopy; - } - - /* Loop all the addresses */ - for (i = 0; i < Count; i++) - { - /* Add an entry for this address */ - DnsAddrArray_AddIp4(Blob->DnsAddrArray, AddressArray[i], IpV4Address); - } - - /* Return the blob */ - return Blob; - -Quickie: - /* Free the blob, set error and fail */ - SaBlob_Free(Blob); - SetLastError(ERROR_OUTOFMEMORY); - return NULL; -} - -VOID -WINAPI -SaBlob_Free(IN PDNS_BLOB Blob) -{ - /* Make sure we got a blob */ - if (Blob) - { - /* Free the name */ - Dns_Free(Blob->Name); - - /* Loop the aliases */ - while (Blob->AliasCount) - { - /* Free the alias */ - Dns_Free(Blob->Aliases[Blob->AliasCount]); - - /* Decrease number of aliases */ - Blob->AliasCount--; - } - - /* Free the DNS Address Array */ - DnsAddrArray_Free(Blob->DnsAddrArray); - - /* Free the blob itself */ - Dns_Free(Blob); - } -} - -PHOSTENT -WINAPI -SaBlob_CreateHostent(IN OUT PULONG_PTR BufferPosition, - IN OUT PSIZE_T FreeBufferSpace, - IN OUT PSIZE_T HostEntrySize, - IN PDNS_BLOB Blob, - IN DWORD StringType, - IN BOOLEAN Relative, - IN BOOLEAN BufferAllocated) -{ - PDNS_ARRAY DnsAddrArray = Blob->DnsAddrArray; - ULONG AliasCount = Blob->AliasCount; - WORD AddressFamily = AF_UNSPEC; - ULONG AddressCount = 0, AddressSize = 0, TotalSize, NamePointerSize; - ULONG AliasPointerSize; - PDNS_FAMILY_INFO FamilyInfo = NULL; - ULONG StringLength = 0; - ULONG i; - ULONG HostentSize = 0; - PHOSTENT Hostent = NULL; - ULONG_PTR HostentPtr; - PVOID CurrentAddress; - - /* Check if we actually have any addresses */ - if (DnsAddrArray) - { - /* Get the address family */ - AddressFamily = DnsAddrArray->Addresses[0].AddressFamily; - - /* Get family information */ - FamilyInfo = FamilyInfo_GetForFamily(AddressFamily); - - /* Save the current address count and their size */ - AddressCount = DnsAddrArray->UsedAddresses; - AddressSize = FamilyInfo->AddressSize; - } - - /* Calculate total size for all the addresses, and their pointers */ - TotalSize = AddressSize * AddressCount; - NamePointerSize = AddressCount * sizeof(PVOID) + sizeof(PVOID); - - /* Check if we have a name */ - if (Blob->Name) - { - /* Find out the size we'll need for a copy */ - StringLength = (Dns_GetBufferLengthForStringCopy(Blob->Name, - 0, - UnicodeString, - StringType) + 1) & ~1; - } - - /* Now do the same for the aliases */ - for (i = AliasCount; i; i--) - { - /* Find out the size we'll need for a copy */ - HostentSize += (Dns_GetBufferLengthForStringCopy(Blob->Aliases[i], - 0, - UnicodeString, - StringType) + 1) & ~1; - } - - /* Find out how much the pointers will take */ - AliasPointerSize = AliasCount * sizeof(PVOID) + sizeof(PVOID); - - /* Calculate Hostent Size */ - HostentSize += TotalSize + - NamePointerSize + - AliasPointerSize + - StringLength + - sizeof(HOSTENT); - - /* Check if we already have a buffer */ - if (!BufferAllocated) - { - /* We don't, allocate space ourselves */ - HostentPtr = (ULONG_PTR)Dns_AllocZero(HostentSize); - } - else - { - /* We do, so allocate space in the buffer */ - HostentPtr = (ULONG_PTR)FlatBuf_Arg_ReserveAlignPointer(BufferPosition, - FreeBufferSpace, - HostentSize); - } - - /* Make sure we got space */ - if (HostentPtr) - { - /* Initialize it */ - Hostent = Hostent_Init((PVOID)&HostentPtr, - AddressFamily, - AddressSize, - AddressCount, - AliasCount); - } - - /* Loop the addresses */ - for (i = 0; i < AddressCount; i++) - { - /* Get the pointer of the current address */ - CurrentAddress = (PVOID)((ULONG_PTR)&DnsAddrArray->Addresses[i] + - FamilyInfo->AddressOffset); - - /* Write the pointer */ - Hostent->h_addr_list[i] = (PCHAR)HostentPtr; - - /* Copy the address */ - RtlCopyMemory((PVOID)HostentPtr, CurrentAddress, AddressSize); - - /* Advance the buffer */ - HostentPtr += AddressSize; - } - - /* Check if we have a name */ - if (Blob->Name) - { - /* Align our current position */ - HostentPtr += 1 & ~1; - - /* Save our name here */ - Hostent->h_name = (LPSTR)HostentPtr; - - /* Now copy it in the blob */ - HostentPtr += Dns_StringCopy((PVOID)HostentPtr, - NULL, - Blob->Name, - 0, - UnicodeString, - StringType); - } - - /* Loop the Aliases */ - for (i = AliasCount; i; i--) - { - /* Align our current position */ - HostentPtr += 1 & ~1; - - /* Save our alias here */ - Hostent->h_aliases[i] = (LPSTR)HostentPtr; - - /* Now copy it in the blob */ - HostentPtr += Dns_StringCopy((PVOID)HostentPtr, - NULL, - Blob->Aliases[i], - 0, - UnicodeString, - StringType); - } - - /* Check if the caller didn't have a buffer */ - if (!BufferAllocated) - { - /* Return the size; not needed if we had a blob, since it's internal */ - *HostEntrySize = *BufferPosition - (ULONG_PTR)HostentPtr; - } - - /* Convert to Offsets if requested */ - if(Relative) Hostent_ConvertToOffsets(Hostent); - - /* Return the full, complete, hostent */ - return Hostent; -} - -INT -WINAPI -SaBlob_WriteNameOrAlias(IN PDNS_BLOB Blob, - IN LPWSTR String, - IN BOOLEAN IsAlias) -{ - /* Check if this is an alias */ - if (!IsAlias) - { - /* It's not. Simply create a copy of the string */ - Blob->Name = Dns_CreateStringCopy_W(String); - if (!Blob->Name) return GetLastError(); - } - else - { - /* Does it have a name, and less then 8 aliases? */ - if ((Blob->Name) && (Blob->AliasCount <= 8)) - { - /* Yup, create a copy of the string and increase the alias count */ - Blob->Aliases[Blob->AliasCount] = Dns_CreateStringCopy_W(String); - Blob->AliasCount++; - } - else - { - /* Invalid request! */ - return ERROR_MORE_DATA; - } - } - - /* Return Success */ - return ERROR_SUCCESS; -} - -INT -WINAPI -SaBlob_WriteAddress(IN PDNS_BLOB Blob, - OUT PDNS_ADDRESS DnsAddr) -{ - /* Check if we have an array yet */ - if (!Blob->DnsAddrArray) - { - /* Allocate one! */ - Blob->DnsAddrArray = DnsAddrArray_Create(1); - if (!Blob->DnsAddrArray) return ERROR_OUTOFMEMORY; - } - - /* Add this address */ - return DnsAddrArray_AddAddr(Blob->DnsAddrArray, DnsAddr, AF_UNSPEC, 0) ? - ERROR_SUCCESS: - ERROR_MORE_DATA; -} - -BOOLEAN -WINAPI -SaBlob_IsSupportedAddrType(WORD DnsType) -{ - /* Check for valid Types that we support */ - return (DnsType == DNS_TYPE_A || - DnsType == DNS_TYPE_ATMA || - DnsType == DNS_TYPE_AAAA); -} - -INT -WINAPI -SaBlob_WriteRecords(OUT PDNS_BLOB Blob, - IN PDNS_RECORD DnsRecord, - IN BOOLEAN DoAlias) -{ - DNS_ADDRESS DnsAddress; - INT ErrorCode = STATUS_INVALID_PARAMETER; - BOOLEAN WroteOnce = FALSE; - - /* Zero out the Address */ - RtlZeroMemory(&DnsAddress, sizeof(DnsAddress)); - - /* Loop through all the Records */ - while (DnsRecord) - { - /* Is this not an answer? */ - if (DnsRecord->Flags.S.Section != DNSREC_ANSWER) - { - /* Then simply move on to the next DNS Record */ - DnsRecord = DnsRecord->pNext; - continue; - } - - /* Check the type of thsi record */ - switch(DnsRecord->wType) - { - /* Regular IPv4, v6 or ATM Record */ - case DNS_TYPE_A: - case DNS_TYPE_AAAA: - case DNS_TYPE_ATMA: - - /* Create a DNS Address from the record */ - DnsAddr_BuildFromDnsRecord(DnsRecord, &DnsAddress); - - /* Add it to the DNS Blob */ - ErrorCode = SaBlob_WriteAddress(Blob, &DnsAddress); - - /* Add the name, if needed */ - if ((DoAlias) && - (!WroteOnce) && - (!Blob->Name) && - (DnsRecord->pName)) - { - /* Write the name from the DNS Record */ - ErrorCode = SaBlob_WriteNameOrAlias(Blob, - DnsRecord->pName, - FALSE); - WroteOnce = TRUE; - } - break; - - case DNS_TYPE_CNAME: - - /* Just write the alias name */ - ErrorCode = SaBlob_WriteNameOrAlias(Blob, - DnsRecord->pName, - TRUE); - break; - - case DNS_TYPE_PTR: - - /* Check if we already have a name */ - if (Blob->Name) - { - /* We don't, so add this as a name */ - ErrorCode = SaBlob_WriteNameOrAlias(Blob, - DnsRecord->pName, - FALSE); - } - else - { - /* We do, so add it as an alias */ - ErrorCode = SaBlob_WriteNameOrAlias(Blob, - DnsRecord->pName, - TRUE); - } - break; - default: - break; - } - - /* Next record */ - DnsRecord = DnsRecord->pNext; - } - - /* Return error code */ - return ErrorCode; -} - -PDNS_BLOB -WINAPI -SaBlob_CreateFromRecords(IN PDNS_RECORD DnsRecord, - IN BOOLEAN DoAliases, - IN DWORD DnsType) -{ - PDNS_RECORD LocalDnsRecord; - ULONG ProcessedCount = 0; - PDNS_BLOB DnsBlob; - INT ErrorCode; - DNS_ADDRESS DnsAddress; - - /* Find out how many DNS Addresses to allocate */ - LocalDnsRecord = DnsRecord; - while (LocalDnsRecord) - { - /* Make sure this record is an answer */ - if ((LocalDnsRecord->Flags.S.Section == DNSREC_ANSWER) && - (SaBlob_IsSupportedAddrType(LocalDnsRecord->wType))) - { - /* Increase number of records to process */ - ProcessedCount++; - } - - /* Move to the next record */ - LocalDnsRecord = LocalDnsRecord->pNext; - } - - /* Create the DNS Blob */ - DnsBlob = SaBlob_Create(ProcessedCount); - if (!DnsBlob) - { - /* Fail */ - ErrorCode = GetLastError(); - goto Quickie; - } - - /* Write the record to the DNS Blob */ - ErrorCode = SaBlob_WriteRecords(DnsBlob, DnsRecord, TRUE); - if (ErrorCode != NO_ERROR) - { - /* We failed... but do we still have valid data? */ - if ((DnsBlob->Name) || (DnsBlob->AliasCount)) - { - /* We'll just assume success then */ - ErrorCode = NO_ERROR; - } - else - { - /* Ok, last chance..do you have a DNS Address Array? */ - if ((DnsBlob->DnsAddrArray) && - (DnsBlob->DnsAddrArray->UsedAddresses)) - { - /* Boy are you lucky! */ - ErrorCode = NO_ERROR; - } - } - - /* Buh-bye! */ - goto Quickie; - } - - /* Check if this is a PTR record */ - if ((DnsRecord->wType == DNS_TYPE_PTR) || - ((DnsType == DNS_TYPE_PTR) && - (DnsRecord->wType == DNS_TYPE_CNAME) && - (DnsRecord->Flags.S.Section == DNSREC_ANSWER))) - { - /* Get a DNS Address Structure */ - if (Dns_ReverseNameToDnsAddr_W(&DnsAddress, DnsRecord->pName)) - { - /* Add it to the Blob */ - if (SaBlob_WriteAddress(DnsBlob, &DnsAddress)) ErrorCode = NO_ERROR; - } - } - - /* Ok...do we still not have a name? */ - if (!(DnsBlob->Name) && (DoAliases) && (LocalDnsRecord)) - { - /* We have an local DNS Record, so just use it to write the name */ - ErrorCode = SaBlob_WriteNameOrAlias(DnsBlob, - LocalDnsRecord->pName, - FALSE); - } - -Quickie: - /* Check error code */ - if (ErrorCode != NO_ERROR) - { - /* Free the blob and set the error */ - SaBlob_Free(DnsBlob); - DnsBlob = NULL; - SetLastError(ErrorCode); - } - - /* Return */ - return DnsBlob; -} - -PDNS_BLOB -WINAPI -SaBlob_Query(IN LPWSTR Name, - IN WORD DnsType, - IN ULONG Flags, - IN PVOID *Reserved, - IN DWORD AddressFamily) -{ - PDNS_RECORD DnsRecord = NULL; - INT ErrorCode; - PDNS_BLOB DnsBlob = NULL; - LPWSTR LocalName, LocalNameCopy; - - /* If they want reserved data back, clear it out in case we fail */ - if (Reserved) *Reserved = NULL; - - /* Query DNS */ - ErrorCode = DnsQuery_W(Name, - DnsType, - Flags, - NULL, - &DnsRecord, - Reserved); - if (ErrorCode != ERROR_SUCCESS) - { - /* We failed... did the caller use reserved data? */ - if (Reserved && *Reserved) - { - /* He did, and it was valid. Free it */ - DnsApiFree(*Reserved); - *Reserved = NULL; - } - - /* Normalize error code */ - if (ErrorCode == RPC_S_SERVER_UNAVAILABLE) ErrorCode = WSATRY_AGAIN; - goto Quickie; - } - - /* Now create the Blob from the DNS Records */ - DnsBlob = SaBlob_CreateFromRecords(DnsRecord, TRUE, DnsType); - if (!DnsBlob) - { - /* Failed, get error code */ - ErrorCode = GetLastError(); - goto Quickie; - } - - /* Make sure it has a name */ - if (!DnsBlob->Name) - { - /* It doesn't, fail */ - ErrorCode = DNS_INFO_NO_RECORDS; - goto Quickie; - } - - /* Check if the name is local or loopback */ - if (!(DnsNameCompare_W(DnsBlob->Name, L"localhost")) && - !(DnsNameCompare_W(DnsBlob->Name, L"loopback"))) - { - /* Nothing left to do, exit! */ - goto Quickie; - } - - /* This is a local name...query it */ - DnsQueryConfig(DnsConfigFullHostName_W, - DNS_CONFIG_FLAG_ALLOC, - NULL, - NULL, - &LocalName, - 0); - if (LocalName) - { - /* Create a copy for the caller */ - LocalNameCopy = Dns_CreateStringCopy_W(LocalName); - if (LocalNameCopy) - { - /* Overwrite the one in the blob */ - DnsBlob->Name = LocalNameCopy; - } - else - { - /* We failed to make a copy, free memory */ - DnsApiFree(LocalName); - } - } - -Quickie: - /* Free the DNS Record if we have one */ - if (DnsRecord) DnsRecordListFree(DnsRecord, DnsFreeRecordList); - - /* Check if this is a failure path with an active blob */ - if ((ErrorCode != ERROR_SUCCESS) && (DnsBlob)) - { - /* Free the blob */ - SaBlob_Free(DnsBlob); - DnsBlob = NULL; - } - - /* Set the last error and return */ - SetLastError(ErrorCode); - return DnsBlob; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/sablob.c - * PURPOSE: Functions for the Saved Answer Blob Implementation - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -PVOID -WINAPI -FlatBuf_Arg_ReserveAlignPointer(IN PVOID Position, - IN PSIZE_T FreeSize, - IN SIZE_T Size) -{ - /* Just a little helper that we use */ - return FlatBuf_Arg_Reserve(Position, FreeSize, Size, sizeof(PVOID)); -} - -PDNS_BLOB -WINAPI -SaBlob_Create(IN ULONG Count) -{ - PDNS_BLOB Blob; - PDNS_ARRAY DnsAddrArray; - - /* Allocate the blob */ - Blob = Dns_AllocZero(sizeof(DNS_BLOB)); - if (Blob) - { - /* Check if it'll hold any addresses */ - if (Count) - { - /* Create the DNS Address Array */ - DnsAddrArray = DnsAddrArray_Create(Count); - if (!DnsAddrArray) - { - /* Failure, free the blob */ - SaBlob_Free(Blob); - SetLastError(ERROR_OUTOFMEMORY); - } - else - { - /* Link it with the blob */ - Blob->DnsAddrArray = DnsAddrArray; - } - } - } - - /* Return the blob */ - return Blob; -} - -PDNS_BLOB -WINAPI -SaBlob_CreateFromIp4(IN LPWSTR Name, - IN ULONG Count, - IN PIN_ADDR AddressArray) -{ - PDNS_BLOB Blob; - LPWSTR NameCopy; - ULONG i; - - /* Create the blob */ - Blob = SaBlob_Create(Count); - if (!Blob) goto Quickie; - - /* If we have a name */ - if (Name) - { - /* Create a copy of it */ - NameCopy = Dns_CreateStringCopy_W(Name); - if (!NameCopy) goto Quickie; - - /* Save the pointer to the name */ - Blob->Name = NameCopy; - } - - /* Loop all the addresses */ - for (i = 0; i < Count; i++) - { - /* Add an entry for this address */ - DnsAddrArray_AddIp4(Blob->DnsAddrArray, AddressArray[i], IpV4Address); - } - - /* Return the blob */ - return Blob; - -Quickie: - /* Free the blob, set error and fail */ - SaBlob_Free(Blob); - SetLastError(ERROR_OUTOFMEMORY); - return NULL; -} - -VOID -WINAPI -SaBlob_Free(IN PDNS_BLOB Blob) -{ - /* Make sure we got a blob */ - if (Blob) - { - /* Free the name */ - Dns_Free(Blob->Name); - - /* Loop the aliases */ - while (Blob->AliasCount) - { - /* Free the alias */ - Dns_Free(Blob->Aliases[Blob->AliasCount]); - - /* Decrease number of aliases */ - Blob->AliasCount--; - } - - /* Free the DNS Address Array */ - DnsAddrArray_Free(Blob->DnsAddrArray); - - /* Free the blob itself */ - Dns_Free(Blob); - } -} - -PHOSTENT -WINAPI -SaBlob_CreateHostent(IN OUT PULONG_PTR BufferPosition, - IN OUT PSIZE_T FreeBufferSpace, - IN OUT PSIZE_T HostEntrySize, - IN PDNS_BLOB Blob, - IN DWORD StringType, - IN BOOLEAN Relative, - IN BOOLEAN BufferAllocated) -{ - PDNS_ARRAY DnsAddrArray = Blob->DnsAddrArray; - ULONG AliasCount = Blob->AliasCount; - WORD AddressFamily = AF_UNSPEC; - ULONG AddressCount = 0, AddressSize = 0, TotalSize, NamePointerSize; - ULONG AliasPointerSize; - PDNS_FAMILY_INFO FamilyInfo = NULL; - ULONG StringLength = 0; - ULONG i; - ULONG HostentSize = 0; - PHOSTENT Hostent = NULL; - ULONG_PTR HostentPtr; - PVOID CurrentAddress; - - /* Check if we actually have any addresses */ - if (DnsAddrArray) - { - /* Get the address family */ - AddressFamily = DnsAddrArray->Addresses[0].AddressFamily; - - /* Get family information */ - FamilyInfo = FamilyInfo_GetForFamily(AddressFamily); - - /* Save the current address count and their size */ - AddressCount = DnsAddrArray->UsedAddresses; - AddressSize = FamilyInfo->AddressSize; - } - - /* Calculate total size for all the addresses, and their pointers */ - TotalSize = AddressSize * AddressCount; - NamePointerSize = AddressCount * sizeof(PVOID) + sizeof(PVOID); - - /* Check if we have a name */ - if (Blob->Name) - { - /* Find out the size we'll need for a copy */ - StringLength = (Dns_GetBufferLengthForStringCopy(Blob->Name, - 0, - UnicodeString, - StringType) + 1) & ~1; - } - - /* Now do the same for the aliases */ - for (i = AliasCount; i; i--) - { - /* Find out the size we'll need for a copy */ - HostentSize += (Dns_GetBufferLengthForStringCopy(Blob->Aliases[i], - 0, - UnicodeString, - StringType) + 1) & ~1; - } - - /* Find out how much the pointers will take */ - AliasPointerSize = AliasCount * sizeof(PVOID) + sizeof(PVOID); - - /* Calculate Hostent Size */ - HostentSize += TotalSize + - NamePointerSize + - AliasPointerSize + - StringLength + - sizeof(HOSTENT); - - /* Check if we already have a buffer */ - if (!BufferAllocated) - { - /* We don't, allocate space ourselves */ - HostentPtr = (ULONG_PTR)Dns_AllocZero(HostentSize); - } - else - { - /* We do, so allocate space in the buffer */ - HostentPtr = (ULONG_PTR)FlatBuf_Arg_ReserveAlignPointer(BufferPosition, - FreeBufferSpace, - HostentSize); - } - - /* Make sure we got space */ - if (HostentPtr) - { - /* Initialize it */ - Hostent = Hostent_Init((PVOID)&HostentPtr, - AddressFamily, - AddressSize, - AddressCount, - AliasCount); - } - - /* Loop the addresses */ - for (i = 0; i < AddressCount; i++) - { - /* Get the pointer of the current address */ - CurrentAddress = (PVOID)((ULONG_PTR)&DnsAddrArray->Addresses[i] + - FamilyInfo->AddressOffset); - - /* Write the pointer */ - Hostent->h_addr_list[i] = (PCHAR)HostentPtr; - - /* Copy the address */ - RtlCopyMemory((PVOID)HostentPtr, CurrentAddress, AddressSize); - - /* Advance the buffer */ - HostentPtr += AddressSize; - } - - /* Check if we have a name */ - if (Blob->Name) - { - /* Align our current position */ - HostentPtr += 1 & ~1; - - /* Save our name here */ - Hostent->h_name = (LPSTR)HostentPtr; - - /* Now copy it in the blob */ - HostentPtr += Dns_StringCopy((PVOID)HostentPtr, - NULL, - Blob->Name, - 0, - UnicodeString, - StringType); - } - - /* Loop the Aliases */ - for (i = AliasCount; i; i--) - { - /* Align our current position */ - HostentPtr += 1 & ~1; - - /* Save our alias here */ - Hostent->h_aliases[i] = (LPSTR)HostentPtr; - - /* Now copy it in the blob */ - HostentPtr += Dns_StringCopy((PVOID)HostentPtr, - NULL, - Blob->Aliases[i], - 0, - UnicodeString, - StringType); - } - - /* Check if the caller didn't have a buffer */ - if (!BufferAllocated) - { - /* Return the size; not needed if we had a blob, since it's internal */ - *HostEntrySize = *BufferPosition - (ULONG_PTR)HostentPtr; - } - - /* Convert to Offsets if requested */ - if(Relative) Hostent_ConvertToOffsets(Hostent); - - /* Return the full, complete, hostent */ - return Hostent; -} - -INT -WINAPI -SaBlob_WriteNameOrAlias(IN PDNS_BLOB Blob, - IN LPWSTR String, - IN BOOLEAN IsAlias) -{ - /* Check if this is an alias */ - if (!IsAlias) - { - /* It's not. Simply create a copy of the string */ - Blob->Name = Dns_CreateStringCopy_W(String); - if (!Blob->Name) return GetLastError(); - } - else - { - /* Does it have a name, and less then 8 aliases? */ - if ((Blob->Name) && (Blob->AliasCount <= 8)) - { - /* Yup, create a copy of the string and increase the alias count */ - Blob->Aliases[Blob->AliasCount] = Dns_CreateStringCopy_W(String); - Blob->AliasCount++; - } - else - { - /* Invalid request! */ - return ERROR_MORE_DATA; - } - } - - /* Return Success */ - return ERROR_SUCCESS; -} - -INT -WINAPI -SaBlob_WriteAddress(IN PDNS_BLOB Blob, - OUT PDNS_ADDRESS DnsAddr) -{ - /* Check if we have an array yet */ - if (!Blob->DnsAddrArray) - { - /* Allocate one! */ - Blob->DnsAddrArray = DnsAddrArray_Create(1); - if (!Blob->DnsAddrArray) return ERROR_OUTOFMEMORY; - } - - /* Add this address */ - return DnsAddrArray_AddAddr(Blob->DnsAddrArray, DnsAddr, AF_UNSPEC, 0) ? - ERROR_SUCCESS: - ERROR_MORE_DATA; -} - -BOOLEAN -WINAPI -SaBlob_IsSupportedAddrType(WORD DnsType) -{ - /* Check for valid Types that we support */ - return (DnsType == DNS_TYPE_A || - DnsType == DNS_TYPE_ATMA || - DnsType == DNS_TYPE_AAAA); -} - -INT -WINAPI -SaBlob_WriteRecords(OUT PDNS_BLOB Blob, - IN PDNS_RECORD DnsRecord, - IN BOOLEAN DoAlias) -{ - DNS_ADDRESS DnsAddress; - INT ErrorCode = STATUS_INVALID_PARAMETER; - BOOLEAN WroteOnce = FALSE; - - /* Zero out the Address */ - RtlZeroMemory(&DnsAddress, sizeof(DnsAddress)); - - /* Loop through all the Records */ - while (DnsRecord) - { - /* Is this not an answer? */ - if (DnsRecord->Flags.S.Section != DNSREC_ANSWER) - { - /* Then simply move on to the next DNS Record */ - DnsRecord = DnsRecord->pNext; - continue; - } - - /* Check the type of thsi record */ - switch(DnsRecord->wType) - { - /* Regular IPv4, v6 or ATM Record */ - case DNS_TYPE_A: - case DNS_TYPE_AAAA: - case DNS_TYPE_ATMA: - - /* Create a DNS Address from the record */ - DnsAddr_BuildFromDnsRecord(DnsRecord, &DnsAddress); - - /* Add it to the DNS Blob */ - ErrorCode = SaBlob_WriteAddress(Blob, &DnsAddress); - - /* Add the name, if needed */ - if ((DoAlias) && - (!WroteOnce) && - (!Blob->Name) && - (DnsRecord->pName)) - { - /* Write the name from the DNS Record */ - ErrorCode = SaBlob_WriteNameOrAlias(Blob, - DnsRecord->pName, - FALSE); - WroteOnce = TRUE; - } - break; - - case DNS_TYPE_CNAME: - - /* Just write the alias name */ - ErrorCode = SaBlob_WriteNameOrAlias(Blob, - DnsRecord->pName, - TRUE); - break; - - case DNS_TYPE_PTR: - - /* Check if we already have a name */ - if (Blob->Name) - { - /* We don't, so add this as a name */ - ErrorCode = SaBlob_WriteNameOrAlias(Blob, - DnsRecord->pName, - FALSE); - } - else - { - /* We do, so add it as an alias */ - ErrorCode = SaBlob_WriteNameOrAlias(Blob, - DnsRecord->pName, - TRUE); - } - break; - default: - break; - } - - /* Next record */ - DnsRecord = DnsRecord->pNext; - } - - /* Return error code */ - return ErrorCode; -} - -PDNS_BLOB -WINAPI -SaBlob_CreateFromRecords(IN PDNS_RECORD DnsRecord, - IN BOOLEAN DoAliases, - IN DWORD DnsType) -{ - PDNS_RECORD LocalDnsRecord; - ULONG ProcessedCount = 0; - PDNS_BLOB DnsBlob; - INT ErrorCode; - DNS_ADDRESS DnsAddress; - - /* Find out how many DNS Addresses to allocate */ - LocalDnsRecord = DnsRecord; - while (LocalDnsRecord) - { - /* Make sure this record is an answer */ - if ((LocalDnsRecord->Flags.S.Section == DNSREC_ANSWER) && - (SaBlob_IsSupportedAddrType(LocalDnsRecord->wType))) - { - /* Increase number of records to process */ - ProcessedCount++; - } - - /* Move to the next record */ - LocalDnsRecord = LocalDnsRecord->pNext; - } - - /* Create the DNS Blob */ - DnsBlob = SaBlob_Create(ProcessedCount); - if (!DnsBlob) - { - /* Fail */ - ErrorCode = GetLastError(); - goto Quickie; - } - - /* Write the record to the DNS Blob */ - ErrorCode = SaBlob_WriteRecords(DnsBlob, DnsRecord, TRUE); - if (ErrorCode != NO_ERROR) - { - /* We failed... but do we still have valid data? */ - if ((DnsBlob->Name) || (DnsBlob->AliasCount)) - { - /* We'll just assume success then */ - ErrorCode = NO_ERROR; - } - else - { - /* Ok, last chance..do you have a DNS Address Array? */ - if ((DnsBlob->DnsAddrArray) && - (DnsBlob->DnsAddrArray->UsedAddresses)) - { - /* Boy are you lucky! */ - ErrorCode = NO_ERROR; - } - } - - /* Buh-bye! */ - goto Quickie; - } - - /* Check if this is a PTR record */ - if ((DnsRecord->wType == DNS_TYPE_PTR) || - ((DnsType == DNS_TYPE_PTR) && - (DnsRecord->wType == DNS_TYPE_CNAME) && - (DnsRecord->Flags.S.Section == DNSREC_ANSWER))) - { - /* Get a DNS Address Structure */ - if (Dns_ReverseNameToDnsAddr_W(&DnsAddress, DnsRecord->pName)) - { - /* Add it to the Blob */ - if (SaBlob_WriteAddress(DnsBlob, &DnsAddress)) ErrorCode = NO_ERROR; - } - } - - /* Ok...do we still not have a name? */ - if (!(DnsBlob->Name) && (DoAliases) && (LocalDnsRecord)) - { - /* We have an local DNS Record, so just use it to write the name */ - ErrorCode = SaBlob_WriteNameOrAlias(DnsBlob, - LocalDnsRecord->pName, - FALSE); - } - -Quickie: - /* Check error code */ - if (ErrorCode != NO_ERROR) - { - /* Free the blob and set the error */ - SaBlob_Free(DnsBlob); - DnsBlob = NULL; - SetLastError(ErrorCode); - } - - /* Return */ - return DnsBlob; -} - -PDNS_BLOB -WINAPI -SaBlob_Query(IN LPWSTR Name, - IN WORD DnsType, - IN ULONG Flags, - IN PVOID *Reserved, - IN DWORD AddressFamily) -{ - PDNS_RECORD DnsRecord = NULL; - INT ErrorCode; - PDNS_BLOB DnsBlob = NULL; - LPWSTR LocalName, LocalNameCopy; - - /* If they want reserved data back, clear it out in case we fail */ - if (Reserved) *Reserved = NULL; - - /* Query DNS */ - ErrorCode = DnsQuery_W(Name, - DnsType, - Flags, - NULL, - &DnsRecord, - Reserved); - if (ErrorCode != ERROR_SUCCESS) - { - /* We failed... did the caller use reserved data? */ - if (Reserved && *Reserved) - { - /* He did, and it was valid. Free it */ - DnsApiFree(*Reserved); - *Reserved = NULL; - } - - /* Normalize error code */ - if (ErrorCode == RPC_S_SERVER_UNAVAILABLE) ErrorCode = WSATRY_AGAIN; - goto Quickie; - } - - /* Now create the Blob from the DNS Records */ - DnsBlob = SaBlob_CreateFromRecords(DnsRecord, TRUE, DnsType); - if (!DnsBlob) - { - /* Failed, get error code */ - ErrorCode = GetLastError(); - goto Quickie; - } - - /* Make sure it has a name */ - if (!DnsBlob->Name) - { - /* It doesn't, fail */ - ErrorCode = DNS_INFO_NO_RECORDS; - goto Quickie; - } - - /* Check if the name is local or loopback */ - if (!(DnsNameCompare_W(DnsBlob->Name, L"localhost")) && - !(DnsNameCompare_W(DnsBlob->Name, L"loopback"))) - { - /* Nothing left to do, exit! */ - goto Quickie; - } - - /* This is a local name...query it */ - DnsQueryConfig(DnsConfigFullHostName_W, - DNS_CONFIG_FLAG_ALLOC, - NULL, - NULL, - &LocalName, - 0); - if (LocalName) - { - /* Create a copy for the caller */ - LocalNameCopy = Dns_CreateStringCopy_W(LocalName); - if (LocalNameCopy) - { - /* Overwrite the one in the blob */ - DnsBlob->Name = LocalNameCopy; - } - else - { - /* We failed to make a copy, free memory */ - DnsApiFree(LocalName); - } - } - -Quickie: - /* Free the DNS Record if we have one */ - if (DnsRecord) DnsRecordListFree(DnsRecord, DnsFreeRecordList); - - /* Check if this is a failure path with an active blob */ - if ((ErrorCode != ERROR_SUCCESS) && (DnsBlob)) - { - /* Free the blob */ - SaBlob_Free(DnsBlob); - DnsBlob = NULL; - } - - /* Set the last error and return */ - SetLastError(ErrorCode); - return DnsBlob; -} - diff --git a/dll/win32/mswsock/dns/straddr.c b/dll/win32/mswsock/dns/straddr.c index 4bf80f51b8b..4215a80dbf0 100644 --- a/dll/win32/mswsock/dns/straddr.c +++ b/dll/win32/mswsock/dns/straddr.c @@ -460,1389 +460,3 @@ Dns_ReverseNameToDnsAddr_W(OUT PDNS_ADDRESS DnsAddr, TRUE); } -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/straddr.c - * PURPOSE: Functions for address<->string conversion. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -LPWSTR -WINAPI -Dns_Ip6AddressToReverseName_W(OUT LPWSTR Name, - IN IN6_ADDR Address) -{ - /* FIXME */ - return NULL; -} - -LPWSTR -WINAPI -Dns_Ip4AddressToReverseName_W(OUT LPWSTR Name, - IN IN_ADDR Address) -{ - /* Simply append the ARPA string */ - return Name + (wsprintfW(Name, - L"%u.%u.%u.%u.in-addr.arpa.", - Address.S_un.S_addr >> 24, - Address.S_un.S_addr >> 10, - Address.S_un.S_addr >> 8, - Address.S_un.S_addr) * sizeof(WCHAR)); -} - -BOOLEAN -WINAPI -Dns_Ip4ReverseNameToAddress_A(OUT PIN_ADDR Address, - IN LPSTR Name) -{ - /* FIXME */ - return FALSE; -} - -BOOLEAN -WINAPI -Dns_Ip6ReverseNameToAddress_A(OUT PIN6_ADDR Address, - IN LPSTR Name) -{ - /* FIXME */ - return FALSE; -} - -BOOLEAN -WINAPI -Dns_Ip6StringToAddress_A(OUT PIN6_ADDR Address, - IN LPSTR Name) -{ - PCHAR Terminator; - NTSTATUS Status; - - /* Let RTL Do it for us */ - Status = RtlIpv6StringToAddressA(Name, &Terminator, Address); - if (NT_SUCCESS(Status)) return TRUE; - - /* We failed */ - return FALSE; -} - -BOOLEAN -WINAPI -Dns_Ip6StringToAddress_W(OUT PIN6_ADDR Address, - IN LPWSTR Name) -{ - PCHAR Terminator; - NTSTATUS Status; - - /* Let RTL Do it for us */ - Status = RtlIpv6StringToAddressW(Name, &Terminator, Address); - if (NT_SUCCESS(Status)) return TRUE; - - /* We failed */ - return FALSE; -} - -BOOLEAN -WINAPI -Dns_Ip4StringToAddress_A(OUT PIN_ADDR Address, - IN LPSTR Name) -{ - ULONG Addr; - - /* Use inet_addr to convert it... */ - Addr = inet_addr(Name); - if (Addr == -1) - { - /* Check if it's the wildcard (which is ok...) */ - if (strcmp("255.255.255.255", Name)) return FALSE; - } - - /* If we got here, then we suceeded... return the address */ - Address->S_un.S_addr = Addr; - return TRUE; -} - -BOOLEAN -WINAPI -Dns_Ip4StringToAddress_W(OUT PIN_ADDR Address, - IN LPWSTR Name) -{ - CHAR AnsiName[16]; - ULONG Size = sizeof(AnsiName); - INT ErrorCode; - - /* Make a copy of the name in ANSI */ - ErrorCode = Dns_StringCopy(&AnsiName, - &Size, - Name, - 0, - UnicodeString, - AnsiString); - if (ErrorCode) - { - /* Copy made sucesfully, now convert it */ - ErrorCode = Dns_Ip4StringToAddress_A(Address, AnsiName); - } - - /* Return either 0 bytes copied (failure == false) or conversion status */ - return ErrorCode; -} - -BOOLEAN -WINAPI -Dns_Ip4ReverseNameToAddress_W(OUT PIN_ADDR Address, - IN LPWSTR Name) -{ - CHAR AnsiName[32]; - ULONG Size = sizeof(AnsiName); - INT ErrorCode; - - /* Make a copy of the name in ANSI */ - ErrorCode = Dns_StringCopy(&AnsiName, - &Size, - Name, - 0, - UnicodeString, - AnsiString); - if (ErrorCode) - { - /* Copy made sucesfully, now convert it */ - ErrorCode = Dns_Ip4ReverseNameToAddress_A(Address, AnsiName); - } - - /* Return either 0 bytes copied (failure == false) or conversion status */ - return ErrorCode; -} - -BOOLEAN -WINAPI -Dns_StringToAddressEx(OUT PVOID Address, - IN OUT PULONG AddressSize, - IN PVOID AddressName, - IN OUT PDWORD AddressFamily, - IN BOOLEAN Unicode, - IN BOOLEAN Reverse) -{ - DWORD Af = *AddressFamily; - ULONG AddrSize = *AddressSize; - IN6_ADDR Addr; - BOOLEAN Return; - INT ErrorCode; - CHAR AnsiName[INET6_ADDRSTRLEN + sizeof("ip6.arpa.")]; - ULONG Size = sizeof(AnsiName); - - /* First check if this is a reverse address string */ - if (Reverse) - { - /* Convert it right now to ANSI as an optimization */ - Dns_StringCopy(AnsiName, - &Size, - AddressName, - 0, - UnicodeString, - AnsiString); - - /* Use the ANSI Name instead */ - AddressName = AnsiName; - } - - /* - * If the caller doesn't know what the family is, we'll assume IPv4 and - * check if we failed or not. If the caller told us it's IPv4, then just - * do IPv4... - */ - if ((Af == AF_UNSPEC) || (Af == AF_INET)) - { - /* Now check if the caller gave us the reverse name or not */ - if (Reverse) - { - /* Get the Address */ - Return = Dns_Ip4ReverseNameToAddress_A((PIN_ADDR)&Addr, AddressName); - } - else - { - /* Check if the caller gave us unicode or not */ - if (Unicode) - { - /* Get the Address */ - Return = Dns_Ip4StringToAddress_W((PIN_ADDR)&Addr, AddressName); - } - else - { - /* Get the Address */ - Return = Dns_Ip4StringToAddress_A((PIN_ADDR)&Addr, AddressName); - } - } - - /* Check if we suceeded */ - if (Return) - { - /* Save address family */ - Af = AF_INET; - - /* Check if the address size matches */ - if (AddrSize < sizeof(IN_ADDR)) - { - /* Invalid match, set error code */ - ErrorCode = ERROR_MORE_DATA; - } - else - { - /* It matches, save the address! */ - *(PIN_ADDR)Address = *(PIN_ADDR)&Addr; - } - } - } - - /* If we are here, either AF_INET6 was specified or IPv4 failed */ - if ((Af == AF_UNSPEC) || (Af == AF_INET6)) - { - /* Now check if the caller gave us the reverse name or not */ - if (Reverse) - { - /* Get the Address */ - Return = Dns_Ip6ReverseNameToAddress_A(&Addr, AddressName); - } - else - { - /* Check if the caller gave us unicode or not */ - if (Unicode) - { - /* Get the Address */ - Return = Dns_Ip6StringToAddress_W(&Addr, AddressName); - } - else - { - /* Get the Address */ - Return = Dns_Ip6StringToAddress_A(&Addr, AddressName); - } - } - - /* Check if we suceeded */ - if (Return) - { - /* Save address family */ - Af = AF_INET6; - - /* Check if the address size matches */ - if (AddrSize < sizeof(IN6_ADDR)) - { - /* Invalid match, set error code */ - ErrorCode = ERROR_MORE_DATA; - } - else - { - /* It matches, save the address! */ - *(PIN6_ADDR)Address = Addr; - } - } - } - else if (Af != AF_INET) - { - /* You're like.. ATM or something? Get outta here! */ - Af = AF_UNSPEC; - ErrorCode = WSA_INVALID_PARAMETER; - } - - /* Set error if we had one */ - if (ErrorCode) SetLastError(ErrorCode); - - /* Return the address family and size */ - *AddressFamily = Af; - *AddressSize = AddrSize; - - /* Return success or failure */ - return (ErrorCode == ERROR_SUCCESS); -} - -BOOLEAN -WINAPI -Dns_StringToAddressW(OUT PVOID Address, - IN OUT PULONG AddressSize, - IN LPWSTR AddressName, - IN OUT PDWORD AddressFamily) -{ - /* Call the common API */ - return Dns_StringToAddressEx(Address, - AddressSize, - AddressName, - AddressFamily, - TRUE, - FALSE); -} - -BOOLEAN -WINAPI -Dns_StringToDnsAddrEx(OUT PDNS_ADDRESS DnsAddr, - IN PVOID AddressName, - IN DWORD AddressFamily, - IN BOOLEAN Unicode, - IN BOOLEAN Reverse) -{ - IN6_ADDR Addr; - BOOLEAN Return; - INT ErrorCode = ERROR_SUCCESS; - CHAR AnsiName[INET6_ADDRSTRLEN + sizeof("ip6.arpa.")]; - ULONG Size = sizeof(AnsiName); - - /* First check if this is a reverse address string */ - if ((Reverse) && (Unicode)) - { - /* Convert it right now to ANSI as an optimization */ - Dns_StringCopy(AnsiName, - &Size, - AddressName, - 0, - UnicodeString, - AnsiString); - - /* Use the ANSI Name instead */ - AddressName = AnsiName; - } - - /* - * If the caller doesn't know what the family is, we'll assume IPv4 and - * check if we failed or not. If the caller told us it's IPv4, then just - * do IPv4... - */ - if ((AddressFamily == AF_UNSPEC) || (AddressFamily == AF_INET)) - { - /* Now check if the caller gave us the reverse name or not */ - if (Reverse) - { - /* Get the Address */ - Return = Dns_Ip4ReverseNameToAddress_A((PIN_ADDR)&Addr, AddressName); - } - else - { - /* Check if the caller gave us unicode or not */ - if (Unicode) - { - /* Get the Address */ - Return = Dns_Ip4StringToAddress_W((PIN_ADDR)&Addr, AddressName); - } - else - { - /* Get the Address */ - Return = Dns_Ip4StringToAddress_A((PIN_ADDR)&Addr, AddressName); - } - } - - /* Check if we suceeded */ - if (Return) - { - /* Build the IPv4 Address */ - DnsAddr_BuildFromIp4(DnsAddr, *(PIN_ADDR)&Addr, 0); - - /* So we don't go in the code below... */ - AddressFamily = AF_INET; - } - } - - /* If we are here, either AF_INET6 was specified or IPv4 failed */ - if ((AddressFamily == AF_UNSPEC) || (AddressFamily == AF_INET6)) - { - /* Now check if the caller gave us the reverse name or not */ - if (Reverse) - { - /* Get the Address */ - Return = Dns_Ip6ReverseNameToAddress_A(&Addr, AddressName); - if (Return) - { - /* Build the IPv6 Address */ - DnsAddr_BuildFromIp6(DnsAddr, &Addr, 0, 0); - } - else - { - goto Quickie; - } - } - else - { - /* Check if the caller gave us unicode or not */ - if (Unicode) - { - /* Get the Address */ - if (NT_SUCCESS(RtlIpv6StringToAddressExW(AddressName, - &DnsAddr->Ip6Address.sin6_addr, - &DnsAddr->Ip6Address.sin6_scope_id, - &DnsAddr->Ip6Address.sin6_port))) - Return = TRUE; - else - Return = FALSE; - } - else - { - /* Get the Address */ - if (NT_SUCCESS(RtlIpv6StringToAddressExA(AddressName, - &DnsAddr->Ip6Address.sin6_addr, - &DnsAddr->Ip6Address.sin6_scope_id, - &DnsAddr->Ip6Address.sin6_port))) - Return = TRUE; - else - Return = FALSE; - } - } - - /* Check if we suceeded */ - if (Return) - { - /* Finish setting up the structure */ - DnsAddr->Ip6Address.sin6_family = AF_INET6; - DnsAddr->AddressLength = sizeof(SOCKADDR_IN6); - } - } - else if (AddressFamily != AF_INET) - { - /* You're like.. ATM or something? Get outta here! */ - RtlZeroMemory(DnsAddr, sizeof(DNS_ADDRESS)); - SetLastError(WSA_INVALID_PARAMETER); - } - -Quickie: - /* Return success or failure */ - return (ErrorCode == ERROR_SUCCESS); -} - -BOOLEAN -WINAPI -Dns_ReverseNameToDnsAddr_W(OUT PDNS_ADDRESS DnsAddr, - IN LPWSTR Name) -{ - /* Call the common API */ - return Dns_StringToDnsAddrEx(DnsAddr, - Name, - AF_UNSPEC, - TRUE, - TRUE); -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/straddr.c - * PURPOSE: Functions for address<->string conversion. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -LPWSTR -WINAPI -Dns_Ip6AddressToReverseName_W(OUT LPWSTR Name, - IN IN6_ADDR Address) -{ - /* FIXME */ - return NULL; -} - -LPWSTR -WINAPI -Dns_Ip4AddressToReverseName_W(OUT LPWSTR Name, - IN IN_ADDR Address) -{ - /* Simply append the ARPA string */ - return Name + (wsprintfW(Name, - L"%u.%u.%u.%u.in-addr.arpa.", - Address.S_un.S_addr >> 24, - Address.S_un.S_addr >> 10, - Address.S_un.S_addr >> 8, - Address.S_un.S_addr) * sizeof(WCHAR)); -} - -BOOLEAN -WINAPI -Dns_Ip4ReverseNameToAddress_A(OUT PIN_ADDR Address, - IN LPSTR Name) -{ - /* FIXME */ - return FALSE; -} - -BOOLEAN -WINAPI -Dns_Ip6ReverseNameToAddress_A(OUT PIN6_ADDR Address, - IN LPSTR Name) -{ - /* FIXME */ - return FALSE; -} - -BOOLEAN -WINAPI -Dns_Ip6StringToAddress_A(OUT PIN6_ADDR Address, - IN LPSTR Name) -{ - PCHAR Terminator; - NTSTATUS Status; - - /* Let RTL Do it for us */ - Status = RtlIpv6StringToAddressA(Name, &Terminator, Address); - if (NT_SUCCESS(Status)) return TRUE; - - /* We failed */ - return FALSE; -} - -BOOLEAN -WINAPI -Dns_Ip6StringToAddress_W(OUT PIN6_ADDR Address, - IN LPWSTR Name) -{ - PCHAR Terminator; - NTSTATUS Status; - - /* Let RTL Do it for us */ - Status = RtlIpv6StringToAddressW(Name, &Terminator, Address); - if (NT_SUCCESS(Status)) return TRUE; - - /* We failed */ - return FALSE; -} - -BOOLEAN -WINAPI -Dns_Ip4StringToAddress_A(OUT PIN_ADDR Address, - IN LPSTR Name) -{ - ULONG Addr; - - /* Use inet_addr to convert it... */ - Addr = inet_addr(Name); - if (Addr == -1) - { - /* Check if it's the wildcard (which is ok...) */ - if (strcmp("255.255.255.255", Name)) return FALSE; - } - - /* If we got here, then we suceeded... return the address */ - Address->S_un.S_addr = Addr; - return TRUE; -} - -BOOLEAN -WINAPI -Dns_Ip4StringToAddress_W(OUT PIN_ADDR Address, - IN LPWSTR Name) -{ - CHAR AnsiName[16]; - ULONG Size = sizeof(AnsiName); - INT ErrorCode; - - /* Make a copy of the name in ANSI */ - ErrorCode = Dns_StringCopy(&AnsiName, - &Size, - Name, - 0, - UnicodeString, - AnsiString); - if (ErrorCode) - { - /* Copy made sucesfully, now convert it */ - ErrorCode = Dns_Ip4StringToAddress_A(Address, AnsiName); - } - - /* Return either 0 bytes copied (failure == false) or conversion status */ - return ErrorCode; -} - -BOOLEAN -WINAPI -Dns_Ip4ReverseNameToAddress_W(OUT PIN_ADDR Address, - IN LPWSTR Name) -{ - CHAR AnsiName[32]; - ULONG Size = sizeof(AnsiName); - INT ErrorCode; - - /* Make a copy of the name in ANSI */ - ErrorCode = Dns_StringCopy(&AnsiName, - &Size, - Name, - 0, - UnicodeString, - AnsiString); - if (ErrorCode) - { - /* Copy made sucesfully, now convert it */ - ErrorCode = Dns_Ip4ReverseNameToAddress_A(Address, AnsiName); - } - - /* Return either 0 bytes copied (failure == false) or conversion status */ - return ErrorCode; -} - -BOOLEAN -WINAPI -Dns_StringToAddressEx(OUT PVOID Address, - IN OUT PULONG AddressSize, - IN PVOID AddressName, - IN OUT PDWORD AddressFamily, - IN BOOLEAN Unicode, - IN BOOLEAN Reverse) -{ - DWORD Af = *AddressFamily; - ULONG AddrSize = *AddressSize; - IN6_ADDR Addr; - BOOLEAN Return; - INT ErrorCode; - CHAR AnsiName[INET6_ADDRSTRLEN + sizeof("ip6.arpa.")]; - ULONG Size = sizeof(AnsiName); - - /* First check if this is a reverse address string */ - if (Reverse) - { - /* Convert it right now to ANSI as an optimization */ - Dns_StringCopy(AnsiName, - &Size, - AddressName, - 0, - UnicodeString, - AnsiString); - - /* Use the ANSI Name instead */ - AddressName = AnsiName; - } - - /* - * If the caller doesn't know what the family is, we'll assume IPv4 and - * check if we failed or not. If the caller told us it's IPv4, then just - * do IPv4... - */ - if ((Af == AF_UNSPEC) || (Af == AF_INET)) - { - /* Now check if the caller gave us the reverse name or not */ - if (Reverse) - { - /* Get the Address */ - Return = Dns_Ip4ReverseNameToAddress_A((PIN_ADDR)&Addr, AddressName); - } - else - { - /* Check if the caller gave us unicode or not */ - if (Unicode) - { - /* Get the Address */ - Return = Dns_Ip4StringToAddress_W((PIN_ADDR)&Addr, AddressName); - } - else - { - /* Get the Address */ - Return = Dns_Ip4StringToAddress_A((PIN_ADDR)&Addr, AddressName); - } - } - - /* Check if we suceeded */ - if (Return) - { - /* Save address family */ - Af = AF_INET; - - /* Check if the address size matches */ - if (AddrSize < sizeof(IN_ADDR)) - { - /* Invalid match, set error code */ - ErrorCode = ERROR_MORE_DATA; - } - else - { - /* It matches, save the address! */ - *(PIN_ADDR)Address = *(PIN_ADDR)&Addr; - } - } - } - - /* If we are here, either AF_INET6 was specified or IPv4 failed */ - if ((Af == AF_UNSPEC) || (Af == AF_INET6)) - { - /* Now check if the caller gave us the reverse name or not */ - if (Reverse) - { - /* Get the Address */ - Return = Dns_Ip6ReverseNameToAddress_A(&Addr, AddressName); - } - else - { - /* Check if the caller gave us unicode or not */ - if (Unicode) - { - /* Get the Address */ - Return = Dns_Ip6StringToAddress_W(&Addr, AddressName); - } - else - { - /* Get the Address */ - Return = Dns_Ip6StringToAddress_A(&Addr, AddressName); - } - } - - /* Check if we suceeded */ - if (Return) - { - /* Save address family */ - Af = AF_INET6; - - /* Check if the address size matches */ - if (AddrSize < sizeof(IN6_ADDR)) - { - /* Invalid match, set error code */ - ErrorCode = ERROR_MORE_DATA; - } - else - { - /* It matches, save the address! */ - *(PIN6_ADDR)Address = Addr; - } - } - } - else if (Af != AF_INET) - { - /* You're like.. ATM or something? Get outta here! */ - Af = AF_UNSPEC; - ErrorCode = WSA_INVALID_PARAMETER; - } - - /* Set error if we had one */ - if (ErrorCode) SetLastError(ErrorCode); - - /* Return the address family and size */ - *AddressFamily = Af; - *AddressSize = AddrSize; - - /* Return success or failure */ - return (ErrorCode == ERROR_SUCCESS); -} - -BOOLEAN -WINAPI -Dns_StringToAddressW(OUT PVOID Address, - IN OUT PULONG AddressSize, - IN LPWSTR AddressName, - IN OUT PDWORD AddressFamily) -{ - /* Call the common API */ - return Dns_StringToAddressEx(Address, - AddressSize, - AddressName, - AddressFamily, - TRUE, - FALSE); -} - -BOOLEAN -WINAPI -Dns_StringToDnsAddrEx(OUT PDNS_ADDRESS DnsAddr, - IN PVOID AddressName, - IN DWORD AddressFamily, - IN BOOLEAN Unicode, - IN BOOLEAN Reverse) -{ - IN6_ADDR Addr; - BOOLEAN Return; - INT ErrorCode = ERROR_SUCCESS; - CHAR AnsiName[INET6_ADDRSTRLEN + sizeof("ip6.arpa.")]; - ULONG Size = sizeof(AnsiName); - - /* First check if this is a reverse address string */ - if ((Reverse) && (Unicode)) - { - /* Convert it right now to ANSI as an optimization */ - Dns_StringCopy(AnsiName, - &Size, - AddressName, - 0, - UnicodeString, - AnsiString); - - /* Use the ANSI Name instead */ - AddressName = AnsiName; - } - - /* - * If the caller doesn't know what the family is, we'll assume IPv4 and - * check if we failed or not. If the caller told us it's IPv4, then just - * do IPv4... - */ - if ((AddressFamily == AF_UNSPEC) || (AddressFamily == AF_INET)) - { - /* Now check if the caller gave us the reverse name or not */ - if (Reverse) - { - /* Get the Address */ - Return = Dns_Ip4ReverseNameToAddress_A((PIN_ADDR)&Addr, AddressName); - } - else - { - /* Check if the caller gave us unicode or not */ - if (Unicode) - { - /* Get the Address */ - Return = Dns_Ip4StringToAddress_W((PIN_ADDR)&Addr, AddressName); - } - else - { - /* Get the Address */ - Return = Dns_Ip4StringToAddress_A((PIN_ADDR)&Addr, AddressName); - } - } - - /* Check if we suceeded */ - if (Return) - { - /* Build the IPv4 Address */ - DnsAddr_BuildFromIp4(DnsAddr, *(PIN_ADDR)&Addr, 0); - - /* So we don't go in the code below... */ - AddressFamily = AF_INET; - } - } - - /* If we are here, either AF_INET6 was specified or IPv4 failed */ - if ((AddressFamily == AF_UNSPEC) || (AddressFamily == AF_INET6)) - { - /* Now check if the caller gave us the reverse name or not */ - if (Reverse) - { - /* Get the Address */ - Return = Dns_Ip6ReverseNameToAddress_A(&Addr, AddressName); - if (Return) - { - /* Build the IPv6 Address */ - DnsAddr_BuildFromIp6(DnsAddr, &Addr, 0, 0); - } - else - { - goto Quickie; - } - } - else - { - /* Check if the caller gave us unicode or not */ - if (Unicode) - { - /* Get the Address */ - if (NT_SUCCESS(RtlIpv6StringToAddressExW(AddressName, - &DnsAddr->Ip6Address.sin6_addr, - &DnsAddr->Ip6Address.sin6_scope_id, - &DnsAddr->Ip6Address.sin6_port))) - Return = TRUE; - else - Return = FALSE; - } - else - { - /* Get the Address */ - if (NT_SUCCESS(RtlIpv6StringToAddressExA(AddressName, - &DnsAddr->Ip6Address.sin6_addr, - &DnsAddr->Ip6Address.sin6_scope_id, - &DnsAddr->Ip6Address.sin6_port))) - Return = TRUE; - else - Return = FALSE; - } - } - - /* Check if we suceeded */ - if (Return) - { - /* Finish setting up the structure */ - DnsAddr->Ip6Address.sin6_family = AF_INET6; - DnsAddr->AddressLength = sizeof(SOCKADDR_IN6); - } - } - else if (AddressFamily != AF_INET) - { - /* You're like.. ATM or something? Get outta here! */ - RtlZeroMemory(DnsAddr, sizeof(DNS_ADDRESS)); - SetLastError(WSA_INVALID_PARAMETER); - } - -Quickie: - /* Return success or failure */ - return (ErrorCode == ERROR_SUCCESS); -} - -BOOLEAN -WINAPI -Dns_ReverseNameToDnsAddr_W(OUT PDNS_ADDRESS DnsAddr, - IN LPWSTR Name) -{ - /* Call the common API */ - return Dns_StringToDnsAddrEx(DnsAddr, - Name, - AF_UNSPEC, - TRUE, - TRUE); -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/straddr.c - * PURPOSE: Functions for address<->string conversion. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -LPWSTR -WINAPI -Dns_Ip6AddressToReverseName_W(OUT LPWSTR Name, - IN IN6_ADDR Address) -{ - /* FIXME */ - return NULL; -} - -LPWSTR -WINAPI -Dns_Ip4AddressToReverseName_W(OUT LPWSTR Name, - IN IN_ADDR Address) -{ - /* Simply append the ARPA string */ - return Name + (wsprintfW(Name, - L"%u.%u.%u.%u.in-addr.arpa.", - Address.S_un.S_addr >> 24, - Address.S_un.S_addr >> 10, - Address.S_un.S_addr >> 8, - Address.S_un.S_addr) * sizeof(WCHAR)); -} - -BOOLEAN -WINAPI -Dns_Ip4ReverseNameToAddress_A(OUT PIN_ADDR Address, - IN LPSTR Name) -{ - /* FIXME */ - return FALSE; -} - -BOOLEAN -WINAPI -Dns_Ip6ReverseNameToAddress_A(OUT PIN6_ADDR Address, - IN LPSTR Name) -{ - /* FIXME */ - return FALSE; -} - -BOOLEAN -WINAPI -Dns_Ip6StringToAddress_A(OUT PIN6_ADDR Address, - IN LPSTR Name) -{ - PCHAR Terminator; - NTSTATUS Status; - - /* Let RTL Do it for us */ - Status = RtlIpv6StringToAddressA(Name, &Terminator, Address); - if (NT_SUCCESS(Status)) return TRUE; - - /* We failed */ - return FALSE; -} - -BOOLEAN -WINAPI -Dns_Ip6StringToAddress_W(OUT PIN6_ADDR Address, - IN LPWSTR Name) -{ - PCHAR Terminator; - NTSTATUS Status; - - /* Let RTL Do it for us */ - Status = RtlIpv6StringToAddressW(Name, &Terminator, Address); - if (NT_SUCCESS(Status)) return TRUE; - - /* We failed */ - return FALSE; -} - -BOOLEAN -WINAPI -Dns_Ip4StringToAddress_A(OUT PIN_ADDR Address, - IN LPSTR Name) -{ - ULONG Addr; - - /* Use inet_addr to convert it... */ - Addr = inet_addr(Name); - if (Addr == -1) - { - /* Check if it's the wildcard (which is ok...) */ - if (strcmp("255.255.255.255", Name)) return FALSE; - } - - /* If we got here, then we suceeded... return the address */ - Address->S_un.S_addr = Addr; - return TRUE; -} - -BOOLEAN -WINAPI -Dns_Ip4StringToAddress_W(OUT PIN_ADDR Address, - IN LPWSTR Name) -{ - CHAR AnsiName[16]; - ULONG Size = sizeof(AnsiName); - INT ErrorCode; - - /* Make a copy of the name in ANSI */ - ErrorCode = Dns_StringCopy(&AnsiName, - &Size, - Name, - 0, - UnicodeString, - AnsiString); - if (ErrorCode) - { - /* Copy made sucesfully, now convert it */ - ErrorCode = Dns_Ip4StringToAddress_A(Address, AnsiName); - } - - /* Return either 0 bytes copied (failure == false) or conversion status */ - return ErrorCode; -} - -BOOLEAN -WINAPI -Dns_Ip4ReverseNameToAddress_W(OUT PIN_ADDR Address, - IN LPWSTR Name) -{ - CHAR AnsiName[32]; - ULONG Size = sizeof(AnsiName); - INT ErrorCode; - - /* Make a copy of the name in ANSI */ - ErrorCode = Dns_StringCopy(&AnsiName, - &Size, - Name, - 0, - UnicodeString, - AnsiString); - if (ErrorCode) - { - /* Copy made sucesfully, now convert it */ - ErrorCode = Dns_Ip4ReverseNameToAddress_A(Address, AnsiName); - } - - /* Return either 0 bytes copied (failure == false) or conversion status */ - return ErrorCode; -} - -BOOLEAN -WINAPI -Dns_StringToAddressEx(OUT PVOID Address, - IN OUT PULONG AddressSize, - IN PVOID AddressName, - IN OUT PDWORD AddressFamily, - IN BOOLEAN Unicode, - IN BOOLEAN Reverse) -{ - DWORD Af = *AddressFamily; - ULONG AddrSize = *AddressSize; - IN6_ADDR Addr; - BOOLEAN Return; - INT ErrorCode; - CHAR AnsiName[INET6_ADDRSTRLEN + sizeof("ip6.arpa.")]; - ULONG Size = sizeof(AnsiName); - - /* First check if this is a reverse address string */ - if (Reverse) - { - /* Convert it right now to ANSI as an optimization */ - Dns_StringCopy(AnsiName, - &Size, - AddressName, - 0, - UnicodeString, - AnsiString); - - /* Use the ANSI Name instead */ - AddressName = AnsiName; - } - - /* - * If the caller doesn't know what the family is, we'll assume IPv4 and - * check if we failed or not. If the caller told us it's IPv4, then just - * do IPv4... - */ - if ((Af == AF_UNSPEC) || (Af == AF_INET)) - { - /* Now check if the caller gave us the reverse name or not */ - if (Reverse) - { - /* Get the Address */ - Return = Dns_Ip4ReverseNameToAddress_A((PIN_ADDR)&Addr, AddressName); - } - else - { - /* Check if the caller gave us unicode or not */ - if (Unicode) - { - /* Get the Address */ - Return = Dns_Ip4StringToAddress_W((PIN_ADDR)&Addr, AddressName); - } - else - { - /* Get the Address */ - Return = Dns_Ip4StringToAddress_A((PIN_ADDR)&Addr, AddressName); - } - } - - /* Check if we suceeded */ - if (Return) - { - /* Save address family */ - Af = AF_INET; - - /* Check if the address size matches */ - if (AddrSize < sizeof(IN_ADDR)) - { - /* Invalid match, set error code */ - ErrorCode = ERROR_MORE_DATA; - } - else - { - /* It matches, save the address! */ - *(PIN_ADDR)Address = *(PIN_ADDR)&Addr; - } - } - } - - /* If we are here, either AF_INET6 was specified or IPv4 failed */ - if ((Af == AF_UNSPEC) || (Af == AF_INET6)) - { - /* Now check if the caller gave us the reverse name or not */ - if (Reverse) - { - /* Get the Address */ - Return = Dns_Ip6ReverseNameToAddress_A(&Addr, AddressName); - } - else - { - /* Check if the caller gave us unicode or not */ - if (Unicode) - { - /* Get the Address */ - Return = Dns_Ip6StringToAddress_W(&Addr, AddressName); - } - else - { - /* Get the Address */ - Return = Dns_Ip6StringToAddress_A(&Addr, AddressName); - } - } - - /* Check if we suceeded */ - if (Return) - { - /* Save address family */ - Af = AF_INET6; - - /* Check if the address size matches */ - if (AddrSize < sizeof(IN6_ADDR)) - { - /* Invalid match, set error code */ - ErrorCode = ERROR_MORE_DATA; - } - else - { - /* It matches, save the address! */ - *(PIN6_ADDR)Address = Addr; - } - } - } - else if (Af != AF_INET) - { - /* You're like.. ATM or something? Get outta here! */ - Af = AF_UNSPEC; - ErrorCode = WSA_INVALID_PARAMETER; - } - - /* Set error if we had one */ - if (ErrorCode) SetLastError(ErrorCode); - - /* Return the address family and size */ - *AddressFamily = Af; - *AddressSize = AddrSize; - - /* Return success or failure */ - return (ErrorCode == ERROR_SUCCESS); -} - -BOOLEAN -WINAPI -Dns_StringToAddressW(OUT PVOID Address, - IN OUT PULONG AddressSize, - IN LPWSTR AddressName, - IN OUT PDWORD AddressFamily) -{ - /* Call the common API */ - return Dns_StringToAddressEx(Address, - AddressSize, - AddressName, - AddressFamily, - TRUE, - FALSE); -} - -BOOLEAN -WINAPI -Dns_StringToDnsAddrEx(OUT PDNS_ADDRESS DnsAddr, - IN PVOID AddressName, - IN DWORD AddressFamily, - IN BOOLEAN Unicode, - IN BOOLEAN Reverse) -{ - IN6_ADDR Addr; - BOOLEAN Return; - INT ErrorCode = ERROR_SUCCESS; - CHAR AnsiName[INET6_ADDRSTRLEN + sizeof("ip6.arpa.")]; - ULONG Size = sizeof(AnsiName); - - /* First check if this is a reverse address string */ - if ((Reverse) && (Unicode)) - { - /* Convert it right now to ANSI as an optimization */ - Dns_StringCopy(AnsiName, - &Size, - AddressName, - 0, - UnicodeString, - AnsiString); - - /* Use the ANSI Name instead */ - AddressName = AnsiName; - } - - /* - * If the caller doesn't know what the family is, we'll assume IPv4 and - * check if we failed or not. If the caller told us it's IPv4, then just - * do IPv4... - */ - if ((AddressFamily == AF_UNSPEC) || (AddressFamily == AF_INET)) - { - /* Now check if the caller gave us the reverse name or not */ - if (Reverse) - { - /* Get the Address */ - Return = Dns_Ip4ReverseNameToAddress_A((PIN_ADDR)&Addr, AddressName); - } - else - { - /* Check if the caller gave us unicode or not */ - if (Unicode) - { - /* Get the Address */ - Return = Dns_Ip4StringToAddress_W((PIN_ADDR)&Addr, AddressName); - } - else - { - /* Get the Address */ - Return = Dns_Ip4StringToAddress_A((PIN_ADDR)&Addr, AddressName); - } - } - - /* Check if we suceeded */ - if (Return) - { - /* Build the IPv4 Address */ - DnsAddr_BuildFromIp4(DnsAddr, *(PIN_ADDR)&Addr, 0); - - /* So we don't go in the code below... */ - AddressFamily = AF_INET; - } - } - - /* If we are here, either AF_INET6 was specified or IPv4 failed */ - if ((AddressFamily == AF_UNSPEC) || (AddressFamily == AF_INET6)) - { - /* Now check if the caller gave us the reverse name or not */ - if (Reverse) - { - /* Get the Address */ - Return = Dns_Ip6ReverseNameToAddress_A(&Addr, AddressName); - if (Return) - { - /* Build the IPv6 Address */ - DnsAddr_BuildFromIp6(DnsAddr, &Addr, 0, 0); - } - else - { - goto Quickie; - } - } - else - { - /* Check if the caller gave us unicode or not */ - if (Unicode) - { - /* Get the Address */ - if (NT_SUCCESS(RtlIpv6StringToAddressExW(AddressName, - &DnsAddr->Ip6Address.sin6_addr, - &DnsAddr->Ip6Address.sin6_scope_id, - &DnsAddr->Ip6Address.sin6_port))) - Return = TRUE; - else - Return = FALSE; - } - else - { - /* Get the Address */ - if (NT_SUCCESS(RtlIpv6StringToAddressExA(AddressName, - &DnsAddr->Ip6Address.sin6_addr, - &DnsAddr->Ip6Address.sin6_scope_id, - &DnsAddr->Ip6Address.sin6_port))) - Return = TRUE; - else - Return = FALSE; - } - } - - /* Check if we suceeded */ - if (Return) - { - /* Finish setting up the structure */ - DnsAddr->Ip6Address.sin6_family = AF_INET6; - DnsAddr->AddressLength = sizeof(SOCKADDR_IN6); - } - } - else if (AddressFamily != AF_INET) - { - /* You're like.. ATM or something? Get outta here! */ - RtlZeroMemory(DnsAddr, sizeof(DNS_ADDRESS)); - SetLastError(WSA_INVALID_PARAMETER); - } - -Quickie: - /* Return success or failure */ - return (ErrorCode == ERROR_SUCCESS); -} - -BOOLEAN -WINAPI -Dns_ReverseNameToDnsAddr_W(OUT PDNS_ADDRESS DnsAddr, - IN LPWSTR Name) -{ - /* Call the common API */ - return Dns_StringToDnsAddrEx(DnsAddr, - Name, - AF_UNSPEC, - TRUE, - TRUE); -} - diff --git a/dll/win32/mswsock/dns/string.c b/dll/win32/mswsock/dns/string.c index d15e4e0d443..e5ec0cfa935 100644 --- a/dll/win32/mswsock/dns/string.c +++ b/dll/win32/mswsock/dns/string.c @@ -255,774 +255,3 @@ Dns_GetBufferLengthForStringCopy(IN PVOID String, return OutputSize; } -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/string.c - * PURPOSE: functions for string manipulation and conversion. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -ULONG -WINAPI -Dns_StringCopy(OUT PVOID Destination, - IN OUT PULONG DestinationSize, - IN PVOID String, - IN ULONG StringSize OPTIONAL, - IN DWORD InputType, - IN DWORD OutputType) -{ - ULONG DestSize; - ULONG OutputSize = 0; - - /* Check if the caller already gave us the string size */ - if (!StringSize) - { - /* He didn't, get the input type */ - if (InputType == UnicodeString) - { - /* Unicode string, calculate the size */ - StringSize = (ULONG)wcslen((LPWSTR)String); - } - else - { - /* ANSI or UTF-8 sting, get the size */ - StringSize = (ULONG)strlen((LPSTR)String); - } - } - - /* Check if we have a limit on the desination size */ - if (DestinationSize) - { - /* Make sure that we can respect it */ - DestSize = Dns_GetBufferLengthForStringCopy(String, - StringSize, - InputType, - OutputType); - if (*DestinationSize < DestSize) - { - /* Fail due to missing buffer space */ - SetLastError(ERROR_MORE_DATA); - - /* Return how much data we actually need */ - *DestinationSize = DestSize; - return 0; - } - else if (!DestSize) - { - /* Fail due to invalid data */ - SetLastError(ERROR_INVALID_DATA); - return 0; - } - - /* Return how much data we actually need */ - *DestinationSize = DestSize; - } - - /* Now check if this is a Unicode String as input */ - if (InputType == UnicodeString) - { - /* Check if the output is ANSI */ - if (OutputType == AnsiString) - { - /* Convert and return the final desination size */ - OutputSize = WideCharToMultiByte(CP_ACP, - 0, - String, - StringSize, - Destination, - -1, - NULL, - NULL) + 1; - } - else if (OutputType == UnicodeString) - { - /* Copy the string */ - StringSize = StringSize * sizeof(WCHAR); - RtlMoveMemory(Destination, String, StringSize); - - /* Return output length */ - OutputSize = StringSize + 2; - } - else if (OutputType == Utf8String) - { - /* FIXME */ - OutputSize = 0; - } - } - else if (InputType == AnsiString) - { - /* It's ANSI, is the output ansi too? */ - if (OutputType == AnsiString) - { - /* Copy the string */ - RtlMoveMemory(Destination, String, StringSize); - - /* Return output length */ - OutputSize = StringSize + 1; - } - else if (OutputType == UnicodeString) - { - /* Convert to Unicode and return size */ - OutputSize = MultiByteToWideChar(CP_ACP, - 0, - String, - StringSize, - Destination, - -1) * sizeof(WCHAR) + 2; - } - else if (OutputType == Utf8String) - { - /* FIXME */ - OutputSize = 0; - } - } - else if (InputType == Utf8String) - { - /* FIXME */ - OutputSize = 0; - } - - /* Return the output size */ - return OutputSize; -} - -LPWSTR -WINAPI -Dns_CreateStringCopy_W(IN LPWSTR Name) -{ - SIZE_T StringLength; - LPWSTR NameCopy; - - /* Make sure that we have a name */ - if (!Name) - { - /* Fail */ - SetLastError(ERROR_INVALID_PARAMETER); - return NULL; - } - - /* Find out the size of the string */ - StringLength = (wcslen(Name) + 1) * sizeof(WCHAR); - - /* Allocate space for the copy */ - NameCopy = Dns_AllocZero(StringLength); - if (NameCopy) - { - /* Copy it */ - RtlCopyMemory(NameCopy, Name, StringLength); - } - else - { - /* Fail */ - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - } - - /* Return the copy */ - return NameCopy; -} - -ULONG -WINAPI -Dns_GetBufferLengthForStringCopy(IN PVOID String, - IN ULONG Size OPTIONAL, - IN DWORD InputType, - IN DWORD OutputType) -{ - ULONG OutputSize = 0; - - /* Check what kind of string this is */ - if (InputType == UnicodeString) - { - /* Check if we have a size */ - if (!Size) - { - /* Get it ourselves */ - Size = (ULONG)wcslen(String); - } - - /* Check the output type */ - if (OutputType == UnicodeString) - { - /* Convert the size to bytes */ - OutputSize = (Size + 1) * sizeof(WCHAR); - } - else if (OutputType == Utf8String) - { - /* FIXME */ - OutputSize = 0; - } - else - { - /* Find out how much it will be in ANSI bytes */ - OutputSize = WideCharToMultiByte(CP_ACP, - 0, - String, - Size, - NULL, - 0, - NULL, - NULL) + 1; - } - } - else if (InputType == AnsiString) - { - /* Check if we have a size */ - if (!Size) - { - /* Get it ourselves */ - Size = (ULONG)strlen(String); - } - - /* Check the output type */ - if (OutputType == AnsiString) - { - /* Just add a byte for the null char */ - OutputSize = Size + 1; - } - else if (OutputType == UnicodeString) - { - /* Calculate the bytes for a Unicode string */ - OutputSize = (MultiByteToWideChar(CP_ACP, - 0, - String, - Size, - NULL, - 0) + 1) * sizeof(WCHAR); - } - else if (OutputType == Utf8String) - { - /* FIXME */ - OutputSize = 0; - } - } - else if (InputType == Utf8String) - { - /* FIXME */ - OutputSize = 0; - } - - /* Return the size required */ - return OutputSize; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/string.c - * PURPOSE: functions for string manipulation and conversion. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -ULONG -WINAPI -Dns_StringCopy(OUT PVOID Destination, - IN OUT PULONG DestinationSize, - IN PVOID String, - IN ULONG StringSize OPTIONAL, - IN DWORD InputType, - IN DWORD OutputType) -{ - ULONG DestSize; - ULONG OutputSize = 0; - - /* Check if the caller already gave us the string size */ - if (!StringSize) - { - /* He didn't, get the input type */ - if (InputType == UnicodeString) - { - /* Unicode string, calculate the size */ - StringSize = (ULONG)wcslen((LPWSTR)String); - } - else - { - /* ANSI or UTF-8 sting, get the size */ - StringSize = (ULONG)strlen((LPSTR)String); - } - } - - /* Check if we have a limit on the desination size */ - if (DestinationSize) - { - /* Make sure that we can respect it */ - DestSize = Dns_GetBufferLengthForStringCopy(String, - StringSize, - InputType, - OutputType); - if (*DestinationSize < DestSize) - { - /* Fail due to missing buffer space */ - SetLastError(ERROR_MORE_DATA); - - /* Return how much data we actually need */ - *DestinationSize = DestSize; - return 0; - } - else if (!DestSize) - { - /* Fail due to invalid data */ - SetLastError(ERROR_INVALID_DATA); - return 0; - } - - /* Return how much data we actually need */ - *DestinationSize = DestSize; - } - - /* Now check if this is a Unicode String as input */ - if (InputType == UnicodeString) - { - /* Check if the output is ANSI */ - if (OutputType == AnsiString) - { - /* Convert and return the final desination size */ - OutputSize = WideCharToMultiByte(CP_ACP, - 0, - String, - StringSize, - Destination, - -1, - NULL, - NULL) + 1; - } - else if (OutputType == UnicodeString) - { - /* Copy the string */ - StringSize = StringSize * sizeof(WCHAR); - RtlMoveMemory(Destination, String, StringSize); - - /* Return output length */ - OutputSize = StringSize + 2; - } - else if (OutputType == Utf8String) - { - /* FIXME */ - OutputSize = 0; - } - } - else if (InputType == AnsiString) - { - /* It's ANSI, is the output ansi too? */ - if (OutputType == AnsiString) - { - /* Copy the string */ - RtlMoveMemory(Destination, String, StringSize); - - /* Return output length */ - OutputSize = StringSize + 1; - } - else if (OutputType == UnicodeString) - { - /* Convert to Unicode and return size */ - OutputSize = MultiByteToWideChar(CP_ACP, - 0, - String, - StringSize, - Destination, - -1) * sizeof(WCHAR) + 2; - } - else if (OutputType == Utf8String) - { - /* FIXME */ - OutputSize = 0; - } - } - else if (InputType == Utf8String) - { - /* FIXME */ - OutputSize = 0; - } - - /* Return the output size */ - return OutputSize; -} - -LPWSTR -WINAPI -Dns_CreateStringCopy_W(IN LPWSTR Name) -{ - SIZE_T StringLength; - LPWSTR NameCopy; - - /* Make sure that we have a name */ - if (!Name) - { - /* Fail */ - SetLastError(ERROR_INVALID_PARAMETER); - return NULL; - } - - /* Find out the size of the string */ - StringLength = (wcslen(Name) + 1) * sizeof(WCHAR); - - /* Allocate space for the copy */ - NameCopy = Dns_AllocZero(StringLength); - if (NameCopy) - { - /* Copy it */ - RtlCopyMemory(NameCopy, Name, StringLength); - } - else - { - /* Fail */ - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - } - - /* Return the copy */ - return NameCopy; -} - -ULONG -WINAPI -Dns_GetBufferLengthForStringCopy(IN PVOID String, - IN ULONG Size OPTIONAL, - IN DWORD InputType, - IN DWORD OutputType) -{ - ULONG OutputSize = 0; - - /* Check what kind of string this is */ - if (InputType == UnicodeString) - { - /* Check if we have a size */ - if (!Size) - { - /* Get it ourselves */ - Size = (ULONG)wcslen(String); - } - - /* Check the output type */ - if (OutputType == UnicodeString) - { - /* Convert the size to bytes */ - OutputSize = (Size + 1) * sizeof(WCHAR); - } - else if (OutputType == Utf8String) - { - /* FIXME */ - OutputSize = 0; - } - else - { - /* Find out how much it will be in ANSI bytes */ - OutputSize = WideCharToMultiByte(CP_ACP, - 0, - String, - Size, - NULL, - 0, - NULL, - NULL) + 1; - } - } - else if (InputType == AnsiString) - { - /* Check if we have a size */ - if (!Size) - { - /* Get it ourselves */ - Size = (ULONG)strlen(String); - } - - /* Check the output type */ - if (OutputType == AnsiString) - { - /* Just add a byte for the null char */ - OutputSize = Size + 1; - } - else if (OutputType == UnicodeString) - { - /* Calculate the bytes for a Unicode string */ - OutputSize = (MultiByteToWideChar(CP_ACP, - 0, - String, - Size, - NULL, - 0) + 1) * sizeof(WCHAR); - } - else if (OutputType == Utf8String) - { - /* FIXME */ - OutputSize = 0; - } - } - else if (InputType == Utf8String) - { - /* FIXME */ - OutputSize = 0; - } - - /* Return the size required */ - return OutputSize; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/string.c - * PURPOSE: functions for string manipulation and conversion. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -ULONG -WINAPI -Dns_StringCopy(OUT PVOID Destination, - IN OUT PULONG DestinationSize, - IN PVOID String, - IN ULONG StringSize OPTIONAL, - IN DWORD InputType, - IN DWORD OutputType) -{ - ULONG DestSize; - ULONG OutputSize = 0; - - /* Check if the caller already gave us the string size */ - if (!StringSize) - { - /* He didn't, get the input type */ - if (InputType == UnicodeString) - { - /* Unicode string, calculate the size */ - StringSize = (ULONG)wcslen((LPWSTR)String); - } - else - { - /* ANSI or UTF-8 sting, get the size */ - StringSize = (ULONG)strlen((LPSTR)String); - } - } - - /* Check if we have a limit on the desination size */ - if (DestinationSize) - { - /* Make sure that we can respect it */ - DestSize = Dns_GetBufferLengthForStringCopy(String, - StringSize, - InputType, - OutputType); - if (*DestinationSize < DestSize) - { - /* Fail due to missing buffer space */ - SetLastError(ERROR_MORE_DATA); - - /* Return how much data we actually need */ - *DestinationSize = DestSize; - return 0; - } - else if (!DestSize) - { - /* Fail due to invalid data */ - SetLastError(ERROR_INVALID_DATA); - return 0; - } - - /* Return how much data we actually need */ - *DestinationSize = DestSize; - } - - /* Now check if this is a Unicode String as input */ - if (InputType == UnicodeString) - { - /* Check if the output is ANSI */ - if (OutputType == AnsiString) - { - /* Convert and return the final desination size */ - OutputSize = WideCharToMultiByte(CP_ACP, - 0, - String, - StringSize, - Destination, - -1, - NULL, - NULL) + 1; - } - else if (OutputType == UnicodeString) - { - /* Copy the string */ - StringSize = StringSize * sizeof(WCHAR); - RtlMoveMemory(Destination, String, StringSize); - - /* Return output length */ - OutputSize = StringSize + 2; - } - else if (OutputType == Utf8String) - { - /* FIXME */ - OutputSize = 0; - } - } - else if (InputType == AnsiString) - { - /* It's ANSI, is the output ansi too? */ - if (OutputType == AnsiString) - { - /* Copy the string */ - RtlMoveMemory(Destination, String, StringSize); - - /* Return output length */ - OutputSize = StringSize + 1; - } - else if (OutputType == UnicodeString) - { - /* Convert to Unicode and return size */ - OutputSize = MultiByteToWideChar(CP_ACP, - 0, - String, - StringSize, - Destination, - -1) * sizeof(WCHAR) + 2; - } - else if (OutputType == Utf8String) - { - /* FIXME */ - OutputSize = 0; - } - } - else if (InputType == Utf8String) - { - /* FIXME */ - OutputSize = 0; - } - - /* Return the output size */ - return OutputSize; -} - -LPWSTR -WINAPI -Dns_CreateStringCopy_W(IN LPWSTR Name) -{ - SIZE_T StringLength; - LPWSTR NameCopy; - - /* Make sure that we have a name */ - if (!Name) - { - /* Fail */ - SetLastError(ERROR_INVALID_PARAMETER); - return NULL; - } - - /* Find out the size of the string */ - StringLength = (wcslen(Name) + 1) * sizeof(WCHAR); - - /* Allocate space for the copy */ - NameCopy = Dns_AllocZero(StringLength); - if (NameCopy) - { - /* Copy it */ - RtlCopyMemory(NameCopy, Name, StringLength); - } - else - { - /* Fail */ - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - } - - /* Return the copy */ - return NameCopy; -} - -ULONG -WINAPI -Dns_GetBufferLengthForStringCopy(IN PVOID String, - IN ULONG Size OPTIONAL, - IN DWORD InputType, - IN DWORD OutputType) -{ - ULONG OutputSize = 0; - - /* Check what kind of string this is */ - if (InputType == UnicodeString) - { - /* Check if we have a size */ - if (!Size) - { - /* Get it ourselves */ - Size = (ULONG)wcslen(String); - } - - /* Check the output type */ - if (OutputType == UnicodeString) - { - /* Convert the size to bytes */ - OutputSize = (Size + 1) * sizeof(WCHAR); - } - else if (OutputType == Utf8String) - { - /* FIXME */ - OutputSize = 0; - } - else - { - /* Find out how much it will be in ANSI bytes */ - OutputSize = WideCharToMultiByte(CP_ACP, - 0, - String, - Size, - NULL, - 0, - NULL, - NULL) + 1; - } - } - else if (InputType == AnsiString) - { - /* Check if we have a size */ - if (!Size) - { - /* Get it ourselves */ - Size = (ULONG)strlen(String); - } - - /* Check the output type */ - if (OutputType == AnsiString) - { - /* Just add a byte for the null char */ - OutputSize = Size + 1; - } - else if (OutputType == UnicodeString) - { - /* Calculate the bytes for a Unicode string */ - OutputSize = (MultiByteToWideChar(CP_ACP, - 0, - String, - Size, - NULL, - 0) + 1) * sizeof(WCHAR); - } - else if (OutputType == Utf8String) - { - /* FIXME */ - OutputSize = 0; - } - } - else if (InputType == Utf8String) - { - /* FIXME */ - OutputSize = 0; - } - - /* Return the size required */ - return OutputSize; -} - diff --git a/dll/win32/mswsock/dns/table.c b/dll/win32/mswsock/dns/table.c index 7660cae281c..266c81b7296 100644 --- a/dll/win32/mswsock/dns/table.c +++ b/dll/win32/mswsock/dns/table.c @@ -12,45 +12,3 @@ /* FUNCTIONS *****************************************************************/ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/table.c - * PURPOSE: Functions for doing Table lookups, such as LUP Flags. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/table.c - * PURPOSE: Functions for doing Table lookups, such as LUP Flags. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/table.c - * PURPOSE: Functions for doing Table lookups, such as LUP Flags. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - diff --git a/dll/win32/mswsock/dns/utf8.c b/dll/win32/mswsock/dns/utf8.c index 55d218bfede..1cb6aa8bd59 100644 --- a/dll/win32/mswsock/dns/utf8.c +++ b/dll/win32/mswsock/dns/utf8.c @@ -12,45 +12,3 @@ /* FUNCTIONS *****************************************************************/ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/utf8.c - * PURPOSE: Functions for doing UTF8 string conversion and manipulation. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/utf8.c - * PURPOSE: Functions for doing UTF8 string conversion and manipulation. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS DNS Shared Library - * FILE: lib/dnslib/utf8.c - * PURPOSE: Functions for doing UTF8 string conversion and manipulation. - */ - -/* INCLUDES ******************************************************************/ -#include "precomp.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - diff --git a/dll/win32/mswsock/msafd/accept.c b/dll/win32/mswsock/msafd/accept.c index 83789067c92..a8644530f5d 100644 --- a/dll/win32/mswsock/msafd/accept.c +++ b/dll/win32/mswsock/msafd/accept.c @@ -973,2928 +973,3 @@ error: return AcceptedHandle; } -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -INT -WSPAPI -SockCoreAccept(IN PSOCKET_INFORMATION Socket, - IN PSOCKET_INFORMATION AcceptedSocket) -{ - INT ErrorCode, ReturnValue; - BOOLEAN BlockMode = Socket->SharedData.NonBlocking; - BOOLEAN Oob = Socket->SharedData.OobInline; - INT HelperContextSize; - PVOID HelperContext = NULL; - HWND hWnd = 0; - UINT wMsg = 0; - HANDLE EventObject = NULL; - ULONG AsyncEvents = 0, NetworkEvents = 0; - CHAR HelperBuffer[256]; - - /* Set the new state */ - AcceptedSocket->SharedData.State = SocketConnected; - - /* Copy some of the settings */ - AcceptedSocket->SharedData.LingerData = Socket->SharedData.LingerData; - AcceptedSocket->SharedData.SizeOfRecvBuffer = Socket->SharedData.SizeOfRecvBuffer; - AcceptedSocket->SharedData.SizeOfSendBuffer = Socket->SharedData.SizeOfSendBuffer; - AcceptedSocket->SharedData.Broadcast = Socket->SharedData.Broadcast; - AcceptedSocket->SharedData.Debug = Socket->SharedData.Debug; - AcceptedSocket->SharedData.OobInline = Socket->SharedData.OobInline; - AcceptedSocket->SharedData.ReuseAddresses = Socket->SharedData.ReuseAddresses; - AcceptedSocket->SharedData.SendTimeout = Socket->SharedData.SendTimeout; - AcceptedSocket->SharedData.RecvTimeout = Socket->SharedData.RecvTimeout; - - /* Check if the old socket had async select */ - if (Socket->SharedData.AsyncEvents) - { - /* Copy the data while we're still under the lock */ - AsyncEvents = Socket->SharedData.AsyncEvents; - hWnd = Socket->SharedData.hWnd; - wMsg = Socket->SharedData.wMsg; - } - else if (Socket->NetworkEvents) - { - /* Copy the data while we're still under the lock */ - NetworkEvents = Socket->NetworkEvents; - EventObject = Socket->EventObject; - } - - /* Check how much space is needed for the context */ - ReturnValue = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, - Socket->Handle, - Socket->TdiAddressHandle, - Socket->TdiConnectionHandle, - SOL_INTERNAL, - SO_CONTEXT, - NULL, - &HelperContextSize); - if (ReturnValue == NO_ERROR) - { - /* Check if our stack buffer is large enough to hold it */ - if (HelperContextSize <= sizeof(HelperBuffer)) - { - /* Use it */ - HelperContext = (PVOID)HelperBuffer; - } - else - { - /* Allocate from the heap instead */ - HelperContext = SockAllocateHeapRoutine(SockPrivateHeap, - 0, - HelperContextSize); - if (!HelperContext) - { - /* Unlock the socket and fail */ - LeaveCriticalSection(&Socket->Lock); - return WSAENOBUFS; - } - } - - /* Get the context */ - ReturnValue = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, - Socket->Handle, - Socket->TdiAddressHandle, - Socket->TdiConnectionHandle, - SOL_INTERNAL, - SO_CONTEXT, - HelperContext, - &HelperContextSize); - } - - /* We're done with the old socket, so we can release the lock */ - LeaveCriticalSection(&Socket->Lock); - - /* Get the TDI Handles for the new socket */ - ErrorCode = SockGetTdiHandles(AcceptedSocket); - - /* Check if we have the handles and the context */ - if ((ErrorCode == NO_ERROR) && (ReturnValue == NO_ERROR)) - { - /* Set the context */ - AcceptedSocket->HelperData->WSHGetSocketInformation(AcceptedSocket->HelperContext, - AcceptedSocket->Handle, - AcceptedSocket->TdiAddressHandle, - AcceptedSocket->TdiConnectionHandle, - SOL_INTERNAL, - SO_CONTEXT, - HelperContext, - &HelperContextSize); - } - - /* Check if we should free from heap */ - if (HelperContext && (HelperContext != (PVOID)HelperBuffer)) - { - /* Free it */ - RtlFreeHeap(SockPrivateHeap, 0, HelperContext); - } - - /* Check if the old socket was non-blocking */ - if (BlockMode) - { - /* Set the new one like that too */ - ErrorCode = SockSetInformation(AcceptedSocket, - AFD_INFO_BLOCKING_MODE, - &BlockMode, - NULL, - NULL); - if (ErrorCode != NO_ERROR) return ErrorCode; - } - - /* Set it internally as well */ - AcceptedSocket->SharedData.NonBlocking = Socket->SharedData.NonBlocking; - - /* Check if inlined OOB was enabled */ - if (Oob) - { - /* Set the new one like that too */ - ErrorCode = SockSetInformation(AcceptedSocket, - AFD_INFO_INLINING_MODE, - &Oob, - NULL, - NULL); - if (ErrorCode != NO_ERROR) return ErrorCode; - } - - /* Set it internally as well */ - AcceptedSocket->SharedData.OobInline = Socket->SharedData.OobInline; - - /* Update the Window Sizes */ - ErrorCode = SockUpdateWindowSizes(AcceptedSocket, FALSE); - if (ErrorCode != NO_ERROR) return ErrorCode; - - /* Check if async select was enabled */ - if (AsyncEvents) - { - /* Call WSPAsyncSelect on the accepted socket too */ - ErrorCode = SockAsyncSelectHelper(AcceptedSocket, - hWnd, - wMsg, - AsyncEvents); - } - else if (NetworkEvents) - { - /* WSPEventSelect was enabled instead, call it on the new socket */ - ErrorCode = SockEventSelectHelper(AcceptedSocket, - EventObject, - NetworkEvents); - } - - /* Check for failure */ - if (ErrorCode != NO_ERROR) return ErrorCode; - - /* Set the new context in AFD */ - ErrorCode = SockSetHandleContext(AcceptedSocket); - if (ErrorCode != NO_ERROR) return ErrorCode; - - /* Return success*/ - return NO_ERROR; -} - -SOCKET -WSPAPI -WSPAccept(SOCKET Handle, - SOCKADDR FAR * SocketAddress, - LPINT SocketAddressLength, - LPCONDITIONPROC lpfnCondition, - DWORD_PTR dwCallbackData, - LPINT lpErrno) -{ - INT ErrorCode, ReturnValue; - PSOCKET_INFORMATION Socket, AcceptedSocket = NULL; - PWINSOCK_TEB_DATA ThreadData; - CHAR AfdAcceptBuffer[32]; - PAFD_RECEIVED_ACCEPT_DATA ReceivedAcceptData = NULL; - ULONG ReceiveBufferSize; - FD_SET ReadFds; - TIMEVAL Timeout; - NTSTATUS Status; - IO_STATUS_BLOCK IoStatusBlock; - ULONG AddressBufferSize; - CHAR AddressBuffer[sizeof(SOCKADDR)]; - PVOID SockAddress; - ULONG ConnectDataSize; - PVOID ConnectData = NULL; - AFD_PENDING_ACCEPT_DATA PendingAcceptData; - INT AddressSize; - PVOID CalleeDataBuffer = NULL; - WSABUF CallerId, CalleeId, CallerData, CalleeData; - GROUP GroupId; - LPQOS Qos = NULL, GroupQos = NULL; - BOOLEAN ValidGroup = TRUE; - AFD_DEFER_ACCEPT_DATA DeferData; - ULONG BytesReturned; - SOCKET AcceptedHandle = INVALID_SOCKET; - AFD_ACCEPT_DATA AcceptData; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* Invalid for datagram sockets */ - if (MSAFD_IS_DGRAM_SOCK(Socket)) - { - /* Fail */ - ErrorCode = WSAEOPNOTSUPP; - goto error; - } - - /* Only valid if the socket is listening */ - if (!Socket->SharedData.Listening) - { - /* Fail */ - ErrorCode = WSAEINVAL; - goto error; - } - - /* Validate address length */ - if (SocketAddressLength && - (Socket->HelperData->MinWSAddressLength > *SocketAddressLength)) - { - /* Fail */ - ErrorCode = WSAEINVAL; - goto error; - } - - /* Calculate how much space we'll need for the Receive Buffer */ - ReceiveBufferSize = sizeof(AFD_RECEIVED_ACCEPT_DATA) + - sizeof(TRANSPORT_ADDRESS) + - Socket->HelperData->MaxTDIAddressLength; - - /* Check if our stack buffer is large enough */ - if (ReceiveBufferSize <= sizeof(AfdAcceptBuffer)) - { - /* Use the stack */ - ReceivedAcceptData = (PVOID)AfdAcceptBuffer; - } - else - { - /* Allocate from heap */ - ReceivedAcceptData = SockAllocateHeapRoutine(SockPrivateHeap, - 0, - ReceiveBufferSize); - if (!ReceivedAcceptData) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - } - - /* If this is non-blocking, make sure there's something for us to accept */ - if (Socket->SharedData.NonBlocking) - { - /* Set up a nonblocking select */ - FD_ZERO(&ReadFds); - FD_SET(Handle, &ReadFds); - Timeout.tv_sec = 0; - Timeout.tv_usec = 0; - - /* See if there's any data */ - ReturnValue = WSPSelect(1, - &ReadFds, - NULL, - NULL, - &Timeout, - lpErrno); - if (ReturnValue == SOCKET_ERROR) - { - /* Fail */ - ErrorCode = *lpErrno; - goto error; - } - - /* Make sure we got a read back */ - if (!FD_ISSET(Handle, &ReadFds)) - { - /* Fail */ - ErrorCode = WSAEWOULDBLOCK; - goto error; - } - } - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_WAIT_FOR_LISTEN, - NULL, - 0, - ReceivedAcceptData, - ReceiveBufferSize); - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion outside the lock */ - LeaveCriticalSection(&Socket->Lock); - SockWaitForSingleObject(ThreadData->EventHandle, - Handle, - MAYBE_BLOCKING_HOOK, - NO_TIMEOUT); - EnterCriticalSection(&Socket->Lock); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - - /* Check if we got a condition callback */ - if (lpfnCondition) - { - /* Find out how much space we'll need for the address */ - AddressBufferSize = Socket->HelperData->MaxWSAddressLength; - - /* Check if our local buffer is enough */ - if (AddressBufferSize <= sizeof(AddressBuffer)) - { - /* It is, use the stack */ - SockAddress = (PVOID)AddressBuffer; - } - else - { - /* Allocate from heap */ - SockAddress = SockAllocateHeapRoutine(SockPrivateHeap, - 0, - AddressBufferSize); - if (!SockAddress) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - } - - /* Assume no connect data */ - ConnectDataSize = 0; - - /* Make sure we support connect data */ - if ((Socket->SharedData.ServiceFlags1 & XP1_CONNECT_DATA)) - { - /* Find out how much data is pending */ - PendingAcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber; - PendingAcceptData.ReturnSize = TRUE; - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_GET_PENDING_CONNECT_DATA, - &PendingAcceptData, - sizeof(PendingAcceptData), - &PendingAcceptData, - sizeof(PendingAcceptData)); - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion */ - SockWaitForSingleObject(ThreadData->EventHandle, - Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - - /* How much data to allocate */ - ConnectDataSize = PtrToUlong(IoStatusBlock.Information); - if (ConnectDataSize) - { - /* Allocate needed space */ - ConnectData = SockAllocateHeapRoutine(SockPrivateHeap, - 0, - ConnectDataSize); - if (!ConnectData) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - - /* Setup the structure to actually get the data now */ - PendingAcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber; - PendingAcceptData.ReturnSize = FALSE; - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_GET_PENDING_CONNECT_DATA, - &PendingAcceptData, - sizeof(PendingAcceptData), - ConnectData, - ConnectDataSize); - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion */ - SockWaitForSingleObject(ThreadData->EventHandle, - Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - } - } - - if ((Socket->SharedData.ServiceFlags1 & XP1_QOS_SUPPORTED)) - { - /* Set the accept data */ - AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber; - AcceptData.ListenHandle = Socket->WshContext.Handle; - - /* Save it in the TEB */ - ThreadData->AcceptData = &AcceptData; - - /* Send the IOCTL to get QOS Size */ - BytesReturned = 0; - ReturnValue = WSPIoctl(Handle, - SIO_GET_QOS, - NULL, - 0, - NULL, - 0, - &BytesReturned, - NULL, - NULL, - NULL, - &ErrorCode); - - /* Check if it failed (it should) */ - if (ReturnValue == SOCKET_ERROR) - { - /* Check if it failed because it had no buffer (it should) */ - if (ErrorCode == WSAEFAULT) - { - /* Make sure it told us how many bytes it needed */ - if (BytesReturned) - { - /* Allocate memory for it */ - Qos = SockAllocateHeapRoutine(SockPrivateHeap, - 0, - BytesReturned); - if (!Qos) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - - /* Save the accept data and set the QoS */ - ThreadData->AcceptData = &AcceptData; - ReturnValue = WSPIoctl(Handle, - SIO_GET_QOS, - NULL, - 0, - Qos, - BytesReturned, - &BytesReturned, - NULL, - NULL, - NULL, - &ErrorCode); - } - } - else - { - /* We got some other weird, error, fail. */ - goto error; - } - } - - /* Save the accept in the TEB */ - ThreadData->AcceptData = &AcceptData; - - /* Send the IOCTL to get Group QOS Size */ - BytesReturned = 0; - ReturnValue = WSPIoctl(Handle, - SIO_GET_GROUP_QOS, - NULL, - 0, - NULL, - 0, - &BytesReturned, - NULL, - NULL, - NULL, - &ErrorCode); - - /* Check if it failed (it should) */ - if (ReturnValue == SOCKET_ERROR) - { - /* Check if it failed because it had no buffer (it should) */ - if (ErrorCode == WSAEFAULT) - { - /* Make sure it told us how many bytes it needed */ - if (BytesReturned) - { - /* Allocate memory for it */ - GroupQos = SockAllocateHeapRoutine(SockPrivateHeap, - 0, - BytesReturned); - if (!GroupQos) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - - /* Save the accept data and set the QoS */ - ThreadData->AcceptData = &AcceptData; - ReturnValue = WSPIoctl(Handle, - SIO_GET_QOS, - NULL, - 0, - GroupQos, - BytesReturned, - &BytesReturned, - NULL, - NULL, - NULL, - &ErrorCode); - } - } - else - { - /* We got some other weird, error, fail. */ - goto error; - } - } - } - - /* Build Callee ID */ - CalleeId.buf = (PVOID)Socket->LocalAddress; - CalleeId.len = Socket->SharedData.SizeOfLocalAddress; - - /* Set up Address in SOCKADDR Format */ - SockBuildSockaddr((PSOCKADDR)SockAddress, - &AddressSize, - &ReceivedAcceptData->Address); - - /* Build Caller ID */ - CallerId.buf = (PVOID)SockAddress; - CallerId.len = AddressSize; - - /* Build Caller Data */ - CallerData.buf = ConnectData; - CallerData.len = ConnectDataSize; - - /* Check if socket supports Conditional Accept */ - if (Socket->SharedData.UseDelayedAcceptance) - { - /* Allocate Buffer for Callee Data */ - CalleeDataBuffer = SockAllocateHeapRoutine(SockPrivateHeap, 0, 4096); - if (CalleeDataBuffer) - { - /* Fill the structure */ - CalleeData.buf = CalleeDataBuffer; - CalleeData.len = 4096; - } - else - { - /* Don't fail, just don't use this... */ - CalleeData.len = 0; - } - } - else - { - /* Nothing */ - CalleeData.buf = NULL; - CalleeData.len = 0; - } - - /* Call the Condition Function */ - ReturnValue = (lpfnCondition)(&CallerId, - !CallerData.buf ? NULL : & CallerData, - NULL, - NULL, - &CalleeId, - !CalleeData.buf ? NULL: & CalleeData, - &GroupId, - dwCallbackData); - - if ((ReturnValue == CF_ACCEPT) && - (GroupId) && - (GroupId != SG_UNCONSTRAINED_GROUP) && - (GroupId != SG_CONSTRAINED_GROUP)) - { - /* Check for validity */ - ErrorCode = SockIsAddressConsistentWithConstrainedGroup(Socket, - GroupId, - SockAddress, - AddressSize); - ValidGroup = (ErrorCode == NO_ERROR); - } - - /* Check if the address was from the heap */ - if (SockAddress != AddressBuffer) - { - /* Free it */ - RtlFreeHeap(SockPrivateHeap, 0, SockAddress); - } - - /* Check if it was accepted */ - if (ReturnValue == CF_ACCEPT) - { - /* Check if the group is invalid, however */ - if (!ValidGroup) goto error; - - /* Now check if QOS is supported */ - if ((Socket->SharedData.ServiceFlags1 & XP1_QOS_SUPPORTED)) - { - /* Check if we had Qos */ - if (Qos) - { - /* Set the accept data */ - AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber; - AcceptData.ListenHandle = Socket->WshContext.Handle; - - /* Save it in the TEB */ - ThreadData->AcceptData = &AcceptData; - - /* Send the IOCTL */ - BytesReturned = 0; - ReturnValue = WSPIoctl(Handle, - SIO_SET_QOS, - Qos, - sizeof(*Qos), - NULL, - 0, - &BytesReturned, - NULL, - NULL, - NULL, - &ErrorCode); - if (ReturnValue == SOCKET_ERROR) goto error; - } - - /* Check if we had Group Qos */ - if (GroupQos) - { - /* Set the accept data */ - AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber; - AcceptData.ListenHandle = Socket->WshContext.Handle; - - /* Save it in the TEB */ - ThreadData->AcceptData = &AcceptData; - - /* Send the IOCTL */ - ReturnValue = WSPIoctl(Handle, - SIO_SET_GROUP_QOS, - GroupQos, - sizeof(*GroupQos), - NULL, - 0, - &BytesReturned, - NULL, - NULL, - NULL, - &ErrorCode); - if (ReturnValue == SOCKET_ERROR) goto error; - } - } - - /* Check if delayed acceptance is used and we have callee data */ - if ((Socket->HelperData->UseDelayedAcceptance) && (CalleeData.len)) - { - /* Save the accept data in the TEB */ - ThreadData->AcceptData = &AcceptData; - - /* Set the connect data */ - ErrorCode = SockGetConnectData(Socket, - IOCTL_AFD_SET_CONNECT_DATA, - CalleeData.buf, - CalleeData.len, - NULL); - if (ErrorCode == SOCKET_ERROR) goto error; - } - } - else - { - /* Callback rejected. Build Defer Structure */ - DeferData.SequenceNumber = ReceivedAcceptData->SequenceNumber; - DeferData.RejectConnection = (ReturnValue == CF_REJECT); - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_DEFER_ACCEPT, - &DeferData, - sizeof(DeferData), - NULL, - 0); - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - - if (ReturnValue == CF_REJECT) - { - /* The connection was refused */ - ErrorCode = WSAECONNREFUSED; - } - else - { - /* The connection was deferred */ - ErrorCode = WSATRY_AGAIN; - } - - /* Fail */ - goto error; - } - } - - /* Create a new Socket */ - ErrorCode = SockSocket(Socket->SharedData.AddressFamily, - Socket->SharedData.SocketType, - Socket->SharedData.Protocol, - &Socket->ProviderId, - GroupId, - Socket->SharedData.CreateFlags, - Socket->SharedData.ProviderFlags, - Socket->SharedData.ServiceFlags1, - Socket->SharedData.CatalogEntryId, - &AcceptedSocket); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - goto error; - } - - /* Set up the Accept Structure */ - AcceptData.ListenHandle = AcceptedSocket->WshContext.Handle; - AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber; - - /* Build the socket address */ - SockBuildSockaddr(AcceptedSocket->RemoteAddress, - &AcceptedSocket->SharedData.SizeOfRemoteAddress, - &ReceivedAcceptData->Address); - - /* Copy the local address */ - RtlCopyMemory(AcceptedSocket->LocalAddress, - Socket->LocalAddress, - Socket->SharedData.SizeOfLocalAddress); - AcceptedSocket->SharedData.SizeOfLocalAddress = Socket->SharedData.SizeOfLocalAddress; - - /* We can release the accepted socket's lock now */ - LeaveCriticalSection(&AcceptedSocket->Lock); - - /* Send IOCTL to Accept */ - AcceptData.UseSAN = SockSanEnabled; - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_ACCEPT, - &AcceptData, - sizeof(AcceptData), - NULL, - 0); - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion outside the lock */ - LeaveCriticalSection(&Socket->Lock); - SockWaitForSingleObject(ThreadData->EventHandle, - Handle, - MAYBE_BLOCKING_HOOK, - NO_TIMEOUT); - EnterCriticalSection(&Socket->Lock); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - - /* Notify the helper DLL */ - ErrorCode = SockNotifyHelperDll(AcceptedSocket, WSH_NOTIFY_ACCEPT); - if (ErrorCode != NO_ERROR) goto error; - - /* If the caller sent a socket address pointer and length */ - if (SocketAddress && SocketAddressLength) - { - /* Return the address in its buffer */ - ErrorCode = SockBuildSockaddr(SocketAddress, - SocketAddressLength, - &ReceivedAcceptData->Address); - if (ErrorCode != NO_ERROR) goto error; - } - - /* Check if async select was active */ - if (SockAsyncSelectCalled) - { - /* Re-enable the regular accept event */ - SockReenableAsyncSelectEvent(Socket, FD_ACCEPT); - } - - /* Finally, do the internal core accept code */ - ErrorCode = SockCoreAccept(Socket, AcceptedSocket); - if (ErrorCode != NO_ERROR) goto error; - - /* Call WPU to tell it about the new handle */ - AcceptedHandle = SockUpcallTable->lpWPUModifyIFSHandle(AcceptedSocket->SharedData.CatalogEntryId, - (SOCKET)AcceptedSocket->WshContext.Handle, - &ErrorCode); - - /* Dereference the socket and clear its pointer for error code logic */ - SockDereferenceSocket(Socket); - Socket = NULL; - -error: - - /* Check if we have a socket here */ - if (Socket) - { - /* Check if async select was active */ - if (SockAsyncSelectCalled) - { - /* Re-enable the regular accept event */ - SockReenableAsyncSelectEvent(Socket, FD_ACCEPT); - } - - /* Unlock and dereference it */ - LeaveCriticalSection(&Socket->Lock); - SockDereferenceSocket(Socket); - } - - /* Check if we got the accepted socket */ - if (AcceptedSocket) - { - /* Check if the accepted socket also has a handle */ - if (ErrorCode == NO_ERROR) - { - /* Close the socket */ - SockCloseSocket(AcceptedSocket); - } - - /* Dereference it */ - SockDereferenceSocket(AcceptedSocket); - } - - /* Check if the accept buffer was from the heap */ - if (ReceivedAcceptData && (ReceivedAcceptData != (PVOID)AfdAcceptBuffer)) - { - /* Free it */ - RtlFreeHeap(SockPrivateHeap, 0, ReceivedAcceptData); - } - - /* Check if we have a connect data buffer */ - if (ConnectData) - { - /* Free it */ - RtlFreeHeap(SockPrivateHeap, 0, ConnectData); - } - - /* Check if we have a callee data buffer */ - if (CalleeDataBuffer) - { - /* Free it */ - RtlFreeHeap(SockPrivateHeap, 0, CalleeDataBuffer); - } - - /* Check if we have allocated QOS structures */ - if (Qos) - { - /* Free it */ - RtlFreeHeap(SockPrivateHeap, 0, Qos); - } - if (GroupQos) - { - /* Free it */ - RtlFreeHeap(SockPrivateHeap, 0, GroupQos); - } - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return INVALID_SOCKET; - } - - /* Return the new handle */ - return AcceptedHandle; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -INT -WSPAPI -SockCoreAccept(IN PSOCKET_INFORMATION Socket, - IN PSOCKET_INFORMATION AcceptedSocket) -{ - INT ErrorCode, ReturnValue; - BOOLEAN BlockMode = Socket->SharedData.NonBlocking; - BOOLEAN Oob = Socket->SharedData.OobInline; - INT HelperContextSize; - PVOID HelperContext = NULL; - HWND hWnd = 0; - UINT wMsg = 0; - HANDLE EventObject = NULL; - ULONG AsyncEvents = 0, NetworkEvents = 0; - CHAR HelperBuffer[256]; - - /* Set the new state */ - AcceptedSocket->SharedData.State = SocketConnected; - - /* Copy some of the settings */ - AcceptedSocket->SharedData.LingerData = Socket->SharedData.LingerData; - AcceptedSocket->SharedData.SizeOfRecvBuffer = Socket->SharedData.SizeOfRecvBuffer; - AcceptedSocket->SharedData.SizeOfSendBuffer = Socket->SharedData.SizeOfSendBuffer; - AcceptedSocket->SharedData.Broadcast = Socket->SharedData.Broadcast; - AcceptedSocket->SharedData.Debug = Socket->SharedData.Debug; - AcceptedSocket->SharedData.OobInline = Socket->SharedData.OobInline; - AcceptedSocket->SharedData.ReuseAddresses = Socket->SharedData.ReuseAddresses; - AcceptedSocket->SharedData.SendTimeout = Socket->SharedData.SendTimeout; - AcceptedSocket->SharedData.RecvTimeout = Socket->SharedData.RecvTimeout; - - /* Check if the old socket had async select */ - if (Socket->SharedData.AsyncEvents) - { - /* Copy the data while we're still under the lock */ - AsyncEvents = Socket->SharedData.AsyncEvents; - hWnd = Socket->SharedData.hWnd; - wMsg = Socket->SharedData.wMsg; - } - else if (Socket->NetworkEvents) - { - /* Copy the data while we're still under the lock */ - NetworkEvents = Socket->NetworkEvents; - EventObject = Socket->EventObject; - } - - /* Check how much space is needed for the context */ - ReturnValue = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, - Socket->Handle, - Socket->TdiAddressHandle, - Socket->TdiConnectionHandle, - SOL_INTERNAL, - SO_CONTEXT, - NULL, - &HelperContextSize); - if (ReturnValue == NO_ERROR) - { - /* Check if our stack buffer is large enough to hold it */ - if (HelperContextSize <= sizeof(HelperBuffer)) - { - /* Use it */ - HelperContext = (PVOID)HelperBuffer; - } - else - { - /* Allocate from the heap instead */ - HelperContext = SockAllocateHeapRoutine(SockPrivateHeap, - 0, - HelperContextSize); - if (!HelperContext) - { - /* Unlock the socket and fail */ - LeaveCriticalSection(&Socket->Lock); - return WSAENOBUFS; - } - } - - /* Get the context */ - ReturnValue = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, - Socket->Handle, - Socket->TdiAddressHandle, - Socket->TdiConnectionHandle, - SOL_INTERNAL, - SO_CONTEXT, - HelperContext, - &HelperContextSize); - } - - /* We're done with the old socket, so we can release the lock */ - LeaveCriticalSection(&Socket->Lock); - - /* Get the TDI Handles for the new socket */ - ErrorCode = SockGetTdiHandles(AcceptedSocket); - - /* Check if we have the handles and the context */ - if ((ErrorCode == NO_ERROR) && (ReturnValue == NO_ERROR)) - { - /* Set the context */ - AcceptedSocket->HelperData->WSHGetSocketInformation(AcceptedSocket->HelperContext, - AcceptedSocket->Handle, - AcceptedSocket->TdiAddressHandle, - AcceptedSocket->TdiConnectionHandle, - SOL_INTERNAL, - SO_CONTEXT, - HelperContext, - &HelperContextSize); - } - - /* Check if we should free from heap */ - if (HelperContext && (HelperContext != (PVOID)HelperBuffer)) - { - /* Free it */ - RtlFreeHeap(SockPrivateHeap, 0, HelperContext); - } - - /* Check if the old socket was non-blocking */ - if (BlockMode) - { - /* Set the new one like that too */ - ErrorCode = SockSetInformation(AcceptedSocket, - AFD_INFO_BLOCKING_MODE, - &BlockMode, - NULL, - NULL); - if (ErrorCode != NO_ERROR) return ErrorCode; - } - - /* Set it internally as well */ - AcceptedSocket->SharedData.NonBlocking = Socket->SharedData.NonBlocking; - - /* Check if inlined OOB was enabled */ - if (Oob) - { - /* Set the new one like that too */ - ErrorCode = SockSetInformation(AcceptedSocket, - AFD_INFO_INLINING_MODE, - &Oob, - NULL, - NULL); - if (ErrorCode != NO_ERROR) return ErrorCode; - } - - /* Set it internally as well */ - AcceptedSocket->SharedData.OobInline = Socket->SharedData.OobInline; - - /* Update the Window Sizes */ - ErrorCode = SockUpdateWindowSizes(AcceptedSocket, FALSE); - if (ErrorCode != NO_ERROR) return ErrorCode; - - /* Check if async select was enabled */ - if (AsyncEvents) - { - /* Call WSPAsyncSelect on the accepted socket too */ - ErrorCode = SockAsyncSelectHelper(AcceptedSocket, - hWnd, - wMsg, - AsyncEvents); - } - else if (NetworkEvents) - { - /* WSPEventSelect was enabled instead, call it on the new socket */ - ErrorCode = SockEventSelectHelper(AcceptedSocket, - EventObject, - NetworkEvents); - } - - /* Check for failure */ - if (ErrorCode != NO_ERROR) return ErrorCode; - - /* Set the new context in AFD */ - ErrorCode = SockSetHandleContext(AcceptedSocket); - if (ErrorCode != NO_ERROR) return ErrorCode; - - /* Return success*/ - return NO_ERROR; -} - -SOCKET -WSPAPI -WSPAccept(SOCKET Handle, - SOCKADDR FAR * SocketAddress, - LPINT SocketAddressLength, - LPCONDITIONPROC lpfnCondition, - DWORD_PTR dwCallbackData, - LPINT lpErrno) -{ - INT ErrorCode, ReturnValue; - PSOCKET_INFORMATION Socket, AcceptedSocket = NULL; - PWINSOCK_TEB_DATA ThreadData; - CHAR AfdAcceptBuffer[32]; - PAFD_RECEIVED_ACCEPT_DATA ReceivedAcceptData = NULL; - ULONG ReceiveBufferSize; - FD_SET ReadFds; - TIMEVAL Timeout; - NTSTATUS Status; - IO_STATUS_BLOCK IoStatusBlock; - ULONG AddressBufferSize; - CHAR AddressBuffer[sizeof(SOCKADDR)]; - PVOID SockAddress; - ULONG ConnectDataSize; - PVOID ConnectData = NULL; - AFD_PENDING_ACCEPT_DATA PendingAcceptData; - INT AddressSize; - PVOID CalleeDataBuffer = NULL; - WSABUF CallerId, CalleeId, CallerData, CalleeData; - GROUP GroupId; - LPQOS Qos = NULL, GroupQos = NULL; - BOOLEAN ValidGroup = TRUE; - AFD_DEFER_ACCEPT_DATA DeferData; - ULONG BytesReturned; - SOCKET AcceptedHandle = INVALID_SOCKET; - AFD_ACCEPT_DATA AcceptData; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* Invalid for datagram sockets */ - if (MSAFD_IS_DGRAM_SOCK(Socket)) - { - /* Fail */ - ErrorCode = WSAEOPNOTSUPP; - goto error; - } - - /* Only valid if the socket is listening */ - if (!Socket->SharedData.Listening) - { - /* Fail */ - ErrorCode = WSAEINVAL; - goto error; - } - - /* Validate address length */ - if (SocketAddressLength && - (Socket->HelperData->MinWSAddressLength > *SocketAddressLength)) - { - /* Fail */ - ErrorCode = WSAEINVAL; - goto error; - } - - /* Calculate how much space we'll need for the Receive Buffer */ - ReceiveBufferSize = sizeof(AFD_RECEIVED_ACCEPT_DATA) + - sizeof(TRANSPORT_ADDRESS) + - Socket->HelperData->MaxTDIAddressLength; - - /* Check if our stack buffer is large enough */ - if (ReceiveBufferSize <= sizeof(AfdAcceptBuffer)) - { - /* Use the stack */ - ReceivedAcceptData = (PVOID)AfdAcceptBuffer; - } - else - { - /* Allocate from heap */ - ReceivedAcceptData = SockAllocateHeapRoutine(SockPrivateHeap, - 0, - ReceiveBufferSize); - if (!ReceivedAcceptData) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - } - - /* If this is non-blocking, make sure there's something for us to accept */ - if (Socket->SharedData.NonBlocking) - { - /* Set up a nonblocking select */ - FD_ZERO(&ReadFds); - FD_SET(Handle, &ReadFds); - Timeout.tv_sec = 0; - Timeout.tv_usec = 0; - - /* See if there's any data */ - ReturnValue = WSPSelect(1, - &ReadFds, - NULL, - NULL, - &Timeout, - lpErrno); - if (ReturnValue == SOCKET_ERROR) - { - /* Fail */ - ErrorCode = *lpErrno; - goto error; - } - - /* Make sure we got a read back */ - if (!FD_ISSET(Handle, &ReadFds)) - { - /* Fail */ - ErrorCode = WSAEWOULDBLOCK; - goto error; - } - } - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_WAIT_FOR_LISTEN, - NULL, - 0, - ReceivedAcceptData, - ReceiveBufferSize); - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion outside the lock */ - LeaveCriticalSection(&Socket->Lock); - SockWaitForSingleObject(ThreadData->EventHandle, - Handle, - MAYBE_BLOCKING_HOOK, - NO_TIMEOUT); - EnterCriticalSection(&Socket->Lock); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - - /* Check if we got a condition callback */ - if (lpfnCondition) - { - /* Find out how much space we'll need for the address */ - AddressBufferSize = Socket->HelperData->MaxWSAddressLength; - - /* Check if our local buffer is enough */ - if (AddressBufferSize <= sizeof(AddressBuffer)) - { - /* It is, use the stack */ - SockAddress = (PVOID)AddressBuffer; - } - else - { - /* Allocate from heap */ - SockAddress = SockAllocateHeapRoutine(SockPrivateHeap, - 0, - AddressBufferSize); - if (!SockAddress) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - } - - /* Assume no connect data */ - ConnectDataSize = 0; - - /* Make sure we support connect data */ - if ((Socket->SharedData.ServiceFlags1 & XP1_CONNECT_DATA)) - { - /* Find out how much data is pending */ - PendingAcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber; - PendingAcceptData.ReturnSize = TRUE; - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_GET_PENDING_CONNECT_DATA, - &PendingAcceptData, - sizeof(PendingAcceptData), - &PendingAcceptData, - sizeof(PendingAcceptData)); - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion */ - SockWaitForSingleObject(ThreadData->EventHandle, - Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - - /* How much data to allocate */ - ConnectDataSize = PtrToUlong(IoStatusBlock.Information); - if (ConnectDataSize) - { - /* Allocate needed space */ - ConnectData = SockAllocateHeapRoutine(SockPrivateHeap, - 0, - ConnectDataSize); - if (!ConnectData) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - - /* Setup the structure to actually get the data now */ - PendingAcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber; - PendingAcceptData.ReturnSize = FALSE; - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_GET_PENDING_CONNECT_DATA, - &PendingAcceptData, - sizeof(PendingAcceptData), - ConnectData, - ConnectDataSize); - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion */ - SockWaitForSingleObject(ThreadData->EventHandle, - Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - } - } - - if ((Socket->SharedData.ServiceFlags1 & XP1_QOS_SUPPORTED)) - { - /* Set the accept data */ - AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber; - AcceptData.ListenHandle = Socket->WshContext.Handle; - - /* Save it in the TEB */ - ThreadData->AcceptData = &AcceptData; - - /* Send the IOCTL to get QOS Size */ - BytesReturned = 0; - ReturnValue = WSPIoctl(Handle, - SIO_GET_QOS, - NULL, - 0, - NULL, - 0, - &BytesReturned, - NULL, - NULL, - NULL, - &ErrorCode); - - /* Check if it failed (it should) */ - if (ReturnValue == SOCKET_ERROR) - { - /* Check if it failed because it had no buffer (it should) */ - if (ErrorCode == WSAEFAULT) - { - /* Make sure it told us how many bytes it needed */ - if (BytesReturned) - { - /* Allocate memory for it */ - Qos = SockAllocateHeapRoutine(SockPrivateHeap, - 0, - BytesReturned); - if (!Qos) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - - /* Save the accept data and set the QoS */ - ThreadData->AcceptData = &AcceptData; - ReturnValue = WSPIoctl(Handle, - SIO_GET_QOS, - NULL, - 0, - Qos, - BytesReturned, - &BytesReturned, - NULL, - NULL, - NULL, - &ErrorCode); - } - } - else - { - /* We got some other weird, error, fail. */ - goto error; - } - } - - /* Save the accept in the TEB */ - ThreadData->AcceptData = &AcceptData; - - /* Send the IOCTL to get Group QOS Size */ - BytesReturned = 0; - ReturnValue = WSPIoctl(Handle, - SIO_GET_GROUP_QOS, - NULL, - 0, - NULL, - 0, - &BytesReturned, - NULL, - NULL, - NULL, - &ErrorCode); - - /* Check if it failed (it should) */ - if (ReturnValue == SOCKET_ERROR) - { - /* Check if it failed because it had no buffer (it should) */ - if (ErrorCode == WSAEFAULT) - { - /* Make sure it told us how many bytes it needed */ - if (BytesReturned) - { - /* Allocate memory for it */ - GroupQos = SockAllocateHeapRoutine(SockPrivateHeap, - 0, - BytesReturned); - if (!GroupQos) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - - /* Save the accept data and set the QoS */ - ThreadData->AcceptData = &AcceptData; - ReturnValue = WSPIoctl(Handle, - SIO_GET_QOS, - NULL, - 0, - GroupQos, - BytesReturned, - &BytesReturned, - NULL, - NULL, - NULL, - &ErrorCode); - } - } - else - { - /* We got some other weird, error, fail. */ - goto error; - } - } - } - - /* Build Callee ID */ - CalleeId.buf = (PVOID)Socket->LocalAddress; - CalleeId.len = Socket->SharedData.SizeOfLocalAddress; - - /* Set up Address in SOCKADDR Format */ - SockBuildSockaddr((PSOCKADDR)SockAddress, - &AddressSize, - &ReceivedAcceptData->Address); - - /* Build Caller ID */ - CallerId.buf = (PVOID)SockAddress; - CallerId.len = AddressSize; - - /* Build Caller Data */ - CallerData.buf = ConnectData; - CallerData.len = ConnectDataSize; - - /* Check if socket supports Conditional Accept */ - if (Socket->SharedData.UseDelayedAcceptance) - { - /* Allocate Buffer for Callee Data */ - CalleeDataBuffer = SockAllocateHeapRoutine(SockPrivateHeap, 0, 4096); - if (CalleeDataBuffer) - { - /* Fill the structure */ - CalleeData.buf = CalleeDataBuffer; - CalleeData.len = 4096; - } - else - { - /* Don't fail, just don't use this... */ - CalleeData.len = 0; - } - } - else - { - /* Nothing */ - CalleeData.buf = NULL; - CalleeData.len = 0; - } - - /* Call the Condition Function */ - ReturnValue = (lpfnCondition)(&CallerId, - !CallerData.buf ? NULL : & CallerData, - NULL, - NULL, - &CalleeId, - !CalleeData.buf ? NULL: & CalleeData, - &GroupId, - dwCallbackData); - - if ((ReturnValue == CF_ACCEPT) && - (GroupId) && - (GroupId != SG_UNCONSTRAINED_GROUP) && - (GroupId != SG_CONSTRAINED_GROUP)) - { - /* Check for validity */ - ErrorCode = SockIsAddressConsistentWithConstrainedGroup(Socket, - GroupId, - SockAddress, - AddressSize); - ValidGroup = (ErrorCode == NO_ERROR); - } - - /* Check if the address was from the heap */ - if (SockAddress != AddressBuffer) - { - /* Free it */ - RtlFreeHeap(SockPrivateHeap, 0, SockAddress); - } - - /* Check if it was accepted */ - if (ReturnValue == CF_ACCEPT) - { - /* Check if the group is invalid, however */ - if (!ValidGroup) goto error; - - /* Now check if QOS is supported */ - if ((Socket->SharedData.ServiceFlags1 & XP1_QOS_SUPPORTED)) - { - /* Check if we had Qos */ - if (Qos) - { - /* Set the accept data */ - AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber; - AcceptData.ListenHandle = Socket->WshContext.Handle; - - /* Save it in the TEB */ - ThreadData->AcceptData = &AcceptData; - - /* Send the IOCTL */ - BytesReturned = 0; - ReturnValue = WSPIoctl(Handle, - SIO_SET_QOS, - Qos, - sizeof(*Qos), - NULL, - 0, - &BytesReturned, - NULL, - NULL, - NULL, - &ErrorCode); - if (ReturnValue == SOCKET_ERROR) goto error; - } - - /* Check if we had Group Qos */ - if (GroupQos) - { - /* Set the accept data */ - AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber; - AcceptData.ListenHandle = Socket->WshContext.Handle; - - /* Save it in the TEB */ - ThreadData->AcceptData = &AcceptData; - - /* Send the IOCTL */ - ReturnValue = WSPIoctl(Handle, - SIO_SET_GROUP_QOS, - GroupQos, - sizeof(*GroupQos), - NULL, - 0, - &BytesReturned, - NULL, - NULL, - NULL, - &ErrorCode); - if (ReturnValue == SOCKET_ERROR) goto error; - } - } - - /* Check if delayed acceptance is used and we have callee data */ - if ((Socket->HelperData->UseDelayedAcceptance) && (CalleeData.len)) - { - /* Save the accept data in the TEB */ - ThreadData->AcceptData = &AcceptData; - - /* Set the connect data */ - ErrorCode = SockGetConnectData(Socket, - IOCTL_AFD_SET_CONNECT_DATA, - CalleeData.buf, - CalleeData.len, - NULL); - if (ErrorCode == SOCKET_ERROR) goto error; - } - } - else - { - /* Callback rejected. Build Defer Structure */ - DeferData.SequenceNumber = ReceivedAcceptData->SequenceNumber; - DeferData.RejectConnection = (ReturnValue == CF_REJECT); - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_DEFER_ACCEPT, - &DeferData, - sizeof(DeferData), - NULL, - 0); - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - - if (ReturnValue == CF_REJECT) - { - /* The connection was refused */ - ErrorCode = WSAECONNREFUSED; - } - else - { - /* The connection was deferred */ - ErrorCode = WSATRY_AGAIN; - } - - /* Fail */ - goto error; - } - } - - /* Create a new Socket */ - ErrorCode = SockSocket(Socket->SharedData.AddressFamily, - Socket->SharedData.SocketType, - Socket->SharedData.Protocol, - &Socket->ProviderId, - GroupId, - Socket->SharedData.CreateFlags, - Socket->SharedData.ProviderFlags, - Socket->SharedData.ServiceFlags1, - Socket->SharedData.CatalogEntryId, - &AcceptedSocket); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - goto error; - } - - /* Set up the Accept Structure */ - AcceptData.ListenHandle = AcceptedSocket->WshContext.Handle; - AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber; - - /* Build the socket address */ - SockBuildSockaddr(AcceptedSocket->RemoteAddress, - &AcceptedSocket->SharedData.SizeOfRemoteAddress, - &ReceivedAcceptData->Address); - - /* Copy the local address */ - RtlCopyMemory(AcceptedSocket->LocalAddress, - Socket->LocalAddress, - Socket->SharedData.SizeOfLocalAddress); - AcceptedSocket->SharedData.SizeOfLocalAddress = Socket->SharedData.SizeOfLocalAddress; - - /* We can release the accepted socket's lock now */ - LeaveCriticalSection(&AcceptedSocket->Lock); - - /* Send IOCTL to Accept */ - AcceptData.UseSAN = SockSanEnabled; - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_ACCEPT, - &AcceptData, - sizeof(AcceptData), - NULL, - 0); - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion outside the lock */ - LeaveCriticalSection(&Socket->Lock); - SockWaitForSingleObject(ThreadData->EventHandle, - Handle, - MAYBE_BLOCKING_HOOK, - NO_TIMEOUT); - EnterCriticalSection(&Socket->Lock); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - - /* Notify the helper DLL */ - ErrorCode = SockNotifyHelperDll(AcceptedSocket, WSH_NOTIFY_ACCEPT); - if (ErrorCode != NO_ERROR) goto error; - - /* If the caller sent a socket address pointer and length */ - if (SocketAddress && SocketAddressLength) - { - /* Return the address in its buffer */ - ErrorCode = SockBuildSockaddr(SocketAddress, - SocketAddressLength, - &ReceivedAcceptData->Address); - if (ErrorCode != NO_ERROR) goto error; - } - - /* Check if async select was active */ - if (SockAsyncSelectCalled) - { - /* Re-enable the regular accept event */ - SockReenableAsyncSelectEvent(Socket, FD_ACCEPT); - } - - /* Finally, do the internal core accept code */ - ErrorCode = SockCoreAccept(Socket, AcceptedSocket); - if (ErrorCode != NO_ERROR) goto error; - - /* Call WPU to tell it about the new handle */ - AcceptedHandle = SockUpcallTable->lpWPUModifyIFSHandle(AcceptedSocket->SharedData.CatalogEntryId, - (SOCKET)AcceptedSocket->WshContext.Handle, - &ErrorCode); - - /* Dereference the socket and clear its pointer for error code logic */ - SockDereferenceSocket(Socket); - Socket = NULL; - -error: - - /* Check if we have a socket here */ - if (Socket) - { - /* Check if async select was active */ - if (SockAsyncSelectCalled) - { - /* Re-enable the regular accept event */ - SockReenableAsyncSelectEvent(Socket, FD_ACCEPT); - } - - /* Unlock and dereference it */ - LeaveCriticalSection(&Socket->Lock); - SockDereferenceSocket(Socket); - } - - /* Check if we got the accepted socket */ - if (AcceptedSocket) - { - /* Check if the accepted socket also has a handle */ - if (ErrorCode == NO_ERROR) - { - /* Close the socket */ - SockCloseSocket(AcceptedSocket); - } - - /* Dereference it */ - SockDereferenceSocket(AcceptedSocket); - } - - /* Check if the accept buffer was from the heap */ - if (ReceivedAcceptData && (ReceivedAcceptData != (PVOID)AfdAcceptBuffer)) - { - /* Free it */ - RtlFreeHeap(SockPrivateHeap, 0, ReceivedAcceptData); - } - - /* Check if we have a connect data buffer */ - if (ConnectData) - { - /* Free it */ - RtlFreeHeap(SockPrivateHeap, 0, ConnectData); - } - - /* Check if we have a callee data buffer */ - if (CalleeDataBuffer) - { - /* Free it */ - RtlFreeHeap(SockPrivateHeap, 0, CalleeDataBuffer); - } - - /* Check if we have allocated QOS structures */ - if (Qos) - { - /* Free it */ - RtlFreeHeap(SockPrivateHeap, 0, Qos); - } - if (GroupQos) - { - /* Free it */ - RtlFreeHeap(SockPrivateHeap, 0, GroupQos); - } - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return INVALID_SOCKET; - } - - /* Return the new handle */ - return AcceptedHandle; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -INT -WSPAPI -SockCoreAccept(IN PSOCKET_INFORMATION Socket, - IN PSOCKET_INFORMATION AcceptedSocket) -{ - INT ErrorCode, ReturnValue; - BOOLEAN BlockMode = Socket->SharedData.NonBlocking; - BOOLEAN Oob = Socket->SharedData.OobInline; - INT HelperContextSize; - PVOID HelperContext = NULL; - HWND hWnd = 0; - UINT wMsg = 0; - HANDLE EventObject = NULL; - ULONG AsyncEvents = 0, NetworkEvents = 0; - CHAR HelperBuffer[256]; - - /* Set the new state */ - AcceptedSocket->SharedData.State = SocketConnected; - - /* Copy some of the settings */ - AcceptedSocket->SharedData.LingerData = Socket->SharedData.LingerData; - AcceptedSocket->SharedData.SizeOfRecvBuffer = Socket->SharedData.SizeOfRecvBuffer; - AcceptedSocket->SharedData.SizeOfSendBuffer = Socket->SharedData.SizeOfSendBuffer; - AcceptedSocket->SharedData.Broadcast = Socket->SharedData.Broadcast; - AcceptedSocket->SharedData.Debug = Socket->SharedData.Debug; - AcceptedSocket->SharedData.OobInline = Socket->SharedData.OobInline; - AcceptedSocket->SharedData.ReuseAddresses = Socket->SharedData.ReuseAddresses; - AcceptedSocket->SharedData.SendTimeout = Socket->SharedData.SendTimeout; - AcceptedSocket->SharedData.RecvTimeout = Socket->SharedData.RecvTimeout; - - /* Check if the old socket had async select */ - if (Socket->SharedData.AsyncEvents) - { - /* Copy the data while we're still under the lock */ - AsyncEvents = Socket->SharedData.AsyncEvents; - hWnd = Socket->SharedData.hWnd; - wMsg = Socket->SharedData.wMsg; - } - else if (Socket->NetworkEvents) - { - /* Copy the data while we're still under the lock */ - NetworkEvents = Socket->NetworkEvents; - EventObject = Socket->EventObject; - } - - /* Check how much space is needed for the context */ - ReturnValue = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, - Socket->Handle, - Socket->TdiAddressHandle, - Socket->TdiConnectionHandle, - SOL_INTERNAL, - SO_CONTEXT, - NULL, - &HelperContextSize); - if (ReturnValue == NO_ERROR) - { - /* Check if our stack buffer is large enough to hold it */ - if (HelperContextSize <= sizeof(HelperBuffer)) - { - /* Use it */ - HelperContext = (PVOID)HelperBuffer; - } - else - { - /* Allocate from the heap instead */ - HelperContext = SockAllocateHeapRoutine(SockPrivateHeap, - 0, - HelperContextSize); - if (!HelperContext) - { - /* Unlock the socket and fail */ - LeaveCriticalSection(&Socket->Lock); - return WSAENOBUFS; - } - } - - /* Get the context */ - ReturnValue = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, - Socket->Handle, - Socket->TdiAddressHandle, - Socket->TdiConnectionHandle, - SOL_INTERNAL, - SO_CONTEXT, - HelperContext, - &HelperContextSize); - } - - /* We're done with the old socket, so we can release the lock */ - LeaveCriticalSection(&Socket->Lock); - - /* Get the TDI Handles for the new socket */ - ErrorCode = SockGetTdiHandles(AcceptedSocket); - - /* Check if we have the handles and the context */ - if ((ErrorCode == NO_ERROR) && (ReturnValue == NO_ERROR)) - { - /* Set the context */ - AcceptedSocket->HelperData->WSHGetSocketInformation(AcceptedSocket->HelperContext, - AcceptedSocket->Handle, - AcceptedSocket->TdiAddressHandle, - AcceptedSocket->TdiConnectionHandle, - SOL_INTERNAL, - SO_CONTEXT, - HelperContext, - &HelperContextSize); - } - - /* Check if we should free from heap */ - if (HelperContext && (HelperContext != (PVOID)HelperBuffer)) - { - /* Free it */ - RtlFreeHeap(SockPrivateHeap, 0, HelperContext); - } - - /* Check if the old socket was non-blocking */ - if (BlockMode) - { - /* Set the new one like that too */ - ErrorCode = SockSetInformation(AcceptedSocket, - AFD_INFO_BLOCKING_MODE, - &BlockMode, - NULL, - NULL); - if (ErrorCode != NO_ERROR) return ErrorCode; - } - - /* Set it internally as well */ - AcceptedSocket->SharedData.NonBlocking = Socket->SharedData.NonBlocking; - - /* Check if inlined OOB was enabled */ - if (Oob) - { - /* Set the new one like that too */ - ErrorCode = SockSetInformation(AcceptedSocket, - AFD_INFO_INLINING_MODE, - &Oob, - NULL, - NULL); - if (ErrorCode != NO_ERROR) return ErrorCode; - } - - /* Set it internally as well */ - AcceptedSocket->SharedData.OobInline = Socket->SharedData.OobInline; - - /* Update the Window Sizes */ - ErrorCode = SockUpdateWindowSizes(AcceptedSocket, FALSE); - if (ErrorCode != NO_ERROR) return ErrorCode; - - /* Check if async select was enabled */ - if (AsyncEvents) - { - /* Call WSPAsyncSelect on the accepted socket too */ - ErrorCode = SockAsyncSelectHelper(AcceptedSocket, - hWnd, - wMsg, - AsyncEvents); - } - else if (NetworkEvents) - { - /* WSPEventSelect was enabled instead, call it on the new socket */ - ErrorCode = SockEventSelectHelper(AcceptedSocket, - EventObject, - NetworkEvents); - } - - /* Check for failure */ - if (ErrorCode != NO_ERROR) return ErrorCode; - - /* Set the new context in AFD */ - ErrorCode = SockSetHandleContext(AcceptedSocket); - if (ErrorCode != NO_ERROR) return ErrorCode; - - /* Return success*/ - return NO_ERROR; -} - -SOCKET -WSPAPI -WSPAccept(SOCKET Handle, - SOCKADDR FAR * SocketAddress, - LPINT SocketAddressLength, - LPCONDITIONPROC lpfnCondition, - DWORD_PTR dwCallbackData, - LPINT lpErrno) -{ - INT ErrorCode, ReturnValue; - PSOCKET_INFORMATION Socket, AcceptedSocket = NULL; - PWINSOCK_TEB_DATA ThreadData; - CHAR AfdAcceptBuffer[32]; - PAFD_RECEIVED_ACCEPT_DATA ReceivedAcceptData = NULL; - ULONG ReceiveBufferSize; - FD_SET ReadFds; - TIMEVAL Timeout; - NTSTATUS Status; - IO_STATUS_BLOCK IoStatusBlock; - ULONG AddressBufferSize; - CHAR AddressBuffer[sizeof(SOCKADDR)]; - PVOID SockAddress; - ULONG ConnectDataSize; - PVOID ConnectData = NULL; - AFD_PENDING_ACCEPT_DATA PendingAcceptData; - INT AddressSize; - PVOID CalleeDataBuffer = NULL; - WSABUF CallerId, CalleeId, CallerData, CalleeData; - GROUP GroupId; - LPQOS Qos = NULL, GroupQos = NULL; - BOOLEAN ValidGroup = TRUE; - AFD_DEFER_ACCEPT_DATA DeferData; - ULONG BytesReturned; - SOCKET AcceptedHandle = INVALID_SOCKET; - AFD_ACCEPT_DATA AcceptData; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* Invalid for datagram sockets */ - if (MSAFD_IS_DGRAM_SOCK(Socket)) - { - /* Fail */ - ErrorCode = WSAEOPNOTSUPP; - goto error; - } - - /* Only valid if the socket is listening */ - if (!Socket->SharedData.Listening) - { - /* Fail */ - ErrorCode = WSAEINVAL; - goto error; - } - - /* Validate address length */ - if (SocketAddressLength && - (Socket->HelperData->MinWSAddressLength > *SocketAddressLength)) - { - /* Fail */ - ErrorCode = WSAEINVAL; - goto error; - } - - /* Calculate how much space we'll need for the Receive Buffer */ - ReceiveBufferSize = sizeof(AFD_RECEIVED_ACCEPT_DATA) + - sizeof(TRANSPORT_ADDRESS) + - Socket->HelperData->MaxTDIAddressLength; - - /* Check if our stack buffer is large enough */ - if (ReceiveBufferSize <= sizeof(AfdAcceptBuffer)) - { - /* Use the stack */ - ReceivedAcceptData = (PVOID)AfdAcceptBuffer; - } - else - { - /* Allocate from heap */ - ReceivedAcceptData = SockAllocateHeapRoutine(SockPrivateHeap, - 0, - ReceiveBufferSize); - if (!ReceivedAcceptData) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - } - - /* If this is non-blocking, make sure there's something for us to accept */ - if (Socket->SharedData.NonBlocking) - { - /* Set up a nonblocking select */ - FD_ZERO(&ReadFds); - FD_SET(Handle, &ReadFds); - Timeout.tv_sec = 0; - Timeout.tv_usec = 0; - - /* See if there's any data */ - ReturnValue = WSPSelect(1, - &ReadFds, - NULL, - NULL, - &Timeout, - lpErrno); - if (ReturnValue == SOCKET_ERROR) - { - /* Fail */ - ErrorCode = *lpErrno; - goto error; - } - - /* Make sure we got a read back */ - if (!FD_ISSET(Handle, &ReadFds)) - { - /* Fail */ - ErrorCode = WSAEWOULDBLOCK; - goto error; - } - } - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_WAIT_FOR_LISTEN, - NULL, - 0, - ReceivedAcceptData, - ReceiveBufferSize); - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion outside the lock */ - LeaveCriticalSection(&Socket->Lock); - SockWaitForSingleObject(ThreadData->EventHandle, - Handle, - MAYBE_BLOCKING_HOOK, - NO_TIMEOUT); - EnterCriticalSection(&Socket->Lock); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - - /* Check if we got a condition callback */ - if (lpfnCondition) - { - /* Find out how much space we'll need for the address */ - AddressBufferSize = Socket->HelperData->MaxWSAddressLength; - - /* Check if our local buffer is enough */ - if (AddressBufferSize <= sizeof(AddressBuffer)) - { - /* It is, use the stack */ - SockAddress = (PVOID)AddressBuffer; - } - else - { - /* Allocate from heap */ - SockAddress = SockAllocateHeapRoutine(SockPrivateHeap, - 0, - AddressBufferSize); - if (!SockAddress) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - } - - /* Assume no connect data */ - ConnectDataSize = 0; - - /* Make sure we support connect data */ - if ((Socket->SharedData.ServiceFlags1 & XP1_CONNECT_DATA)) - { - /* Find out how much data is pending */ - PendingAcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber; - PendingAcceptData.ReturnSize = TRUE; - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_GET_PENDING_CONNECT_DATA, - &PendingAcceptData, - sizeof(PendingAcceptData), - &PendingAcceptData, - sizeof(PendingAcceptData)); - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion */ - SockWaitForSingleObject(ThreadData->EventHandle, - Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - - /* How much data to allocate */ - ConnectDataSize = PtrToUlong(IoStatusBlock.Information); - if (ConnectDataSize) - { - /* Allocate needed space */ - ConnectData = SockAllocateHeapRoutine(SockPrivateHeap, - 0, - ConnectDataSize); - if (!ConnectData) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - - /* Setup the structure to actually get the data now */ - PendingAcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber; - PendingAcceptData.ReturnSize = FALSE; - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_GET_PENDING_CONNECT_DATA, - &PendingAcceptData, - sizeof(PendingAcceptData), - ConnectData, - ConnectDataSize); - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion */ - SockWaitForSingleObject(ThreadData->EventHandle, - Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - } - } - - if ((Socket->SharedData.ServiceFlags1 & XP1_QOS_SUPPORTED)) - { - /* Set the accept data */ - AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber; - AcceptData.ListenHandle = Socket->WshContext.Handle; - - /* Save it in the TEB */ - ThreadData->AcceptData = &AcceptData; - - /* Send the IOCTL to get QOS Size */ - BytesReturned = 0; - ReturnValue = WSPIoctl(Handle, - SIO_GET_QOS, - NULL, - 0, - NULL, - 0, - &BytesReturned, - NULL, - NULL, - NULL, - &ErrorCode); - - /* Check if it failed (it should) */ - if (ReturnValue == SOCKET_ERROR) - { - /* Check if it failed because it had no buffer (it should) */ - if (ErrorCode == WSAEFAULT) - { - /* Make sure it told us how many bytes it needed */ - if (BytesReturned) - { - /* Allocate memory for it */ - Qos = SockAllocateHeapRoutine(SockPrivateHeap, - 0, - BytesReturned); - if (!Qos) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - - /* Save the accept data and set the QoS */ - ThreadData->AcceptData = &AcceptData; - ReturnValue = WSPIoctl(Handle, - SIO_GET_QOS, - NULL, - 0, - Qos, - BytesReturned, - &BytesReturned, - NULL, - NULL, - NULL, - &ErrorCode); - } - } - else - { - /* We got some other weird, error, fail. */ - goto error; - } - } - - /* Save the accept in the TEB */ - ThreadData->AcceptData = &AcceptData; - - /* Send the IOCTL to get Group QOS Size */ - BytesReturned = 0; - ReturnValue = WSPIoctl(Handle, - SIO_GET_GROUP_QOS, - NULL, - 0, - NULL, - 0, - &BytesReturned, - NULL, - NULL, - NULL, - &ErrorCode); - - /* Check if it failed (it should) */ - if (ReturnValue == SOCKET_ERROR) - { - /* Check if it failed because it had no buffer (it should) */ - if (ErrorCode == WSAEFAULT) - { - /* Make sure it told us how many bytes it needed */ - if (BytesReturned) - { - /* Allocate memory for it */ - GroupQos = SockAllocateHeapRoutine(SockPrivateHeap, - 0, - BytesReturned); - if (!GroupQos) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - - /* Save the accept data and set the QoS */ - ThreadData->AcceptData = &AcceptData; - ReturnValue = WSPIoctl(Handle, - SIO_GET_QOS, - NULL, - 0, - GroupQos, - BytesReturned, - &BytesReturned, - NULL, - NULL, - NULL, - &ErrorCode); - } - } - else - { - /* We got some other weird, error, fail. */ - goto error; - } - } - } - - /* Build Callee ID */ - CalleeId.buf = (PVOID)Socket->LocalAddress; - CalleeId.len = Socket->SharedData.SizeOfLocalAddress; - - /* Set up Address in SOCKADDR Format */ - SockBuildSockaddr((PSOCKADDR)SockAddress, - &AddressSize, - &ReceivedAcceptData->Address); - - /* Build Caller ID */ - CallerId.buf = (PVOID)SockAddress; - CallerId.len = AddressSize; - - /* Build Caller Data */ - CallerData.buf = ConnectData; - CallerData.len = ConnectDataSize; - - /* Check if socket supports Conditional Accept */ - if (Socket->SharedData.UseDelayedAcceptance) - { - /* Allocate Buffer for Callee Data */ - CalleeDataBuffer = SockAllocateHeapRoutine(SockPrivateHeap, 0, 4096); - if (CalleeDataBuffer) - { - /* Fill the structure */ - CalleeData.buf = CalleeDataBuffer; - CalleeData.len = 4096; - } - else - { - /* Don't fail, just don't use this... */ - CalleeData.len = 0; - } - } - else - { - /* Nothing */ - CalleeData.buf = NULL; - CalleeData.len = 0; - } - - /* Call the Condition Function */ - ReturnValue = (lpfnCondition)(&CallerId, - !CallerData.buf ? NULL : & CallerData, - NULL, - NULL, - &CalleeId, - !CalleeData.buf ? NULL: & CalleeData, - &GroupId, - dwCallbackData); - - if ((ReturnValue == CF_ACCEPT) && - (GroupId) && - (GroupId != SG_UNCONSTRAINED_GROUP) && - (GroupId != SG_CONSTRAINED_GROUP)) - { - /* Check for validity */ - ErrorCode = SockIsAddressConsistentWithConstrainedGroup(Socket, - GroupId, - SockAddress, - AddressSize); - ValidGroup = (ErrorCode == NO_ERROR); - } - - /* Check if the address was from the heap */ - if (SockAddress != AddressBuffer) - { - /* Free it */ - RtlFreeHeap(SockPrivateHeap, 0, SockAddress); - } - - /* Check if it was accepted */ - if (ReturnValue == CF_ACCEPT) - { - /* Check if the group is invalid, however */ - if (!ValidGroup) goto error; - - /* Now check if QOS is supported */ - if ((Socket->SharedData.ServiceFlags1 & XP1_QOS_SUPPORTED)) - { - /* Check if we had Qos */ - if (Qos) - { - /* Set the accept data */ - AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber; - AcceptData.ListenHandle = Socket->WshContext.Handle; - - /* Save it in the TEB */ - ThreadData->AcceptData = &AcceptData; - - /* Send the IOCTL */ - BytesReturned = 0; - ReturnValue = WSPIoctl(Handle, - SIO_SET_QOS, - Qos, - sizeof(*Qos), - NULL, - 0, - &BytesReturned, - NULL, - NULL, - NULL, - &ErrorCode); - if (ReturnValue == SOCKET_ERROR) goto error; - } - - /* Check if we had Group Qos */ - if (GroupQos) - { - /* Set the accept data */ - AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber; - AcceptData.ListenHandle = Socket->WshContext.Handle; - - /* Save it in the TEB */ - ThreadData->AcceptData = &AcceptData; - - /* Send the IOCTL */ - ReturnValue = WSPIoctl(Handle, - SIO_SET_GROUP_QOS, - GroupQos, - sizeof(*GroupQos), - NULL, - 0, - &BytesReturned, - NULL, - NULL, - NULL, - &ErrorCode); - if (ReturnValue == SOCKET_ERROR) goto error; - } - } - - /* Check if delayed acceptance is used and we have callee data */ - if ((Socket->HelperData->UseDelayedAcceptance) && (CalleeData.len)) - { - /* Save the accept data in the TEB */ - ThreadData->AcceptData = &AcceptData; - - /* Set the connect data */ - ErrorCode = SockGetConnectData(Socket, - IOCTL_AFD_SET_CONNECT_DATA, - CalleeData.buf, - CalleeData.len, - NULL); - if (ErrorCode == SOCKET_ERROR) goto error; - } - } - else - { - /* Callback rejected. Build Defer Structure */ - DeferData.SequenceNumber = ReceivedAcceptData->SequenceNumber; - DeferData.RejectConnection = (ReturnValue == CF_REJECT); - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_DEFER_ACCEPT, - &DeferData, - sizeof(DeferData), - NULL, - 0); - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - - if (ReturnValue == CF_REJECT) - { - /* The connection was refused */ - ErrorCode = WSAECONNREFUSED; - } - else - { - /* The connection was deferred */ - ErrorCode = WSATRY_AGAIN; - } - - /* Fail */ - goto error; - } - } - - /* Create a new Socket */ - ErrorCode = SockSocket(Socket->SharedData.AddressFamily, - Socket->SharedData.SocketType, - Socket->SharedData.Protocol, - &Socket->ProviderId, - GroupId, - Socket->SharedData.CreateFlags, - Socket->SharedData.ProviderFlags, - Socket->SharedData.ServiceFlags1, - Socket->SharedData.CatalogEntryId, - &AcceptedSocket); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - goto error; - } - - /* Set up the Accept Structure */ - AcceptData.ListenHandle = AcceptedSocket->WshContext.Handle; - AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber; - - /* Build the socket address */ - SockBuildSockaddr(AcceptedSocket->RemoteAddress, - &AcceptedSocket->SharedData.SizeOfRemoteAddress, - &ReceivedAcceptData->Address); - - /* Copy the local address */ - RtlCopyMemory(AcceptedSocket->LocalAddress, - Socket->LocalAddress, - Socket->SharedData.SizeOfLocalAddress); - AcceptedSocket->SharedData.SizeOfLocalAddress = Socket->SharedData.SizeOfLocalAddress; - - /* We can release the accepted socket's lock now */ - LeaveCriticalSection(&AcceptedSocket->Lock); - - /* Send IOCTL to Accept */ - AcceptData.UseSAN = SockSanEnabled; - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_ACCEPT, - &AcceptData, - sizeof(AcceptData), - NULL, - 0); - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion outside the lock */ - LeaveCriticalSection(&Socket->Lock); - SockWaitForSingleObject(ThreadData->EventHandle, - Handle, - MAYBE_BLOCKING_HOOK, - NO_TIMEOUT); - EnterCriticalSection(&Socket->Lock); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - - /* Notify the helper DLL */ - ErrorCode = SockNotifyHelperDll(AcceptedSocket, WSH_NOTIFY_ACCEPT); - if (ErrorCode != NO_ERROR) goto error; - - /* If the caller sent a socket address pointer and length */ - if (SocketAddress && SocketAddressLength) - { - /* Return the address in its buffer */ - ErrorCode = SockBuildSockaddr(SocketAddress, - SocketAddressLength, - &ReceivedAcceptData->Address); - if (ErrorCode != NO_ERROR) goto error; - } - - /* Check if async select was active */ - if (SockAsyncSelectCalled) - { - /* Re-enable the regular accept event */ - SockReenableAsyncSelectEvent(Socket, FD_ACCEPT); - } - - /* Finally, do the internal core accept code */ - ErrorCode = SockCoreAccept(Socket, AcceptedSocket); - if (ErrorCode != NO_ERROR) goto error; - - /* Call WPU to tell it about the new handle */ - AcceptedHandle = SockUpcallTable->lpWPUModifyIFSHandle(AcceptedSocket->SharedData.CatalogEntryId, - (SOCKET)AcceptedSocket->WshContext.Handle, - &ErrorCode); - - /* Dereference the socket and clear its pointer for error code logic */ - SockDereferenceSocket(Socket); - Socket = NULL; - -error: - - /* Check if we have a socket here */ - if (Socket) - { - /* Check if async select was active */ - if (SockAsyncSelectCalled) - { - /* Re-enable the regular accept event */ - SockReenableAsyncSelectEvent(Socket, FD_ACCEPT); - } - - /* Unlock and dereference it */ - LeaveCriticalSection(&Socket->Lock); - SockDereferenceSocket(Socket); - } - - /* Check if we got the accepted socket */ - if (AcceptedSocket) - { - /* Check if the accepted socket also has a handle */ - if (ErrorCode == NO_ERROR) - { - /* Close the socket */ - SockCloseSocket(AcceptedSocket); - } - - /* Dereference it */ - SockDereferenceSocket(AcceptedSocket); - } - - /* Check if the accept buffer was from the heap */ - if (ReceivedAcceptData && (ReceivedAcceptData != (PVOID)AfdAcceptBuffer)) - { - /* Free it */ - RtlFreeHeap(SockPrivateHeap, 0, ReceivedAcceptData); - } - - /* Check if we have a connect data buffer */ - if (ConnectData) - { - /* Free it */ - RtlFreeHeap(SockPrivateHeap, 0, ConnectData); - } - - /* Check if we have a callee data buffer */ - if (CalleeDataBuffer) - { - /* Free it */ - RtlFreeHeap(SockPrivateHeap, 0, CalleeDataBuffer); - } - - /* Check if we have allocated QOS structures */ - if (Qos) - { - /* Free it */ - RtlFreeHeap(SockPrivateHeap, 0, Qos); - } - if (GroupQos) - { - /* Free it */ - RtlFreeHeap(SockPrivateHeap, 0, GroupQos); - } - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return INVALID_SOCKET; - } - - /* Return the new handle */ - return AcceptedHandle; -} - diff --git a/dll/win32/mswsock/msafd/addrconv.c b/dll/win32/mswsock/msafd/addrconv.c index 896ccab8748..f699ba800ae 100644 --- a/dll/win32/mswsock/msafd/addrconv.c +++ b/dll/win32/mswsock/msafd/addrconv.c @@ -36,117 +36,3 @@ WSPStringToAddress(IN LPWSTR AddressString, return 0; } -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -INT -WSPAPI -WSPAddressToString(IN LPSOCKADDR lpsaAddress, - IN DWORD dwAddressLength, - IN LPWSAPROTOCOL_INFOW lpProtocolInfo, - OUT LPWSTR lpszAddressString, - IN OUT LPDWORD lpdwAddressStringLength, - OUT LPINT lpErrno) -{ - return 0; -} - -INT -WSPAPI -WSPStringToAddress(IN LPWSTR AddressString, - IN INT AddressFamily, - IN LPWSAPROTOCOL_INFOW lpProtocolInfo, - OUT LPSOCKADDR lpAddress, - IN OUT LPINT lpAddressLength, - OUT LPINT lpErrno) -{ - return 0; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -INT -WSPAPI -WSPAddressToString(IN LPSOCKADDR lpsaAddress, - IN DWORD dwAddressLength, - IN LPWSAPROTOCOL_INFOW lpProtocolInfo, - OUT LPWSTR lpszAddressString, - IN OUT LPDWORD lpdwAddressStringLength, - OUT LPINT lpErrno) -{ - return 0; -} - -INT -WSPAPI -WSPStringToAddress(IN LPWSTR AddressString, - IN INT AddressFamily, - IN LPWSAPROTOCOL_INFOW lpProtocolInfo, - OUT LPSOCKADDR lpAddress, - IN OUT LPINT lpAddressLength, - OUT LPINT lpErrno) -{ - return 0; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -INT -WSPAPI -WSPAddressToString(IN LPSOCKADDR lpsaAddress, - IN DWORD dwAddressLength, - IN LPWSAPROTOCOL_INFOW lpProtocolInfo, - OUT LPWSTR lpszAddressString, - IN OUT LPDWORD lpdwAddressStringLength, - OUT LPINT lpErrno) -{ - return 0; -} - -INT -WSPAPI -WSPStringToAddress(IN LPWSTR AddressString, - IN INT AddressFamily, - IN LPWSAPROTOCOL_INFOW lpProtocolInfo, - OUT LPSOCKADDR lpAddress, - IN OUT LPINT lpAddressLength, - OUT LPINT lpErrno) -{ - return 0; -} - diff --git a/dll/win32/mswsock/msafd/afdsan.c b/dll/win32/mswsock/msafd/afdsan.c index 3e062e90d63..bd1ad2806dc 100644 --- a/dll/win32/mswsock/msafd/afdsan.c +++ b/dll/win32/mswsock/msafd/afdsan.c @@ -12,45 +12,3 @@ /* FUNCTIONS *****************************************************************/ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - diff --git a/dll/win32/mswsock/msafd/async.c b/dll/win32/mswsock/msafd/async.c index 1f4635f34eb..a47987d7f83 100644 --- a/dll/win32/mswsock/msafd/async.c +++ b/dll/win32/mswsock/msafd/async.c @@ -196,597 +196,3 @@ SockAsyncThread(PVOID Context) FreeLibraryAndExitThread(hInstance, NO_ERROR); } -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -HANDLE SockAsyncQueuePort; -LONG SockAsyncThreadReferenceCount; - -/* FUNCTIONS *****************************************************************/ - -INT -WSPAPI -SockCreateAsyncQueuePort(VOID) -{ - NTSTATUS Status; - OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags; - - /* Create the port */ - Status = NtCreateIoCompletion(&SockAsyncQueuePort, - IO_COMPLETION_ALL_ACCESS, - NULL, - -1); - - /* Protect Handle */ - HandleFlags.ProtectFromClose = TRUE; - HandleFlags.Inherit = FALSE; - Status = NtSetInformationObject(SockAsyncQueuePort, - ObjectHandleFlagInformation, - &HandleFlags, - sizeof(HandleFlags)); - - /* Return */ - return NO_ERROR; -} - -VOID -WSPAPI -SockHandleAsyncIndication(IN PASYNC_COMPLETION_ROUTINE Callback, - IN PVOID Context, - IN PIO_STATUS_BLOCK IoStatusBlock) -{ - /* Call the completion routine */ - (*Callback)(Context, IoStatusBlock); -} - -BOOLEAN -WSPAPI -SockCheckAndReferenceAsyncThread(VOID) -{ - LONG Count; - HANDLE hAsyncThread; - DWORD AsyncThreadId; - HANDLE AsyncEvent; - NTSTATUS Status; - INT ErrorCode; - HINSTANCE hInstance; - PWINSOCK_TEB_DATA ThreadData; - - /* Loop while trying to increase the reference count */ - do - { - /* Get the count, and check if it's already been started */ - Count = SockAsyncThreadReferenceCount; - if ((Count > 0) && (InterlockedCompareExchange(&SockAsyncThreadReferenceCount, - Count + 1, - Count) == Count)) - { - /* Simply return */ - return TRUE; - } - } while (Count > 0); - - /* Acquire the lock */ - SockAcquireRwLockExclusive(&SocketGlobalLock); - - /* Check if no completion port exists already and create it */ - if (!SockAsyncQueuePort) SockCreateAsyncQueuePort(); - - /* Create an extra reference so the thread stays alive */ - ErrorCode = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, - (LPCTSTR)WSPStartup, - &hInstance); - - /* Create the Async Event */ - Status = NtCreateEvent(&AsyncEvent, - EVENT_ALL_ACCESS, - NULL, - NotificationEvent, - FALSE); - - /* Allocate the TEB Block */ - ThreadData = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(*ThreadData)); - if (!ThreadData) - { - /* Release the lock, close the event, free extra reference and fail */ - SockReleaseRwLockExclusive(&SocketGlobalLock); - NtClose(AsyncEvent); - FreeLibrary(hInstance); - return FALSE; - } - - /* Initialize thread data */ - RtlZeroMemory(ThreadData, sizeof(*ThreadData)); - ThreadData->EventHandle = AsyncEvent; - ThreadData->SocketHandle = (SOCKET)hInstance; - - /* Create the Async Thread */ - hAsyncThread = CreateThread(NULL, - 0, - (LPTHREAD_START_ROUTINE)SockAsyncThread, - ThreadData, - 0, - &AsyncThreadId); - - /* Close the Handle */ - NtClose(hAsyncThread); - - /* Increase the Reference Count */ - InterlockedExchangeAdd(&SockAsyncThreadReferenceCount, 2); - - /* Release lock and return success */ - SockReleaseRwLockExclusive(&SocketGlobalLock); - return TRUE; -} - -INT -WSPAPI -SockAsyncThread(PVOID Context) -{ - PVOID AsyncContext; - PASYNC_COMPLETION_ROUTINE AsyncCompletionRoutine; - IO_STATUS_BLOCK IoStatusBlock; - NTSTATUS Status; - LARGE_INTEGER Timeout; - PWINSOCK_TEB_DATA ThreadData = (PWINSOCK_TEB_DATA)Context; - HINSTANCE hInstance = (HINSTANCE)ThreadData->SocketHandle; - - /* Return the socket handle back to its unhacked value */ - ThreadData->SocketHandle = INVALID_SOCKET; - - /* Setup the Thread Data pointer */ - NtCurrentTeb()->WinSockData = ThreadData; - - /* Make the Thread Higher Priority */ - SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL); - - /* Setup timeout */ - Timeout.QuadPart = Int32x32To64(300, 10000000); - - /* Do a KQUEUE/WorkItem Style Loop, thanks to IoCompletion Ports */ - do { - /* Get the next completion item */ - Status = NtRemoveIoCompletion(SockAsyncQueuePort, - (PVOID*)&AsyncCompletionRoutine, - &AsyncContext, - &IoStatusBlock, - &Timeout); - /* Check for success */ - if (NT_SUCCESS(Status)) - { - /* Check if this isn't the termination command */ - if (AsyncCompletionRoutine != (PVOID)-1) - { - /* Call the routine */ - SockHandleAsyncIndication(AsyncCompletionRoutine, - Context, - &IoStatusBlock); - } - else - { - /* We have to terminate, fake a timeout */ - Status = STATUS_TIMEOUT; - InterlockedDecrement(&SockAsyncThreadReferenceCount); - } - } - else if ((SockAsyncThreadReferenceCount > 1) && (NT_ERROR(Status))) - { - /* It Failed, sleep for a second */ - Sleep(1000); - } - } while (((Status != STATUS_TIMEOUT) && - (SockWspStartupCount > 0)) || - InterlockedCompareExchange(&SockAsyncThreadReferenceCount, 0, 1) != 1); - - /* Release the lock */ - SockReleaseRwLockShared(&SocketGlobalLock); - - /* Remove our extra reference */ - FreeLibraryAndExitThread(hInstance, NO_ERROR); -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -HANDLE SockAsyncQueuePort; -LONG SockAsyncThreadReferenceCount; - -/* FUNCTIONS *****************************************************************/ - -INT -WSPAPI -SockCreateAsyncQueuePort(VOID) -{ - NTSTATUS Status; - OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags; - - /* Create the port */ - Status = NtCreateIoCompletion(&SockAsyncQueuePort, - IO_COMPLETION_ALL_ACCESS, - NULL, - -1); - - /* Protect Handle */ - HandleFlags.ProtectFromClose = TRUE; - HandleFlags.Inherit = FALSE; - Status = NtSetInformationObject(SockAsyncQueuePort, - ObjectHandleFlagInformation, - &HandleFlags, - sizeof(HandleFlags)); - - /* Return */ - return NO_ERROR; -} - -VOID -WSPAPI -SockHandleAsyncIndication(IN PASYNC_COMPLETION_ROUTINE Callback, - IN PVOID Context, - IN PIO_STATUS_BLOCK IoStatusBlock) -{ - /* Call the completion routine */ - (*Callback)(Context, IoStatusBlock); -} - -BOOLEAN -WSPAPI -SockCheckAndReferenceAsyncThread(VOID) -{ - LONG Count; - HANDLE hAsyncThread; - DWORD AsyncThreadId; - HANDLE AsyncEvent; - NTSTATUS Status; - INT ErrorCode; - HINSTANCE hInstance; - PWINSOCK_TEB_DATA ThreadData; - - /* Loop while trying to increase the reference count */ - do - { - /* Get the count, and check if it's already been started */ - Count = SockAsyncThreadReferenceCount; - if ((Count > 0) && (InterlockedCompareExchange(&SockAsyncThreadReferenceCount, - Count + 1, - Count) == Count)) - { - /* Simply return */ - return TRUE; - } - } while (Count > 0); - - /* Acquire the lock */ - SockAcquireRwLockExclusive(&SocketGlobalLock); - - /* Check if no completion port exists already and create it */ - if (!SockAsyncQueuePort) SockCreateAsyncQueuePort(); - - /* Create an extra reference so the thread stays alive */ - ErrorCode = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, - (LPCTSTR)WSPStartup, - &hInstance); - - /* Create the Async Event */ - Status = NtCreateEvent(&AsyncEvent, - EVENT_ALL_ACCESS, - NULL, - NotificationEvent, - FALSE); - - /* Allocate the TEB Block */ - ThreadData = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(*ThreadData)); - if (!ThreadData) - { - /* Release the lock, close the event, free extra reference and fail */ - SockReleaseRwLockExclusive(&SocketGlobalLock); - NtClose(AsyncEvent); - FreeLibrary(hInstance); - return FALSE; - } - - /* Initialize thread data */ - RtlZeroMemory(ThreadData, sizeof(*ThreadData)); - ThreadData->EventHandle = AsyncEvent; - ThreadData->SocketHandle = (SOCKET)hInstance; - - /* Create the Async Thread */ - hAsyncThread = CreateThread(NULL, - 0, - (LPTHREAD_START_ROUTINE)SockAsyncThread, - ThreadData, - 0, - &AsyncThreadId); - - /* Close the Handle */ - NtClose(hAsyncThread); - - /* Increase the Reference Count */ - InterlockedExchangeAdd(&SockAsyncThreadReferenceCount, 2); - - /* Release lock and return success */ - SockReleaseRwLockExclusive(&SocketGlobalLock); - return TRUE; -} - -INT -WSPAPI -SockAsyncThread(PVOID Context) -{ - PVOID AsyncContext; - PASYNC_COMPLETION_ROUTINE AsyncCompletionRoutine; - IO_STATUS_BLOCK IoStatusBlock; - NTSTATUS Status; - LARGE_INTEGER Timeout; - PWINSOCK_TEB_DATA ThreadData = (PWINSOCK_TEB_DATA)Context; - HINSTANCE hInstance = (HINSTANCE)ThreadData->SocketHandle; - - /* Return the socket handle back to its unhacked value */ - ThreadData->SocketHandle = INVALID_SOCKET; - - /* Setup the Thread Data pointer */ - NtCurrentTeb()->WinSockData = ThreadData; - - /* Make the Thread Higher Priority */ - SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL); - - /* Setup timeout */ - Timeout.QuadPart = Int32x32To64(300, 10000000); - - /* Do a KQUEUE/WorkItem Style Loop, thanks to IoCompletion Ports */ - do { - /* Get the next completion item */ - Status = NtRemoveIoCompletion(SockAsyncQueuePort, - (PVOID*)&AsyncCompletionRoutine, - &AsyncContext, - &IoStatusBlock, - &Timeout); - /* Check for success */ - if (NT_SUCCESS(Status)) - { - /* Check if this isn't the termination command */ - if (AsyncCompletionRoutine != (PVOID)-1) - { - /* Call the routine */ - SockHandleAsyncIndication(AsyncCompletionRoutine, - Context, - &IoStatusBlock); - } - else - { - /* We have to terminate, fake a timeout */ - Status = STATUS_TIMEOUT; - InterlockedDecrement(&SockAsyncThreadReferenceCount); - } - } - else if ((SockAsyncThreadReferenceCount > 1) && (NT_ERROR(Status))) - { - /* It Failed, sleep for a second */ - Sleep(1000); - } - } while (((Status != STATUS_TIMEOUT) && - (SockWspStartupCount > 0)) || - InterlockedCompareExchange(&SockAsyncThreadReferenceCount, 0, 1) != 1); - - /* Release the lock */ - SockReleaseRwLockShared(&SocketGlobalLock); - - /* Remove our extra reference */ - FreeLibraryAndExitThread(hInstance, NO_ERROR); -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -HANDLE SockAsyncQueuePort; -LONG SockAsyncThreadReferenceCount; - -/* FUNCTIONS *****************************************************************/ - -INT -WSPAPI -SockCreateAsyncQueuePort(VOID) -{ - NTSTATUS Status; - OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags; - - /* Create the port */ - Status = NtCreateIoCompletion(&SockAsyncQueuePort, - IO_COMPLETION_ALL_ACCESS, - NULL, - -1); - - /* Protect Handle */ - HandleFlags.ProtectFromClose = TRUE; - HandleFlags.Inherit = FALSE; - Status = NtSetInformationObject(SockAsyncQueuePort, - ObjectHandleFlagInformation, - &HandleFlags, - sizeof(HandleFlags)); - - /* Return */ - return NO_ERROR; -} - -VOID -WSPAPI -SockHandleAsyncIndication(IN PASYNC_COMPLETION_ROUTINE Callback, - IN PVOID Context, - IN PIO_STATUS_BLOCK IoStatusBlock) -{ - /* Call the completion routine */ - (*Callback)(Context, IoStatusBlock); -} - -BOOLEAN -WSPAPI -SockCheckAndReferenceAsyncThread(VOID) -{ - LONG Count; - HANDLE hAsyncThread; - DWORD AsyncThreadId; - HANDLE AsyncEvent; - NTSTATUS Status; - INT ErrorCode; - HINSTANCE hInstance; - PWINSOCK_TEB_DATA ThreadData; - - /* Loop while trying to increase the reference count */ - do - { - /* Get the count, and check if it's already been started */ - Count = SockAsyncThreadReferenceCount; - if ((Count > 0) && (InterlockedCompareExchange(&SockAsyncThreadReferenceCount, - Count + 1, - Count) == Count)) - { - /* Simply return */ - return TRUE; - } - } while (Count > 0); - - /* Acquire the lock */ - SockAcquireRwLockExclusive(&SocketGlobalLock); - - /* Check if no completion port exists already and create it */ - if (!SockAsyncQueuePort) SockCreateAsyncQueuePort(); - - /* Create an extra reference so the thread stays alive */ - ErrorCode = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, - (LPCTSTR)WSPStartup, - &hInstance); - - /* Create the Async Event */ - Status = NtCreateEvent(&AsyncEvent, - EVENT_ALL_ACCESS, - NULL, - NotificationEvent, - FALSE); - - /* Allocate the TEB Block */ - ThreadData = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(*ThreadData)); - if (!ThreadData) - { - /* Release the lock, close the event, free extra reference and fail */ - SockReleaseRwLockExclusive(&SocketGlobalLock); - NtClose(AsyncEvent); - FreeLibrary(hInstance); - return FALSE; - } - - /* Initialize thread data */ - RtlZeroMemory(ThreadData, sizeof(*ThreadData)); - ThreadData->EventHandle = AsyncEvent; - ThreadData->SocketHandle = (SOCKET)hInstance; - - /* Create the Async Thread */ - hAsyncThread = CreateThread(NULL, - 0, - (LPTHREAD_START_ROUTINE)SockAsyncThread, - ThreadData, - 0, - &AsyncThreadId); - - /* Close the Handle */ - NtClose(hAsyncThread); - - /* Increase the Reference Count */ - InterlockedExchangeAdd(&SockAsyncThreadReferenceCount, 2); - - /* Release lock and return success */ - SockReleaseRwLockExclusive(&SocketGlobalLock); - return TRUE; -} - -INT -WSPAPI -SockAsyncThread(PVOID Context) -{ - PVOID AsyncContext; - PASYNC_COMPLETION_ROUTINE AsyncCompletionRoutine; - IO_STATUS_BLOCK IoStatusBlock; - NTSTATUS Status; - LARGE_INTEGER Timeout; - PWINSOCK_TEB_DATA ThreadData = (PWINSOCK_TEB_DATA)Context; - HINSTANCE hInstance = (HINSTANCE)ThreadData->SocketHandle; - - /* Return the socket handle back to its unhacked value */ - ThreadData->SocketHandle = INVALID_SOCKET; - - /* Setup the Thread Data pointer */ - NtCurrentTeb()->WinSockData = ThreadData; - - /* Make the Thread Higher Priority */ - SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL); - - /* Setup timeout */ - Timeout.QuadPart = Int32x32To64(300, 10000000); - - /* Do a KQUEUE/WorkItem Style Loop, thanks to IoCompletion Ports */ - do { - /* Get the next completion item */ - Status = NtRemoveIoCompletion(SockAsyncQueuePort, - (PVOID*)&AsyncCompletionRoutine, - &AsyncContext, - &IoStatusBlock, - &Timeout); - /* Check for success */ - if (NT_SUCCESS(Status)) - { - /* Check if this isn't the termination command */ - if (AsyncCompletionRoutine != (PVOID)-1) - { - /* Call the routine */ - SockHandleAsyncIndication(AsyncCompletionRoutine, - Context, - &IoStatusBlock); - } - else - { - /* We have to terminate, fake a timeout */ - Status = STATUS_TIMEOUT; - InterlockedDecrement(&SockAsyncThreadReferenceCount); - } - } - else if ((SockAsyncThreadReferenceCount > 1) && (NT_ERROR(Status))) - { - /* It Failed, sleep for a second */ - Sleep(1000); - } - } while (((Status != STATUS_TIMEOUT) && - (SockWspStartupCount > 0)) || - InterlockedCompareExchange(&SockAsyncThreadReferenceCount, 0, 1) != 1); - - /* Release the lock */ - SockReleaseRwLockShared(&SocketGlobalLock); - - /* Remove our extra reference */ - FreeLibraryAndExitThread(hInstance, NO_ERROR); -} - diff --git a/dll/win32/mswsock/msafd/bind.c b/dll/win32/mswsock/msafd/bind.c index a2325c24fce..fa3ff3b21ba 100644 --- a/dll/win32/mswsock/msafd/bind.c +++ b/dll/win32/mswsock/msafd/bind.c @@ -211,642 +211,3 @@ error: return NO_ERROR; } -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -INT -WSPAPI -WSPBind(SOCKET Handle, - const SOCKADDR *SocketAddress, - INT SocketAddressLength, - LPINT lpErrno) -{ - INT ErrorCode; - IO_STATUS_BLOCK IoStatusBlock; - PAFD_BIND_DATA BindData; - PSOCKET_INFORMATION Socket; - NTSTATUS Status; - PTDI_ADDRESS_INFO TdiAddress = NULL; - SOCKADDR_INFO SocketInfo; - PWINSOCK_TEB_DATA ThreadData; - CHAR AddressBuffer[FIELD_OFFSET(TDI_ADDRESS_INFO, Address) + - MAX_TDI_ADDRESS_LENGTH]; - ULONG BindDataLength, TdiAddressLength; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* If the socket is already bound, fail */ - if (Socket->SharedData.State != SocketOpen) - { - /* Fail */ - ErrorCode = WSAEINVAL; - goto error; - } - - /* Normalize address size */ - if (SocketAddressLength > Socket->HelperData->MaxWSAddressLength) - { - /* Don't go beyond the maximum */ - SocketAddressLength = Socket->HelperData->MaxWSAddressLength; - } - - /* Get Address Information */ - ErrorCode = Socket->HelperData->WSHGetSockaddrType((PSOCKADDR)SocketAddress, - SocketAddressLength, - &SocketInfo); - if (ErrorCode != NO_ERROR) goto error; - - /* Check how big the Bind and TDI Address Data will be */ - BindDataLength = Socket->HelperData->MaxTDIAddressLength + - FIELD_OFFSET(AFD_BIND_DATA, Address); - TdiAddressLength = Socket->HelperData->MaxTDIAddressLength + - FIELD_OFFSET(TDI_ADDRESS_INFO, Address); - - /* Check if we can fit it in the stack */ - if ((TdiAddressLength <= sizeof(AddressBuffer)) && - (BindDataLength <= sizeof(AddressBuffer))) - { - /* Use the stack */ - TdiAddress = (PVOID)AddressBuffer; - BindData = (PAFD_BIND_DATA)AddressBuffer; - } - else - { - /* Allocate from the heap */ - TdiAddress = SockAllocateHeapRoutine(SockPrivateHeap, 0, TdiAddressLength); - if (!TdiAddress) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - BindData = (PAFD_BIND_DATA)TdiAddress; - } - - /* Set the Share Type */ - if (Socket->SharedData.ExclusiveAddressUse) - { - BindData->ShareType = AFD_SHARE_EXCLUSIVE; - } - else if (SocketInfo.EndpointInfo == SockaddrEndpointInfoWildcard) - { - BindData->ShareType = AFD_SHARE_WILDCARD; - } - else if (Socket->SharedData.ReuseAddresses) - { - BindData->ShareType = AFD_SHARE_REUSE; - } - else - { - BindData->ShareType = AFD_SHARE_UNIQUE; - } - - /* Build the TDI Address */ - ErrorCode = SockBuildTdiAddress(&BindData->Address, - (PSOCKADDR)SocketAddress, - SocketAddressLength); - if (ErrorCode != NO_ERROR) goto error; - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_BIND, - BindData, - BindDataLength, - TdiAddress, - TdiAddressLength); - - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion outside the lock */ - LeaveCriticalSection(&Socket->Lock); - SockWaitForSingleObject(ThreadData->EventHandle, - Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - EnterCriticalSection(&Socket->Lock); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - - /* Save the TDI Address handle */ - Socket->TdiAddressHandle = (HANDLE)IoStatusBlock.Information; - - /* Notify the helper DLL */ - ErrorCode = SockNotifyHelperDll(Socket, WSH_NOTIFY_BIND); - if (ErrorCode != NO_ERROR) goto error; - - /* Re-create Sockaddr format */ - ErrorCode = SockBuildSockaddr(Socket->LocalAddress, - &SocketAddressLength, - &TdiAddress->Address); - if (ErrorCode != NO_ERROR) goto error; - - /* Set us as bound */ - Socket->SharedData.State = SocketBound; - - /* Send the new data to AFD */ - ErrorCode = SockSetHandleContext(Socket); - if (ErrorCode != NO_ERROR) goto error; - - /* Update the window sizes */ - ErrorCode = SockUpdateWindowSizes(Socket, FALSE); - if (ErrorCode != NO_ERROR) goto error; - -error: - /* Check if we have a socket here */ - if (Socket) - { - /* Release the lock and dereference */ - LeaveCriticalSection(&Socket->Lock); - SockDereferenceSocket(Socket); - } - - /* Check if we should free the TDI address */ - if ((TdiAddress) && (TdiAddress != (PVOID)AddressBuffer)) - { - /* Free the Buffer */ - RtlFreeHeap(SockPrivateHeap, 0, TdiAddress); - } - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -INT -WSPAPI -WSPBind(SOCKET Handle, - const SOCKADDR *SocketAddress, - INT SocketAddressLength, - LPINT lpErrno) -{ - INT ErrorCode; - IO_STATUS_BLOCK IoStatusBlock; - PAFD_BIND_DATA BindData; - PSOCKET_INFORMATION Socket; - NTSTATUS Status; - PTDI_ADDRESS_INFO TdiAddress = NULL; - SOCKADDR_INFO SocketInfo; - PWINSOCK_TEB_DATA ThreadData; - CHAR AddressBuffer[FIELD_OFFSET(TDI_ADDRESS_INFO, Address) + - MAX_TDI_ADDRESS_LENGTH]; - ULONG BindDataLength, TdiAddressLength; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* If the socket is already bound, fail */ - if (Socket->SharedData.State != SocketOpen) - { - /* Fail */ - ErrorCode = WSAEINVAL; - goto error; - } - - /* Normalize address size */ - if (SocketAddressLength > Socket->HelperData->MaxWSAddressLength) - { - /* Don't go beyond the maximum */ - SocketAddressLength = Socket->HelperData->MaxWSAddressLength; - } - - /* Get Address Information */ - ErrorCode = Socket->HelperData->WSHGetSockaddrType((PSOCKADDR)SocketAddress, - SocketAddressLength, - &SocketInfo); - if (ErrorCode != NO_ERROR) goto error; - - /* Check how big the Bind and TDI Address Data will be */ - BindDataLength = Socket->HelperData->MaxTDIAddressLength + - FIELD_OFFSET(AFD_BIND_DATA, Address); - TdiAddressLength = Socket->HelperData->MaxTDIAddressLength + - FIELD_OFFSET(TDI_ADDRESS_INFO, Address); - - /* Check if we can fit it in the stack */ - if ((TdiAddressLength <= sizeof(AddressBuffer)) && - (BindDataLength <= sizeof(AddressBuffer))) - { - /* Use the stack */ - TdiAddress = (PVOID)AddressBuffer; - BindData = (PAFD_BIND_DATA)AddressBuffer; - } - else - { - /* Allocate from the heap */ - TdiAddress = SockAllocateHeapRoutine(SockPrivateHeap, 0, TdiAddressLength); - if (!TdiAddress) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - BindData = (PAFD_BIND_DATA)TdiAddress; - } - - /* Set the Share Type */ - if (Socket->SharedData.ExclusiveAddressUse) - { - BindData->ShareType = AFD_SHARE_EXCLUSIVE; - } - else if (SocketInfo.EndpointInfo == SockaddrEndpointInfoWildcard) - { - BindData->ShareType = AFD_SHARE_WILDCARD; - } - else if (Socket->SharedData.ReuseAddresses) - { - BindData->ShareType = AFD_SHARE_REUSE; - } - else - { - BindData->ShareType = AFD_SHARE_UNIQUE; - } - - /* Build the TDI Address */ - ErrorCode = SockBuildTdiAddress(&BindData->Address, - (PSOCKADDR)SocketAddress, - SocketAddressLength); - if (ErrorCode != NO_ERROR) goto error; - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_BIND, - BindData, - BindDataLength, - TdiAddress, - TdiAddressLength); - - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion outside the lock */ - LeaveCriticalSection(&Socket->Lock); - SockWaitForSingleObject(ThreadData->EventHandle, - Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - EnterCriticalSection(&Socket->Lock); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - - /* Save the TDI Address handle */ - Socket->TdiAddressHandle = (HANDLE)IoStatusBlock.Information; - - /* Notify the helper DLL */ - ErrorCode = SockNotifyHelperDll(Socket, WSH_NOTIFY_BIND); - if (ErrorCode != NO_ERROR) goto error; - - /* Re-create Sockaddr format */ - ErrorCode = SockBuildSockaddr(Socket->LocalAddress, - &SocketAddressLength, - &TdiAddress->Address); - if (ErrorCode != NO_ERROR) goto error; - - /* Set us as bound */ - Socket->SharedData.State = SocketBound; - - /* Send the new data to AFD */ - ErrorCode = SockSetHandleContext(Socket); - if (ErrorCode != NO_ERROR) goto error; - - /* Update the window sizes */ - ErrorCode = SockUpdateWindowSizes(Socket, FALSE); - if (ErrorCode != NO_ERROR) goto error; - -error: - /* Check if we have a socket here */ - if (Socket) - { - /* Release the lock and dereference */ - LeaveCriticalSection(&Socket->Lock); - SockDereferenceSocket(Socket); - } - - /* Check if we should free the TDI address */ - if ((TdiAddress) && (TdiAddress != (PVOID)AddressBuffer)) - { - /* Free the Buffer */ - RtlFreeHeap(SockPrivateHeap, 0, TdiAddress); - } - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -INT -WSPAPI -WSPBind(SOCKET Handle, - const SOCKADDR *SocketAddress, - INT SocketAddressLength, - LPINT lpErrno) -{ - INT ErrorCode; - IO_STATUS_BLOCK IoStatusBlock; - PAFD_BIND_DATA BindData; - PSOCKET_INFORMATION Socket; - NTSTATUS Status; - PTDI_ADDRESS_INFO TdiAddress = NULL; - SOCKADDR_INFO SocketInfo; - PWINSOCK_TEB_DATA ThreadData; - CHAR AddressBuffer[FIELD_OFFSET(TDI_ADDRESS_INFO, Address) + - MAX_TDI_ADDRESS_LENGTH]; - ULONG BindDataLength, TdiAddressLength; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* If the socket is already bound, fail */ - if (Socket->SharedData.State != SocketOpen) - { - /* Fail */ - ErrorCode = WSAEINVAL; - goto error; - } - - /* Normalize address size */ - if (SocketAddressLength > Socket->HelperData->MaxWSAddressLength) - { - /* Don't go beyond the maximum */ - SocketAddressLength = Socket->HelperData->MaxWSAddressLength; - } - - /* Get Address Information */ - ErrorCode = Socket->HelperData->WSHGetSockaddrType((PSOCKADDR)SocketAddress, - SocketAddressLength, - &SocketInfo); - if (ErrorCode != NO_ERROR) goto error; - - /* Check how big the Bind and TDI Address Data will be */ - BindDataLength = Socket->HelperData->MaxTDIAddressLength + - FIELD_OFFSET(AFD_BIND_DATA, Address); - TdiAddressLength = Socket->HelperData->MaxTDIAddressLength + - FIELD_OFFSET(TDI_ADDRESS_INFO, Address); - - /* Check if we can fit it in the stack */ - if ((TdiAddressLength <= sizeof(AddressBuffer)) && - (BindDataLength <= sizeof(AddressBuffer))) - { - /* Use the stack */ - TdiAddress = (PVOID)AddressBuffer; - BindData = (PAFD_BIND_DATA)AddressBuffer; - } - else - { - /* Allocate from the heap */ - TdiAddress = SockAllocateHeapRoutine(SockPrivateHeap, 0, TdiAddressLength); - if (!TdiAddress) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - BindData = (PAFD_BIND_DATA)TdiAddress; - } - - /* Set the Share Type */ - if (Socket->SharedData.ExclusiveAddressUse) - { - BindData->ShareType = AFD_SHARE_EXCLUSIVE; - } - else if (SocketInfo.EndpointInfo == SockaddrEndpointInfoWildcard) - { - BindData->ShareType = AFD_SHARE_WILDCARD; - } - else if (Socket->SharedData.ReuseAddresses) - { - BindData->ShareType = AFD_SHARE_REUSE; - } - else - { - BindData->ShareType = AFD_SHARE_UNIQUE; - } - - /* Build the TDI Address */ - ErrorCode = SockBuildTdiAddress(&BindData->Address, - (PSOCKADDR)SocketAddress, - SocketAddressLength); - if (ErrorCode != NO_ERROR) goto error; - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_BIND, - BindData, - BindDataLength, - TdiAddress, - TdiAddressLength); - - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion outside the lock */ - LeaveCriticalSection(&Socket->Lock); - SockWaitForSingleObject(ThreadData->EventHandle, - Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - EnterCriticalSection(&Socket->Lock); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - - /* Save the TDI Address handle */ - Socket->TdiAddressHandle = (HANDLE)IoStatusBlock.Information; - - /* Notify the helper DLL */ - ErrorCode = SockNotifyHelperDll(Socket, WSH_NOTIFY_BIND); - if (ErrorCode != NO_ERROR) goto error; - - /* Re-create Sockaddr format */ - ErrorCode = SockBuildSockaddr(Socket->LocalAddress, - &SocketAddressLength, - &TdiAddress->Address); - if (ErrorCode != NO_ERROR) goto error; - - /* Set us as bound */ - Socket->SharedData.State = SocketBound; - - /* Send the new data to AFD */ - ErrorCode = SockSetHandleContext(Socket); - if (ErrorCode != NO_ERROR) goto error; - - /* Update the window sizes */ - ErrorCode = SockUpdateWindowSizes(Socket, FALSE); - if (ErrorCode != NO_ERROR) goto error; - -error: - /* Check if we have a socket here */ - if (Socket) - { - /* Release the lock and dereference */ - LeaveCriticalSection(&Socket->Lock); - SockDereferenceSocket(Socket); - } - - /* Check if we should free the TDI address */ - if ((TdiAddress) && (TdiAddress != (PVOID)AddressBuffer)) - { - /* Free the Buffer */ - RtlFreeHeap(SockPrivateHeap, 0, TdiAddress); - } - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - diff --git a/dll/win32/mswsock/msafd/connect.c b/dll/win32/mswsock/msafd/connect.c index a2f0fc46750..28d0a12d9e8 100644 --- a/dll/win32/mswsock/msafd/connect.c +++ b/dll/win32/mswsock/msafd/connect.c @@ -676,2037 +676,3 @@ WSPJoinLeaf(IN SOCKET s, return (SOCKET)0; } -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -BOOLEAN -WSPAPI -IsSockaddrEqualToZero(IN const struct sockaddr* SocketAddress, - IN INT SocketAddressLength) -{ - INT i; - - for (i = 0; i < SocketAddressLength; i++) - { - /* Make sure it's 0 */ - if (*(PULONG)SocketAddress + i)return FALSE; - } - - /* All zeroes, succees! */ - return TRUE; -} - -INT -WSPAPI -UnconnectDatagramSocket(IN PSOCKET_INFORMATION Socket) -{ - NTSTATUS Status; - INT ErrorCode; - PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; - AFD_DISCONNECT_INFO DisconnectInfo; - IO_STATUS_BLOCK IoStatusBlock; - - /* Set up the disconnect information */ - DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(-1); - DisconnectInfo.DisconnectType = AFD_DISCONNECT_DATAGRAM; - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_DISCONNECT, - &DisconnectInfo, - sizeof(DisconnectInfo), - NULL, - 0); - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion outside the lock */ - LeaveCriticalSection(&Socket->Lock); - SockWaitForSingleObject(ThreadData->EventHandle, - Socket->Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - EnterCriticalSection(&Socket->Lock); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Convert error code */ - ErrorCode = NtStatusToSocketError(Status); - } - else - { - /* Set us as disconnected (back to bound) */ - Socket->SharedData.State = SocketBound; - ErrorCode = NO_ERROR; - } - - /* Return to caller */ - return ErrorCode; -} - -INT -WSPAPI -SockPostProcessConnect(IN PSOCKET_INFORMATION Socket) -{ - INT ErrorCode; - - /* Notify the helper DLL */ - ErrorCode = SockNotifyHelperDll(Socket, WSH_NOTIFY_CONNECT); - if (ErrorCode != NO_ERROR) return ErrorCode; - - /* Set the new state and update the context in AFD */ - Socket->SharedData.State = SocketConnected; - ErrorCode = SockSetHandleContext(Socket); - if (ErrorCode != NO_ERROR) return ErrorCode; - - /* Update the window sizes */ - ErrorCode = SockUpdateWindowSizes(Socket, FALSE); - - /* Return to caller */ - return ErrorCode; -} - -INT -WSPAPI -SockDoConnectReal(IN PSOCKET_INFORMATION Socket, - IN const struct sockaddr *SocketAddress, - IN INT SocketAddressLength, - IN LPWSABUF lpCalleeData, - IN BOOLEAN UseSan) -{ - INT ErrorCode; - NTSTATUS Status; - DWORD ConnectDataLength; - IO_STATUS_BLOCK IoStatusBlock; - PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; - CHAR ConnectBuffer[FIELD_OFFSET(AFD_CONNECT_INFO, RemoteAddress) + - MAX_TDI_ADDRESS_LENGTH]; - PAFD_CONNECT_INFO ConnectInfo; - ULONG ConnectInfoLength; - - /* Check if someone is waiting for FD_CONNECT */ - if (Socket->SharedData.AsyncEvents & FD_CONNECT) - { - /* - * Disable FD_WRITE and FD_CONNECT - * The latter fixes a race condition where the FD_CONNECT is re-enabled - * at the end of this function right after the Async Thread disables it. - * This should only happen at the *next* WSPConnect - */ - Socket->SharedData.AsyncDisabledEvents |= FD_CONNECT | FD_WRITE; - } - - /* Calculate how much the connection structure will take */ - ConnectInfoLength = FIELD_OFFSET(AFD_CONNECT_INFO, RemoteAddress) + - Socket->HelperData->MaxTDIAddressLength; - - /* Check if our stack buffer is enough */ - if (ConnectInfoLength <= sizeof(ConnectBuffer)) - { - /* Use the stack */ - ConnectInfo = (PVOID)ConnectBuffer; - } - else - { - /* Allocate from heap */ - ConnectInfo = SockAllocateHeapRoutine(SockPrivateHeap, - 0, - ConnectInfoLength); - if (!ConnectInfo) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - } - - /* Create the TDI Address */ - ErrorCode = SockBuildTdiAddress(&ConnectInfo->RemoteAddress, - (PSOCKADDR)SocketAddress, - SocketAddressLength); - if (ErrorCode != NO_ERROR) goto error; - - /* Set the SAN State */ - ConnectInfo->UseSAN = SockSanEnabled; - - /* Check if this is a non-blocking streaming socket */ - if ((Socket->SharedData.NonBlocking) && !(MSAFD_IS_DGRAM_SOCK(Socket))) - { - /* Create the Async Thread if Needed */ - if (!SockCheckAndReferenceAsyncThread()) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - - Status = 0; - } - else - { - /* Start the connect loop */ - do - { - /* Send IOCTL */ - IoStatusBlock.Status = STATUS_PENDING; - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_CONNECT, - ConnectInfo, - ConnectInfoLength, - NULL, - 0); - - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion outside the lock */ - LeaveCriticalSection(&Socket->Lock); - SockWaitForSingleObject(ThreadData->EventHandle, - Socket->Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - EnterCriticalSection(&Socket->Lock); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Make sure we're not closed */ - if (Socket->SharedData.State == SocketClosed) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Check if we failed */ - if (!NT_SUCCESS(Status)) - { - /* Tell the helper DLL */ - ErrorCode = SockNotifyHelperDll(Socket, WSH_NOTIFY_CONNECT_ERROR); - } - - /* Keep looping if the Helper DLL wants us to */ - } while (ErrorCode == WSATRY_AGAIN); - } - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - - /* Now do post-processing */ - ErrorCode = SockPostProcessConnect(Socket); - if (ErrorCode != NO_ERROR) goto error; - - /* Check if we had callee data */ - if ((lpCalleeData) && (lpCalleeData->buf) && (lpCalleeData->len > 0)) - { - /* Set it */ - ErrorCode = SockGetConnectData(Socket, - IOCTL_AFD_SET_CONNECT_DATA_SIZE, - lpCalleeData->buf, - ConnectDataLength, - &ConnectDataLength); - if (ErrorCode == NO_ERROR) - { - /* If we didn't get any data, then assume the buffer is empty */ - if (!lpCalleeData->len) lpCalleeData->buf = NULL; - } - else - { - /* This isn't fatal, assume we didn't get anything instead */ - lpCalleeData->len = 0; - lpCalleeData->buf = NULL; - } - - /* Assume success */ - ErrorCode = NO_ERROR; - } - -error: - - /* Check if we need to free the connect info from the heap */ - if (ConnectInfo && (ConnectInfo != (PVOID)ConnectBuffer)) - { - /* Free it */ - RtlFreeHeap(SockPrivateHeap, 0, ConnectInfo); - } - - /* Check if this the success path */ - if (ErrorCode == NO_ERROR) - { - /* Check if FD_WRITE is being select()ed */ - if (Socket->SharedData.AsyncEvents & FD_WRITE) - { - /* Re-enable it */ - SockReenableAsyncSelectEvent(Socket, FD_WRITE); - } - } - - /* Return the error */ - return ErrorCode; -} - -INT -WSPAPI -SockDoConnect(SOCKET Handle, - const struct sockaddr *SocketAddress, - INT SocketAddressLength, - LPWSABUF lpCallerData, - LPWSABUF lpCalleeData, - LPQOS lpSQOS, - LPQOS lpGQOS) -{ - PSOCKET_INFORMATION Socket; - SOCKADDR_INFO SocketInfo; - PSOCKADDR Sockaddr; - PWINSOCK_TEB_DATA ThreadData; - INT SockaddrLength; - INT ErrorCode, ReturnValue; - DWORD ConnectDataLength; - DWORD BytesReturned; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) return ErrorCode; - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* Make sure we're not already connected unless we are a datagram socket */ - if ((Socket->SharedData.State == SocketConnected) && - !(MSAFD_IS_DGRAM_SOCK(Socket))) - { - /* Fail */ - ErrorCode = WSAEISCONN; - goto error; - } - - /* Check if async connect was in progress */ - if (Socket->AsyncData) - { - /* We have to clean it up */ - SockIsSocketConnected(Socket); - - /* Check again */ - if (Socket->AsyncData) - { - /* Can't do anything but fail now */ - ErrorCode = WSAEALREADY; - goto error; - } - } - - /* Make sure we're either unbound, bound, or connected */ - if ((Socket->SharedData.State != SocketOpen) && - (Socket->SharedData.State != SocketBound) && - (Socket->SharedData.State != SocketConnected)) - { - /* Fail */ - ErrorCode = WSAEINVAL; - goto error; - } - - /* Normalize the address length */ - SocketAddressLength = min(SocketAddressLength, - Socket->HelperData->MaxWSAddressLength); - - /* Also make sure it's not too small */ - if (SocketAddressLength < Socket->HelperData->MinWSAddressLength) - { - /* Fail */ - ErrorCode = WSAEFAULT; - goto error; - } - - /* - * If this is a connected socket, and the address is null (0.0.0.0), - * then do a partial disconnect if this is a datagram socket. - */ - if ((Socket->SharedData.State == SocketConnected) && - (MSAFD_IS_DGRAM_SOCK(Socket)) && - (IsSockaddrEqualToZero(SocketAddress, SocketAddressLength))) - { - /* Disconnect the socket and return */ - return UnconnectDatagramSocket(Socket); - } - - /* Make sure the Address Family is valid */ - if (Socket->SharedData.AddressFamily != SocketAddress->sa_family) - { - /* Fail */ - ErrorCode = WSAEAFNOSUPPORT; - goto error; - } - - /* If this is a non-broadcast datagram socket */ - if ((MSAFD_IS_DGRAM_SOCK(Socket) && !(Socket->SharedData.Broadcast))) - { - /* Find out what kind of address this is */ - ErrorCode = Socket->HelperData->WSHGetSockaddrType((PSOCKADDR)SocketAddress, - SocketAddressLength, - &SocketInfo); - if (ErrorCode != NO_ERROR) - { - /* Find out if this is a broadcast address */ - if (SocketInfo.AddressInfo == SockaddrAddressInfoBroadcast) - { - /* Fail: SO_BROADCAST must be set first in WinSock 2.0+ */ - ErrorCode = WSAEACCES; - } - } - - /* A failure here isn't fatal */ - ErrorCode = NO_ERROR; - } - - /* Check if this is a constrained group */ - if (Socket->SharedData.GroupType == SG_CONSTRAINED_GROUP) - { - /* Validate the address and fail if it's not consistent */ - ErrorCode = SockIsAddressConsistentWithConstrainedGroup(Socket, - Socket->SharedData.GroupID, - (PSOCKADDR)SocketAddress, - SocketAddressLength); - if (ErrorCode != NO_ERROR) goto error; - } - - /* Check if this socket isn't bound yet */ - if (Socket->SharedData.State == SocketOpen) - { - /* Check if we can request the wildcard address */ - if (Socket->HelperData->WSHGetWildcardSockaddr) - { - /* Allocate a new Sockaddr */ - SockaddrLength = Socket->HelperData->MaxWSAddressLength; - Sockaddr = SockAllocateHeapRoutine(SockPrivateHeap, 0, SockaddrLength); - if (!Sockaddr) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - - /* Get the wildcard sockaddr */ - ErrorCode = Socket->HelperData->WSHGetWildcardSockaddr(Socket->HelperContext, - Sockaddr, - &SockaddrLength); - if (ErrorCode != NO_ERROR) - { - /* Free memory and fail */ - RtlFreeHeap(SockPrivateHeap, 0, Sockaddr); - goto error; - } - - /* Bind it */ - ReturnValue = WSPBind(Handle, - Sockaddr, - SockaddrLength, - &ErrorCode); - - /* Free memory */ - RtlFreeHeap(SockPrivateHeap, 0, Sockaddr); - - /* Check if we failed */ - if (ReturnValue == SOCKET_ERROR) goto error; - } - else - { - /* Unbound socket, but can't get the wildcard. Fail */ - ErrorCode = WSAEINVAL; - goto error; - } - } - - /* Check if we have caller data */ - if ((lpCallerData) && (lpCallerData->buf) && (lpCallerData->len > 0)) - { - /* Set it */ - ConnectDataLength = lpCallerData->len; - ErrorCode = SockGetConnectData(Socket, - IOCTL_AFD_SET_CONNECT_DATA, - lpCallerData->buf, - ConnectDataLength, - &ConnectDataLength); - if (ErrorCode != NO_ERROR) goto error; - } - - /* Now check if QOS is supported */ - if ((Socket->SharedData.ServiceFlags1 & XP1_QOS_SUPPORTED)) - { - /* Check if we have QoS data */ - if (lpSQOS) - { - /* Send the IOCTL */ - ReturnValue = WSPIoctl(Handle, - SIO_SET_QOS, - lpSQOS, - sizeof(*lpSQOS), - NULL, - 0, - &BytesReturned, - NULL, - NULL, - NULL, - &ErrorCode); - if (ReturnValue == SOCKET_ERROR) goto error; - } - - /* Check if we have Group QoS data */ - if (lpGQOS) - { - /* Send the IOCTL */ - ReturnValue = WSPIoctl(Handle, - SIO_SET_QOS, - lpGQOS, - sizeof(*lpGQOS), - NULL, - 0, - &BytesReturned, - NULL, - NULL, - NULL, - &ErrorCode); - if (ReturnValue == SOCKET_ERROR) goto error; - } - } - - /* Save the address */ - RtlCopyMemory(Socket->RemoteAddress, SocketAddress, SocketAddressLength); - Socket->SharedData.SizeOfRemoteAddress = SocketAddressLength; - - /* Check if we have callee data */ - if ((lpCalleeData) && (lpCalleeData->buf) && (lpCalleeData->len > 0)) - { - /* Set it */ - ConnectDataLength = lpCalleeData->len; - ErrorCode = SockGetConnectData(Socket, - IOCTL_AFD_SET_CONNECT_DATA_SIZE, - lpCalleeData->buf, - ConnectDataLength, - &ConnectDataLength); - if (ErrorCode != NO_ERROR) goto error; - } - - /* Do the actual connect operation */ - ErrorCode = SockDoConnectReal(Socket, - SocketAddress, - SocketAddressLength, - lpCalleeData, - TRUE); - -error: - - /* Check if we had a socket yet */ - if (Socket) - { - /* Release the lock and dereference the socket */ - LeaveCriticalSection(&Socket->Lock); - SockDereferenceSocket(Socket); - } - - /* Return to caller */ - return ErrorCode; -} - -INT -WSPAPI -WSPConnect(SOCKET Handle, - const struct sockaddr * SocketAddress, - INT SocketAddressLength, - LPWSABUF lpCallerData, - LPWSABUF lpCalleeData, - LPQOS lpSQOS, - LPQOS lpGQOS, - LPINT lpErrno) -{ - INT ErrorCode; - - /* Check for caller data */ - if (lpCallerData) - { - /* Validate it */ - if ((IsBadReadPtr(lpCallerData, sizeof(WSABUF))) || - (IsBadReadPtr(lpCallerData->buf, lpCallerData->len))) - { - /* The pointers are invalid, fail */ - ErrorCode = WSAEFAULT; - goto error; - } - } - - /* Check for callee data */ - if (lpCalleeData) - { - /* Validate it */ - if ((IsBadReadPtr(lpCalleeData, sizeof(WSABUF))) || - (IsBadReadPtr(lpCalleeData->buf, lpCalleeData->len))) - { - /* The pointers are invalid, fail */ - ErrorCode = WSAEFAULT; - goto error; - } - } - - /* Check for QoS */ - if (lpSQOS) - { - /* Validate it */ - if ((IsBadReadPtr(lpSQOS, sizeof(QOS))) || - ((lpSQOS->ProviderSpecific.buf) && - (lpSQOS->ProviderSpecific.len) && - (IsBadReadPtr(lpSQOS->ProviderSpecific.buf, - lpSQOS->ProviderSpecific.len)))) - { - /* The pointers are invalid, fail */ - ErrorCode = WSAEFAULT; - goto error; - } - } - - /* Check for Group QoS */ - if (lpGQOS) - { - /* Validate it */ - if ((IsBadReadPtr(lpGQOS, sizeof(QOS))) || - ((lpGQOS->ProviderSpecific.buf) && - (lpGQOS->ProviderSpecific.len) && - (IsBadReadPtr(lpGQOS->ProviderSpecific.buf, - lpGQOS->ProviderSpecific.len)))) - { - /* The pointers are invalid, fail */ - ErrorCode = WSAEFAULT; - goto error; - } - } - - /* Do the actual connect */ - ErrorCode = SockDoConnect(Handle, - SocketAddress, - SocketAddressLength, - lpCallerData, - lpCalleeData, - lpSQOS, - lpGQOS); - -error: - /* Check if this was an error */ - if (ErrorCode != NO_ERROR) - { - /* Return error */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - -SOCKET -WSPAPI -WSPJoinLeaf(IN SOCKET s, - IN CONST SOCKADDR *name, - IN INT namelen, - IN LPWSABUF lpCallerData, - OUT LPWSABUF lpCalleeData, - IN LPQOS lpSQOS, - IN LPQOS lpGQOS, - IN DWORD dwFlags, - OUT LPINT lpErrno) -{ - return (SOCKET)0; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -BOOLEAN -WSPAPI -IsSockaddrEqualToZero(IN const struct sockaddr* SocketAddress, - IN INT SocketAddressLength) -{ - INT i; - - for (i = 0; i < SocketAddressLength; i++) - { - /* Make sure it's 0 */ - if (*(PULONG)SocketAddress + i)return FALSE; - } - - /* All zeroes, succees! */ - return TRUE; -} - -INT -WSPAPI -UnconnectDatagramSocket(IN PSOCKET_INFORMATION Socket) -{ - NTSTATUS Status; - INT ErrorCode; - PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; - AFD_DISCONNECT_INFO DisconnectInfo; - IO_STATUS_BLOCK IoStatusBlock; - - /* Set up the disconnect information */ - DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(-1); - DisconnectInfo.DisconnectType = AFD_DISCONNECT_DATAGRAM; - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_DISCONNECT, - &DisconnectInfo, - sizeof(DisconnectInfo), - NULL, - 0); - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion outside the lock */ - LeaveCriticalSection(&Socket->Lock); - SockWaitForSingleObject(ThreadData->EventHandle, - Socket->Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - EnterCriticalSection(&Socket->Lock); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Convert error code */ - ErrorCode = NtStatusToSocketError(Status); - } - else - { - /* Set us as disconnected (back to bound) */ - Socket->SharedData.State = SocketBound; - ErrorCode = NO_ERROR; - } - - /* Return to caller */ - return ErrorCode; -} - -INT -WSPAPI -SockPostProcessConnect(IN PSOCKET_INFORMATION Socket) -{ - INT ErrorCode; - - /* Notify the helper DLL */ - ErrorCode = SockNotifyHelperDll(Socket, WSH_NOTIFY_CONNECT); - if (ErrorCode != NO_ERROR) return ErrorCode; - - /* Set the new state and update the context in AFD */ - Socket->SharedData.State = SocketConnected; - ErrorCode = SockSetHandleContext(Socket); - if (ErrorCode != NO_ERROR) return ErrorCode; - - /* Update the window sizes */ - ErrorCode = SockUpdateWindowSizes(Socket, FALSE); - - /* Return to caller */ - return ErrorCode; -} - -INT -WSPAPI -SockDoConnectReal(IN PSOCKET_INFORMATION Socket, - IN const struct sockaddr *SocketAddress, - IN INT SocketAddressLength, - IN LPWSABUF lpCalleeData, - IN BOOLEAN UseSan) -{ - INT ErrorCode; - NTSTATUS Status; - DWORD ConnectDataLength; - IO_STATUS_BLOCK IoStatusBlock; - PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; - CHAR ConnectBuffer[FIELD_OFFSET(AFD_CONNECT_INFO, RemoteAddress) + - MAX_TDI_ADDRESS_LENGTH]; - PAFD_CONNECT_INFO ConnectInfo; - ULONG ConnectInfoLength; - - /* Check if someone is waiting for FD_CONNECT */ - if (Socket->SharedData.AsyncEvents & FD_CONNECT) - { - /* - * Disable FD_WRITE and FD_CONNECT - * The latter fixes a race condition where the FD_CONNECT is re-enabled - * at the end of this function right after the Async Thread disables it. - * This should only happen at the *next* WSPConnect - */ - Socket->SharedData.AsyncDisabledEvents |= FD_CONNECT | FD_WRITE; - } - - /* Calculate how much the connection structure will take */ - ConnectInfoLength = FIELD_OFFSET(AFD_CONNECT_INFO, RemoteAddress) + - Socket->HelperData->MaxTDIAddressLength; - - /* Check if our stack buffer is enough */ - if (ConnectInfoLength <= sizeof(ConnectBuffer)) - { - /* Use the stack */ - ConnectInfo = (PVOID)ConnectBuffer; - } - else - { - /* Allocate from heap */ - ConnectInfo = SockAllocateHeapRoutine(SockPrivateHeap, - 0, - ConnectInfoLength); - if (!ConnectInfo) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - } - - /* Create the TDI Address */ - ErrorCode = SockBuildTdiAddress(&ConnectInfo->RemoteAddress, - (PSOCKADDR)SocketAddress, - SocketAddressLength); - if (ErrorCode != NO_ERROR) goto error; - - /* Set the SAN State */ - ConnectInfo->UseSAN = SockSanEnabled; - - /* Check if this is a non-blocking streaming socket */ - if ((Socket->SharedData.NonBlocking) && !(MSAFD_IS_DGRAM_SOCK(Socket))) - { - /* Create the Async Thread if Needed */ - if (!SockCheckAndReferenceAsyncThread()) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - - Status = 0; - } - else - { - /* Start the connect loop */ - do - { - /* Send IOCTL */ - IoStatusBlock.Status = STATUS_PENDING; - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_CONNECT, - ConnectInfo, - ConnectInfoLength, - NULL, - 0); - - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion outside the lock */ - LeaveCriticalSection(&Socket->Lock); - SockWaitForSingleObject(ThreadData->EventHandle, - Socket->Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - EnterCriticalSection(&Socket->Lock); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Make sure we're not closed */ - if (Socket->SharedData.State == SocketClosed) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Check if we failed */ - if (!NT_SUCCESS(Status)) - { - /* Tell the helper DLL */ - ErrorCode = SockNotifyHelperDll(Socket, WSH_NOTIFY_CONNECT_ERROR); - } - - /* Keep looping if the Helper DLL wants us to */ - } while (ErrorCode == WSATRY_AGAIN); - } - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - - /* Now do post-processing */ - ErrorCode = SockPostProcessConnect(Socket); - if (ErrorCode != NO_ERROR) goto error; - - /* Check if we had callee data */ - if ((lpCalleeData) && (lpCalleeData->buf) && (lpCalleeData->len > 0)) - { - /* Set it */ - ErrorCode = SockGetConnectData(Socket, - IOCTL_AFD_SET_CONNECT_DATA_SIZE, - lpCalleeData->buf, - ConnectDataLength, - &ConnectDataLength); - if (ErrorCode == NO_ERROR) - { - /* If we didn't get any data, then assume the buffer is empty */ - if (!lpCalleeData->len) lpCalleeData->buf = NULL; - } - else - { - /* This isn't fatal, assume we didn't get anything instead */ - lpCalleeData->len = 0; - lpCalleeData->buf = NULL; - } - - /* Assume success */ - ErrorCode = NO_ERROR; - } - -error: - - /* Check if we need to free the connect info from the heap */ - if (ConnectInfo && (ConnectInfo != (PVOID)ConnectBuffer)) - { - /* Free it */ - RtlFreeHeap(SockPrivateHeap, 0, ConnectInfo); - } - - /* Check if this the success path */ - if (ErrorCode == NO_ERROR) - { - /* Check if FD_WRITE is being select()ed */ - if (Socket->SharedData.AsyncEvents & FD_WRITE) - { - /* Re-enable it */ - SockReenableAsyncSelectEvent(Socket, FD_WRITE); - } - } - - /* Return the error */ - return ErrorCode; -} - -INT -WSPAPI -SockDoConnect(SOCKET Handle, - const struct sockaddr *SocketAddress, - INT SocketAddressLength, - LPWSABUF lpCallerData, - LPWSABUF lpCalleeData, - LPQOS lpSQOS, - LPQOS lpGQOS) -{ - PSOCKET_INFORMATION Socket; - SOCKADDR_INFO SocketInfo; - PSOCKADDR Sockaddr; - PWINSOCK_TEB_DATA ThreadData; - INT SockaddrLength; - INT ErrorCode, ReturnValue; - DWORD ConnectDataLength; - DWORD BytesReturned; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) return ErrorCode; - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* Make sure we're not already connected unless we are a datagram socket */ - if ((Socket->SharedData.State == SocketConnected) && - !(MSAFD_IS_DGRAM_SOCK(Socket))) - { - /* Fail */ - ErrorCode = WSAEISCONN; - goto error; - } - - /* Check if async connect was in progress */ - if (Socket->AsyncData) - { - /* We have to clean it up */ - SockIsSocketConnected(Socket); - - /* Check again */ - if (Socket->AsyncData) - { - /* Can't do anything but fail now */ - ErrorCode = WSAEALREADY; - goto error; - } - } - - /* Make sure we're either unbound, bound, or connected */ - if ((Socket->SharedData.State != SocketOpen) && - (Socket->SharedData.State != SocketBound) && - (Socket->SharedData.State != SocketConnected)) - { - /* Fail */ - ErrorCode = WSAEINVAL; - goto error; - } - - /* Normalize the address length */ - SocketAddressLength = min(SocketAddressLength, - Socket->HelperData->MaxWSAddressLength); - - /* Also make sure it's not too small */ - if (SocketAddressLength < Socket->HelperData->MinWSAddressLength) - { - /* Fail */ - ErrorCode = WSAEFAULT; - goto error; - } - - /* - * If this is a connected socket, and the address is null (0.0.0.0), - * then do a partial disconnect if this is a datagram socket. - */ - if ((Socket->SharedData.State == SocketConnected) && - (MSAFD_IS_DGRAM_SOCK(Socket)) && - (IsSockaddrEqualToZero(SocketAddress, SocketAddressLength))) - { - /* Disconnect the socket and return */ - return UnconnectDatagramSocket(Socket); - } - - /* Make sure the Address Family is valid */ - if (Socket->SharedData.AddressFamily != SocketAddress->sa_family) - { - /* Fail */ - ErrorCode = WSAEAFNOSUPPORT; - goto error; - } - - /* If this is a non-broadcast datagram socket */ - if ((MSAFD_IS_DGRAM_SOCK(Socket) && !(Socket->SharedData.Broadcast))) - { - /* Find out what kind of address this is */ - ErrorCode = Socket->HelperData->WSHGetSockaddrType((PSOCKADDR)SocketAddress, - SocketAddressLength, - &SocketInfo); - if (ErrorCode != NO_ERROR) - { - /* Find out if this is a broadcast address */ - if (SocketInfo.AddressInfo == SockaddrAddressInfoBroadcast) - { - /* Fail: SO_BROADCAST must be set first in WinSock 2.0+ */ - ErrorCode = WSAEACCES; - } - } - - /* A failure here isn't fatal */ - ErrorCode = NO_ERROR; - } - - /* Check if this is a constrained group */ - if (Socket->SharedData.GroupType == SG_CONSTRAINED_GROUP) - { - /* Validate the address and fail if it's not consistent */ - ErrorCode = SockIsAddressConsistentWithConstrainedGroup(Socket, - Socket->SharedData.GroupID, - (PSOCKADDR)SocketAddress, - SocketAddressLength); - if (ErrorCode != NO_ERROR) goto error; - } - - /* Check if this socket isn't bound yet */ - if (Socket->SharedData.State == SocketOpen) - { - /* Check if we can request the wildcard address */ - if (Socket->HelperData->WSHGetWildcardSockaddr) - { - /* Allocate a new Sockaddr */ - SockaddrLength = Socket->HelperData->MaxWSAddressLength; - Sockaddr = SockAllocateHeapRoutine(SockPrivateHeap, 0, SockaddrLength); - if (!Sockaddr) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - - /* Get the wildcard sockaddr */ - ErrorCode = Socket->HelperData->WSHGetWildcardSockaddr(Socket->HelperContext, - Sockaddr, - &SockaddrLength); - if (ErrorCode != NO_ERROR) - { - /* Free memory and fail */ - RtlFreeHeap(SockPrivateHeap, 0, Sockaddr); - goto error; - } - - /* Bind it */ - ReturnValue = WSPBind(Handle, - Sockaddr, - SockaddrLength, - &ErrorCode); - - /* Free memory */ - RtlFreeHeap(SockPrivateHeap, 0, Sockaddr); - - /* Check if we failed */ - if (ReturnValue == SOCKET_ERROR) goto error; - } - else - { - /* Unbound socket, but can't get the wildcard. Fail */ - ErrorCode = WSAEINVAL; - goto error; - } - } - - /* Check if we have caller data */ - if ((lpCallerData) && (lpCallerData->buf) && (lpCallerData->len > 0)) - { - /* Set it */ - ConnectDataLength = lpCallerData->len; - ErrorCode = SockGetConnectData(Socket, - IOCTL_AFD_SET_CONNECT_DATA, - lpCallerData->buf, - ConnectDataLength, - &ConnectDataLength); - if (ErrorCode != NO_ERROR) goto error; - } - - /* Now check if QOS is supported */ - if ((Socket->SharedData.ServiceFlags1 & XP1_QOS_SUPPORTED)) - { - /* Check if we have QoS data */ - if (lpSQOS) - { - /* Send the IOCTL */ - ReturnValue = WSPIoctl(Handle, - SIO_SET_QOS, - lpSQOS, - sizeof(*lpSQOS), - NULL, - 0, - &BytesReturned, - NULL, - NULL, - NULL, - &ErrorCode); - if (ReturnValue == SOCKET_ERROR) goto error; - } - - /* Check if we have Group QoS data */ - if (lpGQOS) - { - /* Send the IOCTL */ - ReturnValue = WSPIoctl(Handle, - SIO_SET_QOS, - lpGQOS, - sizeof(*lpGQOS), - NULL, - 0, - &BytesReturned, - NULL, - NULL, - NULL, - &ErrorCode); - if (ReturnValue == SOCKET_ERROR) goto error; - } - } - - /* Save the address */ - RtlCopyMemory(Socket->RemoteAddress, SocketAddress, SocketAddressLength); - Socket->SharedData.SizeOfRemoteAddress = SocketAddressLength; - - /* Check if we have callee data */ - if ((lpCalleeData) && (lpCalleeData->buf) && (lpCalleeData->len > 0)) - { - /* Set it */ - ConnectDataLength = lpCalleeData->len; - ErrorCode = SockGetConnectData(Socket, - IOCTL_AFD_SET_CONNECT_DATA_SIZE, - lpCalleeData->buf, - ConnectDataLength, - &ConnectDataLength); - if (ErrorCode != NO_ERROR) goto error; - } - - /* Do the actual connect operation */ - ErrorCode = SockDoConnectReal(Socket, - SocketAddress, - SocketAddressLength, - lpCalleeData, - TRUE); - -error: - - /* Check if we had a socket yet */ - if (Socket) - { - /* Release the lock and dereference the socket */ - LeaveCriticalSection(&Socket->Lock); - SockDereferenceSocket(Socket); - } - - /* Return to caller */ - return ErrorCode; -} - -INT -WSPAPI -WSPConnect(SOCKET Handle, - const struct sockaddr * SocketAddress, - INT SocketAddressLength, - LPWSABUF lpCallerData, - LPWSABUF lpCalleeData, - LPQOS lpSQOS, - LPQOS lpGQOS, - LPINT lpErrno) -{ - INT ErrorCode; - - /* Check for caller data */ - if (lpCallerData) - { - /* Validate it */ - if ((IsBadReadPtr(lpCallerData, sizeof(WSABUF))) || - (IsBadReadPtr(lpCallerData->buf, lpCallerData->len))) - { - /* The pointers are invalid, fail */ - ErrorCode = WSAEFAULT; - goto error; - } - } - - /* Check for callee data */ - if (lpCalleeData) - { - /* Validate it */ - if ((IsBadReadPtr(lpCalleeData, sizeof(WSABUF))) || - (IsBadReadPtr(lpCalleeData->buf, lpCalleeData->len))) - { - /* The pointers are invalid, fail */ - ErrorCode = WSAEFAULT; - goto error; - } - } - - /* Check for QoS */ - if (lpSQOS) - { - /* Validate it */ - if ((IsBadReadPtr(lpSQOS, sizeof(QOS))) || - ((lpSQOS->ProviderSpecific.buf) && - (lpSQOS->ProviderSpecific.len) && - (IsBadReadPtr(lpSQOS->ProviderSpecific.buf, - lpSQOS->ProviderSpecific.len)))) - { - /* The pointers are invalid, fail */ - ErrorCode = WSAEFAULT; - goto error; - } - } - - /* Check for Group QoS */ - if (lpGQOS) - { - /* Validate it */ - if ((IsBadReadPtr(lpGQOS, sizeof(QOS))) || - ((lpGQOS->ProviderSpecific.buf) && - (lpGQOS->ProviderSpecific.len) && - (IsBadReadPtr(lpGQOS->ProviderSpecific.buf, - lpGQOS->ProviderSpecific.len)))) - { - /* The pointers are invalid, fail */ - ErrorCode = WSAEFAULT; - goto error; - } - } - - /* Do the actual connect */ - ErrorCode = SockDoConnect(Handle, - SocketAddress, - SocketAddressLength, - lpCallerData, - lpCalleeData, - lpSQOS, - lpGQOS); - -error: - /* Check if this was an error */ - if (ErrorCode != NO_ERROR) - { - /* Return error */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - -SOCKET -WSPAPI -WSPJoinLeaf(IN SOCKET s, - IN CONST SOCKADDR *name, - IN INT namelen, - IN LPWSABUF lpCallerData, - OUT LPWSABUF lpCalleeData, - IN LPQOS lpSQOS, - IN LPQOS lpGQOS, - IN DWORD dwFlags, - OUT LPINT lpErrno) -{ - return (SOCKET)0; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -BOOLEAN -WSPAPI -IsSockaddrEqualToZero(IN const struct sockaddr* SocketAddress, - IN INT SocketAddressLength) -{ - INT i; - - for (i = 0; i < SocketAddressLength; i++) - { - /* Make sure it's 0 */ - if (*(PULONG)SocketAddress + i)return FALSE; - } - - /* All zeroes, succees! */ - return TRUE; -} - -INT -WSPAPI -UnconnectDatagramSocket(IN PSOCKET_INFORMATION Socket) -{ - NTSTATUS Status; - INT ErrorCode; - PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; - AFD_DISCONNECT_INFO DisconnectInfo; - IO_STATUS_BLOCK IoStatusBlock; - - /* Set up the disconnect information */ - DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(-1); - DisconnectInfo.DisconnectType = AFD_DISCONNECT_DATAGRAM; - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_DISCONNECT, - &DisconnectInfo, - sizeof(DisconnectInfo), - NULL, - 0); - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion outside the lock */ - LeaveCriticalSection(&Socket->Lock); - SockWaitForSingleObject(ThreadData->EventHandle, - Socket->Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - EnterCriticalSection(&Socket->Lock); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Convert error code */ - ErrorCode = NtStatusToSocketError(Status); - } - else - { - /* Set us as disconnected (back to bound) */ - Socket->SharedData.State = SocketBound; - ErrorCode = NO_ERROR; - } - - /* Return to caller */ - return ErrorCode; -} - -INT -WSPAPI -SockPostProcessConnect(IN PSOCKET_INFORMATION Socket) -{ - INT ErrorCode; - - /* Notify the helper DLL */ - ErrorCode = SockNotifyHelperDll(Socket, WSH_NOTIFY_CONNECT); - if (ErrorCode != NO_ERROR) return ErrorCode; - - /* Set the new state and update the context in AFD */ - Socket->SharedData.State = SocketConnected; - ErrorCode = SockSetHandleContext(Socket); - if (ErrorCode != NO_ERROR) return ErrorCode; - - /* Update the window sizes */ - ErrorCode = SockUpdateWindowSizes(Socket, FALSE); - - /* Return to caller */ - return ErrorCode; -} - -INT -WSPAPI -SockDoConnectReal(IN PSOCKET_INFORMATION Socket, - IN const struct sockaddr *SocketAddress, - IN INT SocketAddressLength, - IN LPWSABUF lpCalleeData, - IN BOOLEAN UseSan) -{ - INT ErrorCode; - NTSTATUS Status; - DWORD ConnectDataLength; - IO_STATUS_BLOCK IoStatusBlock; - PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; - CHAR ConnectBuffer[FIELD_OFFSET(AFD_CONNECT_INFO, RemoteAddress) + - MAX_TDI_ADDRESS_LENGTH]; - PAFD_CONNECT_INFO ConnectInfo; - ULONG ConnectInfoLength; - - /* Check if someone is waiting for FD_CONNECT */ - if (Socket->SharedData.AsyncEvents & FD_CONNECT) - { - /* - * Disable FD_WRITE and FD_CONNECT - * The latter fixes a race condition where the FD_CONNECT is re-enabled - * at the end of this function right after the Async Thread disables it. - * This should only happen at the *next* WSPConnect - */ - Socket->SharedData.AsyncDisabledEvents |= FD_CONNECT | FD_WRITE; - } - - /* Calculate how much the connection structure will take */ - ConnectInfoLength = FIELD_OFFSET(AFD_CONNECT_INFO, RemoteAddress) + - Socket->HelperData->MaxTDIAddressLength; - - /* Check if our stack buffer is enough */ - if (ConnectInfoLength <= sizeof(ConnectBuffer)) - { - /* Use the stack */ - ConnectInfo = (PVOID)ConnectBuffer; - } - else - { - /* Allocate from heap */ - ConnectInfo = SockAllocateHeapRoutine(SockPrivateHeap, - 0, - ConnectInfoLength); - if (!ConnectInfo) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - } - - /* Create the TDI Address */ - ErrorCode = SockBuildTdiAddress(&ConnectInfo->RemoteAddress, - (PSOCKADDR)SocketAddress, - SocketAddressLength); - if (ErrorCode != NO_ERROR) goto error; - - /* Set the SAN State */ - ConnectInfo->UseSAN = SockSanEnabled; - - /* Check if this is a non-blocking streaming socket */ - if ((Socket->SharedData.NonBlocking) && !(MSAFD_IS_DGRAM_SOCK(Socket))) - { - /* Create the Async Thread if Needed */ - if (!SockCheckAndReferenceAsyncThread()) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - - Status = 0; - } - else - { - /* Start the connect loop */ - do - { - /* Send IOCTL */ - IoStatusBlock.Status = STATUS_PENDING; - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_CONNECT, - ConnectInfo, - ConnectInfoLength, - NULL, - 0); - - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion outside the lock */ - LeaveCriticalSection(&Socket->Lock); - SockWaitForSingleObject(ThreadData->EventHandle, - Socket->Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - EnterCriticalSection(&Socket->Lock); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Make sure we're not closed */ - if (Socket->SharedData.State == SocketClosed) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Check if we failed */ - if (!NT_SUCCESS(Status)) - { - /* Tell the helper DLL */ - ErrorCode = SockNotifyHelperDll(Socket, WSH_NOTIFY_CONNECT_ERROR); - } - - /* Keep looping if the Helper DLL wants us to */ - } while (ErrorCode == WSATRY_AGAIN); - } - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - - /* Now do post-processing */ - ErrorCode = SockPostProcessConnect(Socket); - if (ErrorCode != NO_ERROR) goto error; - - /* Check if we had callee data */ - if ((lpCalleeData) && (lpCalleeData->buf) && (lpCalleeData->len > 0)) - { - /* Set it */ - ErrorCode = SockGetConnectData(Socket, - IOCTL_AFD_SET_CONNECT_DATA_SIZE, - lpCalleeData->buf, - ConnectDataLength, - &ConnectDataLength); - if (ErrorCode == NO_ERROR) - { - /* If we didn't get any data, then assume the buffer is empty */ - if (!lpCalleeData->len) lpCalleeData->buf = NULL; - } - else - { - /* This isn't fatal, assume we didn't get anything instead */ - lpCalleeData->len = 0; - lpCalleeData->buf = NULL; - } - - /* Assume success */ - ErrorCode = NO_ERROR; - } - -error: - - /* Check if we need to free the connect info from the heap */ - if (ConnectInfo && (ConnectInfo != (PVOID)ConnectBuffer)) - { - /* Free it */ - RtlFreeHeap(SockPrivateHeap, 0, ConnectInfo); - } - - /* Check if this the success path */ - if (ErrorCode == NO_ERROR) - { - /* Check if FD_WRITE is being select()ed */ - if (Socket->SharedData.AsyncEvents & FD_WRITE) - { - /* Re-enable it */ - SockReenableAsyncSelectEvent(Socket, FD_WRITE); - } - } - - /* Return the error */ - return ErrorCode; -} - -INT -WSPAPI -SockDoConnect(SOCKET Handle, - const struct sockaddr *SocketAddress, - INT SocketAddressLength, - LPWSABUF lpCallerData, - LPWSABUF lpCalleeData, - LPQOS lpSQOS, - LPQOS lpGQOS) -{ - PSOCKET_INFORMATION Socket; - SOCKADDR_INFO SocketInfo; - PSOCKADDR Sockaddr; - PWINSOCK_TEB_DATA ThreadData; - INT SockaddrLength; - INT ErrorCode, ReturnValue; - DWORD ConnectDataLength; - DWORD BytesReturned; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) return ErrorCode; - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* Make sure we're not already connected unless we are a datagram socket */ - if ((Socket->SharedData.State == SocketConnected) && - !(MSAFD_IS_DGRAM_SOCK(Socket))) - { - /* Fail */ - ErrorCode = WSAEISCONN; - goto error; - } - - /* Check if async connect was in progress */ - if (Socket->AsyncData) - { - /* We have to clean it up */ - SockIsSocketConnected(Socket); - - /* Check again */ - if (Socket->AsyncData) - { - /* Can't do anything but fail now */ - ErrorCode = WSAEALREADY; - goto error; - } - } - - /* Make sure we're either unbound, bound, or connected */ - if ((Socket->SharedData.State != SocketOpen) && - (Socket->SharedData.State != SocketBound) && - (Socket->SharedData.State != SocketConnected)) - { - /* Fail */ - ErrorCode = WSAEINVAL; - goto error; - } - - /* Normalize the address length */ - SocketAddressLength = min(SocketAddressLength, - Socket->HelperData->MaxWSAddressLength); - - /* Also make sure it's not too small */ - if (SocketAddressLength < Socket->HelperData->MinWSAddressLength) - { - /* Fail */ - ErrorCode = WSAEFAULT; - goto error; - } - - /* - * If this is a connected socket, and the address is null (0.0.0.0), - * then do a partial disconnect if this is a datagram socket. - */ - if ((Socket->SharedData.State == SocketConnected) && - (MSAFD_IS_DGRAM_SOCK(Socket)) && - (IsSockaddrEqualToZero(SocketAddress, SocketAddressLength))) - { - /* Disconnect the socket and return */ - return UnconnectDatagramSocket(Socket); - } - - /* Make sure the Address Family is valid */ - if (Socket->SharedData.AddressFamily != SocketAddress->sa_family) - { - /* Fail */ - ErrorCode = WSAEAFNOSUPPORT; - goto error; - } - - /* If this is a non-broadcast datagram socket */ - if ((MSAFD_IS_DGRAM_SOCK(Socket) && !(Socket->SharedData.Broadcast))) - { - /* Find out what kind of address this is */ - ErrorCode = Socket->HelperData->WSHGetSockaddrType((PSOCKADDR)SocketAddress, - SocketAddressLength, - &SocketInfo); - if (ErrorCode != NO_ERROR) - { - /* Find out if this is a broadcast address */ - if (SocketInfo.AddressInfo == SockaddrAddressInfoBroadcast) - { - /* Fail: SO_BROADCAST must be set first in WinSock 2.0+ */ - ErrorCode = WSAEACCES; - } - } - - /* A failure here isn't fatal */ - ErrorCode = NO_ERROR; - } - - /* Check if this is a constrained group */ - if (Socket->SharedData.GroupType == SG_CONSTRAINED_GROUP) - { - /* Validate the address and fail if it's not consistent */ - ErrorCode = SockIsAddressConsistentWithConstrainedGroup(Socket, - Socket->SharedData.GroupID, - (PSOCKADDR)SocketAddress, - SocketAddressLength); - if (ErrorCode != NO_ERROR) goto error; - } - - /* Check if this socket isn't bound yet */ - if (Socket->SharedData.State == SocketOpen) - { - /* Check if we can request the wildcard address */ - if (Socket->HelperData->WSHGetWildcardSockaddr) - { - /* Allocate a new Sockaddr */ - SockaddrLength = Socket->HelperData->MaxWSAddressLength; - Sockaddr = SockAllocateHeapRoutine(SockPrivateHeap, 0, SockaddrLength); - if (!Sockaddr) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - - /* Get the wildcard sockaddr */ - ErrorCode = Socket->HelperData->WSHGetWildcardSockaddr(Socket->HelperContext, - Sockaddr, - &SockaddrLength); - if (ErrorCode != NO_ERROR) - { - /* Free memory and fail */ - RtlFreeHeap(SockPrivateHeap, 0, Sockaddr); - goto error; - } - - /* Bind it */ - ReturnValue = WSPBind(Handle, - Sockaddr, - SockaddrLength, - &ErrorCode); - - /* Free memory */ - RtlFreeHeap(SockPrivateHeap, 0, Sockaddr); - - /* Check if we failed */ - if (ReturnValue == SOCKET_ERROR) goto error; - } - else - { - /* Unbound socket, but can't get the wildcard. Fail */ - ErrorCode = WSAEINVAL; - goto error; - } - } - - /* Check if we have caller data */ - if ((lpCallerData) && (lpCallerData->buf) && (lpCallerData->len > 0)) - { - /* Set it */ - ConnectDataLength = lpCallerData->len; - ErrorCode = SockGetConnectData(Socket, - IOCTL_AFD_SET_CONNECT_DATA, - lpCallerData->buf, - ConnectDataLength, - &ConnectDataLength); - if (ErrorCode != NO_ERROR) goto error; - } - - /* Now check if QOS is supported */ - if ((Socket->SharedData.ServiceFlags1 & XP1_QOS_SUPPORTED)) - { - /* Check if we have QoS data */ - if (lpSQOS) - { - /* Send the IOCTL */ - ReturnValue = WSPIoctl(Handle, - SIO_SET_QOS, - lpSQOS, - sizeof(*lpSQOS), - NULL, - 0, - &BytesReturned, - NULL, - NULL, - NULL, - &ErrorCode); - if (ReturnValue == SOCKET_ERROR) goto error; - } - - /* Check if we have Group QoS data */ - if (lpGQOS) - { - /* Send the IOCTL */ - ReturnValue = WSPIoctl(Handle, - SIO_SET_QOS, - lpGQOS, - sizeof(*lpGQOS), - NULL, - 0, - &BytesReturned, - NULL, - NULL, - NULL, - &ErrorCode); - if (ReturnValue == SOCKET_ERROR) goto error; - } - } - - /* Save the address */ - RtlCopyMemory(Socket->RemoteAddress, SocketAddress, SocketAddressLength); - Socket->SharedData.SizeOfRemoteAddress = SocketAddressLength; - - /* Check if we have callee data */ - if ((lpCalleeData) && (lpCalleeData->buf) && (lpCalleeData->len > 0)) - { - /* Set it */ - ConnectDataLength = lpCalleeData->len; - ErrorCode = SockGetConnectData(Socket, - IOCTL_AFD_SET_CONNECT_DATA_SIZE, - lpCalleeData->buf, - ConnectDataLength, - &ConnectDataLength); - if (ErrorCode != NO_ERROR) goto error; - } - - /* Do the actual connect operation */ - ErrorCode = SockDoConnectReal(Socket, - SocketAddress, - SocketAddressLength, - lpCalleeData, - TRUE); - -error: - - /* Check if we had a socket yet */ - if (Socket) - { - /* Release the lock and dereference the socket */ - LeaveCriticalSection(&Socket->Lock); - SockDereferenceSocket(Socket); - } - - /* Return to caller */ - return ErrorCode; -} - -INT -WSPAPI -WSPConnect(SOCKET Handle, - const struct sockaddr * SocketAddress, - INT SocketAddressLength, - LPWSABUF lpCallerData, - LPWSABUF lpCalleeData, - LPQOS lpSQOS, - LPQOS lpGQOS, - LPINT lpErrno) -{ - INT ErrorCode; - - /* Check for caller data */ - if (lpCallerData) - { - /* Validate it */ - if ((IsBadReadPtr(lpCallerData, sizeof(WSABUF))) || - (IsBadReadPtr(lpCallerData->buf, lpCallerData->len))) - { - /* The pointers are invalid, fail */ - ErrorCode = WSAEFAULT; - goto error; - } - } - - /* Check for callee data */ - if (lpCalleeData) - { - /* Validate it */ - if ((IsBadReadPtr(lpCalleeData, sizeof(WSABUF))) || - (IsBadReadPtr(lpCalleeData->buf, lpCalleeData->len))) - { - /* The pointers are invalid, fail */ - ErrorCode = WSAEFAULT; - goto error; - } - } - - /* Check for QoS */ - if (lpSQOS) - { - /* Validate it */ - if ((IsBadReadPtr(lpSQOS, sizeof(QOS))) || - ((lpSQOS->ProviderSpecific.buf) && - (lpSQOS->ProviderSpecific.len) && - (IsBadReadPtr(lpSQOS->ProviderSpecific.buf, - lpSQOS->ProviderSpecific.len)))) - { - /* The pointers are invalid, fail */ - ErrorCode = WSAEFAULT; - goto error; - } - } - - /* Check for Group QoS */ - if (lpGQOS) - { - /* Validate it */ - if ((IsBadReadPtr(lpGQOS, sizeof(QOS))) || - ((lpGQOS->ProviderSpecific.buf) && - (lpGQOS->ProviderSpecific.len) && - (IsBadReadPtr(lpGQOS->ProviderSpecific.buf, - lpGQOS->ProviderSpecific.len)))) - { - /* The pointers are invalid, fail */ - ErrorCode = WSAEFAULT; - goto error; - } - } - - /* Do the actual connect */ - ErrorCode = SockDoConnect(Handle, - SocketAddress, - SocketAddressLength, - lpCallerData, - lpCalleeData, - lpSQOS, - lpGQOS); - -error: - /* Check if this was an error */ - if (ErrorCode != NO_ERROR) - { - /* Return error */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - -SOCKET -WSPAPI -WSPJoinLeaf(IN SOCKET s, - IN CONST SOCKADDR *name, - IN INT namelen, - IN LPWSABUF lpCallerData, - OUT LPWSABUF lpCalleeData, - IN LPQOS lpSQOS, - IN LPQOS lpGQOS, - IN DWORD dwFlags, - OUT LPINT lpErrno) -{ - return (SOCKET)0; -} - diff --git a/dll/win32/mswsock/msafd/eventsel.c b/dll/win32/mswsock/msafd/eventsel.c index ff379a43460..1c6a05d6540 100644 --- a/dll/win32/mswsock/msafd/eventsel.c +++ b/dll/win32/mswsock/msafd/eventsel.c @@ -425,1284 +425,3 @@ error: return NO_ERROR; } -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -typedef struct _SOCK_EVENT_MAPPING -{ - ULONG AfdBit; - ULONG WinsockBit; -} SOCK_EVENT_MAPPING, *PSOCK_EVENT_MAPPING; - -SOCK_EVENT_MAPPING PollEventMapping[] = - { - {AFD_EVENT_RECEIVE_BIT, FD_READ_BIT}, - {AFD_EVENT_SEND_BIT, FD_WRITE_BIT}, - {AFD_EVENT_OOB_RECEIVE_BIT, FD_OOB_BIT}, - {AFD_EVENT_ACCEPT_BIT, FD_ACCEPT_BIT}, - {AFD_EVENT_QOS_BIT, FD_QOS_BIT}, - {AFD_EVENT_GROUP_QOS_BIT, FD_GROUP_QOS_BIT}, - {AFD_EVENT_ROUTING_INTERFACE_CHANGE_BIT, FD_ROUTING_INTERFACE_CHANGE_BIT}, - {AFD_EVENT_ADDRESS_LIST_CHANGE_BIT, FD_ADDRESS_LIST_CHANGE_BIT} -}; - -/* FUNCTIONS *****************************************************************/ - -INT -WSPAPI -SockEventSelectHelper(IN PSOCKET_INFORMATION Socket, - IN WSAEVENT EventObject, - IN LONG Events) -{ - IO_STATUS_BLOCK IoStatusBlock; - AFD_EVENT_SELECT_INFO PollInfo; - NTSTATUS Status; - PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; - - /* Acquire the lock */ - EnterCriticalSection(&Socket->Lock); - - /* Set Structure Info */ - PollInfo.EventObject = EventObject; - PollInfo.Events = 0; - - /* Set receive event */ - if (Events & FD_READ) PollInfo.Events |= AFD_EVENT_RECEIVE; - - /* Set write event */ - if (Events & FD_WRITE) PollInfo.Events |= AFD_EVENT_SEND; - - /* Set out-of-band (OOB) receive event */ - if (Events & FD_OOB) PollInfo.Events |= AFD_EVENT_OOB_RECEIVE; - - /* Set accept event */ - if (Events & FD_ACCEPT) PollInfo.Events |= AFD_EVENT_ACCEPT; - - /* Send Quality-of-Service (QOS) event */ - if (Events & FD_QOS) PollInfo.Events |= AFD_EVENT_QOS; - - /* Send Group Quality-of-Service (QOS) event */ - if (Events & FD_GROUP_QOS) PollInfo.Events |= AFD_EVENT_GROUP_QOS; - - /* Send connect event. Note, this also includes connect failures */ - if (Events & FD_CONNECT) PollInfo.Events |= AFD_EVENT_CONNECT | - AFD_EVENT_CONNECT_FAIL; - - /* Send close event. Note, this includes both aborts and disconnects */ - if (Events & FD_CLOSE) PollInfo.Events |= AFD_EVENT_DISCONNECT | - AFD_EVENT_ABORT; - - /* Send PnP events related to live network hardware changes */ - if (Events & FD_ROUTING_INTERFACE_CHANGE) - { - PollInfo.Events |= AFD_EVENT_ROUTING_INTERFACE_CHANGE; - } - if (Events & FD_ADDRESS_LIST_CHANGE) - { - PollInfo.Events |= AFD_EVENT_ADDRESS_LIST_CHANGE; - } - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_EVENT_SELECT, - &PollInfo, - sizeof(PollInfo), - NULL, - 0); - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion */ - SockWaitForSingleObject(ThreadData->EventHandle, - Socket->Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - LeaveCriticalSection(&Socket->Lock); - return NtStatusToSocketError(Status); - } - - /* Set Socket Data*/ - Socket->EventObject = EventObject; - Socket->NetworkEvents = Events; - - /* Release lock and return success */ - LeaveCriticalSection(&Socket->Lock); - return NO_ERROR; -} - -INT -WSPAPI -WSPEventSelect(SOCKET Handle, - WSAEVENT hEventObject, - LONG lNetworkEvents, - LPINT lpErrno) -{ - PSOCKET_INFORMATION Socket; - PWINSOCK_TEB_DATA ThreadData; - INT ErrorCode; - BOOLEAN BlockMode; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Set Socket to Non-Blocking */ - BlockMode = TRUE; - ErrorCode = SockSetInformation(Socket, - AFD_INFO_BLOCKING_MODE, - &BlockMode, - NULL, - NULL); - if (ErrorCode != NO_ERROR) goto error; - - /* AFD was notified, set it locally as well */ - Socket->SharedData.NonBlocking = TRUE; - - /* Check if there is an async select in progress */ - if (Socket->EventObject) - { - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* Erase all data */ - Socket->SharedData.hWnd = NULL; - Socket->SharedData.wMsg = 0; - Socket->SharedData.AsyncEvents = 0; - - /* Unbalance the sequence number so the request will fail */ - Socket->SharedData.SequenceNumber++; - - /* Give socket access back */ - LeaveCriticalSection(&Socket->Lock); - } - - /* Make sure the flags are valid */ - if ((lNetworkEvents & ~FD_ALL_EVENTS)) - { - /* More then the possible combination, fail */ - ErrorCode = WSAEINVAL; - goto error; - } - - /* Call the helper */ - ErrorCode = SockEventSelectHelper(Socket, hEventObject, lNetworkEvents); - -error: - /* Dereference the socket, if we have one here */ - if (Socket) SockDereferenceSocket(Socket); - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - -INT -WSPAPI -WSPEnumNetworkEvents(IN SOCKET Handle, - IN WSAEVENT hEventObject, - OUT LPWSANETWORKEVENTS lpNetworkEvents, - OUT LPINT lpErrno) -{ - AFD_ENUM_NETWORK_EVENTS_INFO EventInfo; - IO_STATUS_BLOCK IoStatusBlock; - PSOCKET_INFORMATION Socket; - PWINSOCK_TEB_DATA ThreadData; - INT ErrorCode; - NTSTATUS Status, EventStatus; - PSOCK_EVENT_MAPPING EventMapping; - ULONG i; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Make sure we got a pointer */ - if (!lpNetworkEvents) - { - /* Fail */ - ErrorCode = WSAEINVAL; - goto error; - } - - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* Send IOCTL */ - Status = NtDeviceIoControlFile((HANDLE)Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_ENUM_NETWORK_EVENTS, - hEventObject, - 0, - &EventInfo, - sizeof(EventInfo)); - - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion */ - SockWaitForSingleObject(ThreadData->EventHandle, - Socket->Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - - /* Set Events to wait for */ - lpNetworkEvents->lNetworkEvents = 0; - - /* Set our Event Mapping structure */ - EventMapping = PollEventMapping; - - /* Loop it */ - for (i = 0; i < (sizeof(PollEventMapping) / 2 * sizeof(ULONG)); i++) - { - /* First check if we have a match for this bit */ - if (EventInfo.PollEvents & (1 << EventMapping->AfdBit)) - { - /* Match found, write the equivalent bit */ - lpNetworkEvents->lNetworkEvents |= (1 << EventMapping->WinsockBit); - - /* Now get the status */ - EventStatus = EventInfo.EventStatus[EventMapping->AfdBit]; - - /* Check if it failed */ - if (!NT_SUCCESS(Status)) - { - /* Write the Winsock status code directly */ - lpNetworkEvents->iErrorCode[EventMapping->WinsockBit] = NtStatusToSocketError(EventStatus); - } - else - { - /* Write success */ - lpNetworkEvents->iErrorCode[EventMapping->WinsockBit] = NO_ERROR; - } - - /* Move to the next mapping array */ - EventMapping++; - } - - /* Handle the special cases with two flags. Start with connect */ - if (EventInfo.PollEvents & AFD_EVENT_CONNECT) - { - /* Set the equivalent bit */ - lpNetworkEvents->lNetworkEvents |= FD_CONNECT; - - /* Now get the status */ - EventStatus = EventInfo.EventStatus[AFD_EVENT_CONNECT_BIT]; - - /* Check if it failed */ - if (!NT_SUCCESS(Status)) - { - /* Write the Winsock status code directly */ - lpNetworkEvents->iErrorCode[FD_CONNECT_BIT] = NtStatusToSocketError(EventStatus); - } - else - { - /* Write success */ - lpNetworkEvents->iErrorCode[FD_CONNECT_BIT] = NO_ERROR; - } - } - else if (EventInfo.PollEvents & AFD_EVENT_CONNECT_FAIL) - { - /* Do the same thing, but for the failure */ - lpNetworkEvents->lNetworkEvents |= FD_CONNECT; - - /* Now get the status */ - EventStatus = EventInfo.EventStatus[AFD_EVENT_CONNECT_FAIL_BIT]; - - /* Check if it failed */ - if (!NT_SUCCESS(Status)) - { - /* Write the Winsock status code directly */ - lpNetworkEvents->iErrorCode[FD_CONNECT_BIT] = NtStatusToSocketError(EventStatus); - } - else - { - /* Write success */ - lpNetworkEvents->iErrorCode[FD_CONNECT_BIT] = NO_ERROR; - } - } - - /* Now handle Abort/Disconnect */ - if (EventInfo.PollEvents & AFD_EVENT_ABORT) - { - /* Set the equivalent bit */ - lpNetworkEvents->lNetworkEvents |= FD_CLOSE; - - /* Now get the status */ - EventStatus = EventInfo.EventStatus[AFD_EVENT_ABORT_BIT]; - - /* Check if it failed */ - if (!NT_SUCCESS(Status)) - { - /* Write the Winsock status code directly */ - lpNetworkEvents->iErrorCode[FD_CLOSE_BIT] = NtStatusToSocketError(EventStatus); - } - else - { - /* Write success */ - lpNetworkEvents->iErrorCode[FD_CLOSE_BIT] = NO_ERROR; - } - } - else if (EventInfo.PollEvents & AFD_EVENT_DISCONNECT) - { - /* Do the same thing, but for the failure */ - lpNetworkEvents->lNetworkEvents |= FD_CLOSE; - - /* Now get the status */ - EventStatus = EventInfo.EventStatus[AFD_EVENT_DISCONNECT_BIT]; - - /* Check if it failed */ - if (!NT_SUCCESS(Status)) - { - /* Write the Winsock status code directly */ - lpNetworkEvents->iErrorCode[FD_CLOSE_BIT] = NtStatusToSocketError(EventStatus); - } - else - { - /* Write success */ - lpNetworkEvents->iErrorCode[FD_CLOSE_BIT] = NO_ERROR; - } - } - } - -error: - /* Dereference the socket, if we have one here */ - if (Socket) SockDereferenceSocket(Socket); - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -typedef struct _SOCK_EVENT_MAPPING -{ - ULONG AfdBit; - ULONG WinsockBit; -} SOCK_EVENT_MAPPING, *PSOCK_EVENT_MAPPING; - -SOCK_EVENT_MAPPING PollEventMapping[] = - { - {AFD_EVENT_RECEIVE_BIT, FD_READ_BIT}, - {AFD_EVENT_SEND_BIT, FD_WRITE_BIT}, - {AFD_EVENT_OOB_RECEIVE_BIT, FD_OOB_BIT}, - {AFD_EVENT_ACCEPT_BIT, FD_ACCEPT_BIT}, - {AFD_EVENT_QOS_BIT, FD_QOS_BIT}, - {AFD_EVENT_GROUP_QOS_BIT, FD_GROUP_QOS_BIT}, - {AFD_EVENT_ROUTING_INTERFACE_CHANGE_BIT, FD_ROUTING_INTERFACE_CHANGE_BIT}, - {AFD_EVENT_ADDRESS_LIST_CHANGE_BIT, FD_ADDRESS_LIST_CHANGE_BIT} -}; - -/* FUNCTIONS *****************************************************************/ - -INT -WSPAPI -SockEventSelectHelper(IN PSOCKET_INFORMATION Socket, - IN WSAEVENT EventObject, - IN LONG Events) -{ - IO_STATUS_BLOCK IoStatusBlock; - AFD_EVENT_SELECT_INFO PollInfo; - NTSTATUS Status; - PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; - - /* Acquire the lock */ - EnterCriticalSection(&Socket->Lock); - - /* Set Structure Info */ - PollInfo.EventObject = EventObject; - PollInfo.Events = 0; - - /* Set receive event */ - if (Events & FD_READ) PollInfo.Events |= AFD_EVENT_RECEIVE; - - /* Set write event */ - if (Events & FD_WRITE) PollInfo.Events |= AFD_EVENT_SEND; - - /* Set out-of-band (OOB) receive event */ - if (Events & FD_OOB) PollInfo.Events |= AFD_EVENT_OOB_RECEIVE; - - /* Set accept event */ - if (Events & FD_ACCEPT) PollInfo.Events |= AFD_EVENT_ACCEPT; - - /* Send Quality-of-Service (QOS) event */ - if (Events & FD_QOS) PollInfo.Events |= AFD_EVENT_QOS; - - /* Send Group Quality-of-Service (QOS) event */ - if (Events & FD_GROUP_QOS) PollInfo.Events |= AFD_EVENT_GROUP_QOS; - - /* Send connect event. Note, this also includes connect failures */ - if (Events & FD_CONNECT) PollInfo.Events |= AFD_EVENT_CONNECT | - AFD_EVENT_CONNECT_FAIL; - - /* Send close event. Note, this includes both aborts and disconnects */ - if (Events & FD_CLOSE) PollInfo.Events |= AFD_EVENT_DISCONNECT | - AFD_EVENT_ABORT; - - /* Send PnP events related to live network hardware changes */ - if (Events & FD_ROUTING_INTERFACE_CHANGE) - { - PollInfo.Events |= AFD_EVENT_ROUTING_INTERFACE_CHANGE; - } - if (Events & FD_ADDRESS_LIST_CHANGE) - { - PollInfo.Events |= AFD_EVENT_ADDRESS_LIST_CHANGE; - } - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_EVENT_SELECT, - &PollInfo, - sizeof(PollInfo), - NULL, - 0); - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion */ - SockWaitForSingleObject(ThreadData->EventHandle, - Socket->Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - LeaveCriticalSection(&Socket->Lock); - return NtStatusToSocketError(Status); - } - - /* Set Socket Data*/ - Socket->EventObject = EventObject; - Socket->NetworkEvents = Events; - - /* Release lock and return success */ - LeaveCriticalSection(&Socket->Lock); - return NO_ERROR; -} - -INT -WSPAPI -WSPEventSelect(SOCKET Handle, - WSAEVENT hEventObject, - LONG lNetworkEvents, - LPINT lpErrno) -{ - PSOCKET_INFORMATION Socket; - PWINSOCK_TEB_DATA ThreadData; - INT ErrorCode; - BOOLEAN BlockMode; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Set Socket to Non-Blocking */ - BlockMode = TRUE; - ErrorCode = SockSetInformation(Socket, - AFD_INFO_BLOCKING_MODE, - &BlockMode, - NULL, - NULL); - if (ErrorCode != NO_ERROR) goto error; - - /* AFD was notified, set it locally as well */ - Socket->SharedData.NonBlocking = TRUE; - - /* Check if there is an async select in progress */ - if (Socket->EventObject) - { - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* Erase all data */ - Socket->SharedData.hWnd = NULL; - Socket->SharedData.wMsg = 0; - Socket->SharedData.AsyncEvents = 0; - - /* Unbalance the sequence number so the request will fail */ - Socket->SharedData.SequenceNumber++; - - /* Give socket access back */ - LeaveCriticalSection(&Socket->Lock); - } - - /* Make sure the flags are valid */ - if ((lNetworkEvents & ~FD_ALL_EVENTS)) - { - /* More then the possible combination, fail */ - ErrorCode = WSAEINVAL; - goto error; - } - - /* Call the helper */ - ErrorCode = SockEventSelectHelper(Socket, hEventObject, lNetworkEvents); - -error: - /* Dereference the socket, if we have one here */ - if (Socket) SockDereferenceSocket(Socket); - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - -INT -WSPAPI -WSPEnumNetworkEvents(IN SOCKET Handle, - IN WSAEVENT hEventObject, - OUT LPWSANETWORKEVENTS lpNetworkEvents, - OUT LPINT lpErrno) -{ - AFD_ENUM_NETWORK_EVENTS_INFO EventInfo; - IO_STATUS_BLOCK IoStatusBlock; - PSOCKET_INFORMATION Socket; - PWINSOCK_TEB_DATA ThreadData; - INT ErrorCode; - NTSTATUS Status, EventStatus; - PSOCK_EVENT_MAPPING EventMapping; - ULONG i; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Make sure we got a pointer */ - if (!lpNetworkEvents) - { - /* Fail */ - ErrorCode = WSAEINVAL; - goto error; - } - - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* Send IOCTL */ - Status = NtDeviceIoControlFile((HANDLE)Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_ENUM_NETWORK_EVENTS, - hEventObject, - 0, - &EventInfo, - sizeof(EventInfo)); - - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion */ - SockWaitForSingleObject(ThreadData->EventHandle, - Socket->Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - - /* Set Events to wait for */ - lpNetworkEvents->lNetworkEvents = 0; - - /* Set our Event Mapping structure */ - EventMapping = PollEventMapping; - - /* Loop it */ - for (i = 0; i < (sizeof(PollEventMapping) / 2 * sizeof(ULONG)); i++) - { - /* First check if we have a match for this bit */ - if (EventInfo.PollEvents & (1 << EventMapping->AfdBit)) - { - /* Match found, write the equivalent bit */ - lpNetworkEvents->lNetworkEvents |= (1 << EventMapping->WinsockBit); - - /* Now get the status */ - EventStatus = EventInfo.EventStatus[EventMapping->AfdBit]; - - /* Check if it failed */ - if (!NT_SUCCESS(Status)) - { - /* Write the Winsock status code directly */ - lpNetworkEvents->iErrorCode[EventMapping->WinsockBit] = NtStatusToSocketError(EventStatus); - } - else - { - /* Write success */ - lpNetworkEvents->iErrorCode[EventMapping->WinsockBit] = NO_ERROR; - } - - /* Move to the next mapping array */ - EventMapping++; - } - - /* Handle the special cases with two flags. Start with connect */ - if (EventInfo.PollEvents & AFD_EVENT_CONNECT) - { - /* Set the equivalent bit */ - lpNetworkEvents->lNetworkEvents |= FD_CONNECT; - - /* Now get the status */ - EventStatus = EventInfo.EventStatus[AFD_EVENT_CONNECT_BIT]; - - /* Check if it failed */ - if (!NT_SUCCESS(Status)) - { - /* Write the Winsock status code directly */ - lpNetworkEvents->iErrorCode[FD_CONNECT_BIT] = NtStatusToSocketError(EventStatus); - } - else - { - /* Write success */ - lpNetworkEvents->iErrorCode[FD_CONNECT_BIT] = NO_ERROR; - } - } - else if (EventInfo.PollEvents & AFD_EVENT_CONNECT_FAIL) - { - /* Do the same thing, but for the failure */ - lpNetworkEvents->lNetworkEvents |= FD_CONNECT; - - /* Now get the status */ - EventStatus = EventInfo.EventStatus[AFD_EVENT_CONNECT_FAIL_BIT]; - - /* Check if it failed */ - if (!NT_SUCCESS(Status)) - { - /* Write the Winsock status code directly */ - lpNetworkEvents->iErrorCode[FD_CONNECT_BIT] = NtStatusToSocketError(EventStatus); - } - else - { - /* Write success */ - lpNetworkEvents->iErrorCode[FD_CONNECT_BIT] = NO_ERROR; - } - } - - /* Now handle Abort/Disconnect */ - if (EventInfo.PollEvents & AFD_EVENT_ABORT) - { - /* Set the equivalent bit */ - lpNetworkEvents->lNetworkEvents |= FD_CLOSE; - - /* Now get the status */ - EventStatus = EventInfo.EventStatus[AFD_EVENT_ABORT_BIT]; - - /* Check if it failed */ - if (!NT_SUCCESS(Status)) - { - /* Write the Winsock status code directly */ - lpNetworkEvents->iErrorCode[FD_CLOSE_BIT] = NtStatusToSocketError(EventStatus); - } - else - { - /* Write success */ - lpNetworkEvents->iErrorCode[FD_CLOSE_BIT] = NO_ERROR; - } - } - else if (EventInfo.PollEvents & AFD_EVENT_DISCONNECT) - { - /* Do the same thing, but for the failure */ - lpNetworkEvents->lNetworkEvents |= FD_CLOSE; - - /* Now get the status */ - EventStatus = EventInfo.EventStatus[AFD_EVENT_DISCONNECT_BIT]; - - /* Check if it failed */ - if (!NT_SUCCESS(Status)) - { - /* Write the Winsock status code directly */ - lpNetworkEvents->iErrorCode[FD_CLOSE_BIT] = NtStatusToSocketError(EventStatus); - } - else - { - /* Write success */ - lpNetworkEvents->iErrorCode[FD_CLOSE_BIT] = NO_ERROR; - } - } - } - -error: - /* Dereference the socket, if we have one here */ - if (Socket) SockDereferenceSocket(Socket); - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -typedef struct _SOCK_EVENT_MAPPING -{ - ULONG AfdBit; - ULONG WinsockBit; -} SOCK_EVENT_MAPPING, *PSOCK_EVENT_MAPPING; - -SOCK_EVENT_MAPPING PollEventMapping[] = - { - {AFD_EVENT_RECEIVE_BIT, FD_READ_BIT}, - {AFD_EVENT_SEND_BIT, FD_WRITE_BIT}, - {AFD_EVENT_OOB_RECEIVE_BIT, FD_OOB_BIT}, - {AFD_EVENT_ACCEPT_BIT, FD_ACCEPT_BIT}, - {AFD_EVENT_QOS_BIT, FD_QOS_BIT}, - {AFD_EVENT_GROUP_QOS_BIT, FD_GROUP_QOS_BIT}, - {AFD_EVENT_ROUTING_INTERFACE_CHANGE_BIT, FD_ROUTING_INTERFACE_CHANGE_BIT}, - {AFD_EVENT_ADDRESS_LIST_CHANGE_BIT, FD_ADDRESS_LIST_CHANGE_BIT} -}; - -/* FUNCTIONS *****************************************************************/ - -INT -WSPAPI -SockEventSelectHelper(IN PSOCKET_INFORMATION Socket, - IN WSAEVENT EventObject, - IN LONG Events) -{ - IO_STATUS_BLOCK IoStatusBlock; - AFD_EVENT_SELECT_INFO PollInfo; - NTSTATUS Status; - PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; - - /* Acquire the lock */ - EnterCriticalSection(&Socket->Lock); - - /* Set Structure Info */ - PollInfo.EventObject = EventObject; - PollInfo.Events = 0; - - /* Set receive event */ - if (Events & FD_READ) PollInfo.Events |= AFD_EVENT_RECEIVE; - - /* Set write event */ - if (Events & FD_WRITE) PollInfo.Events |= AFD_EVENT_SEND; - - /* Set out-of-band (OOB) receive event */ - if (Events & FD_OOB) PollInfo.Events |= AFD_EVENT_OOB_RECEIVE; - - /* Set accept event */ - if (Events & FD_ACCEPT) PollInfo.Events |= AFD_EVENT_ACCEPT; - - /* Send Quality-of-Service (QOS) event */ - if (Events & FD_QOS) PollInfo.Events |= AFD_EVENT_QOS; - - /* Send Group Quality-of-Service (QOS) event */ - if (Events & FD_GROUP_QOS) PollInfo.Events |= AFD_EVENT_GROUP_QOS; - - /* Send connect event. Note, this also includes connect failures */ - if (Events & FD_CONNECT) PollInfo.Events |= AFD_EVENT_CONNECT | - AFD_EVENT_CONNECT_FAIL; - - /* Send close event. Note, this includes both aborts and disconnects */ - if (Events & FD_CLOSE) PollInfo.Events |= AFD_EVENT_DISCONNECT | - AFD_EVENT_ABORT; - - /* Send PnP events related to live network hardware changes */ - if (Events & FD_ROUTING_INTERFACE_CHANGE) - { - PollInfo.Events |= AFD_EVENT_ROUTING_INTERFACE_CHANGE; - } - if (Events & FD_ADDRESS_LIST_CHANGE) - { - PollInfo.Events |= AFD_EVENT_ADDRESS_LIST_CHANGE; - } - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_EVENT_SELECT, - &PollInfo, - sizeof(PollInfo), - NULL, - 0); - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion */ - SockWaitForSingleObject(ThreadData->EventHandle, - Socket->Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - LeaveCriticalSection(&Socket->Lock); - return NtStatusToSocketError(Status); - } - - /* Set Socket Data*/ - Socket->EventObject = EventObject; - Socket->NetworkEvents = Events; - - /* Release lock and return success */ - LeaveCriticalSection(&Socket->Lock); - return NO_ERROR; -} - -INT -WSPAPI -WSPEventSelect(SOCKET Handle, - WSAEVENT hEventObject, - LONG lNetworkEvents, - LPINT lpErrno) -{ - PSOCKET_INFORMATION Socket; - PWINSOCK_TEB_DATA ThreadData; - INT ErrorCode; - BOOLEAN BlockMode; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Set Socket to Non-Blocking */ - BlockMode = TRUE; - ErrorCode = SockSetInformation(Socket, - AFD_INFO_BLOCKING_MODE, - &BlockMode, - NULL, - NULL); - if (ErrorCode != NO_ERROR) goto error; - - /* AFD was notified, set it locally as well */ - Socket->SharedData.NonBlocking = TRUE; - - /* Check if there is an async select in progress */ - if (Socket->EventObject) - { - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* Erase all data */ - Socket->SharedData.hWnd = NULL; - Socket->SharedData.wMsg = 0; - Socket->SharedData.AsyncEvents = 0; - - /* Unbalance the sequence number so the request will fail */ - Socket->SharedData.SequenceNumber++; - - /* Give socket access back */ - LeaveCriticalSection(&Socket->Lock); - } - - /* Make sure the flags are valid */ - if ((lNetworkEvents & ~FD_ALL_EVENTS)) - { - /* More then the possible combination, fail */ - ErrorCode = WSAEINVAL; - goto error; - } - - /* Call the helper */ - ErrorCode = SockEventSelectHelper(Socket, hEventObject, lNetworkEvents); - -error: - /* Dereference the socket, if we have one here */ - if (Socket) SockDereferenceSocket(Socket); - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - -INT -WSPAPI -WSPEnumNetworkEvents(IN SOCKET Handle, - IN WSAEVENT hEventObject, - OUT LPWSANETWORKEVENTS lpNetworkEvents, - OUT LPINT lpErrno) -{ - AFD_ENUM_NETWORK_EVENTS_INFO EventInfo; - IO_STATUS_BLOCK IoStatusBlock; - PSOCKET_INFORMATION Socket; - PWINSOCK_TEB_DATA ThreadData; - INT ErrorCode; - NTSTATUS Status, EventStatus; - PSOCK_EVENT_MAPPING EventMapping; - ULONG i; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Make sure we got a pointer */ - if (!lpNetworkEvents) - { - /* Fail */ - ErrorCode = WSAEINVAL; - goto error; - } - - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* Send IOCTL */ - Status = NtDeviceIoControlFile((HANDLE)Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_ENUM_NETWORK_EVENTS, - hEventObject, - 0, - &EventInfo, - sizeof(EventInfo)); - - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion */ - SockWaitForSingleObject(ThreadData->EventHandle, - Socket->Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - - /* Set Events to wait for */ - lpNetworkEvents->lNetworkEvents = 0; - - /* Set our Event Mapping structure */ - EventMapping = PollEventMapping; - - /* Loop it */ - for (i = 0; i < (sizeof(PollEventMapping) / 2 * sizeof(ULONG)); i++) - { - /* First check if we have a match for this bit */ - if (EventInfo.PollEvents & (1 << EventMapping->AfdBit)) - { - /* Match found, write the equivalent bit */ - lpNetworkEvents->lNetworkEvents |= (1 << EventMapping->WinsockBit); - - /* Now get the status */ - EventStatus = EventInfo.EventStatus[EventMapping->AfdBit]; - - /* Check if it failed */ - if (!NT_SUCCESS(Status)) - { - /* Write the Winsock status code directly */ - lpNetworkEvents->iErrorCode[EventMapping->WinsockBit] = NtStatusToSocketError(EventStatus); - } - else - { - /* Write success */ - lpNetworkEvents->iErrorCode[EventMapping->WinsockBit] = NO_ERROR; - } - - /* Move to the next mapping array */ - EventMapping++; - } - - /* Handle the special cases with two flags. Start with connect */ - if (EventInfo.PollEvents & AFD_EVENT_CONNECT) - { - /* Set the equivalent bit */ - lpNetworkEvents->lNetworkEvents |= FD_CONNECT; - - /* Now get the status */ - EventStatus = EventInfo.EventStatus[AFD_EVENT_CONNECT_BIT]; - - /* Check if it failed */ - if (!NT_SUCCESS(Status)) - { - /* Write the Winsock status code directly */ - lpNetworkEvents->iErrorCode[FD_CONNECT_BIT] = NtStatusToSocketError(EventStatus); - } - else - { - /* Write success */ - lpNetworkEvents->iErrorCode[FD_CONNECT_BIT] = NO_ERROR; - } - } - else if (EventInfo.PollEvents & AFD_EVENT_CONNECT_FAIL) - { - /* Do the same thing, but for the failure */ - lpNetworkEvents->lNetworkEvents |= FD_CONNECT; - - /* Now get the status */ - EventStatus = EventInfo.EventStatus[AFD_EVENT_CONNECT_FAIL_BIT]; - - /* Check if it failed */ - if (!NT_SUCCESS(Status)) - { - /* Write the Winsock status code directly */ - lpNetworkEvents->iErrorCode[FD_CONNECT_BIT] = NtStatusToSocketError(EventStatus); - } - else - { - /* Write success */ - lpNetworkEvents->iErrorCode[FD_CONNECT_BIT] = NO_ERROR; - } - } - - /* Now handle Abort/Disconnect */ - if (EventInfo.PollEvents & AFD_EVENT_ABORT) - { - /* Set the equivalent bit */ - lpNetworkEvents->lNetworkEvents |= FD_CLOSE; - - /* Now get the status */ - EventStatus = EventInfo.EventStatus[AFD_EVENT_ABORT_BIT]; - - /* Check if it failed */ - if (!NT_SUCCESS(Status)) - { - /* Write the Winsock status code directly */ - lpNetworkEvents->iErrorCode[FD_CLOSE_BIT] = NtStatusToSocketError(EventStatus); - } - else - { - /* Write success */ - lpNetworkEvents->iErrorCode[FD_CLOSE_BIT] = NO_ERROR; - } - } - else if (EventInfo.PollEvents & AFD_EVENT_DISCONNECT) - { - /* Do the same thing, but for the failure */ - lpNetworkEvents->lNetworkEvents |= FD_CLOSE; - - /* Now get the status */ - EventStatus = EventInfo.EventStatus[AFD_EVENT_DISCONNECT_BIT]; - - /* Check if it failed */ - if (!NT_SUCCESS(Status)) - { - /* Write the Winsock status code directly */ - lpNetworkEvents->iErrorCode[FD_CLOSE_BIT] = NtStatusToSocketError(EventStatus); - } - else - { - /* Write success */ - lpNetworkEvents->iErrorCode[FD_CLOSE_BIT] = NO_ERROR; - } - } - } - -error: - /* Dereference the socket, if we have one here */ - if (Socket) SockDereferenceSocket(Socket); - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - diff --git a/dll/win32/mswsock/msafd/getname.c b/dll/win32/mswsock/msafd/getname.c index 8cbaed96e5d..873b396f0a2 100644 --- a/dll/win32/mswsock/msafd/getname.c +++ b/dll/win32/mswsock/msafd/getname.c @@ -243,738 +243,3 @@ error: return NO_ERROR; } -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -INT -WSPAPI -WSPGetSockName(IN SOCKET Handle, - OUT LPSOCKADDR Name, - IN OUT LPINT NameLength, - OUT LPINT lpErrno) -{ - IO_STATUS_BLOCK IoStatusBlock; - ULONG TdiAddressSize; - INT ErrorCode; - PTDI_ADDRESS_INFO TdiAddress = NULL; - PSOCKET_INFORMATION Socket; - NTSTATUS Status; - PWINSOCK_TEB_DATA ThreadData; - CHAR AddressBuffer[FIELD_OFFSET(TDI_ADDRESS_INFO, Address) + - MAX_TDI_ADDRESS_LENGTH]; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* If the socket isn't bound, fail */ - if (Socket->SharedData.State == SocketOpen) - { - /* Fail */ - ErrorCode = WSAEINVAL; - goto error; - } - - /* Check how long the TDI Address is */ - TdiAddressSize = FIELD_OFFSET(TDI_ADDRESS_INFO, Address) + - Socket->HelperData->MaxTDIAddressLength; - - /* See if it can fit in the stack */ - if (TdiAddressSize <= sizeof(AddressBuffer)) - { - /* Use the stack */ - TdiAddress = (PVOID)AddressBuffer; - } - else - { - /* Allocate from heap */ - TdiAddress = SockAllocateHeapRoutine(SockPrivateHeap, 0, TdiAddressSize); - if (!TdiAddress) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - } - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_GET_SOCK_NAME, - NULL, - 0, - TdiAddress, - TdiAddressSize); - - /* Check if it's pending */ - if (Status == STATUS_PENDING) - { - /* Wait for completion */ - LeaveCriticalSection(&Socket->Lock); - SockWaitForSingleObject(ThreadData->EventHandle, - Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - EnterCriticalSection(&Socket->Lock); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - - /* Convert to Sockaddr format */ - SockBuildSockaddr(Socket->LocalAddress, - &Socket->SharedData.SizeOfLocalAddress, - &TdiAddress->Address); - - /* Check for valid length */ - if (Socket->SharedData.SizeOfLocalAddress > *NameLength) - { - /* Fail */ - ErrorCode = WSAEFAULT; - goto error; - } - - /* Write the Address */ - RtlCopyMemory(Name, - Socket->LocalAddress, - Socket->SharedData.SizeOfLocalAddress); - - /* Return the Name Length */ - *NameLength = Socket->SharedData.SizeOfLocalAddress; - -error: - - /* Check if we have a socket here */ - if (Socket) - { - /* Release the lock and dereference */ - LeaveCriticalSection(&Socket->Lock); - SockDereferenceSocket(Socket); - } - - /* Check if we should free the TDI address */ - if ((TdiAddress) && (TdiAddress != (PVOID)AddressBuffer)) - { - /* Free the Buffer */ - RtlFreeHeap(SockPrivateHeap, 0, TdiAddress); - } - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - -INT -WSPAPI -WSPGetPeerName(IN SOCKET Handle, - OUT LPSOCKADDR Name, - IN OUT LPINT NameLength, - OUT LPINT lpErrno) -{ - INT ErrorCode; - PSOCKET_INFORMATION Socket; - PWINSOCK_TEB_DATA ThreadData; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* If the socket isn't connected, then fail */ - if (!(SockIsSocketConnected(Socket)) && !(Socket->AsyncData)) - { - /* Fail */ - ErrorCode = WSAENOTCONN; - goto error; - } - - /* Check for valid length */ - if (Socket->SharedData.SizeOfRemoteAddress > *NameLength) - { - /* Fail */ - ErrorCode = WSAEFAULT; - goto error; - } - - /* Write the Address */ - RtlCopyMemory(Name, - Socket->RemoteAddress, - Socket->SharedData.SizeOfRemoteAddress); - - /* Return the Name Length */ - *NameLength = Socket->SharedData.SizeOfRemoteAddress; - -error: - - /* Check if we have a socket here */ - if (Socket) - { - /* Release the lock and dereference */ - LeaveCriticalSection(&Socket->Lock); - SockDereferenceSocket(Socket); - } - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -INT -WSPAPI -WSPGetSockName(IN SOCKET Handle, - OUT LPSOCKADDR Name, - IN OUT LPINT NameLength, - OUT LPINT lpErrno) -{ - IO_STATUS_BLOCK IoStatusBlock; - ULONG TdiAddressSize; - INT ErrorCode; - PTDI_ADDRESS_INFO TdiAddress = NULL; - PSOCKET_INFORMATION Socket; - NTSTATUS Status; - PWINSOCK_TEB_DATA ThreadData; - CHAR AddressBuffer[FIELD_OFFSET(TDI_ADDRESS_INFO, Address) + - MAX_TDI_ADDRESS_LENGTH]; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* If the socket isn't bound, fail */ - if (Socket->SharedData.State == SocketOpen) - { - /* Fail */ - ErrorCode = WSAEINVAL; - goto error; - } - - /* Check how long the TDI Address is */ - TdiAddressSize = FIELD_OFFSET(TDI_ADDRESS_INFO, Address) + - Socket->HelperData->MaxTDIAddressLength; - - /* See if it can fit in the stack */ - if (TdiAddressSize <= sizeof(AddressBuffer)) - { - /* Use the stack */ - TdiAddress = (PVOID)AddressBuffer; - } - else - { - /* Allocate from heap */ - TdiAddress = SockAllocateHeapRoutine(SockPrivateHeap, 0, TdiAddressSize); - if (!TdiAddress) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - } - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_GET_SOCK_NAME, - NULL, - 0, - TdiAddress, - TdiAddressSize); - - /* Check if it's pending */ - if (Status == STATUS_PENDING) - { - /* Wait for completion */ - LeaveCriticalSection(&Socket->Lock); - SockWaitForSingleObject(ThreadData->EventHandle, - Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - EnterCriticalSection(&Socket->Lock); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - - /* Convert to Sockaddr format */ - SockBuildSockaddr(Socket->LocalAddress, - &Socket->SharedData.SizeOfLocalAddress, - &TdiAddress->Address); - - /* Check for valid length */ - if (Socket->SharedData.SizeOfLocalAddress > *NameLength) - { - /* Fail */ - ErrorCode = WSAEFAULT; - goto error; - } - - /* Write the Address */ - RtlCopyMemory(Name, - Socket->LocalAddress, - Socket->SharedData.SizeOfLocalAddress); - - /* Return the Name Length */ - *NameLength = Socket->SharedData.SizeOfLocalAddress; - -error: - - /* Check if we have a socket here */ - if (Socket) - { - /* Release the lock and dereference */ - LeaveCriticalSection(&Socket->Lock); - SockDereferenceSocket(Socket); - } - - /* Check if we should free the TDI address */ - if ((TdiAddress) && (TdiAddress != (PVOID)AddressBuffer)) - { - /* Free the Buffer */ - RtlFreeHeap(SockPrivateHeap, 0, TdiAddress); - } - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - -INT -WSPAPI -WSPGetPeerName(IN SOCKET Handle, - OUT LPSOCKADDR Name, - IN OUT LPINT NameLength, - OUT LPINT lpErrno) -{ - INT ErrorCode; - PSOCKET_INFORMATION Socket; - PWINSOCK_TEB_DATA ThreadData; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* If the socket isn't connected, then fail */ - if (!(SockIsSocketConnected(Socket)) && !(Socket->AsyncData)) - { - /* Fail */ - ErrorCode = WSAENOTCONN; - goto error; - } - - /* Check for valid length */ - if (Socket->SharedData.SizeOfRemoteAddress > *NameLength) - { - /* Fail */ - ErrorCode = WSAEFAULT; - goto error; - } - - /* Write the Address */ - RtlCopyMemory(Name, - Socket->RemoteAddress, - Socket->SharedData.SizeOfRemoteAddress); - - /* Return the Name Length */ - *NameLength = Socket->SharedData.SizeOfRemoteAddress; - -error: - - /* Check if we have a socket here */ - if (Socket) - { - /* Release the lock and dereference */ - LeaveCriticalSection(&Socket->Lock); - SockDereferenceSocket(Socket); - } - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -INT -WSPAPI -WSPGetSockName(IN SOCKET Handle, - OUT LPSOCKADDR Name, - IN OUT LPINT NameLength, - OUT LPINT lpErrno) -{ - IO_STATUS_BLOCK IoStatusBlock; - ULONG TdiAddressSize; - INT ErrorCode; - PTDI_ADDRESS_INFO TdiAddress = NULL; - PSOCKET_INFORMATION Socket; - NTSTATUS Status; - PWINSOCK_TEB_DATA ThreadData; - CHAR AddressBuffer[FIELD_OFFSET(TDI_ADDRESS_INFO, Address) + - MAX_TDI_ADDRESS_LENGTH]; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* If the socket isn't bound, fail */ - if (Socket->SharedData.State == SocketOpen) - { - /* Fail */ - ErrorCode = WSAEINVAL; - goto error; - } - - /* Check how long the TDI Address is */ - TdiAddressSize = FIELD_OFFSET(TDI_ADDRESS_INFO, Address) + - Socket->HelperData->MaxTDIAddressLength; - - /* See if it can fit in the stack */ - if (TdiAddressSize <= sizeof(AddressBuffer)) - { - /* Use the stack */ - TdiAddress = (PVOID)AddressBuffer; - } - else - { - /* Allocate from heap */ - TdiAddress = SockAllocateHeapRoutine(SockPrivateHeap, 0, TdiAddressSize); - if (!TdiAddress) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - } - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_GET_SOCK_NAME, - NULL, - 0, - TdiAddress, - TdiAddressSize); - - /* Check if it's pending */ - if (Status == STATUS_PENDING) - { - /* Wait for completion */ - LeaveCriticalSection(&Socket->Lock); - SockWaitForSingleObject(ThreadData->EventHandle, - Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - EnterCriticalSection(&Socket->Lock); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - - /* Convert to Sockaddr format */ - SockBuildSockaddr(Socket->LocalAddress, - &Socket->SharedData.SizeOfLocalAddress, - &TdiAddress->Address); - - /* Check for valid length */ - if (Socket->SharedData.SizeOfLocalAddress > *NameLength) - { - /* Fail */ - ErrorCode = WSAEFAULT; - goto error; - } - - /* Write the Address */ - RtlCopyMemory(Name, - Socket->LocalAddress, - Socket->SharedData.SizeOfLocalAddress); - - /* Return the Name Length */ - *NameLength = Socket->SharedData.SizeOfLocalAddress; - -error: - - /* Check if we have a socket here */ - if (Socket) - { - /* Release the lock and dereference */ - LeaveCriticalSection(&Socket->Lock); - SockDereferenceSocket(Socket); - } - - /* Check if we should free the TDI address */ - if ((TdiAddress) && (TdiAddress != (PVOID)AddressBuffer)) - { - /* Free the Buffer */ - RtlFreeHeap(SockPrivateHeap, 0, TdiAddress); - } - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - -INT -WSPAPI -WSPGetPeerName(IN SOCKET Handle, - OUT LPSOCKADDR Name, - IN OUT LPINT NameLength, - OUT LPINT lpErrno) -{ - INT ErrorCode; - PSOCKET_INFORMATION Socket; - PWINSOCK_TEB_DATA ThreadData; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* If the socket isn't connected, then fail */ - if (!(SockIsSocketConnected(Socket)) && !(Socket->AsyncData)) - { - /* Fail */ - ErrorCode = WSAENOTCONN; - goto error; - } - - /* Check for valid length */ - if (Socket->SharedData.SizeOfRemoteAddress > *NameLength) - { - /* Fail */ - ErrorCode = WSAEFAULT; - goto error; - } - - /* Write the Address */ - RtlCopyMemory(Name, - Socket->RemoteAddress, - Socket->SharedData.SizeOfRemoteAddress); - - /* Return the Name Length */ - *NameLength = Socket->SharedData.SizeOfRemoteAddress; - -error: - - /* Check if we have a socket here */ - if (Socket) - { - /* Release the lock and dereference */ - LeaveCriticalSection(&Socket->Lock); - SockDereferenceSocket(Socket); - } - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - diff --git a/dll/win32/mswsock/msafd/helper.c b/dll/win32/mswsock/msafd/helper.c index e506d24937f..de166b4a806 100644 --- a/dll/win32/mswsock/msafd/helper.c +++ b/dll/win32/mswsock/msafd/helper.c @@ -693,2088 +693,3 @@ SockNotifyHelperDll(IN PSOCKET_INFORMATION Socket, Event); } -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -LIST_ENTRY SockHelperDllListHead; - -/* FUNCTIONS *****************************************************************/ - -VOID -WSPAPI -SockFreeHelperDll(IN PHELPER_DATA Helper) -{ - /* Free the DLL */ - FreeLibrary(Helper->hInstance); - - /* Free the mapping */ - RtlFreeHeap(SockPrivateHeap, 0, Helper->Mapping); - - /* Free the DLL Structure itself */ - RtlFreeHeap(SockPrivateHeap, 0, Helper); -} - -INT -WSPAPI -SockGetTdiName(PINT AddressFamily, - PINT SocketType, - PINT Protocol, - LPGUID ProviderId, - GROUP Group, - DWORD Flags, - PUNICODE_STRING TransportName, - PVOID *HelperDllContext, - PHELPER_DATA *HelperDllData, - PDWORD Events) -{ - PHELPER_DATA HelperData; - PWSTR Transports; - PWSTR Transport; - PWINSOCK_MAPPING Mapping; - PLIST_ENTRY Helpers; - BOOLEAN SharedLock = TRUE; - INT ErrorCode; - BOOLEAN AfMatch = FALSE, ProtoMatch = FALSE, SocketMatch = FALSE; - - /* Acquire global lock */ - SockAcquireRwLockShared(&SocketGlobalLock); - -TryAgain: - /* Check in our Current Loaded Helpers */ - for (Helpers = SockHelperDllListHead.Flink; - Helpers != &SockHelperDllListHead; - Helpers = Helpers->Flink) - { - /* Get the current helper */ - HelperData = CONTAINING_RECORD(Helpers, HELPER_DATA, Helpers); - - /* See if this Mapping works for us */ - if (SockIsTripleInMapping(HelperData->Mapping, - *AddressFamily, - &AfMatch, - *SocketType, - &SocketMatch, - *Protocol, - &ProtoMatch)) - { - /* Call the Helper Dll function get the Transport Name */ - if (!HelperData->WSHOpenSocket2) - { - if (!(Flags & WSA_FLAG_MULTIPOINT_ALL)) - { - /* DLL Doesn't support WSHOpenSocket2, call the old one */ - ErrorCode = HelperData->WSHOpenSocket(AddressFamily, - SocketType, - Protocol, - TransportName, - HelperDllContext, - Events); - } - else - { - /* Invalid flag */ - ErrorCode = WSAEINVAL; - } - } - else - { - /* Call the new WSHOpenSocket */ - ErrorCode = HelperData->WSHOpenSocket2(AddressFamily, - SocketType, - Protocol, - Group, - Flags, - TransportName, - HelperDllContext, - Events); - } - - /* Check for success */ - if (ErrorCode == NO_ERROR) - { - /* Reference the helper */ - InterlockedIncrement(&HelperData->RefCount); - - /* Check which lock we acquired */ - if (SharedLock) - { - /* Release the shared lock */ - SockReleaseRwLockShared(&SocketGlobalLock); - } - else - { - /* Release the acquired lock */ - SockReleaseRwLockExclusive(&SocketGlobalLock); - } - - /* Return the Helper Pointers */ - *HelperDllData = HelperData; - return NO_ERROR; - } - - /* Check if we don't need a transport name */ - if ((*SocketType == SOCK_RAW) && (TransportName->Buffer)) - { - /* Free it */ - RtlFreeHeap(RtlGetProcessHeap(), 0, TransportName->Buffer); - TransportName->Buffer = NULL; - } - } - } - - /* We didn't find a match: try again with RW access */ - if (SharedLock) - { - /* Switch locks */ - SockReleaseRwLockShared(&SocketGlobalLock); - SockAcquireRwLockExclusive(&SocketGlobalLock); - - /* Parse the list again */ - SharedLock = FALSE; - goto TryAgain; - } - - /* Get the Transports available */ - ErrorCode = SockLoadTransportList(&Transports); - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - SockReleaseRwLockExclusive(&SocketGlobalLock); - return ErrorCode; - } - - /* Loop through each transport until we find one that can satisfy us */ - for (Transport = Transports; *Transport; Transport += wcslen(Transport) + 1) - { - /* See what mapping this Transport supports */ - ErrorCode = SockLoadTransportMapping(Transport, &Mapping); - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Try the next one */ - continue; - } - - /* See if this Mapping works for us */ - if (SockIsTripleInMapping(Mapping, - *AddressFamily, - &AfMatch, - *SocketType, - &SocketMatch, - *Protocol, - &ProtoMatch)) - { - /* It does, so load the DLL associated with it */ - ErrorCode = SockLoadHelperDll(Transport, Mapping, &HelperData); - - /* Check for success */ - if (ErrorCode == NO_ERROR) - { - /* Call the Helper Dll function get the Transport Name */ - if (!HelperData->WSHOpenSocket2) - { - /* Check for invalid flag combo */ - if (!(Flags & WSA_FLAG_MULTIPOINT_ALL)) - { - /* DLL Doesn't support WSHOpenSocket2, call the old one */ - ErrorCode = HelperData->WSHOpenSocket(AddressFamily, - SocketType, - Protocol, - TransportName, - HelperDllContext, - Events); - } - else - { - /* Fail */ - ErrorCode = WSAEINVAL; - } - } - else - { - /* Call the newer function */ - ErrorCode = HelperData->WSHOpenSocket2(AddressFamily, - SocketType, - Protocol, - Group, - Flags, - TransportName, - HelperDllContext, - Events); - } - - /* Check for success */ - if (ErrorCode == NO_ERROR) - { - /* Reference the helper */ - InterlockedIncrement(&HelperData->RefCount); - - /* Release the lock and free the transports */ - SockReleaseRwLockExclusive(&SocketGlobalLock); - RtlFreeHeap(SockPrivateHeap, 0, Transports); - - /* Return the Helper Pointer */ - *HelperDllData = HelperData; - return NO_ERROR; - } - - /* Check if we don't need a transport name */ - if ((*SocketType == SOCK_RAW) && (TransportName->Buffer)) - { - /* Free it */ - RtlFreeHeap(RtlGetProcessHeap(), 0, TransportName->Buffer); - TransportName->Buffer = NULL; - } - - /* Try again */ - continue; - } - } - - /* Free the mapping and continue */ - RtlFreeHeap(SockPrivateHeap, 0, Mapping); - } - - /* Release the lock and free the transport list */ - SockReleaseRwLockExclusive(&SocketGlobalLock); - RtlFreeHeap(SockPrivateHeap, 0, Transports); - - /* Check why we didn't find a match */ - if (!AfMatch) return WSAEAFNOSUPPORT; - if (!ProtoMatch) return WSAEPROTONOSUPPORT; - if (!SocketMatch) return WSAESOCKTNOSUPPORT; - - /* The comination itself was invalid */ - return WSAEINVAL; -} - -INT -WSPAPI -SockLoadTransportMapping(IN PWSTR TransportName, - OUT PWINSOCK_MAPPING *Mapping) -{ - PWSTR TransportKey; - HKEY KeyHandle; - INT ErrorCode; - ULONG MappingSize = 0; - - /* Allocate a Buffer */ - TransportKey = SockAllocateHeapRoutine(SockPrivateHeap, - 0, - MAX_PATH * sizeof(WCHAR)); - /* Check for error */ - if (!TransportKey) return ERROR_NOT_ENOUGH_MEMORY; - - /* Generate the right key name */ - wcscpy(TransportKey, L"System\\CurrentControlSet\\Services\\"); - wcscat(TransportKey, TransportName); - wcscat(TransportKey, L"\\Parameters\\Winsock"); - - /* Open the Key */ - ErrorCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE, - TransportKey, - 0, - KEY_READ, - &KeyHandle); - - /* We don't need the Transport Key anymore */ - RtlFreeHeap(SockPrivateHeap, 0, TransportKey); - - /* Check for error */ - if ((ErrorCode != ERROR_MORE_DATA) && (ErrorCode != NO_ERROR)) - { - /* Close key and fail */ - RegCloseKey(KeyHandle); - return ErrorCode; - } - - /* Find out how much space we need for the Mapping */ - ErrorCode = RegQueryValueExW(KeyHandle, - L"Mapping", - NULL, - NULL, - NULL, - &MappingSize); - - /* Check for error */ - if ((ErrorCode != ERROR_MORE_DATA) && (ErrorCode != NO_ERROR)) - { - /* Close key and fail */ - RegCloseKey(KeyHandle); - return ErrorCode; - } - - /* Allocate Memory for the Mapping */ - *Mapping = SockAllocateHeapRoutine(SockPrivateHeap, 0, MappingSize); - - /* Check for error */ - if (!(*Mapping)) - { - /* Close key and fail */ - RegCloseKey(KeyHandle); - return ERROR_NOT_ENOUGH_MEMORY; - } - - /* Read the Mapping */ - ErrorCode = RegQueryValueExW(KeyHandle, - L"Mapping", - NULL, - NULL, - (LPBYTE)*Mapping, - &MappingSize); - - /* Check for error */ - if ((ErrorCode != ERROR_MORE_DATA) && (ErrorCode != NO_ERROR)) - { - /* Close key and fail */ - RegCloseKey(KeyHandle); - return ErrorCode; - } - - /* Close key and return */ - RegCloseKey(KeyHandle); - return NO_ERROR; -} - -INT -WSPAPI -SockLoadHelperDll(PWSTR TransportName, - PWINSOCK_MAPPING Mapping, - PHELPER_DATA *HelperDllData) -{ - PHELPER_DATA HelperData; - PWSTR HelperDllName; - PWSTR FullHelperDllName; - ULONG HelperDllNameSize; - PWSTR HelperKey; - HKEY KeyHandle; - ULONG DataSize; - INT ErrorCode; - PLIST_ENTRY Entry; - - /* Allocate space for the Helper Structure and TransportName */ - HelperData = SockAllocateHeapRoutine(SockPrivateHeap, - 0, - sizeof(*HelperData) + - (DWORD)(wcslen(TransportName) + 1) * - sizeof(WCHAR)); - - /* Check for error */ - if (!HelperData) return ERROR_NOT_ENOUGH_MEMORY; - - /* Allocate Space for the Helper DLL Key */ - HelperKey = SockAllocateHeapRoutine(SockPrivateHeap, - 0, - MAX_PATH * sizeof(WCHAR)); - - /* Check for error */ - if (!HelperKey) - { - RtlFreeHeap(SockPrivateHeap, 0, HelperData); - return ERROR_NOT_ENOUGH_MEMORY; - } - - /* Generate the right key name */ - wcscpy(HelperKey, L"System\\CurrentControlSet\\Services\\"); - wcscat(HelperKey, TransportName); - wcscat(HelperKey, L"\\Parameters\\Winsock"); - - /* Open the Key */ - ErrorCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE, - HelperKey, - 0, - KEY_READ, - &KeyHandle); - - /* Free Buffer */ - RtlFreeHeap(SockPrivateHeap, 0, HelperKey); - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Free the helper data and fail */ - RtlFreeHeap(SockPrivateHeap, 0, HelperData); - RegCloseKey(KeyHandle); - return ErrorCode; - } - - /* Read Minimum size of Sockaddr Structures */ - DataSize = sizeof(HelperData->MinWSAddressLength); - RegQueryValueExW(KeyHandle, - L"MinSockaddrLength", - NULL, - NULL, - (LPBYTE)&HelperData->MinWSAddressLength, - &DataSize); - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Free the helper data and fail */ - RtlFreeHeap(SockPrivateHeap, 0, HelperData); - RegCloseKey(KeyHandle); - return ErrorCode; - } - - /* Read Maximum size of Sockaddr Structures */ - DataSize = sizeof(HelperData->MinWSAddressLength); - RegQueryValueExW(KeyHandle, - L"MaxSockaddrLength", - NULL, - NULL, - (LPBYTE)&HelperData->MaxWSAddressLength, - &DataSize); - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Free the helper data and fail */ - RtlFreeHeap(SockPrivateHeap, 0, HelperData); - RegCloseKey(KeyHandle); - return ErrorCode; - } - - /* Size of TDI Structures */ - HelperData->MinTDIAddressLength = HelperData->MinWSAddressLength + 6; - HelperData->MaxTDIAddressLength = HelperData->MaxWSAddressLength + 6; - - /* Read Delayed Acceptance Setting */ - DataSize = sizeof(DWORD); - ErrorCode = RegQueryValueExW(KeyHandle, - L"UseDelayedAcceptance", - NULL, - NULL, - (LPBYTE)&HelperData->UseDelayedAcceptance, - &DataSize); - - /* Use defalt if we failed */ - if (ErrorCode != NO_ERROR) HelperData->UseDelayedAcceptance = -1; - - /* Allocate Space for the Helper DLL Names */ - HelperDllName = SockAllocateHeapRoutine(SockPrivateHeap, - 0, - MAX_PATH * sizeof(WCHAR)); - - /* Check for error */ - if (!HelperDllName) - { - /* Free the helper data and fail */ - RtlFreeHeap(SockPrivateHeap, 0, HelperData); - RegCloseKey(KeyHandle); - return ErrorCode; - } - - /* Allocate space for the expanded version */ - FullHelperDllName = SockAllocateHeapRoutine(SockPrivateHeap, - 0, - MAX_PATH * sizeof(WCHAR)); - - /* Check for error */ - if (!FullHelperDllName) - { - /* Free the helper data and fail */ - RtlFreeHeap(SockPrivateHeap, 0, HelperData); - RtlFreeHeap(SockPrivateHeap, 0, HelperDllName); - RegCloseKey(KeyHandle); - return ErrorCode; - } - - /* Get the name of the Helper DLL*/ - DataSize = 512; - ErrorCode = RegQueryValueExW(KeyHandle, - L"HelperDllName", - NULL, - NULL, - (LPBYTE)HelperDllName, - &DataSize); - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Free the helper data and fail */ - RtlFreeHeap(SockPrivateHeap, 0, HelperData); - RtlFreeHeap(SockPrivateHeap, 0, HelperDllName); - RtlFreeHeap(SockPrivateHeap, 0, FullHelperDllName); - RegCloseKey(KeyHandle); - return ErrorCode; - } - - /* Get the Full name, expanding Environment Strings */ - HelperDllNameSize = ExpandEnvironmentStringsW(HelperDllName, - FullHelperDllName, - MAX_PATH); - - /* Load the DLL */ - HelperData->hInstance = LoadLibraryW(FullHelperDllName); - - /* Free Buffers */ - RtlFreeHeap(SockPrivateHeap, 0, HelperDllName); - RtlFreeHeap(SockPrivateHeap, 0, FullHelperDllName); - - /* Return if we didn't Load it Properly */ - if (!HelperData->hInstance) - { - /* Free memory and fail */ - RtlFreeHeap(SockPrivateHeap, 0, HelperData); - RegCloseKey(KeyHandle); - return GetLastError(); - } - - /* Close Key */ - RegCloseKey(KeyHandle); - - /* Get the Pointers to the Helper Routines */ - HelperData->WSHOpenSocket = (PWSH_OPEN_SOCKET) - GetProcAddress(HelperData->hInstance, - "WSHOpenSocket"); - HelperData->WSHOpenSocket2 = (PWSH_OPEN_SOCKET2) - GetProcAddress(HelperData->hInstance, - "WSHOpenSocket2"); - HelperData->WSHJoinLeaf = (PWSH_JOIN_LEAF) - GetProcAddress(HelperData->hInstance, - "WSHJoinLeaf"); - HelperData->WSHNotify = (PWSH_NOTIFY) - GetProcAddress(HelperData->hInstance, "WSHNotify"); - HelperData->WSHGetSocketInformation = (PWSH_GET_SOCKET_INFORMATION) - GetProcAddress(HelperData->hInstance, - "WSHGetSocketInformation"); - HelperData->WSHSetSocketInformation = (PWSH_SET_SOCKET_INFORMATION) - GetProcAddress(HelperData->hInstance, - "WSHSetSocketInformation"); - HelperData->WSHGetSockaddrType = (PWSH_GET_SOCKADDR_TYPE) - GetProcAddress(HelperData->hInstance, - "WSHGetSockaddrType"); - HelperData->WSHGetWildcardSockaddr = (PWSH_GET_WILDCARD_SOCKADDR) - GetProcAddress(HelperData->hInstance, - "WSHGetWildcardSockaddr"); - HelperData->WSHGetBroadcastSockaddr = (PWSH_GET_BROADCAST_SOCKADDR) - GetProcAddress(HelperData->hInstance, - "WSHGetBroadcastSockaddr"); - HelperData->WSHAddressToString = (PWSH_ADDRESS_TO_STRING) - GetProcAddress(HelperData->hInstance, - "WSHAddressToString"); - HelperData->WSHStringToAddress = (PWSH_STRING_TO_ADDRESS) - GetProcAddress(HelperData->hInstance, - "WSHStringToAddress"); - HelperData->WSHIoctl = (PWSH_IOCTL) - GetProcAddress(HelperData->hInstance, "WSHIoctl"); - - /* Save the Mapping Structure and transport name */ - HelperData->Mapping = Mapping; - wcscpy(HelperData->TransportName, TransportName); - - /* Increment Reference Count */ - HelperData->RefCount = 1; - - /* Add it to our list */ - InsertHeadList(&SockHelperDllListHead, &HelperData->Helpers); - - /* Return Pointers */ - *HelperDllData = HelperData; - - /* Check if this one was already load it */ - Entry = HelperData->Helpers.Flink; - while (Entry != &SockHelperDllListHead) - { - /* Get the entry */ - HelperData = CONTAINING_RECORD(Entry, HELPER_DATA, Helpers); - - /* Move to the next one */ - Entry = Entry->Flink; - - /* Check if the names match */ - if (!wcscmp(HelperData->TransportName, (*HelperDllData)->TransportName)) - { - /* Remove this one */ - RemoveEntryList(&HelperData->Helpers); - SockDereferenceHelperDll(HelperData); - } - } - - /* Return success */ - return NO_ERROR; -} - -BOOL -WSPAPI -SockIsTripleInMapping(IN PWINSOCK_MAPPING Mapping, - IN INT AddressFamily, - OUT PBOOLEAN AfMatch, - IN INT SocketType, - OUT PBOOLEAN SockMatch, - IN INT Protocol, - OUT PBOOLEAN ProtoMatch) -{ - ULONG Row; - BOOLEAN FoundAf = FALSE, FoundProto = FALSE, FoundSocket = FALSE; - - /* Loop through Mapping to Find a matching one */ - for (Row = 0; Row < Mapping->Rows; Row++) - { - /* Check Address Family */ - if ((INT)Mapping->Mapping[Row].AddressFamily == AddressFamily) - { - /* Remember that we found it */ - FoundAf = TRUE; - } - - /* Check Socket Type */ - if ((INT)Mapping->Mapping[Row].SocketType == SocketType) - { - /* Remember that we found it */ - FoundSocket = TRUE; - } - - /* Check Protocol (SOCK_RAW and AF_NETBIOS can skip this check) */ - if (((INT)Mapping->Mapping[Row].SocketType == SocketType) || - (AddressFamily == AF_NETBIOS) || (SocketType == SOCK_RAW)) - { - /* Remember that we found it */ - FoundProto = TRUE; - } - - /* Check of all three values Match */ - if (FoundProto && FoundSocket && FoundAf) - { - /* Return success */ - *AfMatch = *SockMatch = *ProtoMatch = TRUE; - return TRUE; - } - } - - /* Return whatever we found */ - if (FoundAf) *AfMatch = TRUE; - if (FoundSocket) *SockMatch = TRUE; - if (FoundProto) *ProtoMatch = TRUE; - - /* Fail */ - return FALSE; -} - -INT -WSPAPI -SockNotifyHelperDll(IN PSOCKET_INFORMATION Socket, - IN DWORD Event) -{ - INT ErrorCode; - - /* See if this event matters */ - if (!(Socket->HelperEvents & Event)) return NO_ERROR; - - /* See if we have a helper... */ - if (!(Socket->HelperData)) return NO_ERROR; - - /* Get TDI handles */ - ErrorCode = SockGetTdiHandles(Socket); - if (ErrorCode != NO_ERROR) return ErrorCode; - - /* Call the notification */ - return Socket->HelperData->WSHNotify(Socket->HelperContext, - Socket->Handle, - Socket->TdiAddressHandle, - Socket->TdiConnectionHandle, - Event); -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -LIST_ENTRY SockHelperDllListHead; - -/* FUNCTIONS *****************************************************************/ - -VOID -WSPAPI -SockFreeHelperDll(IN PHELPER_DATA Helper) -{ - /* Free the DLL */ - FreeLibrary(Helper->hInstance); - - /* Free the mapping */ - RtlFreeHeap(SockPrivateHeap, 0, Helper->Mapping); - - /* Free the DLL Structure itself */ - RtlFreeHeap(SockPrivateHeap, 0, Helper); -} - -INT -WSPAPI -SockGetTdiName(PINT AddressFamily, - PINT SocketType, - PINT Protocol, - LPGUID ProviderId, - GROUP Group, - DWORD Flags, - PUNICODE_STRING TransportName, - PVOID *HelperDllContext, - PHELPER_DATA *HelperDllData, - PDWORD Events) -{ - PHELPER_DATA HelperData; - PWSTR Transports; - PWSTR Transport; - PWINSOCK_MAPPING Mapping; - PLIST_ENTRY Helpers; - BOOLEAN SharedLock = TRUE; - INT ErrorCode; - BOOLEAN AfMatch = FALSE, ProtoMatch = FALSE, SocketMatch = FALSE; - - /* Acquire global lock */ - SockAcquireRwLockShared(&SocketGlobalLock); - -TryAgain: - /* Check in our Current Loaded Helpers */ - for (Helpers = SockHelperDllListHead.Flink; - Helpers != &SockHelperDllListHead; - Helpers = Helpers->Flink) - { - /* Get the current helper */ - HelperData = CONTAINING_RECORD(Helpers, HELPER_DATA, Helpers); - - /* See if this Mapping works for us */ - if (SockIsTripleInMapping(HelperData->Mapping, - *AddressFamily, - &AfMatch, - *SocketType, - &SocketMatch, - *Protocol, - &ProtoMatch)) - { - /* Call the Helper Dll function get the Transport Name */ - if (!HelperData->WSHOpenSocket2) - { - if (!(Flags & WSA_FLAG_MULTIPOINT_ALL)) - { - /* DLL Doesn't support WSHOpenSocket2, call the old one */ - ErrorCode = HelperData->WSHOpenSocket(AddressFamily, - SocketType, - Protocol, - TransportName, - HelperDllContext, - Events); - } - else - { - /* Invalid flag */ - ErrorCode = WSAEINVAL; - } - } - else - { - /* Call the new WSHOpenSocket */ - ErrorCode = HelperData->WSHOpenSocket2(AddressFamily, - SocketType, - Protocol, - Group, - Flags, - TransportName, - HelperDllContext, - Events); - } - - /* Check for success */ - if (ErrorCode == NO_ERROR) - { - /* Reference the helper */ - InterlockedIncrement(&HelperData->RefCount); - - /* Check which lock we acquired */ - if (SharedLock) - { - /* Release the shared lock */ - SockReleaseRwLockShared(&SocketGlobalLock); - } - else - { - /* Release the acquired lock */ - SockReleaseRwLockExclusive(&SocketGlobalLock); - } - - /* Return the Helper Pointers */ - *HelperDllData = HelperData; - return NO_ERROR; - } - - /* Check if we don't need a transport name */ - if ((*SocketType == SOCK_RAW) && (TransportName->Buffer)) - { - /* Free it */ - RtlFreeHeap(RtlGetProcessHeap(), 0, TransportName->Buffer); - TransportName->Buffer = NULL; - } - } - } - - /* We didn't find a match: try again with RW access */ - if (SharedLock) - { - /* Switch locks */ - SockReleaseRwLockShared(&SocketGlobalLock); - SockAcquireRwLockExclusive(&SocketGlobalLock); - - /* Parse the list again */ - SharedLock = FALSE; - goto TryAgain; - } - - /* Get the Transports available */ - ErrorCode = SockLoadTransportList(&Transports); - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - SockReleaseRwLockExclusive(&SocketGlobalLock); - return ErrorCode; - } - - /* Loop through each transport until we find one that can satisfy us */ - for (Transport = Transports; *Transport; Transport += wcslen(Transport) + 1) - { - /* See what mapping this Transport supports */ - ErrorCode = SockLoadTransportMapping(Transport, &Mapping); - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Try the next one */ - continue; - } - - /* See if this Mapping works for us */ - if (SockIsTripleInMapping(Mapping, - *AddressFamily, - &AfMatch, - *SocketType, - &SocketMatch, - *Protocol, - &ProtoMatch)) - { - /* It does, so load the DLL associated with it */ - ErrorCode = SockLoadHelperDll(Transport, Mapping, &HelperData); - - /* Check for success */ - if (ErrorCode == NO_ERROR) - { - /* Call the Helper Dll function get the Transport Name */ - if (!HelperData->WSHOpenSocket2) - { - /* Check for invalid flag combo */ - if (!(Flags & WSA_FLAG_MULTIPOINT_ALL)) - { - /* DLL Doesn't support WSHOpenSocket2, call the old one */ - ErrorCode = HelperData->WSHOpenSocket(AddressFamily, - SocketType, - Protocol, - TransportName, - HelperDllContext, - Events); - } - else - { - /* Fail */ - ErrorCode = WSAEINVAL; - } - } - else - { - /* Call the newer function */ - ErrorCode = HelperData->WSHOpenSocket2(AddressFamily, - SocketType, - Protocol, - Group, - Flags, - TransportName, - HelperDllContext, - Events); - } - - /* Check for success */ - if (ErrorCode == NO_ERROR) - { - /* Reference the helper */ - InterlockedIncrement(&HelperData->RefCount); - - /* Release the lock and free the transports */ - SockReleaseRwLockExclusive(&SocketGlobalLock); - RtlFreeHeap(SockPrivateHeap, 0, Transports); - - /* Return the Helper Pointer */ - *HelperDllData = HelperData; - return NO_ERROR; - } - - /* Check if we don't need a transport name */ - if ((*SocketType == SOCK_RAW) && (TransportName->Buffer)) - { - /* Free it */ - RtlFreeHeap(RtlGetProcessHeap(), 0, TransportName->Buffer); - TransportName->Buffer = NULL; - } - - /* Try again */ - continue; - } - } - - /* Free the mapping and continue */ - RtlFreeHeap(SockPrivateHeap, 0, Mapping); - } - - /* Release the lock and free the transport list */ - SockReleaseRwLockExclusive(&SocketGlobalLock); - RtlFreeHeap(SockPrivateHeap, 0, Transports); - - /* Check why we didn't find a match */ - if (!AfMatch) return WSAEAFNOSUPPORT; - if (!ProtoMatch) return WSAEPROTONOSUPPORT; - if (!SocketMatch) return WSAESOCKTNOSUPPORT; - - /* The comination itself was invalid */ - return WSAEINVAL; -} - -INT -WSPAPI -SockLoadTransportMapping(IN PWSTR TransportName, - OUT PWINSOCK_MAPPING *Mapping) -{ - PWSTR TransportKey; - HKEY KeyHandle; - INT ErrorCode; - ULONG MappingSize = 0; - - /* Allocate a Buffer */ - TransportKey = SockAllocateHeapRoutine(SockPrivateHeap, - 0, - MAX_PATH * sizeof(WCHAR)); - /* Check for error */ - if (!TransportKey) return ERROR_NOT_ENOUGH_MEMORY; - - /* Generate the right key name */ - wcscpy(TransportKey, L"System\\CurrentControlSet\\Services\\"); - wcscat(TransportKey, TransportName); - wcscat(TransportKey, L"\\Parameters\\Winsock"); - - /* Open the Key */ - ErrorCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE, - TransportKey, - 0, - KEY_READ, - &KeyHandle); - - /* We don't need the Transport Key anymore */ - RtlFreeHeap(SockPrivateHeap, 0, TransportKey); - - /* Check for error */ - if ((ErrorCode != ERROR_MORE_DATA) && (ErrorCode != NO_ERROR)) - { - /* Close key and fail */ - RegCloseKey(KeyHandle); - return ErrorCode; - } - - /* Find out how much space we need for the Mapping */ - ErrorCode = RegQueryValueExW(KeyHandle, - L"Mapping", - NULL, - NULL, - NULL, - &MappingSize); - - /* Check for error */ - if ((ErrorCode != ERROR_MORE_DATA) && (ErrorCode != NO_ERROR)) - { - /* Close key and fail */ - RegCloseKey(KeyHandle); - return ErrorCode; - } - - /* Allocate Memory for the Mapping */ - *Mapping = SockAllocateHeapRoutine(SockPrivateHeap, 0, MappingSize); - - /* Check for error */ - if (!(*Mapping)) - { - /* Close key and fail */ - RegCloseKey(KeyHandle); - return ERROR_NOT_ENOUGH_MEMORY; - } - - /* Read the Mapping */ - ErrorCode = RegQueryValueExW(KeyHandle, - L"Mapping", - NULL, - NULL, - (LPBYTE)*Mapping, - &MappingSize); - - /* Check for error */ - if ((ErrorCode != ERROR_MORE_DATA) && (ErrorCode != NO_ERROR)) - { - /* Close key and fail */ - RegCloseKey(KeyHandle); - return ErrorCode; - } - - /* Close key and return */ - RegCloseKey(KeyHandle); - return NO_ERROR; -} - -INT -WSPAPI -SockLoadHelperDll(PWSTR TransportName, - PWINSOCK_MAPPING Mapping, - PHELPER_DATA *HelperDllData) -{ - PHELPER_DATA HelperData; - PWSTR HelperDllName; - PWSTR FullHelperDllName; - ULONG HelperDllNameSize; - PWSTR HelperKey; - HKEY KeyHandle; - ULONG DataSize; - INT ErrorCode; - PLIST_ENTRY Entry; - - /* Allocate space for the Helper Structure and TransportName */ - HelperData = SockAllocateHeapRoutine(SockPrivateHeap, - 0, - sizeof(*HelperData) + - (DWORD)(wcslen(TransportName) + 1) * - sizeof(WCHAR)); - - /* Check for error */ - if (!HelperData) return ERROR_NOT_ENOUGH_MEMORY; - - /* Allocate Space for the Helper DLL Key */ - HelperKey = SockAllocateHeapRoutine(SockPrivateHeap, - 0, - MAX_PATH * sizeof(WCHAR)); - - /* Check for error */ - if (!HelperKey) - { - RtlFreeHeap(SockPrivateHeap, 0, HelperData); - return ERROR_NOT_ENOUGH_MEMORY; - } - - /* Generate the right key name */ - wcscpy(HelperKey, L"System\\CurrentControlSet\\Services\\"); - wcscat(HelperKey, TransportName); - wcscat(HelperKey, L"\\Parameters\\Winsock"); - - /* Open the Key */ - ErrorCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE, - HelperKey, - 0, - KEY_READ, - &KeyHandle); - - /* Free Buffer */ - RtlFreeHeap(SockPrivateHeap, 0, HelperKey); - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Free the helper data and fail */ - RtlFreeHeap(SockPrivateHeap, 0, HelperData); - RegCloseKey(KeyHandle); - return ErrorCode; - } - - /* Read Minimum size of Sockaddr Structures */ - DataSize = sizeof(HelperData->MinWSAddressLength); - RegQueryValueExW(KeyHandle, - L"MinSockaddrLength", - NULL, - NULL, - (LPBYTE)&HelperData->MinWSAddressLength, - &DataSize); - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Free the helper data and fail */ - RtlFreeHeap(SockPrivateHeap, 0, HelperData); - RegCloseKey(KeyHandle); - return ErrorCode; - } - - /* Read Maximum size of Sockaddr Structures */ - DataSize = sizeof(HelperData->MinWSAddressLength); - RegQueryValueExW(KeyHandle, - L"MaxSockaddrLength", - NULL, - NULL, - (LPBYTE)&HelperData->MaxWSAddressLength, - &DataSize); - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Free the helper data and fail */ - RtlFreeHeap(SockPrivateHeap, 0, HelperData); - RegCloseKey(KeyHandle); - return ErrorCode; - } - - /* Size of TDI Structures */ - HelperData->MinTDIAddressLength = HelperData->MinWSAddressLength + 6; - HelperData->MaxTDIAddressLength = HelperData->MaxWSAddressLength + 6; - - /* Read Delayed Acceptance Setting */ - DataSize = sizeof(DWORD); - ErrorCode = RegQueryValueExW(KeyHandle, - L"UseDelayedAcceptance", - NULL, - NULL, - (LPBYTE)&HelperData->UseDelayedAcceptance, - &DataSize); - - /* Use defalt if we failed */ - if (ErrorCode != NO_ERROR) HelperData->UseDelayedAcceptance = -1; - - /* Allocate Space for the Helper DLL Names */ - HelperDllName = SockAllocateHeapRoutine(SockPrivateHeap, - 0, - MAX_PATH * sizeof(WCHAR)); - - /* Check for error */ - if (!HelperDllName) - { - /* Free the helper data and fail */ - RtlFreeHeap(SockPrivateHeap, 0, HelperData); - RegCloseKey(KeyHandle); - return ErrorCode; - } - - /* Allocate space for the expanded version */ - FullHelperDllName = SockAllocateHeapRoutine(SockPrivateHeap, - 0, - MAX_PATH * sizeof(WCHAR)); - - /* Check for error */ - if (!FullHelperDllName) - { - /* Free the helper data and fail */ - RtlFreeHeap(SockPrivateHeap, 0, HelperData); - RtlFreeHeap(SockPrivateHeap, 0, HelperDllName); - RegCloseKey(KeyHandle); - return ErrorCode; - } - - /* Get the name of the Helper DLL*/ - DataSize = 512; - ErrorCode = RegQueryValueExW(KeyHandle, - L"HelperDllName", - NULL, - NULL, - (LPBYTE)HelperDllName, - &DataSize); - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Free the helper data and fail */ - RtlFreeHeap(SockPrivateHeap, 0, HelperData); - RtlFreeHeap(SockPrivateHeap, 0, HelperDllName); - RtlFreeHeap(SockPrivateHeap, 0, FullHelperDllName); - RegCloseKey(KeyHandle); - return ErrorCode; - } - - /* Get the Full name, expanding Environment Strings */ - HelperDllNameSize = ExpandEnvironmentStringsW(HelperDllName, - FullHelperDllName, - MAX_PATH); - - /* Load the DLL */ - HelperData->hInstance = LoadLibraryW(FullHelperDllName); - - /* Free Buffers */ - RtlFreeHeap(SockPrivateHeap, 0, HelperDllName); - RtlFreeHeap(SockPrivateHeap, 0, FullHelperDllName); - - /* Return if we didn't Load it Properly */ - if (!HelperData->hInstance) - { - /* Free memory and fail */ - RtlFreeHeap(SockPrivateHeap, 0, HelperData); - RegCloseKey(KeyHandle); - return GetLastError(); - } - - /* Close Key */ - RegCloseKey(KeyHandle); - - /* Get the Pointers to the Helper Routines */ - HelperData->WSHOpenSocket = (PWSH_OPEN_SOCKET) - GetProcAddress(HelperData->hInstance, - "WSHOpenSocket"); - HelperData->WSHOpenSocket2 = (PWSH_OPEN_SOCKET2) - GetProcAddress(HelperData->hInstance, - "WSHOpenSocket2"); - HelperData->WSHJoinLeaf = (PWSH_JOIN_LEAF) - GetProcAddress(HelperData->hInstance, - "WSHJoinLeaf"); - HelperData->WSHNotify = (PWSH_NOTIFY) - GetProcAddress(HelperData->hInstance, "WSHNotify"); - HelperData->WSHGetSocketInformation = (PWSH_GET_SOCKET_INFORMATION) - GetProcAddress(HelperData->hInstance, - "WSHGetSocketInformation"); - HelperData->WSHSetSocketInformation = (PWSH_SET_SOCKET_INFORMATION) - GetProcAddress(HelperData->hInstance, - "WSHSetSocketInformation"); - HelperData->WSHGetSockaddrType = (PWSH_GET_SOCKADDR_TYPE) - GetProcAddress(HelperData->hInstance, - "WSHGetSockaddrType"); - HelperData->WSHGetWildcardSockaddr = (PWSH_GET_WILDCARD_SOCKADDR) - GetProcAddress(HelperData->hInstance, - "WSHGetWildcardSockaddr"); - HelperData->WSHGetBroadcastSockaddr = (PWSH_GET_BROADCAST_SOCKADDR) - GetProcAddress(HelperData->hInstance, - "WSHGetBroadcastSockaddr"); - HelperData->WSHAddressToString = (PWSH_ADDRESS_TO_STRING) - GetProcAddress(HelperData->hInstance, - "WSHAddressToString"); - HelperData->WSHStringToAddress = (PWSH_STRING_TO_ADDRESS) - GetProcAddress(HelperData->hInstance, - "WSHStringToAddress"); - HelperData->WSHIoctl = (PWSH_IOCTL) - GetProcAddress(HelperData->hInstance, "WSHIoctl"); - - /* Save the Mapping Structure and transport name */ - HelperData->Mapping = Mapping; - wcscpy(HelperData->TransportName, TransportName); - - /* Increment Reference Count */ - HelperData->RefCount = 1; - - /* Add it to our list */ - InsertHeadList(&SockHelperDllListHead, &HelperData->Helpers); - - /* Return Pointers */ - *HelperDllData = HelperData; - - /* Check if this one was already load it */ - Entry = HelperData->Helpers.Flink; - while (Entry != &SockHelperDllListHead) - { - /* Get the entry */ - HelperData = CONTAINING_RECORD(Entry, HELPER_DATA, Helpers); - - /* Move to the next one */ - Entry = Entry->Flink; - - /* Check if the names match */ - if (!wcscmp(HelperData->TransportName, (*HelperDllData)->TransportName)) - { - /* Remove this one */ - RemoveEntryList(&HelperData->Helpers); - SockDereferenceHelperDll(HelperData); - } - } - - /* Return success */ - return NO_ERROR; -} - -BOOL -WSPAPI -SockIsTripleInMapping(IN PWINSOCK_MAPPING Mapping, - IN INT AddressFamily, - OUT PBOOLEAN AfMatch, - IN INT SocketType, - OUT PBOOLEAN SockMatch, - IN INT Protocol, - OUT PBOOLEAN ProtoMatch) -{ - ULONG Row; - BOOLEAN FoundAf = FALSE, FoundProto = FALSE, FoundSocket = FALSE; - - /* Loop through Mapping to Find a matching one */ - for (Row = 0; Row < Mapping->Rows; Row++) - { - /* Check Address Family */ - if ((INT)Mapping->Mapping[Row].AddressFamily == AddressFamily) - { - /* Remember that we found it */ - FoundAf = TRUE; - } - - /* Check Socket Type */ - if ((INT)Mapping->Mapping[Row].SocketType == SocketType) - { - /* Remember that we found it */ - FoundSocket = TRUE; - } - - /* Check Protocol (SOCK_RAW and AF_NETBIOS can skip this check) */ - if (((INT)Mapping->Mapping[Row].SocketType == SocketType) || - (AddressFamily == AF_NETBIOS) || (SocketType == SOCK_RAW)) - { - /* Remember that we found it */ - FoundProto = TRUE; - } - - /* Check of all three values Match */ - if (FoundProto && FoundSocket && FoundAf) - { - /* Return success */ - *AfMatch = *SockMatch = *ProtoMatch = TRUE; - return TRUE; - } - } - - /* Return whatever we found */ - if (FoundAf) *AfMatch = TRUE; - if (FoundSocket) *SockMatch = TRUE; - if (FoundProto) *ProtoMatch = TRUE; - - /* Fail */ - return FALSE; -} - -INT -WSPAPI -SockNotifyHelperDll(IN PSOCKET_INFORMATION Socket, - IN DWORD Event) -{ - INT ErrorCode; - - /* See if this event matters */ - if (!(Socket->HelperEvents & Event)) return NO_ERROR; - - /* See if we have a helper... */ - if (!(Socket->HelperData)) return NO_ERROR; - - /* Get TDI handles */ - ErrorCode = SockGetTdiHandles(Socket); - if (ErrorCode != NO_ERROR) return ErrorCode; - - /* Call the notification */ - return Socket->HelperData->WSHNotify(Socket->HelperContext, - Socket->Handle, - Socket->TdiAddressHandle, - Socket->TdiConnectionHandle, - Event); -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -LIST_ENTRY SockHelperDllListHead; - -/* FUNCTIONS *****************************************************************/ - -VOID -WSPAPI -SockFreeHelperDll(IN PHELPER_DATA Helper) -{ - /* Free the DLL */ - FreeLibrary(Helper->hInstance); - - /* Free the mapping */ - RtlFreeHeap(SockPrivateHeap, 0, Helper->Mapping); - - /* Free the DLL Structure itself */ - RtlFreeHeap(SockPrivateHeap, 0, Helper); -} - -INT -WSPAPI -SockGetTdiName(PINT AddressFamily, - PINT SocketType, - PINT Protocol, - LPGUID ProviderId, - GROUP Group, - DWORD Flags, - PUNICODE_STRING TransportName, - PVOID *HelperDllContext, - PHELPER_DATA *HelperDllData, - PDWORD Events) -{ - PHELPER_DATA HelperData; - PWSTR Transports; - PWSTR Transport; - PWINSOCK_MAPPING Mapping; - PLIST_ENTRY Helpers; - BOOLEAN SharedLock = TRUE; - INT ErrorCode; - BOOLEAN AfMatch = FALSE, ProtoMatch = FALSE, SocketMatch = FALSE; - - /* Acquire global lock */ - SockAcquireRwLockShared(&SocketGlobalLock); - -TryAgain: - /* Check in our Current Loaded Helpers */ - for (Helpers = SockHelperDllListHead.Flink; - Helpers != &SockHelperDllListHead; - Helpers = Helpers->Flink) - { - /* Get the current helper */ - HelperData = CONTAINING_RECORD(Helpers, HELPER_DATA, Helpers); - - /* See if this Mapping works for us */ - if (SockIsTripleInMapping(HelperData->Mapping, - *AddressFamily, - &AfMatch, - *SocketType, - &SocketMatch, - *Protocol, - &ProtoMatch)) - { - /* Call the Helper Dll function get the Transport Name */ - if (!HelperData->WSHOpenSocket2) - { - if (!(Flags & WSA_FLAG_MULTIPOINT_ALL)) - { - /* DLL Doesn't support WSHOpenSocket2, call the old one */ - ErrorCode = HelperData->WSHOpenSocket(AddressFamily, - SocketType, - Protocol, - TransportName, - HelperDllContext, - Events); - } - else - { - /* Invalid flag */ - ErrorCode = WSAEINVAL; - } - } - else - { - /* Call the new WSHOpenSocket */ - ErrorCode = HelperData->WSHOpenSocket2(AddressFamily, - SocketType, - Protocol, - Group, - Flags, - TransportName, - HelperDllContext, - Events); - } - - /* Check for success */ - if (ErrorCode == NO_ERROR) - { - /* Reference the helper */ - InterlockedIncrement(&HelperData->RefCount); - - /* Check which lock we acquired */ - if (SharedLock) - { - /* Release the shared lock */ - SockReleaseRwLockShared(&SocketGlobalLock); - } - else - { - /* Release the acquired lock */ - SockReleaseRwLockExclusive(&SocketGlobalLock); - } - - /* Return the Helper Pointers */ - *HelperDllData = HelperData; - return NO_ERROR; - } - - /* Check if we don't need a transport name */ - if ((*SocketType == SOCK_RAW) && (TransportName->Buffer)) - { - /* Free it */ - RtlFreeHeap(RtlGetProcessHeap(), 0, TransportName->Buffer); - TransportName->Buffer = NULL; - } - } - } - - /* We didn't find a match: try again with RW access */ - if (SharedLock) - { - /* Switch locks */ - SockReleaseRwLockShared(&SocketGlobalLock); - SockAcquireRwLockExclusive(&SocketGlobalLock); - - /* Parse the list again */ - SharedLock = FALSE; - goto TryAgain; - } - - /* Get the Transports available */ - ErrorCode = SockLoadTransportList(&Transports); - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - SockReleaseRwLockExclusive(&SocketGlobalLock); - return ErrorCode; - } - - /* Loop through each transport until we find one that can satisfy us */ - for (Transport = Transports; *Transport; Transport += wcslen(Transport) + 1) - { - /* See what mapping this Transport supports */ - ErrorCode = SockLoadTransportMapping(Transport, &Mapping); - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Try the next one */ - continue; - } - - /* See if this Mapping works for us */ - if (SockIsTripleInMapping(Mapping, - *AddressFamily, - &AfMatch, - *SocketType, - &SocketMatch, - *Protocol, - &ProtoMatch)) - { - /* It does, so load the DLL associated with it */ - ErrorCode = SockLoadHelperDll(Transport, Mapping, &HelperData); - - /* Check for success */ - if (ErrorCode == NO_ERROR) - { - /* Call the Helper Dll function get the Transport Name */ - if (!HelperData->WSHOpenSocket2) - { - /* Check for invalid flag combo */ - if (!(Flags & WSA_FLAG_MULTIPOINT_ALL)) - { - /* DLL Doesn't support WSHOpenSocket2, call the old one */ - ErrorCode = HelperData->WSHOpenSocket(AddressFamily, - SocketType, - Protocol, - TransportName, - HelperDllContext, - Events); - } - else - { - /* Fail */ - ErrorCode = WSAEINVAL; - } - } - else - { - /* Call the newer function */ - ErrorCode = HelperData->WSHOpenSocket2(AddressFamily, - SocketType, - Protocol, - Group, - Flags, - TransportName, - HelperDllContext, - Events); - } - - /* Check for success */ - if (ErrorCode == NO_ERROR) - { - /* Reference the helper */ - InterlockedIncrement(&HelperData->RefCount); - - /* Release the lock and free the transports */ - SockReleaseRwLockExclusive(&SocketGlobalLock); - RtlFreeHeap(SockPrivateHeap, 0, Transports); - - /* Return the Helper Pointer */ - *HelperDllData = HelperData; - return NO_ERROR; - } - - /* Check if we don't need a transport name */ - if ((*SocketType == SOCK_RAW) && (TransportName->Buffer)) - { - /* Free it */ - RtlFreeHeap(RtlGetProcessHeap(), 0, TransportName->Buffer); - TransportName->Buffer = NULL; - } - - /* Try again */ - continue; - } - } - - /* Free the mapping and continue */ - RtlFreeHeap(SockPrivateHeap, 0, Mapping); - } - - /* Release the lock and free the transport list */ - SockReleaseRwLockExclusive(&SocketGlobalLock); - RtlFreeHeap(SockPrivateHeap, 0, Transports); - - /* Check why we didn't find a match */ - if (!AfMatch) return WSAEAFNOSUPPORT; - if (!ProtoMatch) return WSAEPROTONOSUPPORT; - if (!SocketMatch) return WSAESOCKTNOSUPPORT; - - /* The comination itself was invalid */ - return WSAEINVAL; -} - -INT -WSPAPI -SockLoadTransportMapping(IN PWSTR TransportName, - OUT PWINSOCK_MAPPING *Mapping) -{ - PWSTR TransportKey; - HKEY KeyHandle; - INT ErrorCode; - ULONG MappingSize = 0; - - /* Allocate a Buffer */ - TransportKey = SockAllocateHeapRoutine(SockPrivateHeap, - 0, - MAX_PATH * sizeof(WCHAR)); - /* Check for error */ - if (!TransportKey) return ERROR_NOT_ENOUGH_MEMORY; - - /* Generate the right key name */ - wcscpy(TransportKey, L"System\\CurrentControlSet\\Services\\"); - wcscat(TransportKey, TransportName); - wcscat(TransportKey, L"\\Parameters\\Winsock"); - - /* Open the Key */ - ErrorCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE, - TransportKey, - 0, - KEY_READ, - &KeyHandle); - - /* We don't need the Transport Key anymore */ - RtlFreeHeap(SockPrivateHeap, 0, TransportKey); - - /* Check for error */ - if ((ErrorCode != ERROR_MORE_DATA) && (ErrorCode != NO_ERROR)) - { - /* Close key and fail */ - RegCloseKey(KeyHandle); - return ErrorCode; - } - - /* Find out how much space we need for the Mapping */ - ErrorCode = RegQueryValueExW(KeyHandle, - L"Mapping", - NULL, - NULL, - NULL, - &MappingSize); - - /* Check for error */ - if ((ErrorCode != ERROR_MORE_DATA) && (ErrorCode != NO_ERROR)) - { - /* Close key and fail */ - RegCloseKey(KeyHandle); - return ErrorCode; - } - - /* Allocate Memory for the Mapping */ - *Mapping = SockAllocateHeapRoutine(SockPrivateHeap, 0, MappingSize); - - /* Check for error */ - if (!(*Mapping)) - { - /* Close key and fail */ - RegCloseKey(KeyHandle); - return ERROR_NOT_ENOUGH_MEMORY; - } - - /* Read the Mapping */ - ErrorCode = RegQueryValueExW(KeyHandle, - L"Mapping", - NULL, - NULL, - (LPBYTE)*Mapping, - &MappingSize); - - /* Check for error */ - if ((ErrorCode != ERROR_MORE_DATA) && (ErrorCode != NO_ERROR)) - { - /* Close key and fail */ - RegCloseKey(KeyHandle); - return ErrorCode; - } - - /* Close key and return */ - RegCloseKey(KeyHandle); - return NO_ERROR; -} - -INT -WSPAPI -SockLoadHelperDll(PWSTR TransportName, - PWINSOCK_MAPPING Mapping, - PHELPER_DATA *HelperDllData) -{ - PHELPER_DATA HelperData; - PWSTR HelperDllName; - PWSTR FullHelperDllName; - ULONG HelperDllNameSize; - PWSTR HelperKey; - HKEY KeyHandle; - ULONG DataSize; - INT ErrorCode; - PLIST_ENTRY Entry; - - /* Allocate space for the Helper Structure and TransportName */ - HelperData = SockAllocateHeapRoutine(SockPrivateHeap, - 0, - sizeof(*HelperData) + - (DWORD)(wcslen(TransportName) + 1) * - sizeof(WCHAR)); - - /* Check for error */ - if (!HelperData) return ERROR_NOT_ENOUGH_MEMORY; - - /* Allocate Space for the Helper DLL Key */ - HelperKey = SockAllocateHeapRoutine(SockPrivateHeap, - 0, - MAX_PATH * sizeof(WCHAR)); - - /* Check for error */ - if (!HelperKey) - { - RtlFreeHeap(SockPrivateHeap, 0, HelperData); - return ERROR_NOT_ENOUGH_MEMORY; - } - - /* Generate the right key name */ - wcscpy(HelperKey, L"System\\CurrentControlSet\\Services\\"); - wcscat(HelperKey, TransportName); - wcscat(HelperKey, L"\\Parameters\\Winsock"); - - /* Open the Key */ - ErrorCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE, - HelperKey, - 0, - KEY_READ, - &KeyHandle); - - /* Free Buffer */ - RtlFreeHeap(SockPrivateHeap, 0, HelperKey); - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Free the helper data and fail */ - RtlFreeHeap(SockPrivateHeap, 0, HelperData); - RegCloseKey(KeyHandle); - return ErrorCode; - } - - /* Read Minimum size of Sockaddr Structures */ - DataSize = sizeof(HelperData->MinWSAddressLength); - RegQueryValueExW(KeyHandle, - L"MinSockaddrLength", - NULL, - NULL, - (LPBYTE)&HelperData->MinWSAddressLength, - &DataSize); - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Free the helper data and fail */ - RtlFreeHeap(SockPrivateHeap, 0, HelperData); - RegCloseKey(KeyHandle); - return ErrorCode; - } - - /* Read Maximum size of Sockaddr Structures */ - DataSize = sizeof(HelperData->MinWSAddressLength); - RegQueryValueExW(KeyHandle, - L"MaxSockaddrLength", - NULL, - NULL, - (LPBYTE)&HelperData->MaxWSAddressLength, - &DataSize); - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Free the helper data and fail */ - RtlFreeHeap(SockPrivateHeap, 0, HelperData); - RegCloseKey(KeyHandle); - return ErrorCode; - } - - /* Size of TDI Structures */ - HelperData->MinTDIAddressLength = HelperData->MinWSAddressLength + 6; - HelperData->MaxTDIAddressLength = HelperData->MaxWSAddressLength + 6; - - /* Read Delayed Acceptance Setting */ - DataSize = sizeof(DWORD); - ErrorCode = RegQueryValueExW(KeyHandle, - L"UseDelayedAcceptance", - NULL, - NULL, - (LPBYTE)&HelperData->UseDelayedAcceptance, - &DataSize); - - /* Use defalt if we failed */ - if (ErrorCode != NO_ERROR) HelperData->UseDelayedAcceptance = -1; - - /* Allocate Space for the Helper DLL Names */ - HelperDllName = SockAllocateHeapRoutine(SockPrivateHeap, - 0, - MAX_PATH * sizeof(WCHAR)); - - /* Check for error */ - if (!HelperDllName) - { - /* Free the helper data and fail */ - RtlFreeHeap(SockPrivateHeap, 0, HelperData); - RegCloseKey(KeyHandle); - return ErrorCode; - } - - /* Allocate space for the expanded version */ - FullHelperDllName = SockAllocateHeapRoutine(SockPrivateHeap, - 0, - MAX_PATH * sizeof(WCHAR)); - - /* Check for error */ - if (!FullHelperDllName) - { - /* Free the helper data and fail */ - RtlFreeHeap(SockPrivateHeap, 0, HelperData); - RtlFreeHeap(SockPrivateHeap, 0, HelperDllName); - RegCloseKey(KeyHandle); - return ErrorCode; - } - - /* Get the name of the Helper DLL*/ - DataSize = 512; - ErrorCode = RegQueryValueExW(KeyHandle, - L"HelperDllName", - NULL, - NULL, - (LPBYTE)HelperDllName, - &DataSize); - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Free the helper data and fail */ - RtlFreeHeap(SockPrivateHeap, 0, HelperData); - RtlFreeHeap(SockPrivateHeap, 0, HelperDllName); - RtlFreeHeap(SockPrivateHeap, 0, FullHelperDllName); - RegCloseKey(KeyHandle); - return ErrorCode; - } - - /* Get the Full name, expanding Environment Strings */ - HelperDllNameSize = ExpandEnvironmentStringsW(HelperDllName, - FullHelperDllName, - MAX_PATH); - - /* Load the DLL */ - HelperData->hInstance = LoadLibraryW(FullHelperDllName); - - /* Free Buffers */ - RtlFreeHeap(SockPrivateHeap, 0, HelperDllName); - RtlFreeHeap(SockPrivateHeap, 0, FullHelperDllName); - - /* Return if we didn't Load it Properly */ - if (!HelperData->hInstance) - { - /* Free memory and fail */ - RtlFreeHeap(SockPrivateHeap, 0, HelperData); - RegCloseKey(KeyHandle); - return GetLastError(); - } - - /* Close Key */ - RegCloseKey(KeyHandle); - - /* Get the Pointers to the Helper Routines */ - HelperData->WSHOpenSocket = (PWSH_OPEN_SOCKET) - GetProcAddress(HelperData->hInstance, - "WSHOpenSocket"); - HelperData->WSHOpenSocket2 = (PWSH_OPEN_SOCKET2) - GetProcAddress(HelperData->hInstance, - "WSHOpenSocket2"); - HelperData->WSHJoinLeaf = (PWSH_JOIN_LEAF) - GetProcAddress(HelperData->hInstance, - "WSHJoinLeaf"); - HelperData->WSHNotify = (PWSH_NOTIFY) - GetProcAddress(HelperData->hInstance, "WSHNotify"); - HelperData->WSHGetSocketInformation = (PWSH_GET_SOCKET_INFORMATION) - GetProcAddress(HelperData->hInstance, - "WSHGetSocketInformation"); - HelperData->WSHSetSocketInformation = (PWSH_SET_SOCKET_INFORMATION) - GetProcAddress(HelperData->hInstance, - "WSHSetSocketInformation"); - HelperData->WSHGetSockaddrType = (PWSH_GET_SOCKADDR_TYPE) - GetProcAddress(HelperData->hInstance, - "WSHGetSockaddrType"); - HelperData->WSHGetWildcardSockaddr = (PWSH_GET_WILDCARD_SOCKADDR) - GetProcAddress(HelperData->hInstance, - "WSHGetWildcardSockaddr"); - HelperData->WSHGetBroadcastSockaddr = (PWSH_GET_BROADCAST_SOCKADDR) - GetProcAddress(HelperData->hInstance, - "WSHGetBroadcastSockaddr"); - HelperData->WSHAddressToString = (PWSH_ADDRESS_TO_STRING) - GetProcAddress(HelperData->hInstance, - "WSHAddressToString"); - HelperData->WSHStringToAddress = (PWSH_STRING_TO_ADDRESS) - GetProcAddress(HelperData->hInstance, - "WSHStringToAddress"); - HelperData->WSHIoctl = (PWSH_IOCTL) - GetProcAddress(HelperData->hInstance, "WSHIoctl"); - - /* Save the Mapping Structure and transport name */ - HelperData->Mapping = Mapping; - wcscpy(HelperData->TransportName, TransportName); - - /* Increment Reference Count */ - HelperData->RefCount = 1; - - /* Add it to our list */ - InsertHeadList(&SockHelperDllListHead, &HelperData->Helpers); - - /* Return Pointers */ - *HelperDllData = HelperData; - - /* Check if this one was already load it */ - Entry = HelperData->Helpers.Flink; - while (Entry != &SockHelperDllListHead) - { - /* Get the entry */ - HelperData = CONTAINING_RECORD(Entry, HELPER_DATA, Helpers); - - /* Move to the next one */ - Entry = Entry->Flink; - - /* Check if the names match */ - if (!wcscmp(HelperData->TransportName, (*HelperDllData)->TransportName)) - { - /* Remove this one */ - RemoveEntryList(&HelperData->Helpers); - SockDereferenceHelperDll(HelperData); - } - } - - /* Return success */ - return NO_ERROR; -} - -BOOL -WSPAPI -SockIsTripleInMapping(IN PWINSOCK_MAPPING Mapping, - IN INT AddressFamily, - OUT PBOOLEAN AfMatch, - IN INT SocketType, - OUT PBOOLEAN SockMatch, - IN INT Protocol, - OUT PBOOLEAN ProtoMatch) -{ - ULONG Row; - BOOLEAN FoundAf = FALSE, FoundProto = FALSE, FoundSocket = FALSE; - - /* Loop through Mapping to Find a matching one */ - for (Row = 0; Row < Mapping->Rows; Row++) - { - /* Check Address Family */ - if ((INT)Mapping->Mapping[Row].AddressFamily == AddressFamily) - { - /* Remember that we found it */ - FoundAf = TRUE; - } - - /* Check Socket Type */ - if ((INT)Mapping->Mapping[Row].SocketType == SocketType) - { - /* Remember that we found it */ - FoundSocket = TRUE; - } - - /* Check Protocol (SOCK_RAW and AF_NETBIOS can skip this check) */ - if (((INT)Mapping->Mapping[Row].SocketType == SocketType) || - (AddressFamily == AF_NETBIOS) || (SocketType == SOCK_RAW)) - { - /* Remember that we found it */ - FoundProto = TRUE; - } - - /* Check of all three values Match */ - if (FoundProto && FoundSocket && FoundAf) - { - /* Return success */ - *AfMatch = *SockMatch = *ProtoMatch = TRUE; - return TRUE; - } - } - - /* Return whatever we found */ - if (FoundAf) *AfMatch = TRUE; - if (FoundSocket) *SockMatch = TRUE; - if (FoundProto) *ProtoMatch = TRUE; - - /* Fail */ - return FALSE; -} - -INT -WSPAPI -SockNotifyHelperDll(IN PSOCKET_INFORMATION Socket, - IN DWORD Event) -{ - INT ErrorCode; - - /* See if this event matters */ - if (!(Socket->HelperEvents & Event)) return NO_ERROR; - - /* See if we have a helper... */ - if (!(Socket->HelperData)) return NO_ERROR; - - /* Get TDI handles */ - ErrorCode = SockGetTdiHandles(Socket); - if (ErrorCode != NO_ERROR) return ErrorCode; - - /* Call the notification */ - return Socket->HelperData->WSHNotify(Socket->HelperContext, - Socket->Handle, - Socket->TdiAddressHandle, - Socket->TdiConnectionHandle, - Event); -} - diff --git a/dll/win32/mswsock/msafd/listen.c b/dll/win32/mswsock/msafd/listen.c index ec37ae80613..831f683cdd5 100644 --- a/dll/win32/mswsock/msafd/listen.c +++ b/dll/win32/mswsock/msafd/listen.c @@ -139,426 +139,3 @@ error: return NO_ERROR; } -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -INT -WSPAPI -WSPListen(SOCKET Handle, - INT Backlog, - LPINT lpErrno) -{ - IO_STATUS_BLOCK IoStatusBlock; - AFD_LISTEN_DATA ListenData; - PSOCKET_INFORMATION Socket; - PWINSOCK_TEB_DATA ThreadData; - INT ErrorCode; - NTSTATUS Status; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* If the socket is connection-less, fail */ - if (MSAFD_IS_DGRAM_SOCK(Socket)); - { - /* Fail */ - ErrorCode = WSAEOPNOTSUPP; - goto error; - } - - /* If the socket is already listening, do nothing */ - if (Socket->SharedData.Listening) - { - /* Return happily */ - ErrorCode = NO_ERROR; - goto error; - } - else if (Socket->SharedData.State != SocketConnected) - { - /* If we're not connected, fail */ - ErrorCode = WSAEINVAL; - goto error; - } - - /* Set Up Listen Structure */ - ListenData.UseSAN = SockSanEnabled; - ListenData.UseDelayedAcceptance = Socket->SharedData.UseDelayedAcceptance; - ListenData.Backlog = Backlog; - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_START_LISTEN, - &ListenData, - sizeof(ListenData), - NULL, - 0); - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion outside the lock */ - LeaveCriticalSection(&Socket->Lock); - SockWaitForSingleObject(ThreadData->EventHandle, - Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - EnterCriticalSection(&Socket->Lock); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - - /* Notify helper DLL */ - ErrorCode = SockNotifyHelperDll(Socket, WSH_NOTIFY_LISTEN); - if (ErrorCode != NO_ERROR) goto error; - - /* Set to Listening */ - Socket->SharedData.Listening = TRUE; - - /* Update context with AFD */ - ErrorCode = SockSetHandleContext(Socket); - if (ErrorCode != NO_ERROR) goto error; - -error: - /* Check if we have a socket here */ - if (Socket) - { - /* Release the lock and dereference */ - LeaveCriticalSection(&Socket->Lock); - SockDereferenceSocket(Socket); - } - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -INT -WSPAPI -WSPListen(SOCKET Handle, - INT Backlog, - LPINT lpErrno) -{ - IO_STATUS_BLOCK IoStatusBlock; - AFD_LISTEN_DATA ListenData; - PSOCKET_INFORMATION Socket; - PWINSOCK_TEB_DATA ThreadData; - INT ErrorCode; - NTSTATUS Status; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* If the socket is connection-less, fail */ - if (MSAFD_IS_DGRAM_SOCK(Socket)); - { - /* Fail */ - ErrorCode = WSAEOPNOTSUPP; - goto error; - } - - /* If the socket is already listening, do nothing */ - if (Socket->SharedData.Listening) - { - /* Return happily */ - ErrorCode = NO_ERROR; - goto error; - } - else if (Socket->SharedData.State != SocketConnected) - { - /* If we're not connected, fail */ - ErrorCode = WSAEINVAL; - goto error; - } - - /* Set Up Listen Structure */ - ListenData.UseSAN = SockSanEnabled; - ListenData.UseDelayedAcceptance = Socket->SharedData.UseDelayedAcceptance; - ListenData.Backlog = Backlog; - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_START_LISTEN, - &ListenData, - sizeof(ListenData), - NULL, - 0); - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion outside the lock */ - LeaveCriticalSection(&Socket->Lock); - SockWaitForSingleObject(ThreadData->EventHandle, - Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - EnterCriticalSection(&Socket->Lock); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - - /* Notify helper DLL */ - ErrorCode = SockNotifyHelperDll(Socket, WSH_NOTIFY_LISTEN); - if (ErrorCode != NO_ERROR) goto error; - - /* Set to Listening */ - Socket->SharedData.Listening = TRUE; - - /* Update context with AFD */ - ErrorCode = SockSetHandleContext(Socket); - if (ErrorCode != NO_ERROR) goto error; - -error: - /* Check if we have a socket here */ - if (Socket) - { - /* Release the lock and dereference */ - LeaveCriticalSection(&Socket->Lock); - SockDereferenceSocket(Socket); - } - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -INT -WSPAPI -WSPListen(SOCKET Handle, - INT Backlog, - LPINT lpErrno) -{ - IO_STATUS_BLOCK IoStatusBlock; - AFD_LISTEN_DATA ListenData; - PSOCKET_INFORMATION Socket; - PWINSOCK_TEB_DATA ThreadData; - INT ErrorCode; - NTSTATUS Status; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* If the socket is connection-less, fail */ - if (MSAFD_IS_DGRAM_SOCK(Socket)); - { - /* Fail */ - ErrorCode = WSAEOPNOTSUPP; - goto error; - } - - /* If the socket is already listening, do nothing */ - if (Socket->SharedData.Listening) - { - /* Return happily */ - ErrorCode = NO_ERROR; - goto error; - } - else if (Socket->SharedData.State != SocketConnected) - { - /* If we're not connected, fail */ - ErrorCode = WSAEINVAL; - goto error; - } - - /* Set Up Listen Structure */ - ListenData.UseSAN = SockSanEnabled; - ListenData.UseDelayedAcceptance = Socket->SharedData.UseDelayedAcceptance; - ListenData.Backlog = Backlog; - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_START_LISTEN, - &ListenData, - sizeof(ListenData), - NULL, - 0); - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion outside the lock */ - LeaveCriticalSection(&Socket->Lock); - SockWaitForSingleObject(ThreadData->EventHandle, - Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - EnterCriticalSection(&Socket->Lock); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - - /* Notify helper DLL */ - ErrorCode = SockNotifyHelperDll(Socket, WSH_NOTIFY_LISTEN); - if (ErrorCode != NO_ERROR) goto error; - - /* Set to Listening */ - Socket->SharedData.Listening = TRUE; - - /* Update context with AFD */ - ErrorCode = SockSetHandleContext(Socket); - if (ErrorCode != NO_ERROR) goto error; - -error: - /* Check if we have a socket here */ - if (Socket) - { - /* Release the lock and dereference */ - LeaveCriticalSection(&Socket->Lock); - SockDereferenceSocket(Socket); - } - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - diff --git a/dll/win32/mswsock/msafd/nspeprot.c b/dll/win32/mswsock/msafd/nspeprot.c index 77b3205c368..a1d368ea76d 100644 --- a/dll/win32/mswsock/msafd/nspeprot.c +++ b/dll/win32/mswsock/msafd/nspeprot.c @@ -80,249 +80,3 @@ SockLoadTransportList(PWSTR *TransportList) return NO_ERROR; } -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -INT -WSPAPI -SockLoadTransportList(PWSTR *TransportList) -{ - ULONG TransportListSize = 0; - HKEY KeyHandle; - INT ErrorCode; - - /* Open the Transports Key */ - ErrorCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE, - L"SYSTEM\\CurrentControlSet\\Services\\Winsock\\Parameters", - 0, - KEY_READ, - &KeyHandle); - - /* Check for error */ - if (ErrorCode != NO_ERROR) return ErrorCode; - - /* Get the Transport List Size */ - ErrorCode = RegQueryValueExW(KeyHandle, - L"Transports", - NULL, - NULL, - NULL, - &TransportListSize); - - /* Check for error */ - if ((ErrorCode != ERROR_MORE_DATA) && (ErrorCode != NO_ERROR)) - { - /* Close key and fail */ - RegCloseKey(KeyHandle); - return ErrorCode; - } - - /* Allocate Memory for the Transport List */ - *TransportList = SockAllocateHeapRoutine(SockPrivateHeap, - 0, - TransportListSize); - - /* Check for error */ - if (!(*TransportList)) - { - /* Close key and fail */ - RegCloseKey(KeyHandle); - return ERROR_NOT_ENOUGH_MEMORY; - } - - /* Get the Transports */ - ErrorCode = RegQueryValueExW(KeyHandle, - L"Transports", - NULL, - NULL, - (LPBYTE)*TransportList, - &TransportListSize); - - /* Check for error */ - if ((ErrorCode != ERROR_MORE_DATA) && (ErrorCode != NO_ERROR)) - { - /* Close key and fail */ - RegCloseKey(KeyHandle); - return ErrorCode; - } - - /* Close key and return */ - RegCloseKey(KeyHandle); - return NO_ERROR; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -INT -WSPAPI -SockLoadTransportList(PWSTR *TransportList) -{ - ULONG TransportListSize = 0; - HKEY KeyHandle; - INT ErrorCode; - - /* Open the Transports Key */ - ErrorCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE, - L"SYSTEM\\CurrentControlSet\\Services\\Winsock\\Parameters", - 0, - KEY_READ, - &KeyHandle); - - /* Check for error */ - if (ErrorCode != NO_ERROR) return ErrorCode; - - /* Get the Transport List Size */ - ErrorCode = RegQueryValueExW(KeyHandle, - L"Transports", - NULL, - NULL, - NULL, - &TransportListSize); - - /* Check for error */ - if ((ErrorCode != ERROR_MORE_DATA) && (ErrorCode != NO_ERROR)) - { - /* Close key and fail */ - RegCloseKey(KeyHandle); - return ErrorCode; - } - - /* Allocate Memory for the Transport List */ - *TransportList = SockAllocateHeapRoutine(SockPrivateHeap, - 0, - TransportListSize); - - /* Check for error */ - if (!(*TransportList)) - { - /* Close key and fail */ - RegCloseKey(KeyHandle); - return ERROR_NOT_ENOUGH_MEMORY; - } - - /* Get the Transports */ - ErrorCode = RegQueryValueExW(KeyHandle, - L"Transports", - NULL, - NULL, - (LPBYTE)*TransportList, - &TransportListSize); - - /* Check for error */ - if ((ErrorCode != ERROR_MORE_DATA) && (ErrorCode != NO_ERROR)) - { - /* Close key and fail */ - RegCloseKey(KeyHandle); - return ErrorCode; - } - - /* Close key and return */ - RegCloseKey(KeyHandle); - return NO_ERROR; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -INT -WSPAPI -SockLoadTransportList(PWSTR *TransportList) -{ - ULONG TransportListSize = 0; - HKEY KeyHandle; - INT ErrorCode; - - /* Open the Transports Key */ - ErrorCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE, - L"SYSTEM\\CurrentControlSet\\Services\\Winsock\\Parameters", - 0, - KEY_READ, - &KeyHandle); - - /* Check for error */ - if (ErrorCode != NO_ERROR) return ErrorCode; - - /* Get the Transport List Size */ - ErrorCode = RegQueryValueExW(KeyHandle, - L"Transports", - NULL, - NULL, - NULL, - &TransportListSize); - - /* Check for error */ - if ((ErrorCode != ERROR_MORE_DATA) && (ErrorCode != NO_ERROR)) - { - /* Close key and fail */ - RegCloseKey(KeyHandle); - return ErrorCode; - } - - /* Allocate Memory for the Transport List */ - *TransportList = SockAllocateHeapRoutine(SockPrivateHeap, - 0, - TransportListSize); - - /* Check for error */ - if (!(*TransportList)) - { - /* Close key and fail */ - RegCloseKey(KeyHandle); - return ERROR_NOT_ENOUGH_MEMORY; - } - - /* Get the Transports */ - ErrorCode = RegQueryValueExW(KeyHandle, - L"Transports", - NULL, - NULL, - (LPBYTE)*TransportList, - &TransportListSize); - - /* Check for error */ - if ((ErrorCode != ERROR_MORE_DATA) && (ErrorCode != NO_ERROR)) - { - /* Close key and fail */ - RegCloseKey(KeyHandle); - return ErrorCode; - } - - /* Close key and return */ - RegCloseKey(KeyHandle); - return NO_ERROR; -} - diff --git a/dll/win32/mswsock/msafd/proc.c b/dll/win32/mswsock/msafd/proc.c index 3621f195071..4e7ba97efeb 100644 --- a/dll/win32/mswsock/msafd/proc.c +++ b/dll/win32/mswsock/msafd/proc.c @@ -1156,3477 +1156,3 @@ SockDeleteRwLock(IN PSOCK_RW_LOCK Lock) return RtlDeleteCriticalSection(&Lock->Lock); } -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -SOCK_RW_LOCK SocketGlobalLock; - -/* FUNCTIONS *****************************************************************/ - -VOID -WSPAPI -SockDestroySocket(PSOCKET_INFORMATION Socket) -{ - /* Dereference its helper DLL */ - SockDereferenceHelperDll(Socket->HelperData); - - /* Delete the lock */ - DeleteCriticalSection(&Socket->Lock); - - /* Free the socket */ - RtlFreeHeap(SockPrivateHeap, 0, Socket); -} - -VOID -__inline -WSPAPI -SockDereferenceSocket(IN PSOCKET_INFORMATION Socket) -{ - /* Dereference and see if it's the last count */ - if (!InterlockedDecrement(&Socket->WshContext.RefCount)) - { - /* Destroy the socket */ - SockDestroySocket(Socket); - } -} - -PSOCKET_INFORMATION -WSPAPI -SockImportHandle(IN SOCKET Handle) -{ - PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; - PWAH_HANDLE WahHandle; - NTSTATUS Status; - ULONG ContextSize; - IO_STATUS_BLOCK IoStatusBlock; - PSOCKET_INFORMATION ImportedSocket = NULL; - UNICODE_STRING TransportName; - - /* Acquire the global lock */ - SockAcquireRwLockExclusive(&SocketGlobalLock); - - /* Make sure that the handle is still invalid */ - WahHandle = WahReferenceContextByHandle(SockContextTable, (HANDLE)Handle); - if (WahHandle) - { - /* Some other thread imported it by now, release the lock and return */ - SockReleaseRwLockExclusive(&SocketGlobalLock); - return (PSOCKET_INFORMATION)WahHandle; - } - - /* Setup the NULL name for possible cleanup later */ - RtlInitUnicodeString(&TransportName, NULL); - - /* Call AFD to get the context size */ - Status = NtDeviceIoControlFile((HANDLE)Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_GET_CONTEXT_SIZE, - NULL, - 0, - &ContextSize, - sizeof(ContextSize)); - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion */ - SockWaitForSingleObject(ThreadData->EventHandle, - Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Make sure we didn't fail, and that this is a valid context */ - if (!NT_SUCCESS(Status) || (ContextSize < sizeof(SOCK_SHARED_INFO))) - { - /* Fail (the error handler will convert to Win32 Status) */ - goto error; - } - -error: - /* Release the lock */ - SockReleaseRwLockExclusive(&SocketGlobalLock); - - return ImportedSocket; -} - -INT -WSPAPI -SockSetInformation(IN PSOCKET_INFORMATION Socket, - IN ULONG AfdInformationClass, - IN PBOOLEAN Boolean OPTIONAL, - IN PULONG Ulong OPTIONAL, - IN PLARGE_INTEGER LargeInteger OPTIONAL) -{ - IO_STATUS_BLOCK IoStatusBlock; - AFD_INFO AfdInfo; - NTSTATUS Status; - PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; - - /* Set Info Class */ - AfdInfo.InformationClass = AfdInformationClass; - - /* Set Information */ - if (Boolean) - { - AfdInfo.Information.Boolean = *Boolean; - } - else if (Ulong) - { - AfdInfo.Information.Ulong = *Ulong; - } - else - { - AfdInfo.Information.LargeInteger = *LargeInteger; - } - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_GET_INFO, - &AfdInfo, - sizeof(AfdInfo), - NULL, - 0); - /* Check if we have to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for the operation to finish */ - SockWaitForSingleObject(ThreadData->EventHandle, - Socket->Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Handle failure */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - return NtStatusToSocketError(Status); - } - - /* Return to caller */ - return NO_ERROR; -} - -INT -WSPAPI -SockGetInformation(IN PSOCKET_INFORMATION Socket, - IN ULONG AfdInformationClass, - IN PVOID ExtraData OPTIONAL, - IN ULONG ExtraDataSize, - IN OUT PBOOLEAN Boolean OPTIONAL, - IN OUT PULONG Ulong OPTIONAL, - IN OUT PLARGE_INTEGER LargeInteger OPTIONAL) -{ - ULONG InfoLength; - IO_STATUS_BLOCK IoStatusBlock; - PAFD_INFO AfdInfo; - AFD_INFO InfoData; - NTSTATUS Status; - PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; - - /* Check if extra data is there */ - if (ExtraData && ExtraDataSize) - { - /* Allocate space for it */ - InfoLength = sizeof(InfoData) + ExtraDataSize; - AfdInfo = (PAFD_INFO)SockAllocateHeapRoutine(SockPrivateHeap, - 0, - InfoLength); - if (!AfdInfo) return WSAENOBUFS; - - /* Copy the extra data */ - RtlCopyMemory(AfdInfo + 1, ExtraData, ExtraDataSize); - } - else - { - /* Use local buffer */ - AfdInfo = &InfoData; - InfoLength = sizeof(InfoData); - } - - /* Set Info Class */ - AfdInfo->InformationClass = AfdInformationClass; - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_GET_INFO, - &InfoData, - InfoLength, - &InfoData, - sizeof(InfoData)); - /* Check if we have to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for the operation to finish */ - SockWaitForSingleObject(ThreadData->EventHandle, - Socket->Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Handle failure */ - if (!NT_SUCCESS(Status)) - { - /* Check if we have to free the data */ - if (AfdInfo != &InfoData) RtlFreeHeap(SockPrivateHeap, 0, AfdInfo); - - /* Fail */ - return NtStatusToSocketError(Status); - } - - /* Return Information */ - if (Boolean) - { - *Boolean = AfdInfo->Information.Boolean; - } - else if (Ulong) - { - *Ulong = AfdInfo->Information.Ulong; - } - else - { - *LargeInteger = AfdInfo->Information.LargeInteger; - } - - /* Check if we have to free the data */ - if (AfdInfo != &InfoData) RtlFreeHeap(SockPrivateHeap, 0, AfdInfo); - - /* Return to caller */ - return NO_ERROR; -} - -INT -WSPAPI -SockSetHandleContext(IN PSOCKET_INFORMATION Socket) -{ - IO_STATUS_BLOCK IoStatusBlock; - CHAR ContextData[256]; - PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; - PVOID Context; - ULONG_PTR ContextPos; - ULONG ContextLength; - INT HelperContextLength; - INT ErrorCode; - NTSTATUS Status; - - /* Find out how big the helper DLL context is */ - ErrorCode = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, - Socket->Handle, - Socket->TdiAddressHandle, - Socket->TdiConnectionHandle, - SOL_INTERNAL, - SO_CONTEXT, - NULL, - &HelperContextLength); - - /* Calculate the total space needed */ - ContextLength = sizeof(SOCK_SHARED_INFO) + - 2 * Socket->HelperData->MaxWSAddressLength + - sizeof(ULONG) + HelperContextLength; - - /* See if our stack can hold it */ - if (ContextLength <= sizeof(ContextData)) - { - /* Use our stack */ - Context = ContextData; - } - else - { - /* Allocate from heap */ - Context = SockAllocateHeapRoutine(SockPrivateHeap, 0, ContextLength); - if (!Context) return WSAENOBUFS; - } - - /* - * Create Context, this includes: - * Shared Socket Data, Helper Context Length, Local and Remote Addresses - * and finally the actual helper context. - */ - ContextPos = (ULONG_PTR)Context; - RtlCopyMemory((PVOID)ContextPos, - &Socket->SharedData, - sizeof(SOCK_SHARED_INFO)); - ContextPos += sizeof(SOCK_SHARED_INFO); - *(PULONG)ContextPos = HelperContextLength; - ContextPos += sizeof(ULONG); - RtlCopyMemory((PVOID)ContextPos, - Socket->LocalAddress, - Socket->HelperData->MaxWSAddressLength); - ContextPos += Socket->HelperData->MaxWSAddressLength; - RtlCopyMemory((PVOID)ContextPos, - Socket->RemoteAddress, - Socket->HelperData->MaxWSAddressLength); - ContextPos += Socket->HelperData->MaxWSAddressLength; - - /* Now get the helper context */ - ErrorCode = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, - Socket->Handle, - Socket->TdiAddressHandle, - Socket->TdiConnectionHandle, - SOL_INTERNAL, - SO_CONTEXT, - (PVOID)ContextPos, - &HelperContextLength); - /* Now give it to AFD */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_SET_CONTEXT, - Context, - ContextLength, - NULL, - 0); - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion */ - SockWaitForSingleObject(ThreadData->EventHandle, - Socket->Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check if we need to free from heap */ - if (Context != ContextData) RtlFreeHeap(SockPrivateHeap, 0, Context); - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Convert and return error code */ - ErrorCode = NtStatusToSocketError(Status); - return ErrorCode; - } - - /* Return success */ - return NO_ERROR; -} - -INT -WSPAPI -SockIsAddressConsistentWithConstrainedGroup(IN PSOCKET_INFORMATION Socket, - IN GROUP Group, - IN PSOCKADDR SocketAddress, - IN INT SocketAddressLength) -{ - PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; - INT ErrorCode; - PAFD_VALIDATE_GROUP_DATA ValidateGroupData; - NTSTATUS Status; - IO_STATUS_BLOCK IoStatusBlock; - ULONG ValidateGroupSize; - CHAR ValidateBuffer[sizeof(AFD_VALIDATE_GROUP_DATA) + MAX_TDI_ADDRESS_LENGTH]; - - /* Calculate the length of the buffer */ - ValidateGroupSize = sizeof(AFD_VALIDATE_GROUP_DATA) + - sizeof(TRANSPORT_ADDRESS) + - Socket->HelperData->MaxTDIAddressLength; - - /* Check if our stack buffer is large enough */ - if (ValidateGroupSize <= sizeof(ValidateBuffer)) - { - /* Use the stack */ - ValidateGroupData = (PVOID)ValidateBuffer; - } - else - { - /* Allocate from heap */ - ValidateGroupData = SockAllocateHeapRoutine(SockPrivateHeap, - 0, - ValidateGroupSize); - if (!ValidateGroupData) return WSAENOBUFS; - } - - /* Convert the address to TDI format */ - ErrorCode = SockBuildTdiAddress(&ValidateGroupData->Address, - SocketAddress, - SocketAddressLength); - if (ErrorCode != NO_ERROR) return ErrorCode; - - /* Tell AFD which group to check, and let AFD validate it */ - ValidateGroupData->GroupId = Group; - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_VALIDATE_GROUP, - ValidateGroupData, - ValidateGroupSize, - NULL, - 0); - - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion */ - SockWaitForSingleObject(ThreadData->EventHandle, - Socket->Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check if we need to free the data from heap */ - if (ValidateGroupData != (PVOID)ValidateBuffer) - { - /* Free it */ - RtlFreeHeap(SockPrivateHeap, 0, ValidateGroupData); - } - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - return NtStatusToSocketError(Status); - } - - /* Return success */ - return NO_ERROR; -} - - -INT -WSPAPI -SockGetTdiHandles(IN PSOCKET_INFORMATION Socket) -{ - AFD_TDI_HANDLE_DATA TdiHandleInfo; - NTSTATUS Status; - IO_STATUS_BLOCK IoStatusBlock; - ULONG InfoType = 0; - PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; - - /* See which handle(s) we need */ - if (!Socket->TdiAddressHandle) InfoType |= AFD_ADDRESS_HANDLE; - if (!Socket->TdiConnectionHandle) InfoType |= AFD_CONNECTION_HANDLE; - - /* Make sure we need one */ - if (!InfoType) return NO_ERROR; - - /* Call AFD */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_GET_TDI_HANDLES, - &InfoType, - sizeof(InfoType), - &TdiHandleInfo, - sizeof(TdiHandleInfo)); - /* Check if we shoudl wait */ - if (Status == STATUS_PENDING) - { - /* Wait on it */ - SockWaitForSingleObject(ThreadData->EventHandle, - Socket->Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - - /* Update status */ - Status = IoStatusBlock.Status; - } - - /* Check for success */ - if (!NT_SUCCESS(Status)) return NtStatusToSocketError(Status); - - /* Return handles */ - if (!Socket->TdiAddressHandle) - { - Socket->TdiAddressHandle = TdiHandleInfo.TdiAddressHandle; - } - if (!Socket->TdiConnectionHandle) - { - Socket->TdiConnectionHandle = TdiHandleInfo.TdiConnectionHandle; - } - - /* Return */ - return NO_ERROR; -} - -BOOL -WSPAPI -SockWaitForSingleObject(IN HANDLE Handle, - IN SOCKET SocketHandle, - IN DWORD BlockingFlags, - IN DWORD TimeoutFlags) -{ - LARGE_INTEGER Timeout, CurrentTime, DueTime; - NTSTATUS Status; - PSOCKET_INFORMATION Socket = NULL; - BOOLEAN CallHook, UseTimeout; - LPBLOCKINGCALLBACK BlockingHook; - DWORD_PTR Context; - INT ErrorCode; - PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; - - /* Start with a simple 0.5 second wait */ - Timeout.QuadPart = Int32x32To64(-10000, 500); - Status = NtWaitForSingleObject(Handle, TRUE, &Timeout); - if (Status == STATUS_SUCCESS) return TRUE; - - /* Check if our flags require the socket structure */ - if ((BlockingFlags == MAYBE_BLOCKING_HOOK) || - (BlockingFlags == ALWAYS_BLOCKING_HOOK) || - (TimeoutFlags == SEND_TIMEOUT) || - (TimeoutFlags == RECV_TIMEOUT)) - { - /* Get the socket */ - Socket = SockFindAndReferenceSocket(SocketHandle, FALSE); - if (!Socket) - { - /* We must be waiting on a non-socket for some reason? */ - NtWaitForSingleObject(Handle, TRUE, NULL); - return TRUE; - } - } - - /* Check the blocking flags */ - if (BlockingFlags == ALWAYS_BLOCKING_HOOK) - { - /* Always call it */ - CallHook = TRUE; - } - else if (BlockingFlags == MAYBE_BLOCKING_HOOK) - { - /* Check if we have to call it */ - CallHook = !Socket->SharedData.NonBlocking; - } - else if (BlockingFlags == NO_BLOCKING_HOOK) - { - /* Never call it*/ - CallHook = FALSE; - } - else - { - if (Socket) SockDereferenceSocket(Socket); - return FALSE; - } - - /* Check if we call it */ - if (CallHook) - { - /* Check if it actually exists */ - SockUpcallTable->lpWPUQueryBlockingCallback(Socket->SharedData.CatalogEntryId, - &BlockingHook, - &Context, - &ErrorCode); - - /* See if we'll call it */ - CallHook = (BlockingHook != NULL); - } - - /* Now check the timeout flags */ - if (TimeoutFlags == NO_TIMEOUT) - { - /* None at all */ - UseTimeout = FALSE; - } - else if (TimeoutFlags == SEND_TIMEOUT) - { - /* See if there's a Send Timeout */ - if (Socket->SharedData.SendTimeout) - { - /* Use it */ - UseTimeout = TRUE; - Timeout = RtlEnlargedIntegerMultiply(Socket->SharedData.SendTimeout, - 10 * 1000); - } - else - { - /* There isn't any */ - UseTimeout = FALSE; - } - } - else if (TimeoutFlags == RECV_TIMEOUT) - { - /* See if there's a Receive Timeout */ - if (Socket->SharedData.RecvTimeout) - { - /* Use it */ - UseTimeout = TRUE; - Timeout = RtlEnlargedIntegerMultiply(Socket->SharedData.RecvTimeout, - 10 * 1000); - } - else - { - /* There isn't any */ - UseTimeout = FALSE; - } - } - else - { - if (Socket) SockDereferenceSocket(Socket); - return FALSE; - } - - /* We don't need the socket anymore */ - if (Socket) SockDereferenceSocket(Socket); - - /* Check for timeout */ - if (UseTimeout) - { - /* Calculate the absolute time when the wait ends */ - Status = NtQuerySystemTime(&CurrentTime); - DueTime.QuadPart = CurrentTime.QuadPart + Timeout.QuadPart; - } - else - { - /* Infinite wait */ - DueTime.LowPart = -1; - DueTime.HighPart = 0x7FFFFFFF; - } - - /* Check for blocking hook call */ - if (CallHook) - { - /* We're calling it, so we won't actually be waiting */ - Timeout.LowPart = -1; - Timeout.HighPart = -1; - } - else - { - /* We'll be waiting till the Due Time */ - Timeout = DueTime; - } - - /* Now write data to the TEB so we'll know what's going on */ - ThreadData->CancelIo = FALSE; - ThreadData->SocketHandle = SocketHandle; - - /* Start wait loop */ - do - { - /* Call the hook */ - if (CallHook) (BlockingHook(Context)); - - /* Check if we were cancelled */ - if (ThreadData->CancelIo) - { - /* Infinite timeout and wait for official cancel */ - Timeout.LowPart = -1; - Timeout.HighPart = 0x7FFFFFFF; - } - else - { - /* Check if we're due */ - Status = NtQuerySystemTime(&CurrentTime); - if (CurrentTime.QuadPart > DueTime.QuadPart) - { - /* We're out */ - Status = STATUS_TIMEOUT; - break; - } - } - - /* Do the actual wait */ - Status = NtWaitForSingleObject(Handle, TRUE, &Timeout); - } while ((Status == STATUS_USER_APC) || - (Status == STATUS_ALERTED) || - (Status == STATUS_TIMEOUT)); - - /* Reset thread data */ - ThreadData->SocketHandle = INVALID_SOCKET; - - /* Return to caller */ - if (Status == STATUS_SUCCESS) return TRUE; - return FALSE; -} - -PSOCKET_INFORMATION -WSPAPI -SockFindAndReferenceSocket(IN SOCKET Handle, - IN BOOLEAN Import) -{ - PWAH_HANDLE WahHandle; - - /* Get it from our table and return it */ - WahHandle = WahReferenceContextByHandle(SockContextTable, (HANDLE)Handle); - if (WahHandle) return (PSOCKET_INFORMATION)WahHandle; - - /* Couldn't find it, shoudl we import it? */ - if (Import) return SockImportHandle(Handle); - - /* Nothing found */ - return NULL; -} - -INT -WSPAPI -SockBuildTdiAddress(OUT PTRANSPORT_ADDRESS TdiAddress, - IN PSOCKADDR Sockaddr, - IN INT SockaddrLength) -{ - /* Setup the TDI Address */ - TdiAddress->TAAddressCount = 1; - TdiAddress->Address[0].AddressLength = (USHORT)SockaddrLength - - sizeof(Sockaddr->sa_family); - - /* Copy it */ - RtlCopyMemory(&TdiAddress->Address[0].AddressType, Sockaddr, SockaddrLength); - - /* Return */ - return NO_ERROR; -} - -INT -WSPAPI -SockBuildSockaddr(OUT PSOCKADDR Sockaddr, - OUT PINT SockaddrLength, - IN PTRANSPORT_ADDRESS TdiAddress) -{ - /* Calculate the length it will take */ - *SockaddrLength = TdiAddress->Address[0].AddressLength + - sizeof(Sockaddr->sa_family); - - /* Copy it */ - RtlCopyMemory(Sockaddr, &TdiAddress->Address[0].AddressType, *SockaddrLength); - - /* Return */ - return NO_ERROR; -} - -BOOLEAN -WSPAPI -SockIsSocketConnected(IN PSOCKET_INFORMATION Socket) -{ - LARGE_INTEGER Timeout; - PVOID Context; - PVOID AsyncCallback; - IO_STATUS_BLOCK IoStatusBlock; - NTSTATUS Status; - - /* Check if there is an async connect in progress, but still unprocessed */ - while ((Socket->AsyncData) && - (Socket->AsyncData->IoStatusBlock.Status != STATUS_PENDING)) - { - /* The socket will be locked, release it */ - LeaveCriticalSection(&Socket->Lock); - - /* Setup the timeout and wait on completion */ - Timeout.QuadPart = 0; - Status = NtRemoveIoCompletion(SockAsyncQueuePort, - &AsyncCallback, - &Context, - &IoStatusBlock, - &Timeout); - - /* Check for success */ - if (Status == STATUS_SUCCESS) - { - /* Check if we're supposed to terminate */ - if (AsyncCallback != (PVOID)-1) - { - /* Handle the Async */ - SockHandleAsyncIndication(AsyncCallback, Context, &IoStatusBlock); - } - else - { - /* Terminate it */ - Status = NtSetIoCompletion(SockAsyncQueuePort, - (PVOID)-1, - (PVOID)-1, - 0, - 0); - - /* Acquire the lock and break out */ - EnterCriticalSection(&Socket->Lock); - break; - } - } - - /* Acquire the socket lock again */ - EnterCriticalSection(&Socket->Lock); - } - - /* Check if it's already connected */ - if (Socket->SharedData.State == SocketConnected) return TRUE; - return FALSE; -} - -VOID -WSPAPI -SockCancelIo(IN SOCKET Handle) -{ - IO_STATUS_BLOCK IoStatusBlock; - NTSTATUS Status; - - /* Cancel the I/O */ - Status = NtCancelIoFile((HANDLE)Handle, &IoStatusBlock); -} - -VOID -WSPAPI -SockIoCompletion(IN PVOID ApcContext, - IN PIO_STATUS_BLOCK IoStatusBlock, - DWORD Reserved) -{ - LPWSAOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine = ApcContext; - INT ErrorCode; - DWORD BytesSent; - DWORD Flags = 0; - LPWSAOVERLAPPED lpOverlapped; - PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; - - /* Check if this was an error */ - if (NT_ERROR(IoStatusBlock->Status)) - { - /* Check if it was anything but a simple cancel */ - if (IoStatusBlock->Status != STATUS_CANCELLED) - { - /* Convert it */ - ErrorCode = NtStatusToSocketError(IoStatusBlock->Status); - } - else - { - /* Use the right error */ - ErrorCode = WSA_OPERATION_ABORTED; - } - - /* Either ways, nothing was done */ - BytesSent = 0; - } - else - { - /* No error and check how many bytes were sent */ - ErrorCode = NO_ERROR; - BytesSent = PtrToUlong(IoStatusBlock->Information); - - /* Check the status */ - if (IoStatusBlock->Status == STATUS_BUFFER_OVERFLOW) - { - /* This was an error */ - ErrorCode = WSAEMSGSIZE; - } - else if (IoStatusBlock->Status == STATUS_RECEIVE_PARTIAL) - { - /* Partial receive */ - Flags = MSG_PARTIAL; - } - else if (IoStatusBlock->Status == STATUS_RECEIVE_EXPEDITED) - { - /* OOB receive */ - Flags = MSG_OOB; - } - else if (IoStatusBlock->Status == STATUS_RECEIVE_PARTIAL_EXPEDITED) - { - /* Partial OOB receive */ - Flags = MSG_OOB | MSG_PARTIAL; - } - } - - /* Get the overlapped structure */ - lpOverlapped = CONTAINING_RECORD(IoStatusBlock, WSAOVERLAPPED, Internal); - - /* Call it */ - CompletionRoutine(ErrorCode, BytesSent, lpOverlapped, Flags); - - /* Decrease pending APCs */ - ThreadData->PendingAPCs--; - InterlockedDecrement(&SockProcessPendingAPCCount); -} - -VOID -WSPAPI -SockpWaitForReaderCount(IN PSOCK_RW_LOCK Lock) -{ - NTSTATUS Status; - LARGE_INTEGER Timeout; - - /* Switch threads to see if the lock gets released that way */ - Timeout.QuadPart = 0; - NtDelayExecution(FALSE, &Timeout); - if (Lock->ReaderCount == -2) return; - - /* Either the thread isn't executing (priority inversion) or it's a hog */ - if (!Lock->WriterWaitEvent) - { - /* We don't have an event to wait on yet, allocate it */ - Status = NtCreateEvent(&Lock->WriterWaitEvent, - EVENT_ALL_ACCESS, - NULL, - SynchronizationEvent, - FALSE); - if (!NT_SUCCESS(Status)) - { - /* We can't get an event, do a manual loop */ - Timeout.QuadPart = Int32x32To64(1000, -100); - while (Lock->ReaderCount != -2) NtDelayExecution(FALSE, &Timeout); - } - } - - /* We have en event, now increment the reader count to signal them */ - if (InterlockedIncrement(&Lock->ReaderCount) != -1) - { - /* Wait for them to signal us */ - NtWaitForSingleObject(&Lock->WriterWaitEvent, FALSE, NULL); - } - - /* Finally it's free */ - Lock->ReaderCount = -2; -} - -NTSTATUS -WSPAPI -SockInitializeRwLockAndSpinCount(IN PSOCK_RW_LOCK Lock, - IN ULONG SpinCount) -{ - NTSTATUS Status; - - /* check if this is a special event create request */ - if (SpinCount & 0x80000000) - { - /* Create the event */ - Status = NtCreateEvent(&Lock->WriterWaitEvent, - EVENT_ALL_ACCESS, - NULL, - SynchronizationEvent, - FALSE); - if (!NT_SUCCESS(Status)) return Status; - } - - /* Initialize the lock */ - Status = RtlInitializeCriticalSectionAndSpinCount(&Lock->Lock, SpinCount); - if (NT_SUCCESS(Status)) - { - /* Initialize our structure */ - Lock->ReaderCount = 0; - } - else if (Lock->WriterWaitEvent) - { - /* We failed, close the event if we had one */ - NtClose(Lock->WriterWaitEvent); - Lock->WriterWaitEvent = NULL; - } - - /* Return status */ - return Status; -} - -VOID -WSPAPI -SockAcquireRwLockExclusive(IN PSOCK_RW_LOCK Lock) -{ - LONG Count, NewCount; - ULONG_PTR SpinCount; - - /* Acquire the lock */ - RtlEnterCriticalSection(&Lock->Lock); - - /* Check for ReaderCount */ - if (Lock->ReaderCount >= 0) - { - /* Loop while trying to change the count */ - do - { - /* Get the reader count */ - Count = Lock->ReaderCount; - - /* Modify the count so ReaderCount know that a writer is waiting */ - NewCount = -Count - 2; - } while (InterlockedCompareExchange(&Lock->ReaderCount, - NewCount, - Count) != Count); - - /* Check if some ReaderCount are still active */ - if (NewCount != -2) - { - /* Get the spincount of the CS */ - SpinCount = Lock->Lock.SpinCount; - - /* Loop until they are done */ - while (Lock->ReaderCount != -2) - { - /* Check if the CS has a spin count */ - if (SpinCount) - { - /* Spin on it */ - SpinCount--; - } - else - { - /* Do a full wait for ReaderCount */ - SockpWaitForReaderCount(Lock); - break; - } - } - } - } - else - { - /* Acquiring it again, decrement the count to handle this */ - Lock->ReaderCount--; - } -} - -VOID -WSPAPI -SockAcquireRwLockShared(IN PSOCK_RW_LOCK Lock) -{ - BOOL GotLock = FALSE; - LONG Count, NewCount; - - /* Start acquire loop */ - do - { - /* Get the current count */ - Count = Lock->ReaderCount; - - /* Check if a writer is active */ - if (Count < 0) - { - /* Acquire the lock (this will wait for the writer) */ - RtlEnterCriticalSection(&Lock->Lock); - GotLock = TRUE; - - /* Get the counter again */ - Count = Lock->ReaderCount; - if (Count < 0) - { - /* It's still below 0, so this is a recursive acquire */ - NewCount = Count - 1; - } - else - { - /* Increase the count since the writer has finished */ - NewCount = Count + 1; - } - } - else - { - /* No writers are active, increase count */ - NewCount = Count + 1; - } - - /* Update the count */ - NewCount = InterlockedCompareExchange(&Lock->ReaderCount, - NewCount, - Count); - - /* Check if we got the lock */ - if (GotLock) - { - /* Release it */ - RtlLeaveCriticalSection(&Lock->Lock); - GotLock = FALSE; - } - } while (NewCount != Count); -} - -VOID -WSPAPI -SockReleaseRwLockExclusive(IN PSOCK_RW_LOCK Lock) -{ - /* Increase the reader count and check if it's a recursive acquire */ - if (++Lock->ReaderCount == -1) - { - /* This release is the final one, so unhack the reader count */ - Lock->ReaderCount = 0; - } - - /* Leave the RTL CS */ - RtlLeaveCriticalSection(&Lock->Lock); -} - -VOID -WSPAPI -SockReleaseRwLockShared(IN PSOCK_RW_LOCK Lock) -{ - LONG NewCount, Count = Lock->ReaderCount; - - /* Start release loop */ - while (TRUE) - { - /* Check if writers are using the lock */ - if (Count > 0) - { - /* Lock is free, decrement the count */ - NewCount = Count - 1; - } - else - { - /* Lock is busy, increment the count */ - NewCount = Count + 1; - } - - /* Update the count */ - if (InterlockedCompareExchange(&Lock->ReaderCount, NewCount, Count) == Count) - { - /* Count changed sucesfully, was this the last reader? */ - if (NewCount == -1) - { - /* It was, we need to tell the writer about it */ - NtSetEvent(Lock->WriterWaitEvent, NULL); - } - break; - } - } -} - -NTSTATUS -WSPAPI -SockDeleteRwLock(IN PSOCK_RW_LOCK Lock) -{ - /* Check if there's an event */ - if (Lock->WriterWaitEvent) - { - /* Close it */ - NtClose(Lock->WriterWaitEvent); - Lock->WriterWaitEvent = NULL; - } - - /* Free the Crtitical Section */ - return RtlDeleteCriticalSection(&Lock->Lock); -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -SOCK_RW_LOCK SocketGlobalLock; - -/* FUNCTIONS *****************************************************************/ - -VOID -WSPAPI -SockDestroySocket(PSOCKET_INFORMATION Socket) -{ - /* Dereference its helper DLL */ - SockDereferenceHelperDll(Socket->HelperData); - - /* Delete the lock */ - DeleteCriticalSection(&Socket->Lock); - - /* Free the socket */ - RtlFreeHeap(SockPrivateHeap, 0, Socket); -} - -VOID -__inline -WSPAPI -SockDereferenceSocket(IN PSOCKET_INFORMATION Socket) -{ - /* Dereference and see if it's the last count */ - if (!InterlockedDecrement(&Socket->WshContext.RefCount)) - { - /* Destroy the socket */ - SockDestroySocket(Socket); - } -} - -PSOCKET_INFORMATION -WSPAPI -SockImportHandle(IN SOCKET Handle) -{ - PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; - PWAH_HANDLE WahHandle; - NTSTATUS Status; - ULONG ContextSize; - IO_STATUS_BLOCK IoStatusBlock; - PSOCKET_INFORMATION ImportedSocket = NULL; - UNICODE_STRING TransportName; - - /* Acquire the global lock */ - SockAcquireRwLockExclusive(&SocketGlobalLock); - - /* Make sure that the handle is still invalid */ - WahHandle = WahReferenceContextByHandle(SockContextTable, (HANDLE)Handle); - if (WahHandle) - { - /* Some other thread imported it by now, release the lock and return */ - SockReleaseRwLockExclusive(&SocketGlobalLock); - return (PSOCKET_INFORMATION)WahHandle; - } - - /* Setup the NULL name for possible cleanup later */ - RtlInitUnicodeString(&TransportName, NULL); - - /* Call AFD to get the context size */ - Status = NtDeviceIoControlFile((HANDLE)Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_GET_CONTEXT_SIZE, - NULL, - 0, - &ContextSize, - sizeof(ContextSize)); - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion */ - SockWaitForSingleObject(ThreadData->EventHandle, - Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Make sure we didn't fail, and that this is a valid context */ - if (!NT_SUCCESS(Status) || (ContextSize < sizeof(SOCK_SHARED_INFO))) - { - /* Fail (the error handler will convert to Win32 Status) */ - goto error; - } - -error: - /* Release the lock */ - SockReleaseRwLockExclusive(&SocketGlobalLock); - - return ImportedSocket; -} - -INT -WSPAPI -SockSetInformation(IN PSOCKET_INFORMATION Socket, - IN ULONG AfdInformationClass, - IN PBOOLEAN Boolean OPTIONAL, - IN PULONG Ulong OPTIONAL, - IN PLARGE_INTEGER LargeInteger OPTIONAL) -{ - IO_STATUS_BLOCK IoStatusBlock; - AFD_INFO AfdInfo; - NTSTATUS Status; - PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; - - /* Set Info Class */ - AfdInfo.InformationClass = AfdInformationClass; - - /* Set Information */ - if (Boolean) - { - AfdInfo.Information.Boolean = *Boolean; - } - else if (Ulong) - { - AfdInfo.Information.Ulong = *Ulong; - } - else - { - AfdInfo.Information.LargeInteger = *LargeInteger; - } - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_GET_INFO, - &AfdInfo, - sizeof(AfdInfo), - NULL, - 0); - /* Check if we have to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for the operation to finish */ - SockWaitForSingleObject(ThreadData->EventHandle, - Socket->Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Handle failure */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - return NtStatusToSocketError(Status); - } - - /* Return to caller */ - return NO_ERROR; -} - -INT -WSPAPI -SockGetInformation(IN PSOCKET_INFORMATION Socket, - IN ULONG AfdInformationClass, - IN PVOID ExtraData OPTIONAL, - IN ULONG ExtraDataSize, - IN OUT PBOOLEAN Boolean OPTIONAL, - IN OUT PULONG Ulong OPTIONAL, - IN OUT PLARGE_INTEGER LargeInteger OPTIONAL) -{ - ULONG InfoLength; - IO_STATUS_BLOCK IoStatusBlock; - PAFD_INFO AfdInfo; - AFD_INFO InfoData; - NTSTATUS Status; - PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; - - /* Check if extra data is there */ - if (ExtraData && ExtraDataSize) - { - /* Allocate space for it */ - InfoLength = sizeof(InfoData) + ExtraDataSize; - AfdInfo = (PAFD_INFO)SockAllocateHeapRoutine(SockPrivateHeap, - 0, - InfoLength); - if (!AfdInfo) return WSAENOBUFS; - - /* Copy the extra data */ - RtlCopyMemory(AfdInfo + 1, ExtraData, ExtraDataSize); - } - else - { - /* Use local buffer */ - AfdInfo = &InfoData; - InfoLength = sizeof(InfoData); - } - - /* Set Info Class */ - AfdInfo->InformationClass = AfdInformationClass; - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_GET_INFO, - &InfoData, - InfoLength, - &InfoData, - sizeof(InfoData)); - /* Check if we have to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for the operation to finish */ - SockWaitForSingleObject(ThreadData->EventHandle, - Socket->Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Handle failure */ - if (!NT_SUCCESS(Status)) - { - /* Check if we have to free the data */ - if (AfdInfo != &InfoData) RtlFreeHeap(SockPrivateHeap, 0, AfdInfo); - - /* Fail */ - return NtStatusToSocketError(Status); - } - - /* Return Information */ - if (Boolean) - { - *Boolean = AfdInfo->Information.Boolean; - } - else if (Ulong) - { - *Ulong = AfdInfo->Information.Ulong; - } - else - { - *LargeInteger = AfdInfo->Information.LargeInteger; - } - - /* Check if we have to free the data */ - if (AfdInfo != &InfoData) RtlFreeHeap(SockPrivateHeap, 0, AfdInfo); - - /* Return to caller */ - return NO_ERROR; -} - -INT -WSPAPI -SockSetHandleContext(IN PSOCKET_INFORMATION Socket) -{ - IO_STATUS_BLOCK IoStatusBlock; - CHAR ContextData[256]; - PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; - PVOID Context; - ULONG_PTR ContextPos; - ULONG ContextLength; - INT HelperContextLength; - INT ErrorCode; - NTSTATUS Status; - - /* Find out how big the helper DLL context is */ - ErrorCode = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, - Socket->Handle, - Socket->TdiAddressHandle, - Socket->TdiConnectionHandle, - SOL_INTERNAL, - SO_CONTEXT, - NULL, - &HelperContextLength); - - /* Calculate the total space needed */ - ContextLength = sizeof(SOCK_SHARED_INFO) + - 2 * Socket->HelperData->MaxWSAddressLength + - sizeof(ULONG) + HelperContextLength; - - /* See if our stack can hold it */ - if (ContextLength <= sizeof(ContextData)) - { - /* Use our stack */ - Context = ContextData; - } - else - { - /* Allocate from heap */ - Context = SockAllocateHeapRoutine(SockPrivateHeap, 0, ContextLength); - if (!Context) return WSAENOBUFS; - } - - /* - * Create Context, this includes: - * Shared Socket Data, Helper Context Length, Local and Remote Addresses - * and finally the actual helper context. - */ - ContextPos = (ULONG_PTR)Context; - RtlCopyMemory((PVOID)ContextPos, - &Socket->SharedData, - sizeof(SOCK_SHARED_INFO)); - ContextPos += sizeof(SOCK_SHARED_INFO); - *(PULONG)ContextPos = HelperContextLength; - ContextPos += sizeof(ULONG); - RtlCopyMemory((PVOID)ContextPos, - Socket->LocalAddress, - Socket->HelperData->MaxWSAddressLength); - ContextPos += Socket->HelperData->MaxWSAddressLength; - RtlCopyMemory((PVOID)ContextPos, - Socket->RemoteAddress, - Socket->HelperData->MaxWSAddressLength); - ContextPos += Socket->HelperData->MaxWSAddressLength; - - /* Now get the helper context */ - ErrorCode = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, - Socket->Handle, - Socket->TdiAddressHandle, - Socket->TdiConnectionHandle, - SOL_INTERNAL, - SO_CONTEXT, - (PVOID)ContextPos, - &HelperContextLength); - /* Now give it to AFD */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_SET_CONTEXT, - Context, - ContextLength, - NULL, - 0); - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion */ - SockWaitForSingleObject(ThreadData->EventHandle, - Socket->Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check if we need to free from heap */ - if (Context != ContextData) RtlFreeHeap(SockPrivateHeap, 0, Context); - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Convert and return error code */ - ErrorCode = NtStatusToSocketError(Status); - return ErrorCode; - } - - /* Return success */ - return NO_ERROR; -} - -INT -WSPAPI -SockIsAddressConsistentWithConstrainedGroup(IN PSOCKET_INFORMATION Socket, - IN GROUP Group, - IN PSOCKADDR SocketAddress, - IN INT SocketAddressLength) -{ - PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; - INT ErrorCode; - PAFD_VALIDATE_GROUP_DATA ValidateGroupData; - NTSTATUS Status; - IO_STATUS_BLOCK IoStatusBlock; - ULONG ValidateGroupSize; - CHAR ValidateBuffer[sizeof(AFD_VALIDATE_GROUP_DATA) + MAX_TDI_ADDRESS_LENGTH]; - - /* Calculate the length of the buffer */ - ValidateGroupSize = sizeof(AFD_VALIDATE_GROUP_DATA) + - sizeof(TRANSPORT_ADDRESS) + - Socket->HelperData->MaxTDIAddressLength; - - /* Check if our stack buffer is large enough */ - if (ValidateGroupSize <= sizeof(ValidateBuffer)) - { - /* Use the stack */ - ValidateGroupData = (PVOID)ValidateBuffer; - } - else - { - /* Allocate from heap */ - ValidateGroupData = SockAllocateHeapRoutine(SockPrivateHeap, - 0, - ValidateGroupSize); - if (!ValidateGroupData) return WSAENOBUFS; - } - - /* Convert the address to TDI format */ - ErrorCode = SockBuildTdiAddress(&ValidateGroupData->Address, - SocketAddress, - SocketAddressLength); - if (ErrorCode != NO_ERROR) return ErrorCode; - - /* Tell AFD which group to check, and let AFD validate it */ - ValidateGroupData->GroupId = Group; - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_VALIDATE_GROUP, - ValidateGroupData, - ValidateGroupSize, - NULL, - 0); - - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion */ - SockWaitForSingleObject(ThreadData->EventHandle, - Socket->Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check if we need to free the data from heap */ - if (ValidateGroupData != (PVOID)ValidateBuffer) - { - /* Free it */ - RtlFreeHeap(SockPrivateHeap, 0, ValidateGroupData); - } - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - return NtStatusToSocketError(Status); - } - - /* Return success */ - return NO_ERROR; -} - - -INT -WSPAPI -SockGetTdiHandles(IN PSOCKET_INFORMATION Socket) -{ - AFD_TDI_HANDLE_DATA TdiHandleInfo; - NTSTATUS Status; - IO_STATUS_BLOCK IoStatusBlock; - ULONG InfoType = 0; - PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; - - /* See which handle(s) we need */ - if (!Socket->TdiAddressHandle) InfoType |= AFD_ADDRESS_HANDLE; - if (!Socket->TdiConnectionHandle) InfoType |= AFD_CONNECTION_HANDLE; - - /* Make sure we need one */ - if (!InfoType) return NO_ERROR; - - /* Call AFD */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_GET_TDI_HANDLES, - &InfoType, - sizeof(InfoType), - &TdiHandleInfo, - sizeof(TdiHandleInfo)); - /* Check if we shoudl wait */ - if (Status == STATUS_PENDING) - { - /* Wait on it */ - SockWaitForSingleObject(ThreadData->EventHandle, - Socket->Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - - /* Update status */ - Status = IoStatusBlock.Status; - } - - /* Check for success */ - if (!NT_SUCCESS(Status)) return NtStatusToSocketError(Status); - - /* Return handles */ - if (!Socket->TdiAddressHandle) - { - Socket->TdiAddressHandle = TdiHandleInfo.TdiAddressHandle; - } - if (!Socket->TdiConnectionHandle) - { - Socket->TdiConnectionHandle = TdiHandleInfo.TdiConnectionHandle; - } - - /* Return */ - return NO_ERROR; -} - -BOOL -WSPAPI -SockWaitForSingleObject(IN HANDLE Handle, - IN SOCKET SocketHandle, - IN DWORD BlockingFlags, - IN DWORD TimeoutFlags) -{ - LARGE_INTEGER Timeout, CurrentTime, DueTime; - NTSTATUS Status; - PSOCKET_INFORMATION Socket = NULL; - BOOLEAN CallHook, UseTimeout; - LPBLOCKINGCALLBACK BlockingHook; - DWORD_PTR Context; - INT ErrorCode; - PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; - - /* Start with a simple 0.5 second wait */ - Timeout.QuadPart = Int32x32To64(-10000, 500); - Status = NtWaitForSingleObject(Handle, TRUE, &Timeout); - if (Status == STATUS_SUCCESS) return TRUE; - - /* Check if our flags require the socket structure */ - if ((BlockingFlags == MAYBE_BLOCKING_HOOK) || - (BlockingFlags == ALWAYS_BLOCKING_HOOK) || - (TimeoutFlags == SEND_TIMEOUT) || - (TimeoutFlags == RECV_TIMEOUT)) - { - /* Get the socket */ - Socket = SockFindAndReferenceSocket(SocketHandle, FALSE); - if (!Socket) - { - /* We must be waiting on a non-socket for some reason? */ - NtWaitForSingleObject(Handle, TRUE, NULL); - return TRUE; - } - } - - /* Check the blocking flags */ - if (BlockingFlags == ALWAYS_BLOCKING_HOOK) - { - /* Always call it */ - CallHook = TRUE; - } - else if (BlockingFlags == MAYBE_BLOCKING_HOOK) - { - /* Check if we have to call it */ - CallHook = !Socket->SharedData.NonBlocking; - } - else if (BlockingFlags == NO_BLOCKING_HOOK) - { - /* Never call it*/ - CallHook = FALSE; - } - else - { - if (Socket) SockDereferenceSocket(Socket); - return FALSE; - } - - /* Check if we call it */ - if (CallHook) - { - /* Check if it actually exists */ - SockUpcallTable->lpWPUQueryBlockingCallback(Socket->SharedData.CatalogEntryId, - &BlockingHook, - &Context, - &ErrorCode); - - /* See if we'll call it */ - CallHook = (BlockingHook != NULL); - } - - /* Now check the timeout flags */ - if (TimeoutFlags == NO_TIMEOUT) - { - /* None at all */ - UseTimeout = FALSE; - } - else if (TimeoutFlags == SEND_TIMEOUT) - { - /* See if there's a Send Timeout */ - if (Socket->SharedData.SendTimeout) - { - /* Use it */ - UseTimeout = TRUE; - Timeout = RtlEnlargedIntegerMultiply(Socket->SharedData.SendTimeout, - 10 * 1000); - } - else - { - /* There isn't any */ - UseTimeout = FALSE; - } - } - else if (TimeoutFlags == RECV_TIMEOUT) - { - /* See if there's a Receive Timeout */ - if (Socket->SharedData.RecvTimeout) - { - /* Use it */ - UseTimeout = TRUE; - Timeout = RtlEnlargedIntegerMultiply(Socket->SharedData.RecvTimeout, - 10 * 1000); - } - else - { - /* There isn't any */ - UseTimeout = FALSE; - } - } - else - { - if (Socket) SockDereferenceSocket(Socket); - return FALSE; - } - - /* We don't need the socket anymore */ - if (Socket) SockDereferenceSocket(Socket); - - /* Check for timeout */ - if (UseTimeout) - { - /* Calculate the absolute time when the wait ends */ - Status = NtQuerySystemTime(&CurrentTime); - DueTime.QuadPart = CurrentTime.QuadPart + Timeout.QuadPart; - } - else - { - /* Infinite wait */ - DueTime.LowPart = -1; - DueTime.HighPart = 0x7FFFFFFF; - } - - /* Check for blocking hook call */ - if (CallHook) - { - /* We're calling it, so we won't actually be waiting */ - Timeout.LowPart = -1; - Timeout.HighPart = -1; - } - else - { - /* We'll be waiting till the Due Time */ - Timeout = DueTime; - } - - /* Now write data to the TEB so we'll know what's going on */ - ThreadData->CancelIo = FALSE; - ThreadData->SocketHandle = SocketHandle; - - /* Start wait loop */ - do - { - /* Call the hook */ - if (CallHook) (BlockingHook(Context)); - - /* Check if we were cancelled */ - if (ThreadData->CancelIo) - { - /* Infinite timeout and wait for official cancel */ - Timeout.LowPart = -1; - Timeout.HighPart = 0x7FFFFFFF; - } - else - { - /* Check if we're due */ - Status = NtQuerySystemTime(&CurrentTime); - if (CurrentTime.QuadPart > DueTime.QuadPart) - { - /* We're out */ - Status = STATUS_TIMEOUT; - break; - } - } - - /* Do the actual wait */ - Status = NtWaitForSingleObject(Handle, TRUE, &Timeout); - } while ((Status == STATUS_USER_APC) || - (Status == STATUS_ALERTED) || - (Status == STATUS_TIMEOUT)); - - /* Reset thread data */ - ThreadData->SocketHandle = INVALID_SOCKET; - - /* Return to caller */ - if (Status == STATUS_SUCCESS) return TRUE; - return FALSE; -} - -PSOCKET_INFORMATION -WSPAPI -SockFindAndReferenceSocket(IN SOCKET Handle, - IN BOOLEAN Import) -{ - PWAH_HANDLE WahHandle; - - /* Get it from our table and return it */ - WahHandle = WahReferenceContextByHandle(SockContextTable, (HANDLE)Handle); - if (WahHandle) return (PSOCKET_INFORMATION)WahHandle; - - /* Couldn't find it, shoudl we import it? */ - if (Import) return SockImportHandle(Handle); - - /* Nothing found */ - return NULL; -} - -INT -WSPAPI -SockBuildTdiAddress(OUT PTRANSPORT_ADDRESS TdiAddress, - IN PSOCKADDR Sockaddr, - IN INT SockaddrLength) -{ - /* Setup the TDI Address */ - TdiAddress->TAAddressCount = 1; - TdiAddress->Address[0].AddressLength = (USHORT)SockaddrLength - - sizeof(Sockaddr->sa_family); - - /* Copy it */ - RtlCopyMemory(&TdiAddress->Address[0].AddressType, Sockaddr, SockaddrLength); - - /* Return */ - return NO_ERROR; -} - -INT -WSPAPI -SockBuildSockaddr(OUT PSOCKADDR Sockaddr, - OUT PINT SockaddrLength, - IN PTRANSPORT_ADDRESS TdiAddress) -{ - /* Calculate the length it will take */ - *SockaddrLength = TdiAddress->Address[0].AddressLength + - sizeof(Sockaddr->sa_family); - - /* Copy it */ - RtlCopyMemory(Sockaddr, &TdiAddress->Address[0].AddressType, *SockaddrLength); - - /* Return */ - return NO_ERROR; -} - -BOOLEAN -WSPAPI -SockIsSocketConnected(IN PSOCKET_INFORMATION Socket) -{ - LARGE_INTEGER Timeout; - PVOID Context; - PVOID AsyncCallback; - IO_STATUS_BLOCK IoStatusBlock; - NTSTATUS Status; - - /* Check if there is an async connect in progress, but still unprocessed */ - while ((Socket->AsyncData) && - (Socket->AsyncData->IoStatusBlock.Status != STATUS_PENDING)) - { - /* The socket will be locked, release it */ - LeaveCriticalSection(&Socket->Lock); - - /* Setup the timeout and wait on completion */ - Timeout.QuadPart = 0; - Status = NtRemoveIoCompletion(SockAsyncQueuePort, - &AsyncCallback, - &Context, - &IoStatusBlock, - &Timeout); - - /* Check for success */ - if (Status == STATUS_SUCCESS) - { - /* Check if we're supposed to terminate */ - if (AsyncCallback != (PVOID)-1) - { - /* Handle the Async */ - SockHandleAsyncIndication(AsyncCallback, Context, &IoStatusBlock); - } - else - { - /* Terminate it */ - Status = NtSetIoCompletion(SockAsyncQueuePort, - (PVOID)-1, - (PVOID)-1, - 0, - 0); - - /* Acquire the lock and break out */ - EnterCriticalSection(&Socket->Lock); - break; - } - } - - /* Acquire the socket lock again */ - EnterCriticalSection(&Socket->Lock); - } - - /* Check if it's already connected */ - if (Socket->SharedData.State == SocketConnected) return TRUE; - return FALSE; -} - -VOID -WSPAPI -SockCancelIo(IN SOCKET Handle) -{ - IO_STATUS_BLOCK IoStatusBlock; - NTSTATUS Status; - - /* Cancel the I/O */ - Status = NtCancelIoFile((HANDLE)Handle, &IoStatusBlock); -} - -VOID -WSPAPI -SockIoCompletion(IN PVOID ApcContext, - IN PIO_STATUS_BLOCK IoStatusBlock, - DWORD Reserved) -{ - LPWSAOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine = ApcContext; - INT ErrorCode; - DWORD BytesSent; - DWORD Flags = 0; - LPWSAOVERLAPPED lpOverlapped; - PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; - - /* Check if this was an error */ - if (NT_ERROR(IoStatusBlock->Status)) - { - /* Check if it was anything but a simple cancel */ - if (IoStatusBlock->Status != STATUS_CANCELLED) - { - /* Convert it */ - ErrorCode = NtStatusToSocketError(IoStatusBlock->Status); - } - else - { - /* Use the right error */ - ErrorCode = WSA_OPERATION_ABORTED; - } - - /* Either ways, nothing was done */ - BytesSent = 0; - } - else - { - /* No error and check how many bytes were sent */ - ErrorCode = NO_ERROR; - BytesSent = PtrToUlong(IoStatusBlock->Information); - - /* Check the status */ - if (IoStatusBlock->Status == STATUS_BUFFER_OVERFLOW) - { - /* This was an error */ - ErrorCode = WSAEMSGSIZE; - } - else if (IoStatusBlock->Status == STATUS_RECEIVE_PARTIAL) - { - /* Partial receive */ - Flags = MSG_PARTIAL; - } - else if (IoStatusBlock->Status == STATUS_RECEIVE_EXPEDITED) - { - /* OOB receive */ - Flags = MSG_OOB; - } - else if (IoStatusBlock->Status == STATUS_RECEIVE_PARTIAL_EXPEDITED) - { - /* Partial OOB receive */ - Flags = MSG_OOB | MSG_PARTIAL; - } - } - - /* Get the overlapped structure */ - lpOverlapped = CONTAINING_RECORD(IoStatusBlock, WSAOVERLAPPED, Internal); - - /* Call it */ - CompletionRoutine(ErrorCode, BytesSent, lpOverlapped, Flags); - - /* Decrease pending APCs */ - ThreadData->PendingAPCs--; - InterlockedDecrement(&SockProcessPendingAPCCount); -} - -VOID -WSPAPI -SockpWaitForReaderCount(IN PSOCK_RW_LOCK Lock) -{ - NTSTATUS Status; - LARGE_INTEGER Timeout; - - /* Switch threads to see if the lock gets released that way */ - Timeout.QuadPart = 0; - NtDelayExecution(FALSE, &Timeout); - if (Lock->ReaderCount == -2) return; - - /* Either the thread isn't executing (priority inversion) or it's a hog */ - if (!Lock->WriterWaitEvent) - { - /* We don't have an event to wait on yet, allocate it */ - Status = NtCreateEvent(&Lock->WriterWaitEvent, - EVENT_ALL_ACCESS, - NULL, - SynchronizationEvent, - FALSE); - if (!NT_SUCCESS(Status)) - { - /* We can't get an event, do a manual loop */ - Timeout.QuadPart = Int32x32To64(1000, -100); - while (Lock->ReaderCount != -2) NtDelayExecution(FALSE, &Timeout); - } - } - - /* We have en event, now increment the reader count to signal them */ - if (InterlockedIncrement(&Lock->ReaderCount) != -1) - { - /* Wait for them to signal us */ - NtWaitForSingleObject(&Lock->WriterWaitEvent, FALSE, NULL); - } - - /* Finally it's free */ - Lock->ReaderCount = -2; -} - -NTSTATUS -WSPAPI -SockInitializeRwLockAndSpinCount(IN PSOCK_RW_LOCK Lock, - IN ULONG SpinCount) -{ - NTSTATUS Status; - - /* check if this is a special event create request */ - if (SpinCount & 0x80000000) - { - /* Create the event */ - Status = NtCreateEvent(&Lock->WriterWaitEvent, - EVENT_ALL_ACCESS, - NULL, - SynchronizationEvent, - FALSE); - if (!NT_SUCCESS(Status)) return Status; - } - - /* Initialize the lock */ - Status = RtlInitializeCriticalSectionAndSpinCount(&Lock->Lock, SpinCount); - if (NT_SUCCESS(Status)) - { - /* Initialize our structure */ - Lock->ReaderCount = 0; - } - else if (Lock->WriterWaitEvent) - { - /* We failed, close the event if we had one */ - NtClose(Lock->WriterWaitEvent); - Lock->WriterWaitEvent = NULL; - } - - /* Return status */ - return Status; -} - -VOID -WSPAPI -SockAcquireRwLockExclusive(IN PSOCK_RW_LOCK Lock) -{ - LONG Count, NewCount; - ULONG_PTR SpinCount; - - /* Acquire the lock */ - RtlEnterCriticalSection(&Lock->Lock); - - /* Check for ReaderCount */ - if (Lock->ReaderCount >= 0) - { - /* Loop while trying to change the count */ - do - { - /* Get the reader count */ - Count = Lock->ReaderCount; - - /* Modify the count so ReaderCount know that a writer is waiting */ - NewCount = -Count - 2; - } while (InterlockedCompareExchange(&Lock->ReaderCount, - NewCount, - Count) != Count); - - /* Check if some ReaderCount are still active */ - if (NewCount != -2) - { - /* Get the spincount of the CS */ - SpinCount = Lock->Lock.SpinCount; - - /* Loop until they are done */ - while (Lock->ReaderCount != -2) - { - /* Check if the CS has a spin count */ - if (SpinCount) - { - /* Spin on it */ - SpinCount--; - } - else - { - /* Do a full wait for ReaderCount */ - SockpWaitForReaderCount(Lock); - break; - } - } - } - } - else - { - /* Acquiring it again, decrement the count to handle this */ - Lock->ReaderCount--; - } -} - -VOID -WSPAPI -SockAcquireRwLockShared(IN PSOCK_RW_LOCK Lock) -{ - BOOL GotLock = FALSE; - LONG Count, NewCount; - - /* Start acquire loop */ - do - { - /* Get the current count */ - Count = Lock->ReaderCount; - - /* Check if a writer is active */ - if (Count < 0) - { - /* Acquire the lock (this will wait for the writer) */ - RtlEnterCriticalSection(&Lock->Lock); - GotLock = TRUE; - - /* Get the counter again */ - Count = Lock->ReaderCount; - if (Count < 0) - { - /* It's still below 0, so this is a recursive acquire */ - NewCount = Count - 1; - } - else - { - /* Increase the count since the writer has finished */ - NewCount = Count + 1; - } - } - else - { - /* No writers are active, increase count */ - NewCount = Count + 1; - } - - /* Update the count */ - NewCount = InterlockedCompareExchange(&Lock->ReaderCount, - NewCount, - Count); - - /* Check if we got the lock */ - if (GotLock) - { - /* Release it */ - RtlLeaveCriticalSection(&Lock->Lock); - GotLock = FALSE; - } - } while (NewCount != Count); -} - -VOID -WSPAPI -SockReleaseRwLockExclusive(IN PSOCK_RW_LOCK Lock) -{ - /* Increase the reader count and check if it's a recursive acquire */ - if (++Lock->ReaderCount == -1) - { - /* This release is the final one, so unhack the reader count */ - Lock->ReaderCount = 0; - } - - /* Leave the RTL CS */ - RtlLeaveCriticalSection(&Lock->Lock); -} - -VOID -WSPAPI -SockReleaseRwLockShared(IN PSOCK_RW_LOCK Lock) -{ - LONG NewCount, Count = Lock->ReaderCount; - - /* Start release loop */ - while (TRUE) - { - /* Check if writers are using the lock */ - if (Count > 0) - { - /* Lock is free, decrement the count */ - NewCount = Count - 1; - } - else - { - /* Lock is busy, increment the count */ - NewCount = Count + 1; - } - - /* Update the count */ - if (InterlockedCompareExchange(&Lock->ReaderCount, NewCount, Count) == Count) - { - /* Count changed sucesfully, was this the last reader? */ - if (NewCount == -1) - { - /* It was, we need to tell the writer about it */ - NtSetEvent(Lock->WriterWaitEvent, NULL); - } - break; - } - } -} - -NTSTATUS -WSPAPI -SockDeleteRwLock(IN PSOCK_RW_LOCK Lock) -{ - /* Check if there's an event */ - if (Lock->WriterWaitEvent) - { - /* Close it */ - NtClose(Lock->WriterWaitEvent); - Lock->WriterWaitEvent = NULL; - } - - /* Free the Crtitical Section */ - return RtlDeleteCriticalSection(&Lock->Lock); -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -SOCK_RW_LOCK SocketGlobalLock; - -/* FUNCTIONS *****************************************************************/ - -VOID -WSPAPI -SockDestroySocket(PSOCKET_INFORMATION Socket) -{ - /* Dereference its helper DLL */ - SockDereferenceHelperDll(Socket->HelperData); - - /* Delete the lock */ - DeleteCriticalSection(&Socket->Lock); - - /* Free the socket */ - RtlFreeHeap(SockPrivateHeap, 0, Socket); -} - -VOID -__inline -WSPAPI -SockDereferenceSocket(IN PSOCKET_INFORMATION Socket) -{ - /* Dereference and see if it's the last count */ - if (!InterlockedDecrement(&Socket->WshContext.RefCount)) - { - /* Destroy the socket */ - SockDestroySocket(Socket); - } -} - -PSOCKET_INFORMATION -WSPAPI -SockImportHandle(IN SOCKET Handle) -{ - PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; - PWAH_HANDLE WahHandle; - NTSTATUS Status; - ULONG ContextSize; - IO_STATUS_BLOCK IoStatusBlock; - PSOCKET_INFORMATION ImportedSocket = NULL; - UNICODE_STRING TransportName; - - /* Acquire the global lock */ - SockAcquireRwLockExclusive(&SocketGlobalLock); - - /* Make sure that the handle is still invalid */ - WahHandle = WahReferenceContextByHandle(SockContextTable, (HANDLE)Handle); - if (WahHandle) - { - /* Some other thread imported it by now, release the lock and return */ - SockReleaseRwLockExclusive(&SocketGlobalLock); - return (PSOCKET_INFORMATION)WahHandle; - } - - /* Setup the NULL name for possible cleanup later */ - RtlInitUnicodeString(&TransportName, NULL); - - /* Call AFD to get the context size */ - Status = NtDeviceIoControlFile((HANDLE)Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_GET_CONTEXT_SIZE, - NULL, - 0, - &ContextSize, - sizeof(ContextSize)); - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion */ - SockWaitForSingleObject(ThreadData->EventHandle, - Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Make sure we didn't fail, and that this is a valid context */ - if (!NT_SUCCESS(Status) || (ContextSize < sizeof(SOCK_SHARED_INFO))) - { - /* Fail (the error handler will convert to Win32 Status) */ - goto error; - } - -error: - /* Release the lock */ - SockReleaseRwLockExclusive(&SocketGlobalLock); - - return ImportedSocket; -} - -INT -WSPAPI -SockSetInformation(IN PSOCKET_INFORMATION Socket, - IN ULONG AfdInformationClass, - IN PBOOLEAN Boolean OPTIONAL, - IN PULONG Ulong OPTIONAL, - IN PLARGE_INTEGER LargeInteger OPTIONAL) -{ - IO_STATUS_BLOCK IoStatusBlock; - AFD_INFO AfdInfo; - NTSTATUS Status; - PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; - - /* Set Info Class */ - AfdInfo.InformationClass = AfdInformationClass; - - /* Set Information */ - if (Boolean) - { - AfdInfo.Information.Boolean = *Boolean; - } - else if (Ulong) - { - AfdInfo.Information.Ulong = *Ulong; - } - else - { - AfdInfo.Information.LargeInteger = *LargeInteger; - } - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_GET_INFO, - &AfdInfo, - sizeof(AfdInfo), - NULL, - 0); - /* Check if we have to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for the operation to finish */ - SockWaitForSingleObject(ThreadData->EventHandle, - Socket->Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Handle failure */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - return NtStatusToSocketError(Status); - } - - /* Return to caller */ - return NO_ERROR; -} - -INT -WSPAPI -SockGetInformation(IN PSOCKET_INFORMATION Socket, - IN ULONG AfdInformationClass, - IN PVOID ExtraData OPTIONAL, - IN ULONG ExtraDataSize, - IN OUT PBOOLEAN Boolean OPTIONAL, - IN OUT PULONG Ulong OPTIONAL, - IN OUT PLARGE_INTEGER LargeInteger OPTIONAL) -{ - ULONG InfoLength; - IO_STATUS_BLOCK IoStatusBlock; - PAFD_INFO AfdInfo; - AFD_INFO InfoData; - NTSTATUS Status; - PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; - - /* Check if extra data is there */ - if (ExtraData && ExtraDataSize) - { - /* Allocate space for it */ - InfoLength = sizeof(InfoData) + ExtraDataSize; - AfdInfo = (PAFD_INFO)SockAllocateHeapRoutine(SockPrivateHeap, - 0, - InfoLength); - if (!AfdInfo) return WSAENOBUFS; - - /* Copy the extra data */ - RtlCopyMemory(AfdInfo + 1, ExtraData, ExtraDataSize); - } - else - { - /* Use local buffer */ - AfdInfo = &InfoData; - InfoLength = sizeof(InfoData); - } - - /* Set Info Class */ - AfdInfo->InformationClass = AfdInformationClass; - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_GET_INFO, - &InfoData, - InfoLength, - &InfoData, - sizeof(InfoData)); - /* Check if we have to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for the operation to finish */ - SockWaitForSingleObject(ThreadData->EventHandle, - Socket->Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Handle failure */ - if (!NT_SUCCESS(Status)) - { - /* Check if we have to free the data */ - if (AfdInfo != &InfoData) RtlFreeHeap(SockPrivateHeap, 0, AfdInfo); - - /* Fail */ - return NtStatusToSocketError(Status); - } - - /* Return Information */ - if (Boolean) - { - *Boolean = AfdInfo->Information.Boolean; - } - else if (Ulong) - { - *Ulong = AfdInfo->Information.Ulong; - } - else - { - *LargeInteger = AfdInfo->Information.LargeInteger; - } - - /* Check if we have to free the data */ - if (AfdInfo != &InfoData) RtlFreeHeap(SockPrivateHeap, 0, AfdInfo); - - /* Return to caller */ - return NO_ERROR; -} - -INT -WSPAPI -SockSetHandleContext(IN PSOCKET_INFORMATION Socket) -{ - IO_STATUS_BLOCK IoStatusBlock; - CHAR ContextData[256]; - PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; - PVOID Context; - ULONG_PTR ContextPos; - ULONG ContextLength; - INT HelperContextLength; - INT ErrorCode; - NTSTATUS Status; - - /* Find out how big the helper DLL context is */ - ErrorCode = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, - Socket->Handle, - Socket->TdiAddressHandle, - Socket->TdiConnectionHandle, - SOL_INTERNAL, - SO_CONTEXT, - NULL, - &HelperContextLength); - - /* Calculate the total space needed */ - ContextLength = sizeof(SOCK_SHARED_INFO) + - 2 * Socket->HelperData->MaxWSAddressLength + - sizeof(ULONG) + HelperContextLength; - - /* See if our stack can hold it */ - if (ContextLength <= sizeof(ContextData)) - { - /* Use our stack */ - Context = ContextData; - } - else - { - /* Allocate from heap */ - Context = SockAllocateHeapRoutine(SockPrivateHeap, 0, ContextLength); - if (!Context) return WSAENOBUFS; - } - - /* - * Create Context, this includes: - * Shared Socket Data, Helper Context Length, Local and Remote Addresses - * and finally the actual helper context. - */ - ContextPos = (ULONG_PTR)Context; - RtlCopyMemory((PVOID)ContextPos, - &Socket->SharedData, - sizeof(SOCK_SHARED_INFO)); - ContextPos += sizeof(SOCK_SHARED_INFO); - *(PULONG)ContextPos = HelperContextLength; - ContextPos += sizeof(ULONG); - RtlCopyMemory((PVOID)ContextPos, - Socket->LocalAddress, - Socket->HelperData->MaxWSAddressLength); - ContextPos += Socket->HelperData->MaxWSAddressLength; - RtlCopyMemory((PVOID)ContextPos, - Socket->RemoteAddress, - Socket->HelperData->MaxWSAddressLength); - ContextPos += Socket->HelperData->MaxWSAddressLength; - - /* Now get the helper context */ - ErrorCode = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, - Socket->Handle, - Socket->TdiAddressHandle, - Socket->TdiConnectionHandle, - SOL_INTERNAL, - SO_CONTEXT, - (PVOID)ContextPos, - &HelperContextLength); - /* Now give it to AFD */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_SET_CONTEXT, - Context, - ContextLength, - NULL, - 0); - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion */ - SockWaitForSingleObject(ThreadData->EventHandle, - Socket->Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check if we need to free from heap */ - if (Context != ContextData) RtlFreeHeap(SockPrivateHeap, 0, Context); - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Convert and return error code */ - ErrorCode = NtStatusToSocketError(Status); - return ErrorCode; - } - - /* Return success */ - return NO_ERROR; -} - -INT -WSPAPI -SockIsAddressConsistentWithConstrainedGroup(IN PSOCKET_INFORMATION Socket, - IN GROUP Group, - IN PSOCKADDR SocketAddress, - IN INT SocketAddressLength) -{ - PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; - INT ErrorCode; - PAFD_VALIDATE_GROUP_DATA ValidateGroupData; - NTSTATUS Status; - IO_STATUS_BLOCK IoStatusBlock; - ULONG ValidateGroupSize; - CHAR ValidateBuffer[sizeof(AFD_VALIDATE_GROUP_DATA) + MAX_TDI_ADDRESS_LENGTH]; - - /* Calculate the length of the buffer */ - ValidateGroupSize = sizeof(AFD_VALIDATE_GROUP_DATA) + - sizeof(TRANSPORT_ADDRESS) + - Socket->HelperData->MaxTDIAddressLength; - - /* Check if our stack buffer is large enough */ - if (ValidateGroupSize <= sizeof(ValidateBuffer)) - { - /* Use the stack */ - ValidateGroupData = (PVOID)ValidateBuffer; - } - else - { - /* Allocate from heap */ - ValidateGroupData = SockAllocateHeapRoutine(SockPrivateHeap, - 0, - ValidateGroupSize); - if (!ValidateGroupData) return WSAENOBUFS; - } - - /* Convert the address to TDI format */ - ErrorCode = SockBuildTdiAddress(&ValidateGroupData->Address, - SocketAddress, - SocketAddressLength); - if (ErrorCode != NO_ERROR) return ErrorCode; - - /* Tell AFD which group to check, and let AFD validate it */ - ValidateGroupData->GroupId = Group; - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_VALIDATE_GROUP, - ValidateGroupData, - ValidateGroupSize, - NULL, - 0); - - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion */ - SockWaitForSingleObject(ThreadData->EventHandle, - Socket->Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check if we need to free the data from heap */ - if (ValidateGroupData != (PVOID)ValidateBuffer) - { - /* Free it */ - RtlFreeHeap(SockPrivateHeap, 0, ValidateGroupData); - } - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - return NtStatusToSocketError(Status); - } - - /* Return success */ - return NO_ERROR; -} - - -INT -WSPAPI -SockGetTdiHandles(IN PSOCKET_INFORMATION Socket) -{ - AFD_TDI_HANDLE_DATA TdiHandleInfo; - NTSTATUS Status; - IO_STATUS_BLOCK IoStatusBlock; - ULONG InfoType = 0; - PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; - - /* See which handle(s) we need */ - if (!Socket->TdiAddressHandle) InfoType |= AFD_ADDRESS_HANDLE; - if (!Socket->TdiConnectionHandle) InfoType |= AFD_CONNECTION_HANDLE; - - /* Make sure we need one */ - if (!InfoType) return NO_ERROR; - - /* Call AFD */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_GET_TDI_HANDLES, - &InfoType, - sizeof(InfoType), - &TdiHandleInfo, - sizeof(TdiHandleInfo)); - /* Check if we shoudl wait */ - if (Status == STATUS_PENDING) - { - /* Wait on it */ - SockWaitForSingleObject(ThreadData->EventHandle, - Socket->Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - - /* Update status */ - Status = IoStatusBlock.Status; - } - - /* Check for success */ - if (!NT_SUCCESS(Status)) return NtStatusToSocketError(Status); - - /* Return handles */ - if (!Socket->TdiAddressHandle) - { - Socket->TdiAddressHandle = TdiHandleInfo.TdiAddressHandle; - } - if (!Socket->TdiConnectionHandle) - { - Socket->TdiConnectionHandle = TdiHandleInfo.TdiConnectionHandle; - } - - /* Return */ - return NO_ERROR; -} - -BOOL -WSPAPI -SockWaitForSingleObject(IN HANDLE Handle, - IN SOCKET SocketHandle, - IN DWORD BlockingFlags, - IN DWORD TimeoutFlags) -{ - LARGE_INTEGER Timeout, CurrentTime, DueTime; - NTSTATUS Status; - PSOCKET_INFORMATION Socket = NULL; - BOOLEAN CallHook, UseTimeout; - LPBLOCKINGCALLBACK BlockingHook; - DWORD_PTR Context; - INT ErrorCode; - PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; - - /* Start with a simple 0.5 second wait */ - Timeout.QuadPart = Int32x32To64(-10000, 500); - Status = NtWaitForSingleObject(Handle, TRUE, &Timeout); - if (Status == STATUS_SUCCESS) return TRUE; - - /* Check if our flags require the socket structure */ - if ((BlockingFlags == MAYBE_BLOCKING_HOOK) || - (BlockingFlags == ALWAYS_BLOCKING_HOOK) || - (TimeoutFlags == SEND_TIMEOUT) || - (TimeoutFlags == RECV_TIMEOUT)) - { - /* Get the socket */ - Socket = SockFindAndReferenceSocket(SocketHandle, FALSE); - if (!Socket) - { - /* We must be waiting on a non-socket for some reason? */ - NtWaitForSingleObject(Handle, TRUE, NULL); - return TRUE; - } - } - - /* Check the blocking flags */ - if (BlockingFlags == ALWAYS_BLOCKING_HOOK) - { - /* Always call it */ - CallHook = TRUE; - } - else if (BlockingFlags == MAYBE_BLOCKING_HOOK) - { - /* Check if we have to call it */ - CallHook = !Socket->SharedData.NonBlocking; - } - else if (BlockingFlags == NO_BLOCKING_HOOK) - { - /* Never call it*/ - CallHook = FALSE; - } - else - { - if (Socket) SockDereferenceSocket(Socket); - return FALSE; - } - - /* Check if we call it */ - if (CallHook) - { - /* Check if it actually exists */ - SockUpcallTable->lpWPUQueryBlockingCallback(Socket->SharedData.CatalogEntryId, - &BlockingHook, - &Context, - &ErrorCode); - - /* See if we'll call it */ - CallHook = (BlockingHook != NULL); - } - - /* Now check the timeout flags */ - if (TimeoutFlags == NO_TIMEOUT) - { - /* None at all */ - UseTimeout = FALSE; - } - else if (TimeoutFlags == SEND_TIMEOUT) - { - /* See if there's a Send Timeout */ - if (Socket->SharedData.SendTimeout) - { - /* Use it */ - UseTimeout = TRUE; - Timeout = RtlEnlargedIntegerMultiply(Socket->SharedData.SendTimeout, - 10 * 1000); - } - else - { - /* There isn't any */ - UseTimeout = FALSE; - } - } - else if (TimeoutFlags == RECV_TIMEOUT) - { - /* See if there's a Receive Timeout */ - if (Socket->SharedData.RecvTimeout) - { - /* Use it */ - UseTimeout = TRUE; - Timeout = RtlEnlargedIntegerMultiply(Socket->SharedData.RecvTimeout, - 10 * 1000); - } - else - { - /* There isn't any */ - UseTimeout = FALSE; - } - } - else - { - if (Socket) SockDereferenceSocket(Socket); - return FALSE; - } - - /* We don't need the socket anymore */ - if (Socket) SockDereferenceSocket(Socket); - - /* Check for timeout */ - if (UseTimeout) - { - /* Calculate the absolute time when the wait ends */ - Status = NtQuerySystemTime(&CurrentTime); - DueTime.QuadPart = CurrentTime.QuadPart + Timeout.QuadPart; - } - else - { - /* Infinite wait */ - DueTime.LowPart = -1; - DueTime.HighPart = 0x7FFFFFFF; - } - - /* Check for blocking hook call */ - if (CallHook) - { - /* We're calling it, so we won't actually be waiting */ - Timeout.LowPart = -1; - Timeout.HighPart = -1; - } - else - { - /* We'll be waiting till the Due Time */ - Timeout = DueTime; - } - - /* Now write data to the TEB so we'll know what's going on */ - ThreadData->CancelIo = FALSE; - ThreadData->SocketHandle = SocketHandle; - - /* Start wait loop */ - do - { - /* Call the hook */ - if (CallHook) (BlockingHook(Context)); - - /* Check if we were cancelled */ - if (ThreadData->CancelIo) - { - /* Infinite timeout and wait for official cancel */ - Timeout.LowPart = -1; - Timeout.HighPart = 0x7FFFFFFF; - } - else - { - /* Check if we're due */ - Status = NtQuerySystemTime(&CurrentTime); - if (CurrentTime.QuadPart > DueTime.QuadPart) - { - /* We're out */ - Status = STATUS_TIMEOUT; - break; - } - } - - /* Do the actual wait */ - Status = NtWaitForSingleObject(Handle, TRUE, &Timeout); - } while ((Status == STATUS_USER_APC) || - (Status == STATUS_ALERTED) || - (Status == STATUS_TIMEOUT)); - - /* Reset thread data */ - ThreadData->SocketHandle = INVALID_SOCKET; - - /* Return to caller */ - if (Status == STATUS_SUCCESS) return TRUE; - return FALSE; -} - -PSOCKET_INFORMATION -WSPAPI -SockFindAndReferenceSocket(IN SOCKET Handle, - IN BOOLEAN Import) -{ - PWAH_HANDLE WahHandle; - - /* Get it from our table and return it */ - WahHandle = WahReferenceContextByHandle(SockContextTable, (HANDLE)Handle); - if (WahHandle) return (PSOCKET_INFORMATION)WahHandle; - - /* Couldn't find it, shoudl we import it? */ - if (Import) return SockImportHandle(Handle); - - /* Nothing found */ - return NULL; -} - -INT -WSPAPI -SockBuildTdiAddress(OUT PTRANSPORT_ADDRESS TdiAddress, - IN PSOCKADDR Sockaddr, - IN INT SockaddrLength) -{ - /* Setup the TDI Address */ - TdiAddress->TAAddressCount = 1; - TdiAddress->Address[0].AddressLength = (USHORT)SockaddrLength - - sizeof(Sockaddr->sa_family); - - /* Copy it */ - RtlCopyMemory(&TdiAddress->Address[0].AddressType, Sockaddr, SockaddrLength); - - /* Return */ - return NO_ERROR; -} - -INT -WSPAPI -SockBuildSockaddr(OUT PSOCKADDR Sockaddr, - OUT PINT SockaddrLength, - IN PTRANSPORT_ADDRESS TdiAddress) -{ - /* Calculate the length it will take */ - *SockaddrLength = TdiAddress->Address[0].AddressLength + - sizeof(Sockaddr->sa_family); - - /* Copy it */ - RtlCopyMemory(Sockaddr, &TdiAddress->Address[0].AddressType, *SockaddrLength); - - /* Return */ - return NO_ERROR; -} - -BOOLEAN -WSPAPI -SockIsSocketConnected(IN PSOCKET_INFORMATION Socket) -{ - LARGE_INTEGER Timeout; - PVOID Context; - PVOID AsyncCallback; - IO_STATUS_BLOCK IoStatusBlock; - NTSTATUS Status; - - /* Check if there is an async connect in progress, but still unprocessed */ - while ((Socket->AsyncData) && - (Socket->AsyncData->IoStatusBlock.Status != STATUS_PENDING)) - { - /* The socket will be locked, release it */ - LeaveCriticalSection(&Socket->Lock); - - /* Setup the timeout and wait on completion */ - Timeout.QuadPart = 0; - Status = NtRemoveIoCompletion(SockAsyncQueuePort, - &AsyncCallback, - &Context, - &IoStatusBlock, - &Timeout); - - /* Check for success */ - if (Status == STATUS_SUCCESS) - { - /* Check if we're supposed to terminate */ - if (AsyncCallback != (PVOID)-1) - { - /* Handle the Async */ - SockHandleAsyncIndication(AsyncCallback, Context, &IoStatusBlock); - } - else - { - /* Terminate it */ - Status = NtSetIoCompletion(SockAsyncQueuePort, - (PVOID)-1, - (PVOID)-1, - 0, - 0); - - /* Acquire the lock and break out */ - EnterCriticalSection(&Socket->Lock); - break; - } - } - - /* Acquire the socket lock again */ - EnterCriticalSection(&Socket->Lock); - } - - /* Check if it's already connected */ - if (Socket->SharedData.State == SocketConnected) return TRUE; - return FALSE; -} - -VOID -WSPAPI -SockCancelIo(IN SOCKET Handle) -{ - IO_STATUS_BLOCK IoStatusBlock; - NTSTATUS Status; - - /* Cancel the I/O */ - Status = NtCancelIoFile((HANDLE)Handle, &IoStatusBlock); -} - -VOID -WSPAPI -SockIoCompletion(IN PVOID ApcContext, - IN PIO_STATUS_BLOCK IoStatusBlock, - DWORD Reserved) -{ - LPWSAOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine = ApcContext; - INT ErrorCode; - DWORD BytesSent; - DWORD Flags = 0; - LPWSAOVERLAPPED lpOverlapped; - PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; - - /* Check if this was an error */ - if (NT_ERROR(IoStatusBlock->Status)) - { - /* Check if it was anything but a simple cancel */ - if (IoStatusBlock->Status != STATUS_CANCELLED) - { - /* Convert it */ - ErrorCode = NtStatusToSocketError(IoStatusBlock->Status); - } - else - { - /* Use the right error */ - ErrorCode = WSA_OPERATION_ABORTED; - } - - /* Either ways, nothing was done */ - BytesSent = 0; - } - else - { - /* No error and check how many bytes were sent */ - ErrorCode = NO_ERROR; - BytesSent = PtrToUlong(IoStatusBlock->Information); - - /* Check the status */ - if (IoStatusBlock->Status == STATUS_BUFFER_OVERFLOW) - { - /* This was an error */ - ErrorCode = WSAEMSGSIZE; - } - else if (IoStatusBlock->Status == STATUS_RECEIVE_PARTIAL) - { - /* Partial receive */ - Flags = MSG_PARTIAL; - } - else if (IoStatusBlock->Status == STATUS_RECEIVE_EXPEDITED) - { - /* OOB receive */ - Flags = MSG_OOB; - } - else if (IoStatusBlock->Status == STATUS_RECEIVE_PARTIAL_EXPEDITED) - { - /* Partial OOB receive */ - Flags = MSG_OOB | MSG_PARTIAL; - } - } - - /* Get the overlapped structure */ - lpOverlapped = CONTAINING_RECORD(IoStatusBlock, WSAOVERLAPPED, Internal); - - /* Call it */ - CompletionRoutine(ErrorCode, BytesSent, lpOverlapped, Flags); - - /* Decrease pending APCs */ - ThreadData->PendingAPCs--; - InterlockedDecrement(&SockProcessPendingAPCCount); -} - -VOID -WSPAPI -SockpWaitForReaderCount(IN PSOCK_RW_LOCK Lock) -{ - NTSTATUS Status; - LARGE_INTEGER Timeout; - - /* Switch threads to see if the lock gets released that way */ - Timeout.QuadPart = 0; - NtDelayExecution(FALSE, &Timeout); - if (Lock->ReaderCount == -2) return; - - /* Either the thread isn't executing (priority inversion) or it's a hog */ - if (!Lock->WriterWaitEvent) - { - /* We don't have an event to wait on yet, allocate it */ - Status = NtCreateEvent(&Lock->WriterWaitEvent, - EVENT_ALL_ACCESS, - NULL, - SynchronizationEvent, - FALSE); - if (!NT_SUCCESS(Status)) - { - /* We can't get an event, do a manual loop */ - Timeout.QuadPart = Int32x32To64(1000, -100); - while (Lock->ReaderCount != -2) NtDelayExecution(FALSE, &Timeout); - } - } - - /* We have en event, now increment the reader count to signal them */ - if (InterlockedIncrement(&Lock->ReaderCount) != -1) - { - /* Wait for them to signal us */ - NtWaitForSingleObject(&Lock->WriterWaitEvent, FALSE, NULL); - } - - /* Finally it's free */ - Lock->ReaderCount = -2; -} - -NTSTATUS -WSPAPI -SockInitializeRwLockAndSpinCount(IN PSOCK_RW_LOCK Lock, - IN ULONG SpinCount) -{ - NTSTATUS Status; - - /* check if this is a special event create request */ - if (SpinCount & 0x80000000) - { - /* Create the event */ - Status = NtCreateEvent(&Lock->WriterWaitEvent, - EVENT_ALL_ACCESS, - NULL, - SynchronizationEvent, - FALSE); - if (!NT_SUCCESS(Status)) return Status; - } - - /* Initialize the lock */ - Status = RtlInitializeCriticalSectionAndSpinCount(&Lock->Lock, SpinCount); - if (NT_SUCCESS(Status)) - { - /* Initialize our structure */ - Lock->ReaderCount = 0; - } - else if (Lock->WriterWaitEvent) - { - /* We failed, close the event if we had one */ - NtClose(Lock->WriterWaitEvent); - Lock->WriterWaitEvent = NULL; - } - - /* Return status */ - return Status; -} - -VOID -WSPAPI -SockAcquireRwLockExclusive(IN PSOCK_RW_LOCK Lock) -{ - LONG Count, NewCount; - ULONG_PTR SpinCount; - - /* Acquire the lock */ - RtlEnterCriticalSection(&Lock->Lock); - - /* Check for ReaderCount */ - if (Lock->ReaderCount >= 0) - { - /* Loop while trying to change the count */ - do - { - /* Get the reader count */ - Count = Lock->ReaderCount; - - /* Modify the count so ReaderCount know that a writer is waiting */ - NewCount = -Count - 2; - } while (InterlockedCompareExchange(&Lock->ReaderCount, - NewCount, - Count) != Count); - - /* Check if some ReaderCount are still active */ - if (NewCount != -2) - { - /* Get the spincount of the CS */ - SpinCount = Lock->Lock.SpinCount; - - /* Loop until they are done */ - while (Lock->ReaderCount != -2) - { - /* Check if the CS has a spin count */ - if (SpinCount) - { - /* Spin on it */ - SpinCount--; - } - else - { - /* Do a full wait for ReaderCount */ - SockpWaitForReaderCount(Lock); - break; - } - } - } - } - else - { - /* Acquiring it again, decrement the count to handle this */ - Lock->ReaderCount--; - } -} - -VOID -WSPAPI -SockAcquireRwLockShared(IN PSOCK_RW_LOCK Lock) -{ - BOOL GotLock = FALSE; - LONG Count, NewCount; - - /* Start acquire loop */ - do - { - /* Get the current count */ - Count = Lock->ReaderCount; - - /* Check if a writer is active */ - if (Count < 0) - { - /* Acquire the lock (this will wait for the writer) */ - RtlEnterCriticalSection(&Lock->Lock); - GotLock = TRUE; - - /* Get the counter again */ - Count = Lock->ReaderCount; - if (Count < 0) - { - /* It's still below 0, so this is a recursive acquire */ - NewCount = Count - 1; - } - else - { - /* Increase the count since the writer has finished */ - NewCount = Count + 1; - } - } - else - { - /* No writers are active, increase count */ - NewCount = Count + 1; - } - - /* Update the count */ - NewCount = InterlockedCompareExchange(&Lock->ReaderCount, - NewCount, - Count); - - /* Check if we got the lock */ - if (GotLock) - { - /* Release it */ - RtlLeaveCriticalSection(&Lock->Lock); - GotLock = FALSE; - } - } while (NewCount != Count); -} - -VOID -WSPAPI -SockReleaseRwLockExclusive(IN PSOCK_RW_LOCK Lock) -{ - /* Increase the reader count and check if it's a recursive acquire */ - if (++Lock->ReaderCount == -1) - { - /* This release is the final one, so unhack the reader count */ - Lock->ReaderCount = 0; - } - - /* Leave the RTL CS */ - RtlLeaveCriticalSection(&Lock->Lock); -} - -VOID -WSPAPI -SockReleaseRwLockShared(IN PSOCK_RW_LOCK Lock) -{ - LONG NewCount, Count = Lock->ReaderCount; - - /* Start release loop */ - while (TRUE) - { - /* Check if writers are using the lock */ - if (Count > 0) - { - /* Lock is free, decrement the count */ - NewCount = Count - 1; - } - else - { - /* Lock is busy, increment the count */ - NewCount = Count + 1; - } - - /* Update the count */ - if (InterlockedCompareExchange(&Lock->ReaderCount, NewCount, Count) == Count) - { - /* Count changed sucesfully, was this the last reader? */ - if (NewCount == -1) - { - /* It was, we need to tell the writer about it */ - NtSetEvent(Lock->WriterWaitEvent, NULL); - } - break; - } - } -} - -NTSTATUS -WSPAPI -SockDeleteRwLock(IN PSOCK_RW_LOCK Lock) -{ - /* Check if there's an event */ - if (Lock->WriterWaitEvent) - { - /* Close it */ - NtClose(Lock->WriterWaitEvent); - Lock->WriterWaitEvent = NULL; - } - - /* Free the Crtitical Section */ - return RtlDeleteCriticalSection(&Lock->Lock); -} - diff --git a/dll/win32/mswsock/msafd/recv.c b/dll/win32/mswsock/msafd/recv.c index f85d7dfa42c..4eabcc75d75 100644 --- a/dll/win32/mswsock/msafd/recv.c +++ b/dll/win32/mswsock/msafd/recv.c @@ -560,1689 +560,3 @@ error: return NO_ERROR; } -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -INT -WSPAPI -WSPRecv(SOCKET Handle, - LPWSABUF lpBuffers, - DWORD dwBufferCount, - LPDWORD lpNumberOfBytesRead, - LPDWORD ReceiveFlags, - LPWSAOVERLAPPED lpOverlapped, - LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, - LPWSATHREADID lpThreadId, - LPINT lpErrno) -{ - PIO_STATUS_BLOCK IoStatusBlock; - IO_STATUS_BLOCK DummyIoStatusBlock; - AFD_RECV_INFO RecvInfo; - NTSTATUS Status; - PVOID APCContext; - PVOID ApcFunction; - HANDLE Event; - PWINSOCK_TEB_DATA ThreadData; - PSOCKET_INFORMATION Socket; - INT ErrorCode; - BOOLEAN ReturnValue; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Set up the Receive Structure */ - RecvInfo.BufferArray = (PAFD_WSABUF)lpBuffers; - RecvInfo.BufferCount = dwBufferCount; - RecvInfo.TdiFlags = 0; - RecvInfo.AfdFlags = 0; - - /* Set the TDI Flags */ - if (!(*ReceiveFlags)) - { - /* Use normal TDI Receive */ - RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL; - } - else - { - /* Check for valid flags */ - if ((*ReceiveFlags & ~(MSG_OOB | MSG_PEEK | MSG_PARTIAL))) - { - /* Fail */ - ErrorCode = WSAEOPNOTSUPP; - goto error; - } - - /* Check if OOB is being used */ - if (*ReceiveFlags & MSG_OOB) - { - /* Use Expedited Receive for OOB */ - RecvInfo.TdiFlags |= TDI_RECEIVE_EXPEDITED; - } - else - { - /* Use normal receive */ - RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL; - } - - /* Use Peek Receive if enabled */ - if (*ReceiveFlags & MSG_PEEK) RecvInfo.TdiFlags |= TDI_RECEIVE_PEEK; - - /* Use Partial Receive if enabled */ - if (*ReceiveFlags & MSG_PARTIAL) RecvInfo.TdiFlags |= TDI_RECEIVE_PARTIAL; - } - - /* Verifiy if we should use APC */ - if (!lpOverlapped) - { - /* Not using Overlapped structure, so use normal blocking on event */ - APCContext = NULL; - ApcFunction = NULL; - Event = ThreadData->EventHandle; - IoStatusBlock = &DummyIoStatusBlock; - } - else - { - /* Using apc, check if we have a completion routine */ - if (!lpCompletionRoutine) - { - /* No need for APC */ - APCContext = lpOverlapped; - ApcFunction = NULL; - Event = lpOverlapped->hEvent; - } - else - { - /* Use APC */ - ApcFunction = SockIoCompletion; - APCContext = lpCompletionRoutine; - Event = NULL; - - /* Skip Fast I/O */ - RecvInfo.AfdFlags = AFD_SKIP_FIO; - } - - /* Use the overlapped's structure buffer for the I/O Status Block */ - IoStatusBlock = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; - - /* Make this an overlapped I/O in AFD */ - RecvInfo.AfdFlags |= AFD_OVERLAPPED; - } - - /* Set is as Pending for now */ - IoStatusBlock->Status = STATUS_PENDING; - - /* Send IOCTL */ - Status = NtDeviceIoControlFile((HANDLE)Handle, - Event, - ApcFunction, - APCContext, - IoStatusBlock, - IOCTL_AFD_RECV, - &RecvInfo, - sizeof(RecvInfo), - NULL, - 0); - - /* Increase the pending APC Count if we're using an APC */ - if (!NT_ERROR(Status) && ApcFunction) - { - ThreadData->PendingAPCs++; - InterlockedIncrement(&SockProcessPendingAPCCount); - } - - /* Wait for completition if not overlapped */ - if ((Status == STATUS_PENDING) && !(lpOverlapped)) - { - /* Wait for completion */ - ReturnValue = SockWaitForSingleObject(Event, - Handle, - MAYBE_BLOCKING_HOOK, - RECV_TIMEOUT); - - /* Check if the wait was successful */ - if (ReturnValue) - { - /* Get new status */ - Status = IoStatusBlock->Status; - } - else - { - /* Cancel the I/O */ - SockCancelIo(Handle); - - /* Get new status and normalize */ - Status = IoStatusBlock->Status; - if (Status == STATUS_CANCELLED) Status = STATUS_IO_TIMEOUT; - } - } - - /* Return the Flags */ - *ReceiveFlags = 0; - switch (Status) - { - /* Success */ - case STATUS_SUCCESS: - break; - - /* Pending I/O */ - case STATUS_PENDING: - ErrorCode = WSA_IO_PENDING; - goto error; - - /* Buffer Overflow */ - case STATUS_BUFFER_OVERFLOW: - /* Check if this was overlapped */ - if (lpOverlapped) - { - /* Return without bytes read */ - ErrorCode = WSA_IO_PENDING; - goto error; - } - - /* Return failure with bytes read */ - ErrorCode = WSAEMSGSIZE; - break; - - /* OOB Receive */ - case STATUS_RECEIVE_EXPEDITED: - *ReceiveFlags = MSG_OOB; - break; - - /* Partial OOB Receive */ - case STATUS_RECEIVE_PARTIAL_EXPEDITED: - *ReceiveFlags = MSG_PARTIAL | MSG_OOB; - break; - - /* Parial Receive */ - case STATUS_RECEIVE_PARTIAL: - *ReceiveFlags = MSG_PARTIAL; - break; - - /* Other NT Error */ - default: - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - break; - } - - /* Return the number of bytes read */ - *lpNumberOfBytesRead = PtrToUlong(IoStatusBlock->Information); - -error: - - /* Check if async select was active */ - if (SockAsyncSelectCalled) - { - /* Get the socket */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (Socket) - { - /* Lock it */ - EnterCriticalSection(&Socket->Lock); - - /* Check which event to re-enable */ - if (RecvInfo.TdiFlags & TDI_RECEIVE_EXPEDITED) - { - /* Re-enable the OOB event */ - SockReenableAsyncSelectEvent(Socket, FD_OOB); - } - else - { - /* Re-enable the regular read event */ - SockReenableAsyncSelectEvent(Socket, FD_READ); - } - - /* Unlock and dereference socket */ - LeaveCriticalSection(&Socket->Lock); - SockDereferenceSocket(Socket); - } - } - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - -INT -WSPAPI -WSPRecvFrom(SOCKET Handle, - LPWSABUF lpBuffers, - DWORD dwBufferCount, - LPDWORD lpNumberOfBytesRead, - LPDWORD ReceiveFlags, - PSOCKADDR SocketAddress, - PINT SocketAddressLength, - LPWSAOVERLAPPED lpOverlapped, - LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, - LPWSATHREADID lpThreadId, - LPINT lpErrno) -{ - PIO_STATUS_BLOCK IoStatusBlock; - IO_STATUS_BLOCK DummyIoStatusBlock; - AFD_RECV_INFO_UDP RecvInfo; - NTSTATUS Status; - PVOID APCContext; - PVOID ApcFunction; - HANDLE Event; - PWINSOCK_TEB_DATA ThreadData; - PSOCKET_INFORMATION Socket; - INT ErrorCode; - BOOLEAN ReturnValue; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Get the socket */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Fail if the socket isn't bound */ - if (Socket->SharedData.State == SocketOpen) - { - /* Fail */ - ErrorCode = WSAEINVAL; - goto error; - } - - /* If this is an unconnected or non datagram socket */ - if (!(MSAFD_IS_DGRAM_SOCK(Socket)) || - (!SocketAddress && !SocketAddressLength)) - { - /* Call WSP Recv */ - SockDereferenceSocket(Socket); - return WSPRecv(Handle, - lpBuffers, - dwBufferCount, - lpNumberOfBytesRead, - ReceiveFlags, - lpOverlapped, - lpCompletionRoutine, - lpThreadId, - lpErrno); - } - - /* If receive shutdown is enabled, fail */ - if (Socket->SharedData.ReceiveShutdown) - { - /* Fail */ - ErrorCode = WSAESHUTDOWN; - goto error; - } - - /* Check for valid Socket Address (Length) flags */ - if (!(SocketAddress) ^ (!SocketAddressLength || !(*SocketAddressLength))) - { - /* Fail */ - ErrorCode = WSAEFAULT; - goto error; - } - - /* Check for valid flags */ - if ((*ReceiveFlags & ~(MSG_PEEK | MSG_PARTIAL))) - { - /* Fail */ - ErrorCode = WSAEOPNOTSUPP; - goto error; - } - - /* Check that the length is respected */ - if (SocketAddressLength && - (*SocketAddressLength < Socket->HelperData->MinWSAddressLength)) - { - /* Fail */ - ErrorCode = WSAEFAULT; - goto error; - } - - /* Set up the Receive Structure */ - RecvInfo.BufferArray = (PAFD_WSABUF)lpBuffers; - RecvInfo.BufferCount = dwBufferCount; - RecvInfo.TdiFlags = TDI_RECEIVE_NORMAL; - RecvInfo.AfdFlags = 0; - RecvInfo.Address = SocketAddress; - RecvInfo.AddressLength = SocketAddressLength; - - /* Use Peek Receive if enabled */ - if (*ReceiveFlags & MSG_PEEK) RecvInfo.TdiFlags |= TDI_RECEIVE_PEEK; - - /* Use Partial Receive if enabled */ - if (*ReceiveFlags & MSG_PARTIAL) RecvInfo.TdiFlags |= TDI_RECEIVE_PARTIAL; - - /* Verifiy if we should use APC */ - if (!lpOverlapped) - { - /* Not using Overlapped structure, so use normal blocking on event */ - APCContext = NULL; - ApcFunction = NULL; - Event = ThreadData->EventHandle; - IoStatusBlock = &DummyIoStatusBlock; - } - else - { - /* Using apc, check if we have a completion routine */ - if (!lpCompletionRoutine) - { - /* No need for APC */ - APCContext = lpOverlapped; - ApcFunction = NULL; - Event = lpOverlapped->hEvent; - } - else - { - /* Use APC */ - ApcFunction = SockIoCompletion; - APCContext = lpCompletionRoutine; - Event = NULL; - - /* Skip Fast I/O */ - RecvInfo.AfdFlags = AFD_SKIP_FIO; - } - - /* Use the overlapped's structure buffer for the I/O Status Block */ - IoStatusBlock = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; - - /* Make this an overlapped I/O in AFD */ - RecvInfo.AfdFlags |= AFD_OVERLAPPED; - } - - /* Set is as Pending for now */ - IoStatusBlock->Status = STATUS_PENDING; - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - Event, - ApcFunction, - APCContext, - IoStatusBlock, - IOCTL_AFD_RECV_DATAGRAM, - &RecvInfo, - sizeof(RecvInfo), - NULL, - 0); - - /* Increase the pending APC Count if we're using an APC */ - if (!NT_ERROR(Status) && ApcFunction) - { - ThreadData->PendingAPCs++; - InterlockedIncrement(&SockProcessPendingAPCCount); - } - - /* Wait for completition if not overlapped */ - if ((Status == STATUS_PENDING) && !(lpOverlapped)) - { - /* Wait for completion */ - ReturnValue = SockWaitForSingleObject(Event, - Handle, - MAYBE_BLOCKING_HOOK, - RECV_TIMEOUT); - - /* Check if the wait was successful */ - if (ReturnValue) - { - /* Get new status */ - Status = IoStatusBlock->Status; - } - else - { - /* Cancel the I/O */ - SockCancelIo(Handle); - - /* Get new status and normalize */ - Status = IoStatusBlock->Status; - if (Status == STATUS_CANCELLED) Status = STATUS_IO_TIMEOUT; - } - } - - /* Return the Flags */ - *ReceiveFlags = 0; - switch (Status) - { - /* Success */ - case STATUS_SUCCESS: - break; - - /* Pending I/O */ - case STATUS_PENDING: - ErrorCode = WSA_IO_PENDING; - goto error; - - /* Buffer Overflow */ - case STATUS_BUFFER_OVERFLOW: - /* Check if this was overlapped */ - if (lpOverlapped) - { - /* Return without bytes read */ - ErrorCode = WSA_IO_PENDING; - goto error; - } - - /* Return failure with bytes read */ - ErrorCode = WSAEMSGSIZE; - break; - - /* OOB Receive */ - case STATUS_RECEIVE_EXPEDITED: - *ReceiveFlags = MSG_OOB; - break; - - /* Partial OOB Receive */ - case STATUS_RECEIVE_PARTIAL_EXPEDITED: - *ReceiveFlags = MSG_PARTIAL | MSG_OOB; - break; - - /* Parial Receive */ - case STATUS_RECEIVE_PARTIAL: - *ReceiveFlags = MSG_PARTIAL; - break; - - /* Other NT Error */ - default: - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - break; - } - - /* Return the number of bytes read */ - *lpNumberOfBytesRead = PtrToUlong(IoStatusBlock->Information); - -error: - - /* Check if we have a socket here */ - if (Socket) - { - /* Check if async select was active */ - if (SockAsyncSelectCalled) - { - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* Re-enable the regular read event */ - SockReenableAsyncSelectEvent(Socket, FD_READ); - - /* Unlock socket */ - LeaveCriticalSection(&Socket->Lock); - } - - /* Dereference it */ - SockDereferenceSocket(Socket); - } - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -INT -WSPAPI -WSPRecv(SOCKET Handle, - LPWSABUF lpBuffers, - DWORD dwBufferCount, - LPDWORD lpNumberOfBytesRead, - LPDWORD ReceiveFlags, - LPWSAOVERLAPPED lpOverlapped, - LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, - LPWSATHREADID lpThreadId, - LPINT lpErrno) -{ - PIO_STATUS_BLOCK IoStatusBlock; - IO_STATUS_BLOCK DummyIoStatusBlock; - AFD_RECV_INFO RecvInfo; - NTSTATUS Status; - PVOID APCContext; - PVOID ApcFunction; - HANDLE Event; - PWINSOCK_TEB_DATA ThreadData; - PSOCKET_INFORMATION Socket; - INT ErrorCode; - BOOLEAN ReturnValue; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Set up the Receive Structure */ - RecvInfo.BufferArray = (PAFD_WSABUF)lpBuffers; - RecvInfo.BufferCount = dwBufferCount; - RecvInfo.TdiFlags = 0; - RecvInfo.AfdFlags = 0; - - /* Set the TDI Flags */ - if (!(*ReceiveFlags)) - { - /* Use normal TDI Receive */ - RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL; - } - else - { - /* Check for valid flags */ - if ((*ReceiveFlags & ~(MSG_OOB | MSG_PEEK | MSG_PARTIAL))) - { - /* Fail */ - ErrorCode = WSAEOPNOTSUPP; - goto error; - } - - /* Check if OOB is being used */ - if (*ReceiveFlags & MSG_OOB) - { - /* Use Expedited Receive for OOB */ - RecvInfo.TdiFlags |= TDI_RECEIVE_EXPEDITED; - } - else - { - /* Use normal receive */ - RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL; - } - - /* Use Peek Receive if enabled */ - if (*ReceiveFlags & MSG_PEEK) RecvInfo.TdiFlags |= TDI_RECEIVE_PEEK; - - /* Use Partial Receive if enabled */ - if (*ReceiveFlags & MSG_PARTIAL) RecvInfo.TdiFlags |= TDI_RECEIVE_PARTIAL; - } - - /* Verifiy if we should use APC */ - if (!lpOverlapped) - { - /* Not using Overlapped structure, so use normal blocking on event */ - APCContext = NULL; - ApcFunction = NULL; - Event = ThreadData->EventHandle; - IoStatusBlock = &DummyIoStatusBlock; - } - else - { - /* Using apc, check if we have a completion routine */ - if (!lpCompletionRoutine) - { - /* No need for APC */ - APCContext = lpOverlapped; - ApcFunction = NULL; - Event = lpOverlapped->hEvent; - } - else - { - /* Use APC */ - ApcFunction = SockIoCompletion; - APCContext = lpCompletionRoutine; - Event = NULL; - - /* Skip Fast I/O */ - RecvInfo.AfdFlags = AFD_SKIP_FIO; - } - - /* Use the overlapped's structure buffer for the I/O Status Block */ - IoStatusBlock = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; - - /* Make this an overlapped I/O in AFD */ - RecvInfo.AfdFlags |= AFD_OVERLAPPED; - } - - /* Set is as Pending for now */ - IoStatusBlock->Status = STATUS_PENDING; - - /* Send IOCTL */ - Status = NtDeviceIoControlFile((HANDLE)Handle, - Event, - ApcFunction, - APCContext, - IoStatusBlock, - IOCTL_AFD_RECV, - &RecvInfo, - sizeof(RecvInfo), - NULL, - 0); - - /* Increase the pending APC Count if we're using an APC */ - if (!NT_ERROR(Status) && ApcFunction) - { - ThreadData->PendingAPCs++; - InterlockedIncrement(&SockProcessPendingAPCCount); - } - - /* Wait for completition if not overlapped */ - if ((Status == STATUS_PENDING) && !(lpOverlapped)) - { - /* Wait for completion */ - ReturnValue = SockWaitForSingleObject(Event, - Handle, - MAYBE_BLOCKING_HOOK, - RECV_TIMEOUT); - - /* Check if the wait was successful */ - if (ReturnValue) - { - /* Get new status */ - Status = IoStatusBlock->Status; - } - else - { - /* Cancel the I/O */ - SockCancelIo(Handle); - - /* Get new status and normalize */ - Status = IoStatusBlock->Status; - if (Status == STATUS_CANCELLED) Status = STATUS_IO_TIMEOUT; - } - } - - /* Return the Flags */ - *ReceiveFlags = 0; - switch (Status) - { - /* Success */ - case STATUS_SUCCESS: - break; - - /* Pending I/O */ - case STATUS_PENDING: - ErrorCode = WSA_IO_PENDING; - goto error; - - /* Buffer Overflow */ - case STATUS_BUFFER_OVERFLOW: - /* Check if this was overlapped */ - if (lpOverlapped) - { - /* Return without bytes read */ - ErrorCode = WSA_IO_PENDING; - goto error; - } - - /* Return failure with bytes read */ - ErrorCode = WSAEMSGSIZE; - break; - - /* OOB Receive */ - case STATUS_RECEIVE_EXPEDITED: - *ReceiveFlags = MSG_OOB; - break; - - /* Partial OOB Receive */ - case STATUS_RECEIVE_PARTIAL_EXPEDITED: - *ReceiveFlags = MSG_PARTIAL | MSG_OOB; - break; - - /* Parial Receive */ - case STATUS_RECEIVE_PARTIAL: - *ReceiveFlags = MSG_PARTIAL; - break; - - /* Other NT Error */ - default: - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - break; - } - - /* Return the number of bytes read */ - *lpNumberOfBytesRead = PtrToUlong(IoStatusBlock->Information); - -error: - - /* Check if async select was active */ - if (SockAsyncSelectCalled) - { - /* Get the socket */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (Socket) - { - /* Lock it */ - EnterCriticalSection(&Socket->Lock); - - /* Check which event to re-enable */ - if (RecvInfo.TdiFlags & TDI_RECEIVE_EXPEDITED) - { - /* Re-enable the OOB event */ - SockReenableAsyncSelectEvent(Socket, FD_OOB); - } - else - { - /* Re-enable the regular read event */ - SockReenableAsyncSelectEvent(Socket, FD_READ); - } - - /* Unlock and dereference socket */ - LeaveCriticalSection(&Socket->Lock); - SockDereferenceSocket(Socket); - } - } - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - -INT -WSPAPI -WSPRecvFrom(SOCKET Handle, - LPWSABUF lpBuffers, - DWORD dwBufferCount, - LPDWORD lpNumberOfBytesRead, - LPDWORD ReceiveFlags, - PSOCKADDR SocketAddress, - PINT SocketAddressLength, - LPWSAOVERLAPPED lpOverlapped, - LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, - LPWSATHREADID lpThreadId, - LPINT lpErrno) -{ - PIO_STATUS_BLOCK IoStatusBlock; - IO_STATUS_BLOCK DummyIoStatusBlock; - AFD_RECV_INFO_UDP RecvInfo; - NTSTATUS Status; - PVOID APCContext; - PVOID ApcFunction; - HANDLE Event; - PWINSOCK_TEB_DATA ThreadData; - PSOCKET_INFORMATION Socket; - INT ErrorCode; - BOOLEAN ReturnValue; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Get the socket */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Fail if the socket isn't bound */ - if (Socket->SharedData.State == SocketOpen) - { - /* Fail */ - ErrorCode = WSAEINVAL; - goto error; - } - - /* If this is an unconnected or non datagram socket */ - if (!(MSAFD_IS_DGRAM_SOCK(Socket)) || - (!SocketAddress && !SocketAddressLength)) - { - /* Call WSP Recv */ - SockDereferenceSocket(Socket); - return WSPRecv(Handle, - lpBuffers, - dwBufferCount, - lpNumberOfBytesRead, - ReceiveFlags, - lpOverlapped, - lpCompletionRoutine, - lpThreadId, - lpErrno); - } - - /* If receive shutdown is enabled, fail */ - if (Socket->SharedData.ReceiveShutdown) - { - /* Fail */ - ErrorCode = WSAESHUTDOWN; - goto error; - } - - /* Check for valid Socket Address (Length) flags */ - if (!(SocketAddress) ^ (!SocketAddressLength || !(*SocketAddressLength))) - { - /* Fail */ - ErrorCode = WSAEFAULT; - goto error; - } - - /* Check for valid flags */ - if ((*ReceiveFlags & ~(MSG_PEEK | MSG_PARTIAL))) - { - /* Fail */ - ErrorCode = WSAEOPNOTSUPP; - goto error; - } - - /* Check that the length is respected */ - if (SocketAddressLength && - (*SocketAddressLength < Socket->HelperData->MinWSAddressLength)) - { - /* Fail */ - ErrorCode = WSAEFAULT; - goto error; - } - - /* Set up the Receive Structure */ - RecvInfo.BufferArray = (PAFD_WSABUF)lpBuffers; - RecvInfo.BufferCount = dwBufferCount; - RecvInfo.TdiFlags = TDI_RECEIVE_NORMAL; - RecvInfo.AfdFlags = 0; - RecvInfo.Address = SocketAddress; - RecvInfo.AddressLength = SocketAddressLength; - - /* Use Peek Receive if enabled */ - if (*ReceiveFlags & MSG_PEEK) RecvInfo.TdiFlags |= TDI_RECEIVE_PEEK; - - /* Use Partial Receive if enabled */ - if (*ReceiveFlags & MSG_PARTIAL) RecvInfo.TdiFlags |= TDI_RECEIVE_PARTIAL; - - /* Verifiy if we should use APC */ - if (!lpOverlapped) - { - /* Not using Overlapped structure, so use normal blocking on event */ - APCContext = NULL; - ApcFunction = NULL; - Event = ThreadData->EventHandle; - IoStatusBlock = &DummyIoStatusBlock; - } - else - { - /* Using apc, check if we have a completion routine */ - if (!lpCompletionRoutine) - { - /* No need for APC */ - APCContext = lpOverlapped; - ApcFunction = NULL; - Event = lpOverlapped->hEvent; - } - else - { - /* Use APC */ - ApcFunction = SockIoCompletion; - APCContext = lpCompletionRoutine; - Event = NULL; - - /* Skip Fast I/O */ - RecvInfo.AfdFlags = AFD_SKIP_FIO; - } - - /* Use the overlapped's structure buffer for the I/O Status Block */ - IoStatusBlock = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; - - /* Make this an overlapped I/O in AFD */ - RecvInfo.AfdFlags |= AFD_OVERLAPPED; - } - - /* Set is as Pending for now */ - IoStatusBlock->Status = STATUS_PENDING; - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - Event, - ApcFunction, - APCContext, - IoStatusBlock, - IOCTL_AFD_RECV_DATAGRAM, - &RecvInfo, - sizeof(RecvInfo), - NULL, - 0); - - /* Increase the pending APC Count if we're using an APC */ - if (!NT_ERROR(Status) && ApcFunction) - { - ThreadData->PendingAPCs++; - InterlockedIncrement(&SockProcessPendingAPCCount); - } - - /* Wait for completition if not overlapped */ - if ((Status == STATUS_PENDING) && !(lpOverlapped)) - { - /* Wait for completion */ - ReturnValue = SockWaitForSingleObject(Event, - Handle, - MAYBE_BLOCKING_HOOK, - RECV_TIMEOUT); - - /* Check if the wait was successful */ - if (ReturnValue) - { - /* Get new status */ - Status = IoStatusBlock->Status; - } - else - { - /* Cancel the I/O */ - SockCancelIo(Handle); - - /* Get new status and normalize */ - Status = IoStatusBlock->Status; - if (Status == STATUS_CANCELLED) Status = STATUS_IO_TIMEOUT; - } - } - - /* Return the Flags */ - *ReceiveFlags = 0; - switch (Status) - { - /* Success */ - case STATUS_SUCCESS: - break; - - /* Pending I/O */ - case STATUS_PENDING: - ErrorCode = WSA_IO_PENDING; - goto error; - - /* Buffer Overflow */ - case STATUS_BUFFER_OVERFLOW: - /* Check if this was overlapped */ - if (lpOverlapped) - { - /* Return without bytes read */ - ErrorCode = WSA_IO_PENDING; - goto error; - } - - /* Return failure with bytes read */ - ErrorCode = WSAEMSGSIZE; - break; - - /* OOB Receive */ - case STATUS_RECEIVE_EXPEDITED: - *ReceiveFlags = MSG_OOB; - break; - - /* Partial OOB Receive */ - case STATUS_RECEIVE_PARTIAL_EXPEDITED: - *ReceiveFlags = MSG_PARTIAL | MSG_OOB; - break; - - /* Parial Receive */ - case STATUS_RECEIVE_PARTIAL: - *ReceiveFlags = MSG_PARTIAL; - break; - - /* Other NT Error */ - default: - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - break; - } - - /* Return the number of bytes read */ - *lpNumberOfBytesRead = PtrToUlong(IoStatusBlock->Information); - -error: - - /* Check if we have a socket here */ - if (Socket) - { - /* Check if async select was active */ - if (SockAsyncSelectCalled) - { - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* Re-enable the regular read event */ - SockReenableAsyncSelectEvent(Socket, FD_READ); - - /* Unlock socket */ - LeaveCriticalSection(&Socket->Lock); - } - - /* Dereference it */ - SockDereferenceSocket(Socket); - } - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -INT -WSPAPI -WSPRecv(SOCKET Handle, - LPWSABUF lpBuffers, - DWORD dwBufferCount, - LPDWORD lpNumberOfBytesRead, - LPDWORD ReceiveFlags, - LPWSAOVERLAPPED lpOverlapped, - LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, - LPWSATHREADID lpThreadId, - LPINT lpErrno) -{ - PIO_STATUS_BLOCK IoStatusBlock; - IO_STATUS_BLOCK DummyIoStatusBlock; - AFD_RECV_INFO RecvInfo; - NTSTATUS Status; - PVOID APCContext; - PVOID ApcFunction; - HANDLE Event; - PWINSOCK_TEB_DATA ThreadData; - PSOCKET_INFORMATION Socket; - INT ErrorCode; - BOOLEAN ReturnValue; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Set up the Receive Structure */ - RecvInfo.BufferArray = (PAFD_WSABUF)lpBuffers; - RecvInfo.BufferCount = dwBufferCount; - RecvInfo.TdiFlags = 0; - RecvInfo.AfdFlags = 0; - - /* Set the TDI Flags */ - if (!(*ReceiveFlags)) - { - /* Use normal TDI Receive */ - RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL; - } - else - { - /* Check for valid flags */ - if ((*ReceiveFlags & ~(MSG_OOB | MSG_PEEK | MSG_PARTIAL))) - { - /* Fail */ - ErrorCode = WSAEOPNOTSUPP; - goto error; - } - - /* Check if OOB is being used */ - if (*ReceiveFlags & MSG_OOB) - { - /* Use Expedited Receive for OOB */ - RecvInfo.TdiFlags |= TDI_RECEIVE_EXPEDITED; - } - else - { - /* Use normal receive */ - RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL; - } - - /* Use Peek Receive if enabled */ - if (*ReceiveFlags & MSG_PEEK) RecvInfo.TdiFlags |= TDI_RECEIVE_PEEK; - - /* Use Partial Receive if enabled */ - if (*ReceiveFlags & MSG_PARTIAL) RecvInfo.TdiFlags |= TDI_RECEIVE_PARTIAL; - } - - /* Verifiy if we should use APC */ - if (!lpOverlapped) - { - /* Not using Overlapped structure, so use normal blocking on event */ - APCContext = NULL; - ApcFunction = NULL; - Event = ThreadData->EventHandle; - IoStatusBlock = &DummyIoStatusBlock; - } - else - { - /* Using apc, check if we have a completion routine */ - if (!lpCompletionRoutine) - { - /* No need for APC */ - APCContext = lpOverlapped; - ApcFunction = NULL; - Event = lpOverlapped->hEvent; - } - else - { - /* Use APC */ - ApcFunction = SockIoCompletion; - APCContext = lpCompletionRoutine; - Event = NULL; - - /* Skip Fast I/O */ - RecvInfo.AfdFlags = AFD_SKIP_FIO; - } - - /* Use the overlapped's structure buffer for the I/O Status Block */ - IoStatusBlock = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; - - /* Make this an overlapped I/O in AFD */ - RecvInfo.AfdFlags |= AFD_OVERLAPPED; - } - - /* Set is as Pending for now */ - IoStatusBlock->Status = STATUS_PENDING; - - /* Send IOCTL */ - Status = NtDeviceIoControlFile((HANDLE)Handle, - Event, - ApcFunction, - APCContext, - IoStatusBlock, - IOCTL_AFD_RECV, - &RecvInfo, - sizeof(RecvInfo), - NULL, - 0); - - /* Increase the pending APC Count if we're using an APC */ - if (!NT_ERROR(Status) && ApcFunction) - { - ThreadData->PendingAPCs++; - InterlockedIncrement(&SockProcessPendingAPCCount); - } - - /* Wait for completition if not overlapped */ - if ((Status == STATUS_PENDING) && !(lpOverlapped)) - { - /* Wait for completion */ - ReturnValue = SockWaitForSingleObject(Event, - Handle, - MAYBE_BLOCKING_HOOK, - RECV_TIMEOUT); - - /* Check if the wait was successful */ - if (ReturnValue) - { - /* Get new status */ - Status = IoStatusBlock->Status; - } - else - { - /* Cancel the I/O */ - SockCancelIo(Handle); - - /* Get new status and normalize */ - Status = IoStatusBlock->Status; - if (Status == STATUS_CANCELLED) Status = STATUS_IO_TIMEOUT; - } - } - - /* Return the Flags */ - *ReceiveFlags = 0; - switch (Status) - { - /* Success */ - case STATUS_SUCCESS: - break; - - /* Pending I/O */ - case STATUS_PENDING: - ErrorCode = WSA_IO_PENDING; - goto error; - - /* Buffer Overflow */ - case STATUS_BUFFER_OVERFLOW: - /* Check if this was overlapped */ - if (lpOverlapped) - { - /* Return without bytes read */ - ErrorCode = WSA_IO_PENDING; - goto error; - } - - /* Return failure with bytes read */ - ErrorCode = WSAEMSGSIZE; - break; - - /* OOB Receive */ - case STATUS_RECEIVE_EXPEDITED: - *ReceiveFlags = MSG_OOB; - break; - - /* Partial OOB Receive */ - case STATUS_RECEIVE_PARTIAL_EXPEDITED: - *ReceiveFlags = MSG_PARTIAL | MSG_OOB; - break; - - /* Parial Receive */ - case STATUS_RECEIVE_PARTIAL: - *ReceiveFlags = MSG_PARTIAL; - break; - - /* Other NT Error */ - default: - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - break; - } - - /* Return the number of bytes read */ - *lpNumberOfBytesRead = PtrToUlong(IoStatusBlock->Information); - -error: - - /* Check if async select was active */ - if (SockAsyncSelectCalled) - { - /* Get the socket */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (Socket) - { - /* Lock it */ - EnterCriticalSection(&Socket->Lock); - - /* Check which event to re-enable */ - if (RecvInfo.TdiFlags & TDI_RECEIVE_EXPEDITED) - { - /* Re-enable the OOB event */ - SockReenableAsyncSelectEvent(Socket, FD_OOB); - } - else - { - /* Re-enable the regular read event */ - SockReenableAsyncSelectEvent(Socket, FD_READ); - } - - /* Unlock and dereference socket */ - LeaveCriticalSection(&Socket->Lock); - SockDereferenceSocket(Socket); - } - } - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - -INT -WSPAPI -WSPRecvFrom(SOCKET Handle, - LPWSABUF lpBuffers, - DWORD dwBufferCount, - LPDWORD lpNumberOfBytesRead, - LPDWORD ReceiveFlags, - PSOCKADDR SocketAddress, - PINT SocketAddressLength, - LPWSAOVERLAPPED lpOverlapped, - LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, - LPWSATHREADID lpThreadId, - LPINT lpErrno) -{ - PIO_STATUS_BLOCK IoStatusBlock; - IO_STATUS_BLOCK DummyIoStatusBlock; - AFD_RECV_INFO_UDP RecvInfo; - NTSTATUS Status; - PVOID APCContext; - PVOID ApcFunction; - HANDLE Event; - PWINSOCK_TEB_DATA ThreadData; - PSOCKET_INFORMATION Socket; - INT ErrorCode; - BOOLEAN ReturnValue; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Get the socket */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Fail if the socket isn't bound */ - if (Socket->SharedData.State == SocketOpen) - { - /* Fail */ - ErrorCode = WSAEINVAL; - goto error; - } - - /* If this is an unconnected or non datagram socket */ - if (!(MSAFD_IS_DGRAM_SOCK(Socket)) || - (!SocketAddress && !SocketAddressLength)) - { - /* Call WSP Recv */ - SockDereferenceSocket(Socket); - return WSPRecv(Handle, - lpBuffers, - dwBufferCount, - lpNumberOfBytesRead, - ReceiveFlags, - lpOverlapped, - lpCompletionRoutine, - lpThreadId, - lpErrno); - } - - /* If receive shutdown is enabled, fail */ - if (Socket->SharedData.ReceiveShutdown) - { - /* Fail */ - ErrorCode = WSAESHUTDOWN; - goto error; - } - - /* Check for valid Socket Address (Length) flags */ - if (!(SocketAddress) ^ (!SocketAddressLength || !(*SocketAddressLength))) - { - /* Fail */ - ErrorCode = WSAEFAULT; - goto error; - } - - /* Check for valid flags */ - if ((*ReceiveFlags & ~(MSG_PEEK | MSG_PARTIAL))) - { - /* Fail */ - ErrorCode = WSAEOPNOTSUPP; - goto error; - } - - /* Check that the length is respected */ - if (SocketAddressLength && - (*SocketAddressLength < Socket->HelperData->MinWSAddressLength)) - { - /* Fail */ - ErrorCode = WSAEFAULT; - goto error; - } - - /* Set up the Receive Structure */ - RecvInfo.BufferArray = (PAFD_WSABUF)lpBuffers; - RecvInfo.BufferCount = dwBufferCount; - RecvInfo.TdiFlags = TDI_RECEIVE_NORMAL; - RecvInfo.AfdFlags = 0; - RecvInfo.Address = SocketAddress; - RecvInfo.AddressLength = SocketAddressLength; - - /* Use Peek Receive if enabled */ - if (*ReceiveFlags & MSG_PEEK) RecvInfo.TdiFlags |= TDI_RECEIVE_PEEK; - - /* Use Partial Receive if enabled */ - if (*ReceiveFlags & MSG_PARTIAL) RecvInfo.TdiFlags |= TDI_RECEIVE_PARTIAL; - - /* Verifiy if we should use APC */ - if (!lpOverlapped) - { - /* Not using Overlapped structure, so use normal blocking on event */ - APCContext = NULL; - ApcFunction = NULL; - Event = ThreadData->EventHandle; - IoStatusBlock = &DummyIoStatusBlock; - } - else - { - /* Using apc, check if we have a completion routine */ - if (!lpCompletionRoutine) - { - /* No need for APC */ - APCContext = lpOverlapped; - ApcFunction = NULL; - Event = lpOverlapped->hEvent; - } - else - { - /* Use APC */ - ApcFunction = SockIoCompletion; - APCContext = lpCompletionRoutine; - Event = NULL; - - /* Skip Fast I/O */ - RecvInfo.AfdFlags = AFD_SKIP_FIO; - } - - /* Use the overlapped's structure buffer for the I/O Status Block */ - IoStatusBlock = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; - - /* Make this an overlapped I/O in AFD */ - RecvInfo.AfdFlags |= AFD_OVERLAPPED; - } - - /* Set is as Pending for now */ - IoStatusBlock->Status = STATUS_PENDING; - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - Event, - ApcFunction, - APCContext, - IoStatusBlock, - IOCTL_AFD_RECV_DATAGRAM, - &RecvInfo, - sizeof(RecvInfo), - NULL, - 0); - - /* Increase the pending APC Count if we're using an APC */ - if (!NT_ERROR(Status) && ApcFunction) - { - ThreadData->PendingAPCs++; - InterlockedIncrement(&SockProcessPendingAPCCount); - } - - /* Wait for completition if not overlapped */ - if ((Status == STATUS_PENDING) && !(lpOverlapped)) - { - /* Wait for completion */ - ReturnValue = SockWaitForSingleObject(Event, - Handle, - MAYBE_BLOCKING_HOOK, - RECV_TIMEOUT); - - /* Check if the wait was successful */ - if (ReturnValue) - { - /* Get new status */ - Status = IoStatusBlock->Status; - } - else - { - /* Cancel the I/O */ - SockCancelIo(Handle); - - /* Get new status and normalize */ - Status = IoStatusBlock->Status; - if (Status == STATUS_CANCELLED) Status = STATUS_IO_TIMEOUT; - } - } - - /* Return the Flags */ - *ReceiveFlags = 0; - switch (Status) - { - /* Success */ - case STATUS_SUCCESS: - break; - - /* Pending I/O */ - case STATUS_PENDING: - ErrorCode = WSA_IO_PENDING; - goto error; - - /* Buffer Overflow */ - case STATUS_BUFFER_OVERFLOW: - /* Check if this was overlapped */ - if (lpOverlapped) - { - /* Return without bytes read */ - ErrorCode = WSA_IO_PENDING; - goto error; - } - - /* Return failure with bytes read */ - ErrorCode = WSAEMSGSIZE; - break; - - /* OOB Receive */ - case STATUS_RECEIVE_EXPEDITED: - *ReceiveFlags = MSG_OOB; - break; - - /* Partial OOB Receive */ - case STATUS_RECEIVE_PARTIAL_EXPEDITED: - *ReceiveFlags = MSG_PARTIAL | MSG_OOB; - break; - - /* Parial Receive */ - case STATUS_RECEIVE_PARTIAL: - *ReceiveFlags = MSG_PARTIAL; - break; - - /* Other NT Error */ - default: - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - break; - } - - /* Return the number of bytes read */ - *lpNumberOfBytesRead = PtrToUlong(IoStatusBlock->Information); - -error: - - /* Check if we have a socket here */ - if (Socket) - { - /* Check if async select was active */ - if (SockAsyncSelectCalled) - { - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* Re-enable the regular read event */ - SockReenableAsyncSelectEvent(Socket, FD_READ); - - /* Unlock socket */ - LeaveCriticalSection(&Socket->Lock); - } - - /* Dereference it */ - SockDereferenceSocket(Socket); - } - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - diff --git a/dll/win32/mswsock/msafd/sanaccpt.c b/dll/win32/mswsock/msafd/sanaccpt.c index 3e062e90d63..bd1ad2806dc 100644 --- a/dll/win32/mswsock/msafd/sanaccpt.c +++ b/dll/win32/mswsock/msafd/sanaccpt.c @@ -12,45 +12,3 @@ /* FUNCTIONS *****************************************************************/ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - diff --git a/dll/win32/mswsock/msafd/sanconn.c b/dll/win32/mswsock/msafd/sanconn.c index 3e062e90d63..bd1ad2806dc 100644 --- a/dll/win32/mswsock/msafd/sanconn.c +++ b/dll/win32/mswsock/msafd/sanconn.c @@ -12,45 +12,3 @@ /* FUNCTIONS *****************************************************************/ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - diff --git a/dll/win32/mswsock/msafd/sanflow.c b/dll/win32/mswsock/msafd/sanflow.c index 3e062e90d63..bd1ad2806dc 100644 --- a/dll/win32/mswsock/msafd/sanflow.c +++ b/dll/win32/mswsock/msafd/sanflow.c @@ -12,45 +12,3 @@ /* FUNCTIONS *****************************************************************/ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - diff --git a/dll/win32/mswsock/msafd/sanlistn.c b/dll/win32/mswsock/msafd/sanlistn.c index 3e062e90d63..bd1ad2806dc 100644 --- a/dll/win32/mswsock/msafd/sanlistn.c +++ b/dll/win32/mswsock/msafd/sanlistn.c @@ -12,45 +12,3 @@ /* FUNCTIONS *****************************************************************/ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - diff --git a/dll/win32/mswsock/msafd/sanprov.c b/dll/win32/mswsock/msafd/sanprov.c index ed15fb9f046..802bf6fe43e 100644 --- a/dll/win32/mswsock/msafd/sanprov.c +++ b/dll/win32/mswsock/msafd/sanprov.c @@ -58,183 +58,3 @@ SockSanInitialize(VOID) } -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -HANDLE SockSanCleanUpCompleteEvent; -BOOLEAN SockSanEnabled; - -WSAPROTOCOL_INFOW SockTcpProviderInfo = -{ - XP1_GUARANTEED_DELIVERY | - XP1_GUARANTEED_ORDER | - XP1_GRACEFUL_CLOSE | - XP1_EXPEDITED_DATA | - XP1_IFS_HANDLES, - 0, - 0, - 0, - PFL_MATCHES_PROTOCOL_ZERO, - { - 0xe70f1aa0, - 0xab8b, - 0x11cf, - {0x8c, 0xa3, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92} - }, - 0, - { - BASE_PROTOCOL, - { 0, 0, 0, 0, 0, 0, 0 } - }, - 2, - AF_INET, - sizeof(SOCKADDR_IN), - sizeof(SOCKADDR_IN), - SOCK_STREAM, - IPPROTO_TCP, - 0, - BIGENDIAN, - SECURITY_PROTOCOL_NONE, - 0, - 0, - L"MSAFD Tcpip [TCP/IP]" -}; - -/* FUNCTIONS *****************************************************************/ - -VOID -WSPAPI -SockSanInitialize(VOID) -{ - -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -HANDLE SockSanCleanUpCompleteEvent; -BOOLEAN SockSanEnabled; - -WSAPROTOCOL_INFOW SockTcpProviderInfo = -{ - XP1_GUARANTEED_DELIVERY | - XP1_GUARANTEED_ORDER | - XP1_GRACEFUL_CLOSE | - XP1_EXPEDITED_DATA | - XP1_IFS_HANDLES, - 0, - 0, - 0, - PFL_MATCHES_PROTOCOL_ZERO, - { - 0xe70f1aa0, - 0xab8b, - 0x11cf, - {0x8c, 0xa3, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92} - }, - 0, - { - BASE_PROTOCOL, - { 0, 0, 0, 0, 0, 0, 0 } - }, - 2, - AF_INET, - sizeof(SOCKADDR_IN), - sizeof(SOCKADDR_IN), - SOCK_STREAM, - IPPROTO_TCP, - 0, - BIGENDIAN, - SECURITY_PROTOCOL_NONE, - 0, - 0, - L"MSAFD Tcpip [TCP/IP]" -}; - -/* FUNCTIONS *****************************************************************/ - -VOID -WSPAPI -SockSanInitialize(VOID) -{ - -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -HANDLE SockSanCleanUpCompleteEvent; -BOOLEAN SockSanEnabled; - -WSAPROTOCOL_INFOW SockTcpProviderInfo = -{ - XP1_GUARANTEED_DELIVERY | - XP1_GUARANTEED_ORDER | - XP1_GRACEFUL_CLOSE | - XP1_EXPEDITED_DATA | - XP1_IFS_HANDLES, - 0, - 0, - 0, - PFL_MATCHES_PROTOCOL_ZERO, - { - 0xe70f1aa0, - 0xab8b, - 0x11cf, - {0x8c, 0xa3, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92} - }, - 0, - { - BASE_PROTOCOL, - { 0, 0, 0, 0, 0, 0, 0 } - }, - 2, - AF_INET, - sizeof(SOCKADDR_IN), - sizeof(SOCKADDR_IN), - SOCK_STREAM, - IPPROTO_TCP, - 0, - BIGENDIAN, - SECURITY_PROTOCOL_NONE, - 0, - 0, - L"MSAFD Tcpip [TCP/IP]" -}; - -/* FUNCTIONS *****************************************************************/ - -VOID -WSPAPI -SockSanInitialize(VOID) -{ - -} - diff --git a/dll/win32/mswsock/msafd/sanrdma.c b/dll/win32/mswsock/msafd/sanrdma.c index 3e062e90d63..bd1ad2806dc 100644 --- a/dll/win32/mswsock/msafd/sanrdma.c +++ b/dll/win32/mswsock/msafd/sanrdma.c @@ -12,45 +12,3 @@ /* FUNCTIONS *****************************************************************/ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - diff --git a/dll/win32/mswsock/msafd/sanrecv.c b/dll/win32/mswsock/msafd/sanrecv.c index 3e062e90d63..bd1ad2806dc 100644 --- a/dll/win32/mswsock/msafd/sanrecv.c +++ b/dll/win32/mswsock/msafd/sanrecv.c @@ -12,45 +12,3 @@ /* FUNCTIONS *****************************************************************/ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - diff --git a/dll/win32/mswsock/msafd/sansend.c b/dll/win32/mswsock/msafd/sansend.c index 3e062e90d63..bd1ad2806dc 100644 --- a/dll/win32/mswsock/msafd/sansend.c +++ b/dll/win32/mswsock/msafd/sansend.c @@ -12,45 +12,3 @@ /* FUNCTIONS *****************************************************************/ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - diff --git a/dll/win32/mswsock/msafd/sanshutd.c b/dll/win32/mswsock/msafd/sanshutd.c index 3e062e90d63..bd1ad2806dc 100644 --- a/dll/win32/mswsock/msafd/sanshutd.c +++ b/dll/win32/mswsock/msafd/sanshutd.c @@ -12,45 +12,3 @@ /* FUNCTIONS *****************************************************************/ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - diff --git a/dll/win32/mswsock/msafd/sansock.c b/dll/win32/mswsock/msafd/sansock.c index 3e062e90d63..bd1ad2806dc 100644 --- a/dll/win32/mswsock/msafd/sansock.c +++ b/dll/win32/mswsock/msafd/sansock.c @@ -12,45 +12,3 @@ /* FUNCTIONS *****************************************************************/ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - diff --git a/dll/win32/mswsock/msafd/santf.c b/dll/win32/mswsock/msafd/santf.c index 3e062e90d63..bd1ad2806dc 100644 --- a/dll/win32/mswsock/msafd/santf.c +++ b/dll/win32/mswsock/msafd/santf.c @@ -12,45 +12,3 @@ /* FUNCTIONS *****************************************************************/ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - diff --git a/dll/win32/mswsock/msafd/sanutil.c b/dll/win32/mswsock/msafd/sanutil.c index 3e062e90d63..bd1ad2806dc 100644 --- a/dll/win32/mswsock/msafd/sanutil.c +++ b/dll/win32/mswsock/msafd/sanutil.c @@ -12,45 +12,3 @@ /* FUNCTIONS *****************************************************************/ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - diff --git a/dll/win32/mswsock/msafd/select.c b/dll/win32/mswsock/msafd/select.c index 39f4d505c85..914ac6ec6ff 100644 --- a/dll/win32/mswsock/msafd/select.c +++ b/dll/win32/mswsock/msafd/select.c @@ -986,2967 +986,3 @@ error: return OutCount; } -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -#define MSAFD_CHECK_EVENT(e, s) \ - (!(s->SharedData.AsyncDisabledEvents & e) && \ - (s->SharedData.AsyncEvents & e)) - -#define HANDLES_IN_SET(s) \ - s == NULL ? 0 : (s->fd_count & 0xFFFF) - -/* DATA **********************************************************************/ - -HANDLE SockAsyncSelectHelperHandle; -BOOLEAN SockAsyncSelectCalled; - -/* FUNCTIONS *****************************************************************/ - -BOOLEAN -WSPAPI -SockCheckAndInitAsyncSelectHelper(VOID) -{ - UNICODE_STRING AfdHelper; - OBJECT_ATTRIBUTES ObjectAttributes; - IO_STATUS_BLOCK IoStatusBlock; - NTSTATUS Status; - FILE_COMPLETION_INFORMATION CompletionInfo; - OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags; - - /* First, make sure we're not already intialized */ - if (SockAsyncSelectHelperHandle) return TRUE; - - /* Acquire the global lock */ - SockAcquireRwLockExclusive(&SocketGlobalLock); - - /* Check again, under the lock */ - if (SockAsyncSelectHelperHandle) - { - /* Return without lock */ - SockReleaseRwLockExclusive(&SocketGlobalLock); - return TRUE; - } - - /* Set up Handle Name and Object */ - RtlInitUnicodeString(&AfdHelper, L"\\Device\\Afd\\AsyncSelectHlp" ); - InitializeObjectAttributes(&ObjectAttributes, - &AfdHelper, - OBJ_INHERIT | OBJ_CASE_INSENSITIVE, - NULL, - NULL); - - /* Open the Handle to AFD */ - Status = NtCreateFile(&SockAsyncSelectHelperHandle, - GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, - &ObjectAttributes, - &IoStatusBlock, - NULL, - 0, - FILE_SHARE_READ | FILE_SHARE_WRITE, - FILE_OPEN_IF, - 0, - NULL, - 0); - if (!NT_SUCCESS(Status)) - { - /* Return without lock */ - SockReleaseRwLockExclusive(&SocketGlobalLock); - return TRUE; - } - - /* Check if the port exists, and if not, create it */ - if (SockAsyncQueuePort) SockCreateAsyncQueuePort(); - - /* - * Now Set up the Completion Port Information - * This means that whenever a Poll is finished, the routine will be executed - */ - CompletionInfo.Port = SockAsyncQueuePort; - CompletionInfo.Key = SockAsyncSelectCompletion; - Status = NtSetInformationFile(SockAsyncSelectHelperHandle, - &IoStatusBlock, - &CompletionInfo, - sizeof(CompletionInfo), - FileCompletionInformation); - - /* Protect the Handle */ - HandleFlags.ProtectFromClose = TRUE; - HandleFlags.Inherit = FALSE; - Status = NtSetInformationObject(SockAsyncQueuePort, - ObjectHandleFlagInformation, - &HandleFlags, - sizeof(HandleFlags)); - - /* - * Set this variable to true so that Send/Recv/Accept will know whether - * to renable disabled events - */ - SockAsyncSelectCalled = TRUE; - - /* Release lock and return */ - SockReleaseRwLockExclusive(&SocketGlobalLock); - return TRUE; -} - -VOID -WSPAPI -SockAsyncSelectCompletion(PVOID Context, - PIO_STATUS_BLOCK IoStatusBlock) -{ - PASYNC_DATA AsyncData = Context; - PSOCKET_INFORMATION Socket = AsyncData->ParentSocket; - ULONG Events; - INT ErrorCode; - - /* Acquire the socket lock */ - EnterCriticalSection(&Socket->Lock); - - /* Check if the socket was closed or the I/O cancelled */ - if ((Socket->SharedData.State == SocketClosed) || - (IoStatusBlock->Status == STATUS_CANCELLED)) - { - /* Return */ - LeaveCriticalSection(&Socket->Lock); - goto error; - } - - /* Check if the Sequence Number Changed behind our back */ - if (AsyncData->SequenceNumber != Socket->SharedData.SequenceNumber) - { - /* Return */ - LeaveCriticalSection(&Socket->Lock); - goto error; - } - - /* Check we were manually called b/c of a failure */ - if (!NT_SUCCESS(IoStatusBlock->Status)) - { - /* Get the error and tell WPU about it */ - ErrorCode = NtStatusToSocketError(IoStatusBlock->Status); - SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, - Socket->SharedData.wMsg, - Socket->Handle, - WSAMAKESELECTREPLY(0, ErrorCode)); - - /* Return */ - LeaveCriticalSection(&Socket->Lock); - goto error; - } - - /* Select the event bits */ - Events = AsyncData->AsyncSelectInfo.Handles[0].Events; - - /* Check for receive event */ - if (MSAFD_CHECK_EVENT(FD_READ, Socket) && (Events & AFD_EVENT_RECEIVE)) - { - /* Make the Notifcation */ - SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, - Socket->SharedData.wMsg, - Socket->Handle, - WSAMAKESELECTREPLY(FD_READ, 0)); - - /* Disable this event until the next read(); */ - Socket->SharedData.AsyncDisabledEvents |= FD_READ; - } - - /* Check for oob receive event */ - if (MSAFD_CHECK_EVENT(FD_OOB, Socket) && (Events & AFD_EVENT_OOB_RECEIVE)) - { - /* Make the Notifcation */ - SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, - Socket->SharedData.wMsg, - Socket->Handle, - WSAMAKESELECTREPLY(FD_OOB, 0)); - - /* Disable this event until the next read(); */ - Socket->SharedData.AsyncDisabledEvents |= FD_OOB; - } - - /* Check for write event */ - if (MSAFD_CHECK_EVENT(FD_WRITE, Socket) && (Events & AFD_EVENT_SEND)) - { - /* Make the Notifcation */ - SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, - Socket->SharedData.wMsg, - Socket->Handle, - WSAMAKESELECTREPLY(FD_WRITE, 0)); - - /* Disable this event until the next read(); */ - Socket->SharedData.AsyncDisabledEvents |= FD_WRITE; - } - - /* Check for accept event */ - if (MSAFD_CHECK_EVENT(FD_ACCEPT, Socket) && (Events & AFD_EVENT_ACCEPT)) - { - /* Make the Notifcation */ - SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, - Socket->SharedData.wMsg, - Socket->Handle, - WSAMAKESELECTREPLY(FD_ACCEPT, 0)); - - /* Disable this event until the next read(); */ - Socket->SharedData.AsyncDisabledEvents |= FD_ACCEPT; - } - - /* Check for close events */ - if (MSAFD_CHECK_EVENT(FD_CLOSE, Socket) && ((Events & AFD_EVENT_ACCEPT) || - (Events & AFD_EVENT_ABORT) || - (Events & AFD_EVENT_CLOSE))) - { - /* Make the Notifcation */ - SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, - Socket->SharedData.wMsg, - Socket->Handle, - WSAMAKESELECTREPLY(FD_CLOSE, 0)); - - /* Disable this event until the next read(); */ - Socket->SharedData.AsyncDisabledEvents |= FD_CLOSE; - } - - /* Check for QOS event */ - if (MSAFD_CHECK_EVENT(FD_QOS, Socket) && (Events & AFD_EVENT_QOS)) - { - /* Make the Notifcation */ - SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, - Socket->SharedData.wMsg, - Socket->Handle, - WSAMAKESELECTREPLY(FD_QOS, 0)); - - /* Disable this event until the next read(); */ - Socket->SharedData.AsyncDisabledEvents |= FD_QOS; - } - - /* Check for Group QOS event */ - if (MSAFD_CHECK_EVENT(FD_GROUP_QOS, Socket) && (Events & AFD_EVENT_GROUP_QOS)) - { - /* Make the Notifcation */ - SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, - Socket->SharedData.wMsg, - Socket->Handle, - WSAMAKESELECTREPLY(FD_GROUP_QOS, 0)); - - /* Disable this event until the next read(); */ - Socket->SharedData.AsyncDisabledEvents |= FD_GROUP_QOS; - } - - /* Check for Routing Interface Change event */ - if (MSAFD_CHECK_EVENT(FD_ROUTING_INTERFACE_CHANGE, Socket) && - (Events & AFD_EVENT_ROUTING_INTERFACE_CHANGE)) - { - /* Make the Notifcation */ - SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, - Socket->SharedData.wMsg, - Socket->Handle, - WSAMAKESELECTREPLY(FD_ROUTING_INTERFACE_CHANGE, 0)); - - /* Disable this event until the next read(); */ - Socket->SharedData.AsyncDisabledEvents |= FD_ROUTING_INTERFACE_CHANGE; - } - - /* Check for Address List Change event */ - if (MSAFD_CHECK_EVENT(FD_ADDRESS_LIST_CHANGE, Socket) && - (Events & AFD_EVENT_ADDRESS_LIST_CHANGE)) - { - /* Make the Notifcation */ - SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, - Socket->SharedData.wMsg, - Socket->Handle, - WSAMAKESELECTREPLY(FD_ADDRESS_LIST_CHANGE, 0)); - - /* Disable this event until the next read(); */ - Socket->SharedData.AsyncDisabledEvents |= FD_ADDRESS_LIST_CHANGE; - } - - /* Check if there are any events left for us to check */ - if (!((Socket->SharedData.AsyncEvents) & - (~Socket->SharedData.AsyncDisabledEvents))) - { - /* Nothing left, release lock and return */ - LeaveCriticalSection(&Socket->Lock); - goto error; - } - - /* Keep Polling */ - SockProcessAsyncSelect(Socket, AsyncData); - - /* Leave lock and return */ - LeaveCriticalSection(&Socket->Lock); - return; - -error: - /* Dereference the socket and free the Async Data */ - SockDereferenceSocket(Socket); - RtlFreeHeap(SockPrivateHeap, 0, AsyncData); - - /* Dereference this thread and return */ - InterlockedDecrement(&SockAsyncThreadReferenceCount); - return; -} - -VOID -WSPAPI -SockProcessAsyncSelect(PSOCKET_INFORMATION Socket, - PASYNC_DATA AsyncData) -{ - ULONG lNetworkEvents; - NTSTATUS Status; - - /* Set up the Async Data Event Info */ - AsyncData->AsyncSelectInfo.Timeout.HighPart = 0x7FFFFFFF; - AsyncData->AsyncSelectInfo.Timeout.LowPart = 0xFFFFFFFF; - AsyncData->AsyncSelectInfo.HandleCount = 1; - AsyncData->AsyncSelectInfo.Exclusive = TRUE; - AsyncData->AsyncSelectInfo.Handles[0].Handle = (SOCKET)Socket->WshContext.Handle; - AsyncData->AsyncSelectInfo.Handles[0].Events = 0; - - /* Remove unwanted events */ - lNetworkEvents = Socket->SharedData.AsyncEvents & - (~Socket->SharedData.AsyncDisabledEvents); - - /* Set Events to wait for */ - if (lNetworkEvents & FD_READ) - { - AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_RECEIVE; - } - if (lNetworkEvents & FD_WRITE) - { - AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_SEND; - } - if (lNetworkEvents & FD_OOB) - { - AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_OOB_RECEIVE; - } - if (lNetworkEvents & FD_ACCEPT) - { - AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_ACCEPT; - } - if (lNetworkEvents & FD_CLOSE) - { - AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_DISCONNECT | - AFD_EVENT_ABORT | - AFD_EVENT_CLOSE; - } - if (lNetworkEvents & FD_QOS) - { - AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_QOS; - } - if (lNetworkEvents & FD_GROUP_QOS) - { - AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_GROUP_QOS; - } - if (lNetworkEvents & FD_ROUTING_INTERFACE_CHANGE) - { - AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_ROUTING_INTERFACE_CHANGE; - } - if (lNetworkEvents & FD_ADDRESS_LIST_CHANGE) - { - AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_ADDRESS_LIST_CHANGE; - } - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(SockAsyncSelectHelperHandle, - NULL, - NULL, - AsyncData, - &AsyncData->IoStatusBlock, - IOCTL_AFD_SELECT, - &AsyncData->AsyncSelectInfo, - sizeof(AsyncData->AsyncSelectInfo), - &AsyncData->AsyncSelectInfo, - sizeof(AsyncData->AsyncSelectInfo)); - /* Check for failure */ - if (NT_ERROR(Status)) - { - /* I/O Manager Won't call the completion routine; do it manually */ - AsyncData->IoStatusBlock.Status = Status; - SockAsyncSelectCompletion(AsyncData, &AsyncData->IoStatusBlock); - } -} - -VOID -WSPAPI -SockProcessQueuedAsyncSelect(PVOID Context, - PIO_STATUS_BLOCK IoStatusBlock) -{ - PASYNC_DATA AsyncData = Context; - PSOCKET_INFORMATION Socket = AsyncData->ParentSocket; - - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* Make sure it's not closed */ - if (Socket->SharedData.State == SocketClosed) - { - /* Return */ - LeaveCriticalSection(&Socket->Lock); - goto error; - } - - /* Check if the Sequence Number changed by now */ - if (AsyncData->SequenceNumber != Socket->SharedData.SequenceNumber) - { - /* Return */ - LeaveCriticalSection(&Socket->Lock); - goto error; - } - - /* Check if select is needed */ - if (!((Socket->SharedData.AsyncEvents & - ~Socket->SharedData.AsyncDisabledEvents))) - { - /* Return */ - LeaveCriticalSection(&Socket->Lock); - goto error; - } - - /* Do the actual select */ - SockProcessAsyncSelect(Socket, AsyncData); - - /* Return */ - LeaveCriticalSection(&Socket->Lock); - return; - -error: - /* Dereference the socket and free the async data */ - SockDereferenceSocket(Socket); - RtlFreeHeap(SockPrivateHeap, 0, AsyncData); - - /* Dereference this thread */ - InterlockedDecrement(&SockAsyncThreadReferenceCount); -} - -INT -WSPAPI -SockReenableAsyncSelectEvent(IN PSOCKET_INFORMATION Socket, - IN ULONG Event) -{ - PASYNC_DATA AsyncData; - NTSTATUS Status; - - /* Make sure the event is actually disabled */ - if (!(Socket->SharedData.AsyncDisabledEvents & Event)) return NO_ERROR; - - /* Make sure we're not closed */ - if (Socket->SharedData.State == SocketClosed) return NO_ERROR; - - /* Re-enable it */ - Socket->SharedData.AsyncDisabledEvents &= ~Event; - - /* Return if no more events are being polled */ - if (!((Socket->SharedData.AsyncEvents & - ~Socket->SharedData.AsyncDisabledEvents))) - { - return NO_ERROR; - } - - /* Allocate Async Data */ - AsyncData = SockAllocateHeapRoutine(SockPrivateHeap, 0, sizeof(ASYNC_DATA)); - - /* Increase the sequence number to stop anything else */ - Socket->SharedData.SequenceNumber++; - - /* Set up the Async Data */ - AsyncData->ParentSocket = Socket; - AsyncData->SequenceNumber = Socket->SharedData.SequenceNumber; - - /* Begin Async Select by using I/O Completion */ - Status = NtSetIoCompletion(SockAsyncQueuePort, - (PVOID)&SockProcessQueuedAsyncSelect, - AsyncData, - 0, - 0); - if (!NT_SUCCESS(Status)) - { - /* Dereference the socket and fail */ - SockDereferenceSocket(Socket); - RtlFreeHeap(SockPrivateHeap, 0, AsyncData); - return NtStatusToSocketError(Status); - } - - /* All done */ - return NO_ERROR; -} - -INT -WSPAPI -SockAsyncSelectHelper(IN PSOCKET_INFORMATION Socket, - IN HWND hWnd, - IN UINT wMsg, - IN LONG lEvent) -{ - PASYNC_DATA AsyncData = NULL; - BOOLEAN BlockMode; - NTSTATUS Status; - INT ErrorCode; - - /* Allocate the Async Data Structure to pass on to the Thread later */ - AsyncData = SockAllocateHeapRoutine(SockPrivateHeap, 0, sizeof(*AsyncData)); - if (!AsyncData) return WSAENOBUFS; - - /* Acquire socket lock */ - EnterCriticalSection(&Socket->Lock); - - /* Is there an active WSPEventSelect? */ - if (Socket->SharedData.AsyncEvents) - { - /* Call the helper to process it */ - ErrorCode = SockEventSelectHelper(Socket, NULL, 0); - if (ErrorCode != NO_ERROR) goto error; - } - - /* Set Socket to Non-Blocking */ - BlockMode = TRUE; - ErrorCode = SockSetInformation(Socket, - AFD_INFO_BLOCKING_MODE, - &BlockMode, - NULL, - NULL); - if (ErrorCode != NO_ERROR) goto error; - - /* AFD was notified, set it locally as well */ - Socket->SharedData.NonBlocking = TRUE; - - /* Store Socket Data */ - Socket->SharedData.hWnd = hWnd; - Socket->SharedData.wMsg = wMsg; - Socket->SharedData.AsyncEvents = lEvent; - Socket->SharedData.AsyncDisabledEvents = 0; - - /* Check if the socket is not connected and not a datagram socket */ - if ((!SockIsSocketConnected(Socket)) && !MSAFD_IS_DGRAM_SOCK(Socket)) - { - /* Disable FD_WRITE for now, so we don't get it before FD_CONNECT */ - Socket->SharedData.AsyncDisabledEvents |= FD_WRITE; - } - - /* Increase the sequence number */ - Socket->SharedData.SequenceNumber++; - - /* Return if there are no more Events */ - if (!(Socket->SharedData.AsyncEvents & - (~Socket->SharedData.AsyncDisabledEvents))) - { - /* Release the lock, dereference the async thread and the socket */ - LeaveCriticalSection(&Socket->Lock); - InterlockedDecrement(&SockAsyncThreadReferenceCount); - SockDereferenceSocket(Socket); - - /* Free the Async Data */ - RtlFreeHeap(SockPrivateHeap, 0, AsyncData); - return NO_ERROR; - } - - /* Set up the Async Data */ - AsyncData->ParentSocket = Socket; - AsyncData->SequenceNumber = Socket->SharedData.SequenceNumber; - - /* Release the lock now */ - LeaveCriticalSection(&Socket->Lock); - - /* Begin Async Select by using I/O Completion */ - Status = NtSetIoCompletion(SockAsyncQueuePort, - (PVOID)&SockProcessQueuedAsyncSelect, - AsyncData, - 0, - 0); - if (!NT_SUCCESS(Status)) - { - /* Dereference the async thread and fail */ - InterlockedDecrement(&SockAsyncThreadReferenceCount); - ErrorCode = NtStatusToSocketError(Status); - } - -error: - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Free the async data */ - RtlFreeHeap(SockPrivateHeap, 0, AsyncData); - - /* Fail */ - return SOCKET_ERROR; - } - - /* Increment the socket reference */ - InterlockedIncrement(&Socket->RefCount); - - /* Return success */ - return NO_ERROR; -} - -INT -WSPAPI -WSPAsyncSelect(IN SOCKET Handle, - IN HWND hWnd, - IN UINT wMsg, - IN LONG lEvent, - OUT LPINT lpErrno) -{ - PSOCKET_INFORMATION Socket; - INT ErrorCode; - PWINSOCK_TEB_DATA ThreadData; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Check for valid events */ - if (lEvent & ~FD_ALL_EVENTS) - { - /* Fail */ - ErrorCode = WSAEINVAL; - goto error; - } - - /* Check for valid window handle */ - if (!IsWindow(hWnd)) - { - /* Fail */ - ErrorCode = WSAEINVAL; - goto error; - } - - /* Create the Asynch Thread if Needed */ - if (!SockCheckAndReferenceAsyncThread()) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - - /* Open a Handle to AFD's Async Helper */ - if (!SockCheckAndInitAsyncSelectHelper()) - { - /* Dereference async thread and fail */ - InterlockedDecrement(&SockAsyncThreadReferenceCount); - ErrorCode = WSAENOBUFS; - goto error; - } - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Call the helper to do the work */ - ErrorCode = SockAsyncSelectHelper(Socket, - hWnd, - wMsg, - lEvent); - - /* Dereference the socket */ - SockDereferenceSocket(Socket); - -error: - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - -INT -WSPAPI -WSPSelect(INT nfds, - PFD_SET readfds, - PFD_SET writefds, - PFD_SET exceptfds, - CONST LPTIMEVAL timeout, - LPINT lpErrno) -{ - IO_STATUS_BLOCK IoStatusBlock; - PAFD_POLL_INFO PollInfo = NULL; - NTSTATUS Status; - CHAR PollBuffer[sizeof(AFD_POLL_INFO) + 3 * sizeof(AFD_HANDLE)]; - PAFD_HANDLE HandleArray; - ULONG HandleCount, OutCount = 0; - ULONG PollBufferSize; - ULONG i; - PWINSOCK_TEB_DATA ThreadData; - LARGE_INTEGER uSec; - ULONG BlockType; - INT ErrorCode; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* How many sockets will we check? */ - HandleCount = HANDLES_IN_SET(readfds) + - HANDLES_IN_SET(writefds) + - HANDLES_IN_SET(exceptfds); - - /* Leave if none are */ - if (!HandleCount) return NO_ERROR; - - /* How much space will they require? */ - PollBufferSize = sizeof(*PollInfo) + (HandleCount * sizeof(AFD_HANDLE)); - - /* Check if our stack is big enough to hold it */ - if (PollBufferSize <= sizeof(PollBuffer)) - { - /* Use the stack */ - PollInfo = (PVOID)PollBuffer; - } - else - { - /* Allocate from heap instead */ - PollInfo = SockAllocateHeapRoutine(SockPrivateHeap, 0, PollBufferSize); - if (!PollInfo) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - } - - /* Number of handles for AFD to Check */ - PollInfo->HandleCount = HandleCount; - PollInfo->Exclusive = FALSE; - HandleArray = PollInfo->Handles; - - /* Select the Read Events */ - for (i = 0; readfds && i < (readfds->fd_count & 0xFFFF); i++) - { - /* Fill out handle info */ - HandleArray->Handle = (SOCKET)readfds->fd_array[i]; - HandleArray->Events = AFD_EVENT_RECEIVE | - AFD_EVENT_DISCONNECT | - AFD_EVENT_ABORT; - - /* Move to the next one */ - HandleArray++; - } - for (i = 0; writefds && i < (writefds->fd_count & 0xFFFF); i++) - { - /* Fill out handle info */ - HandleArray->Handle = (SOCKET)writefds->fd_array[i]; - HandleArray->Events = AFD_EVENT_SEND; - - /* Move to the next one */ - HandleArray++; - } - for (i = 0; exceptfds && i < (exceptfds->fd_count & 0xFFFF); i++) - { - /* Fill out handle info */ - HandleArray->Handle = (SOCKET)exceptfds->fd_array[i]; - HandleArray->Events = AFD_EVENT_OOB_RECEIVE | AFD_EVENT_CONNECT_FAIL; - - /* Move to the next one */ - HandleArray++; - } - - /* Check if a timeout was given */ - if (timeout) - { - /* Inifinte Timeout */ - PollInfo->Timeout.u.LowPart = -1; - PollInfo->Timeout.u.HighPart = 0x7FFFFFFF; - } - else - { - /* Calculate microseconds */ - uSec = RtlEnlargedIntegerMultiply(timeout->tv_usec, -10); - - /* Calculate seconds */ - PollInfo->Timeout = RtlEnlargedIntegerMultiply(timeout->tv_sec, - -1 * 1000 * 1000 * 10); - - /* Add microseconds */ - PollInfo->Timeout.QuadPart += uSec.QuadPart; - } - - /* Send IOCTL */ - Status = NtDeviceIoControlFile((HANDLE)PollInfo->Handles[0].Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_SELECT, - PollInfo, - PollBufferSize, - PollInfo, - PollBufferSize); - - /* Check if we have to wait */ - if (Status == STATUS_PENDING) - { - /* Check if we'll call the blocking hook */ - if (!PollInfo->Timeout.QuadPart) BlockType = NO_BLOCKING_HOOK; - - /* Wait for completion */ - SockWaitForSingleObject(ThreadData->EventHandle, - (SOCKET)PollInfo->Handles[0].Handle, - BlockType, - NO_TIMEOUT); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check for failure */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - - /* Clear the Structures */ - if(readfds) FD_ZERO(readfds); - if(writefds) FD_ZERO(writefds); - if(exceptfds) FD_ZERO(exceptfds); - - /* Get the handle info again */ - HandleCount = PollInfo->HandleCount; - HandleArray = PollInfo->Handles; - - /* Loop the Handles that got an event */ - for (i = 0; i < HandleCount; i++) - { - /* Check for a match */ - if (HandleArray->Events & AFD_EVENT_RECEIVE) - { - /* Check if it's not already set */ - if (!FD_ISSET((SOCKET)HandleArray->Handle, readfds)) - { - /* Increase Handles with an Event */ - OutCount++; - - /* Set this handle */ - FD_SET((SOCKET)HandleArray->Handle, readfds); - } - } - /* Check for a match */ - if (HandleArray->Events & AFD_EVENT_SEND) - { - /* Check if it's not already set */ - if (!FD_ISSET((SOCKET)HandleArray->Handle, writefds)) - { - /* Increase Handles with an Event */ - OutCount++; - - /* Set this handle */ - FD_SET((SOCKET)HandleArray->Handle, writefds); - } - } - /* Check for a match */ - if (HandleArray->Events & AFD_EVENT_OOB_RECEIVE) - { - /* Check if it's not already set */ - if (!FD_ISSET((SOCKET)HandleArray->Handle, exceptfds)) - { - /* Increase Handles with an Event */ - OutCount++; - - /* Set this handle */ - FD_SET((SOCKET)HandleArray->Handle, exceptfds); - } - } - /* Check for a match */ - if (HandleArray->Events & AFD_EVENT_ACCEPT) - { - /* Check if it's not already set */ - if (!FD_ISSET((SOCKET)HandleArray->Handle, readfds)) - { - /* Increase Handles with an Event */ - OutCount++; - - /* Set this handle */ - FD_SET((SOCKET)HandleArray->Handle, readfds); - } - } - /* Check for a match */ - if (HandleArray->Events & AFD_EVENT_CONNECT) - { - /* Check if it's not already set */ - if (!FD_ISSET((SOCKET)HandleArray->Handle, writefds)) - { - /* Increase Handles with an Event */ - OutCount++; - - /* Set this handle */ - FD_SET((SOCKET)HandleArray->Handle, writefds); - } - } - /* Check for a match */ - if (HandleArray->Events & AFD_EVENT_CONNECT_FAIL) - { - /* Check if it's not already set */ - if (!FD_ISSET((SOCKET)HandleArray->Handle, exceptfds)) - { - /* Increase Handles with an Event */ - OutCount++; - - /* Set this handle */ - FD_SET((SOCKET)HandleArray->Handle, exceptfds); - } - } - /* Check for a match */ - if (HandleArray->Events & AFD_EVENT_DISCONNECT) - { - /* Check if it's not already set */ - if (!FD_ISSET((SOCKET)HandleArray->Handle, readfds)) - { - /* Increase Handles with an Event */ - OutCount++; - - /* Set this handle */ - FD_SET((SOCKET)HandleArray->Handle, readfds); - } - } - /* Check for a match */ - if (HandleArray->Events & AFD_EVENT_ABORT) - { - /* Check if it's not already set */ - if (!FD_ISSET((SOCKET)HandleArray->Handle, readfds)) - { - /* Increase Handles with an Event */ - OutCount++; - - /* Set this handle */ - FD_SET((SOCKET)HandleArray->Handle, readfds); - } - } - /* Check for a match */ - if (HandleArray->Events & AFD_EVENT_CLOSE) - { - /* Check if it's not already set */ - if (!FD_ISSET((SOCKET)HandleArray->Handle, readfds)) - { - /* Increase Handles with an Event */ - OutCount++; - - /* Set this handle */ - FD_SET((SOCKET)HandleArray->Handle, readfds); - } - } - - /* Move to next entry */ - HandleArray++; - } - -error: - - /* Check if we should free the buffer */ - if (PollInfo && (PollInfo != (PVOID)PollBuffer)) - { - /* Free it from the heap */ - RtlFreeHeap(SockPrivateHeap, 0, PollInfo); - } - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Return error */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return the number of handles */ - return OutCount; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -#define MSAFD_CHECK_EVENT(e, s) \ - (!(s->SharedData.AsyncDisabledEvents & e) && \ - (s->SharedData.AsyncEvents & e)) - -#define HANDLES_IN_SET(s) \ - s == NULL ? 0 : (s->fd_count & 0xFFFF) - -/* DATA **********************************************************************/ - -HANDLE SockAsyncSelectHelperHandle; -BOOLEAN SockAsyncSelectCalled; - -/* FUNCTIONS *****************************************************************/ - -BOOLEAN -WSPAPI -SockCheckAndInitAsyncSelectHelper(VOID) -{ - UNICODE_STRING AfdHelper; - OBJECT_ATTRIBUTES ObjectAttributes; - IO_STATUS_BLOCK IoStatusBlock; - NTSTATUS Status; - FILE_COMPLETION_INFORMATION CompletionInfo; - OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags; - - /* First, make sure we're not already intialized */ - if (SockAsyncSelectHelperHandle) return TRUE; - - /* Acquire the global lock */ - SockAcquireRwLockExclusive(&SocketGlobalLock); - - /* Check again, under the lock */ - if (SockAsyncSelectHelperHandle) - { - /* Return without lock */ - SockReleaseRwLockExclusive(&SocketGlobalLock); - return TRUE; - } - - /* Set up Handle Name and Object */ - RtlInitUnicodeString(&AfdHelper, L"\\Device\\Afd\\AsyncSelectHlp" ); - InitializeObjectAttributes(&ObjectAttributes, - &AfdHelper, - OBJ_INHERIT | OBJ_CASE_INSENSITIVE, - NULL, - NULL); - - /* Open the Handle to AFD */ - Status = NtCreateFile(&SockAsyncSelectHelperHandle, - GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, - &ObjectAttributes, - &IoStatusBlock, - NULL, - 0, - FILE_SHARE_READ | FILE_SHARE_WRITE, - FILE_OPEN_IF, - 0, - NULL, - 0); - if (!NT_SUCCESS(Status)) - { - /* Return without lock */ - SockReleaseRwLockExclusive(&SocketGlobalLock); - return TRUE; - } - - /* Check if the port exists, and if not, create it */ - if (SockAsyncQueuePort) SockCreateAsyncQueuePort(); - - /* - * Now Set up the Completion Port Information - * This means that whenever a Poll is finished, the routine will be executed - */ - CompletionInfo.Port = SockAsyncQueuePort; - CompletionInfo.Key = SockAsyncSelectCompletion; - Status = NtSetInformationFile(SockAsyncSelectHelperHandle, - &IoStatusBlock, - &CompletionInfo, - sizeof(CompletionInfo), - FileCompletionInformation); - - /* Protect the Handle */ - HandleFlags.ProtectFromClose = TRUE; - HandleFlags.Inherit = FALSE; - Status = NtSetInformationObject(SockAsyncQueuePort, - ObjectHandleFlagInformation, - &HandleFlags, - sizeof(HandleFlags)); - - /* - * Set this variable to true so that Send/Recv/Accept will know whether - * to renable disabled events - */ - SockAsyncSelectCalled = TRUE; - - /* Release lock and return */ - SockReleaseRwLockExclusive(&SocketGlobalLock); - return TRUE; -} - -VOID -WSPAPI -SockAsyncSelectCompletion(PVOID Context, - PIO_STATUS_BLOCK IoStatusBlock) -{ - PASYNC_DATA AsyncData = Context; - PSOCKET_INFORMATION Socket = AsyncData->ParentSocket; - ULONG Events; - INT ErrorCode; - - /* Acquire the socket lock */ - EnterCriticalSection(&Socket->Lock); - - /* Check if the socket was closed or the I/O cancelled */ - if ((Socket->SharedData.State == SocketClosed) || - (IoStatusBlock->Status == STATUS_CANCELLED)) - { - /* Return */ - LeaveCriticalSection(&Socket->Lock); - goto error; - } - - /* Check if the Sequence Number Changed behind our back */ - if (AsyncData->SequenceNumber != Socket->SharedData.SequenceNumber) - { - /* Return */ - LeaveCriticalSection(&Socket->Lock); - goto error; - } - - /* Check we were manually called b/c of a failure */ - if (!NT_SUCCESS(IoStatusBlock->Status)) - { - /* Get the error and tell WPU about it */ - ErrorCode = NtStatusToSocketError(IoStatusBlock->Status); - SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, - Socket->SharedData.wMsg, - Socket->Handle, - WSAMAKESELECTREPLY(0, ErrorCode)); - - /* Return */ - LeaveCriticalSection(&Socket->Lock); - goto error; - } - - /* Select the event bits */ - Events = AsyncData->AsyncSelectInfo.Handles[0].Events; - - /* Check for receive event */ - if (MSAFD_CHECK_EVENT(FD_READ, Socket) && (Events & AFD_EVENT_RECEIVE)) - { - /* Make the Notifcation */ - SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, - Socket->SharedData.wMsg, - Socket->Handle, - WSAMAKESELECTREPLY(FD_READ, 0)); - - /* Disable this event until the next read(); */ - Socket->SharedData.AsyncDisabledEvents |= FD_READ; - } - - /* Check for oob receive event */ - if (MSAFD_CHECK_EVENT(FD_OOB, Socket) && (Events & AFD_EVENT_OOB_RECEIVE)) - { - /* Make the Notifcation */ - SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, - Socket->SharedData.wMsg, - Socket->Handle, - WSAMAKESELECTREPLY(FD_OOB, 0)); - - /* Disable this event until the next read(); */ - Socket->SharedData.AsyncDisabledEvents |= FD_OOB; - } - - /* Check for write event */ - if (MSAFD_CHECK_EVENT(FD_WRITE, Socket) && (Events & AFD_EVENT_SEND)) - { - /* Make the Notifcation */ - SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, - Socket->SharedData.wMsg, - Socket->Handle, - WSAMAKESELECTREPLY(FD_WRITE, 0)); - - /* Disable this event until the next read(); */ - Socket->SharedData.AsyncDisabledEvents |= FD_WRITE; - } - - /* Check for accept event */ - if (MSAFD_CHECK_EVENT(FD_ACCEPT, Socket) && (Events & AFD_EVENT_ACCEPT)) - { - /* Make the Notifcation */ - SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, - Socket->SharedData.wMsg, - Socket->Handle, - WSAMAKESELECTREPLY(FD_ACCEPT, 0)); - - /* Disable this event until the next read(); */ - Socket->SharedData.AsyncDisabledEvents |= FD_ACCEPT; - } - - /* Check for close events */ - if (MSAFD_CHECK_EVENT(FD_CLOSE, Socket) && ((Events & AFD_EVENT_ACCEPT) || - (Events & AFD_EVENT_ABORT) || - (Events & AFD_EVENT_CLOSE))) - { - /* Make the Notifcation */ - SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, - Socket->SharedData.wMsg, - Socket->Handle, - WSAMAKESELECTREPLY(FD_CLOSE, 0)); - - /* Disable this event until the next read(); */ - Socket->SharedData.AsyncDisabledEvents |= FD_CLOSE; - } - - /* Check for QOS event */ - if (MSAFD_CHECK_EVENT(FD_QOS, Socket) && (Events & AFD_EVENT_QOS)) - { - /* Make the Notifcation */ - SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, - Socket->SharedData.wMsg, - Socket->Handle, - WSAMAKESELECTREPLY(FD_QOS, 0)); - - /* Disable this event until the next read(); */ - Socket->SharedData.AsyncDisabledEvents |= FD_QOS; - } - - /* Check for Group QOS event */ - if (MSAFD_CHECK_EVENT(FD_GROUP_QOS, Socket) && (Events & AFD_EVENT_GROUP_QOS)) - { - /* Make the Notifcation */ - SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, - Socket->SharedData.wMsg, - Socket->Handle, - WSAMAKESELECTREPLY(FD_GROUP_QOS, 0)); - - /* Disable this event until the next read(); */ - Socket->SharedData.AsyncDisabledEvents |= FD_GROUP_QOS; - } - - /* Check for Routing Interface Change event */ - if (MSAFD_CHECK_EVENT(FD_ROUTING_INTERFACE_CHANGE, Socket) && - (Events & AFD_EVENT_ROUTING_INTERFACE_CHANGE)) - { - /* Make the Notifcation */ - SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, - Socket->SharedData.wMsg, - Socket->Handle, - WSAMAKESELECTREPLY(FD_ROUTING_INTERFACE_CHANGE, 0)); - - /* Disable this event until the next read(); */ - Socket->SharedData.AsyncDisabledEvents |= FD_ROUTING_INTERFACE_CHANGE; - } - - /* Check for Address List Change event */ - if (MSAFD_CHECK_EVENT(FD_ADDRESS_LIST_CHANGE, Socket) && - (Events & AFD_EVENT_ADDRESS_LIST_CHANGE)) - { - /* Make the Notifcation */ - SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, - Socket->SharedData.wMsg, - Socket->Handle, - WSAMAKESELECTREPLY(FD_ADDRESS_LIST_CHANGE, 0)); - - /* Disable this event until the next read(); */ - Socket->SharedData.AsyncDisabledEvents |= FD_ADDRESS_LIST_CHANGE; - } - - /* Check if there are any events left for us to check */ - if (!((Socket->SharedData.AsyncEvents) & - (~Socket->SharedData.AsyncDisabledEvents))) - { - /* Nothing left, release lock and return */ - LeaveCriticalSection(&Socket->Lock); - goto error; - } - - /* Keep Polling */ - SockProcessAsyncSelect(Socket, AsyncData); - - /* Leave lock and return */ - LeaveCriticalSection(&Socket->Lock); - return; - -error: - /* Dereference the socket and free the Async Data */ - SockDereferenceSocket(Socket); - RtlFreeHeap(SockPrivateHeap, 0, AsyncData); - - /* Dereference this thread and return */ - InterlockedDecrement(&SockAsyncThreadReferenceCount); - return; -} - -VOID -WSPAPI -SockProcessAsyncSelect(PSOCKET_INFORMATION Socket, - PASYNC_DATA AsyncData) -{ - ULONG lNetworkEvents; - NTSTATUS Status; - - /* Set up the Async Data Event Info */ - AsyncData->AsyncSelectInfo.Timeout.HighPart = 0x7FFFFFFF; - AsyncData->AsyncSelectInfo.Timeout.LowPart = 0xFFFFFFFF; - AsyncData->AsyncSelectInfo.HandleCount = 1; - AsyncData->AsyncSelectInfo.Exclusive = TRUE; - AsyncData->AsyncSelectInfo.Handles[0].Handle = (SOCKET)Socket->WshContext.Handle; - AsyncData->AsyncSelectInfo.Handles[0].Events = 0; - - /* Remove unwanted events */ - lNetworkEvents = Socket->SharedData.AsyncEvents & - (~Socket->SharedData.AsyncDisabledEvents); - - /* Set Events to wait for */ - if (lNetworkEvents & FD_READ) - { - AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_RECEIVE; - } - if (lNetworkEvents & FD_WRITE) - { - AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_SEND; - } - if (lNetworkEvents & FD_OOB) - { - AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_OOB_RECEIVE; - } - if (lNetworkEvents & FD_ACCEPT) - { - AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_ACCEPT; - } - if (lNetworkEvents & FD_CLOSE) - { - AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_DISCONNECT | - AFD_EVENT_ABORT | - AFD_EVENT_CLOSE; - } - if (lNetworkEvents & FD_QOS) - { - AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_QOS; - } - if (lNetworkEvents & FD_GROUP_QOS) - { - AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_GROUP_QOS; - } - if (lNetworkEvents & FD_ROUTING_INTERFACE_CHANGE) - { - AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_ROUTING_INTERFACE_CHANGE; - } - if (lNetworkEvents & FD_ADDRESS_LIST_CHANGE) - { - AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_ADDRESS_LIST_CHANGE; - } - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(SockAsyncSelectHelperHandle, - NULL, - NULL, - AsyncData, - &AsyncData->IoStatusBlock, - IOCTL_AFD_SELECT, - &AsyncData->AsyncSelectInfo, - sizeof(AsyncData->AsyncSelectInfo), - &AsyncData->AsyncSelectInfo, - sizeof(AsyncData->AsyncSelectInfo)); - /* Check for failure */ - if (NT_ERROR(Status)) - { - /* I/O Manager Won't call the completion routine; do it manually */ - AsyncData->IoStatusBlock.Status = Status; - SockAsyncSelectCompletion(AsyncData, &AsyncData->IoStatusBlock); - } -} - -VOID -WSPAPI -SockProcessQueuedAsyncSelect(PVOID Context, - PIO_STATUS_BLOCK IoStatusBlock) -{ - PASYNC_DATA AsyncData = Context; - PSOCKET_INFORMATION Socket = AsyncData->ParentSocket; - - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* Make sure it's not closed */ - if (Socket->SharedData.State == SocketClosed) - { - /* Return */ - LeaveCriticalSection(&Socket->Lock); - goto error; - } - - /* Check if the Sequence Number changed by now */ - if (AsyncData->SequenceNumber != Socket->SharedData.SequenceNumber) - { - /* Return */ - LeaveCriticalSection(&Socket->Lock); - goto error; - } - - /* Check if select is needed */ - if (!((Socket->SharedData.AsyncEvents & - ~Socket->SharedData.AsyncDisabledEvents))) - { - /* Return */ - LeaveCriticalSection(&Socket->Lock); - goto error; - } - - /* Do the actual select */ - SockProcessAsyncSelect(Socket, AsyncData); - - /* Return */ - LeaveCriticalSection(&Socket->Lock); - return; - -error: - /* Dereference the socket and free the async data */ - SockDereferenceSocket(Socket); - RtlFreeHeap(SockPrivateHeap, 0, AsyncData); - - /* Dereference this thread */ - InterlockedDecrement(&SockAsyncThreadReferenceCount); -} - -INT -WSPAPI -SockReenableAsyncSelectEvent(IN PSOCKET_INFORMATION Socket, - IN ULONG Event) -{ - PASYNC_DATA AsyncData; - NTSTATUS Status; - - /* Make sure the event is actually disabled */ - if (!(Socket->SharedData.AsyncDisabledEvents & Event)) return NO_ERROR; - - /* Make sure we're not closed */ - if (Socket->SharedData.State == SocketClosed) return NO_ERROR; - - /* Re-enable it */ - Socket->SharedData.AsyncDisabledEvents &= ~Event; - - /* Return if no more events are being polled */ - if (!((Socket->SharedData.AsyncEvents & - ~Socket->SharedData.AsyncDisabledEvents))) - { - return NO_ERROR; - } - - /* Allocate Async Data */ - AsyncData = SockAllocateHeapRoutine(SockPrivateHeap, 0, sizeof(ASYNC_DATA)); - - /* Increase the sequence number to stop anything else */ - Socket->SharedData.SequenceNumber++; - - /* Set up the Async Data */ - AsyncData->ParentSocket = Socket; - AsyncData->SequenceNumber = Socket->SharedData.SequenceNumber; - - /* Begin Async Select by using I/O Completion */ - Status = NtSetIoCompletion(SockAsyncQueuePort, - (PVOID)&SockProcessQueuedAsyncSelect, - AsyncData, - 0, - 0); - if (!NT_SUCCESS(Status)) - { - /* Dereference the socket and fail */ - SockDereferenceSocket(Socket); - RtlFreeHeap(SockPrivateHeap, 0, AsyncData); - return NtStatusToSocketError(Status); - } - - /* All done */ - return NO_ERROR; -} - -INT -WSPAPI -SockAsyncSelectHelper(IN PSOCKET_INFORMATION Socket, - IN HWND hWnd, - IN UINT wMsg, - IN LONG lEvent) -{ - PASYNC_DATA AsyncData = NULL; - BOOLEAN BlockMode; - NTSTATUS Status; - INT ErrorCode; - - /* Allocate the Async Data Structure to pass on to the Thread later */ - AsyncData = SockAllocateHeapRoutine(SockPrivateHeap, 0, sizeof(*AsyncData)); - if (!AsyncData) return WSAENOBUFS; - - /* Acquire socket lock */ - EnterCriticalSection(&Socket->Lock); - - /* Is there an active WSPEventSelect? */ - if (Socket->SharedData.AsyncEvents) - { - /* Call the helper to process it */ - ErrorCode = SockEventSelectHelper(Socket, NULL, 0); - if (ErrorCode != NO_ERROR) goto error; - } - - /* Set Socket to Non-Blocking */ - BlockMode = TRUE; - ErrorCode = SockSetInformation(Socket, - AFD_INFO_BLOCKING_MODE, - &BlockMode, - NULL, - NULL); - if (ErrorCode != NO_ERROR) goto error; - - /* AFD was notified, set it locally as well */ - Socket->SharedData.NonBlocking = TRUE; - - /* Store Socket Data */ - Socket->SharedData.hWnd = hWnd; - Socket->SharedData.wMsg = wMsg; - Socket->SharedData.AsyncEvents = lEvent; - Socket->SharedData.AsyncDisabledEvents = 0; - - /* Check if the socket is not connected and not a datagram socket */ - if ((!SockIsSocketConnected(Socket)) && !MSAFD_IS_DGRAM_SOCK(Socket)) - { - /* Disable FD_WRITE for now, so we don't get it before FD_CONNECT */ - Socket->SharedData.AsyncDisabledEvents |= FD_WRITE; - } - - /* Increase the sequence number */ - Socket->SharedData.SequenceNumber++; - - /* Return if there are no more Events */ - if (!(Socket->SharedData.AsyncEvents & - (~Socket->SharedData.AsyncDisabledEvents))) - { - /* Release the lock, dereference the async thread and the socket */ - LeaveCriticalSection(&Socket->Lock); - InterlockedDecrement(&SockAsyncThreadReferenceCount); - SockDereferenceSocket(Socket); - - /* Free the Async Data */ - RtlFreeHeap(SockPrivateHeap, 0, AsyncData); - return NO_ERROR; - } - - /* Set up the Async Data */ - AsyncData->ParentSocket = Socket; - AsyncData->SequenceNumber = Socket->SharedData.SequenceNumber; - - /* Release the lock now */ - LeaveCriticalSection(&Socket->Lock); - - /* Begin Async Select by using I/O Completion */ - Status = NtSetIoCompletion(SockAsyncQueuePort, - (PVOID)&SockProcessQueuedAsyncSelect, - AsyncData, - 0, - 0); - if (!NT_SUCCESS(Status)) - { - /* Dereference the async thread and fail */ - InterlockedDecrement(&SockAsyncThreadReferenceCount); - ErrorCode = NtStatusToSocketError(Status); - } - -error: - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Free the async data */ - RtlFreeHeap(SockPrivateHeap, 0, AsyncData); - - /* Fail */ - return SOCKET_ERROR; - } - - /* Increment the socket reference */ - InterlockedIncrement(&Socket->RefCount); - - /* Return success */ - return NO_ERROR; -} - -INT -WSPAPI -WSPAsyncSelect(IN SOCKET Handle, - IN HWND hWnd, - IN UINT wMsg, - IN LONG lEvent, - OUT LPINT lpErrno) -{ - PSOCKET_INFORMATION Socket; - INT ErrorCode; - PWINSOCK_TEB_DATA ThreadData; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Check for valid events */ - if (lEvent & ~FD_ALL_EVENTS) - { - /* Fail */ - ErrorCode = WSAEINVAL; - goto error; - } - - /* Check for valid window handle */ - if (!IsWindow(hWnd)) - { - /* Fail */ - ErrorCode = WSAEINVAL; - goto error; - } - - /* Create the Asynch Thread if Needed */ - if (!SockCheckAndReferenceAsyncThread()) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - - /* Open a Handle to AFD's Async Helper */ - if (!SockCheckAndInitAsyncSelectHelper()) - { - /* Dereference async thread and fail */ - InterlockedDecrement(&SockAsyncThreadReferenceCount); - ErrorCode = WSAENOBUFS; - goto error; - } - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Call the helper to do the work */ - ErrorCode = SockAsyncSelectHelper(Socket, - hWnd, - wMsg, - lEvent); - - /* Dereference the socket */ - SockDereferenceSocket(Socket); - -error: - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - -INT -WSPAPI -WSPSelect(INT nfds, - PFD_SET readfds, - PFD_SET writefds, - PFD_SET exceptfds, - CONST LPTIMEVAL timeout, - LPINT lpErrno) -{ - IO_STATUS_BLOCK IoStatusBlock; - PAFD_POLL_INFO PollInfo = NULL; - NTSTATUS Status; - CHAR PollBuffer[sizeof(AFD_POLL_INFO) + 3 * sizeof(AFD_HANDLE)]; - PAFD_HANDLE HandleArray; - ULONG HandleCount, OutCount = 0; - ULONG PollBufferSize; - ULONG i; - PWINSOCK_TEB_DATA ThreadData; - LARGE_INTEGER uSec; - ULONG BlockType; - INT ErrorCode; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* How many sockets will we check? */ - HandleCount = HANDLES_IN_SET(readfds) + - HANDLES_IN_SET(writefds) + - HANDLES_IN_SET(exceptfds); - - /* Leave if none are */ - if (!HandleCount) return NO_ERROR; - - /* How much space will they require? */ - PollBufferSize = sizeof(*PollInfo) + (HandleCount * sizeof(AFD_HANDLE)); - - /* Check if our stack is big enough to hold it */ - if (PollBufferSize <= sizeof(PollBuffer)) - { - /* Use the stack */ - PollInfo = (PVOID)PollBuffer; - } - else - { - /* Allocate from heap instead */ - PollInfo = SockAllocateHeapRoutine(SockPrivateHeap, 0, PollBufferSize); - if (!PollInfo) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - } - - /* Number of handles for AFD to Check */ - PollInfo->HandleCount = HandleCount; - PollInfo->Exclusive = FALSE; - HandleArray = PollInfo->Handles; - - /* Select the Read Events */ - for (i = 0; readfds && i < (readfds->fd_count & 0xFFFF); i++) - { - /* Fill out handle info */ - HandleArray->Handle = (SOCKET)readfds->fd_array[i]; - HandleArray->Events = AFD_EVENT_RECEIVE | - AFD_EVENT_DISCONNECT | - AFD_EVENT_ABORT; - - /* Move to the next one */ - HandleArray++; - } - for (i = 0; writefds && i < (writefds->fd_count & 0xFFFF); i++) - { - /* Fill out handle info */ - HandleArray->Handle = (SOCKET)writefds->fd_array[i]; - HandleArray->Events = AFD_EVENT_SEND; - - /* Move to the next one */ - HandleArray++; - } - for (i = 0; exceptfds && i < (exceptfds->fd_count & 0xFFFF); i++) - { - /* Fill out handle info */ - HandleArray->Handle = (SOCKET)exceptfds->fd_array[i]; - HandleArray->Events = AFD_EVENT_OOB_RECEIVE | AFD_EVENT_CONNECT_FAIL; - - /* Move to the next one */ - HandleArray++; - } - - /* Check if a timeout was given */ - if (timeout) - { - /* Inifinte Timeout */ - PollInfo->Timeout.u.LowPart = -1; - PollInfo->Timeout.u.HighPart = 0x7FFFFFFF; - } - else - { - /* Calculate microseconds */ - uSec = RtlEnlargedIntegerMultiply(timeout->tv_usec, -10); - - /* Calculate seconds */ - PollInfo->Timeout = RtlEnlargedIntegerMultiply(timeout->tv_sec, - -1 * 1000 * 1000 * 10); - - /* Add microseconds */ - PollInfo->Timeout.QuadPart += uSec.QuadPart; - } - - /* Send IOCTL */ - Status = NtDeviceIoControlFile((HANDLE)PollInfo->Handles[0].Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_SELECT, - PollInfo, - PollBufferSize, - PollInfo, - PollBufferSize); - - /* Check if we have to wait */ - if (Status == STATUS_PENDING) - { - /* Check if we'll call the blocking hook */ - if (!PollInfo->Timeout.QuadPart) BlockType = NO_BLOCKING_HOOK; - - /* Wait for completion */ - SockWaitForSingleObject(ThreadData->EventHandle, - (SOCKET)PollInfo->Handles[0].Handle, - BlockType, - NO_TIMEOUT); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check for failure */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - - /* Clear the Structures */ - if(readfds) FD_ZERO(readfds); - if(writefds) FD_ZERO(writefds); - if(exceptfds) FD_ZERO(exceptfds); - - /* Get the handle info again */ - HandleCount = PollInfo->HandleCount; - HandleArray = PollInfo->Handles; - - /* Loop the Handles that got an event */ - for (i = 0; i < HandleCount; i++) - { - /* Check for a match */ - if (HandleArray->Events & AFD_EVENT_RECEIVE) - { - /* Check if it's not already set */ - if (!FD_ISSET((SOCKET)HandleArray->Handle, readfds)) - { - /* Increase Handles with an Event */ - OutCount++; - - /* Set this handle */ - FD_SET((SOCKET)HandleArray->Handle, readfds); - } - } - /* Check for a match */ - if (HandleArray->Events & AFD_EVENT_SEND) - { - /* Check if it's not already set */ - if (!FD_ISSET((SOCKET)HandleArray->Handle, writefds)) - { - /* Increase Handles with an Event */ - OutCount++; - - /* Set this handle */ - FD_SET((SOCKET)HandleArray->Handle, writefds); - } - } - /* Check for a match */ - if (HandleArray->Events & AFD_EVENT_OOB_RECEIVE) - { - /* Check if it's not already set */ - if (!FD_ISSET((SOCKET)HandleArray->Handle, exceptfds)) - { - /* Increase Handles with an Event */ - OutCount++; - - /* Set this handle */ - FD_SET((SOCKET)HandleArray->Handle, exceptfds); - } - } - /* Check for a match */ - if (HandleArray->Events & AFD_EVENT_ACCEPT) - { - /* Check if it's not already set */ - if (!FD_ISSET((SOCKET)HandleArray->Handle, readfds)) - { - /* Increase Handles with an Event */ - OutCount++; - - /* Set this handle */ - FD_SET((SOCKET)HandleArray->Handle, readfds); - } - } - /* Check for a match */ - if (HandleArray->Events & AFD_EVENT_CONNECT) - { - /* Check if it's not already set */ - if (!FD_ISSET((SOCKET)HandleArray->Handle, writefds)) - { - /* Increase Handles with an Event */ - OutCount++; - - /* Set this handle */ - FD_SET((SOCKET)HandleArray->Handle, writefds); - } - } - /* Check for a match */ - if (HandleArray->Events & AFD_EVENT_CONNECT_FAIL) - { - /* Check if it's not already set */ - if (!FD_ISSET((SOCKET)HandleArray->Handle, exceptfds)) - { - /* Increase Handles with an Event */ - OutCount++; - - /* Set this handle */ - FD_SET((SOCKET)HandleArray->Handle, exceptfds); - } - } - /* Check for a match */ - if (HandleArray->Events & AFD_EVENT_DISCONNECT) - { - /* Check if it's not already set */ - if (!FD_ISSET((SOCKET)HandleArray->Handle, readfds)) - { - /* Increase Handles with an Event */ - OutCount++; - - /* Set this handle */ - FD_SET((SOCKET)HandleArray->Handle, readfds); - } - } - /* Check for a match */ - if (HandleArray->Events & AFD_EVENT_ABORT) - { - /* Check if it's not already set */ - if (!FD_ISSET((SOCKET)HandleArray->Handle, readfds)) - { - /* Increase Handles with an Event */ - OutCount++; - - /* Set this handle */ - FD_SET((SOCKET)HandleArray->Handle, readfds); - } - } - /* Check for a match */ - if (HandleArray->Events & AFD_EVENT_CLOSE) - { - /* Check if it's not already set */ - if (!FD_ISSET((SOCKET)HandleArray->Handle, readfds)) - { - /* Increase Handles with an Event */ - OutCount++; - - /* Set this handle */ - FD_SET((SOCKET)HandleArray->Handle, readfds); - } - } - - /* Move to next entry */ - HandleArray++; - } - -error: - - /* Check if we should free the buffer */ - if (PollInfo && (PollInfo != (PVOID)PollBuffer)) - { - /* Free it from the heap */ - RtlFreeHeap(SockPrivateHeap, 0, PollInfo); - } - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Return error */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return the number of handles */ - return OutCount; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -#define MSAFD_CHECK_EVENT(e, s) \ - (!(s->SharedData.AsyncDisabledEvents & e) && \ - (s->SharedData.AsyncEvents & e)) - -#define HANDLES_IN_SET(s) \ - s == NULL ? 0 : (s->fd_count & 0xFFFF) - -/* DATA **********************************************************************/ - -HANDLE SockAsyncSelectHelperHandle; -BOOLEAN SockAsyncSelectCalled; - -/* FUNCTIONS *****************************************************************/ - -BOOLEAN -WSPAPI -SockCheckAndInitAsyncSelectHelper(VOID) -{ - UNICODE_STRING AfdHelper; - OBJECT_ATTRIBUTES ObjectAttributes; - IO_STATUS_BLOCK IoStatusBlock; - NTSTATUS Status; - FILE_COMPLETION_INFORMATION CompletionInfo; - OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags; - - /* First, make sure we're not already intialized */ - if (SockAsyncSelectHelperHandle) return TRUE; - - /* Acquire the global lock */ - SockAcquireRwLockExclusive(&SocketGlobalLock); - - /* Check again, under the lock */ - if (SockAsyncSelectHelperHandle) - { - /* Return without lock */ - SockReleaseRwLockExclusive(&SocketGlobalLock); - return TRUE; - } - - /* Set up Handle Name and Object */ - RtlInitUnicodeString(&AfdHelper, L"\\Device\\Afd\\AsyncSelectHlp" ); - InitializeObjectAttributes(&ObjectAttributes, - &AfdHelper, - OBJ_INHERIT | OBJ_CASE_INSENSITIVE, - NULL, - NULL); - - /* Open the Handle to AFD */ - Status = NtCreateFile(&SockAsyncSelectHelperHandle, - GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, - &ObjectAttributes, - &IoStatusBlock, - NULL, - 0, - FILE_SHARE_READ | FILE_SHARE_WRITE, - FILE_OPEN_IF, - 0, - NULL, - 0); - if (!NT_SUCCESS(Status)) - { - /* Return without lock */ - SockReleaseRwLockExclusive(&SocketGlobalLock); - return TRUE; - } - - /* Check if the port exists, and if not, create it */ - if (SockAsyncQueuePort) SockCreateAsyncQueuePort(); - - /* - * Now Set up the Completion Port Information - * This means that whenever a Poll is finished, the routine will be executed - */ - CompletionInfo.Port = SockAsyncQueuePort; - CompletionInfo.Key = SockAsyncSelectCompletion; - Status = NtSetInformationFile(SockAsyncSelectHelperHandle, - &IoStatusBlock, - &CompletionInfo, - sizeof(CompletionInfo), - FileCompletionInformation); - - /* Protect the Handle */ - HandleFlags.ProtectFromClose = TRUE; - HandleFlags.Inherit = FALSE; - Status = NtSetInformationObject(SockAsyncQueuePort, - ObjectHandleFlagInformation, - &HandleFlags, - sizeof(HandleFlags)); - - /* - * Set this variable to true so that Send/Recv/Accept will know whether - * to renable disabled events - */ - SockAsyncSelectCalled = TRUE; - - /* Release lock and return */ - SockReleaseRwLockExclusive(&SocketGlobalLock); - return TRUE; -} - -VOID -WSPAPI -SockAsyncSelectCompletion(PVOID Context, - PIO_STATUS_BLOCK IoStatusBlock) -{ - PASYNC_DATA AsyncData = Context; - PSOCKET_INFORMATION Socket = AsyncData->ParentSocket; - ULONG Events; - INT ErrorCode; - - /* Acquire the socket lock */ - EnterCriticalSection(&Socket->Lock); - - /* Check if the socket was closed or the I/O cancelled */ - if ((Socket->SharedData.State == SocketClosed) || - (IoStatusBlock->Status == STATUS_CANCELLED)) - { - /* Return */ - LeaveCriticalSection(&Socket->Lock); - goto error; - } - - /* Check if the Sequence Number Changed behind our back */ - if (AsyncData->SequenceNumber != Socket->SharedData.SequenceNumber) - { - /* Return */ - LeaveCriticalSection(&Socket->Lock); - goto error; - } - - /* Check we were manually called b/c of a failure */ - if (!NT_SUCCESS(IoStatusBlock->Status)) - { - /* Get the error and tell WPU about it */ - ErrorCode = NtStatusToSocketError(IoStatusBlock->Status); - SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, - Socket->SharedData.wMsg, - Socket->Handle, - WSAMAKESELECTREPLY(0, ErrorCode)); - - /* Return */ - LeaveCriticalSection(&Socket->Lock); - goto error; - } - - /* Select the event bits */ - Events = AsyncData->AsyncSelectInfo.Handles[0].Events; - - /* Check for receive event */ - if (MSAFD_CHECK_EVENT(FD_READ, Socket) && (Events & AFD_EVENT_RECEIVE)) - { - /* Make the Notifcation */ - SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, - Socket->SharedData.wMsg, - Socket->Handle, - WSAMAKESELECTREPLY(FD_READ, 0)); - - /* Disable this event until the next read(); */ - Socket->SharedData.AsyncDisabledEvents |= FD_READ; - } - - /* Check for oob receive event */ - if (MSAFD_CHECK_EVENT(FD_OOB, Socket) && (Events & AFD_EVENT_OOB_RECEIVE)) - { - /* Make the Notifcation */ - SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, - Socket->SharedData.wMsg, - Socket->Handle, - WSAMAKESELECTREPLY(FD_OOB, 0)); - - /* Disable this event until the next read(); */ - Socket->SharedData.AsyncDisabledEvents |= FD_OOB; - } - - /* Check for write event */ - if (MSAFD_CHECK_EVENT(FD_WRITE, Socket) && (Events & AFD_EVENT_SEND)) - { - /* Make the Notifcation */ - SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, - Socket->SharedData.wMsg, - Socket->Handle, - WSAMAKESELECTREPLY(FD_WRITE, 0)); - - /* Disable this event until the next read(); */ - Socket->SharedData.AsyncDisabledEvents |= FD_WRITE; - } - - /* Check for accept event */ - if (MSAFD_CHECK_EVENT(FD_ACCEPT, Socket) && (Events & AFD_EVENT_ACCEPT)) - { - /* Make the Notifcation */ - SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, - Socket->SharedData.wMsg, - Socket->Handle, - WSAMAKESELECTREPLY(FD_ACCEPT, 0)); - - /* Disable this event until the next read(); */ - Socket->SharedData.AsyncDisabledEvents |= FD_ACCEPT; - } - - /* Check for close events */ - if (MSAFD_CHECK_EVENT(FD_CLOSE, Socket) && ((Events & AFD_EVENT_ACCEPT) || - (Events & AFD_EVENT_ABORT) || - (Events & AFD_EVENT_CLOSE))) - { - /* Make the Notifcation */ - SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, - Socket->SharedData.wMsg, - Socket->Handle, - WSAMAKESELECTREPLY(FD_CLOSE, 0)); - - /* Disable this event until the next read(); */ - Socket->SharedData.AsyncDisabledEvents |= FD_CLOSE; - } - - /* Check for QOS event */ - if (MSAFD_CHECK_EVENT(FD_QOS, Socket) && (Events & AFD_EVENT_QOS)) - { - /* Make the Notifcation */ - SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, - Socket->SharedData.wMsg, - Socket->Handle, - WSAMAKESELECTREPLY(FD_QOS, 0)); - - /* Disable this event until the next read(); */ - Socket->SharedData.AsyncDisabledEvents |= FD_QOS; - } - - /* Check for Group QOS event */ - if (MSAFD_CHECK_EVENT(FD_GROUP_QOS, Socket) && (Events & AFD_EVENT_GROUP_QOS)) - { - /* Make the Notifcation */ - SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, - Socket->SharedData.wMsg, - Socket->Handle, - WSAMAKESELECTREPLY(FD_GROUP_QOS, 0)); - - /* Disable this event until the next read(); */ - Socket->SharedData.AsyncDisabledEvents |= FD_GROUP_QOS; - } - - /* Check for Routing Interface Change event */ - if (MSAFD_CHECK_EVENT(FD_ROUTING_INTERFACE_CHANGE, Socket) && - (Events & AFD_EVENT_ROUTING_INTERFACE_CHANGE)) - { - /* Make the Notifcation */ - SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, - Socket->SharedData.wMsg, - Socket->Handle, - WSAMAKESELECTREPLY(FD_ROUTING_INTERFACE_CHANGE, 0)); - - /* Disable this event until the next read(); */ - Socket->SharedData.AsyncDisabledEvents |= FD_ROUTING_INTERFACE_CHANGE; - } - - /* Check for Address List Change event */ - if (MSAFD_CHECK_EVENT(FD_ADDRESS_LIST_CHANGE, Socket) && - (Events & AFD_EVENT_ADDRESS_LIST_CHANGE)) - { - /* Make the Notifcation */ - SockUpcallTable->lpWPUPostMessage(Socket->SharedData.hWnd, - Socket->SharedData.wMsg, - Socket->Handle, - WSAMAKESELECTREPLY(FD_ADDRESS_LIST_CHANGE, 0)); - - /* Disable this event until the next read(); */ - Socket->SharedData.AsyncDisabledEvents |= FD_ADDRESS_LIST_CHANGE; - } - - /* Check if there are any events left for us to check */ - if (!((Socket->SharedData.AsyncEvents) & - (~Socket->SharedData.AsyncDisabledEvents))) - { - /* Nothing left, release lock and return */ - LeaveCriticalSection(&Socket->Lock); - goto error; - } - - /* Keep Polling */ - SockProcessAsyncSelect(Socket, AsyncData); - - /* Leave lock and return */ - LeaveCriticalSection(&Socket->Lock); - return; - -error: - /* Dereference the socket and free the Async Data */ - SockDereferenceSocket(Socket); - RtlFreeHeap(SockPrivateHeap, 0, AsyncData); - - /* Dereference this thread and return */ - InterlockedDecrement(&SockAsyncThreadReferenceCount); - return; -} - -VOID -WSPAPI -SockProcessAsyncSelect(PSOCKET_INFORMATION Socket, - PASYNC_DATA AsyncData) -{ - ULONG lNetworkEvents; - NTSTATUS Status; - - /* Set up the Async Data Event Info */ - AsyncData->AsyncSelectInfo.Timeout.HighPart = 0x7FFFFFFF; - AsyncData->AsyncSelectInfo.Timeout.LowPart = 0xFFFFFFFF; - AsyncData->AsyncSelectInfo.HandleCount = 1; - AsyncData->AsyncSelectInfo.Exclusive = TRUE; - AsyncData->AsyncSelectInfo.Handles[0].Handle = (SOCKET)Socket->WshContext.Handle; - AsyncData->AsyncSelectInfo.Handles[0].Events = 0; - - /* Remove unwanted events */ - lNetworkEvents = Socket->SharedData.AsyncEvents & - (~Socket->SharedData.AsyncDisabledEvents); - - /* Set Events to wait for */ - if (lNetworkEvents & FD_READ) - { - AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_RECEIVE; - } - if (lNetworkEvents & FD_WRITE) - { - AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_SEND; - } - if (lNetworkEvents & FD_OOB) - { - AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_OOB_RECEIVE; - } - if (lNetworkEvents & FD_ACCEPT) - { - AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_ACCEPT; - } - if (lNetworkEvents & FD_CLOSE) - { - AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_DISCONNECT | - AFD_EVENT_ABORT | - AFD_EVENT_CLOSE; - } - if (lNetworkEvents & FD_QOS) - { - AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_QOS; - } - if (lNetworkEvents & FD_GROUP_QOS) - { - AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_GROUP_QOS; - } - if (lNetworkEvents & FD_ROUTING_INTERFACE_CHANGE) - { - AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_ROUTING_INTERFACE_CHANGE; - } - if (lNetworkEvents & FD_ADDRESS_LIST_CHANGE) - { - AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_ADDRESS_LIST_CHANGE; - } - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(SockAsyncSelectHelperHandle, - NULL, - NULL, - AsyncData, - &AsyncData->IoStatusBlock, - IOCTL_AFD_SELECT, - &AsyncData->AsyncSelectInfo, - sizeof(AsyncData->AsyncSelectInfo), - &AsyncData->AsyncSelectInfo, - sizeof(AsyncData->AsyncSelectInfo)); - /* Check for failure */ - if (NT_ERROR(Status)) - { - /* I/O Manager Won't call the completion routine; do it manually */ - AsyncData->IoStatusBlock.Status = Status; - SockAsyncSelectCompletion(AsyncData, &AsyncData->IoStatusBlock); - } -} - -VOID -WSPAPI -SockProcessQueuedAsyncSelect(PVOID Context, - PIO_STATUS_BLOCK IoStatusBlock) -{ - PASYNC_DATA AsyncData = Context; - PSOCKET_INFORMATION Socket = AsyncData->ParentSocket; - - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* Make sure it's not closed */ - if (Socket->SharedData.State == SocketClosed) - { - /* Return */ - LeaveCriticalSection(&Socket->Lock); - goto error; - } - - /* Check if the Sequence Number changed by now */ - if (AsyncData->SequenceNumber != Socket->SharedData.SequenceNumber) - { - /* Return */ - LeaveCriticalSection(&Socket->Lock); - goto error; - } - - /* Check if select is needed */ - if (!((Socket->SharedData.AsyncEvents & - ~Socket->SharedData.AsyncDisabledEvents))) - { - /* Return */ - LeaveCriticalSection(&Socket->Lock); - goto error; - } - - /* Do the actual select */ - SockProcessAsyncSelect(Socket, AsyncData); - - /* Return */ - LeaveCriticalSection(&Socket->Lock); - return; - -error: - /* Dereference the socket and free the async data */ - SockDereferenceSocket(Socket); - RtlFreeHeap(SockPrivateHeap, 0, AsyncData); - - /* Dereference this thread */ - InterlockedDecrement(&SockAsyncThreadReferenceCount); -} - -INT -WSPAPI -SockReenableAsyncSelectEvent(IN PSOCKET_INFORMATION Socket, - IN ULONG Event) -{ - PASYNC_DATA AsyncData; - NTSTATUS Status; - - /* Make sure the event is actually disabled */ - if (!(Socket->SharedData.AsyncDisabledEvents & Event)) return NO_ERROR; - - /* Make sure we're not closed */ - if (Socket->SharedData.State == SocketClosed) return NO_ERROR; - - /* Re-enable it */ - Socket->SharedData.AsyncDisabledEvents &= ~Event; - - /* Return if no more events are being polled */ - if (!((Socket->SharedData.AsyncEvents & - ~Socket->SharedData.AsyncDisabledEvents))) - { - return NO_ERROR; - } - - /* Allocate Async Data */ - AsyncData = SockAllocateHeapRoutine(SockPrivateHeap, 0, sizeof(ASYNC_DATA)); - - /* Increase the sequence number to stop anything else */ - Socket->SharedData.SequenceNumber++; - - /* Set up the Async Data */ - AsyncData->ParentSocket = Socket; - AsyncData->SequenceNumber = Socket->SharedData.SequenceNumber; - - /* Begin Async Select by using I/O Completion */ - Status = NtSetIoCompletion(SockAsyncQueuePort, - (PVOID)&SockProcessQueuedAsyncSelect, - AsyncData, - 0, - 0); - if (!NT_SUCCESS(Status)) - { - /* Dereference the socket and fail */ - SockDereferenceSocket(Socket); - RtlFreeHeap(SockPrivateHeap, 0, AsyncData); - return NtStatusToSocketError(Status); - } - - /* All done */ - return NO_ERROR; -} - -INT -WSPAPI -SockAsyncSelectHelper(IN PSOCKET_INFORMATION Socket, - IN HWND hWnd, - IN UINT wMsg, - IN LONG lEvent) -{ - PASYNC_DATA AsyncData = NULL; - BOOLEAN BlockMode; - NTSTATUS Status; - INT ErrorCode; - - /* Allocate the Async Data Structure to pass on to the Thread later */ - AsyncData = SockAllocateHeapRoutine(SockPrivateHeap, 0, sizeof(*AsyncData)); - if (!AsyncData) return WSAENOBUFS; - - /* Acquire socket lock */ - EnterCriticalSection(&Socket->Lock); - - /* Is there an active WSPEventSelect? */ - if (Socket->SharedData.AsyncEvents) - { - /* Call the helper to process it */ - ErrorCode = SockEventSelectHelper(Socket, NULL, 0); - if (ErrorCode != NO_ERROR) goto error; - } - - /* Set Socket to Non-Blocking */ - BlockMode = TRUE; - ErrorCode = SockSetInformation(Socket, - AFD_INFO_BLOCKING_MODE, - &BlockMode, - NULL, - NULL); - if (ErrorCode != NO_ERROR) goto error; - - /* AFD was notified, set it locally as well */ - Socket->SharedData.NonBlocking = TRUE; - - /* Store Socket Data */ - Socket->SharedData.hWnd = hWnd; - Socket->SharedData.wMsg = wMsg; - Socket->SharedData.AsyncEvents = lEvent; - Socket->SharedData.AsyncDisabledEvents = 0; - - /* Check if the socket is not connected and not a datagram socket */ - if ((!SockIsSocketConnected(Socket)) && !MSAFD_IS_DGRAM_SOCK(Socket)) - { - /* Disable FD_WRITE for now, so we don't get it before FD_CONNECT */ - Socket->SharedData.AsyncDisabledEvents |= FD_WRITE; - } - - /* Increase the sequence number */ - Socket->SharedData.SequenceNumber++; - - /* Return if there are no more Events */ - if (!(Socket->SharedData.AsyncEvents & - (~Socket->SharedData.AsyncDisabledEvents))) - { - /* Release the lock, dereference the async thread and the socket */ - LeaveCriticalSection(&Socket->Lock); - InterlockedDecrement(&SockAsyncThreadReferenceCount); - SockDereferenceSocket(Socket); - - /* Free the Async Data */ - RtlFreeHeap(SockPrivateHeap, 0, AsyncData); - return NO_ERROR; - } - - /* Set up the Async Data */ - AsyncData->ParentSocket = Socket; - AsyncData->SequenceNumber = Socket->SharedData.SequenceNumber; - - /* Release the lock now */ - LeaveCriticalSection(&Socket->Lock); - - /* Begin Async Select by using I/O Completion */ - Status = NtSetIoCompletion(SockAsyncQueuePort, - (PVOID)&SockProcessQueuedAsyncSelect, - AsyncData, - 0, - 0); - if (!NT_SUCCESS(Status)) - { - /* Dereference the async thread and fail */ - InterlockedDecrement(&SockAsyncThreadReferenceCount); - ErrorCode = NtStatusToSocketError(Status); - } - -error: - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Free the async data */ - RtlFreeHeap(SockPrivateHeap, 0, AsyncData); - - /* Fail */ - return SOCKET_ERROR; - } - - /* Increment the socket reference */ - InterlockedIncrement(&Socket->RefCount); - - /* Return success */ - return NO_ERROR; -} - -INT -WSPAPI -WSPAsyncSelect(IN SOCKET Handle, - IN HWND hWnd, - IN UINT wMsg, - IN LONG lEvent, - OUT LPINT lpErrno) -{ - PSOCKET_INFORMATION Socket; - INT ErrorCode; - PWINSOCK_TEB_DATA ThreadData; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Check for valid events */ - if (lEvent & ~FD_ALL_EVENTS) - { - /* Fail */ - ErrorCode = WSAEINVAL; - goto error; - } - - /* Check for valid window handle */ - if (!IsWindow(hWnd)) - { - /* Fail */ - ErrorCode = WSAEINVAL; - goto error; - } - - /* Create the Asynch Thread if Needed */ - if (!SockCheckAndReferenceAsyncThread()) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - - /* Open a Handle to AFD's Async Helper */ - if (!SockCheckAndInitAsyncSelectHelper()) - { - /* Dereference async thread and fail */ - InterlockedDecrement(&SockAsyncThreadReferenceCount); - ErrorCode = WSAENOBUFS; - goto error; - } - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Call the helper to do the work */ - ErrorCode = SockAsyncSelectHelper(Socket, - hWnd, - wMsg, - lEvent); - - /* Dereference the socket */ - SockDereferenceSocket(Socket); - -error: - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - -INT -WSPAPI -WSPSelect(INT nfds, - PFD_SET readfds, - PFD_SET writefds, - PFD_SET exceptfds, - CONST LPTIMEVAL timeout, - LPINT lpErrno) -{ - IO_STATUS_BLOCK IoStatusBlock; - PAFD_POLL_INFO PollInfo = NULL; - NTSTATUS Status; - CHAR PollBuffer[sizeof(AFD_POLL_INFO) + 3 * sizeof(AFD_HANDLE)]; - PAFD_HANDLE HandleArray; - ULONG HandleCount, OutCount = 0; - ULONG PollBufferSize; - ULONG i; - PWINSOCK_TEB_DATA ThreadData; - LARGE_INTEGER uSec; - ULONG BlockType; - INT ErrorCode; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* How many sockets will we check? */ - HandleCount = HANDLES_IN_SET(readfds) + - HANDLES_IN_SET(writefds) + - HANDLES_IN_SET(exceptfds); - - /* Leave if none are */ - if (!HandleCount) return NO_ERROR; - - /* How much space will they require? */ - PollBufferSize = sizeof(*PollInfo) + (HandleCount * sizeof(AFD_HANDLE)); - - /* Check if our stack is big enough to hold it */ - if (PollBufferSize <= sizeof(PollBuffer)) - { - /* Use the stack */ - PollInfo = (PVOID)PollBuffer; - } - else - { - /* Allocate from heap instead */ - PollInfo = SockAllocateHeapRoutine(SockPrivateHeap, 0, PollBufferSize); - if (!PollInfo) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - } - - /* Number of handles for AFD to Check */ - PollInfo->HandleCount = HandleCount; - PollInfo->Exclusive = FALSE; - HandleArray = PollInfo->Handles; - - /* Select the Read Events */ - for (i = 0; readfds && i < (readfds->fd_count & 0xFFFF); i++) - { - /* Fill out handle info */ - HandleArray->Handle = (SOCKET)readfds->fd_array[i]; - HandleArray->Events = AFD_EVENT_RECEIVE | - AFD_EVENT_DISCONNECT | - AFD_EVENT_ABORT; - - /* Move to the next one */ - HandleArray++; - } - for (i = 0; writefds && i < (writefds->fd_count & 0xFFFF); i++) - { - /* Fill out handle info */ - HandleArray->Handle = (SOCKET)writefds->fd_array[i]; - HandleArray->Events = AFD_EVENT_SEND; - - /* Move to the next one */ - HandleArray++; - } - for (i = 0; exceptfds && i < (exceptfds->fd_count & 0xFFFF); i++) - { - /* Fill out handle info */ - HandleArray->Handle = (SOCKET)exceptfds->fd_array[i]; - HandleArray->Events = AFD_EVENT_OOB_RECEIVE | AFD_EVENT_CONNECT_FAIL; - - /* Move to the next one */ - HandleArray++; - } - - /* Check if a timeout was given */ - if (timeout) - { - /* Inifinte Timeout */ - PollInfo->Timeout.u.LowPart = -1; - PollInfo->Timeout.u.HighPart = 0x7FFFFFFF; - } - else - { - /* Calculate microseconds */ - uSec = RtlEnlargedIntegerMultiply(timeout->tv_usec, -10); - - /* Calculate seconds */ - PollInfo->Timeout = RtlEnlargedIntegerMultiply(timeout->tv_sec, - -1 * 1000 * 1000 * 10); - - /* Add microseconds */ - PollInfo->Timeout.QuadPart += uSec.QuadPart; - } - - /* Send IOCTL */ - Status = NtDeviceIoControlFile((HANDLE)PollInfo->Handles[0].Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_SELECT, - PollInfo, - PollBufferSize, - PollInfo, - PollBufferSize); - - /* Check if we have to wait */ - if (Status == STATUS_PENDING) - { - /* Check if we'll call the blocking hook */ - if (!PollInfo->Timeout.QuadPart) BlockType = NO_BLOCKING_HOOK; - - /* Wait for completion */ - SockWaitForSingleObject(ThreadData->EventHandle, - (SOCKET)PollInfo->Handles[0].Handle, - BlockType, - NO_TIMEOUT); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check for failure */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - - /* Clear the Structures */ - if(readfds) FD_ZERO(readfds); - if(writefds) FD_ZERO(writefds); - if(exceptfds) FD_ZERO(exceptfds); - - /* Get the handle info again */ - HandleCount = PollInfo->HandleCount; - HandleArray = PollInfo->Handles; - - /* Loop the Handles that got an event */ - for (i = 0; i < HandleCount; i++) - { - /* Check for a match */ - if (HandleArray->Events & AFD_EVENT_RECEIVE) - { - /* Check if it's not already set */ - if (!FD_ISSET((SOCKET)HandleArray->Handle, readfds)) - { - /* Increase Handles with an Event */ - OutCount++; - - /* Set this handle */ - FD_SET((SOCKET)HandleArray->Handle, readfds); - } - } - /* Check for a match */ - if (HandleArray->Events & AFD_EVENT_SEND) - { - /* Check if it's not already set */ - if (!FD_ISSET((SOCKET)HandleArray->Handle, writefds)) - { - /* Increase Handles with an Event */ - OutCount++; - - /* Set this handle */ - FD_SET((SOCKET)HandleArray->Handle, writefds); - } - } - /* Check for a match */ - if (HandleArray->Events & AFD_EVENT_OOB_RECEIVE) - { - /* Check if it's not already set */ - if (!FD_ISSET((SOCKET)HandleArray->Handle, exceptfds)) - { - /* Increase Handles with an Event */ - OutCount++; - - /* Set this handle */ - FD_SET((SOCKET)HandleArray->Handle, exceptfds); - } - } - /* Check for a match */ - if (HandleArray->Events & AFD_EVENT_ACCEPT) - { - /* Check if it's not already set */ - if (!FD_ISSET((SOCKET)HandleArray->Handle, readfds)) - { - /* Increase Handles with an Event */ - OutCount++; - - /* Set this handle */ - FD_SET((SOCKET)HandleArray->Handle, readfds); - } - } - /* Check for a match */ - if (HandleArray->Events & AFD_EVENT_CONNECT) - { - /* Check if it's not already set */ - if (!FD_ISSET((SOCKET)HandleArray->Handle, writefds)) - { - /* Increase Handles with an Event */ - OutCount++; - - /* Set this handle */ - FD_SET((SOCKET)HandleArray->Handle, writefds); - } - } - /* Check for a match */ - if (HandleArray->Events & AFD_EVENT_CONNECT_FAIL) - { - /* Check if it's not already set */ - if (!FD_ISSET((SOCKET)HandleArray->Handle, exceptfds)) - { - /* Increase Handles with an Event */ - OutCount++; - - /* Set this handle */ - FD_SET((SOCKET)HandleArray->Handle, exceptfds); - } - } - /* Check for a match */ - if (HandleArray->Events & AFD_EVENT_DISCONNECT) - { - /* Check if it's not already set */ - if (!FD_ISSET((SOCKET)HandleArray->Handle, readfds)) - { - /* Increase Handles with an Event */ - OutCount++; - - /* Set this handle */ - FD_SET((SOCKET)HandleArray->Handle, readfds); - } - } - /* Check for a match */ - if (HandleArray->Events & AFD_EVENT_ABORT) - { - /* Check if it's not already set */ - if (!FD_ISSET((SOCKET)HandleArray->Handle, readfds)) - { - /* Increase Handles with an Event */ - OutCount++; - - /* Set this handle */ - FD_SET((SOCKET)HandleArray->Handle, readfds); - } - } - /* Check for a match */ - if (HandleArray->Events & AFD_EVENT_CLOSE) - { - /* Check if it's not already set */ - if (!FD_ISSET((SOCKET)HandleArray->Handle, readfds)) - { - /* Increase Handles with an Event */ - OutCount++; - - /* Set this handle */ - FD_SET((SOCKET)HandleArray->Handle, readfds); - } - } - - /* Move to next entry */ - HandleArray++; - } - -error: - - /* Check if we should free the buffer */ - if (PollInfo && (PollInfo != (PVOID)PollBuffer)) - { - /* Free it from the heap */ - RtlFreeHeap(SockPrivateHeap, 0, PollInfo); - } - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Return error */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return the number of handles */ - return OutCount; -} - diff --git a/dll/win32/mswsock/msafd/send.c b/dll/win32/mswsock/msafd/send.c index 60f377998be..b7840864227 100644 --- a/dll/win32/mswsock/msafd/send.c +++ b/dll/win32/mswsock/msafd/send.c @@ -583,1758 +583,3 @@ error: return NO_ERROR; } -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -INT -WSPAPI -WSPSend(SOCKET Handle, - LPWSABUF lpBuffers, - DWORD dwBufferCount, - LPDWORD lpNumberOfBytesSent, - DWORD iFlags, - LPWSAOVERLAPPED lpOverlapped, - LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, - LPWSATHREADID lpThreadId, - LPINT lpErrno) -{ - PIO_STATUS_BLOCK IoStatusBlock; - IO_STATUS_BLOCK DummyIoStatusBlock; - AFD_SEND_INFO SendInfo; - NTSTATUS Status; - PVOID APCContext; - PVOID ApcFunction; - HANDLE Event; - PWINSOCK_TEB_DATA ThreadData; - PSOCKET_INFORMATION Socket; - INT ErrorCode; - BOOLEAN ReturnValue; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Set up the Receive Structure */ - SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers; - SendInfo.BufferCount = dwBufferCount; - SendInfo.TdiFlags = 0; - SendInfo.AfdFlags = 0; - - /* Set the TDI Flags */ - if (iFlags) - { - /* Check for valid flags */ - if ((iFlags & ~(MSG_OOB | MSG_DONTROUTE | MSG_PARTIAL))) - { - /* Fail */ - ErrorCode = WSAEOPNOTSUPP; - goto error; - } - - /* Check if OOB is being used */ - if (iFlags & MSG_OOB) - { - /* Use Expedited Send for OOB */ - SendInfo.TdiFlags |= TDI_SEND_EXPEDITED; - } - - /* Use Partial Send if enabled */ - if (iFlags & MSG_PARTIAL) SendInfo.TdiFlags |= TDI_SEND_PARTIAL; - } - - /* Verifiy if we should use APC */ - if (!lpOverlapped) - { - /* Not using Overlapped structure, so use normal blocking on event */ - APCContext = NULL; - ApcFunction = NULL; - Event = ThreadData->EventHandle; - IoStatusBlock = &DummyIoStatusBlock; - } - else - { - /* Using apc, check if we have a completion routine */ - if (!lpCompletionRoutine) - { - /* No need for APC */ - APCContext = lpOverlapped; - ApcFunction = NULL; - Event = lpOverlapped->hEvent; - } - else - { - /* Use APC */ - ApcFunction = SockIoCompletion; - APCContext = lpCompletionRoutine; - Event = NULL; - - /* Skip Fast I/O */ - SendInfo.AfdFlags = AFD_SKIP_FIO; - } - - /* Use the overlapped's structure buffer for the I/O Status Block */ - IoStatusBlock = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; - - /* Make this an overlapped I/O in AFD */ - SendInfo.AfdFlags |= AFD_OVERLAPPED; - } - - /* Set is as Pending for now */ - IoStatusBlock->Status = STATUS_PENDING; - - /* Send IOCTL */ - Status = NtDeviceIoControlFile((HANDLE)Handle, - Event, - ApcFunction, - APCContext, - IoStatusBlock, - IOCTL_AFD_SEND, - &SendInfo, - sizeof(SendInfo), - NULL, - 0); - - /* Increase the pending APC Count if we're using an APC */ - if (!NT_ERROR(Status) && ApcFunction) - { - ThreadData->PendingAPCs++; - InterlockedIncrement(&SockProcessPendingAPCCount); - } - - /* Wait for completition if not overlapped */ - if ((Status == STATUS_PENDING) && !(lpOverlapped)) - { - /* Wait for completion */ - ReturnValue = SockWaitForSingleObject(Event, - Handle, - MAYBE_BLOCKING_HOOK, - SEND_TIMEOUT); - - /* Check if the wait was successful */ - if (ReturnValue) - { - /* Get new status */ - Status = IoStatusBlock->Status; - } - else - { - /* Cancel the I/O */ - SockCancelIo(Handle); - Status = STATUS_IO_TIMEOUT; - } - } - - /* Check status */ - switch (Status) - { - /* Success */ - case STATUS_SUCCESS: - break; - - /* Pending I/O */ - case STATUS_PENDING: - ErrorCode = WSA_IO_PENDING; - goto error; - - /* Other NT Error */ - default: - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - break; - } - - /* Return the number of bytes sent */ - *lpNumberOfBytesSent = PtrToUlong(IoStatusBlock->Information); - -error: - - /* Check if async select was active and this blocked */ - if (SockAsyncSelectCalled && (ErrorCode == WSAEWOULDBLOCK)) - { - /* Get the socket */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (Socket) - { - /* Lock it */ - EnterCriticalSection(&Socket->Lock); - - /* Re-enable the regular write event */ - SockReenableAsyncSelectEvent(Socket, FD_WRITE); - - /* Unlock and dereference socket */ - LeaveCriticalSection(&Socket->Lock); - SockDereferenceSocket(Socket); - } - } - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - -INT -WSPAPI -WSPSendTo(SOCKET Handle, - LPWSABUF lpBuffers, - DWORD dwBufferCount, - LPDWORD lpNumberOfBytesSent, - DWORD iFlags, - const struct sockaddr *SocketAddress, - INT SocketAddressLength, - LPWSAOVERLAPPED lpOverlapped, - LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, - LPWSATHREADID lpThreadId, - LPINT lpErrno) -{ - PIO_STATUS_BLOCK IoStatusBlock; - IO_STATUS_BLOCK DummyIoStatusBlock; - AFD_SEND_INFO_UDP SendInfo; - NTSTATUS Status; - PVOID APCContext; - PVOID ApcFunction; - HANDLE Event; - PWINSOCK_TEB_DATA ThreadData; - PSOCKET_INFORMATION Socket; - INT ErrorCode; - INT ReturnValue; - CHAR AddressBuffer[FIELD_OFFSET(TDI_ADDRESS_INFO, Address) + - MAX_TDI_ADDRESS_LENGTH]; - PTRANSPORT_ADDRESS TdiAddress = (PTRANSPORT_ADDRESS)AddressBuffer; - ULONG TdiAddressSize; - INT SockaddrLength; - PSOCKADDR Sockaddr; - SOCKADDR_INFO SocketInfo; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* - * Check if this isn't a datagram socket or if it's a connected socket - * without an address - */ - if (!MSAFD_IS_DGRAM_SOCK(Socket) || - ((Socket->SharedData.State == SocketConnected) && - (!SocketAddress || !SocketAddressLength))) - { - /* Call WSPSend instead */ - SockDereferenceSocket(Socket); - return WSPSend(Handle, - lpBuffers, - dwBufferCount, - lpNumberOfBytesSent, - iFlags, - lpOverlapped, - lpCompletionRoutine, - lpThreadId, - lpErrno); - } - - /* If the socket isn't connected, we need an address*/ - if ((Socket->SharedData.State != SocketConnected) && (!SocketAddress)) - { - /* Fail */ - ErrorCode = WSAENOTCONN; - goto error; - } - - /* Validate length */ - if (SocketAddressLength < Socket->HelperData->MaxWSAddressLength) - { - /* Fail */ - ErrorCode = WSAEFAULT; - goto error; - } - - /* Verify flags */ - if (iFlags & ~MSG_DONTROUTE) - { - /* Fail */ - ErrorCode = WSAEOPNOTSUPP; - goto error; - } - - /* Make sure send shutdown isn't active */ - if (Socket->SharedData.SendShutdown) - { - /* Fail */ - ErrorCode = WSAESHUTDOWN; - goto error; - } - - /* Make sure address families match */ - if (Socket->SharedData.AddressFamily != SocketAddress->sa_family) - { - /* Fail */ - ErrorCode = WSAEOPNOTSUPP; - goto error; - } - - /* Check if broadcast is enabled */ - if (!Socket->SharedData.Broadcast) - { - /* The caller might want to enable it; get the Sockaddr type */ - ErrorCode = Socket->HelperData->WSHGetSockaddrType((PSOCKADDR)SocketAddress, - SocketAddressLength, - &SocketInfo); - if (ErrorCode != NO_ERROR) goto error; - - /* Check if this is a broadcast attempt */ - if (SocketInfo.AddressInfo == SockaddrAddressInfoBroadcast) - { - /* The socket won't allow it */ - ErrorCode = WSAEACCES; - goto error; - } - } - - /* Check if this socket isn't bound yet */ - if (Socket->SharedData.State == SocketOpen) - { - /* Check if we can request the wildcard address */ - if (Socket->HelperData->WSHGetWildcardSockaddr) - { - /* Allocate a new Sockaddr */ - SockaddrLength = Socket->HelperData->MaxWSAddressLength; - Sockaddr = SockAllocateHeapRoutine(SockPrivateHeap, 0, SockaddrLength); - if (!Sockaddr) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - - /* Get the wildcard sockaddr */ - ErrorCode = Socket->HelperData->WSHGetWildcardSockaddr(Socket->HelperContext, - Sockaddr, - &SockaddrLength); - if (ErrorCode != NO_ERROR) - { - /* Free memory and fail */ - RtlFreeHeap(SockPrivateHeap, 0, Sockaddr); - goto error; - } - - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* Make sure it's still unbound */ - if (Socket->SharedData.State == SocketOpen) - { - /* Bind it */ - ReturnValue = WSPBind(Handle, - Sockaddr, - SockaddrLength, - &ErrorCode); - } - else - { - /* It's bound now, fake success */ - ReturnValue = NO_ERROR; - } - - /* Release the lock and free memory */ - LeaveCriticalSection(&Socket->Lock); - RtlFreeHeap(SockPrivateHeap, 0, Sockaddr); - - /* Check if we failed */ - if (ReturnValue == SOCKET_ERROR) goto error; - } - else - { - /* Unbound socket, but can't get the wildcard. Fail */ - ErrorCode = WSAEINVAL; - goto error; - } - } - - /* Check how long the TDI Address is */ - TdiAddressSize = Socket->HelperData->MaxTDIAddressLength; - - /* See if it can fit in the stack */ - if (TdiAddressSize > sizeof(AddressBuffer)) - { - /* Allocate from heap */ - TdiAddress = SockAllocateHeapRoutine(SockPrivateHeap, 0, TdiAddressSize); - if (!TdiAddress) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - } - - /* Build the TDI Address */ - ErrorCode = SockBuildTdiAddress(TdiAddress, - (PSOCKADDR)SocketAddress, - min(SocketAddressLength, - Socket->HelperData->MaxWSAddressLength)); - if (ErrorCode != NO_ERROR) goto error; - - /* Set up the Send Structure */ - SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers; - SendInfo.BufferCount = dwBufferCount; - SendInfo.AfdFlags = 0; - SendInfo.TdiConnection.RemoteAddress = TdiAddress; - SendInfo.TdiConnection.RemoteAddressLength = TdiAddressSize; - - /* Verifiy if we should use APC */ - if (!lpOverlapped) - { - /* Not using Overlapped structure, so use normal blocking on event */ - APCContext = NULL; - ApcFunction = NULL; - Event = ThreadData->EventHandle; - IoStatusBlock = &DummyIoStatusBlock; - } - else - { - /* Using apc, check if we have a completion routine */ - if (!lpCompletionRoutine) - { - /* No need for APC */ - APCContext = lpOverlapped; - ApcFunction = NULL; - Event = lpOverlapped->hEvent; - } - else - { - /* Use APC */ - ApcFunction = SockIoCompletion; - APCContext = lpCompletionRoutine; - Event = NULL; - - /* Skip Fast I/O */ - SendInfo.AfdFlags = AFD_SKIP_FIO; - } - - /* Use the overlapped's structure buffer for the I/O Status Block */ - IoStatusBlock = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; - - /* Make this an overlapped I/O in AFD */ - SendInfo.AfdFlags |= AFD_OVERLAPPED; - } - - /* Set is as Pending for now */ - IoStatusBlock->Status = STATUS_PENDING; - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - Event, - ApcFunction, - APCContext, - IoStatusBlock, - IOCTL_AFD_SEND_DATAGRAM, - &SendInfo, - sizeof(SendInfo), - NULL, - 0); - - /* Increase the pending APC Count if we're using an APC */ - if (!NT_ERROR(Status) && ApcFunction) - { - ThreadData->PendingAPCs++; - InterlockedIncrement(&SockProcessPendingAPCCount); - } - - /* Wait for completition if not overlapped */ - if ((Status == STATUS_PENDING) && !(lpOverlapped)) - { - /* Wait for completion */ - ReturnValue = SockWaitForSingleObject(Event, - Handle, - MAYBE_BLOCKING_HOOK, - SEND_TIMEOUT); - - /* Check if the wait was successful */ - if (ReturnValue) - { - /* Get new status */ - Status = IoStatusBlock->Status; - } - else - { - /* Cancel the I/O */ - SockCancelIo(Handle); - Status = STATUS_IO_TIMEOUT; - } - } - - /* Check status */ - switch (Status) - { - /* Success */ - case STATUS_SUCCESS: - break; - - /* Pending I/O */ - case STATUS_PENDING: - ErrorCode = WSA_IO_PENDING; - goto error; - - /* Other NT Error */ - default: - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - break; - } - - /* Return the number of bytes sent */ - *lpNumberOfBytesSent = PtrToUlong(IoStatusBlock->Information); - -error: - - /* Check if we have a socket */ - if (Socket) - { - /* Check if async select was active and this blocked */ - if (SockAsyncSelectCalled && (ErrorCode == WSAEWOULDBLOCK)) - { - /* Lock it */ - EnterCriticalSection(&Socket->Lock); - - /* Re-enable the regular write event */ - SockReenableAsyncSelectEvent(Socket, FD_WRITE); - - /* Unlock socket */ - LeaveCriticalSection(&Socket->Lock); - } - - /* Dereference socket */ - SockDereferenceSocket(Socket); - } - - /* Check if we should free the TDI Address */ - if (TdiAddress && (TdiAddress != (PVOID)AddressBuffer)) - { - /* Free it from the heap */ - RtlFreeHeap(SockPrivateHeap, 0, TdiAddress); - } - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -INT -WSPAPI -WSPSend(SOCKET Handle, - LPWSABUF lpBuffers, - DWORD dwBufferCount, - LPDWORD lpNumberOfBytesSent, - DWORD iFlags, - LPWSAOVERLAPPED lpOverlapped, - LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, - LPWSATHREADID lpThreadId, - LPINT lpErrno) -{ - PIO_STATUS_BLOCK IoStatusBlock; - IO_STATUS_BLOCK DummyIoStatusBlock; - AFD_SEND_INFO SendInfo; - NTSTATUS Status; - PVOID APCContext; - PVOID ApcFunction; - HANDLE Event; - PWINSOCK_TEB_DATA ThreadData; - PSOCKET_INFORMATION Socket; - INT ErrorCode; - BOOLEAN ReturnValue; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Set up the Receive Structure */ - SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers; - SendInfo.BufferCount = dwBufferCount; - SendInfo.TdiFlags = 0; - SendInfo.AfdFlags = 0; - - /* Set the TDI Flags */ - if (iFlags) - { - /* Check for valid flags */ - if ((iFlags & ~(MSG_OOB | MSG_DONTROUTE | MSG_PARTIAL))) - { - /* Fail */ - ErrorCode = WSAEOPNOTSUPP; - goto error; - } - - /* Check if OOB is being used */ - if (iFlags & MSG_OOB) - { - /* Use Expedited Send for OOB */ - SendInfo.TdiFlags |= TDI_SEND_EXPEDITED; - } - - /* Use Partial Send if enabled */ - if (iFlags & MSG_PARTIAL) SendInfo.TdiFlags |= TDI_SEND_PARTIAL; - } - - /* Verifiy if we should use APC */ - if (!lpOverlapped) - { - /* Not using Overlapped structure, so use normal blocking on event */ - APCContext = NULL; - ApcFunction = NULL; - Event = ThreadData->EventHandle; - IoStatusBlock = &DummyIoStatusBlock; - } - else - { - /* Using apc, check if we have a completion routine */ - if (!lpCompletionRoutine) - { - /* No need for APC */ - APCContext = lpOverlapped; - ApcFunction = NULL; - Event = lpOverlapped->hEvent; - } - else - { - /* Use APC */ - ApcFunction = SockIoCompletion; - APCContext = lpCompletionRoutine; - Event = NULL; - - /* Skip Fast I/O */ - SendInfo.AfdFlags = AFD_SKIP_FIO; - } - - /* Use the overlapped's structure buffer for the I/O Status Block */ - IoStatusBlock = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; - - /* Make this an overlapped I/O in AFD */ - SendInfo.AfdFlags |= AFD_OVERLAPPED; - } - - /* Set is as Pending for now */ - IoStatusBlock->Status = STATUS_PENDING; - - /* Send IOCTL */ - Status = NtDeviceIoControlFile((HANDLE)Handle, - Event, - ApcFunction, - APCContext, - IoStatusBlock, - IOCTL_AFD_SEND, - &SendInfo, - sizeof(SendInfo), - NULL, - 0); - - /* Increase the pending APC Count if we're using an APC */ - if (!NT_ERROR(Status) && ApcFunction) - { - ThreadData->PendingAPCs++; - InterlockedIncrement(&SockProcessPendingAPCCount); - } - - /* Wait for completition if not overlapped */ - if ((Status == STATUS_PENDING) && !(lpOverlapped)) - { - /* Wait for completion */ - ReturnValue = SockWaitForSingleObject(Event, - Handle, - MAYBE_BLOCKING_HOOK, - SEND_TIMEOUT); - - /* Check if the wait was successful */ - if (ReturnValue) - { - /* Get new status */ - Status = IoStatusBlock->Status; - } - else - { - /* Cancel the I/O */ - SockCancelIo(Handle); - Status = STATUS_IO_TIMEOUT; - } - } - - /* Check status */ - switch (Status) - { - /* Success */ - case STATUS_SUCCESS: - break; - - /* Pending I/O */ - case STATUS_PENDING: - ErrorCode = WSA_IO_PENDING; - goto error; - - /* Other NT Error */ - default: - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - break; - } - - /* Return the number of bytes sent */ - *lpNumberOfBytesSent = PtrToUlong(IoStatusBlock->Information); - -error: - - /* Check if async select was active and this blocked */ - if (SockAsyncSelectCalled && (ErrorCode == WSAEWOULDBLOCK)) - { - /* Get the socket */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (Socket) - { - /* Lock it */ - EnterCriticalSection(&Socket->Lock); - - /* Re-enable the regular write event */ - SockReenableAsyncSelectEvent(Socket, FD_WRITE); - - /* Unlock and dereference socket */ - LeaveCriticalSection(&Socket->Lock); - SockDereferenceSocket(Socket); - } - } - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - -INT -WSPAPI -WSPSendTo(SOCKET Handle, - LPWSABUF lpBuffers, - DWORD dwBufferCount, - LPDWORD lpNumberOfBytesSent, - DWORD iFlags, - const struct sockaddr *SocketAddress, - INT SocketAddressLength, - LPWSAOVERLAPPED lpOverlapped, - LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, - LPWSATHREADID lpThreadId, - LPINT lpErrno) -{ - PIO_STATUS_BLOCK IoStatusBlock; - IO_STATUS_BLOCK DummyIoStatusBlock; - AFD_SEND_INFO_UDP SendInfo; - NTSTATUS Status; - PVOID APCContext; - PVOID ApcFunction; - HANDLE Event; - PWINSOCK_TEB_DATA ThreadData; - PSOCKET_INFORMATION Socket; - INT ErrorCode; - INT ReturnValue; - CHAR AddressBuffer[FIELD_OFFSET(TDI_ADDRESS_INFO, Address) + - MAX_TDI_ADDRESS_LENGTH]; - PTRANSPORT_ADDRESS TdiAddress = (PTRANSPORT_ADDRESS)AddressBuffer; - ULONG TdiAddressSize; - INT SockaddrLength; - PSOCKADDR Sockaddr; - SOCKADDR_INFO SocketInfo; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* - * Check if this isn't a datagram socket or if it's a connected socket - * without an address - */ - if (!MSAFD_IS_DGRAM_SOCK(Socket) || - ((Socket->SharedData.State == SocketConnected) && - (!SocketAddress || !SocketAddressLength))) - { - /* Call WSPSend instead */ - SockDereferenceSocket(Socket); - return WSPSend(Handle, - lpBuffers, - dwBufferCount, - lpNumberOfBytesSent, - iFlags, - lpOverlapped, - lpCompletionRoutine, - lpThreadId, - lpErrno); - } - - /* If the socket isn't connected, we need an address*/ - if ((Socket->SharedData.State != SocketConnected) && (!SocketAddress)) - { - /* Fail */ - ErrorCode = WSAENOTCONN; - goto error; - } - - /* Validate length */ - if (SocketAddressLength < Socket->HelperData->MaxWSAddressLength) - { - /* Fail */ - ErrorCode = WSAEFAULT; - goto error; - } - - /* Verify flags */ - if (iFlags & ~MSG_DONTROUTE) - { - /* Fail */ - ErrorCode = WSAEOPNOTSUPP; - goto error; - } - - /* Make sure send shutdown isn't active */ - if (Socket->SharedData.SendShutdown) - { - /* Fail */ - ErrorCode = WSAESHUTDOWN; - goto error; - } - - /* Make sure address families match */ - if (Socket->SharedData.AddressFamily != SocketAddress->sa_family) - { - /* Fail */ - ErrorCode = WSAEOPNOTSUPP; - goto error; - } - - /* Check if broadcast is enabled */ - if (!Socket->SharedData.Broadcast) - { - /* The caller might want to enable it; get the Sockaddr type */ - ErrorCode = Socket->HelperData->WSHGetSockaddrType((PSOCKADDR)SocketAddress, - SocketAddressLength, - &SocketInfo); - if (ErrorCode != NO_ERROR) goto error; - - /* Check if this is a broadcast attempt */ - if (SocketInfo.AddressInfo == SockaddrAddressInfoBroadcast) - { - /* The socket won't allow it */ - ErrorCode = WSAEACCES; - goto error; - } - } - - /* Check if this socket isn't bound yet */ - if (Socket->SharedData.State == SocketOpen) - { - /* Check if we can request the wildcard address */ - if (Socket->HelperData->WSHGetWildcardSockaddr) - { - /* Allocate a new Sockaddr */ - SockaddrLength = Socket->HelperData->MaxWSAddressLength; - Sockaddr = SockAllocateHeapRoutine(SockPrivateHeap, 0, SockaddrLength); - if (!Sockaddr) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - - /* Get the wildcard sockaddr */ - ErrorCode = Socket->HelperData->WSHGetWildcardSockaddr(Socket->HelperContext, - Sockaddr, - &SockaddrLength); - if (ErrorCode != NO_ERROR) - { - /* Free memory and fail */ - RtlFreeHeap(SockPrivateHeap, 0, Sockaddr); - goto error; - } - - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* Make sure it's still unbound */ - if (Socket->SharedData.State == SocketOpen) - { - /* Bind it */ - ReturnValue = WSPBind(Handle, - Sockaddr, - SockaddrLength, - &ErrorCode); - } - else - { - /* It's bound now, fake success */ - ReturnValue = NO_ERROR; - } - - /* Release the lock and free memory */ - LeaveCriticalSection(&Socket->Lock); - RtlFreeHeap(SockPrivateHeap, 0, Sockaddr); - - /* Check if we failed */ - if (ReturnValue == SOCKET_ERROR) goto error; - } - else - { - /* Unbound socket, but can't get the wildcard. Fail */ - ErrorCode = WSAEINVAL; - goto error; - } - } - - /* Check how long the TDI Address is */ - TdiAddressSize = Socket->HelperData->MaxTDIAddressLength; - - /* See if it can fit in the stack */ - if (TdiAddressSize > sizeof(AddressBuffer)) - { - /* Allocate from heap */ - TdiAddress = SockAllocateHeapRoutine(SockPrivateHeap, 0, TdiAddressSize); - if (!TdiAddress) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - } - - /* Build the TDI Address */ - ErrorCode = SockBuildTdiAddress(TdiAddress, - (PSOCKADDR)SocketAddress, - min(SocketAddressLength, - Socket->HelperData->MaxWSAddressLength)); - if (ErrorCode != NO_ERROR) goto error; - - /* Set up the Send Structure */ - SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers; - SendInfo.BufferCount = dwBufferCount; - SendInfo.AfdFlags = 0; - SendInfo.TdiConnection.RemoteAddress = TdiAddress; - SendInfo.TdiConnection.RemoteAddressLength = TdiAddressSize; - - /* Verifiy if we should use APC */ - if (!lpOverlapped) - { - /* Not using Overlapped structure, so use normal blocking on event */ - APCContext = NULL; - ApcFunction = NULL; - Event = ThreadData->EventHandle; - IoStatusBlock = &DummyIoStatusBlock; - } - else - { - /* Using apc, check if we have a completion routine */ - if (!lpCompletionRoutine) - { - /* No need for APC */ - APCContext = lpOverlapped; - ApcFunction = NULL; - Event = lpOverlapped->hEvent; - } - else - { - /* Use APC */ - ApcFunction = SockIoCompletion; - APCContext = lpCompletionRoutine; - Event = NULL; - - /* Skip Fast I/O */ - SendInfo.AfdFlags = AFD_SKIP_FIO; - } - - /* Use the overlapped's structure buffer for the I/O Status Block */ - IoStatusBlock = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; - - /* Make this an overlapped I/O in AFD */ - SendInfo.AfdFlags |= AFD_OVERLAPPED; - } - - /* Set is as Pending for now */ - IoStatusBlock->Status = STATUS_PENDING; - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - Event, - ApcFunction, - APCContext, - IoStatusBlock, - IOCTL_AFD_SEND_DATAGRAM, - &SendInfo, - sizeof(SendInfo), - NULL, - 0); - - /* Increase the pending APC Count if we're using an APC */ - if (!NT_ERROR(Status) && ApcFunction) - { - ThreadData->PendingAPCs++; - InterlockedIncrement(&SockProcessPendingAPCCount); - } - - /* Wait for completition if not overlapped */ - if ((Status == STATUS_PENDING) && !(lpOverlapped)) - { - /* Wait for completion */ - ReturnValue = SockWaitForSingleObject(Event, - Handle, - MAYBE_BLOCKING_HOOK, - SEND_TIMEOUT); - - /* Check if the wait was successful */ - if (ReturnValue) - { - /* Get new status */ - Status = IoStatusBlock->Status; - } - else - { - /* Cancel the I/O */ - SockCancelIo(Handle); - Status = STATUS_IO_TIMEOUT; - } - } - - /* Check status */ - switch (Status) - { - /* Success */ - case STATUS_SUCCESS: - break; - - /* Pending I/O */ - case STATUS_PENDING: - ErrorCode = WSA_IO_PENDING; - goto error; - - /* Other NT Error */ - default: - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - break; - } - - /* Return the number of bytes sent */ - *lpNumberOfBytesSent = PtrToUlong(IoStatusBlock->Information); - -error: - - /* Check if we have a socket */ - if (Socket) - { - /* Check if async select was active and this blocked */ - if (SockAsyncSelectCalled && (ErrorCode == WSAEWOULDBLOCK)) - { - /* Lock it */ - EnterCriticalSection(&Socket->Lock); - - /* Re-enable the regular write event */ - SockReenableAsyncSelectEvent(Socket, FD_WRITE); - - /* Unlock socket */ - LeaveCriticalSection(&Socket->Lock); - } - - /* Dereference socket */ - SockDereferenceSocket(Socket); - } - - /* Check if we should free the TDI Address */ - if (TdiAddress && (TdiAddress != (PVOID)AddressBuffer)) - { - /* Free it from the heap */ - RtlFreeHeap(SockPrivateHeap, 0, TdiAddress); - } - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -INT -WSPAPI -WSPSend(SOCKET Handle, - LPWSABUF lpBuffers, - DWORD dwBufferCount, - LPDWORD lpNumberOfBytesSent, - DWORD iFlags, - LPWSAOVERLAPPED lpOverlapped, - LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, - LPWSATHREADID lpThreadId, - LPINT lpErrno) -{ - PIO_STATUS_BLOCK IoStatusBlock; - IO_STATUS_BLOCK DummyIoStatusBlock; - AFD_SEND_INFO SendInfo; - NTSTATUS Status; - PVOID APCContext; - PVOID ApcFunction; - HANDLE Event; - PWINSOCK_TEB_DATA ThreadData; - PSOCKET_INFORMATION Socket; - INT ErrorCode; - BOOLEAN ReturnValue; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Set up the Receive Structure */ - SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers; - SendInfo.BufferCount = dwBufferCount; - SendInfo.TdiFlags = 0; - SendInfo.AfdFlags = 0; - - /* Set the TDI Flags */ - if (iFlags) - { - /* Check for valid flags */ - if ((iFlags & ~(MSG_OOB | MSG_DONTROUTE | MSG_PARTIAL))) - { - /* Fail */ - ErrorCode = WSAEOPNOTSUPP; - goto error; - } - - /* Check if OOB is being used */ - if (iFlags & MSG_OOB) - { - /* Use Expedited Send for OOB */ - SendInfo.TdiFlags |= TDI_SEND_EXPEDITED; - } - - /* Use Partial Send if enabled */ - if (iFlags & MSG_PARTIAL) SendInfo.TdiFlags |= TDI_SEND_PARTIAL; - } - - /* Verifiy if we should use APC */ - if (!lpOverlapped) - { - /* Not using Overlapped structure, so use normal blocking on event */ - APCContext = NULL; - ApcFunction = NULL; - Event = ThreadData->EventHandle; - IoStatusBlock = &DummyIoStatusBlock; - } - else - { - /* Using apc, check if we have a completion routine */ - if (!lpCompletionRoutine) - { - /* No need for APC */ - APCContext = lpOverlapped; - ApcFunction = NULL; - Event = lpOverlapped->hEvent; - } - else - { - /* Use APC */ - ApcFunction = SockIoCompletion; - APCContext = lpCompletionRoutine; - Event = NULL; - - /* Skip Fast I/O */ - SendInfo.AfdFlags = AFD_SKIP_FIO; - } - - /* Use the overlapped's structure buffer for the I/O Status Block */ - IoStatusBlock = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; - - /* Make this an overlapped I/O in AFD */ - SendInfo.AfdFlags |= AFD_OVERLAPPED; - } - - /* Set is as Pending for now */ - IoStatusBlock->Status = STATUS_PENDING; - - /* Send IOCTL */ - Status = NtDeviceIoControlFile((HANDLE)Handle, - Event, - ApcFunction, - APCContext, - IoStatusBlock, - IOCTL_AFD_SEND, - &SendInfo, - sizeof(SendInfo), - NULL, - 0); - - /* Increase the pending APC Count if we're using an APC */ - if (!NT_ERROR(Status) && ApcFunction) - { - ThreadData->PendingAPCs++; - InterlockedIncrement(&SockProcessPendingAPCCount); - } - - /* Wait for completition if not overlapped */ - if ((Status == STATUS_PENDING) && !(lpOverlapped)) - { - /* Wait for completion */ - ReturnValue = SockWaitForSingleObject(Event, - Handle, - MAYBE_BLOCKING_HOOK, - SEND_TIMEOUT); - - /* Check if the wait was successful */ - if (ReturnValue) - { - /* Get new status */ - Status = IoStatusBlock->Status; - } - else - { - /* Cancel the I/O */ - SockCancelIo(Handle); - Status = STATUS_IO_TIMEOUT; - } - } - - /* Check status */ - switch (Status) - { - /* Success */ - case STATUS_SUCCESS: - break; - - /* Pending I/O */ - case STATUS_PENDING: - ErrorCode = WSA_IO_PENDING; - goto error; - - /* Other NT Error */ - default: - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - break; - } - - /* Return the number of bytes sent */ - *lpNumberOfBytesSent = PtrToUlong(IoStatusBlock->Information); - -error: - - /* Check if async select was active and this blocked */ - if (SockAsyncSelectCalled && (ErrorCode == WSAEWOULDBLOCK)) - { - /* Get the socket */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (Socket) - { - /* Lock it */ - EnterCriticalSection(&Socket->Lock); - - /* Re-enable the regular write event */ - SockReenableAsyncSelectEvent(Socket, FD_WRITE); - - /* Unlock and dereference socket */ - LeaveCriticalSection(&Socket->Lock); - SockDereferenceSocket(Socket); - } - } - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - -INT -WSPAPI -WSPSendTo(SOCKET Handle, - LPWSABUF lpBuffers, - DWORD dwBufferCount, - LPDWORD lpNumberOfBytesSent, - DWORD iFlags, - const struct sockaddr *SocketAddress, - INT SocketAddressLength, - LPWSAOVERLAPPED lpOverlapped, - LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, - LPWSATHREADID lpThreadId, - LPINT lpErrno) -{ - PIO_STATUS_BLOCK IoStatusBlock; - IO_STATUS_BLOCK DummyIoStatusBlock; - AFD_SEND_INFO_UDP SendInfo; - NTSTATUS Status; - PVOID APCContext; - PVOID ApcFunction; - HANDLE Event; - PWINSOCK_TEB_DATA ThreadData; - PSOCKET_INFORMATION Socket; - INT ErrorCode; - INT ReturnValue; - CHAR AddressBuffer[FIELD_OFFSET(TDI_ADDRESS_INFO, Address) + - MAX_TDI_ADDRESS_LENGTH]; - PTRANSPORT_ADDRESS TdiAddress = (PTRANSPORT_ADDRESS)AddressBuffer; - ULONG TdiAddressSize; - INT SockaddrLength; - PSOCKADDR Sockaddr; - SOCKADDR_INFO SocketInfo; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* - * Check if this isn't a datagram socket or if it's a connected socket - * without an address - */ - if (!MSAFD_IS_DGRAM_SOCK(Socket) || - ((Socket->SharedData.State == SocketConnected) && - (!SocketAddress || !SocketAddressLength))) - { - /* Call WSPSend instead */ - SockDereferenceSocket(Socket); - return WSPSend(Handle, - lpBuffers, - dwBufferCount, - lpNumberOfBytesSent, - iFlags, - lpOverlapped, - lpCompletionRoutine, - lpThreadId, - lpErrno); - } - - /* If the socket isn't connected, we need an address*/ - if ((Socket->SharedData.State != SocketConnected) && (!SocketAddress)) - { - /* Fail */ - ErrorCode = WSAENOTCONN; - goto error; - } - - /* Validate length */ - if (SocketAddressLength < Socket->HelperData->MaxWSAddressLength) - { - /* Fail */ - ErrorCode = WSAEFAULT; - goto error; - } - - /* Verify flags */ - if (iFlags & ~MSG_DONTROUTE) - { - /* Fail */ - ErrorCode = WSAEOPNOTSUPP; - goto error; - } - - /* Make sure send shutdown isn't active */ - if (Socket->SharedData.SendShutdown) - { - /* Fail */ - ErrorCode = WSAESHUTDOWN; - goto error; - } - - /* Make sure address families match */ - if (Socket->SharedData.AddressFamily != SocketAddress->sa_family) - { - /* Fail */ - ErrorCode = WSAEOPNOTSUPP; - goto error; - } - - /* Check if broadcast is enabled */ - if (!Socket->SharedData.Broadcast) - { - /* The caller might want to enable it; get the Sockaddr type */ - ErrorCode = Socket->HelperData->WSHGetSockaddrType((PSOCKADDR)SocketAddress, - SocketAddressLength, - &SocketInfo); - if (ErrorCode != NO_ERROR) goto error; - - /* Check if this is a broadcast attempt */ - if (SocketInfo.AddressInfo == SockaddrAddressInfoBroadcast) - { - /* The socket won't allow it */ - ErrorCode = WSAEACCES; - goto error; - } - } - - /* Check if this socket isn't bound yet */ - if (Socket->SharedData.State == SocketOpen) - { - /* Check if we can request the wildcard address */ - if (Socket->HelperData->WSHGetWildcardSockaddr) - { - /* Allocate a new Sockaddr */ - SockaddrLength = Socket->HelperData->MaxWSAddressLength; - Sockaddr = SockAllocateHeapRoutine(SockPrivateHeap, 0, SockaddrLength); - if (!Sockaddr) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - - /* Get the wildcard sockaddr */ - ErrorCode = Socket->HelperData->WSHGetWildcardSockaddr(Socket->HelperContext, - Sockaddr, - &SockaddrLength); - if (ErrorCode != NO_ERROR) - { - /* Free memory and fail */ - RtlFreeHeap(SockPrivateHeap, 0, Sockaddr); - goto error; - } - - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* Make sure it's still unbound */ - if (Socket->SharedData.State == SocketOpen) - { - /* Bind it */ - ReturnValue = WSPBind(Handle, - Sockaddr, - SockaddrLength, - &ErrorCode); - } - else - { - /* It's bound now, fake success */ - ReturnValue = NO_ERROR; - } - - /* Release the lock and free memory */ - LeaveCriticalSection(&Socket->Lock); - RtlFreeHeap(SockPrivateHeap, 0, Sockaddr); - - /* Check if we failed */ - if (ReturnValue == SOCKET_ERROR) goto error; - } - else - { - /* Unbound socket, but can't get the wildcard. Fail */ - ErrorCode = WSAEINVAL; - goto error; - } - } - - /* Check how long the TDI Address is */ - TdiAddressSize = Socket->HelperData->MaxTDIAddressLength; - - /* See if it can fit in the stack */ - if (TdiAddressSize > sizeof(AddressBuffer)) - { - /* Allocate from heap */ - TdiAddress = SockAllocateHeapRoutine(SockPrivateHeap, 0, TdiAddressSize); - if (!TdiAddress) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - } - - /* Build the TDI Address */ - ErrorCode = SockBuildTdiAddress(TdiAddress, - (PSOCKADDR)SocketAddress, - min(SocketAddressLength, - Socket->HelperData->MaxWSAddressLength)); - if (ErrorCode != NO_ERROR) goto error; - - /* Set up the Send Structure */ - SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers; - SendInfo.BufferCount = dwBufferCount; - SendInfo.AfdFlags = 0; - SendInfo.TdiConnection.RemoteAddress = TdiAddress; - SendInfo.TdiConnection.RemoteAddressLength = TdiAddressSize; - - /* Verifiy if we should use APC */ - if (!lpOverlapped) - { - /* Not using Overlapped structure, so use normal blocking on event */ - APCContext = NULL; - ApcFunction = NULL; - Event = ThreadData->EventHandle; - IoStatusBlock = &DummyIoStatusBlock; - } - else - { - /* Using apc, check if we have a completion routine */ - if (!lpCompletionRoutine) - { - /* No need for APC */ - APCContext = lpOverlapped; - ApcFunction = NULL; - Event = lpOverlapped->hEvent; - } - else - { - /* Use APC */ - ApcFunction = SockIoCompletion; - APCContext = lpCompletionRoutine; - Event = NULL; - - /* Skip Fast I/O */ - SendInfo.AfdFlags = AFD_SKIP_FIO; - } - - /* Use the overlapped's structure buffer for the I/O Status Block */ - IoStatusBlock = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; - - /* Make this an overlapped I/O in AFD */ - SendInfo.AfdFlags |= AFD_OVERLAPPED; - } - - /* Set is as Pending for now */ - IoStatusBlock->Status = STATUS_PENDING; - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - Event, - ApcFunction, - APCContext, - IoStatusBlock, - IOCTL_AFD_SEND_DATAGRAM, - &SendInfo, - sizeof(SendInfo), - NULL, - 0); - - /* Increase the pending APC Count if we're using an APC */ - if (!NT_ERROR(Status) && ApcFunction) - { - ThreadData->PendingAPCs++; - InterlockedIncrement(&SockProcessPendingAPCCount); - } - - /* Wait for completition if not overlapped */ - if ((Status == STATUS_PENDING) && !(lpOverlapped)) - { - /* Wait for completion */ - ReturnValue = SockWaitForSingleObject(Event, - Handle, - MAYBE_BLOCKING_HOOK, - SEND_TIMEOUT); - - /* Check if the wait was successful */ - if (ReturnValue) - { - /* Get new status */ - Status = IoStatusBlock->Status; - } - else - { - /* Cancel the I/O */ - SockCancelIo(Handle); - Status = STATUS_IO_TIMEOUT; - } - } - - /* Check status */ - switch (Status) - { - /* Success */ - case STATUS_SUCCESS: - break; - - /* Pending I/O */ - case STATUS_PENDING: - ErrorCode = WSA_IO_PENDING; - goto error; - - /* Other NT Error */ - default: - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - break; - } - - /* Return the number of bytes sent */ - *lpNumberOfBytesSent = PtrToUlong(IoStatusBlock->Information); - -error: - - /* Check if we have a socket */ - if (Socket) - { - /* Check if async select was active and this blocked */ - if (SockAsyncSelectCalled && (ErrorCode == WSAEWOULDBLOCK)) - { - /* Lock it */ - EnterCriticalSection(&Socket->Lock); - - /* Re-enable the regular write event */ - SockReenableAsyncSelectEvent(Socket, FD_WRITE); - - /* Unlock socket */ - LeaveCriticalSection(&Socket->Lock); - } - - /* Dereference socket */ - SockDereferenceSocket(Socket); - } - - /* Check if we should free the TDI Address */ - if (TdiAddress && (TdiAddress != (PVOID)AddressBuffer)) - { - /* Free it from the heap */ - RtlFreeHeap(SockPrivateHeap, 0, TdiAddress); - } - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - diff --git a/dll/win32/mswsock/msafd/shutdown.c b/dll/win32/mswsock/msafd/shutdown.c index 3d24ea4e66d..9ed93deb1be 100644 --- a/dll/win32/mswsock/msafd/shutdown.c +++ b/dll/win32/mswsock/msafd/shutdown.c @@ -172,525 +172,3 @@ error: return NO_ERROR; } -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -INT -WSPAPI -WSPRecvDisconnect(IN SOCKET s, - OUT LPWSABUF lpInboundDisconnectData, - OUT LPINT lpErrno) -{ - return 0; -} - -INT -WSPAPI -WSPSendDisconnect(IN SOCKET s, - IN LPWSABUF lpOutboundDisconnectData, - OUT LPINT lpErrno) -{ - return 0; -} - -INT -WSPAPI -WSPShutdown(SOCKET Handle, - INT HowTo, - LPINT lpErrno) - -{ - IO_STATUS_BLOCK IoStatusBlock; - AFD_DISCONNECT_INFO DisconnectInfo; - PSOCKET_INFORMATION Socket; - PWINSOCK_TEB_DATA ThreadData; - DWORD HelperEvent; - INT ErrorCode; - NTSTATUS Status; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* If the socket is not connection-less, fail if it's not connected */ - if ((MSAFD_IS_DGRAM_SOCK(Socket)) && !(SockIsSocketConnected(Socket))) - { - /* Fail */ - ErrorCode = WSAENOTCONN; - goto error; - } - - /* Set AFD Disconnect Type and WSH Notification Type */ - switch (HowTo) - { - case SD_RECEIVE: - /* Set receive disconnect */ - DisconnectInfo.DisconnectType = AFD_DISCONNECT_RECV; - HelperEvent = WSH_NOTIFY_SHUTDOWN_RECEIVE; - - /* Save it for ourselves */ - Socket->SharedData.ReceiveShutdown = TRUE; - break; - - case SD_SEND: - /* Set receive disconnect */ - DisconnectInfo.DisconnectType = AFD_DISCONNECT_SEND; - HelperEvent = WSH_NOTIFY_SHUTDOWN_SEND; - - /* Save it for ourselves */ - Socket->SharedData.SendShutdown = TRUE; - break; - - case SD_BOTH: - /* Set both */ - DisconnectInfo.DisconnectType = AFD_DISCONNECT_RECV | AFD_DISCONNECT_SEND; - HelperEvent = WSH_NOTIFY_SHUTDOWN_ALL; - - /* Save it for ourselves */ - Socket->SharedData.ReceiveShutdown = Socket->SharedData.SendShutdown = TRUE; - break; - - default: - /* Fail, invalid type */ - ErrorCode = WSAEINVAL; - goto error; - } - - /* Inifite Timeout */ - DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(-1); - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_DISCONNECT, - &DisconnectInfo, - sizeof(DisconnectInfo), - NULL, - 0); - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion outside the lock */ - LeaveCriticalSection(&Socket->Lock); - SockWaitForSingleObject(ThreadData->EventHandle, - Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - EnterCriticalSection(&Socket->Lock); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - - /* Notify helper DLL */ - ErrorCode = SockNotifyHelperDll(Socket, HelperEvent); - if (ErrorCode != NO_ERROR) goto error; - -error: - /* Check if we have a socket here */ - if (Socket) - { - /* Release the lock and dereference */ - LeaveCriticalSection(&Socket->Lock); - SockDereferenceSocket(Socket); - } - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -INT -WSPAPI -WSPRecvDisconnect(IN SOCKET s, - OUT LPWSABUF lpInboundDisconnectData, - OUT LPINT lpErrno) -{ - return 0; -} - -INT -WSPAPI -WSPSendDisconnect(IN SOCKET s, - IN LPWSABUF lpOutboundDisconnectData, - OUT LPINT lpErrno) -{ - return 0; -} - -INT -WSPAPI -WSPShutdown(SOCKET Handle, - INT HowTo, - LPINT lpErrno) - -{ - IO_STATUS_BLOCK IoStatusBlock; - AFD_DISCONNECT_INFO DisconnectInfo; - PSOCKET_INFORMATION Socket; - PWINSOCK_TEB_DATA ThreadData; - DWORD HelperEvent; - INT ErrorCode; - NTSTATUS Status; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* If the socket is not connection-less, fail if it's not connected */ - if ((MSAFD_IS_DGRAM_SOCK(Socket)) && !(SockIsSocketConnected(Socket))) - { - /* Fail */ - ErrorCode = WSAENOTCONN; - goto error; - } - - /* Set AFD Disconnect Type and WSH Notification Type */ - switch (HowTo) - { - case SD_RECEIVE: - /* Set receive disconnect */ - DisconnectInfo.DisconnectType = AFD_DISCONNECT_RECV; - HelperEvent = WSH_NOTIFY_SHUTDOWN_RECEIVE; - - /* Save it for ourselves */ - Socket->SharedData.ReceiveShutdown = TRUE; - break; - - case SD_SEND: - /* Set receive disconnect */ - DisconnectInfo.DisconnectType = AFD_DISCONNECT_SEND; - HelperEvent = WSH_NOTIFY_SHUTDOWN_SEND; - - /* Save it for ourselves */ - Socket->SharedData.SendShutdown = TRUE; - break; - - case SD_BOTH: - /* Set both */ - DisconnectInfo.DisconnectType = AFD_DISCONNECT_RECV | AFD_DISCONNECT_SEND; - HelperEvent = WSH_NOTIFY_SHUTDOWN_ALL; - - /* Save it for ourselves */ - Socket->SharedData.ReceiveShutdown = Socket->SharedData.SendShutdown = TRUE; - break; - - default: - /* Fail, invalid type */ - ErrorCode = WSAEINVAL; - goto error; - } - - /* Inifite Timeout */ - DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(-1); - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_DISCONNECT, - &DisconnectInfo, - sizeof(DisconnectInfo), - NULL, - 0); - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion outside the lock */ - LeaveCriticalSection(&Socket->Lock); - SockWaitForSingleObject(ThreadData->EventHandle, - Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - EnterCriticalSection(&Socket->Lock); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - - /* Notify helper DLL */ - ErrorCode = SockNotifyHelperDll(Socket, HelperEvent); - if (ErrorCode != NO_ERROR) goto error; - -error: - /* Check if we have a socket here */ - if (Socket) - { - /* Release the lock and dereference */ - LeaveCriticalSection(&Socket->Lock); - SockDereferenceSocket(Socket); - } - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -INT -WSPAPI -WSPRecvDisconnect(IN SOCKET s, - OUT LPWSABUF lpInboundDisconnectData, - OUT LPINT lpErrno) -{ - return 0; -} - -INT -WSPAPI -WSPSendDisconnect(IN SOCKET s, - IN LPWSABUF lpOutboundDisconnectData, - OUT LPINT lpErrno) -{ - return 0; -} - -INT -WSPAPI -WSPShutdown(SOCKET Handle, - INT HowTo, - LPINT lpErrno) - -{ - IO_STATUS_BLOCK IoStatusBlock; - AFD_DISCONNECT_INFO DisconnectInfo; - PSOCKET_INFORMATION Socket; - PWINSOCK_TEB_DATA ThreadData; - DWORD HelperEvent; - INT ErrorCode; - NTSTATUS Status; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* If the socket is not connection-less, fail if it's not connected */ - if ((MSAFD_IS_DGRAM_SOCK(Socket)) && !(SockIsSocketConnected(Socket))) - { - /* Fail */ - ErrorCode = WSAENOTCONN; - goto error; - } - - /* Set AFD Disconnect Type and WSH Notification Type */ - switch (HowTo) - { - case SD_RECEIVE: - /* Set receive disconnect */ - DisconnectInfo.DisconnectType = AFD_DISCONNECT_RECV; - HelperEvent = WSH_NOTIFY_SHUTDOWN_RECEIVE; - - /* Save it for ourselves */ - Socket->SharedData.ReceiveShutdown = TRUE; - break; - - case SD_SEND: - /* Set receive disconnect */ - DisconnectInfo.DisconnectType = AFD_DISCONNECT_SEND; - HelperEvent = WSH_NOTIFY_SHUTDOWN_SEND; - - /* Save it for ourselves */ - Socket->SharedData.SendShutdown = TRUE; - break; - - case SD_BOTH: - /* Set both */ - DisconnectInfo.DisconnectType = AFD_DISCONNECT_RECV | AFD_DISCONNECT_SEND; - HelperEvent = WSH_NOTIFY_SHUTDOWN_ALL; - - /* Save it for ourselves */ - Socket->SharedData.ReceiveShutdown = Socket->SharedData.SendShutdown = TRUE; - break; - - default: - /* Fail, invalid type */ - ErrorCode = WSAEINVAL; - goto error; - } - - /* Inifite Timeout */ - DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(-1); - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_DISCONNECT, - &DisconnectInfo, - sizeof(DisconnectInfo), - NULL, - 0); - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion outside the lock */ - LeaveCriticalSection(&Socket->Lock); - SockWaitForSingleObject(ThreadData->EventHandle, - Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - EnterCriticalSection(&Socket->Lock); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - - /* Notify helper DLL */ - ErrorCode = SockNotifyHelperDll(Socket, HelperEvent); - if (ErrorCode != NO_ERROR) goto error; - -error: - /* Check if we have a socket here */ - if (Socket) - { - /* Release the lock and dereference */ - LeaveCriticalSection(&Socket->Lock); - SockDereferenceSocket(Socket); - } - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - diff --git a/dll/win32/mswsock/msafd/sockerr.c b/dll/win32/mswsock/msafd/sockerr.c index 83430cc0062..953dfc44bbf 100644 --- a/dll/win32/mswsock/msafd/sockerr.c +++ b/dll/win32/mswsock/msafd/sockerr.c @@ -136,417 +136,3 @@ NtStatusToSocketError(IN NTSTATUS Status) } } -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -INT -WSPAPI -NtStatusToSocketError(IN NTSTATUS Status) -{ - switch (Status) - { - case STATUS_PENDING: - return ERROR_IO_PENDING; - - case STATUS_INVALID_HANDLE: - case STATUS_OBJECT_TYPE_MISMATCH: - return WSAENOTSOCK; - - case STATUS_INSUFFICIENT_RESOURCES: - case STATUS_PAGEFILE_QUOTA: - case STATUS_COMMITMENT_LIMIT: - case STATUS_WORKING_SET_QUOTA: - case STATUS_NO_MEMORY: - case STATUS_CONFLICTING_ADDRESSES: - case STATUS_QUOTA_EXCEEDED: - case STATUS_TOO_MANY_PAGING_FILES: - case STATUS_REMOTE_RESOURCES: - case STATUS_TOO_MANY_ADDRESSES: - return WSAENOBUFS; - - case STATUS_SHARING_VIOLATION: - case STATUS_ADDRESS_ALREADY_EXISTS: - return WSAEADDRINUSE; - - case STATUS_LINK_TIMEOUT: - case STATUS_IO_TIMEOUT: - case STATUS_TIMEOUT: - return WSAETIMEDOUT; - - case STATUS_GRACEFUL_DISCONNECT: - return WSAEDISCON; - - case STATUS_REMOTE_DISCONNECT: - case STATUS_CONNECTION_RESET: - case STATUS_LINK_FAILED: - case STATUS_CONNECTION_DISCONNECTED: - case STATUS_PORT_UNREACHABLE: - return WSAECONNRESET; - - case STATUS_LOCAL_DISCONNECT: - case STATUS_TRANSACTION_ABORTED: - case STATUS_CONNECTION_ABORTED: - return WSAECONNABORTED; - - case STATUS_BAD_NETWORK_PATH: - case STATUS_NETWORK_UNREACHABLE: - case STATUS_PROTOCOL_UNREACHABLE: - return WSAENETUNREACH; - - case STATUS_HOST_UNREACHABLE: - return WSAEHOSTUNREACH; - - case STATUS_CANCELLED: - case STATUS_REQUEST_ABORTED: - return WSAEINTR; - - case STATUS_BUFFER_OVERFLOW: - case STATUS_INVALID_BUFFER_SIZE: - return WSAEMSGSIZE; - - case STATUS_BUFFER_TOO_SMALL: - case STATUS_ACCESS_VIOLATION: - return WSAEFAULT; - - case STATUS_DEVICE_NOT_READY: - case STATUS_REQUEST_NOT_ACCEPTED: - return WSAEWOULDBLOCK; - - case STATUS_INVALID_NETWORK_RESPONSE: - case STATUS_NETWORK_BUSY: - case STATUS_NO_SUCH_DEVICE: - case STATUS_NO_SUCH_FILE: - case STATUS_OBJECT_PATH_NOT_FOUND: - case STATUS_OBJECT_NAME_NOT_FOUND: - case STATUS_UNEXPECTED_NETWORK_ERROR: - return WSAENETDOWN; - - case STATUS_INVALID_CONNECTION: - return WSAENOTCONN; - - case STATUS_REMOTE_NOT_LISTENING: - case STATUS_CONNECTION_REFUSED: - return WSAECONNREFUSED; - - case STATUS_PIPE_DISCONNECTED: - return WSAESHUTDOWN; - - case STATUS_INVALID_ADDRESS: - case STATUS_INVALID_ADDRESS_COMPONENT: - return WSAEADDRNOTAVAIL; - - case STATUS_NOT_SUPPORTED: - case STATUS_NOT_IMPLEMENTED: - return WSAEOPNOTSUPP; - - case STATUS_ACCESS_DENIED: - return WSAEACCES; - - default: - - if ( NT_SUCCESS(Status) ) { - - return NO_ERROR; - } - - - case STATUS_UNSUCCESSFUL: - case STATUS_INVALID_PARAMETER: - case STATUS_ADDRESS_CLOSED: - case STATUS_CONNECTION_INVALID: - case STATUS_ADDRESS_ALREADY_ASSOCIATED: - case STATUS_ADDRESS_NOT_ASSOCIATED: - case STATUS_CONNECTION_ACTIVE: - case STATUS_INVALID_DEVICE_STATE: - case STATUS_INVALID_DEVICE_REQUEST: - return WSAEINVAL; - } -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -INT -WSPAPI -NtStatusToSocketError(IN NTSTATUS Status) -{ - switch (Status) - { - case STATUS_PENDING: - return ERROR_IO_PENDING; - - case STATUS_INVALID_HANDLE: - case STATUS_OBJECT_TYPE_MISMATCH: - return WSAENOTSOCK; - - case STATUS_INSUFFICIENT_RESOURCES: - case STATUS_PAGEFILE_QUOTA: - case STATUS_COMMITMENT_LIMIT: - case STATUS_WORKING_SET_QUOTA: - case STATUS_NO_MEMORY: - case STATUS_CONFLICTING_ADDRESSES: - case STATUS_QUOTA_EXCEEDED: - case STATUS_TOO_MANY_PAGING_FILES: - case STATUS_REMOTE_RESOURCES: - case STATUS_TOO_MANY_ADDRESSES: - return WSAENOBUFS; - - case STATUS_SHARING_VIOLATION: - case STATUS_ADDRESS_ALREADY_EXISTS: - return WSAEADDRINUSE; - - case STATUS_LINK_TIMEOUT: - case STATUS_IO_TIMEOUT: - case STATUS_TIMEOUT: - return WSAETIMEDOUT; - - case STATUS_GRACEFUL_DISCONNECT: - return WSAEDISCON; - - case STATUS_REMOTE_DISCONNECT: - case STATUS_CONNECTION_RESET: - case STATUS_LINK_FAILED: - case STATUS_CONNECTION_DISCONNECTED: - case STATUS_PORT_UNREACHABLE: - return WSAECONNRESET; - - case STATUS_LOCAL_DISCONNECT: - case STATUS_TRANSACTION_ABORTED: - case STATUS_CONNECTION_ABORTED: - return WSAECONNABORTED; - - case STATUS_BAD_NETWORK_PATH: - case STATUS_NETWORK_UNREACHABLE: - case STATUS_PROTOCOL_UNREACHABLE: - return WSAENETUNREACH; - - case STATUS_HOST_UNREACHABLE: - return WSAEHOSTUNREACH; - - case STATUS_CANCELLED: - case STATUS_REQUEST_ABORTED: - return WSAEINTR; - - case STATUS_BUFFER_OVERFLOW: - case STATUS_INVALID_BUFFER_SIZE: - return WSAEMSGSIZE; - - case STATUS_BUFFER_TOO_SMALL: - case STATUS_ACCESS_VIOLATION: - return WSAEFAULT; - - case STATUS_DEVICE_NOT_READY: - case STATUS_REQUEST_NOT_ACCEPTED: - return WSAEWOULDBLOCK; - - case STATUS_INVALID_NETWORK_RESPONSE: - case STATUS_NETWORK_BUSY: - case STATUS_NO_SUCH_DEVICE: - case STATUS_NO_SUCH_FILE: - case STATUS_OBJECT_PATH_NOT_FOUND: - case STATUS_OBJECT_NAME_NOT_FOUND: - case STATUS_UNEXPECTED_NETWORK_ERROR: - return WSAENETDOWN; - - case STATUS_INVALID_CONNECTION: - return WSAENOTCONN; - - case STATUS_REMOTE_NOT_LISTENING: - case STATUS_CONNECTION_REFUSED: - return WSAECONNREFUSED; - - case STATUS_PIPE_DISCONNECTED: - return WSAESHUTDOWN; - - case STATUS_INVALID_ADDRESS: - case STATUS_INVALID_ADDRESS_COMPONENT: - return WSAEADDRNOTAVAIL; - - case STATUS_NOT_SUPPORTED: - case STATUS_NOT_IMPLEMENTED: - return WSAEOPNOTSUPP; - - case STATUS_ACCESS_DENIED: - return WSAEACCES; - - default: - - if ( NT_SUCCESS(Status) ) { - - return NO_ERROR; - } - - - case STATUS_UNSUCCESSFUL: - case STATUS_INVALID_PARAMETER: - case STATUS_ADDRESS_CLOSED: - case STATUS_CONNECTION_INVALID: - case STATUS_ADDRESS_ALREADY_ASSOCIATED: - case STATUS_ADDRESS_NOT_ASSOCIATED: - case STATUS_CONNECTION_ACTIVE: - case STATUS_INVALID_DEVICE_STATE: - case STATUS_INVALID_DEVICE_REQUEST: - return WSAEINVAL; - } -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -INT -WSPAPI -NtStatusToSocketError(IN NTSTATUS Status) -{ - switch (Status) - { - case STATUS_PENDING: - return ERROR_IO_PENDING; - - case STATUS_INVALID_HANDLE: - case STATUS_OBJECT_TYPE_MISMATCH: - return WSAENOTSOCK; - - case STATUS_INSUFFICIENT_RESOURCES: - case STATUS_PAGEFILE_QUOTA: - case STATUS_COMMITMENT_LIMIT: - case STATUS_WORKING_SET_QUOTA: - case STATUS_NO_MEMORY: - case STATUS_CONFLICTING_ADDRESSES: - case STATUS_QUOTA_EXCEEDED: - case STATUS_TOO_MANY_PAGING_FILES: - case STATUS_REMOTE_RESOURCES: - case STATUS_TOO_MANY_ADDRESSES: - return WSAENOBUFS; - - case STATUS_SHARING_VIOLATION: - case STATUS_ADDRESS_ALREADY_EXISTS: - return WSAEADDRINUSE; - - case STATUS_LINK_TIMEOUT: - case STATUS_IO_TIMEOUT: - case STATUS_TIMEOUT: - return WSAETIMEDOUT; - - case STATUS_GRACEFUL_DISCONNECT: - return WSAEDISCON; - - case STATUS_REMOTE_DISCONNECT: - case STATUS_CONNECTION_RESET: - case STATUS_LINK_FAILED: - case STATUS_CONNECTION_DISCONNECTED: - case STATUS_PORT_UNREACHABLE: - return WSAECONNRESET; - - case STATUS_LOCAL_DISCONNECT: - case STATUS_TRANSACTION_ABORTED: - case STATUS_CONNECTION_ABORTED: - return WSAECONNABORTED; - - case STATUS_BAD_NETWORK_PATH: - case STATUS_NETWORK_UNREACHABLE: - case STATUS_PROTOCOL_UNREACHABLE: - return WSAENETUNREACH; - - case STATUS_HOST_UNREACHABLE: - return WSAEHOSTUNREACH; - - case STATUS_CANCELLED: - case STATUS_REQUEST_ABORTED: - return WSAEINTR; - - case STATUS_BUFFER_OVERFLOW: - case STATUS_INVALID_BUFFER_SIZE: - return WSAEMSGSIZE; - - case STATUS_BUFFER_TOO_SMALL: - case STATUS_ACCESS_VIOLATION: - return WSAEFAULT; - - case STATUS_DEVICE_NOT_READY: - case STATUS_REQUEST_NOT_ACCEPTED: - return WSAEWOULDBLOCK; - - case STATUS_INVALID_NETWORK_RESPONSE: - case STATUS_NETWORK_BUSY: - case STATUS_NO_SUCH_DEVICE: - case STATUS_NO_SUCH_FILE: - case STATUS_OBJECT_PATH_NOT_FOUND: - case STATUS_OBJECT_NAME_NOT_FOUND: - case STATUS_UNEXPECTED_NETWORK_ERROR: - return WSAENETDOWN; - - case STATUS_INVALID_CONNECTION: - return WSAENOTCONN; - - case STATUS_REMOTE_NOT_LISTENING: - case STATUS_CONNECTION_REFUSED: - return WSAECONNREFUSED; - - case STATUS_PIPE_DISCONNECTED: - return WSAESHUTDOWN; - - case STATUS_INVALID_ADDRESS: - case STATUS_INVALID_ADDRESS_COMPONENT: - return WSAEADDRNOTAVAIL; - - case STATUS_NOT_SUPPORTED: - case STATUS_NOT_IMPLEMENTED: - return WSAEOPNOTSUPP; - - case STATUS_ACCESS_DENIED: - return WSAEACCES; - - default: - - if ( NT_SUCCESS(Status) ) { - - return NO_ERROR; - } - - - case STATUS_UNSUCCESSFUL: - case STATUS_INVALID_PARAMETER: - case STATUS_ADDRESS_CLOSED: - case STATUS_CONNECTION_INVALID: - case STATUS_ADDRESS_ALREADY_ASSOCIATED: - case STATUS_ADDRESS_NOT_ASSOCIATED: - case STATUS_CONNECTION_ACTIVE: - case STATUS_INVALID_DEVICE_STATE: - case STATUS_INVALID_DEVICE_REQUEST: - return WSAEINVAL; - } -} - diff --git a/dll/win32/mswsock/msafd/socket.c b/dll/win32/mswsock/msafd/socket.c index 61e491d57e0..02a1c2c6dde 100644 --- a/dll/win32/mswsock/msafd/socket.c +++ b/dll/win32/mswsock/msafd/socket.c @@ -797,2400 +797,3 @@ WSPCloseSocket(IN SOCKET Handle, return NO_ERROR; } -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -INT -WSPAPI -SockSocket(INT AddressFamily, - INT SocketType, - INT Protocol, - LPGUID ProviderId, - GROUP g, - DWORD dwFlags, - DWORD ProviderFlags, - DWORD ServiceFlags, - DWORD CatalogEntryId, - PSOCKET_INFORMATION *NewSocket) -{ - INT ErrorCode; - UNICODE_STRING TransportName; - PVOID HelperDllContext; - PHELPER_DATA HelperData = NULL; - DWORD HelperEvents; - PFILE_FULL_EA_INFORMATION Ea = NULL; - PAFD_CREATE_PACKET AfdPacket; - SOCKET Handle = INVALID_SOCKET; - PSOCKET_INFORMATION Socket = NULL; - BOOLEAN LockInit = FALSE; - USHORT SizeOfPacket; - DWORD SizeOfEa, SocketLength; - OBJECT_ATTRIBUTES ObjectAttributes; - UNICODE_STRING DevName; - LARGE_INTEGER GroupData; - DWORD CreateOptions = 0; - IO_STATUS_BLOCK IoStatusBlock; - PWAH_HANDLE WahHandle; - NTSTATUS Status; - CHAR AfdPacketBuffer[96]; - - /* Initialize the transport name */ - RtlInitUnicodeString(&TransportName, NULL); - - /* Get Helper Data and Transport */ - ErrorCode = SockGetTdiName(&AddressFamily, - &SocketType, - &Protocol, - ProviderId, - g, - dwFlags, - &TransportName, - &HelperDllContext, - &HelperData, - &HelperEvents); - - /* Check for error */ - if (ErrorCode != NO_ERROR) goto error; - - /* Figure out the socket context structure size */ - SocketLength = sizeof(*Socket) + (HelperData->MinWSAddressLength * 2); - - /* Allocate a socket */ - Socket = SockAllocateHeapRoutine(SockPrivateHeap, 0, SocketLength); - if (!Socket) - { - /* Couldn't create it; we need to tell WSH so it can cleanup */ - if (HelperEvents & WSH_NOTIFY_CLOSE) - { - HelperData->WSHNotify(HelperDllContext, - INVALID_SOCKET, - NULL, - NULL, - WSH_NOTIFY_CLOSE); - } - - /* Fail and return */ - ErrorCode = WSAENOBUFS; - goto error; - } - - /* Initialize it */ - RtlZeroMemory(Socket, SocketLength); - Socket->RefCount = 2; - Socket->Handle = INVALID_SOCKET; - Socket->SharedData.State = SocketUndefined; - Socket->SharedData.AddressFamily = AddressFamily; - Socket->SharedData.SocketType = SocketType; - Socket->SharedData.Protocol = Protocol; - Socket->ProviderId = *ProviderId; - Socket->HelperContext = HelperDllContext; - Socket->HelperData = HelperData; - Socket->HelperEvents = HelperEvents; - Socket->LocalAddress = (PVOID)(Socket + 1); - Socket->SharedData.SizeOfLocalAddress = HelperData->MaxWSAddressLength; - Socket->RemoteAddress = (PVOID)((ULONG_PTR)Socket->LocalAddress + - HelperData->MaxWSAddressLength); - Socket->SharedData.SizeOfRemoteAddress = HelperData->MaxWSAddressLength; - Socket->SharedData.UseDelayedAcceptance = HelperData->UseDelayedAcceptance; - Socket->SharedData.CreateFlags = dwFlags; - Socket->SharedData.CatalogEntryId = CatalogEntryId; - Socket->SharedData.ServiceFlags1 = ServiceFlags; - Socket->SharedData.ProviderFlags = ProviderFlags; - Socket->SharedData.GroupID = g; - Socket->SharedData.GroupType = 0; - Socket->SharedData.UseSAN = FALSE; - Socket->SanData = NULL; - Socket->DontUseSan = FALSE; - - /* Initialize the socket lock */ - InitializeCriticalSection(&Socket->Lock); - LockInit = TRUE; - - /* Packet Size */ - SizeOfPacket = TransportName.Length + sizeof(*AfdPacket) + sizeof(WCHAR); - - /* EA Size */ - SizeOfEa = SizeOfPacket + sizeof(*Ea) + AFD_PACKET_COMMAND_LENGTH; - - /* See if our stack buffer is big enough to hold it */ - if (SizeOfEa <= sizeof(AfdPacketBuffer)) - { - /* Use our stack */ - Ea = (PFILE_FULL_EA_INFORMATION)AfdPacketBuffer; - } - else - { - /* Allocate from heap */ - Ea = SockAllocateHeapRoutine(SockPrivateHeap, 0, SizeOfEa); - if (!Ea) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - } - - /* Set up EA */ - Ea->NextEntryOffset = 0; - Ea->Flags = 0; - Ea->EaNameLength = AFD_PACKET_COMMAND_LENGTH; - RtlCopyMemory(Ea->EaName, AfdCommand, AFD_PACKET_COMMAND_LENGTH + 1); - Ea->EaValueLength = SizeOfPacket; - - /* Set up AFD Packet */ - AfdPacket = (PAFD_CREATE_PACKET)(Ea->EaName + Ea->EaNameLength + 1); - AfdPacket->SizeOfTransportName = TransportName.Length; - RtlCopyMemory(AfdPacket->TransportName, - TransportName.Buffer, - TransportName.Length + sizeof(WCHAR)); - AfdPacket->EndpointFlags = 0; - - /* Set up Endpoint Flags */ - if ((Socket->SharedData.ServiceFlags1 & XP1_CONNECTIONLESS)) - { - /* Check the Socket Type */ - if ((SocketType != SOCK_DGRAM) && (SocketType != SOCK_RAW)) - { - /* Only RAW or UDP can be Connectionless */ - ErrorCode = WSAEINVAL; - goto error; - } - - /* Set the flag for AFD */ - AfdPacket->EndpointFlags |= AFD_ENDPOINT_CONNECTIONLESS; - } - - if ((Socket->SharedData.ServiceFlags1 & XP1_MESSAGE_ORIENTED)) - { - /* Check if this is a Stream Socket */ - if (SocketType == SOCK_STREAM) - { - /* Check if we actually support this */ - if (!(Socket->SharedData.ServiceFlags1 & XP1_PSEUDO_STREAM)) - { - /* The Provider doesn't support Message Oriented Streams */ - ErrorCode = WSAEINVAL; - goto error; - } - } - - /* Set the flag for AFD */ - AfdPacket->EndpointFlags |= AFD_ENDPOINT_MESSAGE_ORIENTED; - } - - /* If this is a Raw Socket, let AFD know */ - if (SocketType == SOCK_RAW) AfdPacket->EndpointFlags |= AFD_ENDPOINT_RAW; - - /* Check if we are a Multipoint Control/Data Root or Leaf */ - if (dwFlags & (WSA_FLAG_MULTIPOINT_C_ROOT | - WSA_FLAG_MULTIPOINT_C_LEAF | - WSA_FLAG_MULTIPOINT_D_ROOT | - WSA_FLAG_MULTIPOINT_D_LEAF)) - { - /* First make sure we support Multipoint */ - if (!(Socket->SharedData.ServiceFlags1 & XP1_SUPPORT_MULTIPOINT)) - { - /* The Provider doesn't actually support Multipoint */ - ErrorCode = WSAEINVAL; - goto error; - } - - /* Set the flag for AFD */ - AfdPacket->EndpointFlags |= AFD_ENDPOINT_MULTIPOINT; - - /* Check if we are a Control Plane Root */ - if (dwFlags & WSA_FLAG_MULTIPOINT_C_ROOT) - { - /* Check if we actually support this or if we're already a leaf */ - if ((!(Socket->SharedData.ServiceFlags1 & - XP1_MULTIPOINT_CONTROL_PLANE)) || - ((dwFlags & WSA_FLAG_MULTIPOINT_C_LEAF))) - { - ErrorCode = WSAEINVAL; - goto error; - } - - /* Set the flag for AFD */ - AfdPacket->EndpointFlags |= AFD_ENDPOINT_C_ROOT; - } - - /* Check if we a Data Plane Root */ - if (dwFlags & WSA_FLAG_MULTIPOINT_D_ROOT) - { - /* Check if we actually support this or if we're already a leaf */ - if ((!(Socket->SharedData.ServiceFlags1 & - XP1_MULTIPOINT_DATA_PLANE)) || - ((dwFlags & WSA_FLAG_MULTIPOINT_D_LEAF))) - { - ErrorCode = WSAEINVAL; - goto error; - } - - /* Set the flag for AFD */ - AfdPacket->EndpointFlags |= AFD_ENDPOINT_D_ROOT; - } - } - - /* Set the group ID */ - AfdPacket->GroupID = g; - - /* Set up Object Attributes */ - RtlInitUnicodeString(&DevName, L"\\Device\\Afd\\Endpoint"); - InitializeObjectAttributes(&ObjectAttributes, - &DevName, - OBJ_CASE_INSENSITIVE | OBJ_INHERIT, - NULL, - NULL); - - /* Check if we're not using Overlapped I/O */ - if (!(dwFlags & WSA_FLAG_OVERLAPPED)) - { - /* Set Synchronous I/O */ - CreateOptions = FILE_SYNCHRONOUS_IO_NONALERT; - } - - /* Acquire the global lock */ - SockAcquireRwLockShared(&SocketGlobalLock); - - /* Create the Socket */ - Status = NtCreateFile((PHANDLE)&Handle, - GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, - &ObjectAttributes, - &IoStatusBlock, - NULL, - 0, - FILE_SHARE_READ | FILE_SHARE_WRITE, - FILE_OPEN_IF, - CreateOptions, - Ea, - SizeOfEa); - if (!NT_SUCCESS(Status)) - { - /* Release the lock and fail */ - SockReleaseRwLockShared(&SocketGlobalLock); - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - - /* Save Handle */ - Socket->Handle = Handle; - - /* Check if a group was given */ - if (g != 0) - { - /* Get Group Id and Type */ - ErrorCode = SockGetInformation(Socket, - AFD_INFO_GROUP_ID_TYPE, - NULL, - 0, - NULL, - NULL, - &GroupData); - - /* Save them */ - Socket->SharedData.GroupID = GroupData.u.LowPart; - Socket->SharedData.GroupType = GroupData.u.HighPart; - } - - /* Check if we need to get the window sizes */ - if (!SockSendBufferWindow) - { - /* Get send window size */ - SockGetInformation(Socket, - AFD_INFO_SEND_WINDOW_SIZE, - NULL, - 0, - NULL, - &SockSendBufferWindow, - NULL); - - /* Get receive window size */ - SockGetInformation(Socket, - AFD_INFO_RECEIVE_WINDOW_SIZE, - NULL, - 0, - NULL, - &SockReceiveBufferWindow, - NULL); - } - - /* Save window sizes */ - Socket->SharedData.SizeOfRecvBuffer = SockReceiveBufferWindow; - Socket->SharedData.SizeOfSendBuffer = SockSendBufferWindow; - - /* Insert it into our table */ - WahHandle = WahInsertHandleContext(SockContextTable, &Socket->WshContext); - - /* We can release the lock now */ - SockReleaseRwLockShared(&SocketGlobalLock); - - /* Check if the handles don't match for some reason */ - if (WahHandle != &Socket->WshContext) - { - /* Do they not match? */ - if (WahHandle) - { - /* They don't... someone must've used CloseHandle */ - SockDereferenceSocket((PSOCKET_INFORMATION)WahHandle); - - /* Use the correct handle now */ - WahHandle = &Socket->WshContext; - } - else - { - /* It's not that they don't match: we don't have one at all! */ - ErrorCode = WSAENOBUFS; - goto error; - } - } - -error: - /* Check if we can free the transport name */ - if ((SocketType == SOCK_RAW) && (TransportName.Buffer)) - { - /* Free it */ - RtlFreeHeap(RtlGetProcessHeap(), 0, TransportName.Buffer); - } - - /* Check if we have the EA from the heap */ - if ((Ea) && (Ea != (PVOID)AfdPacketBuffer)) - { - /* Free it */ - RtlFreeHeap(SockPrivateHeap, 0, Ea); - } - - /* Check if this is actually success */ - if (ErrorCode != NO_ERROR) - { - /* Check if we have a socket by now */ - if (Socket) - { - /* Tell the Helper DLL we're closing it */ - SockNotifyHelperDll(Socket, WSH_NOTIFY_CLOSE); - - /* Close its handle if it's valid */ - if (Socket->WshContext.Handle != INVALID_HANDLE_VALUE) - { - NtClose(Socket->WshContext.Handle); - } - - /* Delete its lock */ - if (LockInit) DeleteCriticalSection(&Socket->Lock); - - /* Remove our socket reference */ - SockDereferenceSocket(Socket); - - /* Free it */ - RtlFreeHeap(SockPrivateHeap, 0, Socket); - } - } - - /* Return Socket and error code */ - *NewSocket = Socket; - return ErrorCode; -} - -INT -WSPAPI -SockCloseSocket(IN PSOCKET_INFORMATION Socket) -{ - INT ErrorCode; - PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; - IO_STATUS_BLOCK IoStatusBlock; - NTSTATUS Status; - AFD_DISCONNECT_INFO DisconnectInfo; - SOCKET_STATE OldState; - ULONG LingerWait; - ULONG SendsInProgress; - ULONG SleepWait; - BOOLEAN ActiveConnect; - - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* If a Close is already in Process... */ - if (Socket->SharedData.State == SocketClosed) - { - /* Release lock and fail */ - LeaveCriticalSection(&Socket->Lock); - return WSAENOTSOCK; - } - - /* Save the old state and set the new one to closed */ - OldState = Socket->SharedData.State; - Socket->SharedData.State = SocketClosed; - - /* Check if the socket has an active async data */ - ActiveConnect = (Socket->AsyncData != NULL); - - /* We're done with the socket, release the lock */ - LeaveCriticalSection(&Socket->Lock); - - /* - * If SO_LINGER is ON and the Socket was connected or had an active async - * connect context, then we'll disconnect it. Note that we won't do this - * for connection-less (UDP/RAW) sockets or if a send shutdown is active. - */ - if ((OldState == SocketConnected || ActiveConnect) && - !(Socket->SharedData.SendShutdown) && - !MSAFD_IS_DGRAM_SOCK(Socket) && - (Socket->SharedData.LingerData.l_onoff)) - { - /* We need to respect the timeout */ - SleepWait = 100; - LingerWait = Socket->SharedData.LingerData.l_linger * 1000; - - /* Loop until no more sends are pending, within the timeout */ - while (LingerWait) - { - /* Find out how many Sends are in Progress */ - if (SockGetInformation(Socket, - AFD_INFO_SENDS_IN_PROGRESS, - NULL, - 0, - NULL, - &SendsInProgress, - NULL)) - { - /* Bail out if anything but NO_ERROR */ - LingerWait = 0; - break; - } - - /* Bail out if no more sends are pending */ - if (!SendsInProgress) break; - - /* - * We have to execute a sleep, so it's kind of like - * a block. If the socket is Nonblock, we cannot - * go on since asyncronous operation is expected - * and we cannot offer it - */ - if (Socket->SharedData.NonBlocking) - { - /* Acquire the socket lock */ - EnterCriticalSection(&Socket->Lock); - - /* Restore the socket state */ - Socket->SharedData.State = OldState; - - /* Release the lock again */ - LeaveCriticalSection(&Socket->Lock); - - /* Fail with error code */ - return WSAEWOULDBLOCK; - } - - /* Now we can sleep, and decrement the linger wait */ - /* - * FIXME: It seems Windows does some funky acceleration - * since the waiting seems to be longer and longer. I - * don't think this improves performance so much, so we - * wait a fixed time instead. - */ - Sleep(SleepWait); - LingerWait -= SleepWait; - } - - /* - * We have reached the timeout or sends are over. - * Disconnect if the timeout has been reached. - */ - if (LingerWait <= 0) - { - /* There is no timeout, and this is an abortive disconnect */ - DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(0); - DisconnectInfo.DisconnectType = AFD_DISCONNECT_ABORT; - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_DISCONNECT, - &DisconnectInfo, - sizeof(DisconnectInfo), - NULL, - 0); - /* Check if the operation is pending */ - if (Status == STATUS_PENDING) - { - /* Wait for completion */ - SockWaitForSingleObject(ThreadData->EventHandle, - Socket->Handle, - !Socket->SharedData.LingerData.l_onoff ? - NO_BLOCKING_HOOK : ALWAYS_BLOCKING_HOOK, - NO_TIMEOUT); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* We actually accept errors, unless the driver wasn't ready */ - if (Status == STATUS_DEVICE_NOT_READY) - { - /* This is the equivalent of a WOULDBLOCK, which we fail */ - /* Acquire the socket lock */ - EnterCriticalSection(&Socket->Lock); - - /* Restore the socket state */ - Socket->SharedData.State = OldState; - - /* Release the lock again */ - LeaveCriticalSection(&Socket->Lock); - - /* Fail with error code */ - return WSAEWOULDBLOCK; - } - } - } - - /* Acquire the global lock to protect the handle table */ - SockAcquireRwLockShared(&SocketGlobalLock); - - /* Protect the socket too */ - EnterCriticalSection(&Socket->Lock); - - /* Notify the Helper DLL of Socket Closure */ - ErrorCode = SockNotifyHelperDll(Socket, WSH_NOTIFY_CLOSE); - - /* Cleanup Time! */ - Socket->HelperContext = NULL; - Socket->SharedData.AsyncDisabledEvents = -1; - if (Socket->TdiAddressHandle) - { - /* Close and forget the handle */ - NtClose(Socket->TdiAddressHandle); - Socket->TdiAddressHandle = NULL; - } - if (Socket->TdiConnectionHandle) - { - /* Close and forget the handle */ - NtClose(Socket->TdiConnectionHandle); - Socket->TdiConnectionHandle = NULL; - } - - /* Remove the handle from the table */ - ErrorCode = WahRemoveHandleContext(SockContextTable, &Socket->WshContext); - if (ErrorCode == NO_ERROR) - { - /* Close the socket's handle */ - NtClose(Socket->WshContext.Handle); - - /* Dereference the socket */ - SockDereferenceSocket(Socket); - } - else - { - /* This isn't a socket anymore, or something */ - ErrorCode = WSAENOTSOCK; - } - - /* Release both locks */ - LeaveCriticalSection(&Socket->Lock); - SockReleaseRwLockShared(&SocketGlobalLock); - - /* Return success */ - return ErrorCode; -} - -SOCKET -WSPAPI -WSPSocket(INT AddressFamily, - INT SocketType, - INT Protocol, - LPWSAPROTOCOL_INFOW lpProtocolInfo, - GROUP g, - DWORD dwFlags, - LPINT lpErrno) -{ - DWORD CatalogId; - SOCKET Handle = INVALID_SOCKET; - INT ErrorCode; - DWORD ServiceFlags, ProviderFlags; - PWINSOCK_TEB_DATA ThreadData; - PSOCKET_INFORMATION Socket; - GUID ProviderId; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return INVALID_SOCKET; - } - - /* Get the catalog ID */ - CatalogId = lpProtocolInfo->dwCatalogEntryId; - - /* Check if this is a duplication */ - if(lpProtocolInfo->dwProviderReserved) - { - /* Get the duplicate handle */ - Handle = (SOCKET)lpProtocolInfo->dwProviderReserved; - - /* Get our structure for it */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if(Socket) - { - /* Tell Winsock about it */ - Socket->Handle = SockUpcallTable->lpWPUModifyIFSHandle(CatalogId, - Handle, - &ErrorCode); - /* Check if we got an invalid handle back */ - if(Socket->Handle == INVALID_SOCKET) - { - /* Restore it for the error path */ - Socket->Handle = Handle; - } - } - else - { - /* The duplicate handle is invalid */ - ErrorCode = WSAEINVAL; - } - - /* Fail */ - goto error; - } - - /* See if the address family should be recovered from the protocl info */ - if (!AddressFamily || AddressFamily == FROM_PROTOCOL_INFO) - { - /* Use protocol info data */ - AddressFamily = lpProtocolInfo->iAddressFamily; - } - - /* See if the address family should be recovered from the protocl info */ - if(!SocketType || SocketType == FROM_PROTOCOL_INFO ) - { - /* Use protocol info data */ - SocketType = lpProtocolInfo->iSocketType; - } - - /* See if the address family should be recovered from the protocl info */ - if(Protocol == FROM_PROTOCOL_INFO) - { - /* Use protocol info data */ - Protocol = lpProtocolInfo->iProtocol; - } - - /* Save the service, provider flags and provider ID */ - ServiceFlags = lpProtocolInfo->dwServiceFlags1; - ProviderFlags = lpProtocolInfo->dwProviderFlags; - ProviderId = lpProtocolInfo->ProviderId; - - /* Create the actual socket */ - ErrorCode = SockSocket(AddressFamily, - SocketType, - Protocol, - &ProviderId, - g, - dwFlags, - ProviderFlags, - ServiceFlags, - CatalogId, - &Socket); - if (ErrorCode == ERROR_SUCCESS) - { - /* Acquire the socket lock */ - EnterCriticalSection(&Socket->Lock); - - /* Set status to opened */ - Socket->SharedData.State = SocketOpen; - - /* Create the Socket Context */ - ErrorCode = SockSetHandleContext(Socket); - if (ErrorCode != NO_ERROR) - { - /* Release the lock, close the socket and fail */ - LeaveCriticalSection(&Socket->Lock); - SockCloseSocket(Socket); - goto error; - } - - /* Notify Winsock */ - Handle = SockUpcallTable->lpWPUModifyIFSHandle(Socket->SharedData.CatalogEntryId, - (SOCKET)Socket->WshContext.Handle, - &ErrorCode); - - /* Does Winsock not like it? */ - if (Handle == INVALID_SOCKET) - { - /* Release the lock, close the socket and fail */ - LeaveCriticalSection(&Socket->Lock); - SockCloseSocket(Socket); - goto error; - } - - /* Release the lock */ - LeaveCriticalSection(&Socket->Lock); - } - -error: - /* Write return code */ - *lpErrno = ErrorCode; - - /* Check if we have a socket and dereference it */ - if (Socket) SockDereferenceSocket(Socket); - - /* Return handle */ - return Handle; -} - -INT -WSPAPI -WSPCloseSocket(IN SOCKET Handle, - OUT LPINT lpErrno) -{ - INT ErrorCode; - PSOCKET_INFORMATION Socket; - PWINSOCK_TEB_DATA ThreadData; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - *lpErrno = WSAENOTSOCK; - return SOCKET_ERROR; - } - - /* Close it */ - ErrorCode = SockCloseSocket(Socket); - - /* Remove the final reference */ - SockDereferenceSocket(Socket); - - /* Check if we got here by error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -INT -WSPAPI -SockSocket(INT AddressFamily, - INT SocketType, - INT Protocol, - LPGUID ProviderId, - GROUP g, - DWORD dwFlags, - DWORD ProviderFlags, - DWORD ServiceFlags, - DWORD CatalogEntryId, - PSOCKET_INFORMATION *NewSocket) -{ - INT ErrorCode; - UNICODE_STRING TransportName; - PVOID HelperDllContext; - PHELPER_DATA HelperData = NULL; - DWORD HelperEvents; - PFILE_FULL_EA_INFORMATION Ea = NULL; - PAFD_CREATE_PACKET AfdPacket; - SOCKET Handle = INVALID_SOCKET; - PSOCKET_INFORMATION Socket = NULL; - BOOLEAN LockInit = FALSE; - USHORT SizeOfPacket; - DWORD SizeOfEa, SocketLength; - OBJECT_ATTRIBUTES ObjectAttributes; - UNICODE_STRING DevName; - LARGE_INTEGER GroupData; - DWORD CreateOptions = 0; - IO_STATUS_BLOCK IoStatusBlock; - PWAH_HANDLE WahHandle; - NTSTATUS Status; - CHAR AfdPacketBuffer[96]; - - /* Initialize the transport name */ - RtlInitUnicodeString(&TransportName, NULL); - - /* Get Helper Data and Transport */ - ErrorCode = SockGetTdiName(&AddressFamily, - &SocketType, - &Protocol, - ProviderId, - g, - dwFlags, - &TransportName, - &HelperDllContext, - &HelperData, - &HelperEvents); - - /* Check for error */ - if (ErrorCode != NO_ERROR) goto error; - - /* Figure out the socket context structure size */ - SocketLength = sizeof(*Socket) + (HelperData->MinWSAddressLength * 2); - - /* Allocate a socket */ - Socket = SockAllocateHeapRoutine(SockPrivateHeap, 0, SocketLength); - if (!Socket) - { - /* Couldn't create it; we need to tell WSH so it can cleanup */ - if (HelperEvents & WSH_NOTIFY_CLOSE) - { - HelperData->WSHNotify(HelperDllContext, - INVALID_SOCKET, - NULL, - NULL, - WSH_NOTIFY_CLOSE); - } - - /* Fail and return */ - ErrorCode = WSAENOBUFS; - goto error; - } - - /* Initialize it */ - RtlZeroMemory(Socket, SocketLength); - Socket->RefCount = 2; - Socket->Handle = INVALID_SOCKET; - Socket->SharedData.State = SocketUndefined; - Socket->SharedData.AddressFamily = AddressFamily; - Socket->SharedData.SocketType = SocketType; - Socket->SharedData.Protocol = Protocol; - Socket->ProviderId = *ProviderId; - Socket->HelperContext = HelperDllContext; - Socket->HelperData = HelperData; - Socket->HelperEvents = HelperEvents; - Socket->LocalAddress = (PVOID)(Socket + 1); - Socket->SharedData.SizeOfLocalAddress = HelperData->MaxWSAddressLength; - Socket->RemoteAddress = (PVOID)((ULONG_PTR)Socket->LocalAddress + - HelperData->MaxWSAddressLength); - Socket->SharedData.SizeOfRemoteAddress = HelperData->MaxWSAddressLength; - Socket->SharedData.UseDelayedAcceptance = HelperData->UseDelayedAcceptance; - Socket->SharedData.CreateFlags = dwFlags; - Socket->SharedData.CatalogEntryId = CatalogEntryId; - Socket->SharedData.ServiceFlags1 = ServiceFlags; - Socket->SharedData.ProviderFlags = ProviderFlags; - Socket->SharedData.GroupID = g; - Socket->SharedData.GroupType = 0; - Socket->SharedData.UseSAN = FALSE; - Socket->SanData = NULL; - Socket->DontUseSan = FALSE; - - /* Initialize the socket lock */ - InitializeCriticalSection(&Socket->Lock); - LockInit = TRUE; - - /* Packet Size */ - SizeOfPacket = TransportName.Length + sizeof(*AfdPacket) + sizeof(WCHAR); - - /* EA Size */ - SizeOfEa = SizeOfPacket + sizeof(*Ea) + AFD_PACKET_COMMAND_LENGTH; - - /* See if our stack buffer is big enough to hold it */ - if (SizeOfEa <= sizeof(AfdPacketBuffer)) - { - /* Use our stack */ - Ea = (PFILE_FULL_EA_INFORMATION)AfdPacketBuffer; - } - else - { - /* Allocate from heap */ - Ea = SockAllocateHeapRoutine(SockPrivateHeap, 0, SizeOfEa); - if (!Ea) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - } - - /* Set up EA */ - Ea->NextEntryOffset = 0; - Ea->Flags = 0; - Ea->EaNameLength = AFD_PACKET_COMMAND_LENGTH; - RtlCopyMemory(Ea->EaName, AfdCommand, AFD_PACKET_COMMAND_LENGTH + 1); - Ea->EaValueLength = SizeOfPacket; - - /* Set up AFD Packet */ - AfdPacket = (PAFD_CREATE_PACKET)(Ea->EaName + Ea->EaNameLength + 1); - AfdPacket->SizeOfTransportName = TransportName.Length; - RtlCopyMemory(AfdPacket->TransportName, - TransportName.Buffer, - TransportName.Length + sizeof(WCHAR)); - AfdPacket->EndpointFlags = 0; - - /* Set up Endpoint Flags */ - if ((Socket->SharedData.ServiceFlags1 & XP1_CONNECTIONLESS)) - { - /* Check the Socket Type */ - if ((SocketType != SOCK_DGRAM) && (SocketType != SOCK_RAW)) - { - /* Only RAW or UDP can be Connectionless */ - ErrorCode = WSAEINVAL; - goto error; - } - - /* Set the flag for AFD */ - AfdPacket->EndpointFlags |= AFD_ENDPOINT_CONNECTIONLESS; - } - - if ((Socket->SharedData.ServiceFlags1 & XP1_MESSAGE_ORIENTED)) - { - /* Check if this is a Stream Socket */ - if (SocketType == SOCK_STREAM) - { - /* Check if we actually support this */ - if (!(Socket->SharedData.ServiceFlags1 & XP1_PSEUDO_STREAM)) - { - /* The Provider doesn't support Message Oriented Streams */ - ErrorCode = WSAEINVAL; - goto error; - } - } - - /* Set the flag for AFD */ - AfdPacket->EndpointFlags |= AFD_ENDPOINT_MESSAGE_ORIENTED; - } - - /* If this is a Raw Socket, let AFD know */ - if (SocketType == SOCK_RAW) AfdPacket->EndpointFlags |= AFD_ENDPOINT_RAW; - - /* Check if we are a Multipoint Control/Data Root or Leaf */ - if (dwFlags & (WSA_FLAG_MULTIPOINT_C_ROOT | - WSA_FLAG_MULTIPOINT_C_LEAF | - WSA_FLAG_MULTIPOINT_D_ROOT | - WSA_FLAG_MULTIPOINT_D_LEAF)) - { - /* First make sure we support Multipoint */ - if (!(Socket->SharedData.ServiceFlags1 & XP1_SUPPORT_MULTIPOINT)) - { - /* The Provider doesn't actually support Multipoint */ - ErrorCode = WSAEINVAL; - goto error; - } - - /* Set the flag for AFD */ - AfdPacket->EndpointFlags |= AFD_ENDPOINT_MULTIPOINT; - - /* Check if we are a Control Plane Root */ - if (dwFlags & WSA_FLAG_MULTIPOINT_C_ROOT) - { - /* Check if we actually support this or if we're already a leaf */ - if ((!(Socket->SharedData.ServiceFlags1 & - XP1_MULTIPOINT_CONTROL_PLANE)) || - ((dwFlags & WSA_FLAG_MULTIPOINT_C_LEAF))) - { - ErrorCode = WSAEINVAL; - goto error; - } - - /* Set the flag for AFD */ - AfdPacket->EndpointFlags |= AFD_ENDPOINT_C_ROOT; - } - - /* Check if we a Data Plane Root */ - if (dwFlags & WSA_FLAG_MULTIPOINT_D_ROOT) - { - /* Check if we actually support this or if we're already a leaf */ - if ((!(Socket->SharedData.ServiceFlags1 & - XP1_MULTIPOINT_DATA_PLANE)) || - ((dwFlags & WSA_FLAG_MULTIPOINT_D_LEAF))) - { - ErrorCode = WSAEINVAL; - goto error; - } - - /* Set the flag for AFD */ - AfdPacket->EndpointFlags |= AFD_ENDPOINT_D_ROOT; - } - } - - /* Set the group ID */ - AfdPacket->GroupID = g; - - /* Set up Object Attributes */ - RtlInitUnicodeString(&DevName, L"\\Device\\Afd\\Endpoint"); - InitializeObjectAttributes(&ObjectAttributes, - &DevName, - OBJ_CASE_INSENSITIVE | OBJ_INHERIT, - NULL, - NULL); - - /* Check if we're not using Overlapped I/O */ - if (!(dwFlags & WSA_FLAG_OVERLAPPED)) - { - /* Set Synchronous I/O */ - CreateOptions = FILE_SYNCHRONOUS_IO_NONALERT; - } - - /* Acquire the global lock */ - SockAcquireRwLockShared(&SocketGlobalLock); - - /* Create the Socket */ - Status = NtCreateFile((PHANDLE)&Handle, - GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, - &ObjectAttributes, - &IoStatusBlock, - NULL, - 0, - FILE_SHARE_READ | FILE_SHARE_WRITE, - FILE_OPEN_IF, - CreateOptions, - Ea, - SizeOfEa); - if (!NT_SUCCESS(Status)) - { - /* Release the lock and fail */ - SockReleaseRwLockShared(&SocketGlobalLock); - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - - /* Save Handle */ - Socket->Handle = Handle; - - /* Check if a group was given */ - if (g != 0) - { - /* Get Group Id and Type */ - ErrorCode = SockGetInformation(Socket, - AFD_INFO_GROUP_ID_TYPE, - NULL, - 0, - NULL, - NULL, - &GroupData); - - /* Save them */ - Socket->SharedData.GroupID = GroupData.u.LowPart; - Socket->SharedData.GroupType = GroupData.u.HighPart; - } - - /* Check if we need to get the window sizes */ - if (!SockSendBufferWindow) - { - /* Get send window size */ - SockGetInformation(Socket, - AFD_INFO_SEND_WINDOW_SIZE, - NULL, - 0, - NULL, - &SockSendBufferWindow, - NULL); - - /* Get receive window size */ - SockGetInformation(Socket, - AFD_INFO_RECEIVE_WINDOW_SIZE, - NULL, - 0, - NULL, - &SockReceiveBufferWindow, - NULL); - } - - /* Save window sizes */ - Socket->SharedData.SizeOfRecvBuffer = SockReceiveBufferWindow; - Socket->SharedData.SizeOfSendBuffer = SockSendBufferWindow; - - /* Insert it into our table */ - WahHandle = WahInsertHandleContext(SockContextTable, &Socket->WshContext); - - /* We can release the lock now */ - SockReleaseRwLockShared(&SocketGlobalLock); - - /* Check if the handles don't match for some reason */ - if (WahHandle != &Socket->WshContext) - { - /* Do they not match? */ - if (WahHandle) - { - /* They don't... someone must've used CloseHandle */ - SockDereferenceSocket((PSOCKET_INFORMATION)WahHandle); - - /* Use the correct handle now */ - WahHandle = &Socket->WshContext; - } - else - { - /* It's not that they don't match: we don't have one at all! */ - ErrorCode = WSAENOBUFS; - goto error; - } - } - -error: - /* Check if we can free the transport name */ - if ((SocketType == SOCK_RAW) && (TransportName.Buffer)) - { - /* Free it */ - RtlFreeHeap(RtlGetProcessHeap(), 0, TransportName.Buffer); - } - - /* Check if we have the EA from the heap */ - if ((Ea) && (Ea != (PVOID)AfdPacketBuffer)) - { - /* Free it */ - RtlFreeHeap(SockPrivateHeap, 0, Ea); - } - - /* Check if this is actually success */ - if (ErrorCode != NO_ERROR) - { - /* Check if we have a socket by now */ - if (Socket) - { - /* Tell the Helper DLL we're closing it */ - SockNotifyHelperDll(Socket, WSH_NOTIFY_CLOSE); - - /* Close its handle if it's valid */ - if (Socket->WshContext.Handle != INVALID_HANDLE_VALUE) - { - NtClose(Socket->WshContext.Handle); - } - - /* Delete its lock */ - if (LockInit) DeleteCriticalSection(&Socket->Lock); - - /* Remove our socket reference */ - SockDereferenceSocket(Socket); - - /* Free it */ - RtlFreeHeap(SockPrivateHeap, 0, Socket); - } - } - - /* Return Socket and error code */ - *NewSocket = Socket; - return ErrorCode; -} - -INT -WSPAPI -SockCloseSocket(IN PSOCKET_INFORMATION Socket) -{ - INT ErrorCode; - PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; - IO_STATUS_BLOCK IoStatusBlock; - NTSTATUS Status; - AFD_DISCONNECT_INFO DisconnectInfo; - SOCKET_STATE OldState; - ULONG LingerWait; - ULONG SendsInProgress; - ULONG SleepWait; - BOOLEAN ActiveConnect; - - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* If a Close is already in Process... */ - if (Socket->SharedData.State == SocketClosed) - { - /* Release lock and fail */ - LeaveCriticalSection(&Socket->Lock); - return WSAENOTSOCK; - } - - /* Save the old state and set the new one to closed */ - OldState = Socket->SharedData.State; - Socket->SharedData.State = SocketClosed; - - /* Check if the socket has an active async data */ - ActiveConnect = (Socket->AsyncData != NULL); - - /* We're done with the socket, release the lock */ - LeaveCriticalSection(&Socket->Lock); - - /* - * If SO_LINGER is ON and the Socket was connected or had an active async - * connect context, then we'll disconnect it. Note that we won't do this - * for connection-less (UDP/RAW) sockets or if a send shutdown is active. - */ - if ((OldState == SocketConnected || ActiveConnect) && - !(Socket->SharedData.SendShutdown) && - !MSAFD_IS_DGRAM_SOCK(Socket) && - (Socket->SharedData.LingerData.l_onoff)) - { - /* We need to respect the timeout */ - SleepWait = 100; - LingerWait = Socket->SharedData.LingerData.l_linger * 1000; - - /* Loop until no more sends are pending, within the timeout */ - while (LingerWait) - { - /* Find out how many Sends are in Progress */ - if (SockGetInformation(Socket, - AFD_INFO_SENDS_IN_PROGRESS, - NULL, - 0, - NULL, - &SendsInProgress, - NULL)) - { - /* Bail out if anything but NO_ERROR */ - LingerWait = 0; - break; - } - - /* Bail out if no more sends are pending */ - if (!SendsInProgress) break; - - /* - * We have to execute a sleep, so it's kind of like - * a block. If the socket is Nonblock, we cannot - * go on since asyncronous operation is expected - * and we cannot offer it - */ - if (Socket->SharedData.NonBlocking) - { - /* Acquire the socket lock */ - EnterCriticalSection(&Socket->Lock); - - /* Restore the socket state */ - Socket->SharedData.State = OldState; - - /* Release the lock again */ - LeaveCriticalSection(&Socket->Lock); - - /* Fail with error code */ - return WSAEWOULDBLOCK; - } - - /* Now we can sleep, and decrement the linger wait */ - /* - * FIXME: It seems Windows does some funky acceleration - * since the waiting seems to be longer and longer. I - * don't think this improves performance so much, so we - * wait a fixed time instead. - */ - Sleep(SleepWait); - LingerWait -= SleepWait; - } - - /* - * We have reached the timeout or sends are over. - * Disconnect if the timeout has been reached. - */ - if (LingerWait <= 0) - { - /* There is no timeout, and this is an abortive disconnect */ - DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(0); - DisconnectInfo.DisconnectType = AFD_DISCONNECT_ABORT; - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_DISCONNECT, - &DisconnectInfo, - sizeof(DisconnectInfo), - NULL, - 0); - /* Check if the operation is pending */ - if (Status == STATUS_PENDING) - { - /* Wait for completion */ - SockWaitForSingleObject(ThreadData->EventHandle, - Socket->Handle, - !Socket->SharedData.LingerData.l_onoff ? - NO_BLOCKING_HOOK : ALWAYS_BLOCKING_HOOK, - NO_TIMEOUT); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* We actually accept errors, unless the driver wasn't ready */ - if (Status == STATUS_DEVICE_NOT_READY) - { - /* This is the equivalent of a WOULDBLOCK, which we fail */ - /* Acquire the socket lock */ - EnterCriticalSection(&Socket->Lock); - - /* Restore the socket state */ - Socket->SharedData.State = OldState; - - /* Release the lock again */ - LeaveCriticalSection(&Socket->Lock); - - /* Fail with error code */ - return WSAEWOULDBLOCK; - } - } - } - - /* Acquire the global lock to protect the handle table */ - SockAcquireRwLockShared(&SocketGlobalLock); - - /* Protect the socket too */ - EnterCriticalSection(&Socket->Lock); - - /* Notify the Helper DLL of Socket Closure */ - ErrorCode = SockNotifyHelperDll(Socket, WSH_NOTIFY_CLOSE); - - /* Cleanup Time! */ - Socket->HelperContext = NULL; - Socket->SharedData.AsyncDisabledEvents = -1; - if (Socket->TdiAddressHandle) - { - /* Close and forget the handle */ - NtClose(Socket->TdiAddressHandle); - Socket->TdiAddressHandle = NULL; - } - if (Socket->TdiConnectionHandle) - { - /* Close and forget the handle */ - NtClose(Socket->TdiConnectionHandle); - Socket->TdiConnectionHandle = NULL; - } - - /* Remove the handle from the table */ - ErrorCode = WahRemoveHandleContext(SockContextTable, &Socket->WshContext); - if (ErrorCode == NO_ERROR) - { - /* Close the socket's handle */ - NtClose(Socket->WshContext.Handle); - - /* Dereference the socket */ - SockDereferenceSocket(Socket); - } - else - { - /* This isn't a socket anymore, or something */ - ErrorCode = WSAENOTSOCK; - } - - /* Release both locks */ - LeaveCriticalSection(&Socket->Lock); - SockReleaseRwLockShared(&SocketGlobalLock); - - /* Return success */ - return ErrorCode; -} - -SOCKET -WSPAPI -WSPSocket(INT AddressFamily, - INT SocketType, - INT Protocol, - LPWSAPROTOCOL_INFOW lpProtocolInfo, - GROUP g, - DWORD dwFlags, - LPINT lpErrno) -{ - DWORD CatalogId; - SOCKET Handle = INVALID_SOCKET; - INT ErrorCode; - DWORD ServiceFlags, ProviderFlags; - PWINSOCK_TEB_DATA ThreadData; - PSOCKET_INFORMATION Socket; - GUID ProviderId; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return INVALID_SOCKET; - } - - /* Get the catalog ID */ - CatalogId = lpProtocolInfo->dwCatalogEntryId; - - /* Check if this is a duplication */ - if(lpProtocolInfo->dwProviderReserved) - { - /* Get the duplicate handle */ - Handle = (SOCKET)lpProtocolInfo->dwProviderReserved; - - /* Get our structure for it */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if(Socket) - { - /* Tell Winsock about it */ - Socket->Handle = SockUpcallTable->lpWPUModifyIFSHandle(CatalogId, - Handle, - &ErrorCode); - /* Check if we got an invalid handle back */ - if(Socket->Handle == INVALID_SOCKET) - { - /* Restore it for the error path */ - Socket->Handle = Handle; - } - } - else - { - /* The duplicate handle is invalid */ - ErrorCode = WSAEINVAL; - } - - /* Fail */ - goto error; - } - - /* See if the address family should be recovered from the protocl info */ - if (!AddressFamily || AddressFamily == FROM_PROTOCOL_INFO) - { - /* Use protocol info data */ - AddressFamily = lpProtocolInfo->iAddressFamily; - } - - /* See if the address family should be recovered from the protocl info */ - if(!SocketType || SocketType == FROM_PROTOCOL_INFO ) - { - /* Use protocol info data */ - SocketType = lpProtocolInfo->iSocketType; - } - - /* See if the address family should be recovered from the protocl info */ - if(Protocol == FROM_PROTOCOL_INFO) - { - /* Use protocol info data */ - Protocol = lpProtocolInfo->iProtocol; - } - - /* Save the service, provider flags and provider ID */ - ServiceFlags = lpProtocolInfo->dwServiceFlags1; - ProviderFlags = lpProtocolInfo->dwProviderFlags; - ProviderId = lpProtocolInfo->ProviderId; - - /* Create the actual socket */ - ErrorCode = SockSocket(AddressFamily, - SocketType, - Protocol, - &ProviderId, - g, - dwFlags, - ProviderFlags, - ServiceFlags, - CatalogId, - &Socket); - if (ErrorCode == ERROR_SUCCESS) - { - /* Acquire the socket lock */ - EnterCriticalSection(&Socket->Lock); - - /* Set status to opened */ - Socket->SharedData.State = SocketOpen; - - /* Create the Socket Context */ - ErrorCode = SockSetHandleContext(Socket); - if (ErrorCode != NO_ERROR) - { - /* Release the lock, close the socket and fail */ - LeaveCriticalSection(&Socket->Lock); - SockCloseSocket(Socket); - goto error; - } - - /* Notify Winsock */ - Handle = SockUpcallTable->lpWPUModifyIFSHandle(Socket->SharedData.CatalogEntryId, - (SOCKET)Socket->WshContext.Handle, - &ErrorCode); - - /* Does Winsock not like it? */ - if (Handle == INVALID_SOCKET) - { - /* Release the lock, close the socket and fail */ - LeaveCriticalSection(&Socket->Lock); - SockCloseSocket(Socket); - goto error; - } - - /* Release the lock */ - LeaveCriticalSection(&Socket->Lock); - } - -error: - /* Write return code */ - *lpErrno = ErrorCode; - - /* Check if we have a socket and dereference it */ - if (Socket) SockDereferenceSocket(Socket); - - /* Return handle */ - return Handle; -} - -INT -WSPAPI -WSPCloseSocket(IN SOCKET Handle, - OUT LPINT lpErrno) -{ - INT ErrorCode; - PSOCKET_INFORMATION Socket; - PWINSOCK_TEB_DATA ThreadData; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - *lpErrno = WSAENOTSOCK; - return SOCKET_ERROR; - } - - /* Close it */ - ErrorCode = SockCloseSocket(Socket); - - /* Remove the final reference */ - SockDereferenceSocket(Socket); - - /* Check if we got here by error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -INT -WSPAPI -SockSocket(INT AddressFamily, - INT SocketType, - INT Protocol, - LPGUID ProviderId, - GROUP g, - DWORD dwFlags, - DWORD ProviderFlags, - DWORD ServiceFlags, - DWORD CatalogEntryId, - PSOCKET_INFORMATION *NewSocket) -{ - INT ErrorCode; - UNICODE_STRING TransportName; - PVOID HelperDllContext; - PHELPER_DATA HelperData = NULL; - DWORD HelperEvents; - PFILE_FULL_EA_INFORMATION Ea = NULL; - PAFD_CREATE_PACKET AfdPacket; - SOCKET Handle = INVALID_SOCKET; - PSOCKET_INFORMATION Socket = NULL; - BOOLEAN LockInit = FALSE; - USHORT SizeOfPacket; - DWORD SizeOfEa, SocketLength; - OBJECT_ATTRIBUTES ObjectAttributes; - UNICODE_STRING DevName; - LARGE_INTEGER GroupData; - DWORD CreateOptions = 0; - IO_STATUS_BLOCK IoStatusBlock; - PWAH_HANDLE WahHandle; - NTSTATUS Status; - CHAR AfdPacketBuffer[96]; - - /* Initialize the transport name */ - RtlInitUnicodeString(&TransportName, NULL); - - /* Get Helper Data and Transport */ - ErrorCode = SockGetTdiName(&AddressFamily, - &SocketType, - &Protocol, - ProviderId, - g, - dwFlags, - &TransportName, - &HelperDllContext, - &HelperData, - &HelperEvents); - - /* Check for error */ - if (ErrorCode != NO_ERROR) goto error; - - /* Figure out the socket context structure size */ - SocketLength = sizeof(*Socket) + (HelperData->MinWSAddressLength * 2); - - /* Allocate a socket */ - Socket = SockAllocateHeapRoutine(SockPrivateHeap, 0, SocketLength); - if (!Socket) - { - /* Couldn't create it; we need to tell WSH so it can cleanup */ - if (HelperEvents & WSH_NOTIFY_CLOSE) - { - HelperData->WSHNotify(HelperDllContext, - INVALID_SOCKET, - NULL, - NULL, - WSH_NOTIFY_CLOSE); - } - - /* Fail and return */ - ErrorCode = WSAENOBUFS; - goto error; - } - - /* Initialize it */ - RtlZeroMemory(Socket, SocketLength); - Socket->RefCount = 2; - Socket->Handle = INVALID_SOCKET; - Socket->SharedData.State = SocketUndefined; - Socket->SharedData.AddressFamily = AddressFamily; - Socket->SharedData.SocketType = SocketType; - Socket->SharedData.Protocol = Protocol; - Socket->ProviderId = *ProviderId; - Socket->HelperContext = HelperDllContext; - Socket->HelperData = HelperData; - Socket->HelperEvents = HelperEvents; - Socket->LocalAddress = (PVOID)(Socket + 1); - Socket->SharedData.SizeOfLocalAddress = HelperData->MaxWSAddressLength; - Socket->RemoteAddress = (PVOID)((ULONG_PTR)Socket->LocalAddress + - HelperData->MaxWSAddressLength); - Socket->SharedData.SizeOfRemoteAddress = HelperData->MaxWSAddressLength; - Socket->SharedData.UseDelayedAcceptance = HelperData->UseDelayedAcceptance; - Socket->SharedData.CreateFlags = dwFlags; - Socket->SharedData.CatalogEntryId = CatalogEntryId; - Socket->SharedData.ServiceFlags1 = ServiceFlags; - Socket->SharedData.ProviderFlags = ProviderFlags; - Socket->SharedData.GroupID = g; - Socket->SharedData.GroupType = 0; - Socket->SharedData.UseSAN = FALSE; - Socket->SanData = NULL; - Socket->DontUseSan = FALSE; - - /* Initialize the socket lock */ - InitializeCriticalSection(&Socket->Lock); - LockInit = TRUE; - - /* Packet Size */ - SizeOfPacket = TransportName.Length + sizeof(*AfdPacket) + sizeof(WCHAR); - - /* EA Size */ - SizeOfEa = SizeOfPacket + sizeof(*Ea) + AFD_PACKET_COMMAND_LENGTH; - - /* See if our stack buffer is big enough to hold it */ - if (SizeOfEa <= sizeof(AfdPacketBuffer)) - { - /* Use our stack */ - Ea = (PFILE_FULL_EA_INFORMATION)AfdPacketBuffer; - } - else - { - /* Allocate from heap */ - Ea = SockAllocateHeapRoutine(SockPrivateHeap, 0, SizeOfEa); - if (!Ea) - { - /* Fail */ - ErrorCode = WSAENOBUFS; - goto error; - } - } - - /* Set up EA */ - Ea->NextEntryOffset = 0; - Ea->Flags = 0; - Ea->EaNameLength = AFD_PACKET_COMMAND_LENGTH; - RtlCopyMemory(Ea->EaName, AfdCommand, AFD_PACKET_COMMAND_LENGTH + 1); - Ea->EaValueLength = SizeOfPacket; - - /* Set up AFD Packet */ - AfdPacket = (PAFD_CREATE_PACKET)(Ea->EaName + Ea->EaNameLength + 1); - AfdPacket->SizeOfTransportName = TransportName.Length; - RtlCopyMemory(AfdPacket->TransportName, - TransportName.Buffer, - TransportName.Length + sizeof(WCHAR)); - AfdPacket->EndpointFlags = 0; - - /* Set up Endpoint Flags */ - if ((Socket->SharedData.ServiceFlags1 & XP1_CONNECTIONLESS)) - { - /* Check the Socket Type */ - if ((SocketType != SOCK_DGRAM) && (SocketType != SOCK_RAW)) - { - /* Only RAW or UDP can be Connectionless */ - ErrorCode = WSAEINVAL; - goto error; - } - - /* Set the flag for AFD */ - AfdPacket->EndpointFlags |= AFD_ENDPOINT_CONNECTIONLESS; - } - - if ((Socket->SharedData.ServiceFlags1 & XP1_MESSAGE_ORIENTED)) - { - /* Check if this is a Stream Socket */ - if (SocketType == SOCK_STREAM) - { - /* Check if we actually support this */ - if (!(Socket->SharedData.ServiceFlags1 & XP1_PSEUDO_STREAM)) - { - /* The Provider doesn't support Message Oriented Streams */ - ErrorCode = WSAEINVAL; - goto error; - } - } - - /* Set the flag for AFD */ - AfdPacket->EndpointFlags |= AFD_ENDPOINT_MESSAGE_ORIENTED; - } - - /* If this is a Raw Socket, let AFD know */ - if (SocketType == SOCK_RAW) AfdPacket->EndpointFlags |= AFD_ENDPOINT_RAW; - - /* Check if we are a Multipoint Control/Data Root or Leaf */ - if (dwFlags & (WSA_FLAG_MULTIPOINT_C_ROOT | - WSA_FLAG_MULTIPOINT_C_LEAF | - WSA_FLAG_MULTIPOINT_D_ROOT | - WSA_FLAG_MULTIPOINT_D_LEAF)) - { - /* First make sure we support Multipoint */ - if (!(Socket->SharedData.ServiceFlags1 & XP1_SUPPORT_MULTIPOINT)) - { - /* The Provider doesn't actually support Multipoint */ - ErrorCode = WSAEINVAL; - goto error; - } - - /* Set the flag for AFD */ - AfdPacket->EndpointFlags |= AFD_ENDPOINT_MULTIPOINT; - - /* Check if we are a Control Plane Root */ - if (dwFlags & WSA_FLAG_MULTIPOINT_C_ROOT) - { - /* Check if we actually support this or if we're already a leaf */ - if ((!(Socket->SharedData.ServiceFlags1 & - XP1_MULTIPOINT_CONTROL_PLANE)) || - ((dwFlags & WSA_FLAG_MULTIPOINT_C_LEAF))) - { - ErrorCode = WSAEINVAL; - goto error; - } - - /* Set the flag for AFD */ - AfdPacket->EndpointFlags |= AFD_ENDPOINT_C_ROOT; - } - - /* Check if we a Data Plane Root */ - if (dwFlags & WSA_FLAG_MULTIPOINT_D_ROOT) - { - /* Check if we actually support this or if we're already a leaf */ - if ((!(Socket->SharedData.ServiceFlags1 & - XP1_MULTIPOINT_DATA_PLANE)) || - ((dwFlags & WSA_FLAG_MULTIPOINT_D_LEAF))) - { - ErrorCode = WSAEINVAL; - goto error; - } - - /* Set the flag for AFD */ - AfdPacket->EndpointFlags |= AFD_ENDPOINT_D_ROOT; - } - } - - /* Set the group ID */ - AfdPacket->GroupID = g; - - /* Set up Object Attributes */ - RtlInitUnicodeString(&DevName, L"\\Device\\Afd\\Endpoint"); - InitializeObjectAttributes(&ObjectAttributes, - &DevName, - OBJ_CASE_INSENSITIVE | OBJ_INHERIT, - NULL, - NULL); - - /* Check if we're not using Overlapped I/O */ - if (!(dwFlags & WSA_FLAG_OVERLAPPED)) - { - /* Set Synchronous I/O */ - CreateOptions = FILE_SYNCHRONOUS_IO_NONALERT; - } - - /* Acquire the global lock */ - SockAcquireRwLockShared(&SocketGlobalLock); - - /* Create the Socket */ - Status = NtCreateFile((PHANDLE)&Handle, - GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, - &ObjectAttributes, - &IoStatusBlock, - NULL, - 0, - FILE_SHARE_READ | FILE_SHARE_WRITE, - FILE_OPEN_IF, - CreateOptions, - Ea, - SizeOfEa); - if (!NT_SUCCESS(Status)) - { - /* Release the lock and fail */ - SockReleaseRwLockShared(&SocketGlobalLock); - ErrorCode = NtStatusToSocketError(Status); - goto error; - } - - /* Save Handle */ - Socket->Handle = Handle; - - /* Check if a group was given */ - if (g != 0) - { - /* Get Group Id and Type */ - ErrorCode = SockGetInformation(Socket, - AFD_INFO_GROUP_ID_TYPE, - NULL, - 0, - NULL, - NULL, - &GroupData); - - /* Save them */ - Socket->SharedData.GroupID = GroupData.u.LowPart; - Socket->SharedData.GroupType = GroupData.u.HighPart; - } - - /* Check if we need to get the window sizes */ - if (!SockSendBufferWindow) - { - /* Get send window size */ - SockGetInformation(Socket, - AFD_INFO_SEND_WINDOW_SIZE, - NULL, - 0, - NULL, - &SockSendBufferWindow, - NULL); - - /* Get receive window size */ - SockGetInformation(Socket, - AFD_INFO_RECEIVE_WINDOW_SIZE, - NULL, - 0, - NULL, - &SockReceiveBufferWindow, - NULL); - } - - /* Save window sizes */ - Socket->SharedData.SizeOfRecvBuffer = SockReceiveBufferWindow; - Socket->SharedData.SizeOfSendBuffer = SockSendBufferWindow; - - /* Insert it into our table */ - WahHandle = WahInsertHandleContext(SockContextTable, &Socket->WshContext); - - /* We can release the lock now */ - SockReleaseRwLockShared(&SocketGlobalLock); - - /* Check if the handles don't match for some reason */ - if (WahHandle != &Socket->WshContext) - { - /* Do they not match? */ - if (WahHandle) - { - /* They don't... someone must've used CloseHandle */ - SockDereferenceSocket((PSOCKET_INFORMATION)WahHandle); - - /* Use the correct handle now */ - WahHandle = &Socket->WshContext; - } - else - { - /* It's not that they don't match: we don't have one at all! */ - ErrorCode = WSAENOBUFS; - goto error; - } - } - -error: - /* Check if we can free the transport name */ - if ((SocketType == SOCK_RAW) && (TransportName.Buffer)) - { - /* Free it */ - RtlFreeHeap(RtlGetProcessHeap(), 0, TransportName.Buffer); - } - - /* Check if we have the EA from the heap */ - if ((Ea) && (Ea != (PVOID)AfdPacketBuffer)) - { - /* Free it */ - RtlFreeHeap(SockPrivateHeap, 0, Ea); - } - - /* Check if this is actually success */ - if (ErrorCode != NO_ERROR) - { - /* Check if we have a socket by now */ - if (Socket) - { - /* Tell the Helper DLL we're closing it */ - SockNotifyHelperDll(Socket, WSH_NOTIFY_CLOSE); - - /* Close its handle if it's valid */ - if (Socket->WshContext.Handle != INVALID_HANDLE_VALUE) - { - NtClose(Socket->WshContext.Handle); - } - - /* Delete its lock */ - if (LockInit) DeleteCriticalSection(&Socket->Lock); - - /* Remove our socket reference */ - SockDereferenceSocket(Socket); - - /* Free it */ - RtlFreeHeap(SockPrivateHeap, 0, Socket); - } - } - - /* Return Socket and error code */ - *NewSocket = Socket; - return ErrorCode; -} - -INT -WSPAPI -SockCloseSocket(IN PSOCKET_INFORMATION Socket) -{ - INT ErrorCode; - PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; - IO_STATUS_BLOCK IoStatusBlock; - NTSTATUS Status; - AFD_DISCONNECT_INFO DisconnectInfo; - SOCKET_STATE OldState; - ULONG LingerWait; - ULONG SendsInProgress; - ULONG SleepWait; - BOOLEAN ActiveConnect; - - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* If a Close is already in Process... */ - if (Socket->SharedData.State == SocketClosed) - { - /* Release lock and fail */ - LeaveCriticalSection(&Socket->Lock); - return WSAENOTSOCK; - } - - /* Save the old state and set the new one to closed */ - OldState = Socket->SharedData.State; - Socket->SharedData.State = SocketClosed; - - /* Check if the socket has an active async data */ - ActiveConnect = (Socket->AsyncData != NULL); - - /* We're done with the socket, release the lock */ - LeaveCriticalSection(&Socket->Lock); - - /* - * If SO_LINGER is ON and the Socket was connected or had an active async - * connect context, then we'll disconnect it. Note that we won't do this - * for connection-less (UDP/RAW) sockets or if a send shutdown is active. - */ - if ((OldState == SocketConnected || ActiveConnect) && - !(Socket->SharedData.SendShutdown) && - !MSAFD_IS_DGRAM_SOCK(Socket) && - (Socket->SharedData.LingerData.l_onoff)) - { - /* We need to respect the timeout */ - SleepWait = 100; - LingerWait = Socket->SharedData.LingerData.l_linger * 1000; - - /* Loop until no more sends are pending, within the timeout */ - while (LingerWait) - { - /* Find out how many Sends are in Progress */ - if (SockGetInformation(Socket, - AFD_INFO_SENDS_IN_PROGRESS, - NULL, - 0, - NULL, - &SendsInProgress, - NULL)) - { - /* Bail out if anything but NO_ERROR */ - LingerWait = 0; - break; - } - - /* Bail out if no more sends are pending */ - if (!SendsInProgress) break; - - /* - * We have to execute a sleep, so it's kind of like - * a block. If the socket is Nonblock, we cannot - * go on since asyncronous operation is expected - * and we cannot offer it - */ - if (Socket->SharedData.NonBlocking) - { - /* Acquire the socket lock */ - EnterCriticalSection(&Socket->Lock); - - /* Restore the socket state */ - Socket->SharedData.State = OldState; - - /* Release the lock again */ - LeaveCriticalSection(&Socket->Lock); - - /* Fail with error code */ - return WSAEWOULDBLOCK; - } - - /* Now we can sleep, and decrement the linger wait */ - /* - * FIXME: It seems Windows does some funky acceleration - * since the waiting seems to be longer and longer. I - * don't think this improves performance so much, so we - * wait a fixed time instead. - */ - Sleep(SleepWait); - LingerWait -= SleepWait; - } - - /* - * We have reached the timeout or sends are over. - * Disconnect if the timeout has been reached. - */ - if (LingerWait <= 0) - { - /* There is no timeout, and this is an abortive disconnect */ - DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(0); - DisconnectInfo.DisconnectType = AFD_DISCONNECT_ABORT; - - /* Send IOCTL */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_DISCONNECT, - &DisconnectInfo, - sizeof(DisconnectInfo), - NULL, - 0); - /* Check if the operation is pending */ - if (Status == STATUS_PENDING) - { - /* Wait for completion */ - SockWaitForSingleObject(ThreadData->EventHandle, - Socket->Handle, - !Socket->SharedData.LingerData.l_onoff ? - NO_BLOCKING_HOOK : ALWAYS_BLOCKING_HOOK, - NO_TIMEOUT); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* We actually accept errors, unless the driver wasn't ready */ - if (Status == STATUS_DEVICE_NOT_READY) - { - /* This is the equivalent of a WOULDBLOCK, which we fail */ - /* Acquire the socket lock */ - EnterCriticalSection(&Socket->Lock); - - /* Restore the socket state */ - Socket->SharedData.State = OldState; - - /* Release the lock again */ - LeaveCriticalSection(&Socket->Lock); - - /* Fail with error code */ - return WSAEWOULDBLOCK; - } - } - } - - /* Acquire the global lock to protect the handle table */ - SockAcquireRwLockShared(&SocketGlobalLock); - - /* Protect the socket too */ - EnterCriticalSection(&Socket->Lock); - - /* Notify the Helper DLL of Socket Closure */ - ErrorCode = SockNotifyHelperDll(Socket, WSH_NOTIFY_CLOSE); - - /* Cleanup Time! */ - Socket->HelperContext = NULL; - Socket->SharedData.AsyncDisabledEvents = -1; - if (Socket->TdiAddressHandle) - { - /* Close and forget the handle */ - NtClose(Socket->TdiAddressHandle); - Socket->TdiAddressHandle = NULL; - } - if (Socket->TdiConnectionHandle) - { - /* Close and forget the handle */ - NtClose(Socket->TdiConnectionHandle); - Socket->TdiConnectionHandle = NULL; - } - - /* Remove the handle from the table */ - ErrorCode = WahRemoveHandleContext(SockContextTable, &Socket->WshContext); - if (ErrorCode == NO_ERROR) - { - /* Close the socket's handle */ - NtClose(Socket->WshContext.Handle); - - /* Dereference the socket */ - SockDereferenceSocket(Socket); - } - else - { - /* This isn't a socket anymore, or something */ - ErrorCode = WSAENOTSOCK; - } - - /* Release both locks */ - LeaveCriticalSection(&Socket->Lock); - SockReleaseRwLockShared(&SocketGlobalLock); - - /* Return success */ - return ErrorCode; -} - -SOCKET -WSPAPI -WSPSocket(INT AddressFamily, - INT SocketType, - INT Protocol, - LPWSAPROTOCOL_INFOW lpProtocolInfo, - GROUP g, - DWORD dwFlags, - LPINT lpErrno) -{ - DWORD CatalogId; - SOCKET Handle = INVALID_SOCKET; - INT ErrorCode; - DWORD ServiceFlags, ProviderFlags; - PWINSOCK_TEB_DATA ThreadData; - PSOCKET_INFORMATION Socket; - GUID ProviderId; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return INVALID_SOCKET; - } - - /* Get the catalog ID */ - CatalogId = lpProtocolInfo->dwCatalogEntryId; - - /* Check if this is a duplication */ - if(lpProtocolInfo->dwProviderReserved) - { - /* Get the duplicate handle */ - Handle = (SOCKET)lpProtocolInfo->dwProviderReserved; - - /* Get our structure for it */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if(Socket) - { - /* Tell Winsock about it */ - Socket->Handle = SockUpcallTable->lpWPUModifyIFSHandle(CatalogId, - Handle, - &ErrorCode); - /* Check if we got an invalid handle back */ - if(Socket->Handle == INVALID_SOCKET) - { - /* Restore it for the error path */ - Socket->Handle = Handle; - } - } - else - { - /* The duplicate handle is invalid */ - ErrorCode = WSAEINVAL; - } - - /* Fail */ - goto error; - } - - /* See if the address family should be recovered from the protocl info */ - if (!AddressFamily || AddressFamily == FROM_PROTOCOL_INFO) - { - /* Use protocol info data */ - AddressFamily = lpProtocolInfo->iAddressFamily; - } - - /* See if the address family should be recovered from the protocl info */ - if(!SocketType || SocketType == FROM_PROTOCOL_INFO ) - { - /* Use protocol info data */ - SocketType = lpProtocolInfo->iSocketType; - } - - /* See if the address family should be recovered from the protocl info */ - if(Protocol == FROM_PROTOCOL_INFO) - { - /* Use protocol info data */ - Protocol = lpProtocolInfo->iProtocol; - } - - /* Save the service, provider flags and provider ID */ - ServiceFlags = lpProtocolInfo->dwServiceFlags1; - ProviderFlags = lpProtocolInfo->dwProviderFlags; - ProviderId = lpProtocolInfo->ProviderId; - - /* Create the actual socket */ - ErrorCode = SockSocket(AddressFamily, - SocketType, - Protocol, - &ProviderId, - g, - dwFlags, - ProviderFlags, - ServiceFlags, - CatalogId, - &Socket); - if (ErrorCode == ERROR_SUCCESS) - { - /* Acquire the socket lock */ - EnterCriticalSection(&Socket->Lock); - - /* Set status to opened */ - Socket->SharedData.State = SocketOpen; - - /* Create the Socket Context */ - ErrorCode = SockSetHandleContext(Socket); - if (ErrorCode != NO_ERROR) - { - /* Release the lock, close the socket and fail */ - LeaveCriticalSection(&Socket->Lock); - SockCloseSocket(Socket); - goto error; - } - - /* Notify Winsock */ - Handle = SockUpcallTable->lpWPUModifyIFSHandle(Socket->SharedData.CatalogEntryId, - (SOCKET)Socket->WshContext.Handle, - &ErrorCode); - - /* Does Winsock not like it? */ - if (Handle == INVALID_SOCKET) - { - /* Release the lock, close the socket and fail */ - LeaveCriticalSection(&Socket->Lock); - SockCloseSocket(Socket); - goto error; - } - - /* Release the lock */ - LeaveCriticalSection(&Socket->Lock); - } - -error: - /* Write return code */ - *lpErrno = ErrorCode; - - /* Check if we have a socket and dereference it */ - if (Socket) SockDereferenceSocket(Socket); - - /* Return handle */ - return Handle; -} - -INT -WSPAPI -WSPCloseSocket(IN SOCKET Handle, - OUT LPINT lpErrno) -{ - INT ErrorCode; - PSOCKET_INFORMATION Socket; - PWINSOCK_TEB_DATA ThreadData; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - *lpErrno = WSAENOTSOCK; - return SOCKET_ERROR; - } - - /* Close it */ - ErrorCode = SockCloseSocket(Socket); - - /* Remove the final reference */ - SockDereferenceSocket(Socket); - - /* Check if we got here by error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - diff --git a/dll/win32/mswsock/msafd/sockopt.c b/dll/win32/mswsock/msafd/sockopt.c index b2692ffbc8a..e99f2d2e84c 100644 --- a/dll/win32/mswsock/msafd/sockopt.c +++ b/dll/win32/mswsock/msafd/sockopt.c @@ -587,1770 +587,3 @@ error: return NO_ERROR; } -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -DWORD SockSendBufferWindow; -DWORD SockReceiveBufferWindow; - -/* FUNCTIONS *****************************************************************/ - -INT -WSPAPI -SockUpdateWindowSizes(IN PSOCKET_INFORMATION Socket, - IN BOOLEAN Force) -{ - INT ErrorCode; - - /* Check if this is a connection-less socket */ - if (Socket->SharedData.ServiceFlags1 & XP1_CONNECTIONLESS) - { - /* It must be bound */ - if (Socket->SharedData.State == SocketOpen) return NO_ERROR; - } - else - { - /* It must be connected */ - if (Socket->SharedData.State == SocketConnected) return NO_ERROR; - - /* Get the TDI handles for it */ - ErrorCode = SockGetTdiHandles(Socket); - if (ErrorCode != NO_ERROR) return ErrorCode; - - /* Tell WSH the new size */ - ErrorCode = Socket->HelperData->WSHSetSocketInformation(Socket->HelperContext, - Socket->Handle, - Socket->TdiAddressHandle, - Socket->TdiConnectionHandle, - SOL_SOCKET, - SO_RCVBUF, - (PVOID)&Socket->SharedData.SizeOfRecvBuffer, - sizeof(DWORD)); - } - - /* Check if the buffer changed, or if this is a force */ - if ((Socket->SharedData.SizeOfRecvBuffer != SockReceiveBufferWindow) || - (Force)) - { - /* Set the information in AFD */ - ErrorCode = SockSetInformation(Socket, - AFD_INFO_RECEIVE_WINDOW_SIZE, - NULL, - &Socket->SharedData.SizeOfRecvBuffer, - NULL); - if (ErrorCode != NO_ERROR) return ErrorCode; - } - - /* Do the same thing for the send buffer */ - if ((Socket->SharedData.SizeOfSendBuffer != SockSendBufferWindow) || - (Force)) - { - /* Set the information in AFD */ - ErrorCode = SockSetInformation(Socket, - AFD_INFO_SEND_WINDOW_SIZE, - NULL, - &Socket->SharedData.SizeOfSendBuffer, - NULL); - if (ErrorCode != NO_ERROR) return ErrorCode; - } - - /* Return to caller */ - return NO_ERROR; -} - -BOOLEAN -WSPAPI -IsValidOptionForSocket(IN PSOCKET_INFORMATION Socket, - IN INT Level, - IN INT OptionName) -{ - /* SOL_INTERNAL is always illegal when external, of course */ - if (Level == SOL_INTERNAL) return FALSE; - - /* Anything else but SOL_SOCKET we can't handle, so assume it's legal */ - if (Level != SOL_SOCKET) return TRUE; - - /* Check the option name */ - switch (OptionName) - { - case SO_DONTLINGER: - case SO_KEEPALIVE: - case SO_LINGER: - case SO_OOBINLINE: - case SO_ACCEPTCONN: - /* Only valid on stream sockets */ - if (MSAFD_IS_DGRAM_SOCK(Socket)) return FALSE; - - /* It is one, suceed */ - return TRUE; - - case SO_BROADCAST: - /* Only valid on datagram sockets */ - if (MSAFD_IS_DGRAM_SOCK(Socket)) return TRUE; - - /* It isn't one, fail */ - return FALSE; - - case SO_PROTOCOL_INFOA: - /* Winsock 2 has a hack for this, we should get the W version */ - return FALSE; - - default: - /* Anything else is always valid */ - return TRUE; - } -} - -INT -WSPAPI -SockGetConnectData(IN PSOCKET_INFORMATION Socket, - IN ULONG Ioctl, - IN PVOID Buffer, - IN ULONG BufferLength, - OUT PULONG BufferReturned) -{ - PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; - NTSTATUS Status; - IO_STATUS_BLOCK IoStatusBlock; - AFD_PENDING_ACCEPT_DATA ConnectData; - - /* Make sure we have Accept Info in the TEB for this Socket */ - if ((ThreadData->AcceptData) && - (ThreadData->AcceptData->ListenHandle == Socket->WshContext.Handle)) - { - /* Set the connect data structure */ - ConnectData.SequenceNumber = ThreadData->AcceptData->SequenceNumber; - ConnectData.ReturnSize = FALSE; - - /* Send it to AFD */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - 0, - &IoStatusBlock, - Ioctl, - &ConnectData, - sizeof(ConnectData), - Buffer, - BufferLength); - } - else - { - /* Request it from AFD */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - 0, - &IoStatusBlock, - Ioctl, - NULL, - 0, - Buffer, - BufferLength); - } - - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion */ - SockWaitForSingleObject(ThreadData->EventHandle, - Socket->Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - return NtStatusToSocketError(Status); - } - - /* Return the length */ - if (BufferReturned) *BufferReturned = PtrToUlong(IoStatusBlock.Information); - - /* Return success */ - return NO_ERROR; -} - -INT -WSPAPI -WSPIoctl(IN SOCKET Handle, - IN DWORD dwIoControlCode, - IN LPVOID lpvInBuffer, - IN DWORD cbInBuffer, - OUT LPVOID lpvOutBuffer, - IN DWORD cbOutBuffer, - OUT LPDWORD lpcbBytesReturned, - IN LPWSAOVERLAPPED lpOverlapped, - IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, - IN LPWSATHREADID lpThreadId, - OUT LPINT lpErrno) -{ - PSOCKET_INFORMATION Socket; - INT ErrorCode; - PWINSOCK_TEB_DATA ThreadData; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - switch(dwIoControlCode) { - - case FIONBIO: - - /* Check if the Buffer is OK */ - if(cbInBuffer < sizeof(ULONG)) - { - /* Fail */ - ErrorCode = WSAEFAULT; - goto error; - } - - return 0; - - default: - - /* Unsupported for now */ - *lpErrno = WSAEINVAL; - return SOCKET_ERROR; - } - -error: - /* Check if we had a socket */ - if (Socket) - { - /* Release lock and dereference it */ - LeaveCriticalSection(&Socket->Lock); - SockDereferenceSocket(Socket); - } - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Return error */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return to caller */ - return NO_ERROR; -} - - -INT -WSPAPI -WSPGetSockOpt(IN SOCKET Handle, - IN INT Level, - IN INT OptionName, - OUT CHAR FAR* OptionValue, - IN OUT LPINT OptionLength, - OUT LPINT lpErrno) -{ - PSOCKET_INFORMATION Socket; - INT ErrorCode; - PWINSOCK_TEB_DATA ThreadData; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - *lpErrno = WSAENOTSOCK; - return SOCKET_ERROR; - } - - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* Make sure we're not closed */ - if (Socket->SharedData.State == SocketClosed) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Validate the pointer and length */ - if (!(OptionValue) || - !(OptionLength) || - (*OptionLength < sizeof(CHAR)) || - (*OptionLength & 0x80000000)) - { - /* Fail */ - ErrorCode = WSAEFAULT; - goto error; - } - - /* Validate option */ - if (!IsValidOptionForSocket(Socket, Level, OptionName)) - { - /* Fail */ - ErrorCode = WSAENOPROTOOPT; - goto error; - } - - /* If it's one of the recognized options */ - if (Level == SOL_SOCKET && - (OptionName == SO_BROADCAST || - OptionName == SO_DEBUG || - OptionName == SO_DONTLINGER || - OptionName == SO_LINGER || - OptionName == SO_OOBINLINE || - OptionName == SO_RCVBUF || - OptionName == SO_REUSEADDR || - OptionName == SO_EXCLUSIVEADDRUSE || - OptionName == SO_CONDITIONAL_ACCEPT || - OptionName == SO_SNDBUF || - OptionName == SO_TYPE || - OptionName == SO_ACCEPTCONN || - OptionName == SO_ERROR)) - { - /* Clear the buffer first */ - RtlZeroMemory(OptionValue, *OptionLength); - } - - - /* Check the Level first */ - switch (Level) - { - /* Handle SOL_SOCKET */ - case SOL_SOCKET: - - /* Now check the Option */ - switch (OptionName) - { - case SO_TYPE: - - /* Validate the size */ - if (*OptionLength < sizeof(INT)) - { - /* Size is too small, fail */ - ErrorCode = WSAEFAULT; - goto error; - } - - /* Return the data */ - *OptionValue = Socket->SharedData.SocketType; - *OptionLength = sizeof(INT); - break; - - case SO_RCVBUF: - - /* Validate the size */ - if (*OptionLength < sizeof(INT)) - { - /* Size is too small, fail */ - ErrorCode = WSAEFAULT; - goto error; - } - - /* Return the data */ - *(PINT)OptionValue = Socket->SharedData.SizeOfRecvBuffer; - *OptionLength = sizeof(INT); - break; - - case SO_SNDBUF: - - /* Validate the size */ - if (*OptionLength < sizeof(INT)) - { - /* Size is too small, fail */ - ErrorCode = WSAEFAULT; - goto error; - } - - /* Return the data */ - *(PINT)OptionValue = Socket->SharedData.SizeOfSendBuffer; - *OptionLength = sizeof(INT); - break; - - case SO_ACCEPTCONN: - - /* Return the data */ - *OptionValue = Socket->SharedData.Listening; - *OptionLength = sizeof(BOOLEAN); - break; - - case SO_BROADCAST: - - /* Return the data */ - *OptionValue = Socket->SharedData.Broadcast; - *OptionLength = sizeof(BOOLEAN); - break; - - case SO_DEBUG: - - /* Return the data */ - *OptionValue = Socket->SharedData.Debug; - *OptionLength = sizeof(BOOLEAN); - break; - - case SO_CONDITIONAL_ACCEPT: - case SO_DONTLINGER: - case SO_DONTROUTE: - case SO_ERROR: - case SO_GROUP_ID: - case SO_GROUP_PRIORITY: - case SO_KEEPALIVE: - case SO_LINGER: - case SO_MAX_MSG_SIZE: - case SO_OOBINLINE: - case SO_PROTOCOL_INFO: - case SO_REUSEADDR: - - /* Unsupported */ - - default: - - /* Unsupported by us, give it to the helper */ - ErrorCode = SockGetTdiHandles(Socket); - if (ErrorCode != NO_ERROR) goto error; - - /* Call the helper */ - ErrorCode = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, - Handle, - Socket->TdiAddressHandle, - Socket->TdiConnectionHandle, - Level, - OptionName, - OptionValue, - OptionLength); - if (ErrorCode != NO_ERROR) goto error; - break; - } - - default: - - /* Unsupported by us, give it to the helper */ - ErrorCode = SockGetTdiHandles(Socket); - if (ErrorCode != NO_ERROR) goto error; - - /* Call the helper */ - ErrorCode = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, - Handle, - Socket->TdiAddressHandle, - Socket->TdiConnectionHandle, - Level, - OptionName, - OptionValue, - OptionLength); - if (ErrorCode != NO_ERROR) goto error; - break; - } - -error: - /* Release the lock and dereference the socket */ - LeaveCriticalSection(&Socket->Lock); - SockDereferenceSocket(Socket); - - /* Handle error case */ - if (ErrorCode != NO_ERROR) - { - /* Return error */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - -INT -WSPAPI -WSPSetSockOpt(IN SOCKET Handle, - IN INT Level, - IN INT OptionName, - IN CONST CHAR FAR *OptionValue, - IN INT OptionLength, - OUT LPINT lpErrno) -{ - PSOCKET_INFORMATION Socket; - INT ErrorCode; - PWINSOCK_TEB_DATA ThreadData; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - *lpErrno = WSAENOTSOCK; - return SOCKET_ERROR; - } - - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* Make sure we're not closed */ - if (Socket->SharedData.State == SocketClosed) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Validate the pointer */ - if (!OptionValue) - { - /* Fail */ - ErrorCode = WSAEFAULT; - goto error; - } - - /* Validate option */ - if (!IsValidOptionForSocket(Socket, Level, OptionName)) - { - /* Fail */ - ErrorCode = WSAENOPROTOOPT; - goto error; - } - - /* FIXME: Write code */ - -error: - - /* Check if this is the failure path */ - if (ErrorCode != NO_ERROR) - { - /* Dereference and unlock the socket */ - LeaveCriticalSection(&Socket->Lock); - SockDereferenceSocket(Socket); - - /* Return error */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Update the socket's state in AFD */ - ErrorCode = SockSetHandleContext(Socket); - if (ErrorCode != NO_ERROR) goto error; - - /* Return success */ - return NO_ERROR; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -DWORD SockSendBufferWindow; -DWORD SockReceiveBufferWindow; - -/* FUNCTIONS *****************************************************************/ - -INT -WSPAPI -SockUpdateWindowSizes(IN PSOCKET_INFORMATION Socket, - IN BOOLEAN Force) -{ - INT ErrorCode; - - /* Check if this is a connection-less socket */ - if (Socket->SharedData.ServiceFlags1 & XP1_CONNECTIONLESS) - { - /* It must be bound */ - if (Socket->SharedData.State == SocketOpen) return NO_ERROR; - } - else - { - /* It must be connected */ - if (Socket->SharedData.State == SocketConnected) return NO_ERROR; - - /* Get the TDI handles for it */ - ErrorCode = SockGetTdiHandles(Socket); - if (ErrorCode != NO_ERROR) return ErrorCode; - - /* Tell WSH the new size */ - ErrorCode = Socket->HelperData->WSHSetSocketInformation(Socket->HelperContext, - Socket->Handle, - Socket->TdiAddressHandle, - Socket->TdiConnectionHandle, - SOL_SOCKET, - SO_RCVBUF, - (PVOID)&Socket->SharedData.SizeOfRecvBuffer, - sizeof(DWORD)); - } - - /* Check if the buffer changed, or if this is a force */ - if ((Socket->SharedData.SizeOfRecvBuffer != SockReceiveBufferWindow) || - (Force)) - { - /* Set the information in AFD */ - ErrorCode = SockSetInformation(Socket, - AFD_INFO_RECEIVE_WINDOW_SIZE, - NULL, - &Socket->SharedData.SizeOfRecvBuffer, - NULL); - if (ErrorCode != NO_ERROR) return ErrorCode; - } - - /* Do the same thing for the send buffer */ - if ((Socket->SharedData.SizeOfSendBuffer != SockSendBufferWindow) || - (Force)) - { - /* Set the information in AFD */ - ErrorCode = SockSetInformation(Socket, - AFD_INFO_SEND_WINDOW_SIZE, - NULL, - &Socket->SharedData.SizeOfSendBuffer, - NULL); - if (ErrorCode != NO_ERROR) return ErrorCode; - } - - /* Return to caller */ - return NO_ERROR; -} - -BOOLEAN -WSPAPI -IsValidOptionForSocket(IN PSOCKET_INFORMATION Socket, - IN INT Level, - IN INT OptionName) -{ - /* SOL_INTERNAL is always illegal when external, of course */ - if (Level == SOL_INTERNAL) return FALSE; - - /* Anything else but SOL_SOCKET we can't handle, so assume it's legal */ - if (Level != SOL_SOCKET) return TRUE; - - /* Check the option name */ - switch (OptionName) - { - case SO_DONTLINGER: - case SO_KEEPALIVE: - case SO_LINGER: - case SO_OOBINLINE: - case SO_ACCEPTCONN: - /* Only valid on stream sockets */ - if (MSAFD_IS_DGRAM_SOCK(Socket)) return FALSE; - - /* It is one, suceed */ - return TRUE; - - case SO_BROADCAST: - /* Only valid on datagram sockets */ - if (MSAFD_IS_DGRAM_SOCK(Socket)) return TRUE; - - /* It isn't one, fail */ - return FALSE; - - case SO_PROTOCOL_INFOA: - /* Winsock 2 has a hack for this, we should get the W version */ - return FALSE; - - default: - /* Anything else is always valid */ - return TRUE; - } -} - -INT -WSPAPI -SockGetConnectData(IN PSOCKET_INFORMATION Socket, - IN ULONG Ioctl, - IN PVOID Buffer, - IN ULONG BufferLength, - OUT PULONG BufferReturned) -{ - PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; - NTSTATUS Status; - IO_STATUS_BLOCK IoStatusBlock; - AFD_PENDING_ACCEPT_DATA ConnectData; - - /* Make sure we have Accept Info in the TEB for this Socket */ - if ((ThreadData->AcceptData) && - (ThreadData->AcceptData->ListenHandle == Socket->WshContext.Handle)) - { - /* Set the connect data structure */ - ConnectData.SequenceNumber = ThreadData->AcceptData->SequenceNumber; - ConnectData.ReturnSize = FALSE; - - /* Send it to AFD */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - 0, - &IoStatusBlock, - Ioctl, - &ConnectData, - sizeof(ConnectData), - Buffer, - BufferLength); - } - else - { - /* Request it from AFD */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - 0, - &IoStatusBlock, - Ioctl, - NULL, - 0, - Buffer, - BufferLength); - } - - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion */ - SockWaitForSingleObject(ThreadData->EventHandle, - Socket->Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - return NtStatusToSocketError(Status); - } - - /* Return the length */ - if (BufferReturned) *BufferReturned = PtrToUlong(IoStatusBlock.Information); - - /* Return success */ - return NO_ERROR; -} - -INT -WSPAPI -WSPIoctl(IN SOCKET Handle, - IN DWORD dwIoControlCode, - IN LPVOID lpvInBuffer, - IN DWORD cbInBuffer, - OUT LPVOID lpvOutBuffer, - IN DWORD cbOutBuffer, - OUT LPDWORD lpcbBytesReturned, - IN LPWSAOVERLAPPED lpOverlapped, - IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, - IN LPWSATHREADID lpThreadId, - OUT LPINT lpErrno) -{ - PSOCKET_INFORMATION Socket; - INT ErrorCode; - PWINSOCK_TEB_DATA ThreadData; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - switch(dwIoControlCode) { - - case FIONBIO: - - /* Check if the Buffer is OK */ - if(cbInBuffer < sizeof(ULONG)) - { - /* Fail */ - ErrorCode = WSAEFAULT; - goto error; - } - - return 0; - - default: - - /* Unsupported for now */ - *lpErrno = WSAEINVAL; - return SOCKET_ERROR; - } - -error: - /* Check if we had a socket */ - if (Socket) - { - /* Release lock and dereference it */ - LeaveCriticalSection(&Socket->Lock); - SockDereferenceSocket(Socket); - } - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Return error */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return to caller */ - return NO_ERROR; -} - - -INT -WSPAPI -WSPGetSockOpt(IN SOCKET Handle, - IN INT Level, - IN INT OptionName, - OUT CHAR FAR* OptionValue, - IN OUT LPINT OptionLength, - OUT LPINT lpErrno) -{ - PSOCKET_INFORMATION Socket; - INT ErrorCode; - PWINSOCK_TEB_DATA ThreadData; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - *lpErrno = WSAENOTSOCK; - return SOCKET_ERROR; - } - - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* Make sure we're not closed */ - if (Socket->SharedData.State == SocketClosed) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Validate the pointer and length */ - if (!(OptionValue) || - !(OptionLength) || - (*OptionLength < sizeof(CHAR)) || - (*OptionLength & 0x80000000)) - { - /* Fail */ - ErrorCode = WSAEFAULT; - goto error; - } - - /* Validate option */ - if (!IsValidOptionForSocket(Socket, Level, OptionName)) - { - /* Fail */ - ErrorCode = WSAENOPROTOOPT; - goto error; - } - - /* If it's one of the recognized options */ - if (Level == SOL_SOCKET && - (OptionName == SO_BROADCAST || - OptionName == SO_DEBUG || - OptionName == SO_DONTLINGER || - OptionName == SO_LINGER || - OptionName == SO_OOBINLINE || - OptionName == SO_RCVBUF || - OptionName == SO_REUSEADDR || - OptionName == SO_EXCLUSIVEADDRUSE || - OptionName == SO_CONDITIONAL_ACCEPT || - OptionName == SO_SNDBUF || - OptionName == SO_TYPE || - OptionName == SO_ACCEPTCONN || - OptionName == SO_ERROR)) - { - /* Clear the buffer first */ - RtlZeroMemory(OptionValue, *OptionLength); - } - - - /* Check the Level first */ - switch (Level) - { - /* Handle SOL_SOCKET */ - case SOL_SOCKET: - - /* Now check the Option */ - switch (OptionName) - { - case SO_TYPE: - - /* Validate the size */ - if (*OptionLength < sizeof(INT)) - { - /* Size is too small, fail */ - ErrorCode = WSAEFAULT; - goto error; - } - - /* Return the data */ - *OptionValue = Socket->SharedData.SocketType; - *OptionLength = sizeof(INT); - break; - - case SO_RCVBUF: - - /* Validate the size */ - if (*OptionLength < sizeof(INT)) - { - /* Size is too small, fail */ - ErrorCode = WSAEFAULT; - goto error; - } - - /* Return the data */ - *(PINT)OptionValue = Socket->SharedData.SizeOfRecvBuffer; - *OptionLength = sizeof(INT); - break; - - case SO_SNDBUF: - - /* Validate the size */ - if (*OptionLength < sizeof(INT)) - { - /* Size is too small, fail */ - ErrorCode = WSAEFAULT; - goto error; - } - - /* Return the data */ - *(PINT)OptionValue = Socket->SharedData.SizeOfSendBuffer; - *OptionLength = sizeof(INT); - break; - - case SO_ACCEPTCONN: - - /* Return the data */ - *OptionValue = Socket->SharedData.Listening; - *OptionLength = sizeof(BOOLEAN); - break; - - case SO_BROADCAST: - - /* Return the data */ - *OptionValue = Socket->SharedData.Broadcast; - *OptionLength = sizeof(BOOLEAN); - break; - - case SO_DEBUG: - - /* Return the data */ - *OptionValue = Socket->SharedData.Debug; - *OptionLength = sizeof(BOOLEAN); - break; - - case SO_CONDITIONAL_ACCEPT: - case SO_DONTLINGER: - case SO_DONTROUTE: - case SO_ERROR: - case SO_GROUP_ID: - case SO_GROUP_PRIORITY: - case SO_KEEPALIVE: - case SO_LINGER: - case SO_MAX_MSG_SIZE: - case SO_OOBINLINE: - case SO_PROTOCOL_INFO: - case SO_REUSEADDR: - - /* Unsupported */ - - default: - - /* Unsupported by us, give it to the helper */ - ErrorCode = SockGetTdiHandles(Socket); - if (ErrorCode != NO_ERROR) goto error; - - /* Call the helper */ - ErrorCode = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, - Handle, - Socket->TdiAddressHandle, - Socket->TdiConnectionHandle, - Level, - OptionName, - OptionValue, - OptionLength); - if (ErrorCode != NO_ERROR) goto error; - break; - } - - default: - - /* Unsupported by us, give it to the helper */ - ErrorCode = SockGetTdiHandles(Socket); - if (ErrorCode != NO_ERROR) goto error; - - /* Call the helper */ - ErrorCode = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, - Handle, - Socket->TdiAddressHandle, - Socket->TdiConnectionHandle, - Level, - OptionName, - OptionValue, - OptionLength); - if (ErrorCode != NO_ERROR) goto error; - break; - } - -error: - /* Release the lock and dereference the socket */ - LeaveCriticalSection(&Socket->Lock); - SockDereferenceSocket(Socket); - - /* Handle error case */ - if (ErrorCode != NO_ERROR) - { - /* Return error */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - -INT -WSPAPI -WSPSetSockOpt(IN SOCKET Handle, - IN INT Level, - IN INT OptionName, - IN CONST CHAR FAR *OptionValue, - IN INT OptionLength, - OUT LPINT lpErrno) -{ - PSOCKET_INFORMATION Socket; - INT ErrorCode; - PWINSOCK_TEB_DATA ThreadData; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - *lpErrno = WSAENOTSOCK; - return SOCKET_ERROR; - } - - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* Make sure we're not closed */ - if (Socket->SharedData.State == SocketClosed) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Validate the pointer */ - if (!OptionValue) - { - /* Fail */ - ErrorCode = WSAEFAULT; - goto error; - } - - /* Validate option */ - if (!IsValidOptionForSocket(Socket, Level, OptionName)) - { - /* Fail */ - ErrorCode = WSAENOPROTOOPT; - goto error; - } - - /* FIXME: Write code */ - -error: - - /* Check if this is the failure path */ - if (ErrorCode != NO_ERROR) - { - /* Dereference and unlock the socket */ - LeaveCriticalSection(&Socket->Lock); - SockDereferenceSocket(Socket); - - /* Return error */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Update the socket's state in AFD */ - ErrorCode = SockSetHandleContext(Socket); - if (ErrorCode != NO_ERROR) goto error; - - /* Return success */ - return NO_ERROR; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -DWORD SockSendBufferWindow; -DWORD SockReceiveBufferWindow; - -/* FUNCTIONS *****************************************************************/ - -INT -WSPAPI -SockUpdateWindowSizes(IN PSOCKET_INFORMATION Socket, - IN BOOLEAN Force) -{ - INT ErrorCode; - - /* Check if this is a connection-less socket */ - if (Socket->SharedData.ServiceFlags1 & XP1_CONNECTIONLESS) - { - /* It must be bound */ - if (Socket->SharedData.State == SocketOpen) return NO_ERROR; - } - else - { - /* It must be connected */ - if (Socket->SharedData.State == SocketConnected) return NO_ERROR; - - /* Get the TDI handles for it */ - ErrorCode = SockGetTdiHandles(Socket); - if (ErrorCode != NO_ERROR) return ErrorCode; - - /* Tell WSH the new size */ - ErrorCode = Socket->HelperData->WSHSetSocketInformation(Socket->HelperContext, - Socket->Handle, - Socket->TdiAddressHandle, - Socket->TdiConnectionHandle, - SOL_SOCKET, - SO_RCVBUF, - (PVOID)&Socket->SharedData.SizeOfRecvBuffer, - sizeof(DWORD)); - } - - /* Check if the buffer changed, or if this is a force */ - if ((Socket->SharedData.SizeOfRecvBuffer != SockReceiveBufferWindow) || - (Force)) - { - /* Set the information in AFD */ - ErrorCode = SockSetInformation(Socket, - AFD_INFO_RECEIVE_WINDOW_SIZE, - NULL, - &Socket->SharedData.SizeOfRecvBuffer, - NULL); - if (ErrorCode != NO_ERROR) return ErrorCode; - } - - /* Do the same thing for the send buffer */ - if ((Socket->SharedData.SizeOfSendBuffer != SockSendBufferWindow) || - (Force)) - { - /* Set the information in AFD */ - ErrorCode = SockSetInformation(Socket, - AFD_INFO_SEND_WINDOW_SIZE, - NULL, - &Socket->SharedData.SizeOfSendBuffer, - NULL); - if (ErrorCode != NO_ERROR) return ErrorCode; - } - - /* Return to caller */ - return NO_ERROR; -} - -BOOLEAN -WSPAPI -IsValidOptionForSocket(IN PSOCKET_INFORMATION Socket, - IN INT Level, - IN INT OptionName) -{ - /* SOL_INTERNAL is always illegal when external, of course */ - if (Level == SOL_INTERNAL) return FALSE; - - /* Anything else but SOL_SOCKET we can't handle, so assume it's legal */ - if (Level != SOL_SOCKET) return TRUE; - - /* Check the option name */ - switch (OptionName) - { - case SO_DONTLINGER: - case SO_KEEPALIVE: - case SO_LINGER: - case SO_OOBINLINE: - case SO_ACCEPTCONN: - /* Only valid on stream sockets */ - if (MSAFD_IS_DGRAM_SOCK(Socket)) return FALSE; - - /* It is one, suceed */ - return TRUE; - - case SO_BROADCAST: - /* Only valid on datagram sockets */ - if (MSAFD_IS_DGRAM_SOCK(Socket)) return TRUE; - - /* It isn't one, fail */ - return FALSE; - - case SO_PROTOCOL_INFOA: - /* Winsock 2 has a hack for this, we should get the W version */ - return FALSE; - - default: - /* Anything else is always valid */ - return TRUE; - } -} - -INT -WSPAPI -SockGetConnectData(IN PSOCKET_INFORMATION Socket, - IN ULONG Ioctl, - IN PVOID Buffer, - IN ULONG BufferLength, - OUT PULONG BufferReturned) -{ - PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; - NTSTATUS Status; - IO_STATUS_BLOCK IoStatusBlock; - AFD_PENDING_ACCEPT_DATA ConnectData; - - /* Make sure we have Accept Info in the TEB for this Socket */ - if ((ThreadData->AcceptData) && - (ThreadData->AcceptData->ListenHandle == Socket->WshContext.Handle)) - { - /* Set the connect data structure */ - ConnectData.SequenceNumber = ThreadData->AcceptData->SequenceNumber; - ConnectData.ReturnSize = FALSE; - - /* Send it to AFD */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - 0, - &IoStatusBlock, - Ioctl, - &ConnectData, - sizeof(ConnectData), - Buffer, - BufferLength); - } - else - { - /* Request it from AFD */ - Status = NtDeviceIoControlFile(Socket->WshContext.Handle, - ThreadData->EventHandle, - NULL, - 0, - &IoStatusBlock, - Ioctl, - NULL, - 0, - Buffer, - BufferLength); - } - - /* Check if we need to wait */ - if (Status == STATUS_PENDING) - { - /* Wait for completion */ - SockWaitForSingleObject(ThreadData->EventHandle, - Socket->Handle, - NO_BLOCKING_HOOK, - NO_TIMEOUT); - - /* Get new status */ - Status = IoStatusBlock.Status; - } - - /* Check for error */ - if (!NT_SUCCESS(Status)) - { - /* Fail */ - return NtStatusToSocketError(Status); - } - - /* Return the length */ - if (BufferReturned) *BufferReturned = PtrToUlong(IoStatusBlock.Information); - - /* Return success */ - return NO_ERROR; -} - -INT -WSPAPI -WSPIoctl(IN SOCKET Handle, - IN DWORD dwIoControlCode, - IN LPVOID lpvInBuffer, - IN DWORD cbInBuffer, - OUT LPVOID lpvOutBuffer, - IN DWORD cbOutBuffer, - OUT LPDWORD lpcbBytesReturned, - IN LPWSAOVERLAPPED lpOverlapped, - IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, - IN LPWSATHREADID lpThreadId, - OUT LPINT lpErrno) -{ - PSOCKET_INFORMATION Socket; - INT ErrorCode; - PWINSOCK_TEB_DATA ThreadData; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - switch(dwIoControlCode) { - - case FIONBIO: - - /* Check if the Buffer is OK */ - if(cbInBuffer < sizeof(ULONG)) - { - /* Fail */ - ErrorCode = WSAEFAULT; - goto error; - } - - return 0; - - default: - - /* Unsupported for now */ - *lpErrno = WSAEINVAL; - return SOCKET_ERROR; - } - -error: - /* Check if we had a socket */ - if (Socket) - { - /* Release lock and dereference it */ - LeaveCriticalSection(&Socket->Lock); - SockDereferenceSocket(Socket); - } - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Return error */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return to caller */ - return NO_ERROR; -} - - -INT -WSPAPI -WSPGetSockOpt(IN SOCKET Handle, - IN INT Level, - IN INT OptionName, - OUT CHAR FAR* OptionValue, - IN OUT LPINT OptionLength, - OUT LPINT lpErrno) -{ - PSOCKET_INFORMATION Socket; - INT ErrorCode; - PWINSOCK_TEB_DATA ThreadData; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - *lpErrno = WSAENOTSOCK; - return SOCKET_ERROR; - } - - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* Make sure we're not closed */ - if (Socket->SharedData.State == SocketClosed) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Validate the pointer and length */ - if (!(OptionValue) || - !(OptionLength) || - (*OptionLength < sizeof(CHAR)) || - (*OptionLength & 0x80000000)) - { - /* Fail */ - ErrorCode = WSAEFAULT; - goto error; - } - - /* Validate option */ - if (!IsValidOptionForSocket(Socket, Level, OptionName)) - { - /* Fail */ - ErrorCode = WSAENOPROTOOPT; - goto error; - } - - /* If it's one of the recognized options */ - if (Level == SOL_SOCKET && - (OptionName == SO_BROADCAST || - OptionName == SO_DEBUG || - OptionName == SO_DONTLINGER || - OptionName == SO_LINGER || - OptionName == SO_OOBINLINE || - OptionName == SO_RCVBUF || - OptionName == SO_REUSEADDR || - OptionName == SO_EXCLUSIVEADDRUSE || - OptionName == SO_CONDITIONAL_ACCEPT || - OptionName == SO_SNDBUF || - OptionName == SO_TYPE || - OptionName == SO_ACCEPTCONN || - OptionName == SO_ERROR)) - { - /* Clear the buffer first */ - RtlZeroMemory(OptionValue, *OptionLength); - } - - - /* Check the Level first */ - switch (Level) - { - /* Handle SOL_SOCKET */ - case SOL_SOCKET: - - /* Now check the Option */ - switch (OptionName) - { - case SO_TYPE: - - /* Validate the size */ - if (*OptionLength < sizeof(INT)) - { - /* Size is too small, fail */ - ErrorCode = WSAEFAULT; - goto error; - } - - /* Return the data */ - *OptionValue = Socket->SharedData.SocketType; - *OptionLength = sizeof(INT); - break; - - case SO_RCVBUF: - - /* Validate the size */ - if (*OptionLength < sizeof(INT)) - { - /* Size is too small, fail */ - ErrorCode = WSAEFAULT; - goto error; - } - - /* Return the data */ - *(PINT)OptionValue = Socket->SharedData.SizeOfRecvBuffer; - *OptionLength = sizeof(INT); - break; - - case SO_SNDBUF: - - /* Validate the size */ - if (*OptionLength < sizeof(INT)) - { - /* Size is too small, fail */ - ErrorCode = WSAEFAULT; - goto error; - } - - /* Return the data */ - *(PINT)OptionValue = Socket->SharedData.SizeOfSendBuffer; - *OptionLength = sizeof(INT); - break; - - case SO_ACCEPTCONN: - - /* Return the data */ - *OptionValue = Socket->SharedData.Listening; - *OptionLength = sizeof(BOOLEAN); - break; - - case SO_BROADCAST: - - /* Return the data */ - *OptionValue = Socket->SharedData.Broadcast; - *OptionLength = sizeof(BOOLEAN); - break; - - case SO_DEBUG: - - /* Return the data */ - *OptionValue = Socket->SharedData.Debug; - *OptionLength = sizeof(BOOLEAN); - break; - - case SO_CONDITIONAL_ACCEPT: - case SO_DONTLINGER: - case SO_DONTROUTE: - case SO_ERROR: - case SO_GROUP_ID: - case SO_GROUP_PRIORITY: - case SO_KEEPALIVE: - case SO_LINGER: - case SO_MAX_MSG_SIZE: - case SO_OOBINLINE: - case SO_PROTOCOL_INFO: - case SO_REUSEADDR: - - /* Unsupported */ - - default: - - /* Unsupported by us, give it to the helper */ - ErrorCode = SockGetTdiHandles(Socket); - if (ErrorCode != NO_ERROR) goto error; - - /* Call the helper */ - ErrorCode = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, - Handle, - Socket->TdiAddressHandle, - Socket->TdiConnectionHandle, - Level, - OptionName, - OptionValue, - OptionLength); - if (ErrorCode != NO_ERROR) goto error; - break; - } - - default: - - /* Unsupported by us, give it to the helper */ - ErrorCode = SockGetTdiHandles(Socket); - if (ErrorCode != NO_ERROR) goto error; - - /* Call the helper */ - ErrorCode = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, - Handle, - Socket->TdiAddressHandle, - Socket->TdiConnectionHandle, - Level, - OptionName, - OptionValue, - OptionLength); - if (ErrorCode != NO_ERROR) goto error; - break; - } - -error: - /* Release the lock and dereference the socket */ - LeaveCriticalSection(&Socket->Lock); - SockDereferenceSocket(Socket); - - /* Handle error case */ - if (ErrorCode != NO_ERROR) - { - /* Return error */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Return success */ - return NO_ERROR; -} - -INT -WSPAPI -WSPSetSockOpt(IN SOCKET Handle, - IN INT Level, - IN INT OptionName, - IN CONST CHAR FAR *OptionValue, - IN INT OptionLength, - OUT LPINT lpErrno) -{ - PSOCKET_INFORMATION Socket; - INT ErrorCode; - PWINSOCK_TEB_DATA ThreadData; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Get the socket structure */ - Socket = SockFindAndReferenceSocket(Handle, TRUE); - if (!Socket) - { - /* Fail */ - *lpErrno = WSAENOTSOCK; - return SOCKET_ERROR; - } - - /* Lock the socket */ - EnterCriticalSection(&Socket->Lock); - - /* Make sure we're not closed */ - if (Socket->SharedData.State == SocketClosed) - { - /* Fail */ - ErrorCode = WSAENOTSOCK; - goto error; - } - - /* Validate the pointer */ - if (!OptionValue) - { - /* Fail */ - ErrorCode = WSAEFAULT; - goto error; - } - - /* Validate option */ - if (!IsValidOptionForSocket(Socket, Level, OptionName)) - { - /* Fail */ - ErrorCode = WSAENOPROTOOPT; - goto error; - } - - /* FIXME: Write code */ - -error: - - /* Check if this is the failure path */ - if (ErrorCode != NO_ERROR) - { - /* Dereference and unlock the socket */ - LeaveCriticalSection(&Socket->Lock); - SockDereferenceSocket(Socket); - - /* Return error */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Update the socket's state in AFD */ - ErrorCode = SockSetHandleContext(Socket); - if (ErrorCode != NO_ERROR) goto error; - - /* Return success */ - return NO_ERROR; -} - diff --git a/dll/win32/mswsock/msafd/spi.c b/dll/win32/mswsock/msafd/spi.c index eadc7194da5..07093fd35bb 100644 --- a/dll/win32/mswsock/msafd/spi.c +++ b/dll/win32/mswsock/msafd/spi.c @@ -219,666 +219,3 @@ WSPCleanup(OUT LPINT lpErrno) return 0; } -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -PVOID pfnIcfOpenPort; -PICF_CONNECT pfnIcfConnect; -PVOID pfnIcfDisconnect; -HINSTANCE IcfDllHandle; - -WSPPROC_TABLE SockProcTable = -{ - &WSPAccept, - &WSPAddressToString, - &WSPAsyncSelect, - &WSPBind, - &WSPCancelBlockingCall, - &WSPCleanup, - &WSPCloseSocket, - &WSPConnect, - &WSPDuplicateSocket, - &WSPEnumNetworkEvents, - &WSPEventSelect, - &WSPGetOverlappedResult, - &WSPGetPeerName, - &WSPGetSockName, - &WSPGetSockOpt, - &WSPGetQOSByName, - &WSPIoctl, - &WSPJoinLeaf, - &WSPListen, - &WSPRecv, - &WSPRecvDisconnect, - &WSPRecvFrom, - &WSPSelect, - &WSPSend, - &WSPSendDisconnect, - &WSPSendTo, - &WSPSetSockOpt, - &WSPShutdown, - &WSPSocket, - &WSPStringToAddress -}; - -LONG SockWspStartupCount; -WSPUPCALLTABLE SockUpcallTableHack; -LPWSPUPCALLTABLE SockUpcallTable; - -/* FUNCTIONS *****************************************************************/ - -VOID -WSPAPI -NewIcfConnection(IN PSOCK_ICF_DATA IcfData) -{ - /* Load the ICF DLL */ - IcfData->DllHandle = LoadLibraryW(L"hhnetcfg.dll"); - if (IcfData->DllHandle) - { - /* Get the entrypoints */ - IcfData->IcfOpenDynamicFwPort = GetProcAddress(IcfData->DllHandle, - "IcfOpenDynamicFwPort"); - IcfData->IcfConnect = (PICF_CONNECT)GetProcAddress(IcfData->DllHandle, - "IcfConnect"); - IcfData->IcfDisconnect = GetProcAddress(IcfData->DllHandle, - "IcfDisconnect"); - - /* Now call IcfConnect */ - if (!IcfData->IcfConnect(IcfData)) - { - /* We failed, release the library */ - FreeLibrary(IcfData->DllHandle); - } - } -} - -VOID -WSPAPI -InitializeIcfConnection(IN PSOCK_ICF_DATA IcfData) -{ - /* Make sure we have an ICF Handle */ - if (IcfData->IcfHandle) - { - /* Save the function pointers and dll handle */ - IcfDllHandle = IcfData->DllHandle; - pfnIcfOpenPort = IcfData->IcfOpenDynamicFwPort; - pfnIcfConnect = IcfData->IcfConnect; - pfnIcfDisconnect = IcfData->IcfDisconnect; - } -} - -VOID -WSPAPI -CloseIcfConnection(IN PSOCK_ICF_DATA IcfData) -{ - /* Make sure we have an ICF Handle */ - if (IcfData->IcfHandle) - { - /* Call IcfDisconnect */ - IcfData->IcfConnect(IcfData); - - /* Release the library */ - FreeLibrary(IcfData->DllHandle); - } -} - -INT -WSPAPI -WSPStartup(IN WORD wVersionRequested, - OUT LPWSPDATA lpWSPData, - IN LPWSAPROTOCOL_INFOW lpProtocolInfo, - IN WSPUPCALLTABLE UpcallTable, - OUT LPWSPPROC_TABLE lpProcTable) -{ - CHAR DllPath[MAX_PATH]; - HINSTANCE DllHandle; - SOCK_ICF_DATA IcfData; - NT_PRODUCT_TYPE ProductType; - - /* Call the generic mswsock initialization routine */ - if (!MSWSOCK_Initialize()) return WSAENOBUFS; - - /* Check if we have TEB data yet */ - if (!NtCurrentTeb()->WinSockData) - { - /* We don't have thread data yet, initialize it */ - if (!MSAFD_SockThreadInitialize()) return WSAENOBUFS; - } - - /* Check the version number */ - if (wVersionRequested != MAKEWORD(2,2)) return WSAVERNOTSUPPORTED; - - /* Get ICF entrypoints */ - NewIcfConnection(&IcfData); - - /* Acquire the global lock */ - SockAcquireRwLockExclusive(&SocketGlobalLock); - - /* Check if we've never initialized before */ - if (!SockWspStartupCount) - { - /* Check if we have a context table by now */ - if (!SockContextTable) - { - /* Create it */ - if (WahCreateHandleContextTable(&SockContextTable) != NO_ERROR) - { - /* Fail */ - SockReleaseRwLockExclusive(&SocketGlobalLock); - CloseIcfConnection(&IcfData); - return WSASYSCALLFAILURE; - } - } - - /* Bias our load count so we won't be killed with pending APCs */ - GetModuleFileNameA(SockModuleHandle, DllPath, MAX_PATH); - DllHandle = LoadLibraryA(DllPath); - if (!DllHandle) - { - /* Weird error, release and return */ - SockReleaseRwLockExclusive(&SocketGlobalLock); - CloseIcfConnection(&IcfData); - return WSASYSCALLFAILURE; - } - - /* Initialize ICF */ - InitializeIcfConnection(&IcfData); - - /* Set our Upcall Table */ - SockUpcallTableHack = UpcallTable; - SockUpcallTable = &SockUpcallTableHack; - } - - /* Increase startup count */ - SockWspStartupCount++; - - /* Return our version */ - lpWSPData->wVersion = MAKEWORD(2, 2); - lpWSPData->wHighVersion = MAKEWORD(2, 2); - wcscpy(lpWSPData->szDescription, L"Microsoft Windows Sockets Version 2."); - - /* Return our Internal Table */ - *lpProcTable = SockProcTable; - - /* Check if this is a SAN GUID */ - if (IsEqualGUID(&lpProtocolInfo->ProviderId, &SockTcpProviderInfo.ProviderId)) - { - /* Get the product type and check if this is a server OS */ - RtlGetNtProductType(&ProductType); - if (ProductType != NtProductWinNt) - { - /* Get the SAN TCP/IP Catalog ID */ - /* FIXME: SockSanGetTcpipCatalogId(); */ - - /* Initialize SAN if it's enabled */ - if (SockSanEnabled) SockSanInitialize(); - } - } - - /* Release the lock and return */ - SockReleaseRwLockExclusive(&SocketGlobalLock); - - /* Return to caller */ - return NO_ERROR; -} - -INT -WSPAPI -WSPCleanup(OUT LPINT lpErrno) -{ - /* FIXME: Clean up */ - *lpErrno = NO_ERROR; - return 0; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -PVOID pfnIcfOpenPort; -PICF_CONNECT pfnIcfConnect; -PVOID pfnIcfDisconnect; -HINSTANCE IcfDllHandle; - -WSPPROC_TABLE SockProcTable = -{ - &WSPAccept, - &WSPAddressToString, - &WSPAsyncSelect, - &WSPBind, - &WSPCancelBlockingCall, - &WSPCleanup, - &WSPCloseSocket, - &WSPConnect, - &WSPDuplicateSocket, - &WSPEnumNetworkEvents, - &WSPEventSelect, - &WSPGetOverlappedResult, - &WSPGetPeerName, - &WSPGetSockName, - &WSPGetSockOpt, - &WSPGetQOSByName, - &WSPIoctl, - &WSPJoinLeaf, - &WSPListen, - &WSPRecv, - &WSPRecvDisconnect, - &WSPRecvFrom, - &WSPSelect, - &WSPSend, - &WSPSendDisconnect, - &WSPSendTo, - &WSPSetSockOpt, - &WSPShutdown, - &WSPSocket, - &WSPStringToAddress -}; - -LONG SockWspStartupCount; -WSPUPCALLTABLE SockUpcallTableHack; -LPWSPUPCALLTABLE SockUpcallTable; - -/* FUNCTIONS *****************************************************************/ - -VOID -WSPAPI -NewIcfConnection(IN PSOCK_ICF_DATA IcfData) -{ - /* Load the ICF DLL */ - IcfData->DllHandle = LoadLibraryW(L"hhnetcfg.dll"); - if (IcfData->DllHandle) - { - /* Get the entrypoints */ - IcfData->IcfOpenDynamicFwPort = GetProcAddress(IcfData->DllHandle, - "IcfOpenDynamicFwPort"); - IcfData->IcfConnect = (PICF_CONNECT)GetProcAddress(IcfData->DllHandle, - "IcfConnect"); - IcfData->IcfDisconnect = GetProcAddress(IcfData->DllHandle, - "IcfDisconnect"); - - /* Now call IcfConnect */ - if (!IcfData->IcfConnect(IcfData)) - { - /* We failed, release the library */ - FreeLibrary(IcfData->DllHandle); - } - } -} - -VOID -WSPAPI -InitializeIcfConnection(IN PSOCK_ICF_DATA IcfData) -{ - /* Make sure we have an ICF Handle */ - if (IcfData->IcfHandle) - { - /* Save the function pointers and dll handle */ - IcfDllHandle = IcfData->DllHandle; - pfnIcfOpenPort = IcfData->IcfOpenDynamicFwPort; - pfnIcfConnect = IcfData->IcfConnect; - pfnIcfDisconnect = IcfData->IcfDisconnect; - } -} - -VOID -WSPAPI -CloseIcfConnection(IN PSOCK_ICF_DATA IcfData) -{ - /* Make sure we have an ICF Handle */ - if (IcfData->IcfHandle) - { - /* Call IcfDisconnect */ - IcfData->IcfConnect(IcfData); - - /* Release the library */ - FreeLibrary(IcfData->DllHandle); - } -} - -INT -WSPAPI -WSPStartup(IN WORD wVersionRequested, - OUT LPWSPDATA lpWSPData, - IN LPWSAPROTOCOL_INFOW lpProtocolInfo, - IN WSPUPCALLTABLE UpcallTable, - OUT LPWSPPROC_TABLE lpProcTable) -{ - CHAR DllPath[MAX_PATH]; - HINSTANCE DllHandle; - SOCK_ICF_DATA IcfData; - NT_PRODUCT_TYPE ProductType; - - /* Call the generic mswsock initialization routine */ - if (!MSWSOCK_Initialize()) return WSAENOBUFS; - - /* Check if we have TEB data yet */ - if (!NtCurrentTeb()->WinSockData) - { - /* We don't have thread data yet, initialize it */ - if (!MSAFD_SockThreadInitialize()) return WSAENOBUFS; - } - - /* Check the version number */ - if (wVersionRequested != MAKEWORD(2,2)) return WSAVERNOTSUPPORTED; - - /* Get ICF entrypoints */ - NewIcfConnection(&IcfData); - - /* Acquire the global lock */ - SockAcquireRwLockExclusive(&SocketGlobalLock); - - /* Check if we've never initialized before */ - if (!SockWspStartupCount) - { - /* Check if we have a context table by now */ - if (!SockContextTable) - { - /* Create it */ - if (WahCreateHandleContextTable(&SockContextTable) != NO_ERROR) - { - /* Fail */ - SockReleaseRwLockExclusive(&SocketGlobalLock); - CloseIcfConnection(&IcfData); - return WSASYSCALLFAILURE; - } - } - - /* Bias our load count so we won't be killed with pending APCs */ - GetModuleFileNameA(SockModuleHandle, DllPath, MAX_PATH); - DllHandle = LoadLibraryA(DllPath); - if (!DllHandle) - { - /* Weird error, release and return */ - SockReleaseRwLockExclusive(&SocketGlobalLock); - CloseIcfConnection(&IcfData); - return WSASYSCALLFAILURE; - } - - /* Initialize ICF */ - InitializeIcfConnection(&IcfData); - - /* Set our Upcall Table */ - SockUpcallTableHack = UpcallTable; - SockUpcallTable = &SockUpcallTableHack; - } - - /* Increase startup count */ - SockWspStartupCount++; - - /* Return our version */ - lpWSPData->wVersion = MAKEWORD(2, 2); - lpWSPData->wHighVersion = MAKEWORD(2, 2); - wcscpy(lpWSPData->szDescription, L"Microsoft Windows Sockets Version 2."); - - /* Return our Internal Table */ - *lpProcTable = SockProcTable; - - /* Check if this is a SAN GUID */ - if (IsEqualGUID(&lpProtocolInfo->ProviderId, &SockTcpProviderInfo.ProviderId)) - { - /* Get the product type and check if this is a server OS */ - RtlGetNtProductType(&ProductType); - if (ProductType != NtProductWinNt) - { - /* Get the SAN TCP/IP Catalog ID */ - /* FIXME: SockSanGetTcpipCatalogId(); */ - - /* Initialize SAN if it's enabled */ - if (SockSanEnabled) SockSanInitialize(); - } - } - - /* Release the lock and return */ - SockReleaseRwLockExclusive(&SocketGlobalLock); - - /* Return to caller */ - return NO_ERROR; -} - -INT -WSPAPI -WSPCleanup(OUT LPINT lpErrno) -{ - /* FIXME: Clean up */ - *lpErrno = NO_ERROR; - return 0; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -PVOID pfnIcfOpenPort; -PICF_CONNECT pfnIcfConnect; -PVOID pfnIcfDisconnect; -HINSTANCE IcfDllHandle; - -WSPPROC_TABLE SockProcTable = -{ - &WSPAccept, - &WSPAddressToString, - &WSPAsyncSelect, - &WSPBind, - &WSPCancelBlockingCall, - &WSPCleanup, - &WSPCloseSocket, - &WSPConnect, - &WSPDuplicateSocket, - &WSPEnumNetworkEvents, - &WSPEventSelect, - &WSPGetOverlappedResult, - &WSPGetPeerName, - &WSPGetSockName, - &WSPGetSockOpt, - &WSPGetQOSByName, - &WSPIoctl, - &WSPJoinLeaf, - &WSPListen, - &WSPRecv, - &WSPRecvDisconnect, - &WSPRecvFrom, - &WSPSelect, - &WSPSend, - &WSPSendDisconnect, - &WSPSendTo, - &WSPSetSockOpt, - &WSPShutdown, - &WSPSocket, - &WSPStringToAddress -}; - -LONG SockWspStartupCount; -WSPUPCALLTABLE SockUpcallTableHack; -LPWSPUPCALLTABLE SockUpcallTable; - -/* FUNCTIONS *****************************************************************/ - -VOID -WSPAPI -NewIcfConnection(IN PSOCK_ICF_DATA IcfData) -{ - /* Load the ICF DLL */ - IcfData->DllHandle = LoadLibraryW(L"hhnetcfg.dll"); - if (IcfData->DllHandle) - { - /* Get the entrypoints */ - IcfData->IcfOpenDynamicFwPort = GetProcAddress(IcfData->DllHandle, - "IcfOpenDynamicFwPort"); - IcfData->IcfConnect = (PICF_CONNECT)GetProcAddress(IcfData->DllHandle, - "IcfConnect"); - IcfData->IcfDisconnect = GetProcAddress(IcfData->DllHandle, - "IcfDisconnect"); - - /* Now call IcfConnect */ - if (!IcfData->IcfConnect(IcfData)) - { - /* We failed, release the library */ - FreeLibrary(IcfData->DllHandle); - } - } -} - -VOID -WSPAPI -InitializeIcfConnection(IN PSOCK_ICF_DATA IcfData) -{ - /* Make sure we have an ICF Handle */ - if (IcfData->IcfHandle) - { - /* Save the function pointers and dll handle */ - IcfDllHandle = IcfData->DllHandle; - pfnIcfOpenPort = IcfData->IcfOpenDynamicFwPort; - pfnIcfConnect = IcfData->IcfConnect; - pfnIcfDisconnect = IcfData->IcfDisconnect; - } -} - -VOID -WSPAPI -CloseIcfConnection(IN PSOCK_ICF_DATA IcfData) -{ - /* Make sure we have an ICF Handle */ - if (IcfData->IcfHandle) - { - /* Call IcfDisconnect */ - IcfData->IcfConnect(IcfData); - - /* Release the library */ - FreeLibrary(IcfData->DllHandle); - } -} - -INT -WSPAPI -WSPStartup(IN WORD wVersionRequested, - OUT LPWSPDATA lpWSPData, - IN LPWSAPROTOCOL_INFOW lpProtocolInfo, - IN WSPUPCALLTABLE UpcallTable, - OUT LPWSPPROC_TABLE lpProcTable) -{ - CHAR DllPath[MAX_PATH]; - HINSTANCE DllHandle; - SOCK_ICF_DATA IcfData; - NT_PRODUCT_TYPE ProductType; - - /* Call the generic mswsock initialization routine */ - if (!MSWSOCK_Initialize()) return WSAENOBUFS; - - /* Check if we have TEB data yet */ - if (!NtCurrentTeb()->WinSockData) - { - /* We don't have thread data yet, initialize it */ - if (!MSAFD_SockThreadInitialize()) return WSAENOBUFS; - } - - /* Check the version number */ - if (wVersionRequested != MAKEWORD(2,2)) return WSAVERNOTSUPPORTED; - - /* Get ICF entrypoints */ - NewIcfConnection(&IcfData); - - /* Acquire the global lock */ - SockAcquireRwLockExclusive(&SocketGlobalLock); - - /* Check if we've never initialized before */ - if (!SockWspStartupCount) - { - /* Check if we have a context table by now */ - if (!SockContextTable) - { - /* Create it */ - if (WahCreateHandleContextTable(&SockContextTable) != NO_ERROR) - { - /* Fail */ - SockReleaseRwLockExclusive(&SocketGlobalLock); - CloseIcfConnection(&IcfData); - return WSASYSCALLFAILURE; - } - } - - /* Bias our load count so we won't be killed with pending APCs */ - GetModuleFileNameA(SockModuleHandle, DllPath, MAX_PATH); - DllHandle = LoadLibraryA(DllPath); - if (!DllHandle) - { - /* Weird error, release and return */ - SockReleaseRwLockExclusive(&SocketGlobalLock); - CloseIcfConnection(&IcfData); - return WSASYSCALLFAILURE; - } - - /* Initialize ICF */ - InitializeIcfConnection(&IcfData); - - /* Set our Upcall Table */ - SockUpcallTableHack = UpcallTable; - SockUpcallTable = &SockUpcallTableHack; - } - - /* Increase startup count */ - SockWspStartupCount++; - - /* Return our version */ - lpWSPData->wVersion = MAKEWORD(2, 2); - lpWSPData->wHighVersion = MAKEWORD(2, 2); - wcscpy(lpWSPData->szDescription, L"Microsoft Windows Sockets Version 2."); - - /* Return our Internal Table */ - *lpProcTable = SockProcTable; - - /* Check if this is a SAN GUID */ - if (IsEqualGUID(&lpProtocolInfo->ProviderId, &SockTcpProviderInfo.ProviderId)) - { - /* Get the product type and check if this is a server OS */ - RtlGetNtProductType(&ProductType); - if (ProductType != NtProductWinNt) - { - /* Get the SAN TCP/IP Catalog ID */ - /* FIXME: SockSanGetTcpipCatalogId(); */ - - /* Initialize SAN if it's enabled */ - if (SockSanEnabled) SockSanInitialize(); - } - } - - /* Release the lock and return */ - SockReleaseRwLockExclusive(&SocketGlobalLock); - - /* Return to caller */ - return NO_ERROR; -} - -INT -WSPAPI -WSPCleanup(OUT LPINT lpErrno) -{ - /* FIXME: Clean up */ - *lpErrno = NO_ERROR; - return 0; -} - diff --git a/dll/win32/mswsock/msafd/tpackets.c b/dll/win32/mswsock/msafd/tpackets.c index 3e062e90d63..bd1ad2806dc 100644 --- a/dll/win32/mswsock/msafd/tpackets.c +++ b/dll/win32/mswsock/msafd/tpackets.c @@ -12,45 +12,3 @@ /* FUNCTIONS *****************************************************************/ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - diff --git a/dll/win32/mswsock/msafd/tranfile.c b/dll/win32/mswsock/msafd/tranfile.c index 3e062e90d63..bd1ad2806dc 100644 --- a/dll/win32/mswsock/msafd/tranfile.c +++ b/dll/win32/mswsock/msafd/tranfile.c @@ -12,45 +12,3 @@ /* FUNCTIONS *****************************************************************/ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - diff --git a/dll/win32/mswsock/msafd/wspmisc.c b/dll/win32/mswsock/msafd/wspmisc.c index 0acd28256eb..eeab724286f 100644 --- a/dll/win32/mswsock/msafd/wspmisc.c +++ b/dll/win32/mswsock/msafd/wspmisc.c @@ -86,267 +86,3 @@ WSPDuplicateSocket(IN SOCKET s, return 0; } -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -BOOL -WSPAPI -WSPGetQOSByName(IN SOCKET Handle, - IN OUT LPWSABUF lpQOSName, - OUT LPQOS lpQOS, - OUT LPINT lpErrno) -{ - PWINSOCK_TEB_DATA ThreadData; - INT ErrorCode; - DWORD BytesReturned; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Call WSPIoctl for the job */ - WSPIoctl(Handle, - SIO_GET_QOS, - NULL, - 0, - lpQOS, - sizeof(QOS), - &BytesReturned, - NULL, - NULL, - NULL, - &ErrorCode); - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return FALSE; - } - - /* Success */ - return TRUE; -} - -INT -WSPAPI -WSPCancelBlockingCall(OUT LPINT lpErrno) -{ - return 0; -} - -BOOL -WSPAPI -WSPGetOverlappedResult(IN SOCKET s, - IN LPWSAOVERLAPPED lpOverlapped, - OUT LPDWORD lpcbTransfer, - IN BOOL fWait, - OUT LPDWORD lpdwFlags, - OUT LPINT lpErrno) -{ - return FALSE; -} - -INT -WSPAPI -WSPDuplicateSocket(IN SOCKET s, - IN DWORD dwProcessId, - OUT LPWSAPROTOCOL_INFOW lpProtocolInfo, - OUT LPINT lpErrno) -{ - return 0; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -BOOL -WSPAPI -WSPGetQOSByName(IN SOCKET Handle, - IN OUT LPWSABUF lpQOSName, - OUT LPQOS lpQOS, - OUT LPINT lpErrno) -{ - PWINSOCK_TEB_DATA ThreadData; - INT ErrorCode; - DWORD BytesReturned; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Call WSPIoctl for the job */ - WSPIoctl(Handle, - SIO_GET_QOS, - NULL, - 0, - lpQOS, - sizeof(QOS), - &BytesReturned, - NULL, - NULL, - NULL, - &ErrorCode); - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return FALSE; - } - - /* Success */ - return TRUE; -} - -INT -WSPAPI -WSPCancelBlockingCall(OUT LPINT lpErrno) -{ - return 0; -} - -BOOL -WSPAPI -WSPGetOverlappedResult(IN SOCKET s, - IN LPWSAOVERLAPPED lpOverlapped, - OUT LPDWORD lpcbTransfer, - IN BOOL fWait, - OUT LPDWORD lpdwFlags, - OUT LPINT lpErrno) -{ - return FALSE; -} - -INT -WSPAPI -WSPDuplicateSocket(IN SOCKET s, - IN DWORD dwProcessId, - OUT LPWSAPROTOCOL_INFOW lpProtocolInfo, - OUT LPINT lpErrno) -{ - return 0; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -BOOL -WSPAPI -WSPGetQOSByName(IN SOCKET Handle, - IN OUT LPWSABUF lpQOSName, - OUT LPQOS lpQOS, - OUT LPINT lpErrno) -{ - PWINSOCK_TEB_DATA ThreadData; - INT ErrorCode; - DWORD BytesReturned; - - /* Enter prolog */ - ErrorCode = SockEnterApiFast(&ThreadData); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return SOCKET_ERROR; - } - - /* Call WSPIoctl for the job */ - WSPIoctl(Handle, - SIO_GET_QOS, - NULL, - 0, - lpQOS, - sizeof(QOS), - &BytesReturned, - NULL, - NULL, - NULL, - &ErrorCode); - - /* Check for error */ - if (ErrorCode != NO_ERROR) - { - /* Fail */ - *lpErrno = ErrorCode; - return FALSE; - } - - /* Success */ - return TRUE; -} - -INT -WSPAPI -WSPCancelBlockingCall(OUT LPINT lpErrno) -{ - return 0; -} - -BOOL -WSPAPI -WSPGetOverlappedResult(IN SOCKET s, - IN LPWSAOVERLAPPED lpOverlapped, - OUT LPDWORD lpcbTransfer, - IN BOOL fWait, - OUT LPDWORD lpdwFlags, - OUT LPINT lpErrno) -{ - return FALSE; -} - -INT -WSPAPI -WSPDuplicateSocket(IN SOCKET s, - IN DWORD dwProcessId, - OUT LPWSAPROTOCOL_INFOW lpProtocolInfo, - OUT LPINT lpErrno) -{ - return 0; -} - diff --git a/dll/win32/mswsock/mswsock.rbuild b/dll/win32/mswsock/mswsock.rbuild index 473eac1689e..4c4e3d39ab3 100644 --- a/dll/win32/mswsock/mswsock.rbuild +++ b/dll/win32/mswsock/mswsock.rbuild @@ -1,7 +1,7 @@ include/reactos/winsock - dnslib/inc + dns/inc include/reactos/drivers ntdll advapi32 diff --git a/dll/win32/mswsock/mswsock/init.c b/dll/win32/mswsock/mswsock/init.c index 2a8bc65e9e7..446d0788df4 100644 --- a/dll/win32/mswsock/mswsock/init.c +++ b/dll/win32/mswsock/mswsock/init.c @@ -202,615 +202,3 @@ DllMain(HANDLE hModule, return TRUE; } -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -BOOL SockProcessTerminating; -LONG SockProcessPendingAPCCount; -HINSTANCE SockModuleHandle; - -/* FUNCTIONS *****************************************************************/ - -BOOL -WSPAPI -MSWSOCK_Initialize(VOID) -{ - SYSTEM_INFO SystemInfo; - - /* If our heap is already initialized, we can skip everything */ - if (SockAllocateHeapRoutine) return TRUE; - - /* Make sure nobody thinks we're terminating */ - SockProcessTerminating = FALSE; - - /* Get the system information */ - GetSystemInfo(&SystemInfo); - - /* Check if this is an MP machine */ - if (SystemInfo.dwNumberOfProcessors > 1) - { - /* Use our own heap on MP, to reduce locks */ - SockAllocateHeapRoutine = SockInitializeHeap; - SockPrivateHeap = NULL; - } - else - { - /* Use process heap */ - SockAllocateHeapRoutine = RtlAllocateHeap; - SockPrivateHeap = RtlGetProcessHeap(); - } - - /* Initialize WSM data */ - gWSM_NSPStartupRef = -1; - gWSM_NSPCallRef = 0; - - /* Initialize the helper listhead */ - InitializeListHead(&SockHelperDllListHead); - - /* Initialize the global lock */ - SockInitializeRwLockAndSpinCount(&SocketGlobalLock, 1000); - - /* Initialize the socket lock */ - InitializeCriticalSection(&MSWSOCK_SocketLock); - - /* Initialize RnR locks and other RnR data */ - Rnr_ProcessInit(); - - /* Return success */ - return TRUE; -} - -BOOL -APIENTRY -DllMain(HANDLE hModule, - DWORD dwReason, - LPVOID lpReserved) -{ - OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo; - PWINSOCK_TEB_DATA ThreadData; - - /* Check what's going on */ - switch (dwReason) - { - /* Process attaching */ - case DLL_PROCESS_ATTACH: - - /* Save module handles */ - SockModuleHandle = hModule; - NlsMsgSourcemModuleHandle = hModule; - - /* Initialize us */ - MSWSOCK_Initialize(); - break; - - /* Detaching */ - case DLL_PROCESS_DETACH: - - /* Did we initialize yet? */ - if (!SockAllocateHeapRoutine) break; - - /* Fail all future calls */ - SockProcessTerminating = TRUE; - - /* Is this a FreeLibrary? */ - if (!lpReserved) - { - /* Cleanup RNR */ - Rnr_ProcessCleanup(); - - /* Delete the socket lock */ - DeleteCriticalSection(&MSWSOCK_SocketLock); - - /* Check if we have an Async Queue Port */ - if (SockAsyncQueuePort) - { - /* Unprotect the handle */ - HandleInfo.ProtectFromClose = FALSE; - HandleInfo.Inherit = FALSE; - NtSetInformationObject(SockAsyncQueuePort, - ObjectHandleFlagInformation, - &HandleInfo, - sizeof(HandleInfo)); - - /* Close it, and clear the port */ - NtClose(SockAsyncQueuePort); - SockAsyncQueuePort = NULL; - } - - /* Check if we have a context table */ - if (SockContextTable) - { - /* Destroy it */ - WahDestroyHandleContextTable(SockContextTable); - SockContextTable = NULL; - } - - /* Delete the global lock as well */ - SockDeleteRwLock(&SocketGlobalLock); - - /* Check if we have a buffer keytable */ - if (SockBufferKeyTable) - { - /* Free it */ - VirtualFree(SockBufferKeyTable, 0, MEM_RELEASE); - } - } - - /* Check if we have to a SAN cleanup event */ - if (SockSanCleanUpCompleteEvent) - { - /* Close the event handle */ - CloseHandle(SockSanCleanUpCompleteEvent); - } - - /* Thread detaching */ - case DLL_THREAD_DETACH: - - /* Set the context to NULL for thread detach */ - if (dwReason == DLL_THREAD_DETACH) lpReserved = NULL; - - /* Check if this is a normal thread detach */ - if (!lpReserved) - { - /* Do RnR Thread cleanup */ - Rnr_ThreadCleanup(); - - /* Get thread data */ - ThreadData = NtCurrentTeb()->WinSockData; - if (ThreadData) - { - /* Check if any APCs are pending */ - if (ThreadData->PendingAPCs) - { - /* Save the value */ - InterlockedExchangeAdd(&SockProcessPendingAPCCount, - -(ThreadData->PendingAPCs)); - - /* Close the evnet handle */ - NtClose(ThreadData->EventHandle); - - /* Free the thread data and set it to null */ - RtlFreeHeap(GetProcessHeap(), 0, (PVOID)ThreadData); - NtCurrentTeb()->WinSockData = NULL; - } - } - } - - /* Check if this is a process detach fallthrough */ - if (dwReason == DLL_PROCESS_DETACH && !lpReserved) - { - /* Check if we're using a private heap */ - if (SockPrivateHeap != RtlGetProcessHeap()) - { - /* Destroy it */ - RtlDestroyHeap(SockPrivateHeap); - } - SockAllocateHeapRoutine = NULL; - } - break; - - case DLL_THREAD_ATTACH: - break; - } - - /* Return */ - return TRUE; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -BOOL SockProcessTerminating; -LONG SockProcessPendingAPCCount; -HINSTANCE SockModuleHandle; - -/* FUNCTIONS *****************************************************************/ - -BOOL -WSPAPI -MSWSOCK_Initialize(VOID) -{ - SYSTEM_INFO SystemInfo; - - /* If our heap is already initialized, we can skip everything */ - if (SockAllocateHeapRoutine) return TRUE; - - /* Make sure nobody thinks we're terminating */ - SockProcessTerminating = FALSE; - - /* Get the system information */ - GetSystemInfo(&SystemInfo); - - /* Check if this is an MP machine */ - if (SystemInfo.dwNumberOfProcessors > 1) - { - /* Use our own heap on MP, to reduce locks */ - SockAllocateHeapRoutine = SockInitializeHeap; - SockPrivateHeap = NULL; - } - else - { - /* Use process heap */ - SockAllocateHeapRoutine = RtlAllocateHeap; - SockPrivateHeap = RtlGetProcessHeap(); - } - - /* Initialize WSM data */ - gWSM_NSPStartupRef = -1; - gWSM_NSPCallRef = 0; - - /* Initialize the helper listhead */ - InitializeListHead(&SockHelperDllListHead); - - /* Initialize the global lock */ - SockInitializeRwLockAndSpinCount(&SocketGlobalLock, 1000); - - /* Initialize the socket lock */ - InitializeCriticalSection(&MSWSOCK_SocketLock); - - /* Initialize RnR locks and other RnR data */ - Rnr_ProcessInit(); - - /* Return success */ - return TRUE; -} - -BOOL -APIENTRY -DllMain(HANDLE hModule, - DWORD dwReason, - LPVOID lpReserved) -{ - OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo; - PWINSOCK_TEB_DATA ThreadData; - - /* Check what's going on */ - switch (dwReason) - { - /* Process attaching */ - case DLL_PROCESS_ATTACH: - - /* Save module handles */ - SockModuleHandle = hModule; - NlsMsgSourcemModuleHandle = hModule; - - /* Initialize us */ - MSWSOCK_Initialize(); - break; - - /* Detaching */ - case DLL_PROCESS_DETACH: - - /* Did we initialize yet? */ - if (!SockAllocateHeapRoutine) break; - - /* Fail all future calls */ - SockProcessTerminating = TRUE; - - /* Is this a FreeLibrary? */ - if (!lpReserved) - { - /* Cleanup RNR */ - Rnr_ProcessCleanup(); - - /* Delete the socket lock */ - DeleteCriticalSection(&MSWSOCK_SocketLock); - - /* Check if we have an Async Queue Port */ - if (SockAsyncQueuePort) - { - /* Unprotect the handle */ - HandleInfo.ProtectFromClose = FALSE; - HandleInfo.Inherit = FALSE; - NtSetInformationObject(SockAsyncQueuePort, - ObjectHandleFlagInformation, - &HandleInfo, - sizeof(HandleInfo)); - - /* Close it, and clear the port */ - NtClose(SockAsyncQueuePort); - SockAsyncQueuePort = NULL; - } - - /* Check if we have a context table */ - if (SockContextTable) - { - /* Destroy it */ - WahDestroyHandleContextTable(SockContextTable); - SockContextTable = NULL; - } - - /* Delete the global lock as well */ - SockDeleteRwLock(&SocketGlobalLock); - - /* Check if we have a buffer keytable */ - if (SockBufferKeyTable) - { - /* Free it */ - VirtualFree(SockBufferKeyTable, 0, MEM_RELEASE); - } - } - - /* Check if we have to a SAN cleanup event */ - if (SockSanCleanUpCompleteEvent) - { - /* Close the event handle */ - CloseHandle(SockSanCleanUpCompleteEvent); - } - - /* Thread detaching */ - case DLL_THREAD_DETACH: - - /* Set the context to NULL for thread detach */ - if (dwReason == DLL_THREAD_DETACH) lpReserved = NULL; - - /* Check if this is a normal thread detach */ - if (!lpReserved) - { - /* Do RnR Thread cleanup */ - Rnr_ThreadCleanup(); - - /* Get thread data */ - ThreadData = NtCurrentTeb()->WinSockData; - if (ThreadData) - { - /* Check if any APCs are pending */ - if (ThreadData->PendingAPCs) - { - /* Save the value */ - InterlockedExchangeAdd(&SockProcessPendingAPCCount, - -(ThreadData->PendingAPCs)); - - /* Close the evnet handle */ - NtClose(ThreadData->EventHandle); - - /* Free the thread data and set it to null */ - RtlFreeHeap(GetProcessHeap(), 0, (PVOID)ThreadData); - NtCurrentTeb()->WinSockData = NULL; - } - } - } - - /* Check if this is a process detach fallthrough */ - if (dwReason == DLL_PROCESS_DETACH && !lpReserved) - { - /* Check if we're using a private heap */ - if (SockPrivateHeap != RtlGetProcessHeap()) - { - /* Destroy it */ - RtlDestroyHeap(SockPrivateHeap); - } - SockAllocateHeapRoutine = NULL; - } - break; - - case DLL_THREAD_ATTACH: - break; - } - - /* Return */ - return TRUE; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -BOOL SockProcessTerminating; -LONG SockProcessPendingAPCCount; -HINSTANCE SockModuleHandle; - -/* FUNCTIONS *****************************************************************/ - -BOOL -WSPAPI -MSWSOCK_Initialize(VOID) -{ - SYSTEM_INFO SystemInfo; - - /* If our heap is already initialized, we can skip everything */ - if (SockAllocateHeapRoutine) return TRUE; - - /* Make sure nobody thinks we're terminating */ - SockProcessTerminating = FALSE; - - /* Get the system information */ - GetSystemInfo(&SystemInfo); - - /* Check if this is an MP machine */ - if (SystemInfo.dwNumberOfProcessors > 1) - { - /* Use our own heap on MP, to reduce locks */ - SockAllocateHeapRoutine = SockInitializeHeap; - SockPrivateHeap = NULL; - } - else - { - /* Use process heap */ - SockAllocateHeapRoutine = RtlAllocateHeap; - SockPrivateHeap = RtlGetProcessHeap(); - } - - /* Initialize WSM data */ - gWSM_NSPStartupRef = -1; - gWSM_NSPCallRef = 0; - - /* Initialize the helper listhead */ - InitializeListHead(&SockHelperDllListHead); - - /* Initialize the global lock */ - SockInitializeRwLockAndSpinCount(&SocketGlobalLock, 1000); - - /* Initialize the socket lock */ - InitializeCriticalSection(&MSWSOCK_SocketLock); - - /* Initialize RnR locks and other RnR data */ - Rnr_ProcessInit(); - - /* Return success */ - return TRUE; -} - -BOOL -APIENTRY -DllMain(HANDLE hModule, - DWORD dwReason, - LPVOID lpReserved) -{ - OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo; - PWINSOCK_TEB_DATA ThreadData; - - /* Check what's going on */ - switch (dwReason) - { - /* Process attaching */ - case DLL_PROCESS_ATTACH: - - /* Save module handles */ - SockModuleHandle = hModule; - NlsMsgSourcemModuleHandle = hModule; - - /* Initialize us */ - MSWSOCK_Initialize(); - break; - - /* Detaching */ - case DLL_PROCESS_DETACH: - - /* Did we initialize yet? */ - if (!SockAllocateHeapRoutine) break; - - /* Fail all future calls */ - SockProcessTerminating = TRUE; - - /* Is this a FreeLibrary? */ - if (!lpReserved) - { - /* Cleanup RNR */ - Rnr_ProcessCleanup(); - - /* Delete the socket lock */ - DeleteCriticalSection(&MSWSOCK_SocketLock); - - /* Check if we have an Async Queue Port */ - if (SockAsyncQueuePort) - { - /* Unprotect the handle */ - HandleInfo.ProtectFromClose = FALSE; - HandleInfo.Inherit = FALSE; - NtSetInformationObject(SockAsyncQueuePort, - ObjectHandleFlagInformation, - &HandleInfo, - sizeof(HandleInfo)); - - /* Close it, and clear the port */ - NtClose(SockAsyncQueuePort); - SockAsyncQueuePort = NULL; - } - - /* Check if we have a context table */ - if (SockContextTable) - { - /* Destroy it */ - WahDestroyHandleContextTable(SockContextTable); - SockContextTable = NULL; - } - - /* Delete the global lock as well */ - SockDeleteRwLock(&SocketGlobalLock); - - /* Check if we have a buffer keytable */ - if (SockBufferKeyTable) - { - /* Free it */ - VirtualFree(SockBufferKeyTable, 0, MEM_RELEASE); - } - } - - /* Check if we have to a SAN cleanup event */ - if (SockSanCleanUpCompleteEvent) - { - /* Close the event handle */ - CloseHandle(SockSanCleanUpCompleteEvent); - } - - /* Thread detaching */ - case DLL_THREAD_DETACH: - - /* Set the context to NULL for thread detach */ - if (dwReason == DLL_THREAD_DETACH) lpReserved = NULL; - - /* Check if this is a normal thread detach */ - if (!lpReserved) - { - /* Do RnR Thread cleanup */ - Rnr_ThreadCleanup(); - - /* Get thread data */ - ThreadData = NtCurrentTeb()->WinSockData; - if (ThreadData) - { - /* Check if any APCs are pending */ - if (ThreadData->PendingAPCs) - { - /* Save the value */ - InterlockedExchangeAdd(&SockProcessPendingAPCCount, - -(ThreadData->PendingAPCs)); - - /* Close the evnet handle */ - NtClose(ThreadData->EventHandle); - - /* Free the thread data and set it to null */ - RtlFreeHeap(GetProcessHeap(), 0, (PVOID)ThreadData); - NtCurrentTeb()->WinSockData = NULL; - } - } - } - - /* Check if this is a process detach fallthrough */ - if (dwReason == DLL_PROCESS_DETACH && !lpReserved) - { - /* Check if we're using a private heap */ - if (SockPrivateHeap != RtlGetProcessHeap()) - { - /* Destroy it */ - RtlDestroyHeap(SockPrivateHeap); - } - SockAllocateHeapRoutine = NULL; - } - break; - - case DLL_THREAD_ATTACH: - break; - } - - /* Return */ - return TRUE; -} - diff --git a/dll/win32/mswsock/mswsock/msext.c b/dll/win32/mswsock/mswsock/msext.c index a67b63389a3..fb8a67e1e04 100644 --- a/dll/win32/mswsock/mswsock/msext.c +++ b/dll/win32/mswsock/mswsock/msext.c @@ -50,159 +50,3 @@ TransmitFile(SOCKET Socket, Flags); } -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -PVOID SockBufferKeyTable; -ULONG SockBufferKeyTableSize; - -/* FUNCTIONS *****************************************************************/ -BOOL -WINAPI -TransmitFile(SOCKET Socket, - HANDLE File, - DWORD NumberOfBytesToWrite, - DWORD NumberOfBytesPerSend, - LPOVERLAPPED Overlapped, - LPTRANSMIT_FILE_BUFFERS TransmitBuffers, - DWORD Flags) -{ - static GUID TransmitFileGUID = WSAID_TRANSMITFILE; - LPFN_TRANSMITFILE pfnTransmitFile; - DWORD cbBytesReturned; - - if (WSAIoctl(Socket, - SIO_GET_EXTENSION_FUNCTION_POINTER, - &TransmitFileGUID, - sizeof(TransmitFileGUID), - &pfnTransmitFile, - sizeof(pfnTransmitFile), - &cbBytesReturned, - NULL, - NULL) == SOCKET_ERROR) - { - return FALSE; - } - - return pfnTransmitFile(Socket, - File, - NumberOfBytesToWrite, - NumberOfBytesPerSend, - Overlapped, - TransmitBuffers, - Flags); -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -PVOID SockBufferKeyTable; -ULONG SockBufferKeyTableSize; - -/* FUNCTIONS *****************************************************************/ -BOOL -WINAPI -TransmitFile(SOCKET Socket, - HANDLE File, - DWORD NumberOfBytesToWrite, - DWORD NumberOfBytesPerSend, - LPOVERLAPPED Overlapped, - LPTRANSMIT_FILE_BUFFERS TransmitBuffers, - DWORD Flags) -{ - static GUID TransmitFileGUID = WSAID_TRANSMITFILE; - LPFN_TRANSMITFILE pfnTransmitFile; - DWORD cbBytesReturned; - - if (WSAIoctl(Socket, - SIO_GET_EXTENSION_FUNCTION_POINTER, - &TransmitFileGUID, - sizeof(TransmitFileGUID), - &pfnTransmitFile, - sizeof(pfnTransmitFile), - &cbBytesReturned, - NULL, - NULL) == SOCKET_ERROR) - { - return FALSE; - } - - return pfnTransmitFile(Socket, - File, - NumberOfBytesToWrite, - NumberOfBytesPerSend, - Overlapped, - TransmitBuffers, - Flags); -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -PVOID SockBufferKeyTable; -ULONG SockBufferKeyTableSize; - -/* FUNCTIONS *****************************************************************/ -BOOL -WINAPI -TransmitFile(SOCKET Socket, - HANDLE File, - DWORD NumberOfBytesToWrite, - DWORD NumberOfBytesPerSend, - LPOVERLAPPED Overlapped, - LPTRANSMIT_FILE_BUFFERS TransmitBuffers, - DWORD Flags) -{ - static GUID TransmitFileGUID = WSAID_TRANSMITFILE; - LPFN_TRANSMITFILE pfnTransmitFile; - DWORD cbBytesReturned; - - if (WSAIoctl(Socket, - SIO_GET_EXTENSION_FUNCTION_POINTER, - &TransmitFileGUID, - sizeof(TransmitFileGUID), - &pfnTransmitFile, - sizeof(pfnTransmitFile), - &cbBytesReturned, - NULL, - NULL) == SOCKET_ERROR) - { - return FALSE; - } - - return pfnTransmitFile(Socket, - File, - NumberOfBytesToWrite, - NumberOfBytesPerSend, - Overlapped, - TransmitBuffers, - Flags); -} - diff --git a/dll/win32/mswsock/mswsock/nspgaddr.c b/dll/win32/mswsock/mswsock/nspgaddr.c index 3e062e90d63..bd1ad2806dc 100644 --- a/dll/win32/mswsock/mswsock/nspgaddr.c +++ b/dll/win32/mswsock/mswsock/nspgaddr.c @@ -12,45 +12,3 @@ /* FUNCTIONS *****************************************************************/ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - diff --git a/dll/win32/mswsock/mswsock/nspmisc.c b/dll/win32/mswsock/mswsock/nspmisc.c index 3e062e90d63..bd1ad2806dc 100644 --- a/dll/win32/mswsock/mswsock/nspmisc.c +++ b/dll/win32/mswsock/mswsock/nspmisc.c @@ -12,45 +12,3 @@ /* FUNCTIONS *****************************************************************/ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - diff --git a/dll/win32/mswsock/mswsock/nspsvc.c b/dll/win32/mswsock/mswsock/nspsvc.c index 3e062e90d63..bd1ad2806dc 100644 --- a/dll/win32/mswsock/mswsock/nspsvc.c +++ b/dll/win32/mswsock/mswsock/nspsvc.c @@ -12,45 +12,3 @@ /* FUNCTIONS *****************************************************************/ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - diff --git a/dll/win32/mswsock/mswsock/nsptcpip.c b/dll/win32/mswsock/mswsock/nsptcpip.c index 3e062e90d63..bd1ad2806dc 100644 --- a/dll/win32/mswsock/mswsock/nsptcpip.c +++ b/dll/win32/mswsock/mswsock/nsptcpip.c @@ -12,45 +12,3 @@ /* FUNCTIONS *****************************************************************/ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - diff --git a/dll/win32/mswsock/mswsock/nsputil.c b/dll/win32/mswsock/mswsock/nsputil.c index 3e062e90d63..bd1ad2806dc 100644 --- a/dll/win32/mswsock/mswsock/nsputil.c +++ b/dll/win32/mswsock/mswsock/nsputil.c @@ -12,45 +12,3 @@ /* FUNCTIONS *****************************************************************/ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - diff --git a/dll/win32/mswsock/mswsock/proc.c b/dll/win32/mswsock/mswsock/proc.c index 6b45b5b8f85..4cb227144ec 100644 --- a/dll/win32/mswsock/mswsock/proc.c +++ b/dll/win32/mswsock/mswsock/proc.c @@ -112,345 +112,3 @@ MSAFD_SockThreadInitialize(VOID) return TRUE; } -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -PRTL_HEAP_ALLOCATE SockAllocateHeapRoutine; -HANDLE SockPrivateHeap; -CRITICAL_SECTION MSWSOCK_SocketLock; -PWAH_HANDLE_TABLE SockContextTable; - -/* FUNCTIONS *****************************************************************/ - -PVOID -WSPAPI -SockInitializeHeap(IN HANDLE Heap, - IN ULONG Flags, - IN ULONG Size) -{ - /* Create the heap */ - Heap = RtlCreateHeap(HEAP_GROWABLE, - NULL, - 0, - 0, - NULL, - NULL); - - /* Check if we created it successfully */ - if (Heap) - { - /* Write its pointer */ - if (InterlockedCompareExchangePointer(&SockPrivateHeap, Heap, NULL)) - { - /* Someone already allocated it, destroy ours */ - RtlDestroyHeap(Heap); - } - } - else - { - /* Write the default heap */ - (void)InterlockedCompareExchangePointer(&SockPrivateHeap, - RtlGetProcessHeap(), - NULL); - } - - /* Set the reap heap routine now */ - SockAllocateHeapRoutine = RtlAllocateHeap; - - /* Call it */ - return SockAllocateHeapRoutine(SockPrivateHeap, Flags, Size); -} - -INT -WSPAPI -SockEnterApiSlow(OUT PWINSOCK_TEB_DATA *ThreadData) -{ - /* Check again if we're terminating */ - if (SockProcessTerminating) return WSANOTINITIALISED; - - /* Check if WSPStartup wasn't called */ - if (SockWspStartupCount <= 0) return WSANOTINITIALISED; - - /* Get the thread data */ - *ThreadData = NtCurrentTeb()->WinSockData; - if (!(*ThreadData)) - { - /* Try to initialize the thread */ - if (!MSAFD_SockThreadInitialize()) return WSAENOBUFS; - - /* Get the thread data again */ - *ThreadData = NtCurrentTeb()->WinSockData; - } - - /* Return */ - return NO_ERROR; -} - -BOOL -WSPAPI -MSAFD_SockThreadInitialize(VOID) -{ - NTSTATUS Status; - HANDLE EventHandle; - PWINSOCK_TEB_DATA TebData; - - /* Initialize the event handle */ - Status = NtCreateEvent(&EventHandle, - EVENT_ALL_ACCESS, - NULL, - NotificationEvent, - FALSE); - if (!NT_SUCCESS(Status)) return FALSE; - - /* Allocate the thread data */ - TebData = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(WINSOCK_TEB_DATA)); - if (!TebData) return FALSE; - - /* Set it and zero its contents */ - NtCurrentTeb()->WinSockData = TebData; - RtlZeroMemory(TebData, sizeof(WINSOCK_TEB_DATA)); - - /* Set the event handle */ - TebData->EventHandle = EventHandle; - - /* Return success */ - return TRUE; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -PRTL_HEAP_ALLOCATE SockAllocateHeapRoutine; -HANDLE SockPrivateHeap; -CRITICAL_SECTION MSWSOCK_SocketLock; -PWAH_HANDLE_TABLE SockContextTable; - -/* FUNCTIONS *****************************************************************/ - -PVOID -WSPAPI -SockInitializeHeap(IN HANDLE Heap, - IN ULONG Flags, - IN ULONG Size) -{ - /* Create the heap */ - Heap = RtlCreateHeap(HEAP_GROWABLE, - NULL, - 0, - 0, - NULL, - NULL); - - /* Check if we created it successfully */ - if (Heap) - { - /* Write its pointer */ - if (InterlockedCompareExchangePointer(&SockPrivateHeap, Heap, NULL)) - { - /* Someone already allocated it, destroy ours */ - RtlDestroyHeap(Heap); - } - } - else - { - /* Write the default heap */ - (void)InterlockedCompareExchangePointer(&SockPrivateHeap, - RtlGetProcessHeap(), - NULL); - } - - /* Set the reap heap routine now */ - SockAllocateHeapRoutine = RtlAllocateHeap; - - /* Call it */ - return SockAllocateHeapRoutine(SockPrivateHeap, Flags, Size); -} - -INT -WSPAPI -SockEnterApiSlow(OUT PWINSOCK_TEB_DATA *ThreadData) -{ - /* Check again if we're terminating */ - if (SockProcessTerminating) return WSANOTINITIALISED; - - /* Check if WSPStartup wasn't called */ - if (SockWspStartupCount <= 0) return WSANOTINITIALISED; - - /* Get the thread data */ - *ThreadData = NtCurrentTeb()->WinSockData; - if (!(*ThreadData)) - { - /* Try to initialize the thread */ - if (!MSAFD_SockThreadInitialize()) return WSAENOBUFS; - - /* Get the thread data again */ - *ThreadData = NtCurrentTeb()->WinSockData; - } - - /* Return */ - return NO_ERROR; -} - -BOOL -WSPAPI -MSAFD_SockThreadInitialize(VOID) -{ - NTSTATUS Status; - HANDLE EventHandle; - PWINSOCK_TEB_DATA TebData; - - /* Initialize the event handle */ - Status = NtCreateEvent(&EventHandle, - EVENT_ALL_ACCESS, - NULL, - NotificationEvent, - FALSE); - if (!NT_SUCCESS(Status)) return FALSE; - - /* Allocate the thread data */ - TebData = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(WINSOCK_TEB_DATA)); - if (!TebData) return FALSE; - - /* Set it and zero its contents */ - NtCurrentTeb()->WinSockData = TebData; - RtlZeroMemory(TebData, sizeof(WINSOCK_TEB_DATA)); - - /* Set the event handle */ - TebData->EventHandle = EventHandle; - - /* Return success */ - return TRUE; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -PRTL_HEAP_ALLOCATE SockAllocateHeapRoutine; -HANDLE SockPrivateHeap; -CRITICAL_SECTION MSWSOCK_SocketLock; -PWAH_HANDLE_TABLE SockContextTable; - -/* FUNCTIONS *****************************************************************/ - -PVOID -WSPAPI -SockInitializeHeap(IN HANDLE Heap, - IN ULONG Flags, - IN ULONG Size) -{ - /* Create the heap */ - Heap = RtlCreateHeap(HEAP_GROWABLE, - NULL, - 0, - 0, - NULL, - NULL); - - /* Check if we created it successfully */ - if (Heap) - { - /* Write its pointer */ - if (InterlockedCompareExchangePointer(&SockPrivateHeap, Heap, NULL)) - { - /* Someone already allocated it, destroy ours */ - RtlDestroyHeap(Heap); - } - } - else - { - /* Write the default heap */ - (void)InterlockedCompareExchangePointer(&SockPrivateHeap, - RtlGetProcessHeap(), - NULL); - } - - /* Set the reap heap routine now */ - SockAllocateHeapRoutine = RtlAllocateHeap; - - /* Call it */ - return SockAllocateHeapRoutine(SockPrivateHeap, Flags, Size); -} - -INT -WSPAPI -SockEnterApiSlow(OUT PWINSOCK_TEB_DATA *ThreadData) -{ - /* Check again if we're terminating */ - if (SockProcessTerminating) return WSANOTINITIALISED; - - /* Check if WSPStartup wasn't called */ - if (SockWspStartupCount <= 0) return WSANOTINITIALISED; - - /* Get the thread data */ - *ThreadData = NtCurrentTeb()->WinSockData; - if (!(*ThreadData)) - { - /* Try to initialize the thread */ - if (!MSAFD_SockThreadInitialize()) return WSAENOBUFS; - - /* Get the thread data again */ - *ThreadData = NtCurrentTeb()->WinSockData; - } - - /* Return */ - return NO_ERROR; -} - -BOOL -WSPAPI -MSAFD_SockThreadInitialize(VOID) -{ - NTSTATUS Status; - HANDLE EventHandle; - PWINSOCK_TEB_DATA TebData; - - /* Initialize the event handle */ - Status = NtCreateEvent(&EventHandle, - EVENT_ALL_ACCESS, - NULL, - NotificationEvent, - FALSE); - if (!NT_SUCCESS(Status)) return FALSE; - - /* Allocate the thread data */ - TebData = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(WINSOCK_TEB_DATA)); - if (!TebData) return FALSE; - - /* Set it and zero its contents */ - NtCurrentTeb()->WinSockData = TebData; - RtlZeroMemory(TebData, sizeof(WINSOCK_TEB_DATA)); - - /* Set the event handle */ - TebData->EventHandle = EventHandle; - - /* Return success */ - return TRUE; -} - diff --git a/dll/win32/mswsock/mswsock/recvex.c b/dll/win32/mswsock/mswsock/recvex.c index 3e062e90d63..bd1ad2806dc 100644 --- a/dll/win32/mswsock/mswsock/recvex.c +++ b/dll/win32/mswsock/mswsock/recvex.c @@ -12,45 +12,3 @@ /* FUNCTIONS *****************************************************************/ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - diff --git a/dll/win32/mswsock/mswsock/setup.c b/dll/win32/mswsock/mswsock/setup.c index 3e062e90d63..bd1ad2806dc 100644 --- a/dll/win32/mswsock/mswsock/setup.c +++ b/dll/win32/mswsock/mswsock/setup.c @@ -12,45 +12,3 @@ /* FUNCTIONS *****************************************************************/ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - diff --git a/dll/win32/mswsock/mswsock/stubs.c b/dll/win32/mswsock/mswsock/stubs.c index ad110552d1e..2ab9fc7a297 100644 --- a/dll/win32/mswsock/mswsock/stubs.c +++ b/dll/win32/mswsock/mswsock/stubs.c @@ -345,1044 +345,3 @@ NPLoadNameSpaces( return 0; } -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -BOOL -WINAPI -AcceptEx(SOCKET ListenSocket, - SOCKET AcceptSocket, - PVOID OutputBuffer, - DWORD ReceiveDataLength, - DWORD LocalAddressLength, - DWORD RemoteAddressLength, - LPDWORD BytesReceived, - LPOVERLAPPED Overlapped) -{ - OutputDebugStringW(L"AcceptEx is UNIMPLEMENTED\n"); - - return FALSE; -} - -VOID -WINAPI -GetAcceptExSockaddrs(PVOID OutputBuffer, - DWORD ReceiveDataLength, - DWORD LocalAddressLength, - DWORD RemoteAddressLength, - LPSOCKADDR* LocalSockaddr, - LPINT LocalSockaddrLength, - LPSOCKADDR* RemoteSockaddr, - LPINT RemoteSockaddrLength) -{ - OutputDebugStringW(L"GetAcceptExSockaddrs is UNIMPLEMENTED\n"); -} - -INT -WINAPI -GetAddressByNameA(DWORD NameSpace, - LPGUID ServiceType, - LPSTR ServiceName, - LPINT Protocols, - DWORD Resolution, - LPSERVICE_ASYNC_INFO ServiceAsyncInfo, - LPVOID CsaddrBuffer, - LPDWORD BufferLength, - LPSTR AliasBuffer, - LPDWORD AliasBufferLength) -{ - OutputDebugStringW(L"GetAddressByNameA is UNIMPLEMENTED\n"); - - return SOCKET_ERROR; -} - -INT -WINAPI -GetAddressByNameW(DWORD NameSpace, - LPGUID ServiceType, - LPWSTR ServiceName, - LPINT Protocols, - DWORD Resolution, - LPSERVICE_ASYNC_INFO ServiceAsyncInfo, - LPVOID CsaddrBuffer, - LPDWORD BufferLength, - LPWSTR AliasBuffer, - LPDWORD AliasBufferLength) -{ - OutputDebugStringW(L"GetAddressByNameW is UNIMPLEMENTED\n"); - - return SOCKET_ERROR; -} - -INT -WINAPI -GetServiceA(DWORD NameSpace, - LPGUID Guid, - LPSTR ServiceName, - DWORD Properties, - LPVOID Buffer, - LPDWORD BufferSize, - LPSERVICE_ASYNC_INFO ServiceAsyncInfo) -{ - OutputDebugStringW(L"GetServiceA is UNIMPLEMENTED\n"); - - return SOCKET_ERROR; -} - -INT -WINAPI -GetServiceW(DWORD NameSpace, - LPGUID Guid, - LPWSTR ServiceName, - DWORD Properties, - LPVOID Buffer, - LPDWORD BufferSize, - LPSERVICE_ASYNC_INFO ServiceAsyncInfo) -{ - OutputDebugStringW(L"GetServiceW is UNIMPLEMENTED\n"); - - return SOCKET_ERROR; -} - -INT -WINAPI -GetTypeByNameA(LPSTR ServiceName, - LPGUID ServiceType) -{ - OutputDebugStringW(L"GetTypeByNameA is UNIMPLEMENTED\n"); - - return SOCKET_ERROR; -} - -INT -WINAPI -GetTypeByNameW(LPWSTR ServiceName, - LPGUID ServiceType) -{ - OutputDebugStringW(L"GetTypeByNameW is UNIMPLEMENTED\n"); - - return SOCKET_ERROR; -} - -INT -WINAPI -MigrateWinsockConfiguration(DWORD Unknown1, - DWORD Unknown2, - DWORD Unknown3) -{ - OutputDebugStringW(L"MigrateWinsockConfiguration is UNIMPLEMENTED\n"); - - return SOCKET_ERROR; -} - -INT -WINAPI -SetServiceA(DWORD NameSpace, - DWORD Operation, - DWORD Flags, - LPSERVICE_INFOA ServiceInfo, - LPSERVICE_ASYNC_INFO ServiceAsyncInfo, - LPDWORD dwStatusFlags) -{ - OutputDebugStringW(L"SetServiceA is UNIMPLEMENTED\n"); - - return SOCKET_ERROR; -} - -INT -WINAPI -SetServiceW(DWORD NameSpace, - DWORD Operation, - DWORD Flags, - LPSERVICE_INFOW ServiceInfo, - LPSERVICE_ASYNC_INFO ServiceAsyncInfo, - LPDWORD dwStatusFlags) -{ - OutputDebugStringW(L"SetServiceW is UNIMPLEMENTED\n"); - - return SOCKET_ERROR; -} - -int -WINAPI -WSARecvEx(SOCKET Sock, - char *Buf, - int Len, - int *Flags) -{ - OutputDebugStringW(L"WSARecvEx is UNIMPLEMENTED\n"); - - return SOCKET_ERROR; -} - -int -WINAPI -dn_expand(unsigned char *MessagePtr, - unsigned char *EndofMesOrig, - unsigned char *CompDomNam, - unsigned char *ExpandDomNam, - int Length) -{ - OutputDebugStringW(L"dn_expand is UNIMPLEMENTED\n"); - - return SOCKET_ERROR; -} - -struct netent * -WINAPI -getnetbyname(const char *name) -{ - OutputDebugStringW(L"getnetbyname is UNIMPLEMENTED\n"); - - return NULL; -} - -UINT -WINAPI -inet_network(const char *cp) -{ - OutputDebugStringW(L"inet_network is UNIMPLEMENTED\n"); - - return INADDR_NONE; -} - -SOCKET -WINAPI -rcmd(char **AHost, - USHORT InPort, - char *LocUser, - char *RemUser, - char *Cmd, - int *Fd2p) -{ - OutputDebugStringW(L"rcmd is UNIMPLEMENTED\n"); - - return INVALID_SOCKET; -} - -SOCKET -WINAPI -rexec(char **AHost, - int InPort, - char *User, - char *Passwd, - char *Cmd, - int *Fd2p) -{ - OutputDebugStringW(L"rexec is UNIMPLEMENTED\n"); - - return INVALID_SOCKET; -} - -SOCKET -WINAPI -rresvport(int *port) -{ - OutputDebugStringW(L"rresvport is UNIMPLEMENTED\n"); - - return INVALID_SOCKET; -} - -void -WINAPI -s_perror(const char *str) -{ - OutputDebugStringW(L"s_perror is UNIMPLEMENTED\n"); -} - -int -WINAPI -sethostname(char *Name, int NameLen) -{ - OutputDebugStringW(L"sethostname is UNIMPLEMENTED\n"); - - return SOCKET_ERROR; -} - -INT -WINAPI -GetNameByTypeA(LPGUID lpServiceType, LPSTR lpServiceName, DWORD dwNameLength) -{ - OutputDebugStringW(L"GetNameByTypeA is UNIMPLEMENTED\n"); - - return 0; -} - -INT -WINAPI -GetNameByTypeW(LPGUID lpServiceType, LPWSTR lpServiceName, DWORD dwNameLength) -{ - OutputDebugStringW(L"GetNameByTypeW is UNIMPLEMENTED\n"); - - return 0; -} - -VOID -WINAPI -StartWsdpService() -{ - OutputDebugStringW(L"StartWsdpService is UNIMPLEMENTED\n"); -} - -VOID -WINAPI -StopWsdpService() -{ - OutputDebugStringW(L"StopWsdpService is UNIMPLEMENTED\n"); -} - -DWORD -WINAPI -SvchostPushServiceGlobals(DWORD Value) -{ - OutputDebugStringW(L"SvchostPushServiceGlobals is UNIMPLEMENTED\n"); - - return 0; -} - -VOID -WINAPI -ServiceMain(DWORD Unknown1, DWORD Unknown2) -{ - OutputDebugStringW(L"ServiceMain is UNIMPLEMENTED\n"); -} - -INT -WINAPI -EnumProtocolsA(LPINT ProtocolCount, - LPVOID ProtocolBuffer, - LPDWORD BufferLength) -{ - OutputDebugStringW(L"EnumProtocolsA is UNIMPLEMENTED\n"); - - return SOCKET_ERROR; -} - -INT -WINAPI -EnumProtocolsW(LPINT ProtocolCount, - LPVOID ProtocolBuffer, - LPDWORD BufferLength) -{ - OutputDebugStringW(L"EnumProtocolsW is UNIMPLEMENTED\n"); - - return SOCKET_ERROR; -} - -INT -WINAPI -NPLoadNameSpaces( - IN OUT LPDWORD lpdwVersion, - IN OUT LPNS_ROUTINE nsrBuffer, - IN OUT LPDWORD lpdwBufferLength) -{ - OutputDebugStringW(L"NPLoadNameSpaces is UNIMPLEMENTED\n"); - - return 0; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -BOOL -WINAPI -AcceptEx(SOCKET ListenSocket, - SOCKET AcceptSocket, - PVOID OutputBuffer, - DWORD ReceiveDataLength, - DWORD LocalAddressLength, - DWORD RemoteAddressLength, - LPDWORD BytesReceived, - LPOVERLAPPED Overlapped) -{ - OutputDebugStringW(L"AcceptEx is UNIMPLEMENTED\n"); - - return FALSE; -} - -VOID -WINAPI -GetAcceptExSockaddrs(PVOID OutputBuffer, - DWORD ReceiveDataLength, - DWORD LocalAddressLength, - DWORD RemoteAddressLength, - LPSOCKADDR* LocalSockaddr, - LPINT LocalSockaddrLength, - LPSOCKADDR* RemoteSockaddr, - LPINT RemoteSockaddrLength) -{ - OutputDebugStringW(L"GetAcceptExSockaddrs is UNIMPLEMENTED\n"); -} - -INT -WINAPI -GetAddressByNameA(DWORD NameSpace, - LPGUID ServiceType, - LPSTR ServiceName, - LPINT Protocols, - DWORD Resolution, - LPSERVICE_ASYNC_INFO ServiceAsyncInfo, - LPVOID CsaddrBuffer, - LPDWORD BufferLength, - LPSTR AliasBuffer, - LPDWORD AliasBufferLength) -{ - OutputDebugStringW(L"GetAddressByNameA is UNIMPLEMENTED\n"); - - return SOCKET_ERROR; -} - -INT -WINAPI -GetAddressByNameW(DWORD NameSpace, - LPGUID ServiceType, - LPWSTR ServiceName, - LPINT Protocols, - DWORD Resolution, - LPSERVICE_ASYNC_INFO ServiceAsyncInfo, - LPVOID CsaddrBuffer, - LPDWORD BufferLength, - LPWSTR AliasBuffer, - LPDWORD AliasBufferLength) -{ - OutputDebugStringW(L"GetAddressByNameW is UNIMPLEMENTED\n"); - - return SOCKET_ERROR; -} - -INT -WINAPI -GetServiceA(DWORD NameSpace, - LPGUID Guid, - LPSTR ServiceName, - DWORD Properties, - LPVOID Buffer, - LPDWORD BufferSize, - LPSERVICE_ASYNC_INFO ServiceAsyncInfo) -{ - OutputDebugStringW(L"GetServiceA is UNIMPLEMENTED\n"); - - return SOCKET_ERROR; -} - -INT -WINAPI -GetServiceW(DWORD NameSpace, - LPGUID Guid, - LPWSTR ServiceName, - DWORD Properties, - LPVOID Buffer, - LPDWORD BufferSize, - LPSERVICE_ASYNC_INFO ServiceAsyncInfo) -{ - OutputDebugStringW(L"GetServiceW is UNIMPLEMENTED\n"); - - return SOCKET_ERROR; -} - -INT -WINAPI -GetTypeByNameA(LPSTR ServiceName, - LPGUID ServiceType) -{ - OutputDebugStringW(L"GetTypeByNameA is UNIMPLEMENTED\n"); - - return SOCKET_ERROR; -} - -INT -WINAPI -GetTypeByNameW(LPWSTR ServiceName, - LPGUID ServiceType) -{ - OutputDebugStringW(L"GetTypeByNameW is UNIMPLEMENTED\n"); - - return SOCKET_ERROR; -} - -INT -WINAPI -MigrateWinsockConfiguration(DWORD Unknown1, - DWORD Unknown2, - DWORD Unknown3) -{ - OutputDebugStringW(L"MigrateWinsockConfiguration is UNIMPLEMENTED\n"); - - return SOCKET_ERROR; -} - -INT -WINAPI -SetServiceA(DWORD NameSpace, - DWORD Operation, - DWORD Flags, - LPSERVICE_INFOA ServiceInfo, - LPSERVICE_ASYNC_INFO ServiceAsyncInfo, - LPDWORD dwStatusFlags) -{ - OutputDebugStringW(L"SetServiceA is UNIMPLEMENTED\n"); - - return SOCKET_ERROR; -} - -INT -WINAPI -SetServiceW(DWORD NameSpace, - DWORD Operation, - DWORD Flags, - LPSERVICE_INFOW ServiceInfo, - LPSERVICE_ASYNC_INFO ServiceAsyncInfo, - LPDWORD dwStatusFlags) -{ - OutputDebugStringW(L"SetServiceW is UNIMPLEMENTED\n"); - - return SOCKET_ERROR; -} - -int -WINAPI -WSARecvEx(SOCKET Sock, - char *Buf, - int Len, - int *Flags) -{ - OutputDebugStringW(L"WSARecvEx is UNIMPLEMENTED\n"); - - return SOCKET_ERROR; -} - -int -WINAPI -dn_expand(unsigned char *MessagePtr, - unsigned char *EndofMesOrig, - unsigned char *CompDomNam, - unsigned char *ExpandDomNam, - int Length) -{ - OutputDebugStringW(L"dn_expand is UNIMPLEMENTED\n"); - - return SOCKET_ERROR; -} - -struct netent * -WINAPI -getnetbyname(const char *name) -{ - OutputDebugStringW(L"getnetbyname is UNIMPLEMENTED\n"); - - return NULL; -} - -UINT -WINAPI -inet_network(const char *cp) -{ - OutputDebugStringW(L"inet_network is UNIMPLEMENTED\n"); - - return INADDR_NONE; -} - -SOCKET -WINAPI -rcmd(char **AHost, - USHORT InPort, - char *LocUser, - char *RemUser, - char *Cmd, - int *Fd2p) -{ - OutputDebugStringW(L"rcmd is UNIMPLEMENTED\n"); - - return INVALID_SOCKET; -} - -SOCKET -WINAPI -rexec(char **AHost, - int InPort, - char *User, - char *Passwd, - char *Cmd, - int *Fd2p) -{ - OutputDebugStringW(L"rexec is UNIMPLEMENTED\n"); - - return INVALID_SOCKET; -} - -SOCKET -WINAPI -rresvport(int *port) -{ - OutputDebugStringW(L"rresvport is UNIMPLEMENTED\n"); - - return INVALID_SOCKET; -} - -void -WINAPI -s_perror(const char *str) -{ - OutputDebugStringW(L"s_perror is UNIMPLEMENTED\n"); -} - -int -WINAPI -sethostname(char *Name, int NameLen) -{ - OutputDebugStringW(L"sethostname is UNIMPLEMENTED\n"); - - return SOCKET_ERROR; -} - -INT -WINAPI -GetNameByTypeA(LPGUID lpServiceType, LPSTR lpServiceName, DWORD dwNameLength) -{ - OutputDebugStringW(L"GetNameByTypeA is UNIMPLEMENTED\n"); - - return 0; -} - -INT -WINAPI -GetNameByTypeW(LPGUID lpServiceType, LPWSTR lpServiceName, DWORD dwNameLength) -{ - OutputDebugStringW(L"GetNameByTypeW is UNIMPLEMENTED\n"); - - return 0; -} - -VOID -WINAPI -StartWsdpService() -{ - OutputDebugStringW(L"StartWsdpService is UNIMPLEMENTED\n"); -} - -VOID -WINAPI -StopWsdpService() -{ - OutputDebugStringW(L"StopWsdpService is UNIMPLEMENTED\n"); -} - -DWORD -WINAPI -SvchostPushServiceGlobals(DWORD Value) -{ - OutputDebugStringW(L"SvchostPushServiceGlobals is UNIMPLEMENTED\n"); - - return 0; -} - -VOID -WINAPI -ServiceMain(DWORD Unknown1, DWORD Unknown2) -{ - OutputDebugStringW(L"ServiceMain is UNIMPLEMENTED\n"); -} - -INT -WINAPI -EnumProtocolsA(LPINT ProtocolCount, - LPVOID ProtocolBuffer, - LPDWORD BufferLength) -{ - OutputDebugStringW(L"EnumProtocolsA is UNIMPLEMENTED\n"); - - return SOCKET_ERROR; -} - -INT -WINAPI -EnumProtocolsW(LPINT ProtocolCount, - LPVOID ProtocolBuffer, - LPDWORD BufferLength) -{ - OutputDebugStringW(L"EnumProtocolsW is UNIMPLEMENTED\n"); - - return SOCKET_ERROR; -} - -INT -WINAPI -NPLoadNameSpaces( - IN OUT LPDWORD lpdwVersion, - IN OUT LPNS_ROUTINE nsrBuffer, - IN OUT LPDWORD lpdwBufferLength) -{ - OutputDebugStringW(L"NPLoadNameSpaces is UNIMPLEMENTED\n"); - - return 0; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -BOOL -WINAPI -AcceptEx(SOCKET ListenSocket, - SOCKET AcceptSocket, - PVOID OutputBuffer, - DWORD ReceiveDataLength, - DWORD LocalAddressLength, - DWORD RemoteAddressLength, - LPDWORD BytesReceived, - LPOVERLAPPED Overlapped) -{ - OutputDebugStringW(L"AcceptEx is UNIMPLEMENTED\n"); - - return FALSE; -} - -VOID -WINAPI -GetAcceptExSockaddrs(PVOID OutputBuffer, - DWORD ReceiveDataLength, - DWORD LocalAddressLength, - DWORD RemoteAddressLength, - LPSOCKADDR* LocalSockaddr, - LPINT LocalSockaddrLength, - LPSOCKADDR* RemoteSockaddr, - LPINT RemoteSockaddrLength) -{ - OutputDebugStringW(L"GetAcceptExSockaddrs is UNIMPLEMENTED\n"); -} - -INT -WINAPI -GetAddressByNameA(DWORD NameSpace, - LPGUID ServiceType, - LPSTR ServiceName, - LPINT Protocols, - DWORD Resolution, - LPSERVICE_ASYNC_INFO ServiceAsyncInfo, - LPVOID CsaddrBuffer, - LPDWORD BufferLength, - LPSTR AliasBuffer, - LPDWORD AliasBufferLength) -{ - OutputDebugStringW(L"GetAddressByNameA is UNIMPLEMENTED\n"); - - return SOCKET_ERROR; -} - -INT -WINAPI -GetAddressByNameW(DWORD NameSpace, - LPGUID ServiceType, - LPWSTR ServiceName, - LPINT Protocols, - DWORD Resolution, - LPSERVICE_ASYNC_INFO ServiceAsyncInfo, - LPVOID CsaddrBuffer, - LPDWORD BufferLength, - LPWSTR AliasBuffer, - LPDWORD AliasBufferLength) -{ - OutputDebugStringW(L"GetAddressByNameW is UNIMPLEMENTED\n"); - - return SOCKET_ERROR; -} - -INT -WINAPI -GetServiceA(DWORD NameSpace, - LPGUID Guid, - LPSTR ServiceName, - DWORD Properties, - LPVOID Buffer, - LPDWORD BufferSize, - LPSERVICE_ASYNC_INFO ServiceAsyncInfo) -{ - OutputDebugStringW(L"GetServiceA is UNIMPLEMENTED\n"); - - return SOCKET_ERROR; -} - -INT -WINAPI -GetServiceW(DWORD NameSpace, - LPGUID Guid, - LPWSTR ServiceName, - DWORD Properties, - LPVOID Buffer, - LPDWORD BufferSize, - LPSERVICE_ASYNC_INFO ServiceAsyncInfo) -{ - OutputDebugStringW(L"GetServiceW is UNIMPLEMENTED\n"); - - return SOCKET_ERROR; -} - -INT -WINAPI -GetTypeByNameA(LPSTR ServiceName, - LPGUID ServiceType) -{ - OutputDebugStringW(L"GetTypeByNameA is UNIMPLEMENTED\n"); - - return SOCKET_ERROR; -} - -INT -WINAPI -GetTypeByNameW(LPWSTR ServiceName, - LPGUID ServiceType) -{ - OutputDebugStringW(L"GetTypeByNameW is UNIMPLEMENTED\n"); - - return SOCKET_ERROR; -} - -INT -WINAPI -MigrateWinsockConfiguration(DWORD Unknown1, - DWORD Unknown2, - DWORD Unknown3) -{ - OutputDebugStringW(L"MigrateWinsockConfiguration is UNIMPLEMENTED\n"); - - return SOCKET_ERROR; -} - -INT -WINAPI -SetServiceA(DWORD NameSpace, - DWORD Operation, - DWORD Flags, - LPSERVICE_INFOA ServiceInfo, - LPSERVICE_ASYNC_INFO ServiceAsyncInfo, - LPDWORD dwStatusFlags) -{ - OutputDebugStringW(L"SetServiceA is UNIMPLEMENTED\n"); - - return SOCKET_ERROR; -} - -INT -WINAPI -SetServiceW(DWORD NameSpace, - DWORD Operation, - DWORD Flags, - LPSERVICE_INFOW ServiceInfo, - LPSERVICE_ASYNC_INFO ServiceAsyncInfo, - LPDWORD dwStatusFlags) -{ - OutputDebugStringW(L"SetServiceW is UNIMPLEMENTED\n"); - - return SOCKET_ERROR; -} - -int -WINAPI -WSARecvEx(SOCKET Sock, - char *Buf, - int Len, - int *Flags) -{ - OutputDebugStringW(L"WSARecvEx is UNIMPLEMENTED\n"); - - return SOCKET_ERROR; -} - -int -WINAPI -dn_expand(unsigned char *MessagePtr, - unsigned char *EndofMesOrig, - unsigned char *CompDomNam, - unsigned char *ExpandDomNam, - int Length) -{ - OutputDebugStringW(L"dn_expand is UNIMPLEMENTED\n"); - - return SOCKET_ERROR; -} - -struct netent * -WINAPI -getnetbyname(const char *name) -{ - OutputDebugStringW(L"getnetbyname is UNIMPLEMENTED\n"); - - return NULL; -} - -UINT -WINAPI -inet_network(const char *cp) -{ - OutputDebugStringW(L"inet_network is UNIMPLEMENTED\n"); - - return INADDR_NONE; -} - -SOCKET -WINAPI -rcmd(char **AHost, - USHORT InPort, - char *LocUser, - char *RemUser, - char *Cmd, - int *Fd2p) -{ - OutputDebugStringW(L"rcmd is UNIMPLEMENTED\n"); - - return INVALID_SOCKET; -} - -SOCKET -WINAPI -rexec(char **AHost, - int InPort, - char *User, - char *Passwd, - char *Cmd, - int *Fd2p) -{ - OutputDebugStringW(L"rexec is UNIMPLEMENTED\n"); - - return INVALID_SOCKET; -} - -SOCKET -WINAPI -rresvport(int *port) -{ - OutputDebugStringW(L"rresvport is UNIMPLEMENTED\n"); - - return INVALID_SOCKET; -} - -void -WINAPI -s_perror(const char *str) -{ - OutputDebugStringW(L"s_perror is UNIMPLEMENTED\n"); -} - -int -WINAPI -sethostname(char *Name, int NameLen) -{ - OutputDebugStringW(L"sethostname is UNIMPLEMENTED\n"); - - return SOCKET_ERROR; -} - -INT -WINAPI -GetNameByTypeA(LPGUID lpServiceType, LPSTR lpServiceName, DWORD dwNameLength) -{ - OutputDebugStringW(L"GetNameByTypeA is UNIMPLEMENTED\n"); - - return 0; -} - -INT -WINAPI -GetNameByTypeW(LPGUID lpServiceType, LPWSTR lpServiceName, DWORD dwNameLength) -{ - OutputDebugStringW(L"GetNameByTypeW is UNIMPLEMENTED\n"); - - return 0; -} - -VOID -WINAPI -StartWsdpService() -{ - OutputDebugStringW(L"StartWsdpService is UNIMPLEMENTED\n"); -} - -VOID -WINAPI -StopWsdpService() -{ - OutputDebugStringW(L"StopWsdpService is UNIMPLEMENTED\n"); -} - -DWORD -WINAPI -SvchostPushServiceGlobals(DWORD Value) -{ - OutputDebugStringW(L"SvchostPushServiceGlobals is UNIMPLEMENTED\n"); - - return 0; -} - -VOID -WINAPI -ServiceMain(DWORD Unknown1, DWORD Unknown2) -{ - OutputDebugStringW(L"ServiceMain is UNIMPLEMENTED\n"); -} - -INT -WINAPI -EnumProtocolsA(LPINT ProtocolCount, - LPVOID ProtocolBuffer, - LPDWORD BufferLength) -{ - OutputDebugStringW(L"EnumProtocolsA is UNIMPLEMENTED\n"); - - return SOCKET_ERROR; -} - -INT -WINAPI -EnumProtocolsW(LPINT ProtocolCount, - LPVOID ProtocolBuffer, - LPDWORD BufferLength) -{ - OutputDebugStringW(L"EnumProtocolsW is UNIMPLEMENTED\n"); - - return SOCKET_ERROR; -} - -INT -WINAPI -NPLoadNameSpaces( - IN OUT LPDWORD lpdwVersion, - IN OUT LPNS_ROUTINE nsrBuffer, - IN OUT LPDWORD lpdwBufferLength) -{ - OutputDebugStringW(L"NPLoadNameSpaces is UNIMPLEMENTED\n"); - - return 0; -} - diff --git a/dll/win32/mswsock/rnr20/context.c b/dll/win32/mswsock/rnr20/context.c index dfb5c79dde3..f3c17a86c54 100644 --- a/dll/win32/mswsock/rnr20/context.c +++ b/dll/win32/mswsock/rnr20/context.c @@ -160,489 +160,3 @@ RnrCtx_ListCleanup(VOID) ReleaseRnR2Lock(); } -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -LIST_ENTRY ListAnchor; -BOOLEAN g_fRnrLockInit; -CRITICAL_SECTION g_RnrLock; - -#define AcquireRnR2Lock() EnterCriticalSection(&g_RnrLock); -#define ReleaseRnR2Lock() LeaveCriticalSection(&g_RnrLock); - -/* FUNCTIONS *****************************************************************/ - -PRNR_CONTEXT -WSPAPI -RnrCtx_Create(IN HANDLE LookupHandle, - IN LPWSTR ServiceName) -{ - PRNR_CONTEXT RnrContext; - SIZE_T StringSize = 0; - - /* Get the size of the string */ - if (ServiceName) StringSize = wcslen(ServiceName); - - /* Allocate the Context */ - RnrContext = Temp_AllocZero(sizeof(RNR_CONTEXT) + (DWORD)StringSize); - - /* Check that we got one */ - if (RnrContext) - { - /* Set it up */ - RnrContext->RefCount = 2; - RnrContext->Handle = (LookupHandle ? LookupHandle : (HANDLE)RnrContext); - RnrContext->Instance = -1; - RnrContext->Signature = 0xaabbccdd; - wcscpy(RnrContext->ServiceName, ServiceName); - - /* Insert it into the list */ - AcquireRnR2Lock(); - InsertHeadList(&ListAnchor, &RnrContext->ListEntry); - ReleaseRnR2Lock(); - } - - /* Return it */ - return RnrContext; -} - -VOID -WSPAPI -RnrCtx_Release(PRNR_CONTEXT RnrContext) -{ - /* Acquire the lock */ - AcquireRnR2Lock(); - - /* Decrease reference count and check if it's still in use */ - if(!(--RnrContext->RefCount)) - { - /* Remove it from the List */ - RemoveEntryList(&RnrContext->ListEntry); - - /* Release the lock */ - ReleaseRnR2Lock(); - - /* Deallocated any cached Hostent */ - if(RnrContext->CachedSaBlob) SaBlob_Free(RnrContext->CachedSaBlob); - - /* Deallocate the Blob */ - if(RnrContext->CachedBlob.pBlobData) - { - DnsApiFree(RnrContext->CachedBlob.pBlobData); - } - - /* Deallocate the actual context itself */ - DnsApiFree(RnrContext); - } - else - { - /* Release the lock */ - ReleaseRnR2Lock(); - } -} - -PRNR_CONTEXT -WSPAPI -RnrCtx_Get(HANDLE LookupHandle, - DWORD dwControlFlags, - PLONG Instance) -{ - PLIST_ENTRY Entry; - PRNR_CONTEXT RnRContext = NULL; - - /* Acquire the lock */ - AcquireRnR2Lock(); - - /* Loop the RNR Context List */ - for(Entry = ListAnchor.Flink; Entry != &ListAnchor; Entry = Entry->Flink) - { - /* Get the Current RNR Context */ - RnRContext = CONTAINING_RECORD(Entry, RNR_CONTEXT, ListEntry); - - /* Check if it matches the one we got */ - if(RnRContext == (PRNR_CONTEXT)LookupHandle) break; - } - - /* If we found it, mark it in use */ - if(RnRContext) RnRContext->RefCount++; - - /* Increase the Instance and return it */ - *Instance = ++RnRContext->Instance; - - /* If we're flushing the previous one, then bias the Instance by one */ - if(dwControlFlags & LUP_FLUSHPREVIOUS) *Instance = ++RnRContext->Instance; - - /* Release the lock */ - ReleaseRnR2Lock(); - - /* Return the Context */ - return RnRContext; -} - -VOID -WSPAPI -RnrCtx_DecInstance(IN PRNR_CONTEXT RnrContext) -{ - /* Acquire the lock */ - AcquireRnR2Lock(); - - /* Decrease instance count */ - RnrContext->Instance--; - - /* Release the lock */ - ReleaseRnR2Lock(); -} - -VOID -WSPAPI -RnrCtx_ListCleanup(VOID) -{ - PLIST_ENTRY Entry; - - /* Acquire RnR Lock */ - AcquireRnR2Lock(); - - /* Loop the contexts */ - while ((Entry = ListAnchor.Flink) != &ListAnchor) - { - /* Release this context */ - RnrCtx_Release(CONTAINING_RECORD(Entry, RNR_CONTEXT, ListEntry)); - } - - /* Release lock */ - ReleaseRnR2Lock(); -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -LIST_ENTRY ListAnchor; -BOOLEAN g_fRnrLockInit; -CRITICAL_SECTION g_RnrLock; - -#define AcquireRnR2Lock() EnterCriticalSection(&g_RnrLock); -#define ReleaseRnR2Lock() LeaveCriticalSection(&g_RnrLock); - -/* FUNCTIONS *****************************************************************/ - -PRNR_CONTEXT -WSPAPI -RnrCtx_Create(IN HANDLE LookupHandle, - IN LPWSTR ServiceName) -{ - PRNR_CONTEXT RnrContext; - SIZE_T StringSize = 0; - - /* Get the size of the string */ - if (ServiceName) StringSize = wcslen(ServiceName); - - /* Allocate the Context */ - RnrContext = Temp_AllocZero(sizeof(RNR_CONTEXT) + (DWORD)StringSize); - - /* Check that we got one */ - if (RnrContext) - { - /* Set it up */ - RnrContext->RefCount = 2; - RnrContext->Handle = (LookupHandle ? LookupHandle : (HANDLE)RnrContext); - RnrContext->Instance = -1; - RnrContext->Signature = 0xaabbccdd; - wcscpy(RnrContext->ServiceName, ServiceName); - - /* Insert it into the list */ - AcquireRnR2Lock(); - InsertHeadList(&ListAnchor, &RnrContext->ListEntry); - ReleaseRnR2Lock(); - } - - /* Return it */ - return RnrContext; -} - -VOID -WSPAPI -RnrCtx_Release(PRNR_CONTEXT RnrContext) -{ - /* Acquire the lock */ - AcquireRnR2Lock(); - - /* Decrease reference count and check if it's still in use */ - if(!(--RnrContext->RefCount)) - { - /* Remove it from the List */ - RemoveEntryList(&RnrContext->ListEntry); - - /* Release the lock */ - ReleaseRnR2Lock(); - - /* Deallocated any cached Hostent */ - if(RnrContext->CachedSaBlob) SaBlob_Free(RnrContext->CachedSaBlob); - - /* Deallocate the Blob */ - if(RnrContext->CachedBlob.pBlobData) - { - DnsApiFree(RnrContext->CachedBlob.pBlobData); - } - - /* Deallocate the actual context itself */ - DnsApiFree(RnrContext); - } - else - { - /* Release the lock */ - ReleaseRnR2Lock(); - } -} - -PRNR_CONTEXT -WSPAPI -RnrCtx_Get(HANDLE LookupHandle, - DWORD dwControlFlags, - PLONG Instance) -{ - PLIST_ENTRY Entry; - PRNR_CONTEXT RnRContext = NULL; - - /* Acquire the lock */ - AcquireRnR2Lock(); - - /* Loop the RNR Context List */ - for(Entry = ListAnchor.Flink; Entry != &ListAnchor; Entry = Entry->Flink) - { - /* Get the Current RNR Context */ - RnRContext = CONTAINING_RECORD(Entry, RNR_CONTEXT, ListEntry); - - /* Check if it matches the one we got */ - if(RnRContext == (PRNR_CONTEXT)LookupHandle) break; - } - - /* If we found it, mark it in use */ - if(RnRContext) RnRContext->RefCount++; - - /* Increase the Instance and return it */ - *Instance = ++RnRContext->Instance; - - /* If we're flushing the previous one, then bias the Instance by one */ - if(dwControlFlags & LUP_FLUSHPREVIOUS) *Instance = ++RnRContext->Instance; - - /* Release the lock */ - ReleaseRnR2Lock(); - - /* Return the Context */ - return RnRContext; -} - -VOID -WSPAPI -RnrCtx_DecInstance(IN PRNR_CONTEXT RnrContext) -{ - /* Acquire the lock */ - AcquireRnR2Lock(); - - /* Decrease instance count */ - RnrContext->Instance--; - - /* Release the lock */ - ReleaseRnR2Lock(); -} - -VOID -WSPAPI -RnrCtx_ListCleanup(VOID) -{ - PLIST_ENTRY Entry; - - /* Acquire RnR Lock */ - AcquireRnR2Lock(); - - /* Loop the contexts */ - while ((Entry = ListAnchor.Flink) != &ListAnchor) - { - /* Release this context */ - RnrCtx_Release(CONTAINING_RECORD(Entry, RNR_CONTEXT, ListEntry)); - } - - /* Release lock */ - ReleaseRnR2Lock(); -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -LIST_ENTRY ListAnchor; -BOOLEAN g_fRnrLockInit; -CRITICAL_SECTION g_RnrLock; - -#define AcquireRnR2Lock() EnterCriticalSection(&g_RnrLock); -#define ReleaseRnR2Lock() LeaveCriticalSection(&g_RnrLock); - -/* FUNCTIONS *****************************************************************/ - -PRNR_CONTEXT -WSPAPI -RnrCtx_Create(IN HANDLE LookupHandle, - IN LPWSTR ServiceName) -{ - PRNR_CONTEXT RnrContext; - SIZE_T StringSize = 0; - - /* Get the size of the string */ - if (ServiceName) StringSize = wcslen(ServiceName); - - /* Allocate the Context */ - RnrContext = Temp_AllocZero(sizeof(RNR_CONTEXT) + (DWORD)StringSize); - - /* Check that we got one */ - if (RnrContext) - { - /* Set it up */ - RnrContext->RefCount = 2; - RnrContext->Handle = (LookupHandle ? LookupHandle : (HANDLE)RnrContext); - RnrContext->Instance = -1; - RnrContext->Signature = 0xaabbccdd; - wcscpy(RnrContext->ServiceName, ServiceName); - - /* Insert it into the list */ - AcquireRnR2Lock(); - InsertHeadList(&ListAnchor, &RnrContext->ListEntry); - ReleaseRnR2Lock(); - } - - /* Return it */ - return RnrContext; -} - -VOID -WSPAPI -RnrCtx_Release(PRNR_CONTEXT RnrContext) -{ - /* Acquire the lock */ - AcquireRnR2Lock(); - - /* Decrease reference count and check if it's still in use */ - if(!(--RnrContext->RefCount)) - { - /* Remove it from the List */ - RemoveEntryList(&RnrContext->ListEntry); - - /* Release the lock */ - ReleaseRnR2Lock(); - - /* Deallocated any cached Hostent */ - if(RnrContext->CachedSaBlob) SaBlob_Free(RnrContext->CachedSaBlob); - - /* Deallocate the Blob */ - if(RnrContext->CachedBlob.pBlobData) - { - DnsApiFree(RnrContext->CachedBlob.pBlobData); - } - - /* Deallocate the actual context itself */ - DnsApiFree(RnrContext); - } - else - { - /* Release the lock */ - ReleaseRnR2Lock(); - } -} - -PRNR_CONTEXT -WSPAPI -RnrCtx_Get(HANDLE LookupHandle, - DWORD dwControlFlags, - PLONG Instance) -{ - PLIST_ENTRY Entry; - PRNR_CONTEXT RnRContext = NULL; - - /* Acquire the lock */ - AcquireRnR2Lock(); - - /* Loop the RNR Context List */ - for(Entry = ListAnchor.Flink; Entry != &ListAnchor; Entry = Entry->Flink) - { - /* Get the Current RNR Context */ - RnRContext = CONTAINING_RECORD(Entry, RNR_CONTEXT, ListEntry); - - /* Check if it matches the one we got */ - if(RnRContext == (PRNR_CONTEXT)LookupHandle) break; - } - - /* If we found it, mark it in use */ - if(RnRContext) RnRContext->RefCount++; - - /* Increase the Instance and return it */ - *Instance = ++RnRContext->Instance; - - /* If we're flushing the previous one, then bias the Instance by one */ - if(dwControlFlags & LUP_FLUSHPREVIOUS) *Instance = ++RnRContext->Instance; - - /* Release the lock */ - ReleaseRnR2Lock(); - - /* Return the Context */ - return RnRContext; -} - -VOID -WSPAPI -RnrCtx_DecInstance(IN PRNR_CONTEXT RnrContext) -{ - /* Acquire the lock */ - AcquireRnR2Lock(); - - /* Decrease instance count */ - RnrContext->Instance--; - - /* Release the lock */ - ReleaseRnR2Lock(); -} - -VOID -WSPAPI -RnrCtx_ListCleanup(VOID) -{ - PLIST_ENTRY Entry; - - /* Acquire RnR Lock */ - AcquireRnR2Lock(); - - /* Loop the contexts */ - while ((Entry = ListAnchor.Flink) != &ListAnchor) - { - /* Release this context */ - RnrCtx_Release(CONTAINING_RECORD(Entry, RNR_CONTEXT, ListEntry)); - } - - /* Release lock */ - ReleaseRnR2Lock(); -} - diff --git a/dll/win32/mswsock/rnr20/getserv.c b/dll/win32/mswsock/rnr20/getserv.c index 40d1f1bccaf..cbf06b2dc05 100644 --- a/dll/win32/mswsock/rnr20/getserv.c +++ b/dll/win32/mswsock/rnr20/getserv.c @@ -8,33 +8,3 @@ /* INCLUDES ******************************************************************/ #include "msafd.h" -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - diff --git a/dll/win32/mswsock/rnr20/init.c b/dll/win32/mswsock/rnr20/init.c index e313bd18021..1a7a747a538 100644 --- a/dll/win32/mswsock/rnr20/init.c +++ b/dll/win32/mswsock/rnr20/init.c @@ -87,270 +87,3 @@ Rnr_ThreadCleanup(VOID) /* Clean something in the TEB.. */ } -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -BOOLEAN g_fSocketLockInit; -CRITICAL_SECTION RNRPROV_SocketLock; - -/* FUNCTIONS *****************************************************************/ - -VOID -WSPAPI -Rnr_ProcessInit(VOID) -{ - /* Initialize the RnR Locks */ - InitializeCriticalSection(&RNRPROV_SocketLock); - g_fSocketLockInit = TRUE; - InitializeCriticalSection(&g_RnrLock); - g_fRnrLockInit = TRUE; -} - -BOOLEAN -WSPAPI -Rnr_ThreadInit(VOID) -{ - PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; - PRNR_TEB_DATA RnrThreadData; - - /* Check if we have Thread Data */ - if (!ThreadData) - { - /* Initialize the entire DLL */ - if (!MSAFD_SockThreadInitialize()) return FALSE; - } - - /* Allocate the thread data */ - RnrThreadData = RtlAllocateHeap(RtlGetProcessHeap(), - 0, - sizeof(RNR_TEB_DATA)); - if (RnrThreadData) - { - /* Zero it out */ - RtlZeroMemory(RnrThreadData, sizeof(RNR_TEB_DATA)); - - /* Link it */ - ThreadData->RnrThreadData = RnrThreadData; - - /* Return success */ - return TRUE; - } - - /* If we got here, we failed */ - return FALSE; -} - -VOID -WSPAPI -Rnr_ProcessCleanup(VOID) -{ - /* Check if the RnR Lock is initalized */ - if (g_fRnrLockInit) - { - /* It is, so do NSP cleanup */ - Nsp_GlobalCleanup(); - - /* Free the lock if it's still there */ - if (g_fSocketLockInit) DeleteCriticalSection(&g_RnrLock); - g_fRnrLockInit = FALSE; - } - - /* Free the socket lock if it's there */ - if (g_fSocketLockInit) DeleteCriticalSection(&RNRPROV_SocketLock); - g_fRnrLockInit = FALSE; -} - -VOID -WSPAPI -Rnr_ThreadCleanup(VOID) -{ - /* Clean something in the TEB.. */ -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -BOOLEAN g_fSocketLockInit; -CRITICAL_SECTION RNRPROV_SocketLock; - -/* FUNCTIONS *****************************************************************/ - -VOID -WSPAPI -Rnr_ProcessInit(VOID) -{ - /* Initialize the RnR Locks */ - InitializeCriticalSection(&RNRPROV_SocketLock); - g_fSocketLockInit = TRUE; - InitializeCriticalSection(&g_RnrLock); - g_fRnrLockInit = TRUE; -} - -BOOLEAN -WSPAPI -Rnr_ThreadInit(VOID) -{ - PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; - PRNR_TEB_DATA RnrThreadData; - - /* Check if we have Thread Data */ - if (!ThreadData) - { - /* Initialize the entire DLL */ - if (!MSAFD_SockThreadInitialize()) return FALSE; - } - - /* Allocate the thread data */ - RnrThreadData = RtlAllocateHeap(RtlGetProcessHeap(), - 0, - sizeof(RNR_TEB_DATA)); - if (RnrThreadData) - { - /* Zero it out */ - RtlZeroMemory(RnrThreadData, sizeof(RNR_TEB_DATA)); - - /* Link it */ - ThreadData->RnrThreadData = RnrThreadData; - - /* Return success */ - return TRUE; - } - - /* If we got here, we failed */ - return FALSE; -} - -VOID -WSPAPI -Rnr_ProcessCleanup(VOID) -{ - /* Check if the RnR Lock is initalized */ - if (g_fRnrLockInit) - { - /* It is, so do NSP cleanup */ - Nsp_GlobalCleanup(); - - /* Free the lock if it's still there */ - if (g_fSocketLockInit) DeleteCriticalSection(&g_RnrLock); - g_fRnrLockInit = FALSE; - } - - /* Free the socket lock if it's there */ - if (g_fSocketLockInit) DeleteCriticalSection(&RNRPROV_SocketLock); - g_fRnrLockInit = FALSE; -} - -VOID -WSPAPI -Rnr_ThreadCleanup(VOID) -{ - /* Clean something in the TEB.. */ -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -BOOLEAN g_fSocketLockInit; -CRITICAL_SECTION RNRPROV_SocketLock; - -/* FUNCTIONS *****************************************************************/ - -VOID -WSPAPI -Rnr_ProcessInit(VOID) -{ - /* Initialize the RnR Locks */ - InitializeCriticalSection(&RNRPROV_SocketLock); - g_fSocketLockInit = TRUE; - InitializeCriticalSection(&g_RnrLock); - g_fRnrLockInit = TRUE; -} - -BOOLEAN -WSPAPI -Rnr_ThreadInit(VOID) -{ - PWINSOCK_TEB_DATA ThreadData = NtCurrentTeb()->WinSockData; - PRNR_TEB_DATA RnrThreadData; - - /* Check if we have Thread Data */ - if (!ThreadData) - { - /* Initialize the entire DLL */ - if (!MSAFD_SockThreadInitialize()) return FALSE; - } - - /* Allocate the thread data */ - RnrThreadData = RtlAllocateHeap(RtlGetProcessHeap(), - 0, - sizeof(RNR_TEB_DATA)); - if (RnrThreadData) - { - /* Zero it out */ - RtlZeroMemory(RnrThreadData, sizeof(RNR_TEB_DATA)); - - /* Link it */ - ThreadData->RnrThreadData = RnrThreadData; - - /* Return success */ - return TRUE; - } - - /* If we got here, we failed */ - return FALSE; -} - -VOID -WSPAPI -Rnr_ProcessCleanup(VOID) -{ - /* Check if the RnR Lock is initalized */ - if (g_fRnrLockInit) - { - /* It is, so do NSP cleanup */ - Nsp_GlobalCleanup(); - - /* Free the lock if it's still there */ - if (g_fSocketLockInit) DeleteCriticalSection(&g_RnrLock); - g_fRnrLockInit = FALSE; - } - - /* Free the socket lock if it's there */ - if (g_fSocketLockInit) DeleteCriticalSection(&RNRPROV_SocketLock); - g_fRnrLockInit = FALSE; -} - -VOID -WSPAPI -Rnr_ThreadCleanup(VOID) -{ - /* Clean something in the TEB.. */ -} - diff --git a/dll/win32/mswsock/rnr20/logit.c b/dll/win32/mswsock/rnr20/logit.c index 40d1f1bccaf..cbf06b2dc05 100644 --- a/dll/win32/mswsock/rnr20/logit.c +++ b/dll/win32/mswsock/rnr20/logit.c @@ -8,33 +8,3 @@ /* INCLUDES ******************************************************************/ #include "msafd.h" -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - diff --git a/dll/win32/mswsock/rnr20/lookup.c b/dll/win32/mswsock/rnr20/lookup.c index 3f8e7198a6f..44d7b39a985 100644 --- a/dll/win32/mswsock/rnr20/lookup.c +++ b/dll/win32/mswsock/rnr20/lookup.c @@ -357,1080 +357,3 @@ Rnr_NbtResolveAddr(IN IN_ADDR Address) return NULL; } -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -extern DWORD MaskOfGuids; -extern GUID NbtProviderId; - -/* FUNCTIONS *****************************************************************/ - -PDNS_BLOB -WINAPI -Rnr_DoHostnameLookup(IN PRNR_CONTEXT RnrContext) -{ - INT ErrorCode; - LPWSTR LocalName; - PDNS_BLOB Blob = NULL; - - /* Query the Local Hostname */ - DnsQueryConfig(DnsConfigHostName_W, - DNS_CONFIG_FLAG_ALLOC, - NULL, - NULL, - &LocalName, - 0); - if (!LocalName) - { - /* Set error code if we got "Success" */ - ErrorCode = GetLastError(); - if (ErrorCode == NO_ERROR) ErrorCode = ERROR_OUTOFMEMORY; - goto Fail; - } - - /* Create a Blob */ - Blob = SaBlob_Create(0); - if (!Blob) - { - /* Set error code if we got "Success" */ - ErrorCode = GetLastError(); - if (ErrorCode == NO_ERROR) ErrorCode = ERROR_OUTOFMEMORY; - goto Fail; - } - - /* Write the name */ - ErrorCode = SaBlob_WriteNameOrAlias(Blob, LocalName, FALSE); - if (ErrorCode != NO_ERROR) goto Fail; - - /* Free the name and return the blob */ - DnsApiFree(LocalName); - return Blob; - -Fail: - /* Some kind of failure... delete the blob first */ - if (Blob) SaBlob_Free(Blob); - - /* Free the name */ - DnsApiFree(LocalName); - - /* Set the error and fail */ - SetLastError(ErrorCode); - return NULL; -} - -PDNS_BLOB -WINAPI -Rnr_GetHostByAddr(IN PRNR_CONTEXT RnrContext) -{ - BOOLEAN Prolog; - PDNS_BLOB Blob = NULL; - INT ErrorCode = ERROR_SUCCESS; - DWORD ControlFlags = RnrContext->dwControlFlags; - IN6_ADDR Address; - ULONG AddressSize = sizeof(IN6_ADDR); - DWORD AddressFamily = AF_UNSPEC; - WCHAR ReverseAddress[256]; - - /* Enter the RNR Prolog */ - Prolog = RNRPROV_SockEnterApi(); - if (!Prolog) return NULL; - - /* Get an Address */ - Dns_StringToAddressW(&Address, - &AddressSize, - RnrContext->ServiceName, - &AddressFamily); - - /* Check the address family */ - if (AddressFamily == AF_INET) - { - /* Convert it to the IPv4 Reverse Name */ - Dns_Ip4AddressToReverseName_W(ReverseAddress, *(PIN_ADDR)&Address); - } - else if (AddressFamily == AF_INET6) - { - /* Convert it to the IPv6 Reverse Name */ - Dns_Ip6AddressToReverseName_W(ReverseAddress, Address); - } - - /* Do the DNS Lookup */ - Blob = SaBlob_Query(ReverseAddress, - DNS_TYPE_PTR, - (ControlFlags & LUP_FLUSHCACHE) ? - DNS_QUERY_BYPASS_CACHE : - DNS_QUERY_STANDARD, - NULL, - AddressFamily); - if (!Blob) - { - /* If this is IPv4... */ - if (AddressFamily == AF_INET) - { - /* Can we try NBT? */ - if (Rnr_CheckIfUseNbt(RnrContext)) - { - /* Do NBT Resolution */ - Blob = Rnr_NbtResolveAddr(*(PIN_ADDR)&Address); - } - } - - /* Do we still not have a blob? */ - if (!Blob) ErrorCode = WSANO_DATA; - } - - /* Set the error code and return */ - SetLastError(ErrorCode); - return Blob; -} - -PDNS_BLOB -WINAPI -Rnr_DoDnsLookup(IN PRNR_CONTEXT RnrContext) -{ - LPWSTR Name = RnrContext->ServiceName; - LPGUID Guid = &RnrContext->lpServiceClassId; - WORD DnsType; - PVOID ReservedData = NULL; - PVOID *Reserved = NULL; - BOOL DoDnsQuery = TRUE; - BOOL DoNbtQuery = TRUE; - DWORD DnsFlags; - PDNS_BLOB Blob; - IN_ADDR Addr; - - /* Get the DNS Query Type */ - DnsType = GetDnsQueryTypeFromGuid(Guid); - - /* Check the request type */ - if ((DnsType != DNS_TYPE_A) || - (DnsType != DNS_TYPE_ATMA) || - (DnsType != DNS_TYPE_AAAA) || - (DnsType != DNS_TYPE_PTR)) - { - /* Not a sockaddr request, so read the raw data */ - Reserved = &ReservedData; - } - - /* Check the NS request type */ - switch (RnrContext->dwNameSpace) - { - /* Set the DNS flags for a TCP/IP Local Namespace */ - case NS_TCPIP_LOCAL: - DnsFlags = DNS_QUERY_NO_HOSTS_FILE | DNS_QUERY_NO_WIRE_QUERY; - break; - - /* Set the DNS flags for a TCP/IP Hosts Namespace */ - case NS_TCPIP_HOSTS: - DnsFlags = DNS_QUERY_NO_LOCAL_NAME | - DNS_QUERY_NO_WIRE_QUERY | - DNS_QUERY_BYPASS_CACHE; - break; - - /* Default flags for default, DNS or WINS Namespaces */ - case NS_DNS: - case NS_WINS: - default: - DnsFlags = 0; - break; - } - - /* Check if this is a DNS Server lookup or normal host lookup */ - if (!(Name) && - (DnsType != DNS_TYPE_A) && - ((RnrContext->UdpPort == 53) || (RnrContext->TcpPort == 53))) - { - /* This is actually a DNS Server lookup */ - Name = L"..DnsServers"; - DnsFlags = DNS_QUERY_NO_HOSTS_FILE | - DNS_QUERY_NO_WIRE_QUERY | - DNS_QUERY_BYPASS_CACHE; - } - else - { - /* Normal name lookup */ - DnsFlags |= 0x4000000; - - /* Check which Rr Type this request is */ - if (RnrContext->RrType == 0x10000002) - { - /* - * Check if the previous value should be flushed or if this - * is a local lookup. - */ - if ((RnrContext->dwControlFlags & LUP_FLUSHPREVIOUS) && - (RnrContext->LookupFlags & LOCAL)) - { - /* Tell DNS not to use the Hosts file */ - DnsFlags |= DNS_QUERY_NO_HOSTS_FILE; - } - - /* Tell DNS that this is a ... request */ - DnsFlags |= 0x10000000; - } - } - - /* Check if flushing is enabled */ - if (RnrContext->dwControlFlags & LUP_FLUSHCACHE) - { - /* Bypass the Cache */ - DnsFlags |= DNS_QUERY_BYPASS_CACHE; - } - - /* Make sure we are going to to a DNS Query */ - if (DoDnsQuery) - { - /* Do the DNS Query */ - Blob = SaBlob_Query(Name, - DnsType, - DnsFlags, - Reserved, - 0); - - /* Check if we had reserved data */ - if (Reserved == &ReservedData) - { - /* Check if we need to use it */ - if (RnrContext->RnrId) - { - /* FIXME */ - //SaveAnswer( - } - - /* Free it */ - DnsApiFree(ReservedData); - } - } - - /* Ok, did we get a blob? */ - if (Blob) - { - /* We did..does it have not have name yet? */ - if (!Blob->Name) - { - /* It doesn't... was this a Hostname GUID? */ - if (!memcmp(Guid, &HostnameGuid, sizeof(GUID))) - { - /* Did we not get a name? */ - if (Name || *Name) - { - /* Then we must fail this request */ - SaBlob_Free(Blob); - Blob = NULL; - } - } - } - } - else if (DoNbtQuery) - { - /* Is this an IPv4 record? */ - if (DnsType == DNS_TYPE_A) - { - /* Check if we can use NBT, and use NBT to resolve it */ - if (Rnr_CheckIfUseNbt(RnrContext)) Blob = Rnr_NbtResolveName(Name); - } - else if (DnsType == DNS_TYPE_PTR) - { - /* IPv4 reverse address. Convert it */ - if (Dns_Ip4ReverseNameToAddress_W(&Addr, Name)) - { - /* Resolve it */ - Blob = Rnr_NbtResolveAddr(Addr); - } - } - } - - /* Do we not have a blob? Set the error code */ - if (!Blob) SetLastError(WSANO_ADDRESS); - - /* Return the blob */ - return Blob; -} - -BOOLEAN -WINAPI -Rnr_CheckIfUseNbt(PRNR_CONTEXT RnrContext) -{ - /* If an Rr ID was specified, don't use NBT */ - if (RnrContext->RrType) return FALSE; - - /* Check if we have more then one GUID */ - if (MaskOfGuids) - { - /* Compare this guy's GUID with the NBT Provider GUID */ - if (memcmp(&RnrContext->lpProviderId, - &NbtProviderId, - sizeof(GUID))) - { - /* Not NBT Guid */ - return FALSE; - } - } - - /* Is the DNS Namespace valid for NBT? */ - if ((RnrContext->dwNameSpace == NS_ALL) || - (RnrContext->dwNameSpace == NS_NETBT) || - (RnrContext->dwNameSpace == NS_WINS)) - { - /* Use NBT */ - return TRUE; - } - - /* Don't use NBT */ - return FALSE; -} - -PDNS_BLOB -WINAPI -Rnr_NbtResolveName(IN LPWSTR Name) -{ - /* - * Heh...right...NBT lookups...as if! - * Seriously, don't bother -- MS is considering to deprecate this - * in Vista SP1 or Blackcomb. If someone complains about this, please - * instruct them to deposit a very large check in my bank account... - * - AI 03/12/05 - */ - return NULL; -} - -PDNS_BLOB -WINAPI -Rnr_NbtResolveAddr(IN IN_ADDR Address) -{ - /* - * Heh...right...NBT lookups...as if! - * Seriously, don't bother -- MS is considering to deprecate this - * in Vista SP1 or Blackcomb. If someone complains about this, please - * instruct them to deposit a very large check in my bank account... - * - AI 03/12/05 - */ - return NULL; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -extern DWORD MaskOfGuids; -extern GUID NbtProviderId; - -/* FUNCTIONS *****************************************************************/ - -PDNS_BLOB -WINAPI -Rnr_DoHostnameLookup(IN PRNR_CONTEXT RnrContext) -{ - INT ErrorCode; - LPWSTR LocalName; - PDNS_BLOB Blob = NULL; - - /* Query the Local Hostname */ - DnsQueryConfig(DnsConfigHostName_W, - DNS_CONFIG_FLAG_ALLOC, - NULL, - NULL, - &LocalName, - 0); - if (!LocalName) - { - /* Set error code if we got "Success" */ - ErrorCode = GetLastError(); - if (ErrorCode == NO_ERROR) ErrorCode = ERROR_OUTOFMEMORY; - goto Fail; - } - - /* Create a Blob */ - Blob = SaBlob_Create(0); - if (!Blob) - { - /* Set error code if we got "Success" */ - ErrorCode = GetLastError(); - if (ErrorCode == NO_ERROR) ErrorCode = ERROR_OUTOFMEMORY; - goto Fail; - } - - /* Write the name */ - ErrorCode = SaBlob_WriteNameOrAlias(Blob, LocalName, FALSE); - if (ErrorCode != NO_ERROR) goto Fail; - - /* Free the name and return the blob */ - DnsApiFree(LocalName); - return Blob; - -Fail: - /* Some kind of failure... delete the blob first */ - if (Blob) SaBlob_Free(Blob); - - /* Free the name */ - DnsApiFree(LocalName); - - /* Set the error and fail */ - SetLastError(ErrorCode); - return NULL; -} - -PDNS_BLOB -WINAPI -Rnr_GetHostByAddr(IN PRNR_CONTEXT RnrContext) -{ - BOOLEAN Prolog; - PDNS_BLOB Blob = NULL; - INT ErrorCode = ERROR_SUCCESS; - DWORD ControlFlags = RnrContext->dwControlFlags; - IN6_ADDR Address; - ULONG AddressSize = sizeof(IN6_ADDR); - DWORD AddressFamily = AF_UNSPEC; - WCHAR ReverseAddress[256]; - - /* Enter the RNR Prolog */ - Prolog = RNRPROV_SockEnterApi(); - if (!Prolog) return NULL; - - /* Get an Address */ - Dns_StringToAddressW(&Address, - &AddressSize, - RnrContext->ServiceName, - &AddressFamily); - - /* Check the address family */ - if (AddressFamily == AF_INET) - { - /* Convert it to the IPv4 Reverse Name */ - Dns_Ip4AddressToReverseName_W(ReverseAddress, *(PIN_ADDR)&Address); - } - else if (AddressFamily == AF_INET6) - { - /* Convert it to the IPv6 Reverse Name */ - Dns_Ip6AddressToReverseName_W(ReverseAddress, Address); - } - - /* Do the DNS Lookup */ - Blob = SaBlob_Query(ReverseAddress, - DNS_TYPE_PTR, - (ControlFlags & LUP_FLUSHCACHE) ? - DNS_QUERY_BYPASS_CACHE : - DNS_QUERY_STANDARD, - NULL, - AddressFamily); - if (!Blob) - { - /* If this is IPv4... */ - if (AddressFamily == AF_INET) - { - /* Can we try NBT? */ - if (Rnr_CheckIfUseNbt(RnrContext)) - { - /* Do NBT Resolution */ - Blob = Rnr_NbtResolveAddr(*(PIN_ADDR)&Address); - } - } - - /* Do we still not have a blob? */ - if (!Blob) ErrorCode = WSANO_DATA; - } - - /* Set the error code and return */ - SetLastError(ErrorCode); - return Blob; -} - -PDNS_BLOB -WINAPI -Rnr_DoDnsLookup(IN PRNR_CONTEXT RnrContext) -{ - LPWSTR Name = RnrContext->ServiceName; - LPGUID Guid = &RnrContext->lpServiceClassId; - WORD DnsType; - PVOID ReservedData = NULL; - PVOID *Reserved = NULL; - BOOL DoDnsQuery = TRUE; - BOOL DoNbtQuery = TRUE; - DWORD DnsFlags; - PDNS_BLOB Blob; - IN_ADDR Addr; - - /* Get the DNS Query Type */ - DnsType = GetDnsQueryTypeFromGuid(Guid); - - /* Check the request type */ - if ((DnsType != DNS_TYPE_A) || - (DnsType != DNS_TYPE_ATMA) || - (DnsType != DNS_TYPE_AAAA) || - (DnsType != DNS_TYPE_PTR)) - { - /* Not a sockaddr request, so read the raw data */ - Reserved = &ReservedData; - } - - /* Check the NS request type */ - switch (RnrContext->dwNameSpace) - { - /* Set the DNS flags for a TCP/IP Local Namespace */ - case NS_TCPIP_LOCAL: - DnsFlags = DNS_QUERY_NO_HOSTS_FILE | DNS_QUERY_NO_WIRE_QUERY; - break; - - /* Set the DNS flags for a TCP/IP Hosts Namespace */ - case NS_TCPIP_HOSTS: - DnsFlags = DNS_QUERY_NO_LOCAL_NAME | - DNS_QUERY_NO_WIRE_QUERY | - DNS_QUERY_BYPASS_CACHE; - break; - - /* Default flags for default, DNS or WINS Namespaces */ - case NS_DNS: - case NS_WINS: - default: - DnsFlags = 0; - break; - } - - /* Check if this is a DNS Server lookup or normal host lookup */ - if (!(Name) && - (DnsType != DNS_TYPE_A) && - ((RnrContext->UdpPort == 53) || (RnrContext->TcpPort == 53))) - { - /* This is actually a DNS Server lookup */ - Name = L"..DnsServers"; - DnsFlags = DNS_QUERY_NO_HOSTS_FILE | - DNS_QUERY_NO_WIRE_QUERY | - DNS_QUERY_BYPASS_CACHE; - } - else - { - /* Normal name lookup */ - DnsFlags |= 0x4000000; - - /* Check which Rr Type this request is */ - if (RnrContext->RrType == 0x10000002) - { - /* - * Check if the previous value should be flushed or if this - * is a local lookup. - */ - if ((RnrContext->dwControlFlags & LUP_FLUSHPREVIOUS) && - (RnrContext->LookupFlags & LOCAL)) - { - /* Tell DNS not to use the Hosts file */ - DnsFlags |= DNS_QUERY_NO_HOSTS_FILE; - } - - /* Tell DNS that this is a ... request */ - DnsFlags |= 0x10000000; - } - } - - /* Check if flushing is enabled */ - if (RnrContext->dwControlFlags & LUP_FLUSHCACHE) - { - /* Bypass the Cache */ - DnsFlags |= DNS_QUERY_BYPASS_CACHE; - } - - /* Make sure we are going to to a DNS Query */ - if (DoDnsQuery) - { - /* Do the DNS Query */ - Blob = SaBlob_Query(Name, - DnsType, - DnsFlags, - Reserved, - 0); - - /* Check if we had reserved data */ - if (Reserved == &ReservedData) - { - /* Check if we need to use it */ - if (RnrContext->RnrId) - { - /* FIXME */ - //SaveAnswer( - } - - /* Free it */ - DnsApiFree(ReservedData); - } - } - - /* Ok, did we get a blob? */ - if (Blob) - { - /* We did..does it have not have name yet? */ - if (!Blob->Name) - { - /* It doesn't... was this a Hostname GUID? */ - if (!memcmp(Guid, &HostnameGuid, sizeof(GUID))) - { - /* Did we not get a name? */ - if (Name || *Name) - { - /* Then we must fail this request */ - SaBlob_Free(Blob); - Blob = NULL; - } - } - } - } - else if (DoNbtQuery) - { - /* Is this an IPv4 record? */ - if (DnsType == DNS_TYPE_A) - { - /* Check if we can use NBT, and use NBT to resolve it */ - if (Rnr_CheckIfUseNbt(RnrContext)) Blob = Rnr_NbtResolveName(Name); - } - else if (DnsType == DNS_TYPE_PTR) - { - /* IPv4 reverse address. Convert it */ - if (Dns_Ip4ReverseNameToAddress_W(&Addr, Name)) - { - /* Resolve it */ - Blob = Rnr_NbtResolveAddr(Addr); - } - } - } - - /* Do we not have a blob? Set the error code */ - if (!Blob) SetLastError(WSANO_ADDRESS); - - /* Return the blob */ - return Blob; -} - -BOOLEAN -WINAPI -Rnr_CheckIfUseNbt(PRNR_CONTEXT RnrContext) -{ - /* If an Rr ID was specified, don't use NBT */ - if (RnrContext->RrType) return FALSE; - - /* Check if we have more then one GUID */ - if (MaskOfGuids) - { - /* Compare this guy's GUID with the NBT Provider GUID */ - if (memcmp(&RnrContext->lpProviderId, - &NbtProviderId, - sizeof(GUID))) - { - /* Not NBT Guid */ - return FALSE; - } - } - - /* Is the DNS Namespace valid for NBT? */ - if ((RnrContext->dwNameSpace == NS_ALL) || - (RnrContext->dwNameSpace == NS_NETBT) || - (RnrContext->dwNameSpace == NS_WINS)) - { - /* Use NBT */ - return TRUE; - } - - /* Don't use NBT */ - return FALSE; -} - -PDNS_BLOB -WINAPI -Rnr_NbtResolveName(IN LPWSTR Name) -{ - /* - * Heh...right...NBT lookups...as if! - * Seriously, don't bother -- MS is considering to deprecate this - * in Vista SP1 or Blackcomb. If someone complains about this, please - * instruct them to deposit a very large check in my bank account... - * - AI 03/12/05 - */ - return NULL; -} - -PDNS_BLOB -WINAPI -Rnr_NbtResolveAddr(IN IN_ADDR Address) -{ - /* - * Heh...right...NBT lookups...as if! - * Seriously, don't bother -- MS is considering to deprecate this - * in Vista SP1 or Blackcomb. If someone complains about this, please - * instruct them to deposit a very large check in my bank account... - * - AI 03/12/05 - */ - return NULL; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -extern DWORD MaskOfGuids; -extern GUID NbtProviderId; - -/* FUNCTIONS *****************************************************************/ - -PDNS_BLOB -WINAPI -Rnr_DoHostnameLookup(IN PRNR_CONTEXT RnrContext) -{ - INT ErrorCode; - LPWSTR LocalName; - PDNS_BLOB Blob = NULL; - - /* Query the Local Hostname */ - DnsQueryConfig(DnsConfigHostName_W, - DNS_CONFIG_FLAG_ALLOC, - NULL, - NULL, - &LocalName, - 0); - if (!LocalName) - { - /* Set error code if we got "Success" */ - ErrorCode = GetLastError(); - if (ErrorCode == NO_ERROR) ErrorCode = ERROR_OUTOFMEMORY; - goto Fail; - } - - /* Create a Blob */ - Blob = SaBlob_Create(0); - if (!Blob) - { - /* Set error code if we got "Success" */ - ErrorCode = GetLastError(); - if (ErrorCode == NO_ERROR) ErrorCode = ERROR_OUTOFMEMORY; - goto Fail; - } - - /* Write the name */ - ErrorCode = SaBlob_WriteNameOrAlias(Blob, LocalName, FALSE); - if (ErrorCode != NO_ERROR) goto Fail; - - /* Free the name and return the blob */ - DnsApiFree(LocalName); - return Blob; - -Fail: - /* Some kind of failure... delete the blob first */ - if (Blob) SaBlob_Free(Blob); - - /* Free the name */ - DnsApiFree(LocalName); - - /* Set the error and fail */ - SetLastError(ErrorCode); - return NULL; -} - -PDNS_BLOB -WINAPI -Rnr_GetHostByAddr(IN PRNR_CONTEXT RnrContext) -{ - BOOLEAN Prolog; - PDNS_BLOB Blob = NULL; - INT ErrorCode = ERROR_SUCCESS; - DWORD ControlFlags = RnrContext->dwControlFlags; - IN6_ADDR Address; - ULONG AddressSize = sizeof(IN6_ADDR); - DWORD AddressFamily = AF_UNSPEC; - WCHAR ReverseAddress[256]; - - /* Enter the RNR Prolog */ - Prolog = RNRPROV_SockEnterApi(); - if (!Prolog) return NULL; - - /* Get an Address */ - Dns_StringToAddressW(&Address, - &AddressSize, - RnrContext->ServiceName, - &AddressFamily); - - /* Check the address family */ - if (AddressFamily == AF_INET) - { - /* Convert it to the IPv4 Reverse Name */ - Dns_Ip4AddressToReverseName_W(ReverseAddress, *(PIN_ADDR)&Address); - } - else if (AddressFamily == AF_INET6) - { - /* Convert it to the IPv6 Reverse Name */ - Dns_Ip6AddressToReverseName_W(ReverseAddress, Address); - } - - /* Do the DNS Lookup */ - Blob = SaBlob_Query(ReverseAddress, - DNS_TYPE_PTR, - (ControlFlags & LUP_FLUSHCACHE) ? - DNS_QUERY_BYPASS_CACHE : - DNS_QUERY_STANDARD, - NULL, - AddressFamily); - if (!Blob) - { - /* If this is IPv4... */ - if (AddressFamily == AF_INET) - { - /* Can we try NBT? */ - if (Rnr_CheckIfUseNbt(RnrContext)) - { - /* Do NBT Resolution */ - Blob = Rnr_NbtResolveAddr(*(PIN_ADDR)&Address); - } - } - - /* Do we still not have a blob? */ - if (!Blob) ErrorCode = WSANO_DATA; - } - - /* Set the error code and return */ - SetLastError(ErrorCode); - return Blob; -} - -PDNS_BLOB -WINAPI -Rnr_DoDnsLookup(IN PRNR_CONTEXT RnrContext) -{ - LPWSTR Name = RnrContext->ServiceName; - LPGUID Guid = &RnrContext->lpServiceClassId; - WORD DnsType; - PVOID ReservedData = NULL; - PVOID *Reserved = NULL; - BOOL DoDnsQuery = TRUE; - BOOL DoNbtQuery = TRUE; - DWORD DnsFlags; - PDNS_BLOB Blob; - IN_ADDR Addr; - - /* Get the DNS Query Type */ - DnsType = GetDnsQueryTypeFromGuid(Guid); - - /* Check the request type */ - if ((DnsType != DNS_TYPE_A) || - (DnsType != DNS_TYPE_ATMA) || - (DnsType != DNS_TYPE_AAAA) || - (DnsType != DNS_TYPE_PTR)) - { - /* Not a sockaddr request, so read the raw data */ - Reserved = &ReservedData; - } - - /* Check the NS request type */ - switch (RnrContext->dwNameSpace) - { - /* Set the DNS flags for a TCP/IP Local Namespace */ - case NS_TCPIP_LOCAL: - DnsFlags = DNS_QUERY_NO_HOSTS_FILE | DNS_QUERY_NO_WIRE_QUERY; - break; - - /* Set the DNS flags for a TCP/IP Hosts Namespace */ - case NS_TCPIP_HOSTS: - DnsFlags = DNS_QUERY_NO_LOCAL_NAME | - DNS_QUERY_NO_WIRE_QUERY | - DNS_QUERY_BYPASS_CACHE; - break; - - /* Default flags for default, DNS or WINS Namespaces */ - case NS_DNS: - case NS_WINS: - default: - DnsFlags = 0; - break; - } - - /* Check if this is a DNS Server lookup or normal host lookup */ - if (!(Name) && - (DnsType != DNS_TYPE_A) && - ((RnrContext->UdpPort == 53) || (RnrContext->TcpPort == 53))) - { - /* This is actually a DNS Server lookup */ - Name = L"..DnsServers"; - DnsFlags = DNS_QUERY_NO_HOSTS_FILE | - DNS_QUERY_NO_WIRE_QUERY | - DNS_QUERY_BYPASS_CACHE; - } - else - { - /* Normal name lookup */ - DnsFlags |= 0x4000000; - - /* Check which Rr Type this request is */ - if (RnrContext->RrType == 0x10000002) - { - /* - * Check if the previous value should be flushed or if this - * is a local lookup. - */ - if ((RnrContext->dwControlFlags & LUP_FLUSHPREVIOUS) && - (RnrContext->LookupFlags & LOCAL)) - { - /* Tell DNS not to use the Hosts file */ - DnsFlags |= DNS_QUERY_NO_HOSTS_FILE; - } - - /* Tell DNS that this is a ... request */ - DnsFlags |= 0x10000000; - } - } - - /* Check if flushing is enabled */ - if (RnrContext->dwControlFlags & LUP_FLUSHCACHE) - { - /* Bypass the Cache */ - DnsFlags |= DNS_QUERY_BYPASS_CACHE; - } - - /* Make sure we are going to to a DNS Query */ - if (DoDnsQuery) - { - /* Do the DNS Query */ - Blob = SaBlob_Query(Name, - DnsType, - DnsFlags, - Reserved, - 0); - - /* Check if we had reserved data */ - if (Reserved == &ReservedData) - { - /* Check if we need to use it */ - if (RnrContext->RnrId) - { - /* FIXME */ - //SaveAnswer( - } - - /* Free it */ - DnsApiFree(ReservedData); - } - } - - /* Ok, did we get a blob? */ - if (Blob) - { - /* We did..does it have not have name yet? */ - if (!Blob->Name) - { - /* It doesn't... was this a Hostname GUID? */ - if (!memcmp(Guid, &HostnameGuid, sizeof(GUID))) - { - /* Did we not get a name? */ - if (Name || *Name) - { - /* Then we must fail this request */ - SaBlob_Free(Blob); - Blob = NULL; - } - } - } - } - else if (DoNbtQuery) - { - /* Is this an IPv4 record? */ - if (DnsType == DNS_TYPE_A) - { - /* Check if we can use NBT, and use NBT to resolve it */ - if (Rnr_CheckIfUseNbt(RnrContext)) Blob = Rnr_NbtResolveName(Name); - } - else if (DnsType == DNS_TYPE_PTR) - { - /* IPv4 reverse address. Convert it */ - if (Dns_Ip4ReverseNameToAddress_W(&Addr, Name)) - { - /* Resolve it */ - Blob = Rnr_NbtResolveAddr(Addr); - } - } - } - - /* Do we not have a blob? Set the error code */ - if (!Blob) SetLastError(WSANO_ADDRESS); - - /* Return the blob */ - return Blob; -} - -BOOLEAN -WINAPI -Rnr_CheckIfUseNbt(PRNR_CONTEXT RnrContext) -{ - /* If an Rr ID was specified, don't use NBT */ - if (RnrContext->RrType) return FALSE; - - /* Check if we have more then one GUID */ - if (MaskOfGuids) - { - /* Compare this guy's GUID with the NBT Provider GUID */ - if (memcmp(&RnrContext->lpProviderId, - &NbtProviderId, - sizeof(GUID))) - { - /* Not NBT Guid */ - return FALSE; - } - } - - /* Is the DNS Namespace valid for NBT? */ - if ((RnrContext->dwNameSpace == NS_ALL) || - (RnrContext->dwNameSpace == NS_NETBT) || - (RnrContext->dwNameSpace == NS_WINS)) - { - /* Use NBT */ - return TRUE; - } - - /* Don't use NBT */ - return FALSE; -} - -PDNS_BLOB -WINAPI -Rnr_NbtResolveName(IN LPWSTR Name) -{ - /* - * Heh...right...NBT lookups...as if! - * Seriously, don't bother -- MS is considering to deprecate this - * in Vista SP1 or Blackcomb. If someone complains about this, please - * instruct them to deposit a very large check in my bank account... - * - AI 03/12/05 - */ - return NULL; -} - -PDNS_BLOB -WINAPI -Rnr_NbtResolveAddr(IN IN_ADDR Address) -{ - /* - * Heh...right...NBT lookups...as if! - * Seriously, don't bother -- MS is considering to deprecate this - * in Vista SP1 or Blackcomb. If someone complains about this, please - * instruct them to deposit a very large check in my bank account... - * - AI 03/12/05 - */ - return NULL; -} - diff --git a/dll/win32/mswsock/rnr20/nbt.c b/dll/win32/mswsock/rnr20/nbt.c index 3e062e90d63..bd1ad2806dc 100644 --- a/dll/win32/mswsock/rnr20/nbt.c +++ b/dll/win32/mswsock/rnr20/nbt.c @@ -12,45 +12,3 @@ /* FUNCTIONS *****************************************************************/ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - diff --git a/dll/win32/mswsock/rnr20/nsp.c b/dll/win32/mswsock/rnr20/nsp.c index 7c39fdad843..d5338e20a2a 100644 --- a/dll/win32/mswsock/rnr20/nsp.c +++ b/dll/win32/mswsock/rnr20/nsp.c @@ -942,2835 +942,3 @@ Quickie: return ErrorCode; } -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -#define ALL_LUP_FLAGS (0x0BFFF) - -/* DATA **********************************************************************/ - -LPWSTR g_pszHostName; -LPWSTR g_pszHostFqdn; -LONG g_NspRefCount; -GUID NbtProviderId = {0}; -GUID DNSProviderId = {0}; -DWORD MaskOfGuids; - -NSP_ROUTINE g_NspVector = {sizeof(NSP_ROUTINE), - 1, - 1, - Dns_NSPCleanup, - Dns_NSPLookupServiceBegin, - Dns_NSPLookupServiceNext, - Dns_NSPLookupServiceEnd, - Dns_NSPSetService, - Dns_NSPInstallServiceClass, - Dns_NSPRemoveServiceClass, - Dns_NSPGetServiceClassInfo}; - -/* FUNCTIONS *****************************************************************/ - -INT -WINAPI -Dns_NSPStartup(IN LPGUID lpProviderId, - IN OUT LPNSP_ROUTINE lpsnpRoutines) -{ - INT ErrorCode; - BOOLEAN Prolog; - - /* Validate the size */ - if (lpsnpRoutines->cbSize != sizeof(NSP_ROUTINE)) - { - /* Fail */ - SetLastError(WSAEINVALIDPROCTABLE); - return SOCKET_ERROR; - } - - /* Enter the prolog */ - Prolog = RNRPROV_SockEnterApi(); - if (Prolog) - { - /* Increase our reference count */ - InterlockedIncrement(&g_NspRefCount); - - /* Check if we don't have the hostname */ - if (!g_pszHostName) - { - /* Query it from DNS */ - DnsQueryConfig(DnsConfigHostName_W, - DNS_CONFIG_FLAG_ALLOC, - NULL, - NULL, - &g_pszHostName, - 0); - } - - /* Check if we have a hostname now, but not a Fully-Qualified Domain */ - if (g_pszHostName && !(g_pszHostFqdn)) - { - /* Get the domain from DNS */ - DnsQueryConfig(DnsConfigFullHostName_W, - DNS_CONFIG_FLAG_ALLOC, - NULL, - NULL, - &g_pszHostFqdn, - 0); - } - - /* If we don't have both of them, then set error */ - if (!(g_pszHostName) || !(g_pszHostFqdn)) ErrorCode = SOCKET_ERROR; - } - - /* Check if the Prolog or DNS Local Queries failed */ - if (!(Prolog) || (ErrorCode != NO_ERROR)) - { - /* Fail */ - SetLastError(WSASYSNOTREADY); - return SOCKET_ERROR; - } - - /* Copy the Routines */ - RtlMoveMemory(lpsnpRoutines, &g_NspVector, sizeof(NSP_ROUTINE)); - - /* Check if this is NBT or DNS */ - if (!memcmp(lpProviderId, &NbtProviderId, sizeof(GUID))) - { - /* Enable the NBT Mask */ - MaskOfGuids |= NBT_MASK; - } - else if (!memcmp(lpProviderId, &DNSProviderId, sizeof(GUID))) - { - /* Enable the DNS Mask */ - MaskOfGuids |= DNS_MASK; - } - - /* Return success */ - return NO_ERROR; -} - -VOID -WSPAPI -Nsp_GlobalCleanup(VOID) -{ - /* Cleanup the RnR Contexts */ - RnrCtx_ListCleanup(); - - /* Free the hostnames, if we have them */ - if (g_pszHostName) DnsApiFree(g_pszHostName); - if (g_pszHostFqdn) DnsApiFree(g_pszHostFqdn); - g_pszHostFqdn = g_pszHostName = NULL; -} - -INT -WINAPI -NSPStartup(IN LPGUID lpProviderId, - IN OUT LPNSP_ROUTINE lpsnpRoutines) -{ - INT ErrorCode; - - /* Initialize the DLL */ - ErrorCode = MSWSOCK_Initialize(); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - SetLastError(WSANOTINITIALISED); - return SOCKET_ERROR; - } - - /* Check if this is Winsock Mobile or DNS */ - if (!memcmp(lpProviderId, &gNLANamespaceGuid, sizeof(GUID))) - { - /* Initialize WSM */ - return WSM_NSPStartup(lpProviderId, lpsnpRoutines); - } - - /* Initialize DNS */ - return Dns_NSPStartup(lpProviderId, lpsnpRoutines); -} - -INT -WINAPI -Dns_NSPCleanup(IN LPGUID lpProviderId) -{ - /* Decrement our reference count and do global cleanup if it's reached 0 */ - if (!(InterlockedDecrement(&g_NspRefCount))) Nsp_GlobalCleanup(); - - /* Return success */ - return NO_ERROR; -} - -INT -WINAPI -Dns_NSPSetService(IN LPGUID lpProviderId, - IN LPWSASERVICECLASSINFOW lpServiceClassInfo, - IN LPWSAQUERYSETW lpqsRegInfo, - IN WSAESETSERVICEOP essOperation, - IN DWORD dwControlFlags) -{ - /* Unlike NLA, DNS Services cannot be dynmically modified */ - SetLastError(ERROR_NOT_SUPPORTED); - return SOCKET_ERROR; -} - -INT -WINAPI -Dns_NSPInstallServiceClass(IN LPGUID lpProviderId, - IN LPWSASERVICECLASSINFOW lpServiceClassInfo) -{ - /* Unlike NLA, DNS Services cannot be dynmically modified */ - SetLastError(WSAEOPNOTSUPP); - return SOCKET_ERROR; -}; - -INT -WINAPI -Dns_NSPRemoveServiceClass(IN LPGUID lpProviderId, - IN LPGUID lpServiceCallId) -{ - /* Unlike NLA, DNS Services cannot be dynmically modified */ - SetLastError(WSAEOPNOTSUPP); - return SOCKET_ERROR; -} -INT -WINAPI -Dns_NSPGetServiceClassInfo(IN LPGUID lpProviderId, - IN OUT LPDWORD lpdwBufSize, - IN OUT LPWSASERVICECLASSINFOW lpServiceClassInfo) -{ - /* Unlike NLA, DNS Services cannot be dynmically modified */ - SetLastError(WSAEOPNOTSUPP); - return SOCKET_ERROR; -} - -INT -WINAPI -Dns_NSPLookupServiceEnd(IN HANDLE hLookup) -{ - PRNR_CONTEXT RnrContext; - - /* Get this handle's context */ - RnrContext = RnrCtx_Get(hLookup, 0, NULL); - - /* Mark it as completed */ - RnrContext->LookupFlags |= DONE; - - /* Dereference it once for our _Get */ - RnrCtx_Release(RnrContext); - - /* And once last to delete it */ - RnrCtx_Release(RnrContext); - - /* return */ - return NO_ERROR; -} - -INT -WINAPI -rnr_IdForGuid(IN LPGUID Guid) -{ - - if (memcmp(Guid, &InetHostName, sizeof(GUID))) return 0x10000002; - if (memcmp(Guid, &Ipv6Guid, sizeof(GUID))) return 0x10000023; - if (memcmp(Guid, &HostnameGuid, sizeof(GUID))) return 0x1; - if (memcmp(Guid, &AddressGuid, sizeof(GUID))) return 0x80000000; - if (memcmp(Guid, &IANAGuid, sizeof(GUID))) return 0x2; - if IS_SVCID_DNS(Guid) return 0x5000000; - if IS_SVCID_TCP(Guid) return 0x1000000; - if IS_SVCID_UDP(Guid) return 0x2000000; - return 0; -} - -PVOID -WSPAPI -FlatBuf_ReserveAlignDword(IN PFLATBUFF FlatBuffer, - IN ULONG Size) -{ - /* Let DNSLIB do the grunt work */ - return FlatBuf_Arg_Reserve((PVOID)FlatBuffer->BufferPos, - &FlatBuffer->BufferFreeSize, - Size, - sizeof(PVOID)); -} - -PVOID -WSPAPI -FlatBuf_WriteString(IN PFLATBUFF FlatBuffer, - IN PVOID String, - IN BOOLEAN IsUnicode) -{ - /* Let DNSLIB do the grunt work */ - return FlatBuf_Arg_WriteString((PVOID)FlatBuffer->BufferPos, - &FlatBuffer->BufferFreeSize, - String, - IsUnicode); -} - -PVOID -WSPAPI -FlatBuf_CopyMemory(IN PFLATBUFF FlatBuffer, - IN PVOID Buffer, - IN ULONG Size, - IN ULONG Align) -{ - /* Let DNSLIB do the grunt work */ - return FlatBuf_Arg_CopyMemory((PVOID)FlatBuffer->BufferPos, - &FlatBuffer->BufferFreeSize, - Buffer, - Size, - Align); -} - -INT -WINAPI -Dns_NSPLookupServiceBegin(LPGUID lpProviderId, - LPWSAQUERYSETW lpqsRestrictions, - LPWSASERVICECLASSINFOW lpServiceClassInfo, - DWORD dwControlFlags, - LPHANDLE lphLookup) -{ - INT ErrorCode = SOCKET_ERROR; - PWCHAR ServiceName = lpqsRestrictions->lpszServiceInstanceName; - LPGUID ServiceClassId; - INT RnrId; - ULONG LookupFlags = 0; - BOOL NameRequested = FALSE; - WCHAR StringBuffer[48]; - ULONG i; - DWORD LocalProtocols; - ULONG ProtocolFlags; - PSERVENT LookupServent; - DWORD UdpPort, TcpPort; - PRNR_CONTEXT RnrContext; - PSOCKADDR_IN ReverseSock; - - /* Check if the Size isn't weird */ - if(lpqsRestrictions->dwSize < sizeof(WSAQUERYSETW)) - { - ErrorCode = WSAEFAULT; - goto Quickie; - } - - /* Get the GUID */ - ServiceClassId = lpqsRestrictions->lpServiceClassId; - if(!ServiceClassId) - { - /* No GUID, fail */ - ErrorCode = WSA_INVALID_PARAMETER; - goto Quickie; - } - - /* Get the RNR ID */ - RnrId = rnr_IdForGuid(ServiceClassId); - - /* Make sure that the control flags are valid */ - if ((dwControlFlags & ~ALL_LUP_FLAGS) || - ((dwControlFlags & (LUP_CONTAINERS | LUP_NOCONTAINERS)) == - (LUP_CONTAINERS | LUP_NOCONTAINERS))) - { - /* Either non-recognized flags or invalid combos were passed */ - ErrorCode = WSA_INVALID_PARAMETER; - goto Quickie; - } - - /* Make sure that we have no context, and that LUP_CONTAINERS is not on */ - if(((lpqsRestrictions->lpszContext) && - (*lpqsRestrictions->lpszContext) && - (wcscmp(lpqsRestrictions->lpszContext, L"\\"))) || - (dwControlFlags & LUP_CONTAINERS)) - { - /* We don't support contexts or LUP_CONTAINERS */ - ErrorCode = WSANO_DATA; - goto Quickie; - } - - /* Is this a Reverse Lookup? */ - if (RnrId == 0x80000000) - { - /* Remember for later */ - LookupFlags = REVERSE; - } - else - { - /* Is this a IANA Lookup? */ - if (RnrId == 0x2) - { - /* Mask out this flag since it's of no use now */ - dwControlFlags &= ~(LUP_RETURN_ADDR); - - /* This is a IANA lookup, remember for later */ - LookupFlags |= IANA; - } - - /* Check if we need a name or not */ - if ((RnrId == 0x1) || - (RnrId == 0x10000002) || - (RnrId == 0x10000023) || - (RnrId == 0x10000022)) - { - /* We do */ - NameRequested = TRUE; - } - } - - /* Final check to make sure if we need a name or not */ - if (RnrId & 0x3000000) NameRequested = TRUE; - - /* No Service Name was specified */ - if(!(ServiceName) || !(*ServiceName)) - { - /* - * A name was requested but no Service Name was given, - * so this is a local lookup - */ - if(NameRequested) - { - /* A local Lookup */ - LookupFlags |= LOCAL; - ServiceName = L""; - } - else if((LookupFlags & REVERSE) && - (lpqsRestrictions->lpcsaBuffer) && - (lpqsRestrictions->dwNumberOfCsAddrs == 1)) - { - /* Reverse lookup, make sure a CS Address is there */ - ReverseSock = (struct sockaddr_in*) - lpqsRestrictions->lpcsaBuffer->RemoteAddr.lpSockaddr; - - /* Convert address to Unicode */ - MultiByteToWideChar(CP_ACP, - 0, - inet_ntoa(ReverseSock->sin_addr), - -1, - StringBuffer, - 16); - - /* Set it as the new name */ - ServiceName = StringBuffer; - } - else - { - /* We can't do anything without a service name at this point */ - ErrorCode = WSA_INVALID_PARAMETER; - goto Quickie; - } - } - else if(NameRequested) - { - /* Check for meaningful DNS Names */ - if (DnsNameCompare_W(ServiceName, L"localhost") || - DnsNameCompare_W(ServiceName, L"loopback")) - { - /* This is the local and/or loopback DNS name */ - LookupFlags |= (LOCAL | LOOPBACK); - } - else if (DnsNameCompare_W(ServiceName, g_pszHostName) || - DnsNameCompare_W(ServiceName, g_pszHostFqdn)) - { - /* This is the local name of the computer */ - LookupFlags |= LOCAL; - } - } - - /* Check if any restrictions were made on the protocols */ - if(lpqsRestrictions->lpafpProtocols) - { - /* Save our local copy to speed up the loop */ - LocalProtocols = lpqsRestrictions->dwNumberOfProtocols; - ProtocolFlags = 0; - - /* Loop the protocols */ - for(i = 0; LocalProtocols--;) - { - /* Make sure it's a family that we recognize */ - if ((lpqsRestrictions->lpafpProtocols[i].iAddressFamily == AF_INET) || - (lpqsRestrictions->lpafpProtocols[i].iAddressFamily == AF_INET6) || - (lpqsRestrictions->lpafpProtocols[i].iAddressFamily == AF_UNSPEC) || - (lpqsRestrictions->lpafpProtocols[i].iAddressFamily == AF_ATM)) - { - /* Find which one is used */ - switch(lpqsRestrictions->lpafpProtocols[i].iProtocol) - { - case IPPROTO_UDP: - ProtocolFlags |= UDP; - break; - case IPPROTO_TCP: - ProtocolFlags |= TCP; - break; - case PF_ATM: - ProtocolFlags |= ATM; - break; - default: - break; - } - } - } - /* Make sure we have at least a valid protocol */ - if (!ProtocolFlags) - { - /* Fail */ - ErrorCode = WSANO_DATA; - goto Quickie; - } - } - else - { - /* No restrictions, assume TCP/UDP */ - ProtocolFlags = (TCP | UDP); - } - - /* Create the Servent from the Service String */ - UdpPort = TcpPort = -1; - ProtocolFlags |= GetServerAndProtocolsFromString(lpqsRestrictions->lpszQueryString, - ServiceClassId, - &LookupServent); - - /* Extract the port numbers */ - if(LookupServent) - { - /* Are we using UDP? */ - if(ProtocolFlags & UDP) - { - /* Get the UDP Port, disable the TCP Port */ - UdpPort = ntohs(LookupServent->s_port); - TcpPort = -1; - } - else if(ProtocolFlags & TCP) - { - /* Get the TCP Port, disable the UDP Port */ - TcpPort = ntohs(LookupServent->s_port); - UdpPort = -1; - } - } - else - { - /* No servent, so use the Service ID to check */ - if(ProtocolFlags & UDP) - { - /* Get the Port from the Service ID */ - UdpPort = FetchPortFromClassInfo(UDP, - ServiceClassId, - lpServiceClassInfo); - } - else - { - /* No UDP */ - UdpPort = -1; - } - - /* No servent, so use the Service ID to check */ - if(ProtocolFlags & TCP) - { - /* Get the Port from the Service ID */ - UdpPort = FetchPortFromClassInfo(TCP, - ServiceClassId, - lpServiceClassInfo); - } - else - { - /* No TCP */ - TcpPort = -1; - } - } - - /* Check if we still don't have a valid port by now */ - if((TcpPort == -1) && (UdpPort == -1)) - { - /* Check if this is TCP */ - if ((ProtocolFlags & TCP) || !(ProtocolFlags & UDP)) - { - /* Set the UDP Port to 0 */ - UdpPort = 0; - } - else - { - /* Set the TCP Port to 0 */ - TcpPort = 0; - } - } - - /* Allocate a Context for this Query */ - RnrContext = RnrCtx_Create(NULL, ServiceName); - RnrContext->lpServiceClassId = *ServiceClassId; - RnrContext->RnrId = RnrId; - RnrContext->dwControlFlags = dwControlFlags; - RnrContext->TcpPort = TcpPort; - RnrContext->UdpPort = UdpPort; - RnrContext->LookupFlags = LookupFlags; - RnrContext->lpProviderId = *lpProviderId; - RnrContext->dwNameSpace = lpqsRestrictions->dwNameSpace; - RnrCtx_Release(RnrContext); - - /* Return the context as a handle */ - *lphLookup = (HANDLE)RnrContext; - - /* Check if this was a TCP, UDP or DNS Query */ - if(RnrId & 0x3000000) - { - /* Get the RR Type from the Service ID */ - RnrContext->RrType = RR_FROM_SVCID(ServiceClassId); - } - - /* Return Success */ - ErrorCode = ERROR_SUCCESS; - -Quickie: - /* Check if we got here through a failure path */ - if (ErrorCode != ERROR_SUCCESS) - { - /* Set the last error and fail */ - SetLastError(ErrorCode); - return SOCKET_ERROR; - } - - /* Return success */ - return ERROR_SUCCESS; -} - -INT -WSPAPI -BuildCsAddr(IN LPWSAQUERYSETW QuerySet, - IN PFLATBUFF FlatBuffer, - IN PDNS_BLOB Blob, - IN DWORD UdpPort, - IN DWORD TcpPort, - IN BOOLEAN ReverseLookup) -{ - return WSANO_DATA; -} - -INT -WINAPI -Dns_NSPLookupServiceNext(IN HANDLE hLookup, - IN DWORD dwControlFlags, - IN OUT LPDWORD lpdwBufferLength, - OUT LPWSAQUERYSETW lpqsResults) -{ - INT ErrorCode; - WSAQUERYSETW LocalResults; - LONG Instance; - PRNR_CONTEXT RnrContext = NULL; - FLATBUFF FlatBuffer; - PVOID Name; - PDNS_BLOB Blob = NULL; - DWORD PortNumber; - PSERVENT ServEntry = NULL; - PDNS_ARRAY DnsArray; - BOOLEAN IsUnicode = TRUE; - SIZE_T FreeSize; - ULONG BlobSize; - ULONG_PTR Position; - PVOID BlobData = NULL; - ULONG StringLength; - LPWSTR UnicodeName; - - /* Make sure that the control flags are valid */ - if ((dwControlFlags & ~ALL_LUP_FLAGS) || - ((dwControlFlags & (LUP_CONTAINERS | LUP_NOCONTAINERS)) == - (LUP_CONTAINERS | LUP_NOCONTAINERS))) - { - /* Either non-recognized flags or invalid combos were passed */ - ErrorCode = WSA_INVALID_PARAMETER; - goto Quickie; - } - - /* Get the Context */ - RnrContext = RnrCtx_Get(hLookup, dwControlFlags, &Instance); - if (!RnrContext) - { - /* This lookup handle must be invalid */ - SetLastError(WSA_INVALID_HANDLE); - return SOCKET_ERROR; - } - - /* Assume success for now */ - SetLastError(NO_ERROR); - - /* Validate the query set size */ - if (*lpdwBufferLength < sizeof(WSAQUERYSETW)) - { - /* Windows doesn't fail, but sets up a local QS for you... */ - lpqsResults = &LocalResults; - ErrorCode = WSAEFAULT; - } - - /* Zero out the buffer and fill out basic data */ - RtlZeroMemory(lpqsResults, sizeof(WSAQUERYSETW)); - lpqsResults->dwNameSpace = NS_DNS; - lpqsResults->dwSize = sizeof(WSAQUERYSETW); - - /* Initialize the Buffer */ - FlatBuf_Init(&FlatBuffer, - lpqsResults + 1, - (ULONG)(*lpdwBufferLength - sizeof(WSAQUERYSETW))); - - /* Check if this is an IANA Lookup */ - if(RnrContext->LookupFlags & IANA) - { - /* Service Lookup */ - GetServerAndProtocolsFromString(RnrContext->ServiceName, - (LPGUID)&HostnameGuid, - &ServEntry); - - /* Get the Port */ - PortNumber = ntohs(ServEntry->s_port); - - /* Use this as the name */ - Name = ServEntry->s_name; - IsUnicode = FALSE; - - /* Override some parts of the Context and check for TCP/UDP */ - if(!_stricmp("tcp", ServEntry->s_proto)) - { - /* Set the TCP Guid */ - SET_TCP_SVCID(&RnrContext->lpServiceClassId, PortNumber); - RnrContext->TcpPort = PortNumber; - RnrContext->UdpPort = -1; - } - else - { - /* Set the UDP Guid */ - SET_UDP_SVCID(&RnrContext->lpServiceClassId, PortNumber); - RnrContext->UdpPort = PortNumber; - RnrContext->TcpPort = -1; - } - } - else - { - /* Check if the caller requested for RES_SERVICE */ - if(RnrContext->dwControlFlags & LUP_RES_SERVICE) - { - /* Make sure that this is the first instance */ - if (Instance) - { - /* Fail */ - ErrorCode = WSA_E_NO_MORE; - goto Quickie; - } - -#if 0 - /* Create the blob */ - DnsArray = NULL; - Blob = SaBlob_CreateFromIp4(RnrContext->ServiceName, - 1, - &DnsArray); -#else - /* FIXME */ - Blob = NULL; - DnsArray = NULL; - ErrorCode = WSAEFAULT; - goto Quickie; -#endif - } - else if(!(Blob = RnrContext->CachedSaBlob)) - { - /* An actual Host Lookup, but we don't have a cached HostEntry yet */ - if (!memcmp(&RnrContext->lpServiceClassId, - &HostnameGuid, - sizeof(GUID)) && !(RnrContext->ServiceName)) - { - /* Do a Regular DNS Lookup */ - Blob = Rnr_DoHostnameLookup(RnrContext); - } - else if (RnrContext->LookupFlags & REVERSE) - { - /* Do a Reverse DNS Lookup */ - Blob = Rnr_GetHostByAddr(RnrContext); - } - else - { - /* Do a Hostname Lookup */ - Blob = Rnr_DoDnsLookup(RnrContext); - } - - /* Check if we got a blob, and cache it */ - if (Blob) RnrContext->CachedSaBlob = Blob; - } - - /* We should have a blob by now */ - if (!Blob) - { - /* We dont, fail */ - if (ErrorCode == NO_ERROR) - { - /* Supposedly no error, so find it out */ - ErrorCode = GetLastError(); - if (ErrorCode == NO_ERROR) ErrorCode = WSASERVICE_NOT_FOUND; - } - - /* Fail */ - goto Quickie; - } - } - - /* Check if this is the first instance or not */ - if(!RnrContext->Instance) - { - /* It is, get the name from the blob */ - Name = Blob->Name; - } - else - { - /* Only accept this scenario if the caller wanted Aliases */ - if((RnrContext->dwControlFlags & LUP_RETURN_ALIASES) && - (Blob->AliasCount > RnrContext->Instance)) - { - /* Get the name from the Alias */ - Name = Blob->Aliases[RnrContext->Instance]; - - /* Let the caller know that this is an Alias */ - /* lpqsResults->dwOutputFlags |= RESULT_IS_ALIAS; */ - } - else - { - /* Fail */ - ErrorCode = WSA_E_NO_MORE; - goto Quickie; - } - } - - /* Lookups are complete... time to return the right stuff! */ - lpqsResults->dwNameSpace = NS_DNS; - - /* Caller wants the Type back */ - if(RnrContext->dwControlFlags & LUP_RETURN_TYPE) - { - /* Copy into the flat buffer and point to it */ - lpqsResults->lpServiceClassId = FlatBuf_CopyMemory(&FlatBuffer, - &RnrContext->lpServiceClassId, - sizeof(GUID), - sizeof(PVOID)); - } - - /* Caller wants the Addreses Back */ - if((RnrContext->dwControlFlags & LUP_RETURN_ADDR) && (Blob)) - { - /* Build the CS Addr for the caller */ - ErrorCode = BuildCsAddr(lpqsResults, - &FlatBuffer, - Blob, - RnrContext->UdpPort, - RnrContext->TcpPort, - (RnrContext->LookupFlags & REVERSE) == 1); - } - - /* Caller wants a Blob */ - if(RnrContext->dwControlFlags & LUP_RETURN_BLOB) - { - /* Save the current size and position */ - FreeSize = FlatBuffer.BufferFreeSize; - Position = FlatBuffer.BufferPos; - - /* Allocate some space for the Public Blob */ - lpqsResults->lpBlob = FlatBuf_ReserveAlignDword(&FlatBuffer, - sizeof(BLOB)); - - /* Check for a Cached Blob */ - if((RnrContext->RrType) && (RnrContext->CachedBlob.pBlobData)) - { - /* We have a Cached Blob, use it */ - BlobSize = RnrContext->CachedBlob.cbSize; - BlobData = FlatBuf_ReserveAlignDword(&FlatBuffer, BlobSize); - - /* Copy into the blob */ - RtlCopyMemory(RnrContext->CachedBlob.pBlobData, - BlobData, - BlobSize); - } - else if (!Blob) - { - /* Create an ANSI Host Entry */ - BlobData = SaBlob_CreateHostent(&FlatBuffer.BufferPos, - &FlatBuffer.BufferFreeSize, - &BlobSize, - Blob, - AnsiString, - TRUE, - FALSE); - } - else if ((RnrContext->LookupFlags & IANA) && (ServEntry)) - { - /* Get Servent */ - BlobData = CopyServEntry(ServEntry, - &FlatBuffer.BufferPos, - &FlatBuffer.BufferFreeSize, - &BlobSize, - TRUE); - - /* Manually update the buffer (no SaBlob function for servents) */ - FlatBuffer.BufferPos += BlobSize; - FlatBuffer.BufferFreeSize -= BlobSize; - } - else - { - /* We have nothing to return! */ - BlobSize = 0; - lpqsResults->lpBlob = NULL; - FlatBuffer.BufferPos = Position; - FlatBuffer.BufferFreeSize = FreeSize; - } - - /* Make sure we have a blob by here */ - if (Blob) - { - /* Set it */ - lpqsResults->lpBlob->pBlobData = BlobData; - lpqsResults->lpBlob->cbSize = BlobSize; - } - else - { - /* Set the error code */ - ErrorCode = WSAEFAULT; - } - } - - /* Caller wants a name, and we have one */ - if((RnrContext->dwControlFlags & LUP_RETURN_NAME) && (Name)) - { - /* Check if we have an ANSI name */ - if (!IsUnicode) - { - /* Convert it */ - StringLength = 512; - Dns_StringCopy(&UnicodeName, - &StringLength, - Name, - 0, - AnsiString, - UnicodeString); - } - else - { - /* Keep the name as is */ - UnicodeName = (LPWSTR)Name; - } - - /* Write it to the buffer */ - Name = FlatBuf_WriteString(&FlatBuffer, UnicodeName, TRUE); - - /* Return it to the caller */ - lpqsResults->lpszServiceInstanceName = Name; - } - -Quickie: - /* Check which path got us here */ - if (ErrorCode != NO_ERROR) - { - /* Set error */ - SetLastError(ErrorCode); - - /* Check if was a memory error */ - if (ErrorCode == WSAEFAULT) - { - /* Update buffer length */ - *lpdwBufferLength -= (DWORD)FlatBuffer.BufferFreeSize; - - /* Decrease an instance */ - RnrCtx_DecInstance(RnrContext); - } - - /* Set the normalized error code */ - ErrorCode = SOCKET_ERROR; - } - - /* Release the RnR Context */ - RnrCtx_Release(RnrContext); - - /* Return error code */ - return ErrorCode; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -#define ALL_LUP_FLAGS (0x0BFFF) - -/* DATA **********************************************************************/ - -LPWSTR g_pszHostName; -LPWSTR g_pszHostFqdn; -LONG g_NspRefCount; -GUID NbtProviderId = {0}; -GUID DNSProviderId = {0}; -DWORD MaskOfGuids; - -NSP_ROUTINE g_NspVector = {sizeof(NSP_ROUTINE), - 1, - 1, - Dns_NSPCleanup, - Dns_NSPLookupServiceBegin, - Dns_NSPLookupServiceNext, - Dns_NSPLookupServiceEnd, - Dns_NSPSetService, - Dns_NSPInstallServiceClass, - Dns_NSPRemoveServiceClass, - Dns_NSPGetServiceClassInfo}; - -/* FUNCTIONS *****************************************************************/ - -INT -WINAPI -Dns_NSPStartup(IN LPGUID lpProviderId, - IN OUT LPNSP_ROUTINE lpsnpRoutines) -{ - INT ErrorCode; - BOOLEAN Prolog; - - /* Validate the size */ - if (lpsnpRoutines->cbSize != sizeof(NSP_ROUTINE)) - { - /* Fail */ - SetLastError(WSAEINVALIDPROCTABLE); - return SOCKET_ERROR; - } - - /* Enter the prolog */ - Prolog = RNRPROV_SockEnterApi(); - if (Prolog) - { - /* Increase our reference count */ - InterlockedIncrement(&g_NspRefCount); - - /* Check if we don't have the hostname */ - if (!g_pszHostName) - { - /* Query it from DNS */ - DnsQueryConfig(DnsConfigHostName_W, - DNS_CONFIG_FLAG_ALLOC, - NULL, - NULL, - &g_pszHostName, - 0); - } - - /* Check if we have a hostname now, but not a Fully-Qualified Domain */ - if (g_pszHostName && !(g_pszHostFqdn)) - { - /* Get the domain from DNS */ - DnsQueryConfig(DnsConfigFullHostName_W, - DNS_CONFIG_FLAG_ALLOC, - NULL, - NULL, - &g_pszHostFqdn, - 0); - } - - /* If we don't have both of them, then set error */ - if (!(g_pszHostName) || !(g_pszHostFqdn)) ErrorCode = SOCKET_ERROR; - } - - /* Check if the Prolog or DNS Local Queries failed */ - if (!(Prolog) || (ErrorCode != NO_ERROR)) - { - /* Fail */ - SetLastError(WSASYSNOTREADY); - return SOCKET_ERROR; - } - - /* Copy the Routines */ - RtlMoveMemory(lpsnpRoutines, &g_NspVector, sizeof(NSP_ROUTINE)); - - /* Check if this is NBT or DNS */ - if (!memcmp(lpProviderId, &NbtProviderId, sizeof(GUID))) - { - /* Enable the NBT Mask */ - MaskOfGuids |= NBT_MASK; - } - else if (!memcmp(lpProviderId, &DNSProviderId, sizeof(GUID))) - { - /* Enable the DNS Mask */ - MaskOfGuids |= DNS_MASK; - } - - /* Return success */ - return NO_ERROR; -} - -VOID -WSPAPI -Nsp_GlobalCleanup(VOID) -{ - /* Cleanup the RnR Contexts */ - RnrCtx_ListCleanup(); - - /* Free the hostnames, if we have them */ - if (g_pszHostName) DnsApiFree(g_pszHostName); - if (g_pszHostFqdn) DnsApiFree(g_pszHostFqdn); - g_pszHostFqdn = g_pszHostName = NULL; -} - -INT -WINAPI -NSPStartup(IN LPGUID lpProviderId, - IN OUT LPNSP_ROUTINE lpsnpRoutines) -{ - INT ErrorCode; - - /* Initialize the DLL */ - ErrorCode = MSWSOCK_Initialize(); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - SetLastError(WSANOTINITIALISED); - return SOCKET_ERROR; - } - - /* Check if this is Winsock Mobile or DNS */ - if (!memcmp(lpProviderId, &gNLANamespaceGuid, sizeof(GUID))) - { - /* Initialize WSM */ - return WSM_NSPStartup(lpProviderId, lpsnpRoutines); - } - - /* Initialize DNS */ - return Dns_NSPStartup(lpProviderId, lpsnpRoutines); -} - -INT -WINAPI -Dns_NSPCleanup(IN LPGUID lpProviderId) -{ - /* Decrement our reference count and do global cleanup if it's reached 0 */ - if (!(InterlockedDecrement(&g_NspRefCount))) Nsp_GlobalCleanup(); - - /* Return success */ - return NO_ERROR; -} - -INT -WINAPI -Dns_NSPSetService(IN LPGUID lpProviderId, - IN LPWSASERVICECLASSINFOW lpServiceClassInfo, - IN LPWSAQUERYSETW lpqsRegInfo, - IN WSAESETSERVICEOP essOperation, - IN DWORD dwControlFlags) -{ - /* Unlike NLA, DNS Services cannot be dynmically modified */ - SetLastError(ERROR_NOT_SUPPORTED); - return SOCKET_ERROR; -} - -INT -WINAPI -Dns_NSPInstallServiceClass(IN LPGUID lpProviderId, - IN LPWSASERVICECLASSINFOW lpServiceClassInfo) -{ - /* Unlike NLA, DNS Services cannot be dynmically modified */ - SetLastError(WSAEOPNOTSUPP); - return SOCKET_ERROR; -}; - -INT -WINAPI -Dns_NSPRemoveServiceClass(IN LPGUID lpProviderId, - IN LPGUID lpServiceCallId) -{ - /* Unlike NLA, DNS Services cannot be dynmically modified */ - SetLastError(WSAEOPNOTSUPP); - return SOCKET_ERROR; -} -INT -WINAPI -Dns_NSPGetServiceClassInfo(IN LPGUID lpProviderId, - IN OUT LPDWORD lpdwBufSize, - IN OUT LPWSASERVICECLASSINFOW lpServiceClassInfo) -{ - /* Unlike NLA, DNS Services cannot be dynmically modified */ - SetLastError(WSAEOPNOTSUPP); - return SOCKET_ERROR; -} - -INT -WINAPI -Dns_NSPLookupServiceEnd(IN HANDLE hLookup) -{ - PRNR_CONTEXT RnrContext; - - /* Get this handle's context */ - RnrContext = RnrCtx_Get(hLookup, 0, NULL); - - /* Mark it as completed */ - RnrContext->LookupFlags |= DONE; - - /* Dereference it once for our _Get */ - RnrCtx_Release(RnrContext); - - /* And once last to delete it */ - RnrCtx_Release(RnrContext); - - /* return */ - return NO_ERROR; -} - -INT -WINAPI -rnr_IdForGuid(IN LPGUID Guid) -{ - - if (memcmp(Guid, &InetHostName, sizeof(GUID))) return 0x10000002; - if (memcmp(Guid, &Ipv6Guid, sizeof(GUID))) return 0x10000023; - if (memcmp(Guid, &HostnameGuid, sizeof(GUID))) return 0x1; - if (memcmp(Guid, &AddressGuid, sizeof(GUID))) return 0x80000000; - if (memcmp(Guid, &IANAGuid, sizeof(GUID))) return 0x2; - if IS_SVCID_DNS(Guid) return 0x5000000; - if IS_SVCID_TCP(Guid) return 0x1000000; - if IS_SVCID_UDP(Guid) return 0x2000000; - return 0; -} - -PVOID -WSPAPI -FlatBuf_ReserveAlignDword(IN PFLATBUFF FlatBuffer, - IN ULONG Size) -{ - /* Let DNSLIB do the grunt work */ - return FlatBuf_Arg_Reserve((PVOID)FlatBuffer->BufferPos, - &FlatBuffer->BufferFreeSize, - Size, - sizeof(PVOID)); -} - -PVOID -WSPAPI -FlatBuf_WriteString(IN PFLATBUFF FlatBuffer, - IN PVOID String, - IN BOOLEAN IsUnicode) -{ - /* Let DNSLIB do the grunt work */ - return FlatBuf_Arg_WriteString((PVOID)FlatBuffer->BufferPos, - &FlatBuffer->BufferFreeSize, - String, - IsUnicode); -} - -PVOID -WSPAPI -FlatBuf_CopyMemory(IN PFLATBUFF FlatBuffer, - IN PVOID Buffer, - IN ULONG Size, - IN ULONG Align) -{ - /* Let DNSLIB do the grunt work */ - return FlatBuf_Arg_CopyMemory((PVOID)FlatBuffer->BufferPos, - &FlatBuffer->BufferFreeSize, - Buffer, - Size, - Align); -} - -INT -WINAPI -Dns_NSPLookupServiceBegin(LPGUID lpProviderId, - LPWSAQUERYSETW lpqsRestrictions, - LPWSASERVICECLASSINFOW lpServiceClassInfo, - DWORD dwControlFlags, - LPHANDLE lphLookup) -{ - INT ErrorCode = SOCKET_ERROR; - PWCHAR ServiceName = lpqsRestrictions->lpszServiceInstanceName; - LPGUID ServiceClassId; - INT RnrId; - ULONG LookupFlags = 0; - BOOL NameRequested = FALSE; - WCHAR StringBuffer[48]; - ULONG i; - DWORD LocalProtocols; - ULONG ProtocolFlags; - PSERVENT LookupServent; - DWORD UdpPort, TcpPort; - PRNR_CONTEXT RnrContext; - PSOCKADDR_IN ReverseSock; - - /* Check if the Size isn't weird */ - if(lpqsRestrictions->dwSize < sizeof(WSAQUERYSETW)) - { - ErrorCode = WSAEFAULT; - goto Quickie; - } - - /* Get the GUID */ - ServiceClassId = lpqsRestrictions->lpServiceClassId; - if(!ServiceClassId) - { - /* No GUID, fail */ - ErrorCode = WSA_INVALID_PARAMETER; - goto Quickie; - } - - /* Get the RNR ID */ - RnrId = rnr_IdForGuid(ServiceClassId); - - /* Make sure that the control flags are valid */ - if ((dwControlFlags & ~ALL_LUP_FLAGS) || - ((dwControlFlags & (LUP_CONTAINERS | LUP_NOCONTAINERS)) == - (LUP_CONTAINERS | LUP_NOCONTAINERS))) - { - /* Either non-recognized flags or invalid combos were passed */ - ErrorCode = WSA_INVALID_PARAMETER; - goto Quickie; - } - - /* Make sure that we have no context, and that LUP_CONTAINERS is not on */ - if(((lpqsRestrictions->lpszContext) && - (*lpqsRestrictions->lpszContext) && - (wcscmp(lpqsRestrictions->lpszContext, L"\\"))) || - (dwControlFlags & LUP_CONTAINERS)) - { - /* We don't support contexts or LUP_CONTAINERS */ - ErrorCode = WSANO_DATA; - goto Quickie; - } - - /* Is this a Reverse Lookup? */ - if (RnrId == 0x80000000) - { - /* Remember for later */ - LookupFlags = REVERSE; - } - else - { - /* Is this a IANA Lookup? */ - if (RnrId == 0x2) - { - /* Mask out this flag since it's of no use now */ - dwControlFlags &= ~(LUP_RETURN_ADDR); - - /* This is a IANA lookup, remember for later */ - LookupFlags |= IANA; - } - - /* Check if we need a name or not */ - if ((RnrId == 0x1) || - (RnrId == 0x10000002) || - (RnrId == 0x10000023) || - (RnrId == 0x10000022)) - { - /* We do */ - NameRequested = TRUE; - } - } - - /* Final check to make sure if we need a name or not */ - if (RnrId & 0x3000000) NameRequested = TRUE; - - /* No Service Name was specified */ - if(!(ServiceName) || !(*ServiceName)) - { - /* - * A name was requested but no Service Name was given, - * so this is a local lookup - */ - if(NameRequested) - { - /* A local Lookup */ - LookupFlags |= LOCAL; - ServiceName = L""; - } - else if((LookupFlags & REVERSE) && - (lpqsRestrictions->lpcsaBuffer) && - (lpqsRestrictions->dwNumberOfCsAddrs == 1)) - { - /* Reverse lookup, make sure a CS Address is there */ - ReverseSock = (struct sockaddr_in*) - lpqsRestrictions->lpcsaBuffer->RemoteAddr.lpSockaddr; - - /* Convert address to Unicode */ - MultiByteToWideChar(CP_ACP, - 0, - inet_ntoa(ReverseSock->sin_addr), - -1, - StringBuffer, - 16); - - /* Set it as the new name */ - ServiceName = StringBuffer; - } - else - { - /* We can't do anything without a service name at this point */ - ErrorCode = WSA_INVALID_PARAMETER; - goto Quickie; - } - } - else if(NameRequested) - { - /* Check for meaningful DNS Names */ - if (DnsNameCompare_W(ServiceName, L"localhost") || - DnsNameCompare_W(ServiceName, L"loopback")) - { - /* This is the local and/or loopback DNS name */ - LookupFlags |= (LOCAL | LOOPBACK); - } - else if (DnsNameCompare_W(ServiceName, g_pszHostName) || - DnsNameCompare_W(ServiceName, g_pszHostFqdn)) - { - /* This is the local name of the computer */ - LookupFlags |= LOCAL; - } - } - - /* Check if any restrictions were made on the protocols */ - if(lpqsRestrictions->lpafpProtocols) - { - /* Save our local copy to speed up the loop */ - LocalProtocols = lpqsRestrictions->dwNumberOfProtocols; - ProtocolFlags = 0; - - /* Loop the protocols */ - for(i = 0; LocalProtocols--;) - { - /* Make sure it's a family that we recognize */ - if ((lpqsRestrictions->lpafpProtocols[i].iAddressFamily == AF_INET) || - (lpqsRestrictions->lpafpProtocols[i].iAddressFamily == AF_INET6) || - (lpqsRestrictions->lpafpProtocols[i].iAddressFamily == AF_UNSPEC) || - (lpqsRestrictions->lpafpProtocols[i].iAddressFamily == AF_ATM)) - { - /* Find which one is used */ - switch(lpqsRestrictions->lpafpProtocols[i].iProtocol) - { - case IPPROTO_UDP: - ProtocolFlags |= UDP; - break; - case IPPROTO_TCP: - ProtocolFlags |= TCP; - break; - case PF_ATM: - ProtocolFlags |= ATM; - break; - default: - break; - } - } - } - /* Make sure we have at least a valid protocol */ - if (!ProtocolFlags) - { - /* Fail */ - ErrorCode = WSANO_DATA; - goto Quickie; - } - } - else - { - /* No restrictions, assume TCP/UDP */ - ProtocolFlags = (TCP | UDP); - } - - /* Create the Servent from the Service String */ - UdpPort = TcpPort = -1; - ProtocolFlags |= GetServerAndProtocolsFromString(lpqsRestrictions->lpszQueryString, - ServiceClassId, - &LookupServent); - - /* Extract the port numbers */ - if(LookupServent) - { - /* Are we using UDP? */ - if(ProtocolFlags & UDP) - { - /* Get the UDP Port, disable the TCP Port */ - UdpPort = ntohs(LookupServent->s_port); - TcpPort = -1; - } - else if(ProtocolFlags & TCP) - { - /* Get the TCP Port, disable the UDP Port */ - TcpPort = ntohs(LookupServent->s_port); - UdpPort = -1; - } - } - else - { - /* No servent, so use the Service ID to check */ - if(ProtocolFlags & UDP) - { - /* Get the Port from the Service ID */ - UdpPort = FetchPortFromClassInfo(UDP, - ServiceClassId, - lpServiceClassInfo); - } - else - { - /* No UDP */ - UdpPort = -1; - } - - /* No servent, so use the Service ID to check */ - if(ProtocolFlags & TCP) - { - /* Get the Port from the Service ID */ - UdpPort = FetchPortFromClassInfo(TCP, - ServiceClassId, - lpServiceClassInfo); - } - else - { - /* No TCP */ - TcpPort = -1; - } - } - - /* Check if we still don't have a valid port by now */ - if((TcpPort == -1) && (UdpPort == -1)) - { - /* Check if this is TCP */ - if ((ProtocolFlags & TCP) || !(ProtocolFlags & UDP)) - { - /* Set the UDP Port to 0 */ - UdpPort = 0; - } - else - { - /* Set the TCP Port to 0 */ - TcpPort = 0; - } - } - - /* Allocate a Context for this Query */ - RnrContext = RnrCtx_Create(NULL, ServiceName); - RnrContext->lpServiceClassId = *ServiceClassId; - RnrContext->RnrId = RnrId; - RnrContext->dwControlFlags = dwControlFlags; - RnrContext->TcpPort = TcpPort; - RnrContext->UdpPort = UdpPort; - RnrContext->LookupFlags = LookupFlags; - RnrContext->lpProviderId = *lpProviderId; - RnrContext->dwNameSpace = lpqsRestrictions->dwNameSpace; - RnrCtx_Release(RnrContext); - - /* Return the context as a handle */ - *lphLookup = (HANDLE)RnrContext; - - /* Check if this was a TCP, UDP or DNS Query */ - if(RnrId & 0x3000000) - { - /* Get the RR Type from the Service ID */ - RnrContext->RrType = RR_FROM_SVCID(ServiceClassId); - } - - /* Return Success */ - ErrorCode = ERROR_SUCCESS; - -Quickie: - /* Check if we got here through a failure path */ - if (ErrorCode != ERROR_SUCCESS) - { - /* Set the last error and fail */ - SetLastError(ErrorCode); - return SOCKET_ERROR; - } - - /* Return success */ - return ERROR_SUCCESS; -} - -INT -WSPAPI -BuildCsAddr(IN LPWSAQUERYSETW QuerySet, - IN PFLATBUFF FlatBuffer, - IN PDNS_BLOB Blob, - IN DWORD UdpPort, - IN DWORD TcpPort, - IN BOOLEAN ReverseLookup) -{ - return WSANO_DATA; -} - -INT -WINAPI -Dns_NSPLookupServiceNext(IN HANDLE hLookup, - IN DWORD dwControlFlags, - IN OUT LPDWORD lpdwBufferLength, - OUT LPWSAQUERYSETW lpqsResults) -{ - INT ErrorCode; - WSAQUERYSETW LocalResults; - LONG Instance; - PRNR_CONTEXT RnrContext = NULL; - FLATBUFF FlatBuffer; - PVOID Name; - PDNS_BLOB Blob = NULL; - DWORD PortNumber; - PSERVENT ServEntry = NULL; - PDNS_ARRAY DnsArray; - BOOLEAN IsUnicode = TRUE; - SIZE_T FreeSize; - ULONG BlobSize; - ULONG_PTR Position; - PVOID BlobData = NULL; - ULONG StringLength; - LPWSTR UnicodeName; - - /* Make sure that the control flags are valid */ - if ((dwControlFlags & ~ALL_LUP_FLAGS) || - ((dwControlFlags & (LUP_CONTAINERS | LUP_NOCONTAINERS)) == - (LUP_CONTAINERS | LUP_NOCONTAINERS))) - { - /* Either non-recognized flags or invalid combos were passed */ - ErrorCode = WSA_INVALID_PARAMETER; - goto Quickie; - } - - /* Get the Context */ - RnrContext = RnrCtx_Get(hLookup, dwControlFlags, &Instance); - if (!RnrContext) - { - /* This lookup handle must be invalid */ - SetLastError(WSA_INVALID_HANDLE); - return SOCKET_ERROR; - } - - /* Assume success for now */ - SetLastError(NO_ERROR); - - /* Validate the query set size */ - if (*lpdwBufferLength < sizeof(WSAQUERYSETW)) - { - /* Windows doesn't fail, but sets up a local QS for you... */ - lpqsResults = &LocalResults; - ErrorCode = WSAEFAULT; - } - - /* Zero out the buffer and fill out basic data */ - RtlZeroMemory(lpqsResults, sizeof(WSAQUERYSETW)); - lpqsResults->dwNameSpace = NS_DNS; - lpqsResults->dwSize = sizeof(WSAQUERYSETW); - - /* Initialize the Buffer */ - FlatBuf_Init(&FlatBuffer, - lpqsResults + 1, - (ULONG)(*lpdwBufferLength - sizeof(WSAQUERYSETW))); - - /* Check if this is an IANA Lookup */ - if(RnrContext->LookupFlags & IANA) - { - /* Service Lookup */ - GetServerAndProtocolsFromString(RnrContext->ServiceName, - (LPGUID)&HostnameGuid, - &ServEntry); - - /* Get the Port */ - PortNumber = ntohs(ServEntry->s_port); - - /* Use this as the name */ - Name = ServEntry->s_name; - IsUnicode = FALSE; - - /* Override some parts of the Context and check for TCP/UDP */ - if(!_stricmp("tcp", ServEntry->s_proto)) - { - /* Set the TCP Guid */ - SET_TCP_SVCID(&RnrContext->lpServiceClassId, PortNumber); - RnrContext->TcpPort = PortNumber; - RnrContext->UdpPort = -1; - } - else - { - /* Set the UDP Guid */ - SET_UDP_SVCID(&RnrContext->lpServiceClassId, PortNumber); - RnrContext->UdpPort = PortNumber; - RnrContext->TcpPort = -1; - } - } - else - { - /* Check if the caller requested for RES_SERVICE */ - if(RnrContext->dwControlFlags & LUP_RES_SERVICE) - { - /* Make sure that this is the first instance */ - if (Instance) - { - /* Fail */ - ErrorCode = WSA_E_NO_MORE; - goto Quickie; - } - -#if 0 - /* Create the blob */ - DnsArray = NULL; - Blob = SaBlob_CreateFromIp4(RnrContext->ServiceName, - 1, - &DnsArray); -#else - /* FIXME */ - Blob = NULL; - DnsArray = NULL; - ErrorCode = WSAEFAULT; - goto Quickie; -#endif - } - else if(!(Blob = RnrContext->CachedSaBlob)) - { - /* An actual Host Lookup, but we don't have a cached HostEntry yet */ - if (!memcmp(&RnrContext->lpServiceClassId, - &HostnameGuid, - sizeof(GUID)) && !(RnrContext->ServiceName)) - { - /* Do a Regular DNS Lookup */ - Blob = Rnr_DoHostnameLookup(RnrContext); - } - else if (RnrContext->LookupFlags & REVERSE) - { - /* Do a Reverse DNS Lookup */ - Blob = Rnr_GetHostByAddr(RnrContext); - } - else - { - /* Do a Hostname Lookup */ - Blob = Rnr_DoDnsLookup(RnrContext); - } - - /* Check if we got a blob, and cache it */ - if (Blob) RnrContext->CachedSaBlob = Blob; - } - - /* We should have a blob by now */ - if (!Blob) - { - /* We dont, fail */ - if (ErrorCode == NO_ERROR) - { - /* Supposedly no error, so find it out */ - ErrorCode = GetLastError(); - if (ErrorCode == NO_ERROR) ErrorCode = WSASERVICE_NOT_FOUND; - } - - /* Fail */ - goto Quickie; - } - } - - /* Check if this is the first instance or not */ - if(!RnrContext->Instance) - { - /* It is, get the name from the blob */ - Name = Blob->Name; - } - else - { - /* Only accept this scenario if the caller wanted Aliases */ - if((RnrContext->dwControlFlags & LUP_RETURN_ALIASES) && - (Blob->AliasCount > RnrContext->Instance)) - { - /* Get the name from the Alias */ - Name = Blob->Aliases[RnrContext->Instance]; - - /* Let the caller know that this is an Alias */ - /* lpqsResults->dwOutputFlags |= RESULT_IS_ALIAS; */ - } - else - { - /* Fail */ - ErrorCode = WSA_E_NO_MORE; - goto Quickie; - } - } - - /* Lookups are complete... time to return the right stuff! */ - lpqsResults->dwNameSpace = NS_DNS; - - /* Caller wants the Type back */ - if(RnrContext->dwControlFlags & LUP_RETURN_TYPE) - { - /* Copy into the flat buffer and point to it */ - lpqsResults->lpServiceClassId = FlatBuf_CopyMemory(&FlatBuffer, - &RnrContext->lpServiceClassId, - sizeof(GUID), - sizeof(PVOID)); - } - - /* Caller wants the Addreses Back */ - if((RnrContext->dwControlFlags & LUP_RETURN_ADDR) && (Blob)) - { - /* Build the CS Addr for the caller */ - ErrorCode = BuildCsAddr(lpqsResults, - &FlatBuffer, - Blob, - RnrContext->UdpPort, - RnrContext->TcpPort, - (RnrContext->LookupFlags & REVERSE) == 1); - } - - /* Caller wants a Blob */ - if(RnrContext->dwControlFlags & LUP_RETURN_BLOB) - { - /* Save the current size and position */ - FreeSize = FlatBuffer.BufferFreeSize; - Position = FlatBuffer.BufferPos; - - /* Allocate some space for the Public Blob */ - lpqsResults->lpBlob = FlatBuf_ReserveAlignDword(&FlatBuffer, - sizeof(BLOB)); - - /* Check for a Cached Blob */ - if((RnrContext->RrType) && (RnrContext->CachedBlob.pBlobData)) - { - /* We have a Cached Blob, use it */ - BlobSize = RnrContext->CachedBlob.cbSize; - BlobData = FlatBuf_ReserveAlignDword(&FlatBuffer, BlobSize); - - /* Copy into the blob */ - RtlCopyMemory(RnrContext->CachedBlob.pBlobData, - BlobData, - BlobSize); - } - else if (!Blob) - { - /* Create an ANSI Host Entry */ - BlobData = SaBlob_CreateHostent(&FlatBuffer.BufferPos, - &FlatBuffer.BufferFreeSize, - &BlobSize, - Blob, - AnsiString, - TRUE, - FALSE); - } - else if ((RnrContext->LookupFlags & IANA) && (ServEntry)) - { - /* Get Servent */ - BlobData = CopyServEntry(ServEntry, - &FlatBuffer.BufferPos, - &FlatBuffer.BufferFreeSize, - &BlobSize, - TRUE); - - /* Manually update the buffer (no SaBlob function for servents) */ - FlatBuffer.BufferPos += BlobSize; - FlatBuffer.BufferFreeSize -= BlobSize; - } - else - { - /* We have nothing to return! */ - BlobSize = 0; - lpqsResults->lpBlob = NULL; - FlatBuffer.BufferPos = Position; - FlatBuffer.BufferFreeSize = FreeSize; - } - - /* Make sure we have a blob by here */ - if (Blob) - { - /* Set it */ - lpqsResults->lpBlob->pBlobData = BlobData; - lpqsResults->lpBlob->cbSize = BlobSize; - } - else - { - /* Set the error code */ - ErrorCode = WSAEFAULT; - } - } - - /* Caller wants a name, and we have one */ - if((RnrContext->dwControlFlags & LUP_RETURN_NAME) && (Name)) - { - /* Check if we have an ANSI name */ - if (!IsUnicode) - { - /* Convert it */ - StringLength = 512; - Dns_StringCopy(&UnicodeName, - &StringLength, - Name, - 0, - AnsiString, - UnicodeString); - } - else - { - /* Keep the name as is */ - UnicodeName = (LPWSTR)Name; - } - - /* Write it to the buffer */ - Name = FlatBuf_WriteString(&FlatBuffer, UnicodeName, TRUE); - - /* Return it to the caller */ - lpqsResults->lpszServiceInstanceName = Name; - } - -Quickie: - /* Check which path got us here */ - if (ErrorCode != NO_ERROR) - { - /* Set error */ - SetLastError(ErrorCode); - - /* Check if was a memory error */ - if (ErrorCode == WSAEFAULT) - { - /* Update buffer length */ - *lpdwBufferLength -= (DWORD)FlatBuffer.BufferFreeSize; - - /* Decrease an instance */ - RnrCtx_DecInstance(RnrContext); - } - - /* Set the normalized error code */ - ErrorCode = SOCKET_ERROR; - } - - /* Release the RnR Context */ - RnrCtx_Release(RnrContext); - - /* Return error code */ - return ErrorCode; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -#define ALL_LUP_FLAGS (0x0BFFF) - -/* DATA **********************************************************************/ - -LPWSTR g_pszHostName; -LPWSTR g_pszHostFqdn; -LONG g_NspRefCount; -GUID NbtProviderId = {0}; -GUID DNSProviderId = {0}; -DWORD MaskOfGuids; - -NSP_ROUTINE g_NspVector = {sizeof(NSP_ROUTINE), - 1, - 1, - Dns_NSPCleanup, - Dns_NSPLookupServiceBegin, - Dns_NSPLookupServiceNext, - Dns_NSPLookupServiceEnd, - Dns_NSPSetService, - Dns_NSPInstallServiceClass, - Dns_NSPRemoveServiceClass, - Dns_NSPGetServiceClassInfo}; - -/* FUNCTIONS *****************************************************************/ - -INT -WINAPI -Dns_NSPStartup(IN LPGUID lpProviderId, - IN OUT LPNSP_ROUTINE lpsnpRoutines) -{ - INT ErrorCode; - BOOLEAN Prolog; - - /* Validate the size */ - if (lpsnpRoutines->cbSize != sizeof(NSP_ROUTINE)) - { - /* Fail */ - SetLastError(WSAEINVALIDPROCTABLE); - return SOCKET_ERROR; - } - - /* Enter the prolog */ - Prolog = RNRPROV_SockEnterApi(); - if (Prolog) - { - /* Increase our reference count */ - InterlockedIncrement(&g_NspRefCount); - - /* Check if we don't have the hostname */ - if (!g_pszHostName) - { - /* Query it from DNS */ - DnsQueryConfig(DnsConfigHostName_W, - DNS_CONFIG_FLAG_ALLOC, - NULL, - NULL, - &g_pszHostName, - 0); - } - - /* Check if we have a hostname now, but not a Fully-Qualified Domain */ - if (g_pszHostName && !(g_pszHostFqdn)) - { - /* Get the domain from DNS */ - DnsQueryConfig(DnsConfigFullHostName_W, - DNS_CONFIG_FLAG_ALLOC, - NULL, - NULL, - &g_pszHostFqdn, - 0); - } - - /* If we don't have both of them, then set error */ - if (!(g_pszHostName) || !(g_pszHostFqdn)) ErrorCode = SOCKET_ERROR; - } - - /* Check if the Prolog or DNS Local Queries failed */ - if (!(Prolog) || (ErrorCode != NO_ERROR)) - { - /* Fail */ - SetLastError(WSASYSNOTREADY); - return SOCKET_ERROR; - } - - /* Copy the Routines */ - RtlMoveMemory(lpsnpRoutines, &g_NspVector, sizeof(NSP_ROUTINE)); - - /* Check if this is NBT or DNS */ - if (!memcmp(lpProviderId, &NbtProviderId, sizeof(GUID))) - { - /* Enable the NBT Mask */ - MaskOfGuids |= NBT_MASK; - } - else if (!memcmp(lpProviderId, &DNSProviderId, sizeof(GUID))) - { - /* Enable the DNS Mask */ - MaskOfGuids |= DNS_MASK; - } - - /* Return success */ - return NO_ERROR; -} - -VOID -WSPAPI -Nsp_GlobalCleanup(VOID) -{ - /* Cleanup the RnR Contexts */ - RnrCtx_ListCleanup(); - - /* Free the hostnames, if we have them */ - if (g_pszHostName) DnsApiFree(g_pszHostName); - if (g_pszHostFqdn) DnsApiFree(g_pszHostFqdn); - g_pszHostFqdn = g_pszHostName = NULL; -} - -INT -WINAPI -NSPStartup(IN LPGUID lpProviderId, - IN OUT LPNSP_ROUTINE lpsnpRoutines) -{ - INT ErrorCode; - - /* Initialize the DLL */ - ErrorCode = MSWSOCK_Initialize(); - if (ErrorCode != NO_ERROR) - { - /* Fail */ - SetLastError(WSANOTINITIALISED); - return SOCKET_ERROR; - } - - /* Check if this is Winsock Mobile or DNS */ - if (!memcmp(lpProviderId, &gNLANamespaceGuid, sizeof(GUID))) - { - /* Initialize WSM */ - return WSM_NSPStartup(lpProviderId, lpsnpRoutines); - } - - /* Initialize DNS */ - return Dns_NSPStartup(lpProviderId, lpsnpRoutines); -} - -INT -WINAPI -Dns_NSPCleanup(IN LPGUID lpProviderId) -{ - /* Decrement our reference count and do global cleanup if it's reached 0 */ - if (!(InterlockedDecrement(&g_NspRefCount))) Nsp_GlobalCleanup(); - - /* Return success */ - return NO_ERROR; -} - -INT -WINAPI -Dns_NSPSetService(IN LPGUID lpProviderId, - IN LPWSASERVICECLASSINFOW lpServiceClassInfo, - IN LPWSAQUERYSETW lpqsRegInfo, - IN WSAESETSERVICEOP essOperation, - IN DWORD dwControlFlags) -{ - /* Unlike NLA, DNS Services cannot be dynmically modified */ - SetLastError(ERROR_NOT_SUPPORTED); - return SOCKET_ERROR; -} - -INT -WINAPI -Dns_NSPInstallServiceClass(IN LPGUID lpProviderId, - IN LPWSASERVICECLASSINFOW lpServiceClassInfo) -{ - /* Unlike NLA, DNS Services cannot be dynmically modified */ - SetLastError(WSAEOPNOTSUPP); - return SOCKET_ERROR; -}; - -INT -WINAPI -Dns_NSPRemoveServiceClass(IN LPGUID lpProviderId, - IN LPGUID lpServiceCallId) -{ - /* Unlike NLA, DNS Services cannot be dynmically modified */ - SetLastError(WSAEOPNOTSUPP); - return SOCKET_ERROR; -} -INT -WINAPI -Dns_NSPGetServiceClassInfo(IN LPGUID lpProviderId, - IN OUT LPDWORD lpdwBufSize, - IN OUT LPWSASERVICECLASSINFOW lpServiceClassInfo) -{ - /* Unlike NLA, DNS Services cannot be dynmically modified */ - SetLastError(WSAEOPNOTSUPP); - return SOCKET_ERROR; -} - -INT -WINAPI -Dns_NSPLookupServiceEnd(IN HANDLE hLookup) -{ - PRNR_CONTEXT RnrContext; - - /* Get this handle's context */ - RnrContext = RnrCtx_Get(hLookup, 0, NULL); - - /* Mark it as completed */ - RnrContext->LookupFlags |= DONE; - - /* Dereference it once for our _Get */ - RnrCtx_Release(RnrContext); - - /* And once last to delete it */ - RnrCtx_Release(RnrContext); - - /* return */ - return NO_ERROR; -} - -INT -WINAPI -rnr_IdForGuid(IN LPGUID Guid) -{ - - if (memcmp(Guid, &InetHostName, sizeof(GUID))) return 0x10000002; - if (memcmp(Guid, &Ipv6Guid, sizeof(GUID))) return 0x10000023; - if (memcmp(Guid, &HostnameGuid, sizeof(GUID))) return 0x1; - if (memcmp(Guid, &AddressGuid, sizeof(GUID))) return 0x80000000; - if (memcmp(Guid, &IANAGuid, sizeof(GUID))) return 0x2; - if IS_SVCID_DNS(Guid) return 0x5000000; - if IS_SVCID_TCP(Guid) return 0x1000000; - if IS_SVCID_UDP(Guid) return 0x2000000; - return 0; -} - -PVOID -WSPAPI -FlatBuf_ReserveAlignDword(IN PFLATBUFF FlatBuffer, - IN ULONG Size) -{ - /* Let DNSLIB do the grunt work */ - return FlatBuf_Arg_Reserve((PVOID)FlatBuffer->BufferPos, - &FlatBuffer->BufferFreeSize, - Size, - sizeof(PVOID)); -} - -PVOID -WSPAPI -FlatBuf_WriteString(IN PFLATBUFF FlatBuffer, - IN PVOID String, - IN BOOLEAN IsUnicode) -{ - /* Let DNSLIB do the grunt work */ - return FlatBuf_Arg_WriteString((PVOID)FlatBuffer->BufferPos, - &FlatBuffer->BufferFreeSize, - String, - IsUnicode); -} - -PVOID -WSPAPI -FlatBuf_CopyMemory(IN PFLATBUFF FlatBuffer, - IN PVOID Buffer, - IN ULONG Size, - IN ULONG Align) -{ - /* Let DNSLIB do the grunt work */ - return FlatBuf_Arg_CopyMemory((PVOID)FlatBuffer->BufferPos, - &FlatBuffer->BufferFreeSize, - Buffer, - Size, - Align); -} - -INT -WINAPI -Dns_NSPLookupServiceBegin(LPGUID lpProviderId, - LPWSAQUERYSETW lpqsRestrictions, - LPWSASERVICECLASSINFOW lpServiceClassInfo, - DWORD dwControlFlags, - LPHANDLE lphLookup) -{ - INT ErrorCode = SOCKET_ERROR; - PWCHAR ServiceName = lpqsRestrictions->lpszServiceInstanceName; - LPGUID ServiceClassId; - INT RnrId; - ULONG LookupFlags = 0; - BOOL NameRequested = FALSE; - WCHAR StringBuffer[48]; - ULONG i; - DWORD LocalProtocols; - ULONG ProtocolFlags; - PSERVENT LookupServent; - DWORD UdpPort, TcpPort; - PRNR_CONTEXT RnrContext; - PSOCKADDR_IN ReverseSock; - - /* Check if the Size isn't weird */ - if(lpqsRestrictions->dwSize < sizeof(WSAQUERYSETW)) - { - ErrorCode = WSAEFAULT; - goto Quickie; - } - - /* Get the GUID */ - ServiceClassId = lpqsRestrictions->lpServiceClassId; - if(!ServiceClassId) - { - /* No GUID, fail */ - ErrorCode = WSA_INVALID_PARAMETER; - goto Quickie; - } - - /* Get the RNR ID */ - RnrId = rnr_IdForGuid(ServiceClassId); - - /* Make sure that the control flags are valid */ - if ((dwControlFlags & ~ALL_LUP_FLAGS) || - ((dwControlFlags & (LUP_CONTAINERS | LUP_NOCONTAINERS)) == - (LUP_CONTAINERS | LUP_NOCONTAINERS))) - { - /* Either non-recognized flags or invalid combos were passed */ - ErrorCode = WSA_INVALID_PARAMETER; - goto Quickie; - } - - /* Make sure that we have no context, and that LUP_CONTAINERS is not on */ - if(((lpqsRestrictions->lpszContext) && - (*lpqsRestrictions->lpszContext) && - (wcscmp(lpqsRestrictions->lpszContext, L"\\"))) || - (dwControlFlags & LUP_CONTAINERS)) - { - /* We don't support contexts or LUP_CONTAINERS */ - ErrorCode = WSANO_DATA; - goto Quickie; - } - - /* Is this a Reverse Lookup? */ - if (RnrId == 0x80000000) - { - /* Remember for later */ - LookupFlags = REVERSE; - } - else - { - /* Is this a IANA Lookup? */ - if (RnrId == 0x2) - { - /* Mask out this flag since it's of no use now */ - dwControlFlags &= ~(LUP_RETURN_ADDR); - - /* This is a IANA lookup, remember for later */ - LookupFlags |= IANA; - } - - /* Check if we need a name or not */ - if ((RnrId == 0x1) || - (RnrId == 0x10000002) || - (RnrId == 0x10000023) || - (RnrId == 0x10000022)) - { - /* We do */ - NameRequested = TRUE; - } - } - - /* Final check to make sure if we need a name or not */ - if (RnrId & 0x3000000) NameRequested = TRUE; - - /* No Service Name was specified */ - if(!(ServiceName) || !(*ServiceName)) - { - /* - * A name was requested but no Service Name was given, - * so this is a local lookup - */ - if(NameRequested) - { - /* A local Lookup */ - LookupFlags |= LOCAL; - ServiceName = L""; - } - else if((LookupFlags & REVERSE) && - (lpqsRestrictions->lpcsaBuffer) && - (lpqsRestrictions->dwNumberOfCsAddrs == 1)) - { - /* Reverse lookup, make sure a CS Address is there */ - ReverseSock = (struct sockaddr_in*) - lpqsRestrictions->lpcsaBuffer->RemoteAddr.lpSockaddr; - - /* Convert address to Unicode */ - MultiByteToWideChar(CP_ACP, - 0, - inet_ntoa(ReverseSock->sin_addr), - -1, - StringBuffer, - 16); - - /* Set it as the new name */ - ServiceName = StringBuffer; - } - else - { - /* We can't do anything without a service name at this point */ - ErrorCode = WSA_INVALID_PARAMETER; - goto Quickie; - } - } - else if(NameRequested) - { - /* Check for meaningful DNS Names */ - if (DnsNameCompare_W(ServiceName, L"localhost") || - DnsNameCompare_W(ServiceName, L"loopback")) - { - /* This is the local and/or loopback DNS name */ - LookupFlags |= (LOCAL | LOOPBACK); - } - else if (DnsNameCompare_W(ServiceName, g_pszHostName) || - DnsNameCompare_W(ServiceName, g_pszHostFqdn)) - { - /* This is the local name of the computer */ - LookupFlags |= LOCAL; - } - } - - /* Check if any restrictions were made on the protocols */ - if(lpqsRestrictions->lpafpProtocols) - { - /* Save our local copy to speed up the loop */ - LocalProtocols = lpqsRestrictions->dwNumberOfProtocols; - ProtocolFlags = 0; - - /* Loop the protocols */ - for(i = 0; LocalProtocols--;) - { - /* Make sure it's a family that we recognize */ - if ((lpqsRestrictions->lpafpProtocols[i].iAddressFamily == AF_INET) || - (lpqsRestrictions->lpafpProtocols[i].iAddressFamily == AF_INET6) || - (lpqsRestrictions->lpafpProtocols[i].iAddressFamily == AF_UNSPEC) || - (lpqsRestrictions->lpafpProtocols[i].iAddressFamily == AF_ATM)) - { - /* Find which one is used */ - switch(lpqsRestrictions->lpafpProtocols[i].iProtocol) - { - case IPPROTO_UDP: - ProtocolFlags |= UDP; - break; - case IPPROTO_TCP: - ProtocolFlags |= TCP; - break; - case PF_ATM: - ProtocolFlags |= ATM; - break; - default: - break; - } - } - } - /* Make sure we have at least a valid protocol */ - if (!ProtocolFlags) - { - /* Fail */ - ErrorCode = WSANO_DATA; - goto Quickie; - } - } - else - { - /* No restrictions, assume TCP/UDP */ - ProtocolFlags = (TCP | UDP); - } - - /* Create the Servent from the Service String */ - UdpPort = TcpPort = -1; - ProtocolFlags |= GetServerAndProtocolsFromString(lpqsRestrictions->lpszQueryString, - ServiceClassId, - &LookupServent); - - /* Extract the port numbers */ - if(LookupServent) - { - /* Are we using UDP? */ - if(ProtocolFlags & UDP) - { - /* Get the UDP Port, disable the TCP Port */ - UdpPort = ntohs(LookupServent->s_port); - TcpPort = -1; - } - else if(ProtocolFlags & TCP) - { - /* Get the TCP Port, disable the UDP Port */ - TcpPort = ntohs(LookupServent->s_port); - UdpPort = -1; - } - } - else - { - /* No servent, so use the Service ID to check */ - if(ProtocolFlags & UDP) - { - /* Get the Port from the Service ID */ - UdpPort = FetchPortFromClassInfo(UDP, - ServiceClassId, - lpServiceClassInfo); - } - else - { - /* No UDP */ - UdpPort = -1; - } - - /* No servent, so use the Service ID to check */ - if(ProtocolFlags & TCP) - { - /* Get the Port from the Service ID */ - UdpPort = FetchPortFromClassInfo(TCP, - ServiceClassId, - lpServiceClassInfo); - } - else - { - /* No TCP */ - TcpPort = -1; - } - } - - /* Check if we still don't have a valid port by now */ - if((TcpPort == -1) && (UdpPort == -1)) - { - /* Check if this is TCP */ - if ((ProtocolFlags & TCP) || !(ProtocolFlags & UDP)) - { - /* Set the UDP Port to 0 */ - UdpPort = 0; - } - else - { - /* Set the TCP Port to 0 */ - TcpPort = 0; - } - } - - /* Allocate a Context for this Query */ - RnrContext = RnrCtx_Create(NULL, ServiceName); - RnrContext->lpServiceClassId = *ServiceClassId; - RnrContext->RnrId = RnrId; - RnrContext->dwControlFlags = dwControlFlags; - RnrContext->TcpPort = TcpPort; - RnrContext->UdpPort = UdpPort; - RnrContext->LookupFlags = LookupFlags; - RnrContext->lpProviderId = *lpProviderId; - RnrContext->dwNameSpace = lpqsRestrictions->dwNameSpace; - RnrCtx_Release(RnrContext); - - /* Return the context as a handle */ - *lphLookup = (HANDLE)RnrContext; - - /* Check if this was a TCP, UDP or DNS Query */ - if(RnrId & 0x3000000) - { - /* Get the RR Type from the Service ID */ - RnrContext->RrType = RR_FROM_SVCID(ServiceClassId); - } - - /* Return Success */ - ErrorCode = ERROR_SUCCESS; - -Quickie: - /* Check if we got here through a failure path */ - if (ErrorCode != ERROR_SUCCESS) - { - /* Set the last error and fail */ - SetLastError(ErrorCode); - return SOCKET_ERROR; - } - - /* Return success */ - return ERROR_SUCCESS; -} - -INT -WSPAPI -BuildCsAddr(IN LPWSAQUERYSETW QuerySet, - IN PFLATBUFF FlatBuffer, - IN PDNS_BLOB Blob, - IN DWORD UdpPort, - IN DWORD TcpPort, - IN BOOLEAN ReverseLookup) -{ - return WSANO_DATA; -} - -INT -WINAPI -Dns_NSPLookupServiceNext(IN HANDLE hLookup, - IN DWORD dwControlFlags, - IN OUT LPDWORD lpdwBufferLength, - OUT LPWSAQUERYSETW lpqsResults) -{ - INT ErrorCode; - WSAQUERYSETW LocalResults; - LONG Instance; - PRNR_CONTEXT RnrContext = NULL; - FLATBUFF FlatBuffer; - PVOID Name; - PDNS_BLOB Blob = NULL; - DWORD PortNumber; - PSERVENT ServEntry = NULL; - PDNS_ARRAY DnsArray; - BOOLEAN IsUnicode = TRUE; - SIZE_T FreeSize; - ULONG BlobSize; - ULONG_PTR Position; - PVOID BlobData = NULL; - ULONG StringLength; - LPWSTR UnicodeName; - - /* Make sure that the control flags are valid */ - if ((dwControlFlags & ~ALL_LUP_FLAGS) || - ((dwControlFlags & (LUP_CONTAINERS | LUP_NOCONTAINERS)) == - (LUP_CONTAINERS | LUP_NOCONTAINERS))) - { - /* Either non-recognized flags or invalid combos were passed */ - ErrorCode = WSA_INVALID_PARAMETER; - goto Quickie; - } - - /* Get the Context */ - RnrContext = RnrCtx_Get(hLookup, dwControlFlags, &Instance); - if (!RnrContext) - { - /* This lookup handle must be invalid */ - SetLastError(WSA_INVALID_HANDLE); - return SOCKET_ERROR; - } - - /* Assume success for now */ - SetLastError(NO_ERROR); - - /* Validate the query set size */ - if (*lpdwBufferLength < sizeof(WSAQUERYSETW)) - { - /* Windows doesn't fail, but sets up a local QS for you... */ - lpqsResults = &LocalResults; - ErrorCode = WSAEFAULT; - } - - /* Zero out the buffer and fill out basic data */ - RtlZeroMemory(lpqsResults, sizeof(WSAQUERYSETW)); - lpqsResults->dwNameSpace = NS_DNS; - lpqsResults->dwSize = sizeof(WSAQUERYSETW); - - /* Initialize the Buffer */ - FlatBuf_Init(&FlatBuffer, - lpqsResults + 1, - (ULONG)(*lpdwBufferLength - sizeof(WSAQUERYSETW))); - - /* Check if this is an IANA Lookup */ - if(RnrContext->LookupFlags & IANA) - { - /* Service Lookup */ - GetServerAndProtocolsFromString(RnrContext->ServiceName, - (LPGUID)&HostnameGuid, - &ServEntry); - - /* Get the Port */ - PortNumber = ntohs(ServEntry->s_port); - - /* Use this as the name */ - Name = ServEntry->s_name; - IsUnicode = FALSE; - - /* Override some parts of the Context and check for TCP/UDP */ - if(!_stricmp("tcp", ServEntry->s_proto)) - { - /* Set the TCP Guid */ - SET_TCP_SVCID(&RnrContext->lpServiceClassId, PortNumber); - RnrContext->TcpPort = PortNumber; - RnrContext->UdpPort = -1; - } - else - { - /* Set the UDP Guid */ - SET_UDP_SVCID(&RnrContext->lpServiceClassId, PortNumber); - RnrContext->UdpPort = PortNumber; - RnrContext->TcpPort = -1; - } - } - else - { - /* Check if the caller requested for RES_SERVICE */ - if(RnrContext->dwControlFlags & LUP_RES_SERVICE) - { - /* Make sure that this is the first instance */ - if (Instance) - { - /* Fail */ - ErrorCode = WSA_E_NO_MORE; - goto Quickie; - } - -#if 0 - /* Create the blob */ - DnsArray = NULL; - Blob = SaBlob_CreateFromIp4(RnrContext->ServiceName, - 1, - &DnsArray); -#else - /* FIXME */ - Blob = NULL; - DnsArray = NULL; - ErrorCode = WSAEFAULT; - goto Quickie; -#endif - } - else if(!(Blob = RnrContext->CachedSaBlob)) - { - /* An actual Host Lookup, but we don't have a cached HostEntry yet */ - if (!memcmp(&RnrContext->lpServiceClassId, - &HostnameGuid, - sizeof(GUID)) && !(RnrContext->ServiceName)) - { - /* Do a Regular DNS Lookup */ - Blob = Rnr_DoHostnameLookup(RnrContext); - } - else if (RnrContext->LookupFlags & REVERSE) - { - /* Do a Reverse DNS Lookup */ - Blob = Rnr_GetHostByAddr(RnrContext); - } - else - { - /* Do a Hostname Lookup */ - Blob = Rnr_DoDnsLookup(RnrContext); - } - - /* Check if we got a blob, and cache it */ - if (Blob) RnrContext->CachedSaBlob = Blob; - } - - /* We should have a blob by now */ - if (!Blob) - { - /* We dont, fail */ - if (ErrorCode == NO_ERROR) - { - /* Supposedly no error, so find it out */ - ErrorCode = GetLastError(); - if (ErrorCode == NO_ERROR) ErrorCode = WSASERVICE_NOT_FOUND; - } - - /* Fail */ - goto Quickie; - } - } - - /* Check if this is the first instance or not */ - if(!RnrContext->Instance) - { - /* It is, get the name from the blob */ - Name = Blob->Name; - } - else - { - /* Only accept this scenario if the caller wanted Aliases */ - if((RnrContext->dwControlFlags & LUP_RETURN_ALIASES) && - (Blob->AliasCount > RnrContext->Instance)) - { - /* Get the name from the Alias */ - Name = Blob->Aliases[RnrContext->Instance]; - - /* Let the caller know that this is an Alias */ - /* lpqsResults->dwOutputFlags |= RESULT_IS_ALIAS; */ - } - else - { - /* Fail */ - ErrorCode = WSA_E_NO_MORE; - goto Quickie; - } - } - - /* Lookups are complete... time to return the right stuff! */ - lpqsResults->dwNameSpace = NS_DNS; - - /* Caller wants the Type back */ - if(RnrContext->dwControlFlags & LUP_RETURN_TYPE) - { - /* Copy into the flat buffer and point to it */ - lpqsResults->lpServiceClassId = FlatBuf_CopyMemory(&FlatBuffer, - &RnrContext->lpServiceClassId, - sizeof(GUID), - sizeof(PVOID)); - } - - /* Caller wants the Addreses Back */ - if((RnrContext->dwControlFlags & LUP_RETURN_ADDR) && (Blob)) - { - /* Build the CS Addr for the caller */ - ErrorCode = BuildCsAddr(lpqsResults, - &FlatBuffer, - Blob, - RnrContext->UdpPort, - RnrContext->TcpPort, - (RnrContext->LookupFlags & REVERSE) == 1); - } - - /* Caller wants a Blob */ - if(RnrContext->dwControlFlags & LUP_RETURN_BLOB) - { - /* Save the current size and position */ - FreeSize = FlatBuffer.BufferFreeSize; - Position = FlatBuffer.BufferPos; - - /* Allocate some space for the Public Blob */ - lpqsResults->lpBlob = FlatBuf_ReserveAlignDword(&FlatBuffer, - sizeof(BLOB)); - - /* Check for a Cached Blob */ - if((RnrContext->RrType) && (RnrContext->CachedBlob.pBlobData)) - { - /* We have a Cached Blob, use it */ - BlobSize = RnrContext->CachedBlob.cbSize; - BlobData = FlatBuf_ReserveAlignDword(&FlatBuffer, BlobSize); - - /* Copy into the blob */ - RtlCopyMemory(RnrContext->CachedBlob.pBlobData, - BlobData, - BlobSize); - } - else if (!Blob) - { - /* Create an ANSI Host Entry */ - BlobData = SaBlob_CreateHostent(&FlatBuffer.BufferPos, - &FlatBuffer.BufferFreeSize, - &BlobSize, - Blob, - AnsiString, - TRUE, - FALSE); - } - else if ((RnrContext->LookupFlags & IANA) && (ServEntry)) - { - /* Get Servent */ - BlobData = CopyServEntry(ServEntry, - &FlatBuffer.BufferPos, - &FlatBuffer.BufferFreeSize, - &BlobSize, - TRUE); - - /* Manually update the buffer (no SaBlob function for servents) */ - FlatBuffer.BufferPos += BlobSize; - FlatBuffer.BufferFreeSize -= BlobSize; - } - else - { - /* We have nothing to return! */ - BlobSize = 0; - lpqsResults->lpBlob = NULL; - FlatBuffer.BufferPos = Position; - FlatBuffer.BufferFreeSize = FreeSize; - } - - /* Make sure we have a blob by here */ - if (Blob) - { - /* Set it */ - lpqsResults->lpBlob->pBlobData = BlobData; - lpqsResults->lpBlob->cbSize = BlobSize; - } - else - { - /* Set the error code */ - ErrorCode = WSAEFAULT; - } - } - - /* Caller wants a name, and we have one */ - if((RnrContext->dwControlFlags & LUP_RETURN_NAME) && (Name)) - { - /* Check if we have an ANSI name */ - if (!IsUnicode) - { - /* Convert it */ - StringLength = 512; - Dns_StringCopy(&UnicodeName, - &StringLength, - Name, - 0, - AnsiString, - UnicodeString); - } - else - { - /* Keep the name as is */ - UnicodeName = (LPWSTR)Name; - } - - /* Write it to the buffer */ - Name = FlatBuf_WriteString(&FlatBuffer, UnicodeName, TRUE); - - /* Return it to the caller */ - lpqsResults->lpszServiceInstanceName = Name; - } - -Quickie: - /* Check which path got us here */ - if (ErrorCode != NO_ERROR) - { - /* Set error */ - SetLastError(ErrorCode); - - /* Check if was a memory error */ - if (ErrorCode == WSAEFAULT) - { - /* Update buffer length */ - *lpdwBufferLength -= (DWORD)FlatBuffer.BufferFreeSize; - - /* Decrease an instance */ - RnrCtx_DecInstance(RnrContext); - } - - /* Set the normalized error code */ - ErrorCode = SOCKET_ERROR; - } - - /* Release the RnR Context */ - RnrCtx_Release(RnrContext); - - /* Return error code */ - return ErrorCode; -} - diff --git a/dll/win32/mswsock/rnr20/oldutil.c b/dll/win32/mswsock/rnr20/oldutil.c index 83a78e5d1e0..f66b81c5ea6 100644 --- a/dll/win32/mswsock/rnr20/oldutil.c +++ b/dll/win32/mswsock/rnr20/oldutil.c @@ -219,666 +219,3 @@ CopyServEntry(IN PSERVENT Servent, return NULL; } -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - - -/* FUNCTIONS *****************************************************************/ - -DWORD -WINAPI -FetchPortFromClassInfo(IN DWORD Type, - IN LPGUID Guid, - IN LPWSASERVICECLASSINFOW ServiceClassInfo) -{ - DWORD Port; - - if (Type == UDP) - { - if (IS_SVCID_UDP(Guid)) - { - /* Get the Port from the Service ID */ - Port = PORT_FROM_SVCID_UDP(Guid); - } - else - { - /* No UDP */ - Port = -1; - } - } - else if (Type == TCP) - { - if (IS_SVCID_TCP(Guid)) - { - /* Get the Port from the Service ID */ - Port = PORT_FROM_SVCID_TCP(Guid); - } - else - { - /* No TCP */ - Port = -1; - } - } - else - { - /* Invalid */ - Port = -1; - } - - /* Return it */ - return Port; -} - -WORD -WINAPI -GetDnsQueryTypeFromGuid(IN LPGUID Guid) -{ - WORD DnsType = DNS_TYPE_A; - - /* Check if this is is a DNS GUID and get the type from it */ - if (IS_SVCID_DNS(Guid)) DnsType = RR_FROM_SVCID(Guid); - - /* Return the DNS Type */ - return DnsType; -} - -LPSTR -WINAPI -GetAnsiNameRnR(IN LPWSTR UnicodeName, - IN LPSTR Domain, - OUT PBOOL Result) -{ - SIZE_T Length = 0; - LPSTR AnsiName; - - /* Check if we have a domain */ - if (Domain) Length = strlen(Domain); - - /* Calculate length needed and allocate it */ - Length += ((wcslen(UnicodeName) + 1) * sizeof(WCHAR) * 2); - AnsiName = DnsApiAlloc((DWORD)Length); - - /* Convert the string */ - WideCharToMultiByte(CP_ACP, - 0, - UnicodeName, - -1, - AnsiName, - (DWORD)Length, - 0, - Result); - - /* Add the domain, if needed */ - if (Domain) strcat(AnsiName, Domain); - - /* Return the ANSI name */ - return AnsiName; -} - -DWORD -WINAPI -GetServerAndProtocolsFromString(PWCHAR ServiceString, - LPGUID ServiceType, - PSERVENT *ReverseServent) -{ - PSERVENT LocalServent = NULL; - DWORD ProtocolFlags = 0; - PWCHAR ProtocolString; - PWCHAR ServiceName; - PCHAR AnsiServiceName; - PCHAR AnsiProtocolName; - PCHAR TempString; - ULONG ServiceNameLength; - ULONG PortNumber = 0; - - /* Make sure that this is valid for a Servent lookup */ - if ((ServiceString) && - (ServiceType) && - (memcmp(ServiceType, &HostnameGuid, sizeof(GUID))) && - (memcmp(ServiceType, &InetHostName, sizeof(GUID)))) - { - /* Extract the Protocol */ - ProtocolString = wcschr(ServiceString, L'/'); - if (!ProtocolString) ProtocolString = wcschr(ProtocolString, L'\0'); - - /* Find out the length of the service name */ - ServiceNameLength = (ULONG)(ProtocolString - ServiceString) * sizeof(WCHAR); - - /* Allocate it */ - ServiceName = DnsApiAlloc(ServiceNameLength + sizeof(UNICODE_NULL)); - - /* Copy it and null-terminate */ - RtlMoveMemory(ServiceName, ServiceString, ServiceNameLength); - ServiceName[ServiceNameLength] = UNICODE_NULL; - - /* Get the Ansi Service Name */ - AnsiServiceName = GetAnsiNameRnR(ServiceName, 0, NULL); - DnsApiFree(ServiceName); - if (AnsiServiceName) - { - /* If we only have a port number, convert it */ - for (TempString = AnsiServiceName; - *TempString && isdigit(*TempString); - TempString++); - - /* Convert to Port Number */ - if (!*TempString) PortNumber = atoi(AnsiServiceName); - - /* Check if we have a Protocol Name, and set it */ - if (!(*ProtocolString) || !(*++ProtocolString)) - { - /* No protocol string, so won't have it in ANSI either */ - AnsiProtocolName = NULL; - } - else - { - /* Get it in ANSI */ - AnsiProtocolName = GetAnsiNameRnR(ProtocolString, 0, NULL); - } - - /* Now do the actual operation */ - if (PortNumber) - { - /* FIXME: Get Servent by Port */ - } - else - { - /* FIXME: Get Servent by Name */ - } - - /* Free the ansi names if we had them */ - if (AnsiProtocolName) DnsApiFree(AnsiProtocolName); - if (AnsiServiceName) DnsApiFree(AnsiProtocolName); - } - } - - /* Return Servent */ - if (ReverseServent) *ReverseServent = LocalServent; - - /* Return Protocol */ - if (LocalServent) - { - /* Check if it was UDP */ - if (_stricmp("udp", LocalServent->s_proto)) - { - /* Return UDP */ - ProtocolFlags = UDP; - } - else - { - /* Return TCP */ - ProtocolFlags = TCP; - } - } - else - { - /* Return both, no restrictions */ - ProtocolFlags = (TCP | UDP); - } - - /* Return the flags */ - return ProtocolFlags; -} - -PSERVENT -WSPAPI -CopyServEntry(IN PSERVENT Servent, - IN OUT PULONG_PTR BufferPos, - IN OUT PULONG BufferFreeSize, - IN OUT PULONG BlobSize, - IN BOOLEAN Relative) -{ - return NULL; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - - -/* FUNCTIONS *****************************************************************/ - -DWORD -WINAPI -FetchPortFromClassInfo(IN DWORD Type, - IN LPGUID Guid, - IN LPWSASERVICECLASSINFOW ServiceClassInfo) -{ - DWORD Port; - - if (Type == UDP) - { - if (IS_SVCID_UDP(Guid)) - { - /* Get the Port from the Service ID */ - Port = PORT_FROM_SVCID_UDP(Guid); - } - else - { - /* No UDP */ - Port = -1; - } - } - else if (Type == TCP) - { - if (IS_SVCID_TCP(Guid)) - { - /* Get the Port from the Service ID */ - Port = PORT_FROM_SVCID_TCP(Guid); - } - else - { - /* No TCP */ - Port = -1; - } - } - else - { - /* Invalid */ - Port = -1; - } - - /* Return it */ - return Port; -} - -WORD -WINAPI -GetDnsQueryTypeFromGuid(IN LPGUID Guid) -{ - WORD DnsType = DNS_TYPE_A; - - /* Check if this is is a DNS GUID and get the type from it */ - if (IS_SVCID_DNS(Guid)) DnsType = RR_FROM_SVCID(Guid); - - /* Return the DNS Type */ - return DnsType; -} - -LPSTR -WINAPI -GetAnsiNameRnR(IN LPWSTR UnicodeName, - IN LPSTR Domain, - OUT PBOOL Result) -{ - SIZE_T Length = 0; - LPSTR AnsiName; - - /* Check if we have a domain */ - if (Domain) Length = strlen(Domain); - - /* Calculate length needed and allocate it */ - Length += ((wcslen(UnicodeName) + 1) * sizeof(WCHAR) * 2); - AnsiName = DnsApiAlloc((DWORD)Length); - - /* Convert the string */ - WideCharToMultiByte(CP_ACP, - 0, - UnicodeName, - -1, - AnsiName, - (DWORD)Length, - 0, - Result); - - /* Add the domain, if needed */ - if (Domain) strcat(AnsiName, Domain); - - /* Return the ANSI name */ - return AnsiName; -} - -DWORD -WINAPI -GetServerAndProtocolsFromString(PWCHAR ServiceString, - LPGUID ServiceType, - PSERVENT *ReverseServent) -{ - PSERVENT LocalServent = NULL; - DWORD ProtocolFlags = 0; - PWCHAR ProtocolString; - PWCHAR ServiceName; - PCHAR AnsiServiceName; - PCHAR AnsiProtocolName; - PCHAR TempString; - ULONG ServiceNameLength; - ULONG PortNumber = 0; - - /* Make sure that this is valid for a Servent lookup */ - if ((ServiceString) && - (ServiceType) && - (memcmp(ServiceType, &HostnameGuid, sizeof(GUID))) && - (memcmp(ServiceType, &InetHostName, sizeof(GUID)))) - { - /* Extract the Protocol */ - ProtocolString = wcschr(ServiceString, L'/'); - if (!ProtocolString) ProtocolString = wcschr(ProtocolString, L'\0'); - - /* Find out the length of the service name */ - ServiceNameLength = (ULONG)(ProtocolString - ServiceString) * sizeof(WCHAR); - - /* Allocate it */ - ServiceName = DnsApiAlloc(ServiceNameLength + sizeof(UNICODE_NULL)); - - /* Copy it and null-terminate */ - RtlMoveMemory(ServiceName, ServiceString, ServiceNameLength); - ServiceName[ServiceNameLength] = UNICODE_NULL; - - /* Get the Ansi Service Name */ - AnsiServiceName = GetAnsiNameRnR(ServiceName, 0, NULL); - DnsApiFree(ServiceName); - if (AnsiServiceName) - { - /* If we only have a port number, convert it */ - for (TempString = AnsiServiceName; - *TempString && isdigit(*TempString); - TempString++); - - /* Convert to Port Number */ - if (!*TempString) PortNumber = atoi(AnsiServiceName); - - /* Check if we have a Protocol Name, and set it */ - if (!(*ProtocolString) || !(*++ProtocolString)) - { - /* No protocol string, so won't have it in ANSI either */ - AnsiProtocolName = NULL; - } - else - { - /* Get it in ANSI */ - AnsiProtocolName = GetAnsiNameRnR(ProtocolString, 0, NULL); - } - - /* Now do the actual operation */ - if (PortNumber) - { - /* FIXME: Get Servent by Port */ - } - else - { - /* FIXME: Get Servent by Name */ - } - - /* Free the ansi names if we had them */ - if (AnsiProtocolName) DnsApiFree(AnsiProtocolName); - if (AnsiServiceName) DnsApiFree(AnsiProtocolName); - } - } - - /* Return Servent */ - if (ReverseServent) *ReverseServent = LocalServent; - - /* Return Protocol */ - if (LocalServent) - { - /* Check if it was UDP */ - if (_stricmp("udp", LocalServent->s_proto)) - { - /* Return UDP */ - ProtocolFlags = UDP; - } - else - { - /* Return TCP */ - ProtocolFlags = TCP; - } - } - else - { - /* Return both, no restrictions */ - ProtocolFlags = (TCP | UDP); - } - - /* Return the flags */ - return ProtocolFlags; -} - -PSERVENT -WSPAPI -CopyServEntry(IN PSERVENT Servent, - IN OUT PULONG_PTR BufferPos, - IN OUT PULONG BufferFreeSize, - IN OUT PULONG BlobSize, - IN BOOLEAN Relative) -{ - return NULL; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - - -/* FUNCTIONS *****************************************************************/ - -DWORD -WINAPI -FetchPortFromClassInfo(IN DWORD Type, - IN LPGUID Guid, - IN LPWSASERVICECLASSINFOW ServiceClassInfo) -{ - DWORD Port; - - if (Type == UDP) - { - if (IS_SVCID_UDP(Guid)) - { - /* Get the Port from the Service ID */ - Port = PORT_FROM_SVCID_UDP(Guid); - } - else - { - /* No UDP */ - Port = -1; - } - } - else if (Type == TCP) - { - if (IS_SVCID_TCP(Guid)) - { - /* Get the Port from the Service ID */ - Port = PORT_FROM_SVCID_TCP(Guid); - } - else - { - /* No TCP */ - Port = -1; - } - } - else - { - /* Invalid */ - Port = -1; - } - - /* Return it */ - return Port; -} - -WORD -WINAPI -GetDnsQueryTypeFromGuid(IN LPGUID Guid) -{ - WORD DnsType = DNS_TYPE_A; - - /* Check if this is is a DNS GUID and get the type from it */ - if (IS_SVCID_DNS(Guid)) DnsType = RR_FROM_SVCID(Guid); - - /* Return the DNS Type */ - return DnsType; -} - -LPSTR -WINAPI -GetAnsiNameRnR(IN LPWSTR UnicodeName, - IN LPSTR Domain, - OUT PBOOL Result) -{ - SIZE_T Length = 0; - LPSTR AnsiName; - - /* Check if we have a domain */ - if (Domain) Length = strlen(Domain); - - /* Calculate length needed and allocate it */ - Length += ((wcslen(UnicodeName) + 1) * sizeof(WCHAR) * 2); - AnsiName = DnsApiAlloc((DWORD)Length); - - /* Convert the string */ - WideCharToMultiByte(CP_ACP, - 0, - UnicodeName, - -1, - AnsiName, - (DWORD)Length, - 0, - Result); - - /* Add the domain, if needed */ - if (Domain) strcat(AnsiName, Domain); - - /* Return the ANSI name */ - return AnsiName; -} - -DWORD -WINAPI -GetServerAndProtocolsFromString(PWCHAR ServiceString, - LPGUID ServiceType, - PSERVENT *ReverseServent) -{ - PSERVENT LocalServent = NULL; - DWORD ProtocolFlags = 0; - PWCHAR ProtocolString; - PWCHAR ServiceName; - PCHAR AnsiServiceName; - PCHAR AnsiProtocolName; - PCHAR TempString; - ULONG ServiceNameLength; - ULONG PortNumber = 0; - - /* Make sure that this is valid for a Servent lookup */ - if ((ServiceString) && - (ServiceType) && - (memcmp(ServiceType, &HostnameGuid, sizeof(GUID))) && - (memcmp(ServiceType, &InetHostName, sizeof(GUID)))) - { - /* Extract the Protocol */ - ProtocolString = wcschr(ServiceString, L'/'); - if (!ProtocolString) ProtocolString = wcschr(ProtocolString, L'\0'); - - /* Find out the length of the service name */ - ServiceNameLength = (ULONG)(ProtocolString - ServiceString) * sizeof(WCHAR); - - /* Allocate it */ - ServiceName = DnsApiAlloc(ServiceNameLength + sizeof(UNICODE_NULL)); - - /* Copy it and null-terminate */ - RtlMoveMemory(ServiceName, ServiceString, ServiceNameLength); - ServiceName[ServiceNameLength] = UNICODE_NULL; - - /* Get the Ansi Service Name */ - AnsiServiceName = GetAnsiNameRnR(ServiceName, 0, NULL); - DnsApiFree(ServiceName); - if (AnsiServiceName) - { - /* If we only have a port number, convert it */ - for (TempString = AnsiServiceName; - *TempString && isdigit(*TempString); - TempString++); - - /* Convert to Port Number */ - if (!*TempString) PortNumber = atoi(AnsiServiceName); - - /* Check if we have a Protocol Name, and set it */ - if (!(*ProtocolString) || !(*++ProtocolString)) - { - /* No protocol string, so won't have it in ANSI either */ - AnsiProtocolName = NULL; - } - else - { - /* Get it in ANSI */ - AnsiProtocolName = GetAnsiNameRnR(ProtocolString, 0, NULL); - } - - /* Now do the actual operation */ - if (PortNumber) - { - /* FIXME: Get Servent by Port */ - } - else - { - /* FIXME: Get Servent by Name */ - } - - /* Free the ansi names if we had them */ - if (AnsiProtocolName) DnsApiFree(AnsiProtocolName); - if (AnsiServiceName) DnsApiFree(AnsiProtocolName); - } - } - - /* Return Servent */ - if (ReverseServent) *ReverseServent = LocalServent; - - /* Return Protocol */ - if (LocalServent) - { - /* Check if it was UDP */ - if (_stricmp("udp", LocalServent->s_proto)) - { - /* Return UDP */ - ProtocolFlags = UDP; - } - else - { - /* Return TCP */ - ProtocolFlags = TCP; - } - } - else - { - /* Return both, no restrictions */ - ProtocolFlags = (TCP | UDP); - } - - /* Return the flags */ - return ProtocolFlags; -} - -PSERVENT -WSPAPI -CopyServEntry(IN PSERVENT Servent, - IN OUT PULONG_PTR BufferPos, - IN OUT PULONG BufferFreeSize, - IN OUT PULONG BlobSize, - IN BOOLEAN Relative) -{ - return NULL; -} - diff --git a/dll/win32/mswsock/rnr20/proc.c b/dll/win32/mswsock/rnr20/proc.c index 7336526a34b..42597c43d6f 100644 --- a/dll/win32/mswsock/rnr20/proc.c +++ b/dll/win32/mswsock/rnr20/proc.c @@ -42,135 +42,3 @@ RNRPROV_SockEnterApi(VOID) return TRUE; } -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -BOOLEAN -WINAPI -RNRPROV_SockEnterApi(VOID) -{ - PWINSOCK_TEB_DATA ThreadData; - - /* Make sure we're not terminating */ - if (SockProcessTerminating) - { - SetLastError(WSANOTINITIALISED); - return FALSE; - } - - /* Check if we already intialized */ - ThreadData = NtCurrentTeb()->WinSockData; - if (!(ThreadData) || !(ThreadData->RnrThreadData)) - { - /* Initialize the thread */ - if (!Rnr_ThreadInit()) - { - /* Fail */ - SetLastError(WSAENOBUFS); - return FALSE; - } - } - - /* Return success */ - return TRUE; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -BOOLEAN -WINAPI -RNRPROV_SockEnterApi(VOID) -{ - PWINSOCK_TEB_DATA ThreadData; - - /* Make sure we're not terminating */ - if (SockProcessTerminating) - { - SetLastError(WSANOTINITIALISED); - return FALSE; - } - - /* Check if we already intialized */ - ThreadData = NtCurrentTeb()->WinSockData; - if (!(ThreadData) || !(ThreadData->RnrThreadData)) - { - /* Initialize the thread */ - if (!Rnr_ThreadInit()) - { - /* Fail */ - SetLastError(WSAENOBUFS); - return FALSE; - } - } - - /* Return success */ - return TRUE; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -BOOLEAN -WINAPI -RNRPROV_SockEnterApi(VOID) -{ - PWINSOCK_TEB_DATA ThreadData; - - /* Make sure we're not terminating */ - if (SockProcessTerminating) - { - SetLastError(WSANOTINITIALISED); - return FALSE; - } - - /* Check if we already intialized */ - ThreadData = NtCurrentTeb()->WinSockData; - if (!(ThreadData) || !(ThreadData->RnrThreadData)) - { - /* Initialize the thread */ - if (!Rnr_ThreadInit()) - { - /* Fail */ - SetLastError(WSAENOBUFS); - return FALSE; - } - } - - /* Return success */ - return TRUE; -} - diff --git a/dll/win32/mswsock/rnr20/r_comp.c b/dll/win32/mswsock/rnr20/r_comp.c index 40d1f1bccaf..cbf06b2dc05 100644 --- a/dll/win32/mswsock/rnr20/r_comp.c +++ b/dll/win32/mswsock/rnr20/r_comp.c @@ -8,33 +8,3 @@ /* INCLUDES ******************************************************************/ #include "msafd.h" -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - diff --git a/dll/win32/mswsock/rnr20/util.c b/dll/win32/mswsock/rnr20/util.c index 258edf6fc9c..c8412ab7b5d 100644 --- a/dll/win32/mswsock/rnr20/util.c +++ b/dll/win32/mswsock/rnr20/util.c @@ -30,99 +30,3 @@ Temp_AllocZero(IN DWORD Size) return Data; } -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -PVOID -WSPAPI -Temp_AllocZero(IN DWORD Size) -{ - PVOID Data; - - /* Allocate the memory */ - Data = DnsApiAlloc(Size); - if (Data) - { - /* Zero it out */ - RtlZeroMemory(Data, Size); - } - - /* Return it */ - return Data; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -PVOID -WSPAPI -Temp_AllocZero(IN DWORD Size) -{ - PVOID Data; - - /* Allocate the memory */ - Data = DnsApiAlloc(Size); - if (Data) - { - /* Zero it out */ - RtlZeroMemory(Data, Size); - } - - /* Return it */ - return Data; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -PVOID -WSPAPI -Temp_AllocZero(IN DWORD Size) -{ - PVOID Data; - - /* Allocate the memory */ - Data = DnsApiAlloc(Size); - if (Data) - { - /* Zero it out */ - RtlZeroMemory(Data, Size); - } - - /* Return it */ - return Data; -} - diff --git a/dll/win32/mswsock/wsmobile/lpc.c b/dll/win32/mswsock/wsmobile/lpc.c index 67c2fe25130..6aa6bde21d1 100644 --- a/dll/win32/mswsock/wsmobile/lpc.c +++ b/dll/win32/mswsock/wsmobile/lpc.c @@ -14,51 +14,3 @@ HINSTANCE NlsMsgSourcemModuleHandle; /* FUNCTIONS *****************************************************************/ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -HINSTANCE NlsMsgSourcemModuleHandle; - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -HINSTANCE NlsMsgSourcemModuleHandle; - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -HINSTANCE NlsMsgSourcemModuleHandle; - -/* FUNCTIONS *****************************************************************/ - diff --git a/dll/win32/mswsock/wsmobile/nsp.c b/dll/win32/mswsock/wsmobile/nsp.c index 70d21f483d6..048652a5be8 100644 --- a/dll/win32/mswsock/wsmobile/nsp.c +++ b/dll/win32/mswsock/wsmobile/nsp.c @@ -26,87 +26,3 @@ WSM_NSPStartup(IN LPGUID lpProviderId, return SOCKET_ERROR; } -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -LONG gWSM_NSPStartupRef; -LONG gWSM_NSPCallRef; -GUID gNLANamespaceGuid = NLA_NAMESPACE_GUID; - -/* FUNCTIONS *****************************************************************/ - -INT -WINAPI -WSM_NSPStartup(IN LPGUID lpProviderId, - IN OUT LPNSP_ROUTINE lpsnpRoutines) -{ - /* Go away */ - SetLastError(WSAEINVAL); - return SOCKET_ERROR; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -LONG gWSM_NSPStartupRef; -LONG gWSM_NSPCallRef; -GUID gNLANamespaceGuid = NLA_NAMESPACE_GUID; - -/* FUNCTIONS *****************************************************************/ - -INT -WINAPI -WSM_NSPStartup(IN LPGUID lpProviderId, - IN OUT LPNSP_ROUTINE lpsnpRoutines) -{ - /* Go away */ - SetLastError(WSAEINVAL); - return SOCKET_ERROR; -} - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -LONG gWSM_NSPStartupRef; -LONG gWSM_NSPCallRef; -GUID gNLANamespaceGuid = NLA_NAMESPACE_GUID; - -/* FUNCTIONS *****************************************************************/ - -INT -WINAPI -WSM_NSPStartup(IN LPGUID lpProviderId, - IN OUT LPNSP_ROUTINE lpsnpRoutines) -{ - /* Go away */ - SetLastError(WSAEINVAL); - return SOCKET_ERROR; -} - diff --git a/dll/win32/mswsock/wsmobile/service.c b/dll/win32/mswsock/wsmobile/service.c index 3e062e90d63..bd1ad2806dc 100644 --- a/dll/win32/mswsock/wsmobile/service.c +++ b/dll/win32/mswsock/wsmobile/service.c @@ -12,45 +12,3 @@ /* FUNCTIONS *****************************************************************/ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - diff --git a/dll/win32/mswsock/wsmobile/update.c b/dll/win32/mswsock/wsmobile/update.c index 3e062e90d63..bd1ad2806dc 100644 --- a/dll/win32/mswsock/wsmobile/update.c +++ b/dll/win32/mswsock/wsmobile/update.c @@ -12,45 +12,3 @@ /* FUNCTIONS *****************************************************************/ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Winsock 2 SPI - * FILE: lib/mswsock/lib/init.c - * PURPOSE: DLL Initialization - */ - -/* INCLUDES ******************************************************************/ -#include "msafd.h" - -/* DATA **********************************************************************/ - -/* FUNCTIONS *****************************************************************/ - diff --git a/include/reactos/winsock/msafd.h b/include/reactos/winsock/msafd.h index 1d94bab7f42..b29294fcd7b 100644 --- a/include/reactos/winsock/msafd.h +++ b/include/reactos/winsock/msafd.h @@ -50,55 +50,3 @@ #include "mswinsock.h" /* EOF */ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Ancillary Function Driver DLL - * FILE: include/msafd.h - * PURPOSE: Ancillary Function Driver DLL header - */ - -#define NTOS_MODE_USER -#define WIN32_NO_STATUS -#define _CRT_SECURE_NO_DEPRECATE -#define _WIN32_WINNT 0x502 - -/* Winsock Headers */ -#include -#include -#include -#include -#include -#include -#include - -/* NDK */ -#include -#include -#include -#include -#include - -/* Shared NSP Header */ -#include - -/* Winsock 2 API Helper Header */ -#include - -/* Winsock Helper Header */ -#include - -/* AFD/TDI Headers */ -#include -#include - -/* DNSLIB/API Header */ -#include -#include - -/* Library Headers */ -#include "msafdlib.h" -#include "rnr20lib.h" -#include "wsmobile.h" -#include "mswinsock.h" - -/* EOF */ diff --git a/include/reactos/winsock/msafdlib.h b/include/reactos/winsock/msafdlib.h index 2c5548b8af6..0944141e6f8 100644 --- a/include/reactos/winsock/msafdlib.h +++ b/include/reactos/winsock/msafdlib.h @@ -826,831 +826,3 @@ WSPStringToAddress( OUT LPSOCKADDR lpAddress, IN OUT LPINT lpAddressLength, OUT LPINT lpErrno); -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS WinSock 2 NSP - * FILE: lib/mswsock/sock.h - * PURPOSE: Winsock 2 SPI Utility Header - */ - -#define NO_BLOCKING_HOOK 0 -#define MAYBE_BLOCKING_HOOK 1 -#define ALWAYS_BLOCKING_HOOK 2 - -#define NO_TIMEOUT 0 -#define SEND_TIMEOUT 1 -#define RECV_TIMEOUT 2 - -#define MAX_TDI_ADDRESS_LENGTH 32 - -#define WSA_FLAG_MULTIPOINT_ALL (WSA_FLAG_MULTIPOINT_C_ROOT |\ - WSA_FLAG_MULTIPOINT_C_LEAF |\ - WSA_FLAG_MULTIPOINT_D_ROOT |\ - WSA_FLAG_MULTIPOINT_D_LEAF) - - -/* Socket State */ -typedef enum _SOCKET_STATE -{ - SocketUndefined = -1, - SocketOpen, - SocketBound, - SocketBoundUdp, - SocketConnected, - SocketClosed -} SOCKET_STATE, *PSOCKET_STATE; - -/* - * Shared Socket Information. - * It's called shared because we send it to Kernel-Mode for safekeeping - */ -typedef struct _SOCK_SHARED_INFO { - SOCKET_STATE State; - INT AddressFamily; - INT SocketType; - INT Protocol; - INT SizeOfLocalAddress; - INT SizeOfRemoteAddress; - struct linger LingerData; - ULONG SendTimeout; - ULONG RecvTimeout; - ULONG SizeOfRecvBuffer; - ULONG SizeOfSendBuffer; - struct { - BOOLEAN Listening:1; - BOOLEAN Broadcast:1; - BOOLEAN Debug:1; - BOOLEAN OobInline:1; - BOOLEAN ReuseAddresses:1; - BOOLEAN ExclusiveAddressUse:1; - BOOLEAN NonBlocking:1; - BOOLEAN DontUseWildcard:1; - BOOLEAN ReceiveShutdown:1; - BOOLEAN SendShutdown:1; - BOOLEAN UseDelayedAcceptance:1; - BOOLEAN UseSAN:1; - }; // Flags - DWORD CreateFlags; - DWORD CatalogEntryId; - DWORD ServiceFlags1; - DWORD ProviderFlags; - GROUP GroupID; - DWORD GroupType; - INT GroupPriority; - INT SocketLastError; - HWND hWnd; - LONG Unknown; - DWORD SequenceNumber; - UINT wMsg; - LONG AsyncEvents; - LONG AsyncDisabledEvents; -} SOCK_SHARED_INFO, *PSOCK_SHARED_INFO; - -/* Socket Helper Data. Holds information about the WSH Libraries */ -typedef struct _HELPER_DATA { - LIST_ENTRY Helpers; - LONG RefCount; - HANDLE hInstance; - INT MinWSAddressLength; - INT MaxWSAddressLength; - INT MinTDIAddressLength; - INT MaxTDIAddressLength; - BOOLEAN UseDelayedAcceptance; - PWINSOCK_MAPPING Mapping; - PWSH_OPEN_SOCKET WSHOpenSocket; - PWSH_OPEN_SOCKET2 WSHOpenSocket2; - PWSH_JOIN_LEAF WSHJoinLeaf; - PWSH_NOTIFY WSHNotify; - PWSH_GET_SOCKET_INFORMATION WSHGetSocketInformation; - PWSH_SET_SOCKET_INFORMATION WSHSetSocketInformation; - PWSH_GET_SOCKADDR_TYPE WSHGetSockaddrType; - PWSH_GET_WILDCARD_SOCKADDR WSHGetWildcardSockaddr; - PWSH_GET_BROADCAST_SOCKADDR WSHGetBroadcastSockaddr; - PWSH_ADDRESS_TO_STRING WSHAddressToString; - PWSH_STRING_TO_ADDRESS WSHStringToAddress; - PWSH_IOCTL WSHIoctl; - WCHAR TransportName[1]; -} HELPER_DATA, *PHELPER_DATA; - -typedef struct _ASYNC_DATA -{ - struct _SOCKET_INFORMATION *ParentSocket; - DWORD SequenceNumber; - IO_STATUS_BLOCK IoStatusBlock; - AFD_POLL_INFO AsyncSelectInfo; -} ASYNC_DATA, *PASYNC_DATA; - -/* The actual Socket Structure represented by a handle. Internal to us */ -typedef struct _SOCKET_INFORMATION { - union { - WSH_HANDLE WshContext; - struct { - LONG RefCount; - SOCKET Handle; - }; - }; - SOCK_SHARED_INFO SharedData; - GUID ProviderId; - DWORD HelperEvents; - PHELPER_DATA HelperData; - PVOID HelperContext; - PSOCKADDR LocalAddress; - PSOCKADDR RemoteAddress; - HANDLE TdiAddressHandle; - HANDLE TdiConnectionHandle; - PASYNC_DATA AsyncData; - HANDLE EventObject; - LONG NetworkEvents; - CRITICAL_SECTION Lock; - BOOL DontUseSan; - PVOID SanData; -} SOCKET_INFORMATION, *PSOCKET_INFORMATION; - -/* The blob of data we send to Kernel-Mode for safekeeping */ -typedef struct _SOCKET_CONTEXT { - SOCK_SHARED_INFO SharedData; - ULONG SizeOfHelperData; - ULONG Padding; - SOCKADDR LocalAddress; - SOCKADDR RemoteAddress; - /* Plus Helper Data */ -} SOCKET_CONTEXT, *PSOCKET_CONTEXT; - -typedef struct _SOCK_RW_LOCK -{ - volatile LONG ReaderCount; - HANDLE WriterWaitEvent; - RTL_CRITICAL_SECTION Lock; -} SOCK_RW_LOCK, *PSOCK_RW_LOCK; - -typedef struct _WINSOCK_TEB_DATA -{ - HANDLE EventHandle; - SOCKET SocketHandle; - PAFD_ACCEPT_DATA AcceptData; - LONG PendingAPCs; - BOOLEAN CancelIo; - ULONG Unknown; - PVOID RnrThreadData; -} WINSOCK_TEB_DATA, *PWINSOCK_TEB_DATA; - -typedef INT -(WINAPI *PICF_CONNECT)(PVOID IcfData); - -typedef struct _SOCK_ICF_DATA -{ - HANDLE IcfHandle; - PVOID IcfOpenDynamicFwPort; - PICF_CONNECT IcfConnect; - PVOID IcfDisconnect; - HINSTANCE DllHandle; -} SOCK_ICF_DATA, *PSOCK_ICF_DATA; - -typedef PVOID -(NTAPI *PRTL_HEAP_ALLOCATE)( - IN HANDLE Heap, - IN ULONG Flags, - IN ULONG Size -); - -extern HANDLE SockPrivateHeap; -extern PRTL_HEAP_ALLOCATE SockAllocateHeapRoutine; -extern SOCK_RW_LOCK SocketGlobalLock; -extern PWAH_HANDLE_TABLE SockContextTable; -extern LPWSPUPCALLTABLE SockUpcallTable; -extern BOOL SockProcessTerminating; -extern LONG SockWspStartupCount; -extern DWORD SockSendBufferWindow; -extern DWORD SockReceiveBufferWindow; -extern HANDLE SockAsyncQueuePort; -extern BOOLEAN SockAsyncSelectCalled; -extern LONG SockProcessPendingAPCCount; -extern HINSTANCE SockModuleHandle; -extern LONG gWSM_NSPStartupRef; -extern LONG gWSM_NSPCallRef; -extern LIST_ENTRY SockHelperDllListHead; -extern CRITICAL_SECTION MSWSOCK_SocketLock; -extern HINSTANCE NlsMsgSourcemModuleHandle; -extern PVOID SockBufferKeyTable; -extern ULONG SockBufferKeyTableSize; -extern LONG SockAsyncThreadReferenceCount; -extern BOOLEAN g_fRnrLockInit; -extern CRITICAL_SECTION g_RnrLock; - -BOOL -WSPAPI -MSWSOCK_Initialize(VOID); - -BOOL -WSPAPI -MSAFD_SockThreadInitialize(VOID); - -INT -WSPAPI -SockCreateAsyncQueuePort(VOID); - -PVOID -WSPAPI -SockInitializeHeap(IN HANDLE Heap, - IN ULONG Flags, - IN ULONG Size); - -NTSTATUS -WSPAPI -SockInitializeRwLockAndSpinCount( - IN PSOCK_RW_LOCK Lock, - IN ULONG SpinCount -); - -VOID -WSPAPI -SockAcquireRwLockExclusive(IN PSOCK_RW_LOCK Lock); - -VOID -WSPAPI -SockAcquireRwLockShared(IN PSOCK_RW_LOCK Lock); - -VOID -WSPAPI -SockReleaseRwLockExclusive(IN PSOCK_RW_LOCK Lock); - -VOID -WSPAPI -SockReleaseRwLockShared(IN PSOCK_RW_LOCK Lock); - -NTSTATUS -WSPAPI -SockDeleteRwLock(IN PSOCK_RW_LOCK Lock); - -INT -WSPAPI -SockGetConnectData(IN PSOCKET_INFORMATION Socket, - IN ULONG Ioctl, - IN PVOID Buffer, - IN ULONG BufferLength, - OUT PULONG BufferReturned); - -INT -WSPAPI -SockIsAddressConsistentWithConstrainedGroup(IN PSOCKET_INFORMATION Socket, - IN GROUP Group, - IN PSOCKADDR SocketAddress, - IN INT SocketAddressLength); - -BOOL -WSPAPI -SockWaitForSingleObject(IN HANDLE Handle, - IN SOCKET SocketHandle, - IN DWORD BlockingFlags, - IN DWORD TimeoutFlags); - -BOOLEAN -WSPAPI -SockIsSocketConnected(IN PSOCKET_INFORMATION Socket); - -INT -WSPAPI -SockNotifyHelperDll(IN PSOCKET_INFORMATION Socket, - IN DWORD Event); - -INT -WSPAPI -SockUpdateWindowSizes(IN PSOCKET_INFORMATION Socket, - IN BOOLEAN Force); - -INT -WSPAPI -SockBuildTdiAddress(OUT PTRANSPORT_ADDRESS TdiAddress, - IN PSOCKADDR Sockaddr, - IN INT SockaddrLength); - -INT -WSPAPI -SockBuildSockaddr(OUT PSOCKADDR Sockaddr, - OUT PINT SockaddrLength, - IN PTRANSPORT_ADDRESS TdiAddress); - -INT -WSPAPI -SockGetTdiHandles(IN PSOCKET_INFORMATION Socket); - -VOID -WSPAPI -SockIoCompletion(IN PVOID ApcContext, - IN PIO_STATUS_BLOCK IoStatusBlock, - DWORD Reserved); - -VOID -WSPAPI -SockCancelIo(IN SOCKET Handle); - -INT -WSPAPI -SockGetInformation(IN PSOCKET_INFORMATION Socket, - IN ULONG AfdInformationClass, - IN PVOID ExtraData OPTIONAL, - IN ULONG ExtraDataSize, - IN OUT PBOOLEAN Boolean OPTIONAL, - IN OUT PULONG Ulong OPTIONAL, - IN OUT PLARGE_INTEGER LargeInteger OPTIONAL); - -INT -WSPAPI -SockSetInformation(IN PSOCKET_INFORMATION Socket, - IN ULONG AfdInformationClass, - IN PBOOLEAN Boolean OPTIONAL, - IN PULONG Ulong OPTIONAL, - IN PLARGE_INTEGER LargeInteger OPTIONAL); - -INT -WSPAPI -SockSetHandleContext(IN PSOCKET_INFORMATION Socket); - -VOID -WSPAPI -SockDereferenceSocket(IN PSOCKET_INFORMATION Socket); - -VOID -WSPAPI -SockFreeHelperDll(IN PHELPER_DATA Helper); - -PSOCKET_INFORMATION -WSPAPI -SockFindAndReferenceSocket(IN SOCKET Handle, - IN BOOLEAN Import); - -INT -WSPAPI -SockEnterApiSlow(OUT PWINSOCK_TEB_DATA *ThreadData); - -VOID -WSPAPI -SockSanInitialize(VOID); - -VOID -WSPAPI -SockSanGetTcpipCatalogId(VOID); - -VOID -WSPAPI -CloseIcfConnection(IN PSOCK_ICF_DATA IcfData); - -VOID -WSPAPI -InitializeIcfConnection(IN PSOCK_ICF_DATA IcfData); - -VOID -WSPAPI -NewIcfConnection(IN PSOCK_ICF_DATA IcfData); - -INT -WSPAPI -NtStatusToSocketError(IN NTSTATUS Status); - -INT -WSPAPI -SockSocket(INT AddressFamily, - INT SocketType, - INT Protocol, - LPGUID ProviderId, - GROUP g, - DWORD dwFlags, - DWORD ProviderFlags, - DWORD ServiceFlags, - DWORD CatalogEntryId, - PSOCKET_INFORMATION *NewSocket); - -INT -WSPAPI -SockCloseSocket(IN PSOCKET_INFORMATION Socket); - -FORCEINLINE -INT -WSPAPI -SockEnterApiFast(OUT PWINSOCK_TEB_DATA *ThreadData) -{ - /* Make sure we aren't terminating and get our thread data */ - if (!(SockProcessTerminating) && - (SockWspStartupCount > 0) && - ((*ThreadData == NtCurrentTeb()->WinSockData))) - { - /* Everything is good, return */ - return NO_ERROR; - } - - /* Something didn't work out, use the slow path */ - return SockEnterApiSlow(ThreadData); -} - -FORCEINLINE -VOID -WSPAPI -SockDereferenceHelperDll(IN PHELPER_DATA Helper) -{ - /* Dereference and see if it's the last count */ - if (!InterlockedDecrement(&Helper->RefCount)) - { - /* Destroy the Helper DLL */ - SockFreeHelperDll(Helper); - } -} - -#define MSAFD_IS_DGRAM_SOCK(s) \ - (s->SharedData.ServiceFlags1 & XP1_CONNECTIONLESS) - -/* Global data that we want to share access with */ -extern HANDLE SockSanCleanUpCompleteEvent; -extern BOOLEAN SockSanEnabled; -extern WSAPROTOCOL_INFOW SockTcpProviderInfo; - -typedef VOID -(WSPAPI *PASYNC_COMPLETION_ROUTINE)( - PVOID Context, - PIO_STATUS_BLOCK IoStatusBlock -); - -/* Internal Helper Functions */ -INT -WSPAPI -SockLoadHelperDll( - PWSTR TransportName, - PWINSOCK_MAPPING Mapping, - PHELPER_DATA *HelperDllData -); - -INT -WSPAPI -SockLoadTransportMapping( - PWSTR TransportName, - PWINSOCK_MAPPING *Mapping -); - -INT -WSPAPI -SockLoadTransportList( - PWSTR *TransportList -); - -BOOL -WSPAPI -SockIsTripleInMapping(IN PWINSOCK_MAPPING Mapping, - IN INT AddressFamily, - OUT PBOOLEAN AfMatch, - IN INT SocketType, - OUT PBOOLEAN SockMatch, - IN INT Protocol, - OUT PBOOLEAN ProtoMatch); - -INT -WSPAPI -SockAsyncSelectHelper(IN PSOCKET_INFORMATION Socket, - IN HWND hWnd, - IN UINT wMsg, - IN LONG Events); - -INT -WSPAPI -SockEventSelectHelper(IN PSOCKET_INFORMATION Socket, - IN WSAEVENT EventObject, - IN LONG Events); - -BOOLEAN -WSPAPI -SockCheckAndReferenceAsyncThread(VOID); - -BOOLEAN -WSPAPI -SockCheckAndInitAsyncSelectHelper(VOID); - -INT -WSPAPI -SockGetTdiName(PINT AddressFamily, - PINT SocketType, - PINT Protocol, - LPGUID ProviderId, - GROUP Group, - DWORD Flags, - PUNICODE_STRING TransportName, - PVOID *HelperDllContext, - PHELPER_DATA *HelperDllData, - PDWORD Events); - -INT -WSPAPI -SockAsyncThread( - PVOID ThreadParam -); - -VOID -WSPAPI -SockProcessAsyncSelect(PSOCKET_INFORMATION Socket, - PASYNC_DATA AsyncData); - -VOID -WSPAPI -SockHandleAsyncIndication(IN PASYNC_COMPLETION_ROUTINE Callback, - IN PVOID Context, - IN PIO_STATUS_BLOCK IoStatusBlock); - -INT -WSPAPI -SockReenableAsyncSelectEvent(IN PSOCKET_INFORMATION Socket, - IN ULONG Event); - -VOID -WSPAPI -SockProcessQueuedAsyncSelect(PVOID Context, - PIO_STATUS_BLOCK IoStatusBlock); - -VOID -WSPAPI -SockAsyncSelectCompletion( - PVOID Context, - PIO_STATUS_BLOCK IoStatusBlock -); - -/* Public functions, but not exported! */ -SOCKET -WSPAPI -WSPAccept( - IN SOCKET s, - OUT LPSOCKADDR addr, - IN OUT LPINT addrlen, - IN LPCONDITIONPROC lpfnCondition, - IN DWORD dwCallbackData, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPAddressToString( - IN LPSOCKADDR lpsaAddress, - IN DWORD dwAddressLength, - IN LPWSAPROTOCOL_INFOW lpProtocolInfo, - OUT LPWSTR lpszAddressString, - IN OUT LPDWORD lpdwAddressStringLength, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPAsyncSelect( - IN SOCKET s, - IN HWND hWnd, - IN UINT wMsg, - IN LONG lEvent, - OUT LPINT lpErrno); - -INT -WSPAPI WSPBind( - IN SOCKET s, - IN CONST SOCKADDR *name, - IN INT namelen, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPCancelBlockingCall( - OUT LPINT lpErrno); - -INT -WSPAPI -WSPCleanup( - OUT LPINT lpErrno); - -INT -WSPAPI -WSPCloseSocket( - IN SOCKET s, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPConnect( - IN SOCKET s, - IN CONST SOCKADDR *name, - IN INT namelen, - IN LPWSABUF lpCallerData, - OUT LPWSABUF lpCalleeData, - IN LPQOS lpSQOS, - IN LPQOS lpGQOS, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPDuplicateSocket( - IN SOCKET s, - IN DWORD dwProcessId, - OUT LPWSAPROTOCOL_INFOW lpProtocolInfo, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPEnumNetworkEvents( - IN SOCKET s, - IN WSAEVENT hEventObject, - OUT LPWSANETWORKEVENTS lpNetworkEvents, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPEventSelect( - IN SOCKET s, - IN WSAEVENT hEventObject, - IN LONG lNetworkEvents, - OUT LPINT lpErrno); - -BOOL -WSPAPI -WSPGetOverlappedResult( - IN SOCKET s, - IN LPWSAOVERLAPPED lpOverlapped, - OUT LPDWORD lpcbTransfer, - IN BOOL fWait, - OUT LPDWORD lpdwFlags, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPGetPeerName( - IN SOCKET s, - OUT LPSOCKADDR name, - IN OUT LPINT namelen, - OUT LPINT lpErrno); - -BOOL -WSPAPI -WSPGetQOSByName( - IN SOCKET s, - IN OUT LPWSABUF lpQOSName, - OUT LPQOS lpQOS, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPGetSockName( - IN SOCKET s, - OUT LPSOCKADDR name, - IN OUT LPINT namelen, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPGetSockOpt( - IN SOCKET s, - IN INT level, - IN INT optname, - OUT CHAR FAR* optval, - IN OUT LPINT optlen, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPIoctl( - IN SOCKET s, - IN DWORD dwIoControlCode, - IN LPVOID lpvInBuffer, - IN DWORD cbInBuffer, - OUT LPVOID lpvOutBuffer, - IN DWORD cbOutBuffer, - OUT LPDWORD lpcbBytesReturned, - IN LPWSAOVERLAPPED lpOverlapped, - IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, - IN LPWSATHREADID lpThreadId, - OUT LPINT lpErrno); - -SOCKET -WSPAPI -WSPJoinLeaf( - IN SOCKET s, - IN CONST SOCKADDR *name, - IN INT namelen, - IN LPWSABUF lpCallerData, - OUT LPWSABUF lpCalleeData, - IN LPQOS lpSQOS, - IN LPQOS lpGQOS, - IN DWORD dwFlags, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPListen( - IN SOCKET s, - IN INT backlog, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPRecv( - IN SOCKET s, - IN OUT LPWSABUF lpBuffers, - IN DWORD dwBufferCount, - OUT LPDWORD lpNumberOfBytesRecvd, - IN OUT LPDWORD lpFlags, - IN LPWSAOVERLAPPED lpOverlapped, - IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, - IN LPWSATHREADID lpThreadId, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPRecvDisconnect( - IN SOCKET s, - OUT LPWSABUF lpInboundDisconnectData, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPRecvFrom( - IN SOCKET s, - IN OUT LPWSABUF lpBuffers, - IN DWORD dwBufferCount, - OUT LPDWORD lpNumberOfBytesRecvd, - IN OUT LPDWORD lpFlags, - OUT LPSOCKADDR lpFrom, - IN OUT LPINT lpFromlen, - IN LPWSAOVERLAPPED lpOverlapped, - IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, - IN LPWSATHREADID lpThreadId, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPSelect( - IN INT nfds, - IN OUT LPFD_SET readfds, - IN OUT LPFD_SET writefds, - IN OUT LPFD_SET exceptfds, - IN CONST LPTIMEVAL timeout, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPSend( - IN SOCKET s, - IN LPWSABUF lpBuffers, - IN DWORD dwBufferCount, - OUT LPDWORD lpNumberOfBytesSent, - IN DWORD dwFlags, - IN LPWSAOVERLAPPED lpOverlapped, - IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, - IN LPWSATHREADID lpThreadId, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPSendDisconnect( - IN SOCKET s, - IN LPWSABUF lpOutboundDisconnectData, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPSendTo( - IN SOCKET s, - IN LPWSABUF lpBuffers, - IN DWORD dwBufferCount, - OUT LPDWORD lpNumberOfBytesSent, - IN DWORD dwFlags, - IN CONST SOCKADDR *lpTo, - IN INT iTolen, - IN LPWSAOVERLAPPED lpOverlapped, - IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, - IN LPWSATHREADID lpThreadId, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPSetSockOpt( - IN SOCKET s, - IN INT level, - IN INT optname, - IN CONST CHAR FAR* optval, - IN INT optlen, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPShutdown( - IN SOCKET s, - IN INT how, - OUT LPINT lpErrno); - -SOCKET -WSPAPI -WSPSocket( - IN INT af, - IN INT type, - IN INT protocol, - IN LPWSAPROTOCOL_INFOW lpProtocolInfo, - IN GROUP g, - IN DWORD dwFlags, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPStringToAddress( - IN LPWSTR AddressString, - IN INT AddressFamily, - IN LPWSAPROTOCOL_INFOW lpProtocolInfo, - OUT LPSOCKADDR lpAddress, - IN OUT LPINT lpAddressLength, - OUT LPINT lpErrno); diff --git a/include/reactos/winsock/mswinsock.h b/include/reactos/winsock/mswinsock.h index 403b5ea3550..fff06fc7416 100644 --- a/include/reactos/winsock/mswinsock.h +++ b/include/reactos/winsock/mswinsock.h @@ -17,22 +17,3 @@ typedef struct _NS_ROUTINE { #endif -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Ancillary Function Driver DLL - * FILE: include/mswsock.h - * PURPOSE: Ancillary Function Driver DLL header - */ -#ifndef __MSWINSOCK_H -#define __MSWINSOCK_H - -typedef DWORD (* LPFN_NSPAPI)(VOID); -typedef struct _NS_ROUTINE { - DWORD dwFunctionCount; - LPFN_NSPAPI *alpfnFunctions; - DWORD dwNameSpace; - DWORD dwPriority; -} NS_ROUTINE, *PNS_ROUTINE, * FAR LPNS_ROUTINE; - -#endif - diff --git a/include/reactos/winsock/rnr20lib.h b/include/reactos/winsock/rnr20lib.h index d44793345fa..38410e2d26e 100644 --- a/include/reactos/winsock/rnr20lib.h +++ b/include/reactos/winsock/rnr20lib.h @@ -263,268 +263,3 @@ Dns_NSPStartup( #endif -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS WinSock 2 NSP - * FILE: include/nsp_dns.h - * PURPOSE: WinSock 2 NSP Header - */ - -#ifndef __NSP_H -#define __NSP_H - -/* DEFINES *******************************************************************/ - -/* Lookup Flags */ -#define DONE 0x01 -#define REVERSE 0x02 -#define LOCAL 0x04 -#define IANA 0x10 -#define LOOPBACK 0x20 - -/* Protocol Flags */ -#define UDP 0x01 -#define TCP 0x02 -#define ATM 0x04 - -/* GUID Masks */ -#define NBT_MASK 0x01 -#define DNS_MASK 0x02 - -/* TYPES *********************************************************************/ - -typedef struct _RNR_CONTEXT -{ - LIST_ENTRY ListEntry; - HANDLE Handle; - PDNS_BLOB CachedSaBlob; - DWORD Signature; - DWORD RefCount; - DWORD Instance; - DWORD LookupFlags; - DWORD RnrId; - DWORD dwNameSpace; - DWORD RrType; - DWORD dwControlFlags; - DWORD UdpPort; - DWORD TcpPort; - DWORD ProtocolFlags; - BLOB CachedBlob; - GUID lpServiceClassId; - GUID lpProviderId; - WCHAR ServiceName[1]; -} RNR_CONTEXT, *PRNR_CONTEXT; - -typedef struct _RNR_TEB_DATA -{ - ULONG Foo; -} RNR_TEB_DATA, *PRNR_TEB_DATA; - -/* PROTOTYPES ****************************************************************/ - -/* - * proc.c - */ -BOOLEAN -WINAPI -RNRPROV_SockEnterApi(VOID); - -/* - * oldutil.c - */ -DWORD -WINAPI -GetServerAndProtocolsFromString( - PWCHAR ServiceString, - LPGUID ServiceType, - PSERVENT *ReverseServent -); - -DWORD -WINAPI -FetchPortFromClassInfo( - IN DWORD Type, - IN LPGUID Guid, - IN LPWSASERVICECLASSINFOW ServiceClassInfo -); - -PSERVENT -WSPAPI -CopyServEntry( - IN PSERVENT Servent, - IN OUT PULONG_PTR BufferPos, - IN OUT PULONG BufferFreeSize, - IN OUT PULONG BlobSize, - IN BOOLEAN Relative -); - -WORD -WINAPI -GetDnsQueryTypeFromGuid( - IN LPGUID Guid -); - -/* - * context.c - */ -VOID -WSPAPI -RnrCtx_ListCleanup(VOID); - -VOID -WSPAPI -RnrCtx_Release(PRNR_CONTEXT RnrContext); - -PRNR_CONTEXT -WSPAPI -RnrCtx_Get( - HANDLE LookupHandle, - DWORD dwControlFlags, - PLONG Instance -); - -PRNR_CONTEXT -WSPAPI -RnrCtx_Create( - IN HANDLE LookupHandle, - IN LPWSTR ServiceName -); - -VOID -WSPAPI -RnrCtx_DecInstance(IN PRNR_CONTEXT RnrContext); - -/* - * util.c - */ -PVOID -WSPAPI -Temp_AllocZero(IN DWORD Size); - -/* - * lookup.c - */ -PDNS_BLOB -WSPAPI -Rnr_DoHostnameLookup(IN PRNR_CONTEXT Context); - -PDNS_BLOB -WSPAPI -Rnr_GetHostByAddr(IN PRNR_CONTEXT Context); - -PDNS_BLOB -WSPAPI -Rnr_DoDnsLookup(IN PRNR_CONTEXT Context); - -BOOLEAN -WINAPI -Rnr_CheckIfUseNbt(PRNR_CONTEXT RnrContext); - -PDNS_BLOB -WINAPI -Rnr_NbtResolveAddr(IN IN_ADDR Address); - -PDNS_BLOB -WINAPI -Rnr_NbtResolveName(IN LPWSTR Name); - -/* - * init.c - */ -VOID -WSPAPI -Rnr_ProcessInit(VOID); - -VOID -WSPAPI -Rnr_ProcessCleanup(VOID); - -BOOLEAN -WSPAPI -Rnr_ThreadInit(VOID); - -VOID -WSPAPI -Rnr_ThreadCleanup(VOID); - -/* - * nsp.c - */ -VOID -WSPAPI -Nsp_GlobalCleanup(VOID); - -INT -WINAPI -Dns_NSPCleanup(IN LPGUID lpProviderId); - -INT -WINAPI -Dns_NSPSetService( - IN LPGUID lpProviderId, - IN LPWSASERVICECLASSINFOW lpServiceClassInfo, - IN LPWSAQUERYSETW lpqsRegInfo, - IN WSAESETSERVICEOP essOperation, - IN DWORD dwControlFlags -); - -INT -WINAPI -Dns_NSPInstallServiceClass( - IN LPGUID lpProviderId, - IN LPWSASERVICECLASSINFOW lpServiceClassInfo -); - -INT -WINAPI -Dns_NSPRemoveServiceClass( - IN LPGUID lpProviderId, - IN LPGUID lpServiceCallId -); - -INT -WINAPI -Dns_NSPGetServiceClassInfo( - IN LPGUID lpProviderId, - IN OUT LPDWORD lpdwBufSize, - IN OUT LPWSASERVICECLASSINFOW lpServiceClassInfo -); - -INT -WINAPI -Dns_NSPLookupServiceBegin( - LPGUID lpProviderId, - LPWSAQUERYSETW lpqsRestrictions, - LPWSASERVICECLASSINFOW lpServiceClassInfo, - DWORD dwControlFlags, - LPHANDLE lphLookup -); - -INT -WINAPI -Dns_NSPLookupServiceNext( - IN HANDLE hLookup, - IN DWORD dwControlFlags, - IN OUT LPDWORD lpdwBufferLength, - OUT LPWSAQUERYSETW lpqsResults -); - -INT -WINAPI -Dns_NSPLookupServiceEnd(IN HANDLE hLookup); - -INT -WINAPI -Dns_NSPStartup( - IN LPGUID lpProviderId, - IN OUT LPNSP_ROUTINE lpsnpRoutines -); - -/* Unchecked yet */ -#define ATM_ADDRESS_LENGTH 20 -#define WS2_INTERNAL_MAX_ALIAS 16 -#define MAX_HOSTNAME_LEN 256 -#define MAXADDRS 16 - -#endif - diff --git a/include/reactos/winsock/wsmobile.h b/include/reactos/winsock/wsmobile.h index 3bfce930837..1ce31b95328 100644 --- a/include/reactos/winsock/wsmobile.h +++ b/include/reactos/winsock/wsmobile.h @@ -82,87 +82,3 @@ WSM_NSPStartup( #endif -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS WinSock 2 NSP - * FILE: include/nsp_dns.h - * PURPOSE: WinSock 2 NSP Header - */ - -#ifndef __WSM_H -#define __WSM_H - -/* nsp.cpp */ -extern GUID gNLANamespaceGuid; - -/* - * nsp.cpp - */ -INT -WINAPI -WSM_NSPCleanup(IN LPGUID lpProviderId); - -INT -WINAPI -WSM_NSPSetService( - IN LPGUID lpProviderId, - IN LPWSASERVICECLASSINFOW lpServiceClassInfo, - IN LPWSAQUERYSETW lpqsRegInfo, - IN WSAESETSERVICEOP essOperation, - IN DWORD dwControlFlags -); - -INT -WINAPI -WSM_NSPInstallServiceClass( - IN LPGUID lpProviderId, - IN LPWSASERVICECLASSINFOW lpServiceClassInfo -); - -INT -WINAPI -WSM_NSPRemoveServiceClass( - IN LPGUID lpProviderId, - IN LPGUID lpServiceCallId -); - -INT -WINAPI -WSM_NSPGetServiceClassInfo( - IN LPGUID lpProviderId, - IN OUT LPDWORD lpdwBufSize, - IN OUT LPWSASERVICECLASSINFOW lpServiceClassInfo -); - -INT -WINAPI -WSM_NSPLookupServiceBegin( - LPGUID lpProviderId, - LPWSAQUERYSETW lpqsRestrictions, - LPWSASERVICECLASSINFOW lpServiceClassInfo, - DWORD dwControlFlags, - LPHANDLE lphLookup -); - -INT -WINAPI -WSM_NSPLookupServiceNext( - IN HANDLE hLookup, - IN DWORD dwControlFlags, - IN OUT LPDWORD lpdwBufferLength, - OUT LPWSAQUERYSETW lpqsResults -); - -INT -WINAPI -WSM_NSPLookupServiceEnd(IN HANDLE hLookup); - -INT -WINAPI -WSM_NSPStartup( - IN LPGUID lpProviderId, - IN OUT LPNSP_ROUTINE lpsnpRoutines -); - -#endif - From 9e677d15e1de72a050ed4f975a580dcbcc482df4 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sat, 6 Feb 2010 14:29:09 +0000 Subject: [PATCH 18/24] - Forgot this file (sorry) - mswsock.dll compiles and links now :) svn path=/branches/aicom-network-branch/; revision=45461 --- dll/win32/mswsock/dns/inc/precomp.h | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 dll/win32/mswsock/dns/inc/precomp.h diff --git a/dll/win32/mswsock/dns/inc/precomp.h b/dll/win32/mswsock/dns/inc/precomp.h new file mode 100644 index 00000000000..b30cb072d00 --- /dev/null +++ b/dll/win32/mswsock/dns/inc/precomp.h @@ -0,0 +1,24 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS DNS Shared Library + * FILE: lib/dnslib/precomp.h + * PURPOSE: DNSLIB Precompiled Header + */ + +#define _CRT_SECURE_NO_DEPRECATE +#define _WIN32_WINNT 0x502 +#define WIN32_NO_STATUS + +/* PSDK Headers */ +#include +#include +#include + +/* DNSLIB and DNSAPI Headers */ +#include +#include + +/* NDK */ +#include + +/* EOF */ From 2597cfe258b768473a744df30227f4067252d9b7 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Tue, 9 Feb 2010 17:58:11 +0000 Subject: [PATCH 19/24] - Fix the LARGE_SIZE constant so it uses the lookaside list for mbuf ext buffers allocations again - We added one byte to each ext buffer as a ref count for oskit_buffer_* functions so we need to compensate for that by adding one byte to the LARGE_SIZE constant - This should boost performance too because we allocate one ext buffer for each incoming and outgoing TCP packet svn path=/branches/aicom-network-branch/; revision=45531 --- lib/drivers/ip/transport/tcp/event.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/drivers/ip/transport/tcp/event.c b/lib/drivers/ip/transport/tcp/event.c index 9badd7bcd97..c3762f2c548 100644 --- a/lib/drivers/ip/transport/tcp/event.c +++ b/lib/drivers/ip/transport/tcp/event.c @@ -119,7 +119,7 @@ int TCPPacketSend(void *ClientData, OSK_PCHAR data, OSK_UINT len ) { #define MEM_PROFILE 0 #define SMALL_SIZE 128 -#define LARGE_SIZE 2048 +#define LARGE_SIZE 2049 #define SIGNATURE_LARGE 'LLLL' #define SIGNATURE_SMALL 'SSSS' From 22e30001434a8ba19bf9e61055dc2ef1945bb0c3 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Wed, 10 Feb 2010 00:53:03 +0000 Subject: [PATCH 20/24] - Fix comments related to r45531 svn path=/branches/aicom-network-branch/; revision=45545 --- lib/drivers/ip/transport/tcp/event.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/drivers/ip/transport/tcp/event.c b/lib/drivers/ip/transport/tcp/event.c index c3762f2c548..4534da39c05 100644 --- a/lib/drivers/ip/transport/tcp/event.c +++ b/lib/drivers/ip/transport/tcp/event.c @@ -107,11 +107,11 @@ int TCPPacketSend(void *ClientData, OSK_PCHAR data, OSK_UINT len ) { /* Memory management routines * - * By far the most requests for memory are either for 128 or 2048 byte blocks, + * By far the most requests for memory are either for 128 or 2049 byte blocks, * so we want to satisfy those from lookaside lists. Unfortunately, the * TCPFree() function doesn't pass the size of the block to be freed, so we * need to keep track of it ourselves. We do it by prepending each block with - * 4 bytes, indicating if this is a 'L'arge (2048), 'S'mall (128) or 'O'ther + * 4 bytes, indicating if this is a 'L'arge (2049), 'S'mall (128) or 'O'ther * block. */ From f2f1c844d9a49efa8d112c3ef5aecb8ff65ff6ab Mon Sep 17 00:00:00 2001 From: Sylvain Petreolle Date: Sun, 2 May 2010 19:25:50 +0000 Subject: [PATCH 21/24] Fix merge artifact. svn path=/branches/aicom-network-branch/; revision=47086 --- dll/win32/msafd/misc/dllmain.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/dll/win32/msafd/misc/dllmain.c b/dll/win32/msafd/misc/dllmain.c index 08a029c30d8..e43ab505bfd 100644 --- a/dll/win32/msafd/misc/dllmain.c +++ b/dll/win32/msafd/misc/dllmain.c @@ -656,14 +656,6 @@ WSPBind(SOCKET Handle, NtClose( SockEvent ); HeapFree(GlobalHeap, 0, BindData); - if (Status == STATUS_SUCCESS && (Socket->HelperEvents & WSH_NOTIFY_BIND)) - { - Status = Socket->HelperData->WSHNotify(Socket->HelperContext, - Socket->Handle, - Socket->TdiAddressHandle, - Socket->TdiConnectionHandle, - WSH_NOTIFY_BIND); - if (Status == STATUS_SUCCESS && (Socket->HelperEvents & WSH_NOTIFY_BIND)) { Status = Socket->HelperData->WSHNotify(Socket->HelperContext, From 343454be2fcbbef49989d45f41f7ca555686a6b8 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Mon, 31 May 2010 18:17:05 +0000 Subject: [PATCH 22/24] [MSAFD] - Msafd is really just a stub that points to mswsock svn path=/branches/aicom-network-branch/; revision=47501 --- dll/win32/msafd/include/debug.h | 67 - dll/win32/msafd/include/helpers.h | 73 - dll/win32/msafd/misc/dllmain.c | 2758 ----------------------------- dll/win32/msafd/misc/event.c | 229 --- dll/win32/msafd/misc/helpers.c | 520 ------ dll/win32/msafd/misc/sndrcv.c | 671 ------- dll/win32/msafd/misc/stubs.c | 118 -- dll/win32/msafd/msafd.h | 475 ----- dll/win32/msafd/msafd.rbuild | 15 +- dll/win32/msafd/msafd.spec | 2 +- 10 files changed, 2 insertions(+), 4926 deletions(-) delete mode 100644 dll/win32/msafd/include/debug.h delete mode 100644 dll/win32/msafd/include/helpers.h delete mode 100644 dll/win32/msafd/misc/dllmain.c delete mode 100644 dll/win32/msafd/misc/event.c delete mode 100644 dll/win32/msafd/misc/helpers.c delete mode 100644 dll/win32/msafd/misc/sndrcv.c delete mode 100644 dll/win32/msafd/misc/stubs.c delete mode 100755 dll/win32/msafd/msafd.h diff --git a/dll/win32/msafd/include/debug.h b/dll/win32/msafd/include/debug.h deleted file mode 100644 index 2be8a158b8e..00000000000 --- a/dll/win32/msafd/include/debug.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Ancillary Function Driver DLL - * FILE: include/debug.h - * PURPOSE: Debugging support macros - * DEFINES: DBG - Enable debug output - * NASSERT - Disable assertions - */ -#ifndef __DEBUG_H -#define __DEBUG_H - -#define NORMAL_MASK 0x000000FF -#define SPECIAL_MASK 0xFFFFFF00 -#define MIN_TRACE 0x00000001 -#define MID_TRACE 0x00000002 -#define MAX_TRACE 0x00000003 - -#define DEBUG_CHECK 0x00000100 -#define DEBUG_ULTRA 0xFFFFFFFF - -#ifdef ASSERT -#undef ASSERT -#endif - -#if DBG - -extern DWORD DebugTraceLevel; - -#define AFD_DbgPrint(_t_, _x_) \ - if (((DebugTraceLevel & NORMAL_MASK) >= _t_) || \ - ((DebugTraceLevel & _t_) > NORMAL_MASK)) { \ - DbgPrint("(%hS:%d)(%hS) ", __FILE__, __LINE__, __FUNCTION__); \ - DbgPrint _x_; \ - } - -#ifdef NASSERT -#define ASSERT(x) -#else /* NASSERT */ -#define ASSERT(x) if (!(x)) { AFD_DbgPrint(MIN_TRACE, ("Assertion "#x" failed at %s:%d\n", __FILE__, __LINE__)); ExitProcess(0); } -#endif /* NASSERT */ - -#else /* DBG */ - -#define AFD_DbgPrint(_t_, _x_) - -#define ASSERT_IRQL(x) -#define ASSERT(x) - -#endif /* DBG */ - -#ifdef assert -#undef assert -#endif -#define assert(x) ASSERT(x) - - -#define UNIMPLEMENTED \ - AFD_DbgPrint(MIN_TRACE, ("is unimplemented, please try again later.\n")); - -#define CHECKPOINT \ - AFD_DbgPrint(DEBUG_CHECK, ("\n")); - -#define CP CHECKPOINT - -#endif /* __DEBUG_H */ - -/* EOF */ diff --git a/dll/win32/msafd/include/helpers.h b/dll/win32/msafd/include/helpers.h deleted file mode 100644 index 7fa8e0c2627..00000000000 --- a/dll/win32/msafd/include/helpers.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Ancillary Function Driver DLL - * FILE: include/helpers.h - * PURPOSE: Definitions for helper DLL management - */ -#ifndef __HELPERS_H -#define __HELPERS_H - -//#include - -typedef struct _HELPER_DATA { - LIST_ENTRY Helpers; - LONG RefCount; - HANDLE hInstance; - INT MinWSAddressLength; - INT MaxWSAddressLength; - INT MinTDIAddressLength; - INT MaxTDIAddressLength; - BOOLEAN UseDelayedAcceptance; - PWINSOCK_MAPPING Mapping; - PWSH_OPEN_SOCKET WSHOpenSocket; - PWSH_OPEN_SOCKET2 WSHOpenSocket2; - PWSH_JOIN_LEAF WSHJoinLeaf; - PWSH_NOTIFY WSHNotify; - PWSH_GET_SOCKET_INFORMATION WSHGetSocketInformation; - PWSH_SET_SOCKET_INFORMATION WSHSetSocketInformation; - PWSH_GET_SOCKADDR_TYPE WSHGetSockaddrType; - PWSH_GET_WILDCARD_SOCKADDR WSHGetWildcardSockaddr; - PWSH_GET_BROADCAST_SOCKADDR WSHGetBroadcastSockaddr; - PWSH_ADDRESS_TO_STRING WSHAddressToString; - PWSH_STRING_TO_ADDRESS WSHStringToAddress; - PWSH_IOCTL WSHIoctl; - WCHAR TransportName[1]; -} HELPER_DATA, *PHELPER_DATA; - -int SockLoadHelperDll( - PWSTR TransportName, - PWINSOCK_MAPPING Mapping, - PHELPER_DATA *HelperDllData -); - -int SockLoadTransportMapping( - PWSTR TransportName, - PWINSOCK_MAPPING *Mapping -); - -int SockLoadTransportList( - PWSTR *TransportList -); - -BOOL SockIsTripleInMapping( - PWINSOCK_MAPPING Mapping, - INT AddressFamily, - INT SocketType, - INT Protocol -); - -int SockGetTdiName( - PINT AddressFamily, - PINT SocketType, - PINT Protocol, - GROUP Group, - DWORD Flags, - PUNICODE_STRING TransportName, - PVOID *HelperDllContext, - PHELPER_DATA *HelperDllData, - PDWORD Events -); - -#endif /* __HELPERS_H */ - -/* EOF */ diff --git a/dll/win32/msafd/misc/dllmain.c b/dll/win32/msafd/misc/dllmain.c deleted file mode 100644 index e43ab505bfd..00000000000 --- a/dll/win32/msafd/misc/dllmain.c +++ /dev/null @@ -1,2758 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Ancillary Function Driver DLL - * FILE: misc/dllmain.c - * PURPOSE: DLL entry point - * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) - * Alex Ionescu (alex@relsoft.net) - * REVISIONS: - * CSH 01/09-2000 Created - * Alex 16/07/2004 - Complete Rewrite - */ - -#include - -#include - -#if DBG -//DWORD DebugTraceLevel = DEBUG_ULTRA; -DWORD DebugTraceLevel = 0; -#endif /* DBG */ - -HANDLE GlobalHeap; -WSPUPCALLTABLE Upcalls; -LPWPUCOMPLETEOVERLAPPEDREQUEST lpWPUCompleteOverlappedRequest; -ULONG SocketCount = 0; -PSOCKET_INFORMATION *Sockets = NULL; -LIST_ENTRY SockHelpersListHead = { NULL, NULL }; -ULONG SockAsyncThreadRefCount; -HANDLE SockAsyncHelperAfdHandle; -HANDLE SockAsyncCompletionPort; -BOOLEAN SockAsyncSelectCalled; - - - -/* - * FUNCTION: Creates a new socket - * ARGUMENTS: - * af = Address family - * type = Socket type - * protocol = Protocol type - * lpProtocolInfo = Pointer to protocol information - * g = Reserved - * dwFlags = Socket flags - * lpErrno = Address of buffer for error information - * RETURNS: - * Created socket, or INVALID_SOCKET if it could not be created - */ -SOCKET -WSPAPI -WSPSocket(int AddressFamily, - int SocketType, - int Protocol, - LPWSAPROTOCOL_INFOW lpProtocolInfo, - GROUP g, - DWORD dwFlags, - LPINT lpErrno) -{ - OBJECT_ATTRIBUTES Object; - IO_STATUS_BLOCK IOSB; - USHORT SizeOfPacket; - ULONG SizeOfEA; - PAFD_CREATE_PACKET AfdPacket; - HANDLE Sock; - PSOCKET_INFORMATION Socket = NULL, PrevSocket = NULL; - PFILE_FULL_EA_INFORMATION EABuffer = NULL; - PHELPER_DATA HelperData; - PVOID HelperDLLContext; - DWORD HelperEvents; - UNICODE_STRING TransportName; - UNICODE_STRING DevName; - LARGE_INTEGER GroupData; - INT Status; - - AFD_DbgPrint(MAX_TRACE, ("Creating Socket, getting TDI Name\n")); - AFD_DbgPrint(MAX_TRACE, ("AddressFamily (%d) SocketType (%d) Protocol (%d).\n", - AddressFamily, SocketType, Protocol)); - - /* Get Helper Data and Transport */ - Status = SockGetTdiName (&AddressFamily, - &SocketType, - &Protocol, - g, - dwFlags, - &TransportName, - &HelperDLLContext, - &HelperData, - &HelperEvents); - - /* Check for error */ - if (Status != NO_ERROR) - { - AFD_DbgPrint(MID_TRACE,("SockGetTdiName: Status %x\n", Status)); - goto error; - } - - /* AFD Device Name */ - RtlInitUnicodeString(&DevName, L"\\Device\\Afd\\Endpoint"); - - /* Set Socket Data */ - Socket = HeapAlloc(GlobalHeap, 0, sizeof(*Socket)); - if (!Socket) - return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL); - - RtlZeroMemory(Socket, sizeof(*Socket)); - Socket->RefCount = 2; - Socket->Handle = -1; - Socket->SharedData.Listening = FALSE; - Socket->SharedData.State = SocketOpen; - Socket->SharedData.AddressFamily = AddressFamily; - Socket->SharedData.SocketType = SocketType; - Socket->SharedData.Protocol = Protocol; - Socket->HelperContext = HelperDLLContext; - Socket->HelperData = HelperData; - Socket->HelperEvents = HelperEvents; - Socket->LocalAddress = &Socket->WSLocalAddress; - Socket->SharedData.SizeOfLocalAddress = HelperData->MaxWSAddressLength; - Socket->RemoteAddress = &Socket->WSRemoteAddress; - Socket->SharedData.SizeOfRemoteAddress = HelperData->MaxWSAddressLength; - Socket->SharedData.UseDelayedAcceptance = HelperData->UseDelayedAcceptance; - Socket->SharedData.CreateFlags = dwFlags; - Socket->SharedData.CatalogEntryId = lpProtocolInfo->dwCatalogEntryId; - Socket->SharedData.ServiceFlags1 = lpProtocolInfo->dwServiceFlags1; - Socket->SharedData.ProviderFlags = lpProtocolInfo->dwProviderFlags; - Socket->SharedData.GroupID = g; - Socket->SharedData.GroupType = 0; - Socket->SharedData.UseSAN = FALSE; - Socket->SharedData.NonBlocking = FALSE; /* Sockets start blocking */ - Socket->SanData = NULL; - - /* Ask alex about this */ - if( Socket->SharedData.SocketType == SOCK_DGRAM || - Socket->SharedData.SocketType == SOCK_RAW ) - { - AFD_DbgPrint(MID_TRACE,("Connectionless socket\n")); - Socket->SharedData.ServiceFlags1 |= XP1_CONNECTIONLESS; - } - - /* Packet Size */ - SizeOfPacket = TransportName.Length + sizeof(AFD_CREATE_PACKET) + sizeof(WCHAR); - - /* EA Size */ - SizeOfEA = SizeOfPacket + sizeof(FILE_FULL_EA_INFORMATION) + AFD_PACKET_COMMAND_LENGTH; - - /* Set up EA Buffer */ - EABuffer = HeapAlloc(GlobalHeap, 0, SizeOfEA); - if (!EABuffer) - return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL); - - RtlZeroMemory(EABuffer, SizeOfEA); - EABuffer->NextEntryOffset = 0; - EABuffer->Flags = 0; - EABuffer->EaNameLength = AFD_PACKET_COMMAND_LENGTH; - RtlCopyMemory (EABuffer->EaName, - AfdCommand, - AFD_PACKET_COMMAND_LENGTH + 1); - EABuffer->EaValueLength = SizeOfPacket; - - /* Set up AFD Packet */ - AfdPacket = (PAFD_CREATE_PACKET)(EABuffer->EaName + EABuffer->EaNameLength + 1); - AfdPacket->SizeOfTransportName = TransportName.Length; - RtlCopyMemory (AfdPacket->TransportName, - TransportName.Buffer, - TransportName.Length + sizeof(WCHAR)); - AfdPacket->GroupID = g; - - /* Set up Endpoint Flags */ - if ((Socket->SharedData.ServiceFlags1 & XP1_CONNECTIONLESS) != 0) - { - if ((SocketType != SOCK_DGRAM) && (SocketType != SOCK_RAW)) - { - /* Only RAW or UDP can be Connectionless */ - goto error; - } - AfdPacket->EndpointFlags |= AFD_ENDPOINT_CONNECTIONLESS; - } - - if ((Socket->SharedData.ServiceFlags1 & XP1_MESSAGE_ORIENTED) != 0) - { - if (SocketType == SOCK_STREAM) - { - if ((Socket->SharedData.ServiceFlags1 & XP1_PSEUDO_STREAM) == 0) - { - /* The Provider doesn't actually support Message Oriented Streams */ - goto error; - } - } - AfdPacket->EndpointFlags |= AFD_ENDPOINT_MESSAGE_ORIENTED; - } - - if (SocketType == SOCK_RAW) AfdPacket->EndpointFlags |= AFD_ENDPOINT_RAW; - - if (dwFlags & (WSA_FLAG_MULTIPOINT_C_ROOT | - WSA_FLAG_MULTIPOINT_C_LEAF | - WSA_FLAG_MULTIPOINT_D_ROOT | - WSA_FLAG_MULTIPOINT_D_LEAF)) - { - if ((Socket->SharedData.ServiceFlags1 & XP1_SUPPORT_MULTIPOINT) == 0) - { - /* The Provider doesn't actually support Multipoint */ - goto error; - } - AfdPacket->EndpointFlags |= AFD_ENDPOINT_MULTIPOINT; - - if (dwFlags & WSA_FLAG_MULTIPOINT_C_ROOT) - { - if (((Socket->SharedData.ServiceFlags1 & XP1_MULTIPOINT_CONTROL_PLANE) == 0) - || ((dwFlags & WSA_FLAG_MULTIPOINT_C_LEAF) != 0)) - { - /* The Provider doesn't support Control Planes, or you already gave a leaf */ - goto error; - } - AfdPacket->EndpointFlags |= AFD_ENDPOINT_C_ROOT; - } - - if (dwFlags & WSA_FLAG_MULTIPOINT_D_ROOT) - { - if (((Socket->SharedData.ServiceFlags1 & XP1_MULTIPOINT_DATA_PLANE) == 0) - || ((dwFlags & WSA_FLAG_MULTIPOINT_D_LEAF) != 0)) - { - /* The Provider doesn't support Data Planes, or you already gave a leaf */ - goto error; - } - AfdPacket->EndpointFlags |= AFD_ENDPOINT_D_ROOT; - } - } - - /* Set up Object Attributes */ - InitializeObjectAttributes (&Object, - &DevName, - OBJ_CASE_INSENSITIVE | OBJ_INHERIT, - 0, - 0); - - /* Create the Socket as asynchronous. That means we have to block - ourselves after every call to NtDeviceIoControlFile. This is - because the kernel doesn't support overlapping synchronous I/O - requests (made from multiple threads) at this time (Sep 2005) */ - Status = NtCreateFile(&Sock, - GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, - &Object, - &IOSB, - NULL, - 0, - FILE_SHARE_READ | FILE_SHARE_WRITE, - FILE_OPEN_IF, - 0, - EABuffer, - SizeOfEA); - - HeapFree(GlobalHeap, 0, EABuffer); - - if (Status != STATUS_SUCCESS) - { - AFD_DbgPrint(MIN_TRACE, ("Failed to open socket\n")); - - HeapFree(GlobalHeap, 0, Socket); - - return MsafdReturnWithErrno(Status, lpErrno, 0, NULL); - } - - /* Save Handle */ - Socket->Handle = (SOCKET)Sock; - - /* XXX See if there's a structure we can reuse -- We need to do this - * more properly. */ - PrevSocket = GetSocketStructure( (SOCKET)Sock ); - - if( PrevSocket ) - { - RtlCopyMemory( PrevSocket, Socket, sizeof(*Socket) ); - RtlFreeHeap( GlobalHeap, 0, Socket ); - Socket = PrevSocket; - } - - /* Save Group Info */ - if (g != 0) - { - GetSocketInformation(Socket, AFD_INFO_GROUP_ID_TYPE, 0, &GroupData); - Socket->SharedData.GroupID = GroupData.u.LowPart; - Socket->SharedData.GroupType = GroupData.u.HighPart; - } - - /* Get Window Sizes and Save them */ - GetSocketInformation (Socket, - AFD_INFO_SEND_WINDOW_SIZE, - &Socket->SharedData.SizeOfSendBuffer, - NULL); - - GetSocketInformation (Socket, - AFD_INFO_RECEIVE_WINDOW_SIZE, - &Socket->SharedData.SizeOfRecvBuffer, - NULL); - - /* Save in Process Sockets List */ - Sockets[SocketCount] = Socket; - SocketCount ++; - - /* Create the Socket Context */ - CreateContext(Socket); - - /* Notify Winsock */ - Upcalls.lpWPUModifyIFSHandle(1, (SOCKET)Sock, lpErrno); - - /* Return Socket Handle */ - AFD_DbgPrint(MID_TRACE,("Success %x\n", Sock)); - - return (SOCKET)Sock; - -error: - AFD_DbgPrint(MID_TRACE,("Ending %x\n", Status)); - - if( Socket ) - HeapFree(GlobalHeap, 0, Socket); - - if( lpErrno ) - *lpErrno = Status; - - return INVALID_SOCKET; -} - - -DWORD MsafdReturnWithErrno(NTSTATUS Status, - LPINT Errno, - DWORD Received, - LPDWORD ReturnedBytes) -{ - if( ReturnedBytes ) - *ReturnedBytes = 0; - if( Errno ) - { - switch (Status) - { - case STATUS_CANT_WAIT: - *Errno = WSAEWOULDBLOCK; - break; - case STATUS_TIMEOUT: - *Errno = WSAETIMEDOUT; - break; - case STATUS_SUCCESS: - /* Return Number of bytes Read */ - if( ReturnedBytes ) - *ReturnedBytes = Received; - break; - case STATUS_FILE_CLOSED: - case STATUS_END_OF_FILE: - *Errno = WSAESHUTDOWN; - break; - case STATUS_PENDING: - *Errno = WSA_IO_PENDING; - break; - case STATUS_BUFFER_TOO_SMALL: - case STATUS_BUFFER_OVERFLOW: - DbgPrint("MSAFD: STATUS_BUFFER_TOO_SMALL/STATUS_BUFFER_OVERFLOW\n"); - *Errno = WSAEMSGSIZE; - break; - case STATUS_NO_MEMORY: /* Fall through to STATUS_INSUFFICIENT_RESOURCES */ - case STATUS_INSUFFICIENT_RESOURCES: - DbgPrint("MSAFD: STATUS_NO_MEMORY/STATUS_INSUFFICIENT_RESOURCES\n"); - *Errno = WSAENOBUFS; - break; - case STATUS_INVALID_CONNECTION: - DbgPrint("MSAFD: STATUS_INVALID_CONNECTION\n"); - *Errno = WSAEAFNOSUPPORT; - break; - case STATUS_INVALID_ADDRESS: - DbgPrint("MSAFD: STATUS_INVALID_ADDRESS\n"); - *Errno = WSAEADDRNOTAVAIL; - break; - case STATUS_REMOTE_NOT_LISTENING: - DbgPrint("MSAFD: STATUS_REMOTE_NOT_LISTENING\n"); - *Errno = WSAECONNREFUSED; - break; - case STATUS_NETWORK_UNREACHABLE: - DbgPrint("MSAFD: STATUS_NETWORK_UNREACHABLE\n"); - *Errno = WSAENETUNREACH; - break; - case STATUS_INVALID_PARAMETER: - DbgPrint("MSAFD: STATUS_INVALID_PARAMETER\n"); - *Errno = WSAEINVAL; - break; - case STATUS_CANCELLED: - DbgPrint("MSAFD: STATUS_CANCELLED\n"); - *Errno = WSA_OPERATION_ABORTED; - break; - default: - DbgPrint("MSAFD: Error %x is unknown\n", Status); - *Errno = WSAEINVAL; - break; - } - } - - /* Success */ - return Status == STATUS_SUCCESS ? 0 : SOCKET_ERROR; -} - -/* - * FUNCTION: Closes an open socket - * ARGUMENTS: - * s = Socket descriptor - * lpErrno = Address of buffer for error information - * RETURNS: - * NO_ERROR, or SOCKET_ERROR if the socket could not be closed - */ -INT -WSPAPI -WSPCloseSocket(IN SOCKET Handle, - OUT LPINT lpErrno) -{ - IO_STATUS_BLOCK IoStatusBlock; - PSOCKET_INFORMATION Socket = NULL; - NTSTATUS Status; - HANDLE SockEvent; - AFD_DISCONNECT_INFO DisconnectInfo; - SOCKET_STATE OldState; - - /* Create the Wait Event */ - Status = NtCreateEvent(&SockEvent, - GENERIC_READ | GENERIC_WRITE, - NULL, - 1, - FALSE); - - if(!NT_SUCCESS(Status)) - return SOCKET_ERROR; - - /* Get the Socket Structure associate to this Socket*/ - Socket = GetSocketStructure(Handle); - - if (Socket->HelperEvents & WSH_NOTIFY_CLOSE) - { - Status = Socket->HelperData->WSHNotify(Socket->HelperContext, - Socket->Handle, - Socket->TdiAddressHandle, - Socket->TdiConnectionHandle, - WSH_NOTIFY_CLOSE); - - if (Status) - { - if (lpErrno) *lpErrno = Status; - NtClose(SockEvent); - return SOCKET_ERROR; - } - } - - /* If a Close is already in Process, give up */ - if (Socket->SharedData.State == SocketClosed) - { - NtClose(SockEvent); - *lpErrno = WSAENOTSOCK; - return SOCKET_ERROR; - } - - /* Set the state to close */ - OldState = Socket->SharedData.State; - Socket->SharedData.State = SocketClosed; - - /* If SO_LINGER is ON and the Socket is connected, we need to disconnect */ - /* FIXME: Should we do this on Datagram Sockets too? */ - if ((OldState == SocketConnected) && (Socket->SharedData.LingerData.l_onoff)) - { - ULONG LingerWait; - ULONG SendsInProgress; - ULONG SleepWait; - - /* We need to respect the timeout */ - SleepWait = 100; - LingerWait = Socket->SharedData.LingerData.l_linger * 1000; - - /* Loop until no more sends are pending, within the timeout */ - while (LingerWait) - { - /* Find out how many Sends are in Progress */ - if (GetSocketInformation(Socket, - AFD_INFO_SENDS_IN_PROGRESS, - &SendsInProgress, - NULL)) - { - /* Bail out if anything but NO_ERROR */ - LingerWait = 0; - break; - } - - /* Bail out if no more sends are pending */ - if (!SendsInProgress) - break; - /* - * We have to execute a sleep, so it's kind of like - * a block. If the socket is Nonblock, we cannot - * go on since asyncronous operation is expected - * and we cannot offer it - */ - if (Socket->SharedData.NonBlocking) - { - NtClose(SockEvent); - Socket->SharedData.State = OldState; - *lpErrno = WSAEWOULDBLOCK; - return SOCKET_ERROR; - } - - /* Now we can sleep, and decrement the linger wait */ - /* - * FIXME: It seems Windows does some funky acceleration - * since the waiting seems to be longer and longer. I - * don't think this improves performance so much, so we - * wait a fixed time instead. - */ - Sleep(SleepWait); - LingerWait -= SleepWait; - } - - /* - * We have reached the timeout or sends are over. - * Disconnect if the timeout has been reached. - */ - if (LingerWait <= 0) - { - DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(0); - DisconnectInfo.DisconnectType = AFD_DISCONNECT_ABORT; - - /* Send IOCTL */ - Status = NtDeviceIoControlFile((HANDLE)Handle, - SockEvent, - NULL, - NULL, - &IoStatusBlock, - IOCTL_AFD_DISCONNECT, - &DisconnectInfo, - sizeof(DisconnectInfo), - NULL, - 0); - - /* Wait for return */ - if (Status == STATUS_PENDING) - { - WaitForSingleObject(SockEvent, INFINITE); - Status = IoStatusBlock.Status; - } - } - } - - /* Cleanup Time! */ - Socket->HelperContext = NULL; - Socket->SharedData.AsyncDisabledEvents = -1; - NtClose(Socket->TdiAddressHandle); - Socket->TdiAddressHandle = NULL; - NtClose(Socket->TdiConnectionHandle); - Socket->TdiConnectionHandle = NULL; - - /* Close the handle */ - NtClose((HANDLE)Handle); - NtClose(SockEvent); - - return NO_ERROR; -} - - -/* - * FUNCTION: Associates a local address with a socket - * ARGUMENTS: - * s = Socket descriptor - * name = Pointer to local address - * namelen = Length of name - * lpErrno = Address of buffer for error information - * RETURNS: - * 0, or SOCKET_ERROR if the socket could not be bound - */ -INT -WSPAPI -WSPBind(SOCKET Handle, - const struct sockaddr *SocketAddress, - int SocketAddressLength, - LPINT lpErrno) -{ - IO_STATUS_BLOCK IOSB; - PAFD_BIND_DATA BindData; - PSOCKET_INFORMATION Socket = NULL; - NTSTATUS Status; - SOCKADDR_INFO SocketInfo; - HANDLE SockEvent; - - /* See below */ - BindData = HeapAlloc(GlobalHeap, 0, 0xA + SocketAddressLength); - if (!BindData) - { - return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL); - } - - Status = NtCreateEvent(&SockEvent, - GENERIC_READ | GENERIC_WRITE, - NULL, - 1, - FALSE); - - if (!NT_SUCCESS(Status)) - { - HeapFree(GlobalHeap, 0, BindData); - return SOCKET_ERROR; - } - - /* Get the Socket Structure associate to this Socket*/ - Socket = GetSocketStructure(Handle); - - /* Set up Address in TDI Format */ - BindData->Address.TAAddressCount = 1; - BindData->Address.Address[0].AddressLength = SocketAddressLength - sizeof(SocketAddress->sa_family); - BindData->Address.Address[0].AddressType = SocketAddress->sa_family; - RtlCopyMemory (BindData->Address.Address[0].Address, - SocketAddress->sa_data, - SocketAddressLength - sizeof(SocketAddress->sa_family)); - - /* Get Address Information */ - Socket->HelperData->WSHGetSockaddrType ((PSOCKADDR)SocketAddress, - SocketAddressLength, - &SocketInfo); - - /* Set the Share Type */ - if (Socket->SharedData.ExclusiveAddressUse) - { - BindData->ShareType = AFD_SHARE_EXCLUSIVE; - } - else if (SocketInfo.EndpointInfo == SockaddrEndpointInfoWildcard) - { - BindData->ShareType = AFD_SHARE_WILDCARD; - } - else if (Socket->SharedData.ReuseAddresses) - { - BindData->ShareType = AFD_SHARE_REUSE; - } - else - { - BindData->ShareType = AFD_SHARE_UNIQUE; - } - - /* Send IOCTL */ - Status = NtDeviceIoControlFile((HANDLE)Socket->Handle, - SockEvent, - NULL, - NULL, - &IOSB, - IOCTL_AFD_BIND, - BindData, - 0xA + Socket->SharedData.SizeOfLocalAddress, /* Can't figure out a way to calculate this in C*/ - BindData, - 0xA + Socket->SharedData.SizeOfLocalAddress); /* Can't figure out a way to calculate this C */ - - /* Wait for return */ - if (Status == STATUS_PENDING) - { - WaitForSingleObject(SockEvent, INFINITE); - Status = IOSB.Status; - } - - /* Set up Socket Data */ - Socket->SharedData.State = SocketBound; - Socket->TdiAddressHandle = (HANDLE)IOSB.Information; - - NtClose( SockEvent ); - HeapFree(GlobalHeap, 0, BindData); - if (Status == STATUS_SUCCESS && (Socket->HelperEvents & WSH_NOTIFY_BIND)) - { - Status = Socket->HelperData->WSHNotify(Socket->HelperContext, - Socket->Handle, - Socket->TdiAddressHandle, - Socket->TdiConnectionHandle, - WSH_NOTIFY_BIND); - - if (Status) - { - if (lpErrno) *lpErrno = Status; - return SOCKET_ERROR; - } - } - - return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL ); -} - -int -WSPAPI -WSPListen(SOCKET Handle, - int Backlog, - LPINT lpErrno) -{ - IO_STATUS_BLOCK IOSB; - AFD_LISTEN_DATA ListenData; - PSOCKET_INFORMATION Socket = NULL; - HANDLE SockEvent; - NTSTATUS Status; - - /* Get the Socket Structure associate to this Socket*/ - Socket = GetSocketStructure(Handle); - - if (Socket->SharedData.Listening) - return 0; - - Status = NtCreateEvent(&SockEvent, - GENERIC_READ | GENERIC_WRITE, - NULL, - 1, - FALSE); - - if( !NT_SUCCESS(Status) ) - return -1; - - /* Set Up Listen Structure */ - ListenData.UseSAN = FALSE; - ListenData.UseDelayedAcceptance = Socket->SharedData.UseDelayedAcceptance; - ListenData.Backlog = Backlog; - - /* Send IOCTL */ - Status = NtDeviceIoControlFile((HANDLE)Socket->Handle, - SockEvent, - NULL, - NULL, - &IOSB, - IOCTL_AFD_START_LISTEN, - &ListenData, - sizeof(ListenData), - NULL, - 0); - - /* Wait for return */ - if (Status == STATUS_PENDING) - { - WaitForSingleObject(SockEvent, INFINITE); - Status = IOSB.Status; - } - - /* Set to Listening */ - Socket->SharedData.Listening = TRUE; - - NtClose( SockEvent ); - - if (Status == STATUS_SUCCESS && (Socket->HelperEvents & WSH_NOTIFY_LISTEN)) - { - Status = Socket->HelperData->WSHNotify(Socket->HelperContext, - Socket->Handle, - Socket->TdiAddressHandle, - Socket->TdiConnectionHandle, - WSH_NOTIFY_LISTEN); - - if (Status) - { - if (lpErrno) *lpErrno = Status; - return SOCKET_ERROR; - } - } - - return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL ); -} - - -int -WSPAPI -WSPSelect(int nfds, - fd_set *readfds, - fd_set *writefds, - fd_set *exceptfds, - const LPTIMEVAL timeout, - LPINT lpErrno) -{ - IO_STATUS_BLOCK IOSB; - PAFD_POLL_INFO PollInfo; - NTSTATUS Status; - LONG HandleCount, OutCount = 0; - ULONG PollBufferSize; - PVOID PollBuffer; - ULONG i, j = 0, x; - HANDLE SockEvent; - BOOL HandleCounted; - LARGE_INTEGER Timeout; - - /* Find out how many sockets we have, and how large the buffer needs - * to be */ - - HandleCount = ( readfds ? readfds->fd_count : 0 ) + - ( writefds ? writefds->fd_count : 0 ) + - ( exceptfds ? exceptfds->fd_count : 0 ); - - if ( HandleCount == 0 ) - { - AFD_DbgPrint(MAX_TRACE,("HandleCount: %d. Return SOCKET_ERROR\n", - HandleCount)); - if (lpErrno) *lpErrno = WSAEINVAL; - return SOCKET_ERROR; - } - - PollBufferSize = sizeof(*PollInfo) + ((HandleCount - 1) * sizeof(AFD_HANDLE)); - - AFD_DbgPrint(MID_TRACE,("HandleCount: %d BufferSize: %d\n", - HandleCount, PollBufferSize)); - - /* Convert Timeout to NT Format */ - if (timeout == NULL) - { - Timeout.u.LowPart = -1; - Timeout.u.HighPart = 0x7FFFFFFF; - AFD_DbgPrint(MAX_TRACE,("Infinite timeout\n")); - } - else - { - Timeout = RtlEnlargedIntegerMultiply - ((timeout->tv_sec * 1000) + (timeout->tv_usec / 1000), -10000); - /* Negative timeouts are illegal. Since the kernel represents an - * incremental timeout as a negative number, we check for a positive - * result. - */ - if (Timeout.QuadPart > 0) - { - if (lpErrno) *lpErrno = WSAEINVAL; - return SOCKET_ERROR; - } - AFD_DbgPrint(MAX_TRACE,("Timeout: Orig %d.%06d kernel %d\n", - timeout->tv_sec, timeout->tv_usec, - Timeout.u.LowPart)); - } - - Status = NtCreateEvent(&SockEvent, - GENERIC_READ | GENERIC_WRITE, - NULL, - 1, - FALSE); - - if( !NT_SUCCESS(Status) ) - return SOCKET_ERROR; - - /* Allocate */ - PollBuffer = HeapAlloc(GlobalHeap, 0, PollBufferSize); - - if (!PollBuffer) - { - if (lpErrno) - *lpErrno = WSAEFAULT; - NtClose(SockEvent); - return SOCKET_ERROR; - } - - PollInfo = (PAFD_POLL_INFO)PollBuffer; - - RtlZeroMemory( PollInfo, PollBufferSize ); - - /* Number of handles for AFD to Check */ - PollInfo->Exclusive = FALSE; - PollInfo->Timeout = Timeout; - - if (readfds != NULL) { - for (i = 0; i < readfds->fd_count; i++, j++) - { - PollInfo->Handles[j].Handle = readfds->fd_array[i]; - PollInfo->Handles[j].Events = AFD_EVENT_RECEIVE | - AFD_EVENT_DISCONNECT | - AFD_EVENT_ABORT | - AFD_EVENT_CLOSE | - AFD_EVENT_ACCEPT; - } - } - if (writefds != NULL) - { - for (i = 0; i < writefds->fd_count; i++, j++) - { - PollInfo->Handles[j].Handle = writefds->fd_array[i]; - PollInfo->Handles[j].Events = AFD_EVENT_SEND | AFD_EVENT_CONNECT; - } - } - if (exceptfds != NULL) - { - for (i = 0; i < exceptfds->fd_count; i++, j++) - { - PollInfo->Handles[j].Handle = exceptfds->fd_array[i]; - PollInfo->Handles[j].Events = AFD_EVENT_OOB_RECEIVE | AFD_EVENT_CONNECT_FAIL; - } - } - - PollInfo->HandleCount = j; - PollBufferSize = ((PCHAR)&PollInfo->Handles[j+1]) - ((PCHAR)PollInfo); - - /* Send IOCTL */ - Status = NtDeviceIoControlFile((HANDLE)PollInfo->Handles[0].Handle, - SockEvent, - NULL, - NULL, - &IOSB, - IOCTL_AFD_SELECT, - PollInfo, - PollBufferSize, - PollInfo, - PollBufferSize); - - AFD_DbgPrint(MID_TRACE,("DeviceIoControlFile => %x\n", Status)); - - /* Wait for Completition */ - if (Status == STATUS_PENDING) - { - WaitForSingleObject(SockEvent, INFINITE); - } - - /* Clear the Structures */ - if( readfds ) - FD_ZERO(readfds); - if( writefds ) - FD_ZERO(writefds); - if( exceptfds ) - FD_ZERO(exceptfds); - - /* Loop through return structure */ - HandleCount = PollInfo->HandleCount; - - /* Return in FDSET Format */ - for (i = 0; i < HandleCount; i++) - { - HandleCounted = FALSE; - for(x = 1; x; x<<=1) - { - switch (PollInfo->Handles[i].Events & x) - { - case AFD_EVENT_RECEIVE: - case AFD_EVENT_DISCONNECT: - case AFD_EVENT_ABORT: - case AFD_EVENT_ACCEPT: - case AFD_EVENT_CLOSE: - AFD_DbgPrint(MID_TRACE,("Event %x on handle %x\n", - PollInfo->Handles[i].Events, - PollInfo->Handles[i].Handle)); - if (! HandleCounted) - { - OutCount++; - HandleCounted = TRUE; - } - if( readfds ) - FD_SET(PollInfo->Handles[i].Handle, readfds); - break; - case AFD_EVENT_SEND: - case AFD_EVENT_CONNECT: - AFD_DbgPrint(MID_TRACE,("Event %x on handle %x\n", - PollInfo->Handles[i].Events, - PollInfo->Handles[i].Handle)); - if (! HandleCounted) - { - OutCount++; - HandleCounted = TRUE; - } - if( writefds ) - FD_SET(PollInfo->Handles[i].Handle, writefds); - break; - case AFD_EVENT_OOB_RECEIVE: - case AFD_EVENT_CONNECT_FAIL: - AFD_DbgPrint(MID_TRACE,("Event %x on handle %x\n", - PollInfo->Handles[i].Events, - PollInfo->Handles[i].Handle)); - if (! HandleCounted) - { - OutCount++; - HandleCounted = TRUE; - } - if( exceptfds ) - FD_SET(PollInfo->Handles[i].Handle, exceptfds); - break; - } - } - } - - HeapFree( GlobalHeap, 0, PollBuffer ); - NtClose( SockEvent ); - - if( lpErrno ) - { - switch( IOSB.Status ) - { - case STATUS_SUCCESS: - case STATUS_TIMEOUT: - *lpErrno = 0; - break; - default: - *lpErrno = WSAEINVAL; - break; - } - AFD_DbgPrint(MID_TRACE,("*lpErrno = %x\n", *lpErrno)); - } - - AFD_DbgPrint(MID_TRACE,("%d events\n", OutCount)); - - return OutCount; -} - -SOCKET -WSPAPI -WSPAccept(SOCKET Handle, - struct sockaddr *SocketAddress, - int *SocketAddressLength, - LPCONDITIONPROC lpfnCondition, - DWORD dwCallbackData, - LPINT lpErrno) -{ - IO_STATUS_BLOCK IOSB; - PAFD_RECEIVED_ACCEPT_DATA ListenReceiveData; - AFD_ACCEPT_DATA AcceptData; - AFD_DEFER_ACCEPT_DATA DeferData; - AFD_PENDING_ACCEPT_DATA PendingAcceptData; - PSOCKET_INFORMATION Socket = NULL; - NTSTATUS Status; - struct fd_set ReadSet; - struct timeval Timeout; - PVOID PendingData = NULL; - ULONG PendingDataLength = 0; - PVOID CalleeDataBuffer; - WSABUF CallerData, CalleeID, CallerID, CalleeData; - PSOCKADDR RemoteAddress = NULL; - GROUP GroupID = 0; - ULONG CallBack; - WSAPROTOCOL_INFOW ProtocolInfo; - SOCKET AcceptSocket; - UCHAR ReceiveBuffer[0x1A]; - HANDLE SockEvent; - - Status = NtCreateEvent(&SockEvent, - GENERIC_READ | GENERIC_WRITE, - NULL, - 1, - FALSE); - - if( !NT_SUCCESS(Status) ) - { - MsafdReturnWithErrno( Status, lpErrno, 0, NULL ); - return INVALID_SOCKET; - } - - /* Dynamic Structure...ugh */ - ListenReceiveData = (PAFD_RECEIVED_ACCEPT_DATA)ReceiveBuffer; - - /* Get the Socket Structure associate to this Socket*/ - Socket = GetSocketStructure(Handle); - - /* If this is non-blocking, make sure there's something for us to accept */ - FD_ZERO(&ReadSet); - FD_SET(Socket->Handle, &ReadSet); - Timeout.tv_sec=0; - Timeout.tv_usec=0; - - WSPSelect(0, &ReadSet, NULL, NULL, &Timeout, NULL); - - if (ReadSet.fd_array[0] != Socket->Handle) - { - NtClose(SockEvent); - return 0; - } - - /* Send IOCTL */ - Status = NtDeviceIoControlFile((HANDLE)Socket->Handle, - SockEvent, - NULL, - NULL, - &IOSB, - IOCTL_AFD_WAIT_FOR_LISTEN, - NULL, - 0, - ListenReceiveData, - 0xA + sizeof(*ListenReceiveData)); - - /* Wait for return */ - if (Status == STATUS_PENDING) - { - WaitForSingleObject(SockEvent, INFINITE); - Status = IOSB.Status; - } - - if (!NT_SUCCESS(Status)) - { - NtClose( SockEvent ); - MsafdReturnWithErrno( Status, lpErrno, 0, NULL ); - return INVALID_SOCKET; - } - - if (lpfnCondition != NULL) - { - if ((Socket->SharedData.ServiceFlags1 & XP1_CONNECT_DATA) != 0) - { - /* Find out how much data is pending */ - PendingAcceptData.SequenceNumber = ListenReceiveData->SequenceNumber; - PendingAcceptData.ReturnSize = TRUE; - - /* Send IOCTL */ - Status = NtDeviceIoControlFile((HANDLE)Socket->Handle, - SockEvent, - NULL, - NULL, - &IOSB, - IOCTL_AFD_GET_PENDING_CONNECT_DATA, - &PendingAcceptData, - sizeof(PendingAcceptData), - &PendingAcceptData, - sizeof(PendingAcceptData)); - - /* Wait for return */ - if (Status == STATUS_PENDING) - { - WaitForSingleObject(SockEvent, INFINITE); - Status = IOSB.Status; - } - - if (!NT_SUCCESS(Status)) - { - NtClose( SockEvent ); - MsafdReturnWithErrno( Status, lpErrno, 0, NULL ); - return INVALID_SOCKET; - } - - /* How much data to allocate */ - PendingDataLength = IOSB.Information; - - if (PendingDataLength) - { - /* Allocate needed space */ - PendingData = HeapAlloc(GlobalHeap, 0, PendingDataLength); - if (!PendingData) - { - MsafdReturnWithErrno( STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL ); - return INVALID_SOCKET; - } - - /* We want the data now */ - PendingAcceptData.ReturnSize = FALSE; - - /* Send IOCTL */ - Status = NtDeviceIoControlFile((HANDLE)Socket->Handle, - SockEvent, - NULL, - NULL, - &IOSB, - IOCTL_AFD_GET_PENDING_CONNECT_DATA, - &PendingAcceptData, - sizeof(PendingAcceptData), - PendingData, - PendingDataLength); - - /* Wait for return */ - if (Status == STATUS_PENDING) - { - WaitForSingleObject(SockEvent, INFINITE); - Status = IOSB.Status; - } - - if (!NT_SUCCESS(Status)) - { - NtClose( SockEvent ); - MsafdReturnWithErrno( Status, lpErrno, 0, NULL ); - return INVALID_SOCKET; - } - } - } - - if ((Socket->SharedData.ServiceFlags1 & XP1_QOS_SUPPORTED) != 0) - { - /* I don't support this yet */ - } - - /* Build Callee ID */ - CalleeID.buf = (PVOID)Socket->LocalAddress; - CalleeID.len = Socket->SharedData.SizeOfLocalAddress; - - RemoteAddress = HeapAlloc(GlobalHeap, 0, sizeof(*RemoteAddress)); - if (!RemoteAddress) - { - MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL); - return INVALID_SOCKET; - } - - /* Set up Address in SOCKADDR Format */ - RtlCopyMemory (RemoteAddress, - &ListenReceiveData->Address.Address[0].AddressType, - sizeof(*RemoteAddress)); - - /* Build Caller ID */ - CallerID.buf = (PVOID)RemoteAddress; - CallerID.len = sizeof(*RemoteAddress); - - /* Build Caller Data */ - CallerData.buf = PendingData; - CallerData.len = PendingDataLength; - - /* Check if socket supports Conditional Accept */ - if (Socket->SharedData.UseDelayedAcceptance != 0) - { - /* Allocate Buffer for Callee Data */ - CalleeDataBuffer = HeapAlloc(GlobalHeap, 0, 4096); - if (!CalleeDataBuffer) { - MsafdReturnWithErrno( STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL ); - return INVALID_SOCKET; - } - CalleeData.buf = CalleeDataBuffer; - CalleeData.len = 4096; - } - else - { - /* Nothing */ - CalleeData.buf = 0; - CalleeData.len = 0; - } - - /* Call the Condition Function */ - CallBack = (lpfnCondition)(&CallerID, - CallerData.buf == NULL ? NULL : &CallerData, - NULL, - NULL, - &CalleeID, - CalleeData.buf == NULL ? NULL : &CalleeData, - &GroupID, - dwCallbackData); - - if (((CallBack == CF_ACCEPT) && GroupID) != 0) - { - /* TBD: Check for Validity */ - } - - if (CallBack == CF_ACCEPT) - { - if ((Socket->SharedData.ServiceFlags1 & XP1_QOS_SUPPORTED) != 0) - { - /* I don't support this yet */ - } - if (CalleeData.buf) - { - // SockSetConnectData Sockets(SocketID), IOCTL_AFD_SET_CONNECT_DATA, CalleeData.Buffer, CalleeData.BuffSize, 0 - } - } - else - { - /* Callback rejected. Build Defer Structure */ - DeferData.SequenceNumber = ListenReceiveData->SequenceNumber; - DeferData.RejectConnection = (CallBack == CF_REJECT); - - /* Send IOCTL */ - Status = NtDeviceIoControlFile((HANDLE)Socket->Handle, - SockEvent, - NULL, - NULL, - &IOSB, - IOCTL_AFD_DEFER_ACCEPT, - &DeferData, - sizeof(DeferData), - NULL, - 0); - - /* Wait for return */ - if (Status == STATUS_PENDING) - { - WaitForSingleObject(SockEvent, INFINITE); - Status = IOSB.Status; - } - - NtClose( SockEvent ); - - if (!NT_SUCCESS(Status)) - { - MsafdReturnWithErrno( Status, lpErrno, 0, NULL ); - return INVALID_SOCKET; - } - - if (CallBack == CF_REJECT ) - { - *lpErrno = WSAECONNREFUSED; - return INVALID_SOCKET; - } - else - { - *lpErrno = WSAECONNREFUSED; - return INVALID_SOCKET; - } - } - } - - /* Create a new Socket */ - ProtocolInfo.dwCatalogEntryId = Socket->SharedData.CatalogEntryId; - ProtocolInfo.dwServiceFlags1 = Socket->SharedData.ServiceFlags1; - ProtocolInfo.dwProviderFlags = Socket->SharedData.ProviderFlags; - - AcceptSocket = WSPSocket (Socket->SharedData.AddressFamily, - Socket->SharedData.SocketType, - Socket->SharedData.Protocol, - &ProtocolInfo, - GroupID, - Socket->SharedData.CreateFlags, - NULL); - - /* Set up the Accept Structure */ - AcceptData.ListenHandle = (HANDLE)AcceptSocket; - AcceptData.SequenceNumber = ListenReceiveData->SequenceNumber; - - /* Send IOCTL to Accept */ - Status = NtDeviceIoControlFile((HANDLE)Socket->Handle, - SockEvent, - NULL, - NULL, - &IOSB, - IOCTL_AFD_ACCEPT, - &AcceptData, - sizeof(AcceptData), - NULL, - 0); - - /* Wait for return */ - if (Status == STATUS_PENDING) - { - WaitForSingleObject(SockEvent, INFINITE); - Status = IOSB.Status; - } - - if (!NT_SUCCESS(Status)) - { - NtClose(SockEvent); - WSPCloseSocket( AcceptSocket, lpErrno ); - MsafdReturnWithErrno( Status, lpErrno, 0, NULL ); - return INVALID_SOCKET; - } - - /* Return Address in SOCKADDR FORMAT */ - if( SocketAddress ) - { - RtlCopyMemory (SocketAddress, - &ListenReceiveData->Address.Address[0].AddressType, - sizeof(*RemoteAddress)); - if( SocketAddressLength ) - *SocketAddressLength = ListenReceiveData->Address.Address[0].AddressLength; - } - - NtClose( SockEvent ); - - /* Re-enable Async Event */ - SockReenableAsyncSelectEvent(Socket, FD_ACCEPT); - - AFD_DbgPrint(MID_TRACE,("Socket %x\n", AcceptSocket)); - - if (Status == STATUS_SUCCESS && (Socket->HelperEvents & WSH_NOTIFY_ACCEPT)) - { - Status = Socket->HelperData->WSHNotify(Socket->HelperContext, - Socket->Handle, - Socket->TdiAddressHandle, - Socket->TdiConnectionHandle, - WSH_NOTIFY_ACCEPT); - - if (Status) - { - if (lpErrno) *lpErrno = Status; - return INVALID_SOCKET; - } - } - - *lpErrno = 0; - - /* Return Socket */ - return AcceptSocket; -} - -int -WSPAPI -WSPConnect(SOCKET Handle, - const struct sockaddr * SocketAddress, - int SocketAddressLength, - LPWSABUF lpCallerData, - LPWSABUF lpCalleeData, - LPQOS lpSQOS, - LPQOS lpGQOS, - LPINT lpErrno) -{ - IO_STATUS_BLOCK IOSB; - PAFD_CONNECT_INFO ConnectInfo; - PSOCKET_INFORMATION Socket = NULL; - NTSTATUS Status; - UCHAR ConnectBuffer[0x22]; - ULONG ConnectDataLength; - ULONG InConnectDataLength; - INT BindAddressLength; - PSOCKADDR BindAddress; - HANDLE SockEvent; - - Status = NtCreateEvent(&SockEvent, - GENERIC_READ | GENERIC_WRITE, - NULL, - 1, - FALSE); - - if( !NT_SUCCESS(Status) ) - return -1; - - AFD_DbgPrint(MID_TRACE,("Called\n")); - - /* Get the Socket Structure associate to this Socket*/ - Socket = GetSocketStructure(Handle); - - /* Bind us First */ - if (Socket->SharedData.State == SocketOpen) - { - /* Get the Wildcard Address */ - BindAddressLength = Socket->HelperData->MaxWSAddressLength; - BindAddress = HeapAlloc(GetProcessHeap(), 0, BindAddressLength); - if (!BindAddress) - { - MsafdReturnWithErrno( STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL ); - return INVALID_SOCKET; - } - Socket->HelperData->WSHGetWildcardSockaddr (Socket->HelperContext, - BindAddress, - &BindAddressLength); - /* Bind it */ - WSPBind(Handle, BindAddress, BindAddressLength, NULL); - } - - /* Set the Connect Data */ - if (lpCallerData != NULL) - { - ConnectDataLength = lpCallerData->len; - Status = NtDeviceIoControlFile((HANDLE)Handle, - SockEvent, - NULL, - NULL, - &IOSB, - IOCTL_AFD_SET_CONNECT_DATA, - lpCallerData->buf, - ConnectDataLength, - NULL, - 0); - /* Wait for return */ - if (Status == STATUS_PENDING) - { - WaitForSingleObject(SockEvent, INFINITE); - Status = IOSB.Status; - } - } - - /* Dynamic Structure...ugh */ - ConnectInfo = (PAFD_CONNECT_INFO)ConnectBuffer; - - /* Set up Address in TDI Format */ - ConnectInfo->RemoteAddress.TAAddressCount = 1; - ConnectInfo->RemoteAddress.Address[0].AddressLength = SocketAddressLength - sizeof(SocketAddress->sa_family); - ConnectInfo->RemoteAddress.Address[0].AddressType = SocketAddress->sa_family; - RtlCopyMemory (ConnectInfo->RemoteAddress.Address[0].Address, - SocketAddress->sa_data, - SocketAddressLength - sizeof(SocketAddress->sa_family)); - - /* - * Disable FD_WRITE and FD_CONNECT - * The latter fixes a race condition where the FD_CONNECT is re-enabled - * at the end of this function right after the Async Thread disables it. - * This should only happen at the *next* WSPConnect - */ - if (Socket->SharedData.AsyncEvents & FD_CONNECT) - { - Socket->SharedData.AsyncDisabledEvents |= FD_CONNECT | FD_WRITE; - } - - /* Tell AFD that we want Connection Data back, have it allocate a buffer */ - if (lpCalleeData != NULL) - { - InConnectDataLength = lpCalleeData->len; - Status = NtDeviceIoControlFile((HANDLE)Handle, - SockEvent, - NULL, - NULL, - &IOSB, - IOCTL_AFD_SET_CONNECT_DATA_SIZE, - &InConnectDataLength, - sizeof(InConnectDataLength), - NULL, - 0); - - /* Wait for return */ - if (Status == STATUS_PENDING) - { - WaitForSingleObject(SockEvent, INFINITE); - Status = IOSB.Status; - } - } - - /* AFD doesn't seem to care if these are invalid, but let's 0 them anyways */ - ConnectInfo->Root = 0; - ConnectInfo->UseSAN = FALSE; - ConnectInfo->Unknown = 0; - - /* FIXME: Handle Async Connect */ - if (Socket->SharedData.NonBlocking) - { - AFD_DbgPrint(MIN_TRACE, ("Async Connect UNIMPLEMENTED!\n")); - } - - /* Send IOCTL */ - Status = NtDeviceIoControlFile((HANDLE)Handle, - SockEvent, - NULL, - NULL, - &IOSB, - IOCTL_AFD_CONNECT, - ConnectInfo, - 0x22, - NULL, - 0); - /* Wait for return */ - if (Status == STATUS_PENDING) - { - WaitForSingleObject(SockEvent, INFINITE); - Status = IOSB.Status; - } - - Socket->TdiConnectionHandle = (HANDLE)IOSB.Information; - - /* Get any pending connect data */ - if (lpCalleeData != NULL) - { - Status = NtDeviceIoControlFile((HANDLE)Handle, - SockEvent, - NULL, - NULL, - &IOSB, - IOCTL_AFD_GET_CONNECT_DATA, - NULL, - 0, - lpCalleeData->buf, - lpCalleeData->len); - /* Wait for return */ - if (Status == STATUS_PENDING) - { - WaitForSingleObject(SockEvent, INFINITE); - Status = IOSB.Status; - } - } - - /* Re-enable Async Event */ - SockReenableAsyncSelectEvent(Socket, FD_WRITE); - - /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */ - SockReenableAsyncSelectEvent(Socket, FD_CONNECT); - - AFD_DbgPrint(MID_TRACE,("Ending\n")); - - NtClose( SockEvent ); - - if (Status == STATUS_SUCCESS && (Socket->HelperEvents & WSH_NOTIFY_CONNECT)) - { - Status = Socket->HelperData->WSHNotify(Socket->HelperContext, - Socket->Handle, - Socket->TdiAddressHandle, - Socket->TdiConnectionHandle, - WSH_NOTIFY_CONNECT); - - if (Status) - { - if (lpErrno) *lpErrno = Status; - return SOCKET_ERROR; - } - } - else if (Status != STATUS_SUCCESS && (Socket->HelperEvents & WSH_NOTIFY_CONNECT_ERROR)) - { - Status = Socket->HelperData->WSHNotify(Socket->HelperContext, - Socket->Handle, - Socket->TdiAddressHandle, - Socket->TdiConnectionHandle, - WSH_NOTIFY_CONNECT_ERROR); - - if (Status) - { - if (lpErrno) *lpErrno = Status; - return SOCKET_ERROR; - } - } - - return MsafdReturnWithErrno( Status, lpErrno, 0, NULL ); -} -int -WSPAPI -WSPShutdown(SOCKET Handle, - int HowTo, - LPINT lpErrno) - -{ - IO_STATUS_BLOCK IOSB; - AFD_DISCONNECT_INFO DisconnectInfo; - PSOCKET_INFORMATION Socket = NULL; - NTSTATUS Status; - HANDLE SockEvent; - - Status = NtCreateEvent(&SockEvent, - GENERIC_READ | GENERIC_WRITE, - NULL, - 1, - FALSE); - - if( !NT_SUCCESS(Status) ) - return -1; - - AFD_DbgPrint(MID_TRACE,("Called\n")); - - /* Get the Socket Structure associate to this Socket*/ - Socket = GetSocketStructure(Handle); - - /* Set AFD Disconnect Type */ - switch (HowTo) - { - case SD_RECEIVE: - DisconnectInfo.DisconnectType = AFD_DISCONNECT_RECV; - Socket->SharedData.ReceiveShutdown = TRUE; - break; - case SD_SEND: - DisconnectInfo.DisconnectType= AFD_DISCONNECT_SEND; - Socket->SharedData.SendShutdown = TRUE; - break; - case SD_BOTH: - DisconnectInfo.DisconnectType = AFD_DISCONNECT_RECV | AFD_DISCONNECT_SEND; - Socket->SharedData.ReceiveShutdown = TRUE; - Socket->SharedData.SendShutdown = TRUE; - break; - } - - DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(-1); - - /* Send IOCTL */ - Status = NtDeviceIoControlFile((HANDLE)Handle, - SockEvent, - NULL, - NULL, - &IOSB, - IOCTL_AFD_DISCONNECT, - &DisconnectInfo, - sizeof(DisconnectInfo), - NULL, - 0); - - /* Wait for return */ - if (Status == STATUS_PENDING) - { - WaitForSingleObject(SockEvent, INFINITE); - Status = IOSB.Status; - } - - AFD_DbgPrint(MID_TRACE,("Ending\n")); - - NtClose( SockEvent ); - - return MsafdReturnWithErrno( Status, lpErrno, 0, NULL ); -} - - -INT -WSPAPI -WSPGetSockName(IN SOCKET Handle, - OUT LPSOCKADDR Name, - IN OUT LPINT NameLength, - OUT LPINT lpErrno) -{ - IO_STATUS_BLOCK IOSB; - ULONG TdiAddressSize; - PTDI_ADDRESS_INFO TdiAddress; - PTRANSPORT_ADDRESS SocketAddress; - PSOCKET_INFORMATION Socket = NULL; - NTSTATUS Status; - HANDLE SockEvent; - - Status = NtCreateEvent(&SockEvent, - GENERIC_READ | GENERIC_WRITE, - NULL, - 1, - FALSE); - - if( !NT_SUCCESS(Status) ) - return SOCKET_ERROR; - - /* Get the Socket Structure associate to this Socket*/ - Socket = GetSocketStructure(Handle); - - /* Allocate a buffer for the address */ - TdiAddressSize = - sizeof(TRANSPORT_ADDRESS) + Socket->SharedData.SizeOfLocalAddress; - TdiAddress = HeapAlloc(GlobalHeap, 0, TdiAddressSize); - - if ( TdiAddress == NULL ) - { - NtClose( SockEvent ); - *lpErrno = WSAENOBUFS; - return SOCKET_ERROR; - } - - SocketAddress = &TdiAddress->Address; - - /* Send IOCTL */ - Status = NtDeviceIoControlFile((HANDLE)Socket->Handle, - SockEvent, - NULL, - NULL, - &IOSB, - IOCTL_AFD_GET_SOCK_NAME, - NULL, - 0, - TdiAddress, - TdiAddressSize); - - /* Wait for return */ - if (Status == STATUS_PENDING) - { - WaitForSingleObject(SockEvent, INFINITE); - Status = IOSB.Status; - } - - NtClose( SockEvent ); - - if (NT_SUCCESS(Status)) - { - if (*NameLength >= SocketAddress->Address[0].AddressLength) - { - Name->sa_family = SocketAddress->Address[0].AddressType; - RtlCopyMemory (Name->sa_data, - SocketAddress->Address[0].Address, - SocketAddress->Address[0].AddressLength); - *NameLength = 2 + SocketAddress->Address[0].AddressLength; - AFD_DbgPrint (MID_TRACE, ("NameLength %d Address: %x Port %x\n", - *NameLength, ((struct sockaddr_in *)Name)->sin_addr.s_addr, - ((struct sockaddr_in *)Name)->sin_port)); - HeapFree(GlobalHeap, 0, TdiAddress); - return 0; - } - else - { - HeapFree(GlobalHeap, 0, TdiAddress); - *lpErrno = WSAEFAULT; - return SOCKET_ERROR; - } - } - - return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL ); -} - - -INT -WSPAPI -WSPGetPeerName(IN SOCKET s, - OUT LPSOCKADDR Name, - IN OUT LPINT NameLength, - OUT LPINT lpErrno) -{ - IO_STATUS_BLOCK IOSB; - ULONG TdiAddressSize; - PTRANSPORT_ADDRESS SocketAddress; - PSOCKET_INFORMATION Socket = NULL; - NTSTATUS Status; - HANDLE SockEvent; - - Status = NtCreateEvent(&SockEvent, - GENERIC_READ | GENERIC_WRITE, - NULL, - 1, - FALSE); - - if( !NT_SUCCESS(Status) ) - return SOCKET_ERROR; - - /* Get the Socket Structure associate to this Socket*/ - Socket = GetSocketStructure(s); - - /* Allocate a buffer for the address */ - TdiAddressSize = sizeof(TRANSPORT_ADDRESS) + *NameLength; - SocketAddress = HeapAlloc(GlobalHeap, 0, TdiAddressSize); - - if ( SocketAddress == NULL ) - { - NtClose( SockEvent ); - *lpErrno = WSAENOBUFS; - return SOCKET_ERROR; - } - - /* Send IOCTL */ - Status = NtDeviceIoControlFile((HANDLE)Socket->Handle, - SockEvent, - NULL, - NULL, - &IOSB, - IOCTL_AFD_GET_PEER_NAME, - NULL, - 0, - SocketAddress, - TdiAddressSize); - - /* Wait for return */ - if (Status == STATUS_PENDING) - { - WaitForSingleObject(SockEvent, INFINITE); - Status = IOSB.Status; - } - - NtClose( SockEvent ); - - if (NT_SUCCESS(Status)) - { - if (*NameLength >= SocketAddress->Address[0].AddressLength) - { - Name->sa_family = SocketAddress->Address[0].AddressType; - RtlCopyMemory (Name->sa_data, - SocketAddress->Address[0].Address, - SocketAddress->Address[0].AddressLength); - *NameLength = 2 + SocketAddress->Address[0].AddressLength; - AFD_DbgPrint (MID_TRACE, ("NameLength %d Address: %s Port %x\n", - *NameLength, ((struct sockaddr_in *)Name)->sin_addr.s_addr, - ((struct sockaddr_in *)Name)->sin_port)); - HeapFree(GlobalHeap, 0, SocketAddress); - return 0; - } - else - { - HeapFree(GlobalHeap, 0, SocketAddress); - *lpErrno = WSAEFAULT; - return SOCKET_ERROR; - } - } - - return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL ); -} - -INT -WSPAPI -WSPIoctl(IN SOCKET Handle, - IN DWORD dwIoControlCode, - IN LPVOID lpvInBuffer, - IN DWORD cbInBuffer, - OUT LPVOID lpvOutBuffer, - IN DWORD cbOutBuffer, - OUT LPDWORD lpcbBytesReturned, - IN LPWSAOVERLAPPED lpOverlapped, - IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, - IN LPWSATHREADID lpThreadId, - OUT LPINT lpErrno) -{ - PSOCKET_INFORMATION Socket = NULL; - - /* Get the Socket Structure associate to this Socket*/ - Socket = GetSocketStructure(Handle); - - switch( dwIoControlCode ) - { - case FIONBIO: - if( cbInBuffer < sizeof(INT) || IS_INTRESOURCE(lpvInBuffer) ) - { - *lpErrno = WSAEFAULT; - return SOCKET_ERROR; - } - Socket->SharedData.NonBlocking = *((PULONG)lpvInBuffer) ? 1 : 0; - return SetSocketInformation(Socket, AFD_INFO_BLOCKING_MODE, (PULONG)lpvInBuffer, NULL); - case FIONREAD: - if( cbOutBuffer < sizeof(INT) || IS_INTRESOURCE(lpvOutBuffer) ) - { - *lpErrno = WSAEFAULT; - return SOCKET_ERROR; - } - return GetSocketInformation(Socket, AFD_INFO_RECEIVE_CONTENT_SIZE, (PULONG)lpvOutBuffer, NULL); - default: - *lpErrno = WSAEINVAL; - return SOCKET_ERROR; - } -} - - -INT -WSPAPI -WSPGetSockOpt(IN SOCKET Handle, - IN INT Level, - IN INT OptionName, - OUT CHAR FAR* OptionValue, - IN OUT LPINT OptionLength, - OUT LPINT lpErrno) -{ - PSOCKET_INFORMATION Socket = NULL; - PVOID Buffer; - INT BufferSize; - BOOLEAN BoolBuffer; - - /* Get the Socket Structure associate to this Socket*/ - Socket = GetSocketStructure(Handle); - if (Socket == NULL) - { - *lpErrno = WSAENOTSOCK; - return SOCKET_ERROR; - } - - AFD_DbgPrint(MID_TRACE, ("Called\n")); - - switch (Level) - { - case SOL_SOCKET: - switch (OptionName) - { - case SO_TYPE: - Buffer = &Socket->SharedData.SocketType; - BufferSize = sizeof(INT); - break; - - case SO_RCVBUF: - Buffer = &Socket->SharedData.SizeOfRecvBuffer; - BufferSize = sizeof(INT); - break; - - case SO_SNDBUF: - Buffer = &Socket->SharedData.SizeOfSendBuffer; - BufferSize = sizeof(INT); - break; - - case SO_ACCEPTCONN: - BoolBuffer = Socket->SharedData.Listening; - Buffer = &BoolBuffer; - BufferSize = sizeof(BOOLEAN); - break; - - case SO_BROADCAST: - BoolBuffer = Socket->SharedData.Broadcast; - Buffer = &BoolBuffer; - BufferSize = sizeof(BOOLEAN); - break; - - case SO_DEBUG: - BoolBuffer = Socket->SharedData.Debug; - Buffer = &BoolBuffer; - BufferSize = sizeof(BOOLEAN); - break; - - /* case SO_CONDITIONAL_ACCEPT: */ - case SO_DONTLINGER: - case SO_DONTROUTE: - case SO_ERROR: - case SO_GROUP_ID: - case SO_GROUP_PRIORITY: - case SO_KEEPALIVE: - case SO_LINGER: - case SO_MAX_MSG_SIZE: - case SO_OOBINLINE: - case SO_PROTOCOL_INFO: - case SO_REUSEADDR: - AFD_DbgPrint(MID_TRACE, ("Unimplemented option (%x)\n", - OptionName)); - - default: - *lpErrno = WSAEINVAL; - return SOCKET_ERROR; - } - - if (*OptionLength < BufferSize) - { - *lpErrno = WSAEFAULT; - *OptionLength = BufferSize; - return SOCKET_ERROR; - } - RtlCopyMemory(OptionValue, Buffer, BufferSize); - - return 0; - - case IPPROTO_TCP: /* FIXME */ - default: - *lpErrno = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, - Handle, - Socket->TdiAddressHandle, - Socket->TdiConnectionHandle, - Level, - OptionName, - OptionValue, - (LPINT)OptionLength); - return (*lpErrno == 0) ? 0 : SOCKET_ERROR; - } -} - -INT -WSPAPI -WSPSetSockOpt( - IN SOCKET s, - IN INT level, - IN INT optname, - IN CONST CHAR FAR* optval, - IN INT optlen, - OUT LPINT lpErrno) -{ - PSOCKET_INFORMATION Socket; - - /* Get the Socket Structure associate to this Socket*/ - Socket = GetSocketStructure(s); - if (Socket == NULL) - { - *lpErrno = WSAENOTSOCK; - return SOCKET_ERROR; - } - - - /* FIXME: We should handle some cases here */ - - - *lpErrno = Socket->HelperData->WSHSetSocketInformation(Socket->HelperContext, - s, - Socket->TdiAddressHandle, - Socket->TdiConnectionHandle, - level, - optname, - (PCHAR)optval, - optlen); - return (*lpErrno == 0) ? 0 : SOCKET_ERROR; -} - -/* - * FUNCTION: Initialize service provider for a client - * ARGUMENTS: - * wVersionRequested = Highest WinSock SPI version that the caller can use - * lpWSPData = Address of WSPDATA structure to initialize - * lpProtocolInfo = Pointer to structure that defines the desired protocol - * UpcallTable = Pointer to upcall table of the WinSock DLL - * lpProcTable = Address of procedure table to initialize - * RETURNS: - * Status of operation - */ -INT -WSPAPI -WSPStartup(IN WORD wVersionRequested, - OUT LPWSPDATA lpWSPData, - IN LPWSAPROTOCOL_INFOW lpProtocolInfo, - IN WSPUPCALLTABLE UpcallTable, - OUT LPWSPPROC_TABLE lpProcTable) - -{ - NTSTATUS Status; - - AFD_DbgPrint(MAX_TRACE, ("wVersionRequested (0x%X) \n", wVersionRequested)); - Status = NO_ERROR; - Upcalls = UpcallTable; - - if (Status == NO_ERROR) - { - lpProcTable->lpWSPAccept = WSPAccept; - lpProcTable->lpWSPAddressToString = WSPAddressToString; - lpProcTable->lpWSPAsyncSelect = WSPAsyncSelect; - lpProcTable->lpWSPBind = WSPBind; - lpProcTable->lpWSPCancelBlockingCall = WSPCancelBlockingCall; - lpProcTable->lpWSPCleanup = WSPCleanup; - lpProcTable->lpWSPCloseSocket = WSPCloseSocket; - lpProcTable->lpWSPConnect = WSPConnect; - lpProcTable->lpWSPDuplicateSocket = WSPDuplicateSocket; - lpProcTable->lpWSPEnumNetworkEvents = WSPEnumNetworkEvents; - lpProcTable->lpWSPEventSelect = WSPEventSelect; - lpProcTable->lpWSPGetOverlappedResult = WSPGetOverlappedResult; - lpProcTable->lpWSPGetPeerName = WSPGetPeerName; - lpProcTable->lpWSPGetSockName = WSPGetSockName; - lpProcTable->lpWSPGetSockOpt = WSPGetSockOpt; - lpProcTable->lpWSPGetQOSByName = WSPGetQOSByName; - lpProcTable->lpWSPIoctl = WSPIoctl; - lpProcTable->lpWSPJoinLeaf = WSPJoinLeaf; - lpProcTable->lpWSPListen = WSPListen; - lpProcTable->lpWSPRecv = WSPRecv; - lpProcTable->lpWSPRecvDisconnect = WSPRecvDisconnect; - lpProcTable->lpWSPRecvFrom = WSPRecvFrom; - lpProcTable->lpWSPSelect = WSPSelect; - lpProcTable->lpWSPSend = WSPSend; - lpProcTable->lpWSPSendDisconnect = WSPSendDisconnect; - lpProcTable->lpWSPSendTo = WSPSendTo; - lpProcTable->lpWSPSetSockOpt = WSPSetSockOpt; - lpProcTable->lpWSPShutdown = WSPShutdown; - lpProcTable->lpWSPSocket = WSPSocket; - lpProcTable->lpWSPStringToAddress = WSPStringToAddress; - lpWSPData->wVersion = MAKEWORD(2, 2); - lpWSPData->wHighVersion = MAKEWORD(2, 2); - } - - AFD_DbgPrint(MAX_TRACE, ("Status (%d).\n", Status)); - - return Status; -} - - -/* - * FUNCTION: Cleans up service provider for a client - * ARGUMENTS: - * lpErrno = Address of buffer for error information - * RETURNS: - * 0 if successful, or SOCKET_ERROR if not - */ -INT -WSPAPI -WSPCleanup(OUT LPINT lpErrno) - -{ - AFD_DbgPrint(MAX_TRACE, ("\n")); - AFD_DbgPrint(MAX_TRACE, ("Leaving.\n")); - *lpErrno = NO_ERROR; - - return 0; -} - - - -int -GetSocketInformation(PSOCKET_INFORMATION Socket, - ULONG AfdInformationClass, - PULONG Ulong OPTIONAL, - PLARGE_INTEGER LargeInteger OPTIONAL) -{ - IO_STATUS_BLOCK IOSB; - AFD_INFO InfoData; - NTSTATUS Status; - HANDLE SockEvent; - - Status = NtCreateEvent(&SockEvent, - GENERIC_READ | GENERIC_WRITE, - NULL, - 1, - FALSE); - - if( !NT_SUCCESS(Status) ) - return -1; - - /* Set Info Class */ - InfoData.InformationClass = AfdInformationClass; - - /* Send IOCTL */ - Status = NtDeviceIoControlFile((HANDLE)Socket->Handle, - SockEvent, - NULL, - NULL, - &IOSB, - IOCTL_AFD_GET_INFO, - &InfoData, - sizeof(InfoData), - &InfoData, - sizeof(InfoData)); - - /* Wait for return */ - if (Status == STATUS_PENDING) - { - WaitForSingleObject(SockEvent, INFINITE); - } - - /* Return Information */ - if (Ulong != NULL) - { - *Ulong = InfoData.Information.Ulong; - } - if (LargeInteger != NULL) - { - *LargeInteger = InfoData.Information.LargeInteger; - } - - NtClose( SockEvent ); - - return 0; - -} - - -int -SetSocketInformation(PSOCKET_INFORMATION Socket, - ULONG AfdInformationClass, - PULONG Ulong OPTIONAL, - PLARGE_INTEGER LargeInteger OPTIONAL) -{ - IO_STATUS_BLOCK IOSB; - AFD_INFO InfoData; - NTSTATUS Status; - HANDLE SockEvent; - - Status = NtCreateEvent(&SockEvent, - GENERIC_READ | GENERIC_WRITE, - NULL, - 1, - FALSE); - - if( !NT_SUCCESS(Status) ) - return -1; - - /* Set Info Class */ - InfoData.InformationClass = AfdInformationClass; - - /* Set Information */ - if (Ulong != NULL) - { - InfoData.Information.Ulong = *Ulong; - } - if (LargeInteger != NULL) - { - InfoData.Information.LargeInteger = *LargeInteger; - } - - AFD_DbgPrint(MID_TRACE,("XXX Info %x (Data %x)\n", - AfdInformationClass, *Ulong)); - - /* Send IOCTL */ - Status = NtDeviceIoControlFile((HANDLE)Socket->Handle, - SockEvent, - NULL, - NULL, - &IOSB, - IOCTL_AFD_SET_INFO, - &InfoData, - sizeof(InfoData), - NULL, - 0); - - /* Wait for return */ - if (Status == STATUS_PENDING) - { - WaitForSingleObject(SockEvent, INFINITE); - } - - NtClose( SockEvent ); - - return 0; - -} - -PSOCKET_INFORMATION -GetSocketStructure(SOCKET Handle) -{ - ULONG i; - - for (i=0; iHandle == Handle) - { - return Sockets[i]; - } - } - return 0; -} - -int CreateContext(PSOCKET_INFORMATION Socket) -{ - IO_STATUS_BLOCK IOSB; - SOCKET_CONTEXT ContextData; - NTSTATUS Status; - HANDLE SockEvent; - - Status = NtCreateEvent(&SockEvent, - GENERIC_READ | GENERIC_WRITE, - NULL, - 1, - FALSE); - - if( !NT_SUCCESS(Status) ) - return -1; - - /* Create Context */ - ContextData.SharedData = Socket->SharedData; - ContextData.SizeOfHelperData = 0; - RtlCopyMemory (&ContextData.LocalAddress, - Socket->LocalAddress, - Socket->SharedData.SizeOfLocalAddress); - RtlCopyMemory (&ContextData.RemoteAddress, - Socket->RemoteAddress, - Socket->SharedData.SizeOfRemoteAddress); - - /* Send IOCTL */ - Status = NtDeviceIoControlFile((HANDLE)Socket->Handle, - SockEvent, - NULL, - NULL, - &IOSB, - IOCTL_AFD_SET_CONTEXT, - &ContextData, - sizeof(ContextData), - NULL, - 0); - - /* Wait for Completition */ - if (Status == STATUS_PENDING) - { - WaitForSingleObject(SockEvent, INFINITE); - } - - NtClose( SockEvent ); - - return 0; -} - -BOOLEAN SockCreateOrReferenceAsyncThread(VOID) -{ - HANDLE hAsyncThread; - DWORD AsyncThreadId; - HANDLE AsyncEvent; - OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags; - NTSTATUS Status; - - /* Check if the Thread Already Exists */ - if (SockAsyncThreadRefCount) - { - return TRUE; - } - - /* Create the Completion Port */ - if (!SockAsyncCompletionPort) - { - Status = NtCreateIoCompletion(&SockAsyncCompletionPort, - IO_COMPLETION_ALL_ACCESS, - NULL, - 2); // Allow 2 threads only - - /* Protect Handle */ - HandleFlags.ProtectFromClose = TRUE; - HandleFlags.Inherit = FALSE; - Status = NtSetInformationObject(SockAsyncCompletionPort, - ObjectHandleFlagInformation, - &HandleFlags, - sizeof(HandleFlags)); - } - - /* Create the Async Event */ - Status = NtCreateEvent(&AsyncEvent, - EVENT_ALL_ACCESS, - NULL, - NotificationEvent, - FALSE); - - /* Create the Async Thread */ - hAsyncThread = CreateThread(NULL, - 0, - (LPTHREAD_START_ROUTINE)SockAsyncThread, - NULL, - 0, - &AsyncThreadId); - - /* Close the Handle */ - NtClose(hAsyncThread); - - /* Increase the Reference Count */ - SockAsyncThreadRefCount++; - return TRUE; -} - -int SockAsyncThread(PVOID ThreadParam) -{ - PVOID AsyncContext; - PASYNC_COMPLETION_ROUTINE AsyncCompletionRoutine; - IO_STATUS_BLOCK IOSB; - NTSTATUS Status; - - /* Make the Thread Higher Priority */ - SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL); - - /* Do a KQUEUE/WorkItem Style Loop, thanks to IoCompletion Ports */ - do - { - Status = NtRemoveIoCompletion (SockAsyncCompletionPort, - (PVOID*)&AsyncCompletionRoutine, - &AsyncContext, - &IOSB, - NULL); - /* Call the Async Function */ - if (NT_SUCCESS(Status)) - { - (*AsyncCompletionRoutine)(AsyncContext, &IOSB); - } - else - { - /* It Failed, sleep for a second */ - Sleep(1000); - } - } while ((Status != STATUS_TIMEOUT)); - - /* The Thread has Ended */ - return 0; -} - -BOOLEAN SockGetAsyncSelectHelperAfdHandle(VOID) -{ - UNICODE_STRING AfdHelper; - OBJECT_ATTRIBUTES ObjectAttributes; - IO_STATUS_BLOCK IoSb; - NTSTATUS Status; - FILE_COMPLETION_INFORMATION CompletionInfo; - OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags; - - /* First, make sure we're not already intialized */ - if (SockAsyncHelperAfdHandle) - { - return TRUE; - } - - /* Set up Handle Name and Object */ - RtlInitUnicodeString(&AfdHelper, L"\\Device\\Afd\\AsyncSelectHlp" ); - InitializeObjectAttributes(&ObjectAttributes, - &AfdHelper, - OBJ_INHERIT | OBJ_CASE_INSENSITIVE, - NULL, - NULL); - - /* Open the Handle to AFD */ - Status = NtCreateFile(&SockAsyncHelperAfdHandle, - GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, - &ObjectAttributes, - &IoSb, - NULL, - 0, - FILE_SHARE_READ | FILE_SHARE_WRITE, - FILE_OPEN_IF, - 0, - NULL, - 0); - - /* - * Now Set up the Completion Port Information - * This means that whenever a Poll is finished, the routine will be executed - */ - CompletionInfo.Port = SockAsyncCompletionPort; - CompletionInfo.Key = SockAsyncSelectCompletionRoutine; - Status = NtSetInformationFile(SockAsyncHelperAfdHandle, - &IoSb, - &CompletionInfo, - sizeof(CompletionInfo), - FileCompletionInformation); - - - /* Protect the Handle */ - HandleFlags.ProtectFromClose = TRUE; - HandleFlags.Inherit = FALSE; - Status = NtSetInformationObject(SockAsyncCompletionPort, - ObjectHandleFlagInformation, - &HandleFlags, - sizeof(HandleFlags)); - - - /* Set this variable to true so that Send/Recv/Accept will know wether to renable disabled events */ - SockAsyncSelectCalled = TRUE; - return TRUE; -} - -VOID SockAsyncSelectCompletionRoutine(PVOID Context, PIO_STATUS_BLOCK IoStatusBlock) -{ - - PASYNC_DATA AsyncData = Context; - PSOCKET_INFORMATION Socket; - ULONG x; - - /* Get the Socket */ - Socket = AsyncData->ParentSocket; - - /* Check if the Sequence Number Changed behind our back */ - if (AsyncData->SequenceNumber != Socket->SharedData.SequenceNumber ) - { - return; - } - - /* Check we were manually called b/c of a failure */ - if (!NT_SUCCESS(IoStatusBlock->Status)) - { - /* FIXME: Perform Upcall */ - return; - } - - for (x = 1; x; x<<=1) - { - switch (AsyncData->AsyncSelectInfo.Handles[0].Events & x) - { - case AFD_EVENT_RECEIVE: - if (0 != (Socket->SharedData.AsyncEvents & FD_READ) && - 0 == (Socket->SharedData.AsyncDisabledEvents & FD_READ)) - { - /* Make the Notifcation */ - (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd, - Socket->SharedData.wMsg, - Socket->Handle, - WSAMAKESELECTREPLY(FD_READ, 0)); - /* Disable this event until the next read(); */ - Socket->SharedData.AsyncDisabledEvents |= FD_READ; - } - break; - - case AFD_EVENT_OOB_RECEIVE: - if (0 != (Socket->SharedData.AsyncEvents & FD_OOB) && - 0 == (Socket->SharedData.AsyncDisabledEvents & FD_OOB)) - { - /* Make the Notifcation */ - (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd, - Socket->SharedData.wMsg, - Socket->Handle, - WSAMAKESELECTREPLY(FD_OOB, 0)); - /* Disable this event until the next read(); */ - Socket->SharedData.AsyncDisabledEvents |= FD_OOB; - } - break; - - case AFD_EVENT_SEND: - if (0 != (Socket->SharedData.AsyncEvents & FD_WRITE) && - 0 == (Socket->SharedData.AsyncDisabledEvents & FD_WRITE)) - { - /* Make the Notifcation */ - (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd, - Socket->SharedData.wMsg, - Socket->Handle, - WSAMAKESELECTREPLY(FD_WRITE, 0)); - /* Disable this event until the next write(); */ - Socket->SharedData.AsyncDisabledEvents |= FD_WRITE; - } - break; - - /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */ - case AFD_EVENT_CONNECT: - case AFD_EVENT_CONNECT_FAIL: - if (0 != (Socket->SharedData.AsyncEvents & FD_CONNECT) && - 0 == (Socket->SharedData.AsyncDisabledEvents & FD_CONNECT)) - { - /* Make the Notifcation */ - (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd, - Socket->SharedData.wMsg, - Socket->Handle, - WSAMAKESELECTREPLY(FD_CONNECT, 0)); - /* Disable this event forever; */ - Socket->SharedData.AsyncDisabledEvents |= FD_CONNECT; - } - break; - - case AFD_EVENT_ACCEPT: - if (0 != (Socket->SharedData.AsyncEvents & FD_ACCEPT) && - 0 == (Socket->SharedData.AsyncDisabledEvents & FD_ACCEPT)) - { - /* Make the Notifcation */ - (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd, - Socket->SharedData.wMsg, - Socket->Handle, - WSAMAKESELECTREPLY(FD_ACCEPT, 0)); - /* Disable this event until the next accept(); */ - Socket->SharedData.AsyncDisabledEvents |= FD_ACCEPT; - } - break; - - case AFD_EVENT_DISCONNECT: - case AFD_EVENT_ABORT: - case AFD_EVENT_CLOSE: - if (0 != (Socket->SharedData.AsyncEvents & FD_CLOSE) && - 0 == (Socket->SharedData.AsyncDisabledEvents & FD_CLOSE)) - { - /* Make the Notifcation */ - (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd, - Socket->SharedData.wMsg, - Socket->Handle, - WSAMAKESELECTREPLY(FD_CLOSE, 0)); - /* Disable this event forever; */ - Socket->SharedData.AsyncDisabledEvents |= FD_CLOSE; - } - break; - /* FIXME: Support QOS */ - } - } - - /* Check if there are any events left for us to check */ - if ((Socket->SharedData.AsyncEvents & (~Socket->SharedData.AsyncDisabledEvents)) == 0 ) - { - return; - } - - /* Keep Polling */ - SockProcessAsyncSelect(Socket, AsyncData); - return; -} - -VOID SockProcessAsyncSelect(PSOCKET_INFORMATION Socket, PASYNC_DATA AsyncData) -{ - - ULONG lNetworkEvents; - NTSTATUS Status; - - /* Set up the Async Data Event Info */ - AsyncData->AsyncSelectInfo.Timeout.HighPart = 0x7FFFFFFF; - AsyncData->AsyncSelectInfo.Timeout.LowPart = 0xFFFFFFFF; - AsyncData->AsyncSelectInfo.HandleCount = 1; - AsyncData->AsyncSelectInfo.Exclusive = TRUE; - AsyncData->AsyncSelectInfo.Handles[0].Handle = Socket->Handle; - AsyncData->AsyncSelectInfo.Handles[0].Events = 0; - - /* Remove unwanted events */ - lNetworkEvents = Socket->SharedData.AsyncEvents & (~Socket->SharedData.AsyncDisabledEvents); - - /* Set Events to wait for */ - if (lNetworkEvents & FD_READ) - { - AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_RECEIVE; - } - - if (lNetworkEvents & FD_WRITE) - { - AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_SEND; - } - - if (lNetworkEvents & FD_OOB) - { - AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_OOB_RECEIVE; - } - - if (lNetworkEvents & FD_ACCEPT) - { - AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_ACCEPT; - } - - /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */ - if (lNetworkEvents & FD_CONNECT) - { - AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_CONNECT | AFD_EVENT_CONNECT_FAIL; - } - - if (lNetworkEvents & FD_CLOSE) - { - AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_DISCONNECT | AFD_EVENT_ABORT | AFD_EVENT_CLOSE; - } - - if (lNetworkEvents & FD_QOS) - { - AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_QOS; - } - - if (lNetworkEvents & FD_GROUP_QOS) - { - AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_GROUP_QOS; - } - - /* Send IOCTL */ - Status = NtDeviceIoControlFile (SockAsyncHelperAfdHandle, - NULL, - NULL, - AsyncData, - &AsyncData->IoStatusBlock, - IOCTL_AFD_SELECT, - &AsyncData->AsyncSelectInfo, - sizeof(AsyncData->AsyncSelectInfo), - &AsyncData->AsyncSelectInfo, - sizeof(AsyncData->AsyncSelectInfo)); - - /* I/O Manager Won't call the completion routine, let's do it manually */ - if (NT_SUCCESS(Status)) - { - return; - } - else - { - AsyncData->IoStatusBlock.Status = Status; - SockAsyncSelectCompletionRoutine(AsyncData, &AsyncData->IoStatusBlock); - } -} - -VOID SockProcessQueuedAsyncSelect(PVOID Context, PIO_STATUS_BLOCK IoStatusBlock) -{ - PASYNC_DATA AsyncData = Context; - BOOL FreeContext = TRUE; - PSOCKET_INFORMATION Socket; - - /* Get the Socket */ - Socket = AsyncData->ParentSocket; - - /* If someone closed it, stop the function */ - if (Socket->SharedData.State != SocketClosed) - { - /* Check if the Sequence Number changed by now, in which case quit */ - if (AsyncData->SequenceNumber == Socket->SharedData.SequenceNumber) - { - /* Do the actuall select, if needed */ - if ((Socket->SharedData.AsyncEvents & (~Socket->SharedData.AsyncDisabledEvents))) - { - SockProcessAsyncSelect(Socket, AsyncData); - FreeContext = FALSE; - } - } - } - - /* Free the Context */ - if (FreeContext) - { - HeapFree(GetProcessHeap(), 0, AsyncData); - } - - return; -} - -VOID -SockReenableAsyncSelectEvent (IN PSOCKET_INFORMATION Socket, - IN ULONG Event) -{ - PASYNC_DATA AsyncData; - - /* Make sure the event is actually disabled */ - if (!(Socket->SharedData.AsyncDisabledEvents & Event)) - { - return; - } - - /* Re-enable it */ - Socket->SharedData.AsyncDisabledEvents &= ~Event; - - /* Return if no more events are being polled */ - if ((Socket->SharedData.AsyncEvents & (~Socket->SharedData.AsyncDisabledEvents)) == 0 ) - { - return; - } - - /* Wait on new events */ - AsyncData = HeapAlloc(GetProcessHeap(), 0, sizeof(ASYNC_DATA)); - if (!AsyncData) return; - - /* Create the Asynch Thread if Needed */ - SockCreateOrReferenceAsyncThread(); - - /* Increase the sequence number to stop anything else */ - Socket->SharedData.SequenceNumber++; - - /* Set up the Async Data */ - AsyncData->ParentSocket = Socket; - AsyncData->SequenceNumber = Socket->SharedData.SequenceNumber; - - /* Begin Async Select by using I/O Completion */ - NtSetIoCompletion(SockAsyncCompletionPort, - (PVOID)&SockProcessQueuedAsyncSelect, - AsyncData, - 0, - 0); - - /* All done */ - return; -} - -BOOL -WINAPI -DllMain(HANDLE hInstDll, - ULONG dwReason, - PVOID Reserved) -{ - - switch (dwReason) - { - case DLL_PROCESS_ATTACH: - - AFD_DbgPrint(MAX_TRACE, ("Loading MSAFD.DLL \n")); - - /* Don't need thread attach notifications - so disable them to improve performance */ - DisableThreadLibraryCalls(hInstDll); - - /* List of DLL Helpers */ - InitializeListHead(&SockHelpersListHead); - - /* Heap to use when allocating */ - GlobalHeap = GetProcessHeap(); - - /* Allocate Heap for 1024 Sockets, can be expanded later */ - Sockets = HeapAlloc(GetProcessHeap(), 0, sizeof(PSOCKET_INFORMATION) * 1024); - if (!Sockets) return FALSE; - - AFD_DbgPrint(MAX_TRACE, ("MSAFD.DLL has been loaded\n")); - - break; - - case DLL_THREAD_ATTACH: - break; - - case DLL_THREAD_DETACH: - break; - - case DLL_PROCESS_DETACH: - break; - } - - AFD_DbgPrint(MAX_TRACE, ("DllMain of msafd.dll (leaving)\n")); - - return TRUE; -} - -/* EOF */ - - diff --git a/dll/win32/msafd/misc/event.c b/dll/win32/msafd/misc/event.c deleted file mode 100644 index 9a49e31b282..00000000000 --- a/dll/win32/msafd/misc/event.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Ancillary Function Driver DLL - * FILE: misc/event.c - * PURPOSE: Event handling - * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) - * Alex Ionescu (alex@relsoft.net) - * REVISIONS: - * CSH 15/06-2001 Created - * Alex 16/07/2004 - Complete Rewrite - */ - -#include - -#include - -int -WSPAPI -WSPEventSelect( - SOCKET Handle, - WSAEVENT hEventObject, - long lNetworkEvents, - LPINT lpErrno) -{ - IO_STATUS_BLOCK IOSB; - AFD_EVENT_SELECT_INFO EventSelectInfo; - PSOCKET_INFORMATION Socket = NULL; - NTSTATUS Status; - ULONG BlockMode; - HANDLE SockEvent; - - Status = NtCreateEvent( &SockEvent, GENERIC_READ | GENERIC_WRITE, - NULL, 1, FALSE ); - - if( !NT_SUCCESS(Status) ) return -1; - - /* Get the Socket Structure associate to this Socket*/ - Socket = GetSocketStructure(Handle); - - /* Set Socket to Non-Blocking */ - BlockMode = 1; - SetSocketInformation(Socket, AFD_INFO_BLOCKING_MODE, &BlockMode, NULL); - Socket->SharedData.NonBlocking = TRUE; - - /* Deactivate Async Select if there is one */ - if (Socket->EventObject) { - Socket->SharedData.hWnd = NULL; - Socket->SharedData.wMsg = 0; - Socket->SharedData.AsyncEvents = 0; - Socket->SharedData.SequenceNumber++; // This will kill Async Select after the next completion - } - - /* Set Structure Info */ - EventSelectInfo.EventObject = hEventObject; - EventSelectInfo.Events = 0; - - /* Set Events to wait for */ - if (lNetworkEvents & FD_READ) { - EventSelectInfo.Events |= AFD_EVENT_RECEIVE; - } - - if (lNetworkEvents & FD_WRITE) { - EventSelectInfo.Events |= AFD_EVENT_SEND; - } - - if (lNetworkEvents & FD_OOB) { - EventSelectInfo.Events |= AFD_EVENT_OOB_RECEIVE; - } - - if (lNetworkEvents & FD_ACCEPT) { - EventSelectInfo.Events |= AFD_EVENT_ACCEPT; - } - - if (lNetworkEvents & FD_CONNECT) { - EventSelectInfo.Events |= AFD_EVENT_CONNECT | AFD_EVENT_CONNECT_FAIL; - } - - if (lNetworkEvents & FD_CLOSE) { - EventSelectInfo.Events |= AFD_EVENT_DISCONNECT | AFD_EVENT_ABORT | AFD_EVENT_CLOSE; - } - - if (lNetworkEvents & FD_QOS) { - EventSelectInfo.Events |= AFD_EVENT_QOS; - } - - if (lNetworkEvents & FD_GROUP_QOS) { - EventSelectInfo.Events |= AFD_EVENT_GROUP_QOS; - } - - /* Send IOCTL */ - Status = NtDeviceIoControlFile((HANDLE)Handle, - SockEvent, - NULL, - NULL, - &IOSB, - IOCTL_AFD_EVENT_SELECT, - &EventSelectInfo, - sizeof(EventSelectInfo), - NULL, - 0); - - AFD_DbgPrint(MID_TRACE,("AFD: %x\n", Status)); - - /* Wait for return */ - if (Status == STATUS_PENDING) { - WaitForSingleObject(SockEvent, INFINITE); - } - - AFD_DbgPrint(MID_TRACE,("Waited\n")); - - NtClose( SockEvent ); - - AFD_DbgPrint(MID_TRACE,("Closed event\n")); - - /* Set Socket Data*/ - Socket->EventObject = hEventObject; - Socket->NetworkEvents = lNetworkEvents; - - AFD_DbgPrint(MID_TRACE,("Leaving\n")); - - return 0; -} - - -INT -WSPAPI -WSPEnumNetworkEvents( - IN SOCKET Handle, - IN WSAEVENT hEventObject, - OUT LPWSANETWORKEVENTS lpNetworkEvents, - OUT LPINT lpErrno) -{ - AFD_ENUM_NETWORK_EVENTS_INFO EnumReq; - IO_STATUS_BLOCK IOSB; - PSOCKET_INFORMATION Socket = NULL; - NTSTATUS Status; - HANDLE SockEvent; - - AFD_DbgPrint(MID_TRACE,("Called (lpNetworkEvents %x)\n", lpNetworkEvents)); - - Status = NtCreateEvent( &SockEvent, GENERIC_READ | GENERIC_WRITE, - NULL, 1, FALSE ); - - if( !NT_SUCCESS(Status) ) { - AFD_DbgPrint(MID_TRACE,("Could not make an event %x\n", Status)); - return -1; - } - - /* Get the Socket Structure associate to this Socket*/ - Socket = GetSocketStructure(Handle); - - EnumReq.Event = hEventObject; - - /* Send IOCTL */ - Status = NtDeviceIoControlFile((HANDLE)Handle, - SockEvent, - NULL, - NULL, - &IOSB, - IOCTL_AFD_ENUM_NETWORK_EVENTS, - &EnumReq, - sizeof(EnumReq), - NULL, - 0); - - AFD_DbgPrint(MID_TRACE,("AFD: %x\n", Status)); - - /* Wait for return */ - if (Status == STATUS_PENDING) { - WaitForSingleObject(SockEvent, INFINITE); - Status = STATUS_SUCCESS; - } - - AFD_DbgPrint(MID_TRACE,("Waited\n")); - - NtClose( SockEvent ); - - AFD_DbgPrint(MID_TRACE,("Closed event\n")); - AFD_DbgPrint(MID_TRACE,("About to touch struct at %x (%d)\n", - lpNetworkEvents, sizeof(*lpNetworkEvents))); - - lpNetworkEvents->lNetworkEvents = 0; - - AFD_DbgPrint(MID_TRACE,("Zeroed struct\n")); - - /* Set Events to wait for */ - if (EnumReq.PollEvents & AFD_EVENT_RECEIVE) { - lpNetworkEvents->lNetworkEvents |= FD_READ; - } - - if (EnumReq.PollEvents & AFD_EVENT_SEND) { - lpNetworkEvents->lNetworkEvents |= FD_WRITE; - } - - if (EnumReq.PollEvents & AFD_EVENT_OOB_RECEIVE) { - lpNetworkEvents->lNetworkEvents |= FD_OOB; - } - - if (EnumReq.PollEvents & AFD_EVENT_ACCEPT) { - lpNetworkEvents->lNetworkEvents |= FD_ACCEPT; - } - - if (EnumReq.PollEvents & - (AFD_EVENT_CONNECT | AFD_EVENT_CONNECT_FAIL)) { - lpNetworkEvents->lNetworkEvents |= FD_CONNECT; - } - - if (EnumReq.PollEvents & - (AFD_EVENT_DISCONNECT | AFD_EVENT_ABORT | AFD_EVENT_CLOSE)) { - lpNetworkEvents->lNetworkEvents |= FD_CLOSE; - } - - if (EnumReq.PollEvents & AFD_EVENT_QOS) { - lpNetworkEvents->lNetworkEvents |= FD_QOS; - } - - if (EnumReq.PollEvents & AFD_EVENT_GROUP_QOS) { - lpNetworkEvents->lNetworkEvents |= FD_GROUP_QOS; - } - - if( NT_SUCCESS(Status) ) *lpErrno = 0; - else *lpErrno = WSAEINVAL; - - AFD_DbgPrint(MID_TRACE,("Leaving\n")); - - return 0; -} - -/* EOF */ diff --git a/dll/win32/msafd/misc/helpers.c b/dll/win32/msafd/misc/helpers.c deleted file mode 100644 index 89b1d6ac869..00000000000 --- a/dll/win32/msafd/misc/helpers.c +++ /dev/null @@ -1,520 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Ancillary Function Driver DLL - * FILE: misc/helpers.c - * PURPOSE: Helper DLL management - * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) - * Alex Ionescu (alex@relsoft.net) - * REVISIONS: - * CSH 01/09-2000 Created - * Alex 16/07/2004 - Complete Rewrite - */ -#include - -#include - -CRITICAL_SECTION HelperDLLDatabaseLock; -LIST_ENTRY HelperDLLDatabaseListHead; - - -INT -SockGetTdiName( - PINT AddressFamily, - PINT SocketType, - PINT Protocol, - GROUP Group, - DWORD Flags, - PUNICODE_STRING TransportName, - PVOID *HelperDllContext, - PHELPER_DATA *HelperDllData, - PDWORD Events) -{ - PHELPER_DATA HelperData; - PWSTR Transports; - PWSTR Transport; - PWINSOCK_MAPPING Mapping; - PLIST_ENTRY Helpers; - INT Status; - - AFD_DbgPrint(MID_TRACE,("Called\n")); - - /* Check in our Current Loaded Helpers */ - for (Helpers = SockHelpersListHead.Flink; - Helpers != &SockHelpersListHead; - Helpers = Helpers->Flink ) { - - HelperData = CONTAINING_RECORD(Helpers, HELPER_DATA, Helpers); - - /* See if this Mapping works for us */ - if (SockIsTripleInMapping (HelperData->Mapping, - *AddressFamily, - *SocketType, - *Protocol)) { - - /* Call the Helper Dll function get the Transport Name */ - if (HelperData->WSHOpenSocket2 == NULL ) { - - /* DLL Doesn't support WSHOpenSocket2, call the old one */ - HelperData->WSHOpenSocket(AddressFamily, - SocketType, - Protocol, - TransportName, - HelperDllContext, - Events - ); - } else { - HelperData->WSHOpenSocket2(AddressFamily, - SocketType, - Protocol, - Group, - Flags, - TransportName, - HelperDllContext, - Events - ); - } - - /* Return the Helper Pointers */ - *HelperDllData = HelperData; - return NO_ERROR; - } - } - - /* Get the Transports available */ - Status = SockLoadTransportList(&Transports); - - /* Check for error */ - if (Status) { - AFD_DbgPrint(MIN_TRACE, ("Can't get transport list\n")); - return Status; - } - - /* Loop through each transport until we find one that can satisfy us */ - for (Transport = Transports; - *Transports != 0; - Transport += wcslen(Transport) + 1) { - AFD_DbgPrint(MID_TRACE, ("Transport: %S\n", Transports)); - - /* See what mapping this Transport supports */ - Status = SockLoadTransportMapping(Transport, &Mapping); - - /* Check for error */ - if (Status) { - AFD_DbgPrint(MIN_TRACE, ("Can't get mapping\n")); - HeapFree(GlobalHeap, 0, Transports); - return Status; - } - - /* See if this Mapping works for us */ - if (SockIsTripleInMapping(Mapping, *AddressFamily, *SocketType, *Protocol)) { - - /* It does, so load the DLL associated with it */ - Status = SockLoadHelperDll(Transport, Mapping, &HelperData); - - /* Check for error */ - if (Status) { - AFD_DbgPrint(MIN_TRACE, ("Can't load helper DLL\n")); - HeapFree(GlobalHeap, 0, Transports); - HeapFree(GlobalHeap, 0, Mapping); - return Status; - } - - /* Call the Helper Dll function get the Transport Name */ - if (HelperData->WSHOpenSocket2 == NULL) { - /* DLL Doesn't support WSHOpenSocket2, call the old one */ - HelperData->WSHOpenSocket(AddressFamily, - SocketType, - Protocol, - TransportName, - HelperDllContext, - Events - ); - } else { - HelperData->WSHOpenSocket2(AddressFamily, - SocketType, - Protocol, - Group, - Flags, - TransportName, - HelperDllContext, - Events - ); - } - - /* Return the Helper Pointers */ - *HelperDllData = HelperData; - /* We actually cache these ... the can't be freed yet */ - /*HeapFree(GlobalHeap, 0, Transports);*/ - /*HeapFree(GlobalHeap, 0, Mapping);*/ - return NO_ERROR; - } - - HeapFree(GlobalHeap, 0, Mapping); - } - HeapFree(GlobalHeap, 0, Transports); - return WSAEINVAL; -} - -INT -SockLoadTransportMapping( - PWSTR TransportName, - PWINSOCK_MAPPING *Mapping) -{ - PWSTR TransportKey; - HKEY KeyHandle; - ULONG MappingSize; - LONG Status; - - AFD_DbgPrint(MID_TRACE,("Called: TransportName %ws\n", TransportName)); - - /* Allocate a Buffer */ - TransportKey = HeapAlloc(GlobalHeap, 0, (54 + wcslen(TransportName)) * sizeof(WCHAR)); - - /* Check for error */ - if (TransportKey == NULL) { - AFD_DbgPrint(MIN_TRACE, ("Buffer allocation failed\n")); - return WSAEINVAL; - } - - /* Generate the right key name */ - wcscpy(TransportKey, L"System\\CurrentControlSet\\Services\\"); - wcscat(TransportKey, TransportName); - wcscat(TransportKey, L"\\Parameters\\Winsock"); - - /* Open the Key */ - Status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, TransportKey, 0, KEY_READ, &KeyHandle); - - /* We don't need the Transport Key anymore */ - HeapFree(GlobalHeap, 0, TransportKey); - - /* Check for error */ - if (Status) { - AFD_DbgPrint(MIN_TRACE, ("Error reading transport mapping registry\n")); - return WSAEINVAL; - } - - /* Find out how much space we need for the Mapping */ - Status = RegQueryValueExW(KeyHandle, L"Mapping", NULL, NULL, NULL, &MappingSize); - - /* Check for error */ - if (Status) { - AFD_DbgPrint(MIN_TRACE, ("Error reading transport mapping registry\n")); - return WSAEINVAL; - } - - /* Allocate Memory for the Mapping */ - *Mapping = HeapAlloc(GlobalHeap, 0, MappingSize); - - /* Check for error */ - if (*Mapping == NULL) { - AFD_DbgPrint(MIN_TRACE, ("Buffer allocation failed\n")); - return WSAEINVAL; - } - - /* Read the Mapping */ - Status = RegQueryValueExW(KeyHandle, L"Mapping", NULL, NULL, (LPBYTE)*Mapping, &MappingSize); - - /* Check for error */ - if (Status) { - AFD_DbgPrint(MIN_TRACE, ("Error reading transport mapping registry\n")); - HeapFree(GlobalHeap, 0, *Mapping); - return WSAEINVAL; - } - - /* Close key and return */ - RegCloseKey(KeyHandle); - return 0; -} - -INT -SockLoadTransportList( - PWSTR *TransportList) -{ - ULONG TransportListSize; - HKEY KeyHandle; - LONG Status; - - AFD_DbgPrint(MID_TRACE,("Called\n")); - - /* Open the Transports Key */ - Status = RegOpenKeyExW (HKEY_LOCAL_MACHINE, - L"SYSTEM\\CurrentControlSet\\Services\\Winsock\\Parameters", - 0, - KEY_READ, - &KeyHandle); - - /* Check for error */ - if (Status) { - AFD_DbgPrint(MIN_TRACE, ("Error reading transport list registry\n")); - return WSAEINVAL; - } - - /* Get the Transport List Size */ - Status = RegQueryValueExW(KeyHandle, - L"Transports", - NULL, - NULL, - NULL, - &TransportListSize); - - /* Check for error */ - if (Status) { - AFD_DbgPrint(MIN_TRACE, ("Error reading transport list registry\n")); - return WSAEINVAL; - } - - /* Allocate Memory for the Transport List */ - *TransportList = HeapAlloc(GlobalHeap, 0, TransportListSize); - - /* Check for error */ - if (*TransportList == NULL) { - AFD_DbgPrint(MIN_TRACE, ("Buffer allocation failed\n")); - return WSAEINVAL; - } - - /* Get the Transports */ - Status = RegQueryValueExW (KeyHandle, - L"Transports", - NULL, - NULL, - (LPBYTE)*TransportList, - &TransportListSize); - - /* Check for error */ - if (Status) { - AFD_DbgPrint(MIN_TRACE, ("Error reading transport list registry\n")); - HeapFree(GlobalHeap, 0, *TransportList); - return WSAEINVAL; - } - - /* Close key and return */ - RegCloseKey(KeyHandle); - return 0; -} - -INT -SockLoadHelperDll( - PWSTR TransportName, - PWINSOCK_MAPPING Mapping, - PHELPER_DATA *HelperDllData) -{ - PHELPER_DATA HelperData; - PWSTR HelperDllName; - PWSTR FullHelperDllName; - ULONG HelperDllNameSize; - PWSTR HelperKey; - HKEY KeyHandle; - ULONG DataSize; - LONG Status; - - /* Allocate space for the Helper Structure and TransportName */ - HelperData = HeapAlloc(GlobalHeap, 0, sizeof(*HelperData) + (wcslen(TransportName) + 1) * sizeof(WCHAR)); - - /* Check for error */ - if (HelperData == NULL) { - AFD_DbgPrint(MIN_TRACE, ("Buffer allocation failed\n")); - return WSAEINVAL; - } - - /* Allocate Space for the Helper DLL Key */ - HelperKey = HeapAlloc(GlobalHeap, 0, (54 + wcslen(TransportName)) * sizeof(WCHAR)); - - /* Check for error */ - if (HelperKey == NULL) { - AFD_DbgPrint(MIN_TRACE, ("Buffer allocation failed\n")); - HeapFree(GlobalHeap, 0, HelperData); - return WSAEINVAL; - } - - /* Generate the right key name */ - wcscpy(HelperKey, L"System\\CurrentControlSet\\Services\\"); - wcscat(HelperKey, TransportName); - wcscat(HelperKey, L"\\Parameters\\Winsock"); - - /* Open the Key */ - Status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, HelperKey, 0, KEY_READ, &KeyHandle); - - HeapFree(GlobalHeap, 0, HelperKey); - - /* Check for error */ - if (Status) { - AFD_DbgPrint(MIN_TRACE, ("Error reading helper DLL parameters\n")); - HeapFree(GlobalHeap, 0, HelperData); - return WSAEINVAL; - } - - /* Read Size of SockAddr Structures */ - DataSize = sizeof(HelperData->MinWSAddressLength); - HelperData->MinWSAddressLength = 16; - RegQueryValueExW (KeyHandle, - L"MinSockaddrLength", - NULL, - NULL, - (LPBYTE)&HelperData->MinWSAddressLength, - &DataSize); - DataSize = sizeof(HelperData->MinWSAddressLength); - HelperData->MaxWSAddressLength = 16; - RegQueryValueExW (KeyHandle, - L"MaxSockaddrLength", - NULL, - NULL, - (LPBYTE)&HelperData->MaxWSAddressLength, - &DataSize); - - /* Size of TDI Structures */ - HelperData->MinTDIAddressLength = HelperData->MinWSAddressLength + 6; - HelperData->MaxTDIAddressLength = HelperData->MaxWSAddressLength + 6; - - /* Read Delayed Acceptance Setting */ - DataSize = sizeof(DWORD); - HelperData->UseDelayedAcceptance = FALSE; - RegQueryValueExW (KeyHandle, - L"UseDelayedAcceptance", - NULL, - NULL, - (LPBYTE)&HelperData->UseDelayedAcceptance, - &DataSize); - - /* Allocate Space for the Helper DLL Names */ - HelperDllName = HeapAlloc(GlobalHeap, 0, 512); - - /* Check for error */ - if (HelperDllName == NULL) { - AFD_DbgPrint(MIN_TRACE, ("Buffer allocation failed\n")); - HeapFree(GlobalHeap, 0, HelperData); - return WSAEINVAL; - } - - FullHelperDllName = HeapAlloc(GlobalHeap, 0, 512); - - /* Check for error */ - if (FullHelperDllName == NULL) { - AFD_DbgPrint(MIN_TRACE, ("Buffer allocation failed\n")); - HeapFree(GlobalHeap, 0, HelperDllName); - HeapFree(GlobalHeap, 0, HelperData); - return WSAEINVAL; - } - - /* Get the name of the Helper DLL*/ - DataSize = 512; - Status = RegQueryValueExW (KeyHandle, - L"HelperDllName", - NULL, - NULL, - (LPBYTE)HelperDllName, - &DataSize); - - /* Check for error */ - if (Status) { - AFD_DbgPrint(MIN_TRACE, ("Error reading helper DLL parameters\n")); - HeapFree(GlobalHeap, 0, FullHelperDllName); - HeapFree(GlobalHeap, 0, HelperDllName); - HeapFree(GlobalHeap, 0, HelperData); - return WSAEINVAL; - } - - /* Get the Full name, expanding Environment Strings */ - HelperDllNameSize = ExpandEnvironmentStringsW (HelperDllName, - FullHelperDllName, - 256); - - /* Load the DLL */ - HelperData->hInstance = LoadLibraryW(FullHelperDllName); - - HeapFree(GlobalHeap, 0, HelperDllName); - HeapFree(GlobalHeap, 0, FullHelperDllName); - - if (HelperData->hInstance == NULL) { - AFD_DbgPrint(MIN_TRACE, ("Error loading helper DLL\n")); - HeapFree(GlobalHeap, 0, HelperData); - return WSAEINVAL; - } - - /* Close Key */ - RegCloseKey(KeyHandle); - - /* Get the Pointers to the Helper Routines */ - HelperData->WSHOpenSocket = (PWSH_OPEN_SOCKET) - GetProcAddress(HelperData->hInstance, - "WSHOpenSocket"); - HelperData->WSHOpenSocket2 = (PWSH_OPEN_SOCKET2) - GetProcAddress(HelperData->hInstance, - "WSHOpenSocket2"); - HelperData->WSHJoinLeaf = (PWSH_JOIN_LEAF) - GetProcAddress(HelperData->hInstance, - "WSHJoinLeaf"); - HelperData->WSHNotify = (PWSH_NOTIFY) - GetProcAddress(HelperData->hInstance, "WSHNotify"); - HelperData->WSHGetSocketInformation = (PWSH_GET_SOCKET_INFORMATION) - GetProcAddress(HelperData->hInstance, - "WSHGetSocketInformation"); - HelperData->WSHSetSocketInformation = (PWSH_SET_SOCKET_INFORMATION) - GetProcAddress(HelperData->hInstance, - "WSHSetSocketInformation"); - HelperData->WSHGetSockaddrType = (PWSH_GET_SOCKADDR_TYPE) - GetProcAddress(HelperData->hInstance, - "WSHGetSockaddrType"); - HelperData->WSHGetWildcardSockaddr = (PWSH_GET_WILDCARD_SOCKADDR) - GetProcAddress(HelperData->hInstance, - "WSHGetWildcardSockaddr"); - HelperData->WSHGetBroadcastSockaddr = (PWSH_GET_BROADCAST_SOCKADDR) - GetProcAddress(HelperData->hInstance, - "WSHGetBroadcastSockaddr"); - HelperData->WSHAddressToString = (PWSH_ADDRESS_TO_STRING) - GetProcAddress(HelperData->hInstance, - "WSHAddressToString"); - HelperData->WSHStringToAddress = (PWSH_STRING_TO_ADDRESS) - GetProcAddress(HelperData->hInstance, - "WSHStringToAddress"); - HelperData->WSHIoctl = (PWSH_IOCTL) - GetProcAddress(HelperData->hInstance, - "WSHIoctl"); - - /* Save the Mapping Structure and transport name */ - HelperData->Mapping = Mapping; - wcscpy(HelperData->TransportName, TransportName); - - /* Increment Reference Count */ - HelperData->RefCount = 1; - - /* Add it to our list */ - InsertHeadList(&SockHelpersListHead, &HelperData->Helpers); - - /* Return Pointers */ - *HelperDllData = HelperData; - return 0; -} - -BOOL -SockIsTripleInMapping( - PWINSOCK_MAPPING Mapping, - INT AddressFamily, - INT SocketType, - INT Protocol) -{ - /* The Windows version returns more detailed information on which of the 3 parameters failed...we should do this later */ - ULONG Row; - - AFD_DbgPrint(MID_TRACE,("Called, Mapping rows = %d\n", Mapping->Rows)); - - /* Loop through Mapping to Find a matching one */ - for (Row = 0; Row < Mapping->Rows; Row++) { - AFD_DbgPrint(MID_TRACE,("Examining: row %d: AF %d type %d proto %d\n", - Row, - (INT)Mapping->Mapping[Row].AddressFamily, - (INT)Mapping->Mapping[Row].SocketType, - (INT)Mapping->Mapping[Row].Protocol)); - - /* Check of all three values Match */ - if (((INT)Mapping->Mapping[Row].AddressFamily == AddressFamily) && - ((INT)Mapping->Mapping[Row].SocketType == SocketType) && - ((INT)Mapping->Mapping[Row].Protocol == Protocol)) { - AFD_DbgPrint(MID_TRACE,("Found\n")); - return TRUE; - } - } - AFD_DbgPrint(MID_TRACE,("Not found\n")); - return FALSE; -} - -/* EOF */ diff --git a/dll/win32/msafd/misc/sndrcv.c b/dll/win32/msafd/misc/sndrcv.c deleted file mode 100644 index 212b4fc25ca..00000000000 --- a/dll/win32/msafd/misc/sndrcv.c +++ /dev/null @@ -1,671 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Ancillary Function Driver DLL - * FILE: misc/sndrcv.c - * PURPOSE: Send/receive routines - * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) - * Alex Ionescu (alex@relsoft.net) - * REVISIONS: - * CSH 01/09-2000 Created - * Alex 16/07/2004 - Complete Rewrite - */ - -#include - -#include - -INT -WSPAPI -WSPAsyncSelect(IN SOCKET Handle, - IN HWND hWnd, - IN UINT wMsg, - IN LONG lEvent, - OUT LPINT lpErrno) -{ - PSOCKET_INFORMATION Socket = NULL; - PASYNC_DATA AsyncData; - NTSTATUS Status; - ULONG BlockMode; - - /* Get the Socket Structure associated to this Socket */ - Socket = GetSocketStructure(Handle); - - /* Allocate the Async Data Structure to pass on to the Thread later */ - AsyncData = HeapAlloc(GetProcessHeap(), 0, sizeof(*AsyncData)); - if (!AsyncData) - { - MsafdReturnWithErrno( STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL ); - return INVALID_SOCKET; - } - - /* Change the Socket to Non Blocking */ - BlockMode = 1; - SetSocketInformation(Socket, AFD_INFO_BLOCKING_MODE, &BlockMode, NULL); - Socket->SharedData.NonBlocking = TRUE; - - /* Deactive WSPEventSelect */ - if (Socket->SharedData.AsyncEvents) - { - WSPEventSelect(Handle, NULL, 0, NULL); - } - - /* Create the Asynch Thread if Needed */ - SockCreateOrReferenceAsyncThread(); - - /* Open a Handle to AFD's Async Helper */ - SockGetAsyncSelectHelperAfdHandle(); - - /* Store Socket Data */ - Socket->SharedData.hWnd = hWnd; - Socket->SharedData.wMsg = wMsg; - Socket->SharedData.AsyncEvents = lEvent; - Socket->SharedData.AsyncDisabledEvents = 0; - Socket->SharedData.SequenceNumber++; - - /* Return if there are no more Events */ - if ((Socket->SharedData.AsyncEvents & (~Socket->SharedData.AsyncDisabledEvents)) == 0) - { - HeapFree(GetProcessHeap(), 0, AsyncData); - return 0; - } - - /* Set up the Async Data */ - AsyncData->ParentSocket = Socket; - AsyncData->SequenceNumber = Socket->SharedData.SequenceNumber; - - /* Begin Async Select by using I/O Completion */ - Status = NtSetIoCompletion(SockAsyncCompletionPort, - (PVOID)&SockProcessQueuedAsyncSelect, - AsyncData, - 0, - 0); - - /* Return */ - return ERROR_SUCCESS; -} - - -int -WSPAPI -WSPRecv(SOCKET Handle, - LPWSABUF lpBuffers, - DWORD dwBufferCount, - LPDWORD lpNumberOfBytesRead, - LPDWORD ReceiveFlags, - LPWSAOVERLAPPED lpOverlapped, - LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, - LPWSATHREADID lpThreadId, - LPINT lpErrno) -{ - PIO_STATUS_BLOCK IOSB; - IO_STATUS_BLOCK DummyIOSB; - AFD_RECV_INFO RecvInfo; - NTSTATUS Status; - PVOID APCContext; - PVOID APCFunction; - HANDLE Event = NULL; - HANDLE SockEvent; - PSOCKET_INFORMATION Socket; - - AFD_DbgPrint(MID_TRACE,("Called (%x)\n", Handle)); - - /* Get the Socket Structure associate to this Socket*/ - Socket = GetSocketStructure(Handle); - - Status = NtCreateEvent( &SockEvent, GENERIC_READ | GENERIC_WRITE, - NULL, 1, FALSE ); - - if( !NT_SUCCESS(Status) ) - return -1; - - /* Set up the Receive Structure */ - RecvInfo.BufferArray = (PAFD_WSABUF)lpBuffers; - RecvInfo.BufferCount = dwBufferCount; - RecvInfo.TdiFlags = 0; - RecvInfo.AfdFlags = Socket->SharedData.NonBlocking ? AFD_IMMEDIATE : 0; - - /* Set the TDI Flags */ - if (*ReceiveFlags == 0) - { - RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL; - } - else - { - if (*ReceiveFlags & MSG_OOB) - { - RecvInfo.TdiFlags |= TDI_RECEIVE_EXPEDITED; - } - - if (*ReceiveFlags & MSG_PEEK) - { - RecvInfo.TdiFlags |= TDI_RECEIVE_PEEK; - } - - if (*ReceiveFlags & MSG_PARTIAL) - { - RecvInfo.TdiFlags |= TDI_RECEIVE_PARTIAL; - } - } - - /* Verifiy if we should use APC */ - - if (lpOverlapped == NULL) - { - /* Not using Overlapped structure, so use normal blocking on event */ - APCContext = NULL; - APCFunction = NULL; - Event = SockEvent; - IOSB = &DummyIOSB; - } - else - { - if (lpCompletionRoutine == NULL) - { - /* Using Overlapped Structure, but no Completition Routine, so no need for APC */ - APCContext = lpOverlapped; - APCFunction = NULL; - Event = lpOverlapped->hEvent; - } - else - { - /* Using Overlapped Structure and a Completition Routine, so use an APC */ - APCFunction = NULL; // should be a private io completition function inside us - APCContext = lpCompletionRoutine; - RecvInfo.AfdFlags |= AFD_SKIP_FIO; - } - - IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; - RecvInfo.AfdFlags |= AFD_OVERLAPPED; - } - - IOSB->Status = STATUS_PENDING; - - /* Send IOCTL */ - Status = NtDeviceIoControlFile((HANDLE)Handle, - Event ? Event : SockEvent, - APCFunction, - APCContext, - IOSB, - IOCTL_AFD_RECV, - &RecvInfo, - sizeof(RecvInfo), - NULL, - 0); - - /* Wait for completition of not overlapped */ - if (Status == STATUS_PENDING && lpOverlapped == NULL) - { - /* It's up to the protocol to time out recv. We must wait - * until the protocol decides it's had enough. - */ - WaitForSingleObject(SockEvent, INFINITE); - Status = IOSB->Status; - } - - NtClose( SockEvent ); - - AFD_DbgPrint(MID_TRACE,("Status %x Information %d\n", Status, IOSB->Information)); - - /* Return the Flags */ - *ReceiveFlags = 0; - - switch (Status) - { - case STATUS_RECEIVE_EXPEDITED: - *ReceiveFlags = MSG_OOB; - break; - case STATUS_RECEIVE_PARTIAL_EXPEDITED: - *ReceiveFlags = MSG_PARTIAL | MSG_OOB; - break; - case STATUS_RECEIVE_PARTIAL: - *ReceiveFlags = MSG_PARTIAL; - break; - } - - /* Re-enable Async Event */ - if (*ReceiveFlags == MSG_OOB) - { - SockReenableAsyncSelectEvent(Socket, FD_OOB); - } - else - { - SockReenableAsyncSelectEvent(Socket, FD_READ); - } - - return MsafdReturnWithErrno ( Status, lpErrno, IOSB->Information, lpNumberOfBytesRead ); -} - -int -WSPAPI -WSPRecvFrom(SOCKET Handle, - LPWSABUF lpBuffers, - DWORD dwBufferCount, - LPDWORD lpNumberOfBytesRead, - LPDWORD ReceiveFlags, - struct sockaddr *SocketAddress, - int *SocketAddressLength, - LPWSAOVERLAPPED lpOverlapped, - LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, - LPWSATHREADID lpThreadId, - LPINT lpErrno ) -{ - PIO_STATUS_BLOCK IOSB; - IO_STATUS_BLOCK DummyIOSB; - AFD_RECV_INFO_UDP RecvInfo; - NTSTATUS Status; - PVOID APCContext; - PVOID APCFunction; - HANDLE Event = NULL; - HANDLE SockEvent; - PSOCKET_INFORMATION Socket; - - /* Get the Socket Structure associate to this Socket*/ - Socket = GetSocketStructure(Handle); - - Status = NtCreateEvent( &SockEvent, GENERIC_READ | GENERIC_WRITE, - NULL, 1, FALSE ); - - if( !NT_SUCCESS(Status) ) - return -1; - - /* Set up the Receive Structure */ - RecvInfo.BufferArray = (PAFD_WSABUF)lpBuffers; - RecvInfo.BufferCount = dwBufferCount; - RecvInfo.TdiFlags = 0; - RecvInfo.AfdFlags = Socket->SharedData.NonBlocking ? AFD_IMMEDIATE : 0; - RecvInfo.AddressLength = SocketAddressLength; - RecvInfo.Address = SocketAddress; - - /* Set the TDI Flags */ - if (*ReceiveFlags == 0) - { - RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL; - } - else - { - if (*ReceiveFlags & MSG_OOB) - { - RecvInfo.TdiFlags |= TDI_RECEIVE_EXPEDITED; - } - - if (*ReceiveFlags & MSG_PEEK) - { - RecvInfo.TdiFlags |= TDI_RECEIVE_PEEK; - } - - if (*ReceiveFlags & MSG_PARTIAL) - { - RecvInfo.TdiFlags |= TDI_RECEIVE_PARTIAL; - } - } - - /* Verifiy if we should use APC */ - - if (lpOverlapped == NULL) - { - /* Not using Overlapped structure, so use normal blocking on event */ - APCContext = NULL; - APCFunction = NULL; - Event = SockEvent; - IOSB = &DummyIOSB; - } - else - { - if (lpCompletionRoutine == NULL) - { - /* Using Overlapped Structure, but no Completition Routine, so no need for APC */ - APCContext = lpOverlapped; - APCFunction = NULL; - Event = lpOverlapped->hEvent; - } - else - { - /* Using Overlapped Structure and a Completition Routine, so use an APC */ - APCFunction = NULL; // should be a private io completition function inside us - APCContext = lpCompletionRoutine; - RecvInfo.AfdFlags |= AFD_SKIP_FIO; - } - - IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; - RecvInfo.AfdFlags |= AFD_OVERLAPPED; - } - - IOSB->Status = STATUS_PENDING; - - /* Send IOCTL */ - Status = NtDeviceIoControlFile((HANDLE)Handle, - Event ? Event : SockEvent, - APCFunction, - APCContext, - IOSB, - IOCTL_AFD_RECV_DATAGRAM, - &RecvInfo, - sizeof(RecvInfo), - NULL, - 0); - - /* Wait for completition of not overlapped */ - if (Status == STATUS_PENDING && lpOverlapped == NULL) - { - WaitForSingleObject(SockEvent, INFINITE); // BUGBUG, shouldn wait infintely for receive... - Status = IOSB->Status; - } - - NtClose( SockEvent ); - - /* Return the Flags */ - *ReceiveFlags = 0; - - switch (Status) - { - case STATUS_RECEIVE_EXPEDITED: *ReceiveFlags = MSG_OOB; - break; - case STATUS_RECEIVE_PARTIAL_EXPEDITED: - *ReceiveFlags = MSG_PARTIAL | MSG_OOB; - break; - case STATUS_RECEIVE_PARTIAL: - *ReceiveFlags = MSG_PARTIAL; - break; - } - - /* Re-enable Async Event */ - SockReenableAsyncSelectEvent(Socket, FD_READ); - - return MsafdReturnWithErrno ( Status, lpErrno, IOSB->Information, lpNumberOfBytesRead ); -} - - -int -WSPAPI -WSPSend(SOCKET Handle, - LPWSABUF lpBuffers, - DWORD dwBufferCount, - LPDWORD lpNumberOfBytesSent, - DWORD iFlags, - LPWSAOVERLAPPED lpOverlapped, - LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, - LPWSATHREADID lpThreadId, - LPINT lpErrno) -{ - PIO_STATUS_BLOCK IOSB; - IO_STATUS_BLOCK DummyIOSB; - AFD_SEND_INFO SendInfo; - NTSTATUS Status; - PVOID APCContext; - PVOID APCFunction; - HANDLE Event = NULL; - HANDLE SockEvent; - PSOCKET_INFORMATION Socket; - - /* Get the Socket Structure associate to this Socket*/ - Socket = GetSocketStructure(Handle); - - Status = NtCreateEvent( &SockEvent, GENERIC_READ | GENERIC_WRITE, - NULL, 1, FALSE ); - - if( !NT_SUCCESS(Status) ) - return -1; - - AFD_DbgPrint(MID_TRACE,("Called\n")); - - /* Set up the Send Structure */ - SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers; - SendInfo.BufferCount = dwBufferCount; - SendInfo.TdiFlags = 0; - SendInfo.AfdFlags = Socket->SharedData.NonBlocking ? AFD_IMMEDIATE : 0; - - /* Set the TDI Flags */ - if (iFlags) - { - if (iFlags & MSG_OOB) - { - SendInfo.TdiFlags |= TDI_SEND_EXPEDITED; - } - if (iFlags & MSG_PARTIAL) - { - SendInfo.TdiFlags |= TDI_SEND_PARTIAL; - } - } - - /* Verifiy if we should use APC */ - if (lpOverlapped == NULL) - { - /* Not using Overlapped structure, so use normal blocking on event */ - APCContext = NULL; - APCFunction = NULL; - Event = SockEvent; - IOSB = &DummyIOSB; - } - else - { - if (lpCompletionRoutine == NULL) - { - /* Using Overlapped Structure, but no Completition Routine, so no need for APC */ - APCContext = lpOverlapped; - APCFunction = NULL; - Event = lpOverlapped->hEvent; - } - else - { - /* Using Overlapped Structure and a Completition Routine, so use an APC */ - APCFunction = NULL; // should be a private io completition function inside us - APCContext = lpCompletionRoutine; - SendInfo.AfdFlags |= AFD_SKIP_FIO; - } - - IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; - SendInfo.AfdFlags |= AFD_OVERLAPPED; - } - - IOSB->Status = STATUS_PENDING; - - /* Send IOCTL */ - Status = NtDeviceIoControlFile((HANDLE)Handle, - Event ? Event : SockEvent, - APCFunction, - APCContext, - IOSB, - IOCTL_AFD_SEND, - &SendInfo, - sizeof(SendInfo), - NULL, - 0); - - /* Wait for completition of not overlapped */ - if (Status == STATUS_PENDING && lpOverlapped == NULL) - { - WaitForSingleObject(SockEvent, INFINITE); // BUGBUG, shouldn wait infintely for send... - Status = IOSB->Status; - } - - NtClose( SockEvent ); - - if (Status == STATUS_PENDING) - { - AFD_DbgPrint(MID_TRACE,("Leaving (Pending)\n")); - return WSA_IO_PENDING; - } - - /* Re-enable Async Event */ - SockReenableAsyncSelectEvent(Socket, FD_WRITE); - - AFD_DbgPrint(MID_TRACE,("Leaving (Success, %d)\n", IOSB->Information)); - - return MsafdReturnWithErrno( Status, lpErrno, IOSB->Information, lpNumberOfBytesSent ); -} - -int -WSPAPI -WSPSendTo(SOCKET Handle, - LPWSABUF lpBuffers, - DWORD dwBufferCount, - LPDWORD lpNumberOfBytesSent, - DWORD iFlags, - const struct sockaddr *SocketAddress, - int SocketAddressLength, - LPWSAOVERLAPPED lpOverlapped, - LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, - LPWSATHREADID lpThreadId, - LPINT lpErrno) -{ - PIO_STATUS_BLOCK IOSB; - IO_STATUS_BLOCK DummyIOSB; - AFD_SEND_INFO_UDP SendInfo; - NTSTATUS Status; - PVOID APCContext; - PVOID APCFunction; - HANDLE Event = NULL; - PTRANSPORT_ADDRESS RemoteAddress; - PSOCKADDR BindAddress = NULL; - INT BindAddressLength; - HANDLE SockEvent; - PSOCKET_INFORMATION Socket; - - /* Get the Socket Structure associate to this Socket */ - Socket = GetSocketStructure(Handle); - - /* Bind us First */ - if (Socket->SharedData.State == SocketOpen) - { - /* Get the Wildcard Address */ - BindAddressLength = Socket->HelperData->MaxWSAddressLength; - BindAddress = HeapAlloc(GlobalHeap, 0, BindAddressLength); - if (!BindAddress) - { - MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL); - return INVALID_SOCKET; - } - - Socket->HelperData->WSHGetWildcardSockaddr(Socket->HelperContext, - BindAddress, - &BindAddressLength); - /* Bind it */ - WSPBind(Handle, BindAddress, BindAddressLength, NULL); - } - - RemoteAddress = HeapAlloc(GlobalHeap, 0, 0x6 + SocketAddressLength); - if (!RemoteAddress) - { - if (BindAddress != NULL) - { - HeapFree(GlobalHeap, 0, BindAddress); - } - return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL); - } - - Status = NtCreateEvent(&SockEvent, - GENERIC_READ | GENERIC_WRITE, - NULL, 1, FALSE); - - if (!NT_SUCCESS(Status)) - { - HeapFree(GlobalHeap, 0, RemoteAddress); - if (BindAddress != NULL) - { - HeapFree(GlobalHeap, 0, BindAddress); - } - return SOCKET_ERROR; - } - - /* Set up Address in TDI Format */ - RemoteAddress->TAAddressCount = 1; - RemoteAddress->Address[0].AddressLength = SocketAddressLength - sizeof(SocketAddress->sa_family); - RtlCopyMemory(&RemoteAddress->Address[0].AddressType, SocketAddress, SocketAddressLength); - - /* Set up Structure */ - SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers; - SendInfo.AfdFlags = Socket->SharedData.NonBlocking ? AFD_IMMEDIATE : 0; - SendInfo.BufferCount = dwBufferCount; - SendInfo.TdiConnection.RemoteAddress = RemoteAddress; - SendInfo.TdiConnection.RemoteAddressLength = Socket->HelperData->MaxTDIAddressLength; - - /* Verifiy if we should use APC */ - if (lpOverlapped == NULL) - { - /* Not using Overlapped structure, so use normal blocking on event */ - APCContext = NULL; - APCFunction = NULL; - Event = SockEvent; - IOSB = &DummyIOSB; - } - else - { - if (lpCompletionRoutine == NULL) - { - /* Using Overlapped Structure, but no Completition Routine, so no need for APC */ - APCContext = lpOverlapped; - APCFunction = NULL; - Event = lpOverlapped->hEvent; - } - else - { - /* Using Overlapped Structure and a Completition Routine, so use an APC */ - /* Should be a private io completition function inside us */ - APCFunction = NULL; - APCContext = lpCompletionRoutine; - SendInfo.AfdFlags |= AFD_SKIP_FIO; - } - - IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal; - SendInfo.AfdFlags |= AFD_OVERLAPPED; - } - - /* Send IOCTL */ - Status = NtDeviceIoControlFile((HANDLE)Handle, - Event ? Event : SockEvent, - APCFunction, - APCContext, - IOSB, - IOCTL_AFD_SEND_DATAGRAM, - &SendInfo, - sizeof(SendInfo), - NULL, - 0); - - /* Wait for completition of not overlapped */ - if (Status == STATUS_PENDING && lpOverlapped == NULL) - { - /* BUGBUG, shouldn't wait infintely for send... */ - WaitForSingleObject(SockEvent, INFINITE); - Status = IOSB->Status; - } - - NtClose(SockEvent); - HeapFree(GlobalHeap, 0, RemoteAddress); - if (BindAddress != NULL) - { - HeapFree(GlobalHeap, 0, BindAddress); - } - - if (Status == STATUS_PENDING) - return WSA_IO_PENDING; - - /* Re-enable Async Event */ - SockReenableAsyncSelectEvent(Socket, FD_WRITE); - - return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesSent); -} - -INT -WSPAPI -WSPRecvDisconnect(IN SOCKET s, - OUT LPWSABUF lpInboundDisconnectData, - OUT LPINT lpErrno) -{ - UNIMPLEMENTED - return 0; -} - - - -INT -WSPAPI -WSPSendDisconnect(IN SOCKET s, - IN LPWSABUF lpOutboundDisconnectData, - OUT LPINT lpErrno) -{ - UNIMPLEMENTED - return 0; -} - -/* EOF */ diff --git a/dll/win32/msafd/misc/stubs.c b/dll/win32/msafd/misc/stubs.c deleted file mode 100644 index 5a9da712616..00000000000 --- a/dll/win32/msafd/misc/stubs.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Ancillary Function Driver DLL - * FILE: misc/stubs.c - * PURPOSE: Stubs - * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) - * REVISIONS: - * CSH 01/09-2000 Created - */ -#include - -#include - -INT -WSPAPI -WSPAddressToString( - IN LPSOCKADDR lpsaAddress, - IN DWORD dwAddressLength, - IN LPWSAPROTOCOL_INFOW lpProtocolInfo, - OUT LPWSTR lpszAddressString, - IN OUT LPDWORD lpdwAddressStringLength, - OUT LPINT lpErrno) -{ - UNIMPLEMENTED - - return 0; -} - - -INT -WSPAPI -WSPCancelBlockingCall( - OUT LPINT lpErrno) -{ - UNIMPLEMENTED - - return 0; -} - - -INT -WSPAPI -WSPDuplicateSocket( - IN SOCKET s, - IN DWORD dwProcessId, - OUT LPWSAPROTOCOL_INFOW lpProtocolInfo, - OUT LPINT lpErrno) -{ - UNIMPLEMENTED - - return 0; -} - - -BOOL -WSPAPI -WSPGetOverlappedResult( - IN SOCKET s, - IN LPWSAOVERLAPPED lpOverlapped, - OUT LPDWORD lpcbTransfer, - IN BOOL fWait, - OUT LPDWORD lpdwFlags, - OUT LPINT lpErrno) -{ - UNIMPLEMENTED - - return FALSE; -} - - -BOOL -WSPAPI -WSPGetQOSByName( - IN SOCKET s, - IN OUT LPWSABUF lpQOSName, - OUT LPQOS lpQOS, - OUT LPINT lpErrno) -{ - UNIMPLEMENTED - - return FALSE; -} - - -SOCKET -WSPAPI -WSPJoinLeaf( - IN SOCKET s, - IN CONST SOCKADDR *name, - IN INT namelen, - IN LPWSABUF lpCallerData, - OUT LPWSABUF lpCalleeData, - IN LPQOS lpSQOS, - IN LPQOS lpGQOS, - IN DWORD dwFlags, - OUT LPINT lpErrno) -{ - UNIMPLEMENTED - - return (SOCKET)0; -} - -INT -WSPAPI -WSPStringToAddress( - IN LPWSTR AddressString, - IN INT AddressFamily, - IN LPWSAPROTOCOL_INFOW lpProtocolInfo, - OUT LPSOCKADDR lpAddress, - IN OUT LPINT lpAddressLength, - OUT LPINT lpErrno) -{ - UNIMPLEMENTED - - return 0; -} - -/* EOF */ diff --git a/dll/win32/msafd/msafd.h b/dll/win32/msafd/msafd.h deleted file mode 100755 index fbef176ab47..00000000000 --- a/dll/win32/msafd/msafd.h +++ /dev/null @@ -1,475 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS Ancillary Function Driver DLL - * FILE: include/msafd.h - * PURPOSE: Ancillary Function Driver DLL header - */ -#ifndef __MSAFD_H -#define __MSAFD_H - -#include -#include - -#define WIN32_NO_STATUS -#include -#include -#include -#define NTOS_MODE_USER -#include - -/* This includes ntsecapi.h so it needs to come after the NDK */ -#include -#include -#include -#include - -extern HANDLE GlobalHeap; -extern WSPUPCALLTABLE Upcalls; -extern LPWPUCOMPLETEOVERLAPPEDREQUEST lpWPUCompleteOverlappedRequest; -extern LIST_ENTRY SockHelpersListHead; -extern HANDLE SockEvent; -extern HANDLE SockAsyncCompletionPort; -extern BOOLEAN SockAsyncSelectCalled; - -typedef enum _SOCKET_STATE { - SocketOpen, - SocketBound, - SocketBoundUdp, - SocketConnected, - SocketClosed -} SOCKET_STATE, *PSOCKET_STATE; - -typedef struct _SOCK_SHARED_INFO { - SOCKET_STATE State; - INT AddressFamily; - INT SocketType; - INT Protocol; - INT SizeOfLocalAddress; - INT SizeOfRemoteAddress; - struct linger LingerData; - ULONG SendTimeout; - ULONG RecvTimeout; - ULONG SizeOfRecvBuffer; - ULONG SizeOfSendBuffer; - struct { - BOOLEAN Listening:1; - BOOLEAN Broadcast:1; - BOOLEAN Debug:1; - BOOLEAN OobInline:1; - BOOLEAN ReuseAddresses:1; - BOOLEAN ExclusiveAddressUse:1; - BOOLEAN NonBlocking:1; - BOOLEAN DontUseWildcard:1; - BOOLEAN ReceiveShutdown:1; - BOOLEAN SendShutdown:1; - BOOLEAN UseDelayedAcceptance:1; - BOOLEAN UseSAN:1; - }; // Flags - DWORD CreateFlags; - DWORD CatalogEntryId; - DWORD ServiceFlags1; - DWORD ProviderFlags; - GROUP GroupID; - DWORD GroupType; - INT GroupPriority; - INT SocketLastError; - HWND hWnd; - LONG Unknown; - DWORD SequenceNumber; - UINT wMsg; - LONG AsyncEvents; - LONG AsyncDisabledEvents; -} SOCK_SHARED_INFO, *PSOCK_SHARED_INFO; - -typedef struct _SOCKET_INFORMATION { - ULONG RefCount; - SOCKET Handle; - SOCK_SHARED_INFO SharedData; - DWORD HelperEvents; - PHELPER_DATA HelperData; - PVOID HelperContext; - PSOCKADDR LocalAddress; - PSOCKADDR RemoteAddress; - HANDLE TdiAddressHandle; - HANDLE TdiConnectionHandle; - PVOID AsyncData; - HANDLE EventObject; - LONG NetworkEvents; - CRITICAL_SECTION Lock; - PVOID SanData; - BOOL TrySAN; - SOCKADDR WSLocalAddress; - SOCKADDR WSRemoteAddress; -} SOCKET_INFORMATION, *PSOCKET_INFORMATION; - - -typedef struct _SOCKET_CONTEXT { - SOCK_SHARED_INFO SharedData; - ULONG SizeOfHelperData; - ULONG Padding; - SOCKADDR LocalAddress; - SOCKADDR RemoteAddress; - /* Plus Helper Data */ -} SOCKET_CONTEXT, *PSOCKET_CONTEXT; - -typedef struct _ASYNC_DATA { - PSOCKET_INFORMATION ParentSocket; - DWORD SequenceNumber; - IO_STATUS_BLOCK IoStatusBlock; - AFD_POLL_INFO AsyncSelectInfo; -} ASYNC_DATA, *PASYNC_DATA; - -SOCKET -WSPAPI -WSPAccept( - IN SOCKET s, - OUT LPSOCKADDR addr, - IN OUT LPINT addrlen, - IN LPCONDITIONPROC lpfnCondition, - IN DWORD dwCallbackData, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPAddressToString( - IN LPSOCKADDR lpsaAddress, - IN DWORD dwAddressLength, - IN LPWSAPROTOCOL_INFOW lpProtocolInfo, - OUT LPWSTR lpszAddressString, - IN OUT LPDWORD lpdwAddressStringLength, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPAsyncSelect( - IN SOCKET s, - IN HWND hWnd, - IN UINT wMsg, - IN LONG lEvent, - OUT LPINT lpErrno); - -INT -WSPAPI WSPBind( - IN SOCKET s, - IN CONST SOCKADDR *name, - IN INT namelen, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPCancelBlockingCall( - OUT LPINT lpErrno); - -INT -WSPAPI -WSPCleanup( - OUT LPINT lpErrno); - -INT -WSPAPI -WSPCloseSocket( - IN SOCKET s, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPConnect( - IN SOCKET s, - IN CONST SOCKADDR *name, - IN INT namelen, - IN LPWSABUF lpCallerData, - OUT LPWSABUF lpCalleeData, - IN LPQOS lpSQOS, - IN LPQOS lpGQOS, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPDuplicateSocket( - IN SOCKET s, - IN DWORD dwProcessId, - OUT LPWSAPROTOCOL_INFOW lpProtocolInfo, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPEnumNetworkEvents( - IN SOCKET s, - IN WSAEVENT hEventObject, - OUT LPWSANETWORKEVENTS lpNetworkEvents, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPEventSelect( - IN SOCKET s, - IN WSAEVENT hEventObject, - IN LONG lNetworkEvents, - OUT LPINT lpErrno); - -BOOL -WSPAPI -WSPGetOverlappedResult( - IN SOCKET s, - IN LPWSAOVERLAPPED lpOverlapped, - OUT LPDWORD lpcbTransfer, - IN BOOL fWait, - OUT LPDWORD lpdwFlags, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPGetPeerName( - IN SOCKET s, - OUT LPSOCKADDR name, - IN OUT LPINT namelen, - OUT LPINT lpErrno); - -BOOL -WSPAPI -WSPGetQOSByName( - IN SOCKET s, - IN OUT LPWSABUF lpQOSName, - OUT LPQOS lpQOS, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPGetSockName( - IN SOCKET s, - OUT LPSOCKADDR name, - IN OUT LPINT namelen, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPGetSockOpt( - IN SOCKET s, - IN INT level, - IN INT optname, - OUT CHAR FAR* optval, - IN OUT LPINT optlen, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPIoctl( - IN SOCKET s, - IN DWORD dwIoControlCode, - IN LPVOID lpvInBuffer, - IN DWORD cbInBuffer, - OUT LPVOID lpvOutBuffer, - IN DWORD cbOutBuffer, - OUT LPDWORD lpcbBytesReturned, - IN LPWSAOVERLAPPED lpOverlapped, - IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, - IN LPWSATHREADID lpThreadId, - OUT LPINT lpErrno); - -SOCKET -WSPAPI -WSPJoinLeaf( - IN SOCKET s, - IN CONST SOCKADDR *name, - IN INT namelen, - IN LPWSABUF lpCallerData, - OUT LPWSABUF lpCalleeData, - IN LPQOS lpSQOS, - IN LPQOS lpGQOS, - IN DWORD dwFlags, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPListen( - IN SOCKET s, - IN INT backlog, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPRecv( - IN SOCKET s, - IN OUT LPWSABUF lpBuffers, - IN DWORD dwBufferCount, - OUT LPDWORD lpNumberOfBytesRecvd, - IN OUT LPDWORD lpFlags, - IN LPWSAOVERLAPPED lpOverlapped, - IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, - IN LPWSATHREADID lpThreadId, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPRecvDisconnect( - IN SOCKET s, - OUT LPWSABUF lpInboundDisconnectData, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPRecvFrom( - IN SOCKET s, - IN OUT LPWSABUF lpBuffers, - IN DWORD dwBufferCount, - OUT LPDWORD lpNumberOfBytesRecvd, - IN OUT LPDWORD lpFlags, - OUT LPSOCKADDR lpFrom, - IN OUT LPINT lpFromlen, - IN LPWSAOVERLAPPED lpOverlapped, - IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, - IN LPWSATHREADID lpThreadId, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPSelect( - IN INT nfds, - IN OUT LPFD_SET readfds, - IN OUT LPFD_SET writefds, - IN OUT LPFD_SET exceptfds, - IN CONST LPTIMEVAL timeout, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPSend( - IN SOCKET s, - IN LPWSABUF lpBuffers, - IN DWORD dwBufferCount, - OUT LPDWORD lpNumberOfBytesSent, - IN DWORD dwFlags, - IN LPWSAOVERLAPPED lpOverlapped, - IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, - IN LPWSATHREADID lpThreadId, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPSendDisconnect( - IN SOCKET s, - IN LPWSABUF lpOutboundDisconnectData, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPSendTo( - IN SOCKET s, - IN LPWSABUF lpBuffers, - IN DWORD dwBufferCount, - OUT LPDWORD lpNumberOfBytesSent, - IN DWORD dwFlags, - IN CONST SOCKADDR *lpTo, - IN INT iTolen, - IN LPWSAOVERLAPPED lpOverlapped, - IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, - IN LPWSATHREADID lpThreadId, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPSetSockOpt( - IN SOCKET s, - IN INT level, - IN INT optname, - IN CONST CHAR FAR* optval, - IN INT optlen, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPShutdown( - IN SOCKET s, - IN INT how, - OUT LPINT lpErrno); - -SOCKET -WSPAPI -WSPSocket( - IN INT af, - IN INT type, - IN INT protocol, - IN LPWSAPROTOCOL_INFOW lpProtocolInfo, - IN GROUP g, - IN DWORD dwFlags, - OUT LPINT lpErrno); - -INT -WSPAPI -WSPStringToAddress( - IN LPWSTR AddressString, - IN INT AddressFamily, - IN LPWSAPROTOCOL_INFOW lpProtocolInfo, - OUT LPSOCKADDR lpAddress, - IN OUT LPINT lpAddressLength, - OUT LPINT lpErrno); - - -PSOCKET_INFORMATION GetSocketStructure( - SOCKET Handle -); - -VOID DeleteSocketStructure( SOCKET Handle ); - -int GetSocketInformation( - PSOCKET_INFORMATION Socket, - ULONG AfdInformationClass, - PULONG Ulong OPTIONAL, - PLARGE_INTEGER LargeInteger OPTIONAL -); - -int SetSocketInformation( - PSOCKET_INFORMATION Socket, - ULONG AfdInformationClass, - PULONG Ulong OPTIONAL, - PLARGE_INTEGER LargeInteger OPTIONAL -); - -int CreateContext( - PSOCKET_INFORMATION Socket -); - -int SockAsyncThread( - PVOID ThreadParam -); - -VOID -SockProcessAsyncSelect( - PSOCKET_INFORMATION Socket, - PASYNC_DATA AsyncData -); - -VOID -SockAsyncSelectCompletionRoutine( - PVOID Context, - PIO_STATUS_BLOCK IoStatusBlock -); - -BOOLEAN -SockCreateOrReferenceAsyncThread( - VOID -); - -BOOLEAN SockGetAsyncSelectHelperAfdHandle( - VOID -); - -VOID SockProcessQueuedAsyncSelect( - PVOID Context, - PIO_STATUS_BLOCK IoStatusBlock -); - -VOID -SockReenableAsyncSelectEvent ( - IN PSOCKET_INFORMATION Socket, - IN ULONG Event - ); - -DWORD MsafdReturnWithErrno( NTSTATUS Status, LPINT Errno, DWORD Received, - LPDWORD ReturnedBytes ); - -typedef VOID (*PASYNC_COMPLETION_ROUTINE)(PVOID Context, PIO_STATUS_BLOCK IoStatusBlock); - -#endif /* __MSAFD_H */ - -/* EOF */ diff --git a/dll/win32/msafd/msafd.rbuild b/dll/win32/msafd/msafd.rbuild index bc657128668..97473034d87 100644 --- a/dll/win32/msafd/msafd.rbuild +++ b/dll/win32/msafd/msafd.rbuild @@ -1,17 +1,4 @@ - + - . - include - include/reactos/drivers - msafd.h - ntdll - advapi32 - - dllmain.c - event.c - helpers.c - sndrcv.c - stubs.c - msafd.rc diff --git a/dll/win32/msafd/msafd.spec b/dll/win32/msafd/msafd.spec index cc0ccf9e9cc..35d8116ecfb 100644 --- a/dll/win32/msafd/msafd.spec +++ b/dll/win32/msafd/msafd.spec @@ -1 +1 @@ -@ stdcall WSPStartup (long ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr) +@ stdcall WSPStartup (long ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr) mswsock.WSPStartup From bb72205f9fda7a9fbc5d9ad30245beebdca8a6cb Mon Sep 17 00:00:00 2001 From: Sylvain Petreolle Date: Sun, 6 Jun 2010 16:33:17 +0000 Subject: [PATCH 23/24] Fix RtlIpv4StringToAddressW prototype and its caller in ws2_32. Fixes crash in GetAddrInfoW on xp sp3. svn path=/branches/aicom-network-branch/; revision=47628 --- dll/win32/ws2_32/src/addrinfo.c | 2 +- include/ndk/rtlfuncs.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dll/win32/ws2_32/src/addrinfo.c b/dll/win32/ws2_32/src/addrinfo.c index cfdb4f130dd..7bc55caf522 100644 --- a/dll/win32/ws2_32/src/addrinfo.c +++ b/dll/win32/ws2_32/src/addrinfo.c @@ -91,7 +91,7 @@ ParseV4Address(IN PCWSTR AddressString, LPWSTR Ip = 0; /* Do the conversion, don't accept wildcard */ - RtlIpv4StringToAddressW((LPWSTR)AddressString, 0, Ip, (IN_ADDR *)&Address); + RtlIpv4StringToAddressW((LPWSTR)AddressString, 0, &Ip, (IN_ADDR *)&Address); /* Return the address and success */ *pAddress = Address; diff --git a/include/ndk/rtlfuncs.h b/include/ndk/rtlfuncs.h index 5db3fc34daf..536548645ea 100644 --- a/include/ndk/rtlfuncs.h +++ b/include/ndk/rtlfuncs.h @@ -3183,9 +3183,9 @@ NTSYSAPI NTSTATUS NTAPI RtlIpv4StringToAddressW( - IN PWCHAR String, - IN UCHAR Strict, - OUT PWCHAR Terminator, + IN PCWSTR String, + IN BOOLEAN Strict, + OUT LPWSTR *Terminator, OUT struct in_addr *Addr ); From 6dd30b1f3a1a57c0e2894c6c3214c026f644bdfd Mon Sep 17 00:00:00 2001 From: Sylvain Petreolle Date: Sun, 6 Jun 2010 16:46:25 +0000 Subject: [PATCH 24/24] Forgotten in previous commit. svn path=/branches/aicom-network-branch/; revision=47629 --- lib/rtl/network.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/rtl/network.c b/lib/rtl/network.c index 356d3510fc4..369d15e284b 100644 --- a/lib/rtl/network.c +++ b/lib/rtl/network.c @@ -103,9 +103,9 @@ RtlIpv4StringToAddressExA(IN PCHAR AddressString, */ NTSTATUS NTAPI -RtlIpv4StringToAddressW(IN PWCHAR String, - IN UCHAR Strict, - OUT PWCHAR Terminator, +RtlIpv4StringToAddressW(IN PCWSTR String, + IN BOOLEAN Strict, + OUT LPTSTR *Terminator, OUT struct in_addr *Addr) { UNIMPLEMENTED;