From e2aa2958fa4bfd70bddba437bcb6623b1d6e5a74 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Tue, 26 Jan 2010 04:20:06 +0000 Subject: [PATCH 01/43] - 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/43] - 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/43] - 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/43] - 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/43] - 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/43] [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/43] [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/43] [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/43] - 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/43] - 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/43] - 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/43] - 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/43] - 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/43] - 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/43] - 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/43] - 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/43] - 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/43] - 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/43] - 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/43] - 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/43] 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/43] [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/43] 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/43] 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; From 5ed63500c203a094c0b69098e9811cf29387f5fd Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Mon, 12 Jul 2010 18:41:41 +0000 Subject: [PATCH 25/43] [MSAFD, PSDK] - Merge part of r45435 svn path=/trunk/; revision=48010 --- reactos/dll/win32/msafd/include/helpers.h | 2 +- reactos/dll/win32/msafd/misc/helpers.c | 2 +- reactos/include/psdk/wsahelp.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/reactos/dll/win32/msafd/include/helpers.h b/reactos/dll/win32/msafd/include/helpers.h index 1b73c669df5..7fa8e0c2627 100644 --- a/reactos/dll/win32/msafd/include/helpers.h +++ b/reactos/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/reactos/dll/win32/msafd/misc/helpers.c b/reactos/dll/win32/msafd/misc/helpers.c index f0bb6a9d5f0..89b1d6ac869 100644 --- a/reactos/dll/win32/msafd/misc/helpers.c +++ b/reactos/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/reactos/include/psdk/wsahelp.h b/reactos/include/psdk/wsahelp.h index 132261e0668..2e128a98b5b 100644 --- a/reactos/include/psdk/wsahelp.h +++ b/reactos/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 2d0076856f3c77e307036f18d27105960709655c Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Mon, 12 Jul 2010 18:58:17 +0000 Subject: [PATCH 26/43] [WINSOCK] - Merge r48011 from aicom-network-branch svn path=/trunk/; revision=48012 --- reactos/include/reactos/winsock/msafdlib.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reactos/include/reactos/winsock/msafdlib.h b/reactos/include/reactos/winsock/msafdlib.h index 0944141e6f8..18133bf692f 100644 --- a/reactos/include/reactos/winsock/msafdlib.h +++ b/reactos/include/reactos/winsock/msafdlib.h @@ -404,7 +404,7 @@ SockEnterApiFast(OUT PWINSOCK_TEB_DATA *ThreadData) /* Make sure we aren't terminating and get our thread data */ if (!(SockProcessTerminating) && (SockWspStartupCount > 0) && - ((*ThreadData == NtCurrentTeb()->WinSockData))) + ((*ThreadData = NtCurrentTeb()->WinSockData))) { /* Everything is good, return */ return NO_ERROR; From 7e93e6537fbe819cef59f72213e001e76b7273a9 Mon Sep 17 00:00:00 2001 From: Daniel Reimer Date: Mon, 12 Jul 2010 19:02:47 +0000 Subject: [PATCH 27/43] remove the old and static linked libpng. A new one will follow into the main tree, linked as dll for windowscodecs.dll. svn path=/trunk/; revision=48013 --- rosapps/lib/directory.rbuild | 4 ---- 1 file changed, 4 deletions(-) diff --git a/rosapps/lib/directory.rbuild b/rosapps/lib/directory.rbuild index 143a73ee931..df81a408dec 100644 --- a/rosapps/lib/directory.rbuild +++ b/rosapps/lib/directory.rbuild @@ -1,10 +1,6 @@ - - - - From 812e29c75a63b382af6aa008e7f4d6f26c0b0c9a Mon Sep 17 00:00:00 2001 From: Daniel Reimer Date: Mon, 12 Jul 2010 19:05:15 +0000 Subject: [PATCH 28/43] Update libjpeg from 6b to 8b. Add a new libpng 1.4.3 to main tree, linked dynamically, as libjpeg is, too. Add libtiff 3.9.4, linked dynamically, too. Enable both libs in wine/config.h which results in working png and tiff support in windowscodecs.dll svn path=/trunk/; revision=48014 --- reactos/boot/bootdata/packages/reactos.dff | 2 + reactos/dll/3rdparty/3rdparty.rbuild | 6 + reactos/dll/3rdparty/libjpeg/README | 277 +- reactos/dll/3rdparty/libjpeg/ansi2knr.c | 514 +- reactos/dll/3rdparty/libjpeg/cderror.h | 2 + reactos/dll/3rdparty/libjpeg/cdjpeg.h | 47 +- reactos/dll/3rdparty/libjpeg/change.log | 98 + reactos/dll/3rdparty/libjpeg/cjpeg.c | 44 +- reactos/dll/3rdparty/libjpeg/ckconfig.c | 2 +- reactos/dll/3rdparty/libjpeg/djpeg.c | 7 +- reactos/dll/3rdparty/libjpeg/example.c | 12 +- reactos/dll/3rdparty/libjpeg/jaricom.c | 153 + reactos/dll/3rdparty/libjpeg/jcapimin.c | 10 +- reactos/dll/3rdparty/libjpeg/jcarith.c | 934 ++++ reactos/dll/3rdparty/libjpeg/jccoefct.c | 24 +- reactos/dll/3rdparty/libjpeg/jcdctmgr.c | 511 +- reactos/dll/3rdparty/libjpeg/jchuff.c | 1015 +++- reactos/dll/3rdparty/libjpeg/jchuff.h | 47 - reactos/dll/3rdparty/libjpeg/jcinit.c | 15 +- reactos/dll/3rdparty/libjpeg/jcmainct.c | 14 +- reactos/dll/3rdparty/libjpeg/jcmarker.c | 98 +- reactos/dll/3rdparty/libjpeg/jcmaster.c | 322 +- reactos/dll/3rdparty/libjpeg/jconfig.h | 2 +- reactos/dll/3rdparty/libjpeg/jcparam.c | 72 +- reactos/dll/3rdparty/libjpeg/jcphuff.c | 833 --- reactos/dll/3rdparty/libjpeg/jcprepct.c | 14 +- reactos/dll/3rdparty/libjpeg/jcsample.c | 94 +- reactos/dll/3rdparty/libjpeg/jctrans.c | 24 +- reactos/dll/3rdparty/libjpeg/jdapimin.c | 5 +- reactos/dll/3rdparty/libjpeg/jdapistd.c | 2 +- reactos/dll/3rdparty/libjpeg/jdarith.c | 772 +++ reactos/dll/3rdparty/libjpeg/jdatadst.c | 122 +- reactos/dll/3rdparty/libjpeg/jdatasrc.c | 80 +- reactos/dll/3rdparty/libjpeg/jdcoefct.c | 14 +- reactos/dll/3rdparty/libjpeg/jdct.h | 239 +- reactos/dll/3rdparty/libjpeg/jddctmgr.c | 135 +- reactos/dll/3rdparty/libjpeg/jdhuff.c | 1176 +++- reactos/dll/3rdparty/libjpeg/jdhuff.h | 201 - reactos/dll/3rdparty/libjpeg/jdinput.c | 376 +- reactos/dll/3rdparty/libjpeg/jdmainct.c | 42 +- reactos/dll/3rdparty/libjpeg/jdmarker.c | 74 +- reactos/dll/3rdparty/libjpeg/jdmaster.c | 104 +- reactos/dll/3rdparty/libjpeg/jdphuff.c | 668 --- reactos/dll/3rdparty/libjpeg/jdsample.c | 147 +- reactos/dll/3rdparty/libjpeg/jdtrans.c | 19 +- reactos/dll/3rdparty/libjpeg/jerror.h | 9 +- reactos/dll/3rdparty/libjpeg/jfdctflt.c | 48 +- reactos/dll/3rdparty/libjpeg/jfdctfst.c | 48 +- reactos/dll/3rdparty/libjpeg/jfdctint.c | 4271 +++++++++++++- reactos/dll/3rdparty/libjpeg/jidctflt.c | 53 +- reactos/dll/3rdparty/libjpeg/jidctint.c | 4966 ++++++++++++++++- reactos/dll/3rdparty/libjpeg/jidctred.c | 398 -- reactos/dll/3rdparty/libjpeg/jmorecfg.h | 92 +- reactos/dll/3rdparty/libjpeg/jpegexiforient.c | 299 - reactos/dll/3rdparty/libjpeg/jpegint.h | 43 +- reactos/dll/3rdparty/libjpeg/jpeglib.h | 104 +- reactos/dll/3rdparty/libjpeg/jpegtran.c | 182 +- reactos/dll/3rdparty/libjpeg/jutils.c | 52 + reactos/dll/3rdparty/libjpeg/jversion.h | 6 +- reactos/dll/3rdparty/libjpeg/libjpeg.rbuild | 6 +- .../dll/3rdparty/libjpeg/libjpeg.reactos.diff | 12 - reactos/dll/3rdparty/libjpeg/makefile.ansi | 77 +- reactos/dll/3rdparty/libjpeg/rdbmp.c | 57 +- reactos/dll/3rdparty/libjpeg/rdjpgcom.c | 221 +- reactos/dll/3rdparty/libjpeg/rdppm.c | 1 + reactos/dll/3rdparty/libjpeg/rdswitch.c | 39 +- reactos/dll/3rdparty/libjpeg/transupp.c | 639 +-- reactos/dll/3rdparty/libjpeg/transupp.h | 51 +- reactos/dll/3rdparty/libjpeg/wrppm.c | 5 +- reactos/dll/3rdparty/libpng/docs/ANNOUNCE | 39 + reactos/dll/3rdparty/libpng/docs/CHANGES | 2619 +++++++++ reactos/dll/3rdparty/libpng/docs/INSTALL | 143 + reactos/dll/3rdparty/libpng/docs/LICENSE | 111 + reactos/dll/3rdparty/libpng/docs/README | 257 + reactos/dll/3rdparty/libpng/docs/TODO | 31 + reactos/dll/3rdparty/libpng/docs/example.c | 838 +++ .../dll/3rdparty/libpng/docs/libpng-1.4.3.txt | 3352 +++++++++++ reactos/dll/3rdparty/libpng/libpng.rbuild | 27 + .../3rdparty/libpng/new_push_process_row.c | 204 + reactos/dll/3rdparty/libpng/png.c | 918 +++ reactos/dll/3rdparty/libpng/png.h | 2701 +++++++++ reactos/dll/3rdparty/libpng/pngconf.h | 1525 +++++ reactos/dll/3rdparty/libpng/pngerror.c | 402 ++ reactos/dll/3rdparty/libpng/pngget.c | 925 +++ reactos/dll/3rdparty/libpng/pngmem.c | 611 ++ reactos/dll/3rdparty/libpng/pngpread.c | 1765 ++++++ reactos/dll/3rdparty/libpng/pngpriv.h | 956 ++++ reactos/dll/3rdparty/libpng/pngread.c | 1361 +++++ reactos/dll/3rdparty/libpng/pngrio.c | 163 + reactos/dll/3rdparty/libpng/pngrtran.c | 4203 ++++++++++++++ reactos/dll/3rdparty/libpng/pngrutil.c | 3381 +++++++++++ reactos/dll/3rdparty/libpng/pngset.c | 1167 ++++ reactos/dll/3rdparty/libpng/pngtest.c | 1630 ++++++ reactos/dll/3rdparty/libpng/pngtrans.c | 677 +++ reactos/dll/3rdparty/libpng/pngwio.c | 241 + reactos/dll/3rdparty/libpng/pngwrite.c | 1457 +++++ reactos/dll/3rdparty/libpng/pngwtran.c | 566 ++ reactos/dll/3rdparty/libpng/pngwutil.c | 2786 +++++++++ reactos/dll/3rdparty/libtiff/libtiff.def | 140 + reactos/dll/3rdparty/libtiff/libtiff.rbuild | 50 + reactos/dll/3rdparty/libtiff/mkg3states.c | 451 ++ reactos/dll/3rdparty/libtiff/t4.h | 292 + reactos/dll/3rdparty/libtiff/tif_aux.c | 290 + reactos/dll/3rdparty/libtiff/tif_close.c | 126 + reactos/dll/3rdparty/libtiff/tif_codec.c | 160 + reactos/dll/3rdparty/libtiff/tif_color.c | 282 + reactos/dll/3rdparty/libtiff/tif_compress.c | 295 + reactos/dll/3rdparty/libtiff/tif_config.h | 63 + reactos/dll/3rdparty/libtiff/tif_config.vc.h | 63 + reactos/dll/3rdparty/libtiff/tif_dir.c | 1389 +++++ reactos/dll/3rdparty/libtiff/tif_dir.h | 211 + reactos/dll/3rdparty/libtiff/tif_dirinfo.c | 888 +++ reactos/dll/3rdparty/libtiff/tif_dirread.c | 2081 +++++++ reactos/dll/3rdparty/libtiff/tif_dirwrite.c | 1414 +++++ reactos/dll/3rdparty/libtiff/tif_dumpmode.c | 126 + reactos/dll/3rdparty/libtiff/tif_error.c | 80 + reactos/dll/3rdparty/libtiff/tif_extension.c | 118 + reactos/dll/3rdparty/libtiff/tif_fax3.c | 1626 ++++++ reactos/dll/3rdparty/libtiff/tif_fax3.h | 532 ++ reactos/dll/3rdparty/libtiff/tif_fax3sm.c | 1260 +++++ reactos/dll/3rdparty/libtiff/tif_flush.c | 74 + reactos/dll/3rdparty/libtiff/tif_getimage.c | 2676 +++++++++ reactos/dll/3rdparty/libtiff/tif_jbig.c | 385 ++ reactos/dll/3rdparty/libtiff/tif_jpeg.c | 2065 +++++++ reactos/dll/3rdparty/libtiff/tif_luv.c | 1629 ++++++ reactos/dll/3rdparty/libtiff/tif_lzw.c | 1129 ++++ reactos/dll/3rdparty/libtiff/tif_next.c | 154 + reactos/dll/3rdparty/libtiff/tif_ojpeg.c | 2438 ++++++++ reactos/dll/3rdparty/libtiff/tif_open.c | 695 +++ reactos/dll/3rdparty/libtiff/tif_packbits.c | 300 + reactos/dll/3rdparty/libtiff/tif_pixarlog.c | 1371 +++++ reactos/dll/3rdparty/libtiff/tif_predict.c | 736 +++ reactos/dll/3rdparty/libtiff/tif_predict.h | 77 + reactos/dll/3rdparty/libtiff/tif_print.c | 646 +++ reactos/dll/3rdparty/libtiff/tif_read.c | 750 +++ reactos/dll/3rdparty/libtiff/tif_strip.c | 370 ++ reactos/dll/3rdparty/libtiff/tif_swab.c | 242 + reactos/dll/3rdparty/libtiff/tif_thunder.c | 165 + reactos/dll/3rdparty/libtiff/tif_tile.c | 280 + reactos/dll/3rdparty/libtiff/tif_version.c | 40 + reactos/dll/3rdparty/libtiff/tif_warning.c | 81 + reactos/dll/3rdparty/libtiff/tif_win32.c | 408 ++ reactos/dll/3rdparty/libtiff/tif_write.c | 718 +++ reactos/dll/3rdparty/libtiff/tif_zip.c | 419 ++ reactos/dll/3rdparty/libtiff/tiff.h | 654 +++ reactos/dll/3rdparty/libtiff/tiffconf.h | 103 + reactos/dll/3rdparty/libtiff/tiffconf.vc.h | 116 + reactos/dll/3rdparty/libtiff/tiffio.h | 526 ++ reactos/dll/3rdparty/libtiff/tiffio.hxx | 49 + reactos/dll/3rdparty/libtiff/tiffiop.h | 350 ++ reactos/dll/3rdparty/libtiff/tiffvers.h | 9 + reactos/dll/3rdparty/libtiff/uvcode.h | 180 + .../win32/windowscodecs/windowscodecs.rbuild | 5 +- .../include/reactos/libs/libjpeg/cderror.h | 2 + reactos/include/reactos/libs/libjpeg/cdjpeg.h | 47 +- reactos/include/reactos/libs/libjpeg/jchuff.h | 47 - .../include/reactos/libs/libjpeg/jconfig.h | 4 + reactos/include/reactos/libs/libjpeg/jdct.h | 239 +- reactos/include/reactos/libs/libjpeg/jdhuff.h | 201 - reactos/include/reactos/libs/libjpeg/jerror.h | 9 +- .../include/reactos/libs/libjpeg/jmorecfg.h | 92 +- .../include/reactos/libs/libjpeg/jpegint.h | 43 +- .../include/reactos/libs/libjpeg/jpeglib.h | 104 +- .../include/reactos/libs/libjpeg/jversion.h | 6 +- .../reactos/libs/libjpeg/libjpeg.reactos.diff | 12 - .../include/reactos/libs/libjpeg/transupp.h | 51 +- reactos/include/reactos/libs/libpng/png.h | 2701 +++++++++ reactos/include/reactos/libs/libpng/pngconf.h | 1525 +++++ reactos/include/reactos/libs/libpng/pngpriv.h | 956 ++++ reactos/include/reactos/libs/libtiff/t4.h | 292 + .../include/reactos/libs/libtiff/tif_config.h | 63 + .../reactos/libs/libtiff/tif_config.vc.h | 63 + .../include/reactos/libs/libtiff/tif_dir.h | 211 + .../include/reactos/libs/libtiff/tif_fax3.h | 532 ++ .../reactos/libs/libtiff/tif_predict.h | 77 + reactos/include/reactos/libs/libtiff/tiff.h | 654 +++ .../include/reactos/libs/libtiff/tiffconf.h | 103 + .../reactos/libs/libtiff/tiffconf.vc.h | 116 + reactos/include/reactos/libs/libtiff/tiffio.h | 526 ++ .../include/reactos/libs/libtiff/tiffio.hxx | 49 + .../include/reactos/libs/libtiff/tiffiop.h | 350 ++ .../include/reactos/libs/libtiff/tiffvers.h | 9 + reactos/include/reactos/libs/libtiff/uvcode.h | 180 + reactos/include/reactos/libs/zlib/crc32.h | 441 ++ reactos/include/reactos/libs/zlib/deflate.h | 342 ++ reactos/include/reactos/libs/zlib/gzguts.h | 135 + reactos/include/reactos/libs/zlib/inffast.h | 11 + reactos/include/reactos/libs/zlib/inffixed.h | 94 + reactos/include/reactos/libs/zlib/inflate.h | 122 + reactos/include/reactos/libs/zlib/inftrees.h | 62 + reactos/include/reactos/libs/zlib/trees.h | 128 + reactos/include/reactos/libs/zlib/zconf.h | 428 ++ reactos/include/reactos/libs/zlib/zlib.h | 1613 ++++++ reactos/include/reactos/libs/zlib/zutil.h | 274 + reactos/include/reactos/wine/config.h | 15 + 195 files changed, 95095 insertions(+), 5715 deletions(-) create mode 100644 reactos/dll/3rdparty/libjpeg/jaricom.c create mode 100644 reactos/dll/3rdparty/libjpeg/jcarith.c delete mode 100644 reactos/dll/3rdparty/libjpeg/jchuff.h delete mode 100644 reactos/dll/3rdparty/libjpeg/jcphuff.c create mode 100644 reactos/dll/3rdparty/libjpeg/jdarith.c delete mode 100644 reactos/dll/3rdparty/libjpeg/jdhuff.h delete mode 100644 reactos/dll/3rdparty/libjpeg/jdphuff.c delete mode 100644 reactos/dll/3rdparty/libjpeg/jidctred.c delete mode 100644 reactos/dll/3rdparty/libjpeg/jpegexiforient.c delete mode 100644 reactos/dll/3rdparty/libjpeg/libjpeg.reactos.diff create mode 100644 reactos/dll/3rdparty/libpng/docs/ANNOUNCE create mode 100644 reactos/dll/3rdparty/libpng/docs/CHANGES create mode 100644 reactos/dll/3rdparty/libpng/docs/INSTALL create mode 100644 reactos/dll/3rdparty/libpng/docs/LICENSE create mode 100644 reactos/dll/3rdparty/libpng/docs/README create mode 100644 reactos/dll/3rdparty/libpng/docs/TODO create mode 100644 reactos/dll/3rdparty/libpng/docs/example.c create mode 100644 reactos/dll/3rdparty/libpng/docs/libpng-1.4.3.txt create mode 100644 reactos/dll/3rdparty/libpng/libpng.rbuild create mode 100644 reactos/dll/3rdparty/libpng/new_push_process_row.c create mode 100644 reactos/dll/3rdparty/libpng/png.c create mode 100644 reactos/dll/3rdparty/libpng/png.h create mode 100644 reactos/dll/3rdparty/libpng/pngconf.h create mode 100644 reactos/dll/3rdparty/libpng/pngerror.c create mode 100644 reactos/dll/3rdparty/libpng/pngget.c create mode 100644 reactos/dll/3rdparty/libpng/pngmem.c create mode 100644 reactos/dll/3rdparty/libpng/pngpread.c create mode 100644 reactos/dll/3rdparty/libpng/pngpriv.h create mode 100644 reactos/dll/3rdparty/libpng/pngread.c create mode 100644 reactos/dll/3rdparty/libpng/pngrio.c create mode 100644 reactos/dll/3rdparty/libpng/pngrtran.c create mode 100644 reactos/dll/3rdparty/libpng/pngrutil.c create mode 100644 reactos/dll/3rdparty/libpng/pngset.c create mode 100644 reactos/dll/3rdparty/libpng/pngtest.c create mode 100644 reactos/dll/3rdparty/libpng/pngtrans.c create mode 100644 reactos/dll/3rdparty/libpng/pngwio.c create mode 100644 reactos/dll/3rdparty/libpng/pngwrite.c create mode 100644 reactos/dll/3rdparty/libpng/pngwtran.c create mode 100644 reactos/dll/3rdparty/libpng/pngwutil.c create mode 100644 reactos/dll/3rdparty/libtiff/libtiff.def create mode 100644 reactos/dll/3rdparty/libtiff/libtiff.rbuild create mode 100644 reactos/dll/3rdparty/libtiff/mkg3states.c create mode 100644 reactos/dll/3rdparty/libtiff/t4.h create mode 100644 reactos/dll/3rdparty/libtiff/tif_aux.c create mode 100644 reactos/dll/3rdparty/libtiff/tif_close.c create mode 100644 reactos/dll/3rdparty/libtiff/tif_codec.c create mode 100644 reactos/dll/3rdparty/libtiff/tif_color.c create mode 100644 reactos/dll/3rdparty/libtiff/tif_compress.c create mode 100644 reactos/dll/3rdparty/libtiff/tif_config.h create mode 100644 reactos/dll/3rdparty/libtiff/tif_config.vc.h create mode 100644 reactos/dll/3rdparty/libtiff/tif_dir.c create mode 100644 reactos/dll/3rdparty/libtiff/tif_dir.h create mode 100644 reactos/dll/3rdparty/libtiff/tif_dirinfo.c create mode 100644 reactos/dll/3rdparty/libtiff/tif_dirread.c create mode 100644 reactos/dll/3rdparty/libtiff/tif_dirwrite.c create mode 100644 reactos/dll/3rdparty/libtiff/tif_dumpmode.c create mode 100644 reactos/dll/3rdparty/libtiff/tif_error.c create mode 100644 reactos/dll/3rdparty/libtiff/tif_extension.c create mode 100644 reactos/dll/3rdparty/libtiff/tif_fax3.c create mode 100644 reactos/dll/3rdparty/libtiff/tif_fax3.h create mode 100644 reactos/dll/3rdparty/libtiff/tif_fax3sm.c create mode 100644 reactos/dll/3rdparty/libtiff/tif_flush.c create mode 100644 reactos/dll/3rdparty/libtiff/tif_getimage.c create mode 100644 reactos/dll/3rdparty/libtiff/tif_jbig.c create mode 100644 reactos/dll/3rdparty/libtiff/tif_jpeg.c create mode 100644 reactos/dll/3rdparty/libtiff/tif_luv.c create mode 100644 reactos/dll/3rdparty/libtiff/tif_lzw.c create mode 100644 reactos/dll/3rdparty/libtiff/tif_next.c create mode 100644 reactos/dll/3rdparty/libtiff/tif_ojpeg.c create mode 100644 reactos/dll/3rdparty/libtiff/tif_open.c create mode 100644 reactos/dll/3rdparty/libtiff/tif_packbits.c create mode 100644 reactos/dll/3rdparty/libtiff/tif_pixarlog.c create mode 100644 reactos/dll/3rdparty/libtiff/tif_predict.c create mode 100644 reactos/dll/3rdparty/libtiff/tif_predict.h create mode 100644 reactos/dll/3rdparty/libtiff/tif_print.c create mode 100644 reactos/dll/3rdparty/libtiff/tif_read.c create mode 100644 reactos/dll/3rdparty/libtiff/tif_strip.c create mode 100644 reactos/dll/3rdparty/libtiff/tif_swab.c create mode 100644 reactos/dll/3rdparty/libtiff/tif_thunder.c create mode 100644 reactos/dll/3rdparty/libtiff/tif_tile.c create mode 100644 reactos/dll/3rdparty/libtiff/tif_version.c create mode 100644 reactos/dll/3rdparty/libtiff/tif_warning.c create mode 100644 reactos/dll/3rdparty/libtiff/tif_win32.c create mode 100644 reactos/dll/3rdparty/libtiff/tif_write.c create mode 100644 reactos/dll/3rdparty/libtiff/tif_zip.c create mode 100644 reactos/dll/3rdparty/libtiff/tiff.h create mode 100644 reactos/dll/3rdparty/libtiff/tiffconf.h create mode 100644 reactos/dll/3rdparty/libtiff/tiffconf.vc.h create mode 100644 reactos/dll/3rdparty/libtiff/tiffio.h create mode 100644 reactos/dll/3rdparty/libtiff/tiffio.hxx create mode 100644 reactos/dll/3rdparty/libtiff/tiffiop.h create mode 100644 reactos/dll/3rdparty/libtiff/tiffvers.h create mode 100644 reactos/dll/3rdparty/libtiff/uvcode.h delete mode 100644 reactos/include/reactos/libs/libjpeg/jchuff.h delete mode 100644 reactos/include/reactos/libs/libjpeg/jdhuff.h delete mode 100644 reactos/include/reactos/libs/libjpeg/libjpeg.reactos.diff create mode 100644 reactos/include/reactos/libs/libpng/png.h create mode 100644 reactos/include/reactos/libs/libpng/pngconf.h create mode 100644 reactos/include/reactos/libs/libpng/pngpriv.h create mode 100644 reactos/include/reactos/libs/libtiff/t4.h create mode 100644 reactos/include/reactos/libs/libtiff/tif_config.h create mode 100644 reactos/include/reactos/libs/libtiff/tif_config.vc.h create mode 100644 reactos/include/reactos/libs/libtiff/tif_dir.h create mode 100644 reactos/include/reactos/libs/libtiff/tif_fax3.h create mode 100644 reactos/include/reactos/libs/libtiff/tif_predict.h create mode 100644 reactos/include/reactos/libs/libtiff/tiff.h create mode 100644 reactos/include/reactos/libs/libtiff/tiffconf.h create mode 100644 reactos/include/reactos/libs/libtiff/tiffconf.vc.h create mode 100644 reactos/include/reactos/libs/libtiff/tiffio.h create mode 100644 reactos/include/reactos/libs/libtiff/tiffio.hxx create mode 100644 reactos/include/reactos/libs/libtiff/tiffiop.h create mode 100644 reactos/include/reactos/libs/libtiff/tiffvers.h create mode 100644 reactos/include/reactos/libs/libtiff/uvcode.h create mode 100644 reactos/include/reactos/libs/zlib/crc32.h create mode 100644 reactos/include/reactos/libs/zlib/deflate.h create mode 100644 reactos/include/reactos/libs/zlib/gzguts.h create mode 100644 reactos/include/reactos/libs/zlib/inffast.h create mode 100644 reactos/include/reactos/libs/zlib/inffixed.h create mode 100644 reactos/include/reactos/libs/zlib/inflate.h create mode 100644 reactos/include/reactos/libs/zlib/inftrees.h create mode 100644 reactos/include/reactos/libs/zlib/trees.h create mode 100644 reactos/include/reactos/libs/zlib/zconf.h create mode 100644 reactos/include/reactos/libs/zlib/zlib.h create mode 100644 reactos/include/reactos/libs/zlib/zutil.h diff --git a/reactos/boot/bootdata/packages/reactos.dff b/reactos/boot/bootdata/packages/reactos.dff index d7b0967c2f1..a9b97bb2c02 100644 --- a/reactos/boot/bootdata/packages/reactos.dff +++ b/reactos/boot/bootdata/packages/reactos.dff @@ -127,6 +127,8 @@ base\system\smss\smss.exe 1 ; Dynamic Link Libraries dll\3rdparty\mesa32\mesa32.dll 1 dll\3rdparty\libjpeg\libjpeg.dll 1 +dll\3rdparty\libpng\libpng.dll 1 +dll\3rdparty\libtiff\libtiff.dll 1 dll\3rdparty\libxslt\libxslt.dll 1 dll\3rdparty\dxtn\dxtn.dll 1 optional diff --git a/reactos/dll/3rdparty/3rdparty.rbuild b/reactos/dll/3rdparty/3rdparty.rbuild index e2d58af9496..c6900d07259 100644 --- a/reactos/dll/3rdparty/3rdparty.rbuild +++ b/reactos/dll/3rdparty/3rdparty.rbuild @@ -7,6 +7,12 @@ + + + + + + diff --git a/reactos/dll/3rdparty/libjpeg/README b/reactos/dll/3rdparty/libjpeg/README index 86cc20669d6..e923a320048 100644 --- a/reactos/dll/3rdparty/libjpeg/README +++ b/reactos/dll/3rdparty/libjpeg/README @@ -1,22 +1,17 @@ The Independent JPEG Group's JPEG software ========================================== -README for release 6b of 27-Mar-1998 +README for release 8b of 16-May-2010 ==================================== -This distribution contains the sixth public release of the Independent JPEG +This distribution contains the eighth public release of the Independent JPEG Group's free JPEG software. You are welcome to redistribute this software and to use it for any purpose, subject to the conditions under LEGAL ISSUES, below. -Serious users of this software (particularly those incorporating it into -larger programs) should contact IJG at jpeg-info@uunet.uu.net to be added to -our electronic mailing list. Mailing list members are notified of updates -and have a chance to participate in technical discussions, etc. - -This software is the work of Tom Lane, Philip Gladstone, Jim Boucher, -Lee Crocker, Julian Minguillon, Luis Ortiz, George Phillips, Davide Rossi, -Guido Vollbeding, Ge' Weijers, and other members of the Independent JPEG -Group. +This software is the work of Tom Lane, Guido Vollbeding, Philip Gladstone, +Bill Allombert, Jim Boucher, Lee Crocker, Bob Friesenhahn, Ben Jackson, +Julian Minguillon, Luis Ortiz, George Phillips, Davide Rossi, Ge' Weijers, +and other members of the Independent JPEG Group. IJG is not affiliated with the official ISO JPEG standards committee. @@ -30,27 +25,27 @@ OVERVIEW General description of JPEG and the IJG software. LEGAL ISSUES Copyright, lack of warranty, terms of distribution. REFERENCES Where to learn more about JPEG. ARCHIVE LOCATIONS Where to find newer versions of this software. -RELATED SOFTWARE Other stuff you should get. +ACKNOWLEDGMENTS Special thanks. FILE FORMAT WARS Software *not* to get. TO DO Plans for future IJG releases. Other documentation files in the distribution are: User documentation: - install.doc How to configure and install the IJG software. - usage.doc Usage instructions for cjpeg, djpeg, jpegtran, + install.txt How to configure and install the IJG software. + usage.txt Usage instructions for cjpeg, djpeg, jpegtran, rdjpgcom, and wrjpgcom. - *.1 Unix-style man pages for programs (same info as usage.doc). - wizard.doc Advanced usage instructions for JPEG wizards only. + *.1 Unix-style man pages for programs (same info as usage.txt). + wizard.txt Advanced usage instructions for JPEG wizards only. change.log Version-to-version change highlights. Programmer and internal documentation: - libjpeg.doc How to use the JPEG library in your own programs. + libjpeg.txt How to use the JPEG library in your own programs. example.c Sample code for calling the JPEG library. - structure.doc Overview of the JPEG library's internal structure. - filelist.doc Road map of IJG files. - coderules.doc Coding style rules --- please read if you contribute code. + structure.txt Overview of the JPEG library's internal structure. + filelist.txt Road map of IJG files. + coderules.txt Coding style rules --- please read if you contribute code. -Please read at least the files install.doc and usage.doc. Useful information +Please read at least the files install.txt and usage.txt. Some information can also be found in the JPEG FAQ (Frequently Asked Questions) article. See ARCHIVE LOCATIONS below to find out where to obtain the FAQ article. @@ -62,24 +57,15 @@ the order listed) before diving into the code. OVERVIEW ======== -This package contains C software to implement JPEG image compression and -decompression. JPEG (pronounced "jay-peg") is a standardized compression -method for full-color and gray-scale images. JPEG is intended for compressing -"real-world" scenes; line drawings, cartoons and other non-realistic images -are not its strong suit. JPEG is lossy, meaning that the output image is not -exactly identical to the input image. Hence you must not use JPEG if you -have to have identical output bits. However, on typical photographic images, -very good compression levels can be obtained with no visible change, and -remarkably high compression levels are possible if you can tolerate a -low-quality image. For more details, see the references, or just experiment -with various compression settings. +This package contains C software to implement JPEG image encoding, decoding, +and transcoding. JPEG (pronounced "jay-peg") is a standardized compression +method for full-color and gray-scale images. This software implements JPEG baseline, extended-sequential, and progressive compression processes. Provision is made for supporting all variants of these processes, although some uncommon parameter settings aren't implemented yet. -For legal reasons, we are not distributing code for the arithmetic-coding -variants of JPEG; see LEGAL ISSUES. We have made no provision for supporting -the hierarchical or lossless processes defined in the standard. +We have made no provision for supporting the hierarchical or lossless +processes defined in the standard. We provide a set of library routines for reading and writing JPEG image files, plus two sample applications "cjpeg" and "djpeg", which use the library to @@ -91,10 +77,11 @@ considerable functionality beyond the bare JPEG coding/decoding capability; for example, the color quantization modules are not strictly part of JPEG decoding, but they are essential for output to colormapped file formats or colormapped displays. These extra functions can be compiled out of the -library if not required for a particular application. We have also included -"jpegtran", a utility for lossless transcoding between different JPEG -processes, and "rdjpgcom" and "wrjpgcom", two simple applications for -inserting and extracting textual comments in JFIF files. +library if not required for a particular application. + +We have also included "jpegtran", a utility for lossless transcoding between +different JPEG processes, and "rdjpgcom" and "wrjpgcom", two simple +applications for inserting and extracting textual comments in JFIF files. The emphasis in designing this software has been on achieving portability and flexibility, while also making it fast enough to be useful. In particular, @@ -127,7 +114,7 @@ with respect to this software, its quality, accuracy, merchantability, or fitness for a particular purpose. This software is provided "AS IS", and you, its user, assume the entire risk as to its quality and accuracy. -This software is copyright (C) 1991-1998, Thomas G. Lane. +This software is copyright (C) 1991-2010, Thomas G. Lane, Guido Vollbeding. All Rights Reserved except as specified below. Permission is hereby granted to use, copy, modify, and distribute this @@ -170,17 +157,8 @@ the foregoing paragraphs do. The Unix configuration script "configure" was produced with GNU Autoconf. It is copyright by the Free Software Foundation but is freely distributable. The same holds for its supporting scripts (config.guess, config.sub, -ltconfig, ltmain.sh). Another support script, install-sh, is copyright -by M.I.T. but is also freely distributable. - -It appears that the arithmetic coding option of the JPEG spec is covered by -patents owned by IBM, AT&T, and Mitsubishi. Hence arithmetic coding cannot -legally be used without obtaining one or more licenses. For this reason, -support for arithmetic coding has been removed from the free JPEG software. -(Since arithmetic coding provides only a marginal gain over the unpatented -Huffman mode, it is unlikely that very many implementations will support it.) -So far as we are aware, there are no patent restrictions on the remaining -code. +ltmain.sh). Another support script, install-sh, is copyright by X Consortium +but is also freely distributable. The IJG distribution formerly included code to read and write GIF files. To avoid entanglement with the Unisys LZW patent, GIF reading support has @@ -198,7 +176,7 @@ We are required to state that REFERENCES ========== -We highly recommend reading one or more of these references before trying to +We recommend reading one or more of these references before trying to understand the innards of the JPEG software. The best short technical introduction to the JPEG compression algorithm is @@ -207,7 +185,7 @@ The best short technical introduction to the JPEG compression algorithm is (Adjacent articles in that issue discuss MPEG motion picture compression, applications of JPEG, and related topics.) If you don't have the CACM issue handy, a PostScript file containing a revised version of Wallace's article is -available at ftp://ftp.uu.net/graphics/jpeg/wallace.ps.gz. The file (actually +available at http://www.ijg.org/files/wallace.ps.gz. The file (actually a preprint for an article that appeared in IEEE Trans. Consumer Electronics) omits the sample images that appeared in CACM, but it includes corrections and some added material. Note: the Wallace article is copyright ACM and IEEE, @@ -222,82 +200,65 @@ code but don't know much about data compression in general. The book's JPEG sample code is far from industrial-strength, but when you are ready to look at a full implementation, you've got one here... -The best full description of JPEG is the textbook "JPEG Still Image Data -Compression Standard" by William B. Pennebaker and Joan L. Mitchell, published -by Van Nostrand Reinhold, 1993, ISBN 0-442-01272-1. Price US$59.95, 638 pp. -The book includes the complete text of the ISO JPEG standards (DIS 10918-1 -and draft DIS 10918-2). This is by far the most complete exposition of JPEG -in existence, and we highly recommend it. +The best currently available description of JPEG is the textbook "JPEG Still +Image Data Compression Standard" by William B. Pennebaker and Joan L. +Mitchell, published by Van Nostrand Reinhold, 1993, ISBN 0-442-01272-1. +Price US$59.95, 638 pp. The book includes the complete text of the ISO JPEG +standards (DIS 10918-1 and draft DIS 10918-2). +Although this is by far the most detailed and comprehensive exposition of +JPEG publicly available, we point out that it is still missing an explanation +of the most essential properties and algorithms of the underlying DCT +technology. +If you think that you know about DCT-based JPEG after reading this book, +then you are in delusion. The real fundamentals and corresponding potential +of DCT-based JPEG are not publicly known so far, and that is the reason for +all the mistaken developments taking place in the image coding domain. -The JPEG standard itself is not available electronically; you must order a -paper copy through ISO or ITU. (Unless you feel a need to own a certified -official copy, we recommend buying the Pennebaker and Mitchell book instead; -it's much cheaper and includes a great deal of useful explanatory material.) -In the USA, copies of the standard may be ordered from ANSI Sales at (212) -642-4900, or from Global Engineering Documents at (800) 854-7179. (ANSI -doesn't take credit card orders, but Global does.) It's not cheap: as of -1992, ANSI was charging $95 for Part 1 and $47 for Part 2, plus 7% -shipping/handling. The standard is divided into two parts, Part 1 being the -actual specification, while Part 2 covers compliance testing methods. Part 1 -is titled "Digital Compression and Coding of Continuous-tone Still Images, +The original JPEG standard is divided into two parts, Part 1 being the actual +specification, while Part 2 covers compliance testing methods. Part 1 is +titled "Digital Compression and Coding of Continuous-tone Still Images, Part 1: Requirements and guidelines" and has document numbers ISO/IEC IS 10918-1, ITU-T T.81. Part 2 is titled "Digital Compression and Coding of Continuous-tone Still Images, Part 2: Compliance testing" and has document numbers ISO/IEC IS 10918-2, ITU-T T.83. - -Some extensions to the original JPEG standard are defined in JPEG Part 3, -a newer ISO standard numbered ISO/IEC IS 10918-3 and ITU-T T.84. IJG -currently does not support any Part 3 extensions. +IJG JPEG 8 introduces an implementation of the JPEG SmartScale extension +which is specified in a contributed document at ITU and ISO with title "ITU-T +JPEG-Plus Proposal for Extending ITU-T T.81 for Advanced Image Coding", April +2006, Geneva, Switzerland. The latest version of the document is Revision 3. The JPEG standard does not specify all details of an interchangeable file format. For the omitted details we follow the "JFIF" conventions, revision -1.02. A copy of the JFIF spec is available from: - Literature Department - C-Cube Microsystems, Inc. - 1778 McCarthy Blvd. - Milpitas, CA 95035 - phone (408) 944-6300, fax (408) 944-6314 -A PostScript version of this document is available by FTP at -ftp://ftp.uu.net/graphics/jpeg/jfif.ps.gz. There is also a plain text -version at ftp://ftp.uu.net/graphics/jpeg/jfif.txt.gz, but it is missing -the figures. +1.02. JFIF 1.02 has been adopted as an Ecma International Technical Report +and thus received a formal publication status. It is available as a free +download in PDF format from +http://www.ecma-international.org/publications/techreports/E-TR-098.htm. +A PostScript version of the JFIF document is available at +http://www.ijg.org/files/jfif.ps.gz. There is also a plain text version at +http://www.ijg.org/files/jfif.txt.gz, but it is missing the figures. The TIFF 6.0 file format specification can be obtained by FTP from ftp://ftp.sgi.com/graphics/tiff/TIFF6.ps.gz. The JPEG incorporation scheme found in the TIFF 6.0 spec of 3-June-92 has a number of serious problems. IJG does not recommend use of the TIFF 6.0 design (TIFF Compression tag 6). Instead, we recommend the JPEG design proposed by TIFF Technical Note #2 -(Compression tag 7). Copies of this Note can be obtained from ftp.sgi.com or -from ftp://ftp.uu.net/graphics/jpeg/. It is expected that the next revision +(Compression tag 7). Copies of this Note can be obtained from +http://www.ijg.org/files/. It is expected that the next revision of the TIFF spec will replace the 6.0 JPEG design with the Note's design. Although IJG's own code does not support TIFF/JPEG, the free libtiff library -uses our library to implement TIFF/JPEG per the Note. libtiff is available -from ftp://ftp.sgi.com/graphics/tiff/. +uses our library to implement TIFF/JPEG per the Note. ARCHIVE LOCATIONS ================= -The "official" archive site for this software is ftp.uu.net (Internet -address 192.48.96.9). The most recent released version can always be found -there in directory graphics/jpeg. This particular version will be archived -as ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz. If you don't have -direct Internet access, UUNET's archives are also available via UUCP; contact -help@uunet.uu.net for information on retrieving files that way. +The "official" archive site for this software is www.ijg.org. +The most recent released version can always be found there in +directory "files". This particular version will be archived as +http://www.ijg.org/files/jpegsrc.v8b.tar.gz, and in Windows-compatible +"zip" archive format as http://www.ijg.org/files/jpegsr8b.zip. -Numerous Internet sites maintain copies of the UUNET files. However, only -ftp.uu.net is guaranteed to have the latest official version. - -You can also obtain this software in DOS-compatible "zip" archive format from -the SimTel archives (ftp://ftp.simtel.net/pub/simtelnet/msdos/graphics/), or -on CompuServe in the Graphics Support forum (GO CIS:GRAPHSUP), library 12 -"JPEG Tools". Again, these versions may sometimes lag behind the ftp.uu.net -release. - -The JPEG FAQ (Frequently Asked Questions) article is a useful source of -general information about JPEG. It is updated constantly and therefore is -not included in this distribution. The FAQ is posted every two weeks to -Usenet newsgroups comp.graphics.misc, news.answers, and other groups. +The JPEG FAQ (Frequently Asked Questions) article is a source of some +general information about JPEG. It is available on the World Wide Web at http://www.faqs.org/faqs/jpeg-faq/ and other news.answers archive sites, including the official news.answers archive at rtfm.mit.edu: ftp://rtfm.mit.edu/pub/usenet/news.answers/jpeg-faq/. @@ -307,79 +268,59 @@ with body send usenet/news.answers/jpeg-faq/part2 -RELATED SOFTWARE -================ +ACKNOWLEDGMENTS +=============== -Numerous viewing and image manipulation programs now support JPEG. (Quite a -few of them use this library to do so.) The JPEG FAQ described above lists -some of the more popular free and shareware viewers, and tells where to -obtain them on Internet. +Thank to Juergen Bruder for providing me with a copy of the common DCT +algorithm article, only to find out that I had come to the same result +in a more direct and comprehensible way with a more generative approach. -If you are on a Unix machine, we highly recommend Jef Poskanzer's free -PBMPLUS software, which provides many useful operations on PPM-format image -files. In particular, it can convert PPM images to and from a wide range of -other formats, thus making cjpeg/djpeg considerably more useful. The latest -version is distributed by the NetPBM group, and is available from numerous -sites, notably ftp://wuarchive.wustl.edu/graphics/graphics/packages/NetPBM/. -Unfortunately PBMPLUS/NETPBM is not nearly as portable as the IJG software is; -you are likely to have difficulty making it work on any non-Unix machine. +Thank to Istvan Sebestyen and Joan L. Mitchell for inviting me to the +ITU JPEG (Study Group 16) meeting in Geneva, Switzerland. -A different free JPEG implementation, written by the PVRG group at Stanford, -is available from ftp://havefun.stanford.edu/pub/jpeg/. This program -is designed for research and experimentation rather than production use; -it is slower, harder to use, and less portable than the IJG code, but it -is easier to read and modify. Also, the PVRG code supports lossless JPEG, -which we do not. (On the other hand, it doesn't do progressive JPEG.) +Thank to Thomas Wiegand and Gary Sullivan for inviting me to the +Joint Video Team (MPEG & ITU) meeting in Geneva, Switzerland. + +Thank to John Korejwa and Massimo Ballerini for inviting me to +fruitful consultations in Boston, MA and Milan, Italy. + +Thank to Hendrik Elstner, Roland Fassauer, Simone Zuck, Guenther +Maier-Gerber, Walter Stoeber, and Fred Schmitz for corresponding +business development. + +Thank to Nico Zschach and Dirk Stelling of the technical support team +at the Digital Images company in Halle for providing me with extra +equipment for configuration tests. + +Thank to Richard F. Lyon (then of Foveon Inc.) for fruitful +communication about JPEG configuration in Sigma Photo Pro software. + +Thank to Andrew Finkenstadt for hosting the ijg.org site. + +Last but not least special thank to Thomas G. Lane for the original +design and development of this singular software package. FILE FORMAT WARS ================ -Some JPEG programs produce files that are not compatible with our library. -The root of the problem is that the ISO JPEG committee failed to specify a -concrete file format. Some vendors "filled in the blanks" on their own, -creating proprietary formats that no one else could read. (For example, none -of the early commercial JPEG implementations for the Macintosh were able to -exchange compressed files.) - -The file format we have adopted is called JFIF (see REFERENCES). This format -has been agreed to by a number of major commercial JPEG vendors, and it has -become the de facto standard. JFIF is a minimal or "low end" representation. -We recommend the use of TIFF/JPEG (TIFF revision 6.0 as modified by TIFF -Technical Note #2) for "high end" applications that need to record a lot of -additional data about an image. TIFF/JPEG is fairly new and not yet widely -supported, unfortunately. - -The upcoming JPEG Part 3 standard defines a file format called SPIFF. -SPIFF is interoperable with JFIF, in the sense that most JFIF decoders should -be able to read the most common variant of SPIFF. SPIFF has some technical -advantages over JFIF, but its major claim to fame is simply that it is an -official standard rather than an informal one. At this point it is unclear -whether SPIFF will supersede JFIF or whether JFIF will remain the de-facto -standard. IJG intends to support SPIFF once the standard is frozen, but we -have not decided whether it should become our default output format or not. -(In any case, our decoder will remain capable of reading JFIF indefinitely.) - -Various proprietary file formats incorporating JPEG compression also exist. -We have little or no sympathy for the existence of these formats. Indeed, +The ISO JPEG standards committee actually promotes different formats like +"JPEG 2000" or "JPEG XR" which are incompatible with original DCT-based +JPEG and which are based on faulty technologies. IJG therefore does not +and will not support such momentary mistakes (see REFERENCES). +We have little or no sympathy for the promotion of these formats. Indeed, one of the original reasons for developing this free software was to help -force convergence on common, open format standards for JPEG files. Don't -use a proprietary file format! +force convergence on common, interoperable format standards for JPEG files. +Don't use an incompatible file format! +(In any case, our decoder will remain capable of reading existing JPEG +image files indefinitely.) TO DO ===== -The major thrust for v7 will probably be improvement of visual quality. -The current method for scaling the quantization tables is known not to be -very good at low Q values. We also intend to investigate block boundary -smoothing, "poor man's variable quantization", and other means of improving -quality-vs-file-size performance without sacrificing compatibility. +Version 8 is the first release of a new generation JPEG standard +to overcome the limitations of the original JPEG specification. +More features are being prepared for coming releases... -In future versions, we are considering supporting some of the upcoming JPEG -Part 3 extensions --- principally, variable quantization and the SPIFF file -format. - -As always, speeding things up is of great interest. - -Please send bug reports, offers of help, etc. to jpeg-info@uunet.uu.net. +Please send bug reports, offers of help, etc. to jpeg-info@uc.ag. diff --git a/reactos/dll/3rdparty/libjpeg/ansi2knr.c b/reactos/dll/3rdparty/libjpeg/ansi2knr.c index 4e05fc2d321..e84c210b66b 100644 --- a/reactos/dll/3rdparty/libjpeg/ansi2knr.c +++ b/reactos/dll/3rdparty/libjpeg/ansi2knr.c @@ -1,4 +1,6 @@ -/* ansi2knr.c */ +/* Copyright (C) 1989, 2000 Aladdin Enterprises. All rights reserved. */ + +/*$Id: ansi2knr.c,v 1.14 2003/09/06 05:36:56 eggert Exp $*/ /* Convert ANSI C function definitions to K&R ("traditional C") syntax */ /* @@ -11,10 +13,10 @@ License (the "GPL") for full details. Everyone is granted permission to copy, modify and redistribute ansi2knr, but only under the conditions described in the GPL. A copy of this license is supposed to have been given to you along with ansi2knr so you can know -your rights and responsibilities. It should be in a file named COPYLEFT. -[In the IJG distribution, the GPL appears below, not in a separate file.] -Among other things, the copyright notice and this notice must be preserved -on all copies. +your rights and responsibilities. It should be in a file named COPYLEFT, +or, if there is no file named COPYLEFT, a file named COPYING. Among other +things, the copyright notice and this notice must be preserved on all +copies. We explicitly state here what we believe is already implied by the GPL: if the ansi2knr program is distributed as a separate set of sources and a @@ -25,205 +27,105 @@ constructing it invoke the ansi2knr executable bring any other part of the program under the GPL. */ -/* ----------- Here is the GNU GPL file COPYLEFT, referred to above ---------- ------ These terms do NOT apply to the JPEG software itself; see README ------ - - GHOSTSCRIPT GENERAL PUBLIC LICENSE - (Clarified 11 Feb 1988) - - Copyright (C) 1988 Richard M. Stallman - Everyone is permitted to copy and distribute verbatim copies of this - license, but changing it is not allowed. You can also use this wording - to make the terms for other programs. - - The license agreements of most software companies keep you at the -mercy of those companies. By contrast, our general public license is -intended to give everyone the right to share Ghostscript. To make sure -that you get the rights we want you to have, we need to make -restrictions that forbid anyone to deny you these rights or to ask you -to surrender the rights. Hence this license agreement. - - Specifically, we want to make sure that you have the right to give -away copies of Ghostscript, that you receive source code or else can get -it if you want it, that you can change Ghostscript or use pieces of it -in new free programs, and that you know you can do these things. - - To make sure that everyone has such rights, we have to forbid you to -deprive anyone else of these rights. For example, if you distribute -copies of Ghostscript, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must tell them their rights. - - Also, for our own protection, we must make certain that everyone finds -out that there is no warranty for Ghostscript. If Ghostscript is -modified by someone else and passed on, we want its recipients to know -that what they have is not what we distributed, so that any problems -introduced by others will not reflect on our reputation. - - Therefore we (Richard M. Stallman and the Free Software Foundation, -Inc.) make the following terms which say what you must do to be allowed -to distribute or change Ghostscript. - - - COPYING POLICIES - - 1. You may copy and distribute verbatim copies of Ghostscript source -code as you receive it, in any medium, provided that you conspicuously -and appropriately publish on each copy a valid copyright and license -notice "Copyright (C) 1989 Aladdin Enterprises. All rights reserved. -Distributed by Free Software Foundation, Inc." (or with whatever year is -appropriate); keep intact the notices on all files that refer to this -License Agreement and to the absence of any warranty; and give any other -recipients of the Ghostscript program a copy of this License Agreement -along with the program. You may charge a distribution fee for the -physical act of transferring a copy. - - 2. You may modify your copy or copies of Ghostscript or any portion of -it, and copy and distribute such modifications under the terms of -Paragraph 1 above, provided that you also do the following: - - a) cause the modified files to carry prominent notices stating - that you changed the files and the date of any change; and - - b) cause the whole of any work that you distribute or publish, - that in whole or in part contains or is a derivative of Ghostscript - or any part thereof, to be licensed at no charge to all third - parties on terms identical to those contained in this License - Agreement (except that you may choose to grant more extensive - warranty protection to some or all third parties, at your option). - - c) You may charge a distribution fee for the physical act of - transferring a copy, and you may at your option offer warranty - protection in exchange for a fee. - -Mere aggregation of another unrelated program with this program (or its -derivative) on a volume of a storage or distribution medium does not bring -the other program under the scope of these terms. - - 3. You may copy and distribute Ghostscript (or a portion or derivative -of it, under Paragraph 2) in object code or executable form under the -terms of Paragraphs 1 and 2 above provided that you also do one of the -following: - - a) accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of - Paragraphs 1 and 2 above; or, - - b) accompany it with a written offer, valid for at least three - years, to give any third party free (except for a nominal - shipping charge) a complete machine-readable copy of the - corresponding source code, to be distributed under the terms of - Paragraphs 1 and 2 above; or, - - c) accompany it with the information you received as to where the - corresponding source code may be obtained. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form alone.) - -For an executable file, complete source code means all the source code for -all modules it contains; but, as a special exception, it need not include -source code for modules which are standard libraries that accompany the -operating system on which the executable file runs. - - 4. You may not copy, sublicense, distribute or transfer Ghostscript -except as expressly provided under this License Agreement. Any attempt -otherwise to copy, sublicense, distribute or transfer Ghostscript is -void and your rights to use the program under this License agreement -shall be automatically terminated. However, parties who have received -computer software programs from you with this License Agreement will not -have their licenses terminated so long as such parties remain in full -compliance. - - 5. If you wish to incorporate parts of Ghostscript into other free -programs whose distribution conditions are different, write to the Free -Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not -yet worked out a simple rule that can be stated here, but we will often -permit this. We will be guided by the two goals of preserving the free -status of all derivatives of our free software and of promoting the -sharing and reuse of software. - -Your comments and suggestions about our licensing policies and our -software are welcome! Please contact the Free Software Foundation, -Inc., 675 Mass Ave, Cambridge, MA 02139, or call (617) 876-3296. - - NO WARRANTY - - BECAUSE GHOSTSCRIPT IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY -NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT -WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC, RICHARD -M. STALLMAN, ALADDIN ENTERPRISES, L. PETER DEUTSCH, AND/OR OTHER PARTIES -PROVIDE GHOSTSCRIPT "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER -EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE -ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF GHOSTSCRIPT IS WITH -YOU. SHOULD GHOSTSCRIPT PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL -NECESSARY SERVICING, REPAIR OR CORRECTION. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M. -STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., L. PETER DEUTSCH, ALADDIN -ENTERPRISES, AND/OR ANY OTHER PARTY WHO MAY MODIFY AND REDISTRIBUTE -GHOSTSCRIPT AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING -ANY LOST PROFITS, LOST MONIES, OR OTHER SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE -(INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED -INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A FAILURE OF THE -PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) GHOSTSCRIPT, EVEN IF YOU -HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM -BY ANY OTHER PARTY. - --------------------- End of file COPYLEFT ------------------------------ -*/ - /* * Usage: - ansi2knr input_file [output_file] + ansi2knr [--filename FILENAME] [INPUT_FILE [OUTPUT_FILE]] + * --filename provides the file name for the #line directive in the output, + * overriding input_file (if present). + * If no input_file is supplied, input is read from stdin. * If no output_file is supplied, output goes to stdout. * There are no error messages. * * ansi2knr recognizes function definitions by seeing a non-keyword - * identifier at the left margin, followed by a left parenthesis, - * with a right parenthesis as the last character on the line, - * and with a left brace as the first token on the following line - * (ignoring possible intervening comments). - * It will recognize a multi-line header provided that no intervening - * line ends with a left or right brace or a semicolon. - * These algorithms ignore whitespace and comments, except that - * the function name must be the first thing on the line. - * The following constructs will confuse it: + * identifier at the left margin, followed by a left parenthesis, with a + * right parenthesis as the last character on the line, and with a left + * brace as the first token on the following line (ignoring possible + * intervening comments and/or preprocessor directives), except that a line + * consisting of only + * identifier1(identifier2) + * will not be considered a function definition unless identifier2 is + * the word "void", and a line consisting of + * identifier1(identifier2, <>) + * will not be considered a function definition. + * ansi2knr will recognize a multi-line header provided that no intervening + * line ends with a left or right brace or a semicolon. These algorithms + * ignore whitespace, comments, and preprocessor directives, except that + * the function name must be the first thing on the line. The following + * constructs will confuse it: * - Any other construct that starts at the left margin and * follows the above syntax (such as a macro or function call). - * - Some macros that tinker with the syntax of the function header. + * - Some macros that tinker with the syntax of function headers. */ /* * The original and principal author of ansi2knr is L. Peter Deutsch * . Other authors are noted in the change history * that follows (in reverse chronological order): - lpd 96-01-21 added code to cope with not HAVE_CONFIG_H and with + + lpd 2000-04-12 backs out Eggert's changes because of bugs: + - concatlits didn't declare the type of its bufend argument; + - concatlits didn't recognize when it was inside a comment; + - scanstring could scan backward past the beginning of the string; when + - the check for \ + newline in scanstring was unnecessary. + + 2000-03-05 Paul Eggert + + Add support for concatenated string literals. + * ansi2knr.c (concatlits): New decl. + (main): Invoke concatlits to concatenate string literals. + (scanstring): Handle backslash-newline correctly. Work with + character constants. Fix bug when scanning backwards through + backslash-quote. Check for unterminated strings. + (convert1): Parse character constants, too. + (appendline, concatlits): New functions. + * ansi2knr.1: Document this. + + lpd 1999-08-17 added code to allow preprocessor directives + wherever comments are allowed + lpd 1999-04-12 added minor fixes from Pavel Roskin + for clean compilation with + gcc -W -Wall + lpd 1999-03-22 added hack to recognize lines consisting of + identifier1(identifier2, xxx) as *not* being procedures + lpd 1999-02-03 made indentation of preprocessor commands consistent + lpd 1999-01-28 fixed two bugs: a '/' in an argument list caused an + endless loop; quoted strings within an argument list + confused the parser + lpd 1999-01-24 added a check for write errors on the output, + suggested by Jim Meyering + lpd 1998-11-09 added further hack to recognize identifier(void) + as being a procedure + lpd 1998-10-23 added hack to recognize lines consisting of + identifier1(identifier2) as *not* being procedures + lpd 1997-12-08 made input_file optional; only closes input and/or + output file if not stdin or stdout respectively; prints + usage message on stderr rather than stdout; adds + --filename switch (changes suggested by + ) + lpd 1996-01-21 added code to cope with not HAVE_CONFIG_H and with compilers that don't understand void, as suggested by Tom Lane - lpd 96-01-15 changed to require that the first non-comment token + lpd 1996-01-15 changed to require that the first non-comment token on the line following a function header be a left brace, to reduce sensitivity to macros, as suggested by Tom Lane - lpd 95-06-22 removed #ifndefs whose sole purpose was to define + lpd 1995-06-22 removed #ifndefs whose sole purpose was to define undefined preprocessor symbols as 0; changed all #ifdefs for configuration symbols to #ifs - lpd 95-04-05 changed copyright notice to make it clear that + lpd 1995-04-05 changed copyright notice to make it clear that including ansi2knr in a program does not bring the entire program under the GPL - lpd 94-12-18 added conditionals for systems where ctype macros + lpd 1994-12-18 added conditionals for systems where ctype macros don't handle 8-bit characters properly, suggested by Francois Pinard ; removed --varargs switch (this is now the default) - lpd 94-10-10 removed CONFIG_BROKETS conditional - lpd 94-07-16 added some conditionals to help GNU `configure', + lpd 1994-10-10 removed CONFIG_BROKETS conditional + lpd 1994-07-16 added some conditionals to help GNU `configure', suggested by Francois Pinard ; properly erase prototype args in function parameters, contributed by Jim Avera ; correct error in writeblanks (it shouldn't erase EOLs) - lpd 89-xx-xx original version + lpd 1989-xx-xx original version */ /* Most of the conditionals here are to make ansi2knr work with */ @@ -286,19 +188,24 @@ BY ANY OTHER PARTY. #endif +/* Define NULL (for *very* old compilers). */ +#ifndef NULL +# define NULL (0) +#endif + /* * The ctype macros don't always handle 8-bit characters correctly. * Compensate for this here. */ #ifdef isascii -# undef HAVE_ISASCII /* just in case */ -# define HAVE_ISASCII 1 +# undef HAVE_ISASCII /* just in case */ +# define HAVE_ISASCII 1 #else #endif #if STDC_HEADERS || !HAVE_ISASCII -# define is_ascii(c) 1 +# define is_ascii(c) 1 #else -# define is_ascii(c) isascii(c) +# define is_ascii(c) isascii(c) #endif #define is_space(c) (is_ascii(c) && isspace(c)) @@ -310,7 +217,10 @@ BY ANY OTHER PARTY. #define isidfirstchar(ch) (is_alpha(ch) || (ch) == '_') /* Forward references */ +char *ppdirforward(); +char *ppdirbackward(); char *skipspace(); +char *scanstring(); int writeblanks(); int test1(); int convert1(); @@ -320,11 +230,17 @@ int main(argc, argv) int argc; char *argv[]; -{ FILE *in, *out; +{ FILE *in = stdin; + FILE *out = stdout; + char *filename = 0; + char *program_name = argv[0]; + char *output_name = 0; #define bufsize 5000 /* arbitrary size */ char *buf; char *line; char *more; + char *usage = + "Usage: ansi2knr [--filename FILENAME] [INPUT_FILE [OUTPUT_FILE]]\n"; /* * In previous versions, ansi2knr recognized a --varargs switch. * If this switch was supplied, ansi2knr would attempt to convert @@ -334,40 +250,61 @@ main(argc, argv) * check for this switch for backward compatibility. */ int convert_varargs = 1; + int output_error; - if ( argc > 1 && argv[1][0] == '-' ) - { if ( !strcmp(argv[1], "--varargs") ) - { convert_varargs = 1; - argc--; - argv++; - } - else - { fprintf(stderr, "Unrecognized switch: %s\n", argv[1]); - exit(1); - } + while ( argc > 1 && argv[1][0] == '-' ) { + if ( !strcmp(argv[1], "--varargs") ) { + convert_varargs = 1; + argc--; + argv++; + continue; } + if ( !strcmp(argv[1], "--filename") && argc > 2 ) { + filename = argv[2]; + argc -= 2; + argv += 2; + continue; + } + fprintf(stderr, "%s: Unrecognized switch: %s\n", program_name, + argv[1]); + fprintf(stderr, usage); + exit(1); + } switch ( argc ) { default: - printf("Usage: ansi2knr input_file [output_file]\n"); + fprintf(stderr, usage); exit(0); - case 2: - out = stdout; - break; case 3: - out = fopen(argv[2], "w"); - if ( out == NULL ) - { fprintf(stderr, "Cannot open output file %s\n", argv[2]); - exit(1); - } + output_name = argv[2]; + out = fopen(output_name, "w"); + if ( out == NULL ) { + fprintf(stderr, "%s: Cannot open output file %s\n", + program_name, output_name); + exit(1); + } + /* falls through */ + case 2: + in = fopen(argv[1], "r"); + if ( in == NULL ) { + fprintf(stderr, "%s: Cannot open input file %s\n", + program_name, argv[1]); + exit(1); + } + if ( filename == 0 ) + filename = argv[1]; + /* falls through */ + case 1: + break; } - in = fopen(argv[1], "r"); - if ( in == NULL ) - { fprintf(stderr, "Cannot open input file %s\n", argv[1]); + if ( filename ) + fprintf(out, "#line 1 \"%s\"\n", filename); + buf = malloc(bufsize); + if ( buf == NULL ) + { + fprintf(stderr, "Unable to allocate read buffer!\n"); exit(1); } - fprintf(out, "#line 1 \"%s\"\n", argv[1]); - buf = malloc(bufsize); line = buf; while ( fgets(line, (unsigned)(buf + bufsize - line), in) != NULL ) { @@ -384,7 +321,7 @@ f: if ( line >= buf + (bufsize - 1) ) /* overflow check */ goto wl; if ( fgets(line, (unsigned)(buf + bufsize - line), in) == NULL ) goto wl; - switch ( *skipspace(more, 1) ) + switch ( *skipspace(ppdirforward(more), 1) ) { case '{': /* Definitely a function header. */ @@ -418,30 +355,91 @@ wl: fputs(buf, out); if ( line != buf ) fputs(buf, out); free(buf); - fclose(out); - fclose(in); + if ( output_name ) { + output_error = ferror(out); + output_error |= fclose(out); + } else { /* out == stdout */ + fflush(out); + output_error = ferror(out); + } + if ( output_error ) { + fprintf(stderr, "%s: error writing to %s\n", program_name, + (output_name ? output_name : "stdout")); + exit(1); + } + if ( in != stdin ) + fclose(in); return 0; } -/* Skip over space and comments, in either direction. */ +/* + * Skip forward or backward over one or more preprocessor directives. + */ +char * +ppdirforward(p) + char *p; +{ + for (; *p == '#'; ++p) { + for (; *p != '\r' && *p != '\n'; ++p) + if (*p == 0) + return p; + if (*p == '\r' && p[1] == '\n') + ++p; + } + return p; +} +char * +ppdirbackward(p, limit) + char *p; + char *limit; +{ + char *np = p; + + for (;; p = --np) { + if (*np == '\n' && np[-1] == '\r') + --np; + for (; np > limit && np[-1] != '\r' && np[-1] != '\n'; --np) + if (np[-1] == 0) + return np; + if (*np != '#') + return p; + } +} + +/* + * Skip over whitespace, comments, and preprocessor directives, + * in either direction. + */ char * skipspace(p, dir) - register char *p; - register int dir; /* 1 for forward, -1 for backward */ -{ for ( ; ; ) - { while ( is_space(*p) ) - p += dir; - if ( !(*p == '/' && p[dir] == '*') ) - break; - p += dir; p += dir; - while ( !(*p == '*' && p[dir] == '/') ) - { if ( *p == 0 ) - return p; /* multi-line comment?? */ - p += dir; - } - p += dir; p += dir; - } - return p; + char *p; + int dir; /* 1 for forward, -1 for backward */ +{ + for ( ; ; ) { + while ( is_space(*p) ) + p += dir; + if ( !(*p == '/' && p[dir] == '*') ) + break; + p += dir; p += dir; + while ( !(*p == '*' && p[dir] == '/') ) { + if ( *p == 0 ) + return p; /* multi-line comment?? */ + p += dir; + } + p += dir; p += dir; + } + return p; +} + +/* Scan over a quoted string, in either direction. */ +char * +scanstring(p, dir) + char *p; + int dir; +{ + for (p += dir; ; p += dir) + if (*p == '"' && p[-dir] != '\\') + return p + dir; } /* @@ -475,14 +473,14 @@ writeblanks(start, end) int test1(buf) char *buf; -{ register char *p = buf; +{ char *p = buf; char *bend; char *endfn; int contin; if ( !isidfirstchar(*p) ) return 0; /* no name at left margin */ - bend = skipspace(buf + strlen(buf) - 1, -1); + bend = skipspace(ppdirbackward(buf + strlen(buf) - 1, buf), -1); switch ( *bend ) { case ';': contin = 0 /*2*/; break; @@ -512,7 +510,7 @@ test1(buf) }; char **key = words; char *kp; - int len = endfn - buf; + unsigned len = endfn - buf; while ( (kp = *key) != 0 ) { if ( strlen(kp) == len && !strncmp(kp, buf, len) ) @@ -520,6 +518,36 @@ test1(buf) key++; } } + { + char *id = p; + int len; + /* + * Check for identifier1(identifier2) and not + * identifier1(void), or identifier1(identifier2, xxxx). + */ + + while ( isidchar(*p) ) + p++; + len = p - id; + p = skipspace(p, 1); + if (*p == ',' || + (*p == ')' && (len != 4 || strncmp(id, "void", 4))) + ) + return 0; /* not a function */ + } + /* + * If the last significant character was a ), we need to count + * parentheses, because it might be part of a formal parameter + * that is a procedure. + */ + if (contin > 0) { + int level = 0; + + for (p = skipspace(buf, 1); *p; p = skipspace(p + 1, 1)) + level += (*p == '(' ? 1 : *p == ')' ? -1 : 0); + if (level > 0) + contin = -1; + } return contin; } @@ -531,7 +559,11 @@ convert1(buf, out, header, convert_varargs) int header; /* Boolean */ int convert_varargs; /* Boolean */ { char *endfn; - register char *p; + char *p; + /* + * The breaks table contains pointers to the beginning and end + * of each argument. + */ char **breaks; unsigned num_breaks = 2; /* for testing */ char **btop; @@ -545,7 +577,7 @@ convert1(buf, out, header, convert_varargs) ; top: p = endfn; breaks = (char **)malloc(sizeof(char *) * num_breaks * 2); - if ( breaks == 0 ) + if ( breaks == NULL ) { /* Couldn't allocate break table, give up */ fprintf(stderr, "Unable to allocate break table!\n"); fputs(buf, out); @@ -557,7 +589,7 @@ top: p = endfn; do { int level = 0; char *lp = NULL; - char *rp; + char *rp = NULL; char *end = NULL; if ( bp >= btop ) @@ -584,14 +616,18 @@ top: p = endfn; else rp = p; break; case '/': - p = skipspace(p, 1) - 1; + if (p[1] == '*') + p = skipspace(p, 1) - 1; break; + case '"': + p = scanstring(p, 1) - 1; + break; default: ; } } /* Erase any embedded prototype parameters. */ - if ( lp ) + if ( lp && rp ) writeblanks(lp + 1, rp); p--; /* back up over terminator */ /* Find the name being declared. */ @@ -607,9 +643,19 @@ top: p = endfn; while ( level ) switch ( *--p ) { - case ']': case ')': level++; break; - case '[': case '(': level--; break; - case '/': p = skipspace(p, -1) + 1; break; + case ']': case ')': + level++; + break; + case '[': case '(': + level--; + break; + case '/': + if (p > buf && p[-1] == '*') + p = skipspace(p, -1) + 1; + break; + case '"': + p = scanstring(p, -1) + 1; + break; default: ; } } diff --git a/reactos/dll/3rdparty/libjpeg/cderror.h b/reactos/dll/3rdparty/libjpeg/cderror.h index 70435e161c0..e19c475c5c5 100644 --- a/reactos/dll/3rdparty/libjpeg/cderror.h +++ b/reactos/dll/3rdparty/libjpeg/cderror.h @@ -2,6 +2,7 @@ * cderror.h * * Copyright (C) 1994-1997, Thomas G. Lane. + * Modified 2009 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -45,6 +46,7 @@ JMESSAGE(JERR_BMP_BADHEADER, "Invalid BMP file: bad header length") JMESSAGE(JERR_BMP_BADPLANES, "Invalid BMP file: biPlanes not equal to 1") JMESSAGE(JERR_BMP_COLORSPACE, "BMP output must be grayscale or RGB") JMESSAGE(JERR_BMP_COMPRESSED, "Sorry, compressed BMPs not yet supported") +JMESSAGE(JERR_BMP_EMPTY, "Empty BMP image") JMESSAGE(JERR_BMP_NOT, "Not a BMP file - does not start with BM") JMESSAGE(JTRC_BMP, "%ux%u 24-bit BMP image") JMESSAGE(JTRC_BMP_MAPPED, "%ux%u 8-bit colormapped BMP image") diff --git a/reactos/dll/3rdparty/libjpeg/cdjpeg.h b/reactos/dll/3rdparty/libjpeg/cdjpeg.h index a9abd5471c5..ed024ac3ae8 100644 --- a/reactos/dll/3rdparty/libjpeg/cdjpeg.h +++ b/reactos/dll/3rdparty/libjpeg/cdjpeg.h @@ -104,6 +104,7 @@ typedef struct cdjpeg_progress_mgr * cd_progress_ptr; #define jinit_write_targa jIWrTarga #define read_quant_tables RdQTables #define read_scan_script RdScnScript +#define set_quality_ratings SetQRates #define set_quant_slots SetQSlots #define set_sample_factors SetSFacts #define read_color_map RdCMap @@ -116,39 +117,41 @@ typedef struct cdjpeg_progress_mgr * cd_progress_ptr; /* Module selection routines for I/O modules. */ -EXTERN_1(cjpeg_source_ptr) jinit_read_bmp JPP((j_compress_ptr cinfo)); -EXTERN_1(djpeg_dest_ptr) jinit_write_bmp JPP((j_decompress_ptr cinfo, +EXTERN(cjpeg_source_ptr) jinit_read_bmp JPP((j_compress_ptr cinfo)); +EXTERN(djpeg_dest_ptr) jinit_write_bmp JPP((j_decompress_ptr cinfo, boolean is_os2)); -EXTERN_1(cjpeg_source_ptr) jinit_read_gif JPP((j_compress_ptr cinfo)); -EXTERN_1(djpeg_dest_ptr) jinit_write_gif JPP((j_decompress_ptr cinfo)); -EXTERN_1(cjpeg_source_ptr) jinit_read_ppm JPP((j_compress_ptr cinfo)); -EXTERN_1(djpeg_dest_ptr) jinit_write_ppm JPP((j_decompress_ptr cinfo)); -EXTERN_1(cjpeg_source_ptr) jinit_read_rle JPP((j_compress_ptr cinfo)); -EXTERN_1(djpeg_dest_ptr) jinit_write_rle JPP((j_decompress_ptr cinfo)); -EXTERN_1(cjpeg_source_ptr) jinit_read_targa JPP((j_compress_ptr cinfo)); -EXTERN_1(djpeg_dest_ptr) jinit_write_targa JPP((j_decompress_ptr cinfo)); +EXTERN(cjpeg_source_ptr) jinit_read_gif JPP((j_compress_ptr cinfo)); +EXTERN(djpeg_dest_ptr) jinit_write_gif JPP((j_decompress_ptr cinfo)); +EXTERN(cjpeg_source_ptr) jinit_read_ppm JPP((j_compress_ptr cinfo)); +EXTERN(djpeg_dest_ptr) jinit_write_ppm JPP((j_decompress_ptr cinfo)); +EXTERN(cjpeg_source_ptr) jinit_read_rle JPP((j_compress_ptr cinfo)); +EXTERN(djpeg_dest_ptr) jinit_write_rle JPP((j_decompress_ptr cinfo)); +EXTERN(cjpeg_source_ptr) jinit_read_targa JPP((j_compress_ptr cinfo)); +EXTERN(djpeg_dest_ptr) jinit_write_targa JPP((j_decompress_ptr cinfo)); /* cjpeg support routines (in rdswitch.c) */ -EXTERN_1(boolean) read_quant_tables JPP((j_compress_ptr cinfo, char * filename, - int scale_factor, boolean force_baseline)); -EXTERN_1(boolean) read_scan_script JPP((j_compress_ptr cinfo, char * filename)); -EXTERN_1(boolean) set_quant_slots JPP((j_compress_ptr cinfo, char *arg)); -EXTERN_1(boolean) set_sample_factors JPP((j_compress_ptr cinfo, char *arg)); +EXTERN(boolean) read_quant_tables JPP((j_compress_ptr cinfo, char * filename, + boolean force_baseline)); +EXTERN(boolean) read_scan_script JPP((j_compress_ptr cinfo, char * filename)); +EXTERN(boolean) set_quality_ratings JPP((j_compress_ptr cinfo, char *arg, + boolean force_baseline)); +EXTERN(boolean) set_quant_slots JPP((j_compress_ptr cinfo, char *arg)); +EXTERN(boolean) set_sample_factors JPP((j_compress_ptr cinfo, char *arg)); /* djpeg support routines (in rdcolmap.c) */ -EXTERN_1(void) read_color_map JPP((j_decompress_ptr cinfo, FILE * infile)); +EXTERN(void) read_color_map JPP((j_decompress_ptr cinfo, FILE * infile)); /* common support routines (in cdjpeg.c) */ -EXTERN_1(void) enable_signal_catcher JPP((j_common_ptr cinfo)); -EXTERN_1(void) start_progress_monitor JPP((j_common_ptr cinfo, +EXTERN(void) enable_signal_catcher JPP((j_common_ptr cinfo)); +EXTERN(void) start_progress_monitor JPP((j_common_ptr cinfo, cd_progress_ptr progress)); -EXTERN_1(void) end_progress_monitor JPP((j_common_ptr cinfo)); -EXTERN_1(boolean) keymatch JPP((char * arg, const char * keyword, int minchars)); -EXTERN_1(FILE *) read_stdin JPP((void)); -EXTERN_1(FILE *) write_stdout JPP((void)); +EXTERN(void) end_progress_monitor JPP((j_common_ptr cinfo)); +EXTERN(boolean) keymatch JPP((char * arg, const char * keyword, int minchars)); +EXTERN(FILE *) read_stdin JPP((void)); +EXTERN(FILE *) write_stdout JPP((void)); /* miscellaneous useful macros */ diff --git a/reactos/dll/3rdparty/libjpeg/change.log b/reactos/dll/3rdparty/libjpeg/change.log index 74102c0db5a..f99a867dbb8 100644 --- a/reactos/dll/3rdparty/libjpeg/change.log +++ b/reactos/dll/3rdparty/libjpeg/change.log @@ -1,6 +1,104 @@ CHANGE LOG for Independent JPEG Group's JPEG software +Version 8b 16-May-2010 +----------------------- + +Repair problem in new memory source manager with corrupt JPEG data. +Thank to Ted Campbell and Samuel Chun for the report. + +Repair problem in Makefile.am test target. +Thank to anonymous user for the report. + +Support MinGW installation with automatic configure. +Thank to Volker Grabsch for the suggestion. + + +Version 8a 28-Feb-2010 +----------------------- + +Writing tables-only datastreams via jpeg_write_tables works again. + +Support 32-bit BMPs (RGB image with Alpha channel) for read in cjpeg. +Thank to Brett Blackham for the suggestion. + +Improve accuracy in floating point IDCT calculation. +Thank to Robert Hooke for the hint. + + +Version 8 10-Jan-2010 +---------------------- + +jpegtran now supports the same -scale option as djpeg for "lossless" resize. +An implementation of the JPEG SmartScale extension is required for this +feature. A (draft) specification of the JPEG SmartScale extension is +available as a contributed document at ITU and ISO. Revision 2 or later +of the document is required (latest document version is Revision 3). +The SmartScale extension will enable more features beside lossless resize +in future implementations, as described in the document (new compression +options). + +Add sanity check in BMP reader module to avoid cjpeg crash for empty input +image (thank to Isaev Ildar of ISP RAS, Moscow, RU for reporting this error). + +Add data source and destination managers for read from and write to +memory buffers. New API functions jpeg_mem_src and jpeg_mem_dest. +Thank to Roberto Boni from Italy for the suggestion. + + +Version 7 27-Jun-2009 +---------------------- + +New scaled DCTs implemented. +djpeg now supports scalings N/8 with all N from 1 to 16. +cjpeg now supports scalings 8/N with all N from 1 to 16. +Scaled DCTs with size larger than 8 are now also used for resolving the +common 2x2 chroma subsampling case without additional spatial resampling. +Separate spatial resampling for those kind of files is now only necessary +for N>8 scaling cases. +Furthermore, separate scaled DCT functions are provided for direct resolving +of the common asymmetric subsampling cases (2x1 and 1x2) without additional +spatial resampling. + +cjpeg -quality option has been extended for support of separate quality +settings for luminance and chrominance (or in general, for every provided +quantization table slot). +New API function jpeg_default_qtables() and q_scale_factor array in library. + +Added -nosmooth option to cjpeg, complementary to djpeg. +New variable "do_fancy_downsampling" in library, complement to fancy +upsampling. Fancy upsampling now uses direct DCT scaling with sizes +larger than 8. The old method is not reversible and has been removed. + +Support arithmetic entropy encoding and decoding. +Added files jaricom.c, jcarith.c, jdarith.c. + +Straighten the file structure: +Removed files jidctred.c, jcphuff.c, jchuff.h, jdphuff.c, jdhuff.h. + +jpegtran has a new "lossless" cropping feature. + +Implement -perfect option in jpegtran, new API function +jtransform_perfect_transform() in transupp. (DP 204_perfect.dpatch) + +Better error messages for jpegtran fopen failure. +(DP 203_jpegtran_errmsg.dpatch) + +Fix byte order issue with 16bit PPM/PGM files in rdppm.c/wrppm.c: +according to Netpbm, the de facto standard implementation of the PNM formats, +the most significant byte is first. (DP 203_rdppm.dpatch) + +Add -raw option to rdjpgcom not to mangle the output. +(DP 205_rdjpgcom_raw.dpatch) + +Make rdjpgcom locale aware. (DP 201_rdjpgcom_locale.dpatch) + +Add extern "C" to jpeglib.h. +This avoids the need to put extern "C" { ... } around #include "jpeglib.h" +in your C++ application. Defining the symbol DONT_USE_EXTERN_C in the +configuration prevents this. (DP 202_jpeglib.h_c++.dpatch) + + Version 6b 27-Mar-1998 ----------------------- diff --git a/reactos/dll/3rdparty/libjpeg/cjpeg.c b/reactos/dll/3rdparty/libjpeg/cjpeg.c index f2a929f0c9f..b9d57eb5c86 100644 --- a/reactos/dll/3rdparty/libjpeg/cjpeg.c +++ b/reactos/dll/3rdparty/libjpeg/cjpeg.c @@ -2,6 +2,7 @@ * cjpeg.c * * Copyright (C) 1991-1998, Thomas G. Lane. + * Modified 2003-2008 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -149,7 +150,7 @@ usage (void) #endif fprintf(stderr, "Switches (names may be abbreviated):\n"); - fprintf(stderr, " -quality N Compression quality (0..100; 5-95 is useful range)\n"); + fprintf(stderr, " -quality N[,...] Compression quality (0..100; 5-95 is useful range)\n"); fprintf(stderr, " -grayscale Create monochrome JPEG file\n"); #ifdef ENTROPY_OPT_SUPPORTED fprintf(stderr, " -optimize Optimize Huffman table (smaller file, but slow compression)\n"); @@ -157,6 +158,9 @@ usage (void) #ifdef C_PROGRESSIVE_SUPPORTED fprintf(stderr, " -progressive Create progressive JPEG file\n"); #endif +#ifdef DCT_SCALING_SUPPORTED + fprintf(stderr, " -scale M/N Scale image by fraction M/N, eg, 1/2\n"); +#endif #ifdef TARGA_SUPPORTED fprintf(stderr, " -targa Input file is Targa format (usually not needed)\n"); #endif @@ -173,6 +177,7 @@ usage (void) fprintf(stderr, " -dct float Use floating-point DCT method%s\n", (JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : "")); #endif + fprintf(stderr, " -nosmooth Don't use high-quality downsampling\n"); fprintf(stderr, " -restart N Set restart interval in rows, or in blocks with B\n"); #ifdef INPUT_SMOOTHING_SUPPORTED fprintf(stderr, " -smooth N Smooth dithered input (N=1..100 is strength)\n"); @@ -209,21 +214,16 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv, { int argn; char * arg; - int quality; /* -quality parameter */ - int q_scale_factor; /* scaling percentage for -qtables */ boolean force_baseline; boolean simple_progressive; + char * qualityarg = NULL; /* saves -quality parm if any */ char * qtablefile = NULL; /* saves -qtables filename if any */ char * qslotsarg = NULL; /* saves -qslots parm if any */ char * samplearg = NULL; /* saves -sample parm if any */ char * scansarg = NULL; /* saves -scans parm if any */ /* Set up default JPEG parameters. */ - /* Note that default -quality level need not, and does not, - * match the default scaling for an explicit -qtables argument. - */ - quality = 75; /* default -quality value */ - q_scale_factor = 100; /* default to no scaling for -qtables */ + force_baseline = FALSE; /* by default, allow 16-bit quantizers */ simple_progressive = FALSE; is_targa = FALSE; @@ -300,6 +300,10 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv, lval *= 1000L; cinfo->mem->max_memory_to_use = lval * 1000L; + } else if (keymatch(arg, "nosmooth", 3)) { + /* Suppress fancy downsampling */ + cinfo->do_fancy_downsampling = FALSE; + } else if (keymatch(arg, "optimize", 1) || keymatch(arg, "optimise", 1)) { /* Enable entropy parm optimization. */ #ifdef ENTROPY_OPT_SUPPORTED @@ -328,13 +332,10 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv, #endif } else if (keymatch(arg, "quality", 1)) { - /* Quality factor (quantization table scaling factor). */ + /* Quality ratings (quantization table scaling factors). */ if (++argn >= argc) /* advance to next argument */ usage(); - if (sscanf(argv[argn], "%d", &quality) != 1) - usage(); - /* Change scale factor in case -qtables is present. */ - q_scale_factor = jpeg_quality_scaling(quality); + qualityarg = argv[argn]; } else if (keymatch(arg, "qslots", 2)) { /* Quantization table slot numbers. */ @@ -382,7 +383,15 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv, * default sampling factors. */ - } else if (keymatch(arg, "scans", 2)) { + } else if (keymatch(arg, "scale", 4)) { + /* Scale the image by a fraction M/N. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + if (sscanf(argv[argn], "%d/%d", + &cinfo->scale_num, &cinfo->scale_denom) != 2) + usage(); + + } else if (keymatch(arg, "scans", 4)) { /* Set scan script. */ #ifdef C_MULTISCAN_FILES_SUPPORTED if (++argn >= argc) /* advance to next argument */ @@ -422,11 +431,12 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv, /* Set quantization tables for selected quality. */ /* Some or all may be overridden if -qtables is present. */ - jpeg_set_quality(cinfo, quality, force_baseline); + if (qualityarg != NULL) /* process -quality if it was present */ + if (! set_quality_ratings(cinfo, qualityarg, force_baseline)) + usage(); if (qtablefile != NULL) /* process -qtables if it was present */ - if (! read_quant_tables(cinfo, qtablefile, - q_scale_factor, force_baseline)) + if (! read_quant_tables(cinfo, qtablefile, force_baseline)) usage(); if (qslotsarg != NULL) /* process -qslots if it was present */ diff --git a/reactos/dll/3rdparty/libjpeg/ckconfig.c b/reactos/dll/3rdparty/libjpeg/ckconfig.c index 34baf795b00..e658623fa5e 100644 --- a/reactos/dll/3rdparty/libjpeg/ckconfig.c +++ b/reactos/dll/3rdparty/libjpeg/ckconfig.c @@ -301,7 +301,7 @@ int main (argc, argv) /* Write out all the info */ fprintf(outfile, "/* jconfig.h --- generated by ckconfig.c */\n"); - fprintf(outfile, "/* see jconfig.doc for explanations */\n\n"); + fprintf(outfile, "/* see jconfig.txt for explanations */\n\n"); #ifdef HAVE_PROTOTYPES fprintf(outfile, "#define HAVE_PROTOTYPES\n"); #else diff --git a/reactos/dll/3rdparty/libjpeg/djpeg.c b/reactos/dll/3rdparty/libjpeg/djpeg.c index da1fcc76c65..bc544dc1017 100644 --- a/reactos/dll/3rdparty/libjpeg/djpeg.c +++ b/reactos/dll/3rdparty/libjpeg/djpeg.c @@ -2,6 +2,7 @@ * djpeg.c * * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 2009 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -26,7 +27,6 @@ #include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ #include "jversion.h" /* for version message */ -#include /* to declare setlocal() */ #include /* to declare isprint() */ #ifdef USE_CCOMMAND /* command-line reader for Macintosh */ @@ -328,7 +328,7 @@ parse_switches (j_decompress_ptr cinfo, int argc, char **argv, if (++argn >= argc) /* advance to next argument */ usage(); if (sscanf(argv[argn], "%d/%d", - &cinfo->scale_num, &cinfo->scale_denom) != 2) + &cinfo->scale_num, &cinfo->scale_denom) < 1) usage(); } else if (keymatch(arg, "targa", 1)) { @@ -386,9 +386,6 @@ print_text_marker (j_decompress_ptr cinfo) cinfo->unread_marker - JPEG_APP0, (long) length); } - if (traceit) { - setlocale(LC_ALL, ""); - } while (--length >= 0) { ch = jpeg_getc(cinfo); if (traceit) { diff --git a/reactos/dll/3rdparty/libjpeg/example.c b/reactos/dll/3rdparty/libjpeg/example.c index 7fc354f04d9..1d6f6cc30bc 100644 --- a/reactos/dll/3rdparty/libjpeg/example.c +++ b/reactos/dll/3rdparty/libjpeg/example.c @@ -3,7 +3,7 @@ * * This file illustrates how to use the IJG code as a subroutine library * to read or write JPEG image files. You should look at this code in - * conjunction with the documentation file libjpeg.doc. + * conjunction with the documentation file libjpeg.txt. * * This code will not do anything useful as-is, but it may be helpful as a * skeleton for constructing routines that call the JPEG library. @@ -196,7 +196,7 @@ write_JPEG_file (char * filename, int quality) * files for anything that doesn't fit within the maximum-memory setting. * (Note that temp files are NOT needed if you use the default parameters.) * On some systems you may need to set up a signal handler to ensure that - * temporary files are deleted if the program is interrupted. See libjpeg.doc. + * temporary files are deleted if the program is interrupted. See libjpeg.txt. * * Scanlines MUST be supplied in top-to-bottom order if you want your JPEG * files to be compatible with everyone else's. If you cannot readily read @@ -335,7 +335,7 @@ read_JPEG_file (char * filename) /* We can ignore the return value from jpeg_read_header since * (a) suspension is not possible with the stdio data source, and * (b) we passed TRUE to reject a tables-only JPEG file as an error. - * See libjpeg.doc for more info. + * See libjpeg.txt for more info. */ /* Step 4: set parameters for decompression */ @@ -413,14 +413,14 @@ read_JPEG_file (char * filename) * In the above code, we ignored the return value of jpeg_read_scanlines, * which is the number of scanlines actually read. We could get away with * this because we asked for only one line at a time and we weren't using - * a suspending data source. See libjpeg.doc for more info. + * a suspending data source. See libjpeg.txt for more info. * * We cheated a bit by calling alloc_sarray() after jpeg_start_decompress(); * we should have done it beforehand to ensure that the space would be * counted against the JPEG max_memory setting. In some systems the above * code would risk an out-of-memory error. However, in general we don't * know the output image dimensions before jpeg_start_decompress(), unless we - * call jpeg_calc_output_dimensions(). See libjpeg.doc for more about this. + * call jpeg_calc_output_dimensions(). See libjpeg.txt for more about this. * * Scanlines are returned in the same order as they appear in the JPEG file, * which is standardly top-to-bottom. If you must emit data bottom-to-top, @@ -429,5 +429,5 @@ read_JPEG_file (char * filename) * * As with compression, some operating modes may require temporary files. * On some systems you may need to set up a signal handler to ensure that - * temporary files are deleted if the program is interrupted. See libjpeg.doc. + * temporary files are deleted if the program is interrupted. See libjpeg.txt. */ diff --git a/reactos/dll/3rdparty/libjpeg/jaricom.c b/reactos/dll/3rdparty/libjpeg/jaricom.c new file mode 100644 index 00000000000..f43e2ea7fac --- /dev/null +++ b/reactos/dll/3rdparty/libjpeg/jaricom.c @@ -0,0 +1,153 @@ +/* + * jaricom.c + * + * Developed 1997-2009 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains probability estimation tables for common use in + * arithmetic entropy encoding and decoding routines. + * + * This data represents Table D.2 in the JPEG spec (ISO/IEC IS 10918-1 + * and CCITT Recommendation ITU-T T.81) and Table 24 in the JBIG spec + * (ISO/IEC IS 11544 and CCITT Recommendation ITU-T T.82). + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + +/* The following #define specifies the packing of the four components + * into the compact INT32 representation. + * Note that this formula must match the actual arithmetic encoder + * and decoder implementation. The implementation has to be changed + * if this formula is changed. + * The current organization is leaned on Markus Kuhn's JBIG + * implementation (jbig_tab.c). + */ + +#define V(i,a,b,c,d) (((INT32)a << 16) | ((INT32)c << 8) | ((INT32)d << 7) | b) + +const INT32 jpeg_aritab[113+1] = { +/* + * Index, Qe_Value, Next_Index_LPS, Next_Index_MPS, Switch_MPS + */ + V( 0, 0x5a1d, 1, 1, 1 ), + V( 1, 0x2586, 14, 2, 0 ), + V( 2, 0x1114, 16, 3, 0 ), + V( 3, 0x080b, 18, 4, 0 ), + V( 4, 0x03d8, 20, 5, 0 ), + V( 5, 0x01da, 23, 6, 0 ), + V( 6, 0x00e5, 25, 7, 0 ), + V( 7, 0x006f, 28, 8, 0 ), + V( 8, 0x0036, 30, 9, 0 ), + V( 9, 0x001a, 33, 10, 0 ), + V( 10, 0x000d, 35, 11, 0 ), + V( 11, 0x0006, 9, 12, 0 ), + V( 12, 0x0003, 10, 13, 0 ), + V( 13, 0x0001, 12, 13, 0 ), + V( 14, 0x5a7f, 15, 15, 1 ), + V( 15, 0x3f25, 36, 16, 0 ), + V( 16, 0x2cf2, 38, 17, 0 ), + V( 17, 0x207c, 39, 18, 0 ), + V( 18, 0x17b9, 40, 19, 0 ), + V( 19, 0x1182, 42, 20, 0 ), + V( 20, 0x0cef, 43, 21, 0 ), + V( 21, 0x09a1, 45, 22, 0 ), + V( 22, 0x072f, 46, 23, 0 ), + V( 23, 0x055c, 48, 24, 0 ), + V( 24, 0x0406, 49, 25, 0 ), + V( 25, 0x0303, 51, 26, 0 ), + V( 26, 0x0240, 52, 27, 0 ), + V( 27, 0x01b1, 54, 28, 0 ), + V( 28, 0x0144, 56, 29, 0 ), + V( 29, 0x00f5, 57, 30, 0 ), + V( 30, 0x00b7, 59, 31, 0 ), + V( 31, 0x008a, 60, 32, 0 ), + V( 32, 0x0068, 62, 33, 0 ), + V( 33, 0x004e, 63, 34, 0 ), + V( 34, 0x003b, 32, 35, 0 ), + V( 35, 0x002c, 33, 9, 0 ), + V( 36, 0x5ae1, 37, 37, 1 ), + V( 37, 0x484c, 64, 38, 0 ), + V( 38, 0x3a0d, 65, 39, 0 ), + V( 39, 0x2ef1, 67, 40, 0 ), + V( 40, 0x261f, 68, 41, 0 ), + V( 41, 0x1f33, 69, 42, 0 ), + V( 42, 0x19a8, 70, 43, 0 ), + V( 43, 0x1518, 72, 44, 0 ), + V( 44, 0x1177, 73, 45, 0 ), + V( 45, 0x0e74, 74, 46, 0 ), + V( 46, 0x0bfb, 75, 47, 0 ), + V( 47, 0x09f8, 77, 48, 0 ), + V( 48, 0x0861, 78, 49, 0 ), + V( 49, 0x0706, 79, 50, 0 ), + V( 50, 0x05cd, 48, 51, 0 ), + V( 51, 0x04de, 50, 52, 0 ), + V( 52, 0x040f, 50, 53, 0 ), + V( 53, 0x0363, 51, 54, 0 ), + V( 54, 0x02d4, 52, 55, 0 ), + V( 55, 0x025c, 53, 56, 0 ), + V( 56, 0x01f8, 54, 57, 0 ), + V( 57, 0x01a4, 55, 58, 0 ), + V( 58, 0x0160, 56, 59, 0 ), + V( 59, 0x0125, 57, 60, 0 ), + V( 60, 0x00f6, 58, 61, 0 ), + V( 61, 0x00cb, 59, 62, 0 ), + V( 62, 0x00ab, 61, 63, 0 ), + V( 63, 0x008f, 61, 32, 0 ), + V( 64, 0x5b12, 65, 65, 1 ), + V( 65, 0x4d04, 80, 66, 0 ), + V( 66, 0x412c, 81, 67, 0 ), + V( 67, 0x37d8, 82, 68, 0 ), + V( 68, 0x2fe8, 83, 69, 0 ), + V( 69, 0x293c, 84, 70, 0 ), + V( 70, 0x2379, 86, 71, 0 ), + V( 71, 0x1edf, 87, 72, 0 ), + V( 72, 0x1aa9, 87, 73, 0 ), + V( 73, 0x174e, 72, 74, 0 ), + V( 74, 0x1424, 72, 75, 0 ), + V( 75, 0x119c, 74, 76, 0 ), + V( 76, 0x0f6b, 74, 77, 0 ), + V( 77, 0x0d51, 75, 78, 0 ), + V( 78, 0x0bb6, 77, 79, 0 ), + V( 79, 0x0a40, 77, 48, 0 ), + V( 80, 0x5832, 80, 81, 1 ), + V( 81, 0x4d1c, 88, 82, 0 ), + V( 82, 0x438e, 89, 83, 0 ), + V( 83, 0x3bdd, 90, 84, 0 ), + V( 84, 0x34ee, 91, 85, 0 ), + V( 85, 0x2eae, 92, 86, 0 ), + V( 86, 0x299a, 93, 87, 0 ), + V( 87, 0x2516, 86, 71, 0 ), + V( 88, 0x5570, 88, 89, 1 ), + V( 89, 0x4ca9, 95, 90, 0 ), + V( 90, 0x44d9, 96, 91, 0 ), + V( 91, 0x3e22, 97, 92, 0 ), + V( 92, 0x3824, 99, 93, 0 ), + V( 93, 0x32b4, 99, 94, 0 ), + V( 94, 0x2e17, 93, 86, 0 ), + V( 95, 0x56a8, 95, 96, 1 ), + V( 96, 0x4f46, 101, 97, 0 ), + V( 97, 0x47e5, 102, 98, 0 ), + V( 98, 0x41cf, 103, 99, 0 ), + V( 99, 0x3c3d, 104, 100, 0 ), + V( 100, 0x375e, 99, 93, 0 ), + V( 101, 0x5231, 105, 102, 0 ), + V( 102, 0x4c0f, 106, 103, 0 ), + V( 103, 0x4639, 107, 104, 0 ), + V( 104, 0x415e, 103, 99, 0 ), + V( 105, 0x5627, 105, 106, 1 ), + V( 106, 0x50e7, 108, 107, 0 ), + V( 107, 0x4b85, 109, 103, 0 ), + V( 108, 0x5597, 110, 109, 0 ), + V( 109, 0x504f, 111, 107, 0 ), + V( 110, 0x5a10, 110, 111, 1 ), + V( 111, 0x5522, 112, 109, 0 ), + V( 112, 0x59eb, 112, 111, 1 ), +/* + * This last entry is used for fixed probability estimate of 0.5 + * as recommended in Section 10.3 Table 5 of ITU-T Rec. T.851. + */ + V( 113, 0x5a1d, 113, 113, 0 ) +}; diff --git a/reactos/dll/3rdparty/libjpeg/jcapimin.c b/reactos/dll/3rdparty/libjpeg/jcapimin.c index 54fb8c58c56..639ce86f44f 100644 --- a/reactos/dll/3rdparty/libjpeg/jcapimin.c +++ b/reactos/dll/3rdparty/libjpeg/jcapimin.c @@ -2,6 +2,7 @@ * jcapimin.c * * Copyright (C) 1994-1998, Thomas G. Lane. + * Modified 2003-2010 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -63,14 +64,21 @@ jpeg_CreateCompress (j_compress_ptr cinfo, int version, size_t structsize) cinfo->comp_info = NULL; - for (i = 0; i < NUM_QUANT_TBLS; i++) + for (i = 0; i < NUM_QUANT_TBLS; i++) { cinfo->quant_tbl_ptrs[i] = NULL; + cinfo->q_scale_factor[i] = 100; + } for (i = 0; i < NUM_HUFF_TBLS; i++) { cinfo->dc_huff_tbl_ptrs[i] = NULL; cinfo->ac_huff_tbl_ptrs[i] = NULL; } + /* Must do it here for emit_dqt in case jpeg_write_tables is used */ + cinfo->block_size = DCTSIZE; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + cinfo->script_space = NULL; cinfo->input_gamma = 1.0; /* in case application forgets */ diff --git a/reactos/dll/3rdparty/libjpeg/jcarith.c b/reactos/dll/3rdparty/libjpeg/jcarith.c new file mode 100644 index 00000000000..0b7ea55d404 --- /dev/null +++ b/reactos/dll/3rdparty/libjpeg/jcarith.c @@ -0,0 +1,934 @@ +/* + * jcarith.c + * + * Developed 1997-2009 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains portable arithmetic entropy encoding routines for JPEG + * (implementing the ISO/IEC IS 10918-1 and CCITT Recommendation ITU-T T.81). + * + * Both sequential and progressive modes are supported in this single module. + * + * Suspension is not currently supported in this module. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Expanded entropy encoder object for arithmetic encoding. */ + +typedef struct { + struct jpeg_entropy_encoder pub; /* public fields */ + + INT32 c; /* C register, base of coding interval, layout as in sec. D.1.3 */ + INT32 a; /* A register, normalized size of coding interval */ + INT32 sc; /* counter for stacked 0xFF values which might overflow */ + INT32 zc; /* counter for pending 0x00 output values which might * + * be discarded at the end ("Pacman" termination) */ + int ct; /* bit shift counter, determines when next byte will be written */ + int buffer; /* buffer for most recent output byte != 0xFF */ + + int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ + int dc_context[MAX_COMPS_IN_SCAN]; /* context index for DC conditioning */ + + unsigned int restarts_to_go; /* MCUs left in this restart interval */ + int next_restart_num; /* next restart number to write (0-7) */ + + /* Pointers to statistics areas (these workspaces have image lifespan) */ + unsigned char * dc_stats[NUM_ARITH_TBLS]; + unsigned char * ac_stats[NUM_ARITH_TBLS]; + + /* Statistics bin for coding with fixed probability 0.5 */ + unsigned char fixed_bin[4]; +} arith_entropy_encoder; + +typedef arith_entropy_encoder * arith_entropy_ptr; + +/* The following two definitions specify the allocation chunk size + * for the statistics area. + * According to sections F.1.4.4.1.3 and F.1.4.4.2, we need at least + * 49 statistics bins for DC, and 245 statistics bins for AC coding. + * + * We use a compact representation with 1 byte per statistics bin, + * thus the numbers directly represent byte sizes. + * This 1 byte per statistics bin contains the meaning of the MPS + * (more probable symbol) in the highest bit (mask 0x80), and the + * index into the probability estimation state machine table + * in the lower bits (mask 0x7F). + */ + +#define DC_STAT_BINS 64 +#define AC_STAT_BINS 256 + +/* NOTE: Uncomment the following #define if you want to use the + * given formula for calculating the AC conditioning parameter Kx + * for spectral selection progressive coding in section G.1.3.2 + * of the spec (Kx = Kmin + SRL (8 + Se - Kmin) 4). + * Although the spec and P&M authors claim that this "has proven + * to give good results for 8 bit precision samples", I'm not + * convinced yet that this is really beneficial. + * Early tests gave only very marginal compression enhancements + * (a few - around 5 or so - bytes even for very large files), + * which would turn out rather negative if we'd suppress the + * DAC (Define Arithmetic Conditioning) marker segments for + * the default parameters in the future. + * Note that currently the marker writing module emits 12-byte + * DAC segments for a full-component scan in a color image. + * This is not worth worrying about IMHO. However, since the + * spec defines the default values to be used if the tables + * are omitted (unlike Huffman tables, which are required + * anyway), one might optimize this behaviour in the future, + * and then it would be disadvantageous to use custom tables if + * they don't provide sufficient gain to exceed the DAC size. + * + * On the other hand, I'd consider it as a reasonable result + * that the conditioning has no significant influence on the + * compression performance. This means that the basic + * statistical model is already rather stable. + * + * Thus, at the moment, we use the default conditioning values + * anyway, and do not use the custom formula. + * +#define CALCULATE_SPECTRAL_CONDITIONING + */ + +/* IRIGHT_SHIFT is like RIGHT_SHIFT, but works on int rather than INT32. + * We assume that int right shift is unsigned if INT32 right shift is, + * which should be safe. + */ + +#ifdef RIGHT_SHIFT_IS_UNSIGNED +#define ISHIFT_TEMPS int ishift_temp; +#define IRIGHT_SHIFT(x,shft) \ + ((ishift_temp = (x)) < 0 ? \ + (ishift_temp >> (shft)) | ((~0) << (16-(shft))) : \ + (ishift_temp >> (shft))) +#else +#define ISHIFT_TEMPS +#define IRIGHT_SHIFT(x,shft) ((x) >> (shft)) +#endif + + +LOCAL(void) +emit_byte (int val, j_compress_ptr cinfo) +/* Write next output byte; we do not support suspension in this module. */ +{ + struct jpeg_destination_mgr * dest = cinfo->dest; + + *dest->next_output_byte++ = (JOCTET) val; + if (--dest->free_in_buffer == 0) + if (! (*dest->empty_output_buffer) (cinfo)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); +} + + +/* + * Finish up at the end of an arithmetic-compressed scan. + */ + +METHODDEF(void) +finish_pass (j_compress_ptr cinfo) +{ + arith_entropy_ptr e = (arith_entropy_ptr) cinfo->entropy; + INT32 temp; + + /* Section D.1.8: Termination of encoding */ + + /* Find the e->c in the coding interval with the largest + * number of trailing zero bits */ + if ((temp = (e->a - 1 + e->c) & 0xFFFF0000L) < e->c) + e->c = temp + 0x8000L; + else + e->c = temp; + /* Send remaining bytes to output */ + e->c <<= e->ct; + if (e->c & 0xF8000000L) { + /* One final overflow has to be handled */ + if (e->buffer >= 0) { + if (e->zc) + do emit_byte(0x00, cinfo); + while (--e->zc); + emit_byte(e->buffer + 1, cinfo); + if (e->buffer + 1 == 0xFF) + emit_byte(0x00, cinfo); + } + e->zc += e->sc; /* carry-over converts stacked 0xFF bytes to 0x00 */ + e->sc = 0; + } else { + if (e->buffer == 0) + ++e->zc; + else if (e->buffer >= 0) { + if (e->zc) + do emit_byte(0x00, cinfo); + while (--e->zc); + emit_byte(e->buffer, cinfo); + } + if (e->sc) { + if (e->zc) + do emit_byte(0x00, cinfo); + while (--e->zc); + do { + emit_byte(0xFF, cinfo); + emit_byte(0x00, cinfo); + } while (--e->sc); + } + } + /* Output final bytes only if they are not 0x00 */ + if (e->c & 0x7FFF800L) { + if (e->zc) /* output final pending zero bytes */ + do emit_byte(0x00, cinfo); + while (--e->zc); + emit_byte((e->c >> 19) & 0xFF, cinfo); + if (((e->c >> 19) & 0xFF) == 0xFF) + emit_byte(0x00, cinfo); + if (e->c & 0x7F800L) { + emit_byte((e->c >> 11) & 0xFF, cinfo); + if (((e->c >> 11) & 0xFF) == 0xFF) + emit_byte(0x00, cinfo); + } + } +} + + +/* + * The core arithmetic encoding routine (common in JPEG and JBIG). + * This needs to go as fast as possible. + * Machine-dependent optimization facilities + * are not utilized in this portable implementation. + * However, this code should be fairly efficient and + * may be a good base for further optimizations anyway. + * + * Parameter 'val' to be encoded may be 0 or 1 (binary decision). + * + * Note: I've added full "Pacman" termination support to the + * byte output routines, which is equivalent to the optional + * Discard_final_zeros procedure (Figure D.15) in the spec. + * Thus, we always produce the shortest possible output + * stream compliant to the spec (no trailing zero bytes, + * except for FF stuffing). + * + * I've also introduced a new scheme for accessing + * the probability estimation state machine table, + * derived from Markus Kuhn's JBIG implementation. + */ + +LOCAL(void) +arith_encode (j_compress_ptr cinfo, unsigned char *st, int val) +{ + register arith_entropy_ptr e = (arith_entropy_ptr) cinfo->entropy; + register unsigned char nl, nm; + register INT32 qe, temp; + register int sv; + + /* Fetch values from our compact representation of Table D.2: + * Qe values and probability estimation state machine + */ + sv = *st; + qe = jpeg_aritab[sv & 0x7F]; /* => Qe_Value */ + nl = qe & 0xFF; qe >>= 8; /* Next_Index_LPS + Switch_MPS */ + nm = qe & 0xFF; qe >>= 8; /* Next_Index_MPS */ + + /* Encode & estimation procedures per sections D.1.4 & D.1.5 */ + e->a -= qe; + if (val != (sv >> 7)) { + /* Encode the less probable symbol */ + if (e->a >= qe) { + /* If the interval size (qe) for the less probable symbol (LPS) + * is larger than the interval size for the MPS, then exchange + * the two symbols for coding efficiency, otherwise code the LPS + * as usual: */ + e->c += e->a; + e->a = qe; + } + *st = (sv & 0x80) ^ nl; /* Estimate_after_LPS */ + } else { + /* Encode the more probable symbol */ + if (e->a >= 0x8000L) + return; /* A >= 0x8000 -> ready, no renormalization required */ + if (e->a < qe) { + /* If the interval size (qe) for the less probable symbol (LPS) + * is larger than the interval size for the MPS, then exchange + * the two symbols for coding efficiency: */ + e->c += e->a; + e->a = qe; + } + *st = (sv & 0x80) ^ nm; /* Estimate_after_MPS */ + } + + /* Renormalization & data output per section D.1.6 */ + do { + e->a <<= 1; + e->c <<= 1; + if (--e->ct == 0) { + /* Another byte is ready for output */ + temp = e->c >> 19; + if (temp > 0xFF) { + /* Handle overflow over all stacked 0xFF bytes */ + if (e->buffer >= 0) { + if (e->zc) + do emit_byte(0x00, cinfo); + while (--e->zc); + emit_byte(e->buffer + 1, cinfo); + if (e->buffer + 1 == 0xFF) + emit_byte(0x00, cinfo); + } + e->zc += e->sc; /* carry-over converts stacked 0xFF bytes to 0x00 */ + e->sc = 0; + /* Note: The 3 spacer bits in the C register guarantee + * that the new buffer byte can't be 0xFF here + * (see page 160 in the P&M JPEG book). */ + e->buffer = temp & 0xFF; /* new output byte, might overflow later */ + } else if (temp == 0xFF) { + ++e->sc; /* stack 0xFF byte (which might overflow later) */ + } else { + /* Output all stacked 0xFF bytes, they will not overflow any more */ + if (e->buffer == 0) + ++e->zc; + else if (e->buffer >= 0) { + if (e->zc) + do emit_byte(0x00, cinfo); + while (--e->zc); + emit_byte(e->buffer, cinfo); + } + if (e->sc) { + if (e->zc) + do emit_byte(0x00, cinfo); + while (--e->zc); + do { + emit_byte(0xFF, cinfo); + emit_byte(0x00, cinfo); + } while (--e->sc); + } + e->buffer = temp & 0xFF; /* new output byte (can still overflow) */ + } + e->c &= 0x7FFFFL; + e->ct += 8; + } + } while (e->a < 0x8000L); +} + + +/* + * Emit a restart marker & resynchronize predictions. + */ + +LOCAL(void) +emit_restart (j_compress_ptr cinfo, int restart_num) +{ + arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + int ci; + jpeg_component_info * compptr; + + finish_pass(cinfo); + + emit_byte(0xFF, cinfo); + emit_byte(JPEG_RST0 + restart_num, cinfo); + + /* Re-initialize statistics areas */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* DC needs no table for refinement scan */ + if (cinfo->Ss == 0 && cinfo->Ah == 0) { + MEMZERO(entropy->dc_stats[compptr->dc_tbl_no], DC_STAT_BINS); + /* Reset DC predictions to 0 */ + entropy->last_dc_val[ci] = 0; + entropy->dc_context[ci] = 0; + } + /* AC needs no table when not present */ + if (cinfo->Se) { + MEMZERO(entropy->ac_stats[compptr->ac_tbl_no], AC_STAT_BINS); + } + } + + /* Reset arithmetic encoding variables */ + entropy->c = 0; + entropy->a = 0x10000L; + entropy->sc = 0; + entropy->zc = 0; + entropy->ct = 11; + entropy->buffer = -1; /* empty */ +} + + +/* + * MCU encoding for DC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + JBLOCKROW block; + unsigned char *st; + int blkn, ci, tbl; + int v, v2, m; + ISHIFT_TEMPS + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + emit_restart(cinfo, entropy->next_restart_num); + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + /* Encode the MCU data blocks */ + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + block = MCU_data[blkn]; + ci = cinfo->MCU_membership[blkn]; + tbl = cinfo->cur_comp_info[ci]->dc_tbl_no; + + /* Compute the DC value after the required point transform by Al. + * This is simply an arithmetic right shift. + */ + m = IRIGHT_SHIFT((int) ((*block)[0]), cinfo->Al); + + /* Sections F.1.4.1 & F.1.4.4.1: Encoding of DC coefficients */ + + /* Table F.4: Point to statistics bin S0 for DC coefficient coding */ + st = entropy->dc_stats[tbl] + entropy->dc_context[ci]; + + /* Figure F.4: Encode_DC_DIFF */ + if ((v = m - entropy->last_dc_val[ci]) == 0) { + arith_encode(cinfo, st, 0); + entropy->dc_context[ci] = 0; /* zero diff category */ + } else { + entropy->last_dc_val[ci] = m; + arith_encode(cinfo, st, 1); + /* Figure F.6: Encoding nonzero value v */ + /* Figure F.7: Encoding the sign of v */ + if (v > 0) { + arith_encode(cinfo, st + 1, 0); /* Table F.4: SS = S0 + 1 */ + st += 2; /* Table F.4: SP = S0 + 2 */ + entropy->dc_context[ci] = 4; /* small positive diff category */ + } else { + v = -v; + arith_encode(cinfo, st + 1, 1); /* Table F.4: SS = S0 + 1 */ + st += 3; /* Table F.4: SN = S0 + 3 */ + entropy->dc_context[ci] = 8; /* small negative diff category */ + } + /* Figure F.8: Encoding the magnitude category of v */ + m = 0; + if (v -= 1) { + arith_encode(cinfo, st, 1); + m = 1; + v2 = v; + st = entropy->dc_stats[tbl] + 20; /* Table F.4: X1 = 20 */ + while (v2 >>= 1) { + arith_encode(cinfo, st, 1); + m <<= 1; + st += 1; + } + } + arith_encode(cinfo, st, 0); + /* Section F.1.4.4.1.2: Establish dc_context conditioning category */ + if (m < (int) ((1L << cinfo->arith_dc_L[tbl]) >> 1)) + entropy->dc_context[ci] = 0; /* zero diff category */ + else if (m > (int) ((1L << cinfo->arith_dc_U[tbl]) >> 1)) + entropy->dc_context[ci] += 8; /* large diff category */ + /* Figure F.9: Encoding the magnitude bit pattern of v */ + st += 14; + while (m >>= 1) + arith_encode(cinfo, st, (m & v) ? 1 : 0); + } + } + + return TRUE; +} + + +/* + * MCU encoding for AC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + JBLOCKROW block; + unsigned char *st; + int tbl, k, ke; + int v, v2, m; + const int * natural_order; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + emit_restart(cinfo, entropy->next_restart_num); + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + natural_order = cinfo->natural_order; + + /* Encode the MCU data block */ + block = MCU_data[0]; + tbl = cinfo->cur_comp_info[0]->ac_tbl_no; + + /* Sections F.1.4.2 & F.1.4.4.2: Encoding of AC coefficients */ + + /* Establish EOB (end-of-block) index */ + for (ke = cinfo->Se; ke > 0; ke--) + /* We must apply the point transform by Al. For AC coefficients this + * is an integer division with rounding towards 0. To do this portably + * in C, we shift after obtaining the absolute value. + */ + if ((v = (*block)[natural_order[ke]]) >= 0) { + if (v >>= cinfo->Al) break; + } else { + v = -v; + if (v >>= cinfo->Al) break; + } + + /* Figure F.5: Encode_AC_Coefficients */ + for (k = cinfo->Ss; k <= ke; k++) { + st = entropy->ac_stats[tbl] + 3 * (k - 1); + arith_encode(cinfo, st, 0); /* EOB decision */ + for (;;) { + if ((v = (*block)[natural_order[k]]) >= 0) { + if (v >>= cinfo->Al) { + arith_encode(cinfo, st + 1, 1); + arith_encode(cinfo, entropy->fixed_bin, 0); + break; + } + } else { + v = -v; + if (v >>= cinfo->Al) { + arith_encode(cinfo, st + 1, 1); + arith_encode(cinfo, entropy->fixed_bin, 1); + break; + } + } + arith_encode(cinfo, st + 1, 0); st += 3; k++; + } + st += 2; + /* Figure F.8: Encoding the magnitude category of v */ + m = 0; + if (v -= 1) { + arith_encode(cinfo, st, 1); + m = 1; + v2 = v; + if (v2 >>= 1) { + arith_encode(cinfo, st, 1); + m <<= 1; + st = entropy->ac_stats[tbl] + + (k <= cinfo->arith_ac_K[tbl] ? 189 : 217); + while (v2 >>= 1) { + arith_encode(cinfo, st, 1); + m <<= 1; + st += 1; + } + } + } + arith_encode(cinfo, st, 0); + /* Figure F.9: Encoding the magnitude bit pattern of v */ + st += 14; + while (m >>= 1) + arith_encode(cinfo, st, (m & v) ? 1 : 0); + } + /* Encode EOB decision only if k <= cinfo->Se */ + if (k <= cinfo->Se) { + st = entropy->ac_stats[tbl] + 3 * (k - 1); + arith_encode(cinfo, st, 1); + } + + return TRUE; +} + + +/* + * MCU encoding for DC successive approximation refinement scan. + */ + +METHODDEF(boolean) +encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + unsigned char *st; + int Al, blkn; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + emit_restart(cinfo, entropy->next_restart_num); + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + st = entropy->fixed_bin; /* use fixed probability estimation */ + Al = cinfo->Al; + + /* Encode the MCU data blocks */ + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + /* We simply emit the Al'th bit of the DC coefficient value. */ + arith_encode(cinfo, st, (MCU_data[blkn][0][0] >> Al) & 1); + } + + return TRUE; +} + + +/* + * MCU encoding for AC successive approximation refinement scan. + */ + +METHODDEF(boolean) +encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + JBLOCKROW block; + unsigned char *st; + int tbl, k, ke, kex; + int v; + const int * natural_order; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + emit_restart(cinfo, entropy->next_restart_num); + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + natural_order = cinfo->natural_order; + + /* Encode the MCU data block */ + block = MCU_data[0]; + tbl = cinfo->cur_comp_info[0]->ac_tbl_no; + + /* Section G.1.3.3: Encoding of AC coefficients */ + + /* Establish EOB (end-of-block) index */ + for (ke = cinfo->Se; ke > 0; ke--) + /* We must apply the point transform by Al. For AC coefficients this + * is an integer division with rounding towards 0. To do this portably + * in C, we shift after obtaining the absolute value. + */ + if ((v = (*block)[natural_order[ke]]) >= 0) { + if (v >>= cinfo->Al) break; + } else { + v = -v; + if (v >>= cinfo->Al) break; + } + + /* Establish EOBx (previous stage end-of-block) index */ + for (kex = ke; kex > 0; kex--) + if ((v = (*block)[natural_order[kex]]) >= 0) { + if (v >>= cinfo->Ah) break; + } else { + v = -v; + if (v >>= cinfo->Ah) break; + } + + /* Figure G.10: Encode_AC_Coefficients_SA */ + for (k = cinfo->Ss; k <= ke; k++) { + st = entropy->ac_stats[tbl] + 3 * (k - 1); + if (k > kex) + arith_encode(cinfo, st, 0); /* EOB decision */ + for (;;) { + if ((v = (*block)[natural_order[k]]) >= 0) { + if (v >>= cinfo->Al) { + if (v >> 1) /* previously nonzero coef */ + arith_encode(cinfo, st + 2, (v & 1)); + else { /* newly nonzero coef */ + arith_encode(cinfo, st + 1, 1); + arith_encode(cinfo, entropy->fixed_bin, 0); + } + break; + } + } else { + v = -v; + if (v >>= cinfo->Al) { + if (v >> 1) /* previously nonzero coef */ + arith_encode(cinfo, st + 2, (v & 1)); + else { /* newly nonzero coef */ + arith_encode(cinfo, st + 1, 1); + arith_encode(cinfo, entropy->fixed_bin, 1); + } + break; + } + } + arith_encode(cinfo, st + 1, 0); st += 3; k++; + } + } + /* Encode EOB decision only if k <= cinfo->Se */ + if (k <= cinfo->Se) { + st = entropy->ac_stats[tbl] + 3 * (k - 1); + arith_encode(cinfo, st, 1); + } + + return TRUE; +} + + +/* + * Encode and output one MCU's worth of arithmetic-compressed coefficients. + */ + +METHODDEF(boolean) +encode_mcu (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + jpeg_component_info * compptr; + JBLOCKROW block; + unsigned char *st; + int blkn, ci, tbl, k, ke; + int v, v2, m; + const int * natural_order; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + emit_restart(cinfo, entropy->next_restart_num); + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + natural_order = cinfo->natural_order; + + /* Encode the MCU data blocks */ + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + block = MCU_data[blkn]; + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + + /* Sections F.1.4.1 & F.1.4.4.1: Encoding of DC coefficients */ + + tbl = compptr->dc_tbl_no; + + /* Table F.4: Point to statistics bin S0 for DC coefficient coding */ + st = entropy->dc_stats[tbl] + entropy->dc_context[ci]; + + /* Figure F.4: Encode_DC_DIFF */ + if ((v = (*block)[0] - entropy->last_dc_val[ci]) == 0) { + arith_encode(cinfo, st, 0); + entropy->dc_context[ci] = 0; /* zero diff category */ + } else { + entropy->last_dc_val[ci] = (*block)[0]; + arith_encode(cinfo, st, 1); + /* Figure F.6: Encoding nonzero value v */ + /* Figure F.7: Encoding the sign of v */ + if (v > 0) { + arith_encode(cinfo, st + 1, 0); /* Table F.4: SS = S0 + 1 */ + st += 2; /* Table F.4: SP = S0 + 2 */ + entropy->dc_context[ci] = 4; /* small positive diff category */ + } else { + v = -v; + arith_encode(cinfo, st + 1, 1); /* Table F.4: SS = S0 + 1 */ + st += 3; /* Table F.4: SN = S0 + 3 */ + entropy->dc_context[ci] = 8; /* small negative diff category */ + } + /* Figure F.8: Encoding the magnitude category of v */ + m = 0; + if (v -= 1) { + arith_encode(cinfo, st, 1); + m = 1; + v2 = v; + st = entropy->dc_stats[tbl] + 20; /* Table F.4: X1 = 20 */ + while (v2 >>= 1) { + arith_encode(cinfo, st, 1); + m <<= 1; + st += 1; + } + } + arith_encode(cinfo, st, 0); + /* Section F.1.4.4.1.2: Establish dc_context conditioning category */ + if (m < (int) ((1L << cinfo->arith_dc_L[tbl]) >> 1)) + entropy->dc_context[ci] = 0; /* zero diff category */ + else if (m > (int) ((1L << cinfo->arith_dc_U[tbl]) >> 1)) + entropy->dc_context[ci] += 8; /* large diff category */ + /* Figure F.9: Encoding the magnitude bit pattern of v */ + st += 14; + while (m >>= 1) + arith_encode(cinfo, st, (m & v) ? 1 : 0); + } + + /* Sections F.1.4.2 & F.1.4.4.2: Encoding of AC coefficients */ + + tbl = compptr->ac_tbl_no; + + /* Establish EOB (end-of-block) index */ + for (ke = cinfo->lim_Se; ke > 0; ke--) + if ((*block)[natural_order[ke]]) break; + + /* Figure F.5: Encode_AC_Coefficients */ + for (k = 1; k <= ke; k++) { + st = entropy->ac_stats[tbl] + 3 * (k - 1); + arith_encode(cinfo, st, 0); /* EOB decision */ + while ((v = (*block)[natural_order[k]]) == 0) { + arith_encode(cinfo, st + 1, 0); st += 3; k++; + } + arith_encode(cinfo, st + 1, 1); + /* Figure F.6: Encoding nonzero value v */ + /* Figure F.7: Encoding the sign of v */ + if (v > 0) { + arith_encode(cinfo, entropy->fixed_bin, 0); + } else { + v = -v; + arith_encode(cinfo, entropy->fixed_bin, 1); + } + st += 2; + /* Figure F.8: Encoding the magnitude category of v */ + m = 0; + if (v -= 1) { + arith_encode(cinfo, st, 1); + m = 1; + v2 = v; + if (v2 >>= 1) { + arith_encode(cinfo, st, 1); + m <<= 1; + st = entropy->ac_stats[tbl] + + (k <= cinfo->arith_ac_K[tbl] ? 189 : 217); + while (v2 >>= 1) { + arith_encode(cinfo, st, 1); + m <<= 1; + st += 1; + } + } + } + arith_encode(cinfo, st, 0); + /* Figure F.9: Encoding the magnitude bit pattern of v */ + st += 14; + while (m >>= 1) + arith_encode(cinfo, st, (m & v) ? 1 : 0); + } + /* Encode EOB decision only if k <= cinfo->lim_Se */ + if (k <= cinfo->lim_Se) { + st = entropy->ac_stats[tbl] + 3 * (k - 1); + arith_encode(cinfo, st, 1); + } + } + + return TRUE; +} + + +/* + * Initialize for an arithmetic-compressed scan. + */ + +METHODDEF(void) +start_pass (j_compress_ptr cinfo, boolean gather_statistics) +{ + arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + int ci, tbl; + jpeg_component_info * compptr; + + if (gather_statistics) + /* Make sure to avoid that in the master control logic! + * We are fully adaptive here and need no extra + * statistics gathering pass! + */ + ERREXIT(cinfo, JERR_NOT_COMPILED); + + /* We assume jcmaster.c already validated the progressive scan parameters. */ + + /* Select execution routines */ + if (cinfo->progressive_mode) { + if (cinfo->Ah == 0) { + if (cinfo->Ss == 0) + entropy->pub.encode_mcu = encode_mcu_DC_first; + else + entropy->pub.encode_mcu = encode_mcu_AC_first; + } else { + if (cinfo->Ss == 0) + entropy->pub.encode_mcu = encode_mcu_DC_refine; + else + entropy->pub.encode_mcu = encode_mcu_AC_refine; + } + } else + entropy->pub.encode_mcu = encode_mcu; + + /* Allocate & initialize requested statistics areas */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* DC needs no table for refinement scan */ + if (cinfo->Ss == 0 && cinfo->Ah == 0) { + tbl = compptr->dc_tbl_no; + if (tbl < 0 || tbl >= NUM_ARITH_TBLS) + ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl); + if (entropy->dc_stats[tbl] == NULL) + entropy->dc_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, DC_STAT_BINS); + MEMZERO(entropy->dc_stats[tbl], DC_STAT_BINS); + /* Initialize DC predictions to 0 */ + entropy->last_dc_val[ci] = 0; + entropy->dc_context[ci] = 0; + } + /* AC needs no table when not present */ + if (cinfo->Se) { + tbl = compptr->ac_tbl_no; + if (tbl < 0 || tbl >= NUM_ARITH_TBLS) + ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl); + if (entropy->ac_stats[tbl] == NULL) + entropy->ac_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, AC_STAT_BINS); + MEMZERO(entropy->ac_stats[tbl], AC_STAT_BINS); +#ifdef CALCULATE_SPECTRAL_CONDITIONING + if (cinfo->progressive_mode) + /* Section G.1.3.2: Set appropriate arithmetic conditioning value Kx */ + cinfo->arith_ac_K[tbl] = cinfo->Ss + ((8 + cinfo->Se - cinfo->Ss) >> 4); +#endif + } + } + + /* Initialize arithmetic encoding variables */ + entropy->c = 0; + entropy->a = 0x10000L; + entropy->sc = 0; + entropy->zc = 0; + entropy->ct = 11; + entropy->buffer = -1; /* empty */ + + /* Initialize restart stuff */ + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num = 0; +} + + +/* + * Module initialization routine for arithmetic entropy encoding. + */ + +GLOBAL(void) +jinit_arith_encoder (j_compress_ptr cinfo) +{ + arith_entropy_ptr entropy; + int i; + + entropy = (arith_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(arith_entropy_encoder)); + cinfo->entropy = (struct jpeg_entropy_encoder *) entropy; + entropy->pub.start_pass = start_pass; + entropy->pub.finish_pass = finish_pass; + + /* Mark tables unallocated */ + for (i = 0; i < NUM_ARITH_TBLS; i++) { + entropy->dc_stats[i] = NULL; + entropy->ac_stats[i] = NULL; + } + + /* Initialize index for fixed probability estimation */ + entropy->fixed_bin[0] = 113; +} diff --git a/reactos/dll/3rdparty/libjpeg/jccoefct.c b/reactos/dll/3rdparty/libjpeg/jccoefct.c index 1963ddb61b1..d775313b86f 100644 --- a/reactos/dll/3rdparty/libjpeg/jccoefct.c +++ b/reactos/dll/3rdparty/libjpeg/jccoefct.c @@ -149,6 +149,7 @@ compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf) int blkn, bi, ci, yindex, yoffset, blockcnt; JDIMENSION ypos, xpos; jpeg_component_info *compptr; + forward_DCT_ptr forward_DCT; /* Loop to write as much as one whole iMCU row */ for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; @@ -167,17 +168,19 @@ compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf) blkn = 0; for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; + forward_DCT = cinfo->fdct->forward_DCT[compptr->component_index]; blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width : compptr->last_col_width; xpos = MCU_col_num * compptr->MCU_sample_width; - ypos = yoffset * DCTSIZE; /* ypos == (yoffset+yindex) * DCTSIZE */ + ypos = yoffset * compptr->DCT_v_scaled_size; + /* ypos == (yoffset+yindex) * DCTSIZE */ for (yindex = 0; yindex < compptr->MCU_height; yindex++) { if (coef->iMCU_row_num < last_iMCU_row || yoffset+yindex < compptr->last_row_height) { - (*cinfo->fdct->forward_DCT) (cinfo, compptr, - input_buf[compptr->component_index], - coef->MCU_buffer[blkn], - ypos, xpos, (JDIMENSION) blockcnt); + (*forward_DCT) (cinfo, compptr, + input_buf[compptr->component_index], + coef->MCU_buffer[blkn], + ypos, xpos, (JDIMENSION) blockcnt); if (blockcnt < compptr->MCU_width) { /* Create some dummy blocks at the right edge of the image. */ jzero_far((void FAR *) coef->MCU_buffer[blkn + blockcnt], @@ -195,7 +198,7 @@ compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf) } } blkn += compptr->MCU_width; - ypos += DCTSIZE; + ypos += compptr->DCT_v_scaled_size; } } /* Try to write the MCU. In event of a suspension failure, we will @@ -252,6 +255,7 @@ compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf) jpeg_component_info *compptr; JBLOCKARRAY buffer; JBLOCKROW thisblockrow, lastblockrow; + forward_DCT_ptr forward_DCT; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { @@ -274,15 +278,15 @@ compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf) ndummy = (int) (blocks_across % h_samp_factor); if (ndummy > 0) ndummy = h_samp_factor - ndummy; + forward_DCT = cinfo->fdct->forward_DCT[ci]; /* Perform DCT for all non-dummy blocks in this iMCU row. Each call * on forward_DCT processes a complete horizontal row of DCT blocks. */ for (block_row = 0; block_row < block_rows; block_row++) { thisblockrow = buffer[block_row]; - (*cinfo->fdct->forward_DCT) (cinfo, compptr, - input_buf[ci], thisblockrow, - (JDIMENSION) (block_row * DCTSIZE), - (JDIMENSION) 0, blocks_across); + (*forward_DCT) (cinfo, compptr, input_buf[ci], thisblockrow, + (JDIMENSION) (block_row * compptr->DCT_v_scaled_size), + (JDIMENSION) 0, blocks_across); if (ndummy > 0) { /* Create dummy blocks at the right edge of the image. */ thisblockrow += blocks_across; /* => first dummy block */ diff --git a/reactos/dll/3rdparty/libjpeg/jcdctmgr.c b/reactos/dll/3rdparty/libjpeg/jcdctmgr.c index 61fa79b9e68..0bbdbb685d1 100644 --- a/reactos/dll/3rdparty/libjpeg/jcdctmgr.c +++ b/reactos/dll/3rdparty/libjpeg/jcdctmgr.c @@ -23,7 +23,7 @@ typedef struct { struct jpeg_forward_dct pub; /* public fields */ /* Pointer to the DCT routine actually in use */ - forward_DCT_method_ptr do_dct; + forward_DCT_method_ptr do_dct[MAX_COMPONENTS]; /* The actual post-DCT divisors --- not identical to the quant table * entries, because of scaling (especially for an unnormalized DCT). @@ -33,7 +33,7 @@ typedef struct { #ifdef DCT_FLOAT_SUPPORTED /* Same as above for the floating-point case. */ - float_DCT_method_ptr do_float_dct; + float_DCT_method_ptr do_float_dct[MAX_COMPONENTS]; FAST_FLOAT * float_divisors[NUM_QUANT_TBLS]; #endif } my_fdct_controller; @@ -41,131 +41,16 @@ typedef struct { typedef my_fdct_controller * my_fdct_ptr; -/* - * Initialize for a processing pass. - * Verify that all referenced Q-tables are present, and set up - * the divisor table for each one. - * In the current implementation, DCT of all components is done during - * the first pass, even if only some components will be output in the - * first scan. Hence all components should be examined here. +/* The current scaled-DCT routines require ISLOW-style divisor tables, + * so be sure to compile that code if either ISLOW or SCALING is requested. */ - -METHODDEF(void) -start_pass_fdctmgr (j_compress_ptr cinfo) -{ - my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; - int ci, qtblno, i; - jpeg_component_info *compptr; - JQUANT_TBL * qtbl; - DCTELEM * dtbl; - - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - qtblno = compptr->quant_tbl_no; - /* Make sure specified quantization table is present */ - if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || - cinfo->quant_tbl_ptrs[qtblno] == NULL) - ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); - qtbl = cinfo->quant_tbl_ptrs[qtblno]; - /* Compute divisors for this quant table */ - /* We may do this more than once for same table, but it's not a big deal */ - switch (cinfo->dct_method) { #ifdef DCT_ISLOW_SUPPORTED - case JDCT_ISLOW: - /* For LL&M IDCT method, divisors are equal to raw quantization - * coefficients multiplied by 8 (to counteract scaling). - */ - if (fdct->divisors[qtblno] == NULL) { - fdct->divisors[qtblno] = (DCTELEM *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - DCTSIZE2 * SIZEOF(DCTELEM)); - } - dtbl = fdct->divisors[qtblno]; - for (i = 0; i < DCTSIZE2; i++) { - dtbl[i] = ((DCTELEM) qtbl->quantval[i]) << 3; - } - break; +#define PROVIDE_ISLOW_TABLES +#else +#ifdef DCT_SCALING_SUPPORTED +#define PROVIDE_ISLOW_TABLES #endif -#ifdef DCT_IFAST_SUPPORTED - case JDCT_IFAST: - { - /* For AA&N IDCT method, divisors are equal to quantization - * coefficients scaled by scalefactor[row]*scalefactor[col], where - * scalefactor[0] = 1 - * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 - * We apply a further scale factor of 8. - */ -#define CONST_BITS 14 - static const INT16 aanscales[DCTSIZE2] = { - /* precomputed values scaled up by 14 bits */ - 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, - 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, - 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, - 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, - 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, - 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, - 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, - 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 - }; - SHIFT_TEMPS - - if (fdct->divisors[qtblno] == NULL) { - fdct->divisors[qtblno] = (DCTELEM *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - DCTSIZE2 * SIZEOF(DCTELEM)); - } - dtbl = fdct->divisors[qtblno]; - for (i = 0; i < DCTSIZE2; i++) { - dtbl[i] = (DCTELEM) - DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i], - (INT32) aanscales[i]), - CONST_BITS-3); - } - } - break; #endif -#ifdef DCT_FLOAT_SUPPORTED - case JDCT_FLOAT: - { - /* For float AA&N IDCT method, divisors are equal to quantization - * coefficients scaled by scalefactor[row]*scalefactor[col], where - * scalefactor[0] = 1 - * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 - * We apply a further scale factor of 8. - * What's actually stored is 1/divisor so that the inner loop can - * use a multiplication rather than a division. - */ - FAST_FLOAT * fdtbl; - int row, col; - static const double aanscalefactor[DCTSIZE] = { - 1.0, 1.387039845, 1.306562965, 1.175875602, - 1.0, 0.785694958, 0.541196100, 0.275899379 - }; - - if (fdct->float_divisors[qtblno] == NULL) { - fdct->float_divisors[qtblno] = (FAST_FLOAT *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - DCTSIZE2 * SIZEOF(FAST_FLOAT)); - } - fdtbl = fdct->float_divisors[qtblno]; - i = 0; - for (row = 0; row < DCTSIZE; row++) { - for (col = 0; col < DCTSIZE; col++) { - fdtbl[i] = (FAST_FLOAT) - (1.0 / (((double) qtbl->quantval[i] * - aanscalefactor[row] * aanscalefactor[col] * 8.0))); - i++; - } - } - } - break; -#endif - default: - ERREXIT(cinfo, JERR_NOT_COMPILED); - break; - } - } -} /* @@ -185,43 +70,16 @@ forward_DCT (j_compress_ptr cinfo, jpeg_component_info * compptr, { /* This routine is heavily used, so it's worth coding it tightly. */ my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; - forward_DCT_method_ptr do_dct = fdct->do_dct; + forward_DCT_method_ptr do_dct = fdct->do_dct[compptr->component_index]; DCTELEM * divisors = fdct->divisors[compptr->quant_tbl_no]; DCTELEM workspace[DCTSIZE2]; /* work area for FDCT subroutine */ JDIMENSION bi; sample_data += start_row; /* fold in the vertical offset once */ - for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) { - /* Load data into workspace, applying unsigned->signed conversion */ - { register DCTELEM *workspaceptr; - register JSAMPROW elemptr; - register int elemr; - - workspaceptr = workspace; - for (elemr = 0; elemr < DCTSIZE; elemr++) { - elemptr = sample_data[elemr] + start_col; -#if DCTSIZE == 8 /* unroll the inner loop */ - *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; - *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; - *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; - *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; - *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; - *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; - *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; - *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; -#else - { register int elemc; - for (elemc = DCTSIZE; elemc > 0; elemc--) { - *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; - } - } -#endif - } - } - + for (bi = 0; bi < num_blocks; bi++, start_col += compptr->DCT_h_scaled_size) { /* Perform the DCT */ - (*do_dct) (workspace); + (*do_dct) (workspace, sample_data, start_col); /* Quantize/descale the coefficients, and store into coef_blocks[] */ { register DCTELEM temp, qval; @@ -275,44 +133,16 @@ forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr, { /* This routine is heavily used, so it's worth coding it tightly. */ my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; - float_DCT_method_ptr do_dct = fdct->do_float_dct; + float_DCT_method_ptr do_dct = fdct->do_float_dct[compptr->component_index]; FAST_FLOAT * divisors = fdct->float_divisors[compptr->quant_tbl_no]; FAST_FLOAT workspace[DCTSIZE2]; /* work area for FDCT subroutine */ JDIMENSION bi; sample_data += start_row; /* fold in the vertical offset once */ - for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) { - /* Load data into workspace, applying unsigned->signed conversion */ - { register FAST_FLOAT *workspaceptr; - register JSAMPROW elemptr; - register int elemr; - - workspaceptr = workspace; - for (elemr = 0; elemr < DCTSIZE; elemr++) { - elemptr = sample_data[elemr] + start_col; -#if DCTSIZE == 8 /* unroll the inner loop */ - *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); - *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); - *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); - *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); - *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); - *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); - *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); - *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); -#else - { register int elemc; - for (elemc = DCTSIZE; elemc > 0; elemc--) { - *workspaceptr++ = (FAST_FLOAT) - (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); - } - } -#endif - } - } - + for (bi = 0; bi < num_blocks; bi++, start_col += compptr->DCT_h_scaled_size) { /* Perform the DCT */ - (*do_dct) (workspace); + (*do_dct) (workspace, sample_data, start_col); /* Quantize/descale the coefficients, and store into coef_blocks[] */ { register FAST_FLOAT temp; @@ -337,6 +167,295 @@ forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr, #endif /* DCT_FLOAT_SUPPORTED */ +/* + * Initialize for a processing pass. + * Verify that all referenced Q-tables are present, and set up + * the divisor table for each one. + * In the current implementation, DCT of all components is done during + * the first pass, even if only some components will be output in the + * first scan. Hence all components should be examined here. + */ + +METHODDEF(void) +start_pass_fdctmgr (j_compress_ptr cinfo) +{ + my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; + int ci, qtblno, i; + jpeg_component_info *compptr; + int method = 0; + JQUANT_TBL * qtbl; + DCTELEM * dtbl; + + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Select the proper DCT routine for this component's scaling */ + switch ((compptr->DCT_h_scaled_size << 8) + compptr->DCT_v_scaled_size) { +#ifdef DCT_SCALING_SUPPORTED + case ((1 << 8) + 1): + fdct->do_dct[ci] = jpeg_fdct_1x1; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((2 << 8) + 2): + fdct->do_dct[ci] = jpeg_fdct_2x2; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((3 << 8) + 3): + fdct->do_dct[ci] = jpeg_fdct_3x3; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((4 << 8) + 4): + fdct->do_dct[ci] = jpeg_fdct_4x4; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((5 << 8) + 5): + fdct->do_dct[ci] = jpeg_fdct_5x5; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((6 << 8) + 6): + fdct->do_dct[ci] = jpeg_fdct_6x6; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((7 << 8) + 7): + fdct->do_dct[ci] = jpeg_fdct_7x7; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((9 << 8) + 9): + fdct->do_dct[ci] = jpeg_fdct_9x9; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((10 << 8) + 10): + fdct->do_dct[ci] = jpeg_fdct_10x10; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((11 << 8) + 11): + fdct->do_dct[ci] = jpeg_fdct_11x11; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((12 << 8) + 12): + fdct->do_dct[ci] = jpeg_fdct_12x12; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((13 << 8) + 13): + fdct->do_dct[ci] = jpeg_fdct_13x13; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((14 << 8) + 14): + fdct->do_dct[ci] = jpeg_fdct_14x14; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((15 << 8) + 15): + fdct->do_dct[ci] = jpeg_fdct_15x15; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((16 << 8) + 16): + fdct->do_dct[ci] = jpeg_fdct_16x16; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((16 << 8) + 8): + fdct->do_dct[ci] = jpeg_fdct_16x8; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((14 << 8) + 7): + fdct->do_dct[ci] = jpeg_fdct_14x7; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((12 << 8) + 6): + fdct->do_dct[ci] = jpeg_fdct_12x6; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((10 << 8) + 5): + fdct->do_dct[ci] = jpeg_fdct_10x5; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((8 << 8) + 4): + fdct->do_dct[ci] = jpeg_fdct_8x4; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((6 << 8) + 3): + fdct->do_dct[ci] = jpeg_fdct_6x3; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((4 << 8) + 2): + fdct->do_dct[ci] = jpeg_fdct_4x2; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((2 << 8) + 1): + fdct->do_dct[ci] = jpeg_fdct_2x1; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((8 << 8) + 16): + fdct->do_dct[ci] = jpeg_fdct_8x16; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((7 << 8) + 14): + fdct->do_dct[ci] = jpeg_fdct_7x14; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((6 << 8) + 12): + fdct->do_dct[ci] = jpeg_fdct_6x12; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((5 << 8) + 10): + fdct->do_dct[ci] = jpeg_fdct_5x10; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((4 << 8) + 8): + fdct->do_dct[ci] = jpeg_fdct_4x8; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((3 << 8) + 6): + fdct->do_dct[ci] = jpeg_fdct_3x6; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((2 << 8) + 4): + fdct->do_dct[ci] = jpeg_fdct_2x4; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; + case ((1 << 8) + 2): + fdct->do_dct[ci] = jpeg_fdct_1x2; + method = JDCT_ISLOW; /* jfdctint uses islow-style table */ + break; +#endif + case ((DCTSIZE << 8) + DCTSIZE): + switch (cinfo->dct_method) { +#ifdef DCT_ISLOW_SUPPORTED + case JDCT_ISLOW: + fdct->do_dct[ci] = jpeg_fdct_islow; + method = JDCT_ISLOW; + break; +#endif +#ifdef DCT_IFAST_SUPPORTED + case JDCT_IFAST: + fdct->do_dct[ci] = jpeg_fdct_ifast; + method = JDCT_IFAST; + break; +#endif +#ifdef DCT_FLOAT_SUPPORTED + case JDCT_FLOAT: + fdct->do_float_dct[ci] = jpeg_fdct_float; + method = JDCT_FLOAT; + break; +#endif + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } + break; + default: + ERREXIT2(cinfo, JERR_BAD_DCTSIZE, + compptr->DCT_h_scaled_size, compptr->DCT_v_scaled_size); + break; + } + qtblno = compptr->quant_tbl_no; + /* Make sure specified quantization table is present */ + if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || + cinfo->quant_tbl_ptrs[qtblno] == NULL) + ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); + qtbl = cinfo->quant_tbl_ptrs[qtblno]; + /* Compute divisors for this quant table */ + /* We may do this more than once for same table, but it's not a big deal */ + switch (method) { +#ifdef PROVIDE_ISLOW_TABLES + case JDCT_ISLOW: + /* For LL&M IDCT method, divisors are equal to raw quantization + * coefficients multiplied by 8 (to counteract scaling). + */ + if (fdct->divisors[qtblno] == NULL) { + fdct->divisors[qtblno] = (DCTELEM *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + DCTSIZE2 * SIZEOF(DCTELEM)); + } + dtbl = fdct->divisors[qtblno]; + for (i = 0; i < DCTSIZE2; i++) { + dtbl[i] = ((DCTELEM) qtbl->quantval[i]) << 3; + } + fdct->pub.forward_DCT[ci] = forward_DCT; + break; +#endif +#ifdef DCT_IFAST_SUPPORTED + case JDCT_IFAST: + { + /* For AA&N IDCT method, divisors are equal to quantization + * coefficients scaled by scalefactor[row]*scalefactor[col], where + * scalefactor[0] = 1 + * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + * We apply a further scale factor of 8. + */ +#define CONST_BITS 14 + static const INT16 aanscales[DCTSIZE2] = { + /* precomputed values scaled up by 14 bits */ + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, + 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, + 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, + 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, + 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 + }; + SHIFT_TEMPS + + if (fdct->divisors[qtblno] == NULL) { + fdct->divisors[qtblno] = (DCTELEM *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + DCTSIZE2 * SIZEOF(DCTELEM)); + } + dtbl = fdct->divisors[qtblno]; + for (i = 0; i < DCTSIZE2; i++) { + dtbl[i] = (DCTELEM) + DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i], + (INT32) aanscales[i]), + CONST_BITS-3); + } + } + fdct->pub.forward_DCT[ci] = forward_DCT; + break; +#endif +#ifdef DCT_FLOAT_SUPPORTED + case JDCT_FLOAT: + { + /* For float AA&N IDCT method, divisors are equal to quantization + * coefficients scaled by scalefactor[row]*scalefactor[col], where + * scalefactor[0] = 1 + * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + * We apply a further scale factor of 8. + * What's actually stored is 1/divisor so that the inner loop can + * use a multiplication rather than a division. + */ + FAST_FLOAT * fdtbl; + int row, col; + static const double aanscalefactor[DCTSIZE] = { + 1.0, 1.387039845, 1.306562965, 1.175875602, + 1.0, 0.785694958, 0.541196100, 0.275899379 + }; + + if (fdct->float_divisors[qtblno] == NULL) { + fdct->float_divisors[qtblno] = (FAST_FLOAT *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + DCTSIZE2 * SIZEOF(FAST_FLOAT)); + } + fdtbl = fdct->float_divisors[qtblno]; + i = 0; + for (row = 0; row < DCTSIZE; row++) { + for (col = 0; col < DCTSIZE; col++) { + fdtbl[i] = (FAST_FLOAT) + (1.0 / (((double) qtbl->quantval[i] * + aanscalefactor[row] * aanscalefactor[col] * 8.0))); + i++; + } + } + } + fdct->pub.forward_DCT[ci] = forward_DCT_float; + break; +#endif + default: + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; + } + } +} + + /* * Initialize FDCT manager. */ @@ -353,30 +472,6 @@ jinit_forward_dct (j_compress_ptr cinfo) cinfo->fdct = (struct jpeg_forward_dct *) fdct; fdct->pub.start_pass = start_pass_fdctmgr; - switch (cinfo->dct_method) { -#ifdef DCT_ISLOW_SUPPORTED - case JDCT_ISLOW: - fdct->pub.forward_DCT = forward_DCT; - fdct->do_dct = jpeg_fdct_islow; - break; -#endif -#ifdef DCT_IFAST_SUPPORTED - case JDCT_IFAST: - fdct->pub.forward_DCT = forward_DCT; - fdct->do_dct = jpeg_fdct_ifast; - break; -#endif -#ifdef DCT_FLOAT_SUPPORTED - case JDCT_FLOAT: - fdct->pub.forward_DCT = forward_DCT_float; - fdct->do_float_dct = jpeg_fdct_float; - break; -#endif - default: - ERREXIT(cinfo, JERR_NOT_COMPILED); - break; - } - /* Mark divisor tables unallocated */ for (i = 0; i < NUM_QUANT_TBLS; i++) { fdct->divisors[i] = NULL; diff --git a/reactos/dll/3rdparty/libjpeg/jchuff.c b/reactos/dll/3rdparty/libjpeg/jchuff.c index f2352505486..257d7aa1f54 100644 --- a/reactos/dll/3rdparty/libjpeg/jchuff.c +++ b/reactos/dll/3rdparty/libjpeg/jchuff.c @@ -2,22 +2,48 @@ * jchuff.c * * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 2006-2009 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains Huffman entropy encoding routines. + * Both sequential and progressive modes are supported in this single module. * * Much of the complexity here has to do with supporting output suspension. * If the data destination module demands suspension, we want to be able to * back up to the start of the current MCU. To do this, we copy state * variables into local working storage, and update them back to the * permanent JPEG objects only upon successful completion of an MCU. + * + * We do not support output suspension for the progressive JPEG mode, since + * the library currently does not allow multiple-scan files to be written + * with output suspension. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" -#include "jchuff.h" /* Declarations shared with jcphuff.c */ + + +/* The legal range of a DCT coefficient is + * -1024 .. +1023 for 8-bit data; + * -16384 .. +16383 for 12-bit data. + * Hence the magnitude should always fit in 10 or 14 bits respectively. + */ + +#if BITS_IN_JSAMPLE == 8 +#define MAX_COEF_BITS 10 +#else +#define MAX_COEF_BITS 14 +#endif + +/* Derived data constructed for each Huffman table */ + +typedef struct { + unsigned int ehufco[256]; /* code for each symbol */ + char ehufsi[256]; /* length of code for each symbol */ + /* If no code has been allocated for a symbol S, ehufsi[S] contains 0 */ +} c_derived_tbl; /* Expanded entropy encoder object for Huffman encoding. @@ -65,15 +91,32 @@ typedef struct { c_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS]; c_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS]; -#ifdef ENTROPY_OPT_SUPPORTED /* Statistics tables for optimization */ + /* Statistics tables for optimization */ long * dc_count_ptrs[NUM_HUFF_TBLS]; long * ac_count_ptrs[NUM_HUFF_TBLS]; -#endif + + /* Following fields used only in progressive mode */ + + /* Mode flag: TRUE for optimization, FALSE for actual data output */ + boolean gather_statistics; + + /* next_output_byte/free_in_buffer are local copies of cinfo->dest fields. + */ + JOCTET * next_output_byte; /* => next byte to write in buffer */ + size_t free_in_buffer; /* # of byte spaces remaining in buffer */ + j_compress_ptr cinfo; /* link to cinfo (needed for dump_buffer) */ + + /* Coding status for AC components */ + int ac_tbl_no; /* the table number of the single component */ + unsigned int EOBRUN; /* run length of EOBs */ + unsigned int BE; /* # of buffered correction bits before MCU */ + char * bit_buffer; /* buffer for correction bits (1 per char) */ + /* packing correction bits tightly would save some space but cost time... */ } huff_entropy_encoder; typedef huff_entropy_encoder * huff_entropy_ptr; -/* Working state while writing an MCU. +/* Working state while writing an MCU (sequential mode). * This struct contains all the fields that are needed by subroutines. */ @@ -84,98 +127,37 @@ typedef struct { j_compress_ptr cinfo; /* dump_buffer needs access to this */ } working_state; - -/* Forward declarations */ -METHODDEF(boolean) encode_mcu_huff JPP((j_compress_ptr cinfo, - JBLOCKROW *MCU_data)); -METHODDEF(void) finish_pass_huff JPP((j_compress_ptr cinfo)); -#ifdef ENTROPY_OPT_SUPPORTED -METHODDEF(boolean) encode_mcu_gather JPP((j_compress_ptr cinfo, - JBLOCKROW *MCU_data)); -METHODDEF(void) finish_pass_gather JPP((j_compress_ptr cinfo)); -#endif - - -/* - * Initialize for a Huffman-compressed scan. - * If gather_statistics is TRUE, we do not output anything during the scan, - * just count the Huffman symbols used and generate Huffman code tables. +/* MAX_CORR_BITS is the number of bits the AC refinement correction-bit + * buffer can hold. Larger sizes may slightly improve compression, but + * 1000 is already well into the realm of overkill. + * The minimum safe size is 64 bits. */ -METHODDEF(void) -start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics) -{ - huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; - int ci, dctbl, actbl; - jpeg_component_info * compptr; +#define MAX_CORR_BITS 1000 /* Max # of correction bits I can buffer */ - if (gather_statistics) { -#ifdef ENTROPY_OPT_SUPPORTED - entropy->pub.encode_mcu = encode_mcu_gather; - entropy->pub.finish_pass = finish_pass_gather; +/* IRIGHT_SHIFT is like RIGHT_SHIFT, but works on int rather than INT32. + * We assume that int right shift is unsigned if INT32 right shift is, + * which should be safe. + */ + +#ifdef RIGHT_SHIFT_IS_UNSIGNED +#define ISHIFT_TEMPS int ishift_temp; +#define IRIGHT_SHIFT(x,shft) \ + ((ishift_temp = (x)) < 0 ? \ + (ishift_temp >> (shft)) | ((~0) << (16-(shft))) : \ + (ishift_temp >> (shft))) #else - ERREXIT(cinfo, JERR_NOT_COMPILED); +#define ISHIFT_TEMPS +#define IRIGHT_SHIFT(x,shft) ((x) >> (shft)) #endif - } else { - entropy->pub.encode_mcu = encode_mcu_huff; - entropy->pub.finish_pass = finish_pass_huff; - } - - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - dctbl = compptr->dc_tbl_no; - actbl = compptr->ac_tbl_no; - if (gather_statistics) { -#ifdef ENTROPY_OPT_SUPPORTED - /* Check for invalid table indexes */ - /* (make_c_derived_tbl does this in the other path) */ - if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS) - ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl); - if (actbl < 0 || actbl >= NUM_HUFF_TBLS) - ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, actbl); - /* Allocate and zero the statistics tables */ - /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */ - if (entropy->dc_count_ptrs[dctbl] == NULL) - entropy->dc_count_ptrs[dctbl] = (long *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - 257 * SIZEOF(long)); - MEMZERO(entropy->dc_count_ptrs[dctbl], 257 * SIZEOF(long)); - if (entropy->ac_count_ptrs[actbl] == NULL) - entropy->ac_count_ptrs[actbl] = (long *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - 257 * SIZEOF(long)); - MEMZERO(entropy->ac_count_ptrs[actbl], 257 * SIZEOF(long)); -#endif - } else { - /* Compute derived values for Huffman tables */ - /* We may do this more than once for a table, but it's not expensive */ - jpeg_make_c_derived_tbl(cinfo, TRUE, dctbl, - & entropy->dc_derived_tbls[dctbl]); - jpeg_make_c_derived_tbl(cinfo, FALSE, actbl, - & entropy->ac_derived_tbls[actbl]); - } - /* Initialize DC predictions to 0 */ - entropy->saved.last_dc_val[ci] = 0; - } - - /* Initialize bit buffer to empty */ - entropy->saved.put_buffer = 0; - entropy->saved.put_bits = 0; - - /* Initialize restart stuff */ - entropy->restarts_to_go = cinfo->restart_interval; - entropy->next_restart_num = 0; -} /* * Compute the derived values for a Huffman table. * This routine also performs some validation checks on the table. - * - * Note this is also used by jcphuff.c. */ -GLOBAL(void) +LOCAL(void) jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno, c_derived_tbl ** pdtbl) { @@ -264,18 +246,27 @@ jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno, } -/* Outputting bytes to the file */ +/* Outputting bytes to the file. + * NB: these must be called only when actually outputting, + * that is, entropy->gather_statistics == FALSE. + */ /* Emit a byte, taking 'action' if must suspend. */ -#define emit_byte(state,val,action) \ +#define emit_byte_s(state,val,action) \ { *(state)->next_output_byte++ = (JOCTET) (val); \ if (--(state)->free_in_buffer == 0) \ - if (! dump_buffer(state)) \ + if (! dump_buffer_s(state)) \ { action; } } +/* Emit a byte */ +#define emit_byte_e(entropy,val) \ + { *(entropy)->next_output_byte++ = (JOCTET) (val); \ + if (--(entropy)->free_in_buffer == 0) \ + dump_buffer_e(entropy); } + LOCAL(boolean) -dump_buffer (working_state * state) +dump_buffer_s (working_state * state) /* Empty the output buffer; return TRUE if successful, FALSE if must suspend */ { struct jpeg_destination_mgr * dest = state->cinfo->dest; @@ -289,6 +280,20 @@ dump_buffer (working_state * state) } +LOCAL(void) +dump_buffer_e (huff_entropy_ptr entropy) +/* Empty the output buffer; we do not support suspension in this case. */ +{ + struct jpeg_destination_mgr * dest = entropy->cinfo->dest; + + if (! (*dest->empty_output_buffer) (entropy->cinfo)) + ERREXIT(entropy->cinfo, JERR_CANT_SUSPEND); + /* After a successful buffer dump, must reset buffer pointers */ + entropy->next_output_byte = dest->next_output_byte; + entropy->free_in_buffer = dest->free_in_buffer; +} + + /* Outputting bits to the file */ /* Only the right 24 bits of put_buffer are used; the valid bits are @@ -299,7 +304,7 @@ dump_buffer (working_state * state) INLINE LOCAL(boolean) -emit_bits (working_state * state, unsigned int code, int size) +emit_bits_s (working_state * state, unsigned int code, int size) /* Emit some bits; return TRUE if successful, FALSE if must suspend */ { /* This routine is heavily used, so it's worth coding tightly. */ @@ -321,9 +326,9 @@ emit_bits (working_state * state, unsigned int code, int size) while (put_bits >= 8) { int c = (int) ((put_buffer >> 16) & 0xFF); - emit_byte(state, c, return FALSE); + emit_byte_s(state, c, return FALSE); if (c == 0xFF) { /* need to stuff a zero byte? */ - emit_byte(state, 0, return FALSE); + emit_byte_s(state, 0, return FALSE); } put_buffer <<= 8; put_bits -= 8; @@ -336,17 +341,575 @@ emit_bits (working_state * state, unsigned int code, int size) } -LOCAL(boolean) -flush_bits (working_state * state) +INLINE +LOCAL(void) +emit_bits_e (huff_entropy_ptr entropy, unsigned int code, int size) +/* Emit some bits, unless we are in gather mode */ { - if (! emit_bits(state, 0x7F, 7)) /* fill any partial byte with ones */ + /* This routine is heavily used, so it's worth coding tightly. */ + register INT32 put_buffer = (INT32) code; + register int put_bits = entropy->saved.put_bits; + + /* if size is 0, caller used an invalid Huffman table entry */ + if (size == 0) + ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE); + + if (entropy->gather_statistics) + return; /* do nothing if we're only getting stats */ + + put_buffer &= (((INT32) 1)<saved.put_buffer; + + while (put_bits >= 8) { + int c = (int) ((put_buffer >> 16) & 0xFF); + + emit_byte_e(entropy, c); + if (c == 0xFF) { /* need to stuff a zero byte? */ + emit_byte_e(entropy, 0); + } + put_buffer <<= 8; + put_bits -= 8; + } + + entropy->saved.put_buffer = put_buffer; /* update variables */ + entropy->saved.put_bits = put_bits; +} + + +LOCAL(boolean) +flush_bits_s (working_state * state) +{ + if (! emit_bits_s(state, 0x7F, 7)) /* fill any partial byte with ones */ return FALSE; - state->cur.put_buffer = 0; /* and reset bit-buffer to empty */ + state->cur.put_buffer = 0; /* and reset bit-buffer to empty */ state->cur.put_bits = 0; return TRUE; } +LOCAL(void) +flush_bits_e (huff_entropy_ptr entropy) +{ + emit_bits_e(entropy, 0x7F, 7); /* fill any partial byte with ones */ + entropy->saved.put_buffer = 0; /* and reset bit-buffer to empty */ + entropy->saved.put_bits = 0; +} + + +/* + * Emit (or just count) a Huffman symbol. + */ + +INLINE +LOCAL(void) +emit_dc_symbol (huff_entropy_ptr entropy, int tbl_no, int symbol) +{ + if (entropy->gather_statistics) + entropy->dc_count_ptrs[tbl_no][symbol]++; + else { + c_derived_tbl * tbl = entropy->dc_derived_tbls[tbl_no]; + emit_bits_e(entropy, tbl->ehufco[symbol], tbl->ehufsi[symbol]); + } +} + + +INLINE +LOCAL(void) +emit_ac_symbol (huff_entropy_ptr entropy, int tbl_no, int symbol) +{ + if (entropy->gather_statistics) + entropy->ac_count_ptrs[tbl_no][symbol]++; + else { + c_derived_tbl * tbl = entropy->ac_derived_tbls[tbl_no]; + emit_bits_e(entropy, tbl->ehufco[symbol], tbl->ehufsi[symbol]); + } +} + + +/* + * Emit bits from a correction bit buffer. + */ + +LOCAL(void) +emit_buffered_bits (huff_entropy_ptr entropy, char * bufstart, + unsigned int nbits) +{ + if (entropy->gather_statistics) + return; /* no real work */ + + while (nbits > 0) { + emit_bits_e(entropy, (unsigned int) (*bufstart), 1); + bufstart++; + nbits--; + } +} + + +/* + * Emit any pending EOBRUN symbol. + */ + +LOCAL(void) +emit_eobrun (huff_entropy_ptr entropy) +{ + register int temp, nbits; + + if (entropy->EOBRUN > 0) { /* if there is any pending EOBRUN */ + temp = entropy->EOBRUN; + nbits = 0; + while ((temp >>= 1)) + nbits++; + /* safety check: shouldn't happen given limited correction-bit buffer */ + if (nbits > 14) + ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE); + + emit_ac_symbol(entropy, entropy->ac_tbl_no, nbits << 4); + if (nbits) + emit_bits_e(entropy, entropy->EOBRUN, nbits); + + entropy->EOBRUN = 0; + + /* Emit any buffered correction bits */ + emit_buffered_bits(entropy, entropy->bit_buffer, entropy->BE); + entropy->BE = 0; + } +} + + +/* + * Emit a restart marker & resynchronize predictions. + */ + +LOCAL(boolean) +emit_restart_s (working_state * state, int restart_num) +{ + int ci; + + if (! flush_bits_s(state)) + return FALSE; + + emit_byte_s(state, 0xFF, return FALSE); + emit_byte_s(state, JPEG_RST0 + restart_num, return FALSE); + + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < state->cinfo->comps_in_scan; ci++) + state->cur.last_dc_val[ci] = 0; + + /* The restart counter is not updated until we successfully write the MCU. */ + + return TRUE; +} + + +LOCAL(void) +emit_restart_e (huff_entropy_ptr entropy, int restart_num) +{ + int ci; + + emit_eobrun(entropy); + + if (! entropy->gather_statistics) { + flush_bits_e(entropy); + emit_byte_e(entropy, 0xFF); + emit_byte_e(entropy, JPEG_RST0 + restart_num); + } + + if (entropy->cinfo->Ss == 0) { + /* Re-initialize DC predictions to 0 */ + for (ci = 0; ci < entropy->cinfo->comps_in_scan; ci++) + entropy->saved.last_dc_val[ci] = 0; + } else { + /* Re-initialize all AC-related fields to 0 */ + entropy->EOBRUN = 0; + entropy->BE = 0; + } +} + + +/* + * MCU encoding for DC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + register int temp, temp2; + register int nbits; + int blkn, ci; + int Al = cinfo->Al; + JBLOCKROW block; + jpeg_component_info * compptr; + ISHIFT_TEMPS + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) + if (entropy->restarts_to_go == 0) + emit_restart_e(entropy, entropy->next_restart_num); + + /* Encode the MCU data blocks */ + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + block = MCU_data[blkn]; + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + + /* Compute the DC value after the required point transform by Al. + * This is simply an arithmetic right shift. + */ + temp2 = IRIGHT_SHIFT((int) ((*block)[0]), Al); + + /* DC differences are figured on the point-transformed values. */ + temp = temp2 - entropy->saved.last_dc_val[ci]; + entropy->saved.last_dc_val[ci] = temp2; + + /* Encode the DC coefficient difference per section G.1.2.1 */ + temp2 = temp; + if (temp < 0) { + temp = -temp; /* temp is abs value of input */ + /* For a negative input, want temp2 = bitwise complement of abs(input) */ + /* This code assumes we are on a two's complement machine */ + temp2--; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 0; + while (temp) { + nbits++; + temp >>= 1; + } + /* Check for out-of-range coefficient values. + * Since we're encoding a difference, the range limit is twice as much. + */ + if (nbits > MAX_COEF_BITS+1) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); + + /* Count/emit the Huffman-coded symbol for the number of bits */ + emit_dc_symbol(entropy, compptr->dc_tbl_no, nbits); + + /* Emit that number of bits of the value, if positive, */ + /* or the complement of its magnitude, if negative. */ + if (nbits) /* emit_bits rejects calls with size 0 */ + emit_bits_e(entropy, (unsigned int) temp2, nbits); + } + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * MCU encoding for AC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + register int temp, temp2; + register int nbits; + register int r, k; + int Se, Al; + const int * natural_order; + JBLOCKROW block; + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) + if (entropy->restarts_to_go == 0) + emit_restart_e(entropy, entropy->next_restart_num); + + Se = cinfo->Se; + Al = cinfo->Al; + natural_order = cinfo->natural_order; + + /* Encode the MCU data block */ + block = MCU_data[0]; + + /* Encode the AC coefficients per section G.1.2.2, fig. G.3 */ + + r = 0; /* r = run length of zeros */ + + for (k = cinfo->Ss; k <= Se; k++) { + if ((temp = (*block)[natural_order[k]]) == 0) { + r++; + continue; + } + /* We must apply the point transform by Al. For AC coefficients this + * is an integer division with rounding towards 0. To do this portably + * in C, we shift after obtaining the absolute value; so the code is + * interwoven with finding the abs value (temp) and output bits (temp2). + */ + if (temp < 0) { + temp = -temp; /* temp is abs value of input */ + temp >>= Al; /* apply the point transform */ + /* For a negative coef, want temp2 = bitwise complement of abs(coef) */ + temp2 = ~temp; + } else { + temp >>= Al; /* apply the point transform */ + temp2 = temp; + } + /* Watch out for case that nonzero coef is zero after point transform */ + if (temp == 0) { + r++; + continue; + } + + /* Emit any pending EOBRUN */ + if (entropy->EOBRUN > 0) + emit_eobrun(entropy); + /* if run length > 15, must emit special run-length-16 codes (0xF0) */ + while (r > 15) { + emit_ac_symbol(entropy, entropy->ac_tbl_no, 0xF0); + r -= 16; + } + + /* Find the number of bits needed for the magnitude of the coefficient */ + nbits = 1; /* there must be at least one 1 bit */ + while ((temp >>= 1)) + nbits++; + /* Check for out-of-range coefficient values */ + if (nbits > MAX_COEF_BITS) + ERREXIT(cinfo, JERR_BAD_DCT_COEF); + + /* Count/emit Huffman symbol for run length / number of bits */ + emit_ac_symbol(entropy, entropy->ac_tbl_no, (r << 4) + nbits); + + /* Emit that number of bits of the value, if positive, */ + /* or the complement of its magnitude, if negative. */ + emit_bits_e(entropy, (unsigned int) temp2, nbits); + + r = 0; /* reset zero run length */ + } + + if (r > 0) { /* If there are trailing zeroes, */ + entropy->EOBRUN++; /* count an EOB */ + if (entropy->EOBRUN == 0x7FFF) + emit_eobrun(entropy); /* force it out to avoid overflow */ + } + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * MCU encoding for DC successive approximation refinement scan. + * Note: we assume such scans can be multi-component, although the spec + * is not very clear on the point. + */ + +METHODDEF(boolean) +encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + register int temp; + int blkn; + int Al = cinfo->Al; + JBLOCKROW block; + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) + if (entropy->restarts_to_go == 0) + emit_restart_e(entropy, entropy->next_restart_num); + + /* Encode the MCU data blocks */ + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + block = MCU_data[blkn]; + + /* We simply emit the Al'th bit of the DC coefficient value. */ + temp = (*block)[0]; + emit_bits_e(entropy, (unsigned int) (temp >> Al), 1); + } + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + +/* + * MCU encoding for AC successive approximation refinement scan. + */ + +METHODDEF(boolean) +encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + register int temp; + register int r, k; + int EOB; + char *BR_buffer; + unsigned int BR; + int Se, Al; + const int * natural_order; + JBLOCKROW block; + int absvalues[DCTSIZE2]; + + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; + + /* Emit restart marker if needed */ + if (cinfo->restart_interval) + if (entropy->restarts_to_go == 0) + emit_restart_e(entropy, entropy->next_restart_num); + + Se = cinfo->Se; + Al = cinfo->Al; + natural_order = cinfo->natural_order; + + /* Encode the MCU data block */ + block = MCU_data[0]; + + /* It is convenient to make a pre-pass to determine the transformed + * coefficients' absolute values and the EOB position. + */ + EOB = 0; + for (k = cinfo->Ss; k <= Se; k++) { + temp = (*block)[natural_order[k]]; + /* We must apply the point transform by Al. For AC coefficients this + * is an integer division with rounding towards 0. To do this portably + * in C, we shift after obtaining the absolute value. + */ + if (temp < 0) + temp = -temp; /* temp is abs value of input */ + temp >>= Al; /* apply the point transform */ + absvalues[k] = temp; /* save abs value for main pass */ + if (temp == 1) + EOB = k; /* EOB = index of last newly-nonzero coef */ + } + + /* Encode the AC coefficients per section G.1.2.3, fig. G.7 */ + + r = 0; /* r = run length of zeros */ + BR = 0; /* BR = count of buffered bits added now */ + BR_buffer = entropy->bit_buffer + entropy->BE; /* Append bits to buffer */ + + for (k = cinfo->Ss; k <= Se; k++) { + if ((temp = absvalues[k]) == 0) { + r++; + continue; + } + + /* Emit any required ZRLs, but not if they can be folded into EOB */ + while (r > 15 && k <= EOB) { + /* emit any pending EOBRUN and the BE correction bits */ + emit_eobrun(entropy); + /* Emit ZRL */ + emit_ac_symbol(entropy, entropy->ac_tbl_no, 0xF0); + r -= 16; + /* Emit buffered correction bits that must be associated with ZRL */ + emit_buffered_bits(entropy, BR_buffer, BR); + BR_buffer = entropy->bit_buffer; /* BE bits are gone now */ + BR = 0; + } + + /* If the coef was previously nonzero, it only needs a correction bit. + * NOTE: a straight translation of the spec's figure G.7 would suggest + * that we also need to test r > 15. But if r > 15, we can only get here + * if k > EOB, which implies that this coefficient is not 1. + */ + if (temp > 1) { + /* The correction bit is the next bit of the absolute value. */ + BR_buffer[BR++] = (char) (temp & 1); + continue; + } + + /* Emit any pending EOBRUN and the BE correction bits */ + emit_eobrun(entropy); + + /* Count/emit Huffman symbol for run length / number of bits */ + emit_ac_symbol(entropy, entropy->ac_tbl_no, (r << 4) + 1); + + /* Emit output bit for newly-nonzero coef */ + temp = ((*block)[natural_order[k]] < 0) ? 0 : 1; + emit_bits_e(entropy, (unsigned int) temp, 1); + + /* Emit buffered correction bits that must be associated with this code */ + emit_buffered_bits(entropy, BR_buffer, BR); + BR_buffer = entropy->bit_buffer; /* BE bits are gone now */ + BR = 0; + r = 0; /* reset zero run length */ + } + + if (r > 0 || BR > 0) { /* If there are trailing zeroes, */ + entropy->EOBRUN++; /* count an EOB */ + entropy->BE += BR; /* concat my correction bits to older ones */ + /* We force out the EOB if we risk either: + * 1. overflow of the EOB counter; + * 2. overflow of the correction bit buffer during the next MCU. + */ + if (entropy->EOBRUN == 0x7FFF || entropy->BE > (MAX_CORR_BITS-DCTSIZE2+1)) + emit_eobrun(entropy); + } + + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; + + /* Update restart-interval state too */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) { + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num++; + entropy->next_restart_num &= 7; + } + entropy->restarts_to_go--; + } + + return TRUE; +} + + /* Encode a single block's worth of coefficients */ LOCAL(boolean) @@ -356,9 +919,11 @@ encode_one_block (working_state * state, JCOEFPTR block, int last_dc_val, register int temp, temp2; register int nbits; register int k, r, i; - + int Se = state->cinfo->lim_Se; + const int * natural_order = state->cinfo->natural_order; + /* Encode the DC coefficient difference per section F.1.2.1 */ - + temp = temp2 = block[0] - last_dc_val; if (temp < 0) { @@ -367,7 +932,7 @@ encode_one_block (working_state * state, JCOEFPTR block, int last_dc_val, /* This code assumes we are on a two's complement machine */ temp2--; } - + /* Find the number of bits needed for the magnitude of the coefficient */ nbits = 0; while (temp) { @@ -379,28 +944,28 @@ encode_one_block (working_state * state, JCOEFPTR block, int last_dc_val, */ if (nbits > MAX_COEF_BITS+1) ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); - + /* Emit the Huffman-coded symbol for the number of bits */ - if (! emit_bits(state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits])) + if (! emit_bits_s(state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits])) return FALSE; /* Emit that number of bits of the value, if positive, */ /* or the complement of its magnitude, if negative. */ if (nbits) /* emit_bits rejects calls with size 0 */ - if (! emit_bits(state, (unsigned int) temp2, nbits)) + if (! emit_bits_s(state, (unsigned int) temp2, nbits)) return FALSE; /* Encode the AC coefficients per section F.1.2.2 */ - + r = 0; /* r = run length of zeros */ - - for (k = 1; k < DCTSIZE2; k++) { - if ((temp = block[jpeg_natural_order[k]]) == 0) { + + for (k = 1; k <= Se; k++) { + if ((temp = block[natural_order[k]]) == 0) { r++; } else { /* if run length > 15, must emit special run-length-16 codes (0xF0) */ while (r > 15) { - if (! emit_bits(state, actbl->ehufco[0xF0], actbl->ehufsi[0xF0])) + if (! emit_bits_s(state, actbl->ehufco[0xF0], actbl->ehufsi[0xF0])) return FALSE; r -= 16; } @@ -411,7 +976,7 @@ encode_one_block (working_state * state, JCOEFPTR block, int last_dc_val, /* This code assumes we are on a two's complement machine */ temp2--; } - + /* Find the number of bits needed for the magnitude of the coefficient */ nbits = 1; /* there must be at least one 1 bit */ while ((temp >>= 1)) @@ -419,55 +984,30 @@ encode_one_block (working_state * state, JCOEFPTR block, int last_dc_val, /* Check for out-of-range coefficient values */ if (nbits > MAX_COEF_BITS) ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); - + /* Emit Huffman symbol for run length / number of bits */ i = (r << 4) + nbits; - if (! emit_bits(state, actbl->ehufco[i], actbl->ehufsi[i])) + if (! emit_bits_s(state, actbl->ehufco[i], actbl->ehufsi[i])) return FALSE; /* Emit that number of bits of the value, if positive, */ /* or the complement of its magnitude, if negative. */ - if (! emit_bits(state, (unsigned int) temp2, nbits)) + if (! emit_bits_s(state, (unsigned int) temp2, nbits)) return FALSE; - + r = 0; } } /* If the last coef(s) were zero, emit an end-of-block code */ if (r > 0) - if (! emit_bits(state, actbl->ehufco[0], actbl->ehufsi[0])) + if (! emit_bits_s(state, actbl->ehufco[0], actbl->ehufsi[0])) return FALSE; return TRUE; } -/* - * Emit a restart marker & resynchronize predictions. - */ - -LOCAL(boolean) -emit_restart (working_state * state, int restart_num) -{ - int ci; - - if (! flush_bits(state)) - return FALSE; - - emit_byte(state, 0xFF, return FALSE); - emit_byte(state, JPEG_RST0 + restart_num, return FALSE); - - /* Re-initialize DC predictions to 0 */ - for (ci = 0; ci < state->cinfo->comps_in_scan; ci++) - state->cur.last_dc_val[ci] = 0; - - /* The restart counter is not updated until we successfully write the MCU. */ - - return TRUE; -} - - /* * Encode and output one MCU's worth of Huffman-compressed coefficients. */ @@ -489,7 +1029,7 @@ encode_mcu_huff (j_compress_ptr cinfo, JBLOCKROW *MCU_data) /* Emit restart marker if needed */ if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) - if (! emit_restart(&state, entropy->next_restart_num)) + if (! emit_restart_s(&state, entropy->next_restart_num)) return FALSE; } @@ -535,20 +1075,32 @@ finish_pass_huff (j_compress_ptr cinfo) huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; working_state state; - /* Load up working state ... flush_bits needs it */ - state.next_output_byte = cinfo->dest->next_output_byte; - state.free_in_buffer = cinfo->dest->free_in_buffer; - ASSIGN_STATE(state.cur, entropy->saved); - state.cinfo = cinfo; + if (cinfo->progressive_mode) { + entropy->next_output_byte = cinfo->dest->next_output_byte; + entropy->free_in_buffer = cinfo->dest->free_in_buffer; - /* Flush out the last data */ - if (! flush_bits(&state)) - ERREXIT(cinfo, JERR_CANT_SUSPEND); + /* Flush out any buffered data */ + emit_eobrun(entropy); + flush_bits_e(entropy); - /* Update state */ - cinfo->dest->next_output_byte = state.next_output_byte; - cinfo->dest->free_in_buffer = state.free_in_buffer; - ASSIGN_STATE(entropy->saved, state.cur); + cinfo->dest->next_output_byte = entropy->next_output_byte; + cinfo->dest->free_in_buffer = entropy->free_in_buffer; + } else { + /* Load up working state ... flush_bits needs it */ + state.next_output_byte = cinfo->dest->next_output_byte; + state.free_in_buffer = cinfo->dest->free_in_buffer; + ASSIGN_STATE(state.cur, entropy->saved); + state.cinfo = cinfo; + + /* Flush out the last data */ + if (! flush_bits_s(&state)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + + /* Update state */ + cinfo->dest->next_output_byte = state.next_output_byte; + cinfo->dest->free_in_buffer = state.free_in_buffer; + ASSIGN_STATE(entropy->saved, state.cur); + } } @@ -563,8 +1115,6 @@ finish_pass_huff (j_compress_ptr cinfo) * the compressed data. */ -#ifdef ENTROPY_OPT_SUPPORTED - /* Process a single block's worth of coefficients */ @@ -575,6 +1125,8 @@ htest_one_block (j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val, register int temp; register int nbits; register int k, r; + int Se = cinfo->lim_Se; + const int * natural_order = cinfo->natural_order; /* Encode the DC coefficient difference per section F.1.2.1 */ @@ -601,8 +1153,8 @@ htest_one_block (j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val, r = 0; /* r = run length of zeros */ - for (k = 1; k < DCTSIZE2; k++) { - if ((temp = block[jpeg_natural_order[k]]) == 0) { + for (k = 1; k <= Se; k++) { + if ((temp = block[natural_order[k]]) == 0) { r++; } else { /* if run length > 15, must emit special run-length-16 codes (0xF0) */ @@ -675,7 +1227,6 @@ encode_mcu_gather (j_compress_ptr cinfo, JBLOCKROW *MCU_data) /* * Generate the best Huffman code table for the given counts, fill htbl. - * Note this is also used by jcphuff.c. * * The JPEG standard requires that no symbol be assigned a codeword of all * one bits (so that padding bits added at the end of a compressed segment @@ -701,7 +1252,7 @@ encode_mcu_gather (j_compress_ptr cinfo, JBLOCKROW *MCU_data) * So the extra complexity of an optimal algorithm doesn't seem worthwhile. */ -GLOBAL(void) +LOCAL(void) jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[]) { #define MAX_CLEN 32 /* assumed maximum initial code length */ @@ -846,7 +1397,7 @@ METHODDEF(void) finish_pass_gather (j_compress_ptr cinfo) { huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; - int ci, dctbl, actbl; + int ci, tbl; jpeg_component_info * compptr; JHUFF_TBL **htblptr; boolean did_dc[NUM_HUFF_TBLS]; @@ -855,32 +1406,147 @@ finish_pass_gather (j_compress_ptr cinfo) /* It's important not to apply jpeg_gen_optimal_table more than once * per table, because it clobbers the input frequency counts! */ + if (cinfo->progressive_mode) + /* Flush out buffered data (all we care about is counting the EOB symbol) */ + emit_eobrun(entropy); + MEMZERO(did_dc, SIZEOF(did_dc)); MEMZERO(did_ac, SIZEOF(did_ac)); for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; - dctbl = compptr->dc_tbl_no; - actbl = compptr->ac_tbl_no; - if (! did_dc[dctbl]) { - htblptr = & cinfo->dc_huff_tbl_ptrs[dctbl]; - if (*htblptr == NULL) - *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); - jpeg_gen_optimal_table(cinfo, *htblptr, entropy->dc_count_ptrs[dctbl]); - did_dc[dctbl] = TRUE; + /* DC needs no table for refinement scan */ + if (cinfo->Ss == 0 && cinfo->Ah == 0) { + tbl = compptr->dc_tbl_no; + if (! did_dc[tbl]) { + htblptr = & cinfo->dc_huff_tbl_ptrs[tbl]; + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + jpeg_gen_optimal_table(cinfo, *htblptr, entropy->dc_count_ptrs[tbl]); + did_dc[tbl] = TRUE; + } } - if (! did_ac[actbl]) { - htblptr = & cinfo->ac_huff_tbl_ptrs[actbl]; - if (*htblptr == NULL) - *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); - jpeg_gen_optimal_table(cinfo, *htblptr, entropy->ac_count_ptrs[actbl]); - did_ac[actbl] = TRUE; + /* AC needs no table when not present */ + if (cinfo->Se) { + tbl = compptr->ac_tbl_no; + if (! did_ac[tbl]) { + htblptr = & cinfo->ac_huff_tbl_ptrs[tbl]; + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + jpeg_gen_optimal_table(cinfo, *htblptr, entropy->ac_count_ptrs[tbl]); + did_ac[tbl] = TRUE; + } } } } -#endif /* ENTROPY_OPT_SUPPORTED */ +/* + * Initialize for a Huffman-compressed scan. + * If gather_statistics is TRUE, we do not output anything during the scan, + * just count the Huffman symbols used and generate Huffman code tables. + */ + +METHODDEF(void) +start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int ci, tbl; + jpeg_component_info * compptr; + + if (gather_statistics) + entropy->pub.finish_pass = finish_pass_gather; + else + entropy->pub.finish_pass = finish_pass_huff; + + if (cinfo->progressive_mode) { + entropy->cinfo = cinfo; + entropy->gather_statistics = gather_statistics; + + /* We assume jcmaster.c already validated the scan parameters. */ + + /* Select execution routine */ + if (cinfo->Ah == 0) { + if (cinfo->Ss == 0) + entropy->pub.encode_mcu = encode_mcu_DC_first; + else + entropy->pub.encode_mcu = encode_mcu_AC_first; + } else { + if (cinfo->Ss == 0) + entropy->pub.encode_mcu = encode_mcu_DC_refine; + else { + entropy->pub.encode_mcu = encode_mcu_AC_refine; + /* AC refinement needs a correction bit buffer */ + if (entropy->bit_buffer == NULL) + entropy->bit_buffer = (char *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + MAX_CORR_BITS * SIZEOF(char)); + } + } + + /* Initialize AC stuff */ + entropy->ac_tbl_no = cinfo->cur_comp_info[0]->ac_tbl_no; + entropy->EOBRUN = 0; + entropy->BE = 0; + } else { + if (gather_statistics) + entropy->pub.encode_mcu = encode_mcu_gather; + else + entropy->pub.encode_mcu = encode_mcu_huff; + } + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* DC needs no table for refinement scan */ + if (cinfo->Ss == 0 && cinfo->Ah == 0) { + tbl = compptr->dc_tbl_no; + if (gather_statistics) { + /* Check for invalid table index */ + /* (make_c_derived_tbl does this in the other path) */ + if (tbl < 0 || tbl >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tbl); + /* Allocate and zero the statistics tables */ + /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */ + if (entropy->dc_count_ptrs[tbl] == NULL) + entropy->dc_count_ptrs[tbl] = (long *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + 257 * SIZEOF(long)); + MEMZERO(entropy->dc_count_ptrs[tbl], 257 * SIZEOF(long)); + } else { + /* Compute derived values for Huffman tables */ + /* We may do this more than once for a table, but it's not expensive */ + jpeg_make_c_derived_tbl(cinfo, TRUE, tbl, + & entropy->dc_derived_tbls[tbl]); + } + /* Initialize DC predictions to 0 */ + entropy->saved.last_dc_val[ci] = 0; + } + /* AC needs no table when not present */ + if (cinfo->Se) { + tbl = compptr->ac_tbl_no; + if (gather_statistics) { + if (tbl < 0 || tbl >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tbl); + if (entropy->ac_count_ptrs[tbl] == NULL) + entropy->ac_count_ptrs[tbl] = (long *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + 257 * SIZEOF(long)); + MEMZERO(entropy->ac_count_ptrs[tbl], 257 * SIZEOF(long)); + } else { + jpeg_make_c_derived_tbl(cinfo, FALSE, tbl, + & entropy->ac_derived_tbls[tbl]); + } + } + } + + /* Initialize bit buffer to empty */ + entropy->saved.put_buffer = 0; + entropy->saved.put_bits = 0; + + /* Initialize restart stuff */ + entropy->restarts_to_go = cinfo->restart_interval; + entropy->next_restart_num = 0; +} /* @@ -902,8 +1568,9 @@ jinit_huff_encoder (j_compress_ptr cinfo) /* Mark tables unallocated */ for (i = 0; i < NUM_HUFF_TBLS; i++) { entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL; -#ifdef ENTROPY_OPT_SUPPORTED entropy->dc_count_ptrs[i] = entropy->ac_count_ptrs[i] = NULL; -#endif } + + if (cinfo->progressive_mode) + entropy->bit_buffer = NULL; /* needed only in AC refinement scan */ } diff --git a/reactos/dll/3rdparty/libjpeg/jchuff.h b/reactos/dll/3rdparty/libjpeg/jchuff.h deleted file mode 100644 index a9599fc1e6f..00000000000 --- a/reactos/dll/3rdparty/libjpeg/jchuff.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * jchuff.h - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains declarations for Huffman entropy encoding routines - * that are shared between the sequential encoder (jchuff.c) and the - * progressive encoder (jcphuff.c). No other modules need to see these. - */ - -/* The legal range of a DCT coefficient is - * -1024 .. +1023 for 8-bit data; - * -16384 .. +16383 for 12-bit data. - * Hence the magnitude should always fit in 10 or 14 bits respectively. - */ - -#if BITS_IN_JSAMPLE == 8 -#define MAX_COEF_BITS 10 -#else -#define MAX_COEF_BITS 14 -#endif - -/* Derived data constructed for each Huffman table */ - -typedef struct { - unsigned int ehufco[256]; /* code for each symbol */ - char ehufsi[256]; /* length of code for each symbol */ - /* If no code has been allocated for a symbol S, ehufsi[S] contains 0 */ -} c_derived_tbl; - -/* Short forms of external names for systems with brain-damaged linkers. */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jpeg_make_c_derived_tbl jMkCDerived -#define jpeg_gen_optimal_table jGenOptTbl -#endif /* NEED_SHORT_EXTERNAL_NAMES */ - -/* Expand a Huffman table definition into the derived format */ -EXTERN(void) jpeg_make_c_derived_tbl - JPP((j_compress_ptr cinfo, boolean isDC, int tblno, - c_derived_tbl ** pdtbl)); - -/* Generate an optimal table definition given the specified counts */ -EXTERN(void) jpeg_gen_optimal_table - JPP((j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[])); diff --git a/reactos/dll/3rdparty/libjpeg/jcinit.c b/reactos/dll/3rdparty/libjpeg/jcinit.c index 5efffe33166..0ba310f217d 100644 --- a/reactos/dll/3rdparty/libjpeg/jcinit.c +++ b/reactos/dll/3rdparty/libjpeg/jcinit.c @@ -41,17 +41,10 @@ jinit_compress_master (j_compress_ptr cinfo) /* Forward DCT */ jinit_forward_dct(cinfo); /* Entropy encoding: either Huffman or arithmetic coding. */ - if (cinfo->arith_code) { - ERREXIT(cinfo, JERR_ARITH_NOTIMPL); - } else { - if (cinfo->progressive_mode) { -#ifdef C_PROGRESSIVE_SUPPORTED - jinit_phuff_encoder(cinfo); -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } else - jinit_huff_encoder(cinfo); + if (cinfo->arith_code) + jinit_arith_encoder(cinfo); + else { + jinit_huff_encoder(cinfo); } /* Need a full-image coefficient buffer in any multi-pass mode. */ diff --git a/reactos/dll/3rdparty/libjpeg/jcmainct.c b/reactos/dll/3rdparty/libjpeg/jcmainct.c index e0279a7e017..7de75d16758 100644 --- a/reactos/dll/3rdparty/libjpeg/jcmainct.c +++ b/reactos/dll/3rdparty/libjpeg/jcmainct.c @@ -118,17 +118,17 @@ process_data_simple_main (j_compress_ptr cinfo, while (main->cur_iMCU_row < cinfo->total_iMCU_rows) { /* Read input data if we haven't filled the main buffer yet */ - if (main->rowgroup_ctr < DCTSIZE) + if (main->rowgroup_ctr < (JDIMENSION) cinfo->min_DCT_v_scaled_size) (*cinfo->prep->pre_process_data) (cinfo, input_buf, in_row_ctr, in_rows_avail, main->buffer, &main->rowgroup_ctr, - (JDIMENSION) DCTSIZE); + (JDIMENSION) cinfo->min_DCT_v_scaled_size); /* If we don't have a full iMCU row buffered, return to application for * more data. Note that preprocessor will always pad to fill the iMCU row * at the bottom of the image. */ - if (main->rowgroup_ctr != DCTSIZE) + if (main->rowgroup_ctr != (JDIMENSION) cinfo->min_DCT_v_scaled_size) return; /* Send the completed row to the compressor */ @@ -269,10 +269,10 @@ jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer) ci++, compptr++) { main->whole_image[ci] = (*cinfo->mem->request_virt_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, - compptr->width_in_blocks * DCTSIZE, + compptr->width_in_blocks * compptr->DCT_h_scaled_size, (JDIMENSION) jround_up((long) compptr->height_in_blocks, (long) compptr->v_samp_factor) * DCTSIZE, - (JDIMENSION) (compptr->v_samp_factor * DCTSIZE)); + (JDIMENSION) (compptr->v_samp_factor * compptr->DCT_v_scaled_size)); } #else ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); @@ -286,8 +286,8 @@ jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer) ci++, compptr++) { main->buffer[ci] = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, - compptr->width_in_blocks * DCTSIZE, - (JDIMENSION) (compptr->v_samp_factor * DCTSIZE)); + compptr->width_in_blocks * compptr->DCT_h_scaled_size, + (JDIMENSION) (compptr->v_samp_factor * compptr->DCT_v_scaled_size)); } } } diff --git a/reactos/dll/3rdparty/libjpeg/jcmarker.c b/reactos/dll/3rdparty/libjpeg/jcmarker.c index 3d1e6c6d524..2e289834245 100644 --- a/reactos/dll/3rdparty/libjpeg/jcmarker.c +++ b/reactos/dll/3rdparty/libjpeg/jcmarker.c @@ -2,6 +2,7 @@ * jcmarker.c * * Copyright (C) 1991-1998, Thomas G. Lane. + * Modified 2003-2009 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -153,21 +154,22 @@ emit_dqt (j_compress_ptr cinfo, int index) ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, index); prec = 0; - for (i = 0; i < DCTSIZE2; i++) { - if (qtbl->quantval[i] > 255) + for (i = 0; i <= cinfo->lim_Se; i++) { + if (qtbl->quantval[cinfo->natural_order[i]] > 255) prec = 1; } if (! qtbl->sent_table) { emit_marker(cinfo, M_DQT); - emit_2bytes(cinfo, prec ? DCTSIZE2*2 + 1 + 2 : DCTSIZE2 + 1 + 2); + emit_2bytes(cinfo, + prec ? cinfo->lim_Se * 2 + 2 + 1 + 2 : cinfo->lim_Se + 1 + 1 + 2); emit_byte(cinfo, index + (prec<<4)); - for (i = 0; i < DCTSIZE2; i++) { + for (i = 0; i <= cinfo->lim_Se; i++) { /* The table entries must be emitted in zigzag order. */ - unsigned int qval = qtbl->quantval[jpeg_natural_order[i]]; + unsigned int qval = qtbl->quantval[cinfo->natural_order[i]]; if (prec) emit_byte(cinfo, (int) (qval >> 8)); emit_byte(cinfo, (int) (qval & 0xFF)); @@ -235,8 +237,12 @@ emit_dac (j_compress_ptr cinfo) for (i = 0; i < cinfo->comps_in_scan; i++) { compptr = cinfo->cur_comp_info[i]; - dc_in_use[compptr->dc_tbl_no] = 1; - ac_in_use[compptr->ac_tbl_no] = 1; + /* DC needs no table for refinement scan */ + if (cinfo->Ss == 0 && cinfo->Ah == 0) + dc_in_use[compptr->dc_tbl_no] = 1; + /* AC needs no table when not present */ + if (cinfo->Se) + ac_in_use[compptr->ac_tbl_no] = 1; } length = 0; @@ -285,13 +291,13 @@ emit_sof (j_compress_ptr cinfo, JPEG_MARKER code) emit_2bytes(cinfo, 3 * cinfo->num_components + 2 + 5 + 1); /* length */ /* Make sure image isn't bigger than SOF field can handle */ - if ((long) cinfo->image_height > 65535L || - (long) cinfo->image_width > 65535L) + if ((long) cinfo->jpeg_height > 65535L || + (long) cinfo->jpeg_width > 65535L) ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) 65535); emit_byte(cinfo, cinfo->data_precision); - emit_2bytes(cinfo, (int) cinfo->image_height); - emit_2bytes(cinfo, (int) cinfo->image_width); + emit_2bytes(cinfo, (int) cinfo->jpeg_height); + emit_2bytes(cinfo, (int) cinfo->jpeg_width); emit_byte(cinfo, cinfo->num_components); @@ -320,22 +326,16 @@ emit_sos (j_compress_ptr cinfo) for (i = 0; i < cinfo->comps_in_scan; i++) { compptr = cinfo->cur_comp_info[i]; emit_byte(cinfo, compptr->component_id); - td = compptr->dc_tbl_no; - ta = compptr->ac_tbl_no; - if (cinfo->progressive_mode) { - /* Progressive mode: only DC or only AC tables are used in one scan; - * furthermore, Huffman coding of DC refinement uses no table at all. - * We emit 0 for unused field(s); this is recommended by the P&M text - * but does not seem to be specified in the standard. - */ - if (cinfo->Ss == 0) { - ta = 0; /* DC scan */ - if (cinfo->Ah != 0 && !cinfo->arith_code) - td = 0; /* no DC table either */ - } else { - td = 0; /* AC scan */ - } - } + + /* We emit 0 for unused field(s); this is recommended by the P&M text + * but does not seem to be specified in the standard. + */ + + /* DC needs no table for refinement scan */ + td = cinfo->Ss == 0 && cinfo->Ah == 0 ? compptr->dc_tbl_no : 0; + /* AC needs no table when not present */ + ta = cinfo->Se ? compptr->ac_tbl_no : 0; + emit_byte(cinfo, (td << 4) + ta); } @@ -345,6 +345,22 @@ emit_sos (j_compress_ptr cinfo) } +LOCAL(void) +emit_pseudo_sos (j_compress_ptr cinfo) +/* Emit a pseudo SOS marker */ +{ + emit_marker(cinfo, M_SOS); + + emit_2bytes(cinfo, 2 + 1 + 3); /* length */ + + emit_byte(cinfo, 0); /* Ns */ + + emit_byte(cinfo, 0); /* Ss */ + emit_byte(cinfo, cinfo->block_size * cinfo->block_size - 1); /* Se */ + emit_byte(cinfo, 0); /* Ah/Al */ +} + + LOCAL(void) emit_jfif_app0 (j_compress_ptr cinfo) /* Emit a JFIF-compliant APP0 marker */ @@ -484,7 +500,7 @@ write_file_header (j_compress_ptr cinfo) /* * Write frame header. - * This consists of DQT and SOFn markers. + * This consists of DQT and SOFn markers, and a conditional pseudo SOS marker. * Note that we do not emit the SOF until we have emitted the DQT(s). * This avoids compatibility problems with incorrect implementations that * try to error-check the quant table numbers as soon as they see the SOF. @@ -511,7 +527,7 @@ write_frame_header (j_compress_ptr cinfo) * Note we assume that Huffman table numbers won't be changed later. */ if (cinfo->arith_code || cinfo->progressive_mode || - cinfo->data_precision != 8) { + cinfo->data_precision != 8 || cinfo->block_size != DCTSIZE) { is_baseline = FALSE; } else { is_baseline = TRUE; @@ -529,7 +545,10 @@ write_frame_header (j_compress_ptr cinfo) /* Emit the proper SOF marker */ if (cinfo->arith_code) { - emit_sof(cinfo, M_SOF9); /* SOF code for arithmetic coding */ + if (cinfo->progressive_mode) + emit_sof(cinfo, M_SOF10); /* SOF code for progressive arithmetic */ + else + emit_sof(cinfo, M_SOF9); /* SOF code for sequential arithmetic */ } else { if (cinfo->progressive_mode) emit_sof(cinfo, M_SOF2); /* SOF code for progressive Huffman */ @@ -538,6 +557,10 @@ write_frame_header (j_compress_ptr cinfo) else emit_sof(cinfo, M_SOF1); /* SOF code for non-baseline Huffman file */ } + + /* Check to emit pseudo SOS marker */ + if (cinfo->progressive_mode && cinfo->block_size != DCTSIZE) + emit_pseudo_sos(cinfo); } @@ -566,19 +589,12 @@ write_scan_header (j_compress_ptr cinfo) */ for (i = 0; i < cinfo->comps_in_scan; i++) { compptr = cinfo->cur_comp_info[i]; - if (cinfo->progressive_mode) { - /* Progressive mode: only DC or only AC tables are used in one scan */ - if (cinfo->Ss == 0) { - if (cinfo->Ah == 0) /* DC needs no table for refinement scan */ - emit_dht(cinfo, compptr->dc_tbl_no, FALSE); - } else { - emit_dht(cinfo, compptr->ac_tbl_no, TRUE); - } - } else { - /* Sequential mode: need both DC and AC tables */ + /* DC needs no table for refinement scan */ + if (cinfo->Ss == 0 && cinfo->Ah == 0) emit_dht(cinfo, compptr->dc_tbl_no, FALSE); + /* AC needs no table when not present */ + if (cinfo->Se) emit_dht(cinfo, compptr->ac_tbl_no, TRUE); - } } } diff --git a/reactos/dll/3rdparty/libjpeg/jcmaster.c b/reactos/dll/3rdparty/libjpeg/jcmaster.c index aab4020b879..660883f459a 100644 --- a/reactos/dll/3rdparty/libjpeg/jcmaster.c +++ b/reactos/dll/3rdparty/libjpeg/jcmaster.c @@ -2,6 +2,7 @@ * jcmaster.c * * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 2003-2010 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -42,23 +43,200 @@ typedef my_comp_master * my_master_ptr; * Support routines that do various essential calculations. */ -LOCAL(void) -initial_setup (j_compress_ptr cinfo) +/* + * Compute JPEG image dimensions and related values. + * NOTE: this is exported for possible use by application. + * Hence it mustn't do anything that can't be done twice. + */ + +GLOBAL(void) +jpeg_calc_jpeg_dimensions (j_compress_ptr cinfo) /* Do computations that are needed before master selection phase */ { - int ci; +#ifdef DCT_SCALING_SUPPORTED + + /* Compute actual JPEG image dimensions and DCT scaling choices. */ + if (cinfo->scale_num >= cinfo->scale_denom * 8) { + /* Provide 8/1 scaling */ + cinfo->jpeg_width = cinfo->image_width << 3; + cinfo->jpeg_height = cinfo->image_height << 3; + cinfo->min_DCT_h_scaled_size = 1; + cinfo->min_DCT_v_scaled_size = 1; + } else if (cinfo->scale_num >= cinfo->scale_denom * 4) { + /* Provide 4/1 scaling */ + cinfo->jpeg_width = cinfo->image_width << 2; + cinfo->jpeg_height = cinfo->image_height << 2; + cinfo->min_DCT_h_scaled_size = 2; + cinfo->min_DCT_v_scaled_size = 2; + } else if (cinfo->scale_num * 3 >= cinfo->scale_denom * 8) { + /* Provide 8/3 scaling */ + cinfo->jpeg_width = (cinfo->image_width << 1) + (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 2, 3L); + cinfo->jpeg_height = (cinfo->image_height << 1) + (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 2, 3L); + cinfo->min_DCT_h_scaled_size = 3; + cinfo->min_DCT_v_scaled_size = 3; + } else if (cinfo->scale_num >= cinfo->scale_denom * 2) { + /* Provide 2/1 scaling */ + cinfo->jpeg_width = cinfo->image_width << 1; + cinfo->jpeg_height = cinfo->image_height << 1; + cinfo->min_DCT_h_scaled_size = 4; + cinfo->min_DCT_v_scaled_size = 4; + } else if (cinfo->scale_num * 5 >= cinfo->scale_denom * 8) { + /* Provide 8/5 scaling */ + cinfo->jpeg_width = cinfo->image_width + (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 3, 5L); + cinfo->jpeg_height = cinfo->image_height + (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 3, 5L); + cinfo->min_DCT_h_scaled_size = 5; + cinfo->min_DCT_v_scaled_size = 5; + } else if (cinfo->scale_num * 3 >= cinfo->scale_denom * 4) { + /* Provide 4/3 scaling */ + cinfo->jpeg_width = cinfo->image_width + (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, 3L); + cinfo->jpeg_height = cinfo->image_height + (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, 3L); + cinfo->min_DCT_h_scaled_size = 6; + cinfo->min_DCT_v_scaled_size = 6; + } else if (cinfo->scale_num * 7 >= cinfo->scale_denom * 8) { + /* Provide 8/7 scaling */ + cinfo->jpeg_width = cinfo->image_width + (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, 7L); + cinfo->jpeg_height = cinfo->image_height + (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, 7L); + cinfo->min_DCT_h_scaled_size = 7; + cinfo->min_DCT_v_scaled_size = 7; + } else if (cinfo->scale_num >= cinfo->scale_denom) { + /* Provide 1/1 scaling */ + cinfo->jpeg_width = cinfo->image_width; + cinfo->jpeg_height = cinfo->image_height; + cinfo->min_DCT_h_scaled_size = 8; + cinfo->min_DCT_v_scaled_size = 8; + } else if (cinfo->scale_num * 9 >= cinfo->scale_denom * 8) { + /* Provide 8/9 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 8, 9L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 8, 9L); + cinfo->min_DCT_h_scaled_size = 9; + cinfo->min_DCT_v_scaled_size = 9; + } else if (cinfo->scale_num * 5 >= cinfo->scale_denom * 4) { + /* Provide 4/5 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 4, 5L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 4, 5L); + cinfo->min_DCT_h_scaled_size = 10; + cinfo->min_DCT_v_scaled_size = 10; + } else if (cinfo->scale_num * 11 >= cinfo->scale_denom * 8) { + /* Provide 8/11 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 8, 11L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 8, 11L); + cinfo->min_DCT_h_scaled_size = 11; + cinfo->min_DCT_v_scaled_size = 11; + } else if (cinfo->scale_num * 3 >= cinfo->scale_denom * 2) { + /* Provide 2/3 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 2, 3L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 2, 3L); + cinfo->min_DCT_h_scaled_size = 12; + cinfo->min_DCT_v_scaled_size = 12; + } else if (cinfo->scale_num * 13 >= cinfo->scale_denom * 8) { + /* Provide 8/13 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 8, 13L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 8, 13L); + cinfo->min_DCT_h_scaled_size = 13; + cinfo->min_DCT_v_scaled_size = 13; + } else if (cinfo->scale_num * 7 >= cinfo->scale_denom * 4) { + /* Provide 4/7 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 4, 7L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 4, 7L); + cinfo->min_DCT_h_scaled_size = 14; + cinfo->min_DCT_v_scaled_size = 14; + } else if (cinfo->scale_num * 15 >= cinfo->scale_denom * 8) { + /* Provide 8/15 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 8, 15L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 8, 15L); + cinfo->min_DCT_h_scaled_size = 15; + cinfo->min_DCT_v_scaled_size = 15; + } else { + /* Provide 1/2 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, 2L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, 2L); + cinfo->min_DCT_h_scaled_size = 16; + cinfo->min_DCT_v_scaled_size = 16; + } + +#else /* !DCT_SCALING_SUPPORTED */ + + /* Hardwire it to "no scaling" */ + cinfo->jpeg_width = cinfo->image_width; + cinfo->jpeg_height = cinfo->image_height; + cinfo->min_DCT_h_scaled_size = DCTSIZE; + cinfo->min_DCT_v_scaled_size = DCTSIZE; + +#endif /* DCT_SCALING_SUPPORTED */ +} + + +LOCAL(void) +jpeg_calc_trans_dimensions (j_compress_ptr cinfo) +{ + if (cinfo->min_DCT_h_scaled_size < 1 || cinfo->min_DCT_h_scaled_size > 16 + || cinfo->min_DCT_h_scaled_size != cinfo->min_DCT_v_scaled_size) + ERREXIT2(cinfo, JERR_BAD_DCTSIZE, + cinfo->min_DCT_h_scaled_size, cinfo->min_DCT_v_scaled_size); + + cinfo->block_size = cinfo->min_DCT_h_scaled_size; + + switch (cinfo->block_size) { + case 2: cinfo->natural_order = jpeg_natural_order2; break; + case 3: cinfo->natural_order = jpeg_natural_order3; break; + case 4: cinfo->natural_order = jpeg_natural_order4; break; + case 5: cinfo->natural_order = jpeg_natural_order5; break; + case 6: cinfo->natural_order = jpeg_natural_order6; break; + case 7: cinfo->natural_order = jpeg_natural_order7; break; + default: cinfo->natural_order = jpeg_natural_order; break; + } + + cinfo->lim_Se = cinfo->block_size < DCTSIZE ? + cinfo->block_size * cinfo->block_size - 1 : DCTSIZE2-1; +} + + +LOCAL(void) +initial_setup (j_compress_ptr cinfo, boolean transcode_only) +/* Do computations that are needed before master selection phase */ +{ + int ci, ssize; jpeg_component_info *compptr; long samplesperrow; JDIMENSION jd_samplesperrow; + if (transcode_only) + jpeg_calc_trans_dimensions(cinfo); + else + jpeg_calc_jpeg_dimensions(cinfo); + /* Sanity check on image dimensions */ - if (cinfo->image_height <= 0 || cinfo->image_width <= 0 - || cinfo->num_components <= 0 || cinfo->input_components <= 0) + if (cinfo->jpeg_height <= 0 || cinfo->jpeg_width <= 0 || + cinfo->num_components <= 0 || cinfo->input_components <= 0) ERREXIT(cinfo, JERR_EMPTY_IMAGE); /* Make sure image isn't bigger than I can handle */ - if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION || - (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION) + if ((long) cinfo->jpeg_height > (long) JPEG_MAX_DIMENSION || + (long) cinfo->jpeg_width > (long) JPEG_MAX_DIMENSION) ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); /* Width of an input scanline must be representable as JDIMENSION. */ @@ -95,22 +273,52 @@ initial_setup (j_compress_ptr cinfo) ci++, compptr++) { /* Fill in the correct component_index value; don't rely on application */ compptr->component_index = ci; - /* For compression, we never do DCT scaling. */ - compptr->DCT_scaled_size = DCTSIZE; + /* In selecting the actual DCT scaling for each component, we try to + * scale down the chroma components via DCT scaling rather than downsampling. + * This saves time if the downsampler gets to use 1:1 scaling. + * Note this code adapts subsampling ratios which are powers of 2. + */ + ssize = 1; +#ifdef DCT_SCALING_SUPPORTED + while (cinfo->min_DCT_h_scaled_size * ssize <= + (cinfo->do_fancy_downsampling ? DCTSIZE : DCTSIZE / 2) && + (cinfo->max_h_samp_factor % (compptr->h_samp_factor * ssize * 2)) == 0) { + ssize = ssize * 2; + } +#endif + compptr->DCT_h_scaled_size = cinfo->min_DCT_h_scaled_size * ssize; + ssize = 1; +#ifdef DCT_SCALING_SUPPORTED + while (cinfo->min_DCT_v_scaled_size * ssize <= + (cinfo->do_fancy_downsampling ? DCTSIZE : DCTSIZE / 2) && + (cinfo->max_v_samp_factor % (compptr->v_samp_factor * ssize * 2)) == 0) { + ssize = ssize * 2; + } +#endif + compptr->DCT_v_scaled_size = cinfo->min_DCT_v_scaled_size * ssize; + + /* We don't support DCT ratios larger than 2. */ + if (compptr->DCT_h_scaled_size > compptr->DCT_v_scaled_size * 2) + compptr->DCT_h_scaled_size = compptr->DCT_v_scaled_size * 2; + else if (compptr->DCT_v_scaled_size > compptr->DCT_h_scaled_size * 2) + compptr->DCT_v_scaled_size = compptr->DCT_h_scaled_size * 2; + /* Size in DCT blocks */ compptr->width_in_blocks = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, - (long) (cinfo->max_h_samp_factor * DCTSIZE)); + jdiv_round_up((long) cinfo->jpeg_width * (long) compptr->h_samp_factor, + (long) (cinfo->max_h_samp_factor * cinfo->block_size)); compptr->height_in_blocks = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, - (long) (cinfo->max_v_samp_factor * DCTSIZE)); + jdiv_round_up((long) cinfo->jpeg_height * (long) compptr->v_samp_factor, + (long) (cinfo->max_v_samp_factor * cinfo->block_size)); /* Size in samples */ compptr->downsampled_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, - (long) cinfo->max_h_samp_factor); + jdiv_round_up((long) cinfo->jpeg_width * + (long) (compptr->h_samp_factor * compptr->DCT_h_scaled_size), + (long) (cinfo->max_h_samp_factor * cinfo->block_size)); compptr->downsampled_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, - (long) cinfo->max_v_samp_factor); + jdiv_round_up((long) cinfo->jpeg_height * + (long) (compptr->v_samp_factor * compptr->DCT_v_scaled_size), + (long) (cinfo->max_v_samp_factor * cinfo->block_size)); /* Mark component needed (this flag isn't actually used for compression) */ compptr->component_needed = TRUE; } @@ -119,8 +327,8 @@ initial_setup (j_compress_ptr cinfo) * main controller will call coefficient controller). */ cinfo->total_iMCU_rows = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height, - (long) (cinfo->max_v_samp_factor*DCTSIZE)); + jdiv_round_up((long) cinfo->jpeg_height, + (long) (cinfo->max_v_samp_factor * cinfo->block_size)); } @@ -260,6 +468,39 @@ validate_script (j_compress_ptr cinfo) } } + +LOCAL(void) +reduce_script (j_compress_ptr cinfo) +/* Adapt scan script for use with reduced block size; + * assume that script has been validated before. + */ +{ + jpeg_scan_info * scanptr; + int idxout, idxin; + + /* Circumvent const declaration for this function */ + scanptr = (jpeg_scan_info *) cinfo->scan_info; + idxout = 0; + + for (idxin = 0; idxin < cinfo->num_scans; idxin++) { + /* After skipping, idxout becomes smaller than idxin */ + if (idxin != idxout) + /* Copy rest of data; + * note we stay in given chunk of allocated memory. + */ + scanptr[idxout] = scanptr[idxin]; + if (scanptr[idxout].Ss > cinfo->lim_Se) + /* Entire scan out of range - skip this entry */ + continue; + if (scanptr[idxout].Se > cinfo->lim_Se) + /* Limit scan to end of block */ + scanptr[idxout].Se = cinfo->lim_Se; + idxout++; + } + + cinfo->num_scans = idxout; +} + #endif /* C_MULTISCAN_FILES_SUPPORTED */ @@ -280,10 +521,13 @@ select_scan_parameters (j_compress_ptr cinfo) cinfo->cur_comp_info[ci] = &cinfo->comp_info[scanptr->component_index[ci]]; } - cinfo->Ss = scanptr->Ss; - cinfo->Se = scanptr->Se; - cinfo->Ah = scanptr->Ah; - cinfo->Al = scanptr->Al; + if (cinfo->progressive_mode) { + cinfo->Ss = scanptr->Ss; + cinfo->Se = scanptr->Se; + cinfo->Ah = scanptr->Ah; + cinfo->Al = scanptr->Al; + return; + } } else #endif @@ -296,11 +540,11 @@ select_scan_parameters (j_compress_ptr cinfo) for (ci = 0; ci < cinfo->num_components; ci++) { cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci]; } - cinfo->Ss = 0; - cinfo->Se = DCTSIZE2-1; - cinfo->Ah = 0; - cinfo->Al = 0; } + cinfo->Ss = 0; + cinfo->Se = cinfo->block_size * cinfo->block_size - 1; + cinfo->Ah = 0; + cinfo->Al = 0; } @@ -325,7 +569,7 @@ per_scan_setup (j_compress_ptr cinfo) compptr->MCU_width = 1; compptr->MCU_height = 1; compptr->MCU_blocks = 1; - compptr->MCU_sample_width = DCTSIZE; + compptr->MCU_sample_width = compptr->DCT_h_scaled_size; compptr->last_col_width = 1; /* For noninterleaved scans, it is convenient to define last_row_height * as the number of block rows present in the last iMCU row. @@ -347,11 +591,11 @@ per_scan_setup (j_compress_ptr cinfo) /* Overall image size in MCUs */ cinfo->MCUs_per_row = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width, - (long) (cinfo->max_h_samp_factor*DCTSIZE)); + jdiv_round_up((long) cinfo->jpeg_width, + (long) (cinfo->max_h_samp_factor * cinfo->block_size)); cinfo->MCU_rows_in_scan = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height, - (long) (cinfo->max_v_samp_factor*DCTSIZE)); + jdiv_round_up((long) cinfo->jpeg_height, + (long) (cinfo->max_v_samp_factor * cinfo->block_size)); cinfo->blocks_in_MCU = 0; @@ -361,7 +605,7 @@ per_scan_setup (j_compress_ptr cinfo) compptr->MCU_width = compptr->h_samp_factor; compptr->MCU_height = compptr->v_samp_factor; compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height; - compptr->MCU_sample_width = compptr->MCU_width * DCTSIZE; + compptr->MCU_sample_width = compptr->MCU_width * compptr->DCT_h_scaled_size; /* Figure number of non-dummy blocks in last MCU column & row */ tmp = (int) (compptr->width_in_blocks % compptr->MCU_width); if (tmp == 0) tmp = compptr->MCU_width; @@ -433,7 +677,7 @@ prepare_for_pass (j_compress_ptr cinfo) /* Do Huffman optimization for a scan after the first one. */ select_scan_parameters(cinfo); per_scan_setup(cinfo); - if (cinfo->Ss != 0 || cinfo->Ah == 0 || cinfo->arith_code) { + if (cinfo->Ss != 0 || cinfo->Ah == 0) { (*cinfo->entropy->start_pass) (cinfo, TRUE); (*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST); master->pub.call_pass_startup = FALSE; @@ -554,11 +798,13 @@ jinit_c_master_control (j_compress_ptr cinfo, boolean transcode_only) master->pub.is_last_pass = FALSE; /* Validate parameters, determine derived values */ - initial_setup(cinfo); + initial_setup(cinfo, transcode_only); if (cinfo->scan_info != NULL) { #ifdef C_MULTISCAN_FILES_SUPPORTED validate_script(cinfo); + if (cinfo->block_size < DCTSIZE) + reduce_script(cinfo); #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif @@ -567,8 +813,10 @@ jinit_c_master_control (j_compress_ptr cinfo, boolean transcode_only) cinfo->num_scans = 1; } - if (cinfo->progressive_mode) /* TEMPORARY HACK ??? */ - cinfo->optimize_coding = TRUE; /* assume default tables no good for progressive mode */ + if ((cinfo->progressive_mode || cinfo->block_size < DCTSIZE) && + !cinfo->arith_code) /* TEMPORARY HACK ??? */ + /* assume default tables no good for progressive or downscale mode */ + cinfo->optimize_coding = TRUE; /* Initialize my private state */ if (transcode_only) { diff --git a/reactos/dll/3rdparty/libjpeg/jconfig.h b/reactos/dll/3rdparty/libjpeg/jconfig.h index afee66e672e..99172ce91c2 100644 --- a/reactos/dll/3rdparty/libjpeg/jconfig.h +++ b/reactos/dll/3rdparty/libjpeg/jconfig.h @@ -15,4 +15,4 @@ typedef unsigned char boolean; #undef NEED_SHORT_EXTERNAL_NAMES #undef INCOMPLETE_TYPES_BROKEN -typedef long INT32; +// typedef long INT32; diff --git a/reactos/dll/3rdparty/libjpeg/jcparam.c b/reactos/dll/3rdparty/libjpeg/jcparam.c index 6fc48f53653..c5e85dda550 100644 --- a/reactos/dll/3rdparty/libjpeg/jcparam.c +++ b/reactos/dll/3rdparty/libjpeg/jcparam.c @@ -2,6 +2,7 @@ * jcparam.c * * Copyright (C) 1991-1998, Thomas G. Lane. + * Modified 2003-2008 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -60,6 +61,47 @@ jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl, } +/* These are the sample quantization tables given in JPEG spec section K.1. + * The spec says that the values given produce "good" quality, and + * when divided by 2, "very good" quality. + */ +static const unsigned int std_luminance_quant_tbl[DCTSIZE2] = { + 16, 11, 10, 16, 24, 40, 51, 61, + 12, 12, 14, 19, 26, 58, 60, 55, + 14, 13, 16, 24, 40, 57, 69, 56, + 14, 17, 22, 29, 51, 87, 80, 62, + 18, 22, 37, 56, 68, 109, 103, 77, + 24, 35, 55, 64, 81, 104, 113, 92, + 49, 64, 78, 87, 103, 121, 120, 101, + 72, 92, 95, 98, 112, 100, 103, 99 +}; +static const unsigned int std_chrominance_quant_tbl[DCTSIZE2] = { + 17, 18, 24, 47, 99, 99, 99, 99, + 18, 21, 26, 66, 99, 99, 99, 99, + 24, 26, 56, 99, 99, 99, 99, 99, + 47, 66, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99 +}; + + +GLOBAL(void) +jpeg_default_qtables (j_compress_ptr cinfo, boolean force_baseline) +/* Set or change the 'quality' (quantization) setting, using default tables + * and straight percentage-scaling quality scales. + * This entry point allows different scalings for luminance and chrominance. + */ +{ + /* Set up two quantization tables using the specified scaling */ + jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl, + cinfo->q_scale_factor[0], force_baseline); + jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl, + cinfo->q_scale_factor[1], force_baseline); +} + + GLOBAL(void) jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor, boolean force_baseline) @@ -69,31 +111,6 @@ jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor, * applications that insist on a linear percentage scaling. */ { - /* These are the sample quantization tables given in JPEG spec section K.1. - * The spec says that the values given produce "good" quality, and - * when divided by 2, "very good" quality. - */ - static const unsigned int std_luminance_quant_tbl[DCTSIZE2] = { - 16, 11, 10, 16, 24, 40, 51, 61, - 12, 12, 14, 19, 26, 58, 60, 55, - 14, 13, 16, 24, 40, 57, 69, 56, - 14, 17, 22, 29, 51, 87, 80, 62, - 18, 22, 37, 56, 68, 109, 103, 77, - 24, 35, 55, 64, 81, 104, 113, 92, - 49, 64, 78, 87, 103, 121, 120, 101, - 72, 92, 95, 98, 112, 100, 103, 99 - }; - static const unsigned int std_chrominance_quant_tbl[DCTSIZE2] = { - 17, 18, 24, 47, 99, 99, 99, 99, - 18, 21, 26, 66, 99, 99, 99, 99, - 24, 26, 56, 99, 99, 99, 99, 99, - 47, 66, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99 - }; - /* Set up two quantization tables using the specified scaling */ jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl, scale_factor, force_baseline); @@ -284,6 +301,8 @@ jpeg_set_defaults (j_compress_ptr cinfo) /* Initialize everything not dependent on the color space */ + cinfo->scale_num = 1; /* 1:1 scaling */ + cinfo->scale_denom = 1; cinfo->data_precision = BITS_IN_JSAMPLE; /* Set up two quantization tables using default quality of 75 */ jpeg_set_quality(cinfo, 75, TRUE); @@ -320,6 +339,9 @@ jpeg_set_defaults (j_compress_ptr cinfo) /* By default, use the simpler non-cosited sampling alignment */ cinfo->CCIR601_sampling = FALSE; + /* By default, apply fancy downsampling */ + cinfo->do_fancy_downsampling = TRUE; + /* No input smoothing */ cinfo->smoothing_factor = 0; diff --git a/reactos/dll/3rdparty/libjpeg/jcphuff.c b/reactos/dll/3rdparty/libjpeg/jcphuff.c deleted file mode 100644 index 07f9178b01c..00000000000 --- a/reactos/dll/3rdparty/libjpeg/jcphuff.c +++ /dev/null @@ -1,833 +0,0 @@ -/* - * jcphuff.c - * - * Copyright (C) 1995-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains Huffman entropy encoding routines for progressive JPEG. - * - * We do not support output suspension in this module, since the library - * currently does not allow multiple-scan files to be written with output - * suspension. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jchuff.h" /* Declarations shared with jchuff.c */ - -#ifdef C_PROGRESSIVE_SUPPORTED - -/* Expanded entropy encoder object for progressive Huffman encoding. */ - -typedef struct { - struct jpeg_entropy_encoder pub; /* public fields */ - - /* Mode flag: TRUE for optimization, FALSE for actual data output */ - boolean gather_statistics; - - /* Bit-level coding status. - * next_output_byte/free_in_buffer are local copies of cinfo->dest fields. - */ - JOCTET * next_output_byte; /* => next byte to write in buffer */ - size_t free_in_buffer; /* # of byte spaces remaining in buffer */ - INT32 put_buffer; /* current bit-accumulation buffer */ - int put_bits; /* # of bits now in it */ - j_compress_ptr cinfo; /* link to cinfo (needed for dump_buffer) */ - - /* Coding status for DC components */ - int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ - - /* Coding status for AC components */ - int ac_tbl_no; /* the table number of the single component */ - unsigned int EOBRUN; /* run length of EOBs */ - unsigned int BE; /* # of buffered correction bits before MCU */ - char * bit_buffer; /* buffer for correction bits (1 per char) */ - /* packing correction bits tightly would save some space but cost time... */ - - unsigned int restarts_to_go; /* MCUs left in this restart interval */ - int next_restart_num; /* next restart number to write (0-7) */ - - /* Pointers to derived tables (these workspaces have image lifespan). - * Since any one scan codes only DC or only AC, we only need one set - * of tables, not one for DC and one for AC. - */ - c_derived_tbl * derived_tbls[NUM_HUFF_TBLS]; - - /* Statistics tables for optimization; again, one set is enough */ - long * count_ptrs[NUM_HUFF_TBLS]; -} phuff_entropy_encoder; - -typedef phuff_entropy_encoder * phuff_entropy_ptr; - -/* MAX_CORR_BITS is the number of bits the AC refinement correction-bit - * buffer can hold. Larger sizes may slightly improve compression, but - * 1000 is already well into the realm of overkill. - * The minimum safe size is 64 bits. - */ - -#define MAX_CORR_BITS 1000 /* Max # of correction bits I can buffer */ - -/* IRIGHT_SHIFT is like RIGHT_SHIFT, but works on int rather than INT32. - * We assume that int right shift is unsigned if INT32 right shift is, - * which should be safe. - */ - -#ifdef RIGHT_SHIFT_IS_UNSIGNED -#define ISHIFT_TEMPS int ishift_temp; -#define IRIGHT_SHIFT(x,shft) \ - ((ishift_temp = (x)) < 0 ? \ - (ishift_temp >> (shft)) | ((~0) << (16-(shft))) : \ - (ishift_temp >> (shft))) -#else -#define ISHIFT_TEMPS -#define IRIGHT_SHIFT(x,shft) ((x) >> (shft)) -#endif - -/* Forward declarations */ -METHODDEF(boolean) encode_mcu_DC_first JPP((j_compress_ptr cinfo, - JBLOCKROW *MCU_data)); -METHODDEF(boolean) encode_mcu_AC_first JPP((j_compress_ptr cinfo, - JBLOCKROW *MCU_data)); -METHODDEF(boolean) encode_mcu_DC_refine JPP((j_compress_ptr cinfo, - JBLOCKROW *MCU_data)); -METHODDEF(boolean) encode_mcu_AC_refine JPP((j_compress_ptr cinfo, - JBLOCKROW *MCU_data)); -METHODDEF(void) finish_pass_phuff JPP((j_compress_ptr cinfo)); -METHODDEF(void) finish_pass_gather_phuff JPP((j_compress_ptr cinfo)); - - -/* - * Initialize for a Huffman-compressed scan using progressive JPEG. - */ - -METHODDEF(void) -start_pass_phuff (j_compress_ptr cinfo, boolean gather_statistics) -{ - phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; - boolean is_DC_band; - int ci, tbl; - jpeg_component_info * compptr; - - entropy->cinfo = cinfo; - entropy->gather_statistics = gather_statistics; - - is_DC_band = (cinfo->Ss == 0); - - /* We assume jcmaster.c already validated the scan parameters. */ - - /* Select execution routines */ - if (cinfo->Ah == 0) { - if (is_DC_band) - entropy->pub.encode_mcu = encode_mcu_DC_first; - else - entropy->pub.encode_mcu = encode_mcu_AC_first; - } else { - if (is_DC_band) - entropy->pub.encode_mcu = encode_mcu_DC_refine; - else { - entropy->pub.encode_mcu = encode_mcu_AC_refine; - /* AC refinement needs a correction bit buffer */ - if (entropy->bit_buffer == NULL) - entropy->bit_buffer = (char *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - MAX_CORR_BITS * SIZEOF(char)); - } - } - if (gather_statistics) - entropy->pub.finish_pass = finish_pass_gather_phuff; - else - entropy->pub.finish_pass = finish_pass_phuff; - - /* Only DC coefficients may be interleaved, so cinfo->comps_in_scan = 1 - * for AC coefficients. - */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - /* Initialize DC predictions to 0 */ - entropy->last_dc_val[ci] = 0; - /* Get table index */ - if (is_DC_band) { - if (cinfo->Ah != 0) /* DC refinement needs no table */ - continue; - tbl = compptr->dc_tbl_no; - } else { - entropy->ac_tbl_no = tbl = compptr->ac_tbl_no; - } - if (gather_statistics) { - /* Check for invalid table index */ - /* (make_c_derived_tbl does this in the other path) */ - if (tbl < 0 || tbl >= NUM_HUFF_TBLS) - ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tbl); - /* Allocate and zero the statistics tables */ - /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */ - if (entropy->count_ptrs[tbl] == NULL) - entropy->count_ptrs[tbl] = (long *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - 257 * SIZEOF(long)); - MEMZERO(entropy->count_ptrs[tbl], 257 * SIZEOF(long)); - } else { - /* Compute derived values for Huffman table */ - /* We may do this more than once for a table, but it's not expensive */ - jpeg_make_c_derived_tbl(cinfo, is_DC_band, tbl, - & entropy->derived_tbls[tbl]); - } - } - - /* Initialize AC stuff */ - entropy->EOBRUN = 0; - entropy->BE = 0; - - /* Initialize bit buffer to empty */ - entropy->put_buffer = 0; - entropy->put_bits = 0; - - /* Initialize restart stuff */ - entropy->restarts_to_go = cinfo->restart_interval; - entropy->next_restart_num = 0; -} - - -/* Outputting bytes to the file. - * NB: these must be called only when actually outputting, - * that is, entropy->gather_statistics == FALSE. - */ - -/* Emit a byte */ -#define emit_byte(entropy,val) \ - { *(entropy)->next_output_byte++ = (JOCTET) (val); \ - if (--(entropy)->free_in_buffer == 0) \ - dump_buffer(entropy); } - - -LOCAL(void) -dump_buffer (phuff_entropy_ptr entropy) -/* Empty the output buffer; we do not support suspension in this module. */ -{ - struct jpeg_destination_mgr * dest = entropy->cinfo->dest; - - if (! (*dest->empty_output_buffer) (entropy->cinfo)) - ERREXIT(entropy->cinfo, JERR_CANT_SUSPEND); - /* After a successful buffer dump, must reset buffer pointers */ - entropy->next_output_byte = dest->next_output_byte; - entropy->free_in_buffer = dest->free_in_buffer; -} - - -/* Outputting bits to the file */ - -/* Only the right 24 bits of put_buffer are used; the valid bits are - * left-justified in this part. At most 16 bits can be passed to emit_bits - * in one call, and we never retain more than 7 bits in put_buffer - * between calls, so 24 bits are sufficient. - */ - -INLINE -LOCAL(void) -emit_bits (phuff_entropy_ptr entropy, unsigned int code, int size) -/* Emit some bits, unless we are in gather mode */ -{ - /* This routine is heavily used, so it's worth coding tightly. */ - register INT32 put_buffer = (INT32) code; - register int put_bits = entropy->put_bits; - - /* if size is 0, caller used an invalid Huffman table entry */ - if (size == 0) - ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE); - - if (entropy->gather_statistics) - return; /* do nothing if we're only getting stats */ - - put_buffer &= (((INT32) 1)<put_buffer; /* and merge with old buffer contents */ - - while (put_bits >= 8) { - int c = (int) ((put_buffer >> 16) & 0xFF); - - emit_byte(entropy, c); - if (c == 0xFF) { /* need to stuff a zero byte? */ - emit_byte(entropy, 0); - } - put_buffer <<= 8; - put_bits -= 8; - } - - entropy->put_buffer = put_buffer; /* update variables */ - entropy->put_bits = put_bits; -} - - -LOCAL(void) -flush_bits (phuff_entropy_ptr entropy) -{ - emit_bits(entropy, 0x7F, 7); /* fill any partial byte with ones */ - entropy->put_buffer = 0; /* and reset bit-buffer to empty */ - entropy->put_bits = 0; -} - - -/* - * Emit (or just count) a Huffman symbol. - */ - -INLINE -LOCAL(void) -emit_symbol (phuff_entropy_ptr entropy, int tbl_no, int symbol) -{ - if (entropy->gather_statistics) - entropy->count_ptrs[tbl_no][symbol]++; - else { - c_derived_tbl * tbl = entropy->derived_tbls[tbl_no]; - emit_bits(entropy, tbl->ehufco[symbol], tbl->ehufsi[symbol]); - } -} - - -/* - * Emit bits from a correction bit buffer. - */ - -LOCAL(void) -emit_buffered_bits (phuff_entropy_ptr entropy, char * bufstart, - unsigned int nbits) -{ - if (entropy->gather_statistics) - return; /* no real work */ - - while (nbits > 0) { - emit_bits(entropy, (unsigned int) (*bufstart), 1); - bufstart++; - nbits--; - } -} - - -/* - * Emit any pending EOBRUN symbol. - */ - -LOCAL(void) -emit_eobrun (phuff_entropy_ptr entropy) -{ - register int temp, nbits; - - if (entropy->EOBRUN > 0) { /* if there is any pending EOBRUN */ - temp = entropy->EOBRUN; - nbits = 0; - while ((temp >>= 1)) - nbits++; - /* safety check: shouldn't happen given limited correction-bit buffer */ - if (nbits > 14) - ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE); - - emit_symbol(entropy, entropy->ac_tbl_no, nbits << 4); - if (nbits) - emit_bits(entropy, entropy->EOBRUN, nbits); - - entropy->EOBRUN = 0; - - /* Emit any buffered correction bits */ - emit_buffered_bits(entropy, entropy->bit_buffer, entropy->BE); - entropy->BE = 0; - } -} - - -/* - * Emit a restart marker & resynchronize predictions. - */ - -LOCAL(void) -emit_restart (phuff_entropy_ptr entropy, int restart_num) -{ - int ci; - - emit_eobrun(entropy); - - if (! entropy->gather_statistics) { - flush_bits(entropy); - emit_byte(entropy, 0xFF); - emit_byte(entropy, JPEG_RST0 + restart_num); - } - - if (entropy->cinfo->Ss == 0) { - /* Re-initialize DC predictions to 0 */ - for (ci = 0; ci < entropy->cinfo->comps_in_scan; ci++) - entropy->last_dc_val[ci] = 0; - } else { - /* Re-initialize all AC-related fields to 0 */ - entropy->EOBRUN = 0; - entropy->BE = 0; - } -} - - -/* - * MCU encoding for DC initial scan (either spectral selection, - * or first pass of successive approximation). - */ - -METHODDEF(boolean) -encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) -{ - phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; - register int temp, temp2; - register int nbits; - int blkn, ci; - int Al = cinfo->Al; - JBLOCKROW block; - jpeg_component_info * compptr; - ISHIFT_TEMPS - - entropy->next_output_byte = cinfo->dest->next_output_byte; - entropy->free_in_buffer = cinfo->dest->free_in_buffer; - - /* Emit restart marker if needed */ - if (cinfo->restart_interval) - if (entropy->restarts_to_go == 0) - emit_restart(entropy, entropy->next_restart_num); - - /* Encode the MCU data blocks */ - for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - block = MCU_data[blkn]; - ci = cinfo->MCU_membership[blkn]; - compptr = cinfo->cur_comp_info[ci]; - - /* Compute the DC value after the required point transform by Al. - * This is simply an arithmetic right shift. - */ - temp2 = IRIGHT_SHIFT((int) ((*block)[0]), Al); - - /* DC differences are figured on the point-transformed values. */ - temp = temp2 - entropy->last_dc_val[ci]; - entropy->last_dc_val[ci] = temp2; - - /* Encode the DC coefficient difference per section G.1.2.1 */ - temp2 = temp; - if (temp < 0) { - temp = -temp; /* temp is abs value of input */ - /* For a negative input, want temp2 = bitwise complement of abs(input) */ - /* This code assumes we are on a two's complement machine */ - temp2--; - } - - /* Find the number of bits needed for the magnitude of the coefficient */ - nbits = 0; - while (temp) { - nbits++; - temp >>= 1; - } - /* Check for out-of-range coefficient values. - * Since we're encoding a difference, the range limit is twice as much. - */ - if (nbits > MAX_COEF_BITS+1) - ERREXIT(cinfo, JERR_BAD_DCT_COEF); - - /* Count/emit the Huffman-coded symbol for the number of bits */ - emit_symbol(entropy, compptr->dc_tbl_no, nbits); - - /* Emit that number of bits of the value, if positive, */ - /* or the complement of its magnitude, if negative. */ - if (nbits) /* emit_bits rejects calls with size 0 */ - emit_bits(entropy, (unsigned int) temp2, nbits); - } - - cinfo->dest->next_output_byte = entropy->next_output_byte; - cinfo->dest->free_in_buffer = entropy->free_in_buffer; - - /* Update restart-interval state too */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) { - entropy->restarts_to_go = cinfo->restart_interval; - entropy->next_restart_num++; - entropy->next_restart_num &= 7; - } - entropy->restarts_to_go--; - } - - return TRUE; -} - - -/* - * MCU encoding for AC initial scan (either spectral selection, - * or first pass of successive approximation). - */ - -METHODDEF(boolean) -encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) -{ - phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; - register int temp, temp2; - register int nbits; - register int r, k; - int Se = cinfo->Se; - int Al = cinfo->Al; - JBLOCKROW block; - - entropy->next_output_byte = cinfo->dest->next_output_byte; - entropy->free_in_buffer = cinfo->dest->free_in_buffer; - - /* Emit restart marker if needed */ - if (cinfo->restart_interval) - if (entropy->restarts_to_go == 0) - emit_restart(entropy, entropy->next_restart_num); - - /* Encode the MCU data block */ - block = MCU_data[0]; - - /* Encode the AC coefficients per section G.1.2.2, fig. G.3 */ - - r = 0; /* r = run length of zeros */ - - for (k = cinfo->Ss; k <= Se; k++) { - if ((temp = (*block)[jpeg_natural_order[k]]) == 0) { - r++; - continue; - } - /* We must apply the point transform by Al. For AC coefficients this - * is an integer division with rounding towards 0. To do this portably - * in C, we shift after obtaining the absolute value; so the code is - * interwoven with finding the abs value (temp) and output bits (temp2). - */ - if (temp < 0) { - temp = -temp; /* temp is abs value of input */ - temp >>= Al; /* apply the point transform */ - /* For a negative coef, want temp2 = bitwise complement of abs(coef) */ - temp2 = ~temp; - } else { - temp >>= Al; /* apply the point transform */ - temp2 = temp; - } - /* Watch out for case that nonzero coef is zero after point transform */ - if (temp == 0) { - r++; - continue; - } - - /* Emit any pending EOBRUN */ - if (entropy->EOBRUN > 0) - emit_eobrun(entropy); - /* if run length > 15, must emit special run-length-16 codes (0xF0) */ - while (r > 15) { - emit_symbol(entropy, entropy->ac_tbl_no, 0xF0); - r -= 16; - } - - /* Find the number of bits needed for the magnitude of the coefficient */ - nbits = 1; /* there must be at least one 1 bit */ - while ((temp >>= 1)) - nbits++; - /* Check for out-of-range coefficient values */ - if (nbits > MAX_COEF_BITS) - ERREXIT(cinfo, JERR_BAD_DCT_COEF); - - /* Count/emit Huffman symbol for run length / number of bits */ - emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + nbits); - - /* Emit that number of bits of the value, if positive, */ - /* or the complement of its magnitude, if negative. */ - emit_bits(entropy, (unsigned int) temp2, nbits); - - r = 0; /* reset zero run length */ - } - - if (r > 0) { /* If there are trailing zeroes, */ - entropy->EOBRUN++; /* count an EOB */ - if (entropy->EOBRUN == 0x7FFF) - emit_eobrun(entropy); /* force it out to avoid overflow */ - } - - cinfo->dest->next_output_byte = entropy->next_output_byte; - cinfo->dest->free_in_buffer = entropy->free_in_buffer; - - /* Update restart-interval state too */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) { - entropy->restarts_to_go = cinfo->restart_interval; - entropy->next_restart_num++; - entropy->next_restart_num &= 7; - } - entropy->restarts_to_go--; - } - - return TRUE; -} - - -/* - * MCU encoding for DC successive approximation refinement scan. - * Note: we assume such scans can be multi-component, although the spec - * is not very clear on the point. - */ - -METHODDEF(boolean) -encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) -{ - phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; - register int temp; - int blkn; - int Al = cinfo->Al; - JBLOCKROW block; - - entropy->next_output_byte = cinfo->dest->next_output_byte; - entropy->free_in_buffer = cinfo->dest->free_in_buffer; - - /* Emit restart marker if needed */ - if (cinfo->restart_interval) - if (entropy->restarts_to_go == 0) - emit_restart(entropy, entropy->next_restart_num); - - /* Encode the MCU data blocks */ - for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - block = MCU_data[blkn]; - - /* We simply emit the Al'th bit of the DC coefficient value. */ - temp = (*block)[0]; - emit_bits(entropy, (unsigned int) (temp >> Al), 1); - } - - cinfo->dest->next_output_byte = entropy->next_output_byte; - cinfo->dest->free_in_buffer = entropy->free_in_buffer; - - /* Update restart-interval state too */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) { - entropy->restarts_to_go = cinfo->restart_interval; - entropy->next_restart_num++; - entropy->next_restart_num &= 7; - } - entropy->restarts_to_go--; - } - - return TRUE; -} - - -/* - * MCU encoding for AC successive approximation refinement scan. - */ - -METHODDEF(boolean) -encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) -{ - phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; - register int temp; - register int r, k; - int EOB; - char *BR_buffer; - unsigned int BR; - int Se = cinfo->Se; - int Al = cinfo->Al; - JBLOCKROW block; - int absvalues[DCTSIZE2]; - - entropy->next_output_byte = cinfo->dest->next_output_byte; - entropy->free_in_buffer = cinfo->dest->free_in_buffer; - - /* Emit restart marker if needed */ - if (cinfo->restart_interval) - if (entropy->restarts_to_go == 0) - emit_restart(entropy, entropy->next_restart_num); - - /* Encode the MCU data block */ - block = MCU_data[0]; - - /* It is convenient to make a pre-pass to determine the transformed - * coefficients' absolute values and the EOB position. - */ - EOB = 0; - for (k = cinfo->Ss; k <= Se; k++) { - temp = (*block)[jpeg_natural_order[k]]; - /* We must apply the point transform by Al. For AC coefficients this - * is an integer division with rounding towards 0. To do this portably - * in C, we shift after obtaining the absolute value. - */ - if (temp < 0) - temp = -temp; /* temp is abs value of input */ - temp >>= Al; /* apply the point transform */ - absvalues[k] = temp; /* save abs value for main pass */ - if (temp == 1) - EOB = k; /* EOB = index of last newly-nonzero coef */ - } - - /* Encode the AC coefficients per section G.1.2.3, fig. G.7 */ - - r = 0; /* r = run length of zeros */ - BR = 0; /* BR = count of buffered bits added now */ - BR_buffer = entropy->bit_buffer + entropy->BE; /* Append bits to buffer */ - - for (k = cinfo->Ss; k <= Se; k++) { - if ((temp = absvalues[k]) == 0) { - r++; - continue; - } - - /* Emit any required ZRLs, but not if they can be folded into EOB */ - while (r > 15 && k <= EOB) { - /* emit any pending EOBRUN and the BE correction bits */ - emit_eobrun(entropy); - /* Emit ZRL */ - emit_symbol(entropy, entropy->ac_tbl_no, 0xF0); - r -= 16; - /* Emit buffered correction bits that must be associated with ZRL */ - emit_buffered_bits(entropy, BR_buffer, BR); - BR_buffer = entropy->bit_buffer; /* BE bits are gone now */ - BR = 0; - } - - /* If the coef was previously nonzero, it only needs a correction bit. - * NOTE: a straight translation of the spec's figure G.7 would suggest - * that we also need to test r > 15. But if r > 15, we can only get here - * if k > EOB, which implies that this coefficient is not 1. - */ - if (temp > 1) { - /* The correction bit is the next bit of the absolute value. */ - BR_buffer[BR++] = (char) (temp & 1); - continue; - } - - /* Emit any pending EOBRUN and the BE correction bits */ - emit_eobrun(entropy); - - /* Count/emit Huffman symbol for run length / number of bits */ - emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + 1); - - /* Emit output bit for newly-nonzero coef */ - temp = ((*block)[jpeg_natural_order[k]] < 0) ? 0 : 1; - emit_bits(entropy, (unsigned int) temp, 1); - - /* Emit buffered correction bits that must be associated with this code */ - emit_buffered_bits(entropy, BR_buffer, BR); - BR_buffer = entropy->bit_buffer; /* BE bits are gone now */ - BR = 0; - r = 0; /* reset zero run length */ - } - - if (r > 0 || BR > 0) { /* If there are trailing zeroes, */ - entropy->EOBRUN++; /* count an EOB */ - entropy->BE += BR; /* concat my correction bits to older ones */ - /* We force out the EOB if we risk either: - * 1. overflow of the EOB counter; - * 2. overflow of the correction bit buffer during the next MCU. - */ - if (entropy->EOBRUN == 0x7FFF || entropy->BE > (MAX_CORR_BITS-DCTSIZE2+1)) - emit_eobrun(entropy); - } - - cinfo->dest->next_output_byte = entropy->next_output_byte; - cinfo->dest->free_in_buffer = entropy->free_in_buffer; - - /* Update restart-interval state too */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) { - entropy->restarts_to_go = cinfo->restart_interval; - entropy->next_restart_num++; - entropy->next_restart_num &= 7; - } - entropy->restarts_to_go--; - } - - return TRUE; -} - - -/* - * Finish up at the end of a Huffman-compressed progressive scan. - */ - -METHODDEF(void) -finish_pass_phuff (j_compress_ptr cinfo) -{ - phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; - - entropy->next_output_byte = cinfo->dest->next_output_byte; - entropy->free_in_buffer = cinfo->dest->free_in_buffer; - - /* Flush out any buffered data */ - emit_eobrun(entropy); - flush_bits(entropy); - - cinfo->dest->next_output_byte = entropy->next_output_byte; - cinfo->dest->free_in_buffer = entropy->free_in_buffer; -} - - -/* - * Finish up a statistics-gathering pass and create the new Huffman tables. - */ - -METHODDEF(void) -finish_pass_gather_phuff (j_compress_ptr cinfo) -{ - phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; - boolean is_DC_band; - int ci, tbl; - jpeg_component_info * compptr; - JHUFF_TBL **htblptr; - boolean did[NUM_HUFF_TBLS]; - - /* Flush out buffered data (all we care about is counting the EOB symbol) */ - emit_eobrun(entropy); - - is_DC_band = (cinfo->Ss == 0); - - /* It's important not to apply jpeg_gen_optimal_table more than once - * per table, because it clobbers the input frequency counts! - */ - MEMZERO(did, SIZEOF(did)); - - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - if (is_DC_band) { - if (cinfo->Ah != 0) /* DC refinement needs no table */ - continue; - tbl = compptr->dc_tbl_no; - } else { - tbl = compptr->ac_tbl_no; - } - if (! did[tbl]) { - if (is_DC_band) - htblptr = & cinfo->dc_huff_tbl_ptrs[tbl]; - else - htblptr = & cinfo->ac_huff_tbl_ptrs[tbl]; - if (*htblptr == NULL) - *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); - jpeg_gen_optimal_table(cinfo, *htblptr, entropy->count_ptrs[tbl]); - did[tbl] = TRUE; - } - } -} - - -/* - * Module initialization routine for progressive Huffman entropy encoding. - */ - -GLOBAL(void) -jinit_phuff_encoder (j_compress_ptr cinfo) -{ - phuff_entropy_ptr entropy; - int i; - - entropy = (phuff_entropy_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(phuff_entropy_encoder)); - cinfo->entropy = (struct jpeg_entropy_encoder *) entropy; - entropy->pub.start_pass = start_pass_phuff; - - /* Mark tables unallocated */ - for (i = 0; i < NUM_HUFF_TBLS; i++) { - entropy->derived_tbls[i] = NULL; - entropy->count_ptrs[i] = NULL; - } - entropy->bit_buffer = NULL; /* needed only in AC refinement scan */ -} - -#endif /* C_PROGRESSIVE_SUPPORTED */ diff --git a/reactos/dll/3rdparty/libjpeg/jcprepct.c b/reactos/dll/3rdparty/libjpeg/jcprepct.c index fa93333db20..be44cc4b451 100644 --- a/reactos/dll/3rdparty/libjpeg/jcprepct.c +++ b/reactos/dll/3rdparty/libjpeg/jcprepct.c @@ -173,10 +173,12 @@ pre_process_data (j_compress_ptr cinfo, *out_row_group_ctr < out_row_groups_avail) { for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { + numrows = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) / + cinfo->min_DCT_v_scaled_size; expand_bottom_edge(output_buf[ci], - compptr->width_in_blocks * DCTSIZE, - (int) (*out_row_group_ctr * compptr->v_samp_factor), - (int) (out_row_groups_avail * compptr->v_samp_factor)); + compptr->width_in_blocks * compptr->DCT_h_scaled_size, + (int) (*out_row_group_ctr * numrows), + (int) (out_row_groups_avail * numrows)); } *out_row_group_ctr = out_row_groups_avail; break; /* can exit outer loop without test */ @@ -288,7 +290,8 @@ create_context_buffer (j_compress_ptr cinfo) */ true_buffer = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE * + (JDIMENSION) (((long) compptr->width_in_blocks * + cinfo->min_DCT_h_scaled_size * cinfo->max_h_samp_factor) / compptr->h_samp_factor), (JDIMENSION) (3 * rgroup_height)); /* Copy true buffer row pointers into the middle of the fake row array */ @@ -346,7 +349,8 @@ jinit_c_prep_controller (j_compress_ptr cinfo, boolean need_full_buffer) ci++, compptr++) { prep->color_buf[ci] = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE * + (JDIMENSION) (((long) compptr->width_in_blocks * + cinfo->min_DCT_h_scaled_size * cinfo->max_h_samp_factor) / compptr->h_samp_factor), (JDIMENSION) cinfo->max_v_samp_factor); } diff --git a/reactos/dll/3rdparty/libjpeg/jcsample.c b/reactos/dll/3rdparty/libjpeg/jcsample.c index 212ec8757c4..4d36f85f356 100644 --- a/reactos/dll/3rdparty/libjpeg/jcsample.c +++ b/reactos/dll/3rdparty/libjpeg/jcsample.c @@ -62,6 +62,15 @@ typedef struct { /* Downsampling method pointers, one per component */ downsample1_ptr methods[MAX_COMPONENTS]; + + /* Height of an output row group for each component. */ + int rowgroup_height[MAX_COMPONENTS]; + + /* These arrays save pixel expansion factors so that int_downsample need not + * recompute them each time. They are unused for other downsampling methods. + */ + UINT8 h_expand[MAX_COMPONENTS]; + UINT8 v_expand[MAX_COMPONENTS]; } my_downsampler; typedef my_downsampler * my_downsample_ptr; @@ -123,7 +132,8 @@ sep_downsample (j_compress_ptr cinfo, for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { in_ptr = input_buf[ci] + in_row_index; - out_ptr = output_buf[ci] + (out_row_group_index * compptr->v_samp_factor); + out_ptr = output_buf[ci] + + (out_row_group_index * downsample->rowgroup_height[ci]); (*downsample->methods[ci]) (cinfo, compptr, in_ptr, out_ptr); } } @@ -140,14 +150,15 @@ METHODDEF(void) int_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY output_data) { + my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample; int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v; JDIMENSION outcol, outcol_h; /* outcol_h == outcol*h_expand */ - JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; + JDIMENSION output_cols = compptr->width_in_blocks * compptr->DCT_h_scaled_size; JSAMPROW inptr, outptr; INT32 outvalue; - h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor; - v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor; + h_expand = downsample->h_expand[compptr->component_index]; + v_expand = downsample->v_expand[compptr->component_index]; numpix = h_expand * v_expand; numpix2 = numpix/2; @@ -158,8 +169,8 @@ int_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, expand_right_edge(input_data, cinfo->max_v_samp_factor, cinfo->image_width, output_cols * h_expand); - inrow = 0; - for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { + inrow = outrow = 0; + while (inrow < cinfo->max_v_samp_factor) { outptr = output_data[outrow]; for (outcol = 0, outcol_h = 0; outcol < output_cols; outcol++, outcol_h += h_expand) { @@ -173,6 +184,7 @@ int_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, *outptr++ = (JSAMPLE) ((outvalue + numpix2) / numpix); } inrow += v_expand; + outrow++; } } @@ -191,8 +203,8 @@ fullsize_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, jcopy_sample_rows(input_data, 0, output_data, 0, cinfo->max_v_samp_factor, cinfo->image_width); /* Edge-expand */ - expand_right_edge(output_data, cinfo->max_v_samp_factor, - cinfo->image_width, compptr->width_in_blocks * DCTSIZE); + expand_right_edge(output_data, cinfo->max_v_samp_factor, cinfo->image_width, + compptr->width_in_blocks * compptr->DCT_h_scaled_size); } @@ -212,9 +224,9 @@ METHODDEF(void) h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY output_data) { - int outrow; + int inrow; JDIMENSION outcol; - JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; + JDIMENSION output_cols = compptr->width_in_blocks * compptr->DCT_h_scaled_size; register JSAMPROW inptr, outptr; register int bias; @@ -225,9 +237,9 @@ h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, expand_right_edge(input_data, cinfo->max_v_samp_factor, cinfo->image_width, output_cols * 2); - for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { - outptr = output_data[outrow]; - inptr = input_data[outrow]; + for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { + outptr = output_data[inrow]; + inptr = input_data[inrow]; bias = 0; /* bias = 0,1,0,1,... for successive samples */ for (outcol = 0; outcol < output_cols; outcol++) { *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1]) @@ -251,7 +263,7 @@ h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, { int inrow, outrow; JDIMENSION outcol; - JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; + JDIMENSION output_cols = compptr->width_in_blocks * compptr->DCT_h_scaled_size; register JSAMPROW inptr0, inptr1, outptr; register int bias; @@ -262,8 +274,8 @@ h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, expand_right_edge(input_data, cinfo->max_v_samp_factor, cinfo->image_width, output_cols * 2); - inrow = 0; - for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { + inrow = outrow = 0; + while (inrow < cinfo->max_v_samp_factor) { outptr = output_data[outrow]; inptr0 = input_data[inrow]; inptr1 = input_data[inrow+1]; @@ -276,6 +288,7 @@ h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, inptr0 += 2; inptr1 += 2; } inrow += 2; + outrow++; } } @@ -294,7 +307,7 @@ h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, { int inrow, outrow; JDIMENSION colctr; - JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; + JDIMENSION output_cols = compptr->width_in_blocks * compptr->DCT_h_scaled_size; register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr; INT32 membersum, neighsum, memberscale, neighscale; @@ -321,8 +334,8 @@ h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, memberscale = 16384 - cinfo->smoothing_factor * 80; /* scaled (1-5*SF)/4 */ neighscale = cinfo->smoothing_factor * 16; /* scaled SF/4 */ - inrow = 0; - for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { + inrow = outrow = 0; + while (inrow < cinfo->max_v_samp_factor) { outptr = output_data[outrow]; inptr0 = input_data[inrow]; inptr1 = input_data[inrow+1]; @@ -378,6 +391,7 @@ h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, *outptr = (JSAMPLE) ((membersum + 32768) >> 16); inrow += 2; + outrow++; } } @@ -392,9 +406,9 @@ METHODDEF(void) fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr, JSAMPARRAY input_data, JSAMPARRAY output_data) { - int outrow; + int inrow; JDIMENSION colctr; - JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; + JDIMENSION output_cols = compptr->width_in_blocks * compptr->DCT_h_scaled_size; register JSAMPROW inptr, above_ptr, below_ptr, outptr; INT32 membersum, neighsum, memberscale, neighscale; int colsum, lastcolsum, nextcolsum; @@ -415,11 +429,11 @@ fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr, memberscale = 65536L - cinfo->smoothing_factor * 512L; /* scaled 1-8*SF */ neighscale = cinfo->smoothing_factor * 64; /* scaled SF */ - for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { - outptr = output_data[outrow]; - inptr = input_data[outrow]; - above_ptr = input_data[outrow-1]; - below_ptr = input_data[outrow+1]; + for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { + outptr = output_data[inrow]; + inptr = input_data[inrow]; + above_ptr = input_data[inrow-1]; + below_ptr = input_data[inrow+1]; /* Special case for first column */ colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) + @@ -467,6 +481,7 @@ jinit_downsampler (j_compress_ptr cinfo) int ci; jpeg_component_info * compptr; boolean smoothok = TRUE; + int h_in_group, v_in_group, h_out_group, v_out_group; downsample = (my_downsample_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, @@ -482,8 +497,17 @@ jinit_downsampler (j_compress_ptr cinfo) /* Verify we can handle the sampling factors, and set up method pointers */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { - if (compptr->h_samp_factor == cinfo->max_h_samp_factor && - compptr->v_samp_factor == cinfo->max_v_samp_factor) { + /* Compute size of an "output group" for DCT scaling. This many samples + * are to be converted from max_h_samp_factor * max_v_samp_factor pixels. + */ + h_out_group = (compptr->h_samp_factor * compptr->DCT_h_scaled_size) / + cinfo->min_DCT_h_scaled_size; + v_out_group = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) / + cinfo->min_DCT_v_scaled_size; + h_in_group = cinfo->max_h_samp_factor; + v_in_group = cinfo->max_v_samp_factor; + downsample->rowgroup_height[ci] = v_out_group; /* save for use later */ + if (h_in_group == h_out_group && v_in_group == v_out_group) { #ifdef INPUT_SMOOTHING_SUPPORTED if (cinfo->smoothing_factor) { downsample->methods[ci] = fullsize_smooth_downsample; @@ -491,12 +515,12 @@ jinit_downsampler (j_compress_ptr cinfo) } else #endif downsample->methods[ci] = fullsize_downsample; - } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && - compptr->v_samp_factor == cinfo->max_v_samp_factor) { + } else if (h_in_group == h_out_group * 2 && + v_in_group == v_out_group) { smoothok = FALSE; downsample->methods[ci] = h2v1_downsample; - } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && - compptr->v_samp_factor * 2 == cinfo->max_v_samp_factor) { + } else if (h_in_group == h_out_group * 2 && + v_in_group == v_out_group * 2) { #ifdef INPUT_SMOOTHING_SUPPORTED if (cinfo->smoothing_factor) { downsample->methods[ci] = h2v2_smooth_downsample; @@ -504,10 +528,12 @@ jinit_downsampler (j_compress_ptr cinfo) } else #endif downsample->methods[ci] = h2v2_downsample; - } else if ((cinfo->max_h_samp_factor % compptr->h_samp_factor) == 0 && - (cinfo->max_v_samp_factor % compptr->v_samp_factor) == 0) { + } else if ((h_in_group % h_out_group) == 0 && + (v_in_group % v_out_group) == 0) { smoothok = FALSE; downsample->methods[ci] = int_downsample; + downsample->h_expand[ci] = (UINT8) (h_in_group / h_out_group); + downsample->v_expand[ci] = (UINT8) (v_in_group / v_out_group); } else ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); } diff --git a/reactos/dll/3rdparty/libjpeg/jctrans.c b/reactos/dll/3rdparty/libjpeg/jctrans.c index 0e6d70769df..cee6b0f343f 100644 --- a/reactos/dll/3rdparty/libjpeg/jctrans.c +++ b/reactos/dll/3rdparty/libjpeg/jctrans.c @@ -2,6 +2,7 @@ * jctrans.c * * Copyright (C) 1995-1998, Thomas G. Lane. + * Modified 2000-2009 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -76,6 +77,10 @@ jpeg_copy_critical_parameters (j_decompress_ptr srcinfo, dstinfo->image_height = srcinfo->image_height; dstinfo->input_components = srcinfo->num_components; dstinfo->in_color_space = srcinfo->jpeg_color_space; + dstinfo->jpeg_width = srcinfo->output_width; + dstinfo->jpeg_height = srcinfo->output_height; + dstinfo->min_DCT_h_scaled_size = srcinfo->min_DCT_h_scaled_size; + dstinfo->min_DCT_v_scaled_size = srcinfo->min_DCT_v_scaled_size; /* Initialize all parameters to default values */ jpeg_set_defaults(dstinfo); /* jpeg_set_defaults may choose wrong colorspace, eg YCbCr if input is RGB. @@ -158,25 +163,14 @@ LOCAL(void) transencode_master_selection (j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays) { - /* Although we don't actually use input_components for transcoding, - * jcmaster.c's initial_setup will complain if input_components is 0. - */ - cinfo->input_components = 1; /* Initialize master control (includes parameter checking/processing) */ jinit_c_master_control(cinfo, TRUE /* transcode only */); /* Entropy encoding: either Huffman or arithmetic coding. */ - if (cinfo->arith_code) { - ERREXIT(cinfo, JERR_ARITH_NOTIMPL); - } else { - if (cinfo->progressive_mode) { -#ifdef C_PROGRESSIVE_SUPPORTED - jinit_phuff_encoder(cinfo); -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } else - jinit_huff_encoder(cinfo); + if (cinfo->arith_code) + jinit_arith_encoder(cinfo); + else { + jinit_huff_encoder(cinfo); } /* We need a special coefficient buffer controller. */ diff --git a/reactos/dll/3rdparty/libjpeg/jdapimin.c b/reactos/dll/3rdparty/libjpeg/jdapimin.c index cadb59fce3a..7f1ce4c05b2 100644 --- a/reactos/dll/3rdparty/libjpeg/jdapimin.c +++ b/reactos/dll/3rdparty/libjpeg/jdapimin.c @@ -2,6 +2,7 @@ * jdapimin.c * * Copyright (C) 1994-1998, Thomas G. Lane. + * Modified 2009 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -185,8 +186,8 @@ default_decompress_parms (j_decompress_ptr cinfo) } /* Set defaults for other decompression parameters. */ - cinfo->scale_num = 1; /* 1:1 scaling */ - cinfo->scale_denom = 1; + cinfo->scale_num = cinfo->block_size; /* 1:1 scaling */ + cinfo->scale_denom = cinfo->block_size; cinfo->output_gamma = 1.0; cinfo->buffered_image = FALSE; cinfo->raw_data_out = FALSE; diff --git a/reactos/dll/3rdparty/libjpeg/jdapistd.c b/reactos/dll/3rdparty/libjpeg/jdapistd.c index c8e3fa0c35d..9d745377724 100644 --- a/reactos/dll/3rdparty/libjpeg/jdapistd.c +++ b/reactos/dll/3rdparty/libjpeg/jdapistd.c @@ -202,7 +202,7 @@ jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data, } /* Verify that at least one iMCU row can be returned. */ - lines_per_iMCU_row = cinfo->max_v_samp_factor * cinfo->min_DCT_scaled_size; + lines_per_iMCU_row = cinfo->max_v_samp_factor * cinfo->min_DCT_v_scaled_size; if (max_lines < lines_per_iMCU_row) ERREXIT(cinfo, JERR_BUFFER_SIZE); diff --git a/reactos/dll/3rdparty/libjpeg/jdarith.c b/reactos/dll/3rdparty/libjpeg/jdarith.c new file mode 100644 index 00000000000..c858b248b6b --- /dev/null +++ b/reactos/dll/3rdparty/libjpeg/jdarith.c @@ -0,0 +1,772 @@ +/* + * jdarith.c + * + * Developed 1997-2009 by Guido Vollbeding. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains portable arithmetic entropy decoding routines for JPEG + * (implementing the ISO/IEC IS 10918-1 and CCITT Recommendation ITU-T T.81). + * + * Both sequential and progressive modes are supported in this single module. + * + * Suspension is not currently supported in this module. + */ + +#define JPEG_INTERNALS +#include "jinclude.h" +#include "jpeglib.h" + + +/* Expanded entropy decoder object for arithmetic decoding. */ + +typedef struct { + struct jpeg_entropy_decoder pub; /* public fields */ + + INT32 c; /* C register, base of coding interval + input bit buffer */ + INT32 a; /* A register, normalized size of coding interval */ + int ct; /* bit shift counter, # of bits left in bit buffer part of C */ + /* init: ct = -16 */ + /* run: ct = 0..7 */ + /* error: ct = -1 */ + int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ + int dc_context[MAX_COMPS_IN_SCAN]; /* context index for DC conditioning */ + + unsigned int restarts_to_go; /* MCUs left in this restart interval */ + + /* Pointers to statistics areas (these workspaces have image lifespan) */ + unsigned char * dc_stats[NUM_ARITH_TBLS]; + unsigned char * ac_stats[NUM_ARITH_TBLS]; + + /* Statistics bin for coding with fixed probability 0.5 */ + unsigned char fixed_bin[4]; +} arith_entropy_decoder; + +typedef arith_entropy_decoder * arith_entropy_ptr; + +/* The following two definitions specify the allocation chunk size + * for the statistics area. + * According to sections F.1.4.4.1.3 and F.1.4.4.2, we need at least + * 49 statistics bins for DC, and 245 statistics bins for AC coding. + * + * We use a compact representation with 1 byte per statistics bin, + * thus the numbers directly represent byte sizes. + * This 1 byte per statistics bin contains the meaning of the MPS + * (more probable symbol) in the highest bit (mask 0x80), and the + * index into the probability estimation state machine table + * in the lower bits (mask 0x7F). + */ + +#define DC_STAT_BINS 64 +#define AC_STAT_BINS 256 + + +LOCAL(int) +get_byte (j_decompress_ptr cinfo) +/* Read next input byte; we do not support suspension in this module. */ +{ + struct jpeg_source_mgr * src = cinfo->src; + + if (src->bytes_in_buffer == 0) + if (! (*src->fill_input_buffer) (cinfo)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + src->bytes_in_buffer--; + return GETJOCTET(*src->next_input_byte++); +} + + +/* + * The core arithmetic decoding routine (common in JPEG and JBIG). + * This needs to go as fast as possible. + * Machine-dependent optimization facilities + * are not utilized in this portable implementation. + * However, this code should be fairly efficient and + * may be a good base for further optimizations anyway. + * + * Return value is 0 or 1 (binary decision). + * + * Note: I've changed the handling of the code base & bit + * buffer register C compared to other implementations + * based on the standards layout & procedures. + * While it also contains both the actual base of the + * coding interval (16 bits) and the next-bits buffer, + * the cut-point between these two parts is floating + * (instead of fixed) with the bit shift counter CT. + * Thus, we also need only one (variable instead of + * fixed size) shift for the LPS/MPS decision, and + * we can get away with any renormalization update + * of C (except for new data insertion, of course). + * + * I've also introduced a new scheme for accessing + * the probability estimation state machine table, + * derived from Markus Kuhn's JBIG implementation. + */ + +LOCAL(int) +arith_decode (j_decompress_ptr cinfo, unsigned char *st) +{ + register arith_entropy_ptr e = (arith_entropy_ptr) cinfo->entropy; + register unsigned char nl, nm; + register INT32 qe, temp; + register int sv, data; + + /* Renormalization & data input per section D.2.6 */ + while (e->a < 0x8000L) { + if (--e->ct < 0) { + /* Need to fetch next data byte */ + if (cinfo->unread_marker) + data = 0; /* stuff zero data */ + else { + data = get_byte(cinfo); /* read next input byte */ + if (data == 0xFF) { /* zero stuff or marker code */ + do data = get_byte(cinfo); + while (data == 0xFF); /* swallow extra 0xFF bytes */ + if (data == 0) + data = 0xFF; /* discard stuffed zero byte */ + else { + /* Note: Different from the Huffman decoder, hitting + * a marker while processing the compressed data + * segment is legal in arithmetic coding. + * The convention is to supply zero data + * then until decoding is complete. + */ + cinfo->unread_marker = data; + data = 0; + } + } + } + e->c = (e->c << 8) | data; /* insert data into C register */ + if ((e->ct += 8) < 0) /* update bit shift counter */ + /* Need more initial bytes */ + if (++e->ct == 0) + /* Got 2 initial bytes -> re-init A and exit loop */ + e->a = 0x8000L; /* => e->a = 0x10000L after loop exit */ + } + e->a <<= 1; + } + + /* Fetch values from our compact representation of Table D.2: + * Qe values and probability estimation state machine + */ + sv = *st; + qe = jpeg_aritab[sv & 0x7F]; /* => Qe_Value */ + nl = qe & 0xFF; qe >>= 8; /* Next_Index_LPS + Switch_MPS */ + nm = qe & 0xFF; qe >>= 8; /* Next_Index_MPS */ + + /* Decode & estimation procedures per sections D.2.4 & D.2.5 */ + temp = e->a - qe; + e->a = temp; + temp <<= e->ct; + if (e->c >= temp) { + e->c -= temp; + /* Conditional LPS (less probable symbol) exchange */ + if (e->a < qe) { + e->a = qe; + *st = (sv & 0x80) ^ nm; /* Estimate_after_MPS */ + } else { + e->a = qe; + *st = (sv & 0x80) ^ nl; /* Estimate_after_LPS */ + sv ^= 0x80; /* Exchange LPS/MPS */ + } + } else if (e->a < 0x8000L) { + /* Conditional MPS (more probable symbol) exchange */ + if (e->a < qe) { + *st = (sv & 0x80) ^ nl; /* Estimate_after_LPS */ + sv ^= 0x80; /* Exchange LPS/MPS */ + } else { + *st = (sv & 0x80) ^ nm; /* Estimate_after_MPS */ + } + } + + return sv >> 7; +} + + +/* + * Check for a restart marker & resynchronize decoder. + */ + +LOCAL(void) +process_restart (j_decompress_ptr cinfo) +{ + arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + int ci; + jpeg_component_info * compptr; + + /* Advance past the RSTn marker */ + if (! (*cinfo->marker->read_restart_marker) (cinfo)) + ERREXIT(cinfo, JERR_CANT_SUSPEND); + + /* Re-initialize statistics areas */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + if (! cinfo->progressive_mode || (cinfo->Ss == 0 && cinfo->Ah == 0)) { + MEMZERO(entropy->dc_stats[compptr->dc_tbl_no], DC_STAT_BINS); + /* Reset DC predictions to 0 */ + entropy->last_dc_val[ci] = 0; + entropy->dc_context[ci] = 0; + } + if ((! cinfo->progressive_mode && cinfo->lim_Se) || + (cinfo->progressive_mode && cinfo->Ss)) { + MEMZERO(entropy->ac_stats[compptr->ac_tbl_no], AC_STAT_BINS); + } + } + + /* Reset arithmetic decoding variables */ + entropy->c = 0; + entropy->a = 0; + entropy->ct = -16; /* force reading 2 initial bytes to fill C */ + + /* Reset restart counter */ + entropy->restarts_to_go = cinfo->restart_interval; +} + + +/* + * Arithmetic MCU decoding. + * Each of these routines decodes and returns one MCU's worth of + * arithmetic-compressed coefficients. + * The coefficients are reordered from zigzag order into natural array order, + * but are not dequantized. + * + * The i'th block of the MCU is stored into the block pointed to by + * MCU_data[i]. WE ASSUME THIS AREA IS INITIALLY ZEROED BY THE CALLER. + */ + +/* + * MCU decoding for DC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + JBLOCKROW block; + unsigned char *st; + int blkn, ci, tbl, sign; + int v, m; + + /* Process restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + process_restart(cinfo); + entropy->restarts_to_go--; + } + + if (entropy->ct == -1) return TRUE; /* if error do nothing */ + + /* Outer loop handles each block in the MCU */ + + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + block = MCU_data[blkn]; + ci = cinfo->MCU_membership[blkn]; + tbl = cinfo->cur_comp_info[ci]->dc_tbl_no; + + /* Sections F.2.4.1 & F.1.4.4.1: Decoding of DC coefficients */ + + /* Table F.4: Point to statistics bin S0 for DC coefficient coding */ + st = entropy->dc_stats[tbl] + entropy->dc_context[ci]; + + /* Figure F.19: Decode_DC_DIFF */ + if (arith_decode(cinfo, st) == 0) + entropy->dc_context[ci] = 0; + else { + /* Figure F.21: Decoding nonzero value v */ + /* Figure F.22: Decoding the sign of v */ + sign = arith_decode(cinfo, st + 1); + st += 2; st += sign; + /* Figure F.23: Decoding the magnitude category of v */ + if ((m = arith_decode(cinfo, st)) != 0) { + st = entropy->dc_stats[tbl] + 20; /* Table F.4: X1 = 20 */ + while (arith_decode(cinfo, st)) { + if ((m <<= 1) == 0x8000) { + WARNMS(cinfo, JWRN_ARITH_BAD_CODE); + entropy->ct = -1; /* magnitude overflow */ + return TRUE; + } + st += 1; + } + } + /* Section F.1.4.4.1.2: Establish dc_context conditioning category */ + if (m < (int) ((1L << cinfo->arith_dc_L[tbl]) >> 1)) + entropy->dc_context[ci] = 0; /* zero diff category */ + else if (m > (int) ((1L << cinfo->arith_dc_U[tbl]) >> 1)) + entropy->dc_context[ci] = 12 + (sign * 4); /* large diff category */ + else + entropy->dc_context[ci] = 4 + (sign * 4); /* small diff category */ + v = m; + /* Figure F.24: Decoding the magnitude bit pattern of v */ + st += 14; + while (m >>= 1) + if (arith_decode(cinfo, st)) v |= m; + v += 1; if (sign) v = -v; + entropy->last_dc_val[ci] += v; + } + + /* Scale and output the DC coefficient (assumes jpeg_natural_order[0]=0) */ + (*block)[0] = (JCOEF) (entropy->last_dc_val[ci] << cinfo->Al); + } + + return TRUE; +} + + +/* + * MCU decoding for AC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + JBLOCKROW block; + unsigned char *st; + int tbl, sign, k; + int v, m; + const int * natural_order; + + /* Process restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + process_restart(cinfo); + entropy->restarts_to_go--; + } + + if (entropy->ct == -1) return TRUE; /* if error do nothing */ + + natural_order = cinfo->natural_order; + + /* There is always only one block per MCU */ + block = MCU_data[0]; + tbl = cinfo->cur_comp_info[0]->ac_tbl_no; + + /* Sections F.2.4.2 & F.1.4.4.2: Decoding of AC coefficients */ + + /* Figure F.20: Decode_AC_coefficients */ + for (k = cinfo->Ss; k <= cinfo->Se; k++) { + st = entropy->ac_stats[tbl] + 3 * (k - 1); + if (arith_decode(cinfo, st)) break; /* EOB flag */ + while (arith_decode(cinfo, st + 1) == 0) { + st += 3; k++; + if (k > cinfo->Se) { + WARNMS(cinfo, JWRN_ARITH_BAD_CODE); + entropy->ct = -1; /* spectral overflow */ + return TRUE; + } + } + /* Figure F.21: Decoding nonzero value v */ + /* Figure F.22: Decoding the sign of v */ + sign = arith_decode(cinfo, entropy->fixed_bin); + st += 2; + /* Figure F.23: Decoding the magnitude category of v */ + if ((m = arith_decode(cinfo, st)) != 0) { + if (arith_decode(cinfo, st)) { + m <<= 1; + st = entropy->ac_stats[tbl] + + (k <= cinfo->arith_ac_K[tbl] ? 189 : 217); + while (arith_decode(cinfo, st)) { + if ((m <<= 1) == 0x8000) { + WARNMS(cinfo, JWRN_ARITH_BAD_CODE); + entropy->ct = -1; /* magnitude overflow */ + return TRUE; + } + st += 1; + } + } + } + v = m; + /* Figure F.24: Decoding the magnitude bit pattern of v */ + st += 14; + while (m >>= 1) + if (arith_decode(cinfo, st)) v |= m; + v += 1; if (sign) v = -v; + /* Scale and output coefficient in natural (dezigzagged) order */ + (*block)[natural_order[k]] = (JCOEF) (v << cinfo->Al); + } + + return TRUE; +} + + +/* + * MCU decoding for DC successive approximation refinement scan. + */ + +METHODDEF(boolean) +decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + unsigned char *st; + int p1, blkn; + + /* Process restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + process_restart(cinfo); + entropy->restarts_to_go--; + } + + st = entropy->fixed_bin; /* use fixed probability estimation */ + p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ + + /* Outer loop handles each block in the MCU */ + + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + /* Encoded data is simply the next bit of the two's-complement DC value */ + if (arith_decode(cinfo, st)) + MCU_data[blkn][0][0] |= p1; + } + + return TRUE; +} + + +/* + * MCU decoding for AC successive approximation refinement scan. + */ + +METHODDEF(boolean) +decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + JBLOCKROW block; + JCOEFPTR thiscoef; + unsigned char *st; + int tbl, k, kex; + int p1, m1; + const int * natural_order; + + /* Process restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + process_restart(cinfo); + entropy->restarts_to_go--; + } + + if (entropy->ct == -1) return TRUE; /* if error do nothing */ + + natural_order = cinfo->natural_order; + + /* There is always only one block per MCU */ + block = MCU_data[0]; + tbl = cinfo->cur_comp_info[0]->ac_tbl_no; + + p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ + m1 = (-1) << cinfo->Al; /* -1 in the bit position being coded */ + + /* Establish EOBx (previous stage end-of-block) index */ + for (kex = cinfo->Se; kex > 0; kex--) + if ((*block)[natural_order[kex]]) break; + + for (k = cinfo->Ss; k <= cinfo->Se; k++) { + st = entropy->ac_stats[tbl] + 3 * (k - 1); + if (k > kex) + if (arith_decode(cinfo, st)) break; /* EOB flag */ + for (;;) { + thiscoef = *block + natural_order[k]; + if (*thiscoef) { /* previously nonzero coef */ + if (arith_decode(cinfo, st + 2)) { + if (*thiscoef < 0) + *thiscoef += m1; + else + *thiscoef += p1; + } + break; + } + if (arith_decode(cinfo, st + 1)) { /* newly nonzero coef */ + if (arith_decode(cinfo, entropy->fixed_bin)) + *thiscoef = m1; + else + *thiscoef = p1; + break; + } + st += 3; k++; + if (k > cinfo->Se) { + WARNMS(cinfo, JWRN_ARITH_BAD_CODE); + entropy->ct = -1; /* spectral overflow */ + return TRUE; + } + } + } + + return TRUE; +} + + +/* + * Decode one MCU's worth of arithmetic-compressed coefficients. + */ + +METHODDEF(boolean) +decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + jpeg_component_info * compptr; + JBLOCKROW block; + unsigned char *st; + int blkn, ci, tbl, sign, k; + int v, m; + const int * natural_order; + + /* Process restart marker if needed */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + process_restart(cinfo); + entropy->restarts_to_go--; + } + + if (entropy->ct == -1) return TRUE; /* if error do nothing */ + + natural_order = cinfo->natural_order; + + /* Outer loop handles each block in the MCU */ + + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + block = MCU_data[blkn]; + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + + /* Sections F.2.4.1 & F.1.4.4.1: Decoding of DC coefficients */ + + tbl = compptr->dc_tbl_no; + + /* Table F.4: Point to statistics bin S0 for DC coefficient coding */ + st = entropy->dc_stats[tbl] + entropy->dc_context[ci]; + + /* Figure F.19: Decode_DC_DIFF */ + if (arith_decode(cinfo, st) == 0) + entropy->dc_context[ci] = 0; + else { + /* Figure F.21: Decoding nonzero value v */ + /* Figure F.22: Decoding the sign of v */ + sign = arith_decode(cinfo, st + 1); + st += 2; st += sign; + /* Figure F.23: Decoding the magnitude category of v */ + if ((m = arith_decode(cinfo, st)) != 0) { + st = entropy->dc_stats[tbl] + 20; /* Table F.4: X1 = 20 */ + while (arith_decode(cinfo, st)) { + if ((m <<= 1) == 0x8000) { + WARNMS(cinfo, JWRN_ARITH_BAD_CODE); + entropy->ct = -1; /* magnitude overflow */ + return TRUE; + } + st += 1; + } + } + /* Section F.1.4.4.1.2: Establish dc_context conditioning category */ + if (m < (int) ((1L << cinfo->arith_dc_L[tbl]) >> 1)) + entropy->dc_context[ci] = 0; /* zero diff category */ + else if (m > (int) ((1L << cinfo->arith_dc_U[tbl]) >> 1)) + entropy->dc_context[ci] = 12 + (sign * 4); /* large diff category */ + else + entropy->dc_context[ci] = 4 + (sign * 4); /* small diff category */ + v = m; + /* Figure F.24: Decoding the magnitude bit pattern of v */ + st += 14; + while (m >>= 1) + if (arith_decode(cinfo, st)) v |= m; + v += 1; if (sign) v = -v; + entropy->last_dc_val[ci] += v; + } + + (*block)[0] = (JCOEF) entropy->last_dc_val[ci]; + + /* Sections F.2.4.2 & F.1.4.4.2: Decoding of AC coefficients */ + + tbl = compptr->ac_tbl_no; + + /* Figure F.20: Decode_AC_coefficients */ + for (k = 1; k <= cinfo->lim_Se; k++) { + st = entropy->ac_stats[tbl] + 3 * (k - 1); + if (arith_decode(cinfo, st)) break; /* EOB flag */ + while (arith_decode(cinfo, st + 1) == 0) { + st += 3; k++; + if (k > cinfo->lim_Se) { + WARNMS(cinfo, JWRN_ARITH_BAD_CODE); + entropy->ct = -1; /* spectral overflow */ + return TRUE; + } + } + /* Figure F.21: Decoding nonzero value v */ + /* Figure F.22: Decoding the sign of v */ + sign = arith_decode(cinfo, entropy->fixed_bin); + st += 2; + /* Figure F.23: Decoding the magnitude category of v */ + if ((m = arith_decode(cinfo, st)) != 0) { + if (arith_decode(cinfo, st)) { + m <<= 1; + st = entropy->ac_stats[tbl] + + (k <= cinfo->arith_ac_K[tbl] ? 189 : 217); + while (arith_decode(cinfo, st)) { + if ((m <<= 1) == 0x8000) { + WARNMS(cinfo, JWRN_ARITH_BAD_CODE); + entropy->ct = -1; /* magnitude overflow */ + return TRUE; + } + st += 1; + } + } + } + v = m; + /* Figure F.24: Decoding the magnitude bit pattern of v */ + st += 14; + while (m >>= 1) + if (arith_decode(cinfo, st)) v |= m; + v += 1; if (sign) v = -v; + (*block)[natural_order[k]] = (JCOEF) v; + } + } + + return TRUE; +} + + +/* + * Initialize for an arithmetic-compressed scan. + */ + +METHODDEF(void) +start_pass (j_decompress_ptr cinfo) +{ + arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + int ci, tbl; + jpeg_component_info * compptr; + + if (cinfo->progressive_mode) { + /* Validate progressive scan parameters */ + if (cinfo->Ss == 0) { + if (cinfo->Se != 0) + goto bad; + } else { + /* need not check Ss/Se < 0 since they came from unsigned bytes */ + if (cinfo->Se < cinfo->Ss || cinfo->Se > cinfo->lim_Se) + goto bad; + /* AC scans may have only one component */ + if (cinfo->comps_in_scan != 1) + goto bad; + } + if (cinfo->Ah != 0) { + /* Successive approximation refinement scan: must have Al = Ah-1. */ + if (cinfo->Ah-1 != cinfo->Al) + goto bad; + } + if (cinfo->Al > 13) { /* need not check for < 0 */ + bad: + ERREXIT4(cinfo, JERR_BAD_PROGRESSION, + cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); + } + /* Update progression status, and verify that scan order is legal. + * Note that inter-scan inconsistencies are treated as warnings + * not fatal errors ... not clear if this is right way to behave. + */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + int coefi, cindex = cinfo->cur_comp_info[ci]->component_index; + int *coef_bit_ptr = & cinfo->coef_bits[cindex][0]; + if (cinfo->Ss && coef_bit_ptr[0] < 0) /* AC without prior DC scan */ + WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0); + for (coefi = cinfo->Ss; coefi <= cinfo->Se; coefi++) { + int expected = (coef_bit_ptr[coefi] < 0) ? 0 : coef_bit_ptr[coefi]; + if (cinfo->Ah != expected) + WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, coefi); + coef_bit_ptr[coefi] = cinfo->Al; + } + } + /* Select MCU decoding routine */ + if (cinfo->Ah == 0) { + if (cinfo->Ss == 0) + entropy->pub.decode_mcu = decode_mcu_DC_first; + else + entropy->pub.decode_mcu = decode_mcu_AC_first; + } else { + if (cinfo->Ss == 0) + entropy->pub.decode_mcu = decode_mcu_DC_refine; + else + entropy->pub.decode_mcu = decode_mcu_AC_refine; + } + } else { + /* Check that the scan parameters Ss, Se, Ah/Al are OK for sequential JPEG. + * This ought to be an error condition, but we make it a warning. + */ + if (cinfo->Ss != 0 || cinfo->Ah != 0 || cinfo->Al != 0 || + (cinfo->Se < DCTSIZE2 && cinfo->Se != cinfo->lim_Se)) + WARNMS(cinfo, JWRN_NOT_SEQUENTIAL); + /* Select MCU decoding routine */ + entropy->pub.decode_mcu = decode_mcu; + } + + /* Allocate & initialize requested statistics areas */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + if (! cinfo->progressive_mode || (cinfo->Ss == 0 && cinfo->Ah == 0)) { + tbl = compptr->dc_tbl_no; + if (tbl < 0 || tbl >= NUM_ARITH_TBLS) + ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl); + if (entropy->dc_stats[tbl] == NULL) + entropy->dc_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, DC_STAT_BINS); + MEMZERO(entropy->dc_stats[tbl], DC_STAT_BINS); + /* Initialize DC predictions to 0 */ + entropy->last_dc_val[ci] = 0; + entropy->dc_context[ci] = 0; + } + if ((! cinfo->progressive_mode && cinfo->lim_Se) || + (cinfo->progressive_mode && cinfo->Ss)) { + tbl = compptr->ac_tbl_no; + if (tbl < 0 || tbl >= NUM_ARITH_TBLS) + ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl); + if (entropy->ac_stats[tbl] == NULL) + entropy->ac_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, AC_STAT_BINS); + MEMZERO(entropy->ac_stats[tbl], AC_STAT_BINS); + } + } + + /* Initialize arithmetic decoding variables */ + entropy->c = 0; + entropy->a = 0; + entropy->ct = -16; /* force reading 2 initial bytes to fill C */ + + /* Initialize restart counter */ + entropy->restarts_to_go = cinfo->restart_interval; +} + + +/* + * Module initialization routine for arithmetic entropy decoding. + */ + +GLOBAL(void) +jinit_arith_decoder (j_decompress_ptr cinfo) +{ + arith_entropy_ptr entropy; + int i; + + entropy = (arith_entropy_ptr) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(arith_entropy_decoder)); + cinfo->entropy = (struct jpeg_entropy_decoder *) entropy; + entropy->pub.start_pass = start_pass; + + /* Mark tables unallocated */ + for (i = 0; i < NUM_ARITH_TBLS; i++) { + entropy->dc_stats[i] = NULL; + entropy->ac_stats[i] = NULL; + } + + /* Initialize index for fixed probability estimation */ + entropy->fixed_bin[0] = 113; + + if (cinfo->progressive_mode) { + /* Create progression status table */ + int *coef_bit_ptr, ci; + cinfo->coef_bits = (int (*)[DCTSIZE2]) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + cinfo->num_components*DCTSIZE2*SIZEOF(int)); + coef_bit_ptr = & cinfo->coef_bits[0][0]; + for (ci = 0; ci < cinfo->num_components; ci++) + for (i = 0; i < DCTSIZE2; i++) + *coef_bit_ptr++ = -1; + } +} diff --git a/reactos/dll/3rdparty/libjpeg/jdatadst.c b/reactos/dll/3rdparty/libjpeg/jdatadst.c index a8f6fb0e025..472d5f32418 100644 --- a/reactos/dll/3rdparty/libjpeg/jdatadst.c +++ b/reactos/dll/3rdparty/libjpeg/jdatadst.c @@ -2,13 +2,14 @@ * jdatadst.c * * Copyright (C) 1994-1996, Thomas G. Lane. + * Modified 2009 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains compression data destination routines for the case of - * emitting JPEG data to a file (or any stdio stream). While these routines - * are sufficient for most applications, some will want to use a different - * destination manager. + * emitting JPEG data to memory or to a file (or any stdio stream). + * While these routines are sufficient for most applications, + * some will want to use a different destination manager. * IMPORTANT: we assume that fwrite() will correctly transcribe an array of * JOCTETs into 8-bit-wide elements on external storage. If char is wider * than 8 bits on your machine, you may need to do some tweaking. @@ -19,6 +20,11 @@ #include "jpeglib.h" #include "jerror.h" +#ifndef HAVE_STDLIB_H /* should declare malloc(),free() */ +extern void * malloc JPP((size_t size)); +extern void free JPP((void *ptr)); +#endif + /* Expanded data destination object for stdio output */ @@ -34,6 +40,21 @@ typedef my_destination_mgr * my_dest_ptr; #define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */ +/* Expanded data destination object for memory output */ + +typedef struct { + struct jpeg_destination_mgr pub; /* public fields */ + + unsigned char ** outbuffer; /* target buffer */ + unsigned long * outsize; + unsigned char * newbuffer; /* newly allocated buffer */ + JOCTET * buffer; /* start of buffer */ + size_t bufsize; +} my_mem_destination_mgr; + +typedef my_mem_destination_mgr * my_mem_dest_ptr; + + /* * Initialize destination --- called by jpeg_start_compress * before any data is actually written. @@ -53,6 +74,12 @@ init_destination (j_compress_ptr cinfo) dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; } +METHODDEF(void) +init_mem_destination (j_compress_ptr cinfo) +{ + /* no work necessary here */ +} + /* * Empty the output buffer --- called whenever buffer fills up. @@ -92,6 +119,36 @@ empty_output_buffer (j_compress_ptr cinfo) return TRUE; } +METHODDEF(boolean) +empty_mem_output_buffer (j_compress_ptr cinfo) +{ + size_t nextsize; + JOCTET * nextbuffer; + my_mem_dest_ptr dest = (my_mem_dest_ptr) cinfo->dest; + + /* Try to allocate new buffer with double size */ + nextsize = dest->bufsize * 2; + nextbuffer = malloc(nextsize); + + if (nextbuffer == NULL) + ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 10); + + MEMCOPY(nextbuffer, dest->buffer, dest->bufsize); + + if (dest->newbuffer != NULL) + free(dest->newbuffer); + + dest->newbuffer = nextbuffer; + + dest->pub.next_output_byte = nextbuffer + dest->bufsize; + dest->pub.free_in_buffer = dest->bufsize; + + dest->buffer = nextbuffer; + dest->bufsize = nextsize; + + return TRUE; +} + /* * Terminate destination --- called by jpeg_finish_compress @@ -119,6 +176,15 @@ term_destination (j_compress_ptr cinfo) ERREXIT(cinfo, JERR_FILE_WRITE); } +METHODDEF(void) +term_mem_destination (j_compress_ptr cinfo) +{ + my_mem_dest_ptr dest = (my_mem_dest_ptr) cinfo->dest; + + *dest->outbuffer = dest->buffer; + *dest->outsize = dest->bufsize - dest->pub.free_in_buffer; +} + /* * Prepare for output to a stdio stream. @@ -149,3 +215,53 @@ jpeg_stdio_dest (j_compress_ptr cinfo, FILE * outfile) dest->pub.term_destination = term_destination; dest->outfile = outfile; } + + +/* + * Prepare for output to a memory buffer. + * The caller may supply an own initial buffer with appropriate size. + * Otherwise, or when the actual data output exceeds the given size, + * the library adapts the buffer size as necessary. + * The standard library functions malloc/free are used for allocating + * larger memory, so the buffer is available to the application after + * finishing compression, and then the application is responsible for + * freeing the requested memory. + */ + +GLOBAL(void) +jpeg_mem_dest (j_compress_ptr cinfo, + unsigned char ** outbuffer, unsigned long * outsize) +{ + my_mem_dest_ptr dest; + + if (outbuffer == NULL || outsize == NULL) /* sanity check */ + ERREXIT(cinfo, JERR_BUFFER_SIZE); + + /* The destination object is made permanent so that multiple JPEG images + * can be written to the same buffer without re-executing jpeg_mem_dest. + */ + if (cinfo->dest == NULL) { /* first time for this JPEG object? */ + cinfo->dest = (struct jpeg_destination_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(my_mem_destination_mgr)); + } + + dest = (my_mem_dest_ptr) cinfo->dest; + dest->pub.init_destination = init_mem_destination; + dest->pub.empty_output_buffer = empty_mem_output_buffer; + dest->pub.term_destination = term_mem_destination; + dest->outbuffer = outbuffer; + dest->outsize = outsize; + dest->newbuffer = NULL; + + if (*outbuffer == NULL || *outsize == 0) { + /* Allocate initial buffer */ + dest->newbuffer = *outbuffer = malloc(OUTPUT_BUF_SIZE); + if (dest->newbuffer == NULL) + ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 10); + *outsize = OUTPUT_BUF_SIZE; + } + + dest->pub.next_output_byte = dest->buffer = *outbuffer; + dest->pub.free_in_buffer = dest->bufsize = *outsize; +} diff --git a/reactos/dll/3rdparty/libjpeg/jdatasrc.c b/reactos/dll/3rdparty/libjpeg/jdatasrc.c index edc752bf5d8..c8fe3daf336 100644 --- a/reactos/dll/3rdparty/libjpeg/jdatasrc.c +++ b/reactos/dll/3rdparty/libjpeg/jdatasrc.c @@ -2,13 +2,14 @@ * jdatasrc.c * * Copyright (C) 1994-1996, Thomas G. Lane. + * Modified 2009-2010 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains decompression data source routines for the case of - * reading JPEG data from a file (or any stdio stream). While these routines - * are sufficient for most applications, some will want to use a different - * source manager. + * reading JPEG data from memory or from a file (or any stdio stream). + * While these routines are sufficient for most applications, + * some will want to use a different source manager. * IMPORTANT: we assume that fread() will correctly transcribe an array of * JOCTETs from 8-bit-wide elements on external storage. If char is wider * than 8 bits on your machine, you may need to do some tweaking. @@ -52,6 +53,12 @@ init_source (j_decompress_ptr cinfo) src->start_of_file = TRUE; } +METHODDEF(void) +init_mem_source (j_decompress_ptr cinfo) +{ + /* no work necessary here */ +} + /* * Fill the input buffer --- called whenever buffer is emptied. @@ -111,6 +118,26 @@ fill_input_buffer (j_decompress_ptr cinfo) return TRUE; } +METHODDEF(boolean) +fill_mem_input_buffer (j_decompress_ptr cinfo) +{ + static JOCTET mybuffer[4]; + + /* The whole JPEG data is expected to reside in the supplied memory + * buffer, so any request for more data beyond the given buffer size + * is treated as an error. + */ + WARNMS(cinfo, JWRN_JPEG_EOF); + /* Insert a fake EOI marker */ + mybuffer[0] = (JOCTET) 0xFF; + mybuffer[1] = (JOCTET) JPEG_EOI; + + cinfo->src->next_input_byte = mybuffer; + cinfo->src->bytes_in_buffer = 2; + + return TRUE; +} + /* * Skip data --- used to skip over a potentially large amount of @@ -127,22 +154,22 @@ fill_input_buffer (j_decompress_ptr cinfo) METHODDEF(void) skip_input_data (j_decompress_ptr cinfo, long num_bytes) { - my_src_ptr src = (my_src_ptr) cinfo->src; + struct jpeg_source_mgr * src = cinfo->src; /* Just a dumb implementation for now. Could use fseek() except * it doesn't work on pipes. Not clear that being smart is worth * any trouble anyway --- large skips are infrequent. */ if (num_bytes > 0) { - while (num_bytes > (long) src->pub.bytes_in_buffer) { - num_bytes -= (long) src->pub.bytes_in_buffer; - (void) fill_input_buffer(cinfo); + while (num_bytes > (long) src->bytes_in_buffer) { + num_bytes -= (long) src->bytes_in_buffer; + (void) (*src->fill_input_buffer) (cinfo); /* note we assume that fill_input_buffer will never return FALSE, * so suspension need not be handled. */ } - src->pub.next_input_byte += (size_t) num_bytes; - src->pub.bytes_in_buffer -= (size_t) num_bytes; + src->next_input_byte += (size_t) num_bytes; + src->bytes_in_buffer -= (size_t) num_bytes; } } @@ -210,3 +237,38 @@ jpeg_stdio_src (j_decompress_ptr cinfo, FILE * infile) src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */ src->pub.next_input_byte = NULL; /* until buffer loaded */ } + + +/* + * Prepare for input from a supplied memory buffer. + * The buffer must contain the whole JPEG data. + */ + +GLOBAL(void) +jpeg_mem_src (j_decompress_ptr cinfo, + unsigned char * inbuffer, unsigned long insize) +{ + struct jpeg_source_mgr * src; + + if (inbuffer == NULL || insize == 0) /* Treat empty input as fatal error */ + ERREXIT(cinfo, JERR_INPUT_EMPTY); + + /* The source object is made permanent so that a series of JPEG images + * can be read from the same buffer by calling jpeg_mem_src only before + * the first one. + */ + if (cinfo->src == NULL) { /* first time for this JPEG object? */ + cinfo->src = (struct jpeg_source_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + SIZEOF(struct jpeg_source_mgr)); + } + + src = cinfo->src; + src->init_source = init_mem_source; + src->fill_input_buffer = fill_mem_input_buffer; + src->skip_input_data = skip_input_data; + src->resync_to_restart = jpeg_resync_to_restart; /* use default method */ + src->term_source = term_source; + src->bytes_in_buffer = (size_t) insize; + src->next_input_byte = (JOCTET *) inbuffer; +} diff --git a/reactos/dll/3rdparty/libjpeg/jdcoefct.c b/reactos/dll/3rdparty/libjpeg/jdcoefct.c index 4938d20fcb6..462e92c6125 100644 --- a/reactos/dll/3rdparty/libjpeg/jdcoefct.c +++ b/reactos/dll/3rdparty/libjpeg/jdcoefct.c @@ -187,7 +187,7 @@ decompress_onepass (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) useful_width = (MCU_col_num < last_MCU_col) ? compptr->MCU_width : compptr->last_col_width; output_ptr = output_buf[compptr->component_index] + - yoffset * compptr->DCT_scaled_size; + yoffset * compptr->DCT_v_scaled_size; start_col = MCU_col_num * compptr->MCU_sample_width; for (yindex = 0; yindex < compptr->MCU_height; yindex++) { if (cinfo->input_iMCU_row < last_iMCU_row || @@ -197,11 +197,11 @@ decompress_onepass (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) (*inverse_DCT) (cinfo, compptr, (JCOEFPTR) coef->MCU_buffer[blkn+xindex], output_ptr, output_col); - output_col += compptr->DCT_scaled_size; + output_col += compptr->DCT_h_scaled_size; } } blkn += compptr->MCU_width; - output_ptr += compptr->DCT_scaled_size; + output_ptr += compptr->DCT_v_scaled_size; } } } @@ -362,9 +362,9 @@ decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) (*inverse_DCT) (cinfo, compptr, (JCOEFPTR) buffer_ptr, output_ptr, output_col); buffer_ptr++; - output_col += compptr->DCT_scaled_size; + output_col += compptr->DCT_h_scaled_size; } - output_ptr += compptr->DCT_scaled_size; + output_ptr += compptr->DCT_v_scaled_size; } } @@ -654,9 +654,9 @@ decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) DC4 = DC5; DC5 = DC6; DC7 = DC8; DC8 = DC9; buffer_ptr++, prev_block_row++, next_block_row++; - output_col += compptr->DCT_scaled_size; + output_col += compptr->DCT_h_scaled_size; } - output_ptr += compptr->DCT_scaled_size; + output_ptr += compptr->DCT_v_scaled_size; } } diff --git a/reactos/dll/3rdparty/libjpeg/jdct.h b/reactos/dll/3rdparty/libjpeg/jdct.h index 04192a266ae..360dec80c94 100644 --- a/reactos/dll/3rdparty/libjpeg/jdct.h +++ b/reactos/dll/3rdparty/libjpeg/jdct.h @@ -14,11 +14,16 @@ /* - * A forward DCT routine is given a pointer to a work area of type DCTELEM[]; - * the DCT is to be performed in-place in that buffer. Type DCTELEM is int - * for 8-bit samples, INT32 for 12-bit samples. (NOTE: Floating-point DCT - * implementations use an array of type FAST_FLOAT, instead.) - * The DCT inputs are expected to be signed (range +-CENTERJSAMPLE). + * A forward DCT routine is given a pointer to an input sample array and + * a pointer to a work area of type DCTELEM[]; the DCT is to be performed + * in-place in that buffer. Type DCTELEM is int for 8-bit samples, INT32 + * for 12-bit samples. (NOTE: Floating-point DCT implementations use an + * array of type FAST_FLOAT, instead.) + * The input data is to be fetched from the sample array starting at a + * specified column. (Any row offset needed will be applied to the array + * pointer before it is passed to the FDCT code.) + * Note that the number of samples fetched by the FDCT routine is + * DCT_h_scaled_size * DCT_v_scaled_size. * The DCT outputs are returned scaled up by a factor of 8; they therefore * have a range of +-8K for 8-bit data, +-128K for 12-bit data. This * convention improves accuracy in integer implementations and saves some @@ -32,8 +37,12 @@ typedef int DCTELEM; /* 16 or 32 bits is fine */ typedef INT32 DCTELEM; /* must have 32 bits */ #endif -typedef JMETHOD(void, forward_DCT_method_ptr, (DCTELEM * data)); -typedef JMETHOD(void, float_DCT_method_ptr, (FAST_FLOAT * data)); +typedef JMETHOD(void, forward_DCT_method_ptr, (DCTELEM * data, + JSAMPARRAY sample_data, + JDIMENSION start_col)); +typedef JMETHOD(void, float_DCT_method_ptr, (FAST_FLOAT * data, + JSAMPARRAY sample_data, + JDIMENSION start_col)); /* @@ -44,7 +53,7 @@ typedef JMETHOD(void, float_DCT_method_ptr, (FAST_FLOAT * data)); * sample array starting at a specified column. (Any row offset needed will * be applied to the array pointer before it is passed to the IDCT code.) * Note that the number of samples emitted by the IDCT routine is - * DCT_scaled_size * DCT_scaled_size. + * DCT_h_scaled_size * DCT_v_scaled_size. */ /* typedef inverse_DCT_method_ptr is declared in jpegint.h */ @@ -84,19 +93,143 @@ typedef FAST_FLOAT FLOAT_MULT_TYPE; /* preferred floating type */ #define jpeg_fdct_islow jFDislow #define jpeg_fdct_ifast jFDifast #define jpeg_fdct_float jFDfloat +#define jpeg_fdct_7x7 jFD7x7 +#define jpeg_fdct_6x6 jFD6x6 +#define jpeg_fdct_5x5 jFD5x5 +#define jpeg_fdct_4x4 jFD4x4 +#define jpeg_fdct_3x3 jFD3x3 +#define jpeg_fdct_2x2 jFD2x2 +#define jpeg_fdct_1x1 jFD1x1 +#define jpeg_fdct_9x9 jFD9x9 +#define jpeg_fdct_10x10 jFD10x10 +#define jpeg_fdct_11x11 jFD11x11 +#define jpeg_fdct_12x12 jFD12x12 +#define jpeg_fdct_13x13 jFD13x13 +#define jpeg_fdct_14x14 jFD14x14 +#define jpeg_fdct_15x15 jFD15x15 +#define jpeg_fdct_16x16 jFD16x16 +#define jpeg_fdct_16x8 jFD16x8 +#define jpeg_fdct_14x7 jFD14x7 +#define jpeg_fdct_12x6 jFD12x6 +#define jpeg_fdct_10x5 jFD10x5 +#define jpeg_fdct_8x4 jFD8x4 +#define jpeg_fdct_6x3 jFD6x3 +#define jpeg_fdct_4x2 jFD4x2 +#define jpeg_fdct_2x1 jFD2x1 +#define jpeg_fdct_8x16 jFD8x16 +#define jpeg_fdct_7x14 jFD7x14 +#define jpeg_fdct_6x12 jFD6x12 +#define jpeg_fdct_5x10 jFD5x10 +#define jpeg_fdct_4x8 jFD4x8 +#define jpeg_fdct_3x6 jFD3x6 +#define jpeg_fdct_2x4 jFD2x4 +#define jpeg_fdct_1x2 jFD1x2 #define jpeg_idct_islow jRDislow #define jpeg_idct_ifast jRDifast #define jpeg_idct_float jRDfloat +#define jpeg_idct_7x7 jRD7x7 +#define jpeg_idct_6x6 jRD6x6 +#define jpeg_idct_5x5 jRD5x5 #define jpeg_idct_4x4 jRD4x4 +#define jpeg_idct_3x3 jRD3x3 #define jpeg_idct_2x2 jRD2x2 #define jpeg_idct_1x1 jRD1x1 +#define jpeg_idct_9x9 jRD9x9 +#define jpeg_idct_10x10 jRD10x10 +#define jpeg_idct_11x11 jRD11x11 +#define jpeg_idct_12x12 jRD12x12 +#define jpeg_idct_13x13 jRD13x13 +#define jpeg_idct_14x14 jRD14x14 +#define jpeg_idct_15x15 jRD15x15 +#define jpeg_idct_16x16 jRD16x16 +#define jpeg_idct_16x8 jRD16x8 +#define jpeg_idct_14x7 jRD14x7 +#define jpeg_idct_12x6 jRD12x6 +#define jpeg_idct_10x5 jRD10x5 +#define jpeg_idct_8x4 jRD8x4 +#define jpeg_idct_6x3 jRD6x3 +#define jpeg_idct_4x2 jRD4x2 +#define jpeg_idct_2x1 jRD2x1 +#define jpeg_idct_8x16 jRD8x16 +#define jpeg_idct_7x14 jRD7x14 +#define jpeg_idct_6x12 jRD6x12 +#define jpeg_idct_5x10 jRD5x10 +#define jpeg_idct_4x8 jRD4x8 +#define jpeg_idct_3x6 jRD3x8 +#define jpeg_idct_2x4 jRD2x4 +#define jpeg_idct_1x2 jRD1x2 #endif /* NEED_SHORT_EXTERNAL_NAMES */ /* Extern declarations for the forward and inverse DCT routines. */ -EXTERN(void) jpeg_fdct_islow JPP((DCTELEM * data)); -EXTERN(void) jpeg_fdct_ifast JPP((DCTELEM * data)); -EXTERN(void) jpeg_fdct_float JPP((FAST_FLOAT * data)); +EXTERN(void) jpeg_fdct_islow + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_ifast + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_float + JPP((FAST_FLOAT * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_7x7 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_6x6 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_5x5 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_4x4 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_3x3 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_2x2 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_1x1 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_9x9 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_10x10 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_11x11 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_12x12 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_13x13 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_14x14 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_15x15 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_16x16 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_16x8 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_14x7 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_12x6 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_10x5 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_8x4 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_6x3 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_4x2 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_2x1 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_8x16 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_7x14 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_6x12 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_5x10 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_4x8 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_3x6 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_2x4 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_1x2 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); EXTERN(void) jpeg_idct_islow JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, @@ -107,15 +240,99 @@ EXTERN(void) jpeg_idct_ifast EXTERN(void) jpeg_idct_float JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_7x7 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_6x6 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_5x5 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_4x4 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_3x3 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_2x2 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_1x1 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_9x9 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_10x10 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_11x11 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_12x12 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_13x13 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_14x14 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_15x15 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_16x16 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_16x8 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_14x7 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_12x6 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_10x5 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_8x4 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_6x3 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_4x2 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_2x1 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_8x16 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_7x14 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_6x12 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_5x10 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_4x8 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_3x6 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_2x4 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_1x2 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); /* diff --git a/reactos/dll/3rdparty/libjpeg/jddctmgr.c b/reactos/dll/3rdparty/libjpeg/jddctmgr.c index bbf8d0e92fd..0ded9d57413 100644 --- a/reactos/dll/3rdparty/libjpeg/jddctmgr.c +++ b/reactos/dll/3rdparty/libjpeg/jddctmgr.c @@ -2,6 +2,7 @@ * jddctmgr.c * * Copyright (C) 1994-1996, Thomas G. Lane. + * Modified 2002-2010 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -98,22 +99,134 @@ start_pass (j_decompress_ptr cinfo) for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { /* Select the proper IDCT routine for this component's scaling */ - switch (compptr->DCT_scaled_size) { + switch ((compptr->DCT_h_scaled_size << 8) + compptr->DCT_v_scaled_size) { #ifdef IDCT_SCALING_SUPPORTED - case 1: + case ((1 << 8) + 1): method_ptr = jpeg_idct_1x1; - method = JDCT_ISLOW; /* jidctred uses islow-style table */ + method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; - case 2: + case ((2 << 8) + 2): method_ptr = jpeg_idct_2x2; - method = JDCT_ISLOW; /* jidctred uses islow-style table */ + method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; - case 4: + case ((3 << 8) + 3): + method_ptr = jpeg_idct_3x3; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((4 << 8) + 4): method_ptr = jpeg_idct_4x4; - method = JDCT_ISLOW; /* jidctred uses islow-style table */ + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((5 << 8) + 5): + method_ptr = jpeg_idct_5x5; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((6 << 8) + 6): + method_ptr = jpeg_idct_6x6; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((7 << 8) + 7): + method_ptr = jpeg_idct_7x7; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((9 << 8) + 9): + method_ptr = jpeg_idct_9x9; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((10 << 8) + 10): + method_ptr = jpeg_idct_10x10; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((11 << 8) + 11): + method_ptr = jpeg_idct_11x11; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((12 << 8) + 12): + method_ptr = jpeg_idct_12x12; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((13 << 8) + 13): + method_ptr = jpeg_idct_13x13; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((14 << 8) + 14): + method_ptr = jpeg_idct_14x14; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((15 << 8) + 15): + method_ptr = jpeg_idct_15x15; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((16 << 8) + 16): + method_ptr = jpeg_idct_16x16; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((16 << 8) + 8): + method_ptr = jpeg_idct_16x8; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((14 << 8) + 7): + method_ptr = jpeg_idct_14x7; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((12 << 8) + 6): + method_ptr = jpeg_idct_12x6; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((10 << 8) + 5): + method_ptr = jpeg_idct_10x5; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((8 << 8) + 4): + method_ptr = jpeg_idct_8x4; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((6 << 8) + 3): + method_ptr = jpeg_idct_6x3; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((4 << 8) + 2): + method_ptr = jpeg_idct_4x2; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((2 << 8) + 1): + method_ptr = jpeg_idct_2x1; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((8 << 8) + 16): + method_ptr = jpeg_idct_8x16; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((7 << 8) + 14): + method_ptr = jpeg_idct_7x14; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((6 << 8) + 12): + method_ptr = jpeg_idct_6x12; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((5 << 8) + 10): + method_ptr = jpeg_idct_5x10; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((4 << 8) + 8): + method_ptr = jpeg_idct_4x8; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((3 << 8) + 6): + method_ptr = jpeg_idct_3x6; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((2 << 8) + 4): + method_ptr = jpeg_idct_2x4; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ + break; + case ((1 << 8) + 2): + method_ptr = jpeg_idct_1x2; + method = JDCT_ISLOW; /* jidctint uses islow-style table */ break; #endif - case DCTSIZE: + case ((DCTSIZE << 8) + DCTSIZE): switch (cinfo->dct_method) { #ifdef DCT_ISLOW_SUPPORTED case JDCT_ISLOW: @@ -139,7 +252,8 @@ start_pass (j_decompress_ptr cinfo) } break; default: - ERREXIT1(cinfo, JERR_BAD_DCTSIZE, compptr->DCT_scaled_size); + ERREXIT2(cinfo, JERR_BAD_DCTSIZE, + compptr->DCT_h_scaled_size, compptr->DCT_v_scaled_size); break; } idct->pub.inverse_DCT[ci] = method_ptr; @@ -211,6 +325,7 @@ start_pass (j_decompress_ptr cinfo) * coefficients scaled by scalefactor[row]*scalefactor[col], where * scalefactor[0] = 1 * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + * We apply a further scale factor of 1/8. */ FLOAT_MULT_TYPE * fmtbl = (FLOAT_MULT_TYPE *) compptr->dct_table; int row, col; @@ -224,7 +339,7 @@ start_pass (j_decompress_ptr cinfo) for (col = 0; col < DCTSIZE; col++) { fmtbl[i] = (FLOAT_MULT_TYPE) ((double) qtbl->quantval[i] * - aanscalefactor[row] * aanscalefactor[col]); + aanscalefactor[row] * aanscalefactor[col] * 0.125); i++; } } diff --git a/reactos/dll/3rdparty/libjpeg/jdhuff.c b/reactos/dll/3rdparty/libjpeg/jdhuff.c index b5ba39f736a..06f92fe47f6 100644 --- a/reactos/dll/3rdparty/libjpeg/jdhuff.c +++ b/reactos/dll/3rdparty/libjpeg/jdhuff.c @@ -2,10 +2,12 @@ * jdhuff.c * * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 2006-2009 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains Huffman entropy decoding routines. + * Both sequential and progressive modes are supported in this single module. * * Much of the complexity here has to do with supporting input suspension. * If the data source module demands suspension, we want to be able to back @@ -17,7 +19,173 @@ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" -#include "jdhuff.h" /* Declarations shared with jdphuff.c */ + + +/* Derived data constructed for each Huffman table */ + +#define HUFF_LOOKAHEAD 8 /* # of bits of lookahead */ + +typedef struct { + /* Basic tables: (element [0] of each array is unused) */ + INT32 maxcode[18]; /* largest code of length k (-1 if none) */ + /* (maxcode[17] is a sentinel to ensure jpeg_huff_decode terminates) */ + INT32 valoffset[17]; /* huffval[] offset for codes of length k */ + /* valoffset[k] = huffval[] index of 1st symbol of code length k, less + * the smallest code of length k; so given a code of length k, the + * corresponding symbol is huffval[code + valoffset[k]] + */ + + /* Link to public Huffman table (needed only in jpeg_huff_decode) */ + JHUFF_TBL *pub; + + /* Lookahead tables: indexed by the next HUFF_LOOKAHEAD bits of + * the input data stream. If the next Huffman code is no more + * than HUFF_LOOKAHEAD bits long, we can obtain its length and + * the corresponding symbol directly from these tables. + */ + int look_nbits[1< 32 bits on your machine, and shifting/masking longs is + * reasonably fast, making bit_buf_type be long and setting BIT_BUF_SIZE + * appropriately should be a win. Unfortunately we can't define the size + * with something like #define BIT_BUF_SIZE (sizeof(bit_buf_type)*8) + * because not all machines measure sizeof in 8-bit bytes. + */ + +typedef struct { /* Bitreading state saved across MCUs */ + bit_buf_type get_buffer; /* current bit-extraction buffer */ + int bits_left; /* # of unused bits in it */ +} bitread_perm_state; + +typedef struct { /* Bitreading working state within an MCU */ + /* Current data source location */ + /* We need a copy, rather than munging the original, in case of suspension */ + const JOCTET * next_input_byte; /* => next byte to read from source */ + size_t bytes_in_buffer; /* # of bytes remaining in source buffer */ + /* Bit input buffer --- note these values are kept in register variables, + * not in this struct, inside the inner loops. + */ + bit_buf_type get_buffer; /* current bit-extraction buffer */ + int bits_left; /* # of unused bits in it */ + /* Pointer needed by jpeg_fill_bit_buffer. */ + j_decompress_ptr cinfo; /* back link to decompress master record */ +} bitread_working_state; + +/* Macros to declare and load/save bitread local variables. */ +#define BITREAD_STATE_VARS \ + register bit_buf_type get_buffer; \ + register int bits_left; \ + bitread_working_state br_state + +#define BITREAD_LOAD_STATE(cinfop,permstate) \ + br_state.cinfo = cinfop; \ + br_state.next_input_byte = cinfop->src->next_input_byte; \ + br_state.bytes_in_buffer = cinfop->src->bytes_in_buffer; \ + get_buffer = permstate.get_buffer; \ + bits_left = permstate.bits_left; + +#define BITREAD_SAVE_STATE(cinfop,permstate) \ + cinfop->src->next_input_byte = br_state.next_input_byte; \ + cinfop->src->bytes_in_buffer = br_state.bytes_in_buffer; \ + permstate.get_buffer = get_buffer; \ + permstate.bits_left = bits_left + +/* + * These macros provide the in-line portion of bit fetching. + * Use CHECK_BIT_BUFFER to ensure there are N bits in get_buffer + * before using GET_BITS, PEEK_BITS, or DROP_BITS. + * The variables get_buffer and bits_left are assumed to be locals, + * but the state struct might not be (jpeg_huff_decode needs this). + * CHECK_BIT_BUFFER(state,n,action); + * Ensure there are N bits in get_buffer; if suspend, take action. + * val = GET_BITS(n); + * Fetch next N bits. + * val = PEEK_BITS(n); + * Fetch next N bits without removing them from the buffer. + * DROP_BITS(n); + * Discard next N bits. + * The value N should be a simple variable, not an expression, because it + * is evaluated multiple times. + */ + +#define CHECK_BIT_BUFFER(state,nbits,action) \ + { if (bits_left < (nbits)) { \ + if (! jpeg_fill_bit_buffer(&(state),get_buffer,bits_left,nbits)) \ + { action; } \ + get_buffer = (state).get_buffer; bits_left = (state).bits_left; } } + +#define GET_BITS(nbits) \ + (((int) (get_buffer >> (bits_left -= (nbits)))) & BIT_MASK(nbits)) + +#define PEEK_BITS(nbits) \ + (((int) (get_buffer >> (bits_left - (nbits)))) & BIT_MASK(nbits)) + +#define DROP_BITS(nbits) \ + (bits_left -= (nbits)) + + +/* + * Code for extracting next Huffman-coded symbol from input bit stream. + * Again, this is time-critical and we make the main paths be macros. + * + * We use a lookahead table to process codes of up to HUFF_LOOKAHEAD bits + * without looping. Usually, more than 95% of the Huffman codes will be 8 + * or fewer bits long. The few overlength codes are handled with a loop, + * which need not be inline code. + * + * Notes about the HUFF_DECODE macro: + * 1. Near the end of the data segment, we may fail to get enough bits + * for a lookahead. In that case, we do it the hard way. + * 2. If the lookahead table contains no entry, the next code must be + * more than HUFF_LOOKAHEAD bits long. + * 3. jpeg_huff_decode returns -1 if forced to suspend. + */ + +#define HUFF_DECODE(result,state,htbl,failaction,slowlabel) \ +{ register int nb, look; \ + if (bits_left < HUFF_LOOKAHEAD) { \ + if (! jpeg_fill_bit_buffer(&state,get_buffer,bits_left, 0)) {failaction;} \ + get_buffer = state.get_buffer; bits_left = state.bits_left; \ + if (bits_left < HUFF_LOOKAHEAD) { \ + nb = 1; goto slowlabel; \ + } \ + } \ + look = PEEK_BITS(HUFF_LOOKAHEAD); \ + if ((nb = htbl->look_nbits[look]) != 0) { \ + DROP_BITS(nb); \ + result = htbl->look_sym[look]; \ + } else { \ + nb = HUFF_LOOKAHEAD+1; \ +slowlabel: \ + if ((result=jpeg_huff_decode(&state,get_buffer,bits_left,htbl,nb)) < 0) \ + { failaction; } \ + get_buffer = state.get_buffer; bits_left = state.bits_left; \ + } \ +} /* @@ -28,7 +196,8 @@ */ typedef struct { - int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ + unsigned int EOBRUN; /* remaining EOBs in EOBRUN */ + int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ } savable_state; /* This macro is to work around compilers with missing or broken @@ -41,7 +210,8 @@ typedef struct { #else #if MAX_COMPS_IN_SCAN == 4 #define ASSIGN_STATE(dest,src) \ - ((dest).last_dc_val[0] = (src).last_dc_val[0], \ + ((dest).EOBRUN = (src).EOBRUN, \ + (dest).last_dc_val[0] = (src).last_dc_val[0], \ (dest).last_dc_val[1] = (src).last_dc_val[1], \ (dest).last_dc_val[2] = (src).last_dc_val[2], \ (dest).last_dc_val[3] = (src).last_dc_val[3]) @@ -59,8 +229,18 @@ typedef struct { savable_state saved; /* Other state at start of MCU */ /* These fields are NOT loaded into local working state. */ + boolean insufficient_data; /* set TRUE after emitting warning */ unsigned int restarts_to_go; /* MCUs left in this restart interval */ + /* Following two fields used only in progressive mode */ + + /* Pointers to derived tables (these workspaces have image lifespan) */ + d_derived_tbl * derived_tbls[NUM_HUFF_TBLS]; + + d_derived_tbl * ac_derived_tbl; /* active table during an AC scan */ + + /* Following fields used only in sequential mode */ + /* Pointers to derived tables (these workspaces have image lifespan) */ d_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS]; d_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS]; @@ -71,81 +251,75 @@ typedef struct { d_derived_tbl * dc_cur_tbls[D_MAX_BLOCKS_IN_MCU]; d_derived_tbl * ac_cur_tbls[D_MAX_BLOCKS_IN_MCU]; /* Whether we care about the DC and AC coefficient values for each block */ - boolean dc_needed[D_MAX_BLOCKS_IN_MCU]; - boolean ac_needed[D_MAX_BLOCKS_IN_MCU]; + int coef_limit[D_MAX_BLOCKS_IN_MCU]; } huff_entropy_decoder; typedef huff_entropy_decoder * huff_entropy_ptr; -/* - * Initialize for a Huffman-compressed scan. - */ +static const int jpeg_zigzag_order[8][8] = { + { 0, 1, 5, 6, 14, 15, 27, 28 }, + { 2, 4, 7, 13, 16, 26, 29, 42 }, + { 3, 8, 12, 17, 25, 30, 41, 43 }, + { 9, 11, 18, 24, 31, 40, 44, 53 }, + { 10, 19, 23, 32, 39, 45, 52, 54 }, + { 20, 22, 33, 38, 46, 51, 55, 60 }, + { 21, 34, 37, 47, 50, 56, 59, 61 }, + { 35, 36, 48, 49, 57, 58, 62, 63 } +}; -METHODDEF(void) -start_pass_huff_decoder (j_decompress_ptr cinfo) -{ - huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; - int ci, blkn, dctbl, actbl; - jpeg_component_info * compptr; +static const int jpeg_zigzag_order7[7][7] = { + { 0, 1, 5, 6, 14, 15, 27 }, + { 2, 4, 7, 13, 16, 26, 28 }, + { 3, 8, 12, 17, 25, 29, 38 }, + { 9, 11, 18, 24, 30, 37, 39 }, + { 10, 19, 23, 31, 36, 40, 45 }, + { 20, 22, 32, 35, 41, 44, 46 }, + { 21, 33, 34, 42, 43, 47, 48 } +}; - /* Check that the scan parameters Ss, Se, Ah/Al are OK for sequential JPEG. - * This ought to be an error condition, but we make it a warning because - * there are some baseline files out there with all zeroes in these bytes. - */ - if (cinfo->Ss != 0 || cinfo->Se != DCTSIZE2-1 || - cinfo->Ah != 0 || cinfo->Al != 0) - WARNMS(cinfo, JWRN_NOT_SEQUENTIAL); +static const int jpeg_zigzag_order6[6][6] = { + { 0, 1, 5, 6, 14, 15 }, + { 2, 4, 7, 13, 16, 25 }, + { 3, 8, 12, 17, 24, 26 }, + { 9, 11, 18, 23, 27, 32 }, + { 10, 19, 22, 28, 31, 33 }, + { 20, 21, 29, 30, 34, 35 } +}; - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - dctbl = compptr->dc_tbl_no; - actbl = compptr->ac_tbl_no; - /* Compute derived values for Huffman tables */ - /* We may do this more than once for a table, but it's not expensive */ - jpeg_make_d_derived_tbl(cinfo, TRUE, dctbl, - & entropy->dc_derived_tbls[dctbl]); - jpeg_make_d_derived_tbl(cinfo, FALSE, actbl, - & entropy->ac_derived_tbls[actbl]); - /* Initialize DC predictions to 0 */ - entropy->saved.last_dc_val[ci] = 0; - } +static const int jpeg_zigzag_order5[5][5] = { + { 0, 1, 5, 6, 14 }, + { 2, 4, 7, 13, 15 }, + { 3, 8, 12, 16, 21 }, + { 9, 11, 17, 20, 22 }, + { 10, 18, 19, 23, 24 } +}; - /* Precalculate decoding info for each block in an MCU of this scan */ - for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - ci = cinfo->MCU_membership[blkn]; - compptr = cinfo->cur_comp_info[ci]; - /* Precalculate which table to use for each block */ - entropy->dc_cur_tbls[blkn] = entropy->dc_derived_tbls[compptr->dc_tbl_no]; - entropy->ac_cur_tbls[blkn] = entropy->ac_derived_tbls[compptr->ac_tbl_no]; - /* Decide whether we really care about the coefficient values */ - if (compptr->component_needed) { - entropy->dc_needed[blkn] = TRUE; - /* we don't need the ACs if producing a 1/8th-size image */ - entropy->ac_needed[blkn] = (compptr->DCT_scaled_size > 1); - } else { - entropy->dc_needed[blkn] = entropy->ac_needed[blkn] = FALSE; - } - } +static const int jpeg_zigzag_order4[4][4] = { + { 0, 1, 5, 6 }, + { 2, 4, 7, 12 }, + { 3, 8, 11, 13 }, + { 9, 10, 14, 15 } +}; - /* Initialize bitread state variables */ - entropy->bitstate.bits_left = 0; - entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */ - entropy->pub.insufficient_data = FALSE; +static const int jpeg_zigzag_order3[3][3] = { + { 0, 1, 5 }, + { 2, 4, 6 }, + { 3, 7, 8 } +}; - /* Initialize restart counter */ - entropy->restarts_to_go = cinfo->restart_interval; -} +static const int jpeg_zigzag_order2[2][2] = { + { 0, 1 }, + { 2, 3 } +}; /* * Compute the derived values for a Huffman table. * This routine also performs some validation checks on the table. - * - * Note this is also used by jdphuff.c. */ -GLOBAL(void) +LOCAL(void) jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno, d_derived_tbl ** pdtbl) { @@ -267,8 +441,7 @@ jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno, /* - * Out-of-line code for bit fetching (shared with jdphuff.c). - * See jdhuff.h for info about usage. + * Out-of-line code for bit fetching. * Note: current values of get_buffer and bits_left are passed as parameters, * but are returned in the corresponding fields of the state struct. * @@ -288,7 +461,7 @@ jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno, #endif -GLOBAL(boolean) +LOCAL(boolean) jpeg_fill_bit_buffer (bitread_working_state * state, register bit_buf_type get_buffer, register int bits_left, int nbits) @@ -369,9 +542,9 @@ jpeg_fill_bit_buffer (bitread_working_state * state, * We use a nonvolatile flag to ensure that only one warning message * appears per data segment. */ - if (! cinfo->entropy->insufficient_data) { + if (! ((huff_entropy_ptr) cinfo->entropy)->insufficient_data) { WARNMS(cinfo, JWRN_HIT_MARKER); - cinfo->entropy->insufficient_data = TRUE; + ((huff_entropy_ptr) cinfo->entropy)->insufficient_data = TRUE; } /* Fill the buffer with zero bits */ get_buffer <<= MIN_GET_BITS - bits_left; @@ -390,11 +563,32 @@ jpeg_fill_bit_buffer (bitread_working_state * state, /* - * Out-of-line code for Huffman code decoding. - * See jdhuff.h for info about usage. + * Figure F.12: extend sign bit. + * On some machines, a shift and sub will be faster than a table lookup. */ -GLOBAL(int) +#ifdef AVOID_TABLES + +#define BIT_MASK(nbits) ((1<<(nbits))-1) +#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) - ((1<<(s))-1) : (x)) + +#else + +#define BIT_MASK(nbits) bmask[nbits] +#define HUFF_EXTEND(x,s) ((x) <= bmask[(s) - 1] ? (x) - bmask[s] : (x)) + +static const int bmask[16] = /* bmask[n] is mask for n rightmost bits */ + { 0, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, + 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF }; + +#endif /* AVOID_TABLES */ + + +/* + * Out-of-line code for Huffman code decoding. + */ + +LOCAL(int) jpeg_huff_decode (bitread_working_state * state, register bit_buf_type get_buffer, register int bits_left, d_derived_tbl * htbl, int min_bits) @@ -433,32 +627,6 @@ jpeg_huff_decode (bitread_working_state * state, } -/* - * Figure F.12: extend sign bit. - * On some machines, a shift and add will be faster than a table lookup. - */ - -#ifdef AVOID_TABLES - -#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x)) - -#else - -#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x)) - -static const int extend_test[16] = /* entry n is 2**(n-1) */ - { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, - 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 }; - -static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */ - { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1, - ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1, - ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, - ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 }; - -#endif /* AVOID_TABLES */ - - /* * Check for a restart marker & resynchronize decoder. * Returns FALSE if must suspend. @@ -482,6 +650,8 @@ process_restart (j_decompress_ptr cinfo) /* Re-initialize DC predictions to 0 */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) entropy->saved.last_dc_val[ci] = 0; + /* Re-init EOB run count, too */ + entropy->saved.EOBRUN = 0; /* Reset restart counter */ entropy->restarts_to_go = cinfo->restart_interval; @@ -492,25 +662,525 @@ process_restart (j_decompress_ptr cinfo) * leaving the flag set. */ if (cinfo->unread_marker == 0) - entropy->pub.insufficient_data = FALSE; + entropy->insufficient_data = FALSE; return TRUE; } /* - * Decode and return one MCU's worth of Huffman-compressed coefficients. + * Huffman MCU decoding. + * Each of these routines decodes and returns one MCU's worth of + * Huffman-compressed coefficients. * The coefficients are reordered from zigzag order into natural array order, * but are not dequantized. * * The i'th block of the MCU is stored into the block pointed to by - * MCU_data[i]. WE ASSUME THIS AREA HAS BEEN ZEROED BY THE CALLER. + * MCU_data[i]. WE ASSUME THIS AREA IS INITIALLY ZEROED BY THE CALLER. * (Wholesale zeroing is usually a little faster than retail...) * - * Returns FALSE if data source requested suspension. In that case no + * We return FALSE if data source requested suspension. In that case no * changes have been made to permanent state. (Exception: some output * coefficients may already have been assigned. This is harmless for - * this module, since we'll just re-assign them on the next call.) + * spectral selection, since we'll just re-assign them on the next call. + * Successive approximation AC refinement has to be more careful, however.) + */ + +/* + * MCU decoding for DC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int Al = cinfo->Al; + register int s, r; + int blkn, ci; + JBLOCKROW block; + BITREAD_STATE_VARS; + savable_state state; + d_derived_tbl * tbl; + jpeg_component_info * compptr; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* If we've run out of data, just leave the MCU set to zeroes. + * This way, we return uniform gray for the remainder of the segment. + */ + if (! entropy->insufficient_data) { + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(state, entropy->saved); + + /* Outer loop handles each block in the MCU */ + + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + block = MCU_data[blkn]; + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + tbl = entropy->derived_tbls[compptr->dc_tbl_no]; + + /* Decode a single block's worth of coefficients */ + + /* Section F.2.2.1: decode the DC coefficient difference */ + HUFF_DECODE(s, br_state, tbl, return FALSE, label1); + if (s) { + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + } + + /* Convert DC difference to actual value, update last_dc_val */ + s += state.last_dc_val[ci]; + state.last_dc_val[ci] = s; + /* Scale and output the coefficient (assumes jpeg_natural_order[0]=0) */ + (*block)[0] = (JCOEF) (s << Al); + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(entropy->saved, state); + } + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; +} + + +/* + * MCU decoding for AC initial scan (either spectral selection, + * or first pass of successive approximation). + */ + +METHODDEF(boolean) +decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + register int s, k, r; + unsigned int EOBRUN; + int Se, Al; + const int * natural_order; + JBLOCKROW block; + BITREAD_STATE_VARS; + d_derived_tbl * tbl; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* If we've run out of data, just leave the MCU set to zeroes. + * This way, we return uniform gray for the remainder of the segment. + */ + if (! entropy->insufficient_data) { + + Se = cinfo->Se; + Al = cinfo->Al; + natural_order = cinfo->natural_order; + + /* Load up working state. + * We can avoid loading/saving bitread state if in an EOB run. + */ + EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */ + + /* There is always only one block per MCU */ + + if (EOBRUN > 0) /* if it's a band of zeroes... */ + EOBRUN--; /* ...process it now (we do nothing) */ + else { + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + block = MCU_data[0]; + tbl = entropy->ac_derived_tbl; + + for (k = cinfo->Ss; k <= Se; k++) { + HUFF_DECODE(s, br_state, tbl, return FALSE, label2); + r = s >> 4; + s &= 15; + if (s) { + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + /* Scale and output coefficient in natural (dezigzagged) order */ + (*block)[natural_order[k]] = (JCOEF) (s << Al); + } else { + if (r == 15) { /* ZRL */ + k += 15; /* skip 15 zeroes in band */ + } else { /* EOBr, run length is 2^r + appended bits */ + EOBRUN = 1 << r; + if (r) { /* EOBr, r > 0 */ + CHECK_BIT_BUFFER(br_state, r, return FALSE); + r = GET_BITS(r); + EOBRUN += r; + } + EOBRUN--; /* this band is processed at this moment */ + break; /* force end-of-band */ + } + } + } + + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + } + + /* Completed MCU, so update state */ + entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */ + } + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; +} + + +/* + * MCU decoding for DC successive approximation refinement scan. + * Note: we assume such scans can be multi-component, although the spec + * is not very clear on the point. + */ + +METHODDEF(boolean) +decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ + int blkn; + JBLOCKROW block; + BITREAD_STATE_VARS; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* Not worth the cycles to check insufficient_data here, + * since we will not change the data anyway if we read zeroes. + */ + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + + /* Outer loop handles each block in the MCU */ + + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + block = MCU_data[blkn]; + + /* Encoded data is simply the next bit of the two's-complement DC value */ + CHECK_BIT_BUFFER(br_state, 1, return FALSE); + if (GET_BITS(1)) + (*block)[0] |= p1; + /* Note: since we use |=, repeating the assignment later is safe */ + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; +} + + +/* + * MCU decoding for AC successive approximation refinement scan. + */ + +METHODDEF(boolean) +decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + register int s, k, r; + unsigned int EOBRUN; + int Se, p1, m1; + const int * natural_order; + JBLOCKROW block; + JCOEFPTR thiscoef; + BITREAD_STATE_VARS; + d_derived_tbl * tbl; + int num_newnz; + int newnz_pos[DCTSIZE2]; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* If we've run out of data, don't modify the MCU. + */ + if (! entropy->insufficient_data) { + + Se = cinfo->Se; + p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ + m1 = (-1) << cinfo->Al; /* -1 in the bit position being coded */ + natural_order = cinfo->natural_order; + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */ + + /* There is always only one block per MCU */ + block = MCU_data[0]; + tbl = entropy->ac_derived_tbl; + + /* If we are forced to suspend, we must undo the assignments to any newly + * nonzero coefficients in the block, because otherwise we'd get confused + * next time about which coefficients were already nonzero. + * But we need not undo addition of bits to already-nonzero coefficients; + * instead, we can test the current bit to see if we already did it. + */ + num_newnz = 0; + + /* initialize coefficient loop counter to start of band */ + k = cinfo->Ss; + + if (EOBRUN == 0) { + for (; k <= Se; k++) { + HUFF_DECODE(s, br_state, tbl, goto undoit, label3); + r = s >> 4; + s &= 15; + if (s) { + if (s != 1) /* size of new coef should always be 1 */ + WARNMS(cinfo, JWRN_HUFF_BAD_CODE); + CHECK_BIT_BUFFER(br_state, 1, goto undoit); + if (GET_BITS(1)) + s = p1; /* newly nonzero coef is positive */ + else + s = m1; /* newly nonzero coef is negative */ + } else { + if (r != 15) { + EOBRUN = 1 << r; /* EOBr, run length is 2^r + appended bits */ + if (r) { + CHECK_BIT_BUFFER(br_state, r, goto undoit); + r = GET_BITS(r); + EOBRUN += r; + } + break; /* rest of block is handled by EOB logic */ + } + /* note s = 0 for processing ZRL */ + } + /* Advance over already-nonzero coefs and r still-zero coefs, + * appending correction bits to the nonzeroes. A correction bit is 1 + * if the absolute value of the coefficient must be increased. + */ + do { + thiscoef = *block + natural_order[k]; + if (*thiscoef != 0) { + CHECK_BIT_BUFFER(br_state, 1, goto undoit); + if (GET_BITS(1)) { + if ((*thiscoef & p1) == 0) { /* do nothing if already set it */ + if (*thiscoef >= 0) + *thiscoef += p1; + else + *thiscoef += m1; + } + } + } else { + if (--r < 0) + break; /* reached target zero coefficient */ + } + k++; + } while (k <= Se); + if (s) { + int pos = natural_order[k]; + /* Output newly nonzero coefficient */ + (*block)[pos] = (JCOEF) s; + /* Remember its position in case we have to suspend */ + newnz_pos[num_newnz++] = pos; + } + } + } + + if (EOBRUN > 0) { + /* Scan any remaining coefficient positions after the end-of-band + * (the last newly nonzero coefficient, if any). Append a correction + * bit to each already-nonzero coefficient. A correction bit is 1 + * if the absolute value of the coefficient must be increased. + */ + for (; k <= Se; k++) { + thiscoef = *block + natural_order[k]; + if (*thiscoef != 0) { + CHECK_BIT_BUFFER(br_state, 1, goto undoit); + if (GET_BITS(1)) { + if ((*thiscoef & p1) == 0) { /* do nothing if already changed it */ + if (*thiscoef >= 0) + *thiscoef += p1; + else + *thiscoef += m1; + } + } + } + } + /* Count one block completed in EOB run */ + EOBRUN--; + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */ + } + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; + +undoit: + /* Re-zero any output coefficients that we made newly nonzero */ + while (num_newnz > 0) + (*block)[newnz_pos[--num_newnz]] = 0; + + return FALSE; +} + + +/* + * Decode one MCU's worth of Huffman-compressed coefficients, + * partial blocks. + */ + +METHODDEF(boolean) +decode_mcu_sub (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + const int * natural_order; + int Se, blkn; + BITREAD_STATE_VARS; + savable_state state; + + /* Process restart marker if needed; may have to suspend */ + if (cinfo->restart_interval) { + if (entropy->restarts_to_go == 0) + if (! process_restart(cinfo)) + return FALSE; + } + + /* If we've run out of data, just leave the MCU set to zeroes. + * This way, we return uniform gray for the remainder of the segment. + */ + if (! entropy->insufficient_data) { + + natural_order = cinfo->natural_order; + Se = cinfo->lim_Se; + + /* Load up working state */ + BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(state, entropy->saved); + + /* Outer loop handles each block in the MCU */ + + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + JBLOCKROW block = MCU_data[blkn]; + d_derived_tbl * htbl; + register int s, k, r; + int coef_limit, ci; + + /* Decode a single block's worth of coefficients */ + + /* Section F.2.2.1: decode the DC coefficient difference */ + htbl = entropy->dc_cur_tbls[blkn]; + HUFF_DECODE(s, br_state, htbl, return FALSE, label1); + + htbl = entropy->ac_cur_tbls[blkn]; + k = 1; + coef_limit = entropy->coef_limit[blkn]; + if (coef_limit) { + /* Convert DC difference to actual value, update last_dc_val */ + if (s) { + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + } + ci = cinfo->MCU_membership[blkn]; + s += state.last_dc_val[ci]; + state.last_dc_val[ci] = s; + /* Output the DC coefficient */ + (*block)[0] = (JCOEF) s; + + /* Section F.2.2.2: decode the AC coefficients */ + /* Since zeroes are skipped, output area must be cleared beforehand */ + for (; k < coef_limit; k++) { + HUFF_DECODE(s, br_state, htbl, return FALSE, label2); + + r = s >> 4; + s &= 15; + + if (s) { + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + /* Output coefficient in natural (dezigzagged) order. + * Note: the extra entries in natural_order[] will save us + * if k > Se, which could happen if the data is corrupted. + */ + (*block)[natural_order[k]] = (JCOEF) s; + } else { + if (r != 15) + goto EndOfBlock; + k += 15; + } + } + } else { + if (s) { + CHECK_BIT_BUFFER(br_state, s, return FALSE); + DROP_BITS(s); + } + } + + /* Section F.2.2.2: decode the AC coefficients */ + /* In this path we just discard the values */ + for (; k <= Se; k++) { + HUFF_DECODE(s, br_state, htbl, return FALSE, label3); + + r = s >> 4; + s &= 15; + + if (s) { + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + DROP_BITS(s); + } else { + if (r != 15) + break; + k += 15; + } + } + + EndOfBlock: ; + } + + /* Completed MCU, so update state */ + BITREAD_SAVE_STATE(cinfo,entropy->bitstate); + ASSIGN_STATE(entropy->saved, state); + } + + /* Account for restart interval (no-op if not using restarts) */ + entropy->restarts_to_go--; + + return TRUE; +} + + +/* + * Decode one MCU's worth of Huffman-compressed coefficients, + * full-size blocks. */ METHODDEF(boolean) @@ -531,7 +1201,7 @@ decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) /* If we've run out of data, just leave the MCU set to zeroes. * This way, we return uniform gray for the remainder of the segment. */ - if (! entropy->pub.insufficient_data) { + if (! entropy->insufficient_data) { /* Load up working state */ BITREAD_LOAD_STATE(cinfo,entropy->bitstate); @@ -541,39 +1211,40 @@ decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { JBLOCKROW block = MCU_data[blkn]; - d_derived_tbl * dctbl = entropy->dc_cur_tbls[blkn]; - d_derived_tbl * actbl = entropy->ac_cur_tbls[blkn]; + d_derived_tbl * htbl; register int s, k, r; + int coef_limit, ci; /* Decode a single block's worth of coefficients */ /* Section F.2.2.1: decode the DC coefficient difference */ - HUFF_DECODE(s, br_state, dctbl, return FALSE, label1); - if (s) { - CHECK_BIT_BUFFER(br_state, s, return FALSE); - r = GET_BITS(s); - s = HUFF_EXTEND(r, s); - } + htbl = entropy->dc_cur_tbls[blkn]; + HUFF_DECODE(s, br_state, htbl, return FALSE, label1); - if (entropy->dc_needed[blkn]) { + htbl = entropy->ac_cur_tbls[blkn]; + k = 1; + coef_limit = entropy->coef_limit[blkn]; + if (coef_limit) { /* Convert DC difference to actual value, update last_dc_val */ - int ci = cinfo->MCU_membership[blkn]; + if (s) { + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + } + ci = cinfo->MCU_membership[blkn]; s += state.last_dc_val[ci]; state.last_dc_val[ci] = s; - /* Output the DC coefficient (assumes jpeg_natural_order[0] = 0) */ + /* Output the DC coefficient */ (*block)[0] = (JCOEF) s; - } - - if (entropy->ac_needed[blkn]) { /* Section F.2.2.2: decode the AC coefficients */ /* Since zeroes are skipped, output area must be cleared beforehand */ - for (k = 1; k < DCTSIZE2; k++) { - HUFF_DECODE(s, br_state, actbl, return FALSE, label2); - + for (; k < coef_limit; k++) { + HUFF_DECODE(s, br_state, htbl, return FALSE, label2); + r = s >> 4; s &= 15; - + if (s) { k += r; CHECK_BIT_BUFFER(br_state, s, return FALSE); @@ -586,33 +1257,37 @@ decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) (*block)[jpeg_natural_order[k]] = (JCOEF) s; } else { if (r != 15) - break; + goto EndOfBlock; k += 15; } } - } else { - - /* Section F.2.2.2: decode the AC coefficients */ - /* In this path we just discard the values */ - for (k = 1; k < DCTSIZE2; k++) { - HUFF_DECODE(s, br_state, actbl, return FALSE, label3); - - r = s >> 4; - s &= 15; - - if (s) { - k += r; - CHECK_BIT_BUFFER(br_state, s, return FALSE); - DROP_BITS(s); - } else { - if (r != 15) - break; - k += 15; - } + if (s) { + CHECK_BIT_BUFFER(br_state, s, return FALSE); + DROP_BITS(s); } - } + + /* Section F.2.2.2: decode the AC coefficients */ + /* In this path we just discard the values */ + for (; k < DCTSIZE2; k++) { + HUFF_DECODE(s, br_state, htbl, return FALSE, label3); + + r = s >> 4; + s &= 15; + + if (s) { + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + DROP_BITS(s); + } else { + if (r != 15) + break; + k += 15; + } + } + + EndOfBlock: ; } /* Completed MCU, so update state */ @@ -627,6 +1302,205 @@ decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) } +/* + * Initialize for a Huffman-compressed scan. + */ + +METHODDEF(void) +start_pass_huff_decoder (j_decompress_ptr cinfo) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + int ci, blkn, tbl, i; + jpeg_component_info * compptr; + + if (cinfo->progressive_mode) { + /* Validate progressive scan parameters */ + if (cinfo->Ss == 0) { + if (cinfo->Se != 0) + goto bad; + } else { + /* need not check Ss/Se < 0 since they came from unsigned bytes */ + if (cinfo->Se < cinfo->Ss || cinfo->Se > cinfo->lim_Se) + goto bad; + /* AC scans may have only one component */ + if (cinfo->comps_in_scan != 1) + goto bad; + } + if (cinfo->Ah != 0) { + /* Successive approximation refinement scan: must have Al = Ah-1. */ + if (cinfo->Ah-1 != cinfo->Al) + goto bad; + } + if (cinfo->Al > 13) { /* need not check for < 0 */ + /* Arguably the maximum Al value should be less than 13 for 8-bit precision, + * but the spec doesn't say so, and we try to be liberal about what we + * accept. Note: large Al values could result in out-of-range DC + * coefficients during early scans, leading to bizarre displays due to + * overflows in the IDCT math. But we won't crash. + */ + bad: + ERREXIT4(cinfo, JERR_BAD_PROGRESSION, + cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); + } + /* Update progression status, and verify that scan order is legal. + * Note that inter-scan inconsistencies are treated as warnings + * not fatal errors ... not clear if this is right way to behave. + */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + int coefi, cindex = cinfo->cur_comp_info[ci]->component_index; + int *coef_bit_ptr = & cinfo->coef_bits[cindex][0]; + if (cinfo->Ss && coef_bit_ptr[0] < 0) /* AC without prior DC scan */ + WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0); + for (coefi = cinfo->Ss; coefi <= cinfo->Se; coefi++) { + int expected = (coef_bit_ptr[coefi] < 0) ? 0 : coef_bit_ptr[coefi]; + if (cinfo->Ah != expected) + WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, coefi); + coef_bit_ptr[coefi] = cinfo->Al; + } + } + + /* Select MCU decoding routine */ + if (cinfo->Ah == 0) { + if (cinfo->Ss == 0) + entropy->pub.decode_mcu = decode_mcu_DC_first; + else + entropy->pub.decode_mcu = decode_mcu_AC_first; + } else { + if (cinfo->Ss == 0) + entropy->pub.decode_mcu = decode_mcu_DC_refine; + else + entropy->pub.decode_mcu = decode_mcu_AC_refine; + } + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Make sure requested tables are present, and compute derived tables. + * We may build same derived table more than once, but it's not expensive. + */ + if (cinfo->Ss == 0) { + if (cinfo->Ah == 0) { /* DC refinement needs no table */ + tbl = compptr->dc_tbl_no; + jpeg_make_d_derived_tbl(cinfo, TRUE, tbl, + & entropy->derived_tbls[tbl]); + } + } else { + tbl = compptr->ac_tbl_no; + jpeg_make_d_derived_tbl(cinfo, FALSE, tbl, + & entropy->derived_tbls[tbl]); + /* remember the single active table */ + entropy->ac_derived_tbl = entropy->derived_tbls[tbl]; + } + /* Initialize DC predictions to 0 */ + entropy->saved.last_dc_val[ci] = 0; + } + + /* Initialize private state variables */ + entropy->saved.EOBRUN = 0; + } else { + /* Check that the scan parameters Ss, Se, Ah/Al are OK for sequential JPEG. + * This ought to be an error condition, but we make it a warning because + * there are some baseline files out there with all zeroes in these bytes. + */ + if (cinfo->Ss != 0 || cinfo->Ah != 0 || cinfo->Al != 0 || + ((cinfo->is_baseline || cinfo->Se < DCTSIZE2) && + cinfo->Se != cinfo->lim_Se)) + WARNMS(cinfo, JWRN_NOT_SEQUENTIAL); + + /* Select MCU decoding routine */ + /* We retain the hard-coded case for full-size blocks. + * This is not necessary, but it appears that this version is slightly + * more performant in the given implementation. + * With an improved implementation we would prefer a single optimized + * function. + */ + if (cinfo->lim_Se != DCTSIZE2-1) + entropy->pub.decode_mcu = decode_mcu_sub; + else + entropy->pub.decode_mcu = decode_mcu; + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Compute derived values for Huffman tables */ + /* We may do this more than once for a table, but it's not expensive */ + tbl = compptr->dc_tbl_no; + jpeg_make_d_derived_tbl(cinfo, TRUE, tbl, + & entropy->dc_derived_tbls[tbl]); + if (cinfo->lim_Se) { /* AC needs no table when not present */ + tbl = compptr->ac_tbl_no; + jpeg_make_d_derived_tbl(cinfo, FALSE, tbl, + & entropy->ac_derived_tbls[tbl]); + } + /* Initialize DC predictions to 0 */ + entropy->saved.last_dc_val[ci] = 0; + } + + /* Precalculate decoding info for each block in an MCU of this scan */ + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + ci = cinfo->MCU_membership[blkn]; + compptr = cinfo->cur_comp_info[ci]; + /* Precalculate which table to use for each block */ + entropy->dc_cur_tbls[blkn] = entropy->dc_derived_tbls[compptr->dc_tbl_no]; + entropy->ac_cur_tbls[blkn] = entropy->ac_derived_tbls[compptr->ac_tbl_no]; + /* Decide whether we really care about the coefficient values */ + if (compptr->component_needed) { + ci = compptr->DCT_v_scaled_size; + i = compptr->DCT_h_scaled_size; + switch (cinfo->lim_Se) { + case (1*1-1): + entropy->coef_limit[blkn] = 1; + break; + case (2*2-1): + if (ci <= 0 || ci > 2) ci = 2; + if (i <= 0 || i > 2) i = 2; + entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order2[ci - 1][i - 1]; + break; + case (3*3-1): + if (ci <= 0 || ci > 3) ci = 3; + if (i <= 0 || i > 3) i = 3; + entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order3[ci - 1][i - 1]; + break; + case (4*4-1): + if (ci <= 0 || ci > 4) ci = 4; + if (i <= 0 || i > 4) i = 4; + entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order4[ci - 1][i - 1]; + break; + case (5*5-1): + if (ci <= 0 || ci > 5) ci = 5; + if (i <= 0 || i > 5) i = 5; + entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order5[ci - 1][i - 1]; + break; + case (6*6-1): + if (ci <= 0 || ci > 6) ci = 6; + if (i <= 0 || i > 6) i = 6; + entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order6[ci - 1][i - 1]; + break; + case (7*7-1): + if (ci <= 0 || ci > 7) ci = 7; + if (i <= 0 || i > 7) i = 7; + entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order7[ci - 1][i - 1]; + break; + default: + if (ci <= 0 || ci > 8) ci = 8; + if (i <= 0 || i > 8) i = 8; + entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order[ci - 1][i - 1]; + break; + } + } else { + entropy->coef_limit[blkn] = 0; + } + } + } + + /* Initialize bitread state variables */ + entropy->bitstate.bits_left = 0; + entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */ + entropy->insufficient_data = FALSE; + + /* Initialize restart counter */ + entropy->restarts_to_go = cinfo->restart_interval; +} + + /* * Module initialization routine for Huffman entropy decoding. */ @@ -642,10 +1516,26 @@ jinit_huff_decoder (j_decompress_ptr cinfo) SIZEOF(huff_entropy_decoder)); cinfo->entropy = (struct jpeg_entropy_decoder *) entropy; entropy->pub.start_pass = start_pass_huff_decoder; - entropy->pub.decode_mcu = decode_mcu; - /* Mark tables unallocated */ - for (i = 0; i < NUM_HUFF_TBLS; i++) { - entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL; + if (cinfo->progressive_mode) { + /* Create progression status table */ + int *coef_bit_ptr, ci; + cinfo->coef_bits = (int (*)[DCTSIZE2]) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + cinfo->num_components*DCTSIZE2*SIZEOF(int)); + coef_bit_ptr = & cinfo->coef_bits[0][0]; + for (ci = 0; ci < cinfo->num_components; ci++) + for (i = 0; i < DCTSIZE2; i++) + *coef_bit_ptr++ = -1; + + /* Mark derived tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->derived_tbls[i] = NULL; + } + } else { + /* Mark tables unallocated */ + for (i = 0; i < NUM_HUFF_TBLS; i++) { + entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL; + } } } diff --git a/reactos/dll/3rdparty/libjpeg/jdhuff.h b/reactos/dll/3rdparty/libjpeg/jdhuff.h deleted file mode 100644 index ae19b6cafd7..00000000000 --- a/reactos/dll/3rdparty/libjpeg/jdhuff.h +++ /dev/null @@ -1,201 +0,0 @@ -/* - * jdhuff.h - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains declarations for Huffman entropy decoding routines - * that are shared between the sequential decoder (jdhuff.c) and the - * progressive decoder (jdphuff.c). No other modules need to see these. - */ - -/* Short forms of external names for systems with brain-damaged linkers. */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jpeg_make_d_derived_tbl jMkDDerived -#define jpeg_fill_bit_buffer jFilBitBuf -#define jpeg_huff_decode jHufDecode -#endif /* NEED_SHORT_EXTERNAL_NAMES */ - - -/* Derived data constructed for each Huffman table */ - -#define HUFF_LOOKAHEAD 8 /* # of bits of lookahead */ - -typedef struct { - /* Basic tables: (element [0] of each array is unused) */ - INT32 maxcode[18]; /* largest code of length k (-1 if none) */ - /* (maxcode[17] is a sentinel to ensure jpeg_huff_decode terminates) */ - INT32 valoffset[17]; /* huffval[] offset for codes of length k */ - /* valoffset[k] = huffval[] index of 1st symbol of code length k, less - * the smallest code of length k; so given a code of length k, the - * corresponding symbol is huffval[code + valoffset[k]] - */ - - /* Link to public Huffman table (needed only in jpeg_huff_decode) */ - JHUFF_TBL *pub; - - /* Lookahead tables: indexed by the next HUFF_LOOKAHEAD bits of - * the input data stream. If the next Huffman code is no more - * than HUFF_LOOKAHEAD bits long, we can obtain its length and - * the corresponding symbol directly from these tables. - */ - int look_nbits[1< 32 bits on your machine, and shifting/masking longs is - * reasonably fast, making bit_buf_type be long and setting BIT_BUF_SIZE - * appropriately should be a win. Unfortunately we can't define the size - * with something like #define BIT_BUF_SIZE (sizeof(bit_buf_type)*8) - * because not all machines measure sizeof in 8-bit bytes. - */ - -typedef struct { /* Bitreading state saved across MCUs */ - bit_buf_type get_buffer; /* current bit-extraction buffer */ - int bits_left; /* # of unused bits in it */ -} bitread_perm_state; - -typedef struct { /* Bitreading working state within an MCU */ - /* Current data source location */ - /* We need a copy, rather than munging the original, in case of suspension */ - const JOCTET * next_input_byte; /* => next byte to read from source */ - size_t bytes_in_buffer; /* # of bytes remaining in source buffer */ - /* Bit input buffer --- note these values are kept in register variables, - * not in this struct, inside the inner loops. - */ - bit_buf_type get_buffer; /* current bit-extraction buffer */ - int bits_left; /* # of unused bits in it */ - /* Pointer needed by jpeg_fill_bit_buffer. */ - j_decompress_ptr cinfo; /* back link to decompress master record */ -} bitread_working_state; - -/* Macros to declare and load/save bitread local variables. */ -#define BITREAD_STATE_VARS \ - register bit_buf_type get_buffer; \ - register int bits_left; \ - bitread_working_state br_state - -#define BITREAD_LOAD_STATE(cinfop,permstate) \ - br_state.cinfo = cinfop; \ - br_state.next_input_byte = cinfop->src->next_input_byte; \ - br_state.bytes_in_buffer = cinfop->src->bytes_in_buffer; \ - get_buffer = permstate.get_buffer; \ - bits_left = permstate.bits_left; - -#define BITREAD_SAVE_STATE(cinfop,permstate) \ - cinfop->src->next_input_byte = br_state.next_input_byte; \ - cinfop->src->bytes_in_buffer = br_state.bytes_in_buffer; \ - permstate.get_buffer = get_buffer; \ - permstate.bits_left = bits_left - -/* - * These macros provide the in-line portion of bit fetching. - * Use CHECK_BIT_BUFFER to ensure there are N bits in get_buffer - * before using GET_BITS, PEEK_BITS, or DROP_BITS. - * The variables get_buffer and bits_left are assumed to be locals, - * but the state struct might not be (jpeg_huff_decode needs this). - * CHECK_BIT_BUFFER(state,n,action); - * Ensure there are N bits in get_buffer; if suspend, take action. - * val = GET_BITS(n); - * Fetch next N bits. - * val = PEEK_BITS(n); - * Fetch next N bits without removing them from the buffer. - * DROP_BITS(n); - * Discard next N bits. - * The value N should be a simple variable, not an expression, because it - * is evaluated multiple times. - */ - -#define CHECK_BIT_BUFFER(state,nbits,action) \ - { if (bits_left < (nbits)) { \ - if (! jpeg_fill_bit_buffer(&(state),get_buffer,bits_left,nbits)) \ - { action; } \ - get_buffer = (state).get_buffer; bits_left = (state).bits_left; } } - -#define GET_BITS(nbits) \ - (((int) (get_buffer >> (bits_left -= (nbits)))) & ((1<<(nbits))-1)) - -#define PEEK_BITS(nbits) \ - (((int) (get_buffer >> (bits_left - (nbits)))) & ((1<<(nbits))-1)) - -#define DROP_BITS(nbits) \ - (bits_left -= (nbits)) - -/* Load up the bit buffer to a depth of at least nbits */ -EXTERN(boolean) jpeg_fill_bit_buffer - JPP((bitread_working_state * state, register bit_buf_type get_buffer, - register int bits_left, int nbits)); - - -/* - * Code for extracting next Huffman-coded symbol from input bit stream. - * Again, this is time-critical and we make the main paths be macros. - * - * We use a lookahead table to process codes of up to HUFF_LOOKAHEAD bits - * without looping. Usually, more than 95% of the Huffman codes will be 8 - * or fewer bits long. The few overlength codes are handled with a loop, - * which need not be inline code. - * - * Notes about the HUFF_DECODE macro: - * 1. Near the end of the data segment, we may fail to get enough bits - * for a lookahead. In that case, we do it the hard way. - * 2. If the lookahead table contains no entry, the next code must be - * more than HUFF_LOOKAHEAD bits long. - * 3. jpeg_huff_decode returns -1 if forced to suspend. - */ - -#define HUFF_DECODE(result,state,htbl,failaction,slowlabel) \ -{ register int nb, look; \ - if (bits_left < HUFF_LOOKAHEAD) { \ - if (! jpeg_fill_bit_buffer(&state,get_buffer,bits_left, 0)) {failaction;} \ - get_buffer = state.get_buffer; bits_left = state.bits_left; \ - if (bits_left < HUFF_LOOKAHEAD) { \ - nb = 1; goto slowlabel; \ - } \ - } \ - look = PEEK_BITS(HUFF_LOOKAHEAD); \ - if ((nb = htbl->look_nbits[look]) != 0) { \ - DROP_BITS(nb); \ - result = htbl->look_sym[look]; \ - } else { \ - nb = HUFF_LOOKAHEAD+1; \ -slowlabel: \ - if ((result=jpeg_huff_decode(&state,get_buffer,bits_left,htbl,nb)) < 0) \ - { failaction; } \ - get_buffer = state.get_buffer; bits_left = state.bits_left; \ - } \ -} - -/* Out-of-line case for Huffman code fetching */ -EXTERN(int) jpeg_huff_decode - JPP((bitread_working_state * state, register bit_buf_type get_buffer, - register int bits_left, d_derived_tbl * htbl, int min_bits)); diff --git a/reactos/dll/3rdparty/libjpeg/jdinput.c b/reactos/dll/3rdparty/libjpeg/jdinput.c index 0c2ac8f120b..2c5c717b9c3 100644 --- a/reactos/dll/3rdparty/libjpeg/jdinput.c +++ b/reactos/dll/3rdparty/libjpeg/jdinput.c @@ -2,13 +2,14 @@ * jdinput.c * * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 2002-2009 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains input control logic for the JPEG decompressor. * These routines are concerned with controlling the decompressor's input * processing (marker reading and coefficient decoding). The actual input - * reading is done in jdmarker.c, jdhuff.c, and jdphuff.c. + * reading is done in jdmarker.c, jdhuff.c, and jdarith.c. */ #define JPEG_INTERNALS @@ -21,7 +22,7 @@ typedef struct { struct jpeg_input_controller pub; /* public fields */ - boolean inheaders; /* TRUE until first SOS is reached */ + int inheaders; /* Nonzero until first SOS is reached */ } my_input_controller; typedef my_input_controller * my_inputctl_ptr; @@ -35,6 +36,174 @@ METHODDEF(int) consume_markers JPP((j_decompress_ptr cinfo)); * Routines to calculate various quantities related to the size of the image. */ + +/* + * Compute output image dimensions and related values. + * NOTE: this is exported for possible use by application. + * Hence it mustn't do anything that can't be done twice. + */ + +GLOBAL(void) +jpeg_core_output_dimensions (j_decompress_ptr cinfo) +/* Do computations that are needed before master selection phase. + * This function is used for transcoding and full decompression. + */ +{ +#ifdef IDCT_SCALING_SUPPORTED + int ci; + jpeg_component_info *compptr; + + /* Compute actual output image dimensions and DCT scaling choices. */ + if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom) { + /* Provide 1/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 1; + cinfo->min_DCT_v_scaled_size = 1; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 2) { + /* Provide 2/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 2L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 2L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 2; + cinfo->min_DCT_v_scaled_size = 2; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 3) { + /* Provide 3/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 3L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 3L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 3; + cinfo->min_DCT_v_scaled_size = 3; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 4) { + /* Provide 4/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 4L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 4L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 4; + cinfo->min_DCT_v_scaled_size = 4; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 5) { + /* Provide 5/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 5L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 5L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 5; + cinfo->min_DCT_v_scaled_size = 5; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 6) { + /* Provide 6/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 6L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 6L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 6; + cinfo->min_DCT_v_scaled_size = 6; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 7) { + /* Provide 7/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 7L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 7L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 7; + cinfo->min_DCT_v_scaled_size = 7; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 8) { + /* Provide 8/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 8L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 8L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 8; + cinfo->min_DCT_v_scaled_size = 8; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 9) { + /* Provide 9/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 9L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 9L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 9; + cinfo->min_DCT_v_scaled_size = 9; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 10) { + /* Provide 10/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 10L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 10L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 10; + cinfo->min_DCT_v_scaled_size = 10; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 11) { + /* Provide 11/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 11L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 11L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 11; + cinfo->min_DCT_v_scaled_size = 11; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 12) { + /* Provide 12/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 12L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 12L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 12; + cinfo->min_DCT_v_scaled_size = 12; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 13) { + /* Provide 13/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 13L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 13L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 13; + cinfo->min_DCT_v_scaled_size = 13; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 14) { + /* Provide 14/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 14L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 14L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 14; + cinfo->min_DCT_v_scaled_size = 14; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 15) { + /* Provide 15/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 15L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 15L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 15; + cinfo->min_DCT_v_scaled_size = 15; + } else { + /* Provide 16/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 16L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 16L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 16; + cinfo->min_DCT_v_scaled_size = 16; + } + + /* Recompute dimensions of components */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + compptr->DCT_h_scaled_size = cinfo->min_DCT_h_scaled_size; + compptr->DCT_v_scaled_size = cinfo->min_DCT_v_scaled_size; + } + +#else /* !IDCT_SCALING_SUPPORTED */ + + /* Hardwire it to "no scaling" */ + cinfo->output_width = cinfo->image_width; + cinfo->output_height = cinfo->image_height; + /* jdinput.c has already initialized DCT_scaled_size, + * and has computed unscaled downsampled_width and downsampled_height. + */ + +#endif /* IDCT_SCALING_SUPPORTED */ +} + + LOCAL(void) initial_setup (j_decompress_ptr cinfo) /* Called once, when first SOS marker is reached */ @@ -70,23 +239,121 @@ initial_setup (j_decompress_ptr cinfo) compptr->v_samp_factor); } - /* We initialize DCT_scaled_size and min_DCT_scaled_size to DCTSIZE. - * In the full decompressor, this will be overridden by jdmaster.c; - * but in the transcoder, jdmaster.c is not used, so we must do it here. + /* Derive block_size, natural_order, and lim_Se */ + if (cinfo->is_baseline || (cinfo->progressive_mode && + cinfo->comps_in_scan)) { /* no pseudo SOS marker */ + cinfo->block_size = DCTSIZE; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + } else + switch (cinfo->Se) { + case (1*1-1): + cinfo->block_size = 1; + cinfo->natural_order = jpeg_natural_order; /* not needed */ + cinfo->lim_Se = cinfo->Se; + break; + case (2*2-1): + cinfo->block_size = 2; + cinfo->natural_order = jpeg_natural_order2; + cinfo->lim_Se = cinfo->Se; + break; + case (3*3-1): + cinfo->block_size = 3; + cinfo->natural_order = jpeg_natural_order3; + cinfo->lim_Se = cinfo->Se; + break; + case (4*4-1): + cinfo->block_size = 4; + cinfo->natural_order = jpeg_natural_order4; + cinfo->lim_Se = cinfo->Se; + break; + case (5*5-1): + cinfo->block_size = 5; + cinfo->natural_order = jpeg_natural_order5; + cinfo->lim_Se = cinfo->Se; + break; + case (6*6-1): + cinfo->block_size = 6; + cinfo->natural_order = jpeg_natural_order6; + cinfo->lim_Se = cinfo->Se; + break; + case (7*7-1): + cinfo->block_size = 7; + cinfo->natural_order = jpeg_natural_order7; + cinfo->lim_Se = cinfo->Se; + break; + case (8*8-1): + cinfo->block_size = 8; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + break; + case (9*9-1): + cinfo->block_size = 9; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + break; + case (10*10-1): + cinfo->block_size = 10; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + break; + case (11*11-1): + cinfo->block_size = 11; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + break; + case (12*12-1): + cinfo->block_size = 12; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + break; + case (13*13-1): + cinfo->block_size = 13; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + break; + case (14*14-1): + cinfo->block_size = 14; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + break; + case (15*15-1): + cinfo->block_size = 15; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + break; + case (16*16-1): + cinfo->block_size = 16; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + break; + default: + ERREXIT4(cinfo, JERR_BAD_PROGRESSION, + cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); + break; + } + + /* We initialize DCT_scaled_size and min_DCT_scaled_size to block_size. + * In the full decompressor, + * this will be overridden by jpeg_calc_output_dimensions in jdmaster.c; + * but in the transcoder, + * jpeg_calc_output_dimensions is not used, so we must do it here. */ - cinfo->min_DCT_scaled_size = DCTSIZE; + cinfo->min_DCT_h_scaled_size = cinfo->block_size; + cinfo->min_DCT_v_scaled_size = cinfo->block_size; /* Compute dimensions of components */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { - compptr->DCT_scaled_size = DCTSIZE; + compptr->DCT_h_scaled_size = cinfo->block_size; + compptr->DCT_v_scaled_size = cinfo->block_size; /* Size in DCT blocks */ compptr->width_in_blocks = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, - (long) (cinfo->max_h_samp_factor * DCTSIZE)); + (long) (cinfo->max_h_samp_factor * cinfo->block_size)); compptr->height_in_blocks = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, - (long) (cinfo->max_v_samp_factor * DCTSIZE)); + (long) (cinfo->max_v_samp_factor * cinfo->block_size)); /* downsampled_width and downsampled_height will also be overridden by * jdmaster.c if we are doing full decompression. The transcoder library * doesn't use these values, but the calling application might. @@ -107,7 +374,7 @@ initial_setup (j_decompress_ptr cinfo) /* Compute number of fully interleaved MCU rows. */ cinfo->total_iMCU_rows = (JDIMENSION) jdiv_round_up((long) cinfo->image_height, - (long) (cinfo->max_v_samp_factor*DCTSIZE)); + (long) (cinfo->max_v_samp_factor * cinfo->block_size)); /* Decide whether file contains multiple scans */ if (cinfo->comps_in_scan < cinfo->num_components || cinfo->progressive_mode) @@ -138,7 +405,7 @@ per_scan_setup (j_decompress_ptr cinfo) compptr->MCU_width = 1; compptr->MCU_height = 1; compptr->MCU_blocks = 1; - compptr->MCU_sample_width = compptr->DCT_scaled_size; + compptr->MCU_sample_width = compptr->DCT_h_scaled_size; compptr->last_col_width = 1; /* For noninterleaved scans, it is convenient to define last_row_height * as the number of block rows present in the last iMCU row. @@ -161,10 +428,10 @@ per_scan_setup (j_decompress_ptr cinfo) /* Overall image size in MCUs */ cinfo->MCUs_per_row = (JDIMENSION) jdiv_round_up((long) cinfo->image_width, - (long) (cinfo->max_h_samp_factor*DCTSIZE)); + (long) (cinfo->max_h_samp_factor * cinfo->block_size)); cinfo->MCU_rows_in_scan = (JDIMENSION) jdiv_round_up((long) cinfo->image_height, - (long) (cinfo->max_v_samp_factor*DCTSIZE)); + (long) (cinfo->max_v_samp_factor * cinfo->block_size)); cinfo->blocks_in_MCU = 0; @@ -174,7 +441,7 @@ per_scan_setup (j_decompress_ptr cinfo) compptr->MCU_width = compptr->h_samp_factor; compptr->MCU_height = compptr->v_samp_factor; compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height; - compptr->MCU_sample_width = compptr->MCU_width * compptr->DCT_scaled_size; + compptr->MCU_sample_width = compptr->MCU_width * compptr->DCT_h_scaled_size; /* Figure number of non-dummy blocks in last MCU column & row */ tmp = (int) (compptr->width_in_blocks % compptr->MCU_width); if (tmp == 0) tmp = compptr->MCU_width; @@ -282,6 +549,10 @@ finish_input_pass (j_decompress_ptr cinfo) * The consume_input method pointer points either here or to the * coefficient controller's consume_data routine, depending on whether * we are reading a compressed data segment or inter-segment markers. + * + * Note: This function should NOT return a pseudo SOS marker (with zero + * component number) to the caller. A pseudo marker received by + * read_markers is processed and then skipped for other markers. */ METHODDEF(int) @@ -293,41 +564,50 @@ consume_markers (j_decompress_ptr cinfo) if (inputctl->pub.eoi_reached) /* After hitting EOI, read no further */ return JPEG_REACHED_EOI; - val = (*cinfo->marker->read_markers) (cinfo); + for (;;) { /* Loop to pass pseudo SOS marker */ + val = (*cinfo->marker->read_markers) (cinfo); - switch (val) { - case JPEG_REACHED_SOS: /* Found SOS */ - if (inputctl->inheaders) { /* 1st SOS */ - initial_setup(cinfo); - inputctl->inheaders = FALSE; - /* Note: start_input_pass must be called by jdmaster.c - * before any more input can be consumed. jdapimin.c is - * responsible for enforcing this sequencing. - */ - } else { /* 2nd or later SOS marker */ - if (! inputctl->pub.has_multiple_scans) - ERREXIT(cinfo, JERR_EOI_EXPECTED); /* Oops, I wasn't expecting this! */ - start_input_pass(cinfo); + switch (val) { + case JPEG_REACHED_SOS: /* Found SOS */ + if (inputctl->inheaders) { /* 1st SOS */ + if (inputctl->inheaders == 1) + initial_setup(cinfo); + if (cinfo->comps_in_scan == 0) { /* pseudo SOS marker */ + inputctl->inheaders = 2; + break; + } + inputctl->inheaders = 0; + /* Note: start_input_pass must be called by jdmaster.c + * before any more input can be consumed. jdapimin.c is + * responsible for enforcing this sequencing. + */ + } else { /* 2nd or later SOS marker */ + if (! inputctl->pub.has_multiple_scans) + ERREXIT(cinfo, JERR_EOI_EXPECTED); /* Oops, I wasn't expecting this! */ + if (cinfo->comps_in_scan == 0) /* unexpected pseudo SOS marker */ + break; + start_input_pass(cinfo); + } + return val; + case JPEG_REACHED_EOI: /* Found EOI */ + inputctl->pub.eoi_reached = TRUE; + if (inputctl->inheaders) { /* Tables-only datastream, apparently */ + if (cinfo->marker->saw_SOF) + ERREXIT(cinfo, JERR_SOF_NO_SOS); + } else { + /* Prevent infinite loop in coef ctlr's decompress_data routine + * if user set output_scan_number larger than number of scans. + */ + if (cinfo->output_scan_number > cinfo->input_scan_number) + cinfo->output_scan_number = cinfo->input_scan_number; + } + return val; + case JPEG_SUSPENDED: + return val; + default: + return val; } - break; - case JPEG_REACHED_EOI: /* Found EOI */ - inputctl->pub.eoi_reached = TRUE; - if (inputctl->inheaders) { /* Tables-only datastream, apparently */ - if (cinfo->marker->saw_SOF) - ERREXIT(cinfo, JERR_SOF_NO_SOS); - } else { - /* Prevent infinite loop in coef ctlr's decompress_data routine - * if user set output_scan_number larger than number of scans. - */ - if (cinfo->output_scan_number > cinfo->input_scan_number) - cinfo->output_scan_number = cinfo->input_scan_number; - } - break; - case JPEG_SUSPENDED: - break; } - - return val; } @@ -343,7 +623,7 @@ reset_input_controller (j_decompress_ptr cinfo) inputctl->pub.consume_input = consume_markers; inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */ inputctl->pub.eoi_reached = FALSE; - inputctl->inheaders = TRUE; + inputctl->inheaders = 1; /* Reset other modules */ (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); (*cinfo->marker->reset_marker_reader) (cinfo); @@ -377,5 +657,5 @@ jinit_input_controller (j_decompress_ptr cinfo) */ inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */ inputctl->pub.eoi_reached = FALSE; - inputctl->inheaders = TRUE; + inputctl->inheaders = 1; } diff --git a/reactos/dll/3rdparty/libjpeg/jdmainct.c b/reactos/dll/3rdparty/libjpeg/jdmainct.c index 13c956f5deb..02723ca732a 100644 --- a/reactos/dll/3rdparty/libjpeg/jdmainct.c +++ b/reactos/dll/3rdparty/libjpeg/jdmainct.c @@ -161,7 +161,7 @@ alloc_funny_pointers (j_decompress_ptr cinfo) { my_main_ptr main = (my_main_ptr) cinfo->main; int ci, rgroup; - int M = cinfo->min_DCT_scaled_size; + int M = cinfo->min_DCT_v_scaled_size; jpeg_component_info *compptr; JSAMPARRAY xbuf; @@ -175,8 +175,8 @@ alloc_funny_pointers (j_decompress_ptr cinfo) for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { - rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / - cinfo->min_DCT_scaled_size; /* height of a row group of component */ + rgroup = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) / + cinfo->min_DCT_v_scaled_size; /* height of a row group of component */ /* Get space for pointer lists --- M+4 row groups in each list. * We alloc both pointer lists with one call to save a few cycles. */ @@ -202,14 +202,14 @@ make_funny_pointers (j_decompress_ptr cinfo) { my_main_ptr main = (my_main_ptr) cinfo->main; int ci, i, rgroup; - int M = cinfo->min_DCT_scaled_size; + int M = cinfo->min_DCT_v_scaled_size; jpeg_component_info *compptr; JSAMPARRAY buf, xbuf0, xbuf1; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { - rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / - cinfo->min_DCT_scaled_size; /* height of a row group of component */ + rgroup = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) / + cinfo->min_DCT_v_scaled_size; /* height of a row group of component */ xbuf0 = main->xbuffer[0][ci]; xbuf1 = main->xbuffer[1][ci]; /* First copy the workspace pointers as-is */ @@ -242,14 +242,14 @@ set_wraparound_pointers (j_decompress_ptr cinfo) { my_main_ptr main = (my_main_ptr) cinfo->main; int ci, i, rgroup; - int M = cinfo->min_DCT_scaled_size; + int M = cinfo->min_DCT_v_scaled_size; jpeg_component_info *compptr; JSAMPARRAY xbuf0, xbuf1; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { - rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / - cinfo->min_DCT_scaled_size; /* height of a row group of component */ + rgroup = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) / + cinfo->min_DCT_v_scaled_size; /* height of a row group of component */ xbuf0 = main->xbuffer[0][ci]; xbuf1 = main->xbuffer[1][ci]; for (i = 0; i < rgroup; i++) { @@ -277,8 +277,8 @@ set_bottom_pointers (j_decompress_ptr cinfo) for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { /* Count sample rows in one iMCU row and in one row group */ - iMCUheight = compptr->v_samp_factor * compptr->DCT_scaled_size; - rgroup = iMCUheight / cinfo->min_DCT_scaled_size; + iMCUheight = compptr->v_samp_factor * compptr->DCT_v_scaled_size; + rgroup = iMCUheight / cinfo->min_DCT_v_scaled_size; /* Count nondummy sample rows remaining for this component */ rows_left = (int) (compptr->downsampled_height % (JDIMENSION) iMCUheight); if (rows_left == 0) rows_left = iMCUheight; @@ -357,7 +357,7 @@ process_data_simple_main (j_decompress_ptr cinfo, } /* There are always min_DCT_scaled_size row groups in an iMCU row. */ - rowgroups_avail = (JDIMENSION) cinfo->min_DCT_scaled_size; + rowgroups_avail = (JDIMENSION) cinfo->min_DCT_v_scaled_size; /* Note: at the bottom of the image, we may pass extra garbage row groups * to the postprocessor. The postprocessor has to check for bottom * of image anyway (at row resolution), so no point in us doing it too. @@ -417,7 +417,7 @@ process_data_context_main (j_decompress_ptr cinfo, case CTX_PREPARE_FOR_IMCU: /* Prepare to process first M-1 row groups of this iMCU row */ main->rowgroup_ctr = 0; - main->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size - 1); + main->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_v_scaled_size - 1); /* Check for bottom of image: if so, tweak pointers to "duplicate" * the last sample row, and adjust rowgroups_avail to ignore padding rows. */ @@ -440,8 +440,8 @@ process_data_context_main (j_decompress_ptr cinfo, main->buffer_full = FALSE; /* Still need to process last row group of this iMCU row, */ /* which is saved at index M+1 of the other xbuffer */ - main->rowgroup_ctr = (JDIMENSION) (cinfo->min_DCT_scaled_size + 1); - main->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size + 2); + main->rowgroup_ctr = (JDIMENSION) (cinfo->min_DCT_v_scaled_size + 1); + main->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_v_scaled_size + 2); main->context_state = CTX_POSTPONED_ROW; } } @@ -492,21 +492,21 @@ jinit_d_main_controller (j_decompress_ptr cinfo, boolean need_full_buffer) * ngroups is the number of row groups we need. */ if (cinfo->upsample->need_context_rows) { - if (cinfo->min_DCT_scaled_size < 2) /* unsupported, see comments above */ + if (cinfo->min_DCT_v_scaled_size < 2) /* unsupported, see comments above */ ERREXIT(cinfo, JERR_NOTIMPL); alloc_funny_pointers(cinfo); /* Alloc space for xbuffer[] lists */ - ngroups = cinfo->min_DCT_scaled_size + 2; + ngroups = cinfo->min_DCT_v_scaled_size + 2; } else { - ngroups = cinfo->min_DCT_scaled_size; + ngroups = cinfo->min_DCT_v_scaled_size; } for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { - rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / - cinfo->min_DCT_scaled_size; /* height of a row group of component */ + rgroup = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) / + cinfo->min_DCT_v_scaled_size; /* height of a row group of component */ main->buffer[ci] = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, - compptr->width_in_blocks * compptr->DCT_scaled_size, + compptr->width_in_blocks * compptr->DCT_h_scaled_size, (JDIMENSION) (rgroup * ngroups)); } } diff --git a/reactos/dll/3rdparty/libjpeg/jdmarker.c b/reactos/dll/3rdparty/libjpeg/jdmarker.c index f4cca8cc835..f2a9cc42951 100644 --- a/reactos/dll/3rdparty/libjpeg/jdmarker.c +++ b/reactos/dll/3rdparty/libjpeg/jdmarker.c @@ -2,6 +2,7 @@ * jdmarker.c * * Copyright (C) 1991-1998, Thomas G. Lane. + * Modified 2009 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -234,7 +235,8 @@ get_soi (j_decompress_ptr cinfo) LOCAL(boolean) -get_sof (j_decompress_ptr cinfo, boolean is_prog, boolean is_arith) +get_sof (j_decompress_ptr cinfo, boolean is_baseline, boolean is_prog, + boolean is_arith) /* Process a SOFn marker */ { INT32 length; @@ -242,6 +244,7 @@ get_sof (j_decompress_ptr cinfo, boolean is_prog, boolean is_arith) jpeg_component_info * compptr; INPUT_VARS(cinfo); + cinfo->is_baseline = is_baseline; cinfo->progressive_mode = is_prog; cinfo->arith_code = is_arith; @@ -315,7 +318,9 @@ get_sos (j_decompress_ptr cinfo) TRACEMS1(cinfo, 1, JTRC_SOS, n); - if (length != (n * 2 + 6) || n < 1 || n > MAX_COMPS_IN_SCAN) + if (length != (n * 2 + 6) || n > MAX_COMPS_IN_SCAN || + (n == 0 && !cinfo->progressive_mode)) + /* pseudo SOS marker only allowed in progressive mode */ ERREXIT(cinfo, JERR_BAD_LENGTH); cinfo->comps_in_scan = n; @@ -359,8 +364,8 @@ get_sos (j_decompress_ptr cinfo) /* Prepare to scan data & restart markers */ cinfo->marker->next_restart_num = 0; - /* Count another SOS marker */ - cinfo->input_scan_number++; + /* Count another (non-pseudo) SOS marker */ + if (n) cinfo->input_scan_number++; INPUT_SYNC(cinfo); return TRUE; @@ -490,16 +495,18 @@ LOCAL(boolean) get_dqt (j_decompress_ptr cinfo) /* Process a DQT marker */ { - INT32 length; - int n, i, prec; + INT32 length, count, i; + int n, prec; unsigned int tmp; JQUANT_TBL *quant_ptr; + const int *natural_order; INPUT_VARS(cinfo); INPUT_2BYTES(cinfo, length, return FALSE); length -= 2; while (length > 0) { + length--; INPUT_BYTE(cinfo, n, return FALSE); prec = n >> 4; n &= 0x0F; @@ -513,13 +520,43 @@ get_dqt (j_decompress_ptr cinfo) cinfo->quant_tbl_ptrs[n] = jpeg_alloc_quant_table((j_common_ptr) cinfo); quant_ptr = cinfo->quant_tbl_ptrs[n]; - for (i = 0; i < DCTSIZE2; i++) { + if (prec) { + if (length < DCTSIZE2 * 2) { + /* Initialize full table for safety. */ + for (i = 0; i < DCTSIZE2; i++) { + quant_ptr->quantval[i] = 1; + } + count = length >> 1; + } else + count = DCTSIZE2; + } else { + if (length < DCTSIZE2) { + /* Initialize full table for safety. */ + for (i = 0; i < DCTSIZE2; i++) { + quant_ptr->quantval[i] = 1; + } + count = length; + } else + count = DCTSIZE2; + } + + switch (count) { + case (2*2): natural_order = jpeg_natural_order2; break; + case (3*3): natural_order = jpeg_natural_order3; break; + case (4*4): natural_order = jpeg_natural_order4; break; + case (5*5): natural_order = jpeg_natural_order5; break; + case (6*6): natural_order = jpeg_natural_order6; break; + case (7*7): natural_order = jpeg_natural_order7; break; + default: natural_order = jpeg_natural_order; break; + } + + for (i = 0; i < count; i++) { if (prec) INPUT_2BYTES(cinfo, tmp, return FALSE); else INPUT_BYTE(cinfo, tmp, return FALSE); /* We convert the zigzag-order table to natural array order. */ - quant_ptr->quantval[jpeg_natural_order[i]] = (UINT16) tmp; + quant_ptr->quantval[natural_order[i]] = (UINT16) tmp; } if (cinfo->err->trace_level >= 2) { @@ -532,8 +569,8 @@ get_dqt (j_decompress_ptr cinfo) } } - length -= DCTSIZE2+1; - if (prec) length -= DCTSIZE2; + length -= count; + if (prec) length -= count; } if (length != 0) @@ -946,6 +983,11 @@ first_marker (j_decompress_ptr cinfo) * * Returns same codes as are defined for jpeg_consume_input: * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. + * + * Note: This function may return a pseudo SOS marker (with zero + * component number) for treat by input controller's consume_input. + * consume_input itself should filter out (skip) the pseudo marker + * after processing for the caller. */ METHODDEF(int) @@ -975,23 +1017,27 @@ read_markers (j_decompress_ptr cinfo) break; case M_SOF0: /* Baseline */ + if (! get_sof(cinfo, TRUE, FALSE, FALSE)) + return JPEG_SUSPENDED; + break; + case M_SOF1: /* Extended sequential, Huffman */ - if (! get_sof(cinfo, FALSE, FALSE)) + if (! get_sof(cinfo, FALSE, FALSE, FALSE)) return JPEG_SUSPENDED; break; case M_SOF2: /* Progressive, Huffman */ - if (! get_sof(cinfo, TRUE, FALSE)) + if (! get_sof(cinfo, FALSE, TRUE, FALSE)) return JPEG_SUSPENDED; break; case M_SOF9: /* Extended sequential, arithmetic */ - if (! get_sof(cinfo, FALSE, TRUE)) + if (! get_sof(cinfo, FALSE, FALSE, TRUE)) return JPEG_SUSPENDED; break; case M_SOF10: /* Progressive, arithmetic */ - if (! get_sof(cinfo, TRUE, TRUE)) + if (! get_sof(cinfo, FALSE, TRUE, TRUE)) return JPEG_SUSPENDED; break; diff --git a/reactos/dll/3rdparty/libjpeg/jdmaster.c b/reactos/dll/3rdparty/libjpeg/jdmaster.c index 2802c5b7b29..8c1146e4fe1 100644 --- a/reactos/dll/3rdparty/libjpeg/jdmaster.c +++ b/reactos/dll/3rdparty/libjpeg/jdmaster.c @@ -2,6 +2,7 @@ * jdmaster.c * * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 2002-2009 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -61,9 +62,12 @@ use_merged_upsample (j_decompress_ptr cinfo) cinfo->comp_info[2].v_samp_factor != 1) return FALSE; /* furthermore, it doesn't work if we've scaled the IDCTs differently */ - if (cinfo->comp_info[0].DCT_scaled_size != cinfo->min_DCT_scaled_size || - cinfo->comp_info[1].DCT_scaled_size != cinfo->min_DCT_scaled_size || - cinfo->comp_info[2].DCT_scaled_size != cinfo->min_DCT_scaled_size) + if (cinfo->comp_info[0].DCT_h_scaled_size != cinfo->min_DCT_h_scaled_size || + cinfo->comp_info[1].DCT_h_scaled_size != cinfo->min_DCT_h_scaled_size || + cinfo->comp_info[2].DCT_h_scaled_size != cinfo->min_DCT_h_scaled_size || + cinfo->comp_info[0].DCT_v_scaled_size != cinfo->min_DCT_v_scaled_size || + cinfo->comp_info[1].DCT_v_scaled_size != cinfo->min_DCT_v_scaled_size || + cinfo->comp_info[2].DCT_v_scaled_size != cinfo->min_DCT_v_scaled_size) return FALSE; /* ??? also need to test for upsample-time rescaling, when & if supported */ return TRUE; /* by golly, it'll work... */ @@ -82,7 +86,9 @@ use_merged_upsample (j_decompress_ptr cinfo) GLOBAL(void) jpeg_calc_output_dimensions (j_decompress_ptr cinfo) -/* Do computations that are needed before master selection phase */ +/* Do computations that are needed before master selection phase. + * This function is used for full decompression. + */ { #ifdef IDCT_SCALING_SUPPORTED int ci; @@ -93,52 +99,38 @@ jpeg_calc_output_dimensions (j_decompress_ptr cinfo) if (cinfo->global_state != DSTATE_READY) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); + /* Compute core output image dimensions and DCT scaling choices. */ + jpeg_core_output_dimensions(cinfo); + #ifdef IDCT_SCALING_SUPPORTED - /* Compute actual output image dimensions and DCT scaling choices. */ - if (cinfo->scale_num * 8 <= cinfo->scale_denom) { - /* Provide 1/8 scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width, 8L); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height, 8L); - cinfo->min_DCT_scaled_size = 1; - } else if (cinfo->scale_num * 4 <= cinfo->scale_denom) { - /* Provide 1/4 scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width, 4L); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height, 4L); - cinfo->min_DCT_scaled_size = 2; - } else if (cinfo->scale_num * 2 <= cinfo->scale_denom) { - /* Provide 1/2 scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width, 2L); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height, 2L); - cinfo->min_DCT_scaled_size = 4; - } else { - /* Provide 1/1 scaling */ - cinfo->output_width = cinfo->image_width; - cinfo->output_height = cinfo->image_height; - cinfo->min_DCT_scaled_size = DCTSIZE; - } /* In selecting the actual DCT scaling for each component, we try to * scale up the chroma components via IDCT scaling rather than upsampling. * This saves time if the upsampler gets to use 1:1 scaling. - * Note this code assumes that the supported DCT scalings are powers of 2. + * Note this code adapts subsampling ratios which are powers of 2. */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { - int ssize = cinfo->min_DCT_scaled_size; - while (ssize < DCTSIZE && - (compptr->h_samp_factor * ssize * 2 <= - cinfo->max_h_samp_factor * cinfo->min_DCT_scaled_size) && - (compptr->v_samp_factor * ssize * 2 <= - cinfo->max_v_samp_factor * cinfo->min_DCT_scaled_size)) { + int ssize = 1; + while (cinfo->min_DCT_h_scaled_size * ssize <= + (cinfo->do_fancy_upsampling ? DCTSIZE : DCTSIZE / 2) && + (cinfo->max_h_samp_factor % (compptr->h_samp_factor * ssize * 2)) == 0) { ssize = ssize * 2; } - compptr->DCT_scaled_size = ssize; + compptr->DCT_h_scaled_size = cinfo->min_DCT_h_scaled_size * ssize; + ssize = 1; + while (cinfo->min_DCT_v_scaled_size * ssize <= + (cinfo->do_fancy_upsampling ? DCTSIZE : DCTSIZE / 2) && + (cinfo->max_v_samp_factor % (compptr->v_samp_factor * ssize * 2)) == 0) { + ssize = ssize * 2; + } + compptr->DCT_v_scaled_size = cinfo->min_DCT_v_scaled_size * ssize; + + /* We don't support IDCT ratios larger than 2. */ + if (compptr->DCT_h_scaled_size > compptr->DCT_v_scaled_size * 2) + compptr->DCT_h_scaled_size = compptr->DCT_v_scaled_size * 2; + else if (compptr->DCT_v_scaled_size > compptr->DCT_h_scaled_size * 2) + compptr->DCT_v_scaled_size = compptr->DCT_h_scaled_size * 2; } /* Recompute downsampled dimensions of components; @@ -149,23 +141,14 @@ jpeg_calc_output_dimensions (j_decompress_ptr cinfo) /* Size in samples, after IDCT scaling */ compptr->downsampled_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * - (long) (compptr->h_samp_factor * compptr->DCT_scaled_size), - (long) (cinfo->max_h_samp_factor * DCTSIZE)); + (long) (compptr->h_samp_factor * compptr->DCT_h_scaled_size), + (long) (cinfo->max_h_samp_factor * cinfo->block_size)); compptr->downsampled_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * - (long) (compptr->v_samp_factor * compptr->DCT_scaled_size), - (long) (cinfo->max_v_samp_factor * DCTSIZE)); + (long) (compptr->v_samp_factor * compptr->DCT_v_scaled_size), + (long) (cinfo->max_v_samp_factor * cinfo->block_size)); } -#else /* !IDCT_SCALING_SUPPORTED */ - - /* Hardwire it to "no scaling" */ - cinfo->output_width = cinfo->image_width; - cinfo->output_height = cinfo->image_height; - /* jdinput.c has already initialized DCT_scaled_size to DCTSIZE, - * and has computed unscaled downsampled_width and downsampled_height. - */ - #endif /* IDCT_SCALING_SUPPORTED */ /* Report number of components in selected colorspace. */ @@ -372,17 +355,10 @@ master_selection (j_decompress_ptr cinfo) /* Inverse DCT */ jinit_inverse_dct(cinfo); /* Entropy decoding: either Huffman or arithmetic coding. */ - if (cinfo->arith_code) { - ERREXIT(cinfo, JERR_ARITH_NOTIMPL); - } else { - if (cinfo->progressive_mode) { -#ifdef D_PROGRESSIVE_SUPPORTED - jinit_phuff_decoder(cinfo); -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } else - jinit_huff_decoder(cinfo); + if (cinfo->arith_code) + jinit_arith_decoder(cinfo); + else { + jinit_huff_decoder(cinfo); } /* Initialize principal buffer controllers. */ diff --git a/reactos/dll/3rdparty/libjpeg/jdphuff.c b/reactos/dll/3rdparty/libjpeg/jdphuff.c deleted file mode 100644 index 22678099451..00000000000 --- a/reactos/dll/3rdparty/libjpeg/jdphuff.c +++ /dev/null @@ -1,668 +0,0 @@ -/* - * jdphuff.c - * - * Copyright (C) 1995-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains Huffman entropy decoding routines for progressive JPEG. - * - * Much of the complexity here has to do with supporting input suspension. - * If the data source module demands suspension, we want to be able to back - * up to the start of the current MCU. To do this, we copy state variables - * into local working storage, and update them back to the permanent - * storage only upon successful completion of an MCU. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jdhuff.h" /* Declarations shared with jdhuff.c */ - - -#ifdef D_PROGRESSIVE_SUPPORTED - -/* - * Expanded entropy decoder object for progressive Huffman decoding. - * - * The savable_state subrecord contains fields that change within an MCU, - * but must not be updated permanently until we complete the MCU. - */ - -typedef struct { - unsigned int EOBRUN; /* remaining EOBs in EOBRUN */ - int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ -} savable_state; - -/* This macro is to work around compilers with missing or broken - * structure assignment. You'll need to fix this code if you have - * such a compiler and you change MAX_COMPS_IN_SCAN. - */ - -#ifndef NO_STRUCT_ASSIGN -#define ASSIGN_STATE(dest,src) ((dest) = (src)) -#else -#if MAX_COMPS_IN_SCAN == 4 -#define ASSIGN_STATE(dest,src) \ - ((dest).EOBRUN = (src).EOBRUN, \ - (dest).last_dc_val[0] = (src).last_dc_val[0], \ - (dest).last_dc_val[1] = (src).last_dc_val[1], \ - (dest).last_dc_val[2] = (src).last_dc_val[2], \ - (dest).last_dc_val[3] = (src).last_dc_val[3]) -#endif -#endif - - -typedef struct { - struct jpeg_entropy_decoder pub; /* public fields */ - - /* These fields are loaded into local variables at start of each MCU. - * In case of suspension, we exit WITHOUT updating them. - */ - bitread_perm_state bitstate; /* Bit buffer at start of MCU */ - savable_state saved; /* Other state at start of MCU */ - - /* These fields are NOT loaded into local working state. */ - unsigned int restarts_to_go; /* MCUs left in this restart interval */ - - /* Pointers to derived tables (these workspaces have image lifespan) */ - d_derived_tbl * derived_tbls[NUM_HUFF_TBLS]; - - d_derived_tbl * ac_derived_tbl; /* active table during an AC scan */ -} phuff_entropy_decoder; - -typedef phuff_entropy_decoder * phuff_entropy_ptr; - -/* Forward declarations */ -METHODDEF(boolean) decode_mcu_DC_first JPP((j_decompress_ptr cinfo, - JBLOCKROW *MCU_data)); -METHODDEF(boolean) decode_mcu_AC_first JPP((j_decompress_ptr cinfo, - JBLOCKROW *MCU_data)); -METHODDEF(boolean) decode_mcu_DC_refine JPP((j_decompress_ptr cinfo, - JBLOCKROW *MCU_data)); -METHODDEF(boolean) decode_mcu_AC_refine JPP((j_decompress_ptr cinfo, - JBLOCKROW *MCU_data)); - - -/* - * Initialize for a Huffman-compressed scan. - */ - -METHODDEF(void) -start_pass_phuff_decoder (j_decompress_ptr cinfo) -{ - phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; - boolean is_DC_band, bad; - int ci, coefi, tbl; - int *coef_bit_ptr; - jpeg_component_info * compptr; - - is_DC_band = (cinfo->Ss == 0); - - /* Validate scan parameters */ - bad = FALSE; - if (is_DC_band) { - if (cinfo->Se != 0) - bad = TRUE; - } else { - /* need not check Ss/Se < 0 since they came from unsigned bytes */ - if (cinfo->Ss > cinfo->Se || cinfo->Se >= DCTSIZE2) - bad = TRUE; - /* AC scans may have only one component */ - if (cinfo->comps_in_scan != 1) - bad = TRUE; - } - if (cinfo->Ah != 0) { - /* Successive approximation refinement scan: must have Al = Ah-1. */ - if (cinfo->Al != cinfo->Ah-1) - bad = TRUE; - } - if (cinfo->Al > 13) /* need not check for < 0 */ - bad = TRUE; - /* Arguably the maximum Al value should be less than 13 for 8-bit precision, - * but the spec doesn't say so, and we try to be liberal about what we - * accept. Note: large Al values could result in out-of-range DC - * coefficients during early scans, leading to bizarre displays due to - * overflows in the IDCT math. But we won't crash. - */ - if (bad) - ERREXIT4(cinfo, JERR_BAD_PROGRESSION, - cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); - /* Update progression status, and verify that scan order is legal. - * Note that inter-scan inconsistencies are treated as warnings - * not fatal errors ... not clear if this is right way to behave. - */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - int cindex = cinfo->cur_comp_info[ci]->component_index; - coef_bit_ptr = & cinfo->coef_bits[cindex][0]; - if (!is_DC_band && coef_bit_ptr[0] < 0) /* AC without prior DC scan */ - WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0); - for (coefi = cinfo->Ss; coefi <= cinfo->Se; coefi++) { - int expected = (coef_bit_ptr[coefi] < 0) ? 0 : coef_bit_ptr[coefi]; - if (cinfo->Ah != expected) - WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, coefi); - coef_bit_ptr[coefi] = cinfo->Al; - } - } - - /* Select MCU decoding routine */ - if (cinfo->Ah == 0) { - if (is_DC_band) - entropy->pub.decode_mcu = decode_mcu_DC_first; - else - entropy->pub.decode_mcu = decode_mcu_AC_first; - } else { - if (is_DC_band) - entropy->pub.decode_mcu = decode_mcu_DC_refine; - else - entropy->pub.decode_mcu = decode_mcu_AC_refine; - } - - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - /* Make sure requested tables are present, and compute derived tables. - * We may build same derived table more than once, but it's not expensive. - */ - if (is_DC_band) { - if (cinfo->Ah == 0) { /* DC refinement needs no table */ - tbl = compptr->dc_tbl_no; - jpeg_make_d_derived_tbl(cinfo, TRUE, tbl, - & entropy->derived_tbls[tbl]); - } - } else { - tbl = compptr->ac_tbl_no; - jpeg_make_d_derived_tbl(cinfo, FALSE, tbl, - & entropy->derived_tbls[tbl]); - /* remember the single active table */ - entropy->ac_derived_tbl = entropy->derived_tbls[tbl]; - } - /* Initialize DC predictions to 0 */ - entropy->saved.last_dc_val[ci] = 0; - } - - /* Initialize bitread state variables */ - entropy->bitstate.bits_left = 0; - entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */ - entropy->pub.insufficient_data = FALSE; - - /* Initialize private state variables */ - entropy->saved.EOBRUN = 0; - - /* Initialize restart counter */ - entropy->restarts_to_go = cinfo->restart_interval; -} - - -/* - * Figure F.12: extend sign bit. - * On some machines, a shift and add will be faster than a table lookup. - */ - -#ifdef AVOID_TABLES - -#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x)) - -#else - -#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x)) - -static const int extend_test[16] = /* entry n is 2**(n-1) */ - { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, - 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 }; - -static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */ - { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1, - ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1, - ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, - ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 }; - -#endif /* AVOID_TABLES */ - - -/* - * Check for a restart marker & resynchronize decoder. - * Returns FALSE if must suspend. - */ - -LOCAL(boolean) -process_restart (j_decompress_ptr cinfo) -{ - phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; - int ci; - - /* Throw away any unused bits remaining in bit buffer; */ - /* include any full bytes in next_marker's count of discarded bytes */ - cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8; - entropy->bitstate.bits_left = 0; - - /* Advance past the RSTn marker */ - if (! (*cinfo->marker->read_restart_marker) (cinfo)) - return FALSE; - - /* Re-initialize DC predictions to 0 */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) - entropy->saved.last_dc_val[ci] = 0; - /* Re-init EOB run count, too */ - entropy->saved.EOBRUN = 0; - - /* Reset restart counter */ - entropy->restarts_to_go = cinfo->restart_interval; - - /* Reset out-of-data flag, unless read_restart_marker left us smack up - * against a marker. In that case we will end up treating the next data - * segment as empty, and we can avoid producing bogus output pixels by - * leaving the flag set. - */ - if (cinfo->unread_marker == 0) - entropy->pub.insufficient_data = FALSE; - - return TRUE; -} - - -/* - * Huffman MCU decoding. - * Each of these routines decodes and returns one MCU's worth of - * Huffman-compressed coefficients. - * The coefficients are reordered from zigzag order into natural array order, - * but are not dequantized. - * - * The i'th block of the MCU is stored into the block pointed to by - * MCU_data[i]. WE ASSUME THIS AREA IS INITIALLY ZEROED BY THE CALLER. - * - * We return FALSE if data source requested suspension. In that case no - * changes have been made to permanent state. (Exception: some output - * coefficients may already have been assigned. This is harmless for - * spectral selection, since we'll just re-assign them on the next call. - * Successive approximation AC refinement has to be more careful, however.) - */ - -/* - * MCU decoding for DC initial scan (either spectral selection, - * or first pass of successive approximation). - */ - -METHODDEF(boolean) -decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) -{ - phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; - int Al = cinfo->Al; - register int s, r; - int blkn, ci; - JBLOCKROW block; - BITREAD_STATE_VARS; - savable_state state; - d_derived_tbl * tbl; - jpeg_component_info * compptr; - - /* Process restart marker if needed; may have to suspend */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) - if (! process_restart(cinfo)) - return FALSE; - } - - /* If we've run out of data, just leave the MCU set to zeroes. - * This way, we return uniform gray for the remainder of the segment. - */ - if (! entropy->pub.insufficient_data) { - - /* Load up working state */ - BITREAD_LOAD_STATE(cinfo,entropy->bitstate); - ASSIGN_STATE(state, entropy->saved); - - /* Outer loop handles each block in the MCU */ - - for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - block = MCU_data[blkn]; - ci = cinfo->MCU_membership[blkn]; - compptr = cinfo->cur_comp_info[ci]; - tbl = entropy->derived_tbls[compptr->dc_tbl_no]; - - /* Decode a single block's worth of coefficients */ - - /* Section F.2.2.1: decode the DC coefficient difference */ - HUFF_DECODE(s, br_state, tbl, return FALSE, label1); - if (s) { - CHECK_BIT_BUFFER(br_state, s, return FALSE); - r = GET_BITS(s); - s = HUFF_EXTEND(r, s); - } - - /* Convert DC difference to actual value, update last_dc_val */ - s += state.last_dc_val[ci]; - state.last_dc_val[ci] = s; - /* Scale and output the coefficient (assumes jpeg_natural_order[0]=0) */ - (*block)[0] = (JCOEF) (s << Al); - } - - /* Completed MCU, so update state */ - BITREAD_SAVE_STATE(cinfo,entropy->bitstate); - ASSIGN_STATE(entropy->saved, state); - } - - /* Account for restart interval (no-op if not using restarts) */ - entropy->restarts_to_go--; - - return TRUE; -} - - -/* - * MCU decoding for AC initial scan (either spectral selection, - * or first pass of successive approximation). - */ - -METHODDEF(boolean) -decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) -{ - phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; - int Se = cinfo->Se; - int Al = cinfo->Al; - register int s, k, r; - unsigned int EOBRUN; - JBLOCKROW block; - BITREAD_STATE_VARS; - d_derived_tbl * tbl; - - /* Process restart marker if needed; may have to suspend */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) - if (! process_restart(cinfo)) - return FALSE; - } - - /* If we've run out of data, just leave the MCU set to zeroes. - * This way, we return uniform gray for the remainder of the segment. - */ - if (! entropy->pub.insufficient_data) { - - /* Load up working state. - * We can avoid loading/saving bitread state if in an EOB run. - */ - EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */ - - /* There is always only one block per MCU */ - - if (EOBRUN > 0) /* if it's a band of zeroes... */ - EOBRUN--; /* ...process it now (we do nothing) */ - else { - BITREAD_LOAD_STATE(cinfo,entropy->bitstate); - block = MCU_data[0]; - tbl = entropy->ac_derived_tbl; - - for (k = cinfo->Ss; k <= Se; k++) { - HUFF_DECODE(s, br_state, tbl, return FALSE, label2); - r = s >> 4; - s &= 15; - if (s) { - k += r; - CHECK_BIT_BUFFER(br_state, s, return FALSE); - r = GET_BITS(s); - s = HUFF_EXTEND(r, s); - /* Scale and output coefficient in natural (dezigzagged) order */ - (*block)[jpeg_natural_order[k]] = (JCOEF) (s << Al); - } else { - if (r == 15) { /* ZRL */ - k += 15; /* skip 15 zeroes in band */ - } else { /* EOBr, run length is 2^r + appended bits */ - EOBRUN = 1 << r; - if (r) { /* EOBr, r > 0 */ - CHECK_BIT_BUFFER(br_state, r, return FALSE); - r = GET_BITS(r); - EOBRUN += r; - } - EOBRUN--; /* this band is processed at this moment */ - break; /* force end-of-band */ - } - } - } - - BITREAD_SAVE_STATE(cinfo,entropy->bitstate); - } - - /* Completed MCU, so update state */ - entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */ - } - - /* Account for restart interval (no-op if not using restarts) */ - entropy->restarts_to_go--; - - return TRUE; -} - - -/* - * MCU decoding for DC successive approximation refinement scan. - * Note: we assume such scans can be multi-component, although the spec - * is not very clear on the point. - */ - -METHODDEF(boolean) -decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) -{ - phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; - int p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ - int blkn; - JBLOCKROW block; - BITREAD_STATE_VARS; - - /* Process restart marker if needed; may have to suspend */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) - if (! process_restart(cinfo)) - return FALSE; - } - - /* Not worth the cycles to check insufficient_data here, - * since we will not change the data anyway if we read zeroes. - */ - - /* Load up working state */ - BITREAD_LOAD_STATE(cinfo,entropy->bitstate); - - /* Outer loop handles each block in the MCU */ - - for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - block = MCU_data[blkn]; - - /* Encoded data is simply the next bit of the two's-complement DC value */ - CHECK_BIT_BUFFER(br_state, 1, return FALSE); - if (GET_BITS(1)) - (*block)[0] |= p1; - /* Note: since we use |=, repeating the assignment later is safe */ - } - - /* Completed MCU, so update state */ - BITREAD_SAVE_STATE(cinfo,entropy->bitstate); - - /* Account for restart interval (no-op if not using restarts) */ - entropy->restarts_to_go--; - - return TRUE; -} - - -/* - * MCU decoding for AC successive approximation refinement scan. - */ - -METHODDEF(boolean) -decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) -{ - phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; - int Se = cinfo->Se; - int p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ - int m1 = (-1) << cinfo->Al; /* -1 in the bit position being coded */ - register int s, k, r; - unsigned int EOBRUN; - JBLOCKROW block; - JCOEFPTR thiscoef; - BITREAD_STATE_VARS; - d_derived_tbl * tbl; - int num_newnz; - int newnz_pos[DCTSIZE2]; - - /* Process restart marker if needed; may have to suspend */ - if (cinfo->restart_interval) { - if (entropy->restarts_to_go == 0) - if (! process_restart(cinfo)) - return FALSE; - } - - /* If we've run out of data, don't modify the MCU. - */ - if (! entropy->pub.insufficient_data) { - - /* Load up working state */ - BITREAD_LOAD_STATE(cinfo,entropy->bitstate); - EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */ - - /* There is always only one block per MCU */ - block = MCU_data[0]; - tbl = entropy->ac_derived_tbl; - - /* If we are forced to suspend, we must undo the assignments to any newly - * nonzero coefficients in the block, because otherwise we'd get confused - * next time about which coefficients were already nonzero. - * But we need not undo addition of bits to already-nonzero coefficients; - * instead, we can test the current bit to see if we already did it. - */ - num_newnz = 0; - - /* initialize coefficient loop counter to start of band */ - k = cinfo->Ss; - - if (EOBRUN == 0) { - for (; k <= Se; k++) { - HUFF_DECODE(s, br_state, tbl, goto undoit, label3); - r = s >> 4; - s &= 15; - if (s) { - if (s != 1) /* size of new coef should always be 1 */ - WARNMS(cinfo, JWRN_HUFF_BAD_CODE); - CHECK_BIT_BUFFER(br_state, 1, goto undoit); - if (GET_BITS(1)) - s = p1; /* newly nonzero coef is positive */ - else - s = m1; /* newly nonzero coef is negative */ - } else { - if (r != 15) { - EOBRUN = 1 << r; /* EOBr, run length is 2^r + appended bits */ - if (r) { - CHECK_BIT_BUFFER(br_state, r, goto undoit); - r = GET_BITS(r); - EOBRUN += r; - } - break; /* rest of block is handled by EOB logic */ - } - /* note s = 0 for processing ZRL */ - } - /* Advance over already-nonzero coefs and r still-zero coefs, - * appending correction bits to the nonzeroes. A correction bit is 1 - * if the absolute value of the coefficient must be increased. - */ - do { - thiscoef = *block + jpeg_natural_order[k]; - if (*thiscoef != 0) { - CHECK_BIT_BUFFER(br_state, 1, goto undoit); - if (GET_BITS(1)) { - if ((*thiscoef & p1) == 0) { /* do nothing if already set it */ - if (*thiscoef >= 0) - *thiscoef += p1; - else - *thiscoef += m1; - } - } - } else { - if (--r < 0) - break; /* reached target zero coefficient */ - } - k++; - } while (k <= Se); - if (s) { - int pos = jpeg_natural_order[k]; - /* Output newly nonzero coefficient */ - (*block)[pos] = (JCOEF) s; - /* Remember its position in case we have to suspend */ - newnz_pos[num_newnz++] = pos; - } - } - } - - if (EOBRUN > 0) { - /* Scan any remaining coefficient positions after the end-of-band - * (the last newly nonzero coefficient, if any). Append a correction - * bit to each already-nonzero coefficient. A correction bit is 1 - * if the absolute value of the coefficient must be increased. - */ - for (; k <= Se; k++) { - thiscoef = *block + jpeg_natural_order[k]; - if (*thiscoef != 0) { - CHECK_BIT_BUFFER(br_state, 1, goto undoit); - if (GET_BITS(1)) { - if ((*thiscoef & p1) == 0) { /* do nothing if already changed it */ - if (*thiscoef >= 0) - *thiscoef += p1; - else - *thiscoef += m1; - } - } - } - } - /* Count one block completed in EOB run */ - EOBRUN--; - } - - /* Completed MCU, so update state */ - BITREAD_SAVE_STATE(cinfo,entropy->bitstate); - entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */ - } - - /* Account for restart interval (no-op if not using restarts) */ - entropy->restarts_to_go--; - - return TRUE; - -undoit: - /* Re-zero any output coefficients that we made newly nonzero */ - while (num_newnz > 0) - (*block)[newnz_pos[--num_newnz]] = 0; - - return FALSE; -} - - -/* - * Module initialization routine for progressive Huffman entropy decoding. - */ - -GLOBAL(void) -jinit_phuff_decoder (j_decompress_ptr cinfo) -{ - phuff_entropy_ptr entropy; - int *coef_bit_ptr; - int ci, i; - - entropy = (phuff_entropy_ptr) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(phuff_entropy_decoder)); - cinfo->entropy = (struct jpeg_entropy_decoder *) entropy; - entropy->pub.start_pass = start_pass_phuff_decoder; - - /* Mark derived tables unallocated */ - for (i = 0; i < NUM_HUFF_TBLS; i++) { - entropy->derived_tbls[i] = NULL; - } - - /* Create progression status table */ - cinfo->coef_bits = (int (*)[DCTSIZE2]) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - cinfo->num_components*DCTSIZE2*SIZEOF(int)); - coef_bit_ptr = & cinfo->coef_bits[0][0]; - for (ci = 0; ci < cinfo->num_components; ci++) - for (i = 0; i < DCTSIZE2; i++) - *coef_bit_ptr++ = -1; -} - -#endif /* D_PROGRESSIVE_SUPPORTED */ diff --git a/reactos/dll/3rdparty/libjpeg/jdsample.c b/reactos/dll/3rdparty/libjpeg/jdsample.c index 80ffefb2a1c..7bc8885b02e 100644 --- a/reactos/dll/3rdparty/libjpeg/jdsample.c +++ b/reactos/dll/3rdparty/libjpeg/jdsample.c @@ -2,13 +2,14 @@ * jdsample.c * * Copyright (C) 1991-1996, Thomas G. Lane. + * Modified 2002-2008 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains upsampling routines. * * Upsampling input data is counted in "row groups". A row group - * is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size) + * is defined to be (v_samp_factor * DCT_v_scaled_size / min_DCT_v_scaled_size) * sample rows of each component. Upsampling will normally produce * max_v_samp_factor pixel rows from each row group (but this could vary * if the upsampler is applying a scale factor of its own). @@ -237,11 +238,11 @@ h2v1_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, register JSAMPROW inptr, outptr; register JSAMPLE invalue; JSAMPROW outend; - int inrow; + int outrow; - for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { - inptr = input_data[inrow]; - outptr = output_data[inrow]; + for (outrow = 0; outrow < cinfo->max_v_samp_factor; outrow++) { + inptr = input_data[outrow]; + outptr = output_data[outrow]; outend = outptr + cinfo->output_width; while (outptr < outend) { invalue = *inptr++; /* don't need GETJSAMPLE() here */ @@ -285,112 +286,6 @@ h2v2_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, } -/* - * Fancy processing for the common case of 2:1 horizontal and 1:1 vertical. - * - * The upsampling algorithm is linear interpolation between pixel centers, - * also known as a "triangle filter". This is a good compromise between - * speed and visual quality. The centers of the output pixels are 1/4 and 3/4 - * of the way between input pixel centers. - * - * A note about the "bias" calculations: when rounding fractional values to - * integer, we do not want to always round 0.5 up to the next integer. - * If we did that, we'd introduce a noticeable bias towards larger values. - * Instead, this code is arranged so that 0.5 will be rounded up or down at - * alternate pixel locations (a simple ordered dither pattern). - */ - -METHODDEF(void) -h2v1_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) -{ - JSAMPARRAY output_data = *output_data_ptr; - register JSAMPROW inptr, outptr; - register int invalue; - register JDIMENSION colctr; - int inrow; - - for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { - inptr = input_data[inrow]; - outptr = output_data[inrow]; - /* Special case for first column */ - invalue = GETJSAMPLE(*inptr++); - *outptr++ = (JSAMPLE) invalue; - *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(*inptr) + 2) >> 2); - - for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) { - /* General case: 3/4 * nearer pixel + 1/4 * further pixel */ - invalue = GETJSAMPLE(*inptr++) * 3; - *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(inptr[-2]) + 1) >> 2); - *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(*inptr) + 2) >> 2); - } - - /* Special case for last column */ - invalue = GETJSAMPLE(*inptr); - *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(inptr[-1]) + 1) >> 2); - *outptr++ = (JSAMPLE) invalue; - } -} - - -/* - * Fancy processing for the common case of 2:1 horizontal and 2:1 vertical. - * Again a triangle filter; see comments for h2v1 case, above. - * - * It is OK for us to reference the adjacent input rows because we demanded - * context from the main buffer controller (see initialization code). - */ - -METHODDEF(void) -h2v2_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) -{ - JSAMPARRAY output_data = *output_data_ptr; - register JSAMPROW inptr0, inptr1, outptr; -#if BITS_IN_JSAMPLE == 8 - register int thiscolsum, lastcolsum, nextcolsum; -#else - register INT32 thiscolsum, lastcolsum, nextcolsum; -#endif - register JDIMENSION colctr; - int inrow, outrow, v; - - inrow = outrow = 0; - while (outrow < cinfo->max_v_samp_factor) { - for (v = 0; v < 2; v++) { - /* inptr0 points to nearest input row, inptr1 points to next nearest */ - inptr0 = input_data[inrow]; - if (v == 0) /* next nearest is row above */ - inptr1 = input_data[inrow-1]; - else /* next nearest is row below */ - inptr1 = input_data[inrow+1]; - outptr = output_data[outrow++]; - - /* Special case for first column */ - thiscolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); - nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); - *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 8) >> 4); - *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4); - lastcolsum = thiscolsum; thiscolsum = nextcolsum; - - for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) { - /* General case: 3/4 * nearer pixel + 1/4 * further pixel in each */ - /* dimension, thus 9/16, 3/16, 3/16, 1/16 overall */ - nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); - *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4); - *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4); - lastcolsum = thiscolsum; thiscolsum = nextcolsum; - } - - /* Special case for last column */ - *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4); - *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 7) >> 4); - } - inrow++; - } -} - - /* * Module initialization routine for upsampling. */ @@ -401,7 +296,7 @@ jinit_upsampler (j_decompress_ptr cinfo) my_upsample_ptr upsample; int ci; jpeg_component_info * compptr; - boolean need_buffer, do_fancy; + boolean need_buffer; int h_in_group, v_in_group, h_out_group, v_out_group; upsample = (my_upsample_ptr) @@ -415,11 +310,6 @@ jinit_upsampler (j_decompress_ptr cinfo) if (cinfo->CCIR601_sampling) /* this isn't supported */ ERREXIT(cinfo, JERR_CCIR601_NOTIMPL); - /* jdmainct.c doesn't support context rows when min_DCT_scaled_size = 1, - * so don't ask for it. - */ - do_fancy = cinfo->do_fancy_upsampling && cinfo->min_DCT_scaled_size > 1; - /* Verify we can handle the sampling factors, select per-component methods, * and create storage as needed. */ @@ -428,10 +318,10 @@ jinit_upsampler (j_decompress_ptr cinfo) /* Compute size of an "input group" after IDCT scaling. This many samples * are to be converted to max_h_samp_factor * max_v_samp_factor pixels. */ - h_in_group = (compptr->h_samp_factor * compptr->DCT_scaled_size) / - cinfo->min_DCT_scaled_size; - v_in_group = (compptr->v_samp_factor * compptr->DCT_scaled_size) / - cinfo->min_DCT_scaled_size; + h_in_group = (compptr->h_samp_factor * compptr->DCT_h_scaled_size) / + cinfo->min_DCT_h_scaled_size; + v_in_group = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) / + cinfo->min_DCT_v_scaled_size; h_out_group = cinfo->max_h_samp_factor; v_out_group = cinfo->max_v_samp_factor; upsample->rowgroup_height[ci] = v_in_group; /* save for use later */ @@ -446,19 +336,12 @@ jinit_upsampler (j_decompress_ptr cinfo) need_buffer = FALSE; } else if (h_in_group * 2 == h_out_group && v_in_group == v_out_group) { - /* Special cases for 2h1v upsampling */ - if (do_fancy && compptr->downsampled_width > 2) - upsample->methods[ci] = h2v1_fancy_upsample; - else - upsample->methods[ci] = h2v1_upsample; + /* Special case for 2h1v upsampling */ + upsample->methods[ci] = h2v1_upsample; } else if (h_in_group * 2 == h_out_group && v_in_group * 2 == v_out_group) { - /* Special cases for 2h2v upsampling */ - if (do_fancy && compptr->downsampled_width > 2) { - upsample->methods[ci] = h2v2_fancy_upsample; - upsample->pub.need_context_rows = TRUE; - } else - upsample->methods[ci] = h2v2_upsample; + /* Special case for 2h2v upsampling */ + upsample->methods[ci] = h2v2_upsample; } else if ((h_out_group % h_in_group) == 0 && (v_out_group % v_in_group) == 0) { /* Generic integral-factors upsampling method */ diff --git a/reactos/dll/3rdparty/libjpeg/jdtrans.c b/reactos/dll/3rdparty/libjpeg/jdtrans.c index 6c0ab715d32..22dd47fb5c5 100644 --- a/reactos/dll/3rdparty/libjpeg/jdtrans.c +++ b/reactos/dll/3rdparty/libjpeg/jdtrans.c @@ -2,6 +2,7 @@ * jdtrans.c * * Copyright (C) 1995-1997, Thomas G. Lane. + * Modified 2000-2009 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -99,18 +100,14 @@ transdecode_master_selection (j_decompress_ptr cinfo) /* This is effectively a buffered-image operation. */ cinfo->buffered_image = TRUE; + /* Compute output image dimensions and related values. */ + jpeg_core_output_dimensions(cinfo); + /* Entropy decoding: either Huffman or arithmetic coding. */ - if (cinfo->arith_code) { - ERREXIT(cinfo, JERR_ARITH_NOTIMPL); - } else { - if (cinfo->progressive_mode) { -#ifdef D_PROGRESSIVE_SUPPORTED - jinit_phuff_decoder(cinfo); -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } else - jinit_huff_decoder(cinfo); + if (cinfo->arith_code) + jinit_arith_decoder(cinfo); + else { + jinit_huff_decoder(cinfo); } /* Always get a full-image coefficient buffer. */ diff --git a/reactos/dll/3rdparty/libjpeg/jerror.h b/reactos/dll/3rdparty/libjpeg/jerror.h index fcdf6a83d46..1cfb2b19d85 100644 --- a/reactos/dll/3rdparty/libjpeg/jerror.h +++ b/reactos/dll/3rdparty/libjpeg/jerror.h @@ -2,6 +2,7 @@ * jerror.h * * Copyright (C) 1994-1997, Thomas G. Lane. + * Modified 1997-2009 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -39,17 +40,15 @@ typedef enum { JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */ /* For maintenance convenience, list is alphabetical by message code name */ -JMESSAGE(JERR_ARITH_NOTIMPL, - "Sorry, there are legal restrictions on arithmetic coding") JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix") JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix") JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode") JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS") JMESSAGE(JERR_BAD_CROP_SPEC, "Invalid crop request") JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range") -JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported") +JMESSAGE(JERR_BAD_DCTSIZE, "DCT scaled block size %dx%d not supported") JMESSAGE(JERR_BAD_DROP_SAMPLING, - "Component index %d: mismatching sampling ratio %d:%d, %d:%d, %c") + "Component index %d: mismatching sampling ratio %d:%d, %d:%d, %c") JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition") JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace") JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace") @@ -96,6 +95,7 @@ JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data") JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change") JMESSAGE(JERR_NOTIMPL, "Not implemented yet") JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time") +JMESSAGE(JERR_NO_ARITH_TABLE, "Arithmetic table 0x%02x was not defined") JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported") JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined") JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image") @@ -173,6 +173,7 @@ JMESSAGE(JTRC_UNKNOWN_IDS, JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u") JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u") JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d") +JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code") JMESSAGE(JWRN_BOGUS_PROGRESSION, "Inconsistent progression sequence for component %d coefficient %d") JMESSAGE(JWRN_EXTRANEOUS_DATA, diff --git a/reactos/dll/3rdparty/libjpeg/jfdctflt.c b/reactos/dll/3rdparty/libjpeg/jfdctflt.c index 79d7a007874..74d0d862dcb 100644 --- a/reactos/dll/3rdparty/libjpeg/jfdctflt.c +++ b/reactos/dll/3rdparty/libjpeg/jfdctflt.c @@ -2,6 +2,7 @@ * jfdctflt.c * * Copyright (C) 1994-1996, Thomas G. Lane. + * Modified 2003-2009 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -56,41 +57,46 @@ */ GLOBAL(void) -jpeg_fdct_float (FAST_FLOAT * data) +jpeg_fdct_float (FAST_FLOAT * data, JSAMPARRAY sample_data, JDIMENSION start_col) { FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; FAST_FLOAT tmp10, tmp11, tmp12, tmp13; FAST_FLOAT z1, z2, z3, z4, z5, z11, z13; FAST_FLOAT *dataptr; + JSAMPROW elemptr; int ctr; /* Pass 1: process rows. */ dataptr = data; - for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { - tmp0 = dataptr[0] + dataptr[7]; - tmp7 = dataptr[0] - dataptr[7]; - tmp1 = dataptr[1] + dataptr[6]; - tmp6 = dataptr[1] - dataptr[6]; - tmp2 = dataptr[2] + dataptr[5]; - tmp5 = dataptr[2] - dataptr[5]; - tmp3 = dataptr[3] + dataptr[4]; - tmp4 = dataptr[3] - dataptr[4]; - + for (ctr = 0; ctr < DCTSIZE; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Load data into workspace */ + tmp0 = (FAST_FLOAT) (GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[7])); + tmp7 = (FAST_FLOAT) (GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[7])); + tmp1 = (FAST_FLOAT) (GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[6])); + tmp6 = (FAST_FLOAT) (GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[6])); + tmp2 = (FAST_FLOAT) (GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[5])); + tmp5 = (FAST_FLOAT) (GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[5])); + tmp3 = (FAST_FLOAT) (GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[4])); + tmp4 = (FAST_FLOAT) (GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[4])); + /* Even part */ - + tmp10 = tmp0 + tmp3; /* phase 2 */ tmp13 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; - - dataptr[0] = tmp10 + tmp11; /* phase 3 */ + + /* Apply unsigned->signed conversion */ + dataptr[0] = tmp10 + tmp11 - 8 * CENTERJSAMPLE; /* phase 3 */ dataptr[4] = tmp10 - tmp11; - + z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */ dataptr[2] = tmp13 + z1; /* phase 5 */ dataptr[6] = tmp13 - z1; - + /* Odd part */ tmp10 = tmp4 + tmp5; /* phase 2 */ @@ -126,21 +132,21 @@ jpeg_fdct_float (FAST_FLOAT * data) tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; - + /* Even part */ - + tmp10 = tmp0 + tmp3; /* phase 2 */ tmp13 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; - + dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */ dataptr[DCTSIZE*4] = tmp10 - tmp11; - + z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */ dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */ dataptr[DCTSIZE*6] = tmp13 - z1; - + /* Odd part */ tmp10 = tmp4 + tmp5; /* phase 2 */ diff --git a/reactos/dll/3rdparty/libjpeg/jfdctfst.c b/reactos/dll/3rdparty/libjpeg/jfdctfst.c index ccb378a3b45..8cad5f22939 100644 --- a/reactos/dll/3rdparty/libjpeg/jfdctfst.c +++ b/reactos/dll/3rdparty/libjpeg/jfdctfst.c @@ -2,6 +2,7 @@ * jfdctfst.c * * Copyright (C) 1994-1996, Thomas G. Lane. + * Modified 2003-2009 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -111,42 +112,47 @@ */ GLOBAL(void) -jpeg_fdct_ifast (DCTELEM * data) +jpeg_fdct_ifast (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) { DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; DCTELEM tmp10, tmp11, tmp12, tmp13; DCTELEM z1, z2, z3, z4, z5, z11, z13; DCTELEM *dataptr; + JSAMPROW elemptr; int ctr; SHIFT_TEMPS /* Pass 1: process rows. */ dataptr = data; - for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { - tmp0 = dataptr[0] + dataptr[7]; - tmp7 = dataptr[0] - dataptr[7]; - tmp1 = dataptr[1] + dataptr[6]; - tmp6 = dataptr[1] - dataptr[6]; - tmp2 = dataptr[2] + dataptr[5]; - tmp5 = dataptr[2] - dataptr[5]; - tmp3 = dataptr[3] + dataptr[4]; - tmp4 = dataptr[3] - dataptr[4]; - + for (ctr = 0; ctr < DCTSIZE; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Load data into workspace */ + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[7]); + tmp7 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[7]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[6]); + tmp6 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[6]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[5]); + tmp5 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[5]); + tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[4]); + tmp4 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[4]); + /* Even part */ - + tmp10 = tmp0 + tmp3; /* phase 2 */ tmp13 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; - - dataptr[0] = tmp10 + tmp11; /* phase 3 */ + + /* Apply unsigned->signed conversion */ + dataptr[0] = tmp10 + tmp11 - 8 * CENTERJSAMPLE; /* phase 3 */ dataptr[4] = tmp10 - tmp11; - + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */ dataptr[2] = tmp13 + z1; /* phase 5 */ dataptr[6] = tmp13 - z1; - + /* Odd part */ tmp10 = tmp4 + tmp5; /* phase 2 */ @@ -182,21 +188,21 @@ jpeg_fdct_ifast (DCTELEM * data) tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; - + /* Even part */ - + tmp10 = tmp0 + tmp3; /* phase 2 */ tmp13 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; - + dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */ dataptr[DCTSIZE*4] = tmp10 - tmp11; - + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */ dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */ dataptr[DCTSIZE*6] = tmp13 - z1; - + /* Odd part */ tmp10 = tmp4 + tmp5; /* phase 2 */ diff --git a/reactos/dll/3rdparty/libjpeg/jfdctint.c b/reactos/dll/3rdparty/libjpeg/jfdctint.c index 0a78b64aee8..1dde58c499d 100644 --- a/reactos/dll/3rdparty/libjpeg/jfdctint.c +++ b/reactos/dll/3rdparty/libjpeg/jfdctint.c @@ -2,6 +2,7 @@ * jfdctint.c * * Copyright (C) 1991-1996, Thomas G. Lane. + * Modification developed 2003-2009 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -21,6 +22,23 @@ * The advantage of this method is that no data path contains more than one * multiplication; this allows a very simple and accurate implementation in * scaled fixed-point arithmetic, with a minimal number of shifts. + * + * We also provide FDCT routines with various input sample block sizes for + * direct resolution reduction or enlargement and for direct resolving the + * common 2x1 and 1x2 subsampling cases without additional resampling: NxN + * (N=1...16), 2NxN, and Nx2N (N=1...8) pixels for one 8x8 output DCT block. + * + * For N<8 we fill the remaining block coefficients with zero. + * For N>8 we apply a partial N-point FDCT on the input samples, computing + * just the lower 8 frequency coefficients and discarding the rest. + * + * We must scale the output coefficients of the N-point FDCT appropriately + * to the standard 8-point FDCT level by 8/N per 1-D pass. This scaling + * is folded into the constant multipliers (pass 2) and/or final/initial + * shifting. + * + * CAUTION: We rely on the FIX() macro except for the N=1,2,4,8 cases + * since there would be too many additional constants to pre-calculate. */ #define JPEG_INTERNALS @@ -36,7 +54,7 @@ */ #if DCTSIZE != 8 - Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ + Sorry, this code only copes with 8x8 DCT blocks. /* deliberate syntax err */ #endif @@ -137,12 +155,13 @@ */ GLOBAL(void) -jpeg_fdct_islow (DCTELEM * data) +jpeg_fdct_islow (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) { - INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + INT32 tmp0, tmp1, tmp2, tmp3; INT32 tmp10, tmp11, tmp12, tmp13; - INT32 z1, z2, z3, z4, z5; + INT32 z1; DCTELEM *dataptr; + JSAMPROW elemptr; int ctr; SHIFT_TEMPS @@ -151,62 +170,74 @@ jpeg_fdct_islow (DCTELEM * data) /* furthermore, we scale the results by 2**PASS1_BITS. */ dataptr = data; - for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { - tmp0 = dataptr[0] + dataptr[7]; - tmp7 = dataptr[0] - dataptr[7]; - tmp1 = dataptr[1] + dataptr[6]; - tmp6 = dataptr[1] - dataptr[6]; - tmp2 = dataptr[2] + dataptr[5]; - tmp5 = dataptr[2] - dataptr[5]; - tmp3 = dataptr[3] + dataptr[4]; - tmp4 = dataptr[3] - dataptr[4]; - + for (ctr = 0; ctr < DCTSIZE; ctr++) { + elemptr = sample_data[ctr] + start_col; + /* Even part per LL&M figure 1 --- note that published figure is faulty; * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". */ - + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[7]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[6]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[5]); + tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[4]); + tmp10 = tmp0 + tmp3; - tmp13 = tmp0 - tmp3; + tmp12 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; - tmp12 = tmp1 - tmp2; - - dataptr[0] = (DCTELEM) ((tmp10 + tmp11) << PASS1_BITS); + tmp13 = tmp1 - tmp2; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[7]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[6]); + tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[5]); + tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[4]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) ((tmp10 + tmp11 - 8 * CENTERJSAMPLE) << PASS1_BITS); dataptr[4] = (DCTELEM) ((tmp10 - tmp11) << PASS1_BITS); - + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); - dataptr[2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865), - CONST_BITS-PASS1_BITS); - dataptr[6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065), - CONST_BITS-PASS1_BITS); - + /* Add fudge factor here for final descale. */ + z1 += ONE << (CONST_BITS-PASS1_BITS-1); + dataptr[2] = (DCTELEM) RIGHT_SHIFT(z1 + MULTIPLY(tmp12, FIX_0_765366865), + CONST_BITS-PASS1_BITS); + dataptr[6] = (DCTELEM) RIGHT_SHIFT(z1 - MULTIPLY(tmp13, FIX_1_847759065), + CONST_BITS-PASS1_BITS); + /* Odd part per figure 8 --- note paper omits factor of sqrt(2). - * cK represents cos(K*pi/16). - * i0..i3 in the paper are tmp4..tmp7 here. + * cK represents sqrt(2) * cos(K*pi/16). + * i0..i3 in the paper are tmp0..tmp3 here. */ - - z1 = tmp4 + tmp7; - z2 = tmp5 + tmp6; - z3 = tmp4 + tmp6; - z4 = tmp5 + tmp7; - z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ - - tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ - tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ - tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ - tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ - z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ - z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ - z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ - z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ - - z3 += z5; - z4 += z5; - - dataptr[7] = (DCTELEM) DESCALE(tmp4 + z1 + z3, CONST_BITS-PASS1_BITS); - dataptr[5] = (DCTELEM) DESCALE(tmp5 + z2 + z4, CONST_BITS-PASS1_BITS); - dataptr[3] = (DCTELEM) DESCALE(tmp6 + z2 + z3, CONST_BITS-PASS1_BITS); - dataptr[1] = (DCTELEM) DESCALE(tmp7 + z1 + z4, CONST_BITS-PASS1_BITS); - + + tmp10 = tmp0 + tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp0 + tmp2; + tmp13 = tmp1 + tmp3; + z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */ + /* Add fudge factor here for final descale. */ + z1 += ONE << (CONST_BITS-PASS1_BITS-1); + + tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */ + tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */ + tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */ + tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */ + tmp10 = MULTIPLY(tmp10, - FIX_0_899976223); /* c7-c3 */ + tmp11 = MULTIPLY(tmp11, - FIX_2_562915447); /* -c1-c3 */ + tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* c5-c3 */ + tmp13 = MULTIPLY(tmp13, - FIX_1_961570560); /* -c3-c5 */ + + tmp12 += z1; + tmp13 += z1; + + dataptr[1] = (DCTELEM) + RIGHT_SHIFT(tmp0 + tmp10 + tmp12, CONST_BITS-PASS1_BITS); + dataptr[3] = (DCTELEM) + RIGHT_SHIFT(tmp1 + tmp11 + tmp13, CONST_BITS-PASS1_BITS); + dataptr[5] = (DCTELEM) + RIGHT_SHIFT(tmp2 + tmp11 + tmp12, CONST_BITS-PASS1_BITS); + dataptr[7] = (DCTELEM) + RIGHT_SHIFT(tmp3 + tmp10 + tmp13, CONST_BITS-PASS1_BITS); + dataptr += DCTSIZE; /* advance pointer to next row */ } @@ -217,67 +248,4101 @@ jpeg_fdct_islow (DCTELEM * data) dataptr = data; for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { - tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; - tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; - tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; - tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; - tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; - tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; - tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; - tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; - /* Even part per LL&M figure 1 --- note that published figure is faulty; * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". */ - - tmp10 = tmp0 + tmp3; - tmp13 = tmp0 - tmp3; + + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; + + /* Add fudge factor here for final descale. */ + tmp10 = tmp0 + tmp3 + (ONE << (PASS1_BITS-1)); + tmp12 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; - tmp12 = tmp1 - tmp2; - - dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp11, PASS1_BITS); - dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp10 - tmp11, PASS1_BITS); - + tmp13 = tmp1 - tmp2; + + tmp0 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; + + dataptr[DCTSIZE*0] = (DCTELEM) RIGHT_SHIFT(tmp10 + tmp11, PASS1_BITS); + dataptr[DCTSIZE*4] = (DCTELEM) RIGHT_SHIFT(tmp10 - tmp11, PASS1_BITS); + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); - dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865), - CONST_BITS+PASS1_BITS); - dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065), - CONST_BITS+PASS1_BITS); - + /* Add fudge factor here for final descale. */ + z1 += ONE << (CONST_BITS+PASS1_BITS-1); + dataptr[DCTSIZE*2] = (DCTELEM) + RIGHT_SHIFT(z1 + MULTIPLY(tmp12, FIX_0_765366865), CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*6] = (DCTELEM) + RIGHT_SHIFT(z1 - MULTIPLY(tmp13, FIX_1_847759065), CONST_BITS+PASS1_BITS); + /* Odd part per figure 8 --- note paper omits factor of sqrt(2). - * cK represents cos(K*pi/16). - * i0..i3 in the paper are tmp4..tmp7 here. + * cK represents sqrt(2) * cos(K*pi/16). + * i0..i3 in the paper are tmp0..tmp3 here. */ - - z1 = tmp4 + tmp7; - z2 = tmp5 + tmp6; - z3 = tmp4 + tmp6; - z4 = tmp5 + tmp7; - z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ - - tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ - tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ - tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ - tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ - z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ - z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ - z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ - z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ - - z3 += z5; - z4 += z5; - - dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp4 + z1 + z3, - CONST_BITS+PASS1_BITS); - dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp5 + z2 + z4, - CONST_BITS+PASS1_BITS); - dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp6 + z2 + z3, - CONST_BITS+PASS1_BITS); - dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp7 + z1 + z4, - CONST_BITS+PASS1_BITS); - + + tmp10 = tmp0 + tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp0 + tmp2; + tmp13 = tmp1 + tmp3; + z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */ + /* Add fudge factor here for final descale. */ + z1 += ONE << (CONST_BITS+PASS1_BITS-1); + + tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */ + tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */ + tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */ + tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */ + tmp10 = MULTIPLY(tmp10, - FIX_0_899976223); /* c7-c3 */ + tmp11 = MULTIPLY(tmp11, - FIX_2_562915447); /* -c1-c3 */ + tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* c5-c3 */ + tmp13 = MULTIPLY(tmp13, - FIX_1_961570560); /* -c3-c5 */ + + tmp12 += z1; + tmp13 += z1; + + dataptr[DCTSIZE*1] = (DCTELEM) + RIGHT_SHIFT(tmp0 + tmp10 + tmp12, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*3] = (DCTELEM) + RIGHT_SHIFT(tmp1 + tmp11 + tmp13, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*5] = (DCTELEM) + RIGHT_SHIFT(tmp2 + tmp11 + tmp12, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*7] = (DCTELEM) + RIGHT_SHIFT(tmp3 + tmp10 + tmp13, CONST_BITS+PASS1_BITS); + dataptr++; /* advance pointer to next column */ } } +#ifdef DCT_SCALING_SUPPORTED + + +/* + * Perform the forward DCT on a 7x7 sample block. + */ + +GLOBAL(void) +jpeg_fdct_7x7 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3; + INT32 tmp10, tmp11, tmp12; + INT32 z1, z2, z3; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + /* cK represents sqrt(2) * cos(K*pi/14). */ + + dataptr = data; + for (ctr = 0; ctr < 7; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[6]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[5]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[4]); + tmp3 = GETJSAMPLE(elemptr[3]); + + tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[6]); + tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[5]); + tmp12 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[4]); + + z1 = tmp0 + tmp2; + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + ((z1 + tmp1 + tmp3 - 7 * CENTERJSAMPLE) << PASS1_BITS); + tmp3 += tmp3; + z1 -= tmp3; + z1 -= tmp3; + z1 = MULTIPLY(z1, FIX(0.353553391)); /* (c2+c6-c4)/2 */ + z2 = MULTIPLY(tmp0 - tmp2, FIX(0.920609002)); /* (c2+c4-c6)/2 */ + z3 = MULTIPLY(tmp1 - tmp2, FIX(0.314692123)); /* c6 */ + dataptr[2] = (DCTELEM) DESCALE(z1 + z2 + z3, CONST_BITS-PASS1_BITS); + z1 -= z2; + z2 = MULTIPLY(tmp0 - tmp1, FIX(0.881747734)); /* c4 */ + dataptr[4] = (DCTELEM) + DESCALE(z2 + z3 - MULTIPLY(tmp1 - tmp3, FIX(0.707106781)), /* c2+c6-c4 */ + CONST_BITS-PASS1_BITS); + dataptr[6] = (DCTELEM) DESCALE(z1 + z2, CONST_BITS-PASS1_BITS); + + /* Odd part */ + + tmp1 = MULTIPLY(tmp10 + tmp11, FIX(0.935414347)); /* (c3+c1-c5)/2 */ + tmp2 = MULTIPLY(tmp10 - tmp11, FIX(0.170262339)); /* (c3+c5-c1)/2 */ + tmp0 = tmp1 - tmp2; + tmp1 += tmp2; + tmp2 = MULTIPLY(tmp11 + tmp12, - FIX(1.378756276)); /* -c1 */ + tmp1 += tmp2; + tmp3 = MULTIPLY(tmp10 + tmp12, FIX(0.613604268)); /* c5 */ + tmp0 += tmp3; + tmp2 += tmp3 + MULTIPLY(tmp12, FIX(1.870828693)); /* c3+c1-c5 */ + + dataptr[1] = (DCTELEM) DESCALE(tmp0, CONST_BITS-PASS1_BITS); + dataptr[3] = (DCTELEM) DESCALE(tmp1, CONST_BITS-PASS1_BITS); + dataptr[5] = (DCTELEM) DESCALE(tmp2, CONST_BITS-PASS1_BITS); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by (8/7)**2 = 64/49, which we fold + * into the constant multipliers: + * cK now represents sqrt(2) * cos(K*pi/14) * 64/49. + */ + + dataptr = data; + for (ctr = 0; ctr < 7; ctr++) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*6]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*5]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*4]; + tmp3 = dataptr[DCTSIZE*3]; + + tmp10 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*6]; + tmp11 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*5]; + tmp12 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*4]; + + z1 = tmp0 + tmp2; + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(z1 + tmp1 + tmp3, FIX(1.306122449)), /* 64/49 */ + CONST_BITS+PASS1_BITS); + tmp3 += tmp3; + z1 -= tmp3; + z1 -= tmp3; + z1 = MULTIPLY(z1, FIX(0.461784020)); /* (c2+c6-c4)/2 */ + z2 = MULTIPLY(tmp0 - tmp2, FIX(1.202428084)); /* (c2+c4-c6)/2 */ + z3 = MULTIPLY(tmp1 - tmp2, FIX(0.411026446)); /* c6 */ + dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + z2 + z3, CONST_BITS+PASS1_BITS); + z1 -= z2; + z2 = MULTIPLY(tmp0 - tmp1, FIX(1.151670509)); /* c4 */ + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(z2 + z3 - MULTIPLY(tmp1 - tmp3, FIX(0.923568041)), /* c2+c6-c4 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 + z2, CONST_BITS+PASS1_BITS); + + /* Odd part */ + + tmp1 = MULTIPLY(tmp10 + tmp11, FIX(1.221765677)); /* (c3+c1-c5)/2 */ + tmp2 = MULTIPLY(tmp10 - tmp11, FIX(0.222383464)); /* (c3+c5-c1)/2 */ + tmp0 = tmp1 - tmp2; + tmp1 += tmp2; + tmp2 = MULTIPLY(tmp11 + tmp12, - FIX(1.800824523)); /* -c1 */ + tmp1 += tmp2; + tmp3 = MULTIPLY(tmp10 + tmp12, FIX(0.801442310)); /* c5 */ + tmp0 += tmp3; + tmp2 += tmp3 + MULTIPLY(tmp12, FIX(2.443531355)); /* c3+c1-c5 */ + + dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp0, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp1, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp2, CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 6x6 sample block. + */ + +GLOBAL(void) +jpeg_fdct_6x6 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2; + INT32 tmp10, tmp11, tmp12; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + /* cK represents sqrt(2) * cos(K*pi/12). */ + + dataptr = data; + for (ctr = 0; ctr < 6; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[5]); + tmp11 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[4]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[3]); + + tmp10 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[5]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[4]); + tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[3]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + ((tmp10 + tmp11 - 6 * CENTERJSAMPLE) << PASS1_BITS); + dataptr[2] = (DCTELEM) + DESCALE(MULTIPLY(tmp12, FIX(1.224744871)), /* c2 */ + CONST_BITS-PASS1_BITS); + dataptr[4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp11 - tmp11, FIX(0.707106781)), /* c4 */ + CONST_BITS-PASS1_BITS); + + /* Odd part */ + + tmp10 = DESCALE(MULTIPLY(tmp0 + tmp2, FIX(0.366025404)), /* c5 */ + CONST_BITS-PASS1_BITS); + + dataptr[1] = (DCTELEM) (tmp10 + ((tmp0 + tmp1) << PASS1_BITS)); + dataptr[3] = (DCTELEM) ((tmp0 - tmp1 - tmp2) << PASS1_BITS); + dataptr[5] = (DCTELEM) (tmp10 + ((tmp2 - tmp1) << PASS1_BITS)); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by (8/6)**2 = 16/9, which we fold + * into the constant multipliers: + * cK now represents sqrt(2) * cos(K*pi/12) * 16/9. + */ + + dataptr = data; + for (ctr = 0; ctr < 6; ctr++) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*5]; + tmp11 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*4]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*3]; + + tmp10 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + + tmp0 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*5]; + tmp1 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*4]; + tmp2 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*3]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 + tmp11, FIX(1.777777778)), /* 16/9 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(MULTIPLY(tmp12, FIX(2.177324216)), /* c2 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp11 - tmp11, FIX(1.257078722)), /* c4 */ + CONST_BITS+PASS1_BITS); + + /* Odd part */ + + tmp10 = MULTIPLY(tmp0 + tmp2, FIX(0.650711829)); /* c5 */ + + dataptr[DCTSIZE*1] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp0 + tmp1, FIX(1.777777778)), /* 16/9 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*3] = (DCTELEM) + DESCALE(MULTIPLY(tmp0 - tmp1 - tmp2, FIX(1.777777778)), /* 16/9 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*5] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp2 - tmp1, FIX(1.777777778)), /* 16/9 */ + CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 5x5 sample block. + */ + +GLOBAL(void) +jpeg_fdct_5x5 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2; + INT32 tmp10, tmp11; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + /* We scale the results further by 2 as part of output adaption */ + /* scaling for different DCT size. */ + /* cK represents sqrt(2) * cos(K*pi/10). */ + + dataptr = data; + for (ctr = 0; ctr < 5; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[4]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[3]); + tmp2 = GETJSAMPLE(elemptr[2]); + + tmp10 = tmp0 + tmp1; + tmp11 = tmp0 - tmp1; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[4]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[3]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + ((tmp10 + tmp2 - 5 * CENTERJSAMPLE) << (PASS1_BITS+1)); + tmp11 = MULTIPLY(tmp11, FIX(0.790569415)); /* (c2+c4)/2 */ + tmp10 -= tmp2 << 2; + tmp10 = MULTIPLY(tmp10, FIX(0.353553391)); /* (c2-c4)/2 */ + dataptr[2] = (DCTELEM) DESCALE(tmp11 + tmp10, CONST_BITS-PASS1_BITS-1); + dataptr[4] = (DCTELEM) DESCALE(tmp11 - tmp10, CONST_BITS-PASS1_BITS-1); + + /* Odd part */ + + tmp10 = MULTIPLY(tmp0 + tmp1, FIX(0.831253876)); /* c3 */ + + dataptr[1] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp0, FIX(0.513743148)), /* c1-c3 */ + CONST_BITS-PASS1_BITS-1); + dataptr[3] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp1, FIX(2.176250899)), /* c1+c3 */ + CONST_BITS-PASS1_BITS-1); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by (8/5)**2 = 64/25, which we partially + * fold into the constant multipliers (other part was done in pass 1): + * cK now represents sqrt(2) * cos(K*pi/10) * 32/25. + */ + + dataptr = data; + for (ctr = 0; ctr < 5; ctr++) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*4]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*3]; + tmp2 = dataptr[DCTSIZE*2]; + + tmp10 = tmp0 + tmp1; + tmp11 = tmp0 - tmp1; + + tmp0 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*4]; + tmp1 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*3]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 + tmp2, FIX(1.28)), /* 32/25 */ + CONST_BITS+PASS1_BITS); + tmp11 = MULTIPLY(tmp11, FIX(1.011928851)); /* (c2+c4)/2 */ + tmp10 -= tmp2 << 2; + tmp10 = MULTIPLY(tmp10, FIX(0.452548340)); /* (c2-c4)/2 */ + dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(tmp11 + tmp10, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp11 - tmp10, CONST_BITS+PASS1_BITS); + + /* Odd part */ + + tmp10 = MULTIPLY(tmp0 + tmp1, FIX(1.064004961)); /* c3 */ + + dataptr[DCTSIZE*1] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp0, FIX(0.657591230)), /* c1-c3 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*3] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp1, FIX(2.785601151)), /* c1+c3 */ + CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 4x4 sample block. + */ + +GLOBAL(void) +jpeg_fdct_4x4 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1; + INT32 tmp10, tmp11; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + /* We must also scale the output by (8/4)**2 = 2**2, which we add here. */ + /* cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point FDCT]. */ + + dataptr = data; + for (ctr = 0; ctr < 4; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[3]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[2]); + + tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[3]); + tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[2]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + ((tmp0 + tmp1 - 4 * CENTERJSAMPLE) << (PASS1_BITS+2)); + dataptr[2] = (DCTELEM) ((tmp0 - tmp1) << (PASS1_BITS+2)); + + /* Odd part */ + + tmp0 = MULTIPLY(tmp10 + tmp11, FIX_0_541196100); /* c6 */ + /* Add fudge factor here for final descale. */ + tmp0 += ONE << (CONST_BITS-PASS1_BITS-3); + + dataptr[1] = (DCTELEM) + RIGHT_SHIFT(tmp0 + MULTIPLY(tmp10, FIX_0_765366865), /* c2-c6 */ + CONST_BITS-PASS1_BITS-2); + dataptr[3] = (DCTELEM) + RIGHT_SHIFT(tmp0 - MULTIPLY(tmp11, FIX_1_847759065), /* c2+c6 */ + CONST_BITS-PASS1_BITS-2); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + */ + + dataptr = data; + for (ctr = 0; ctr < 4; ctr++) { + /* Even part */ + + /* Add fudge factor here for final descale. */ + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*3] + (ONE << (PASS1_BITS-1)); + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*2]; + + tmp10 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*3]; + tmp11 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*2]; + + dataptr[DCTSIZE*0] = (DCTELEM) RIGHT_SHIFT(tmp0 + tmp1, PASS1_BITS); + dataptr[DCTSIZE*2] = (DCTELEM) RIGHT_SHIFT(tmp0 - tmp1, PASS1_BITS); + + /* Odd part */ + + tmp0 = MULTIPLY(tmp10 + tmp11, FIX_0_541196100); /* c6 */ + /* Add fudge factor here for final descale. */ + tmp0 += ONE << (CONST_BITS+PASS1_BITS-1); + + dataptr[DCTSIZE*1] = (DCTELEM) + RIGHT_SHIFT(tmp0 + MULTIPLY(tmp10, FIX_0_765366865), /* c2-c6 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*3] = (DCTELEM) + RIGHT_SHIFT(tmp0 - MULTIPLY(tmp11, FIX_1_847759065), /* c2+c6 */ + CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 3x3 sample block. + */ + +GLOBAL(void) +jpeg_fdct_3x3 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + /* We scale the results further by 2**2 as part of output adaption */ + /* scaling for different DCT size. */ + /* cK represents sqrt(2) * cos(K*pi/6). */ + + dataptr = data; + for (ctr = 0; ctr < 3; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[2]); + tmp1 = GETJSAMPLE(elemptr[1]); + + tmp2 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[2]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + ((tmp0 + tmp1 - 3 * CENTERJSAMPLE) << (PASS1_BITS+2)); + dataptr[2] = (DCTELEM) + DESCALE(MULTIPLY(tmp0 - tmp1 - tmp1, FIX(0.707106781)), /* c2 */ + CONST_BITS-PASS1_BITS-2); + + /* Odd part */ + + dataptr[1] = (DCTELEM) + DESCALE(MULTIPLY(tmp2, FIX(1.224744871)), /* c1 */ + CONST_BITS-PASS1_BITS-2); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by (8/3)**2 = 64/9, which we partially + * fold into the constant multipliers (other part was done in pass 1): + * cK now represents sqrt(2) * cos(K*pi/6) * 16/9. + */ + + dataptr = data; + for (ctr = 0; ctr < 3; ctr++) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*2]; + tmp1 = dataptr[DCTSIZE*1]; + + tmp2 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*2]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp0 + tmp1, FIX(1.777777778)), /* 16/9 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(MULTIPLY(tmp0 - tmp1 - tmp1, FIX(1.257078722)), /* c2 */ + CONST_BITS+PASS1_BITS); + + /* Odd part */ + + dataptr[DCTSIZE*1] = (DCTELEM) + DESCALE(MULTIPLY(tmp2, FIX(2.177324216)), /* c1 */ + CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 2x2 sample block. + */ + +GLOBAL(void) +jpeg_fdct_2x2 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3; + JSAMPROW elemptr; + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT. */ + + /* Row 0 */ + elemptr = sample_data[0] + start_col; + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[1]); + tmp1 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[1]); + + /* Row 1 */ + elemptr = sample_data[1] + start_col; + + tmp2 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[1]); + tmp3 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[1]); + + /* Pass 2: process columns. + * We leave the results scaled up by an overall factor of 8. + * We must also scale the output by (8/2)**2 = 2**4. + */ + + /* Column 0 */ + /* Apply unsigned->signed conversion */ + data[DCTSIZE*0] = (DCTELEM) ((tmp0 + tmp2 - 4 * CENTERJSAMPLE) << 4); + data[DCTSIZE*1] = (DCTELEM) ((tmp0 - tmp2) << 4); + + /* Column 1 */ + data[DCTSIZE*0+1] = (DCTELEM) ((tmp1 + tmp3) << 4); + data[DCTSIZE*1+1] = (DCTELEM) ((tmp1 - tmp3) << 4); +} + + +/* + * Perform the forward DCT on a 1x1 sample block. + */ + +GLOBAL(void) +jpeg_fdct_1x1 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* We leave the result scaled up by an overall factor of 8. */ + /* We must also scale the output by (8/1)**2 = 2**6. */ + /* Apply unsigned->signed conversion */ + data[0] = (DCTELEM) + ((GETJSAMPLE(sample_data[0][start_col]) - CENTERJSAMPLE) << 6); +} + + +/* + * Perform the forward DCT on a 9x9 sample block. + */ + +GLOBAL(void) +jpeg_fdct_9x9 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4; + INT32 tmp10, tmp11, tmp12, tmp13; + INT32 z1, z2; + DCTELEM workspace[8]; + DCTELEM *dataptr; + DCTELEM *wsptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* we scale the results further by 2 as part of output adaption */ + /* scaling for different DCT size. */ + /* cK represents sqrt(2) * cos(K*pi/18). */ + + dataptr = data; + ctr = 0; + for (;;) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[8]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[7]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[6]); + tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[5]); + tmp4 = GETJSAMPLE(elemptr[4]); + + tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[8]); + tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[7]); + tmp12 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[6]); + tmp13 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[5]); + + z1 = tmp0 + tmp2 + tmp3; + z2 = tmp1 + tmp4; + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) ((z1 + z2 - 9 * CENTERJSAMPLE) << 1); + dataptr[6] = (DCTELEM) + DESCALE(MULTIPLY(z1 - z2 - z2, FIX(0.707106781)), /* c6 */ + CONST_BITS-1); + z1 = MULTIPLY(tmp0 - tmp2, FIX(1.328926049)); /* c2 */ + z2 = MULTIPLY(tmp1 - tmp4 - tmp4, FIX(0.707106781)); /* c6 */ + dataptr[2] = (DCTELEM) + DESCALE(MULTIPLY(tmp2 - tmp3, FIX(1.083350441)) /* c4 */ + + z1 + z2, CONST_BITS-1); + dataptr[4] = (DCTELEM) + DESCALE(MULTIPLY(tmp3 - tmp0, FIX(0.245575608)) /* c8 */ + + z1 - z2, CONST_BITS-1); + + /* Odd part */ + + dataptr[3] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp12 - tmp13, FIX(1.224744871)), /* c3 */ + CONST_BITS-1); + + tmp11 = MULTIPLY(tmp11, FIX(1.224744871)); /* c3 */ + tmp0 = MULTIPLY(tmp10 + tmp12, FIX(0.909038955)); /* c5 */ + tmp1 = MULTIPLY(tmp10 + tmp13, FIX(0.483689525)); /* c7 */ + + dataptr[1] = (DCTELEM) DESCALE(tmp11 + tmp0 + tmp1, CONST_BITS-1); + + tmp2 = MULTIPLY(tmp12 - tmp13, FIX(1.392728481)); /* c1 */ + + dataptr[5] = (DCTELEM) DESCALE(tmp0 - tmp11 - tmp2, CONST_BITS-1); + dataptr[7] = (DCTELEM) DESCALE(tmp1 - tmp11 + tmp2, CONST_BITS-1); + + ctr++; + + if (ctr != DCTSIZE) { + if (ctr == 9) + break; /* Done. */ + dataptr += DCTSIZE; /* advance pointer to next row */ + } else + dataptr = workspace; /* switch pointer to extended workspace */ + } + + /* Pass 2: process columns. + * We leave the results scaled up by an overall factor of 8. + * We must also scale the output by (8/9)**2 = 64/81, which we partially + * fold into the constant multipliers and final/initial shifting: + * cK now represents sqrt(2) * cos(K*pi/18) * 128/81. + */ + + dataptr = data; + wsptr = workspace; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*0]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*7]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*6]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*5]; + tmp4 = dataptr[DCTSIZE*4]; + + tmp10 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*0]; + tmp11 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*7]; + tmp12 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*6]; + tmp13 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*5]; + + z1 = tmp0 + tmp2 + tmp3; + z2 = tmp1 + tmp4; + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(z1 + z2, FIX(1.580246914)), /* 128/81 */ + CONST_BITS+2); + dataptr[DCTSIZE*6] = (DCTELEM) + DESCALE(MULTIPLY(z1 - z2 - z2, FIX(1.117403309)), /* c6 */ + CONST_BITS+2); + z1 = MULTIPLY(tmp0 - tmp2, FIX(2.100031287)); /* c2 */ + z2 = MULTIPLY(tmp1 - tmp4 - tmp4, FIX(1.117403309)); /* c6 */ + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(MULTIPLY(tmp2 - tmp3, FIX(1.711961190)) /* c4 */ + + z1 + z2, CONST_BITS+2); + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(MULTIPLY(tmp3 - tmp0, FIX(0.388070096)) /* c8 */ + + z1 - z2, CONST_BITS+2); + + /* Odd part */ + + dataptr[DCTSIZE*3] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp12 - tmp13, FIX(1.935399303)), /* c3 */ + CONST_BITS+2); + + tmp11 = MULTIPLY(tmp11, FIX(1.935399303)); /* c3 */ + tmp0 = MULTIPLY(tmp10 + tmp12, FIX(1.436506004)); /* c5 */ + tmp1 = MULTIPLY(tmp10 + tmp13, FIX(0.764348879)); /* c7 */ + + dataptr[DCTSIZE*1] = (DCTELEM) + DESCALE(tmp11 + tmp0 + tmp1, CONST_BITS+2); + + tmp2 = MULTIPLY(tmp12 - tmp13, FIX(2.200854883)); /* c1 */ + + dataptr[DCTSIZE*5] = (DCTELEM) + DESCALE(tmp0 - tmp11 - tmp2, CONST_BITS+2); + dataptr[DCTSIZE*7] = (DCTELEM) + DESCALE(tmp1 - tmp11 + tmp2, CONST_BITS+2); + + dataptr++; /* advance pointer to next column */ + wsptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 10x10 sample block. + */ + +GLOBAL(void) +jpeg_fdct_10x10 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14; + DCTELEM workspace[8*2]; + DCTELEM *dataptr; + DCTELEM *wsptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* we scale the results further by 2 as part of output adaption */ + /* scaling for different DCT size. */ + /* cK represents sqrt(2) * cos(K*pi/20). */ + + dataptr = data; + ctr = 0; + for (;;) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[9]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[8]); + tmp12 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[7]); + tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[6]); + tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[5]); + + tmp10 = tmp0 + tmp4; + tmp13 = tmp0 - tmp4; + tmp11 = tmp1 + tmp3; + tmp14 = tmp1 - tmp3; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[9]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[8]); + tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[7]); + tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[6]); + tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[5]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + ((tmp10 + tmp11 + tmp12 - 10 * CENTERJSAMPLE) << 1); + tmp12 += tmp12; + dataptr[4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.144122806)) - /* c4 */ + MULTIPLY(tmp11 - tmp12, FIX(0.437016024)), /* c8 */ + CONST_BITS-1); + tmp10 = MULTIPLY(tmp13 + tmp14, FIX(0.831253876)); /* c6 */ + dataptr[2] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp13, FIX(0.513743148)), /* c2-c6 */ + CONST_BITS-1); + dataptr[6] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp14, FIX(2.176250899)), /* c2+c6 */ + CONST_BITS-1); + + /* Odd part */ + + tmp10 = tmp0 + tmp4; + tmp11 = tmp1 - tmp3; + dataptr[5] = (DCTELEM) ((tmp10 - tmp11 - tmp2) << 1); + tmp2 <<= CONST_BITS; + dataptr[1] = (DCTELEM) + DESCALE(MULTIPLY(tmp0, FIX(1.396802247)) + /* c1 */ + MULTIPLY(tmp1, FIX(1.260073511)) + tmp2 + /* c3 */ + MULTIPLY(tmp3, FIX(0.642039522)) + /* c7 */ + MULTIPLY(tmp4, FIX(0.221231742)), /* c9 */ + CONST_BITS-1); + tmp12 = MULTIPLY(tmp0 - tmp4, FIX(0.951056516)) - /* (c3+c7)/2 */ + MULTIPLY(tmp1 + tmp3, FIX(0.587785252)); /* (c1-c9)/2 */ + tmp13 = MULTIPLY(tmp10 + tmp11, FIX(0.309016994)) + /* (c3-c7)/2 */ + (tmp11 << (CONST_BITS - 1)) - tmp2; + dataptr[3] = (DCTELEM) DESCALE(tmp12 + tmp13, CONST_BITS-1); + dataptr[7] = (DCTELEM) DESCALE(tmp12 - tmp13, CONST_BITS-1); + + ctr++; + + if (ctr != DCTSIZE) { + if (ctr == 10) + break; /* Done. */ + dataptr += DCTSIZE; /* advance pointer to next row */ + } else + dataptr = workspace; /* switch pointer to extended workspace */ + } + + /* Pass 2: process columns. + * We leave the results scaled up by an overall factor of 8. + * We must also scale the output by (8/10)**2 = 16/25, which we partially + * fold into the constant multipliers and final/initial shifting: + * cK now represents sqrt(2) * cos(K*pi/20) * 32/25. + */ + + dataptr = data; + wsptr = workspace; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*1]; + tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*0]; + tmp12 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*7]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*6]; + tmp4 = dataptr[DCTSIZE*4] + dataptr[DCTSIZE*5]; + + tmp10 = tmp0 + tmp4; + tmp13 = tmp0 - tmp4; + tmp11 = tmp1 + tmp3; + tmp14 = tmp1 - tmp3; + + tmp0 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*1]; + tmp1 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*0]; + tmp2 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*7]; + tmp3 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*6]; + tmp4 = dataptr[DCTSIZE*4] - dataptr[DCTSIZE*5]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 + tmp11 + tmp12, FIX(1.28)), /* 32/25 */ + CONST_BITS+2); + tmp12 += tmp12; + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.464477191)) - /* c4 */ + MULTIPLY(tmp11 - tmp12, FIX(0.559380511)), /* c8 */ + CONST_BITS+2); + tmp10 = MULTIPLY(tmp13 + tmp14, FIX(1.064004961)); /* c6 */ + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp13, FIX(0.657591230)), /* c2-c6 */ + CONST_BITS+2); + dataptr[DCTSIZE*6] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp14, FIX(2.785601151)), /* c2+c6 */ + CONST_BITS+2); + + /* Odd part */ + + tmp10 = tmp0 + tmp4; + tmp11 = tmp1 - tmp3; + dataptr[DCTSIZE*5] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp11 - tmp2, FIX(1.28)), /* 32/25 */ + CONST_BITS+2); + tmp2 = MULTIPLY(tmp2, FIX(1.28)); /* 32/25 */ + dataptr[DCTSIZE*1] = (DCTELEM) + DESCALE(MULTIPLY(tmp0, FIX(1.787906876)) + /* c1 */ + MULTIPLY(tmp1, FIX(1.612894094)) + tmp2 + /* c3 */ + MULTIPLY(tmp3, FIX(0.821810588)) + /* c7 */ + MULTIPLY(tmp4, FIX(0.283176630)), /* c9 */ + CONST_BITS+2); + tmp12 = MULTIPLY(tmp0 - tmp4, FIX(1.217352341)) - /* (c3+c7)/2 */ + MULTIPLY(tmp1 + tmp3, FIX(0.752365123)); /* (c1-c9)/2 */ + tmp13 = MULTIPLY(tmp10 + tmp11, FIX(0.395541753)) + /* (c3-c7)/2 */ + MULTIPLY(tmp11, FIX(0.64)) - tmp2; /* 16/25 */ + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp12 + tmp13, CONST_BITS+2); + dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp12 - tmp13, CONST_BITS+2); + + dataptr++; /* advance pointer to next column */ + wsptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on an 11x11 sample block. + */ + +GLOBAL(void) +jpeg_fdct_11x11 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14; + INT32 z1, z2, z3; + DCTELEM workspace[8*3]; + DCTELEM *dataptr; + DCTELEM *wsptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* we scale the results further by 2 as part of output adaption */ + /* scaling for different DCT size. */ + /* cK represents sqrt(2) * cos(K*pi/22). */ + + dataptr = data; + ctr = 0; + for (;;) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[10]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[9]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[8]); + tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[7]); + tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[6]); + tmp5 = GETJSAMPLE(elemptr[5]); + + tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[10]); + tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[9]); + tmp12 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[8]); + tmp13 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[7]); + tmp14 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[6]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + ((tmp0 + tmp1 + tmp2 + tmp3 + tmp4 + tmp5 - 11 * CENTERJSAMPLE) << 1); + tmp5 += tmp5; + tmp0 -= tmp5; + tmp1 -= tmp5; + tmp2 -= tmp5; + tmp3 -= tmp5; + tmp4 -= tmp5; + z1 = MULTIPLY(tmp0 + tmp3, FIX(1.356927976)) + /* c2 */ + MULTIPLY(tmp2 + tmp4, FIX(0.201263574)); /* c10 */ + z2 = MULTIPLY(tmp1 - tmp3, FIX(0.926112931)); /* c6 */ + z3 = MULTIPLY(tmp0 - tmp1, FIX(1.189712156)); /* c4 */ + dataptr[2] = (DCTELEM) + DESCALE(z1 + z2 - MULTIPLY(tmp3, FIX(1.018300590)) /* c2+c8-c6 */ + - MULTIPLY(tmp4, FIX(1.390975730)), /* c4+c10 */ + CONST_BITS-1); + dataptr[4] = (DCTELEM) + DESCALE(z2 + z3 + MULTIPLY(tmp1, FIX(0.062335650)) /* c4-c6-c10 */ + - MULTIPLY(tmp2, FIX(1.356927976)) /* c2 */ + + MULTIPLY(tmp4, FIX(0.587485545)), /* c8 */ + CONST_BITS-1); + dataptr[6] = (DCTELEM) + DESCALE(z1 + z3 - MULTIPLY(tmp0, FIX(1.620527200)) /* c2+c4-c6 */ + - MULTIPLY(tmp2, FIX(0.788749120)), /* c8+c10 */ + CONST_BITS-1); + + /* Odd part */ + + tmp1 = MULTIPLY(tmp10 + tmp11, FIX(1.286413905)); /* c3 */ + tmp2 = MULTIPLY(tmp10 + tmp12, FIX(1.068791298)); /* c5 */ + tmp3 = MULTIPLY(tmp10 + tmp13, FIX(0.764581576)); /* c7 */ + tmp0 = tmp1 + tmp2 + tmp3 - MULTIPLY(tmp10, FIX(1.719967871)) /* c7+c5+c3-c1 */ + + MULTIPLY(tmp14, FIX(0.398430003)); /* c9 */ + tmp4 = MULTIPLY(tmp11 + tmp12, - FIX(0.764581576)); /* -c7 */ + tmp5 = MULTIPLY(tmp11 + tmp13, - FIX(1.399818907)); /* -c1 */ + tmp1 += tmp4 + tmp5 + MULTIPLY(tmp11, FIX(1.276416582)) /* c9+c7+c1-c3 */ + - MULTIPLY(tmp14, FIX(1.068791298)); /* c5 */ + tmp10 = MULTIPLY(tmp12 + tmp13, FIX(0.398430003)); /* c9 */ + tmp2 += tmp4 + tmp10 - MULTIPLY(tmp12, FIX(1.989053629)) /* c9+c5+c3-c7 */ + + MULTIPLY(tmp14, FIX(1.399818907)); /* c1 */ + tmp3 += tmp5 + tmp10 + MULTIPLY(tmp13, FIX(1.305598626)) /* c1+c5-c9-c7 */ + - MULTIPLY(tmp14, FIX(1.286413905)); /* c3 */ + + dataptr[1] = (DCTELEM) DESCALE(tmp0, CONST_BITS-1); + dataptr[3] = (DCTELEM) DESCALE(tmp1, CONST_BITS-1); + dataptr[5] = (DCTELEM) DESCALE(tmp2, CONST_BITS-1); + dataptr[7] = (DCTELEM) DESCALE(tmp3, CONST_BITS-1); + + ctr++; + + if (ctr != DCTSIZE) { + if (ctr == 11) + break; /* Done. */ + dataptr += DCTSIZE; /* advance pointer to next row */ + } else + dataptr = workspace; /* switch pointer to extended workspace */ + } + + /* Pass 2: process columns. + * We leave the results scaled up by an overall factor of 8. + * We must also scale the output by (8/11)**2 = 64/121, which we partially + * fold into the constant multipliers and final/initial shifting: + * cK now represents sqrt(2) * cos(K*pi/22) * 128/121. + */ + + dataptr = data; + wsptr = workspace; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*2]; + tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*1]; + tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*0]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*7]; + tmp4 = dataptr[DCTSIZE*4] + dataptr[DCTSIZE*6]; + tmp5 = dataptr[DCTSIZE*5]; + + tmp10 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*2]; + tmp11 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*1]; + tmp12 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*0]; + tmp13 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*7]; + tmp14 = dataptr[DCTSIZE*4] - dataptr[DCTSIZE*6]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp0 + tmp1 + tmp2 + tmp3 + tmp4 + tmp5, + FIX(1.057851240)), /* 128/121 */ + CONST_BITS+2); + tmp5 += tmp5; + tmp0 -= tmp5; + tmp1 -= tmp5; + tmp2 -= tmp5; + tmp3 -= tmp5; + tmp4 -= tmp5; + z1 = MULTIPLY(tmp0 + tmp3, FIX(1.435427942)) + /* c2 */ + MULTIPLY(tmp2 + tmp4, FIX(0.212906922)); /* c10 */ + z2 = MULTIPLY(tmp1 - tmp3, FIX(0.979689713)); /* c6 */ + z3 = MULTIPLY(tmp0 - tmp1, FIX(1.258538479)); /* c4 */ + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(z1 + z2 - MULTIPLY(tmp3, FIX(1.077210542)) /* c2+c8-c6 */ + - MULTIPLY(tmp4, FIX(1.471445400)), /* c4+c10 */ + CONST_BITS+2); + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(z2 + z3 + MULTIPLY(tmp1, FIX(0.065941844)) /* c4-c6-c10 */ + - MULTIPLY(tmp2, FIX(1.435427942)) /* c2 */ + + MULTIPLY(tmp4, FIX(0.621472312)), /* c8 */ + CONST_BITS+2); + dataptr[DCTSIZE*6] = (DCTELEM) + DESCALE(z1 + z3 - MULTIPLY(tmp0, FIX(1.714276708)) /* c2+c4-c6 */ + - MULTIPLY(tmp2, FIX(0.834379234)), /* c8+c10 */ + CONST_BITS+2); + + /* Odd part */ + + tmp1 = MULTIPLY(tmp10 + tmp11, FIX(1.360834544)); /* c3 */ + tmp2 = MULTIPLY(tmp10 + tmp12, FIX(1.130622199)); /* c5 */ + tmp3 = MULTIPLY(tmp10 + tmp13, FIX(0.808813568)); /* c7 */ + tmp0 = tmp1 + tmp2 + tmp3 - MULTIPLY(tmp10, FIX(1.819470145)) /* c7+c5+c3-c1 */ + + MULTIPLY(tmp14, FIX(0.421479672)); /* c9 */ + tmp4 = MULTIPLY(tmp11 + tmp12, - FIX(0.808813568)); /* -c7 */ + tmp5 = MULTIPLY(tmp11 + tmp13, - FIX(1.480800167)); /* -c1 */ + tmp1 += tmp4 + tmp5 + MULTIPLY(tmp11, FIX(1.350258864)) /* c9+c7+c1-c3 */ + - MULTIPLY(tmp14, FIX(1.130622199)); /* c5 */ + tmp10 = MULTIPLY(tmp12 + tmp13, FIX(0.421479672)); /* c9 */ + tmp2 += tmp4 + tmp10 - MULTIPLY(tmp12, FIX(2.104122847)) /* c9+c5+c3-c7 */ + + MULTIPLY(tmp14, FIX(1.480800167)); /* c1 */ + tmp3 += tmp5 + tmp10 + MULTIPLY(tmp13, FIX(1.381129125)) /* c1+c5-c9-c7 */ + - MULTIPLY(tmp14, FIX(1.360834544)); /* c3 */ + + dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp0, CONST_BITS+2); + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp1, CONST_BITS+2); + dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp2, CONST_BITS+2); + dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp3, CONST_BITS+2); + + dataptr++; /* advance pointer to next column */ + wsptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 12x12 sample block. + */ + +GLOBAL(void) +jpeg_fdct_12x12 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; + DCTELEM workspace[8*4]; + DCTELEM *dataptr; + DCTELEM *wsptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT. */ + /* cK represents sqrt(2) * cos(K*pi/24). */ + + dataptr = data; + ctr = 0; + for (;;) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[11]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[10]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[9]); + tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[8]); + tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[7]); + tmp5 = GETJSAMPLE(elemptr[5]) + GETJSAMPLE(elemptr[6]); + + tmp10 = tmp0 + tmp5; + tmp13 = tmp0 - tmp5; + tmp11 = tmp1 + tmp4; + tmp14 = tmp1 - tmp4; + tmp12 = tmp2 + tmp3; + tmp15 = tmp2 - tmp3; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[11]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[10]); + tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[9]); + tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[8]); + tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[7]); + tmp5 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[6]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) (tmp10 + tmp11 + tmp12 - 12 * CENTERJSAMPLE); + dataptr[6] = (DCTELEM) (tmp13 - tmp14 - tmp15); + dataptr[4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.224744871)), /* c4 */ + CONST_BITS); + dataptr[2] = (DCTELEM) + DESCALE(tmp14 - tmp15 + MULTIPLY(tmp13 + tmp15, FIX(1.366025404)), /* c2 */ + CONST_BITS); + + /* Odd part */ + + tmp10 = MULTIPLY(tmp1 + tmp4, FIX_0_541196100); /* c9 */ + tmp14 = tmp10 + MULTIPLY(tmp1, FIX_0_765366865); /* c3-c9 */ + tmp15 = tmp10 - MULTIPLY(tmp4, FIX_1_847759065); /* c3+c9 */ + tmp12 = MULTIPLY(tmp0 + tmp2, FIX(1.121971054)); /* c5 */ + tmp13 = MULTIPLY(tmp0 + tmp3, FIX(0.860918669)); /* c7 */ + tmp10 = tmp12 + tmp13 + tmp14 - MULTIPLY(tmp0, FIX(0.580774953)) /* c5+c7-c1 */ + + MULTIPLY(tmp5, FIX(0.184591911)); /* c11 */ + tmp11 = MULTIPLY(tmp2 + tmp3, - FIX(0.184591911)); /* -c11 */ + tmp12 += tmp11 - tmp15 - MULTIPLY(tmp2, FIX(2.339493912)) /* c1+c5-c11 */ + + MULTIPLY(tmp5, FIX(0.860918669)); /* c7 */ + tmp13 += tmp11 - tmp14 + MULTIPLY(tmp3, FIX(0.725788011)) /* c1+c11-c7 */ + - MULTIPLY(tmp5, FIX(1.121971054)); /* c5 */ + tmp11 = tmp15 + MULTIPLY(tmp0 - tmp3, FIX(1.306562965)) /* c3 */ + - MULTIPLY(tmp2 + tmp5, FIX_0_541196100); /* c9 */ + + dataptr[1] = (DCTELEM) DESCALE(tmp10, CONST_BITS); + dataptr[3] = (DCTELEM) DESCALE(tmp11, CONST_BITS); + dataptr[5] = (DCTELEM) DESCALE(tmp12, CONST_BITS); + dataptr[7] = (DCTELEM) DESCALE(tmp13, CONST_BITS); + + ctr++; + + if (ctr != DCTSIZE) { + if (ctr == 12) + break; /* Done. */ + dataptr += DCTSIZE; /* advance pointer to next row */ + } else + dataptr = workspace; /* switch pointer to extended workspace */ + } + + /* Pass 2: process columns. + * We leave the results scaled up by an overall factor of 8. + * We must also scale the output by (8/12)**2 = 4/9, which we partially + * fold into the constant multipliers and final shifting: + * cK now represents sqrt(2) * cos(K*pi/24) * 8/9. + */ + + dataptr = data; + wsptr = workspace; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*3]; + tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*2]; + tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*1]; + tmp3 = dataptr[DCTSIZE*3] + wsptr[DCTSIZE*0]; + tmp4 = dataptr[DCTSIZE*4] + dataptr[DCTSIZE*7]; + tmp5 = dataptr[DCTSIZE*5] + dataptr[DCTSIZE*6]; + + tmp10 = tmp0 + tmp5; + tmp13 = tmp0 - tmp5; + tmp11 = tmp1 + tmp4; + tmp14 = tmp1 - tmp4; + tmp12 = tmp2 + tmp3; + tmp15 = tmp2 - tmp3; + + tmp0 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*3]; + tmp1 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*2]; + tmp2 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*1]; + tmp3 = dataptr[DCTSIZE*3] - wsptr[DCTSIZE*0]; + tmp4 = dataptr[DCTSIZE*4] - dataptr[DCTSIZE*7]; + tmp5 = dataptr[DCTSIZE*5] - dataptr[DCTSIZE*6]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 + tmp11 + tmp12, FIX(0.888888889)), /* 8/9 */ + CONST_BITS+1); + dataptr[DCTSIZE*6] = (DCTELEM) + DESCALE(MULTIPLY(tmp13 - tmp14 - tmp15, FIX(0.888888889)), /* 8/9 */ + CONST_BITS+1); + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.088662108)), /* c4 */ + CONST_BITS+1); + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(MULTIPLY(tmp14 - tmp15, FIX(0.888888889)) + /* 8/9 */ + MULTIPLY(tmp13 + tmp15, FIX(1.214244803)), /* c2 */ + CONST_BITS+1); + + /* Odd part */ + + tmp10 = MULTIPLY(tmp1 + tmp4, FIX(0.481063200)); /* c9 */ + tmp14 = tmp10 + MULTIPLY(tmp1, FIX(0.680326102)); /* c3-c9 */ + tmp15 = tmp10 - MULTIPLY(tmp4, FIX(1.642452502)); /* c3+c9 */ + tmp12 = MULTIPLY(tmp0 + tmp2, FIX(0.997307603)); /* c5 */ + tmp13 = MULTIPLY(tmp0 + tmp3, FIX(0.765261039)); /* c7 */ + tmp10 = tmp12 + tmp13 + tmp14 - MULTIPLY(tmp0, FIX(0.516244403)) /* c5+c7-c1 */ + + MULTIPLY(tmp5, FIX(0.164081699)); /* c11 */ + tmp11 = MULTIPLY(tmp2 + tmp3, - FIX(0.164081699)); /* -c11 */ + tmp12 += tmp11 - tmp15 - MULTIPLY(tmp2, FIX(2.079550144)) /* c1+c5-c11 */ + + MULTIPLY(tmp5, FIX(0.765261039)); /* c7 */ + tmp13 += tmp11 - tmp14 + MULTIPLY(tmp3, FIX(0.645144899)) /* c1+c11-c7 */ + - MULTIPLY(tmp5, FIX(0.997307603)); /* c5 */ + tmp11 = tmp15 + MULTIPLY(tmp0 - tmp3, FIX(1.161389302)) /* c3 */ + - MULTIPLY(tmp2 + tmp5, FIX(0.481063200)); /* c9 */ + + dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp10, CONST_BITS+1); + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp11, CONST_BITS+1); + dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp12, CONST_BITS+1); + dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp13, CONST_BITS+1); + + dataptr++; /* advance pointer to next column */ + wsptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 13x13 sample block. + */ + +GLOBAL(void) +jpeg_fdct_13x13 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; + INT32 z1, z2; + DCTELEM workspace[8*5]; + DCTELEM *dataptr; + DCTELEM *wsptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT. */ + /* cK represents sqrt(2) * cos(K*pi/26). */ + + dataptr = data; + ctr = 0; + for (;;) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[12]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[11]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[10]); + tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[9]); + tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[8]); + tmp5 = GETJSAMPLE(elemptr[5]) + GETJSAMPLE(elemptr[7]); + tmp6 = GETJSAMPLE(elemptr[6]); + + tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[12]); + tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[11]); + tmp12 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[10]); + tmp13 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[9]); + tmp14 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[8]); + tmp15 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[7]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + (tmp0 + tmp1 + tmp2 + tmp3 + tmp4 + tmp5 + tmp6 - 13 * CENTERJSAMPLE); + tmp6 += tmp6; + tmp0 -= tmp6; + tmp1 -= tmp6; + tmp2 -= tmp6; + tmp3 -= tmp6; + tmp4 -= tmp6; + tmp5 -= tmp6; + dataptr[2] = (DCTELEM) + DESCALE(MULTIPLY(tmp0, FIX(1.373119086)) + /* c2 */ + MULTIPLY(tmp1, FIX(1.058554052)) + /* c6 */ + MULTIPLY(tmp2, FIX(0.501487041)) - /* c10 */ + MULTIPLY(tmp3, FIX(0.170464608)) - /* c12 */ + MULTIPLY(tmp4, FIX(0.803364869)) - /* c8 */ + MULTIPLY(tmp5, FIX(1.252223920)), /* c4 */ + CONST_BITS); + z1 = MULTIPLY(tmp0 - tmp2, FIX(1.155388986)) - /* (c4+c6)/2 */ + MULTIPLY(tmp3 - tmp4, FIX(0.435816023)) - /* (c2-c10)/2 */ + MULTIPLY(tmp1 - tmp5, FIX(0.316450131)); /* (c8-c12)/2 */ + z2 = MULTIPLY(tmp0 + tmp2, FIX(0.096834934)) - /* (c4-c6)/2 */ + MULTIPLY(tmp3 + tmp4, FIX(0.937303064)) + /* (c2+c10)/2 */ + MULTIPLY(tmp1 + tmp5, FIX(0.486914739)); /* (c8+c12)/2 */ + + dataptr[4] = (DCTELEM) DESCALE(z1 + z2, CONST_BITS); + dataptr[6] = (DCTELEM) DESCALE(z1 - z2, CONST_BITS); + + /* Odd part */ + + tmp1 = MULTIPLY(tmp10 + tmp11, FIX(1.322312651)); /* c3 */ + tmp2 = MULTIPLY(tmp10 + tmp12, FIX(1.163874945)); /* c5 */ + tmp3 = MULTIPLY(tmp10 + tmp13, FIX(0.937797057)) + /* c7 */ + MULTIPLY(tmp14 + tmp15, FIX(0.338443458)); /* c11 */ + tmp0 = tmp1 + tmp2 + tmp3 - + MULTIPLY(tmp10, FIX(2.020082300)) + /* c3+c5+c7-c1 */ + MULTIPLY(tmp14, FIX(0.318774355)); /* c9-c11 */ + tmp4 = MULTIPLY(tmp14 - tmp15, FIX(0.937797057)) - /* c7 */ + MULTIPLY(tmp11 + tmp12, FIX(0.338443458)); /* c11 */ + tmp5 = MULTIPLY(tmp11 + tmp13, - FIX(1.163874945)); /* -c5 */ + tmp1 += tmp4 + tmp5 + + MULTIPLY(tmp11, FIX(0.837223564)) - /* c5+c9+c11-c3 */ + MULTIPLY(tmp14, FIX(2.341699410)); /* c1+c7 */ + tmp6 = MULTIPLY(tmp12 + tmp13, - FIX(0.657217813)); /* -c9 */ + tmp2 += tmp4 + tmp6 - + MULTIPLY(tmp12, FIX(1.572116027)) + /* c1+c5-c9-c11 */ + MULTIPLY(tmp15, FIX(2.260109708)); /* c3+c7 */ + tmp3 += tmp5 + tmp6 + + MULTIPLY(tmp13, FIX(2.205608352)) - /* c3+c5+c9-c7 */ + MULTIPLY(tmp15, FIX(1.742345811)); /* c1+c11 */ + + dataptr[1] = (DCTELEM) DESCALE(tmp0, CONST_BITS); + dataptr[3] = (DCTELEM) DESCALE(tmp1, CONST_BITS); + dataptr[5] = (DCTELEM) DESCALE(tmp2, CONST_BITS); + dataptr[7] = (DCTELEM) DESCALE(tmp3, CONST_BITS); + + ctr++; + + if (ctr != DCTSIZE) { + if (ctr == 13) + break; /* Done. */ + dataptr += DCTSIZE; /* advance pointer to next row */ + } else + dataptr = workspace; /* switch pointer to extended workspace */ + } + + /* Pass 2: process columns. + * We leave the results scaled up by an overall factor of 8. + * We must also scale the output by (8/13)**2 = 64/169, which we partially + * fold into the constant multipliers and final shifting: + * cK now represents sqrt(2) * cos(K*pi/26) * 128/169. + */ + + dataptr = data; + wsptr = workspace; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*4]; + tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*3]; + tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*2]; + tmp3 = dataptr[DCTSIZE*3] + wsptr[DCTSIZE*1]; + tmp4 = dataptr[DCTSIZE*4] + wsptr[DCTSIZE*0]; + tmp5 = dataptr[DCTSIZE*5] + dataptr[DCTSIZE*7]; + tmp6 = dataptr[DCTSIZE*6]; + + tmp10 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*4]; + tmp11 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*3]; + tmp12 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*2]; + tmp13 = dataptr[DCTSIZE*3] - wsptr[DCTSIZE*1]; + tmp14 = dataptr[DCTSIZE*4] - wsptr[DCTSIZE*0]; + tmp15 = dataptr[DCTSIZE*5] - dataptr[DCTSIZE*7]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp0 + tmp1 + tmp2 + tmp3 + tmp4 + tmp5 + tmp6, + FIX(0.757396450)), /* 128/169 */ + CONST_BITS+1); + tmp6 += tmp6; + tmp0 -= tmp6; + tmp1 -= tmp6; + tmp2 -= tmp6; + tmp3 -= tmp6; + tmp4 -= tmp6; + tmp5 -= tmp6; + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(MULTIPLY(tmp0, FIX(1.039995521)) + /* c2 */ + MULTIPLY(tmp1, FIX(0.801745081)) + /* c6 */ + MULTIPLY(tmp2, FIX(0.379824504)) - /* c10 */ + MULTIPLY(tmp3, FIX(0.129109289)) - /* c12 */ + MULTIPLY(tmp4, FIX(0.608465700)) - /* c8 */ + MULTIPLY(tmp5, FIX(0.948429952)), /* c4 */ + CONST_BITS+1); + z1 = MULTIPLY(tmp0 - tmp2, FIX(0.875087516)) - /* (c4+c6)/2 */ + MULTIPLY(tmp3 - tmp4, FIX(0.330085509)) - /* (c2-c10)/2 */ + MULTIPLY(tmp1 - tmp5, FIX(0.239678205)); /* (c8-c12)/2 */ + z2 = MULTIPLY(tmp0 + tmp2, FIX(0.073342435)) - /* (c4-c6)/2 */ + MULTIPLY(tmp3 + tmp4, FIX(0.709910013)) + /* (c2+c10)/2 */ + MULTIPLY(tmp1 + tmp5, FIX(0.368787494)); /* (c8+c12)/2 */ + + dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(z1 + z2, CONST_BITS+1); + dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 - z2, CONST_BITS+1); + + /* Odd part */ + + tmp1 = MULTIPLY(tmp10 + tmp11, FIX(1.001514908)); /* c3 */ + tmp2 = MULTIPLY(tmp10 + tmp12, FIX(0.881514751)); /* c5 */ + tmp3 = MULTIPLY(tmp10 + tmp13, FIX(0.710284161)) + /* c7 */ + MULTIPLY(tmp14 + tmp15, FIX(0.256335874)); /* c11 */ + tmp0 = tmp1 + tmp2 + tmp3 - + MULTIPLY(tmp10, FIX(1.530003162)) + /* c3+c5+c7-c1 */ + MULTIPLY(tmp14, FIX(0.241438564)); /* c9-c11 */ + tmp4 = MULTIPLY(tmp14 - tmp15, FIX(0.710284161)) - /* c7 */ + MULTIPLY(tmp11 + tmp12, FIX(0.256335874)); /* c11 */ + tmp5 = MULTIPLY(tmp11 + tmp13, - FIX(0.881514751)); /* -c5 */ + tmp1 += tmp4 + tmp5 + + MULTIPLY(tmp11, FIX(0.634110155)) - /* c5+c9+c11-c3 */ + MULTIPLY(tmp14, FIX(1.773594819)); /* c1+c7 */ + tmp6 = MULTIPLY(tmp12 + tmp13, - FIX(0.497774438)); /* -c9 */ + tmp2 += tmp4 + tmp6 - + MULTIPLY(tmp12, FIX(1.190715098)) + /* c1+c5-c9-c11 */ + MULTIPLY(tmp15, FIX(1.711799069)); /* c3+c7 */ + tmp3 += tmp5 + tmp6 + + MULTIPLY(tmp13, FIX(1.670519935)) - /* c3+c5+c9-c7 */ + MULTIPLY(tmp15, FIX(1.319646532)); /* c1+c11 */ + + dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp0, CONST_BITS+1); + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp1, CONST_BITS+1); + dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp2, CONST_BITS+1); + dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp3, CONST_BITS+1); + + dataptr++; /* advance pointer to next column */ + wsptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 14x14 sample block. + */ + +GLOBAL(void) +jpeg_fdct_14x14 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; + DCTELEM workspace[8*6]; + DCTELEM *dataptr; + DCTELEM *wsptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT. */ + /* cK represents sqrt(2) * cos(K*pi/28). */ + + dataptr = data; + ctr = 0; + for (;;) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[13]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[12]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[11]); + tmp13 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[10]); + tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[9]); + tmp5 = GETJSAMPLE(elemptr[5]) + GETJSAMPLE(elemptr[8]); + tmp6 = GETJSAMPLE(elemptr[6]) + GETJSAMPLE(elemptr[7]); + + tmp10 = tmp0 + tmp6; + tmp14 = tmp0 - tmp6; + tmp11 = tmp1 + tmp5; + tmp15 = tmp1 - tmp5; + tmp12 = tmp2 + tmp4; + tmp16 = tmp2 - tmp4; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[13]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[12]); + tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[11]); + tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[10]); + tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[9]); + tmp5 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[8]); + tmp6 = GETJSAMPLE(elemptr[6]) - GETJSAMPLE(elemptr[7]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + (tmp10 + tmp11 + tmp12 + tmp13 - 14 * CENTERJSAMPLE); + tmp13 += tmp13; + dataptr[4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp13, FIX(1.274162392)) + /* c4 */ + MULTIPLY(tmp11 - tmp13, FIX(0.314692123)) - /* c12 */ + MULTIPLY(tmp12 - tmp13, FIX(0.881747734)), /* c8 */ + CONST_BITS); + + tmp10 = MULTIPLY(tmp14 + tmp15, FIX(1.105676686)); /* c6 */ + + dataptr[2] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp14, FIX(0.273079590)) /* c2-c6 */ + + MULTIPLY(tmp16, FIX(0.613604268)), /* c10 */ + CONST_BITS); + dataptr[6] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp15, FIX(1.719280954)) /* c6+c10 */ + - MULTIPLY(tmp16, FIX(1.378756276)), /* c2 */ + CONST_BITS); + + /* Odd part */ + + tmp10 = tmp1 + tmp2; + tmp11 = tmp5 - tmp4; + dataptr[7] = (DCTELEM) (tmp0 - tmp10 + tmp3 - tmp11 - tmp6); + tmp3 <<= CONST_BITS; + tmp10 = MULTIPLY(tmp10, - FIX(0.158341681)); /* -c13 */ + tmp11 = MULTIPLY(tmp11, FIX(1.405321284)); /* c1 */ + tmp10 += tmp11 - tmp3; + tmp11 = MULTIPLY(tmp0 + tmp2, FIX(1.197448846)) + /* c5 */ + MULTIPLY(tmp4 + tmp6, FIX(0.752406978)); /* c9 */ + dataptr[5] = (DCTELEM) + DESCALE(tmp10 + tmp11 - MULTIPLY(tmp2, FIX(2.373959773)) /* c3+c5-c13 */ + + MULTIPLY(tmp4, FIX(1.119999435)), /* c1+c11-c9 */ + CONST_BITS); + tmp12 = MULTIPLY(tmp0 + tmp1, FIX(1.334852607)) + /* c3 */ + MULTIPLY(tmp5 - tmp6, FIX(0.467085129)); /* c11 */ + dataptr[3] = (DCTELEM) + DESCALE(tmp10 + tmp12 - MULTIPLY(tmp1, FIX(0.424103948)) /* c3-c9-c13 */ + - MULTIPLY(tmp5, FIX(3.069855259)), /* c1+c5+c11 */ + CONST_BITS); + dataptr[1] = (DCTELEM) + DESCALE(tmp11 + tmp12 + tmp3 + tmp6 - + MULTIPLY(tmp0 + tmp6, FIX(1.126980169)), /* c3+c5-c1 */ + CONST_BITS); + + ctr++; + + if (ctr != DCTSIZE) { + if (ctr == 14) + break; /* Done. */ + dataptr += DCTSIZE; /* advance pointer to next row */ + } else + dataptr = workspace; /* switch pointer to extended workspace */ + } + + /* Pass 2: process columns. + * We leave the results scaled up by an overall factor of 8. + * We must also scale the output by (8/14)**2 = 16/49, which we partially + * fold into the constant multipliers and final shifting: + * cK now represents sqrt(2) * cos(K*pi/28) * 32/49. + */ + + dataptr = data; + wsptr = workspace; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*5]; + tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*4]; + tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*3]; + tmp13 = dataptr[DCTSIZE*3] + wsptr[DCTSIZE*2]; + tmp4 = dataptr[DCTSIZE*4] + wsptr[DCTSIZE*1]; + tmp5 = dataptr[DCTSIZE*5] + wsptr[DCTSIZE*0]; + tmp6 = dataptr[DCTSIZE*6] + dataptr[DCTSIZE*7]; + + tmp10 = tmp0 + tmp6; + tmp14 = tmp0 - tmp6; + tmp11 = tmp1 + tmp5; + tmp15 = tmp1 - tmp5; + tmp12 = tmp2 + tmp4; + tmp16 = tmp2 - tmp4; + + tmp0 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*5]; + tmp1 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*4]; + tmp2 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*3]; + tmp3 = dataptr[DCTSIZE*3] - wsptr[DCTSIZE*2]; + tmp4 = dataptr[DCTSIZE*4] - wsptr[DCTSIZE*1]; + tmp5 = dataptr[DCTSIZE*5] - wsptr[DCTSIZE*0]; + tmp6 = dataptr[DCTSIZE*6] - dataptr[DCTSIZE*7]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 + tmp11 + tmp12 + tmp13, + FIX(0.653061224)), /* 32/49 */ + CONST_BITS+1); + tmp13 += tmp13; + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp13, FIX(0.832106052)) + /* c4 */ + MULTIPLY(tmp11 - tmp13, FIX(0.205513223)) - /* c12 */ + MULTIPLY(tmp12 - tmp13, FIX(0.575835255)), /* c8 */ + CONST_BITS+1); + + tmp10 = MULTIPLY(tmp14 + tmp15, FIX(0.722074570)); /* c6 */ + + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp14, FIX(0.178337691)) /* c2-c6 */ + + MULTIPLY(tmp16, FIX(0.400721155)), /* c10 */ + CONST_BITS+1); + dataptr[DCTSIZE*6] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp15, FIX(1.122795725)) /* c6+c10 */ + - MULTIPLY(tmp16, FIX(0.900412262)), /* c2 */ + CONST_BITS+1); + + /* Odd part */ + + tmp10 = tmp1 + tmp2; + tmp11 = tmp5 - tmp4; + dataptr[DCTSIZE*7] = (DCTELEM) + DESCALE(MULTIPLY(tmp0 - tmp10 + tmp3 - tmp11 - tmp6, + FIX(0.653061224)), /* 32/49 */ + CONST_BITS+1); + tmp3 = MULTIPLY(tmp3 , FIX(0.653061224)); /* 32/49 */ + tmp10 = MULTIPLY(tmp10, - FIX(0.103406812)); /* -c13 */ + tmp11 = MULTIPLY(tmp11, FIX(0.917760839)); /* c1 */ + tmp10 += tmp11 - tmp3; + tmp11 = MULTIPLY(tmp0 + tmp2, FIX(0.782007410)) + /* c5 */ + MULTIPLY(tmp4 + tmp6, FIX(0.491367823)); /* c9 */ + dataptr[DCTSIZE*5] = (DCTELEM) + DESCALE(tmp10 + tmp11 - MULTIPLY(tmp2, FIX(1.550341076)) /* c3+c5-c13 */ + + MULTIPLY(tmp4, FIX(0.731428202)), /* c1+c11-c9 */ + CONST_BITS+1); + tmp12 = MULTIPLY(tmp0 + tmp1, FIX(0.871740478)) + /* c3 */ + MULTIPLY(tmp5 - tmp6, FIX(0.305035186)); /* c11 */ + dataptr[DCTSIZE*3] = (DCTELEM) + DESCALE(tmp10 + tmp12 - MULTIPLY(tmp1, FIX(0.276965844)) /* c3-c9-c13 */ + - MULTIPLY(tmp5, FIX(2.004803435)), /* c1+c5+c11 */ + CONST_BITS+1); + dataptr[DCTSIZE*1] = (DCTELEM) + DESCALE(tmp11 + tmp12 + tmp3 + - MULTIPLY(tmp0, FIX(0.735987049)) /* c3+c5-c1 */ + - MULTIPLY(tmp6, FIX(0.082925825)), /* c9-c11-c13 */ + CONST_BITS+1); + + dataptr++; /* advance pointer to next column */ + wsptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 15x15 sample block. + */ + +GLOBAL(void) +jpeg_fdct_15x15 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; + INT32 z1, z2, z3; + DCTELEM workspace[8*7]; + DCTELEM *dataptr; + DCTELEM *wsptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT. */ + /* cK represents sqrt(2) * cos(K*pi/30). */ + + dataptr = data; + ctr = 0; + for (;;) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[14]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[13]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[12]); + tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[11]); + tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[10]); + tmp5 = GETJSAMPLE(elemptr[5]) + GETJSAMPLE(elemptr[9]); + tmp6 = GETJSAMPLE(elemptr[6]) + GETJSAMPLE(elemptr[8]); + tmp7 = GETJSAMPLE(elemptr[7]); + + tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[14]); + tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[13]); + tmp12 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[12]); + tmp13 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[11]); + tmp14 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[10]); + tmp15 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[9]); + tmp16 = GETJSAMPLE(elemptr[6]) - GETJSAMPLE(elemptr[8]); + + z1 = tmp0 + tmp4 + tmp5; + z2 = tmp1 + tmp3 + tmp6; + z3 = tmp2 + tmp7; + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) (z1 + z2 + z3 - 15 * CENTERJSAMPLE); + z3 += z3; + dataptr[6] = (DCTELEM) + DESCALE(MULTIPLY(z1 - z3, FIX(1.144122806)) - /* c6 */ + MULTIPLY(z2 - z3, FIX(0.437016024)), /* c12 */ + CONST_BITS); + tmp2 += ((tmp1 + tmp4) >> 1) - tmp7 - tmp7; + z1 = MULTIPLY(tmp3 - tmp2, FIX(1.531135173)) - /* c2+c14 */ + MULTIPLY(tmp6 - tmp2, FIX(2.238241955)); /* c4+c8 */ + z2 = MULTIPLY(tmp5 - tmp2, FIX(0.798468008)) - /* c8-c14 */ + MULTIPLY(tmp0 - tmp2, FIX(0.091361227)); /* c2-c4 */ + z3 = MULTIPLY(tmp0 - tmp3, FIX(1.383309603)) + /* c2 */ + MULTIPLY(tmp6 - tmp5, FIX(0.946293579)) + /* c8 */ + MULTIPLY(tmp1 - tmp4, FIX(0.790569415)); /* (c6+c12)/2 */ + + dataptr[2] = (DCTELEM) DESCALE(z1 + z3, CONST_BITS); + dataptr[4] = (DCTELEM) DESCALE(z2 + z3, CONST_BITS); + + /* Odd part */ + + tmp2 = MULTIPLY(tmp10 - tmp12 - tmp13 + tmp15 + tmp16, + FIX(1.224744871)); /* c5 */ + tmp1 = MULTIPLY(tmp10 - tmp14 - tmp15, FIX(1.344997024)) + /* c3 */ + MULTIPLY(tmp11 - tmp13 - tmp16, FIX(0.831253876)); /* c9 */ + tmp12 = MULTIPLY(tmp12, FIX(1.224744871)); /* c5 */ + tmp4 = MULTIPLY(tmp10 - tmp16, FIX(1.406466353)) + /* c1 */ + MULTIPLY(tmp11 + tmp14, FIX(1.344997024)) + /* c3 */ + MULTIPLY(tmp13 + tmp15, FIX(0.575212477)); /* c11 */ + tmp0 = MULTIPLY(tmp13, FIX(0.475753014)) - /* c7-c11 */ + MULTIPLY(tmp14, FIX(0.513743148)) + /* c3-c9 */ + MULTIPLY(tmp16, FIX(1.700497885)) + tmp4 + tmp12; /* c1+c13 */ + tmp3 = MULTIPLY(tmp10, - FIX(0.355500862)) - /* -(c1-c7) */ + MULTIPLY(tmp11, FIX(2.176250899)) - /* c3+c9 */ + MULTIPLY(tmp15, FIX(0.869244010)) + tmp4 - tmp12; /* c11+c13 */ + + dataptr[1] = (DCTELEM) DESCALE(tmp0, CONST_BITS); + dataptr[3] = (DCTELEM) DESCALE(tmp1, CONST_BITS); + dataptr[5] = (DCTELEM) DESCALE(tmp2, CONST_BITS); + dataptr[7] = (DCTELEM) DESCALE(tmp3, CONST_BITS); + + ctr++; + + if (ctr != DCTSIZE) { + if (ctr == 15) + break; /* Done. */ + dataptr += DCTSIZE; /* advance pointer to next row */ + } else + dataptr = workspace; /* switch pointer to extended workspace */ + } + + /* Pass 2: process columns. + * We leave the results scaled up by an overall factor of 8. + * We must also scale the output by (8/15)**2 = 64/225, which we partially + * fold into the constant multipliers and final shifting: + * cK now represents sqrt(2) * cos(K*pi/30) * 256/225. + */ + + dataptr = data; + wsptr = workspace; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*6]; + tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*5]; + tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*4]; + tmp3 = dataptr[DCTSIZE*3] + wsptr[DCTSIZE*3]; + tmp4 = dataptr[DCTSIZE*4] + wsptr[DCTSIZE*2]; + tmp5 = dataptr[DCTSIZE*5] + wsptr[DCTSIZE*1]; + tmp6 = dataptr[DCTSIZE*6] + wsptr[DCTSIZE*0]; + tmp7 = dataptr[DCTSIZE*7]; + + tmp10 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*6]; + tmp11 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*5]; + tmp12 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*4]; + tmp13 = dataptr[DCTSIZE*3] - wsptr[DCTSIZE*3]; + tmp14 = dataptr[DCTSIZE*4] - wsptr[DCTSIZE*2]; + tmp15 = dataptr[DCTSIZE*5] - wsptr[DCTSIZE*1]; + tmp16 = dataptr[DCTSIZE*6] - wsptr[DCTSIZE*0]; + + z1 = tmp0 + tmp4 + tmp5; + z2 = tmp1 + tmp3 + tmp6; + z3 = tmp2 + tmp7; + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(z1 + z2 + z3, FIX(1.137777778)), /* 256/225 */ + CONST_BITS+2); + z3 += z3; + dataptr[DCTSIZE*6] = (DCTELEM) + DESCALE(MULTIPLY(z1 - z3, FIX(1.301757503)) - /* c6 */ + MULTIPLY(z2 - z3, FIX(0.497227121)), /* c12 */ + CONST_BITS+2); + tmp2 += ((tmp1 + tmp4) >> 1) - tmp7 - tmp7; + z1 = MULTIPLY(tmp3 - tmp2, FIX(1.742091575)) - /* c2+c14 */ + MULTIPLY(tmp6 - tmp2, FIX(2.546621957)); /* c4+c8 */ + z2 = MULTIPLY(tmp5 - tmp2, FIX(0.908479156)) - /* c8-c14 */ + MULTIPLY(tmp0 - tmp2, FIX(0.103948774)); /* c2-c4 */ + z3 = MULTIPLY(tmp0 - tmp3, FIX(1.573898926)) + /* c2 */ + MULTIPLY(tmp6 - tmp5, FIX(1.076671805)) + /* c8 */ + MULTIPLY(tmp1 - tmp4, FIX(0.899492312)); /* (c6+c12)/2 */ + + dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + z3, CONST_BITS+2); + dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(z2 + z3, CONST_BITS+2); + + /* Odd part */ + + tmp2 = MULTIPLY(tmp10 - tmp12 - tmp13 + tmp15 + tmp16, + FIX(1.393487498)); /* c5 */ + tmp1 = MULTIPLY(tmp10 - tmp14 - tmp15, FIX(1.530307725)) + /* c3 */ + MULTIPLY(tmp11 - tmp13 - tmp16, FIX(0.945782187)); /* c9 */ + tmp12 = MULTIPLY(tmp12, FIX(1.393487498)); /* c5 */ + tmp4 = MULTIPLY(tmp10 - tmp16, FIX(1.600246161)) + /* c1 */ + MULTIPLY(tmp11 + tmp14, FIX(1.530307725)) + /* c3 */ + MULTIPLY(tmp13 + tmp15, FIX(0.654463974)); /* c11 */ + tmp0 = MULTIPLY(tmp13, FIX(0.541301207)) - /* c7-c11 */ + MULTIPLY(tmp14, FIX(0.584525538)) + /* c3-c9 */ + MULTIPLY(tmp16, FIX(1.934788705)) + tmp4 + tmp12; /* c1+c13 */ + tmp3 = MULTIPLY(tmp10, - FIX(0.404480980)) - /* -(c1-c7) */ + MULTIPLY(tmp11, FIX(2.476089912)) - /* c3+c9 */ + MULTIPLY(tmp15, FIX(0.989006518)) + tmp4 - tmp12; /* c11+c13 */ + + dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp0, CONST_BITS+2); + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp1, CONST_BITS+2); + dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp2, CONST_BITS+2); + dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp3, CONST_BITS+2); + + dataptr++; /* advance pointer to next column */ + wsptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 16x16 sample block. + */ + +GLOBAL(void) +jpeg_fdct_16x16 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16, tmp17; + DCTELEM workspace[DCTSIZE2]; + DCTELEM *dataptr; + DCTELEM *wsptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + /* cK represents sqrt(2) * cos(K*pi/32). */ + + dataptr = data; + ctr = 0; + for (;;) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[15]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[14]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[13]); + tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[12]); + tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[11]); + tmp5 = GETJSAMPLE(elemptr[5]) + GETJSAMPLE(elemptr[10]); + tmp6 = GETJSAMPLE(elemptr[6]) + GETJSAMPLE(elemptr[9]); + tmp7 = GETJSAMPLE(elemptr[7]) + GETJSAMPLE(elemptr[8]); + + tmp10 = tmp0 + tmp7; + tmp14 = tmp0 - tmp7; + tmp11 = tmp1 + tmp6; + tmp15 = tmp1 - tmp6; + tmp12 = tmp2 + tmp5; + tmp16 = tmp2 - tmp5; + tmp13 = tmp3 + tmp4; + tmp17 = tmp3 - tmp4; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[15]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[14]); + tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[13]); + tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[12]); + tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[11]); + tmp5 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[10]); + tmp6 = GETJSAMPLE(elemptr[6]) - GETJSAMPLE(elemptr[9]); + tmp7 = GETJSAMPLE(elemptr[7]) - GETJSAMPLE(elemptr[8]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + ((tmp10 + tmp11 + tmp12 + tmp13 - 16 * CENTERJSAMPLE) << PASS1_BITS); + dataptr[4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp13, FIX(1.306562965)) + /* c4[16] = c2[8] */ + MULTIPLY(tmp11 - tmp12, FIX_0_541196100), /* c12[16] = c6[8] */ + CONST_BITS-PASS1_BITS); + + tmp10 = MULTIPLY(tmp17 - tmp15, FIX(0.275899379)) + /* c14[16] = c7[8] */ + MULTIPLY(tmp14 - tmp16, FIX(1.387039845)); /* c2[16] = c1[8] */ + + dataptr[2] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp15, FIX(1.451774982)) /* c6+c14 */ + + MULTIPLY(tmp16, FIX(2.172734804)), /* c2+c10 */ + CONST_BITS-PASS1_BITS); + dataptr[6] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp14, FIX(0.211164243)) /* c2-c6 */ + - MULTIPLY(tmp17, FIX(1.061594338)), /* c10+c14 */ + CONST_BITS-PASS1_BITS); + + /* Odd part */ + + tmp11 = MULTIPLY(tmp0 + tmp1, FIX(1.353318001)) + /* c3 */ + MULTIPLY(tmp6 - tmp7, FIX(0.410524528)); /* c13 */ + tmp12 = MULTIPLY(tmp0 + tmp2, FIX(1.247225013)) + /* c5 */ + MULTIPLY(tmp5 + tmp7, FIX(0.666655658)); /* c11 */ + tmp13 = MULTIPLY(tmp0 + tmp3, FIX(1.093201867)) + /* c7 */ + MULTIPLY(tmp4 - tmp7, FIX(0.897167586)); /* c9 */ + tmp14 = MULTIPLY(tmp1 + tmp2, FIX(0.138617169)) + /* c15 */ + MULTIPLY(tmp6 - tmp5, FIX(1.407403738)); /* c1 */ + tmp15 = MULTIPLY(tmp1 + tmp3, - FIX(0.666655658)) + /* -c11 */ + MULTIPLY(tmp4 + tmp6, - FIX(1.247225013)); /* -c5 */ + tmp16 = MULTIPLY(tmp2 + tmp3, - FIX(1.353318001)) + /* -c3 */ + MULTIPLY(tmp5 - tmp4, FIX(0.410524528)); /* c13 */ + tmp10 = tmp11 + tmp12 + tmp13 - + MULTIPLY(tmp0, FIX(2.286341144)) + /* c7+c5+c3-c1 */ + MULTIPLY(tmp7, FIX(0.779653625)); /* c15+c13-c11+c9 */ + tmp11 += tmp14 + tmp15 + MULTIPLY(tmp1, FIX(0.071888074)) /* c9-c3-c15+c11 */ + - MULTIPLY(tmp6, FIX(1.663905119)); /* c7+c13+c1-c5 */ + tmp12 += tmp14 + tmp16 - MULTIPLY(tmp2, FIX(1.125726048)) /* c7+c5+c15-c3 */ + + MULTIPLY(tmp5, FIX(1.227391138)); /* c9-c11+c1-c13 */ + tmp13 += tmp15 + tmp16 + MULTIPLY(tmp3, FIX(1.065388962)) /* c15+c3+c11-c7 */ + + MULTIPLY(tmp4, FIX(2.167985692)); /* c1+c13+c5-c9 */ + + dataptr[1] = (DCTELEM) DESCALE(tmp10, CONST_BITS-PASS1_BITS); + dataptr[3] = (DCTELEM) DESCALE(tmp11, CONST_BITS-PASS1_BITS); + dataptr[5] = (DCTELEM) DESCALE(tmp12, CONST_BITS-PASS1_BITS); + dataptr[7] = (DCTELEM) DESCALE(tmp13, CONST_BITS-PASS1_BITS); + + ctr++; + + if (ctr != DCTSIZE) { + if (ctr == DCTSIZE * 2) + break; /* Done. */ + dataptr += DCTSIZE; /* advance pointer to next row */ + } else + dataptr = workspace; /* switch pointer to extended workspace */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by (8/16)**2 = 1/2**2. + */ + + dataptr = data; + wsptr = workspace; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + wsptr[DCTSIZE*4]; + tmp4 = dataptr[DCTSIZE*4] + wsptr[DCTSIZE*3]; + tmp5 = dataptr[DCTSIZE*5] + wsptr[DCTSIZE*2]; + tmp6 = dataptr[DCTSIZE*6] + wsptr[DCTSIZE*1]; + tmp7 = dataptr[DCTSIZE*7] + wsptr[DCTSIZE*0]; + + tmp10 = tmp0 + tmp7; + tmp14 = tmp0 - tmp7; + tmp11 = tmp1 + tmp6; + tmp15 = tmp1 - tmp6; + tmp12 = tmp2 + tmp5; + tmp16 = tmp2 - tmp5; + tmp13 = tmp3 + tmp4; + tmp17 = tmp3 - tmp4; + + tmp0 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] - wsptr[DCTSIZE*4]; + tmp4 = dataptr[DCTSIZE*4] - wsptr[DCTSIZE*3]; + tmp5 = dataptr[DCTSIZE*5] - wsptr[DCTSIZE*2]; + tmp6 = dataptr[DCTSIZE*6] - wsptr[DCTSIZE*1]; + tmp7 = dataptr[DCTSIZE*7] - wsptr[DCTSIZE*0]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(tmp10 + tmp11 + tmp12 + tmp13, PASS1_BITS+2); + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp13, FIX(1.306562965)) + /* c4[16] = c2[8] */ + MULTIPLY(tmp11 - tmp12, FIX_0_541196100), /* c12[16] = c6[8] */ + CONST_BITS+PASS1_BITS+2); + + tmp10 = MULTIPLY(tmp17 - tmp15, FIX(0.275899379)) + /* c14[16] = c7[8] */ + MULTIPLY(tmp14 - tmp16, FIX(1.387039845)); /* c2[16] = c1[8] */ + + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp15, FIX(1.451774982)) /* c6+c14 */ + + MULTIPLY(tmp16, FIX(2.172734804)), /* c2+10 */ + CONST_BITS+PASS1_BITS+2); + dataptr[DCTSIZE*6] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp14, FIX(0.211164243)) /* c2-c6 */ + - MULTIPLY(tmp17, FIX(1.061594338)), /* c10+c14 */ + CONST_BITS+PASS1_BITS+2); + + /* Odd part */ + + tmp11 = MULTIPLY(tmp0 + tmp1, FIX(1.353318001)) + /* c3 */ + MULTIPLY(tmp6 - tmp7, FIX(0.410524528)); /* c13 */ + tmp12 = MULTIPLY(tmp0 + tmp2, FIX(1.247225013)) + /* c5 */ + MULTIPLY(tmp5 + tmp7, FIX(0.666655658)); /* c11 */ + tmp13 = MULTIPLY(tmp0 + tmp3, FIX(1.093201867)) + /* c7 */ + MULTIPLY(tmp4 - tmp7, FIX(0.897167586)); /* c9 */ + tmp14 = MULTIPLY(tmp1 + tmp2, FIX(0.138617169)) + /* c15 */ + MULTIPLY(tmp6 - tmp5, FIX(1.407403738)); /* c1 */ + tmp15 = MULTIPLY(tmp1 + tmp3, - FIX(0.666655658)) + /* -c11 */ + MULTIPLY(tmp4 + tmp6, - FIX(1.247225013)); /* -c5 */ + tmp16 = MULTIPLY(tmp2 + tmp3, - FIX(1.353318001)) + /* -c3 */ + MULTIPLY(tmp5 - tmp4, FIX(0.410524528)); /* c13 */ + tmp10 = tmp11 + tmp12 + tmp13 - + MULTIPLY(tmp0, FIX(2.286341144)) + /* c7+c5+c3-c1 */ + MULTIPLY(tmp7, FIX(0.779653625)); /* c15+c13-c11+c9 */ + tmp11 += tmp14 + tmp15 + MULTIPLY(tmp1, FIX(0.071888074)) /* c9-c3-c15+c11 */ + - MULTIPLY(tmp6, FIX(1.663905119)); /* c7+c13+c1-c5 */ + tmp12 += tmp14 + tmp16 - MULTIPLY(tmp2, FIX(1.125726048)) /* c7+c5+c15-c3 */ + + MULTIPLY(tmp5, FIX(1.227391138)); /* c9-c11+c1-c13 */ + tmp13 += tmp15 + tmp16 + MULTIPLY(tmp3, FIX(1.065388962)) /* c15+c3+c11-c7 */ + + MULTIPLY(tmp4, FIX(2.167985692)); /* c1+c13+c5-c9 */ + + dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp10, CONST_BITS+PASS1_BITS+2); + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp11, CONST_BITS+PASS1_BITS+2); + dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp12, CONST_BITS+PASS1_BITS+2); + dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp13, CONST_BITS+PASS1_BITS+2); + + dataptr++; /* advance pointer to next column */ + wsptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 16x8 sample block. + * + * 16-point FDCT in pass 1 (rows), 8-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_16x8 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16, tmp17; + INT32 z1; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + /* 16-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/32). */ + + dataptr = data; + ctr = 0; + for (ctr = 0; ctr < DCTSIZE; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[15]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[14]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[13]); + tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[12]); + tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[11]); + tmp5 = GETJSAMPLE(elemptr[5]) + GETJSAMPLE(elemptr[10]); + tmp6 = GETJSAMPLE(elemptr[6]) + GETJSAMPLE(elemptr[9]); + tmp7 = GETJSAMPLE(elemptr[7]) + GETJSAMPLE(elemptr[8]); + + tmp10 = tmp0 + tmp7; + tmp14 = tmp0 - tmp7; + tmp11 = tmp1 + tmp6; + tmp15 = tmp1 - tmp6; + tmp12 = tmp2 + tmp5; + tmp16 = tmp2 - tmp5; + tmp13 = tmp3 + tmp4; + tmp17 = tmp3 - tmp4; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[15]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[14]); + tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[13]); + tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[12]); + tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[11]); + tmp5 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[10]); + tmp6 = GETJSAMPLE(elemptr[6]) - GETJSAMPLE(elemptr[9]); + tmp7 = GETJSAMPLE(elemptr[7]) - GETJSAMPLE(elemptr[8]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + ((tmp10 + tmp11 + tmp12 + tmp13 - 16 * CENTERJSAMPLE) << PASS1_BITS); + dataptr[4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp13, FIX(1.306562965)) + /* c4[16] = c2[8] */ + MULTIPLY(tmp11 - tmp12, FIX_0_541196100), /* c12[16] = c6[8] */ + CONST_BITS-PASS1_BITS); + + tmp10 = MULTIPLY(tmp17 - tmp15, FIX(0.275899379)) + /* c14[16] = c7[8] */ + MULTIPLY(tmp14 - tmp16, FIX(1.387039845)); /* c2[16] = c1[8] */ + + dataptr[2] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp15, FIX(1.451774982)) /* c6+c14 */ + + MULTIPLY(tmp16, FIX(2.172734804)), /* c2+c10 */ + CONST_BITS-PASS1_BITS); + dataptr[6] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp14, FIX(0.211164243)) /* c2-c6 */ + - MULTIPLY(tmp17, FIX(1.061594338)), /* c10+c14 */ + CONST_BITS-PASS1_BITS); + + /* Odd part */ + + tmp11 = MULTIPLY(tmp0 + tmp1, FIX(1.353318001)) + /* c3 */ + MULTIPLY(tmp6 - tmp7, FIX(0.410524528)); /* c13 */ + tmp12 = MULTIPLY(tmp0 + tmp2, FIX(1.247225013)) + /* c5 */ + MULTIPLY(tmp5 + tmp7, FIX(0.666655658)); /* c11 */ + tmp13 = MULTIPLY(tmp0 + tmp3, FIX(1.093201867)) + /* c7 */ + MULTIPLY(tmp4 - tmp7, FIX(0.897167586)); /* c9 */ + tmp14 = MULTIPLY(tmp1 + tmp2, FIX(0.138617169)) + /* c15 */ + MULTIPLY(tmp6 - tmp5, FIX(1.407403738)); /* c1 */ + tmp15 = MULTIPLY(tmp1 + tmp3, - FIX(0.666655658)) + /* -c11 */ + MULTIPLY(tmp4 + tmp6, - FIX(1.247225013)); /* -c5 */ + tmp16 = MULTIPLY(tmp2 + tmp3, - FIX(1.353318001)) + /* -c3 */ + MULTIPLY(tmp5 - tmp4, FIX(0.410524528)); /* c13 */ + tmp10 = tmp11 + tmp12 + tmp13 - + MULTIPLY(tmp0, FIX(2.286341144)) + /* c7+c5+c3-c1 */ + MULTIPLY(tmp7, FIX(0.779653625)); /* c15+c13-c11+c9 */ + tmp11 += tmp14 + tmp15 + MULTIPLY(tmp1, FIX(0.071888074)) /* c9-c3-c15+c11 */ + - MULTIPLY(tmp6, FIX(1.663905119)); /* c7+c13+c1-c5 */ + tmp12 += tmp14 + tmp16 - MULTIPLY(tmp2, FIX(1.125726048)) /* c7+c5+c15-c3 */ + + MULTIPLY(tmp5, FIX(1.227391138)); /* c9-c11+c1-c13 */ + tmp13 += tmp15 + tmp16 + MULTIPLY(tmp3, FIX(1.065388962)) /* c15+c3+c11-c7 */ + + MULTIPLY(tmp4, FIX(2.167985692)); /* c1+c13+c5-c9 */ + + dataptr[1] = (DCTELEM) DESCALE(tmp10, CONST_BITS-PASS1_BITS); + dataptr[3] = (DCTELEM) DESCALE(tmp11, CONST_BITS-PASS1_BITS); + dataptr[5] = (DCTELEM) DESCALE(tmp12, CONST_BITS-PASS1_BITS); + dataptr[7] = (DCTELEM) DESCALE(tmp13, CONST_BITS-PASS1_BITS); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by 8/16 = 1/2. + */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + /* Even part per LL&M figure 1 --- note that published figure is faulty; + * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". + */ + + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; + + tmp10 = tmp0 + tmp3; + tmp12 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp13 = tmp1 - tmp2; + + tmp0 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; + + dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp11, PASS1_BITS+1); + dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp10 - tmp11, PASS1_BITS+1); + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); + dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, FIX_0_765366865), + CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 - MULTIPLY(tmp13, FIX_1_847759065), + CONST_BITS+PASS1_BITS+1); + + /* Odd part per figure 8 --- note paper omits factor of sqrt(2). + * 8-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/16). + * i0..i3 in the paper are tmp0..tmp3 here. + */ + + tmp10 = tmp0 + tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp0 + tmp2; + tmp13 = tmp1 + tmp3; + z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */ + + tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */ + tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */ + tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */ + tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */ + tmp10 = MULTIPLY(tmp10, - FIX_0_899976223); /* c7-c3 */ + tmp11 = MULTIPLY(tmp11, - FIX_2_562915447); /* -c1-c3 */ + tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* c5-c3 */ + tmp13 = MULTIPLY(tmp13, - FIX_1_961570560); /* -c3-c5 */ + + tmp12 += z1; + tmp13 += z1; + + dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp0 + tmp10 + tmp12, + CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp1 + tmp11 + tmp13, + CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp2 + tmp11 + tmp12, + CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp3 + tmp10 + tmp13, + CONST_BITS+PASS1_BITS+1); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 14x7 sample block. + * + * 14-point FDCT in pass 1 (rows), 7-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_14x7 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; + INT32 z1, z2, z3; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Zero bottom row of output coefficient block. */ + MEMZERO(&data[DCTSIZE*7], SIZEOF(DCTELEM) * DCTSIZE); + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + /* 14-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/28). */ + + dataptr = data; + for (ctr = 0; ctr < 7; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[13]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[12]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[11]); + tmp13 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[10]); + tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[9]); + tmp5 = GETJSAMPLE(elemptr[5]) + GETJSAMPLE(elemptr[8]); + tmp6 = GETJSAMPLE(elemptr[6]) + GETJSAMPLE(elemptr[7]); + + tmp10 = tmp0 + tmp6; + tmp14 = tmp0 - tmp6; + tmp11 = tmp1 + tmp5; + tmp15 = tmp1 - tmp5; + tmp12 = tmp2 + tmp4; + tmp16 = tmp2 - tmp4; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[13]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[12]); + tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[11]); + tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[10]); + tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[9]); + tmp5 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[8]); + tmp6 = GETJSAMPLE(elemptr[6]) - GETJSAMPLE(elemptr[7]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + ((tmp10 + tmp11 + tmp12 + tmp13 - 14 * CENTERJSAMPLE) << PASS1_BITS); + tmp13 += tmp13; + dataptr[4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp13, FIX(1.274162392)) + /* c4 */ + MULTIPLY(tmp11 - tmp13, FIX(0.314692123)) - /* c12 */ + MULTIPLY(tmp12 - tmp13, FIX(0.881747734)), /* c8 */ + CONST_BITS-PASS1_BITS); + + tmp10 = MULTIPLY(tmp14 + tmp15, FIX(1.105676686)); /* c6 */ + + dataptr[2] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp14, FIX(0.273079590)) /* c2-c6 */ + + MULTIPLY(tmp16, FIX(0.613604268)), /* c10 */ + CONST_BITS-PASS1_BITS); + dataptr[6] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp15, FIX(1.719280954)) /* c6+c10 */ + - MULTIPLY(tmp16, FIX(1.378756276)), /* c2 */ + CONST_BITS-PASS1_BITS); + + /* Odd part */ + + tmp10 = tmp1 + tmp2; + tmp11 = tmp5 - tmp4; + dataptr[7] = (DCTELEM) ((tmp0 - tmp10 + tmp3 - tmp11 - tmp6) << PASS1_BITS); + tmp3 <<= CONST_BITS; + tmp10 = MULTIPLY(tmp10, - FIX(0.158341681)); /* -c13 */ + tmp11 = MULTIPLY(tmp11, FIX(1.405321284)); /* c1 */ + tmp10 += tmp11 - tmp3; + tmp11 = MULTIPLY(tmp0 + tmp2, FIX(1.197448846)) + /* c5 */ + MULTIPLY(tmp4 + tmp6, FIX(0.752406978)); /* c9 */ + dataptr[5] = (DCTELEM) + DESCALE(tmp10 + tmp11 - MULTIPLY(tmp2, FIX(2.373959773)) /* c3+c5-c13 */ + + MULTIPLY(tmp4, FIX(1.119999435)), /* c1+c11-c9 */ + CONST_BITS-PASS1_BITS); + tmp12 = MULTIPLY(tmp0 + tmp1, FIX(1.334852607)) + /* c3 */ + MULTIPLY(tmp5 - tmp6, FIX(0.467085129)); /* c11 */ + dataptr[3] = (DCTELEM) + DESCALE(tmp10 + tmp12 - MULTIPLY(tmp1, FIX(0.424103948)) /* c3-c9-c13 */ + - MULTIPLY(tmp5, FIX(3.069855259)), /* c1+c5+c11 */ + CONST_BITS-PASS1_BITS); + dataptr[1] = (DCTELEM) + DESCALE(tmp11 + tmp12 + tmp3 + tmp6 - + MULTIPLY(tmp0 + tmp6, FIX(1.126980169)), /* c3+c5-c1 */ + CONST_BITS-PASS1_BITS); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by (8/14)*(8/7) = 32/49, which we + * partially fold into the constant multipliers and final shifting: + * 7-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/14) * 64/49. + */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*6]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*5]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*4]; + tmp3 = dataptr[DCTSIZE*3]; + + tmp10 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*6]; + tmp11 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*5]; + tmp12 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*4]; + + z1 = tmp0 + tmp2; + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(z1 + tmp1 + tmp3, FIX(1.306122449)), /* 64/49 */ + CONST_BITS+PASS1_BITS+1); + tmp3 += tmp3; + z1 -= tmp3; + z1 -= tmp3; + z1 = MULTIPLY(z1, FIX(0.461784020)); /* (c2+c6-c4)/2 */ + z2 = MULTIPLY(tmp0 - tmp2, FIX(1.202428084)); /* (c2+c4-c6)/2 */ + z3 = MULTIPLY(tmp1 - tmp2, FIX(0.411026446)); /* c6 */ + dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + z2 + z3, CONST_BITS+PASS1_BITS+1); + z1 -= z2; + z2 = MULTIPLY(tmp0 - tmp1, FIX(1.151670509)); /* c4 */ + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(z2 + z3 - MULTIPLY(tmp1 - tmp3, FIX(0.923568041)), /* c2+c6-c4 */ + CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 + z2, CONST_BITS+PASS1_BITS+1); + + /* Odd part */ + + tmp1 = MULTIPLY(tmp10 + tmp11, FIX(1.221765677)); /* (c3+c1-c5)/2 */ + tmp2 = MULTIPLY(tmp10 - tmp11, FIX(0.222383464)); /* (c3+c5-c1)/2 */ + tmp0 = tmp1 - tmp2; + tmp1 += tmp2; + tmp2 = MULTIPLY(tmp11 + tmp12, - FIX(1.800824523)); /* -c1 */ + tmp1 += tmp2; + tmp3 = MULTIPLY(tmp10 + tmp12, FIX(0.801442310)); /* c5 */ + tmp0 += tmp3; + tmp2 += tmp3 + MULTIPLY(tmp12, FIX(2.443531355)); /* c3+c1-c5 */ + + dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp0, CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp1, CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp2, CONST_BITS+PASS1_BITS+1); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 12x6 sample block. + * + * 12-point FDCT in pass 1 (rows), 6-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_12x6 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Zero 2 bottom rows of output coefficient block. */ + MEMZERO(&data[DCTSIZE*6], SIZEOF(DCTELEM) * DCTSIZE * 2); + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + /* 12-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/24). */ + + dataptr = data; + for (ctr = 0; ctr < 6; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[11]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[10]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[9]); + tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[8]); + tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[7]); + tmp5 = GETJSAMPLE(elemptr[5]) + GETJSAMPLE(elemptr[6]); + + tmp10 = tmp0 + tmp5; + tmp13 = tmp0 - tmp5; + tmp11 = tmp1 + tmp4; + tmp14 = tmp1 - tmp4; + tmp12 = tmp2 + tmp3; + tmp15 = tmp2 - tmp3; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[11]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[10]); + tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[9]); + tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[8]); + tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[7]); + tmp5 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[6]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + ((tmp10 + tmp11 + tmp12 - 12 * CENTERJSAMPLE) << PASS1_BITS); + dataptr[6] = (DCTELEM) ((tmp13 - tmp14 - tmp15) << PASS1_BITS); + dataptr[4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.224744871)), /* c4 */ + CONST_BITS-PASS1_BITS); + dataptr[2] = (DCTELEM) + DESCALE(tmp14 - tmp15 + MULTIPLY(tmp13 + tmp15, FIX(1.366025404)), /* c2 */ + CONST_BITS-PASS1_BITS); + + /* Odd part */ + + tmp10 = MULTIPLY(tmp1 + tmp4, FIX_0_541196100); /* c9 */ + tmp14 = tmp10 + MULTIPLY(tmp1, FIX_0_765366865); /* c3-c9 */ + tmp15 = tmp10 - MULTIPLY(tmp4, FIX_1_847759065); /* c3+c9 */ + tmp12 = MULTIPLY(tmp0 + tmp2, FIX(1.121971054)); /* c5 */ + tmp13 = MULTIPLY(tmp0 + tmp3, FIX(0.860918669)); /* c7 */ + tmp10 = tmp12 + tmp13 + tmp14 - MULTIPLY(tmp0, FIX(0.580774953)) /* c5+c7-c1 */ + + MULTIPLY(tmp5, FIX(0.184591911)); /* c11 */ + tmp11 = MULTIPLY(tmp2 + tmp3, - FIX(0.184591911)); /* -c11 */ + tmp12 += tmp11 - tmp15 - MULTIPLY(tmp2, FIX(2.339493912)) /* c1+c5-c11 */ + + MULTIPLY(tmp5, FIX(0.860918669)); /* c7 */ + tmp13 += tmp11 - tmp14 + MULTIPLY(tmp3, FIX(0.725788011)) /* c1+c11-c7 */ + - MULTIPLY(tmp5, FIX(1.121971054)); /* c5 */ + tmp11 = tmp15 + MULTIPLY(tmp0 - tmp3, FIX(1.306562965)) /* c3 */ + - MULTIPLY(tmp2 + tmp5, FIX_0_541196100); /* c9 */ + + dataptr[1] = (DCTELEM) DESCALE(tmp10, CONST_BITS-PASS1_BITS); + dataptr[3] = (DCTELEM) DESCALE(tmp11, CONST_BITS-PASS1_BITS); + dataptr[5] = (DCTELEM) DESCALE(tmp12, CONST_BITS-PASS1_BITS); + dataptr[7] = (DCTELEM) DESCALE(tmp13, CONST_BITS-PASS1_BITS); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by (8/12)*(8/6) = 8/9, which we + * partially fold into the constant multipliers and final shifting: + * 6-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/12) * 16/9. + */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*5]; + tmp11 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*4]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*3]; + + tmp10 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + + tmp0 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*5]; + tmp1 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*4]; + tmp2 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*3]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 + tmp11, FIX(1.777777778)), /* 16/9 */ + CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(MULTIPLY(tmp12, FIX(2.177324216)), /* c2 */ + CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp11 - tmp11, FIX(1.257078722)), /* c4 */ + CONST_BITS+PASS1_BITS+1); + + /* Odd part */ + + tmp10 = MULTIPLY(tmp0 + tmp2, FIX(0.650711829)); /* c5 */ + + dataptr[DCTSIZE*1] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp0 + tmp1, FIX(1.777777778)), /* 16/9 */ + CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*3] = (DCTELEM) + DESCALE(MULTIPLY(tmp0 - tmp1 - tmp2, FIX(1.777777778)), /* 16/9 */ + CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*5] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp2 - tmp1, FIX(1.777777778)), /* 16/9 */ + CONST_BITS+PASS1_BITS+1); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 10x5 sample block. + * + * 10-point FDCT in pass 1 (rows), 5-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_10x5 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Zero 3 bottom rows of output coefficient block. */ + MEMZERO(&data[DCTSIZE*5], SIZEOF(DCTELEM) * DCTSIZE * 3); + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + /* 10-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/20). */ + + dataptr = data; + for (ctr = 0; ctr < 5; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[9]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[8]); + tmp12 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[7]); + tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[6]); + tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[5]); + + tmp10 = tmp0 + tmp4; + tmp13 = tmp0 - tmp4; + tmp11 = tmp1 + tmp3; + tmp14 = tmp1 - tmp3; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[9]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[8]); + tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[7]); + tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[6]); + tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[5]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + ((tmp10 + tmp11 + tmp12 - 10 * CENTERJSAMPLE) << PASS1_BITS); + tmp12 += tmp12; + dataptr[4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.144122806)) - /* c4 */ + MULTIPLY(tmp11 - tmp12, FIX(0.437016024)), /* c8 */ + CONST_BITS-PASS1_BITS); + tmp10 = MULTIPLY(tmp13 + tmp14, FIX(0.831253876)); /* c6 */ + dataptr[2] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp13, FIX(0.513743148)), /* c2-c6 */ + CONST_BITS-PASS1_BITS); + dataptr[6] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp14, FIX(2.176250899)), /* c2+c6 */ + CONST_BITS-PASS1_BITS); + + /* Odd part */ + + tmp10 = tmp0 + tmp4; + tmp11 = tmp1 - tmp3; + dataptr[5] = (DCTELEM) ((tmp10 - tmp11 - tmp2) << PASS1_BITS); + tmp2 <<= CONST_BITS; + dataptr[1] = (DCTELEM) + DESCALE(MULTIPLY(tmp0, FIX(1.396802247)) + /* c1 */ + MULTIPLY(tmp1, FIX(1.260073511)) + tmp2 + /* c3 */ + MULTIPLY(tmp3, FIX(0.642039522)) + /* c7 */ + MULTIPLY(tmp4, FIX(0.221231742)), /* c9 */ + CONST_BITS-PASS1_BITS); + tmp12 = MULTIPLY(tmp0 - tmp4, FIX(0.951056516)) - /* (c3+c7)/2 */ + MULTIPLY(tmp1 + tmp3, FIX(0.587785252)); /* (c1-c9)/2 */ + tmp13 = MULTIPLY(tmp10 + tmp11, FIX(0.309016994)) + /* (c3-c7)/2 */ + (tmp11 << (CONST_BITS - 1)) - tmp2; + dataptr[3] = (DCTELEM) DESCALE(tmp12 + tmp13, CONST_BITS-PASS1_BITS); + dataptr[7] = (DCTELEM) DESCALE(tmp12 - tmp13, CONST_BITS-PASS1_BITS); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by (8/10)*(8/5) = 32/25, which we + * fold into the constant multipliers: + * 5-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/10) * 32/25. + */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*4]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*3]; + tmp2 = dataptr[DCTSIZE*2]; + + tmp10 = tmp0 + tmp1; + tmp11 = tmp0 - tmp1; + + tmp0 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*4]; + tmp1 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*3]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 + tmp2, FIX(1.28)), /* 32/25 */ + CONST_BITS+PASS1_BITS); + tmp11 = MULTIPLY(tmp11, FIX(1.011928851)); /* (c2+c4)/2 */ + tmp10 -= tmp2 << 2; + tmp10 = MULTIPLY(tmp10, FIX(0.452548340)); /* (c2-c4)/2 */ + dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(tmp11 + tmp10, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp11 - tmp10, CONST_BITS+PASS1_BITS); + + /* Odd part */ + + tmp10 = MULTIPLY(tmp0 + tmp1, FIX(1.064004961)); /* c3 */ + + dataptr[DCTSIZE*1] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp0, FIX(0.657591230)), /* c1-c3 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*3] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp1, FIX(2.785601151)), /* c1+c3 */ + CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on an 8x4 sample block. + * + * 8-point FDCT in pass 1 (rows), 4-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_8x4 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3; + INT32 tmp10, tmp11, tmp12, tmp13; + INT32 z1; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Zero 4 bottom rows of output coefficient block. */ + MEMZERO(&data[DCTSIZE*4], SIZEOF(DCTELEM) * DCTSIZE * 4); + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + /* We must also scale the output by 8/4 = 2, which we add here. */ + + dataptr = data; + for (ctr = 0; ctr < 4; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part per LL&M figure 1 --- note that published figure is faulty; + * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". + */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[7]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[6]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[5]); + tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[4]); + + tmp10 = tmp0 + tmp3; + tmp12 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp13 = tmp1 - tmp2; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[7]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[6]); + tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[5]); + tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[4]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + ((tmp10 + tmp11 - 8 * CENTERJSAMPLE) << (PASS1_BITS+1)); + dataptr[4] = (DCTELEM) ((tmp10 - tmp11) << (PASS1_BITS+1)); + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); + /* Add fudge factor here for final descale. */ + z1 += ONE << (CONST_BITS-PASS1_BITS-2); + dataptr[2] = (DCTELEM) RIGHT_SHIFT(z1 + MULTIPLY(tmp12, FIX_0_765366865), + CONST_BITS-PASS1_BITS-1); + dataptr[6] = (DCTELEM) RIGHT_SHIFT(z1 - MULTIPLY(tmp13, FIX_1_847759065), + CONST_BITS-PASS1_BITS-1); + + /* Odd part per figure 8 --- note paper omits factor of sqrt(2). + * 8-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/16). + * i0..i3 in the paper are tmp0..tmp3 here. + */ + + tmp10 = tmp0 + tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp0 + tmp2; + tmp13 = tmp1 + tmp3; + z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */ + /* Add fudge factor here for final descale. */ + z1 += ONE << (CONST_BITS-PASS1_BITS-2); + + tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */ + tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */ + tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */ + tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */ + tmp10 = MULTIPLY(tmp10, - FIX_0_899976223); /* c7-c3 */ + tmp11 = MULTIPLY(tmp11, - FIX_2_562915447); /* -c1-c3 */ + tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* c5-c3 */ + tmp13 = MULTIPLY(tmp13, - FIX_1_961570560); /* -c3-c5 */ + + tmp12 += z1; + tmp13 += z1; + + dataptr[1] = (DCTELEM) + RIGHT_SHIFT(tmp0 + tmp10 + tmp12, CONST_BITS-PASS1_BITS-1); + dataptr[3] = (DCTELEM) + RIGHT_SHIFT(tmp1 + tmp11 + tmp13, CONST_BITS-PASS1_BITS-1); + dataptr[5] = (DCTELEM) + RIGHT_SHIFT(tmp2 + tmp11 + tmp12, CONST_BITS-PASS1_BITS-1); + dataptr[7] = (DCTELEM) + RIGHT_SHIFT(tmp3 + tmp10 + tmp13, CONST_BITS-PASS1_BITS-1); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * 4-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/16). + */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + /* Even part */ + + /* Add fudge factor here for final descale. */ + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*3] + (ONE << (PASS1_BITS-1)); + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*2]; + + tmp10 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*3]; + tmp11 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*2]; + + dataptr[DCTSIZE*0] = (DCTELEM) RIGHT_SHIFT(tmp0 + tmp1, PASS1_BITS); + dataptr[DCTSIZE*2] = (DCTELEM) RIGHT_SHIFT(tmp0 - tmp1, PASS1_BITS); + + /* Odd part */ + + tmp0 = MULTIPLY(tmp10 + tmp11, FIX_0_541196100); /* c6 */ + /* Add fudge factor here for final descale. */ + tmp0 += ONE << (CONST_BITS+PASS1_BITS-1); + + dataptr[DCTSIZE*1] = (DCTELEM) + RIGHT_SHIFT(tmp0 + MULTIPLY(tmp10, FIX_0_765366865), /* c2-c6 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*3] = (DCTELEM) + RIGHT_SHIFT(tmp0 - MULTIPLY(tmp11, FIX_1_847759065), /* c2+c6 */ + CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 6x3 sample block. + * + * 6-point FDCT in pass 1 (rows), 3-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_6x3 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2; + INT32 tmp10, tmp11, tmp12; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + /* We scale the results further by 2 as part of output adaption */ + /* scaling for different DCT size. */ + /* 6-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/12). */ + + dataptr = data; + for (ctr = 0; ctr < 3; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[5]); + tmp11 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[4]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[3]); + + tmp10 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[5]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[4]); + tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[3]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + ((tmp10 + tmp11 - 6 * CENTERJSAMPLE) << (PASS1_BITS+1)); + dataptr[2] = (DCTELEM) + DESCALE(MULTIPLY(tmp12, FIX(1.224744871)), /* c2 */ + CONST_BITS-PASS1_BITS-1); + dataptr[4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp11 - tmp11, FIX(0.707106781)), /* c4 */ + CONST_BITS-PASS1_BITS-1); + + /* Odd part */ + + tmp10 = DESCALE(MULTIPLY(tmp0 + tmp2, FIX(0.366025404)), /* c5 */ + CONST_BITS-PASS1_BITS-1); + + dataptr[1] = (DCTELEM) (tmp10 + ((tmp0 + tmp1) << (PASS1_BITS+1))); + dataptr[3] = (DCTELEM) ((tmp0 - tmp1 - tmp2) << (PASS1_BITS+1)); + dataptr[5] = (DCTELEM) (tmp10 + ((tmp2 - tmp1) << (PASS1_BITS+1))); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by (8/6)*(8/3) = 32/9, which we partially + * fold into the constant multipliers (other part was done in pass 1): + * 3-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/6) * 16/9. + */ + + dataptr = data; + for (ctr = 0; ctr < 6; ctr++) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*2]; + tmp1 = dataptr[DCTSIZE*1]; + + tmp2 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*2]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp0 + tmp1, FIX(1.777777778)), /* 16/9 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(MULTIPLY(tmp0 - tmp1 - tmp1, FIX(1.257078722)), /* c2 */ + CONST_BITS+PASS1_BITS); + + /* Odd part */ + + dataptr[DCTSIZE*1] = (DCTELEM) + DESCALE(MULTIPLY(tmp2, FIX(2.177324216)), /* c1 */ + CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 4x2 sample block. + * + * 4-point FDCT in pass 1 (rows), 2-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_4x2 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1; + INT32 tmp10, tmp11; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + /* We must also scale the output by (8/4)*(8/2) = 2**3, which we add here. */ + /* 4-point FDCT kernel, */ + /* cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point FDCT]. */ + + dataptr = data; + for (ctr = 0; ctr < 2; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[3]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[2]); + + tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[3]); + tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[2]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + ((tmp0 + tmp1 - 4 * CENTERJSAMPLE) << (PASS1_BITS+3)); + dataptr[2] = (DCTELEM) ((tmp0 - tmp1) << (PASS1_BITS+3)); + + /* Odd part */ + + tmp0 = MULTIPLY(tmp10 + tmp11, FIX_0_541196100); /* c6 */ + /* Add fudge factor here for final descale. */ + tmp0 += ONE << (CONST_BITS-PASS1_BITS-4); + + dataptr[1] = (DCTELEM) + RIGHT_SHIFT(tmp0 + MULTIPLY(tmp10, FIX_0_765366865), /* c2-c6 */ + CONST_BITS-PASS1_BITS-3); + dataptr[3] = (DCTELEM) + RIGHT_SHIFT(tmp0 - MULTIPLY(tmp11, FIX_1_847759065), /* c2+c6 */ + CONST_BITS-PASS1_BITS-3); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + */ + + dataptr = data; + for (ctr = 0; ctr < 4; ctr++) { + /* Even part */ + + /* Add fudge factor here for final descale. */ + tmp0 = dataptr[DCTSIZE*0] + (ONE << (PASS1_BITS-1)); + tmp1 = dataptr[DCTSIZE*1]; + + dataptr[DCTSIZE*0] = (DCTELEM) RIGHT_SHIFT(tmp0 + tmp1, PASS1_BITS); + + /* Odd part */ + + dataptr[DCTSIZE*1] = (DCTELEM) RIGHT_SHIFT(tmp0 - tmp1, PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 2x1 sample block. + * + * 2-point FDCT in pass 1 (rows), 1-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_2x1 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1; + JSAMPROW elemptr; + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + elemptr = sample_data[0] + start_col; + + tmp0 = GETJSAMPLE(elemptr[0]); + tmp1 = GETJSAMPLE(elemptr[1]); + + /* We leave the results scaled up by an overall factor of 8. + * We must also scale the output by (8/2)*(8/1) = 2**5. + */ + + /* Even part */ + /* Apply unsigned->signed conversion */ + data[0] = (DCTELEM) ((tmp0 + tmp1 - 2 * CENTERJSAMPLE) << 5); + + /* Odd part */ + data[1] = (DCTELEM) ((tmp0 - tmp1) << 5); +} + + +/* + * Perform the forward DCT on an 8x16 sample block. + * + * 8-point FDCT in pass 1 (rows), 16-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_8x16 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16, tmp17; + INT32 z1; + DCTELEM workspace[DCTSIZE2]; + DCTELEM *dataptr; + DCTELEM *wsptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + + dataptr = data; + ctr = 0; + for (;;) { + elemptr = sample_data[ctr] + start_col; + + /* Even part per LL&M figure 1 --- note that published figure is faulty; + * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". + */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[7]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[6]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[5]); + tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[4]); + + tmp10 = tmp0 + tmp3; + tmp12 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp13 = tmp1 - tmp2; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[7]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[6]); + tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[5]); + tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[4]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) ((tmp10 + tmp11 - 8 * CENTERJSAMPLE) << PASS1_BITS); + dataptr[4] = (DCTELEM) ((tmp10 - tmp11) << PASS1_BITS); + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); + dataptr[2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, FIX_0_765366865), + CONST_BITS-PASS1_BITS); + dataptr[6] = (DCTELEM) DESCALE(z1 - MULTIPLY(tmp13, FIX_1_847759065), + CONST_BITS-PASS1_BITS); + + /* Odd part per figure 8 --- note paper omits factor of sqrt(2). + * 8-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/16). + * i0..i3 in the paper are tmp0..tmp3 here. + */ + + tmp10 = tmp0 + tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp0 + tmp2; + tmp13 = tmp1 + tmp3; + z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */ + + tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */ + tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */ + tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */ + tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */ + tmp10 = MULTIPLY(tmp10, - FIX_0_899976223); /* c7-c3 */ + tmp11 = MULTIPLY(tmp11, - FIX_2_562915447); /* -c1-c3 */ + tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* c5-c3 */ + tmp13 = MULTIPLY(tmp13, - FIX_1_961570560); /* -c3-c5 */ + + tmp12 += z1; + tmp13 += z1; + + dataptr[1] = (DCTELEM) DESCALE(tmp0 + tmp10 + tmp12, CONST_BITS-PASS1_BITS); + dataptr[3] = (DCTELEM) DESCALE(tmp1 + tmp11 + tmp13, CONST_BITS-PASS1_BITS); + dataptr[5] = (DCTELEM) DESCALE(tmp2 + tmp11 + tmp12, CONST_BITS-PASS1_BITS); + dataptr[7] = (DCTELEM) DESCALE(tmp3 + tmp10 + tmp13, CONST_BITS-PASS1_BITS); + + ctr++; + + if (ctr != DCTSIZE) { + if (ctr == DCTSIZE * 2) + break; /* Done. */ + dataptr += DCTSIZE; /* advance pointer to next row */ + } else + dataptr = workspace; /* switch pointer to extended workspace */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by 8/16 = 1/2. + * 16-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/32). + */ + + dataptr = data; + wsptr = workspace; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + wsptr[DCTSIZE*4]; + tmp4 = dataptr[DCTSIZE*4] + wsptr[DCTSIZE*3]; + tmp5 = dataptr[DCTSIZE*5] + wsptr[DCTSIZE*2]; + tmp6 = dataptr[DCTSIZE*6] + wsptr[DCTSIZE*1]; + tmp7 = dataptr[DCTSIZE*7] + wsptr[DCTSIZE*0]; + + tmp10 = tmp0 + tmp7; + tmp14 = tmp0 - tmp7; + tmp11 = tmp1 + tmp6; + tmp15 = tmp1 - tmp6; + tmp12 = tmp2 + tmp5; + tmp16 = tmp2 - tmp5; + tmp13 = tmp3 + tmp4; + tmp17 = tmp3 - tmp4; + + tmp0 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] - wsptr[DCTSIZE*4]; + tmp4 = dataptr[DCTSIZE*4] - wsptr[DCTSIZE*3]; + tmp5 = dataptr[DCTSIZE*5] - wsptr[DCTSIZE*2]; + tmp6 = dataptr[DCTSIZE*6] - wsptr[DCTSIZE*1]; + tmp7 = dataptr[DCTSIZE*7] - wsptr[DCTSIZE*0]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(tmp10 + tmp11 + tmp12 + tmp13, PASS1_BITS+1); + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp13, FIX(1.306562965)) + /* c4[16] = c2[8] */ + MULTIPLY(tmp11 - tmp12, FIX_0_541196100), /* c12[16] = c6[8] */ + CONST_BITS+PASS1_BITS+1); + + tmp10 = MULTIPLY(tmp17 - tmp15, FIX(0.275899379)) + /* c14[16] = c7[8] */ + MULTIPLY(tmp14 - tmp16, FIX(1.387039845)); /* c2[16] = c1[8] */ + + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp15, FIX(1.451774982)) /* c6+c14 */ + + MULTIPLY(tmp16, FIX(2.172734804)), /* c2+c10 */ + CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*6] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp14, FIX(0.211164243)) /* c2-c6 */ + - MULTIPLY(tmp17, FIX(1.061594338)), /* c10+c14 */ + CONST_BITS+PASS1_BITS+1); + + /* Odd part */ + + tmp11 = MULTIPLY(tmp0 + tmp1, FIX(1.353318001)) + /* c3 */ + MULTIPLY(tmp6 - tmp7, FIX(0.410524528)); /* c13 */ + tmp12 = MULTIPLY(tmp0 + tmp2, FIX(1.247225013)) + /* c5 */ + MULTIPLY(tmp5 + tmp7, FIX(0.666655658)); /* c11 */ + tmp13 = MULTIPLY(tmp0 + tmp3, FIX(1.093201867)) + /* c7 */ + MULTIPLY(tmp4 - tmp7, FIX(0.897167586)); /* c9 */ + tmp14 = MULTIPLY(tmp1 + tmp2, FIX(0.138617169)) + /* c15 */ + MULTIPLY(tmp6 - tmp5, FIX(1.407403738)); /* c1 */ + tmp15 = MULTIPLY(tmp1 + tmp3, - FIX(0.666655658)) + /* -c11 */ + MULTIPLY(tmp4 + tmp6, - FIX(1.247225013)); /* -c5 */ + tmp16 = MULTIPLY(tmp2 + tmp3, - FIX(1.353318001)) + /* -c3 */ + MULTIPLY(tmp5 - tmp4, FIX(0.410524528)); /* c13 */ + tmp10 = tmp11 + tmp12 + tmp13 - + MULTIPLY(tmp0, FIX(2.286341144)) + /* c7+c5+c3-c1 */ + MULTIPLY(tmp7, FIX(0.779653625)); /* c15+c13-c11+c9 */ + tmp11 += tmp14 + tmp15 + MULTIPLY(tmp1, FIX(0.071888074)) /* c9-c3-c15+c11 */ + - MULTIPLY(tmp6, FIX(1.663905119)); /* c7+c13+c1-c5 */ + tmp12 += tmp14 + tmp16 - MULTIPLY(tmp2, FIX(1.125726048)) /* c7+c5+c15-c3 */ + + MULTIPLY(tmp5, FIX(1.227391138)); /* c9-c11+c1-c13 */ + tmp13 += tmp15 + tmp16 + MULTIPLY(tmp3, FIX(1.065388962)) /* c15+c3+c11-c7 */ + + MULTIPLY(tmp4, FIX(2.167985692)); /* c1+c13+c5-c9 */ + + dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp10, CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp11, CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp12, CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp13, CONST_BITS+PASS1_BITS+1); + + dataptr++; /* advance pointer to next column */ + wsptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 7x14 sample block. + * + * 7-point FDCT in pass 1 (rows), 14-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_7x14 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; + INT32 z1, z2, z3; + DCTELEM workspace[8*6]; + DCTELEM *dataptr; + DCTELEM *wsptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + /* 7-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/14). */ + + dataptr = data; + ctr = 0; + for (;;) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[6]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[5]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[4]); + tmp3 = GETJSAMPLE(elemptr[3]); + + tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[6]); + tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[5]); + tmp12 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[4]); + + z1 = tmp0 + tmp2; + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + ((z1 + tmp1 + tmp3 - 7 * CENTERJSAMPLE) << PASS1_BITS); + tmp3 += tmp3; + z1 -= tmp3; + z1 -= tmp3; + z1 = MULTIPLY(z1, FIX(0.353553391)); /* (c2+c6-c4)/2 */ + z2 = MULTIPLY(tmp0 - tmp2, FIX(0.920609002)); /* (c2+c4-c6)/2 */ + z3 = MULTIPLY(tmp1 - tmp2, FIX(0.314692123)); /* c6 */ + dataptr[2] = (DCTELEM) DESCALE(z1 + z2 + z3, CONST_BITS-PASS1_BITS); + z1 -= z2; + z2 = MULTIPLY(tmp0 - tmp1, FIX(0.881747734)); /* c4 */ + dataptr[4] = (DCTELEM) + DESCALE(z2 + z3 - MULTIPLY(tmp1 - tmp3, FIX(0.707106781)), /* c2+c6-c4 */ + CONST_BITS-PASS1_BITS); + dataptr[6] = (DCTELEM) DESCALE(z1 + z2, CONST_BITS-PASS1_BITS); + + /* Odd part */ + + tmp1 = MULTIPLY(tmp10 + tmp11, FIX(0.935414347)); /* (c3+c1-c5)/2 */ + tmp2 = MULTIPLY(tmp10 - tmp11, FIX(0.170262339)); /* (c3+c5-c1)/2 */ + tmp0 = tmp1 - tmp2; + tmp1 += tmp2; + tmp2 = MULTIPLY(tmp11 + tmp12, - FIX(1.378756276)); /* -c1 */ + tmp1 += tmp2; + tmp3 = MULTIPLY(tmp10 + tmp12, FIX(0.613604268)); /* c5 */ + tmp0 += tmp3; + tmp2 += tmp3 + MULTIPLY(tmp12, FIX(1.870828693)); /* c3+c1-c5 */ + + dataptr[1] = (DCTELEM) DESCALE(tmp0, CONST_BITS-PASS1_BITS); + dataptr[3] = (DCTELEM) DESCALE(tmp1, CONST_BITS-PASS1_BITS); + dataptr[5] = (DCTELEM) DESCALE(tmp2, CONST_BITS-PASS1_BITS); + + ctr++; + + if (ctr != DCTSIZE) { + if (ctr == 14) + break; /* Done. */ + dataptr += DCTSIZE; /* advance pointer to next row */ + } else + dataptr = workspace; /* switch pointer to extended workspace */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by (8/7)*(8/14) = 32/49, which we + * fold into the constant multipliers: + * 14-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/28) * 32/49. + */ + + dataptr = data; + wsptr = workspace; + for (ctr = 0; ctr < 7; ctr++) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*5]; + tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*4]; + tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*3]; + tmp13 = dataptr[DCTSIZE*3] + wsptr[DCTSIZE*2]; + tmp4 = dataptr[DCTSIZE*4] + wsptr[DCTSIZE*1]; + tmp5 = dataptr[DCTSIZE*5] + wsptr[DCTSIZE*0]; + tmp6 = dataptr[DCTSIZE*6] + dataptr[DCTSIZE*7]; + + tmp10 = tmp0 + tmp6; + tmp14 = tmp0 - tmp6; + tmp11 = tmp1 + tmp5; + tmp15 = tmp1 - tmp5; + tmp12 = tmp2 + tmp4; + tmp16 = tmp2 - tmp4; + + tmp0 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*5]; + tmp1 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*4]; + tmp2 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*3]; + tmp3 = dataptr[DCTSIZE*3] - wsptr[DCTSIZE*2]; + tmp4 = dataptr[DCTSIZE*4] - wsptr[DCTSIZE*1]; + tmp5 = dataptr[DCTSIZE*5] - wsptr[DCTSIZE*0]; + tmp6 = dataptr[DCTSIZE*6] - dataptr[DCTSIZE*7]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 + tmp11 + tmp12 + tmp13, + FIX(0.653061224)), /* 32/49 */ + CONST_BITS+PASS1_BITS); + tmp13 += tmp13; + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp13, FIX(0.832106052)) + /* c4 */ + MULTIPLY(tmp11 - tmp13, FIX(0.205513223)) - /* c12 */ + MULTIPLY(tmp12 - tmp13, FIX(0.575835255)), /* c8 */ + CONST_BITS+PASS1_BITS); + + tmp10 = MULTIPLY(tmp14 + tmp15, FIX(0.722074570)); /* c6 */ + + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp14, FIX(0.178337691)) /* c2-c6 */ + + MULTIPLY(tmp16, FIX(0.400721155)), /* c10 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*6] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp15, FIX(1.122795725)) /* c6+c10 */ + - MULTIPLY(tmp16, FIX(0.900412262)), /* c2 */ + CONST_BITS+PASS1_BITS); + + /* Odd part */ + + tmp10 = tmp1 + tmp2; + tmp11 = tmp5 - tmp4; + dataptr[DCTSIZE*7] = (DCTELEM) + DESCALE(MULTIPLY(tmp0 - tmp10 + tmp3 - tmp11 - tmp6, + FIX(0.653061224)), /* 32/49 */ + CONST_BITS+PASS1_BITS); + tmp3 = MULTIPLY(tmp3 , FIX(0.653061224)); /* 32/49 */ + tmp10 = MULTIPLY(tmp10, - FIX(0.103406812)); /* -c13 */ + tmp11 = MULTIPLY(tmp11, FIX(0.917760839)); /* c1 */ + tmp10 += tmp11 - tmp3; + tmp11 = MULTIPLY(tmp0 + tmp2, FIX(0.782007410)) + /* c5 */ + MULTIPLY(tmp4 + tmp6, FIX(0.491367823)); /* c9 */ + dataptr[DCTSIZE*5] = (DCTELEM) + DESCALE(tmp10 + tmp11 - MULTIPLY(tmp2, FIX(1.550341076)) /* c3+c5-c13 */ + + MULTIPLY(tmp4, FIX(0.731428202)), /* c1+c11-c9 */ + CONST_BITS+PASS1_BITS); + tmp12 = MULTIPLY(tmp0 + tmp1, FIX(0.871740478)) + /* c3 */ + MULTIPLY(tmp5 - tmp6, FIX(0.305035186)); /* c11 */ + dataptr[DCTSIZE*3] = (DCTELEM) + DESCALE(tmp10 + tmp12 - MULTIPLY(tmp1, FIX(0.276965844)) /* c3-c9-c13 */ + - MULTIPLY(tmp5, FIX(2.004803435)), /* c1+c5+c11 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*1] = (DCTELEM) + DESCALE(tmp11 + tmp12 + tmp3 + - MULTIPLY(tmp0, FIX(0.735987049)) /* c3+c5-c1 */ + - MULTIPLY(tmp6, FIX(0.082925825)), /* c9-c11-c13 */ + CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + wsptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 6x12 sample block. + * + * 6-point FDCT in pass 1 (rows), 12-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_6x12 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; + DCTELEM workspace[8*4]; + DCTELEM *dataptr; + DCTELEM *wsptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + /* 6-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/12). */ + + dataptr = data; + ctr = 0; + for (;;) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[5]); + tmp11 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[4]); + tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[3]); + + tmp10 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[5]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[4]); + tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[3]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + ((tmp10 + tmp11 - 6 * CENTERJSAMPLE) << PASS1_BITS); + dataptr[2] = (DCTELEM) + DESCALE(MULTIPLY(tmp12, FIX(1.224744871)), /* c2 */ + CONST_BITS-PASS1_BITS); + dataptr[4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp11 - tmp11, FIX(0.707106781)), /* c4 */ + CONST_BITS-PASS1_BITS); + + /* Odd part */ + + tmp10 = DESCALE(MULTIPLY(tmp0 + tmp2, FIX(0.366025404)), /* c5 */ + CONST_BITS-PASS1_BITS); + + dataptr[1] = (DCTELEM) (tmp10 + ((tmp0 + tmp1) << PASS1_BITS)); + dataptr[3] = (DCTELEM) ((tmp0 - tmp1 - tmp2) << PASS1_BITS); + dataptr[5] = (DCTELEM) (tmp10 + ((tmp2 - tmp1) << PASS1_BITS)); + + ctr++; + + if (ctr != DCTSIZE) { + if (ctr == 12) + break; /* Done. */ + dataptr += DCTSIZE; /* advance pointer to next row */ + } else + dataptr = workspace; /* switch pointer to extended workspace */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by (8/6)*(8/12) = 8/9, which we + * fold into the constant multipliers: + * 12-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/24) * 8/9. + */ + + dataptr = data; + wsptr = workspace; + for (ctr = 0; ctr < 6; ctr++) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*3]; + tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*2]; + tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*1]; + tmp3 = dataptr[DCTSIZE*3] + wsptr[DCTSIZE*0]; + tmp4 = dataptr[DCTSIZE*4] + dataptr[DCTSIZE*7]; + tmp5 = dataptr[DCTSIZE*5] + dataptr[DCTSIZE*6]; + + tmp10 = tmp0 + tmp5; + tmp13 = tmp0 - tmp5; + tmp11 = tmp1 + tmp4; + tmp14 = tmp1 - tmp4; + tmp12 = tmp2 + tmp3; + tmp15 = tmp2 - tmp3; + + tmp0 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*3]; + tmp1 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*2]; + tmp2 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*1]; + tmp3 = dataptr[DCTSIZE*3] - wsptr[DCTSIZE*0]; + tmp4 = dataptr[DCTSIZE*4] - dataptr[DCTSIZE*7]; + tmp5 = dataptr[DCTSIZE*5] - dataptr[DCTSIZE*6]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 + tmp11 + tmp12, FIX(0.888888889)), /* 8/9 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*6] = (DCTELEM) + DESCALE(MULTIPLY(tmp13 - tmp14 - tmp15, FIX(0.888888889)), /* 8/9 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.088662108)), /* c4 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(MULTIPLY(tmp14 - tmp15, FIX(0.888888889)) + /* 8/9 */ + MULTIPLY(tmp13 + tmp15, FIX(1.214244803)), /* c2 */ + CONST_BITS+PASS1_BITS); + + /* Odd part */ + + tmp10 = MULTIPLY(tmp1 + tmp4, FIX(0.481063200)); /* c9 */ + tmp14 = tmp10 + MULTIPLY(tmp1, FIX(0.680326102)); /* c3-c9 */ + tmp15 = tmp10 - MULTIPLY(tmp4, FIX(1.642452502)); /* c3+c9 */ + tmp12 = MULTIPLY(tmp0 + tmp2, FIX(0.997307603)); /* c5 */ + tmp13 = MULTIPLY(tmp0 + tmp3, FIX(0.765261039)); /* c7 */ + tmp10 = tmp12 + tmp13 + tmp14 - MULTIPLY(tmp0, FIX(0.516244403)) /* c5+c7-c1 */ + + MULTIPLY(tmp5, FIX(0.164081699)); /* c11 */ + tmp11 = MULTIPLY(tmp2 + tmp3, - FIX(0.164081699)); /* -c11 */ + tmp12 += tmp11 - tmp15 - MULTIPLY(tmp2, FIX(2.079550144)) /* c1+c5-c11 */ + + MULTIPLY(tmp5, FIX(0.765261039)); /* c7 */ + tmp13 += tmp11 - tmp14 + MULTIPLY(tmp3, FIX(0.645144899)) /* c1+c11-c7 */ + - MULTIPLY(tmp5, FIX(0.997307603)); /* c5 */ + tmp11 = tmp15 + MULTIPLY(tmp0 - tmp3, FIX(1.161389302)) /* c3 */ + - MULTIPLY(tmp2 + tmp5, FIX(0.481063200)); /* c9 */ + + dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp10, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp11, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp12, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp13, CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + wsptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 5x10 sample block. + * + * 5-point FDCT in pass 1 (rows), 10-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_5x10 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4; + INT32 tmp10, tmp11, tmp12, tmp13, tmp14; + DCTELEM workspace[8*2]; + DCTELEM *dataptr; + DCTELEM *wsptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + /* 5-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/10). */ + + dataptr = data; + ctr = 0; + for (;;) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[4]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[3]); + tmp2 = GETJSAMPLE(elemptr[2]); + + tmp10 = tmp0 + tmp1; + tmp11 = tmp0 - tmp1; + + tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[4]); + tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[3]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + ((tmp10 + tmp2 - 5 * CENTERJSAMPLE) << PASS1_BITS); + tmp11 = MULTIPLY(tmp11, FIX(0.790569415)); /* (c2+c4)/2 */ + tmp10 -= tmp2 << 2; + tmp10 = MULTIPLY(tmp10, FIX(0.353553391)); /* (c2-c4)/2 */ + dataptr[2] = (DCTELEM) DESCALE(tmp11 + tmp10, CONST_BITS-PASS1_BITS); + dataptr[4] = (DCTELEM) DESCALE(tmp11 - tmp10, CONST_BITS-PASS1_BITS); + + /* Odd part */ + + tmp10 = MULTIPLY(tmp0 + tmp1, FIX(0.831253876)); /* c3 */ + + dataptr[1] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp0, FIX(0.513743148)), /* c1-c3 */ + CONST_BITS-PASS1_BITS); + dataptr[3] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp1, FIX(2.176250899)), /* c1+c3 */ + CONST_BITS-PASS1_BITS); + + ctr++; + + if (ctr != DCTSIZE) { + if (ctr == 10) + break; /* Done. */ + dataptr += DCTSIZE; /* advance pointer to next row */ + } else + dataptr = workspace; /* switch pointer to extended workspace */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by (8/5)*(8/10) = 32/25, which we + * fold into the constant multipliers: + * 10-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/20) * 32/25. + */ + + dataptr = data; + wsptr = workspace; + for (ctr = 0; ctr < 5; ctr++) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*1]; + tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*0]; + tmp12 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*7]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*6]; + tmp4 = dataptr[DCTSIZE*4] + dataptr[DCTSIZE*5]; + + tmp10 = tmp0 + tmp4; + tmp13 = tmp0 - tmp4; + tmp11 = tmp1 + tmp3; + tmp14 = tmp1 - tmp3; + + tmp0 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*1]; + tmp1 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*0]; + tmp2 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*7]; + tmp3 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*6]; + tmp4 = dataptr[DCTSIZE*4] - dataptr[DCTSIZE*5]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 + tmp11 + tmp12, FIX(1.28)), /* 32/25 */ + CONST_BITS+PASS1_BITS); + tmp12 += tmp12; + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.464477191)) - /* c4 */ + MULTIPLY(tmp11 - tmp12, FIX(0.559380511)), /* c8 */ + CONST_BITS+PASS1_BITS); + tmp10 = MULTIPLY(tmp13 + tmp14, FIX(1.064004961)); /* c6 */ + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp13, FIX(0.657591230)), /* c2-c6 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*6] = (DCTELEM) + DESCALE(tmp10 - MULTIPLY(tmp14, FIX(2.785601151)), /* c2+c6 */ + CONST_BITS+PASS1_BITS); + + /* Odd part */ + + tmp10 = tmp0 + tmp4; + tmp11 = tmp1 - tmp3; + dataptr[DCTSIZE*5] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp11 - tmp2, FIX(1.28)), /* 32/25 */ + CONST_BITS+PASS1_BITS); + tmp2 = MULTIPLY(tmp2, FIX(1.28)); /* 32/25 */ + dataptr[DCTSIZE*1] = (DCTELEM) + DESCALE(MULTIPLY(tmp0, FIX(1.787906876)) + /* c1 */ + MULTIPLY(tmp1, FIX(1.612894094)) + tmp2 + /* c3 */ + MULTIPLY(tmp3, FIX(0.821810588)) + /* c7 */ + MULTIPLY(tmp4, FIX(0.283176630)), /* c9 */ + CONST_BITS+PASS1_BITS); + tmp12 = MULTIPLY(tmp0 - tmp4, FIX(1.217352341)) - /* (c3+c7)/2 */ + MULTIPLY(tmp1 + tmp3, FIX(0.752365123)); /* (c1-c9)/2 */ + tmp13 = MULTIPLY(tmp10 + tmp11, FIX(0.395541753)) + /* (c3-c7)/2 */ + MULTIPLY(tmp11, FIX(0.64)) - tmp2; /* 16/25 */ + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp12 + tmp13, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp12 - tmp13, CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + wsptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 4x8 sample block. + * + * 4-point FDCT in pass 1 (rows), 8-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_4x8 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3; + INT32 tmp10, tmp11, tmp12, tmp13; + INT32 z1; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + /* We must also scale the output by 8/4 = 2, which we add here. */ + /* 4-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/16). */ + + dataptr = data; + for (ctr = 0; ctr < DCTSIZE; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[3]); + tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[2]); + + tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[3]); + tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[2]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + ((tmp0 + tmp1 - 4 * CENTERJSAMPLE) << (PASS1_BITS+1)); + dataptr[2] = (DCTELEM) ((tmp0 - tmp1) << (PASS1_BITS+1)); + + /* Odd part */ + + tmp0 = MULTIPLY(tmp10 + tmp11, FIX_0_541196100); /* c6 */ + /* Add fudge factor here for final descale. */ + tmp0 += ONE << (CONST_BITS-PASS1_BITS-2); + + dataptr[1] = (DCTELEM) + RIGHT_SHIFT(tmp0 + MULTIPLY(tmp10, FIX_0_765366865), /* c2-c6 */ + CONST_BITS-PASS1_BITS-1); + dataptr[3] = (DCTELEM) + RIGHT_SHIFT(tmp0 - MULTIPLY(tmp11, FIX_1_847759065), /* c2+c6 */ + CONST_BITS-PASS1_BITS-1); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + */ + + dataptr = data; + for (ctr = 0; ctr < 4; ctr++) { + /* Even part per LL&M figure 1 --- note that published figure is faulty; + * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". + */ + + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; + + /* Add fudge factor here for final descale. */ + tmp10 = tmp0 + tmp3 + (ONE << (PASS1_BITS-1)); + tmp12 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp13 = tmp1 - tmp2; + + tmp0 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; + + dataptr[DCTSIZE*0] = (DCTELEM) RIGHT_SHIFT(tmp10 + tmp11, PASS1_BITS); + dataptr[DCTSIZE*4] = (DCTELEM) RIGHT_SHIFT(tmp10 - tmp11, PASS1_BITS); + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); + /* Add fudge factor here for final descale. */ + z1 += ONE << (CONST_BITS+PASS1_BITS-1); + dataptr[DCTSIZE*2] = (DCTELEM) + RIGHT_SHIFT(z1 + MULTIPLY(tmp12, FIX_0_765366865), CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*6] = (DCTELEM) + RIGHT_SHIFT(z1 - MULTIPLY(tmp13, FIX_1_847759065), CONST_BITS+PASS1_BITS); + + /* Odd part per figure 8 --- note paper omits factor of sqrt(2). + * 8-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/16). + * i0..i3 in the paper are tmp0..tmp3 here. + */ + + tmp10 = tmp0 + tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp0 + tmp2; + tmp13 = tmp1 + tmp3; + z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */ + /* Add fudge factor here for final descale. */ + z1 += ONE << (CONST_BITS+PASS1_BITS-1); + + tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */ + tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */ + tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */ + tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */ + tmp10 = MULTIPLY(tmp10, - FIX_0_899976223); /* c7-c3 */ + tmp11 = MULTIPLY(tmp11, - FIX_2_562915447); /* -c1-c3 */ + tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* c5-c3 */ + tmp13 = MULTIPLY(tmp13, - FIX_1_961570560); /* -c3-c5 */ + + tmp12 += z1; + tmp13 += z1; + + dataptr[DCTSIZE*1] = (DCTELEM) + RIGHT_SHIFT(tmp0 + tmp10 + tmp12, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*3] = (DCTELEM) + RIGHT_SHIFT(tmp1 + tmp11 + tmp13, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*5] = (DCTELEM) + RIGHT_SHIFT(tmp2 + tmp11 + tmp12, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*7] = (DCTELEM) + RIGHT_SHIFT(tmp3 + tmp10 + tmp13, CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 3x6 sample block. + * + * 3-point FDCT in pass 1 (rows), 6-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_3x6 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1, tmp2; + INT32 tmp10, tmp11, tmp12; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + /* We scale the results further by 2 as part of output adaption */ + /* scaling for different DCT size. */ + /* 3-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/6). */ + + dataptr = data; + for (ctr = 0; ctr < 6; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[2]); + tmp1 = GETJSAMPLE(elemptr[1]); + + tmp2 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[2]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) + ((tmp0 + tmp1 - 3 * CENTERJSAMPLE) << (PASS1_BITS+1)); + dataptr[2] = (DCTELEM) + DESCALE(MULTIPLY(tmp0 - tmp1 - tmp1, FIX(0.707106781)), /* c2 */ + CONST_BITS-PASS1_BITS-1); + + /* Odd part */ + + dataptr[1] = (DCTELEM) + DESCALE(MULTIPLY(tmp2, FIX(1.224744871)), /* c1 */ + CONST_BITS-PASS1_BITS-1); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We remove the PASS1_BITS scaling, but leave the results scaled up + * by an overall factor of 8. + * We must also scale the output by (8/6)*(8/3) = 32/9, which we partially + * fold into the constant multipliers (other part was done in pass 1): + * 6-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/12) * 16/9. + */ + + dataptr = data; + for (ctr = 0; ctr < 3; ctr++) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*5]; + tmp11 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*4]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*3]; + + tmp10 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + + tmp0 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*5]; + tmp1 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*4]; + tmp2 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*3]; + + dataptr[DCTSIZE*0] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 + tmp11, FIX(1.777777778)), /* 16/9 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(MULTIPLY(tmp12, FIX(2.177324216)), /* c2 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*4] = (DCTELEM) + DESCALE(MULTIPLY(tmp10 - tmp11 - tmp11, FIX(1.257078722)), /* c4 */ + CONST_BITS+PASS1_BITS); + + /* Odd part */ + + tmp10 = MULTIPLY(tmp0 + tmp2, FIX(0.650711829)); /* c5 */ + + dataptr[DCTSIZE*1] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp0 + tmp1, FIX(1.777777778)), /* 16/9 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*3] = (DCTELEM) + DESCALE(MULTIPLY(tmp0 - tmp1 - tmp2, FIX(1.777777778)), /* 16/9 */ + CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*5] = (DCTELEM) + DESCALE(tmp10 + MULTIPLY(tmp2 - tmp1, FIX(1.777777778)), /* 16/9 */ + CONST_BITS+PASS1_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 2x4 sample block. + * + * 2-point FDCT in pass 1 (rows), 4-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_2x4 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1; + INT32 tmp10, tmp11; + DCTELEM *dataptr; + JSAMPROW elemptr; + int ctr; + SHIFT_TEMPS + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true DCT. */ + /* We must also scale the output by (8/2)*(8/4) = 2**3, which we add here. */ + + dataptr = data; + for (ctr = 0; ctr < 4; ctr++) { + elemptr = sample_data[ctr] + start_col; + + /* Even part */ + + tmp0 = GETJSAMPLE(elemptr[0]); + tmp1 = GETJSAMPLE(elemptr[1]); + + /* Apply unsigned->signed conversion */ + dataptr[0] = (DCTELEM) ((tmp0 + tmp1 - 2 * CENTERJSAMPLE) << 3); + + /* Odd part */ + + dataptr[1] = (DCTELEM) ((tmp0 - tmp1) << 3); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. + * We leave the results scaled up by an overall factor of 8. + * 4-point FDCT kernel, + * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point FDCT]. + */ + + dataptr = data; + for (ctr = 0; ctr < 2; ctr++) { + /* Even part */ + + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*3]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*2]; + + tmp10 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*3]; + tmp11 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*2]; + + dataptr[DCTSIZE*0] = (DCTELEM) (tmp0 + tmp1); + dataptr[DCTSIZE*2] = (DCTELEM) (tmp0 - tmp1); + + /* Odd part */ + + tmp0 = MULTIPLY(tmp10 + tmp11, FIX_0_541196100); /* c6 */ + /* Add fudge factor here for final descale. */ + tmp0 += ONE << (CONST_BITS-1); + + dataptr[DCTSIZE*1] = (DCTELEM) + RIGHT_SHIFT(tmp0 + MULTIPLY(tmp10, FIX_0_765366865), /* c2-c6 */ + CONST_BITS); + dataptr[DCTSIZE*3] = (DCTELEM) + RIGHT_SHIFT(tmp0 - MULTIPLY(tmp11, FIX_1_847759065), /* c2+c6 */ + CONST_BITS); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* + * Perform the forward DCT on a 1x2 sample block. + * + * 1-point FDCT in pass 1 (rows), 2-point in pass 2 (columns). + */ + +GLOBAL(void) +jpeg_fdct_1x2 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) +{ + INT32 tmp0, tmp1; + + /* Pre-zero output coefficient block. */ + MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + + tmp0 = GETJSAMPLE(sample_data[0][start_col]); + tmp1 = GETJSAMPLE(sample_data[1][start_col]); + + /* We leave the results scaled up by an overall factor of 8. + * We must also scale the output by (8/1)*(8/2) = 2**5. + */ + + /* Even part */ + /* Apply unsigned->signed conversion */ + data[DCTSIZE*0] = (DCTELEM) ((tmp0 + tmp1 - 2 * CENTERJSAMPLE) << 5); + + /* Odd part */ + data[DCTSIZE*1] = (DCTELEM) ((tmp0 - tmp1) << 5); +} + +#endif /* DCT_SCALING_SUPPORTED */ #endif /* DCT_ISLOW_SUPPORTED */ diff --git a/reactos/dll/3rdparty/libjpeg/jidctflt.c b/reactos/dll/3rdparty/libjpeg/jidctflt.c index 0188ce3dfcd..23ae9d333b7 100644 --- a/reactos/dll/3rdparty/libjpeg/jidctflt.c +++ b/reactos/dll/3rdparty/libjpeg/jidctflt.c @@ -2,6 +2,7 @@ * jidctflt.c * * Copyright (C) 1994-1998, Thomas G. Lane. + * Modified 2010 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -76,10 +77,9 @@ jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr, FLOAT_MULT_TYPE * quantptr; FAST_FLOAT * wsptr; JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); + JSAMPLE *range_limit = cinfo->sample_range_limit; int ctr; FAST_FLOAT workspace[DCTSIZE2]; /* buffers data between passes */ - SHIFT_TEMPS /* Pass 1: process columns from input, store into work array. */ @@ -152,12 +152,12 @@ jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr, tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); /* 2*c4 */ z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */ - tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */ - tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */ + tmp10 = z5 - z12 * ((FAST_FLOAT) 1.082392200); /* 2*(c2-c6) */ + tmp12 = z5 - z10 * ((FAST_FLOAT) 2.613125930); /* 2*(c2+c6) */ tmp6 = tmp12 - tmp7; /* phase 2 */ tmp5 = tmp11 - tmp6; - tmp4 = tmp10 + tmp5; + tmp4 = tmp10 - tmp5; wsptr[DCTSIZE*0] = tmp0 + tmp7; wsptr[DCTSIZE*7] = tmp0 - tmp7; @@ -165,8 +165,8 @@ jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr, wsptr[DCTSIZE*6] = tmp1 - tmp6; wsptr[DCTSIZE*2] = tmp2 + tmp5; wsptr[DCTSIZE*5] = tmp2 - tmp5; - wsptr[DCTSIZE*4] = tmp3 + tmp4; - wsptr[DCTSIZE*3] = tmp3 - tmp4; + wsptr[DCTSIZE*3] = tmp3 + tmp4; + wsptr[DCTSIZE*4] = tmp3 - tmp4; inptr++; /* advance pointers to next column */ quantptr++; @@ -174,7 +174,6 @@ jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr, } /* Pass 2: process rows from work array, store into output array. */ - /* Note that we must descale the results by a factor of 8 == 2**3. */ wsptr = workspace; for (ctr = 0; ctr < DCTSIZE; ctr++) { @@ -187,8 +186,10 @@ jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Even part */ - tmp10 = wsptr[0] + wsptr[4]; - tmp11 = wsptr[0] - wsptr[4]; + /* Apply signed->unsigned and prepare float->int conversion */ + z5 = wsptr[0] + ((FAST_FLOAT) CENTERJSAMPLE + (FAST_FLOAT) 0.5); + tmp10 = z5 + wsptr[4]; + tmp11 = z5 - wsptr[4]; tmp13 = wsptr[2] + wsptr[6]; tmp12 = (wsptr[2] - wsptr[6]) * ((FAST_FLOAT) 1.414213562) - tmp13; @@ -209,31 +210,23 @@ jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr, tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */ - tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */ - tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */ + tmp10 = z5 - z12 * ((FAST_FLOAT) 1.082392200); /* 2*(c2-c6) */ + tmp12 = z5 - z10 * ((FAST_FLOAT) 2.613125930); /* 2*(c2+c6) */ tmp6 = tmp12 - tmp7; tmp5 = tmp11 - tmp6; - tmp4 = tmp10 + tmp5; + tmp4 = tmp10 - tmp5; - /* Final output stage: scale down by a factor of 8 and range-limit */ + /* Final output stage: float->int conversion and range-limit */ - outptr[0] = range_limit[(int) DESCALE((INT32) (tmp0 + tmp7), 3) - & RANGE_MASK]; - outptr[7] = range_limit[(int) DESCALE((INT32) (tmp0 - tmp7), 3) - & RANGE_MASK]; - outptr[1] = range_limit[(int) DESCALE((INT32) (tmp1 + tmp6), 3) - & RANGE_MASK]; - outptr[6] = range_limit[(int) DESCALE((INT32) (tmp1 - tmp6), 3) - & RANGE_MASK]; - outptr[2] = range_limit[(int) DESCALE((INT32) (tmp2 + tmp5), 3) - & RANGE_MASK]; - outptr[5] = range_limit[(int) DESCALE((INT32) (tmp2 - tmp5), 3) - & RANGE_MASK]; - outptr[4] = range_limit[(int) DESCALE((INT32) (tmp3 + tmp4), 3) - & RANGE_MASK]; - outptr[3] = range_limit[(int) DESCALE((INT32) (tmp3 - tmp4), 3) - & RANGE_MASK]; + outptr[0] = range_limit[((int) (tmp0 + tmp7)) & RANGE_MASK]; + outptr[7] = range_limit[((int) (tmp0 - tmp7)) & RANGE_MASK]; + outptr[1] = range_limit[((int) (tmp1 + tmp6)) & RANGE_MASK]; + outptr[6] = range_limit[((int) (tmp1 - tmp6)) & RANGE_MASK]; + outptr[2] = range_limit[((int) (tmp2 + tmp5)) & RANGE_MASK]; + outptr[5] = range_limit[((int) (tmp2 - tmp5)) & RANGE_MASK]; + outptr[3] = range_limit[((int) (tmp3 + tmp4)) & RANGE_MASK]; + outptr[4] = range_limit[((int) (tmp3 - tmp4)) & RANGE_MASK]; wsptr += DCTSIZE; /* advance pointer to next row */ } diff --git a/reactos/dll/3rdparty/libjpeg/jidctint.c b/reactos/dll/3rdparty/libjpeg/jidctint.c index a72b3207caf..dcdf7ce4547 100644 --- a/reactos/dll/3rdparty/libjpeg/jidctint.c +++ b/reactos/dll/3rdparty/libjpeg/jidctint.c @@ -2,6 +2,7 @@ * jidctint.c * * Copyright (C) 1991-1998, Thomas G. Lane. + * Modification developed 2002-2009 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -23,6 +24,28 @@ * The advantage of this method is that no data path contains more than one * multiplication; this allows a very simple and accurate implementation in * scaled fixed-point arithmetic, with a minimal number of shifts. + * + * We also provide IDCT routines with various output sample block sizes for + * direct resolution reduction or enlargement and for direct resolving the + * common 2x1 and 1x2 subsampling cases without additional resampling: NxN + * (N=1...16), 2NxN, and Nx2N (N=1...8) pixels for one 8x8 input DCT block. + * + * For N<8 we simply take the corresponding low-frequency coefficients of + * the 8x8 input DCT block and apply an NxN point IDCT on the sub-block + * to yield the downscaled outputs. + * This can be seen as direct low-pass downsampling from the DCT domain + * point of view rather than the usual spatial domain point of view, + * yielding significant computational savings and results at least + * as good as common bilinear (averaging) spatial downsampling. + * + * For N>8 we apply a partial NxN IDCT on the 8 input coefficients as + * lower frequencies and higher frequencies assumed to be zero. + * It turns out that the computational effort is similar to the 8x8 IDCT + * regarding the output size. + * Furthermore, the scaling and descaling is the same for all IDCT sizes. + * + * CAUTION: We rely on the FIX() macro except for the N=1,2,4,8 cases + * since there would be too many additional constants to pre-calculate. */ #define JPEG_INTERNALS @@ -38,7 +61,7 @@ */ #if DCTSIZE != 8 - Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ + Sorry, this code only copes with 8x8 DCT blocks. /* deliberate syntax err */ #endif @@ -151,7 +174,7 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, { INT32 tmp0, tmp1, tmp2, tmp3; INT32 tmp10, tmp11, tmp12, tmp13; - INT32 z1, z2, z3, z4, z5; + INT32 z1, z2, z3; JCOEFPTR inptr; ISLOW_MULT_TYPE * quantptr; int * wsptr; @@ -165,6 +188,2657 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Note results are scaled up by sqrt(8) compared to a true IDCT; */ /* furthermore, we scale the results by 2**PASS1_BITS. */ + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; ctr--) { + /* Due to quantization, we will usually find that many of the input + * coefficients are zero, especially the AC terms. We can exploit this + * by short-circuiting the IDCT calculation for any column in which all + * the AC terms are zero. In that case each output is equal to the + * DC coefficient (with scale factor as needed). + * With typical images and quantization tables, half or more of the + * column DCT calculations can be simplified this way. + */ + + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && + inptr[DCTSIZE*7] == 0) { + /* AC terms all zero */ + int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; + + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + wsptr[DCTSIZE*2] = dcval; + wsptr[DCTSIZE*3] = dcval; + wsptr[DCTSIZE*4] = dcval; + wsptr[DCTSIZE*5] = dcval; + wsptr[DCTSIZE*6] = dcval; + wsptr[DCTSIZE*7] = dcval; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + continue; + } + + /* Even part: reverse the even part of the forward DCT. */ + /* The rotator is sqrt(2)*c(-6). */ + + z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); + tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); + + z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z2 <<= CONST_BITS; + z3 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + z2 += ONE << (CONST_BITS-PASS1_BITS-1); + + tmp0 = z2 + z3; + tmp1 = z2 - z3; + + tmp10 = tmp0 + tmp2; + tmp13 = tmp0 - tmp2; + tmp11 = tmp1 + tmp3; + tmp12 = tmp1 - tmp3; + + /* Odd part per figure 8; the matrix is unitary and hence its + * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. + */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + tmp1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + tmp3 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + + z2 = tmp0 + tmp2; + z3 = tmp1 + tmp3; + + z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* sqrt(2) * c3 */ + z2 = MULTIPLY(z2, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z3 = MULTIPLY(z3, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + z2 += z1; + z3 += z1; + + z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + tmp0 += z1 + z2; + tmp3 += z1 + z3; + + z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp1 += z1 + z3; + tmp2 += z1 + z2; + + /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ + + wsptr[DCTSIZE*0] = (int) RIGHT_SHIFT(tmp10 + tmp3, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*7] = (int) RIGHT_SHIFT(tmp10 - tmp3, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*1] = (int) RIGHT_SHIFT(tmp11 + tmp2, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*6] = (int) RIGHT_SHIFT(tmp11 - tmp2, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*2] = (int) RIGHT_SHIFT(tmp12 + tmp1, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*5] = (int) RIGHT_SHIFT(tmp12 - tmp1, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*3] = (int) RIGHT_SHIFT(tmp13 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*4] = (int) RIGHT_SHIFT(tmp13 - tmp0, CONST_BITS-PASS1_BITS); + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + } + + /* Pass 2: process rows from work array, store into output array. */ + /* Note that we must descale the results by a factor of 8 == 2**3, */ + /* and also undo the PASS1_BITS scaling. */ + + wsptr = workspace; + for (ctr = 0; ctr < DCTSIZE; ctr++) { + outptr = output_buf[ctr] + output_col; + /* Rows of zeroes can be exploited in the same way as we did with columns. + * However, the column calculation has created many nonzero AC terms, so + * the simplification applies less often (typically 5% to 10% of the time). + * On machines with very fast multiplication, it's possible that the + * test takes more time than it's worth. In that case this section + * may be commented out. + */ + +#ifndef NO_ZERO_ROW_TEST + if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 && + wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { + /* AC terms all zero */ + JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3) + & RANGE_MASK]; + + outptr[0] = dcval; + outptr[1] = dcval; + outptr[2] = dcval; + outptr[3] = dcval; + outptr[4] = dcval; + outptr[5] = dcval; + outptr[6] = dcval; + outptr[7] = dcval; + + wsptr += DCTSIZE; /* advance pointer to next row */ + continue; + } +#endif + + /* Even part: reverse the even part of the forward DCT. */ + /* The rotator is sqrt(2)*c(-6). */ + + z2 = (INT32) wsptr[2]; + z3 = (INT32) wsptr[6]; + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); + tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); + + /* Add fudge factor here for final descale. */ + z2 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + z3 = (INT32) wsptr[4]; + + tmp0 = (z2 + z3) << CONST_BITS; + tmp1 = (z2 - z3) << CONST_BITS; + + tmp10 = tmp0 + tmp2; + tmp13 = tmp0 - tmp2; + tmp11 = tmp1 + tmp3; + tmp12 = tmp1 - tmp3; + + /* Odd part per figure 8; the matrix is unitary and hence its + * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. + */ + + tmp0 = (INT32) wsptr[7]; + tmp1 = (INT32) wsptr[5]; + tmp2 = (INT32) wsptr[3]; + tmp3 = (INT32) wsptr[1]; + + z2 = tmp0 + tmp2; + z3 = tmp1 + tmp3; + + z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* sqrt(2) * c3 */ + z2 = MULTIPLY(z2, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z3 = MULTIPLY(z3, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + z2 += z1; + z3 += z1; + + z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + tmp0 += z1 + z2; + tmp3 += z1 + z3; + + z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp1 += z1 + z3; + tmp2 += z1 + z2; + + /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp13 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp13 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + +#ifdef IDCT_SCALING_SUPPORTED + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 7x7 output block. + * + * Optimized algorithm with 12 multiplications in the 1-D kernel. + * cK represents sqrt(2) * cos(K*pi/14). + */ + +GLOBAL(void) +jpeg_idct_7x7 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp1, tmp2, tmp10, tmp11, tmp12, tmp13; + INT32 z1, z2, z3; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[7*7]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 7; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp13 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp13 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + tmp13 += ONE << (CONST_BITS-PASS1_BITS-1); + + z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + tmp10 = MULTIPLY(z2 - z3, FIX(0.881747734)); /* c4 */ + tmp12 = MULTIPLY(z1 - z2, FIX(0.314692123)); /* c6 */ + tmp11 = tmp10 + tmp12 + tmp13 - MULTIPLY(z2, FIX(1.841218003)); /* c2+c4-c6 */ + tmp0 = z1 + z3; + z2 -= tmp0; + tmp0 = MULTIPLY(tmp0, FIX(1.274162392)) + tmp13; /* c2 */ + tmp10 += tmp0 - MULTIPLY(z3, FIX(0.077722536)); /* c2-c4-c6 */ + tmp12 += tmp0 - MULTIPLY(z1, FIX(2.470602249)); /* c2+c4+c6 */ + tmp13 += MULTIPLY(z2, FIX(1.414213562)); /* c0 */ + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + + tmp1 = MULTIPLY(z1 + z2, FIX(0.935414347)); /* (c3+c1-c5)/2 */ + tmp2 = MULTIPLY(z1 - z2, FIX(0.170262339)); /* (c3+c5-c1)/2 */ + tmp0 = tmp1 - tmp2; + tmp1 += tmp2; + tmp2 = MULTIPLY(z2 + z3, - FIX(1.378756276)); /* -c1 */ + tmp1 += tmp2; + z2 = MULTIPLY(z1 + z3, FIX(0.613604268)); /* c5 */ + tmp0 += z2; + tmp2 += z2 + MULTIPLY(z3, FIX(1.870828693)); /* c3+c1-c5 */ + + /* Final output stage */ + + wsptr[7*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[7*6] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS); + wsptr[7*1] = (int) RIGHT_SHIFT(tmp11 + tmp1, CONST_BITS-PASS1_BITS); + wsptr[7*5] = (int) RIGHT_SHIFT(tmp11 - tmp1, CONST_BITS-PASS1_BITS); + wsptr[7*2] = (int) RIGHT_SHIFT(tmp12 + tmp2, CONST_BITS-PASS1_BITS); + wsptr[7*4] = (int) RIGHT_SHIFT(tmp12 - tmp2, CONST_BITS-PASS1_BITS); + wsptr[7*3] = (int) RIGHT_SHIFT(tmp13, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 7 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 7; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + tmp13 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + tmp13 <<= CONST_BITS; + + z1 = (INT32) wsptr[2]; + z2 = (INT32) wsptr[4]; + z3 = (INT32) wsptr[6]; + + tmp10 = MULTIPLY(z2 - z3, FIX(0.881747734)); /* c4 */ + tmp12 = MULTIPLY(z1 - z2, FIX(0.314692123)); /* c6 */ + tmp11 = tmp10 + tmp12 + tmp13 - MULTIPLY(z2, FIX(1.841218003)); /* c2+c4-c6 */ + tmp0 = z1 + z3; + z2 -= tmp0; + tmp0 = MULTIPLY(tmp0, FIX(1.274162392)) + tmp13; /* c2 */ + tmp10 += tmp0 - MULTIPLY(z3, FIX(0.077722536)); /* c2-c4-c6 */ + tmp12 += tmp0 - MULTIPLY(z1, FIX(2.470602249)); /* c2+c4+c6 */ + tmp13 += MULTIPLY(z2, FIX(1.414213562)); /* c0 */ + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + + tmp1 = MULTIPLY(z1 + z2, FIX(0.935414347)); /* (c3+c1-c5)/2 */ + tmp2 = MULTIPLY(z1 - z2, FIX(0.170262339)); /* (c3+c5-c1)/2 */ + tmp0 = tmp1 - tmp2; + tmp1 += tmp2; + tmp2 = MULTIPLY(z2 + z3, - FIX(1.378756276)); /* -c1 */ + tmp1 += tmp2; + z2 = MULTIPLY(z1 + z3, FIX(0.613604268)); /* c5 */ + tmp0 += z2; + tmp2 += z2 + MULTIPLY(z3, FIX(1.870828693)); /* c3+c1-c5 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 7; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 6x6 output block. + * + * Optimized algorithm with 3 multiplications in the 1-D kernel. + * cK represents sqrt(2) * cos(K*pi/12). + */ + +GLOBAL(void) +jpeg_idct_6x6 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp1, tmp2, tmp10, tmp11, tmp12; + INT32 z1, z2, z3; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[6*6]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 6; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp0 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + tmp0 += ONE << (CONST_BITS-PASS1_BITS-1); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + tmp10 = MULTIPLY(tmp2, FIX(0.707106781)); /* c4 */ + tmp1 = tmp0 + tmp10; + tmp11 = RIGHT_SHIFT(tmp0 - tmp10 - tmp10, CONST_BITS-PASS1_BITS); + tmp10 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + tmp0 = MULTIPLY(tmp10, FIX(1.224744871)); /* c2 */ + tmp10 = tmp1 + tmp0; + tmp12 = tmp1 - tmp0; + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp1 = MULTIPLY(z1 + z3, FIX(0.366025404)); /* c5 */ + tmp0 = tmp1 + ((z1 + z2) << CONST_BITS); + tmp2 = tmp1 + ((z3 - z2) << CONST_BITS); + tmp1 = (z1 - z2 - z3) << PASS1_BITS; + + /* Final output stage */ + + wsptr[6*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[6*5] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS); + wsptr[6*1] = (int) (tmp11 + tmp1); + wsptr[6*4] = (int) (tmp11 - tmp1); + wsptr[6*2] = (int) RIGHT_SHIFT(tmp12 + tmp2, CONST_BITS-PASS1_BITS); + wsptr[6*3] = (int) RIGHT_SHIFT(tmp12 - tmp2, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 6 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 6; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + tmp0 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + tmp0 <<= CONST_BITS; + tmp2 = (INT32) wsptr[4]; + tmp10 = MULTIPLY(tmp2, FIX(0.707106781)); /* c4 */ + tmp1 = tmp0 + tmp10; + tmp11 = tmp0 - tmp10 - tmp10; + tmp10 = (INT32) wsptr[2]; + tmp0 = MULTIPLY(tmp10, FIX(1.224744871)); /* c2 */ + tmp10 = tmp1 + tmp0; + tmp12 = tmp1 - tmp0; + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + tmp1 = MULTIPLY(z1 + z3, FIX(0.366025404)); /* c5 */ + tmp0 = tmp1 + ((z1 + z2) << CONST_BITS); + tmp2 = tmp1 + ((z3 - z2) << CONST_BITS); + tmp1 = (z1 - z2 - z3) << CONST_BITS; + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 6; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 5x5 output block. + * + * Optimized algorithm with 5 multiplications in the 1-D kernel. + * cK represents sqrt(2) * cos(K*pi/10). + */ + +GLOBAL(void) +jpeg_idct_5x5 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp1, tmp10, tmp11, tmp12; + INT32 z1, z2, z3; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[5*5]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 5; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp12 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp12 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + tmp12 += ONE << (CONST_BITS-PASS1_BITS-1); + tmp0 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + tmp1 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z1 = MULTIPLY(tmp0 + tmp1, FIX(0.790569415)); /* (c2+c4)/2 */ + z2 = MULTIPLY(tmp0 - tmp1, FIX(0.353553391)); /* (c2-c4)/2 */ + z3 = tmp12 + z2; + tmp10 = z3 + z1; + tmp11 = z3 - z1; + tmp12 -= z2 << 2; + + /* Odd part */ + + z2 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + + z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c3 */ + tmp0 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c1-c3 */ + tmp1 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c1+c3 */ + + /* Final output stage */ + + wsptr[5*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[5*4] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS); + wsptr[5*1] = (int) RIGHT_SHIFT(tmp11 + tmp1, CONST_BITS-PASS1_BITS); + wsptr[5*3] = (int) RIGHT_SHIFT(tmp11 - tmp1, CONST_BITS-PASS1_BITS); + wsptr[5*2] = (int) RIGHT_SHIFT(tmp12, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 5 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 5; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + tmp12 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + tmp12 <<= CONST_BITS; + tmp0 = (INT32) wsptr[2]; + tmp1 = (INT32) wsptr[4]; + z1 = MULTIPLY(tmp0 + tmp1, FIX(0.790569415)); /* (c2+c4)/2 */ + z2 = MULTIPLY(tmp0 - tmp1, FIX(0.353553391)); /* (c2-c4)/2 */ + z3 = tmp12 + z2; + tmp10 = z3 + z1; + tmp11 = z3 - z1; + tmp12 -= z2 << 2; + + /* Odd part */ + + z2 = (INT32) wsptr[1]; + z3 = (INT32) wsptr[3]; + + z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c3 */ + tmp0 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c1-c3 */ + tmp1 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c1+c3 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 5; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 4x4 output block. + * + * Optimized algorithm with 3 multiplications in the 1-D kernel. + * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point IDCT]. + */ + +GLOBAL(void) +jpeg_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp2, tmp10, tmp12; + INT32 z1, z2, z3; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[4*4]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 4; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + + tmp10 = (tmp0 + tmp2) << PASS1_BITS; + tmp12 = (tmp0 - tmp2) << PASS1_BITS; + + /* Odd part */ + /* Same rotation as in the even part of the 8x8 LL&M IDCT */ + + z2 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ + /* Add fudge factor here for final descale. */ + z1 += ONE << (CONST_BITS-PASS1_BITS-1); + tmp0 = RIGHT_SHIFT(z1 + MULTIPLY(z2, FIX_0_765366865), /* c2-c6 */ + CONST_BITS-PASS1_BITS); + tmp2 = RIGHT_SHIFT(z1 - MULTIPLY(z3, FIX_1_847759065), /* c2+c6 */ + CONST_BITS-PASS1_BITS); + + /* Final output stage */ + + wsptr[4*0] = (int) (tmp10 + tmp0); + wsptr[4*3] = (int) (tmp10 - tmp0); + wsptr[4*1] = (int) (tmp12 + tmp2); + wsptr[4*2] = (int) (tmp12 - tmp2); + } + + /* Pass 2: process 4 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 4; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + tmp0 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + tmp2 = (INT32) wsptr[2]; + + tmp10 = (tmp0 + tmp2) << CONST_BITS; + tmp12 = (tmp0 - tmp2) << CONST_BITS; + + /* Odd part */ + /* Same rotation as in the even part of the 8x8 LL&M IDCT */ + + z2 = (INT32) wsptr[1]; + z3 = (INT32) wsptr[3]; + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ + tmp0 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ + tmp2 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 4; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 3x3 output block. + * + * Optimized algorithm with 2 multiplications in the 1-D kernel. + * cK represents sqrt(2) * cos(K*pi/6). + */ + +GLOBAL(void) +jpeg_idct_3x3 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp2, tmp10, tmp12; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[3*3]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 3; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp0 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + tmp0 += ONE << (CONST_BITS-PASS1_BITS-1); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + tmp12 = MULTIPLY(tmp2, FIX(0.707106781)); /* c2 */ + tmp10 = tmp0 + tmp12; + tmp2 = tmp0 - tmp12 - tmp12; + + /* Odd part */ + + tmp12 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + tmp0 = MULTIPLY(tmp12, FIX(1.224744871)); /* c1 */ + + /* Final output stage */ + + wsptr[3*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[3*2] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS); + wsptr[3*1] = (int) RIGHT_SHIFT(tmp2, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 3 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 3; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + tmp0 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + tmp0 <<= CONST_BITS; + tmp2 = (INT32) wsptr[2]; + tmp12 = MULTIPLY(tmp2, FIX(0.707106781)); /* c2 */ + tmp10 = tmp0 + tmp12; + tmp2 = tmp0 - tmp12 - tmp12; + + /* Odd part */ + + tmp12 = (INT32) wsptr[1]; + tmp0 = MULTIPLY(tmp12, FIX(1.224744871)); /* c1 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 3; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 2x2 output block. + * + * Multiplication-less algorithm. + */ + +GLOBAL(void) +jpeg_idct_2x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + ISLOW_MULT_TYPE * quantptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + SHIFT_TEMPS + + /* Pass 1: process columns from input. */ + + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + + /* Column 0 */ + tmp4 = DEQUANTIZE(coef_block[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp5 = DEQUANTIZE(coef_block[DCTSIZE*1], quantptr[DCTSIZE*1]); + /* Add fudge factor here for final descale. */ + tmp4 += ONE << 2; + + tmp0 = tmp4 + tmp5; + tmp2 = tmp4 - tmp5; + + /* Column 1 */ + tmp4 = DEQUANTIZE(coef_block[DCTSIZE*0+1], quantptr[DCTSIZE*0+1]); + tmp5 = DEQUANTIZE(coef_block[DCTSIZE*1+1], quantptr[DCTSIZE*1+1]); + + tmp1 = tmp4 + tmp5; + tmp3 = tmp4 - tmp5; + + /* Pass 2: process 2 rows, store into output array. */ + + /* Row 0 */ + outptr = output_buf[0] + output_col; + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp0 + tmp1, 3) & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp0 - tmp1, 3) & RANGE_MASK]; + + /* Row 1 */ + outptr = output_buf[1] + output_col; + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp2 + tmp3, 3) & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp2 - tmp3, 3) & RANGE_MASK]; +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 1x1 output block. + * + * We hardly need an inverse DCT routine for this: just take the + * average pixel value, which is one-eighth of the DC coefficient. + */ + +GLOBAL(void) +jpeg_idct_1x1 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + int dcval; + ISLOW_MULT_TYPE * quantptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + SHIFT_TEMPS + + /* 1x1 is trivial: just take the DC coefficient divided by 8. */ + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + dcval = DEQUANTIZE(coef_block[0], quantptr[0]); + dcval = (int) DESCALE((INT32) dcval, 3); + + output_buf[0][output_col] = range_limit[dcval & RANGE_MASK]; +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 9x9 output block. + * + * Optimized algorithm with 10 multiplications in the 1-D kernel. + * cK represents sqrt(2) * cos(K*pi/18). + */ + +GLOBAL(void) +jpeg_idct_9x9 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp10, tmp11, tmp12, tmp13, tmp14; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[8*9]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp0 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + tmp0 += ONE << (CONST_BITS-PASS1_BITS-1); + + z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + tmp3 = MULTIPLY(z3, FIX(0.707106781)); /* c6 */ + tmp1 = tmp0 + tmp3; + tmp2 = tmp0 - tmp3 - tmp3; + + tmp0 = MULTIPLY(z1 - z2, FIX(0.707106781)); /* c6 */ + tmp11 = tmp2 + tmp0; + tmp14 = tmp2 - tmp0 - tmp0; + + tmp0 = MULTIPLY(z1 + z2, FIX(1.328926049)); /* c2 */ + tmp2 = MULTIPLY(z1, FIX(1.083350441)); /* c4 */ + tmp3 = MULTIPLY(z2, FIX(0.245575608)); /* c8 */ + + tmp10 = tmp1 + tmp0 - tmp3; + tmp12 = tmp1 - tmp0 + tmp2; + tmp13 = tmp1 - tmp2 + tmp3; + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + z2 = MULTIPLY(z2, - FIX(1.224744871)); /* -c3 */ + + tmp2 = MULTIPLY(z1 + z3, FIX(0.909038955)); /* c5 */ + tmp3 = MULTIPLY(z1 + z4, FIX(0.483689525)); /* c7 */ + tmp0 = tmp2 + tmp3 - z2; + tmp1 = MULTIPLY(z3 - z4, FIX(1.392728481)); /* c1 */ + tmp2 += z2 - tmp1; + tmp3 += z2 + tmp1; + tmp1 = MULTIPLY(z1 - z3 - z4, FIX(1.224744871)); /* c3 */ + + /* Final output stage */ + + wsptr[8*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[8*8] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS); + wsptr[8*1] = (int) RIGHT_SHIFT(tmp11 + tmp1, CONST_BITS-PASS1_BITS); + wsptr[8*7] = (int) RIGHT_SHIFT(tmp11 - tmp1, CONST_BITS-PASS1_BITS); + wsptr[8*2] = (int) RIGHT_SHIFT(tmp12 + tmp2, CONST_BITS-PASS1_BITS); + wsptr[8*6] = (int) RIGHT_SHIFT(tmp12 - tmp2, CONST_BITS-PASS1_BITS); + wsptr[8*3] = (int) RIGHT_SHIFT(tmp13 + tmp3, CONST_BITS-PASS1_BITS); + wsptr[8*5] = (int) RIGHT_SHIFT(tmp13 - tmp3, CONST_BITS-PASS1_BITS); + wsptr[8*4] = (int) RIGHT_SHIFT(tmp14, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 9 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 9; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + tmp0 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + tmp0 <<= CONST_BITS; + + z1 = (INT32) wsptr[2]; + z2 = (INT32) wsptr[4]; + z3 = (INT32) wsptr[6]; + + tmp3 = MULTIPLY(z3, FIX(0.707106781)); /* c6 */ + tmp1 = tmp0 + tmp3; + tmp2 = tmp0 - tmp3 - tmp3; + + tmp0 = MULTIPLY(z1 - z2, FIX(0.707106781)); /* c6 */ + tmp11 = tmp2 + tmp0; + tmp14 = tmp2 - tmp0 - tmp0; + + tmp0 = MULTIPLY(z1 + z2, FIX(1.328926049)); /* c2 */ + tmp2 = MULTIPLY(z1, FIX(1.083350441)); /* c4 */ + tmp3 = MULTIPLY(z2, FIX(0.245575608)); /* c8 */ + + tmp10 = tmp1 + tmp0 - tmp3; + tmp12 = tmp1 - tmp0 + tmp2; + tmp13 = tmp1 - tmp2 + tmp3; + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + z4 = (INT32) wsptr[7]; + + z2 = MULTIPLY(z2, - FIX(1.224744871)); /* -c3 */ + + tmp2 = MULTIPLY(z1 + z3, FIX(0.909038955)); /* c5 */ + tmp3 = MULTIPLY(z1 + z4, FIX(0.483689525)); /* c7 */ + tmp0 = tmp2 + tmp3 - z2; + tmp1 = MULTIPLY(z3 - z4, FIX(1.392728481)); /* c1 */ + tmp2 += z2 - tmp1; + tmp3 += z2 + tmp1; + tmp1 = MULTIPLY(z1 - z3 - z4, FIX(1.224744871)); /* c3 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp13 + tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp13 - tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 8; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 10x10 output block. + * + * Optimized algorithm with 12 multiplications in the 1-D kernel. + * cK represents sqrt(2) * cos(K*pi/20). + */ + +GLOBAL(void) +jpeg_idct_10x10 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp10, tmp11, tmp12, tmp13, tmp14; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24; + INT32 z1, z2, z3, z4, z5; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[8*10]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + z3 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + z3 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + z3 += ONE << (CONST_BITS-PASS1_BITS-1); + z4 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z1 = MULTIPLY(z4, FIX(1.144122806)); /* c4 */ + z2 = MULTIPLY(z4, FIX(0.437016024)); /* c8 */ + tmp10 = z3 + z1; + tmp11 = z3 - z2; + + tmp22 = RIGHT_SHIFT(z3 - ((z1 - z2) << 1), /* c0 = (c4-c8)*2 */ + CONST_BITS-PASS1_BITS); + + z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c6 */ + tmp12 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c2-c6 */ + tmp13 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c2+c6 */ + + tmp20 = tmp10 + tmp12; + tmp24 = tmp10 - tmp12; + tmp21 = tmp11 + tmp13; + tmp23 = tmp11 - tmp13; + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + tmp11 = z2 + z4; + tmp13 = z2 - z4; + + tmp12 = MULTIPLY(tmp13, FIX(0.309016994)); /* (c3-c7)/2 */ + z5 = z3 << CONST_BITS; + + z2 = MULTIPLY(tmp11, FIX(0.951056516)); /* (c3+c7)/2 */ + z4 = z5 + tmp12; + + tmp10 = MULTIPLY(z1, FIX(1.396802247)) + z2 + z4; /* c1 */ + tmp14 = MULTIPLY(z1, FIX(0.221231742)) - z2 + z4; /* c9 */ + + z2 = MULTIPLY(tmp11, FIX(0.587785252)); /* (c1-c9)/2 */ + z4 = z5 - tmp12 - (tmp13 << (CONST_BITS - 1)); + + tmp12 = (z1 - tmp13 - z3) << PASS1_BITS; + + tmp11 = MULTIPLY(z1, FIX(1.260073511)) - z2 - z4; /* c3 */ + tmp13 = MULTIPLY(z1, FIX(0.642039522)) - z2 + z4; /* c7 */ + + /* Final output stage */ + + wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*9] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*8] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*2] = (int) (tmp22 + tmp12); + wsptr[8*7] = (int) (tmp22 - tmp12); + wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS); + wsptr[8*6] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS); + wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); + wsptr[8*5] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 10 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 10; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + z3 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + z3 <<= CONST_BITS; + z4 = (INT32) wsptr[4]; + z1 = MULTIPLY(z4, FIX(1.144122806)); /* c4 */ + z2 = MULTIPLY(z4, FIX(0.437016024)); /* c8 */ + tmp10 = z3 + z1; + tmp11 = z3 - z2; + + tmp22 = z3 - ((z1 - z2) << 1); /* c0 = (c4-c8)*2 */ + + z2 = (INT32) wsptr[2]; + z3 = (INT32) wsptr[6]; + + z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c6 */ + tmp12 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c2-c6 */ + tmp13 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c2+c6 */ + + tmp20 = tmp10 + tmp12; + tmp24 = tmp10 - tmp12; + tmp21 = tmp11 + tmp13; + tmp23 = tmp11 - tmp13; + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + z3 <<= CONST_BITS; + z4 = (INT32) wsptr[7]; + + tmp11 = z2 + z4; + tmp13 = z2 - z4; + + tmp12 = MULTIPLY(tmp13, FIX(0.309016994)); /* (c3-c7)/2 */ + + z2 = MULTIPLY(tmp11, FIX(0.951056516)); /* (c3+c7)/2 */ + z4 = z3 + tmp12; + + tmp10 = MULTIPLY(z1, FIX(1.396802247)) + z2 + z4; /* c1 */ + tmp14 = MULTIPLY(z1, FIX(0.221231742)) - z2 + z4; /* c9 */ + + z2 = MULTIPLY(tmp11, FIX(0.587785252)); /* (c1-c9)/2 */ + z4 = z3 - tmp12 - (tmp13 << (CONST_BITS - 1)); + + tmp12 = ((z1 - tmp13) << CONST_BITS) - z3; + + tmp11 = MULTIPLY(z1, FIX(1.260073511)) - z2 - z4; /* c3 */ + tmp13 = MULTIPLY(z1, FIX(0.642039522)) - z2 + z4; /* c7 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 8; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 11x11 output block. + * + * Optimized algorithm with 24 multiplications in the 1-D kernel. + * cK represents sqrt(2) * cos(K*pi/22). + */ + +GLOBAL(void) +jpeg_idct_11x11 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp10, tmp11, tmp12, tmp13, tmp14; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[8*11]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp10 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp10 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + tmp10 += ONE << (CONST_BITS-PASS1_BITS-1); + + z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + tmp20 = MULTIPLY(z2 - z3, FIX(2.546640132)); /* c2+c4 */ + tmp23 = MULTIPLY(z2 - z1, FIX(0.430815045)); /* c2-c6 */ + z4 = z1 + z3; + tmp24 = MULTIPLY(z4, - FIX(1.155664402)); /* -(c2-c10) */ + z4 -= z2; + tmp25 = tmp10 + MULTIPLY(z4, FIX(1.356927976)); /* c2 */ + tmp21 = tmp20 + tmp23 + tmp25 - + MULTIPLY(z2, FIX(1.821790775)); /* c2+c4+c10-c6 */ + tmp20 += tmp25 + MULTIPLY(z3, FIX(2.115825087)); /* c4+c6 */ + tmp23 += tmp25 - MULTIPLY(z1, FIX(1.513598477)); /* c6+c8 */ + tmp24 += tmp25; + tmp22 = tmp24 - MULTIPLY(z3, FIX(0.788749120)); /* c8+c10 */ + tmp24 += MULTIPLY(z2, FIX(1.944413522)) - /* c2+c8 */ + MULTIPLY(z1, FIX(1.390975730)); /* c4+c10 */ + tmp25 = tmp10 - MULTIPLY(z4, FIX(1.414213562)); /* c0 */ + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + tmp11 = z1 + z2; + tmp14 = MULTIPLY(tmp11 + z3 + z4, FIX(0.398430003)); /* c9 */ + tmp11 = MULTIPLY(tmp11, FIX(0.887983902)); /* c3-c9 */ + tmp12 = MULTIPLY(z1 + z3, FIX(0.670361295)); /* c5-c9 */ + tmp13 = tmp14 + MULTIPLY(z1 + z4, FIX(0.366151574)); /* c7-c9 */ + tmp10 = tmp11 + tmp12 + tmp13 - + MULTIPLY(z1, FIX(0.923107866)); /* c7+c5+c3-c1-2*c9 */ + z1 = tmp14 - MULTIPLY(z2 + z3, FIX(1.163011579)); /* c7+c9 */ + tmp11 += z1 + MULTIPLY(z2, FIX(2.073276588)); /* c1+c7+3*c9-c3 */ + tmp12 += z1 - MULTIPLY(z3, FIX(1.192193623)); /* c3+c5-c7-c9 */ + z1 = MULTIPLY(z2 + z4, - FIX(1.798248910)); /* -(c1+c9) */ + tmp11 += z1; + tmp13 += z1 + MULTIPLY(z4, FIX(2.102458632)); /* c1+c5+c9-c7 */ + tmp14 += MULTIPLY(z2, - FIX(1.467221301)) + /* -(c5+c9) */ + MULTIPLY(z3, FIX(1.001388905)) - /* c1-c9 */ + MULTIPLY(z4, FIX(1.684843907)); /* c3+c9 */ + + /* Final output stage */ + + wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*10] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*9] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*8] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS); + wsptr[8*7] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS); + wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); + wsptr[8*6] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); + wsptr[8*5] = (int) RIGHT_SHIFT(tmp25, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 11 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 11; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + tmp10 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + tmp10 <<= CONST_BITS; + + z1 = (INT32) wsptr[2]; + z2 = (INT32) wsptr[4]; + z3 = (INT32) wsptr[6]; + + tmp20 = MULTIPLY(z2 - z3, FIX(2.546640132)); /* c2+c4 */ + tmp23 = MULTIPLY(z2 - z1, FIX(0.430815045)); /* c2-c6 */ + z4 = z1 + z3; + tmp24 = MULTIPLY(z4, - FIX(1.155664402)); /* -(c2-c10) */ + z4 -= z2; + tmp25 = tmp10 + MULTIPLY(z4, FIX(1.356927976)); /* c2 */ + tmp21 = tmp20 + tmp23 + tmp25 - + MULTIPLY(z2, FIX(1.821790775)); /* c2+c4+c10-c6 */ + tmp20 += tmp25 + MULTIPLY(z3, FIX(2.115825087)); /* c4+c6 */ + tmp23 += tmp25 - MULTIPLY(z1, FIX(1.513598477)); /* c6+c8 */ + tmp24 += tmp25; + tmp22 = tmp24 - MULTIPLY(z3, FIX(0.788749120)); /* c8+c10 */ + tmp24 += MULTIPLY(z2, FIX(1.944413522)) - /* c2+c8 */ + MULTIPLY(z1, FIX(1.390975730)); /* c4+c10 */ + tmp25 = tmp10 - MULTIPLY(z4, FIX(1.414213562)); /* c0 */ + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + z4 = (INT32) wsptr[7]; + + tmp11 = z1 + z2; + tmp14 = MULTIPLY(tmp11 + z3 + z4, FIX(0.398430003)); /* c9 */ + tmp11 = MULTIPLY(tmp11, FIX(0.887983902)); /* c3-c9 */ + tmp12 = MULTIPLY(z1 + z3, FIX(0.670361295)); /* c5-c9 */ + tmp13 = tmp14 + MULTIPLY(z1 + z4, FIX(0.366151574)); /* c7-c9 */ + tmp10 = tmp11 + tmp12 + tmp13 - + MULTIPLY(z1, FIX(0.923107866)); /* c7+c5+c3-c1-2*c9 */ + z1 = tmp14 - MULTIPLY(z2 + z3, FIX(1.163011579)); /* c7+c9 */ + tmp11 += z1 + MULTIPLY(z2, FIX(2.073276588)); /* c1+c7+3*c9-c3 */ + tmp12 += z1 - MULTIPLY(z3, FIX(1.192193623)); /* c3+c5-c7-c9 */ + z1 = MULTIPLY(z2 + z4, - FIX(1.798248910)); /* -(c1+c9) */ + tmp11 += z1; + tmp13 += z1 + MULTIPLY(z4, FIX(2.102458632)); /* c1+c5+c9-c7 */ + tmp14 += MULTIPLY(z2, - FIX(1.467221301)) + /* -(c5+c9) */ + MULTIPLY(z3, FIX(1.001388905)) - /* c1-c9 */ + MULTIPLY(z4, FIX(1.684843907)); /* c3+c9 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 8; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 12x12 output block. + * + * Optimized algorithm with 15 multiplications in the 1-D kernel. + * cK represents sqrt(2) * cos(K*pi/24). + */ + +GLOBAL(void) +jpeg_idct_12x12 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[8*12]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + z3 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + z3 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + z3 += ONE << (CONST_BITS-PASS1_BITS-1); + + z4 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z4 = MULTIPLY(z4, FIX(1.224744871)); /* c4 */ + + tmp10 = z3 + z4; + tmp11 = z3 - z4; + + z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z4 = MULTIPLY(z1, FIX(1.366025404)); /* c2 */ + z1 <<= CONST_BITS; + z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + z2 <<= CONST_BITS; + + tmp12 = z1 - z2; + + tmp21 = z3 + tmp12; + tmp24 = z3 - tmp12; + + tmp12 = z4 + z2; + + tmp20 = tmp10 + tmp12; + tmp25 = tmp10 - tmp12; + + tmp12 = z4 - z1 - z2; + + tmp22 = tmp11 + tmp12; + tmp23 = tmp11 - tmp12; + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + tmp11 = MULTIPLY(z2, FIX(1.306562965)); /* c3 */ + tmp14 = MULTIPLY(z2, - FIX_0_541196100); /* -c9 */ + + tmp10 = z1 + z3; + tmp15 = MULTIPLY(tmp10 + z4, FIX(0.860918669)); /* c7 */ + tmp12 = tmp15 + MULTIPLY(tmp10, FIX(0.261052384)); /* c5-c7 */ + tmp10 = tmp12 + tmp11 + MULTIPLY(z1, FIX(0.280143716)); /* c1-c5 */ + tmp13 = MULTIPLY(z3 + z4, - FIX(1.045510580)); /* -(c7+c11) */ + tmp12 += tmp13 + tmp14 - MULTIPLY(z3, FIX(1.478575242)); /* c1+c5-c7-c11 */ + tmp13 += tmp15 - tmp11 + MULTIPLY(z4, FIX(1.586706681)); /* c1+c11 */ + tmp15 += tmp14 - MULTIPLY(z1, FIX(0.676326758)) - /* c7-c11 */ + MULTIPLY(z4, FIX(1.982889723)); /* c5+c7 */ + + z1 -= z4; + z2 -= z3; + z3 = MULTIPLY(z1 + z2, FIX_0_541196100); /* c9 */ + tmp11 = z3 + MULTIPLY(z1, FIX_0_765366865); /* c3-c9 */ + tmp14 = z3 - MULTIPLY(z2, FIX_1_847759065); /* c3+c9 */ + + /* Final output stage */ + + wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*11] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*10] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*9] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS); + wsptr[8*8] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS); + wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); + wsptr[8*7] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); + wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS); + wsptr[8*6] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 12 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 12; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + z3 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + z3 <<= CONST_BITS; + + z4 = (INT32) wsptr[4]; + z4 = MULTIPLY(z4, FIX(1.224744871)); /* c4 */ + + tmp10 = z3 + z4; + tmp11 = z3 - z4; + + z1 = (INT32) wsptr[2]; + z4 = MULTIPLY(z1, FIX(1.366025404)); /* c2 */ + z1 <<= CONST_BITS; + z2 = (INT32) wsptr[6]; + z2 <<= CONST_BITS; + + tmp12 = z1 - z2; + + tmp21 = z3 + tmp12; + tmp24 = z3 - tmp12; + + tmp12 = z4 + z2; + + tmp20 = tmp10 + tmp12; + tmp25 = tmp10 - tmp12; + + tmp12 = z4 - z1 - z2; + + tmp22 = tmp11 + tmp12; + tmp23 = tmp11 - tmp12; + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + z4 = (INT32) wsptr[7]; + + tmp11 = MULTIPLY(z2, FIX(1.306562965)); /* c3 */ + tmp14 = MULTIPLY(z2, - FIX_0_541196100); /* -c9 */ + + tmp10 = z1 + z3; + tmp15 = MULTIPLY(tmp10 + z4, FIX(0.860918669)); /* c7 */ + tmp12 = tmp15 + MULTIPLY(tmp10, FIX(0.261052384)); /* c5-c7 */ + tmp10 = tmp12 + tmp11 + MULTIPLY(z1, FIX(0.280143716)); /* c1-c5 */ + tmp13 = MULTIPLY(z3 + z4, - FIX(1.045510580)); /* -(c7+c11) */ + tmp12 += tmp13 + tmp14 - MULTIPLY(z3, FIX(1.478575242)); /* c1+c5-c7-c11 */ + tmp13 += tmp15 - tmp11 + MULTIPLY(z4, FIX(1.586706681)); /* c1+c11 */ + tmp15 += tmp14 - MULTIPLY(z1, FIX(0.676326758)) - /* c7-c11 */ + MULTIPLY(z4, FIX(1.982889723)); /* c5+c7 */ + + z1 -= z4; + z2 -= z3; + z3 = MULTIPLY(z1 + z2, FIX_0_541196100); /* c9 */ + tmp11 = z3 + MULTIPLY(z1, FIX_0_765366865); /* c3-c9 */ + tmp14 = z3 - MULTIPLY(z2, FIX_1_847759065); /* c3+c9 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 8; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 13x13 output block. + * + * Optimized algorithm with 29 multiplications in the 1-D kernel. + * cK represents sqrt(2) * cos(K*pi/26). + */ + +GLOBAL(void) +jpeg_idct_13x13 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[8*13]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + z1 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + z1 += ONE << (CONST_BITS-PASS1_BITS-1); + + z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z4 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + tmp10 = z3 + z4; + tmp11 = z3 - z4; + + tmp12 = MULTIPLY(tmp10, FIX(1.155388986)); /* (c4+c6)/2 */ + tmp13 = MULTIPLY(tmp11, FIX(0.096834934)) + z1; /* (c4-c6)/2 */ + + tmp20 = MULTIPLY(z2, FIX(1.373119086)) + tmp12 + tmp13; /* c2 */ + tmp22 = MULTIPLY(z2, FIX(0.501487041)) - tmp12 + tmp13; /* c10 */ + + tmp12 = MULTIPLY(tmp10, FIX(0.316450131)); /* (c8-c12)/2 */ + tmp13 = MULTIPLY(tmp11, FIX(0.486914739)) + z1; /* (c8+c12)/2 */ + + tmp21 = MULTIPLY(z2, FIX(1.058554052)) - tmp12 + tmp13; /* c6 */ + tmp25 = MULTIPLY(z2, - FIX(1.252223920)) + tmp12 + tmp13; /* c4 */ + + tmp12 = MULTIPLY(tmp10, FIX(0.435816023)); /* (c2-c10)/2 */ + tmp13 = MULTIPLY(tmp11, FIX(0.937303064)) - z1; /* (c2+c10)/2 */ + + tmp23 = MULTIPLY(z2, - FIX(0.170464608)) - tmp12 - tmp13; /* c12 */ + tmp24 = MULTIPLY(z2, - FIX(0.803364869)) + tmp12 - tmp13; /* c8 */ + + tmp26 = MULTIPLY(tmp11 - z2, FIX(1.414213562)) + z1; /* c0 */ + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + tmp11 = MULTIPLY(z1 + z2, FIX(1.322312651)); /* c3 */ + tmp12 = MULTIPLY(z1 + z3, FIX(1.163874945)); /* c5 */ + tmp15 = z1 + z4; + tmp13 = MULTIPLY(tmp15, FIX(0.937797057)); /* c7 */ + tmp10 = tmp11 + tmp12 + tmp13 - + MULTIPLY(z1, FIX(2.020082300)); /* c7+c5+c3-c1 */ + tmp14 = MULTIPLY(z2 + z3, - FIX(0.338443458)); /* -c11 */ + tmp11 += tmp14 + MULTIPLY(z2, FIX(0.837223564)); /* c5+c9+c11-c3 */ + tmp12 += tmp14 - MULTIPLY(z3, FIX(1.572116027)); /* c1+c5-c9-c11 */ + tmp14 = MULTIPLY(z2 + z4, - FIX(1.163874945)); /* -c5 */ + tmp11 += tmp14; + tmp13 += tmp14 + MULTIPLY(z4, FIX(2.205608352)); /* c3+c5+c9-c7 */ + tmp14 = MULTIPLY(z3 + z4, - FIX(0.657217813)); /* -c9 */ + tmp12 += tmp14; + tmp13 += tmp14; + tmp15 = MULTIPLY(tmp15, FIX(0.338443458)); /* c11 */ + tmp14 = tmp15 + MULTIPLY(z1, FIX(0.318774355)) - /* c9-c11 */ + MULTIPLY(z2, FIX(0.466105296)); /* c1-c7 */ + z1 = MULTIPLY(z3 - z2, FIX(0.937797057)); /* c7 */ + tmp14 += z1; + tmp15 += z1 + MULTIPLY(z3, FIX(0.384515595)) - /* c3-c7 */ + MULTIPLY(z4, FIX(1.742345811)); /* c1+c11 */ + + /* Final output stage */ + + wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*12] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*11] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*10] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS); + wsptr[8*9] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS); + wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); + wsptr[8*8] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); + wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS); + wsptr[8*7] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS); + wsptr[8*6] = (int) RIGHT_SHIFT(tmp26, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 13 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 13; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + z1 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + z1 <<= CONST_BITS; + + z2 = (INT32) wsptr[2]; + z3 = (INT32) wsptr[4]; + z4 = (INT32) wsptr[6]; + + tmp10 = z3 + z4; + tmp11 = z3 - z4; + + tmp12 = MULTIPLY(tmp10, FIX(1.155388986)); /* (c4+c6)/2 */ + tmp13 = MULTIPLY(tmp11, FIX(0.096834934)) + z1; /* (c4-c6)/2 */ + + tmp20 = MULTIPLY(z2, FIX(1.373119086)) + tmp12 + tmp13; /* c2 */ + tmp22 = MULTIPLY(z2, FIX(0.501487041)) - tmp12 + tmp13; /* c10 */ + + tmp12 = MULTIPLY(tmp10, FIX(0.316450131)); /* (c8-c12)/2 */ + tmp13 = MULTIPLY(tmp11, FIX(0.486914739)) + z1; /* (c8+c12)/2 */ + + tmp21 = MULTIPLY(z2, FIX(1.058554052)) - tmp12 + tmp13; /* c6 */ + tmp25 = MULTIPLY(z2, - FIX(1.252223920)) + tmp12 + tmp13; /* c4 */ + + tmp12 = MULTIPLY(tmp10, FIX(0.435816023)); /* (c2-c10)/2 */ + tmp13 = MULTIPLY(tmp11, FIX(0.937303064)) - z1; /* (c2+c10)/2 */ + + tmp23 = MULTIPLY(z2, - FIX(0.170464608)) - tmp12 - tmp13; /* c12 */ + tmp24 = MULTIPLY(z2, - FIX(0.803364869)) + tmp12 - tmp13; /* c8 */ + + tmp26 = MULTIPLY(tmp11 - z2, FIX(1.414213562)) + z1; /* c0 */ + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + z4 = (INT32) wsptr[7]; + + tmp11 = MULTIPLY(z1 + z2, FIX(1.322312651)); /* c3 */ + tmp12 = MULTIPLY(z1 + z3, FIX(1.163874945)); /* c5 */ + tmp15 = z1 + z4; + tmp13 = MULTIPLY(tmp15, FIX(0.937797057)); /* c7 */ + tmp10 = tmp11 + tmp12 + tmp13 - + MULTIPLY(z1, FIX(2.020082300)); /* c7+c5+c3-c1 */ + tmp14 = MULTIPLY(z2 + z3, - FIX(0.338443458)); /* -c11 */ + tmp11 += tmp14 + MULTIPLY(z2, FIX(0.837223564)); /* c5+c9+c11-c3 */ + tmp12 += tmp14 - MULTIPLY(z3, FIX(1.572116027)); /* c1+c5-c9-c11 */ + tmp14 = MULTIPLY(z2 + z4, - FIX(1.163874945)); /* -c5 */ + tmp11 += tmp14; + tmp13 += tmp14 + MULTIPLY(z4, FIX(2.205608352)); /* c3+c5+c9-c7 */ + tmp14 = MULTIPLY(z3 + z4, - FIX(0.657217813)); /* -c9 */ + tmp12 += tmp14; + tmp13 += tmp14; + tmp15 = MULTIPLY(tmp15, FIX(0.338443458)); /* c11 */ + tmp14 = tmp15 + MULTIPLY(z1, FIX(0.318774355)) - /* c9-c11 */ + MULTIPLY(z2, FIX(0.466105296)); /* c1-c7 */ + z1 = MULTIPLY(z3 - z2, FIX(0.937797057)); /* c7 */ + tmp14 += z1; + tmp15 += z1 + MULTIPLY(z3, FIX(0.384515595)) - /* c3-c7 */ + MULTIPLY(z4, FIX(1.742345811)); /* c1+c11 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 8; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 14x14 output block. + * + * Optimized algorithm with 20 multiplications in the 1-D kernel. + * cK represents sqrt(2) * cos(K*pi/28). + */ + +GLOBAL(void) +jpeg_idct_14x14 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[8*14]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + z1 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + z1 += ONE << (CONST_BITS-PASS1_BITS-1); + z4 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z2 = MULTIPLY(z4, FIX(1.274162392)); /* c4 */ + z3 = MULTIPLY(z4, FIX(0.314692123)); /* c12 */ + z4 = MULTIPLY(z4, FIX(0.881747734)); /* c8 */ + + tmp10 = z1 + z2; + tmp11 = z1 + z3; + tmp12 = z1 - z4; + + tmp23 = RIGHT_SHIFT(z1 - ((z2 + z3 - z4) << 1), /* c0 = (c4+c12-c8)*2 */ + CONST_BITS-PASS1_BITS); + + z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + z3 = MULTIPLY(z1 + z2, FIX(1.105676686)); /* c6 */ + + tmp13 = z3 + MULTIPLY(z1, FIX(0.273079590)); /* c2-c6 */ + tmp14 = z3 - MULTIPLY(z2, FIX(1.719280954)); /* c6+c10 */ + tmp15 = MULTIPLY(z1, FIX(0.613604268)) - /* c10 */ + MULTIPLY(z2, FIX(1.378756276)); /* c2 */ + + tmp20 = tmp10 + tmp13; + tmp26 = tmp10 - tmp13; + tmp21 = tmp11 + tmp14; + tmp25 = tmp11 - tmp14; + tmp22 = tmp12 + tmp15; + tmp24 = tmp12 - tmp15; + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + tmp13 = z4 << CONST_BITS; + + tmp14 = z1 + z3; + tmp11 = MULTIPLY(z1 + z2, FIX(1.334852607)); /* c3 */ + tmp12 = MULTIPLY(tmp14, FIX(1.197448846)); /* c5 */ + tmp10 = tmp11 + tmp12 + tmp13 - MULTIPLY(z1, FIX(1.126980169)); /* c3+c5-c1 */ + tmp14 = MULTIPLY(tmp14, FIX(0.752406978)); /* c9 */ + tmp16 = tmp14 - MULTIPLY(z1, FIX(1.061150426)); /* c9+c11-c13 */ + z1 -= z2; + tmp15 = MULTIPLY(z1, FIX(0.467085129)) - tmp13; /* c11 */ + tmp16 += tmp15; + z1 += z4; + z4 = MULTIPLY(z2 + z3, - FIX(0.158341681)) - tmp13; /* -c13 */ + tmp11 += z4 - MULTIPLY(z2, FIX(0.424103948)); /* c3-c9-c13 */ + tmp12 += z4 - MULTIPLY(z3, FIX(2.373959773)); /* c3+c5-c13 */ + z4 = MULTIPLY(z3 - z2, FIX(1.405321284)); /* c1 */ + tmp14 += z4 + tmp13 - MULTIPLY(z3, FIX(1.6906431334)); /* c1+c9-c11 */ + tmp15 += z4 + MULTIPLY(z2, FIX(0.674957567)); /* c1+c11-c5 */ + + tmp13 = (z1 - z3) << PASS1_BITS; + + /* Final output stage */ + + wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*13] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*12] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*11] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*3] = (int) (tmp23 + tmp13); + wsptr[8*10] = (int) (tmp23 - tmp13); + wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); + wsptr[8*9] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); + wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS); + wsptr[8*8] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS); + wsptr[8*6] = (int) RIGHT_SHIFT(tmp26 + tmp16, CONST_BITS-PASS1_BITS); + wsptr[8*7] = (int) RIGHT_SHIFT(tmp26 - tmp16, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 14 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 14; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + z1 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + z1 <<= CONST_BITS; + z4 = (INT32) wsptr[4]; + z2 = MULTIPLY(z4, FIX(1.274162392)); /* c4 */ + z3 = MULTIPLY(z4, FIX(0.314692123)); /* c12 */ + z4 = MULTIPLY(z4, FIX(0.881747734)); /* c8 */ + + tmp10 = z1 + z2; + tmp11 = z1 + z3; + tmp12 = z1 - z4; + + tmp23 = z1 - ((z2 + z3 - z4) << 1); /* c0 = (c4+c12-c8)*2 */ + + z1 = (INT32) wsptr[2]; + z2 = (INT32) wsptr[6]; + + z3 = MULTIPLY(z1 + z2, FIX(1.105676686)); /* c6 */ + + tmp13 = z3 + MULTIPLY(z1, FIX(0.273079590)); /* c2-c6 */ + tmp14 = z3 - MULTIPLY(z2, FIX(1.719280954)); /* c6+c10 */ + tmp15 = MULTIPLY(z1, FIX(0.613604268)) - /* c10 */ + MULTIPLY(z2, FIX(1.378756276)); /* c2 */ + + tmp20 = tmp10 + tmp13; + tmp26 = tmp10 - tmp13; + tmp21 = tmp11 + tmp14; + tmp25 = tmp11 - tmp14; + tmp22 = tmp12 + tmp15; + tmp24 = tmp12 - tmp15; + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + z4 = (INT32) wsptr[7]; + z4 <<= CONST_BITS; + + tmp14 = z1 + z3; + tmp11 = MULTIPLY(z1 + z2, FIX(1.334852607)); /* c3 */ + tmp12 = MULTIPLY(tmp14, FIX(1.197448846)); /* c5 */ + tmp10 = tmp11 + tmp12 + z4 - MULTIPLY(z1, FIX(1.126980169)); /* c3+c5-c1 */ + tmp14 = MULTIPLY(tmp14, FIX(0.752406978)); /* c9 */ + tmp16 = tmp14 - MULTIPLY(z1, FIX(1.061150426)); /* c9+c11-c13 */ + z1 -= z2; + tmp15 = MULTIPLY(z1, FIX(0.467085129)) - z4; /* c11 */ + tmp16 += tmp15; + tmp13 = MULTIPLY(z2 + z3, - FIX(0.158341681)) - z4; /* -c13 */ + tmp11 += tmp13 - MULTIPLY(z2, FIX(0.424103948)); /* c3-c9-c13 */ + tmp12 += tmp13 - MULTIPLY(z3, FIX(2.373959773)); /* c3+c5-c13 */ + tmp13 = MULTIPLY(z3 - z2, FIX(1.405321284)); /* c1 */ + tmp14 += tmp13 + z4 - MULTIPLY(z3, FIX(1.6906431334)); /* c1+c9-c11 */ + tmp15 += tmp13 + MULTIPLY(z2, FIX(0.674957567)); /* c1+c11-c5 */ + + tmp13 = ((z1 - z3) << CONST_BITS) + z4; + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[13] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26 + tmp16, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp26 - tmp16, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 8; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 15x15 output block. + * + * Optimized algorithm with 22 multiplications in the 1-D kernel. + * cK represents sqrt(2) * cos(K*pi/30). + */ + +GLOBAL(void) +jpeg_idct_15x15 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[8*15]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + z1 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + z1 += ONE << (CONST_BITS-PASS1_BITS-1); + + z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z4 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + tmp10 = MULTIPLY(z4, FIX(0.437016024)); /* c12 */ + tmp11 = MULTIPLY(z4, FIX(1.144122806)); /* c6 */ + + tmp12 = z1 - tmp10; + tmp13 = z1 + tmp11; + z1 -= (tmp11 - tmp10) << 1; /* c0 = (c6-c12)*2 */ + + z4 = z2 - z3; + z3 += z2; + tmp10 = MULTIPLY(z3, FIX(1.337628990)); /* (c2+c4)/2 */ + tmp11 = MULTIPLY(z4, FIX(0.045680613)); /* (c2-c4)/2 */ + z2 = MULTIPLY(z2, FIX(1.439773946)); /* c4+c14 */ + + tmp20 = tmp13 + tmp10 + tmp11; + tmp23 = tmp12 - tmp10 + tmp11 + z2; + + tmp10 = MULTIPLY(z3, FIX(0.547059574)); /* (c8+c14)/2 */ + tmp11 = MULTIPLY(z4, FIX(0.399234004)); /* (c8-c14)/2 */ + + tmp25 = tmp13 - tmp10 - tmp11; + tmp26 = tmp12 + tmp10 - tmp11 - z2; + + tmp10 = MULTIPLY(z3, FIX(0.790569415)); /* (c6+c12)/2 */ + tmp11 = MULTIPLY(z4, FIX(0.353553391)); /* (c6-c12)/2 */ + + tmp21 = tmp12 + tmp10 + tmp11; + tmp24 = tmp13 - tmp10 + tmp11; + tmp11 += tmp11; + tmp22 = z1 + tmp11; /* c10 = c6-c12 */ + tmp27 = z1 - tmp11 - tmp11; /* c0 = (c6-c12)*2 */ + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z4 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z3 = MULTIPLY(z4, FIX(1.224744871)); /* c5 */ + z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + tmp13 = z2 - z4; + tmp15 = MULTIPLY(z1 + tmp13, FIX(0.831253876)); /* c9 */ + tmp11 = tmp15 + MULTIPLY(z1, FIX(0.513743148)); /* c3-c9 */ + tmp14 = tmp15 - MULTIPLY(tmp13, FIX(2.176250899)); /* c3+c9 */ + + tmp13 = MULTIPLY(z2, - FIX(0.831253876)); /* -c9 */ + tmp15 = MULTIPLY(z2, - FIX(1.344997024)); /* -c3 */ + z2 = z1 - z4; + tmp12 = z3 + MULTIPLY(z2, FIX(1.406466353)); /* c1 */ + + tmp10 = tmp12 + MULTIPLY(z4, FIX(2.457431844)) - tmp15; /* c1+c7 */ + tmp16 = tmp12 - MULTIPLY(z1, FIX(1.112434820)) + tmp13; /* c1-c13 */ + tmp12 = MULTIPLY(z2, FIX(1.224744871)) - z3; /* c5 */ + z2 = MULTIPLY(z1 + z4, FIX(0.575212477)); /* c11 */ + tmp13 += z2 + MULTIPLY(z1, FIX(0.475753014)) - z3; /* c7-c11 */ + tmp15 += z2 - MULTIPLY(z4, FIX(0.869244010)) + z3; /* c11+c13 */ + + /* Final output stage */ + + wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*14] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*13] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*12] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS); + wsptr[8*11] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS); + wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); + wsptr[8*10] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); + wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS); + wsptr[8*9] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS); + wsptr[8*6] = (int) RIGHT_SHIFT(tmp26 + tmp16, CONST_BITS-PASS1_BITS); + wsptr[8*8] = (int) RIGHT_SHIFT(tmp26 - tmp16, CONST_BITS-PASS1_BITS); + wsptr[8*7] = (int) RIGHT_SHIFT(tmp27, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 15 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 15; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + z1 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + z1 <<= CONST_BITS; + + z2 = (INT32) wsptr[2]; + z3 = (INT32) wsptr[4]; + z4 = (INT32) wsptr[6]; + + tmp10 = MULTIPLY(z4, FIX(0.437016024)); /* c12 */ + tmp11 = MULTIPLY(z4, FIX(1.144122806)); /* c6 */ + + tmp12 = z1 - tmp10; + tmp13 = z1 + tmp11; + z1 -= (tmp11 - tmp10) << 1; /* c0 = (c6-c12)*2 */ + + z4 = z2 - z3; + z3 += z2; + tmp10 = MULTIPLY(z3, FIX(1.337628990)); /* (c2+c4)/2 */ + tmp11 = MULTIPLY(z4, FIX(0.045680613)); /* (c2-c4)/2 */ + z2 = MULTIPLY(z2, FIX(1.439773946)); /* c4+c14 */ + + tmp20 = tmp13 + tmp10 + tmp11; + tmp23 = tmp12 - tmp10 + tmp11 + z2; + + tmp10 = MULTIPLY(z3, FIX(0.547059574)); /* (c8+c14)/2 */ + tmp11 = MULTIPLY(z4, FIX(0.399234004)); /* (c8-c14)/2 */ + + tmp25 = tmp13 - tmp10 - tmp11; + tmp26 = tmp12 + tmp10 - tmp11 - z2; + + tmp10 = MULTIPLY(z3, FIX(0.790569415)); /* (c6+c12)/2 */ + tmp11 = MULTIPLY(z4, FIX(0.353553391)); /* (c6-c12)/2 */ + + tmp21 = tmp12 + tmp10 + tmp11; + tmp24 = tmp13 - tmp10 + tmp11; + tmp11 += tmp11; + tmp22 = z1 + tmp11; /* c10 = c6-c12 */ + tmp27 = z1 - tmp11 - tmp11; /* c0 = (c6-c12)*2 */ + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z4 = (INT32) wsptr[5]; + z3 = MULTIPLY(z4, FIX(1.224744871)); /* c5 */ + z4 = (INT32) wsptr[7]; + + tmp13 = z2 - z4; + tmp15 = MULTIPLY(z1 + tmp13, FIX(0.831253876)); /* c9 */ + tmp11 = tmp15 + MULTIPLY(z1, FIX(0.513743148)); /* c3-c9 */ + tmp14 = tmp15 - MULTIPLY(tmp13, FIX(2.176250899)); /* c3+c9 */ + + tmp13 = MULTIPLY(z2, - FIX(0.831253876)); /* -c9 */ + tmp15 = MULTIPLY(z2, - FIX(1.344997024)); /* -c3 */ + z2 = z1 - z4; + tmp12 = z3 + MULTIPLY(z2, FIX(1.406466353)); /* c1 */ + + tmp10 = tmp12 + MULTIPLY(z4, FIX(2.457431844)) - tmp15; /* c1+c7 */ + tmp16 = tmp12 - MULTIPLY(z1, FIX(1.112434820)) + tmp13; /* c1-c13 */ + tmp12 = MULTIPLY(z2, FIX(1.224744871)) - z3; /* c5 */ + z2 = MULTIPLY(z1 + z4, FIX(0.575212477)); /* c11 */ + tmp13 += z2 + MULTIPLY(z1, FIX(0.475753014)) - z3; /* c7-c11 */ + tmp15 += z2 - MULTIPLY(z4, FIX(0.869244010)) + z3; /* c11+c13 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[14] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[13] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26 + tmp16, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp26 - tmp16, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp27, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 8; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 16x16 output block. + * + * Optimized algorithm with 28 multiplications in the 1-D kernel. + * cK represents sqrt(2) * cos(K*pi/32). + */ + +GLOBAL(void) +jpeg_idct_16x16 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp10, tmp11, tmp12, tmp13; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[8*16]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp0 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + tmp0 += 1 << (CONST_BITS-PASS1_BITS-1); + + z1 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + tmp1 = MULTIPLY(z1, FIX(1.306562965)); /* c4[16] = c2[8] */ + tmp2 = MULTIPLY(z1, FIX_0_541196100); /* c12[16] = c6[8] */ + + tmp10 = tmp0 + tmp1; + tmp11 = tmp0 - tmp1; + tmp12 = tmp0 + tmp2; + tmp13 = tmp0 - tmp2; + + z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + z3 = z1 - z2; + z4 = MULTIPLY(z3, FIX(0.275899379)); /* c14[16] = c7[8] */ + z3 = MULTIPLY(z3, FIX(1.387039845)); /* c2[16] = c1[8] */ + + tmp0 = z3 + MULTIPLY(z2, FIX_2_562915447); /* (c6+c2)[16] = (c3+c1)[8] */ + tmp1 = z4 + MULTIPLY(z1, FIX_0_899976223); /* (c6-c14)[16] = (c3-c7)[8] */ + tmp2 = z3 - MULTIPLY(z1, FIX(0.601344887)); /* (c2-c10)[16] = (c1-c5)[8] */ + tmp3 = z4 - MULTIPLY(z2, FIX(0.509795579)); /* (c10-c14)[16] = (c5-c7)[8] */ + + tmp20 = tmp10 + tmp0; + tmp27 = tmp10 - tmp0; + tmp21 = tmp12 + tmp1; + tmp26 = tmp12 - tmp1; + tmp22 = tmp13 + tmp2; + tmp25 = tmp13 - tmp2; + tmp23 = tmp11 + tmp3; + tmp24 = tmp11 - tmp3; + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + tmp11 = z1 + z3; + + tmp1 = MULTIPLY(z1 + z2, FIX(1.353318001)); /* c3 */ + tmp2 = MULTIPLY(tmp11, FIX(1.247225013)); /* c5 */ + tmp3 = MULTIPLY(z1 + z4, FIX(1.093201867)); /* c7 */ + tmp10 = MULTIPLY(z1 - z4, FIX(0.897167586)); /* c9 */ + tmp11 = MULTIPLY(tmp11, FIX(0.666655658)); /* c11 */ + tmp12 = MULTIPLY(z1 - z2, FIX(0.410524528)); /* c13 */ + tmp0 = tmp1 + tmp2 + tmp3 - + MULTIPLY(z1, FIX(2.286341144)); /* c7+c5+c3-c1 */ + tmp13 = tmp10 + tmp11 + tmp12 - + MULTIPLY(z1, FIX(1.835730603)); /* c9+c11+c13-c15 */ + z1 = MULTIPLY(z2 + z3, FIX(0.138617169)); /* c15 */ + tmp1 += z1 + MULTIPLY(z2, FIX(0.071888074)); /* c9+c11-c3-c15 */ + tmp2 += z1 - MULTIPLY(z3, FIX(1.125726048)); /* c5+c7+c15-c3 */ + z1 = MULTIPLY(z3 - z2, FIX(1.407403738)); /* c1 */ + tmp11 += z1 - MULTIPLY(z3, FIX(0.766367282)); /* c1+c11-c9-c13 */ + tmp12 += z1 + MULTIPLY(z2, FIX(1.971951411)); /* c1+c5+c13-c7 */ + z2 += z4; + z1 = MULTIPLY(z2, - FIX(0.666655658)); /* -c11 */ + tmp1 += z1; + tmp3 += z1 + MULTIPLY(z4, FIX(1.065388962)); /* c3+c11+c15-c7 */ + z2 = MULTIPLY(z2, - FIX(1.247225013)); /* -c5 */ + tmp10 += z2 + MULTIPLY(z4, FIX(3.141271809)); /* c1+c5+c9-c13 */ + tmp12 += z2; + z2 = MULTIPLY(z3 + z4, - FIX(1.353318001)); /* -c3 */ + tmp2 += z2; + tmp3 += z2; + z2 = MULTIPLY(z4 - z3, FIX(0.410524528)); /* c13 */ + tmp10 += z2; + tmp11 += z2; + + /* Final output stage */ + + wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[8*15] = (int) RIGHT_SHIFT(tmp20 - tmp0, CONST_BITS-PASS1_BITS); + wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp1, CONST_BITS-PASS1_BITS); + wsptr[8*14] = (int) RIGHT_SHIFT(tmp21 - tmp1, CONST_BITS-PASS1_BITS); + wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp2, CONST_BITS-PASS1_BITS); + wsptr[8*13] = (int) RIGHT_SHIFT(tmp22 - tmp2, CONST_BITS-PASS1_BITS); + wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp3, CONST_BITS-PASS1_BITS); + wsptr[8*12] = (int) RIGHT_SHIFT(tmp23 - tmp3, CONST_BITS-PASS1_BITS); + wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*11] = (int) RIGHT_SHIFT(tmp24 - tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*10] = (int) RIGHT_SHIFT(tmp25 - tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*6] = (int) RIGHT_SHIFT(tmp26 + tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*9] = (int) RIGHT_SHIFT(tmp26 - tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*7] = (int) RIGHT_SHIFT(tmp27 + tmp13, CONST_BITS-PASS1_BITS); + wsptr[8*8] = (int) RIGHT_SHIFT(tmp27 - tmp13, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 16 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 16; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + tmp0 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + tmp0 <<= CONST_BITS; + + z1 = (INT32) wsptr[4]; + tmp1 = MULTIPLY(z1, FIX(1.306562965)); /* c4[16] = c2[8] */ + tmp2 = MULTIPLY(z1, FIX_0_541196100); /* c12[16] = c6[8] */ + + tmp10 = tmp0 + tmp1; + tmp11 = tmp0 - tmp1; + tmp12 = tmp0 + tmp2; + tmp13 = tmp0 - tmp2; + + z1 = (INT32) wsptr[2]; + z2 = (INT32) wsptr[6]; + z3 = z1 - z2; + z4 = MULTIPLY(z3, FIX(0.275899379)); /* c14[16] = c7[8] */ + z3 = MULTIPLY(z3, FIX(1.387039845)); /* c2[16] = c1[8] */ + + tmp0 = z3 + MULTIPLY(z2, FIX_2_562915447); /* (c6+c2)[16] = (c3+c1)[8] */ + tmp1 = z4 + MULTIPLY(z1, FIX_0_899976223); /* (c6-c14)[16] = (c3-c7)[8] */ + tmp2 = z3 - MULTIPLY(z1, FIX(0.601344887)); /* (c2-c10)[16] = (c1-c5)[8] */ + tmp3 = z4 - MULTIPLY(z2, FIX(0.509795579)); /* (c10-c14)[16] = (c5-c7)[8] */ + + tmp20 = tmp10 + tmp0; + tmp27 = tmp10 - tmp0; + tmp21 = tmp12 + tmp1; + tmp26 = tmp12 - tmp1; + tmp22 = tmp13 + tmp2; + tmp25 = tmp13 - tmp2; + tmp23 = tmp11 + tmp3; + tmp24 = tmp11 - tmp3; + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + z4 = (INT32) wsptr[7]; + + tmp11 = z1 + z3; + + tmp1 = MULTIPLY(z1 + z2, FIX(1.353318001)); /* c3 */ + tmp2 = MULTIPLY(tmp11, FIX(1.247225013)); /* c5 */ + tmp3 = MULTIPLY(z1 + z4, FIX(1.093201867)); /* c7 */ + tmp10 = MULTIPLY(z1 - z4, FIX(0.897167586)); /* c9 */ + tmp11 = MULTIPLY(tmp11, FIX(0.666655658)); /* c11 */ + tmp12 = MULTIPLY(z1 - z2, FIX(0.410524528)); /* c13 */ + tmp0 = tmp1 + tmp2 + tmp3 - + MULTIPLY(z1, FIX(2.286341144)); /* c7+c5+c3-c1 */ + tmp13 = tmp10 + tmp11 + tmp12 - + MULTIPLY(z1, FIX(1.835730603)); /* c9+c11+c13-c15 */ + z1 = MULTIPLY(z2 + z3, FIX(0.138617169)); /* c15 */ + tmp1 += z1 + MULTIPLY(z2, FIX(0.071888074)); /* c9+c11-c3-c15 */ + tmp2 += z1 - MULTIPLY(z3, FIX(1.125726048)); /* c5+c7+c15-c3 */ + z1 = MULTIPLY(z3 - z2, FIX(1.407403738)); /* c1 */ + tmp11 += z1 - MULTIPLY(z3, FIX(0.766367282)); /* c1+c11-c9-c13 */ + tmp12 += z1 + MULTIPLY(z2, FIX(1.971951411)); /* c1+c5+c13-c7 */ + z2 += z4; + z1 = MULTIPLY(z2, - FIX(0.666655658)); /* -c11 */ + tmp1 += z1; + tmp3 += z1 + MULTIPLY(z4, FIX(1.065388962)); /* c3+c11+c15-c7 */ + z2 = MULTIPLY(z2, - FIX(1.247225013)); /* -c5 */ + tmp10 += z2 + MULTIPLY(z4, FIX(3.141271809)); /* c1+c5+c9-c13 */ + tmp12 += z2; + z2 = MULTIPLY(z3 + z4, - FIX(1.353318001)); /* -c3 */ + tmp2 += z2; + tmp3 += z2; + z2 = MULTIPLY(z4 - z3, FIX(0.410524528)); /* c13 */ + tmp10 += z2; + tmp11 += z2; + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[15] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[14] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[13] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26 + tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp26 - tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp27 + tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp27 - tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 8; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 16x8 output block. + * + * 8-point IDCT in pass 1 (columns), 16-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_16x8 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp10, tmp11, tmp12, tmp13; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[8*8]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + /* Note results are scaled up by sqrt(8) compared to a true IDCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; @@ -207,19 +2881,23 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); z1 = MULTIPLY(z2 + z3, FIX_0_541196100); - tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065); - tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865); + tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); + tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z2 <<= CONST_BITS; + z3 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + z2 += ONE << (CONST_BITS-PASS1_BITS-1); - tmp0 = (z2 + z3) << CONST_BITS; - tmp1 = (z2 - z3) << CONST_BITS; + tmp0 = z2 + z3; + tmp1 = z2 - z3; - tmp10 = tmp0 + tmp3; - tmp13 = tmp0 - tmp3; - tmp11 = tmp1 + tmp2; - tmp12 = tmp1 - tmp2; + tmp10 = tmp0 + tmp2; + tmp13 = tmp0 - tmp2; + tmp11 = tmp1 + tmp3; + tmp12 = tmp1 - tmp3; /* Odd part per figure 8; the matrix is unitary and hence its * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. @@ -230,80 +2908,1240 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, tmp2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); tmp3 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - z1 = tmp0 + tmp3; - z2 = tmp1 + tmp2; - z3 = tmp0 + tmp2; - z4 = tmp1 + tmp3; - z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ - + z2 = tmp0 + tmp2; + z3 = tmp1 + tmp3; + + z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* sqrt(2) * c3 */ + z2 = MULTIPLY(z2, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z3 = MULTIPLY(z3, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + z2 += z1; + z3 += z1; + + z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + tmp0 += z1 + z2; + tmp3 += z1 + z3; + + z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ - tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ - z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ - z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ - z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ - z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ - - z3 += z5; - z4 += z5; - - tmp0 += z1 + z3; - tmp1 += z2 + z4; - tmp2 += z2 + z3; - tmp3 += z1 + z4; + tmp1 += z1 + z3; + tmp2 += z1 + z2; /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ - wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*7] = (int) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*1] = (int) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*6] = (int) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*5] = (int) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*3] = (int) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS); - wsptr[DCTSIZE*4] = (int) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*0] = (int) RIGHT_SHIFT(tmp10 + tmp3, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*7] = (int) RIGHT_SHIFT(tmp10 - tmp3, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*1] = (int) RIGHT_SHIFT(tmp11 + tmp2, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*6] = (int) RIGHT_SHIFT(tmp11 - tmp2, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*2] = (int) RIGHT_SHIFT(tmp12 + tmp1, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*5] = (int) RIGHT_SHIFT(tmp12 - tmp1, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*3] = (int) RIGHT_SHIFT(tmp13 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[DCTSIZE*4] = (int) RIGHT_SHIFT(tmp13 - tmp0, CONST_BITS-PASS1_BITS); inptr++; /* advance pointers to next column */ quantptr++; wsptr++; } + + /* Pass 2: process 8 rows from work array, store into output array. + * 16-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/32). + */ + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + tmp0 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + tmp0 <<= CONST_BITS; + + z1 = (INT32) wsptr[4]; + tmp1 = MULTIPLY(z1, FIX(1.306562965)); /* c4[16] = c2[8] */ + tmp2 = MULTIPLY(z1, FIX_0_541196100); /* c12[16] = c6[8] */ + + tmp10 = tmp0 + tmp1; + tmp11 = tmp0 - tmp1; + tmp12 = tmp0 + tmp2; + tmp13 = tmp0 - tmp2; + + z1 = (INT32) wsptr[2]; + z2 = (INT32) wsptr[6]; + z3 = z1 - z2; + z4 = MULTIPLY(z3, FIX(0.275899379)); /* c14[16] = c7[8] */ + z3 = MULTIPLY(z3, FIX(1.387039845)); /* c2[16] = c1[8] */ + + tmp0 = z3 + MULTIPLY(z2, FIX_2_562915447); /* (c6+c2)[16] = (c3+c1)[8] */ + tmp1 = z4 + MULTIPLY(z1, FIX_0_899976223); /* (c6-c14)[16] = (c3-c7)[8] */ + tmp2 = z3 - MULTIPLY(z1, FIX(0.601344887)); /* (c2-c10)[16] = (c1-c5)[8] */ + tmp3 = z4 - MULTIPLY(z2, FIX(0.509795579)); /* (c10-c14)[16] = (c5-c7)[8] */ + + tmp20 = tmp10 + tmp0; + tmp27 = tmp10 - tmp0; + tmp21 = tmp12 + tmp1; + tmp26 = tmp12 - tmp1; + tmp22 = tmp13 + tmp2; + tmp25 = tmp13 - tmp2; + tmp23 = tmp11 + tmp3; + tmp24 = tmp11 - tmp3; + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + z4 = (INT32) wsptr[7]; + + tmp11 = z1 + z3; + + tmp1 = MULTIPLY(z1 + z2, FIX(1.353318001)); /* c3 */ + tmp2 = MULTIPLY(tmp11, FIX(1.247225013)); /* c5 */ + tmp3 = MULTIPLY(z1 + z4, FIX(1.093201867)); /* c7 */ + tmp10 = MULTIPLY(z1 - z4, FIX(0.897167586)); /* c9 */ + tmp11 = MULTIPLY(tmp11, FIX(0.666655658)); /* c11 */ + tmp12 = MULTIPLY(z1 - z2, FIX(0.410524528)); /* c13 */ + tmp0 = tmp1 + tmp2 + tmp3 - + MULTIPLY(z1, FIX(2.286341144)); /* c7+c5+c3-c1 */ + tmp13 = tmp10 + tmp11 + tmp12 - + MULTIPLY(z1, FIX(1.835730603)); /* c9+c11+c13-c15 */ + z1 = MULTIPLY(z2 + z3, FIX(0.138617169)); /* c15 */ + tmp1 += z1 + MULTIPLY(z2, FIX(0.071888074)); /* c9+c11-c3-c15 */ + tmp2 += z1 - MULTIPLY(z3, FIX(1.125726048)); /* c5+c7+c15-c3 */ + z1 = MULTIPLY(z3 - z2, FIX(1.407403738)); /* c1 */ + tmp11 += z1 - MULTIPLY(z3, FIX(0.766367282)); /* c1+c11-c9-c13 */ + tmp12 += z1 + MULTIPLY(z2, FIX(1.971951411)); /* c1+c5+c13-c7 */ + z2 += z4; + z1 = MULTIPLY(z2, - FIX(0.666655658)); /* -c11 */ + tmp1 += z1; + tmp3 += z1 + MULTIPLY(z4, FIX(1.065388962)); /* c3+c11+c15-c7 */ + z2 = MULTIPLY(z2, - FIX(1.247225013)); /* -c5 */ + tmp10 += z2 + MULTIPLY(z4, FIX(3.141271809)); /* c1+c5+c9-c13 */ + tmp12 += z2; + z2 = MULTIPLY(z3 + z4, - FIX(1.353318001)); /* -c3 */ + tmp2 += z2; + tmp3 += z2; + z2 = MULTIPLY(z4 - z3, FIX(0.410524528)); /* c13 */ + tmp10 += z2; + tmp11 += z2; + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[15] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[14] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[13] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26 + tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp26 - tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp27 + tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp27 - tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 8; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 14x7 output block. + * + * 7-point IDCT in pass 1 (columns), 14-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_14x7 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[8*7]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. + * 7-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/14). + */ + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp23 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp23 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + tmp23 += ONE << (CONST_BITS-PASS1_BITS-1); + + z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + tmp20 = MULTIPLY(z2 - z3, FIX(0.881747734)); /* c4 */ + tmp22 = MULTIPLY(z1 - z2, FIX(0.314692123)); /* c6 */ + tmp21 = tmp20 + tmp22 + tmp23 - MULTIPLY(z2, FIX(1.841218003)); /* c2+c4-c6 */ + tmp10 = z1 + z3; + z2 -= tmp10; + tmp10 = MULTIPLY(tmp10, FIX(1.274162392)) + tmp23; /* c2 */ + tmp20 += tmp10 - MULTIPLY(z3, FIX(0.077722536)); /* c2-c4-c6 */ + tmp22 += tmp10 - MULTIPLY(z1, FIX(2.470602249)); /* c2+c4+c6 */ + tmp23 += MULTIPLY(z2, FIX(1.414213562)); /* c0 */ + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + + tmp11 = MULTIPLY(z1 + z2, FIX(0.935414347)); /* (c3+c1-c5)/2 */ + tmp12 = MULTIPLY(z1 - z2, FIX(0.170262339)); /* (c3+c5-c1)/2 */ + tmp10 = tmp11 - tmp12; + tmp11 += tmp12; + tmp12 = MULTIPLY(z2 + z3, - FIX(1.378756276)); /* -c1 */ + tmp11 += tmp12; + z2 = MULTIPLY(z1 + z3, FIX(0.613604268)); /* c5 */ + tmp10 += z2; + tmp12 += z2 + MULTIPLY(z3, FIX(1.870828693)); /* c3+c1-c5 */ + + /* Final output stage */ + + wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*6] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*5] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*4] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*3] = (int) RIGHT_SHIFT(tmp23, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 7 rows from work array, store into output array. + * 14-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/28). + */ + wsptr = workspace; + for (ctr = 0; ctr < 7; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + z1 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + z1 <<= CONST_BITS; + z4 = (INT32) wsptr[4]; + z2 = MULTIPLY(z4, FIX(1.274162392)); /* c4 */ + z3 = MULTIPLY(z4, FIX(0.314692123)); /* c12 */ + z4 = MULTIPLY(z4, FIX(0.881747734)); /* c8 */ + + tmp10 = z1 + z2; + tmp11 = z1 + z3; + tmp12 = z1 - z4; + + tmp23 = z1 - ((z2 + z3 - z4) << 1); /* c0 = (c4+c12-c8)*2 */ + + z1 = (INT32) wsptr[2]; + z2 = (INT32) wsptr[6]; + + z3 = MULTIPLY(z1 + z2, FIX(1.105676686)); /* c6 */ + + tmp13 = z3 + MULTIPLY(z1, FIX(0.273079590)); /* c2-c6 */ + tmp14 = z3 - MULTIPLY(z2, FIX(1.719280954)); /* c6+c10 */ + tmp15 = MULTIPLY(z1, FIX(0.613604268)) - /* c10 */ + MULTIPLY(z2, FIX(1.378756276)); /* c2 */ + + tmp20 = tmp10 + tmp13; + tmp26 = tmp10 - tmp13; + tmp21 = tmp11 + tmp14; + tmp25 = tmp11 - tmp14; + tmp22 = tmp12 + tmp15; + tmp24 = tmp12 - tmp15; + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + z4 = (INT32) wsptr[7]; + z4 <<= CONST_BITS; + + tmp14 = z1 + z3; + tmp11 = MULTIPLY(z1 + z2, FIX(1.334852607)); /* c3 */ + tmp12 = MULTIPLY(tmp14, FIX(1.197448846)); /* c5 */ + tmp10 = tmp11 + tmp12 + z4 - MULTIPLY(z1, FIX(1.126980169)); /* c3+c5-c1 */ + tmp14 = MULTIPLY(tmp14, FIX(0.752406978)); /* c9 */ + tmp16 = tmp14 - MULTIPLY(z1, FIX(1.061150426)); /* c9+c11-c13 */ + z1 -= z2; + tmp15 = MULTIPLY(z1, FIX(0.467085129)) - z4; /* c11 */ + tmp16 += tmp15; + tmp13 = MULTIPLY(z2 + z3, - FIX(0.158341681)) - z4; /* -c13 */ + tmp11 += tmp13 - MULTIPLY(z2, FIX(0.424103948)); /* c3-c9-c13 */ + tmp12 += tmp13 - MULTIPLY(z3, FIX(2.373959773)); /* c3+c5-c13 */ + tmp13 = MULTIPLY(z3 - z2, FIX(1.405321284)); /* c1 */ + tmp14 += tmp13 + z4 - MULTIPLY(z3, FIX(1.6906431334)); /* c1+c9-c11 */ + tmp15 += tmp13 + MULTIPLY(z2, FIX(0.674957567)); /* c1+c11-c5 */ + + tmp13 = ((z1 - z3) << CONST_BITS) + z4; + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[13] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26 + tmp16, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp26 - tmp16, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 8; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 12x6 output block. + * + * 6-point IDCT in pass 1 (columns), 12-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_12x6 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[8*6]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. + * 6-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/12). + */ + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp10 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp10 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + tmp10 += ONE << (CONST_BITS-PASS1_BITS-1); + tmp12 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + tmp20 = MULTIPLY(tmp12, FIX(0.707106781)); /* c4 */ + tmp11 = tmp10 + tmp20; + tmp21 = RIGHT_SHIFT(tmp10 - tmp20 - tmp20, CONST_BITS-PASS1_BITS); + tmp20 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + tmp10 = MULTIPLY(tmp20, FIX(1.224744871)); /* c2 */ + tmp20 = tmp11 + tmp10; + tmp22 = tmp11 - tmp10; + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp11 = MULTIPLY(z1 + z3, FIX(0.366025404)); /* c5 */ + tmp10 = tmp11 + ((z1 + z2) << CONST_BITS); + tmp12 = tmp11 + ((z3 - z2) << CONST_BITS); + tmp11 = (z1 - z2 - z3) << PASS1_BITS; + + /* Final output stage */ + + wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*5] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*1] = (int) (tmp21 + tmp11); + wsptr[8*4] = (int) (tmp21 - tmp11); + wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*3] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 6 rows from work array, store into output array. + * 12-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/24). + */ + wsptr = workspace; + for (ctr = 0; ctr < 6; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + z3 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + z3 <<= CONST_BITS; + + z4 = (INT32) wsptr[4]; + z4 = MULTIPLY(z4, FIX(1.224744871)); /* c4 */ + + tmp10 = z3 + z4; + tmp11 = z3 - z4; + + z1 = (INT32) wsptr[2]; + z4 = MULTIPLY(z1, FIX(1.366025404)); /* c2 */ + z1 <<= CONST_BITS; + z2 = (INT32) wsptr[6]; + z2 <<= CONST_BITS; + + tmp12 = z1 - z2; + + tmp21 = z3 + tmp12; + tmp24 = z3 - tmp12; + + tmp12 = z4 + z2; + + tmp20 = tmp10 + tmp12; + tmp25 = tmp10 - tmp12; + + tmp12 = z4 - z1 - z2; + + tmp22 = tmp11 + tmp12; + tmp23 = tmp11 - tmp12; + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + z4 = (INT32) wsptr[7]; + + tmp11 = MULTIPLY(z2, FIX(1.306562965)); /* c3 */ + tmp14 = MULTIPLY(z2, - FIX_0_541196100); /* -c9 */ + + tmp10 = z1 + z3; + tmp15 = MULTIPLY(tmp10 + z4, FIX(0.860918669)); /* c7 */ + tmp12 = tmp15 + MULTIPLY(tmp10, FIX(0.261052384)); /* c5-c7 */ + tmp10 = tmp12 + tmp11 + MULTIPLY(z1, FIX(0.280143716)); /* c1-c5 */ + tmp13 = MULTIPLY(z3 + z4, - FIX(1.045510580)); /* -(c7+c11) */ + tmp12 += tmp13 + tmp14 - MULTIPLY(z3, FIX(1.478575242)); /* c1+c5-c7-c11 */ + tmp13 += tmp15 - tmp11 + MULTIPLY(z4, FIX(1.586706681)); /* c1+c11 */ + tmp15 += tmp14 - MULTIPLY(z1, FIX(0.676326758)) - /* c7-c11 */ + MULTIPLY(z4, FIX(1.982889723)); /* c5+c7 */ + + z1 -= z4; + z2 -= z3; + z3 = MULTIPLY(z1 + z2, FIX_0_541196100); /* c9 */ + tmp11 = z3 + MULTIPLY(z1, FIX_0_765366865); /* c3-c9 */ + tmp14 = z3 - MULTIPLY(z2, FIX_1_847759065); /* c3+c9 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 8; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 10x5 output block. + * + * 5-point IDCT in pass 1 (columns), 10-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_10x5 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp10, tmp11, tmp12, tmp13, tmp14; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[8*5]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. + * 5-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/10). + */ + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp12 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp12 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + tmp12 += ONE << (CONST_BITS-PASS1_BITS-1); + tmp13 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + tmp14 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z1 = MULTIPLY(tmp13 + tmp14, FIX(0.790569415)); /* (c2+c4)/2 */ + z2 = MULTIPLY(tmp13 - tmp14, FIX(0.353553391)); /* (c2-c4)/2 */ + z3 = tmp12 + z2; + tmp10 = z3 + z1; + tmp11 = z3 - z1; + tmp12 -= z2 << 2; + + /* Odd part */ + + z2 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + + z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c3 */ + tmp13 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c1-c3 */ + tmp14 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c1+c3 */ + + /* Final output stage */ + + wsptr[8*0] = (int) RIGHT_SHIFT(tmp10 + tmp13, CONST_BITS-PASS1_BITS); + wsptr[8*4] = (int) RIGHT_SHIFT(tmp10 - tmp13, CONST_BITS-PASS1_BITS); + wsptr[8*1] = (int) RIGHT_SHIFT(tmp11 + tmp14, CONST_BITS-PASS1_BITS); + wsptr[8*3] = (int) RIGHT_SHIFT(tmp11 - tmp14, CONST_BITS-PASS1_BITS); + wsptr[8*2] = (int) RIGHT_SHIFT(tmp12, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 5 rows from work array, store into output array. + * 10-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/20). + */ + wsptr = workspace; + for (ctr = 0; ctr < 5; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + z3 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + z3 <<= CONST_BITS; + z4 = (INT32) wsptr[4]; + z1 = MULTIPLY(z4, FIX(1.144122806)); /* c4 */ + z2 = MULTIPLY(z4, FIX(0.437016024)); /* c8 */ + tmp10 = z3 + z1; + tmp11 = z3 - z2; + + tmp22 = z3 - ((z1 - z2) << 1); /* c0 = (c4-c8)*2 */ + + z2 = (INT32) wsptr[2]; + z3 = (INT32) wsptr[6]; + + z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c6 */ + tmp12 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c2-c6 */ + tmp13 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c2+c6 */ + + tmp20 = tmp10 + tmp12; + tmp24 = tmp10 - tmp12; + tmp21 = tmp11 + tmp13; + tmp23 = tmp11 - tmp13; + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + z3 <<= CONST_BITS; + z4 = (INT32) wsptr[7]; + + tmp11 = z2 + z4; + tmp13 = z2 - z4; + + tmp12 = MULTIPLY(tmp13, FIX(0.309016994)); /* (c3-c7)/2 */ + + z2 = MULTIPLY(tmp11, FIX(0.951056516)); /* (c3+c7)/2 */ + z4 = z3 + tmp12; + + tmp10 = MULTIPLY(z1, FIX(1.396802247)) + z2 + z4; /* c1 */ + tmp14 = MULTIPLY(z1, FIX(0.221231742)) - z2 + z4; /* c9 */ + + z2 = MULTIPLY(tmp11, FIX(0.587785252)); /* (c1-c9)/2 */ + z4 = z3 - tmp12 - (tmp13 << (CONST_BITS - 1)); + + tmp12 = ((z1 - tmp13) << CONST_BITS) - z3; + + tmp11 = MULTIPLY(z1, FIX(1.260073511)) - z2 - z4; /* c3 */ + tmp13 = MULTIPLY(z1, FIX(0.642039522)) - z2 + z4; /* c7 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 8; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 8x4 output block. + * + * 4-point IDCT in pass 1 (columns), 8-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_8x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3; + INT32 tmp10, tmp11, tmp12, tmp13; + INT32 z1, z2, z3; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[8*4]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. + * 4-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/16). + */ + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + + tmp10 = (tmp0 + tmp2) << PASS1_BITS; + tmp12 = (tmp0 - tmp2) << PASS1_BITS; + + /* Odd part */ + /* Same rotation as in the even part of the 8x8 LL&M IDCT */ + + z2 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ + /* Add fudge factor here for final descale. */ + z1 += ONE << (CONST_BITS-PASS1_BITS-1); + tmp0 = RIGHT_SHIFT(z1 + MULTIPLY(z2, FIX_0_765366865), /* c2-c6 */ + CONST_BITS-PASS1_BITS); + tmp2 = RIGHT_SHIFT(z1 - MULTIPLY(z3, FIX_1_847759065), /* c2+c6 */ + CONST_BITS-PASS1_BITS); + + /* Final output stage */ + + wsptr[8*0] = (int) (tmp10 + tmp0); + wsptr[8*3] = (int) (tmp10 - tmp0); + wsptr[8*1] = (int) (tmp12 + tmp2); + wsptr[8*2] = (int) (tmp12 - tmp2); + } + + /* Pass 2: process rows from work array, store into output array. */ + /* Note that we must descale the results by a factor of 8 == 2**3, */ + /* and also undo the PASS1_BITS scaling. */ + + wsptr = workspace; + for (ctr = 0; ctr < 4; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part: reverse the even part of the forward DCT. */ + /* The rotator is sqrt(2)*c(-6). */ + + z2 = (INT32) wsptr[2]; + z3 = (INT32) wsptr[6]; + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); + tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); + + /* Add fudge factor here for final descale. */ + z2 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + z3 = (INT32) wsptr[4]; + + tmp0 = (z2 + z3) << CONST_BITS; + tmp1 = (z2 - z3) << CONST_BITS; + + tmp10 = tmp0 + tmp2; + tmp13 = tmp0 - tmp2; + tmp11 = tmp1 + tmp3; + tmp12 = tmp1 - tmp3; + + /* Odd part per figure 8; the matrix is unitary and hence its + * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. + */ + + tmp0 = (INT32) wsptr[7]; + tmp1 = (INT32) wsptr[5]; + tmp2 = (INT32) wsptr[3]; + tmp3 = (INT32) wsptr[1]; + + z2 = tmp0 + tmp2; + z3 = tmp1 + tmp3; + + z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* sqrt(2) * c3 */ + z2 = MULTIPLY(z2, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z3 = MULTIPLY(z3, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + z2 += z1; + z3 += z1; + + z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + tmp0 += z1 + z2; + tmp3 += z1 + z3; + + z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp1 += z1 + z3; + tmp2 += z1 + z2; + + /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp3, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp13 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp13 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 6x3 output block. + * + * 3-point IDCT in pass 1 (columns), 6-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_6x3 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp1, tmp2, tmp10, tmp11, tmp12; + INT32 z1, z2, z3; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[6*3]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. + * 3-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/6). + */ + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 6; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp0 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + tmp0 += ONE << (CONST_BITS-PASS1_BITS-1); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + tmp12 = MULTIPLY(tmp2, FIX(0.707106781)); /* c2 */ + tmp10 = tmp0 + tmp12; + tmp2 = tmp0 - tmp12 - tmp12; + + /* Odd part */ + + tmp12 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + tmp0 = MULTIPLY(tmp12, FIX(1.224744871)); /* c1 */ + + /* Final output stage */ + + wsptr[6*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[6*2] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS); + wsptr[6*1] = (int) RIGHT_SHIFT(tmp2, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 3 rows from work array, store into output array. + * 6-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/12). + */ + wsptr = workspace; + for (ctr = 0; ctr < 3; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + tmp0 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + tmp0 <<= CONST_BITS; + tmp2 = (INT32) wsptr[4]; + tmp10 = MULTIPLY(tmp2, FIX(0.707106781)); /* c4 */ + tmp1 = tmp0 + tmp10; + tmp11 = tmp0 - tmp10 - tmp10; + tmp10 = (INT32) wsptr[2]; + tmp0 = MULTIPLY(tmp10, FIX(1.224744871)); /* c2 */ + tmp10 = tmp1 + tmp0; + tmp12 = tmp1 - tmp0; + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + tmp1 = MULTIPLY(z1 + z3, FIX(0.366025404)); /* c5 */ + tmp0 = tmp1 + ((z1 + z2) << CONST_BITS); + tmp2 = tmp1 + ((z3 - z2) << CONST_BITS); + tmp1 = (z1 - z2 - z3) << CONST_BITS; + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp1, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 6; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 4x2 output block. + * + * 2-point IDCT in pass 1 (columns), 4-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_4x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp2, tmp10, tmp12; + INT32 z1, z2, z3; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + INT32 * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + INT32 workspace[4*2]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 4; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp10 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + + /* Odd part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + + /* Final output stage */ + + wsptr[4*0] = tmp10 + tmp0; + wsptr[4*1] = tmp10 - tmp0; + } + + /* Pass 2: process 2 rows from work array, store into output array. + * 4-point IDCT kernel, + * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point IDCT]. + */ + wsptr = workspace; + for (ctr = 0; ctr < 2; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + tmp0 = wsptr[0] + (ONE << 2); + tmp2 = wsptr[2]; + + tmp10 = (tmp0 + tmp2) << CONST_BITS; + tmp12 = (tmp0 - tmp2) << CONST_BITS; + + /* Odd part */ + /* Same rotation as in the even part of the 8x8 LL&M IDCT */ + + z2 = wsptr[1]; + z3 = wsptr[3]; + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ + tmp0 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ + tmp2 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, + CONST_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, + CONST_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2, + CONST_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2, + CONST_BITS+3) + & RANGE_MASK]; + + wsptr += 4; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 2x1 output block. + * + * 1-point IDCT in pass 1 (columns), 2-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_2x1 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp10; + ISLOW_MULT_TYPE * quantptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + SHIFT_TEMPS + + /* Pass 1: empty. */ + + /* Pass 2: process 1 row from input, store into output array. */ + + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + outptr = output_buf[0] + output_col; + + /* Even part */ + + tmp10 = DEQUANTIZE(coef_block[0], quantptr[0]); + /* Add fudge factor here for final descale. */ + tmp10 += ONE << 2; + + /* Odd part */ + + tmp0 = DEQUANTIZE(coef_block[1], quantptr[1]); + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, 3) & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, 3) & RANGE_MASK]; +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 8x16 output block. + * + * 16-point IDCT in pass 1 (columns), 8-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_8x16 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3, tmp10, tmp11, tmp12, tmp13; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[8*16]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. + * 16-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/32). + */ + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp0 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + tmp0 += ONE << (CONST_BITS-PASS1_BITS-1); + + z1 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + tmp1 = MULTIPLY(z1, FIX(1.306562965)); /* c4[16] = c2[8] */ + tmp2 = MULTIPLY(z1, FIX_0_541196100); /* c12[16] = c6[8] */ + + tmp10 = tmp0 + tmp1; + tmp11 = tmp0 - tmp1; + tmp12 = tmp0 + tmp2; + tmp13 = tmp0 - tmp2; + + z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + z3 = z1 - z2; + z4 = MULTIPLY(z3, FIX(0.275899379)); /* c14[16] = c7[8] */ + z3 = MULTIPLY(z3, FIX(1.387039845)); /* c2[16] = c1[8] */ + + tmp0 = z3 + MULTIPLY(z2, FIX_2_562915447); /* (c6+c2)[16] = (c3+c1)[8] */ + tmp1 = z4 + MULTIPLY(z1, FIX_0_899976223); /* (c6-c14)[16] = (c3-c7)[8] */ + tmp2 = z3 - MULTIPLY(z1, FIX(0.601344887)); /* (c2-c10)[16] = (c1-c5)[8] */ + tmp3 = z4 - MULTIPLY(z2, FIX(0.509795579)); /* (c10-c14)[16] = (c5-c7)[8] */ + + tmp20 = tmp10 + tmp0; + tmp27 = tmp10 - tmp0; + tmp21 = tmp12 + tmp1; + tmp26 = tmp12 - tmp1; + tmp22 = tmp13 + tmp2; + tmp25 = tmp13 - tmp2; + tmp23 = tmp11 + tmp3; + tmp24 = tmp11 - tmp3; + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + tmp11 = z1 + z3; + + tmp1 = MULTIPLY(z1 + z2, FIX(1.353318001)); /* c3 */ + tmp2 = MULTIPLY(tmp11, FIX(1.247225013)); /* c5 */ + tmp3 = MULTIPLY(z1 + z4, FIX(1.093201867)); /* c7 */ + tmp10 = MULTIPLY(z1 - z4, FIX(0.897167586)); /* c9 */ + tmp11 = MULTIPLY(tmp11, FIX(0.666655658)); /* c11 */ + tmp12 = MULTIPLY(z1 - z2, FIX(0.410524528)); /* c13 */ + tmp0 = tmp1 + tmp2 + tmp3 - + MULTIPLY(z1, FIX(2.286341144)); /* c7+c5+c3-c1 */ + tmp13 = tmp10 + tmp11 + tmp12 - + MULTIPLY(z1, FIX(1.835730603)); /* c9+c11+c13-c15 */ + z1 = MULTIPLY(z2 + z3, FIX(0.138617169)); /* c15 */ + tmp1 += z1 + MULTIPLY(z2, FIX(0.071888074)); /* c9+c11-c3-c15 */ + tmp2 += z1 - MULTIPLY(z3, FIX(1.125726048)); /* c5+c7+c15-c3 */ + z1 = MULTIPLY(z3 - z2, FIX(1.407403738)); /* c1 */ + tmp11 += z1 - MULTIPLY(z3, FIX(0.766367282)); /* c1+c11-c9-c13 */ + tmp12 += z1 + MULTIPLY(z2, FIX(1.971951411)); /* c1+c5+c13-c7 */ + z2 += z4; + z1 = MULTIPLY(z2, - FIX(0.666655658)); /* -c11 */ + tmp1 += z1; + tmp3 += z1 + MULTIPLY(z4, FIX(1.065388962)); /* c3+c11+c15-c7 */ + z2 = MULTIPLY(z2, - FIX(1.247225013)); /* -c5 */ + tmp10 += z2 + MULTIPLY(z4, FIX(3.141271809)); /* c1+c5+c9-c13 */ + tmp12 += z2; + z2 = MULTIPLY(z3 + z4, - FIX(1.353318001)); /* -c3 */ + tmp2 += z2; + tmp3 += z2; + z2 = MULTIPLY(z4 - z3, FIX(0.410524528)); /* c13 */ + tmp10 += z2; + tmp11 += z2; + + /* Final output stage */ + + wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[8*15] = (int) RIGHT_SHIFT(tmp20 - tmp0, CONST_BITS-PASS1_BITS); + wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp1, CONST_BITS-PASS1_BITS); + wsptr[8*14] = (int) RIGHT_SHIFT(tmp21 - tmp1, CONST_BITS-PASS1_BITS); + wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp2, CONST_BITS-PASS1_BITS); + wsptr[8*13] = (int) RIGHT_SHIFT(tmp22 - tmp2, CONST_BITS-PASS1_BITS); + wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp3, CONST_BITS-PASS1_BITS); + wsptr[8*12] = (int) RIGHT_SHIFT(tmp23 - tmp3, CONST_BITS-PASS1_BITS); + wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*11] = (int) RIGHT_SHIFT(tmp24 - tmp10, CONST_BITS-PASS1_BITS); + wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*10] = (int) RIGHT_SHIFT(tmp25 - tmp11, CONST_BITS-PASS1_BITS); + wsptr[8*6] = (int) RIGHT_SHIFT(tmp26 + tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*9] = (int) RIGHT_SHIFT(tmp26 - tmp12, CONST_BITS-PASS1_BITS); + wsptr[8*7] = (int) RIGHT_SHIFT(tmp27 + tmp13, CONST_BITS-PASS1_BITS); + wsptr[8*8] = (int) RIGHT_SHIFT(tmp27 - tmp13, CONST_BITS-PASS1_BITS); + } /* Pass 2: process rows from work array, store into output array. */ /* Note that we must descale the results by a factor of 8 == 2**3, */ /* and also undo the PASS1_BITS scaling. */ wsptr = workspace; - for (ctr = 0; ctr < DCTSIZE; ctr++) { + for (ctr = 0; ctr < 16; ctr++) { outptr = output_buf[ctr] + output_col; - /* Rows of zeroes can be exploited in the same way as we did with columns. - * However, the column calculation has created many nonzero AC terms, so - * the simplification applies less often (typically 5% to 10% of the time). - * On machines with very fast multiplication, it's possible that the - * test takes more time than it's worth. In that case this section - * may be commented out. - */ - -#ifndef NO_ZERO_ROW_TEST - if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 && - wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { - /* AC terms all zero */ - JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3) - & RANGE_MASK]; - - outptr[0] = dcval; - outptr[1] = dcval; - outptr[2] = dcval; - outptr[3] = dcval; - outptr[4] = dcval; - outptr[5] = dcval; - outptr[6] = dcval; - outptr[7] = dcval; - - wsptr += DCTSIZE; /* advance pointer to next row */ - continue; - } -#endif /* Even part: reverse the even part of the forward DCT. */ /* The rotator is sqrt(2)*c(-6). */ @@ -312,16 +4150,20 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, z3 = (INT32) wsptr[6]; z1 = MULTIPLY(z2 + z3, FIX_0_541196100); - tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065); - tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865); + tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); + tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); - tmp0 = ((INT32) wsptr[0] + (INT32) wsptr[4]) << CONST_BITS; - tmp1 = ((INT32) wsptr[0] - (INT32) wsptr[4]) << CONST_BITS; + /* Add fudge factor here for final descale. */ + z2 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + z3 = (INT32) wsptr[4]; - tmp10 = tmp0 + tmp3; - tmp13 = tmp0 - tmp3; - tmp11 = tmp1 + tmp2; - tmp12 = tmp1 - tmp2; + tmp0 = (z2 + z3) << CONST_BITS; + tmp1 = (z2 - z3) << CONST_BITS; + + tmp10 = tmp0 + tmp2; + tmp13 = tmp0 - tmp2; + tmp11 = tmp1 + tmp3; + tmp12 = tmp1 - tmp3; /* Odd part per figure 8; the matrix is unitary and hence its * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. @@ -332,58 +4174,964 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, tmp2 = (INT32) wsptr[3]; tmp3 = (INT32) wsptr[1]; - z1 = tmp0 + tmp3; - z2 = tmp1 + tmp2; - z3 = tmp0 + tmp2; - z4 = tmp1 + tmp3; - z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ - + z2 = tmp0 + tmp2; + z3 = tmp1 + tmp3; + + z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* sqrt(2) * c3 */ + z2 = MULTIPLY(z2, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z3 = MULTIPLY(z3, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + z2 += z1; + z3 += z1; + + z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + tmp0 += z1 + z2; + tmp3 += z1 + z3; + + z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ - tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ - z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ - z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ - z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ - z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ - - z3 += z5; - z4 += z5; - - tmp0 += z1 + z3; - tmp1 += z2 + z4; - tmp2 += z2 + z3; - tmp3 += z1 + z4; + tmp1 += z1 + z3; + tmp2 += z1 + z2; /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ - outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp3, - CONST_BITS+PASS1_BITS+3) + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp3, + CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; - outptr[7] = range_limit[(int) DESCALE(tmp10 - tmp3, - CONST_BITS+PASS1_BITS+3) + outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp3, + CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; - outptr[1] = range_limit[(int) DESCALE(tmp11 + tmp2, - CONST_BITS+PASS1_BITS+3) + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp2, + CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; - outptr[6] = range_limit[(int) DESCALE(tmp11 - tmp2, - CONST_BITS+PASS1_BITS+3) + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp2, + CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; - outptr[2] = range_limit[(int) DESCALE(tmp12 + tmp1, - CONST_BITS+PASS1_BITS+3) + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp1, + CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; - outptr[5] = range_limit[(int) DESCALE(tmp12 - tmp1, - CONST_BITS+PASS1_BITS+3) + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp1, + CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; - outptr[3] = range_limit[(int) DESCALE(tmp13 + tmp0, - CONST_BITS+PASS1_BITS+3) + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp13 + tmp0, + CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; - outptr[4] = range_limit[(int) DESCALE(tmp13 - tmp0, - CONST_BITS+PASS1_BITS+3) + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp13 - tmp0, + CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; wsptr += DCTSIZE; /* advance pointer to next row */ } } + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 7x14 output block. + * + * 14-point IDCT in pass 1 (columns), 7-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_7x14 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[7*14]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. + * 14-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/28). + */ + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 7; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + z1 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + z1 += ONE << (CONST_BITS-PASS1_BITS-1); + z4 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z2 = MULTIPLY(z4, FIX(1.274162392)); /* c4 */ + z3 = MULTIPLY(z4, FIX(0.314692123)); /* c12 */ + z4 = MULTIPLY(z4, FIX(0.881747734)); /* c8 */ + + tmp10 = z1 + z2; + tmp11 = z1 + z3; + tmp12 = z1 - z4; + + tmp23 = RIGHT_SHIFT(z1 - ((z2 + z3 - z4) << 1), /* c0 = (c4+c12-c8)*2 */ + CONST_BITS-PASS1_BITS); + + z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + z3 = MULTIPLY(z1 + z2, FIX(1.105676686)); /* c6 */ + + tmp13 = z3 + MULTIPLY(z1, FIX(0.273079590)); /* c2-c6 */ + tmp14 = z3 - MULTIPLY(z2, FIX(1.719280954)); /* c6+c10 */ + tmp15 = MULTIPLY(z1, FIX(0.613604268)) - /* c10 */ + MULTIPLY(z2, FIX(1.378756276)); /* c2 */ + + tmp20 = tmp10 + tmp13; + tmp26 = tmp10 - tmp13; + tmp21 = tmp11 + tmp14; + tmp25 = tmp11 - tmp14; + tmp22 = tmp12 + tmp15; + tmp24 = tmp12 - tmp15; + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + tmp13 = z4 << CONST_BITS; + + tmp14 = z1 + z3; + tmp11 = MULTIPLY(z1 + z2, FIX(1.334852607)); /* c3 */ + tmp12 = MULTIPLY(tmp14, FIX(1.197448846)); /* c5 */ + tmp10 = tmp11 + tmp12 + tmp13 - MULTIPLY(z1, FIX(1.126980169)); /* c3+c5-c1 */ + tmp14 = MULTIPLY(tmp14, FIX(0.752406978)); /* c9 */ + tmp16 = tmp14 - MULTIPLY(z1, FIX(1.061150426)); /* c9+c11-c13 */ + z1 -= z2; + tmp15 = MULTIPLY(z1, FIX(0.467085129)) - tmp13; /* c11 */ + tmp16 += tmp15; + z1 += z4; + z4 = MULTIPLY(z2 + z3, - FIX(0.158341681)) - tmp13; /* -c13 */ + tmp11 += z4 - MULTIPLY(z2, FIX(0.424103948)); /* c3-c9-c13 */ + tmp12 += z4 - MULTIPLY(z3, FIX(2.373959773)); /* c3+c5-c13 */ + z4 = MULTIPLY(z3 - z2, FIX(1.405321284)); /* c1 */ + tmp14 += z4 + tmp13 - MULTIPLY(z3, FIX(1.6906431334)); /* c1+c9-c11 */ + tmp15 += z4 + MULTIPLY(z2, FIX(0.674957567)); /* c1+c11-c5 */ + + tmp13 = (z1 - z3) << PASS1_BITS; + + /* Final output stage */ + + wsptr[7*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); + wsptr[7*13] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); + wsptr[7*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); + wsptr[7*12] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); + wsptr[7*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); + wsptr[7*11] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); + wsptr[7*3] = (int) (tmp23 + tmp13); + wsptr[7*10] = (int) (tmp23 - tmp13); + wsptr[7*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); + wsptr[7*9] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); + wsptr[7*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS); + wsptr[7*8] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS); + wsptr[7*6] = (int) RIGHT_SHIFT(tmp26 + tmp16, CONST_BITS-PASS1_BITS); + wsptr[7*7] = (int) RIGHT_SHIFT(tmp26 - tmp16, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 14 rows from work array, store into output array. + * 7-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/14). + */ + wsptr = workspace; + for (ctr = 0; ctr < 14; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + tmp23 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + tmp23 <<= CONST_BITS; + + z1 = (INT32) wsptr[2]; + z2 = (INT32) wsptr[4]; + z3 = (INT32) wsptr[6]; + + tmp20 = MULTIPLY(z2 - z3, FIX(0.881747734)); /* c4 */ + tmp22 = MULTIPLY(z1 - z2, FIX(0.314692123)); /* c6 */ + tmp21 = tmp20 + tmp22 + tmp23 - MULTIPLY(z2, FIX(1.841218003)); /* c2+c4-c6 */ + tmp10 = z1 + z3; + z2 -= tmp10; + tmp10 = MULTIPLY(tmp10, FIX(1.274162392)) + tmp23; /* c2 */ + tmp20 += tmp10 - MULTIPLY(z3, FIX(0.077722536)); /* c2-c4-c6 */ + tmp22 += tmp10 - MULTIPLY(z1, FIX(2.470602249)); /* c2+c4+c6 */ + tmp23 += MULTIPLY(z2, FIX(1.414213562)); /* c0 */ + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + + tmp11 = MULTIPLY(z1 + z2, FIX(0.935414347)); /* (c3+c1-c5)/2 */ + tmp12 = MULTIPLY(z1 - z2, FIX(0.170262339)); /* (c3+c5-c1)/2 */ + tmp10 = tmp11 - tmp12; + tmp11 += tmp12; + tmp12 = MULTIPLY(z2 + z3, - FIX(1.378756276)); /* -c1 */ + tmp11 += tmp12; + z2 = MULTIPLY(z1 + z3, FIX(0.613604268)); /* c5 */ + tmp10 += z2; + tmp12 += z2 + MULTIPLY(z3, FIX(1.870828693)); /* c3+c1-c5 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 7; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 6x12 output block. + * + * 12-point IDCT in pass 1 (columns), 6-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_6x12 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25; + INT32 z1, z2, z3, z4; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[6*12]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. + * 12-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/24). + */ + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 6; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + z3 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + z3 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + z3 += ONE << (CONST_BITS-PASS1_BITS-1); + + z4 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z4 = MULTIPLY(z4, FIX(1.224744871)); /* c4 */ + + tmp10 = z3 + z4; + tmp11 = z3 - z4; + + z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z4 = MULTIPLY(z1, FIX(1.366025404)); /* c2 */ + z1 <<= CONST_BITS; + z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + z2 <<= CONST_BITS; + + tmp12 = z1 - z2; + + tmp21 = z3 + tmp12; + tmp24 = z3 - tmp12; + + tmp12 = z4 + z2; + + tmp20 = tmp10 + tmp12; + tmp25 = tmp10 - tmp12; + + tmp12 = z4 - z1 - z2; + + tmp22 = tmp11 + tmp12; + tmp23 = tmp11 - tmp12; + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + tmp11 = MULTIPLY(z2, FIX(1.306562965)); /* c3 */ + tmp14 = MULTIPLY(z2, - FIX_0_541196100); /* -c9 */ + + tmp10 = z1 + z3; + tmp15 = MULTIPLY(tmp10 + z4, FIX(0.860918669)); /* c7 */ + tmp12 = tmp15 + MULTIPLY(tmp10, FIX(0.261052384)); /* c5-c7 */ + tmp10 = tmp12 + tmp11 + MULTIPLY(z1, FIX(0.280143716)); /* c1-c5 */ + tmp13 = MULTIPLY(z3 + z4, - FIX(1.045510580)); /* -(c7+c11) */ + tmp12 += tmp13 + tmp14 - MULTIPLY(z3, FIX(1.478575242)); /* c1+c5-c7-c11 */ + tmp13 += tmp15 - tmp11 + MULTIPLY(z4, FIX(1.586706681)); /* c1+c11 */ + tmp15 += tmp14 - MULTIPLY(z1, FIX(0.676326758)) - /* c7-c11 */ + MULTIPLY(z4, FIX(1.982889723)); /* c5+c7 */ + + z1 -= z4; + z2 -= z3; + z3 = MULTIPLY(z1 + z2, FIX_0_541196100); /* c9 */ + tmp11 = z3 + MULTIPLY(z1, FIX_0_765366865); /* c3-c9 */ + tmp14 = z3 - MULTIPLY(z2, FIX_1_847759065); /* c3+c9 */ + + /* Final output stage */ + + wsptr[6*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); + wsptr[6*11] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); + wsptr[6*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); + wsptr[6*10] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); + wsptr[6*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS); + wsptr[6*9] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS); + wsptr[6*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS); + wsptr[6*8] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS); + wsptr[6*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); + wsptr[6*7] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); + wsptr[6*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS); + wsptr[6*6] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 12 rows from work array, store into output array. + * 6-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/12). + */ + wsptr = workspace; + for (ctr = 0; ctr < 12; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + tmp10 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + tmp10 <<= CONST_BITS; + tmp12 = (INT32) wsptr[4]; + tmp20 = MULTIPLY(tmp12, FIX(0.707106781)); /* c4 */ + tmp11 = tmp10 + tmp20; + tmp21 = tmp10 - tmp20 - tmp20; + tmp20 = (INT32) wsptr[2]; + tmp10 = MULTIPLY(tmp20, FIX(1.224744871)); /* c2 */ + tmp20 = tmp11 + tmp10; + tmp22 = tmp11 - tmp10; + + /* Odd part */ + + z1 = (INT32) wsptr[1]; + z2 = (INT32) wsptr[3]; + z3 = (INT32) wsptr[5]; + tmp11 = MULTIPLY(z1 + z3, FIX(0.366025404)); /* c5 */ + tmp10 = tmp11 + ((z1 + z2) << CONST_BITS); + tmp12 = tmp11 + ((z3 - z2) << CONST_BITS); + tmp11 = (z1 - z2 - z3) << CONST_BITS; + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 6; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 5x10 output block. + * + * 10-point IDCT in pass 1 (columns), 5-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_5x10 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp10, tmp11, tmp12, tmp13, tmp14; + INT32 tmp20, tmp21, tmp22, tmp23, tmp24; + INT32 z1, z2, z3, z4, z5; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[5*10]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. + * 10-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/20). + */ + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 5; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + z3 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + z3 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + z3 += ONE << (CONST_BITS-PASS1_BITS-1); + z4 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z1 = MULTIPLY(z4, FIX(1.144122806)); /* c4 */ + z2 = MULTIPLY(z4, FIX(0.437016024)); /* c8 */ + tmp10 = z3 + z1; + tmp11 = z3 - z2; + + tmp22 = RIGHT_SHIFT(z3 - ((z1 - z2) << 1), /* c0 = (c4-c8)*2 */ + CONST_BITS-PASS1_BITS); + + z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c6 */ + tmp12 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c2-c6 */ + tmp13 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c2+c6 */ + + tmp20 = tmp10 + tmp12; + tmp24 = tmp10 - tmp12; + tmp21 = tmp11 + tmp13; + tmp23 = tmp11 - tmp13; + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + tmp11 = z2 + z4; + tmp13 = z2 - z4; + + tmp12 = MULTIPLY(tmp13, FIX(0.309016994)); /* (c3-c7)/2 */ + z5 = z3 << CONST_BITS; + + z2 = MULTIPLY(tmp11, FIX(0.951056516)); /* (c3+c7)/2 */ + z4 = z5 + tmp12; + + tmp10 = MULTIPLY(z1, FIX(1.396802247)) + z2 + z4; /* c1 */ + tmp14 = MULTIPLY(z1, FIX(0.221231742)) - z2 + z4; /* c9 */ + + z2 = MULTIPLY(tmp11, FIX(0.587785252)); /* (c1-c9)/2 */ + z4 = z5 - tmp12 - (tmp13 << (CONST_BITS - 1)); + + tmp12 = (z1 - tmp13 - z3) << PASS1_BITS; + + tmp11 = MULTIPLY(z1, FIX(1.260073511)) - z2 - z4; /* c3 */ + tmp13 = MULTIPLY(z1, FIX(0.642039522)) - z2 + z4; /* c7 */ + + /* Final output stage */ + + wsptr[5*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS); + wsptr[5*9] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS); + wsptr[5*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS); + wsptr[5*8] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS); + wsptr[5*2] = (int) (tmp22 + tmp12); + wsptr[5*7] = (int) (tmp22 - tmp12); + wsptr[5*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS); + wsptr[5*6] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS); + wsptr[5*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS); + wsptr[5*5] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 10 rows from work array, store into output array. + * 5-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/10). + */ + wsptr = workspace; + for (ctr = 0; ctr < 10; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + tmp12 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + tmp12 <<= CONST_BITS; + tmp13 = (INT32) wsptr[2]; + tmp14 = (INT32) wsptr[4]; + z1 = MULTIPLY(tmp13 + tmp14, FIX(0.790569415)); /* (c2+c4)/2 */ + z2 = MULTIPLY(tmp13 - tmp14, FIX(0.353553391)); /* (c2-c4)/2 */ + z3 = tmp12 + z2; + tmp10 = z3 + z1; + tmp11 = z3 - z1; + tmp12 -= z2 << 2; + + /* Odd part */ + + z2 = (INT32) wsptr[1]; + z3 = (INT32) wsptr[3]; + + z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c3 */ + tmp13 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c1-c3 */ + tmp14 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c1+c3 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp13, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp14, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 5; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 4x8 output block. + * + * 8-point IDCT in pass 1 (columns), 4-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_4x8 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp1, tmp2, tmp3; + INT32 tmp10, tmp11, tmp12, tmp13; + INT32 z1, z2, z3; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[4*8]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. */ + /* Note results are scaled up by sqrt(8) compared to a true IDCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 4; ctr > 0; ctr--) { + /* Due to quantization, we will usually find that many of the input + * coefficients are zero, especially the AC terms. We can exploit this + * by short-circuiting the IDCT calculation for any column in which all + * the AC terms are zero. In that case each output is equal to the + * DC coefficient (with scale factor as needed). + * With typical images and quantization tables, half or more of the + * column DCT calculations can be simplified this way. + */ + + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && + inptr[DCTSIZE*7] == 0) { + /* AC terms all zero */ + int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; + + wsptr[4*0] = dcval; + wsptr[4*1] = dcval; + wsptr[4*2] = dcval; + wsptr[4*3] = dcval; + wsptr[4*4] = dcval; + wsptr[4*5] = dcval; + wsptr[4*6] = dcval; + wsptr[4*7] = dcval; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + continue; + } + + /* Even part: reverse the even part of the forward DCT. */ + /* The rotator is sqrt(2)*c(-6). */ + + z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); + tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); + + z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + z2 <<= CONST_BITS; + z3 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + z2 += ONE << (CONST_BITS-PASS1_BITS-1); + + tmp0 = z2 + z3; + tmp1 = z2 - z3; + + tmp10 = tmp0 + tmp2; + tmp13 = tmp0 - tmp2; + tmp11 = tmp1 + tmp3; + tmp12 = tmp1 - tmp3; + + /* Odd part per figure 8; the matrix is unitary and hence its + * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. + */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + tmp1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + tmp3 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + + z2 = tmp0 + tmp2; + z3 = tmp1 + tmp3; + + z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* sqrt(2) * c3 */ + z2 = MULTIPLY(z2, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ + z3 = MULTIPLY(z3, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + z2 += z1; + z3 += z1; + + z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ + tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ + tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + tmp0 += z1 + z2; + tmp3 += z1 + z3; + + z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ + tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ + tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + tmp1 += z1 + z3; + tmp2 += z1 + z2; + + /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ + + wsptr[4*0] = (int) RIGHT_SHIFT(tmp10 + tmp3, CONST_BITS-PASS1_BITS); + wsptr[4*7] = (int) RIGHT_SHIFT(tmp10 - tmp3, CONST_BITS-PASS1_BITS); + wsptr[4*1] = (int) RIGHT_SHIFT(tmp11 + tmp2, CONST_BITS-PASS1_BITS); + wsptr[4*6] = (int) RIGHT_SHIFT(tmp11 - tmp2, CONST_BITS-PASS1_BITS); + wsptr[4*2] = (int) RIGHT_SHIFT(tmp12 + tmp1, CONST_BITS-PASS1_BITS); + wsptr[4*5] = (int) RIGHT_SHIFT(tmp12 - tmp1, CONST_BITS-PASS1_BITS); + wsptr[4*3] = (int) RIGHT_SHIFT(tmp13 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[4*4] = (int) RIGHT_SHIFT(tmp13 - tmp0, CONST_BITS-PASS1_BITS); + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + } + + /* Pass 2: process 8 rows from work array, store into output array. + * 4-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/16). + */ + wsptr = workspace; + for (ctr = 0; ctr < 8; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + tmp0 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + tmp2 = (INT32) wsptr[2]; + + tmp10 = (tmp0 + tmp2) << CONST_BITS; + tmp12 = (tmp0 - tmp2) << CONST_BITS; + + /* Odd part */ + /* Same rotation as in the even part of the 8x8 LL&M IDCT */ + + z2 = (INT32) wsptr[1]; + z3 = (INT32) wsptr[3]; + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ + tmp0 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ + tmp2 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 4; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a reduced-size 3x6 output block. + * + * 6-point IDCT in pass 1 (columns), 3-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_3x6 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp1, tmp2, tmp10, tmp11, tmp12; + INT32 z1, z2, z3; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + int * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + int workspace[3*6]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. + * 6-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/12). + */ + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 3; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp0 <<= CONST_BITS; + /* Add fudge factor here for final descale. */ + tmp0 += ONE << (CONST_BITS-PASS1_BITS-1); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + tmp10 = MULTIPLY(tmp2, FIX(0.707106781)); /* c4 */ + tmp1 = tmp0 + tmp10; + tmp11 = RIGHT_SHIFT(tmp0 - tmp10 - tmp10, CONST_BITS-PASS1_BITS); + tmp10 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + tmp0 = MULTIPLY(tmp10, FIX(1.224744871)); /* c2 */ + tmp10 = tmp1 + tmp0; + tmp12 = tmp1 - tmp0; + + /* Odd part */ + + z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp1 = MULTIPLY(z1 + z3, FIX(0.366025404)); /* c5 */ + tmp0 = tmp1 + ((z1 + z2) << CONST_BITS); + tmp2 = tmp1 + ((z3 - z2) << CONST_BITS); + tmp1 = (z1 - z2 - z3) << PASS1_BITS; + + /* Final output stage */ + + wsptr[3*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS); + wsptr[3*5] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS); + wsptr[3*1] = (int) (tmp11 + tmp1); + wsptr[3*4] = (int) (tmp11 - tmp1); + wsptr[3*2] = (int) RIGHT_SHIFT(tmp12 + tmp2, CONST_BITS-PASS1_BITS); + wsptr[3*3] = (int) RIGHT_SHIFT(tmp12 - tmp2, CONST_BITS-PASS1_BITS); + } + + /* Pass 2: process 6 rows from work array, store into output array. + * 3-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/6). + */ + wsptr = workspace; + for (ctr = 0; ctr < 6; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + tmp0 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + tmp0 <<= CONST_BITS; + tmp2 = (INT32) wsptr[2]; + tmp12 = MULTIPLY(tmp2, FIX(0.707106781)); /* c2 */ + tmp10 = tmp0 + tmp12; + tmp2 = tmp0 - tmp12 - tmp12; + + /* Odd part */ + + tmp12 = (INT32) wsptr[1]; + tmp0 = MULTIPLY(tmp12, FIX(1.224744871)); /* c1 */ + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp2, + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; + + wsptr += 3; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 2x4 output block. + * + * 4-point IDCT in pass 1 (columns), 2-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_2x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp2, tmp10, tmp12; + INT32 z1, z2, z3; + JCOEFPTR inptr; + ISLOW_MULT_TYPE * quantptr; + INT32 * wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + int ctr; + INT32 workspace[2*4]; /* buffers data between passes */ + SHIFT_TEMPS + + /* Pass 1: process columns from input, store into work array. + * 4-point IDCT kernel, + * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point IDCT]. + */ + inptr = coef_block; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + wsptr = workspace; + for (ctr = 0; ctr < 2; ctr++, inptr++, quantptr++, wsptr++) { + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + + tmp10 = (tmp0 + tmp2) << CONST_BITS; + tmp12 = (tmp0 - tmp2) << CONST_BITS; + + /* Odd part */ + /* Same rotation as in the even part of the 8x8 LL&M IDCT */ + + z2 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ + tmp0 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ + tmp2 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ + + /* Final output stage */ + + wsptr[2*0] = tmp10 + tmp0; + wsptr[2*3] = tmp10 - tmp0; + wsptr[2*1] = tmp12 + tmp2; + wsptr[2*2] = tmp12 - tmp2; + } + + /* Pass 2: process 4 rows from work array, store into output array. */ + + wsptr = workspace; + for (ctr = 0; ctr < 4; ctr++) { + outptr = output_buf[ctr] + output_col; + + /* Even part */ + + /* Add fudge factor here for final descale. */ + tmp10 = wsptr[0] + (ONE << (CONST_BITS+2)); + + /* Odd part */ + + tmp0 = wsptr[1]; + + /* Final output stage */ + + outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS+3) + & RANGE_MASK]; + + wsptr += 2; /* advance pointer to next row */ + } +} + + +/* + * Perform dequantization and inverse DCT on one block of coefficients, + * producing a 1x2 output block. + * + * 2-point IDCT in pass 1 (columns), 1-point in pass 2 (rows). + */ + +GLOBAL(void) +jpeg_idct_1x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) +{ + INT32 tmp0, tmp10; + ISLOW_MULT_TYPE * quantptr; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); + SHIFT_TEMPS + + /* Process 1 column from input, store into output array. */ + + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + + /* Even part */ + + tmp10 = DEQUANTIZE(coef_block[DCTSIZE*0], quantptr[DCTSIZE*0]); + /* Add fudge factor here for final descale. */ + tmp10 += ONE << 2; + + /* Odd part */ + + tmp0 = DEQUANTIZE(coef_block[DCTSIZE*1], quantptr[DCTSIZE*1]); + + /* Final output stage */ + + output_buf[0][output_col] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, 3) + & RANGE_MASK]; + output_buf[1][output_col] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, 3) + & RANGE_MASK]; +} + +#endif /* IDCT_SCALING_SUPPORTED */ #endif /* DCT_ISLOW_SUPPORTED */ diff --git a/reactos/dll/3rdparty/libjpeg/jidctred.c b/reactos/dll/3rdparty/libjpeg/jidctred.c deleted file mode 100644 index 421f3c7ca1e..00000000000 --- a/reactos/dll/3rdparty/libjpeg/jidctred.c +++ /dev/null @@ -1,398 +0,0 @@ -/* - * jidctred.c - * - * Copyright (C) 1994-1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains inverse-DCT routines that produce reduced-size output: - * either 4x4, 2x2, or 1x1 pixels from an 8x8 DCT block. - * - * The implementation is based on the Loeffler, Ligtenberg and Moschytz (LL&M) - * algorithm used in jidctint.c. We simply replace each 8-to-8 1-D IDCT step - * with an 8-to-4 step that produces the four averages of two adjacent outputs - * (or an 8-to-2 step producing two averages of four outputs, for 2x2 output). - * These steps were derived by computing the corresponding values at the end - * of the normal LL&M code, then simplifying as much as possible. - * - * 1x1 is trivial: just take the DC coefficient divided by 8. - * - * See jidctint.c for additional comments. - */ - -#define JPEG_INTERNALS -#include "jinclude.h" -#include "jpeglib.h" -#include "jdct.h" /* Private declarations for DCT subsystem */ - -#ifdef IDCT_SCALING_SUPPORTED - - -/* - * This module is specialized to the case DCTSIZE = 8. - */ - -#if DCTSIZE != 8 - Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ -#endif - - -/* Scaling is the same as in jidctint.c. */ - -#if BITS_IN_JSAMPLE == 8 -#define CONST_BITS 13 -#define PASS1_BITS 2 -#else -#define CONST_BITS 13 -#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ -#endif - -/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus - * causing a lot of useless floating-point operations at run time. - * To get around this we use the following pre-calculated constants. - * If you change CONST_BITS you may want to add appropriate values. - * (With a reasonable C compiler, you can just rely on the FIX() macro...) - */ - -#if CONST_BITS == 13 -#define FIX_0_211164243 ((INT32) 1730) /* FIX(0.211164243) */ -#define FIX_0_509795579 ((INT32) 4176) /* FIX(0.509795579) */ -#define FIX_0_601344887 ((INT32) 4926) /* FIX(0.601344887) */ -#define FIX_0_720959822 ((INT32) 5906) /* FIX(0.720959822) */ -#define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */ -#define FIX_0_850430095 ((INT32) 6967) /* FIX(0.850430095) */ -#define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */ -#define FIX_1_061594337 ((INT32) 8697) /* FIX(1.061594337) */ -#define FIX_1_272758580 ((INT32) 10426) /* FIX(1.272758580) */ -#define FIX_1_451774981 ((INT32) 11893) /* FIX(1.451774981) */ -#define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */ -#define FIX_2_172734803 ((INT32) 17799) /* FIX(2.172734803) */ -#define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */ -#define FIX_3_624509785 ((INT32) 29692) /* FIX(3.624509785) */ -#else -#define FIX_0_211164243 FIX(0.211164243) -#define FIX_0_509795579 FIX(0.509795579) -#define FIX_0_601344887 FIX(0.601344887) -#define FIX_0_720959822 FIX(0.720959822) -#define FIX_0_765366865 FIX(0.765366865) -#define FIX_0_850430095 FIX(0.850430095) -#define FIX_0_899976223 FIX(0.899976223) -#define FIX_1_061594337 FIX(1.061594337) -#define FIX_1_272758580 FIX(1.272758580) -#define FIX_1_451774981 FIX(1.451774981) -#define FIX_1_847759065 FIX(1.847759065) -#define FIX_2_172734803 FIX(2.172734803) -#define FIX_2_562915447 FIX(2.562915447) -#define FIX_3_624509785 FIX(3.624509785) -#endif - - -/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. - * For 8-bit samples with the recommended scaling, all the variable - * and constant values involved are no more than 16 bits wide, so a - * 16x16->32 bit multiply can be used instead of a full 32x32 multiply. - * For 12-bit samples, a full 32-bit multiplication will be needed. - */ - -#if BITS_IN_JSAMPLE == 8 -#define MULTIPLY(var,const) MULTIPLY16C16(var,const) -#else -#define MULTIPLY(var,const) ((var) * (const)) -#endif - - -/* Dequantize a coefficient by multiplying it by the multiplier-table - * entry; produce an int result. In this module, both inputs and result - * are 16 bits or less, so either int or short multiply will work. - */ - -#define DEQUANTIZE(coef,quantval) (((ISLOW_MULT_TYPE) (coef)) * (quantval)) - - -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a reduced-size 4x4 output block. - */ - -GLOBAL(void) -jpeg_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - INT32 tmp0, tmp2, tmp10, tmp12; - INT32 z1, z2, z3, z4; - JCOEFPTR inptr; - ISLOW_MULT_TYPE * quantptr; - int * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - int workspace[DCTSIZE*4]; /* buffers data between passes */ - SHIFT_TEMPS - - /* Pass 1: process columns from input, store into work array. */ - - inptr = coef_block; - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = DCTSIZE; ctr > 0; inptr++, quantptr++, wsptr++, ctr--) { - /* Don't bother to process column 4, because second pass won't use it */ - if (ctr == DCTSIZE-4) - continue; - if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && - inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*5] == 0 && - inptr[DCTSIZE*6] == 0 && inptr[DCTSIZE*7] == 0) { - /* AC terms all zero; we need not examine term 4 for 4x4 output */ - int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; - - wsptr[DCTSIZE*0] = dcval; - wsptr[DCTSIZE*1] = dcval; - wsptr[DCTSIZE*2] = dcval; - wsptr[DCTSIZE*3] = dcval; - - continue; - } - - /* Even part */ - - tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - tmp0 <<= (CONST_BITS+1); - - z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); - - tmp2 = MULTIPLY(z2, FIX_1_847759065) + MULTIPLY(z3, - FIX_0_765366865); - - tmp10 = tmp0 + tmp2; - tmp12 = tmp0 - tmp2; - - /* Odd part */ - - z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); - z2 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); - z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - z4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - - tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */ - + MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */ - + MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */ - + MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */ - - tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */ - + MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */ - + MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */ - + MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */ - - /* Final output stage */ - - wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp2, CONST_BITS-PASS1_BITS+1); - wsptr[DCTSIZE*3] = (int) DESCALE(tmp10 - tmp2, CONST_BITS-PASS1_BITS+1); - wsptr[DCTSIZE*1] = (int) DESCALE(tmp12 + tmp0, CONST_BITS-PASS1_BITS+1); - wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 - tmp0, CONST_BITS-PASS1_BITS+1); - } - - /* Pass 2: process 4 rows from work array, store into output array. */ - - wsptr = workspace; - for (ctr = 0; ctr < 4; ctr++) { - outptr = output_buf[ctr] + output_col; - /* It's not clear whether a zero row test is worthwhile here ... */ - -#ifndef NO_ZERO_ROW_TEST - if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && - wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { - /* AC terms all zero */ - JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3) - & RANGE_MASK]; - - outptr[0] = dcval; - outptr[1] = dcval; - outptr[2] = dcval; - outptr[3] = dcval; - - wsptr += DCTSIZE; /* advance pointer to next row */ - continue; - } -#endif - - /* Even part */ - - tmp0 = ((INT32) wsptr[0]) << (CONST_BITS+1); - - tmp2 = MULTIPLY((INT32) wsptr[2], FIX_1_847759065) - + MULTIPLY((INT32) wsptr[6], - FIX_0_765366865); - - tmp10 = tmp0 + tmp2; - tmp12 = tmp0 - tmp2; - - /* Odd part */ - - z1 = (INT32) wsptr[7]; - z2 = (INT32) wsptr[5]; - z3 = (INT32) wsptr[3]; - z4 = (INT32) wsptr[1]; - - tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */ - + MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */ - + MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */ - + MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */ - - tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */ - + MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */ - + MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */ - + MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */ - - /* Final output stage */ - - outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp2, - CONST_BITS+PASS1_BITS+3+1) - & RANGE_MASK]; - outptr[3] = range_limit[(int) DESCALE(tmp10 - tmp2, - CONST_BITS+PASS1_BITS+3+1) - & RANGE_MASK]; - outptr[1] = range_limit[(int) DESCALE(tmp12 + tmp0, - CONST_BITS+PASS1_BITS+3+1) - & RANGE_MASK]; - outptr[2] = range_limit[(int) DESCALE(tmp12 - tmp0, - CONST_BITS+PASS1_BITS+3+1) - & RANGE_MASK]; - - wsptr += DCTSIZE; /* advance pointer to next row */ - } -} - - -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a reduced-size 2x2 output block. - */ - -GLOBAL(void) -jpeg_idct_2x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - INT32 tmp0, tmp10, z1; - JCOEFPTR inptr; - ISLOW_MULT_TYPE * quantptr; - int * wsptr; - JSAMPROW outptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - int ctr; - int workspace[DCTSIZE*2]; /* buffers data between passes */ - SHIFT_TEMPS - - /* Pass 1: process columns from input, store into work array. */ - - inptr = coef_block; - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - wsptr = workspace; - for (ctr = DCTSIZE; ctr > 0; inptr++, quantptr++, wsptr++, ctr--) { - /* Don't bother to process columns 2,4,6 */ - if (ctr == DCTSIZE-2 || ctr == DCTSIZE-4 || ctr == DCTSIZE-6) - continue; - if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*3] == 0 && - inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*7] == 0) { - /* AC terms all zero; we need not examine terms 2,4,6 for 2x2 output */ - int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; - - wsptr[DCTSIZE*0] = dcval; - wsptr[DCTSIZE*1] = dcval; - - continue; - } - - /* Even part */ - - z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - tmp10 = z1 << (CONST_BITS+2); - - /* Odd part */ - - z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); - tmp0 = MULTIPLY(z1, - FIX_0_720959822); /* sqrt(2) * (c7-c5+c3-c1) */ - z1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); - tmp0 += MULTIPLY(z1, FIX_0_850430095); /* sqrt(2) * (-c1+c3+c5+c7) */ - z1 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - tmp0 += MULTIPLY(z1, - FIX_1_272758580); /* sqrt(2) * (-c1+c3-c5-c7) */ - z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - tmp0 += MULTIPLY(z1, FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */ - - /* Final output stage */ - - wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp0, CONST_BITS-PASS1_BITS+2); - wsptr[DCTSIZE*1] = (int) DESCALE(tmp10 - tmp0, CONST_BITS-PASS1_BITS+2); - } - - /* Pass 2: process 2 rows from work array, store into output array. */ - - wsptr = workspace; - for (ctr = 0; ctr < 2; ctr++) { - outptr = output_buf[ctr] + output_col; - /* It's not clear whether a zero row test is worthwhile here ... */ - -#ifndef NO_ZERO_ROW_TEST - if (wsptr[1] == 0 && wsptr[3] == 0 && wsptr[5] == 0 && wsptr[7] == 0) { - /* AC terms all zero */ - JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3) - & RANGE_MASK]; - - outptr[0] = dcval; - outptr[1] = dcval; - - wsptr += DCTSIZE; /* advance pointer to next row */ - continue; - } -#endif - - /* Even part */ - - tmp10 = ((INT32) wsptr[0]) << (CONST_BITS+2); - - /* Odd part */ - - tmp0 = MULTIPLY((INT32) wsptr[7], - FIX_0_720959822) /* sqrt(2) * (c7-c5+c3-c1) */ - + MULTIPLY((INT32) wsptr[5], FIX_0_850430095) /* sqrt(2) * (-c1+c3+c5+c7) */ - + MULTIPLY((INT32) wsptr[3], - FIX_1_272758580) /* sqrt(2) * (-c1+c3-c5-c7) */ - + MULTIPLY((INT32) wsptr[1], FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */ - - /* Final output stage */ - - outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp0, - CONST_BITS+PASS1_BITS+3+2) - & RANGE_MASK]; - outptr[1] = range_limit[(int) DESCALE(tmp10 - tmp0, - CONST_BITS+PASS1_BITS+3+2) - & RANGE_MASK]; - - wsptr += DCTSIZE; /* advance pointer to next row */ - } -} - - -/* - * Perform dequantization and inverse DCT on one block of coefficients, - * producing a reduced-size 1x1 output block. - */ - -GLOBAL(void) -jpeg_idct_1x1 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) -{ - int dcval; - ISLOW_MULT_TYPE * quantptr; - JSAMPLE *range_limit = IDCT_range_limit(cinfo); - SHIFT_TEMPS - - /* We hardly need an inverse DCT routine for this: just take the - * average pixel value, which is one-eighth of the DC coefficient. - */ - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - dcval = DEQUANTIZE(coef_block[0], quantptr[0]); - dcval = (int) DESCALE((INT32) dcval, 3); - - output_buf[0][output_col] = range_limit[dcval & RANGE_MASK]; -} - -#endif /* IDCT_SCALING_SUPPORTED */ diff --git a/reactos/dll/3rdparty/libjpeg/jmorecfg.h b/reactos/dll/3rdparty/libjpeg/jmorecfg.h index 41b329ef306..a9478f460bd 100644 --- a/reactos/dll/3rdparty/libjpeg/jmorecfg.h +++ b/reactos/dll/3rdparty/libjpeg/jmorecfg.h @@ -2,6 +2,7 @@ * jmorecfg.h * * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 1997-2009 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -134,7 +135,6 @@ typedef char JOCTET; */ /* UINT8 must hold at least the values 0..255. */ -#ifndef HAVE_ALL_INTS #ifdef HAVE_UNSIGNED_CHAR typedef unsigned char UINT8; @@ -162,11 +162,15 @@ typedef short INT16; /* INT32 must hold at least signed 32-bit values. */ -#if !defined(XMD_H) && !defined(_WIN32) /* X11/xmd.h correctly defines INT32 */ +#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */ +#ifndef _BASETSD_H_ /* Microsoft defines it in basetsd.h */ +#ifndef _BASETSD_H /* MinGW is slightly different */ +#ifndef QGLOBAL_H /* Qt defines it in qglobal.h */ typedef long INT32; #endif - -#endif /* HAVE_ALL_INTS */ +#endif +#endif +#endif /* Datatype used for image dimensions. The JPEG standard only supports * images up to 64K*64K due to 16-bit fields in SOF markers. Therefore @@ -187,63 +191,14 @@ typedef unsigned int JDIMENSION; * or code profilers that require it. */ -#ifdef _WIN32 -# if defined(ALL_STATIC) -# if defined(JPEG_DLL) -# undef JPEG_DLL -# endif -# if !defined(JPEG_STATIC) -# define JPEG_STATIC -# endif -# endif -# if defined(JPEG_DLL) -# if defined(JPEG_STATIC) -# undef JPEG_STATIC -# endif -# endif -# if defined(JPEG_DLL) -/* building a DLL */ -# define JPEG_IMPEXP __declspec(dllexport) -# elif defined(JPEG_STATIC) -/* building or linking to a static library */ -# define JPEG_IMPEXP -# else -/* linking to the DLL */ -# define JPEG_IMPEXP __declspec(dllimport) -# endif -# if !defined(JPEG_API) -# define JPEG_API __cdecl -# endif -/* The only remaining magic that is necessary for cygwin */ -#elif defined(__CYGWIN__) -# if !defined(JPEG_IMPEXP) -# define JPEG_IMPEXP -# endif -# if !defined(JPEG_API) -# define JPEG_API __cdecl -# endif -#endif - -/* Ensure our magic doesn't hurt other platforms */ -#if !defined(JPEG_IMPEXP) -# define JPEG_IMPEXP -#endif -#if !defined(JPEG_API) -# define JPEG_API -#endif - /* a function called through method pointers: */ -#define METHODDEF(type) static type +#define METHODDEF(type) static type /* a function used only in its module: */ -#define LOCAL(type) static type +#define LOCAL(type) static type /* a function referenced thru EXTERNs: */ -#define GLOBAL(type) type JPEG_API +#define GLOBAL(type) type /* a reference to a GLOBAL function: */ -#ifndef EXTERN -# define EXTERN(type) extern JPEG_IMPEXP type JPEG_API -/* a reference to a "GLOBAL" function exported by sourcefiles of utility progs */ -#endif /* EXTERN */ -#define EXTERN_1(type) extern type JPEG_API +#define EXTERN(type) extern type /* This macro is used to declare a "method", that is, a function pointer. @@ -265,16 +220,12 @@ typedef unsigned int JDIMENSION; * explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol. */ -/* jmorecfg.h line 220 */ -/* HJH modification: several of the windows header files already define FAR - because of this, the code below was changed so that it only tinkers with - the FAR define if FAR is still undefined */ #ifndef FAR - #ifdef NEED_FAR_POINTERS - #define FAR far - #else - #define FAR - #endif +#ifdef NEED_FAR_POINTERS +#define FAR far +#else +#define FAR +#endif #endif @@ -318,8 +269,6 @@ typedef int boolean; * (You may HAVE to do that if your compiler doesn't like null source files.) */ -/* Arithmetic coding is unsupported for legal reasons. Complaints to IBM. */ - /* Capability options common to encoder and decoder: */ #define DCT_ISLOW_SUPPORTED /* slow but accurate integer algorithm */ @@ -328,9 +277,10 @@ typedef int boolean; /* Encoder capability options: */ -#undef C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#define C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ #define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ #define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define DCT_SCALING_SUPPORTED /* Input rescaling via DCT? (Requires DCT_ISLOW)*/ #define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */ /* Note: if you selected 12-bit data precision, it is dangerous to turn off * ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit @@ -344,12 +294,12 @@ typedef int boolean; /* Decoder capability options: */ -#undef D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#define D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ #define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ #define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */ #define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */ #define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */ -#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */ #undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */ #define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */ #define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */ diff --git a/reactos/dll/3rdparty/libjpeg/jpegexiforient.c b/reactos/dll/3rdparty/libjpeg/jpegexiforient.c deleted file mode 100644 index 4e966c837cb..00000000000 --- a/reactos/dll/3rdparty/libjpeg/jpegexiforient.c +++ /dev/null @@ -1,299 +0,0 @@ -/* - * jpegexiforient.c - * - * This is a utility program to get and set the Exif Orientation Tag. - * It can be used together with jpegtran in scripts for automatic - * orientation correction of digital camera pictures. - * - * The Exif orientation value gives the orientation of the camera - * relative to the scene when the image was captured. The relation - * of the '0th row' and '0th column' to visual position is shown as - * below. - * - * Value | 0th Row | 0th Column - * ------+-------------+----------- - * 1 | top | left side - * 2 | top | rigth side - * 3 | bottom | rigth side - * 4 | bottom | left side - * 5 | left side | top - * 6 | right side | top - * 7 | right side | bottom - * 8 | left side | bottom - * - * For convenience, here is what the letter F would look like if it were - * tagged correctly and displayed by a program that ignores the orientation - * tag: - * - * 1 2 3 4 5 6 7 8 - * - * 888888 888888 88 88 8888888888 88 88 8888888888 - * 88 88 88 88 88 88 88 88 88 88 88 88 - * 8888 8888 8888 8888 88 8888888888 8888888888 88 - * 88 88 88 88 - * 88 88 888888 888888 - * - */ - -#include -#include - -static FILE * myfile; /* My JPEG file */ - -static unsigned char exif_data[65536L]; - -/* Return next input byte, or EOF if no more */ -#define NEXTBYTE() getc(myfile) - -/* Error exit handler */ -#define ERREXIT(msg) (exit(0)) - -/* Read one byte, testing for EOF */ -static int -read_1_byte (void) -{ - int c; - - c = NEXTBYTE(); - if (c == EOF) - ERREXIT("Premature EOF in JPEG file"); - return c; -} - -/* Read 2 bytes, convert to unsigned int */ -/* All 2-byte quantities in JPEG markers are MSB first */ -static unsigned int -read_2_bytes (void) -{ - int c1, c2; - - c1 = NEXTBYTE(); - if (c1 == EOF) - ERREXIT("Premature EOF in JPEG file"); - c2 = NEXTBYTE(); - if (c2 == EOF) - ERREXIT("Premature EOF in JPEG file"); - return (((unsigned int) c1) << 8) + ((unsigned int) c2); -} - -static const char * progname; /* program name for error messages */ - -static void -usage (FILE *out) -/* complain about bad command line */ -{ - fprintf(out, "jpegexiforient reads or writes the Exif Orientation Tag "); - fprintf(out, "in a JPEG Exif file.\n"); - - fprintf(out, "Usage: %s [switches] jpegfile\n", progname); - - fprintf(out, "Switches:\n"); - fprintf(out, " --help display this help and exit\n"); - fprintf(out, " --version output version information and exit\n"); - fprintf(out, " -n Do not output the trailing newline\n"); - fprintf(out, " -1 .. -8 Set orientation value 1 .. 8\n"); -} - -/* - * The main program. - */ - -int -main (int argc, char **argv) -{ - int n_flag, set_flag; - unsigned int length, i; - int is_motorola; /* Flag for byte order */ - unsigned int offset, number_of_tags, tagnum; - - progname = argv[0]; - if (progname == NULL || progname[0] == 0) - progname = "jpegexiforient"; /* in case C library doesn't provide it */ - - if (argc < 2) { usage(stderr); return 1; } - - n_flag = 0; set_flag = 0; - - i = 1; - while (argv[i][0] == '-') { - switch (argv[i][1]) { - case '-': - switch (argv[i][2]) { - case 'h': usage(stdout); return 0; - case 'v': fprintf(stdout,"jpegexiforient\n"); return 0; - } - case 'n': - n_flag = 1; - break; - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - set_flag = argv[i][1] - '0'; - break; - default: - usage(stderr); return 1; - } - if (++i >= argc) { usage(stderr); return 1; } - } - - if (set_flag) { - if ((myfile = fopen(argv[i], "rb+")) == NULL) { - fprintf(stderr, "%s: can't open %s\n", progname, argv[i]); - return 0; - } - } else { - if ((myfile = fopen(argv[i], "rb")) == NULL) { - fprintf(stderr, "%s: can't open %s\n", progname, argv[i]); - return 0; - } - } - - /* Read File head, check for JPEG SOI + Exif APP1 */ - for (i = 0; i < 4; i++) - exif_data[i] = (unsigned char) read_1_byte(); - if (exif_data[0] != 0xFF || - exif_data[1] != 0xD8 || - exif_data[2] != 0xFF || - exif_data[3] != 0xE1) - return 0; - - /* Get the marker parameter length count */ - length = read_2_bytes(); - /* Length includes itself, so must be at least 2 */ - /* Following Exif data length must be at least 6 */ - if (length < 8) - return 0; - length -= 8; - /* Read Exif head, check for "Exif" */ - for (i = 0; i < 6; i++) - exif_data[i] = (unsigned char) read_1_byte(); - if (exif_data[0] != 0x45 || - exif_data[1] != 0x78 || - exif_data[2] != 0x69 || - exif_data[3] != 0x66 || - exif_data[4] != 0 || - exif_data[5] != 0) - return 0; - /* Read Exif body */ - for (i = 0; i < length; i++) - exif_data[i] = (unsigned char) read_1_byte(); - - if (length < 12) return 0; /* Length of an IFD entry */ - - /* Discover byte order */ - if (exif_data[0] == 0x49 && exif_data[1] == 0x49) - is_motorola = 0; - else if (exif_data[0] == 0x4D && exif_data[1] == 0x4D) - is_motorola = 1; - else - return 0; - - /* Check Tag Mark */ - if (is_motorola) { - if (exif_data[2] != 0) return 0; - if (exif_data[3] != 0x2A) return 0; - } else { - if (exif_data[3] != 0) return 0; - if (exif_data[2] != 0x2A) return 0; - } - - /* Get first IFD offset (offset to IFD0) */ - if (is_motorola) { - if (exif_data[4] != 0) return 0; - if (exif_data[5] != 0) return 0; - offset = exif_data[6]; - offset <<= 8; - offset += exif_data[7]; - } else { - if (exif_data[7] != 0) return 0; - if (exif_data[6] != 0) return 0; - offset = exif_data[5]; - offset <<= 8; - offset += exif_data[4]; - } - if (offset > length - 2) return 0; /* check end of data segment */ - - /* Get the number of directory entries contained in this IFD */ - if (is_motorola) { - number_of_tags = exif_data[offset]; - number_of_tags <<= 8; - number_of_tags += exif_data[offset+1]; - } else { - number_of_tags = exif_data[offset+1]; - number_of_tags <<= 8; - number_of_tags += exif_data[offset]; - } - if (number_of_tags == 0) return 0; - offset += 2; - - /* Search for Orientation Tag in IFD0 */ - for (;;) { - if (offset > length - 12) return 0; /* check end of data segment */ - /* Get Tag number */ - if (is_motorola) { - tagnum = exif_data[offset]; - tagnum <<= 8; - tagnum += exif_data[offset+1]; - } else { - tagnum = exif_data[offset+1]; - tagnum <<= 8; - tagnum += exif_data[offset]; - } - if (tagnum == 0x0112) break; /* found Orientation Tag */ - if (--number_of_tags == 0) return 0; - offset += 12; - } - - if (set_flag) { - /* Set the Orientation value */ - if (is_motorola) { - exif_data[offset+2] = 0; /* Format = unsigned short (2 octets) */ - exif_data[offset+3] = 3; - exif_data[offset+4] = 0; /* Number Of Components = 1 */ - exif_data[offset+5] = 0; - exif_data[offset+6] = 0; - exif_data[offset+7] = 1; - exif_data[offset+8] = 0; - exif_data[offset+9] = (unsigned char)set_flag; - exif_data[offset+10] = 0; - exif_data[offset+11] = 0; - } else { - exif_data[offset+2] = 3; /* Format = unsigned short (2 octets) */ - exif_data[offset+3] = 0; - exif_data[offset+4] = 1; /* Number Of Components = 1 */ - exif_data[offset+5] = 0; - exif_data[offset+6] = 0; - exif_data[offset+7] = 0; - exif_data[offset+8] = (unsigned char)set_flag; - exif_data[offset+9] = 0; - exif_data[offset+10] = 0; - exif_data[offset+11] = 0; - } - fseek(myfile, (4 + 2 + 6 + 2) + offset, SEEK_SET); - fwrite(exif_data + 2 + offset, 1, 10, myfile); - } else { - /* Get the Orientation value */ - if (is_motorola) { - if (exif_data[offset+8] != 0) return 0; - set_flag = exif_data[offset+9]; - } else { - if (exif_data[offset+9] != 0) return 0; - set_flag = exif_data[offset+8]; - } - if (set_flag > 8) return 0; - } - - /* Write out Orientation value */ - if (n_flag) - printf("%c", '0' + set_flag); - else - printf("%c\n", '0' + set_flag); - - /* All done. */ - return 0; -} diff --git a/reactos/dll/3rdparty/libjpeg/jpegint.h b/reactos/dll/3rdparty/libjpeg/jpegint.h index 95b00d405ca..0c27a4e4a03 100644 --- a/reactos/dll/3rdparty/libjpeg/jpegint.h +++ b/reactos/dll/3rdparty/libjpeg/jpegint.h @@ -2,6 +2,7 @@ * jpegint.h * * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 1997-2009 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -99,14 +100,16 @@ struct jpeg_downsampler { }; /* Forward DCT (also controls coefficient quantization) */ +typedef JMETHOD(void, forward_DCT_ptr, + (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY sample_data, JBLOCKROW coef_blocks, + JDIMENSION start_row, JDIMENSION start_col, + JDIMENSION num_blocks)); + struct jpeg_forward_dct { JMETHOD(void, start_pass, (j_compress_ptr cinfo)); - /* perhaps this should be an array??? */ - JMETHOD(void, forward_DCT, (j_compress_ptr cinfo, - jpeg_component_info * compptr, - JSAMPARRAY sample_data, JBLOCKROW coef_blocks, - JDIMENSION start_row, JDIMENSION start_col, - JDIMENSION num_blocks)); + /* It is useful to allow each component to have a separate FDCT method. */ + forward_DCT_ptr forward_DCT[MAX_COMPONENTS]; }; /* Entropy encoding */ @@ -210,10 +213,6 @@ struct jpeg_entropy_decoder { JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); JMETHOD(boolean, decode_mcu, (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)); - - /* This is here to share code between baseline and progressive decoders; */ - /* other modules probably should not use it */ - boolean insufficient_data; /* set TRUE after emitting warning */ }; /* Inverse DCT (also performs dequantization) */ @@ -303,7 +302,7 @@ struct jpeg_color_quantizer { #define jinit_downsampler jIDownsampler #define jinit_forward_dct jIFDCT #define jinit_huff_encoder jIHEncoder -#define jinit_phuff_encoder jIPHEncoder +#define jinit_arith_encoder jIAEncoder #define jinit_marker_writer jIMWriter #define jinit_master_decompress jIDMaster #define jinit_d_main_controller jIDMainC @@ -312,7 +311,7 @@ struct jpeg_color_quantizer { #define jinit_input_controller jIInCtlr #define jinit_marker_reader jIMReader #define jinit_huff_decoder jIHDecoder -#define jinit_phuff_decoder jIPHDecoder +#define jinit_arith_decoder jIADecoder #define jinit_inverse_dct jIIDCT #define jinit_upsampler jIUpsampler #define jinit_color_deconverter jIDColor @@ -327,6 +326,13 @@ struct jpeg_color_quantizer { #define jzero_far jZeroFar #define jpeg_zigzag_order jZIGTable #define jpeg_natural_order jZAGTable +#define jpeg_natural_order7 jZAGTable7 +#define jpeg_natural_order6 jZAGTable6 +#define jpeg_natural_order5 jZAGTable5 +#define jpeg_natural_order4 jZAGTable4 +#define jpeg_natural_order3 jZAGTable3 +#define jpeg_natural_order2 jZAGTable2 +#define jpeg_aritab jAriTab #endif /* NEED_SHORT_EXTERNAL_NAMES */ @@ -344,7 +350,7 @@ EXTERN(void) jinit_color_converter JPP((j_compress_ptr cinfo)); EXTERN(void) jinit_downsampler JPP((j_compress_ptr cinfo)); EXTERN(void) jinit_forward_dct JPP((j_compress_ptr cinfo)); EXTERN(void) jinit_huff_encoder JPP((j_compress_ptr cinfo)); -EXTERN(void) jinit_phuff_encoder JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_arith_encoder JPP((j_compress_ptr cinfo)); EXTERN(void) jinit_marker_writer JPP((j_compress_ptr cinfo)); /* Decompression module initialization routines */ EXTERN(void) jinit_master_decompress JPP((j_decompress_ptr cinfo)); @@ -357,7 +363,7 @@ EXTERN(void) jinit_d_post_controller JPP((j_decompress_ptr cinfo, EXTERN(void) jinit_input_controller JPP((j_decompress_ptr cinfo)); EXTERN(void) jinit_marker_reader JPP((j_decompress_ptr cinfo)); EXTERN(void) jinit_huff_decoder JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_phuff_decoder JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_arith_decoder JPP((j_decompress_ptr cinfo)); EXTERN(void) jinit_inverse_dct JPP((j_decompress_ptr cinfo)); EXTERN(void) jinit_upsampler JPP((j_decompress_ptr cinfo)); EXTERN(void) jinit_color_deconverter JPP((j_decompress_ptr cinfo)); @@ -381,6 +387,15 @@ EXTERN(void) jzero_far JPP((void FAR * target, size_t bytestozero)); extern const int jpeg_zigzag_order[]; /* natural coef order to zigzag order */ #endif extern const int jpeg_natural_order[]; /* zigzag coef order to natural order */ +extern const int jpeg_natural_order7[]; /* zz to natural order for 7x7 block */ +extern const int jpeg_natural_order6[]; /* zz to natural order for 6x6 block */ +extern const int jpeg_natural_order5[]; /* zz to natural order for 5x5 block */ +extern const int jpeg_natural_order4[]; /* zz to natural order for 4x4 block */ +extern const int jpeg_natural_order3[]; /* zz to natural order for 3x3 block */ +extern const int jpeg_natural_order2[]; /* zz to natural order for 2x2 block */ + +/* Arithmetic coding probability estimation tables in jaricom.c */ +extern const INT32 jpeg_aritab[]; /* Suppress undefined-structure complaints if necessary. */ diff --git a/reactos/dll/3rdparty/libjpeg/jpeglib.h b/reactos/dll/3rdparty/libjpeg/jpeglib.h index 2091dbebf94..5039d4bf4c4 100644 --- a/reactos/dll/3rdparty/libjpeg/jpeglib.h +++ b/reactos/dll/3rdparty/libjpeg/jpeglib.h @@ -2,6 +2,7 @@ * jpeglib.h * * Copyright (C) 1991-1998, Thomas G. Lane. + * Modified 2002-2009 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -13,10 +14,6 @@ #ifndef JPEGLIB_H #define JPEGLIB_H -#ifdef __cplusplus -extern "C" { -#endif - /* * First we include the configuration files that record how this * installation of the JPEG library is set up. jconfig.h can be @@ -29,15 +26,18 @@ extern "C" { #endif #include "jmorecfg.h" /* seldom changed options */ + #ifdef __cplusplus +#ifndef DONT_USE_EXTERN_C extern "C" { -#endif /* __cplusplus */ +#endif +#endif /* Version ID for the JPEG library. - * Might be useful for tests like "#if JPEG_LIB_VERSION >= 60". + * Might be useful for tests like "#if JPEG_LIB_VERSION >= 80". */ -#define JPEG_LIB_VERSION 62 /* Version 6b */ +#define JPEG_LIB_VERSION 80 /* Version 8.0 */ /* Various constants determining the sizes of things. @@ -145,18 +145,18 @@ typedef struct { */ JDIMENSION width_in_blocks; JDIMENSION height_in_blocks; - /* Size of a DCT block in samples. Always DCTSIZE for compression. - * For decompression this is the size of the output from one DCT block, - * reflecting any scaling we choose to apply during the IDCT step. - * Values of 1,2,4,8 are likely to be supported. Note that different - * components may receive different IDCT scalings. + /* Size of a DCT block in samples, + * reflecting any scaling we choose to apply during the DCT step. + * Values from 1 to 16 are supported. + * Note that different components may receive different DCT scalings. */ - int DCT_scaled_size; + int DCT_h_scaled_size; + int DCT_v_scaled_size; /* The downsampled dimensions are the component's actual, unpadded number - * of samples at the main buffer (preprocessing/compression interface), thus - * downsampled_width = ceil(image_width * Hi/Hmax) - * and similarly for height. For decompression, IDCT scaling is included, so - * downsampled_width = ceil(image_width * Hi/Hmax * DCT_scaled_size/DCTSIZE) + * of samples at the main buffer (preprocessing/compression interface); + * DCT scaling is included, so + * downsampled_width = ceil(image_width * Hi/Hmax * DCT_h_scaled_size/DCTSIZE) + * and similarly for height. */ JDIMENSION downsampled_width; /* actual width in samples */ JDIMENSION downsampled_height; /* actual height in samples */ @@ -171,7 +171,7 @@ typedef struct { int MCU_width; /* number of blocks per MCU, horizontally */ int MCU_height; /* number of blocks per MCU, vertically */ int MCU_blocks; /* MCU_width * MCU_height */ - int MCU_sample_width; /* MCU width in samples, MCU_width*DCT_scaled_size */ + int MCU_sample_width; /* MCU width in samples: MCU_width * DCT_h_scaled_size */ int last_col_width; /* # of non-dummy blocks across in last MCU */ int last_row_height; /* # of non-dummy blocks down in last MCU */ @@ -298,6 +298,17 @@ struct jpeg_compress_struct { * helper routines to simplify changing parameters. */ + unsigned int scale_num, scale_denom; /* fraction by which to scale image */ + + JDIMENSION jpeg_width; /* scaled JPEG image width */ + JDIMENSION jpeg_height; /* scaled JPEG image height */ + /* Dimensions of actual JPEG image that will be written to file, + * derived from input dimensions by scaling factors above. + * These fields are computed by jpeg_start_compress(). + * You can also use jpeg_calc_jpeg_dimensions() to determine these values + * in advance of calling jpeg_start_compress(). + */ + int data_precision; /* bits of precision in image data */ int num_components; /* # of color components in JPEG image */ @@ -305,14 +316,17 @@ struct jpeg_compress_struct { jpeg_component_info * comp_info; /* comp_info[i] describes component that appears i'th in SOF */ - + JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; - /* ptrs to coefficient quantization tables, or NULL if not defined */ - + int q_scale_factor[NUM_QUANT_TBLS]; + /* ptrs to coefficient quantization tables, or NULL if not defined, + * and corresponding scale factors (percentage, initialized 100). + */ + JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; /* ptrs to Huffman coding tables, or NULL if not defined */ - + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ @@ -328,6 +342,7 @@ struct jpeg_compress_struct { boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ boolean optimize_coding; /* TRUE=optimize entropy encoding parms */ boolean CCIR601_sampling; /* TRUE=first samples are cosited */ + boolean do_fancy_downsampling; /* TRUE=apply fancy downsampling */ int smoothing_factor; /* 1..100, or 0 for no input smoothing */ J_DCT_METHOD dct_method; /* DCT algorithm selector */ @@ -371,6 +386,9 @@ struct jpeg_compress_struct { int max_h_samp_factor; /* largest h_samp_factor */ int max_v_samp_factor; /* largest v_samp_factor */ + int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */ + int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */ + JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coef ctlr */ /* The coefficient controller receives data in units of MCU rows as defined * for fully interleaved scans (whether the JPEG file is interleaved or not). @@ -396,6 +414,10 @@ struct jpeg_compress_struct { int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ + int block_size; /* the basic DCT block size: 1..16 */ + const int * natural_order; /* natural-order position array */ + int lim_Se; /* min( Se, DCTSIZE2-1 ) */ + /* * Links to compression subobjects (methods and private variables of modules) */ @@ -542,6 +564,7 @@ struct jpeg_decompress_struct { jpeg_component_info * comp_info; /* comp_info[i] describes component that appears i'th in SOF */ + boolean is_baseline; /* TRUE if Baseline SOF0 encountered */ boolean progressive_mode; /* TRUE if SOFn specifies progressive mode */ boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ @@ -582,7 +605,8 @@ struct jpeg_decompress_struct { int max_h_samp_factor; /* largest h_samp_factor */ int max_v_samp_factor; /* largest v_samp_factor */ - int min_DCT_scaled_size; /* smallest DCT_scaled_size of any component */ + int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */ + int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */ JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */ /* The coefficient controller's input and output progress is measured in @@ -590,7 +614,7 @@ struct jpeg_decompress_struct { * in fully interleaved JPEG scans, but are used whether the scan is * interleaved or not. We define an iMCU row as v_samp_factor DCT block * rows of each component. Therefore, the IDCT output contains - * v_samp_factor*DCT_scaled_size sample rows of a component per iMCU row. + * v_samp_factor*DCT_v_scaled_size sample rows of a component per iMCU row. */ JSAMPLE * sample_range_limit; /* table for fast range-limiting */ @@ -614,6 +638,12 @@ struct jpeg_decompress_struct { int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ + /* These fields are derived from Se of first SOS marker. + */ + int block_size; /* the basic DCT block size: 1..16 */ + const int * natural_order; /* natural-order position array for entropy decode */ + int lim_Se; /* min( Se, DCTSIZE2-1 ) for entropy decode */ + /* This field is shared between entropy decoder and marker parser. * It is either zero or the code of a JPEG marker that has been * read from the data source, but has not yet been processed. @@ -843,11 +873,14 @@ typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo)); #define jpeg_destroy_decompress jDestDecompress #define jpeg_stdio_dest jStdDest #define jpeg_stdio_src jStdSrc +#define jpeg_mem_dest jMemDest +#define jpeg_mem_src jMemSrc #define jpeg_set_defaults jSetDefaults #define jpeg_set_colorspace jSetColorspace #define jpeg_default_colorspace jDefColorspace #define jpeg_set_quality jSetQuality #define jpeg_set_linear_quality jSetLQuality +#define jpeg_default_qtables jDefQTables #define jpeg_add_quant_table jAddQuantTable #define jpeg_quality_scaling jQualityScaling #define jpeg_simple_progression jSimProgress @@ -857,6 +890,7 @@ typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo)); #define jpeg_start_compress jStrtCompress #define jpeg_write_scanlines jWrtScanlines #define jpeg_finish_compress jFinCompress +#define jpeg_calc_jpeg_dimensions jCjpegDimensions #define jpeg_write_raw_data jWrtRawData #define jpeg_write_marker jWrtMarker #define jpeg_write_m_header jWrtMHeader @@ -873,6 +907,7 @@ typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo)); #define jpeg_input_complete jInComplete #define jpeg_new_colormap jNewCMap #define jpeg_consume_input jConsumeInput +#define jpeg_core_output_dimensions jCoreDimensions #define jpeg_calc_output_dimensions jCalcDimensions #define jpeg_save_markers jSaveMarkers #define jpeg_set_marker_processor jSetMarker @@ -917,6 +952,14 @@ EXTERN(void) jpeg_destroy_decompress JPP((j_decompress_ptr cinfo)); EXTERN(void) jpeg_stdio_dest JPP((j_compress_ptr cinfo, FILE * outfile)); EXTERN(void) jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile)); +/* Data source and destination managers: memory buffers. */ +EXTERN(void) jpeg_mem_dest JPP((j_compress_ptr cinfo, + unsigned char ** outbuffer, + unsigned long * outsize)); +EXTERN(void) jpeg_mem_src JPP((j_decompress_ptr cinfo, + unsigned char * inbuffer, + unsigned long insize)); + /* Default parameter setup for compression */ EXTERN(void) jpeg_set_defaults JPP((j_compress_ptr cinfo)); /* Compression parameter setup aids */ @@ -928,6 +971,8 @@ EXTERN(void) jpeg_set_quality JPP((j_compress_ptr cinfo, int quality, EXTERN(void) jpeg_set_linear_quality JPP((j_compress_ptr cinfo, int scale_factor, boolean force_baseline)); +EXTERN(void) jpeg_default_qtables JPP((j_compress_ptr cinfo, + boolean force_baseline)); EXTERN(void) jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl, const unsigned int *basic_table, int scale_factor, @@ -947,12 +992,15 @@ EXTERN(JDIMENSION) jpeg_write_scanlines JPP((j_compress_ptr cinfo, JDIMENSION num_lines)); EXTERN(void) jpeg_finish_compress JPP((j_compress_ptr cinfo)); +/* Precalculate JPEG dimensions for current compression parameters. */ +EXTERN(void) jpeg_calc_jpeg_dimensions JPP((j_compress_ptr cinfo)); + /* Replaces jpeg_write_scanlines when writing raw downsampled data. */ EXTERN(JDIMENSION) jpeg_write_raw_data JPP((j_compress_ptr cinfo, JSAMPIMAGE data, JDIMENSION num_lines)); -/* Write a special marker. See libjpeg.doc concerning safe usage. */ +/* Write a special marker. See libjpeg.txt concerning safe usage. */ EXTERN(void) jpeg_write_marker JPP((j_compress_ptr cinfo, int marker, const JOCTET * dataptr, unsigned int datalen)); @@ -1006,6 +1054,7 @@ EXTERN(int) jpeg_consume_input JPP((j_decompress_ptr cinfo)); #define JPEG_SCAN_COMPLETED 4 /* Completed last iMCU row of a scan */ /* Precalculate output dimensions for current decompression parameters. */ +EXTERN(void) jpeg_core_output_dimensions JPP((j_decompress_ptr cinfo)); EXTERN(void) jpeg_calc_output_dimensions JPP((j_decompress_ptr cinfo)); /* Control saving of COM and APPn markers into marker_list. */ @@ -1087,9 +1136,6 @@ struct jpeg_color_quantizer { long dummy; }; #endif /* JPEG_INTERNALS */ #endif /* INCOMPLETE_TYPES_BROKEN */ -#ifdef __cplusplus -} -#endif /* * The JPEG library modules define JPEG_INTERNALS before including this file. @@ -1104,7 +1150,9 @@ struct jpeg_color_quantizer { long dummy; }; #endif #ifdef __cplusplus +#ifndef DONT_USE_EXTERN_C } #endif +#endif #endif /* JPEGLIB_H */ diff --git a/reactos/dll/3rdparty/libjpeg/jpegtran.c b/reactos/dll/3rdparty/libjpeg/jpegtran.c index a5777808233..8cb3d807fbb 100644 --- a/reactos/dll/3rdparty/libjpeg/jpegtran.c +++ b/reactos/dll/3rdparty/libjpeg/jpegtran.c @@ -1,14 +1,14 @@ /* * jpegtran.c * - * Copyright (C) 1995-2001, Thomas G. Lane. + * Copyright (C) 1995-2010, Thomas G. Lane, Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains a command-line user interface for JPEG transcoding. - * It is very similar to cjpeg.c, but provides lossless transcoding between - * different JPEG file formats. It also provides some lossless and sort-of- - * lossless transformations of JPEG data. + * It is very similar to cjpeg.c, and partly to djpeg.c, but provides + * lossless transcoding between different JPEG file formats. It also + * provides some lossless and sort-of-lossless transformations of JPEG data. */ #include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ @@ -37,7 +37,7 @@ static const char * progname; /* program name for error messages */ static char * outfilename; /* for -outfile switch */ -static char * dropfilename; /* for -drop switch */ +static char * scaleoption; /* -scale switch */ static JCOPY_OPTION copyoption; /* -copy switch */ static jpeg_transform_info transformoption; /* image transformation options */ @@ -57,26 +57,26 @@ usage (void) fprintf(stderr, " -copy none Copy no extra markers from source file\n"); fprintf(stderr, " -copy comments Copy only comment markers (default)\n"); fprintf(stderr, " -copy all Copy all extra markers\n"); - fprintf(stderr, " -copy exif Copy EXIF marker and omit JFIF if EXIF\n"); #ifdef ENTROPY_OPT_SUPPORTED fprintf(stderr, " -optimize Optimize Huffman table (smaller file, but slow compression)\n"); #endif #ifdef C_PROGRESSIVE_SUPPORTED fprintf(stderr, " -progressive Create progressive JPEG file\n"); #endif -#if TRANSFORMS_SUPPORTED fprintf(stderr, "Switches for modifying the image:\n"); +#if TRANSFORMS_SUPPORTED fprintf(stderr, " -crop WxH+X+Y Crop to a rectangular subarea\n"); - fprintf(stderr, " -drop +X+Y filename Drop another image\n"); fprintf(stderr, " -grayscale Reduce to grayscale (omit color data)\n"); fprintf(stderr, " -flip [horizontal|vertical] Mirror image (left-right or top-bottom)\n"); fprintf(stderr, " -perfect Fail if there is non-transformable edge blocks\n"); fprintf(stderr, " -rotate [90|180|270] Rotate image (degrees clockwise)\n"); +#endif + fprintf(stderr, " -scale M/N Scale output image by fraction M/N, eg, 1/8\n"); +#if TRANSFORMS_SUPPORTED fprintf(stderr, " -transpose Transpose image\n"); fprintf(stderr, " -transverse Transverse transpose image\n"); - fprintf(stderr, " -trim Drop non-transformable edge blocks or\n"); - fprintf(stderr, " with -drop: Requantize drop file to source file\n"); -#endif /* TRANSFORMS_SUPPORTED */ + fprintf(stderr, " -trim Drop non-transformable edge blocks\n"); +#endif fprintf(stderr, "Switches for advanced users:\n"); fprintf(stderr, " -restart N Set restart interval in rows, or in blocks with B\n"); fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n"); @@ -115,50 +115,6 @@ select_transform (JXFORM_CODE transform) #endif } -LOCAL(void) -handle_exif (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, - JCOPY_OPTION *copyoption) -/* Adjust the marker writing options to create an EXIF file, instead of JFIF, - * if so requested or an EXIF file is detected as input. Must be called after - * jpeg_copy_critical_parameters() as that sets the defaults. */ -{ - jpeg_saved_marker_ptr cur_marker, prev_marker; - - /* Look for an exif marker */ - prev_marker = NULL; - cur_marker = srcinfo->marker_list; - while (cur_marker != NULL) { - if (cur_marker->marker == JPEG_APP0+1 && - cur_marker->data_length >= 6 && - GETJOCTET(cur_marker->data[0]) == 0x45 && - GETJOCTET(cur_marker->data[1]) == 0x78 && - GETJOCTET(cur_marker->data[2]) == 0x69 && - GETJOCTET(cur_marker->data[3]) == 0x66 && - GETJOCTET(cur_marker->data[4]) == 0 && - GETJOCTET(cur_marker->data[5]) == 0) - break; /* found an EXIF marker */ - prev_marker = cur_marker; - cur_marker = cur_marker->next; - } - /* If we've found an EXIF marker but not JFIF this is an EXIF file. Unless - * explicitely requested, make sure we keep the EXIF marker and do not - * emit a JFIF marker (which would come before). EXIF requires that the - * first marker be EXIF. */ - if (cur_marker != NULL && - ((*copyoption != JCOPYOPT_NONE && !srcinfo->saw_JFIF_marker) || - (*copyoption == JCOPYOPT_EXIF))) { - dstinfo->write_JFIF_header = FALSE; - if (*copyoption == JCOPYOPT_COMMENTS) - *copyoption = JCOPYOPT_EXIF; - } - /* If making an EXIF file, make sure that EXIF is first marker */ - if (cur_marker != NULL && prev_marker != NULL && - *copyoption == JCOPYOPT_EXIF) { - prev_marker->next = cur_marker->next; - cur_marker->next = srcinfo->marker_list; - srcinfo->marker_list = cur_marker; - } -} LOCAL(int) parse_switches (j_compress_ptr cinfo, int argc, char **argv, @@ -180,11 +136,11 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv, /* Set up default JPEG parameters. */ simple_progressive = FALSE; outfilename = NULL; - dropfilename = NULL; + scaleoption = NULL; copyoption = JCOPYOPT_DEFAULT; transformoption.transform = JXFORM_NONE; - transformoption.trim = FALSE; transformoption.perfect = FALSE; + transformoption.trim = FALSE; transformoption.force_grayscale = FALSE; transformoption.crop = FALSE; cinfo->err->trace_level = 0; @@ -223,8 +179,6 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv, copyoption = JCOPYOPT_COMMENTS; } else if (keymatch(argv[argn], "all", 1)) { copyoption = JCOPYOPT_ALL; - } else if (keymatch(argv[argn], "exif", 1)) { - copyoption = JCOPYOPT_EXIF; } else usage(); @@ -233,8 +187,7 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv, #if TRANSFORMS_SUPPORTED if (++argn >= argc) /* advance to next argument */ usage(); - if (transformoption.crop /* reject multiple crop/drop requests */ || - ! jtransform_parse_crop_spec(&transformoption, argv[argn])) { + if (! jtransform_parse_crop_spec(&transformoption, argv[argn])) { fprintf(stderr, "%s: bogus -crop argument '%s'\n", progname, argv[argn]); exit(EXIT_FAILURE); @@ -243,27 +196,6 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv, select_transform(JXFORM_NONE); /* force an error */ #endif - } else if (keymatch(arg, "drop", 2)) { -#if TRANSFORMS_SUPPORTED - if (++argn >= argc) /* advance to next argument */ - usage(); - if (transformoption.crop /* reject multiple crop/drop requests */ || - ! jtransform_parse_crop_spec(&transformoption, argv[argn]) || - transformoption.crop_width_set != JCROP_UNSET || - transformoption.crop_height_set != JCROP_UNSET) { - fprintf(stderr, "%s: bogus -drop argument '%s'\n", - progname, argv[argn]); - exit(EXIT_FAILURE); - } - if (++argn >= argc) /* advance to next argument */ - usage(); - dropfilename = argv[argn]; - select_transform(JXFORM_DROP); -#else - select_transform(JXFORM_NONE); /* force an error */ -#endif - - } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) { /* Enable debug printouts. */ /* On first -d, print version identification */ @@ -272,7 +204,6 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv, if (! printed_version) { fprintf(stderr, "Independent JPEG Group's JPEGTRAN, version %s\n%s\n", JVERSION, JCOPYRIGHT); - fprintf(stderr, "EXIF support v 0.1 added 29-Sep-2003\n"); printed_version = TRUE; } cinfo->err->trace_level++; @@ -373,6 +304,13 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv, else usage(); + } else if (keymatch(arg, "scale", 4)) { + /* Scale the output image by a fraction M/N. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + scaleoption = argv[argn]; + /* We must postpone processing until decompression startup. */ + } else if (keymatch(arg, "scans", 1)) { /* Set scan script. */ #ifdef C_MULTISCAN_FILES_SUPPORTED @@ -431,14 +369,8 @@ int main (int argc, char **argv) { struct jpeg_decompress_struct srcinfo; - struct jpeg_error_mgr jsrcerr; -#if TRANSFORMS_SUPPORTED - struct jpeg_decompress_struct dropinfo; - struct jpeg_error_mgr jdroperr; - FILE * drop_file; -#endif struct jpeg_compress_struct dstinfo; - struct jpeg_error_mgr jdsterr; + struct jpeg_error_mgr jsrcerr, jdsterr; #ifdef PROGRESS_REPORT struct cdjpeg_progress_mgr progress; #endif @@ -519,21 +451,6 @@ main (int argc, char **argv) /* default input file is stdin */ fp = read_stdin(); } -#if TRANSFORMS_SUPPORTED - /* Open the drop file. */ - if (dropfilename != NULL) { - if ((drop_file = fopen(dropfilename, READ_BINARY)) == NULL) { - fprintf(stderr, "%s: can't open %s for reading\n", progname, dropfilename); - exit(EXIT_FAILURE); - } - dropinfo.err = jpeg_std_error(&jdroperr); - jpeg_create_decompress(&dropinfo); - jpeg_stdio_src(&dropinfo, drop_file); - } else { - drop_file = NULL; - } -#endif - #ifdef PROGRESS_REPORT start_progress_monitor((j_common_ptr) &dstinfo, &progress); @@ -548,46 +465,30 @@ main (int argc, char **argv) /* Read file header */ (void) jpeg_read_header(&srcinfo, TRUE); -#if TRANSFORMS_SUPPORTED - if (dropfilename != NULL) { - (void) jpeg_read_header(&dropinfo, TRUE); - transformoption.crop_width = dropinfo.image_width; - transformoption.crop_width_set = JCROP_POS; - transformoption.crop_height = dropinfo.image_height; - transformoption.crop_height_set = JCROP_POS; - transformoption.drop_ptr = &dropinfo; - } -#endif + /* Adjust default decompression parameters */ + if (scaleoption != NULL) + if (sscanf(scaleoption, "%d/%d", + &srcinfo.scale_num, &srcinfo.scale_denom) < 1) + usage(); /* Any space needed by a transform option must be requested before * jpeg_read_coefficients so that memory allocation will be done right. */ #if TRANSFORMS_SUPPORTED - /* Fails right away if -perfect is given and transformation is not perfect. + /* Fail right away if -perfect is given and transformation is not perfect. */ - if (transformoption.perfect && - !jtransform_perfect_transform(srcinfo.image_width, srcinfo.image_height, - srcinfo.max_h_samp_factor * DCTSIZE, srcinfo.max_v_samp_factor * DCTSIZE, - transformoption.transform)) { + if (!jtransform_request_workspace(&srcinfo, &transformoption)) { fprintf(stderr, "%s: transformation is not perfect\n", progname); exit(EXIT_FAILURE); } - jtransform_request_workspace(&srcinfo, &transformoption); #endif /* Read source file as DCT coefficients */ src_coef_arrays = jpeg_read_coefficients(&srcinfo); -#if TRANSFORMS_SUPPORTED - if (dropfilename != NULL) { - transformoption.drop_coef_arrays = jpeg_read_coefficients(&dropinfo); - } -#endif - /* Initialize destination compression parameters from source values */ jpeg_copy_critical_parameters(&srcinfo, &dstinfo); - /* Adjust destination parameters if required by transform options; * also find out which set of coefficient arrays will hold the output. */ @@ -621,12 +522,8 @@ main (int argc, char **argv) } /* Adjust default compression parameters by re-parsing the options */ - /* Save value of copyoption */ file_index = parse_switches(&dstinfo, argc, argv, 0, TRUE); - /* If we want EXIF, make sure we do not write incompatible markers */ - handle_exif(&srcinfo,&dstinfo,©option); - /* Specify data destination for compression */ jpeg_stdio_dest(&dstinfo, fp); @@ -638,41 +535,26 @@ main (int argc, char **argv) /* Execute image transformation, if any */ #if TRANSFORMS_SUPPORTED - jtransform_execute_transform(&srcinfo, &dstinfo, - src_coef_arrays, - &transformoption); + jtransform_execute_transformation(&srcinfo, &dstinfo, + src_coef_arrays, + &transformoption); #endif /* Finish compression and release memory */ jpeg_finish_compress(&dstinfo); jpeg_destroy_compress(&dstinfo); -#if TRANSFORMS_SUPPORTED - if (dropfilename != NULL) { - (void) jpeg_finish_decompress(&dropinfo); - jpeg_destroy_decompress(&dropinfo); - } -#endif (void) jpeg_finish_decompress(&srcinfo); jpeg_destroy_decompress(&srcinfo); /* Close output file, if we opened it */ if (fp != stdout) fclose(fp); -#if TRANSFORMS_SUPPORTED - if (drop_file != NULL) - fclose(drop_file); -#endif #ifdef PROGRESS_REPORT end_progress_monitor((j_common_ptr) &dstinfo); #endif /* All done. */ -#if TRANSFORMS_SUPPORTED - if (dropfilename != NULL) - exit(jsrcerr.num_warnings + jdroperr.num_warnings + jdsterr.num_warnings ? - EXIT_WARNING : EXIT_SUCCESS); -#endif exit(jsrcerr.num_warnings + jdsterr.num_warnings ?EXIT_WARNING:EXIT_SUCCESS); return 0; /* suppress no-return-value warnings */ } diff --git a/reactos/dll/3rdparty/libjpeg/jutils.c b/reactos/dll/3rdparty/libjpeg/jutils.c index d18a9555621..04351797cd7 100644 --- a/reactos/dll/3rdparty/libjpeg/jutils.c +++ b/reactos/dll/3rdparty/libjpeg/jutils.c @@ -2,6 +2,7 @@ * jutils.c * * Copyright (C) 1991-1996, Thomas G. Lane. + * Modified 2009 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -63,6 +64,57 @@ const int jpeg_natural_order[DCTSIZE2+16] = { 63, 63, 63, 63, 63, 63, 63, 63 }; +const int jpeg_natural_order7[7*7+16] = { + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 14, 21, 28, 35, + 42, 49, 50, 43, 36, 29, 22, 30, + 37, 44, 51, 52, 45, 38, 46, 53, + 54, + 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ + 63, 63, 63, 63, 63, 63, 63, 63 +}; + +const int jpeg_natural_order6[6*6+16] = { + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 41, 34, 27, + 20, 13, 21, 28, 35, 42, 43, 36, + 29, 37, 44, 45, + 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ + 63, 63, 63, 63, 63, 63, 63, 63 +}; + +const int jpeg_natural_order5[5*5+16] = { + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 12, + 19, 26, 33, 34, 27, 20, 28, 35, + 36, + 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ + 63, 63, 63, 63, 63, 63, 63, 63 +}; + +const int jpeg_natural_order4[4*4+16] = { + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 25, 18, 11, 19, 26, 27, + 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ + 63, 63, 63, 63, 63, 63, 63, 63 +}; + +const int jpeg_natural_order3[3*3+16] = { + 0, 1, 8, 16, 9, 2, 10, 17, + 18, + 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ + 63, 63, 63, 63, 63, 63, 63, 63 +}; + +const int jpeg_natural_order2[2*2+16] = { + 0, 1, 8, 9, + 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ + 63, 63, 63, 63, 63, 63, 63, 63 +}; + /* * Arithmetic utilities diff --git a/reactos/dll/3rdparty/libjpeg/jversion.h b/reactos/dll/3rdparty/libjpeg/jversion.h index 6472c58d351..70c8b6fe176 100644 --- a/reactos/dll/3rdparty/libjpeg/jversion.h +++ b/reactos/dll/3rdparty/libjpeg/jversion.h @@ -1,7 +1,7 @@ /* * jversion.h * - * Copyright (C) 1991-1998, Thomas G. Lane. + * Copyright (C) 1991-2010, Thomas G. Lane, Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -9,6 +9,6 @@ */ -#define JVERSION "6b 27-Mar-1998" +#define JVERSION "8b 16-May-2010" -#define JCOPYRIGHT "Copyright (C) 1998, Thomas G. Lane" +#define JCOPYRIGHT "Copyright (C) 2010, Thomas G. Lane, Guido Vollbeding" diff --git a/reactos/dll/3rdparty/libjpeg/libjpeg.rbuild b/reactos/dll/3rdparty/libjpeg/libjpeg.rbuild index 9749f7ab35e..5916c5de7ee 100644 --- a/reactos/dll/3rdparty/libjpeg/libjpeg.rbuild +++ b/reactos/dll/3rdparty/libjpeg/libjpeg.rbuild @@ -7,8 +7,10 @@ mainptr . + jaricom.c jcapimin.c jcapistd.c + jcarith.c jccoefct.c jccolor.c jcdctmgr.c @@ -19,12 +21,12 @@ jcmaster.c jcomapi.c jcparam.c - jcphuff.c jcprepct.c jcsample.c jctrans.c jdapimin.c jdapistd.c + jdarith.c jdatadst.c jdatasrc.c jdcoefct.c @@ -36,7 +38,6 @@ jdmarker.c jdmaster.c jdmerge.c - jdphuff.c jdpostct.c jdsample.c jdtrans.c @@ -47,7 +48,6 @@ jidctflt.c jidctfst.c jidctint.c - jidctred.c jquant1.c jquant2.c jutils.c diff --git a/reactos/dll/3rdparty/libjpeg/libjpeg.reactos.diff b/reactos/dll/3rdparty/libjpeg/libjpeg.reactos.diff deleted file mode 100644 index 5793f5153bf..00000000000 --- a/reactos/dll/3rdparty/libjpeg/libjpeg.reactos.diff +++ /dev/null @@ -1,12 +0,0 @@ -Index: jmorecfg.h -=================================================================== ---- jmorecfg.h (revision 42441) -+++ jmorecfg.h (working copy) -@@ -24,7 +24,6 @@ - - #if (defined (_MSC_VER) && (_MSC_VER >= 800)) - #define HAVE_UNSIGNED_CHAR --#define HAVE_ALL_INTS - #define EXTERN(type) extern type __cdecl - #endif - diff --git a/reactos/dll/3rdparty/libjpeg/makefile.ansi b/reactos/dll/3rdparty/libjpeg/makefile.ansi index 82919135937..7d0499f8f49 100644 --- a/reactos/dll/3rdparty/libjpeg/makefile.ansi +++ b/reactos/dll/3rdparty/libjpeg/makefile.ansi @@ -38,13 +38,13 @@ AR2= ranlib # source files: JPEG library proper -LIBSOURCES= jcapimin.c jcapistd.c jccoefct.c jccolor.c jcdctmgr.c jchuff.c \ - jcinit.c jcmainct.c jcmarker.c jcmaster.c jcomapi.c jcparam.c \ - jcphuff.c jcprepct.c jcsample.c jctrans.c jdapimin.c jdapistd.c \ - jdatadst.c jdatasrc.c jdcoefct.c jdcolor.c jddctmgr.c jdhuff.c \ - jdinput.c jdmainct.c jdmarker.c jdmaster.c jdmerge.c jdphuff.c \ - jdpostct.c jdsample.c jdtrans.c jerror.c jfdctflt.c jfdctfst.c \ - jfdctint.c jidctflt.c jidctfst.c jidctint.c jidctred.c jquant1.c \ +LIBSOURCES= jaricom.c jcapimin.c jcapistd.c jcarith.c jccoefct.c jccolor.c \ + jcdctmgr.c jchuff.c jcinit.c jcmainct.c jcmarker.c jcmaster.c \ + jcomapi.c jcparam.c jcprepct.c jcsample.c jctrans.c jdapimin.c \ + jdapistd.c jdarith.c jdatadst.c jdatasrc.c jdcoefct.c jdcolor.c \ + jddctmgr.c jdhuff.c jdinput.c jdmainct.c jdmarker.c jdmaster.c \ + jdmerge.c jdpostct.c jdsample.c jdtrans.c jerror.c jfdctflt.c \ + jfdctfst.c jfdctint.c jidctflt.c jidctfst.c jidctint.c jquant1.c \ jquant2.c jutils.c jmemmgr.c # memmgr back ends: compile only one of these into a working library SYSDEPSOURCES= jmemansi.c jmemname.c jmemnobs.c jmemdos.c jmemmac.c @@ -54,38 +54,45 @@ APPSOURCES= cjpeg.c djpeg.c jpegtran.c rdjpgcom.c wrjpgcom.c cdjpeg.c \ rdtarga.c wrtarga.c rdbmp.c wrbmp.c rdrle.c wrrle.c SOURCES= $(LIBSOURCES) $(SYSDEPSOURCES) $(APPSOURCES) # files included by source files -INCLUDES= jchuff.h jdhuff.h jdct.h jerror.h jinclude.h jmemsys.h jmorecfg.h \ - jpegint.h jpeglib.h jversion.h cdjpeg.h cderror.h transupp.h +INCLUDES= jdct.h jerror.h jinclude.h jmemsys.h jmorecfg.h jpegint.h \ + jpeglib.h jversion.h cdjpeg.h cderror.h transupp.h # documentation, test, and support files -DOCS= README install.doc usage.doc cjpeg.1 djpeg.1 jpegtran.1 rdjpgcom.1 \ - wrjpgcom.1 wizard.doc example.c libjpeg.doc structure.doc \ - coderules.doc filelist.doc change.log -MKFILES= configure makefile.cfg makefile.ansi makefile.unix makefile.bcc \ - makefile.mc6 makefile.dj makefile.wat makefile.vc makelib.ds \ - makeapps.ds makeproj.mac makcjpeg.st makdjpeg.st makljpeg.st \ - maktjpeg.st makefile.manx makefile.sas makefile.mms makefile.vms \ - makvms.opt +DOCS= README install.txt usage.txt cjpeg.1 djpeg.1 jpegtran.1 rdjpgcom.1 \ + wrjpgcom.1 wizard.txt example.c libjpeg.txt structure.txt \ + coderules.txt filelist.txt change.log +MKFILES= configure Makefile.in makefile.ansi makefile.unix makefile.bcc \ + makefile.mc6 makefile.dj makefile.wat makefile.vc makejdsw.vc6 \ + makeadsw.vc6 makejdep.vc6 makejdsp.vc6 makejmak.vc6 makecdep.vc6 \ + makecdsp.vc6 makecmak.vc6 makeddep.vc6 makeddsp.vc6 makedmak.vc6 \ + maketdep.vc6 maketdsp.vc6 maketmak.vc6 makerdep.vc6 makerdsp.vc6 \ + makermak.vc6 makewdep.vc6 makewdsp.vc6 makewmak.vc6 makejsln.v10 \ + makeasln.v10 makejvcx.v10 makejfil.v10 makecvcx.v10 makecfil.v10 \ + makedvcx.v10 makedfil.v10 maketvcx.v10 maketfil.v10 makervcx.v10 \ + makerfil.v10 makewvcx.v10 makewfil.v10 makeproj.mac makcjpeg.st \ + makdjpeg.st makljpeg.st maktjpeg.st makefile.manx makefile.sas \ + makefile.mms makefile.vms makvms.opt CONFIGFILES= jconfig.cfg jconfig.bcc jconfig.mc6 jconfig.dj jconfig.wat \ jconfig.vc jconfig.mac jconfig.st jconfig.manx jconfig.sas \ jconfig.vms -CONFIGUREFILES= config.guess config.sub install-sh ltconfig ltmain.sh -OTHERFILES= jconfig.doc ckconfig.c ansi2knr.c ansi2knr.1 jmemdosa.asm +CONFIGUREFILES= config.guess config.sub install-sh ltmain.sh depcomp missing +OTHERFILES= jconfig.txt ckconfig.c ansi2knr.c ansi2knr.1 jmemdosa.asm \ + libjpeg.map TESTFILES= testorig.jpg testimg.ppm testimg.bmp testimg.jpg testprog.jpg \ testimgp.jpg DISTFILES= $(DOCS) $(MKFILES) $(CONFIGFILES) $(SOURCES) $(INCLUDES) \ $(CONFIGUREFILES) $(OTHERFILES) $(TESTFILES) # library object files common to compression and decompression -COMOBJECTS= jcomapi.o jutils.o jerror.o jmemmgr.o $(SYSDEPMEM) +COMOBJECTS= jaricom.o jcomapi.o jutils.o jerror.o jmemmgr.o $(SYSDEPMEM) # compression library object files -CLIBOBJECTS= jcapimin.o jcapistd.o jctrans.o jcparam.o jdatadst.o jcinit.o \ - jcmaster.o jcmarker.o jcmainct.o jcprepct.o jccoefct.o jccolor.o \ - jcsample.o jchuff.o jcphuff.o jcdctmgr.o jfdctfst.o jfdctflt.o \ - jfdctint.o +CLIBOBJECTS= jcapimin.o jcapistd.o jcarith.o jctrans.o jcparam.o \ + jdatadst.o jcinit.o jcmaster.o jcmarker.o jcmainct.o jcprepct.o \ + jccoefct.o jccolor.o jcsample.o jchuff.o jcdctmgr.o jfdctfst.o \ + jfdctflt.o jfdctint.o # decompression library object files -DLIBOBJECTS= jdapimin.o jdapistd.o jdtrans.o jdatasrc.o jdmaster.o \ - jdinput.o jdmarker.o jdhuff.o jdphuff.o jdmainct.o jdcoefct.o \ - jdpostct.o jddctmgr.o jidctfst.o jidctflt.o jidctint.o jidctred.o \ - jdsample.o jdcolor.o jquant1.o jquant2.o jdmerge.o +DLIBOBJECTS= jdapimin.o jdapistd.o jdarith.o jdtrans.o jdatasrc.o \ + jdmaster.o jdinput.o jdmarker.o jdhuff.o jdmainct.o \ + jdcoefct.o jdpostct.o jddctmgr.o jidctfst.o jidctflt.o \ + jidctint.o jdsample.o jdcolor.o jquant1.o jquant2.o jdmerge.o # These objectfiles are included in libjpeg.a LIBOBJECTS= $(CLIBOBJECTS) $(DLIBOBJECTS) $(COMOBJECTS) # object files for sample applications (excluding library files) @@ -118,9 +125,9 @@ rdjpgcom: rdjpgcom.o wrjpgcom: wrjpgcom.o $(LN) $(LDFLAGS) -o wrjpgcom wrjpgcom.o $(LDLIBS) -jconfig.h: jconfig.doc +jconfig.h: jconfig.txt echo You must prepare a system-dependent jconfig.h file. - echo Please read the installation directions in install.doc. + echo Please read the installation directions in install.txt. exit 1 clean: @@ -143,36 +150,37 @@ test: cjpeg djpeg jpegtran cmp testorig.jpg testoutt.jpg +jaricom.o: jaricom.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcapimin.o: jcapimin.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcapistd.o: jcapistd.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jcarith.o: jcarith.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jccoefct.o: jccoefct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jccolor.o: jccolor.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcdctmgr.o: jcdctmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h -jchuff.o: jchuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jchuff.h +jchuff.o: jchuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcinit.o: jcinit.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcmainct.o: jcmainct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcmarker.o: jcmarker.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcmaster.o: jcmaster.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcomapi.o: jcomapi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcparam.o: jcparam.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h -jcphuff.o: jcphuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jchuff.h jcprepct.o: jcprepct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcsample.o: jcsample.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jctrans.o: jctrans.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdapimin.o: jdapimin.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdapistd.o: jdapistd.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h +jdarith.o: jdarith.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdatadst.o: jdatadst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h jdatasrc.o: jdatasrc.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h jdcoefct.o: jdcoefct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdcolor.o: jdcolor.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jddctmgr.o: jddctmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h -jdhuff.o: jdhuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdhuff.h +jdhuff.o: jdhuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdinput.o: jdinput.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdmainct.o: jdmainct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdmarker.o: jdmarker.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdmaster.o: jdmaster.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdmerge.o: jdmerge.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h -jdphuff.o: jdphuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdhuff.h jdpostct.o: jdpostct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdsample.o: jdsample.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdtrans.o: jdtrans.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h @@ -183,7 +191,6 @@ jfdctint.o: jfdctint.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerro jidctflt.o: jidctflt.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jidctfst.o: jidctfst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jidctint.o: jidctint.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h -jidctred.o: jidctred.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jquant1.o: jquant1.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jquant2.o: jquant2.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jutils.o: jutils.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h diff --git a/reactos/dll/3rdparty/libjpeg/rdbmp.c b/reactos/dll/3rdparty/libjpeg/rdbmp.c index b05fe2ac47c..fd773d4bb5e 100644 --- a/reactos/dll/3rdparty/libjpeg/rdbmp.c +++ b/reactos/dll/3rdparty/libjpeg/rdbmp.c @@ -2,6 +2,7 @@ * rdbmp.c * * Copyright (C) 1994-1996, Thomas G. Lane. + * Modified 2009-2010 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -177,10 +178,41 @@ get_24bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) } +METHODDEF(JDIMENSION) +get_32bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading 32-bit pixels */ +{ + bmp_source_ptr source = (bmp_source_ptr) sinfo; + JSAMPARRAY image_ptr; + register JSAMPROW inptr, outptr; + register JDIMENSION col; + + /* Fetch next row from virtual array */ + source->source_row--; + image_ptr = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, source->whole_image, + source->source_row, (JDIMENSION) 1, FALSE); + /* Transfer data. Note source values are in BGR order + * (even though Microsoft's own documents say the opposite). + */ + inptr = image_ptr[0]; + outptr = source->pub.buffer[0]; + for (col = cinfo->image_width; col > 0; col--) { + outptr[2] = *inptr++; /* can omit GETJSAMPLE() safely */ + outptr[1] = *inptr++; + outptr[0] = *inptr++; + inptr++; /* skip the 4th byte (Alpha channel) */ + outptr += 3; + } + + return 1; +} + + /* * This method loads the image into whole_image during the first call on * get_pixel_rows. The get_pixel_rows pointer is then adjusted to call - * get_8bit_row or get_24bit_row on subsequent calls. + * get_8bit_row, get_24bit_row, or get_32bit_row on subsequent calls. */ METHODDEF(JDIMENSION) @@ -223,6 +255,9 @@ preload_image (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) case 24: source->pub.get_pixel_rows = get_24bit_row; break; + case 32: + source->pub.get_pixel_rows = get_32bit_row; + break; default: ERREXIT(cinfo, JERR_BMP_BADDEPTH); } @@ -251,8 +286,8 @@ start_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) (((INT32) UCH(array[offset+3])) << 24)) INT32 bfOffBits; INT32 headerSize; - INT32 biWidth = 0; /* initialize to avoid compiler warning */ - INT32 biHeight = 0; + INT32 biWidth; + INT32 biHeight; unsigned int biPlanes; INT32 biCompression; INT32 biXPelsPerMeter,biYPelsPerMeter; @@ -300,8 +335,6 @@ start_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) ERREXIT(cinfo, JERR_BMP_BADDEPTH); break; } - if (biPlanes != 1) - ERREXIT(cinfo, JERR_BMP_BADPLANES); break; case 40: case 64: @@ -325,12 +358,13 @@ start_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) case 24: /* RGB image */ TRACEMS2(cinfo, 1, JTRC_BMP, (int) biWidth, (int) biHeight); break; + case 32: /* RGB image + Alpha channel */ + TRACEMS2(cinfo, 1, JTRC_BMP, (int) biWidth, (int) biHeight); + break; default: ERREXIT(cinfo, JERR_BMP_BADDEPTH); break; } - if (biPlanes != 1) - ERREXIT(cinfo, JERR_BMP_BADPLANES); if (biCompression != 0) ERREXIT(cinfo, JERR_BMP_COMPRESSED); @@ -343,9 +377,14 @@ start_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) break; default: ERREXIT(cinfo, JERR_BMP_BADHEADER); - break; + return; } + if (biWidth <= 0 || biHeight <= 0) + ERREXIT(cinfo, JERR_BMP_EMPTY); + if (biPlanes != 1) + ERREXIT(cinfo, JERR_BMP_BADPLANES); + /* Compute distance to bitmap data --- will adjust for colormap below */ bPad = bfOffBits - (headerSize + 14); @@ -375,6 +414,8 @@ start_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) /* Compute row width in file, including padding to 4-byte boundary */ if (source->bits_per_pixel == 24) row_width = (JDIMENSION) (biWidth * 3); + else if (source->bits_per_pixel == 32) + row_width = (JDIMENSION) (biWidth * 4); else row_width = (JDIMENSION) biWidth; while ((row_width & 3) != 0) row_width++; diff --git a/reactos/dll/3rdparty/libjpeg/rdjpgcom.c b/reactos/dll/3rdparty/libjpeg/rdjpgcom.c index bafd30b2fdc..37191547486 100644 --- a/reactos/dll/3rdparty/libjpeg/rdjpgcom.c +++ b/reactos/dll/3rdparty/libjpeg/rdjpgcom.c @@ -2,6 +2,7 @@ * rdjpgcom.c * * Copyright (C) 1994-1997, Thomas G. Lane. + * Modified 2009 by Bill Allombert, Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -14,7 +15,9 @@ #define JPEG_CJPEG_DJPEG /* to get the command-line config symbols */ #include "jinclude.h" /* get auto-config symbols, */ -#include /* to declare setlocale() */ +#ifdef HAVE_LOCALE_H +#include /* Bill Allombert: use locale for isprint */ +#endif #include /* to declare isupper(), tolower() */ #ifdef USE_SETMODE #include /* to declare setmode()'s parameter macros */ @@ -121,7 +124,6 @@ read_2_bytes (void) #define M_EOI 0xD9 /* End Of Image (end of datastream) */ #define M_SOS 0xDA /* Start Of Scan (begins compressed data) */ #define M_APP0 0xE0 /* Application-specific marker, type N */ -#define M_APP1 0xE1 /* Typically EXIF marker */ #define M_APP12 0xEC /* (we don't bother to list all 16 APPn's) */ #define M_COM 0xFE /* COMment */ @@ -212,175 +214,6 @@ skip_variable (void) } } -/* - * Helper routine to skip the given number of bytes. - */ - -static void -skip_n (unsigned int length) -{ - while (length > 0) { - (void) read_1_byte(); - length--; - } -} - -/* - * Parses an APP1 marker looking for EXIF data. If EXIF, the orientation is - * reported to stdout. - */ - -static void -process_APP1 (void) -{ - unsigned int length, i; - int is_motorola; /* byte order indicator */ - unsigned int offset, number_of_tags, tagnum; - int orientation; - char *ostr; - /* This 64K buffer would probably be best if allocated dynamically, but it's - * the only one on this program so it's really not that - * important. Allocating on the stack is not an option, as 64K might be too - * big for some (crippled) platforms. */ - static unsigned char exif_data[65536L]; - - /* Get the marker parameter length count */ - length = read_2_bytes(); - /* Length includes itself, so must be at least 2 */ - if (length < 2) - ERREXIT("Erroneous JPEG marker length"); - length -= 2; - - /* We only care if APP1 is really an EXIF marker. Minimum length is 6 for - * signature plus 12 for an IFD. */ - if (length < 18) { - skip_n(length); - return; - } - - /* Check for actual EXIF marker */ - for (i=0; i < 6; i++) - exif_data[i] = (unsigned char) read_1_byte(); - length -= 6; - if (exif_data[0] != 0x45 || - exif_data[1] != 0x78 || - exif_data[2] != 0x69 || - exif_data[3] != 0x66 || - exif_data[4] != 0 || - exif_data[5] != 0) { - skip_n(length); - return; - } - - /* Read all EXIF body */ - for (i=0; i < length; i++) - exif_data[i] = (unsigned char) read_1_byte(); - - /* Discover byte order */ - if (exif_data[0] == 0x49 && exif_data[1] == 0x49) - is_motorola = 0; - else if (exif_data[0] == 0x4D && exif_data[1] == 0x4D) - is_motorola = 1; - else - return; - - /* Check Tag Mark */ - if (is_motorola) { - if (exif_data[2] != 0) return; - if (exif_data[3] != 0x2A) return; - } else { - if (exif_data[3] != 0) return; - if (exif_data[2] != 0x2A) return; - } - - /* Get first IFD offset (offset to IFD0) */ - if (is_motorola) { - if (exif_data[4] != 0) return; - if (exif_data[5] != 0) return; - offset = exif_data[6]; - offset <<= 8; - offset += exif_data[7]; - } else { - if (exif_data[7] != 0) return; - if (exif_data[6] != 0) return; - offset = exif_data[5]; - offset <<= 8; - offset += exif_data[4]; - } - if (offset > length - 2) return; /* check end of data segment */ - - /* Get the number of directory entries contained in this IFD */ - if (is_motorola) { - number_of_tags = exif_data[offset]; - number_of_tags <<= 8; - number_of_tags += exif_data[offset+1]; - } else { - number_of_tags = exif_data[offset+1]; - number_of_tags <<= 8; - number_of_tags += exif_data[offset]; - } - if (number_of_tags == 0) return; - offset += 2; - - /* Search for Orientation Tag in IFD0 */ - for (;;) { - if (offset > length - 12) return; /* check end of data segment */ - /* Get Tag number */ - if (is_motorola) { - tagnum = exif_data[offset]; - tagnum <<= 8; - tagnum += exif_data[offset+1]; - } else { - tagnum = exif_data[offset+1]; - tagnum <<= 8; - tagnum += exif_data[offset]; - } - if (tagnum == 0x0112) break; /* found Orientation Tag */ - if (--number_of_tags == 0) return; - offset += 12; - } - - /* Get the Orientation value */ - if (is_motorola) { - if (exif_data[offset+8] != 0) return; - orientation = exif_data[offset+9]; - } else { - if (exif_data[offset+9] != 0) return; - orientation = exif_data[offset+8]; - } - if (orientation == 0 || orientation > 8) return; - - /* Print the orientation (position of the 0th row - 0th column) */ - switch (orientation) { - case 1: - ostr = "top-left"; - break; - case 2: - ostr = "top-right"; - break; - case 3: - ostr = "bottom-right"; - break; - case 4: - ostr = "bottom-left"; - break; - case 5: - ostr = "left-top"; - break; - case 6: - ostr = "right-top"; - break; - case 7: - ostr = "right-bottom"; - break; - case 8: - ostr = "left-bottom"; - break; - default: - return; - } - printf("EXIF orientation: %s\n",ostr); -} /* * Process a COM marker. @@ -389,15 +222,17 @@ process_APP1 (void) */ static void -process_COM (void) +process_COM (int raw) { unsigned int length; int ch; int lastch = 0; -/* ballombe@debian.org Thu, 15 Nov 2001 20:04:47 +0100*/ -/* Set locale properly for isprint*/ - setlocale(LC_CTYPE,""); - + + /* Bill Allombert: set locale properly for isprint */ +#ifdef HAVE_LOCALE_H + setlocale(LC_CTYPE, ""); +#endif + /* Get the marker parameter length count */ length = read_2_bytes(); /* Length includes itself, so must be at least 2 */ @@ -405,15 +240,16 @@ process_COM (void) ERREXIT("Erroneous JPEG marker length"); length -= 2; - setlocale(LC_ALL, ""); while (length > 0) { ch = read_1_byte(); + if (raw) { + putc(ch, stdout); /* Emit the character in a readable form. * Nonprintables are converted to \nnn form, * while \ is converted to \\. * Newlines in CR, CR/LF, or LF form will be printed as one newline. */ - if (ch == '\r') { + } else if (ch == '\r') { printf("\n"); } else if (ch == '\n') { if (lastch != '\r') @@ -429,8 +265,11 @@ process_COM (void) length--; } printf("\n"); -/*ballombe@debian.org: revert to C locale*/ - setlocale(LC_CTYPE,"C"); + + /* Bill Allombert: revert to C locale */ +#ifdef HAVE_LOCALE_H + setlocale(LC_CTYPE, "C"); +#endif } @@ -498,7 +337,7 @@ process_SOFn (int marker) */ static int -scan_JPEG_header (int verbose) +scan_JPEG_header (int verbose, int raw) { int marker; @@ -539,16 +378,7 @@ scan_JPEG_header (int verbose) return marker; case M_COM: - process_COM(); - break; - - case M_APP1: - /* APP1 is usually the EXIF marker used by digital cameras, attempt to - * process it to give some useful info. */ - if (verbose) { - process_APP1(); - } else - skip_variable(); + process_COM(raw); break; case M_APP12: @@ -557,7 +387,7 @@ scan_JPEG_header (int verbose) */ if (verbose) { printf("APP12 contains:\n"); - process_COM(); + process_COM(raw); } else skip_variable(); break; @@ -584,6 +414,7 @@ usage (void) fprintf(stderr, "Usage: %s [switches] [inputfile]\n", progname); fprintf(stderr, "Switches (names may be abbreviated):\n"); + fprintf(stderr, " -raw Display non-printable characters in comments (unsafe)\n"); fprintf(stderr, " -verbose Also display dimensions of JPEG image\n"); exit(EXIT_FAILURE); @@ -624,7 +455,7 @@ main (int argc, char **argv) { int argn; char * arg; - int verbose = 0; + int verbose = 0, raw = 0; /* On Mac, fetch a command line. */ #ifdef USE_CCOMMAND @@ -643,6 +474,8 @@ main (int argc, char **argv) arg++; /* advance over '-' */ if (keymatch(arg, "verbose", 1)) { verbose++; + } else if (keymatch(arg, "raw", 1)) { + raw = 1; } else usage(); } @@ -674,7 +507,7 @@ main (int argc, char **argv) } /* Scan the JPEG headers. */ - (void) scan_JPEG_header(verbose); + (void) scan_JPEG_header(verbose, raw); /* All done. */ exit(EXIT_SUCCESS); diff --git a/reactos/dll/3rdparty/libjpeg/rdppm.c b/reactos/dll/3rdparty/libjpeg/rdppm.c index 309c943d77d..a7570227ce9 100644 --- a/reactos/dll/3rdparty/libjpeg/rdppm.c +++ b/reactos/dll/3rdparty/libjpeg/rdppm.c @@ -2,6 +2,7 @@ * rdppm.c * * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 2009 by Bill Allombert, Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * diff --git a/reactos/dll/3rdparty/libjpeg/rdswitch.c b/reactos/dll/3rdparty/libjpeg/rdswitch.c index 4f4bb4f5899..7a839af7a4f 100644 --- a/reactos/dll/3rdparty/libjpeg/rdswitch.c +++ b/reactos/dll/3rdparty/libjpeg/rdswitch.c @@ -9,6 +9,7 @@ * command-line switches. Switches processed here are: * -qtables file Read quantization tables from text file * -scans file Read scan script from text file + * -quality N[,N,...] Set quality ratings * -qslots N[,N,...] Set component quantization table selectors * -sample HxV[,HxV,...] Set component sampling factors */ @@ -70,8 +71,7 @@ read_text_integer (FILE * file, long * result, int * termchar) GLOBAL(boolean) -read_quant_tables (j_compress_ptr cinfo, char * filename, - int scale_factor, boolean force_baseline) +read_quant_tables (j_compress_ptr cinfo, char * filename, boolean force_baseline) /* Read a set of quantization tables from the specified file. * The file is plain ASCII text: decimal numbers with whitespace between. * Comments preceded by '#' may be included in the file. @@ -108,7 +108,8 @@ read_quant_tables (j_compress_ptr cinfo, char * filename, } table[i] = (unsigned int) val; } - jpeg_add_quant_table(cinfo, tblno, table, scale_factor, force_baseline); + jpeg_add_quant_table(cinfo, tblno, table, cinfo->q_scale_factor[tblno], + force_baseline); tblno++; } @@ -262,6 +263,38 @@ bogus: #endif /* C_MULTISCAN_FILES_SUPPORTED */ +GLOBAL(boolean) +set_quality_ratings (j_compress_ptr cinfo, char *arg, boolean force_baseline) +/* Process a quality-ratings parameter string, of the form + * N[,N,...] + * If there are more q-table slots than parameters, the last value is replicated. + */ +{ + int val = 75; /* default value */ + int tblno; + char ch; + + for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) { + if (*arg) { + ch = ','; /* if not set by sscanf, will be ',' */ + if (sscanf(arg, "%d%c", &val, &ch) < 1) + return FALSE; + if (ch != ',') /* syntax check */ + return FALSE; + /* Convert user 0-100 rating to percentage scaling */ + cinfo->q_scale_factor[tblno] = jpeg_quality_scaling(val); + while (*arg && *arg++ != ',') /* advance to next segment of arg string */ + ; + } else { + /* reached end of parameter, set remaining factors to last value */ + cinfo->q_scale_factor[tblno] = jpeg_quality_scaling(val); + } + } + jpeg_default_qtables(cinfo, force_baseline); + return TRUE; +} + + GLOBAL(boolean) set_quant_slots (j_compress_ptr cinfo, char *arg) /* Process a quantization-table-selectors parameter string, of the form diff --git a/reactos/dll/3rdparty/libjpeg/transupp.c b/reactos/dll/3rdparty/libjpeg/transupp.c index 3d12d00dc75..4060544828e 100644 --- a/reactos/dll/3rdparty/libjpeg/transupp.c +++ b/reactos/dll/3rdparty/libjpeg/transupp.c @@ -1,7 +1,7 @@ /* * transupp.c * - * Copyright (C) 1997-2001, Thomas G. Lane. + * Copyright (C) 1997-2009, Thomas G. Lane, Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -75,293 +75,23 @@ */ -/* Drop code may be used with or without virtual memory adaptation code. - * This code has some dependencies on internal library behavior, so you - * may choose to disable it. For example, it doesn't make a difference - * if you only use jmemnobs anyway. - */ -#ifndef DROP_REQUEST_FROM_SRC -#define DROP_REQUEST_FROM_SRC 1 /* 0 disables adaptation */ -#endif - - -#if DROP_REQUEST_FROM_SRC -/* Force jpeg_read_coefficients to request - * the virtual coefficient arrays from - * the source decompression object. - */ -METHODDEF(jvirt_barray_ptr) -drop_request_virt_barray (j_common_ptr cinfo, int pool_id, boolean pre_zero, - JDIMENSION blocksperrow, JDIMENSION numrows, - JDIMENSION maxaccess) -{ - j_decompress_ptr srcinfo = (j_decompress_ptr) cinfo->client_data; - - return (*srcinfo->mem->request_virt_barray) - ((j_common_ptr) srcinfo, pool_id, pre_zero, - blocksperrow, numrows, maxaccess); -} - - -/* Force jpeg_read_coefficients to return - * after requesting and before accessing - * the virtual coefficient arrays. - */ -METHODDEF(int) -drop_consume_input (j_decompress_ptr cinfo) -{ - return JPEG_SUSPENDED; -} - - -METHODDEF(void) -drop_start_input_pass (j_decompress_ptr cinfo) -{ - cinfo->inputctl->consume_input = drop_consume_input; -} - - -LOCAL(void) -drop_request_from_src (j_decompress_ptr dropinfo, j_decompress_ptr srcinfo) -{ - void *save_client_data; - JMETHOD(jvirt_barray_ptr, save_request_virt_barray, - (j_common_ptr cinfo, int pool_id, boolean pre_zero, - JDIMENSION blocksperrow, JDIMENSION numrows, JDIMENSION maxaccess)); - JMETHOD(void, save_start_input_pass, (j_decompress_ptr cinfo)); - - /* Set custom method pointers, save original pointers */ - save_client_data = dropinfo->client_data; - dropinfo->client_data = (void *) srcinfo; - save_request_virt_barray = dropinfo->mem->request_virt_barray; - dropinfo->mem->request_virt_barray = drop_request_virt_barray; - save_start_input_pass = dropinfo->inputctl->start_input_pass; - dropinfo->inputctl->start_input_pass = drop_start_input_pass; - - /* Execute only initialization part. - * Requested coefficient arrays will be realized later by the srcinfo object. - * Next call to the same function will then do the actual data reading. - * NB: since we request the coefficient arrays from another object, - * the inherent realization call is effectively a no-op. - */ - (void) jpeg_read_coefficients(dropinfo); - - /* Reset method pointers */ - dropinfo->client_data = save_client_data; - dropinfo->mem->request_virt_barray = save_request_virt_barray; - dropinfo->inputctl->start_input_pass = save_start_input_pass; - /* Do input initialization for first scan now, - * which also resets the consume_input method. - */ - (*save_start_input_pass)(dropinfo); -} -#endif /* DROP_REQUEST_FROM_SRC */ - - -LOCAL(void) -dequant_comp (j_decompress_ptr cinfo, jpeg_component_info *compptr, - jvirt_barray_ptr coef_array, JQUANT_TBL *qtblptr1) -{ - JDIMENSION blk_x, blk_y; - int offset_y, k; - JQUANT_TBL *qtblptr; - JBLOCKARRAY buffer; - JBLOCKROW block; - JCOEFPTR ptr; - - qtblptr = compptr->quant_table; - for (blk_y = 0; blk_y < compptr->height_in_blocks; - blk_y += compptr->v_samp_factor) { - buffer = (*cinfo->mem->access_virt_barray) - ((j_common_ptr) cinfo, coef_array, blk_y, - (JDIMENSION) compptr->v_samp_factor, TRUE); - for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { - block = buffer[offset_y]; - for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) { - ptr = block[blk_x]; - for (k = 0; k < DCTSIZE2; k++) - if (qtblptr->quantval[k] != qtblptr1->quantval[k]) - ptr[k] *= qtblptr->quantval[k] / qtblptr1->quantval[k]; - } - } - } -} - - -LOCAL(void) -requant_comp (j_decompress_ptr cinfo, jpeg_component_info *compptr, - jvirt_barray_ptr coef_array, JQUANT_TBL *qtblptr1) -{ - JDIMENSION blk_x, blk_y; - int offset_y, k; - JQUANT_TBL *qtblptr; - JBLOCKARRAY buffer; - JBLOCKROW block; - JCOEFPTR ptr; - JCOEF temp, qval; - - qtblptr = compptr->quant_table; - for (blk_y = 0; blk_y < compptr->height_in_blocks; - blk_y += compptr->v_samp_factor) { - buffer = (*cinfo->mem->access_virt_barray) - ((j_common_ptr) cinfo, coef_array, blk_y, - (JDIMENSION) compptr->v_samp_factor, TRUE); - for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { - block = buffer[offset_y]; - for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) { - ptr = block[blk_x]; - for (k = 0; k < DCTSIZE2; k++) { - temp = qtblptr->quantval[k]; - qval = qtblptr1->quantval[k]; - if (temp != qval) { - temp *= ptr[k]; - /* The following quantization code is a copy from jcdctmgr.c */ -#ifdef FAST_DIVIDE -#define DIVIDE_BY(a,b) a /= b -#else -#define DIVIDE_BY(a,b) if (a >= b) a /= b; else a = 0 -#endif - if (temp < 0) { - temp = -temp; - temp += qval>>1; /* for rounding */ - DIVIDE_BY(temp, qval); - temp = -temp; - } else { - temp += qval>>1; /* for rounding */ - DIVIDE_BY(temp, qval); - } - ptr[k] = temp; - } - } - } - } - } -} - - -/* Calculate largest common denominator with Euklid's algorithm. - */ -LOCAL(JCOEF) -largest_common_denominator(JCOEF a, JCOEF b) -{ - JCOEF c; - - do { - c = a % b; - a = b; - b = c; - } while (c); - - return a; -} - - -LOCAL(void) -adjust_quant(j_decompress_ptr srcinfo, jvirt_barray_ptr *src_coef_arrays, - j_decompress_ptr dropinfo, jvirt_barray_ptr *drop_coef_arrays, - boolean trim, j_compress_ptr dstinfo) -{ - jpeg_component_info *compptr1, *compptr2; - JQUANT_TBL *qtblptr1, *qtblptr2, *qtblptr3; - int ci, k; - - for (ci = 0; ci < dstinfo->num_components && - ci < dropinfo->num_components; ci++) { - compptr1 = srcinfo->comp_info + ci; - compptr2 = dropinfo->comp_info + ci; - qtblptr1 = compptr1->quant_table; - qtblptr2 = compptr2->quant_table; - for (k = 0; k < DCTSIZE2; k++) { - if (qtblptr1->quantval[k] != qtblptr2->quantval[k]) { - if (trim) - requant_comp(dropinfo, compptr2, drop_coef_arrays[ci], qtblptr1); - else { - qtblptr3 = dstinfo->quant_tbl_ptrs[compptr1->quant_tbl_no]; - for (k = 0; k < DCTSIZE2; k++) - if (qtblptr1->quantval[k] != qtblptr2->quantval[k]) - qtblptr3->quantval[k] = largest_common_denominator - (qtblptr1->quantval[k], qtblptr2->quantval[k]); - dequant_comp(srcinfo, compptr1, src_coef_arrays[ci], qtblptr3); - dequant_comp(dropinfo, compptr2, drop_coef_arrays[ci], qtblptr3); - } - break; - } - } - } -} - - -LOCAL(void) -do_drop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, - JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, - jvirt_barray_ptr *src_coef_arrays, - j_decompress_ptr dropinfo, jvirt_barray_ptr *drop_coef_arrays, - JDIMENSION drop_width, JDIMENSION drop_height) -/* Drop. If the dropinfo component number is smaller than the destination's, - * we fill in the remaining components with zero. This provides the feature - * of dropping grayscale into (arbitrarily sampled) color images. - */ -{ - JDIMENSION comp_width, comp_height; - JDIMENSION blk_y, x_drop_blocks, y_drop_blocks; - int ci, offset_y; - JBLOCKARRAY src_buffer, dst_buffer; - jpeg_component_info *compptr; - - for (ci = 0; ci < dstinfo->num_components; ci++) { - compptr = dstinfo->comp_info + ci; - comp_width = drop_width * compptr->h_samp_factor; - comp_height = drop_height * compptr->v_samp_factor; - x_drop_blocks = x_crop_offset * compptr->h_samp_factor; - y_drop_blocks = y_crop_offset * compptr->v_samp_factor; - for (blk_y = 0; blk_y < comp_height; blk_y += compptr->v_samp_factor) { - dst_buffer = (*srcinfo->mem->access_virt_barray) - ((j_common_ptr) srcinfo, src_coef_arrays[ci], blk_y + y_drop_blocks, - (JDIMENSION) compptr->v_samp_factor, TRUE); - if (ci < dropinfo->num_components) { - src_buffer = (*srcinfo->mem->access_virt_barray) - ((j_common_ptr) srcinfo, drop_coef_arrays[ci], blk_y, - (JDIMENSION) compptr->v_samp_factor, FALSE); - for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { - jcopy_block_row(src_buffer[offset_y], - dst_buffer[offset_y] + x_drop_blocks, - comp_width); - } - } else { - for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { - jzero_far(dst_buffer[offset_y] + x_drop_blocks, - comp_width * SIZEOF(JBLOCK)); - } - } - } - } -} - - LOCAL(void) do_crop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, JDIMENSION x_crop_offset, JDIMENSION y_crop_offset, jvirt_barray_ptr *src_coef_arrays, jvirt_barray_ptr *dst_coef_arrays) -/* Crop. This is only used when no rotate/flip is requested with the crop. - * Extension: If the destination size is larger than the source, we fill in - * the extra area with zero (neutral gray). Note we also have to zero partial - * iMCUs at the right and bottom edge of the source image area in this case. - */ +/* Crop. This is only used when no rotate/flip is requested with the crop. */ { - JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height; JDIMENSION dst_blk_y, x_crop_blocks, y_crop_blocks; int ci, offset_y; JBLOCKARRAY src_buffer, dst_buffer; jpeg_component_info *compptr; - MCU_cols = srcinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE); - MCU_rows = srcinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE); - + /* We simply have to copy the right amount of data (the destination's + * image size) starting at the given X and Y offsets in the source. + */ for (ci = 0; ci < dstinfo->num_components; ci++) { compptr = dstinfo->comp_info + ci; - comp_width = MCU_cols * compptr->h_samp_factor; - comp_height = MCU_rows * compptr->v_samp_factor; x_crop_blocks = x_crop_offset * compptr->h_samp_factor; y_crop_blocks = y_crop_offset * compptr->v_samp_factor; for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks; @@ -369,45 +99,14 @@ do_crop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, dst_buffer = (*srcinfo->mem->access_virt_barray) ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y, (JDIMENSION) compptr->v_samp_factor, TRUE); - if (dstinfo->image_height > srcinfo->image_height) { - if (dst_blk_y < y_crop_blocks || - dst_blk_y >= comp_height + y_crop_blocks) { - for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { - jzero_far(dst_buffer[offset_y], - compptr->width_in_blocks * SIZEOF(JBLOCK)); - } - continue; - } - src_buffer = (*srcinfo->mem->access_virt_barray) - ((j_common_ptr) srcinfo, src_coef_arrays[ci], - dst_blk_y - y_crop_blocks, - (JDIMENSION) compptr->v_samp_factor, FALSE); - } else { - src_buffer = (*srcinfo->mem->access_virt_barray) - ((j_common_ptr) srcinfo, src_coef_arrays[ci], - dst_blk_y + y_crop_blocks, - (JDIMENSION) compptr->v_samp_factor, FALSE); - } + src_buffer = (*srcinfo->mem->access_virt_barray) + ((j_common_ptr) srcinfo, src_coef_arrays[ci], + dst_blk_y + y_crop_blocks, + (JDIMENSION) compptr->v_samp_factor, FALSE); for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) { - if (dstinfo->image_width > srcinfo->image_width) { - if (x_crop_blocks > 0) { - jzero_far(dst_buffer[offset_y], - x_crop_blocks * SIZEOF(JBLOCK)); - } - jcopy_block_row(src_buffer[offset_y], - dst_buffer[offset_y] + x_crop_blocks, - comp_width); - if (compptr->width_in_blocks > comp_width + x_crop_blocks) { - jzero_far(dst_buffer[offset_y] + - comp_width + x_crop_blocks, - (compptr->width_in_blocks - - comp_width - x_crop_blocks) * SIZEOF(JBLOCK)); - } - } else { - jcopy_block_row(src_buffer[offset_y] + x_crop_blocks, - dst_buffer[offset_y], - compptr->width_in_blocks); - } + jcopy_block_row(src_buffer[offset_y] + x_crop_blocks, + dst_buffer[offset_y], + compptr->width_in_blocks); } } } @@ -434,7 +133,8 @@ do_flip_h_no_crop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, * mirroring by changing the signs of odd-numbered columns. * Partial iMCUs at the right edge are left untouched. */ - MCU_cols = srcinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE); + MCU_cols = srcinfo->output_width / + (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); for (ci = 0; ci < dstinfo->num_components; ci++) { compptr = dstinfo->comp_info + ci; @@ -499,7 +199,8 @@ do_flip_h (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, * different rows of a single virtual array simultaneously. Otherwise, * this is essentially the same as the routine above. */ - MCU_cols = srcinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE); + MCU_cols = srcinfo->output_width / + (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); for (ci = 0; ci < dstinfo->num_components; ci++) { compptr = dstinfo->comp_info + ci; @@ -563,7 +264,8 @@ do_flip_v (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, * of odd-numbered rows. * Partial iMCUs at the bottom edge are copied verbatim. */ - MCU_rows = srcinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE); + MCU_rows = srcinfo->output_height / + (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); for (ci = 0; ci < dstinfo->num_components; ci++) { compptr = dstinfo->comp_info + ci; @@ -690,7 +392,8 @@ do_rot_90 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, * at the (output) right edge properly. They just get transposed and * not mirrored. */ - MCU_cols = srcinfo->image_height / (dstinfo->max_h_samp_factor * DCTSIZE); + MCU_cols = srcinfo->output_height / + (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); for (ci = 0; ci < dstinfo->num_components; ci++) { compptr = dstinfo->comp_info + ci; @@ -770,7 +473,8 @@ do_rot_270 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, * at the (output) bottom edge properly. They just get transposed and * not mirrored. */ - MCU_rows = srcinfo->image_width / (dstinfo->max_v_samp_factor * DCTSIZE); + MCU_rows = srcinfo->output_width / + (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); for (ci = 0; ci < dstinfo->num_components; ci++) { compptr = dstinfo->comp_info + ci; @@ -837,8 +541,10 @@ do_rot_180 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, JCOEFPTR src_ptr, dst_ptr; jpeg_component_info *compptr; - MCU_cols = srcinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE); - MCU_rows = srcinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE); + MCU_cols = srcinfo->output_width / + (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); + MCU_rows = srcinfo->output_height / + (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); for (ci = 0; ci < dstinfo->num_components; ci++) { compptr = dstinfo->comp_info + ci; @@ -946,8 +652,10 @@ do_transverse (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, JCOEFPTR src_ptr, dst_ptr; jpeg_component_info *compptr; - MCU_cols = srcinfo->image_height / (dstinfo->max_h_samp_factor * DCTSIZE); - MCU_rows = srcinfo->image_width / (dstinfo->max_v_samp_factor * DCTSIZE); + MCU_cols = srcinfo->output_height / + (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); + MCU_rows = srcinfo->output_width / + (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); for (ci = 0; ci < dstinfo->num_components; ci++) { compptr = dstinfo->comp_info + ci; @@ -1123,10 +831,10 @@ trim_right_edge (jpeg_transform_info *info, JDIMENSION full_width) { JDIMENSION MCU_cols; - MCU_cols = info->output_width / (info->max_h_samp_factor * DCTSIZE); + MCU_cols = info->output_width / info->iMCU_sample_width; if (MCU_cols > 0 && info->x_crop_offset + MCU_cols == - full_width / (info->max_h_samp_factor * DCTSIZE)) - info->output_width = MCU_cols * (info->max_h_samp_factor * DCTSIZE); + full_width / info->iMCU_sample_width) + info->output_width = MCU_cols * info->iMCU_sample_width; } LOCAL(void) @@ -1134,10 +842,10 @@ trim_bottom_edge (jpeg_transform_info *info, JDIMENSION full_height) { JDIMENSION MCU_rows; - MCU_rows = info->output_height / (info->max_v_samp_factor * DCTSIZE); + MCU_rows = info->output_height / info->iMCU_sample_height; if (MCU_rows > 0 && info->y_crop_offset + MCU_rows == - full_height / (info->max_v_samp_factor * DCTSIZE)) - info->output_height = MCU_rows * (info->max_v_samp_factor * DCTSIZE); + full_height / info->iMCU_sample_height) + info->output_height = MCU_rows * info->iMCU_sample_height; } @@ -1153,59 +861,89 @@ trim_bottom_edge (jpeg_transform_info *info, JDIMENSION full_height) * Hence, this routine must be called after jpeg_read_header (which reads * the image dimensions) and before jpeg_read_coefficients (which realizes * the source's virtual arrays). + * + * This function returns FALSE right away if -perfect is given + * and transformation is not perfect. Otherwise returns TRUE. */ -GLOBAL(void) +GLOBAL(boolean) jtransform_request_workspace (j_decompress_ptr srcinfo, jpeg_transform_info *info) { - jvirt_barray_ptr *coef_arrays = NULL; + jvirt_barray_ptr *coef_arrays; boolean need_workspace, transpose_it; jpeg_component_info *compptr; - JDIMENSION xoffset, yoffset, dtemp, width_in_iMCUs, height_in_iMCUs; + JDIMENSION xoffset, yoffset; + JDIMENSION width_in_iMCUs, height_in_iMCUs; JDIMENSION width_in_blocks, height_in_blocks; - int itemp, ci, h_samp_factor, v_samp_factor; + int ci, h_samp_factor, v_samp_factor; /* Determine number of components in output image */ if (info->force_grayscale && srcinfo->jpeg_color_space == JCS_YCbCr && - srcinfo->num_components == 3) { + srcinfo->num_components == 3) /* We'll only process the first component */ info->num_components = 1; - } else { + else /* Process all the components */ info->num_components = srcinfo->num_components; + + /* Compute output image dimensions and related values. */ + jpeg_core_output_dimensions(srcinfo); + + /* Return right away if -perfect is given and transformation is not perfect. + */ + if (info->perfect) { + if (info->num_components == 1) { + if (!jtransform_perfect_transform(srcinfo->output_width, + srcinfo->output_height, + srcinfo->min_DCT_h_scaled_size, + srcinfo->min_DCT_v_scaled_size, + info->transform)) + return FALSE; + } else { + if (!jtransform_perfect_transform(srcinfo->output_width, + srcinfo->output_height, + srcinfo->max_h_samp_factor * srcinfo->min_DCT_h_scaled_size, + srcinfo->max_v_samp_factor * srcinfo->min_DCT_v_scaled_size, + info->transform)) + return FALSE; + } } + /* If there is only one output component, force the iMCU size to be 1; * else use the source iMCU size. (This allows us to do the right thing * when reducing color to grayscale, and also provides a handy way of * cleaning up "funny" grayscale images whose sampling factors are not 1x1.) */ - switch (info->transform) { case JXFORM_TRANSPOSE: case JXFORM_TRANSVERSE: case JXFORM_ROT_90: case JXFORM_ROT_270: - info->output_width = srcinfo->image_height; - info->output_height = srcinfo->image_width; + info->output_width = srcinfo->output_height; + info->output_height = srcinfo->output_width; if (info->num_components == 1) { - info->max_h_samp_factor = 1; - info->max_v_samp_factor = 1; + info->iMCU_sample_width = srcinfo->min_DCT_v_scaled_size; + info->iMCU_sample_height = srcinfo->min_DCT_h_scaled_size; } else { - info->max_h_samp_factor = srcinfo->max_v_samp_factor; - info->max_v_samp_factor = srcinfo->max_h_samp_factor; + info->iMCU_sample_width = + srcinfo->max_v_samp_factor * srcinfo->min_DCT_v_scaled_size; + info->iMCU_sample_height = + srcinfo->max_h_samp_factor * srcinfo->min_DCT_h_scaled_size; } break; default: - info->output_width = srcinfo->image_width; - info->output_height = srcinfo->image_height; + info->output_width = srcinfo->output_width; + info->output_height = srcinfo->output_height; if (info->num_components == 1) { - info->max_h_samp_factor = 1; - info->max_v_samp_factor = 1; + info->iMCU_sample_width = srcinfo->min_DCT_h_scaled_size; + info->iMCU_sample_height = srcinfo->min_DCT_v_scaled_size; } else { - info->max_h_samp_factor = srcinfo->max_h_samp_factor; - info->max_v_samp_factor = srcinfo->max_v_samp_factor; + info->iMCU_sample_width = + srcinfo->max_h_samp_factor * srcinfo->min_DCT_h_scaled_size; + info->iMCU_sample_height = + srcinfo->max_v_samp_factor * srcinfo->min_DCT_v_scaled_size; } break; } @@ -1219,115 +957,36 @@ jtransform_request_workspace (j_decompress_ptr srcinfo, info->crop_xoffset = 0; /* default to +0 */ if (info->crop_yoffset_set == JCROP_UNSET) info->crop_yoffset = 0; /* default to +0 */ - if (info->crop_width_set == JCROP_UNSET) { - if (info->crop_xoffset >= info->output_width) - ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); + if (info->crop_xoffset >= info->output_width || + info->crop_yoffset >= info->output_height) + ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); + if (info->crop_width_set == JCROP_UNSET) info->crop_width = info->output_width - info->crop_xoffset; - } else { - /* Check for crop extension */ - if (info->crop_width > info->output_width) { - /* Crop extension does not work when transforming! */ - if (info->transform != JXFORM_NONE || - info->crop_xoffset >= info->crop_width || - info->crop_xoffset > info->crop_width - info->output_width) - ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); - } else { - if (info->crop_xoffset >= info->output_width || - info->crop_width <= 0 || - info->crop_xoffset > info->output_width - info->crop_width) - ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); - } - } - if (info->crop_height_set == JCROP_UNSET) { - if (info->crop_yoffset >= info->output_height) - ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); + if (info->crop_height_set == JCROP_UNSET) info->crop_height = info->output_height - info->crop_yoffset; - } else { - /* Check for crop extension */ - if (info->crop_height > info->output_height) { - /* Crop extension does not work when transforming! */ - if (info->transform != JXFORM_NONE || - info->crop_yoffset >= info->crop_height || - info->crop_yoffset > info->crop_height - info->output_height) - ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); - } else { - if (info->crop_yoffset >= info->output_height || - info->crop_height <= 0 || - info->crop_yoffset > info->output_height - info->crop_height) - ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); - } - } + /* Ensure parameters are valid */ + if (info->crop_width <= 0 || info->crop_width > info->output_width || + info->crop_height <= 0 || info->crop_height > info->output_height || + info->crop_xoffset > info->output_width - info->crop_width || + info->crop_yoffset > info->output_height - info->crop_height) + ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); /* Convert negative crop offsets into regular offsets */ - if (info->crop_xoffset_set == JCROP_NEG) { - if (info->crop_width > info->output_width) - xoffset = info->crop_width - info->output_width - info->crop_xoffset; - else - xoffset = info->output_width - info->crop_width - info->crop_xoffset; - } else + if (info->crop_xoffset_set == JCROP_NEG) + xoffset = info->output_width - info->crop_width - info->crop_xoffset; + else xoffset = info->crop_xoffset; - if (info->crop_yoffset_set == JCROP_NEG) { - if (info->crop_height > info->output_height) - yoffset = info->crop_height - info->output_height - info->crop_yoffset; - else - yoffset = info->output_height - info->crop_height - info->crop_yoffset; - } else + if (info->crop_yoffset_set == JCROP_NEG) + yoffset = info->output_height - info->crop_height - info->crop_yoffset; + else yoffset = info->crop_yoffset; /* Now adjust so that upper left corner falls at an iMCU boundary */ - if (info->transform == JXFORM_DROP) { - /* Ensure the effective drop region will not exceed the requested */ - itemp = info->max_h_samp_factor * DCTSIZE; - dtemp = itemp - 1 - ((xoffset + itemp - 1) % itemp); - xoffset += dtemp; - if (info->crop_width > dtemp) - info->drop_width = (info->crop_width - dtemp) / itemp; - else - info->drop_width = 0; - itemp = info->max_v_samp_factor * DCTSIZE; - dtemp = itemp - 1 - ((yoffset + itemp - 1) % itemp); - yoffset += dtemp; - if (info->crop_height > dtemp) - info->drop_height = (info->crop_height - dtemp) / itemp; - else - info->drop_height = 0; - /* Check if sampling factors match for dropping */ - if (info->drop_width != 0 && info->drop_height != 0) - for (ci = 0; ci < info->num_components && - ci < info->drop_ptr->num_components; ci++) { - if (info->drop_ptr->comp_info[ci].h_samp_factor * - srcinfo->max_h_samp_factor != - srcinfo->comp_info[ci].h_samp_factor * - info->drop_ptr->max_h_samp_factor) - ERREXIT6(srcinfo, JERR_BAD_DROP_SAMPLING, ci, - info->drop_ptr->comp_info[ci].h_samp_factor, - info->drop_ptr->max_h_samp_factor, - srcinfo->comp_info[ci].h_samp_factor, - srcinfo->max_h_samp_factor, 'h'); - if (info->drop_ptr->comp_info[ci].v_samp_factor * - srcinfo->max_v_samp_factor != - srcinfo->comp_info[ci].v_samp_factor * - info->drop_ptr->max_v_samp_factor) - ERREXIT6(srcinfo, JERR_BAD_DROP_SAMPLING, ci, - info->drop_ptr->comp_info[ci].v_samp_factor, - info->drop_ptr->max_v_samp_factor, - srcinfo->comp_info[ci].v_samp_factor, - srcinfo->max_v_samp_factor, 'v'); - } - } else { - /* Ensure the effective crop region will cover the requested */ - if (info->crop_width > info->output_width) - info->output_width = info->crop_width; - else - info->output_width = - info->crop_width + (xoffset % (info->max_h_samp_factor * DCTSIZE)); - if (info->crop_height > info->output_height) - info->output_height = info->crop_height; - else - info->output_height = - info->crop_height + (yoffset % (info->max_v_samp_factor * DCTSIZE)); - } + info->output_width = + info->crop_width + (xoffset % info->iMCU_sample_width); + info->output_height = + info->crop_height + (yoffset % info->iMCU_sample_height); /* Save x/y offsets measured in iMCUs */ - info->x_crop_offset = xoffset / (info->max_h_samp_factor * DCTSIZE); - info->y_crop_offset = yoffset / (info->max_v_samp_factor * DCTSIZE); + info->x_crop_offset = xoffset / info->iMCU_sample_width; + info->y_crop_offset = yoffset / info->iMCU_sample_height; } else { info->x_crop_offset = 0; info->y_crop_offset = 0; @@ -1340,22 +999,20 @@ jtransform_request_workspace (j_decompress_ptr srcinfo, transpose_it = FALSE; switch (info->transform) { case JXFORM_NONE: - if (info->x_crop_offset != 0 || info->y_crop_offset != 0 || - info->output_width > srcinfo->image_width || - info->output_height > srcinfo->image_height) + if (info->x_crop_offset != 0 || info->y_crop_offset != 0) need_workspace = TRUE; /* No workspace needed if neither cropping nor transforming */ break; case JXFORM_FLIP_H: if (info->trim) - trim_right_edge(info, srcinfo->image_width); + trim_right_edge(info, srcinfo->output_width); if (info->y_crop_offset != 0) need_workspace = TRUE; /* do_flip_h_no_crop doesn't need a workspace array */ break; case JXFORM_FLIP_V: if (info->trim) - trim_bottom_edge(info, srcinfo->image_height); + trim_bottom_edge(info, srcinfo->output_height); /* Need workspace arrays having same dimensions as source image. */ need_workspace = TRUE; break; @@ -1367,8 +1024,8 @@ jtransform_request_workspace (j_decompress_ptr srcinfo, break; case JXFORM_TRANSVERSE: if (info->trim) { - trim_right_edge(info, srcinfo->image_height); - trim_bottom_edge(info, srcinfo->image_width); + trim_right_edge(info, srcinfo->output_height); + trim_bottom_edge(info, srcinfo->output_width); } /* Need workspace arrays having transposed dimensions. */ need_workspace = TRUE; @@ -1376,31 +1033,26 @@ jtransform_request_workspace (j_decompress_ptr srcinfo, break; case JXFORM_ROT_90: if (info->trim) - trim_right_edge(info, srcinfo->image_height); + trim_right_edge(info, srcinfo->output_height); /* Need workspace arrays having transposed dimensions. */ need_workspace = TRUE; transpose_it = TRUE; break; case JXFORM_ROT_180: if (info->trim) { - trim_right_edge(info, srcinfo->image_width); - trim_bottom_edge(info, srcinfo->image_height); + trim_right_edge(info, srcinfo->output_width); + trim_bottom_edge(info, srcinfo->output_height); } /* Need workspace arrays having same dimensions as source image. */ need_workspace = TRUE; break; case JXFORM_ROT_270: if (info->trim) - trim_bottom_edge(info, srcinfo->image_width); + trim_bottom_edge(info, srcinfo->output_width); /* Need workspace arrays having transposed dimensions. */ need_workspace = TRUE; transpose_it = TRUE; break; - case JXFORM_DROP: -#if DROP_REQUEST_FROM_SRC - drop_request_from_src(info->drop_ptr, srcinfo); -#endif - break; } /* Allocate workspace if needed. @@ -1413,10 +1065,10 @@ jtransform_request_workspace (j_decompress_ptr srcinfo, SIZEOF(jvirt_barray_ptr) * info->num_components); width_in_iMCUs = (JDIMENSION) jdiv_round_up((long) info->output_width, - (long) (info->max_h_samp_factor * DCTSIZE)); + (long) info->iMCU_sample_width); height_in_iMCUs = (JDIMENSION) jdiv_round_up((long) info->output_height, - (long) (info->max_v_samp_factor * DCTSIZE)); + (long) info->iMCU_sample_height); for (ci = 0; ci < info->num_components; ci++) { compptr = srcinfo->comp_info + ci; if (info->num_components == 1) { @@ -1435,9 +1087,11 @@ jtransform_request_workspace (j_decompress_ptr srcinfo, ((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE, width_in_blocks, height_in_blocks, (JDIMENSION) v_samp_factor); } - } + info->workspace_coef_arrays = coef_arrays; + } else + info->workspace_coef_arrays = NULL; - info->workspace_coef_arrays = coef_arrays; + return TRUE; } @@ -1449,8 +1103,17 @@ transpose_critical_parameters (j_compress_ptr dstinfo) int tblno, i, j, ci, itemp; jpeg_component_info *compptr; JQUANT_TBL *qtblptr; + JDIMENSION jtemp; UINT16 qtemp; + /* Transpose image dimensions */ + jtemp = dstinfo->image_width; + dstinfo->image_width = dstinfo->image_height; + dstinfo->image_height = jtemp; + itemp = dstinfo->min_DCT_h_scaled_size; + dstinfo->min_DCT_h_scaled_size = dstinfo->min_DCT_v_scaled_size; + dstinfo->min_DCT_v_scaled_size = itemp; + /* Transpose sampling factors */ for (ci = 0; ci < dstinfo->num_components; ci++) { compptr = dstinfo->comp_info + ci; @@ -1682,11 +1345,13 @@ jtransform_adjust_parameters (j_decompress_ptr srcinfo, dstinfo->comp_info[0].v_samp_factor = 1; } - /* Correct the destination's image dimensions etc as necessary - * for crop and rotate/flip operations. + /* Correct the destination's image dimensions as necessary + * for rotate/flip, resize, and crop operations. */ - dstinfo->image_width = info->output_width; - dstinfo->image_height = info->output_height; + dstinfo->jpeg_width = info->output_width; + dstinfo->jpeg_height = info->output_height; + + /* Transpose destination image parameters */ switch (info->transform) { case JXFORM_TRANSPOSE: case JXFORM_TRANSVERSE: @@ -1694,11 +1359,7 @@ jtransform_adjust_parameters (j_decompress_ptr srcinfo, case JXFORM_ROT_270: transpose_critical_parameters(dstinfo); break; - case JXFORM_DROP: - if (info->drop_width != 0 && info->drop_height != 0) - adjust_quant(srcinfo, src_coef_arrays, - info->drop_ptr, info->drop_coef_arrays, - info->trim, dstinfo); + default: break; } @@ -1715,12 +1376,12 @@ jtransform_adjust_parameters (j_decompress_ptr srcinfo, /* Suppress output of JFIF marker */ dstinfo->write_JFIF_header = FALSE; /* Adjust Exif image parameters */ - if (dstinfo->image_width != srcinfo->image_width || - dstinfo->image_height != srcinfo->image_height) + if (dstinfo->jpeg_width != srcinfo->image_width || + dstinfo->jpeg_height != srcinfo->image_height) /* Align data segment to start of TIFF structure for parsing */ adjust_exif_parameters(srcinfo->marker_list->data + 6, srcinfo->marker_list->data_length - 6, - dstinfo->image_width, dstinfo->image_height); + dstinfo->jpeg_width, dstinfo->jpeg_height); } /* Return the appropriate output data set */ @@ -1752,9 +1413,7 @@ jtransform_execute_transform (j_decompress_ptr srcinfo, */ switch (info->transform) { case JXFORM_NONE: - if (info->x_crop_offset != 0 || info->y_crop_offset != 0 || - info->output_width > srcinfo->image_width || - info->output_height > srcinfo->image_height) + if (info->x_crop_offset != 0 || info->y_crop_offset != 0) do_crop(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, src_coef_arrays, dst_coef_arrays); break; @@ -1790,12 +1449,6 @@ jtransform_execute_transform (j_decompress_ptr srcinfo, do_rot_270(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, src_coef_arrays, dst_coef_arrays); break; - case JXFORM_DROP: - if (info->drop_width != 0 && info->drop_height != 0) - do_drop(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset, - src_coef_arrays, info->drop_ptr, info->drop_coef_arrays, - info->drop_width, info->drop_height); - break; } } @@ -1812,8 +1465,8 @@ jtransform_execute_transform (j_decompress_ptr srcinfo, * (after reading source header): * image_width = cinfo.image_width * image_height = cinfo.image_height - * MCU_width = cinfo.max_h_samp_factor * DCTSIZE - * MCU_height = cinfo.max_v_samp_factor * DCTSIZE + * MCU_width = cinfo.max_h_samp_factor * cinfo.block_size + * MCU_height = cinfo.max_v_samp_factor * cinfo.block_size * Result: * TRUE = perfect transformation possible * FALSE = perfect transformation not possible @@ -1845,6 +1498,8 @@ jtransform_perfect_transform(JDIMENSION image_width, JDIMENSION image_height, if (image_height % (JDIMENSION) MCU_height) result = FALSE; break; + default: + break; } return result; diff --git a/reactos/dll/3rdparty/libjpeg/transupp.h b/reactos/dll/3rdparty/libjpeg/transupp.h index 00b6a8412d2..7c16c19c440 100644 --- a/reactos/dll/3rdparty/libjpeg/transupp.h +++ b/reactos/dll/3rdparty/libjpeg/transupp.h @@ -1,7 +1,7 @@ /* * transupp.h * - * Copyright (C) 1997-2001, Thomas G. Lane. + * Copyright (C) 1997-2009, Thomas G. Lane, Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -58,9 +58,14 @@ * dimensions to keep the lower right crop corner unchanged. (Thus, the * output image covers at least the requested region, but may cover more.) * - * If both crop and a rotate/flip transform are requested, the crop is applied - * last --- that is, the crop region is specified in terms of the destination - * image. + * We also provide a lossless-resize option, which is kind of a lossless-crop + * operation in the DCT coefficient block domain - it discards higher-order + * coefficients and losslessly preserves lower-order coefficients of a + * sub-block. + * + * Rotate/flip transform, resize, and crop can be requested together in a + * single invocation. The crop is applied last --- that is, the crop region + * is specified in terms of the destination image after transform/resize. * * We also offer a "force to grayscale" option, which simply discards the * chrominance channels of a YCbCr image. This is lossless in the sense that @@ -96,8 +101,7 @@ typedef enum { JXFORM_TRANSVERSE, /* transpose across UR-to-LL axis */ JXFORM_ROT_90, /* 90-degree clockwise rotation */ JXFORM_ROT_180, /* 180-degree rotation */ - JXFORM_ROT_270, /* 270-degree clockwise (or 90 ccw) */ - JXFORM_DROP /* drop */ + JXFORM_ROT_270 /* 270-degree clockwise (or 90 ccw) */ } JXFORM_CODE; /* @@ -137,10 +141,6 @@ typedef struct { JDIMENSION crop_yoffset; /* Y offset of selected region */ JCROP_CODE crop_yoffset_set; /* (negative measures from bottom edge) */ - /* Drop parameters: set by caller for drop request */ - j_decompress_ptr drop_ptr; - jvirt_barray_ptr * drop_coef_arrays; - /* Internal workspace: caller should not touch these */ int num_components; /* # of components in workspace */ jvirt_barray_ptr * workspace_coef_arrays; /* workspace for transformations */ @@ -148,45 +148,43 @@ typedef struct { JDIMENSION output_height; JDIMENSION x_crop_offset; /* destination crop offsets measured in iMCUs */ JDIMENSION y_crop_offset; - JDIMENSION drop_width; /* drop dimensions measured in iMCUs */ - JDIMENSION drop_height; - int max_h_samp_factor; /* destination iMCU size */ - int max_v_samp_factor; + int iMCU_sample_width; /* destination iMCU size */ + int iMCU_sample_height; } jpeg_transform_info; #if TRANSFORMS_SUPPORTED /* Parse a crop specification (written in X11 geometry style) */ -EXTERN_1(boolean) jtransform_parse_crop_spec +EXTERN(boolean) jtransform_parse_crop_spec JPP((jpeg_transform_info *info, const char *spec)); /* Request any required workspace */ -EXTERN_1(void) jtransform_request_workspace +EXTERN(boolean) jtransform_request_workspace JPP((j_decompress_ptr srcinfo, jpeg_transform_info *info)); /* Adjust output image parameters */ -EXTERN_1(jvirt_barray_ptr *) jtransform_adjust_parameters +EXTERN(jvirt_barray_ptr *) jtransform_adjust_parameters JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo, jvirt_barray_ptr *src_coef_arrays, jpeg_transform_info *info)); /* Execute the actual transformation, if any */ -EXTERN_1(void) jtransform_execute_transform +EXTERN(void) jtransform_execute_transform JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo, jvirt_barray_ptr *src_coef_arrays, jpeg_transform_info *info)); /* Determine whether lossless transformation is perfectly * possible for a specified image and transformation. */ -EXTERN_1(boolean) jtransform_perfect_transform - JPP((JDIMENSION image_width, JDIMENSION image_height, - int MCU_width, int MCU_height, - JXFORM_CODE transform)); +EXTERN(boolean) jtransform_perfect_transform + JPP((JDIMENSION image_width, JDIMENSION image_height, + int MCU_width, int MCU_height, + JXFORM_CODE transform)); /* jtransform_execute_transform used to be called * jtransform_execute_transformation, but some compilers complain about * routine names that long. This macro is here to avoid breaking any * old source code that uses the original name... */ -#define jtransform_execute_transformation jtransform_execute_transform +#define jtransform_execute_transformation jtransform_execute_transform #endif /* TRANSFORMS_SUPPORTED */ @@ -198,16 +196,15 @@ EXTERN_1(boolean) jtransform_perfect_transform typedef enum { JCOPYOPT_NONE, /* copy no optional markers */ JCOPYOPT_COMMENTS, /* copy only comment (COM) markers */ - JCOPYOPT_ALL, /* copy all optional markers */ - JCOPYOPT_EXIF /* copy Exif APP1 marker */ + JCOPYOPT_ALL /* copy all optional markers */ } JCOPY_OPTION; #define JCOPYOPT_DEFAULT JCOPYOPT_COMMENTS /* recommended default */ /* Setup decompression object to save desired markers in memory */ -EXTERN_1(void) jcopy_markers_setup +EXTERN(void) jcopy_markers_setup JPP((j_decompress_ptr srcinfo, JCOPY_OPTION option)); /* Copy markers saved in the given source object to the destination object */ -EXTERN_1(void) jcopy_markers_execute +EXTERN(void) jcopy_markers_execute JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo, JCOPY_OPTION option)); diff --git a/reactos/dll/3rdparty/libjpeg/wrppm.c b/reactos/dll/3rdparty/libjpeg/wrppm.c index 6c6d908817c..68e0c85c3ca 100644 --- a/reactos/dll/3rdparty/libjpeg/wrppm.c +++ b/reactos/dll/3rdparty/libjpeg/wrppm.c @@ -2,6 +2,7 @@ * wrppm.c * * Copyright (C) 1991-1996, Thomas G. Lane. + * Modified 2009 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -40,11 +41,11 @@ #define BYTESPERSAMPLE 1 #define PPM_MAXVAL 255 #else -/* The word-per-sample format always puts the LSB first. */ +/* The word-per-sample format always puts the MSB first. */ #define PUTPPMSAMPLE(ptr,v) \ { register int val_ = v; \ - *ptr++ = (char) (val_ & 0xFF); \ *ptr++ = (char) ((val_ >> 8) & 0xFF); \ + *ptr++ = (char) (val_ & 0xFF); \ } #define BYTESPERSAMPLE 2 #define PPM_MAXVAL ((1< functions to be + png_set_. We now have corresponding png_get_ + functions in pngget.c to get information in info_ptr. This isolates + the application from the internal organization of png_info_struct + (good for shared library implementations). + +version 0.96 [May, 1997] + fixed serious bug with < 8bpp images introduced in 0.95 + fixed 256-color transparency bug (Greg Roelofs) + fixed up documentation (Greg Roelofs, Laszlo Nyul) + fixed "error" in pngconf.h for Linux setjmp() behaviour + fixed DOS medium model support (Tim Wegner) + fixed png_check_keyword() for case with error in static string text + added read of CRC after IEND chunk for embedded PNGs (Laszlo Nyul) + added typecasts to quiet compiler errors + added more debugging info + +version 0.97 [January, 1998] + removed PNG_USE_OWN_CRC capability + relocated png_set_crc_action from pngrutil.c to pngrtran.c + fixed typecasts of "new_key", etc. (Andreas Dilger) + added RFC 1152 [sic] date support + fixed bug in gamma handling of 4-bit grayscale + added 2-bit grayscale gamma handling (Glenn R-P) + added more typecasts. 65536L becomes (png_uint_32)65536L, etc. (Glenn R-P) + minor corrections in libpng.txt + added simple sRGB support (Glenn R-P) + easier conditional compiling, e.g. define PNG_READ/WRITE_NOT_FULLY_SUPPORTED; + all configurable options can be selected from command-line instead + of having to edit pngconf.h (Glenn R-P) + fixed memory leak in pngwrite.c (free info_ptr->text) (Glenn R-P) + added more conditions for png_do_background, to avoid changing + black pixels to background when a background is supplied and + no pixels are transparent + repaired PNG_NO_STDIO behaviour + tested NODIV support and made it default behaviour (Greg Roelofs) + added "-m" option and PNGTEST_DEBUG_MEMORY to pngtest (John Bowler) + regularized version numbering scheme and bumped shared-library major + version number to 2 to avoid problems with libpng 0.89 apps (Greg Roelofs) + +version 0.98 [January, 1998] + cleaned up some typos in libpng.txt and in code documentation + fixed memory leaks in pCAL chunk processing (Glenn R-P and John Bowler) + cosmetic change "display_gamma" to "screen_gamma" in pngrtran.c + changed recommendation about file_gamma for PC images to .51 from .45, + in example.c and libpng.txt, added comments to distinguish between + screen_gamma, viewing_gamma, and display_gamma. + changed all references to RFC1152 to read RFC1123 and changed the + PNG_TIME_RFC1152_SUPPORTED macro to PNG_TIME_RFC1123_SUPPORTED + added png_invert_alpha capability (Glenn R-P -- suggestion by Jon Vincent) + changed srgb_intent from png_byte to int to avoid compiler bugs + +version 0.99 [January 30, 1998] + free info_ptr->text instead of end_info_ptr->text in pngread.c (John Bowler) + fixed a longstanding "packswap" bug in pngtrans.c + fixed some inconsistencies in pngconf.h that prevented compiling with + PNG_READ_GAMMA_SUPPORTED and PNG_READ_hIST_SUPPORTED undefined + fixed some typos and made other minor rearrangement of libpng.txt (Andreas) + changed recommendation about file_gamma for PC images to .50 from .51 in + example.c and libpng.txt, and changed file_gamma for sRGB images to .45 + added a number of functions to access information from the png structure + png_get_image_height(), etc. (Glenn R-P, suggestion by Brad Pettit) + added TARGET_MACOS similar to zlib-1.0.8 + define PNG_ALWAYS_EXTERN when __MWERKS__ && WIN32 are defined + added type casting to all png_malloc() function calls +version 0.99a [January 31, 1998] + Added type casts and parentheses to all returns that return a value.(Tim W.) +version 0.99b [February 4, 1998] + Added type cast png_uint_32 on malloc function calls where needed. + Changed type of num_hist from png_uint_32 to int (same as num_palette). + Added checks for rowbytes overflow, in case png_size_t is less than 32 bits. + Renamed makefile.elf to makefile.lnx. +version 0.99c [February 7, 1998] + More type casting. Removed erroneous overflow test in pngmem.c. + Added png_buffered_memcpy() and png_buffered_memset(), apply them to rowbytes. + Added UNIX manual pages libpng.3 (incorporating libpng.txt) and png.5. +version 0.99d [February 11, 1998] + Renamed "far_to_near()" "png_far_to_near()" + Revised libpng.3 + Version 99c "buffered" operations didn't work as intended. Replaced them + with png_memcpy_check() and png_memset_check(). + Added many "if (png_ptr == NULL) return" to quell compiler warnings about + unused png_ptr, mostly in pngget.c and pngset.c. + Check for overlength tRNS chunk present when indexed-color PLTE is read. + Cleaned up spelling errors in libpng.3/libpng.txt + Corrected a problem with png_get_tRNS() which returned undefined trans array +version 0.99e [February 28, 1998] + Corrected png_get_tRNS() again. + Add parentheses for easier reading of pngget.c, fixed "||" should be "&&". + Touched up example.c to make more of it compileable, although the entire + file still can't be compiled (Willem van Schaik) + Fixed a bug in png_do_shift() (Bryan Tsai) + Added a space in png.h prototype for png_write_chunk_start() + Replaced pngtest.png with one created with zlib 1.1.1 + Changed pngtest to report PASS even when file size is different (Jean-loup G.) + Corrected some logic errors in png_do_invert_alpha() (Chris Patterson) +version 0.99f [March 5, 1998] + Corrected a bug in pngpread() introduced in version 99c (Kevin Bracey) + Moved makefiles into a "scripts" directory, and added INSTALL instruction file + Added makefile.os2 and pngos2.def (A. Zabolotny) and makefile.s2x (W. Sebok) + Added pointers to "note on libpng versions" in makefile.lnx and README + Added row callback feature when reading and writing nonprogressive rows + and added a test of this feature in pngtest.c + Added user transform callbacks, with test of the feature in pngtest.c +version 0.99g [March 6, 1998, morning] + Minor changes to pngtest.c to suppress compiler warnings. + Removed "beta" language from documentation. +version 0.99h [March 6, 1998, evening] + Minor changes to previous minor changes to pngtest.c + Changed PNG_READ_NOT_FULLY_SUPPORTED to PNG_READ_TRANSFORMS_NOT_SUPPORTED + and added PNG_PROGRESSIVE_READ_NOT_SUPPORTED macro + Added user transform capability + +version 1.00 [March 7, 1998] + Changed several typedefs in pngrutil.c + Added makefile.wat (Pawel Mrochen), updated makefile.tc3 (Willem van Schaik) + replaced "while(1)" with "for(;;)" + added PNGARG() to prototypes in pngtest.c and removed some prototypes + updated some of the makefiles (Tom Lane) + changed some typedefs (s_start, etc.) in pngrutil.c + fixed dimensions of "short_months" array in pngwrite.c + Replaced ansi2knr.c with the one from jpeg-v6 + +version 1.0.0 [March 8, 1998] + Changed name from 1.00 to 1.0.0 (Adam Costello) + Added smakefile.ppc (with SCOPTIONS.ppc) for Amiga PPC (Andreas Kleinert) +version 1.0.0a [March 9, 1998] + Fixed three bugs in pngrtran.c to make gamma+background handling consistent + (Greg Roelofs) + Changed format of the PNG_LIBPNG_VER integer to xyyzz instead of xyz + for major, minor, and bugfix releases. This is 10001. (Adam Costello, + Tom Lane) + Make months range from 1-12 in png_convert_to_rfc1123 +version 1.0.0b [March 13, 1998] + Quieted compiler complaints about two empty "for" loops in pngrutil.c + Minor changes to makefile.s2x + Removed #ifdef/#endif around a png_free() in pngread.c + +version 1.0.1 [March 14, 1998] + Changed makefile.s2x to reduce security risk of using a relative pathname + Fixed some typos in the documentation (Greg). + Fixed a problem with value of "channels" returned by png_read_update_info() +version 1.0.1a [April 21, 1998] + Optimized Paeth calculations by replacing abs() function calls with intrinsics + plus other loop optimizations. Improves avg decoding speed by about 20%. + Commented out i386istic "align" compiler flags in makefile.lnx. + Reduced the default warning level in some makefiles, to make them consistent. + Removed references to IJG and JPEG in the ansi2knr.c copyright statement. + Fixed a bug in png_do_strip_filler with XXRRGGBB => RRGGBB transformation. + Added grayscale and 16-bit capability to png_do_read_filler(). + Fixed a bug in pngset.c, introduced in version 0.99c, that sets rowbytes + too large when writing an image with bit_depth < 8 (Bob Dellaca). + Corrected some bugs in the experimental weighted filtering heuristics. + Moved a misplaced pngrutil code block that truncates tRNS if it has more + than num_palette entries -- test was done before num_palette was defined. + Fixed a png_convert_to_rfc1123() bug that converts day 31 to 0 (Steve Eddins). + Changed compiler flags in makefile.wat for better optimization (Pawel Mrochen). +version 1.0.1b [May 2, 1998] + Relocated png_do_gray_to_rgb() within png_do_read_transformations() (Greg). + Relocated the png_composite macros from pngrtran.c to png.h (Greg). + Added makefile.sco (contributed by Mike Hopkirk). + Fixed two bugs (missing definitions of "istop") introduced in libpng-1.0.1a. + Fixed a bug in pngrtran.c that would set channels=5 under some circumstances. + More work on the Paeth-filtering, achieving imperceptible speedup (A Kleinert). + More work on loop optimization which may help when compiled with C++ compilers. + Added warnings when people try to use transforms they've defined out. + Collapsed 4 "i" and "c" loops into single "i" loops in pngrtran and pngwtran. + Revised paragraph about png_set_expand() in libpng.txt and libpng.3 (Greg) +version 1.0.1c [May 11, 1998] + Fixed a bug in pngrtran.c (introduced in libpng-1.0.1a) where the masks for + filler bytes should have been 0xff instead of 0xf. + Added max_pixel_depth=32 in pngrutil.c when using FILLER with palette images. + Moved PNG_WRITE_WEIGHTED_FILTER_SUPPORTED and PNG_WRITE_FLUSH_SUPPORTED + out of the PNG_WRITE_TRANSFORMS_NOT_SUPPORTED block of pngconf.h + Added "PNG_NO_WRITE_TRANSFORMS" etc., as alternatives for *_NOT_SUPPORTED, + for consistency, in pngconf.h + Added individual "ifndef PNG_NO_[CAPABILITY]" in pngconf.h to make it easier + to remove unwanted capabilities via the compile line + Made some corrections to grammar (which, it's) in documentation (Greg). + Corrected example.c, use of row_pointers in png_write_image(). +version 1.0.1d [May 24, 1998] + Corrected several statements that used side effects illegally in pngrutil.c + and pngtrans.c, that were introduced in version 1.0.1b + Revised png_read_rows() to avoid repeated if-testing for NULL (A Kleinert) + More corrections to example.c, use of row_pointers in png_write_image() + and png_read_rows(). + Added pngdll.mak and pngdef.pas to scripts directory, contributed by + Bob Dellaca, to make a png32bd.dll with Borland C++ 4.5 + Fixed error in example.c with png_set_text: num_text is 3, not 2 (Guido V.) + Changed several loops from count-down to count-up, for consistency. +version 1.0.1e [June 6, 1998] + Revised libpng.txt and libpng.3 description of png_set_read|write_fn(), and + added warnings when people try to set png_read_fn and png_write_fn in + the same structure. + Added a test such that png_do_gamma will be done when num_trans==0 + for truecolor images that have defined a background. This corrects an + error that was introduced in libpng-0.90 that can cause gamma processing + to be skipped. + Added tests in png.h to include "trans" and "trans_values" in structures + when PNG_READ_BACKGROUND_SUPPORTED or PNG_READ_EXPAND_SUPPORTED is defined. + Add png_free(png_ptr->time_buffer) in png_destroy_read_struct() + Moved png_convert_to_rfc_1123() from pngwrite.c to png.c + Added capability for user-provided malloc_fn() and free_fn() functions, + and revised pngtest.c to demonstrate their use, replacing the + PNGTEST_DEBUG_MEM feature. + Added makefile.w32, for Microsoft C++ 4.0 and later (Tim Wegner). + +version 1.0.2 [June 14, 1998] + Fixed two bugs in makefile.bor . +version 1.0.2a [December 30, 1998] + Replaced and extended code that was removed from png_set_filler() in 1.0.1a. + Fixed a bug in png_do_filler() that made it fail to write filler bytes in + the left-most pixel of each row (Kevin Bracey). + Changed "static pngcharp tIME_string" to "static char tIME_string[30]" + in pngtest.c (Duncan Simpson). + Fixed a bug in pngtest.c that caused pngtest to try to write a tIME chunk + even when no tIME chunk was present in the source file. + Fixed a problem in pngrutil.c: gray_to_rgb didn't always work with 16-bit. + Fixed a problem in png_read_push_finish_row(), which would not skip some + passes that it should skip, for images that are less than 3 pixels high. + Interchanged the order of calls to png_do_swap() and png_do_shift() + in pngwtran.c (John Cromer). + Added #ifdef PNG_DEBUG/#endif surrounding use of PNG_DEBUG in png.h . + Changed "bad adaptive filter type" from error to warning in pngrutil.c . + Fixed a documentation error about default filtering with 8-bit indexed-color. + Separated the PNG_NO_STDIO macro into PNG_NO_STDIO and PNG_NO_CONSOLE_IO + (L. Peter Deutsch). + Added png_set_rgb_to_gray() and png_get_rgb_to_gray_status() functions. + Added png_get_copyright() and png_get_header_version() functions. + Revised comments on png_set_progressive_read_fn() in libpng.txt and example.c + Added information about debugging in libpng.txt and libpng.3 . + Changed "ln -sf" to "ln -s -f" in makefile.s2x, makefile.lnx, and makefile.sco. + Removed lines after Dynamic Dependencies" in makefile.aco . + Revised makefile.dec to make a shared library (Jeremie Petit). + Removed trailing blanks from all files. +version 1.0.2a [January 6, 1999] + Removed misplaced #endif and #ifdef PNG_NO_EXTERN near the end of png.h + Added "if" tests to silence complaints about unused png_ptr in png.h and png.c + Changed "check_if_png" function in example.c to return true (nonzero) if PNG. + Changed libpng.txt to demonstrate png_sig_cmp() instead of png_check_sig() + which is obsolete. + +version 1.0.3 [January 14, 1999] + Added makefile.hux, for Hewlett Packard HPUX 10.20 and 11.00 (Jim Rice) + Added a statement of Y2K compliance in png.h, libpng.3, and Y2KINFO. +version 1.0.3a [August 12, 1999] + Added check for PNG_READ_INTERLACE_SUPPORTED in pngread.c; issue a warning + if an attempt is made to read an interlaced image when it's not supported. + Added check if png_ptr->trans is defined before freeing it in pngread.c + Modified the Y2K statement to include versions back to version 0.71 + Fixed a bug in the check for valid IHDR bit_depth/color_types in pngrutil.c + Modified makefile.wat (added -zp8 flag, ".symbolic", changed some comments) + Replaced leading blanks with tab characters in makefile.hux + Changed "dworkin.wustl.edu" to "ccrc.wustl.edu" in various documents. + Changed (float)red and (float)green to (double)red, (double)green + in png_set_rgb_to_gray() to avoid "promotion" problems in AIX. + Fixed a bug in pngconf.h that omitted when PNG_DEBUG==0 (K Bracey). + Reformatted libpng.3 and libpngpf.3 with proper fonts (script by J. vanZandt). + Updated documentation to refer to the PNG-1.2 specification. + Removed ansi2knr.c and left pointers to the latest source for ansi2knr.c + in makefile.knr, INSTALL, and README (L. Peter Deutsch) + Fixed bugs in calculation of the length of rowbytes when adding alpha + channels to 16-bit images, in pngrtran.c (Chris Nokleberg) + Added function png_set_user_transform_info() to store user_transform_ptr, + user_depth, and user_channels into the png_struct, and a function + png_get_user_transform_ptr() to retrieve the pointer (Chris Nokleberg) + Added function png_set_empty_plte_permitted() to make libpng useable + in MNG applications. + Corrected the typedef for png_free_ptr in png.h (Jesse Jones). + Correct gamma with srgb is 45455 instead of 45000 in pngrutil.c, to be + consistent with PNG-1.2, and allow variance of 500 before complaining. + Added assembler code contributed by Intel in file pngvcrd.c and modified + makefile.w32 to use it (Nirav Chhatrapati, INTEL Corporation, Gilles Vollant) + Changed "ln -s -f" to "ln -f -s" in the makefiles to make Solaris happy. + Added some aliases for png_set_expand() in pngrtran.c, namely + png_set_expand_PLTE(), png_set_expand_depth(), and png_set_expand_tRNS() + (Greg Roelofs, in "PNG: The Definitive Guide"). + Added makefile.beo for BEOS on X86, contributed by Sander Stok. +version 1.0.3b [August 26, 1999] + Replaced 2147483647L several places with PNG_MAX_UINT macro, defined in png.h + Changed leading blanks to tabs in all makefiles. + Define PNG_USE_PNGVCRD in makefile.w32, to get MMX assembler code. + Made alternate versions of png_set_expand() in pngrtran.c, namely + png_set_gray_1_2_4_to_8, png_set_palette_to_rgb, and png_set_tRNS_to_alpha + (Greg Roelofs, in "PNG: The Definitive Guide"). Deleted the 1.0.3a aliases. + Relocated start of 'extern "C"' block in png.h so it doesn't include pngconf.h + Revised calculation of num_blocks in pngmem.c to avoid a potentially + negative shift distance, whose results are undefined in the C language. + Added a check in pngset.c to prevent writing multiple tIME chunks. + Added a check in pngwrite.c to detect invalid small window_bits sizes. +version 1.0.3d [September 4, 1999] + Fixed type casting of igamma in pngrutil.c + Added new png_expand functions to scripts/pngdef.pas and pngos2.def + Added a demo read_user_transform_fn that examines the row filters in pngtest.c + +version 1.0.4 [September 24, 1999] + Define PNG_ALWAYS_EXTERN in pngconf.h if __STDC__ is defined + Delete #define PNG_INTERNAL and include "png.h" from pngasmrd.h + Made several minor corrections to pngtest.c + Renamed the makefiles with longer but more user friendly extensions. + Copied the PNG copyright and license to a separate LICENSE file. + Revised documentation, png.h, and example.c to remove reference to + "viewing_gamma" which no longer appears in the PNG specification. + Revised pngvcrd.c to use MMX code for interlacing only on the final pass. + Updated pngvcrd.c to use the faster C filter algorithms from libpng-1.0.1a + Split makefile.win32vc into two versions, makefile.vcawin32 (uses MMX + assembler code) and makefile.vcwin32 (doesn't). + Added a CPU timing report to pngtest.c (enabled by defining PNGTEST_TIMING) + Added a copy of pngnow.png to the distribution. +version 1.0.4a [September 25, 1999] + Increase max_pixel_depth in pngrutil.c if a user transform needs it. + Changed several division operations to right-shifts in pngvcrd.c +version 1.0.4b [September 30, 1999] + Added parentheses in line 3732 of pngvcrd.c + Added a comment in makefile.linux warning about buggy -O3 in pgcc 2.95.1 +version 1.0.4c [October 1, 1999] + Added a "png_check_version" function in png.c and pngtest.c that will generate + a helpful compiler error if an old png.h is found in the search path. + Changed type of png_user_transform_depth|channels from int to png_byte. +version 1.0.4d [October 6, 1999] + Changed 0.45 to 0.45455 in png_set_sRGB() + Removed unused PLTE entries from pngnow.png + Re-enabled some parts of pngvcrd.c (png_combine_row) that work properly. +version 1.0.4e [October 10, 1999] + Fixed sign error in pngvcrd.c (Greg Roelofs) + Replaced some instances of memcpy with simple assignments in pngvcrd (GR-P) +version 1.0.4f [October 15, 1999] + Surrounded example.c code with #if 0 .. #endif to prevent people from + inadvertently trying to compile it. + Changed png_get_header_version() from a function to a macro in png.h + Added type casting mostly in pngrtran.c and pngwtran.c + Removed some pointless "ptr = NULL" in pngmem.c + Added a "contrib" directory containing the source code from Greg's book. + +version 1.0.5 [October 15, 1999] + Minor editing of the INSTALL and README files. +version 1.0.5a [October 23, 1999] + Added contrib/pngsuite and contrib/pngminus (Willem van Schaik) + Fixed a typo in the png_set_sRGB() function call in example.c (Jan Nijtmans) + Further optimization and bugfix of pngvcrd.c + Revised pngset.c so that it does not allocate or free memory in the user's + text_ptr structure. Instead, it makes its own copy. + Created separate write_end_info_struct in pngtest.c for a more severe test. + Added code in pngwrite.c to free info_ptr->text[i].key to stop a memory leak. +version 1.0.5b [November 23, 1999] + Moved PNG_FLAG_HAVE_CHUNK_HEADER, PNG_FLAG_BACKGROUND_IS_GRAY and + PNG_FLAG_WROTE_tIME from flags to mode. + Added png_write_info_before_PLTE() function. + Fixed some typecasting in contrib/gregbook/*.c + Updated scripts/makevms.com and added makevms.com to contrib/gregbook + and contrib/pngminus (Martin Zinser) +version 1.0.5c [November 26, 1999] + Moved png_get_header_version from png.h to png.c, to accommodate ansi2knr. + Removed all global arrays (according to PNG_NO_GLOBAL_ARRAYS macro), to + accommodate making DLL's: Moved usr_png_ver from global variable to function + png_get_header_ver() in png.c. Moved png_sig to png_sig_bytes in png.c and + eliminated use of png_sig in pngwutil.c. Moved the various png_CHNK arrays + into pngtypes.h. Eliminated use of global png_pass arrays. Declared the + png_CHNK and png_pass arrays to be "const". Made the global arrays + available to applications (although none are used in libpng itself) when + PNG_NO_GLOBAL_ARRAYS is not defined or when PNG_GLOBAL_ARRAYS is defined. + Removed some extraneous "-I" from contrib/pngminus/makefile.std + Changed the PNG_sRGB_INTENT macros in png.h to be consistent with PNG-1.2. + Change PNG_SRGB_INTENT to PNG_sRGB_INTENT in libpng.txt and libpng.3 +version 1.0.5d [November 29, 1999] + Add type cast (png_const_charp) two places in png.c + Eliminated pngtypes.h; use macros instead to declare PNG_CHNK arrays. + Renamed "PNG_GLOBAL_ARRAYS" to "PNG_USE_GLOBAL_ARRAYS" and made available + to applications a macro "PNG_USE_LOCAL_ARRAYS". + comment out (with #ifdef) all the new declarations when + PNG_USE_GLOBAL_ARRAYS is defined. + Added PNG_EXPORT_VAR macro to accommodate making DLL's. +version 1.0.5e [November 30, 1999] + Added iCCP, iTXt, and sPLT support; added "lang" member to the png_text + structure; refactored the inflate/deflate support to make adding new chunks + with trailing compressed parts easier in the future, and added new functions + png_free_iCCP, png_free_pCAL, png_free_sPLT, png_free_text, png_get_iCCP, + png_get_spalettes, png_set_iCCP, png_set_spalettes (Eric S. Raymond). + NOTE: Applications that write text chunks MUST define png_text->lang + before calling png_set_text(). It must be set to NULL if you want to + write tEXt or zTXt chunks. If you want your application to be able to + run with older versions of libpng, use + + #ifdef PNG_iTXt_SUPPORTED + png_text[i].lang = NULL; + #endif + + Changed png_get_oFFs() and png_set_oFFs() to use signed rather than unsigned + offsets (Eric S. Raymond). + Combined PNG_READ_cHNK_SUPPORTED and PNG_WRITE_cHNK_SUPPORTED macros into + PNG_cHNK_SUPPORTED and combined the three types of PNG_text_SUPPORTED + macros, leaving the separate macros also available. + Removed comments on #endifs at the end of many short, non-nested #if-blocks. +version 1.0.5f [December 6, 1999] + Changed makefile.solaris to issue a warning about potential problems when + the ucb "ld" is in the path ahead of the ccs "ld". + Removed "- [date]" from the "synopsis" line in libpng.3 and libpngpf.3. + Added sCAL chunk support (Eric S. Raymond). +version 1.0.5g [December 7, 1999] + Fixed "png_free_spallettes" typo in png.h + Added code to handle new chunks in pngpread.c + Moved PNG_CHNK string macro definitions outside of PNG_NO_EXTERN block + Added "translated_key" to png_text structure and png_write_iTXt(). + Added code in pngwrite.c to work around a newly discovered zlib bug. +version 1.0.5h [December 10, 1999] + NOTE: regarding the note for version 1.0.5e, the following must also + be included in your code: + png_text[i].translated_key = NULL; + Unknown chunk handling is now supported. + Option to eliminate all floating point support was added. Some new + fixed-point functions such as png_set_gAMA_fixed() were added. + Expanded tabs and removed trailing blanks in source files. +version 1.0.5i [December 13, 1999] + Added some type casts to silence compiler warnings. + Renamed "png_free_spalette" to "png_free_spalettes" for consistency. + Removed leading blanks from a #define in pngvcrd.c + Added some parameters to the new png_set_keep_unknown_chunks() function. + Added a test for up->location != 0 in the first instance of writing + unknown chunks in pngwrite.c + Changed "num" to "i" in png_free_spalettes() and png_free_unknowns() to + prevent recursion. + Added png_free_hIST() function. + Various patches to fix bugs in the sCAL and integer cHRM processing, + and to add some convenience macros for use with sCAL. +version 1.0.5j [December 21, 1999] + Changed "unit" parameter of png_write_sCAL from png_byte to int, to work + around buggy compilers. + Added new type "png_fixed_point" for integers that hold float*100000 values + Restored backward compatibility of tEXt/zTXt chunk processing: + Restored the first four members of png_text to the same order as v.1.0.5d. + Added members "lang_key" and "itxt_length" to png_text struct. Set + text_length=0 when "text" contains iTXt data. Use the "compression" + member to distinguish among tEXt/zTXt/iTXt types. Added + PNG_ITXT_COMPRESSION_NONE (1) and PNG_ITXT_COMPRESSION_zTXt(2) macros. + The "Note" above, about backward incompatibility of libpng-1.0.5e, no + longer applies. + Fixed png_read|write_iTXt() to read|write parameters in the right order, + and to write the iTXt chunk after IDAT if it appears in the end_ptr. + Added pnggccrd.c, version of pngvcrd.c Intel assembler for gcc (Greg Roelofs) + Reversed the order of trying to write floating-point and fixed-point gAMA. +version 1.0.5k [December 27, 1999] + Added many parentheses, e.g., "if (a && b & c)" becomes "if (a && (b & c))" + Added png_handle_as_unknown() function (Glenn) + Added png_free_chunk_list() function and chunk_list and num_chunk_list members + of png_ptr. + Eliminated erroneous warnings about multiple sPLT chunks and sPLT-after-PLTE. + Fixed a libpng-1.0.5h bug in pngrutil.c that was issuing erroneous warnings + about ignoring incorrect gAMA with sRGB (gAMA was in fact not ignored) + Added png_free_tRNS(); png_set_tRNS() now malloc's its own trans array (ESR). + Define png_get_int_32 when oFFs chunk is supported as well as when pCAL is. + Changed type of proflen from png_int_32 to png_uint_32 in png_get_iCCP(). +version 1.0.5l [January 1, 2000] + Added functions png_set_read_user_chunk_fn() and png_get_user_chunk_ptr() + for setting a callback function to handle unknown chunks and for + retrieving the associated user pointer (Glenn). +version 1.0.5m [January 7, 2000] + Added high-level functions png_read_png(), png_write_png(), png_free_pixels(). +version 1.0.5n [January 9, 2000] + Added png_free_PLTE() function, and modified png_set_PLTE() to malloc its + own memory for info_ptr->palette. This makes it safe for the calling + application to free its copy of the palette any time after it calls + png_set_PLTE(). +version 1.0.5o [January 20, 2000] + Cosmetic changes only (removed some trailing blanks and TABs) +version 1.0.5p [January 31, 2000] + Renamed pngdll.mak to makefile.bd32 + Cosmetic changes in pngtest.c +version 1.0.5q [February 5, 2000] + Relocated the makefile.solaris warning about PATH problems. + Fixed pngvcrd.c bug by pushing/popping registers in mmxsupport (Bruce Oberg) + Revised makefile.gcmmx + Added PNG_SETJMP_SUPPORTED, PNG_SETJMP_NOT_SUPPORTED, and PNG_ABORT() macros +version 1.0.5r [February 7, 2000] + Removed superfluous prototype for png_get_itxt from png.h + Fixed a bug in pngrtran.c that improperly expanded the background color. + Return *num_text=0 from png_get_text() when appropriate, and fix documentation + of png_get_text() in libpng.txt/libpng.3. +version 1.0.5s [February 18, 2000] + Added "png_jmp_env()" macro to pngconf.h, to help people migrate to the + new error handler that's planned for the next libpng release, and changed + example.c, pngtest.c, and contrib programs to use this macro. + Revised some of the DLL-export macros in pngconf.h (Greg Roelofs) + Fixed a bug in png_read_png() that caused it to fail to expand some images + that it should have expanded. + Fixed some mistakes in the unused and undocumented INCH_CONVERSIONS functions + in pngget.c + Changed the allocation of palette, history, and trans arrays back to + the version 1.0.5 method (linking instead of copying) which restores + backward compatibility with version 1.0.5. Added some remarks about + that in example.c. Added "free_me" member to info_ptr and png_ptr + and added png_free_data() function. + Updated makefile.linux and makefile.gccmmx to make directories conditionally. + Made cosmetic changes to pngasmrd.h + Added png_set_rows() and png_get_rows(), for use with png_read|write_png(). + Modified png_read_png() to allocate info_ptr->row_pointers only if it + hasn't already been allocated. +version 1.0.5t [March 4, 2000] + Changed png_jmp_env() migration aiding macro to png_jmpbuf(). + Fixed "interlace" typo (should be "interlaced") in contrib/gregbook/read2-x.c + Fixed bug with use of PNG_BEFORE_IHDR bit in png_ptr->mode, introduced when + PNG_FLAG_HAVE_CHUNK_HEADER was moved into png_ptr->mode in version 1.0.5b + Files in contrib/gregbook were revised to use png_jmpbuf() and to select + a 24-bit visual if one is available, and to allow abbreviated options. + Files in contrib/pngminus were revised to use the png_jmpbuf() macro. + Removed spaces in makefile.linux and makefile.gcmmx, introduced in 1.0.5s +version 1.0.5u [March 5, 2000] + Simplified the code that detects old png.h in png.c and pngtest.c + Renamed png_spalette (_p, _pp) to png_sPLT_t (_tp, _tpp) + Increased precision of rgb_to_gray calculations from 8 to 15 bits and + added png_set_rgb_to_gray_fixed() function. + Added makefile.bc32 (32-bit Borland C++, C mode) +version 1.0.5v [March 11, 2000] + Added some parentheses to the png_jmpbuf macro definition. + Updated references to the zlib home page, which has moved to freesoftware.com. + Corrected bugs in documentation regarding png_read_row() and png_write_row(). + Updated documentation of png_rgb_to_gray calculations in libpng.3/libpng.txt. + Renamed makefile.borland,turboc3 back to makefile.bor,tc3 as in version 1.0.3, + revised borland makefiles; added makefile.ibmvac3 and makefile.gcc (Cosmin) + +version 1.0.6 [March 20, 2000] + Minor revisions of makefile.bor, libpng.txt, and gregbook/rpng2-win.c + Added makefile.sggcc (SGI IRIX with gcc) +version 1.0.6d [April 7, 2000] + Changed sprintf() to strcpy() in png_write_sCAL_s() to work without STDIO + Added data_length parameter to png_decompress_chunk() function + Revised documentation to remove reference to abandoned png_free_chnk functions + Fixed an error in png_rgb_to_gray_fixed() + Revised example.c, usage of png_destroy_write_struct(). + Renamed makefile.ibmvac3 to makefile.ibmc, added libpng.icc IBM project file + Added a check for info_ptr->free_me&PNG_FREE_TEXT when freeing text in png.c + Simplify png_sig_bytes() function to remove use of non-ISO-C strdup(). +version 1.0.6e [April 9, 2000] + Added png_data_freer() function. + In the code that checks for over-length tRNS chunks, added check of + info_ptr->num_trans as well as png_ptr->num_trans (Matthias Benckmann) + Minor revisions of libpng.txt/libpng.3. + Check for existing data and free it if the free_me flag is set, in png_set_*() + and png_handle_*(). + Only define PNG_WEIGHTED_FILTERS_SUPPORTED when PNG_FLOATING_POINT_SUPPORTED + is defined. + Changed several instances of PNG_NO_CONSOLE_ID to PNG_NO_STDIO in pngrutil.c + and mentioned the purposes of the two macros in libpng.txt/libpng.3. +version 1.0.6f [April 14, 2000] + Revised png_set_iCCP() and png_set_rows() to avoid prematurely freeing data. + Add checks in png_set_text() for NULL members of the input text structure. + Revised libpng.txt/libpng.3. + Removed superfluous prototype for png_set_itxt from png.h + Removed "else" from pngread.c, after png_error(), and changed "0" to "length". + Changed several png_errors about malformed ancillary chunks to png_warnings. +version 1.0.6g [April 24, 2000] + Added png_pass-* arrays to pnggccrd.c when PNG_USE_LOCAL_ARRAYS is defined. + Relocated paragraph about png_set_background() in libpng.3/libpng.txt + and other revisions (Matthias Benckmann) + Relocated info_ptr->free_me, png_ptr->free_me, and other info_ptr and + png_ptr members to restore binary compatibility with libpng-1.0.5 + (breaks compatibility with libpng-1.0.6). +version 1.0.6h [April 24, 2000] + Changed shared library so-number pattern from 2.x.y.z to xy.z (this builds + libpng.so.10 & libpng.so.10.6h instead of libpng.so.2 & libpng.so.2.1.0.6h) + This is a temporary change for test purposes. +version 1.0.6i [May 2, 2000] + Rearranged some members at the end of png_info and png_struct, to put + unknown_chunks_num and free_me within the original size of the png_structs + and free_me, png_read_user_fn, and png_free_fn within the original png_info, + because some old applications allocate the structs directly instead of + using png_create_*(). + Added documentation of user memory functions in libpng.txt/libpng.3 + Modified png_read_png so that it will use user_allocated row_pointers + if present, unless free_me directs that it be freed, and added description + of the use of png_set_rows() and png_get_rows() in libpng.txt/libpng.3. + Added PNG_LEGACY_SUPPORTED macro, and #ifdef out all new (since version + 1.00) members of png_struct and png_info, to regain binary compatibility + when you define this macro. Capabilities lost in this event + are user transforms (new in version 1.0.0),the user transform pointer + (new in version 1.0.2), rgb_to_gray (new in 1.0.5), iCCP, sCAL, sPLT, + the high-level interface, and unknown chunks support (all new in 1.0.6). + This was necessary because of old applications that allocate the structs + directly as authors were instructed to do in libpng-0.88 and earlier, + instead of using png_create_*(). + Added modes PNG_CREATED_READ_STRUCT and PNG_CREATED_WRITE_STRUCT which + can be used to detect codes that directly allocate the structs, and + code to check these modes in png_read_init() and png_write_init() and + generate a libpng error if the modes aren't set and PNG_LEGACY_SUPPORTED + was not defined. + Added makefile.intel and updated makefile.watcom (Pawel Mrochen) +version 1.0.6j [May 3, 2000] + Overloaded png_read_init() and png_write_init() with macros that convert + calls to png_read_init_2() or png_write_init_2() that check the version + and structure sizes. +version 1.0.7beta11 [May 7, 2000] + Removed the new PNG_CREATED_READ_STRUCT and PNG_CREATED_WRITE_STRUCT modes + which are no longer used. + Eliminated the three new members of png_text when PNG_LEGACY_SUPPORTED is + defined or when neither PNG_READ_iTXt_SUPPORTED nor PNG_WRITE_iTXT_SUPPORTED + is defined. + Made PNG_NO_READ|WRITE_iTXt the default setting, to avoid memory + overrun when old applications fill the info_ptr->text structure directly. + Added PNGAPI macro, and added it to the definitions of all exported functions. + Relocated version macro definitions ahead of the includes of zlib.h and + pngconf.h in png.h. +version 1.0.7beta12 [May 12, 2000] + Revised pngset.c to avoid a problem with expanding the png_debug macro. + Deleted some extraneous defines from pngconf.h + Made PNG_NO_CONSOLE_IO the default condition when PNG_BUILD_DLL is defined. + Use MSC _RPTn debugging instead of fprintf if _MSC_VER is defined. + Added png_access_version_number() function. + Check for mask&PNG_FREE_CHNK (for TEXT, SCAL, PCAL) in png_free_data(). + Expanded libpng.3/libpng.txt information about png_data_freer(). +version 1.0.7beta14 [May 17, 2000] (beta13 was not published) + Changed pnggccrd.c and pngvcrd.c to handle bad adaptive filter types as + warnings instead of errors, as pngrutil.c does. + Set the PNG_INFO_IDAT valid flag in png_set_rows() so png_write_png() + will actually write IDATs. + Made the default PNG_USE_LOCAL_ARRAYS depend on PNG_DLL instead of WIN32. + Make png_free_data() ignore its final parameter except when freeing data + that can have multiple instances (text, sPLT, unknowns). + Fixed a new bug in png_set_rows(). + Removed info_ptr->valid tests from png_free_data(), as in version 1.0.5. + Added png_set_invalid() function. + Fixed incorrect illustrations of png_destroy_write_struct() in example.c. +version 1.0.7beta15 [May 30, 2000] + Revised the deliberately erroneous Linux setjmp code in pngconf.h to produce + fewer error messages. + Rearranged checks for Z_OK to check the most likely path first in pngpread.c + and pngwutil.c. + Added checks in pngtest.c for png_create_*() returning NULL, and mentioned + in libpng.txt/libpng.3 the need for applications to check this. + Changed names of png_default_*() functions in pngtest to pngtest_*(). + Changed return type of png_get_x|y_offset_*() from png_uint_32 to png_int_32. + Fixed some bugs in the unused PNG_INCH_CONVERSIONS functions in pngget.c + Set each pointer to NULL after freeing it in png_free_data(). + Worked around a problem in pngconf.h; AIX's strings.h defines an "index" + macro that conflicts with libpng's png_color_16.index. (Dimitri Papadapoulos) + Added "msvc" directory with MSVC++ project files (Simon-Pierre Cadieux). +version 1.0.7beta16 [June 4, 2000] + Revised the workaround of AIX string.h "index" bug. + Added a check for overlength PLTE chunk in pngrutil.c. + Added PNG_NO_POINTER_INDEXING macro to use array-indexing instead of pointer + indexing in pngrutil.c and pngwutil.c to accommodate a buggy compiler. + Added a warning in png_decompress_chunk() when it runs out of data, e.g. + when it tries to read an erroneous PhotoShop iCCP chunk. + Added PNG_USE_DLL macro. + Revised the copyright/disclaimer/license notice. + Added contrib/msvctest directory +version 1.0.7rc1 [June 9, 2000] + Corrected the definition of PNG_TRANSFORM_INVERT_ALPHA (0x0400 not 0x0200) + Added contrib/visupng directory (Willem van Schaik) +version 1.0.7beta18 [June 23, 2000] + Revised PNGAPI definition, and pngvcrd.c to work with __GCC__ + and do not redefine PNGAPI if it is passed in via a compiler directive. + Revised visupng/PngFile.c to remove returns from within the Try block. + Removed leading underscores from "_PNG_H" and "_PNG_SAVE_BSD_SOURCE" macros. + Updated contrib/visupng/cexcept.h to version 1.0.0. + Fixed bugs in pngwrite.c and pngwutil.c that prevented writing iCCP chunks. +version 1.0.7rc2 [June 28, 2000] + Updated license to include disclaimers required by UCITA. + Fixed "DJBPP" typo in pnggccrd.c introduced in beta18. + +version 1.0.7 [July 1, 2000] + Revised the definition of "trans_values" in libpng.3/libpng.txt +version 1.0.8beta1 [July 8, 2000] + Added png_free(png_ptr, key) two places in pngpread.c to stop memory leaks. + Changed PNG_NO_STDIO to PNG_NO_CONSOLE_IO, several places in pngrutil.c and + pngwutil.c. + Changed PNG_EXPORT_VAR to use PNG_IMPEXP, in pngconf.h. + Removed unused "#include " from png.c + Added WindowsCE support. + Revised pnggccrd.c to work with gcc-2.95.2 and in the Cygwin environment. +version 1.0.8beta2 [July 10, 2000] + Added project files to the wince directory and made further revisions + of pngtest.c, pngrio.c, and pngwio.c in support of WindowsCE. +version 1.0.8beta3 [July 11, 2000] + Only set the PNG_FLAG_FREE_TRNS or PNG_FREE_TRNS flag in png_handle_tRNS() + for indexed-color input files to avoid potential double-freeing trans array + under some unusual conditions; problem was introduced in version 1.0.6f. + Further revisions to pngtest.c and files in the wince subdirectory. +version 1.0.8beta4 [July 14, 2000] + Added the files pngbar.png and pngbar.jpg to the distribution. + Added makefile.cygwin, and cygwin support in pngconf.h + Added PNG_NO_ZALLOC_ZERO macro (makes png_zalloc skip zeroing memory) +version 1.0.8rc1 [July 16, 2000] + Revised png_debug() macros and statements to eliminate compiler warnings. + +version 1.0.8 [July 24, 2000] + Added png_flush() in pngwrite.c, after png_write_IEND(). + Updated makefile.hpux to build a shared library. +version 1.0.9beta1 [November 10, 2000] + Fixed typo in scripts/makefile.hpux + Updated makevms.com in scripts and contrib/* and contrib/* (Martin Zinser) + Fixed seqence-point bug in contrib/pngminus/png2pnm (Martin Zinser) + Changed "cdrom.com" in documentation to "libpng.org" + Revised pnggccrd.c to get it all working, and updated makefile.gcmmx (Greg). + Changed type of "params" from voidp to png_voidp in png_read|write_png(). + Make sure PNGAPI and PNG_IMPEXP are defined in pngconf.h. + Revised the 3 instances of WRITEFILE in pngtest.c. + Relocated "msvc" and "wince" project subdirectories into "dll" subdirectory. + Updated png.rc in dll/msvc project + Revised makefile.dec to define and use LIBPATH and INCPATH + Increased size of global png_libpng_ver[] array from 12 to 18 chars. + Made global png_libpng_ver[], png_sig[] and png_pass_*[] arrays const. + Removed duplicate png_crc_finish() from png_handle_bKGD() function. + Added a warning when application calls png_read_update_info() multiple times. + Revised makefile.cygwin + Fixed bugs in iCCP support in pngrutil.c and pngwutil.c. + Replaced png_set_empty_plte_permitted() with png_permit_mng_features(). +version 1.0.9beta2 [November 19, 2000] + Renamed the "dll" subdirectory "projects". + Added borland project files to "projects" subdirectory. + Set VS_FF_PRERELEASE and VS_FF_PATCHED flags in msvc/png.rc when appropriate. + Add error message in png_set_compression_buffer_size() when malloc fails. +version 1.0.9beta3 [November 23, 2000] + Revised PNG_LIBPNG_BUILD_TYPE macro in png.h, used in the msvc project. + Removed the png_flush() in pngwrite.c that crashes some applications + that don't set png_output_flush_fn. + Added makefile.macosx and makefile.aix to scripts directory. +version 1.0.9beta4 [December 1, 2000] + Change png_chunk_warning to png_warning in png_check_keyword(). + Increased the first part of msg buffer from 16 to 18 in png_chunk_error(). +version 1.0.9beta5 [December 15, 2000] + Added support for filter method 64 (for PNG datastreams embedded in MNG). +version 1.0.9beta6 [December 18, 2000] + Revised png_set_filter() to accept filter method 64 when appropriate. + Added new PNG_HAVE_PNG_SIGNATURE bit to png_ptr->mode and use it to + help prevent applications from using MNG features in PNG datastreams. + Added png_permit_mng_features() function. + Revised libpng.3/libpng.txt. Changed "filter type" to "filter method". +version 1.0.9rc1 [December 23, 2000] + Revised test for PNG_HAVE_PNG_SIGNATURE in pngrutil.c + Fixed error handling of unknown compression type in png_decompress_chunk(). + In pngconf.h, define __cdecl when _MSC_VER is defined. +version 1.0.9beta7 [December 28, 2000] + Changed PNG_TEXT_COMPRESSION_zTXt to PNG_COMPRESSION_TYPE_BASE several places. + Revised memory management in png_set_hIST and png_handle_hIST in a backward + compatible manner. PLTE and tRNS were revised similarly. + Revised the iCCP chunk reader to ignore trailing garbage. +version 1.0.9beta8 [January 12, 2001] + Moved pngasmrd.h into pngconf.h. + Improved handling of out-of-spec garbage iCCP chunks generated by PhotoShop. +version 1.0.9beta9 [January 15, 2001] + Added png_set_invalid, png_permit_mng_features, and png_mmx_supported to + wince and msvc project module definition files. + Minor revision of makefile.cygwin. + Fixed bug with progressive reading of narrow interlaced images in pngpread.c +version 1.0.9beta10 [January 16, 2001] + Do not typedef png_FILE_p in pngconf.h when PNG_NO_STDIO is defined. + Fixed "png_mmx_supported" typo in project definition files. +version 1.0.9beta11 [January 19, 2001] + Updated makefile.sgi to make shared library. + Removed png_mmx_support() function and disabled PNG_MNG_FEATURES_SUPPORTED + by default, for the benefit of DLL forward compatibility. These will + be re-enabled in version 1.2.0. +version 1.0.9rc2 [January 22, 2001] + Revised cygwin support. + +version 1.0.9 [January 31, 2001] + Added check of cygwin's ALL_STATIC in pngconf.h + Added "-nommx" parameter to contrib/gregbook/rpng2-win and rpng2-x demos. +version 1.0.10beta1 [March 14, 2001] + Revised makefile.dec, makefile.sgi, and makefile.sggcc; added makefile.hpgcc. + Reformatted libpng.3 to eliminate bad line breaks. + Added checks for _mmx_supported in the read_filter_row function of pnggccrd.c + Added prototype for png_mmx_support() near the top of pnggccrd.c + Moved some error checking from png_handle_IHDR to png_set_IHDR. + Added PNG_NO_READ_SUPPORTED and PNG_NO_WRITE_SUPPORTED macros. + Revised png_mmx_support() function in pnggccrd.c + Restored version 1.0.8 PNG_WRITE_EMPTY_PLTE_SUPPORTED behavior in pngwutil.c + Fixed memory leak in contrib/visupng/PngFile.c + Fixed bugs in png_combine_row() in pnggccrd.c and pngvcrd.c (C version) + Added warnings when retrieving or setting gamma=0. + Increased the first part of msg buffer from 16 to 18 in png_chunk_warning(). +version 1.0.10rc1 [March 23, 2001] + Changed all instances of memcpy, strcpy, and strlen to png_memcpy, png_strcpy, + and png_strlen. + Revised png_mmx_supported() function in pnggccrd.c to return proper value. + Fixed bug in progressive reading (pngpread.c) with small images (height < 8). + +version 1.0.10 [March 30, 2001] + Deleted extraneous space (introduced in 1.0.9) from line 42 of makefile.cygwin + Added beos project files (Chris Herborth) +version 1.0.11beta1 [April 3, 2001] + Added type casts on several png_malloc() calls (Dimitri Papadapoulos). + Removed a no-longer needed AIX work-around from pngconf.h + Changed several "//" single-line comments to C-style in pnggccrd.c +version 1.0.11beta2 [April 11, 2001] + Removed PNGAPI from several functions whose prototypes did not have PNGAPI. + Updated scripts/pngos2.def +version 1.0.11beta3 [April 14, 2001] + Added checking the results of many instances of png_malloc() for NULL +version 1.0.11beta4 [April 20, 2001] + Undid the changes from version 1.0.11beta3. Added a check for NULL return + from user's malloc_fn(). + Removed some useless type casts of the NULL pointer. + Added makefile.netbsd + +version 1.0.11 [April 27, 2001] + Revised makefile.netbsd +version 1.0.12beta1 [May 14, 2001] + Test for Windows platform in pngconf.h when including malloc.h (Emmanuel Blot) + Updated makefile.cygwin and handling of Cygwin's ALL_STATIC in pngconf.h + Added some never-to-be-executed code in pnggccrd.c to quiet compiler warnings. + Eliminated the png_error about apps using png_read|write_init(). Instead, + libpng will reallocate the png_struct and info_struct if they are too small. + This retains future binary compatibility for old applications written for + libpng-0.88 and earlier. +version 1.2.0beta1 [May 6, 2001] + Bumped DLLNUM to 2. + Re-enabled PNG_MNG_FEATURES_SUPPORTED and enabled PNG_ASSEMBLER_CODE_SUPPORTED + by default. + Added runtime selection of MMX features. + Added png_set_strip_error_numbers function and related macros. +version 1.2.0beta2 [May 7, 2001] + Finished merging 1.2.0beta1 with version 1.0.11 + Added a check for attempts to read or write PLTE in grayscale PNG datastreams. +version 1.2.0beta3 [May 17, 2001] + Enabled user memory function by default. + Modified png_create_struct so it passes user mem_ptr to user memory allocator. + Increased png_mng_features flag from png_byte to png_uint_32. + Bumped shared-library (so-number) and dll-number to 3. +version 1.2.0beta4 [June 23, 2001] + Check for missing profile length field in iCCP chunk and free chunk_data + in case of truncated iCCP chunk. + Bumped shared-library number to 3 in makefile.sgi and makefile.sggcc + Bumped dll-number from 2 to 3 in makefile.cygwin + Revised contrib/gregbook/rpng*-x.c to avoid a memory leak and to exit cleanly + if user attempts to run it on an 8-bit display. + Updated contrib/gregbook + Use png_malloc instead of png_zalloc to allocate palette in pngset.c + Updated makefile.ibmc + Added some typecasts to eliminate gcc 3.0 warnings. Changed prototypes + of png_write_oFFS width and height from png_uint_32 to png_int_32. + Updated example.c + Revised prototypes for png_debug_malloc and png_debug_free in pngtest.c +version 1.2.0beta5 [August 8, 2001] + Revised contrib/gregbook + Revised makefile.gcmmx + Revised pnggccrd.c to conditionally compile some thread-unsafe code only + when PNG_THREAD_UNSAFE_OK is defined. + Added tests to prevent pngwutil.c from writing a bKGD or tRNS chunk with + value exceeding 2^bit_depth-1 + Revised makefile.sgi and makefile.sggcc + Replaced calls to fprintf(stderr,...) with png_warning() in pnggccrd.c + Removed restriction that do_invert_mono only operate on 1-bit opaque files + +version 1.2.0 [September 1, 2001] + Changed a png_warning() to png_debug() in pnggccrd.c + Fixed contrib/gregbook/rpng-x.c, rpng2-x.c to avoid crash with XFreeGC(). +version 1.2.1beta1 [October 19, 2001] + Revised makefile.std in contrib/pngminus + Include background_1 in png_struct regardless of gamma support. + Revised makefile.netbsd and makefile.macosx, added makefile.darwin. + Revised example.c to provide more details about using row_callback(). +version 1.2.1beta2 [October 25, 2001] + Added type cast to each NULL appearing in a function call, except for + WINCE functions. + Added makefile.so9. +version 1.2.1beta3 [October 27, 2001] + Removed type casts from all NULLs. + Simplified png_create_struct_2(). +version 1.2.1beta4 [November 7, 2001] + Revised png_create_info_struct() and png_creat_struct_2(). + Added error message if png_write_info() was omitted. + Type cast NULLs appearing in function calls when _NO_PROTO or + PNG_TYPECAST_NULL is defined. +version 1.2.1rc1 [November 24, 2001] + Type cast NULLs appearing in function calls except when PNG_NO_TYPECAST_NULL + is defined. + Changed typecast of "size" argument to png_size_t in pngmem.c calls to + the user malloc_fn, to agree with the prototype in png.h + Added a pop/push operation to pnggccrd.c, to preserve Eflag (Maxim Sobolev) + Updated makefile.sgi to recognize LIBPATH and INCPATH. + Updated various makefiles so "make clean" does not remove previous major + version of the shared library. +version 1.2.1rc2 [December 4, 2001] + Always allocate 256-entry internal palette, hist, and trans arrays, to + avoid out-of-bounds memory reference caused by invalid PNG datastreams. + Added a check for prefix_length > data_length in iCCP chunk handler. + +version 1.2.1 [December 7, 2001] + None. +version 1.2.2beta1 [February 22, 2002] + Fixed a bug with reading the length of iCCP profiles (Larry Reeves). + Revised makefile.linux, makefile.gcmmx, and makefile.sgi to generate + libpng.a, libpng12.so (not libpng.so.3), and libpng12/png.h + Revised makefile.darwin to remove "-undefined suppress" option. + Added checks for gamma and chromaticity values over 21474.83, which exceed + the limit for PNG unsigned 32-bit integers when encoded. + Revised calls to png_create_read_struct() and png_create_write_struct() + for simpler debugging. + Revised png_zalloc() so zlib handles errors (uses PNG_FLAG_MALLOC_NULL_MEM_OK) +version 1.2.2beta2 [February 23, 2002] + Check chunk_length and idat_size for invalid (over PNG_MAX_UINT) lengths. + Check for invalid image dimensions in png_get_IHDR. + Added missing "fi;" in the install target of the SGI makefiles. + Added install-static to all makefiles that make shared libraries. + Always do gamma compensation when image is partially transparent. +version 1.2.2beta3 [March 7, 2002] + Compute background.gray and background_1.gray even when color_type is RGB + in case image gets reduced to gray later. + Modified shared-library makefiles to install pkgconfig/libpngNN.pc. + Export (with PNGAPI) png_zalloc, png_zfree, and png_handle_as_unknown + Removed unused png_write_destroy_info prototype from png.h + Eliminated incorrect use of width_mmx from pnggccrd.c in pixel_bytes == 8 case + Added install-shared target to all makefiles that make shared libraries. + Stopped a double free of palette, hist, and trans when not using free_me. + Added makefile.32sunu for Sun Ultra 32 and makefile.64sunu for Sun Ultra 64. +version 1.2.2beta4 [March 8, 2002] + Compute background.gray and background_1.gray even when color_type is RGB + in case image gets reduced to gray later (Jason Summers). + Relocated a misplaced /bin/rm in the "install-shared" makefile targets + Added PNG_1_0_X macro which can be used to build a 1.0.x-compatible library. +version 1.2.2beta5 [March 26, 2002] + Added missing PNGAPI to several function definitions. + Check for invalid bit_depth or color_type in png_get_IHDR(), and + check for missing PLTE or IHDR in png_push_read_chunk() (Matthias Clasen). + Revised iTXt support to accept NULL for lang and lang_key. + Compute gamma for color components of background even when color_type is gray. + Changed "()" to "{}" in scripts/libpng.pc.in. + Revised makefiles to put png.h and pngconf.h only in $prefix/include/libpngNN + Revised makefiles to make symlink to libpng.so.NN in addition to libpngNN.so +version 1.2.2beta6 [March 31, 2002] +version 1.0.13beta1 [March 31, 2002] + Prevent png_zalloc() from trying to memset memory that it failed to acquire. + Add typecasts of PNG_MAX_UINT in pngset_cHRM_fixed() (Matt Holgate). + Ensure that the right function (user or default) is used to free the + png_struct after an error in png_create_read_struct_2(). +version 1.2.2rc1 [April 7, 2002] +version 1.0.13rc1 [April 7, 2002] + Save the ebx register in pnggccrd.c (Sami Farin) + Add "mem_ptr = png_ptr->mem_ptr" in png_destroy_write_struct() (Paul Gardner). + Updated makefiles to put headers in include/libpng and remove old include/*.h. + +version 1.2.2 [April 15, 2002] +version 1.0.13 [April 15, 2002] + Revised description of png_set_filter() in libpng.3/libpng.txt. + Revised makefile.netbsd and added makefile.neNNbsd and makefile.freebsd +version 1.0.13patch01 [April 17, 2002] +version 1.2.2patch01 [April 17, 2002] + Changed ${PNGMAJ}.${PNGVER} bug to ${PNGVER} in makefile.sgi and makefile.sggcc + Fixed VER -> PNGVER typo in makefile.macosx and added install-static to install + Added install: target to makefile.32sunu and makefile.64sunu +version 1.0.13patch03 [April 18, 2002] +version 1.2.2patch03 [April 18, 2002] + Revised 15 makefiles to link libpng.a to libpngNN.a and the include libpng + subdirectory to libpngNN subdirectory without the full pathname. + Moved generation of libpng.pc from "install" to "all" in 15 makefiles. +version 1.2.3rc1 [April 28, 2002] + Added install-man target to 15 makefiles (Dimitri Papadopolous-Orfanos). + Added $(DESTDIR) feature to 24 makefiles (Tim Mooney) + Fixed bug with $prefix, should be $(prefix) in makefile.hpux. + Updated cygwin-specific portion of pngconf.h and revised makefile.cygwin + Added a link from libpngNN.pc to libpng.pc in 15 makefiles. + Added links from include/libpngNN/*.h to include/*.h in 24 makefiles. + Revised makefile.darwin to make relative links without full pathname. + Added setjmp() at the end of png_create_*_struct_2() in case user forgets + to put one in their application. + Restored png_zalloc() and png_zfree() prototypes to version 1.2.1 and + removed them from module definition files. +version 1.2.3rc2 [May 1, 2002] + Fixed bug in reporting number of channels in pngget.c and pngset.c, + that was introduced in version 1.2.2beta5. + Exported png_zalloc(), png_zfree(), png_default_read(), png_default_write(), + png_default_flush(), and png_push_fill_buffer() and included them in + module definition files. + Added "libpng.pc" dependency to the "install-shared" target in 15 makefiles. +version 1.2.3rc3 [May 1, 2002] + Revised prototype for png_default_flush() + Remove old libpng.pc and libpngNN.pc before installing new ones. +version 1.2.3rc4 [May 2, 2002] + Typos in *.def files (png_default_read|write -> png_default_read|write_data) + In makefiles, changed rm libpng.NN.pc to rm libpngNN.pc + Added libpng-config and libpngNN-config and modified makefiles to install them. + Changed $(MANPATH) to $(DESTDIR)$(MANPATH) in makefiles + Added "Win32 DLL VB" configuration to projects/msvc/libpng.dsp +version 1.2.3rc5 [May 11, 2002] + Changed "error" and "message" in prototypes to "error_message" and + "warning_message" to avoid namespace conflict. + Revised 15 makefiles to build libpng-config from libpng-config-*.in + Once more restored png_zalloc and png_zfree to regular nonexported form. + Restored png_default_read|write_data, png_default_flush, png_read_fill_buffer + to nonexported form, but with PNGAPI, and removed them from module def files. +version 1.2.3rc6 [May 14, 2002] + Removed "PNGAPI" from png_zalloc() and png_zfree() in png.c + Changed "Gz" to "Gd" in projects/msvc/libpng.dsp and zlib.dsp. + Removed leftover libpng-config "sed" script from four makefiles. + Revised libpng-config creating script in 16 makefiles. + +version 1.2.3 [May 22, 2002] + Revised libpng-config target in makefile.cygwin. + Removed description of png_set_mem_fn() from documentation. + Revised makefile.freebsd. + Minor cosmetic changes to 15 makefiles, e.g., $(DI) = $(DESTDIR)/$(INCDIR). + Revised projects/msvc/README.txt + Changed -lpng to -lpngNN in LDFLAGS in several makefiles. +version 1.2.4beta1 [May 24, 2002] + Added libpng.pc and libpng-config to "all:" target in 16 makefiles. + Fixed bug in 16 makefiles: $(DESTDIR)/$(LIBPATH) to $(DESTDIR)$(LIBPATH) + Added missing "\" before closing double quote in makefile.gcmmx. + Plugged various memory leaks; added png_malloc_warn() and png_set_text_2() + functions. +version 1.2.4beta2 [June 25, 2002] + Plugged memory leak of png_ptr->current_text (Matt Holgate). + Check for buffer overflow before reading CRC in pngpread.c (Warwick Allison) + Added -soname to the loader flags in makefile.dec, makefile.sgi, and + makefile.sggcc. + Added "test-installed" target to makefile.linux, makefile.gcmmx, + makefile.sgi, and makefile.sggcc. +version 1.2.4beta3 [June 28, 2002] + Plugged memory leak of row_buf in pngtest.c when there is a png_error(). + Detect buffer overflow in pngpread.c when IDAT is corrupted with extra data. + Added "test-installed" target to makefile.32sunu, makefile.64sunu, + makefile.beos, makefile.darwin, makefile.dec, makefile.macosx, + makefile.solaris, makefile.hpux, makefile.hpgcc, and makefile.so9. +version 1.2.4rc1 and 1.0.14rc1 [July 2, 2002] + Added "test-installed" target to makefile.cygwin and makefile.sco. + Revised pnggccrd.c to be able to back out version 1.0.x via PNG_1_0_X macro. + +version 1.2.4 and 1.0.14 [July 8, 2002] + Changed png_warning() to png_error() when width is too large to process. +version 1.2.4patch01 [July 20, 2002] + Revised makefile.cygwin to use DLL number 12 instead of 13. +version 1.2.5beta1 [August 6, 2002] + Added code to contrib/gregbook/readpng2.c to ignore unused chunks. + Replaced toucan.png in contrib/gregbook (it has been corrupt since 1.0.11) + Removed some stray *.o files from contrib/gregbook. + Changed png_error() to png_warning() about "Too much data" in pngpread.c + and about "Extra compressed data" in pngrutil.c. + Prevent png_ptr->pass from exceeding 7 in png_push_finish_row(). + Updated makefile.hpgcc + Updated png.c and pnggccrd.c handling of return from png_mmx_support() +version 1.2.5beta2 [August 15, 2002] + Only issue png_warning() about "Too much data" in pngpread.c when avail_in + is nonzero. + Updated makefiles to install a separate libpng.so.3 with its own rpath. +version 1.2.5rc1 and 1.0.15rc1 [August 24, 2002] + Revised makefiles to not remove previous minor versions of shared libraries. +version 1.2.5rc2 and 1.0.15rc2 [September 16, 2002] + Revised 13 makefiles to remove "-lz" and "-L$(ZLIBLIB)", etc., from shared + library loader directive. + Added missing "$OBJSDLL" line to makefile.gcmmx. + Added missing "; fi" to makefile.32sunu. +version 1.2.5rc3 and 1.0.15rc3 [September 18, 2002] + Revised libpng-config script. + +version 1.2.5 and 1.0.15 [October 3, 2002] + Revised makefile.macosx, makefile.darwin, makefile.hpgcc, and makefile.hpux, + and makefile.aix. + Relocated two misplaced PNGAPI lines in pngtest.c +version 1.2.6beta1 [October 22, 2002] + Commented out warning about uninitialized mmx_support in pnggccrd.c. + Changed "IBMCPP__" flag to "__IBMCPP__" in pngconf.h. + Relocated two more misplaced PNGAPI lines in pngtest.c + Fixed memory overrun bug in png_do_read_filler() with 16-bit datastreams, + introduced in version 1.0.2. + Revised makefile.macosx, makefile.dec, makefile.aix, and makefile.32sunu. +version 1.2.6beta2 [November 1, 2002] + Added libpng-config "--ldopts" output. + Added "AR=ar" and "ARFLAGS=rc" and changed "ar rc" to "$(AR) $(ARFLAGS)" + in makefiles. +version 1.2.6beta3 [July 18, 2004] + Reverted makefile changes from version 1.2.6beta2 and some of the changes + from version 1.2.6beta1; these will be postponed until version 1.2.7. + Version 1.2.6 is going to be a simple bugfix release. + Changed the one instance of "ln -sf" to "ln -f -s" in each Sun makefile. + Fixed potential overrun in pngerror.c by using strncpy instead of memcpy. + Added "#!/bin/sh" at the top of configure, for recognition of the + 'x' flag under Cygwin (Cosmin). + Optimized vacuous tests that silence compiler warnings, in png.c (Cosmin). + Added support for PNG_USER_CONFIG, in pngconf.h (Cosmin). + Fixed the special memory handler for Borland C under DOS, in pngmem.c + (Cosmin). + Removed some spurious assignments in pngrutil.c (Cosmin). + Replaced 65536 with 65536L, and 0xffff with 0xffffL, to silence warnings + on 16-bit platforms (Cosmin). + Enclosed shift op expressions in parentheses, to silence warnings (Cosmin). + Used proper type png_fixed_point, to avoid problems on 16-bit platforms, + in png_handle_sRGB() (Cosmin). + Added compression_type to png_struct, and optimized the window size + inside the deflate stream (Cosmin). + Fixed definition of isnonalpha(), in pngerror.c and pngrutil.c (Cosmin). + Fixed handling of unknown chunks that come after IDAT (Cosmin). + Allowed png_error() and png_warning() to work even if png_ptr == NULL + (Cosmin). + Replaced row_info->rowbytes with row_bytes in png_write_find_filter() + (Cosmin). + Fixed definition of PNG_LIBPNG_VER_DLLNUM (Simon-Pierre). + Used PNG_LIBPNG_VER and PNG_LIBPNG_VER_STRING instead of the hardcoded + values in png.c (Simon-Pierre, Cosmin). + Initialized png_libpng_ver[] with PNG_LIBPNG_VER_STRING (Simon-Pierre). + Replaced PNG_LIBPNG_VER_MAJOR with PNG_LIBPNG_VER_DLLNUM in png.rc + (Simon-Pierre). + Moved the definition of PNG_HEADER_VERSION_STRING near the definitions + of the other PNG_LIBPNG_VER_... symbols in png.h (Cosmin). + Relocated #ifndef PNGAPI guards in pngconf.h (Simon-Pierre, Cosmin). + Updated scripts/makefile.vc(a)win32 (Cosmin). + Updated the MSVC project (Simon-Pierre, Cosmin). + Updated the Borland C++ Builder project (Cosmin). + Avoided access to asm_flags in pngvcrd.c, if PNG_1_0_X is defined (Cosmin). + Commented out warning about uninitialized mmx_support in pngvcrd.c (Cosmin). + Removed scripts/makefile.bd32 and scripts/pngdef.pas (Cosmin). + Added extra guard around inclusion of Turbo C memory headers, in pngconf.h + (Cosmin). + Renamed projects/msvc/ to projects/visualc6/, and projects/borland/ to + projects/cbuilder5/ (Cosmin). + Moved projects/visualc6/png32ms.def to scripts/pngw32.def, + and projects/visualc6/png.rc to scripts/pngw32.rc (Cosmin). + Added projects/visualc6/pngtest.dsp; removed contrib/msvctest/ (Cosmin). + Changed line endings to DOS style in cbuilder5 and visualc6 files, even + in the tar.* distributions (Cosmin). + Updated contrib/visupng/VisualPng.dsp (Cosmin). + Updated contrib/visupng/cexcept.h to version 2.0.0 (Cosmin). + Added a separate distribution with "configure" and supporting files (Junichi). +version 1.2.6beta4 [July 28, 2004] + Added user ability to change png_size_t via a PNG_SIZE_T macro. + Added png_sizeof() and png_convert_size() functions. + Added PNG_SIZE_MAX (maximum value of a png_size_t variable. + Added check in png_malloc_default() for (size_t)size != (png_uint_32)size + which would indicate an overflow. + Changed sPLT failure action from png_error to png_warning and abandon chunk. + Changed sCAL and iCCP failures from png_error to png_warning and abandon. + Added png_get_uint_31(png_ptr, buf) function. + Added PNG_UINT_32_MAX macro. + Renamed PNG_MAX_UINT to PNG_UINT_31_MAX. + Made png_zalloc() issue a png_warning and return NULL on potential + overflow. + Turn on PNG_NO_ZALLOC_ZERO by default in version 1.2.x + Revised "clobber list" in pnggccrd.c so it will compile under gcc-3.4. + Revised Borland portion of png_malloc() to return NULL or issue + png_error() according to setting of PNG_FLAG_MALLOC_NULL_MEM_OK. + Added PNG_NO_SEQUENTIAL_READ_SUPPORTED macro to conditionally remove + sequential read support. + Added some "#if PNG_WRITE_SUPPORTED" blocks. + Added #ifdef to remove some redundancy in png_malloc_default(). + Use png_malloc instead of png_zalloc to allocate the pallete. +version 1.0.16rc1 and 1.2.6rc1 [August 4, 2004] + Fixed buffer overflow vulnerability in png_handle_tRNS() + Fixed integer arithmetic overflow vulnerability in png_read_png(). + Fixed some harmless bugs in png_handle_sBIT, etc, that would cause + duplicate chunk types to go undetected. + Fixed some timestamps in the -config version + Rearranged order of processing of color types in png_handle_tRNS(). + Added ROWBYTES macro to calculate rowbytes without integer overflow. + Updated makefile.darwin and removed makefile.macosx from scripts directory. + Imposed default one million column, one-million row limits on the image + dimensions, and added png_set_user_limits() function to override them. + Revised use of PNG_SET_USER_LIMITS_SUPPORTED macro. + Fixed wrong cast of returns from png_get_user_width|height_max(). + Changed some "keep the compiler happy" from empty statements to returns, + Revised libpng.txt to remove 1.2.x stuff from the 1.0.x distribution +version 1.0.16rc2 and 1.2.6rc2 [August 7, 2004] + Revised makefile.darwin and makefile.solaris. Removed makefile.macosx. + Revised pngtest's png_debug_malloc() to use png_malloc() instead of + png_malloc_default() which is not supposed to be exported. + Fixed off-by-one error in one of the conversions to PNG_ROWBYTES() in + pngpread.c. Bug was introduced in 1.2.6rc1. + Fixed bug in RGB to RGBX transformation introduced in 1.2.6rc1. + Fixed old bug in RGB to Gray transformation. + Fixed problem with 64-bit compilers by casting arguments to abs() + to png_int_32. + Changed "ln -sf" to "ln -f -s" in three makefiles (solaris, sco, so9). + Changed "HANDLE_CHUNK_*" to "PNG_HANDLE_CHUNK_*" (Cosmin) + Added "-@/bin/rm -f $(DL)/$(LIBNAME).so.$(PNGMAJ)" to 15 *NIX makefiles. + Added code to update the row_info->colortype in png_do_read_filler() (MSB). +version 1.0.16rc3 and 1.2.6rc3 [August 9, 2004] + Eliminated use of "abs()" in testing cHRM and gAMA values, to avoid + trouble with some 64-bit compilers. Created PNG_OUT_OF_RANGE() macro. + Revised documentation of png_set_keep_unknown_chunks(). + Check handle_as_unknown status in pngpread.c, as in pngread.c previously. + Moved "PNG_HANDLE_CHUNK_*" macros out of PNG_INTERNAL section of png.h + Added "rim" definitions for CONST4 and CONST6 in pnggccrd.c +version 1.0.16rc4 and 1.2.6rc4 [August 10, 2004] + Fixed mistake in pngtest.c introduced in 1.2.6rc2 (declaration of + "pinfo" was out of place). +version 1.0.16rc5 and 1.2.6rc5 [August 10, 2004] + Moved "PNG_HANDLE_CHUNK_*" macros out of PNG_ASSEMBLER_CODE_SUPPORTED + section of png.h where they were inadvertently placed in version rc3. + +version 1.2.6 and 1.0.16 [August 15, 2004] + Revised pngtest so memory allocation testing is only done when PNG_DEBUG==1. +version 1.2.7beta1 [August 26, 2004] + Removed unused pngasmrd.h file. + Removed references to uu.net for archived files. Added references to + PNG Spec (second edition) and the PNG ISO/IEC Standard. + Added "test-dd" target in 15 makefiles, to run pngtest in DESTDIR. + Fixed bug with "optimized window size" in the IDAT datastream, that + causes libpng to write PNG files with incorrect zlib header bytes. +version 1.2.7beta2 [August 28, 2004] + Fixed bug with sCAL chunk and big-endian machines (David Munro). + Undid new code added in 1.2.6rc2 to update the color_type in + png_set_filler(). + Added png_set_add_alpha() that updates color type. +version 1.0.17rc1 and 1.2.7rc1 [September 4, 2004] + Revised png_set_strip_filler() to not remove alpha if color_type has alpha. + +version 1.2.7 and 1.0.17 [September 12, 2004] + Added makefile.hp64 + Changed projects/msvc/png32ms.def to scripts/png32ms.def in makefile.cygwin +version 1.2.8beta1 [November 1, 2004] + Fixed bug in png_text_compress() that would fail to complete a large block. + Fixed bug, introduced in libpng-1.2.7, that overruns a buffer during + strip alpha operation in png_do_strip_filler(). + Added PNG_1_2_X definition in pngconf.h + Use #ifdef to comment out png_info_init in png.c and png_read_init in + pngread.c (as of 1.3.0) +version 1.2.8beta2 [November 2, 2004] + Reduce color_type to a nonalpha type after strip alpha operation in + png_do_strip_filler(). +version 1.2.8beta3 [November 3, 2004] + Revised definitions of PNG_MAX_UINT_32, PNG_MAX_SIZE, and PNG_MAXSUM +version 1.2.8beta4 [November 12, 2004] + Fixed (again) definition of PNG_LIBPNG_VER_DLLNUM in png.h (Cosmin). + Added PNG_LIBPNG_BUILD_PRIVATE in png.h (Cosmin). + Set png_ptr->zstream.data_type to Z_BINARY, to avoid unnecessary detection + of data type in deflate (Cosmin). + Deprecated but continue to support SPECIALBUILD and PRIVATEBUILD in favor of + PNG_LIBPNG_BUILD_SPECIAL_STRING and PNG_LIBPNG_BUILD_PRIVATE_STRING. +version 1.2.8beta5 [November 20, 2004] + Use png_ptr->flags instead of png_ptr->transformations to pass + PNG_STRIP_ALPHA info to png_do_strip_filler(), to preserve ABI + compatibility. + Revised handling of SPECIALBUILD, PRIVATEBUILD, + PNG_LIBPNG_BUILD_SPECIAL_STRING and PNG_LIBPNG_BUILD_PRIVATE_STRING. +version 1.2.8rc1 [November 24, 2004] + Moved handling of BUILD macros from pngconf.h to png.h + Added definition of PNG_LIBPNG_BASE_TYPE in png.h, inadvertently + omitted from beta5. + Revised scripts/pngw32.rc + Despammed mailing addresses by masking "@" with "at". + Inadvertently installed a supposedly faster test version of pngrutil.c +version 1.2.8rc2 [November 26, 2004] + Added two missing "\" in png.h + Change tests in pngread.c and pngpread.c to + if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA)) + png_do_read_transformations(png_ptr); +version 1.2.8rc3 [November 28, 2004] + Reverted pngrutil.c to version libpng-1.2.8beta5. + Added scripts/makefile.elf with supporting code in pngconf.h for symbol + versioning (John Bowler). +version 1.2.8rc4 [November 29, 2004] + Added projects/visualc7 (Simon-pierre). +version 1.2.8rc5 [November 29, 2004] + Fixed new typo in scripts/pngw32.rc + +version 1.2.8 [December 3, 2004] + Removed projects/visualc7, added projects/visualc71. + +version 1.2.9beta1 [February 21, 2006] + + Initialized some structure members in pngwutil.c to avoid gcc-4.0.0 complaints + Revised man page and libpng.txt to make it clear that one should not call + png_read_end or png_write_end after png_read_png or png_write_png. + Updated references to png-mng-implement mailing list. + Fixed an incorrect typecast in pngrutil.c + Added PNG_NO_READ_SUPPORTED conditional for making a write-only library. + Added PNG_NO_WRITE_INTERLACING_SUPPORTED conditional. + Optimized alpha-inversion loops in pngwtran.c + Moved test for nonzero gamma outside of png_build_gamma_table() in pngrtran.c + Make sure num_trans is <= 256 before copying data in png_set_tRNS(). + Make sure num_palette is <= 256 before copying data in png_set_PLTE(). + Interchanged order of write_swap_alpha and write_invert_alpha transforms. + Added parentheses in the definition of PNG_LIBPNG_BUILD_TYPE (Cosmin). + Optimized zlib window flag (CINFO) in contrib/pngsuite/*.png (Cosmin). + Updated scripts/makefile.bc32 for Borland C++ 5.6 (Cosmin). + Exported png_get_uint_32, png_save_uint_32, png_get_uint_16, png_save_uint_16, + png_get_int_32, png_save_int_32, png_get_uint_31 (Cosmin). + Added type cast (png_byte) in png_write_sCAL() (Cosmin). + Fixed scripts/makefile.cygwin (Christian Biesinger, Cosmin). + Default iTXt support was inadvertently enabled. + +version 1.2.9beta2 [February 21, 2006] + + Check for png_rgb_to_gray and png_gray_to_rgb read transformations before + checking for png_read_dither in pngrtran.c + Revised checking of chromaticity limits to accommodate extended RGB + colorspace (John Denker). + Changed line endings in some of the project files to CRLF, even in the + "Unix" tar distributions (Cosmin). + Made png_get_int_32 and png_save_int_32 always available (Cosmin). + Updated scripts/pngos2.def, scripts/pngw32.def and projects/wince/png32ce.def + with the newly exported functions. + Eliminated distributions without the "configure" script. + Updated INSTALL instructions. + +version 1.2.9beta3 [February 24, 2006] + + Fixed CRCRLF line endings in contrib/visupng/VisualPng.dsp + Made libpng.pc respect EXEC_PREFIX (D. P. Kreil, J. Bowler) + Removed reference to pngasmrd.h from Makefile.am + Renamed CHANGES to ChangeLog. + Renamed LICENSE to COPYING. + Renamed ANNOUNCE to NEWS. + Created AUTHORS file. + +version 1.2.9beta4 [March 3, 2006] + + Changed definition of PKGCONFIG from $prefix/lib to $libdir in configure.ac + Reverted to filenames LICENSE and ANNOUNCE; removed AUTHORS and COPYING. + Removed newline from the end of some error and warning messages. + Removed test for sqrt() from configure.ac and configure. + Made swap tables in pngtrans.c PNG_CONST (Carlo Bramix). + Disabled default iTXt support that was inadvertently enabled in + libpng-1.2.9beta1. + Added "OS2" to list of systems that don't need underscores, in pnggccrd.c + Removed libpng version and date from *.c files. + +version 1.2.9beta5 [March 4, 2006] + Removed trailing blanks from source files. + Put version and date of latest change in each source file, and changed + copyright year accordingly. + More cleanup of configure.ac, Makefile.ac, and associated scripts. + Restored scripts/makefile.elf which was inadvertently deleted. + +version 1.2.9beta6 [March 6, 2006] + Fixed typo (RELEASE) in configuration files. + +version 1.2.9beta7 [March 7, 2006] + Removed libpng.vers and libpng.sym from libpng12_la_SOURCES in Makefile.am + Fixed inconsistent #ifdef's around png_sig_bytes() and png_set_sCAL_s() + in png.h. + Updated makefile.elf as suggested by debian. + Made cosmetic changes to some makefiles, adding LN_SF and other macros. + Made some makefiles accept "exec_prefix". + +version 1.2.9beta8 [March 9, 2006] + Fixed some "#if defined (..." which should be "#if defined(..." + Bug introduced in libpng-1.2.8. + Fixed inconsistency in definition of png_default_read_data() + Restored blank that was lost from makefile.sggcc "clean" target in beta7. + Revised calculation of "current" and "major" for irix in ltmain.sh + Changed "mkdir" to "MKDIR_P" in some makefiles. + Separated PNG_EXPAND and PNG_EXPAND_tRNS. + Added png_set_expand_gray_1_2_4_to_8() and deprecated + png_set_gray_1_2_4_to_8() which also expands tRNS to alpha. + +version 1.2.9beta9 [March 10, 2006] + Include "config.h" in pngconf.h when available. + Added some checks for NULL png_ptr or NULL info_ptr (timeless) + +version 1.2.9beta10 [March 20, 2006] + Removed extra CR from contrib/visualpng/VisualPng.dsw (Cosmin) + Made pnggccrd.c PIC-compliant (Christian Aichinger). + Added makefile.mingw (Wolfgang Glas). + Revised pngconf.h MMX checking. + +version 1.2.9beta11 [March 22, 2006] + Fixed out-of-order declaration in pngwrite.c that was introduced in beta9 + Simplified some makefiles by using LIBSO, LIBSOMAJ, and LIBSOVER macros. + +version 1.2.9rc1 [March 31, 2006] + Defined PNG_USER_PRIVATEBUILD when including "pngusr.h" (Cosmin). + Removed nonsensical assertion check from pngtest.c (Cosmin). + +version 1.2.9 [April 14, 2006] + Revised makefile.beos and added "none" selector in ltmain.sh + +version 1.2.10beta1 [April 15, 2006] + Renamed "config.h" to "png_conf.h" and revised Makefile.am to add + -DPNG_BUILDING_LIBPNG to compile directive, and modified pngconf.h + to include png_conf.h only when PNG_BUILDING_LIBPNG is defined. + +version 1.2.10beta2 [April 15, 2006] + Manually updated Makefile.in and configure. Changed png_conf.h.in + back to config.h. + +version 1.2.10beta3 [April 15, 2006] + Change png_conf.h back to config.h in pngconf.h. + +version 1.2.10beta4 [April 16, 2006] + Change PNG_BUILDING_LIBPNG to PNG_CONFIGURE_LIBPNG in config/Makefile*. + +version 1.2.10beta5 [April 16, 2006] + Added a configure check for compiling assembler code in pnggccrd.c + +version 1.2.10beta6 [April 17, 2006] + Revised the configure check for pnggccrd.c + Moved -DPNG_CONFIGURE_LIBPNG into @LIBPNG_DEFINES@ + Added @LIBPNG_DEFINES@ to arguments when building libpng.sym + +version 1.2.10beta7 [April 18, 2006] + Change "exec_prefix=$prefix" to "exec_prefix=$(prefix)" in makefiles. + +version 1.2.10rc1 [April 19, 2006] + Ensure pngconf.h doesn't define both PNG_USE_PNGGCCRD and PNG_USE_PNGVCRD + Fixed "LN_FS" typo in makefile.sco and makefile.solaris. + +version 1.2.10rc2 [April 20, 2006] + Added a backslash between -DPNG_CONFIGURE_LIBPNG and -DPNG_NO_ASSEMBLER_CODE + in configure.ac and configure + Made the configure warning about versioned symbols less arrogant. + +version 1.2.10rc3 [April 21, 2006] + Added a note in libpng.txt that png_set_sig_bytes(8) can be used when + writing an embedded PNG without the 8-byte signature. + Revised makefiles and configure to avoid making links to libpng.so.* + +version 1.2.10 [April 23, 2006] + Reverted configure to "rc2" state. + +version 1.2.11beta1 [May 31, 2006] + scripts/libpng.pc.in contained "configure" style version info and would + not work with makefiles. + The shared-library makefiles were linking to libpng.so.0 instead of + libpng.so.3 compatibility as the library. + +version 1.2.11beta2 [June 2, 2006] + Increased sprintf buffer from 50 to 52 chars in pngrutil.c to avoid + buffer overflow. + Fixed bug in example.c (png_set_palette_rgb -> png_set_palette_to_rgb) + +version 1.2.11beta3 [June 5, 2006] + Prepended "#! /bin/sh" to ltmail.sh and contrib/pngminus/*.sh (Cosmin). + Removed the accidental leftover Makefile.in~ (Cosmin). + Avoided potential buffer overflow and optimized buffer in + png_write_sCAL(), png_write_sCAL_s() (Cosmin). + Removed the include directories and libraries from CFLAGS and LDFLAGS + in scripts/makefile.gcc (Nelson A. de Oliveira, Cosmin). + +version 1.2.11beta4 [June 6, 2006] + Allow zero-length IDAT chunks after the entire zlib datastream, but not + after another intervening chunk type. + +version 1.0.19rc1, 1.2.11rc1 [June 13, 2006] + Deleted extraneous square brackets from [config.h] in configure.ac + +version 1.0.19rc2, 1.2.11rc2 [June 14, 2006] + Added prototypes for PNG_INCH_CONVERSIONS functions to png.h + Revised INSTALL and autogen.sh + Fixed typo in several makefiles (-W1 should be -Wl) + Added typedef for png_int_32 and png_uint_32 on 64-bit systems. + +version 1.0.19rc3, 1.2.11rc3 [June 15, 2006] + Removed the new typedefs for 64-bit systems (delay until version 1.4.0) + Added one zero element to png_gamma_shift[] array in pngrtran.c to avoid + reading out of bounds. + +version 1.0.19rc4, 1.2.11rc4 [June 15, 2006] + Really removed the new typedefs for 64-bit systems. + +version 1.0.19rc5, 1.2.11rc5 [June 22, 2006] + Removed png_sig_bytes entry from scripts/pngw32.def + +version 1.0.19, 1.2.11 [June 26, 2006] + None. + +version 1.0.20, 1.2.12 [June 27, 2006] + Really increased sprintf buffer from 50 to 52 chars in pngrutil.c to avoid + buffer overflow. + +version 1.2.13beta1 [October 2, 2006] + Removed AC_FUNC_MALLOC from configure.ac + Work around Intel-Mac compiler bug by setting PNG_NO_MMX_CODE in pngconf.h + Change "logical" to "bitwise" throughout documentation. + Detect and fix attempt to write wrong iCCP profile length. + +version 1.0.21, 1.2.13 [November 14, 2006] + Fix potential buffer overflow in sPLT chunk handler. + Fix Makefile.am to not try to link to noexistent files. + Check all exported functions for NULL png_ptr. + +version 1.2.14beta1 [November 17, 2006] + Relocated three misplaced tests for NULL png_ptr. + Built Makefile.in with automake-1.9.6 instead of 1.9.2. + Build configure with autoconf-2.60 instead of 2.59 + +version 1.2.14beta2 [November 17, 2006] + Added some typecasts in png_zalloc(). + +version 1.2.14rc1 [November 20, 2006] + Changed "strtod" to "png_strtod" in pngrutil.c + +version 1.0.22, 1.2.14 [November 27, 2006] + Added missing "$(srcdir)" in Makefile.am and Makefile.in + +version 1.2.15beta1 [December 3, 2006] + Generated configure with autoconf-2.61 instead of 2.60 + Revised configure.ac to update libpng.pc and libpng-config. + +version 1.2.15beta2 [December 3, 2006] + Always export MMX asm functions, just stubs if not building pnggccrd.c + +version 1.2.15beta3 [December 4, 2006] + Add "png_bytep" typecast to profile while calculating length in pngwutil.c + +version 1.2.15beta4 [December 7, 2006] + Added scripts/CMakeLists.txt + Changed PNG_NO_ASSEMBLER_CODE to PNG_NO_MMX_CODE in scripts, like 1.4.0beta + +version 1.2.15beta5 [December 7, 2006] + Changed some instances of PNG_ASSEMBLER_* to PNG_MMX_* in pnggccrd.c + Revised scripts/CMakeLists.txt + +version 1.2.15beta6 [December 13, 2006] + Revised scripts/CMakeLists.txt and configure.ac + +version 1.2.15rc1 [December 18, 2006] + Revised scripts/CMakeLists.txt + +version 1.2.15rc2 [December 21, 2006] + Added conditional #undef jmpbuf in pngtest.c to undo #define in AIX headers. + Added scripts/makefile.nommx + +version 1.2.15rc3 [December 25, 2006] + Fixed shared library numbering error that was introduced in 1.2.15beta6. + +version 1.2.15rc4 [December 27, 2006] + Fixed handling of rgb_to_gray when png_ptr->color.gray isn't set. + +version 1.2.15rc5 [December 31, 2006] + Revised handling of rgb_to_gray. + +version 1.2.15 [January 5, 2007] + Added some (unsigned long) typecasts in pngtest.c to avoid printing errors. + +version 1.2.16beta1 [January 6, 2007] + Fix bugs in makefile.nommx + +version 1.2.16beta2 [January 16, 2007] + Revised scripts/CMakeLists.txt + +version 1.2.16 [January 31, 2007] + No changes. + +version 1.2.17beta1 [March 6, 2007] + Revised scripts/CMakeLists.txt to install both shared and static libraries. + Deleted a redundant line from pngset.c. + +version 1.2.17beta2 [April 26, 2007] + Relocated misplaced test for png_ptr == NULL in pngpread.c + Change "==" to "&" for testing PNG_RGB_TO_GRAY_ERR & PNG_RGB_TO_GRAY_WARN + flags. + Changed remaining instances of PNG_ASSEMBLER_* to PNG_MMX_* + Added pngerror() when write_IHDR fails in deflateInit2(). + Added "const" to some array declarations. + Mention examples of libpng usage in the libpng*.txt and libpng.3 documents. + +version 1.2.17rc1 [May 4, 2007] + No changes. + +version 1.2.17rc2 [May 8, 2007] + Moved several PNG_HAVE_* macros out of PNG_INTERNAL because applications + calling set_unknown_chunk_location() need them. + Changed transformation flag from PNG_EXPAND_tRNS to PNG_EXPAND in + png_set_expand_gray_1_2_4_to_8(). + Added png_ptr->unknown_chunk to hold working unknown chunk data, so it + can be free'ed in case of error. Revised unknown chunk handling in + pngrutil.c and pngpread.c to use this structure. + +version 1.2.17rc3 [May 8, 2007] + Revised symbol-handling in configure script. + +version 1.2.17rc4 [May 10, 2007] + Revised unknown chunk handling to avoid storing unknown critical chunks. + +version 1.0.25 [May 15, 2007] +version 1.2.17 [May 15, 2007] + Added "png_ptr->num_trans=0" before error return in png_handle_tRNS, + to eliminate a vulnerability (CVE-2007-2445, CERT VU#684664) + +version 1.0.26 [May 15, 2007] +version 1.2.18 [May 15, 2007] + Reverted the libpng-1.2.17rc3 change to symbol-handling in configure script + +version 1.2.19beta1 [May 18, 2007] + Changed "const static" to "static PNG_CONST" everywhere, mostly undoing + change of libpng-1.2.17beta2. Changed other "const" to "PNG_CONST" + Changed some handling of unused parameters, to avoid compiler warnings. + "if (unused == NULL) return;" becomes "unused = unused". + +version 1.2.19beta2 [May 18, 2007] + Only use the valid bits of tRNS value in png_do_expand() (Brian Cartier) + +version 1.2.19beta3 [May 19, 2007] + Add some "png_byte" typecasts in png_check_keyword() and write new_key + instead of key in zTXt chunk (Kevin Ryde). + +version 1.2.19beta4 [May 21, 2007] + Add png_snprintf() function and use it in place of sprint() for improved + defense against buffer overflows. + +version 1.2.19beta5 [May 21, 2007] + Fixed png_handle_tRNS() to only use the valid bits of tRNS value. + Changed handling of more unused parameters, to avoid compiler warnings. + Removed some PNG_CONST in pngwutil.c to avoid compiler warnings. + +version 1.2.19beta6 [May 22, 2007] + Added some #ifdef PNG_MMX_CODE_SUPPORTED where needed in pngvcrd.c + Added a special "_MSC_VER" case that defines png_snprintf to _snprintf + +version 1.2.19beta7 [May 22, 2007] + Squelched png_squelch_warnings() in pnggccrd.c and added + an #ifdef PNG_MMX_CODE_SUPPORTED block around the declarations that caused + the warnings that png_squelch_warnings was squelching. + +version 1.2.19beta8 [May 22, 2007] + Removed __MMX__ from test in pngconf.h. + +version 1.2.19beta9 [May 23, 2007] + Made png_squelch_warnings() available via PNG_SQUELCH_WARNINGS macro. + Revised png_squelch_warnings() so it might work. + Updated makefile.sgcc and makefile.solaris; added makefile.solaris-x86. + +version 1.2.19beta10 [May 24, 2007] + Resquelched png_squelch_warnings(), use "__attribute__((used))" instead. + +version 1.4.0beta1 [April 20, 2006] + Enabled iTXt support (changes png_struct, thus requires so-number change). + Cleaned up PNG_ASSEMBLER_CODE_SUPPORTED vs PNG_MMX_CODE_SUPPORTED + Eliminated PNG_1_0_X and PNG_1_2_X macros. + Removed deprecated functions png_read_init, png_write_init, png_info_init, + png_permit_empty_plte, png_set_gray_1_2_4_to_8, png_check_sig, and + removed the deprecated macro PNG_MAX_UINT. + Moved "PNG_INTERNAL" parts of png.h and pngconf.h into pngintrn.h + Removed many WIN32_WCE #ifdefs (Cosmin). + Reduced dependency on C-runtime library when on Windows (Simon-Pierre) + Replaced sprintf() with png_sprintf() (Simon-Pierre) + +version 1.4.0beta2 [April 20, 2006] + Revised makefiles and configure to avoid making links to libpng.so.* + Moved some leftover MMX-related defines from pngconf.h to pngintrn.h + Updated scripts/pngos2.def, pngw32.def, and projects/wince/png32ce.def + +version 1.4.0beta3 [May 10, 2006] + Updated scripts/pngw32.def to comment out MMX functions. + Added PNG_NO_GET_INT_32 and PNG_NO_SAVE_INT_32 macros. + Scripts/libpng.pc.in contained "configure" style version info and would + not work with makefiles. + Revised pngconf.h and added pngconf.h.in, so makefiles and configure can + pass defines to libpng and applications. + +version 1.4.0beta4 [May 11, 2006] + Revised configure.ac, Makefile.am, and many of the makefiles to write + their defines in pngconf.h. + +version 1.4.0beta5 [May 15, 2006] + Added a missing semicolon in Makefile.am and Makefile.in + Deleted extraneous square brackets from configure.ac + +version 1.4.0beta6 [June 2, 2006] + Increased sprintf buffer from 50 to 52 chars in pngrutil.c to avoid + buffer overflow. + Changed sonum from 0 to 1. + Removed unused prototype for png_check_sig() from png.h + +version 1.4.0beta7 [June 16, 2006] + Exported png_write_sig (Cosmin). + Optimized buffer in png_handle_cHRM() (Cosmin). + Set pHYs = 2835 x 2835 pixels per meter, and added + sCAL = 0.352778e-3 x 0.352778e-3 meters, in pngtest.png (Cosmin). + Added png_set_benign_errors(), png_benign_error(), png_chunk_benign_error(). + Added typedef for png_int_32 and png_uint_32 on 64-bit systems. + Added "(unsigned long)" typecast on png_uint_32 variables in printf lists. + +version 1.4.0beta8 [June 22, 2006] + Added demonstration of user chunk support in pngtest.c, to support the + public sTER chunk and a private vpAg chunk. + +version 1.4.0beta9 [July 3, 2006] + Removed ordinals from scripts/pngw32.def and removed png_info_int and + png_set_gray_1_2_4_to_8 entries. + Inline call of png_get_uint_32() in png_get_uint_31(). + Use png_get_uint_31() to get vpAg width and height in pngtest.c + Removed WINCE and Netware projects. + Removed standalone Y2KINFO file. + +version 1.4.0beta10 [July 12, 2006] + Eliminated automatic copy of pngconf.h to pngconf.h.in from configure and + some makefiles, because it was not working reliably. Instead, distribute + pngconf.h.in along with pngconf.h and cause configure and some of the + makefiles to update pngconf.h from pngconf.h.in. + Added pngconf.h to DEPENDENCIES in Makefile.am + +version 1.4.0beta11 [August 19, 2006] + Removed AC_FUNC_MALLOC from configure.ac. + Added a warning when writing iCCP profile with mismatched profile length. + Patched pnggccrd.c to assemble on x86_64 platforms. + Moved chunk header reading into a separate function png_read_chunk_header() + in pngrutil.c. The chunk header (len+sig) is now serialized in a single + operation (Cosmin). + Implemented support for I/O states. Added png_ptr member io_state, and + functions png_get_io_chunk_name() and png_get_io_state() in pngget.c + (Cosmin). + Added png_get_io_chunk_name and png_get_io_state to scripts/*.def (Cosmin). + Renamed scripts/pngw32.* to scripts/pngwin.* (Cosmin). + Removed the include directories and libraries from CFLAGS and LDFLAGS + in scripts/makefile.gcc (Cosmin). + Used png_save_uint_32() to set vpAg width and height in pngtest.c (Cosmin). + Cast to proper type when getting/setting vpAg units in pngtest.c (Cosmin). + Added pngintrn.h to the Visual C++ projects (Cosmin). + Removed scripts/list (Cosmin). + Updated copyright year in scripts/pngwin.def (Cosmin). + Removed PNG_TYPECAST_NULL and used standard NULL consistently (Cosmin). + Disallowed the user to redefine png_size_t, and enforced a consistent use + of png_size_t across libpng (Cosmin). + Changed the type of png_ptr->rowbytes, PNG_ROWBYTES() and friends + to png_size_t (Cosmin). + Removed png_convert_size() and replaced png_sizeof with sizeof (Cosmin). + Removed some unnecessary type casts (Cosmin). + Changed prototype of png_get_compression_buffer_size() and + png_set_compression_buffer_size() to work with png_size_t instead of + png_uint_32 (Cosmin). + Removed png_memcpy_check() and png_memset_check() (Cosmin). + Fixed a typo (png_byte --> png_bytep) in libpng.3 and libpng.txt (Cosmin). + Clarified that png_zalloc() does not clear the allocated memory, + and png_zalloc() and png_zfree() cannot be PNGAPI (Cosmin). + Renamed png_mem_size_t to png_alloc_size_t, fixed its definition in + pngconf.h, and used it in all memory allocation functions (Cosmin). + Renamed pngintrn.h to pngpriv.h, added a comment at the top of the file + mentioning that the symbols declared in that file are private, and + updated the scripts and the Visual C++ projects accordingly (Cosmin). + Removed circular references between pngconf.h and pngconf.h.in in + scripts/makefile.vc*win32 (Cosmin). + Removing trailing '.' from the warning and error messages (Cosmin). + Added pngdefs.h that is built by makefile or configure, instead of + pngconf.h.in (Glenn). + Detect and fix attempt to write wrong iCCP profile length. + +version 1.4.0beta12 [October 19, 2006] + Changed "logical" to "bitwise" in the documentation. + Work around Intel-Mac compiler bug by setting PNG_NO_MMX_CODE in pngconf.h + Add a typecast to stifle compiler warning in pngrutil.c + +version 1.4.0beta13 [November 10, 2006] + Fix potential buffer overflow in sPLT chunk handler. + Fix Makefile.am to not try to link to noexistent files. + +version 1.4.0beta14 [November 15, 2006] + Check all exported functions for NULL png_ptr. + +version 1.4.0beta15 [November 17, 2006] + Relocated two misplaced tests for NULL png_ptr. + Built Makefile.in with automake-1.9.6 instead of 1.9.2. + Build configure with autoconf-2.60 instead of 2.59 + Add "install: all" in Makefile.am so "configure; make install" will work. + +version 1.4.0beta16 [November 17, 2006] + Added a typecast in png_zalloc(). + +version 1.4.0beta17 [December 4, 2006] + Changed "new_key[79] = '\0';" to "(*new_key)[79] = '\0';" in pngwutil.c + Add "png_bytep" typecast to profile while calculating length in pngwutil.c + +version 1.4.0beta18 [December 7, 2006] + Added scripts/CMakeLists.txt + +version 1.4.0beta19 [May 16, 2007] + Revised scripts/CMakeLists.txt + Rebuilt configure and Makefile.in with newer tools. + Added conditional #undef jmpbuf in pngtest.c to undo #define in AIX headers. + Added scripts/makefile.nommx + +version 1.4.0beta20 [July 9, 2008] + Moved several PNG_HAVE_* macros from pngpriv.h to png.h because applications + calling set_unknown_chunk_location() need them. + Moved several macro definitions from pngpriv.h to pngconf.h + Merge with changes to the 1.2.X branch, as of 1.2.30beta04. + Deleted all use of the MMX assembler code and Intel-licensed optimizations. + Revised makefile.mingw + +version 1.4.0beta21 [July 21, 2008] + Moved local array "chunkdata" from pngrutil.c to the png_struct, so + it will be freed by png_read_destroy() in case of a read error (Kurt + Christensen). + +version 1.4.0beta22 [July 21, 2008] + Change "purpose" and "buffer" to png_ptr->chunkdata to avoid memory leaking. + +version 1.4.0beta23 [July 22, 2008] + Change "chunkdata = NULL" to "png_ptr->chunkdata = NULL" several places in + png_decompress_chunk(). + +version 1.4.0beta24 [July 25, 2008] + Change all remaining "chunkdata" to "png_ptr->chunkdata" in + png_decompress_chunk(), and remove "chunkdata" from parameter list. + Put a call to png_check_chunk_name() in png_read_chunk_header(). + Revised png_check_chunk_name() to reject a name with a lowercase 3rd byte. + Removed two calls to png_check_chunk_name() occuring later in the process. + Define PNG_NO_ERROR_NUMBERS by default in pngconf.h + +version 1.4.0beta25 [July 30, 2008] + Added a call to png_check_chunk_name() in pngpread.c + Reverted png_check_chunk_name() to accept a name with a lowercase 3rd byte. + Added png_push_have_buffer() function to pngpread.c + Eliminated PNG_BIG_ENDIAN_SUPPORTED and associated png_get_* macros. + Made inline expansion of png_get_*() optional with PNG_USE_READ_MACROS. + Eliminated all PNG_USELESS_TESTS and PNG_CORRECT_PALETTE_SUPPORTED code. + Synced contrib directory and configure files with libpng-1.2.30beta06. + Eliminated no-longer-used pngdefs.h (but it's still built in the makefiles) + Relocated a misplaced "#endif /* PNG_NO_WRITE_FILTER */" in pngwutil.c + +version 1.4.0beta26 [August 4, 2008] + Removed png_push_have_buffer() function in pngpread.c. It increased the + compiled library size slightly. + Changed "-Wall" to "-W -Wall" in the CFLAGS in all makefiles (Cosmin Truta) + Declared png_ptr "volatile" in pngread.c and pngwrite.c to avoid warnings. + Updated contrib/visupng/cexcept.h to version 2.0.1 + Added PNG_LITERAL_CHARACTER macros for #, [, and ]. + +version 1.4.0beta27 [August 5, 2008] + Revised usage of PNG_LITERAL_SHARP in pngerror.c. + Moved newline character from individual png_debug messages into the + png_debug macros. + Allow user to #define their own png_debug, png_debug1, and png_debug2. + +version 1.4.0beta28 [August 5, 2008] + Revised usage of PNG_LITERAL_SHARP in pngerror.c. + Added PNG_STRING_NEWLINE macro + +version 1.4.0beta29 [August 9, 2008] + Revised usage of PNG_STRING_NEWLINE to work on non-ISO compilers. + Added PNG_STRING_COPYRIGHT macro. + Added non-ISO versions of png_debug macros. + +version 1.4.0beta30 [August 14, 2008] + Added premultiplied alpha feature (Volker Wiendl). + +version 1.4.0beta31 [August 18, 2008] + Moved png_set_premultiply_alpha from pngtrans.c to pngrtran.c + Removed extra crc check at the end of png_handle_cHRM(). Bug introduced + in libpng-1.4.0beta20. + +version 1.4.0beta32 [August 19, 2008] + Added PNG_WRITE_FLUSH_SUPPORTED block around new png_flush() call. + Revised PNG_NO_STDIO version of png_write_flush() + +version 1.4.0beta33 [August 20, 2008] + Added png_get|set_chunk_cache_max() to limit the total number of sPLT, + text, and unknown chunks that can be stored. + +version 1.4.0beta34 [September 6, 2008] + Shortened tIME_string to 29 bytes in pngtest.c + Fixed off-by-one error introduced in png_push_read_zTXt() function in + libpng-1.2.30beta04/pngpread.c (Harald van Dijk) + +version 1.4.0beta35 [October 6, 2008] + Changed "trans_values" to "trans_color". + Changed so-number from 0 to 14. Some OS do not like 0. + Revised makefile.darwin to fix shared library numbering. + Change png_set_gray_1_2_4_to_8() to png_set_expand_gray_1_2_4_to_8() + in example.c (debian bug report) + +version 1.4.0beta36 [October 25, 2008] + Sync with tEXt vulnerability fix in libpng-1.2.33rc02. + +version 1.4.0beta37 [November 13, 2008] + Added png_check_cHRM in png.c and moved checking from pngget.c, pngrutil.c, + and pngwrite.c + +version 1.4.0beta38 [November 22, 2008] + Added check for zero-area RGB cHRM triangle in png_check_cHRM() and + png_check_cHRM_fixed(). + +version 1.4.0beta39 [November 23, 2008] + Revised png_warning() to write its message on standard output by default + when warning_fn is NULL. + +version 1.4.0beta40 [November 24, 2008] + Eliminated png_check_cHRM(). Instead, always use png_check_cHRM_fixed(). + In png_check_cHRM_fixed(), ensure white_y is > 0, and removed redundant + check for all-zero coordinates that is detected by the triangle check. + +version 1.4.0beta41 [November 26, 2008] + Fixed string vs pointer-to-string error in png_check_keyword(). + Rearranged test expressions in png_check_cHRM_fixed() to avoid internal + overflows. + Added PNG_NO_CHECK_cHRM conditional. + +version 1.4.0beta42, 43 [December 1, 2008] + Merge png_debug with version 1.2.34beta04. + +version 1.4.0beta44 [December 6, 2008] + Removed redundant check for key==NULL before calling png_check_keyword() + to ensure that new_key gets initialized and removed extra warning + (Merge with version 1.2.34beta05 -- Arvan Pritchard). + +version 1.4.0beta45 [December 9, 2008] + In png_write_png(), respect the placement of the filler bytes in an earlier + call to png_set_filler() (Jim Barry). + +version 1.4.0beta46 [December 10, 2008] + Undid previous change and added PNG_TRANSFORM_STRIP_FILLER_BEFORE and + PNG_TRANSFORM_STRIP_FILLER_AFTER conditionals and deprecated + PNG_TRANSFORM_STRIP_FILLER (Jim Barry). + +version 1.4.0beta47 [December 15, 2008] + Support for dithering was disabled by default, because it has never + been well tested and doesn't work very well. The code has not + been removed, however, and can be enabled by building libpng with + PNG_READ_DITHER_SUPPORTED defined. + +version 1.4.0beta48 [February 14, 2009] + Added new exported function png_calloc(). + Combined several instances of png_malloc(); png_memset() into png_calloc(). + Removed prototype for png_freeptr() that was added in libpng-1.4.0beta24 + but was never defined. + +version 1.4.0beta49 [February 28, 2009] + Added png_fileno() macro to pngconf.h, used in pngwio.c + Corrected order of #ifdef's in png_debug definition in png.h + Fixed bug introduced in libpng-1.4.0beta48 with the memset arguments + for pcal_params. + Fixed order of #ifdef directives in the png_debug defines in png.h + (bug introduced in libpng-1.2.34/1.4.0beta29). + Revised comments in png_set_read_fn() and png_set_write_fn(). + +version 1.4.0beta50 [March 18, 2009] + Use png_calloc() instead of png_malloc() to allocate big_row_buf when + reading an interlaced file, to avoid a possible UMR. + Undid revision of PNG_NO_STDIO version of png_write_flush(). Users + having trouble with fflush() can build with PNG_NO_WRITE_FLUSH defined + or supply their own flush_fn() replacement. + Revised libpng*.txt and png.h documentation about use of png_write_flush() + and png_set_write_fn(). + Removed fflush() from pngtest.c. + Added "#define PNG_NO_WRITE_FLUSH" to contrib/pngminim/encoder/pngusr.h + +version 1.4.0beta51 [March 21, 2009] + Removed new png_fileno() macro from pngconf.h . + +version 1.4.0beta52 [March 27, 2009] + Relocated png_do_chop() ahead of building gamma tables in pngrtran.c + This avoids building 16-bit gamma tables unnecessarily. + Removed fflush() from pngtest.c. + Added "#define PNG_NO_WRITE_FLUSH" to contrib/pngminim/encoder/pngusr.h + Added a section on differences between 1.0.x and 1.2.x to libpng.3/libpng.txt + +version 1.4.0beta53 [April 1, 2009] + Removed some remaining MMX macros from pngpriv.h + Fixed potential memory leak of "new_name" in png_write_iCCP() (Ralph Giles) + +version 1.4.0beta54 [April 13, 2009] + Added "ifndef PNG_SKIP_SETJMP_CHECK" block in pngconf.h to allow + application code writers to bypass the check for multiple inclusion + of setjmp.h when they know that it is safe to ignore the situation. + Eliminated internal use of setjmp() in pngread.c and pngwrite.c + Reordered ancillary chunks in pngtest.png to be the same as what + pngtest now produces, and made some cosmetic changes to pngtest output. + Eliminated deprecated png_read_init_3() and png_write_init_3() functions. + +version 1.4.0beta55 [April 15, 2009] + Simplified error handling in pngread.c and pngwrite.c by putting + the new png_read_cleanup() and png_write_cleanup() functions inline. + +version 1.4.0beta56 [April 25, 2009] + Renamed "user_chunk_data" to "my_user_chunk_data" in pngtest.c to suppress + "shadowed declaration" warning from gcc-4.3.3. + Renamed "gamma" to "png_gamma" in pngset.c to avoid "shadowed declaration" + warning about a global "gamma" variable in math.h on some platforms. + +version 1.4.0beta57 [May 2, 2009] + Removed prototype for png_freeptr() that was added in libpng-1.4.0beta24 + but was never defined (again). + Rebuilt configure scripts with autoconf-2.63 instead of 2.62 + Removed pngprefs.h and MMX from makefiles + +version 1.4.0beta58 [May 14, 2009] + Changed pngw32.def to pngwin.def in makefile.mingw (typo was introduced + in beta57). + Clarified usage of sig_bit versus sig_bit_p in example.c (Vincent Torri) + +version 1.4.0beta59 [May 15, 2009] + Reformated sources in libpng style (3-space intentation, comment format) + Fixed typo in libpng docs (PNG_FILTER_AVE should be PNG_FILTER_AVG) + Added sections about the git repository and our coding style to the + documentation + Relocated misplaced #endif in pngwrite.c, sCAL chunk handler. + +version 1.4.0beta60 [May 19, 2009] + Conditionally compile png_read_finish_row() which is not used by + progressive readers. + Added contrib/pngminim/preader to demonstrate building minimal progressive + decoder, based on contrib/gregbook with embedded libpng and zlib. + +version 1.4.0beta61 [May 20, 2009] + In contrib/pngminim/*, renamed "makefile.std" to "makefile", since there + is only one makefile in those directories, and revised the README files + accordingly. + More reformatting of comments, mostly to capitalize sentences. + +version 1.4.0beta62 [June 2, 2009] + Added "#define PNG_NO_WRITE_SWAP" to contrib/pngminim/encoder/pngusr.h + and "define PNG_NO_READ_SWAP" to decoder/pngusr.h and preader/pngusr.h + Reformatted several remaining "else statement" into two lines. + Added a section to the libpng documentation about using png_get_io_ptr() + in configure scripts to detect the presence of libpng. + +version 1.4.0beta63 [June 15, 2009] + Revised libpng*.txt and libpng.3 to mention calling png_set_IHDR() + multiple times and to specify the sample order in the tRNS chunk, + because the ISO PNG specification has a typo in the tRNS table. + Changed several PNG_UNKNOWN_CHUNK_SUPPORTED to + PNG_HANDLE_AS_UNKNOWN_SUPPORTED, to make the png_set_keep mechanism + available for ignoring known chunks even when not saving unknown chunks. + Adopted preference for consistent use of "#ifdef" and "#ifndef" versus + "#if defined()" and "if !defined()" where possible. + +version 1.4.0beta64 [June 24, 2009] + Eliminated PNG_LEGACY_SUPPORTED code. + Moved the various unknown chunk macro definitions outside of the + PNG_READ|WRITE_ANCILLARY_CHUNK_SUPPORTED blocks. + +version 1.4.0beta65 [June 26, 2009] + Added a reference to the libpng license in each file. + +version 1.4.0beta66 [June 27, 2009] + Refer to the libpng license instead of the libpng license in each file. + +version 1.4.0beta67 [July 6, 2009] + Relocated INVERT_ALPHA within png_read_png() and png_write_png(). + Added high-level API transform PNG_TRANSFORM_GRAY_TO_RGB. + Added an "xcode" project to the projects directory (Alam Arias). + +version 1.4.0beta68 [July 19, 2009] + Avoid some tests in filter selection in pngwutil.c + +version 1.4.0beta69 [July 25, 2009] + Simplified the new filter-selection test. This runs faster in the + common "PNG_ALL_FILTERS" and PNG_FILTER_NONE cases. + Removed extraneous declaration from the new call to png_read_gray_to_rgb() + (bug introduced in libpng-1.4.0beta67). + Fixed up xcode project (Alam Arias) + Added a prototype for png_64bit_product() in png.c + +version 1.4.0beta70 [July 27, 2009] + Avoid a possible NULL dereference in debug build, in png_set_text_2(). + (bug introduced in libpng-0.95, discovered by Evan Rouault) + +version 1.4.0beta71 [July 29, 2009] + Rebuilt configure scripts with autoconf-2.64. + +version 1.4.0beta72 [August 1, 2009] + Replaced *.tar.lzma with *.tar.xz in distribution. Get the xz codec + from . + +version 1.4.0beta73 [August 1, 2009] + Reject attempt to write iCCP chunk with negative embedded profile length + (JD Chen) + +version 1.4.0beta74 [August 8, 2009] + Changed png_ptr and info_ptr member "trans" to "trans_alpha". + +version 1.4.0beta75 [August 21, 2009] + Removed an extra png_debug() recently added to png_write_find_filter(). + Fixed incorrect #ifdef in pngset.c regarding unknown chunk support. + +version 1.4.0beta76 [August 22, 2009] + Moved an incorrectly located test in png_read_row() in pngread.c + +version 1.4.0beta77 [August 27, 2009] + Removed lpXYZ.tar.bz2 (with CRLF), KNOWNBUG, libpng-x.y.z-KNOWNBUG.txt, + and the "noconfig" files from the distribution. + Moved CMakeLists.txt from scripts into the main libpng directory. + Various bugfixes and improvements to CMakeLists.txt (Philip Lowman) + +version 1.4.0beta78 [August 31, 2009] + Converted all PNG_NO_* tests to PNG_*_SUPPORTED everywhere except pngconf.h + Eliminated PNG_NO_FREE_ME and PNG_FREE_ME_SUPPORTED macros. + Use png_malloc plus a loop instead of png_calloc() to initialize + row_pointers in png_read_png(). + +version 1.4.0beta79 [September 1, 2009] + Eliminated PNG_GLOBAL_ARRAYS and PNG_LOCAL_ARRAYS; always use local arrays. + Eliminated PNG_CALLOC_SUPPORTED macro and always provide png_calloc(). + +version 1.4.0beta80 [September 17, 2009] + Removed scripts/libpng.icc + Changed typecast of filler from png_byte to png_uint_16 in png_set_filler(). + (Dennis Gustafsson) + Fixed typo introduced in beta78 in pngtest.c ("#if def " should be "#ifdef ") + +version 1.4.0beta81 [September 23, 2009] + Eliminated unused PNG_FLAG_FREE_* defines from pngpriv.h + Expanded TAB characters in pngrtran.c + Removed PNG_CONST from all "PNG_CONST PNG_CHNK" declarations to avoid + compiler complaints about doubly declaring things "const". + Changed all "#if [!]defined(X)" to "if[n]def X" where possible. + Eliminated unused png_ptr->row_buf_size + +version 1.4.0beta82 [September 25, 2009] + Moved redundant IHDR checking into new png_check_IHDR() in png.c + and report all errors found in the IHDR data. + Eliminated useless call to png_check_cHRM() from pngset.c + +version 1.4.0beta83 [September 25, 2009] + Revised png_check_IHDR() to eliminate bogus complaint about filter_type. + +version 1.4.0beta84 [September 30, 2009] + Fixed some inconsistent indentation in pngconf.h + Revised png_check_IHDR() to add a test for width variable less than 32-bit. + +version 1.4.0beta85 [October 1, 2009] + Revised png_check_IHDR() again, to check info_ptr members instead of + the contents of the returned parameters. + +version 1.4.0beta86 [October 9, 2009] + Updated the "xcode" project (Alam Arias). + Eliminated a shadowed declaration of "pp" in png_handle_sPLT(). + +version 1.4.0rc01 [October 19, 2009] + Trivial cosmetic changes. + +version 1.4.0beta87 [October 30, 2009] + Moved version 1.4.0 back into beta. + +version 1.4.0beta88 [October 30, 2009] + Revised libpng*.txt section about differences between 1.2.x and 1.4.0 + because most of the new features have now been ported back to 1.2.41 + +version 1.4.0beta89 [November 1, 2009] + More bugfixes and improvements to CMakeLists.txt (Philip Lowman) + Removed a harmless extra png_set_invert_alpha() from pngwrite.c + Apply png_user_chunk_cache_max within png_decompress_chunk(). + Merged libpng-1.2.41.txt with libpng-1.4.0.txt where appropriate. + +version 1.4.0beta90 [November 2, 2009] + Removed all remaining WIN32_WCE #ifdefs except those involving the + time.h "tm" structure + +version 1.4.0beta91 [November 3, 2009] + Updated scripts/pngw32.def and projects/wince/png32ce.def + Copied projects/wince/png32ce.def to the scripts directory. + Added scripts/makefile.wce + Patched ltmain.sh for wince support. + Added PNG_CONVERT_tIME_SUPPORTED macro. + +version 1.4.0beta92 [November 4, 2009] + Make inclusion of time.h in pngconf.h depend on PNG_CONVERT_tIME_SUPPORTED + Make #define PNG_CONVERT_tIME_SUPPORTED depend on PNG_WRITE_tIME_SUPPORTED + Revised libpng*.txt to describe differences from 1.2.40 to 1.4.0 (instead + of differences from 1.2.41 to 1.4.0) + +version 1.4.0beta93 [November 7, 2009] + Added PNG_DEPSTRUCT, PNG_DEPRECATED, PNG_USE_RESULT, PNG_NORETURN, and + PNG_ALLOCATED macros to detect deprecated direct access to the + png_struct or info_struct members and other deprecated usage in + applications (John Bowler). + Updated scripts/makefile* to add "-DPNG_CONFIGURE_LIBPNG" to CFLAGS, + to prevent warnings about direct access to png structs by libpng + functions while building libpng. They need to be tested, especially + those using compilers other than gcc. + Updated projects/visualc6 and visualc71 with "/d PNG_CONFIGURE_LIBPNG". + They should work but still need to be updated to remove + references to pnggccrd.c or pngvcrd.c and ASM building. + Added README.txt to the beos, cbuilder5, netware, and xcode projects warning + that they need to be updated, to remove references to pnggccrd.c and + pngvcrd.c and to depend on pngpriv.h + Removed three direct references to read_info_ptr members in pngtest.c + that were detected by the new PNG_DEPSTRUCT macro. + Moved the png_debug macro definitions and the png_read_destroy(), + png_write_destroy() and png_far_to_near() prototypes from png.h + to pngpriv.h (John Bowler) + Moved the synopsis lines for png_read_destroy(), png_write_destroy() + png_debug(), png_debug1(), and png_debug2() from libpng.3 to libpngpf.3. + +version 1.4.0beta94 [November 9, 2009] + Removed the obsolete, unused pnggccrd.c and pngvcrd.c files. + Updated CMakeLists.txt to add "-DPNG_CONFIGURE_LIBPNG" to the definitions. + Removed dependency of pngtest.o on pngpriv.h in the makefiles. + Only #define PNG_DEPSTRUCT, etc. in pngconf.h if not already defined. + +version 1.4.0beta95 [November 10, 2009] + Changed png_check_sig() to !png_sig_cmp() in contrib programs. + Added -DPNG_CONFIGURE_LIBPNG to contrib/pngminm/*/makefile + Changed png_check_sig() to !png_sig_cmp() in contrib programs. + Corrected the png_get_IHDR() call in contrib/gregbook/readpng2.c + Changed pngminim/*/gather.sh to stop trying to remove pnggccrd.c and pngvcrd.c + Added dependency on pngpriv.h in contrib/pngminim/*/makefile + +version 1.4.0beta96 [November 12, 2009] + Renamed scripts/makefile.wce to scripts/makefile.cegcc + Revised Makefile.am to use libpng.sys while building libpng.so + so that only PNG_EXPORT functions are exported. + Removed the deprecated png_check_sig() function/macro. + Removed recently removed function names from scripts/*.def + Revised pngtest.png to put chunks in the same order written by pngtest + (evidently the same change made in libpng-1.0beta54 was lost). + Added PNG_PRIVATE macro definition in pngconf.h for possible future use. + +version 1.4.0beta97 [November 13, 2009] + Restored pngtest.png to the libpng-1.4.0beta7 version. + Removed projects/beos and netware.txt; no one seems to be supporting them. + Revised Makefile.in + +version 1.4.0beta98 [November 13, 2009] + Added the "xcode" project to zip distributions, + Fixed a typo in scripts/pngwin.def introduced in beta97. + +version 1.4.0beta99 [November 14, 2009] + Moved libpng-config.in and libpng.pc-configure.in out of the scripts + directory, to libpng-config.in and libpng-pc.in, respectively, and + modified Makefile.am and configure.ac accordingly. Now "configure" + needs nothing from the "scripts" directory. + Avoid redefining PNG_CONST in pngconf.h + +version 1.4.0beta100 [November 14, 2009] + Removed ASM builds from projects/visualc6 and projects/visualc71 + Removed scripts/makefile.nommx and makefile.vcawin32 + Revised CMakeLists.txt to account for new location of libpng-config.in + and libpng-pc.in + Updated INSTALL to reflect removal and relocation of files. + +version 1.4.0beta101 [November 14, 2009] + Restored the binary files (*.jpg, *.png, some project files) that were + accidentally deleted from the zip and 7z distributions when the xcode + project was added. + +version 1.4.0beta102 [November 18, 2009] + Added libpng-config.in and libpng-pc.in to the zip and 7z distributions. + Fixed a typo in projects/visualc6/pngtest.dsp, introduced in beta100. + Moved descriptions of makefiles and other scripts out of INSTALL into + scripts/README.txt + Updated the copyright year in scripts/pngwin.rc from 2006 to 2009. + +version 1.4.0beta103 [November 21, 2009] + Removed obsolete comments about ASM from projects/visualc71/README_zlib.txt + Align row_buf on 16-byte boundary in memory. + Restored the PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED guard around the call + to png_flush() after png_write_IEND(). See 1.4.0beta32, 1.4.0beta50 + changes above and 1.2.30, 1.2.30rc01 and rc03 in 1.2.41 CHANGES. Someone + needs this feature. + Make the 'png_jmpbuf' macro expand to a call that records the correct + longjmp function as well as returning a pointer to the setjmp + jmp_buf buffer, and marked direct access to jmpbuf 'deprecated'. + (John Bowler) + +version 1.4.0beta104 [November 22, 2009] + Removed png_longjmp_ptr from scripts/*.def and libpng.3 + Rebuilt configure scripts with autoconf-2.65 + +version 1.4.0beta105 [November 25, 2009] + Use fast integer PNG_DIVIDE_BY_255() or PNG_DIVIDE_BY_65535() + to accomplish alpha premultiplication when + PNG_READ_COMPOSITE_NODIV_SUPPORTED is defined. + Changed "/255" to "/255.0" in background calculations to make it clear + that the 255 is used as a double. + +version 1.4.0beta106 [November 27, 2009] + Removed premultiplied alpha feature. + +version 1.4.0beta107 [December 4, 2009] + Updated README + Added "#define PNG_NO_PEDANTIC_WARNINGS" in the libpng source files. + Removed "-DPNG_CONFIGURE_LIBPNG" from the makefiles and projects. + Revised scripts/makefile.netbsd, makefile.openbsd, and makefile.sco + to put png.h and pngconf.h in $prefix/include, like the other scripts, + instead of in $prefix/include/libpng. Also revised makefile.sco + to put them in $prefix/include/libpng14 instead of in + $prefix/include/libpng/libpng14. + +version 1.4.0beta108 [December 11, 2009] + Removed leftover "-DPNG_CONFIGURE_LIBPNG" from contrib/pngminim/*/makefile + Relocated png_do_chop() to its original position in pngrtran.c; the + change in version 1.2.41beta08 caused transparency to be handled wrong + in some 16-bit datastreams (Yusaku Sugai). + +version 1.4.0beta109 [December 13, 2009] + Added "bit_depth" parameter to the private png_build_gamma_table() function. + Pass bit_depth=8 to png_build_gamma_table() when bit_depth is 16 but the + PNG_16_TO_8 transform has been set, to avoid unnecessary build of 16-bit + tables. + +version 1.4.0rc02 [December 20, 2009] + Declared png_cleanup_needed "volatile" in pngread.c and pngwrite.c + +version 1.4.0rc03 [December 22, 2009] + Renamed libpng-pc.in back to libpng.pc.in and revised CMakeLists.txt + (revising the change in 1.4.0beta99) + +version 1.4.0rc04 [December 25, 2009] + Swapped PNG_UNKNOWN_CHUNKS_SUPPORTED and PNG_HANDLE_AS_UNKNOWN_SUPPORTED + in pngset.c to be consistent with other changes in version 1.2.38. + +version 1.4.0rc05 [December 25, 2009] + Changed "libpng-pc.in" to "libpng.pc.in" in configure.ac, configure, and + Makefile.in to be consistent with changes in libpng-1.4.0rc03 + +version 1.4.0rc06 [December 29, 2009] + Reverted the gamma_table changes from libpng-1.4.0beta109. + Fixed some indentation errors. + +version 1.4.0rc07 [January 1, 2010] + Revised libpng*.txt and libpng.3 about 1.2.x->1.4.x differences. + Use png_calloc() instead of png_malloc(); png_memset() in pngrutil.c + Update copyright year to 2010. + +version 1.4.0rc08 [January 2, 2010] + Avoid deprecated references to png_ptr-io_ptr and png_ptr->error_ptr + in pngtest.c + +version 1.4.0 [January 3, 2010] + No changes. + +version 1.4.1beta01 [January 8, 2010] + Updated CMakeLists.txt for consistent indentation and to avoid an + unclosed if-statement warning (Philip Lowman). + Revised Makefile.am and Makefile.in to remove references to Y2KINFO, + KNOWNBUG, and libpng.la (Robert Schwebel). + Revised the makefiles to install the same files and symbolic + links as configure, except for libpng.la and libpng14.la. + Make png_set|get_compression_buffer_size() available even when + PNG_WRITE_SUPPORTED is not enabled. + Revised Makefile.am and Makefile.in to simplify their maintenance. + Revised scripts/makefile.linux to install a link to libpng14.so.14.1 + +version 1.4.1beta02 [January 9, 2010] + Revised the rest of the makefiles to install a link to libpng14.so.14.1 + +version 1.4.1beta03 [January 10, 2010] + Removed png_set_premultiply_alpha() from scripts/*.def + +version 1.4.1rc01 [January 16, 2010] + No changes. + +version 1.4.1beta04 [January 23, 2010] + Revised png_decompress_chunk() to improve speed and memory usage when + decoding large chunks. + Added png_set|get_chunk_malloc_max() functions. + +version 1.4.1beta05 [January 26, 2010] + Relocated "int k" declaration in pngtest.c to minimize its scope. + +version 1.4.1beta06 [January 28, 2010] + Revised png_decompress_chunk() to use a two-pass method suggested by + John Bowler. + +version 1.4.1beta07 [February 6, 2010] + Folded some long lines in the source files. + Added defineable PNG_USER_CHUNK_CACHE_MAX, PNG_USER_CHUNK_MALLOC_MAX, + and a PNG_USER_LIMITS_SUPPORTED flag. + Eliminated use of png_ptr->irowbytes and reused the slot in png_ptr as + png_ptr->png_user_chunk_malloc_max. + Revised png_push_save_buffer() to do fewer but larger png_malloc() calls. + +version 1.4.1beta08 [February 6, 2010] + Minor cleanup and updating of dates and copyright year. + +version 1.4.1beta09 [February 7, 2010] + Reverted to original png_push_save_buffer() code. + +version 1.4.1beta10 [February 9, 2010] + Return allocated "old_buffer" in png_push_save_buffer() before calling + png_error(), to avoid a potential memory leak. + +version 1.4.1beta11 [February 12, 2010] + Relocated misplaced closing curley bracket in png_decompress_chunk(). + Removed unused "buffer_size" variable from png_decompress_chunk(). + Removed the cbuilder5 project, which has not been updated to 1.4.0. + Complete rewrite of two-pass png_decompress_chunk() by John Bowler. + +version 1.4.1beta12 [February 14, 2010] + Fixed type declaration of png_get_user_malloc_max() in pngget.c (Daisuke + Nishikawa) + +version 1.4.1rc02 [January 18, 2010] + No changes. + +version 1.4.1rc03 [February 19, 2010] + Noted in scripts/makefile.mingw that it expects to be run under MSYS. + Removed obsolete unused MMX-querying support from contrib/gregbook + Removed the AIX redefinition of jmpbuf in png.h + Define _ALL_SOURCE in configure.ac, makefile.aix, and CMakeLists.txt + when using AIX compiler. + +version 1.4.1rc04 [February 19, 2010] + Removed unused gzio.c from contrib/pngminim gather and makefile scripts + +version 1.4.1 [February 25, 2010] + +version 1.4.2beta01 [April 1, 2010] + Conditionally compile an "else" statement in png_decompress_chunk(). + Restored the macro definition of png_check_sig(). + +version 1.4.2rc01 [April 10, 2010] + No changes. + +version 1.4.2rc02 [April 16, 2010] + Documented the fact that png_set_dither() was disabled since libpng-1.4.0. + Reenabled png_set_dither() but renamed it to png_set_quantize() to reflect + more accurately what it actually does. At the same time, renamed + the PNG_DITHER_[RED,GREEN_BLUE]_BITS macros to + PNG_QUANTIZE_[RED,GREEN,BLUE]_BITS. + +version 1.4.2rc03 [April 24, 2010] + Added some "(long)" typecasts to printf calls in png_handle_cHRM(). + Relaxed the overly-restrictive permissions of some files. + +version 1.4.2rc04 [April 28, 2010] + Added the "vstudio" project to replace "visualc6" and "visualc71" which + will be removed from libpng-1.5.0. + Demonstrate in example.c that lang_key should be initialized. + Set PNG_NO_READ_BGR, PNG_NO_IO_STATE, and PNG_NO_TIME_RFC1123 in + contrib/pngminim/decoder/pngusr.h to make a smaller decoder application. + +version 1.4.2rc05 [April 29, 2010] + Include png_reset_zstream() in png.c only when PNG_READ_SUPPORTED is defined. + Removed dummy_inflate.c and uncompr.c from contrib/pngminim/encoder + Corrected PNG_UNKNOWN_CHUNKS_SUPPORTED to PNG_HANDLE_AS_UNKNOWN_SUPPORTED + in gregbook/readpng2.c + Corrected protection of png_get_user_transform_ptr. The API declaration in + png.h is removed if both READ and WRITE USER_TRANSFORM are turned off + but was left defined in pngtrans.c + +version 1.4.2rc06 [May 3, 2010] + Moved declarations of umsg[] inside the proper #ifdef blocks in pngrutil.c + +version 1.4.2 [May 6, 2010] + +version 1.4.3beta01 [June 18, 2010] + Added missing quotation marks in the aix block of configure.ac + The new "vstudio" project was missing from the zip and 7z distributions. + In pngpread.c: png_push_have_row() add check for new_row > height + +version 1.4.3beta02 [June 18, 2010] + Removed the now-redundant check for out-of-bounds new_row from example.c + +version 1.4.3beta03 [June 18, 2010] + In pngpread.c: png_push_finish_row() add check for too many rows. + +version 1.4.3beta04 [June 19, 2010] + In pngpread.c: png_push_process_row() add check for too many rows. + Removed the checks added in beta01 and beta03, as they are now redundant. + +version 1.4.3beta05 [June 20, 2010] + Rewrote png_process_IDAT_data to consistently treat extra data as warnings + and handle end conditions more cleanly. + Removed the new (beta04) check in png_push_process_row(). + +version 1.4.3rc01 [June 21, 2010] + Revised some comments in png_process_IDAT_data(). + +version 1.4.3rc02 [June 22, 2010] + Changed char *msg to PNG_CONST char *msg in pngrutil.c + Stop memory leak when reading a malformed sCAL chunk. + Removed some trailing blanks. + +version 1.4.3rc03 [June 23, 2010] + Revised pngpread.c patch of beta05 to avoid an endless loop. + +version 1.4.3 [June 26, 2010] + Updated some of the "last changed" dates. + +Send comments/corrections/commendations to glennrp at users.sourceforge.net +or to png-mng-implement at lists.sf.net (subscription required; visit +https://lists.sourceforge.net/lists/listinfo/png-mng-implement). + +Glenn R-P +*/ } +#endif diff --git a/reactos/dll/3rdparty/libpng/docs/INSTALL b/reactos/dll/3rdparty/libpng/docs/INSTALL new file mode 100644 index 00000000000..584ac048eac --- /dev/null +++ b/reactos/dll/3rdparty/libpng/docs/INSTALL @@ -0,0 +1,143 @@ + +Installing libpng version 1.4.3 - June 26, 2010 + +On Unix/Linux and similar systems, you can simply type + + ./configure [--prefix=/path] + make check + make install + +and ignore the rest of this document. + +If configure does not work on your system and you have a reasonably +up-to-date set of tools, running ./autogen.sh before running ./configure +may fix the problem. You can also run the individual commands in +autogen.sh with the --force option, if supported by your version of +the tools. If you run 'libtoolize --force', though, this will replace +the distributed, patched, version of ltmain.sh with an unpatched version +and your shared library builds may fail to produce libraries with the +correct version numbers. + +Instead, you can use one of the custom-built makefiles in the +"scripts" directory + + cp scripts/makefile.system makefile + make test + make install + +The files that are presently available in the scripts directory +are listed and described in scripts/README.txt. + +Or you can use one of the "projects" in the "projects" directory. + +Before installing libpng, you must first install zlib, if it +is not already on your system. zlib can usually be found +wherever you got libpng. zlib can be placed in another directory, +at the same level as libpng. + +If you want to use "cmake" (see www.cmake.org), type + + cmake . -DCMAKE_INSTALL_PREFIX=/path + make + make install + +If your system already has a preinstalled zlib you will still need +to have access to the zlib.h and zconf.h include files that +correspond to the version of zlib that's installed. + +You can rename the directories that you downloaded (they +might be called "libpng-1.4.3" or "libpng14" and "zlib-1.2.3" +or "zlib123") so that you have directories called "zlib" and "libpng". + +Your directory structure should look like this: + + .. (the parent directory) + libpng (this directory) + INSTALL (this file) + README + *.h + *.c + CMakeLists.txt => "cmake" script + configuration files: + configure.ac, configure, Makefile.am, Makefile.in, + autogen.sh, config.guess, ltmain.sh, missing, libpng.pc.in, + libpng-config.in, aclocal.m4, config.h.in, config.sub, + depcomp, install-sh, mkinstalldirs, test-pngtest.sh + contrib + gregbook + pngminim + pngminus + pngsuite + visupng + projects + cbuilder5 (Borland) + visualc6 (msvc) + visualc71 + xcode + scripts + makefile.* + *.def (module definition files) + pngtest.png + etc. + zlib + README + *.h + *.c + contrib + etc. + +If the line endings in the files look funny, you may wish to get the other +distribution of libpng. It is available in both tar.gz (UNIX style line +endings) and zip (DOS style line endings) formats. + +If you are building libpng with MSVC, you can enter the +libpng projects\visualc6 or visualc71 directory and follow the instructions +in README.txt. + +Otherwise enter the zlib directory and follow the instructions in zlib/README, +then come back here and run "configure" or choose the appropriate +makefile.sys in the scripts directory. + +Copy the file (or files) that you need from the +scripts directory into this directory, for example + + MSDOS example: copy scripts\makefile.msc makefile + UNIX example: cp scripts/makefile.std makefile + +Read the makefile to see if you need to change any source or +target directories to match your preferences. + +Then read pngconf.h to see if you want to make any configuration +changes. + +Then just run "make" which will create the libpng library in +this directory and "make test" which will run a quick test that reads +the "pngtest.png" file and writes a "pngout.png" file that should be +identical to it. Look for "9782 zero samples" in the output of the +test. For more confidence, you can run another test by typing +"pngtest pngnow.png" and looking for "289 zero samples" in the output. +Also, you can run "pngtest -m contrib/pngsuite/*.png" and compare +your output with the result shown in contrib/pngsuite/README. + +Most of the makefiles will allow you to run "make install" to +put the library in its final resting place (if you want to +do that, run "make install" in the zlib directory first if necessary). +Some also allow you to run "make test-installed" after you have +run "make install". + +If you encounter a compiler error message complaining about the +lines + + __png.h__ already includes setjmp.h; + __dont__ include it again.; + +this means you have compiled another module that includes setjmp.h, +which is hazardous because the two modules might not include exactly +the same setjmp.h. If you are sure that you know what you are doing +and that they are exactly the same, then you can comment out or +delete the two lines. Better yet, use the cexcept interface +instead, as demonstrated in contrib/visupng of the libpng distribution. + +Further information can be found in the README and libpng.txt +files, in the individual makefiles, in png.h, and the manual pages +libpng.3 and png.5. diff --git a/reactos/dll/3rdparty/libpng/docs/LICENSE b/reactos/dll/3rdparty/libpng/docs/LICENSE new file mode 100644 index 00000000000..dd89a668478 --- /dev/null +++ b/reactos/dll/3rdparty/libpng/docs/LICENSE @@ -0,0 +1,111 @@ + +This copy of the libpng notices is provided for your convenience. In case of +any discrepancy between this copy and the notices in the file png.h that is +included in the libpng distribution, the latter shall prevail. + +COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: + +If you modify libpng you may insert additional notices immediately following +this sentence. + +This code is released under the libpng license. + +libpng versions 1.2.6, August 15, 2004, through 1.4.3, June 26, 2010, are +Copyright (c) 2004, 2006-2007 Glenn Randers-Pehrson, and are +distributed according to the same disclaimer and license as libpng-1.2.5 +with the following individual added to the list of Contributing Authors + + Cosmin Truta + +libpng versions 1.0.7, July 1, 2000, through 1.2.5 - October 3, 2002, are +Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are +distributed according to the same disclaimer and license as libpng-1.0.6 +with the following individuals added to the list of Contributing Authors + + Simon-Pierre Cadieux + Eric S. Raymond + Gilles Vollant + +and with the following additions to the disclaimer: + + There is no warranty against interference with your enjoyment of the + library or against infringement. There is no warranty that our + efforts or the library will fulfill any of your particular purposes + or needs. This library is provided with all faults, and the entire + risk of satisfactory quality, performance, accuracy, and effort is with + the user. + +libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are +Copyright (c) 1998, 1999 Glenn Randers-Pehrson, and are +distributed according to the same disclaimer and license as libpng-0.96, +with the following individuals added to the list of Contributing Authors: + + Tom Lane + Glenn Randers-Pehrson + Willem van Schaik + +libpng versions 0.89, June 1996, through 0.96, May 1997, are +Copyright (c) 1996, 1997 Andreas Dilger +Distributed according to the same disclaimer and license as libpng-0.88, +with the following individuals added to the list of Contributing Authors: + + John Bowler + Kevin Bracey + Sam Bushell + Magnus Holmgren + Greg Roelofs + Tom Tanner + +libpng versions 0.5, May 1995, through 0.88, January 1996, are +Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. + +For the purposes of this copyright and license, "Contributing Authors" +is defined as the following set of individuals: + + Andreas Dilger + Dave Martindale + Guy Eric Schalnat + Paul Schmidt + Tim Wegner + +The PNG Reference Library is supplied "AS IS". The Contributing Authors +and Group 42, Inc. disclaim all warranties, expressed or implied, +including, without limitation, the warranties of merchantability and of +fitness for any purpose. The Contributing Authors and Group 42, Inc. +assume no liability for direct, indirect, incidental, special, exemplary, +or consequential damages, which may result from the use of the PNG +Reference Library, even if advised of the possibility of such damage. + +Permission is hereby granted to use, copy, modify, and distribute this +source code, or portions hereof, for any purpose, without fee, subject +to the following restrictions: + +1. The origin of this source code must not be misrepresented. + +2. Altered versions must be plainly marked as such and must not + be misrepresented as being the original source. + +3. This Copyright notice may not be removed or altered from any + source or altered source distribution. + +The Contributing Authors and Group 42, Inc. specifically permit, without +fee, and encourage the use of this source code as a component to +supporting the PNG file format in commercial products. If you use this +source code in a product, acknowledgment is not required but would be +appreciated. + + +A "png_get_copyright" function is available, for convenient use in "about" +boxes and the like: + + printf("%s",png_get_copyright(NULL)); + +Also, the PNG logo (in PNG format, of course) is supplied in the +files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31). + +Libpng is OSI Certified Open Source Software. OSI Certified Open Source is a +certification mark of the Open Source Initiative. + +Glenn Randers-Pehrson +glennrp at users.sourceforge.net +June 26, 2010 diff --git a/reactos/dll/3rdparty/libpng/docs/README b/reactos/dll/3rdparty/libpng/docs/README new file mode 100644 index 00000000000..799f3ebe022 --- /dev/null +++ b/reactos/dll/3rdparty/libpng/docs/README @@ -0,0 +1,257 @@ +README for libpng version 1.4.3 - June 26, 2010 (shared library 14.0) +See the note about version numbers near the top of png.h + +See INSTALL for instructions on how to install libpng. + +Libpng comes in several distribution formats. Get libpng-*.tar.gz, +libpng-*.tar.xz or libpng-*.tar.bz2 if you want UNIX-style line endings +in the text files, or lpng*.zip if you want DOS-style line endings. + +Version 0.89 was the first official release of libpng. Don't let the +fact that it's the first release fool you. The libpng library has been in +extensive use and testing since mid-1995. By late 1997 it had +finally gotten to the stage where there hadn't been significant +changes to the API in some time, and people have a bad feeling about +libraries with versions < 1.0. Version 1.0.0 was released in +March 1998. + +**** +Note that some of the changes to the png_info structure render this +version of the library binary incompatible with libpng-0.89 or +earlier versions if you are using a shared library. The type of the +"filler" parameter for png_set_filler() has changed from png_byte to +png_uint_32, which will affect shared-library applications that use +this function. + +To avoid problems with changes to the internals of png_info_struct, +new APIs have been made available in 0.95 to avoid direct application +access to info_ptr. These functions are the png_set_ and +png_get_ functions. These functions should be used when +accessing/storing the info_struct data, rather than manipulating it +directly, to avoid such problems in the future. + +It is important to note that the APIs do not make current programs +that access the info struct directly incompatible with the new +library. However, it is strongly suggested that new programs use +the new APIs (as shown in example.c and pngtest.c), and older programs +be converted to the new format, to facilitate upgrades in the future. +**** + +Additions since 0.90 include the ability to compile libpng as a +Windows DLL, and new APIs for accessing data in the info struct. +Experimental functions include the ability to set weighting and cost +factors for row filter selection, direct reads of integers from buffers +on big-endian processors that support misaligned data access, faster +methods of doing alpha composition, and more accurate 16->8 bit color +conversion. + +The additions since 0.89 include the ability to read from a PNG stream +which has had some (or all) of the signature bytes read by the calling +application. This also allows the reading of embedded PNG streams that +do not have the PNG file signature. As well, it is now possible to set +the library action on the detection of chunk CRC errors. It is possible +to set different actions based on whether the CRC error occurred in a +critical or an ancillary chunk. + +The changes made to the library, and bugs fixed are based on discussions +on the PNG-implement mailing list and not on material submitted +privately to Guy, Andreas, or Glenn. They will forward any good +suggestions to the list. + +For a detailed description on using libpng, read libpng.txt. For +examples of libpng in a program, see example.c and pngtest.c. For usage +information and restrictions (what little they are) on libpng, see +png.h. For a description on using zlib (the compression library used by +libpng) and zlib's restrictions, see zlib.h + +I have included a general makefile, as well as several machine and +compiler specific ones, but you may have to modify one for your own needs. + +You should use zlib 1.0.4 or later to run this, but it MAY work with +versions as old as zlib 0.95. Even so, there are bugs in older zlib +versions which can cause the output of invalid compression streams for +some images. You will definitely need zlib 1.0.4 or later if you are +taking advantage of the MS-DOS "far" structure allocation for the small +and medium memory models. You should also note that zlib is a +compression library that is useful for more things than just PNG files. +You can use zlib as a drop-in replacement for fread() and fwrite() if +you are so inclined. + +zlib should be available at the same place that libpng is, or at. +ftp://ftp.info-zip.org/pub/infozip/zlib + +You may also want a copy of the PNG specification. It is available +as an RFC, a W3C Recommendation, and an ISO/IEC Standard. You can find +these at http://www.libpng.org/pub/png/documents/ + +This code is currently being archived at libpng.sf.net in the +[DOWNLOAD] area, and on CompuServe, Lib 20 (PNG SUPPORT) +at GO GRAPHSUP. If you can't find it in any of those places, +e-mail me, and I'll help you find it. + +If you have any code changes, requests, problems, etc., please e-mail +them to me. Also, I'd appreciate any make files or project files, +and any modifications you needed to make to get libpng to compile, +along with a #define variable to tell what compiler/system you are on. +If you needed to add transformations to libpng, or wish libpng would +provide the image in a different way, drop me a note (and code, if +possible), so I can consider supporting the transformation. +Finally, if you get any warning messages when compiling libpng +(note: not zlib), and they are easy to fix, I'd appreciate the +fix. Please mention "libpng" somewhere in the subject line. Thanks. + +This release was created and will be supported by myself (of course +based in a large way on Guy's and Andreas' earlier work), and the PNG +development group. + +Send comments/corrections/commendations to png-mng-implement at +lists.sourceforge.net (subscription required; visit +https://lists.sourceforge.net/lists/listinfo/png-mng-implement +to subscribe) or to glennrp at users.sourceforge.net + +You can't reach Guy, the original libpng author, at the addresses +given in previous versions of this document. He and Andreas will +read mail addressed to the png-implement list, however. + +Please do not send general questions about PNG. Send them to +the (png-list at ccrc.wustl.edu, subscription required, write to +majordomo at ccrc.wustl.edu with "subscribe png-list" in your message). +On the other hand, +please do not send libpng questions to that address, send them to me +or to the png-implement list. I'll +get them in the end anyway. If you have a question about something +in the PNG specification that is related to using libpng, send it +to me. Send me any questions that start with "I was using libpng, +and ...". If in doubt, send questions to me. I'll bounce them +to others, if necessary. + +Please do not send suggestions on how to change PNG. We have +been discussing PNG for nine years now, and it is official and +finished. If you have suggestions for libpng, however, I'll +gladly listen. Even if your suggestion is not used immediately, +it may be used later. + +Files in this distribution: + + ANNOUNCE => Announcement of this version, with recent changes + CHANGES => Description of changes between libpng versions + KNOWNBUG => List of known bugs and deficiencies + LICENSE => License to use and redistribute libpng + README => This file + TODO => Things not implemented in the current library + Y2KINFO => Statement of Y2K compliance + example.c => Example code for using libpng functions + libpng.3 => manual page for libpng (includes libpng.txt) + libpng.txt => Description of libpng and its functions + libpngpf.3 => manual page for libpng's private functions + png.5 => manual page for the PNG format + png.c => Basic interface functions common to library + png.h => Library function and interface declarations + pngconf.h => System specific library configuration + pngerror.c => Error/warning message I/O functions + pngget.c => Functions for retrieving info from struct + pngmem.c => Memory handling functions + pngbar.png => PNG logo, 88x31 + pngnow.png => PNG logo, 98x31 + pngpread.c => Progressive reading functions + pngread.c => Read data/helper high-level functions + pngrio.c => Lowest-level data read I/O functions + pngrtran.c => Read data transformation functions + pngrutil.c => Read data utility functions + pngset.c => Functions for storing data into the info_struct + pngtest.c => Library test program + pngtest.png => Library test sample image + pngtrans.c => Common data transformation functions + pngwio.c => Lowest-level write I/O functions + pngwrite.c => High-level write functions + pngwtran.c => Write data transformations + pngwutil.c => Write utility functions + contrib => Contributions + gregbook => source code for PNG reading and writing, from + Greg Roelofs' "PNG: The Definitive Guide", + O'Reilly, 1999 + msvctest => Builds and runs pngtest using a MSVC workspace + pngminus => Simple pnm2png and png2pnm programs + pngsuite => Test images + visupng => Contains a MSVC workspace for VisualPng + projects => Contains project files and workspaces for + building a DLL + c5builder => Contains a Borland workspace for building + libpng and zlib + visualc6 => Contains a Microsoft Visual C++ (MSVC) + workspace for building libpng and zlib + scripts => Directory containing scripts for building libpng: + descrip.mms => VMS makefile for MMS or MMK + makefile.std => Generic UNIX makefile (cc, creates static + libpng.a) + makefile.elf => Linux/ELF makefile symbol versioning, + gcc, creates libpng14.so.14.1.4.3) + makefile.linux => Linux/ELF makefile + (gcc, creates libpng14.so.14.1.4.3) + makefile.gcc => Generic makefile (gcc, creates static libpng.a) + makefile.knr => Archaic UNIX Makefile that converts files with + ansi2knr (Requires ansi2knr.c from + ftp://ftp.cs.wisc.edu/ghost) + makefile.aix => AIX makefile + makefile.cygwin => Cygwin/gcc makefile + makefile.darwin => Darwin makefile + makefile.dec => DEC Alpha UNIX makefile + makefile.freebsd => FreeBSD makefile + makefile.hpgcc => HPUX makefile using gcc + makefile.hpux => HPUX (10.20 and 11.00) makefile + makefile.hp64 => HPUX (10.20 and 11.00) makefile, 64 bit + makefile.ibmc => IBM C/C++ version 3.x for Win32 and OS/2 (static) + makefile.intel => Intel C/C++ version 4.0 and later + makefile.mingw => Mingw/gcc makefile + makefile.netbsd => NetBSD/cc makefile, makes libpng.so. + makefile.ne14bsd => NetBSD/cc makefile, makes + libpng14.so + makefile.openbsd => OpenBSD makefile + makefile.sgi => Silicon Graphics IRIX (cc, creates static lib) + makefile.sggcc => Silicon Graphics + (gcc, creates libpng14.so.14.1.4.3) + makefile.sunos => Sun makefile + makefile.solaris => Solaris 2.X makefile + (gcc, creates libpng14.so.14.1.4.3) + makefile.so9 => Solaris 9 makefile + (gcc, creates libpng14.so.14.1.4.3) + makefile.32sunu => Sun Ultra 32-bit makefile + makefile.64sunu => Sun Ultra 64-bit makefile + makefile.sco => For SCO OSr5 ELF and Unixware 7 with Native cc + makefile.mips => MIPS makefile + makefile.acorn => Acorn makefile + makefile.amiga => Amiga makefile + smakefile.ppc => AMIGA smakefile for SAS C V6.58/7.00 PPC + compiler (Requires SCOPTIONS, copied from + scripts/SCOPTIONS.ppc) + makefile.atari => Atari makefile + makefile.beos => BEOS makefile for X86 + makefile.bor => Borland makefile (uses bcc) + makefile.bc32 => 32-bit Borland C++ (all modules compiled in C mode) + makefile.tc3 => Turbo C 3.0 makefile + makefile.dj2 => DJGPP 2 makefile + makefile.msc => Microsoft C makefile + makefile.vcwin32 => makefile for Microsoft Visual C++ 4.0 and + later (does not use assembler code) + makefile.os2 => OS/2 Makefile (gcc and emx, requires pngos2.def) + png32ce.def => module definition for makefile.cegccg + pngos2.def => OS/2 module definition file used by + makefile.os2 + pngwin.def => module definition file used by + makefile.cygwin and makefile.mingw + makefile.watcom => Watcom 10a+ Makefile, 32-bit flat memory model + makevms.com => VMS build script + SCOPTIONS.ppc => Used with smakefile.ppc + +Good luck, and happy coding. + +-Glenn Randers-Pehrson (current maintainer, since 1998) + Internet: glennrp at users.sourceforge.net + +-Andreas Eric Dilger (former maintainer, 1996-1997) + Internet: adilger at enel.ucalgary.ca + Web: http://www-mddsp.enel.ucalgary.ca/People/adilger/ + +-Guy Eric Schalnat (original author and former maintainer, 1995-1996) + (formerly of Group 42, Inc) + Internet: gschal at infinet.com diff --git a/reactos/dll/3rdparty/libpng/docs/TODO b/reactos/dll/3rdparty/libpng/docs/TODO new file mode 100644 index 00000000000..0af8d827a46 --- /dev/null +++ b/reactos/dll/3rdparty/libpng/docs/TODO @@ -0,0 +1,31 @@ +/* +TODO - list of things to do for libpng: + +Final bug fixes. +Improve API by hiding the png_struct and png_info structs. +Finish work on the no-floating-point version (including gamma compensation) +Better C++ wrapper/full C++ implementation? +Fix problem with C++ and EXTERN "C". +cHRM transformation. +Improve setjmp/longjmp usage or remove it in favor of returning error codes. +Add "grayscale->palette" transformation and "palette->grayscale" detection. +Improved quantizing and dithering. +Multi-lingual error and warning message support. +Complete sRGB transformation (presently it simply uses gamma=0.45455). +Man pages for function calls. +Better documentation. +Better filter selection + (counting huffman bits/precompression? filter inertia? filter costs?). +Histogram creation. +Text conversion between different code pages (Latin-1 -> Mac and DOS). +Build gamma tables using fixed point (and do away with floating point entirely). +Avoid building gamma tables whenever possible. +Use greater precision when changing to linear gamma for compositing against + background and doing rgb-to-gray transformation. +Investigate pre-incremented loop counters and other loop constructions. +Add interpolated method of handling interlacing. +Provide for conditional compilation of 16-bit support (except for the + initial stripping down to 8-bits when reading a 16-bit PNG datastream). +Switch to the simpler zlib (zlib/libpng) license if legally possible. + +*/ diff --git a/reactos/dll/3rdparty/libpng/docs/example.c b/reactos/dll/3rdparty/libpng/docs/example.c new file mode 100644 index 00000000000..d7391734de1 --- /dev/null +++ b/reactos/dll/3rdparty/libpng/docs/example.c @@ -0,0 +1,838 @@ + +#if 0 /* in case someone actually tries to compile this */ + +/* example.c - an example of using libpng + * Last changed in libpng 1.4.2 [May 6, 2010] + * This file has been placed in the public domain by the authors. + * Maintained 1998-2010 Glenn Randers-Pehrson + * Maintained 1996, 1997 Andreas Dilger) + * Written 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + */ + +/* This is an example of how to use libpng to read and write PNG files. + * The file libpng.txt is much more verbose then this. If you have not + * read it, do so first. This was designed to be a starting point of an + * implementation. This is not officially part of libpng, is hereby placed + * in the public domain, and therefore does not require a copyright notice. + * + * This file does not currently compile, because it is missing certain + * parts, like allocating memory to hold an image. You will have to + * supply these parts to get it to compile. For an example of a minimal + * working PNG reader/writer, see pngtest.c, included in this distribution; + * see also the programs in the contrib directory. + */ + +#include "png.h" + + /* The png_jmpbuf() macro, used in error handling, became available in + * libpng version 1.0.6. If you want to be able to run your code with older + * versions of libpng, you must define the macro yourself (but only if it + * is not already defined by libpng!). + */ + +#ifndef png_jmpbuf +# define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) +#endif + +/* Check to see if a file is a PNG file using png_sig_cmp(). png_sig_cmp() + * returns zero if the image is a PNG and nonzero if it isn't a PNG. + * + * The function check_if_png() shown here, but not used, returns nonzero (true) + * if the file can be opened and is a PNG, 0 (false) otherwise. + * + * If this call is successful, and you are going to keep the file open, + * you should call png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK); once + * you have created the png_ptr, so that libpng knows your application + * has read that many bytes from the start of the file. Make sure you + * don't call png_set_sig_bytes() with more than 8 bytes read or give it + * an incorrect number of bytes read, or you will either have read too + * many bytes (your fault), or you are telling libpng to read the wrong + * number of magic bytes (also your fault). + * + * Many applications already read the first 2 or 4 bytes from the start + * of the image to determine the file type, so it would be easiest just + * to pass the bytes to png_sig_cmp() or even skip that if you know + * you have a PNG file, and call png_set_sig_bytes(). + */ +#define PNG_BYTES_TO_CHECK 4 +int check_if_png(char *file_name, FILE **fp) +{ + char buf[PNG_BYTES_TO_CHECK]; + + /* Open the prospective PNG file. */ + if ((*fp = fopen(file_name, "rb")) == NULL) + return 0; + + /* Read in some of the signature bytes */ + if (fread(buf, 1, PNG_BYTES_TO_CHECK, *fp) != PNG_BYTES_TO_CHECK) + return 0; + + /* Compare the first PNG_BYTES_TO_CHECK bytes of the signature. + Return nonzero (true) if they match */ + + return(!png_sig_cmp(buf, (png_size_t)0, PNG_BYTES_TO_CHECK)); +} + +/* Read a PNG file. You may want to return an error code if the read + * fails (depending upon the failure). There are two "prototypes" given + * here - one where we are given the filename, and we need to open the + * file, and the other where we are given an open file (possibly with + * some or all of the magic bytes read - see comments above). + */ +#ifdef open_file /* prototype 1 */ +void read_png(char *file_name) /* We need to open the file */ +{ + png_structp png_ptr; + png_infop info_ptr; + unsigned int sig_read = 0; + png_uint_32 width, height; + int bit_depth, color_type, interlace_type; + FILE *fp; + + if ((fp = fopen(file_name, "rb")) == NULL) + return (ERROR); + +#else no_open_file /* prototype 2 */ +void read_png(FILE *fp, unsigned int sig_read) /* File is already open */ +{ + png_structp png_ptr; + png_infop info_ptr; + png_uint_32 width, height; + int bit_depth, color_type, interlace_type; +#endif no_open_file /* Only use one prototype! */ + + /* Create and initialize the png_struct with the desired error handler + * functions. If you want to use the default stderr and longjump method, + * you can supply NULL for the last three parameters. We also supply the + * the compiler header file version, so that we know if the application + * was compiled with a compatible version of the library. REQUIRED + */ + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, + png_voidp user_error_ptr, user_error_fn, user_warning_fn); + + if (png_ptr == NULL) + { + fclose(fp); + return (ERROR); + } + + /* Allocate/initialize the memory for image information. REQUIRED. */ + info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) + { + fclose(fp); + png_destroy_read_struct(&png_ptr, NULL, NULL); + return (ERROR); + } + + /* Set error handling if you are using the setjmp/longjmp method (this is + * the normal method of doing things with libpng). REQUIRED unless you + * set up your own error handlers in the png_create_read_struct() earlier. + */ + + if (setjmp(png_jmpbuf(png_ptr))) + { + /* Free all of the memory associated with the png_ptr and info_ptr */ + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + fclose(fp); + /* If we get here, we had a problem reading the file */ + return (ERROR); + } + + /* One of the following I/O initialization methods is REQUIRED */ +#ifdef streams /* PNG file I/O method 1 */ + /* Set up the input control if you are using standard C streams */ + png_init_io(png_ptr, fp); + +#else no_streams /* PNG file I/O method 2 */ + /* If you are using replacement read functions, instead of calling + * png_init_io() here you would call: + */ + png_set_read_fn(png_ptr, (void *)user_io_ptr, user_read_fn); + /* where user_io_ptr is a structure you want available to the callbacks */ +#endif no_streams /* Use only one I/O method! */ + + /* If we have already read some of the signature */ + png_set_sig_bytes(png_ptr, sig_read); + +#ifdef hilevel + /* + * If you have enough memory to read in the entire image at once, + * and you need to specify only transforms that can be controlled + * with one of the PNG_TRANSFORM_* bits (this presently excludes + * quantizing, filling, setting background, and doing gamma + * adjustment), then you can read the entire image (including + * pixels) into the info structure with this call: + */ + png_read_png(png_ptr, info_ptr, png_transforms, NULL); + +#else + /* OK, you're doing it the hard way, with the lower-level functions */ + + /* The call to png_read_info() gives us all of the information from the + * PNG file before the first IDAT (image data chunk). REQUIRED + */ + png_read_info(png_ptr, info_ptr); + + png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, + &interlace_type, NULL, NULL); + + /* Set up the data transformations you want. Note that these are all + * optional. Only call them if you want/need them. Many of the + * transformations only work on specific types of images, and many + * are mutually exclusive. + */ + + /* Tell libpng to strip 16 bit/color files down to 8 bits/color */ + png_set_strip_16(png_ptr); + + /* Strip alpha bytes from the input data without combining with the + * background (not recommended). + */ + png_set_strip_alpha(png_ptr); + + /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single + * byte into separate bytes (useful for paletted and grayscale images). + */ + png_set_packing(png_ptr); + + /* Change the order of packed pixels to least significant bit first + * (not useful if you are using png_set_packing). */ + png_set_packswap(png_ptr); + + /* Expand paletted colors into true RGB triplets */ + if (color_type == PNG_COLOR_TYPE_PALETTE) + png_set_palette_to_rgb(png_ptr); + + /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */ + if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) + png_set_expand_gray_1_2_4_to_8(png_ptr); + + /* Expand paletted or RGB images with transparency to full alpha channels + * so the data will be available as RGBA quartets. + */ + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) + png_set_tRNS_to_alpha(png_ptr); + + /* Set the background color to draw transparent and alpha images over. + * It is possible to set the red, green, and blue components directly + * for paletted images instead of supplying a palette index. Note that + * even if the PNG file supplies a background, you are not required to + * use it - you should use the (solid) application background if it has one. + */ + + png_color_16 my_background, *image_background; + + if (png_get_bKGD(png_ptr, info_ptr, &image_background)) + png_set_background(png_ptr, image_background, + PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); + else + png_set_background(png_ptr, &my_background, + PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); + + /* Some suggestions as to how to get a screen gamma value + * + * Note that screen gamma is the display_exponent, which includes + * the CRT_exponent and any correction for viewing conditions + */ + if (/* We have a user-defined screen gamma value */) + { + screen_gamma = user-defined screen_gamma; + } + /* This is one way that applications share the same screen gamma value */ + else if ((gamma_str = getenv("SCREEN_GAMMA")) != NULL) + { + screen_gamma = atof(gamma_str); + } + /* If we don't have another value */ + else + { + screen_gamma = 2.2; /* A good guess for a PC monitor in a dimly + lit room */ + screen_gamma = 1.7 or 1.0; /* A good guess for Mac systems */ + } + + /* Tell libpng to handle the gamma conversion for you. The final call + * is a good guess for PC generated images, but it should be configurable + * by the user at run time by the user. It is strongly suggested that + * your application support gamma correction. + */ + + int intent; + + if (png_get_sRGB(png_ptr, info_ptr, &intent)) + png_set_gamma(png_ptr, screen_gamma, 0.45455); + else + { + double image_gamma; + if (png_get_gAMA(png_ptr, info_ptr, &image_gamma)) + png_set_gamma(png_ptr, screen_gamma, image_gamma); + else + png_set_gamma(png_ptr, screen_gamma, 0.45455); + } + +#ifdef PNG_READ_QUANTIZE_SUPPORTED + /* Quantize RGB files down to 8 bit palette or reduce palettes + * to the number of colors available on your screen. + */ + if (color_type & PNG_COLOR_MASK_COLOR) + { + int num_palette; + png_colorp palette; + + /* This reduces the image to the application supplied palette */ + if (/* We have our own palette */) + { + /* An array of colors to which the image should be quantized */ + png_color std_color_cube[MAX_SCREEN_COLORS]; + + /* Prior to libpng-1.4.2, this was png_set_dither(). */ + png_set_quantize(png_ptr, std_color_cube, MAX_SCREEN_COLORS, + MAX_SCREEN_COLORS, NULL, 0); + } + /* This reduces the image to the palette supplied in the file */ + else if (png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette)) + { + png_uint_16p histogram = NULL; + + png_get_hIST(png_ptr, info_ptr, &histogram); + + png_set_quantize(png_ptr, palette, num_palette, + max_screen_colors, histogram, 0); + } + } +#endif /* PNG_READ_QUANTIZE_SUPPORTED */ + + /* Invert monochrome files to have 0 as white and 1 as black */ + png_set_invert_mono(png_ptr); + + /* If you want to shift the pixel values from the range [0,255] or + * [0,65535] to the original [0,7] or [0,31], or whatever range the + * colors were originally in: + */ + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT)) + { + png_color_8p sig_bit_p; + + png_get_sBIT(png_ptr, info_ptr, &sig_bit_p); + png_set_shift(png_ptr, sig_bit_p); + } + + /* Flip the RGB pixels to BGR (or RGBA to BGRA) */ + if (color_type & PNG_COLOR_MASK_COLOR) + png_set_bgr(png_ptr); + + /* Swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */ + png_set_swap_alpha(png_ptr); + + /* Swap bytes of 16 bit files to least significant byte first */ + png_set_swap(png_ptr); + + /* Add filler (or alpha) byte (before/after each RGB triplet) */ + png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); + + /* Turn on interlace handling. REQUIRED if you are not using + * png_read_image(). To see how to handle interlacing passes, + * see the png_read_row() method below: + */ + number_passes = png_set_interlace_handling(png_ptr); + + /* Optional call to gamma correct and add the background to the palette + * and update info structure. REQUIRED if you are expecting libpng to + * update the palette for you (ie you selected such a transform above). + */ + png_read_update_info(png_ptr, info_ptr); + + /* Allocate the memory to hold the image using the fields of info_ptr. */ + + /* The easiest way to read the image: */ + png_bytep row_pointers[height]; + + /* Clear the pointer array */ + for (row = 0; row < height; row++) + row_pointers[row] = NULL; + + for (row = 0; row < height; row++) + row_pointers[row] = png_malloc(png_ptr, png_get_rowbytes(png_ptr, + info_ptr)); + + /* Now it's time to read the image. One of these methods is REQUIRED */ +#ifdef entire /* Read the entire image in one go */ + png_read_image(png_ptr, row_pointers); + +#else no_entire /* Read the image one or more scanlines at a time */ + /* The other way to read images - deal with interlacing: */ + + for (pass = 0; pass < number_passes; pass++) + { +#ifdef single /* Read the image a single row at a time */ + for (y = 0; y < height; y++) + { + png_read_rows(png_ptr, &row_pointers[y], NULL, 1); + } + +#else no_single /* Read the image several rows at a time */ + for (y = 0; y < height; y += number_of_rows) + { +#ifdef sparkle /* Read the image using the "sparkle" effect. */ + png_read_rows(png_ptr, &row_pointers[y], NULL, + number_of_rows); +#else no_sparkle /* Read the image using the "rectangle" effect */ + png_read_rows(png_ptr, NULL, &row_pointers[y], + number_of_rows); +#endif no_sparkle /* Use only one of these two methods */ + } + + /* If you want to display the image after every pass, do so here */ +#endif no_single /* Use only one of these two methods */ + } +#endif no_entire /* Use only one of these two methods */ + + /* Read rest of file, and get additional chunks in info_ptr - REQUIRED */ + png_read_end(png_ptr, info_ptr); +#endif hilevel + + /* At this point you have read the entire image */ + + /* Clean up after the read, and free any memory allocated - REQUIRED */ + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + + /* Close the file */ + fclose(fp); + + /* That's it */ + return (OK); +} + +/* Progressively read a file */ + +int +initialize_png_reader(png_structp *png_ptr, png_infop *info_ptr) +{ + /* Create and initialize the png_struct with the desired error handler + * functions. If you want to use the default stderr and longjump method, + * you can supply NULL for the last three parameters. We also check that + * the library version is compatible in case we are using dynamically + * linked libraries. + */ + *png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, + png_voidp user_error_ptr, user_error_fn, user_warning_fn); + + if (*png_ptr == NULL) + { + *info_ptr = NULL; + return (ERROR); + } + + *info_ptr = png_create_info_struct(png_ptr); + + if (*info_ptr == NULL) + { + png_destroy_read_struct(png_ptr, info_ptr, NULL); + return (ERROR); + } + + if (setjmp(png_jmpbuf((*png_ptr)))) + { + png_destroy_read_struct(png_ptr, info_ptr, NULL); + return (ERROR); + } + + /* This one's new. You will need to provide all three + * function callbacks, even if you aren't using them all. + * If you aren't using all functions, you can specify NULL + * parameters. Even when all three functions are NULL, + * you need to call png_set_progressive_read_fn(). + * These functions shouldn't be dependent on global or + * static variables if you are decoding several images + * simultaneously. You should store stream specific data + * in a separate struct, given as the second parameter, + * and retrieve the pointer from inside the callbacks using + * the function png_get_progressive_ptr(png_ptr). + */ + png_set_progressive_read_fn(*png_ptr, (void *)stream_data, + info_callback, row_callback, end_callback); + + return (OK); +} + +int +process_data(png_structp *png_ptr, png_infop *info_ptr, + png_bytep buffer, png_uint_32 length) +{ + if (setjmp(png_jmpbuf((*png_ptr)))) + { + /* Free the png_ptr and info_ptr memory on error */ + png_destroy_read_struct(png_ptr, info_ptr, NULL); + return (ERROR); + } + + /* This one's new also. Simply give it chunks of data as + * they arrive from the data stream (in order, of course). + * On segmented machines, don't give it any more than 64K. + * The library seems to run fine with sizes of 4K, although + * you can give it much less if necessary (I assume you can + * give it chunks of 1 byte, but I haven't tried with less + * than 256 bytes yet). When this function returns, you may + * want to display any rows that were generated in the row + * callback, if you aren't already displaying them there. + */ + png_process_data(*png_ptr, *info_ptr, buffer, length); + return (OK); +} + +info_callback(png_structp png_ptr, png_infop info) +{ + /* Do any setup here, including setting any of the transformations + * mentioned in the Reading PNG files section. For now, you _must_ + * call either png_start_read_image() or png_read_update_info() + * after all the transformations are set (even if you don't set + * any). You may start getting rows before png_process_data() + * returns, so this is your last chance to prepare for that. + */ +} + +row_callback(png_structp png_ptr, png_bytep new_row, + png_uint_32 row_num, int pass) +{ + /* + * This function is called for every row in the image. If the + * image is interlaced, and you turned on the interlace handler, + * this function will be called for every row in every pass. + * + * In this function you will receive a pointer to new row data from + * libpng called new_row that is to replace a corresponding row (of + * the same data format) in a buffer allocated by your application. + * + * The new row data pointer "new_row" may be NULL, indicating there is + * no new data to be replaced (in cases of interlace loading). + * + * If new_row is not NULL then you need to call + * png_progressive_combine_row() to replace the corresponding row as + * shown below: + */ + + /* Get pointer to corresponding row in our + * PNG read buffer. + */ + png_bytep old_row = ((png_bytep *)our_data)[row_num]; + + /* If both rows are allocated then copy the new row + * data to the corresponding row data. + */ + if ((old_row != NULL) && (new_row != NULL)) + png_progressive_combine_row(png_ptr, old_row, new_row); + + /* + * The rows and passes are called in order, so you don't really + * need the row_num and pass, but I'm supplying them because it + * may make your life easier. + * + * For the non-NULL rows of interlaced images, you must call + * png_progressive_combine_row() passing in the new row and the + * old row, as demonstrated above. You can call this function for + * NULL rows (it will just return) and for non-interlaced images + * (it just does the png_memcpy for you) if it will make the code + * easier. Thus, you can just do this for all cases: + */ + + png_progressive_combine_row(png_ptr, old_row, new_row); + + /* where old_row is what was displayed for previous rows. Note + * that the first pass (pass == 0 really) will completely cover + * the old row, so the rows do not have to be initialized. After + * the first pass (and only for interlaced images), you will have + * to pass the current row as new_row, and the function will combine + * the old row and the new row. + */ +} + +end_callback(png_structp png_ptr, png_infop info) +{ + /* This function is called when the whole image has been read, + * including any chunks after the image (up to and including + * the IEND). You will usually have the same info chunk as you + * had in the header, although some data may have been added + * to the comments and time fields. + * + * Most people won't do much here, perhaps setting a flag that + * marks the image as finished. + */ +} + +/* Write a png file */ +void write_png(char *file_name /* , ... other image information ... */) +{ + FILE *fp; + png_structp png_ptr; + png_infop info_ptr; + png_colorp palette; + + /* Open the file */ + fp = fopen(file_name, "wb"); + if (fp == NULL) + return (ERROR); + + /* Create and initialize the png_struct with the desired error handler + * functions. If you want to use the default stderr and longjump method, + * you can supply NULL for the last three parameters. We also check that + * the library version is compatible with the one used at compile time, + * in case we are using dynamically linked libraries. REQUIRED. + */ + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, + png_voidp user_error_ptr, user_error_fn, user_warning_fn); + + if (png_ptr == NULL) + { + fclose(fp); + return (ERROR); + } + + /* Allocate/initialize the image information data. REQUIRED */ + info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) + { + fclose(fp); + png_destroy_write_struct(&png_ptr, NULL); + return (ERROR); + } + + /* Set error handling. REQUIRED if you aren't supplying your own + * error handling functions in the png_create_write_struct() call. + */ + if (setjmp(png_jmpbuf(png_ptr))) + { + /* If we get here, we had a problem writing the file */ + fclose(fp); + png_destroy_write_struct(&png_ptr, &info_ptr); + return (ERROR); + } + + /* One of the following I/O initialization functions is REQUIRED */ + +#ifdef streams /* I/O initialization method 1 */ + /* Set up the output control if you are using standard C streams */ + png_init_io(png_ptr, fp); + +#else no_streams /* I/O initialization method 2 */ + /* If you are using replacement write functions, instead of calling + * png_init_io() here you would call + */ + png_set_write_fn(png_ptr, (void *)user_io_ptr, user_write_fn, + user_IO_flush_function); + /* where user_io_ptr is a structure you want available to the callbacks */ +#endif no_streams /* Only use one initialization method */ + +#ifdef hilevel + /* This is the easy way. Use it if you already have all the + * image info living in the structure. You could "|" many + * PNG_TRANSFORM flags into the png_transforms integer here. + */ + png_write_png(png_ptr, info_ptr, png_transforms, NULL); + +#else + /* This is the hard way */ + + /* Set the image information here. Width and height are up to 2^31, + * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on + * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY, + * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB, + * or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or + * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST + * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED + */ + png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, PNG_COLOR_TYPE_???, + PNG_INTERLACE_????, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + /* Set the palette if there is one. REQUIRED for indexed-color images */ + palette = (png_colorp)png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH + * png_sizeof(png_color)); + /* ... Set palette colors ... */ + png_set_PLTE(png_ptr, info_ptr, palette, PNG_MAX_PALETTE_LENGTH); + /* You must not free palette here, because png_set_PLTE only makes a link to + * the palette that you malloced. Wait until you are about to destroy + * the png structure. + */ + + /* Optional significant bit (sBIT) chunk */ + png_color_8 sig_bit; + /* If we are dealing with a grayscale image then */ + sig_bit.gray = true_bit_depth; + /* Otherwise, if we are dealing with a color image then */ + sig_bit.red = true_red_bit_depth; + sig_bit.green = true_green_bit_depth; + sig_bit.blue = true_blue_bit_depth; + /* If the image has an alpha channel then */ + sig_bit.alpha = true_alpha_bit_depth; + png_set_sBIT(png_ptr, info_ptr, &sig_bit); + + + /* Optional gamma chunk is strongly suggested if you have any guess + * as to the correct gamma of the image. + */ + png_set_gAMA(png_ptr, info_ptr, gamma); + + /* Optionally write comments into the image */ + text_ptr[0].key = "Title"; + text_ptr[0].text = "Mona Lisa"; + text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE; + text_ptr[1].key = "Author"; + text_ptr[1].text = "Leonardo DaVinci"; + text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE; + text_ptr[2].key = "Description"; + text_ptr[2].text = ""; + text_ptr[2].compression = PNG_TEXT_COMPRESSION_zTXt; +#ifdef PNG_iTXt_SUPPORTED + text_ptr[0].lang = NULL; + text_ptr[0].lang_key = NULL; + text_ptr[1].lang = NULL; + text_ptr[1].lang_key = NULL; + text_ptr[2].lang = NULL; + text_ptr[2].lang_key = NULL; +#endif + png_set_text(png_ptr, info_ptr, text_ptr, 3); + + /* Other optional chunks like cHRM, bKGD, tRNS, tIME, oFFs, pHYs */ + + /* Note that if sRGB is present the gAMA and cHRM chunks must be ignored + * on read and, if your application chooses to write them, they must + * be written in accordance with the sRGB profile + */ + + /* Write the file header information. REQUIRED */ + png_write_info(png_ptr, info_ptr); + + /* If you want, you can write the info in two steps, in case you need to + * write your private chunk ahead of PLTE: + * + * png_write_info_before_PLTE(write_ptr, write_info_ptr); + * write_my_chunk(); + * png_write_info(png_ptr, info_ptr); + * + * However, given the level of known- and unknown-chunk support in 1.2.0 + * and up, this should no longer be necessary. + */ + + /* Once we write out the header, the compression type on the text + * chunks gets changed to PNG_TEXT_COMPRESSION_NONE_WR or + * PNG_TEXT_COMPRESSION_zTXt_WR, so it doesn't get written out again + * at the end. + */ + + /* Set up the transformations you want. Note that these are + * all optional. Only call them if you want them. + */ + + /* Invert monochrome pixels */ + png_set_invert_mono(png_ptr); + + /* Shift the pixels up to a legal bit depth and fill in + * as appropriate to correctly scale the image. + */ + png_set_shift(png_ptr, &sig_bit); + + /* Pack pixels into bytes */ + png_set_packing(png_ptr); + + /* Swap location of alpha bytes from ARGB to RGBA */ + png_set_swap_alpha(png_ptr); + + /* Get rid of filler (OR ALPHA) bytes, pack XRGB/RGBX/ARGB/RGBA into + * RGB (4 channels -> 3 channels). The second parameter is not used. + */ + png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); + + /* Flip BGR pixels to RGB */ + png_set_bgr(png_ptr); + + /* Swap bytes of 16-bit files to most significant byte first */ + png_set_swap(png_ptr); + + /* Swap bits of 1, 2, 4 bit packed pixel formats */ + png_set_packswap(png_ptr); + + /* Turn on interlace handling if you are not using png_write_image() */ + if (interlacing) + number_passes = png_set_interlace_handling(png_ptr); + else + number_passes = 1; + + /* The easiest way to write the image (you may have a different memory + * layout, however, so choose what fits your needs best). You need to + * use the first method if you aren't handling interlacing yourself. + */ + png_uint_32 k, height, width; + png_byte image[height][width*bytes_per_pixel]; + png_bytep row_pointers[height]; + + if (height > PNG_UINT_32_MAX/png_sizeof(png_bytep)) + png_error (png_ptr, "Image is too tall to process in memory"); + + for (k = 0; k < height; k++) + row_pointers[k] = image + k*width*bytes_per_pixel; + + /* One of the following output methods is REQUIRED */ + +#ifdef entire /* Write out the entire image data in one call */ + png_write_image(png_ptr, row_pointers); + + /* The other way to write the image - deal with interlacing */ + +#else no_entire /* Write out the image data by one or more scanlines */ + + /* The number of passes is either 1 for non-interlaced images, + * or 7 for interlaced images. + */ + for (pass = 0; pass < number_passes; pass++) + { + /* Write a few rows at a time. */ + png_write_rows(png_ptr, &row_pointers[first_row], number_of_rows); + + /* If you are only writing one row at a time, this works */ + for (y = 0; y < height; y++) + png_write_rows(png_ptr, &row_pointers[y], 1); + } +#endif no_entire /* Use only one output method */ + + /* You can write optional chunks like tEXt, zTXt, and tIME at the end + * as well. Shouldn't be necessary in 1.2.0 and up as all the public + * chunks are supported and you can use png_set_unknown_chunks() to + * register unknown chunks into the info structure to be written out. + */ + + /* It is REQUIRED to call this to finish writing the rest of the file */ + png_write_end(png_ptr, info_ptr); +#endif hilevel + + /* If you png_malloced a palette, free it here (don't free info_ptr->palette, + * as recommended in versions 1.0.5m and earlier of this example; if + * libpng mallocs info_ptr->palette, libpng will free it). If you + * allocated it with malloc() instead of png_malloc(), use free() instead + * of png_free(). + */ + png_free(png_ptr, palette); + palette = NULL; + + /* Similarly, if you png_malloced any data that you passed in with + * png_set_something(), such as a hist or trans array, free it here, + * when you can be sure that libpng is through with it. + */ + png_free(png_ptr, trans); + trans = NULL; + /* Whenever you use png_free() it is a good idea to set the pointer to + * NULL in case your application inadvertently tries to png_free() it + * again. When png_free() sees a NULL it returns without action, thus + * avoiding the double-free security problem. + */ + + /* Clean up after the write, and free any memory allocated */ + png_destroy_write_struct(&png_ptr, &info_ptr); + + /* Close the file */ + fclose(fp); + + /* That's it */ + return (OK); +} + +#endif /* if 0 */ diff --git a/reactos/dll/3rdparty/libpng/docs/libpng-1.4.3.txt b/reactos/dll/3rdparty/libpng/docs/libpng-1.4.3.txt new file mode 100644 index 00000000000..5451f2fc139 --- /dev/null +++ b/reactos/dll/3rdparty/libpng/docs/libpng-1.4.3.txt @@ -0,0 +1,3352 @@ +libpng.txt - A description on how to use and modify libpng + + libpng version 1.4.3 - June 26, 2010 + Updated and distributed by Glenn Randers-Pehrson + + Copyright (c) 1998-2009 Glenn Randers-Pehrson + + This document is released under the libpng license. + For conditions of distribution and use, see the disclaimer + and license in png.h + + Based on: + + libpng versions 0.97, January 1998, through 1.4.3 - June 26, 2010 + Updated and distributed by Glenn Randers-Pehrson + Copyright (c) 1998-2009 Glenn Randers-Pehrson + + libpng 1.0 beta 6 version 0.96 May 28, 1997 + Updated and distributed by Andreas Dilger + Copyright (c) 1996, 1997 Andreas Dilger + + libpng 1.0 beta 2 - version 0.88 January 26, 1996 + For conditions of distribution and use, see copyright + notice in png.h. Copyright (c) 1995, 1996 Guy Eric + Schalnat, Group 42, Inc. + + Updated/rewritten per request in the libpng FAQ + Copyright (c) 1995, 1996 Frank J. T. Wojcik + December 18, 1995 & January 20, 1996 + +I. Introduction + +This file describes how to use and modify the PNG reference library +(known as libpng) for your own use. There are five sections to this +file: introduction, structures, reading, writing, and modification and +configuration notes for various special platforms. In addition to this +file, example.c is a good starting point for using the library, as +it is heavily commented and should include everything most people +will need. We assume that libpng is already installed; see the +INSTALL file for instructions on how to install libpng. + +For examples of libpng usage, see the files "example.c", "pngtest.c", +and the files in the "contrib" directory, all of which are included in +the libpng distribution. + +Libpng was written as a companion to the PNG specification, as a way +of reducing the amount of time and effort it takes to support the PNG +file format in application programs. + +The PNG specification (second edition), November 2003, is available as +a W3C Recommendation and as an ISO Standard (ISO/IEC 15948:2003 (E)) at +. It is technically equivalent +to the PNG specification (second edition) but has some additional material. + +The PNG-1.0 specification is available +as RFC 2083 and as a +W3C Recommendation . + +Some additional chunks are described in the special-purpose public chunks +documents at . + +Other information +about PNG, and the latest version of libpng, can be found at the PNG home +page, . + +Most users will not have to modify the library significantly; advanced +users may want to modify it more. All attempts were made to make it as +complete as possible, while keeping the code easy to understand. +Currently, this library only supports C. Support for other languages +is being considered. + +Libpng has been designed to handle multiple sessions at one time, +to be easily modifiable, to be portable to the vast majority of +machines (ANSI, K&R, 16-, 32-, and 64-bit) available, and to be easy +to use. The ultimate goal of libpng is to promote the acceptance of +the PNG file format in whatever way possible. While there is still +work to be done (see the TODO file), libpng should cover the +majority of the needs of its users. + +Libpng uses zlib for its compression and decompression of PNG files. +Further information about zlib, and the latest version of zlib, can +be found at the zlib home page, . +The zlib compression utility is a general purpose utility that is +useful for more than PNG files, and can be used without libpng. +See the documentation delivered with zlib for more details. +You can usually find the source files for the zlib utility wherever you +find the libpng source files. + +Libpng is thread safe, provided the threads are using different +instances of the structures. Each thread should have its own +png_struct and png_info instances, and thus its own image. +Libpng does not protect itself against two threads using the +same instance of a structure. + +II. Structures + +There are two main structures that are important to libpng, png_struct +and png_info. The first, png_struct, is an internal structure that +will not, for the most part, be used by a user except as the first +variable passed to every libpng function call. + +The png_info structure is designed to provide information about the +PNG file. At one time, the fields of png_info were intended to be +directly accessible to the user. However, this tended to cause problems +with applications using dynamically loaded libraries, and as a result +a set of interface functions for png_info (the png_get_*() and png_set_*() +functions) was developed. The fields of png_info are still available for +older applications, but it is suggested that applications use the new +interfaces if at all possible. + +Applications that do make direct access to the members of png_struct (except +for png_ptr->jmpbuf) must be recompiled whenever the library is updated, +and applications that make direct access to the members of png_info must +be recompiled if they were compiled or loaded with libpng version 1.0.6, +in which the members were in a different order. In version 1.0.7, the +members of the png_info structure reverted to the old order, as they were +in versions 0.97c through 1.0.5. Starting with version 2.0.0, both +structures are going to be hidden, and the contents of the structures will +only be accessible through the png_get/png_set functions. + +The png.h header file is an invaluable reference for programming with libpng. +And while I'm on the topic, make sure you include the libpng header file: + +#include + +III. Reading + +We'll now walk you through the possible functions to call when reading +in a PNG file sequentially, briefly explaining the syntax and purpose +of each one. See example.c and png.h for more detail. While +progressive reading is covered in the next section, you will still +need some of the functions discussed in this section to read a PNG +file. + +Setup + +You will want to do the I/O initialization(*) before you get into libpng, +so if it doesn't work, you don't have much to undo. Of course, you +will also want to insure that you are, in fact, dealing with a PNG +file. Libpng provides a simple check to see if a file is a PNG file. +To use it, pass in the first 1 to 8 bytes of the file to the function +png_sig_cmp(), and it will return 0 (false) if the bytes match the +corresponding bytes of the PNG signature, or nonzero (true) otherwise. +Of course, the more bytes you pass in, the greater the accuracy of the +prediction. + +If you are intending to keep the file pointer open for use in libpng, +you must ensure you don't read more than 8 bytes from the beginning +of the file, and you also have to make a call to png_set_sig_bytes_read() +with the number of bytes you read from the beginning. Libpng will +then only check the bytes (if any) that your program didn't read. + +(*): If you are not using the standard I/O functions, you will need +to replace them with custom functions. See the discussion under +Customizing libpng. + + + FILE *fp = fopen(file_name, "rb"); + if (!fp) + { + return (ERROR); + } + fread(header, 1, number, fp); + is_png = !png_sig_cmp(header, 0, number); + if (!is_png) + { + return (NOT_PNG); + } + + +Next, png_struct and png_info need to be allocated and initialized. In +order to ensure that the size of these structures is correct even with a +dynamically linked libpng, there are functions to initialize and +allocate the structures. We also pass the library version, optional +pointers to error handling functions, and a pointer to a data struct for +use by the error functions, if necessary (the pointer and functions can +be NULL if the default error handlers are to be used). See the section +on Changes to Libpng below regarding the old initialization functions. +The structure allocation functions quietly return NULL if they fail to +create the structure, so your application should check for that. + + png_structp png_ptr = png_create_read_struct + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + user_error_fn, user_warning_fn); + if (!png_ptr) + return (ERROR); + + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + { + png_destroy_read_struct(&png_ptr, + (png_infopp)NULL, (png_infopp)NULL); + return (ERROR); + } + + png_infop end_info = png_create_info_struct(png_ptr); + if (!end_info) + { + png_destroy_read_struct(&png_ptr, &info_ptr, + (png_infopp)NULL); + return (ERROR); + } + +If you want to use your own memory allocation routines, +define PNG_USER_MEM_SUPPORTED and use +png_create_read_struct_2() instead of png_create_read_struct(): + + png_structp png_ptr = png_create_read_struct_2 + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + user_error_fn, user_warning_fn, (png_voidp) + user_mem_ptr, user_malloc_fn, user_free_fn); + +The error handling routines passed to png_create_read_struct() +and the memory alloc/free routines passed to png_create_struct_2() +are only necessary if you are not using the libpng supplied error +handling and memory alloc/free functions. + +When libpng encounters an error, it expects to longjmp back +to your routine. Therefore, you will need to call setjmp and pass +your png_jmpbuf(png_ptr). If you read the file from different +routines, you will need to update the jmpbuf field every time you enter +a new routine that will call a png_*() function. + +See your documentation of setjmp/longjmp for your compiler for more +information on setjmp/longjmp. See the discussion on libpng error +handling in the Customizing Libpng section below for more information +on the libpng error handling. If an error occurs, and libpng longjmp's +back to your setjmp, you will want to call png_destroy_read_struct() to +free any memory. + + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_read_struct(&png_ptr, &info_ptr, + &end_info); + fclose(fp); + return (ERROR); + } + +If you would rather avoid the complexity of setjmp/longjmp issues, +you can compile libpng with PNG_NO_SETJMP, in which case +errors will result in a call to PNG_ABORT() which defaults to abort(). + +You can #define PNG_ABORT() to a function that does something +more useful than abort(), as long as your function does not +return. + +Now you need to set up the input code. The default for libpng is to +use the C function fread(). If you use this, you will need to pass a +valid FILE * in the function png_init_io(). Be sure that the file is +opened in binary mode. If you wish to handle reading data in another +way, you need not call the png_init_io() function, but you must then +implement the libpng I/O methods discussed in the Customizing Libpng +section below. + + png_init_io(png_ptr, fp); + +If you had previously opened the file and read any of the signature from +the beginning in order to see if this was a PNG file, you need to let +libpng know that there are some bytes missing from the start of the file. + + png_set_sig_bytes(png_ptr, number); + +You can change the zlib compression buffer size to be used while +reading compressed data with + + png_set_compression_buffer_size(png_ptr, buffer_size); + +where the default size is 8192 bytes. Note that the buffer size +is changed immediately and the buffer is reallocated immediately, +instead of setting a flag to be acted upon later. + +Setting up callback code + +You can set up a callback function to handle any unknown chunks in the +input stream. You must supply the function + + read_chunk_callback(png_ptr ptr, + png_unknown_chunkp chunk); + { + /* The unknown chunk structure contains your + chunk data, along with similar data for any other + unknown chunks: */ + + png_byte name[5]; + png_byte *data; + png_size_t size; + + /* Note that libpng has already taken care of + the CRC handling */ + + /* put your code here. Search for your chunk in the + unknown chunk structure, process it, and return one + of the following: */ + + return (-n); /* chunk had an error */ + return (0); /* did not recognize */ + return (n); /* success */ + } + +(You can give your function another name that you like instead of +"read_chunk_callback") + +To inform libpng about your function, use + + png_set_read_user_chunk_fn(png_ptr, user_chunk_ptr, + read_chunk_callback); + +This names not only the callback function, but also a user pointer that +you can retrieve with + + png_get_user_chunk_ptr(png_ptr); + +If you call the png_set_read_user_chunk_fn() function, then all unknown +chunks will be saved when read, in case your callback function will need +one or more of them. This behavior can be changed with the +png_set_keep_unknown_chunks() function, described below. + +At this point, you can set up a callback function that will be +called after each row has been read, which you can use to control +a progress meter or the like. It's demonstrated in pngtest.c. +You must supply a function + + void read_row_callback(png_ptr ptr, png_uint_32 row, + int pass); + { + /* put your code here */ + } + +(You can give it another name that you like instead of "read_row_callback") + +To inform libpng about your function, use + + png_set_read_status_fn(png_ptr, read_row_callback); + +Unknown-chunk handling + +Now you get to set the way the library processes unknown chunks in the +input PNG stream. Both known and unknown chunks will be read. Normal +behavior is that known chunks will be parsed into information in +various info_ptr members while unknown chunks will be discarded. This +behavior can be wasteful if your application will never use some known +chunk types. To change this, you can call: + + png_set_keep_unknown_chunks(png_ptr, keep, + chunk_list, num_chunks); + keep - 0: default unknown chunk handling + 1: ignore; do not keep + 2: keep only if safe-to-copy + 3: keep even if unsafe-to-copy + You can use these definitions: + PNG_HANDLE_CHUNK_AS_DEFAULT 0 + PNG_HANDLE_CHUNK_NEVER 1 + PNG_HANDLE_CHUNK_IF_SAFE 2 + PNG_HANDLE_CHUNK_ALWAYS 3 + chunk_list - list of chunks affected (a byte string, + five bytes per chunk, NULL or '\0' if + num_chunks is 0) + num_chunks - number of chunks affected; if 0, all + unknown chunks are affected. If nonzero, + only the chunks in the list are affected + +Unknown chunks declared in this way will be saved as raw data onto a +list of png_unknown_chunk structures. If a chunk that is normally +known to libpng is named in the list, it will be handled as unknown, +according to the "keep" directive. If a chunk is named in successive +instances of png_set_keep_unknown_chunks(), the final instance will +take precedence. The IHDR and IEND chunks should not be named in +chunk_list; if they are, libpng will process them normally anyway. + +Here is an example of the usage of png_set_keep_unknown_chunks(), +where the private "vpAg" chunk will later be processed by a user chunk +callback function: + + png_byte vpAg[5]={118, 112, 65, 103, (png_byte) '\0'}; + + #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) + png_byte unused_chunks[]= + { + 104, 73, 83, 84, (png_byte) '\0', /* hIST */ + 105, 84, 88, 116, (png_byte) '\0', /* iTXt */ + 112, 67, 65, 76, (png_byte) '\0', /* pCAL */ + 115, 67, 65, 76, (png_byte) '\0', /* sCAL */ + 115, 80, 76, 84, (png_byte) '\0', /* sPLT */ + 116, 73, 77, 69, (png_byte) '\0', /* tIME */ + }; + #endif + + ... + + #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) + /* ignore all unknown chunks: */ + png_set_keep_unknown_chunks(read_ptr, 1, NULL, 0); + /* except for vpAg: */ + png_set_keep_unknown_chunks(read_ptr, 2, vpAg, 1); + /* also ignore unused known chunks: */ + png_set_keep_unknown_chunks(read_ptr, 1, unused_chunks, + (int)sizeof(unused_chunks)/5); + #endif + +User limits + +The PNG specification allows the width and height of an image to be as +large as 2^31-1 (0x7fffffff), or about 2.147 billion rows and columns. +Since very few applications really need to process such large images, +we have imposed an arbitrary 1-million limit on rows and columns. +Larger images will be rejected immediately with a png_error() call. If +you wish to override this limit, you can use + + png_set_user_limits(png_ptr, width_max, height_max); + +to set your own limits, or use width_max = height_max = 0x7fffffffL +to allow all valid dimensions (libpng may reject some very large images +anyway because of potential buffer overflow conditions). + +You should put this statement after you create the PNG structure and +before calling png_read_info(), png_read_png(), or png_process_data(). +If you need to retrieve the limits that are being applied, use + + width_max = png_get_user_width_max(png_ptr); + height_max = png_get_user_height_max(png_ptr); + +The PNG specification sets no limit on the number of ancillary chunks +allowed in a PNG datastream. You can impose a limit on the total number +of sPLT, tEXt, iTXt, zTXt, and unknown chunks that will be stored, with + + png_set_chunk_cache_max(png_ptr, user_chunk_cache_max); + +where 0x7fffffffL means unlimited. You can retrieve this limit with + + chunk_cache_max = png_get_chunk_cache_max(png_ptr); + +This limit also applies to the number of buffers that can be allocated +by png_decompress_chunk() while decompressing iTXt, zTXt, and iCCP chunks. + +You can also set a limit on the amount of memory that a compressed chunk +other than IDAT can occupy, with + + png_set_chunk_malloc_max(png_ptr, user_chunk_malloc_max); + +and you can retrieve the limit with + + chunk_malloc_max = png_get_chunk_malloc_max(png_ptr); + +Any chunks that would cause either of these limits to be exceeded will +be ignored. + +The high-level read interface + +At this point there are two ways to proceed; through the high-level +read interface, or through a sequence of low-level read operations. +You can use the high-level interface if (a) you are willing to read +the entire image into memory, and (b) the input transformations +you want to do are limited to the following set: + + PNG_TRANSFORM_IDENTITY No transformation + PNG_TRANSFORM_STRIP_16 Strip 16-bit samples to + 8 bits + PNG_TRANSFORM_STRIP_ALPHA Discard the alpha channel + PNG_TRANSFORM_PACKING Expand 1, 2 and 4-bit + samples to bytes + PNG_TRANSFORM_PACKSWAP Change order of packed + pixels to LSB first + PNG_TRANSFORM_EXPAND Perform set_expand() + PNG_TRANSFORM_INVERT_MONO Invert monochrome images + PNG_TRANSFORM_SHIFT Normalize pixels to the + sBIT depth + PNG_TRANSFORM_BGR Flip RGB to BGR, RGBA + to BGRA + PNG_TRANSFORM_SWAP_ALPHA Flip RGBA to ARGB or GA + to AG + PNG_TRANSFORM_INVERT_ALPHA Change alpha from opacity + to transparency + PNG_TRANSFORM_SWAP_ENDIAN Byte-swap 16-bit samples + PNG_TRANSFORM_GRAY_TO_RGB Expand grayscale samples + to RGB (or GA to RGBA) + +(This excludes setting a background color, doing gamma transformation, +quantizing, and setting filler.) If this is the case, simply do this: + + png_read_png(png_ptr, info_ptr, png_transforms, NULL) + +where png_transforms is an integer containing the bitwise OR of some +set of transformation flags. This call is equivalent to png_read_info(), +followed the set of transformations indicated by the transform mask, +then png_read_image(), and finally png_read_end(). + +(The final parameter of this call is not yet used. Someday it might point +to transformation parameters required by some future input transform.) + +You must use png_transforms and not call any png_set_transform() functions +when you use png_read_png(). + +After you have called png_read_png(), you can retrieve the image data +with + + row_pointers = png_get_rows(png_ptr, info_ptr); + +where row_pointers is an array of pointers to the pixel data for each row: + + png_bytep row_pointers[height]; + +If you know your image size and pixel size ahead of time, you can allocate +row_pointers prior to calling png_read_png() with + + if (height > PNG_UINT_32_MAX/png_sizeof(png_byte)) + png_error (png_ptr, + "Image is too tall to process in memory"); + if (width > PNG_UINT_32_MAX/pixel_size) + png_error (png_ptr, + "Image is too wide to process in memory"); + row_pointers = png_malloc(png_ptr, + height*png_sizeof(png_bytep)); + for (int i=0; i) and +png_get_(png_ptr, info_ptr, ...) functions return non-zero if the +data has been read, or zero if it is missing. The parameters to the +png_get_ are set directly if they are simple data types, or a +pointer into the info_ptr is returned for any complex types. + + png_get_PLTE(png_ptr, info_ptr, &palette, + &num_palette); + palette - the palette for the file + (array of png_color) + num_palette - number of entries in the palette + + png_get_gAMA(png_ptr, info_ptr, &gamma); + gamma - the gamma the file is written + at (PNG_INFO_gAMA) + + png_get_sRGB(png_ptr, info_ptr, &srgb_intent); + srgb_intent - the rendering intent (PNG_INFO_sRGB) + The presence of the sRGB chunk + means that the pixel data is in the + sRGB color space. This chunk also + implies specific values of gAMA and + cHRM. + + png_get_iCCP(png_ptr, info_ptr, &name, + &compression_type, &profile, &proflen); + name - The profile name. + compression - The compression type; always + PNG_COMPRESSION_TYPE_BASE for PNG 1.0. + You may give NULL to this argument to + ignore it. + profile - International Color Consortium color + profile data. May contain NULs. + proflen - length of profile data in bytes. + + png_get_sBIT(png_ptr, info_ptr, &sig_bit); + sig_bit - the number of significant bits for + (PNG_INFO_sBIT) each of the gray, + red, green, and blue channels, + whichever are appropriate for the + given color type (png_color_16) + + png_get_tRNS(png_ptr, info_ptr, &trans_alpha, + &num_trans, &trans_color); + trans_alpha - array of alpha (transparency) + entries for palette (PNG_INFO_tRNS) + trans_color - graylevel or color sample values of + the single transparent color for + non-paletted images (PNG_INFO_tRNS) + num_trans - number of transparent entries + (PNG_INFO_tRNS) + + png_get_hIST(png_ptr, info_ptr, &hist); + (PNG_INFO_hIST) + hist - histogram of palette (array of + png_uint_16) + + png_get_tIME(png_ptr, info_ptr, &mod_time); + mod_time - time image was last modified + (PNG_VALID_tIME) + + png_get_bKGD(png_ptr, info_ptr, &background); + background - background color (PNG_VALID_bKGD) + valid 16-bit red, green and blue + values, regardless of color_type + + num_comments = png_get_text(png_ptr, info_ptr, + &text_ptr, &num_text); + num_comments - number of comments + text_ptr - array of png_text holding image + comments + text_ptr[i].compression - type of compression used + on "text" PNG_TEXT_COMPRESSION_NONE + PNG_TEXT_COMPRESSION_zTXt + PNG_ITXT_COMPRESSION_NONE + PNG_ITXT_COMPRESSION_zTXt + text_ptr[i].key - keyword for comment. Must contain + 1-79 characters. + text_ptr[i].text - text comments for current + keyword. Can be empty. + text_ptr[i].text_length - length of text string, + after decompression, 0 for iTXt + text_ptr[i].itxt_length - length of itxt string, + after decompression, 0 for tEXt/zTXt + text_ptr[i].lang - language of comment (empty + string for unknown). + text_ptr[i].lang_key - keyword in UTF-8 + (empty string for unknown). + Note that the itxt_length, lang, and lang_key + members of the text_ptr structure only exist + when the library is built with iTXt chunk support. + + num_text - number of comments (same as + num_comments; you can put NULL here + to avoid the duplication) + Note while png_set_text() will accept text, language, + and translated keywords that can be NULL pointers, the + structure returned by png_get_text will always contain + regular zero-terminated C strings. They might be + empty strings but they will never be NULL pointers. + + num_spalettes = png_get_sPLT(png_ptr, info_ptr, + &palette_ptr); + palette_ptr - array of palette structures holding + contents of one or more sPLT chunks + read. + num_spalettes - number of sPLT chunks read. + + png_get_oFFs(png_ptr, info_ptr, &offset_x, &offset_y, + &unit_type); + offset_x - positive offset from the left edge + of the screen + offset_y - positive offset from the top edge + of the screen + unit_type - PNG_OFFSET_PIXEL, PNG_OFFSET_MICROMETER + + png_get_pHYs(png_ptr, info_ptr, &res_x, &res_y, + &unit_type); + res_x - pixels/unit physical resolution in + x direction + res_y - pixels/unit physical resolution in + x direction + unit_type - PNG_RESOLUTION_UNKNOWN, + PNG_RESOLUTION_METER + + png_get_sCAL(png_ptr, info_ptr, &unit, &width, + &height) + unit - physical scale units (an integer) + width - width of a pixel in physical scale units + height - height of a pixel in physical scale units + (width and height are doubles) + + png_get_sCAL_s(png_ptr, info_ptr, &unit, &width, + &height) + unit - physical scale units (an integer) + width - width of a pixel in physical scale units + height - height of a pixel in physical scale units + (width and height are strings like "2.54") + + num_unknown_chunks = png_get_unknown_chunks(png_ptr, + info_ptr, &unknowns) + unknowns - array of png_unknown_chunk + structures holding unknown chunks + unknowns[i].name - name of unknown chunk + unknowns[i].data - data of unknown chunk + unknowns[i].size - size of unknown chunk's data + unknowns[i].location - position of chunk in file + + The value of "i" corresponds to the order in which the + chunks were read from the PNG file or inserted with the + png_set_unknown_chunks() function. + +The data from the pHYs chunk can be retrieved in several convenient +forms: + + res_x = png_get_x_pixels_per_meter(png_ptr, + info_ptr) + res_y = png_get_y_pixels_per_meter(png_ptr, + info_ptr) + res_x_and_y = png_get_pixels_per_meter(png_ptr, + info_ptr) + res_x = png_get_x_pixels_per_inch(png_ptr, + info_ptr) + res_y = png_get_y_pixels_per_inch(png_ptr, + info_ptr) + res_x_and_y = png_get_pixels_per_inch(png_ptr, + info_ptr) + aspect_ratio = png_get_pixel_aspect_ratio(png_ptr, + info_ptr) + + (Each of these returns 0 [signifying "unknown"] if + the data is not present or if res_x is 0; + res_x_and_y is 0 if res_x != res_y) + +The data from the oFFs chunk can be retrieved in several convenient +forms: + + x_offset = png_get_x_offset_microns(png_ptr, info_ptr); + y_offset = png_get_y_offset_microns(png_ptr, info_ptr); + x_offset = png_get_x_offset_inches(png_ptr, info_ptr); + y_offset = png_get_y_offset_inches(png_ptr, info_ptr); + + (Each of these returns 0 [signifying "unknown" if both + x and y are 0] if the data is not present or if the + chunk is present but the unit is the pixel) + +For more information, see the png_info definition in png.h and the +PNG specification for chunk contents. Be careful with trusting +rowbytes, as some of the transformations could increase the space +needed to hold a row (expand, filler, gray_to_rgb, etc.). +See png_read_update_info(), below. + +A quick word about text_ptr and num_text. PNG stores comments in +keyword/text pairs, one pair per chunk, with no limit on the number +of text chunks, and a 2^31 byte limit on their size. While there are +suggested keywords, there is no requirement to restrict the use to these +strings. It is strongly suggested that keywords and text be sensible +to humans (that's the point), so don't use abbreviations. Non-printing +symbols are not allowed. See the PNG specification for more details. +There is also no requirement to have text after the keyword. + +Keywords should be limited to 79 Latin-1 characters without leading or +trailing spaces, but non-consecutive spaces are allowed within the +keyword. It is possible to have the same keyword any number of times. +The text_ptr is an array of png_text structures, each holding a +pointer to a language string, a pointer to a keyword and a pointer to +a text string. The text string, language code, and translated +keyword may be empty or NULL pointers. The keyword/text +pairs are put into the array in the order that they are received. +However, some or all of the text chunks may be after the image, so, to +make sure you have read all the text chunks, don't mess with these +until after you read the stuff after the image. This will be +mentioned again below in the discussion that goes with png_read_end(). + +Input transformations + +After you've read the header information, you can set up the library +to handle any special transformations of the image data. The various +ways to transform the data will be described in the order that they +should occur. This is important, as some of these change the color +type and/or bit depth of the data, and some others only work on +certain color types and bit depths. Even though each transformation +checks to see if it has data that it can do something with, you should +make sure to only enable a transformation if it will be valid for the +data. For example, don't swap red and blue on grayscale data. + +The colors used for the background and transparency values should be +supplied in the same format/depth as the current image data. They +are stored in the same format/depth as the image data in a bKGD or tRNS +chunk, so this is what libpng expects for this data. The colors are +transformed to keep in sync with the image data when an application +calls the png_read_update_info() routine (see below). + +Data will be decoded into the supplied row buffers packed into bytes +unless the library has been told to transform it into another format. +For example, 4 bit/pixel paletted or grayscale data will be returned +2 pixels/byte with the leftmost pixel in the high-order bits of the +byte, unless png_set_packing() is called. 8-bit RGB data will be stored +in RGB RGB RGB format unless png_set_filler() or png_set_add_alpha() +is called to insert filler bytes, either before or after each RGB triplet. +16-bit RGB data will be returned RRGGBB RRGGBB, with the most significant +byte of the color value first, unless png_set_strip_16() is called to +transform it to regular RGB RGB triplets, or png_set_filler() or +png_set_add alpha() is called to insert filler bytes, either before or +after each RRGGBB triplet. Similarly, 8-bit or 16-bit grayscale data can +be modified with +png_set_filler(), png_set_add_alpha(), or png_set_strip_16(). + +The following code transforms grayscale images of less than 8 to 8 bits, +changes paletted images to RGB, and adds a full alpha channel if there is +transparency information in a tRNS chunk. This is most useful on +grayscale images with bit depths of 2 or 4 or if there is a multiple-image +viewing application that wishes to treat all images in the same way. + + if (color_type == PNG_COLOR_TYPE_PALETTE) + png_set_palette_to_rgb(png_ptr); + + if (color_type == PNG_COLOR_TYPE_GRAY && + bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png_ptr); + + if (png_get_valid(png_ptr, info_ptr, + PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr); + +These three functions are actually aliases for png_set_expand(), added +in libpng version 1.0.4, with the function names expanded to improve code +readability. In some future version they may actually do different +things. + +As of libpng version 1.2.9, png_set_expand_gray_1_2_4_to_8() was +added. It expands the sample depth without changing tRNS to alpha. + +As of libpng version 1.4.3, not all possible expansions are supported. + +In the following table, the 01 means grayscale with depth<8, 31 means +indexed with depth<8, other numerals represent the color type, "T" means +the tRNS chunk is present, A means an alpha channel is present, and O +means tRNS or alpha is present but all pixels in the image are opaque. + + FROM 01 31 0 0T 0O 2 2T 2O 3 3T 3O 4A 4O 6A 6O + TO + 01 - + 31 - + 0 1 - + 0T - + 0O - + 2 GX - + 2T - + 2O - + 3 1 - + 3T - + 3O - + 4A T - + 4O - + 6A GX TX TX - + 6O GX TX - + +Within the matrix, + "-" means the transformation is not supported. + "X" means the transformation is obtained by png_set_expand(). + "1" means the transformation is obtained by + png_set_expand_gray_1_2_4_to_8 + "G" means the transformation is obtained by + png_set_gray_to_rgb(). + "P" means the transformation is obtained by + png_set_expand_palette_to_rgb(). + "T" means the transformation is obtained by + png_set_tRNS_to_alpha(). + +PNG can have files with 16 bits per channel. If you only can handle +8 bits per channel, this will strip the pixels down to 8 bit. + + if (bit_depth == 16) + png_set_strip_16(png_ptr); + +If, for some reason, you don't need the alpha channel on an image, +and you want to remove it rather than combining it with the background +(but the image author certainly had in mind that you *would* combine +it with the background, so that's what you should probably do): + + if (color_type & PNG_COLOR_MASK_ALPHA) + png_set_strip_alpha(png_ptr); + +In PNG files, the alpha channel in an image +is the level of opacity. If you need the alpha channel in an image to +be the level of transparency instead of opacity, you can invert the +alpha channel (or the tRNS chunk data) after it's read, so that 0 is +fully opaque and 255 (in 8-bit or paletted images) or 65535 (in 16-bit +images) is fully transparent, with + + png_set_invert_alpha(png_ptr); + +PNG files pack pixels of bit depths 1, 2, and 4 into bytes as small as +they can, resulting in, for example, 8 pixels per byte for 1 bit +files. This code expands to 1 pixel per byte without changing the +values of the pixels: + + if (bit_depth < 8) + png_set_packing(png_ptr); + +PNG files have possible bit depths of 1, 2, 4, 8, and 16. All pixels +stored in a PNG image have been "scaled" or "shifted" up to the next +higher possible bit depth (e.g. from 5 bits/sample in the range [0,31] +to 8 bits/sample in the range [0, 255]). However, it is also possible +to convert the PNG pixel data back to the original bit depth of the +image. This call reduces the pixels back down to the original bit depth: + + png_color_8p sig_bit; + + if (png_get_sBIT(png_ptr, info_ptr, &sig_bit)) + png_set_shift(png_ptr, sig_bit); + +PNG files store 3-color pixels in red, green, blue order. This code +changes the storage of the pixels to blue, green, red: + + if (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_RGB_ALPHA) + png_set_bgr(png_ptr); + +PNG files store RGB pixels packed into 3 or 6 bytes. This code expands them +into 4 or 8 bytes for windowing systems that need them in this format: + + if (color_type == PNG_COLOR_TYPE_RGB) + png_set_filler(png_ptr, filler, PNG_FILLER_BEFORE); + +where "filler" is the 8 or 16-bit number to fill with, and the location is +either PNG_FILLER_BEFORE or PNG_FILLER_AFTER, depending upon whether +you want the filler before the RGB or after. This transformation +does not affect images that already have full alpha channels. To add an +opaque alpha channel, use filler=0xff or 0xffff and PNG_FILLER_AFTER which +will generate RGBA pixels. + +Note that png_set_filler() does not change the color type. If you want +to do that, you can add a true alpha channel with + + if (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_GRAY) + png_set_add_alpha(png_ptr, filler, PNG_FILLER_AFTER); + +where "filler" contains the alpha value to assign to each pixel. +This function was added in libpng-1.2.7. + +If you are reading an image with an alpha channel, and you need the +data as ARGB instead of the normal PNG format RGBA: + + if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) + png_set_swap_alpha(png_ptr); + +For some uses, you may want a grayscale image to be represented as +RGB. This code will do that conversion: + + if (color_type == PNG_COLOR_TYPE_GRAY || + color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_gray_to_rgb(png_ptr); + +Conversely, you can convert an RGB or RGBA image to grayscale or grayscale +with alpha. + + if (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_RGB_ALPHA) + png_set_rgb_to_gray_fixed(png_ptr, error_action, + int red_weight, int green_weight); + + error_action = 1: silently do the conversion + error_action = 2: issue a warning if the original + image has any pixel where + red != green or red != blue + error_action = 3: issue an error and abort the + conversion if the original + image has any pixel where + red != green or red != blue + + red_weight: weight of red component times 100000 + green_weight: weight of green component times 100000 + If either weight is negative, default + weights (21268, 71514) are used. + +If you have set error_action = 1 or 2, you can +later check whether the image really was gray, after processing +the image rows, with the png_get_rgb_to_gray_status(png_ptr) function. +It will return a png_byte that is zero if the image was gray or +1 if there were any non-gray pixels. bKGD and sBIT data +will be silently converted to grayscale, using the green channel +data, regardless of the error_action setting. + +With red_weight+green_weight<=100000, +the normalized graylevel is computed: + + int rw = red_weight * 65536; + int gw = green_weight * 65536; + int bw = 65536 - (rw + gw); + gray = (rw*red + gw*green + bw*blue)/65536; + +The default values approximate those recommended in the Charles +Poynton's Color FAQ, +Copyright (c) 1998-01-04 Charles Poynton + + Y = 0.212671 * R + 0.715160 * G + 0.072169 * B + +Libpng approximates this with + + Y = 0.21268 * R + 0.7151 * G + 0.07217 * B + +which can be expressed with integers as + + Y = (6969 * R + 23434 * G + 2365 * B)/32768 + +The calculation is done in a linear colorspace, if the image gamma +is known. + +If you have a grayscale and you are using png_set_expand_depth(), +png_set_expand(), or png_set_gray_to_rgb to change to truecolor or to +a higher bit-depth, you must either supply the background color as a gray +value at the original file bit-depth (need_expand = 1) or else supply the +background color as an RGB triplet at the final, expanded bit depth +(need_expand = 0). Similarly, if you are reading a paletted image, you +must either supply the background color as a palette index (need_expand = 1) +or as an RGB triplet that may or may not be in the palette (need_expand = 0). + + png_color_16 my_background; + png_color_16p image_background; + + if (png_get_bKGD(png_ptr, info_ptr, &image_background)) + png_set_background(png_ptr, image_background, + PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); + else + png_set_background(png_ptr, &my_background, + PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); + +The png_set_background() function tells libpng to composite images +with alpha or simple transparency against the supplied background +color. If the PNG file contains a bKGD chunk (PNG_INFO_bKGD valid), +you may use this color, or supply another color more suitable for +the current display (e.g., the background color from a web page). You +need to tell libpng whether the color is in the gamma space of the +display (PNG_BACKGROUND_GAMMA_SCREEN for colors you supply), the file +(PNG_BACKGROUND_GAMMA_FILE for colors from the bKGD chunk), or one +that is neither of these gammas (PNG_BACKGROUND_GAMMA_UNIQUE - I don't +know why anyone would use this, but it's here). + +To properly display PNG images on any kind of system, the application needs +to know what the display gamma is. Ideally, the user will know this, and +the application will allow them to set it. One method of allowing the user +to set the display gamma separately for each system is to check for a +SCREEN_GAMMA or DISPLAY_GAMMA environment variable, which will hopefully be +correctly set. + +Note that display_gamma is the overall gamma correction required to produce +pleasing results, which depends on the lighting conditions in the surrounding +environment. In a dim or brightly lit room, no compensation other than +the physical gamma exponent of the monitor is needed, while in a dark room +a slightly smaller exponent is better. + + double gamma, screen_gamma; + + if (/* We have a user-defined screen + gamma value */) + { + screen_gamma = user_defined_screen_gamma; + } + /* One way that applications can share the same + screen gamma value */ + else if ((gamma_str = getenv("SCREEN_GAMMA")) + != NULL) + { + screen_gamma = (double)atof(gamma_str); + } + /* If we don't have another value */ + else + { + screen_gamma = 2.2; /* A good guess for a + PC monitor in a bright office or a dim room */ + screen_gamma = 2.0; /* A good guess for a + PC monitor in a dark room */ + screen_gamma = 1.7 or 1.0; /* A good + guess for Mac systems */ + } + +The png_set_gamma() function handles gamma transformations of the data. +Pass both the file gamma and the current screen_gamma. If the file does +not have a gamma value, you can pass one anyway if you have an idea what +it is (usually 0.45455 is a good guess for GIF images on PCs). Note +that file gammas are inverted from screen gammas. See the discussions +on gamma in the PNG specification for an excellent description of what +gamma is, and why all applications should support it. It is strongly +recommended that PNG viewers support gamma correction. + + if (png_get_gAMA(png_ptr, info_ptr, &gamma)) + png_set_gamma(png_ptr, screen_gamma, gamma); + else + png_set_gamma(png_ptr, screen_gamma, 0.45455); + +If you need to reduce an RGB file to a paletted file, or if a paletted +file has more entries then will fit on your screen, png_set_quantize() +will do that. Note that this is a simple match dither that merely +finds the closest color available. This should work fairly well with +optimized palettes, and fairly badly with linear color cubes. If you +pass a palette that is larger then maximum_colors, the file will +reduce the number of colors in the palette so it will fit into +maximum_colors. If there is a histogram, it will use it to make +more intelligent choices when reducing the palette. If there is no +histogram, it may not do as good a job. + + if (color_type & PNG_COLOR_MASK_COLOR) + { + if (png_get_valid(png_ptr, info_ptr, + PNG_INFO_PLTE)) + { + png_uint_16p histogram = NULL; + + png_get_hIST(png_ptr, info_ptr, + &histogram); + png_set_quantize(png_ptr, palette, num_palette, + max_screen_colors, histogram, 1); + } + else + { + png_color std_color_cube[MAX_SCREEN_COLORS] = + { ... colors ... }; + + png_set_quantize(png_ptr, std_color_cube, + MAX_SCREEN_COLORS, MAX_SCREEN_COLORS, + NULL,0); + } + } + +PNG files describe monochrome as black being zero and white being one. +The following code will reverse this (make black be one and white be +zero): + + if (bit_depth == 1 && color_type == PNG_COLOR_TYPE_GRAY) + png_set_invert_mono(png_ptr); + +This function can also be used to invert grayscale and gray-alpha images: + + if (color_type == PNG_COLOR_TYPE_GRAY || + color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_invert_mono(png_ptr); + +PNG files store 16 bit pixels in network byte order (big-endian, +ie. most significant bits first). This code changes the storage to the +other way (little-endian, i.e. least significant bits first, the +way PCs store them): + + if (bit_depth == 16) + png_set_swap(png_ptr); + +If you are using packed-pixel images (1, 2, or 4 bits/pixel), and you +need to change the order the pixels are packed into bytes, you can use: + + if (bit_depth < 8) + png_set_packswap(png_ptr); + +Finally, you can write your own transformation function if none of +the existing ones meets your needs. This is done by setting a callback +with + + png_set_read_user_transform_fn(png_ptr, + read_transform_fn); + +You must supply the function + + void read_transform_fn(png_ptr ptr, row_info_ptr + row_info, png_bytep data) + +See pngtest.c for a working example. Your function will be called +after all of the other transformations have been processed. + +You can also set up a pointer to a user structure for use by your +callback function, and you can inform libpng that your transform +function will change the number of channels or bit depth with the +function + + png_set_user_transform_info(png_ptr, user_ptr, + user_depth, user_channels); + +The user's application, not libpng, is responsible for allocating and +freeing any memory required for the user structure. + +You can retrieve the pointer via the function +png_get_user_transform_ptr(). For example: + + voidp read_user_transform_ptr = + png_get_user_transform_ptr(png_ptr); + +The last thing to handle is interlacing; this is covered in detail below, +but you must call the function here if you want libpng to handle expansion +of the interlaced image. + + number_of_passes = png_set_interlace_handling(png_ptr); + +After setting the transformations, libpng can update your png_info +structure to reflect any transformations you've requested with this +call. This is most useful to update the info structure's rowbytes +field so you can use it to allocate your image memory. This function +will also update your palette with the correct screen_gamma and +background if these have been given with the calls above. + + png_read_update_info(png_ptr, info_ptr); + +After you call png_read_update_info(), you can allocate any +memory you need to hold the image. The row data is simply +raw byte data for all forms of images. As the actual allocation +varies among applications, no example will be given. If you +are allocating one large chunk, you will need to build an +array of pointers to each row, as it will be needed for some +of the functions below. + +Reading image data + +After you've allocated memory, you can read the image data. +The simplest way to do this is in one function call. If you are +allocating enough memory to hold the whole image, you can just +call png_read_image() and libpng will read in all the image data +and put it in the memory area supplied. You will need to pass in +an array of pointers to each row. + +This function automatically handles interlacing, so you don't need +to call png_set_interlace_handling() or call this function multiple +times, or any of that other stuff necessary with png_read_rows(). + + png_read_image(png_ptr, row_pointers); + +where row_pointers is: + + png_bytep row_pointers[height]; + +You can point to void or char or whatever you use for pixels. + +If you don't want to read in the whole image at once, you can +use png_read_rows() instead. If there is no interlacing (check +interlace_type == PNG_INTERLACE_NONE), this is simple: + + png_read_rows(png_ptr, row_pointers, NULL, + number_of_rows); + +where row_pointers is the same as in the png_read_image() call. + +If you are doing this just one row at a time, you can do this with +a single row_pointer instead of an array of row_pointers: + + png_bytep row_pointer = row; + png_read_row(png_ptr, row_pointer, NULL); + +If the file is interlaced (interlace_type != 0 in the IHDR chunk), things +get somewhat harder. The only current (PNG Specification version 1.2) +interlacing type for PNG is (interlace_type == PNG_INTERLACE_ADAM7) +is a somewhat complicated 2D interlace scheme, known as Adam7, that +breaks down an image into seven smaller images of varying size, based +on an 8x8 grid. + +libpng can fill out those images or it can give them to you "as is". +If you want them filled out, there are two ways to do that. The one +mentioned in the PNG specification is to expand each pixel to cover +those pixels that have not been read yet (the "rectangle" method). +This results in a blocky image for the first pass, which gradually +smooths out as more pixels are read. The other method is the "sparkle" +method, where pixels are drawn only in their final locations, with the +rest of the image remaining whatever colors they were initialized to +before the start of the read. The first method usually looks better, +but tends to be slower, as there are more pixels to put in the rows. + +If you don't want libpng to handle the interlacing details, just call +png_read_rows() seven times to read in all seven images. Each of the +images is a valid image by itself, or they can all be combined on an +8x8 grid to form a single image (although if you intend to combine them +you would be far better off using the libpng interlace handling). + +The first pass will return an image 1/8 as wide as the entire image +(every 8th column starting in column 0) and 1/8 as high as the original +(every 8th row starting in row 0), the second will be 1/8 as wide +(starting in column 4) and 1/8 as high (also starting in row 0). The +third pass will be 1/4 as wide (every 4th pixel starting in column 0) and +1/8 as high (every 8th row starting in row 4), and the fourth pass will +be 1/4 as wide and 1/4 as high (every 4th column starting in column 2, +and every 4th row starting in row 0). The fifth pass will return an +image 1/2 as wide, and 1/4 as high (starting at column 0 and row 2), +while the sixth pass will be 1/2 as wide and 1/2 as high as the original +(starting in column 1 and row 0). The seventh and final pass will be as +wide as the original, and 1/2 as high, containing all of the odd +numbered scanlines. Phew! + +If you want libpng to expand the images, call this before calling +png_start_read_image() or png_read_update_info(): + + if (interlace_type == PNG_INTERLACE_ADAM7) + number_of_passes + = png_set_interlace_handling(png_ptr); + +This will return the number of passes needed. Currently, this +is seven, but may change if another interlace type is added. +This function can be called even if the file is not interlaced, +where it will return one pass. + +If you are not going to display the image after each pass, but are +going to wait until the entire image is read in, use the sparkle +effect. This effect is faster and the end result of either method +is exactly the same. If you are planning on displaying the image +after each pass, the "rectangle" effect is generally considered the +better looking one. + +If you only want the "sparkle" effect, just call png_read_rows() as +normal, with the third parameter NULL. Make sure you make pass over +the image number_of_passes times, and you don't change the data in the +rows between calls. You can change the locations of the data, just +not the data. Each pass only writes the pixels appropriate for that +pass, and assumes the data from previous passes is still valid. + + png_read_rows(png_ptr, row_pointers, NULL, + number_of_rows); + +If you only want the first effect (the rectangles), do the same as +before except pass the row buffer in the third parameter, and leave +the second parameter NULL. + + png_read_rows(png_ptr, NULL, row_pointers, + number_of_rows); + +Finishing a sequential read + +After you are finished reading the image through the +low-level interface, you can finish reading the file. If you are +interested in comments or time, which may be stored either before or +after the image data, you should pass the separate png_info struct if +you want to keep the comments from before and after the image +separate. If you are not interested, you can pass NULL. + + png_read_end(png_ptr, end_info); + +When you are done, you can free all memory allocated by libpng like this: + + png_destroy_read_struct(&png_ptr, &info_ptr, + &end_info); + +It is also possible to individually free the info_ptr members that +point to libpng-allocated storage with the following function: + + png_free_data(png_ptr, info_ptr, mask, seq) + mask - identifies data to be freed, a mask + containing the bitwise OR of one or + more of + PNG_FREE_PLTE, PNG_FREE_TRNS, + PNG_FREE_HIST, PNG_FREE_ICCP, + PNG_FREE_PCAL, PNG_FREE_ROWS, + PNG_FREE_SCAL, PNG_FREE_SPLT, + PNG_FREE_TEXT, PNG_FREE_UNKN, + or simply PNG_FREE_ALL + seq - sequence number of item to be freed + (-1 for all items) + +This function may be safely called when the relevant storage has +already been freed, or has not yet been allocated, or was allocated +by the user and not by libpng, and will in those cases do nothing. +The "seq" parameter is ignored if only one item of the selected data +type, such as PLTE, is allowed. If "seq" is not -1, and multiple items +are allowed for the data type identified in the mask, such as text or +sPLT, only the n'th item in the structure is freed, where n is "seq". + +The default behavior is only to free data that was allocated internally +by libpng. This can be changed, so that libpng will not free the data, +or so that it will free data that was allocated by the user with png_malloc() +or png_zalloc() and passed in via a png_set_*() function, with + + png_data_freer(png_ptr, info_ptr, freer, mask) + mask - which data elements are affected + same choices as in png_free_data() + freer - one of + PNG_DESTROY_WILL_FREE_DATA + PNG_SET_WILL_FREE_DATA + PNG_USER_WILL_FREE_DATA + +This function only affects data that has already been allocated. +You can call this function after reading the PNG data but before calling +any png_set_*() functions, to control whether the user or the png_set_*() +function is responsible for freeing any existing data that might be present, +and again after the png_set_*() functions to control whether the user +or png_destroy_*() is supposed to free the data. When the user assumes +responsibility for libpng-allocated data, the application must use +png_free() to free it, and when the user transfers responsibility to libpng +for data that the user has allocated, the user must have used png_malloc() +or png_zalloc() to allocate it. + +If you allocated your row_pointers in a single block, as suggested above in +the description of the high level read interface, you must not transfer +responsibility for freeing it to the png_set_rows or png_read_destroy function, +because they would also try to free the individual row_pointers[i]. + +If you allocated text_ptr.text, text_ptr.lang, and text_ptr.translated_keyword +separately, do not transfer responsibility for freeing text_ptr to libpng, +because when libpng fills a png_text structure it combines these members with +the key member, and png_free_data() will free only text_ptr.key. Similarly, +if you transfer responsibility for free'ing text_ptr from libpng to your +application, your application must not separately free those members. + +The png_free_data() function will turn off the "valid" flag for anything +it frees. If you need to turn the flag off for a chunk that was freed by +your application instead of by libpng, you can use + + png_set_invalid(png_ptr, info_ptr, mask); + mask - identifies the chunks to be made invalid, + containing the bitwise OR of one or + more of + PNG_INFO_gAMA, PNG_INFO_sBIT, + PNG_INFO_cHRM, PNG_INFO_PLTE, + PNG_INFO_tRNS, PNG_INFO_bKGD, + PNG_INFO_hIST, PNG_INFO_pHYs, + PNG_INFO_oFFs, PNG_INFO_tIME, + PNG_INFO_pCAL, PNG_INFO_sRGB, + PNG_INFO_iCCP, PNG_INFO_sPLT, + PNG_INFO_sCAL, PNG_INFO_IDAT + +For a more compact example of reading a PNG image, see the file example.c. + +Reading PNG files progressively + +The progressive reader is slightly different then the non-progressive +reader. Instead of calling png_read_info(), png_read_rows(), and +png_read_end(), you make one call to png_process_data(), which calls +callbacks when it has the info, a row, or the end of the image. You +set up these callbacks with png_set_progressive_read_fn(). You don't +have to worry about the input/output functions of libpng, as you are +giving the library the data directly in png_process_data(). I will +assume that you have read the section on reading PNG files above, +so I will only highlight the differences (although I will show +all of the code). + +png_structp png_ptr; +png_infop info_ptr; + + /* An example code fragment of how you would + initialize the progressive reader in your + application. */ + int + initialize_png_reader() + { + png_ptr = png_create_read_struct + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + user_error_fn, user_warning_fn); + if (!png_ptr) + return (ERROR); + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + { + png_destroy_read_struct(&png_ptr, (png_infopp)NULL, + (png_infopp)NULL); + return (ERROR); + } + + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_read_struct(&png_ptr, &info_ptr, + (png_infopp)NULL); + return (ERROR); + } + + /* This one's new. You can provide functions + to be called when the header info is valid, + when each row is completed, and when the image + is finished. If you aren't using all functions, + you can specify NULL parameters. Even when all + three functions are NULL, you need to call + png_set_progressive_read_fn(). You can use + any struct as the user_ptr (cast to a void pointer + for the function call), and retrieve the pointer + from inside the callbacks using the function + + png_get_progressive_ptr(png_ptr); + + which will return a void pointer, which you have + to cast appropriately. + */ + png_set_progressive_read_fn(png_ptr, (void *)user_ptr, + info_callback, row_callback, end_callback); + + return 0; + } + + /* A code fragment that you call as you receive blocks + of data */ + int + process_data(png_bytep buffer, png_uint_32 length) + { + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_read_struct(&png_ptr, &info_ptr, + (png_infopp)NULL); + return (ERROR); + } + + /* This one's new also. Simply give it a chunk + of data from the file stream (in order, of + course). On machines with segmented memory + models machines, don't give it any more than + 64K. The library seems to run fine with sizes + of 4K. Although you can give it much less if + necessary (I assume you can give it chunks of + 1 byte, I haven't tried less then 256 bytes + yet). When this function returns, you may + want to display any rows that were generated + in the row callback if you don't already do + so there. + */ + png_process_data(png_ptr, info_ptr, buffer, length); + return 0; + } + + /* This function is called (as set by + png_set_progressive_read_fn() above) when enough data + has been supplied so all of the header has been + read. + */ + void + info_callback(png_structp png_ptr, png_infop info) + { + /* Do any setup here, including setting any of + the transformations mentioned in the Reading + PNG files section. For now, you _must_ call + either png_start_read_image() or + png_read_update_info() after all the + transformations are set (even if you don't set + any). You may start getting rows before + png_process_data() returns, so this is your + last chance to prepare for that. + */ + } + + /* This function is called when each row of image + data is complete */ + void + row_callback(png_structp png_ptr, png_bytep new_row, + png_uint_32 row_num, int pass) + { + /* If the image is interlaced, and you turned + on the interlace handler, this function will + be called for every row in every pass. Some + of these rows will not be changed from the + previous pass. When the row is not changed, + the new_row variable will be NULL. The rows + and passes are called in order, so you don't + really need the row_num and pass, but I'm + supplying them because it may make your life + easier. + + For the non-NULL rows of interlaced images, + you must call png_progressive_combine_row() + passing in the row and the old row. You can + call this function for NULL rows (it will just + return) and for non-interlaced images (it just + does the memcpy for you) if it will make the + code easier. Thus, you can just do this for + all cases: + */ + + png_progressive_combine_row(png_ptr, old_row, + new_row); + + /* where old_row is what was displayed for + previously for the row. Note that the first + pass (pass == 0, really) will completely cover + the old row, so the rows do not have to be + initialized. After the first pass (and only + for interlaced images), you will have to pass + the current row, and the function will combine + the old row and the new row. + */ + } + + void + end_callback(png_structp png_ptr, png_infop info) + { + /* This function is called after the whole image + has been read, including any chunks after the + image (up to and including the IEND). You + will usually have the same info chunk as you + had in the header, although some data may have + been added to the comments and time fields. + + Most people won't do much here, perhaps setting + a flag that marks the image as finished. + */ + } + + + +IV. Writing + +Much of this is very similar to reading. However, everything of +importance is repeated here, so you won't have to constantly look +back up in the reading section to understand writing. + +Setup + +You will want to do the I/O initialization before you get into libpng, +so if it doesn't work, you don't have anything to undo. If you are not +using the standard I/O functions, you will need to replace them with +custom writing functions. See the discussion under Customizing libpng. + + FILE *fp = fopen(file_name, "wb"); + if (!fp) + { + return (ERROR); + } + +Next, png_struct and png_info need to be allocated and initialized. +As these can be both relatively large, you may not want to store these +on the stack, unless you have stack space to spare. Of course, you +will want to check if they return NULL. If you are also reading, +you won't want to name your read structure and your write structure +both "png_ptr"; you can call them anything you like, such as +"read_ptr" and "write_ptr". Look at pngtest.c, for example. + + png_structp png_ptr = png_create_write_struct + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + user_error_fn, user_warning_fn); + if (!png_ptr) + return (ERROR); + + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + { + png_destroy_write_struct(&png_ptr, + (png_infopp)NULL); + return (ERROR); + } + +If you want to use your own memory allocation routines, +define PNG_USER_MEM_SUPPORTED and use +png_create_write_struct_2() instead of png_create_write_struct(): + + png_structp png_ptr = png_create_write_struct_2 + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + user_error_fn, user_warning_fn, (png_voidp) + user_mem_ptr, user_malloc_fn, user_free_fn); + +After you have these structures, you will need to set up the +error handling. When libpng encounters an error, it expects to +longjmp() back to your routine. Therefore, you will need to call +setjmp() and pass the png_jmpbuf(png_ptr). If you +write the file from different routines, you will need to update +the png_jmpbuf(png_ptr) every time you enter a new routine that will +call a png_*() function. See your documentation of setjmp/longjmp +for your compiler for more information on setjmp/longjmp. See +the discussion on libpng error handling in the Customizing Libpng +section below for more information on the libpng error handling. + + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_write_struct(&png_ptr, &info_ptr); + fclose(fp); + return (ERROR); + } + ... + return; + +If you would rather avoid the complexity of setjmp/longjmp issues, +you can compile libpng with PNG_NO_SETJMP, in which case +errors will result in a call to PNG_ABORT() which defaults to abort(). + +You can #define PNG_ABORT() to a function that does something +more useful than abort(), as long as your function does not +return. + +Now you need to set up the output code. The default for libpng is to +use the C function fwrite(). If you use this, you will need to pass a +valid FILE * in the function png_init_io(). Be sure that the file is +opened in binary mode. Again, if you wish to handle writing data in +another way, see the discussion on libpng I/O handling in the Customizing +Libpng section below. + + png_init_io(png_ptr, fp); + +If you are embedding your PNG into a datastream such as MNG, and don't +want libpng to write the 8-byte signature, or if you have already +written the signature in your application, use + + png_set_sig_bytes(png_ptr, 8); + +to inform libpng that it should not write a signature. + +Write callbacks + +At this point, you can set up a callback function that will be +called after each row has been written, which you can use to control +a progress meter or the like. It's demonstrated in pngtest.c. +You must supply a function + + void write_row_callback(png_ptr, png_uint_32 row, + int pass); + { + /* put your code here */ + } + +(You can give it another name that you like instead of "write_row_callback") + +To inform libpng about your function, use + + png_set_write_status_fn(png_ptr, write_row_callback); + +You now have the option of modifying how the compression library will +run. The following functions are mainly for testing, but may be useful +in some cases, like if you need to write PNG files extremely fast and +are willing to give up some compression, or if you want to get the +maximum possible compression at the expense of slower writing. If you +have no special needs in this area, let the library do what it wants by +not calling this function at all, as it has been tuned to deliver a good +speed/compression ratio. The second parameter to png_set_filter() is +the filter method, for which the only valid values are 0 (as of the +July 1999 PNG specification, version 1.2) or 64 (if you are writing +a PNG datastream that is to be embedded in a MNG datastream). The third +parameter is a flag that indicates which filter type(s) are to be tested +for each scanline. See the PNG specification for details on the specific +filter types. + + + /* turn on or off filtering, and/or choose + specific filters. You can use either a single + PNG_FILTER_VALUE_NAME or the bitwise OR of one + or more PNG_FILTER_NAME masks. */ + png_set_filter(png_ptr, 0, + PNG_FILTER_NONE | PNG_FILTER_VALUE_NONE | + PNG_FILTER_SUB | PNG_FILTER_VALUE_SUB | + PNG_FILTER_UP | PNG_FILTER_VALUE_UP | + PNG_FILTER_AVG | PNG_FILTER_VALUE_AVG | + PNG_FILTER_PAETH | PNG_FILTER_VALUE_PAETH| + PNG_ALL_FILTERS); + +If an application +wants to start and stop using particular filters during compression, +it should start out with all of the filters (to ensure that the previous +row of pixels will be stored in case it's needed later), and then add +and remove them after the start of compression. + +If you are writing a PNG datastream that is to be embedded in a MNG +datastream, the second parameter can be either 0 or 64. + +The png_set_compression_*() functions interface to the zlib compression +library, and should mostly be ignored unless you really know what you are +doing. The only generally useful call is png_set_compression_level() +which changes how much time zlib spends on trying to compress the image +data. See the Compression Library (zlib.h and algorithm.txt, distributed +with zlib) for details on the compression levels. + + /* set the zlib compression level */ + png_set_compression_level(png_ptr, + Z_BEST_COMPRESSION); + + /* set other zlib parameters */ + png_set_compression_mem_level(png_ptr, 8); + png_set_compression_strategy(png_ptr, + Z_DEFAULT_STRATEGY); + png_set_compression_window_bits(png_ptr, 15); + png_set_compression_method(png_ptr, 8); + png_set_compression_buffer_size(png_ptr, 8192) + +extern PNG_EXPORT(void,png_set_zbuf_size) + +Setting the contents of info for output + +You now need to fill in the png_info structure with all the data you +wish to write before the actual image. Note that the only thing you +are allowed to write after the image is the text chunks and the time +chunk (as of PNG Specification 1.2, anyway). See png_write_end() and +the latest PNG specification for more information on that. If you +wish to write them before the image, fill them in now, and flag that +data as being valid. If you want to wait until after the data, don't +fill them until png_write_end(). For all the fields in png_info and +their data types, see png.h. For explanations of what the fields +contain, see the PNG specification. + +Some of the more important parts of the png_info are: + + png_set_IHDR(png_ptr, info_ptr, width, height, + bit_depth, color_type, interlace_type, + compression_type, filter_method) + width - holds the width of the image + in pixels (up to 2^31). + height - holds the height of the image + in pixels (up to 2^31). + bit_depth - holds the bit depth of one of the + image channels. + (valid values are 1, 2, 4, 8, 16 + and depend also on the + color_type. See also significant + bits (sBIT) below). + color_type - describes which color/alpha + channels are present. + PNG_COLOR_TYPE_GRAY + (bit depths 1, 2, 4, 8, 16) + PNG_COLOR_TYPE_GRAY_ALPHA + (bit depths 8, 16) + PNG_COLOR_TYPE_PALETTE + (bit depths 1, 2, 4, 8) + PNG_COLOR_TYPE_RGB + (bit_depths 8, 16) + PNG_COLOR_TYPE_RGB_ALPHA + (bit_depths 8, 16) + + PNG_COLOR_MASK_PALETTE + PNG_COLOR_MASK_COLOR + PNG_COLOR_MASK_ALPHA + + interlace_type - PNG_INTERLACE_NONE or + PNG_INTERLACE_ADAM7 + compression_type - (must be + PNG_COMPRESSION_TYPE_DEFAULT) + filter_method - (must be PNG_FILTER_TYPE_DEFAULT + or, if you are writing a PNG to + be embedded in a MNG datastream, + can also be + PNG_INTRAPIXEL_DIFFERENCING) + +If you call png_set_IHDR(), the call must appear before any of the +other png_set_*() functions, because they might require access to some of +the IHDR settings. The remaining png_set_*() functions can be called +in any order. + +If you wish, you can reset the compression_type, interlace_type, or +filter_method later by calling png_set_IHDR() again; if you do this, the +width, height, bit_depth, and color_type must be the same in each call. + + png_set_PLTE(png_ptr, info_ptr, palette, + num_palette); + palette - the palette for the file + (array of png_color) + num_palette - number of entries in the palette + + png_set_gAMA(png_ptr, info_ptr, gamma); + gamma - the gamma the image was created + at (PNG_INFO_gAMA) + + png_set_sRGB(png_ptr, info_ptr, srgb_intent); + srgb_intent - the rendering intent + (PNG_INFO_sRGB) The presence of + the sRGB chunk means that the pixel + data is in the sRGB color space. + This chunk also implies specific + values of gAMA and cHRM. Rendering + intent is the CSS-1 property that + has been defined by the International + Color Consortium + (http://www.color.org). + It can be one of + PNG_sRGB_INTENT_SATURATION, + PNG_sRGB_INTENT_PERCEPTUAL, + PNG_sRGB_INTENT_ABSOLUTE, or + PNG_sRGB_INTENT_RELATIVE. + + + png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, + srgb_intent); + srgb_intent - the rendering intent + (PNG_INFO_sRGB) The presence of the + sRGB chunk means that the pixel + data is in the sRGB color space. + This function also causes gAMA and + cHRM chunks with the specific values + that are consistent with sRGB to be + written. + + png_set_iCCP(png_ptr, info_ptr, name, compression_type, + profile, proflen); + name - The profile name. + compression - The compression type; always + PNG_COMPRESSION_TYPE_BASE for PNG 1.0. + You may give NULL to this argument to + ignore it. + profile - International Color Consortium color + profile data. May contain NULs. + proflen - length of profile data in bytes. + + png_set_sBIT(png_ptr, info_ptr, sig_bit); + sig_bit - the number of significant bits for + (PNG_INFO_sBIT) each of the gray, red, + green, and blue channels, whichever are + appropriate for the given color type + (png_color_16) + + png_set_tRNS(png_ptr, info_ptr, trans_alpha, + num_trans, trans_color); + trans_alpha - array of alpha (transparency) + entries for palette (PNG_INFO_tRNS) + trans_color - graylevel or color sample values + (in order red, green, blue) of the + single transparent color for + non-paletted images (PNG_INFO_tRNS) + num_trans - number of transparent entries + (PNG_INFO_tRNS) + + png_set_hIST(png_ptr, info_ptr, hist); + (PNG_INFO_hIST) + hist - histogram of palette (array of + png_uint_16) + + png_set_tIME(png_ptr, info_ptr, mod_time); + mod_time - time image was last modified + (PNG_VALID_tIME) + + png_set_bKGD(png_ptr, info_ptr, background); + background - background color (PNG_VALID_bKGD) + + png_set_text(png_ptr, info_ptr, text_ptr, num_text); + text_ptr - array of png_text holding image + comments + text_ptr[i].compression - type of compression used + on "text" PNG_TEXT_COMPRESSION_NONE + PNG_TEXT_COMPRESSION_zTXt + PNG_ITXT_COMPRESSION_NONE + PNG_ITXT_COMPRESSION_zTXt + text_ptr[i].key - keyword for comment. Must contain + 1-79 characters. + text_ptr[i].text - text comments for current + keyword. Can be NULL or empty. + text_ptr[i].text_length - length of text string, + after decompression, 0 for iTXt + text_ptr[i].itxt_length - length of itxt string, + after decompression, 0 for tEXt/zTXt + text_ptr[i].lang - language of comment (NULL or + empty for unknown). + text_ptr[i].translated_keyword - keyword in UTF-8 (NULL + or empty for unknown). + Note that the itxt_length, lang, and lang_key + members of the text_ptr structure only exist + when the library is built with iTXt chunk support. + + num_text - number of comments + + png_set_sPLT(png_ptr, info_ptr, &palette_ptr, + num_spalettes); + palette_ptr - array of png_sPLT_struct structures + to be added to the list of palettes + in the info structure. + num_spalettes - number of palette structures to be + added. + + png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, + unit_type); + offset_x - positive offset from the left + edge of the screen + offset_y - positive offset from the top + edge of the screen + unit_type - PNG_OFFSET_PIXEL, PNG_OFFSET_MICROMETER + + png_set_pHYs(png_ptr, info_ptr, res_x, res_y, + unit_type); + res_x - pixels/unit physical resolution + in x direction + res_y - pixels/unit physical resolution + in y direction + unit_type - PNG_RESOLUTION_UNKNOWN, + PNG_RESOLUTION_METER + + png_set_sCAL(png_ptr, info_ptr, unit, width, height) + unit - physical scale units (an integer) + width - width of a pixel in physical scale units + height - height of a pixel in physical scale units + (width and height are doubles) + + png_set_sCAL_s(png_ptr, info_ptr, unit, width, height) + unit - physical scale units (an integer) + width - width of a pixel in physical scale units + height - height of a pixel in physical scale units + (width and height are strings like "2.54") + + png_set_unknown_chunks(png_ptr, info_ptr, &unknowns, + num_unknowns) + unknowns - array of png_unknown_chunk + structures holding unknown chunks + unknowns[i].name - name of unknown chunk + unknowns[i].data - data of unknown chunk + unknowns[i].size - size of unknown chunk's data + unknowns[i].location - position to write chunk in file + 0: do not write chunk + PNG_HAVE_IHDR: before PLTE + PNG_HAVE_PLTE: before IDAT + PNG_AFTER_IDAT: after IDAT + +The "location" member is set automatically according to +what part of the output file has already been written. +You can change its value after calling png_set_unknown_chunks() +as demonstrated in pngtest.c. Within each of the "locations", +the chunks are sequenced according to their position in the +structure (that is, the value of "i", which is the order in which +the chunk was either read from the input file or defined with +png_set_unknown_chunks). + +A quick word about text and num_text. text is an array of png_text +structures. num_text is the number of valid structures in the array. +Each png_text structure holds a language code, a keyword, a text value, +and a compression type. + +The compression types have the same valid numbers as the compression +types of the image data. Currently, the only valid number is zero. +However, you can store text either compressed or uncompressed, unlike +images, which always have to be compressed. So if you don't want the +text compressed, set the compression type to PNG_TEXT_COMPRESSION_NONE. +Because tEXt and zTXt chunks don't have a language field, if you +specify PNG_TEXT_COMPRESSION_NONE or PNG_TEXT_COMPRESSION_zTXt +any language code or translated keyword will not be written out. + +Until text gets around 1000 bytes, it is not worth compressing it. +After the text has been written out to the file, the compression type +is set to PNG_TEXT_COMPRESSION_NONE_WR or PNG_TEXT_COMPRESSION_zTXt_WR, +so that it isn't written out again at the end (in case you are calling +png_write_end() with the same struct. + +The keywords that are given in the PNG Specification are: + + Title Short (one line) title or + caption for image + Author Name of image's creator + Description Description of image (possibly long) + Copyright Copyright notice + Creation Time Time of original image creation + (usually RFC 1123 format, see below) + Software Software used to create the image + Disclaimer Legal disclaimer + Warning Warning of nature of content + Source Device used to create the image + Comment Miscellaneous comment; conversion + from other image format + +The keyword-text pairs work like this. Keywords should be short +simple descriptions of what the comment is about. Some typical +keywords are found in the PNG specification, as is some recommendations +on keywords. You can repeat keywords in a file. You can even write +some text before the image and some after. For example, you may want +to put a description of the image before the image, but leave the +disclaimer until after, so viewers working over modem connections +don't have to wait for the disclaimer to go over the modem before +they start seeing the image. Finally, keywords should be full +words, not abbreviations. Keywords and text are in the ISO 8859-1 +(Latin-1) character set (a superset of regular ASCII) and can not +contain NUL characters, and should not contain control or other +unprintable characters. To make the comments widely readable, stick +with basic ASCII, and avoid machine specific character set extensions +like the IBM-PC character set. The keyword must be present, but +you can leave off the text string on non-compressed pairs. +Compressed pairs must have a text string, as only the text string +is compressed anyway, so the compression would be meaningless. + +PNG supports modification time via the png_time structure. Two +conversion routines are provided, png_convert_from_time_t() for +time_t and png_convert_from_struct_tm() for struct tm. The +time_t routine uses gmtime(). You don't have to use either of +these, but if you wish to fill in the png_time structure directly, +you should provide the time in universal time (GMT) if possible +instead of your local time. Note that the year number is the full +year (e.g. 1998, rather than 98 - PNG is year 2000 compliant!), and +that months start with 1. + +If you want to store the time of the original image creation, you should +use a plain tEXt chunk with the "Creation Time" keyword. This is +necessary because the "creation time" of a PNG image is somewhat vague, +depending on whether you mean the PNG file, the time the image was +created in a non-PNG format, a still photo from which the image was +scanned, or possibly the subject matter itself. In order to facilitate +machine-readable dates, it is recommended that the "Creation Time" +tEXt chunk use RFC 1123 format dates (e.g. "22 May 1997 18:07:10 GMT"), +although this isn't a requirement. Unlike the tIME chunk, the +"Creation Time" tEXt chunk is not expected to be automatically changed +by the software. To facilitate the use of RFC 1123 dates, a function +png_convert_to_rfc1123(png_timep) is provided to convert from PNG +time to an RFC 1123 format string. + +Writing unknown chunks + +You can use the png_set_unknown_chunks function to queue up chunks +for writing. You give it a chunk name, raw data, and a size; that's +all there is to it. The chunks will be written by the next following +png_write_info_before_PLTE, png_write_info, or png_write_end function. +Any chunks previously read into the info structure's unknown-chunk +list will also be written out in a sequence that satisfies the PNG +specification's ordering rules. + +The high-level write interface + +At this point there are two ways to proceed; through the high-level +write interface, or through a sequence of low-level write operations. +You can use the high-level interface if your image data is present +in the info structure. All defined output +transformations are permitted, enabled by the following masks. + + PNG_TRANSFORM_IDENTITY No transformation + PNG_TRANSFORM_PACKING Pack 1, 2 and 4-bit samples + PNG_TRANSFORM_PACKSWAP Change order of packed + pixels to LSB first + PNG_TRANSFORM_INVERT_MONO Invert monochrome images + PNG_TRANSFORM_SHIFT Normalize pixels to the + sBIT depth + PNG_TRANSFORM_BGR Flip RGB to BGR, RGBA + to BGRA + PNG_TRANSFORM_SWAP_ALPHA Flip RGBA to ARGB or GA + to AG + PNG_TRANSFORM_INVERT_ALPHA Change alpha from opacity + to transparency + PNG_TRANSFORM_SWAP_ENDIAN Byte-swap 16-bit samples + PNG_TRANSFORM_STRIP_FILLER Strip out filler + bytes (deprecated). + PNG_TRANSFORM_STRIP_FILLER_BEFORE Strip out leading + filler bytes + PNG_TRANSFORM_STRIP_FILLER_AFTER Strip out trailing + filler bytes + +If you have valid image data in the info structure (you can use +png_set_rows() to put image data in the info structure), simply do this: + + png_write_png(png_ptr, info_ptr, png_transforms, NULL) + +where png_transforms is an integer containing the bitwise OR of some set of +transformation flags. This call is equivalent to png_write_info(), +followed the set of transformations indicated by the transform mask, +then png_write_image(), and finally png_write_end(). + +(The final parameter of this call is not yet used. Someday it might point +to transformation parameters required by some future output transform.) + +You must use png_transforms and not call any png_set_transform() functions +when you use png_write_png(). + +The low-level write interface + +If you are going the low-level route instead, you are now ready to +write all the file information up to the actual image data. You do +this with a call to png_write_info(). + + png_write_info(png_ptr, info_ptr); + +Note that there is one transformation you may need to do before +png_write_info(). In PNG files, the alpha channel in an image is the +level of opacity. If your data is supplied as a level of transparency, +you can invert the alpha channel before you write it, so that 0 is +fully transparent and 255 (in 8-bit or paletted images) or 65535 +(in 16-bit images) is fully opaque, with + + png_set_invert_alpha(png_ptr); + +This must appear before png_write_info() instead of later with the +other transformations because in the case of paletted images the tRNS +chunk data has to be inverted before the tRNS chunk is written. If +your image is not a paletted image, the tRNS data (which in such cases +represents a single color to be rendered as transparent) won't need to +be changed, and you can safely do this transformation after your +png_write_info() call. + +If you need to write a private chunk that you want to appear before +the PLTE chunk when PLTE is present, you can write the PNG info in +two steps, and insert code to write your own chunk between them: + + png_write_info_before_PLTE(png_ptr, info_ptr); + png_set_unknown_chunks(png_ptr, info_ptr, ...); + png_write_info(png_ptr, info_ptr); + +After you've written the file information, you can set up the library +to handle any special transformations of the image data. The various +ways to transform the data will be described in the order that they +should occur. This is important, as some of these change the color +type and/or bit depth of the data, and some others only work on +certain color types and bit depths. Even though each transformation +checks to see if it has data that it can do something with, you should +make sure to only enable a transformation if it will be valid for the +data. For example, don't swap red and blue on grayscale data. + +PNG files store RGB pixels packed into 3 or 6 bytes. This code tells +the library to strip input data that has 4 or 8 bytes per pixel down +to 3 or 6 bytes (or strip 2 or 4-byte grayscale+filler data to 1 or 2 +bytes per pixel). + + png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); + +where the 0 is unused, and the location is either PNG_FILLER_BEFORE or +PNG_FILLER_AFTER, depending upon whether the filler byte in the pixel +is stored XRGB or RGBX. + +PNG files pack pixels of bit depths 1, 2, and 4 into bytes as small as +they can, resulting in, for example, 8 pixels per byte for 1 bit files. +If the data is supplied at 1 pixel per byte, use this code, which will +correctly pack the pixels into a single byte: + + png_set_packing(png_ptr); + +PNG files reduce possible bit depths to 1, 2, 4, 8, and 16. If your +data is of another bit depth, you can write an sBIT chunk into the +file so that decoders can recover the original data if desired. + + /* Set the true bit depth of the image data */ + if (color_type & PNG_COLOR_MASK_COLOR) + { + sig_bit.red = true_bit_depth; + sig_bit.green = true_bit_depth; + sig_bit.blue = true_bit_depth; + } + else + { + sig_bit.gray = true_bit_depth; + } + if (color_type & PNG_COLOR_MASK_ALPHA) + { + sig_bit.alpha = true_bit_depth; + } + + png_set_sBIT(png_ptr, info_ptr, &sig_bit); + +If the data is stored in the row buffer in a bit depth other than +one supported by PNG (e.g. 3 bit data in the range 0-7 for a 4-bit PNG), +this will scale the values to appear to be the correct bit depth as +is required by PNG. + + png_set_shift(png_ptr, &sig_bit); + +PNG files store 16 bit pixels in network byte order (big-endian, +ie. most significant bits first). This code would be used if they are +supplied the other way (little-endian, i.e. least significant bits +first, the way PCs store them): + + if (bit_depth > 8) + png_set_swap(png_ptr); + +If you are using packed-pixel images (1, 2, or 4 bits/pixel), and you +need to change the order the pixels are packed into bytes, you can use: + + if (bit_depth < 8) + png_set_packswap(png_ptr); + +PNG files store 3 color pixels in red, green, blue order. This code +would be used if they are supplied as blue, green, red: + + png_set_bgr(png_ptr); + +PNG files describe monochrome as black being zero and white being +one. This code would be used if the pixels are supplied with this reversed +(black being one and white being zero): + + png_set_invert_mono(png_ptr); + +Finally, you can write your own transformation function if none of +the existing ones meets your needs. This is done by setting a callback +with + + png_set_write_user_transform_fn(png_ptr, + write_transform_fn); + +You must supply the function + + void write_transform_fn(png_ptr ptr, row_info_ptr + row_info, png_bytep data) + +See pngtest.c for a working example. Your function will be called +before any of the other transformations are processed. + +You can also set up a pointer to a user structure for use by your +callback function. + + png_set_user_transform_info(png_ptr, user_ptr, 0, 0); + +The user_channels and user_depth parameters of this function are ignored +when writing; you can set them to zero as shown. + +You can retrieve the pointer via the function png_get_user_transform_ptr(). +For example: + + voidp write_user_transform_ptr = + png_get_user_transform_ptr(png_ptr); + +It is possible to have libpng flush any pending output, either manually, +or automatically after a certain number of lines have been written. To +flush the output stream a single time call: + + png_write_flush(png_ptr); + +and to have libpng flush the output stream periodically after a certain +number of scanlines have been written, call: + + png_set_flush(png_ptr, nrows); + +Note that the distance between rows is from the last time png_write_flush() +was called, or the first row of the image if it has never been called. +So if you write 50 lines, and then png_set_flush 25, it will flush the +output on the next scanline, and every 25 lines thereafter, unless +png_write_flush() is called before 25 more lines have been written. +If nrows is too small (less than about 10 lines for a 640 pixel wide +RGB image) the image compression may decrease noticeably (although this +may be acceptable for real-time applications). Infrequent flushing will +only degrade the compression performance by a few percent over images +that do not use flushing. + +Writing the image data + +That's it for the transformations. Now you can write the image data. +The simplest way to do this is in one function call. If you have the +whole image in memory, you can just call png_write_image() and libpng +will write the image. You will need to pass in an array of pointers to +each row. This function automatically handles interlacing, so you don't +need to call png_set_interlace_handling() or call this function multiple +times, or any of that other stuff necessary with png_write_rows(). + + png_write_image(png_ptr, row_pointers); + +where row_pointers is: + + png_byte *row_pointers[height]; + +You can point to void or char or whatever you use for pixels. + +If you don't want to write the whole image at once, you can +use png_write_rows() instead. If the file is not interlaced, +this is simple: + + png_write_rows(png_ptr, row_pointers, + number_of_rows); + +row_pointers is the same as in the png_write_image() call. + +If you are just writing one row at a time, you can do this with +a single row_pointer instead of an array of row_pointers: + + png_bytep row_pointer = row; + + png_write_row(png_ptr, row_pointer); + +When the file is interlaced, things can get a good deal more complicated. +The only currently (as of the PNG Specification version 1.2, dated July +1999) defined interlacing scheme for PNG files is the "Adam7" interlace +scheme, that breaks down an image into seven smaller images of varying +size. libpng will build these images for you, or you can do them +yourself. If you want to build them yourself, see the PNG specification +for details of which pixels to write when. + +If you don't want libpng to handle the interlacing details, just +use png_set_interlace_handling() and call png_write_rows() the +correct number of times to write all seven sub-images. + +If you want libpng to build the sub-images, call this before you start +writing any rows: + + number_of_passes = + png_set_interlace_handling(png_ptr); + +This will return the number of passes needed. Currently, this is seven, +but may change if another interlace type is added. + +Then write the complete image number_of_passes times. + + png_write_rows(png_ptr, row_pointers, + number_of_rows); + +As some of these rows are not used, and thus return immediately, you may +want to read about interlacing in the PNG specification, and only update +the rows that are actually used. + +Finishing a sequential write + +After you are finished writing the image, you should finish writing +the file. If you are interested in writing comments or time, you should +pass an appropriately filled png_info pointer. If you are not interested, +you can pass NULL. + + png_write_end(png_ptr, info_ptr); + +When you are done, you can free all memory used by libpng like this: + + png_destroy_write_struct(&png_ptr, &info_ptr); + +It is also possible to individually free the info_ptr members that +point to libpng-allocated storage with the following function: + + png_free_data(png_ptr, info_ptr, mask, seq) + mask - identifies data to be freed, a mask + containing the bitwise OR of one or + more of + PNG_FREE_PLTE, PNG_FREE_TRNS, + PNG_FREE_HIST, PNG_FREE_ICCP, + PNG_FREE_PCAL, PNG_FREE_ROWS, + PNG_FREE_SCAL, PNG_FREE_SPLT, + PNG_FREE_TEXT, PNG_FREE_UNKN, + or simply PNG_FREE_ALL + seq - sequence number of item to be freed + (-1 for all items) + +This function may be safely called when the relevant storage has +already been freed, or has not yet been allocated, or was allocated +by the user and not by libpng, and will in those cases do nothing. +The "seq" parameter is ignored if only one item of the selected data +type, such as PLTE, is allowed. If "seq" is not -1, and multiple items +are allowed for the data type identified in the mask, such as text or +sPLT, only the n'th item in the structure is freed, where n is "seq". + +If you allocated data such as a palette that you passed in to libpng +with png_set_*, you must not free it until just before the call to +png_destroy_write_struct(). + +The default behavior is only to free data that was allocated internally +by libpng. This can be changed, so that libpng will not free the data, +or so that it will free data that was allocated by the user with png_malloc() +or png_zalloc() and passed in via a png_set_*() function, with + + png_data_freer(png_ptr, info_ptr, freer, mask) + mask - which data elements are affected + same choices as in png_free_data() + freer - one of + PNG_DESTROY_WILL_FREE_DATA + PNG_SET_WILL_FREE_DATA + PNG_USER_WILL_FREE_DATA + +For example, to transfer responsibility for some data from a read structure +to a write structure, you could use + + png_data_freer(read_ptr, read_info_ptr, + PNG_USER_WILL_FREE_DATA, + PNG_FREE_PLTE|PNG_FREE_tRNS|PNG_FREE_hIST) + png_data_freer(write_ptr, write_info_ptr, + PNG_DESTROY_WILL_FREE_DATA, + PNG_FREE_PLTE|PNG_FREE_tRNS|PNG_FREE_hIST) + +thereby briefly reassigning responsibility for freeing to the user but +immediately afterwards reassigning it once more to the write_destroy +function. Having done this, it would then be safe to destroy the read +structure and continue to use the PLTE, tRNS, and hIST data in the write +structure. + +This function only affects data that has already been allocated. +You can call this function before calling after the png_set_*() functions +to control whether the user or png_destroy_*() is supposed to free the data. +When the user assumes responsibility for libpng-allocated data, the +application must use +png_free() to free it, and when the user transfers responsibility to libpng +for data that the user has allocated, the user must have used png_malloc() +or png_zalloc() to allocate it. + +If you allocated text_ptr.text, text_ptr.lang, and text_ptr.translated_keyword +separately, do not transfer responsibility for freeing text_ptr to libpng, +because when libpng fills a png_text structure it combines these members with +the key member, and png_free_data() will free only text_ptr.key. Similarly, +if you transfer responsibility for free'ing text_ptr from libpng to your +application, your application must not separately free those members. +For a more compact example of writing a PNG image, see the file example.c. + +V. Modifying/Customizing libpng: + +There are two issues here. The first is changing how libpng does +standard things like memory allocation, input/output, and error handling. +The second deals with more complicated things like adding new chunks, +adding new transformations, and generally changing how libpng works. +Both of those are compile-time issues; that is, they are generally +determined at the time the code is written, and there is rarely a need +to provide the user with a means of changing them. + +Memory allocation, input/output, and error handling + +All of the memory allocation, input/output, and error handling in libpng +goes through callbacks that are user-settable. The default routines are +in pngmem.c, pngrio.c, pngwio.c, and pngerror.c, respectively. To change +these functions, call the appropriate png_set_*_fn() function. + +Memory allocation is done through the functions png_malloc(), png_calloc(), +and png_free(). These currently just call the standard C functions. +png_calloc() calls png_malloc() and then png_memset() to clear the newly +allocated memory to zero. If your pointers can't access more then 64K +at a time, you will want to set MAXSEG_64K in zlib.h. Since it is +unlikely that the method of handling memory allocation on a platform +will change between applications, these functions must be modified in +the library at compile time. If you prefer to use a different method +of allocating and freeing data, you can use png_create_read_struct_2() or +png_create_write_struct_2() to register your own functions as described +above. These functions also provide a void pointer that can be retrieved +via + + mem_ptr=png_get_mem_ptr(png_ptr); + +Your replacement memory functions must have prototypes as follows: + + png_voidp malloc_fn(png_structp png_ptr, + png_alloc_size_t size); + void free_fn(png_structp png_ptr, png_voidp ptr); + +Your malloc_fn() must return NULL in case of failure. The png_malloc() +function will normally call png_error() if it receives a NULL from the +system memory allocator or from your replacement malloc_fn(). + +Your free_fn() will never be called with a NULL ptr, since libpng's +png_free() checks for NULL before calling free_fn(). + +Input/Output in libpng is done through png_read() and png_write(), +which currently just call fread() and fwrite(). The FILE * is stored in +png_struct and is initialized via png_init_io(). If you wish to change +the method of I/O, the library supplies callbacks that you can set +through the function png_set_read_fn() and png_set_write_fn() at run +time, instead of calling the png_init_io() function. These functions +also provide a void pointer that can be retrieved via the function +png_get_io_ptr(). For example: + + png_set_read_fn(png_structp read_ptr, + voidp read_io_ptr, png_rw_ptr read_data_fn) + + png_set_write_fn(png_structp write_ptr, + voidp write_io_ptr, png_rw_ptr write_data_fn, + png_flush_ptr output_flush_fn); + + voidp read_io_ptr = png_get_io_ptr(read_ptr); + voidp write_io_ptr = png_get_io_ptr(write_ptr); + +The replacement I/O functions must have prototypes as follows: + + void user_read_data(png_structp png_ptr, + png_bytep data, png_size_t length); + void user_write_data(png_structp png_ptr, + png_bytep data, png_size_t length); + void user_flush_data(png_structp png_ptr); + +The user_read_data() function is responsible for detecting and +handling end-of-data errors. + +Supplying NULL for the read, write, or flush functions sets them back +to using the default C stream functions, which expect the io_ptr to +point to a standard *FILE structure. It is probably a mistake +to use NULL for one of write_data_fn and output_flush_fn but not both +of them, unless you have built libpng with PNG_NO_WRITE_FLUSH defined. +It is an error to read from a write stream, and vice versa. + +Error handling in libpng is done through png_error() and png_warning(). +Errors handled through png_error() are fatal, meaning that png_error() +should never return to its caller. Currently, this is handled via +setjmp() and longjmp() (unless you have compiled libpng with +PNG_NO_SETJMP, in which case it is handled via PNG_ABORT()), +but you could change this to do things like exit() if you should wish, +as long as your function does not return. + +On non-fatal errors, png_warning() is called +to print a warning message, and then control returns to the calling code. +By default png_error() and png_warning() print a message on stderr via +fprintf() unless the library is compiled with PNG_NO_CONSOLE_IO defined +(because you don't want the messages) or PNG_NO_STDIO defined (because +fprintf() isn't available). If you wish to change the behavior of the error +functions, you will need to set up your own message callbacks. These +functions are normally supplied at the time that the png_struct is created. +It is also possible to redirect errors and warnings to your own replacement +functions after png_create_*_struct() has been called by calling: + + png_set_error_fn(png_structp png_ptr, + png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warning_fn); + + png_voidp error_ptr = png_get_error_ptr(png_ptr); + +If NULL is supplied for either error_fn or warning_fn, then the libpng +default function will be used, calling fprintf() and/or longjmp() if a +problem is encountered. The replacement error functions should have +parameters as follows: + + void user_error_fn(png_structp png_ptr, + png_const_charp error_msg); + void user_warning_fn(png_structp png_ptr, + png_const_charp warning_msg); + +The motivation behind using setjmp() and longjmp() is the C++ throw and +catch exception handling methods. This makes the code much easier to write, +as there is no need to check every return code of every function call. +However, there are some uncertainties about the status of local variables +after a longjmp, so the user may want to be careful about doing anything +after setjmp returns non-zero besides returning itself. Consult your +compiler documentation for more details. For an alternative approach, you +may wish to use the "cexcept" facility (see http://cexcept.sourceforge.net). + +Custom chunks + +If you need to read or write custom chunks, you may need to get deeper +into the libpng code. The library now has mechanisms for storing +and writing chunks of unknown type; you can even declare callbacks +for custom chunks. However, this may not be good enough if the +library code itself needs to know about interactions between your +chunk and existing `intrinsic' chunks. + +If you need to write a new intrinsic chunk, first read the PNG +specification. Acquire a first level of understanding of how it works. +Pay particular attention to the sections that describe chunk names, +and look at how other chunks were designed, so you can do things +similarly. Second, check out the sections of libpng that read and +write chunks. Try to find a chunk that is similar to yours and use +it as a template. More details can be found in the comments inside +the code. It is best to handle unknown chunks in a generic method, +via callback functions, instead of by modifying libpng functions. + +If you wish to write your own transformation for the data, look through +the part of the code that does the transformations, and check out some of +the simpler ones to get an idea of how they work. Try to find a similar +transformation to the one you want to add and copy off of it. More details +can be found in the comments inside the code itself. + +Configuring for 16 bit platforms + +You will want to look into zconf.h to tell zlib (and thus libpng) that +it cannot allocate more then 64K at a time. Even if you can, the memory +won't be accessible. So limit zlib and libpng to 64K by defining MAXSEG_64K. + +Configuring for DOS + +For DOS users who only have access to the lower 640K, you will +have to limit zlib's memory usage via a png_set_compression_mem_level() +call. See zlib.h or zconf.h in the zlib library for more information. + +Configuring for Medium Model + +Libpng's support for medium model has been tested on most of the popular +compilers. Make sure MAXSEG_64K gets defined, USE_FAR_KEYWORD gets +defined, and FAR gets defined to far in pngconf.h, and you should be +all set. Everything in the library (except for zlib's structure) is +expecting far data. You must use the typedefs with the p or pp on +the end for pointers (or at least look at them and be careful). Make +note that the rows of data are defined as png_bytepp, which is an +unsigned char far * far *. + +Configuring for gui/windowing platforms: + +You will need to write new error and warning functions that use the GUI +interface, as described previously, and set them to be the error and +warning functions at the time that png_create_*_struct() is called, +in order to have them available during the structure initialization. +They can be changed later via png_set_error_fn(). On some compilers, +you may also have to change the memory allocators (png_malloc, etc.). + +Configuring for compiler xxx: + +All includes for libpng are in pngconf.h. If you need to add, change +or delete an include, this is the place to do it. +The includes that are not needed outside libpng are placed in pngpriv.h, +which is only used by the routines inside libpng itself. +The files in libpng proper only include pngpriv.h and png.h, which +in turn includes pngconf.h. + +Configuring zlib: + +There are special functions to configure the compression. Perhaps the +most useful one changes the compression level, which currently uses +input compression values in the range 0 - 9. The library normally +uses the default compression level (Z_DEFAULT_COMPRESSION = 6). Tests +have shown that for a large majority of images, compression values in +the range 3-6 compress nearly as well as higher levels, and do so much +faster. For online applications it may be desirable to have maximum speed +(Z_BEST_SPEED = 1). With versions of zlib after v0.99, you can also +specify no compression (Z_NO_COMPRESSION = 0), but this would create +files larger than just storing the raw bitmap. You can specify the +compression level by calling: + + png_set_compression_level(png_ptr, level); + +Another useful one is to reduce the memory level used by the library. +The memory level defaults to 8, but it can be lowered if you are +short on memory (running DOS, for example, where you only have 640K). +Note that the memory level does have an effect on compression; among +other things, lower levels will result in sections of incompressible +data being emitted in smaller stored blocks, with a correspondingly +larger relative overhead of up to 15% in the worst case. + + png_set_compression_mem_level(png_ptr, level); + +The other functions are for configuring zlib. They are not recommended +for normal use and may result in writing an invalid PNG file. See +zlib.h for more information on what these mean. + + png_set_compression_strategy(png_ptr, + strategy); + png_set_compression_window_bits(png_ptr, + window_bits); + png_set_compression_method(png_ptr, method); + png_set_compression_buffer_size(png_ptr, size); + +Controlling row filtering + +If you want to control whether libpng uses filtering or not, which +filters are used, and how it goes about picking row filters, you +can call one of these functions. The selection and configuration +of row filters can have a significant impact on the size and +encoding speed and a somewhat lesser impact on the decoding speed +of an image. Filtering is enabled by default for RGB and grayscale +images (with and without alpha), but not for paletted images nor +for any images with bit depths less than 8 bits/pixel. + +The 'method' parameter sets the main filtering method, which is +currently only '0' in the PNG 1.2 specification. The 'filters' +parameter sets which filter(s), if any, should be used for each +scanline. Possible values are PNG_ALL_FILTERS and PNG_NO_FILTERS +to turn filtering on and off, respectively. + +Individual filter types are PNG_FILTER_NONE, PNG_FILTER_SUB, +PNG_FILTER_UP, PNG_FILTER_AVG, PNG_FILTER_PAETH, which can be bitwise +ORed together with '|' to specify one or more filters to use. +These filters are described in more detail in the PNG specification. +If you intend to change the filter type during the course of writing +the image, you should start with flags set for all of the filters +you intend to use so that libpng can initialize its internal +structures appropriately for all of the filter types. (Note that this +means the first row must always be adaptively filtered, because libpng +currently does not allocate the filter buffers until png_write_row() +is called for the first time.) + + filters = PNG_FILTER_NONE | PNG_FILTER_SUB + PNG_FILTER_UP | PNG_FILTER_AVG | + PNG_FILTER_PAETH | PNG_ALL_FILTERS; + + png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, + filters); + The second parameter can also be + PNG_INTRAPIXEL_DIFFERENCING if you are + writing a PNG to be embedded in a MNG + datastream. This parameter must be the + same as the value of filter_method used + in png_set_IHDR(). + +It is also possible to influence how libpng chooses from among the +available filters. This is done in one or both of two ways - by +telling it how important it is to keep the same filter for successive +rows, and by telling it the relative computational costs of the filters. + + double weights[3] = {1.5, 1.3, 1.1}, + costs[PNG_FILTER_VALUE_LAST] = + {1.0, 1.3, 1.3, 1.5, 1.7}; + + png_set_filter_heuristics(png_ptr, + PNG_FILTER_HEURISTIC_WEIGHTED, 3, + weights, costs); + +The weights are multiplying factors that indicate to libpng that the +row filter should be the same for successive rows unless another row filter +is that many times better than the previous filter. In the above example, +if the previous 3 filters were SUB, SUB, NONE, the SUB filter could have a +"sum of absolute differences" 1.5 x 1.3 times higher than other filters +and still be chosen, while the NONE filter could have a sum 1.1 times +higher than other filters and still be chosen. Unspecified weights are +taken to be 1.0, and the specified weights should probably be declining +like those above in order to emphasize recent filters over older filters. + +The filter costs specify for each filter type a relative decoding cost +to be considered when selecting row filters. This means that filters +with higher costs are less likely to be chosen over filters with lower +costs, unless their "sum of absolute differences" is that much smaller. +The costs do not necessarily reflect the exact computational speeds of +the various filters, since this would unduly influence the final image +size. + +Note that the numbers above were invented purely for this example and +are given only to help explain the function usage. Little testing has +been done to find optimum values for either the costs or the weights. + +Removing unwanted object code + +There are a bunch of #define's in pngconf.h that control what parts of +libpng are compiled. All the defines end in _SUPPORTED. If you are +never going to use a capability, you can change the #define to #undef +before recompiling libpng and save yourself code and data space, or +you can turn off individual capabilities with defines that begin with +PNG_NO_. + +You can also turn all of the transforms and ancillary chunk capabilities +off en masse with compiler directives that define +PNG_NO_READ[or WRITE]_TRANSFORMS, or PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS, +or all four, +along with directives to turn on any of the capabilities that you do +want. The PNG_NO_READ[or WRITE]_TRANSFORMS directives disable the extra +transformations but still leave the library fully capable of reading +and writing PNG files with all known public chunks. Use of the +PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS directive produces a library +that is incapable of reading or writing ancillary chunks. If you are +not using the progressive reading capability, you can turn that off +with PNG_NO_PROGRESSIVE_READ (don't confuse this with the INTERLACING +capability, which you'll still have). + +All the reading and writing specific code are in separate files, so the +linker should only grab the files it needs. However, if you want to +make sure, or if you are building a stand alone library, all the +reading files start with pngr and all the writing files start with +pngw. The files that don't match either (like png.c, pngtrans.c, etc.) +are used for both reading and writing, and always need to be included. +The progressive reader is in pngpread.c + +If you are creating or distributing a dynamically linked library (a .so +or DLL file), you should not remove or disable any parts of the library, +as this will cause applications linked with different versions of the +library to fail if they call functions not available in your library. +The size of the library itself should not be an issue, because only +those sections that are actually used will be loaded into memory. + +Requesting debug printout + +The macro definition PNG_DEBUG can be used to request debugging +printout. Set it to an integer value in the range 0 to 3. Higher +numbers result in increasing amounts of debugging information. The +information is printed to the "stderr" file, unless another file +name is specified in the PNG_DEBUG_FILE macro definition. + +When PNG_DEBUG > 0, the following functions (macros) become available: + + png_debug(level, message) + png_debug1(level, message, p1) + png_debug2(level, message, p1, p2) + +in which "level" is compared to PNG_DEBUG to decide whether to print +the message, "message" is the formatted string to be printed, +and p1 and p2 are parameters that are to be embedded in the string +according to printf-style formatting directives. For example, + + png_debug1(2, "foo=%d\n", foo); + +is expanded to + + if(PNG_DEBUG > 2) + fprintf(PNG_DEBUG_FILE, "foo=%d\n", foo); + +When PNG_DEBUG is defined but is zero, the macros aren't defined, but you +can still use PNG_DEBUG to control your own debugging: + + #ifdef PNG_DEBUG + fprintf(stderr, ... + #endif + +When PNG_DEBUG = 1, the macros are defined, but only png_debug statements +having level = 0 will be printed. There aren't any such statements in +this version of libpng, but if you insert some they will be printed. + +VI. MNG support + +The MNG specification (available at http://www.libpng.org/pub/mng) allows +certain extensions to PNG for PNG images that are embedded in MNG datastreams. +Libpng can support some of these extensions. To enable them, use the +png_permit_mng_features() function: + + feature_set = png_permit_mng_features(png_ptr, mask) + mask is a png_uint_32 containing the bitwise OR of the + features you want to enable. These include + PNG_FLAG_MNG_EMPTY_PLTE + PNG_FLAG_MNG_FILTER_64 + PNG_ALL_MNG_FEATURES + feature_set is a png_uint_32 that is the bitwise AND of + your mask with the set of MNG features that is + supported by the version of libpng that you are using. + +It is an error to use this function when reading or writing a standalone +PNG file with the PNG 8-byte signature. The PNG datastream must be wrapped +in a MNG datastream. As a minimum, it must have the MNG 8-byte signature +and the MHDR and MEND chunks. Libpng does not provide support for these +or any other MNG chunks; your application must provide its own support for +them. You may wish to consider using libmng (available at +http://www.libmng.com) instead. + +VII. Changes to Libpng from version 0.88 + +It should be noted that versions of libpng later than 0.96 are not +distributed by the original libpng author, Guy Schalnat, nor by +Andreas Dilger, who had taken over from Guy during 1996 and 1997, and +distributed versions 0.89 through 0.96, but rather by another member +of the original PNG Group, Glenn Randers-Pehrson. Guy and Andreas are +still alive and well, but they have moved on to other things. + +The old libpng functions png_read_init(), png_write_init(), +png_info_init(), png_read_destroy(), and png_write_destroy() have been +moved to PNG_INTERNAL in version 0.95 to discourage their use. These +functions will be removed from libpng version 2.0.0. + +The preferred method of creating and initializing the libpng structures is +via the png_create_read_struct(), png_create_write_struct(), and +png_create_info_struct() because they isolate the size of the structures +from the application, allow version error checking, and also allow the +use of custom error handling routines during the initialization, which +the old functions do not. The functions png_read_destroy() and +png_write_destroy() do not actually free the memory that libpng +allocated for these structs, but just reset the data structures, so they +can be used instead of png_destroy_read_struct() and +png_destroy_write_struct() if you feel there is too much system overhead +allocating and freeing the png_struct for each image read. + +Setting the error callbacks via png_set_message_fn() before +png_read_init() as was suggested in libpng-0.88 is no longer supported +because this caused applications that do not use custom error functions +to fail if the png_ptr was not initialized to zero. It is still possible +to set the error callbacks AFTER png_read_init(), or to change them with +png_set_error_fn(), which is essentially the same function, but with a new +name to force compilation errors with applications that try to use the old +method. + +Starting with version 1.0.7, you can find out which version of the library +you are using at run-time: + + png_uint_32 libpng_vn = png_access_version_number(); + +The number libpng_vn is constructed from the major version, minor +version with leading zero, and release number with leading zero, +(e.g., libpng_vn for version 1.0.7 is 10007). + +You can also check which version of png.h you used when compiling your +application: + + png_uint_32 application_vn = PNG_LIBPNG_VER; + +VIII. Changes to Libpng from version 1.0.x to 1.2.x + +Support for user memory management was enabled by default. To +accomplish this, the functions png_create_read_struct_2(), +png_create_write_struct_2(), png_set_mem_fn(), png_get_mem_ptr(), +png_malloc_default(), and png_free_default() were added. + +Support for the iTXt chunk has been enabled by default as of +version 1.2.41. + +Support for certain MNG features was enabled. + +Support for numbered error messages was added. However, we never got +around to actually numbering the error messages. The function +png_set_strip_error_numbers() was added (Note: the prototype for this +function was inadvertently removed from png.h in PNG_NO_ASSEMBLER_CODE +builds of libpng-1.2.15. It was restored in libpng-1.2.36). + +The png_malloc_warn() function was added at libpng-1.2.3. This issues +a png_warning and returns NULL instead of aborting when it fails to +acquire the requested memory allocation. + +Support for setting user limits on image width and height was enabled +by default. The functions png_set_user_limits(), png_get_user_width_max(), +and png_get_user_height_max() were added at libpng-1.2.6. + +The png_set_add_alpha() function was added at libpng-1.2.7. + +The function png_set_expand_gray_1_2_4_to_8() was added at libpng-1.2.9. +Unlike png_set_gray_1_2_4_to_8(), the new function does not expand the +tRNS chunk to alpha. The png_set_gray_1_2_4_to_8() function is +deprecated. + +A number of macro definitions in support of runtime selection of +assembler code features (especially Intel MMX code support) were +added at libpng-1.2.0: + + PNG_ASM_FLAG_MMX_SUPPORT_COMPILED + PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU + PNG_ASM_FLAG_MMX_READ_COMBINE_ROW + PNG_ASM_FLAG_MMX_READ_INTERLACE + PNG_ASM_FLAG_MMX_READ_FILTER_SUB + PNG_ASM_FLAG_MMX_READ_FILTER_UP + PNG_ASM_FLAG_MMX_READ_FILTER_AVG + PNG_ASM_FLAG_MMX_READ_FILTER_PAETH + PNG_ASM_FLAGS_INITIALIZED + PNG_MMX_READ_FLAGS + PNG_MMX_FLAGS + PNG_MMX_WRITE_FLAGS + PNG_MMX_FLAGS + +We added the following functions in support of runtime +selection of assembler code features: + + png_get_mmx_flagmask() + png_set_mmx_thresholds() + png_get_asm_flags() + png_get_mmx_bitdepth_threshold() + png_get_mmx_rowbytes_threshold() + png_set_asm_flags() + +We replaced all of these functions with simple stubs in libpng-1.2.20, +when the Intel assembler code was removed due to a licensing issue. + +These macros are deprecated: + + PNG_READ_TRANSFORMS_NOT_SUPPORTED + PNG_PROGRESSIVE_READ_NOT_SUPPORTED + PNG_NO_SEQUENTIAL_READ_SUPPORTED + PNG_WRITE_TRANSFORMS_NOT_SUPPORTED + PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED + PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED + +They have been replaced, respectively, by: + + PNG_NO_READ_TRANSFORMS + PNG_NO_PROGRESSIVE_READ + PNG_NO_SEQUENTIAL_READ + PNG_NO_WRITE_TRANSFORMS + PNG_NO_READ_ANCILLARY_CHUNKS + PNG_NO_WRITE_ANCILLARY_CHUNKS + +PNG_MAX_UINT was replaced with PNG_UINT_31_MAX. It has been +deprecated since libpng-1.0.16 and libpng-1.2.6. + +The function + png_check_sig(sig, num) +was replaced with + !png_sig_cmp(sig, 0, num) +It has been deprecated since libpng-0.90. + +The function + png_set_gray_1_2_4_to_8() +which also expands tRNS to alpha was replaced with + png_set_expand_gray_1_2_4_to_8() +which does not. It has been deprecated since libpng-1.0.18 and 1.2.9. + +IX. Changes to Libpng from version 1.0.x/1.2.x to 1.4.x + +Private libpng prototypes and macro definitions were moved from +png.h and pngconf.h into a new pngpriv.h header file. + +Functions png_set_benign_errors(), png_benign_error(), and +png_chunk_benign_error() were added. + +Support for setting the maximum amount of memory that the application +will allocate for reading chunks was added, as a security measure. +The functions png_set_chunk_cache_max() and png_get_chunk_cache_max() +were added to the library. + +We implemented support for I/O states by adding png_ptr member io_state +and functions png_get_io_chunk_name() and png_get_io_state() in pngget.c + +We added PNG_TRANSFORM_GRAY_TO_RGB to the available high-level +input transforms. + +Checking for and reporting of errors in the IHDR chunk is more thorough. + +Support for global arrays was removed, to improve thread safety. + +Some obsolete/deprecated macros and functions have been removed. + +Typecasted NULL definitions such as + #define png_voidp_NULL (png_voidp)NULL +were eliminated. If you used these in your application, just use +NULL instead. + +The png_struct and info_struct members "trans" and "trans_values" were +changed to "trans_alpha" and "trans_color", respectively. + +The obsolete, unused pnggccrd.c and pngvcrd.c files and related makefiles +were removed. + +The PNG_1_0_X and PNG_1_2_X macros were eliminated. + +The PNG_LEGACY_SUPPORTED macro was eliminated. + +Many WIN32_WCE #ifdefs were removed. + +The functions png_read_init(info_ptr), png_write_init(info_ptr), +png_info_init(info_ptr), png_read_destroy(), and png_write_destroy() +have been removed. They have been deprecated since libpng-0.95. + +The png_permit_empty_plte() was removed. It has been deprecated +since libpng-1.0.9. Use png_permit_mng_features() instead. + +We removed the obsolete stub functions png_get_mmx_flagmask(), +png_set_mmx_thresholds(), png_get_asm_flags(), +png_get_mmx_bitdepth_threshold(), png_get_mmx_rowbytes_threshold(), +png_set_asm_flags(), and png_mmx_supported() + +We removed the obsolete png_check_sig(), png_memcpy_check(), and +png_memset_check() functions. Instead use !png_sig_cmp(), png_memcpy(), +and png_memset(), respectively. + +The function png_set_gray_1_2_4_to_8() was removed. It has been +deprecated since libpng-1.0.18 and 1.2.9, when it was replaced with +png_set_expand_gray_1_2_4_to_8() because the former function also +expanded palette images. + +We changed the prototype for png_malloc() from + png_malloc(png_structp png_ptr, png_uint_32 size) +to + png_malloc(png_structp png_ptr, png_alloc_size_t size) + +This also applies to the prototype for the user replacement malloc_fn(). + +The png_calloc() function was added and is used in place of +of "png_malloc(); png_memset();" except in the case in png_read_png() +where the array consists of pointers; in this case a "for" loop is used +after the png_malloc() to set the pointers to NULL, to give robust. +behavior in case the application runs out of memory part-way through +the process. + +We changed the prototypes of png_get_compression_buffer_size() and +png_set_compression_buffer_size() to work with png_size_t instead of +png_uint_32. + +Support for numbered error messages was removed by default, since we +never got around to actually numbering the error messages. The function +png_set_strip_error_numbers() was removed from the library by default. + +The png_zalloc() and png_zfree() functions are no longer exported. +The png_zalloc() function no longer zeroes out the memory that it +allocates. + +Support for dithering was disabled by default in libpng-1.4.0, because +been well tested and doesn't actually "dither". The code was not +removed, however, and could be enabled by building libpng with +PNG_READ_DITHER_SUPPORTED defined. In libpng-1.4.2, this support +was reenabled, but the function was renamed png_set_quantize() to +reflect more accurately what it actually does. At the same time, +the PNG_DITHER_[RED,GREEN_BLUE]_BITS macros were also renamed to +PNG_QUANTIZE_[RED,GREEN,BLUE]_BITS. + +We removed the trailing '.' from the warning and error messages. + +X. Detecting libpng + +The png_get_io_ptr() function has been present since libpng-0.88, has never +changed, and is unaffected by conditional compilation macros. It is the +best choice for use in configure scripts for detecting the presence of any +libpng version since 0.88. In an autoconf "configure.in" you could use + + AC_CHECK_LIB(png, png_get_io_ptr, ... + +XI. Source code repository + +Since about February 2009, version 1.2.34, libpng has been under "git" source +control. The git repository was built from old libpng-x.y.z.tar.gz files +going back to version 0.70. You can access the git repository (read only) +at + + git://libpng.git.sourceforge.net/gitroot/libpng + +or you can browse it via "gitweb" at + + http://libpng.git.sourceforge.net/git/gitweb.cgi?p=libpng + +Patches can be sent to glennrp at users.sourceforge.net or to +png-mng-implement at lists.sourceforge.net or you can upload them to +the libpng bug tracker at + + http://libpng.sourceforge.net + +XII. Coding style + +Our coding style is similar to the "Allman" style, with curly +braces on separate lines: + + if (condition) + { + action; + } + + else if (another condition) + { + another action; + } + +The braces can be omitted from simple one-line actions: + + if (condition) + return (0); + +We use 3-space indentation, except for continued statements which +are usually indented the same as the first line of the statement +plus four more spaces. + +For macro definitions we use 2-space indentation, always leaving the "#" +in the first column. + + #ifndef PNG_NO_FEATURE + # ifndef PNG_FEATURE_SUPPORTED + # define PNG_FEATURE_SUPPORTED + # endif + #endif + +Comments appear with the leading "/*" at the same indentation as +the statement that follows the comment: + + /* Single-line comment */ + statement; + + /* This is a multiple-line + * comment. + */ + statement; + +Very short comments can be placed after the end of the statement +to which they pertain: + + statement; /* comment */ + +We don't use C++ style ("//") comments. We have, however, +used them in the past in some now-abandoned MMX assembler +code. + +Functions and their curly braces are not indented, and +exported functions are marked with PNGAPI: + + /* This is a public function that is visible to + * application programers. It does thus-and-so. + */ + void PNGAPI + png_exported_function(png_ptr, png_info, foo) + { + body; + } + +The prototypes for all exported functions appear in png.h, +above the comment that says + + /* Maintainer: Put new public prototypes here ... */ + +We mark all non-exported functions with "/* PRIVATE */"": + + void /* PRIVATE */ + png_non_exported_function(png_ptr, png_info, foo) + { + body; + } + +The prototypes for non-exported functions (except for those in +pngtest) appear in +pngpriv.h +above the comment that says + + /* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */ + +The names of all exported functions and variables begin +with "png_", and all publicly visible C preprocessor +macros begin with "PNG_". + +We put a space after each comma and after each semicolon +in "for" statments, and we put spaces before and after each +C binary operator and after "for" or "while", and before +"?". We don't put a space between a typecast and the expression +being cast, nor do we put one between a function name and the +left parenthesis that follows it: + + for (i = 2; i > 0; --i) + y[i] = a(x) + (int)b; + +We prefer #ifdef and #ifndef to #if defined() and if !defined() +when there is only one macro being tested. + +We do not use the TAB character for indentation in the C sources. + +Lines do not exceed 80 characters. + +Other rules can be inferred by inspecting the libpng source. + +XIII. Y2K Compliance in libpng + +June 26, 2010 + +Since the PNG Development group is an ad-hoc body, we can't make +an official declaration. + +This is your unofficial assurance that libpng from version 0.71 and +upward through 1.4.3 are Y2K compliant. It is my belief that earlier +versions were also Y2K compliant. + +Libpng only has three year fields. One is a 2-byte unsigned integer that +will hold years up to 65535. The other two hold the date in text +format, and will hold years up to 9999. + +The integer is + "png_uint_16 year" in png_time_struct. + +The strings are + "png_charp time_buffer" in png_struct and + "near_time_buffer", which is a local character string in png.c. + +There are seven time-related functions: + + png_convert_to_rfc_1123() in png.c + (formerly png_convert_to_rfc_1152() in error) + png_convert_from_struct_tm() in pngwrite.c, called + in pngwrite.c + png_convert_from_time_t() in pngwrite.c + png_get_tIME() in pngget.c + png_handle_tIME() in pngrutil.c, called in pngread.c + png_set_tIME() in pngset.c + png_write_tIME() in pngwutil.c, called in pngwrite.c + +All appear to handle dates properly in a Y2K environment. The +png_convert_from_time_t() function calls gmtime() to convert from system +clock time, which returns (year - 1900), which we properly convert to +the full 4-digit year. There is a possibility that applications using +libpng are not passing 4-digit years into the png_convert_to_rfc_1123() +function, or that they are incorrectly passing only a 2-digit year +instead of "year - 1900" into the png_convert_from_struct_tm() function, +but this is not under our control. The libpng documentation has always +stated that it works with 4-digit years, and the APIs have been +documented as such. + +The tIME chunk itself is also Y2K compliant. It uses a 2-byte unsigned +integer to hold the year, and can hold years as large as 65535. + +zlib, upon which libpng depends, is also Y2K compliant. It contains +no date-related code. + + + Glenn Randers-Pehrson + libpng maintainer + PNG Development Group diff --git a/reactos/dll/3rdparty/libpng/libpng.rbuild b/reactos/dll/3rdparty/libpng/libpng.rbuild new file mode 100644 index 00000000000..806d418cdbc --- /dev/null +++ b/reactos/dll/3rdparty/libpng/libpng.rbuild @@ -0,0 +1,27 @@ + + + + + + + + . + lib/3rdparty/zlib + zlib + png.c + pngerror.c + pngget.c + pngmem.c + pngpread.c + pngread.c + pngrio.c + pngrtran.c + pngrutil.c + pngset.c + pngtest.c + pngtrans.c + pngwio.c + pngwrite.c + pngwtran.c + pngwutil.c + diff --git a/reactos/dll/3rdparty/libpng/new_push_process_row.c b/reactos/dll/3rdparty/libpng/new_push_process_row.c new file mode 100644 index 00000000000..fbd7dcfb9f8 --- /dev/null +++ b/reactos/dll/3rdparty/libpng/new_push_process_row.c @@ -0,0 +1,204 @@ +void /* PRIVATE */ +png_push_process_row(png_structp png_ptr) +{ + png_ptr->row_info.color_type = png_ptr->color_type; + png_ptr->row_info.width = png_ptr->iwidth; + png_ptr->row_info.channels = png_ptr->channels; + png_ptr->row_info.bit_depth = png_ptr->bit_depth; + png_ptr->row_info.pixel_depth = png_ptr->pixel_depth; + + png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, + png_ptr->row_info.width); + + png_read_filter_row(png_ptr, &(png_ptr->row_info), + png_ptr->row_buf + 1, png_ptr->prev_row + 1, + (int)(png_ptr->row_buf[0])); + + png_memcpy(png_ptr->prev_row, png_ptr->row_buf, png_ptr->rowbytes + 1); + + if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA)) + png_do_read_transformations(png_ptr); + +#ifdef PNG_READ_INTERLACING_SUPPORTED + /* Blow up interlaced rows to full size */ + if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) + { + if (png_ptr->pass < 6) +/* old interface (pre-1.0.9): + png_do_read_interlace(&(png_ptr->row_info), + png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations); + */ + png_do_read_interlace(png_ptr); + + switch (png_ptr->pass) + { + case 0: + { + int i; + for (i = 0; i < 8 && png_ptr->pass == 0; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); /* Updates png_ptr->pass */ + } + + if (png_ptr->pass == 2) /* Pass 1 might be empty */ + { + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + + if (png_ptr->pass == 4 && png_ptr->height <= 4) + { + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + + if (png_ptr->pass == 6 && png_ptr->height <= 4) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + + break; + } + + case 1: + { + int i; + for (i = 0; i < 8 && png_ptr->pass == 1; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 2) /* Skip top 4 generated rows */ + { + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + + break; + } + + case 2: + { + int i; + + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 4) /* Pass 3 might be empty */ + { + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + + break; + } + + case 3: + { + int i; + + for (i = 0; i < 4 && png_ptr->pass == 3; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 4) /* Skip top two generated rows */ + { + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + + break; + } + + case 4: + { + int i; + + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 6) /* Pass 5 might be empty */ + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + + break; + } + + case 5: + { + int i; + + for (i = 0; i < 2 && png_ptr->pass == 5; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 6) /* Skip top generated row */ + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + + break; + } + case 6: + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + + if (png_ptr->pass != 6) + break; + + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + } + else +#endif + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } +} diff --git a/reactos/dll/3rdparty/libpng/png.c b/reactos/dll/3rdparty/libpng/png.c new file mode 100644 index 00000000000..dab4f36459d --- /dev/null +++ b/reactos/dll/3rdparty/libpng/png.c @@ -0,0 +1,918 @@ + +/* png.c - location for general purpose libpng functions + * + * Last changed in libpng 1.4.2 [May 6, 2010] + * Copyright (c) 1998-2010 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#define PNG_NO_EXTERN +#define PNG_NO_PEDANTIC_WARNINGS +#include "png.h" +#include "pngpriv.h" + +/* Generate a compiler error if there is an old png.h in the search path. */ +typedef version_1_4_3 Your_png_h_is_not_version_1_4_3; + +/* Version information for C files. This had better match the version + * string defined in png.h. + */ + +/* Tells libpng that we have already handled the first "num_bytes" bytes + * of the PNG file signature. If the PNG data is embedded into another + * stream we can set num_bytes = 8 so that libpng will not attempt to read + * or write any of the magic bytes before it starts on the IHDR. + */ + +#ifdef PNG_READ_SUPPORTED +void PNGAPI +png_set_sig_bytes(png_structp png_ptr, int num_bytes) +{ + png_debug(1, "in png_set_sig_bytes"); + + if (png_ptr == NULL) + return; + + if (num_bytes > 8) + png_error(png_ptr, "Too many bytes for PNG signature"); + + png_ptr->sig_bytes = (png_byte)(num_bytes < 0 ? 0 : num_bytes); +} + +/* Checks whether the supplied bytes match the PNG signature. We allow + * checking less than the full 8-byte signature so that those apps that + * already read the first few bytes of a file to determine the file type + * can simply check the remaining bytes for extra assurance. Returns + * an integer less than, equal to, or greater than zero if sig is found, + * respectively, to be less than, to match, or be greater than the correct + * PNG signature (this is the same behaviour as strcmp, memcmp, etc). + */ +int PNGAPI +png_sig_cmp(png_bytep sig, png_size_t start, png_size_t num_to_check) +{ + png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; + if (num_to_check > 8) + num_to_check = 8; + else if (num_to_check < 1) + return (-1); + + if (start > 7) + return (-1); + + if (start + num_to_check > 8) + num_to_check = 8 - start; + + return ((int)(png_memcmp(&sig[start], &png_signature[start], num_to_check))); +} + +#endif /* PNG_READ_SUPPORTED */ + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +/* Function to allocate memory for zlib and clear it to 0. */ +voidpf /* PRIVATE */ +png_zalloc(voidpf png_ptr, uInt items, uInt size) +{ + png_voidp ptr; + png_structp p=(png_structp)png_ptr; + png_uint_32 save_flags=p->flags; + png_alloc_size_t num_bytes; + + if (png_ptr == NULL) + return (NULL); + if (items > PNG_UINT_32_MAX/size) + { + png_warning (p, "Potential overflow in png_zalloc()"); + return (NULL); + } + num_bytes = (png_alloc_size_t)items * size; + + p->flags|=PNG_FLAG_MALLOC_NULL_MEM_OK; + ptr = (png_voidp)png_malloc((png_structp)png_ptr, num_bytes); + p->flags=save_flags; + + return ((voidpf)ptr); +} + +/* Function to free memory for zlib */ +void /* PRIVATE */ +png_zfree(voidpf png_ptr, voidpf ptr) +{ + png_free((png_structp)png_ptr, (png_voidp)ptr); +} + +/* Reset the CRC variable to 32 bits of 1's. Care must be taken + * in case CRC is > 32 bits to leave the top bits 0. + */ +void /* PRIVATE */ +png_reset_crc(png_structp png_ptr) +{ + png_ptr->crc = crc32(0, Z_NULL, 0); +} + +/* Calculate the CRC over a section of data. We can only pass as + * much data to this routine as the largest single buffer size. We + * also check that this data will actually be used before going to the + * trouble of calculating it. + */ +void /* PRIVATE */ +png_calculate_crc(png_structp png_ptr, png_bytep ptr, png_size_t length) +{ + int need_crc = 1; + + if (png_ptr->chunk_name[0] & 0x20) /* ancillary */ + { + if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) == + (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN)) + need_crc = 0; + } + else /* critical */ + { + if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) + need_crc = 0; + } + + if (need_crc) + png_ptr->crc = crc32(png_ptr->crc, ptr, (uInt)length); +} + +/* Allocate the memory for an info_struct for the application. We don't + * really need the png_ptr, but it could potentially be useful in the + * future. This should be used in favour of malloc(png_sizeof(png_info)) + * and png_info_init() so that applications that want to use a shared + * libpng don't have to be recompiled if png_info changes size. + */ +png_infop PNGAPI +png_create_info_struct(png_structp png_ptr) +{ + png_infop info_ptr; + + png_debug(1, "in png_create_info_struct"); + + if (png_ptr == NULL) + return (NULL); + +#ifdef PNG_USER_MEM_SUPPORTED + info_ptr = (png_infop)png_create_struct_2(PNG_STRUCT_INFO, + png_ptr->malloc_fn, png_ptr->mem_ptr); +#else + info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO); +#endif + if (info_ptr != NULL) + png_info_init_3(&info_ptr, png_sizeof(png_info)); + + return (info_ptr); +} + +/* This function frees the memory associated with a single info struct. + * Normally, one would use either png_destroy_read_struct() or + * png_destroy_write_struct() to free an info struct, but this may be + * useful for some applications. + */ +void PNGAPI +png_destroy_info_struct(png_structp png_ptr, png_infopp info_ptr_ptr) +{ + png_infop info_ptr = NULL; + + png_debug(1, "in png_destroy_info_struct"); + + if (png_ptr == NULL) + return; + + if (info_ptr_ptr != NULL) + info_ptr = *info_ptr_ptr; + + if (info_ptr != NULL) + { + png_info_destroy(png_ptr, info_ptr); + +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)info_ptr, png_ptr->free_fn, + png_ptr->mem_ptr); +#else + png_destroy_struct((png_voidp)info_ptr); +#endif + *info_ptr_ptr = NULL; + } +} + +/* Initialize the info structure. This is now an internal function (0.89) + * and applications using it are urged to use png_create_info_struct() + * instead. + */ + +void PNGAPI +png_info_init_3(png_infopp ptr_ptr, png_size_t png_info_struct_size) +{ + png_infop info_ptr = *ptr_ptr; + + png_debug(1, "in png_info_init_3"); + + if (info_ptr == NULL) + return; + + if (png_sizeof(png_info) > png_info_struct_size) + { + png_destroy_struct(info_ptr); + info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO); + *ptr_ptr = info_ptr; + } + + /* Set everything to 0 */ + png_memset(info_ptr, 0, png_sizeof(png_info)); +} + +void PNGAPI +png_data_freer(png_structp png_ptr, png_infop info_ptr, + int freer, png_uint_32 mask) +{ + png_debug(1, "in png_data_freer"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (freer == PNG_DESTROY_WILL_FREE_DATA) + info_ptr->free_me |= mask; + else if (freer == PNG_USER_WILL_FREE_DATA) + info_ptr->free_me &= ~mask; + else + png_warning(png_ptr, + "Unknown freer parameter in png_data_freer"); +} + +void PNGAPI +png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask, + int num) +{ + png_debug(1, "in png_free_data"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + +#ifdef PNG_TEXT_SUPPORTED + /* Free text item num or (if num == -1) all text items */ + if ((mask & PNG_FREE_TEXT) & info_ptr->free_me) + { + if (num != -1) + { + if (info_ptr->text && info_ptr->text[num].key) + { + png_free(png_ptr, info_ptr->text[num].key); + info_ptr->text[num].key = NULL; + } + } + else + { + int i; + for (i = 0; i < info_ptr->num_text; i++) + png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, i); + png_free(png_ptr, info_ptr->text); + info_ptr->text = NULL; + info_ptr->num_text=0; + } + } +#endif + +#ifdef PNG_tRNS_SUPPORTED + /* Free any tRNS entry */ + if ((mask & PNG_FREE_TRNS) & info_ptr->free_me) + { + png_free(png_ptr, info_ptr->trans_alpha); + info_ptr->trans_alpha = NULL; + info_ptr->valid &= ~PNG_INFO_tRNS; + } +#endif + +#ifdef PNG_sCAL_SUPPORTED + /* Free any sCAL entry */ + if ((mask & PNG_FREE_SCAL) & info_ptr->free_me) + { +#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED) + png_free(png_ptr, info_ptr->scal_s_width); + png_free(png_ptr, info_ptr->scal_s_height); + info_ptr->scal_s_width = NULL; + info_ptr->scal_s_height = NULL; +#endif + info_ptr->valid &= ~PNG_INFO_sCAL; + } +#endif + +#ifdef PNG_pCAL_SUPPORTED + /* Free any pCAL entry */ + if ((mask & PNG_FREE_PCAL) & info_ptr->free_me) + { + png_free(png_ptr, info_ptr->pcal_purpose); + png_free(png_ptr, info_ptr->pcal_units); + info_ptr->pcal_purpose = NULL; + info_ptr->pcal_units = NULL; + if (info_ptr->pcal_params != NULL) + { + int i; + for (i = 0; i < (int)info_ptr->pcal_nparams; i++) + { + png_free(png_ptr, info_ptr->pcal_params[i]); + info_ptr->pcal_params[i] = NULL; + } + png_free(png_ptr, info_ptr->pcal_params); + info_ptr->pcal_params = NULL; + } + info_ptr->valid &= ~PNG_INFO_pCAL; + } +#endif + +#ifdef PNG_iCCP_SUPPORTED + /* Free any iCCP entry */ + if ((mask & PNG_FREE_ICCP) & info_ptr->free_me) + { + png_free(png_ptr, info_ptr->iccp_name); + png_free(png_ptr, info_ptr->iccp_profile); + info_ptr->iccp_name = NULL; + info_ptr->iccp_profile = NULL; + info_ptr->valid &= ~PNG_INFO_iCCP; + } +#endif + +#ifdef PNG_sPLT_SUPPORTED + /* Free a given sPLT entry, or (if num == -1) all sPLT entries */ + if ((mask & PNG_FREE_SPLT) & info_ptr->free_me) + { + if (num != -1) + { + if (info_ptr->splt_palettes) + { + png_free(png_ptr, info_ptr->splt_palettes[num].name); + png_free(png_ptr, info_ptr->splt_palettes[num].entries); + info_ptr->splt_palettes[num].name = NULL; + info_ptr->splt_palettes[num].entries = NULL; + } + } + else + { + if (info_ptr->splt_palettes_num) + { + int i; + for (i = 0; i < (int)info_ptr->splt_palettes_num; i++) + png_free_data(png_ptr, info_ptr, PNG_FREE_SPLT, i); + + png_free(png_ptr, info_ptr->splt_palettes); + info_ptr->splt_palettes = NULL; + info_ptr->splt_palettes_num = 0; + } + info_ptr->valid &= ~PNG_INFO_sPLT; + } + } +#endif + +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED + if (png_ptr->unknown_chunk.data) + { + png_free(png_ptr, png_ptr->unknown_chunk.data); + png_ptr->unknown_chunk.data = NULL; + } + + if ((mask & PNG_FREE_UNKN) & info_ptr->free_me) + { + if (num != -1) + { + if (info_ptr->unknown_chunks) + { + png_free(png_ptr, info_ptr->unknown_chunks[num].data); + info_ptr->unknown_chunks[num].data = NULL; + } + } + else + { + int i; + + if (info_ptr->unknown_chunks_num) + { + for (i = 0; i < (int)info_ptr->unknown_chunks_num; i++) + png_free_data(png_ptr, info_ptr, PNG_FREE_UNKN, i); + + png_free(png_ptr, info_ptr->unknown_chunks); + info_ptr->unknown_chunks = NULL; + info_ptr->unknown_chunks_num = 0; + } + } + } +#endif + +#ifdef PNG_hIST_SUPPORTED + /* Free any hIST entry */ + if ((mask & PNG_FREE_HIST) & info_ptr->free_me) + { + png_free(png_ptr, info_ptr->hist); + info_ptr->hist = NULL; + info_ptr->valid &= ~PNG_INFO_hIST; + } +#endif + + /* Free any PLTE entry that was internally allocated */ + if ((mask & PNG_FREE_PLTE) & info_ptr->free_me) + { + png_zfree(png_ptr, info_ptr->palette); + info_ptr->palette = NULL; + info_ptr->valid &= ~PNG_INFO_PLTE; + info_ptr->num_palette = 0; + } + +#ifdef PNG_INFO_IMAGE_SUPPORTED + /* Free any image bits attached to the info structure */ + if ((mask & PNG_FREE_ROWS) & info_ptr->free_me) + { + if (info_ptr->row_pointers) + { + int row; + for (row = 0; row < (int)info_ptr->height; row++) + { + png_free(png_ptr, info_ptr->row_pointers[row]); + info_ptr->row_pointers[row] = NULL; + } + png_free(png_ptr, info_ptr->row_pointers); + info_ptr->row_pointers = NULL; + } + info_ptr->valid &= ~PNG_INFO_IDAT; + } +#endif + + if (num == -1) + info_ptr->free_me &= ~mask; + else + info_ptr->free_me &= ~(mask & ~PNG_FREE_MUL); +} + +/* This is an internal routine to free any memory that the info struct is + * pointing to before re-using it or freeing the struct itself. Recall + * that png_free() checks for NULL pointers for us. + */ +void /* PRIVATE */ +png_info_destroy(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_info_destroy"); + + png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + if (png_ptr->num_chunk_list) + { + png_free(png_ptr, png_ptr->chunk_list); + png_ptr->chunk_list = NULL; + png_ptr->num_chunk_list = 0; + } +#endif + + png_info_init_3(&info_ptr, png_sizeof(png_info)); +} +#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ + +/* This function returns a pointer to the io_ptr associated with the user + * functions. The application should free any memory associated with this + * pointer before png_write_destroy() or png_read_destroy() are called. + */ +png_voidp PNGAPI +png_get_io_ptr(png_structp png_ptr) +{ + if (png_ptr == NULL) + return (NULL); + return (png_ptr->io_ptr); +} + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +#ifdef PNG_STDIO_SUPPORTED +/* Initialize the default input/output functions for the PNG file. If you + * use your own read or write routines, you can call either png_set_read_fn() + * or png_set_write_fn() instead of png_init_io(). If you have defined + * PNG_NO_STDIO, you must use a function of your own because "FILE *" isn't + * necessarily available. + */ +void PNGAPI +png_init_io(png_structp png_ptr, png_FILE_p fp) +{ + png_debug(1, "in png_init_io"); + + if (png_ptr == NULL) + return; + + png_ptr->io_ptr = (png_voidp)fp; +} +#endif + +#ifdef PNG_TIME_RFC1123_SUPPORTED +/* Convert the supplied time into an RFC 1123 string suitable for use in + * a "Creation Time" or other text-based time string. + */ +png_charp PNGAPI +png_convert_to_rfc1123(png_structp png_ptr, png_timep ptime) +{ + static PNG_CONST char short_months[12][4] = + {"Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + + if (png_ptr == NULL) + return (NULL); + if (png_ptr->time_buffer == NULL) + { + png_ptr->time_buffer = (png_charp)png_malloc(png_ptr, (png_uint_32)(29* + png_sizeof(char))); + } + +#ifdef USE_FAR_KEYWORD + { + char near_time_buf[29]; + png_snprintf6(near_time_buf, 29, "%d %s %d %02d:%02d:%02d +0000", + ptime->day % 32, short_months[(ptime->month - 1) % 12], + ptime->year, ptime->hour % 24, ptime->minute % 60, + ptime->second % 61); + png_memcpy(png_ptr->time_buffer, near_time_buf, + 29*png_sizeof(char)); + } +#else + png_snprintf6(png_ptr->time_buffer, 29, "%d %s %d %02d:%02d:%02d +0000", + ptime->day % 32, short_months[(ptime->month - 1) % 12], + ptime->year, ptime->hour % 24, ptime->minute % 60, + ptime->second % 61); +#endif + return ((png_charp)png_ptr->time_buffer); +} +#endif /* PNG_TIME_RFC1123_SUPPORTED */ + +#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ + +png_charp PNGAPI +png_get_copyright(png_structp png_ptr) +{ + png_ptr = png_ptr; /* Silence compiler warning about unused png_ptr */ +#ifdef PNG_STRING_COPYRIGHT + return PNG_STRING_COPYRIGHT +#else +#ifdef __STDC__ + return ((png_charp) PNG_STRING_NEWLINE \ + "libpng version 1.4.3 - June 26, 2010" PNG_STRING_NEWLINE \ + "Copyright (c) 1998-2010 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \ + "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \ + "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \ + PNG_STRING_NEWLINE); +#else + return ((png_charp) "libpng version 1.4.3 - June 26, 2010\ + Copyright (c) 1998-2010 Glenn Randers-Pehrson\ + Copyright (c) 1996-1997 Andreas Dilger\ + Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc."); +#endif +#endif +} + +/* The following return the library version as a short string in the + * format 1.0.0 through 99.99.99zz. To get the version of *.h files + * used with your application, print out PNG_LIBPNG_VER_STRING, which + * is defined in png.h. + * Note: now there is no difference between png_get_libpng_ver() and + * png_get_header_ver(). Due to the version_nn_nn_nn typedef guard, + * it is guaranteed that png.c uses the correct version of png.h. + */ +png_charp PNGAPI +png_get_libpng_ver(png_structp png_ptr) +{ + /* Version of *.c files used when building libpng */ + png_ptr = png_ptr; /* Silence compiler warning about unused png_ptr */ + return ((png_charp) PNG_LIBPNG_VER_STRING); +} + +png_charp PNGAPI +png_get_header_ver(png_structp png_ptr) +{ + /* Version of *.h files used when building libpng */ + png_ptr = png_ptr; /* Silence compiler warning about unused png_ptr */ + return ((png_charp) PNG_LIBPNG_VER_STRING); +} + +png_charp PNGAPI +png_get_header_version(png_structp png_ptr) +{ + /* Returns longer string containing both version and date */ + png_ptr = png_ptr; /* Silence compiler warning about unused png_ptr */ +#ifdef __STDC__ + return ((png_charp) PNG_HEADER_VERSION_STRING +#ifndef PNG_READ_SUPPORTED + " (NO READ SUPPORT)" +#endif + PNG_STRING_NEWLINE); +#else + return ((png_charp) PNG_HEADER_VERSION_STRING); +#endif +} + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +int PNGAPI +png_handle_as_unknown(png_structp png_ptr, png_bytep chunk_name) +{ + /* Check chunk_name and return "keep" value if it's on the list, else 0 */ + int i; + png_bytep p; + if (png_ptr == NULL || chunk_name == NULL || png_ptr->num_chunk_list<=0) + return 0; + p = png_ptr->chunk_list + png_ptr->num_chunk_list*5 - 5; + for (i = png_ptr->num_chunk_list; i; i--, p -= 5) + if (!png_memcmp(chunk_name, p, 4)) + return ((int)*(p + 4)); + return 0; +} +#endif +#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ + +#ifdef PNG_READ_SUPPORTED +/* This function, added to libpng-1.0.6g, is untested. */ +int PNGAPI +png_reset_zstream(png_structp png_ptr) +{ + if (png_ptr == NULL) + return Z_STREAM_ERROR; + return (inflateReset(&png_ptr->zstream)); +} +#endif /* PNG_READ_SUPPORTED */ + +/* This function was added to libpng-1.0.7 */ +png_uint_32 PNGAPI +png_access_version_number(void) +{ + /* Version of *.c files used when building libpng */ + return((png_uint_32) PNG_LIBPNG_VER); +} + + + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +#ifdef PNG_SIZE_T +/* Added at libpng version 1.2.6 */ + PNG_EXTERN png_size_t PNGAPI png_convert_size PNGARG((size_t size)); +png_size_t PNGAPI +png_convert_size(size_t size) +{ + if (size > (png_size_t)-1) + PNG_ABORT(); /* We haven't got access to png_ptr, so no png_error() */ + return ((png_size_t)size); +} +#endif /* PNG_SIZE_T */ + +/* Added at libpng version 1.2.34 and 1.4.0 (moved from pngset.c) */ +#ifdef PNG_cHRM_SUPPORTED +#ifdef PNG_CHECK_cHRM_SUPPORTED + +/* + * Multiply two 32-bit numbers, V1 and V2, using 32-bit + * arithmetic, to produce a 64 bit result in the HI/LO words. + * + * A B + * x C D + * ------ + * AD || BD + * AC || CB || 0 + * + * where A and B are the high and low 16-bit words of V1, + * C and D are the 16-bit words of V2, AD is the product of + * A and D, and X || Y is (X << 16) + Y. +*/ + +void /* PRIVATE */ +png_64bit_product (long v1, long v2, unsigned long *hi_product, + unsigned long *lo_product) +{ + int a, b, c, d; + long lo, hi, x, y; + + a = (v1 >> 16) & 0xffff; + b = v1 & 0xffff; + c = (v2 >> 16) & 0xffff; + d = v2 & 0xffff; + + lo = b * d; /* BD */ + x = a * d + c * b; /* AD + CB */ + y = ((lo >> 16) & 0xffff) + x; + + lo = (lo & 0xffff) | ((y & 0xffff) << 16); + hi = (y >> 16) & 0xffff; + + hi += a * c; /* AC */ + + *hi_product = (unsigned long)hi; + *lo_product = (unsigned long)lo; +} + +int /* PRIVATE */ +png_check_cHRM_fixed(png_structp png_ptr, + png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x, + png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y, + png_fixed_point blue_x, png_fixed_point blue_y) +{ + int ret = 1; + unsigned long xy_hi,xy_lo,yx_hi,yx_lo; + + png_debug(1, "in function png_check_cHRM_fixed"); + + if (png_ptr == NULL) + return 0; + + if (white_x < 0 || white_y <= 0 || + red_x < 0 || red_y < 0 || + green_x < 0 || green_y < 0 || + blue_x < 0 || blue_y < 0) + { + png_warning(png_ptr, + "Ignoring attempt to set negative chromaticity value"); + ret = 0; + } + if (white_x > (png_fixed_point) PNG_UINT_31_MAX || + white_y > (png_fixed_point) PNG_UINT_31_MAX || + red_x > (png_fixed_point) PNG_UINT_31_MAX || + red_y > (png_fixed_point) PNG_UINT_31_MAX || + green_x > (png_fixed_point) PNG_UINT_31_MAX || + green_y > (png_fixed_point) PNG_UINT_31_MAX || + blue_x > (png_fixed_point) PNG_UINT_31_MAX || + blue_y > (png_fixed_point) PNG_UINT_31_MAX ) + { + png_warning(png_ptr, + "Ignoring attempt to set chromaticity value exceeding 21474.83"); + ret = 0; + } + if (white_x > 100000L - white_y) + { + png_warning(png_ptr, "Invalid cHRM white point"); + ret = 0; + } + if (red_x > 100000L - red_y) + { + png_warning(png_ptr, "Invalid cHRM red point"); + ret = 0; + } + if (green_x > 100000L - green_y) + { + png_warning(png_ptr, "Invalid cHRM green point"); + ret = 0; + } + if (blue_x > 100000L - blue_y) + { + png_warning(png_ptr, "Invalid cHRM blue point"); + ret = 0; + } + + png_64bit_product(green_x - red_x, blue_y - red_y, &xy_hi, &xy_lo); + png_64bit_product(green_y - red_y, blue_x - red_x, &yx_hi, &yx_lo); + + if (xy_hi == yx_hi && xy_lo == yx_lo) + { + png_warning(png_ptr, + "Ignoring attempt to set cHRM RGB triangle with zero area"); + ret = 0; + } + + return ret; +} +#endif /* PNG_CHECK_cHRM_SUPPORTED */ +#endif /* PNG_cHRM_SUPPORTED */ + +void /* PRIVATE */ +png_check_IHDR(png_structp png_ptr, + png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_type, int compression_type, + int filter_type) +{ + int error = 0; + + /* Check for width and height valid values */ + if (width == 0) + { + png_warning(png_ptr, "Image width is zero in IHDR"); + error = 1; + } + + if (height == 0) + { + png_warning(png_ptr, "Image height is zero in IHDR"); + error = 1; + } + +#ifdef PNG_SET_USER_LIMITS_SUPPORTED + if (width > png_ptr->user_width_max || width > PNG_USER_WIDTH_MAX) +#else + if (width > PNG_USER_WIDTH_MAX) +#endif + { + png_warning(png_ptr, "Image width exceeds user limit in IHDR"); + error = 1; + } + +#ifdef PNG_SET_USER_LIMITS_SUPPORTED + if (height > png_ptr->user_height_max || height > PNG_USER_HEIGHT_MAX) +#else + if (height > PNG_USER_HEIGHT_MAX) +#endif + { + png_warning(png_ptr, "Image height exceeds user limit in IHDR"); + error = 1; + } + + if (width > PNG_UINT_31_MAX) + { + png_warning(png_ptr, "Invalid image width in IHDR"); + error = 1; + } + + if ( height > PNG_UINT_31_MAX) + { + png_warning(png_ptr, "Invalid image height in IHDR"); + error = 1; + } + + if ( width > (PNG_UINT_32_MAX + >> 3) /* 8-byte RGBA pixels */ + - 64 /* bigrowbuf hack */ + - 1 /* filter byte */ + - 7*8 /* rounding of width to multiple of 8 pixels */ + - 8) /* extra max_pixel_depth pad */ + png_warning(png_ptr, "Width is too large for libpng to process pixels"); + + /* Check other values */ + if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 && + bit_depth != 8 && bit_depth != 16) + { + png_warning(png_ptr, "Invalid bit depth in IHDR"); + error = 1; + } + + if (color_type < 0 || color_type == 1 || + color_type == 5 || color_type > 6) + { + png_warning(png_ptr, "Invalid color type in IHDR"); + error = 1; + } + + if (((color_type == PNG_COLOR_TYPE_PALETTE) && bit_depth > 8) || + ((color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_GRAY_ALPHA || + color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8)) + { + png_warning(png_ptr, "Invalid color type/bit depth combination in IHDR"); + error = 1; + } + + if (interlace_type >= PNG_INTERLACE_LAST) + { + png_warning(png_ptr, "Unknown interlace method in IHDR"); + error = 1; + } + + if (compression_type != PNG_COMPRESSION_TYPE_BASE) + { + png_warning(png_ptr, "Unknown compression method in IHDR"); + error = 1; + } + +#ifdef PNG_MNG_FEATURES_SUPPORTED + /* Accept filter_method 64 (intrapixel differencing) only if + * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and + * 2. Libpng did not read a PNG signature (this filter_method is only + * used in PNG datastreams that are embedded in MNG datastreams) and + * 3. The application called png_permit_mng_features with a mask that + * included PNG_FLAG_MNG_FILTER_64 and + * 4. The filter_method is 64 and + * 5. The color_type is RGB or RGBA + */ + if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) && + png_ptr->mng_features_permitted) + png_warning(png_ptr, "MNG features are not allowed in a PNG datastream"); + + if (filter_type != PNG_FILTER_TYPE_BASE) + { + if (!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (filter_type == PNG_INTRAPIXEL_DIFFERENCING) && + ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) == 0) && + (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_RGB_ALPHA))) + { + png_warning(png_ptr, "Unknown filter method in IHDR"); + error = 1; + } + + if (png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) + { + png_warning(png_ptr, "Invalid filter method in IHDR"); + error = 1; + } + } + +#else + if (filter_type != PNG_FILTER_TYPE_BASE) + { + png_warning(png_ptr, "Unknown filter method in IHDR"); + error = 1; + } +#endif + + if (error == 1) + png_error(png_ptr, "Invalid IHDR data"); +} +#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ diff --git a/reactos/dll/3rdparty/libpng/png.h b/reactos/dll/3rdparty/libpng/png.h new file mode 100644 index 00000000000..842f3fc951b --- /dev/null +++ b/reactos/dll/3rdparty/libpng/png.h @@ -0,0 +1,2701 @@ + +/* png.h - header file for PNG reference library + * + * libpng version 1.4.3 - June 26, 2010 + * Copyright (c) 1998-2010 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license (See LICENSE, below) + * + * Authors and maintainers: + * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat + * libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger + * libpng versions 0.97, January 1998, through 1.4.3 - June 26, 2010: Glenn + * See also "Contributing Authors", below. + * + * Note about libpng version numbers: + * + * Due to various miscommunications, unforeseen code incompatibilities + * and occasional factors outside the authors' control, version numbering + * on the library has not always been consistent and straightforward. + * The following table summarizes matters since version 0.89c, which was + * the first widely used release: + * + * source png.h png.h shared-lib + * version string int version + * ------- ------ ----- ---------- + * 0.89c "1.0 beta 3" 0.89 89 1.0.89 + * 0.90 "1.0 beta 4" 0.90 90 0.90 [should have been 2.0.90] + * 0.95 "1.0 beta 5" 0.95 95 0.95 [should have been 2.0.95] + * 0.96 "1.0 beta 6" 0.96 96 0.96 [should have been 2.0.96] + * 0.97b "1.00.97 beta 7" 1.00.97 97 1.0.1 [should have been 2.0.97] + * 0.97c 0.97 97 2.0.97 + * 0.98 0.98 98 2.0.98 + * 0.99 0.99 98 2.0.99 + * 0.99a-m 0.99 99 2.0.99 + * 1.00 1.00 100 2.1.0 [100 should be 10000] + * 1.0.0 (from here on, the 100 2.1.0 [100 should be 10000] + * 1.0.1 png.h string is 10001 2.1.0 + * 1.0.1a-e identical to the 10002 from here on, the shared library + * 1.0.2 source version) 10002 is 2.V where V is the source code + * 1.0.2a-b 10003 version, except as noted. + * 1.0.3 10003 + * 1.0.3a-d 10004 + * 1.0.4 10004 + * 1.0.4a-f 10005 + * 1.0.5 (+ 2 patches) 10005 + * 1.0.5a-d 10006 + * 1.0.5e-r 10100 (not source compatible) + * 1.0.5s-v 10006 (not binary compatible) + * 1.0.6 (+ 3 patches) 10006 (still binary incompatible) + * 1.0.6d-f 10007 (still binary incompatible) + * 1.0.6g 10007 + * 1.0.6h 10007 10.6h (testing xy.z so-numbering) + * 1.0.6i 10007 10.6i + * 1.0.6j 10007 2.1.0.6j (incompatible with 1.0.0) + * 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 (binary compatible) + * 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 (binary compatible) + * 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible) + * 1.0.7 1 10007 (still compatible) + * 1.0.8beta1-4 1 10008 2.1.0.8beta1-4 + * 1.0.8rc1 1 10008 2.1.0.8rc1 + * 1.0.8 1 10008 2.1.0.8 + * 1.0.9beta1-6 1 10009 2.1.0.9beta1-6 + * 1.0.9rc1 1 10009 2.1.0.9rc1 + * 1.0.9beta7-10 1 10009 2.1.0.9beta7-10 + * 1.0.9rc2 1 10009 2.1.0.9rc2 + * 1.0.9 1 10009 2.1.0.9 + * 1.0.10beta1 1 10010 2.1.0.10beta1 + * 1.0.10rc1 1 10010 2.1.0.10rc1 + * 1.0.10 1 10010 2.1.0.10 + * 1.0.11beta1-3 1 10011 2.1.0.11beta1-3 + * 1.0.11rc1 1 10011 2.1.0.11rc1 + * 1.0.11 1 10011 2.1.0.11 + * 1.0.12beta1-2 2 10012 2.1.0.12beta1-2 + * 1.0.12rc1 2 10012 2.1.0.12rc1 + * 1.0.12 2 10012 2.1.0.12 + * 1.1.0a-f - 10100 2.1.1.0a-f (branch abandoned) + * 1.2.0beta1-2 2 10200 2.1.2.0beta1-2 + * 1.2.0beta3-5 3 10200 3.1.2.0beta3-5 + * 1.2.0rc1 3 10200 3.1.2.0rc1 + * 1.2.0 3 10200 3.1.2.0 + * 1.2.1beta1-4 3 10201 3.1.2.1beta1-4 + * 1.2.1rc1-2 3 10201 3.1.2.1rc1-2 + * 1.2.1 3 10201 3.1.2.1 + * 1.2.2beta1-6 12 10202 12.so.0.1.2.2beta1-6 + * 1.0.13beta1 10 10013 10.so.0.1.0.13beta1 + * 1.0.13rc1 10 10013 10.so.0.1.0.13rc1 + * 1.2.2rc1 12 10202 12.so.0.1.2.2rc1 + * 1.0.13 10 10013 10.so.0.1.0.13 + * 1.2.2 12 10202 12.so.0.1.2.2 + * 1.2.3rc1-6 12 10203 12.so.0.1.2.3rc1-6 + * 1.2.3 12 10203 12.so.0.1.2.3 + * 1.2.4beta1-3 13 10204 12.so.0.1.2.4beta1-3 + * 1.0.14rc1 13 10014 10.so.0.1.0.14rc1 + * 1.2.4rc1 13 10204 12.so.0.1.2.4rc1 + * 1.0.14 10 10014 10.so.0.1.0.14 + * 1.2.4 13 10204 12.so.0.1.2.4 + * 1.2.5beta1-2 13 10205 12.so.0.1.2.5beta1-2 + * 1.0.15rc1-3 10 10015 10.so.0.1.0.15rc1-3 + * 1.2.5rc1-3 13 10205 12.so.0.1.2.5rc1-3 + * 1.0.15 10 10015 10.so.0.1.0.15 + * 1.2.5 13 10205 12.so.0.1.2.5 + * 1.2.6beta1-4 13 10206 12.so.0.1.2.6beta1-4 + * 1.0.16 10 10016 10.so.0.1.0.16 + * 1.2.6 13 10206 12.so.0.1.2.6 + * 1.2.7beta1-2 13 10207 12.so.0.1.2.7beta1-2 + * 1.0.17rc1 10 10017 12.so.0.1.0.17rc1 + * 1.2.7rc1 13 10207 12.so.0.1.2.7rc1 + * 1.0.17 10 10017 12.so.0.1.0.17 + * 1.2.7 13 10207 12.so.0.1.2.7 + * 1.2.8beta1-5 13 10208 12.so.0.1.2.8beta1-5 + * 1.0.18rc1-5 10 10018 12.so.0.1.0.18rc1-5 + * 1.2.8rc1-5 13 10208 12.so.0.1.2.8rc1-5 + * 1.0.18 10 10018 12.so.0.1.0.18 + * 1.2.8 13 10208 12.so.0.1.2.8 + * 1.2.9beta1-3 13 10209 12.so.0.1.2.9beta1-3 + * 1.2.9beta4-11 13 10209 12.so.0.9[.0] + * 1.2.9rc1 13 10209 12.so.0.9[.0] + * 1.2.9 13 10209 12.so.0.9[.0] + * 1.2.10beta1-7 13 10210 12.so.0.10[.0] + * 1.2.10rc1-2 13 10210 12.so.0.10[.0] + * 1.2.10 13 10210 12.so.0.10[.0] + * 1.4.0beta1-5 14 10400 14.so.0.0[.0] + * 1.2.11beta1-4 13 10211 12.so.0.11[.0] + * 1.4.0beta7-8 14 10400 14.so.0.0[.0] + * 1.2.11 13 10211 12.so.0.11[.0] + * 1.2.12 13 10212 12.so.0.12[.0] + * 1.4.0beta9-14 14 10400 14.so.0.0[.0] + * 1.2.13 13 10213 12.so.0.13[.0] + * 1.4.0beta15-36 14 10400 14.so.0.0[.0] + * 1.4.0beta37-87 14 10400 14.so.14.0[.0] + * 1.4.0rc01 14 10400 14.so.14.0[.0] + * 1.4.0beta88-109 14 10400 14.so.14.0[.0] + * 1.4.0rc02-08 14 10400 14.so.14.0[.0] + * 1.4.0 14 10400 14.so.14.0[.0] + * 1.4.1beta01-03 14 10401 14.so.14.1[.0] + * 1.4.1rc01 14 10401 14.so.14.1[.0] + * 1.4.1beta04-12 14 10401 14.so.14.1[.0] + * 1.4.1rc02-04 14 10401 14.so.14.1[.0] + * 1.4.1 14 10401 14.so.14.1[.0] + * 1.4.2beta01 14 10402 14.so.14.2[.0] + * 1.4.2rc02-06 14 10402 14.so.14.2[.0] + * 1.4.2 14 10402 14.so.14.2[.0] + * 1.4.3beta01-05 14 10403 14.so.14.3[.0] + * 1.4.3rc01-03 14 10403 14.so.14.3[.0] + * 1.4.3 14 10403 14.so.14.3[.0] + * + * Henceforth the source version will match the shared-library major + * and minor numbers; the shared-library major version number will be + * used for changes in backward compatibility, as it is intended. The + * PNG_LIBPNG_VER macro, which is not used within libpng but is available + * for applications, is an unsigned integer of the form xyyzz corresponding + * to the source version x.y.z (leading zeros in y and z). Beta versions + * were given the previous public release number plus a letter, until + * version 1.0.6j; from then on they were given the upcoming public + * release number plus "betaNN" or "rcN". + * + * Binary incompatibility exists only when applications make direct access + * to the info_ptr or png_ptr members through png.h, and the compiled + * application is loaded with a different version of the library. + * + * DLLNUM will change each time there are forward or backward changes + * in binary compatibility (e.g., when a new feature is added). + * + * See libpng.txt or libpng.3 for more information. The PNG specification + * is available as a W3C Recommendation and as an ISO Specification, + * defines should NOT be changed. + */ +#define PNG_INFO_gAMA 0x0001 +#define PNG_INFO_sBIT 0x0002 +#define PNG_INFO_cHRM 0x0004 +#define PNG_INFO_PLTE 0x0008 +#define PNG_INFO_tRNS 0x0010 +#define PNG_INFO_bKGD 0x0020 +#define PNG_INFO_hIST 0x0040 +#define PNG_INFO_pHYs 0x0080 +#define PNG_INFO_oFFs 0x0100 +#define PNG_INFO_tIME 0x0200 +#define PNG_INFO_pCAL 0x0400 +#define PNG_INFO_sRGB 0x0800 /* GR-P, 0.96a */ +#define PNG_INFO_iCCP 0x1000 /* ESR, 1.0.6 */ +#define PNG_INFO_sPLT 0x2000 /* ESR, 1.0.6 */ +#define PNG_INFO_sCAL 0x4000 /* ESR, 1.0.6 */ +#define PNG_INFO_IDAT 0x8000L /* ESR, 1.0.6 */ + +/* This is used for the transformation routines, as some of them + * change these values for the row. It also should enable using + * the routines for other purposes. + */ +typedef struct png_row_info_struct +{ + png_uint_32 width; /* width of row */ + png_size_t rowbytes; /* number of bytes in row */ + png_byte color_type; /* color type of row */ + png_byte bit_depth; /* bit depth of row */ + png_byte channels; /* number of channels (1, 2, 3, or 4) */ + png_byte pixel_depth; /* bits per pixel (depth * channels) */ +} png_row_info; + +typedef png_row_info FAR * png_row_infop; +typedef png_row_info FAR * FAR * png_row_infopp; + +/* These are the function types for the I/O functions and for the functions + * that allow the user to override the default I/O functions with his or her + * own. The png_error_ptr type should match that of user-supplied warning + * and error functions, while the png_rw_ptr type should match that of the + * user read/write data functions. + */ +typedef struct png_struct_def png_struct; +typedef png_struct FAR * png_structp; + +typedef void (PNGAPI *png_error_ptr) PNGARG((png_structp, png_const_charp)); +typedef void (PNGAPI *png_rw_ptr) PNGARG((png_structp, png_bytep, png_size_t)); +typedef void (PNGAPI *png_flush_ptr) PNGARG((png_structp)); +typedef void (PNGAPI *png_read_status_ptr) PNGARG((png_structp, png_uint_32, + int)); +typedef void (PNGAPI *png_write_status_ptr) PNGARG((png_structp, png_uint_32, + int)); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +typedef void (PNGAPI *png_progressive_info_ptr) PNGARG((png_structp, + png_infop)); +typedef void (PNGAPI *png_progressive_end_ptr) PNGARG((png_structp, png_infop)); +typedef void (PNGAPI *png_progressive_row_ptr) PNGARG((png_structp, png_bytep, + png_uint_32, int)); +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +typedef void (PNGAPI *png_user_transform_ptr) PNGARG((png_structp, + png_row_infop, png_bytep)); +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +typedef int (PNGAPI *png_user_chunk_ptr) PNGARG((png_structp, + png_unknown_chunkp)); +#endif +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED +typedef void (PNGAPI *png_unknown_chunk_ptr) PNGARG((png_structp)); +#endif +#ifdef PNG_SETJMP_SUPPORTED +/* This must match the function definition in , and the + * application must include this before png.h to obtain the definition + * of jmp_buf. + */ +typedef void (PNGAPI *png_longjmp_ptr) PNGARG((jmp_buf, int)); +#endif + +/* Transform masks for the high-level interface */ +#define PNG_TRANSFORM_IDENTITY 0x0000 /* read and write */ +#define PNG_TRANSFORM_STRIP_16 0x0001 /* read only */ +#define PNG_TRANSFORM_STRIP_ALPHA 0x0002 /* read only */ +#define PNG_TRANSFORM_PACKING 0x0004 /* read and write */ +#define PNG_TRANSFORM_PACKSWAP 0x0008 /* read and write */ +#define PNG_TRANSFORM_EXPAND 0x0010 /* read only */ +#define PNG_TRANSFORM_INVERT_MONO 0x0020 /* read and write */ +#define PNG_TRANSFORM_SHIFT 0x0040 /* read and write */ +#define PNG_TRANSFORM_BGR 0x0080 /* read and write */ +#define PNG_TRANSFORM_SWAP_ALPHA 0x0100 /* read and write */ +#define PNG_TRANSFORM_SWAP_ENDIAN 0x0200 /* read and write */ +#define PNG_TRANSFORM_INVERT_ALPHA 0x0400 /* read and write */ +#define PNG_TRANSFORM_STRIP_FILLER 0x0800 /* write only */ +/* Added to libpng-1.2.34 */ +#define PNG_TRANSFORM_STRIP_FILLER_BEFORE PNG_TRANSFORM_STRIP_FILLER +#define PNG_TRANSFORM_STRIP_FILLER_AFTER 0x1000 /* write only */ +/* Added to libpng-1.4.0 */ +#define PNG_TRANSFORM_GRAY_TO_RGB 0x2000 /* read only */ + +/* Flags for MNG supported features */ +#define PNG_FLAG_MNG_EMPTY_PLTE 0x01 +#define PNG_FLAG_MNG_FILTER_64 0x04 +#define PNG_ALL_MNG_FEATURES 0x05 + +typedef png_voidp (*png_malloc_ptr) PNGARG((png_structp, png_alloc_size_t)); +typedef void (*png_free_ptr) PNGARG((png_structp, png_voidp)); + +/* The structure that holds the information to read and write PNG files. + * The only people who need to care about what is inside of this are the + * people who will be modifying the library for their own special needs. + * It should NOT be accessed directly by an application, except to store + * the jmp_buf. + */ + +struct png_struct_def +{ +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf jmpbuf PNG_DEPSTRUCT; /* used in png_error */ + png_longjmp_ptr longjmp_fn PNG_DEPSTRUCT;/* setjmp non-local goto + function. */ +#endif + png_error_ptr error_fn PNG_DEPSTRUCT; /* function for printing + errors and aborting */ + png_error_ptr warning_fn PNG_DEPSTRUCT; /* function for printing + warnings */ + png_voidp error_ptr PNG_DEPSTRUCT; /* user supplied struct for + error functions */ + png_rw_ptr write_data_fn PNG_DEPSTRUCT; /* function for writing + output data */ + png_rw_ptr read_data_fn PNG_DEPSTRUCT; /* function for reading + input data */ + png_voidp io_ptr PNG_DEPSTRUCT; /* ptr to application struct + for I/O functions */ + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + png_user_transform_ptr read_user_transform_fn PNG_DEPSTRUCT; /* user read + transform */ +#endif + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED + png_user_transform_ptr write_user_transform_fn PNG_DEPSTRUCT; /* user write + transform */ +#endif + +/* These were added in libpng-1.0.2 */ +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) + png_voidp user_transform_ptr PNG_DEPSTRUCT; /* user supplied struct + for user transform */ + png_byte user_transform_depth PNG_DEPSTRUCT; /* bit depth of user + transformed pixels */ + png_byte user_transform_channels PNG_DEPSTRUCT; /* channels in user + transformed pixels */ +#endif +#endif + + png_uint_32 mode PNG_DEPSTRUCT; /* tells us where we are in + the PNG file */ + png_uint_32 flags PNG_DEPSTRUCT; /* flags indicating various + things to libpng */ + png_uint_32 transformations PNG_DEPSTRUCT; /* which transformations + to perform */ + + z_stream zstream PNG_DEPSTRUCT; /* pointer to decompression + structure (below) */ + png_bytep zbuf PNG_DEPSTRUCT; /* buffer for zlib */ + png_size_t zbuf_size PNG_DEPSTRUCT; /* size of zbuf */ + int zlib_level PNG_DEPSTRUCT; /* holds zlib compression level */ + int zlib_method PNG_DEPSTRUCT; /* holds zlib compression method */ + int zlib_window_bits PNG_DEPSTRUCT; /* holds zlib compression window + bits */ + int zlib_mem_level PNG_DEPSTRUCT; /* holds zlib compression memory + level */ + int zlib_strategy PNG_DEPSTRUCT; /* holds zlib compression + strategy */ + + png_uint_32 width PNG_DEPSTRUCT; /* width of image in pixels */ + png_uint_32 height PNG_DEPSTRUCT; /* height of image in pixels */ + png_uint_32 num_rows PNG_DEPSTRUCT; /* number of rows in current pass */ + png_uint_32 usr_width PNG_DEPSTRUCT; /* width of row at start of write */ + png_size_t rowbytes PNG_DEPSTRUCT; /* size of row in bytes */ +#if 0 /* Replaced with the following in libpng-1.4.1 */ + png_size_t irowbytes PNG_DEPSTRUCT; +#endif +/* Added in libpng-1.4.1 */ +#ifdef PNG_USER_LIMITS_SUPPORTED + /* Total memory that a zTXt, sPLT, iTXt, iCCP, or unknown chunk + * can occupy when decompressed. 0 means unlimited. + * We will change the typedef from png_size_t to png_alloc_size_t + * in libpng-1.6.0 + */ + png_alloc_size_t user_chunk_malloc_max PNG_DEPSTRUCT; +#endif + png_uint_32 iwidth PNG_DEPSTRUCT; /* width of current interlaced + row in pixels */ + png_uint_32 row_number PNG_DEPSTRUCT; /* current row in interlace pass */ + png_bytep prev_row PNG_DEPSTRUCT; /* buffer to save previous + (unfiltered) row */ + png_bytep row_buf PNG_DEPSTRUCT; /* buffer to save current + (unfiltered) row */ + png_bytep sub_row PNG_DEPSTRUCT; /* buffer to save "sub" row + when filtering */ + png_bytep up_row PNG_DEPSTRUCT; /* buffer to save "up" row + when filtering */ + png_bytep avg_row PNG_DEPSTRUCT; /* buffer to save "avg" row + when filtering */ + png_bytep paeth_row PNG_DEPSTRUCT; /* buffer to save "Paeth" row + when filtering */ + png_row_info row_info PNG_DEPSTRUCT; /* used for transformation + routines */ + + png_uint_32 idat_size PNG_DEPSTRUCT; /* current IDAT size for read */ + png_uint_32 crc PNG_DEPSTRUCT; /* current chunk CRC value */ + png_colorp palette PNG_DEPSTRUCT; /* palette from the input file */ + png_uint_16 num_palette PNG_DEPSTRUCT; /* number of color entries in + palette */ + png_uint_16 num_trans PNG_DEPSTRUCT; /* number of transparency values */ + png_byte chunk_name[5] PNG_DEPSTRUCT; /* null-terminated name of current + chunk */ + png_byte compression PNG_DEPSTRUCT; /* file compression type + (always 0) */ + png_byte filter PNG_DEPSTRUCT; /* file filter type (always 0) */ + png_byte interlaced PNG_DEPSTRUCT; /* PNG_INTERLACE_NONE, + PNG_INTERLACE_ADAM7 */ + png_byte pass PNG_DEPSTRUCT; /* current interlace pass (0 - 6) */ + png_byte do_filter PNG_DEPSTRUCT; /* row filter flags (see + PNG_FILTER_ below ) */ + png_byte color_type PNG_DEPSTRUCT; /* color type of file */ + png_byte bit_depth PNG_DEPSTRUCT; /* bit depth of file */ + png_byte usr_bit_depth PNG_DEPSTRUCT; /* bit depth of users row */ + png_byte pixel_depth PNG_DEPSTRUCT; /* number of bits per pixel */ + png_byte channels PNG_DEPSTRUCT; /* number of channels in file */ + png_byte usr_channels PNG_DEPSTRUCT; /* channels at start of write */ + png_byte sig_bytes PNG_DEPSTRUCT; /* magic bytes read/written from + start of file */ + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) + png_uint_16 filler PNG_DEPSTRUCT; /* filler bytes for pixel + expansion */ +#endif + +#ifdef PNG_bKGD_SUPPORTED + png_byte background_gamma_type PNG_DEPSTRUCT; +# ifdef PNG_FLOATING_POINT_SUPPORTED + float background_gamma PNG_DEPSTRUCT; +# endif + png_color_16 background PNG_DEPSTRUCT; /* background color in + screen gamma space */ +#ifdef PNG_READ_GAMMA_SUPPORTED + png_color_16 background_1 PNG_DEPSTRUCT; /* background normalized + to gamma 1.0 */ +#endif +#endif /* PNG_bKGD_SUPPORTED */ + +#ifdef PNG_WRITE_FLUSH_SUPPORTED + png_flush_ptr output_flush_fn PNG_DEPSTRUCT; /* Function for flushing + output */ + png_uint_32 flush_dist PNG_DEPSTRUCT; /* how many rows apart to flush, + 0 - no flush */ + png_uint_32 flush_rows PNG_DEPSTRUCT; /* number of rows written since + last flush */ +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + int gamma_shift PNG_DEPSTRUCT; /* number of "insignificant" bits + 16-bit gamma */ +#ifdef PNG_FLOATING_POINT_SUPPORTED + float gamma PNG_DEPSTRUCT; /* file gamma value */ + float screen_gamma PNG_DEPSTRUCT; /* screen gamma value + (display_exponent) */ +#endif +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + png_bytep gamma_table PNG_DEPSTRUCT; /* gamma table for 8-bit + depth files */ + png_bytep gamma_from_1 PNG_DEPSTRUCT; /* converts from 1.0 to screen */ + png_bytep gamma_to_1 PNG_DEPSTRUCT; /* converts from file to 1.0 */ + png_uint_16pp gamma_16_table PNG_DEPSTRUCT; /* gamma table for 16-bit + depth files */ + png_uint_16pp gamma_16_from_1 PNG_DEPSTRUCT; /* converts from 1.0 to + screen */ + png_uint_16pp gamma_16_to_1 PNG_DEPSTRUCT; /* converts from file to 1.0 */ +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_sBIT_SUPPORTED) + png_color_8 sig_bit PNG_DEPSTRUCT; /* significant bits in each + available channel */ +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) + png_color_8 shift PNG_DEPSTRUCT; /* shift for significant bit + tranformation */ +#endif + +#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) \ + || defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + png_bytep trans_alpha PNG_DEPSTRUCT; /* alpha values for + paletted files */ + png_color_16 trans_color PNG_DEPSTRUCT; /* transparent color for + non-paletted files */ +#endif + + png_read_status_ptr read_row_fn PNG_DEPSTRUCT; /* called after each + row is decoded */ + png_write_status_ptr write_row_fn PNG_DEPSTRUCT; /* called after each + row is encoded */ +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED + png_progressive_info_ptr info_fn PNG_DEPSTRUCT; /* called after header + data fully read */ + png_progressive_row_ptr row_fn PNG_DEPSTRUCT; /* called after each + prog. row is decoded */ + png_progressive_end_ptr end_fn PNG_DEPSTRUCT; /* called after image + is complete */ + png_bytep save_buffer_ptr PNG_DEPSTRUCT; /* current location in + save_buffer */ + png_bytep save_buffer PNG_DEPSTRUCT; /* buffer for previously + read data */ + png_bytep current_buffer_ptr PNG_DEPSTRUCT; /* current location in + current_buffer */ + png_bytep current_buffer PNG_DEPSTRUCT; /* buffer for recently + used data */ + png_uint_32 push_length PNG_DEPSTRUCT; /* size of current input + chunk */ + png_uint_32 skip_length PNG_DEPSTRUCT; /* bytes to skip in + input data */ + png_size_t save_buffer_size PNG_DEPSTRUCT; /* amount of data now + in save_buffer */ + png_size_t save_buffer_max PNG_DEPSTRUCT; /* total size of + save_buffer */ + png_size_t buffer_size PNG_DEPSTRUCT; /* total amount of + available input data */ + png_size_t current_buffer_size PNG_DEPSTRUCT; /* amount of data now + in current_buffer */ + int process_mode PNG_DEPSTRUCT; /* what push library + is currently doing */ + int cur_palette PNG_DEPSTRUCT; /* current push library + palette index */ + +# ifdef PNG_TEXT_SUPPORTED + png_size_t current_text_size PNG_DEPSTRUCT; /* current size of + text input data */ + png_size_t current_text_left PNG_DEPSTRUCT; /* how much text left + to read in input */ + png_charp current_text PNG_DEPSTRUCT; /* current text chunk + buffer */ + png_charp current_text_ptr PNG_DEPSTRUCT; /* current location + in current_text */ +# endif /* PNG_PROGRESSIVE_READ_SUPPORTED && PNG_TEXT_SUPPORTED */ + +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + +#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__) +/* For the Borland special 64K segment handler */ + png_bytepp offset_table_ptr PNG_DEPSTRUCT; + png_bytep offset_table PNG_DEPSTRUCT; + png_uint_16 offset_table_number PNG_DEPSTRUCT; + png_uint_16 offset_table_count PNG_DEPSTRUCT; + png_uint_16 offset_table_count_free PNG_DEPSTRUCT; +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED + png_bytep palette_lookup PNG_DEPSTRUCT; /* lookup table for quantizing */ + png_bytep quantize_index PNG_DEPSTRUCT; /* index translation for palette + files */ +#endif + +#if defined(PNG_READ_QUANTIZE_SUPPORTED) || defined(PNG_hIST_SUPPORTED) + png_uint_16p hist PNG_DEPSTRUCT; /* histogram */ +#endif + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + png_byte heuristic_method PNG_DEPSTRUCT; /* heuristic for row + filter selection */ + png_byte num_prev_filters PNG_DEPSTRUCT; /* number of weights + for previous rows */ + png_bytep prev_filters PNG_DEPSTRUCT; /* filter type(s) of + previous row(s) */ + png_uint_16p filter_weights PNG_DEPSTRUCT; /* weight(s) for previous + line(s) */ + png_uint_16p inv_filter_weights PNG_DEPSTRUCT; /* 1/weight(s) for + previous line(s) */ + png_uint_16p filter_costs PNG_DEPSTRUCT; /* relative filter + calculation cost */ + png_uint_16p inv_filter_costs PNG_DEPSTRUCT; /* 1/relative filter + calculation cost */ +#endif + +#ifdef PNG_TIME_RFC1123_SUPPORTED + png_charp time_buffer PNG_DEPSTRUCT; /* String to hold RFC 1123 time text */ +#endif + +/* New members added in libpng-1.0.6 */ + + png_uint_32 free_me PNG_DEPSTRUCT; /* flags items libpng is + responsible for freeing */ + +#ifdef PNG_USER_CHUNKS_SUPPORTED + png_voidp user_chunk_ptr PNG_DEPSTRUCT; + png_user_chunk_ptr read_user_chunk_fn PNG_DEPSTRUCT; /* user read + chunk handler */ +#endif + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + int num_chunk_list PNG_DEPSTRUCT; + png_bytep chunk_list PNG_DEPSTRUCT; +#endif + +/* New members added in libpng-1.0.3 */ +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + png_byte rgb_to_gray_status PNG_DEPSTRUCT; + /* These were changed from png_byte in libpng-1.0.6 */ + png_uint_16 rgb_to_gray_red_coeff PNG_DEPSTRUCT; + png_uint_16 rgb_to_gray_green_coeff PNG_DEPSTRUCT; + png_uint_16 rgb_to_gray_blue_coeff PNG_DEPSTRUCT; +#endif + +/* New member added in libpng-1.0.4 (renamed in 1.0.9) */ +#if defined(PNG_MNG_FEATURES_SUPPORTED) || \ + defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \ + defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) +/* Changed from png_byte to png_uint_32 at version 1.2.0 */ + png_uint_32 mng_features_permitted PNG_DEPSTRUCT; +#endif + +/* New member added in libpng-1.0.7 */ +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + png_fixed_point int_gamma PNG_DEPSTRUCT; +#endif + +/* New member added in libpng-1.0.9, ifdef'ed out in 1.0.12, enabled in 1.2.0 */ +#ifdef PNG_MNG_FEATURES_SUPPORTED + png_byte filter_type PNG_DEPSTRUCT; +#endif + +/* New members added in libpng-1.2.0 */ + +/* New members added in libpng-1.0.2 but first enabled by default in 1.2.0 */ +#ifdef PNG_USER_MEM_SUPPORTED + png_voidp mem_ptr PNG_DEPSTRUCT; /* user supplied struct for + mem functions */ + png_malloc_ptr malloc_fn PNG_DEPSTRUCT; /* function for + allocating memory */ + png_free_ptr free_fn PNG_DEPSTRUCT; /* function for + freeing memory */ +#endif + +/* New member added in libpng-1.0.13 and 1.2.0 */ + png_bytep big_row_buf PNG_DEPSTRUCT; /* buffer to save current + (unfiltered) row */ + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +/* The following three members were added at version 1.0.14 and 1.2.4 */ + png_bytep quantize_sort PNG_DEPSTRUCT; /* working sort array */ + png_bytep index_to_palette PNG_DEPSTRUCT; /* where the original + index currently is + in the palette */ + png_bytep palette_to_index PNG_DEPSTRUCT; /* which original index + points to this + palette color */ +#endif + +/* New members added in libpng-1.0.16 and 1.2.6 */ + png_byte compression_type PNG_DEPSTRUCT; + +#ifdef PNG_USER_LIMITS_SUPPORTED + png_uint_32 user_width_max PNG_DEPSTRUCT; + png_uint_32 user_height_max PNG_DEPSTRUCT; + /* Added in libpng-1.4.0: Total number of sPLT, text, and unknown + * chunks that can be stored (0 means unlimited). + */ + png_uint_32 user_chunk_cache_max PNG_DEPSTRUCT; +#endif + +/* New member added in libpng-1.0.25 and 1.2.17 */ +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED + /* Storage for unknown chunk that the library doesn't recognize. */ + png_unknown_chunk unknown_chunk PNG_DEPSTRUCT; +#endif + +/* New members added in libpng-1.2.26 */ + png_uint_32 old_big_row_buf_size PNG_DEPSTRUCT; + png_uint_32 old_prev_row_size PNG_DEPSTRUCT; + +/* New member added in libpng-1.2.30 */ + png_charp chunkdata PNG_DEPSTRUCT; /* buffer for reading chunk data */ + +#ifdef PNG_IO_STATE_SUPPORTED +/* New member added in libpng-1.4.0 */ + png_uint_32 io_state PNG_DEPSTRUCT; +#endif +}; + + +/* This triggers a compiler error in png.c, if png.c and png.h + * do not agree upon the version number. + */ +typedef png_structp version_1_4_3; + +typedef png_struct FAR * FAR * png_structpp; + +/* Here are the function definitions most commonly used. This is not + * the place to find out how to use libpng. See libpng.txt for the + * full explanation, see example.c for the summary. This just provides + * a simple one line description of the use of each function. + */ + +/* Returns the version number of the library */ +extern PNG_EXPORT(png_uint_32,png_access_version_number) PNGARG((void)); + +/* Tell lib we have already handled the first magic bytes. + * Handling more than 8 bytes from the beginning of the file is an error. + */ +extern PNG_EXPORT(void,png_set_sig_bytes) PNGARG((png_structp png_ptr, + int num_bytes)); + +/* Check sig[start] through sig[start + num_to_check - 1] to see if it's a + * PNG file. Returns zero if the supplied bytes match the 8-byte PNG + * signature, and non-zero otherwise. Having num_to_check == 0 or + * start > 7 will always fail (ie return non-zero). + */ +extern PNG_EXPORT(int,png_sig_cmp) PNGARG((png_bytep sig, png_size_t start, + png_size_t num_to_check)); + +/* Simple signature checking function. This is the same as calling + * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n). + */ +#define png_check_sig(sig,n) !png_sig_cmp((sig), 0, (n)) + +/* Allocate and initialize png_ptr struct for reading, and any other memory. */ +extern PNG_EXPORT(png_structp,png_create_read_struct) + PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn)) PNG_ALLOCATED; + +/* Allocate and initialize png_ptr struct for writing, and any other memory */ +extern PNG_EXPORT(png_structp,png_create_write_struct) + PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn)) PNG_ALLOCATED; + +extern PNG_EXPORT(png_size_t,png_get_compression_buffer_size) + PNGARG((png_structp png_ptr)); + +extern PNG_EXPORT(void,png_set_compression_buffer_size) + PNGARG((png_structp png_ptr, png_size_t size)); + +/* Moved from pngconf.h in 1.4.0 and modified to ensure setjmp/longjmp + * match up. + */ +#ifdef PNG_SETJMP_SUPPORTED +/* This function returns the jmp_buf built in to *png_ptr. It must be + * supplied with an appropriate 'longjmp' function to use on that jmp_buf + * unless the default error function is overridden in which case NULL is + * acceptable. The size of the jmp_buf is checked against the actual size + * allocated by the library - the call will return NULL on a mismatch + * indicating an ABI mismatch. + */ +extern PNG_EXPORT(jmp_buf*, png_set_longjmp_fn) + PNGARG((png_structp png_ptr, png_longjmp_ptr longjmp_fn, size_t + jmp_buf_size)); +# define png_jmpbuf(png_ptr) \ + (*png_set_longjmp_fn((png_ptr), longjmp, sizeof (jmp_buf))) +#else +# define png_jmpbuf(png_ptr) \ + (LIBPNG_WAS_COMPILED_WITH__PNG_NO_SETJMP) +#endif + +#ifdef PNG_READ_SUPPORTED +/* Reset the compression stream */ +extern PNG_EXPORT(int,png_reset_zstream) PNGARG((png_structp png_ptr)); +#endif + +/* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */ +#ifdef PNG_USER_MEM_SUPPORTED +extern PNG_EXPORT(png_structp,png_create_read_struct_2) + PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn)) PNG_ALLOCATED; +extern PNG_EXPORT(png_structp,png_create_write_struct_2) + PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn)) PNG_ALLOCATED; +#endif + +/* Write the PNG file signature. */ +extern PNG_EXPORT(void,png_write_sig) PNGARG((png_structp png_ptr)); + +/* Write a PNG chunk - size, type, (optional) data, CRC. */ +extern PNG_EXPORT(void,png_write_chunk) PNGARG((png_structp png_ptr, + png_bytep chunk_name, png_bytep data, png_size_t length)); + +/* Write the start of a PNG chunk - length and chunk name. */ +extern PNG_EXPORT(void,png_write_chunk_start) PNGARG((png_structp png_ptr, + png_bytep chunk_name, png_uint_32 length)); + +/* Write the data of a PNG chunk started with png_write_chunk_start(). */ +extern PNG_EXPORT(void,png_write_chunk_data) PNGARG((png_structp png_ptr, + png_bytep data, png_size_t length)); + +/* Finish a chunk started with png_write_chunk_start() (includes CRC). */ +extern PNG_EXPORT(void,png_write_chunk_end) PNGARG((png_structp png_ptr)); + +/* Allocate and initialize the info structure */ +extern PNG_EXPORT(png_infop,png_create_info_struct) + PNGARG((png_structp png_ptr)) PNG_ALLOCATED; + +extern PNG_EXPORT(void,png_info_init_3) PNGARG((png_infopp info_ptr, + png_size_t png_info_struct_size)); + +/* Writes all the PNG information before the image. */ +extern PNG_EXPORT(void,png_write_info_before_PLTE) PNGARG((png_structp png_ptr, + png_infop info_ptr)); +extern PNG_EXPORT(void,png_write_info) PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the information before the actual image data. */ +extern PNG_EXPORT(void,png_read_info) PNGARG((png_structp png_ptr, + png_infop info_ptr)); +#endif + +#ifdef PNG_TIME_RFC1123_SUPPORTED +extern PNG_EXPORT(png_charp,png_convert_to_rfc1123) + PNGARG((png_structp png_ptr, png_timep ptime)); +#endif + +#ifdef PNG_CONVERT_tIME_SUPPORTED +/* Convert from a struct tm to png_time */ +extern PNG_EXPORT(void,png_convert_from_struct_tm) PNGARG((png_timep ptime, + struct tm FAR * ttime)); + +/* Convert from time_t to png_time. Uses gmtime() */ +extern PNG_EXPORT(void,png_convert_from_time_t) PNGARG((png_timep ptime, + time_t ttime)); +#endif /* PNG_CONVERT_tIME_SUPPORTED */ + +#ifdef PNG_READ_EXPAND_SUPPORTED +/* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */ +extern PNG_EXPORT(void,png_set_expand) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(void,png_set_expand_gray_1_2_4_to_8) PNGARG((png_structp + png_ptr)); +extern PNG_EXPORT(void,png_set_palette_to_rgb) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(void,png_set_tRNS_to_alpha) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* Use blue, green, red order for pixels. */ +extern PNG_EXPORT(void,png_set_bgr) PNGARG((png_structp png_ptr)); +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED +/* Expand the grayscale to 24-bit RGB if necessary. */ +extern PNG_EXPORT(void,png_set_gray_to_rgb) PNGARG((png_structp png_ptr)); +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +/* Reduce RGB to grayscale. */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_rgb_to_gray) PNGARG((png_structp png_ptr, + int error_action, double red, double green )); +#endif +extern PNG_EXPORT(void,png_set_rgb_to_gray_fixed) PNGARG((png_structp png_ptr, + int error_action, png_fixed_point red, png_fixed_point green )); +extern PNG_EXPORT(png_byte,png_get_rgb_to_gray_status) PNGARG((png_structp + png_ptr)); +#endif + +extern PNG_EXPORT(void,png_build_grayscale_palette) PNGARG((int bit_depth, + png_colorp palette)); + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED +extern PNG_EXPORT(void,png_set_strip_alpha) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +extern PNG_EXPORT(void,png_set_swap_alpha) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +extern PNG_EXPORT(void,png_set_invert_alpha) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) +/* Add a filler byte to 8-bit Gray or 24-bit RGB images. */ +extern PNG_EXPORT(void,png_set_filler) PNGARG((png_structp png_ptr, + png_uint_32 filler, int flags)); +/* The values of the PNG_FILLER_ defines should NOT be changed */ +#define PNG_FILLER_BEFORE 0 +#define PNG_FILLER_AFTER 1 +/* Add an alpha byte to 8-bit Gray or 24-bit RGB images. */ +extern PNG_EXPORT(void,png_set_add_alpha) PNGARG((png_structp png_ptr, + png_uint_32 filler, int flags)); +#endif /* PNG_READ_FILLER_SUPPORTED || PNG_WRITE_FILLER_SUPPORTED */ + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* Swap bytes in 16-bit depth files. */ +extern PNG_EXPORT(void,png_set_swap) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) +/* Use 1 byte per pixel in 1, 2, or 4-bit depth files. */ +extern PNG_EXPORT(void,png_set_packing) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) || \ + defined(PNG_WRITE_PACKSWAP_SUPPORTED) +/* Swap packing order of pixels in bytes. */ +extern PNG_EXPORT(void,png_set_packswap) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) +/* Converts files to legal bit depths. */ +extern PNG_EXPORT(void,png_set_shift) PNGARG((png_structp png_ptr, + png_color_8p true_bits)); +#endif + +#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ + defined(PNG_WRITE_INTERLACING_SUPPORTED) +/* Have the code handle the interlacing. Returns the number of passes. */ +extern PNG_EXPORT(int,png_set_interlace_handling) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +/* Invert monochrome files */ +extern PNG_EXPORT(void,png_set_invert_mono) PNGARG((png_structp png_ptr)); +#endif + +#ifdef PNG_READ_BACKGROUND_SUPPORTED +/* Handle alpha and tRNS by replacing with a background color. */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_background) PNGARG((png_structp png_ptr, + png_color_16p background_color, int background_gamma_code, + int need_expand, double background_gamma)); +#endif +#define PNG_BACKGROUND_GAMMA_UNKNOWN 0 +#define PNG_BACKGROUND_GAMMA_SCREEN 1 +#define PNG_BACKGROUND_GAMMA_FILE 2 +#define PNG_BACKGROUND_GAMMA_UNIQUE 3 +#endif + +#ifdef PNG_READ_16_TO_8_SUPPORTED +/* Strip the second byte of information from a 16-bit depth file. */ +extern PNG_EXPORT(void,png_set_strip_16) PNGARG((png_structp png_ptr)); +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +/* Turn on quantizing, and reduce the palette to the number of colors + * available. Prior to libpng-1.4.2, this was png_set_dither(). + */ +extern PNG_EXPORT(void,png_set_quantize) PNGARG((png_structp png_ptr, + png_colorp palette, int num_palette, int maximum_colors, + png_uint_16p histogram, int full_quantize)); +#endif +/* This migration aid will be removed from libpng-1.5.0 */ +#define png_set_dither png_set_quantize + +#ifdef PNG_READ_GAMMA_SUPPORTED +/* Handle gamma correction. Screen_gamma=(display_exponent) */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_gamma) PNGARG((png_structp png_ptr, + double screen_gamma, double default_file_gamma)); +#endif +#endif + + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +/* Set how many lines between output flushes - 0 for no flushing */ +extern PNG_EXPORT(void,png_set_flush) PNGARG((png_structp png_ptr, int nrows)); +/* Flush the current PNG output buffer */ +extern PNG_EXPORT(void,png_write_flush) PNGARG((png_structp png_ptr)); +#endif + +/* Optional update palette with requested transformations */ +extern PNG_EXPORT(void,png_start_read_image) PNGARG((png_structp png_ptr)); + +/* Optional call to update the users info structure */ +extern PNG_EXPORT(void,png_read_update_info) PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read one or more rows of image data. */ +extern PNG_EXPORT(void,png_read_rows) PNGARG((png_structp png_ptr, + png_bytepp row, png_bytepp display_row, png_uint_32 num_rows)); +#endif + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read a row of data. */ +extern PNG_EXPORT(void,png_read_row) PNGARG((png_structp png_ptr, + png_bytep row, + png_bytep display_row)); +#endif + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the whole image into memory at once. */ +extern PNG_EXPORT(void,png_read_image) PNGARG((png_structp png_ptr, + png_bytepp image)); +#endif + +/* Write a row of image data */ +extern PNG_EXPORT(void,png_write_row) PNGARG((png_structp png_ptr, + png_bytep row)); + +/* Write a few rows of image data */ +extern PNG_EXPORT(void,png_write_rows) PNGARG((png_structp png_ptr, + png_bytepp row, png_uint_32 num_rows)); + +/* Write the image data */ +extern PNG_EXPORT(void,png_write_image) PNGARG((png_structp png_ptr, + png_bytepp image)); + +/* Write the end of the PNG file. */ +extern PNG_EXPORT(void,png_write_end) PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the end of the PNG file. */ +extern PNG_EXPORT(void,png_read_end) PNGARG((png_structp png_ptr, + png_infop info_ptr)); +#endif + +/* Free any memory associated with the png_info_struct */ +extern PNG_EXPORT(void,png_destroy_info_struct) PNGARG((png_structp png_ptr, + png_infopp info_ptr_ptr)); + +/* Free any memory associated with the png_struct and the png_info_structs */ +extern PNG_EXPORT(void,png_destroy_read_struct) PNGARG((png_structpp + png_ptr_ptr, png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr)); + +/* Free any memory associated with the png_struct and the png_info_structs */ +extern PNG_EXPORT(void,png_destroy_write_struct) + PNGARG((png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)); + +/* Set the libpng method of handling chunk CRC errors */ +extern PNG_EXPORT(void,png_set_crc_action) PNGARG((png_structp png_ptr, + int crit_action, int ancil_action)); + +/* Values for png_set_crc_action() to say how to handle CRC errors in + * ancillary and critical chunks, and whether to use the data contained + * therein. Note that it is impossible to "discard" data in a critical + * chunk. For versions prior to 0.90, the action was always error/quit, + * whereas in version 0.90 and later, the action for CRC errors in ancillary + * chunks is warn/discard. These values should NOT be changed. + * + * value action:critical action:ancillary + */ +#define PNG_CRC_DEFAULT 0 /* error/quit warn/discard data */ +#define PNG_CRC_ERROR_QUIT 1 /* error/quit error/quit */ +#define PNG_CRC_WARN_DISCARD 2 /* (INVALID) warn/discard data */ +#define PNG_CRC_WARN_USE 3 /* warn/use data warn/use data */ +#define PNG_CRC_QUIET_USE 4 /* quiet/use data quiet/use data */ +#define PNG_CRC_NO_CHANGE 5 /* use current value use current value */ + +/* These functions give the user control over the scan-line filtering in + * libpng and the compression methods used by zlib. These functions are + * mainly useful for testing, as the defaults should work with most users. + * Those users who are tight on memory or want faster performance at the + * expense of compression can modify them. See the compression library + * header file (zlib.h) for an explination of the compression functions. + */ + +/* Set the filtering method(s) used by libpng. Currently, the only valid + * value for "method" is 0. + */ +extern PNG_EXPORT(void,png_set_filter) PNGARG((png_structp png_ptr, int method, + int filters)); + +/* Flags for png_set_filter() to say which filters to use. The flags + * are chosen so that they don't conflict with real filter types + * below, in case they are supplied instead of the #defined constants. + * These values should NOT be changed. + */ +#define PNG_NO_FILTERS 0x00 +#define PNG_FILTER_NONE 0x08 +#define PNG_FILTER_SUB 0x10 +#define PNG_FILTER_UP 0x20 +#define PNG_FILTER_AVG 0x40 +#define PNG_FILTER_PAETH 0x80 +#define PNG_ALL_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP | \ + PNG_FILTER_AVG | PNG_FILTER_PAETH) + +/* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now. + * These defines should NOT be changed. + */ +#define PNG_FILTER_VALUE_NONE 0 +#define PNG_FILTER_VALUE_SUB 1 +#define PNG_FILTER_VALUE_UP 2 +#define PNG_FILTER_VALUE_AVG 3 +#define PNG_FILTER_VALUE_PAETH 4 +#define PNG_FILTER_VALUE_LAST 5 + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* EXPERIMENTAL */ +/* The "heuristic_method" is given by one of the PNG_FILTER_HEURISTIC_ + * defines, either the default (minimum-sum-of-absolute-differences), or + * the experimental method (weighted-minimum-sum-of-absolute-differences). + * + * Weights are factors >= 1.0, indicating how important it is to keep the + * filter type consistent between rows. Larger numbers mean the current + * filter is that many times as likely to be the same as the "num_weights" + * previous filters. This is cumulative for each previous row with a weight. + * There needs to be "num_weights" values in "filter_weights", or it can be + * NULL if the weights aren't being specified. Weights have no influence on + * the selection of the first row filter. Well chosen weights can (in theory) + * improve the compression for a given image. + * + * Costs are factors >= 1.0 indicating the relative decoding costs of a + * filter type. Higher costs indicate more decoding expense, and are + * therefore less likely to be selected over a filter with lower computational + * costs. There needs to be a value in "filter_costs" for each valid filter + * type (given by PNG_FILTER_VALUE_LAST), or it can be NULL if you aren't + * setting the costs. Costs try to improve the speed of decompression without + * unduly increasing the compressed image size. + * + * A negative weight or cost indicates the default value is to be used, and + * values in the range [0.0, 1.0) indicate the value is to remain unchanged. + * The default values for both weights and costs are currently 1.0, but may + * change if good general weighting/cost heuristics can be found. If both + * the weights and costs are set to 1.0, this degenerates the WEIGHTED method + * to the UNWEIGHTED method, but with added encoding time/computation. + */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_filter_heuristics) PNGARG((png_structp png_ptr, + int heuristic_method, int num_weights, png_doublep filter_weights, + png_doublep filter_costs)); +#endif +#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ + +/* Heuristic used for row filter selection. These defines should NOT be + * changed. + */ +#define PNG_FILTER_HEURISTIC_DEFAULT 0 /* Currently "UNWEIGHTED" */ +#define PNG_FILTER_HEURISTIC_UNWEIGHTED 1 /* Used by libpng < 0.95 */ +#define PNG_FILTER_HEURISTIC_WEIGHTED 2 /* Experimental feature */ +#define PNG_FILTER_HEURISTIC_LAST 3 /* Not a valid value */ + +/* Set the library compression level. Currently, valid values range from + * 0 - 9, corresponding directly to the zlib compression levels 0 - 9 + * (0 - no compression, 9 - "maximal" compression). Note that tests have + * shown that zlib compression levels 3-6 usually perform as well as level 9 + * for PNG images, and do considerably fewer caclulations. In the future, + * these values may not correspond directly to the zlib compression levels. + */ +extern PNG_EXPORT(void,png_set_compression_level) PNGARG((png_structp png_ptr, + int level)); + +extern PNG_EXPORT(void,png_set_compression_mem_level) + PNGARG((png_structp png_ptr, int mem_level)); + +extern PNG_EXPORT(void,png_set_compression_strategy) + PNGARG((png_structp png_ptr, int strategy)); + +extern PNG_EXPORT(void,png_set_compression_window_bits) + PNGARG((png_structp png_ptr, int window_bits)); + +extern PNG_EXPORT(void,png_set_compression_method) PNGARG((png_structp png_ptr, + int method)); + +/* These next functions are called for input/output, memory, and error + * handling. They are in the file pngrio.c, pngwio.c, and pngerror.c, + * and call standard C I/O routines such as fread(), fwrite(), and + * fprintf(). These functions can be made to use other I/O routines + * at run time for those applications that need to handle I/O in a + * different manner by calling png_set_???_fn(). See libpng.txt for + * more information. + */ + +#ifdef PNG_STDIO_SUPPORTED +/* Initialize the input/output for the PNG file to the default functions. */ +extern PNG_EXPORT(void,png_init_io) PNGARG((png_structp png_ptr, + png_FILE_p fp)); +#endif + +/* Replace the (error and abort), and warning functions with user + * supplied functions. If no messages are to be printed you must still + * write and use replacement functions. The replacement error_fn should + * still do a longjmp to the last setjmp location if you are using this + * method of error handling. If error_fn or warning_fn is NULL, the + * default function will be used. + */ + +extern PNG_EXPORT(void,png_set_error_fn) PNGARG((png_structp png_ptr, + png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn)); + +/* Return the user pointer associated with the error functions */ +extern PNG_EXPORT(png_voidp,png_get_error_ptr) PNGARG((png_structp png_ptr)); + +/* Replace the default data output functions with a user supplied one(s). + * If buffered output is not used, then output_flush_fn can be set to NULL. + * If PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile time + * output_flush_fn will be ignored (and thus can be NULL). + * It is probably a mistake to use NULL for output_flush_fn if + * write_data_fn is not also NULL unless you have built libpng with + * PNG_WRITE_FLUSH_SUPPORTED undefined, because in this case libpng's + * default flush function, which uses the standard *FILE structure, will + * be used. + */ +extern PNG_EXPORT(void,png_set_write_fn) PNGARG((png_structp png_ptr, + png_voidp io_ptr, png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)); + +/* Replace the default data input function with a user supplied one. */ +extern PNG_EXPORT(void,png_set_read_fn) PNGARG((png_structp png_ptr, + png_voidp io_ptr, png_rw_ptr read_data_fn)); + +/* Return the user pointer associated with the I/O functions */ +extern PNG_EXPORT(png_voidp,png_get_io_ptr) PNGARG((png_structp png_ptr)); + +extern PNG_EXPORT(void,png_set_read_status_fn) PNGARG((png_structp png_ptr, + png_read_status_ptr read_row_fn)); + +extern PNG_EXPORT(void,png_set_write_status_fn) PNGARG((png_structp png_ptr, + png_write_status_ptr write_row_fn)); + +#ifdef PNG_USER_MEM_SUPPORTED +/* Replace the default memory allocation functions with user supplied one(s). */ +extern PNG_EXPORT(void,png_set_mem_fn) PNGARG((png_structp png_ptr, + png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn)); +/* Return the user pointer associated with the memory functions */ +extern PNG_EXPORT(png_voidp,png_get_mem_ptr) PNGARG((png_structp png_ptr)); +#endif + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED +extern PNG_EXPORT(void,png_set_read_user_transform_fn) PNGARG((png_structp + png_ptr, png_user_transform_ptr read_user_transform_fn)); +#endif + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED +extern PNG_EXPORT(void,png_set_write_user_transform_fn) PNGARG((png_structp + png_ptr, png_user_transform_ptr write_user_transform_fn)); +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +extern PNG_EXPORT(void,png_set_user_transform_info) PNGARG((png_structp + png_ptr, png_voidp user_transform_ptr, int user_transform_depth, + int user_transform_channels)); +/* Return the user pointer associated with the user transform functions */ +extern PNG_EXPORT(png_voidp,png_get_user_transform_ptr) + PNGARG((png_structp png_ptr)); +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +extern PNG_EXPORT(void,png_set_read_user_chunk_fn) PNGARG((png_structp png_ptr, + png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn)); +extern PNG_EXPORT(png_voidp,png_get_user_chunk_ptr) PNGARG((png_structp + png_ptr)); +#endif + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +/* Sets the function callbacks for the push reader, and a pointer to a + * user-defined structure available to the callback functions. + */ +extern PNG_EXPORT(void,png_set_progressive_read_fn) PNGARG((png_structp png_ptr, + png_voidp progressive_ptr, + png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn, + png_progressive_end_ptr end_fn)); + +/* Returns the user pointer associated with the push read functions */ +extern PNG_EXPORT(png_voidp,png_get_progressive_ptr) + PNGARG((png_structp png_ptr)); + +/* Function to be called when data becomes available */ +extern PNG_EXPORT(void,png_process_data) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_bytep buffer, png_size_t buffer_size)); + +/* Function that combines rows. Not very much different than the + * png_combine_row() call. Is this even used????? + */ +extern PNG_EXPORT(void,png_progressive_combine_row) PNGARG((png_structp png_ptr, + png_bytep old_row, png_bytep new_row)); +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + +extern PNG_EXPORT(png_voidp,png_malloc) PNGARG((png_structp png_ptr, + png_alloc_size_t size)) PNG_ALLOCATED; +/* Added at libpng version 1.4.0 */ +extern PNG_EXPORT(png_voidp,png_calloc) PNGARG((png_structp png_ptr, + png_alloc_size_t size)) PNG_ALLOCATED; + +/* Added at libpng version 1.2.4 */ +extern PNG_EXPORT(png_voidp,png_malloc_warn) PNGARG((png_structp png_ptr, + png_alloc_size_t size)) PNG_ALLOCATED; + +/* Frees a pointer allocated by png_malloc() */ +extern PNG_EXPORT(void,png_free) PNGARG((png_structp png_ptr, png_voidp ptr)); + +/* Free data that was allocated internally */ +extern PNG_EXPORT(void,png_free_data) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 free_me, int num)); +/* Reassign responsibility for freeing existing data, whether allocated + * by libpng or by the application */ +extern PNG_EXPORT(void,png_data_freer) PNGARG((png_structp png_ptr, + png_infop info_ptr, int freer, png_uint_32 mask)); +/* Assignments for png_data_freer */ +#define PNG_DESTROY_WILL_FREE_DATA 1 +#define PNG_SET_WILL_FREE_DATA 1 +#define PNG_USER_WILL_FREE_DATA 2 +/* Flags for png_ptr->free_me and info_ptr->free_me */ +#define PNG_FREE_HIST 0x0008 +#define PNG_FREE_ICCP 0x0010 +#define PNG_FREE_SPLT 0x0020 +#define PNG_FREE_ROWS 0x0040 +#define PNG_FREE_PCAL 0x0080 +#define PNG_FREE_SCAL 0x0100 +#define PNG_FREE_UNKN 0x0200 +#define PNG_FREE_LIST 0x0400 +#define PNG_FREE_PLTE 0x1000 +#define PNG_FREE_TRNS 0x2000 +#define PNG_FREE_TEXT 0x4000 +#define PNG_FREE_ALL 0x7fff +#define PNG_FREE_MUL 0x4220 /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */ + +#ifdef PNG_USER_MEM_SUPPORTED +extern PNG_EXPORT(png_voidp,png_malloc_default) PNGARG((png_structp png_ptr, + png_alloc_size_t size)) PNG_ALLOCATED; +extern PNG_EXPORT(void,png_free_default) PNGARG((png_structp png_ptr, + png_voidp ptr)); +#endif + +#ifndef PNG_NO_ERROR_TEXT +/* Fatal error in PNG image of libpng - can't continue */ +extern PNG_EXPORT(void,png_error) PNGARG((png_structp png_ptr, + png_const_charp error_message)) PNG_NORETURN; + +/* The same, but the chunk name is prepended to the error string. */ +extern PNG_EXPORT(void,png_chunk_error) PNGARG((png_structp png_ptr, + png_const_charp error_message)) PNG_NORETURN; + +#else +/* Fatal error in PNG image of libpng - can't continue */ +extern PNG_EXPORT(void,png_err) PNGARG((png_structp png_ptr)) PNG_NORETURN; +#endif + +/* Non-fatal error in libpng. Can continue, but may have a problem. */ +extern PNG_EXPORT(void,png_warning) PNGARG((png_structp png_ptr, + png_const_charp warning_message)); + +/* Non-fatal error in libpng, chunk name is prepended to message. */ +extern PNG_EXPORT(void,png_chunk_warning) PNGARG((png_structp png_ptr, + png_const_charp warning_message)); + +#ifdef PNG_BENIGN_ERRORS_SUPPORTED +/* Benign error in libpng. Can continue, but may have a problem. + * User can choose whether to handle as a fatal error or as a warning. */ +extern PNG_EXPORT(void,png_benign_error) PNGARG((png_structp png_ptr, + png_const_charp warning_message)); + +/* Same, chunk name is prepended to message. */ +extern PNG_EXPORT(void,png_chunk_benign_error) PNGARG((png_structp png_ptr, + png_const_charp warning_message)); + +extern PNG_EXPORT(void,png_set_benign_errors) PNGARG((png_structp + png_ptr, int allowed)); +#endif + +/* The png_set_ functions are for storing values in the png_info_struct. + * Similarly, the png_get_ calls are used to read values from the + * png_info_struct, either storing the parameters in the passed variables, or + * setting pointers into the png_info_struct where the data is stored. The + * png_get_ functions return a non-zero value if the data was available + * in info_ptr, or return zero and do not change any of the parameters if the + * data was not available. + * + * These functions should be used instead of directly accessing png_info + * to avoid problems with future changes in the size and internal layout of + * png_info_struct. + */ +/* Returns "flag" if chunk data is valid in info_ptr. */ +extern PNG_EXPORT(png_uint_32,png_get_valid) PNGARG((png_structp png_ptr, +png_infop info_ptr, png_uint_32 flag)); + +/* Returns number of bytes needed to hold a transformed row. */ +extern PNG_EXPORT(png_size_t,png_get_rowbytes) PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +#ifdef PNG_INFO_IMAGE_SUPPORTED +/* Returns row_pointers, which is an array of pointers to scanlines that was + * returned from png_read_png(). + */ +extern PNG_EXPORT(png_bytepp,png_get_rows) PNGARG((png_structp png_ptr, +png_infop info_ptr)); +/* Set row_pointers, which is an array of pointers to scanlines for use + * by png_write_png(). + */ +extern PNG_EXPORT(void,png_set_rows) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_bytepp row_pointers)); +#endif + +/* Returns number of color channels in image. */ +extern PNG_EXPORT(png_byte,png_get_channels) PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +#ifdef PNG_EASY_ACCESS_SUPPORTED +/* Returns image width in pixels. */ +extern PNG_EXPORT(png_uint_32, png_get_image_width) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image height in pixels. */ +extern PNG_EXPORT(png_uint_32, png_get_image_height) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image bit_depth. */ +extern PNG_EXPORT(png_byte, png_get_bit_depth) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image color_type. */ +extern PNG_EXPORT(png_byte, png_get_color_type) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image filter_type. */ +extern PNG_EXPORT(png_byte, png_get_filter_type) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image interlace_type. */ +extern PNG_EXPORT(png_byte, png_get_interlace_type) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image compression_type. */ +extern PNG_EXPORT(png_byte, png_get_compression_type) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image resolution in pixels per meter, from pHYs chunk data. */ +extern PNG_EXPORT(png_uint_32, png_get_pixels_per_meter) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_uint_32, png_get_x_pixels_per_meter) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_uint_32, png_get_y_pixels_per_meter) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns pixel aspect ratio, computed from pHYs chunk data. */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(float, png_get_pixel_aspect_ratio) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +#endif + +/* Returns image x, y offset in pixels or microns, from oFFs chunk data. */ +extern PNG_EXPORT(png_int_32, png_get_x_offset_pixels) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_int_32, png_get_y_offset_pixels) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_int_32, png_get_x_offset_microns) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_int_32, png_get_y_offset_microns) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +#endif /* PNG_EASY_ACCESS_SUPPORTED */ + +/* Returns pointer to signature string read from PNG header */ +extern PNG_EXPORT(png_bytep,png_get_signature) PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +#ifdef PNG_bKGD_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_bKGD) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_color_16p *background)); +#endif + +#ifdef PNG_bKGD_SUPPORTED +extern PNG_EXPORT(void,png_set_bKGD) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_color_16p background)); +#endif + +#ifdef PNG_cHRM_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_cHRM) PNGARG((png_structp png_ptr, + png_infop info_ptr, double *white_x, double *white_y, double *red_x, + double *red_y, double *green_x, double *green_y, double *blue_x, + double *blue_y)); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_cHRM_fixed) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_fixed_point *int_white_x, png_fixed_point + *int_white_y, png_fixed_point *int_red_x, png_fixed_point *int_red_y, + png_fixed_point *int_green_x, png_fixed_point *int_green_y, png_fixed_point + *int_blue_x, png_fixed_point *int_blue_y)); +#endif +#endif + +#ifdef PNG_cHRM_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_cHRM) PNGARG((png_structp png_ptr, + png_infop info_ptr, double white_x, double white_y, double red_x, + double red_y, double green_x, double green_y, double blue_x, double blue_y)); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_cHRM_fixed) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_fixed_point int_white_x, png_fixed_point int_white_y, + png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point + int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x, + png_fixed_point int_blue_y)); +#endif +#endif + +#ifdef PNG_gAMA_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_gAMA) PNGARG((png_structp png_ptr, + png_infop info_ptr, double *file_gamma)); +#endif +extern PNG_EXPORT(png_uint_32,png_get_gAMA_fixed) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_fixed_point *int_file_gamma)); +#endif + +#ifdef PNG_gAMA_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_gAMA) PNGARG((png_structp png_ptr, + png_infop info_ptr, double file_gamma)); +#endif +extern PNG_EXPORT(void,png_set_gAMA_fixed) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_fixed_point int_file_gamma)); +#endif + +#ifdef PNG_hIST_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_hIST) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_16p *hist)); +#endif + +#ifdef PNG_hIST_SUPPORTED +extern PNG_EXPORT(void,png_set_hIST) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_16p hist)); +#endif + +extern PNG_EXPORT(png_uint_32,png_get_IHDR) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 *width, png_uint_32 *height, + int *bit_depth, int *color_type, int *interlace_method, + int *compression_method, int *filter_method)); + +extern PNG_EXPORT(void,png_set_IHDR) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_method, int compression_method, + int filter_method)); + +#ifdef PNG_oFFs_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_oFFs) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_int_32 *offset_x, png_int_32 *offset_y, + int *unit_type)); +#endif + +#ifdef PNG_oFFs_SUPPORTED +extern PNG_EXPORT(void,png_set_oFFs) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_int_32 offset_x, png_int_32 offset_y, + int unit_type)); +#endif + +#ifdef PNG_pCAL_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_pCAL) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_charp *purpose, png_int_32 *X0, png_int_32 *X1, + int *type, int *nparams, png_charp *units, png_charpp *params)); +#endif + +#ifdef PNG_pCAL_SUPPORTED +extern PNG_EXPORT(void,png_set_pCAL) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_charp purpose, png_int_32 X0, png_int_32 X1, + int type, int nparams, png_charp units, png_charpp params)); +#endif + +#ifdef PNG_pHYs_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_pHYs) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)); +#endif + +#ifdef PNG_pHYs_SUPPORTED +extern PNG_EXPORT(void,png_set_pHYs) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 res_x, png_uint_32 res_y, int unit_type)); +#endif + +extern PNG_EXPORT(png_uint_32,png_get_PLTE) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_colorp *palette, int *num_palette)); + +extern PNG_EXPORT(void,png_set_PLTE) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_colorp palette, int num_palette)); + +#ifdef PNG_sBIT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_sBIT) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_color_8p *sig_bit)); +#endif + +#ifdef PNG_sBIT_SUPPORTED +extern PNG_EXPORT(void,png_set_sBIT) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_color_8p sig_bit)); +#endif + +#ifdef PNG_sRGB_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_sRGB) PNGARG((png_structp png_ptr, + png_infop info_ptr, int *intent)); +#endif + +#ifdef PNG_sRGB_SUPPORTED +extern PNG_EXPORT(void,png_set_sRGB) PNGARG((png_structp png_ptr, + png_infop info_ptr, int intent)); +extern PNG_EXPORT(void,png_set_sRGB_gAMA_and_cHRM) PNGARG((png_structp png_ptr, + png_infop info_ptr, int intent)); +#endif + +#ifdef PNG_iCCP_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_iCCP) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_charpp name, int *compression_type, + png_charpp profile, png_uint_32 *proflen)); + /* Note to maintainer: profile should be png_bytepp */ +#endif + +#ifdef PNG_iCCP_SUPPORTED +extern PNG_EXPORT(void,png_set_iCCP) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_charp name, int compression_type, + png_charp profile, png_uint_32 proflen)); + /* Note to maintainer: profile should be png_bytep */ +#endif + +#ifdef PNG_sPLT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_sPLT) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_sPLT_tpp entries)); +#endif + +#ifdef PNG_sPLT_SUPPORTED +extern PNG_EXPORT(void,png_set_sPLT) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_sPLT_tp entries, int nentries)); +#endif + +#ifdef PNG_TEXT_SUPPORTED +/* png_get_text also returns the number of text chunks in *num_text */ +extern PNG_EXPORT(png_uint_32,png_get_text) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_textp *text_ptr, int *num_text)); +#endif + +/* Note while png_set_text() will accept a structure whose text, + * language, and translated keywords are NULL pointers, the structure + * returned by png_get_text will always contain regular + * zero-terminated C strings. They might be empty strings but + * they will never be NULL pointers. + */ + +#ifdef PNG_TEXT_SUPPORTED +extern PNG_EXPORT(void,png_set_text) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_textp text_ptr, int num_text)); +#endif + +#ifdef PNG_tIME_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_tIME) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_timep *mod_time)); +#endif + +#ifdef PNG_tIME_SUPPORTED +extern PNG_EXPORT(void,png_set_tIME) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_timep mod_time)); +#endif + +#ifdef PNG_tRNS_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_tRNS) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_bytep *trans_alpha, int *num_trans, + png_color_16p *trans_color)); +#endif + +#ifdef PNG_tRNS_SUPPORTED +extern PNG_EXPORT(void,png_set_tRNS) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_bytep trans_alpha, int num_trans, + png_color_16p trans_color)); +#endif + +#ifdef PNG_tRNS_SUPPORTED +#endif + +#ifdef PNG_sCAL_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_sCAL) PNGARG((png_structp png_ptr, + png_infop info_ptr, int *unit, double *width, double *height)); +#else +#ifdef PNG_FIXED_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_sCAL_s) PNGARG((png_structp png_ptr, + png_infop info_ptr, int *unit, png_charpp swidth, png_charpp sheight)); +#endif +#endif +#endif /* PNG_sCAL_SUPPORTED */ + +#ifdef PNG_sCAL_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_sCAL) PNGARG((png_structp png_ptr, + png_infop info_ptr, int unit, double width, double height)); +#else +#ifdef PNG_FIXED_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_sCAL_s) PNGARG((png_structp png_ptr, + png_infop info_ptr, int unit, png_charp swidth, png_charp sheight)); +#endif +#endif +#endif /* PNG_sCAL_SUPPORTED || PNG_WRITE_sCAL_SUPPORTED */ + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +/* Provide a list of chunks and how they are to be handled, if the built-in + handling or default unknown chunk handling is not desired. Any chunks not + listed will be handled in the default manner. The IHDR and IEND chunks + must not be listed. + keep = 0: follow default behaviour + = 1: do not keep + = 2: keep only if safe-to-copy + = 3: keep even if unsafe-to-copy +*/ +extern PNG_EXPORT(void, png_set_keep_unknown_chunks) PNGARG((png_structp + png_ptr, int keep, png_bytep chunk_list, int num_chunks)); +PNG_EXPORT(int,png_handle_as_unknown) PNGARG((png_structp png_ptr, png_bytep + chunk_name)); +#endif +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED +extern PNG_EXPORT(void, png_set_unknown_chunks) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns)); +extern PNG_EXPORT(void, png_set_unknown_chunk_location) + PNGARG((png_structp png_ptr, png_infop info_ptr, int chunk, int location)); +extern PNG_EXPORT(png_uint_32,png_get_unknown_chunks) PNGARG((png_structp + png_ptr, png_infop info_ptr, png_unknown_chunkpp entries)); +#endif + +/* Png_free_data() will turn off the "valid" flag for anything it frees. + * If you need to turn it off for a chunk that your application has freed, + * you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK); + */ +extern PNG_EXPORT(void, png_set_invalid) PNGARG((png_structp png_ptr, + png_infop info_ptr, int mask)); + +#ifdef PNG_INFO_IMAGE_SUPPORTED +/* The "params" pointer is currently not used and is for future expansion. */ +extern PNG_EXPORT(void, png_read_png) PNGARG((png_structp png_ptr, + png_infop info_ptr, + int transforms, + png_voidp params)); +extern PNG_EXPORT(void, png_write_png) PNGARG((png_structp png_ptr, + png_infop info_ptr, + int transforms, + png_voidp params)); +#endif + +extern PNG_EXPORT(png_charp,png_get_copyright) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(png_charp,png_get_header_ver) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(png_charp,png_get_header_version) PNGARG((png_structp + png_ptr)); +extern PNG_EXPORT(png_charp,png_get_libpng_ver) PNGARG((png_structp png_ptr)); + +#ifdef PNG_MNG_FEATURES_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_permit_mng_features) PNGARG((png_structp + png_ptr, png_uint_32 mng_features_permitted)); +#endif + +/* For use in png_set_keep_unknown, added to version 1.2.6 */ +#define PNG_HANDLE_CHUNK_AS_DEFAULT 0 +#define PNG_HANDLE_CHUNK_NEVER 1 +#define PNG_HANDLE_CHUNK_IF_SAFE 2 +#define PNG_HANDLE_CHUNK_ALWAYS 3 + +/* Strip the prepended error numbers ("#nnn ") from error and warning + * messages before passing them to the error or warning handler. + */ +#ifdef PNG_ERROR_NUMBERS_SUPPORTED +extern PNG_EXPORT(void,png_set_strip_error_numbers) PNGARG((png_structp + png_ptr, png_uint_32 strip_mode)); +#endif + +/* Added in libpng-1.2.6 */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +extern PNG_EXPORT(void,png_set_user_limits) PNGARG((png_structp + png_ptr, png_uint_32 user_width_max, png_uint_32 user_height_max)); +extern PNG_EXPORT(png_uint_32,png_get_user_width_max) PNGARG((png_structp + png_ptr)); +extern PNG_EXPORT(png_uint_32,png_get_user_height_max) PNGARG((png_structp + png_ptr)); +/* Added in libpng-1.4.0 */ +extern PNG_EXPORT(void,png_set_chunk_cache_max) PNGARG((png_structp + png_ptr, png_uint_32 user_chunk_cache_max)); +extern PNG_EXPORT(png_uint_32,png_get_chunk_cache_max) + PNGARG((png_structp png_ptr)); +/* Added in libpng-1.4.1 */ +extern PNG_EXPORT(void,png_set_chunk_malloc_max) PNGARG((png_structp + png_ptr, png_alloc_size_t user_chunk_cache_max)); +extern PNG_EXPORT(png_alloc_size_t,png_get_chunk_malloc_max) + PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_INCH_CONVERSIONS) && defined(PNG_FLOATING_POINT_SUPPORTED) +PNG_EXPORT(png_uint_32,png_get_pixels_per_inch) PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +PNG_EXPORT(png_uint_32,png_get_x_pixels_per_inch) PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +PNG_EXPORT(png_uint_32,png_get_y_pixels_per_inch) PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +PNG_EXPORT(float,png_get_x_offset_inches) PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +PNG_EXPORT(float,png_get_y_offset_inches) PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +#ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(png_uint_32,png_get_pHYs_dpi) PNGARG((png_structp png_ptr, +png_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)); +#endif /* PNG_pHYs_SUPPORTED */ +#endif /* PNG_INCH_CONVERSIONS && PNG_FLOATING_POINT_SUPPORTED */ + +/* Added in libpng-1.4.0 */ +#ifdef PNG_IO_STATE_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_io_state) PNGARG((png_structp png_ptr)); + +extern PNG_EXPORT(png_bytep,png_get_io_chunk_name) + PNGARG((png_structp png_ptr)); + +/* The flags returned by png_get_io_state() are the following: */ +#define PNG_IO_NONE 0x0000 /* no I/O at this moment */ +#define PNG_IO_READING 0x0001 /* currently reading */ +#define PNG_IO_WRITING 0x0002 /* currently writing */ +#define PNG_IO_SIGNATURE 0x0010 /* currently at the file signature */ +#define PNG_IO_CHUNK_HDR 0x0020 /* currently at the chunk header */ +#define PNG_IO_CHUNK_DATA 0x0040 /* currently at the chunk data */ +#define PNG_IO_CHUNK_CRC 0x0080 /* currently at the chunk crc */ +#define PNG_IO_MASK_OP 0x000f /* current operation: reading/writing */ +#define PNG_IO_MASK_LOC 0x00f0 /* current location: sig/hdr/data/crc */ +#endif /* ?PNG_IO_STATE_SUPPORTED */ + +/* Maintainer: Put new public prototypes here ^, in libpng.3, and project + * defs + */ + +#ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED +/* With these routines we avoid an integer divide, which will be slower on + * most machines. However, it does take more operations than the corresponding + * divide method, so it may be slower on a few RISC systems. There are two + * shifts (by 8 or 16 bits) and an addition, versus a single integer divide. + * + * Note that the rounding factors are NOT supposed to be the same! 128 and + * 32768 are correct for the NODIV code; 127 and 32767 are correct for the + * standard method. + * + * [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ] + */ + + /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */ + +# define png_composite(composite, fg, alpha, bg) \ + { png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) \ + * (png_uint_16)(alpha) \ + + (png_uint_16)(bg)*(png_uint_16)(255 \ + - (png_uint_16)(alpha)) + (png_uint_16)128); \ + (composite) = (png_byte)((temp + (temp >> 8)) >> 8); } + +# define png_composite_16(composite, fg, alpha, bg) \ + { png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) \ + * (png_uint_32)(alpha) \ + + (png_uint_32)(bg)*(png_uint_32)(65535L \ + - (png_uint_32)(alpha)) + (png_uint_32)32768L); \ + (composite) = (png_uint_16)((temp + (temp >> 16)) >> 16); } + +#else /* Standard method using integer division */ + +# define png_composite(composite, fg, alpha, bg) \ + (composite) = (png_byte)(((png_uint_16)(fg) * (png_uint_16)(alpha) + \ + (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \ + (png_uint_16)127) / 255) + +# define png_composite_16(composite, fg, alpha, bg) \ + (composite) = (png_uint_16)(((png_uint_32)(fg) * (png_uint_32)(alpha) + \ + (png_uint_32)(bg)*(png_uint_32)(65535L - (png_uint_32)(alpha)) + \ + (png_uint_32)32767) / (png_uint_32)65535L) +#endif /* PNG_READ_COMPOSITE_NODIV_SUPPORTED */ + +#ifdef PNG_USE_READ_MACROS +/* Inline macros to do direct reads of bytes from the input buffer. + * The png_get_int_32() routine assumes we are using two's complement + * format for negative values, which is almost certainly true. + */ +/* We could make special-case BIG_ENDIAN macros that do direct reads here */ +# define png_get_uint_32(buf) \ + (((png_uint_32)(*(buf)) << 24) + \ + ((png_uint_32)(*((buf) + 1)) << 16) + \ + ((png_uint_32)(*((buf) + 2)) << 8) + \ + ((png_uint_32)(*((buf) + 3)))) +# define png_get_uint_16(buf) \ + (((png_uint_32)(*(buf)) << 8) + \ + ((png_uint_32)(*((buf) + 1)))) +#ifdef PNG_GET_INT_32_SUPPORTED +# define png_get_int_32(buf) \ + (((png_int_32)(*(buf)) << 24) + \ + ((png_int_32)(*((buf) + 1)) << 16) + \ + ((png_int_32)(*((buf) + 2)) << 8) + \ + ((png_int_32)(*((buf) + 3)))) +#endif +#else +extern PNG_EXPORT(png_uint_32,png_get_uint_32) PNGARG((png_bytep buf)); +extern PNG_EXPORT(png_uint_16,png_get_uint_16) PNGARG((png_bytep buf)); +#ifdef PNG_GET_INT_32_SUPPORTED +extern PNG_EXPORT(png_int_32,png_get_int_32) PNGARG((png_bytep buf)); +#endif +#endif +extern PNG_EXPORT(png_uint_32,png_get_uint_31) + PNGARG((png_structp png_ptr, png_bytep buf)); +/* No png_get_int_16 -- may be added if there's a real need for it. */ + +/* Place a 32-bit number into a buffer in PNG byte order (big-endian). */ +extern PNG_EXPORT(void,png_save_uint_32) + PNGARG((png_bytep buf, png_uint_32 i)); +extern PNG_EXPORT(void,png_save_int_32) + PNGARG((png_bytep buf, png_int_32 i)); + +/* Place a 16-bit number into a buffer in PNG byte order. + * The parameter is declared unsigned int, not png_uint_16, + * just to avoid potential problems on pre-ANSI C compilers. + */ +extern PNG_EXPORT(void,png_save_uint_16) + PNGARG((png_bytep buf, unsigned int i)); +/* No png_save_int_16 -- may be added if there's a real need for it. */ + +/* ************************************************************************* */ + +/* Various modes of operation. Note that after an init, mode is set to + * zero automatically when the structure is created. + */ +#define PNG_HAVE_IHDR 0x01 +#define PNG_HAVE_PLTE 0x02 +#define PNG_HAVE_IDAT 0x04 +#define PNG_AFTER_IDAT 0x08 /* Have complete zlib datastream */ +#define PNG_HAVE_IEND 0x10 +#define PNG_HAVE_gAMA 0x20 +#define PNG_HAVE_cHRM 0x40 + +#ifdef __cplusplus +} +#endif + +#endif /* PNG_VERSION_INFO_ONLY */ +/* Do not put anything past this line */ +#endif /* PNG_H */ diff --git a/reactos/dll/3rdparty/libpng/pngconf.h b/reactos/dll/3rdparty/libpng/pngconf.h new file mode 100644 index 00000000000..0c1065cfb47 --- /dev/null +++ b/reactos/dll/3rdparty/libpng/pngconf.h @@ -0,0 +1,1525 @@ + +/* pngconf.h - machine configurable file for libpng + * + * libpng version 1.4.3 - June 26, 2010 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2010 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + */ + +/* Any machine specific code is near the front of this file, so if you + * are configuring libpng for a machine, you may want to read the section + * starting here down to where it starts to typedef png_color, png_text, + * and png_info. + */ + +#ifndef PNGCONF_H +#define PNGCONF_H + +#ifndef PNG_NO_LIMITS_H +# include +#endif + +/* Added at libpng-1.2.9 */ + +/* config.h is created by and PNG_CONFIGURE_LIBPNG is set by the "configure" + * script. + */ +#ifdef PNG_CONFIGURE_LIBPNG +# ifdef HAVE_CONFIG_H +# include "config.h" +# endif +#endif + +/* + * Added at libpng-1.2.8 + * + * PNG_USER_CONFIG has to be defined on the compiler command line. This + * includes the resource compiler for Windows DLL configurations. + */ +#ifdef PNG_USER_CONFIG +# ifndef PNG_USER_PRIVATEBUILD +# define PNG_USER_PRIVATEBUILD +# endif +# include "pngusr.h" +#endif + +/* + * If you create a private DLL you need to define in "pngusr.h" the followings: + * #define PNG_USER_PRIVATEBUILD + * e.g. #define PNG_USER_PRIVATEBUILD "Build by MyCompany for xyz reasons." + * #define PNG_USER_DLLFNAME_POSTFIX + * e.g. // private DLL "libpng13gx.dll" + * #define PNG_USER_DLLFNAME_POSTFIX "gx" + * + * The following macros are also at your disposal if you want to complete the + * DLL VERSIONINFO structure. + * - PNG_USER_VERSIONINFO_COMMENTS + * - PNG_USER_VERSIONINFO_COMPANYNAME + * - PNG_USER_VERSIONINFO_LEGALTRADEMARKS + */ + +#ifdef __STDC__ +# ifdef SPECIALBUILD +# pragma message("PNG_LIBPNG_SPECIALBUILD (and deprecated SPECIALBUILD)\ + are now LIBPNG reserved macros. Use PNG_USER_PRIVATEBUILD instead.") +# endif + +# ifdef PRIVATEBUILD +# pragma message("PRIVATEBUILD is deprecated.\ + Use PNG_USER_PRIVATEBUILD instead.") +# define PNG_USER_PRIVATEBUILD PRIVATEBUILD +# endif +#endif /* __STDC__ */ + +/* End of material added to libpng-1.2.8 */ + +#ifndef PNG_VERSION_INFO_ONLY + +/* This is the size of the compression buffer, and thus the size of + * an IDAT chunk. Make this whatever size you feel is best for your + * machine. One of these will be allocated per png_struct. When this + * is full, it writes the data to the disk, and does some other + * calculations. Making this an extremely small size will slow + * the library down, but you may want to experiment to determine + * where it becomes significant, if you are concerned with memory + * usage. Note that zlib allocates at least 32Kb also. For readers, + * this describes the size of the buffer available to read the data in. + * Unless this gets smaller than the size of a row (compressed), + * it should not make much difference how big this is. + */ + +#ifndef PNG_ZBUF_SIZE +# define PNG_ZBUF_SIZE 8192 +#endif + +/* Enable if you want a write-only libpng */ + +#ifndef PNG_NO_READ_SUPPORTED +# define PNG_READ_SUPPORTED +#endif + +/* Enable if you want a read-only libpng */ + +#ifndef PNG_NO_WRITE_SUPPORTED +# define PNG_WRITE_SUPPORTED +#endif + +/* Enabled in 1.4.0. */ +#ifdef PNG_ALLOW_BENIGN_ERRORS +# define png_benign_error png_warning +# define png_chunk_benign_error png_chunk_warning +#else +# ifndef PNG_BENIGN_ERRORS_SUPPORTED +# define png_benign_error png_error +# define png_chunk_benign_error png_chunk_error +# endif +#endif + +/* Added at libpng version 1.4.0 */ +#if !defined(PNG_NO_WARNINGS) && !defined(PNG_WARNINGS_SUPPORTED) +# define PNG_WARNINGS_SUPPORTED +#endif + +/* Added at libpng version 1.4.0 */ +#if !defined(PNG_NO_ERROR_TEXT) && !defined(PNG_ERROR_TEXT_SUPPORTED) +# define PNG_ERROR_TEXT_SUPPORTED +#endif + +/* Added at libpng version 1.4.0 */ +#if !defined(PNG_NO_CHECK_cHRM) && !defined(PNG_CHECK_cHRM_SUPPORTED) +# define PNG_CHECK_cHRM_SUPPORTED +#endif + +/* Added at libpng version 1.4.0 */ +#if !defined(PNG_NO_ALIGNED_MEMORY) && !defined(PNG_ALIGNED_MEMORY_SUPPORTED) +# define PNG_ALIGNED_MEMORY_SUPPORTED +#endif + +/* Enabled by default in 1.2.0. You can disable this if you don't need to + support PNGs that are embedded in MNG datastreams */ +#ifndef PNG_NO_MNG_FEATURES +# ifndef PNG_MNG_FEATURES_SUPPORTED +# define PNG_MNG_FEATURES_SUPPORTED +# endif +#endif + +/* Added at libpng version 1.4.0 */ +#ifndef PNG_NO_FLOATING_POINT_SUPPORTED +# ifndef PNG_FLOATING_POINT_SUPPORTED +# define PNG_FLOATING_POINT_SUPPORTED +# endif +#endif + +/* Added at libpng-1.4.0beta49 for testing (this test is no longer used + in libpng and png_calloc() is always present) + */ +#define PNG_CALLOC_SUPPORTED + +/* If you are running on a machine where you cannot allocate more + * than 64K of memory at once, uncomment this. While libpng will not + * normally need that much memory in a chunk (unless you load up a very + * large file), zlib needs to know how big of a chunk it can use, and + * libpng thus makes sure to check any memory allocation to verify it + * will fit into memory. +#define PNG_MAX_MALLOC_64K + */ +#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K) +# define PNG_MAX_MALLOC_64K +#endif + +/* Special munging to support doing things the 'cygwin' way: + * 'Normal' png-on-win32 defines/defaults: + * PNG_BUILD_DLL -- building dll + * PNG_USE_DLL -- building an application, linking to dll + * (no define) -- building static library, or building an + * application and linking to the static lib + * 'Cygwin' defines/defaults: + * PNG_BUILD_DLL -- (ignored) building the dll + * (no define) -- (ignored) building an application, linking to the dll + * PNG_STATIC -- (ignored) building the static lib, or building an + * application that links to the static lib. + * ALL_STATIC -- (ignored) building various static libs, or building an + * application that links to the static libs. + * Thus, + * a cygwin user should define either PNG_BUILD_DLL or PNG_STATIC, and + * this bit of #ifdefs will define the 'correct' config variables based on + * that. If a cygwin user *wants* to define 'PNG_USE_DLL' that's okay, but + * unnecessary. + * + * Also, the precedence order is: + * ALL_STATIC (since we can't #undef something outside our namespace) + * PNG_BUILD_DLL + * PNG_STATIC + * (nothing) == PNG_USE_DLL + * + * CYGWIN (2002-01-20): The preceding is now obsolete. With the advent + * of auto-import in binutils, we no longer need to worry about + * __declspec(dllexport) / __declspec(dllimport) and friends. Therefore, + * we don't need to worry about PNG_STATIC or ALL_STATIC when it comes + * to __declspec() stuff. However, we DO need to worry about + * PNG_BUILD_DLL and PNG_STATIC because those change some defaults + * such as CONSOLE_IO. + */ +#ifdef __CYGWIN__ +# ifdef ALL_STATIC +# ifdef PNG_BUILD_DLL +# undef PNG_BUILD_DLL +# endif +# ifdef PNG_USE_DLL +# undef PNG_USE_DLL +# endif +# ifdef PNG_DLL +# undef PNG_DLL +# endif +# ifndef PNG_STATIC +# define PNG_STATIC +# endif +# else +# ifdef PNG_BUILD_DLL +# ifdef PNG_STATIC +# undef PNG_STATIC +# endif +# ifdef PNG_USE_DLL +# undef PNG_USE_DLL +# endif +# ifndef PNG_DLL +# define PNG_DLL +# endif +# else +# ifdef PNG_STATIC +# ifdef PNG_USE_DLL +# undef PNG_USE_DLL +# endif +# ifdef PNG_DLL +# undef PNG_DLL +# endif +# else +# ifndef PNG_USE_DLL +# define PNG_USE_DLL +# endif +# ifndef PNG_DLL +# define PNG_DLL +# endif +# endif +# endif +# endif +#endif + +/* This protects us against compilers that run on a windowing system + * and thus don't have or would rather us not use the stdio types: + * stdin, stdout, and stderr. The only one currently used is stderr + * in png_error() and png_warning(). #defining PNG_NO_CONSOLE_IO will + * prevent these from being compiled and used. #defining PNG_NO_STDIO + * will also prevent these, plus will prevent the entire set of stdio + * macros and functions (FILE *, printf, etc.) from being compiled and used, + * unless (PNG_DEBUG > 0) has been #defined. + * + * #define PNG_NO_CONSOLE_IO + * #define PNG_NO_STDIO + */ + +#if !defined(PNG_NO_STDIO) && !defined(PNG_STDIO_SUPPORTED) +# define PNG_STDIO_SUPPORTED +#endif + + +#ifdef PNG_BUILD_DLL +# if !defined(PNG_CONSOLE_IO_SUPPORTED) && !defined(PNG_NO_CONSOLE_IO) +# define PNG_NO_CONSOLE_IO +# endif +#endif + +# ifdef PNG_NO_STDIO +# ifndef PNG_NO_CONSOLE_IO +# define PNG_NO_CONSOLE_IO +# endif +# ifdef PNG_DEBUG +# if (PNG_DEBUG > 0) +# include +# endif +# endif +# else +# include +# endif + +#if !(defined PNG_NO_CONSOLE_IO) && !defined(PNG_CONSOLE_IO_SUPPORTED) +# define PNG_CONSOLE_IO_SUPPORTED +#endif + +/* This macro protects us against machines that don't have function + * prototypes (ie K&R style headers). If your compiler does not handle + * function prototypes, define this macro and use the included ansi2knr. + * I've always been able to use _NO_PROTO as the indicator, but you may + * need to drag the empty declaration out in front of here, or change the + * ifdef to suit your own needs. + */ +#ifndef PNGARG + +#ifdef OF /* zlib prototype munger */ +# define PNGARG(arglist) OF(arglist) +#else + +#ifdef _NO_PROTO +# define PNGARG(arglist) () +#else +# define PNGARG(arglist) arglist +#endif /* _NO_PROTO */ + +#endif /* OF */ + +#endif /* PNGARG */ + +/* Try to determine if we are compiling on a Mac. Note that testing for + * just __MWERKS__ is not good enough, because the Codewarrior is now used + * on non-Mac platforms. + */ +#ifndef MACOS +# if (defined(__MWERKS__) && defined(macintosh)) || defined(applec) || \ + defined(THINK_C) || defined(__SC__) || defined(TARGET_OS_MAC) +# define MACOS +# endif +#endif + +/* Enough people need this for various reasons to include it here */ +#if !defined(MACOS) && !defined(RISCOS) +# include +#endif + +/* PNG_SETJMP_NOT_SUPPORTED and PNG_NO_SETJMP_SUPPORTED are deprecated. */ +#if !defined(PNG_NO_SETJMP) && \ + !defined(PNG_SETJMP_NOT_SUPPORTED) && !defined(PNG_NO_SETJMP_SUPPORTED) +# define PNG_SETJMP_SUPPORTED +#endif + +#ifdef PNG_SETJMP_SUPPORTED +/* This is an attempt to force a single setjmp behaviour on Linux. If + * the X config stuff didn't define _BSD_SOURCE we wouldn't need this. + * + * You can bypass this test if you know that your application uses exactly + * the same setjmp.h that was included when libpng was built. Only define + * PNG_SKIP_SETJMP_CHECK while building your application, prior to the + * application's '#include "png.h"'. Don't define PNG_SKIP_SETJMP_CHECK + * while building a separate libpng library for general use. + */ + +# ifndef PNG_SKIP_SETJMP_CHECK +# ifdef __linux__ +# ifdef _BSD_SOURCE +# define PNG_SAVE_BSD_SOURCE +# undef _BSD_SOURCE +# endif +# ifdef _SETJMP_H + /* If you encounter a compiler error here, see the explanation + * near the end of INSTALL. + */ + __pngconf.h__ in libpng already includes setjmp.h; + __dont__ include it again.; +# endif +# endif /* __linux__ */ +# endif /* PNG_SKIP_SETJMP_CHECK */ + + /* Include setjmp.h for error handling */ +# include + +# ifdef __linux__ +# ifdef PNG_SAVE_BSD_SOURCE +# ifdef _BSD_SOURCE +# undef _BSD_SOURCE +# endif +# define _BSD_SOURCE +# undef PNG_SAVE_BSD_SOURCE +# endif +# endif /* __linux__ */ +#endif /* PNG_SETJMP_SUPPORTED */ + +#ifdef BSD +# include +#else +# include +#endif + +/* Other defines for things like memory and the like can go here. */ + +/* This controls how fine the quantizing gets. As this allocates + * a largish chunk of memory (32K), those who are not as concerned + * with quantizing quality can decrease some or all of these. + */ + +/* Prior to libpng-1.4.2, these were PNG_DITHER_*_BITS + * These migration aids will be removed from libpng-1.5.0. + */ +#ifdef PNG_DITHER_RED_BITS +# define PNG_QUANTIZE_RED_BITS PNG_DITHER_RED_BITS +#endif +#ifdef PNG_DITHER_GREEN_BITS +# define PNG_QUANTIZE_GREEN_BITS PNG_DITHER_GREEN_BITS +#endif +#ifdef PNG_DITHER_BLUE_BITS +# define PNG_QUANTIZE_BLUE_BITS PNG_DITHER_BLUE_BITS +#endif + +#ifndef PNG_QUANTIZE_RED_BITS +# define PNG_QUANTIZE_RED_BITS 5 +#endif +#ifndef PNG_QUANTIZE_GREEN_BITS +# define PNG_QUANTIZE_GREEN_BITS 5 +#endif +#ifndef PNG_QUANTIZE_BLUE_BITS +# define PNG_QUANTIZE_BLUE_BITS 5 +#endif + +/* This controls how fine the gamma correction becomes when you + * are only interested in 8 bits anyway. Increasing this value + * results in more memory being used, and more pow() functions + * being called to fill in the gamma tables. Don't set this value + * less then 8, and even that may not work (I haven't tested it). + */ + +#ifndef PNG_MAX_GAMMA_8 +# define PNG_MAX_GAMMA_8 11 +#endif + +/* This controls how much a difference in gamma we can tolerate before + * we actually start doing gamma conversion. + */ +#ifndef PNG_GAMMA_THRESHOLD +# define PNG_GAMMA_THRESHOLD 0.05 +#endif + +/* The following uses const char * instead of char * for error + * and warning message functions, so some compilers won't complain. + * If you do not want to use const, define PNG_NO_CONST here. + */ + +#ifndef PNG_CONST +# ifndef PNG_NO_CONST +# define PNG_CONST const +# else +# define PNG_CONST +# endif +#endif + +/* The following defines give you the ability to remove code from the + * library that you will not be using. I wish I could figure out how to + * automate this, but I can't do that without making it seriously hard + * on the users. So if you are not using an ability, change the #define + * to and #undef, and that part of the library will not be compiled. If + * your linker can't find a function, you may want to make sure the + * ability is defined here. Some of these depend upon some others being + * defined. I haven't figured out all the interactions here, so you may + * have to experiment awhile to get everything to compile. If you are + * creating or using a shared library, you probably shouldn't touch this, + * as it will affect the size of the structures, and this will cause bad + * things to happen if the library and/or application ever change. + */ + +/* Any features you will not be using can be undef'ed here */ + +/* GR-P, 0.96a: Set "*TRANSFORMS_SUPPORTED as default but allow user + * to turn it off with PNG_NO_READ|WRITE_TRANSFORMS on the compile line, + * then pick and choose which ones to define without having to edit this + * file. It is safe to use the PNG_NO_READ|WRITE_TRANSFORMS + * if you only want to have a png-compliant reader/writer but don't need + * any of the extra transformations. This saves about 80 kbytes in a + * typical installation of the library. (PNG_NO_* form added in version + * 1.0.1c, for consistency; PNG_*_TRANSFORMS_NOT_SUPPORTED deprecated in + * 1.4.0) + */ + +/* Ignore attempt to turn off both floating and fixed point support */ +#if !defined(PNG_FLOATING_POINT_SUPPORTED) || \ + !defined(PNG_NO_FIXED_POINT_SUPPORTED) +# define PNG_FIXED_POINT_SUPPORTED +#endif + +#ifdef PNG_READ_SUPPORTED + +/* PNG_READ_TRANSFORMS_NOT_SUPPORTED is deprecated. */ +#if !defined(PNG_READ_TRANSFORMS_NOT_SUPPORTED) && \ + !defined(PNG_NO_READ_TRANSFORMS) +# define PNG_READ_TRANSFORMS_SUPPORTED +#endif + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED +# ifndef PNG_NO_READ_EXPAND +# define PNG_READ_EXPAND_SUPPORTED +# endif +# ifndef PNG_NO_READ_SHIFT +# define PNG_READ_SHIFT_SUPPORTED +# endif +# ifndef PNG_NO_READ_PACK +# define PNG_READ_PACK_SUPPORTED +# endif +# ifndef PNG_NO_READ_BGR +# define PNG_READ_BGR_SUPPORTED +# endif +# ifndef PNG_NO_READ_SWAP +# define PNG_READ_SWAP_SUPPORTED +# endif +# ifndef PNG_NO_READ_PACKSWAP +# define PNG_READ_PACKSWAP_SUPPORTED +# endif +# ifndef PNG_NO_READ_INVERT +# define PNG_READ_INVERT_SUPPORTED +# endif +# ifndef PNG_NO_READ_QUANTIZE + /* Prior to libpng-1.4.0 this was PNG_READ_DITHER_SUPPORTED */ +# ifndef PNG_NO_READ_DITHER /* This migration aid will be removed */ +# define PNG_READ_QUANTIZE_SUPPORTED +# endif +# endif +# ifndef PNG_NO_READ_BACKGROUND +# define PNG_READ_BACKGROUND_SUPPORTED +# endif +# ifndef PNG_NO_READ_16_TO_8 +# define PNG_READ_16_TO_8_SUPPORTED +# endif +# ifndef PNG_NO_READ_FILLER +# define PNG_READ_FILLER_SUPPORTED +# endif +# ifndef PNG_NO_READ_GAMMA +# define PNG_READ_GAMMA_SUPPORTED +# endif +# ifndef PNG_NO_READ_GRAY_TO_RGB +# define PNG_READ_GRAY_TO_RGB_SUPPORTED +# endif +# ifndef PNG_NO_READ_SWAP_ALPHA +# define PNG_READ_SWAP_ALPHA_SUPPORTED +# endif +# ifndef PNG_NO_READ_INVERT_ALPHA +# define PNG_READ_INVERT_ALPHA_SUPPORTED +# endif +# ifndef PNG_NO_READ_STRIP_ALPHA +# define PNG_READ_STRIP_ALPHA_SUPPORTED +# endif +# ifndef PNG_NO_READ_USER_TRANSFORM +# define PNG_READ_USER_TRANSFORM_SUPPORTED +# endif +# ifndef PNG_NO_READ_RGB_TO_GRAY +# define PNG_READ_RGB_TO_GRAY_SUPPORTED +# endif +#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ + +/* PNG_PROGRESSIVE_READ_NOT_SUPPORTED is deprecated. */ +#if !defined(PNG_NO_PROGRESSIVE_READ) && \ + !defined(PNG_PROGRESSIVE_READ_NOT_SUPPORTED) /* if you don't do progressive */ +# define PNG_PROGRESSIVE_READ_SUPPORTED /* reading. This is not talking */ +#endif /* about interlacing capability! You'll */ + /* still have interlacing unless you change the following define: */ + +#define PNG_READ_INTERLACING_SUPPORTED /* required for PNG-compliant decoders */ + +/* PNG_NO_SEQUENTIAL_READ_SUPPORTED is deprecated. */ +#if !defined(PNG_NO_SEQUENTIAL_READ) && \ + !defined(PNG_SEQUENTIAL_READ_SUPPORTED) && \ + !defined(PNG_NO_SEQUENTIAL_READ_SUPPORTED) +# define PNG_SEQUENTIAL_READ_SUPPORTED +#endif + +#ifndef PNG_NO_READ_COMPOSITE_NODIV +# ifndef PNG_NO_READ_COMPOSITED_NODIV /* libpng-1.0.x misspelling */ +# define PNG_READ_COMPOSITE_NODIV_SUPPORTED /* well tested on Intel, SGI */ +# endif +#endif + +#if !defined(PNG_NO_GET_INT_32) || defined(PNG_READ_oFFS_SUPPORTED) || \ + defined(PNG_READ_pCAL_SUPPORTED) +# ifndef PNG_GET_INT_32_SUPPORTED +# define PNG_GET_INT_32_SUPPORTED +# endif +#endif + +#endif /* PNG_READ_SUPPORTED */ + +#ifdef PNG_WRITE_SUPPORTED + +/* PNG_WRITE_TRANSFORMS_NOT_SUPPORTED is deprecated. */ +#if !defined(PNG_WRITE_TRANSFORMS_NOT_SUPPORTED) && \ + !defined(PNG_NO_WRITE_TRANSFORMS) +# define PNG_WRITE_TRANSFORMS_SUPPORTED +#endif + +#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED +# ifndef PNG_NO_WRITE_SHIFT +# define PNG_WRITE_SHIFT_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_PACK +# define PNG_WRITE_PACK_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_BGR +# define PNG_WRITE_BGR_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_SWAP +# define PNG_WRITE_SWAP_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_PACKSWAP +# define PNG_WRITE_PACKSWAP_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_INVERT +# define PNG_WRITE_INVERT_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_FILLER +# define PNG_WRITE_FILLER_SUPPORTED /* same as WRITE_STRIP_ALPHA */ +# endif +# ifndef PNG_NO_WRITE_SWAP_ALPHA +# define PNG_WRITE_SWAP_ALPHA_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_INVERT_ALPHA +# define PNG_WRITE_INVERT_ALPHA_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_USER_TRANSFORM +# define PNG_WRITE_USER_TRANSFORM_SUPPORTED +# endif +#endif /* PNG_WRITE_TRANSFORMS_SUPPORTED */ + +#if !defined(PNG_NO_WRITE_INTERLACING_SUPPORTED) && \ + !defined(PNG_WRITE_INTERLACING_SUPPORTED) + /* This is not required for PNG-compliant encoders, but can cause + * trouble if left undefined + */ +# define PNG_WRITE_INTERLACING_SUPPORTED +#endif + +#if !defined(PNG_NO_WRITE_WEIGHTED_FILTER) && \ + !defined(PNG_WRITE_WEIGHTED_FILTER) && \ + defined(PNG_FLOATING_POINT_SUPPORTED) +# define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED +#endif + +#ifndef PNG_NO_WRITE_FLUSH +# define PNG_WRITE_FLUSH_SUPPORTED +#endif + +#if !defined(PNG_NO_SAVE_INT_32) || defined(PNG_WRITE_oFFS_SUPPORTED) || \ + defined(PNG_WRITE_pCAL_SUPPORTED) +# ifndef PNG_SAVE_INT_32_SUPPORTED +# define PNG_SAVE_INT_32_SUPPORTED +# endif +#endif + +#endif /* PNG_WRITE_SUPPORTED */ + +#define PNG_NO_ERROR_NUMBERS + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +# ifndef PNG_NO_USER_TRANSFORM_PTR +# define PNG_USER_TRANSFORM_PTR_SUPPORTED +# endif +#endif + +#if defined(PNG_STDIO_SUPPORTED) && !defined(PNG_TIME_RFC1123_SUPPORTED) +# define PNG_TIME_RFC1123_SUPPORTED +#endif + +/* This adds extra functions in pngget.c for accessing data from the + * info pointer (added in version 0.99) + * png_get_image_width() + * png_get_image_height() + * png_get_bit_depth() + * png_get_color_type() + * png_get_compression_type() + * png_get_filter_type() + * png_get_interlace_type() + * png_get_pixel_aspect_ratio() + * png_get_pixels_per_meter() + * png_get_x_offset_pixels() + * png_get_y_offset_pixels() + * png_get_x_offset_microns() + * png_get_y_offset_microns() + */ +#if !defined(PNG_NO_EASY_ACCESS) && !defined(PNG_EASY_ACCESS_SUPPORTED) +# define PNG_EASY_ACCESS_SUPPORTED +#endif + +/* Added at libpng-1.2.0 */ +#if !defined(PNG_NO_USER_MEM) && !defined(PNG_USER_MEM_SUPPORTED) +# define PNG_USER_MEM_SUPPORTED +#endif + +/* Added at libpng-1.2.6 */ +#ifndef PNG_NO_SET_USER_LIMITS +# ifndef PNG_SET_USER_LIMITS_SUPPORTED +# define PNG_SET_USER_LIMITS_SUPPORTED +# endif + /* Feature added at libpng-1.4.0, this flag added at 1.4.1 */ +# ifndef PNG_SET_CHUNK_CACHE_LIMIT_SUPPORTED +# define PNG_SET_CHUNK_CACHE_LIMIT_SUPPORTED +# endif + /* Feature added at libpng-1.4.1, this flag added at 1.4.1 */ +# ifndef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED +# define PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED +# endif +#endif + +/* Added at libpng-1.2.43 */ +#ifndef PNG_USER_LIMITS_SUPPORTED +# ifndef PNG_NO_USER_LIMITS +# define PNG_USER_LIMITS_SUPPORTED +# endif +#endif + +/* Added at libpng-1.0.16 and 1.2.6. To accept all valid PNGs no matter + * how large, set these two limits to 0x7fffffffL + */ +#ifndef PNG_USER_WIDTH_MAX +# define PNG_USER_WIDTH_MAX 1000000L +#endif +#ifndef PNG_USER_HEIGHT_MAX +# define PNG_USER_HEIGHT_MAX 1000000L +#endif + +/* Added at libpng-1.2.43. To accept all valid PNGs no matter + * how large, set these two limits to 0. + */ +#ifndef PNG_USER_CHUNK_CACHE_MAX +# define PNG_USER_CHUNK_CACHE_MAX 0 +#endif + +/* Added at libpng-1.2.43 */ +#ifndef PNG_USER_CHUNK_MALLOC_MAX +# define PNG_USER_CHUNK_MALLOC_MAX 0 +#endif + +/* Added at libpng-1.4.0 */ +#if !defined(PNG_NO_IO_STATE) && !defined(PNG_IO_STATE_SUPPORTED) +# define PNG_IO_STATE_SUPPORTED +#endif + +#ifndef PNG_LITERAL_SHARP +# define PNG_LITERAL_SHARP 0x23 +#endif +#ifndef PNG_LITERAL_LEFT_SQUARE_BRACKET +# define PNG_LITERAL_LEFT_SQUARE_BRACKET 0x5b +#endif +#ifndef PNG_LITERAL_RIGHT_SQUARE_BRACKET +# define PNG_LITERAL_RIGHT_SQUARE_BRACKET 0x5d +#endif +#ifndef PNG_STRING_NEWLINE +#define PNG_STRING_NEWLINE "\n" +#endif + +/* These are currently experimental features, define them if you want */ + +/* Very little testing */ +/* +#ifdef PNG_READ_SUPPORTED +# ifndef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED +# define PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED +# endif +#endif +*/ + +/* This is only for PowerPC big-endian and 680x0 systems */ +/* some testing */ +/* +#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED +# define PNG_READ_BIG_ENDIAN_SUPPORTED +#endif +*/ + +#if !defined(PNG_NO_USE_READ_MACROS) && !defined(PNG_USE_READ_MACROS) +# define PNG_USE_READ_MACROS +#endif + +/* Buggy compilers (e.g., gcc 2.7.2.2) need PNG_NO_POINTER_INDEXING */ + +#if !defined(PNG_NO_POINTER_INDEXING) && \ + !defined(PNG_POINTER_INDEXING_SUPPORTED) +# define PNG_POINTER_INDEXING_SUPPORTED +#endif + + +/* Any chunks you are not interested in, you can undef here. The + * ones that allocate memory may be expecially important (hIST, + * tEXt, zTXt, tRNS, pCAL). Others will just save time and make png_info + * a bit smaller. + */ + +/* The size of the png_text structure changed in libpng-1.0.6 when + * iTXt support was added. iTXt support was turned off by default through + * libpng-1.2.x, to support old apps that malloc the png_text structure + * instead of calling png_set_text() and letting libpng malloc it. It + * was turned on by default in libpng-1.4.0. + */ + +/* PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED is deprecated. */ +#if defined(PNG_READ_SUPPORTED) && \ + !defined(PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \ + !defined(PNG_NO_READ_ANCILLARY_CHUNKS) +# define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED +#endif + +/* PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED is deprecated. */ +#if defined(PNG_WRITE_SUPPORTED) && \ + !defined(PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \ + !defined(PNG_NO_WRITE_ANCILLARY_CHUNKS) +# define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED +#endif + +#ifdef PNG_READ_ANCILLARY_CHUNKS_SUPPORTED + +#ifdef PNG_NO_READ_TEXT +# define PNG_NO_READ_iTXt +# define PNG_NO_READ_tEXt +# define PNG_NO_READ_zTXt +#endif + +#ifndef PNG_NO_READ_bKGD +# define PNG_READ_bKGD_SUPPORTED +# define PNG_bKGD_SUPPORTED +#endif +#ifndef PNG_NO_READ_cHRM +# define PNG_READ_cHRM_SUPPORTED +# define PNG_cHRM_SUPPORTED +#endif +#ifndef PNG_NO_READ_gAMA +# define PNG_READ_gAMA_SUPPORTED +# define PNG_gAMA_SUPPORTED +#endif +#ifndef PNG_NO_READ_hIST +# define PNG_READ_hIST_SUPPORTED +# define PNG_hIST_SUPPORTED +#endif +#ifndef PNG_NO_READ_iCCP +# define PNG_READ_iCCP_SUPPORTED +# define PNG_iCCP_SUPPORTED +#endif +#ifndef PNG_NO_READ_iTXt +# ifndef PNG_READ_iTXt_SUPPORTED +# define PNG_READ_iTXt_SUPPORTED +# endif +# ifndef PNG_iTXt_SUPPORTED +# define PNG_iTXt_SUPPORTED +# endif +#endif +#ifndef PNG_NO_READ_oFFs +# define PNG_READ_oFFs_SUPPORTED +# define PNG_oFFs_SUPPORTED +#endif +#ifndef PNG_NO_READ_pCAL +# define PNG_READ_pCAL_SUPPORTED +# define PNG_pCAL_SUPPORTED +#endif +#ifndef PNG_NO_READ_sCAL +# define PNG_READ_sCAL_SUPPORTED +# define PNG_sCAL_SUPPORTED +#endif +#ifndef PNG_NO_READ_pHYs +# define PNG_READ_pHYs_SUPPORTED +# define PNG_pHYs_SUPPORTED +#endif +#ifndef PNG_NO_READ_sBIT +# define PNG_READ_sBIT_SUPPORTED +# define PNG_sBIT_SUPPORTED +#endif +#ifndef PNG_NO_READ_sPLT +# define PNG_READ_sPLT_SUPPORTED +# define PNG_sPLT_SUPPORTED +#endif +#ifndef PNG_NO_READ_sRGB +# define PNG_READ_sRGB_SUPPORTED +# define PNG_sRGB_SUPPORTED +#endif +#ifndef PNG_NO_READ_tEXt +# define PNG_READ_tEXt_SUPPORTED +# define PNG_tEXt_SUPPORTED +#endif +#ifndef PNG_NO_READ_tIME +# define PNG_READ_tIME_SUPPORTED +# define PNG_tIME_SUPPORTED +#endif +#ifndef PNG_NO_READ_tRNS +# define PNG_READ_tRNS_SUPPORTED +# define PNG_tRNS_SUPPORTED +#endif +#ifndef PNG_NO_READ_zTXt +# define PNG_READ_zTXt_SUPPORTED +# define PNG_zTXt_SUPPORTED +#endif +#ifndef PNG_NO_READ_OPT_PLTE +# define PNG_READ_OPT_PLTE_SUPPORTED /* only affects support of the */ +#endif /* optional PLTE chunk in RGB and RGBA images */ +#if defined(PNG_READ_iTXt_SUPPORTED) || defined(PNG_READ_tEXt_SUPPORTED) || \ + defined(PNG_READ_zTXt_SUPPORTED) +# define PNG_READ_TEXT_SUPPORTED +# define PNG_TEXT_SUPPORTED +#endif + +#endif /* PNG_READ_ANCILLARY_CHUNKS_SUPPORTED */ + +#ifndef PNG_NO_READ_UNKNOWN_CHUNKS +# ifndef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED +# define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED +# endif +# ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED +# define PNG_UNKNOWN_CHUNKS_SUPPORTED +# endif +# ifndef PNG_READ_USER_CHUNKS_SUPPORTED +# define PNG_READ_USER_CHUNKS_SUPPORTED +# endif +#endif +#ifndef PNG_NO_READ_USER_CHUNKS +# ifndef PNG_READ_USER_CHUNKS_SUPPORTED +# define PNG_READ_USER_CHUNKS_SUPPORTED +# endif +# ifndef PNG_USER_CHUNKS_SUPPORTED +# define PNG_USER_CHUNKS_SUPPORTED +# endif +#endif +#ifndef PNG_NO_HANDLE_AS_UNKNOWN +# ifndef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +# define PNG_HANDLE_AS_UNKNOWN_SUPPORTED +# endif +#endif + +#ifdef PNG_WRITE_SUPPORTED +#ifdef PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED + +#ifdef PNG_NO_WRITE_TEXT +# define PNG_NO_WRITE_iTXt +# define PNG_NO_WRITE_tEXt +# define PNG_NO_WRITE_zTXt +#endif +#ifndef PNG_NO_WRITE_bKGD +# define PNG_WRITE_bKGD_SUPPORTED +# ifndef PNG_bKGD_SUPPORTED +# define PNG_bKGD_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_cHRM +# define PNG_WRITE_cHRM_SUPPORTED +# ifndef PNG_cHRM_SUPPORTED +# define PNG_cHRM_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_gAMA +# define PNG_WRITE_gAMA_SUPPORTED +# ifndef PNG_gAMA_SUPPORTED +# define PNG_gAMA_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_hIST +# define PNG_WRITE_hIST_SUPPORTED +# ifndef PNG_hIST_SUPPORTED +# define PNG_hIST_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_iCCP +# define PNG_WRITE_iCCP_SUPPORTED +# ifndef PNG_iCCP_SUPPORTED +# define PNG_iCCP_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_iTXt +# ifndef PNG_WRITE_iTXt_SUPPORTED +# define PNG_WRITE_iTXt_SUPPORTED +# endif +# ifndef PNG_iTXt_SUPPORTED +# define PNG_iTXt_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_oFFs +# define PNG_WRITE_oFFs_SUPPORTED +# ifndef PNG_oFFs_SUPPORTED +# define PNG_oFFs_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_pCAL +# define PNG_WRITE_pCAL_SUPPORTED +# ifndef PNG_pCAL_SUPPORTED +# define PNG_pCAL_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_sCAL +# define PNG_WRITE_sCAL_SUPPORTED +# ifndef PNG_sCAL_SUPPORTED +# define PNG_sCAL_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_pHYs +# define PNG_WRITE_pHYs_SUPPORTED +# ifndef PNG_pHYs_SUPPORTED +# define PNG_pHYs_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_sBIT +# define PNG_WRITE_sBIT_SUPPORTED +# ifndef PNG_sBIT_SUPPORTED +# define PNG_sBIT_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_sPLT +# define PNG_WRITE_sPLT_SUPPORTED +# ifndef PNG_sPLT_SUPPORTED +# define PNG_sPLT_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_sRGB +# define PNG_WRITE_sRGB_SUPPORTED +# ifndef PNG_sRGB_SUPPORTED +# define PNG_sRGB_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_tEXt +# define PNG_WRITE_tEXt_SUPPORTED +# ifndef PNG_tEXt_SUPPORTED +# define PNG_tEXt_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_tIME +# define PNG_WRITE_tIME_SUPPORTED +# ifndef PNG_tIME_SUPPORTED +# define PNG_tIME_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_tRNS +# define PNG_WRITE_tRNS_SUPPORTED +# ifndef PNG_tRNS_SUPPORTED +# define PNG_tRNS_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_zTXt +# define PNG_WRITE_zTXt_SUPPORTED +# ifndef PNG_zTXt_SUPPORTED +# define PNG_zTXt_SUPPORTED +# endif +#endif +#if defined(PNG_WRITE_iTXt_SUPPORTED) || defined(PNG_WRITE_tEXt_SUPPORTED) || \ + defined(PNG_WRITE_zTXt_SUPPORTED) +# define PNG_WRITE_TEXT_SUPPORTED +# ifndef PNG_TEXT_SUPPORTED +# define PNG_TEXT_SUPPORTED +# endif +#endif + +#ifdef PNG_WRITE_tIME_SUPPORTED +# ifndef PNG_NO_CONVERT_tIME +# ifndef _WIN32_WCE +/* The "tm" structure is not supported on WindowsCE */ +# ifndef PNG_CONVERT_tIME_SUPPORTED +# define PNG_CONVERT_tIME_SUPPORTED +# endif +# endif +# endif +#endif + +#endif /* PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED */ + +#ifndef PNG_NO_WRITE_FILTER +# ifndef PNG_WRITE_FILTER_SUPPORTED +# define PNG_WRITE_FILTER_SUPPORTED +# endif +#endif + +#ifndef PNG_NO_WRITE_UNKNOWN_CHUNKS +# define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED +# ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED +# define PNG_UNKNOWN_CHUNKS_SUPPORTED +# endif +#endif +#ifndef PNG_NO_HANDLE_AS_UNKNOWN +# ifndef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +# define PNG_HANDLE_AS_UNKNOWN_SUPPORTED +# endif +#endif +#endif /* PNG_WRITE_SUPPORTED */ + +/* Turn this off to disable png_read_png() and + * png_write_png() and leave the row_pointers member + * out of the info structure. + */ +#ifndef PNG_NO_INFO_IMAGE +# define PNG_INFO_IMAGE_SUPPORTED +#endif + +/* Need the time information for converting tIME chunks */ +#ifdef PNG_CONVERT_tIME_SUPPORTED + /* "time.h" functions are not supported on WindowsCE */ +# include +#endif + +/* Some typedefs to get us started. These should be safe on most of the + * common platforms. The typedefs should be at least as large as the + * numbers suggest (a png_uint_32 must be at least 32 bits long), but they + * don't have to be exactly that size. Some compilers dislike passing + * unsigned shorts as function parameters, so you may be better off using + * unsigned int for png_uint_16. + */ + +#if defined(INT_MAX) && (INT_MAX > 0x7ffffffeL) +typedef unsigned int png_uint_32; +typedef int png_int_32; +#else +typedef unsigned long png_uint_32; +typedef long png_int_32; +#endif +typedef unsigned short png_uint_16; +typedef short png_int_16; +typedef unsigned char png_byte; + +#ifdef PNG_NO_SIZE_T + typedef unsigned int png_size_t; +#else + typedef size_t png_size_t; +#endif +#define png_sizeof(x) sizeof(x) + +/* The following is needed for medium model support. It cannot be in the + * pngpriv.h header. Needs modification for other compilers besides + * MSC. Model independent support declares all arrays and pointers to be + * large using the far keyword. The zlib version used must also support + * model independent data. As of version zlib 1.0.4, the necessary changes + * have been made in zlib. The USE_FAR_KEYWORD define triggers other + * changes that are needed. (Tim Wegner) + */ + +/* Separate compiler dependencies (problem here is that zlib.h always + * defines FAR. (SJT) + */ +#ifdef __BORLANDC__ +# if defined(__LARGE__) || defined(__HUGE__) || defined(__COMPACT__) +# define LDATA 1 +# else +# define LDATA 0 +# endif + /* GRR: why is Cygwin in here? Cygwin is not Borland C... */ +# if !defined(__WIN32__) && !defined(__FLAT__) && !defined(__CYGWIN__) +# define PNG_MAX_MALLOC_64K +# if (LDATA != 1) +# ifndef FAR +# define FAR __far +# endif +# define USE_FAR_KEYWORD +# endif /* LDATA != 1 */ + /* Possibly useful for moving data out of default segment. + * Uncomment it if you want. Could also define FARDATA as + * const if your compiler supports it. (SJT) +# define FARDATA FAR + */ +# endif /* __WIN32__, __FLAT__, __CYGWIN__ */ +#endif /* __BORLANDC__ */ + + +/* Suggest testing for specific compiler first before testing for + * FAR. The Watcom compiler defines both __MEDIUM__ and M_I86MM, + * making reliance oncertain keywords suspect. (SJT) + */ + +/* MSC Medium model */ +#ifdef FAR +# ifdef M_I86MM +# define USE_FAR_KEYWORD +# define FARDATA FAR +# include +# endif +#endif + +/* SJT: default case */ +#ifndef FAR +# define FAR +#endif + +/* At this point FAR is always defined */ +#ifndef FARDATA +# define FARDATA +#endif + +/* Typedef for floating-point numbers that are converted + to fixed-point with a multiple of 100,000, e.g., int_gamma */ +typedef png_int_32 png_fixed_point; + +/* Add typedefs for pointers */ +typedef void FAR * png_voidp; +typedef png_byte FAR * png_bytep; +typedef png_uint_32 FAR * png_uint_32p; +typedef png_int_32 FAR * png_int_32p; +typedef png_uint_16 FAR * png_uint_16p; +typedef png_int_16 FAR * png_int_16p; +typedef PNG_CONST char FAR * png_const_charp; +typedef char FAR * png_charp; +typedef png_fixed_point FAR * png_fixed_point_p; + +#ifndef PNG_NO_STDIO +typedef FILE * png_FILE_p; +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double FAR * png_doublep; +#endif + +/* Pointers to pointers; i.e. arrays */ +typedef png_byte FAR * FAR * png_bytepp; +typedef png_uint_32 FAR * FAR * png_uint_32pp; +typedef png_int_32 FAR * FAR * png_int_32pp; +typedef png_uint_16 FAR * FAR * png_uint_16pp; +typedef png_int_16 FAR * FAR * png_int_16pp; +typedef PNG_CONST char FAR * FAR * png_const_charpp; +typedef char FAR * FAR * png_charpp; +typedef png_fixed_point FAR * FAR * png_fixed_point_pp; +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double FAR * FAR * png_doublepp; +#endif + +/* Pointers to pointers to pointers; i.e., pointer to array */ +typedef char FAR * FAR * FAR * png_charppp; + +/* Define PNG_BUILD_DLL if the module being built is a Windows + * LIBPNG DLL. + * + * Define PNG_USE_DLL if you want to *link* to the Windows LIBPNG DLL. + * It is equivalent to Microsoft predefined macro _DLL that is + * automatically defined when you compile using the share + * version of the CRT (C Run-Time library) + * + * The cygwin mods make this behavior a little different: + * Define PNG_BUILD_DLL if you are building a dll for use with cygwin + * Define PNG_STATIC if you are building a static library for use with cygwin, + * -or- if you are building an application that you want to link to the + * static library. + * PNG_USE_DLL is defined by default (no user action needed) unless one of + * the other flags is defined. + */ + +#if !defined(PNG_DLL) && (defined(PNG_BUILD_DLL) || defined(PNG_USE_DLL)) +# define PNG_DLL +#endif + +#ifdef __CYGWIN__ +# undef PNGAPI +# define PNGAPI __cdecl +# undef PNG_IMPEXP +# define PNG_IMPEXP +#endif + +#define PNG_USE_LOCAL_ARRAYS /* Not used in libpng, defined for legacy apps */ + +/* If you define PNGAPI, e.g., with compiler option "-DPNGAPI=__stdcall", + * you may get warnings regarding the linkage of png_zalloc and png_zfree. + * Don't ignore those warnings; you must also reset the default calling + * convention in your compiler to match your PNGAPI, and you must build + * zlib and your applications the same way you build libpng. + */ + +#if defined(__MINGW32__) && !defined(PNG_MODULEDEF) +# ifndef PNG_NO_MODULEDEF +# define PNG_NO_MODULEDEF +# endif +#endif + +#if !defined(PNG_IMPEXP) && defined(PNG_BUILD_DLL) && !defined(PNG_NO_MODULEDEF) +# define PNG_IMPEXP +#endif + +#if defined(PNG_DLL) || defined(_DLL) || defined(__DLL__ ) || \ + (( defined(_Windows) || defined(_WINDOWS) || \ + defined(WIN32) || defined(_WIN32) || defined(__WIN32__) )) + +# ifndef PNGAPI +# if defined(__GNUC__) || (defined (_MSC_VER) && (_MSC_VER >= 800)) +# define PNGAPI __cdecl +# else +# define PNGAPI _cdecl +# endif +# endif + +# if !defined(PNG_IMPEXP) && (!defined(PNG_DLL) || \ + 0 /* WINCOMPILER_WITH_NO_SUPPORT_FOR_DECLIMPEXP */) +# define PNG_IMPEXP +# endif + +# ifndef PNG_IMPEXP + +# define PNG_EXPORT_TYPE1(type,symbol) PNG_IMPEXP type PNGAPI symbol +# define PNG_EXPORT_TYPE2(type,symbol) type PNG_IMPEXP PNGAPI symbol + + /* Borland/Microsoft */ +# if defined(_MSC_VER) || defined(__BORLANDC__) +# if (_MSC_VER >= 800) || (__BORLANDC__ >= 0x500) +# define PNG_EXPORT PNG_EXPORT_TYPE1 +# else +# define PNG_EXPORT PNG_EXPORT_TYPE2 +# ifdef PNG_BUILD_DLL +# define PNG_IMPEXP __export +# else +# define PNG_IMPEXP /*__import */ /* doesn't exist AFAIK in VC++ */ +# endif /* Exists in Borland C++ for + C++ classes (== huge) */ +# endif +# endif + +# ifndef PNG_IMPEXP +# ifdef PNG_BUILD_DLL +# define PNG_IMPEXP __declspec(dllexport) +# else +# define PNG_IMPEXP __declspec(dllimport) +# endif +# endif +# endif /* PNG_IMPEXP */ +#else /* !(DLL || non-cygwin WINDOWS) */ +# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__) +# ifndef PNGAPI +# define PNGAPI _System +# endif +# else +# if 0 /* ... other platforms, with other meanings */ +# endif +# endif +#endif + +#ifndef PNGAPI +# define PNGAPI +#endif +#ifndef PNG_IMPEXP +# define PNG_IMPEXP +#endif + +#ifdef PNG_BUILDSYMS +# ifndef PNG_EXPORT +# define PNG_EXPORT(type,symbol) PNG_FUNCTION_EXPORT symbol END +# endif +#endif + +#ifndef PNG_EXPORT +# define PNG_EXPORT(type,symbol) PNG_IMPEXP type PNGAPI symbol +#endif + +/* Support for compiler specific function attributes. These are used + * so that where compiler support is available incorrect use of API + * functions in png.h will generate compiler warnings. + * + * Added at libpng-1.2.41. + */ + +#ifndef PNG_NO_PEDANTIC_WARNINGS +# ifndef PNG_PEDANTIC_WARNINGS_SUPPORTED +# define PNG_PEDANTIC_WARNINGS_SUPPORTED +# endif +#endif + +#ifdef PNG_PEDANTIC_WARNINGS_SUPPORTED +/* Support for compiler specific function attributes. These are used + * so that where compiler support is available incorrect use of API + * functions in png.h will generate compiler warnings. Added at libpng + * version 1.2.41. + */ +# ifdef __GNUC__ +# ifndef PNG_USE_RESULT +# define PNG_USE_RESULT __attribute__((__warn_unused_result__)) +# endif +# ifndef PNG_NORETURN +# define PNG_NORETURN __attribute__((__noreturn__)) +# endif +# ifndef PNG_ALLOCATED +# define PNG_ALLOCATED __attribute__((__malloc__)) +# endif + + /* This specifically protects structure members that should only be + * accessed from within the library, therefore should be empty during + * a library build. + */ +# ifndef PNG_DEPRECATED +# define PNG_DEPRECATED __attribute__((__deprecated__)) +# endif +# ifndef PNG_DEPSTRUCT +# define PNG_DEPSTRUCT __attribute__((__deprecated__)) +# endif +# ifndef PNG_PRIVATE +# if 0 /* Doesn't work so we use deprecated instead*/ +# define PNG_PRIVATE \ + __attribute__((warning("This function is not exported by libpng."))) +# else +# define PNG_PRIVATE \ + __attribute__((__deprecated__)) +# endif +# endif /* PNG_PRIVATE */ +# endif /* __GNUC__ */ +#endif /* PNG_PEDANTIC_WARNINGS */ + +#ifndef PNG_DEPRECATED +# define PNG_DEPRECATED /* Use of this function is deprecated */ +#endif +#ifndef PNG_USE_RESULT +# define PNG_USE_RESULT /* The result of this function must be checked */ +#endif +#ifndef PNG_NORETURN +# define PNG_NORETURN /* This function does not return */ +#endif +#ifndef PNG_ALLOCATED +# define PNG_ALLOCATED /* The result of the function is new memory */ +#endif +#ifndef PNG_DEPSTRUCT +# define PNG_DEPSTRUCT /* Access to this struct member is deprecated */ +#endif +#ifndef PNG_PRIVATE +# define PNG_PRIVATE /* This is a private libpng function */ +#endif + +/* Users may want to use these so they are not private. Any library + * functions that are passed far data must be model-independent. + */ + +/* memory model/platform independent fns */ +#ifndef PNG_ABORT +# ifdef _WINDOWS_ +# define PNG_ABORT() ExitProcess(0) +# else +# define PNG_ABORT() abort() +# endif +#endif + +#ifdef USE_FAR_KEYWORD +/* Use this to make far-to-near assignments */ +# define CHECK 1 +# define NOCHECK 0 +# define CVT_PTR(ptr) (png_far_to_near(png_ptr,ptr,CHECK)) +# define CVT_PTR_NOCHECK(ptr) (png_far_to_near(png_ptr,ptr,NOCHECK)) +# define png_strcpy _fstrcpy +# define png_strncpy _fstrncpy /* Added to v 1.2.6 */ +# define png_strlen _fstrlen +# define png_memcmp _fmemcmp /* SJT: added */ +# define png_memcpy _fmemcpy +# define png_memset _fmemset +# define png_sprintf sprintf +#else +# ifdef _WINDOWS_ /* Favor Windows over C runtime fns */ +# define CVT_PTR(ptr) (ptr) +# define CVT_PTR_NOCHECK(ptr) (ptr) +# define png_strcpy lstrcpyA +# define png_strncpy lstrcpynA +# define png_strlen lstrlenA +# define png_memcmp memcmp +# define png_memcpy CopyMemory +# define png_memset memset +# define png_sprintf wsprintfA +# else +# define CVT_PTR(ptr) (ptr) +# define CVT_PTR_NOCHECK(ptr) (ptr) +# define png_strcpy strcpy +# define png_strncpy strncpy /* Added to v 1.2.6 */ +# define png_strlen strlen +# define png_memcmp memcmp /* SJT: added */ +# define png_memcpy memcpy +# define png_memset memset +# define png_sprintf sprintf +# ifndef PNG_NO_SNPRINTF +# ifdef _MSC_VER +# define png_snprintf _snprintf /* Added to v 1.2.19 */ +# define png_snprintf2 _snprintf +# define png_snprintf6 _snprintf +# else +# define png_snprintf snprintf /* Added to v 1.2.19 */ +# define png_snprintf2 snprintf +# define png_snprintf6 snprintf +# endif +# else + /* You don't have or don't want to use snprintf(). Caution: Using + * sprintf instead of snprintf exposes your application to accidental + * or malevolent buffer overflows. If you don't have snprintf() + * as a general rule you should provide one (you can get one from + * Portable OpenSSH). + */ +# define png_snprintf(s1,n,fmt,x1) sprintf(s1,fmt,x1) +# define png_snprintf2(s1,n,fmt,x1,x2) sprintf(s1,fmt,x1,x2) +# define png_snprintf6(s1,n,fmt,x1,x2,x3,x4,x5,x6) \ + sprintf(s1,fmt,x1,x2,x3,x4,x5,x6) +# endif +# endif +#endif + +/* png_alloc_size_t is guaranteed to be no smaller than png_size_t, + * and no smaller than png_uint_32. Casts from png_size_t or png_uint_32 + * to png_alloc_size_t are not necessary; in fact, it is recommended + * not to use them at all so that the compiler can complain when something + * turns out to be problematic. + * Casts in the other direction (from png_alloc_size_t to png_size_t or + * png_uint_32) should be explicitly applied; however, we do not expect + * to encounter practical situations that require such conversions. + */ +#if defined(__TURBOC__) && !defined(__FLAT__) +# define png_mem_alloc farmalloc +# define png_mem_free farfree + typedef unsigned long png_alloc_size_t; +#else +# if defined(_MSC_VER) && defined(MAXSEG_64K) +# define png_mem_alloc(s) halloc(s, 1) +# define png_mem_free hfree + typedef unsigned long png_alloc_size_t; +# else +# if defined(_WINDOWS_) && (!defined(INT_MAX) || INT_MAX <= 0x7ffffffeL) +# define png_mem_alloc(s) HeapAlloc(GetProcessHeap(), 0, s) +# define png_mem_free(p) HeapFree(GetProcessHeap(), 0, p) + typedef DWORD png_alloc_size_t; +# else +# define png_mem_alloc malloc +# define png_mem_free free + typedef png_size_t png_alloc_size_t; +# endif +# endif +#endif +/* End of memory model/platform independent support */ + +/* Just a little check that someone hasn't tried to define something + * contradictory. + */ +#if (PNG_ZBUF_SIZE > 65536L) && defined(PNG_MAX_MALLOC_64K) +# undef PNG_ZBUF_SIZE +# define PNG_ZBUF_SIZE 65536L +#endif + + +/* Added at libpng-1.2.8 */ +#endif /* PNG_VERSION_INFO_ONLY */ + +#endif /* PNGCONF_H */ diff --git a/reactos/dll/3rdparty/libpng/pngerror.c b/reactos/dll/3rdparty/libpng/pngerror.c new file mode 100644 index 00000000000..633eae29f9e --- /dev/null +++ b/reactos/dll/3rdparty/libpng/pngerror.c @@ -0,0 +1,402 @@ + +/* pngerror.c - stub functions for i/o and memory allocation + * + * Last changed in libpng 1.4.0 [January 3, 2010] + * Copyright (c) 1998-2010 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file provides a location for all error handling. Users who + * need special error handling are expected to write replacement functions + * and use png_set_error_fn() to use those functions. See the instructions + * at each function. + */ + +#define PNG_NO_PEDANTIC_WARNINGS +#include "png.h" +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +#include "pngpriv.h" + +static void /* PRIVATE */ +png_default_error PNGARG((png_structp png_ptr, + png_const_charp error_message)) PNG_NORETURN; +#ifdef PNG_WARNINGS_SUPPORTED +static void /* PRIVATE */ +png_default_warning PNGARG((png_structp png_ptr, + png_const_charp warning_message)); +#endif /* PNG_WARNINGS_SUPPORTED */ + +/* This function is called whenever there is a fatal error. This function + * should not be changed. If there is a need to handle errors differently, + * you should supply a replacement error function and use png_set_error_fn() + * to replace the error function at run-time. + */ +#ifdef PNG_ERROR_TEXT_SUPPORTED +void PNGAPI +png_error(png_structp png_ptr, png_const_charp error_message) +{ +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + char msg[16]; + if (png_ptr != NULL) + { + if (png_ptr->flags& + (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) + { + if (*error_message == PNG_LITERAL_SHARP) + { + /* Strip "#nnnn " from beginning of error message. */ + int offset; + for (offset = 1; offset<15; offset++) + if (error_message[offset] == ' ') + break; + if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT) + { + int i; + for (i = 0; i < offset - 1; i++) + msg[i] = error_message[i + 1]; + msg[i - 1] = '\0'; + error_message = msg; + } + else + error_message += offset; + } + else + { + if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT) + { + msg[0] = '0'; + msg[1] = '\0'; + error_message = msg; + } + } + } + } +#endif + if (png_ptr != NULL && png_ptr->error_fn != NULL) + (*(png_ptr->error_fn))(png_ptr, error_message); + + /* If the custom handler doesn't exist, or if it returns, + use the default handler, which will not return. */ + png_default_error(png_ptr, error_message); +} +#else +void PNGAPI +png_err(png_structp png_ptr) +{ + if (png_ptr != NULL && png_ptr->error_fn != NULL) + (*(png_ptr->error_fn))(png_ptr, '\0'); + + /* If the custom handler doesn't exist, or if it returns, + use the default handler, which will not return. */ + png_default_error(png_ptr, '\0'); +} +#endif /* PNG_ERROR_TEXT_SUPPORTED */ + +#ifdef PNG_WARNINGS_SUPPORTED +/* This function is called whenever there is a non-fatal error. This function + * should not be changed. If there is a need to handle warnings differently, + * you should supply a replacement warning function and use + * png_set_error_fn() to replace the warning function at run-time. + */ +void PNGAPI +png_warning(png_structp png_ptr, png_const_charp warning_message) +{ + int offset = 0; + if (png_ptr != NULL) + { +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + if (png_ptr->flags& + (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) +#endif + { + if (*warning_message == PNG_LITERAL_SHARP) + { + for (offset = 1; offset < 15; offset++) + if (warning_message[offset] == ' ') + break; + } + } + } + if (png_ptr != NULL && png_ptr->warning_fn != NULL) + (*(png_ptr->warning_fn))(png_ptr, warning_message + offset); + else + png_default_warning(png_ptr, warning_message + offset); +} +#endif /* PNG_WARNINGS_SUPPORTED */ + +#ifdef PNG_BENIGN_ERRORS_SUPPORTED +void PNGAPI +png_benign_error(png_structp png_ptr, png_const_charp error_message) +{ + if (png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) + png_warning(png_ptr, error_message); + else + png_error(png_ptr, error_message); +} +#endif + +/* These utilities are used internally to build an error message that relates + * to the current chunk. The chunk name comes from png_ptr->chunk_name, + * this is used to prefix the message. The message is limited in length + * to 63 bytes, the name characters are output as hex digits wrapped in [] + * if the character is invalid. + */ +#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) +static PNG_CONST char png_digit[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F' +}; + +#define PNG_MAX_ERROR_TEXT 64 +#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_ERROR_TEXT_SUPPORTED) +static void /* PRIVATE */ +png_format_buffer(png_structp png_ptr, png_charp buffer, png_const_charp + error_message) +{ + int iout = 0, iin = 0; + + while (iin < 4) + { + int c = png_ptr->chunk_name[iin++]; + if (isnonalpha(c)) + { + buffer[iout++] = PNG_LITERAL_LEFT_SQUARE_BRACKET; + buffer[iout++] = png_digit[(c & 0xf0) >> 4]; + buffer[iout++] = png_digit[c & 0x0f]; + buffer[iout++] = PNG_LITERAL_RIGHT_SQUARE_BRACKET; + } + else + { + buffer[iout++] = (png_byte)c; + } + } + + if (error_message == NULL) + buffer[iout] = '\0'; + else + { + buffer[iout++] = ':'; + buffer[iout++] = ' '; + png_memcpy(buffer + iout, error_message, PNG_MAX_ERROR_TEXT); + buffer[iout + PNG_MAX_ERROR_TEXT - 1] = '\0'; + } +} + +#ifdef PNG_READ_SUPPORTED +void PNGAPI +png_chunk_error(png_structp png_ptr, png_const_charp error_message) +{ + char msg[18+PNG_MAX_ERROR_TEXT]; + if (png_ptr == NULL) + png_error(png_ptr, error_message); + else + { + png_format_buffer(png_ptr, msg, error_message); + png_error(png_ptr, msg); + } +} +#endif /* PNG_READ_SUPPORTED */ +#endif /* PNG_WARNINGS_SUPPORTED || PNG_ERROR_TEXT_SUPPORTED */ + +#ifdef PNG_WARNINGS_SUPPORTED +void PNGAPI +png_chunk_warning(png_structp png_ptr, png_const_charp warning_message) +{ + char msg[18+PNG_MAX_ERROR_TEXT]; + if (png_ptr == NULL) + png_warning(png_ptr, warning_message); + else + { + png_format_buffer(png_ptr, msg, warning_message); + png_warning(png_ptr, msg); + } +} +#endif /* PNG_WARNINGS_SUPPORTED */ + +#ifdef PNG_READ_SUPPORTED +#ifdef PNG_BENIGN_ERRORS_SUPPORTED +void PNGAPI +png_chunk_benign_error(png_structp png_ptr, png_const_charp error_message) +{ + if (png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) + png_chunk_warning(png_ptr, error_message); + else + png_chunk_error(png_ptr, error_message); +} +#endif +#endif /* PNG_READ_SUPPORTED */ + +#ifdef PNG_SETJMP_SUPPORTED +/* This API only exists if ANSI-C style error handling is used, + * otherwise it is necessary for png_default_error to be overridden. + */ +jmp_buf* PNGAPI +png_set_longjmp_fn(png_structp png_ptr, png_longjmp_ptr longjmp_fn, + size_t jmp_buf_size) +{ + if (png_ptr == NULL || jmp_buf_size != png_sizeof(jmp_buf)) + return NULL; + + png_ptr->longjmp_fn = longjmp_fn; + return &png_ptr->jmpbuf; +} +#endif + +/* This is the default error handling function. Note that replacements for + * this function MUST NOT RETURN, or the program will likely crash. This + * function is used by default, or if the program supplies NULL for the + * error function pointer in png_set_error_fn(). + */ +static void /* PRIVATE */ +png_default_error(png_structp png_ptr, png_const_charp error_message) +{ +#ifdef PNG_CONSOLE_IO_SUPPORTED +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + if (*error_message == PNG_LITERAL_SHARP) + { + /* Strip "#nnnn " from beginning of error message. */ + int offset; + char error_number[16]; + for (offset = 0; offset<15; offset++) + { + error_number[offset] = error_message[offset + 1]; + if (error_message[offset] == ' ') + break; + } + if ((offset > 1) && (offset < 15)) + { + error_number[offset - 1] = '\0'; + fprintf(stderr, "libpng error no. %s: %s", + error_number, error_message + offset + 1); + fprintf(stderr, PNG_STRING_NEWLINE); + } + else + { + fprintf(stderr, "libpng error: %s, offset=%d", + error_message, offset); + fprintf(stderr, PNG_STRING_NEWLINE); + } + } + else +#endif + { + fprintf(stderr, "libpng error: %s", error_message); + fprintf(stderr, PNG_STRING_NEWLINE); + } +#endif + +#ifdef PNG_SETJMP_SUPPORTED + if (png_ptr && png_ptr->longjmp_fn) + { +# ifdef USE_FAR_KEYWORD + { + jmp_buf jmpbuf; + png_memcpy(jmpbuf, png_ptr->jmpbuf, png_sizeof(jmp_buf)); + png_ptr->longjmp_fn(jmpbuf, 1); + } +# else + png_ptr->longjmp_fn(png_ptr->jmpbuf, 1); +# endif + } +#endif + /* Here if not setjmp support or if png_ptr is null. */ + PNG_ABORT(); +#ifndef PNG_CONSOLE_IO_SUPPORTED + error_message = error_message; /* Make compiler happy */ +#endif +} + +#ifdef PNG_WARNINGS_SUPPORTED +/* This function is called when there is a warning, but the library thinks + * it can continue anyway. Replacement functions don't have to do anything + * here if you don't want them to. In the default configuration, png_ptr is + * not used, but it is passed in case it may be useful. + */ +static void /* PRIVATE */ +png_default_warning(png_structp png_ptr, png_const_charp warning_message) +{ +#ifdef PNG_CONSOLE_IO_SUPPORTED +# ifdef PNG_ERROR_NUMBERS_SUPPORTED + if (*warning_message == PNG_LITERAL_SHARP) + { + int offset; + char warning_number[16]; + for (offset = 0; offset < 15; offset++) + { + warning_number[offset] = warning_message[offset + 1]; + if (warning_message[offset] == ' ') + break; + } + if ((offset > 1) && (offset < 15)) + { + warning_number[offset + 1] = '\0'; + fprintf(stderr, "libpng warning no. %s: %s", + warning_number, warning_message + offset); + fprintf(stderr, PNG_STRING_NEWLINE); + } + else + { + fprintf(stderr, "libpng warning: %s", + warning_message); + fprintf(stderr, PNG_STRING_NEWLINE); + } + } + else +# endif + { + fprintf(stderr, "libpng warning: %s", warning_message); + fprintf(stderr, PNG_STRING_NEWLINE); + } +#else + warning_message = warning_message; /* Make compiler happy */ +#endif + png_ptr = png_ptr; /* Make compiler happy */ +} +#endif /* PNG_WARNINGS_SUPPORTED */ + +/* This function is called when the application wants to use another method + * of handling errors and warnings. Note that the error function MUST NOT + * return to the calling routine or serious problems will occur. The return + * method used in the default routine calls longjmp(png_ptr->jmpbuf, 1) + */ +void PNGAPI +png_set_error_fn(png_structp png_ptr, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warning_fn) +{ + if (png_ptr == NULL) + return; + png_ptr->error_ptr = error_ptr; + png_ptr->error_fn = error_fn; + png_ptr->warning_fn = warning_fn; +} + + +/* This function returns a pointer to the error_ptr associated with the user + * functions. The application should free any memory associated with this + * pointer before png_write_destroy and png_read_destroy are called. + */ +png_voidp PNGAPI +png_get_error_ptr(png_structp png_ptr) +{ + if (png_ptr == NULL) + return NULL; + return ((png_voidp)png_ptr->error_ptr); +} + + +#ifdef PNG_ERROR_NUMBERS_SUPPORTED +void PNGAPI +png_set_strip_error_numbers(png_structp png_ptr, png_uint_32 strip_mode) +{ + if (png_ptr != NULL) + { + png_ptr->flags &= + ((~(PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT))&strip_mode); + } +} +#endif +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/reactos/dll/3rdparty/libpng/pngget.c b/reactos/dll/3rdparty/libpng/pngget.c new file mode 100644 index 00000000000..abe721bd589 --- /dev/null +++ b/reactos/dll/3rdparty/libpng/pngget.c @@ -0,0 +1,925 @@ + +/* pngget.c - retrieval of values from info struct + * + * Last changed in libpng 1.4.2 [May 6, 2010] + * Copyright (c) 1998-2010 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + */ + +#define PNG_NO_PEDANTIC_WARNINGS +#include "png.h" +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +#include "pngpriv.h" + +png_uint_32 PNGAPI +png_get_valid(png_structp png_ptr, png_infop info_ptr, png_uint_32 flag) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->valid & flag); + + else + return(0); +} + +png_size_t PNGAPI +png_get_rowbytes(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->rowbytes); + + else + return(0); +} + +#ifdef PNG_INFO_IMAGE_SUPPORTED +png_bytepp PNGAPI +png_get_rows(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->row_pointers); + + else + return(0); +} +#endif + +#ifdef PNG_EASY_ACCESS_SUPPORTED +/* Easy access to info, added in libpng-0.99 */ +png_uint_32 PNGAPI +png_get_image_width(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->width; + + return (0); +} + +png_uint_32 PNGAPI +png_get_image_height(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->height; + + return (0); +} + +png_byte PNGAPI +png_get_bit_depth(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->bit_depth; + + return (0); +} + +png_byte PNGAPI +png_get_color_type(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->color_type; + + return (0); +} + +png_byte PNGAPI +png_get_filter_type(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->filter_type; + + return (0); +} + +png_byte PNGAPI +png_get_interlace_type(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->interlace_type; + + return (0); +} + +png_byte PNGAPI +png_get_compression_type(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->compression_type; + + return (0); +} + +png_uint_32 PNGAPI +png_get_x_pixels_per_meter(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) +#ifdef PNG_pHYs_SUPPORTED + if (info_ptr->valid & PNG_INFO_pHYs) + { + png_debug1(1, "in %s retrieval function", "png_get_x_pixels_per_meter"); + + if (info_ptr->phys_unit_type != PNG_RESOLUTION_METER) + return (0); + + else + return (info_ptr->x_pixels_per_unit); + } +#else + return (0); +#endif + return (0); +} + +png_uint_32 PNGAPI +png_get_y_pixels_per_meter(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) +#ifdef PNG_pHYs_SUPPORTED + if (info_ptr->valid & PNG_INFO_pHYs) + { + png_debug1(1, "in %s retrieval function", "png_get_y_pixels_per_meter"); + + if (info_ptr->phys_unit_type != PNG_RESOLUTION_METER) + return (0); + + else + return (info_ptr->y_pixels_per_unit); + } +#else + return (0); +#endif + return (0); +} + +png_uint_32 PNGAPI +png_get_pixels_per_meter(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) +#ifdef PNG_pHYs_SUPPORTED + if (info_ptr->valid & PNG_INFO_pHYs) + { + png_debug1(1, "in %s retrieval function", "png_get_pixels_per_meter"); + + if (info_ptr->phys_unit_type != PNG_RESOLUTION_METER || + info_ptr->x_pixels_per_unit != info_ptr->y_pixels_per_unit) + return (0); + + else + return (info_ptr->x_pixels_per_unit); + } +#else + return (0); +#endif + return (0); +} + +#ifdef PNG_FLOATING_POINT_SUPPORTED +float PNGAPI +png_get_pixel_aspect_ratio(png_structp png_ptr, png_infop info_ptr) + { + if (png_ptr != NULL && info_ptr != NULL) +#ifdef PNG_pHYs_SUPPORTED + + if (info_ptr->valid & PNG_INFO_pHYs) + { + png_debug1(1, "in %s retrieval function", "png_get_aspect_ratio"); + + if (info_ptr->x_pixels_per_unit == 0) + return ((float)0.0); + + else + return ((float)((float)info_ptr->y_pixels_per_unit + /(float)info_ptr->x_pixels_per_unit)); + } +#else + return (0.0); +#endif + return ((float)0.0); +} +#endif + +png_int_32 PNGAPI +png_get_x_offset_microns(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) +#ifdef PNG_oFFs_SUPPORTED + + if (info_ptr->valid & PNG_INFO_oFFs) + { + png_debug1(1, "in %s retrieval function", "png_get_x_offset_microns"); + + if (info_ptr->offset_unit_type != PNG_OFFSET_MICROMETER) + return (0); + + else + return (info_ptr->x_offset); + } +#else + return (0); +#endif + return (0); +} + +png_int_32 PNGAPI +png_get_y_offset_microns(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + +#ifdef PNG_oFFs_SUPPORTED + if (info_ptr->valid & PNG_INFO_oFFs) + { + png_debug1(1, "in %s retrieval function", "png_get_y_offset_microns"); + + if (info_ptr->offset_unit_type != PNG_OFFSET_MICROMETER) + return (0); + + else + return (info_ptr->y_offset); + } +#else + return (0); +#endif + return (0); +} + +png_int_32 PNGAPI +png_get_x_offset_pixels(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + +#ifdef PNG_oFFs_SUPPORTED + if (info_ptr->valid & PNG_INFO_oFFs) + { + png_debug1(1, "in %s retrieval function", "png_get_x_offset_microns"); + + if (info_ptr->offset_unit_type != PNG_OFFSET_PIXEL) + return (0); + + else + return (info_ptr->x_offset); + } +#else + return (0); +#endif + return (0); +} + +png_int_32 PNGAPI +png_get_y_offset_pixels(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + +#ifdef PNG_oFFs_SUPPORTED + if (info_ptr->valid & PNG_INFO_oFFs) + { + png_debug1(1, "in %s retrieval function", "png_get_y_offset_microns"); + + if (info_ptr->offset_unit_type != PNG_OFFSET_PIXEL) + return (0); + + else + return (info_ptr->y_offset); + } +#else + return (0); +#endif + return (0); +} + +#if defined(PNG_INCH_CONVERSIONS) && defined(PNG_FLOATING_POINT_SUPPORTED) +png_uint_32 PNGAPI +png_get_pixels_per_inch(png_structp png_ptr, png_infop info_ptr) +{ + return ((png_uint_32)((float)png_get_pixels_per_meter(png_ptr, info_ptr) + *.0254 +.5)); +} + +png_uint_32 PNGAPI +png_get_x_pixels_per_inch(png_structp png_ptr, png_infop info_ptr) +{ + return ((png_uint_32)((float)png_get_x_pixels_per_meter(png_ptr, info_ptr) + *.0254 +.5)); +} + +png_uint_32 PNGAPI +png_get_y_pixels_per_inch(png_structp png_ptr, png_infop info_ptr) +{ + return ((png_uint_32)((float)png_get_y_pixels_per_meter(png_ptr, info_ptr) + *.0254 +.5)); +} + +float PNGAPI +png_get_x_offset_inches(png_structp png_ptr, png_infop info_ptr) +{ + return ((float)png_get_x_offset_microns(png_ptr, info_ptr) + *.00003937); +} + +float PNGAPI +png_get_y_offset_inches(png_structp png_ptr, png_infop info_ptr) +{ + return ((float)png_get_y_offset_microns(png_ptr, info_ptr) + *.00003937); +} + +#ifdef PNG_pHYs_SUPPORTED +png_uint_32 PNGAPI +png_get_pHYs_dpi(png_structp png_ptr, png_infop info_ptr, + png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type) +{ + png_uint_32 retval = 0; + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) + { + png_debug1(1, "in %s retrieval function", "pHYs"); + + if (res_x != NULL) + { + *res_x = info_ptr->x_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + if (res_y != NULL) + { + *res_y = info_ptr->y_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + if (unit_type != NULL) + { + *unit_type = (int)info_ptr->phys_unit_type; + retval |= PNG_INFO_pHYs; + if (*unit_type == 1) + { + if (res_x != NULL) *res_x = (png_uint_32)(*res_x * .0254 + .50); + if (res_y != NULL) *res_y = (png_uint_32)(*res_y * .0254 + .50); + } + } + } + return (retval); +} +#endif /* PNG_pHYs_SUPPORTED */ +#endif /* PNG_INCH_CONVERSIONS && PNG_FLOATING_POINT_SUPPORTED */ + +/* png_get_channels really belongs in here, too, but it's been around longer */ + +#endif /* PNG_EASY_ACCESS_SUPPORTED */ + +png_byte PNGAPI +png_get_channels(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->channels); + else + return (0); +} + +png_bytep PNGAPI +png_get_signature(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->signature); + else + return (NULL); +} + +#ifdef PNG_bKGD_SUPPORTED +png_uint_32 PNGAPI +png_get_bKGD(png_structp png_ptr, png_infop info_ptr, + png_color_16p *background) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD) + && background != NULL) + { + png_debug1(1, "in %s retrieval function", "bKGD"); + + *background = &(info_ptr->background); + return (PNG_INFO_bKGD); + } + return (0); +} +#endif + +#ifdef PNG_cHRM_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_cHRM(png_structp png_ptr, png_infop info_ptr, + double *white_x, double *white_y, double *red_x, double *red_y, + double *green_x, double *green_y, double *blue_x, double *blue_y) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)) + { + png_debug1(1, "in %s retrieval function", "cHRM"); + + if (white_x != NULL) + *white_x = (double)info_ptr->x_white; + if (white_y != NULL) + *white_y = (double)info_ptr->y_white; + if (red_x != NULL) + *red_x = (double)info_ptr->x_red; + if (red_y != NULL) + *red_y = (double)info_ptr->y_red; + if (green_x != NULL) + *green_x = (double)info_ptr->x_green; + if (green_y != NULL) + *green_y = (double)info_ptr->y_green; + if (blue_x != NULL) + *blue_x = (double)info_ptr->x_blue; + if (blue_y != NULL) + *blue_y = (double)info_ptr->y_blue; + return (PNG_INFO_cHRM); + } + return (0); +} +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_cHRM_fixed(png_structp png_ptr, png_infop info_ptr, + png_fixed_point *white_x, png_fixed_point *white_y, png_fixed_point *red_x, + png_fixed_point *red_y, png_fixed_point *green_x, png_fixed_point *green_y, + png_fixed_point *blue_x, png_fixed_point *blue_y) +{ + png_debug1(1, "in %s retrieval function", "cHRM"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)) + { + if (white_x != NULL) + *white_x = info_ptr->int_x_white; + if (white_y != NULL) + *white_y = info_ptr->int_y_white; + if (red_x != NULL) + *red_x = info_ptr->int_x_red; + if (red_y != NULL) + *red_y = info_ptr->int_y_red; + if (green_x != NULL) + *green_x = info_ptr->int_x_green; + if (green_y != NULL) + *green_y = info_ptr->int_y_green; + if (blue_x != NULL) + *blue_x = info_ptr->int_x_blue; + if (blue_y != NULL) + *blue_y = info_ptr->int_y_blue; + return (PNG_INFO_cHRM); + } + return (0); +} +#endif +#endif + +#ifdef PNG_gAMA_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_gAMA(png_structp png_ptr, png_infop info_ptr, double *file_gamma) +{ + png_debug1(1, "in %s retrieval function", "gAMA"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA) + && file_gamma != NULL) + { + *file_gamma = (double)info_ptr->gamma; + return (PNG_INFO_gAMA); + } + return (0); +} +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, + png_fixed_point *int_file_gamma) +{ + png_debug1(1, "in %s retrieval function", "gAMA"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA) + && int_file_gamma != NULL) + { + *int_file_gamma = info_ptr->int_gamma; + return (PNG_INFO_gAMA); + } + return (0); +} +#endif +#endif + +#ifdef PNG_sRGB_SUPPORTED +png_uint_32 PNGAPI +png_get_sRGB(png_structp png_ptr, png_infop info_ptr, int *file_srgb_intent) +{ + png_debug1(1, "in %s retrieval function", "sRGB"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB) + && file_srgb_intent != NULL) + { + *file_srgb_intent = (int)info_ptr->srgb_intent; + return (PNG_INFO_sRGB); + } + return (0); +} +#endif + +#ifdef PNG_iCCP_SUPPORTED +png_uint_32 PNGAPI +png_get_iCCP(png_structp png_ptr, png_infop info_ptr, + png_charpp name, int *compression_type, + png_charpp profile, png_uint_32 *proflen) +{ + png_debug1(1, "in %s retrieval function", "iCCP"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP) + && name != NULL && profile != NULL && proflen != NULL) + { + *name = info_ptr->iccp_name; + *profile = info_ptr->iccp_profile; + /* Compression_type is a dummy so the API won't have to change + * if we introduce multiple compression types later. + */ + *proflen = (int)info_ptr->iccp_proflen; + *compression_type = (int)info_ptr->iccp_compression; + return (PNG_INFO_iCCP); + } + return (0); +} +#endif + +#ifdef PNG_sPLT_SUPPORTED +png_uint_32 PNGAPI +png_get_sPLT(png_structp png_ptr, png_infop info_ptr, + png_sPLT_tpp spalettes) +{ + if (png_ptr != NULL && info_ptr != NULL && spalettes != NULL) + { + *spalettes = info_ptr->splt_palettes; + return ((png_uint_32)info_ptr->splt_palettes_num); + } + return (0); +} +#endif + +#ifdef PNG_hIST_SUPPORTED +png_uint_32 PNGAPI +png_get_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_16p *hist) +{ + png_debug1(1, "in %s retrieval function", "hIST"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST) + && hist != NULL) + { + *hist = info_ptr->hist; + return (PNG_INFO_hIST); + } + return (0); +} +#endif + +png_uint_32 PNGAPI +png_get_IHDR(png_structp png_ptr, png_infop info_ptr, + png_uint_32 *width, png_uint_32 *height, int *bit_depth, + int *color_type, int *interlace_type, int *compression_type, + int *filter_type) + +{ + png_debug1(1, "in %s retrieval function", "IHDR"); + + if (png_ptr == NULL || info_ptr == NULL || width == NULL || + height == NULL || bit_depth == NULL || color_type == NULL) + return (0); + + *width = info_ptr->width; + *height = info_ptr->height; + *bit_depth = info_ptr->bit_depth; + *color_type = info_ptr->color_type; + + if (compression_type != NULL) + *compression_type = info_ptr->compression_type; + + if (filter_type != NULL) + *filter_type = info_ptr->filter_type; + + if (interlace_type != NULL) + *interlace_type = info_ptr->interlace_type; + + /* This is redundant if we can be sure that the info_ptr values were all + * assigned in png_set_IHDR(). We do the check anyhow in case an + * application has ignored our advice not to mess with the members + * of info_ptr directly. + */ + png_check_IHDR (png_ptr, info_ptr->width, info_ptr->height, + info_ptr->bit_depth, info_ptr->color_type, info_ptr->interlace_type, + info_ptr->compression_type, info_ptr->filter_type); + + return (1); +} + +#ifdef PNG_oFFs_SUPPORTED +png_uint_32 PNGAPI +png_get_oFFs(png_structp png_ptr, png_infop info_ptr, + png_int_32 *offset_x, png_int_32 *offset_y, int *unit_type) +{ + png_debug1(1, "in %s retrieval function", "oFFs"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs) + && offset_x != NULL && offset_y != NULL && unit_type != NULL) + { + *offset_x = info_ptr->x_offset; + *offset_y = info_ptr->y_offset; + *unit_type = (int)info_ptr->offset_unit_type; + return (PNG_INFO_oFFs); + } + return (0); +} +#endif + +#ifdef PNG_pCAL_SUPPORTED +png_uint_32 PNGAPI +png_get_pCAL(png_structp png_ptr, png_infop info_ptr, + png_charp *purpose, png_int_32 *X0, png_int_32 *X1, int *type, int *nparams, + png_charp *units, png_charpp *params) +{ + png_debug1(1, "in %s retrieval function", "pCAL"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL) + && purpose != NULL && X0 != NULL && X1 != NULL && type != NULL && + nparams != NULL && units != NULL && params != NULL) + { + *purpose = info_ptr->pcal_purpose; + *X0 = info_ptr->pcal_X0; + *X1 = info_ptr->pcal_X1; + *type = (int)info_ptr->pcal_type; + *nparams = (int)info_ptr->pcal_nparams; + *units = info_ptr->pcal_units; + *params = info_ptr->pcal_params; + return (PNG_INFO_pCAL); + } + return (0); +} +#endif + +#ifdef PNG_sCAL_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_sCAL(png_structp png_ptr, png_infop info_ptr, + int *unit, double *width, double *height) +{ + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_sCAL)) + { + *unit = info_ptr->scal_unit; + *width = info_ptr->scal_pixel_width; + *height = info_ptr->scal_pixel_height; + return (PNG_INFO_sCAL); + } + return(0); +} +#else +#ifdef PNG_FIXED_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_sCAL_s(png_structp png_ptr, png_infop info_ptr, + int *unit, png_charpp width, png_charpp height) +{ + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_sCAL)) + { + *unit = info_ptr->scal_unit; + *width = info_ptr->scal_s_width; + *height = info_ptr->scal_s_height; + return (PNG_INFO_sCAL); + } + return(0); +} +#endif +#endif +#endif + +#ifdef PNG_pHYs_SUPPORTED +png_uint_32 PNGAPI +png_get_pHYs(png_structp png_ptr, png_infop info_ptr, + png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type) +{ + png_uint_32 retval = 0; + + png_debug1(1, "in %s retrieval function", "pHYs"); + + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_pHYs)) + { + if (res_x != NULL) + { + *res_x = info_ptr->x_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + + if (res_y != NULL) + { + *res_y = info_ptr->y_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + + if (unit_type != NULL) + { + *unit_type = (int)info_ptr->phys_unit_type; + retval |= PNG_INFO_pHYs; + } + } + return (retval); +} +#endif + +png_uint_32 PNGAPI +png_get_PLTE(png_structp png_ptr, png_infop info_ptr, png_colorp *palette, + int *num_palette) +{ + png_debug1(1, "in %s retrieval function", "PLTE"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_PLTE) + && palette != NULL) + { + *palette = info_ptr->palette; + *num_palette = info_ptr->num_palette; + png_debug1(3, "num_palette = %d", *num_palette); + return (PNG_INFO_PLTE); + } + return (0); +} + +#ifdef PNG_sBIT_SUPPORTED +png_uint_32 PNGAPI +png_get_sBIT(png_structp png_ptr, png_infop info_ptr, png_color_8p *sig_bit) +{ + png_debug1(1, "in %s retrieval function", "sBIT"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT) + && sig_bit != NULL) + { + *sig_bit = &(info_ptr->sig_bit); + return (PNG_INFO_sBIT); + } + return (0); +} +#endif + +#ifdef PNG_TEXT_SUPPORTED +png_uint_32 PNGAPI +png_get_text(png_structp png_ptr, png_infop info_ptr, png_textp *text_ptr, + int *num_text) +{ + if (png_ptr != NULL && info_ptr != NULL && info_ptr->num_text > 0) + { + png_debug1(1, "in %s retrieval function", + (png_ptr->chunk_name[0] == '\0' ? "text" + : (png_const_charp)png_ptr->chunk_name)); + + if (text_ptr != NULL) + *text_ptr = info_ptr->text; + + if (num_text != NULL) + *num_text = info_ptr->num_text; + + return ((png_uint_32)info_ptr->num_text); + } + if (num_text != NULL) + *num_text = 0; + return(0); +} +#endif + +#ifdef PNG_tIME_SUPPORTED +png_uint_32 PNGAPI +png_get_tIME(png_structp png_ptr, png_infop info_ptr, png_timep *mod_time) +{ + png_debug1(1, "in %s retrieval function", "tIME"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME) + && mod_time != NULL) + { + *mod_time = &(info_ptr->mod_time); + return (PNG_INFO_tIME); + } + return (0); +} +#endif + +#ifdef PNG_tRNS_SUPPORTED +png_uint_32 PNGAPI +png_get_tRNS(png_structp png_ptr, png_infop info_ptr, + png_bytep *trans_alpha, int *num_trans, png_color_16p *trans_color) +{ + png_uint_32 retval = 0; + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) + { + png_debug1(1, "in %s retrieval function", "tRNS"); + + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (trans_alpha != NULL) + { + *trans_alpha = info_ptr->trans_alpha; + retval |= PNG_INFO_tRNS; + } + + if (trans_color != NULL) + *trans_color = &(info_ptr->trans_color); + } + else /* if (info_ptr->color_type != PNG_COLOR_TYPE_PALETTE) */ + { + if (trans_color != NULL) + { + *trans_color = &(info_ptr->trans_color); + retval |= PNG_INFO_tRNS; + } + + if (trans_alpha != NULL) + *trans_alpha = NULL; + } + if (num_trans != NULL) + { + *num_trans = info_ptr->num_trans; + retval |= PNG_INFO_tRNS; + } + } + return (retval); +} +#endif + +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED +png_uint_32 PNGAPI +png_get_unknown_chunks(png_structp png_ptr, png_infop info_ptr, + png_unknown_chunkpp unknowns) +{ + if (png_ptr != NULL && info_ptr != NULL && unknowns != NULL) + { + *unknowns = info_ptr->unknown_chunks; + return ((png_uint_32)info_ptr->unknown_chunks_num); + } + return (0); +} +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +png_byte PNGAPI +png_get_rgb_to_gray_status (png_structp png_ptr) +{ + return (png_byte)(png_ptr? png_ptr->rgb_to_gray_status : 0); +} +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +png_voidp PNGAPI +png_get_user_chunk_ptr(png_structp png_ptr) +{ + return (png_ptr? png_ptr->user_chunk_ptr : NULL); +} +#endif + +png_size_t PNGAPI +png_get_compression_buffer_size(png_structp png_ptr) +{ + return (png_ptr ? png_ptr->zbuf_size : 0L); +} + + +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +/* These functions were added to libpng 1.2.6 and were enabled + * by default in libpng-1.4.0 */ +png_uint_32 PNGAPI +png_get_user_width_max (png_structp png_ptr) +{ + return (png_ptr? png_ptr->user_width_max : 0); +} +png_uint_32 PNGAPI +png_get_user_height_max (png_structp png_ptr) +{ + return (png_ptr? png_ptr->user_height_max : 0); +} +/* This function was added to libpng 1.4.0 */ +png_uint_32 PNGAPI +png_get_chunk_cache_max (png_structp png_ptr) +{ + return (png_ptr? png_ptr->user_chunk_cache_max : 0); +} +/* This function was added to libpng 1.4.1 */ +png_alloc_size_t PNGAPI +png_get_chunk_malloc_max (png_structp png_ptr) +{ + return (png_ptr? + png_ptr->user_chunk_malloc_max : 0); +} +#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */ + +/* These functions were added to libpng 1.4.0 */ +#ifdef PNG_IO_STATE_SUPPORTED +png_uint_32 PNGAPI +png_get_io_state (png_structp png_ptr) +{ + return png_ptr->io_state; +} + +png_bytep PNGAPI +png_get_io_chunk_name (png_structp png_ptr) +{ + return png_ptr->chunk_name; +} +#endif /* ?PNG_IO_STATE_SUPPORTED */ + +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/reactos/dll/3rdparty/libpng/pngmem.c b/reactos/dll/3rdparty/libpng/pngmem.c new file mode 100644 index 00000000000..c8a3f6f59af --- /dev/null +++ b/reactos/dll/3rdparty/libpng/pngmem.c @@ -0,0 +1,611 @@ + +/* pngmem.c - stub functions for memory allocation + * + * Last changed in libpng 1.4.2 [May 6, 2010] + * Copyright (c) 1998-2010 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file provides a location for all memory allocation. Users who + * need special memory handling are expected to supply replacement + * functions for png_malloc() and png_free(), and to use + * png_create_read_struct_2() and png_create_write_struct_2() to + * identify the replacement functions. + */ + +#define PNG_NO_PEDANTIC_WARNINGS +#include "png.h" +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +#include "pngpriv.h" + +/* Borland DOS special memory handler */ +#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__) +/* If you change this, be sure to change the one in png.h also */ + +/* Allocate memory for a png_struct. The malloc and memset can be replaced + by a single call to calloc() if this is thought to improve performance. */ +png_voidp /* PRIVATE */ +png_create_struct(int type) +{ +#ifdef PNG_USER_MEM_SUPPORTED + return (png_create_struct_2(type, NULL, NULL)); +} + +/* Alternate version of png_create_struct, for use with user-defined malloc. */ +png_voidp /* PRIVATE */ +png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ + png_size_t size; + png_voidp struct_ptr; + + if (type == PNG_STRUCT_INFO) + size = png_sizeof(png_info); + else if (type == PNG_STRUCT_PNG) + size = png_sizeof(png_struct); + else + return (png_get_copyright(NULL)); + +#ifdef PNG_USER_MEM_SUPPORTED + if (malloc_fn != NULL) + { + png_struct dummy_struct; + png_structp png_ptr = &dummy_struct; + png_ptr->mem_ptr=mem_ptr; + struct_ptr = (*(malloc_fn))(png_ptr, (png_uint_32)size); + } + else +#endif /* PNG_USER_MEM_SUPPORTED */ + struct_ptr = (png_voidp)farmalloc(size); + if (struct_ptr != NULL) + png_memset(struct_ptr, 0, size); + return (struct_ptr); +} + +/* Free memory allocated by a png_create_struct() call */ +void /* PRIVATE */ +png_destroy_struct(png_voidp struct_ptr) +{ +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2(struct_ptr, NULL, NULL); +} + +/* Free memory allocated by a png_create_struct() call */ +void /* PRIVATE */ +png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn, + png_voidp mem_ptr) +{ +#endif + if (struct_ptr != NULL) + { +#ifdef PNG_USER_MEM_SUPPORTED + if (free_fn != NULL) + { + png_struct dummy_struct; + png_structp png_ptr = &dummy_struct; + png_ptr->mem_ptr=mem_ptr; + (*(free_fn))(png_ptr, struct_ptr); + return; + } +#endif /* PNG_USER_MEM_SUPPORTED */ + farfree (struct_ptr); + } +} + +/* Allocate memory. For reasonable files, size should never exceed + * 64K. However, zlib may allocate more then 64K if you don't tell + * it not to. See zconf.h and png.h for more information. zlib does + * need to allocate exactly 64K, so whatever you call here must + * have the ability to do that. + * + * Borland seems to have a problem in DOS mode for exactly 64K. + * It gives you a segment with an offset of 8 (perhaps to store its + * memory stuff). zlib doesn't like this at all, so we have to + * detect and deal with it. This code should not be needed in + * Windows or OS/2 modes, and only in 16 bit mode. This code has + * been updated by Alexander Lehmann for version 0.89 to waste less + * memory. + * + * Note that we can't use png_size_t for the "size" declaration, + * since on some systems a png_size_t is a 16-bit quantity, and as a + * result, we would be truncating potentially larger memory requests + * (which should cause a fatal error) and introducing major problems. + */ +png_voidp PNGAPI +png_calloc(png_structp png_ptr, png_alloc_size_t size) +{ + png_voidp ret; + + ret = (png_malloc(png_ptr, size)); + if (ret != NULL) + png_memset(ret,0,(png_size_t)size); + return (ret); +} + +png_voidp PNGAPI +png_malloc(png_structp png_ptr, png_alloc_size_t size) +{ + png_voidp ret; + + if (png_ptr == NULL || size == 0) + return (NULL); + +#ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr->malloc_fn != NULL) + ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size)); + else + ret = (png_malloc_default(png_ptr, size)); + if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out of memory"); + return (ret); +} + +png_voidp PNGAPI +png_malloc_default(png_structp png_ptr, png_alloc_size_t size) +{ + png_voidp ret; +#endif /* PNG_USER_MEM_SUPPORTED */ + + if (png_ptr == NULL || size == 0) + return (NULL); + +#ifdef PNG_MAX_MALLOC_64K + if (size > (png_uint_32)65536L) + { + png_warning(png_ptr, "Cannot Allocate > 64K"); + ret = NULL; + } + else +#endif + + if (size != (size_t)size) + ret = NULL; + else if (size == (png_uint_32)65536L) + { + if (png_ptr->offset_table == NULL) + { + /* Try to see if we need to do any of this fancy stuff */ + ret = farmalloc(size); + if (ret == NULL || ((png_size_t)ret & 0xffff)) + { + int num_blocks; + png_uint_32 total_size; + png_bytep table; + int i; + png_byte huge * hptr; + + if (ret != NULL) + { + farfree(ret); + ret = NULL; + } + + if (png_ptr->zlib_window_bits > 14) + num_blocks = (int)(1 << (png_ptr->zlib_window_bits - 14)); + else + num_blocks = 1; + if (png_ptr->zlib_mem_level >= 7) + num_blocks += (int)(1 << (png_ptr->zlib_mem_level - 7)); + else + num_blocks++; + + total_size = ((png_uint_32)65536L) * (png_uint_32)num_blocks+16; + + table = farmalloc(total_size); + + if (table == NULL) + { +#ifndef PNG_USER_MEM_SUPPORTED + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out Of Memory"); /* Note "O", "M" */ + else + png_warning(png_ptr, "Out Of Memory"); +#endif + return (NULL); + } + + if ((png_size_t)table & 0xfff0) + { +#ifndef PNG_USER_MEM_SUPPORTED + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, + "Farmalloc didn't return normalized pointer"); + else + png_warning(png_ptr, + "Farmalloc didn't return normalized pointer"); +#endif + return (NULL); + } + + png_ptr->offset_table = table; + png_ptr->offset_table_ptr = farmalloc(num_blocks * + png_sizeof(png_bytep)); + + if (png_ptr->offset_table_ptr == NULL) + { +#ifndef PNG_USER_MEM_SUPPORTED + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out Of memory"); /* Note "O", "m" */ + else + png_warning(png_ptr, "Out Of memory"); +#endif + return (NULL); + } + + hptr = (png_byte huge *)table; + if ((png_size_t)hptr & 0xf) + { + hptr = (png_byte huge *)((long)(hptr) & 0xfffffff0L); + hptr = hptr + 16L; /* "hptr += 16L" fails on Turbo C++ 3.0 */ + } + for (i = 0; i < num_blocks; i++) + { + png_ptr->offset_table_ptr[i] = (png_bytep)hptr; + hptr = hptr + (png_uint_32)65536L; /* "+=" fails on TC++3.0 */ + } + + png_ptr->offset_table_number = num_blocks; + png_ptr->offset_table_count = 0; + png_ptr->offset_table_count_free = 0; + } + } + + if (png_ptr->offset_table_count >= png_ptr->offset_table_number) + { +#ifndef PNG_USER_MEM_SUPPORTED + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out of Memory"); /* Note "o" and "M" */ + else + png_warning(png_ptr, "Out of Memory"); +#endif + return (NULL); + } + + ret = png_ptr->offset_table_ptr[png_ptr->offset_table_count++]; + } + else + ret = farmalloc(size); + +#ifndef PNG_USER_MEM_SUPPORTED + if (ret == NULL) + { + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out of memory"); /* Note "o" and "m" */ + else + png_warning(png_ptr, "Out of memory"); /* Note "o" and "m" */ + } +#endif + + return (ret); +} + +/* Free a pointer allocated by png_malloc(). In the default + * configuration, png_ptr is not used, but is passed in case it + * is needed. If ptr is NULL, return without taking any action. + */ +void PNGAPI +png_free(png_structp png_ptr, png_voidp ptr) +{ + if (png_ptr == NULL || ptr == NULL) + return; + +#ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr->free_fn != NULL) + { + (*(png_ptr->free_fn))(png_ptr, ptr); + return; + } + else + png_free_default(png_ptr, ptr); +} + +void PNGAPI +png_free_default(png_structp png_ptr, png_voidp ptr) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ + + if (png_ptr == NULL || ptr == NULL) + return; + + if (png_ptr->offset_table != NULL) + { + int i; + + for (i = 0; i < png_ptr->offset_table_count; i++) + { + if (ptr == png_ptr->offset_table_ptr[i]) + { + ptr = NULL; + png_ptr->offset_table_count_free++; + break; + } + } + if (png_ptr->offset_table_count_free == png_ptr->offset_table_count) + { + farfree(png_ptr->offset_table); + farfree(png_ptr->offset_table_ptr); + png_ptr->offset_table = NULL; + png_ptr->offset_table_ptr = NULL; + } + } + + if (ptr != NULL) + { + farfree(ptr); + } +} + +#else /* Not the Borland DOS special memory handler */ + +/* Allocate memory for a png_struct or a png_info. The malloc and + memset can be replaced by a single call to calloc() if this is thought + to improve performance noticably. */ +png_voidp /* PRIVATE */ +png_create_struct(int type) +{ +#ifdef PNG_USER_MEM_SUPPORTED + return (png_create_struct_2(type, NULL, NULL)); +} + +/* Allocate memory for a png_struct or a png_info. The malloc and + memset can be replaced by a single call to calloc() if this is thought + to improve performance noticably. */ +png_voidp /* PRIVATE */ +png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ + png_size_t size; + png_voidp struct_ptr; + + if (type == PNG_STRUCT_INFO) + size = png_sizeof(png_info); + else if (type == PNG_STRUCT_PNG) + size = png_sizeof(png_struct); + else + return (NULL); + +#ifdef PNG_USER_MEM_SUPPORTED + if (malloc_fn != NULL) + { + png_struct dummy_struct; + png_structp png_ptr = &dummy_struct; + png_ptr->mem_ptr=mem_ptr; + struct_ptr = (*(malloc_fn))(png_ptr, size); + if (struct_ptr != NULL) + png_memset(struct_ptr, 0, size); + return (struct_ptr); + } +#endif /* PNG_USER_MEM_SUPPORTED */ + +#if defined(__TURBOC__) && !defined(__FLAT__) + struct_ptr = (png_voidp)farmalloc(size); +#else +# if defined(_MSC_VER) && defined(MAXSEG_64K) + struct_ptr = (png_voidp)halloc(size, 1); +# else + struct_ptr = (png_voidp)malloc(size); +# endif +#endif + if (struct_ptr != NULL) + png_memset(struct_ptr, 0, size); + + return (struct_ptr); +} + + +/* Free memory allocated by a png_create_struct() call */ +void /* PRIVATE */ +png_destroy_struct(png_voidp struct_ptr) +{ +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2(struct_ptr, NULL, NULL); +} + +/* Free memory allocated by a png_create_struct() call */ +void /* PRIVATE */ +png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn, + png_voidp mem_ptr) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ + if (struct_ptr != NULL) + { +#ifdef PNG_USER_MEM_SUPPORTED + if (free_fn != NULL) + { + png_struct dummy_struct; + png_structp png_ptr = &dummy_struct; + png_ptr->mem_ptr=mem_ptr; + (*(free_fn))(png_ptr, struct_ptr); + return; + } +#endif /* PNG_USER_MEM_SUPPORTED */ +#if defined(__TURBOC__) && !defined(__FLAT__) + farfree(struct_ptr); +#else +# if defined(_MSC_VER) && defined(MAXSEG_64K) + hfree(struct_ptr); +# else + free(struct_ptr); +# endif +#endif + } +} + +/* Allocate memory. For reasonable files, size should never exceed + * 64K. However, zlib may allocate more then 64K if you don't tell + * it not to. See zconf.h and png.h for more information. zlib does + * need to allocate exactly 64K, so whatever you call here must + * have the ability to do that. + */ + +png_voidp PNGAPI +png_calloc(png_structp png_ptr, png_alloc_size_t size) +{ + png_voidp ret; + + ret = (png_malloc(png_ptr, size)); + if (ret != NULL) + png_memset(ret,0,(png_size_t)size); + return (ret); +} + +png_voidp PNGAPI +png_malloc(png_structp png_ptr, png_alloc_size_t size) +{ + png_voidp ret; + +#ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr == NULL || size == 0) + return (NULL); + + if (png_ptr->malloc_fn != NULL) + ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size)); + else + ret = (png_malloc_default(png_ptr, size)); + if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out of Memory"); + return (ret); +} + +png_voidp PNGAPI +png_malloc_default(png_structp png_ptr, png_alloc_size_t size) +{ + png_voidp ret; +#endif /* PNG_USER_MEM_SUPPORTED */ + + if (png_ptr == NULL || size == 0) + return (NULL); + +#ifdef PNG_MAX_MALLOC_64K + if (size > (png_uint_32)65536L) + { +#ifndef PNG_USER_MEM_SUPPORTED + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Cannot Allocate > 64K"); + else +#endif + return NULL; + } +#endif + + /* Check for overflow */ +#if defined(__TURBOC__) && !defined(__FLAT__) + if (size != (unsigned long)size) + ret = NULL; + else + ret = farmalloc(size); +#else +# if defined(_MSC_VER) && defined(MAXSEG_64K) + if (size != (unsigned long)size) + ret = NULL; + else + ret = halloc(size, 1); +# else + if (size != (size_t)size) + ret = NULL; + else + ret = malloc((size_t)size); +# endif +#endif + +#ifndef PNG_USER_MEM_SUPPORTED + if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out of Memory"); +#endif + + return (ret); +} + +/* Free a pointer allocated by png_malloc(). If ptr is NULL, return + * without taking any action. + */ +void PNGAPI +png_free(png_structp png_ptr, png_voidp ptr) +{ + if (png_ptr == NULL || ptr == NULL) + return; + +#ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr->free_fn != NULL) + { + (*(png_ptr->free_fn))(png_ptr, ptr); + return; + } + else + png_free_default(png_ptr, ptr); +} +void PNGAPI +png_free_default(png_structp png_ptr, png_voidp ptr) +{ + if (png_ptr == NULL || ptr == NULL) + return; + +#endif /* PNG_USER_MEM_SUPPORTED */ + +#if defined(__TURBOC__) && !defined(__FLAT__) + farfree(ptr); +#else +# if defined(_MSC_VER) && defined(MAXSEG_64K) + hfree(ptr); +# else + free(ptr); +# endif +#endif +} + +#endif /* Not Borland DOS special memory handler */ + +/* This function was added at libpng version 1.2.3. The png_malloc_warn() + * function will set up png_malloc() to issue a png_warning and return NULL + * instead of issuing a png_error, if it fails to allocate the requested + * memory. + */ +png_voidp PNGAPI +png_malloc_warn(png_structp png_ptr, png_alloc_size_t size) +{ + png_voidp ptr; + png_uint_32 save_flags; + if (png_ptr == NULL) + return (NULL); + + save_flags = png_ptr->flags; + png_ptr->flags|=PNG_FLAG_MALLOC_NULL_MEM_OK; + ptr = (png_voidp)png_malloc((png_structp)png_ptr, size); + png_ptr->flags=save_flags; + return(ptr); +} + + +#ifdef PNG_USER_MEM_SUPPORTED +/* This function is called when the application wants to use another method + * of allocating and freeing memory. + */ +void PNGAPI +png_set_mem_fn(png_structp png_ptr, png_voidp mem_ptr, png_malloc_ptr + malloc_fn, png_free_ptr free_fn) +{ + if (png_ptr != NULL) + { + png_ptr->mem_ptr = mem_ptr; + png_ptr->malloc_fn = malloc_fn; + png_ptr->free_fn = free_fn; + } +} + +/* This function returns a pointer to the mem_ptr associated with the user + * functions. The application should free any memory associated with this + * pointer before png_write_destroy and png_read_destroy are called. + */ +png_voidp PNGAPI +png_get_mem_ptr(png_structp png_ptr) +{ + if (png_ptr == NULL) + return (NULL); + return ((png_voidp)png_ptr->mem_ptr); +} +#endif /* PNG_USER_MEM_SUPPORTED */ +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/reactos/dll/3rdparty/libpng/pngpread.c b/reactos/dll/3rdparty/libpng/pngpread.c new file mode 100644 index 00000000000..3280d34b048 --- /dev/null +++ b/reactos/dll/3rdparty/libpng/pngpread.c @@ -0,0 +1,1765 @@ + +/* pngpread.c - read a png file in push mode + * + * Last changed in libpng 1.4.3 [June 26, 2010] + * Copyright (c) 1998-2010 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#define PNG_NO_PEDANTIC_WARNINGS +#include "png.h" +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +#include "pngpriv.h" + +/* Push model modes */ +#define PNG_READ_SIG_MODE 0 +#define PNG_READ_CHUNK_MODE 1 +#define PNG_READ_IDAT_MODE 2 +#define PNG_SKIP_MODE 3 +#define PNG_READ_tEXt_MODE 4 +#define PNG_READ_zTXt_MODE 5 +#define PNG_READ_DONE_MODE 6 +#define PNG_READ_iTXt_MODE 7 +#define PNG_ERROR_MODE 8 + +void PNGAPI +png_process_data(png_structp png_ptr, png_infop info_ptr, + png_bytep buffer, png_size_t buffer_size) +{ + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_push_restore_buffer(png_ptr, buffer, buffer_size); + + while (png_ptr->buffer_size) + { + png_process_some_data(png_ptr, info_ptr); + } +} + +/* What we do with the incoming data depends on what we were previously + * doing before we ran out of data... + */ +void /* PRIVATE */ +png_process_some_data(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr == NULL) + return; + + switch (png_ptr->process_mode) + { + case PNG_READ_SIG_MODE: + { + png_push_read_sig(png_ptr, info_ptr); + break; + } + + case PNG_READ_CHUNK_MODE: + { + png_push_read_chunk(png_ptr, info_ptr); + break; + } + + case PNG_READ_IDAT_MODE: + { + png_push_read_IDAT(png_ptr); + break; + } + +#ifdef PNG_READ_tEXt_SUPPORTED + case PNG_READ_tEXt_MODE: + { + png_push_read_tEXt(png_ptr, info_ptr); + break; + } + +#endif +#ifdef PNG_READ_zTXt_SUPPORTED + case PNG_READ_zTXt_MODE: + { + png_push_read_zTXt(png_ptr, info_ptr); + break; + } + +#endif +#ifdef PNG_READ_iTXt_SUPPORTED + case PNG_READ_iTXt_MODE: + { + png_push_read_iTXt(png_ptr, info_ptr); + break; + } + +#endif + case PNG_SKIP_MODE: + { + png_push_crc_finish(png_ptr); + break; + } + + default: + { + png_ptr->buffer_size = 0; + break; + } + } +} + +/* Read any remaining signature bytes from the stream and compare them with + * the correct PNG signature. It is possible that this routine is called + * with bytes already read from the signature, either because they have been + * checked by the calling application, or because of multiple calls to this + * routine. + */ +void /* PRIVATE */ +png_push_read_sig(png_structp png_ptr, png_infop info_ptr) +{ + png_size_t num_checked = png_ptr->sig_bytes, + num_to_check = 8 - num_checked; + + if (png_ptr->buffer_size < num_to_check) + { + num_to_check = png_ptr->buffer_size; + } + + png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]), + num_to_check); + png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes + num_to_check); + + if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check)) + { + if (num_checked < 4 && + png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) + png_error(png_ptr, "Not a PNG file"); + else + png_error(png_ptr, "PNG file corrupted by ASCII conversion"); + } + else + { + if (png_ptr->sig_bytes >= 8) + { + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + } + } +} + +void /* PRIVATE */ +png_push_read_chunk(png_structp png_ptr, png_infop info_ptr) +{ + PNG_IHDR; + PNG_IDAT; + PNG_IEND; + PNG_PLTE; +#ifdef PNG_READ_bKGD_SUPPORTED + PNG_bKGD; +#endif +#ifdef PNG_READ_cHRM_SUPPORTED + PNG_cHRM; +#endif +#ifdef PNG_READ_gAMA_SUPPORTED + PNG_gAMA; +#endif +#ifdef PNG_READ_hIST_SUPPORTED + PNG_hIST; +#endif +#ifdef PNG_READ_iCCP_SUPPORTED + PNG_iCCP; +#endif +#ifdef PNG_READ_iTXt_SUPPORTED + PNG_iTXt; +#endif +#ifdef PNG_READ_oFFs_SUPPORTED + PNG_oFFs; +#endif +#ifdef PNG_READ_pCAL_SUPPORTED + PNG_pCAL; +#endif +#ifdef PNG_READ_pHYs_SUPPORTED + PNG_pHYs; +#endif +#ifdef PNG_READ_sBIT_SUPPORTED + PNG_sBIT; +#endif +#ifdef PNG_READ_sCAL_SUPPORTED + PNG_sCAL; +#endif +#ifdef PNG_READ_sRGB_SUPPORTED + PNG_sRGB; +#endif +#ifdef PNG_READ_sPLT_SUPPORTED + PNG_sPLT; +#endif +#ifdef PNG_READ_tEXt_SUPPORTED + PNG_tEXt; +#endif +#ifdef PNG_READ_tIME_SUPPORTED + PNG_tIME; +#endif +#ifdef PNG_READ_tRNS_SUPPORTED + PNG_tRNS; +#endif +#ifdef PNG_READ_zTXt_SUPPORTED + PNG_zTXt; +#endif + + /* First we make sure we have enough data for the 4 byte chunk name + * and the 4 byte chunk length before proceeding with decoding the + * chunk data. To fully decode each of these chunks, we also make + * sure we have enough data in the buffer for the 4 byte CRC at the + * end of every chunk (except IDAT, which is handled separately). + */ + if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER)) + { + png_byte chunk_length[4]; + + if (png_ptr->buffer_size < 8) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_fill_buffer(png_ptr, chunk_length, 4); + png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length); + png_reset_crc(png_ptr); + png_crc_read(png_ptr, png_ptr->chunk_name, 4); + png_check_chunk_name(png_ptr, png_ptr->chunk_name); + png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; + } + + if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + if (png_ptr->mode & PNG_AFTER_IDAT) + png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT; + + if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4)) + { + if (png_ptr->push_length != 13) + png_error(png_ptr, "Invalid IHDR length"); + + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length); + } + + else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length); + + png_ptr->process_mode = PNG_READ_DONE_MODE; + png_push_have_end(png_ptr, info_ptr); + } + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + png_ptr->mode |= PNG_HAVE_IDAT; + + png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length); + + if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) + png_ptr->mode |= PNG_HAVE_PLTE; + + else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + { + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before IDAT"); + + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + png_error(png_ptr, "Missing PLTE before IDAT"); + } + } + +#endif + else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length); + } + + else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + { + /* If we reach an IDAT chunk, this means we have read all of the + * header chunks, and we can start reading the image (or if this + * is called after the image has been read - we have an error). + */ + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before IDAT"); + + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + png_error(png_ptr, "Missing PLTE before IDAT"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + { + if (!(png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) + if (png_ptr->push_length == 0) + return; + + if (png_ptr->mode & PNG_AFTER_IDAT) + png_benign_error(png_ptr, "Too many IDATs found"); + } + + png_ptr->idat_size = png_ptr->push_length; + png_ptr->mode |= PNG_HAVE_IDAT; + png_ptr->process_mode = PNG_READ_IDAT_MODE; + png_push_have_info(png_ptr, info_ptr); + png_ptr->zstream.avail_out = + (uInt) PNG_ROWBYTES(png_ptr->pixel_depth, + png_ptr->iwidth) + 1; + png_ptr->zstream.next_out = png_ptr->row_buf; + return; + } + +#ifdef PNG_READ_gAMA_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_sBIT_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_cHRM_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_sRGB_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_iCCP_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_sPLT_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_tRNS_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_bKGD_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_hIST_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_pHYs_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_oFFs_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length); + } +#endif + +#ifdef PNG_READ_pCAL_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_sCAL_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_tIME_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_tEXt_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_zTXt_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_iTXt_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif + else + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_push_handle_unknown(png_ptr, info_ptr, png_ptr->push_length); + } + + png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; +} + +void /* PRIVATE */ +png_push_crc_skip(png_structp png_ptr, png_uint_32 skip) +{ + png_ptr->process_mode = PNG_SKIP_MODE; + png_ptr->skip_length = skip; +} + +void /* PRIVATE */ +png_push_crc_finish(png_structp png_ptr) +{ + if (png_ptr->skip_length && png_ptr->save_buffer_size) + { + png_size_t save_size; + + if (png_ptr->skip_length < (png_uint_32)png_ptr->save_buffer_size) + save_size = (png_size_t)png_ptr->skip_length; + else + save_size = png_ptr->save_buffer_size; + + png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size); + + png_ptr->skip_length -= save_size; + png_ptr->buffer_size -= save_size; + png_ptr->save_buffer_size -= save_size; + png_ptr->save_buffer_ptr += save_size; + } + if (png_ptr->skip_length && png_ptr->current_buffer_size) + { + png_size_t save_size; + + if (png_ptr->skip_length < (png_uint_32)png_ptr->current_buffer_size) + save_size = (png_size_t)png_ptr->skip_length; + else + save_size = png_ptr->current_buffer_size; + + png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size); + + png_ptr->skip_length -= save_size; + png_ptr->buffer_size -= save_size; + png_ptr->current_buffer_size -= save_size; + png_ptr->current_buffer_ptr += save_size; + } + if (!png_ptr->skip_length) + { + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_crc_finish(png_ptr, 0); + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + } +} + +void PNGAPI +png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length) +{ + png_bytep ptr; + + if (png_ptr == NULL) + return; + + ptr = buffer; + if (png_ptr->save_buffer_size) + { + png_size_t save_size; + + if (length < png_ptr->save_buffer_size) + save_size = length; + else + save_size = png_ptr->save_buffer_size; + + png_memcpy(ptr, png_ptr->save_buffer_ptr, save_size); + length -= save_size; + ptr += save_size; + png_ptr->buffer_size -= save_size; + png_ptr->save_buffer_size -= save_size; + png_ptr->save_buffer_ptr += save_size; + } + if (length && png_ptr->current_buffer_size) + { + png_size_t save_size; + + if (length < png_ptr->current_buffer_size) + save_size = length; + + else + save_size = png_ptr->current_buffer_size; + + png_memcpy(ptr, png_ptr->current_buffer_ptr, save_size); + png_ptr->buffer_size -= save_size; + png_ptr->current_buffer_size -= save_size; + png_ptr->current_buffer_ptr += save_size; + } +} + +void /* PRIVATE */ +png_push_save_buffer(png_structp png_ptr) +{ + if (png_ptr->save_buffer_size) + { + if (png_ptr->save_buffer_ptr != png_ptr->save_buffer) + { + png_size_t i, istop; + png_bytep sp; + png_bytep dp; + + istop = png_ptr->save_buffer_size; + for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer; + i < istop; i++, sp++, dp++) + { + *dp = *sp; + } + } + } + if (png_ptr->save_buffer_size + png_ptr->current_buffer_size > + png_ptr->save_buffer_max) + { + png_size_t new_max; + png_bytep old_buffer; + + if (png_ptr->save_buffer_size > PNG_SIZE_MAX - + (png_ptr->current_buffer_size + 256)) + { + png_error(png_ptr, "Potential overflow of save_buffer"); + } + + new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256; + old_buffer = png_ptr->save_buffer; + png_ptr->save_buffer = (png_bytep)png_malloc_warn(png_ptr, + (png_size_t)new_max); + if (png_ptr->save_buffer == NULL) + { + png_free(png_ptr, old_buffer); + png_error(png_ptr, "Insufficient memory for save_buffer"); + } + png_memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size); + png_free(png_ptr, old_buffer); + png_ptr->save_buffer_max = new_max; + } + if (png_ptr->current_buffer_size) + { + png_memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size, + png_ptr->current_buffer_ptr, png_ptr->current_buffer_size); + png_ptr->save_buffer_size += png_ptr->current_buffer_size; + png_ptr->current_buffer_size = 0; + } + png_ptr->save_buffer_ptr = png_ptr->save_buffer; + png_ptr->buffer_size = 0; +} + +void /* PRIVATE */ +png_push_restore_buffer(png_structp png_ptr, png_bytep buffer, + png_size_t buffer_length) +{ + png_ptr->current_buffer = buffer; + png_ptr->current_buffer_size = buffer_length; + png_ptr->buffer_size = buffer_length + png_ptr->save_buffer_size; + png_ptr->current_buffer_ptr = png_ptr->current_buffer; +} + +void /* PRIVATE */ +png_push_read_IDAT(png_structp png_ptr) +{ + PNG_IDAT; + if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER)) + { + png_byte chunk_length[4]; + + if (png_ptr->buffer_size < 8) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_fill_buffer(png_ptr, chunk_length, 4); + png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length); + png_reset_crc(png_ptr); + png_crc_read(png_ptr, png_ptr->chunk_name, 4); + png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; + + if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + { + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) + png_error(png_ptr, "Not enough compressed data"); + return; + } + + png_ptr->idat_size = png_ptr->push_length; + } + if (png_ptr->idat_size && png_ptr->save_buffer_size) + { + png_size_t save_size; + + if (png_ptr->idat_size < (png_uint_32)png_ptr->save_buffer_size) + { + save_size = (png_size_t)png_ptr->idat_size; + + /* Check for overflow */ + if ((png_uint_32)save_size != png_ptr->idat_size) + png_error(png_ptr, "save_size overflowed in pngpread"); + } + else + save_size = png_ptr->save_buffer_size; + + png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size); + + png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size); + + png_ptr->idat_size -= save_size; + png_ptr->buffer_size -= save_size; + png_ptr->save_buffer_size -= save_size; + png_ptr->save_buffer_ptr += save_size; + } + if (png_ptr->idat_size && png_ptr->current_buffer_size) + { + png_size_t save_size; + + if (png_ptr->idat_size < (png_uint_32)png_ptr->current_buffer_size) + { + save_size = (png_size_t)png_ptr->idat_size; + + /* Check for overflow */ + if ((png_uint_32)save_size != png_ptr->idat_size) + png_error(png_ptr, "save_size overflowed in pngpread"); + } + else + save_size = png_ptr->current_buffer_size; + + png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size); + + png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size); + + png_ptr->idat_size -= save_size; + png_ptr->buffer_size -= save_size; + png_ptr->current_buffer_size -= save_size; + png_ptr->current_buffer_ptr += save_size; + } + if (!png_ptr->idat_size) + { + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_crc_finish(png_ptr, 0); + png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; + png_ptr->mode |= PNG_AFTER_IDAT; + } +} + +void /* PRIVATE */ +png_process_IDAT_data(png_structp png_ptr, png_bytep buffer, + png_size_t buffer_length) +{ + /* The caller checks for a non-zero buffer length. */ + if (!(buffer_length > 0) || buffer == NULL) + png_error(png_ptr, "No IDAT data (internal error)"); + + /* This routine must process all the data it has been given + * before returning, calling the row callback as required to + * handle the uncompressed results. + */ + png_ptr->zstream.next_in = buffer; + png_ptr->zstream.avail_in = (uInt)buffer_length; + + /* Keep going until the decompressed data is all processed + * or the stream marked as finished. + */ + while (png_ptr->zstream.avail_in > 0 && + !(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) + { + int ret; + + /* We have data for zlib, but we must check that zlib + * has somewhere to put the results. It doesn't matter + * if we don't expect any results -- it may be the input + * data is just the LZ end code. + */ + if (!(png_ptr->zstream.avail_out > 0)) + { + png_ptr->zstream.avail_out = + (uInt) PNG_ROWBYTES(png_ptr->pixel_depth, + png_ptr->iwidth) + 1; + png_ptr->zstream.next_out = png_ptr->row_buf; + } + + /* Using Z_SYNC_FLUSH here means that an unterminated + * LZ stream can still be handled (a stream with a missing + * end code), otherwise (Z_NO_FLUSH) a future zlib + * implementation might defer output and, therefore, + * change the current behavior. (See comments in inflate.c + * for why this doesn't happen at present with zlib 1.2.5.) + */ + ret = inflate(&png_ptr->zstream, Z_SYNC_FLUSH); + + /* Check for any failure before proceeding. */ + if (ret != Z_OK && ret != Z_STREAM_END) + { + /* Terminate the decompression. */ + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + + /* This may be a truncated stream (missing or + * damaged end code). Treat that as a warning. + */ + if (png_ptr->row_number >= png_ptr->num_rows || + png_ptr->pass > 6) + png_warning(png_ptr, "Truncated compressed data in IDAT"); + else + png_error(png_ptr, "Decompression error in IDAT"); + + /* Skip the check on unprocessed input */ + return; + } + + /* Did inflate output any data? */ + if (png_ptr->zstream.next_out != png_ptr->row_buf) + { + /* Is this unexpected data after the last row? + * If it is, artificially terminate the LZ output + * here. + */ + if (png_ptr->row_number >= png_ptr->num_rows || + png_ptr->pass > 6) + { + /* Extra data. */ + png_warning(png_ptr, "Extra compressed data in IDAT"); + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + /* Do no more processing; skip the unprocessed + * input check below. + */ + return; + } + + /* Do we have a complete row? */ + if (png_ptr->zstream.avail_out == 0) + png_push_process_row(png_ptr); + } + + /* And check for the end of the stream. */ + if (ret == Z_STREAM_END) + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + } + + /* All the data should have been processed, if anything + * is left at this point we have bytes of IDAT data + * after the zlib end code. + */ + if (png_ptr->zstream.avail_in > 0) + png_warning(png_ptr, "Extra compression data"); +} + +void /* PRIVATE */ +png_push_process_row(png_structp png_ptr) +{ + png_ptr->row_info.color_type = png_ptr->color_type; + png_ptr->row_info.width = png_ptr->iwidth; + png_ptr->row_info.channels = png_ptr->channels; + png_ptr->row_info.bit_depth = png_ptr->bit_depth; + png_ptr->row_info.pixel_depth = png_ptr->pixel_depth; + + png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, + png_ptr->row_info.width); + + png_read_filter_row(png_ptr, &(png_ptr->row_info), + png_ptr->row_buf + 1, png_ptr->prev_row + 1, + (int)(png_ptr->row_buf[0])); + + png_memcpy(png_ptr->prev_row, png_ptr->row_buf, png_ptr->rowbytes + 1); + + if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA)) + png_do_read_transformations(png_ptr); + +#ifdef PNG_READ_INTERLACING_SUPPORTED + /* Blow up interlaced rows to full size */ + if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) + { + if (png_ptr->pass < 6) +/* old interface (pre-1.0.9): + png_do_read_interlace(&(png_ptr->row_info), + png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations); + */ + png_do_read_interlace(png_ptr); + + switch (png_ptr->pass) + { + case 0: + { + int i; + for (i = 0; i < 8 && png_ptr->pass == 0; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); /* Updates png_ptr->pass */ + } + + if (png_ptr->pass == 2) /* Pass 1 might be empty */ + { + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + + if (png_ptr->pass == 4 && png_ptr->height <= 4) + { + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + + if (png_ptr->pass == 6 && png_ptr->height <= 4) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + + break; + } + + case 1: + { + int i; + for (i = 0; i < 8 && png_ptr->pass == 1; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 2) /* Skip top 4 generated rows */ + { + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + + break; + } + + case 2: + { + int i; + + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 4) /* Pass 3 might be empty */ + { + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + + break; + } + + case 3: + { + int i; + + for (i = 0; i < 4 && png_ptr->pass == 3; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 4) /* Skip top two generated rows */ + { + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + + break; + } + + case 4: + { + int i; + + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 6) /* Pass 5 might be empty */ + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + + break; + } + + case 5: + { + int i; + + for (i = 0; i < 2 && png_ptr->pass == 5; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 6) /* Skip top generated row */ + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + + break; + } + case 6: + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + + if (png_ptr->pass != 6) + break; + + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + } + else +#endif + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } +} + +void /* PRIVATE */ +png_read_push_finish_row(png_structp png_ptr) +{ + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + PNG_CONST int FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + PNG_CONST int FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + PNG_CONST int FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + PNG_CONST int FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2}; + + /* Height of interlace block. This is not currently used - if you need + * it, uncomment it here and in png.h + PNG_CONST int FARDATA png_pass_height[] = {8, 8, 4, 4, 2, 2, 1}; + */ + + png_ptr->row_number++; + if (png_ptr->row_number < png_ptr->num_rows) + return; + +#ifdef PNG_READ_INTERLACING_SUPPORTED + if (png_ptr->interlaced) + { + png_ptr->row_number = 0; + png_memset(png_ptr->prev_row, 0, + png_ptr->rowbytes + 1); + do + { + png_ptr->pass++; + if ((png_ptr->pass == 1 && png_ptr->width < 5) || + (png_ptr->pass == 3 && png_ptr->width < 3) || + (png_ptr->pass == 5 && png_ptr->width < 2)) + png_ptr->pass++; + + if (png_ptr->pass > 7) + png_ptr->pass--; + + if (png_ptr->pass >= 7) + break; + + png_ptr->iwidth = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + + if (png_ptr->transformations & PNG_INTERLACE) + break; + + png_ptr->num_rows = (png_ptr->height + + png_pass_yinc[png_ptr->pass] - 1 - + png_pass_ystart[png_ptr->pass]) / + png_pass_yinc[png_ptr->pass]; + + } while (png_ptr->iwidth == 0 || png_ptr->num_rows == 0); + } +#endif /* PNG_READ_INTERLACING_SUPPORTED */ +} + +#ifdef PNG_READ_tEXt_SUPPORTED +void /* PRIVATE */ +png_push_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 + length) +{ + if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) + { + png_error(png_ptr, "Out of place tEXt"); + info_ptr = info_ptr; /* To quiet some compiler warnings */ + } + +#ifdef PNG_MAX_MALLOC_64K + png_ptr->skip_length = 0; /* This may not be necessary */ + + if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */ + { + png_warning(png_ptr, "tEXt chunk too large to fit in memory"); + png_ptr->skip_length = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + png_ptr->current_text = (png_charp)png_malloc(png_ptr, + (png_size_t)(length + 1)); + png_ptr->current_text[length] = '\0'; + png_ptr->current_text_ptr = png_ptr->current_text; + png_ptr->current_text_size = (png_size_t)length; + png_ptr->current_text_left = (png_size_t)length; + png_ptr->process_mode = PNG_READ_tEXt_MODE; +} + +void /* PRIVATE */ +png_push_read_tEXt(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr->buffer_size && png_ptr->current_text_left) + { + png_size_t text_size; + + if (png_ptr->buffer_size < png_ptr->current_text_left) + text_size = png_ptr->buffer_size; + + else + text_size = png_ptr->current_text_left; + + png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); + png_ptr->current_text_left -= text_size; + png_ptr->current_text_ptr += text_size; + } + if (!(png_ptr->current_text_left)) + { + png_textp text_ptr; + png_charp text; + png_charp key; + int ret; + + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_crc_finish(png_ptr); + +#ifdef PNG_MAX_MALLOC_64K + if (png_ptr->skip_length) + return; +#endif + + key = png_ptr->current_text; + + for (text = key; *text; text++) + /* Empty loop */ ; + + if (text < key + png_ptr->current_text_size) + text++; + + text_ptr = (png_textp)png_malloc(png_ptr, + png_sizeof(png_text)); + text_ptr->compression = PNG_TEXT_COMPRESSION_NONE; + text_ptr->key = key; +#ifdef PNG_iTXt_SUPPORTED + text_ptr->lang = NULL; + text_ptr->lang_key = NULL; +#endif + text_ptr->text = text; + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, key); + png_free(png_ptr, text_ptr); + png_ptr->current_text = NULL; + + if (ret) + png_warning(png_ptr, "Insufficient memory to store text chunk"); + } +} +#endif + +#ifdef PNG_READ_zTXt_SUPPORTED +void /* PRIVATE */ +png_push_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 + length) +{ + if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) + { + png_error(png_ptr, "Out of place zTXt"); + info_ptr = info_ptr; /* To quiet some compiler warnings */ + } + +#ifdef PNG_MAX_MALLOC_64K + /* We can't handle zTXt chunks > 64K, since we don't have enough space + * to be able to store the uncompressed data. Actually, the threshold + * is probably around 32K, but it isn't as definite as 64K is. + */ + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "zTXt chunk too large to fit in memory"); + png_push_crc_skip(png_ptr, length); + return; + } +#endif + + png_ptr->current_text = (png_charp)png_malloc(png_ptr, + (png_size_t)(length + 1)); + png_ptr->current_text[length] = '\0'; + png_ptr->current_text_ptr = png_ptr->current_text; + png_ptr->current_text_size = (png_size_t)length; + png_ptr->current_text_left = (png_size_t)length; + png_ptr->process_mode = PNG_READ_zTXt_MODE; +} + +void /* PRIVATE */ +png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr->buffer_size && png_ptr->current_text_left) + { + png_size_t text_size; + + if (png_ptr->buffer_size < (png_uint_32)png_ptr->current_text_left) + text_size = png_ptr->buffer_size; + + else + text_size = png_ptr->current_text_left; + + png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); + png_ptr->current_text_left -= text_size; + png_ptr->current_text_ptr += text_size; + } + if (!(png_ptr->current_text_left)) + { + png_textp text_ptr; + png_charp text; + png_charp key; + int ret; + png_size_t text_size, key_size; + + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_crc_finish(png_ptr); + + key = png_ptr->current_text; + + for (text = key; *text; text++) + /* Empty loop */ ; + + /* zTXt can't have zero text */ + if (text >= key + png_ptr->current_text_size) + { + png_ptr->current_text = NULL; + png_free(png_ptr, key); + return; + } + + text++; + + if (*text != PNG_TEXT_COMPRESSION_zTXt) /* Check compression byte */ + { + png_ptr->current_text = NULL; + png_free(png_ptr, key); + return; + } + + text++; + + png_ptr->zstream.next_in = (png_bytep )text; + png_ptr->zstream.avail_in = (uInt)(png_ptr->current_text_size - + (text - key)); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + + key_size = text - key; + text_size = 0; + text = NULL; + ret = Z_STREAM_END; + + while (png_ptr->zstream.avail_in) + { + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + if (ret != Z_OK && ret != Z_STREAM_END) + { + inflateReset(&png_ptr->zstream); + png_ptr->zstream.avail_in = 0; + png_ptr->current_text = NULL; + png_free(png_ptr, key); + png_free(png_ptr, text); + return; + } + if (!(png_ptr->zstream.avail_out) || ret == Z_STREAM_END) + { + if (text == NULL) + { + text = (png_charp)png_malloc(png_ptr, + (png_ptr->zbuf_size + - png_ptr->zstream.avail_out + key_size + 1)); + + png_memcpy(text + key_size, png_ptr->zbuf, + png_ptr->zbuf_size - png_ptr->zstream.avail_out); + + png_memcpy(text, key, key_size); + + text_size = key_size + png_ptr->zbuf_size - + png_ptr->zstream.avail_out; + + *(text + text_size) = '\0'; + } + else + { + png_charp tmp; + + tmp = text; + text = (png_charp)png_malloc(png_ptr, text_size + + (png_ptr->zbuf_size + - png_ptr->zstream.avail_out + 1)); + + png_memcpy(text, tmp, text_size); + png_free(png_ptr, tmp); + + png_memcpy(text + text_size, png_ptr->zbuf, + png_ptr->zbuf_size - png_ptr->zstream.avail_out); + + text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out; + *(text + text_size) = '\0'; + } + if (ret != Z_STREAM_END) + { + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + } + } + else + { + break; + } + + if (ret == Z_STREAM_END) + break; + } + + inflateReset(&png_ptr->zstream); + png_ptr->zstream.avail_in = 0; + + if (ret != Z_STREAM_END) + { + png_ptr->current_text = NULL; + png_free(png_ptr, key); + png_free(png_ptr, text); + return; + } + + png_ptr->current_text = NULL; + png_free(png_ptr, key); + key = text; + text += key_size; + + text_ptr = (png_textp)png_malloc(png_ptr, + png_sizeof(png_text)); + text_ptr->compression = PNG_TEXT_COMPRESSION_zTXt; + text_ptr->key = key; +#ifdef PNG_iTXt_SUPPORTED + text_ptr->lang = NULL; + text_ptr->lang_key = NULL; +#endif + text_ptr->text = text; + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, key); + png_free(png_ptr, text_ptr); + + if (ret) + png_warning(png_ptr, "Insufficient memory to store text chunk"); + } +} +#endif + +#ifdef PNG_READ_iTXt_SUPPORTED +void /* PRIVATE */ +png_push_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 + length) +{ + if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) + { + png_error(png_ptr, "Out of place iTXt"); + info_ptr = info_ptr; /* To quiet some compiler warnings */ + } + +#ifdef PNG_MAX_MALLOC_64K + png_ptr->skip_length = 0; /* This may not be necessary */ + + if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */ + { + png_warning(png_ptr, "iTXt chunk too large to fit in memory"); + png_ptr->skip_length = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + png_ptr->current_text = (png_charp)png_malloc(png_ptr, + (png_size_t)(length + 1)); + png_ptr->current_text[length] = '\0'; + png_ptr->current_text_ptr = png_ptr->current_text; + png_ptr->current_text_size = (png_size_t)length; + png_ptr->current_text_left = (png_size_t)length; + png_ptr->process_mode = PNG_READ_iTXt_MODE; +} + +void /* PRIVATE */ +png_push_read_iTXt(png_structp png_ptr, png_infop info_ptr) +{ + + if (png_ptr->buffer_size && png_ptr->current_text_left) + { + png_size_t text_size; + + if (png_ptr->buffer_size < png_ptr->current_text_left) + text_size = png_ptr->buffer_size; + + else + text_size = png_ptr->current_text_left; + + png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); + png_ptr->current_text_left -= text_size; + png_ptr->current_text_ptr += text_size; + } + if (!(png_ptr->current_text_left)) + { + png_textp text_ptr; + png_charp key; + int comp_flag; + png_charp lang; + png_charp lang_key; + png_charp text; + int ret; + + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_crc_finish(png_ptr); + +#ifdef PNG_MAX_MALLOC_64K + if (png_ptr->skip_length) + return; +#endif + + key = png_ptr->current_text; + + for (lang = key; *lang; lang++) + /* Empty loop */ ; + + if (lang < key + png_ptr->current_text_size - 3) + lang++; + + comp_flag = *lang++; + lang++; /* Skip comp_type, always zero */ + + for (lang_key = lang; *lang_key; lang_key++) + /* Empty loop */ ; + + lang_key++; /* Skip NUL separator */ + + text=lang_key; + + if (lang_key < key + png_ptr->current_text_size - 1) + { + for (; *text; text++) + /* Empty loop */ ; + } + + if (text < key + png_ptr->current_text_size) + text++; + + text_ptr = (png_textp)png_malloc(png_ptr, + png_sizeof(png_text)); + + text_ptr->compression = comp_flag + 2; + text_ptr->key = key; + text_ptr->lang = lang; + text_ptr->lang_key = lang_key; + text_ptr->text = text; + text_ptr->text_length = 0; + text_ptr->itxt_length = png_strlen(text); + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_ptr->current_text = NULL; + + png_free(png_ptr, text_ptr); + if (ret) + png_warning(png_ptr, "Insufficient memory to store iTXt chunk"); + } +} +#endif + +/* This function is called when we haven't found a handler for this + * chunk. If there isn't a problem with the chunk itself (ie a bad chunk + * name or a critical chunk), the chunk is (currently) silently ignored. + */ +void /* PRIVATE */ +png_push_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 + length) +{ + png_uint_32 skip = 0; + + if (!(png_ptr->chunk_name[0] & 0x20)) + { +#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED + if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != + PNG_HANDLE_CHUNK_ALWAYS +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED + && png_ptr->read_user_chunk_fn == NULL +#endif + ) +#endif + png_chunk_error(png_ptr, "unknown critical chunk"); + + info_ptr = info_ptr; /* To quiet some compiler warnings */ + } + +#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED + if (png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) + { +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "unknown chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + png_memcpy((png_charp)png_ptr->unknown_chunk.name, + (png_charp)png_ptr->chunk_name, + png_sizeof(png_ptr->unknown_chunk.name)); + png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name) - 1] + = '\0'; + + png_ptr->unknown_chunk.size = (png_size_t)length; + + if (length == 0) + png_ptr->unknown_chunk.data = NULL; + + else + { + png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, + (png_size_t)length); + png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length); + } + +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED + if (png_ptr->read_user_chunk_fn != NULL) + { + /* Callback to user unknown chunk handler */ + int ret; + ret = (*(png_ptr->read_user_chunk_fn)) + (png_ptr, &png_ptr->unknown_chunk); + + if (ret < 0) + png_chunk_error(png_ptr, "error in user chunk"); + + if (ret == 0) + { + if (!(png_ptr->chunk_name[0] & 0x20)) + if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != + PNG_HANDLE_CHUNK_ALWAYS) + png_chunk_error(png_ptr, "unknown critical chunk"); + png_set_unknown_chunks(png_ptr, info_ptr, + &png_ptr->unknown_chunk, 1); + } + } + + else +#endif + png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1); + png_free(png_ptr, png_ptr->unknown_chunk.data); + png_ptr->unknown_chunk.data = NULL; + } + + else +#endif + skip=length; + png_push_crc_skip(png_ptr, skip); +} + +void /* PRIVATE */ +png_push_have_info(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr->info_fn != NULL) + (*(png_ptr->info_fn))(png_ptr, info_ptr); +} + +void /* PRIVATE */ +png_push_have_end(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr->end_fn != NULL) + (*(png_ptr->end_fn))(png_ptr, info_ptr); +} + +void /* PRIVATE */ +png_push_have_row(png_structp png_ptr, png_bytep row) +{ + if (png_ptr->row_fn != NULL) + (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number, + (int)png_ptr->pass); +} + +void PNGAPI +png_progressive_combine_row (png_structp png_ptr, + png_bytep old_row, png_bytep new_row) +{ + PNG_CONST int FARDATA png_pass_dsp_mask[7] = + {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff}; + + if (png_ptr == NULL) + return; + + if (new_row != NULL) /* new_row must == png_ptr->row_buf here. */ + png_combine_row(png_ptr, old_row, png_pass_dsp_mask[png_ptr->pass]); +} + +void PNGAPI +png_set_progressive_read_fn(png_structp png_ptr, png_voidp progressive_ptr, + png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn, + png_progressive_end_ptr end_fn) +{ + if (png_ptr == NULL) + return; + + png_ptr->info_fn = info_fn; + png_ptr->row_fn = row_fn; + png_ptr->end_fn = end_fn; + + png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer); +} + +png_voidp PNGAPI +png_get_progressive_ptr(png_structp png_ptr) +{ + if (png_ptr == NULL) + return (NULL); + + return png_ptr->io_ptr; +} +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ diff --git a/reactos/dll/3rdparty/libpng/pngpriv.h b/reactos/dll/3rdparty/libpng/pngpriv.h new file mode 100644 index 00000000000..19b797c7447 --- /dev/null +++ b/reactos/dll/3rdparty/libpng/pngpriv.h @@ -0,0 +1,956 @@ + +/* pngpriv.h - private declarations for use inside libpng + * + * libpng version 1.4.3 - June 26, 2010 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2010 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +/* The symbols declared in this file (including the functions declared + * as PNG_EXTERN) are PRIVATE. They are not part of the libpng public + * interface, and are not recommended for use by regular applications. + * Some of them may become public in the future; others may stay private, + * change in an incompatible way, or even disappear. + * Although the libpng users are not forbidden to include this header, + * they should be well aware of the issues that may arise from doing so. + */ + +#ifndef PNGPRIV_H +#define PNGPRIV_H + +#ifndef PNG_VERSION_INFO_ONLY + +#include + +/* The functions exported by PNG_EXTERN are internal functions, which + * aren't usually used outside the library (as far as I know), so it is + * debatable if they should be exported at all. In the future, when it + * is possible to have run-time registry of chunk-handling functions, + * some of these will be made available again. +#define PNG_EXTERN extern + */ +#define PNG_EXTERN + +/* Other defines specific to compilers can go here. Try to keep + * them inside an appropriate ifdef/endif pair for portability. + */ + +#ifdef PNG_FLOATING_POINT_SUPPORTED +# ifdef MACOS + /* We need to check that hasn't already been included earlier + * as it seems it doesn't agree with , yet we should really use + * if possible. + */ +# if !defined(__MATH_H__) && !defined(__MATH_H) && !defined(__cmath__) +# include +# endif +# else +# include +# endif +# if defined(_AMIGA) && defined(__SASC) && defined(_M68881) + /* Amiga SAS/C: We must include builtin FPU functions when compiling using + * MATH=68881 + */ +# include +# endif +#endif + +/* Codewarrior on NT has linking problems without this. */ +#if (defined(__MWERKS__) && defined(WIN32)) || defined(__STDC__) +# define PNG_ALWAYS_EXTERN +#endif + +/* This provides the non-ANSI (far) memory allocation routines. */ +#if defined(__TURBOC__) && defined(__MSDOS__) +# include +# include +#endif + +#if defined(WIN32) || defined(_Windows) || defined(_WINDOWS) || \ + defined(_WIN32) || defined(__WIN32__) +# include /* defines _WINDOWS_ macro */ +/* I have no idea why is this necessary... */ +# ifdef _MSC_VER +# include +# endif +#endif + +/* Various modes of operation. Note that after an init, mode is set to + * zero automatically when the structure is created. + */ +#define PNG_HAVE_IHDR 0x01 +#define PNG_HAVE_PLTE 0x02 +#define PNG_HAVE_IDAT 0x04 +#define PNG_AFTER_IDAT 0x08 /* Have complete zlib datastream */ +#define PNG_HAVE_IEND 0x10 +#define PNG_HAVE_gAMA 0x20 +#define PNG_HAVE_cHRM 0x40 +#define PNG_HAVE_sRGB 0x80 +#define PNG_HAVE_CHUNK_HEADER 0x100 +#define PNG_WROTE_tIME 0x200 +#define PNG_WROTE_INFO_BEFORE_PLTE 0x400 +#define PNG_BACKGROUND_IS_GRAY 0x800 +#define PNG_HAVE_PNG_SIGNATURE 0x1000 +#define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000 /* Have another chunk after IDAT */ + +/* Flags for the transformations the PNG library does on the image data */ +#define PNG_BGR 0x0001 +#define PNG_INTERLACE 0x0002 +#define PNG_PACK 0x0004 +#define PNG_SHIFT 0x0008 +#define PNG_SWAP_BYTES 0x0010 +#define PNG_INVERT_MONO 0x0020 +#define PNG_QUANTIZE 0x0040 /* formerly PNG_DITHER */ +#define PNG_BACKGROUND 0x0080 +#define PNG_BACKGROUND_EXPAND 0x0100 + /* 0x0200 unused */ +#define PNG_16_TO_8 0x0400 +#define PNG_RGBA 0x0800 +#define PNG_EXPAND 0x1000 +#define PNG_GAMMA 0x2000 +#define PNG_GRAY_TO_RGB 0x4000 +#define PNG_FILLER 0x8000L +#define PNG_PACKSWAP 0x10000L +#define PNG_SWAP_ALPHA 0x20000L +#define PNG_STRIP_ALPHA 0x40000L +#define PNG_INVERT_ALPHA 0x80000L +#define PNG_USER_TRANSFORM 0x100000L +#define PNG_RGB_TO_GRAY_ERR 0x200000L +#define PNG_RGB_TO_GRAY_WARN 0x400000L +#define PNG_RGB_TO_GRAY 0x600000L /* two bits, RGB_TO_GRAY_ERR|WARN */ + /* 0x800000L Unused */ +#define PNG_ADD_ALPHA 0x1000000L /* Added to libpng-1.2.7 */ +#define PNG_EXPAND_tRNS 0x2000000L /* Added to libpng-1.2.9 */ + /* 0x4000000L unused */ + /* 0x8000000L unused */ + /* 0x10000000L unused */ + /* 0x20000000L unused */ + /* 0x40000000L unused */ + +/* Flags for png_create_struct */ +#define PNG_STRUCT_PNG 0x0001 +#define PNG_STRUCT_INFO 0x0002 + +/* Scaling factor for filter heuristic weighting calculations */ +#define PNG_WEIGHT_SHIFT 8 +#define PNG_WEIGHT_FACTOR (1<<(PNG_WEIGHT_SHIFT)) +#define PNG_COST_SHIFT 3 +#define PNG_COST_FACTOR (1<<(PNG_COST_SHIFT)) + +/* Flags for the png_ptr->flags rather than declaring a byte for each one */ +#define PNG_FLAG_ZLIB_CUSTOM_STRATEGY 0x0001 +#define PNG_FLAG_ZLIB_CUSTOM_LEVEL 0x0002 +#define PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL 0x0004 +#define PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS 0x0008 +#define PNG_FLAG_ZLIB_CUSTOM_METHOD 0x0010 +#define PNG_FLAG_ZLIB_FINISHED 0x0020 +#define PNG_FLAG_ROW_INIT 0x0040 +#define PNG_FLAG_FILLER_AFTER 0x0080 +#define PNG_FLAG_CRC_ANCILLARY_USE 0x0100 +#define PNG_FLAG_CRC_ANCILLARY_NOWARN 0x0200 +#define PNG_FLAG_CRC_CRITICAL_USE 0x0400 +#define PNG_FLAG_CRC_CRITICAL_IGNORE 0x0800 + /* 0x1000 unused */ + /* 0x2000 unused */ + /* 0x4000 unused */ +#define PNG_FLAG_KEEP_UNKNOWN_CHUNKS 0x8000L +#define PNG_FLAG_KEEP_UNSAFE_CHUNKS 0x10000L +#define PNG_FLAG_LIBRARY_MISMATCH 0x20000L +#define PNG_FLAG_STRIP_ERROR_NUMBERS 0x40000L +#define PNG_FLAG_STRIP_ERROR_TEXT 0x80000L +#define PNG_FLAG_MALLOC_NULL_MEM_OK 0x100000L +#define PNG_FLAG_ADD_ALPHA 0x200000L /* Added to libpng-1.2.8 */ +#define PNG_FLAG_STRIP_ALPHA 0x400000L /* Added to libpng-1.2.8 */ +#define PNG_FLAG_BENIGN_ERRORS_WARN 0x800000L /* Added to libpng-1.4.0 */ + /* 0x1000000L unused */ + /* 0x2000000L unused */ + /* 0x4000000L unused */ + /* 0x8000000L unused */ + /* 0x10000000L unused */ + /* 0x20000000L unused */ + /* 0x40000000L unused */ + +#define PNG_FLAG_CRC_ANCILLARY_MASK (PNG_FLAG_CRC_ANCILLARY_USE | \ + PNG_FLAG_CRC_ANCILLARY_NOWARN) + +#define PNG_FLAG_CRC_CRITICAL_MASK (PNG_FLAG_CRC_CRITICAL_USE | \ + PNG_FLAG_CRC_CRITICAL_IGNORE) + +#define PNG_FLAG_CRC_MASK (PNG_FLAG_CRC_ANCILLARY_MASK | \ + PNG_FLAG_CRC_CRITICAL_MASK) + +/* Save typing and make code easier to understand */ + +#define PNG_COLOR_DIST(c1, c2) (abs((int)((c1).red) - (int)((c2).red)) + \ + abs((int)((c1).green) - (int)((c2).green)) + \ + abs((int)((c1).blue) - (int)((c2).blue))) + +/* Added to libpng-1.2.6 JB */ +#define PNG_ROWBYTES(pixel_bits, width) \ + ((pixel_bits) >= 8 ? \ + ((png_size_t)(width) * (((png_size_t)(pixel_bits)) >> 3)) : \ + (( ((png_size_t)(width) * ((png_size_t)(pixel_bits))) + 7) >> 3) ) + +/* PNG_OUT_OF_RANGE returns true if value is outside the range + * ideal-delta..ideal+delta. Each argument is evaluated twice. + * "ideal" and "delta" should be constants, normally simple + * integers, "value" a variable. Added to libpng-1.2.6 JB + */ +#define PNG_OUT_OF_RANGE(value, ideal, delta) \ + ( (value) < (ideal)-(delta) || (value) > (ideal)+(delta) ) + +/* Constant strings for known chunk types. If you need to add a chunk, + * define the name here, and add an invocation of the macro wherever it's + * needed. + */ +#define PNG_IHDR PNG_CONST png_byte png_IHDR[5] = { 73, 72, 68, 82, '\0'} +#define PNG_IDAT PNG_CONST png_byte png_IDAT[5] = { 73, 68, 65, 84, '\0'} +#define PNG_IEND PNG_CONST png_byte png_IEND[5] = { 73, 69, 78, 68, '\0'} +#define PNG_PLTE PNG_CONST png_byte png_PLTE[5] = { 80, 76, 84, 69, '\0'} +#define PNG_bKGD PNG_CONST png_byte png_bKGD[5] = { 98, 75, 71, 68, '\0'} +#define PNG_cHRM PNG_CONST png_byte png_cHRM[5] = { 99, 72, 82, 77, '\0'} +#define PNG_gAMA PNG_CONST png_byte png_gAMA[5] = {103, 65, 77, 65, '\0'} +#define PNG_hIST PNG_CONST png_byte png_hIST[5] = {104, 73, 83, 84, '\0'} +#define PNG_iCCP PNG_CONST png_byte png_iCCP[5] = {105, 67, 67, 80, '\0'} +#define PNG_iTXt PNG_CONST png_byte png_iTXt[5] = {105, 84, 88, 116, '\0'} +#define PNG_oFFs PNG_CONST png_byte png_oFFs[5] = {111, 70, 70, 115, '\0'} +#define PNG_pCAL PNG_CONST png_byte png_pCAL[5] = {112, 67, 65, 76, '\0'} +#define PNG_sCAL PNG_CONST png_byte png_sCAL[5] = {115, 67, 65, 76, '\0'} +#define PNG_pHYs PNG_CONST png_byte png_pHYs[5] = {112, 72, 89, 115, '\0'} +#define PNG_sBIT PNG_CONST png_byte png_sBIT[5] = {115, 66, 73, 84, '\0'} +#define PNG_sPLT PNG_CONST png_byte png_sPLT[5] = {115, 80, 76, 84, '\0'} +#define PNG_sRGB PNG_CONST png_byte png_sRGB[5] = {115, 82, 71, 66, '\0'} +#define PNG_sTER PNG_CONST png_byte png_sTER[5] = {115, 84, 69, 82, '\0'} +#define PNG_tEXt PNG_CONST png_byte png_tEXt[5] = {116, 69, 88, 116, '\0'} +#define PNG_tIME PNG_CONST png_byte png_tIME[5] = {116, 73, 77, 69, '\0'} +#define PNG_tRNS PNG_CONST png_byte png_tRNS[5] = {116, 82, 78, 83, '\0'} +#define PNG_zTXt PNG_CONST png_byte png_zTXt[5] = {122, 84, 88, 116, '\0'} + + +/* Inhibit C++ name-mangling for libpng functions but not for system calls. */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* These functions are used internally in the code. They generally + * shouldn't be used unless you are writing code to add or replace some + * functionality in libpng. More information about most functions can + * be found in the files where the functions are located. + */ + +/* Allocate memory for an internal libpng struct */ +PNG_EXTERN png_voidp png_create_struct PNGARG((int type)); + +/* Free memory from internal libpng struct */ +PNG_EXTERN void png_destroy_struct PNGARG((png_voidp struct_ptr)); + +PNG_EXTERN png_voidp png_create_struct_2 PNGARG((int type, png_malloc_ptr + malloc_fn, png_voidp mem_ptr)); +PNG_EXTERN void png_destroy_struct_2 PNGARG((png_voidp struct_ptr, + png_free_ptr free_fn, png_voidp mem_ptr)); + +/* Free any memory that info_ptr points to and reset struct. */ +PNG_EXTERN void png_info_destroy PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +/* Function to allocate memory for zlib. PNGAPI is disallowed. */ +PNG_EXTERN voidpf png_zalloc PNGARG((voidpf png_ptr, uInt items, uInt size)); + +/* Function to free memory for zlib. PNGAPI is disallowed. */ +PNG_EXTERN void png_zfree PNGARG((voidpf png_ptr, voidpf ptr)); + +/* Next four functions are used internally as callbacks. PNGAPI is required + * but not PNG_EXPORT. PNGAPI added at libpng version 1.2.3. */ + +PNG_EXTERN void PNGAPI png_default_read_data PNGARG((png_structp png_ptr, + png_bytep data, png_size_t length)); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +PNG_EXTERN void PNGAPI png_push_fill_buffer PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t length)); +#endif + +PNG_EXTERN void PNGAPI png_default_write_data PNGARG((png_structp png_ptr, + png_bytep data, png_size_t length)); + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +#ifdef PNG_STDIO_SUPPORTED +PNG_EXTERN void PNGAPI png_default_flush PNGARG((png_structp png_ptr)); +#endif +#endif + +/* Reset the CRC variable */ +PNG_EXTERN void png_reset_crc PNGARG((png_structp png_ptr)); + +/* Write the "data" buffer to whatever output you are using */ +PNG_EXTERN void png_write_data PNGARG((png_structp png_ptr, png_bytep data, + png_size_t length)); + +/* Read the chunk header (length + type name) */ +PNG_EXTERN png_uint_32 png_read_chunk_header PNGARG((png_structp png_ptr)); + +/* Read data from whatever input you are using into the "data" buffer */ +PNG_EXTERN void png_read_data PNGARG((png_structp png_ptr, png_bytep data, + png_size_t length)); + +/* Read bytes into buf, and update png_ptr->crc */ +PNG_EXTERN void png_crc_read PNGARG((png_structp png_ptr, png_bytep buf, + png_size_t length)); + +/* Decompress data in a chunk that uses compression */ +#if defined(PNG_zTXt_SUPPORTED) || defined(PNG_iTXt_SUPPORTED) || \ + defined(PNG_iCCP_SUPPORTED) || defined(PNG_sPLT_SUPPORTED) +PNG_EXTERN void png_decompress_chunk PNGARG((png_structp png_ptr, + int comp_type, png_size_t chunklength, png_size_t prefix_length, + png_size_t *data_length)); +#endif + +/* Read "skip" bytes, read the file crc, and (optionally) verify png_ptr->crc */ +PNG_EXTERN int png_crc_finish PNGARG((png_structp png_ptr, png_uint_32 skip)); + +/* Read the CRC from the file and compare it to the libpng calculated CRC */ +PNG_EXTERN int png_crc_error PNGARG((png_structp png_ptr)); + +/* Calculate the CRC over a section of data. Note that we are only + * passing a maximum of 64K on systems that have this as a memory limit, + * since this is the maximum buffer size we can specify. + */ +PNG_EXTERN void png_calculate_crc PNGARG((png_structp png_ptr, png_bytep ptr, + png_size_t length)); + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +PNG_EXTERN void png_flush PNGARG((png_structp png_ptr)); +#endif + +/* Write various chunks */ + +/* Write the IHDR chunk, and update the png_struct with the necessary + * information. + */ +PNG_EXTERN void png_write_IHDR PNGARG((png_structp png_ptr, png_uint_32 width, + png_uint_32 height, + int bit_depth, int color_type, int compression_method, int filter_method, + int interlace_method)); + +PNG_EXTERN void png_write_PLTE PNGARG((png_structp png_ptr, png_colorp palette, + png_uint_32 num_pal)); + +PNG_EXTERN void png_write_IDAT PNGARG((png_structp png_ptr, png_bytep data, + png_size_t length)); + +PNG_EXTERN void png_write_IEND PNGARG((png_structp png_ptr)); + +#ifdef PNG_WRITE_gAMA_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +PNG_EXTERN void png_write_gAMA PNGARG((png_structp png_ptr, double file_gamma)); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +PNG_EXTERN void png_write_gAMA_fixed PNGARG((png_structp png_ptr, + png_fixed_point file_gamma)); +#endif +#endif + +#ifdef PNG_WRITE_sBIT_SUPPORTED +PNG_EXTERN void png_write_sBIT PNGARG((png_structp png_ptr, png_color_8p sbit, + int color_type)); +#endif + +#ifdef PNG_WRITE_cHRM_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +PNG_EXTERN void png_write_cHRM PNGARG((png_structp png_ptr, + double white_x, double white_y, + double red_x, double red_y, double green_x, double green_y, + double blue_x, double blue_y)); +#endif +PNG_EXTERN void png_write_cHRM_fixed PNGARG((png_structp png_ptr, + png_fixed_point int_white_x, png_fixed_point int_white_y, + png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point + int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x, + png_fixed_point int_blue_y)); +#endif + +#ifdef PNG_WRITE_sRGB_SUPPORTED +PNG_EXTERN void png_write_sRGB PNGARG((png_structp png_ptr, + int intent)); +#endif + +#ifdef PNG_WRITE_iCCP_SUPPORTED +PNG_EXTERN void png_write_iCCP PNGARG((png_structp png_ptr, + png_charp name, int compression_type, + png_charp profile, int proflen)); + /* Note to maintainer: profile should be png_bytep */ +#endif + +#ifdef PNG_WRITE_sPLT_SUPPORTED +PNG_EXTERN void png_write_sPLT PNGARG((png_structp png_ptr, + png_sPLT_tp palette)); +#endif + +#ifdef PNG_WRITE_tRNS_SUPPORTED +PNG_EXTERN void png_write_tRNS PNGARG((png_structp png_ptr, png_bytep trans, + png_color_16p values, int number, int color_type)); +#endif + +#ifdef PNG_WRITE_bKGD_SUPPORTED +PNG_EXTERN void png_write_bKGD PNGARG((png_structp png_ptr, + png_color_16p values, int color_type)); +#endif + +#ifdef PNG_WRITE_hIST_SUPPORTED +PNG_EXTERN void png_write_hIST PNGARG((png_structp png_ptr, png_uint_16p hist, + int num_hist)); +#endif + +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \ + defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) +PNG_EXTERN png_size_t png_check_keyword PNGARG((png_structp png_ptr, + png_charp key, png_charpp new_key)); +#endif + +#ifdef PNG_WRITE_tEXt_SUPPORTED +PNG_EXTERN void png_write_tEXt PNGARG((png_structp png_ptr, png_charp key, + png_charp text, png_size_t text_len)); +#endif + +#ifdef PNG_WRITE_zTXt_SUPPORTED +PNG_EXTERN void png_write_zTXt PNGARG((png_structp png_ptr, png_charp key, + png_charp text, png_size_t text_len, int compression)); +#endif + +#ifdef PNG_WRITE_iTXt_SUPPORTED +PNG_EXTERN void png_write_iTXt PNGARG((png_structp png_ptr, + int compression, png_charp key, png_charp lang, png_charp lang_key, + png_charp text)); +#endif + +#ifdef PNG_TEXT_SUPPORTED /* Added at version 1.0.14 and 1.2.4 */ +PNG_EXTERN int png_set_text_2 PNGARG((png_structp png_ptr, + png_infop info_ptr, png_textp text_ptr, int num_text)); +#endif + +#ifdef PNG_WRITE_oFFs_SUPPORTED +PNG_EXTERN void png_write_oFFs PNGARG((png_structp png_ptr, + png_int_32 x_offset, png_int_32 y_offset, int unit_type)); +#endif + +#ifdef PNG_WRITE_pCAL_SUPPORTED +PNG_EXTERN void png_write_pCAL PNGARG((png_structp png_ptr, png_charp purpose, + png_int_32 X0, png_int_32 X1, int type, int nparams, + png_charp units, png_charpp params)); +#endif + +#ifdef PNG_WRITE_pHYs_SUPPORTED +PNG_EXTERN void png_write_pHYs PNGARG((png_structp png_ptr, + png_uint_32 x_pixels_per_unit, png_uint_32 y_pixels_per_unit, + int unit_type)); +#endif + +#ifdef PNG_WRITE_tIME_SUPPORTED +PNG_EXTERN void png_write_tIME PNGARG((png_structp png_ptr, + png_timep mod_time)); +#endif + +#ifdef PNG_WRITE_sCAL_SUPPORTED +#if defined(PNG_FLOATING_POINT_SUPPORTED) && defined(PNG_STDIO_SUPPORTED) +PNG_EXTERN void png_write_sCAL PNGARG((png_structp png_ptr, + int unit, double width, double height)); +#else +#ifdef PNG_FIXED_POINT_SUPPORTED +PNG_EXTERN void png_write_sCAL_s PNGARG((png_structp png_ptr, + int unit, png_charp width, png_charp height)); +#endif +#endif +#endif + +/* Called when finished processing a row of data */ +PNG_EXTERN void png_write_finish_row PNGARG((png_structp png_ptr)); + +/* Internal use only. Called before first row of data */ +PNG_EXTERN void png_write_start_row PNGARG((png_structp png_ptr)); + +#ifdef PNG_READ_GAMMA_SUPPORTED +PNG_EXTERN void png_build_gamma_table PNGARG((png_structp png_ptr, + png_byte bit_depth)); +#endif + +/* Combine a row of data, dealing with alpha, etc. if requested */ +PNG_EXTERN void png_combine_row PNGARG((png_structp png_ptr, png_bytep row, + int mask)); + +#ifdef PNG_READ_INTERLACING_SUPPORTED +/* Expand an interlaced row */ +/* OLD pre-1.0.9 interface: +PNG_EXTERN void png_do_read_interlace PNGARG((png_row_infop row_info, + png_bytep row, int pass, png_uint_32 transformations)); + */ +PNG_EXTERN void png_do_read_interlace PNGARG((png_structp png_ptr)); +#endif + +/* GRR TO DO (2.0 or whenever): simplify other internal calling interfaces */ + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED +/* Grab pixels out of a row for an interlaced pass */ +PNG_EXTERN void png_do_write_interlace PNGARG((png_row_infop row_info, + png_bytep row, int pass)); +#endif + +/* Unfilter a row */ +PNG_EXTERN void png_read_filter_row PNGARG((png_structp png_ptr, + png_row_infop row_info, png_bytep row, png_bytep prev_row, int filter)); + +/* Choose the best filter to use and filter the row data */ +PNG_EXTERN void png_write_find_filter PNGARG((png_structp png_ptr, + png_row_infop row_info)); + +/* Write out the filtered row. */ +PNG_EXTERN void png_write_filtered_row PNGARG((png_structp png_ptr, + png_bytep filtered_row)); +/* Finish a row while reading, dealing with interlacing passes, etc. */ +PNG_EXTERN void png_read_finish_row PNGARG((png_structp png_ptr)); + +/* Initialize the row buffers, etc. */ +PNG_EXTERN void png_read_start_row PNGARG((png_structp png_ptr)); +/* Optional call to update the users info structure */ +PNG_EXTERN void png_read_transform_info PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +/* These are the functions that do the transformations */ +#ifdef PNG_READ_FILLER_SUPPORTED +PNG_EXTERN void png_do_read_filler PNGARG((png_row_infop row_info, + png_bytep row, png_uint_32 filler, png_uint_32 flags)); +#endif + +#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED +PNG_EXTERN void png_do_read_swap_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED +PNG_EXTERN void png_do_write_swap_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED +PNG_EXTERN void png_do_read_invert_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED +PNG_EXTERN void png_do_write_invert_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#if defined(PNG_WRITE_FILLER_SUPPORTED) || \ + defined(PNG_READ_STRIP_ALPHA_SUPPORTED) +PNG_EXTERN void png_do_strip_filler PNGARG((png_row_infop row_info, + png_bytep row, png_uint_32 flags)); +#endif + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +PNG_EXTERN void png_do_swap PNGARG((png_row_infop row_info, png_bytep row)); +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) || \ + defined(PNG_WRITE_PACKSWAP_SUPPORTED) +PNG_EXTERN void png_do_packswap PNGARG((png_row_infop row_info, png_bytep row)); +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +PNG_EXTERN int png_do_rgb_to_gray PNGARG((png_structp png_ptr, png_row_infop + row_info, png_bytep row)); +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED +PNG_EXTERN void png_do_gray_to_rgb PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#ifdef PNG_READ_PACK_SUPPORTED +PNG_EXTERN void png_do_unpack PNGARG((png_row_infop row_info, png_bytep row)); +#endif + +#ifdef PNG_READ_SHIFT_SUPPORTED +PNG_EXTERN void png_do_unshift PNGARG((png_row_infop row_info, png_bytep row, + png_color_8p sig_bits)); +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +PNG_EXTERN void png_do_invert PNGARG((png_row_infop row_info, png_bytep row)); +#endif + +#ifdef PNG_READ_16_TO_8_SUPPORTED +PNG_EXTERN void png_do_chop PNGARG((png_row_infop row_info, png_bytep row)); +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +PNG_EXTERN void png_do_quantize PNGARG((png_row_infop row_info, + png_bytep row, png_bytep palette_lookup, png_bytep quantize_lookup)); + +# ifdef PNG_CORRECT_PALETTE_SUPPORTED +PNG_EXTERN void png_correct_palette PNGARG((png_structp png_ptr, + png_colorp palette, int num_palette)); +# endif +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +PNG_EXTERN void png_do_bgr PNGARG((png_row_infop row_info, png_bytep row)); +#endif + +#ifdef PNG_WRITE_PACK_SUPPORTED +PNG_EXTERN void png_do_pack PNGARG((png_row_infop row_info, + png_bytep row, png_uint_32 bit_depth)); +#endif + +#ifdef PNG_WRITE_SHIFT_SUPPORTED +PNG_EXTERN void png_do_shift PNGARG((png_row_infop row_info, png_bytep row, + png_color_8p bit_depth)); +#endif + +#ifdef PNG_READ_BACKGROUND_SUPPORTED +#ifdef PNG_READ_GAMMA_SUPPORTED +PNG_EXTERN void png_do_background PNGARG((png_row_infop row_info, png_bytep row, + png_color_16p trans_color, png_color_16p background, + png_color_16p background_1, + png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1, + png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1, + png_uint_16pp gamma_16_to_1, int gamma_shift)); +#else +PNG_EXTERN void png_do_background PNGARG((png_row_infop row_info, png_bytep row, + png_color_16p trans_color, png_color_16p background)); +#endif +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED +PNG_EXTERN void png_do_gamma PNGARG((png_row_infop row_info, png_bytep row, + png_bytep gamma_table, png_uint_16pp gamma_16_table, + int gamma_shift)); +#endif + +#ifdef PNG_READ_EXPAND_SUPPORTED +PNG_EXTERN void png_do_expand_palette PNGARG((png_row_infop row_info, + png_bytep row, png_colorp palette, png_bytep trans, int num_trans)); +PNG_EXTERN void png_do_expand PNGARG((png_row_infop row_info, + png_bytep row, png_color_16p trans_value)); +#endif + +/* The following decodes the appropriate chunks, and does error correction, + * then calls the appropriate callback for the chunk if it is valid. + */ + +/* Decode the IHDR chunk */ +PNG_EXTERN void png_handle_IHDR PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +PNG_EXTERN void png_handle_PLTE PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +PNG_EXTERN void png_handle_IEND PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); + +#ifdef PNG_READ_bKGD_SUPPORTED +PNG_EXTERN void png_handle_bKGD PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_cHRM_SUPPORTED +PNG_EXTERN void png_handle_cHRM PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_gAMA_SUPPORTED +PNG_EXTERN void png_handle_gAMA PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_hIST_SUPPORTED +PNG_EXTERN void png_handle_hIST PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_iCCP_SUPPORTED +extern void png_handle_iCCP PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif /* PNG_READ_iCCP_SUPPORTED */ + +#ifdef PNG_READ_iTXt_SUPPORTED +PNG_EXTERN void png_handle_iTXt PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_oFFs_SUPPORTED +PNG_EXTERN void png_handle_oFFs PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_pCAL_SUPPORTED +PNG_EXTERN void png_handle_pCAL PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_pHYs_SUPPORTED +PNG_EXTERN void png_handle_pHYs PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_sBIT_SUPPORTED +PNG_EXTERN void png_handle_sBIT PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_sCAL_SUPPORTED +PNG_EXTERN void png_handle_sCAL PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_sPLT_SUPPORTED +extern void png_handle_sPLT PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif /* PNG_READ_sPLT_SUPPORTED */ + +#ifdef PNG_READ_sRGB_SUPPORTED +PNG_EXTERN void png_handle_sRGB PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_tEXt_SUPPORTED +PNG_EXTERN void png_handle_tEXt PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_tIME_SUPPORTED +PNG_EXTERN void png_handle_tIME PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_tRNS_SUPPORTED +PNG_EXTERN void png_handle_tRNS PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_zTXt_SUPPORTED +PNG_EXTERN void png_handle_zTXt PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +PNG_EXTERN void png_handle_unknown PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); + +PNG_EXTERN void png_check_chunk_name PNGARG((png_structp png_ptr, + png_bytep chunk_name)); + +/* Handle the transformations for reading and writing */ +PNG_EXTERN void png_do_read_transformations PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_do_write_transformations PNGARG((png_structp png_ptr)); + +PNG_EXTERN void png_init_read_transformations PNGARG((png_structp png_ptr)); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +PNG_EXTERN void png_push_read_chunk PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_read_sig PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_check_crc PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_crc_skip PNGARG((png_structp png_ptr, + png_uint_32 length)); +PNG_EXTERN void png_push_crc_finish PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_save_buffer PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_restore_buffer PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t buffer_length)); +PNG_EXTERN void png_push_read_IDAT PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_process_IDAT_data PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t buffer_length)); +PNG_EXTERN void png_push_process_row PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_handle_unknown PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_have_info PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_have_end PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_have_row PNGARG((png_structp png_ptr, png_bytep row)); +PNG_EXTERN void png_push_read_end PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_process_some_data PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_read_push_finish_row PNGARG((png_structp png_ptr)); +#ifdef PNG_READ_tEXt_SUPPORTED +PNG_EXTERN void png_push_handle_tEXt PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_read_tEXt PNGARG((png_structp png_ptr, + png_infop info_ptr)); +#endif +#ifdef PNG_READ_zTXt_SUPPORTED +PNG_EXTERN void png_push_handle_zTXt PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_read_zTXt PNGARG((png_structp png_ptr, + png_infop info_ptr)); +#endif +#ifdef PNG_READ_iTXt_SUPPORTED +PNG_EXTERN void png_push_handle_iTXt PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_read_iTXt PNGARG((png_structp png_ptr, + png_infop info_ptr)); +#endif + +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + +#ifdef PNG_MNG_FEATURES_SUPPORTED +PNG_EXTERN void png_do_read_intrapixel PNGARG((png_row_infop row_info, + png_bytep row)); +PNG_EXTERN void png_do_write_intrapixel PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +/* Added at libpng version 1.4.0 */ +#ifdef PNG_cHRM_SUPPORTED +PNG_EXTERN int png_check_cHRM_fixed PNGARG((png_structp png_ptr, + png_fixed_point int_white_x, png_fixed_point int_white_y, + png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point + int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x, + png_fixed_point int_blue_y)); +#endif + +#ifdef PNG_cHRM_SUPPORTED +#ifdef PNG_CHECK_cHRM_SUPPORTED +/* Added at libpng version 1.2.34 and 1.4.0 */ +PNG_EXTERN void png_64bit_product PNGARG((long v1, long v2, + unsigned long *hi_product, unsigned long *lo_product)); +#endif +#endif + +/* Added at libpng version 1.4.0 */ +PNG_EXTERN void png_check_IHDR PNGARG((png_structp png_ptr, + png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_type, int compression_type, + int filter_type)); + +/* Free all memory used by the read (old method - NOT DLL EXPORTED) */ +extern void png_read_destroy PNGARG((png_structp png_ptr, png_infop info_ptr, + png_infop end_info_ptr)); + +/* Free any memory used in png_ptr struct (old method - NOT DLL EXPORTED) */ +extern void png_write_destroy PNGARG((png_structp png_ptr)); + +#ifdef USE_FAR_KEYWORD /* memory model conversion function */ +extern void *png_far_to_near PNGARG((png_structp png_ptr,png_voidp ptr, + int check)); +#endif /* USE_FAR_KEYWORD */ + +/* Define PNG_DEBUG at compile time for debugging information. Higher + * numbers for PNG_DEBUG mean more debugging information. This has + * only been added since version 0.95 so it is not implemented throughout + * libpng yet, but more support will be added as needed. + */ +#ifdef PNG_DEBUG +#if (PNG_DEBUG > 0) +#if !defined(PNG_DEBUG_FILE) && defined(_MSC_VER) +#include +#if (PNG_DEBUG > 1) +#ifndef _DEBUG +# define _DEBUG +#endif +#ifndef png_debug +#define png_debug(l,m) _RPT0(_CRT_WARN,m PNG_STRING_NEWLINE) +#endif +#ifndef png_debug1 +#define png_debug1(l,m,p1) _RPT1(_CRT_WARN,m PNG_STRING_NEWLINE,p1) +#endif +#ifndef png_debug2 +#define png_debug2(l,m,p1,p2) _RPT2(_CRT_WARN,m PNG_STRING_NEWLINE,p1,p2) +#endif +#endif +#else /* PNG_DEBUG_FILE || !_MSC_VER */ +#ifndef PNG_DEBUG_FILE +#define PNG_DEBUG_FILE stderr +#endif /* PNG_DEBUG_FILE */ + +#if (PNG_DEBUG > 1) +/* Note: ["%s"m PNG_STRING_NEWLINE] probably does not work on + * non-ISO compilers + */ +# ifdef __STDC__ +# ifndef png_debug +# define png_debug(l,m) \ + { \ + int num_tabs=l; \ + fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":"")))); \ + } +# endif +# ifndef png_debug1 +# define png_debug1(l,m,p1) \ + { \ + int num_tabs=l; \ + fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1); \ + } +# endif +# ifndef png_debug2 +# define png_debug2(l,m,p1,p2) \ + { \ + int num_tabs=l; \ + fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1,p2); \ + } +# endif +# else /* __STDC __ */ +# ifndef png_debug +# define png_debug(l,m) \ + { \ + int num_tabs=l; \ + char format[256]; \ + snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \ + m,PNG_STRING_NEWLINE); \ + fprintf(PNG_DEBUG_FILE,format); \ + } +# endif +# ifndef png_debug1 +# define png_debug1(l,m,p1) \ + { \ + int num_tabs=l; \ + char format[256]; \ + snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \ + m,PNG_STRING_NEWLINE); \ + fprintf(PNG_DEBUG_FILE,format,p1); \ + } +# endif +# ifndef png_debug2 +# define png_debug2(l,m,p1,p2) \ + { \ + int num_tabs=l; \ + char format[256]; \ + snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \ + m,PNG_STRING_NEWLINE); \ + fprintf(PNG_DEBUG_FILE,format,p1,p2); \ + } +# endif +# endif /* __STDC __ */ +#endif /* (PNG_DEBUG > 1) */ + +#endif /* _MSC_VER */ +#endif /* (PNG_DEBUG > 0) */ +#endif /* PNG_DEBUG */ +#ifndef png_debug +#define png_debug(l, m) +#endif +#ifndef png_debug1 +#define png_debug1(l, m, p1) +#endif +#ifndef png_debug2 +#define png_debug2(l, m, p1, p2) +#endif + +/* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */ + +#ifdef __cplusplus +} +#endif + +#endif /* PNG_VERSION_INFO_ONLY */ +#endif /* PNGPRIV_H */ diff --git a/reactos/dll/3rdparty/libpng/pngread.c b/reactos/dll/3rdparty/libpng/pngread.c new file mode 100644 index 00000000000..92060d2bc6c --- /dev/null +++ b/reactos/dll/3rdparty/libpng/pngread.c @@ -0,0 +1,1361 @@ + +/* pngread.c - read a PNG file + * + * Last changed in libpng 1.4.1 [February 25, 2010] + * Copyright (c) 1998-2010 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file contains routines that an application calls directly to + * read a PNG file or stream. + */ + +#define PNG_NO_PEDANTIC_WARNINGS +#include "png.h" +#ifdef PNG_READ_SUPPORTED +#include "pngpriv.h" + + +/* Create a PNG structure for reading, and allocate any memory needed. */ +png_structp PNGAPI +png_create_read_struct(png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn) +{ + +#ifdef PNG_USER_MEM_SUPPORTED + return (png_create_read_struct_2(user_png_ver, error_ptr, error_fn, + warn_fn, NULL, NULL, NULL)); +} + +/* Alternate create PNG structure for reading, and allocate any memory + * needed. + */ +png_structp PNGAPI +png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ + +#ifdef PNG_SETJMP_SUPPORTED + volatile +#endif + png_structp png_ptr; + volatile int png_cleanup_needed = 0; + +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + jmp_buf jmpbuf; +#endif +#endif + + int i; + + png_debug(1, "in png_create_read_struct"); + +#ifdef PNG_USER_MEM_SUPPORTED + png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG, + malloc_fn, mem_ptr); +#else + png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); +#endif + if (png_ptr == NULL) + return (NULL); + + /* Added at libpng-1.2.6 */ +#ifdef PNG_USER_LIMITS_SUPPORTED + png_ptr->user_width_max = PNG_USER_WIDTH_MAX; + png_ptr->user_height_max = PNG_USER_HEIGHT_MAX; +# ifdef PNG_USER_CHUNK_CACHE_MAX + /* Added at libpng-1.2.43 and 1.4.0 */ + png_ptr->user_chunk_cache_max = PNG_USER_CHUNK_CACHE_MAX; +# endif +# ifdef PNG_SET_USER_CHUNK_MALLOC_MAX + /* Added at libpng-1.2.43 and 1.4.1 */ + png_ptr->user_chunk_malloc_max = PNG_USER_CHUNK_MALLOC_MAX; +# endif +#endif + +#ifdef PNG_SETJMP_SUPPORTED +/* Applications that neglect to set up their own setjmp() and then + encounter a png_error() will longjmp here. Since the jmpbuf is + then meaningless we abort instead of returning. */ +#ifdef USE_FAR_KEYWORD + if (setjmp(jmpbuf)) +#else + if (setjmp(png_jmpbuf(png_ptr))) /* Sets longjmp to match setjmp */ +#endif + PNG_ABORT(); +#ifdef USE_FAR_KEYWORD + png_memcpy(png_jmpbuf(png_ptr), jmpbuf, png_sizeof(jmp_buf)); +#endif +#endif /* PNG_SETJMP_SUPPORTED */ + +#ifdef PNG_USER_MEM_SUPPORTED + png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn); +#endif + + png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn); + + if (user_png_ver) + { + i = 0; + do + { + if (user_png_ver[i] != png_libpng_ver[i]) + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; + } while (png_libpng_ver[i++]); + } + else + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; + + + if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) + { + /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so + * we must recompile any applications that use any older library version. + * For versions after libpng 1.0, we will be compatible, so we need + * only check the first digit. + */ + if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] || + (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) || + (user_png_ver[0] == '0' && user_png_ver[2] < '9')) + { +#ifdef PNG_STDIO_SUPPORTED + char msg[80]; + if (user_png_ver) + { + png_snprintf(msg, 80, + "Application was compiled with png.h from libpng-%.20s", + user_png_ver); + png_warning(png_ptr, msg); + } + png_snprintf(msg, 80, + "Application is running with png.c from libpng-%.20s", + png_libpng_ver); + png_warning(png_ptr, msg); +#endif +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + png_ptr->flags = 0; +#endif + png_warning(png_ptr, + "Incompatible libpng version in application and library"); + + png_cleanup_needed = 1; + } + } + + if (!png_cleanup_needed) + { + /* Initialize zbuf - compression buffer */ + png_ptr->zbuf_size = PNG_ZBUF_SIZE; + png_ptr->zbuf = (png_bytep)png_malloc_warn(png_ptr, + png_ptr->zbuf_size); + if (png_ptr->zbuf == NULL) + png_cleanup_needed = 1; + } + png_ptr->zstream.zalloc = png_zalloc; + png_ptr->zstream.zfree = png_zfree; + png_ptr->zstream.opaque = (voidpf)png_ptr; + + if (!png_cleanup_needed) + { + switch (inflateInit(&png_ptr->zstream)) + { + case Z_OK: /* Do nothing */ break; + case Z_MEM_ERROR: + case Z_STREAM_ERROR: png_warning(png_ptr, "zlib memory error"); + png_cleanup_needed = 1; break; + case Z_VERSION_ERROR: png_warning(png_ptr, "zlib version error"); + png_cleanup_needed = 1; break; + default: png_warning(png_ptr, "Unknown zlib error"); + png_cleanup_needed = 1; + } + } + + if (png_cleanup_needed) + { + /* Clean up PNG structure and deallocate any memory. */ + png_free(png_ptr, png_ptr->zbuf); + png_ptr->zbuf = NULL; +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)png_ptr, + (png_free_ptr)free_fn, (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)png_ptr); +#endif + return (NULL); + } + + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + + png_set_read_fn(png_ptr, NULL, NULL); + + + return (png_ptr); +} + + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the information before the actual image data. This has been + * changed in v0.90 to allow reading a file that already has the magic + * bytes read from the stream. You can tell libpng how many bytes have + * been read from the beginning of the stream (up to the maximum of 8) + * via png_set_sig_bytes(), and we will only check the remaining bytes + * here. The application can then have access to the signature bytes we + * read if it is determined that this isn't a valid PNG file. + */ +void PNGAPI +png_read_info(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_read_info"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + /* If we haven't checked all of the PNG signature bytes, do so now. */ + if (png_ptr->sig_bytes < 8) + { + png_size_t num_checked = png_ptr->sig_bytes, + num_to_check = 8 - num_checked; + +#ifdef PNG_IO_STATE_SUPPORTED + png_ptr->io_state = PNG_IO_READING | PNG_IO_SIGNATURE; +#endif + + png_read_data(png_ptr, &(info_ptr->signature[num_checked]), num_to_check); + png_ptr->sig_bytes = 8; + + if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check)) + { + if (num_checked < 4 && + png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) + png_error(png_ptr, "Not a PNG file"); + else + png_error(png_ptr, "PNG file corrupted by ASCII conversion"); + } + if (num_checked < 3) + png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; + } + + for (;;) + { + PNG_IHDR; + PNG_IDAT; + PNG_IEND; + PNG_PLTE; +#ifdef PNG_READ_bKGD_SUPPORTED + PNG_bKGD; +#endif +#ifdef PNG_READ_cHRM_SUPPORTED + PNG_cHRM; +#endif +#ifdef PNG_READ_gAMA_SUPPORTED + PNG_gAMA; +#endif +#ifdef PNG_READ_hIST_SUPPORTED + PNG_hIST; +#endif +#ifdef PNG_READ_iCCP_SUPPORTED + PNG_iCCP; +#endif +#ifdef PNG_READ_iTXt_SUPPORTED + PNG_iTXt; +#endif +#ifdef PNG_READ_oFFs_SUPPORTED + PNG_oFFs; +#endif +#ifdef PNG_READ_pCAL_SUPPORTED + PNG_pCAL; +#endif +#ifdef PNG_READ_pHYs_SUPPORTED + PNG_pHYs; +#endif +#ifdef PNG_READ_sBIT_SUPPORTED + PNG_sBIT; +#endif +#ifdef PNG_READ_sCAL_SUPPORTED + PNG_sCAL; +#endif +#ifdef PNG_READ_sPLT_SUPPORTED + PNG_sPLT; +#endif +#ifdef PNG_READ_sRGB_SUPPORTED + PNG_sRGB; +#endif +#ifdef PNG_READ_tEXt_SUPPORTED + PNG_tEXt; +#endif +#ifdef PNG_READ_tIME_SUPPORTED + PNG_tIME; +#endif +#ifdef PNG_READ_tRNS_SUPPORTED + PNG_tRNS; +#endif +#ifdef PNG_READ_zTXt_SUPPORTED + PNG_zTXt; +#endif + png_uint_32 length = png_read_chunk_header(png_ptr); + PNG_CONST png_bytep chunk_name = png_ptr->chunk_name; + + /* This should be a binary subdivision search or a hash for + * matching the chunk name rather than a linear search. + */ + if (!png_memcmp(chunk_name, png_IDAT, 4)) + if (png_ptr->mode & PNG_AFTER_IDAT) + png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT; + + if (!png_memcmp(chunk_name, png_IHDR, 4)) + png_handle_IHDR(png_ptr, info_ptr, length); + else if (!png_memcmp(chunk_name, png_IEND, 4)) + png_handle_IEND(png_ptr, info_ptr, length); +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + else if (png_handle_as_unknown(png_ptr, chunk_name)) + { + if (!png_memcmp(chunk_name, png_IDAT, 4)) + png_ptr->mode |= PNG_HAVE_IDAT; + png_handle_unknown(png_ptr, info_ptr, length); + if (!png_memcmp(chunk_name, png_PLTE, 4)) + png_ptr->mode |= PNG_HAVE_PLTE; + else if (!png_memcmp(chunk_name, png_IDAT, 4)) + { + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before IDAT"); + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + png_error(png_ptr, "Missing PLTE before IDAT"); + break; + } + } +#endif + else if (!png_memcmp(chunk_name, png_PLTE, 4)) + png_handle_PLTE(png_ptr, info_ptr, length); + else if (!png_memcmp(chunk_name, png_IDAT, 4)) + { + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before IDAT"); + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + png_error(png_ptr, "Missing PLTE before IDAT"); + + png_ptr->idat_size = length; + png_ptr->mode |= PNG_HAVE_IDAT; + break; + } +#ifdef PNG_READ_bKGD_SUPPORTED + else if (!png_memcmp(chunk_name, png_bKGD, 4)) + png_handle_bKGD(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_cHRM_SUPPORTED + else if (!png_memcmp(chunk_name, png_cHRM, 4)) + png_handle_cHRM(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_gAMA_SUPPORTED + else if (!png_memcmp(chunk_name, png_gAMA, 4)) + png_handle_gAMA(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_hIST_SUPPORTED + else if (!png_memcmp(chunk_name, png_hIST, 4)) + png_handle_hIST(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_oFFs_SUPPORTED + else if (!png_memcmp(chunk_name, png_oFFs, 4)) + png_handle_oFFs(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_pCAL_SUPPORTED + else if (!png_memcmp(chunk_name, png_pCAL, 4)) + png_handle_pCAL(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_sCAL_SUPPORTED + else if (!png_memcmp(chunk_name, png_sCAL, 4)) + png_handle_sCAL(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_pHYs_SUPPORTED + else if (!png_memcmp(chunk_name, png_pHYs, 4)) + png_handle_pHYs(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_sBIT_SUPPORTED + else if (!png_memcmp(chunk_name, png_sBIT, 4)) + png_handle_sBIT(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_sRGB_SUPPORTED + else if (!png_memcmp(chunk_name, png_sRGB, 4)) + png_handle_sRGB(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_iCCP_SUPPORTED + else if (!png_memcmp(chunk_name, png_iCCP, 4)) + png_handle_iCCP(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_sPLT_SUPPORTED + else if (!png_memcmp(chunk_name, png_sPLT, 4)) + png_handle_sPLT(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_tEXt_SUPPORTED + else if (!png_memcmp(chunk_name, png_tEXt, 4)) + png_handle_tEXt(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_tIME_SUPPORTED + else if (!png_memcmp(chunk_name, png_tIME, 4)) + png_handle_tIME(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_tRNS_SUPPORTED + else if (!png_memcmp(chunk_name, png_tRNS, 4)) + png_handle_tRNS(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_zTXt_SUPPORTED + else if (!png_memcmp(chunk_name, png_zTXt, 4)) + png_handle_zTXt(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_iTXt_SUPPORTED + else if (!png_memcmp(chunk_name, png_iTXt, 4)) + png_handle_iTXt(png_ptr, info_ptr, length); +#endif + else + png_handle_unknown(png_ptr, info_ptr, length); + } +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +/* Optional call to update the users info_ptr structure */ +void PNGAPI +png_read_update_info(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_read_update_info"); + + if (png_ptr == NULL) + return; + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) + png_read_start_row(png_ptr); + else + png_warning(png_ptr, + "Ignoring extra png_read_update_info() call; row buffer not reallocated"); + + png_read_transform_info(png_ptr, info_ptr); +} + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Initialize palette, background, etc, after transformations + * are set, but before any reading takes place. This allows + * the user to obtain a gamma-corrected palette, for example. + * If the user doesn't call this, we will do it ourselves. + */ +void PNGAPI +png_start_read_image(png_structp png_ptr) +{ + png_debug(1, "in png_start_read_image"); + + if (png_ptr == NULL) + return; + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) + png_read_start_row(png_ptr); +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +void PNGAPI +png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row) +{ + PNG_IDAT; + PNG_CONST int png_pass_dsp_mask[7] = {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, + 0xff}; + PNG_CONST int png_pass_mask[7] = {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff}; + int ret; + + if (png_ptr == NULL) + return; + + png_debug2(1, "in png_read_row (row %lu, pass %d)", + (unsigned long) png_ptr->row_number, png_ptr->pass); + + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) + png_read_start_row(png_ptr); + if (png_ptr->row_number == 0 && png_ptr->pass == 0) + { + /* Check for transforms that have been set but were defined out */ +#if defined(PNG_WRITE_INVERT_SUPPORTED) && !defined(PNG_READ_INVERT_SUPPORTED) + if (png_ptr->transformations & PNG_INVERT_MONO) + png_warning(png_ptr, "PNG_READ_INVERT_SUPPORTED is not defined"); +#endif +#if defined(PNG_WRITE_FILLER_SUPPORTED) && !defined(PNG_READ_FILLER_SUPPORTED) + if (png_ptr->transformations & PNG_FILLER) + png_warning(png_ptr, "PNG_READ_FILLER_SUPPORTED is not defined"); +#endif +#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \ + !defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + png_warning(png_ptr, "PNG_READ_PACKSWAP_SUPPORTED is not defined"); +#endif +#if defined(PNG_WRITE_PACK_SUPPORTED) && !defined(PNG_READ_PACK_SUPPORTED) + if (png_ptr->transformations & PNG_PACK) + png_warning(png_ptr, "PNG_READ_PACK_SUPPORTED is not defined"); +#endif +#if defined(PNG_WRITE_SHIFT_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) + if (png_ptr->transformations & PNG_SHIFT) + png_warning(png_ptr, "PNG_READ_SHIFT_SUPPORTED is not defined"); +#endif +#if defined(PNG_WRITE_BGR_SUPPORTED) && !defined(PNG_READ_BGR_SUPPORTED) + if (png_ptr->transformations & PNG_BGR) + png_warning(png_ptr, "PNG_READ_BGR_SUPPORTED is not defined"); +#endif +#if defined(PNG_WRITE_SWAP_SUPPORTED) && !defined(PNG_READ_SWAP_SUPPORTED) + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_warning(png_ptr, "PNG_READ_SWAP_SUPPORTED is not defined"); +#endif + } + +#ifdef PNG_READ_INTERLACING_SUPPORTED + /* If interlaced and we do not need a new row, combine row and return */ + if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) + { + switch (png_ptr->pass) + { + case 0: + if (png_ptr->row_number & 0x07) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + case 1: + if ((png_ptr->row_number & 0x07) || png_ptr->width < 5) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + case 2: + if ((png_ptr->row_number & 0x07) != 4) + { + if (dsp_row != NULL && (png_ptr->row_number & 4)) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + case 3: + if ((png_ptr->row_number & 3) || png_ptr->width < 3) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + case 4: + if ((png_ptr->row_number & 3) != 2) + { + if (dsp_row != NULL && (png_ptr->row_number & 2)) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + case 5: + if ((png_ptr->row_number & 1) || png_ptr->width < 2) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + case 6: + if (!(png_ptr->row_number & 1)) + { + png_read_finish_row(png_ptr); + return; + } + break; + } + } +#endif + + if (!(png_ptr->mode & PNG_HAVE_IDAT)) + png_error(png_ptr, "Invalid attempt to read row data"); + + png_ptr->zstream.next_out = png_ptr->row_buf; + png_ptr->zstream.avail_out = + (uInt)(PNG_ROWBYTES(png_ptr->pixel_depth, + png_ptr->iwidth) + 1); + do + { + if (!(png_ptr->zstream.avail_in)) + { + while (!png_ptr->idat_size) + { + png_crc_finish(png_ptr, 0); + + png_ptr->idat_size = png_read_chunk_header(png_ptr); + if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + png_error(png_ptr, "Not enough image data"); + } + png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_in = png_ptr->zbuf; + if (png_ptr->zbuf_size > png_ptr->idat_size) + png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size; + png_crc_read(png_ptr, png_ptr->zbuf, + (png_size_t)png_ptr->zstream.avail_in); + png_ptr->idat_size -= png_ptr->zstream.avail_in; + } + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + if (ret == Z_STREAM_END) + { + if (png_ptr->zstream.avail_out || png_ptr->zstream.avail_in || + png_ptr->idat_size) + png_benign_error(png_ptr, "Extra compressed data"); + png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + break; + } + if (ret != Z_OK) + png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg : + "Decompression error"); + + } while (png_ptr->zstream.avail_out); + + png_ptr->row_info.color_type = png_ptr->color_type; + png_ptr->row_info.width = png_ptr->iwidth; + png_ptr->row_info.channels = png_ptr->channels; + png_ptr->row_info.bit_depth = png_ptr->bit_depth; + png_ptr->row_info.pixel_depth = png_ptr->pixel_depth; + png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, + png_ptr->row_info.width); + + if (png_ptr->row_buf[0]) + png_read_filter_row(png_ptr, &(png_ptr->row_info), + png_ptr->row_buf + 1, png_ptr->prev_row + 1, + (int)(png_ptr->row_buf[0])); + + png_memcpy(png_ptr->prev_row, png_ptr->row_buf, png_ptr->rowbytes + 1); + +#ifdef PNG_MNG_FEATURES_SUPPORTED + if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING)) + { + /* Intrapixel differencing */ + png_do_read_intrapixel(&(png_ptr->row_info), png_ptr->row_buf + 1); + } +#endif + + + if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA)) + png_do_read_transformations(png_ptr); + +#ifdef PNG_READ_INTERLACING_SUPPORTED + /* Blow up interlaced rows to full size */ + if (png_ptr->interlaced && + (png_ptr->transformations & PNG_INTERLACE)) + { + if (png_ptr->pass < 6) + /* Old interface (pre-1.0.9): + * png_do_read_interlace(&(png_ptr->row_info), + * png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations); + */ + png_do_read_interlace(png_ptr); + + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + if (row != NULL) + png_combine_row(png_ptr, row, + png_pass_mask[png_ptr->pass]); + } + else +#endif + { + if (row != NULL) + png_combine_row(png_ptr, row, 0xff); + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, 0xff); + } + png_read_finish_row(png_ptr); + + if (png_ptr->read_row_fn != NULL) + (*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass); +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read one or more rows of image data. If the image is interlaced, + * and png_set_interlace_handling() has been called, the rows need to + * contain the contents of the rows from the previous pass. If the + * image has alpha or transparency, and png_handle_alpha()[*] has been + * called, the rows contents must be initialized to the contents of the + * screen. + * + * "row" holds the actual image, and pixels are placed in it + * as they arrive. If the image is displayed after each pass, it will + * appear to "sparkle" in. "display_row" can be used to display a + * "chunky" progressive image, with finer detail added as it becomes + * available. If you do not want this "chunky" display, you may pass + * NULL for display_row. If you do not want the sparkle display, and + * you have not called png_handle_alpha(), you may pass NULL for rows. + * If you have called png_handle_alpha(), and the image has either an + * alpha channel or a transparency chunk, you must provide a buffer for + * rows. In this case, you do not have to provide a display_row buffer + * also, but you may. If the image is not interlaced, or if you have + * not called png_set_interlace_handling(), the display_row buffer will + * be ignored, so pass NULL to it. + * + * [*] png_handle_alpha() does not exist yet, as of this version of libpng + */ + +void PNGAPI +png_read_rows(png_structp png_ptr, png_bytepp row, + png_bytepp display_row, png_uint_32 num_rows) +{ + png_uint_32 i; + png_bytepp rp; + png_bytepp dp; + + png_debug(1, "in png_read_rows"); + + if (png_ptr == NULL) + return; + rp = row; + dp = display_row; + if (rp != NULL && dp != NULL) + for (i = 0; i < num_rows; i++) + { + png_bytep rptr = *rp++; + png_bytep dptr = *dp++; + + png_read_row(png_ptr, rptr, dptr); + } + else if (rp != NULL) + for (i = 0; i < num_rows; i++) + { + png_bytep rptr = *rp; + png_read_row(png_ptr, rptr, NULL); + rp++; + } + else if (dp != NULL) + for (i = 0; i < num_rows; i++) + { + png_bytep dptr = *dp; + png_read_row(png_ptr, NULL, dptr); + dp++; + } +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the entire image. If the image has an alpha channel or a tRNS + * chunk, and you have called png_handle_alpha()[*], you will need to + * initialize the image to the current image that PNG will be overlaying. + * We set the num_rows again here, in case it was incorrectly set in + * png_read_start_row() by a call to png_read_update_info() or + * png_start_read_image() if png_set_interlace_handling() wasn't called + * prior to either of these functions like it should have been. You can + * only call this function once. If you desire to have an image for + * each pass of a interlaced image, use png_read_rows() instead. + * + * [*] png_handle_alpha() does not exist yet, as of this version of libpng + */ +void PNGAPI +png_read_image(png_structp png_ptr, png_bytepp image) +{ + png_uint_32 i, image_height; + int pass, j; + png_bytepp rp; + + png_debug(1, "in png_read_image"); + + if (png_ptr == NULL) + return; + +#ifdef PNG_READ_INTERLACING_SUPPORTED + pass = png_set_interlace_handling(png_ptr); +#else + if (png_ptr->interlaced) + png_error(png_ptr, + "Cannot read interlaced image -- interlace handler disabled"); + pass = 1; +#endif + + + image_height=png_ptr->height; + png_ptr->num_rows = image_height; /* Make sure this is set correctly */ + + for (j = 0; j < pass; j++) + { + rp = image; + for (i = 0; i < image_height; i++) + { + png_read_row(png_ptr, *rp, NULL); + rp++; + } + } +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the end of the PNG file. Will not read past the end of the + * file, will verify the end is accurate, and will read any comments + * or time information at the end of the file, if info is not NULL. + */ +void PNGAPI +png_read_end(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_read_end"); + + if (png_ptr == NULL) + return; + png_crc_finish(png_ptr, 0); /* Finish off CRC from last IDAT chunk */ + + do + { + PNG_IHDR; + PNG_IDAT; + PNG_IEND; + PNG_PLTE; +#ifdef PNG_READ_bKGD_SUPPORTED + PNG_bKGD; +#endif +#ifdef PNG_READ_cHRM_SUPPORTED + PNG_cHRM; +#endif +#ifdef PNG_READ_gAMA_SUPPORTED + PNG_gAMA; +#endif +#ifdef PNG_READ_hIST_SUPPORTED + PNG_hIST; +#endif +#ifdef PNG_READ_iCCP_SUPPORTED + PNG_iCCP; +#endif +#ifdef PNG_READ_iTXt_SUPPORTED + PNG_iTXt; +#endif +#ifdef PNG_READ_oFFs_SUPPORTED + PNG_oFFs; +#endif +#ifdef PNG_READ_pCAL_SUPPORTED + PNG_pCAL; +#endif +#ifdef PNG_READ_pHYs_SUPPORTED + PNG_pHYs; +#endif +#ifdef PNG_READ_sBIT_SUPPORTED + PNG_sBIT; +#endif +#ifdef PNG_READ_sCAL_SUPPORTED + PNG_sCAL; +#endif +#ifdef PNG_READ_sPLT_SUPPORTED + PNG_sPLT; +#endif +#ifdef PNG_READ_sRGB_SUPPORTED + PNG_sRGB; +#endif +#ifdef PNG_READ_tEXt_SUPPORTED + PNG_tEXt; +#endif +#ifdef PNG_READ_tIME_SUPPORTED + PNG_tIME; +#endif +#ifdef PNG_READ_tRNS_SUPPORTED + PNG_tRNS; +#endif +#ifdef PNG_READ_zTXt_SUPPORTED + PNG_zTXt; +#endif + png_uint_32 length = png_read_chunk_header(png_ptr); + PNG_CONST png_bytep chunk_name = png_ptr->chunk_name; + + if (!png_memcmp(chunk_name, png_IHDR, 4)) + png_handle_IHDR(png_ptr, info_ptr, length); + else if (!png_memcmp(chunk_name, png_IEND, 4)) + png_handle_IEND(png_ptr, info_ptr, length); +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + else if (png_handle_as_unknown(png_ptr, chunk_name)) + { + if (!png_memcmp(chunk_name, png_IDAT, 4)) + { + if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) + png_benign_error(png_ptr, "Too many IDATs found"); + } + png_handle_unknown(png_ptr, info_ptr, length); + if (!png_memcmp(chunk_name, png_PLTE, 4)) + png_ptr->mode |= PNG_HAVE_PLTE; + } +#endif + else if (!png_memcmp(chunk_name, png_IDAT, 4)) + { + /* Zero length IDATs are legal after the last IDAT has been + * read, but not after other chunks have been read. + */ + if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) + png_benign_error(png_ptr, "Too many IDATs found"); + png_crc_finish(png_ptr, length); + } + else if (!png_memcmp(chunk_name, png_PLTE, 4)) + png_handle_PLTE(png_ptr, info_ptr, length); +#ifdef PNG_READ_bKGD_SUPPORTED + else if (!png_memcmp(chunk_name, png_bKGD, 4)) + png_handle_bKGD(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_cHRM_SUPPORTED + else if (!png_memcmp(chunk_name, png_cHRM, 4)) + png_handle_cHRM(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_gAMA_SUPPORTED + else if (!png_memcmp(chunk_name, png_gAMA, 4)) + png_handle_gAMA(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_hIST_SUPPORTED + else if (!png_memcmp(chunk_name, png_hIST, 4)) + png_handle_hIST(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_oFFs_SUPPORTED + else if (!png_memcmp(chunk_name, png_oFFs, 4)) + png_handle_oFFs(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_pCAL_SUPPORTED + else if (!png_memcmp(chunk_name, png_pCAL, 4)) + png_handle_pCAL(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_sCAL_SUPPORTED + else if (!png_memcmp(chunk_name, png_sCAL, 4)) + png_handle_sCAL(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_pHYs_SUPPORTED + else if (!png_memcmp(chunk_name, png_pHYs, 4)) + png_handle_pHYs(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_sBIT_SUPPORTED + else if (!png_memcmp(chunk_name, png_sBIT, 4)) + png_handle_sBIT(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_sRGB_SUPPORTED + else if (!png_memcmp(chunk_name, png_sRGB, 4)) + png_handle_sRGB(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_iCCP_SUPPORTED + else if (!png_memcmp(chunk_name, png_iCCP, 4)) + png_handle_iCCP(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_sPLT_SUPPORTED + else if (!png_memcmp(chunk_name, png_sPLT, 4)) + png_handle_sPLT(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_tEXt_SUPPORTED + else if (!png_memcmp(chunk_name, png_tEXt, 4)) + png_handle_tEXt(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_tIME_SUPPORTED + else if (!png_memcmp(chunk_name, png_tIME, 4)) + png_handle_tIME(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_tRNS_SUPPORTED + else if (!png_memcmp(chunk_name, png_tRNS, 4)) + png_handle_tRNS(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_zTXt_SUPPORTED + else if (!png_memcmp(chunk_name, png_zTXt, 4)) + png_handle_zTXt(png_ptr, info_ptr, length); +#endif +#ifdef PNG_READ_iTXt_SUPPORTED + else if (!png_memcmp(chunk_name, png_iTXt, 4)) + png_handle_iTXt(png_ptr, info_ptr, length); +#endif + else + png_handle_unknown(png_ptr, info_ptr, length); + } while (!(png_ptr->mode & PNG_HAVE_IEND)); +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +/* Free all memory used by the read */ +void PNGAPI +png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr, + png_infopp end_info_ptr_ptr) +{ + png_structp png_ptr = NULL; + png_infop info_ptr = NULL, end_info_ptr = NULL; +#ifdef PNG_USER_MEM_SUPPORTED + png_free_ptr free_fn = NULL; + png_voidp mem_ptr = NULL; +#endif + + png_debug(1, "in png_destroy_read_struct"); + + if (png_ptr_ptr != NULL) + png_ptr = *png_ptr_ptr; + if (png_ptr == NULL) + return; + +#ifdef PNG_USER_MEM_SUPPORTED + free_fn = png_ptr->free_fn; + mem_ptr = png_ptr->mem_ptr; +#endif + + if (info_ptr_ptr != NULL) + info_ptr = *info_ptr_ptr; + + if (end_info_ptr_ptr != NULL) + end_info_ptr = *end_info_ptr_ptr; + + png_read_destroy(png_ptr, info_ptr, end_info_ptr); + + if (info_ptr != NULL) + { +#ifdef PNG_TEXT_SUPPORTED + png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, -1); +#endif + +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)info_ptr); +#endif + *info_ptr_ptr = NULL; + } + + if (end_info_ptr != NULL) + { +#ifdef PNG_READ_TEXT_SUPPORTED + png_free_data(png_ptr, end_info_ptr, PNG_FREE_TEXT, -1); +#endif +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)end_info_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)end_info_ptr); +#endif + *end_info_ptr_ptr = NULL; + } + + if (png_ptr != NULL) + { +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)png_ptr); +#endif + *png_ptr_ptr = NULL; + } +} + +/* Free all memory used by the read (old method) */ +void /* PRIVATE */ +png_read_destroy(png_structp png_ptr, png_infop info_ptr, + png_infop end_info_ptr) +{ +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf tmp_jmp; +#endif + png_error_ptr error_fn; + png_error_ptr warning_fn; + png_voidp error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + png_free_ptr free_fn; +#endif + + png_debug(1, "in png_read_destroy"); + + if (info_ptr != NULL) + png_info_destroy(png_ptr, info_ptr); + + if (end_info_ptr != NULL) + png_info_destroy(png_ptr, end_info_ptr); + + png_free(png_ptr, png_ptr->zbuf); + png_free(png_ptr, png_ptr->big_row_buf); + png_free(png_ptr, png_ptr->prev_row); + png_free(png_ptr, png_ptr->chunkdata); +#ifdef PNG_READ_QUANTIZE_SUPPORTED + png_free(png_ptr, png_ptr->palette_lookup); + png_free(png_ptr, png_ptr->quantize_index); +#endif +#ifdef PNG_READ_GAMMA_SUPPORTED + png_free(png_ptr, png_ptr->gamma_table); +#endif +#ifdef PNG_READ_BACKGROUND_SUPPORTED + png_free(png_ptr, png_ptr->gamma_from_1); + png_free(png_ptr, png_ptr->gamma_to_1); +#endif + if (png_ptr->free_me & PNG_FREE_PLTE) + png_zfree(png_ptr, png_ptr->palette); + png_ptr->free_me &= ~PNG_FREE_PLTE; +#if defined(PNG_tRNS_SUPPORTED) || \ + defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->free_me & PNG_FREE_TRNS) + png_free(png_ptr, png_ptr->trans_alpha); + png_ptr->free_me &= ~PNG_FREE_TRNS; +#endif +#ifdef PNG_READ_hIST_SUPPORTED + if (png_ptr->free_me & PNG_FREE_HIST) + png_free(png_ptr, png_ptr->hist); + png_ptr->free_me &= ~PNG_FREE_HIST; +#endif +#ifdef PNG_READ_GAMMA_SUPPORTED + if (png_ptr->gamma_16_table != NULL) + { + int i; + int istop = (1 << (8 - png_ptr->gamma_shift)); + for (i = 0; i < istop; i++) + { + png_free(png_ptr, png_ptr->gamma_16_table[i]); + } + png_free(png_ptr, png_ptr->gamma_16_table); + } +#ifdef PNG_READ_BACKGROUND_SUPPORTED + if (png_ptr->gamma_16_from_1 != NULL) + { + int i; + int istop = (1 << (8 - png_ptr->gamma_shift)); + for (i = 0; i < istop; i++) + { + png_free(png_ptr, png_ptr->gamma_16_from_1[i]); + } + png_free(png_ptr, png_ptr->gamma_16_from_1); + } + if (png_ptr->gamma_16_to_1 != NULL) + { + int i; + int istop = (1 << (8 - png_ptr->gamma_shift)); + for (i = 0; i < istop; i++) + { + png_free(png_ptr, png_ptr->gamma_16_to_1[i]); + } + png_free(png_ptr, png_ptr->gamma_16_to_1); + } +#endif +#endif +#ifdef PNG_TIME_RFC1123_SUPPORTED + png_free(png_ptr, png_ptr->time_buffer); +#endif + + inflateEnd(&png_ptr->zstream); +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED + png_free(png_ptr, png_ptr->save_buffer); +#endif + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +#ifdef PNG_TEXT_SUPPORTED + png_free(png_ptr, png_ptr->current_text); +#endif /* PNG_TEXT_SUPPORTED */ +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + + /* Save the important info out of the png_struct, in case it is + * being used again. + */ +#ifdef PNG_SETJMP_SUPPORTED + png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof(jmp_buf)); +#endif + + error_fn = png_ptr->error_fn; + warning_fn = png_ptr->warning_fn; + error_ptr = png_ptr->error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + free_fn = png_ptr->free_fn; +#endif + + png_memset(png_ptr, 0, png_sizeof(png_struct)); + + png_ptr->error_fn = error_fn; + png_ptr->warning_fn = warning_fn; + png_ptr->error_ptr = error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + png_ptr->free_fn = free_fn; +#endif + +#ifdef PNG_SETJMP_SUPPORTED + png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof(jmp_buf)); +#endif + +} + +void PNGAPI +png_set_read_status_fn(png_structp png_ptr, png_read_status_ptr read_row_fn) +{ + if (png_ptr == NULL) + return; + png_ptr->read_row_fn = read_row_fn; +} + + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +#ifdef PNG_INFO_IMAGE_SUPPORTED +void PNGAPI +png_read_png(png_structp png_ptr, png_infop info_ptr, + int transforms, + voidp params) +{ + int row; + + if (png_ptr == NULL) + return; + + /* png_read_info() gives us all of the information from the + * PNG file before the first IDAT (image data chunk). + */ + png_read_info(png_ptr, info_ptr); + if (info_ptr->height > PNG_UINT_32_MAX/png_sizeof(png_bytep)) + png_error(png_ptr, "Image is too high to process with png_read_png()"); + + /* -------------- image transformations start here ------------------- */ + +#ifdef PNG_READ_16_TO_8_SUPPORTED + /* Tell libpng to strip 16 bit/color files down to 8 bits per color. + */ + if (transforms & PNG_TRANSFORM_STRIP_16) + png_set_strip_16(png_ptr); +#endif + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED + /* Strip alpha bytes from the input data without combining with + * the background (not recommended). + */ + if (transforms & PNG_TRANSFORM_STRIP_ALPHA) + png_set_strip_alpha(png_ptr); +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) && !defined(PNG_READ_EXPAND_SUPPORTED) + /* Extract multiple pixels with bit depths of 1, 2, or 4 from a single + * byte into separate bytes (useful for paletted and grayscale images). + */ + if (transforms & PNG_TRANSFORM_PACKING) + png_set_packing(png_ptr); +#endif + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + /* Change the order of packed pixels to least significant bit first + * (not useful if you are using png_set_packing). + */ + if (transforms & PNG_TRANSFORM_PACKSWAP) + png_set_packswap(png_ptr); +#endif + +#ifdef PNG_READ_EXPAND_SUPPORTED + /* Expand paletted colors into true RGB triplets + * Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel + * Expand paletted or RGB images with transparency to full alpha + * channels so the data will be available as RGBA quartets. + */ + if (transforms & PNG_TRANSFORM_EXPAND) + if ((png_ptr->bit_depth < 8) || + (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) || + (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))) + png_set_expand(png_ptr); +#endif + + /* We don't handle background color or gamma transformation or quantizing. + */ + +#ifdef PNG_READ_INVERT_SUPPORTED + /* Invert monochrome files to have 0 as white and 1 as black + */ + if (transforms & PNG_TRANSFORM_INVERT_MONO) + png_set_invert_mono(png_ptr); +#endif + +#ifdef PNG_READ_SHIFT_SUPPORTED + /* If you want to shift the pixel values from the range [0,255] or + * [0,65535] to the original [0,7] or [0,31], or whatever range the + * colors were originally in: + */ + if ((transforms & PNG_TRANSFORM_SHIFT) + && png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT)) + { + png_color_8p sig_bit; + + png_get_sBIT(png_ptr, info_ptr, &sig_bit); + png_set_shift(png_ptr, sig_bit); + } +#endif + +#ifdef PNG_READ_BGR_SUPPORTED + /* Flip the RGB pixels to BGR (or RGBA to BGRA) + */ + if (transforms & PNG_TRANSFORM_BGR) + png_set_bgr(png_ptr); +#endif + +#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED + /* Swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) + */ + if (transforms & PNG_TRANSFORM_SWAP_ALPHA) + png_set_swap_alpha(png_ptr); +#endif + +#ifdef PNG_READ_SWAP_SUPPORTED + /* Swap bytes of 16 bit files to least significant byte first + */ + if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) + png_set_swap(png_ptr); +#endif + +/* Added at libpng-1.2.41 */ +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED + /* Invert the alpha channel from opacity to transparency + */ + if (transforms & PNG_TRANSFORM_INVERT_ALPHA) + png_set_invert_alpha(png_ptr); +#endif + +/* Added at libpng-1.2.41 */ +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED + /* Expand grayscale image to RGB + */ + if (transforms & PNG_TRANSFORM_GRAY_TO_RGB) + png_set_gray_to_rgb(png_ptr); +#endif + + /* We don't handle adding filler bytes */ + + /* Optional call to gamma correct and add the background to the palette + * and update info structure. REQUIRED if you are expecting libpng to + * update the palette for you (i.e., you selected such a transform above). + */ + png_read_update_info(png_ptr, info_ptr); + + /* -------------- image transformations end here ------------------- */ + + png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); + if (info_ptr->row_pointers == NULL) + { + png_uint_32 iptr; + + info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr, + info_ptr->height * png_sizeof(png_bytep)); + for (iptr=0; iptrheight; iptr++) + info_ptr->row_pointers[iptr] = NULL; + + info_ptr->free_me |= PNG_FREE_ROWS; + + for (row = 0; row < (int)info_ptr->height; row++) + info_ptr->row_pointers[row] = (png_bytep)png_malloc(png_ptr, + png_get_rowbytes(png_ptr, info_ptr)); + } + + png_read_image(png_ptr, info_ptr->row_pointers); + info_ptr->valid |= PNG_INFO_IDAT; + + /* Read rest of file, and get additional chunks in info_ptr - REQUIRED */ + png_read_end(png_ptr, info_ptr); + + transforms = transforms; /* Quiet compiler warnings */ + params = params; + +} +#endif /* PNG_INFO_IMAGE_SUPPORTED */ +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ +#endif /* PNG_READ_SUPPORTED */ diff --git a/reactos/dll/3rdparty/libpng/pngrio.c b/reactos/dll/3rdparty/libpng/pngrio.c new file mode 100644 index 00000000000..59059caf692 --- /dev/null +++ b/reactos/dll/3rdparty/libpng/pngrio.c @@ -0,0 +1,163 @@ + +/* pngrio.c - functions for data input + * + * Last changed in libpng 1.4.1 [February 25, 2010] + * Copyright (c) 1998-2010 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file provides a location for all input. Users who need + * special handling are expected to write a function that has the same + * arguments as this and performs a similar function, but that possibly + * has a different input method. Note that you shouldn't change this + * function, but rather write a replacement function and then make + * libpng use it at run time with png_set_read_fn(...). + */ + +#define PNG_NO_PEDANTIC_WARNINGS +#include "png.h" +#ifdef PNG_READ_SUPPORTED +#include "pngpriv.h" + +/* Read the data from whatever input you are using. The default routine + * reads from a file pointer. Note that this routine sometimes gets called + * with very small lengths, so you should implement some kind of simple + * buffering if you are using unbuffered reads. This should never be asked + * to read more then 64K on a 16 bit machine. + */ +void /* PRIVATE */ +png_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_debug1(4, "reading %d bytes", (int)length); + + if (png_ptr->read_data_fn != NULL) + (*(png_ptr->read_data_fn))(png_ptr, data, length); + else + png_error(png_ptr, "Call to NULL read function"); +} + +#ifdef PNG_STDIO_SUPPORTED +/* This is the function that does the actual reading of data. If you are + * not reading from a standard C stream, you should create a replacement + * read_data function and use it at run time with png_set_read_fn(), rather + * than changing the library. + */ +#ifndef USE_FAR_KEYWORD +void PNGAPI +png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check; + + if (png_ptr == NULL) + return; + /* fread() returns 0 on error, so it is OK to store this in a png_size_t + * instead of an int, which is what fread() actually returns. + */ + check = fread(data, 1, length, (png_FILE_p)png_ptr->io_ptr); + + if (check != length) + png_error(png_ptr, "Read Error"); +} +#else +/* This is the model-independent version. Since the standard I/O library + can't handle far buffers in the medium and small models, we have to copy + the data. +*/ + +#define NEAR_BUF_SIZE 1024 +#define MIN(a,b) (a <= b ? a : b) + +static void PNGAPI +png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check; + png_byte *n_data; + png_FILE_p io_ptr; + + if (png_ptr == NULL) + return; + /* Check if data really is near. If so, use usual code. */ + n_data = (png_byte *)CVT_PTR_NOCHECK(data); + io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); + if ((png_bytep)n_data == data) + { + check = fread(n_data, 1, length, io_ptr); + } + else + { + png_byte buf[NEAR_BUF_SIZE]; + png_size_t read, remaining, err; + check = 0; + remaining = length; + do + { + read = MIN(NEAR_BUF_SIZE, remaining); + err = fread(buf, 1, read, io_ptr); + png_memcpy(data, buf, read); /* copy far buffer to near buffer */ + if (err != read) + break; + else + check += err; + data += read; + remaining -= read; + } + while (remaining != 0); + } + if ((png_uint_32)check != (png_uint_32)length) + png_error(png_ptr, "read Error"); +} +#endif +#endif + +/* This function allows the application to supply a new input function + * for libpng if standard C streams aren't being used. + * + * This function takes as its arguments: + * png_ptr - pointer to a png input data structure + * io_ptr - pointer to user supplied structure containing info about + * the input functions. May be NULL. + * read_data_fn - pointer to a new input function that takes as its + * arguments a pointer to a png_struct, a pointer to + * a location where input data can be stored, and a 32-bit + * unsigned int that is the number of bytes to be read. + * To exit and output any fatal error messages the new write + * function should call png_error(png_ptr, "Error msg"). + * May be NULL, in which case libpng's default function will + * be used. + */ +void PNGAPI +png_set_read_fn(png_structp png_ptr, png_voidp io_ptr, + png_rw_ptr read_data_fn) +{ + if (png_ptr == NULL) + return; + png_ptr->io_ptr = io_ptr; + +#ifdef PNG_STDIO_SUPPORTED + if (read_data_fn != NULL) + png_ptr->read_data_fn = read_data_fn; + else + png_ptr->read_data_fn = png_default_read_data; +#else + png_ptr->read_data_fn = read_data_fn; +#endif + + /* It is an error to write to a read device */ + if (png_ptr->write_data_fn != NULL) + { + png_ptr->write_data_fn = NULL; + png_warning(png_ptr, + "It's an error to set both read_data_fn and write_data_fn in the "); + png_warning(png_ptr, + "same structure. Resetting write_data_fn to NULL"); + } + +#ifdef PNG_WRITE_FLUSH_SUPPORTED + png_ptr->output_flush_fn = NULL; +#endif +} +#endif /* PNG_READ_SUPPORTED */ diff --git a/reactos/dll/3rdparty/libpng/pngrtran.c b/reactos/dll/3rdparty/libpng/pngrtran.c new file mode 100644 index 00000000000..b5e8f1a26f2 --- /dev/null +++ b/reactos/dll/3rdparty/libpng/pngrtran.c @@ -0,0 +1,4203 @@ + +/* pngrtran.c - transforms the data in a row for PNG readers + * + * Last changed in libpng 1.4.2 [May 6, 2010] + * Copyright (c) 1998-2010 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file contains functions optionally called by an application + * in order to tell libpng how to handle data when reading a PNG. + * Transformations that are used in both reading and writing are + * in pngtrans.c. + */ + +#define PNG_NO_PEDANTIC_WARNINGS +#include "png.h" +#ifdef PNG_READ_SUPPORTED +#include "pngpriv.h" + +/* Set the action on getting a CRC error for an ancillary or critical chunk. */ +void PNGAPI +png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action) +{ + png_debug(1, "in png_set_crc_action"); + + if (png_ptr == NULL) + return; + + /* Tell libpng how we react to CRC errors in critical chunks */ + switch (crit_action) + { + case PNG_CRC_NO_CHANGE: /* Leave setting as is */ + break; + + case PNG_CRC_WARN_USE: /* Warn/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; + png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE; + break; + + case PNG_CRC_QUIET_USE: /* Quiet/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; + png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE | + PNG_FLAG_CRC_CRITICAL_IGNORE; + break; + + case PNG_CRC_WARN_DISCARD: /* Not a valid action for critical data */ + png_warning(png_ptr, + "Can't discard critical data on CRC error"); + case PNG_CRC_ERROR_QUIT: /* Error/quit */ + + case PNG_CRC_DEFAULT: + default: + png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; + break; + } + + /* Tell libpng how we react to CRC errors in ancillary chunks */ + switch (ancil_action) + { + case PNG_CRC_NO_CHANGE: /* Leave setting as is */ + break; + + case PNG_CRC_WARN_USE: /* Warn/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE; + break; + + case PNG_CRC_QUIET_USE: /* Quiet/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE | + PNG_FLAG_CRC_ANCILLARY_NOWARN; + break; + + case PNG_CRC_ERROR_QUIT: /* Error/quit */ + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN; + break; + + case PNG_CRC_WARN_DISCARD: /* Warn/discard data */ + + case PNG_CRC_DEFAULT: + default: + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + break; + } +} + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ + defined(PNG_FLOATING_POINT_SUPPORTED) +/* Handle alpha and tRNS via a background color */ +void PNGAPI +png_set_background(png_structp png_ptr, + png_color_16p background_color, int background_gamma_code, + int need_expand, double background_gamma) +{ + png_debug(1, "in png_set_background"); + + if (png_ptr == NULL) + return; + if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN) + { + png_warning(png_ptr, "Application must supply a known background gamma"); + return; + } + + png_ptr->transformations |= PNG_BACKGROUND; + png_memcpy(&(png_ptr->background), background_color, + png_sizeof(png_color_16)); + png_ptr->background_gamma = (float)background_gamma; + png_ptr->background_gamma_type = (png_byte)(background_gamma_code); + png_ptr->transformations |= (need_expand ? PNG_BACKGROUND_EXPAND : 0); +} +#endif + +#ifdef PNG_READ_16_TO_8_SUPPORTED +/* Strip 16 bit depth files to 8 bit depth */ +void PNGAPI +png_set_strip_16(png_structp png_ptr) +{ + png_debug(1, "in png_set_strip_16"); + + if (png_ptr == NULL) + return; + png_ptr->transformations |= PNG_16_TO_8; +} +#endif + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED +void PNGAPI +png_set_strip_alpha(png_structp png_ptr) +{ + png_debug(1, "in png_set_strip_alpha"); + + if (png_ptr == NULL) + return; + png_ptr->flags |= PNG_FLAG_STRIP_ALPHA; +} +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +/* Quantize file to 8 bit. Supply a palette, the current number + * of elements in the palette, the maximum number of elements + * allowed, and a histogram if possible. If the current number + * of colors is greater then the maximum number, the palette will be + * modified to fit in the maximum number. "full_quantize" indicates + * whether we need a quantizeing cube set up for RGB images, or if we + * simply are reducing the number of colors in a paletted image. + */ + +typedef struct png_dsort_struct +{ + struct png_dsort_struct FAR * next; + png_byte left; + png_byte right; +} png_dsort; +typedef png_dsort FAR * png_dsortp; +typedef png_dsort FAR * FAR * png_dsortpp; + +void PNGAPI +png_set_quantize(png_structp png_ptr, png_colorp palette, + int num_palette, int maximum_colors, png_uint_16p histogram, + int full_quantize) +{ + png_debug(1, "in png_set_quantize"); + + if (png_ptr == NULL) + return; + png_ptr->transformations |= PNG_QUANTIZE; + + if (!full_quantize) + { + int i; + + png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * png_sizeof(png_byte))); + for (i = 0; i < num_palette; i++) + png_ptr->quantize_index[i] = (png_byte)i; + } + + if (num_palette > maximum_colors) + { + if (histogram != NULL) + { + /* This is easy enough, just throw out the least used colors. + * Perhaps not the best solution, but good enough. + */ + + int i; + + /* Initialize an array to sort colors */ + png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * png_sizeof(png_byte))); + + /* Initialize the quantize_sort array */ + for (i = 0; i < num_palette; i++) + png_ptr->quantize_sort[i] = (png_byte)i; + + /* Find the least used palette entries by starting a + * bubble sort, and running it until we have sorted + * out enough colors. Note that we don't care about + * sorting all the colors, just finding which are + * least used. + */ + + for (i = num_palette - 1; i >= maximum_colors; i--) + { + int done; /* To stop early if the list is pre-sorted */ + int j; + + done = 1; + for (j = 0; j < i; j++) + { + if (histogram[png_ptr->quantize_sort[j]] + < histogram[png_ptr->quantize_sort[j + 1]]) + { + png_byte t; + + t = png_ptr->quantize_sort[j]; + png_ptr->quantize_sort[j] = png_ptr->quantize_sort[j + 1]; + png_ptr->quantize_sort[j + 1] = t; + done = 0; + } + } + if (done) + break; + } + + /* Swap the palette around, and set up a table, if necessary */ + if (full_quantize) + { + int j = num_palette; + + /* Put all the useful colors within the max, but don't + * move the others. + */ + for (i = 0; i < maximum_colors; i++) + { + if ((int)png_ptr->quantize_sort[i] >= maximum_colors) + { + do + j--; + while ((int)png_ptr->quantize_sort[j] >= maximum_colors); + palette[i] = palette[j]; + } + } + } + else + { + int j = num_palette; + + /* Move all the used colors inside the max limit, and + * develop a translation table. + */ + for (i = 0; i < maximum_colors; i++) + { + /* Only move the colors we need to */ + if ((int)png_ptr->quantize_sort[i] >= maximum_colors) + { + png_color tmp_color; + + do + j--; + while ((int)png_ptr->quantize_sort[j] >= maximum_colors); + + tmp_color = palette[j]; + palette[j] = palette[i]; + palette[i] = tmp_color; + /* Indicate where the color went */ + png_ptr->quantize_index[j] = (png_byte)i; + png_ptr->quantize_index[i] = (png_byte)j; + } + } + + /* Find closest color for those colors we are not using */ + for (i = 0; i < num_palette; i++) + { + if ((int)png_ptr->quantize_index[i] >= maximum_colors) + { + int min_d, k, min_k, d_index; + + /* Find the closest color to one we threw out */ + d_index = png_ptr->quantize_index[i]; + min_d = PNG_COLOR_DIST(palette[d_index], palette[0]); + for (k = 1, min_k = 0; k < maximum_colors; k++) + { + int d; + + d = PNG_COLOR_DIST(palette[d_index], palette[k]); + + if (d < min_d) + { + min_d = d; + min_k = k; + } + } + /* Point to closest color */ + png_ptr->quantize_index[i] = (png_byte)min_k; + } + } + } + png_free(png_ptr, png_ptr->quantize_sort); + png_ptr->quantize_sort = NULL; + } + else + { + /* This is much harder to do simply (and quickly). Perhaps + * we need to go through a median cut routine, but those + * don't always behave themselves with only a few colors + * as input. So we will just find the closest two colors, + * and throw out one of them (chosen somewhat randomly). + * [We don't understand this at all, so if someone wants to + * work on improving it, be our guest - AED, GRP] + */ + int i; + int max_d; + int num_new_palette; + png_dsortp t; + png_dsortpp hash; + + t = NULL; + + /* Initialize palette index arrays */ + png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * png_sizeof(png_byte))); + png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * png_sizeof(png_byte))); + + /* Initialize the sort array */ + for (i = 0; i < num_palette; i++) + { + png_ptr->index_to_palette[i] = (png_byte)i; + png_ptr->palette_to_index[i] = (png_byte)i; + } + + hash = (png_dsortpp)png_calloc(png_ptr, (png_uint_32)(769 * + png_sizeof(png_dsortp))); + + num_new_palette = num_palette; + + /* Initial wild guess at how far apart the farthest pixel + * pair we will be eliminating will be. Larger + * numbers mean more areas will be allocated, Smaller + * numbers run the risk of not saving enough data, and + * having to do this all over again. + * + * I have not done extensive checking on this number. + */ + max_d = 96; + + while (num_new_palette > maximum_colors) + { + for (i = 0; i < num_new_palette - 1; i++) + { + int j; + + for (j = i + 1; j < num_new_palette; j++) + { + int d; + + d = PNG_COLOR_DIST(palette[i], palette[j]); + + if (d <= max_d) + { + + t = (png_dsortp)png_malloc_warn(png_ptr, + (png_uint_32)(png_sizeof(png_dsort))); + if (t == NULL) + break; + t->next = hash[d]; + t->left = (png_byte)i; + t->right = (png_byte)j; + hash[d] = t; + } + } + if (t == NULL) + break; + } + + if (t != NULL) + for (i = 0; i <= max_d; i++) + { + if (hash[i] != NULL) + { + png_dsortp p; + + for (p = hash[i]; p; p = p->next) + { + if ((int)png_ptr->index_to_palette[p->left] + < num_new_palette && + (int)png_ptr->index_to_palette[p->right] + < num_new_palette) + { + int j, next_j; + + if (num_new_palette & 0x01) + { + j = p->left; + next_j = p->right; + } + else + { + j = p->right; + next_j = p->left; + } + + num_new_palette--; + palette[png_ptr->index_to_palette[j]] + = palette[num_new_palette]; + if (!full_quantize) + { + int k; + + for (k = 0; k < num_palette; k++) + { + if (png_ptr->quantize_index[k] == + png_ptr->index_to_palette[j]) + png_ptr->quantize_index[k] = + png_ptr->index_to_palette[next_j]; + if ((int)png_ptr->quantize_index[k] == + num_new_palette) + png_ptr->quantize_index[k] = + png_ptr->index_to_palette[j]; + } + } + + png_ptr->index_to_palette[png_ptr->palette_to_index + [num_new_palette]] = png_ptr->index_to_palette[j]; + png_ptr->palette_to_index[png_ptr->index_to_palette[j]] + = png_ptr->palette_to_index[num_new_palette]; + + png_ptr->index_to_palette[j] = + (png_byte)num_new_palette; + png_ptr->palette_to_index[num_new_palette] = + (png_byte)j; + } + if (num_new_palette <= maximum_colors) + break; + } + if (num_new_palette <= maximum_colors) + break; + } + } + + for (i = 0; i < 769; i++) + { + if (hash[i] != NULL) + { + png_dsortp p = hash[i]; + while (p) + { + t = p->next; + png_free(png_ptr, p); + p = t; + } + } + hash[i] = 0; + } + max_d += 96; + } + png_free(png_ptr, hash); + png_free(png_ptr, png_ptr->palette_to_index); + png_free(png_ptr, png_ptr->index_to_palette); + png_ptr->palette_to_index = NULL; + png_ptr->index_to_palette = NULL; + } + num_palette = maximum_colors; + } + if (png_ptr->palette == NULL) + { + png_ptr->palette = palette; + } + png_ptr->num_palette = (png_uint_16)num_palette; + + if (full_quantize) + { + int i; + png_bytep distance; + int total_bits = PNG_QUANTIZE_RED_BITS + PNG_QUANTIZE_GREEN_BITS + + PNG_QUANTIZE_BLUE_BITS; + int num_red = (1 << PNG_QUANTIZE_RED_BITS); + int num_green = (1 << PNG_QUANTIZE_GREEN_BITS); + int num_blue = (1 << PNG_QUANTIZE_BLUE_BITS); + png_size_t num_entries = ((png_size_t)1 << total_bits); + + png_ptr->palette_lookup = (png_bytep )png_calloc(png_ptr, + (png_uint_32)(num_entries * png_sizeof(png_byte))); + + distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries * + png_sizeof(png_byte))); + png_memset(distance, 0xff, num_entries * png_sizeof(png_byte)); + + for (i = 0; i < num_palette; i++) + { + int ir, ig, ib; + int r = (palette[i].red >> (8 - PNG_QUANTIZE_RED_BITS)); + int g = (palette[i].green >> (8 - PNG_QUANTIZE_GREEN_BITS)); + int b = (palette[i].blue >> (8 - PNG_QUANTIZE_BLUE_BITS)); + + for (ir = 0; ir < num_red; ir++) + { + /* int dr = abs(ir - r); */ + int dr = ((ir > r) ? ir - r : r - ir); + int index_r = (ir << (PNG_QUANTIZE_BLUE_BITS + + PNG_QUANTIZE_GREEN_BITS)); + + for (ig = 0; ig < num_green; ig++) + { + /* int dg = abs(ig - g); */ + int dg = ((ig > g) ? ig - g : g - ig); + int dt = dr + dg; + int dm = ((dr > dg) ? dr : dg); + int index_g = index_r | (ig << PNG_QUANTIZE_BLUE_BITS); + + for (ib = 0; ib < num_blue; ib++) + { + int d_index = index_g | ib; + /* int db = abs(ib - b); */ + int db = ((ib > b) ? ib - b : b - ib); + int dmax = ((dm > db) ? dm : db); + int d = dmax + dt + db; + + if (d < (int)distance[d_index]) + { + distance[d_index] = (png_byte)d; + png_ptr->palette_lookup[d_index] = (png_byte)i; + } + } + } + } + } + + png_free(png_ptr, distance); + } +} +#endif /* PNG_READ_QUANTIZE_SUPPORTED */ + +#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) +/* Transform the image from the file_gamma to the screen_gamma. We + * only do transformations on images where the file_gamma and screen_gamma + * are not close reciprocals, otherwise it slows things down slightly, and + * also needlessly introduces small errors. + * + * We will turn off gamma transformation later if no semitransparent entries + * are present in the tRNS array for palette images. We can't do it here + * because we don't necessarily have the tRNS chunk yet. + */ +void PNGAPI +png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma) +{ + png_debug(1, "in png_set_gamma"); + + if (png_ptr == NULL) + return; + + if ((fabs(scrn_gamma * file_gamma - 1.0) > PNG_GAMMA_THRESHOLD) || + (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) || + (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)) + png_ptr->transformations |= PNG_GAMMA; + png_ptr->gamma = (float)file_gamma; + png_ptr->screen_gamma = (float)scrn_gamma; +} +#endif + +#ifdef PNG_READ_EXPAND_SUPPORTED +/* Expand paletted images to RGB, expand grayscale images of + * less than 8-bit depth to 8-bit depth, and expand tRNS chunks + * to alpha channels. + */ +void PNGAPI +png_set_expand(png_structp png_ptr) +{ + png_debug(1, "in png_set_expand"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); + png_ptr->flags &= ~PNG_FLAG_ROW_INIT; +} + +/* GRR 19990627: the following three functions currently are identical + * to png_set_expand(). However, it is entirely reasonable that someone + * might wish to expand an indexed image to RGB but *not* expand a single, + * fully transparent palette entry to a full alpha channel--perhaps instead + * convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace + * the transparent color with a particular RGB value, or drop tRNS entirely. + * IOW, a future version of the library may make the transformations flag + * a bit more fine-grained, with separate bits for each of these three + * functions. + * + * More to the point, these functions make it obvious what libpng will be + * doing, whereas "expand" can (and does) mean any number of things. + * + * GRP 20060307: In libpng-1.2.9, png_set_gray_1_2_4_to_8() was modified + * to expand only the sample depth but not to expand the tRNS to alpha + * and its name was changed to png_set_expand_gray_1_2_4_to_8(). + */ + +/* Expand paletted images to RGB. */ +void PNGAPI +png_set_palette_to_rgb(png_structp png_ptr) +{ + png_debug(1, "in png_set_palette_to_rgb"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); + png_ptr->flags &= ~PNG_FLAG_ROW_INIT; +} + +/* Expand grayscale images of less than 8-bit depth to 8 bits. */ +void PNGAPI +png_set_expand_gray_1_2_4_to_8(png_structp png_ptr) +{ + png_debug(1, "in png_set_expand_gray_1_2_4_to_8"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_EXPAND; + png_ptr->flags &= ~PNG_FLAG_ROW_INIT; +} + + + +/* Expand tRNS chunks to alpha channels. */ +void PNGAPI +png_set_tRNS_to_alpha(png_structp png_ptr) +{ + png_debug(1, "in png_set_tRNS_to_alpha"); + + png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); + png_ptr->flags &= ~PNG_FLAG_ROW_INIT; +} +#endif /* defined(PNG_READ_EXPAND_SUPPORTED) */ + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED +void PNGAPI +png_set_gray_to_rgb(png_structp png_ptr) +{ + png_debug(1, "in png_set_gray_to_rgb"); + + png_ptr->transformations |= PNG_GRAY_TO_RGB; + png_ptr->flags &= ~PNG_FLAG_ROW_INIT; +} +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +/* Convert a RGB image to a grayscale of the same width. This allows us, + * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image. + */ + +void PNGAPI +png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red, + double green) +{ + int red_fixed = (int)((float)red*100000.0 + 0.5); + int green_fixed = (int)((float)green*100000.0 + 0.5); + if (png_ptr == NULL) + return; + png_set_rgb_to_gray_fixed(png_ptr, error_action, red_fixed, green_fixed); +} +#endif + +void PNGAPI +png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action, + png_fixed_point red, png_fixed_point green) +{ + png_debug(1, "in png_set_rgb_to_gray"); + + if (png_ptr == NULL) + return; + + switch(error_action) + { + case 1: png_ptr->transformations |= PNG_RGB_TO_GRAY; + break; + + case 2: png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN; + break; + + case 3: png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR; + } + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) +#ifdef PNG_READ_EXPAND_SUPPORTED + png_ptr->transformations |= PNG_EXPAND; +#else + { + png_warning(png_ptr, + "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED"); + png_ptr->transformations &= ~PNG_RGB_TO_GRAY; + } +#endif + { + png_uint_16 red_int, green_int; + if (red < 0 || green < 0) + { + red_int = 6968; /* .212671 * 32768 + .5 */ + green_int = 23434; /* .715160 * 32768 + .5 */ + } + else if (red + green < 100000L) + { + red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L); + green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L); + } + else + { + png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients"); + red_int = 6968; + green_int = 23434; + } + png_ptr->rgb_to_gray_red_coeff = red_int; + png_ptr->rgb_to_gray_green_coeff = green_int; + png_ptr->rgb_to_gray_blue_coeff = + (png_uint_16)(32768 - red_int - green_int); + } +} +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +void PNGAPI +png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr + read_user_transform_fn) +{ + png_debug(1, "in png_set_read_user_transform_fn"); + + if (png_ptr == NULL) + return; + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + png_ptr->transformations |= PNG_USER_TRANSFORM; + png_ptr->read_user_transform_fn = read_user_transform_fn; +#endif +} +#endif + +/* Initialize everything needed for the read. This includes modifying + * the palette. + */ +void /* PRIVATE */ +png_init_read_transformations(png_structp png_ptr) +{ + png_debug(1, "in png_init_read_transformations"); + + { +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_SHIFT_SUPPORTED) || \ + defined(PNG_READ_GAMMA_SUPPORTED) + int color_type = png_ptr->color_type; +#endif + +#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED + /* Detect gray background and attempt to enable optimization + * for gray --> RGB case + * + * Note: if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or + * RGB_ALPHA (in which case need_expand is superfluous anyway), the + * background color might actually be gray yet not be flagged as such. + * This is not a problem for the current code, which uses + * PNG_BACKGROUND_IS_GRAY only to decide when to do the + * png_do_gray_to_rgb() transformation. + */ + if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && + !(color_type & PNG_COLOR_MASK_COLOR)) + { + png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; + } else if ((png_ptr->transformations & PNG_BACKGROUND) && + !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) && + (png_ptr->transformations & PNG_GRAY_TO_RGB) && + png_ptr->background.red == png_ptr->background.green && + png_ptr->background.red == png_ptr->background.blue) + { + png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; + png_ptr->background.gray = png_ptr->background.red; + } +#endif + + if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && + (png_ptr->transformations & PNG_EXPAND)) + { + if (!(color_type & PNG_COLOR_MASK_COLOR)) /* i.e., GRAY or GRAY_ALPHA */ + { + /* Expand background and tRNS chunks */ + switch (png_ptr->bit_depth) + { + case 1: + png_ptr->background.gray *= (png_uint_16)0xff; + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) + { + png_ptr->trans_color.gray *= (png_uint_16)0xff; + png_ptr->trans_color.red = png_ptr->trans_color.green + = png_ptr->trans_color.blue = png_ptr->trans_color.gray; + } + break; + + case 2: + png_ptr->background.gray *= (png_uint_16)0x55; + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) + { + png_ptr->trans_color.gray *= (png_uint_16)0x55; + png_ptr->trans_color.red = png_ptr->trans_color.green + = png_ptr->trans_color.blue = png_ptr->trans_color.gray; + } + break; + + case 4: + png_ptr->background.gray *= (png_uint_16)0x11; + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) + { + png_ptr->trans_color.gray *= (png_uint_16)0x11; + png_ptr->trans_color.red = png_ptr->trans_color.green + = png_ptr->trans_color.blue = png_ptr->trans_color.gray; + } + break; + + case 8: + + case 16: + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + break; + } + } + else if (color_type == PNG_COLOR_TYPE_PALETTE) + { + png_ptr->background.red = + png_ptr->palette[png_ptr->background.index].red; + png_ptr->background.green = + png_ptr->palette[png_ptr->background.index].green; + png_ptr->background.blue = + png_ptr->palette[png_ptr->background.index].blue; + +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED + if (png_ptr->transformations & PNG_INVERT_ALPHA) + { +#ifdef PNG_READ_EXPAND_SUPPORTED + if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) +#endif + { + /* Invert the alpha channel (in tRNS) unless the pixels are + * going to be expanded, in which case leave it for later + */ + int i, istop; + istop=(int)png_ptr->num_trans; + for (i=0; itrans_alpha[i] = (png_byte)(255 - png_ptr->trans_alpha[i]); + } + } +#endif + + } + } +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED) + png_ptr->background_1 = png_ptr->background; +#endif +#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) + + if ((color_type == PNG_COLOR_TYPE_PALETTE && png_ptr->num_trans != 0) + && (fabs(png_ptr->screen_gamma * png_ptr->gamma - 1.0) + < PNG_GAMMA_THRESHOLD)) + { + int i, k; + k=0; + for (i=0; inum_trans; i++) + { + if (png_ptr->trans_alpha[i] != 0 && png_ptr->trans_alpha[i] != 0xff) + k=1; /* Partial transparency is present */ + } + if (k == 0) + png_ptr->transformations &= ~PNG_GAMMA; + } + + if ((png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY)) && + png_ptr->gamma != 0.0) + { + png_build_gamma_table(png_ptr, png_ptr->bit_depth); + +#ifdef PNG_READ_BACKGROUND_SUPPORTED + if (png_ptr->transformations & PNG_BACKGROUND) + { + if (color_type == PNG_COLOR_TYPE_PALETTE) + { + /* Could skip if no transparency */ + png_color back, back_1; + png_colorp palette = png_ptr->palette; + int num_palette = png_ptr->num_palette; + int i; + if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE) + { + back.red = png_ptr->gamma_table[png_ptr->background.red]; + back.green = png_ptr->gamma_table[png_ptr->background.green]; + back.blue = png_ptr->gamma_table[png_ptr->background.blue]; + + back_1.red = png_ptr->gamma_to_1[png_ptr->background.red]; + back_1.green = png_ptr->gamma_to_1[png_ptr->background.green]; + back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue]; + } + else + { + double g, gs; + + switch (png_ptr->background_gamma_type) + { + case PNG_BACKGROUND_GAMMA_SCREEN: + g = (png_ptr->screen_gamma); + gs = 1.0; + break; + + case PNG_BACKGROUND_GAMMA_FILE: + g = 1.0 / (png_ptr->gamma); + gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); + break; + + case PNG_BACKGROUND_GAMMA_UNIQUE: + g = 1.0 / (png_ptr->background_gamma); + gs = 1.0 / (png_ptr->background_gamma * + png_ptr->screen_gamma); + break; + default: + g = 1.0; /* back_1 */ + gs = 1.0; /* back */ + } + + if ( fabs(gs - 1.0) < PNG_GAMMA_THRESHOLD) + { + back.red = (png_byte)png_ptr->background.red; + back.green = (png_byte)png_ptr->background.green; + back.blue = (png_byte)png_ptr->background.blue; + } + else + { + back.red = (png_byte)(pow( + (double)png_ptr->background.red/255.0, gs) * 255.0 + .5); + back.green = (png_byte)(pow( + (double)png_ptr->background.green/255.0, gs) * 255.0 + + .5); + back.blue = (png_byte)(pow( + (double)png_ptr->background.blue/255.0, gs) * 255.0 + .5); + } + + back_1.red = (png_byte)(pow( + (double)png_ptr->background.red/255.0, g) * 255.0 + .5); + back_1.green = (png_byte)(pow( + (double)png_ptr->background.green/255.0, g) * 255.0 + .5); + back_1.blue = (png_byte)(pow( + (double)png_ptr->background.blue/255.0, g) * 255.0 + .5); + } + for (i = 0; i < num_palette; i++) + { + if (i < (int)png_ptr->num_trans && png_ptr->trans_alpha[i] != 0xff) + { + if (png_ptr->trans_alpha[i] == 0) + { + palette[i] = back; + } + else /* if (png_ptr->trans_alpha[i] != 0xff) */ + { + png_byte v, w; + + v = png_ptr->gamma_to_1[palette[i].red]; + png_composite(w, v, png_ptr->trans_alpha[i], back_1.red); + palette[i].red = png_ptr->gamma_from_1[w]; + + v = png_ptr->gamma_to_1[palette[i].green]; + png_composite(w, v, png_ptr->trans_alpha[i], back_1.green); + palette[i].green = png_ptr->gamma_from_1[w]; + + v = png_ptr->gamma_to_1[palette[i].blue]; + png_composite(w, v, png_ptr->trans_alpha[i], back_1.blue); + palette[i].blue = png_ptr->gamma_from_1[w]; + } + } + else + { + palette[i].red = png_ptr->gamma_table[palette[i].red]; + palette[i].green = png_ptr->gamma_table[palette[i].green]; + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; + } + } + /* Prevent the transformations being done again, and make sure + * that the now spurious alpha channel is stripped - the code + * has just reduced background composition and gamma correction + * to a simple alpha channel strip. + */ + png_ptr->transformations &= ~PNG_BACKGROUND; + png_ptr->transformations &= ~PNG_GAMMA; + png_ptr->transformations |= PNG_STRIP_ALPHA; + } + /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */ + else + /* color_type != PNG_COLOR_TYPE_PALETTE */ + { + double m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1); + double g = 1.0; + double gs = 1.0; + + switch (png_ptr->background_gamma_type) + { + case PNG_BACKGROUND_GAMMA_SCREEN: + g = (png_ptr->screen_gamma); + gs = 1.0; + break; + + case PNG_BACKGROUND_GAMMA_FILE: + g = 1.0 / (png_ptr->gamma); + gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); + break; + + case PNG_BACKGROUND_GAMMA_UNIQUE: + g = 1.0 / (png_ptr->background_gamma); + gs = 1.0 / (png_ptr->background_gamma * + png_ptr->screen_gamma); + break; + } + + png_ptr->background_1.gray = (png_uint_16)(pow( + (double)png_ptr->background.gray / m, g) * m + .5); + png_ptr->background.gray = (png_uint_16)(pow( + (double)png_ptr->background.gray / m, gs) * m + .5); + + if ((png_ptr->background.red != png_ptr->background.green) || + (png_ptr->background.red != png_ptr->background.blue) || + (png_ptr->background.red != png_ptr->background.gray)) + { + /* RGB or RGBA with color background */ + png_ptr->background_1.red = (png_uint_16)(pow( + (double)png_ptr->background.red / m, g) * m + .5); + png_ptr->background_1.green = (png_uint_16)(pow( + (double)png_ptr->background.green / m, g) * m + .5); + png_ptr->background_1.blue = (png_uint_16)(pow( + (double)png_ptr->background.blue / m, g) * m + .5); + png_ptr->background.red = (png_uint_16)(pow( + (double)png_ptr->background.red / m, gs) * m + .5); + png_ptr->background.green = (png_uint_16)(pow( + (double)png_ptr->background.green / m, gs) * m + .5); + png_ptr->background.blue = (png_uint_16)(pow( + (double)png_ptr->background.blue / m, gs) * m + .5); + } + else + { + /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */ + png_ptr->background_1.red = png_ptr->background_1.green + = png_ptr->background_1.blue = png_ptr->background_1.gray; + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + } + } + } + else + /* Transformation does not include PNG_BACKGROUND */ +#endif /* PNG_READ_BACKGROUND_SUPPORTED */ + if (color_type == PNG_COLOR_TYPE_PALETTE) + { + png_colorp palette = png_ptr->palette; + int num_palette = png_ptr->num_palette; + int i; + + for (i = 0; i < num_palette; i++) + { + palette[i].red = png_ptr->gamma_table[palette[i].red]; + palette[i].green = png_ptr->gamma_table[palette[i].green]; + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; + } + + /* Done the gamma correction. */ + png_ptr->transformations &= ~PNG_GAMMA; + } + } +#ifdef PNG_READ_BACKGROUND_SUPPORTED + else +#endif +#endif /* PNG_READ_GAMMA_SUPPORTED && PNG_FLOATING_POINT_SUPPORTED */ +#ifdef PNG_READ_BACKGROUND_SUPPORTED + /* No GAMMA transformation */ + if ((png_ptr->transformations & PNG_BACKGROUND) && + (color_type == PNG_COLOR_TYPE_PALETTE)) + { + int i; + int istop = (int)png_ptr->num_trans; + png_color back; + png_colorp palette = png_ptr->palette; + + back.red = (png_byte)png_ptr->background.red; + back.green = (png_byte)png_ptr->background.green; + back.blue = (png_byte)png_ptr->background.blue; + + for (i = 0; i < istop; i++) + { + if (png_ptr->trans_alpha[i] == 0) + { + palette[i] = back; + } + else if (png_ptr->trans_alpha[i] != 0xff) + { + /* The png_composite() macro is defined in png.h */ + png_composite(palette[i].red, palette[i].red, + png_ptr->trans_alpha[i], back.red); + png_composite(palette[i].green, palette[i].green, + png_ptr->trans_alpha[i], back.green); + png_composite(palette[i].blue, palette[i].blue, + png_ptr->trans_alpha[i], back.blue); + } + } + + /* Handled alpha, still need to strip the channel. */ + png_ptr->transformations &= ~PNG_BACKGROUND; + png_ptr->transformations |= PNG_STRIP_ALPHA; + } +#endif /* PNG_READ_BACKGROUND_SUPPORTED */ + +#ifdef PNG_READ_SHIFT_SUPPORTED + if ((png_ptr->transformations & PNG_SHIFT) && + (color_type == PNG_COLOR_TYPE_PALETTE)) + { + png_uint_16 i; + png_uint_16 istop = png_ptr->num_palette; + int sr = 8 - png_ptr->sig_bit.red; + int sg = 8 - png_ptr->sig_bit.green; + int sb = 8 - png_ptr->sig_bit.blue; + + if (sr < 0 || sr > 8) + sr = 0; + if (sg < 0 || sg > 8) + sg = 0; + if (sb < 0 || sb > 8) + sb = 0; + for (i = 0; i < istop; i++) + { + png_ptr->palette[i].red >>= sr; + png_ptr->palette[i].green >>= sg; + png_ptr->palette[i].blue >>= sb; + } + } +#endif /* PNG_READ_SHIFT_SUPPORTED */ + } +#if !defined(PNG_READ_GAMMA_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) \ + && !defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr) + return; +#endif +} + +/* Modify the info structure to reflect the transformations. The + * info should be updated so a PNG file could be written with it, + * assuming the transformations result in valid PNG data. + */ +void /* PRIVATE */ +png_read_transform_info(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_read_transform_info"); + +#ifdef PNG_READ_EXPAND_SUPPORTED + if (png_ptr->transformations & PNG_EXPAND) + { + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (png_ptr->num_trans && + (png_ptr->transformations & PNG_EXPAND_tRNS)) + info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA; + else + info_ptr->color_type = PNG_COLOR_TYPE_RGB; + info_ptr->bit_depth = 8; + info_ptr->num_trans = 0; + } + else + { + if (png_ptr->num_trans) + { + if (png_ptr->transformations & PNG_EXPAND_tRNS) + info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; + } + if (info_ptr->bit_depth < 8) + info_ptr->bit_depth = 8; + info_ptr->num_trans = 0; + } + } +#endif + +#ifdef PNG_READ_BACKGROUND_SUPPORTED + if (png_ptr->transformations & PNG_BACKGROUND) + { + info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA; + info_ptr->num_trans = 0; + info_ptr->background = png_ptr->background; + } +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED + if (png_ptr->transformations & PNG_GAMMA) + { +#ifdef PNG_FLOATING_POINT_SUPPORTED + info_ptr->gamma = png_ptr->gamma; +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED + info_ptr->int_gamma = png_ptr->int_gamma; +#endif + } +#endif + +#ifdef PNG_READ_16_TO_8_SUPPORTED + if ((png_ptr->transformations & PNG_16_TO_8) && (info_ptr->bit_depth == 16)) + info_ptr->bit_depth = 8; +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED + if (png_ptr->transformations & PNG_GRAY_TO_RGB) + info_ptr->color_type |= PNG_COLOR_MASK_COLOR; +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + if (png_ptr->transformations & PNG_RGB_TO_GRAY) + info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR; +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED + if (png_ptr->transformations & PNG_QUANTIZE) + { + if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || + (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) && + png_ptr->palette_lookup && info_ptr->bit_depth == 8) + { + info_ptr->color_type = PNG_COLOR_TYPE_PALETTE; + } + } +#endif + +#ifdef PNG_READ_PACK_SUPPORTED + if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8)) + info_ptr->bit_depth = 8; +#endif + + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + info_ptr->channels = 1; + else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) + info_ptr->channels = 3; + else + info_ptr->channels = 1; + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED + if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA) + info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA; +#endif + + if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) + info_ptr->channels++; + +#ifdef PNG_READ_FILLER_SUPPORTED + /* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */ + if ((png_ptr->transformations & PNG_FILLER) && + ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || + (info_ptr->color_type == PNG_COLOR_TYPE_GRAY))) + { + info_ptr->channels++; + /* If adding a true alpha channel not just filler */ + if (png_ptr->transformations & PNG_ADD_ALPHA) + info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; + } +#endif + +#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \ +defined(PNG_READ_USER_TRANSFORM_SUPPORTED) + if (png_ptr->transformations & PNG_USER_TRANSFORM) + { + if (info_ptr->bit_depth < png_ptr->user_transform_depth) + info_ptr->bit_depth = png_ptr->user_transform_depth; + if (info_ptr->channels < png_ptr->user_transform_channels) + info_ptr->channels = png_ptr->user_transform_channels; + } +#endif + + info_ptr->pixel_depth = (png_byte)(info_ptr->channels * + info_ptr->bit_depth); + + info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width); + +#ifndef PNG_READ_EXPAND_SUPPORTED + if (png_ptr) + return; +#endif +} + +/* Transform the row. The order of transformations is significant, + * and is very touchy. If you add a transformation, take care to + * decide how it fits in with the other transformations here. + */ +void /* PRIVATE */ +png_do_read_transformations(png_structp png_ptr) +{ + png_debug(1, "in png_do_read_transformations"); + + if (png_ptr->row_buf == NULL) + { +#ifdef PNG_STDIO_SUPPORTED + char msg[50]; + + png_snprintf2(msg, 50, + "NULL row buffer for row %ld, pass %d", (long)png_ptr->row_number, + png_ptr->pass); + png_error(png_ptr, msg); +#else + png_error(png_ptr, "NULL row buffer"); +#endif + } +#ifdef PNG_WARN_UNINITIALIZED_ROW + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) + /* Application has failed to call either png_read_start_image() + * or png_read_update_info() after setting transforms that expand + * pixels. This check added to libpng-1.2.19 + */ +#if (PNG_WARN_UNINITIALIZED_ROW==1) + png_error(png_ptr, "Uninitialized row"); +#else + png_warning(png_ptr, "Uninitialized row"); +#endif +#endif + +#ifdef PNG_READ_EXPAND_SUPPORTED + if (png_ptr->transformations & PNG_EXPAND) + { + if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE) + { + png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1, + png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans); + } + else + { + if (png_ptr->num_trans && + (png_ptr->transformations & PNG_EXPAND_tRNS)) + png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1, + &(png_ptr->trans_color)); + else + png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1, + NULL); + } + } +#endif + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED + if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA) + png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, + PNG_FLAG_FILLER_AFTER | (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)); +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + if (png_ptr->transformations & PNG_RGB_TO_GRAY) + { + int rgb_error = + png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info), + png_ptr->row_buf + 1); + if (rgb_error) + { + png_ptr->rgb_to_gray_status=1; + if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == + PNG_RGB_TO_GRAY_WARN) + png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel"); + if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == + PNG_RGB_TO_GRAY_ERR) + png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel"); + } + } +#endif + +/* From Andreas Dilger e-mail to png-implement, 26 March 1998: + * + * In most cases, the "simple transparency" should be done prior to doing + * gray-to-RGB, or you will have to test 3x as many bytes to check if a + * pixel is transparent. You would also need to make sure that the + * transparency information is upgraded to RGB. + * + * To summarize, the current flow is: + * - Gray + simple transparency -> compare 1 or 2 gray bytes and composite + * with background "in place" if transparent, + * convert to RGB if necessary + * - Gray + alpha -> composite with gray background and remove alpha bytes, + * convert to RGB if necessary + * + * To support RGB backgrounds for gray images we need: + * - Gray + simple transparency -> convert to RGB + simple transparency, + * compare 3 or 6 bytes and composite with + * background "in place" if transparent + * (3x compare/pixel compared to doing + * composite with gray bkgrnd) + * - Gray + alpha -> convert to RGB + alpha, composite with background and + * remove alpha bytes (3x float + * operations/pixel compared with composite + * on gray background) + * + * Greg's change will do this. The reason it wasn't done before is for + * performance, as this increases the per-pixel operations. If we would check + * in advance if the background was gray or RGB, and position the gray-to-RGB + * transform appropriately, then it would save a lot of work/time. + */ + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED + /* If gray -> RGB, do so now only if background is non-gray; else do later + * for performance reasons + */ + if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && + !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) + png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_BACKGROUND_SUPPORTED + if ((png_ptr->transformations & PNG_BACKGROUND) && + ((png_ptr->num_trans != 0 ) || + (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) + png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1, + &(png_ptr->trans_color), &(png_ptr->background) +#ifdef PNG_READ_GAMMA_SUPPORTED + , &(png_ptr->background_1), + png_ptr->gamma_table, png_ptr->gamma_from_1, + png_ptr->gamma_to_1, png_ptr->gamma_16_table, + png_ptr->gamma_16_from_1, png_ptr->gamma_16_to_1, + png_ptr->gamma_shift +#endif +); +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED + if ((png_ptr->transformations & PNG_GAMMA) && +#ifdef PNG_READ_BACKGROUND_SUPPORTED + !((png_ptr->transformations & PNG_BACKGROUND) && + ((png_ptr->num_trans != 0) || + (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) && +#endif + (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)) + png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1, + png_ptr->gamma_table, png_ptr->gamma_16_table, + png_ptr->gamma_shift); +#endif + +#ifdef PNG_READ_16_TO_8_SUPPORTED + if (png_ptr->transformations & PNG_16_TO_8) + png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED + if (png_ptr->transformations & PNG_QUANTIZE) + { + png_do_quantize((png_row_infop)&(png_ptr->row_info), png_ptr->row_buf + 1, + png_ptr->palette_lookup, png_ptr->quantize_index); + if (png_ptr->row_info.rowbytes == (png_uint_32)0) + png_error(png_ptr, "png_do_quantize returned rowbytes=0"); + } +#endif + +#ifdef PNG_READ_INVERT_SUPPORTED + if (png_ptr->transformations & PNG_INVERT_MONO) + png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_SHIFT_SUPPORTED + if (png_ptr->transformations & PNG_SHIFT) + png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1, + &(png_ptr->shift)); +#endif + +#ifdef PNG_READ_PACK_SUPPORTED + if (png_ptr->transformations & PNG_PACK) + png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_BGR_SUPPORTED + if (png_ptr->transformations & PNG_BGR) + png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (png_ptr->transformations & PNG_PACKSWAP) + png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED + /* If gray -> RGB, do so now only if we did not do so above */ + if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && + (png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) + png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_FILLER_SUPPORTED + if (png_ptr->transformations & PNG_FILLER) + png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, + (png_uint_32)png_ptr->filler, png_ptr->flags); +#endif + +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED + if (png_ptr->transformations & PNG_INVERT_ALPHA) + png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED + if (png_ptr->transformations & PNG_SWAP_ALPHA) + png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_SWAP_SUPPORTED + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + if (png_ptr->transformations & PNG_USER_TRANSFORM) + { + if (png_ptr->read_user_transform_fn != NULL) + (*(png_ptr->read_user_transform_fn)) /* User read transform function */ + (png_ptr, /* png_ptr */ + &(png_ptr->row_info), /* row_info: */ + /* png_uint_32 width; width of row */ + /* png_uint_32 rowbytes; number of bytes in row */ + /* png_byte color_type; color type of pixels */ + /* png_byte bit_depth; bit depth of samples */ + /* png_byte channels; number of channels (1-4) */ + /* png_byte pixel_depth; bits per pixel (depth*channels) */ + png_ptr->row_buf + 1); /* start of pixel data for row */ +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED + if (png_ptr->user_transform_depth) + png_ptr->row_info.bit_depth = png_ptr->user_transform_depth; + if (png_ptr->user_transform_channels) + png_ptr->row_info.channels = png_ptr->user_transform_channels; +#endif + png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth * + png_ptr->row_info.channels); + png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, + png_ptr->row_info.width); + } +#endif + +} + +#ifdef PNG_READ_PACK_SUPPORTED +/* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel, + * without changing the actual values. Thus, if you had a row with + * a bit depth of 1, you would end up with bytes that only contained + * the numbers 0 or 1. If you would rather they contain 0 and 255, use + * png_do_shift() after this. + */ +void /* PRIVATE */ +png_do_unpack(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_unpack"); + + if (row_info->bit_depth < 8) + { + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + switch (row_info->bit_depth) + { + case 1: + { + png_bytep sp = row + (png_size_t)((row_width - 1) >> 3); + png_bytep dp = row + (png_size_t)row_width - 1; + png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07); + for (i = 0; i < row_width; i++) + { + *dp = (png_byte)((*sp >> shift) & 0x01); + if (shift == 7) + { + shift = 0; + sp--; + } + else + shift++; + + dp--; + } + break; + } + + case 2: + { + + png_bytep sp = row + (png_size_t)((row_width - 1) >> 2); + png_bytep dp = row + (png_size_t)row_width - 1; + png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); + for (i = 0; i < row_width; i++) + { + *dp = (png_byte)((*sp >> shift) & 0x03); + if (shift == 6) + { + shift = 0; + sp--; + } + else + shift += 2; + + dp--; + } + break; + } + + case 4: + { + png_bytep sp = row + (png_size_t)((row_width - 1) >> 1); + png_bytep dp = row + (png_size_t)row_width - 1; + png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); + for (i = 0; i < row_width; i++) + { + *dp = (png_byte)((*sp >> shift) & 0x0f); + if (shift == 4) + { + shift = 0; + sp--; + } + else + shift = 4; + + dp--; + } + break; + } + } + row_info->bit_depth = 8; + row_info->pixel_depth = (png_byte)(8 * row_info->channels); + row_info->rowbytes = row_width * row_info->channels; + } +} +#endif + +#ifdef PNG_READ_SHIFT_SUPPORTED +/* Reverse the effects of png_do_shift. This routine merely shifts the + * pixels back to their significant bits values. Thus, if you have + * a row of bit depth 8, but only 5 are significant, this will shift + * the values back to 0 through 31. + */ +void /* PRIVATE */ +png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits) +{ + png_debug(1, "in png_do_unshift"); + + if ( + row_info->color_type != PNG_COLOR_TYPE_PALETTE) + { + int shift[4]; + int channels = 0; + int c; + png_uint_16 value = 0; + png_uint_32 row_width = row_info->width; + + if (row_info->color_type & PNG_COLOR_MASK_COLOR) + { + shift[channels++] = row_info->bit_depth - sig_bits->red; + shift[channels++] = row_info->bit_depth - sig_bits->green; + shift[channels++] = row_info->bit_depth - sig_bits->blue; + } + else + { + shift[channels++] = row_info->bit_depth - sig_bits->gray; + } + if (row_info->color_type & PNG_COLOR_MASK_ALPHA) + { + shift[channels++] = row_info->bit_depth - sig_bits->alpha; + } + + for (c = 0; c < channels; c++) + { + if (shift[c] <= 0) + shift[c] = 0; + else + value = 1; + } + + if (!value) + return; + + switch (row_info->bit_depth) + { + case 2: + { + png_bytep bp; + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + + for (bp = row, i = 0; i < istop; i++) + { + *bp >>= 1; + *bp++ &= 0x55; + } + break; + } + + case 4: + { + png_bytep bp = row; + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) | + (png_byte)((int)0xf >> shift[0])); + + for (i = 0; i < istop; i++) + { + *bp >>= shift[0]; + *bp++ &= mask; + } + break; + } + + case 8: + { + png_bytep bp = row; + png_uint_32 i; + png_uint_32 istop = row_width * channels; + + for (i = 0; i < istop; i++) + { + *bp++ >>= shift[i%channels]; + } + break; + } + + case 16: + { + png_bytep bp = row; + png_uint_32 i; + png_uint_32 istop = channels * row_width; + + for (i = 0; i < istop; i++) + { + value = (png_uint_16)((*bp << 8) + *(bp + 1)); + value >>= shift[i%channels]; + *bp++ = (png_byte)(value >> 8); + *bp++ = (png_byte)(value & 0xff); + } + break; + } + } + } +} +#endif + +#ifdef PNG_READ_16_TO_8_SUPPORTED +/* Chop rows of bit depth 16 down to 8 */ +void /* PRIVATE */ +png_do_chop(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_chop"); + + if (row_info->bit_depth == 16) + { + png_bytep sp = row; + png_bytep dp = row; + png_uint_32 i; + png_uint_32 istop = row_info->width * row_info->channels; + + for (i = 0; i> 8)) >> 8; + * + * Approximate calculation with shift/add instead of multiply/divide: + * *dp = ((((png_uint_32)(*sp) << 8) | + * (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8; + * + * What we actually do to avoid extra shifting and conversion: + */ + + *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0); +#else + /* Simply discard the low order byte */ + *dp = *sp; +#endif + } + row_info->bit_depth = 8; + row_info->pixel_depth = (png_byte)(8 * row_info->channels); + row_info->rowbytes = row_info->width * row_info->channels; + } +} +#endif + +#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED +void /* PRIVATE */ +png_do_read_swap_alpha(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_read_swap_alpha"); + + { + png_uint_32 row_width = row_info->width; + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + /* This converts from RGBA to ARGB */ + if (row_info->bit_depth == 8) + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save; + } + } + /* This converts from RRGGBBAA to AARRGGBB */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save[2]; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save[0] = *(--sp); + save[1] = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save[0]; + *(--dp) = save[1]; + } + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + /* This converts from GA to AG */ + if (row_info->bit_depth == 8) + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save; + } + } + /* This converts from GGAA to AAGG */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save[2]; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save[0] = *(--sp); + save[1] = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save[0]; + *(--dp) = save[1]; + } + } + } + } +} +#endif + +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED +void /* PRIVATE */ +png_do_read_invert_alpha(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_read_invert_alpha"); + + { + png_uint_32 row_width = row_info->width; + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + /* This inverts the alpha channel in RGBA */ + if (row_info->bit_depth == 8) + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + +/* This does nothing: + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + We can replace it with: +*/ + sp-=3; + dp=sp; + } + } + /* This inverts the alpha channel in RRGGBBAA */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + *(--dp) = (png_byte)(255 - *(--sp)); + +/* This does nothing: + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + We can replace it with: +*/ + sp-=6; + dp=sp; + } + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + /* This inverts the alpha channel in GA */ + if (row_info->bit_depth == 8) + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + *(--dp) = *(--sp); + } + } + /* This inverts the alpha channel in GGAA */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + *(--dp) = (png_byte)(255 - *(--sp)); +/* + *(--dp) = *(--sp); + *(--dp) = *(--sp); +*/ + sp-=2; + dp=sp; + } + } + } + } +} +#endif + +#ifdef PNG_READ_FILLER_SUPPORTED +/* Add filler channel if we have RGB color */ +void /* PRIVATE */ +png_do_read_filler(png_row_infop row_info, png_bytep row, + png_uint_32 filler, png_uint_32 flags) +{ + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + png_byte hi_filler = (png_byte)((filler>>8) & 0xff); + png_byte lo_filler = (png_byte)(filler & 0xff); + + png_debug(1, "in png_do_read_filler"); + + if ( + row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + if (row_info->bit_depth == 8) + { + /* This changes the data from G to GX */ + if (flags & PNG_FLAG_FILLER_AFTER) + { + png_bytep sp = row + (png_size_t)row_width; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 1; i < row_width; i++) + { + *(--dp) = lo_filler; + *(--dp) = *(--sp); + } + *(--dp) = lo_filler; + row_info->channels = 2; + row_info->pixel_depth = 16; + row_info->rowbytes = row_width * 2; + } + /* This changes the data from G to XG */ + else + { + png_bytep sp = row + (png_size_t)row_width; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = lo_filler; + } + row_info->channels = 2; + row_info->pixel_depth = 16; + row_info->rowbytes = row_width * 2; + } + } + else if (row_info->bit_depth == 16) + { + /* This changes the data from GG to GGXX */ + if (flags & PNG_FLAG_FILLER_AFTER) + { + png_bytep sp = row + (png_size_t)row_width * 2; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 1; i < row_width; i++) + { + *(--dp) = hi_filler; + *(--dp) = lo_filler; + *(--dp) = *(--sp); + *(--dp) = *(--sp); + } + *(--dp) = hi_filler; + *(--dp) = lo_filler; + row_info->channels = 2; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + /* This changes the data from GG to XXGG */ + else + { + png_bytep sp = row + (png_size_t)row_width * 2; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = hi_filler; + *(--dp) = lo_filler; + } + row_info->channels = 2; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + } + } /* COLOR_TYPE == GRAY */ + else if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + if (row_info->bit_depth == 8) + { + /* This changes the data from RGB to RGBX */ + if (flags & PNG_FLAG_FILLER_AFTER) + { + png_bytep sp = row + (png_size_t)row_width * 3; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 1; i < row_width; i++) + { + *(--dp) = lo_filler; + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + } + *(--dp) = lo_filler; + row_info->channels = 4; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + /* This changes the data from RGB to XRGB */ + else + { + png_bytep sp = row + (png_size_t)row_width * 3; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = lo_filler; + } + row_info->channels = 4; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + } + else if (row_info->bit_depth == 16) + { + /* This changes the data from RRGGBB to RRGGBBXX */ + if (flags & PNG_FLAG_FILLER_AFTER) + { + png_bytep sp = row + (png_size_t)row_width * 6; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 1; i < row_width; i++) + { + *(--dp) = hi_filler; + *(--dp) = lo_filler; + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + } + *(--dp) = hi_filler; + *(--dp) = lo_filler; + row_info->channels = 4; + row_info->pixel_depth = 64; + row_info->rowbytes = row_width * 8; + } + /* This changes the data from RRGGBB to XXRRGGBB */ + else + { + png_bytep sp = row + (png_size_t)row_width * 6; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = hi_filler; + *(--dp) = lo_filler; + } + row_info->channels = 4; + row_info->pixel_depth = 64; + row_info->rowbytes = row_width * 8; + } + } + } /* COLOR_TYPE == RGB */ +} +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED +/* Expand grayscale files to RGB, with or without alpha */ +void /* PRIVATE */ +png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) +{ + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + png_debug(1, "in png_do_gray_to_rgb"); + + if (row_info->bit_depth >= 8 && + !(row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + if (row_info->bit_depth == 8) + { + png_bytep sp = row + (png_size_t)row_width - 1; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(dp--) = *sp; + *(dp--) = *sp; + *(dp--) = *(sp--); + } + } + else + { + png_bytep sp = row + (png_size_t)row_width * 2 - 1; + png_bytep dp = sp + (png_size_t)row_width * 4; + for (i = 0; i < row_width; i++) + { + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *(sp--); + *(dp--) = *(sp--); + } + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (row_info->bit_depth == 8) + { + png_bytep sp = row + (png_size_t)row_width * 2 - 1; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(dp--) = *(sp--); + *(dp--) = *sp; + *(dp--) = *sp; + *(dp--) = *(sp--); + } + } + else + { + png_bytep sp = row + (png_size_t)row_width * 4 - 1; + png_bytep dp = sp + (png_size_t)row_width * 4; + for (i = 0; i < row_width; i++) + { + *(dp--) = *(sp--); + *(dp--) = *(sp--); + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *(sp--); + *(dp--) = *(sp--); + } + } + } + row_info->channels += (png_byte)2; + row_info->color_type |= PNG_COLOR_MASK_COLOR; + row_info->pixel_depth = (png_byte)(row_info->channels * + row_info->bit_depth); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } +} +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +/* Reduce RGB files to grayscale, with or without alpha + * using the equation given in Poynton's ColorFAQ at + * (THIS LINK IS DEAD June 2008) + * New link: + * + * Charles Poynton poynton at poynton.com + * + * Y = 0.212671 * R + 0.715160 * G + 0.072169 * B + * + * We approximate this with + * + * Y = 0.21268 * R + 0.7151 * G + 0.07217 * B + * + * which can be expressed with integers as + * + * Y = (6969 * R + 23434 * G + 2365 * B)/32768 + * + * The calculation is to be done in a linear colorspace. + * + * Other integer coefficents can be used via png_set_rgb_to_gray(). + */ +int /* PRIVATE */ +png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row) + +{ + png_uint_32 i; + + png_uint_32 row_width = row_info->width; + int rgb_error = 0; + + png_debug(1, "in png_do_rgb_to_gray"); + + if ( + (row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff; + png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff; + png_uint_32 bc = png_ptr->rgb_to_gray_blue_coeff; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + if (row_info->bit_depth == 8) + { +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + + for (i = 0; i < row_width; i++) + { + png_byte red = png_ptr->gamma_to_1[*(sp++)]; + png_byte green = png_ptr->gamma_to_1[*(sp++)]; + png_byte blue = png_ptr->gamma_to_1[*(sp++)]; + if (red != green || red != blue) + { + rgb_error |= 1; + *(dp++) = png_ptr->gamma_from_1[ + (rc*red + gc*green + bc*blue)>>15]; + } + else + *(dp++) = *(sp - 1); + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_byte red = *(sp++); + png_byte green = *(sp++); + png_byte blue = *(sp++); + if (red != green || red != blue) + { + rgb_error |= 1; + *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15); + } + else + *(dp++) = *(sp - 1); + } + } + } + + else /* RGB bit_depth == 16 */ + { +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_16_to_1 != NULL && + png_ptr->gamma_16_from_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, w; + + red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + + if (red == green && red == blue) + w = red; + else + { + png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >> + png_ptr->gamma_shift][red>>8]; + png_uint_16 green_1 = + png_ptr->gamma_16_to_1[(green&0xff) >> + png_ptr->gamma_shift][green>>8]; + png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >> + png_ptr->gamma_shift][blue>>8]; + png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_1 + + bc*blue_1)>>15); + w = png_ptr->gamma_16_from_1[(gray16&0xff) >> + png_ptr->gamma_shift][gray16 >> 8]; + rgb_error |= 1; + } + + *(dp++) = (png_byte)((w>>8) & 0xff); + *(dp++) = (png_byte)(w & 0xff); + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, gray16; + + red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + + if (red != green || red != blue) + rgb_error |= 1; + gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15); + *(dp++) = (png_byte)((gray16>>8) & 0xff); + *(dp++) = (png_byte)(gray16 & 0xff); + } + } + } + } + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + if (row_info->bit_depth == 8) + { +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_byte red = png_ptr->gamma_to_1[*(sp++)]; + png_byte green = png_ptr->gamma_to_1[*(sp++)]; + png_byte blue = png_ptr->gamma_to_1[*(sp++)]; + if (red != green || red != blue) + rgb_error |= 1; + *(dp++) = png_ptr->gamma_from_1 + [(rc*red + gc*green + bc*blue)>>15]; + *(dp++) = *(sp++); /* alpha */ + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_byte red = *(sp++); + png_byte green = *(sp++); + png_byte blue = *(sp++); + if (red != green || red != blue) + rgb_error |= 1; + *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15); + *(dp++) = *(sp++); /* alpha */ + } + } + } + else /* RGBA bit_depth == 16 */ + { +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_16_to_1 != NULL && + png_ptr->gamma_16_from_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, w; + + red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; + + if (red == green && red == blue) + w = red; + else + { + png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >> + png_ptr->gamma_shift][red>>8]; + png_uint_16 green_1 = + png_ptr->gamma_16_to_1[(green&0xff) >> + png_ptr->gamma_shift][green>>8]; + png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >> + png_ptr->gamma_shift][blue>>8]; + png_uint_16 gray16 = (png_uint_16)((rc * red_1 + + gc * green_1 + bc * blue_1)>>15); + w = png_ptr->gamma_16_from_1[(gray16&0xff) >> + png_ptr->gamma_shift][gray16 >> 8]; + rgb_error |= 1; + } + + *(dp++) = (png_byte)((w>>8) & 0xff); + *(dp++) = (png_byte)(w & 0xff); + *(dp++) = *(sp++); /* alpha */ + *(dp++) = *(sp++); + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, gray16; + red = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2; + green = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2; + blue = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2; + if (red != green || red != blue) + rgb_error |= 1; + gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15); + *(dp++) = (png_byte)((gray16>>8) & 0xff); + *(dp++) = (png_byte)(gray16 & 0xff); + *(dp++) = *(sp++); /* alpha */ + *(dp++) = *(sp++); + } + } + } + } + row_info->channels -= (png_byte)2; + row_info->color_type &= ~PNG_COLOR_MASK_COLOR; + row_info->pixel_depth = (png_byte)(row_info->channels * + row_info->bit_depth); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } + return rgb_error; +} +#endif + +/* Build a grayscale palette. Palette is assumed to be 1 << bit_depth + * large of png_color. This lets grayscale images be treated as + * paletted. Most useful for gamma correction and simplification + * of code. + */ +void PNGAPI +png_build_grayscale_palette(int bit_depth, png_colorp palette) +{ + int num_palette; + int color_inc; + int i; + int v; + + png_debug(1, "in png_do_build_grayscale_palette"); + + if (palette == NULL) + return; + + switch (bit_depth) + { + case 1: + num_palette = 2; + color_inc = 0xff; + break; + + case 2: + num_palette = 4; + color_inc = 0x55; + break; + + case 4: + num_palette = 16; + color_inc = 0x11; + break; + + case 8: + num_palette = 256; + color_inc = 1; + break; + + default: + num_palette = 0; + color_inc = 0; + break; + } + + for (i = 0, v = 0; i < num_palette; i++, v += color_inc) + { + palette[i].red = (png_byte)v; + palette[i].green = (png_byte)v; + palette[i].blue = (png_byte)v; + } +} + + +#ifdef PNG_READ_BACKGROUND_SUPPORTED +/* Replace any alpha or transparency with the supplied background color. + * "background" is already in the screen gamma, while "background_1" is + * at a gamma of 1.0. Paletted files have already been taken care of. + */ +void /* PRIVATE */ +png_do_background(png_row_infop row_info, png_bytep row, + png_color_16p trans_color, png_color_16p background +#ifdef PNG_READ_GAMMA_SUPPORTED + , png_color_16p background_1, + png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1, + png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1, + png_uint_16pp gamma_16_to_1, int gamma_shift +#endif + ) +{ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + int shift; + + png_debug(1, "in png_do_background"); + + if (background != NULL && + (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) || + (row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_color))) + { + switch (row_info->color_type) + { + case PNG_COLOR_TYPE_GRAY: + { + switch (row_info->bit_depth) + { + case 1: + { + sp = row; + shift = 7; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x01) + == trans_color->gray) + { + *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + if (!shift) + { + shift = 7; + sp++; + } + else + shift--; + } + break; + } + + case 2: + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_table != NULL) + { + sp = row; + shift = 6; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x03) + == trans_color->gray) + { + *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + else + { + png_byte p = (png_byte)((*sp >> shift) & 0x03); + png_byte g = (png_byte)((gamma_table [p | (p << 2) | + (p << 4) | (p << 6)] >> 6) & 0x03); + *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *sp |= (png_byte)(g << shift); + } + if (!shift) + { + shift = 6; + sp++; + } + else + shift -= 2; + } + } + else +#endif + { + sp = row; + shift = 6; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x03) + == trans_color->gray) + { + *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + if (!shift) + { + shift = 6; + sp++; + } + else + shift -= 2; + } + } + break; + } + + case 4: + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_table != NULL) + { + sp = row; + shift = 4; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x0f) + == trans_color->gray) + { + *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + else + { + png_byte p = (png_byte)((*sp >> shift) & 0x0f); + png_byte g = (png_byte)((gamma_table[p | + (p << 4)] >> 4) & 0x0f); + *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *sp |= (png_byte)(g << shift); + } + if (!shift) + { + shift = 4; + sp++; + } + else + shift -= 4; + } + } + else +#endif + { + sp = row; + shift = 4; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x0f) + == trans_color->gray) + { + *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + if (!shift) + { + shift = 4; + sp++; + } + else + shift -= 4; + } + } + break; + } + + case 8: + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp++) + { + if (*sp == trans_color->gray) + { + *sp = (png_byte)background->gray; + } + else + { + *sp = gamma_table[*sp]; + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp++) + { + if (*sp == trans_color->gray) + { + *sp = (png_byte)background->gray; + } + } + } + break; + } + + case 16: + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_16 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 2) + { + png_uint_16 v; + + v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + if (v == trans_color->gray) + { + /* Background is already in screen gamma */ + *sp = (png_byte)((background->gray >> 8) & 0xff); + *(sp + 1) = (png_byte)(background->gray & 0xff); + } + else + { + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 2) + { + png_uint_16 v; + + v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + if (v == trans_color->gray) + { + *sp = (png_byte)((background->gray >> 8) & 0xff); + *(sp + 1) = (png_byte)(background->gray & 0xff); + } + } + } + break; + } + } + break; + } + + case PNG_COLOR_TYPE_RGB: + { + if (row_info->bit_depth == 8) + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 3) + { + if (*sp == trans_color->red && + *(sp + 1) == trans_color->green && + *(sp + 2) == trans_color->blue) + { + *sp = (png_byte)background->red; + *(sp + 1) = (png_byte)background->green; + *(sp + 2) = (png_byte)background->blue; + } + else + { + *sp = gamma_table[*sp]; + *(sp + 1) = gamma_table[*(sp + 1)]; + *(sp + 2) = gamma_table[*(sp + 2)]; + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 3) + { + if (*sp == trans_color->red && + *(sp + 1) == trans_color->green && + *(sp + 2) == trans_color->blue) + { + *sp = (png_byte)background->red; + *(sp + 1) = (png_byte)background->green; + *(sp + 2) = (png_byte)background->blue; + } + } + } + } + else /* if (row_info->bit_depth == 16) */ + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_16 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 6) + { + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); + png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5)); + if (r == trans_color->red && g == trans_color->green && + b == trans_color->blue) + { + /* Background is already in screen gamma */ + *sp = (png_byte)((background->red >> 8) & 0xff); + *(sp + 1) = (png_byte)(background->red & 0xff); + *(sp + 2) = (png_byte)((background->green >> 8) & 0xff); + *(sp + 3) = (png_byte)(background->green & 0xff); + *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff); + *(sp + 5) = (png_byte)(background->blue & 0xff); + } + else + { + png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; + *(sp + 2) = (png_byte)((v >> 8) & 0xff); + *(sp + 3) = (png_byte)(v & 0xff); + v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; + *(sp + 4) = (png_byte)((v >> 8) & 0xff); + *(sp + 5) = (png_byte)(v & 0xff); + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 6) + { + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp+1)); + png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); + png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5)); + + if (r == trans_color->red && g == trans_color->green && + b == trans_color->blue) + { + *sp = (png_byte)((background->red >> 8) & 0xff); + *(sp + 1) = (png_byte)(background->red & 0xff); + *(sp + 2) = (png_byte)((background->green >> 8) & 0xff); + *(sp + 3) = (png_byte)(background->green & 0xff); + *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff); + *(sp + 5) = (png_byte)(background->blue & 0xff); + } + } + } + } + break; + } + + case PNG_COLOR_TYPE_GRAY_ALPHA: + { + if (row_info->bit_depth == 8) + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_to_1 != NULL && gamma_from_1 != NULL && + gamma_table != NULL) + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 2, dp++) + { + png_uint_16 a = *(sp + 1); + + if (a == 0xff) + { + *dp = gamma_table[*sp]; + } + else if (a == 0) + { + /* Background is already in screen gamma */ + *dp = (png_byte)background->gray; + } + else + { + png_byte v, w; + + v = gamma_to_1[*sp]; + png_composite(w, v, a, background_1->gray); + *dp = gamma_from_1[w]; + } + } + } + else +#endif + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 2, dp++) + { + png_byte a = *(sp + 1); + + if (a == 0xff) + { + *dp = *sp; + } +#ifdef PNG_READ_GAMMA_SUPPORTED + else if (a == 0) + { + *dp = (png_byte)background->gray; + } + else + { + png_composite(*dp, *sp, a, background_1->gray); + } +#else + *dp = (png_byte)background->gray; +#endif + } + } + } + else /* if (png_ptr->bit_depth == 16) */ + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_16 != NULL && gamma_16_from_1 != NULL && + gamma_16_to_1 != NULL) + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 4, dp += 2) + { + png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); + + if (a == (png_uint_16)0xffff) + { + png_uint_16 v; + + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *dp = (png_byte)((v >> 8) & 0xff); + *(dp + 1) = (png_byte)(v & 0xff); + } +#ifdef PNG_READ_GAMMA_SUPPORTED + else if (a == 0) +#else + else +#endif + { + /* Background is already in screen gamma */ + *dp = (png_byte)((background->gray >> 8) & 0xff); + *(dp + 1) = (png_byte)(background->gray & 0xff); + } +#ifdef PNG_READ_GAMMA_SUPPORTED + else + { + png_uint_16 g, v, w; + + g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; + png_composite_16(v, g, a, background_1->gray); + w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8]; + *dp = (png_byte)((w >> 8) & 0xff); + *(dp + 1) = (png_byte)(w & 0xff); + } +#endif + } + } + else +#endif + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 4, dp += 2) + { + png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); + if (a == (png_uint_16)0xffff) + { + png_memcpy(dp, sp, 2); + } +#ifdef PNG_READ_GAMMA_SUPPORTED + else if (a == 0) +#else + else +#endif + { + *dp = (png_byte)((background->gray >> 8) & 0xff); + *(dp + 1) = (png_byte)(background->gray & 0xff); + } +#ifdef PNG_READ_GAMMA_SUPPORTED + else + { + png_uint_16 g, v; + + g = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_composite_16(v, g, a, background_1->gray); + *dp = (png_byte)((v >> 8) & 0xff); + *(dp + 1) = (png_byte)(v & 0xff); + } +#endif + } + } + } + break; + } + + case PNG_COLOR_TYPE_RGB_ALPHA: + { + if (row_info->bit_depth == 8) + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_to_1 != NULL && gamma_from_1 != NULL && + gamma_table != NULL) + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 4, dp += 3) + { + png_byte a = *(sp + 3); + + if (a == 0xff) + { + *dp = gamma_table[*sp]; + *(dp + 1) = gamma_table[*(sp + 1)]; + *(dp + 2) = gamma_table[*(sp + 2)]; + } + else if (a == 0) + { + /* Background is already in screen gamma */ + *dp = (png_byte)background->red; + *(dp + 1) = (png_byte)background->green; + *(dp + 2) = (png_byte)background->blue; + } + else + { + png_byte v, w; + + v = gamma_to_1[*sp]; + png_composite(w, v, a, background_1->red); + *dp = gamma_from_1[w]; + v = gamma_to_1[*(sp + 1)]; + png_composite(w, v, a, background_1->green); + *(dp + 1) = gamma_from_1[w]; + v = gamma_to_1[*(sp + 2)]; + png_composite(w, v, a, background_1->blue); + *(dp + 2) = gamma_from_1[w]; + } + } + } + else +#endif + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 4, dp += 3) + { + png_byte a = *(sp + 3); + + if (a == 0xff) + { + *dp = *sp; + *(dp + 1) = *(sp + 1); + *(dp + 2) = *(sp + 2); + } + else if (a == 0) + { + *dp = (png_byte)background->red; + *(dp + 1) = (png_byte)background->green; + *(dp + 2) = (png_byte)background->blue; + } + else + { + png_composite(*dp, *sp, a, background->red); + png_composite(*(dp + 1), *(sp + 1), a, + background->green); + png_composite(*(dp + 2), *(sp + 2), a, + background->blue); + } + } + } + } + else /* if (row_info->bit_depth == 16) */ + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_16 != NULL && gamma_16_from_1 != NULL && + gamma_16_to_1 != NULL) + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 8, dp += 6) + { + png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) + << 8) + (png_uint_16)(*(sp + 7))); + if (a == (png_uint_16)0xffff) + { + png_uint_16 v; + + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *dp = (png_byte)((v >> 8) & 0xff); + *(dp + 1) = (png_byte)(v & 0xff); + v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; + *(dp + 2) = (png_byte)((v >> 8) & 0xff); + *(dp + 3) = (png_byte)(v & 0xff); + v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; + *(dp + 4) = (png_byte)((v >> 8) & 0xff); + *(dp + 5) = (png_byte)(v & 0xff); + } + else if (a == 0) + { + /* Background is already in screen gamma */ + *dp = (png_byte)((background->red >> 8) & 0xff); + *(dp + 1) = (png_byte)(background->red & 0xff); + *(dp + 2) = (png_byte)((background->green >> 8) & 0xff); + *(dp + 3) = (png_byte)(background->green & 0xff); + *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff); + *(dp + 5) = (png_byte)(background->blue & 0xff); + } + else + { + png_uint_16 v, w, x; + + v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; + png_composite_16(w, v, a, background_1->red); + x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; + *dp = (png_byte)((x >> 8) & 0xff); + *(dp + 1) = (png_byte)(x & 0xff); + v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)]; + png_composite_16(w, v, a, background_1->green); + x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; + *(dp + 2) = (png_byte)((x >> 8) & 0xff); + *(dp + 3) = (png_byte)(x & 0xff); + v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)]; + png_composite_16(w, v, a, background_1->blue); + x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8]; + *(dp + 4) = (png_byte)((x >> 8) & 0xff); + *(dp + 5) = (png_byte)(x & 0xff); + } + } + } + else +#endif + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 8, dp += 6) + { + png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) + << 8) + (png_uint_16)(*(sp + 7))); + if (a == (png_uint_16)0xffff) + { + png_memcpy(dp, sp, 6); + } + else if (a == 0) + { + *dp = (png_byte)((background->red >> 8) & 0xff); + *(dp + 1) = (png_byte)(background->red & 0xff); + *(dp + 2) = (png_byte)((background->green >> 8) & 0xff); + *(dp + 3) = (png_byte)(background->green & 0xff); + *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff); + *(dp + 5) = (png_byte)(background->blue & 0xff); + } + else + { + png_uint_16 v; + + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) + + *(sp + 5)); + + png_composite_16(v, r, a, background->red); + *dp = (png_byte)((v >> 8) & 0xff); + *(dp + 1) = (png_byte)(v & 0xff); + png_composite_16(v, g, a, background->green); + *(dp + 2) = (png_byte)((v >> 8) & 0xff); + *(dp + 3) = (png_byte)(v & 0xff); + png_composite_16(v, b, a, background->blue); + *(dp + 4) = (png_byte)((v >> 8) & 0xff); + *(dp + 5) = (png_byte)(v & 0xff); + } + } + } + } + break; + } + } + + if (row_info->color_type & PNG_COLOR_MASK_ALPHA) + { + row_info->color_type &= ~PNG_COLOR_MASK_ALPHA; + row_info->channels--; + row_info->pixel_depth = (png_byte)(row_info->channels * + row_info->bit_depth); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } + } +} +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED +/* Gamma correct the image, avoiding the alpha channel. Make sure + * you do this after you deal with the transparency issue on grayscale + * or RGB images. If your bit depth is 8, use gamma_table, if it + * is 16, use gamma_16_table and gamma_shift. Build these with + * build_gamma_table(). + */ +void /* PRIVATE */ +png_do_gamma(png_row_infop row_info, png_bytep row, + png_bytep gamma_table, png_uint_16pp gamma_16_table, + int gamma_shift) +{ + png_bytep sp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_gamma"); + + if ( + ((row_info->bit_depth <= 8 && gamma_table != NULL) || + (row_info->bit_depth == 16 && gamma_16_table != NULL))) + { + switch (row_info->color_type) + { + case PNG_COLOR_TYPE_RGB: + { + if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp++; + *sp = gamma_table[*sp]; + sp++; + *sp = gamma_table[*sp]; + sp++; + } + } + else /* if (row_info->bit_depth == 16) */ + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v; + + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + } + } + break; + } + + case PNG_COLOR_TYPE_RGB_ALPHA: + { + if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp++; + *sp = gamma_table[*sp]; + sp++; + *sp = gamma_table[*sp]; + sp++; + sp++; + } + } + else /* if (row_info->bit_depth == 16) */ + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 4; + } + } + break; + } + + case PNG_COLOR_TYPE_GRAY_ALPHA: + { + if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp += 2; + } + } + else /* if (row_info->bit_depth == 16) */ + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 4; + } + } + break; + } + + case PNG_COLOR_TYPE_GRAY: + { + if (row_info->bit_depth == 2) + { + sp = row; + for (i = 0; i < row_width; i += 4) + { + int a = *sp & 0xc0; + int b = *sp & 0x30; + int c = *sp & 0x0c; + int d = *sp & 0x03; + + *sp = (png_byte)( + ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)]) ) & 0xc0)| + ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)| + ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)| + ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) )); + sp++; + } + } + + if (row_info->bit_depth == 4) + { + sp = row; + for (i = 0; i < row_width; i += 2) + { + int msb = *sp & 0xf0; + int lsb = *sp & 0x0f; + + *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0) + | (((int)gamma_table[(lsb << 4) | lsb]) >> 4)); + sp++; + } + } + + else if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp++; + } + } + + else if (row_info->bit_depth == 16) + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + } + } + break; + } + } + } +} +#endif + +#ifdef PNG_READ_EXPAND_SUPPORTED +/* Expands a palette row to an RGB or RGBA row depending + * upon whether you supply trans and num_trans. + */ +void /* PRIVATE */ +png_do_expand_palette(png_row_infop row_info, png_bytep row, + png_colorp palette, png_bytep trans_alpha, int num_trans) +{ + int shift, value; + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_expand_palette"); + + if ( + row_info->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (row_info->bit_depth < 8) + { + switch (row_info->bit_depth) + { + case 1: + { + sp = row + (png_size_t)((row_width - 1) >> 3); + dp = row + (png_size_t)row_width - 1; + shift = 7 - (int)((row_width + 7) & 0x07); + for (i = 0; i < row_width; i++) + { + if ((*sp >> shift) & 0x01) + *dp = 1; + else + *dp = 0; + if (shift == 7) + { + shift = 0; + sp--; + } + else + shift++; + + dp--; + } + break; + } + + case 2: + { + sp = row + (png_size_t)((row_width - 1) >> 2); + dp = row + (png_size_t)row_width - 1; + shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x03; + *dp = (png_byte)value; + if (shift == 6) + { + shift = 0; + sp--; + } + else + shift += 2; + + dp--; + } + break; + } + + case 4: + { + sp = row + (png_size_t)((row_width - 1) >> 1); + dp = row + (png_size_t)row_width - 1; + shift = (int)((row_width & 0x01) << 2); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x0f; + *dp = (png_byte)value; + if (shift == 4) + { + shift = 0; + sp--; + } + else + shift += 4; + + dp--; + } + break; + } + } + row_info->bit_depth = 8; + row_info->pixel_depth = 8; + row_info->rowbytes = row_width; + } + switch (row_info->bit_depth) + { + case 8: + { + if (trans_alpha != NULL) + { + sp = row + (png_size_t)row_width - 1; + dp = row + (png_size_t)(row_width << 2) - 1; + + for (i = 0; i < row_width; i++) + { + if ((int)(*sp) >= num_trans) + *dp-- = 0xff; + else + *dp-- = trans_alpha[*sp]; + *dp-- = palette[*sp].blue; + *dp-- = palette[*sp].green; + *dp-- = palette[*sp].red; + sp--; + } + row_info->bit_depth = 8; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + row_info->color_type = 6; + row_info->channels = 4; + } + else + { + sp = row + (png_size_t)row_width - 1; + dp = row + (png_size_t)(row_width * 3) - 1; + + for (i = 0; i < row_width; i++) + { + *dp-- = palette[*sp].blue; + *dp-- = palette[*sp].green; + *dp-- = palette[*sp].red; + sp--; + } + + row_info->bit_depth = 8; + row_info->pixel_depth = 24; + row_info->rowbytes = row_width * 3; + row_info->color_type = 2; + row_info->channels = 3; + } + break; + } + } + } +} + +/* If the bit depth < 8, it is expanded to 8. Also, if the already + * expanded transparency value is supplied, an alpha channel is built. + */ +void /* PRIVATE */ +png_do_expand(png_row_infop row_info, png_bytep row, + png_color_16p trans_value) +{ + int shift, value; + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_expand"); + + { + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + png_uint_16 gray = (png_uint_16)(trans_value ? trans_value->gray : 0); + + if (row_info->bit_depth < 8) + { + switch (row_info->bit_depth) + { + case 1: + { + gray = (png_uint_16)((gray&0x01)*0xff); + sp = row + (png_size_t)((row_width - 1) >> 3); + dp = row + (png_size_t)row_width - 1; + shift = 7 - (int)((row_width + 7) & 0x07); + for (i = 0; i < row_width; i++) + { + if ((*sp >> shift) & 0x01) + *dp = 0xff; + else + *dp = 0; + if (shift == 7) + { + shift = 0; + sp--; + } + else + shift++; + + dp--; + } + break; + } + + case 2: + { + gray = (png_uint_16)((gray&0x03)*0x55); + sp = row + (png_size_t)((row_width - 1) >> 2); + dp = row + (png_size_t)row_width - 1; + shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x03; + *dp = (png_byte)(value | (value << 2) | (value << 4) | + (value << 6)); + if (shift == 6) + { + shift = 0; + sp--; + } + else + shift += 2; + + dp--; + } + break; + } + + case 4: + { + gray = (png_uint_16)((gray&0x0f)*0x11); + sp = row + (png_size_t)((row_width - 1) >> 1); + dp = row + (png_size_t)row_width - 1; + shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x0f; + *dp = (png_byte)(value | (value << 4)); + if (shift == 4) + { + shift = 0; + sp--; + } + else + shift = 4; + + dp--; + } + break; + } + } + + row_info->bit_depth = 8; + row_info->pixel_depth = 8; + row_info->rowbytes = row_width; + } + + if (trans_value != NULL) + { + if (row_info->bit_depth == 8) + { + gray = gray & 0xff; + sp = row + (png_size_t)row_width - 1; + dp = row + (png_size_t)(row_width << 1) - 1; + for (i = 0; i < row_width; i++) + { + if (*sp == gray) + *dp-- = 0; + else + *dp-- = 0xff; + *dp-- = *sp--; + } + } + + else if (row_info->bit_depth == 16) + { + png_byte gray_high = (gray >> 8) & 0xff; + png_byte gray_low = gray & 0xff; + sp = row + row_info->rowbytes - 1; + dp = row + (row_info->rowbytes << 1) - 1; + for (i = 0; i < row_width; i++) + { + if (*(sp - 1) == gray_high && *(sp) == gray_low) + { + *dp-- = 0; + *dp-- = 0; + } + else + { + *dp-- = 0xff; + *dp-- = 0xff; + } + *dp-- = *sp--; + *dp-- = *sp--; + } + } + + row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA; + row_info->channels = 2; + row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, + row_width); + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value) + { + if (row_info->bit_depth == 8) + { + png_byte red = trans_value->red & 0xff; + png_byte green = trans_value->green & 0xff; + png_byte blue = trans_value->blue & 0xff; + sp = row + (png_size_t)row_info->rowbytes - 1; + dp = row + (png_size_t)(row_width << 2) - 1; + for (i = 0; i < row_width; i++) + { + if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue) + *dp-- = 0; + else + *dp-- = 0xff; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + } + } + else if (row_info->bit_depth == 16) + { + png_byte red_high = (trans_value->red >> 8) & 0xff; + png_byte green_high = (trans_value->green >> 8) & 0xff; + png_byte blue_high = (trans_value->blue >> 8) & 0xff; + png_byte red_low = trans_value->red & 0xff; + png_byte green_low = trans_value->green & 0xff; + png_byte blue_low = trans_value->blue & 0xff; + sp = row + row_info->rowbytes - 1; + dp = row + (png_size_t)(row_width << 3) - 1; + for (i = 0; i < row_width; i++) + { + if (*(sp - 5) == red_high && + *(sp - 4) == red_low && + *(sp - 3) == green_high && + *(sp - 2) == green_low && + *(sp - 1) == blue_high && + *(sp ) == blue_low) + { + *dp-- = 0; + *dp-- = 0; + } + else + { + *dp-- = 0xff; + *dp-- = 0xff; + } + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + } + } + row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA; + row_info->channels = 4; + row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } + } +} +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +void /* PRIVATE */ +png_do_quantize(png_row_infop row_info, png_bytep row, + png_bytep palette_lookup, png_bytep quantize_lookup) +{ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_quantize"); + + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB && + palette_lookup && row_info->bit_depth == 8) + { + int r, g, b, p; + sp = row; + dp = row; + for (i = 0; i < row_width; i++) + { + r = *sp++; + g = *sp++; + b = *sp++; + + /* This looks real messy, but the compiler will reduce + * it down to a reasonable formula. For example, with + * 5 bits per color, we get: + * p = (((r >> 3) & 0x1f) << 10) | + * (((g >> 3) & 0x1f) << 5) | + * ((b >> 3) & 0x1f); + */ + p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) & + ((1 << PNG_QUANTIZE_RED_BITS) - 1)) << + (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) | + (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) & + ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) << + (PNG_QUANTIZE_BLUE_BITS)) | + ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) & + ((1 << PNG_QUANTIZE_BLUE_BITS) - 1)); + + *dp++ = palette_lookup[p]; + } + row_info->color_type = PNG_COLOR_TYPE_PALETTE; + row_info->channels = 1; + row_info->pixel_depth = row_info->bit_depth; + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA && + palette_lookup != NULL && row_info->bit_depth == 8) + { + int r, g, b, p; + sp = row; + dp = row; + for (i = 0; i < row_width; i++) + { + r = *sp++; + g = *sp++; + b = *sp++; + sp++; + + p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) & + ((1 << PNG_QUANTIZE_RED_BITS) - 1)) << + (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) | + (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) & + ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) << + (PNG_QUANTIZE_BLUE_BITS)) | + ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) & + ((1 << PNG_QUANTIZE_BLUE_BITS) - 1)); + + *dp++ = palette_lookup[p]; + } + row_info->color_type = PNG_COLOR_TYPE_PALETTE; + row_info->channels = 1; + row_info->pixel_depth = row_info->bit_depth; + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } + else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE && + quantize_lookup && row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++, sp++) + { + *sp = quantize_lookup[*sp]; + } + } + } +} +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +#ifdef PNG_READ_GAMMA_SUPPORTED +static PNG_CONST int png_gamma_shift[] = + {0x10, 0x21, 0x42, 0x84, 0x110, 0x248, 0x550, 0xff0, 0x00}; + +/* We build the 8- or 16-bit gamma tables here. Note that for 16-bit + * tables, we don't make a full table if we are reducing to 8-bit in + * the future. Note also how the gamma_16 tables are segmented so that + * we don't need to allocate > 64K chunks for a full 16-bit table. + * + * See the PNG extensions document for an integer algorithm for creating + * the gamma tables. Maybe we will implement that here someday. + * + * We should only reach this point if + * + * the file_gamma is known (i.e., the gAMA or sRGB chunk is present, + * or the application has provided a file_gamma) + * + * AND + * { + * the screen_gamma is known + * + * OR + * + * RGB_to_gray transformation is being performed + * } + * + * AND + * { + * the screen_gamma is different from the reciprocal of the + * file_gamma by more than the specified threshold + * + * OR + * + * a background color has been specified and the file_gamma + * and screen_gamma are not 1.0, within the specified threshold. + * } + */ + +void /* PRIVATE */ +png_build_gamma_table(png_structp png_ptr, png_byte bit_depth) +{ + png_debug(1, "in png_build_gamma_table"); + + if (bit_depth <= 8) + { + int i; + double g; + + if (png_ptr->screen_gamma > .000001) + g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); + + else + g = 1.0; + + png_ptr->gamma_table = (png_bytep)png_malloc(png_ptr, + (png_uint_32)256); + + for (i = 0; i < 256; i++) + { + png_ptr->gamma_table[i] = (png_byte)(pow((double)i / 255.0, + g) * 255.0 + .5); + } + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY)) + { + + g = 1.0 / (png_ptr->gamma); + + png_ptr->gamma_to_1 = (png_bytep)png_malloc(png_ptr, + (png_uint_32)256); + + for (i = 0; i < 256; i++) + { + png_ptr->gamma_to_1[i] = (png_byte)(pow((double)i / 255.0, + g) * 255.0 + .5); + } + + + png_ptr->gamma_from_1 = (png_bytep)png_malloc(png_ptr, + (png_uint_32)256); + + if (png_ptr->screen_gamma > 0.000001) + g = 1.0 / png_ptr->screen_gamma; + + else + g = png_ptr->gamma; /* Probably doing rgb_to_gray */ + + for (i = 0; i < 256; i++) + { + png_ptr->gamma_from_1[i] = (png_byte)(pow((double)i / 255.0, + g) * 255.0 + .5); + + } + } +#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */ + } + else + { + double g; + int i, j, shift, num; + int sig_bit; + png_uint_32 ig; + + if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) + { + sig_bit = (int)png_ptr->sig_bit.red; + + if ((int)png_ptr->sig_bit.green > sig_bit) + sig_bit = png_ptr->sig_bit.green; + + if ((int)png_ptr->sig_bit.blue > sig_bit) + sig_bit = png_ptr->sig_bit.blue; + } + else + { + sig_bit = (int)png_ptr->sig_bit.gray; + } + + if (sig_bit > 0) + shift = 16 - sig_bit; + + else + shift = 0; + + if (png_ptr->transformations & PNG_16_TO_8) + { + if (shift < (16 - PNG_MAX_GAMMA_8)) + shift = (16 - PNG_MAX_GAMMA_8); + } + + if (shift > 8) + shift = 8; + + if (shift < 0) + shift = 0; + + png_ptr->gamma_shift = (png_byte)shift; + + num = (1 << (8 - shift)); + + if (png_ptr->screen_gamma > .000001) + g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); + else + g = 1.0; + + png_ptr->gamma_16_table = (png_uint_16pp)png_calloc(png_ptr, + (png_uint_32)(num * png_sizeof(png_uint_16p))); + + if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND)) + { + double fin, fout; + png_uint_32 last, max; + + for (i = 0; i < num; i++) + { + png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(256 * png_sizeof(png_uint_16))); + } + + g = 1.0 / g; + last = 0; + for (i = 0; i < 256; i++) + { + fout = ((double)i + 0.5) / 256.0; + fin = pow(fout, g); + max = (png_uint_32)(fin * (double)((png_uint_32)num << 8)); + while (last <= max) + { + png_ptr->gamma_16_table[(int)(last & (0xff >> shift))] + [(int)(last >> (8 - shift))] = (png_uint_16)( + (png_uint_16)i | ((png_uint_16)i << 8)); + last++; + } + } + while (last < ((png_uint_32)num << 8)) + { + png_ptr->gamma_16_table[(int)(last & (0xff >> shift))] + [(int)(last >> (8 - shift))] = (png_uint_16)65535L; + last++; + } + } + else + { + for (i = 0; i < num; i++) + { + png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(256 * png_sizeof(png_uint_16))); + + ig = (((png_uint_32)i * (png_uint_32)png_gamma_shift[shift]) >> 4); + + for (j = 0; j < 256; j++) + { + png_ptr->gamma_16_table[i][j] = + (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) / + 65535.0, g) * 65535.0 + .5); + } + } + } + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY)) + { + + g = 1.0 / (png_ptr->gamma); + + png_ptr->gamma_16_to_1 = (png_uint_16pp)png_calloc(png_ptr, + (png_uint_32)(num * png_sizeof(png_uint_16p ))); + + for (i = 0; i < num; i++) + { + png_ptr->gamma_16_to_1[i] = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(256 * png_sizeof(png_uint_16))); + + ig = (((png_uint_32)i * + (png_uint_32)png_gamma_shift[shift]) >> 4); + for (j = 0; j < 256; j++) + { + png_ptr->gamma_16_to_1[i][j] = + (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) / + 65535.0, g) * 65535.0 + .5); + } + } + + if (png_ptr->screen_gamma > 0.000001) + g = 1.0 / png_ptr->screen_gamma; + + else + g = png_ptr->gamma; /* Probably doing rgb_to_gray */ + + png_ptr->gamma_16_from_1 = (png_uint_16pp)png_calloc(png_ptr, + (png_uint_32)(num * png_sizeof(png_uint_16p))); + + for (i = 0; i < num; i++) + { + png_ptr->gamma_16_from_1[i] = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(256 * png_sizeof(png_uint_16))); + + ig = (((png_uint_32)i * + (png_uint_32)png_gamma_shift[shift]) >> 4); + + for (j = 0; j < 256; j++) + { + png_ptr->gamma_16_from_1[i][j] = + (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) / + 65535.0, g) * 65535.0 + .5); + } + } + } +#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */ + } +} +#endif +/* To do: install integer version of png_build_gamma_table here */ +#endif + +#ifdef PNG_MNG_FEATURES_SUPPORTED +/* Undoes intrapixel differencing */ +void /* PRIVATE */ +png_do_read_intrapixel(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_read_intrapixel"); + + if ( + (row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + int bytes_per_pixel; + png_uint_32 row_width = row_info->width; + if (row_info->bit_depth == 8) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 3; + + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 4; + + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + *(rp) = (png_byte)((256 + *rp + *(rp+1))&0xff); + *(rp+2) = (png_byte)((256 + *(rp+2) + *(rp+1))&0xff); + } + } + else if (row_info->bit_depth == 16) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 6; + + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 8; + + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1); + png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3); + png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5); + png_uint_32 red = (png_uint_32)((s0 + s1 + 65536L) & 0xffffL); + png_uint_32 blue = (png_uint_32)((s2 + s1 + 65536L) & 0xffffL); + *(rp ) = (png_byte)((red >> 8) & 0xff); + *(rp+1) = (png_byte)(red & 0xff); + *(rp+4) = (png_byte)((blue >> 8) & 0xff); + *(rp+5) = (png_byte)(blue & 0xff); + } + } + } +} +#endif /* PNG_MNG_FEATURES_SUPPORTED */ +#endif /* PNG_READ_SUPPORTED */ diff --git a/reactos/dll/3rdparty/libpng/pngrutil.c b/reactos/dll/3rdparty/libpng/pngrutil.c new file mode 100644 index 00000000000..416e5d228a1 --- /dev/null +++ b/reactos/dll/3rdparty/libpng/pngrutil.c @@ -0,0 +1,3381 @@ + +/* pngrutil.c - utilities to read a PNG file + * + * Last changed in libpng 1.4.3 [June 26, 2010] + * Copyright (c) 1998-2010 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file contains routines that are only called from within + * libpng itself during the course of reading an image. + */ + +#define PNG_NO_PEDANTIC_WARNINGS +#include "png.h" +#ifdef PNG_READ_SUPPORTED +#include "pngpriv.h" + +# define png_strtod(p,a,b) strtod(a,b) +png_uint_32 PNGAPI +png_get_uint_31(png_structp png_ptr, png_bytep buf) +{ + png_uint_32 i = png_get_uint_32(buf); + if (i > PNG_UINT_31_MAX) + png_error(png_ptr, "PNG unsigned integer out of range"); + return (i); +} +#ifndef PNG_USE_READ_MACROS +/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */ +png_uint_32 PNGAPI +png_get_uint_32(png_bytep buf) +{ + png_uint_32 i = ((png_uint_32)(*buf) << 24) + + ((png_uint_32)(*(buf + 1)) << 16) + + ((png_uint_32)(*(buf + 2)) << 8) + + (png_uint_32)(*(buf + 3)); + + return (i); +} + +/* Grab a signed 32-bit integer from a buffer in big-endian format. The + * data is stored in the PNG file in two's complement format, and it is + * assumed that the machine format for signed integers is the same. + */ +png_int_32 PNGAPI +png_get_int_32(png_bytep buf) +{ + png_int_32 i = ((png_int_32)(*buf) << 24) + + ((png_int_32)(*(buf + 1)) << 16) + + ((png_int_32)(*(buf + 2)) << 8) + + (png_int_32)(*(buf + 3)); + + return (i); +} + +/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */ +png_uint_16 PNGAPI +png_get_uint_16(png_bytep buf) +{ + png_uint_16 i = (png_uint_16)(((png_uint_16)(*buf) << 8) + + (png_uint_16)(*(buf + 1))); + + return (i); +} +#endif /* PNG_USE_READ_MACROS */ + +/* Read the chunk header (length + type name). + * Put the type name into png_ptr->chunk_name, and return the length. + */ +png_uint_32 /* PRIVATE */ +png_read_chunk_header(png_structp png_ptr) +{ + png_byte buf[8]; + png_uint_32 length; + +#ifdef PNG_IO_STATE_SUPPORTED + /* Inform the I/O callback that the chunk header is being read. + * PNG_IO_CHUNK_HDR requires a single I/O call. + */ + png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_HDR; +#endif + + /* Read the length and the chunk name */ + png_read_data(png_ptr, buf, 8); + length = png_get_uint_31(png_ptr, buf); + + /* Put the chunk name into png_ptr->chunk_name */ + png_memcpy(png_ptr->chunk_name, buf + 4, 4); + + png_debug2(0, "Reading %s chunk, length = %lu", + png_ptr->chunk_name, length); + + /* Reset the crc and run it over the chunk name */ + png_reset_crc(png_ptr); + png_calculate_crc(png_ptr, png_ptr->chunk_name, 4); + + /* Check to see if chunk name is valid */ + png_check_chunk_name(png_ptr, png_ptr->chunk_name); + +#ifdef PNG_IO_STATE_SUPPORTED + /* Inform the I/O callback that chunk data will (possibly) be read. + * PNG_IO_CHUNK_DATA does NOT require a specific number of I/O calls. + */ + png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_DATA; +#endif + + return length; +} + +/* Read data, and (optionally) run it through the CRC. */ +void /* PRIVATE */ +png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length) +{ + if (png_ptr == NULL) + return; + png_read_data(png_ptr, buf, length); + png_calculate_crc(png_ptr, buf, length); +} + +/* Optionally skip data and then check the CRC. Depending on whether we + * are reading a ancillary or critical chunk, and how the program has set + * things up, we may calculate the CRC on the data and print a message. + * Returns '1' if there was a CRC error, '0' otherwise. + */ +int /* PRIVATE */ +png_crc_finish(png_structp png_ptr, png_uint_32 skip) +{ + png_size_t i; + png_size_t istop = png_ptr->zbuf_size; + + for (i = (png_size_t)skip; i > istop; i -= istop) + { + png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); + } + if (i) + { + png_crc_read(png_ptr, png_ptr->zbuf, i); + } + + if (png_crc_error(png_ptr)) + { + if (((png_ptr->chunk_name[0] & 0x20) && /* Ancillary */ + !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) || + (!(png_ptr->chunk_name[0] & 0x20) && /* Critical */ + (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE))) + { + png_chunk_warning(png_ptr, "CRC error"); + } + else + { + png_chunk_benign_error(png_ptr, "CRC error"); + return (0); + } + return (1); + } + + return (0); +} + +/* Compare the CRC stored in the PNG file with that calculated by libpng from + * the data it has read thus far. + */ +int /* PRIVATE */ +png_crc_error(png_structp png_ptr) +{ + png_byte crc_bytes[4]; + png_uint_32 crc; + int need_crc = 1; + + if (png_ptr->chunk_name[0] & 0x20) /* ancillary */ + { + if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) == + (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN)) + need_crc = 0; + } + else /* critical */ + { + if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) + need_crc = 0; + } + +#ifdef PNG_IO_STATE_SUPPORTED + /* Inform the I/O callback that the chunk CRC is being read */ + /* PNG_IO_CHUNK_CRC requires the I/O to be done at once */ + png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_CRC; +#endif + + png_read_data(png_ptr, crc_bytes, 4); + + if (need_crc) + { + crc = png_get_uint_32(crc_bytes); + return ((int)(crc != png_ptr->crc)); + } + else + return (0); +} + +#if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \ + defined(PNG_READ_iCCP_SUPPORTED) +static png_size_t +png_inflate(png_structp png_ptr, const png_byte *data, png_size_t size, + png_bytep output, png_size_t output_size) +{ + png_size_t count = 0; + + png_ptr->zstream.next_in = (png_bytep)data; /* const_cast: VALID */ + png_ptr->zstream.avail_in = size; + + while (1) + { + int ret, avail; + + /* Reset the output buffer each time round - we empty it + * after every inflate call. + */ + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = png_ptr->zbuf_size; + + ret = inflate(&png_ptr->zstream, Z_NO_FLUSH); + avail = png_ptr->zbuf_size - png_ptr->zstream.avail_out; + + /* First copy/count any new output - but only if we didn't + * get an error code. + */ + if ((ret == Z_OK || ret == Z_STREAM_END) && avail > 0) + { + if (output != 0 && output_size > count) + { + int copy = output_size - count; + if (avail < copy) copy = avail; + png_memcpy(output + count, png_ptr->zbuf, copy); + } + count += avail; + } + + if (ret == Z_OK) + continue; + + /* Termination conditions - always reset the zstream, it + * must be left in inflateInit state. + */ + png_ptr->zstream.avail_in = 0; + inflateReset(&png_ptr->zstream); + + if (ret == Z_STREAM_END) + return count; /* NOTE: may be zero. */ + + /* Now handle the error codes - the API always returns 0 + * and the error message is dumped into the uncompressed + * buffer if available. + */ + { + PNG_CONST char *msg; + if (png_ptr->zstream.msg != 0) + msg = png_ptr->zstream.msg; + else + { +#ifdef PNG_STDIO_SUPPORTED + char umsg[52]; + + switch (ret) + { + case Z_BUF_ERROR: + msg = "Buffer error in compressed datastream in %s chunk"; + break; + case Z_DATA_ERROR: + msg = "Data error in compressed datastream in %s chunk"; + break; + default: + msg = "Incomplete compressed datastream in %s chunk"; + break; + } + + png_snprintf(umsg, sizeof umsg, msg, png_ptr->chunk_name); + msg = umsg; +#else + msg = "Damaged compressed datastream in chunk other than IDAT"; +#endif + } + + png_warning(png_ptr, msg); + } + + /* 0 means an error - notice that this code simple ignores + * zero length compressed chunks as a result. + */ + return 0; + } +} + +/* + * Decompress trailing data in a chunk. The assumption is that chunkdata + * points at an allocated area holding the contents of a chunk with a + * trailing compressed part. What we get back is an allocated area + * holding the original prefix part and an uncompressed version of the + * trailing part (the malloc area passed in is freed). + */ +void /* PRIVATE */ +png_decompress_chunk(png_structp png_ptr, int comp_type, + png_size_t chunklength, + png_size_t prefix_size, png_size_t *newlength) +{ + /* The caller should guarantee this */ + if (prefix_size > chunklength) + { + /* The recovery is to delete the chunk. */ + png_warning(png_ptr, "invalid chunklength"); + prefix_size = 0; /* To delete everything */ + } + + else if (comp_type == PNG_COMPRESSION_TYPE_BASE) + { + png_size_t expanded_size = png_inflate(png_ptr, + (png_bytep)(png_ptr->chunkdata + prefix_size), + chunklength - prefix_size, + 0/*output*/, 0/*output size*/); + + /* Now check the limits on this chunk - if the limit fails the + * compressed data will be removed, the prefix will remain. + */ +#ifdef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED + if (png_ptr->user_chunk_malloc_max && + (prefix_size + expanded_size >= png_ptr->user_chunk_malloc_max - 1)) +#else +# ifdef PNG_USER_CHUNK_MALLOC_MAX + if ((PNG_USER_CHUNK_MALLOC_MAX > 0) && + prefix_size + expanded_size >= PNG_USER_CHUNK_MALLOC_MAX - 1) +# endif +#endif + png_warning(png_ptr, "Exceeded size limit while expanding chunk"); + + /* If the size is zero either there was an error and a message + * has already been output (warning) or the size really is zero + * and we have nothing to do - the code will exit through the + * error case below. + */ +#if defined(PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED) || \ + defined(PNG_USER_CHUNK_MALLOC_MAX) + else +#endif + if (expanded_size > 0) + { + /* Success (maybe) - really uncompress the chunk. */ + png_size_t new_size = 0; + png_charp text = png_malloc_warn(png_ptr, + prefix_size + expanded_size + 1); + + if (text != NULL) + { + png_memcpy(text, png_ptr->chunkdata, prefix_size); + new_size = png_inflate(png_ptr, + (png_bytep)(png_ptr->chunkdata + prefix_size), + chunklength - prefix_size, + (png_bytep)(text + prefix_size), expanded_size); + text[prefix_size + expanded_size] = 0; /* just in case */ + + if (new_size == expanded_size) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = text; + *newlength = prefix_size + expanded_size; + return; /* The success return! */ + } + + png_warning(png_ptr, "png_inflate logic error"); + png_free(png_ptr, text); + } + else + png_warning(png_ptr, "Not enough memory to decompress chunk"); + } + } + + else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */ + { +#ifdef PNG_STDIO_SUPPORTED + char umsg[50]; + + png_snprintf(umsg, sizeof umsg, "Unknown zTXt compression type %d", + comp_type); + png_warning(png_ptr, umsg); +#else + png_warning(png_ptr, "Unknown zTXt compression type"); +#endif + + /* The recovery is to simply drop the data. */ + } + + /* Generic error return - leave the prefix, delete the compressed + * data, reallocate the chunkdata to remove the potentially large + * amount of compressed data. + */ + { + png_charp text = png_malloc_warn(png_ptr, prefix_size + 1); + if (text != NULL) + { + if (prefix_size > 0) + png_memcpy(text, png_ptr->chunkdata, prefix_size); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = text; + + /* This is an extra zero in the 'uncompressed' part. */ + *(png_ptr->chunkdata + prefix_size) = 0x00; + } + /* Ignore a malloc error here - it is safe. */ + } + + *newlength = prefix_size; +} +#endif + +/* Read and check the IDHR chunk */ +void /* PRIVATE */ +png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[13]; + png_uint_32 width, height; + int bit_depth, color_type, compression_type, filter_type; + int interlace_type; + + png_debug(1, "in png_handle_IHDR"); + + if (png_ptr->mode & PNG_HAVE_IHDR) + png_error(png_ptr, "Out of place IHDR"); + + /* Check the length */ + if (length != 13) + png_error(png_ptr, "Invalid IHDR chunk"); + + png_ptr->mode |= PNG_HAVE_IHDR; + + png_crc_read(png_ptr, buf, 13); + png_crc_finish(png_ptr, 0); + + width = png_get_uint_31(png_ptr, buf); + height = png_get_uint_31(png_ptr, buf + 4); + bit_depth = buf[8]; + color_type = buf[9]; + compression_type = buf[10]; + filter_type = buf[11]; + interlace_type = buf[12]; + + /* Set internal variables */ + png_ptr->width = width; + png_ptr->height = height; + png_ptr->bit_depth = (png_byte)bit_depth; + png_ptr->interlaced = (png_byte)interlace_type; + png_ptr->color_type = (png_byte)color_type; +#ifdef PNG_MNG_FEATURES_SUPPORTED + png_ptr->filter_type = (png_byte)filter_type; +#endif + png_ptr->compression_type = (png_byte)compression_type; + + /* Find number of channels */ + switch (png_ptr->color_type) + { + case PNG_COLOR_TYPE_GRAY: + case PNG_COLOR_TYPE_PALETTE: + png_ptr->channels = 1; + break; + + case PNG_COLOR_TYPE_RGB: + png_ptr->channels = 3; + break; + + case PNG_COLOR_TYPE_GRAY_ALPHA: + png_ptr->channels = 2; + break; + + case PNG_COLOR_TYPE_RGB_ALPHA: + png_ptr->channels = 4; + break; + } + + /* Set up other useful info */ + png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth * + png_ptr->channels); + png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->width); + png_debug1(3, "bit_depth = %d", png_ptr->bit_depth); + png_debug1(3, "channels = %d", png_ptr->channels); + png_debug1(3, "rowbytes = %lu", png_ptr->rowbytes); + png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, + color_type, interlace_type, compression_type, filter_type); +} + +/* Read and check the palette */ +void /* PRIVATE */ +png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_color palette[PNG_MAX_PALETTE_LENGTH]; + int num, i; +#ifdef PNG_POINTER_INDEXING_SUPPORTED + png_colorp pal_ptr; +#endif + + png_debug(1, "in png_handle_PLTE"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before PLTE"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid PLTE after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + + else if (png_ptr->mode & PNG_HAVE_PLTE) + png_error(png_ptr, "Duplicate PLTE chunk"); + + png_ptr->mode |= PNG_HAVE_PLTE; + + if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR)) + { + png_warning(png_ptr, + "Ignoring PLTE chunk in grayscale PNG"); + png_crc_finish(png_ptr, length); + return; + } +#ifndef PNG_READ_OPT_PLTE_SUPPORTED + if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE) + { + png_crc_finish(png_ptr, length); + return; + } +#endif + + if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3) + { + if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE) + { + png_warning(png_ptr, "Invalid palette chunk"); + png_crc_finish(png_ptr, length); + return; + } + + else + { + png_error(png_ptr, "Invalid palette chunk"); + } + } + + num = (int)length / 3; + +#ifdef PNG_POINTER_INDEXING_SUPPORTED + for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++) + { + png_byte buf[3]; + + png_crc_read(png_ptr, buf, 3); + pal_ptr->red = buf[0]; + pal_ptr->green = buf[1]; + pal_ptr->blue = buf[2]; + } +#else + for (i = 0; i < num; i++) + { + png_byte buf[3]; + + png_crc_read(png_ptr, buf, 3); + /* Don't depend upon png_color being any order */ + palette[i].red = buf[0]; + palette[i].green = buf[1]; + palette[i].blue = buf[2]; + } +#endif + + /* If we actually NEED the PLTE chunk (ie for a paletted image), we do + * whatever the normal CRC configuration tells us. However, if we + * have an RGB image, the PLTE can be considered ancillary, so + * we will act as though it is. + */ +#ifndef PNG_READ_OPT_PLTE_SUPPORTED + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) +#endif + { + png_crc_finish(png_ptr, 0); + } +#ifndef PNG_READ_OPT_PLTE_SUPPORTED + else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */ + { + /* If we don't want to use the data from an ancillary chunk, + we have two options: an error abort, or a warning and we + ignore the data in this chunk (which should be OK, since + it's considered ancillary for a RGB or RGBA image). */ + if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE)) + { + if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) + { + png_chunk_benign_error(png_ptr, "CRC error"); + } + else + { + png_chunk_warning(png_ptr, "CRC error"); + return; + } + } + /* Otherwise, we (optionally) emit a warning and use the chunk. */ + else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) + { + png_chunk_warning(png_ptr, "CRC error"); + } + } +#endif + + png_set_PLTE(png_ptr, info_ptr, palette, num); + +#ifdef PNG_READ_tRNS_SUPPORTED + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) + { + if (png_ptr->num_trans > (png_uint_16)num) + { + png_warning(png_ptr, "Truncating incorrect tRNS chunk length"); + png_ptr->num_trans = (png_uint_16)num; + } + if (info_ptr->num_trans > (png_uint_16)num) + { + png_warning(png_ptr, "Truncating incorrect info tRNS chunk length"); + info_ptr->num_trans = (png_uint_16)num; + } + } + } +#endif + +} + +void /* PRIVATE */ +png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_debug(1, "in png_handle_IEND"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT)) + { + png_error(png_ptr, "No image in file"); + } + + png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND); + + if (length != 0) + { + png_warning(png_ptr, "Incorrect IEND chunk length"); + } + png_crc_finish(png_ptr, length); + + info_ptr = info_ptr; /* Quiet compiler warnings about unused info_ptr */ +} + +#ifdef PNG_READ_gAMA_SUPPORTED +void /* PRIVATE */ +png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_fixed_point igamma; +#ifdef PNG_FLOATING_POINT_SUPPORTED + float file_gamma; +#endif + png_byte buf[4]; + + png_debug(1, "in png_handle_gAMA"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before gAMA"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid gAMA after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (png_ptr->mode & PNG_HAVE_PLTE) + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Out of place gAMA chunk"); + + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA) +#ifdef PNG_READ_sRGB_SUPPORTED + && !(info_ptr->valid & PNG_INFO_sRGB) +#endif + ) + { + png_warning(png_ptr, "Duplicate gAMA chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 4) + { + png_warning(png_ptr, "Incorrect gAMA chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 4); + if (png_crc_finish(png_ptr, 0)) + return; + + igamma = (png_fixed_point)png_get_uint_32(buf); + /* Check for zero gamma */ + if (igamma == 0) + { + png_warning(png_ptr, + "Ignoring gAMA chunk with gamma=0"); + return; + } + +#ifdef PNG_READ_sRGB_SUPPORTED + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB)) + if (PNG_OUT_OF_RANGE(igamma, 45500L, 500)) + { + png_warning(png_ptr, + "Ignoring incorrect gAMA value when sRGB is also present"); +#ifdef PNG_CONSOLE_IO_SUPPORTED + fprintf(stderr, "gamma = (%d/100000)", (int)igamma); +#endif + return; + } +#endif /* PNG_READ_sRGB_SUPPORTED */ + +#ifdef PNG_FLOATING_POINT_SUPPORTED + file_gamma = (float)igamma / (float)100000.0; +# ifdef PNG_READ_GAMMA_SUPPORTED + png_ptr->gamma = file_gamma; +# endif + png_set_gAMA(png_ptr, info_ptr, file_gamma); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED + png_set_gAMA_fixed(png_ptr, info_ptr, igamma); +#endif +} +#endif + +#ifdef PNG_READ_sBIT_SUPPORTED +void /* PRIVATE */ +png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_size_t truelen; + png_byte buf[4]; + + png_debug(1, "in png_handle_sBIT"); + + buf[0] = buf[1] = buf[2] = buf[3] = 0; + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before sBIT"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid sBIT after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (png_ptr->mode & PNG_HAVE_PLTE) + { + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Out of place sBIT chunk"); + } + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT)) + { + png_warning(png_ptr, "Duplicate sBIT chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + truelen = 3; + else + truelen = (png_size_t)png_ptr->channels; + + if (length != truelen || length > 4) + { + png_warning(png_ptr, "Incorrect sBIT chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, truelen); + if (png_crc_finish(png_ptr, 0)) + return; + + if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) + { + png_ptr->sig_bit.red = buf[0]; + png_ptr->sig_bit.green = buf[1]; + png_ptr->sig_bit.blue = buf[2]; + png_ptr->sig_bit.alpha = buf[3]; + } + else + { + png_ptr->sig_bit.gray = buf[0]; + png_ptr->sig_bit.red = buf[0]; + png_ptr->sig_bit.green = buf[0]; + png_ptr->sig_bit.blue = buf[0]; + png_ptr->sig_bit.alpha = buf[1]; + } + png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit)); +} +#endif + +#ifdef PNG_READ_cHRM_SUPPORTED +void /* PRIVATE */ +png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[32]; +#ifdef PNG_FLOATING_POINT_SUPPORTED + float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y; +#endif + png_fixed_point int_x_white, int_y_white, int_x_red, int_y_red, int_x_green, + int_y_green, int_x_blue, int_y_blue; + + png_uint_32 uint_x, uint_y; + + png_debug(1, "in png_handle_cHRM"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before cHRM"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid cHRM after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (png_ptr->mode & PNG_HAVE_PLTE) + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Missing PLTE before cHRM"); + + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM) +#ifdef PNG_READ_sRGB_SUPPORTED + && !(info_ptr->valid & PNG_INFO_sRGB) +#endif + ) + { + png_warning(png_ptr, "Duplicate cHRM chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 32) + { + png_warning(png_ptr, "Incorrect cHRM chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 32); + if (png_crc_finish(png_ptr, 0)) + return; + + uint_x = png_get_uint_32(buf); + uint_y = png_get_uint_32(buf + 4); + int_x_white = (png_fixed_point)uint_x; + int_y_white = (png_fixed_point)uint_y; + + uint_x = png_get_uint_32(buf + 8); + uint_y = png_get_uint_32(buf + 12); + int_x_red = (png_fixed_point)uint_x; + int_y_red = (png_fixed_point)uint_y; + + uint_x = png_get_uint_32(buf + 16); + uint_y = png_get_uint_32(buf + 20); + int_x_green = (png_fixed_point)uint_x; + int_y_green = (png_fixed_point)uint_y; + + uint_x = png_get_uint_32(buf + 24); + uint_y = png_get_uint_32(buf + 28); + int_x_blue = (png_fixed_point)uint_x; + int_y_blue = (png_fixed_point)uint_y; + +#ifdef PNG_FLOATING_POINT_SUPPORTED + white_x = (float)int_x_white / (float)100000.0; + white_y = (float)int_y_white / (float)100000.0; + red_x = (float)int_x_red / (float)100000.0; + red_y = (float)int_y_red / (float)100000.0; + green_x = (float)int_x_green / (float)100000.0; + green_y = (float)int_y_green / (float)100000.0; + blue_x = (float)int_x_blue / (float)100000.0; + blue_y = (float)int_y_blue / (float)100000.0; +#endif + +#ifdef PNG_READ_sRGB_SUPPORTED + if ((info_ptr != NULL) && (info_ptr->valid & PNG_INFO_sRGB)) + { + if (PNG_OUT_OF_RANGE(int_x_white, 31270, 1000) || + PNG_OUT_OF_RANGE(int_y_white, 32900, 1000) || + PNG_OUT_OF_RANGE(int_x_red, 64000L, 1000) || + PNG_OUT_OF_RANGE(int_y_red, 33000, 1000) || + PNG_OUT_OF_RANGE(int_x_green, 30000, 1000) || + PNG_OUT_OF_RANGE(int_y_green, 60000L, 1000) || + PNG_OUT_OF_RANGE(int_x_blue, 15000, 1000) || + PNG_OUT_OF_RANGE(int_y_blue, 6000, 1000)) + { + png_warning(png_ptr, + "Ignoring incorrect cHRM value when sRGB is also present"); +#ifdef PNG_CONSOLE_IO_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED + fprintf(stderr, "wx=%f, wy=%f, rx=%f, ry=%f\n", + white_x, white_y, red_x, red_y); + fprintf(stderr, "gx=%f, gy=%f, bx=%f, by=%f\n", + green_x, green_y, blue_x, blue_y); +#else + fprintf(stderr, "wx=%ld, wy=%ld, rx=%ld, ry=%ld\n", + (long)int_x_white, (long)int_y_white, + (long)int_x_red, (long)int_y_red); + fprintf(stderr, "gx=%ld, gy=%ld, bx=%ld, by=%ld\n", + (long)int_x_green, (long)int_y_green, + (long)int_x_blue, (long)int_y_blue); +#endif +#endif /* PNG_CONSOLE_IO_SUPPORTED */ + } + return; + } +#endif /* PNG_READ_sRGB_SUPPORTED */ + +#ifdef PNG_FLOATING_POINT_SUPPORTED + png_set_cHRM(png_ptr, info_ptr, + white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED + png_set_cHRM_fixed(png_ptr, info_ptr, + int_x_white, int_y_white, int_x_red, int_y_red, int_x_green, + int_y_green, int_x_blue, int_y_blue); +#endif +} +#endif + +#ifdef PNG_READ_sRGB_SUPPORTED +void /* PRIVATE */ +png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + int intent; + png_byte buf[1]; + + png_debug(1, "in png_handle_sRGB"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before sRGB"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid sRGB after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (png_ptr->mode & PNG_HAVE_PLTE) + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Out of place sRGB chunk"); + + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB)) + { + png_warning(png_ptr, "Duplicate sRGB chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 1) + { + png_warning(png_ptr, "Incorrect sRGB chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 1); + if (png_crc_finish(png_ptr, 0)) + return; + + intent = buf[0]; + /* Check for bad intent */ + if (intent >= PNG_sRGB_INTENT_LAST) + { + png_warning(png_ptr, "Unknown sRGB intent"); + return; + } + +#if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED) + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)) + { + png_fixed_point igamma; +#ifdef PNG_FIXED_POINT_SUPPORTED + igamma=info_ptr->int_gamma; +#else +# ifdef PNG_FLOATING_POINT_SUPPORTED + igamma=(png_fixed_point)(info_ptr->gamma * 100000.); +# endif +#endif + if (PNG_OUT_OF_RANGE(igamma, 45500L, 500)) + { + png_warning(png_ptr, + "Ignoring incorrect gAMA value when sRGB is also present"); +#ifdef PNG_CONSOLE_IO_SUPPORTED +# ifdef PNG_FIXED_POINT_SUPPORTED + fprintf(stderr, "incorrect gamma=(%d/100000)\n", + (int)png_ptr->int_gamma); +# else +# ifdef PNG_FLOATING_POINT_SUPPORTED + fprintf(stderr, "incorrect gamma=%f\n", png_ptr->gamma); +# endif +# endif +#endif + } + } +#endif /* PNG_READ_gAMA_SUPPORTED */ + +#ifdef PNG_READ_cHRM_SUPPORTED +#ifdef PNG_FIXED_POINT_SUPPORTED + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)) + if (PNG_OUT_OF_RANGE(info_ptr->int_x_white, 31270, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_y_white, 32900, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_x_red, 64000L, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_y_red, 33000, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_x_green, 30000, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_y_green, 60000L, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_x_blue, 15000, 1000) || + PNG_OUT_OF_RANGE(info_ptr->int_y_blue, 6000, 1000)) + { + png_warning(png_ptr, + "Ignoring incorrect cHRM value when sRGB is also present"); + } +#endif /* PNG_FIXED_POINT_SUPPORTED */ +#endif /* PNG_READ_cHRM_SUPPORTED */ + + png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent); +} +#endif /* PNG_READ_sRGB_SUPPORTED */ + +#ifdef PNG_READ_iCCP_SUPPORTED +void /* PRIVATE */ +png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +/* Note: this does not properly handle chunks that are > 64K under DOS */ +{ + png_byte compression_type; + png_bytep pC; + png_charp profile; + png_uint_32 skip = 0; + png_uint_32 profile_size, profile_length; + png_size_t slength, prefix_length, data_length; + + png_debug(1, "in png_handle_iCCP"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before iCCP"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid iCCP after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (png_ptr->mode & PNG_HAVE_PLTE) + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Out of place iCCP chunk"); + + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP)) + { + png_warning(png_ptr, "Duplicate iCCP chunk"); + png_crc_finish(png_ptr, length); + return; + } + +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "iCCP chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1); + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + + if (png_crc_finish(png_ptr, skip)) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + png_ptr->chunkdata[slength] = 0x00; + + for (profile = png_ptr->chunkdata; *profile; profile++) + /* Empty loop to find end of name */ ; + + ++profile; + + /* There should be at least one zero (the compression type byte) + * following the separator, and we should be on it + */ + if ( profile >= png_ptr->chunkdata + slength - 1) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_warning(png_ptr, "Malformed iCCP chunk"); + return; + } + + /* Compression_type should always be zero */ + compression_type = *profile++; + if (compression_type) + { + png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk"); + compression_type = 0x00; /* Reset it to zero (libpng-1.0.6 through 1.0.8 + wrote nonzero) */ + } + + prefix_length = profile - png_ptr->chunkdata; + png_decompress_chunk(png_ptr, compression_type, + slength, prefix_length, &data_length); + + profile_length = data_length - prefix_length; + + if ( prefix_length > data_length || profile_length < 4) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_warning(png_ptr, "Profile size field missing from iCCP chunk"); + return; + } + + /* Check the profile_size recorded in the first 32 bits of the ICC profile */ + pC = (png_bytep)(png_ptr->chunkdata + prefix_length); + profile_size = ((*(pC ))<<24) | + ((*(pC + 1))<<16) | + ((*(pC + 2))<< 8) | + ((*(pC + 3)) ); + + if (profile_size < profile_length) + profile_length = profile_size; + + if (profile_size > profile_length) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_warning(png_ptr, "Ignoring truncated iCCP profile"); +#ifdef PNG_STDIO_SUPPORTED + { + char umsg[50]; + + png_snprintf(umsg, 50, "declared profile size = %lu", + (unsigned long)profile_size); + png_warning(png_ptr, umsg); + png_snprintf(umsg, 50, "actual profile length = %lu", + (unsigned long)profile_length); + png_warning(png_ptr, umsg); + } +#endif + return; + } + + png_set_iCCP(png_ptr, info_ptr, png_ptr->chunkdata, + compression_type, png_ptr->chunkdata + prefix_length, profile_length); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; +} +#endif /* PNG_READ_iCCP_SUPPORTED */ + +#ifdef PNG_READ_sPLT_SUPPORTED +void /* PRIVATE */ +png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +/* Note: this does not properly handle chunks that are > 64K under DOS */ +{ + png_bytep entry_start; + png_sPLT_t new_palette; +#ifdef PNG_POINTER_INDEXING_SUPPORTED + png_sPLT_entryp pp; +#endif + int data_length, entry_size, i; + png_uint_32 skip = 0; + png_size_t slength; + + png_debug(1, "in png_handle_sPLT"); + +#ifdef PNG_USER_LIMITS_SUPPORTED + + if (png_ptr->user_chunk_cache_max != 0) + { + if (png_ptr->user_chunk_cache_max == 1) + { + png_crc_finish(png_ptr, length); + return; + } + if (--png_ptr->user_chunk_cache_max == 1) + { + png_warning(png_ptr, "No space in chunk cache for sPLT"); + png_crc_finish(png_ptr, length); + return; + } + } +#endif + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before sPLT"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid sPLT after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "sPLT chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1); + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + + if (png_crc_finish(png_ptr, skip)) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + png_ptr->chunkdata[slength] = 0x00; + + for (entry_start = (png_bytep)png_ptr->chunkdata; *entry_start; + entry_start++) + /* Empty loop to find end of name */ ; + ++entry_start; + + /* A sample depth should follow the separator, and we should be on it */ + if (entry_start > (png_bytep)png_ptr->chunkdata + slength - 2) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_warning(png_ptr, "malformed sPLT chunk"); + return; + } + + new_palette.depth = *entry_start++; + entry_size = (new_palette.depth == 8 ? 6 : 10); + data_length = (slength - (entry_start - (png_bytep)png_ptr->chunkdata)); + + /* Integrity-check the data length */ + if (data_length % entry_size) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_warning(png_ptr, "sPLT chunk has bad length"); + return; + } + + new_palette.nentries = (png_int_32) ( data_length / entry_size); + if ((png_uint_32) new_palette.nentries > + (png_uint_32) (PNG_SIZE_MAX / png_sizeof(png_sPLT_entry))) + { + png_warning(png_ptr, "sPLT chunk too long"); + return; + } + new_palette.entries = (png_sPLT_entryp)png_malloc_warn( + png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry)); + if (new_palette.entries == NULL) + { + png_warning(png_ptr, "sPLT chunk requires too much memory"); + return; + } + +#ifdef PNG_POINTER_INDEXING_SUPPORTED + for (i = 0; i < new_palette.nentries; i++) + { + pp = new_palette.entries + i; + + if (new_palette.depth == 8) + { + pp->red = *entry_start++; + pp->green = *entry_start++; + pp->blue = *entry_start++; + pp->alpha = *entry_start++; + } + else + { + pp->red = png_get_uint_16(entry_start); entry_start += 2; + pp->green = png_get_uint_16(entry_start); entry_start += 2; + pp->blue = png_get_uint_16(entry_start); entry_start += 2; + pp->alpha = png_get_uint_16(entry_start); entry_start += 2; + } + pp->frequency = png_get_uint_16(entry_start); entry_start += 2; + } +#else + pp = new_palette.entries; + for (i = 0; i < new_palette.nentries; i++) + { + + if (new_palette.depth == 8) + { + pp[i].red = *entry_start++; + pp[i].green = *entry_start++; + pp[i].blue = *entry_start++; + pp[i].alpha = *entry_start++; + } + else + { + pp[i].red = png_get_uint_16(entry_start); entry_start += 2; + pp[i].green = png_get_uint_16(entry_start); entry_start += 2; + pp[i].blue = png_get_uint_16(entry_start); entry_start += 2; + pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2; + } + pp->frequency = png_get_uint_16(entry_start); entry_start += 2; + } +#endif + + /* Discard all chunk data except the name and stash that */ + new_palette.name = png_ptr->chunkdata; + + png_set_sPLT(png_ptr, info_ptr, &new_palette, 1); + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_free(png_ptr, new_palette.entries); +} +#endif /* PNG_READ_sPLT_SUPPORTED */ + +#ifdef PNG_READ_tRNS_SUPPORTED +void /* PRIVATE */ +png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte readbuf[PNG_MAX_PALETTE_LENGTH]; + + png_debug(1, "in png_handle_tRNS"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before tRNS"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid tRNS after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) + { + png_warning(png_ptr, "Duplicate tRNS chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) + { + png_byte buf[2]; + + if (length != 2) + { + png_warning(png_ptr, "Incorrect tRNS chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 2); + png_ptr->num_trans = 1; + png_ptr->trans_color.gray = png_get_uint_16(buf); + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + { + png_byte buf[6]; + + if (length != 6) + { + png_warning(png_ptr, "Incorrect tRNS chunk length"); + png_crc_finish(png_ptr, length); + return; + } + png_crc_read(png_ptr, buf, (png_size_t)length); + png_ptr->num_trans = 1; + png_ptr->trans_color.red = png_get_uint_16(buf); + png_ptr->trans_color.green = png_get_uint_16(buf + 2); + png_ptr->trans_color.blue = png_get_uint_16(buf + 4); + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (!(png_ptr->mode & PNG_HAVE_PLTE)) + { + /* Should be an error, but we can cope with it. */ + png_warning(png_ptr, "Missing PLTE before tRNS"); + } + if (length > (png_uint_32)png_ptr->num_palette || + length > PNG_MAX_PALETTE_LENGTH) + { + png_warning(png_ptr, "Incorrect tRNS chunk length"); + png_crc_finish(png_ptr, length); + return; + } + if (length == 0) + { + png_warning(png_ptr, "Zero length tRNS chunk"); + png_crc_finish(png_ptr, length); + return; + } + png_crc_read(png_ptr, readbuf, (png_size_t)length); + png_ptr->num_trans = (png_uint_16)length; + } + else + { + png_warning(png_ptr, "tRNS chunk not allowed with alpha channel"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_crc_finish(png_ptr, 0)) + { + png_ptr->num_trans = 0; + return; + } + + png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans, + &(png_ptr->trans_color)); +} +#endif + +#ifdef PNG_READ_bKGD_SUPPORTED +void /* PRIVATE */ +png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_size_t truelen; + png_byte buf[6]; + + png_debug(1, "in png_handle_bKGD"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before bKGD"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid bKGD after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + { + png_warning(png_ptr, "Missing PLTE before bKGD"); + png_crc_finish(png_ptr, length); + return; + } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD)) + { + png_warning(png_ptr, "Duplicate bKGD chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + truelen = 1; + else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) + truelen = 6; + else + truelen = 2; + + if (length != truelen) + { + png_warning(png_ptr, "Incorrect bKGD chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, truelen); + if (png_crc_finish(png_ptr, 0)) + return; + + /* We convert the index value into RGB components so that we can allow + * arbitrary RGB values for background when we have transparency, and + * so it is easy to determine the RGB values of the background color + * from the info_ptr struct. */ + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + png_ptr->background.index = buf[0]; + if (info_ptr && info_ptr->num_palette) + { + if (buf[0] >= info_ptr->num_palette) + { + png_warning(png_ptr, "Incorrect bKGD chunk index value"); + return; + } + png_ptr->background.red = + (png_uint_16)png_ptr->palette[buf[0]].red; + png_ptr->background.green = + (png_uint_16)png_ptr->palette[buf[0]].green; + png_ptr->background.blue = + (png_uint_16)png_ptr->palette[buf[0]].blue; + } + } + else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */ + { + png_ptr->background.red = + png_ptr->background.green = + png_ptr->background.blue = + png_ptr->background.gray = png_get_uint_16(buf); + } + else + { + png_ptr->background.red = png_get_uint_16(buf); + png_ptr->background.green = png_get_uint_16(buf + 2); + png_ptr->background.blue = png_get_uint_16(buf + 4); + } + + png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background)); +} +#endif + +#ifdef PNG_READ_hIST_SUPPORTED +void /* PRIVATE */ +png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + unsigned int num, i; + png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH]; + + png_debug(1, "in png_handle_hIST"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before hIST"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid hIST after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (!(png_ptr->mode & PNG_HAVE_PLTE)) + { + png_warning(png_ptr, "Missing PLTE before hIST"); + png_crc_finish(png_ptr, length); + return; + } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST)) + { + png_warning(png_ptr, "Duplicate hIST chunk"); + png_crc_finish(png_ptr, length); + return; + } + + num = length / 2 ; + if (num != (unsigned int) png_ptr->num_palette || num > + (unsigned int) PNG_MAX_PALETTE_LENGTH) + { + png_warning(png_ptr, "Incorrect hIST chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + for (i = 0; i < num; i++) + { + png_byte buf[2]; + + png_crc_read(png_ptr, buf, 2); + readbuf[i] = png_get_uint_16(buf); + } + + if (png_crc_finish(png_ptr, 0)) + return; + + png_set_hIST(png_ptr, info_ptr, readbuf); +} +#endif + +#ifdef PNG_READ_pHYs_SUPPORTED +void /* PRIVATE */ +png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[9]; + png_uint_32 res_x, res_y; + int unit_type; + + png_debug(1, "in png_handle_pHYs"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before pHYs"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid pHYs after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) + { + png_warning(png_ptr, "Duplicate pHYs chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 9) + { + png_warning(png_ptr, "Incorrect pHYs chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 9); + if (png_crc_finish(png_ptr, 0)) + return; + + res_x = png_get_uint_32(buf); + res_y = png_get_uint_32(buf + 4); + unit_type = buf[8]; + png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type); +} +#endif + +#ifdef PNG_READ_oFFs_SUPPORTED +void /* PRIVATE */ +png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[9]; + png_int_32 offset_x, offset_y; + int unit_type; + + png_debug(1, "in png_handle_oFFs"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before oFFs"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid oFFs after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) + { + png_warning(png_ptr, "Duplicate oFFs chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 9) + { + png_warning(png_ptr, "Incorrect oFFs chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 9); + if (png_crc_finish(png_ptr, 0)) + return; + + offset_x = png_get_int_32(buf); + offset_y = png_get_int_32(buf + 4); + unit_type = buf[8]; + png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type); +} +#endif + +#ifdef PNG_READ_pCAL_SUPPORTED +/* Read the pCAL chunk (described in the PNG Extensions document) */ +void /* PRIVATE */ +png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_int_32 X0, X1; + png_byte type, nparams; + png_charp buf, units, endptr; + png_charpp params; + png_size_t slength; + int i; + + png_debug(1, "in png_handle_pCAL"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before pCAL"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid pCAL after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL)) + { + png_warning(png_ptr, "Duplicate pCAL chunk"); + png_crc_finish(png_ptr, length); + return; + } + + png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)", + length + 1); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); + if (png_ptr->chunkdata == NULL) + { + png_warning(png_ptr, "No memory for pCAL purpose"); + return; + } + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + + if (png_crc_finish(png_ptr, 0)) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */ + + png_debug(3, "Finding end of pCAL purpose string"); + for (buf = png_ptr->chunkdata; *buf; buf++) + /* Empty loop */ ; + + endptr = png_ptr->chunkdata + slength; + + /* We need to have at least 12 bytes after the purpose string + in order to get the parameter information. */ + if (endptr <= buf + 12) + { + png_warning(png_ptr, "Invalid pCAL data"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + png_debug(3, "Reading pCAL X0, X1, type, nparams, and units"); + X0 = png_get_int_32((png_bytep)buf+1); + X1 = png_get_int_32((png_bytep)buf+5); + type = buf[9]; + nparams = buf[10]; + units = buf + 11; + + png_debug(3, "Checking pCAL equation type and number of parameters"); + /* Check that we have the right number of parameters for known + equation types. */ + if ((type == PNG_EQUATION_LINEAR && nparams != 2) || + (type == PNG_EQUATION_BASE_E && nparams != 3) || + (type == PNG_EQUATION_ARBITRARY && nparams != 3) || + (type == PNG_EQUATION_HYPERBOLIC && nparams != 4)) + { + png_warning(png_ptr, "Invalid pCAL parameters for equation type"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + else if (type >= PNG_EQUATION_LAST) + { + png_warning(png_ptr, "Unrecognized equation type for pCAL chunk"); + } + + for (buf = units; *buf; buf++) + /* Empty loop to move past the units string. */ ; + + png_debug(3, "Allocating pCAL parameters array"); + params = (png_charpp)png_malloc_warn(png_ptr, + (png_size_t)(nparams * png_sizeof(png_charp))); + if (params == NULL) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_warning(png_ptr, "No memory for pCAL params"); + return; + } + + /* Get pointers to the start of each parameter string. */ + for (i = 0; i < (int)nparams; i++) + { + buf++; /* Skip the null string terminator from previous parameter. */ + + png_debug1(3, "Reading pCAL parameter %d", i); + for (params[i] = buf; buf <= endptr && *buf != 0x00; buf++) + /* Empty loop to move past each parameter string */ ; + + /* Make sure we haven't run out of data yet */ + if (buf > endptr) + { + png_warning(png_ptr, "Invalid pCAL data"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_free(png_ptr, params); + return; + } + } + + png_set_pCAL(png_ptr, info_ptr, png_ptr->chunkdata, X0, X1, type, nparams, + units, params); + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_free(png_ptr, params); +} +#endif + +#ifdef PNG_READ_sCAL_SUPPORTED +/* Read the sCAL chunk */ +void /* PRIVATE */ +png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_charp ep; +#ifdef PNG_FLOATING_POINT_SUPPORTED + double width, height; + png_charp vp; +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + png_charp swidth, sheight; +#endif +#endif + png_size_t slength; + + png_debug(1, "in png_handle_sCAL"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before sCAL"); + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid sCAL after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL)) + { + png_warning(png_ptr, "Duplicate sCAL chunk"); + png_crc_finish(png_ptr, length); + return; + } + + png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)", + length + 1); + png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); + if (png_ptr->chunkdata == NULL) + { + png_warning(png_ptr, "Out of memory while processing sCAL chunk"); + png_crc_finish(png_ptr, length); + return; + } + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + + if (png_crc_finish(png_ptr, 0)) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */ + + ep = png_ptr->chunkdata + 1; /* Skip unit byte */ + +#ifdef PNG_FLOATING_POINT_SUPPORTED + width = png_strtod(png_ptr, ep, &vp); + if (*vp) + { + png_warning(png_ptr, "malformed width string in sCAL chunk"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + swidth = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1); + if (swidth == NULL) + { + png_warning(png_ptr, "Out of memory while processing sCAL chunk width"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + png_memcpy(swidth, ep, png_strlen(ep)); +#endif +#endif + + for (ep = png_ptr->chunkdata; *ep; ep++) + /* Empty loop */ ; + ep++; + + if (png_ptr->chunkdata + slength < ep) + { + png_warning(png_ptr, "Truncated sCAL chunk"); +#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED) + png_free(png_ptr, swidth); +#endif + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + +#ifdef PNG_FLOATING_POINT_SUPPORTED + height = png_strtod(png_ptr, ep, &vp); + if (*vp) + { + png_warning(png_ptr, "malformed height string in sCAL chunk"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; +#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED) + png_free(png_ptr, swidth); +#endif + return; + } +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + sheight = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1); + if (sheight == NULL) + { + png_warning(png_ptr, "Out of memory while processing sCAL chunk height"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; +#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED) + png_free(png_ptr, swidth); +#endif + return; + } + png_memcpy(sheight, ep, png_strlen(ep)); +#endif +#endif + + if (png_ptr->chunkdata + slength < ep +#ifdef PNG_FLOATING_POINT_SUPPORTED + || width <= 0. || height <= 0. +#endif + ) + { + png_warning(png_ptr, "Invalid sCAL data"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; +#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED) + png_free(png_ptr, swidth); + png_free(png_ptr, sheight); +#endif + return; + } + + +#ifdef PNG_FLOATING_POINT_SUPPORTED + png_set_sCAL(png_ptr, info_ptr, png_ptr->chunkdata[0], width, height); +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + png_set_sCAL_s(png_ptr, info_ptr, png_ptr->chunkdata[0], swidth, sheight); +#endif +#endif + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; +#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED) + png_free(png_ptr, swidth); + png_free(png_ptr, sheight); +#endif +} +#endif + +#ifdef PNG_READ_tIME_SUPPORTED +void /* PRIVATE */ +png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[7]; + png_time mod_time; + + png_debug(1, "in png_handle_tIME"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Out of place tIME chunk"); + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME)) + { + png_warning(png_ptr, "Duplicate tIME chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + + if (length != 7) + { + png_warning(png_ptr, "Incorrect tIME chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 7); + if (png_crc_finish(png_ptr, 0)) + return; + + mod_time.second = buf[6]; + mod_time.minute = buf[5]; + mod_time.hour = buf[4]; + mod_time.day = buf[3]; + mod_time.month = buf[2]; + mod_time.year = png_get_uint_16(buf); + + png_set_tIME(png_ptr, info_ptr, &mod_time); +} +#endif + +#ifdef PNG_READ_tEXt_SUPPORTED +/* Note: this does not properly handle chunks that are > 64K under DOS */ +void /* PRIVATE */ +png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_textp text_ptr; + png_charp key; + png_charp text; + png_uint_32 skip = 0; + png_size_t slength; + int ret; + + png_debug(1, "in png_handle_tEXt"); + +#ifdef PNG_USER_LIMITS_SUPPORTED + if (png_ptr->user_chunk_cache_max != 0) + { + if (png_ptr->user_chunk_cache_max == 1) + { + png_crc_finish(png_ptr, length); + return; + } + if (--png_ptr->user_chunk_cache_max == 1) + { + png_warning(png_ptr, "No space in chunk cache for tEXt"); + png_crc_finish(png_ptr, length); + return; + } + } +#endif + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before tEXt"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "tEXt chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + png_free(png_ptr, png_ptr->chunkdata); + + png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); + if (png_ptr->chunkdata == NULL) + { + png_warning(png_ptr, "No memory to process text chunk"); + return; + } + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + + if (png_crc_finish(png_ptr, skip)) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + key = png_ptr->chunkdata; + + key[slength] = 0x00; + + for (text = key; *text; text++) + /* Empty loop to find end of key */ ; + + if (text != key + slength) + text++; + + text_ptr = (png_textp)png_malloc_warn(png_ptr, + png_sizeof(png_text)); + if (text_ptr == NULL) + { + png_warning(png_ptr, "Not enough memory to process text chunk"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + text_ptr->compression = PNG_TEXT_COMPRESSION_NONE; + text_ptr->key = key; +#ifdef PNG_iTXt_SUPPORTED + text_ptr->lang = NULL; + text_ptr->lang_key = NULL; + text_ptr->itxt_length = 0; +#endif + text_ptr->text = text; + text_ptr->text_length = png_strlen(text); + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_free(png_ptr, text_ptr); + if (ret) + png_warning(png_ptr, "Insufficient memory to process text chunk"); +} +#endif + +#ifdef PNG_READ_zTXt_SUPPORTED +/* Note: this does not correctly handle chunks that are > 64K under DOS */ +void /* PRIVATE */ +png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_textp text_ptr; + png_charp text; + int comp_type; + int ret; + png_size_t slength, prefix_len, data_len; + + png_debug(1, "in png_handle_zTXt"); + +#ifdef PNG_USER_LIMITS_SUPPORTED + if (png_ptr->user_chunk_cache_max != 0) + { + if (png_ptr->user_chunk_cache_max == 1) + { + png_crc_finish(png_ptr, length); + return; + } + if (--png_ptr->user_chunk_cache_max == 1) + { + png_warning(png_ptr, "No space in chunk cache for zTXt"); + png_crc_finish(png_ptr, length); + return; + } + } +#endif + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before zTXt"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + +#ifdef PNG_MAX_MALLOC_64K + /* We will no doubt have problems with chunks even half this size, but + there is no hard and fast rule to tell us where to stop. */ + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "zTXt chunk too large to fit in memory"); + png_crc_finish(png_ptr, length); + return; + } +#endif + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); + if (png_ptr->chunkdata == NULL) + { + png_warning(png_ptr, "Out of memory processing zTXt chunk"); + return; + } + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + if (png_crc_finish(png_ptr, 0)) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + png_ptr->chunkdata[slength] = 0x00; + + for (text = png_ptr->chunkdata; *text; text++) + /* Empty loop */ ; + + /* zTXt must have some text after the chunkdataword */ + if (text >= png_ptr->chunkdata + slength - 2) + { + png_warning(png_ptr, "Truncated zTXt chunk"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + else + { + comp_type = *(++text); + if (comp_type != PNG_TEXT_COMPRESSION_zTXt) + { + png_warning(png_ptr, "Unknown compression type in zTXt chunk"); + comp_type = PNG_TEXT_COMPRESSION_zTXt; + } + text++; /* Skip the compression_method byte */ + } + prefix_len = text - png_ptr->chunkdata; + + png_decompress_chunk(png_ptr, comp_type, + (png_size_t)length, prefix_len, &data_len); + + text_ptr = (png_textp)png_malloc_warn(png_ptr, + png_sizeof(png_text)); + if (text_ptr == NULL) + { + png_warning(png_ptr, "Not enough memory to process zTXt chunk"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + text_ptr->compression = comp_type; + text_ptr->key = png_ptr->chunkdata; +#ifdef PNG_iTXt_SUPPORTED + text_ptr->lang = NULL; + text_ptr->lang_key = NULL; + text_ptr->itxt_length = 0; +#endif + text_ptr->text = png_ptr->chunkdata + prefix_len; + text_ptr->text_length = data_len; + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, text_ptr); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + if (ret) + png_error(png_ptr, "Insufficient memory to store zTXt chunk"); +} +#endif + +#ifdef PNG_READ_iTXt_SUPPORTED +/* Note: this does not correctly handle chunks that are > 64K under DOS */ +void /* PRIVATE */ +png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_textp text_ptr; + png_charp key, lang, text, lang_key; + int comp_flag; + int comp_type = 0; + int ret; + png_size_t slength, prefix_len, data_len; + + png_debug(1, "in png_handle_iTXt"); + +#ifdef PNG_USER_LIMITS_SUPPORTED + if (png_ptr->user_chunk_cache_max != 0) + { + if (png_ptr->user_chunk_cache_max == 1) + { + png_crc_finish(png_ptr, length); + return; + } + if (--png_ptr->user_chunk_cache_max == 1) + { + png_warning(png_ptr, "No space in chunk cache for iTXt"); + png_crc_finish(png_ptr, length); + return; + } + } +#endif + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before iTXt"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + +#ifdef PNG_MAX_MALLOC_64K + /* We will no doubt have problems with chunks even half this size, but + there is no hard and fast rule to tell us where to stop. */ + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "iTXt chunk too large to fit in memory"); + png_crc_finish(png_ptr, length); + return; + } +#endif + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); + if (png_ptr->chunkdata == NULL) + { + png_warning(png_ptr, "No memory to process iTXt chunk"); + return; + } + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + if (png_crc_finish(png_ptr, 0)) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + png_ptr->chunkdata[slength] = 0x00; + + for (lang = png_ptr->chunkdata; *lang; lang++) + /* Empty loop */ ; + lang++; /* Skip NUL separator */ + + /* iTXt must have a language tag (possibly empty), two compression bytes, + * translated keyword (possibly empty), and possibly some text after the + * keyword + */ + + if (lang >= png_ptr->chunkdata + slength - 3) + { + png_warning(png_ptr, "Truncated iTXt chunk"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + else + { + comp_flag = *lang++; + comp_type = *lang++; + } + + for (lang_key = lang; *lang_key; lang_key++) + /* Empty loop */ ; + lang_key++; /* Skip NUL separator */ + + if (lang_key >= png_ptr->chunkdata + slength) + { + png_warning(png_ptr, "Truncated iTXt chunk"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + for (text = lang_key; *text; text++) + /* Empty loop */ ; + text++; /* Skip NUL separator */ + if (text >= png_ptr->chunkdata + slength) + { + png_warning(png_ptr, "Malformed iTXt chunk"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + prefix_len = text - png_ptr->chunkdata; + + key=png_ptr->chunkdata; + if (comp_flag) + png_decompress_chunk(png_ptr, comp_type, + (size_t)length, prefix_len, &data_len); + else + data_len = png_strlen(png_ptr->chunkdata + prefix_len); + text_ptr = (png_textp)png_malloc_warn(png_ptr, + png_sizeof(png_text)); + if (text_ptr == NULL) + { + png_warning(png_ptr, "Not enough memory to process iTXt chunk"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + text_ptr->compression = (int)comp_flag + 1; + text_ptr->lang_key = png_ptr->chunkdata + (lang_key - key); + text_ptr->lang = png_ptr->chunkdata + (lang - key); + text_ptr->itxt_length = data_len; + text_ptr->text_length = 0; + text_ptr->key = png_ptr->chunkdata; + text_ptr->text = png_ptr->chunkdata + prefix_len; + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, text_ptr); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + if (ret) + png_error(png_ptr, "Insufficient memory to store iTXt chunk"); +} +#endif + +/* This function is called when we haven't found a handler for a + chunk. If there isn't a problem with the chunk itself (ie bad + chunk name, CRC, or a critical chunk), the chunk is silently ignored + -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which + case it will be saved away to be written out later. */ +void /* PRIVATE */ +png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_uint_32 skip = 0; + + png_debug(1, "in png_handle_unknown"); + +#ifdef PNG_USER_LIMITS_SUPPORTED + if (png_ptr->user_chunk_cache_max != 0) + { + if (png_ptr->user_chunk_cache_max == 1) + { + png_crc_finish(png_ptr, length); + return; + } + if (--png_ptr->user_chunk_cache_max == 1) + { + png_warning(png_ptr, "No space in chunk cache for unknown chunk"); + png_crc_finish(png_ptr, length); + return; + } + } +#endif + + if (png_ptr->mode & PNG_HAVE_IDAT) + { + PNG_IDAT; + if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* Not an IDAT */ + png_ptr->mode |= PNG_AFTER_IDAT; + } + + if (!(png_ptr->chunk_name[0] & 0x20)) + { +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != + PNG_HANDLE_CHUNK_ALWAYS +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED + && png_ptr->read_user_chunk_fn == NULL +#endif + ) +#endif + png_chunk_error(png_ptr, "unknown critical chunk"); + } + +#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED + if ((png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED + || (png_ptr->read_user_chunk_fn != NULL) +#endif + ) + { +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "unknown chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + png_memcpy((png_charp)png_ptr->unknown_chunk.name, + (png_charp)png_ptr->chunk_name, + png_sizeof(png_ptr->unknown_chunk.name)); + png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name)-1] + = '\0'; + png_ptr->unknown_chunk.size = (png_size_t)length; + if (length == 0) + png_ptr->unknown_chunk.data = NULL; + else + { + png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length); + png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length); + } +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED + if (png_ptr->read_user_chunk_fn != NULL) + { + /* Callback to user unknown chunk handler */ + int ret; + ret = (*(png_ptr->read_user_chunk_fn)) + (png_ptr, &png_ptr->unknown_chunk); + if (ret < 0) + png_chunk_error(png_ptr, "error in user chunk"); + if (ret == 0) + { + if (!(png_ptr->chunk_name[0] & 0x20)) +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != + PNG_HANDLE_CHUNK_ALWAYS) +#endif + png_chunk_error(png_ptr, "unknown critical chunk"); + png_set_unknown_chunks(png_ptr, info_ptr, + &png_ptr->unknown_chunk, 1); + } + } + else +#endif + png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1); + png_free(png_ptr, png_ptr->unknown_chunk.data); + png_ptr->unknown_chunk.data = NULL; + } + else +#endif + skip = length; + + png_crc_finish(png_ptr, skip); + +#ifndef PNG_READ_USER_CHUNKS_SUPPORTED + info_ptr = info_ptr; /* Quiet compiler warnings about unused info_ptr */ +#endif +} + +/* This function is called to verify that a chunk name is valid. + This function can't have the "critical chunk check" incorporated + into it, since in the future we will need to be able to call user + functions to handle unknown critical chunks after we check that + the chunk name itself is valid. */ + +#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) + +void /* PRIVATE */ +png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name) +{ + png_debug(1, "in png_check_chunk_name"); + if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) || + isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3])) + { + png_chunk_error(png_ptr, "invalid chunk type"); + } +} + +/* Combines the row recently read in with the existing pixels in the + row. This routine takes care of alpha and transparency if requested. + This routine also handles the two methods of progressive display + of interlaced images, depending on the mask value. + The mask value describes which pixels are to be combined with + the row. The pattern always repeats every 8 pixels, so just 8 + bits are needed. A one indicates the pixel is to be combined, + a zero indicates the pixel is to be skipped. This is in addition + to any alpha or transparency value associated with the pixel. If + you want all pixels to be combined, pass 0xff (255) in mask. */ + +void /* PRIVATE */ +png_combine_row(png_structp png_ptr, png_bytep row, int mask) +{ + png_debug(1, "in png_combine_row"); + if (mask == 0xff) + { + png_memcpy(row, png_ptr->row_buf + 1, + PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width)); + } + else + { + switch (png_ptr->row_info.pixel_depth) + { + case 1: + { + png_bytep sp = png_ptr->row_buf + 1; + png_bytep dp = row; + int s_inc, s_start, s_end; + int m = 0x80; + int shift; + png_uint_32 i; + png_uint_32 row_width = png_ptr->width; + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (png_ptr->transformations & PNG_PACKSWAP) + { + s_start = 0; + s_end = 7; + s_inc = 1; + } + else +#endif + { + s_start = 7; + s_end = 0; + s_inc = -1; + } + + shift = s_start; + + for (i = 0; i < row_width; i++) + { + if (m & mask) + { + int value; + + value = (*sp >> shift) & 0x01; + *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff); + *dp |= (png_byte)(value << shift); + } + + if (shift == s_end) + { + shift = s_start; + sp++; + dp++; + } + else + shift += s_inc; + + if (m == 1) + m = 0x80; + else + m >>= 1; + } + break; + } + case 2: + { + png_bytep sp = png_ptr->row_buf + 1; + png_bytep dp = row; + int s_start, s_end, s_inc; + int m = 0x80; + int shift; + png_uint_32 i; + png_uint_32 row_width = png_ptr->width; + int value; + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (png_ptr->transformations & PNG_PACKSWAP) + { + s_start = 0; + s_end = 6; + s_inc = 2; + } + else +#endif + { + s_start = 6; + s_end = 0; + s_inc = -2; + } + + shift = s_start; + + for (i = 0; i < row_width; i++) + { + if (m & mask) + { + value = (*sp >> shift) & 0x03; + *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *dp |= (png_byte)(value << shift); + } + + if (shift == s_end) + { + shift = s_start; + sp++; + dp++; + } + else + shift += s_inc; + if (m == 1) + m = 0x80; + else + m >>= 1; + } + break; + } + case 4: + { + png_bytep sp = png_ptr->row_buf + 1; + png_bytep dp = row; + int s_start, s_end, s_inc; + int m = 0x80; + int shift; + png_uint_32 i; + png_uint_32 row_width = png_ptr->width; + int value; + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (png_ptr->transformations & PNG_PACKSWAP) + { + s_start = 0; + s_end = 4; + s_inc = 4; + } + else +#endif + { + s_start = 4; + s_end = 0; + s_inc = -4; + } + shift = s_start; + + for (i = 0; i < row_width; i++) + { + if (m & mask) + { + value = (*sp >> shift) & 0xf; + *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *dp |= (png_byte)(value << shift); + } + + if (shift == s_end) + { + shift = s_start; + sp++; + dp++; + } + else + shift += s_inc; + if (m == 1) + m = 0x80; + else + m >>= 1; + } + break; + } + default: + { + png_bytep sp = png_ptr->row_buf + 1; + png_bytep dp = row; + png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3); + png_uint_32 i; + png_uint_32 row_width = png_ptr->width; + png_byte m = 0x80; + + + for (i = 0; i < row_width; i++) + { + if (m & mask) + { + png_memcpy(dp, sp, pixel_bytes); + } + + sp += pixel_bytes; + dp += pixel_bytes; + + if (m == 1) + m = 0x80; + else + m >>= 1; + } + break; + } + } + } +} + +#ifdef PNG_READ_INTERLACING_SUPPORTED +/* OLD pre-1.0.9 interface: +void png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, + png_uint_32 transformations) + */ +void /* PRIVATE */ +png_do_read_interlace(png_structp png_ptr) +{ + png_row_infop row_info = &(png_ptr->row_info); + png_bytep row = png_ptr->row_buf + 1; + int pass = png_ptr->pass; + png_uint_32 transformations = png_ptr->transformations; + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + /* Offset to next interlace block */ + PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + png_debug(1, "in png_do_read_interlace"); + if (row != NULL && row_info != NULL) + { + png_uint_32 final_width; + + final_width = row_info->width * png_pass_inc[pass]; + + switch (row_info->pixel_depth) + { + case 1: + { + png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3); + png_bytep dp = row + (png_size_t)((final_width - 1) >> 3); + int sshift, dshift; + int s_start, s_end, s_inc; + int jstop = png_pass_inc[pass]; + png_byte v; + png_uint_32 i; + int j; + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (transformations & PNG_PACKSWAP) + { + sshift = (int)((row_info->width + 7) & 0x07); + dshift = (int)((final_width + 7) & 0x07); + s_start = 7; + s_end = 0; + s_inc = -1; + } + else +#endif + { + sshift = 7 - (int)((row_info->width + 7) & 0x07); + dshift = 7 - (int)((final_width + 7) & 0x07); + s_start = 0; + s_end = 7; + s_inc = 1; + } + + for (i = 0; i < row_info->width; i++) + { + v = (png_byte)((*sp >> sshift) & 0x01); + for (j = 0; j < jstop; j++) + { + *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff); + *dp |= (png_byte)(v << dshift); + if (dshift == s_end) + { + dshift = s_start; + dp--; + } + else + dshift += s_inc; + } + if (sshift == s_end) + { + sshift = s_start; + sp--; + } + else + sshift += s_inc; + } + break; + } + case 2: + { + png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2); + png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2); + int sshift, dshift; + int s_start, s_end, s_inc; + int jstop = png_pass_inc[pass]; + png_uint_32 i; + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (transformations & PNG_PACKSWAP) + { + sshift = (int)(((row_info->width + 3) & 0x03) << 1); + dshift = (int)(((final_width + 3) & 0x03) << 1); + s_start = 6; + s_end = 0; + s_inc = -2; + } + else +#endif + { + sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1); + dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1); + s_start = 0; + s_end = 6; + s_inc = 2; + } + + for (i = 0; i < row_info->width; i++) + { + png_byte v; + int j; + + v = (png_byte)((*sp >> sshift) & 0x03); + for (j = 0; j < jstop; j++) + { + *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff); + *dp |= (png_byte)(v << dshift); + if (dshift == s_end) + { + dshift = s_start; + dp--; + } + else + dshift += s_inc; + } + if (sshift == s_end) + { + sshift = s_start; + sp--; + } + else + sshift += s_inc; + } + break; + } + case 4: + { + png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1); + png_bytep dp = row + (png_size_t)((final_width - 1) >> 1); + int sshift, dshift; + int s_start, s_end, s_inc; + png_uint_32 i; + int jstop = png_pass_inc[pass]; + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (transformations & PNG_PACKSWAP) + { + sshift = (int)(((row_info->width + 1) & 0x01) << 2); + dshift = (int)(((final_width + 1) & 0x01) << 2); + s_start = 4; + s_end = 0; + s_inc = -4; + } + else +#endif + { + sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2); + dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2); + s_start = 0; + s_end = 4; + s_inc = 4; + } + + for (i = 0; i < row_info->width; i++) + { + png_byte v = (png_byte)((*sp >> sshift) & 0xf); + int j; + + for (j = 0; j < jstop; j++) + { + *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff); + *dp |= (png_byte)(v << dshift); + if (dshift == s_end) + { + dshift = s_start; + dp--; + } + else + dshift += s_inc; + } + if (sshift == s_end) + { + sshift = s_start; + sp--; + } + else + sshift += s_inc; + } + break; + } + default: + { + png_size_t pixel_bytes = (row_info->pixel_depth >> 3); + png_bytep sp = row + (png_size_t)(row_info->width - 1) + * pixel_bytes; + png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes; + + int jstop = png_pass_inc[pass]; + png_uint_32 i; + + for (i = 0; i < row_info->width; i++) + { + png_byte v[8]; + int j; + + png_memcpy(v, sp, pixel_bytes); + for (j = 0; j < jstop; j++) + { + png_memcpy(dp, v, pixel_bytes); + dp -= pixel_bytes; + } + sp -= pixel_bytes; + } + break; + } + } + row_info->width = final_width; + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, final_width); + } +#ifndef PNG_READ_PACKSWAP_SUPPORTED + transformations = transformations; /* Silence compiler warning */ +#endif +} +#endif /* PNG_READ_INTERLACING_SUPPORTED */ + +void /* PRIVATE */ +png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row, + png_bytep prev_row, int filter) +{ + png_debug(1, "in png_read_filter_row"); + png_debug2(2, "row = %lu, filter = %d", png_ptr->row_number, filter); + switch (filter) + { + case PNG_FILTER_VALUE_NONE: + break; + case PNG_FILTER_VALUE_SUB: + { + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; + png_bytep rp = row + bpp; + png_bytep lp = row; + + for (i = bpp; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff); + rp++; + } + break; + } + case PNG_FILTER_VALUE_UP: + { + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + png_bytep rp = row; + png_bytep pp = prev_row; + + for (i = 0; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); + rp++; + } + break; + } + case PNG_FILTER_VALUE_AVG: + { + png_uint_32 i; + png_bytep rp = row; + png_bytep pp = prev_row; + png_bytep lp = row; + png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; + png_uint_32 istop = row_info->rowbytes - bpp; + + for (i = 0; i < bpp; i++) + { + *rp = (png_byte)(((int)(*rp) + + ((int)(*pp++) / 2 )) & 0xff); + rp++; + } + + for (i = 0; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + + (int)(*pp++ + *lp++) / 2 ) & 0xff); + rp++; + } + break; + } + case PNG_FILTER_VALUE_PAETH: + { + png_uint_32 i; + png_bytep rp = row; + png_bytep pp = prev_row; + png_bytep lp = row; + png_bytep cp = prev_row; + png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; + png_uint_32 istop=row_info->rowbytes - bpp; + + for (i = 0; i < bpp; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); + rp++; + } + + for (i = 0; i < istop; i++) /* Use leftover rp,pp */ + { + int a, b, c, pa, pb, pc, p; + + a = *lp++; + b = *pp++; + c = *cp++; + + p = b - c; + pc = a - c; + +#ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +#else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +#endif + + /* + if (pa <= pb && pa <= pc) + p = a; + else if (pb <= pc) + p = b; + else + p = c; + */ + + p = (pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c; + + *rp = (png_byte)(((int)(*rp) + p) & 0xff); + rp++; + } + break; + } + default: + png_warning(png_ptr, "Ignoring bad adaptive filter type"); + *row = 0; + break; + } +} + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +void /* PRIVATE */ +png_read_finish_row(png_structp png_ptr) +{ +#ifdef PNG_READ_INTERLACING_SUPPORTED + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif /* PNG_READ_INTERLACING_SUPPORTED */ + + png_debug(1, "in png_read_finish_row"); + png_ptr->row_number++; + if (png_ptr->row_number < png_ptr->num_rows) + return; + +#ifdef PNG_READ_INTERLACING_SUPPORTED + if (png_ptr->interlaced) + { + png_ptr->row_number = 0; + png_memset(png_ptr->prev_row, 0, + png_ptr->rowbytes + 1); + do + { + png_ptr->pass++; + if (png_ptr->pass >= 7) + break; + png_ptr->iwidth = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + + if (!(png_ptr->transformations & PNG_INTERLACE)) + { + png_ptr->num_rows = (png_ptr->height + + png_pass_yinc[png_ptr->pass] - 1 - + png_pass_ystart[png_ptr->pass]) / + png_pass_yinc[png_ptr->pass]; + if (!(png_ptr->num_rows)) + continue; + } + else /* if (png_ptr->transformations & PNG_INTERLACE) */ + break; + } while (png_ptr->iwidth == 0); + + if (png_ptr->pass < 7) + return; + } +#endif /* PNG_READ_INTERLACING_SUPPORTED */ + + if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) + { + PNG_IDAT; + char extra; + int ret; + + png_ptr->zstream.next_out = (Byte *)&extra; + png_ptr->zstream.avail_out = (uInt)1; + for (;;) + { + if (!(png_ptr->zstream.avail_in)) + { + while (!png_ptr->idat_size) + { + png_byte chunk_length[4]; + + png_crc_finish(png_ptr, 0); + + png_read_data(png_ptr, chunk_length, 4); + png_ptr->idat_size = png_get_uint_31(png_ptr, chunk_length); + png_reset_crc(png_ptr); + png_crc_read(png_ptr, png_ptr->chunk_name, 4); + if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + png_error(png_ptr, "Not enough image data"); + + } + png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_in = png_ptr->zbuf; + if (png_ptr->zbuf_size > png_ptr->idat_size) + png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size; + png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in); + png_ptr->idat_size -= png_ptr->zstream.avail_in; + } + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + if (ret == Z_STREAM_END) + { + if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in || + png_ptr->idat_size) + png_warning(png_ptr, "Extra compressed data"); + png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + break; + } + if (ret != Z_OK) + png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg : + "Decompression Error"); + + if (!(png_ptr->zstream.avail_out)) + { + png_warning(png_ptr, "Extra compressed data"); + png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + break; + } + + } + png_ptr->zstream.avail_out = 0; + } + + if (png_ptr->idat_size || png_ptr->zstream.avail_in) + png_warning(png_ptr, "Extra compression data"); + + inflateReset(&png_ptr->zstream); + + png_ptr->mode |= PNG_AFTER_IDAT; +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +void /* PRIVATE */ +png_read_start_row(png_structp png_ptr) +{ +#ifdef PNG_READ_INTERLACING_SUPPORTED + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif + + int max_pixel_depth; + png_size_t row_bytes; + + png_debug(1, "in png_read_start_row"); + png_ptr->zstream.avail_in = 0; + png_init_read_transformations(png_ptr); +#ifdef PNG_READ_INTERLACING_SUPPORTED + if (png_ptr->interlaced) + { + if (!(png_ptr->transformations & PNG_INTERLACE)) + png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - + png_pass_ystart[0]) / png_pass_yinc[0]; + else + png_ptr->num_rows = png_ptr->height; + + png_ptr->iwidth = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + } + else +#endif /* PNG_READ_INTERLACING_SUPPORTED */ + { + png_ptr->num_rows = png_ptr->height; + png_ptr->iwidth = png_ptr->width; + } + max_pixel_depth = png_ptr->pixel_depth; + +#ifdef PNG_READ_PACK_SUPPORTED + if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8) + max_pixel_depth = 8; +#endif + +#ifdef PNG_READ_EXPAND_SUPPORTED + if (png_ptr->transformations & PNG_EXPAND) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (png_ptr->num_trans) + max_pixel_depth = 32; + else + max_pixel_depth = 24; + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) + { + if (max_pixel_depth < 8) + max_pixel_depth = 8; + if (png_ptr->num_trans) + max_pixel_depth *= 2; + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + { + if (png_ptr->num_trans) + { + max_pixel_depth *= 4; + max_pixel_depth /= 3; + } + } + } +#endif + +#ifdef PNG_READ_FILLER_SUPPORTED + if (png_ptr->transformations & (PNG_FILLER)) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + max_pixel_depth = 32; + else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) + { + if (max_pixel_depth <= 8) + max_pixel_depth = 16; + else + max_pixel_depth = 32; + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + { + if (max_pixel_depth <= 32) + max_pixel_depth = 32; + else + max_pixel_depth = 64; + } + } +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED + if (png_ptr->transformations & PNG_GRAY_TO_RGB) + { + if ( +#ifdef PNG_READ_EXPAND_SUPPORTED + (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) || +#endif +#ifdef PNG_READ_FILLER_SUPPORTED + (png_ptr->transformations & (PNG_FILLER)) || +#endif + png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (max_pixel_depth <= 16) + max_pixel_depth = 32; + else + max_pixel_depth = 64; + } + else + { + if (max_pixel_depth <= 8) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + max_pixel_depth = 32; + else + max_pixel_depth = 24; + } + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + max_pixel_depth = 64; + else + max_pixel_depth = 48; + } + } +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \ +defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) + if (png_ptr->transformations & PNG_USER_TRANSFORM) + { + int user_pixel_depth = png_ptr->user_transform_depth* + png_ptr->user_transform_channels; + if (user_pixel_depth > max_pixel_depth) + max_pixel_depth=user_pixel_depth; + } +#endif + + /* Align the width on the next larger 8 pixels. Mainly used + * for interlacing + */ + row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7)); + /* Calculate the maximum bytes needed, adding a byte and a pixel + * for safety's sake + */ + row_bytes = PNG_ROWBYTES(max_pixel_depth, row_bytes) + + 1 + ((max_pixel_depth + 7) >> 3); +#ifdef PNG_MAX_MALLOC_64K + if (row_bytes > (png_uint_32)65536L) + png_error(png_ptr, "This image requires a row greater than 64KB"); +#endif + + if (row_bytes + 48 > png_ptr->old_big_row_buf_size) + { + png_free(png_ptr, png_ptr->big_row_buf); + if (png_ptr->interlaced) + png_ptr->big_row_buf = (png_bytep)png_calloc(png_ptr, + row_bytes + 48); + else + png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, + row_bytes + 48); + png_ptr->old_big_row_buf_size = row_bytes + 48; + +#ifdef PNG_ALIGNED_MEMORY_SUPPORTED + /* Use 16-byte aligned memory for row_buf with at least 16 bytes + * of padding before and after row_buf. + */ + png_ptr->row_buf = png_ptr->big_row_buf + 32 + - (((png_alloc_size_t)&(png_ptr->big_row_buf[0]) + 15) % 16); + png_ptr->old_big_row_buf_size = row_bytes + 48; +#else + /* Use 32 bytes of padding before and 16 bytes after row_buf. */ + png_ptr->row_buf = png_ptr->big_row_buf + 32; +#endif + png_ptr->old_big_row_buf_size = row_bytes + 48; + } + +#ifdef PNG_MAX_MALLOC_64K + if ((png_uint_32)png_ptr->rowbytes + 1 > (png_uint_32)65536L) + png_error(png_ptr, "This image requires a row greater than 64KB"); +#endif + if ((png_uint_32)png_ptr->rowbytes > (png_uint_32)(PNG_SIZE_MAX - 1)) + png_error(png_ptr, "Row has too many bytes to allocate in memory"); + + if (png_ptr->rowbytes + 1 > png_ptr->old_prev_row_size) + { + png_free(png_ptr, png_ptr->prev_row); + png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)( + png_ptr->rowbytes + 1)); + png_ptr->old_prev_row_size = png_ptr->rowbytes + 1; + } + + png_memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1); + + png_debug1(3, "width = %lu,", png_ptr->width); + png_debug1(3, "height = %lu,", png_ptr->height); + png_debug1(3, "iwidth = %lu,", png_ptr->iwidth); + png_debug1(3, "num_rows = %lu,", png_ptr->num_rows); + png_debug1(3, "rowbytes = %lu,", png_ptr->rowbytes); + png_debug1(3, "irowbytes = %lu", + PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1); + + png_ptr->flags |= PNG_FLAG_ROW_INIT; +} +#endif /* PNG_READ_SUPPORTED */ diff --git a/reactos/dll/3rdparty/libpng/pngset.c b/reactos/dll/3rdparty/libpng/pngset.c new file mode 100644 index 00000000000..1f972c4edb6 --- /dev/null +++ b/reactos/dll/3rdparty/libpng/pngset.c @@ -0,0 +1,1167 @@ + +/* pngset.c - storage of image information into info struct + * + * Last changed in libpng 1.4.1 [February 25, 2010] + * Copyright (c) 1998-2010 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * The functions here are used during reads to store data from the file + * into the info struct, and during writes to store application data + * into the info struct for writing into the file. This abstracts the + * info struct and allows us to change the structure in the future. + */ + +#define PNG_NO_PEDANTIC_WARNINGS +#include "png.h" +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +#include "pngpriv.h" + +#ifdef PNG_bKGD_SUPPORTED +void PNGAPI +png_set_bKGD(png_structp png_ptr, png_infop info_ptr, png_color_16p background) +{ + png_debug1(1, "in %s storage function", "bKGD"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_memcpy(&(info_ptr->background), background, png_sizeof(png_color_16)); + info_ptr->valid |= PNG_INFO_bKGD; +} +#endif + +#ifdef PNG_cHRM_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_cHRM(png_structp png_ptr, png_infop info_ptr, + double white_x, double white_y, double red_x, double red_y, + double green_x, double green_y, double blue_x, double blue_y) +{ + png_debug1(1, "in %s storage function", "cHRM"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->x_white = (float)white_x; + info_ptr->y_white = (float)white_y; + info_ptr->x_red = (float)red_x; + info_ptr->y_red = (float)red_y; + info_ptr->x_green = (float)green_x; + info_ptr->y_green = (float)green_y; + info_ptr->x_blue = (float)blue_x; + info_ptr->y_blue = (float)blue_y; +#ifdef PNG_FIXED_POINT_SUPPORTED + info_ptr->int_x_white = (png_fixed_point)(white_x*100000.+0.5); + info_ptr->int_y_white = (png_fixed_point)(white_y*100000.+0.5); + info_ptr->int_x_red = (png_fixed_point)( red_x*100000.+0.5); + info_ptr->int_y_red = (png_fixed_point)( red_y*100000.+0.5); + info_ptr->int_x_green = (png_fixed_point)(green_x*100000.+0.5); + info_ptr->int_y_green = (png_fixed_point)(green_y*100000.+0.5); + info_ptr->int_x_blue = (png_fixed_point)( blue_x*100000.+0.5); + info_ptr->int_y_blue = (png_fixed_point)( blue_y*100000.+0.5); +#endif + info_ptr->valid |= PNG_INFO_cHRM; +} +#endif /* PNG_FLOATING_POINT_SUPPORTED */ + +#ifdef PNG_FIXED_POINT_SUPPORTED +void PNGAPI +png_set_cHRM_fixed(png_structp png_ptr, png_infop info_ptr, + png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x, + png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y, + png_fixed_point blue_x, png_fixed_point blue_y) +{ + png_debug1(1, "in %s storage function", "cHRM fixed"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + +#ifdef PNG_CHECK_cHRM_SUPPORTED + if (png_check_cHRM_fixed(png_ptr, + white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y)) +#endif + { + info_ptr->int_x_white = white_x; + info_ptr->int_y_white = white_y; + info_ptr->int_x_red = red_x; + info_ptr->int_y_red = red_y; + info_ptr->int_x_green = green_x; + info_ptr->int_y_green = green_y; + info_ptr->int_x_blue = blue_x; + info_ptr->int_y_blue = blue_y; +#ifdef PNG_FLOATING_POINT_SUPPORTED + info_ptr->x_white = (float)(white_x/100000.); + info_ptr->y_white = (float)(white_y/100000.); + info_ptr->x_red = (float)( red_x/100000.); + info_ptr->y_red = (float)( red_y/100000.); + info_ptr->x_green = (float)(green_x/100000.); + info_ptr->y_green = (float)(green_y/100000.); + info_ptr->x_blue = (float)( blue_x/100000.); + info_ptr->y_blue = (float)( blue_y/100000.); +#endif + info_ptr->valid |= PNG_INFO_cHRM; + } +} +#endif /* PNG_FIXED_POINT_SUPPORTED */ +#endif /* PNG_cHRM_SUPPORTED */ + +#ifdef PNG_gAMA_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_gAMA(png_structp png_ptr, png_infop info_ptr, double file_gamma) +{ + double png_gamma; + + png_debug1(1, "in %s storage function", "gAMA"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + /* Check for overflow */ + if (file_gamma > 21474.83) + { + png_warning(png_ptr, "Limiting gamma to 21474.83"); + png_gamma=21474.83; + } + else + png_gamma = file_gamma; + info_ptr->gamma = (float)png_gamma; +#ifdef PNG_FIXED_POINT_SUPPORTED + info_ptr->int_gamma = (int)(png_gamma*100000.+.5); +#endif + info_ptr->valid |= PNG_INFO_gAMA; + if (png_gamma == 0.0) + png_warning(png_ptr, "Setting gamma=0"); +} +#endif +void PNGAPI +png_set_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, png_fixed_point + int_gamma) +{ + png_fixed_point png_gamma; + + png_debug1(1, "in %s storage function", "gAMA"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (int_gamma > (png_fixed_point)PNG_UINT_31_MAX) + { + png_warning(png_ptr, "Limiting gamma to 21474.83"); + png_gamma=PNG_UINT_31_MAX; + } + else + { + if (int_gamma < 0) + { + png_warning(png_ptr, "Setting negative gamma to zero"); + png_gamma = 0; + } + else + png_gamma = int_gamma; + } +#ifdef PNG_FLOATING_POINT_SUPPORTED + info_ptr->gamma = (float)(png_gamma/100000.); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED + info_ptr->int_gamma = png_gamma; +#endif + info_ptr->valid |= PNG_INFO_gAMA; + if (png_gamma == 0) + png_warning(png_ptr, "Setting gamma=0"); +} +#endif + +#ifdef PNG_hIST_SUPPORTED +void PNGAPI +png_set_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_16p hist) +{ + int i; + + png_debug1(1, "in %s storage function", "hIST"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (info_ptr->num_palette == 0 || info_ptr->num_palette + > PNG_MAX_PALETTE_LENGTH) + { + png_warning(png_ptr, + "Invalid palette size, hIST allocation skipped"); + return; + } + + png_free_data(png_ptr, info_ptr, PNG_FREE_HIST, 0); + /* Changed from info->num_palette to PNG_MAX_PALETTE_LENGTH in + * version 1.2.1 + */ + png_ptr->hist = (png_uint_16p)png_malloc_warn(png_ptr, + PNG_MAX_PALETTE_LENGTH * png_sizeof(png_uint_16)); + if (png_ptr->hist == NULL) + { + png_warning(png_ptr, "Insufficient memory for hIST chunk data"); + return; + } + + for (i = 0; i < info_ptr->num_palette; i++) + png_ptr->hist[i] = hist[i]; + info_ptr->hist = png_ptr->hist; + info_ptr->valid |= PNG_INFO_hIST; + + info_ptr->free_me |= PNG_FREE_HIST; +} +#endif + +void PNGAPI +png_set_IHDR(png_structp png_ptr, png_infop info_ptr, + png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_type, int compression_type, + int filter_type) +{ + png_debug1(1, "in %s storage function", "IHDR"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->width = width; + info_ptr->height = height; + info_ptr->bit_depth = (png_byte)bit_depth; + info_ptr->color_type = (png_byte)color_type; + info_ptr->compression_type = (png_byte)compression_type; + info_ptr->filter_type = (png_byte)filter_type; + info_ptr->interlace_type = (png_byte)interlace_type; + + png_check_IHDR (png_ptr, info_ptr->width, info_ptr->height, + info_ptr->bit_depth, info_ptr->color_type, info_ptr->interlace_type, + info_ptr->compression_type, info_ptr->filter_type); + + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + info_ptr->channels = 1; + else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) + info_ptr->channels = 3; + else + info_ptr->channels = 1; + if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) + info_ptr->channels++; + info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth); + + /* Check for potential overflow */ + if (width > (PNG_UINT_32_MAX + >> 3) /* 8-byte RGBA pixels */ + - 64 /* bigrowbuf hack */ + - 1 /* filter byte */ + - 7*8 /* rounding of width to multiple of 8 pixels */ + - 8) /* extra max_pixel_depth pad */ + info_ptr->rowbytes = 0; + else + info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width); +} + +#ifdef PNG_oFFs_SUPPORTED +void PNGAPI +png_set_oFFs(png_structp png_ptr, png_infop info_ptr, + png_int_32 offset_x, png_int_32 offset_y, int unit_type) +{ + png_debug1(1, "in %s storage function", "oFFs"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->x_offset = offset_x; + info_ptr->y_offset = offset_y; + info_ptr->offset_unit_type = (png_byte)unit_type; + info_ptr->valid |= PNG_INFO_oFFs; +} +#endif + +#ifdef PNG_pCAL_SUPPORTED +void PNGAPI +png_set_pCAL(png_structp png_ptr, png_infop info_ptr, + png_charp purpose, png_int_32 X0, png_int_32 X1, int type, int nparams, + png_charp units, png_charpp params) +{ + png_size_t length; + int i; + + png_debug1(1, "in %s storage function", "pCAL"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + length = png_strlen(purpose) + 1; + png_debug1(3, "allocating purpose for info (%lu bytes)", + (unsigned long)length); + info_ptr->pcal_purpose = (png_charp)png_malloc_warn(png_ptr, length); + if (info_ptr->pcal_purpose == NULL) + { + png_warning(png_ptr, "Insufficient memory for pCAL purpose"); + return; + } + png_memcpy(info_ptr->pcal_purpose, purpose, length); + + png_debug(3, "storing X0, X1, type, and nparams in info"); + info_ptr->pcal_X0 = X0; + info_ptr->pcal_X1 = X1; + info_ptr->pcal_type = (png_byte)type; + info_ptr->pcal_nparams = (png_byte)nparams; + + length = png_strlen(units) + 1; + png_debug1(3, "allocating units for info (%lu bytes)", + (unsigned long)length); + info_ptr->pcal_units = (png_charp)png_malloc_warn(png_ptr, length); + if (info_ptr->pcal_units == NULL) + { + png_warning(png_ptr, "Insufficient memory for pCAL units"); + return; + } + png_memcpy(info_ptr->pcal_units, units, length); + + info_ptr->pcal_params = (png_charpp)png_malloc_warn(png_ptr, + (png_size_t)((nparams + 1) * png_sizeof(png_charp))); + if (info_ptr->pcal_params == NULL) + { + png_warning(png_ptr, "Insufficient memory for pCAL params"); + return; + } + + png_memset(info_ptr->pcal_params, 0, (nparams + 1) * png_sizeof(png_charp)); + + for (i = 0; i < nparams; i++) + { + length = png_strlen(params[i]) + 1; + png_debug2(3, "allocating parameter %d for info (%lu bytes)", i, + (unsigned long)length); + info_ptr->pcal_params[i] = (png_charp)png_malloc_warn(png_ptr, length); + if (info_ptr->pcal_params[i] == NULL) + { + png_warning(png_ptr, "Insufficient memory for pCAL parameter"); + return; + } + png_memcpy(info_ptr->pcal_params[i], params[i], length); + } + + info_ptr->valid |= PNG_INFO_pCAL; + info_ptr->free_me |= PNG_FREE_PCAL; +} +#endif + +#if defined(PNG_READ_sCAL_SUPPORTED) || defined(PNG_WRITE_sCAL_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_sCAL(png_structp png_ptr, png_infop info_ptr, + int unit, double width, double height) +{ + png_debug1(1, "in %s storage function", "sCAL"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->scal_unit = (png_byte)unit; + info_ptr->scal_pixel_width = width; + info_ptr->scal_pixel_height = height; + + info_ptr->valid |= PNG_INFO_sCAL; +} +#else +#ifdef PNG_FIXED_POINT_SUPPORTED +void PNGAPI +png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr, + int unit, png_charp swidth, png_charp sheight) +{ + png_size_t length; + + png_debug1(1, "in %s storage function", "sCAL"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->scal_unit = (png_byte)unit; + + length = png_strlen(swidth) + 1; + png_debug1(3, "allocating unit for info (%u bytes)", + (unsigned int)length); + info_ptr->scal_s_width = (png_charp)png_malloc_warn(png_ptr, length); + if (info_ptr->scal_s_width == NULL) + { + png_warning(png_ptr, + "Memory allocation failed while processing sCAL"); + return; + } + png_memcpy(info_ptr->scal_s_width, swidth, length); + + length = png_strlen(sheight) + 1; + png_debug1(3, "allocating unit for info (%u bytes)", + (unsigned int)length); + info_ptr->scal_s_height = (png_charp)png_malloc_warn(png_ptr, length); + if (info_ptr->scal_s_height == NULL) + { + png_free (png_ptr, info_ptr->scal_s_width); + info_ptr->scal_s_width = NULL; + png_warning(png_ptr, + "Memory allocation failed while processing sCAL"); + return; + } + png_memcpy(info_ptr->scal_s_height, sheight, length); + info_ptr->valid |= PNG_INFO_sCAL; + info_ptr->free_me |= PNG_FREE_SCAL; +} +#endif +#endif +#endif + +#ifdef PNG_pHYs_SUPPORTED +void PNGAPI +png_set_pHYs(png_structp png_ptr, png_infop info_ptr, + png_uint_32 res_x, png_uint_32 res_y, int unit_type) +{ + png_debug1(1, "in %s storage function", "pHYs"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->x_pixels_per_unit = res_x; + info_ptr->y_pixels_per_unit = res_y; + info_ptr->phys_unit_type = (png_byte)unit_type; + info_ptr->valid |= PNG_INFO_pHYs; +} +#endif + +void PNGAPI +png_set_PLTE(png_structp png_ptr, png_infop info_ptr, + png_colorp palette, int num_palette) +{ + + png_debug1(1, "in %s storage function", "PLTE"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (num_palette < 0 || num_palette > PNG_MAX_PALETTE_LENGTH) + { + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + png_error(png_ptr, "Invalid palette length"); + else + { + png_warning(png_ptr, "Invalid palette length"); + return; + } + } + + /* It may not actually be necessary to set png_ptr->palette here; + * we do it for backward compatibility with the way the png_handle_tRNS + * function used to do the allocation. + */ + png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0); + + /* Changed in libpng-1.2.1 to allocate PNG_MAX_PALETTE_LENGTH instead + * of num_palette entries, in case of an invalid PNG file that has + * too-large sample values. + */ + png_ptr->palette = (png_colorp)png_calloc(png_ptr, + PNG_MAX_PALETTE_LENGTH * png_sizeof(png_color)); + png_memcpy(png_ptr->palette, palette, num_palette * png_sizeof(png_color)); + info_ptr->palette = png_ptr->palette; + info_ptr->num_palette = png_ptr->num_palette = (png_uint_16)num_palette; + + info_ptr->free_me |= PNG_FREE_PLTE; + + info_ptr->valid |= PNG_INFO_PLTE; +} + +#ifdef PNG_sBIT_SUPPORTED +void PNGAPI +png_set_sBIT(png_structp png_ptr, png_infop info_ptr, + png_color_8p sig_bit) +{ + png_debug1(1, "in %s storage function", "sBIT"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_memcpy(&(info_ptr->sig_bit), sig_bit, png_sizeof(png_color_8)); + info_ptr->valid |= PNG_INFO_sBIT; +} +#endif + +#ifdef PNG_sRGB_SUPPORTED +void PNGAPI +png_set_sRGB(png_structp png_ptr, png_infop info_ptr, int intent) +{ + png_debug1(1, "in %s storage function", "sRGB"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->srgb_intent = (png_byte)intent; + info_ptr->valid |= PNG_INFO_sRGB; +} + +void PNGAPI +png_set_sRGB_gAMA_and_cHRM(png_structp png_ptr, png_infop info_ptr, + int intent) +{ +#ifdef PNG_gAMA_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED + float file_gamma; +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED + png_fixed_point int_file_gamma; +#endif +#endif +#ifdef PNG_cHRM_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED + float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y; +#endif + png_fixed_point int_white_x, int_white_y, int_red_x, int_red_y, int_green_x, + int_green_y, int_blue_x, int_blue_y; +#endif + png_debug1(1, "in %s storage function", "sRGB_gAMA_and_cHRM"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_set_sRGB(png_ptr, info_ptr, intent); + +#ifdef PNG_gAMA_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED + file_gamma = (float).45455; + png_set_gAMA(png_ptr, info_ptr, file_gamma); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED + int_file_gamma = 45455L; + png_set_gAMA_fixed(png_ptr, info_ptr, int_file_gamma); +#endif +#endif + +#ifdef PNG_cHRM_SUPPORTED + int_white_x = 31270L; + int_white_y = 32900L; + int_red_x = 64000L; + int_red_y = 33000L; + int_green_x = 30000L; + int_green_y = 60000L; + int_blue_x = 15000L; + int_blue_y = 6000L; + +#ifdef PNG_FLOATING_POINT_SUPPORTED + white_x = (float).3127; + white_y = (float).3290; + red_x = (float).64; + red_y = (float).33; + green_x = (float).30; + green_y = (float).60; + blue_x = (float).15; + blue_y = (float).06; +#endif + +#ifdef PNG_FIXED_POINT_SUPPORTED + png_set_cHRM_fixed(png_ptr, info_ptr, + int_white_x, int_white_y, int_red_x, int_red_y, int_green_x, + int_green_y, int_blue_x, int_blue_y); +#endif +#ifdef PNG_FLOATING_POINT_SUPPORTED + png_set_cHRM(png_ptr, info_ptr, + white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y); +#endif +#endif /* cHRM */ +} +#endif /* sRGB */ + + +#ifdef PNG_iCCP_SUPPORTED +void PNGAPI +png_set_iCCP(png_structp png_ptr, png_infop info_ptr, + png_charp name, int compression_type, + png_charp profile, png_uint_32 proflen) +{ + png_charp new_iccp_name; + png_charp new_iccp_profile; + png_uint_32 length; + + png_debug1(1, "in %s storage function", "iCCP"); + + if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL) + return; + + length = png_strlen(name)+1; + new_iccp_name = (png_charp)png_malloc_warn(png_ptr, length); + if (new_iccp_name == NULL) + { + png_warning(png_ptr, "Insufficient memory to process iCCP chunk"); + return; + } + png_memcpy(new_iccp_name, name, length); + new_iccp_profile = (png_charp)png_malloc_warn(png_ptr, proflen); + if (new_iccp_profile == NULL) + { + png_free (png_ptr, new_iccp_name); + png_warning(png_ptr, + "Insufficient memory to process iCCP profile"); + return; + } + png_memcpy(new_iccp_profile, profile, (png_size_t)proflen); + + png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0); + + info_ptr->iccp_proflen = proflen; + info_ptr->iccp_name = new_iccp_name; + info_ptr->iccp_profile = new_iccp_profile; + /* Compression is always zero but is here so the API and info structure + * does not have to change if we introduce multiple compression types + */ + info_ptr->iccp_compression = (png_byte)compression_type; + info_ptr->free_me |= PNG_FREE_ICCP; + info_ptr->valid |= PNG_INFO_iCCP; +} +#endif + +#ifdef PNG_TEXT_SUPPORTED +void PNGAPI +png_set_text(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr, + int num_text) +{ + int ret; + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, num_text); + if (ret) + png_error(png_ptr, "Insufficient memory to store text"); +} + +int /* PRIVATE */ +png_set_text_2(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr, + int num_text) +{ + int i; + + png_debug1(1, "in %s storage function", ((png_ptr == NULL || + png_ptr->chunk_name[0] == '\0') ? + "text" : (png_const_charp)png_ptr->chunk_name)); + + if (png_ptr == NULL || info_ptr == NULL || num_text == 0) + return(0); + + /* Make sure we have enough space in the "text" array in info_struct + * to hold all of the incoming text_ptr objects. + */ + if (info_ptr->num_text + num_text > info_ptr->max_text) + { + if (info_ptr->text != NULL) + { + png_textp old_text; + int old_max; + + old_max = info_ptr->max_text; + info_ptr->max_text = info_ptr->num_text + num_text + 8; + old_text = info_ptr->text; + info_ptr->text = (png_textp)png_malloc_warn(png_ptr, + (png_size_t)(info_ptr->max_text * png_sizeof(png_text))); + if (info_ptr->text == NULL) + { + png_free(png_ptr, old_text); + return(1); + } + png_memcpy(info_ptr->text, old_text, (png_size_t)(old_max * + png_sizeof(png_text))); + png_free(png_ptr, old_text); + } + else + { + info_ptr->max_text = num_text + 8; + info_ptr->num_text = 0; + info_ptr->text = (png_textp)png_malloc_warn(png_ptr, + (png_size_t)(info_ptr->max_text * png_sizeof(png_text))); + if (info_ptr->text == NULL) + return(1); + info_ptr->free_me |= PNG_FREE_TEXT; + } + png_debug1(3, "allocated %d entries for info_ptr->text", + info_ptr->max_text); + } + for (i = 0; i < num_text; i++) + { + png_size_t text_length, key_len; + png_size_t lang_len, lang_key_len; + png_textp textp = &(info_ptr->text[info_ptr->num_text]); + + if (text_ptr[i].key == NULL) + continue; + + key_len = png_strlen(text_ptr[i].key); + + if (text_ptr[i].compression <= 0) + { + lang_len = 0; + lang_key_len = 0; + } + + else +#ifdef PNG_iTXt_SUPPORTED + { + /* Set iTXt data */ + + if (text_ptr[i].lang != NULL) + lang_len = png_strlen(text_ptr[i].lang); + else + lang_len = 0; + if (text_ptr[i].lang_key != NULL) + lang_key_len = png_strlen(text_ptr[i].lang_key); + else + lang_key_len = 0; + } +#else /* PNG_iTXt_SUPPORTED */ + { + png_warning(png_ptr, "iTXt chunk not supported"); + continue; + } +#endif + + if (text_ptr[i].text == NULL || text_ptr[i].text[0] == '\0') + { + text_length = 0; +#ifdef PNG_iTXt_SUPPORTED + if (text_ptr[i].compression > 0) + textp->compression = PNG_ITXT_COMPRESSION_NONE; + else +#endif + textp->compression = PNG_TEXT_COMPRESSION_NONE; + } + + else + { + text_length = png_strlen(text_ptr[i].text); + textp->compression = text_ptr[i].compression; + } + + textp->key = (png_charp)png_malloc_warn(png_ptr, + (png_size_t) + (key_len + text_length + lang_len + lang_key_len + 4)); + if (textp->key == NULL) + return(1); + png_debug2(2, "Allocated %lu bytes at %x in png_set_text", + (unsigned long)(png_uint_32) + (key_len + lang_len + lang_key_len + text_length + 4), + (int)textp->key); + + png_memcpy(textp->key, text_ptr[i].key,(png_size_t)(key_len)); + *(textp->key + key_len) = '\0'; +#ifdef PNG_iTXt_SUPPORTED + if (text_ptr[i].compression > 0) + { + textp->lang = textp->key + key_len + 1; + png_memcpy(textp->lang, text_ptr[i].lang, lang_len); + *(textp->lang + lang_len) = '\0'; + textp->lang_key = textp->lang + lang_len + 1; + png_memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len); + *(textp->lang_key + lang_key_len) = '\0'; + textp->text = textp->lang_key + lang_key_len + 1; + } + else +#endif + { +#ifdef PNG_iTXt_SUPPORTED + textp->lang=NULL; + textp->lang_key=NULL; +#endif + textp->text = textp->key + key_len + 1; + } + if (text_length) + png_memcpy(textp->text, text_ptr[i].text, + (png_size_t)(text_length)); + *(textp->text + text_length) = '\0'; + +#ifdef PNG_iTXt_SUPPORTED + if (textp->compression > 0) + { + textp->text_length = 0; + textp->itxt_length = text_length; + } + else +#endif + + { + textp->text_length = text_length; +#ifdef PNG_iTXt_SUPPORTED + textp->itxt_length = 0; +#endif + } + info_ptr->num_text++; + png_debug1(3, "transferred text chunk %d", info_ptr->num_text); + } + return(0); +} +#endif + +#ifdef PNG_tIME_SUPPORTED +void PNGAPI +png_set_tIME(png_structp png_ptr, png_infop info_ptr, png_timep mod_time) +{ + png_debug1(1, "in %s storage function", "tIME"); + + if (png_ptr == NULL || info_ptr == NULL || + (png_ptr->mode & PNG_WROTE_tIME)) + return; + + png_memcpy(&(info_ptr->mod_time), mod_time, png_sizeof(png_time)); + info_ptr->valid |= PNG_INFO_tIME; +} +#endif + +#ifdef PNG_tRNS_SUPPORTED +void PNGAPI +png_set_tRNS(png_structp png_ptr, png_infop info_ptr, + png_bytep trans_alpha, int num_trans, png_color_16p trans_color) +{ + png_debug1(1, "in %s storage function", "tRNS"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (trans_alpha != NULL) + { + /* It may not actually be necessary to set png_ptr->trans_alpha here; + * we do it for backward compatibility with the way the png_handle_tRNS + * function used to do the allocation. + */ + + png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0); + + /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */ + png_ptr->trans_alpha = info_ptr->trans_alpha = (png_bytep)png_malloc(png_ptr, + (png_size_t)PNG_MAX_PALETTE_LENGTH); + if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH) + png_memcpy(info_ptr->trans_alpha, trans_alpha, (png_size_t)num_trans); + } + + if (trans_color != NULL) + { + int sample_max = (1 << info_ptr->bit_depth); + if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY && + (int)trans_color->gray > sample_max) || + (info_ptr->color_type == PNG_COLOR_TYPE_RGB && + ((int)trans_color->red > sample_max || + (int)trans_color->green > sample_max || + (int)trans_color->blue > sample_max))) + png_warning(png_ptr, + "tRNS chunk has out-of-range samples for bit_depth"); + png_memcpy(&(info_ptr->trans_color), trans_color, + png_sizeof(png_color_16)); + if (num_trans == 0) + num_trans = 1; + } + + info_ptr->num_trans = (png_uint_16)num_trans; + if (num_trans != 0) + { + info_ptr->valid |= PNG_INFO_tRNS; + info_ptr->free_me |= PNG_FREE_TRNS; + } +} +#endif + +#ifdef PNG_sPLT_SUPPORTED +void PNGAPI +png_set_sPLT(png_structp png_ptr, + png_infop info_ptr, png_sPLT_tp entries, int nentries) +/* + * entries - array of png_sPLT_t structures + * to be added to the list of palettes + * in the info structure. + * nentries - number of palette structures to be + * added. + */ +{ + png_sPLT_tp np; + int i; + + if (png_ptr == NULL || info_ptr == NULL) + return; + + np = (png_sPLT_tp)png_malloc_warn(png_ptr, + (info_ptr->splt_palettes_num + nentries) * + (png_size_t)png_sizeof(png_sPLT_t)); + if (np == NULL) + { + png_warning(png_ptr, "No memory for sPLT palettes"); + return; + } + + png_memcpy(np, info_ptr->splt_palettes, + info_ptr->splt_palettes_num * png_sizeof(png_sPLT_t)); + png_free(png_ptr, info_ptr->splt_palettes); + info_ptr->splt_palettes=NULL; + + for (i = 0; i < nentries; i++) + { + png_sPLT_tp to = np + info_ptr->splt_palettes_num + i; + png_sPLT_tp from = entries + i; + png_uint_32 length; + + length = png_strlen(from->name) + 1; + to->name = (png_charp)png_malloc_warn(png_ptr, (png_size_t)length); + if (to->name == NULL) + { + png_warning(png_ptr, + "Out of memory while processing sPLT chunk"); + continue; + } + png_memcpy(to->name, from->name, length); + to->entries = (png_sPLT_entryp)png_malloc_warn(png_ptr, + (png_size_t)(from->nentries * png_sizeof(png_sPLT_entry))); + if (to->entries == NULL) + { + png_warning(png_ptr, + "Out of memory while processing sPLT chunk"); + png_free(png_ptr, to->name); + to->name = NULL; + continue; + } + png_memcpy(to->entries, from->entries, + from->nentries * png_sizeof(png_sPLT_entry)); + to->nentries = from->nentries; + to->depth = from->depth; + } + + info_ptr->splt_palettes = np; + info_ptr->splt_palettes_num += nentries; + info_ptr->valid |= PNG_INFO_sPLT; + info_ptr->free_me |= PNG_FREE_SPLT; +} +#endif /* PNG_sPLT_SUPPORTED */ + +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED +void PNGAPI +png_set_unknown_chunks(png_structp png_ptr, + png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns) +{ + png_unknown_chunkp np; + int i; + + if (png_ptr == NULL || info_ptr == NULL || num_unknowns == 0) + return; + + np = (png_unknown_chunkp)png_malloc_warn(png_ptr, + (png_size_t)((info_ptr->unknown_chunks_num + num_unknowns) * + png_sizeof(png_unknown_chunk))); + if (np == NULL) + { + png_warning(png_ptr, + "Out of memory while processing unknown chunk"); + return; + } + + png_memcpy(np, info_ptr->unknown_chunks, + info_ptr->unknown_chunks_num * png_sizeof(png_unknown_chunk)); + png_free(png_ptr, info_ptr->unknown_chunks); + info_ptr->unknown_chunks = NULL; + + for (i = 0; i < num_unknowns; i++) + { + png_unknown_chunkp to = np + info_ptr->unknown_chunks_num + i; + png_unknown_chunkp from = unknowns + i; + + png_memcpy((png_charp)to->name, (png_charp)from->name, + png_sizeof(from->name)); + to->name[png_sizeof(to->name)-1] = '\0'; + to->size = from->size; + /* Note our location in the read or write sequence */ + to->location = (png_byte)(png_ptr->mode & 0xff); + + if (from->size == 0) + to->data=NULL; + else + { + to->data = (png_bytep)png_malloc_warn(png_ptr, + (png_size_t)from->size); + if (to->data == NULL) + { + png_warning(png_ptr, + "Out of memory while processing unknown chunk"); + to->size = 0; + } + else + png_memcpy(to->data, from->data, from->size); + } + } + + info_ptr->unknown_chunks = np; + info_ptr->unknown_chunks_num += num_unknowns; + info_ptr->free_me |= PNG_FREE_UNKN; +} +void PNGAPI +png_set_unknown_chunk_location(png_structp png_ptr, png_infop info_ptr, + int chunk, int location) +{ + if (png_ptr != NULL && info_ptr != NULL && chunk >= 0 && chunk < + (int)info_ptr->unknown_chunks_num) + info_ptr->unknown_chunks[chunk].location = (png_byte)location; +} +#endif + + +#ifdef PNG_MNG_FEATURES_SUPPORTED +png_uint_32 PNGAPI +png_permit_mng_features (png_structp png_ptr, png_uint_32 mng_features) +{ + png_debug(1, "in png_permit_mng_features"); + + if (png_ptr == NULL) + return (png_uint_32)0; + png_ptr->mng_features_permitted = + (png_byte)(mng_features & PNG_ALL_MNG_FEATURES); + return (png_uint_32)png_ptr->mng_features_permitted; +} +#endif + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +void PNGAPI +png_set_keep_unknown_chunks(png_structp png_ptr, int keep, png_bytep + chunk_list, int num_chunks) +{ + png_bytep new_list, p; + int i, old_num_chunks; + if (png_ptr == NULL) + return; + if (num_chunks == 0) + { + if (keep == PNG_HANDLE_CHUNK_ALWAYS || keep == PNG_HANDLE_CHUNK_IF_SAFE) + png_ptr->flags |= PNG_FLAG_KEEP_UNKNOWN_CHUNKS; + else + png_ptr->flags &= ~PNG_FLAG_KEEP_UNKNOWN_CHUNKS; + + if (keep == PNG_HANDLE_CHUNK_ALWAYS) + png_ptr->flags |= PNG_FLAG_KEEP_UNSAFE_CHUNKS; + else + png_ptr->flags &= ~PNG_FLAG_KEEP_UNSAFE_CHUNKS; + return; + } + if (chunk_list == NULL) + return; + old_num_chunks = png_ptr->num_chunk_list; + new_list=(png_bytep)png_malloc(png_ptr, + (png_size_t) + (5*(num_chunks + old_num_chunks))); + if (png_ptr->chunk_list != NULL) + { + png_memcpy(new_list, png_ptr->chunk_list, + (png_size_t)(5*old_num_chunks)); + png_free(png_ptr, png_ptr->chunk_list); + png_ptr->chunk_list=NULL; + } + png_memcpy(new_list + 5*old_num_chunks, chunk_list, + (png_size_t)(5*num_chunks)); + for (p = new_list + 5*old_num_chunks + 4, i = 0; inum_chunk_list = old_num_chunks + num_chunks; + png_ptr->chunk_list = new_list; + png_ptr->free_me |= PNG_FREE_LIST; +} +#endif + +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED +void PNGAPI +png_set_read_user_chunk_fn(png_structp png_ptr, png_voidp user_chunk_ptr, + png_user_chunk_ptr read_user_chunk_fn) +{ + png_debug(1, "in png_set_read_user_chunk_fn"); + + if (png_ptr == NULL) + return; + + png_ptr->read_user_chunk_fn = read_user_chunk_fn; + png_ptr->user_chunk_ptr = user_chunk_ptr; +} +#endif + +#ifdef PNG_INFO_IMAGE_SUPPORTED +void PNGAPI +png_set_rows(png_structp png_ptr, png_infop info_ptr, png_bytepp row_pointers) +{ + png_debug1(1, "in %s storage function", "rows"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (info_ptr->row_pointers && (info_ptr->row_pointers != row_pointers)) + png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); + info_ptr->row_pointers = row_pointers; + if (row_pointers) + info_ptr->valid |= PNG_INFO_IDAT; +} +#endif + +void PNGAPI +png_set_compression_buffer_size(png_structp png_ptr, + png_size_t size) +{ + if (png_ptr == NULL) + return; + png_free(png_ptr, png_ptr->zbuf); + png_ptr->zbuf_size = size; + png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, size); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; +} + +void PNGAPI +png_set_invalid(png_structp png_ptr, png_infop info_ptr, int mask) +{ + if (png_ptr && info_ptr) + info_ptr->valid &= ~mask; +} + + + +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +/* This function was added to libpng 1.2.6 */ +void PNGAPI +png_set_user_limits (png_structp png_ptr, png_uint_32 user_width_max, + png_uint_32 user_height_max) +{ + /* Images with dimensions larger than these limits will be + * rejected by png_set_IHDR(). To accept any PNG datastream + * regardless of dimensions, set both limits to 0x7ffffffL. + */ + if (png_ptr == NULL) + return; + png_ptr->user_width_max = user_width_max; + png_ptr->user_height_max = user_height_max; +} + +/* This function was added to libpng 1.4.0 */ +void PNGAPI +png_set_chunk_cache_max (png_structp png_ptr, + png_uint_32 user_chunk_cache_max) +{ + if (png_ptr) + png_ptr->user_chunk_cache_max = user_chunk_cache_max; +} + +/* This function was added to libpng 1.4.1 */ +void PNGAPI +png_set_chunk_malloc_max (png_structp png_ptr, + png_alloc_size_t user_chunk_malloc_max) +{ + if (png_ptr) + png_ptr->user_chunk_malloc_max = + (png_size_t)user_chunk_malloc_max; +} +#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */ + + +#ifdef PNG_BENIGN_ERRORS_SUPPORTED +void PNGAPI +png_set_benign_errors(png_structp png_ptr, int allowed) +{ + png_debug(1, "in png_set_benign_errors"); + + if (allowed) + png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN; + else + png_ptr->flags &= ~PNG_FLAG_BENIGN_ERRORS_WARN; +} +#endif /* PNG_BENIGN_ERRORS_SUPPORTED */ +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/reactos/dll/3rdparty/libpng/pngtest.c b/reactos/dll/3rdparty/libpng/pngtest.c new file mode 100644 index 00000000000..836441d6dbe --- /dev/null +++ b/reactos/dll/3rdparty/libpng/pngtest.c @@ -0,0 +1,1630 @@ + +/* pngtest.c - a simple test program to test libpng + * + * Last changed in libpng 1.4.1 [February 25, 2010] + * Copyright (c) 1998-2010 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This program reads in a PNG image, writes it out again, and then + * compares the two files. If the files are identical, this shows that + * the basic chunk handling, filtering, and (de)compression code is working + * properly. It does not currently test all of the transforms, although + * it probably should. + * + * The program will report "FAIL" in certain legitimate cases: + * 1) when the compression level or filter selection method is changed. + * 2) when the maximum IDAT size (PNG_ZBUF_SIZE in pngconf.h) is not 8192. + * 3) unknown unsafe-to-copy ancillary chunks or unknown critical chunks + * exist in the input file. + * 4) others not listed here... + * In these cases, it is best to check with another tool such as "pngcheck" + * to see what the differences between the two files are. + * + * If a filename is given on the command-line, then this file is used + * for the input, rather than the default "pngtest.png". This allows + * testing a wide variety of files easily. You can also test a number + * of files at once by typing "pngtest -m file1.png file2.png ..." + */ + +#include "png.h" +#include "pngpriv.h" + +# include +# include +# define FCLOSE(file) fclose(file) + +#ifndef PNG_STDIO_SUPPORTED + typedef FILE * png_FILE_p; +#endif + +/* Makes pngtest verbose so we can find problems (needs to be before png.h) */ +#ifndef PNG_DEBUG +# define PNG_DEBUG 0 +#endif + +#if !PNG_DEBUG +# define SINGLE_ROWBUF_ALLOC /* Makes buffer overruns easier to nail */ +#endif + +/* Turn on CPU timing +#define PNGTEST_TIMING +*/ + +#ifndef PNG_FLOATING_POINT_SUPPORTED +#undef PNGTEST_TIMING +#endif + +#ifdef PNGTEST_TIMING +static float t_start, t_stop, t_decode, t_encode, t_misc; +#include +#endif + +#ifdef PNG_TIME_RFC1123_SUPPORTED +#define PNG_tIME_STRING_LENGTH 29 +static int tIME_chunk_present = 0; +static char tIME_string[PNG_tIME_STRING_LENGTH] = "tIME chunk is not present"; +#endif + +static int verbose = 0; + +int test_one_file PNGARG((PNG_CONST char *inname, PNG_CONST char *outname)); + +#ifdef __TURBOC__ +#include +#endif + +/* Defined so I can write to a file on gui/windowing platforms */ +/* #define STDERR stderr */ +#define STDERR stdout /* For DOS */ + +/* In case a system header (e.g., on AIX) defined jmpbuf */ +#ifdef jmpbuf +# undef jmpbuf +#endif + +/* Define png_jmpbuf() in case we are using a pre-1.0.6 version of libpng */ +#ifndef png_jmpbuf +# define png_jmpbuf(png_ptr) png_ptr->jmpbuf +#endif + +/* Example of using row callbacks to make a simple progress meter */ +static int status_pass = 1; +static int status_dots_requested = 0; +static int status_dots = 1; + +void +read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass); +void +read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass) +{ + if (png_ptr == NULL || row_number > PNG_UINT_31_MAX) + return; + if (status_pass != pass) + { + fprintf(stdout, "\n Pass %d: ", pass); + status_pass = pass; + status_dots = 31; + } + status_dots--; + if (status_dots == 0) + { + fprintf(stdout, "\n "); + status_dots=30; + } + fprintf(stdout, "r"); +} + +void +write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass); +void +write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass) +{ + if (png_ptr == NULL || row_number > PNG_UINT_31_MAX || pass > 7) + return; + fprintf(stdout, "w"); +} + + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED +/* Example of using user transform callback (we don't transform anything, + * but merely examine the row filters. We set this to 256 rather than + * 5 in case illegal filter values are present.) + */ +static png_uint_32 filters_used[256]; +void +count_filters(png_structp png_ptr, png_row_infop row_info, png_bytep data); +void +count_filters(png_structp png_ptr, png_row_infop row_info, png_bytep data) +{ + if (png_ptr != NULL && row_info != NULL) + ++filters_used[*(data - 1)]; +} +#endif + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED +/* Example of using user transform callback (we don't transform anything, + * but merely count the zero samples) + */ + +static png_uint_32 zero_samples; + +void +count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data); +void +count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data) +{ + png_bytep dp = data; + if (png_ptr == NULL)return; + + /* Contents of row_info: + * png_uint_32 width width of row + * png_uint_32 rowbytes number of bytes in row + * png_byte color_type color type of pixels + * png_byte bit_depth bit depth of samples + * png_byte channels number of channels (1-4) + * png_byte pixel_depth bits per pixel (depth*channels) + */ + + /* Counts the number of zero samples (or zero pixels if color_type is 3 */ + + if (row_info->color_type == 0 || row_info->color_type == 3) + { + int pos = 0; + png_uint_32 n, nstop; + for (n = 0, nstop=row_info->width; nbit_depth == 1) + { + if (((*dp << pos++ ) & 0x80) == 0) + zero_samples++; + if (pos == 8) + { + pos = 0; + dp++; + } + } + if (row_info->bit_depth == 2) + { + if (((*dp << (pos+=2)) & 0xc0) == 0) + zero_samples++; + if (pos == 8) + { + pos = 0; + dp++; + } + } + if (row_info->bit_depth == 4) + { + if (((*dp << (pos+=4)) & 0xf0) == 0) + zero_samples++; + if (pos == 8) + { + pos = 0; + dp++; + } + } + if (row_info->bit_depth == 8) + if (*dp++ == 0) + zero_samples++; + if (row_info->bit_depth == 16) + { + if ((*dp | *(dp+1)) == 0) + zero_samples++; + dp+=2; + } + } + } + else /* Other color types */ + { + png_uint_32 n, nstop; + int channel; + int color_channels = row_info->channels; + if (row_info->color_type > 3)color_channels--; + + for (n = 0, nstop=row_info->width; nbit_depth == 8) + if (*dp++ == 0) + zero_samples++; + if (row_info->bit_depth == 16) + { + if ((*dp | *(dp+1)) == 0) + zero_samples++; + dp+=2; + } + } + if (row_info->color_type > 3) + { + dp++; + if (row_info->bit_depth == 16) + dp++; + } + } + } +} +#endif /* PNG_WRITE_USER_TRANSFORM_SUPPORTED */ + +static int wrote_question = 0; + +#ifndef PNG_STDIO_SUPPORTED +/* START of code to validate stdio-free compilation */ +/* These copies of the default read/write functions come from pngrio.c and + * pngwio.c. They allow "don't include stdio" testing of the library. + * This is the function that does the actual reading of data. If you are + * not reading from a standard C stream, you should create a replacement + * read_data function and use it at run time with png_set_read_fn(), rather + * than changing the library. + */ + +#ifndef USE_FAR_KEYWORD +static void +pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check = 0; + png_voidp io_ptr; + + /* fread() returns 0 on error, so it is OK to store this in a png_size_t + * instead of an int, which is what fread() actually returns. + */ + io_ptr = png_get_io_ptr(png_ptr); + if (io_ptr != NULL) + { + check = fread(data, 1, length, (png_FILE_p)io_ptr); + } + + if (check != length) + { + png_error(png_ptr, "Read Error!"); + } +} +#else +/* This is the model-independent version. Since the standard I/O library + can't handle far buffers in the medium and small models, we have to copy + the data. +*/ + +#define NEAR_BUF_SIZE 1024 +#define MIN(a,b) (a <= b ? a : b) + +static void +pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check; + png_byte *n_data; + png_FILE_p io_ptr; + + /* Check if data really is near. If so, use usual code. */ + n_data = (png_byte *)CVT_PTR_NOCHECK(data); + io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); + if ((png_bytep)n_data == data) + { + check = fread(n_data, 1, length, io_ptr); + } + else + { + png_byte buf[NEAR_BUF_SIZE]; + png_size_t read, remaining, err; + check = 0; + remaining = length; + do + { + read = MIN(NEAR_BUF_SIZE, remaining); + err = fread(buf, 1, 1, io_ptr); + png_memcpy(data, buf, read); /* Copy far buffer to near buffer */ + if (err != read) + break; + else + check += err; + data += read; + remaining -= read; + } + while (remaining != 0); + } + if (check != length) + png_error(png_ptr, "read Error"); +} +#endif /* USE_FAR_KEYWORD */ + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +static void +pngtest_flush(png_structp png_ptr) +{ + /* Do nothing; fflush() is said to be just a waste of energy. */ + png_ptr = png_ptr; /* Stifle compiler warning */ +} +#endif + +/* This is the function that does the actual writing of data. If you are + * not writing to a standard C stream, you should create a replacement + * write_data function and use it at run time with png_set_write_fn(), rather + * than changing the library. + */ +#ifndef USE_FAR_KEYWORD +static void +pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check; + + check = fwrite(data, 1, length, (png_FILE_p)png_ptr->io_ptr); + if (check != length) + { + png_error(png_ptr, "Write Error"); + } +} +#else +/* This is the model-independent version. Since the standard I/O library + can't handle far buffers in the medium and small models, we have to copy + the data. +*/ + +#define NEAR_BUF_SIZE 1024 +#define MIN(a,b) (a <= b ? a : b) + +static void +pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check; + png_byte *near_data; /* Needs to be "png_byte *" instead of "png_bytep" */ + png_FILE_p io_ptr; + + /* Check if data really is near. If so, use usual code. */ + near_data = (png_byte *)CVT_PTR_NOCHECK(data); + io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); + if ((png_bytep)near_data == data) + { + check = fwrite(near_data, 1, length, io_ptr); + } + else + { + png_byte buf[NEAR_BUF_SIZE]; + png_size_t written, remaining, err; + check = 0; + remaining = length; + do + { + written = MIN(NEAR_BUF_SIZE, remaining); + png_memcpy(buf, data, written); /* Copy far buffer to near buffer */ + err = fwrite(buf, 1, written, io_ptr); + if (err != written) + break; + else + check += err; + data += written; + remaining -= written; + } + while (remaining != 0); + } + if (check != length) + { + png_error(png_ptr, "Write Error"); + } +} +#endif /* USE_FAR_KEYWORD */ + +/* This function is called when there is a warning, but the library thinks + * it can continue anyway. Replacement functions don't have to do anything + * here if you don't want to. In the default configuration, png_ptr is + * not used, but it is passed in case it may be useful. + */ +static void +pngtest_warning(png_structp png_ptr, png_const_charp message) +{ + PNG_CONST char *name = "UNKNOWN (ERROR!)"; + char *test; + test = png_get_error_ptr(png_ptr); + if (test == NULL) + fprintf(STDERR, "%s: libpng warning: %s\n", name, message); + else + fprintf(STDERR, "%s: libpng warning: %s\n", test, message); +} + +/* This is the default error handling function. Note that replacements for + * this function MUST NOT RETURN, or the program will likely crash. This + * function is used by default, or if the program supplies NULL for the + * error function pointer in png_set_error_fn(). + */ +static void +pngtest_error(png_structp png_ptr, png_const_charp message) +{ + pngtest_warning(png_ptr, message); + /* We can return because png_error calls the default handler, which is + * actually OK in this case. + */ +} +#endif /* !PNG_STDIO_SUPPORTED */ +/* END of code to validate stdio-free compilation */ + +/* START of code to validate memory allocation and deallocation */ +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + +/* Allocate memory. For reasonable files, size should never exceed + * 64K. However, zlib may allocate more then 64K if you don't tell + * it not to. See zconf.h and png.h for more information. zlib does + * need to allocate exactly 64K, so whatever you call here must + * have the ability to do that. + * + * This piece of code can be compiled to validate max 64K allocations + * by setting MAXSEG_64K in zlib zconf.h *or* PNG_MAX_MALLOC_64K. + */ +typedef struct memory_information +{ + png_alloc_size_t size; + png_voidp pointer; + struct memory_information FAR *next; +} memory_information; +typedef memory_information FAR *memory_infop; + +static memory_infop pinformation = NULL; +static int current_allocation = 0; +static int maximum_allocation = 0; +static int total_allocation = 0; +static int num_allocations = 0; + +png_voidp png_debug_malloc + PNGARG((png_structp png_ptr, png_alloc_size_t size)); +void png_debug_free PNGARG((png_structp png_ptr, png_voidp ptr)); + +png_voidp +png_debug_malloc(png_structp png_ptr, png_alloc_size_t size) +{ + + /* png_malloc has already tested for NULL; png_create_struct calls + * png_debug_malloc directly, with png_ptr == NULL which is OK + */ + + if (size == 0) + return (NULL); + + /* This calls the library allocator twice, once to get the requested + buffer and once to get a new free list entry. */ + { + /* Disable malloc_fn and free_fn */ + memory_infop pinfo; + png_set_mem_fn(png_ptr, NULL, NULL, NULL); + pinfo = (memory_infop)png_malloc(png_ptr, + png_sizeof(*pinfo)); + pinfo->size = size; + current_allocation += size; + total_allocation += size; + num_allocations ++; + if (current_allocation > maximum_allocation) + maximum_allocation = current_allocation; + pinfo->pointer = png_malloc(png_ptr, size); + /* Restore malloc_fn and free_fn */ + png_set_mem_fn(png_ptr, + NULL, png_debug_malloc, png_debug_free); + if (size != 0 && pinfo->pointer == NULL) + { + current_allocation -= size; + total_allocation -= size; + png_error(png_ptr, + "out of memory in pngtest->png_debug_malloc"); + } + pinfo->next = pinformation; + pinformation = pinfo; + /* Make sure the caller isn't assuming zeroed memory. */ + png_memset(pinfo->pointer, 0xdd, pinfo->size); + if (verbose) + printf("png_malloc %lu bytes at %x\n", (unsigned long)size, + pinfo->pointer); + return (png_voidp)(pinfo->pointer); + } +} + +/* Free a pointer. It is removed from the list at the same time. */ +void +png_debug_free(png_structp png_ptr, png_voidp ptr) +{ + if (png_ptr == NULL) + fprintf(STDERR, "NULL pointer to png_debug_free.\n"); + if (ptr == 0) + { +#if 0 /* This happens all the time. */ + fprintf(STDERR, "WARNING: freeing NULL pointer\n"); +#endif + return; + } + + /* Unlink the element from the list. */ + { + memory_infop FAR *ppinfo = &pinformation; + for (;;) + { + memory_infop pinfo = *ppinfo; + if (pinfo->pointer == ptr) + { + *ppinfo = pinfo->next; + current_allocation -= pinfo->size; + if (current_allocation < 0) + fprintf(STDERR, "Duplicate free of memory\n"); + /* We must free the list element too, but first kill + the memory that is to be freed. */ + png_memset(ptr, 0x55, pinfo->size); + png_free_default(png_ptr, pinfo); + pinfo = NULL; + break; + } + if (pinfo->next == NULL) + { + fprintf(STDERR, "Pointer %x not found\n", (unsigned int)ptr); + break; + } + ppinfo = &pinfo->next; + } + } + + /* Finally free the data. */ + if (verbose) + printf("Freeing %x\n", ptr); + png_free_default(png_ptr, ptr); + ptr = NULL; +} +#endif /* PNG_USER_MEM_SUPPORTED && PNG_DEBUG */ +/* END of code to test memory allocation/deallocation */ + + +/* Demonstration of user chunk support of the sTER and vpAg chunks */ +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED + +/* (sTER is a public chunk not yet known by libpng. vpAg is a private +chunk used in ImageMagick to store "virtual page" size). */ + +static png_uint_32 user_chunk_data[4]; + + /* 0: sTER mode + 1 + * 1: vpAg width + * 2: vpAg height + * 3: vpAg units + */ + +static int read_user_chunk_callback(png_struct *png_ptr, + png_unknown_chunkp chunk) +{ + png_uint_32 + *my_user_chunk_data; + + /* Return one of the following: + * return (-n); chunk had an error + * return (0); did not recognize + * return (n); success + * + * The unknown chunk structure contains the chunk data: + * png_byte name[5]; + * png_byte *data; + * png_size_t size; + * + * Note that libpng has already taken care of the CRC handling. + */ + + if (chunk->name[0] == 115 && chunk->name[1] == 84 && /* s T */ + chunk->name[2] == 69 && chunk->name[3] == 82) /* E R */ + { + /* Found sTER chunk */ + if (chunk->size != 1) + return (-1); /* Error return */ + if (chunk->data[0] != 0 && chunk->data[0] != 1) + return (-1); /* Invalid mode */ + my_user_chunk_data=(png_uint_32 *) png_get_user_chunk_ptr(png_ptr); + my_user_chunk_data[0]=chunk->data[0]+1; + return (1); + } + + if (chunk->name[0] != 118 || chunk->name[1] != 112 || /* v p */ + chunk->name[2] != 65 || chunk->name[3] != 103) /* A g */ + return (0); /* Did not recognize */ + + /* Found ImageMagick vpAg chunk */ + + if (chunk->size != 9) + return (-1); /* Error return */ + + my_user_chunk_data=(png_uint_32 *) png_get_user_chunk_ptr(png_ptr); + + my_user_chunk_data[1]=png_get_uint_31(png_ptr, chunk->data); + my_user_chunk_data[2]=png_get_uint_31(png_ptr, chunk->data + 4); + my_user_chunk_data[3]=(png_uint_32)chunk->data[8]; + + return (1); + +} +#endif +/* END of code to demonstrate user chunk support */ + +/* Test one file */ +int +test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) +{ + static png_FILE_p fpin; + static png_FILE_p fpout; /* "static" prevents setjmp corruption */ + png_structp read_ptr; + png_infop read_info_ptr, end_info_ptr; +#ifdef PNG_WRITE_SUPPORTED + png_structp write_ptr; + png_infop write_info_ptr; + png_infop write_end_info_ptr; +#else + png_structp write_ptr = NULL; + png_infop write_info_ptr = NULL; + png_infop write_end_info_ptr = NULL; +#endif + png_bytep row_buf; + png_uint_32 y; + png_uint_32 width, height; + int num_pass, pass; + int bit_depth, color_type; +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + jmp_buf jmpbuf; +#endif +#endif + + char inbuf[256], outbuf[256]; + + row_buf = NULL; + + if ((fpin = fopen(inname, "rb")) == NULL) + { + fprintf(STDERR, "Could not find input file %s\n", inname); + return (1); + } + + if ((fpout = fopen(outname, "wb")) == NULL) + { + fprintf(STDERR, "Could not open output file %s\n", outname); + FCLOSE(fpin); + return (1); + } + + png_debug(0, "Allocating read and write structures"); +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + read_ptr = + png_create_read_struct_2(PNG_LIBPNG_VER_STRING, NULL, + NULL, NULL, NULL, + (png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free); +#else + read_ptr = + png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); +#endif +#ifndef PNG_STDIO_SUPPORTED + png_set_error_fn(read_ptr, (png_voidp)inname, pngtest_error, + pngtest_warning); +#endif + +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED + user_chunk_data[0] = 0; + user_chunk_data[1] = 0; + user_chunk_data[2] = 0; + user_chunk_data[3] = 0; + png_set_read_user_chunk_fn(read_ptr, user_chunk_data, + read_user_chunk_callback); + +#endif +#ifdef PNG_WRITE_SUPPORTED +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + write_ptr = + png_create_write_struct_2(PNG_LIBPNG_VER_STRING, NULL, + NULL, NULL, NULL, png_debug_malloc, png_debug_free); +#else + write_ptr = + png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); +#endif +#ifndef PNG_STDIO_SUPPORTED + png_set_error_fn(write_ptr, (png_voidp)inname, pngtest_error, + pngtest_warning); +#endif +#endif + png_debug(0, "Allocating read_info, write_info and end_info structures"); + read_info_ptr = png_create_info_struct(read_ptr); + end_info_ptr = png_create_info_struct(read_ptr); +#ifdef PNG_WRITE_SUPPORTED + write_info_ptr = png_create_info_struct(write_ptr); + write_end_info_ptr = png_create_info_struct(write_ptr); +#endif + +#ifdef PNG_SETJMP_SUPPORTED + png_debug(0, "Setting jmpbuf for read struct"); +#ifdef USE_FAR_KEYWORD + if (setjmp(jmpbuf)) +#else + if (setjmp(png_jmpbuf(read_ptr))) +#endif + { + fprintf(STDERR, "%s -> %s: libpng read error\n", inname, outname); + png_free(read_ptr, row_buf); + row_buf = NULL; + png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); +#ifdef PNG_WRITE_SUPPORTED + png_destroy_info_struct(write_ptr, &write_end_info_ptr); + png_destroy_write_struct(&write_ptr, &write_info_ptr); +#endif + FCLOSE(fpin); + FCLOSE(fpout); + return (1); + } +#ifdef USE_FAR_KEYWORD + png_memcpy(png_jmpbuf(read_ptr), jmpbuf, png_sizeof(jmp_buf)); +#endif + +#ifdef PNG_WRITE_SUPPORTED + png_debug(0, "Setting jmpbuf for write struct"); +#ifdef USE_FAR_KEYWORD + if (setjmp(jmpbuf)) +#else + if (setjmp(png_jmpbuf(write_ptr))) +#endif + { + fprintf(STDERR, "%s -> %s: libpng write error\n", inname, outname); + png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); + png_destroy_info_struct(write_ptr, &write_end_info_ptr); +#ifdef PNG_WRITE_SUPPORTED + png_destroy_write_struct(&write_ptr, &write_info_ptr); +#endif + FCLOSE(fpin); + FCLOSE(fpout); + return (1); + } +#ifdef USE_FAR_KEYWORD + png_memcpy(png_jmpbuf(write_ptr), jmpbuf, png_sizeof(jmp_buf)); +#endif +#endif +#endif + + png_debug(0, "Initializing input and output streams"); +#ifdef PNG_STDIO_SUPPORTED + png_init_io(read_ptr, fpin); +# ifdef PNG_WRITE_SUPPORTED + png_init_io(write_ptr, fpout); +# endif +#else + png_set_read_fn(read_ptr, (png_voidp)fpin, pngtest_read_data); +# ifdef PNG_WRITE_SUPPORTED + png_set_write_fn(write_ptr, (png_voidp)fpout, pngtest_write_data, +# ifdef PNG_WRITE_FLUSH_SUPPORTED + pngtest_flush); +# else + NULL); +# endif +# endif +#endif + if (status_dots_requested == 1) + { +#ifdef PNG_WRITE_SUPPORTED + png_set_write_status_fn(write_ptr, write_row_callback); +#endif + png_set_read_status_fn(read_ptr, read_row_callback); + } + else + { +#ifdef PNG_WRITE_SUPPORTED + png_set_write_status_fn(write_ptr, NULL); +#endif + png_set_read_status_fn(read_ptr, NULL); + } + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + { + int i; + for (i = 0; i<256; i++) + filters_used[i] = 0; + png_set_read_user_transform_fn(read_ptr, count_filters); + } +#endif +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED + zero_samples = 0; + png_set_write_user_transform_fn(write_ptr, count_zero_samples); +#endif + +#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED +# ifndef PNG_HANDLE_CHUNK_ALWAYS +# define PNG_HANDLE_CHUNK_ALWAYS 3 +# endif + png_set_keep_unknown_chunks(read_ptr, PNG_HANDLE_CHUNK_ALWAYS, + NULL, 0); +#endif +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED +# ifndef PNG_HANDLE_CHUNK_IF_SAFE +# define PNG_HANDLE_CHUNK_IF_SAFE 2 +# endif + png_set_keep_unknown_chunks(write_ptr, PNG_HANDLE_CHUNK_IF_SAFE, + NULL, 0); +#endif + + png_debug(0, "Reading info struct"); + png_read_info(read_ptr, read_info_ptr); + + png_debug(0, "Transferring info struct"); + { + int interlace_type, compression_type, filter_type; + + if (png_get_IHDR(read_ptr, read_info_ptr, &width, &height, &bit_depth, + &color_type, &interlace_type, &compression_type, &filter_type)) + { + png_set_IHDR(write_ptr, write_info_ptr, width, height, bit_depth, +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + color_type, interlace_type, compression_type, filter_type); +#else + color_type, PNG_INTERLACE_NONE, compression_type, filter_type); +#endif + } + } +#ifdef PNG_FIXED_POINT_SUPPORTED +#ifdef PNG_cHRM_SUPPORTED + { + png_fixed_point white_x, white_y, red_x, red_y, green_x, green_y, blue_x, + blue_y; + if (png_get_cHRM_fixed(read_ptr, read_info_ptr, &white_x, &white_y, + &red_x, &red_y, &green_x, &green_y, &blue_x, &blue_y)) + { + png_set_cHRM_fixed(write_ptr, write_info_ptr, white_x, white_y, red_x, + red_y, green_x, green_y, blue_x, blue_y); + } + } +#endif +#ifdef PNG_gAMA_SUPPORTED + { + png_fixed_point gamma; + + if (png_get_gAMA_fixed(read_ptr, read_info_ptr, &gamma)) + png_set_gAMA_fixed(write_ptr, write_info_ptr, gamma); + } +#endif +#else /* Use floating point versions */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +#ifdef PNG_cHRM_SUPPORTED + { + double white_x, white_y, red_x, red_y, green_x, green_y, blue_x, + blue_y; + if (png_get_cHRM(read_ptr, read_info_ptr, &white_x, &white_y, &red_x, + &red_y, &green_x, &green_y, &blue_x, &blue_y)) + { + png_set_cHRM(write_ptr, write_info_ptr, white_x, white_y, red_x, + red_y, green_x, green_y, blue_x, blue_y); + } + } +#endif +#ifdef PNG_gAMA_SUPPORTED + { + double gamma; + + if (png_get_gAMA(read_ptr, read_info_ptr, &gamma)) + png_set_gAMA(write_ptr, write_info_ptr, gamma); + } +#endif +#endif /* Floating point */ +#endif /* Fixed point */ +#ifdef PNG_iCCP_SUPPORTED + { + png_charp name; + png_charp profile; + png_uint_32 proflen; + int compression_type; + + if (png_get_iCCP(read_ptr, read_info_ptr, &name, &compression_type, + &profile, &proflen)) + { + png_set_iCCP(write_ptr, write_info_ptr, name, compression_type, + profile, proflen); + } + } +#endif +#ifdef PNG_sRGB_SUPPORTED + { + int intent; + + if (png_get_sRGB(read_ptr, read_info_ptr, &intent)) + png_set_sRGB(write_ptr, write_info_ptr, intent); + } +#endif + { + png_colorp palette; + int num_palette; + + if (png_get_PLTE(read_ptr, read_info_ptr, &palette, &num_palette)) + png_set_PLTE(write_ptr, write_info_ptr, palette, num_palette); + } +#ifdef PNG_bKGD_SUPPORTED + { + png_color_16p background; + + if (png_get_bKGD(read_ptr, read_info_ptr, &background)) + { + png_set_bKGD(write_ptr, write_info_ptr, background); + } + } +#endif +#ifdef PNG_hIST_SUPPORTED + { + png_uint_16p hist; + + if (png_get_hIST(read_ptr, read_info_ptr, &hist)) + png_set_hIST(write_ptr, write_info_ptr, hist); + } +#endif +#ifdef PNG_oFFs_SUPPORTED + { + png_int_32 offset_x, offset_y; + int unit_type; + + if (png_get_oFFs(read_ptr, read_info_ptr, &offset_x, &offset_y, + &unit_type)) + { + png_set_oFFs(write_ptr, write_info_ptr, offset_x, offset_y, unit_type); + } + } +#endif +#ifdef PNG_pCAL_SUPPORTED + { + png_charp purpose, units; + png_charpp params; + png_int_32 X0, X1; + int type, nparams; + + if (png_get_pCAL(read_ptr, read_info_ptr, &purpose, &X0, &X1, &type, + &nparams, &units, ¶ms)) + { + png_set_pCAL(write_ptr, write_info_ptr, purpose, X0, X1, type, + nparams, units, params); + } + } +#endif +#ifdef PNG_pHYs_SUPPORTED + { + png_uint_32 res_x, res_y; + int unit_type; + + if (png_get_pHYs(read_ptr, read_info_ptr, &res_x, &res_y, &unit_type)) + png_set_pHYs(write_ptr, write_info_ptr, res_x, res_y, unit_type); + } +#endif +#ifdef PNG_sBIT_SUPPORTED + { + png_color_8p sig_bit; + + if (png_get_sBIT(read_ptr, read_info_ptr, &sig_bit)) + png_set_sBIT(write_ptr, write_info_ptr, sig_bit); + } +#endif +#ifdef PNG_sCAL_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED + { + int unit; + double scal_width, scal_height; + + if (png_get_sCAL(read_ptr, read_info_ptr, &unit, &scal_width, + &scal_height)) + { + png_set_sCAL(write_ptr, write_info_ptr, unit, scal_width, scal_height); + } + } +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + { + int unit; + png_charp scal_width, scal_height; + + if (png_get_sCAL_s(read_ptr, read_info_ptr, &unit, &scal_width, + &scal_height)) + { + png_set_sCAL_s(write_ptr, write_info_ptr, unit, scal_width, + scal_height); + } + } +#endif +#endif +#endif +#ifdef PNG_TEXT_SUPPORTED + { + png_textp text_ptr; + int num_text; + + if (png_get_text(read_ptr, read_info_ptr, &text_ptr, &num_text) > 0) + { + png_debug1(0, "Handling %d iTXt/tEXt/zTXt chunks", num_text); + png_set_text(write_ptr, write_info_ptr, text_ptr, num_text); + } + } +#endif +#ifdef PNG_tIME_SUPPORTED + { + png_timep mod_time; + + if (png_get_tIME(read_ptr, read_info_ptr, &mod_time)) + { + png_set_tIME(write_ptr, write_info_ptr, mod_time); +#ifdef PNG_TIME_RFC1123_SUPPORTED + /* We have to use png_memcpy instead of "=" because the string + * pointed to by png_convert_to_rfc1123() gets free'ed before + * we use it. + */ + png_memcpy(tIME_string, + png_convert_to_rfc1123(read_ptr, mod_time), + png_sizeof(tIME_string)); + tIME_string[png_sizeof(tIME_string) - 1] = '\0'; + tIME_chunk_present++; +#endif /* PNG_TIME_RFC1123_SUPPORTED */ + } + } +#endif +#ifdef PNG_tRNS_SUPPORTED + { + png_bytep trans_alpha; + int num_trans; + png_color_16p trans_color; + + if (png_get_tRNS(read_ptr, read_info_ptr, &trans_alpha, &num_trans, + &trans_color)) + { + int sample_max = (1 << bit_depth); + /* libpng doesn't reject a tRNS chunk with out-of-range samples */ + if (!((color_type == PNG_COLOR_TYPE_GRAY && + (int)trans_color->gray > sample_max) || + (color_type == PNG_COLOR_TYPE_RGB && + ((int)trans_color->red > sample_max || + (int)trans_color->green > sample_max || + (int)trans_color->blue > sample_max)))) + png_set_tRNS(write_ptr, write_info_ptr, trans_alpha, num_trans, + trans_color); + } + } +#endif +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + { + png_unknown_chunkp unknowns; + int num_unknowns = (int)png_get_unknown_chunks(read_ptr, read_info_ptr, + &unknowns); + if (num_unknowns) + { + png_size_t i; + png_set_unknown_chunks(write_ptr, write_info_ptr, unknowns, + num_unknowns); + /* Copy the locations from the read_info_ptr. The automatically + * generated locations in write_info_ptr are wrong because we + * haven't written anything yet. + */ + for (i = 0; i < (png_size_t)num_unknowns; i++) + png_set_unknown_chunk_location(write_ptr, write_info_ptr, i, + unknowns[i].location); + } + } +#endif + +#ifdef PNG_WRITE_SUPPORTED + png_debug(0, "Writing info struct"); + +/* If we wanted, we could write info in two steps: + * png_write_info_before_PLTE(write_ptr, write_info_ptr); + */ + png_write_info(write_ptr, write_info_ptr); + +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED + if (user_chunk_data[0] != 0) + { + png_byte png_sTER[5] = {115, 84, 69, 82, '\0'}; + + unsigned char + ster_chunk_data[1]; + + if (verbose) + fprintf(STDERR, "\n stereo mode = %lu\n", + (unsigned long)(user_chunk_data[0] - 1)); + ster_chunk_data[0]=(unsigned char)(user_chunk_data[0] - 1); + png_write_chunk(write_ptr, png_sTER, ster_chunk_data, 1); + } + if (user_chunk_data[1] != 0 || user_chunk_data[2] != 0) + { + png_byte png_vpAg[5] = {118, 112, 65, 103, '\0'}; + + unsigned char + vpag_chunk_data[9]; + + if (verbose) + fprintf(STDERR, " vpAg = %lu x %lu, units = %lu\n", + (unsigned long)user_chunk_data[1], + (unsigned long)user_chunk_data[2], + (unsigned long)user_chunk_data[3]); + png_save_uint_32(vpag_chunk_data, user_chunk_data[1]); + png_save_uint_32(vpag_chunk_data + 4, user_chunk_data[2]); + vpag_chunk_data[8] = (unsigned char)(user_chunk_data[3] & 0xff); + png_write_chunk(write_ptr, png_vpAg, vpag_chunk_data, 9); + } + +#endif +#endif + +#ifdef SINGLE_ROWBUF_ALLOC + png_debug(0, "Allocating row buffer..."); + row_buf = (png_bytep)png_malloc(read_ptr, + png_get_rowbytes(read_ptr, read_info_ptr)); + png_debug1(0, "0x%08lx", (unsigned long)row_buf); +#endif /* SINGLE_ROWBUF_ALLOC */ + png_debug(0, "Writing row data"); + +#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ + defined(PNG_WRITE_INTERLACING_SUPPORTED) + num_pass = png_set_interlace_handling(read_ptr); +# ifdef PNG_WRITE_SUPPORTED + png_set_interlace_handling(write_ptr); +# endif +#else + num_pass = 1; +#endif + +#ifdef PNGTEST_TIMING + t_stop = (float)clock(); + t_misc += (t_stop - t_start); + t_start = t_stop; +#endif + for (pass = 0; pass < num_pass; pass++) + { + png_debug1(0, "Writing row data for pass %d", pass); + for (y = 0; y < height; y++) + { +#ifndef SINGLE_ROWBUF_ALLOC + png_debug2(0, "Allocating row buffer (pass %d, y = %ld)...", pass, y); + row_buf = (png_bytep)png_malloc(read_ptr, + png_get_rowbytes(read_ptr, read_info_ptr)); + png_debug2(0, "0x%08lx (%ld bytes)", (unsigned long)row_buf, + png_get_rowbytes(read_ptr, read_info_ptr)); +#endif /* !SINGLE_ROWBUF_ALLOC */ + png_read_rows(read_ptr, (png_bytepp)&row_buf, NULL, 1); + +#ifdef PNG_WRITE_SUPPORTED +#ifdef PNGTEST_TIMING + t_stop = (float)clock(); + t_decode += (t_stop - t_start); + t_start = t_stop; +#endif + png_write_rows(write_ptr, (png_bytepp)&row_buf, 1); +#ifdef PNGTEST_TIMING + t_stop = (float)clock(); + t_encode += (t_stop - t_start); + t_start = t_stop; +#endif +#endif /* PNG_WRITE_SUPPORTED */ + +#ifndef SINGLE_ROWBUF_ALLOC + png_debug2(0, "Freeing row buffer (pass %d, y = %ld)", pass, y); + png_free(read_ptr, row_buf); + row_buf = NULL; +#endif /* !SINGLE_ROWBUF_ALLOC */ + } + } + +#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED + png_free_data(read_ptr, read_info_ptr, PNG_FREE_UNKN, -1); +#endif +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + png_free_data(write_ptr, write_info_ptr, PNG_FREE_UNKN, -1); +#endif + + png_debug(0, "Reading and writing end_info data"); + + png_read_end(read_ptr, end_info_ptr); +#ifdef PNG_TEXT_SUPPORTED + { + png_textp text_ptr; + int num_text; + + if (png_get_text(read_ptr, end_info_ptr, &text_ptr, &num_text) > 0) + { + png_debug1(0, "Handling %d iTXt/tEXt/zTXt chunks", num_text); + png_set_text(write_ptr, write_end_info_ptr, text_ptr, num_text); + } + } +#endif +#ifdef PNG_tIME_SUPPORTED + { + png_timep mod_time; + + if (png_get_tIME(read_ptr, end_info_ptr, &mod_time)) + { + png_set_tIME(write_ptr, write_end_info_ptr, mod_time); +#ifdef PNG_TIME_RFC1123_SUPPORTED + /* We have to use png_memcpy instead of "=" because the string + pointed to by png_convert_to_rfc1123() gets free'ed before + we use it */ + png_memcpy(tIME_string, + png_convert_to_rfc1123(read_ptr, mod_time), + png_sizeof(tIME_string)); + tIME_string[png_sizeof(tIME_string) - 1] = '\0'; + tIME_chunk_present++; +#endif /* PNG_TIME_RFC1123_SUPPORTED */ + } + } +#endif +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + { + png_unknown_chunkp unknowns; + int num_unknowns; + num_unknowns = (int)png_get_unknown_chunks(read_ptr, end_info_ptr, + &unknowns); + if (num_unknowns) + { + png_size_t i; + png_set_unknown_chunks(write_ptr, write_end_info_ptr, unknowns, + num_unknowns); + /* Copy the locations from the read_info_ptr. The automatically + * generated locations in write_end_info_ptr are wrong because we + * haven't written the end_info yet. + */ + for (i = 0; i < (png_size_t)num_unknowns; i++) + png_set_unknown_chunk_location(write_ptr, write_end_info_ptr, i, + unknowns[i].location); + } + } +#endif +#ifdef PNG_WRITE_SUPPORTED + png_write_end(write_ptr, write_end_info_ptr); +#endif + +#ifdef PNG_EASY_ACCESS_SUPPORTED + if (verbose) + { + png_uint_32 iwidth, iheight; + iwidth = png_get_image_width(write_ptr, write_info_ptr); + iheight = png_get_image_height(write_ptr, write_info_ptr); + fprintf(STDERR, "\n Image width = %lu, height = %lu\n", + (unsigned long)iwidth, (unsigned long)iheight); + } +#endif + + png_debug(0, "Destroying data structs"); +#ifdef SINGLE_ROWBUF_ALLOC + png_debug(1, "destroying row_buf for read_ptr"); + png_free(read_ptr, row_buf); + row_buf = NULL; +#endif /* SINGLE_ROWBUF_ALLOC */ + png_debug(1, "destroying read_ptr, read_info_ptr, end_info_ptr"); + png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); +#ifdef PNG_WRITE_SUPPORTED + png_debug(1, "destroying write_end_info_ptr"); + png_destroy_info_struct(write_ptr, &write_end_info_ptr); + png_debug(1, "destroying write_ptr, write_info_ptr"); + png_destroy_write_struct(&write_ptr, &write_info_ptr); +#endif + png_debug(0, "Destruction complete."); + + FCLOSE(fpin); + FCLOSE(fpout); + + png_debug(0, "Opening files for comparison"); + if ((fpin = fopen(inname, "rb")) == NULL) + { + fprintf(STDERR, "Could not find file %s\n", inname); + return (1); + } + + if ((fpout = fopen(outname, "rb")) == NULL) + { + fprintf(STDERR, "Could not find file %s\n", outname); + FCLOSE(fpin); + return (1); + } + + for (;;) + { + png_size_t num_in, num_out; + + num_in = fread(inbuf, 1, 1, fpin); + num_out = fread(outbuf, 1, 1, fpout); + + if (num_in != num_out) + { + fprintf(STDERR, "\nFiles %s and %s are of a different size\n", + inname, outname); + if (wrote_question == 0) + { + fprintf(STDERR, + " Was %s written with the same maximum IDAT chunk size (%d bytes),", + inname, PNG_ZBUF_SIZE); + fprintf(STDERR, + "\n filtering heuristic (libpng default), compression"); + fprintf(STDERR, + " level (zlib default),\n and zlib version (%s)?\n\n", + ZLIB_VERSION); + wrote_question = 1; + } + FCLOSE(fpin); + FCLOSE(fpout); + return (0); + } + + if (!num_in) + break; + + if (png_memcmp(inbuf, outbuf, num_in)) + { + fprintf(STDERR, "\nFiles %s and %s are different\n", inname, outname); + if (wrote_question == 0) + { + fprintf(STDERR, + " Was %s written with the same maximum IDAT chunk size (%d bytes),", + inname, PNG_ZBUF_SIZE); + fprintf(STDERR, + "\n filtering heuristic (libpng default), compression"); + fprintf(STDERR, + " level (zlib default),\n and zlib version (%s)?\n\n", + ZLIB_VERSION); + wrote_question = 1; + } + FCLOSE(fpin); + FCLOSE(fpout); + return (0); + } + } + + FCLOSE(fpin); + FCLOSE(fpout); + + return (0); +} + +/* Input and output filenames */ +#ifdef RISCOS +static PNG_CONST char *inname = "pngtest/png"; +static PNG_CONST char *outname = "pngout/png"; +#else +static PNG_CONST char *inname = "pngtest.png"; +static PNG_CONST char *outname = "pngout.png"; +#endif + +int +main(int argc, char *argv[]) +{ + int multiple = 0; + int ierror = 0; + + fprintf(STDERR, "\n Testing libpng version %s\n", PNG_LIBPNG_VER_STRING); + fprintf(STDERR, " with zlib version %s\n", ZLIB_VERSION); + fprintf(STDERR, "%s", png_get_copyright(NULL)); + /* Show the version of libpng used in building the library */ + fprintf(STDERR, " library (%lu):%s", + (unsigned long)png_access_version_number(), + png_get_header_version(NULL)); + /* Show the version of libpng used in building the application */ + fprintf(STDERR, " pngtest (%lu):%s", (unsigned long)PNG_LIBPNG_VER, + PNG_HEADER_VERSION_STRING); + fprintf(STDERR, " sizeof(png_struct)=%ld, sizeof(png_info)=%ld\n", + (long)png_sizeof(png_struct), (long)png_sizeof(png_info)); + + /* Do some consistency checking on the memory allocation settings, I'm + * not sure this matters, but it is nice to know, the first of these + * tests should be impossible because of the way the macros are set + * in pngconf.h + */ +#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K) + fprintf(STDERR, " NOTE: Zlib compiled for max 64k, libpng not\n"); +#endif + /* I think the following can happen. */ +#if !defined(MAXSEG_64K) && defined(PNG_MAX_MALLOC_64K) + fprintf(STDERR, " NOTE: libpng compiled for max 64k, zlib not\n"); +#endif + + if (strcmp(png_libpng_ver, PNG_LIBPNG_VER_STRING)) + { + fprintf(STDERR, + "Warning: versions are different between png.h and png.c\n"); + fprintf(STDERR, " png.h version: %s\n", PNG_LIBPNG_VER_STRING); + fprintf(STDERR, " png.c version: %s\n\n", png_libpng_ver); + ++ierror; + } + + if (argc > 1) + { + if (strcmp(argv[1], "-m") == 0) + { + multiple = 1; + status_dots_requested = 0; + } + else if (strcmp(argv[1], "-mv") == 0 || + strcmp(argv[1], "-vm") == 0 ) + { + multiple = 1; + verbose = 1; + status_dots_requested = 1; + } + else if (strcmp(argv[1], "-v") == 0) + { + verbose = 1; + status_dots_requested = 1; + inname = argv[2]; + } + else + { + inname = argv[1]; + status_dots_requested = 0; + } + } + + if (!multiple && argc == 3 + verbose) + outname = argv[2 + verbose]; + + if ((!multiple && argc > 3 + verbose) || (multiple && argc < 2)) + { + fprintf(STDERR, + "usage: %s [infile.png] [outfile.png]\n\t%s -m {infile.png}\n", + argv[0], argv[0]); + fprintf(STDERR, + " reads/writes one PNG file (without -m) or multiple files (-m)\n"); + fprintf(STDERR, + " with -m %s is used as a temporary file\n", outname); + exit(1); + } + + if (multiple) + { + int i; +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + int allocation_now = current_allocation; +#endif + for (i=2; isize, + (unsigned int) pinfo->pointer); + pinfo = pinfo->next; + } + } +#endif + } +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + fprintf(STDERR, " Current memory allocation: %10d bytes\n", + current_allocation); + fprintf(STDERR, " Maximum memory allocation: %10d bytes\n", + maximum_allocation); + fprintf(STDERR, " Total memory allocation: %10d bytes\n", + total_allocation); + fprintf(STDERR, " Number of allocations: %10d\n", + num_allocations); +#endif + } + else + { + int i; + for (i = 0; i<3; ++i) + { + int kerror; +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + int allocation_now = current_allocation; +#endif + if (i == 1) status_dots_requested = 1; + else if (verbose == 0)status_dots_requested = 0; + if (i == 0 || verbose == 1 || ierror != 0) + fprintf(STDERR, "\n Testing %s:", inname); + kerror = test_one_file(inname, outname); + if (kerror == 0) + { + if (verbose == 1 || i == 2) + { +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + int k; +#endif +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED + fprintf(STDERR, "\n PASS (%lu zero samples)\n", + (unsigned long)zero_samples); +#else + fprintf(STDERR, " PASS\n"); +#endif +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + for (k = 0; k<256; k++) + if (filters_used[k]) + fprintf(STDERR, " Filter %d was used %lu times\n", + k, (unsigned long)filters_used[k]); +#endif +#ifdef PNG_TIME_RFC1123_SUPPORTED + if (tIME_chunk_present != 0) + fprintf(STDERR, " tIME = %s\n", tIME_string); +#endif /* PNG_TIME_RFC1123_SUPPORTED */ + } + } + else + { + if (verbose == 0 && i != 2) + fprintf(STDERR, "\n Testing %s:", inname); + fprintf(STDERR, " FAIL\n"); + ierror += kerror; + } +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + if (allocation_now != current_allocation) + fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n", + current_allocation - allocation_now); + if (current_allocation != 0) + { + memory_infop pinfo = pinformation; + + fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n", + current_allocation); + while (pinfo != NULL) + { + fprintf(STDERR, " %lu bytes at %x\n", + (unsigned long)pinfo->size, (unsigned int)pinfo->pointer); + pinfo = pinfo->next; + } + } +#endif + } +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + fprintf(STDERR, " Current memory allocation: %10d bytes\n", + current_allocation); + fprintf(STDERR, " Maximum memory allocation: %10d bytes\n", + maximum_allocation); + fprintf(STDERR, " Total memory allocation: %10d bytes\n", + total_allocation); + fprintf(STDERR, " Number of allocations: %10d\n", + num_allocations); +#endif + } + +#ifdef PNGTEST_TIMING + t_stop = (float)clock(); + t_misc += (t_stop - t_start); + t_start = t_stop; + fprintf(STDERR, " CPU time used = %.3f seconds", + (t_misc+t_decode+t_encode)/(float)CLOCKS_PER_SEC); + fprintf(STDERR, " (decoding %.3f,\n", + t_decode/(float)CLOCKS_PER_SEC); + fprintf(STDERR, " encoding %.3f ,", + t_encode/(float)CLOCKS_PER_SEC); + fprintf(STDERR, " other %.3f seconds)\n\n", + t_misc/(float)CLOCKS_PER_SEC); +#endif + + if (ierror == 0) + fprintf(STDERR, " libpng passes test\n"); + else + fprintf(STDERR, " libpng FAILS test\n"); + return (int)(ierror != 0); +} + +/* Generate a compiler error if there is an old png.h in the search path. */ +typedef version_1_4_3 your_png_h_is_not_version_1_4_3; diff --git a/reactos/dll/3rdparty/libpng/pngtrans.c b/reactos/dll/3rdparty/libpng/pngtrans.c new file mode 100644 index 00000000000..f80679a19d1 --- /dev/null +++ b/reactos/dll/3rdparty/libpng/pngtrans.c @@ -0,0 +1,677 @@ + +/* pngtrans.c - transforms the data in a row (used by both readers and writers) + * + * Last changed in libpng 1.4.2 [April 29, 2010] + * Copyright (c) 1998-2010 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#define PNG_NO_PEDANTIC_WARNINGS +#include "png.h" +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +#include "pngpriv.h" + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* Turn on BGR-to-RGB mapping */ +void PNGAPI +png_set_bgr(png_structp png_ptr) +{ + png_debug(1, "in png_set_bgr"); + + if (png_ptr == NULL) + return; + png_ptr->transformations |= PNG_BGR; +} +#endif + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* Turn on 16 bit byte swapping */ +void PNGAPI +png_set_swap(png_structp png_ptr) +{ + png_debug(1, "in png_set_swap"); + + if (png_ptr == NULL) + return; + if (png_ptr->bit_depth == 16) + png_ptr->transformations |= PNG_SWAP_BYTES; +} +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) +/* Turn on pixel packing */ +void PNGAPI +png_set_packing(png_structp png_ptr) +{ + png_debug(1, "in png_set_packing"); + + if (png_ptr == NULL) + return; + if (png_ptr->bit_depth < 8) + { + png_ptr->transformations |= PNG_PACK; + png_ptr->usr_bit_depth = 8; + } +} +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED) +/* Turn on packed pixel swapping */ +void PNGAPI +png_set_packswap(png_structp png_ptr) +{ + png_debug(1, "in png_set_packswap"); + + if (png_ptr == NULL) + return; + if (png_ptr->bit_depth < 8) + png_ptr->transformations |= PNG_PACKSWAP; +} +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) +void PNGAPI +png_set_shift(png_structp png_ptr, png_color_8p true_bits) +{ + png_debug(1, "in png_set_shift"); + + if (png_ptr == NULL) + return; + png_ptr->transformations |= PNG_SHIFT; + png_ptr->shift = *true_bits; +} +#endif + +#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ + defined(PNG_WRITE_INTERLACING_SUPPORTED) +int PNGAPI +png_set_interlace_handling(png_structp png_ptr) +{ + png_debug(1, "in png_set_interlace handling"); + + if (png_ptr && png_ptr->interlaced) + { + png_ptr->transformations |= PNG_INTERLACE; + return (7); + } + + return (1); +} +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) +/* Add a filler byte on read, or remove a filler or alpha byte on write. + * The filler type has changed in v0.95 to allow future 2-byte fillers + * for 48-bit input data, as well as to avoid problems with some compilers + * that don't like bytes as parameters. + */ +void PNGAPI +png_set_filler(png_structp png_ptr, png_uint_32 filler, int filler_loc) +{ + png_debug(1, "in png_set_filler"); + + if (png_ptr == NULL) + return; + png_ptr->transformations |= PNG_FILLER; + png_ptr->filler = (png_uint_16)filler; + if (filler_loc == PNG_FILLER_AFTER) + png_ptr->flags |= PNG_FLAG_FILLER_AFTER; + else + png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER; + + /* This should probably go in the "do_read_filler" routine. + * I attempted to do that in libpng-1.0.1a but that caused problems + * so I restored it in libpng-1.0.2a + */ + + if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + { + png_ptr->usr_channels = 4; + } + + /* Also I added this in libpng-1.0.2a (what happens when we expand + * a less-than-8-bit grayscale to GA? */ + + if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY && png_ptr->bit_depth >= 8) + { + png_ptr->usr_channels = 2; + } +} + +/* Added to libpng-1.2.7 */ +void PNGAPI +png_set_add_alpha(png_structp png_ptr, png_uint_32 filler, int filler_loc) +{ + png_debug(1, "in png_set_add_alpha"); + + if (png_ptr == NULL) + return; + png_set_filler(png_ptr, filler, filler_loc); + png_ptr->transformations |= PNG_ADD_ALPHA; +} + +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +void PNGAPI +png_set_swap_alpha(png_structp png_ptr) +{ + png_debug(1, "in png_set_swap_alpha"); + + if (png_ptr == NULL) + return; + png_ptr->transformations |= PNG_SWAP_ALPHA; +} +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +void PNGAPI +png_set_invert_alpha(png_structp png_ptr) +{ + png_debug(1, "in png_set_invert_alpha"); + + if (png_ptr == NULL) + return; + png_ptr->transformations |= PNG_INVERT_ALPHA; +} +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +void PNGAPI +png_set_invert_mono(png_structp png_ptr) +{ + png_debug(1, "in png_set_invert_mono"); + + if (png_ptr == NULL) + return; + png_ptr->transformations |= PNG_INVERT_MONO; +} + +/* Invert monochrome grayscale data */ +void /* PRIVATE */ +png_do_invert(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_invert"); + + /* This test removed from libpng version 1.0.13 and 1.2.0: + * if (row_info->bit_depth == 1 && + */ + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + png_bytep rp = row; + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + + for (i = 0; i < istop; i++) + { + *rp = (png_byte)(~(*rp)); + rp++; + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && + row_info->bit_depth == 8) + { + png_bytep rp = row; + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + + for (i = 0; i < istop; i+=2) + { + *rp = (png_byte)(~(*rp)); + rp+=2; + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && + row_info->bit_depth == 16) + { + png_bytep rp = row; + png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; + + for (i = 0; i < istop; i+=4) + { + *rp = (png_byte)(~(*rp)); + *(rp+1) = (png_byte)(~(*(rp+1))); + rp+=4; + } + } +} +#endif + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* Swaps byte order on 16 bit depth images */ +void /* PRIVATE */ +png_do_swap(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_swap"); + + if ( + row_info->bit_depth == 16) + { + png_bytep rp = row; + png_uint_32 i; + png_uint_32 istop= row_info->width * row_info->channels; + + for (i = 0; i < istop; i++, rp += 2) + { + png_byte t = *rp; + *rp = *(rp + 1); + *(rp + 1) = t; + } + } +} +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED) +static PNG_CONST png_byte onebppswaptable[256] = { + 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, + 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, + 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, + 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, + 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, + 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, + 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, + 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, + 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, + 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, + 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, + 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, + 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, + 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, + 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, + 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, + 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, + 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, + 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, + 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, + 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, + 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, + 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, + 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, + 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, + 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, + 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, + 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, + 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, + 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, + 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, + 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF +}; + +static PNG_CONST png_byte twobppswaptable[256] = { + 0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0, + 0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0, + 0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4, + 0x24, 0x64, 0xA4, 0xE4, 0x34, 0x74, 0xB4, 0xF4, + 0x08, 0x48, 0x88, 0xC8, 0x18, 0x58, 0x98, 0xD8, + 0x28, 0x68, 0xA8, 0xE8, 0x38, 0x78, 0xB8, 0xF8, + 0x0C, 0x4C, 0x8C, 0xCC, 0x1C, 0x5C, 0x9C, 0xDC, + 0x2C, 0x6C, 0xAC, 0xEC, 0x3C, 0x7C, 0xBC, 0xFC, + 0x01, 0x41, 0x81, 0xC1, 0x11, 0x51, 0x91, 0xD1, + 0x21, 0x61, 0xA1, 0xE1, 0x31, 0x71, 0xB1, 0xF1, + 0x05, 0x45, 0x85, 0xC5, 0x15, 0x55, 0x95, 0xD5, + 0x25, 0x65, 0xA5, 0xE5, 0x35, 0x75, 0xB5, 0xF5, + 0x09, 0x49, 0x89, 0xC9, 0x19, 0x59, 0x99, 0xD9, + 0x29, 0x69, 0xA9, 0xE9, 0x39, 0x79, 0xB9, 0xF9, + 0x0D, 0x4D, 0x8D, 0xCD, 0x1D, 0x5D, 0x9D, 0xDD, + 0x2D, 0x6D, 0xAD, 0xED, 0x3D, 0x7D, 0xBD, 0xFD, + 0x02, 0x42, 0x82, 0xC2, 0x12, 0x52, 0x92, 0xD2, + 0x22, 0x62, 0xA2, 0xE2, 0x32, 0x72, 0xB2, 0xF2, + 0x06, 0x46, 0x86, 0xC6, 0x16, 0x56, 0x96, 0xD6, + 0x26, 0x66, 0xA6, 0xE6, 0x36, 0x76, 0xB6, 0xF6, + 0x0A, 0x4A, 0x8A, 0xCA, 0x1A, 0x5A, 0x9A, 0xDA, + 0x2A, 0x6A, 0xAA, 0xEA, 0x3A, 0x7A, 0xBA, 0xFA, + 0x0E, 0x4E, 0x8E, 0xCE, 0x1E, 0x5E, 0x9E, 0xDE, + 0x2E, 0x6E, 0xAE, 0xEE, 0x3E, 0x7E, 0xBE, 0xFE, + 0x03, 0x43, 0x83, 0xC3, 0x13, 0x53, 0x93, 0xD3, + 0x23, 0x63, 0xA3, 0xE3, 0x33, 0x73, 0xB3, 0xF3, + 0x07, 0x47, 0x87, 0xC7, 0x17, 0x57, 0x97, 0xD7, + 0x27, 0x67, 0xA7, 0xE7, 0x37, 0x77, 0xB7, 0xF7, + 0x0B, 0x4B, 0x8B, 0xCB, 0x1B, 0x5B, 0x9B, 0xDB, + 0x2B, 0x6B, 0xAB, 0xEB, 0x3B, 0x7B, 0xBB, 0xFB, + 0x0F, 0x4F, 0x8F, 0xCF, 0x1F, 0x5F, 0x9F, 0xDF, + 0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF +}; + +static PNG_CONST png_byte fourbppswaptable[256] = { + 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, + 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0, + 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71, + 0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1, + 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72, + 0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2, + 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73, + 0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3, + 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74, + 0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4, + 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75, + 0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5, + 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76, + 0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6, + 0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77, + 0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7, + 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78, + 0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8, + 0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79, + 0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9, + 0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A, + 0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA, + 0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B, + 0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB, + 0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C, + 0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC, + 0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D, + 0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD, + 0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E, + 0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE, + 0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F, + 0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF +}; + +/* Swaps pixel packing order within bytes */ +void /* PRIVATE */ +png_do_packswap(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_packswap"); + + if ( + row_info->bit_depth < 8) + { + png_bytep rp, end, table; + + end = row + row_info->rowbytes; + + if (row_info->bit_depth == 1) + table = (png_bytep)onebppswaptable; + else if (row_info->bit_depth == 2) + table = (png_bytep)twobppswaptable; + else if (row_info->bit_depth == 4) + table = (png_bytep)fourbppswaptable; + else + return; + + for (rp = row; rp < end; rp++) + *rp = table[*rp]; + } +} +#endif /* PNG_READ_PACKSWAP_SUPPORTED or PNG_WRITE_PACKSWAP_SUPPORTED */ + +#if defined(PNG_WRITE_FILLER_SUPPORTED) || \ + defined(PNG_READ_STRIP_ALPHA_SUPPORTED) +/* Remove filler or alpha byte(s) */ +void /* PRIVATE */ +png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags) +{ + png_debug(1, "in png_do_strip_filler"); + + { + png_bytep sp=row; + png_bytep dp=row; + png_uint_32 row_width=row_info->width; + png_uint_32 i; + + if ((row_info->color_type == PNG_COLOR_TYPE_RGB || + (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA && + (flags & PNG_FLAG_STRIP_ALPHA))) && + row_info->channels == 4) + { + if (row_info->bit_depth == 8) + { + /* This converts from RGBX or RGBA to RGB */ + if (flags & PNG_FLAG_FILLER_AFTER) + { + dp+=3; sp+=4; + for (i = 1; i < row_width; i++) + { + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + sp++; + } + } + /* This converts from XRGB or ARGB to RGB */ + else + { + for (i = 0; i < row_width; i++) + { + sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + } + } + row_info->pixel_depth = 24; + row_info->rowbytes = row_width * 3; + } + else /* if (row_info->bit_depth == 16) */ + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + /* This converts from RRGGBBXX or RRGGBBAA to RRGGBB */ + sp += 8; dp += 6; + for (i = 1; i < row_width; i++) + { + /* This could be (although png_memcpy is probably slower): + png_memcpy(dp, sp, 6); + sp += 8; + dp += 6; + */ + + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + sp += 2; + } + } + else + { + /* This converts from XXRRGGBB or AARRGGBB to RRGGBB */ + for (i = 0; i < row_width; i++) + { + /* This could be (although png_memcpy is probably slower): + png_memcpy(dp, sp, 6); + sp += 8; + dp += 6; + */ + + sp+=2; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + } + } + row_info->pixel_depth = 48; + row_info->rowbytes = row_width * 6; + } + row_info->channels = 3; + } + else if ((row_info->color_type == PNG_COLOR_TYPE_GRAY || + (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && + (flags & PNG_FLAG_STRIP_ALPHA))) && + row_info->channels == 2) + { + if (row_info->bit_depth == 8) + { + /* This converts from GX or GA to G */ + if (flags & PNG_FLAG_FILLER_AFTER) + { + for (i = 0; i < row_width; i++) + { + *dp++ = *sp++; + sp++; + } + } + /* This converts from XG or AG to G */ + else + { + for (i = 0; i < row_width; i++) + { + sp++; + *dp++ = *sp++; + } + } + row_info->pixel_depth = 8; + row_info->rowbytes = row_width; + } + else /* if (row_info->bit_depth == 16) */ + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + /* This converts from GGXX or GGAA to GG */ + sp += 4; dp += 2; + for (i = 1; i < row_width; i++) + { + *dp++ = *sp++; + *dp++ = *sp++; + sp += 2; + } + } + else + { + /* This converts from XXGG or AAGG to GG */ + for (i = 0; i < row_width; i++) + { + sp += 2; + *dp++ = *sp++; + *dp++ = *sp++; + } + } + row_info->pixel_depth = 16; + row_info->rowbytes = row_width * 2; + } + row_info->channels = 1; + } + if (flags & PNG_FLAG_STRIP_ALPHA) + row_info->color_type &= ~PNG_COLOR_MASK_ALPHA; + } +} +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* Swaps red and blue bytes within a pixel */ +void /* PRIVATE */ +png_do_bgr(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_bgr"); + + if ( + (row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + png_uint_32 row_width = row_info->width; + if (row_info->bit_depth == 8) + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 3) + { + png_byte save = *rp; + *rp = *(rp + 2); + *(rp + 2) = save; + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 4) + { + png_byte save = *rp; + *rp = *(rp + 2); + *(rp + 2) = save; + } + } + } + else if (row_info->bit_depth == 16) + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 6) + { + png_byte save = *rp; + *rp = *(rp + 4); + *(rp + 4) = save; + save = *(rp + 1); + *(rp + 1) = *(rp + 5); + *(rp + 5) = save; + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 8) + { + png_byte save = *rp; + *rp = *(rp + 4); + *(rp + 4) = save; + save = *(rp + 1); + *(rp + 1) = *(rp + 5); + *(rp + 5) = save; + } + } + } + } +} +#endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */ + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +void PNGAPI +png_set_user_transform_info(png_structp png_ptr, png_voidp + user_transform_ptr, int user_transform_depth, int user_transform_channels) +{ + png_debug(1, "in png_set_user_transform_info"); + + if (png_ptr == NULL) + return; +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED + png_ptr->user_transform_ptr = user_transform_ptr; + png_ptr->user_transform_depth = (png_byte)user_transform_depth; + png_ptr->user_transform_channels = (png_byte)user_transform_channels; +#else + if (user_transform_ptr || user_transform_depth || user_transform_channels) + png_warning(png_ptr, + "This version of libpng does not support user transform info"); +#endif +} + +/* This function returns a pointer to the user_transform_ptr associated with + * the user transform functions. The application should free any memory + * associated with this pointer before png_write_destroy and png_read_destroy + * are called. + */ +png_voidp PNGAPI +png_get_user_transform_ptr(png_structp png_ptr) +{ + if (png_ptr == NULL) + return (NULL); +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED + return ((png_voidp)png_ptr->user_transform_ptr); +#else + return (NULL); +#endif +} +#endif /* PNG_READ_USER_TRANSFORM_SUPPORTED || + PNG_WRITE_USER_TRANSFORM_SUPPORTED */ +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/reactos/dll/3rdparty/libpng/pngwio.c b/reactos/dll/3rdparty/libpng/pngwio.c new file mode 100644 index 00000000000..513a71a0622 --- /dev/null +++ b/reactos/dll/3rdparty/libpng/pngwio.c @@ -0,0 +1,241 @@ + +/* pngwio.c - functions for data output + * + * Last changed in libpng 1.4.0 [January 3, 2010] + * Copyright (c) 1998-2010 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file provides a location for all output. Users who need + * special handling are expected to write functions that have the same + * arguments as these and perform similar functions, but that possibly + * use different output methods. Note that you shouldn't change these + * functions, but rather write replacement functions and then change + * them at run time with png_set_write_fn(...). + */ + +#define PNG_NO_PEDANTIC_WARNINGS +#include "png.h" +#ifdef PNG_WRITE_SUPPORTED +#include "pngpriv.h" + +/* Write the data to whatever output you are using. The default routine + * writes to a file pointer. Note that this routine sometimes gets called + * with very small lengths, so you should implement some kind of simple + * buffering if you are using unbuffered writes. This should never be asked + * to write more than 64K on a 16 bit machine. + */ + +void /* PRIVATE */ +png_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + if (png_ptr->write_data_fn != NULL ) + (*(png_ptr->write_data_fn))(png_ptr, data, length); + else + png_error(png_ptr, "Call to NULL write function"); +} + +#ifdef PNG_STDIO_SUPPORTED +/* This is the function that does the actual writing of data. If you are + * not writing to a standard C stream, you should create a replacement + * write_data function and use it at run time with png_set_write_fn(), rather + * than changing the library. + */ +#ifndef USE_FAR_KEYWORD +void PNGAPI +png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_uint_32 check; + + if (png_ptr == NULL) + return; + check = fwrite(data, 1, length, (png_FILE_p)(png_ptr->io_ptr)); + if (check != length) + png_error(png_ptr, "Write Error"); +} +#else +/* This is the model-independent version. Since the standard I/O library + * can't handle far buffers in the medium and small models, we have to copy + * the data. + */ + +#define NEAR_BUF_SIZE 1024 +#define MIN(a,b) (a <= b ? a : b) + +void PNGAPI +png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_uint_32 check; + png_byte *near_data; /* Needs to be "png_byte *" instead of "png_bytep" */ + png_FILE_p io_ptr; + + if (png_ptr == NULL) + return; + /* Check if data really is near. If so, use usual code. */ + near_data = (png_byte *)CVT_PTR_NOCHECK(data); + io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); + if ((png_bytep)near_data == data) + { + check = fwrite(near_data, 1, length, io_ptr); + } + else + { + png_byte buf[NEAR_BUF_SIZE]; + png_size_t written, remaining, err; + check = 0; + remaining = length; + do + { + written = MIN(NEAR_BUF_SIZE, remaining); + png_memcpy(buf, data, written); /* Copy far buffer to near buffer */ + err = fwrite(buf, 1, written, io_ptr); + if (err != written) + break; + + else + check += err; + + data += written; + remaining -= written; + } + while (remaining != 0); + } + if (check != length) + png_error(png_ptr, "Write Error"); +} + +#endif +#endif + +/* This function is called to output any data pending writing (normally + * to disk). After png_flush is called, there should be no data pending + * writing in any buffers. + */ +#ifdef PNG_WRITE_FLUSH_SUPPORTED +void /* PRIVATE */ +png_flush(png_structp png_ptr) +{ + if (png_ptr->output_flush_fn != NULL) + (*(png_ptr->output_flush_fn))(png_ptr); +} + +#ifdef PNG_STDIO_SUPPORTED +void PNGAPI +png_default_flush(png_structp png_ptr) +{ + png_FILE_p io_ptr; + if (png_ptr == NULL) + return; + io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr)); + fflush(io_ptr); +} +#endif +#endif + +/* This function allows the application to supply new output functions for + * libpng if standard C streams aren't being used. + * + * This function takes as its arguments: + * png_ptr - pointer to a png output data structure + * io_ptr - pointer to user supplied structure containing info about + * the output functions. May be NULL. + * write_data_fn - pointer to a new output function that takes as its + * arguments a pointer to a png_struct, a pointer to + * data to be written, and a 32-bit unsigned int that is + * the number of bytes to be written. The new write + * function should call png_error(png_ptr, "Error msg") + * to exit and output any fatal error messages. May be + * NULL, in which case libpng's default function will + * be used. + * flush_data_fn - pointer to a new flush function that takes as its + * arguments a pointer to a png_struct. After a call to + * the flush function, there should be no data in any buffers + * or pending transmission. If the output method doesn't do + * any buffering of output, a function prototype must still be + * supplied although it doesn't have to do anything. If + * PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile + * time, output_flush_fn will be ignored, although it must be + * supplied for compatibility. May be NULL, in which case + * libpng's default function will be used, if + * PNG_WRITE_FLUSH_SUPPORTED is defined. This is not + * a good idea if io_ptr does not point to a standard + * *FILE structure. + */ +void PNGAPI +png_set_write_fn(png_structp png_ptr, png_voidp io_ptr, + png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn) +{ + if (png_ptr == NULL) + return; + + png_ptr->io_ptr = io_ptr; + +#ifdef PNG_STDIO_SUPPORTED + if (write_data_fn != NULL) + png_ptr->write_data_fn = write_data_fn; + + else + png_ptr->write_data_fn = png_default_write_data; +#else + png_ptr->write_data_fn = write_data_fn; +#endif + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +#ifdef PNG_STDIO_SUPPORTED + if (output_flush_fn != NULL) + png_ptr->output_flush_fn = output_flush_fn; + + else + png_ptr->output_flush_fn = png_default_flush; +#else + png_ptr->output_flush_fn = output_flush_fn; +#endif +#endif /* PNG_WRITE_FLUSH_SUPPORTED */ + + /* It is an error to read while writing a png file */ + if (png_ptr->read_data_fn != NULL) + { + png_ptr->read_data_fn = NULL; + png_warning(png_ptr, + "Attempted to set both read_data_fn and write_data_fn in"); + png_warning(png_ptr, + "the same structure. Resetting read_data_fn to NULL"); + } +} + +#ifdef USE_FAR_KEYWORD +#ifdef _MSC_VER +void *png_far_to_near(png_structp png_ptr, png_voidp ptr, int check) +{ + void *near_ptr; + void FAR *far_ptr; + FP_OFF(near_ptr) = FP_OFF(ptr); + far_ptr = (void FAR *)near_ptr; + + if (check != 0) + if (FP_SEG(ptr) != FP_SEG(far_ptr)) + png_error(png_ptr, "segment lost in conversion"); + + return(near_ptr); +} +# else +void *png_far_to_near(png_structp png_ptr, png_voidp ptr, int check) +{ + void *near_ptr; + void FAR *far_ptr; + near_ptr = (void FAR *)ptr; + far_ptr = (void FAR *)near_ptr; + + if (check != 0) + if (far_ptr != ptr) + png_error(png_ptr, "segment lost in conversion"); + + return(near_ptr); +} +# endif +# endif +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/reactos/dll/3rdparty/libpng/pngwrite.c b/reactos/dll/3rdparty/libpng/pngwrite.c new file mode 100644 index 00000000000..0252051989c --- /dev/null +++ b/reactos/dll/3rdparty/libpng/pngwrite.c @@ -0,0 +1,1457 @@ + +/* pngwrite.c - general routines to write a PNG file + * + * Last changed in libpng 1.4.0 [January 3, 2010] + * Copyright (c) 1998-2010 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +/* Get internal access to png.h */ +#define PNG_NO_PEDANTIC_WARNINGS +#include "png.h" +#ifdef PNG_WRITE_SUPPORTED +#include "pngpriv.h" + +/* Writes all the PNG information. This is the suggested way to use the + * library. If you have a new chunk to add, make a function to write it, + * and put it in the correct location here. If you want the chunk written + * after the image data, put it in png_write_end(). I strongly encourage + * you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing + * the chunk, as that will keep the code from breaking if you want to just + * write a plain PNG file. If you have long comments, I suggest writing + * them in png_write_end(), and compressing them. + */ +void PNGAPI +png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_write_info_before_PLTE"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE)) + { + /* Write PNG signature */ + png_write_sig(png_ptr); +#ifdef PNG_MNG_FEATURES_SUPPORTED + if ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) && \ + (png_ptr->mng_features_permitted)) + { + png_warning(png_ptr, "MNG features are not allowed in a PNG datastream"); + png_ptr->mng_features_permitted = 0; + } +#endif + /* Write IHDR information. */ + png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height, + info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type, + info_ptr->filter_type, +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + info_ptr->interlace_type); +#else + 0); +#endif + /* The rest of these check to see if the valid field has the appropriate + * flag set, and if it does, writes the chunk. + */ +#ifdef PNG_WRITE_gAMA_SUPPORTED + if (info_ptr->valid & PNG_INFO_gAMA) + { +# ifdef PNG_FLOATING_POINT_SUPPORTED + png_write_gAMA(png_ptr, info_ptr->gamma); +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + png_write_gAMA_fixed(png_ptr, info_ptr->int_gamma); +# endif +#endif + } +#endif +#ifdef PNG_WRITE_sRGB_SUPPORTED + if (info_ptr->valid & PNG_INFO_sRGB) + png_write_sRGB(png_ptr, (int)info_ptr->srgb_intent); +#endif +#ifdef PNG_WRITE_iCCP_SUPPORTED + if (info_ptr->valid & PNG_INFO_iCCP) + png_write_iCCP(png_ptr, info_ptr->iccp_name, PNG_COMPRESSION_TYPE_BASE, + info_ptr->iccp_profile, (int)info_ptr->iccp_proflen); +#endif +#ifdef PNG_WRITE_sBIT_SUPPORTED + if (info_ptr->valid & PNG_INFO_sBIT) + png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type); +#endif +#ifdef PNG_WRITE_cHRM_SUPPORTED + if (info_ptr->valid & PNG_INFO_cHRM) + { +#ifdef PNG_FLOATING_POINT_SUPPORTED + png_write_cHRM(png_ptr, + info_ptr->x_white, info_ptr->y_white, + info_ptr->x_red, info_ptr->y_red, + info_ptr->x_green, info_ptr->y_green, + info_ptr->x_blue, info_ptr->y_blue); +#else +# ifdef PNG_FIXED_POINT_SUPPORTED + png_write_cHRM_fixed(png_ptr, + info_ptr->int_x_white, info_ptr->int_y_white, + info_ptr->int_x_red, info_ptr->int_y_red, + info_ptr->int_x_green, info_ptr->int_y_green, + info_ptr->int_x_blue, info_ptr->int_y_blue); +# endif +#endif + } +#endif +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + if (info_ptr->unknown_chunks_num) + { + png_unknown_chunk *up; + + png_debug(5, "writing extra chunks"); + + for (up = info_ptr->unknown_chunks; + up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; + up++) + { + int keep = png_handle_as_unknown(png_ptr, up->name); + if (keep != PNG_HANDLE_CHUNK_NEVER && + up->location && !(up->location & PNG_HAVE_PLTE) && + !(up->location & PNG_HAVE_IDAT) && + ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || + (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) + { + if (up->size == 0) + png_warning(png_ptr, "Writing zero-length unknown chunk"); + png_write_chunk(png_ptr, up->name, up->data, up->size); + } + } + } +#endif + png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE; + } +} + +void PNGAPI +png_write_info(png_structp png_ptr, png_infop info_ptr) +{ +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) + int i; +#endif + + png_debug(1, "in png_write_info"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_write_info_before_PLTE(png_ptr, info_ptr); + + if (info_ptr->valid & PNG_INFO_PLTE) + png_write_PLTE(png_ptr, info_ptr->palette, + (png_uint_32)info_ptr->num_palette); + else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + png_error(png_ptr, "Valid palette required for paletted images"); + +#ifdef PNG_WRITE_tRNS_SUPPORTED + if (info_ptr->valid & PNG_INFO_tRNS) + { +#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED + /* Invert the alpha channel (in tRNS) */ + if ((png_ptr->transformations & PNG_INVERT_ALPHA) && + info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + int j; + for (j = 0; j<(int)info_ptr->num_trans; j++) + info_ptr->trans_alpha[j] = (png_byte)(255 - info_ptr->trans_alpha[j]); + } +#endif + png_write_tRNS(png_ptr, info_ptr->trans_alpha, &(info_ptr->trans_color), + info_ptr->num_trans, info_ptr->color_type); + } +#endif +#ifdef PNG_WRITE_bKGD_SUPPORTED + if (info_ptr->valid & PNG_INFO_bKGD) + png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type); +#endif +#ifdef PNG_WRITE_hIST_SUPPORTED + if (info_ptr->valid & PNG_INFO_hIST) + png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette); +#endif +#ifdef PNG_WRITE_oFFs_SUPPORTED + if (info_ptr->valid & PNG_INFO_oFFs) + png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset, + info_ptr->offset_unit_type); +#endif +#ifdef PNG_WRITE_pCAL_SUPPORTED + if (info_ptr->valid & PNG_INFO_pCAL) + png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0, + info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams, + info_ptr->pcal_units, info_ptr->pcal_params); +#endif + +#ifdef PNG_sCAL_SUPPORTED + if (info_ptr->valid & PNG_INFO_sCAL) +#ifdef PNG_WRITE_sCAL_SUPPORTED +#if defined(PNG_FLOATING_POINT_SUPPORTED) && defined(PNG_STDIO_SUPPORTED) + png_write_sCAL(png_ptr, (int)info_ptr->scal_unit, + info_ptr->scal_pixel_width, info_ptr->scal_pixel_height); +#else /* !FLOATING_POINT */ +#ifdef PNG_FIXED_POINT_SUPPORTED + png_write_sCAL_s(png_ptr, (int)info_ptr->scal_unit, + info_ptr->scal_s_width, info_ptr->scal_s_height); +#endif /* FIXED_POINT */ +#endif /* FLOATING_POINT */ +#else /* !WRITE_sCAL */ + png_warning(png_ptr, + "png_write_sCAL not supported; sCAL chunk not written"); +#endif /* WRITE_sCAL */ +#endif /* sCAL */ + +#ifdef PNG_WRITE_pHYs_SUPPORTED + if (info_ptr->valid & PNG_INFO_pHYs) + png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit, + info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type); +#endif /* pHYs */ + +#ifdef PNG_WRITE_tIME_SUPPORTED + if (info_ptr->valid & PNG_INFO_tIME) + { + png_write_tIME(png_ptr, &(info_ptr->mod_time)); + png_ptr->mode |= PNG_WROTE_tIME; + } +#endif /* tIME */ + +#ifdef PNG_WRITE_sPLT_SUPPORTED + if (info_ptr->valid & PNG_INFO_sPLT) + for (i = 0; i < (int)info_ptr->splt_palettes_num; i++) + png_write_sPLT(png_ptr, info_ptr->splt_palettes + i); +#endif /* sPLT */ + +#ifdef PNG_WRITE_TEXT_SUPPORTED + /* Check to see if we need to write text chunks */ + for (i = 0; i < info_ptr->num_text; i++) + { + png_debug2(2, "Writing header text chunk %d, type %d", i, + info_ptr->text[i].compression); + /* An internationalized chunk? */ + if (info_ptr->text[i].compression > 0) + { +#ifdef PNG_WRITE_iTXt_SUPPORTED + /* Write international chunk */ + png_write_iTXt(png_ptr, + info_ptr->text[i].compression, + info_ptr->text[i].key, + info_ptr->text[i].lang, + info_ptr->text[i].lang_key, + info_ptr->text[i].text); +#else + png_warning(png_ptr, "Unable to write international text"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; + } + /* If we want a compressed text chunk */ + else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_zTXt) + { +#ifdef PNG_WRITE_zTXt_SUPPORTED + /* Write compressed chunk */ + png_write_zTXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, 0, + info_ptr->text[i].compression); +#else + png_warning(png_ptr, "Unable to write compressed text"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; + } + else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) + { +#ifdef PNG_WRITE_tEXt_SUPPORTED + /* Write uncompressed chunk */ + png_write_tEXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, + 0); + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; +#else + /* Can't get here */ + png_warning(png_ptr, "Unable to write uncompressed text"); +#endif + } + } +#endif /* tEXt */ + +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + if (info_ptr->unknown_chunks_num) + { + png_unknown_chunk *up; + + png_debug(5, "writing extra chunks"); + + for (up = info_ptr->unknown_chunks; + up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; + up++) + { + int keep = png_handle_as_unknown(png_ptr, up->name); + if (keep != PNG_HANDLE_CHUNK_NEVER && + up->location && (up->location & PNG_HAVE_PLTE) && + !(up->location & PNG_HAVE_IDAT) && + ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || + (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) + { + png_write_chunk(png_ptr, up->name, up->data, up->size); + } + } + } +#endif +} + +/* Writes the end of the PNG file. If you don't want to write comments or + * time information, you can pass NULL for info. If you already wrote these + * in png_write_info(), do not write them again here. If you have long + * comments, I suggest writing them here, and compressing them. + */ +void PNGAPI +png_write_end(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_write_end"); + + if (png_ptr == NULL) + return; + if (!(png_ptr->mode & PNG_HAVE_IDAT)) + png_error(png_ptr, "No IDATs written into file"); + + /* See if user wants us to write information chunks */ + if (info_ptr != NULL) + { +#ifdef PNG_WRITE_TEXT_SUPPORTED + int i; /* local index variable */ +#endif +#ifdef PNG_WRITE_tIME_SUPPORTED + /* Check to see if user has supplied a time chunk */ + if ((info_ptr->valid & PNG_INFO_tIME) && + !(png_ptr->mode & PNG_WROTE_tIME)) + png_write_tIME(png_ptr, &(info_ptr->mod_time)); +#endif +#ifdef PNG_WRITE_TEXT_SUPPORTED + /* Loop through comment chunks */ + for (i = 0; i < info_ptr->num_text; i++) + { + png_debug2(2, "Writing trailer text chunk %d, type %d", i, + info_ptr->text[i].compression); + /* An internationalized chunk? */ + if (info_ptr->text[i].compression > 0) + { +#ifdef PNG_WRITE_iTXt_SUPPORTED + /* Write international chunk */ + png_write_iTXt(png_ptr, + info_ptr->text[i].compression, + info_ptr->text[i].key, + info_ptr->text[i].lang, + info_ptr->text[i].lang_key, + info_ptr->text[i].text); +#else + png_warning(png_ptr, "Unable to write international text"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; + } + else if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt) + { +#ifdef PNG_WRITE_zTXt_SUPPORTED + /* Write compressed chunk */ + png_write_zTXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, 0, + info_ptr->text[i].compression); +#else + png_warning(png_ptr, "Unable to write compressed text"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; + } + else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) + { +#ifdef PNG_WRITE_tEXt_SUPPORTED + /* Write uncompressed chunk */ + png_write_tEXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, 0); +#else + png_warning(png_ptr, "Unable to write uncompressed text"); +#endif + + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; + } + } +#endif +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + if (info_ptr->unknown_chunks_num) + { + png_unknown_chunk *up; + + png_debug(5, "writing extra chunks"); + + for (up = info_ptr->unknown_chunks; + up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; + up++) + { + int keep = png_handle_as_unknown(png_ptr, up->name); + if (keep != PNG_HANDLE_CHUNK_NEVER && + up->location && (up->location & PNG_AFTER_IDAT) && + ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || + (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) + { + png_write_chunk(png_ptr, up->name, up->data, up->size); + } + } + } +#endif + } + + png_ptr->mode |= PNG_AFTER_IDAT; + + /* Write end of PNG file */ + png_write_IEND(png_ptr); + /* This flush, added in libpng-1.0.8, removed from libpng-1.0.9beta03, + * and restored again in libpng-1.2.30, may cause some applications that + * do not set png_ptr->output_flush_fn to crash. If your application + * experiences a problem, please try building libpng with + * PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED defined, and report the event to + * png-mng-implement at lists.sf.net . + */ +#ifdef PNG_WRITE_FLUSH_SUPPORTED +# ifdef PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED + png_flush(png_ptr); +# endif +#endif +} + +#ifdef PNG_CONVERT_tIME_SUPPORTED +/* "tm" structure is not supported on WindowsCE */ +void PNGAPI +png_convert_from_struct_tm(png_timep ptime, struct tm FAR * ttime) +{ + png_debug(1, "in png_convert_from_struct_tm"); + + ptime->year = (png_uint_16)(1900 + ttime->tm_year); + ptime->month = (png_byte)(ttime->tm_mon + 1); + ptime->day = (png_byte)ttime->tm_mday; + ptime->hour = (png_byte)ttime->tm_hour; + ptime->minute = (png_byte)ttime->tm_min; + ptime->second = (png_byte)ttime->tm_sec; +} + +void PNGAPI +png_convert_from_time_t(png_timep ptime, time_t ttime) +{ + struct tm *tbuf; + + png_debug(1, "in png_convert_from_time_t"); + + tbuf = gmtime(&ttime); + png_convert_from_struct_tm(ptime, tbuf); +} +#endif + +/* Initialize png_ptr structure, and allocate any memory needed */ +png_structp PNGAPI +png_create_write_struct(png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn) +{ +#ifdef PNG_USER_MEM_SUPPORTED + return (png_create_write_struct_2(user_png_ver, error_ptr, error_fn, + warn_fn, NULL, NULL, NULL)); +} + +/* Alternate initialize png_ptr structure, and allocate any memory needed */ +png_structp PNGAPI +png_create_write_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ + volatile int png_cleanup_needed = 0; +#ifdef PNG_SETJMP_SUPPORTED + volatile +#endif + png_structp png_ptr; +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + jmp_buf jmpbuf; +#endif +#endif + int i; + + png_debug(1, "in png_create_write_struct"); + +#ifdef PNG_USER_MEM_SUPPORTED + png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG, + (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr); +#else + png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); +#endif /* PNG_USER_MEM_SUPPORTED */ + if (png_ptr == NULL) + return (NULL); + + /* Added at libpng-1.2.6 */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED + png_ptr->user_width_max = PNG_USER_WIDTH_MAX; + png_ptr->user_height_max = PNG_USER_HEIGHT_MAX; +#endif + +#ifdef PNG_SETJMP_SUPPORTED +/* Applications that neglect to set up their own setjmp() and then + encounter a png_error() will longjmp here. Since the jmpbuf is + then meaningless we abort instead of returning. */ +#ifdef USE_FAR_KEYWORD + if (setjmp(jmpbuf)) +#else + if (setjmp(png_jmpbuf(png_ptr))) /* sets longjmp to match setjmp */ +#endif +#ifdef USE_FAR_KEYWORD + png_memcpy(png_jmpbuf(png_ptr), jmpbuf, png_sizeof(jmp_buf)); +#endif + PNG_ABORT(); +#endif + +#ifdef PNG_USER_MEM_SUPPORTED + png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn); +#endif /* PNG_USER_MEM_SUPPORTED */ + png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn); + + if (user_png_ver) + { + i = 0; + do + { + if (user_png_ver[i] != png_libpng_ver[i]) + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; + } while (png_libpng_ver[i++]); + } + + if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) + { + /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so + * we must recompile any applications that use any older library version. + * For versions after libpng 1.0, we will be compatible, so we need + * only check the first digit. + */ + if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] || + (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) || + (user_png_ver[0] == '0' && user_png_ver[2] < '9')) + { +#ifdef PNG_STDIO_SUPPORTED + char msg[80]; + if (user_png_ver) + { + png_snprintf(msg, 80, + "Application was compiled with png.h from libpng-%.20s", + user_png_ver); + png_warning(png_ptr, msg); + } + png_snprintf(msg, 80, + "Application is running with png.c from libpng-%.20s", + png_libpng_ver); + png_warning(png_ptr, msg); +#endif +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + png_ptr->flags = 0; +#endif + png_warning(png_ptr, + "Incompatible libpng version in application and library"); + png_cleanup_needed = 1; + } + } + + /* Initialize zbuf - compression buffer */ + png_ptr->zbuf_size = PNG_ZBUF_SIZE; + if (!png_cleanup_needed) + { + png_ptr->zbuf = (png_bytep)png_malloc_warn(png_ptr, + png_ptr->zbuf_size); + if (png_ptr->zbuf == NULL) + png_cleanup_needed = 1; + } + if (png_cleanup_needed) + { + /* Clean up PNG structure and deallocate any memory. */ + png_free(png_ptr, png_ptr->zbuf); + png_ptr->zbuf = NULL; +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)png_ptr, + (png_free_ptr)free_fn, (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)png_ptr); +#endif + return (NULL); + } + + png_set_write_fn(png_ptr, NULL, NULL, NULL); + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT, + 1, NULL, NULL); +#endif + + return (png_ptr); +} + + +/* Write a few rows of image data. If the image is interlaced, + * either you will have to write the 7 sub images, or, if you + * have called png_set_interlace_handling(), you will have to + * "write" the image seven times. + */ +void PNGAPI +png_write_rows(png_structp png_ptr, png_bytepp row, + png_uint_32 num_rows) +{ + png_uint_32 i; /* row counter */ + png_bytepp rp; /* row pointer */ + + png_debug(1, "in png_write_rows"); + + if (png_ptr == NULL) + return; + + /* Loop through the rows */ + for (i = 0, rp = row; i < num_rows; i++, rp++) + { + png_write_row(png_ptr, *rp); + } +} + +/* Write the image. You only need to call this function once, even + * if you are writing an interlaced image. + */ +void PNGAPI +png_write_image(png_structp png_ptr, png_bytepp image) +{ + png_uint_32 i; /* row index */ + int pass, num_pass; /* pass variables */ + png_bytepp rp; /* points to current row */ + + if (png_ptr == NULL) + return; + + png_debug(1, "in png_write_image"); + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* Initialize interlace handling. If image is not interlaced, + * this will set pass to 1 + */ + num_pass = png_set_interlace_handling(png_ptr); +#else + num_pass = 1; +#endif + /* Loop through passes */ + for (pass = 0; pass < num_pass; pass++) + { + /* Loop through image */ + for (i = 0, rp = image; i < png_ptr->height; i++, rp++) + { + png_write_row(png_ptr, *rp); + } + } +} + +/* Called by user to write a row of image data */ +void PNGAPI +png_write_row(png_structp png_ptr, png_bytep row) +{ + if (png_ptr == NULL) + return; + + png_debug2(1, "in png_write_row (row %ld, pass %d)", + png_ptr->row_number, png_ptr->pass); + + /* Initialize transformations and other stuff if first time */ + if (png_ptr->row_number == 0 && png_ptr->pass == 0) + { + /* Make sure we wrote the header info */ + if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE)) + png_error(png_ptr, + "png_write_info was never called before png_write_row"); + + /* Check for transforms that have been set but were defined out */ +#if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED) + if (png_ptr->transformations & PNG_INVERT_MONO) + png_warning(png_ptr, "PNG_WRITE_INVERT_SUPPORTED is not defined"); +#endif +#if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED) + if (png_ptr->transformations & PNG_FILLER) + png_warning(png_ptr, "PNG_WRITE_FILLER_SUPPORTED is not defined"); +#endif +#if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \ + defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + png_warning(png_ptr, + "PNG_WRITE_PACKSWAP_SUPPORTED is not defined"); +#endif +#if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED) + if (png_ptr->transformations & PNG_PACK) + png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined"); +#endif +#if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED) + if (png_ptr->transformations & PNG_SHIFT) + png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined"); +#endif +#if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED) + if (png_ptr->transformations & PNG_BGR) + png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined"); +#endif +#if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED) + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined"); +#endif + + png_write_start_row(png_ptr); + } + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* If interlaced and not interested in row, return */ + if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) + { + switch (png_ptr->pass) + { + case 0: + if (png_ptr->row_number & 0x07) + { + png_write_finish_row(png_ptr); + return; + } + break; + case 1: + if ((png_ptr->row_number & 0x07) || png_ptr->width < 5) + { + png_write_finish_row(png_ptr); + return; + } + break; + case 2: + if ((png_ptr->row_number & 0x07) != 4) + { + png_write_finish_row(png_ptr); + return; + } + break; + case 3: + if ((png_ptr->row_number & 0x03) || png_ptr->width < 3) + { + png_write_finish_row(png_ptr); + return; + } + break; + case 4: + if ((png_ptr->row_number & 0x03) != 2) + { + png_write_finish_row(png_ptr); + return; + } + break; + case 5: + if ((png_ptr->row_number & 0x01) || png_ptr->width < 2) + { + png_write_finish_row(png_ptr); + return; + } + break; + case 6: + if (!(png_ptr->row_number & 0x01)) + { + png_write_finish_row(png_ptr); + return; + } + break; + } + } +#endif + + /* Set up row info for transformations */ + png_ptr->row_info.color_type = png_ptr->color_type; + png_ptr->row_info.width = png_ptr->usr_width; + png_ptr->row_info.channels = png_ptr->usr_channels; + png_ptr->row_info.bit_depth = png_ptr->usr_bit_depth; + png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth * + png_ptr->row_info.channels); + + png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, + png_ptr->row_info.width); + + png_debug1(3, "row_info->color_type = %d", png_ptr->row_info.color_type); + png_debug1(3, "row_info->width = %lu", png_ptr->row_info.width); + png_debug1(3, "row_info->channels = %d", png_ptr->row_info.channels); + png_debug1(3, "row_info->bit_depth = %d", png_ptr->row_info.bit_depth); + png_debug1(3, "row_info->pixel_depth = %d", png_ptr->row_info.pixel_depth); + png_debug1(3, "row_info->rowbytes = %lu", png_ptr->row_info.rowbytes); + + /* Copy user's row into buffer, leaving room for filter byte. */ + png_memcpy(png_ptr->row_buf + 1, row, png_ptr->row_info.rowbytes); + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* Handle interlacing */ + if (png_ptr->interlaced && png_ptr->pass < 6 && + (png_ptr->transformations & PNG_INTERLACE)) + { + png_do_write_interlace(&(png_ptr->row_info), + png_ptr->row_buf + 1, png_ptr->pass); + /* This should always get caught above, but still ... */ + if (!(png_ptr->row_info.width)) + { + png_write_finish_row(png_ptr); + return; + } + } +#endif + + /* Handle other transformations */ + if (png_ptr->transformations) + png_do_write_transformations(png_ptr); + +#ifdef PNG_MNG_FEATURES_SUPPORTED + /* Write filter_method 64 (intrapixel differencing) only if + * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and + * 2. Libpng did not write a PNG signature (this filter_method is only + * used in PNG datastreams that are embedded in MNG datastreams) and + * 3. The application called png_permit_mng_features with a mask that + * included PNG_FLAG_MNG_FILTER_64 and + * 4. The filter_method is 64 and + * 5. The color_type is RGB or RGBA + */ + if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING)) + { + /* Intrapixel differencing */ + png_do_write_intrapixel(&(png_ptr->row_info), png_ptr->row_buf + 1); + } +#endif + + /* Find a filter if necessary, filter the row and write it out. */ + png_write_find_filter(png_ptr, &(png_ptr->row_info)); + + if (png_ptr->write_row_fn != NULL) + (*(png_ptr->write_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass); +} + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +/* Set the automatic flush interval or 0 to turn flushing off */ +void PNGAPI +png_set_flush(png_structp png_ptr, int nrows) +{ + png_debug(1, "in png_set_flush"); + + if (png_ptr == NULL) + return; + png_ptr->flush_dist = (nrows < 0 ? 0 : nrows); +} + +/* Flush the current output buffers now */ +void PNGAPI +png_write_flush(png_structp png_ptr) +{ + int wrote_IDAT; + + png_debug(1, "in png_write_flush"); + + if (png_ptr == NULL) + return; + /* We have already written out all of the data */ + if (png_ptr->row_number >= png_ptr->num_rows) + return; + + do + { + int ret; + + /* Compress the data */ + ret = deflate(&png_ptr->zstream, Z_SYNC_FLUSH); + wrote_IDAT = 0; + + /* Check for compression errors */ + if (ret != Z_OK) + { + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + else + png_error(png_ptr, "zlib error"); + } + + if (!(png_ptr->zstream.avail_out)) + { + /* Write the IDAT and reset the zlib output buffer */ + png_write_IDAT(png_ptr, png_ptr->zbuf, + png_ptr->zbuf_size); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + wrote_IDAT = 1; + } + } while(wrote_IDAT == 1); + + /* If there is any data left to be output, write it into a new IDAT */ + if (png_ptr->zbuf_size != png_ptr->zstream.avail_out) + { + /* Write the IDAT and reset the zlib output buffer */ + png_write_IDAT(png_ptr, png_ptr->zbuf, + png_ptr->zbuf_size - png_ptr->zstream.avail_out); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + } + png_ptr->flush_rows = 0; + png_flush(png_ptr); +} +#endif /* PNG_WRITE_FLUSH_SUPPORTED */ + +/* Free all memory used by the write */ +void PNGAPI +png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr) +{ + png_structp png_ptr = NULL; + png_infop info_ptr = NULL; +#ifdef PNG_USER_MEM_SUPPORTED + png_free_ptr free_fn = NULL; + png_voidp mem_ptr = NULL; +#endif + + png_debug(1, "in png_destroy_write_struct"); + + if (png_ptr_ptr != NULL) + { + png_ptr = *png_ptr_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + free_fn = png_ptr->free_fn; + mem_ptr = png_ptr->mem_ptr; +#endif + } + +#ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr != NULL) + { + free_fn = png_ptr->free_fn; + mem_ptr = png_ptr->mem_ptr; + } +#endif + + if (info_ptr_ptr != NULL) + info_ptr = *info_ptr_ptr; + + if (info_ptr != NULL) + { + if (png_ptr != NULL) + { + png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + if (png_ptr->num_chunk_list) + { + png_free(png_ptr, png_ptr->chunk_list); + png_ptr->num_chunk_list = 0; + } +#endif + } + +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)info_ptr); +#endif + *info_ptr_ptr = NULL; + } + + if (png_ptr != NULL) + { + png_write_destroy(png_ptr); +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)png_ptr); +#endif + *png_ptr_ptr = NULL; + } +} + + +/* Free any memory used in png_ptr struct (old method) */ +void /* PRIVATE */ +png_write_destroy(png_structp png_ptr) +{ +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf tmp_jmp; /* Save jump buffer */ +#endif + png_error_ptr error_fn; + png_error_ptr warning_fn; + png_voidp error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + png_free_ptr free_fn; +#endif + + png_debug(1, "in png_write_destroy"); + + /* Free any memory zlib uses */ + deflateEnd(&png_ptr->zstream); + + /* Free our memory. png_free checks NULL for us. */ + png_free(png_ptr, png_ptr->zbuf); + png_free(png_ptr, png_ptr->row_buf); +#ifdef PNG_WRITE_FILTER_SUPPORTED + png_free(png_ptr, png_ptr->prev_row); + png_free(png_ptr, png_ptr->sub_row); + png_free(png_ptr, png_ptr->up_row); + png_free(png_ptr, png_ptr->avg_row); + png_free(png_ptr, png_ptr->paeth_row); +#endif + +#ifdef PNG_TIME_RFC1123_SUPPORTED + png_free(png_ptr, png_ptr->time_buffer); +#endif + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + png_free(png_ptr, png_ptr->prev_filters); + png_free(png_ptr, png_ptr->filter_weights); + png_free(png_ptr, png_ptr->inv_filter_weights); + png_free(png_ptr, png_ptr->filter_costs); + png_free(png_ptr, png_ptr->inv_filter_costs); +#endif + +#ifdef PNG_SETJMP_SUPPORTED + /* Reset structure */ + png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof(jmp_buf)); +#endif + + error_fn = png_ptr->error_fn; + warning_fn = png_ptr->warning_fn; + error_ptr = png_ptr->error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + free_fn = png_ptr->free_fn; +#endif + + png_memset(png_ptr, 0, png_sizeof(png_struct)); + + png_ptr->error_fn = error_fn; + png_ptr->warning_fn = warning_fn; + png_ptr->error_ptr = error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + png_ptr->free_fn = free_fn; +#endif + +#ifdef PNG_SETJMP_SUPPORTED + png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof(jmp_buf)); +#endif +} + +/* Allow the application to select one or more row filters to use. */ +void PNGAPI +png_set_filter(png_structp png_ptr, int method, int filters) +{ + png_debug(1, "in png_set_filter"); + + if (png_ptr == NULL) + return; +#ifdef PNG_MNG_FEATURES_SUPPORTED + if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (method == PNG_INTRAPIXEL_DIFFERENCING)) + method = PNG_FILTER_TYPE_BASE; +#endif + if (method == PNG_FILTER_TYPE_BASE) + { + switch (filters & (PNG_ALL_FILTERS | 0x07)) + { +#ifdef PNG_WRITE_FILTER_SUPPORTED + case 5: + case 6: + case 7: png_warning(png_ptr, "Unknown row filter for method 0"); +#endif /* PNG_WRITE_FILTER_SUPPORTED */ + case PNG_FILTER_VALUE_NONE: + png_ptr->do_filter = PNG_FILTER_NONE; break; +#ifdef PNG_WRITE_FILTER_SUPPORTED + case PNG_FILTER_VALUE_SUB: + png_ptr->do_filter = PNG_FILTER_SUB; break; + case PNG_FILTER_VALUE_UP: + png_ptr->do_filter = PNG_FILTER_UP; break; + case PNG_FILTER_VALUE_AVG: + png_ptr->do_filter = PNG_FILTER_AVG; break; + case PNG_FILTER_VALUE_PAETH: + png_ptr->do_filter = PNG_FILTER_PAETH; break; + default: png_ptr->do_filter = (png_byte)filters; break; +#else + default: png_warning(png_ptr, "Unknown row filter for method 0"); +#endif /* PNG_WRITE_FILTER_SUPPORTED */ + } + + /* If we have allocated the row_buf, this means we have already started + * with the image and we should have allocated all of the filter buffers + * that have been selected. If prev_row isn't already allocated, then + * it is too late to start using the filters that need it, since we + * will be missing the data in the previous row. If an application + * wants to start and stop using particular filters during compression, + * it should start out with all of the filters, and then add and + * remove them after the start of compression. + */ + if (png_ptr->row_buf != NULL) + { +#ifdef PNG_WRITE_FILTER_SUPPORTED + if ((png_ptr->do_filter & PNG_FILTER_SUB) && png_ptr->sub_row == NULL) + { + png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB; + } + + if ((png_ptr->do_filter & PNG_FILTER_UP) && png_ptr->up_row == NULL) + { + if (png_ptr->prev_row == NULL) + { + png_warning(png_ptr, "Can't add Up filter after starting"); + png_ptr->do_filter &= ~PNG_FILTER_UP; + } + else + { + png_ptr->up_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->up_row[0] = PNG_FILTER_VALUE_UP; + } + } + + if ((png_ptr->do_filter & PNG_FILTER_AVG) && png_ptr->avg_row == NULL) + { + if (png_ptr->prev_row == NULL) + { + png_warning(png_ptr, "Can't add Average filter after starting"); + png_ptr->do_filter &= ~PNG_FILTER_AVG; + } + else + { + png_ptr->avg_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG; + } + } + + if ((png_ptr->do_filter & PNG_FILTER_PAETH) && + png_ptr->paeth_row == NULL) + { + if (png_ptr->prev_row == NULL) + { + png_warning(png_ptr, "Can't add Paeth filter after starting"); + png_ptr->do_filter &= (png_byte)(~PNG_FILTER_PAETH); + } + else + { + png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH; + } + } + + if (png_ptr->do_filter == PNG_NO_FILTERS) +#endif /* PNG_WRITE_FILTER_SUPPORTED */ + png_ptr->do_filter = PNG_FILTER_NONE; + } + } + else + png_error(png_ptr, "Unknown custom filter method"); +} + +/* This allows us to influence the way in which libpng chooses the "best" + * filter for the current scanline. While the "minimum-sum-of-absolute- + * differences metric is relatively fast and effective, there is some + * question as to whether it can be improved upon by trying to keep the + * filtered data going to zlib more consistent, hopefully resulting in + * better compression. + */ +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* GRR 970116 */ +void PNGAPI +png_set_filter_heuristics(png_structp png_ptr, int heuristic_method, + int num_weights, png_doublep filter_weights, + png_doublep filter_costs) +{ + int i; + + png_debug(1, "in png_set_filter_heuristics"); + + if (png_ptr == NULL) + return; + if (heuristic_method >= PNG_FILTER_HEURISTIC_LAST) + { + png_warning(png_ptr, "Unknown filter heuristic method"); + return; + } + + if (heuristic_method == PNG_FILTER_HEURISTIC_DEFAULT) + { + heuristic_method = PNG_FILTER_HEURISTIC_UNWEIGHTED; + } + + if (num_weights < 0 || filter_weights == NULL || + heuristic_method == PNG_FILTER_HEURISTIC_UNWEIGHTED) + { + num_weights = 0; + } + + png_ptr->num_prev_filters = (png_byte)num_weights; + png_ptr->heuristic_method = (png_byte)heuristic_method; + + if (num_weights > 0) + { + if (png_ptr->prev_filters == NULL) + { + png_ptr->prev_filters = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_byte) * num_weights)); + + /* To make sure that the weighting starts out fairly */ + for (i = 0; i < num_weights; i++) + { + png_ptr->prev_filters[i] = 255; + } + } + + if (png_ptr->filter_weights == NULL) + { + png_ptr->filter_weights = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_uint_16) * num_weights)); + + png_ptr->inv_filter_weights = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_uint_16) * num_weights)); + for (i = 0; i < num_weights; i++) + { + png_ptr->inv_filter_weights[i] = + png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; + } + } + + for (i = 0; i < num_weights; i++) + { + if (filter_weights[i] < 0.0) + { + png_ptr->inv_filter_weights[i] = + png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; + } + else + { + png_ptr->inv_filter_weights[i] = + (png_uint_16)((double)PNG_WEIGHT_FACTOR*filter_weights[i]+0.5); + png_ptr->filter_weights[i] = + (png_uint_16)((double)PNG_WEIGHT_FACTOR/filter_weights[i]+0.5); + } + } + } + + /* If, in the future, there are other filter methods, this would + * need to be based on png_ptr->filter. + */ + if (png_ptr->filter_costs == NULL) + { + png_ptr->filter_costs = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST)); + + png_ptr->inv_filter_costs = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST)); + + for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) + { + png_ptr->inv_filter_costs[i] = + png_ptr->filter_costs[i] = PNG_COST_FACTOR; + } + } + + /* Here is where we set the relative costs of the different filters. We + * should take the desired compression level into account when setting + * the costs, so that Paeth, for instance, has a high relative cost at low + * compression levels, while it has a lower relative cost at higher + * compression settings. The filter types are in order of increasing + * relative cost, so it would be possible to do this with an algorithm. + */ + for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) + { + if (filter_costs == NULL || filter_costs[i] < 0.0) + { + png_ptr->inv_filter_costs[i] = + png_ptr->filter_costs[i] = PNG_COST_FACTOR; + } + else if (filter_costs[i] >= 1.0) + { + png_ptr->inv_filter_costs[i] = + (png_uint_16)((double)PNG_COST_FACTOR / filter_costs[i] + 0.5); + png_ptr->filter_costs[i] = + (png_uint_16)((double)PNG_COST_FACTOR * filter_costs[i] + 0.5); + } + } +} +#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ + +void PNGAPI +png_set_compression_level(png_structp png_ptr, int level) +{ + png_debug(1, "in png_set_compression_level"); + + if (png_ptr == NULL) + return; + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_LEVEL; + png_ptr->zlib_level = level; +} + +void PNGAPI +png_set_compression_mem_level(png_structp png_ptr, int mem_level) +{ + png_debug(1, "in png_set_compression_mem_level"); + + if (png_ptr == NULL) + return; + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL; + png_ptr->zlib_mem_level = mem_level; +} + +void PNGAPI +png_set_compression_strategy(png_structp png_ptr, int strategy) +{ + png_debug(1, "in png_set_compression_strategy"); + + if (png_ptr == NULL) + return; + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY; + png_ptr->zlib_strategy = strategy; +} + +void PNGAPI +png_set_compression_window_bits(png_structp png_ptr, int window_bits) +{ + if (png_ptr == NULL) + return; + if (window_bits > 15) + png_warning(png_ptr, "Only compression windows <= 32k supported by PNG"); + else if (window_bits < 8) + png_warning(png_ptr, "Only compression windows >= 256 supported by PNG"); +#ifndef WBITS_8_OK + /* Avoid libpng bug with 256-byte windows */ + if (window_bits == 8) + { + png_warning(png_ptr, "Compression window is being reset to 512"); + window_bits = 9; + } +#endif + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS; + png_ptr->zlib_window_bits = window_bits; +} + +void PNGAPI +png_set_compression_method(png_structp png_ptr, int method) +{ + png_debug(1, "in png_set_compression_method"); + + if (png_ptr == NULL) + return; + if (method != 8) + png_warning(png_ptr, "Only compression method 8 is supported by PNG"); + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_METHOD; + png_ptr->zlib_method = method; +} + +void PNGAPI +png_set_write_status_fn(png_structp png_ptr, png_write_status_ptr write_row_fn) +{ + if (png_ptr == NULL) + return; + png_ptr->write_row_fn = write_row_fn; +} + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED +void PNGAPI +png_set_write_user_transform_fn(png_structp png_ptr, png_user_transform_ptr + write_user_transform_fn) +{ + png_debug(1, "in png_set_write_user_transform_fn"); + + if (png_ptr == NULL) + return; + png_ptr->transformations |= PNG_USER_TRANSFORM; + png_ptr->write_user_transform_fn = write_user_transform_fn; +} +#endif + + +#ifdef PNG_INFO_IMAGE_SUPPORTED +void PNGAPI +png_write_png(png_structp png_ptr, png_infop info_ptr, + int transforms, voidp params) +{ + if (png_ptr == NULL || info_ptr == NULL) + return; + + /* Write the file header information. */ + png_write_info(png_ptr, info_ptr); + + /* ------ these transformations don't touch the info structure ------- */ + +#ifdef PNG_WRITE_INVERT_SUPPORTED + /* Invert monochrome pixels */ + if (transforms & PNG_TRANSFORM_INVERT_MONO) + png_set_invert_mono(png_ptr); +#endif + +#ifdef PNG_WRITE_SHIFT_SUPPORTED + /* Shift the pixels up to a legal bit depth and fill in + * as appropriate to correctly scale the image. + */ + if ((transforms & PNG_TRANSFORM_SHIFT) + && (info_ptr->valid & PNG_INFO_sBIT)) + png_set_shift(png_ptr, &info_ptr->sig_bit); +#endif + +#ifdef PNG_WRITE_PACK_SUPPORTED + /* Pack pixels into bytes */ + if (transforms & PNG_TRANSFORM_PACKING) + png_set_packing(png_ptr); +#endif + +#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED + /* Swap location of alpha bytes from ARGB to RGBA */ + if (transforms & PNG_TRANSFORM_SWAP_ALPHA) + png_set_swap_alpha(png_ptr); +#endif + +#ifdef PNG_WRITE_FILLER_SUPPORTED + /* Pack XRGB/RGBX/ARGB/RGBA into * RGB (4 channels -> 3 channels) */ + if (transforms & PNG_TRANSFORM_STRIP_FILLER_AFTER) + png_set_filler(png_ptr, 0, PNG_FILLER_AFTER); + else if (transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE) + png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); +#endif + +#ifdef PNG_WRITE_BGR_SUPPORTED + /* Flip BGR pixels to RGB */ + if (transforms & PNG_TRANSFORM_BGR) + png_set_bgr(png_ptr); +#endif + +#ifdef PNG_WRITE_SWAP_SUPPORTED + /* Swap bytes of 16-bit files to most significant byte first */ + if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) + png_set_swap(png_ptr); +#endif + +#ifdef PNG_WRITE_PACKSWAP_SUPPORTED + /* Swap bits of 1, 2, 4 bit packed pixel formats */ + if (transforms & PNG_TRANSFORM_PACKSWAP) + png_set_packswap(png_ptr); +#endif + +#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED + /* Invert the alpha channel from opacity to transparency */ + if (transforms & PNG_TRANSFORM_INVERT_ALPHA) + png_set_invert_alpha(png_ptr); +#endif + + /* ----------------------- end of transformations ------------------- */ + + /* Write the bits */ + if (info_ptr->valid & PNG_INFO_IDAT) + png_write_image(png_ptr, info_ptr->row_pointers); + + /* It is REQUIRED to call this to finish writing the rest of the file */ + png_write_end(png_ptr, info_ptr); + + transforms = transforms; /* Quiet compiler warnings */ + params = params; +} +#endif +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/reactos/dll/3rdparty/libpng/pngwtran.c b/reactos/dll/3rdparty/libpng/pngwtran.c new file mode 100644 index 00000000000..070caa544de --- /dev/null +++ b/reactos/dll/3rdparty/libpng/pngwtran.c @@ -0,0 +1,566 @@ + +/* pngwtran.c - transforms the data in a row for PNG writers + * + * Last changed in libpng 1.4.1 [February 25, 2010] + * Copyright (c) 1998-2010 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#define PNG_NO_PEDANTIC_WARNINGS +#include "png.h" +#ifdef PNG_WRITE_SUPPORTED +#include "pngpriv.h" + +/* Transform the data according to the user's wishes. The order of + * transformations is significant. + */ +void /* PRIVATE */ +png_do_write_transformations(png_structp png_ptr) +{ + png_debug(1, "in png_do_write_transformations"); + + if (png_ptr == NULL) + return; + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED + if (png_ptr->transformations & PNG_USER_TRANSFORM) + if (png_ptr->write_user_transform_fn != NULL) + (*(png_ptr->write_user_transform_fn)) /* User write transform + function */ + (png_ptr, /* png_ptr */ + &(png_ptr->row_info), /* row_info: */ + /* png_uint_32 width; width of row */ + /* png_uint_32 rowbytes; number of bytes in row */ + /* png_byte color_type; color type of pixels */ + /* png_byte bit_depth; bit depth of samples */ + /* png_byte channels; number of channels (1-4) */ + /* png_byte pixel_depth; bits per pixel (depth*channels) */ + png_ptr->row_buf + 1); /* start of pixel data for row */ +#endif +#ifdef PNG_WRITE_FILLER_SUPPORTED + if (png_ptr->transformations & PNG_FILLER) + png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, + png_ptr->flags); +#endif +#ifdef PNG_WRITE_PACKSWAP_SUPPORTED + if (png_ptr->transformations & PNG_PACKSWAP) + png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif +#ifdef PNG_WRITE_PACK_SUPPORTED + if (png_ptr->transformations & PNG_PACK) + png_do_pack(&(png_ptr->row_info), png_ptr->row_buf + 1, + (png_uint_32)png_ptr->bit_depth); +#endif +#ifdef PNG_WRITE_SWAP_SUPPORTED + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif +#ifdef PNG_WRITE_SHIFT_SUPPORTED + if (png_ptr->transformations & PNG_SHIFT) + png_do_shift(&(png_ptr->row_info), png_ptr->row_buf + 1, + &(png_ptr->shift)); +#endif +#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED + if (png_ptr->transformations & PNG_SWAP_ALPHA) + png_do_write_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif +#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED + if (png_ptr->transformations & PNG_INVERT_ALPHA) + png_do_write_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif +#ifdef PNG_WRITE_BGR_SUPPORTED + if (png_ptr->transformations & PNG_BGR) + png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif +#ifdef PNG_WRITE_INVERT_SUPPORTED + if (png_ptr->transformations & PNG_INVERT_MONO) + png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif +} + +#ifdef PNG_WRITE_PACK_SUPPORTED +/* Pack pixels into bytes. Pass the true bit depth in bit_depth. The + * row_info bit depth should be 8 (one pixel per byte). The channels + * should be 1 (this only happens on grayscale and paletted images). + */ +void /* PRIVATE */ +png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth) +{ + png_debug(1, "in png_do_pack"); + + if (row_info->bit_depth == 8 && + row_info->channels == 1) + { + switch ((int)bit_depth) + { + case 1: + { + png_bytep sp, dp; + int mask, v; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + sp = row; + dp = row; + mask = 0x80; + v = 0; + + for (i = 0; i < row_width; i++) + { + if (*sp != 0) + v |= mask; + sp++; + if (mask > 1) + mask >>= 1; + else + { + mask = 0x80; + *dp = (png_byte)v; + dp++; + v = 0; + } + } + if (mask != 0x80) + *dp = (png_byte)v; + break; + } + case 2: + { + png_bytep sp, dp; + int shift, v; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + sp = row; + dp = row; + shift = 6; + v = 0; + for (i = 0; i < row_width; i++) + { + png_byte value; + + value = (png_byte)(*sp & 0x03); + v |= (value << shift); + if (shift == 0) + { + shift = 6; + *dp = (png_byte)v; + dp++; + v = 0; + } + else + shift -= 2; + sp++; + } + if (shift != 6) + *dp = (png_byte)v; + break; + } + case 4: + { + png_bytep sp, dp; + int shift, v; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + sp = row; + dp = row; + shift = 4; + v = 0; + for (i = 0; i < row_width; i++) + { + png_byte value; + + value = (png_byte)(*sp & 0x0f); + v |= (value << shift); + + if (shift == 0) + { + shift = 4; + *dp = (png_byte)v; + dp++; + v = 0; + } + else + shift -= 4; + + sp++; + } + if (shift != 4) + *dp = (png_byte)v; + break; + } + } + row_info->bit_depth = (png_byte)bit_depth; + row_info->pixel_depth = (png_byte)(bit_depth * row_info->channels); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, + row_info->width); + } +} +#endif + +#ifdef PNG_WRITE_SHIFT_SUPPORTED +/* Shift pixel values to take advantage of whole range. Pass the + * true number of bits in bit_depth. The row should be packed + * according to row_info->bit_depth. Thus, if you had a row of + * bit depth 4, but the pixels only had values from 0 to 7, you + * would pass 3 as bit_depth, and this routine would translate the + * data to 0 to 15. + */ +void /* PRIVATE */ +png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth) +{ + png_debug(1, "in png_do_shift"); + + if ( + row_info->color_type != PNG_COLOR_TYPE_PALETTE) + { + int shift_start[4], shift_dec[4]; + int channels = 0; + + if (row_info->color_type & PNG_COLOR_MASK_COLOR) + { + shift_start[channels] = row_info->bit_depth - bit_depth->red; + shift_dec[channels] = bit_depth->red; + channels++; + shift_start[channels] = row_info->bit_depth - bit_depth->green; + shift_dec[channels] = bit_depth->green; + channels++; + shift_start[channels] = row_info->bit_depth - bit_depth->blue; + shift_dec[channels] = bit_depth->blue; + channels++; + } + else + { + shift_start[channels] = row_info->bit_depth - bit_depth->gray; + shift_dec[channels] = bit_depth->gray; + channels++; + } + if (row_info->color_type & PNG_COLOR_MASK_ALPHA) + { + shift_start[channels] = row_info->bit_depth - bit_depth->alpha; + shift_dec[channels] = bit_depth->alpha; + channels++; + } + + /* With low row depths, could only be grayscale, so one channel */ + if (row_info->bit_depth < 8) + { + png_bytep bp = row; + png_uint_32 i; + png_byte mask; + png_uint_32 row_bytes = row_info->rowbytes; + + if (bit_depth->gray == 1 && row_info->bit_depth == 2) + mask = 0x55; + else if (row_info->bit_depth == 4 && bit_depth->gray == 3) + mask = 0x11; + else + mask = 0xff; + + for (i = 0; i < row_bytes; i++, bp++) + { + png_uint_16 v; + int j; + + v = *bp; + *bp = 0; + for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0]) + { + if (j > 0) + *bp |= (png_byte)((v << j) & 0xff); + else + *bp |= (png_byte)((v >> (-j)) & mask); + } + } + } + else if (row_info->bit_depth == 8) + { + png_bytep bp = row; + png_uint_32 i; + png_uint_32 istop = channels * row_info->width; + + for (i = 0; i < istop; i++, bp++) + { + + png_uint_16 v; + int j; + int c = (int)(i%channels); + + v = *bp; + *bp = 0; + for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c]) + { + if (j > 0) + *bp |= (png_byte)((v << j) & 0xff); + else + *bp |= (png_byte)((v >> (-j)) & 0xff); + } + } + } + else + { + png_bytep bp; + png_uint_32 i; + png_uint_32 istop = channels * row_info->width; + + for (bp = row, i = 0; i < istop; i++) + { + int c = (int)(i%channels); + png_uint_16 value, v; + int j; + + v = (png_uint_16)(((png_uint_16)(*bp) << 8) + *(bp + 1)); + value = 0; + for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c]) + { + if (j > 0) + value |= (png_uint_16)((v << j) & (png_uint_16)0xffff); + else + value |= (png_uint_16)((v >> (-j)) & (png_uint_16)0xffff); + } + *bp++ = (png_byte)(value >> 8); + *bp++ = (png_byte)(value & 0xff); + } + } + } +} +#endif + +#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED +void /* PRIVATE */ +png_do_write_swap_alpha(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_write_swap_alpha"); + + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + /* This converts from ARGB to RGBA */ + if (row_info->bit_depth == 8) + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save; + } + } + /* This converts from AARRGGBB to RRGGBBAA */ + else + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save[2]; + save[0] = *(sp++); + save[1] = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save[0]; + *(dp++) = save[1]; + } + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + /* This converts from AG to GA */ + if (row_info->bit_depth == 8) + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save; + } + } + /* This converts from AAGG to GGAA */ + else + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save[2]; + save[0] = *(sp++); + save[1] = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save[0]; + *(dp++) = save[1]; + } + } + } + } +} +#endif + +#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED +void /* PRIVATE */ +png_do_write_invert_alpha(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_write_invert_alpha"); + + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + /* This inverts the alpha channel in RGBA */ + if (row_info->bit_depth == 8) + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + for (i = 0, sp = dp = row; i < row_width; i++) + { + /* Does nothing + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + */ + sp+=3; dp = sp; + *(dp++) = (png_byte)(255 - *(sp++)); + } + } + /* This inverts the alpha channel in RRGGBBAA */ + else + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + /* Does nothing + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + */ + sp+=6; dp = sp; + *(dp++) = (png_byte)(255 - *(sp++)); + *(dp++) = (png_byte)(255 - *(sp++)); + } + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + /* This inverts the alpha channel in GA */ + if (row_info->bit_depth == 8) + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + *(dp++) = *(sp++); + *(dp++) = (png_byte)(255 - *(sp++)); + } + } + /* This inverts the alpha channel in GGAA */ + else + { + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + /* Does nothing + *(dp++) = *(sp++); + *(dp++) = *(sp++); + */ + sp+=2; dp = sp; + *(dp++) = (png_byte)(255 - *(sp++)); + *(dp++) = (png_byte)(255 - *(sp++)); + } + } + } + } +} +#endif + +#ifdef PNG_MNG_FEATURES_SUPPORTED +/* Undoes intrapixel differencing */ +void /* PRIVATE */ +png_do_write_intrapixel(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_write_intrapixel"); + + if ( + (row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + int bytes_per_pixel; + png_uint_32 row_width = row_info->width; + if (row_info->bit_depth == 8) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 3; + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 4; + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + *(rp) = (png_byte)((*rp - *(rp+1))&0xff); + *(rp+2) = (png_byte)((*(rp+2) - *(rp+1))&0xff); + } + } + else if (row_info->bit_depth == 16) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 6; + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 8; + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + png_uint_32 s0 = (*(rp ) << 8) | *(rp+1); + png_uint_32 s1 = (*(rp+2) << 8) | *(rp+3); + png_uint_32 s2 = (*(rp+4) << 8) | *(rp+5); + png_uint_32 red = (png_uint_32)((s0 - s1) & 0xffffL); + png_uint_32 blue = (png_uint_32)((s2 - s1) & 0xffffL); + *(rp ) = (png_byte)((red >> 8) & 0xff); + *(rp+1) = (png_byte)(red & 0xff); + *(rp+4) = (png_byte)((blue >> 8) & 0xff); + *(rp+5) = (png_byte)(blue & 0xff); + } + } + } +} +#endif /* PNG_MNG_FEATURES_SUPPORTED */ +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/reactos/dll/3rdparty/libpng/pngwutil.c b/reactos/dll/3rdparty/libpng/pngwutil.c new file mode 100644 index 00000000000..19feb1d98c2 --- /dev/null +++ b/reactos/dll/3rdparty/libpng/pngwutil.c @@ -0,0 +1,2786 @@ + +/* pngwutil.c - utilities to write a PNG file + * + * Last changed in libpng 1.4.1 [February 25, 2010] + * Copyright (c) 1998-2010 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#define PNG_NO_PEDANTIC_WARNINGS +#include "png.h" +#ifdef PNG_WRITE_SUPPORTED +#include "pngpriv.h" + +/* Place a 32-bit number into a buffer in PNG byte order. We work + * with unsigned numbers for convenience, although one supported + * ancillary chunk uses signed (two's complement) numbers. + */ +void PNGAPI +png_save_uint_32(png_bytep buf, png_uint_32 i) +{ + buf[0] = (png_byte)((i >> 24) & 0xff); + buf[1] = (png_byte)((i >> 16) & 0xff); + buf[2] = (png_byte)((i >> 8) & 0xff); + buf[3] = (png_byte)(i & 0xff); +} + +#ifdef PNG_SAVE_INT_32_SUPPORTED +/* The png_save_int_32 function assumes integers are stored in two's + * complement format. If this isn't the case, then this routine needs to + * be modified to write data in two's complement format. + */ +void PNGAPI +png_save_int_32(png_bytep buf, png_int_32 i) +{ + buf[0] = (png_byte)((i >> 24) & 0xff); + buf[1] = (png_byte)((i >> 16) & 0xff); + buf[2] = (png_byte)((i >> 8) & 0xff); + buf[3] = (png_byte)(i & 0xff); +} +#endif + +/* Place a 16-bit number into a buffer in PNG byte order. + * The parameter is declared unsigned int, not png_uint_16, + * just to avoid potential problems on pre-ANSI C compilers. + */ +void PNGAPI +png_save_uint_16(png_bytep buf, unsigned int i) +{ + buf[0] = (png_byte)((i >> 8) & 0xff); + buf[1] = (png_byte)(i & 0xff); +} + +/* Simple function to write the signature. If we have already written + * the magic bytes of the signature, or more likely, the PNG stream is + * being embedded into another stream and doesn't need its own signature, + * we should call png_set_sig_bytes() to tell libpng how many of the + * bytes have already been written. + */ +void PNGAPI +png_write_sig(png_structp png_ptr) +{ + png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; + +#ifdef PNG_IO_STATE_SUPPORTED + /* Inform the I/O callback that the signature is being written */ + png_ptr->io_state = PNG_IO_WRITING | PNG_IO_SIGNATURE; +#endif + + /* Write the rest of the 8 byte signature */ + png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes], + (png_size_t)(8 - png_ptr->sig_bytes)); + if (png_ptr->sig_bytes < 3) + png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; +} + +/* Write a PNG chunk all at once. The type is an array of ASCII characters + * representing the chunk name. The array must be at least 4 bytes in + * length, and does not need to be null terminated. To be safe, pass the + * pre-defined chunk names here, and if you need a new one, define it + * where the others are defined. The length is the length of the data. + * All the data must be present. If that is not possible, use the + * png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end() + * functions instead. + */ +void PNGAPI +png_write_chunk(png_structp png_ptr, png_bytep chunk_name, + png_bytep data, png_size_t length) +{ + if (png_ptr == NULL) + return; + png_write_chunk_start(png_ptr, chunk_name, (png_uint_32)length); + png_write_chunk_data(png_ptr, data, (png_size_t)length); + png_write_chunk_end(png_ptr); +} + +/* Write the start of a PNG chunk. The type is the chunk type. + * The total_length is the sum of the lengths of all the data you will be + * passing in png_write_chunk_data(). + */ +void PNGAPI +png_write_chunk_start(png_structp png_ptr, png_bytep chunk_name, + png_uint_32 length) +{ + png_byte buf[8]; + + png_debug2(0, "Writing %s chunk, length = %lu", chunk_name, + (unsigned long)length); + + if (png_ptr == NULL) + return; + +#ifdef PNG_IO_STATE_SUPPORTED + /* Inform the I/O callback that the chunk header is being written. + * PNG_IO_CHUNK_HDR requires a single I/O call. + */ + png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_HDR; +#endif + + /* Write the length and the chunk name */ + png_save_uint_32(buf, length); + png_memcpy(buf + 4, chunk_name, 4); + png_write_data(png_ptr, buf, (png_size_t)8); + /* Put the chunk name into png_ptr->chunk_name */ + png_memcpy(png_ptr->chunk_name, chunk_name, 4); + /* Reset the crc and run it over the chunk name */ + png_reset_crc(png_ptr); + png_calculate_crc(png_ptr, chunk_name, 4); + +#ifdef PNG_IO_STATE_SUPPORTED + /* Inform the I/O callback that chunk data will (possibly) be written. + * PNG_IO_CHUNK_DATA does NOT require a specific number of I/O calls. + */ + png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_DATA; +#endif +} + +/* Write the data of a PNG chunk started with png_write_chunk_start(). + * Note that multiple calls to this function are allowed, and that the + * sum of the lengths from these calls *must* add up to the total_length + * given to png_write_chunk_start(). + */ +void PNGAPI +png_write_chunk_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + /* Write the data, and run the CRC over it */ + if (png_ptr == NULL) + return; + if (data != NULL && length > 0) + { + png_write_data(png_ptr, data, length); + /* Update the CRC after writing the data, + * in case that the user I/O routine alters it. + */ + png_calculate_crc(png_ptr, data, length); + } +} + +/* Finish a chunk started with png_write_chunk_start(). */ +void PNGAPI +png_write_chunk_end(png_structp png_ptr) +{ + png_byte buf[4]; + + if (png_ptr == NULL) return; + +#ifdef PNG_IO_STATE_SUPPORTED + /* Inform the I/O callback that the chunk CRC is being written. + * PNG_IO_CHUNK_CRC requires a single I/O function call. + */ + png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_CRC; +#endif + + /* Write the crc in a single operation */ + png_save_uint_32(buf, png_ptr->crc); + + png_write_data(png_ptr, buf, (png_size_t)4); +} + +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_iCCP_SUPPORTED) +/* This pair of functions encapsulates the operation of (a) compressing a + * text string, and (b) issuing it later as a series of chunk data writes. + * The compression_state structure is shared context for these functions + * set up by the caller in order to make the whole mess thread-safe. + */ + +typedef struct +{ + char *input; /* The uncompressed input data */ + int input_len; /* Its length */ + int num_output_ptr; /* Number of output pointers used */ + int max_output_ptr; /* Size of output_ptr */ + png_charpp output_ptr; /* Array of pointers to output */ +} compression_state; + +/* Compress given text into storage in the png_ptr structure */ +static int /* PRIVATE */ +png_text_compress(png_structp png_ptr, + png_charp text, png_size_t text_len, int compression, + compression_state *comp) +{ + int ret; + + comp->num_output_ptr = 0; + comp->max_output_ptr = 0; + comp->output_ptr = NULL; + comp->input = NULL; + comp->input_len = 0; + + /* We may just want to pass the text right through */ + if (compression == PNG_TEXT_COMPRESSION_NONE) + { + comp->input = text; + comp->input_len = text_len; + return((int)text_len); + } + + if (compression >= PNG_TEXT_COMPRESSION_LAST) + { +#ifdef PNG_STDIO_SUPPORTED + char msg[50]; + png_snprintf(msg, 50, "Unknown compression type %d", compression); + png_warning(png_ptr, msg); +#else + png_warning(png_ptr, "Unknown compression type"); +#endif + } + + /* We can't write the chunk until we find out how much data we have, + * which means we need to run the compressor first and save the + * output. This shouldn't be a problem, as the vast majority of + * comments should be reasonable, but we will set up an array of + * malloc'd pointers to be sure. + * + * If we knew the application was well behaved, we could simplify this + * greatly by assuming we can always malloc an output buffer large + * enough to hold the compressed text ((1001 * text_len / 1000) + 12) + * and malloc this directly. The only time this would be a bad idea is + * if we can't malloc more than 64K and we have 64K of random input + * data, or if the input string is incredibly large (although this + * wouldn't cause a failure, just a slowdown due to swapping). + */ + + /* Set up the compression buffers */ + png_ptr->zstream.avail_in = (uInt)text_len; + png_ptr->zstream.next_in = (Bytef *)text; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_out = (Bytef *)png_ptr->zbuf; + + /* This is the same compression loop as in png_write_row() */ + do + { + /* Compress the data */ + ret = deflate(&png_ptr->zstream, Z_NO_FLUSH); + if (ret != Z_OK) + { + /* Error */ + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + else + png_error(png_ptr, "zlib error"); + } + /* Check to see if we need more room */ + if (!(png_ptr->zstream.avail_out)) + { + /* Make sure the output array has room */ + if (comp->num_output_ptr >= comp->max_output_ptr) + { + int old_max; + + old_max = comp->max_output_ptr; + comp->max_output_ptr = comp->num_output_ptr + 4; + if (comp->output_ptr != NULL) + { + png_charpp old_ptr; + + old_ptr = comp->output_ptr; + comp->output_ptr = (png_charpp)png_malloc(png_ptr, + (png_alloc_size_t) + (comp->max_output_ptr * png_sizeof(png_charpp))); + png_memcpy(comp->output_ptr, old_ptr, old_max + * png_sizeof(png_charp)); + png_free(png_ptr, old_ptr); + } + else + comp->output_ptr = (png_charpp)png_malloc(png_ptr, + (png_alloc_size_t) + (comp->max_output_ptr * png_sizeof(png_charp))); + } + + /* Save the data */ + comp->output_ptr[comp->num_output_ptr] = + (png_charp)png_malloc(png_ptr, + (png_alloc_size_t)png_ptr->zbuf_size); + png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf, + png_ptr->zbuf_size); + comp->num_output_ptr++; + + /* and reset the buffer */ + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_out = png_ptr->zbuf; + } + /* Continue until we don't have any more to compress */ + } while (png_ptr->zstream.avail_in); + + /* Finish the compression */ + do + { + /* Tell zlib we are finished */ + ret = deflate(&png_ptr->zstream, Z_FINISH); + + if (ret == Z_OK) + { + /* Check to see if we need more room */ + if (!(png_ptr->zstream.avail_out)) + { + /* Check to make sure our output array has room */ + if (comp->num_output_ptr >= comp->max_output_ptr) + { + int old_max; + + old_max = comp->max_output_ptr; + comp->max_output_ptr = comp->num_output_ptr + 4; + if (comp->output_ptr != NULL) + { + png_charpp old_ptr; + + old_ptr = comp->output_ptr; + /* This could be optimized to realloc() */ + comp->output_ptr = (png_charpp)png_malloc(png_ptr, + (png_alloc_size_t)(comp->max_output_ptr * + png_sizeof(png_charp))); + png_memcpy(comp->output_ptr, old_ptr, + old_max * png_sizeof(png_charp)); + png_free(png_ptr, old_ptr); + } + else + comp->output_ptr = (png_charpp)png_malloc(png_ptr, + (png_alloc_size_t)(comp->max_output_ptr * + png_sizeof(png_charp))); + } + + /* Save the data */ + comp->output_ptr[comp->num_output_ptr] = + (png_charp)png_malloc(png_ptr, + (png_alloc_size_t)png_ptr->zbuf_size); + png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf, + png_ptr->zbuf_size); + comp->num_output_ptr++; + + /* and reset the buffer pointers */ + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_out = png_ptr->zbuf; + } + } + else if (ret != Z_STREAM_END) + { + /* We got an error */ + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + else + png_error(png_ptr, "zlib error"); + } + } while (ret != Z_STREAM_END); + + /* Text length is number of buffers plus last buffer */ + text_len = png_ptr->zbuf_size * comp->num_output_ptr; + if (png_ptr->zstream.avail_out < png_ptr->zbuf_size) + text_len += png_ptr->zbuf_size - (png_size_t)png_ptr->zstream.avail_out; + + return((int)text_len); +} + +/* Ship the compressed text out via chunk writes */ +static void /* PRIVATE */ +png_write_compressed_data_out(png_structp png_ptr, compression_state *comp) +{ + int i; + + /* Handle the no-compression case */ + if (comp->input) + { + png_write_chunk_data(png_ptr, (png_bytep)comp->input, + (png_size_t)comp->input_len); + return; + } + + /* Write saved output buffers, if any */ + for (i = 0; i < comp->num_output_ptr; i++) + { + png_write_chunk_data(png_ptr, (png_bytep)comp->output_ptr[i], + (png_size_t)png_ptr->zbuf_size); + png_free(png_ptr, comp->output_ptr[i]); + } + if (comp->max_output_ptr != 0) + png_free(png_ptr, comp->output_ptr); + /* Write anything left in zbuf */ + if (png_ptr->zstream.avail_out < (png_uint_32)png_ptr->zbuf_size) + png_write_chunk_data(png_ptr, png_ptr->zbuf, + (png_size_t)(png_ptr->zbuf_size - png_ptr->zstream.avail_out)); + + /* Reset zlib for another zTXt/iTXt or image data */ + deflateReset(&png_ptr->zstream); + png_ptr->zstream.data_type = Z_BINARY; +} +#endif + +/* Write the IHDR chunk, and update the png_struct with the necessary + * information. Note that the rest of this code depends upon this + * information being correct. + */ +void /* PRIVATE */ +png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height, + int bit_depth, int color_type, int compression_type, int filter_type, + int interlace_type) +{ + PNG_IHDR; + int ret; + + png_byte buf[13]; /* Buffer to store the IHDR info */ + + png_debug(1, "in png_write_IHDR"); + + /* Check that we have valid input data from the application info */ + switch (color_type) + { + case PNG_COLOR_TYPE_GRAY: + switch (bit_depth) + { + case 1: + case 2: + case 4: + case 8: + case 16: png_ptr->channels = 1; break; + default: png_error(png_ptr, + "Invalid bit depth for grayscale image"); + } + break; + case PNG_COLOR_TYPE_RGB: + if (bit_depth != 8 && bit_depth != 16) + png_error(png_ptr, "Invalid bit depth for RGB image"); + png_ptr->channels = 3; + break; + case PNG_COLOR_TYPE_PALETTE: + switch (bit_depth) + { + case 1: + case 2: + case 4: + case 8: png_ptr->channels = 1; break; + default: png_error(png_ptr, "Invalid bit depth for paletted image"); + } + break; + case PNG_COLOR_TYPE_GRAY_ALPHA: + if (bit_depth != 8 && bit_depth != 16) + png_error(png_ptr, "Invalid bit depth for grayscale+alpha image"); + png_ptr->channels = 2; + break; + case PNG_COLOR_TYPE_RGB_ALPHA: + if (bit_depth != 8 && bit_depth != 16) + png_error(png_ptr, "Invalid bit depth for RGBA image"); + png_ptr->channels = 4; + break; + default: + png_error(png_ptr, "Invalid image color type specified"); + } + + if (compression_type != PNG_COMPRESSION_TYPE_BASE) + { + png_warning(png_ptr, "Invalid compression type specified"); + compression_type = PNG_COMPRESSION_TYPE_BASE; + } + + /* Write filter_method 64 (intrapixel differencing) only if + * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and + * 2. Libpng did not write a PNG signature (this filter_method is only + * used in PNG datastreams that are embedded in MNG datastreams) and + * 3. The application called png_permit_mng_features with a mask that + * included PNG_FLAG_MNG_FILTER_64 and + * 4. The filter_method is 64 and + * 5. The color_type is RGB or RGBA + */ + if ( +#ifdef PNG_MNG_FEATURES_SUPPORTED + !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) && + (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_RGB_ALPHA) && + (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) && +#endif + filter_type != PNG_FILTER_TYPE_BASE) + { + png_warning(png_ptr, "Invalid filter type specified"); + filter_type = PNG_FILTER_TYPE_BASE; + } + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + if (interlace_type != PNG_INTERLACE_NONE && + interlace_type != PNG_INTERLACE_ADAM7) + { + png_warning(png_ptr, "Invalid interlace type specified"); + interlace_type = PNG_INTERLACE_ADAM7; + } +#else + interlace_type=PNG_INTERLACE_NONE; +#endif + + /* Save the relevent information */ + png_ptr->bit_depth = (png_byte)bit_depth; + png_ptr->color_type = (png_byte)color_type; + png_ptr->interlaced = (png_byte)interlace_type; +#ifdef PNG_MNG_FEATURES_SUPPORTED + png_ptr->filter_type = (png_byte)filter_type; +#endif + png_ptr->compression_type = (png_byte)compression_type; + png_ptr->width = width; + png_ptr->height = height; + + png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels); + png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width); + /* Set the usr info, so any transformations can modify it */ + png_ptr->usr_width = png_ptr->width; + png_ptr->usr_bit_depth = png_ptr->bit_depth; + png_ptr->usr_channels = png_ptr->channels; + + /* Pack the header information into the buffer */ + png_save_uint_32(buf, width); + png_save_uint_32(buf + 4, height); + buf[8] = (png_byte)bit_depth; + buf[9] = (png_byte)color_type; + buf[10] = (png_byte)compression_type; + buf[11] = (png_byte)filter_type; + buf[12] = (png_byte)interlace_type; + + /* Write the chunk */ + png_write_chunk(png_ptr, (png_bytep)png_IHDR, buf, (png_size_t)13); + + /* Initialize zlib with PNG info */ + png_ptr->zstream.zalloc = png_zalloc; + png_ptr->zstream.zfree = png_zfree; + png_ptr->zstream.opaque = (voidpf)png_ptr; + if (!(png_ptr->do_filter)) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE || + png_ptr->bit_depth < 8) + png_ptr->do_filter = PNG_FILTER_NONE; + else + png_ptr->do_filter = PNG_ALL_FILTERS; + } + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY)) + { + if (png_ptr->do_filter != PNG_FILTER_NONE) + png_ptr->zlib_strategy = Z_FILTERED; + else + png_ptr->zlib_strategy = Z_DEFAULT_STRATEGY; + } + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_LEVEL)) + png_ptr->zlib_level = Z_DEFAULT_COMPRESSION; + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL)) + png_ptr->zlib_mem_level = 8; + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS)) + png_ptr->zlib_window_bits = 15; + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_METHOD)) + png_ptr->zlib_method = 8; + ret = deflateInit2(&png_ptr->zstream, png_ptr->zlib_level, + png_ptr->zlib_method, png_ptr->zlib_window_bits, + png_ptr->zlib_mem_level, png_ptr->zlib_strategy); + if (ret != Z_OK) + { + if (ret == Z_VERSION_ERROR) png_error(png_ptr, + "zlib failed to initialize compressor -- version error"); + if (ret == Z_STREAM_ERROR) png_error(png_ptr, + "zlib failed to initialize compressor -- stream error"); + if (ret == Z_MEM_ERROR) png_error(png_ptr, + "zlib failed to initialize compressor -- mem error"); + png_error(png_ptr, "zlib failed to initialize compressor"); + } + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + /* libpng is not interested in zstream.data_type */ + /* Set it to a predefined value, to avoid its evaluation inside zlib */ + png_ptr->zstream.data_type = Z_BINARY; + + png_ptr->mode = PNG_HAVE_IHDR; +} + +/* Write the palette. We are careful not to trust png_color to be in the + * correct order for PNG, so people can redefine it to any convenient + * structure. + */ +void /* PRIVATE */ +png_write_PLTE(png_structp png_ptr, png_colorp palette, png_uint_32 num_pal) +{ + PNG_PLTE; + png_uint_32 i; + png_colorp pal_ptr; + png_byte buf[3]; + + png_debug(1, "in png_write_PLTE"); + + if (( +#ifdef PNG_MNG_FEATURES_SUPPORTED + !(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) && +#endif + num_pal == 0) || num_pal > 256) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + png_error(png_ptr, "Invalid number of colors in palette"); + } + else + { + png_warning(png_ptr, "Invalid number of colors in palette"); + return; + } + } + + if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR)) + { + png_warning(png_ptr, + "Ignoring request to write a PLTE chunk in grayscale PNG"); + return; + } + + png_ptr->num_palette = (png_uint_16)num_pal; + png_debug1(3, "num_palette = %d", png_ptr->num_palette); + + png_write_chunk_start(png_ptr, (png_bytep)png_PLTE, + (png_uint_32)(num_pal * 3)); +#ifdef PNG_POINTER_INDEXING_SUPPORTED + for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++) + { + buf[0] = pal_ptr->red; + buf[1] = pal_ptr->green; + buf[2] = pal_ptr->blue; + png_write_chunk_data(png_ptr, buf, (png_size_t)3); + } +#else + /* This is a little slower but some buggy compilers need to do this + * instead + */ + pal_ptr=palette; + for (i = 0; i < num_pal; i++) + { + buf[0] = pal_ptr[i].red; + buf[1] = pal_ptr[i].green; + buf[2] = pal_ptr[i].blue; + png_write_chunk_data(png_ptr, buf, (png_size_t)3); + } +#endif + png_write_chunk_end(png_ptr); + png_ptr->mode |= PNG_HAVE_PLTE; +} + +/* Write an IDAT chunk */ +void /* PRIVATE */ +png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length) +{ + PNG_IDAT; + + png_debug(1, "in png_write_IDAT"); + + /* Optimize the CMF field in the zlib stream. */ + /* This hack of the zlib stream is compliant to the stream specification. */ + if (!(png_ptr->mode & PNG_HAVE_IDAT) && + png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE) + { + unsigned int z_cmf = data[0]; /* zlib compression method and flags */ + if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70) + { + /* Avoid memory underflows and multiplication overflows. + * + * The conditions below are practically always satisfied; + * however, they still must be checked. + */ + if (length >= 2 && + png_ptr->height < 16384 && png_ptr->width < 16384) + { + png_uint_32 uncompressed_idat_size = png_ptr->height * + ((png_ptr->width * + png_ptr->channels * png_ptr->bit_depth + 15) >> 3); + unsigned int z_cinfo = z_cmf >> 4; + unsigned int half_z_window_size = 1 << (z_cinfo + 7); + while (uncompressed_idat_size <= half_z_window_size && + half_z_window_size >= 256) + { + z_cinfo--; + half_z_window_size >>= 1; + } + z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4); + if (data[0] != (png_byte)z_cmf) + { + data[0] = (png_byte)z_cmf; + data[1] &= 0xe0; + data[1] += (png_byte)(0x1f - ((z_cmf << 8) + data[1]) % 0x1f); + } + } + } + else + png_error(png_ptr, + "Invalid zlib compression method or flags in IDAT"); + } + + png_write_chunk(png_ptr, (png_bytep)png_IDAT, data, length); + png_ptr->mode |= PNG_HAVE_IDAT; +} + +/* Write an IEND chunk */ +void /* PRIVATE */ +png_write_IEND(png_structp png_ptr) +{ + PNG_IEND; + + png_debug(1, "in png_write_IEND"); + + png_write_chunk(png_ptr, (png_bytep)png_IEND, NULL, + (png_size_t)0); + png_ptr->mode |= PNG_HAVE_IEND; +} + +#ifdef PNG_WRITE_gAMA_SUPPORTED +/* Write a gAMA chunk */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +void /* PRIVATE */ +png_write_gAMA(png_structp png_ptr, double file_gamma) +{ + PNG_gAMA; + png_uint_32 igamma; + png_byte buf[4]; + + png_debug(1, "in png_write_gAMA"); + + /* file_gamma is saved in 1/100,000ths */ + igamma = (png_uint_32)(file_gamma * 100000.0 + 0.5); + png_save_uint_32(buf, igamma); + png_write_chunk(png_ptr, (png_bytep)png_gAMA, buf, (png_size_t)4); +} +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +void /* PRIVATE */ +png_write_gAMA_fixed(png_structp png_ptr, png_fixed_point file_gamma) +{ + PNG_gAMA; + png_byte buf[4]; + + png_debug(1, "in png_write_gAMA"); + + /* file_gamma is saved in 1/100,000ths */ + png_save_uint_32(buf, (png_uint_32)file_gamma); + png_write_chunk(png_ptr, (png_bytep)png_gAMA, buf, (png_size_t)4); +} +#endif +#endif + +#ifdef PNG_WRITE_sRGB_SUPPORTED +/* Write a sRGB chunk */ +void /* PRIVATE */ +png_write_sRGB(png_structp png_ptr, int srgb_intent) +{ + PNG_sRGB; + png_byte buf[1]; + + png_debug(1, "in png_write_sRGB"); + + if (srgb_intent >= PNG_sRGB_INTENT_LAST) + png_warning(png_ptr, + "Invalid sRGB rendering intent specified"); + buf[0]=(png_byte)srgb_intent; + png_write_chunk(png_ptr, (png_bytep)png_sRGB, buf, (png_size_t)1); +} +#endif + +#ifdef PNG_WRITE_iCCP_SUPPORTED +/* Write an iCCP chunk */ +void /* PRIVATE */ +png_write_iCCP(png_structp png_ptr, png_charp name, int compression_type, + png_charp profile, int profile_len) +{ + PNG_iCCP; + png_size_t name_len; + png_charp new_name; + compression_state comp; + int embedded_profile_len = 0; + + png_debug(1, "in png_write_iCCP"); + + comp.num_output_ptr = 0; + comp.max_output_ptr = 0; + comp.output_ptr = NULL; + comp.input = NULL; + comp.input_len = 0; + + if ((name_len = png_check_keyword(png_ptr, name, + &new_name)) == 0) + return; + + if (compression_type != PNG_COMPRESSION_TYPE_BASE) + png_warning(png_ptr, "Unknown compression type in iCCP chunk"); + + if (profile == NULL) + profile_len = 0; + + if (profile_len > 3) + embedded_profile_len = + ((*( (png_bytep)profile ))<<24) | + ((*( (png_bytep)profile + 1))<<16) | + ((*( (png_bytep)profile + 2))<< 8) | + ((*( (png_bytep)profile + 3)) ); + + if (embedded_profile_len < 0) + { + png_warning(png_ptr, + "Embedded profile length in iCCP chunk is negative"); + png_free(png_ptr, new_name); + return; + } + + if (profile_len < embedded_profile_len) + { + png_warning(png_ptr, + "Embedded profile length too large in iCCP chunk"); + png_free(png_ptr, new_name); + return; + } + + if (profile_len > embedded_profile_len) + { + png_warning(png_ptr, + "Truncating profile to actual length in iCCP chunk"); + profile_len = embedded_profile_len; + } + + if (profile_len) + profile_len = png_text_compress(png_ptr, profile, + (png_size_t)profile_len, PNG_COMPRESSION_TYPE_BASE, &comp); + + /* Make sure we include the NULL after the name and the compression type */ + png_write_chunk_start(png_ptr, (png_bytep)png_iCCP, + (png_uint_32)(name_len + profile_len + 2)); + new_name[name_len + 1] = 0x00; + png_write_chunk_data(png_ptr, (png_bytep)new_name, + (png_size_t)(name_len + 2)); + + if (profile_len) + png_write_compressed_data_out(png_ptr, &comp); + + png_write_chunk_end(png_ptr); + png_free(png_ptr, new_name); +} +#endif + +#ifdef PNG_WRITE_sPLT_SUPPORTED +/* Write a sPLT chunk */ +void /* PRIVATE */ +png_write_sPLT(png_structp png_ptr, png_sPLT_tp spalette) +{ + PNG_sPLT; + png_size_t name_len; + png_charp new_name; + png_byte entrybuf[10]; + png_size_t entry_size = (spalette->depth == 8 ? 6 : 10); + png_size_t palette_size = entry_size * spalette->nentries; + png_sPLT_entryp ep; +#ifndef PNG_POINTER_INDEXING_SUPPORTED + int i; +#endif + + png_debug(1, "in png_write_sPLT"); + + if ((name_len = png_check_keyword(png_ptr,spalette->name, &new_name))==0) + return; + + /* Make sure we include the NULL after the name */ + png_write_chunk_start(png_ptr, (png_bytep)png_sPLT, + (png_uint_32)(name_len + 2 + palette_size)); + png_write_chunk_data(png_ptr, (png_bytep)new_name, + (png_size_t)(name_len + 1)); + png_write_chunk_data(png_ptr, (png_bytep)&spalette->depth, (png_size_t)1); + + /* Loop through each palette entry, writing appropriately */ +#ifdef PNG_POINTER_INDEXING_SUPPORTED + for (ep = spalette->entries; epentries + spalette->nentries; ep++) + { + if (spalette->depth == 8) + { + entrybuf[0] = (png_byte)ep->red; + entrybuf[1] = (png_byte)ep->green; + entrybuf[2] = (png_byte)ep->blue; + entrybuf[3] = (png_byte)ep->alpha; + png_save_uint_16(entrybuf + 4, ep->frequency); + } + else + { + png_save_uint_16(entrybuf + 0, ep->red); + png_save_uint_16(entrybuf + 2, ep->green); + png_save_uint_16(entrybuf + 4, ep->blue); + png_save_uint_16(entrybuf + 6, ep->alpha); + png_save_uint_16(entrybuf + 8, ep->frequency); + } + png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size); + } +#else + ep=spalette->entries; + for (i=0; i>spalette->nentries; i++) + { + if (spalette->depth == 8) + { + entrybuf[0] = (png_byte)ep[i].red; + entrybuf[1] = (png_byte)ep[i].green; + entrybuf[2] = (png_byte)ep[i].blue; + entrybuf[3] = (png_byte)ep[i].alpha; + png_save_uint_16(entrybuf + 4, ep[i].frequency); + } + else + { + png_save_uint_16(entrybuf + 0, ep[i].red); + png_save_uint_16(entrybuf + 2, ep[i].green); + png_save_uint_16(entrybuf + 4, ep[i].blue); + png_save_uint_16(entrybuf + 6, ep[i].alpha); + png_save_uint_16(entrybuf + 8, ep[i].frequency); + } + png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size); + } +#endif + + png_write_chunk_end(png_ptr); + png_free(png_ptr, new_name); +} +#endif + +#ifdef PNG_WRITE_sBIT_SUPPORTED +/* Write the sBIT chunk */ +void /* PRIVATE */ +png_write_sBIT(png_structp png_ptr, png_color_8p sbit, int color_type) +{ + PNG_sBIT; + png_byte buf[4]; + png_size_t size; + + png_debug(1, "in png_write_sBIT"); + + /* Make sure we don't depend upon the order of PNG_COLOR_8 */ + if (color_type & PNG_COLOR_MASK_COLOR) + { + png_byte maxbits; + + maxbits = (png_byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 : + png_ptr->usr_bit_depth); + if (sbit->red == 0 || sbit->red > maxbits || + sbit->green == 0 || sbit->green > maxbits || + sbit->blue == 0 || sbit->blue > maxbits) + { + png_warning(png_ptr, "Invalid sBIT depth specified"); + return; + } + buf[0] = sbit->red; + buf[1] = sbit->green; + buf[2] = sbit->blue; + size = 3; + } + else + { + if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth) + { + png_warning(png_ptr, "Invalid sBIT depth specified"); + return; + } + buf[0] = sbit->gray; + size = 1; + } + + if (color_type & PNG_COLOR_MASK_ALPHA) + { + if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth) + { + png_warning(png_ptr, "Invalid sBIT depth specified"); + return; + } + buf[size++] = sbit->alpha; + } + + png_write_chunk(png_ptr, (png_bytep)png_sBIT, buf, size); +} +#endif + +#ifdef PNG_WRITE_cHRM_SUPPORTED +/* Write the cHRM chunk */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +void /* PRIVATE */ +png_write_cHRM(png_structp png_ptr, double white_x, double white_y, + double red_x, double red_y, double green_x, double green_y, + double blue_x, double blue_y) +{ + PNG_cHRM; + png_byte buf[32]; + + png_fixed_point int_white_x, int_white_y, int_red_x, int_red_y, + int_green_x, int_green_y, int_blue_x, int_blue_y; + + png_debug(1, "in png_write_cHRM"); + + int_white_x = (png_uint_32)(white_x * 100000.0 + 0.5); + int_white_y = (png_uint_32)(white_y * 100000.0 + 0.5); + int_red_x = (png_uint_32)(red_x * 100000.0 + 0.5); + int_red_y = (png_uint_32)(red_y * 100000.0 + 0.5); + int_green_x = (png_uint_32)(green_x * 100000.0 + 0.5); + int_green_y = (png_uint_32)(green_y * 100000.0 + 0.5); + int_blue_x = (png_uint_32)(blue_x * 100000.0 + 0.5); + int_blue_y = (png_uint_32)(blue_y * 100000.0 + 0.5); + +#ifdef PNG_CHECK_cHRM_SUPPORTED + if (png_check_cHRM_fixed(png_ptr, int_white_x, int_white_y, + int_red_x, int_red_y, int_green_x, int_green_y, int_blue_x, int_blue_y)) +#endif + { + /* Each value is saved in 1/100,000ths */ + + png_save_uint_32(buf, int_white_x); + png_save_uint_32(buf + 4, int_white_y); + + png_save_uint_32(buf + 8, int_red_x); + png_save_uint_32(buf + 12, int_red_y); + + png_save_uint_32(buf + 16, int_green_x); + png_save_uint_32(buf + 20, int_green_y); + + png_save_uint_32(buf + 24, int_blue_x); + png_save_uint_32(buf + 28, int_blue_y); + + png_write_chunk(png_ptr, (png_bytep)png_cHRM, buf, (png_size_t)32); + } +} +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +void /* PRIVATE */ +png_write_cHRM_fixed(png_structp png_ptr, png_fixed_point white_x, + png_fixed_point white_y, png_fixed_point red_x, png_fixed_point red_y, + png_fixed_point green_x, png_fixed_point green_y, png_fixed_point blue_x, + png_fixed_point blue_y) +{ + PNG_cHRM; + png_byte buf[32]; + + png_debug(1, "in png_write_cHRM"); + + /* Each value is saved in 1/100,000ths */ +#ifdef PNG_CHECK_cHRM_SUPPORTED + if (png_check_cHRM_fixed(png_ptr, white_x, white_y, red_x, red_y, + green_x, green_y, blue_x, blue_y)) +#endif + { + png_save_uint_32(buf, (png_uint_32)white_x); + png_save_uint_32(buf + 4, (png_uint_32)white_y); + + png_save_uint_32(buf + 8, (png_uint_32)red_x); + png_save_uint_32(buf + 12, (png_uint_32)red_y); + + png_save_uint_32(buf + 16, (png_uint_32)green_x); + png_save_uint_32(buf + 20, (png_uint_32)green_y); + + png_save_uint_32(buf + 24, (png_uint_32)blue_x); + png_save_uint_32(buf + 28, (png_uint_32)blue_y); + + png_write_chunk(png_ptr, (png_bytep)png_cHRM, buf, (png_size_t)32); + } +} +#endif +#endif + +#ifdef PNG_WRITE_tRNS_SUPPORTED +/* Write the tRNS chunk */ +void /* PRIVATE */ +png_write_tRNS(png_structp png_ptr, png_bytep trans_alpha, png_color_16p tran, + int num_trans, int color_type) +{ + PNG_tRNS; + png_byte buf[6]; + + png_debug(1, "in png_write_tRNS"); + + if (color_type == PNG_COLOR_TYPE_PALETTE) + { + if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette) + { + png_warning(png_ptr, "Invalid number of transparent colors specified"); + return; + } + /* Write the chunk out as it is */ + png_write_chunk(png_ptr, (png_bytep)png_tRNS, trans_alpha, + (png_size_t)num_trans); + } + else if (color_type == PNG_COLOR_TYPE_GRAY) + { + /* One 16 bit value */ + if (tran->gray >= (1 << png_ptr->bit_depth)) + { + png_warning(png_ptr, + "Ignoring attempt to write tRNS chunk out-of-range for bit_depth"); + return; + } + png_save_uint_16(buf, tran->gray); + png_write_chunk(png_ptr, (png_bytep)png_tRNS, buf, (png_size_t)2); + } + else if (color_type == PNG_COLOR_TYPE_RGB) + { + /* Three 16 bit values */ + png_save_uint_16(buf, tran->red); + png_save_uint_16(buf + 2, tran->green); + png_save_uint_16(buf + 4, tran->blue); + if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4])) + { + png_warning(png_ptr, + "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8"); + return; + } + png_write_chunk(png_ptr, (png_bytep)png_tRNS, buf, (png_size_t)6); + } + else + { + png_warning(png_ptr, "Can't write tRNS with an alpha channel"); + } +} +#endif + +#ifdef PNG_WRITE_bKGD_SUPPORTED +/* Write the background chunk */ +void /* PRIVATE */ +png_write_bKGD(png_structp png_ptr, png_color_16p back, int color_type) +{ + PNG_bKGD; + png_byte buf[6]; + + png_debug(1, "in png_write_bKGD"); + + if (color_type == PNG_COLOR_TYPE_PALETTE) + { + if ( +#ifdef PNG_MNG_FEATURES_SUPPORTED + (png_ptr->num_palette || + (!(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE))) && +#endif + back->index >= png_ptr->num_palette) + { + png_warning(png_ptr, "Invalid background palette index"); + return; + } + buf[0] = back->index; + png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)1); + } + else if (color_type & PNG_COLOR_MASK_COLOR) + { + png_save_uint_16(buf, back->red); + png_save_uint_16(buf + 2, back->green); + png_save_uint_16(buf + 4, back->blue); + if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4])) + { + png_warning(png_ptr, + "Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8"); + return; + } + png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)6); + } + else + { + if (back->gray >= (1 << png_ptr->bit_depth)) + { + png_warning(png_ptr, + "Ignoring attempt to write bKGD chunk out-of-range for bit_depth"); + return; + } + png_save_uint_16(buf, back->gray); + png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)2); + } +} +#endif + +#ifdef PNG_WRITE_hIST_SUPPORTED +/* Write the histogram */ +void /* PRIVATE */ +png_write_hIST(png_structp png_ptr, png_uint_16p hist, int num_hist) +{ + PNG_hIST; + int i; + png_byte buf[3]; + + png_debug(1, "in png_write_hIST"); + + if (num_hist > (int)png_ptr->num_palette) + { + png_debug2(3, "num_hist = %d, num_palette = %d", num_hist, + png_ptr->num_palette); + png_warning(png_ptr, "Invalid number of histogram entries specified"); + return; + } + + png_write_chunk_start(png_ptr, (png_bytep)png_hIST, + (png_uint_32)(num_hist * 2)); + for (i = 0; i < num_hist; i++) + { + png_save_uint_16(buf, hist[i]); + png_write_chunk_data(png_ptr, buf, (png_size_t)2); + } + png_write_chunk_end(png_ptr); +} +#endif + +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \ + defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) +/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification, + * and if invalid, correct the keyword rather than discarding the entire + * chunk. The PNG 1.0 specification requires keywords 1-79 characters in + * length, forbids leading or trailing whitespace, multiple internal spaces, + * and the non-break space (0x80) from ISO 8859-1. Returns keyword length. + * + * The new_key is allocated to hold the corrected keyword and must be freed + * by the calling routine. This avoids problems with trying to write to + * static keywords without having to have duplicate copies of the strings. + */ +png_size_t /* PRIVATE */ +png_check_keyword(png_structp png_ptr, png_charp key, png_charpp new_key) +{ + png_size_t key_len; + png_charp kp, dp; + int kflag; + int kwarn=0; + + png_debug(1, "in png_check_keyword"); + + *new_key = NULL; + + if (key == NULL || (key_len = png_strlen(key)) == 0) + { + png_warning(png_ptr, "zero length keyword"); + return ((png_size_t)0); + } + + png_debug1(2, "Keyword to be checked is '%s'", key); + + *new_key = (png_charp)png_malloc_warn(png_ptr, (png_uint_32)(key_len + 2)); + if (*new_key == NULL) + { + png_warning(png_ptr, "Out of memory while procesing keyword"); + return ((png_size_t)0); + } + + /* Replace non-printing characters with a blank and print a warning */ + for (kp = key, dp = *new_key; *kp != '\0'; kp++, dp++) + { + if ((png_byte)*kp < 0x20 || + ((png_byte)*kp > 0x7E && (png_byte)*kp < 0xA1)) + { +#ifdef PNG_STDIO_SUPPORTED + char msg[40]; + + png_snprintf(msg, 40, + "invalid keyword character 0x%02X", (png_byte)*kp); + png_warning(png_ptr, msg); +#else + png_warning(png_ptr, "invalid character in keyword"); +#endif + *dp = ' '; + } + else + { + *dp = *kp; + } + } + *dp = '\0'; + + /* Remove any trailing white space. */ + kp = *new_key + key_len - 1; + if (*kp == ' ') + { + png_warning(png_ptr, "trailing spaces removed from keyword"); + + while (*kp == ' ') + { + *(kp--) = '\0'; + key_len--; + } + } + + /* Remove any leading white space. */ + kp = *new_key; + if (*kp == ' ') + { + png_warning(png_ptr, "leading spaces removed from keyword"); + + while (*kp == ' ') + { + kp++; + key_len--; + } + } + + png_debug1(2, "Checking for multiple internal spaces in '%s'", kp); + + /* Remove multiple internal spaces. */ + for (kflag = 0, dp = *new_key; *kp != '\0'; kp++) + { + if (*kp == ' ' && kflag == 0) + { + *(dp++) = *kp; + kflag = 1; + } + else if (*kp == ' ') + { + key_len--; + kwarn=1; + } + else + { + *(dp++) = *kp; + kflag = 0; + } + } + *dp = '\0'; + if (kwarn) + png_warning(png_ptr, "extra interior spaces removed from keyword"); + + if (key_len == 0) + { + png_free(png_ptr, *new_key); + png_warning(png_ptr, "Zero length keyword"); + } + + if (key_len > 79) + { + png_warning(png_ptr, "keyword length must be 1 - 79 characters"); + (*new_key)[79] = '\0'; + key_len = 79; + } + + return (key_len); +} +#endif + +#ifdef PNG_WRITE_tEXt_SUPPORTED +/* Write a tEXt chunk */ +void /* PRIVATE */ +png_write_tEXt(png_structp png_ptr, png_charp key, png_charp text, + png_size_t text_len) +{ + PNG_tEXt; + png_size_t key_len; + png_charp new_key; + + png_debug(1, "in png_write_tEXt"); + + if ((key_len = png_check_keyword(png_ptr, key, &new_key))==0) + return; + + if (text == NULL || *text == '\0') + text_len = 0; + else + text_len = png_strlen(text); + + /* Make sure we include the 0 after the key */ + png_write_chunk_start(png_ptr, (png_bytep)png_tEXt, + (png_uint_32)(key_len + text_len + 1)); + /* + * We leave it to the application to meet PNG-1.0 requirements on the + * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of + * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them. + * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. + */ + png_write_chunk_data(png_ptr, (png_bytep)new_key, + (png_size_t)(key_len + 1)); + if (text_len) + png_write_chunk_data(png_ptr, (png_bytep)text, (png_size_t)text_len); + + png_write_chunk_end(png_ptr); + png_free(png_ptr, new_key); +} +#endif + +#ifdef PNG_WRITE_zTXt_SUPPORTED +/* Write a compressed text chunk */ +void /* PRIVATE */ +png_write_zTXt(png_structp png_ptr, png_charp key, png_charp text, + png_size_t text_len, int compression) +{ + PNG_zTXt; + png_size_t key_len; + char buf[1]; + png_charp new_key; + compression_state comp; + + png_debug(1, "in png_write_zTXt"); + + comp.num_output_ptr = 0; + comp.max_output_ptr = 0; + comp.output_ptr = NULL; + comp.input = NULL; + comp.input_len = 0; + + if ((key_len = png_check_keyword(png_ptr, key, &new_key))==0) + { + png_free(png_ptr, new_key); + return; + } + + if (text == NULL || *text == '\0' || compression==PNG_TEXT_COMPRESSION_NONE) + { + png_write_tEXt(png_ptr, new_key, text, (png_size_t)0); + png_free(png_ptr, new_key); + return; + } + + text_len = png_strlen(text); + + /* Compute the compressed data; do it now for the length */ + text_len = png_text_compress(png_ptr, text, text_len, compression, + &comp); + + /* Write start of chunk */ + png_write_chunk_start(png_ptr, (png_bytep)png_zTXt, + (png_uint_32)(key_len+text_len + 2)); + /* Write key */ + png_write_chunk_data(png_ptr, (png_bytep)new_key, + (png_size_t)(key_len + 1)); + png_free(png_ptr, new_key); + + buf[0] = (png_byte)compression; + /* Write compression */ + png_write_chunk_data(png_ptr, (png_bytep)buf, (png_size_t)1); + /* Write the compressed data */ + png_write_compressed_data_out(png_ptr, &comp); + + /* Close the chunk */ + png_write_chunk_end(png_ptr); +} +#endif + +#ifdef PNG_WRITE_iTXt_SUPPORTED +/* Write an iTXt chunk */ +void /* PRIVATE */ +png_write_iTXt(png_structp png_ptr, int compression, png_charp key, + png_charp lang, png_charp lang_key, png_charp text) +{ + PNG_iTXt; + png_size_t lang_len, key_len, lang_key_len, text_len; + png_charp new_lang; + png_charp new_key = NULL; + png_byte cbuf[2]; + compression_state comp; + + png_debug(1, "in png_write_iTXt"); + + comp.num_output_ptr = 0; + comp.max_output_ptr = 0; + comp.output_ptr = NULL; + comp.input = NULL; + + if ((key_len = png_check_keyword(png_ptr, key, &new_key))==0) + return; + + if ((lang_len = png_check_keyword(png_ptr, lang, &new_lang))==0) + { + png_warning(png_ptr, "Empty language field in iTXt chunk"); + new_lang = NULL; + lang_len = 0; + } + + if (lang_key == NULL) + lang_key_len = 0; + else + lang_key_len = png_strlen(lang_key); + + if (text == NULL) + text_len = 0; + else + text_len = png_strlen(text); + + /* Compute the compressed data; do it now for the length */ + text_len = png_text_compress(png_ptr, text, text_len, compression-2, + &comp); + + + /* Make sure we include the compression flag, the compression byte, + * and the NULs after the key, lang, and lang_key parts */ + + png_write_chunk_start(png_ptr, (png_bytep)png_iTXt, + (png_uint_32)( + 5 /* comp byte, comp flag, terminators for key, lang and lang_key */ + + key_len + + lang_len + + lang_key_len + + text_len)); + + /* We leave it to the application to meet PNG-1.0 requirements on the + * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of + * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them. + * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. + */ + png_write_chunk_data(png_ptr, (png_bytep)new_key, + (png_size_t)(key_len + 1)); + + /* Set the compression flag */ + if (compression == PNG_ITXT_COMPRESSION_NONE || \ + compression == PNG_TEXT_COMPRESSION_NONE) + cbuf[0] = 0; + else /* compression == PNG_ITXT_COMPRESSION_zTXt */ + cbuf[0] = 1; + /* Set the compression method */ + cbuf[1] = 0; + png_write_chunk_data(png_ptr, cbuf, (png_size_t)2); + + cbuf[0] = 0; + png_write_chunk_data(png_ptr, (new_lang ? (png_bytep)new_lang : cbuf), + (png_size_t)(lang_len + 1)); + png_write_chunk_data(png_ptr, (lang_key ? (png_bytep)lang_key : cbuf), + (png_size_t)(lang_key_len + 1)); + png_write_compressed_data_out(png_ptr, &comp); + + png_write_chunk_end(png_ptr); + png_free(png_ptr, new_key); + png_free(png_ptr, new_lang); +} +#endif + +#ifdef PNG_WRITE_oFFs_SUPPORTED +/* Write the oFFs chunk */ +void /* PRIVATE */ +png_write_oFFs(png_structp png_ptr, png_int_32 x_offset, png_int_32 y_offset, + int unit_type) +{ + PNG_oFFs; + png_byte buf[9]; + + png_debug(1, "in png_write_oFFs"); + + if (unit_type >= PNG_OFFSET_LAST) + png_warning(png_ptr, "Unrecognized unit type for oFFs chunk"); + + png_save_int_32(buf, x_offset); + png_save_int_32(buf + 4, y_offset); + buf[8] = (png_byte)unit_type; + + png_write_chunk(png_ptr, (png_bytep)png_oFFs, buf, (png_size_t)9); +} +#endif +#ifdef PNG_WRITE_pCAL_SUPPORTED +/* Write the pCAL chunk (described in the PNG extensions document) */ +void /* PRIVATE */ +png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0, + png_int_32 X1, int type, int nparams, png_charp units, png_charpp params) +{ + PNG_pCAL; + png_size_t purpose_len, units_len, total_len; + png_uint_32p params_len; + png_byte buf[10]; + png_charp new_purpose; + int i; + + png_debug1(1, "in png_write_pCAL (%d parameters)", nparams); + + if (type >= PNG_EQUATION_LAST) + png_warning(png_ptr, "Unrecognized equation type for pCAL chunk"); + + purpose_len = png_check_keyword(png_ptr, purpose, &new_purpose) + 1; + png_debug1(3, "pCAL purpose length = %d", (int)purpose_len); + units_len = png_strlen(units) + (nparams == 0 ? 0 : 1); + png_debug1(3, "pCAL units length = %d", (int)units_len); + total_len = purpose_len + units_len + 10; + + params_len = (png_uint_32p)png_malloc(png_ptr, + (png_alloc_size_t)(nparams * png_sizeof(png_uint_32))); + + /* Find the length of each parameter, making sure we don't count the + null terminator for the last parameter. */ + for (i = 0; i < nparams; i++) + { + params_len[i] = png_strlen(params[i]) + (i == nparams - 1 ? 0 : 1); + png_debug2(3, "pCAL parameter %d length = %lu", i, + (unsigned long) params_len[i]); + total_len += (png_size_t)params_len[i]; + } + + png_debug1(3, "pCAL total length = %d", (int)total_len); + png_write_chunk_start(png_ptr, (png_bytep)png_pCAL, (png_uint_32)total_len); + png_write_chunk_data(png_ptr, (png_bytep)new_purpose, + (png_size_t)purpose_len); + png_save_int_32(buf, X0); + png_save_int_32(buf + 4, X1); + buf[8] = (png_byte)type; + buf[9] = (png_byte)nparams; + png_write_chunk_data(png_ptr, buf, (png_size_t)10); + png_write_chunk_data(png_ptr, (png_bytep)units, (png_size_t)units_len); + + png_free(png_ptr, new_purpose); + + for (i = 0; i < nparams; i++) + { + png_write_chunk_data(png_ptr, (png_bytep)params[i], + (png_size_t)params_len[i]); + } + + png_free(png_ptr, params_len); + png_write_chunk_end(png_ptr); +} +#endif + +#ifdef PNG_WRITE_sCAL_SUPPORTED +/* Write the sCAL chunk */ +#if defined(PNG_FLOATING_POINT_SUPPORTED) && defined(PNG_STDIO_SUPPORTED) +void /* PRIVATE */ +png_write_sCAL(png_structp png_ptr, int unit, double width, double height) +{ + PNG_sCAL; + char buf[64]; + png_size_t total_len; + + png_debug(1, "in png_write_sCAL"); + + buf[0] = (char)unit; + png_snprintf(buf + 1, 63, "%12.12e", width); + total_len = 1 + png_strlen(buf + 1) + 1; + png_snprintf(buf + total_len, 64-total_len, "%12.12e", height); + total_len += png_strlen(buf + total_len); + + png_debug1(3, "sCAL total length = %u", (unsigned int)total_len); + png_write_chunk(png_ptr, (png_bytep)png_sCAL, (png_bytep)buf, total_len); +} +#else +#ifdef PNG_FIXED_POINT_SUPPORTED +void /* PRIVATE */ +png_write_sCAL_s(png_structp png_ptr, int unit, png_charp width, + png_charp height) +{ + PNG_sCAL; + png_byte buf[64]; + png_size_t wlen, hlen, total_len; + + png_debug(1, "in png_write_sCAL_s"); + + wlen = png_strlen(width); + hlen = png_strlen(height); + total_len = wlen + hlen + 2; + if (total_len > 64) + { + png_warning(png_ptr, "Can't write sCAL (buffer too small)"); + return; + } + + buf[0] = (png_byte)unit; + png_memcpy(buf + 1, width, wlen + 1); /* Append the '\0' here */ + png_memcpy(buf + wlen + 2, height, hlen); /* Do NOT append the '\0' here */ + + png_debug1(3, "sCAL total length = %u", (unsigned int)total_len); + png_write_chunk(png_ptr, (png_bytep)png_sCAL, buf, total_len); +} +#endif +#endif +#endif + +#ifdef PNG_WRITE_pHYs_SUPPORTED +/* Write the pHYs chunk */ +void /* PRIVATE */ +png_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit, + png_uint_32 y_pixels_per_unit, + int unit_type) +{ + PNG_pHYs; + png_byte buf[9]; + + png_debug(1, "in png_write_pHYs"); + + if (unit_type >= PNG_RESOLUTION_LAST) + png_warning(png_ptr, "Unrecognized unit type for pHYs chunk"); + + png_save_uint_32(buf, x_pixels_per_unit); + png_save_uint_32(buf + 4, y_pixels_per_unit); + buf[8] = (png_byte)unit_type; + + png_write_chunk(png_ptr, (png_bytep)png_pHYs, buf, (png_size_t)9); +} +#endif + +#ifdef PNG_WRITE_tIME_SUPPORTED +/* Write the tIME chunk. Use either png_convert_from_struct_tm() + * or png_convert_from_time_t(), or fill in the structure yourself. + */ +void /* PRIVATE */ +png_write_tIME(png_structp png_ptr, png_timep mod_time) +{ + PNG_tIME; + png_byte buf[7]; + + png_debug(1, "in png_write_tIME"); + + if (mod_time->month > 12 || mod_time->month < 1 || + mod_time->day > 31 || mod_time->day < 1 || + mod_time->hour > 23 || mod_time->second > 60) + { + png_warning(png_ptr, "Invalid time specified for tIME chunk"); + return; + } + + png_save_uint_16(buf, mod_time->year); + buf[2] = mod_time->month; + buf[3] = mod_time->day; + buf[4] = mod_time->hour; + buf[5] = mod_time->minute; + buf[6] = mod_time->second; + + png_write_chunk(png_ptr, (png_bytep)png_tIME, buf, (png_size_t)7); +} +#endif + +/* Initializes the row writing capability of libpng */ +void /* PRIVATE */ +png_write_start_row(png_structp png_ptr) +{ +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif + + png_size_t buf_size; + + png_debug(1, "in png_write_start_row"); + + buf_size = (png_size_t)(PNG_ROWBYTES( + png_ptr->usr_channels*png_ptr->usr_bit_depth, png_ptr->width) + 1); + + /* Set up row buffer */ + png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, + (png_alloc_size_t)buf_size); + png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE; + +#ifdef PNG_WRITE_FILTER_SUPPORTED + /* Set up filtering buffer, if using this filter */ + if (png_ptr->do_filter & PNG_FILTER_SUB) + { + png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, + (png_alloc_size_t)(png_ptr->rowbytes + 1)); + png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB; + } + + /* We only need to keep the previous row if we are using one of these. */ + if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH)) + { + /* Set up previous row buffer */ + png_ptr->prev_row = (png_bytep)png_calloc(png_ptr, + (png_alloc_size_t)buf_size); + + if (png_ptr->do_filter & PNG_FILTER_UP) + { + png_ptr->up_row = (png_bytep)png_malloc(png_ptr, + (png_size_t)(png_ptr->rowbytes + 1)); + png_ptr->up_row[0] = PNG_FILTER_VALUE_UP; + } + + if (png_ptr->do_filter & PNG_FILTER_AVG) + { + png_ptr->avg_row = (png_bytep)png_malloc(png_ptr, + (png_alloc_size_t)(png_ptr->rowbytes + 1)); + png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG; + } + + if (png_ptr->do_filter & PNG_FILTER_PAETH) + { + png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr, + (png_size_t)(png_ptr->rowbytes + 1)); + png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH; + } + } +#endif /* PNG_WRITE_FILTER_SUPPORTED */ + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* If interlaced, we need to set up width and height of pass */ + if (png_ptr->interlaced) + { + if (!(png_ptr->transformations & PNG_INTERLACE)) + { + png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - + png_pass_ystart[0]) / png_pass_yinc[0]; + png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 - + png_pass_start[0]) / png_pass_inc[0]; + } + else + { + png_ptr->num_rows = png_ptr->height; + png_ptr->usr_width = png_ptr->width; + } + } + else +#endif + { + png_ptr->num_rows = png_ptr->height; + png_ptr->usr_width = png_ptr->width; + } + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_out = png_ptr->zbuf; +} + +/* Internal use only. Called when finished processing a row of data. */ +void /* PRIVATE */ +png_write_finish_row(png_structp png_ptr) +{ +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif + + int ret; + + png_debug(1, "in png_write_finish_row"); + + /* Next row */ + png_ptr->row_number++; + + /* See if we are done */ + if (png_ptr->row_number < png_ptr->num_rows) + return; + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* If interlaced, go to next pass */ + if (png_ptr->interlaced) + { + png_ptr->row_number = 0; + if (png_ptr->transformations & PNG_INTERLACE) + { + png_ptr->pass++; + } + else + { + /* Loop until we find a non-zero width or height pass */ + do + { + png_ptr->pass++; + if (png_ptr->pass >= 7) + break; + png_ptr->usr_width = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + png_ptr->num_rows = (png_ptr->height + + png_pass_yinc[png_ptr->pass] - 1 - + png_pass_ystart[png_ptr->pass]) / + png_pass_yinc[png_ptr->pass]; + if (png_ptr->transformations & PNG_INTERLACE) + break; + } while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0); + + } + + /* Reset the row above the image for the next pass */ + if (png_ptr->pass < 7) + { + if (png_ptr->prev_row != NULL) + png_memset(png_ptr->prev_row, 0, + (png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels* + png_ptr->usr_bit_depth, png_ptr->width)) + 1); + return; + } + } +#endif + + /* If we get here, we've just written the last row, so we need + to flush the compressor */ + do + { + /* Tell the compressor we are done */ + ret = deflate(&png_ptr->zstream, Z_FINISH); + /* Check for an error */ + if (ret == Z_OK) + { + /* Check to see if we need more room */ + if (!(png_ptr->zstream.avail_out)) + { + png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + } + } + else if (ret != Z_STREAM_END) + { + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + else + png_error(png_ptr, "zlib error"); + } + } while (ret != Z_STREAM_END); + + /* Write any extra space */ + if (png_ptr->zstream.avail_out < png_ptr->zbuf_size) + { + png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size - + png_ptr->zstream.avail_out); + } + + deflateReset(&png_ptr->zstream); + png_ptr->zstream.data_type = Z_BINARY; +} + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED +/* Pick out the correct pixels for the interlace pass. + * The basic idea here is to go through the row with a source + * pointer and a destination pointer (sp and dp), and copy the + * correct pixels for the pass. As the row gets compacted, + * sp will always be >= dp, so we should never overwrite anything. + * See the default: case for the easiest code to understand. + */ +void /* PRIVATE */ +png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) +{ + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + png_debug(1, "in png_do_write_interlace"); + + /* We don't have to do anything on the last pass (6) */ + if (pass < 6) + { + /* Each pixel depth is handled separately */ + switch (row_info->pixel_depth) + { + case 1: + { + png_bytep sp; + png_bytep dp; + int shift; + int d; + int value; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + dp = row; + d = 0; + shift = 7; + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + sp = row + (png_size_t)(i >> 3); + value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01; + d |= (value << shift); + + if (shift == 0) + { + shift = 7; + *dp++ = (png_byte)d; + d = 0; + } + else + shift--; + + } + if (shift != 7) + *dp = (png_byte)d; + break; + } + case 2: + { + png_bytep sp; + png_bytep dp; + int shift; + int d; + int value; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + dp = row; + shift = 6; + d = 0; + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + sp = row + (png_size_t)(i >> 2); + value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03; + d |= (value << shift); + + if (shift == 0) + { + shift = 6; + *dp++ = (png_byte)d; + d = 0; + } + else + shift -= 2; + } + if (shift != 6) + *dp = (png_byte)d; + break; + } + case 4: + { + png_bytep sp; + png_bytep dp; + int shift; + int d; + int value; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + dp = row; + shift = 4; + d = 0; + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + sp = row + (png_size_t)(i >> 1); + value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f; + d |= (value << shift); + + if (shift == 0) + { + shift = 4; + *dp++ = (png_byte)d; + d = 0; + } + else + shift -= 4; + } + if (shift != 4) + *dp = (png_byte)d; + break; + } + default: + { + png_bytep sp; + png_bytep dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + png_size_t pixel_bytes; + + /* Start at the beginning */ + dp = row; + /* Find out how many bytes each pixel takes up */ + pixel_bytes = (row_info->pixel_depth >> 3); + /* Loop through the row, only looking at the pixels that + matter */ + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + /* Find out where the original pixel is */ + sp = row + (png_size_t)i * pixel_bytes; + /* Move the pixel */ + if (dp != sp) + png_memcpy(dp, sp, pixel_bytes); + /* Next pixel */ + dp += pixel_bytes; + } + break; + } + } + /* Set new row width */ + row_info->width = (row_info->width + + png_pass_inc[pass] - 1 - + png_pass_start[pass]) / + png_pass_inc[pass]; + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, + row_info->width); + } +} +#endif + +/* This filters the row, chooses which filter to use, if it has not already + * been specified by the application, and then writes the row out with the + * chosen filter. + */ +#define PNG_MAXSUM (((png_uint_32)(-1)) >> 1) +#define PNG_HISHIFT 10 +#define PNG_LOMASK ((png_uint_32)0xffffL) +#define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT)) +void /* PRIVATE */ +png_write_find_filter(png_structp png_ptr, png_row_infop row_info) +{ + png_bytep best_row; +#ifdef PNG_WRITE_FILTER_SUPPORTED + png_bytep prev_row, row_buf; + png_uint_32 mins, bpp; + png_byte filter_to_do = png_ptr->do_filter; + png_uint_32 row_bytes = row_info->rowbytes; +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + int num_p_filters = (int)png_ptr->num_prev_filters; +#endif + + png_debug(1, "in png_write_find_filter"); + +#ifndef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->row_number == 0 && filter_to_do == PNG_ALL_FILTERS) + { + /* These will never be selected so we need not test them. */ + filter_to_do &= ~(PNG_FILTER_UP | PNG_FILTER_PAETH); + } +#endif + + /* Find out how many bytes offset each pixel is */ + bpp = (row_info->pixel_depth + 7) >> 3; + + prev_row = png_ptr->prev_row; +#endif + best_row = png_ptr->row_buf; +#ifdef PNG_WRITE_FILTER_SUPPORTED + row_buf = best_row; + mins = PNG_MAXSUM; + + /* The prediction method we use is to find which method provides the + * smallest value when summing the absolute values of the distances + * from zero, using anything >= 128 as negative numbers. This is known + * as the "minimum sum of absolute differences" heuristic. Other + * heuristics are the "weighted minimum sum of absolute differences" + * (experimental and can in theory improve compression), and the "zlib + * predictive" method (not implemented yet), which does test compressions + * of lines using different filter methods, and then chooses the + * (series of) filter(s) that give minimum compressed data size (VERY + * computationally expensive). + * + * GRR 980525: consider also + * (1) minimum sum of absolute differences from running average (i.e., + * keep running sum of non-absolute differences & count of bytes) + * [track dispersion, too? restart average if dispersion too large?] + * (1b) minimum sum of absolute differences from sliding average, probably + * with window size <= deflate window (usually 32K) + * (2) minimum sum of squared differences from zero or running average + * (i.e., ~ root-mean-square approach) + */ + + + /* We don't need to test the 'no filter' case if this is the only filter + * that has been chosen, as it doesn't actually do anything to the data. + */ + if ((filter_to_do & PNG_FILTER_NONE) && + filter_to_do != PNG_FILTER_NONE) + { + png_bytep rp; + png_uint_32 sum = 0; + png_uint_32 i; + int v; + + for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++) + { + v = *rp; + sum += (v < 128) ? v : 256 - v; + } + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + png_uint_32 sumhi, sumlo; + int j; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; /* Gives us some footroom */ + + /* Reduce the sum if we match any of the previous rows */ + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + /* Factor in the cost of this filter (this is here for completeness, + * but it makes no sense to have a "cost" for the NONE filter, as + * it has the minimum possible computational cost - none). + */ + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> + PNG_COST_SHIFT; + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + mins = sum; + } + + /* Sub filter */ + if (filter_to_do == PNG_FILTER_SUB) + /* It's the only filter so no testing is needed */ + { + png_bytep rp, lp, dp; + png_uint_32 i; + for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; + i++, rp++, dp++) + { + *dp = *rp; + } + for (lp = row_buf + 1; i < row_bytes; + i++, rp++, lp++, dp++) + { + *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); + } + best_row = png_ptr->sub_row; + } + + else if (filter_to_do & PNG_FILTER_SUB) + { + png_bytep rp, dp, lp; + png_uint_32 sum = 0, lmins = mins; + png_uint_32 i; + int v; + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + /* We temporarily increase the "minimum sum" by the factor we + * would reduce the sum of this filter, so that we can do the + * early exit comparison without scaling the sum each time. + */ + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; + i++, rp++, dp++) + { + v = *dp = *rp; + + sum += (v < 128) ? v : 256 - v; + } + for (lp = row_buf + 1; i < row_bytes; + i++, rp++, lp++, dp++) + { + v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB) + { + sumlo = (sumlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + sumhi = (sumhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + sumhi = (sumhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + mins = sum; + best_row = png_ptr->sub_row; + } + } + + /* Up filter */ + if (filter_to_do == PNG_FILTER_UP) + { + png_bytep rp, dp, pp; + png_uint_32 i; + + for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, + pp = prev_row + 1; i < row_bytes; + i++, rp++, pp++, dp++) + { + *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff); + } + best_row = png_ptr->up_row; + } + + else if (filter_to_do & PNG_FILTER_UP) + { + png_bytep rp, dp, pp; + png_uint_32 sum = 0, lmins = mins; + png_uint_32 i; + int v; + + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, + pp = prev_row + 1; i < row_bytes; i++) + { + v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + mins = sum; + best_row = png_ptr->up_row; + } + } + + /* Avg filter */ + if (filter_to_do == PNG_FILTER_AVG) + { + png_bytep rp, dp, pp, lp; + png_uint_32 i; + for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); + } + for (lp = row_buf + 1; i < row_bytes; i++) + { + *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) + & 0xff); + } + best_row = png_ptr->avg_row; + } + + else if (filter_to_do & PNG_FILTER_AVG) + { + png_bytep rp, dp, pp, lp; + png_uint_32 sum = 0, lmins = mins; + png_uint_32 i; + int v; + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_AVG) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); + + sum += (v < 128) ? v : 256 - v; + } + for (lp = row_buf + 1; i < row_bytes; i++) + { + v = *dp++ = + (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + mins = sum; + best_row = png_ptr->avg_row; + } + } + + /* Paeth filter */ + if (filter_to_do == PNG_FILTER_PAETH) + { + png_bytep rp, dp, pp, cp, lp; + png_uint_32 i; + for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); + } + + for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) + { + int a, b, c, pa, pb, pc, p; + + b = *pp++; + c = *cp++; + a = *lp++; + + p = b - c; + pc = a - c; + +#ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +#else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +#endif + + p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; + + *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); + } + best_row = png_ptr->paeth_row; + } + + else if (filter_to_do & PNG_FILTER_PAETH) + { + png_bytep rp, dp, pp, cp, lp; + png_uint_32 sum = 0, lmins = mins; + png_uint_32 i; + int v; + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); + + sum += (v < 128) ? v : 256 - v; + } + + for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) + { + int a, b, c, pa, pb, pc, p; + + b = *pp++; + c = *cp++; + a = *lp++; + +#ifndef PNG_SLOW_PAETH + p = b - c; + pc = a - c; +#ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +#else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +#endif + p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; +#else /* PNG_SLOW_PAETH */ + p = a + b - c; + pa = abs(p - a); + pb = abs(p - b); + pc = abs(p - c); + if (pa <= pb && pa <= pc) + p = a; + else if (pb <= pc) + p = b; + else + p = c; +#endif /* PNG_SLOW_PAETH */ + + v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + best_row = png_ptr->paeth_row; + } + } +#endif /* PNG_WRITE_FILTER_SUPPORTED */ + /* Do the actual writing of the filtered row data from the chosen filter. */ + + png_write_filtered_row(png_ptr, best_row); + +#ifdef PNG_WRITE_FILTER_SUPPORTED +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + /* Save the type of filter we picked this time for future calculations */ + if (png_ptr->num_prev_filters > 0) + { + int j; + for (j = 1; j < num_p_filters; j++) + { + png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1]; + } + png_ptr->prev_filters[j] = best_row[0]; + } +#endif +#endif /* PNG_WRITE_FILTER_SUPPORTED */ +} + + +/* Do the actual writing of a previously filtered row. */ +void /* PRIVATE */ +png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row) +{ + png_debug(1, "in png_write_filtered_row"); + + png_debug1(2, "filter = %d", filtered_row[0]); + /* Set up the zlib input buffer */ + + png_ptr->zstream.next_in = filtered_row; + png_ptr->zstream.avail_in = (uInt)png_ptr->row_info.rowbytes + 1; + /* Repeat until we have compressed all the data */ + do + { + int ret; /* Return of zlib */ + + /* Compress the data */ + ret = deflate(&png_ptr->zstream, Z_NO_FLUSH); + /* Check for compression errors */ + if (ret != Z_OK) + { + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + else + png_error(png_ptr, "zlib error"); + } + + /* See if it is time to write another IDAT */ + if (!(png_ptr->zstream.avail_out)) + { + /* Write the IDAT and reset the zlib output buffer */ + png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + } + /* Repeat until all data has been compressed */ + } while (png_ptr->zstream.avail_in); + + /* Swap the current and previous rows */ + if (png_ptr->prev_row != NULL) + { + png_bytep tptr; + + tptr = png_ptr->prev_row; + png_ptr->prev_row = png_ptr->row_buf; + png_ptr->row_buf = tptr; + } + + /* Finish row - updates counters and flushes zlib if last row */ + png_write_finish_row(png_ptr); + +#ifdef PNG_WRITE_FLUSH_SUPPORTED + png_ptr->flush_rows++; + + if (png_ptr->flush_dist > 0 && + png_ptr->flush_rows >= png_ptr->flush_dist) + { + png_write_flush(png_ptr); + } +#endif +} +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/reactos/dll/3rdparty/libtiff/libtiff.def b/reactos/dll/3rdparty/libtiff/libtiff.def new file mode 100644 index 00000000000..3caefd83654 --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/libtiff.def @@ -0,0 +1,140 @@ +EXPORTS TIFFOpen + TIFFOpenW + TIFFGetVersion + TIFFCleanup + TIFFClose + TIFFFlush + TIFFFlushData + TIFFGetField + TIFFVGetField + TIFFGetFieldDefaulted + TIFFVGetFieldDefaulted + TIFFGetTagListEntry + TIFFGetTagListCount + TIFFReadDirectory + TIFFScanlineSize + TIFFStripSize + TIFFVStripSize + TIFFRawStripSize + TIFFTileRowSize + TIFFTileSize + TIFFVTileSize + TIFFFileno + TIFFSetFileno + TIFFGetMode + TIFFIsTiled + TIFFIsByteSwapped + TIFFIsBigEndian + TIFFIsMSB2LSB + TIFFIsUpSampled + TIFFCIELabToRGBInit + TIFFCIELabToXYZ + TIFFXYZToRGB + TIFFYCbCrToRGBInit + TIFFYCbCrtoRGB + TIFFCurrentRow + TIFFCurrentDirectory + TIFFCurrentStrip + TIFFCurrentTile + TIFFDataWidth + TIFFReadBufferSetup + TIFFWriteBufferSetup + TIFFSetupStrips + TIFFLastDirectory + TIFFSetDirectory + TIFFSetSubDirectory + TIFFUnlinkDirectory + TIFFSetField + TIFFVSetField + TIFFCheckpointDirectory + TIFFWriteDirectory + TIFFRewriteDirectory + TIFFPrintDirectory + TIFFReadScanline + TIFFWriteScanline + TIFFReadRGBAImage + TIFFReadRGBAImageOriented + TIFFFdOpen + TIFFClientOpen + TIFFFileName + TIFFError + TIFFErrorExt + TIFFWarning + TIFFWarningExt + TIFFSetErrorHandler + TIFFSetErrorHandlerExt + TIFFSetWarningHandler + TIFFSetWarningHandlerExt + TIFFComputeTile + TIFFCheckTile + TIFFNumberOfTiles + TIFFReadTile + TIFFWriteTile + TIFFComputeStrip + TIFFNumberOfStrips + TIFFRGBAImageBegin + TIFFRGBAImageGet + TIFFRGBAImageEnd + TIFFReadEncodedStrip + TIFFReadRawStrip + TIFFReadEncodedTile + TIFFReadRawTile + TIFFReadRGBATile + TIFFReadRGBAStrip + TIFFWriteEncodedStrip + TIFFWriteRawStrip + TIFFWriteEncodedTile + TIFFWriteRawTile + TIFFSetWriteOffset + TIFFSwabDouble + TIFFSwabShort + TIFFSwabLong + TIFFSwabArrayOfShort + TIFFSwabArrayOfLong + TIFFSwabArrayOfDouble + TIFFSwabArrayOfTriples + TIFFReverseBits + TIFFGetBitRevTable + TIFFDefaultStripSize + TIFFDefaultTileSize + TIFFRasterScanlineSize + _TIFFmalloc + _TIFFrealloc + _TIFFfree + _TIFFmemset + _TIFFmemcpy + _TIFFmemcmp + TIFFCreateDirectory + TIFFSetTagExtender + TIFFMergeFieldInfo + TIFFFindFieldInfo + TIFFFindFieldInfoByName + TIFFFieldWithName + TIFFFieldWithTag + TIFFCurrentDirOffset + TIFFWriteCheck + TIFFRGBAImageOK + TIFFNumberOfDirectories + TIFFSetFileName + TIFFSetClientdata + TIFFSetMode + TIFFClientdata + TIFFGetReadProc + TIFFGetWriteProc + TIFFGetSeekProc + TIFFGetCloseProc + TIFFGetSizeProc + TIFFGetMapFileProc + TIFFGetUnmapFileProc + TIFFIsCODECConfigured + TIFFGetConfiguredCODECs + TIFFFindCODEC + TIFFRegisterCODEC + TIFFUnRegisterCODEC + TIFFFreeDirectory + TIFFReadCustomDirectory + TIFFReadEXIFDirectory + TIFFAccessTagMethods + TIFFGetClientInfo + TIFFSetClientInfo + TIFFReassignTagToIgnore diff --git a/reactos/dll/3rdparty/libtiff/libtiff.rbuild b/reactos/dll/3rdparty/libtiff/libtiff.rbuild new file mode 100644 index 00000000000..cb3ea02447a --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/libtiff.rbuild @@ -0,0 +1,50 @@ + + + + + + + + . + lib/3rdparty/zlib + user32 + zlib + mkg3states.c + tif_aux.c + tif_close.c + tif_codec.c + tif_color.c + tif_compress.c + tif_dir.c + tif_dirinfo.c + tif_dirread.c + tif_dirwrite.c + tif_dumpmode.c + tif_error.c + tif_extension.c + tif_fax3.c + tif_fax3sm.c + tif_flush.c + tif_getimage.c + tif_jbig.c + tif_jpeg.c + tif_luv.c + tif_lzw.c + tif_next.c + tif_ojpeg.c + tif_open.c + tif_packbits.c + tif_pixarlog.c + tif_predict.c + tif_print.c + tif_read.c + tif_strip.c + tif_swab.c + tif_thunder.c + tif_tile.c + tif_version.c + tif_warning.c + tif_win32.c + tif_write.c + tif_zip.c + diff --git a/reactos/dll/3rdparty/libtiff/mkg3states.c b/reactos/dll/3rdparty/libtiff/mkg3states.c new file mode 100644 index 00000000000..7f4346b7f3a --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/mkg3states.c @@ -0,0 +1,451 @@ +/* "$Id: mkg3states.c,v 1.10.2.1 2010-06-08 18:50:41 bfriesen Exp $ */ + +/* + * Copyright (c) 1991-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* Initialise fax decoder tables + * Decoder support is derived, with permission, from the code + * in Frank Cringle's viewfax program; + * Copyright (C) 1990, 1995 Frank D. Cringle. + */ +#include "tif_config.h" + +#include +#include +#include + +#ifdef HAVE_UNISTD_H +# include +#endif + +#include "tif_fax3.h" + +#ifndef HAVE_GETOPT +extern int getopt(int, char**, char*); +#endif + +#define streq(a,b) (strcmp(a,b) == 0) + +/* NB: can't use names in tif_fax3.h 'cuz they are declared const */ +TIFFFaxTabEnt MainTable[128]; +TIFFFaxTabEnt WhiteTable[4096]; +TIFFFaxTabEnt BlackTable[8192]; + +struct proto { + uint16 code; /* right justified, lsb-first, zero filled */ + uint16 val; /* (pixel count)<<4 + code width */ +}; + +static struct proto Pass[] = { +{ 0x0008, 4 }, +{ 0, 0 } +}; + +static struct proto Horiz[] = { +{ 0x0004, 3 }, +{ 0, 0 } +}; + +static struct proto V0[] = { +{ 0x0001, 1 }, +{ 0, 0 } +}; + +static struct proto VR[] = { +{ 0x0006, (1<<4)+3 }, +{ 0x0030, (2<<4)+6 }, +{ 0x0060, (3<<4)+7 }, +{ 0, 0 } +}; + +static struct proto VL[] = { +{ 0x0002, (1<<4)+3 }, +{ 0x0010, (2<<4)+6 }, +{ 0x0020, (3<<4)+7 }, +{ 0, 0 } +}; + +static struct proto Ext[] = { +{ 0x0040, 7 }, +{ 0, 0 } +}; + +static struct proto EOLV[] = { +{ 0x0000, 7 }, +{ 0, 0 } +}; + +static struct proto MakeUpW[] = { +{ 0x001b, 1029 }, +{ 0x0009, 2053 }, +{ 0x003a, 3078 }, +{ 0x0076, 4103 }, +{ 0x006c, 5128 }, +{ 0x00ec, 6152 }, +{ 0x0026, 7176 }, +{ 0x00a6, 8200 }, +{ 0x0016, 9224 }, +{ 0x00e6, 10248 }, +{ 0x0066, 11273 }, +{ 0x0166, 12297 }, +{ 0x0096, 13321 }, +{ 0x0196, 14345 }, +{ 0x0056, 15369 }, +{ 0x0156, 16393 }, +{ 0x00d6, 17417 }, +{ 0x01d6, 18441 }, +{ 0x0036, 19465 }, +{ 0x0136, 20489 }, +{ 0x00b6, 21513 }, +{ 0x01b6, 22537 }, +{ 0x0032, 23561 }, +{ 0x0132, 24585 }, +{ 0x00b2, 25609 }, +{ 0x0006, 26630 }, +{ 0x01b2, 27657 }, +{ 0, 0 } +}; + +static struct proto MakeUpB[] = { +{ 0x03c0, 1034 }, +{ 0x0130, 2060 }, +{ 0x0930, 3084 }, +{ 0x0da0, 4108 }, +{ 0x0cc0, 5132 }, +{ 0x02c0, 6156 }, +{ 0x0ac0, 7180 }, +{ 0x06c0, 8205 }, +{ 0x16c0, 9229 }, +{ 0x0a40, 10253 }, +{ 0x1a40, 11277 }, +{ 0x0640, 12301 }, +{ 0x1640, 13325 }, +{ 0x09c0, 14349 }, +{ 0x19c0, 15373 }, +{ 0x05c0, 16397 }, +{ 0x15c0, 17421 }, +{ 0x0dc0, 18445 }, +{ 0x1dc0, 19469 }, +{ 0x0940, 20493 }, +{ 0x1940, 21517 }, +{ 0x0540, 22541 }, +{ 0x1540, 23565 }, +{ 0x0b40, 24589 }, +{ 0x1b40, 25613 }, +{ 0x04c0, 26637 }, +{ 0x14c0, 27661 }, +{ 0, 0 } +}; + +static struct proto MakeUp[] = { +{ 0x0080, 28683 }, +{ 0x0180, 29707 }, +{ 0x0580, 30731 }, +{ 0x0480, 31756 }, +{ 0x0c80, 32780 }, +{ 0x0280, 33804 }, +{ 0x0a80, 34828 }, +{ 0x0680, 35852 }, +{ 0x0e80, 36876 }, +{ 0x0380, 37900 }, +{ 0x0b80, 38924 }, +{ 0x0780, 39948 }, +{ 0x0f80, 40972 }, +{ 0, 0 } +}; + +static struct proto TermW[] = { +{ 0x00ac, 8 }, +{ 0x0038, 22 }, +{ 0x000e, 36 }, +{ 0x0001, 52 }, +{ 0x000d, 68 }, +{ 0x0003, 84 }, +{ 0x0007, 100 }, +{ 0x000f, 116 }, +{ 0x0019, 133 }, +{ 0x0005, 149 }, +{ 0x001c, 165 }, +{ 0x0002, 181 }, +{ 0x0004, 198 }, +{ 0x0030, 214 }, +{ 0x000b, 230 }, +{ 0x002b, 246 }, +{ 0x0015, 262 }, +{ 0x0035, 278 }, +{ 0x0072, 295 }, +{ 0x0018, 311 }, +{ 0x0008, 327 }, +{ 0x0074, 343 }, +{ 0x0060, 359 }, +{ 0x0010, 375 }, +{ 0x000a, 391 }, +{ 0x006a, 407 }, +{ 0x0064, 423 }, +{ 0x0012, 439 }, +{ 0x000c, 455 }, +{ 0x0040, 472 }, +{ 0x00c0, 488 }, +{ 0x0058, 504 }, +{ 0x00d8, 520 }, +{ 0x0048, 536 }, +{ 0x00c8, 552 }, +{ 0x0028, 568 }, +{ 0x00a8, 584 }, +{ 0x0068, 600 }, +{ 0x00e8, 616 }, +{ 0x0014, 632 }, +{ 0x0094, 648 }, +{ 0x0054, 664 }, +{ 0x00d4, 680 }, +{ 0x0034, 696 }, +{ 0x00b4, 712 }, +{ 0x0020, 728 }, +{ 0x00a0, 744 }, +{ 0x0050, 760 }, +{ 0x00d0, 776 }, +{ 0x004a, 792 }, +{ 0x00ca, 808 }, +{ 0x002a, 824 }, +{ 0x00aa, 840 }, +{ 0x0024, 856 }, +{ 0x00a4, 872 }, +{ 0x001a, 888 }, +{ 0x009a, 904 }, +{ 0x005a, 920 }, +{ 0x00da, 936 }, +{ 0x0052, 952 }, +{ 0x00d2, 968 }, +{ 0x004c, 984 }, +{ 0x00cc, 1000 }, +{ 0x002c, 1016 }, +{ 0, 0 } +}; + +static struct proto TermB[] = { +{ 0x03b0, 10 }, +{ 0x0002, 19 }, +{ 0x0003, 34 }, +{ 0x0001, 50 }, +{ 0x0006, 67 }, +{ 0x000c, 84 }, +{ 0x0004, 100 }, +{ 0x0018, 117 }, +{ 0x0028, 134 }, +{ 0x0008, 150 }, +{ 0x0010, 167 }, +{ 0x0050, 183 }, +{ 0x0070, 199 }, +{ 0x0020, 216 }, +{ 0x00e0, 232 }, +{ 0x0030, 249 }, +{ 0x03a0, 266 }, +{ 0x0060, 282 }, +{ 0x0040, 298 }, +{ 0x0730, 315 }, +{ 0x00b0, 331 }, +{ 0x01b0, 347 }, +{ 0x0760, 363 }, +{ 0x00a0, 379 }, +{ 0x0740, 395 }, +{ 0x00c0, 411 }, +{ 0x0530, 428 }, +{ 0x0d30, 444 }, +{ 0x0330, 460 }, +{ 0x0b30, 476 }, +{ 0x0160, 492 }, +{ 0x0960, 508 }, +{ 0x0560, 524 }, +{ 0x0d60, 540 }, +{ 0x04b0, 556 }, +{ 0x0cb0, 572 }, +{ 0x02b0, 588 }, +{ 0x0ab0, 604 }, +{ 0x06b0, 620 }, +{ 0x0eb0, 636 }, +{ 0x0360, 652 }, +{ 0x0b60, 668 }, +{ 0x05b0, 684 }, +{ 0x0db0, 700 }, +{ 0x02a0, 716 }, +{ 0x0aa0, 732 }, +{ 0x06a0, 748 }, +{ 0x0ea0, 764 }, +{ 0x0260, 780 }, +{ 0x0a60, 796 }, +{ 0x04a0, 812 }, +{ 0x0ca0, 828 }, +{ 0x0240, 844 }, +{ 0x0ec0, 860 }, +{ 0x01c0, 876 }, +{ 0x0e40, 892 }, +{ 0x0140, 908 }, +{ 0x01a0, 924 }, +{ 0x09a0, 940 }, +{ 0x0d40, 956 }, +{ 0x0340, 972 }, +{ 0x05a0, 988 }, +{ 0x0660, 1004 }, +{ 0x0e60, 1020 }, +{ 0, 0 } +}; + +static struct proto EOLH[] = { +{ 0x0000, 11 }, +{ 0, 0 } +}; + +static void +FillTable(TIFFFaxTabEnt *T, int Size, struct proto *P, int State) +{ + int limit = 1 << Size; + + while (P->val) { + int width = P->val & 15; + int param = P->val >> 4; + int incr = 1 << width; + int code; + for (code = P->code; code < limit; code += incr) { + TIFFFaxTabEnt *E = T+code; + E->State = State; + E->Width = width; + E->Param = param; + } + P++; + } +} + +static char* storage_class = ""; +static char* const_class = ""; +static int packoutput = 1; +static char* prebrace = ""; +static char* postbrace = ""; + +void +WriteTable(FILE* fd, const TIFFFaxTabEnt* T, int Size, const char* name) +{ + int i; + char* sep; + + fprintf(fd, "%s %s TIFFFaxTabEnt %s[%d] = {", + storage_class, const_class, name, Size); + if (packoutput) { + sep = "\n"; + for (i = 0; i < Size; i++) { + fprintf(fd, "%s%s%d,%d,%d%s", + sep, prebrace, T->State, T->Width, (int) T->Param, postbrace); + if (((i+1) % 10) == 0) + sep = ",\n"; + else + sep = ","; + T++; + } + } else { + sep = "\n "; + for (i = 0; i < Size; i++) { + fprintf(fd, "%s%s%3d,%3d,%4d%s", + sep, prebrace, T->State, T->Width, (int) T->Param, postbrace); + if (((i+1) % 6) == 0) + sep = ",\n "; + else + sep = ","; + T++; + } + } + fprintf(fd, "\n};\n"); +} + +/* initialise the huffman code tables */ +int +main(int argc, char* argv[]) +{ + FILE* fd; + char* outputfile; + int c; + extern int optind; + extern char* optarg; + + while ((c = getopt(argc, argv, "c:s:bp")) != -1) + switch (c) { + case 'c': + const_class = optarg; + break; + case 's': + storage_class = optarg; + break; + case 'p': + packoutput = 0; + break; + case 'b': + prebrace = "{"; + postbrace = "}"; + break; + case '?': + fprintf(stderr, + "usage: %s [-c const] [-s storage] [-p] [-b] file\n", + argv[0]); + return (-1); + } + outputfile = optind < argc ? argv[optind] : "g3states.h"; + fd = fopen(outputfile, "w"); + if (fd == NULL) { + fprintf(stderr, "%s: %s: Cannot create output file.\n", + argv[0], outputfile); + return (-2); + } + FillTable(MainTable, 7, Pass, S_Pass); + FillTable(MainTable, 7, Horiz, S_Horiz); + FillTable(MainTable, 7, V0, S_V0); + FillTable(MainTable, 7, VR, S_VR); + FillTable(MainTable, 7, VL, S_VL); + FillTable(MainTable, 7, Ext, S_Ext); + FillTable(MainTable, 7, EOLV, S_EOL); + FillTable(WhiteTable, 12, MakeUpW, S_MakeUpW); + FillTable(WhiteTable, 12, MakeUp, S_MakeUp); + FillTable(WhiteTable, 12, TermW, S_TermW); + FillTable(WhiteTable, 12, EOLH, S_EOL); + FillTable(BlackTable, 13, MakeUpB, S_MakeUpB); + FillTable(BlackTable, 13, MakeUp, S_MakeUp); + FillTable(BlackTable, 13, TermB, S_TermB); + FillTable(BlackTable, 13, EOLH, S_EOL); + + fprintf(fd, "/* WARNING, this file was automatically generated by the\n"); + fprintf(fd, " mkg3states program */\n"); + fprintf(fd, "#include \"tiff.h\"\n"); + fprintf(fd, "#include \"tif_fax3.h\"\n"); + WriteTable(fd, MainTable, 128, "TIFFFaxMainTable"); + WriteTable(fd, WhiteTable, 4096, "TIFFFaxWhiteTable"); + WriteTable(fd, BlackTable, 8192, "TIFFFaxBlackTable"); + fclose(fd); + return (0); +} + +/* vim: set ts=8 sts=8 sw=8 noet: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/t4.h b/reactos/dll/3rdparty/libtiff/t4.h new file mode 100644 index 00000000000..870704ffe8a --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/t4.h @@ -0,0 +1,292 @@ +/* $Id: t4.h,v 1.1.1.1.2.1 2010-06-08 18:50:41 bfriesen Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _T4_ +#define _T4_ +/* + * CCITT T.4 1D Huffman runlength codes and + * related definitions. Given the small sizes + * of these tables it does not seem + * worthwhile to make code & length 8 bits. + */ +typedef struct tableentry { + unsigned short length; /* bit length of g3 code */ + unsigned short code; /* g3 code */ + short runlen; /* run length in bits */ +} tableentry; + +#define EOL 0x001 /* EOL code value - 0000 0000 0000 1 */ + +/* status values returned instead of a run length */ +#define G3CODE_EOL -1 /* NB: ACT_EOL - ACT_WRUNT */ +#define G3CODE_INVALID -2 /* NB: ACT_INVALID - ACT_WRUNT */ +#define G3CODE_EOF -3 /* end of input data */ +#define G3CODE_INCOMP -4 /* incomplete run code */ + +/* + * Note that these tables are ordered such that the + * index into the table is known to be either the + * run length, or (run length / 64) + a fixed offset. + * + * NB: The G3CODE_INVALID entries are only used + * during state generation (see mkg3states.c). + */ +#ifdef G3CODES +const tableentry TIFFFaxWhiteCodes[] = { + { 8, 0x35, 0 }, /* 0011 0101 */ + { 6, 0x7, 1 }, /* 0001 11 */ + { 4, 0x7, 2 }, /* 0111 */ + { 4, 0x8, 3 }, /* 1000 */ + { 4, 0xB, 4 }, /* 1011 */ + { 4, 0xC, 5 }, /* 1100 */ + { 4, 0xE, 6 }, /* 1110 */ + { 4, 0xF, 7 }, /* 1111 */ + { 5, 0x13, 8 }, /* 1001 1 */ + { 5, 0x14, 9 }, /* 1010 0 */ + { 5, 0x7, 10 }, /* 0011 1 */ + { 5, 0x8, 11 }, /* 0100 0 */ + { 6, 0x8, 12 }, /* 0010 00 */ + { 6, 0x3, 13 }, /* 0000 11 */ + { 6, 0x34, 14 }, /* 1101 00 */ + { 6, 0x35, 15 }, /* 1101 01 */ + { 6, 0x2A, 16 }, /* 1010 10 */ + { 6, 0x2B, 17 }, /* 1010 11 */ + { 7, 0x27, 18 }, /* 0100 111 */ + { 7, 0xC, 19 }, /* 0001 100 */ + { 7, 0x8, 20 }, /* 0001 000 */ + { 7, 0x17, 21 }, /* 0010 111 */ + { 7, 0x3, 22 }, /* 0000 011 */ + { 7, 0x4, 23 }, /* 0000 100 */ + { 7, 0x28, 24 }, /* 0101 000 */ + { 7, 0x2B, 25 }, /* 0101 011 */ + { 7, 0x13, 26 }, /* 0010 011 */ + { 7, 0x24, 27 }, /* 0100 100 */ + { 7, 0x18, 28 }, /* 0011 000 */ + { 8, 0x2, 29 }, /* 0000 0010 */ + { 8, 0x3, 30 }, /* 0000 0011 */ + { 8, 0x1A, 31 }, /* 0001 1010 */ + { 8, 0x1B, 32 }, /* 0001 1011 */ + { 8, 0x12, 33 }, /* 0001 0010 */ + { 8, 0x13, 34 }, /* 0001 0011 */ + { 8, 0x14, 35 }, /* 0001 0100 */ + { 8, 0x15, 36 }, /* 0001 0101 */ + { 8, 0x16, 37 }, /* 0001 0110 */ + { 8, 0x17, 38 }, /* 0001 0111 */ + { 8, 0x28, 39 }, /* 0010 1000 */ + { 8, 0x29, 40 }, /* 0010 1001 */ + { 8, 0x2A, 41 }, /* 0010 1010 */ + { 8, 0x2B, 42 }, /* 0010 1011 */ + { 8, 0x2C, 43 }, /* 0010 1100 */ + { 8, 0x2D, 44 }, /* 0010 1101 */ + { 8, 0x4, 45 }, /* 0000 0100 */ + { 8, 0x5, 46 }, /* 0000 0101 */ + { 8, 0xA, 47 }, /* 0000 1010 */ + { 8, 0xB, 48 }, /* 0000 1011 */ + { 8, 0x52, 49 }, /* 0101 0010 */ + { 8, 0x53, 50 }, /* 0101 0011 */ + { 8, 0x54, 51 }, /* 0101 0100 */ + { 8, 0x55, 52 }, /* 0101 0101 */ + { 8, 0x24, 53 }, /* 0010 0100 */ + { 8, 0x25, 54 }, /* 0010 0101 */ + { 8, 0x58, 55 }, /* 0101 1000 */ + { 8, 0x59, 56 }, /* 0101 1001 */ + { 8, 0x5A, 57 }, /* 0101 1010 */ + { 8, 0x5B, 58 }, /* 0101 1011 */ + { 8, 0x4A, 59 }, /* 0100 1010 */ + { 8, 0x4B, 60 }, /* 0100 1011 */ + { 8, 0x32, 61 }, /* 0011 0010 */ + { 8, 0x33, 62 }, /* 0011 0011 */ + { 8, 0x34, 63 }, /* 0011 0100 */ + { 5, 0x1B, 64 }, /* 1101 1 */ + { 5, 0x12, 128 }, /* 1001 0 */ + { 6, 0x17, 192 }, /* 0101 11 */ + { 7, 0x37, 256 }, /* 0110 111 */ + { 8, 0x36, 320 }, /* 0011 0110 */ + { 8, 0x37, 384 }, /* 0011 0111 */ + { 8, 0x64, 448 }, /* 0110 0100 */ + { 8, 0x65, 512 }, /* 0110 0101 */ + { 8, 0x68, 576 }, /* 0110 1000 */ + { 8, 0x67, 640 }, /* 0110 0111 */ + { 9, 0xCC, 704 }, /* 0110 0110 0 */ + { 9, 0xCD, 768 }, /* 0110 0110 1 */ + { 9, 0xD2, 832 }, /* 0110 1001 0 */ + { 9, 0xD3, 896 }, /* 0110 1001 1 */ + { 9, 0xD4, 960 }, /* 0110 1010 0 */ + { 9, 0xD5, 1024 }, /* 0110 1010 1 */ + { 9, 0xD6, 1088 }, /* 0110 1011 0 */ + { 9, 0xD7, 1152 }, /* 0110 1011 1 */ + { 9, 0xD8, 1216 }, /* 0110 1100 0 */ + { 9, 0xD9, 1280 }, /* 0110 1100 1 */ + { 9, 0xDA, 1344 }, /* 0110 1101 0 */ + { 9, 0xDB, 1408 }, /* 0110 1101 1 */ + { 9, 0x98, 1472 }, /* 0100 1100 0 */ + { 9, 0x99, 1536 }, /* 0100 1100 1 */ + { 9, 0x9A, 1600 }, /* 0100 1101 0 */ + { 6, 0x18, 1664 }, /* 0110 00 */ + { 9, 0x9B, 1728 }, /* 0100 1101 1 */ + { 11, 0x8, 1792 }, /* 0000 0001 000 */ + { 11, 0xC, 1856 }, /* 0000 0001 100 */ + { 11, 0xD, 1920 }, /* 0000 0001 101 */ + { 12, 0x12, 1984 }, /* 0000 0001 0010 */ + { 12, 0x13, 2048 }, /* 0000 0001 0011 */ + { 12, 0x14, 2112 }, /* 0000 0001 0100 */ + { 12, 0x15, 2176 }, /* 0000 0001 0101 */ + { 12, 0x16, 2240 }, /* 0000 0001 0110 */ + { 12, 0x17, 2304 }, /* 0000 0001 0111 */ + { 12, 0x1C, 2368 }, /* 0000 0001 1100 */ + { 12, 0x1D, 2432 }, /* 0000 0001 1101 */ + { 12, 0x1E, 2496 }, /* 0000 0001 1110 */ + { 12, 0x1F, 2560 }, /* 0000 0001 1111 */ + { 12, 0x1, G3CODE_EOL }, /* 0000 0000 0001 */ + { 9, 0x1, G3CODE_INVALID }, /* 0000 0000 1 */ + { 10, 0x1, G3CODE_INVALID }, /* 0000 0000 01 */ + { 11, 0x1, G3CODE_INVALID }, /* 0000 0000 001 */ + { 12, 0x0, G3CODE_INVALID }, /* 0000 0000 0000 */ +}; + +const tableentry TIFFFaxBlackCodes[] = { + { 10, 0x37, 0 }, /* 0000 1101 11 */ + { 3, 0x2, 1 }, /* 010 */ + { 2, 0x3, 2 }, /* 11 */ + { 2, 0x2, 3 }, /* 10 */ + { 3, 0x3, 4 }, /* 011 */ + { 4, 0x3, 5 }, /* 0011 */ + { 4, 0x2, 6 }, /* 0010 */ + { 5, 0x3, 7 }, /* 0001 1 */ + { 6, 0x5, 8 }, /* 0001 01 */ + { 6, 0x4, 9 }, /* 0001 00 */ + { 7, 0x4, 10 }, /* 0000 100 */ + { 7, 0x5, 11 }, /* 0000 101 */ + { 7, 0x7, 12 }, /* 0000 111 */ + { 8, 0x4, 13 }, /* 0000 0100 */ + { 8, 0x7, 14 }, /* 0000 0111 */ + { 9, 0x18, 15 }, /* 0000 1100 0 */ + { 10, 0x17, 16 }, /* 0000 0101 11 */ + { 10, 0x18, 17 }, /* 0000 0110 00 */ + { 10, 0x8, 18 }, /* 0000 0010 00 */ + { 11, 0x67, 19 }, /* 0000 1100 111 */ + { 11, 0x68, 20 }, /* 0000 1101 000 */ + { 11, 0x6C, 21 }, /* 0000 1101 100 */ + { 11, 0x37, 22 }, /* 0000 0110 111 */ + { 11, 0x28, 23 }, /* 0000 0101 000 */ + { 11, 0x17, 24 }, /* 0000 0010 111 */ + { 11, 0x18, 25 }, /* 0000 0011 000 */ + { 12, 0xCA, 26 }, /* 0000 1100 1010 */ + { 12, 0xCB, 27 }, /* 0000 1100 1011 */ + { 12, 0xCC, 28 }, /* 0000 1100 1100 */ + { 12, 0xCD, 29 }, /* 0000 1100 1101 */ + { 12, 0x68, 30 }, /* 0000 0110 1000 */ + { 12, 0x69, 31 }, /* 0000 0110 1001 */ + { 12, 0x6A, 32 }, /* 0000 0110 1010 */ + { 12, 0x6B, 33 }, /* 0000 0110 1011 */ + { 12, 0xD2, 34 }, /* 0000 1101 0010 */ + { 12, 0xD3, 35 }, /* 0000 1101 0011 */ + { 12, 0xD4, 36 }, /* 0000 1101 0100 */ + { 12, 0xD5, 37 }, /* 0000 1101 0101 */ + { 12, 0xD6, 38 }, /* 0000 1101 0110 */ + { 12, 0xD7, 39 }, /* 0000 1101 0111 */ + { 12, 0x6C, 40 }, /* 0000 0110 1100 */ + { 12, 0x6D, 41 }, /* 0000 0110 1101 */ + { 12, 0xDA, 42 }, /* 0000 1101 1010 */ + { 12, 0xDB, 43 }, /* 0000 1101 1011 */ + { 12, 0x54, 44 }, /* 0000 0101 0100 */ + { 12, 0x55, 45 }, /* 0000 0101 0101 */ + { 12, 0x56, 46 }, /* 0000 0101 0110 */ + { 12, 0x57, 47 }, /* 0000 0101 0111 */ + { 12, 0x64, 48 }, /* 0000 0110 0100 */ + { 12, 0x65, 49 }, /* 0000 0110 0101 */ + { 12, 0x52, 50 }, /* 0000 0101 0010 */ + { 12, 0x53, 51 }, /* 0000 0101 0011 */ + { 12, 0x24, 52 }, /* 0000 0010 0100 */ + { 12, 0x37, 53 }, /* 0000 0011 0111 */ + { 12, 0x38, 54 }, /* 0000 0011 1000 */ + { 12, 0x27, 55 }, /* 0000 0010 0111 */ + { 12, 0x28, 56 }, /* 0000 0010 1000 */ + { 12, 0x58, 57 }, /* 0000 0101 1000 */ + { 12, 0x59, 58 }, /* 0000 0101 1001 */ + { 12, 0x2B, 59 }, /* 0000 0010 1011 */ + { 12, 0x2C, 60 }, /* 0000 0010 1100 */ + { 12, 0x5A, 61 }, /* 0000 0101 1010 */ + { 12, 0x66, 62 }, /* 0000 0110 0110 */ + { 12, 0x67, 63 }, /* 0000 0110 0111 */ + { 10, 0xF, 64 }, /* 0000 0011 11 */ + { 12, 0xC8, 128 }, /* 0000 1100 1000 */ + { 12, 0xC9, 192 }, /* 0000 1100 1001 */ + { 12, 0x5B, 256 }, /* 0000 0101 1011 */ + { 12, 0x33, 320 }, /* 0000 0011 0011 */ + { 12, 0x34, 384 }, /* 0000 0011 0100 */ + { 12, 0x35, 448 }, /* 0000 0011 0101 */ + { 13, 0x6C, 512 }, /* 0000 0011 0110 0 */ + { 13, 0x6D, 576 }, /* 0000 0011 0110 1 */ + { 13, 0x4A, 640 }, /* 0000 0010 0101 0 */ + { 13, 0x4B, 704 }, /* 0000 0010 0101 1 */ + { 13, 0x4C, 768 }, /* 0000 0010 0110 0 */ + { 13, 0x4D, 832 }, /* 0000 0010 0110 1 */ + { 13, 0x72, 896 }, /* 0000 0011 1001 0 */ + { 13, 0x73, 960 }, /* 0000 0011 1001 1 */ + { 13, 0x74, 1024 }, /* 0000 0011 1010 0 */ + { 13, 0x75, 1088 }, /* 0000 0011 1010 1 */ + { 13, 0x76, 1152 }, /* 0000 0011 1011 0 */ + { 13, 0x77, 1216 }, /* 0000 0011 1011 1 */ + { 13, 0x52, 1280 }, /* 0000 0010 1001 0 */ + { 13, 0x53, 1344 }, /* 0000 0010 1001 1 */ + { 13, 0x54, 1408 }, /* 0000 0010 1010 0 */ + { 13, 0x55, 1472 }, /* 0000 0010 1010 1 */ + { 13, 0x5A, 1536 }, /* 0000 0010 1101 0 */ + { 13, 0x5B, 1600 }, /* 0000 0010 1101 1 */ + { 13, 0x64, 1664 }, /* 0000 0011 0010 0 */ + { 13, 0x65, 1728 }, /* 0000 0011 0010 1 */ + { 11, 0x8, 1792 }, /* 0000 0001 000 */ + { 11, 0xC, 1856 }, /* 0000 0001 100 */ + { 11, 0xD, 1920 }, /* 0000 0001 101 */ + { 12, 0x12, 1984 }, /* 0000 0001 0010 */ + { 12, 0x13, 2048 }, /* 0000 0001 0011 */ + { 12, 0x14, 2112 }, /* 0000 0001 0100 */ + { 12, 0x15, 2176 }, /* 0000 0001 0101 */ + { 12, 0x16, 2240 }, /* 0000 0001 0110 */ + { 12, 0x17, 2304 }, /* 0000 0001 0111 */ + { 12, 0x1C, 2368 }, /* 0000 0001 1100 */ + { 12, 0x1D, 2432 }, /* 0000 0001 1101 */ + { 12, 0x1E, 2496 }, /* 0000 0001 1110 */ + { 12, 0x1F, 2560 }, /* 0000 0001 1111 */ + { 12, 0x1, G3CODE_EOL }, /* 0000 0000 0001 */ + { 9, 0x1, G3CODE_INVALID }, /* 0000 0000 1 */ + { 10, 0x1, G3CODE_INVALID }, /* 0000 0000 01 */ + { 11, 0x1, G3CODE_INVALID }, /* 0000 0000 001 */ + { 12, 0x0, G3CODE_INVALID }, /* 0000 0000 0000 */ +}; +#else +extern const tableentry TIFFFaxWhiteCodes[]; +extern const tableentry TIFFFaxBlackCodes[]; +#endif +#endif /* _T4_ */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tif_aux.c b/reactos/dll/3rdparty/libtiff/tif_aux.c new file mode 100644 index 00000000000..272f0d9b682 --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tif_aux.c @@ -0,0 +1,290 @@ +/* $Id: tif_aux.c,v 1.20.2.3 2010-06-09 21:15:27 bfriesen Exp $ */ + +/* + * Copyright (c) 1991-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library. + * + * Auxiliary Support Routines. + */ +#include "tiffiop.h" +#include "tif_predict.h" +#include + +tdata_t +_TIFFCheckRealloc(TIFF* tif, tdata_t buffer, + size_t nmemb, size_t elem_size, const char* what) +{ + tdata_t cp = NULL; + tsize_t bytes = nmemb * elem_size; + + /* + * XXX: Check for integer overflow. + */ + if (nmemb && elem_size && bytes / elem_size == nmemb) + cp = _TIFFrealloc(buffer, bytes); + + if (cp == NULL) + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Failed to allocate memory for %s " + "(%ld elements of %ld bytes each)", + what,(long) nmemb, (long) elem_size); + + return cp; +} + +tdata_t +_TIFFCheckMalloc(TIFF* tif, size_t nmemb, size_t elem_size, const char* what) +{ + return _TIFFCheckRealloc(tif, NULL, nmemb, elem_size, what); +} + +static int +TIFFDefaultTransferFunction(TIFFDirectory* td) +{ + uint16 **tf = td->td_transferfunction; + tsize_t i, n, nbytes; + + tf[0] = tf[1] = tf[2] = 0; + if (td->td_bitspersample >= sizeof(tsize_t) * 8 - 2) + return 0; + + n = 1<td_bitspersample; + nbytes = n * sizeof (uint16); + if (!(tf[0] = (uint16 *)_TIFFmalloc(nbytes))) + return 0; + tf[0][0] = 0; + for (i = 1; i < n; i++) { + double t = (double)i/((double) n-1.); + tf[0][i] = (uint16)floor(65535.*pow(t, 2.2) + .5); + } + + if (td->td_samplesperpixel - td->td_extrasamples > 1) { + if (!(tf[1] = (uint16 *)_TIFFmalloc(nbytes))) + goto bad; + _TIFFmemcpy(tf[1], tf[0], nbytes); + if (!(tf[2] = (uint16 *)_TIFFmalloc(nbytes))) + goto bad; + _TIFFmemcpy(tf[2], tf[0], nbytes); + } + return 1; + +bad: + if (tf[0]) + _TIFFfree(tf[0]); + if (tf[1]) + _TIFFfree(tf[1]); + if (tf[2]) + _TIFFfree(tf[2]); + tf[0] = tf[1] = tf[2] = 0; + return 0; +} + +static int +TIFFDefaultRefBlackWhite(TIFFDirectory* td) +{ + int i; + + if (!(td->td_refblackwhite = (float *)_TIFFmalloc(6*sizeof (float)))) + return 0; + if (td->td_photometric == PHOTOMETRIC_YCBCR) { + /* + * YCbCr (Class Y) images must have the ReferenceBlackWhite + * tag set. Fix the broken images, which lacks that tag. + */ + td->td_refblackwhite[0] = 0.0F; + td->td_refblackwhite[1] = td->td_refblackwhite[3] = + td->td_refblackwhite[5] = 255.0F; + td->td_refblackwhite[2] = td->td_refblackwhite[4] = 128.0F; + } else { + /* + * Assume RGB (Class R) + */ + for (i = 0; i < 3; i++) { + td->td_refblackwhite[2*i+0] = 0; + td->td_refblackwhite[2*i+1] = + (float)((1L<td_bitspersample)-1L); + } + } + return 1; +} + +/* + * Like TIFFGetField, but return any default + * value if the tag is not present in the directory. + * + * NB: We use the value in the directory, rather than + * explcit values so that defaults exist only one + * place in the library -- in TIFFDefaultDirectory. + */ +int +TIFFVGetFieldDefaulted(TIFF* tif, ttag_t tag, va_list ap) +{ + TIFFDirectory *td = &tif->tif_dir; + + if (TIFFVGetField(tif, tag, ap)) + return (1); + switch (tag) { + case TIFFTAG_SUBFILETYPE: + *va_arg(ap, uint32 *) = td->td_subfiletype; + return (1); + case TIFFTAG_BITSPERSAMPLE: + *va_arg(ap, uint16 *) = td->td_bitspersample; + return (1); + case TIFFTAG_THRESHHOLDING: + *va_arg(ap, uint16 *) = td->td_threshholding; + return (1); + case TIFFTAG_FILLORDER: + *va_arg(ap, uint16 *) = td->td_fillorder; + return (1); + case TIFFTAG_ORIENTATION: + *va_arg(ap, uint16 *) = td->td_orientation; + return (1); + case TIFFTAG_SAMPLESPERPIXEL: + *va_arg(ap, uint16 *) = td->td_samplesperpixel; + return (1); + case TIFFTAG_ROWSPERSTRIP: + *va_arg(ap, uint32 *) = td->td_rowsperstrip; + return (1); + case TIFFTAG_MINSAMPLEVALUE: + *va_arg(ap, uint16 *) = td->td_minsamplevalue; + return (1); + case TIFFTAG_MAXSAMPLEVALUE: + *va_arg(ap, uint16 *) = td->td_maxsamplevalue; + return (1); + case TIFFTAG_PLANARCONFIG: + *va_arg(ap, uint16 *) = td->td_planarconfig; + return (1); + case TIFFTAG_RESOLUTIONUNIT: + *va_arg(ap, uint16 *) = td->td_resolutionunit; + return (1); + case TIFFTAG_PREDICTOR: + { + TIFFPredictorState* sp = (TIFFPredictorState*) tif->tif_data; + *va_arg(ap, uint16*) = (uint16) sp->predictor; + return 1; + } + case TIFFTAG_DOTRANGE: + *va_arg(ap, uint16 *) = 0; + *va_arg(ap, uint16 *) = (1<td_bitspersample)-1; + return (1); + case TIFFTAG_INKSET: + *va_arg(ap, uint16 *) = INKSET_CMYK; + return 1; + case TIFFTAG_NUMBEROFINKS: + *va_arg(ap, uint16 *) = 4; + return (1); + case TIFFTAG_EXTRASAMPLES: + *va_arg(ap, uint16 *) = td->td_extrasamples; + *va_arg(ap, uint16 **) = td->td_sampleinfo; + return (1); + case TIFFTAG_MATTEING: + *va_arg(ap, uint16 *) = + (td->td_extrasamples == 1 && + td->td_sampleinfo[0] == EXTRASAMPLE_ASSOCALPHA); + return (1); + case TIFFTAG_TILEDEPTH: + *va_arg(ap, uint32 *) = td->td_tiledepth; + return (1); + case TIFFTAG_DATATYPE: + *va_arg(ap, uint16 *) = td->td_sampleformat-1; + return (1); + case TIFFTAG_SAMPLEFORMAT: + *va_arg(ap, uint16 *) = td->td_sampleformat; + return(1); + case TIFFTAG_IMAGEDEPTH: + *va_arg(ap, uint32 *) = td->td_imagedepth; + return (1); + case TIFFTAG_YCBCRCOEFFICIENTS: + { + /* defaults are from CCIR Recommendation 601-1 */ + static float ycbcrcoeffs[] = { 0.299f, 0.587f, 0.114f }; + *va_arg(ap, float **) = ycbcrcoeffs; + return 1; + } + case TIFFTAG_YCBCRSUBSAMPLING: + *va_arg(ap, uint16 *) = td->td_ycbcrsubsampling[0]; + *va_arg(ap, uint16 *) = td->td_ycbcrsubsampling[1]; + return (1); + case TIFFTAG_YCBCRPOSITIONING: + *va_arg(ap, uint16 *) = td->td_ycbcrpositioning; + return (1); + case TIFFTAG_WHITEPOINT: + { + static float whitepoint[2]; + + /* TIFF 6.0 specification tells that it is no default + value for the WhitePoint, but AdobePhotoshop TIFF + Technical Note tells that it should be CIE D50. */ + whitepoint[0] = D50_X0 / (D50_X0 + D50_Y0 + D50_Z0); + whitepoint[1] = D50_Y0 / (D50_X0 + D50_Y0 + D50_Z0); + *va_arg(ap, float **) = whitepoint; + return 1; + } + case TIFFTAG_TRANSFERFUNCTION: + if (!td->td_transferfunction[0] && + !TIFFDefaultTransferFunction(td)) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "No space for \"TransferFunction\" tag"); + return (0); + } + *va_arg(ap, uint16 **) = td->td_transferfunction[0]; + if (td->td_samplesperpixel - td->td_extrasamples > 1) { + *va_arg(ap, uint16 **) = td->td_transferfunction[1]; + *va_arg(ap, uint16 **) = td->td_transferfunction[2]; + } + return (1); + case TIFFTAG_REFERENCEBLACKWHITE: + if (!td->td_refblackwhite && !TIFFDefaultRefBlackWhite(td)) + return (0); + *va_arg(ap, float **) = td->td_refblackwhite; + return (1); + } + return 0; +} + +/* + * Like TIFFGetField, but return any default + * value if the tag is not present in the directory. + */ +int +TIFFGetFieldDefaulted(TIFF* tif, ttag_t tag, ...) +{ + int ok; + va_list ap; + + va_start(ap, tag); + ok = TIFFVGetFieldDefaulted(tif, tag, ap); + va_end(ap); + return (ok); +} + +/* vim: set ts=8 sts=8 sw=8 noet: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tif_close.c b/reactos/dll/3rdparty/libtiff/tif_close.c new file mode 100644 index 00000000000..02591ba978f --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tif_close.c @@ -0,0 +1,126 @@ +/* $Id: tif_close.c,v 1.10.2.1 2010-06-08 18:50:41 bfriesen Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library. + */ +#include "tiffiop.h" + +/************************************************************************/ +/* TIFFCleanup() */ +/************************************************************************/ + +/** + * Auxiliary function to free the TIFF structure. Given structure will be + * completetly freed, so you should save opened file handle and pointer + * to the close procedure in external variables before calling + * _TIFFCleanup(), if you will need these ones to close the file. + * + * @param tif A TIFF pointer. + */ + +void +TIFFCleanup(TIFF* tif) +{ + if (tif->tif_mode != O_RDONLY) + /* + * Flush buffered data and directory (if dirty). + */ + TIFFFlush(tif); + (*tif->tif_cleanup)(tif); + TIFFFreeDirectory(tif); + + if (tif->tif_dirlist) + _TIFFfree(tif->tif_dirlist); + + /* Clean up client info links */ + while( tif->tif_clientinfo ) + { + TIFFClientInfoLink *link = tif->tif_clientinfo; + + tif->tif_clientinfo = link->next; + _TIFFfree( link->name ); + _TIFFfree( link ); + } + + if (tif->tif_rawdata && (tif->tif_flags&TIFF_MYBUFFER)) + _TIFFfree(tif->tif_rawdata); + if (isMapped(tif)) + TIFFUnmapFileContents(tif, tif->tif_base, tif->tif_size); + + /* Clean up custom fields */ + if (tif->tif_nfields > 0) + { + size_t i; + + for (i = 0; i < tif->tif_nfields; i++) + { + TIFFFieldInfo *fld = tif->tif_fieldinfo[i]; + if (fld->field_bit == FIELD_CUSTOM && + strncmp("Tag ", fld->field_name, 4) == 0) + { + _TIFFfree(fld->field_name); + _TIFFfree(fld); + } + } + + _TIFFfree(tif->tif_fieldinfo); + } + + _TIFFfree(tif); +} + +/************************************************************************/ +/* TIFFClose() */ +/************************************************************************/ + +/** + * Close a previously opened TIFF file. + * + * TIFFClose closes a file that was previously opened with TIFFOpen(). + * Any buffered data are flushed to the file, including the contents of + * the current directory (if modified); and all resources are reclaimed. + * + * @param tif A TIFF pointer. + */ + +void +TIFFClose(TIFF* tif) +{ + TIFFCloseProc closeproc = tif->tif_closeproc; + thandle_t fd = tif->tif_clientdata; + + TIFFCleanup(tif); + (void) (*closeproc)(fd); +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tif_codec.c b/reactos/dll/3rdparty/libtiff/tif_codec.c new file mode 100644 index 00000000000..d5c6fd1149d --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tif_codec.c @@ -0,0 +1,160 @@ +/* $Id: tif_codec.c,v 1.10.2.2 2010-06-08 18:50:41 bfriesen Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library + * + * Builtin Compression Scheme Configuration Support. + */ +#include "tiffiop.h" + +static int NotConfigured(TIFF*, int); + +#ifndef LZW_SUPPORT +#define TIFFInitLZW NotConfigured +#endif +#ifndef PACKBITS_SUPPORT +#define TIFFInitPackBits NotConfigured +#endif +#ifndef THUNDER_SUPPORT +#define TIFFInitThunderScan NotConfigured +#endif +#ifndef NEXT_SUPPORT +#define TIFFInitNeXT NotConfigured +#endif +#ifndef JPEG_SUPPORT +#define TIFFInitJPEG NotConfigured +#endif +#ifndef OJPEG_SUPPORT +#define TIFFInitOJPEG NotConfigured +#endif +#ifndef CCITT_SUPPORT +#define TIFFInitCCITTRLE NotConfigured +#define TIFFInitCCITTRLEW NotConfigured +#define TIFFInitCCITTFax3 NotConfigured +#define TIFFInitCCITTFax4 NotConfigured +#endif +#ifndef JBIG_SUPPORT +#define TIFFInitJBIG NotConfigured +#endif +#ifndef ZIP_SUPPORT +#define TIFFInitZIP NotConfigured +#endif +#ifndef PIXARLOG_SUPPORT +#define TIFFInitPixarLog NotConfigured +#endif +#ifndef LOGLUV_SUPPORT +#define TIFFInitSGILog NotConfigured +#endif + +/* + * Compression schemes statically built into the library. + */ +#ifdef VMS +const TIFFCodec _TIFFBuiltinCODECS[] = { +#else +TIFFCodec _TIFFBuiltinCODECS[] = { +#endif + { "None", COMPRESSION_NONE, TIFFInitDumpMode }, + { "LZW", COMPRESSION_LZW, TIFFInitLZW }, + { "PackBits", COMPRESSION_PACKBITS, TIFFInitPackBits }, + { "ThunderScan", COMPRESSION_THUNDERSCAN,TIFFInitThunderScan }, + { "NeXT", COMPRESSION_NEXT, TIFFInitNeXT }, + { "JPEG", COMPRESSION_JPEG, TIFFInitJPEG }, + { "Old-style JPEG", COMPRESSION_OJPEG, TIFFInitOJPEG }, + { "CCITT RLE", COMPRESSION_CCITTRLE, TIFFInitCCITTRLE }, + { "CCITT RLE/W", COMPRESSION_CCITTRLEW, TIFFInitCCITTRLEW }, + { "CCITT Group 3", COMPRESSION_CCITTFAX3, TIFFInitCCITTFax3 }, + { "CCITT Group 4", COMPRESSION_CCITTFAX4, TIFFInitCCITTFax4 }, + { "ISO JBIG", COMPRESSION_JBIG, TIFFInitJBIG }, + { "Deflate", COMPRESSION_DEFLATE, TIFFInitZIP }, + { "AdobeDeflate", COMPRESSION_ADOBE_DEFLATE , TIFFInitZIP }, + { "PixarLog", COMPRESSION_PIXARLOG, TIFFInitPixarLog }, + { "SGILog", COMPRESSION_SGILOG, TIFFInitSGILog }, + { "SGILog24", COMPRESSION_SGILOG24, TIFFInitSGILog }, + { NULL, 0, NULL } +}; + +static int +_notConfigured(TIFF* tif) +{ + const TIFFCodec* c = TIFFFindCODEC(tif->tif_dir.td_compression); + char compression_code[20]; + + sprintf( compression_code, "%d", tif->tif_dir.td_compression ); + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "%s compression support is not configured", + c ? c->name : compression_code ); + return (0); +} + +static int +NotConfigured(TIFF* tif, int scheme) +{ + (void) scheme; + + tif->tif_decodestatus = FALSE; + tif->tif_setupdecode = _notConfigured; + tif->tif_encodestatus = FALSE; + tif->tif_setupencode = _notConfigured; + return (1); +} + +/************************************************************************/ +/* TIFFIsCODECConfigured() */ +/************************************************************************/ + +/** + * Check whether we have working codec for the specific coding scheme. + * + * @return returns 1 if the codec is configured and working. Otherwise + * 0 will be returned. + */ + +int +TIFFIsCODECConfigured(uint16 scheme) +{ + const TIFFCodec* codec = TIFFFindCODEC(scheme); + + if(codec == NULL) { + return 0; + } + if(codec->init == NULL) { + return 0; + } + if(codec->init != NotConfigured){ + return 1; + } + return 0; +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tif_color.c b/reactos/dll/3rdparty/libtiff/tif_color.c new file mode 100644 index 00000000000..02eb346b06b --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tif_color.c @@ -0,0 +1,282 @@ +/* $Id: tif_color.c,v 1.12.2.1 2010-06-08 18:50:41 bfriesen Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * CIE L*a*b* to CIE XYZ and CIE XYZ to RGB conversion routines are taken + * from the VIPS library (http://www.vips.ecs.soton.ac.uk) with + * the permission of John Cupitt, the VIPS author. + */ + +/* + * TIFF Library. + * + * Color space conversion routines. + */ + +#include "tiffiop.h" +#include + +/* + * Convert color value from the CIE L*a*b* 1976 space to CIE XYZ. + */ +void +TIFFCIELabToXYZ(TIFFCIELabToRGB *cielab, uint32 l, int32 a, int32 b, + float *X, float *Y, float *Z) +{ + float L = (float)l * 100.0F / 255.0F; + float cby, tmp; + + if( L < 8.856F ) { + *Y = (L * cielab->Y0) / 903.292F; + cby = 7.787F * (*Y / cielab->Y0) + 16.0F / 116.0F; + } else { + cby = (L + 16.0F) / 116.0F; + *Y = cielab->Y0 * cby * cby * cby; + } + + tmp = (float)a / 500.0F + cby; + if( tmp < 0.2069F ) + *X = cielab->X0 * (tmp - 0.13793F) / 7.787F; + else + *X = cielab->X0 * tmp * tmp * tmp; + + tmp = cby - (float)b / 200.0F; + if( tmp < 0.2069F ) + *Z = cielab->Z0 * (tmp - 0.13793F) / 7.787F; + else + *Z = cielab->Z0 * tmp * tmp * tmp; +} + +#define RINT(R) ((uint32)((R)>0?((R)+0.5):((R)-0.5))) +/* + * Convert color value from the XYZ space to RGB. + */ +void +TIFFXYZToRGB(TIFFCIELabToRGB *cielab, float X, float Y, float Z, + uint32 *r, uint32 *g, uint32 *b) +{ + int i; + float Yr, Yg, Yb; + float *matrix = &cielab->display.d_mat[0][0]; + + /* Multiply through the matrix to get luminosity values. */ + Yr = matrix[0] * X + matrix[1] * Y + matrix[2] * Z; + Yg = matrix[3] * X + matrix[4] * Y + matrix[5] * Z; + Yb = matrix[6] * X + matrix[7] * Y + matrix[8] * Z; + + /* Clip input */ + Yr = TIFFmax(Yr, cielab->display.d_Y0R); + Yg = TIFFmax(Yg, cielab->display.d_Y0G); + Yb = TIFFmax(Yb, cielab->display.d_Y0B); + + /* Avoid overflow in case of wrong input values */ + Yr = TIFFmin(Yr, cielab->display.d_YCR); + Yg = TIFFmin(Yg, cielab->display.d_YCG); + Yb = TIFFmin(Yb, cielab->display.d_YCB); + + /* Turn luminosity to colour value. */ + i = (int)((Yr - cielab->display.d_Y0R) / cielab->rstep); + i = TIFFmin(cielab->range, i); + *r = RINT(cielab->Yr2r[i]); + + i = (int)((Yg - cielab->display.d_Y0G) / cielab->gstep); + i = TIFFmin(cielab->range, i); + *g = RINT(cielab->Yg2g[i]); + + i = (int)((Yb - cielab->display.d_Y0B) / cielab->bstep); + i = TIFFmin(cielab->range, i); + *b = RINT(cielab->Yb2b[i]); + + /* Clip output. */ + *r = TIFFmin(*r, cielab->display.d_Vrwr); + *g = TIFFmin(*g, cielab->display.d_Vrwg); + *b = TIFFmin(*b, cielab->display.d_Vrwb); +} +#undef RINT + +/* + * Allocate conversion state structures and make look_up tables for + * the Yr,Yb,Yg <=> r,g,b conversions. + */ +int +TIFFCIELabToRGBInit(TIFFCIELabToRGB* cielab, + TIFFDisplay *display, float *refWhite) +{ + int i; + double gamma; + + cielab->range = CIELABTORGB_TABLE_RANGE; + + _TIFFmemcpy(&cielab->display, display, sizeof(TIFFDisplay)); + + /* Red */ + gamma = 1.0 / cielab->display.d_gammaR ; + cielab->rstep = + (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range; + for(i = 0; i <= cielab->range; i++) { + cielab->Yr2r[i] = cielab->display.d_Vrwr + * ((float)pow((double)i / cielab->range, gamma)); + } + + /* Green */ + gamma = 1.0 / cielab->display.d_gammaG ; + cielab->gstep = + (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range; + for(i = 0; i <= cielab->range; i++) { + cielab->Yg2g[i] = cielab->display.d_Vrwg + * ((float)pow((double)i / cielab->range, gamma)); + } + + /* Blue */ + gamma = 1.0 / cielab->display.d_gammaB ; + cielab->bstep = + (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range; + for(i = 0; i <= cielab->range; i++) { + cielab->Yb2b[i] = cielab->display.d_Vrwb + * ((float)pow((double)i / cielab->range, gamma)); + } + + /* Init reference white point */ + cielab->X0 = refWhite[0]; + cielab->Y0 = refWhite[1]; + cielab->Z0 = refWhite[2]; + + return 0; +} + +/* + * Convert color value from the YCbCr space to CIE XYZ. + * The colorspace conversion algorithm comes from the IJG v5a code; + * see below for more information on how it works. + */ +#define SHIFT 16 +#define FIX(x) ((int32)((x) * (1L<(max)?(max):(f)) +#define HICLAMP(f,max) ((f)>(max)?(max):(f)) + +void +TIFFYCbCrtoRGB(TIFFYCbCrToRGB *ycbcr, uint32 Y, int32 Cb, int32 Cr, + uint32 *r, uint32 *g, uint32 *b) +{ + /* XXX: Only 8-bit YCbCr input supported for now */ + Y = HICLAMP(Y, 255), Cb = CLAMP(Cb, 0, 255), Cr = CLAMP(Cr, 0, 255); + + *r = ycbcr->clamptab[ycbcr->Y_tab[Y] + ycbcr->Cr_r_tab[Cr]]; + *g = ycbcr->clamptab[ycbcr->Y_tab[Y] + + (int)((ycbcr->Cb_g_tab[Cb] + ycbcr->Cr_g_tab[Cr]) >> SHIFT)]; + *b = ycbcr->clamptab[ycbcr->Y_tab[Y] + ycbcr->Cb_b_tab[Cb]]; +} + +/* + * Initialize the YCbCr->RGB conversion tables. The conversion + * is done according to the 6.0 spec: + * + * R = Y + Cr*(2 - 2*LumaRed) + * B = Y + Cb*(2 - 2*LumaBlue) + * G = Y + * - LumaBlue*Cb*(2-2*LumaBlue)/LumaGreen + * - LumaRed*Cr*(2-2*LumaRed)/LumaGreen + * + * To avoid floating point arithmetic the fractional constants that + * come out of the equations are represented as fixed point values + * in the range 0...2^16. We also eliminate multiplications by + * pre-calculating possible values indexed by Cb and Cr (this code + * assumes conversion is being done for 8-bit samples). + */ +int +TIFFYCbCrToRGBInit(TIFFYCbCrToRGB* ycbcr, float *luma, float *refBlackWhite) +{ + TIFFRGBValue* clamptab; + int i; + +#define LumaRed luma[0] +#define LumaGreen luma[1] +#define LumaBlue luma[2] + + clamptab = (TIFFRGBValue*)( + (tidata_t) ycbcr+TIFFroundup(sizeof (TIFFYCbCrToRGB), sizeof (long))); + _TIFFmemset(clamptab, 0, 256); /* v < 0 => 0 */ + ycbcr->clamptab = (clamptab += 256); + for (i = 0; i < 256; i++) + clamptab[i] = (TIFFRGBValue) i; + _TIFFmemset(clamptab+256, 255, 2*256); /* v > 255 => 255 */ + ycbcr->Cr_r_tab = (int*) (clamptab + 3*256); + ycbcr->Cb_b_tab = ycbcr->Cr_r_tab + 256; + ycbcr->Cr_g_tab = (int32*) (ycbcr->Cb_b_tab + 256); + ycbcr->Cb_g_tab = ycbcr->Cr_g_tab + 256; + ycbcr->Y_tab = ycbcr->Cb_g_tab + 256; + + { float f1 = 2-2*LumaRed; int32 D1 = FIX(f1); + float f2 = LumaRed*f1/LumaGreen; int32 D2 = -FIX(f2); + float f3 = 2-2*LumaBlue; int32 D3 = FIX(f3); + float f4 = LumaBlue*f3/LumaGreen; int32 D4 = -FIX(f4); + int x; + +#undef LumaBlue +#undef LumaGreen +#undef LumaRed + + /* + * i is the actual input pixel value in the range 0..255 + * Cb and Cr values are in the range -128..127 (actually + * they are in a range defined by the ReferenceBlackWhite + * tag) so there is some range shifting to do here when + * constructing tables indexed by the raw pixel data. + */ + for (i = 0, x = -128; i < 256; i++, x++) { + int32 Cr = (int32)Code2V(x, refBlackWhite[4] - 128.0F, + refBlackWhite[5] - 128.0F, 127); + int32 Cb = (int32)Code2V(x, refBlackWhite[2] - 128.0F, + refBlackWhite[3] - 128.0F, 127); + + ycbcr->Cr_r_tab[i] = (int32)((D1*Cr + ONE_HALF)>>SHIFT); + ycbcr->Cb_b_tab[i] = (int32)((D3*Cb + ONE_HALF)>>SHIFT); + ycbcr->Cr_g_tab[i] = D2*Cr; + ycbcr->Cb_g_tab[i] = D4*Cb + ONE_HALF; + ycbcr->Y_tab[i] = + (int32)Code2V(x + 128, refBlackWhite[0], refBlackWhite[1], 255); + } + } + + return 0; +} +#undef HICLAMP +#undef CLAMP +#undef Code2V +#undef SHIFT +#undef ONE_HALF +#undef FIX + +/* vim: set ts=8 sts=8 sw=8 noet: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tif_compress.c b/reactos/dll/3rdparty/libtiff/tif_compress.c new file mode 100644 index 00000000000..0ce509b0bd8 --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tif_compress.c @@ -0,0 +1,295 @@ +/* $Id: tif_compress.c,v 1.13.2.1 2010-06-08 18:50:41 bfriesen Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library + * + * Compression Scheme Configuration Support. + */ +#include "tiffiop.h" + +static int +TIFFNoEncode(TIFF* tif, const char* method) +{ + const TIFFCodec* c = TIFFFindCODEC(tif->tif_dir.td_compression); + + if (c) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "%s %s encoding is not implemented", + c->name, method); + } else { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Compression scheme %u %s encoding is not implemented", + tif->tif_dir.td_compression, method); + } + return (-1); +} + +int +_TIFFNoRowEncode(TIFF* tif, tidata_t pp, tsize_t cc, tsample_t s) +{ + (void) pp; (void) cc; (void) s; + return (TIFFNoEncode(tif, "scanline")); +} + +int +_TIFFNoStripEncode(TIFF* tif, tidata_t pp, tsize_t cc, tsample_t s) +{ + (void) pp; (void) cc; (void) s; + return (TIFFNoEncode(tif, "strip")); +} + +int +_TIFFNoTileEncode(TIFF* tif, tidata_t pp, tsize_t cc, tsample_t s) +{ + (void) pp; (void) cc; (void) s; + return (TIFFNoEncode(tif, "tile")); +} + +static int +TIFFNoDecode(TIFF* tif, const char* method) +{ + const TIFFCodec* c = TIFFFindCODEC(tif->tif_dir.td_compression); + + if (c) + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "%s %s decoding is not implemented", + c->name, method); + else + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Compression scheme %u %s decoding is not implemented", + tif->tif_dir.td_compression, method); + return (-1); +} + +int +_TIFFNoRowDecode(TIFF* tif, tidata_t pp, tsize_t cc, tsample_t s) +{ + (void) pp; (void) cc; (void) s; + return (TIFFNoDecode(tif, "scanline")); +} + +int +_TIFFNoStripDecode(TIFF* tif, tidata_t pp, tsize_t cc, tsample_t s) +{ + (void) pp; (void) cc; (void) s; + return (TIFFNoDecode(tif, "strip")); +} + +int +_TIFFNoTileDecode(TIFF* tif, tidata_t pp, tsize_t cc, tsample_t s) +{ + (void) pp; (void) cc; (void) s; + return (TIFFNoDecode(tif, "tile")); +} + +int +_TIFFNoSeek(TIFF* tif, uint32 off) +{ + (void) off; + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Compression algorithm does not support random access"); + return (0); +} + +int +_TIFFNoPreCode(TIFF* tif, tsample_t s) +{ + (void) tif; (void) s; + return (1); +} + +static int _TIFFtrue(TIFF* tif) { (void) tif; return (1); } +static void _TIFFvoid(TIFF* tif) { (void) tif; } + +void +_TIFFSetDefaultCompressionState(TIFF* tif) +{ + tif->tif_decodestatus = TRUE; + tif->tif_setupdecode = _TIFFtrue; + tif->tif_predecode = _TIFFNoPreCode; + tif->tif_decoderow = _TIFFNoRowDecode; + tif->tif_decodestrip = _TIFFNoStripDecode; + tif->tif_decodetile = _TIFFNoTileDecode; + tif->tif_encodestatus = TRUE; + tif->tif_setupencode = _TIFFtrue; + tif->tif_preencode = _TIFFNoPreCode; + tif->tif_postencode = _TIFFtrue; + tif->tif_encoderow = _TIFFNoRowEncode; + tif->tif_encodestrip = _TIFFNoStripEncode; + tif->tif_encodetile = _TIFFNoTileEncode; + tif->tif_close = _TIFFvoid; + tif->tif_seek = _TIFFNoSeek; + tif->tif_cleanup = _TIFFvoid; + tif->tif_defstripsize = _TIFFDefaultStripSize; + tif->tif_deftilesize = _TIFFDefaultTileSize; + tif->tif_flags &= ~(TIFF_NOBITREV|TIFF_NOREADRAW); +} + +int +TIFFSetCompressionScheme(TIFF* tif, int scheme) +{ + const TIFFCodec *c = TIFFFindCODEC((uint16) scheme); + + _TIFFSetDefaultCompressionState(tif); + /* + * Don't treat an unknown compression scheme as an error. + * This permits applications to open files with data that + * the library does not have builtin support for, but which + * may still be meaningful. + */ + return (c ? (*c->init)(tif, scheme) : 1); +} + +/* + * Other compression schemes may be registered. Registered + * schemes can also override the builtin versions provided + * by this library. + */ +typedef struct _codec { + struct _codec* next; + TIFFCodec* info; +} codec_t; +static codec_t* registeredCODECS = NULL; + +const TIFFCodec* +TIFFFindCODEC(uint16 scheme) +{ + const TIFFCodec* c; + codec_t* cd; + + for (cd = registeredCODECS; cd; cd = cd->next) + if (cd->info->scheme == scheme) + return ((const TIFFCodec*) cd->info); + for (c = _TIFFBuiltinCODECS; c->name; c++) + if (c->scheme == scheme) + return (c); + return ((const TIFFCodec*) 0); +} + +TIFFCodec* +TIFFRegisterCODEC(uint16 scheme, const char* name, TIFFInitMethod init) +{ + codec_t* cd = (codec_t*) + _TIFFmalloc(sizeof (codec_t) + sizeof (TIFFCodec) + strlen(name)+1); + + if (cd != NULL) { + cd->info = (TIFFCodec*) ((tidata_t) cd + sizeof (codec_t)); + cd->info->name = (char*) + ((tidata_t) cd->info + sizeof (TIFFCodec)); + strcpy(cd->info->name, name); + cd->info->scheme = scheme; + cd->info->init = init; + cd->next = registeredCODECS; + registeredCODECS = cd; + } else { + TIFFErrorExt(0, "TIFFRegisterCODEC", + "No space to register compression scheme %s", name); + return NULL; + } + return (cd->info); +} + +void +TIFFUnRegisterCODEC(TIFFCodec* c) +{ + codec_t* cd; + codec_t** pcd; + + for (pcd = ®isteredCODECS; (cd = *pcd); pcd = &cd->next) + if (cd->info == c) { + *pcd = cd->next; + _TIFFfree(cd); + return; + } + TIFFErrorExt(0, "TIFFUnRegisterCODEC", + "Cannot remove compression scheme %s; not registered", c->name); +} + +/************************************************************************/ +/* TIFFGetConfisuredCODECs() */ +/************************************************************************/ + +/** + * Get list of configured codecs, both built-in and registered by user. + * Caller is responsible to free this structure. + * + * @return returns array of TIFFCodec records (the last record should be NULL) + * or NULL if function failed. + */ + +TIFFCodec* +TIFFGetConfiguredCODECs() +{ + int i = 1; + codec_t *cd; + const TIFFCodec *c; + TIFFCodec *codecs = NULL, *new_codecs; + + for (cd = registeredCODECS; cd; cd = cd->next) { + new_codecs = (TIFFCodec *) + _TIFFrealloc(codecs, i * sizeof(TIFFCodec)); + if (!new_codecs) { + _TIFFfree (codecs); + return NULL; + } + codecs = new_codecs; + _TIFFmemcpy(codecs + i - 1, cd, sizeof(TIFFCodec)); + i++; + } + for (c = _TIFFBuiltinCODECS; c->name; c++) { + if (TIFFIsCODECConfigured(c->scheme)) { + new_codecs = (TIFFCodec *) + _TIFFrealloc(codecs, i * sizeof(TIFFCodec)); + if (!new_codecs) { + _TIFFfree (codecs); + return NULL; + } + codecs = new_codecs; + _TIFFmemcpy(codecs + i - 1, (const tdata_t)c, sizeof(TIFFCodec)); + i++; + } + } + + new_codecs = (TIFFCodec *) _TIFFrealloc(codecs, i * sizeof(TIFFCodec)); + if (!new_codecs) { + _TIFFfree (codecs); + return NULL; + } + codecs = new_codecs; + _TIFFmemset(codecs + i - 1, 0, sizeof(TIFFCodec)); + + return codecs; +} + +/* vim: set ts=8 sts=8 sw=8 noet: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tif_config.h b/reactos/dll/3rdparty/libtiff/tif_config.h new file mode 100644 index 00000000000..4dd77dd8cf1 --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tif_config.h @@ -0,0 +1,63 @@ +/* Define to 1 if you have the header file. */ +#define HAVE_ASSERT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define as 0 or 1 according to the floating point format suported by the + machine */ +#define HAVE_IEEEFP 1 + +/* Define to 1 if you have the `jbg_newlen' function. */ +#define HAVE_JBG_NEWLEN 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_IO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SEARCH_H 1 + +/* Define to 1 if you have the `setmode' function. */ +#define HAVE_SETMODE 1 + +/* The size of a `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of a `long', as computed by sizeof. */ +#define SIZEOF_LONG 4 + +/* Signed 64-bit type */ +#define TIFF_INT64_T signed __int64 + +/* Unsigned 64-bit type */ +#define TIFF_UINT64_T unsigned __int64 + +/* Set the native cpu bit order */ +#define HOST_FILLORDER FILLORDER_LSB2MSB + +/* Define to 1 if your processor stores words with the most significant byte + first (like Motorola and SPARC, unlike Intel and VAX). */ +/* #undef WORDS_BIGENDIAN */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +# ifndef inline +# define inline __inline +# endif +#endif + +#define lfind _lfind +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tif_config.vc.h b/reactos/dll/3rdparty/libtiff/tif_config.vc.h new file mode 100644 index 00000000000..4dd77dd8cf1 --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tif_config.vc.h @@ -0,0 +1,63 @@ +/* Define to 1 if you have the header file. */ +#define HAVE_ASSERT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define as 0 or 1 according to the floating point format suported by the + machine */ +#define HAVE_IEEEFP 1 + +/* Define to 1 if you have the `jbg_newlen' function. */ +#define HAVE_JBG_NEWLEN 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_IO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SEARCH_H 1 + +/* Define to 1 if you have the `setmode' function. */ +#define HAVE_SETMODE 1 + +/* The size of a `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of a `long', as computed by sizeof. */ +#define SIZEOF_LONG 4 + +/* Signed 64-bit type */ +#define TIFF_INT64_T signed __int64 + +/* Unsigned 64-bit type */ +#define TIFF_UINT64_T unsigned __int64 + +/* Set the native cpu bit order */ +#define HOST_FILLORDER FILLORDER_LSB2MSB + +/* Define to 1 if your processor stores words with the most significant byte + first (like Motorola and SPARC, unlike Intel and VAX). */ +/* #undef WORDS_BIGENDIAN */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +# ifndef inline +# define inline __inline +# endif +#endif + +#define lfind _lfind +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tif_dir.c b/reactos/dll/3rdparty/libtiff/tif_dir.c new file mode 100644 index 00000000000..ac44b381f8b --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tif_dir.c @@ -0,0 +1,1389 @@ +/* $Id: tif_dir.c,v 1.75.2.5 2010-06-09 21:15:27 bfriesen Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library. + * + * Directory Tag Get & Set Routines. + * (and also some miscellaneous stuff) + */ +#include "tiffiop.h" + +/* + * These are used in the backwards compatibility code... + */ +#define DATATYPE_VOID 0 /* !untyped data */ +#define DATATYPE_INT 1 /* !signed integer data */ +#define DATATYPE_UINT 2 /* !unsigned integer data */ +#define DATATYPE_IEEEFP 3 /* !IEEE floating point data */ + +static void +setByteArray(void** vpp, void* vp, size_t nmemb, size_t elem_size) +{ + if (*vpp) + _TIFFfree(*vpp), *vpp = 0; + if (vp) { + tsize_t bytes = nmemb * elem_size; + if (elem_size && bytes / elem_size == nmemb) + *vpp = (void*) _TIFFmalloc(bytes); + if (*vpp) + _TIFFmemcpy(*vpp, vp, bytes); + } +} +void _TIFFsetByteArray(void** vpp, void* vp, uint32 n) + { setByteArray(vpp, vp, n, 1); } +void _TIFFsetString(char** cpp, char* cp) + { setByteArray((void**) cpp, (void*) cp, strlen(cp)+1, 1); } +void _TIFFsetNString(char** cpp, char* cp, uint32 n) + { setByteArray((void**) cpp, (void*) cp, n, 1); } +void _TIFFsetShortArray(uint16** wpp, uint16* wp, uint32 n) + { setByteArray((void**) wpp, (void*) wp, n, sizeof (uint16)); } +void _TIFFsetLongArray(uint32** lpp, uint32* lp, uint32 n) + { setByteArray((void**) lpp, (void*) lp, n, sizeof (uint32)); } +void _TIFFsetFloatArray(float** fpp, float* fp, uint32 n) + { setByteArray((void**) fpp, (void*) fp, n, sizeof (float)); } +void _TIFFsetDoubleArray(double** dpp, double* dp, uint32 n) + { setByteArray((void**) dpp, (void*) dp, n, sizeof (double)); } + +/* + * Install extra samples information. + */ +static int +setExtraSamples(TIFFDirectory* td, va_list ap, uint32* v) +{ +/* XXX: Unassociated alpha data == 999 is a known Corel Draw bug, see below */ +#define EXTRASAMPLE_COREL_UNASSALPHA 999 + + uint16* va; + uint32 i; + + *v = va_arg(ap, uint32); + if ((uint16) *v > td->td_samplesperpixel) + return 0; + va = va_arg(ap, uint16*); + if (*v > 0 && va == NULL) /* typically missing param */ + return 0; + for (i = 0; i < *v; i++) { + if (va[i] > EXTRASAMPLE_UNASSALPHA) { + /* + * XXX: Corel Draw is known to produce incorrect + * ExtraSamples tags which must be patched here if we + * want to be able to open some of the damaged TIFF + * files: + */ + if (va[i] == EXTRASAMPLE_COREL_UNASSALPHA) + va[i] = EXTRASAMPLE_UNASSALPHA; + else + return 0; + } + } + td->td_extrasamples = (uint16) *v; + _TIFFsetShortArray(&td->td_sampleinfo, va, td->td_extrasamples); + return 1; + +#undef EXTRASAMPLE_COREL_UNASSALPHA +} + +static uint32 +checkInkNamesString(TIFF* tif, uint32 slen, const char* s) +{ + TIFFDirectory* td = &tif->tif_dir; + uint16 i = td->td_samplesperpixel; + + if (slen > 0) { + const char* ep = s+slen; + const char* cp = s; + for (; i > 0; i--) { + for (; *cp != '\0'; cp++) + if (cp >= ep) + goto bad; + cp++; /* skip \0 */ + } + return (cp-s); + } +bad: + TIFFErrorExt(tif->tif_clientdata, "TIFFSetField", + "%s: Invalid InkNames value; expecting %d names, found %d", + tif->tif_name, + td->td_samplesperpixel, + td->td_samplesperpixel-i); + return (0); +} + +static int +_TIFFVSetField(TIFF* tif, ttag_t tag, va_list ap) +{ + static const char module[] = "_TIFFVSetField"; + + TIFFDirectory* td = &tif->tif_dir; + int status = 1; + uint32 v32, i, v; + char* s; + + switch (tag) { + case TIFFTAG_SUBFILETYPE: + td->td_subfiletype = va_arg(ap, uint32); + break; + case TIFFTAG_IMAGEWIDTH: + td->td_imagewidth = va_arg(ap, uint32); + break; + case TIFFTAG_IMAGELENGTH: + td->td_imagelength = va_arg(ap, uint32); + break; + case TIFFTAG_BITSPERSAMPLE: + td->td_bitspersample = (uint16) va_arg(ap, int); + /* + * If the data require post-decoding processing to byte-swap + * samples, set it up here. Note that since tags are required + * to be ordered, compression code can override this behaviour + * in the setup method if it wants to roll the post decoding + * work in with its normal work. + */ + if (tif->tif_flags & TIFF_SWAB) { + if (td->td_bitspersample == 16) + tif->tif_postdecode = _TIFFSwab16BitData; + else if (td->td_bitspersample == 24) + tif->tif_postdecode = _TIFFSwab24BitData; + else if (td->td_bitspersample == 32) + tif->tif_postdecode = _TIFFSwab32BitData; + else if (td->td_bitspersample == 64) + tif->tif_postdecode = _TIFFSwab64BitData; + else if (td->td_bitspersample == 128) /* two 64's */ + tif->tif_postdecode = _TIFFSwab64BitData; + } + break; + case TIFFTAG_COMPRESSION: + v = va_arg(ap, uint32) & 0xffff; + /* + * If we're changing the compression scheme, the notify the + * previous module so that it can cleanup any state it's + * setup. + */ + if (TIFFFieldSet(tif, FIELD_COMPRESSION)) { + if (td->td_compression == v) + break; + (*tif->tif_cleanup)(tif); + tif->tif_flags &= ~TIFF_CODERSETUP; + } + /* + * Setup new compression routine state. + */ + if( (status = TIFFSetCompressionScheme(tif, v)) != 0 ) + td->td_compression = (uint16) v; + else + status = 0; + break; + case TIFFTAG_PHOTOMETRIC: + td->td_photometric = (uint16) va_arg(ap, int); + break; + case TIFFTAG_THRESHHOLDING: + td->td_threshholding = (uint16) va_arg(ap, int); + break; + case TIFFTAG_FILLORDER: + v = va_arg(ap, uint32); + if (v != FILLORDER_LSB2MSB && v != FILLORDER_MSB2LSB) + goto badvalue; + td->td_fillorder = (uint16) v; + break; + case TIFFTAG_ORIENTATION: + v = va_arg(ap, uint32); + if (v < ORIENTATION_TOPLEFT || ORIENTATION_LEFTBOT < v) + goto badvalue; + else + td->td_orientation = (uint16) v; + break; + case TIFFTAG_SAMPLESPERPIXEL: + /* XXX should cross check -- e.g. if pallette, then 1 */ + v = va_arg(ap, uint32); + if (v == 0) + goto badvalue; + td->td_samplesperpixel = (uint16) v; + break; + case TIFFTAG_ROWSPERSTRIP: + v32 = va_arg(ap, uint32); + if (v32 == 0) + goto badvalue32; + td->td_rowsperstrip = v32; + if (!TIFFFieldSet(tif, FIELD_TILEDIMENSIONS)) { + td->td_tilelength = v32; + td->td_tilewidth = td->td_imagewidth; + } + break; + case TIFFTAG_MINSAMPLEVALUE: + td->td_minsamplevalue = (uint16) va_arg(ap, int); + break; + case TIFFTAG_MAXSAMPLEVALUE: + td->td_maxsamplevalue = (uint16) va_arg(ap, int); + break; + case TIFFTAG_SMINSAMPLEVALUE: + td->td_sminsamplevalue = va_arg(ap, double); + break; + case TIFFTAG_SMAXSAMPLEVALUE: + td->td_smaxsamplevalue = va_arg(ap, double); + break; + case TIFFTAG_XRESOLUTION: + td->td_xresolution = (float) va_arg(ap, double); + break; + case TIFFTAG_YRESOLUTION: + td->td_yresolution = (float) va_arg(ap, double); + break; + case TIFFTAG_PLANARCONFIG: + v = va_arg(ap, uint32); + if (v != PLANARCONFIG_CONTIG && v != PLANARCONFIG_SEPARATE) + goto badvalue; + td->td_planarconfig = (uint16) v; + break; + case TIFFTAG_XPOSITION: + td->td_xposition = (float) va_arg(ap, double); + break; + case TIFFTAG_YPOSITION: + td->td_yposition = (float) va_arg(ap, double); + break; + case TIFFTAG_RESOLUTIONUNIT: + v = va_arg(ap, uint32); + if (v < RESUNIT_NONE || RESUNIT_CENTIMETER < v) + goto badvalue; + td->td_resolutionunit = (uint16) v; + break; + case TIFFTAG_PAGENUMBER: + td->td_pagenumber[0] = (uint16) va_arg(ap, int); + td->td_pagenumber[1] = (uint16) va_arg(ap, int); + break; + case TIFFTAG_HALFTONEHINTS: + td->td_halftonehints[0] = (uint16) va_arg(ap, int); + td->td_halftonehints[1] = (uint16) va_arg(ap, int); + break; + case TIFFTAG_COLORMAP: + v32 = (uint32)(1L<td_bitspersample); + _TIFFsetShortArray(&td->td_colormap[0], va_arg(ap, uint16*), v32); + _TIFFsetShortArray(&td->td_colormap[1], va_arg(ap, uint16*), v32); + _TIFFsetShortArray(&td->td_colormap[2], va_arg(ap, uint16*), v32); + break; + case TIFFTAG_EXTRASAMPLES: + if (!setExtraSamples(td, ap, &v)) + goto badvalue; + break; + case TIFFTAG_MATTEING: + td->td_extrasamples = (uint16) (va_arg(ap, int) != 0); + if (td->td_extrasamples) { + uint16 sv = EXTRASAMPLE_ASSOCALPHA; + _TIFFsetShortArray(&td->td_sampleinfo, &sv, 1); + } + break; + case TIFFTAG_TILEWIDTH: + v32 = va_arg(ap, uint32); + if (v32 % 16) { + if (tif->tif_mode != O_RDONLY) + goto badvalue32; + TIFFWarningExt(tif->tif_clientdata, tif->tif_name, + "Nonstandard tile width %d, convert file", v32); + } + td->td_tilewidth = v32; + tif->tif_flags |= TIFF_ISTILED; + break; + case TIFFTAG_TILELENGTH: + v32 = va_arg(ap, uint32); + if (v32 % 16) { + if (tif->tif_mode != O_RDONLY) + goto badvalue32; + TIFFWarningExt(tif->tif_clientdata, tif->tif_name, + "Nonstandard tile length %d, convert file", v32); + } + td->td_tilelength = v32; + tif->tif_flags |= TIFF_ISTILED; + break; + case TIFFTAG_TILEDEPTH: + v32 = va_arg(ap, uint32); + if (v32 == 0) + goto badvalue32; + td->td_tiledepth = v32; + break; + case TIFFTAG_DATATYPE: + v = va_arg(ap, uint32); + switch (v) { + case DATATYPE_VOID: v = SAMPLEFORMAT_VOID; break; + case DATATYPE_INT: v = SAMPLEFORMAT_INT; break; + case DATATYPE_UINT: v = SAMPLEFORMAT_UINT; break; + case DATATYPE_IEEEFP: v = SAMPLEFORMAT_IEEEFP;break; + default: goto badvalue; + } + td->td_sampleformat = (uint16) v; + break; + case TIFFTAG_SAMPLEFORMAT: + v = va_arg(ap, uint32); + if (v < SAMPLEFORMAT_UINT || SAMPLEFORMAT_COMPLEXIEEEFP < v) + goto badvalue; + td->td_sampleformat = (uint16) v; + + /* Try to fix up the SWAB function for complex data. */ + if( td->td_sampleformat == SAMPLEFORMAT_COMPLEXINT + && td->td_bitspersample == 32 + && tif->tif_postdecode == _TIFFSwab32BitData ) + tif->tif_postdecode = _TIFFSwab16BitData; + else if( (td->td_sampleformat == SAMPLEFORMAT_COMPLEXINT + || td->td_sampleformat == SAMPLEFORMAT_COMPLEXIEEEFP) + && td->td_bitspersample == 64 + && tif->tif_postdecode == _TIFFSwab64BitData ) + tif->tif_postdecode = _TIFFSwab32BitData; + break; + case TIFFTAG_IMAGEDEPTH: + td->td_imagedepth = va_arg(ap, uint32); + break; + case TIFFTAG_SUBIFD: + if ((tif->tif_flags & TIFF_INSUBIFD) == 0) { + td->td_nsubifd = (uint16) va_arg(ap, int); + _TIFFsetLongArray(&td->td_subifd, va_arg(ap, uint32*), + (long) td->td_nsubifd); + } else { + TIFFErrorExt(tif->tif_clientdata, module, + "%s: Sorry, cannot nest SubIFDs", + tif->tif_name); + status = 0; + } + break; + case TIFFTAG_YCBCRPOSITIONING: + td->td_ycbcrpositioning = (uint16) va_arg(ap, int); + break; + case TIFFTAG_YCBCRSUBSAMPLING: + td->td_ycbcrsubsampling[0] = (uint16) va_arg(ap, int); + td->td_ycbcrsubsampling[1] = (uint16) va_arg(ap, int); + break; + case TIFFTAG_TRANSFERFUNCTION: + v = (td->td_samplesperpixel - td->td_extrasamples) > 1 ? 3 : 1; + for (i = 0; i < v; i++) + _TIFFsetShortArray(&td->td_transferfunction[i], + va_arg(ap, uint16*), 1L<td_bitspersample); + break; + case TIFFTAG_REFERENCEBLACKWHITE: + /* XXX should check for null range */ + _TIFFsetFloatArray(&td->td_refblackwhite, va_arg(ap, float*), 6); + break; + case TIFFTAG_INKNAMES: + v = va_arg(ap, uint32); + s = va_arg(ap, char*); + v = checkInkNamesString(tif, v, s); + status = v > 0; + if( v > 0 ) { + _TIFFsetNString(&td->td_inknames, s, v); + td->td_inknameslen = v; + } + break; + default: { + TIFFTagValue *tv; + int tv_size, iCustom; + const TIFFFieldInfo* fip = _TIFFFindFieldInfo(tif, tag, TIFF_ANY); + + /* + * This can happen if multiple images are open with different + * codecs which have private tags. The global tag information + * table may then have tags that are valid for one file but not + * the other. If the client tries to set a tag that is not valid + * for the image's codec then we'll arrive here. This + * happens, for example, when tiffcp is used to convert between + * compression schemes and codec-specific tags are blindly copied. + */ + if(fip == NULL || fip->field_bit != FIELD_CUSTOM) { + TIFFErrorExt(tif->tif_clientdata, module, + "%s: Invalid %stag \"%s\" (not supported by codec)", + tif->tif_name, isPseudoTag(tag) ? "pseudo-" : "", + fip ? fip->field_name : "Unknown"); + status = 0; + break; + } + + /* + * Find the existing entry for this custom value. + */ + tv = NULL; + for (iCustom = 0; iCustom < td->td_customValueCount; iCustom++) { + if (td->td_customValues[iCustom].info->field_tag == tag) { + tv = td->td_customValues + iCustom; + if (tv->value != NULL) { + _TIFFfree(tv->value); + tv->value = NULL; + } + break; + } + } + + /* + * Grow the custom list if the entry was not found. + */ + if(tv == NULL) { + TIFFTagValue *new_customValues; + + td->td_customValueCount++; + new_customValues = (TIFFTagValue *) + _TIFFrealloc(td->td_customValues, + sizeof(TIFFTagValue) * td->td_customValueCount); + if (!new_customValues) { + TIFFErrorExt(tif->tif_clientdata, module, + "%s: Failed to allocate space for list of custom values", + tif->tif_name); + status = 0; + goto end; + } + + td->td_customValues = new_customValues; + + tv = td->td_customValues + (td->td_customValueCount - 1); + tv->info = fip; + tv->value = NULL; + tv->count = 0; + } + + /* + * Set custom value ... save a copy of the custom tag value. + */ + tv_size = _TIFFDataSize(fip->field_type); + if (tv_size == 0) { + status = 0; + TIFFErrorExt(tif->tif_clientdata, module, + "%s: Bad field type %d for \"%s\"", + tif->tif_name, fip->field_type, + fip->field_name); + goto end; + } + + if(fip->field_passcount) { + if (fip->field_writecount == TIFF_VARIABLE2) + tv->count = (uint32) va_arg(ap, uint32); + else + tv->count = (int) va_arg(ap, int); + } else if (fip->field_writecount == TIFF_VARIABLE + || fip->field_writecount == TIFF_VARIABLE2) + tv->count = 1; + else if (fip->field_writecount == TIFF_SPP) + tv->count = td->td_samplesperpixel; + else + tv->count = fip->field_writecount; + + + if (fip->field_type == TIFF_ASCII) + _TIFFsetString((char **)&tv->value, va_arg(ap, char *)); + else { + tv->value = _TIFFCheckMalloc(tif, tv_size, tv->count, + "Tag Value"); + if (!tv->value) { + status = 0; + goto end; + } + + if ((fip->field_passcount + || fip->field_writecount == TIFF_VARIABLE + || fip->field_writecount == TIFF_VARIABLE2 + || fip->field_writecount == TIFF_SPP + || tv->count > 1) + && fip->field_tag != TIFFTAG_PAGENUMBER + && fip->field_tag != TIFFTAG_HALFTONEHINTS + && fip->field_tag != TIFFTAG_YCBCRSUBSAMPLING + && fip->field_tag != TIFFTAG_DOTRANGE) { + _TIFFmemcpy(tv->value, va_arg(ap, void *), + tv->count * tv_size); + } else { + /* + * XXX: The following loop required to handle + * TIFFTAG_PAGENUMBER, TIFFTAG_HALFTONEHINTS, + * TIFFTAG_YCBCRSUBSAMPLING and TIFFTAG_DOTRANGE tags. + * These tags are actually arrays and should be passed as + * array pointers to TIFFSetField() function, but actually + * passed as a list of separate values. This behaviour + * must be changed in the future! + */ + int i; + char *val = (char *)tv->value; + + for (i = 0; i < tv->count; i++, val += tv_size) { + switch (fip->field_type) { + case TIFF_BYTE: + case TIFF_UNDEFINED: + { + uint8 v = (uint8)va_arg(ap, int); + _TIFFmemcpy(val, &v, tv_size); + } + break; + case TIFF_SBYTE: + { + int8 v = (int8)va_arg(ap, int); + _TIFFmemcpy(val, &v, tv_size); + } + break; + case TIFF_SHORT: + { + uint16 v = (uint16)va_arg(ap, int); + _TIFFmemcpy(val, &v, tv_size); + } + break; + case TIFF_SSHORT: + { + int16 v = (int16)va_arg(ap, int); + _TIFFmemcpy(val, &v, tv_size); + } + break; + case TIFF_LONG: + case TIFF_IFD: + { + uint32 v = va_arg(ap, uint32); + _TIFFmemcpy(val, &v, tv_size); + } + break; + case TIFF_SLONG: + { + int32 v = va_arg(ap, int32); + _TIFFmemcpy(val, &v, tv_size); + } + break; + case TIFF_RATIONAL: + case TIFF_SRATIONAL: + case TIFF_FLOAT: + { + float v = (float)va_arg(ap, double); + _TIFFmemcpy(val, &v, tv_size); + } + break; + case TIFF_DOUBLE: + { + double v = va_arg(ap, double); + _TIFFmemcpy(val, &v, tv_size); + } + break; + default: + _TIFFmemset(val, 0, tv_size); + status = 0; + break; + } + } + } + } + } + } + if (status) { + TIFFSetFieldBit(tif, _TIFFFieldWithTag(tif, tag)->field_bit); + tif->tif_flags |= TIFF_DIRTYDIRECT; + } + +end: + va_end(ap); + return (status); +badvalue: + TIFFErrorExt(tif->tif_clientdata, module, + "%s: Bad value %d for \"%s\" tag", + tif->tif_name, v, + _TIFFFieldWithTag(tif, tag)->field_name); + va_end(ap); + return (0); +badvalue32: + TIFFErrorExt(tif->tif_clientdata, module, + "%s: Bad value %u for \"%s\" tag", + tif->tif_name, v32, + _TIFFFieldWithTag(tif, tag)->field_name); + va_end(ap); + return (0); +} + +/* + * Return 1/0 according to whether or not + * it is permissible to set the tag's value. + * Note that we allow ImageLength to be changed + * so that we can append and extend to images. + * Any other tag may not be altered once writing + * has commenced, unless its value has no effect + * on the format of the data that is written. + */ +static int +OkToChangeTag(TIFF* tif, ttag_t tag) +{ + const TIFFFieldInfo* fip = _TIFFFindFieldInfo(tif, tag, TIFF_ANY); + if (!fip) { /* unknown tag */ + TIFFErrorExt(tif->tif_clientdata, "TIFFSetField", "%s: Unknown %stag %u", + tif->tif_name, isPseudoTag(tag) ? "pseudo-" : "", tag); + return (0); + } + if (tag != TIFFTAG_IMAGELENGTH && (tif->tif_flags & TIFF_BEENWRITING) && + !fip->field_oktochange) { + /* + * Consult info table to see if tag can be changed + * after we've started writing. We only allow changes + * to those tags that don't/shouldn't affect the + * compression and/or format of the data. + */ + TIFFErrorExt(tif->tif_clientdata, "TIFFSetField", + "%s: Cannot modify tag \"%s\" while writing", + tif->tif_name, fip->field_name); + return (0); + } + return (1); +} + +/* + * Record the value of a field in the + * internal directory structure. The + * field will be written to the file + * when/if the directory structure is + * updated. + */ +int +TIFFSetField(TIFF* tif, ttag_t tag, ...) +{ + va_list ap; + int status; + + va_start(ap, tag); + status = TIFFVSetField(tif, tag, ap); + va_end(ap); + return (status); +} + +/* + * Like TIFFSetField, but taking a varargs + * parameter list. This routine is useful + * for building higher-level interfaces on + * top of the library. + */ +int +TIFFVSetField(TIFF* tif, ttag_t tag, va_list ap) +{ + return OkToChangeTag(tif, tag) ? + (*tif->tif_tagmethods.vsetfield)(tif, tag, ap) : 0; +} + +static int +_TIFFVGetField(TIFF* tif, ttag_t tag, va_list ap) +{ + TIFFDirectory* td = &tif->tif_dir; + int ret_val = 1; + + switch (tag) { + case TIFFTAG_SUBFILETYPE: + *va_arg(ap, uint32*) = td->td_subfiletype; + break; + case TIFFTAG_IMAGEWIDTH: + *va_arg(ap, uint32*) = td->td_imagewidth; + break; + case TIFFTAG_IMAGELENGTH: + *va_arg(ap, uint32*) = td->td_imagelength; + break; + case TIFFTAG_BITSPERSAMPLE: + *va_arg(ap, uint16*) = td->td_bitspersample; + break; + case TIFFTAG_COMPRESSION: + *va_arg(ap, uint16*) = td->td_compression; + break; + case TIFFTAG_PHOTOMETRIC: + *va_arg(ap, uint16*) = td->td_photometric; + break; + case TIFFTAG_THRESHHOLDING: + *va_arg(ap, uint16*) = td->td_threshholding; + break; + case TIFFTAG_FILLORDER: + *va_arg(ap, uint16*) = td->td_fillorder; + break; + case TIFFTAG_ORIENTATION: + *va_arg(ap, uint16*) = td->td_orientation; + break; + case TIFFTAG_SAMPLESPERPIXEL: + *va_arg(ap, uint16*) = td->td_samplesperpixel; + break; + case TIFFTAG_ROWSPERSTRIP: + *va_arg(ap, uint32*) = td->td_rowsperstrip; + break; + case TIFFTAG_MINSAMPLEVALUE: + *va_arg(ap, uint16*) = td->td_minsamplevalue; + break; + case TIFFTAG_MAXSAMPLEVALUE: + *va_arg(ap, uint16*) = td->td_maxsamplevalue; + break; + case TIFFTAG_SMINSAMPLEVALUE: + *va_arg(ap, double*) = td->td_sminsamplevalue; + break; + case TIFFTAG_SMAXSAMPLEVALUE: + *va_arg(ap, double*) = td->td_smaxsamplevalue; + break; + case TIFFTAG_XRESOLUTION: + *va_arg(ap, float*) = td->td_xresolution; + break; + case TIFFTAG_YRESOLUTION: + *va_arg(ap, float*) = td->td_yresolution; + break; + case TIFFTAG_PLANARCONFIG: + *va_arg(ap, uint16*) = td->td_planarconfig; + break; + case TIFFTAG_XPOSITION: + *va_arg(ap, float*) = td->td_xposition; + break; + case TIFFTAG_YPOSITION: + *va_arg(ap, float*) = td->td_yposition; + break; + case TIFFTAG_RESOLUTIONUNIT: + *va_arg(ap, uint16*) = td->td_resolutionunit; + break; + case TIFFTAG_PAGENUMBER: + *va_arg(ap, uint16*) = td->td_pagenumber[0]; + *va_arg(ap, uint16*) = td->td_pagenumber[1]; + break; + case TIFFTAG_HALFTONEHINTS: + *va_arg(ap, uint16*) = td->td_halftonehints[0]; + *va_arg(ap, uint16*) = td->td_halftonehints[1]; + break; + case TIFFTAG_COLORMAP: + *va_arg(ap, uint16**) = td->td_colormap[0]; + *va_arg(ap, uint16**) = td->td_colormap[1]; + *va_arg(ap, uint16**) = td->td_colormap[2]; + break; + case TIFFTAG_STRIPOFFSETS: + case TIFFTAG_TILEOFFSETS: + *va_arg(ap, uint32**) = td->td_stripoffset; + break; + case TIFFTAG_STRIPBYTECOUNTS: + case TIFFTAG_TILEBYTECOUNTS: + *va_arg(ap, uint32**) = td->td_stripbytecount; + break; + case TIFFTAG_MATTEING: + *va_arg(ap, uint16*) = + (td->td_extrasamples == 1 && + td->td_sampleinfo[0] == EXTRASAMPLE_ASSOCALPHA); + break; + case TIFFTAG_EXTRASAMPLES: + *va_arg(ap, uint16*) = td->td_extrasamples; + *va_arg(ap, uint16**) = td->td_sampleinfo; + break; + case TIFFTAG_TILEWIDTH: + *va_arg(ap, uint32*) = td->td_tilewidth; + break; + case TIFFTAG_TILELENGTH: + *va_arg(ap, uint32*) = td->td_tilelength; + break; + case TIFFTAG_TILEDEPTH: + *va_arg(ap, uint32*) = td->td_tiledepth; + break; + case TIFFTAG_DATATYPE: + switch (td->td_sampleformat) { + case SAMPLEFORMAT_UINT: + *va_arg(ap, uint16*) = DATATYPE_UINT; + break; + case SAMPLEFORMAT_INT: + *va_arg(ap, uint16*) = DATATYPE_INT; + break; + case SAMPLEFORMAT_IEEEFP: + *va_arg(ap, uint16*) = DATATYPE_IEEEFP; + break; + case SAMPLEFORMAT_VOID: + *va_arg(ap, uint16*) = DATATYPE_VOID; + break; + } + break; + case TIFFTAG_SAMPLEFORMAT: + *va_arg(ap, uint16*) = td->td_sampleformat; + break; + case TIFFTAG_IMAGEDEPTH: + *va_arg(ap, uint32*) = td->td_imagedepth; + break; + case TIFFTAG_SUBIFD: + *va_arg(ap, uint16*) = td->td_nsubifd; + *va_arg(ap, uint32**) = td->td_subifd; + break; + case TIFFTAG_YCBCRPOSITIONING: + *va_arg(ap, uint16*) = td->td_ycbcrpositioning; + break; + case TIFFTAG_YCBCRSUBSAMPLING: + *va_arg(ap, uint16*) = td->td_ycbcrsubsampling[0]; + *va_arg(ap, uint16*) = td->td_ycbcrsubsampling[1]; + break; + case TIFFTAG_TRANSFERFUNCTION: + *va_arg(ap, uint16**) = td->td_transferfunction[0]; + if (td->td_samplesperpixel - td->td_extrasamples > 1) { + *va_arg(ap, uint16**) = td->td_transferfunction[1]; + *va_arg(ap, uint16**) = td->td_transferfunction[2]; + } + break; + case TIFFTAG_REFERENCEBLACKWHITE: + *va_arg(ap, float**) = td->td_refblackwhite; + break; + case TIFFTAG_INKNAMES: + *va_arg(ap, char**) = td->td_inknames; + break; + default: + { + const TIFFFieldInfo* fip = _TIFFFindFieldInfo(tif, tag, TIFF_ANY); + int i; + + /* + * This can happen if multiple images are open with different + * codecs which have private tags. The global tag information + * table may then have tags that are valid for one file but not + * the other. If the client tries to get a tag that is not valid + * for the image's codec then we'll arrive here. + */ + if( fip == NULL || fip->field_bit != FIELD_CUSTOM ) + { + TIFFErrorExt(tif->tif_clientdata, "_TIFFVGetField", + "%s: Invalid %stag \"%s\" " + "(not supported by codec)", + tif->tif_name, + isPseudoTag(tag) ? "pseudo-" : "", + fip ? fip->field_name : "Unknown"); + ret_val = 0; + break; + } + + /* + * Do we have a custom value? + */ + ret_val = 0; + for (i = 0; i < td->td_customValueCount; i++) { + TIFFTagValue *tv = td->td_customValues + i; + + if (tv->info->field_tag != tag) + continue; + + if (fip->field_passcount) { + if (fip->field_readcount == TIFF_VARIABLE2) + *va_arg(ap, uint32*) = (uint32)tv->count; + else /* Assume TIFF_VARIABLE */ + *va_arg(ap, uint16*) = (uint16)tv->count; + *va_arg(ap, void **) = tv->value; + ret_val = 1; + } else { + if ((fip->field_type == TIFF_ASCII + || fip->field_readcount == TIFF_VARIABLE + || fip->field_readcount == TIFF_VARIABLE2 + || fip->field_readcount == TIFF_SPP + || tv->count > 1) + && fip->field_tag != TIFFTAG_PAGENUMBER + && fip->field_tag != TIFFTAG_HALFTONEHINTS + && fip->field_tag != TIFFTAG_YCBCRSUBSAMPLING + && fip->field_tag != TIFFTAG_DOTRANGE) { + *va_arg(ap, void **) = tv->value; + ret_val = 1; + } else { + int j; + char *val = (char *)tv->value; + + for (j = 0; j < tv->count; + j++, val += _TIFFDataSize(tv->info->field_type)) { + switch (fip->field_type) { + case TIFF_BYTE: + case TIFF_UNDEFINED: + *va_arg(ap, uint8*) = + *(uint8 *)val; + ret_val = 1; + break; + case TIFF_SBYTE: + *va_arg(ap, int8*) = + *(int8 *)val; + ret_val = 1; + break; + case TIFF_SHORT: + *va_arg(ap, uint16*) = + *(uint16 *)val; + ret_val = 1; + break; + case TIFF_SSHORT: + *va_arg(ap, int16*) = + *(int16 *)val; + ret_val = 1; + break; + case TIFF_LONG: + case TIFF_IFD: + *va_arg(ap, uint32*) = + *(uint32 *)val; + ret_val = 1; + break; + case TIFF_SLONG: + *va_arg(ap, int32*) = + *(int32 *)val; + ret_val = 1; + break; + case TIFF_RATIONAL: + case TIFF_SRATIONAL: + case TIFF_FLOAT: + *va_arg(ap, float*) = + *(float *)val; + ret_val = 1; + break; + case TIFF_DOUBLE: + *va_arg(ap, double*) = + *(double *)val; + ret_val = 1; + break; + default: + ret_val = 0; + break; + } + } + } + } + break; + } + } + } + return(ret_val); +} + +/* + * Return the value of a field in the + * internal directory structure. + */ +int +TIFFGetField(TIFF* tif, ttag_t tag, ...) +{ + int status; + va_list ap; + + va_start(ap, tag); + status = TIFFVGetField(tif, tag, ap); + va_end(ap); + return (status); +} + +/* + * Like TIFFGetField, but taking a varargs + * parameter list. This routine is useful + * for building higher-level interfaces on + * top of the library. + */ +int +TIFFVGetField(TIFF* tif, ttag_t tag, va_list ap) +{ + const TIFFFieldInfo* fip = _TIFFFindFieldInfo(tif, tag, TIFF_ANY); + return (fip && (isPseudoTag(tag) || TIFFFieldSet(tif, fip->field_bit)) ? + (*tif->tif_tagmethods.vgetfield)(tif, tag, ap) : 0); +} + +#define CleanupField(member) { \ + if (td->member) { \ + _TIFFfree(td->member); \ + td->member = 0; \ + } \ +} + +/* + * Release storage associated with a directory. + */ +void +TIFFFreeDirectory(TIFF* tif) +{ + TIFFDirectory *td = &tif->tif_dir; + int i; + + _TIFFmemset(td->td_fieldsset, 0, FIELD_SETLONGS); + CleanupField(td_colormap[0]); + CleanupField(td_colormap[1]); + CleanupField(td_colormap[2]); + CleanupField(td_sampleinfo); + CleanupField(td_subifd); + CleanupField(td_inknames); + CleanupField(td_refblackwhite); + CleanupField(td_transferfunction[0]); + CleanupField(td_transferfunction[1]); + CleanupField(td_transferfunction[2]); + CleanupField(td_stripoffset); + CleanupField(td_stripbytecount); + TIFFClrFieldBit(tif, FIELD_YCBCRSUBSAMPLING); + TIFFClrFieldBit(tif, FIELD_YCBCRPOSITIONING); + + /* Cleanup custom tag values */ + for( i = 0; i < td->td_customValueCount; i++ ) { + if (td->td_customValues[i].value) + _TIFFfree(td->td_customValues[i].value); + } + + td->td_customValueCount = 0; + CleanupField(td_customValues); +} +#undef CleanupField + +/* + * Client Tag extension support (from Niles Ritter). + */ +static TIFFExtendProc _TIFFextender = (TIFFExtendProc) NULL; + +TIFFExtendProc +TIFFSetTagExtender(TIFFExtendProc extender) +{ + TIFFExtendProc prev = _TIFFextender; + _TIFFextender = extender; + return (prev); +} + +/* + * Setup for a new directory. Should we automatically call + * TIFFWriteDirectory() if the current one is dirty? + * + * The newly created directory will not exist on the file till + * TIFFWriteDirectory(), TIFFFlush() or TIFFClose() is called. + */ +int +TIFFCreateDirectory(TIFF* tif) +{ + TIFFDefaultDirectory(tif); + tif->tif_diroff = 0; + tif->tif_nextdiroff = 0; + tif->tif_curoff = 0; + tif->tif_row = (uint32) -1; + tif->tif_curstrip = (tstrip_t) -1; + + return 0; +} + +/* + * Setup a default directory structure. + */ +int +TIFFDefaultDirectory(TIFF* tif) +{ + register TIFFDirectory* td = &tif->tif_dir; + + size_t tiffFieldInfoCount; + const TIFFFieldInfo *tiffFieldInfo = + _TIFFGetFieldInfo(&tiffFieldInfoCount); + _TIFFSetupFieldInfo(tif, tiffFieldInfo, tiffFieldInfoCount); + + _TIFFmemset(td, 0, sizeof (*td)); + td->td_fillorder = FILLORDER_MSB2LSB; + td->td_bitspersample = 1; + td->td_threshholding = THRESHHOLD_BILEVEL; + td->td_orientation = ORIENTATION_TOPLEFT; + td->td_samplesperpixel = 1; + td->td_rowsperstrip = (uint32) -1; + td->td_tilewidth = 0; + td->td_tilelength = 0; + td->td_tiledepth = 1; + td->td_stripbytecountsorted = 1; /* Our own arrays always sorted. */ + td->td_resolutionunit = RESUNIT_INCH; + td->td_sampleformat = SAMPLEFORMAT_UINT; + td->td_imagedepth = 1; + td->td_ycbcrsubsampling[0] = 2; + td->td_ycbcrsubsampling[1] = 2; + td->td_ycbcrpositioning = YCBCRPOSITION_CENTERED; + tif->tif_postdecode = _TIFFNoPostDecode; + tif->tif_foundfield = NULL; + tif->tif_tagmethods.vsetfield = _TIFFVSetField; + tif->tif_tagmethods.vgetfield = _TIFFVGetField; + tif->tif_tagmethods.printdir = NULL; + /* + * Give client code a chance to install their own + * tag extensions & methods, prior to compression overloads. + */ + if (_TIFFextender) + (*_TIFFextender)(tif); + (void) TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE); + /* + * NB: The directory is marked dirty as a result of setting + * up the default compression scheme. However, this really + * isn't correct -- we want TIFF_DIRTYDIRECT to be set only + * if the user does something. We could just do the setup + * by hand, but it seems better to use the normal mechanism + * (i.e. TIFFSetField). + */ + tif->tif_flags &= ~TIFF_DIRTYDIRECT; + + /* + * As per http://bugzilla.remotesensing.org/show_bug.cgi?id=19 + * we clear the ISTILED flag when setting up a new directory. + * Should we also be clearing stuff like INSUBIFD? + */ + tif->tif_flags &= ~TIFF_ISTILED; + /* + * Clear other directory-specific fields. + */ + tif->tif_tilesize = -1; + tif->tif_scanlinesize = -1; + + return (1); +} + +static int +TIFFAdvanceDirectory(TIFF* tif, uint32* nextdir, toff_t* off) +{ + static const char module[] = "TIFFAdvanceDirectory"; + uint16 dircount; + if (isMapped(tif)) + { + toff_t poff=*nextdir; + if (poff+sizeof(uint16) > tif->tif_size) + { + TIFFErrorExt(tif->tif_clientdata, module, "%s: Error fetching directory count", + tif->tif_name); + return (0); + } + _TIFFmemcpy(&dircount, tif->tif_base+poff, sizeof (uint16)); + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabShort(&dircount); + poff+=sizeof (uint16)+dircount*sizeof (TIFFDirEntry); + if (off != NULL) + *off = poff; + if (((toff_t) (poff+sizeof (uint32))) > tif->tif_size) + { + TIFFErrorExt(tif->tif_clientdata, module, "%s: Error fetching directory link", + tif->tif_name); + return (0); + } + _TIFFmemcpy(nextdir, tif->tif_base+poff, sizeof (uint32)); + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabLong(nextdir); + return (1); + } + else + { + if (!SeekOK(tif, *nextdir) || + !ReadOK(tif, &dircount, sizeof (uint16))) { + TIFFErrorExt(tif->tif_clientdata, module, "%s: Error fetching directory count", + tif->tif_name); + return (0); + } + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabShort(&dircount); + if (off != NULL) + *off = TIFFSeekFile(tif, + dircount*sizeof (TIFFDirEntry), SEEK_CUR); + else + (void) TIFFSeekFile(tif, + dircount*sizeof (TIFFDirEntry), SEEK_CUR); + if (!ReadOK(tif, nextdir, sizeof (uint32))) { + TIFFErrorExt(tif->tif_clientdata, module, "%s: Error fetching directory link", + tif->tif_name); + return (0); + } + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabLong(nextdir); + return (1); + } +} + +/* + * Count the number of directories in a file. + */ +tdir_t +TIFFNumberOfDirectories(TIFF* tif) +{ + toff_t nextdir = tif->tif_header.tiff_diroff; + tdir_t n = 0; + + while (nextdir != 0 && TIFFAdvanceDirectory(tif, &nextdir, NULL)) + n++; + return (n); +} + +/* + * Set the n-th directory as the current directory. + * NB: Directories are numbered starting at 0. + */ +int +TIFFSetDirectory(TIFF* tif, tdir_t dirn) +{ + toff_t nextdir; + tdir_t n; + + nextdir = tif->tif_header.tiff_diroff; + for (n = dirn; n > 0 && nextdir != 0; n--) + if (!TIFFAdvanceDirectory(tif, &nextdir, NULL)) + return (0); + tif->tif_nextdiroff = nextdir; + /* + * Set curdir to the actual directory index. The + * -1 is because TIFFReadDirectory will increment + * tif_curdir after successfully reading the directory. + */ + tif->tif_curdir = (dirn - n) - 1; + /* + * Reset tif_dirnumber counter and start new list of seen directories. + * We need this to prevent IFD loops. + */ + tif->tif_dirnumber = 0; + return (TIFFReadDirectory(tif)); +} + +/* + * Set the current directory to be the directory + * located at the specified file offset. This interface + * is used mainly to access directories linked with + * the SubIFD tag (e.g. thumbnail images). + */ +int +TIFFSetSubDirectory(TIFF* tif, uint32 diroff) +{ + tif->tif_nextdiroff = diroff; + /* + * Reset tif_dirnumber counter and start new list of seen directories. + * We need this to prevent IFD loops. + */ + tif->tif_dirnumber = 0; + return (TIFFReadDirectory(tif)); +} + +/* + * Return file offset of the current directory. + */ +uint32 +TIFFCurrentDirOffset(TIFF* tif) +{ + return (tif->tif_diroff); +} + +/* + * Return an indication of whether or not we are + * at the last directory in the file. + */ +int +TIFFLastDirectory(TIFF* tif) +{ + return (tif->tif_nextdiroff == 0); +} + +/* + * Unlink the specified directory from the directory chain. + */ +int +TIFFUnlinkDirectory(TIFF* tif, tdir_t dirn) +{ + static const char module[] = "TIFFUnlinkDirectory"; + toff_t nextdir; + toff_t off; + tdir_t n; + + if (tif->tif_mode == O_RDONLY) { + TIFFErrorExt(tif->tif_clientdata, module, + "Can not unlink directory in read-only file"); + return (0); + } + /* + * Go to the directory before the one we want + * to unlink and nab the offset of the link + * field we'll need to patch. + */ + nextdir = tif->tif_header.tiff_diroff; + off = sizeof (uint16) + sizeof (uint16); + for (n = dirn-1; n > 0; n--) { + if (nextdir == 0) { + TIFFErrorExt(tif->tif_clientdata, module, "Directory %d does not exist", dirn); + return (0); + } + if (!TIFFAdvanceDirectory(tif, &nextdir, &off)) + return (0); + } + /* + * Advance to the directory to be unlinked and fetch + * the offset of the directory that follows. + */ + if (!TIFFAdvanceDirectory(tif, &nextdir, NULL)) + return (0); + /* + * Go back and patch the link field of the preceding + * directory to point to the offset of the directory + * that follows. + */ + (void) TIFFSeekFile(tif, off, SEEK_SET); + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabLong(&nextdir); + if (!WriteOK(tif, &nextdir, sizeof (uint32))) { + TIFFErrorExt(tif->tif_clientdata, module, "Error writing directory link"); + return (0); + } + /* + * Leave directory state setup safely. We don't have + * facilities for doing inserting and removing directories, + * so it's safest to just invalidate everything. This + * means that the caller can only append to the directory + * chain. + */ + (*tif->tif_cleanup)(tif); + if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) { + _TIFFfree(tif->tif_rawdata); + tif->tif_rawdata = NULL; + tif->tif_rawcc = 0; + } + tif->tif_flags &= ~(TIFF_BEENWRITING|TIFF_BUFFERSETUP|TIFF_POSTENCODE); + TIFFFreeDirectory(tif); + TIFFDefaultDirectory(tif); + tif->tif_diroff = 0; /* force link on next write */ + tif->tif_nextdiroff = 0; /* next write must be at end */ + tif->tif_curoff = 0; + tif->tif_row = (uint32) -1; + tif->tif_curstrip = (tstrip_t) -1; + return (1); +} + +/* [BFC] + * + * Author: Bruce Cameron + * + * Set a table of tags that are to be replaced during directory process by the + * 'IGNORE' state - or return TRUE/FALSE for the requested tag such that + * 'ReadDirectory' can use the stored information. + * + * FIXME: this is never used properly. Should be removed in the future. + */ +int +TIFFReassignTagToIgnore (enum TIFFIgnoreSense task, int TIFFtagID) +{ + static int TIFFignoretags [FIELD_LAST]; + static int tagcount = 0 ; + int i; /* Loop index */ + int j; /* Loop index */ + + switch (task) + { + case TIS_STORE: + if ( tagcount < (FIELD_LAST - 1) ) + { + for ( j = 0 ; j < tagcount ; ++j ) + { /* Do not add duplicate tag */ + if ( TIFFignoretags [j] == TIFFtagID ) + return (TRUE) ; + } + TIFFignoretags [tagcount++] = TIFFtagID ; + return (TRUE) ; + } + break ; + + case TIS_EXTRACT: + for ( i = 0 ; i < tagcount ; ++i ) + { + if ( TIFFignoretags [i] == TIFFtagID ) + return (TRUE) ; + } + break; + + case TIS_EMPTY: + tagcount = 0 ; /* Clear the list */ + return (TRUE) ; + + default: + break; + } + + return (FALSE); +} + +/* vim: set ts=8 sts=8 sw=8 noet: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tif_dir.h b/reactos/dll/3rdparty/libtiff/tif_dir.h new file mode 100644 index 00000000000..515af19942c --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tif_dir.h @@ -0,0 +1,211 @@ +/* $Id: tif_dir.h,v 1.30.2.3 2010-06-09 21:15:27 bfriesen Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _TIFFDIR_ +#define _TIFFDIR_ +/* + * ``Library-private'' Directory-related Definitions. + */ + +/* + * Internal format of a TIFF directory entry. + */ +typedef struct { +#define FIELD_SETLONGS 4 + /* bit vector of fields that are set */ + unsigned long td_fieldsset[FIELD_SETLONGS]; + + uint32 td_imagewidth, td_imagelength, td_imagedepth; + uint32 td_tilewidth, td_tilelength, td_tiledepth; + uint32 td_subfiletype; + uint16 td_bitspersample; + uint16 td_sampleformat; + uint16 td_compression; + uint16 td_photometric; + uint16 td_threshholding; + uint16 td_fillorder; + uint16 td_orientation; + uint16 td_samplesperpixel; + uint32 td_rowsperstrip; + uint16 td_minsamplevalue, td_maxsamplevalue; + double td_sminsamplevalue, td_smaxsamplevalue; + float td_xresolution, td_yresolution; + uint16 td_resolutionunit; + uint16 td_planarconfig; + float td_xposition, td_yposition; + uint16 td_pagenumber[2]; + uint16* td_colormap[3]; + uint16 td_halftonehints[2]; + uint16 td_extrasamples; + uint16* td_sampleinfo; + /* even though the name is misleading, td_stripsperimage is the number + * of striles (=strips or tiles) per plane, and td_nstrips the total + * number of striles */ + tstrile_t td_stripsperimage; + tstrile_t td_nstrips; /* size of offset & bytecount arrays */ + toff_t* td_stripoffset; + toff_t* td_stripbytecount; /* FIXME: it should be tsize_t array */ + int td_stripbytecountsorted; /* is the bytecount array sorted ascending? */ + uint16 td_nsubifd; + uint32* td_subifd; + /* YCbCr parameters */ + uint16 td_ycbcrsubsampling[2]; + uint16 td_ycbcrpositioning; + /* Colorimetry parameters */ + float* td_refblackwhite; + uint16* td_transferfunction[3]; + /* CMYK parameters */ + int td_inknameslen; + char* td_inknames; + + int td_customValueCount; + TIFFTagValue *td_customValues; +} TIFFDirectory; + +/* + * Field flags used to indicate fields that have + * been set in a directory, and to reference fields + * when manipulating a directory. + */ + +/* + * FIELD_IGNORE is used to signify tags that are to + * be processed but otherwise ignored. This permits + * antiquated tags to be quietly read and discarded. + * Note that a bit *is* allocated for ignored tags; + * this is understood by the directory reading logic + * which uses this fact to avoid special-case handling + */ +#define FIELD_IGNORE 0 + +/* multi-item fields */ +#define FIELD_IMAGEDIMENSIONS 1 +#define FIELD_TILEDIMENSIONS 2 +#define FIELD_RESOLUTION 3 +#define FIELD_POSITION 4 + +/* single-item fields */ +#define FIELD_SUBFILETYPE 5 +#define FIELD_BITSPERSAMPLE 6 +#define FIELD_COMPRESSION 7 +#define FIELD_PHOTOMETRIC 8 +#define FIELD_THRESHHOLDING 9 +#define FIELD_FILLORDER 10 +#define FIELD_ORIENTATION 15 +#define FIELD_SAMPLESPERPIXEL 16 +#define FIELD_ROWSPERSTRIP 17 +#define FIELD_MINSAMPLEVALUE 18 +#define FIELD_MAXSAMPLEVALUE 19 +#define FIELD_PLANARCONFIG 20 +#define FIELD_RESOLUTIONUNIT 22 +#define FIELD_PAGENUMBER 23 +#define FIELD_STRIPBYTECOUNTS 24 +#define FIELD_STRIPOFFSETS 25 +#define FIELD_COLORMAP 26 +#define FIELD_EXTRASAMPLES 31 +#define FIELD_SAMPLEFORMAT 32 +#define FIELD_SMINSAMPLEVALUE 33 +#define FIELD_SMAXSAMPLEVALUE 34 +#define FIELD_IMAGEDEPTH 35 +#define FIELD_TILEDEPTH 36 +#define FIELD_HALFTONEHINTS 37 +#define FIELD_YCBCRSUBSAMPLING 39 +#define FIELD_YCBCRPOSITIONING 40 +#define FIELD_REFBLACKWHITE 41 +#define FIELD_TRANSFERFUNCTION 44 +#define FIELD_INKNAMES 46 +#define FIELD_SUBIFD 49 +/* FIELD_CUSTOM (see tiffio.h) 65 */ +/* end of support for well-known tags; codec-private tags follow */ +#define FIELD_CODEC 66 /* base of codec-private tags */ + + +/* + * Pseudo-tags don't normally need field bits since they + * are not written to an output file (by definition). + * The library also has express logic to always query a + * codec for a pseudo-tag so allocating a field bit for + * one is a waste. If codec wants to promote the notion + * of a pseudo-tag being ``set'' or ``unset'' then it can + * do using internal state flags without polluting the + * field bit space defined for real tags. + */ +#define FIELD_PSEUDO 0 + +#define FIELD_LAST (32*FIELD_SETLONGS-1) + +#define TIFFExtractData(tif, type, v) \ + ((uint32) ((tif)->tif_header.tiff_magic == TIFF_BIGENDIAN ? \ + ((v) >> (tif)->tif_typeshift[type]) & (tif)->tif_typemask[type] : \ + (v) & (tif)->tif_typemask[type])) +#define TIFFInsertData(tif, type, v) \ + ((uint32) ((tif)->tif_header.tiff_magic == TIFF_BIGENDIAN ? \ + ((v) & (tif)->tif_typemask[type]) << (tif)->tif_typeshift[type] : \ + (v) & (tif)->tif_typemask[type])) + + +#define BITn(n) (((unsigned long)1L)<<((n)&0x1f)) +#define BITFIELDn(tif, n) ((tif)->tif_dir.td_fieldsset[(n)/32]) +#define TIFFFieldSet(tif, field) (BITFIELDn(tif, field) & BITn(field)) +#define TIFFSetFieldBit(tif, field) (BITFIELDn(tif, field) |= BITn(field)) +#define TIFFClrFieldBit(tif, field) (BITFIELDn(tif, field) &= ~BITn(field)) + +#define FieldSet(fields, f) (fields[(f)/32] & BITn(f)) +#define ResetFieldBit(fields, f) (fields[(f)/32] &= ~BITn(f)) + +#if defined(__cplusplus) +extern "C" { +#endif +extern const TIFFFieldInfo *_TIFFGetFieldInfo(size_t *); +extern const TIFFFieldInfo *_TIFFGetExifFieldInfo(size_t *); +extern void _TIFFSetupFieldInfo(TIFF*, const TIFFFieldInfo[], size_t); +extern int _TIFFMergeFieldInfo(TIFF*, const TIFFFieldInfo[], int); +extern void _TIFFPrintFieldInfo(TIFF*, FILE*); +extern TIFFDataType _TIFFSampleToTagType(TIFF*); +extern const TIFFFieldInfo* _TIFFFindOrRegisterFieldInfo( TIFF *tif, + ttag_t tag, + TIFFDataType dt ); +extern TIFFFieldInfo* _TIFFCreateAnonFieldInfo( TIFF *tif, ttag_t tag, + TIFFDataType dt ); + +#define _TIFFFindFieldInfo TIFFFindFieldInfo +#define _TIFFFindFieldInfoByName TIFFFindFieldInfoByName +#define _TIFFFieldWithTag TIFFFieldWithTag +#define _TIFFFieldWithName TIFFFieldWithName + +#if defined(__cplusplus) +} +#endif +#endif /* _TIFFDIR_ */ + +/* vim: set ts=8 sts=8 sw=8 noet: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tif_dirinfo.c b/reactos/dll/3rdparty/libtiff/tif_dirinfo.c new file mode 100644 index 00000000000..0a77c9714e2 --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tif_dirinfo.c @@ -0,0 +1,888 @@ +/* $Id: tif_dirinfo.c,v 1.65.2.9 2010-06-09 21:15:27 bfriesen Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library. + * + * Core Directory Tag Support. + */ +#include "tiffiop.h" +#include +#include + +/* + * NB: NB: THIS ARRAY IS ASSUMED TO BE SORTED BY TAG. + * If a tag can have both LONG and SHORT types then the LONG must be + * placed before the SHORT for writing to work properly. + * + * NOTE: The second field (field_readcount) and third field (field_writecount) + * sometimes use the values TIFF_VARIABLE (-1), TIFF_VARIABLE2 (-3) + * and TIFFTAG_SPP (-2). The macros should be used but would throw off + * the formatting of the code, so please interprete the -1, -2 and -3 + * values accordingly. + */ +static const TIFFFieldInfo +tiffFieldInfo[] = { + { TIFFTAG_SUBFILETYPE, 1, 1, TIFF_LONG, FIELD_SUBFILETYPE, + 1, 0, "SubfileType" }, +/* XXX SHORT for compatibility w/ old versions of the library */ + { TIFFTAG_SUBFILETYPE, 1, 1, TIFF_SHORT, FIELD_SUBFILETYPE, + 1, 0, "SubfileType" }, + { TIFFTAG_OSUBFILETYPE, 1, 1, TIFF_SHORT, FIELD_SUBFILETYPE, + 1, 0, "OldSubfileType" }, + { TIFFTAG_IMAGEWIDTH, 1, 1, TIFF_LONG, FIELD_IMAGEDIMENSIONS, + 0, 0, "ImageWidth" }, + { TIFFTAG_IMAGEWIDTH, 1, 1, TIFF_SHORT, FIELD_IMAGEDIMENSIONS, + 0, 0, "ImageWidth" }, + { TIFFTAG_IMAGELENGTH, 1, 1, TIFF_LONG, FIELD_IMAGEDIMENSIONS, + 1, 0, "ImageLength" }, + { TIFFTAG_IMAGELENGTH, 1, 1, TIFF_SHORT, FIELD_IMAGEDIMENSIONS, + 1, 0, "ImageLength" }, + { TIFFTAG_BITSPERSAMPLE, -1,-1, TIFF_SHORT, FIELD_BITSPERSAMPLE, + 0, 0, "BitsPerSample" }, +/* XXX LONG for compatibility with some broken TIFF writers */ + { TIFFTAG_BITSPERSAMPLE, -1,-1, TIFF_LONG, FIELD_BITSPERSAMPLE, + 0, 0, "BitsPerSample" }, + { TIFFTAG_COMPRESSION, -1, 1, TIFF_SHORT, FIELD_COMPRESSION, + 0, 0, "Compression" }, +/* XXX LONG for compatibility with some broken TIFF writers */ + { TIFFTAG_COMPRESSION, -1, 1, TIFF_LONG, FIELD_COMPRESSION, + 0, 0, "Compression" }, + { TIFFTAG_PHOTOMETRIC, 1, 1, TIFF_SHORT, FIELD_PHOTOMETRIC, + 0, 0, "PhotometricInterpretation" }, +/* XXX LONG for compatibility with some broken TIFF writers */ + { TIFFTAG_PHOTOMETRIC, 1, 1, TIFF_LONG, FIELD_PHOTOMETRIC, + 0, 0, "PhotometricInterpretation" }, + { TIFFTAG_THRESHHOLDING, 1, 1, TIFF_SHORT, FIELD_THRESHHOLDING, + 1, 0, "Threshholding" }, + { TIFFTAG_CELLWIDTH, 1, 1, TIFF_SHORT, FIELD_IGNORE, + 1, 0, "CellWidth" }, + { TIFFTAG_CELLLENGTH, 1, 1, TIFF_SHORT, FIELD_IGNORE, + 1, 0, "CellLength" }, + { TIFFTAG_FILLORDER, 1, 1, TIFF_SHORT, FIELD_FILLORDER, + 0, 0, "FillOrder" }, + { TIFFTAG_DOCUMENTNAME, -1,-1, TIFF_ASCII, FIELD_CUSTOM, + 1, 0, "DocumentName" }, + { TIFFTAG_IMAGEDESCRIPTION, -1,-1, TIFF_ASCII, FIELD_CUSTOM, + 1, 0, "ImageDescription" }, + { TIFFTAG_MAKE, -1,-1, TIFF_ASCII, FIELD_CUSTOM, + 1, 0, "Make" }, + { TIFFTAG_MODEL, -1,-1, TIFF_ASCII, FIELD_CUSTOM, + 1, 0, "Model" }, + { TIFFTAG_STRIPOFFSETS, -1,-1, TIFF_LONG, FIELD_STRIPOFFSETS, + 0, 0, "StripOffsets" }, + { TIFFTAG_STRIPOFFSETS, -1,-1, TIFF_SHORT, FIELD_STRIPOFFSETS, + 0, 0, "StripOffsets" }, + { TIFFTAG_ORIENTATION, 1, 1, TIFF_SHORT, FIELD_ORIENTATION, + 0, 0, "Orientation" }, + { TIFFTAG_SAMPLESPERPIXEL, 1, 1, TIFF_SHORT, FIELD_SAMPLESPERPIXEL, + 0, 0, "SamplesPerPixel" }, + { TIFFTAG_ROWSPERSTRIP, 1, 1, TIFF_LONG, FIELD_ROWSPERSTRIP, + 0, 0, "RowsPerStrip" }, + { TIFFTAG_ROWSPERSTRIP, 1, 1, TIFF_SHORT, FIELD_ROWSPERSTRIP, + 0, 0, "RowsPerStrip" }, + { TIFFTAG_STRIPBYTECOUNTS, -1,-1, TIFF_LONG, FIELD_STRIPBYTECOUNTS, + 0, 0, "StripByteCounts" }, + { TIFFTAG_STRIPBYTECOUNTS, -1,-1, TIFF_SHORT, FIELD_STRIPBYTECOUNTS, + 0, 0, "StripByteCounts" }, + { TIFFTAG_MINSAMPLEVALUE, -2,-1, TIFF_SHORT, FIELD_MINSAMPLEVALUE, + 1, 0, "MinSampleValue" }, + { TIFFTAG_MAXSAMPLEVALUE, -2,-1, TIFF_SHORT, FIELD_MAXSAMPLEVALUE, + 1, 0, "MaxSampleValue" }, + { TIFFTAG_XRESOLUTION, 1, 1, TIFF_RATIONAL, FIELD_RESOLUTION, + 1, 0, "XResolution" }, + { TIFFTAG_YRESOLUTION, 1, 1, TIFF_RATIONAL, FIELD_RESOLUTION, + 1, 0, "YResolution" }, + { TIFFTAG_PLANARCONFIG, 1, 1, TIFF_SHORT, FIELD_PLANARCONFIG, + 0, 0, "PlanarConfiguration" }, + { TIFFTAG_PAGENAME, -1,-1, TIFF_ASCII, FIELD_CUSTOM, + 1, 0, "PageName" }, + { TIFFTAG_XPOSITION, 1, 1, TIFF_RATIONAL, FIELD_POSITION, + 1, 0, "XPosition" }, + { TIFFTAG_YPOSITION, 1, 1, TIFF_RATIONAL, FIELD_POSITION, + 1, 0, "YPosition" }, + { TIFFTAG_FREEOFFSETS, -1,-1, TIFF_LONG, FIELD_IGNORE, + 0, 0, "FreeOffsets" }, + { TIFFTAG_FREEBYTECOUNTS, -1,-1, TIFF_LONG, FIELD_IGNORE, + 0, 0, "FreeByteCounts" }, + { TIFFTAG_GRAYRESPONSEUNIT, 1, 1, TIFF_SHORT, FIELD_IGNORE, + 1, 0, "GrayResponseUnit" }, + { TIFFTAG_GRAYRESPONSECURVE,-1,-1, TIFF_SHORT, FIELD_IGNORE, + 1, 0, "GrayResponseCurve" }, + { TIFFTAG_RESOLUTIONUNIT, 1, 1, TIFF_SHORT, FIELD_RESOLUTIONUNIT, + 1, 0, "ResolutionUnit" }, + { TIFFTAG_PAGENUMBER, 2, 2, TIFF_SHORT, FIELD_PAGENUMBER, + 1, 0, "PageNumber" }, + { TIFFTAG_COLORRESPONSEUNIT, 1, 1, TIFF_SHORT, FIELD_IGNORE, + 1, 0, "ColorResponseUnit" }, + { TIFFTAG_TRANSFERFUNCTION, -1,-1, TIFF_SHORT, FIELD_TRANSFERFUNCTION, + 1, 0, "TransferFunction" }, + { TIFFTAG_SOFTWARE, -1,-1, TIFF_ASCII, FIELD_CUSTOM, + 1, 0, "Software" }, + { TIFFTAG_DATETIME, 20,20, TIFF_ASCII, FIELD_CUSTOM, + 1, 0, "DateTime" }, + { TIFFTAG_ARTIST, -1,-1, TIFF_ASCII, FIELD_CUSTOM, + 1, 0, "Artist" }, + { TIFFTAG_HOSTCOMPUTER, -1,-1, TIFF_ASCII, FIELD_CUSTOM, + 1, 0, "HostComputer" }, + { TIFFTAG_WHITEPOINT, 2, 2, TIFF_RATIONAL, FIELD_CUSTOM, + 1, 0, "WhitePoint" }, + { TIFFTAG_PRIMARYCHROMATICITIES,6,6,TIFF_RATIONAL, FIELD_CUSTOM, + 1, 0, "PrimaryChromaticities" }, + { TIFFTAG_COLORMAP, -1,-1, TIFF_SHORT, FIELD_COLORMAP, + 1, 0, "ColorMap" }, + { TIFFTAG_HALFTONEHINTS, 2, 2, TIFF_SHORT, FIELD_HALFTONEHINTS, + 1, 0, "HalftoneHints" }, + { TIFFTAG_TILEWIDTH, 1, 1, TIFF_LONG, FIELD_TILEDIMENSIONS, + 0, 0, "TileWidth" }, + { TIFFTAG_TILEWIDTH, 1, 1, TIFF_SHORT, FIELD_TILEDIMENSIONS, + 0, 0, "TileWidth" }, + { TIFFTAG_TILELENGTH, 1, 1, TIFF_LONG, FIELD_TILEDIMENSIONS, + 0, 0, "TileLength" }, + { TIFFTAG_TILELENGTH, 1, 1, TIFF_SHORT, FIELD_TILEDIMENSIONS, + 0, 0, "TileLength" }, + { TIFFTAG_TILEOFFSETS, -1, 1, TIFF_LONG, FIELD_STRIPOFFSETS, + 0, 0, "TileOffsets" }, + { TIFFTAG_TILEBYTECOUNTS, -1, 1, TIFF_LONG, FIELD_STRIPBYTECOUNTS, + 0, 0, "TileByteCounts" }, + { TIFFTAG_TILEBYTECOUNTS, -1, 1, TIFF_SHORT, FIELD_STRIPBYTECOUNTS, + 0, 0, "TileByteCounts" }, + { TIFFTAG_SUBIFD, -1,-1, TIFF_IFD, FIELD_SUBIFD, + 1, 1, "SubIFD" }, + { TIFFTAG_SUBIFD, -1,-1, TIFF_LONG, FIELD_SUBIFD, + 1, 1, "SubIFD" }, + { TIFFTAG_INKSET, 1, 1, TIFF_SHORT, FIELD_CUSTOM, + 0, 0, "InkSet" }, + { TIFFTAG_INKNAMES, -1,-1, TIFF_ASCII, FIELD_INKNAMES, + 1, 1, "InkNames" }, + { TIFFTAG_NUMBEROFINKS, 1, 1, TIFF_SHORT, FIELD_CUSTOM, + 1, 0, "NumberOfInks" }, + { TIFFTAG_DOTRANGE, 2, 2, TIFF_SHORT, FIELD_CUSTOM, + 0, 0, "DotRange" }, + { TIFFTAG_DOTRANGE, 2, 2, TIFF_BYTE, FIELD_CUSTOM, + 0, 0, "DotRange" }, + { TIFFTAG_TARGETPRINTER, -1,-1, TIFF_ASCII, FIELD_CUSTOM, + 1, 0, "TargetPrinter" }, + { TIFFTAG_EXTRASAMPLES, -1,-1, TIFF_SHORT, FIELD_EXTRASAMPLES, + 0, 1, "ExtraSamples" }, +/* XXX for bogus Adobe Photoshop v2.5 files */ + { TIFFTAG_EXTRASAMPLES, -1,-1, TIFF_BYTE, FIELD_EXTRASAMPLES, + 0, 1, "ExtraSamples" }, + { TIFFTAG_SAMPLEFORMAT, -1,-1, TIFF_SHORT, FIELD_SAMPLEFORMAT, + 0, 0, "SampleFormat" }, + { TIFFTAG_SMINSAMPLEVALUE, -2,-1, TIFF_ANY, FIELD_SMINSAMPLEVALUE, + 1, 0, "SMinSampleValue" }, + { TIFFTAG_SMAXSAMPLEVALUE, -2,-1, TIFF_ANY, FIELD_SMAXSAMPLEVALUE, + 1, 0, "SMaxSampleValue" }, + { TIFFTAG_CLIPPATH, -1, -3, TIFF_BYTE, FIELD_CUSTOM, + 0, 1, "ClipPath" }, + { TIFFTAG_XCLIPPATHUNITS, 1, 1, TIFF_SLONG, FIELD_CUSTOM, + 0, 0, "XClipPathUnits" }, + { TIFFTAG_XCLIPPATHUNITS, 1, 1, TIFF_SSHORT, FIELD_CUSTOM, + 0, 0, "XClipPathUnits" }, + { TIFFTAG_XCLIPPATHUNITS, 1, 1, TIFF_SBYTE, FIELD_CUSTOM, + 0, 0, "XClipPathUnits" }, + { TIFFTAG_YCLIPPATHUNITS, 1, 1, TIFF_SLONG, FIELD_CUSTOM, + 0, 0, "YClipPathUnits" }, + { TIFFTAG_YCLIPPATHUNITS, 1, 1, TIFF_SSHORT, FIELD_CUSTOM, + 0, 0, "YClipPathUnits" }, + { TIFFTAG_YCLIPPATHUNITS, 1, 1, TIFF_SBYTE, FIELD_CUSTOM, + 0, 0, "YClipPathUnits" }, + { TIFFTAG_YCBCRCOEFFICIENTS, 3, 3, TIFF_RATIONAL, FIELD_CUSTOM, + 0, 0, "YCbCrCoefficients" }, + { TIFFTAG_YCBCRSUBSAMPLING, 2, 2, TIFF_SHORT, FIELD_YCBCRSUBSAMPLING, + 0, 0, "YCbCrSubsampling" }, + { TIFFTAG_YCBCRPOSITIONING, 1, 1, TIFF_SHORT, FIELD_YCBCRPOSITIONING, + 0, 0, "YCbCrPositioning" }, + { TIFFTAG_REFERENCEBLACKWHITE, 6, 6, TIFF_RATIONAL, FIELD_REFBLACKWHITE, + 1, 0, "ReferenceBlackWhite" }, +/* XXX temporarily accept LONG for backwards compatibility */ + { TIFFTAG_REFERENCEBLACKWHITE, 6, 6, TIFF_LONG, FIELD_REFBLACKWHITE, + 1, 0, "ReferenceBlackWhite" }, + { TIFFTAG_XMLPACKET, -3,-3, TIFF_BYTE, FIELD_CUSTOM, + 0, 1, "XMLPacket" }, +/* begin SGI tags */ + { TIFFTAG_MATTEING, 1, 1, TIFF_SHORT, FIELD_EXTRASAMPLES, + 0, 0, "Matteing" }, + { TIFFTAG_DATATYPE, -2,-1, TIFF_SHORT, FIELD_SAMPLEFORMAT, + 0, 0, "DataType" }, + { TIFFTAG_IMAGEDEPTH, 1, 1, TIFF_LONG, FIELD_IMAGEDEPTH, + 0, 0, "ImageDepth" }, + { TIFFTAG_IMAGEDEPTH, 1, 1, TIFF_SHORT, FIELD_IMAGEDEPTH, + 0, 0, "ImageDepth" }, + { TIFFTAG_TILEDEPTH, 1, 1, TIFF_LONG, FIELD_TILEDEPTH, + 0, 0, "TileDepth" }, + { TIFFTAG_TILEDEPTH, 1, 1, TIFF_SHORT, FIELD_TILEDEPTH, + 0, 0, "TileDepth" }, +/* end SGI tags */ +/* begin Pixar tags */ + { TIFFTAG_PIXAR_IMAGEFULLWIDTH, 1, 1, TIFF_LONG, FIELD_CUSTOM, + 1, 0, "ImageFullWidth" }, + { TIFFTAG_PIXAR_IMAGEFULLLENGTH, 1, 1, TIFF_LONG, FIELD_CUSTOM, + 1, 0, "ImageFullLength" }, + { TIFFTAG_PIXAR_TEXTUREFORMAT, -1, -1, TIFF_ASCII, FIELD_CUSTOM, + 1, 0, "TextureFormat" }, + { TIFFTAG_PIXAR_WRAPMODES, -1, -1, TIFF_ASCII, FIELD_CUSTOM, + 1, 0, "TextureWrapModes" }, + { TIFFTAG_PIXAR_FOVCOT, 1, 1, TIFF_FLOAT, FIELD_CUSTOM, + 1, 0, "FieldOfViewCotangent" }, + { TIFFTAG_PIXAR_MATRIX_WORLDTOSCREEN, 16,16, TIFF_FLOAT, + FIELD_CUSTOM, 1, 0, "MatrixWorldToScreen" }, + { TIFFTAG_PIXAR_MATRIX_WORLDTOCAMERA, 16,16, TIFF_FLOAT, + FIELD_CUSTOM, 1, 0, "MatrixWorldToCamera" }, + { TIFFTAG_COPYRIGHT, -1, -1, TIFF_ASCII, FIELD_CUSTOM, + 1, 0, "Copyright" }, +/* end Pixar tags */ + { TIFFTAG_RICHTIFFIPTC, -3, -3, TIFF_LONG, FIELD_CUSTOM, + 0, 1, "RichTIFFIPTC" }, + { TIFFTAG_PHOTOSHOP, -3, -3, TIFF_BYTE, FIELD_CUSTOM, + 0, 1, "Photoshop" }, + { TIFFTAG_EXIFIFD, 1, 1, TIFF_LONG, FIELD_CUSTOM, + 0, 0, "EXIFIFDOffset" }, + { TIFFTAG_ICCPROFILE, -3, -3, TIFF_UNDEFINED, FIELD_CUSTOM, + 0, 1, "ICC Profile" }, + { TIFFTAG_GPSIFD, 1, 1, TIFF_LONG, FIELD_CUSTOM, + 0, 0, "GPSIFDOffset" }, + { TIFFTAG_STONITS, 1, 1, TIFF_DOUBLE, FIELD_CUSTOM, + 0, 0, "StoNits" }, + { TIFFTAG_INTEROPERABILITYIFD, 1, 1, TIFF_LONG, FIELD_CUSTOM, + 0, 0, "InteroperabilityIFDOffset" }, +/* begin DNG tags */ + { TIFFTAG_DNGVERSION, 4, 4, TIFF_BYTE, FIELD_CUSTOM, + 0, 0, "DNGVersion" }, + { TIFFTAG_DNGBACKWARDVERSION, 4, 4, TIFF_BYTE, FIELD_CUSTOM, + 0, 0, "DNGBackwardVersion" }, + { TIFFTAG_UNIQUECAMERAMODEL, -1, -1, TIFF_ASCII, FIELD_CUSTOM, + 1, 0, "UniqueCameraModel" }, + { TIFFTAG_LOCALIZEDCAMERAMODEL, -1, -1, TIFF_ASCII, FIELD_CUSTOM, + 1, 0, "LocalizedCameraModel" }, + { TIFFTAG_LOCALIZEDCAMERAMODEL, -1, -1, TIFF_BYTE, FIELD_CUSTOM, + 1, 1, "LocalizedCameraModel" }, + { TIFFTAG_CFAPLANECOLOR, -1, -1, TIFF_BYTE, FIELD_CUSTOM, + 0, 1, "CFAPlaneColor" }, + { TIFFTAG_CFALAYOUT, 1, 1, TIFF_SHORT, FIELD_CUSTOM, + 0, 0, "CFALayout" }, + { TIFFTAG_LINEARIZATIONTABLE, -1, -1, TIFF_SHORT, FIELD_CUSTOM, + 0, 1, "LinearizationTable" }, + { TIFFTAG_BLACKLEVELREPEATDIM, 2, 2, TIFF_SHORT, FIELD_CUSTOM, + 0, 0, "BlackLevelRepeatDim" }, + { TIFFTAG_BLACKLEVEL, -1, -1, TIFF_LONG, FIELD_CUSTOM, + 0, 1, "BlackLevel" }, + { TIFFTAG_BLACKLEVEL, -1, -1, TIFF_SHORT, FIELD_CUSTOM, + 0, 1, "BlackLevel" }, + { TIFFTAG_BLACKLEVEL, -1, -1, TIFF_RATIONAL, FIELD_CUSTOM, + 0, 1, "BlackLevel" }, + { TIFFTAG_BLACKLEVELDELTAH, -1, -1, TIFF_SRATIONAL, FIELD_CUSTOM, + 0, 1, "BlackLevelDeltaH" }, + { TIFFTAG_BLACKLEVELDELTAV, -1, -1, TIFF_SRATIONAL, FIELD_CUSTOM, + 0, 1, "BlackLevelDeltaV" }, + { TIFFTAG_WHITELEVEL, -2, -2, TIFF_LONG, FIELD_CUSTOM, + 0, 0, "WhiteLevel" }, + { TIFFTAG_WHITELEVEL, -2, -2, TIFF_SHORT, FIELD_CUSTOM, + 0, 0, "WhiteLevel" }, + { TIFFTAG_DEFAULTSCALE, 2, 2, TIFF_RATIONAL, FIELD_CUSTOM, + 0, 0, "DefaultScale" }, + { TIFFTAG_BESTQUALITYSCALE, 1, 1, TIFF_RATIONAL, FIELD_CUSTOM, + 0, 0, "BestQualityScale" }, + { TIFFTAG_DEFAULTCROPORIGIN, 2, 2, TIFF_LONG, FIELD_CUSTOM, + 0, 0, "DefaultCropOrigin" }, + { TIFFTAG_DEFAULTCROPORIGIN, 2, 2, TIFF_SHORT, FIELD_CUSTOM, + 0, 0, "DefaultCropOrigin" }, + { TIFFTAG_DEFAULTCROPORIGIN, 2, 2, TIFF_RATIONAL, FIELD_CUSTOM, + 0, 0, "DefaultCropOrigin" }, + { TIFFTAG_DEFAULTCROPSIZE, 2, 2, TIFF_LONG, FIELD_CUSTOM, + 0, 0, "DefaultCropSize" }, + { TIFFTAG_DEFAULTCROPSIZE, 2, 2, TIFF_SHORT, FIELD_CUSTOM, + 0, 0, "DefaultCropSize" }, + { TIFFTAG_DEFAULTCROPSIZE, 2, 2, TIFF_RATIONAL, FIELD_CUSTOM, + 0, 0, "DefaultCropSize" }, + { TIFFTAG_COLORMATRIX1, -1, -1, TIFF_SRATIONAL, FIELD_CUSTOM, + 0, 1, "ColorMatrix1" }, + { TIFFTAG_COLORMATRIX2, -1, -1, TIFF_SRATIONAL, FIELD_CUSTOM, + 0, 1, "ColorMatrix2" }, + { TIFFTAG_CAMERACALIBRATION1, -1, -1, TIFF_SRATIONAL, FIELD_CUSTOM, + 0, 1, "CameraCalibration1" }, + { TIFFTAG_CAMERACALIBRATION2, -1, -1, TIFF_SRATIONAL, FIELD_CUSTOM, + 0, 1, "CameraCalibration2" }, + { TIFFTAG_REDUCTIONMATRIX1, -1, -1, TIFF_SRATIONAL, FIELD_CUSTOM, + 0, 1, "ReductionMatrix1" }, + { TIFFTAG_REDUCTIONMATRIX2, -1, -1, TIFF_SRATIONAL, FIELD_CUSTOM, + 0, 1, "ReductionMatrix2" }, + { TIFFTAG_ANALOGBALANCE, -1, -1, TIFF_RATIONAL, FIELD_CUSTOM, + 0, 1, "AnalogBalance" }, + { TIFFTAG_ASSHOTNEUTRAL, -1, -1, TIFF_SHORT, FIELD_CUSTOM, + 0, 1, "AsShotNeutral" }, + { TIFFTAG_ASSHOTNEUTRAL, -1, -1, TIFF_RATIONAL, FIELD_CUSTOM, + 0, 1, "AsShotNeutral" }, + { TIFFTAG_ASSHOTWHITEXY, 2, 2, TIFF_RATIONAL, FIELD_CUSTOM, + 0, 0, "AsShotWhiteXY" }, + { TIFFTAG_BASELINEEXPOSURE, 1, 1, TIFF_SRATIONAL, FIELD_CUSTOM, + 0, 0, "BaselineExposure" }, + { TIFFTAG_BASELINENOISE, 1, 1, TIFF_RATIONAL, FIELD_CUSTOM, + 0, 0, "BaselineNoise" }, + { TIFFTAG_BASELINESHARPNESS, 1, 1, TIFF_RATIONAL, FIELD_CUSTOM, + 0, 0, "BaselineSharpness" }, + { TIFFTAG_BAYERGREENSPLIT, 1, 1, TIFF_LONG, FIELD_CUSTOM, + 0, 0, "BayerGreenSplit" }, + { TIFFTAG_LINEARRESPONSELIMIT, 1, 1, TIFF_RATIONAL, FIELD_CUSTOM, + 0, 0, "LinearResponseLimit" }, + { TIFFTAG_CAMERASERIALNUMBER, -1, -1, TIFF_ASCII, FIELD_CUSTOM, + 1, 0, "CameraSerialNumber" }, + { TIFFTAG_LENSINFO, 4, 4, TIFF_RATIONAL, FIELD_CUSTOM, + 0, 0, "LensInfo" }, + { TIFFTAG_CHROMABLURRADIUS, 1, 1, TIFF_RATIONAL, FIELD_CUSTOM, + 0, 0, "ChromaBlurRadius" }, + { TIFFTAG_ANTIALIASSTRENGTH, 1, 1, TIFF_RATIONAL, FIELD_CUSTOM, + 0, 0, "AntiAliasStrength" }, + { TIFFTAG_SHADOWSCALE, 1, 1, TIFF_RATIONAL, FIELD_CUSTOM, + 0, 0, "ShadowScale" }, + { TIFFTAG_DNGPRIVATEDATA, -1, -1, TIFF_BYTE, FIELD_CUSTOM, + 0, 1, "DNGPrivateData" }, + { TIFFTAG_MAKERNOTESAFETY, 1, 1, TIFF_SHORT, FIELD_CUSTOM, + 0, 0, "MakerNoteSafety" }, + { TIFFTAG_CALIBRATIONILLUMINANT1, 1, 1, TIFF_SHORT, FIELD_CUSTOM, + 0, 0, "CalibrationIlluminant1" }, + { TIFFTAG_CALIBRATIONILLUMINANT2, 1, 1, TIFF_SHORT, FIELD_CUSTOM, + 0, 0, "CalibrationIlluminant2" }, + { TIFFTAG_RAWDATAUNIQUEID, 16, 16, TIFF_BYTE, FIELD_CUSTOM, + 0, 0, "RawDataUniqueID" }, + { TIFFTAG_ORIGINALRAWFILENAME, -1, -1, TIFF_ASCII, FIELD_CUSTOM, + 1, 0, "OriginalRawFileName" }, + { TIFFTAG_ORIGINALRAWFILENAME, -1, -1, TIFF_BYTE, FIELD_CUSTOM, + 1, 1, "OriginalRawFileName" }, + { TIFFTAG_ORIGINALRAWFILEDATA, -1, -1, TIFF_UNDEFINED, FIELD_CUSTOM, + 0, 1, "OriginalRawFileData" }, + { TIFFTAG_ACTIVEAREA, 4, 4, TIFF_LONG, FIELD_CUSTOM, + 0, 0, "ActiveArea" }, + { TIFFTAG_ACTIVEAREA, 4, 4, TIFF_SHORT, FIELD_CUSTOM, + 0, 0, "ActiveArea" }, + { TIFFTAG_MASKEDAREAS, -1, -1, TIFF_LONG, FIELD_CUSTOM, + 0, 1, "MaskedAreas" }, + { TIFFTAG_ASSHOTICCPROFILE, -1, -1, TIFF_UNDEFINED, FIELD_CUSTOM, + 0, 1, "AsShotICCProfile" }, + { TIFFTAG_ASSHOTPREPROFILEMATRIX, -1, -1, TIFF_SRATIONAL, FIELD_CUSTOM, + 0, 1, "AsShotPreProfileMatrix" }, + { TIFFTAG_CURRENTICCPROFILE, -1, -1, TIFF_UNDEFINED, FIELD_CUSTOM, + 0, 1, "CurrentICCProfile" }, + { TIFFTAG_CURRENTPREPROFILEMATRIX, -1, -1, TIFF_SRATIONAL, FIELD_CUSTOM, + 0, 1, "CurrentPreProfileMatrix" }, +/* end DNG tags */ +}; + +static const TIFFFieldInfo +exifFieldInfo[] = { + { EXIFTAG_EXPOSURETIME, 1, 1, TIFF_RATIONAL, FIELD_CUSTOM, + 1, 0, "ExposureTime" }, + { EXIFTAG_FNUMBER, 1, 1, TIFF_RATIONAL, FIELD_CUSTOM, + 1, 0, "FNumber" }, + { EXIFTAG_EXPOSUREPROGRAM, 1, 1, TIFF_SHORT, FIELD_CUSTOM, + 1, 0, "ExposureProgram" }, + { EXIFTAG_SPECTRALSENSITIVITY, -1, -1, TIFF_ASCII, FIELD_CUSTOM, + 1, 0, "SpectralSensitivity" }, + { EXIFTAG_ISOSPEEDRATINGS, -1, -1, TIFF_SHORT, FIELD_CUSTOM, + 1, 1, "ISOSpeedRatings" }, + { EXIFTAG_OECF, -1, -1, TIFF_UNDEFINED, FIELD_CUSTOM, + 1, 1, "OptoelectricConversionFactor" }, + { EXIFTAG_EXIFVERSION, 4, 4, TIFF_UNDEFINED, FIELD_CUSTOM, + 1, 0, "ExifVersion" }, + { EXIFTAG_DATETIMEORIGINAL, 20, 20, TIFF_ASCII, FIELD_CUSTOM, + 1, 0, "DateTimeOriginal" }, + { EXIFTAG_DATETIMEDIGITIZED, 20, 20, TIFF_ASCII, FIELD_CUSTOM, + 1, 0, "DateTimeDigitized" }, + { EXIFTAG_COMPONENTSCONFIGURATION, 4, 4, TIFF_UNDEFINED, FIELD_CUSTOM, + 1, 0, "ComponentsConfiguration" }, + { EXIFTAG_COMPRESSEDBITSPERPIXEL, 1, 1, TIFF_RATIONAL, FIELD_CUSTOM, + 1, 0, "CompressedBitsPerPixel" }, + { EXIFTAG_SHUTTERSPEEDVALUE, 1, 1, TIFF_SRATIONAL, FIELD_CUSTOM, + 1, 0, "ShutterSpeedValue" }, + { EXIFTAG_APERTUREVALUE, 1, 1, TIFF_RATIONAL, FIELD_CUSTOM, + 1, 0, "ApertureValue" }, + { EXIFTAG_BRIGHTNESSVALUE, 1, 1, TIFF_SRATIONAL, FIELD_CUSTOM, + 1, 0, "BrightnessValue" }, + { EXIFTAG_EXPOSUREBIASVALUE, 1, 1, TIFF_SRATIONAL, FIELD_CUSTOM, + 1, 0, "ExposureBiasValue" }, + { EXIFTAG_MAXAPERTUREVALUE, 1, 1, TIFF_RATIONAL, FIELD_CUSTOM, + 1, 0, "MaxApertureValue" }, + { EXIFTAG_SUBJECTDISTANCE, 1, 1, TIFF_RATIONAL, FIELD_CUSTOM, + 1, 0, "SubjectDistance" }, + { EXIFTAG_METERINGMODE, 1, 1, TIFF_SHORT, FIELD_CUSTOM, + 1, 0, "MeteringMode" }, + { EXIFTAG_LIGHTSOURCE, 1, 1, TIFF_SHORT, FIELD_CUSTOM, + 1, 0, "LightSource" }, + { EXIFTAG_FLASH, 1, 1, TIFF_SHORT, FIELD_CUSTOM, + 1, 0, "Flash" }, + { EXIFTAG_FOCALLENGTH, 1, 1, TIFF_RATIONAL, FIELD_CUSTOM, + 1, 0, "FocalLength" }, + { EXIFTAG_SUBJECTAREA, -1, -1, TIFF_SHORT, FIELD_CUSTOM, + 1, 1, "SubjectArea" }, + { EXIFTAG_MAKERNOTE, -1, -1, TIFF_UNDEFINED, FIELD_CUSTOM, + 1, 1, "MakerNote" }, + { EXIFTAG_USERCOMMENT, -1, -1, TIFF_UNDEFINED, FIELD_CUSTOM, + 1, 1, "UserComment" }, + { EXIFTAG_SUBSECTIME, -1, -1, TIFF_ASCII, FIELD_CUSTOM, + 1, 0, "SubSecTime" }, + { EXIFTAG_SUBSECTIMEORIGINAL, -1, -1, TIFF_ASCII, FIELD_CUSTOM, + 1, 0, "SubSecTimeOriginal" }, + { EXIFTAG_SUBSECTIMEDIGITIZED,-1, -1, TIFF_ASCII, FIELD_CUSTOM, + 1, 0, "SubSecTimeDigitized" }, + { EXIFTAG_FLASHPIXVERSION, 4, 4, TIFF_UNDEFINED, FIELD_CUSTOM, + 1, 0, "FlashpixVersion" }, + { EXIFTAG_COLORSPACE, 1, 1, TIFF_SHORT, FIELD_CUSTOM, + 1, 0, "ColorSpace" }, + { EXIFTAG_PIXELXDIMENSION, 1, 1, TIFF_LONG, FIELD_CUSTOM, + 1, 0, "PixelXDimension" }, + { EXIFTAG_PIXELXDIMENSION, 1, 1, TIFF_SHORT, FIELD_CUSTOM, + 1, 0, "PixelXDimension" }, + { EXIFTAG_PIXELYDIMENSION, 1, 1, TIFF_LONG, FIELD_CUSTOM, + 1, 0, "PixelYDimension" }, + { EXIFTAG_PIXELYDIMENSION, 1, 1, TIFF_SHORT, FIELD_CUSTOM, + 1, 0, "PixelYDimension" }, + { EXIFTAG_RELATEDSOUNDFILE, 13, 13, TIFF_ASCII, FIELD_CUSTOM, + 1, 0, "RelatedSoundFile" }, + { EXIFTAG_FLASHENERGY, 1, 1, TIFF_RATIONAL, FIELD_CUSTOM, + 1, 0, "FlashEnergy" }, + { EXIFTAG_SPATIALFREQUENCYRESPONSE, -1, -1, TIFF_UNDEFINED, FIELD_CUSTOM, + 1, 1, "SpatialFrequencyResponse" }, + { EXIFTAG_FOCALPLANEXRESOLUTION, 1, 1, TIFF_RATIONAL, FIELD_CUSTOM, + 1, 0, "FocalPlaneXResolution" }, + { EXIFTAG_FOCALPLANEYRESOLUTION, 1, 1, TIFF_RATIONAL, FIELD_CUSTOM, + 1, 0, "FocalPlaneYResolution" }, + { EXIFTAG_FOCALPLANERESOLUTIONUNIT, 1, 1, TIFF_SHORT, FIELD_CUSTOM, + 1, 0, "FocalPlaneResolutionUnit" }, + { EXIFTAG_SUBJECTLOCATION, 2, 2, TIFF_SHORT, FIELD_CUSTOM, + 1, 0, "SubjectLocation" }, + { EXIFTAG_EXPOSUREINDEX, 1, 1, TIFF_RATIONAL, FIELD_CUSTOM, + 1, 0, "ExposureIndex" }, + { EXIFTAG_SENSINGMETHOD, 1, 1, TIFF_SHORT, FIELD_CUSTOM, + 1, 0, "SensingMethod" }, + { EXIFTAG_FILESOURCE, 1, 1, TIFF_UNDEFINED, FIELD_CUSTOM, + 1, 0, "FileSource" }, + { EXIFTAG_SCENETYPE, 1, 1, TIFF_UNDEFINED, FIELD_CUSTOM, + 1, 0, "SceneType" }, + { EXIFTAG_CFAPATTERN, -1, -1, TIFF_UNDEFINED, FIELD_CUSTOM, + 1, 1, "CFAPattern" }, + { EXIFTAG_CUSTOMRENDERED, 1, 1, TIFF_SHORT, FIELD_CUSTOM, + 1, 0, "CustomRendered" }, + { EXIFTAG_EXPOSUREMODE, 1, 1, TIFF_SHORT, FIELD_CUSTOM, + 1, 0, "ExposureMode" }, + { EXIFTAG_WHITEBALANCE, 1, 1, TIFF_SHORT, FIELD_CUSTOM, + 1, 0, "WhiteBalance" }, + { EXIFTAG_DIGITALZOOMRATIO, 1, 1, TIFF_RATIONAL, FIELD_CUSTOM, + 1, 0, "DigitalZoomRatio" }, + { EXIFTAG_FOCALLENGTHIN35MMFILM, 1, 1, TIFF_SHORT, FIELD_CUSTOM, + 1, 0, "FocalLengthIn35mmFilm" }, + { EXIFTAG_SCENECAPTURETYPE, 1, 1, TIFF_SHORT, FIELD_CUSTOM, + 1, 0, "SceneCaptureType" }, + { EXIFTAG_GAINCONTROL, 1, 1, TIFF_RATIONAL, FIELD_CUSTOM, + 1, 0, "GainControl" }, + { EXIFTAG_CONTRAST, 1, 1, TIFF_SHORT, FIELD_CUSTOM, + 1, 0, "Contrast" }, + { EXIFTAG_SATURATION, 1, 1, TIFF_SHORT, FIELD_CUSTOM, + 1, 0, "Saturation" }, + { EXIFTAG_SHARPNESS, 1, 1, TIFF_SHORT, FIELD_CUSTOM, + 1, 0, "Sharpness" }, + { EXIFTAG_DEVICESETTINGDESCRIPTION, -1, -1, TIFF_UNDEFINED, FIELD_CUSTOM, + 1, 1, "DeviceSettingDescription" }, + { EXIFTAG_SUBJECTDISTANCERANGE, 1, 1, TIFF_SHORT, FIELD_CUSTOM, + 1, 0, "SubjectDistanceRange" }, + { EXIFTAG_IMAGEUNIQUEID, 33, 33, TIFF_ASCII, FIELD_CUSTOM, + 1, 0, "ImageUniqueID" } +}; + +const TIFFFieldInfo * +_TIFFGetFieldInfo(size_t *size) +{ + *size = TIFFArrayCount(tiffFieldInfo); + return tiffFieldInfo; +} + +const TIFFFieldInfo * +_TIFFGetExifFieldInfo(size_t *size) +{ + *size = TIFFArrayCount(exifFieldInfo); + return exifFieldInfo; +} + +void +_TIFFSetupFieldInfo(TIFF* tif, const TIFFFieldInfo info[], size_t n) +{ + if (tif->tif_fieldinfo) { + size_t i; + + for (i = 0; i < tif->tif_nfields; i++) + { + TIFFFieldInfo *fld = tif->tif_fieldinfo[i]; + if (fld->field_bit == FIELD_CUSTOM && + strncmp("Tag ", fld->field_name, 4) == 0) { + _TIFFfree(fld->field_name); + _TIFFfree(fld); + } + } + + _TIFFfree(tif->tif_fieldinfo); + tif->tif_nfields = 0; + } + if (!_TIFFMergeFieldInfo(tif, info, n)) + { + TIFFErrorExt(tif->tif_clientdata, "_TIFFSetupFieldInfo", + "Setting up field info failed"); + } +} + +static int +tagCompare(const void* a, const void* b) +{ + const TIFFFieldInfo* ta = *(const TIFFFieldInfo**) a; + const TIFFFieldInfo* tb = *(const TIFFFieldInfo**) b; + /* NB: be careful of return values for 16-bit platforms */ + if (ta->field_tag != tb->field_tag) + return (int)ta->field_tag - (int)tb->field_tag; + else + return (ta->field_type == TIFF_ANY) ? + 0 : ((int)tb->field_type - (int)ta->field_type); +} + +static int +tagNameCompare(const void* a, const void* b) +{ + const TIFFFieldInfo* ta = *(const TIFFFieldInfo**) a; + const TIFFFieldInfo* tb = *(const TIFFFieldInfo**) b; + int ret = strcmp(ta->field_name, tb->field_name); + + if (ret) + return ret; + else + return (ta->field_type == TIFF_ANY) ? + 0 : ((int)tb->field_type - (int)ta->field_type); +} + +void +TIFFMergeFieldInfo(TIFF* tif, const TIFFFieldInfo info[], int n) +{ + if (_TIFFMergeFieldInfo(tif, info, n) < 0) + { + TIFFErrorExt(tif->tif_clientdata, "TIFFMergeFieldInfo", + "Merging block of %d fields failed", n); + } +} + +int +_TIFFMergeFieldInfo(TIFF* tif, const TIFFFieldInfo info[], int n) +{ + static const char module[] = "_TIFFMergeFieldInfo"; + static const char reason[] = "for field info array"; + TIFFFieldInfo** tp; + int i; + + tif->tif_foundfield = NULL; + + if (tif->tif_nfields > 0) { + tif->tif_fieldinfo = (TIFFFieldInfo**) + _TIFFCheckRealloc(tif, tif->tif_fieldinfo, + (tif->tif_nfields + n), + sizeof (TIFFFieldInfo*), reason); + } else { + tif->tif_fieldinfo = (TIFFFieldInfo**) + _TIFFCheckMalloc(tif, n, sizeof (TIFFFieldInfo*), + reason); + } + if (!tif->tif_fieldinfo) { + TIFFErrorExt(tif->tif_clientdata, module, + "Failed to allocate field info array"); + return 0; + } + tp = tif->tif_fieldinfo + tif->tif_nfields; + for (i = 0; i < n; i++) + { + const TIFFFieldInfo *fip = + _TIFFFindFieldInfo(tif, info[i].field_tag, info[i].field_type); + + /* only add definitions that aren't already present */ + if (!fip) { + *tp++ = (TIFFFieldInfo*) (info + i); + tif->tif_nfields++; + } + } + + /* Sort the field info by tag number */ + qsort(tif->tif_fieldinfo, tif->tif_nfields, + sizeof (TIFFFieldInfo*), tagCompare); + + return n; +} + +void +_TIFFPrintFieldInfo(TIFF* tif, FILE* fd) +{ + size_t i; + + fprintf(fd, "%s: \n", tif->tif_name); + for (i = 0; i < tif->tif_nfields; i++) { + const TIFFFieldInfo* fip = tif->tif_fieldinfo[i]; + fprintf(fd, "field[%2d] %5lu, %2d, %2d, %d, %2d, %5s, %5s, %s\n" + , (int)i + , (unsigned long) fip->field_tag + , fip->field_readcount, fip->field_writecount + , fip->field_type + , fip->field_bit + , fip->field_oktochange ? "TRUE" : "FALSE" + , fip->field_passcount ? "TRUE" : "FALSE" + , fip->field_name + ); + } +} + +/* + * Return size of TIFFDataType in bytes + */ +int +TIFFDataWidth(TIFFDataType type) +{ + switch(type) + { + case 0: /* nothing */ + case 1: /* TIFF_BYTE */ + case 2: /* TIFF_ASCII */ + case 6: /* TIFF_SBYTE */ + case 7: /* TIFF_UNDEFINED */ + return 1; + case 3: /* TIFF_SHORT */ + case 8: /* TIFF_SSHORT */ + return 2; + case 4: /* TIFF_LONG */ + case 9: /* TIFF_SLONG */ + case 11: /* TIFF_FLOAT */ + case 13: /* TIFF_IFD */ + return 4; + case 5: /* TIFF_RATIONAL */ + case 10: /* TIFF_SRATIONAL */ + case 12: /* TIFF_DOUBLE */ + return 8; + default: + return 0; /* will return 0 for unknown types */ + } +} + +/* + * Return size of TIFFDataType in bytes. + * + * XXX: We need a separate function to determine the space needed + * to store the value. For TIFF_RATIONAL values TIFFDataWidth() returns 8, + * but we use 4-byte float to represent rationals. + */ +int +_TIFFDataSize(TIFFDataType type) +{ + switch (type) { + case TIFF_BYTE: + case TIFF_SBYTE: + case TIFF_ASCII: + case TIFF_UNDEFINED: + return 1; + case TIFF_SHORT: + case TIFF_SSHORT: + return 2; + case TIFF_LONG: + case TIFF_SLONG: + case TIFF_FLOAT: + case TIFF_IFD: + case TIFF_RATIONAL: + case TIFF_SRATIONAL: + return 4; + case TIFF_DOUBLE: + return 8; + default: + return 0; + } +} + +/* + * Return nearest TIFFDataType to the sample type of an image. + */ +TIFFDataType +_TIFFSampleToTagType(TIFF* tif) +{ + uint32 bps = TIFFhowmany8(tif->tif_dir.td_bitspersample); + + switch (tif->tif_dir.td_sampleformat) { + case SAMPLEFORMAT_IEEEFP: + return (bps == 4 ? TIFF_FLOAT : TIFF_DOUBLE); + case SAMPLEFORMAT_INT: + return (bps <= 1 ? TIFF_SBYTE : + bps <= 2 ? TIFF_SSHORT : TIFF_SLONG); + case SAMPLEFORMAT_UINT: + return (bps <= 1 ? TIFF_BYTE : + bps <= 2 ? TIFF_SHORT : TIFF_LONG); + case SAMPLEFORMAT_VOID: + return (TIFF_UNDEFINED); + } + /*NOTREACHED*/ + return (TIFF_UNDEFINED); +} + +const TIFFFieldInfo* +_TIFFFindFieldInfo(TIFF* tif, ttag_t tag, TIFFDataType dt) +{ + TIFFFieldInfo key = {0, 0, 0, TIFF_NOTYPE, 0, 0, 0, 0}; + TIFFFieldInfo* pkey = &key; + const TIFFFieldInfo **ret; + + if (tif->tif_foundfield && tif->tif_foundfield->field_tag == tag && + (dt == TIFF_ANY || dt == tif->tif_foundfield->field_type)) + return tif->tif_foundfield; + + /* If we are invoked with no field information, then just return. */ + if ( !tif->tif_fieldinfo ) { + return NULL; + } + + /* NB: use sorted search (e.g. binary search) */ + key.field_tag = tag; + key.field_type = dt; + + ret = (const TIFFFieldInfo **) bsearch(&pkey, + tif->tif_fieldinfo, + tif->tif_nfields, + sizeof(TIFFFieldInfo *), + tagCompare); + return tif->tif_foundfield = (ret ? *ret : NULL); +} + +const TIFFFieldInfo* +_TIFFFindFieldInfoByName(TIFF* tif, const char *field_name, TIFFDataType dt) +{ + TIFFFieldInfo key = {0, 0, 0, TIFF_NOTYPE, 0, 0, 0, 0}; + TIFFFieldInfo* pkey = &key; + const TIFFFieldInfo **ret; + + if (tif->tif_foundfield + && streq(tif->tif_foundfield->field_name, field_name) + && (dt == TIFF_ANY || dt == tif->tif_foundfield->field_type)) + return (tif->tif_foundfield); + + /* If we are invoked with no field information, then just return. */ + if ( !tif->tif_fieldinfo ) { + return NULL; + } + + /* NB: use sorted search (e.g. binary search) */ + key.field_name = (char *)field_name; + key.field_type = dt; + + ret = (const TIFFFieldInfo **) lfind(&pkey, + tif->tif_fieldinfo, + &tif->tif_nfields, + sizeof(TIFFFieldInfo *), + tagNameCompare); + return tif->tif_foundfield = (ret ? *ret : NULL); +} + +const TIFFFieldInfo* +_TIFFFieldWithTag(TIFF* tif, ttag_t tag) +{ + const TIFFFieldInfo* fip = _TIFFFindFieldInfo(tif, tag, TIFF_ANY); + if (!fip) { + TIFFErrorExt(tif->tif_clientdata, "TIFFFieldWithTag", + "Internal error, unknown tag 0x%x", + (unsigned int) tag); + assert(fip != NULL); + /*NOTREACHED*/ + } + return (fip); +} + +const TIFFFieldInfo* +_TIFFFieldWithName(TIFF* tif, const char *field_name) +{ + const TIFFFieldInfo* fip = + _TIFFFindFieldInfoByName(tif, field_name, TIFF_ANY); + if (!fip) { + TIFFErrorExt(tif->tif_clientdata, "TIFFFieldWithName", + "Internal error, unknown tag %s", field_name); + assert(fip != NULL); + /*NOTREACHED*/ + } + return (fip); +} + +const TIFFFieldInfo* +_TIFFFindOrRegisterFieldInfo( TIFF *tif, ttag_t tag, TIFFDataType dt ) + +{ + const TIFFFieldInfo *fld; + + fld = _TIFFFindFieldInfo( tif, tag, dt ); + if( fld == NULL ) + { + fld = _TIFFCreateAnonFieldInfo( tif, tag, dt ); + if (!_TIFFMergeFieldInfo(tif, fld, 1)) + return NULL; + } + + return fld; +} + +TIFFFieldInfo* +_TIFFCreateAnonFieldInfo(TIFF *tif, ttag_t tag, TIFFDataType field_type) +{ + TIFFFieldInfo *fld; + (void) tif; + + fld = (TIFFFieldInfo *) _TIFFmalloc(sizeof (TIFFFieldInfo)); + if (fld == NULL) + return NULL; + _TIFFmemset( fld, 0, sizeof(TIFFFieldInfo) ); + + fld->field_tag = tag; + fld->field_readcount = TIFF_VARIABLE2; + fld->field_writecount = TIFF_VARIABLE2; + fld->field_type = field_type; + fld->field_bit = FIELD_CUSTOM; + fld->field_oktochange = TRUE; + fld->field_passcount = TRUE; + fld->field_name = (char *) _TIFFmalloc(32); + if (fld->field_name == NULL) { + _TIFFfree(fld); + return NULL; + } + + /* + * note that this name is a special sign to TIFFClose() and + * _TIFFSetupFieldInfo() to free the field + */ + sprintf(fld->field_name, "Tag %d", (int) tag); + + return fld; +} + +/* vim: set ts=8 sts=8 sw=8 noet: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tif_dirread.c b/reactos/dll/3rdparty/libtiff/tif_dirread.c new file mode 100644 index 00000000000..907b53188c8 --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tif_dirread.c @@ -0,0 +1,2081 @@ +/* $Id: tif_dirread.c,v 1.92.2.9 2010-06-14 00:21:46 fwarmerdam Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library. + * + * Directory Read Support Routines. + */ +#include "tiffiop.h" + +#define IGNORE 0 /* tag placeholder used below */ + +#ifdef HAVE_IEEEFP +# define TIFFCvtIEEEFloatToNative(tif, n, fp) +# define TIFFCvtIEEEDoubleToNative(tif, n, dp) +#else +extern void TIFFCvtIEEEFloatToNative(TIFF*, uint32, float*); +extern void TIFFCvtIEEEDoubleToNative(TIFF*, uint32, double*); +#endif + +static TIFFDirEntry* TIFFReadDirectoryFind(TIFFDirEntry* dir, + uint16 dircount, uint16 tagid); +static int EstimateStripByteCounts(TIFF*, TIFFDirEntry*, uint16); +static void MissingRequired(TIFF*, const char*); +static int TIFFCheckDirOffset(TIFF*, toff_t); +static int CheckDirCount(TIFF*, TIFFDirEntry*, uint32); +static uint16 TIFFFetchDirectory(TIFF*, toff_t, TIFFDirEntry**, toff_t *); +static tsize_t TIFFFetchData(TIFF*, TIFFDirEntry*, char*); +static tsize_t TIFFFetchString(TIFF*, TIFFDirEntry*, char*); +static float TIFFFetchRational(TIFF*, TIFFDirEntry*); +static int TIFFFetchNormalTag(TIFF*, TIFFDirEntry*); +static int TIFFFetchPerSampleShorts(TIFF*, TIFFDirEntry*, uint16*); +static int TIFFFetchPerSampleLongs(TIFF*, TIFFDirEntry*, uint32*); +static int TIFFFetchPerSampleAnys(TIFF*, TIFFDirEntry*, double*); +static int TIFFFetchShortArray(TIFF*, TIFFDirEntry*, uint16*); +static int TIFFFetchStripThing(TIFF*, TIFFDirEntry*, long, uint32**); +static int TIFFFetchRefBlackWhite(TIFF*, TIFFDirEntry*); +static int TIFFFetchSubjectDistance(TIFF*, TIFFDirEntry*); +static float TIFFFetchFloat(TIFF*, TIFFDirEntry*); +static int TIFFFetchFloatArray(TIFF*, TIFFDirEntry*, float*); +static int TIFFFetchDoubleArray(TIFF*, TIFFDirEntry*, double*); +static int TIFFFetchAnyArray(TIFF*, TIFFDirEntry*, double*); +static int TIFFFetchShortPair(TIFF*, TIFFDirEntry*); +static void ChopUpSingleUncompressedStrip(TIFF*); + +/* + * Read the next TIFF directory from a file and convert it to the internal + * format. We read directories sequentially. + */ +int +TIFFReadDirectory(TIFF* tif) +{ + static const char module[] = "TIFFReadDirectory"; + + int n; + TIFFDirectory* td; + TIFFDirEntry *dp, *dir = NULL; + uint16 iv; + uint32 v; + const TIFFFieldInfo* fip; + size_t fix; + uint16 dircount; + int diroutoforderwarning = 0, compressionknown = 0; + int haveunknowntags = 0; + + tif->tif_diroff = tif->tif_nextdiroff; + /* + * Check whether we have the last offset or bad offset (IFD looping). + */ + if (!TIFFCheckDirOffset(tif, tif->tif_nextdiroff)) + return 0; + /* + * Cleanup any previous compression state. + */ + (*tif->tif_cleanup)(tif); + tif->tif_curdir++; + dircount = TIFFFetchDirectory(tif, tif->tif_nextdiroff, + &dir, &tif->tif_nextdiroff); + if (!dircount) { + TIFFErrorExt(tif->tif_clientdata, module, + "%s: Failed to read directory at offset %u", + tif->tif_name, tif->tif_nextdiroff); + return 0; + } + + tif->tif_flags &= ~TIFF_BEENWRITING; /* reset before new dir */ + /* + * Setup default value and then make a pass over + * the fields to check type and tag information, + * and to extract info required to size data + * structures. A second pass is made afterwards + * to read in everthing not taken in the first pass. + */ + td = &tif->tif_dir; + /* free any old stuff and reinit */ + TIFFFreeDirectory(tif); + TIFFDefaultDirectory(tif); + /* + * Electronic Arts writes gray-scale TIFF files + * without a PlanarConfiguration directory entry. + * Thus we setup a default value here, even though + * the TIFF spec says there is no default value. + */ + TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); + + /* + * Sigh, we must make a separate pass through the + * directory for the following reason: + * + * We must process the Compression tag in the first pass + * in order to merge in codec-private tag definitions (otherwise + * we may get complaints about unknown tags). However, the + * Compression tag may be dependent on the SamplesPerPixel + * tag value because older TIFF specs permited Compression + * to be written as a SamplesPerPixel-count tag entry. + * Thus if we don't first figure out the correct SamplesPerPixel + * tag value then we may end up ignoring the Compression tag + * value because it has an incorrect count value (if the + * true value of SamplesPerPixel is not 1). + * + * It sure would have been nice if Aldus had really thought + * this stuff through carefully. + */ + for (dp = dir, n = dircount; n > 0; n--, dp++) { + if (tif->tif_flags & TIFF_SWAB) { + TIFFSwabArrayOfShort(&dp->tdir_tag, 2); + TIFFSwabArrayOfLong(&dp->tdir_count, 2); + } + if (dp->tdir_tag == TIFFTAG_SAMPLESPERPIXEL) { + if (!TIFFFetchNormalTag(tif, dp)) + goto bad; + dp->tdir_tag = IGNORE; + } + } + /* + * First real pass over the directory. + */ + fix = 0; + for (dp = dir, n = dircount; n > 0; n--, dp++) { + + if (dp->tdir_tag == IGNORE) + continue; + if (fix >= tif->tif_nfields) + fix = 0; + + /* + * Silicon Beach (at least) writes unordered + * directory tags (violating the spec). Handle + * it here, but be obnoxious (maybe they'll fix it?). + */ + if (dp->tdir_tag < tif->tif_fieldinfo[fix]->field_tag) { + if (!diroutoforderwarning) { + TIFFWarningExt(tif->tif_clientdata, module, + "%s: invalid TIFF directory; tags are not sorted in ascending order", + tif->tif_name); + diroutoforderwarning = 1; + } + fix = 0; /* O(n^2) */ + } + while (fix < tif->tif_nfields && + tif->tif_fieldinfo[fix]->field_tag < dp->tdir_tag) + fix++; + if (fix >= tif->tif_nfields || + tif->tif_fieldinfo[fix]->field_tag != dp->tdir_tag) { + /* Unknown tag ... we'll deal with it below */ + haveunknowntags = 1; + continue; + } + /* + * Null out old tags that we ignore. + */ + if (tif->tif_fieldinfo[fix]->field_bit == FIELD_IGNORE) { + ignore: + dp->tdir_tag = IGNORE; + continue; + } + /* + * Check data type. + */ + fip = tif->tif_fieldinfo[fix]; + while (dp->tdir_type != (unsigned short) fip->field_type + && fix < tif->tif_nfields) { + if (fip->field_type == TIFF_ANY) /* wildcard */ + break; + fip = tif->tif_fieldinfo[++fix]; + if (fix >= tif->tif_nfields || + fip->field_tag != dp->tdir_tag) { + TIFFWarningExt(tif->tif_clientdata, module, + "%s: wrong data type %d for \"%s\"; tag ignored", + tif->tif_name, dp->tdir_type, + tif->tif_fieldinfo[fix-1]->field_name); + goto ignore; + } + } + /* + * Check count if known in advance. + */ + if (fip->field_readcount != TIFF_VARIABLE + && fip->field_readcount != TIFF_VARIABLE2) { + uint32 expected = (fip->field_readcount == TIFF_SPP) ? + (uint32) td->td_samplesperpixel : + (uint32) fip->field_readcount; + if (!CheckDirCount(tif, dp, expected)) + goto ignore; + } + + switch (dp->tdir_tag) { + case TIFFTAG_COMPRESSION: + /* + * The 5.0 spec says the Compression tag has + * one value, while earlier specs say it has + * one value per sample. Because of this, we + * accept the tag if one value is supplied. + */ + if (dp->tdir_count == 1) { + v = TIFFExtractData(tif, + dp->tdir_type, dp->tdir_offset); + if (!TIFFSetField(tif, dp->tdir_tag, (uint16)v)) + goto bad; + else + compressionknown = 1; + break; + /* XXX: workaround for broken TIFFs */ + } else if (dp->tdir_type == TIFF_LONG) { + if (!TIFFFetchPerSampleLongs(tif, dp, &v) || + !TIFFSetField(tif, dp->tdir_tag, (uint16)v)) + goto bad; + } else { + if (!TIFFFetchPerSampleShorts(tif, dp, &iv) + || !TIFFSetField(tif, dp->tdir_tag, iv)) + goto bad; + } + dp->tdir_tag = IGNORE; + break; + case TIFFTAG_STRIPOFFSETS: + case TIFFTAG_STRIPBYTECOUNTS: + case TIFFTAG_TILEOFFSETS: + case TIFFTAG_TILEBYTECOUNTS: + TIFFSetFieldBit(tif, fip->field_bit); + break; + case TIFFTAG_IMAGEWIDTH: + case TIFFTAG_IMAGELENGTH: + case TIFFTAG_IMAGEDEPTH: + case TIFFTAG_TILELENGTH: + case TIFFTAG_TILEWIDTH: + case TIFFTAG_TILEDEPTH: + case TIFFTAG_PLANARCONFIG: + case TIFFTAG_ROWSPERSTRIP: + case TIFFTAG_EXTRASAMPLES: + if (!TIFFFetchNormalTag(tif, dp)) + goto bad; + dp->tdir_tag = IGNORE; + break; + } + } + + /* + * If we saw any unknown tags, make an extra pass over the directory + * to deal with them. This must be done separately because the tags + * could have become known when we registered a codec after finding + * the Compression tag. In a correctly-sorted directory there's + * no problem because Compression will come before any codec-private + * tags, but if the sorting is wrong that might not hold. + */ + if (haveunknowntags) { + fix = 0; + for (dp = dir, n = dircount; n > 0; n--, dp++) { + if (dp->tdir_tag == IGNORE) + continue; + if (fix >= tif->tif_nfields || + dp->tdir_tag < tif->tif_fieldinfo[fix]->field_tag) + fix = 0; /* O(n^2) */ + while (fix < tif->tif_nfields && + tif->tif_fieldinfo[fix]->field_tag < dp->tdir_tag) + fix++; + if (fix >= tif->tif_nfields || + tif->tif_fieldinfo[fix]->field_tag != dp->tdir_tag) { + + TIFFWarningExt(tif->tif_clientdata, + module, + "%s: unknown field with tag %d (0x%x) encountered", + tif->tif_name, + dp->tdir_tag, + dp->tdir_tag); + + if (!_TIFFMergeFieldInfo(tif, + _TIFFCreateAnonFieldInfo(tif, + dp->tdir_tag, + (TIFFDataType) dp->tdir_type), + 1)) + { + TIFFWarningExt(tif->tif_clientdata, + module, + "Registering anonymous field with tag %d (0x%x) failed", + dp->tdir_tag, + dp->tdir_tag); + dp->tdir_tag = IGNORE; + continue; + } + fix = 0; + while (fix < tif->tif_nfields && + tif->tif_fieldinfo[fix]->field_tag < dp->tdir_tag) + fix++; + } + /* + * Check data type. + */ + fip = tif->tif_fieldinfo[fix]; + while (dp->tdir_type != (unsigned short) fip->field_type + && fix < tif->tif_nfields) { + if (fip->field_type == TIFF_ANY) /* wildcard */ + break; + fip = tif->tif_fieldinfo[++fix]; + if (fix >= tif->tif_nfields || + fip->field_tag != dp->tdir_tag) { + TIFFWarningExt(tif->tif_clientdata, module, + "%s: wrong data type %d for \"%s\"; tag ignored", + tif->tif_name, dp->tdir_type, + tif->tif_fieldinfo[fix-1]->field_name); + dp->tdir_tag = IGNORE; + break; + } + } + } + } + + /* + * XXX: OJPEG hack. + * If a) compression is OJPEG, b) planarconfig tag says it's separate, + * c) strip offsets/bytecounts tag are both present and + * d) both contain exactly one value, then we consistently find + * that the buggy implementation of the buggy compression scheme + * matches contig planarconfig best. So we 'fix-up' the tag here + */ + if ((td->td_compression==COMPRESSION_OJPEG) && + (td->td_planarconfig==PLANARCONFIG_SEPARATE)) { + dp = TIFFReadDirectoryFind(dir,dircount,TIFFTAG_STRIPOFFSETS); + if ((dp!=0) && (dp->tdir_count==1)) { + dp = TIFFReadDirectoryFind(dir, dircount, + TIFFTAG_STRIPBYTECOUNTS); + if ((dp!=0) && (dp->tdir_count==1)) { + td->td_planarconfig=PLANARCONFIG_CONTIG; + TIFFWarningExt(tif->tif_clientdata, + "TIFFReadDirectory", + "Planarconfig tag value assumed incorrect, " + "assuming data is contig instead of chunky"); + } + } + } + + /* + * Allocate directory structure and setup defaults. + */ + if (!TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS)) { + MissingRequired(tif, "ImageLength"); + goto bad; + } + /* + * Setup appropriate structures (by strip or by tile) + */ + if (!TIFFFieldSet(tif, FIELD_TILEDIMENSIONS)) { + td->td_nstrips = TIFFNumberOfStrips(tif); + td->td_tilewidth = td->td_imagewidth; + td->td_tilelength = td->td_rowsperstrip; + td->td_tiledepth = td->td_imagedepth; + tif->tif_flags &= ~TIFF_ISTILED; + } else { + td->td_nstrips = TIFFNumberOfTiles(tif); + tif->tif_flags |= TIFF_ISTILED; + } + if (!td->td_nstrips) { + TIFFErrorExt(tif->tif_clientdata, module, + "%s: cannot handle zero number of %s", + tif->tif_name, isTiled(tif) ? "tiles" : "strips"); + goto bad; + } + td->td_stripsperimage = td->td_nstrips; + if (td->td_planarconfig == PLANARCONFIG_SEPARATE) + td->td_stripsperimage /= td->td_samplesperpixel; + if (!TIFFFieldSet(tif, FIELD_STRIPOFFSETS)) { + if ((td->td_compression==COMPRESSION_OJPEG) && + (isTiled(tif)==0) && + (td->td_nstrips==1)) { + /* + * XXX: OJPEG hack. + * If a) compression is OJPEG, b) it's not a tiled TIFF, + * and c) the number of strips is 1, + * then we tolerate the absence of stripoffsets tag, + * because, presumably, all required data is in the + * JpegInterchangeFormat stream. + */ + TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS); + } else { + MissingRequired(tif, + isTiled(tif) ? "TileOffsets" : "StripOffsets"); + goto bad; + } + } + + /* + * Second pass: extract other information. + */ + for (dp = dir, n = dircount; n > 0; n--, dp++) { + if (dp->tdir_tag == IGNORE) + continue; + switch (dp->tdir_tag) { + case TIFFTAG_MINSAMPLEVALUE: + case TIFFTAG_MAXSAMPLEVALUE: + case TIFFTAG_BITSPERSAMPLE: + case TIFFTAG_DATATYPE: + case TIFFTAG_SAMPLEFORMAT: + /* + * The 5.0 spec says the Compression tag has + * one value, while earlier specs say it has + * one value per sample. Because of this, we + * accept the tag if one value is supplied. + * + * The MinSampleValue, MaxSampleValue, BitsPerSample + * DataType and SampleFormat tags are supposed to be + * written as one value/sample, but some vendors + * incorrectly write one value only -- so we accept + * that as well (yech). Other vendors write correct + * value for NumberOfSamples, but incorrect one for + * BitsPerSample and friends, and we will read this + * too. + */ + if (dp->tdir_count == 1) { + v = TIFFExtractData(tif, + dp->tdir_type, dp->tdir_offset); + if (!TIFFSetField(tif, dp->tdir_tag, (uint16)v)) + goto bad; + /* XXX: workaround for broken TIFFs */ + } else if (dp->tdir_tag == TIFFTAG_BITSPERSAMPLE + && dp->tdir_type == TIFF_LONG) { + if (!TIFFFetchPerSampleLongs(tif, dp, &v) || + !TIFFSetField(tif, dp->tdir_tag, (uint16)v)) + goto bad; + } else { + if (!TIFFFetchPerSampleShorts(tif, dp, &iv) || + !TIFFSetField(tif, dp->tdir_tag, iv)) + goto bad; + } + break; + case TIFFTAG_SMINSAMPLEVALUE: + case TIFFTAG_SMAXSAMPLEVALUE: + { + double dv = 0.0; + if (!TIFFFetchPerSampleAnys(tif, dp, &dv) || + !TIFFSetField(tif, dp->tdir_tag, dv)) + goto bad; + } + break; + case TIFFTAG_STRIPOFFSETS: + case TIFFTAG_TILEOFFSETS: + if (!TIFFFetchStripThing(tif, dp, + td->td_nstrips, &td->td_stripoffset)) + goto bad; + break; + case TIFFTAG_STRIPBYTECOUNTS: + case TIFFTAG_TILEBYTECOUNTS: + if (!TIFFFetchStripThing(tif, dp, + td->td_nstrips, &td->td_stripbytecount)) + goto bad; + break; + case TIFFTAG_COLORMAP: + case TIFFTAG_TRANSFERFUNCTION: + { + char* cp; + /* + * TransferFunction can have either 1x or 3x + * data values; Colormap can have only 3x + * items. + */ + v = 1L<td_bitspersample; + if (dp->tdir_tag == TIFFTAG_COLORMAP || + dp->tdir_count != v) { + if (!CheckDirCount(tif, dp, 3 * v)) + break; + } + v *= sizeof(uint16); + cp = (char *)_TIFFCheckMalloc(tif, + dp->tdir_count, + sizeof (uint16), + "to read \"TransferFunction\" tag"); + if (cp != NULL) { + if (TIFFFetchData(tif, dp, cp)) { + /* + * This deals with there being + * only one array to apply to + * all samples. + */ + uint32 c = 1L << td->td_bitspersample; + if (dp->tdir_count == c) + v = 0L; + TIFFSetField(tif, dp->tdir_tag, + cp, cp+v, cp+2*v); + } + _TIFFfree(cp); + } + break; + } + case TIFFTAG_PAGENUMBER: + case TIFFTAG_HALFTONEHINTS: + case TIFFTAG_YCBCRSUBSAMPLING: + case TIFFTAG_DOTRANGE: + (void) TIFFFetchShortPair(tif, dp); + break; + case TIFFTAG_REFERENCEBLACKWHITE: + (void) TIFFFetchRefBlackWhite(tif, dp); + break; +/* BEGIN REV 4.0 COMPATIBILITY */ + case TIFFTAG_OSUBFILETYPE: + v = 0L; + switch (TIFFExtractData(tif, dp->tdir_type, + dp->tdir_offset)) { + case OFILETYPE_REDUCEDIMAGE: + v = FILETYPE_REDUCEDIMAGE; + break; + case OFILETYPE_PAGE: + v = FILETYPE_PAGE; + break; + } + if (v) + TIFFSetField(tif, TIFFTAG_SUBFILETYPE, v); + break; +/* END REV 4.0 COMPATIBILITY */ + default: + (void) TIFFFetchNormalTag(tif, dp); + break; + } + } + /* + * OJPEG hack: + * - If a) compression is OJPEG, and b) photometric tag is missing, + * then we consistently find that photometric should be YCbCr + * - If a) compression is OJPEG, and b) photometric tag says it's RGB, + * then we consistently find that the buggy implementation of the + * buggy compression scheme matches photometric YCbCr instead. + * - If a) compression is OJPEG, and b) bitspersample tag is missing, + * then we consistently find bitspersample should be 8. + * - If a) compression is OJPEG, b) samplesperpixel tag is missing, + * and c) photometric is RGB or YCbCr, then we consistently find + * samplesperpixel should be 3 + * - If a) compression is OJPEG, b) samplesperpixel tag is missing, + * and c) photometric is MINISWHITE or MINISBLACK, then we consistently + * find samplesperpixel should be 3 + */ + if (td->td_compression==COMPRESSION_OJPEG) + { + if (!TIFFFieldSet(tif,FIELD_PHOTOMETRIC)) + { + TIFFWarningExt(tif->tif_clientdata, "TIFFReadDirectory", + "Photometric tag is missing, assuming data is YCbCr"); + if (!TIFFSetField(tif,TIFFTAG_PHOTOMETRIC,PHOTOMETRIC_YCBCR)) + goto bad; + } + else if (td->td_photometric==PHOTOMETRIC_RGB) + { + td->td_photometric=PHOTOMETRIC_YCBCR; + TIFFWarningExt(tif->tif_clientdata, "TIFFReadDirectory", + "Photometric tag value assumed incorrect, " + "assuming data is YCbCr instead of RGB"); + } + if (!TIFFFieldSet(tif,FIELD_BITSPERSAMPLE)) + { + TIFFWarningExt(tif->tif_clientdata,"TIFFReadDirectory", + "BitsPerSample tag is missing, assuming 8 bits per sample"); + if (!TIFFSetField(tif,TIFFTAG_BITSPERSAMPLE,8)) + goto bad; + } + if (!TIFFFieldSet(tif,FIELD_SAMPLESPERPIXEL)) + { + if ((td->td_photometric==PHOTOMETRIC_RGB) + || (td->td_photometric==PHOTOMETRIC_YCBCR)) + { + TIFFWarningExt(tif->tif_clientdata, + "TIFFReadDirectory", + "SamplesPerPixel tag is missing, " + "assuming correct SamplesPerPixel value is 3"); + if (!TIFFSetField(tif,TIFFTAG_SAMPLESPERPIXEL,3)) + goto bad; + } + else if ((td->td_photometric==PHOTOMETRIC_MINISWHITE) + || (td->td_photometric==PHOTOMETRIC_MINISBLACK)) + { + TIFFWarningExt(tif->tif_clientdata, + "TIFFReadDirectory", + "SamplesPerPixel tag is missing, " + "assuming correct SamplesPerPixel value is 1"); + if (!TIFFSetField(tif,TIFFTAG_SAMPLESPERPIXEL,1)) + goto bad; + } + } + } + /* + * Verify Palette image has a Colormap. + */ + if (td->td_photometric == PHOTOMETRIC_PALETTE && + !TIFFFieldSet(tif, FIELD_COLORMAP)) { + MissingRequired(tif, "Colormap"); + goto bad; + } + /* + * OJPEG hack: + * We do no further messing with strip/tile offsets/bytecounts in OJPEG + * TIFFs + */ + if (td->td_compression!=COMPRESSION_OJPEG) + { + /* + * Attempt to deal with a missing StripByteCounts tag. + */ + if (!TIFFFieldSet(tif, FIELD_STRIPBYTECOUNTS)) { + /* + * Some manufacturers violate the spec by not giving + * the size of the strips. In this case, assume there + * is one uncompressed strip of data. + */ + if ((td->td_planarconfig == PLANARCONFIG_CONTIG && + td->td_nstrips > 1) || + (td->td_planarconfig == PLANARCONFIG_SEPARATE && + td->td_nstrips != td->td_samplesperpixel)) { + MissingRequired(tif, "StripByteCounts"); + goto bad; + } + TIFFWarningExt(tif->tif_clientdata, module, + "%s: TIFF directory is missing required " + "\"%s\" field, calculating from imagelength", + tif->tif_name, + _TIFFFieldWithTag(tif,TIFFTAG_STRIPBYTECOUNTS)->field_name); + if (EstimateStripByteCounts(tif, dir, dircount) < 0) + goto bad; + /* + * Assume we have wrong StripByteCount value (in case + * of single strip) in following cases: + * - it is equal to zero along with StripOffset; + * - it is larger than file itself (in case of uncompressed + * image); + * - it is smaller than the size of the bytes per row + * multiplied on the number of rows. The last case should + * not be checked in the case of writing new image, + * because we may do not know the exact strip size + * until the whole image will be written and directory + * dumped out. + */ + #define BYTECOUNTLOOKSBAD \ + ( (td->td_stripbytecount[0] == 0 && td->td_stripoffset[0] != 0) || \ + (td->td_compression == COMPRESSION_NONE && \ + td->td_stripbytecount[0] > TIFFGetFileSize(tif) - td->td_stripoffset[0]) || \ + (tif->tif_mode == O_RDONLY && \ + td->td_compression == COMPRESSION_NONE && \ + td->td_stripbytecount[0] < TIFFScanlineSize(tif) * td->td_imagelength) ) + + } else if (td->td_nstrips == 1 + && td->td_stripoffset[0] != 0 + && BYTECOUNTLOOKSBAD) { + /* + * XXX: Plexus (and others) sometimes give a value of + * zero for a tag when they don't know what the + * correct value is! Try and handle the simple case + * of estimating the size of a one strip image. + */ + TIFFWarningExt(tif->tif_clientdata, module, + "%s: Bogus \"%s\" field, ignoring and calculating from imagelength", + tif->tif_name, + _TIFFFieldWithTag(tif,TIFFTAG_STRIPBYTECOUNTS)->field_name); + if(EstimateStripByteCounts(tif, dir, dircount) < 0) + goto bad; + } else if (td->td_planarconfig == PLANARCONFIG_CONTIG + && td->td_nstrips > 2 + && td->td_compression == COMPRESSION_NONE + && td->td_stripbytecount[0] != td->td_stripbytecount[1] + && td->td_stripbytecount[0] != 0 + && td->td_stripbytecount[1] != 0 ) { + /* + * XXX: Some vendors fill StripByteCount array with + * absolutely wrong values (it can be equal to + * StripOffset array, for example). Catch this case + * here. + */ + TIFFWarningExt(tif->tif_clientdata, module, + "%s: Wrong \"%s\" field, ignoring and calculating from imagelength", + tif->tif_name, + _TIFFFieldWithTag(tif,TIFFTAG_STRIPBYTECOUNTS)->field_name); + if (EstimateStripByteCounts(tif, dir, dircount) < 0) + goto bad; + } + } + if (dir) { + _TIFFfree((char *)dir); + dir = NULL; + } + if (!TIFFFieldSet(tif, FIELD_MAXSAMPLEVALUE)) + td->td_maxsamplevalue = (uint16)((1L<td_bitspersample)-1); + /* + * Setup default compression scheme. + */ + + /* + * XXX: We can optimize checking for the strip bounds using the sorted + * bytecounts array. See also comments for TIFFAppendToStrip() + * function in tif_write.c. + */ + if (td->td_nstrips > 1) { + tstrip_t strip; + + td->td_stripbytecountsorted = 1; + for (strip = 1; strip < td->td_nstrips; strip++) { + if (td->td_stripoffset[strip - 1] > + td->td_stripoffset[strip]) { + td->td_stripbytecountsorted = 0; + break; + } + } + } + + if (!TIFFFieldSet(tif, FIELD_COMPRESSION)) + TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE); + /* + * Some manufacturers make life difficult by writing + * large amounts of uncompressed data as a single strip. + * This is contrary to the recommendations of the spec. + * The following makes an attempt at breaking such images + * into strips closer to the recommended 8k bytes. A + * side effect, however, is that the RowsPerStrip tag + * value may be changed. + */ + if (td->td_nstrips == 1 && td->td_compression == COMPRESSION_NONE && + (tif->tif_flags & (TIFF_STRIPCHOP|TIFF_ISTILED)) == TIFF_STRIPCHOP) + ChopUpSingleUncompressedStrip(tif); + + /* + * Reinitialize i/o since we are starting on a new directory. + */ + tif->tif_row = (uint32) -1; + tif->tif_curstrip = (tstrip_t) -1; + tif->tif_col = (uint32) -1; + tif->tif_curtile = (ttile_t) -1; + tif->tif_tilesize = (tsize_t) -1; + + tif->tif_scanlinesize = TIFFScanlineSize(tif); + if (!tif->tif_scanlinesize) { + TIFFErrorExt(tif->tif_clientdata, module, + "%s: cannot handle zero scanline size", + tif->tif_name); + return (0); + } + + if (isTiled(tif)) { + tif->tif_tilesize = TIFFTileSize(tif); + if (!tif->tif_tilesize) { + TIFFErrorExt(tif->tif_clientdata, module, + "%s: cannot handle zero tile size", + tif->tif_name); + return (0); + } + } else { + if (!TIFFStripSize(tif)) { + TIFFErrorExt(tif->tif_clientdata, module, + "%s: cannot handle zero strip size", + tif->tif_name); + return (0); + } + } + return (1); +bad: + if (dir) + _TIFFfree(dir); + return (0); +} + +static TIFFDirEntry* +TIFFReadDirectoryFind(TIFFDirEntry* dir, uint16 dircount, uint16 tagid) +{ + TIFFDirEntry* m; + uint16 n; + for (m=dir, n=0; ntdir_tag==tagid) + return(m); + } + return(0); +} + +/* + * Read custom directory from the arbitarry offset. + * The code is very similar to TIFFReadDirectory(). + */ +int +TIFFReadCustomDirectory(TIFF* tif, toff_t diroff, + const TIFFFieldInfo info[], size_t n) +{ + static const char module[] = "TIFFReadCustomDirectory"; + + TIFFDirectory* td = &tif->tif_dir; + TIFFDirEntry *dp, *dir = NULL; + const TIFFFieldInfo* fip; + size_t fix; + uint16 i, dircount; + + _TIFFSetupFieldInfo(tif, info, n); + + dircount = TIFFFetchDirectory(tif, diroff, &dir, NULL); + if (!dircount) { + TIFFErrorExt(tif->tif_clientdata, module, + "%s: Failed to read custom directory at offset %u", + tif->tif_name, diroff); + return 0; + } + + TIFFFreeDirectory(tif); + _TIFFmemset(&tif->tif_dir, 0, sizeof(TIFFDirectory)); + + fix = 0; + for (dp = dir, i = dircount; i > 0; i--, dp++) { + if (tif->tif_flags & TIFF_SWAB) { + TIFFSwabArrayOfShort(&dp->tdir_tag, 2); + TIFFSwabArrayOfLong(&dp->tdir_count, 2); + } + + if (fix >= tif->tif_nfields || dp->tdir_tag == IGNORE) + continue; + + while (fix < tif->tif_nfields && + tif->tif_fieldinfo[fix]->field_tag < dp->tdir_tag) + fix++; + + if (fix >= tif->tif_nfields || + tif->tif_fieldinfo[fix]->field_tag != dp->tdir_tag) { + + TIFFWarningExt(tif->tif_clientdata, module, + "%s: unknown field with tag %d (0x%x) encountered", + tif->tif_name, dp->tdir_tag, dp->tdir_tag); + if (!_TIFFMergeFieldInfo(tif, + _TIFFCreateAnonFieldInfo(tif, + dp->tdir_tag, + (TIFFDataType) dp->tdir_type), + 1)) + { + TIFFWarningExt(tif->tif_clientdata, module, + "Registering anonymous field with tag %d (0x%x) failed", + dp->tdir_tag, dp->tdir_tag); + goto ignore; + } + + fix = 0; + while (fix < tif->tif_nfields && + tif->tif_fieldinfo[fix]->field_tag < dp->tdir_tag) + fix++; + } + /* + * Null out old tags that we ignore. + */ + if (tif->tif_fieldinfo[fix]->field_bit == FIELD_IGNORE) { + ignore: + dp->tdir_tag = IGNORE; + continue; + } + /* + * Check data type. + */ + fip = tif->tif_fieldinfo[fix]; + while (dp->tdir_type != (unsigned short) fip->field_type + && fix < tif->tif_nfields) { + if (fip->field_type == TIFF_ANY) /* wildcard */ + break; + fip = tif->tif_fieldinfo[++fix]; + if (fix >= tif->tif_nfields || + fip->field_tag != dp->tdir_tag) { + TIFFWarningExt(tif->tif_clientdata, module, + "%s: wrong data type %d for \"%s\"; tag ignored", + tif->tif_name, dp->tdir_type, + tif->tif_fieldinfo[fix-1]->field_name); + goto ignore; + } + } + /* + * Check count if known in advance. + */ + if (fip->field_readcount != TIFF_VARIABLE + && fip->field_readcount != TIFF_VARIABLE2) { + uint32 expected = (fip->field_readcount == TIFF_SPP) ? + (uint32) td->td_samplesperpixel : + (uint32) fip->field_readcount; + if (!CheckDirCount(tif, dp, expected)) + goto ignore; + } + + /* + * EXIF tags which need to be specifically processed. + */ + switch (dp->tdir_tag) { + case EXIFTAG_SUBJECTDISTANCE: + (void) TIFFFetchSubjectDistance(tif, dp); + break; + default: + (void) TIFFFetchNormalTag(tif, dp); + break; + } + } + + if (dir) + _TIFFfree(dir); + return 1; +} + +/* + * EXIF is important special case of custom IFD, so we have a special + * function to read it. + */ +int +TIFFReadEXIFDirectory(TIFF* tif, toff_t diroff) +{ + size_t exifFieldInfoCount; + const TIFFFieldInfo *exifFieldInfo = + _TIFFGetExifFieldInfo(&exifFieldInfoCount); + return TIFFReadCustomDirectory(tif, diroff, exifFieldInfo, + exifFieldInfoCount); +} + +static int +EstimateStripByteCounts(TIFF* tif, TIFFDirEntry* dir, uint16 dircount) +{ + static const char module[] = "EstimateStripByteCounts"; + + TIFFDirEntry *dp; + TIFFDirectory *td = &tif->tif_dir; + uint32 strip; + + if (td->td_stripbytecount) + _TIFFfree(td->td_stripbytecount); + td->td_stripbytecount = (uint32*) + _TIFFCheckMalloc(tif, td->td_nstrips, sizeof (uint32), + "for \"StripByteCounts\" array"); + if( td->td_stripbytecount == NULL ) + return -1; + + if (td->td_compression != COMPRESSION_NONE) { + uint32 space = (uint32)(sizeof (TIFFHeader) + + sizeof (uint16) + + (dircount * sizeof (TIFFDirEntry)) + + sizeof (uint32)); + toff_t filesize = TIFFGetFileSize(tif); + uint16 n; + + /* calculate amount of space used by indirect values */ + for (dp = dir, n = dircount; n > 0; n--, dp++) + { + uint32 cc = TIFFDataWidth((TIFFDataType) dp->tdir_type); + if (cc == 0) { + TIFFErrorExt(tif->tif_clientdata, module, + "%s: Cannot determine size of unknown tag type %d", + tif->tif_name, dp->tdir_type); + return -1; + } + cc = cc * dp->tdir_count; + if (cc > sizeof (uint32)) + space += cc; + } + space = filesize - space; + if (td->td_planarconfig == PLANARCONFIG_SEPARATE) + space /= td->td_samplesperpixel; + for (strip = 0; strip < td->td_nstrips; strip++) + td->td_stripbytecount[strip] = space; + /* + * This gross hack handles the case were the offset to + * the last strip is past the place where we think the strip + * should begin. Since a strip of data must be contiguous, + * it's safe to assume that we've overestimated the amount + * of data in the strip and trim this number back accordingly. + */ + strip--; + if (((toff_t)(td->td_stripoffset[strip]+ + td->td_stripbytecount[strip])) > filesize) + td->td_stripbytecount[strip] = + filesize - td->td_stripoffset[strip]; + } else if (isTiled(tif)) { + uint32 bytespertile = TIFFTileSize(tif); + + for (strip = 0; strip < td->td_nstrips; strip++) + td->td_stripbytecount[strip] = bytespertile; + } else { + uint32 rowbytes = TIFFScanlineSize(tif); + uint32 rowsperstrip = td->td_imagelength/td->td_stripsperimage; + for (strip = 0; strip < td->td_nstrips; strip++) + td->td_stripbytecount[strip] = rowbytes * rowsperstrip; + } + TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS); + if (!TIFFFieldSet(tif, FIELD_ROWSPERSTRIP)) + td->td_rowsperstrip = td->td_imagelength; + return 1; +} + +static void +MissingRequired(TIFF* tif, const char* tagname) +{ + static const char module[] = "MissingRequired"; + + TIFFErrorExt(tif->tif_clientdata, module, + "%s: TIFF directory is missing required \"%s\" field", + tif->tif_name, tagname); +} + +/* + * Check the directory offset against the list of already seen directory + * offsets. This is a trick to prevent IFD looping. The one can create TIFF + * file with looped directory pointers. We will maintain a list of already + * seen directories and check every IFD offset against that list. + */ +static int +TIFFCheckDirOffset(TIFF* tif, toff_t diroff) +{ + uint16 n; + + if (diroff == 0) /* no more directories */ + return 0; + + for (n = 0; n < tif->tif_dirnumber && tif->tif_dirlist; n++) { + if (tif->tif_dirlist[n] == diroff) + return 0; + } + + tif->tif_dirnumber++; + + if (tif->tif_dirnumber > tif->tif_dirlistsize) { + toff_t* new_dirlist; + + /* + * XXX: Reduce memory allocation granularity of the dirlist + * array. + */ + new_dirlist = (toff_t *)_TIFFCheckRealloc(tif, + tif->tif_dirlist, + tif->tif_dirnumber, + 2 * sizeof(toff_t), + "for IFD list"); + if (!new_dirlist) + return 0; + tif->tif_dirlistsize = 2 * tif->tif_dirnumber; + tif->tif_dirlist = new_dirlist; + } + + tif->tif_dirlist[tif->tif_dirnumber - 1] = diroff; + + return 1; +} + +/* + * Check the count field of a directory entry against a known value. The + * caller is expected to skip/ignore the tag if there is a mismatch. + */ +static int +CheckDirCount(TIFF* tif, TIFFDirEntry* dir, uint32 count) +{ + if (count > dir->tdir_count) { + TIFFWarningExt(tif->tif_clientdata, tif->tif_name, + "incorrect count for field \"%s\" (%u, expecting %u); tag ignored", + _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name, + dir->tdir_count, count); + return (0); + } else if (count < dir->tdir_count) { + TIFFWarningExt(tif->tif_clientdata, tif->tif_name, + "incorrect count for field \"%s\" (%u, expecting %u); tag trimmed", + _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name, + dir->tdir_count, count); + return (1); + } + return (1); +} + +/* + * Read IFD structure from the specified offset. If the pointer to + * nextdiroff variable has been specified, read it too. Function returns a + * number of fields in the directory or 0 if failed. + */ +static uint16 +TIFFFetchDirectory(TIFF* tif, toff_t diroff, TIFFDirEntry **pdir, + toff_t *nextdiroff) +{ + static const char module[] = "TIFFFetchDirectory"; + + TIFFDirEntry *dir; + uint16 dircount; + + assert(pdir); + + tif->tif_diroff = diroff; + if (nextdiroff) + *nextdiroff = 0; + if (!isMapped(tif)) { + if (!SeekOK(tif, tif->tif_diroff)) { + TIFFErrorExt(tif->tif_clientdata, module, + "%s: Seek error accessing TIFF directory", + tif->tif_name); + return 0; + } + if (!ReadOK(tif, &dircount, sizeof (uint16))) { + TIFFErrorExt(tif->tif_clientdata, module, + "%s: Can not read TIFF directory count", + tif->tif_name); + return 0; + } + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabShort(&dircount); + dir = (TIFFDirEntry *)_TIFFCheckMalloc(tif, dircount, + sizeof (TIFFDirEntry), + "to read TIFF directory"); + if (dir == NULL) + return 0; + if (!ReadOK(tif, dir, dircount*sizeof (TIFFDirEntry))) { + TIFFErrorExt(tif->tif_clientdata, module, + "%.100s: Can not read TIFF directory", + tif->tif_name); + _TIFFfree(dir); + return 0; + } + /* + * Read offset to next directory for sequential scans if + * needed. + */ + if (nextdiroff) + (void) ReadOK(tif, nextdiroff, sizeof(uint32)); + } else { + toff_t off = tif->tif_diroff; + + /* + * Check for integer overflow when validating the dir_off, + * otherwise a very high offset may cause an OOB read and + * crash the client. Make two comparisons instead of + * + * off + sizeof(uint16) > tif->tif_size + * + * to avoid overflow. + */ + if (tif->tif_size < sizeof (uint16) || + off > tif->tif_size - sizeof(uint16)) { + TIFFErrorExt(tif->tif_clientdata, module, + "%s: Can not read TIFF directory count", + tif->tif_name); + return 0; + } else { + _TIFFmemcpy(&dircount, tif->tif_base + off, + sizeof(uint16)); + } + off += sizeof (uint16); + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabShort(&dircount); + dir = (TIFFDirEntry *)_TIFFCheckMalloc(tif, dircount, + sizeof(TIFFDirEntry), + "to read TIFF directory"); + if (dir == NULL) + return 0; + if (off + dircount * sizeof (TIFFDirEntry) > tif->tif_size) { + TIFFErrorExt(tif->tif_clientdata, module, + "%s: Can not read TIFF directory", + tif->tif_name); + _TIFFfree(dir); + return 0; + } else { + _TIFFmemcpy(dir, tif->tif_base + off, + dircount * sizeof(TIFFDirEntry)); + } + if (nextdiroff) { + off += dircount * sizeof (TIFFDirEntry); + if (off + sizeof (uint32) <= tif->tif_size) { + _TIFFmemcpy(nextdiroff, tif->tif_base + off, + sizeof (uint32)); + } + } + } + if (nextdiroff && tif->tif_flags & TIFF_SWAB) + TIFFSwabLong(nextdiroff); + *pdir = dir; + return dircount; +} + +/* + * Fetch a contiguous directory item. + */ +static tsize_t +TIFFFetchData(TIFF* tif, TIFFDirEntry* dir, char* cp) +{ + uint32 w = TIFFDataWidth((TIFFDataType) dir->tdir_type); + /* + * FIXME: butecount should have tsize_t type, but for now libtiff + * defines tsize_t as a signed 32-bit integer and we are losing + * ability to read arrays larger than 2^31 bytes. So we are using + * uint32 instead of tsize_t here. + */ + uint32 cc = dir->tdir_count * w; + + /* Check for overflow. */ + if (!dir->tdir_count || !w || cc / w != dir->tdir_count) + goto bad; + + if (!isMapped(tif)) { + if (!SeekOK(tif, dir->tdir_offset)) + goto bad; + if (!ReadOK(tif, cp, cc)) + goto bad; + } else { + /* Check for overflow. */ + if (dir->tdir_offset + cc < dir->tdir_offset + || dir->tdir_offset + cc < cc + || dir->tdir_offset + cc > tif->tif_size) + goto bad; + _TIFFmemcpy(cp, tif->tif_base + dir->tdir_offset, cc); + } + if (tif->tif_flags & TIFF_SWAB) { + switch (dir->tdir_type) { + case TIFF_SHORT: + case TIFF_SSHORT: + TIFFSwabArrayOfShort((uint16*) cp, dir->tdir_count); + break; + case TIFF_LONG: + case TIFF_SLONG: + case TIFF_FLOAT: + TIFFSwabArrayOfLong((uint32*) cp, dir->tdir_count); + break; + case TIFF_RATIONAL: + case TIFF_SRATIONAL: + TIFFSwabArrayOfLong((uint32*) cp, 2*dir->tdir_count); + break; + case TIFF_DOUBLE: + TIFFSwabArrayOfDouble((double*) cp, dir->tdir_count); + break; + } + } + return (cc); +bad: + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Error fetching data for field \"%s\"", + _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name); + return (tsize_t) 0; +} + +/* + * Fetch an ASCII item from the file. + */ +static tsize_t +TIFFFetchString(TIFF* tif, TIFFDirEntry* dir, char* cp) +{ + if (dir->tdir_count <= 4) { + uint32 l = dir->tdir_offset; + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabLong(&l); + _TIFFmemcpy(cp, &l, dir->tdir_count); + return (1); + } + return (TIFFFetchData(tif, dir, cp)); +} + +/* + * Convert numerator+denominator to float. + */ +static int +cvtRational(TIFF* tif, TIFFDirEntry* dir, uint32 num, uint32 denom, float* rv) +{ + if (denom == 0) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "%s: Rational with zero denominator (num = %u)", + _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name, num); + return (0); + } else { + if (dir->tdir_type == TIFF_RATIONAL) + *rv = ((float)num / (float)denom); + else + *rv = ((float)(int32)num / (float)(int32)denom); + return (1); + } +} + +/* + * Fetch a rational item from the file at offset off and return the value as a + * floating point number. + */ +static float +TIFFFetchRational(TIFF* tif, TIFFDirEntry* dir) +{ + uint32 l[2]; + float v; + + return (!TIFFFetchData(tif, dir, (char *)l) || + !cvtRational(tif, dir, l[0], l[1], &v) ? 1.0f : v); +} + +/* + * Fetch a single floating point value from the offset field and return it as + * a native float. + */ +static float +TIFFFetchFloat(TIFF* tif, TIFFDirEntry* dir) +{ + float v; + int32 l = TIFFExtractData(tif, dir->tdir_type, dir->tdir_offset); + _TIFFmemcpy(&v, &l, sizeof(float)); + TIFFCvtIEEEFloatToNative(tif, 1, &v); + return (v); +} + +/* + * Fetch an array of BYTE or SBYTE values. + */ +static int +TIFFFetchByteArray(TIFF* tif, TIFFDirEntry* dir, uint8* v) +{ + if (dir->tdir_count <= 4) { + /* + * Extract data from offset field. + */ + if (tif->tif_header.tiff_magic == TIFF_BIGENDIAN) { + if (dir->tdir_type == TIFF_SBYTE) + switch (dir->tdir_count) { + case 4: v[3] = dir->tdir_offset & 0xff; + case 3: v[2] = (dir->tdir_offset >> 8) & 0xff; + case 2: v[1] = (dir->tdir_offset >> 16) & 0xff; + case 1: v[0] = dir->tdir_offset >> 24; + } + else + switch (dir->tdir_count) { + case 4: v[3] = dir->tdir_offset & 0xff; + case 3: v[2] = (dir->tdir_offset >> 8) & 0xff; + case 2: v[1] = (dir->tdir_offset >> 16) & 0xff; + case 1: v[0] = dir->tdir_offset >> 24; + } + } else { + if (dir->tdir_type == TIFF_SBYTE) + switch (dir->tdir_count) { + case 4: v[3] = dir->tdir_offset >> 24; + case 3: v[2] = (dir->tdir_offset >> 16) & 0xff; + case 2: v[1] = (dir->tdir_offset >> 8) & 0xff; + case 1: v[0] = dir->tdir_offset & 0xff; + } + else + switch (dir->tdir_count) { + case 4: v[3] = dir->tdir_offset >> 24; + case 3: v[2] = (dir->tdir_offset >> 16) & 0xff; + case 2: v[1] = (dir->tdir_offset >> 8) & 0xff; + case 1: v[0] = dir->tdir_offset & 0xff; + } + } + return (1); + } else + return (TIFFFetchData(tif, dir, (char*) v) != 0); /* XXX */ +} + +/* + * Fetch an array of SHORT or SSHORT values. + */ +static int +TIFFFetchShortArray(TIFF* tif, TIFFDirEntry* dir, uint16* v) +{ + if (dir->tdir_count <= 2) { + if (tif->tif_header.tiff_magic == TIFF_BIGENDIAN) { + switch (dir->tdir_count) { + case 2: v[1] = (uint16) (dir->tdir_offset & 0xffff); + case 1: v[0] = (uint16) (dir->tdir_offset >> 16); + } + } else { + switch (dir->tdir_count) { + case 2: v[1] = (uint16) (dir->tdir_offset >> 16); + case 1: v[0] = (uint16) (dir->tdir_offset & 0xffff); + } + } + return (1); + } else + return (TIFFFetchData(tif, dir, (char *)v) != 0); +} + +/* + * Fetch a pair of SHORT or BYTE values. Some tags may have either BYTE + * or SHORT type and this function works with both ones. + */ +static int +TIFFFetchShortPair(TIFF* tif, TIFFDirEntry* dir) +{ + /* + * Prevent overflowing the v stack arrays below by performing a sanity + * check on tdir_count, this should never be greater than two. + */ + if (dir->tdir_count > 2) { + TIFFWarningExt(tif->tif_clientdata, tif->tif_name, + "unexpected count for field \"%s\", %u, expected 2; ignored", + _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name, + dir->tdir_count); + return 0; + } + + switch (dir->tdir_type) { + case TIFF_BYTE: + case TIFF_SBYTE: + { + uint8 v[4]; + return TIFFFetchByteArray(tif, dir, v) + && TIFFSetField(tif, dir->tdir_tag, v[0], v[1]); + } + case TIFF_SHORT: + case TIFF_SSHORT: + { + uint16 v[2]; + return TIFFFetchShortArray(tif, dir, v) + && TIFFSetField(tif, dir->tdir_tag, v[0], v[1]); + } + default: + return 0; + } +} + +/* + * Fetch an array of LONG or SLONG values. + */ +static int +TIFFFetchLongArray(TIFF* tif, TIFFDirEntry* dir, uint32* v) +{ + if (dir->tdir_count == 1) { + v[0] = dir->tdir_offset; + return (1); + } else + return (TIFFFetchData(tif, dir, (char*) v) != 0); +} + +/* + * Fetch an array of RATIONAL or SRATIONAL values. + */ +static int +TIFFFetchRationalArray(TIFF* tif, TIFFDirEntry* dir, float* v) +{ + int ok = 0; + uint32* l; + + l = (uint32*)_TIFFCheckMalloc(tif, + dir->tdir_count, TIFFDataWidth((TIFFDataType) dir->tdir_type), + "to fetch array of rationals"); + if (l) { + if (TIFFFetchData(tif, dir, (char *)l)) { + uint32 i; + for (i = 0; i < dir->tdir_count; i++) { + ok = cvtRational(tif, dir, + l[2*i+0], l[2*i+1], &v[i]); + if (!ok) + break; + } + } + _TIFFfree((char *)l); + } + return (ok); +} + +/* + * Fetch an array of FLOAT values. + */ +static int +TIFFFetchFloatArray(TIFF* tif, TIFFDirEntry* dir, float* v) +{ + + if (dir->tdir_count == 1) { + union + { + float f; + uint32 i; + } float_union; + + float_union.i=dir->tdir_offset; + v[0]=float_union.f; + TIFFCvtIEEEFloatToNative(tif, dir->tdir_count, v); + return (1); + } else if (TIFFFetchData(tif, dir, (char*) v)) { + TIFFCvtIEEEFloatToNative(tif, dir->tdir_count, v); + return (1); + } else + return (0); +} + +/* + * Fetch an array of DOUBLE values. + */ +static int +TIFFFetchDoubleArray(TIFF* tif, TIFFDirEntry* dir, double* v) +{ + if (TIFFFetchData(tif, dir, (char*) v)) { + TIFFCvtIEEEDoubleToNative(tif, dir->tdir_count, v); + return (1); + } else + return (0); +} + +/* + * Fetch an array of ANY values. The actual values are returned as doubles + * which should be able hold all the types. Yes, there really should be an + * tany_t to avoid this potential non-portability ... Note in particular that + * we assume that the double return value vector is large enough to read in + * any fundamental type. We use that vector as a buffer to read in the base + * type vector and then convert it in place to double (from end to front of + * course). + */ +static int +TIFFFetchAnyArray(TIFF* tif, TIFFDirEntry* dir, double* v) +{ + int i; + + switch (dir->tdir_type) { + case TIFF_BYTE: + case TIFF_SBYTE: + if (!TIFFFetchByteArray(tif, dir, (uint8*) v)) + return (0); + if (dir->tdir_type == TIFF_BYTE) { + uint8* vp = (uint8*) v; + for (i = dir->tdir_count-1; i >= 0; i--) + v[i] = vp[i]; + } else { + int8* vp = (int8*) v; + for (i = dir->tdir_count-1; i >= 0; i--) + v[i] = vp[i]; + } + break; + case TIFF_SHORT: + case TIFF_SSHORT: + if (!TIFFFetchShortArray(tif, dir, (uint16*) v)) + return (0); + if (dir->tdir_type == TIFF_SHORT) { + uint16* vp = (uint16*) v; + for (i = dir->tdir_count-1; i >= 0; i--) + v[i] = vp[i]; + } else { + int16* vp = (int16*) v; + for (i = dir->tdir_count-1; i >= 0; i--) + v[i] = vp[i]; + } + break; + case TIFF_LONG: + case TIFF_SLONG: + if (!TIFFFetchLongArray(tif, dir, (uint32*) v)) + return (0); + if (dir->tdir_type == TIFF_LONG) { + uint32* vp = (uint32*) v; + for (i = dir->tdir_count-1; i >= 0; i--) + v[i] = vp[i]; + } else { + int32* vp = (int32*) v; + for (i = dir->tdir_count-1; i >= 0; i--) + v[i] = vp[i]; + } + break; + case TIFF_RATIONAL: + case TIFF_SRATIONAL: + if (!TIFFFetchRationalArray(tif, dir, (float*) v)) + return (0); + { float* vp = (float*) v; + for (i = dir->tdir_count-1; i >= 0; i--) + v[i] = vp[i]; + } + break; + case TIFF_FLOAT: + if (!TIFFFetchFloatArray(tif, dir, (float*) v)) + return (0); + { float* vp = (float*) v; + for (i = dir->tdir_count-1; i >= 0; i--) + v[i] = vp[i]; + } + break; + case TIFF_DOUBLE: + return (TIFFFetchDoubleArray(tif, dir, (double*) v)); + default: + /* TIFF_NOTYPE */ + /* TIFF_ASCII */ + /* TIFF_UNDEFINED */ + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "cannot read TIFF_ANY type %d for field \"%s\"", + dir->tdir_type, + _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name); + return (0); + } + return (1); +} + +/* + * Fetch a tag that is not handled by special case code. + */ +static int +TIFFFetchNormalTag(TIFF* tif, TIFFDirEntry* dp) +{ + static const char mesg[] = "to fetch tag value"; + int ok = 0; + const TIFFFieldInfo* fip = _TIFFFieldWithTag(tif, dp->tdir_tag); + + if (dp->tdir_count > 1) { /* array of values */ + char* cp = NULL; + + switch (dp->tdir_type) { + case TIFF_BYTE: + case TIFF_SBYTE: + cp = (char *)_TIFFCheckMalloc(tif, + dp->tdir_count, sizeof (uint8), mesg); + ok = cp && TIFFFetchByteArray(tif, dp, (uint8*) cp); + break; + case TIFF_SHORT: + case TIFF_SSHORT: + cp = (char *)_TIFFCheckMalloc(tif, + dp->tdir_count, sizeof (uint16), mesg); + ok = cp && TIFFFetchShortArray(tif, dp, (uint16*) cp); + break; + case TIFF_LONG: + case TIFF_SLONG: + cp = (char *)_TIFFCheckMalloc(tif, + dp->tdir_count, sizeof (uint32), mesg); + ok = cp && TIFFFetchLongArray(tif, dp, (uint32*) cp); + break; + case TIFF_RATIONAL: + case TIFF_SRATIONAL: + cp = (char *)_TIFFCheckMalloc(tif, + dp->tdir_count, sizeof (float), mesg); + ok = cp && TIFFFetchRationalArray(tif, dp, (float*) cp); + break; + case TIFF_FLOAT: + cp = (char *)_TIFFCheckMalloc(tif, + dp->tdir_count, sizeof (float), mesg); + ok = cp && TIFFFetchFloatArray(tif, dp, (float*) cp); + break; + case TIFF_DOUBLE: + cp = (char *)_TIFFCheckMalloc(tif, + dp->tdir_count, sizeof (double), mesg); + ok = cp && TIFFFetchDoubleArray(tif, dp, (double*) cp); + break; + case TIFF_ASCII: + case TIFF_UNDEFINED: /* bit of a cheat... */ + /* + * Some vendors write strings w/o the trailing + * NULL byte, so always append one just in case. + */ + cp = (char *)_TIFFCheckMalloc(tif, dp->tdir_count + 1, + 1, mesg); + if( (ok = (cp && TIFFFetchString(tif, dp, cp))) != 0 ) + cp[dp->tdir_count] = '\0'; /* XXX */ + break; + } + if (ok) { + ok = (fip->field_passcount ? + TIFFSetField(tif, dp->tdir_tag, dp->tdir_count, cp) + : TIFFSetField(tif, dp->tdir_tag, cp)); + } + if (cp != NULL) + _TIFFfree(cp); + } else if (CheckDirCount(tif, dp, 1)) { /* singleton value */ + switch (dp->tdir_type) { + case TIFF_BYTE: + case TIFF_SBYTE: + case TIFF_SHORT: + case TIFF_SSHORT: + /* + * If the tag is also acceptable as a LONG or SLONG + * then TIFFSetField will expect an uint32 parameter + * passed to it (through varargs). Thus, for machines + * where sizeof (int) != sizeof (uint32) we must do + * a careful check here. It's hard to say if this + * is worth optimizing. + * + * NB: We use TIFFFieldWithTag here knowing that + * it returns us the first entry in the table + * for the tag and that that entry is for the + * widest potential data type the tag may have. + */ + { TIFFDataType type = fip->field_type; + if (type != TIFF_LONG && type != TIFF_SLONG) { + uint16 v = (uint16) + TIFFExtractData(tif, dp->tdir_type, dp->tdir_offset); + ok = (fip->field_passcount ? + TIFFSetField(tif, dp->tdir_tag, 1, &v) + : TIFFSetField(tif, dp->tdir_tag, v)); + break; + } + } + /* fall thru... */ + case TIFF_LONG: + case TIFF_SLONG: + { uint32 v32 = + TIFFExtractData(tif, dp->tdir_type, dp->tdir_offset); + ok = (fip->field_passcount ? + TIFFSetField(tif, dp->tdir_tag, 1, &v32) + : TIFFSetField(tif, dp->tdir_tag, v32)); + } + break; + case TIFF_RATIONAL: + case TIFF_SRATIONAL: + case TIFF_FLOAT: + { float v = (dp->tdir_type == TIFF_FLOAT ? + TIFFFetchFloat(tif, dp) + : TIFFFetchRational(tif, dp)); + ok = (fip->field_passcount ? + TIFFSetField(tif, dp->tdir_tag, 1, &v) + : TIFFSetField(tif, dp->tdir_tag, v)); + } + break; + case TIFF_DOUBLE: + { double v; + ok = (TIFFFetchDoubleArray(tif, dp, &v) && + (fip->field_passcount ? + TIFFSetField(tif, dp->tdir_tag, 1, &v) + : TIFFSetField(tif, dp->tdir_tag, v)) + ); + } + break; + case TIFF_ASCII: + case TIFF_UNDEFINED: /* bit of a cheat... */ + { char c[2]; + if( (ok = (TIFFFetchString(tif, dp, c) != 0)) != 0 ) { + c[1] = '\0'; /* XXX paranoid */ + ok = (fip->field_passcount ? + TIFFSetField(tif, dp->tdir_tag, 1, c) + : TIFFSetField(tif, dp->tdir_tag, c)); + } + } + break; + } + } + return (ok); +} + +#define NITEMS(x) (sizeof (x) / sizeof (x[0])) +/* + * Fetch samples/pixel short values for + * the specified tag and verify that + * all values are the same. + */ +static int +TIFFFetchPerSampleShorts(TIFF* tif, TIFFDirEntry* dir, uint16* pl) +{ + uint16 samples = tif->tif_dir.td_samplesperpixel; + int status = 0; + + if (CheckDirCount(tif, dir, (uint32) samples)) { + uint16 buf[10]; + uint16* v = buf; + + if (dir->tdir_count > NITEMS(buf)) + v = (uint16*) _TIFFCheckMalloc(tif, dir->tdir_count, sizeof(uint16), + "to fetch per-sample values"); + if (v && TIFFFetchShortArray(tif, dir, v)) { + uint16 i; + int check_count = dir->tdir_count; + if( samples < check_count ) + check_count = samples; + + for (i = 1; i < check_count; i++) + if (v[i] != v[0]) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Cannot handle different per-sample values for field \"%s\"", + _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name); + goto bad; + } + *pl = v[0]; + status = 1; + } + bad: + if (v && v != buf) + _TIFFfree(v); + } + return (status); +} + +/* + * Fetch samples/pixel long values for + * the specified tag and verify that + * all values are the same. + */ +static int +TIFFFetchPerSampleLongs(TIFF* tif, TIFFDirEntry* dir, uint32* pl) +{ + uint16 samples = tif->tif_dir.td_samplesperpixel; + int status = 0; + + if (CheckDirCount(tif, dir, (uint32) samples)) { + uint32 buf[10]; + uint32* v = buf; + + if (dir->tdir_count > NITEMS(buf)) + v = (uint32*) _TIFFCheckMalloc(tif, dir->tdir_count, sizeof(uint32), + "to fetch per-sample values"); + if (v && TIFFFetchLongArray(tif, dir, v)) { + uint16 i; + int check_count = dir->tdir_count; + + if( samples < check_count ) + check_count = samples; + for (i = 1; i < check_count; i++) + if (v[i] != v[0]) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Cannot handle different per-sample values for field \"%s\"", + _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name); + goto bad; + } + *pl = v[0]; + status = 1; + } + bad: + if (v && v != buf) + _TIFFfree(v); + } + return (status); +} + +/* + * Fetch samples/pixel ANY values for the specified tag and verify that all + * values are the same. + */ +static int +TIFFFetchPerSampleAnys(TIFF* tif, TIFFDirEntry* dir, double* pl) +{ + uint16 samples = tif->tif_dir.td_samplesperpixel; + int status = 0; + + if (CheckDirCount(tif, dir, (uint32) samples)) { + double buf[10]; + double* v = buf; + + if (dir->tdir_count > NITEMS(buf)) + v = (double*) _TIFFCheckMalloc(tif, dir->tdir_count, sizeof (double), + "to fetch per-sample values"); + if (v && TIFFFetchAnyArray(tif, dir, v)) { + uint16 i; + int check_count = dir->tdir_count; + if( samples < check_count ) + check_count = samples; + + for (i = 1; i < check_count; i++) + if (v[i] != v[0]) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Cannot handle different per-sample values for field \"%s\"", + _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name); + goto bad; + } + *pl = v[0]; + status = 1; + } + bad: + if (v && v != buf) + _TIFFfree(v); + } + return (status); +} +#undef NITEMS + +/* + * Fetch a set of offsets or lengths. + * While this routine says "strips", in fact it's also used for tiles. + */ +static int +TIFFFetchStripThing(TIFF* tif, TIFFDirEntry* dir, long nstrips, uint32** lpp) +{ + register uint32* lp; + int status; + + CheckDirCount(tif, dir, (uint32) nstrips); + + /* + * Allocate space for strip information. + */ + if (*lpp == NULL && + (*lpp = (uint32 *)_TIFFCheckMalloc(tif, + nstrips, sizeof (uint32), "for strip array")) == NULL) + return (0); + lp = *lpp; + _TIFFmemset( lp, 0, sizeof(uint32) * nstrips ); + + if (dir->tdir_type == (int)TIFF_SHORT) { + /* + * Handle uint16->uint32 expansion. + */ + uint16* dp = (uint16*) _TIFFCheckMalloc(tif, + dir->tdir_count, sizeof (uint16), "to fetch strip tag"); + if (dp == NULL) + return (0); + if( (status = TIFFFetchShortArray(tif, dir, dp)) != 0 ) { + int i; + + for( i = 0; i < nstrips && i < (int) dir->tdir_count; i++ ) + { + lp[i] = dp[i]; + } + } + _TIFFfree((char*) dp); + + } else if( nstrips != (int) dir->tdir_count ) { + /* Special case to correct length */ + + uint32* dp = (uint32*) _TIFFCheckMalloc(tif, + dir->tdir_count, sizeof (uint32), "to fetch strip tag"); + if (dp == NULL) + return (0); + + status = TIFFFetchLongArray(tif, dir, dp); + if( status != 0 ) { + int i; + + for( i = 0; i < nstrips && i < (int) dir->tdir_count; i++ ) + { + lp[i] = dp[i]; + } + } + + _TIFFfree( (char *) dp ); + } else + status = TIFFFetchLongArray(tif, dir, lp); + + return (status); +} + +/* + * Fetch and set the RefBlackWhite tag. + */ +static int +TIFFFetchRefBlackWhite(TIFF* tif, TIFFDirEntry* dir) +{ + static const char mesg[] = "for \"ReferenceBlackWhite\" array"; + char* cp; + int ok; + + if (dir->tdir_type == TIFF_RATIONAL) + return (TIFFFetchNormalTag(tif, dir)); + /* + * Handle LONG's for backward compatibility. + */ + cp = (char *)_TIFFCheckMalloc(tif, dir->tdir_count, + sizeof (uint32), mesg); + if( (ok = (cp && TIFFFetchLongArray(tif, dir, (uint32*) cp))) != 0) { + float* fp = (float*) + _TIFFCheckMalloc(tif, dir->tdir_count, sizeof (float), mesg); + if( (ok = (fp != NULL)) != 0 ) { + uint32 i; + for (i = 0; i < dir->tdir_count; i++) + fp[i] = (float)((uint32*) cp)[i]; + ok = TIFFSetField(tif, dir->tdir_tag, fp); + _TIFFfree((char*) fp); + } + } + if (cp) + _TIFFfree(cp); + return (ok); +} + +/* + * Fetch and set the SubjectDistance EXIF tag. + */ +static int +TIFFFetchSubjectDistance(TIFF* tif, TIFFDirEntry* dir) +{ + uint32 l[2]; + float v; + int ok = 0; + + if( dir->tdir_count != 1 || dir->tdir_type != TIFF_RATIONAL ) + { + TIFFWarningExt(tif->tif_clientdata, tif->tif_name, + "incorrect count or type for SubjectDistance, tag ignored" ); + return (0); + } + + if (TIFFFetchData(tif, dir, (char *)l) + && cvtRational(tif, dir, l[0], l[1], &v)) { + /* + * XXX: Numerator 0xFFFFFFFF means that we have infinite + * distance. Indicate that with a negative floating point + * SubjectDistance value. + */ + ok = TIFFSetField(tif, dir->tdir_tag, + (l[0] != 0xFFFFFFFF) ? v : -v); + } + + return ok; +} + +/* + * Replace a single strip (tile) of uncompressed data by multiple strips + * (tiles), each approximately STRIP_SIZE_DEFAULT bytes. This is useful for + * dealing with large images or for dealing with machines with a limited + * amount memory. + */ +static void +ChopUpSingleUncompressedStrip(TIFF* tif) +{ + register TIFFDirectory *td = &tif->tif_dir; + uint32 bytecount = td->td_stripbytecount[0]; + uint32 offset = td->td_stripoffset[0]; + tsize_t rowbytes = TIFFVTileSize(tif, 1), stripbytes; + tstrip_t strip, nstrips, rowsperstrip; + uint32* newcounts; + uint32* newoffsets; + + /* + * Make the rows hold at least one scanline, but fill specified amount + * of data if possible. + */ + if (rowbytes > STRIP_SIZE_DEFAULT) { + stripbytes = rowbytes; + rowsperstrip = 1; + } else if (rowbytes > 0 ) { + rowsperstrip = STRIP_SIZE_DEFAULT / rowbytes; + stripbytes = rowbytes * rowsperstrip; + } + else + return; + + /* + * never increase the number of strips in an image + */ + if (rowsperstrip >= td->td_rowsperstrip) + return; + nstrips = (tstrip_t) TIFFhowmany(bytecount, stripbytes); + if( nstrips == 0 ) /* something is wonky, do nothing. */ + return; + + newcounts = (uint32*) _TIFFCheckMalloc(tif, nstrips, sizeof (uint32), + "for chopped \"StripByteCounts\" array"); + newoffsets = (uint32*) _TIFFCheckMalloc(tif, nstrips, sizeof (uint32), + "for chopped \"StripOffsets\" array"); + if (newcounts == NULL || newoffsets == NULL) { + /* + * Unable to allocate new strip information, give up and use + * the original one strip information. + */ + if (newcounts != NULL) + _TIFFfree(newcounts); + if (newoffsets != NULL) + _TIFFfree(newoffsets); + return; + } + /* + * Fill the strip information arrays with new bytecounts and offsets + * that reflect the broken-up format. + */ + for (strip = 0; strip < nstrips; strip++) { + if ((uint32)stripbytes > bytecount) + stripbytes = bytecount; + newcounts[strip] = stripbytes; + newoffsets[strip] = offset; + offset += stripbytes; + bytecount -= stripbytes; + } + /* + * Replace old single strip info with multi-strip info. + */ + td->td_stripsperimage = td->td_nstrips = nstrips; + TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip); + + _TIFFfree(td->td_stripbytecount); + _TIFFfree(td->td_stripoffset); + td->td_stripbytecount = newcounts; + td->td_stripoffset = newoffsets; + td->td_stripbytecountsorted = 1; +} + +/* vim: set ts=8 sts=8 sw=8 noet: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tif_dirwrite.c b/reactos/dll/3rdparty/libtiff/tif_dirwrite.c new file mode 100644 index 00000000000..8d308c42926 --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tif_dirwrite.c @@ -0,0 +1,1414 @@ +/* $Id: tif_dirwrite.c,v 1.37.2.7 2010-06-08 18:50:42 bfriesen Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library. + * + * Directory Write Support Routines. + */ +#include "tiffiop.h" + +#ifdef HAVE_IEEEFP +# define TIFFCvtNativeToIEEEFloat(tif, n, fp) +# define TIFFCvtNativeToIEEEDouble(tif, n, dp) +#else +extern void TIFFCvtNativeToIEEEFloat(TIFF*, uint32, float*); +extern void TIFFCvtNativeToIEEEDouble(TIFF*, uint32, double*); +#endif + +static int TIFFWriteNormalTag(TIFF*, TIFFDirEntry*, const TIFFFieldInfo*); +static void TIFFSetupShortLong(TIFF*, ttag_t, TIFFDirEntry*, uint32); +static void TIFFSetupShort(TIFF*, ttag_t, TIFFDirEntry*, uint16); +static int TIFFSetupShortPair(TIFF*, ttag_t, TIFFDirEntry*); +static int TIFFWritePerSampleShorts(TIFF*, ttag_t, TIFFDirEntry*); +static int TIFFWritePerSampleAnys(TIFF*, TIFFDataType, ttag_t, TIFFDirEntry*); +static int TIFFWriteShortTable(TIFF*, ttag_t, TIFFDirEntry*, uint32, uint16**); +static int TIFFWriteShortArray(TIFF*, TIFFDirEntry*, uint16*); +static int TIFFWriteLongArray(TIFF *, TIFFDirEntry*, uint32*); +static int TIFFWriteRationalArray(TIFF *, TIFFDirEntry*, float*); +static int TIFFWriteFloatArray(TIFF *, TIFFDirEntry*, float*); +static int TIFFWriteDoubleArray(TIFF *, TIFFDirEntry*, double*); +static int TIFFWriteByteArray(TIFF*, TIFFDirEntry*, char*); +static int TIFFWriteAnyArray(TIFF*, + TIFFDataType, ttag_t, TIFFDirEntry*, uint32, double*); +static int TIFFWriteTransferFunction(TIFF*, TIFFDirEntry*); +static int TIFFWriteInkNames(TIFF*, TIFFDirEntry*); +static int TIFFWriteData(TIFF*, TIFFDirEntry*, char*); +static int TIFFLinkDirectory(TIFF*); + +#define WriteRationalPair(type, tag1, v1, tag2, v2) { \ + TIFFWriteRational((tif), (type), (tag1), (dir), (v1)) \ + TIFFWriteRational((tif), (type), (tag2), (dir)+1, (v2)) \ + (dir)++; \ +} +#define TIFFWriteRational(tif, type, tag, dir, v) \ + (dir)->tdir_tag = (tag); \ + (dir)->tdir_type = (type); \ + (dir)->tdir_count = 1; \ + if (!TIFFWriteRationalArray((tif), (dir), &(v))) \ + goto bad; + +/* + * Write the contents of the current directory + * to the specified file. This routine doesn't + * handle overwriting a directory with auxiliary + * storage that's been changed. + */ +static int +_TIFFWriteDirectory(TIFF* tif, int done) +{ + uint16 dircount; + toff_t diroff; + ttag_t tag; + uint32 nfields; + tsize_t dirsize; + char* data; + TIFFDirEntry* dir; + TIFFDirectory* td; + unsigned long b, fields[FIELD_SETLONGS]; + int fi, nfi; + + if (tif->tif_mode == O_RDONLY) + return (1); + /* + * Clear write state so that subsequent images with + * different characteristics get the right buffers + * setup for them. + */ + if (done) + { + if (tif->tif_flags & TIFF_POSTENCODE) { + tif->tif_flags &= ~TIFF_POSTENCODE; + if (!(*tif->tif_postencode)(tif)) { + TIFFErrorExt(tif->tif_clientdata, + tif->tif_name, + "Error post-encoding before directory write"); + return (0); + } + } + (*tif->tif_close)(tif); /* shutdown encoder */ + /* + * Flush any data that might have been written + * by the compression close+cleanup routines. + */ + if (tif->tif_rawcc > 0 + && (tif->tif_flags & TIFF_BEENWRITING) != 0 + && !TIFFFlushData1(tif)) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Error flushing data before directory write"); + return (0); + } + if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) { + _TIFFfree(tif->tif_rawdata); + tif->tif_rawdata = NULL; + tif->tif_rawcc = 0; + tif->tif_rawdatasize = 0; + } + tif->tif_flags &= ~(TIFF_BEENWRITING|TIFF_BUFFERSETUP); + } + + td = &tif->tif_dir; + /* + * Size the directory so that we can calculate + * offsets for the data items that aren't kept + * in-place in each field. + */ + nfields = 0; + for (b = 0; b <= FIELD_LAST; b++) + if (TIFFFieldSet(tif, b) && b != FIELD_CUSTOM) + nfields += (b < FIELD_SUBFILETYPE ? 2 : 1); + nfields += td->td_customValueCount; + dirsize = nfields * sizeof (TIFFDirEntry); + data = (char*) _TIFFmalloc(dirsize); + if (data == NULL) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Cannot write directory, out of space"); + return (0); + } + /* + * Directory hasn't been placed yet, put + * it at the end of the file and link it + * into the existing directory structure. + */ + if (tif->tif_diroff == 0 && !TIFFLinkDirectory(tif)) + goto bad; + tif->tif_dataoff = (toff_t)( + tif->tif_diroff + sizeof (uint16) + dirsize + sizeof (toff_t)); + if (tif->tif_dataoff & 1) + tif->tif_dataoff++; + (void) TIFFSeekFile(tif, tif->tif_dataoff, SEEK_SET); + tif->tif_curdir++; + dir = (TIFFDirEntry*) data; + /* + * Setup external form of directory + * entries and write data items. + */ + _TIFFmemcpy(fields, td->td_fieldsset, sizeof (fields)); + /* + * Write out ExtraSamples tag only if + * extra samples are present in the data. + */ + if (FieldSet(fields, FIELD_EXTRASAMPLES) && !td->td_extrasamples) { + ResetFieldBit(fields, FIELD_EXTRASAMPLES); + nfields--; + dirsize -= sizeof (TIFFDirEntry); + } /*XXX*/ + for (fi = 0, nfi = tif->tif_nfields; nfi > 0; nfi--, fi++) { + const TIFFFieldInfo* fip = tif->tif_fieldinfo[fi]; + + /* + * For custom fields, we test to see if the custom field + * is set or not. For normal fields, we just use the + * FieldSet test. + */ + if( fip->field_bit == FIELD_CUSTOM ) + { + int ci, is_set = FALSE; + + for( ci = 0; ci < td->td_customValueCount; ci++ ) + is_set |= (td->td_customValues[ci].info == fip); + + if( !is_set ) + continue; + } + else if (!FieldSet(fields, fip->field_bit)) + continue; + + /* + * Handle other fields. + */ + switch (fip->field_bit) + { + case FIELD_STRIPOFFSETS: + /* + * We use one field bit for both strip and tile + + * offsets, and so must be careful in selecting + * the appropriate field descriptor (so that tags + * are written in sorted order). + */ + tag = isTiled(tif) ? + TIFFTAG_TILEOFFSETS : TIFFTAG_STRIPOFFSETS; + if (tag != fip->field_tag) + continue; + + dir->tdir_tag = (uint16) tag; + dir->tdir_type = (uint16) TIFF_LONG; + dir->tdir_count = (uint32) td->td_nstrips; + if (!TIFFWriteLongArray(tif, dir, td->td_stripoffset)) + goto bad; + break; + case FIELD_STRIPBYTECOUNTS: + /* + * We use one field bit for both strip and tile + * byte counts, and so must be careful in selecting + * the appropriate field descriptor (so that tags + * are written in sorted order). + */ + tag = isTiled(tif) ? + TIFFTAG_TILEBYTECOUNTS : TIFFTAG_STRIPBYTECOUNTS; + if (tag != fip->field_tag) + continue; + + dir->tdir_tag = (uint16) tag; + dir->tdir_type = (uint16) TIFF_LONG; + dir->tdir_count = (uint32) td->td_nstrips; + if (!TIFFWriteLongArray(tif, dir, td->td_stripbytecount)) + goto bad; + break; + case FIELD_ROWSPERSTRIP: + TIFFSetupShortLong(tif, TIFFTAG_ROWSPERSTRIP, + dir, td->td_rowsperstrip); + break; + case FIELD_COLORMAP: + if (!TIFFWriteShortTable(tif, TIFFTAG_COLORMAP, dir, + 3, td->td_colormap)) + goto bad; + break; + case FIELD_IMAGEDIMENSIONS: + TIFFSetupShortLong(tif, TIFFTAG_IMAGEWIDTH, + dir++, td->td_imagewidth); + TIFFSetupShortLong(tif, TIFFTAG_IMAGELENGTH, + dir, td->td_imagelength); + break; + case FIELD_TILEDIMENSIONS: + TIFFSetupShortLong(tif, TIFFTAG_TILEWIDTH, + dir++, td->td_tilewidth); + TIFFSetupShortLong(tif, TIFFTAG_TILELENGTH, + dir, td->td_tilelength); + break; + case FIELD_COMPRESSION: + TIFFSetupShort(tif, TIFFTAG_COMPRESSION, + dir, td->td_compression); + break; + case FIELD_PHOTOMETRIC: + TIFFSetupShort(tif, TIFFTAG_PHOTOMETRIC, + dir, td->td_photometric); + break; + case FIELD_POSITION: + WriteRationalPair(TIFF_RATIONAL, + TIFFTAG_XPOSITION, td->td_xposition, + TIFFTAG_YPOSITION, td->td_yposition); + break; + case FIELD_RESOLUTION: + WriteRationalPair(TIFF_RATIONAL, + TIFFTAG_XRESOLUTION, td->td_xresolution, + TIFFTAG_YRESOLUTION, td->td_yresolution); + break; + case FIELD_BITSPERSAMPLE: + case FIELD_MINSAMPLEVALUE: + case FIELD_MAXSAMPLEVALUE: + case FIELD_SAMPLEFORMAT: + if (!TIFFWritePerSampleShorts(tif, fip->field_tag, dir)) + goto bad; + break; + case FIELD_SMINSAMPLEVALUE: + case FIELD_SMAXSAMPLEVALUE: + if (!TIFFWritePerSampleAnys(tif, + _TIFFSampleToTagType(tif), fip->field_tag, dir)) + goto bad; + break; + case FIELD_PAGENUMBER: + case FIELD_HALFTONEHINTS: + case FIELD_YCBCRSUBSAMPLING: + if (!TIFFSetupShortPair(tif, fip->field_tag, dir)) + goto bad; + break; + case FIELD_INKNAMES: + if (!TIFFWriteInkNames(tif, dir)) + goto bad; + break; + case FIELD_TRANSFERFUNCTION: + if (!TIFFWriteTransferFunction(tif, dir)) + goto bad; + break; + case FIELD_SUBIFD: + /* + * XXX: Always write this field using LONG type + * for backward compatibility. + */ + dir->tdir_tag = (uint16) fip->field_tag; + dir->tdir_type = (uint16) TIFF_LONG; + dir->tdir_count = (uint32) td->td_nsubifd; + if (!TIFFWriteLongArray(tif, dir, td->td_subifd)) + goto bad; + /* + * Total hack: if this directory includes a SubIFD + * tag then force the next directories to be + * written as ``sub directories'' of this one. This + * is used to write things like thumbnails and + * image masks that one wants to keep out of the + * normal directory linkage access mechanism. + */ + if (dir->tdir_count > 0) { + tif->tif_flags |= TIFF_INSUBIFD; + tif->tif_nsubifd = (uint16) dir->tdir_count; + if (dir->tdir_count > 1) + tif->tif_subifdoff = dir->tdir_offset; + else + tif->tif_subifdoff = (uint32)( + tif->tif_diroff + + sizeof (uint16) + + ((char*)&dir->tdir_offset-data)); + } + break; + default: + /* XXX: Should be fixed and removed. */ + if (fip->field_tag == TIFFTAG_DOTRANGE) { + if (!TIFFSetupShortPair(tif, fip->field_tag, dir)) + goto bad; + } + else if (!TIFFWriteNormalTag(tif, dir, fip)) + goto bad; + break; + } + dir++; + + if( fip->field_bit != FIELD_CUSTOM ) + ResetFieldBit(fields, fip->field_bit); + } + + /* + * Write directory. + */ + dircount = (uint16) nfields; + diroff = (uint32) tif->tif_nextdiroff; + if (tif->tif_flags & TIFF_SWAB) { + /* + * The file's byte order is opposite to the + * native machine architecture. We overwrite + * the directory information with impunity + * because it'll be released below after we + * write it to the file. Note that all the + * other tag construction routines assume that + * we do this byte-swapping; i.e. they only + * byte-swap indirect data. + */ + for (dir = (TIFFDirEntry*) data; dircount; dir++, dircount--) { + TIFFSwabArrayOfShort(&dir->tdir_tag, 2); + TIFFSwabArrayOfLong(&dir->tdir_count, 2); + } + dircount = (uint16) nfields; + TIFFSwabShort(&dircount); + TIFFSwabLong(&diroff); + } + (void) TIFFSeekFile(tif, tif->tif_diroff, SEEK_SET); + if (!WriteOK(tif, &dircount, sizeof (dircount))) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Error writing directory count"); + goto bad; + } + if (!WriteOK(tif, data, dirsize)) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Error writing directory contents"); + goto bad; + } + if (!WriteOK(tif, &diroff, sizeof (uint32))) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Error writing directory link"); + goto bad; + } + if (done) { + TIFFFreeDirectory(tif); + tif->tif_flags &= ~TIFF_DIRTYDIRECT; + (*tif->tif_cleanup)(tif); + + /* + * Reset directory-related state for subsequent + * directories. + */ + TIFFCreateDirectory(tif); + } + _TIFFfree(data); + return (1); +bad: + _TIFFfree(data); + return (0); +} +#undef WriteRationalPair + +int +TIFFWriteDirectory(TIFF* tif) +{ + return _TIFFWriteDirectory(tif, TRUE); +} + +/* + * Similar to TIFFWriteDirectory(), writes the directory out + * but leaves all data structures in memory so that it can be + * written again. This will make a partially written TIFF file + * readable before it is successfully completed/closed. + */ +int +TIFFCheckpointDirectory(TIFF* tif) +{ + int rc; + /* Setup the strips arrays, if they haven't already been. */ + if (tif->tif_dir.td_stripoffset == NULL) + (void) TIFFSetupStrips(tif); + rc = _TIFFWriteDirectory(tif, FALSE); + (void) TIFFSetWriteOffset(tif, TIFFSeekFile(tif, 0, SEEK_END)); + return rc; +} + +static int +_TIFFWriteCustomDirectory(TIFF* tif, toff_t *pdiroff) +{ + uint16 dircount; + uint32 nfields; + tsize_t dirsize; + char* data; + TIFFDirEntry* dir; + TIFFDirectory* td; + unsigned long b, fields[FIELD_SETLONGS]; + int fi, nfi; + + if (tif->tif_mode == O_RDONLY) + return (1); + + td = &tif->tif_dir; + /* + * Size the directory so that we can calculate + * offsets for the data items that aren't kept + * in-place in each field. + */ + nfields = 0; + for (b = 0; b <= FIELD_LAST; b++) + if (TIFFFieldSet(tif, b) && b != FIELD_CUSTOM) + nfields += (b < FIELD_SUBFILETYPE ? 2 : 1); + nfields += td->td_customValueCount; + dirsize = nfields * sizeof (TIFFDirEntry); + data = (char*) _TIFFmalloc(dirsize); + if (data == NULL) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Cannot write directory, out of space"); + return (0); + } + /* + * Put the directory at the end of the file. + */ + tif->tif_diroff = (TIFFSeekFile(tif, (toff_t) 0, SEEK_END)+1) &~ 1; + tif->tif_dataoff = (toff_t)( + tif->tif_diroff + sizeof (uint16) + dirsize + sizeof (toff_t)); + if (tif->tif_dataoff & 1) + tif->tif_dataoff++; + (void) TIFFSeekFile(tif, tif->tif_dataoff, SEEK_SET); + dir = (TIFFDirEntry*) data; + /* + * Setup external form of directory + * entries and write data items. + */ + _TIFFmemcpy(fields, td->td_fieldsset, sizeof (fields)); + + for (fi = 0, nfi = tif->tif_nfields; nfi > 0; nfi--, fi++) { + const TIFFFieldInfo* fip = tif->tif_fieldinfo[fi]; + + /* + * For custom fields, we test to see if the custom field + * is set or not. For normal fields, we just use the + * FieldSet test. + */ + if( fip->field_bit == FIELD_CUSTOM ) + { + int ci, is_set = FALSE; + + for( ci = 0; ci < td->td_customValueCount; ci++ ) + is_set |= (td->td_customValues[ci].info == fip); + + if( !is_set ) + continue; + } + else if (!FieldSet(fields, fip->field_bit)) + continue; + + if( fip->field_bit != FIELD_CUSTOM ) + ResetFieldBit(fields, fip->field_bit); + } + + /* + * Write directory. + */ + dircount = (uint16) nfields; + *pdiroff = (uint32) tif->tif_nextdiroff; + if (tif->tif_flags & TIFF_SWAB) { + /* + * The file's byte order is opposite to the + * native machine architecture. We overwrite + * the directory information with impunity + * because it'll be released below after we + * write it to the file. Note that all the + * other tag construction routines assume that + * we do this byte-swapping; i.e. they only + * byte-swap indirect data. + */ + for (dir = (TIFFDirEntry*) data; dircount; dir++, dircount--) { + TIFFSwabArrayOfShort(&dir->tdir_tag, 2); + TIFFSwabArrayOfLong(&dir->tdir_count, 2); + } + dircount = (uint16) nfields; + TIFFSwabShort(&dircount); + TIFFSwabLong(pdiroff); + } + (void) TIFFSeekFile(tif, tif->tif_diroff, SEEK_SET); + if (!WriteOK(tif, &dircount, sizeof (dircount))) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Error writing directory count"); + goto bad; + } + if (!WriteOK(tif, data, dirsize)) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Error writing directory contents"); + goto bad; + } + if (!WriteOK(tif, pdiroff, sizeof (uint32))) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Error writing directory link"); + goto bad; + } + _TIFFfree(data); + return (1); +bad: + _TIFFfree(data); + return (0); +} + +int +TIFFWriteCustomDirectory(TIFF* tif, toff_t *pdiroff) +{ + return _TIFFWriteCustomDirectory(tif, pdiroff); +} + +/* + * Process tags that are not special cased. + */ +static int +TIFFWriteNormalTag(TIFF* tif, TIFFDirEntry* dir, const TIFFFieldInfo* fip) +{ + uint16 wc = (uint16) fip->field_writecount; + uint32 wc2; + + dir->tdir_tag = (uint16) fip->field_tag; + dir->tdir_type = (uint16) fip->field_type; + dir->tdir_count = wc; + + switch (fip->field_type) { + case TIFF_SHORT: + case TIFF_SSHORT: + if (fip->field_passcount) { + uint16* wp; + if (wc == (uint16) TIFF_VARIABLE2) { + TIFFGetField(tif, fip->field_tag, &wc2, &wp); + dir->tdir_count = wc2; + } else { /* Assume TIFF_VARIABLE */ + TIFFGetField(tif, fip->field_tag, &wc, &wp); + dir->tdir_count = wc; + } + if (!TIFFWriteShortArray(tif, dir, wp)) + return 0; + } else { + if (wc == 1) { + uint16 sv; + TIFFGetField(tif, fip->field_tag, &sv); + dir->tdir_offset = + TIFFInsertData(tif, dir->tdir_type, sv); + } else { + uint16* wp; + TIFFGetField(tif, fip->field_tag, &wp); + if (!TIFFWriteShortArray(tif, dir, wp)) + return 0; + } + } + break; + case TIFF_LONG: + case TIFF_SLONG: + case TIFF_IFD: + if (fip->field_passcount) { + uint32* lp; + if (wc == (uint16) TIFF_VARIABLE2) { + TIFFGetField(tif, fip->field_tag, &wc2, &lp); + dir->tdir_count = wc2; + } else { /* Assume TIFF_VARIABLE */ + TIFFGetField(tif, fip->field_tag, &wc, &lp); + dir->tdir_count = wc; + } + if (!TIFFWriteLongArray(tif, dir, lp)) + return 0; + } else { + if (wc == 1) { + /* XXX handle LONG->SHORT conversion */ + TIFFGetField(tif, fip->field_tag, + &dir->tdir_offset); + } else { + uint32* lp; + TIFFGetField(tif, fip->field_tag, &lp); + if (!TIFFWriteLongArray(tif, dir, lp)) + return 0; + } + } + break; + case TIFF_RATIONAL: + case TIFF_SRATIONAL: + if (fip->field_passcount) { + float* fp; + if (wc == (uint16) TIFF_VARIABLE2) { + TIFFGetField(tif, fip->field_tag, &wc2, &fp); + dir->tdir_count = wc2; + } else { /* Assume TIFF_VARIABLE */ + TIFFGetField(tif, fip->field_tag, &wc, &fp); + dir->tdir_count = wc; + } + if (!TIFFWriteRationalArray(tif, dir, fp)) + return 0; + } else { + if (wc == 1) { + float fv; + TIFFGetField(tif, fip->field_tag, &fv); + if (!TIFFWriteRationalArray(tif, dir, &fv)) + return 0; + } else { + float* fp; + TIFFGetField(tif, fip->field_tag, &fp); + if (!TIFFWriteRationalArray(tif, dir, fp)) + return 0; + } + } + break; + case TIFF_FLOAT: + if (fip->field_passcount) { + float* fp; + if (wc == (uint16) TIFF_VARIABLE2) { + TIFFGetField(tif, fip->field_tag, &wc2, &fp); + dir->tdir_count = wc2; + } else { /* Assume TIFF_VARIABLE */ + TIFFGetField(tif, fip->field_tag, &wc, &fp); + dir->tdir_count = wc; + } + if (!TIFFWriteFloatArray(tif, dir, fp)) + return 0; + } else { + if (wc == 1) { + float fv; + TIFFGetField(tif, fip->field_tag, &fv); + if (!TIFFWriteFloatArray(tif, dir, &fv)) + return 0; + } else { + float* fp; + TIFFGetField(tif, fip->field_tag, &fp); + if (!TIFFWriteFloatArray(tif, dir, fp)) + return 0; + } + } + break; + case TIFF_DOUBLE: + if (fip->field_passcount) { + double* dp; + if (wc == (uint16) TIFF_VARIABLE2) { + TIFFGetField(tif, fip->field_tag, &wc2, &dp); + dir->tdir_count = wc2; + } else { /* Assume TIFF_VARIABLE */ + TIFFGetField(tif, fip->field_tag, &wc, &dp); + dir->tdir_count = wc; + } + if (!TIFFWriteDoubleArray(tif, dir, dp)) + return 0; + } else { + if (wc == 1) { + double dv; + TIFFGetField(tif, fip->field_tag, &dv); + if (!TIFFWriteDoubleArray(tif, dir, &dv)) + return 0; + } else { + double* dp; + TIFFGetField(tif, fip->field_tag, &dp); + if (!TIFFWriteDoubleArray(tif, dir, dp)) + return 0; + } + } + break; + case TIFF_ASCII: + { + char* cp; + if (fip->field_passcount) + { + if( wc == (uint16) TIFF_VARIABLE2 ) + TIFFGetField(tif, fip->field_tag, &wc2, &cp); + else + TIFFGetField(tif, fip->field_tag, &wc, &cp); + } + else + TIFFGetField(tif, fip->field_tag, &cp); + + dir->tdir_count = (uint32) (strlen(cp) + 1); + if (!TIFFWriteByteArray(tif, dir, cp)) + return (0); + } + break; + + case TIFF_BYTE: + case TIFF_SBYTE: + if (fip->field_passcount) { + char* cp; + if (wc == (uint16) TIFF_VARIABLE2) { + TIFFGetField(tif, fip->field_tag, &wc2, &cp); + dir->tdir_count = wc2; + } else { /* Assume TIFF_VARIABLE */ + TIFFGetField(tif, fip->field_tag, &wc, &cp); + dir->tdir_count = wc; + } + if (!TIFFWriteByteArray(tif, dir, cp)) + return 0; + } else { + if (wc == 1) { + char cv; + TIFFGetField(tif, fip->field_tag, &cv); + if (!TIFFWriteByteArray(tif, dir, &cv)) + return 0; + } else { + char* cp; + TIFFGetField(tif, fip->field_tag, &cp); + if (!TIFFWriteByteArray(tif, dir, cp)) + return 0; + } + } + break; + + case TIFF_UNDEFINED: + { char* cp; + if (wc == (unsigned short) TIFF_VARIABLE) { + TIFFGetField(tif, fip->field_tag, &wc, &cp); + dir->tdir_count = wc; + } else if (wc == (unsigned short) TIFF_VARIABLE2) { + TIFFGetField(tif, fip->field_tag, &wc2, &cp); + dir->tdir_count = wc2; + } else + TIFFGetField(tif, fip->field_tag, &cp); + if (!TIFFWriteByteArray(tif, dir, cp)) + return (0); + } + break; + + case TIFF_NOTYPE: + break; + } + return (1); +} + +/* + * Setup a directory entry with either a SHORT + * or LONG type according to the value. + */ +static void +TIFFSetupShortLong(TIFF* tif, ttag_t tag, TIFFDirEntry* dir, uint32 v) +{ + dir->tdir_tag = (uint16) tag; + dir->tdir_count = 1; + if (v > 0xffffL) { + dir->tdir_type = (short) TIFF_LONG; + dir->tdir_offset = v; + } else { + dir->tdir_type = (short) TIFF_SHORT; + dir->tdir_offset = TIFFInsertData(tif, (int) TIFF_SHORT, v); + } +} + +/* + * Setup a SHORT directory entry + */ +static void +TIFFSetupShort(TIFF* tif, ttag_t tag, TIFFDirEntry* dir, uint16 v) +{ + dir->tdir_tag = (uint16) tag; + dir->tdir_count = 1; + dir->tdir_type = (short) TIFF_SHORT; + dir->tdir_offset = TIFFInsertData(tif, (int) TIFF_SHORT, v); +} +#undef MakeShortDirent + +#define NITEMS(x) (sizeof (x) / sizeof (x[0])) +/* + * Setup a directory entry that references a + * samples/pixel array of SHORT values and + * (potentially) write the associated indirect + * values. + */ +static int +TIFFWritePerSampleShorts(TIFF* tif, ttag_t tag, TIFFDirEntry* dir) +{ + uint16 buf[10], v; + uint16* w = buf; + uint16 i, samples = tif->tif_dir.td_samplesperpixel; + int status; + + if (samples > NITEMS(buf)) { + w = (uint16*) _TIFFmalloc(samples * sizeof (uint16)); + if (w == NULL) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "No space to write per-sample shorts"); + return (0); + } + } + TIFFGetField(tif, tag, &v); + for (i = 0; i < samples; i++) + w[i] = v; + + dir->tdir_tag = (uint16) tag; + dir->tdir_type = (uint16) TIFF_SHORT; + dir->tdir_count = samples; + status = TIFFWriteShortArray(tif, dir, w); + if (w != buf) + _TIFFfree((char*) w); + return (status); +} + +/* + * Setup a directory entry that references a samples/pixel array of ``type'' + * values and (potentially) write the associated indirect values. The source + * data from TIFFGetField() for the specified tag must be returned as double. + */ +static int +TIFFWritePerSampleAnys(TIFF* tif, + TIFFDataType type, ttag_t tag, TIFFDirEntry* dir) +{ + double buf[10], v; + double* w = buf; + uint16 i, samples = tif->tif_dir.td_samplesperpixel; + int status; + + if (samples > NITEMS(buf)) { + w = (double*) _TIFFmalloc(samples * sizeof (double)); + if (w == NULL) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "No space to write per-sample values"); + return (0); + } + } + TIFFGetField(tif, tag, &v); + for (i = 0; i < samples; i++) + w[i] = v; + status = TIFFWriteAnyArray(tif, type, tag, dir, samples, w); + if (w != buf) + _TIFFfree(w); + return (status); +} +#undef NITEMS + +/* + * Setup a pair of shorts that are returned by + * value, rather than as a reference to an array. + */ +static int +TIFFSetupShortPair(TIFF* tif, ttag_t tag, TIFFDirEntry* dir) +{ + uint16 v[2]; + + TIFFGetField(tif, tag, &v[0], &v[1]); + + dir->tdir_tag = (uint16) tag; + dir->tdir_type = (uint16) TIFF_SHORT; + dir->tdir_count = 2; + return (TIFFWriteShortArray(tif, dir, v)); +} + +/* + * Setup a directory entry for an NxM table of shorts, + * where M is known to be 2**bitspersample, and write + * the associated indirect data. + */ +static int +TIFFWriteShortTable(TIFF* tif, + ttag_t tag, TIFFDirEntry* dir, uint32 n, uint16** table) +{ + uint32 i, off; + + dir->tdir_tag = (uint16) tag; + dir->tdir_type = (short) TIFF_SHORT; + /* XXX -- yech, fool TIFFWriteData */ + dir->tdir_count = (uint32) (1L<tif_dir.td_bitspersample); + off = tif->tif_dataoff; + for (i = 0; i < n; i++) + if (!TIFFWriteData(tif, dir, (char *)table[i])) + return (0); + dir->tdir_count *= n; + dir->tdir_offset = off; + return (1); +} + +/* + * Write/copy data associated with an ASCII or opaque tag value. + */ +static int +TIFFWriteByteArray(TIFF* tif, TIFFDirEntry* dir, char* cp) +{ + if (dir->tdir_count <= 4) { + if (tif->tif_header.tiff_magic == TIFF_BIGENDIAN) { + dir->tdir_offset = (uint32)cp[0] << 24; + if (dir->tdir_count >= 2) + dir->tdir_offset |= (uint32)cp[1] << 16; + if (dir->tdir_count >= 3) + dir->tdir_offset |= (uint32)cp[2] << 8; + if (dir->tdir_count == 4) + dir->tdir_offset |= cp[3]; + } else { + dir->tdir_offset = cp[0]; + if (dir->tdir_count >= 2) + dir->tdir_offset |= (uint32) cp[1] << 8; + if (dir->tdir_count >= 3) + dir->tdir_offset |= (uint32) cp[2] << 16; + if (dir->tdir_count == 4) + dir->tdir_offset |= (uint32) cp[3] << 24; + } + return 1; + } else + return TIFFWriteData(tif, dir, cp); +} + +/* + * Setup a directory entry of an array of SHORT + * or SSHORT and write the associated indirect values. + */ +static int +TIFFWriteShortArray(TIFF* tif, TIFFDirEntry* dir, uint16* v) +{ + if (dir->tdir_count <= 2) { + if (tif->tif_header.tiff_magic == TIFF_BIGENDIAN) { + dir->tdir_offset = (uint32) v[0] << 16; + if (dir->tdir_count == 2) + dir->tdir_offset |= v[1] & 0xffff; + } else { + dir->tdir_offset = v[0] & 0xffff; + if (dir->tdir_count == 2) + dir->tdir_offset |= (uint32) v[1] << 16; + } + return (1); + } else + return (TIFFWriteData(tif, dir, (char*) v)); +} + +/* + * Setup a directory entry of an array of LONG + * or SLONG and write the associated indirect values. + */ +static int +TIFFWriteLongArray(TIFF* tif, TIFFDirEntry* dir, uint32* v) +{ + if (dir->tdir_count == 1) { + dir->tdir_offset = v[0]; + return (1); + } else + return (TIFFWriteData(tif, dir, (char*) v)); +} + +/* + * Setup a directory entry of an array of RATIONAL + * or SRATIONAL and write the associated indirect values. + */ +static int +TIFFWriteRationalArray(TIFF* tif, TIFFDirEntry* dir, float* v) +{ + uint32 i; + uint32* t; + int status; + + t = (uint32*) _TIFFmalloc(2 * dir->tdir_count * sizeof (uint32)); + if (t == NULL) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "No space to write RATIONAL array"); + return (0); + } + for (i = 0; i < dir->tdir_count; i++) { + float fv = v[i]; + int sign = 1; + uint32 den; + + if (fv < 0) { + if (dir->tdir_type == TIFF_RATIONAL) { + TIFFWarningExt(tif->tif_clientdata, + tif->tif_name, + "\"%s\": Information lost writing value (%g) as (unsigned) RATIONAL", + _TIFFFieldWithTag(tif,dir->tdir_tag)->field_name, + fv); + fv = 0; + } else + fv = -fv, sign = -1; + } + den = 1L; + if (fv > 0) { + while (fv < 1L<<(31-3) && den < 1L<<(31-3)) + fv *= 1<<3, den *= 1L<<3; + } + t[2*i+0] = (uint32) (sign * (fv + 0.5)); + t[2*i+1] = den; + } + status = TIFFWriteData(tif, dir, (char *)t); + _TIFFfree((char*) t); + return (status); +} + +static int +TIFFWriteFloatArray(TIFF* tif, TIFFDirEntry* dir, float* v) +{ + TIFFCvtNativeToIEEEFloat(tif, dir->tdir_count, v); + if (dir->tdir_count == 1) { + dir->tdir_offset = *(uint32*) &v[0]; + return (1); + } else + return (TIFFWriteData(tif, dir, (char*) v)); +} + +static int +TIFFWriteDoubleArray(TIFF* tif, TIFFDirEntry* dir, double* v) +{ + TIFFCvtNativeToIEEEDouble(tif, dir->tdir_count, v); + return (TIFFWriteData(tif, dir, (char*) v)); +} + +/* + * Write an array of ``type'' values for a specified tag (i.e. this is a tag + * which is allowed to have different types, e.g. SMaxSampleType). + * Internally the data values are represented as double since a double can + * hold any of the TIFF tag types (yes, this should really be an abstract + * type tany_t for portability). The data is converted into the specified + * type in a temporary buffer and then handed off to the appropriate array + * writer. + */ +static int +TIFFWriteAnyArray(TIFF* tif, + TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, double* v) +{ + char buf[10 * sizeof(double)]; + char* w = buf; + int i, status = 0; + + if (n * TIFFDataWidth(type) > sizeof buf) { + w = (char*) _TIFFmalloc(n * TIFFDataWidth(type)); + if (w == NULL) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "No space to write array"); + return (0); + } + } + + dir->tdir_tag = (uint16) tag; + dir->tdir_type = (uint16) type; + dir->tdir_count = n; + + switch (type) { + case TIFF_BYTE: + { + uint8* bp = (uint8*) w; + for (i = 0; i < (int) n; i++) + bp[i] = (uint8) v[i]; + if (!TIFFWriteByteArray(tif, dir, (char*) bp)) + goto out; + } + break; + case TIFF_SBYTE: + { + int8* bp = (int8*) w; + for (i = 0; i < (int) n; i++) + bp[i] = (int8) v[i]; + if (!TIFFWriteByteArray(tif, dir, (char*) bp)) + goto out; + } + break; + case TIFF_SHORT: + { + uint16* bp = (uint16*) w; + for (i = 0; i < (int) n; i++) + bp[i] = (uint16) v[i]; + if (!TIFFWriteShortArray(tif, dir, (uint16*)bp)) + goto out; + } + break; + case TIFF_SSHORT: + { + int16* bp = (int16*) w; + for (i = 0; i < (int) n; i++) + bp[i] = (int16) v[i]; + if (!TIFFWriteShortArray(tif, dir, (uint16*)bp)) + goto out; + } + break; + case TIFF_LONG: + { + uint32* bp = (uint32*) w; + for (i = 0; i < (int) n; i++) + bp[i] = (uint32) v[i]; + if (!TIFFWriteLongArray(tif, dir, bp)) + goto out; + } + break; + case TIFF_SLONG: + { + int32* bp = (int32*) w; + for (i = 0; i < (int) n; i++) + bp[i] = (int32) v[i]; + if (!TIFFWriteLongArray(tif, dir, (uint32*) bp)) + goto out; + } + break; + case TIFF_FLOAT: + { + float* bp = (float*) w; + for (i = 0; i < (int) n; i++) + bp[i] = (float) v[i]; + if (!TIFFWriteFloatArray(tif, dir, bp)) + goto out; + } + break; + case TIFF_DOUBLE: + { + if( !TIFFWriteDoubleArray(tif, dir, v)) + goto out; + } + break; + default: + /* TIFF_NOTYPE */ + /* TIFF_ASCII */ + /* TIFF_UNDEFINED */ + /* TIFF_RATIONAL */ + /* TIFF_SRATIONAL */ + goto out; + } + status = 1; + out: + if (w != buf) + _TIFFfree(w); + return (status); +} + +static int +TIFFWriteTransferFunction(TIFF* tif, TIFFDirEntry* dir) +{ + TIFFDirectory* td = &tif->tif_dir; + tsize_t n = (1L<td_bitspersample) * sizeof (uint16); + uint16** tf = td->td_transferfunction; + int ncols; + + /* + * Check if the table can be written as a single column, + * or if it must be written as 3 columns. Note that we + * write a 3-column tag if there are 2 samples/pixel and + * a single column of data won't suffice--hmm. + */ + switch (td->td_samplesperpixel - td->td_extrasamples) { + default: if (_TIFFmemcmp(tf[0], tf[2], n)) { ncols = 3; break; } + case 2: if (_TIFFmemcmp(tf[0], tf[1], n)) { ncols = 3; break; } + case 1: case 0: ncols = 1; + } + return (TIFFWriteShortTable(tif, + TIFFTAG_TRANSFERFUNCTION, dir, ncols, tf)); +} + +static int +TIFFWriteInkNames(TIFF* tif, TIFFDirEntry* dir) +{ + TIFFDirectory* td = &tif->tif_dir; + + dir->tdir_tag = TIFFTAG_INKNAMES; + dir->tdir_type = (short) TIFF_ASCII; + dir->tdir_count = td->td_inknameslen; + return (TIFFWriteByteArray(tif, dir, td->td_inknames)); +} + +/* + * Write a contiguous directory item. + */ +static int +TIFFWriteData(TIFF* tif, TIFFDirEntry* dir, char* cp) +{ + tsize_t cc; + + if (tif->tif_flags & TIFF_SWAB) { + switch (dir->tdir_type) { + case TIFF_SHORT: + case TIFF_SSHORT: + TIFFSwabArrayOfShort((uint16*) cp, dir->tdir_count); + break; + case TIFF_LONG: + case TIFF_SLONG: + case TIFF_FLOAT: + TIFFSwabArrayOfLong((uint32*) cp, dir->tdir_count); + break; + case TIFF_RATIONAL: + case TIFF_SRATIONAL: + TIFFSwabArrayOfLong((uint32*) cp, 2*dir->tdir_count); + break; + case TIFF_DOUBLE: + TIFFSwabArrayOfDouble((double*) cp, dir->tdir_count); + break; + } + } + dir->tdir_offset = tif->tif_dataoff; + cc = dir->tdir_count * TIFFDataWidth((TIFFDataType) dir->tdir_type); + if (SeekOK(tif, dir->tdir_offset) && + WriteOK(tif, cp, cc)) { + tif->tif_dataoff += (cc + 1) & ~1; + return (1); + } + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Error writing data for field \"%s\"", + _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name); + return (0); +} + +/* + * Similar to TIFFWriteDirectory(), but if the directory has already + * been written once, it is relocated to the end of the file, in case it + * has changed in size. Note that this will result in the loss of the + * previously used directory space. + */ + +int +TIFFRewriteDirectory( TIFF *tif ) +{ + static const char module[] = "TIFFRewriteDirectory"; + + /* We don't need to do anything special if it hasn't been written. */ + if( tif->tif_diroff == 0 ) + return TIFFWriteDirectory( tif ); + + /* + ** Find and zero the pointer to this directory, so that TIFFLinkDirectory + ** will cause it to be added after this directories current pre-link. + */ + + /* Is it the first directory in the file? */ + if (tif->tif_header.tiff_diroff == tif->tif_diroff) + { + tif->tif_header.tiff_diroff = 0; + tif->tif_diroff = 0; + + TIFFSeekFile(tif, (toff_t)(TIFF_MAGIC_SIZE+TIFF_VERSION_SIZE), + SEEK_SET); + if (!WriteOK(tif, &(tif->tif_header.tiff_diroff), + sizeof (tif->tif_diroff))) + { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Error updating TIFF header"); + return (0); + } + } + else + { + toff_t nextdir, off; + + nextdir = tif->tif_header.tiff_diroff; + do { + uint16 dircount; + + if (!SeekOK(tif, nextdir) || + !ReadOK(tif, &dircount, sizeof (dircount))) { + TIFFErrorExt(tif->tif_clientdata, module, + "Error fetching directory count"); + return (0); + } + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabShort(&dircount); + (void) TIFFSeekFile(tif, + dircount * sizeof (TIFFDirEntry), SEEK_CUR); + if (!ReadOK(tif, &nextdir, sizeof (nextdir))) { + TIFFErrorExt(tif->tif_clientdata, module, + "Error fetching directory link"); + return (0); + } + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabLong(&nextdir); + } while (nextdir != tif->tif_diroff && nextdir != 0); + off = TIFFSeekFile(tif, 0, SEEK_CUR); /* get current offset */ + (void) TIFFSeekFile(tif, off - (toff_t)sizeof(nextdir), SEEK_SET); + tif->tif_diroff = 0; + if (!WriteOK(tif, &(tif->tif_diroff), sizeof (nextdir))) { + TIFFErrorExt(tif->tif_clientdata, module, + "Error writing directory link"); + return (0); + } + } + + /* + ** Now use TIFFWriteDirectory() normally. + */ + + return TIFFWriteDirectory( tif ); +} + + +/* + * Link the current directory into the directory chain for the file. + */ +static int +TIFFLinkDirectory(TIFF* tif) +{ + static const char module[] = "TIFFLinkDirectory"; + toff_t nextdir; + toff_t diroff, off; + + tif->tif_diroff = (TIFFSeekFile(tif, (toff_t) 0, SEEK_END)+1) &~ 1; + diroff = tif->tif_diroff; + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabLong(&diroff); + + /* + * Handle SubIFDs + */ + if (tif->tif_flags & TIFF_INSUBIFD) { + (void) TIFFSeekFile(tif, tif->tif_subifdoff, SEEK_SET); + if (!WriteOK(tif, &diroff, sizeof (diroff))) { + TIFFErrorExt(tif->tif_clientdata, module, + "%s: Error writing SubIFD directory link", + tif->tif_name); + return (0); + } + /* + * Advance to the next SubIFD or, if this is + * the last one configured, revert back to the + * normal directory linkage. + */ + if (--tif->tif_nsubifd) + tif->tif_subifdoff += sizeof (diroff); + else + tif->tif_flags &= ~TIFF_INSUBIFD; + return (1); + } + + if (tif->tif_header.tiff_diroff == 0) { + /* + * First directory, overwrite offset in header. + */ + tif->tif_header.tiff_diroff = tif->tif_diroff; + (void) TIFFSeekFile(tif, + (toff_t)(TIFF_MAGIC_SIZE+TIFF_VERSION_SIZE), + SEEK_SET); + if (!WriteOK(tif, &diroff, sizeof (diroff))) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Error writing TIFF header"); + return (0); + } + return (1); + } + /* + * Not the first directory, search to the last and append. + */ + nextdir = tif->tif_header.tiff_diroff; + do { + uint16 dircount; + + if (!SeekOK(tif, nextdir) || + !ReadOK(tif, &dircount, sizeof (dircount))) { + TIFFErrorExt(tif->tif_clientdata, module, + "Error fetching directory count"); + return (0); + } + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabShort(&dircount); + (void) TIFFSeekFile(tif, + dircount * sizeof (TIFFDirEntry), SEEK_CUR); + if (!ReadOK(tif, &nextdir, sizeof (nextdir))) { + TIFFErrorExt(tif->tif_clientdata, module, + "Error fetching directory link"); + return (0); + } + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabLong(&nextdir); + } while (nextdir != 0); + off = TIFFSeekFile(tif, 0, SEEK_CUR); /* get current offset */ + (void) TIFFSeekFile(tif, off - (toff_t)sizeof(nextdir), SEEK_SET); + if (!WriteOK(tif, &diroff, sizeof (diroff))) { + TIFFErrorExt(tif->tif_clientdata, module, + "Error writing directory link"); + return (0); + } + return (1); +} + +/* vim: set ts=8 sts=8 sw=8 noet: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tif_dumpmode.c b/reactos/dll/3rdparty/libtiff/tif_dumpmode.c new file mode 100644 index 00000000000..da861503d80 --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tif_dumpmode.c @@ -0,0 +1,126 @@ +/* $Header: /cvs/maptools/cvsroot/libtiff/libtiff/tif_dumpmode.c,v 1.5.2.2 2010-06-08 18:50:42 bfriesen Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library. + * + * "Null" Compression Algorithm Support. + */ +#include "tiffiop.h" + +/* + * Encode a hunk of pixels. + */ +static int +DumpModeEncode(TIFF* tif, tidata_t pp, tsize_t cc, tsample_t s) +{ + (void) s; + while (cc > 0) { + tsize_t n; + + n = cc; + if (tif->tif_rawcc + n > tif->tif_rawdatasize) + n = tif->tif_rawdatasize - tif->tif_rawcc; + + assert( n > 0 ); + + /* + * Avoid copy if client has setup raw + * data buffer to avoid extra copy. + */ + if (tif->tif_rawcp != pp) + _TIFFmemcpy(tif->tif_rawcp, pp, n); + tif->tif_rawcp += n; + tif->tif_rawcc += n; + pp += n; + cc -= n; + if (tif->tif_rawcc >= tif->tif_rawdatasize && + !TIFFFlushData1(tif)) + return (-1); + } + return (1); +} + +/* + * Decode a hunk of pixels. + */ +static int +DumpModeDecode(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s) +{ + (void) s; +/* fprintf(stderr,"DumpModeDecode: scanline %ld, expected %ld bytes, got %ld bytes\n", */ +/* (long) tif->tif_row, (long) tif->tif_rawcc, (long) cc); */ + if (tif->tif_rawcc < cc) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "DumpModeDecode: Not enough data for scanline %d", + tif->tif_row); + return (0); + } + /* + * Avoid copy if client has setup raw + * data buffer to avoid extra copy. + */ + if (tif->tif_rawcp != buf) + _TIFFmemcpy(buf, tif->tif_rawcp, cc); + tif->tif_rawcp += cc; + tif->tif_rawcc -= cc; + return (1); +} + +/* + * Seek forwards nrows in the current strip. + */ +static int +DumpModeSeek(TIFF* tif, uint32 nrows) +{ + tif->tif_rawcp += nrows * tif->tif_scanlinesize; + tif->tif_rawcc -= nrows * tif->tif_scanlinesize; + return (1); +} + +/* + * Initialize dump mode. + */ +int +TIFFInitDumpMode(TIFF* tif, int scheme) +{ + (void) scheme; + tif->tif_decoderow = DumpModeDecode; + tif->tif_decodestrip = DumpModeDecode; + tif->tif_decodetile = DumpModeDecode; + tif->tif_encoderow = DumpModeEncode; + tif->tif_encodestrip = DumpModeEncode; + tif->tif_encodetile = DumpModeEncode; + tif->tif_seek = DumpModeSeek; + return (1); +} +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tif_error.c b/reactos/dll/3rdparty/libtiff/tif_error.c new file mode 100644 index 00000000000..2377abda877 --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tif_error.c @@ -0,0 +1,80 @@ +/* $Header: /cvs/maptools/cvsroot/libtiff/libtiff/tif_error.c,v 1.4.2.1 2010-06-08 18:50:42 bfriesen Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library. + */ +#include "tiffiop.h" + +TIFFErrorHandlerExt _TIFFerrorHandlerExt = NULL; + +TIFFErrorHandler +TIFFSetErrorHandler(TIFFErrorHandler handler) +{ + TIFFErrorHandler prev = _TIFFerrorHandler; + _TIFFerrorHandler = handler; + return (prev); +} + +TIFFErrorHandlerExt +TIFFSetErrorHandlerExt(TIFFErrorHandlerExt handler) +{ + TIFFErrorHandlerExt prev = _TIFFerrorHandlerExt; + _TIFFerrorHandlerExt = handler; + return (prev); +} + +void +TIFFError(const char* module, const char* fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + if (_TIFFerrorHandler) + (*_TIFFerrorHandler)(module, fmt, ap); + if (_TIFFerrorHandlerExt) + (*_TIFFerrorHandlerExt)(0, module, fmt, ap); + va_end(ap); +} + +void +TIFFErrorExt(thandle_t fd, const char* module, const char* fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + if (_TIFFerrorHandler) + (*_TIFFerrorHandler)(module, fmt, ap); + if (_TIFFerrorHandlerExt) + (*_TIFFerrorHandlerExt)(fd, module, fmt, ap); + va_end(ap); +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tif_extension.c b/reactos/dll/3rdparty/libtiff/tif_extension.c new file mode 100644 index 00000000000..b67c0f00be3 --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tif_extension.c @@ -0,0 +1,118 @@ +/* $Header: /cvs/maptools/cvsroot/libtiff/libtiff/tif_extension.c,v 1.4.2.1 2010-06-08 18:50:42 bfriesen Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library. + * + * Various routines support external extension of the tag set, and other + * application extension capabilities. + */ + +#include "tiffiop.h" + +int TIFFGetTagListCount( TIFF *tif ) + +{ + TIFFDirectory* td = &tif->tif_dir; + + return td->td_customValueCount; +} + +ttag_t TIFFGetTagListEntry( TIFF *tif, int tag_index ) + +{ + TIFFDirectory* td = &tif->tif_dir; + + if( tag_index < 0 || tag_index >= td->td_customValueCount ) + return (ttag_t) -1; + else + return td->td_customValues[tag_index].info->field_tag; +} + +/* +** This provides read/write access to the TIFFTagMethods within the TIFF +** structure to application code without giving access to the private +** TIFF structure. +*/ +TIFFTagMethods *TIFFAccessTagMethods( TIFF *tif ) + +{ + return &(tif->tif_tagmethods); +} + +void *TIFFGetClientInfo( TIFF *tif, const char *name ) + +{ + TIFFClientInfoLink *link = tif->tif_clientinfo; + + while( link != NULL && strcmp(link->name,name) != 0 ) + link = link->next; + + if( link != NULL ) + return link->data; + else + return NULL; +} + +void TIFFSetClientInfo( TIFF *tif, void *data, const char *name ) + +{ + TIFFClientInfoLink *link = tif->tif_clientinfo; + + /* + ** Do we have an existing link with this name? If so, just + ** set it. + */ + while( link != NULL && strcmp(link->name,name) != 0 ) + link = link->next; + + if( link != NULL ) + { + link->data = data; + return; + } + + /* + ** Create a new link. + */ + + link = (TIFFClientInfoLink *) _TIFFmalloc(sizeof(TIFFClientInfoLink)); + assert (link != NULL); + link->next = tif->tif_clientinfo; + link->name = (char *) _TIFFmalloc(strlen(name)+1); + assert (link->name != NULL); + strcpy(link->name, name); + link->data = data; + + tif->tif_clientinfo = link; +} +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tif_fax3.c b/reactos/dll/3rdparty/libtiff/tif_fax3.c new file mode 100644 index 00000000000..9eec4ab7b7a --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tif_fax3.c @@ -0,0 +1,1626 @@ +/* $Id: tif_fax3.c,v 1.43.2.10 2010-06-09 17:16:58 bfriesen Exp $ */ + +/* + * Copyright (c) 1990-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include "tiffiop.h" +#ifdef CCITT_SUPPORT +/* + * TIFF Library. + * + * CCITT Group 3 (T.4) and Group 4 (T.6) Compression Support. + * + * This file contains support for decoding and encoding TIFF + * compression algorithms 2, 3, 4, and 32771. + * + * Decoder support is derived, with permission, from the code + * in Frank Cringle's viewfax program; + * Copyright (C) 1990, 1995 Frank D. Cringle. + */ +#include "tif_fax3.h" +#define G3CODES +#include "t4.h" +#include + +/* + * Compression+decompression state blocks are + * derived from this ``base state'' block. + */ +typedef struct { + int rw_mode; /* O_RDONLY for decode, else encode */ + int mode; /* operating mode */ + uint32 rowbytes; /* bytes in a decoded scanline */ + uint32 rowpixels; /* pixels in a scanline */ + + uint16 cleanfaxdata; /* CleanFaxData tag */ + uint32 badfaxrun; /* BadFaxRun tag */ + uint32 badfaxlines; /* BadFaxLines tag */ + uint32 groupoptions; /* Group 3/4 options tag */ + uint32 recvparams; /* encoded Class 2 session params */ + char* subaddress; /* subaddress string */ + uint32 recvtime; /* time spent receiving (secs) */ + char* faxdcs; /* Table 2/T.30 encoded session params */ + TIFFVGetMethod vgetparent; /* super-class method */ + TIFFVSetMethod vsetparent; /* super-class method */ + TIFFPrintMethod printdir; /* super-class method */ +} Fax3BaseState; +#define Fax3State(tif) ((Fax3BaseState*) (tif)->tif_data) + +typedef enum { G3_1D, G3_2D } Ttag; +typedef struct { + Fax3BaseState b; + + /* Decoder state info */ + const unsigned char* bitmap; /* bit reversal table */ + uint32 data; /* current i/o byte/word */ + int bit; /* current i/o bit in byte */ + int EOLcnt; /* count of EOL codes recognized */ + TIFFFaxFillFunc fill; /* fill routine */ + uint32* runs; /* b&w runs for current/previous row */ + uint32* refruns; /* runs for reference line */ + uint32* curruns; /* runs for current line */ + + /* Encoder state info */ + Ttag tag; /* encoding state */ + unsigned char* refline; /* reference line for 2d decoding */ + int k; /* #rows left that can be 2d encoded */ + int maxk; /* max #rows that can be 2d encoded */ + + int line; +} Fax3CodecState; +#define DecoderState(tif) ((Fax3CodecState*) Fax3State(tif)) +#define EncoderState(tif) ((Fax3CodecState*) Fax3State(tif)) + +#define is2DEncoding(sp) \ + (sp->b.groupoptions & GROUP3OPT_2DENCODING) +#define isAligned(p,t) ((((unsigned long)(p)) & (sizeof (t)-1)) == 0) + +/* + * Group 3 and Group 4 Decoding. + */ + +/* + * These macros glue the TIFF library state to + * the state expected by Frank's decoder. + */ +#define DECLARE_STATE(tif, sp, mod) \ + static const char module[] = mod; \ + Fax3CodecState* sp = DecoderState(tif); \ + int a0; /* reference element */ \ + int lastx = sp->b.rowpixels; /* last element in row */ \ + uint32 BitAcc; /* bit accumulator */ \ + int BitsAvail; /* # valid bits in BitAcc */ \ + int RunLength; /* length of current run */ \ + unsigned char* cp; /* next byte of input data */ \ + unsigned char* ep; /* end of input data */ \ + uint32* pa; /* place to stuff next run */ \ + uint32* thisrun; /* current row's run array */ \ + int EOLcnt; /* # EOL codes recognized */ \ + const unsigned char* bitmap = sp->bitmap; /* input data bit reverser */ \ + const TIFFFaxTabEnt* TabEnt +#define DECLARE_STATE_2D(tif, sp, mod) \ + DECLARE_STATE(tif, sp, mod); \ + int b1; /* next change on prev line */ \ + uint32* pb /* next run in reference line */\ +/* + * Load any state that may be changed during decoding. + */ +#define CACHE_STATE(tif, sp) do { \ + BitAcc = sp->data; \ + BitsAvail = sp->bit; \ + EOLcnt = sp->EOLcnt; \ + cp = (unsigned char*) tif->tif_rawcp; \ + ep = cp + tif->tif_rawcc; \ +} while (0) +/* + * Save state possibly changed during decoding. + */ +#define UNCACHE_STATE(tif, sp) do { \ + sp->bit = BitsAvail; \ + sp->data = BitAcc; \ + sp->EOLcnt = EOLcnt; \ + tif->tif_rawcc -= (tidata_t) cp - tif->tif_rawcp; \ + tif->tif_rawcp = (tidata_t) cp; \ +} while (0) + +/* + * Setup state for decoding a strip. + */ +static int +Fax3PreDecode(TIFF* tif, tsample_t s) +{ + Fax3CodecState* sp = DecoderState(tif); + + (void) s; + assert(sp != NULL); + sp->bit = 0; /* force initial read */ + sp->data = 0; + sp->EOLcnt = 0; /* force initial scan for EOL */ + /* + * Decoder assumes lsb-to-msb bit order. Note that we select + * this here rather than in Fax3SetupState so that viewers can + * hold the image open, fiddle with the FillOrder tag value, + * and then re-decode the image. Otherwise they'd need to close + * and open the image to get the state reset. + */ + sp->bitmap = + TIFFGetBitRevTable(tif->tif_dir.td_fillorder != FILLORDER_LSB2MSB); + if (sp->refruns) { /* init reference line to white */ + sp->refruns[0] = (uint32) sp->b.rowpixels; + sp->refruns[1] = 0; + } + sp->line = 0; + return (1); +} + +/* + * Routine for handling various errors/conditions. + * Note how they are "glued into the decoder" by + * overriding the definitions used by the decoder. + */ + +static void +Fax3Unexpected(const char* module, TIFF* tif, uint32 line, uint32 a0) +{ + TIFFErrorExt(tif->tif_clientdata, module, "%s: Bad code word at line %u of %s %u (x %u)", + tif->tif_name, line, isTiled(tif) ? "tile" : "strip", + (isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip), + a0); +} +#define unexpected(table, a0) Fax3Unexpected(module, tif, sp->line, a0) + +static void +Fax3Extension(const char* module, TIFF* tif, uint32 line, uint32 a0) +{ + TIFFErrorExt(tif->tif_clientdata, module, + "%s: Uncompressed data (not supported) at line %u of %s %u (x %u)", + tif->tif_name, line, isTiled(tif) ? "tile" : "strip", + (isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip), + a0); +} +#define extension(a0) Fax3Extension(module, tif, sp->line, a0) + +static void +Fax3BadLength(const char* module, TIFF* tif, uint32 line, uint32 a0, uint32 lastx) +{ + TIFFWarningExt(tif->tif_clientdata, module, "%s: %s at line %u of %s %u (got %u, expected %u)", + tif->tif_name, + a0 < lastx ? "Premature EOL" : "Line length mismatch", + line, isTiled(tif) ? "tile" : "strip", + (isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip), + a0, lastx); +} +#define badlength(a0,lastx) Fax3BadLength(module, tif, sp->line, a0, lastx) + +static void +Fax3PrematureEOF(const char* module, TIFF* tif, uint32 line, uint32 a0) +{ + TIFFWarningExt(tif->tif_clientdata, module, "%s: Premature EOF at line %u of %s %u (x %u)", + tif->tif_name, + line, isTiled(tif) ? "tile" : "strip", + (isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip), + a0); +} +#define prematureEOF(a0) Fax3PrematureEOF(module, tif, sp->line, a0) + +#define Nop + +/* + * Decode the requested amount of G3 1D-encoded data. + */ +static int +Fax3Decode1D(TIFF* tif, tidata_t buf, tsize_t occ, tsample_t s) +{ + DECLARE_STATE(tif, sp, "Fax3Decode1D"); + + (void) s; + CACHE_STATE(tif, sp); + thisrun = sp->curruns; + while ((long)occ > 0) { + a0 = 0; + RunLength = 0; + pa = thisrun; +#ifdef FAX3_DEBUG + printf("\nBitAcc=%08X, BitsAvail = %d\n", BitAcc, BitsAvail); + printf("-------------------- %d\n", tif->tif_row); + fflush(stdout); +#endif + SYNC_EOL(EOF1D); + EXPAND1D(EOF1Da); + (*sp->fill)(buf, thisrun, pa, lastx); + buf += sp->b.rowbytes; + occ -= sp->b.rowbytes; + sp->line++; + continue; + EOF1D: /* premature EOF */ + CLEANUP_RUNS(); + EOF1Da: /* premature EOF */ + (*sp->fill)(buf, thisrun, pa, lastx); + UNCACHE_STATE(tif, sp); + return (-1); + } + UNCACHE_STATE(tif, sp); + return (1); +} + +#define SWAP(t,a,b) { t x; x = (a); (a) = (b); (b) = x; } +/* + * Decode the requested amount of G3 2D-encoded data. + */ +static int +Fax3Decode2D(TIFF* tif, tidata_t buf, tsize_t occ, tsample_t s) +{ + DECLARE_STATE_2D(tif, sp, "Fax3Decode2D"); + int is1D; /* current line is 1d/2d-encoded */ + + (void) s; + CACHE_STATE(tif, sp); + while ((long)occ > 0) { + a0 = 0; + RunLength = 0; + pa = thisrun = sp->curruns; +#ifdef FAX3_DEBUG + printf("\nBitAcc=%08X, BitsAvail = %d EOLcnt = %d", + BitAcc, BitsAvail, EOLcnt); +#endif + SYNC_EOL(EOF2D); + NeedBits8(1, EOF2D); + is1D = GetBits(1); /* 1D/2D-encoding tag bit */ + ClrBits(1); +#ifdef FAX3_DEBUG + printf(" %s\n-------------------- %d\n", + is1D ? "1D" : "2D", tif->tif_row); + fflush(stdout); +#endif + pb = sp->refruns; + b1 = *pb++; + if (is1D) + EXPAND1D(EOF2Da); + else + EXPAND2D(EOF2Da); + (*sp->fill)(buf, thisrun, pa, lastx); + SETVALUE(0); /* imaginary change for reference */ + SWAP(uint32*, sp->curruns, sp->refruns); + buf += sp->b.rowbytes; + occ -= sp->b.rowbytes; + sp->line++; + continue; + EOF2D: /* premature EOF */ + CLEANUP_RUNS(); + EOF2Da: /* premature EOF */ + (*sp->fill)(buf, thisrun, pa, lastx); + UNCACHE_STATE(tif, sp); + return (-1); + } + UNCACHE_STATE(tif, sp); + return (1); +} +#undef SWAP + +/* + * The ZERO & FILL macros must handle spans < 2*sizeof(long) bytes. + * For machines with 64-bit longs this is <16 bytes; otherwise + * this is <8 bytes. We optimize the code here to reflect the + * machine characteristics. + */ +#if SIZEOF_LONG == 8 +# define FILL(n, cp) \ + switch (n) { \ + case 15:(cp)[14] = 0xff; case 14:(cp)[13] = 0xff; case 13: (cp)[12] = 0xff;\ + case 12:(cp)[11] = 0xff; case 11:(cp)[10] = 0xff; case 10: (cp)[9] = 0xff;\ + case 9: (cp)[8] = 0xff; case 8: (cp)[7] = 0xff; case 7: (cp)[6] = 0xff;\ + case 6: (cp)[5] = 0xff; case 5: (cp)[4] = 0xff; case 4: (cp)[3] = 0xff;\ + case 3: (cp)[2] = 0xff; case 2: (cp)[1] = 0xff; \ + case 1: (cp)[0] = 0xff; (cp) += (n); case 0: ; \ + } +# define ZERO(n, cp) \ + switch (n) { \ + case 15:(cp)[14] = 0; case 14:(cp)[13] = 0; case 13: (cp)[12] = 0; \ + case 12:(cp)[11] = 0; case 11:(cp)[10] = 0; case 10: (cp)[9] = 0; \ + case 9: (cp)[8] = 0; case 8: (cp)[7] = 0; case 7: (cp)[6] = 0; \ + case 6: (cp)[5] = 0; case 5: (cp)[4] = 0; case 4: (cp)[3] = 0; \ + case 3: (cp)[2] = 0; case 2: (cp)[1] = 0; \ + case 1: (cp)[0] = 0; (cp) += (n); case 0: ; \ + } +#else +# define FILL(n, cp) \ + switch (n) { \ + case 7: (cp)[6] = 0xff; case 6: (cp)[5] = 0xff; case 5: (cp)[4] = 0xff; \ + case 4: (cp)[3] = 0xff; case 3: (cp)[2] = 0xff; case 2: (cp)[1] = 0xff; \ + case 1: (cp)[0] = 0xff; (cp) += (n); case 0: ; \ + } +# define ZERO(n, cp) \ + switch (n) { \ + case 7: (cp)[6] = 0; case 6: (cp)[5] = 0; case 5: (cp)[4] = 0; \ + case 4: (cp)[3] = 0; case 3: (cp)[2] = 0; case 2: (cp)[1] = 0; \ + case 1: (cp)[0] = 0; (cp) += (n); case 0: ; \ + } +#endif + +/* + * Bit-fill a row according to the white/black + * runs generated during G3/G4 decoding. + */ +void +_TIFFFax3fillruns(unsigned char* buf, uint32* runs, uint32* erun, uint32 lastx) +{ + static const unsigned char _fillmasks[] = + { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff }; + unsigned char* cp; + uint32 x, bx, run; + int32 n, nw; + long* lp; + + if ((erun-runs)&1) + *erun++ = 0; + x = 0; + for (; runs < erun; runs += 2) { + run = runs[0]; + if (x+run > lastx || run > lastx ) + run = runs[0] = (uint32) (lastx - x); + if (run) { + cp = buf + (x>>3); + bx = x&7; + if (run > 8-bx) { + if (bx) { /* align to byte boundary */ + *cp++ &= 0xff << (8-bx); + run -= 8-bx; + } + if( (n = run >> 3) != 0 ) { /* multiple bytes to fill */ + if ((n/sizeof (long)) > 1) { + /* + * Align to longword boundary and fill. + */ + for (; n && !isAligned(cp, long); n--) + *cp++ = 0x00; + lp = (long*) cp; + nw = (int32)(n / sizeof (long)); + n -= nw * sizeof (long); + do { + *lp++ = 0L; + } while (--nw); + cp = (unsigned char*) lp; + } + ZERO(n, cp); + run &= 7; + } + if (run) + cp[0] &= 0xff >> run; + } else + cp[0] &= ~(_fillmasks[run]>>bx); + x += runs[0]; + } + run = runs[1]; + if (x+run > lastx || run > lastx ) + run = runs[1] = lastx - x; + if (run) { + cp = buf + (x>>3); + bx = x&7; + if (run > 8-bx) { + if (bx) { /* align to byte boundary */ + *cp++ |= 0xff >> bx; + run -= 8-bx; + } + if( (n = run>>3) != 0 ) { /* multiple bytes to fill */ + if ((n/sizeof (long)) > 1) { + /* + * Align to longword boundary and fill. + */ + for (; n && !isAligned(cp, long); n--) + *cp++ = 0xff; + lp = (long*) cp; + nw = (int32)(n / sizeof (long)); + n -= nw * sizeof (long); + do { + *lp++ = -1L; + } while (--nw); + cp = (unsigned char*) lp; + } + FILL(n, cp); + run &= 7; + } + if (run) + cp[0] |= 0xff00 >> run; + } else + cp[0] |= _fillmasks[run]>>bx; + x += runs[1]; + } + } + assert(x == lastx); +} +#undef ZERO +#undef FILL + +/* + * Setup G3/G4-related compression/decompression state + * before data is processed. This routine is called once + * per image -- it sets up different state based on whether + * or not decoding or encoding is being done and whether + * 1D- or 2D-encoded data is involved. + */ +static int +Fax3SetupState(TIFF* tif) +{ + TIFFDirectory* td = &tif->tif_dir; + Fax3BaseState* sp = Fax3State(tif); + int needsRefLine; + Fax3CodecState* dsp = (Fax3CodecState*) Fax3State(tif); + uint32 rowbytes, rowpixels, nruns; + + if (td->td_bitspersample != 1) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Bits/sample must be 1 for Group 3/4 encoding/decoding"); + return (0); + } + /* + * Calculate the scanline/tile widths. + */ + if (isTiled(tif)) { + rowbytes = TIFFTileRowSize(tif); + rowpixels = td->td_tilewidth; + } else { + rowbytes = TIFFScanlineSize(tif); + rowpixels = td->td_imagewidth; + } + sp->rowbytes = (uint32) rowbytes; + sp->rowpixels = (uint32) rowpixels; + /* + * Allocate any additional space required for decoding/encoding. + */ + needsRefLine = ( + (sp->groupoptions & GROUP3OPT_2DENCODING) || + td->td_compression == COMPRESSION_CCITTFAX4 + ); + + /* + Assure that allocation computations do not overflow. + + TIFFroundup and TIFFSafeMultiply return zero on integer overflow + */ + dsp->runs=(uint32*) NULL; + nruns = TIFFroundup(rowpixels,32); + if (needsRefLine) { + nruns = TIFFSafeMultiply(uint32,nruns,2); + } + if ((nruns == 0) || (TIFFSafeMultiply(uint32,nruns,2) == 0)) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Row pixels integer overflow (rowpixels %u)", + rowpixels); + return (0); + } + dsp->runs = (uint32*) _TIFFCheckMalloc(tif, + TIFFSafeMultiply(uint32,nruns,2), + sizeof (uint32), + "for Group 3/4 run arrays"); + if (dsp->runs == NULL) + return (0); + dsp->curruns = dsp->runs; + if (needsRefLine) + dsp->refruns = dsp->runs + nruns; + else + dsp->refruns = NULL; + if (td->td_compression == COMPRESSION_CCITTFAX3 + && is2DEncoding(dsp)) { /* NB: default is 1D routine */ + tif->tif_decoderow = Fax3Decode2D; + tif->tif_decodestrip = Fax3Decode2D; + tif->tif_decodetile = Fax3Decode2D; + } + + if (needsRefLine) { /* 2d encoding */ + Fax3CodecState* esp = EncoderState(tif); + /* + * 2d encoding requires a scanline + * buffer for the ``reference line''; the + * scanline against which delta encoding + * is referenced. The reference line must + * be initialized to be ``white'' (done elsewhere). + */ + esp->refline = (unsigned char*) _TIFFmalloc(rowbytes); + if (esp->refline == NULL) { + TIFFErrorExt(tif->tif_clientdata, "Fax3SetupState", + "%s: No space for Group 3/4 reference line", + tif->tif_name); + return (0); + } + } else /* 1d encoding */ + EncoderState(tif)->refline = NULL; + + return (1); +} + +/* + * CCITT Group 3 FAX Encoding. + */ + +#define Fax3FlushBits(tif, sp) { \ + if ((tif)->tif_rawcc >= (tif)->tif_rawdatasize) \ + (void) TIFFFlushData1(tif); \ + *(tif)->tif_rawcp++ = (tidataval_t) (sp)->data; \ + (tif)->tif_rawcc++; \ + (sp)->data = 0, (sp)->bit = 8; \ +} +#define _FlushBits(tif) { \ + if ((tif)->tif_rawcc >= (tif)->tif_rawdatasize) \ + (void) TIFFFlushData1(tif); \ + *(tif)->tif_rawcp++ = (tidataval_t) data; \ + (tif)->tif_rawcc++; \ + data = 0, bit = 8; \ +} +static const int _msbmask[9] = + { 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff }; +#define _PutBits(tif, bits, length) { \ + while (length > bit) { \ + data |= bits >> (length - bit); \ + length -= bit; \ + _FlushBits(tif); \ + } \ + data |= (bits & _msbmask[length]) << (bit - length); \ + bit -= length; \ + if (bit == 0) \ + _FlushBits(tif); \ +} + +/* + * Write a variable-length bit-value to + * the output stream. Values are + * assumed to be at most 16 bits. + */ +static void +Fax3PutBits(TIFF* tif, unsigned int bits, unsigned int length) +{ + Fax3CodecState* sp = EncoderState(tif); + unsigned int bit = sp->bit; + int data = sp->data; + + _PutBits(tif, bits, length); + + sp->data = data; + sp->bit = bit; +} + +/* + * Write a code to the output stream. + */ +#define putcode(tif, te) Fax3PutBits(tif, (te)->code, (te)->length) + +#ifdef FAX3_DEBUG +#define DEBUG_COLOR(w) (tab == TIFFFaxWhiteCodes ? w "W" : w "B") +#define DEBUG_PRINT(what,len) { \ + int t; \ + printf("%08X/%-2d: %s%5d\t", data, bit, DEBUG_COLOR(what), len); \ + for (t = length-1; t >= 0; t--) \ + putchar(code & (1<bit; + int data = sp->data; + unsigned int code, length; + + while (span >= 2624) { + const tableentry* te = &tab[63 + (2560>>6)]; + code = te->code, length = te->length; +#ifdef FAX3_DEBUG + DEBUG_PRINT("MakeUp", te->runlen); +#endif + _PutBits(tif, code, length); + span -= te->runlen; + } + if (span >= 64) { + const tableentry* te = &tab[63 + (span>>6)]; + assert(te->runlen == 64*(span>>6)); + code = te->code, length = te->length; +#ifdef FAX3_DEBUG + DEBUG_PRINT("MakeUp", te->runlen); +#endif + _PutBits(tif, code, length); + span -= te->runlen; + } + code = tab[span].code, length = tab[span].length; +#ifdef FAX3_DEBUG + DEBUG_PRINT(" Term", tab[span].runlen); +#endif + _PutBits(tif, code, length); + + sp->data = data; + sp->bit = bit; +} + +/* + * Write an EOL code to the output stream. The zero-fill + * logic for byte-aligning encoded scanlines is handled + * here. We also handle writing the tag bit for the next + * scanline when doing 2d encoding. + */ +static void +Fax3PutEOL(TIFF* tif) +{ + Fax3CodecState* sp = EncoderState(tif); + unsigned int bit = sp->bit; + int data = sp->data; + unsigned int code, length, tparm; + + if (sp->b.groupoptions & GROUP3OPT_FILLBITS) { + /* + * Force bit alignment so EOL will terminate on + * a byte boundary. That is, force the bit alignment + * to 16-12 = 4 before putting out the EOL code. + */ + int align = 8 - 4; + if (align != sp->bit) { + if (align > sp->bit) + align = sp->bit + (8 - align); + else + align = sp->bit - align; + code = 0; + tparm=align; + _PutBits(tif, 0, tparm); + } + } + code = EOL, length = 12; + if (is2DEncoding(sp)) + code = (code<<1) | (sp->tag == G3_1D), length++; + _PutBits(tif, code, length); + + sp->data = data; + sp->bit = bit; +} + +/* + * Reset encoding state at the start of a strip. + */ +static int +Fax3PreEncode(TIFF* tif, tsample_t s) +{ + Fax3CodecState* sp = EncoderState(tif); + + (void) s; + assert(sp != NULL); + sp->bit = 8; + sp->data = 0; + sp->tag = G3_1D; + /* + * This is necessary for Group 4; otherwise it isn't + * needed because the first scanline of each strip ends + * up being copied into the refline. + */ + if (sp->refline) + _TIFFmemset(sp->refline, 0x00, sp->b.rowbytes); + if (is2DEncoding(sp)) { + float res = tif->tif_dir.td_yresolution; + /* + * The CCITT spec says that when doing 2d encoding, you + * should only do it on K consecutive scanlines, where K + * depends on the resolution of the image being encoded + * (2 for <= 200 lpi, 4 for > 200 lpi). Since the directory + * code initializes td_yresolution to 0, this code will + * select a K of 2 unless the YResolution tag is set + * appropriately. (Note also that we fudge a little here + * and use 150 lpi to avoid problems with units conversion.) + */ + if (tif->tif_dir.td_resolutionunit == RESUNIT_CENTIMETER) + res *= 2.54f; /* convert to inches */ + sp->maxk = (res > 150 ? 4 : 2); + sp->k = sp->maxk-1; + } else + sp->k = sp->maxk = 0; + sp->line = 0; + return (1); +} + +static const unsigned char zeroruns[256] = { + 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, /* 0x00 - 0x0f */ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0x10 - 0x1f */ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x20 - 0x2f */ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x30 - 0x3f */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40 - 0x4f */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x50 - 0x5f */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60 - 0x6f */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x70 - 0x7f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 - 0x8f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 - 0x9f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0 - 0xaf */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0 - 0xbf */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xc0 - 0xcf */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd0 - 0xdf */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xe0 - 0xef */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xf0 - 0xff */ +}; +static const unsigned char oneruns[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 - 0x0f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 - 0x1f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 - 0x2f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x30 - 0x3f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 - 0x4f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 - 0x5f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 - 0x6f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 - 0x7f */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x80 - 0x8f */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x90 - 0x9f */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xa0 - 0xaf */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xb0 - 0xbf */ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xc0 - 0xcf */ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xd0 - 0xdf */ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xe0 - 0xef */ + 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8, /* 0xf0 - 0xff */ +}; + +/* + * On certain systems it pays to inline + * the routines that find pixel spans. + */ +#ifdef VAXC +static int32 find0span(unsigned char*, int32, int32); +static int32 find1span(unsigned char*, int32, int32); +#pragma inline(find0span,find1span) +#endif + +/* + * Find a span of ones or zeros using the supplied + * table. The ``base'' of the bit string is supplied + * along with the start+end bit indices. + */ +static int32 +find0span(unsigned char* bp, int32 bs, int32 be) +{ + int32 bits = be - bs; + int32 n, span; + + bp += bs>>3; + /* + * Check partial byte on lhs. + */ + if (bits > 0 && (n = (bs & 7))) { + span = zeroruns[(*bp << n) & 0xff]; + if (span > 8-n) /* table value too generous */ + span = 8-n; + if (span > bits) /* constrain span to bit range */ + span = bits; + if (n+span < 8) /* doesn't extend to edge of byte */ + return (span); + bits -= span; + bp++; + } else + span = 0; + if (bits >= (int32)(2 * 8 * sizeof(long))) { + long* lp; + /* + * Align to longword boundary and check longwords. + */ + while (!isAligned(bp, long)) { + if (*bp != 0x00) + return (span + zeroruns[*bp]); + span += 8, bits -= 8; + bp++; + } + lp = (long*) bp; + while ((bits >= (int32)(8 * sizeof(long))) && (0 == *lp)) { + span += 8*sizeof (long), bits -= 8*sizeof (long); + lp++; + } + bp = (unsigned char*) lp; + } + /* + * Scan full bytes for all 0's. + */ + while (bits >= 8) { + if (*bp != 0x00) /* end of run */ + return (span + zeroruns[*bp]); + span += 8, bits -= 8; + bp++; + } + /* + * Check partial byte on rhs. + */ + if (bits > 0) { + n = zeroruns[*bp]; + span += (n > bits ? bits : n); + } + return (span); +} + +static int32 +find1span(unsigned char* bp, int32 bs, int32 be) +{ + int32 bits = be - bs; + int32 n, span; + + bp += bs>>3; + /* + * Check partial byte on lhs. + */ + if (bits > 0 && (n = (bs & 7))) { + span = oneruns[(*bp << n) & 0xff]; + if (span > 8-n) /* table value too generous */ + span = 8-n; + if (span > bits) /* constrain span to bit range */ + span = bits; + if (n+span < 8) /* doesn't extend to edge of byte */ + return (span); + bits -= span; + bp++; + } else + span = 0; + if (bits >= (int32)(2 * 8 * sizeof(long))) { + long* lp; + /* + * Align to longword boundary and check longwords. + */ + while (!isAligned(bp, long)) { + if (*bp != 0xff) + return (span + oneruns[*bp]); + span += 8, bits -= 8; + bp++; + } + lp = (long*) bp; + while ((bits >= (int32)(8 * sizeof(long))) && (~0 == *lp)) { + span += 8*sizeof (long), bits -= 8*sizeof (long); + lp++; + } + bp = (unsigned char*) lp; + } + /* + * Scan full bytes for all 1's. + */ + while (bits >= 8) { + if (*bp != 0xff) /* end of run */ + return (span + oneruns[*bp]); + span += 8, bits -= 8; + bp++; + } + /* + * Check partial byte on rhs. + */ + if (bits > 0) { + n = oneruns[*bp]; + span += (n > bits ? bits : n); + } + return (span); +} + +/* + * Return the offset of the next bit in the range + * [bs..be] that is different from the specified + * color. The end, be, is returned if no such bit + * exists. + */ +#define finddiff(_cp, _bs, _be, _color) \ + (_bs + (_color ? find1span(_cp,_bs,_be) : find0span(_cp,_bs,_be))) +/* + * Like finddiff, but also check the starting bit + * against the end in case start > end. + */ +#define finddiff2(_cp, _bs, _be, _color) \ + (_bs < _be ? finddiff(_cp,_bs,_be,_color) : _be) + +/* + * 1d-encode a row of pixels. The encoding is + * a sequence of all-white or all-black spans + * of pixels encoded with Huffman codes. + */ +static int +Fax3Encode1DRow(TIFF* tif, unsigned char* bp, uint32 bits) +{ + Fax3CodecState* sp = EncoderState(tif); + int32 span; + uint32 bs = 0; + + for (;;) { + span = find0span(bp, bs, bits); /* white span */ + putspan(tif, span, TIFFFaxWhiteCodes); + bs += span; + if (bs >= bits) + break; + span = find1span(bp, bs, bits); /* black span */ + putspan(tif, span, TIFFFaxBlackCodes); + bs += span; + if (bs >= bits) + break; + } + if (sp->b.mode & (FAXMODE_BYTEALIGN|FAXMODE_WORDALIGN)) { + if (sp->bit != 8) /* byte-align */ + Fax3FlushBits(tif, sp); + if ((sp->b.mode&FAXMODE_WORDALIGN) && + !isAligned(tif->tif_rawcp, uint16)) + Fax3FlushBits(tif, sp); + } + return (1); +} + +static const tableentry horizcode = + { 3, 0x1, 0 }; /* 001 */ +static const tableentry passcode = + { 4, 0x1, 0 }; /* 0001 */ +static const tableentry vcodes[7] = { + { 7, 0x03, 0 }, /* 0000 011 */ + { 6, 0x03, 0 }, /* 0000 11 */ + { 3, 0x03, 0 }, /* 011 */ + { 1, 0x1, 0 }, /* 1 */ + { 3, 0x2, 0 }, /* 010 */ + { 6, 0x02, 0 }, /* 0000 10 */ + { 7, 0x02, 0 } /* 0000 010 */ +}; + +/* + * 2d-encode a row of pixels. Consult the CCITT + * documentation for the algorithm. + */ +static int +Fax3Encode2DRow(TIFF* tif, unsigned char* bp, unsigned char* rp, uint32 bits) +{ +#define PIXEL(buf,ix) ((((buf)[(ix)>>3]) >> (7-((ix)&7))) & 1) + uint32 a0 = 0; + uint32 a1 = (PIXEL(bp, 0) != 0 ? 0 : finddiff(bp, 0, bits, 0)); + uint32 b1 = (PIXEL(rp, 0) != 0 ? 0 : finddiff(rp, 0, bits, 0)); + uint32 a2, b2; + + for (;;) { + b2 = finddiff2(rp, b1, bits, PIXEL(rp,b1)); + if (b2 >= a1) { + int32 d = b1 - a1; + if (!(-3 <= d && d <= 3)) { /* horizontal mode */ + a2 = finddiff2(bp, a1, bits, PIXEL(bp,a1)); + putcode(tif, &horizcode); + if (a0+a1 == 0 || PIXEL(bp, a0) == 0) { + putspan(tif, a1-a0, TIFFFaxWhiteCodes); + putspan(tif, a2-a1, TIFFFaxBlackCodes); + } else { + putspan(tif, a1-a0, TIFFFaxBlackCodes); + putspan(tif, a2-a1, TIFFFaxWhiteCodes); + } + a0 = a2; + } else { /* vertical mode */ + putcode(tif, &vcodes[d+3]); + a0 = a1; + } + } else { /* pass mode */ + putcode(tif, &passcode); + a0 = b2; + } + if (a0 >= bits) + break; + a1 = finddiff(bp, a0, bits, PIXEL(bp,a0)); + b1 = finddiff(rp, a0, bits, !PIXEL(bp,a0)); + b1 = finddiff(rp, b1, bits, PIXEL(bp,a0)); + } + return (1); +#undef PIXEL +} + +/* + * Encode a buffer of pixels. + */ +static int +Fax3Encode(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s) +{ + Fax3CodecState* sp = EncoderState(tif); + + (void) s; + while ((long)cc > 0) { + if ((sp->b.mode & FAXMODE_NOEOL) == 0) + Fax3PutEOL(tif); + if (is2DEncoding(sp)) { + if (sp->tag == G3_1D) { + if (!Fax3Encode1DRow(tif, bp, sp->b.rowpixels)) + return (0); + sp->tag = G3_2D; + } else { + if (!Fax3Encode2DRow(tif, bp, sp->refline, + sp->b.rowpixels)) + return (0); + sp->k--; + } + if (sp->k == 0) { + sp->tag = G3_1D; + sp->k = sp->maxk-1; + } else + _TIFFmemcpy(sp->refline, bp, sp->b.rowbytes); + } else { + if (!Fax3Encode1DRow(tif, bp, sp->b.rowpixels)) + return (0); + } + bp += sp->b.rowbytes; + cc -= sp->b.rowbytes; + } + return (1); +} + +static int +Fax3PostEncode(TIFF* tif) +{ + Fax3CodecState* sp = EncoderState(tif); + + if (sp->bit != 8) + Fax3FlushBits(tif, sp); + return (1); +} + +static void +Fax3Close(TIFF* tif) +{ + if ((Fax3State(tif)->mode & FAXMODE_NORTC) == 0) { + Fax3CodecState* sp = EncoderState(tif); + unsigned int code = EOL; + unsigned int length = 12; + int i; + + if (is2DEncoding(sp)) + code = (code<<1) | (sp->tag == G3_1D), length++; + for (i = 0; i < 6; i++) + Fax3PutBits(tif, code, length); + Fax3FlushBits(tif, sp); + } +} + +static void +Fax3Cleanup(TIFF* tif) +{ + Fax3CodecState* sp = DecoderState(tif); + + assert(sp != 0); + + tif->tif_tagmethods.vgetfield = sp->b.vgetparent; + tif->tif_tagmethods.vsetfield = sp->b.vsetparent; + tif->tif_tagmethods.printdir = sp->b.printdir; + + if (sp->runs) + _TIFFfree(sp->runs); + if (sp->refline) + _TIFFfree(sp->refline); + + if (Fax3State(tif)->subaddress) + _TIFFfree(Fax3State(tif)->subaddress); + if (Fax3State(tif)->faxdcs) + _TIFFfree(Fax3State(tif)->faxdcs); + + _TIFFfree(tif->tif_data); + tif->tif_data = NULL; + + _TIFFSetDefaultCompressionState(tif); +} + +#define FIELD_BADFAXLINES (FIELD_CODEC+0) +#define FIELD_CLEANFAXDATA (FIELD_CODEC+1) +#define FIELD_BADFAXRUN (FIELD_CODEC+2) +#define FIELD_RECVPARAMS (FIELD_CODEC+3) +#define FIELD_SUBADDRESS (FIELD_CODEC+4) +#define FIELD_RECVTIME (FIELD_CODEC+5) +#define FIELD_FAXDCS (FIELD_CODEC+6) + +#define FIELD_OPTIONS (FIELD_CODEC+7) + +static const TIFFFieldInfo faxFieldInfo[] = { + { TIFFTAG_FAXMODE, 0, 0, TIFF_ANY, FIELD_PSEUDO, + FALSE, FALSE, "FaxMode" }, + { TIFFTAG_FAXFILLFUNC, 0, 0, TIFF_ANY, FIELD_PSEUDO, + FALSE, FALSE, "FaxFillFunc" }, + { TIFFTAG_BADFAXLINES, 1, 1, TIFF_LONG, FIELD_BADFAXLINES, + TRUE, FALSE, "BadFaxLines" }, + { TIFFTAG_BADFAXLINES, 1, 1, TIFF_SHORT, FIELD_BADFAXLINES, + TRUE, FALSE, "BadFaxLines" }, + { TIFFTAG_CLEANFAXDATA, 1, 1, TIFF_SHORT, FIELD_CLEANFAXDATA, + TRUE, FALSE, "CleanFaxData" }, + { TIFFTAG_CONSECUTIVEBADFAXLINES,1,1, TIFF_LONG, FIELD_BADFAXRUN, + TRUE, FALSE, "ConsecutiveBadFaxLines" }, + { TIFFTAG_CONSECUTIVEBADFAXLINES,1,1, TIFF_SHORT, FIELD_BADFAXRUN, + TRUE, FALSE, "ConsecutiveBadFaxLines" }, + { TIFFTAG_FAXRECVPARAMS, 1, 1, TIFF_LONG, FIELD_RECVPARAMS, + TRUE, FALSE, "FaxRecvParams" }, + { TIFFTAG_FAXSUBADDRESS, -1,-1, TIFF_ASCII, FIELD_SUBADDRESS, + TRUE, FALSE, "FaxSubAddress" }, + { TIFFTAG_FAXRECVTIME, 1, 1, TIFF_LONG, FIELD_RECVTIME, + TRUE, FALSE, "FaxRecvTime" }, + { TIFFTAG_FAXDCS, -1,-1, TIFF_ASCII, FIELD_FAXDCS, + TRUE, FALSE, "FaxDcs" }, +}; +static const TIFFFieldInfo fax3FieldInfo[] = { + { TIFFTAG_GROUP3OPTIONS, 1, 1, TIFF_LONG, FIELD_OPTIONS, + FALSE, FALSE, "Group3Options" }, +}; +static const TIFFFieldInfo fax4FieldInfo[] = { + { TIFFTAG_GROUP4OPTIONS, 1, 1, TIFF_LONG, FIELD_OPTIONS, + FALSE, FALSE, "Group4Options" }, +}; +#define N(a) (sizeof (a) / sizeof (a[0])) + +static int +Fax3VSetField(TIFF* tif, ttag_t tag, va_list ap) +{ + Fax3BaseState* sp = Fax3State(tif); + const TIFFFieldInfo* fip; + + assert(sp != 0); + assert(sp->vsetparent != 0); + + switch (tag) { + case TIFFTAG_FAXMODE: + sp->mode = va_arg(ap, int); + return 1; /* NB: pseudo tag */ + case TIFFTAG_FAXFILLFUNC: + DecoderState(tif)->fill = va_arg(ap, TIFFFaxFillFunc); + return 1; /* NB: pseudo tag */ + case TIFFTAG_GROUP3OPTIONS: + /* XXX: avoid reading options if compression mismatches. */ + if (tif->tif_dir.td_compression == COMPRESSION_CCITTFAX3) + sp->groupoptions = va_arg(ap, uint32); + break; + case TIFFTAG_GROUP4OPTIONS: + /* XXX: avoid reading options if compression mismatches. */ + if (tif->tif_dir.td_compression == COMPRESSION_CCITTFAX4) + sp->groupoptions = va_arg(ap, uint32); + break; + case TIFFTAG_BADFAXLINES: + sp->badfaxlines = va_arg(ap, uint32); + break; + case TIFFTAG_CLEANFAXDATA: + sp->cleanfaxdata = (uint16) va_arg(ap, int); + break; + case TIFFTAG_CONSECUTIVEBADFAXLINES: + sp->badfaxrun = va_arg(ap, uint32); + break; + case TIFFTAG_FAXRECVPARAMS: + sp->recvparams = va_arg(ap, uint32); + break; + case TIFFTAG_FAXSUBADDRESS: + _TIFFsetString(&sp->subaddress, va_arg(ap, char*)); + break; + case TIFFTAG_FAXRECVTIME: + sp->recvtime = va_arg(ap, uint32); + break; + case TIFFTAG_FAXDCS: + _TIFFsetString(&sp->faxdcs, va_arg(ap, char*)); + break; + default: + return (*sp->vsetparent)(tif, tag, ap); + } + + if ((fip = _TIFFFieldWithTag(tif, tag))) + TIFFSetFieldBit(tif, fip->field_bit); + else + return 0; + + tif->tif_flags |= TIFF_DIRTYDIRECT; + return 1; +} + +static int +Fax3VGetField(TIFF* tif, ttag_t tag, va_list ap) +{ + Fax3BaseState* sp = Fax3State(tif); + + assert(sp != 0); + + switch (tag) { + case TIFFTAG_FAXMODE: + *va_arg(ap, int*) = sp->mode; + break; + case TIFFTAG_FAXFILLFUNC: + *va_arg(ap, TIFFFaxFillFunc*) = DecoderState(tif)->fill; + break; + case TIFFTAG_GROUP3OPTIONS: + case TIFFTAG_GROUP4OPTIONS: + *va_arg(ap, uint32*) = sp->groupoptions; + break; + case TIFFTAG_BADFAXLINES: + *va_arg(ap, uint32*) = sp->badfaxlines; + break; + case TIFFTAG_CLEANFAXDATA: + *va_arg(ap, uint16*) = sp->cleanfaxdata; + break; + case TIFFTAG_CONSECUTIVEBADFAXLINES: + *va_arg(ap, uint32*) = sp->badfaxrun; + break; + case TIFFTAG_FAXRECVPARAMS: + *va_arg(ap, uint32*) = sp->recvparams; + break; + case TIFFTAG_FAXSUBADDRESS: + *va_arg(ap, char**) = sp->subaddress; + break; + case TIFFTAG_FAXRECVTIME: + *va_arg(ap, uint32*) = sp->recvtime; + break; + case TIFFTAG_FAXDCS: + *va_arg(ap, char**) = sp->faxdcs; + break; + default: + return (*sp->vgetparent)(tif, tag, ap); + } + return (1); +} + +static void +Fax3PrintDir(TIFF* tif, FILE* fd, long flags) +{ + Fax3BaseState* sp = Fax3State(tif); + + assert(sp != 0); + + (void) flags; + if (TIFFFieldSet(tif,FIELD_OPTIONS)) { + const char* sep = " "; + if (tif->tif_dir.td_compression == COMPRESSION_CCITTFAX4) { + fprintf(fd, " Group 4 Options:"); + if (sp->groupoptions & GROUP4OPT_UNCOMPRESSED) + fprintf(fd, "%suncompressed data", sep); + } else { + + fprintf(fd, " Group 3 Options:"); + if (sp->groupoptions & GROUP3OPT_2DENCODING) + fprintf(fd, "%s2-d encoding", sep), sep = "+"; + if (sp->groupoptions & GROUP3OPT_FILLBITS) + fprintf(fd, "%sEOL padding", sep), sep = "+"; + if (sp->groupoptions & GROUP3OPT_UNCOMPRESSED) + fprintf(fd, "%suncompressed data", sep); + } + fprintf(fd, " (%lu = 0x%lx)\n", + (unsigned long) sp->groupoptions, + (unsigned long) sp->groupoptions); + } + if (TIFFFieldSet(tif,FIELD_CLEANFAXDATA)) { + fprintf(fd, " Fax Data:"); + switch (sp->cleanfaxdata) { + case CLEANFAXDATA_CLEAN: + fprintf(fd, " clean"); + break; + case CLEANFAXDATA_REGENERATED: + fprintf(fd, " receiver regenerated"); + break; + case CLEANFAXDATA_UNCLEAN: + fprintf(fd, " uncorrected errors"); + break; + } + fprintf(fd, " (%u = 0x%x)\n", + sp->cleanfaxdata, sp->cleanfaxdata); + } + if (TIFFFieldSet(tif,FIELD_BADFAXLINES)) + fprintf(fd, " Bad Fax Lines: %lu\n", + (unsigned long) sp->badfaxlines); + if (TIFFFieldSet(tif,FIELD_BADFAXRUN)) + fprintf(fd, " Consecutive Bad Fax Lines: %lu\n", + (unsigned long) sp->badfaxrun); + if (TIFFFieldSet(tif,FIELD_RECVPARAMS)) + fprintf(fd, " Fax Receive Parameters: %08lx\n", + (unsigned long) sp->recvparams); + if (TIFFFieldSet(tif,FIELD_SUBADDRESS)) + fprintf(fd, " Fax SubAddress: %s\n", sp->subaddress); + if (TIFFFieldSet(tif,FIELD_RECVTIME)) + fprintf(fd, " Fax Receive Time: %lu secs\n", + (unsigned long) sp->recvtime); + if (TIFFFieldSet(tif,FIELD_FAXDCS)) + fprintf(fd, " Fax DCS: %s\n", sp->faxdcs); +} + +static int +InitCCITTFax3(TIFF* tif) +{ + Fax3BaseState* sp; + + /* + * Merge codec-specific tag information. + */ + if (!_TIFFMergeFieldInfo(tif, faxFieldInfo, N(faxFieldInfo))) { + TIFFErrorExt(tif->tif_clientdata, "InitCCITTFax3", + "Merging common CCITT Fax codec-specific tags failed"); + return 0; + } + + /* + * Allocate state block so tag methods have storage to record values. + */ + tif->tif_data = (tidata_t) + _TIFFmalloc(sizeof (Fax3CodecState)); + + if (tif->tif_data == NULL) { + TIFFErrorExt(tif->tif_clientdata, "TIFFInitCCITTFax3", + "%s: No space for state block", tif->tif_name); + return (0); + } + + sp = Fax3State(tif); + sp->rw_mode = tif->tif_mode; + + /* + * Override parent get/set field methods. + */ + sp->vgetparent = tif->tif_tagmethods.vgetfield; + tif->tif_tagmethods.vgetfield = Fax3VGetField; /* hook for codec tags */ + sp->vsetparent = tif->tif_tagmethods.vsetfield; + tif->tif_tagmethods.vsetfield = Fax3VSetField; /* hook for codec tags */ + sp->printdir = tif->tif_tagmethods.printdir; + tif->tif_tagmethods.printdir = Fax3PrintDir; /* hook for codec tags */ + sp->groupoptions = 0; + sp->recvparams = 0; + sp->subaddress = NULL; + sp->faxdcs = NULL; + + if (sp->rw_mode == O_RDONLY) /* FIXME: improve for in place update */ + tif->tif_flags |= TIFF_NOBITREV; /* decoder does bit reversal */ + DecoderState(tif)->runs = NULL; + TIFFSetField(tif, TIFFTAG_FAXFILLFUNC, _TIFFFax3fillruns); + EncoderState(tif)->refline = NULL; + + /* + * Install codec methods. + */ + tif->tif_setupdecode = Fax3SetupState; + tif->tif_predecode = Fax3PreDecode; + tif->tif_decoderow = Fax3Decode1D; + tif->tif_decodestrip = Fax3Decode1D; + tif->tif_decodetile = Fax3Decode1D; + tif->tif_setupencode = Fax3SetupState; + tif->tif_preencode = Fax3PreEncode; + tif->tif_postencode = Fax3PostEncode; + tif->tif_encoderow = Fax3Encode; + tif->tif_encodestrip = Fax3Encode; + tif->tif_encodetile = Fax3Encode; + tif->tif_close = Fax3Close; + tif->tif_cleanup = Fax3Cleanup; + + return (1); +} + +int +TIFFInitCCITTFax3(TIFF* tif, int scheme) +{ + (void) scheme; + if (InitCCITTFax3(tif)) { + /* + * Merge codec-specific tag information. + */ + if (!_TIFFMergeFieldInfo(tif, fax3FieldInfo, N(fax3FieldInfo))) { + TIFFErrorExt(tif->tif_clientdata, "TIFFInitCCITTFax3", + "Merging CCITT Fax 3 codec-specific tags failed"); + return 0; + } + + /* + * The default format is Class/F-style w/o RTC. + */ + return TIFFSetField(tif, TIFFTAG_FAXMODE, FAXMODE_CLASSF); + } else + return 01; +} + +/* + * CCITT Group 4 (T.6) Facsimile-compatible + * Compression Scheme Support. + */ + +#define SWAP(t,a,b) { t x; x = (a); (a) = (b); (b) = x; } +/* + * Decode the requested amount of G4-encoded data. + */ +static int +Fax4Decode(TIFF* tif, tidata_t buf, tsize_t occ, tsample_t s) +{ + DECLARE_STATE_2D(tif, sp, "Fax4Decode"); + + (void) s; + CACHE_STATE(tif, sp); + while ((long)occ > 0) { + a0 = 0; + RunLength = 0; + pa = thisrun = sp->curruns; + pb = sp->refruns; + b1 = *pb++; +#ifdef FAX3_DEBUG + printf("\nBitAcc=%08X, BitsAvail = %d\n", BitAcc, BitsAvail); + printf("-------------------- %d\n", tif->tif_row); + fflush(stdout); +#endif + EXPAND2D(EOFG4); + if (EOLcnt) + goto EOFG4; + (*sp->fill)(buf, thisrun, pa, lastx); + SETVALUE(0); /* imaginary change for reference */ + SWAP(uint32*, sp->curruns, sp->refruns); + buf += sp->b.rowbytes; + occ -= sp->b.rowbytes; + sp->line++; + continue; + EOFG4: + NeedBits16( 13, BADG4 ); + BADG4: +#ifdef FAX3_DEBUG + if( GetBits(13) != 0x1001 ) + fputs( "Bad EOFB\n", stderr ); +#endif + ClrBits( 13 ); + (*sp->fill)(buf, thisrun, pa, lastx); + UNCACHE_STATE(tif, sp); + return ( sp->line ? 1 : -1); /* don't error on badly-terminated strips */ + } + UNCACHE_STATE(tif, sp); + return (1); +} +#undef SWAP + +/* + * Encode the requested amount of data. + */ +static int +Fax4Encode(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s) +{ + Fax3CodecState *sp = EncoderState(tif); + + (void) s; + while ((long)cc > 0) { + if (!Fax3Encode2DRow(tif, bp, sp->refline, sp->b.rowpixels)) + return (0); + _TIFFmemcpy(sp->refline, bp, sp->b.rowbytes); + bp += sp->b.rowbytes; + cc -= sp->b.rowbytes; + } + return (1); +} + +static int +Fax4PostEncode(TIFF* tif) +{ + Fax3CodecState *sp = EncoderState(tif); + + /* terminate strip w/ EOFB */ + Fax3PutBits(tif, EOL, 12); + Fax3PutBits(tif, EOL, 12); + if (sp->bit != 8) + Fax3FlushBits(tif, sp); + return (1); +} + +int +TIFFInitCCITTFax4(TIFF* tif, int scheme) +{ + (void) scheme; + if (InitCCITTFax3(tif)) { /* reuse G3 support */ + /* + * Merge codec-specific tag information. + */ + if (!_TIFFMergeFieldInfo(tif, fax4FieldInfo, N(fax4FieldInfo))) { + TIFFErrorExt(tif->tif_clientdata, "TIFFInitCCITTFax4", + "Merging CCITT Fax 4 codec-specific tags failed"); + return 0; + } + + tif->tif_decoderow = Fax4Decode; + tif->tif_decodestrip = Fax4Decode; + tif->tif_decodetile = Fax4Decode; + tif->tif_encoderow = Fax4Encode; + tif->tif_encodestrip = Fax4Encode; + tif->tif_encodetile = Fax4Encode; + tif->tif_postencode = Fax4PostEncode; + /* + * Suppress RTC at the end of each strip. + */ + return TIFFSetField(tif, TIFFTAG_FAXMODE, FAXMODE_NORTC); + } else + return (0); +} + +/* + * CCITT Group 3 1-D Modified Huffman RLE Compression Support. + * (Compression algorithms 2 and 32771) + */ + +/* + * Decode the requested amount of RLE-encoded data. + */ +static int +Fax3DecodeRLE(TIFF* tif, tidata_t buf, tsize_t occ, tsample_t s) +{ + DECLARE_STATE(tif, sp, "Fax3DecodeRLE"); + int mode = sp->b.mode; + + (void) s; + CACHE_STATE(tif, sp); + thisrun = sp->curruns; + while ((long)occ > 0) { + a0 = 0; + RunLength = 0; + pa = thisrun; +#ifdef FAX3_DEBUG + printf("\nBitAcc=%08X, BitsAvail = %d\n", BitAcc, BitsAvail); + printf("-------------------- %d\n", tif->tif_row); + fflush(stdout); +#endif + EXPAND1D(EOFRLE); + (*sp->fill)(buf, thisrun, pa, lastx); + /* + * Cleanup at the end of the row. + */ + if (mode & FAXMODE_BYTEALIGN) { + int n = BitsAvail - (BitsAvail &~ 7); + ClrBits(n); + } else if (mode & FAXMODE_WORDALIGN) { + int n = BitsAvail - (BitsAvail &~ 15); + ClrBits(n); + if (BitsAvail == 0 && !isAligned(cp, uint16)) + cp++; + } + buf += sp->b.rowbytes; + occ -= sp->b.rowbytes; + sp->line++; + continue; + EOFRLE: /* premature EOF */ + (*sp->fill)(buf, thisrun, pa, lastx); + UNCACHE_STATE(tif, sp); + return (-1); + } + UNCACHE_STATE(tif, sp); + return (1); +} + +int +TIFFInitCCITTRLE(TIFF* tif, int scheme) +{ + (void) scheme; + if (InitCCITTFax3(tif)) { /* reuse G3 support */ + tif->tif_decoderow = Fax3DecodeRLE; + tif->tif_decodestrip = Fax3DecodeRLE; + tif->tif_decodetile = Fax3DecodeRLE; + /* + * Suppress RTC+EOLs when encoding and byte-align data. + */ + return TIFFSetField(tif, TIFFTAG_FAXMODE, + FAXMODE_NORTC|FAXMODE_NOEOL|FAXMODE_BYTEALIGN); + } else + return (0); +} + +int +TIFFInitCCITTRLEW(TIFF* tif, int scheme) +{ + (void) scheme; + if (InitCCITTFax3(tif)) { /* reuse G3 support */ + tif->tif_decoderow = Fax3DecodeRLE; + tif->tif_decodestrip = Fax3DecodeRLE; + tif->tif_decodetile = Fax3DecodeRLE; + /* + * Suppress RTC+EOLs when encoding and word-align data. + */ + return TIFFSetField(tif, TIFFTAG_FAXMODE, + FAXMODE_NORTC|FAXMODE_NOEOL|FAXMODE_WORDALIGN); + } else + return (0); +} +#endif /* CCITT_SUPPORT */ + +/* vim: set ts=8 sts=8 sw=8 noet: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tif_fax3.h b/reactos/dll/3rdparty/libtiff/tif_fax3.h new file mode 100644 index 00000000000..40718bcfa71 --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tif_fax3.h @@ -0,0 +1,532 @@ +/* $Id: tif_fax3.h,v 1.5.2.1 2010-06-08 18:50:42 bfriesen Exp $ */ + +/* + * Copyright (c) 1990-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _FAX3_ +#define _FAX3_ +/* + * TIFF Library. + * + * CCITT Group 3 (T.4) and Group 4 (T.6) Decompression Support. + * + * Decoder support is derived, with permission, from the code + * in Frank Cringle's viewfax program; + * Copyright (C) 1990, 1995 Frank D. Cringle. + */ +#include "tiff.h" + +/* + * To override the default routine used to image decoded + * spans one can use the pseduo tag TIFFTAG_FAXFILLFUNC. + * The routine must have the type signature given below; + * for example: + * + * fillruns(unsigned char* buf, uint32* runs, uint32* erun, uint32 lastx) + * + * where buf is place to set the bits, runs is the array of b&w run + * lengths (white then black), erun is the last run in the array, and + * lastx is the width of the row in pixels. Fill routines can assume + * the run array has room for at least lastx runs and can overwrite + * data in the run array as needed (e.g. to append zero runs to bring + * the count up to a nice multiple). + */ +typedef void (*TIFFFaxFillFunc)(unsigned char*, uint32*, uint32*, uint32); + +/* + * The default run filler; made external for other decoders. + */ +#if defined(__cplusplus) +extern "C" { +#endif +extern void _TIFFFax3fillruns(unsigned char*, uint32*, uint32*, uint32); +#if defined(__cplusplus) +} +#endif + + +/* finite state machine codes */ +#define S_Null 0 +#define S_Pass 1 +#define S_Horiz 2 +#define S_V0 3 +#define S_VR 4 +#define S_VL 5 +#define S_Ext 6 +#define S_TermW 7 +#define S_TermB 8 +#define S_MakeUpW 9 +#define S_MakeUpB 10 +#define S_MakeUp 11 +#define S_EOL 12 + +typedef struct { /* state table entry */ + unsigned char State; /* see above */ + unsigned char Width; /* width of code in bits */ + uint32 Param; /* unsigned 32-bit run length in bits */ +} TIFFFaxTabEnt; + +extern const TIFFFaxTabEnt TIFFFaxMainTable[]; +extern const TIFFFaxTabEnt TIFFFaxWhiteTable[]; +extern const TIFFFaxTabEnt TIFFFaxBlackTable[]; + +/* + * The following macros define the majority of the G3/G4 decoder + * algorithm using the state tables defined elsewhere. To build + * a decoder you need some setup code and some glue code. Note + * that you may also need/want to change the way the NeedBits* + * macros get input data if, for example, you know the data to be + * decoded is properly aligned and oriented (doing so before running + * the decoder can be a big performance win). + * + * Consult the decoder in the TIFF library for an idea of what you + * need to define and setup to make use of these definitions. + * + * NB: to enable a debugging version of these macros define FAX3_DEBUG + * before including this file. Trace output goes to stdout. + */ + +#ifndef EndOfData +#define EndOfData() (cp >= ep) +#endif +/* + * Need <=8 or <=16 bits of input data. Unlike viewfax we + * cannot use/assume a word-aligned, properly bit swizzled + * input data set because data may come from an arbitrarily + * aligned, read-only source such as a memory-mapped file. + * Note also that the viewfax decoder does not check for + * running off the end of the input data buffer. This is + * possible for G3-encoded data because it prescans the input + * data to count EOL markers, but can cause problems for G4 + * data. In any event, we don't prescan and must watch for + * running out of data since we can't permit the library to + * scan past the end of the input data buffer. + * + * Finally, note that we must handle remaindered data at the end + * of a strip specially. The coder asks for a fixed number of + * bits when scanning for the next code. This may be more bits + * than are actually present in the data stream. If we appear + * to run out of data but still have some number of valid bits + * remaining then we makeup the requested amount with zeros and + * return successfully. If the returned data is incorrect then + * we should be called again and get a premature EOF error; + * otherwise we should get the right answer. + */ +#ifndef NeedBits8 +#define NeedBits8(n,eoflab) do { \ + if (BitsAvail < (n)) { \ + if (EndOfData()) { \ + if (BitsAvail == 0) /* no valid bits */ \ + goto eoflab; \ + BitsAvail = (n); /* pad with zeros */ \ + } else { \ + BitAcc |= ((uint32) bitmap[*cp++])<>= (n); \ +} while (0) + +#ifdef FAX3_DEBUG +static const char* StateNames[] = { + "Null ", + "Pass ", + "Horiz ", + "V0 ", + "VR ", + "VL ", + "Ext ", + "TermW ", + "TermB ", + "MakeUpW", + "MakeUpB", + "MakeUp ", + "EOL ", +}; +#define DEBUG_SHOW putchar(BitAcc & (1 << t) ? '1' : '0') +#define LOOKUP8(wid,tab,eoflab) do { \ + int t; \ + NeedBits8(wid,eoflab); \ + TabEnt = tab + GetBits(wid); \ + printf("%08lX/%d: %s%5d\t", (long) BitAcc, BitsAvail, \ + StateNames[TabEnt->State], TabEnt->Param); \ + for (t = 0; t < TabEnt->Width; t++) \ + DEBUG_SHOW; \ + putchar('\n'); \ + fflush(stdout); \ + ClrBits(TabEnt->Width); \ +} while (0) +#define LOOKUP16(wid,tab,eoflab) do { \ + int t; \ + NeedBits16(wid,eoflab); \ + TabEnt = tab + GetBits(wid); \ + printf("%08lX/%d: %s%5d\t", (long) BitAcc, BitsAvail, \ + StateNames[TabEnt->State], TabEnt->Param); \ + for (t = 0; t < TabEnt->Width; t++) \ + DEBUG_SHOW; \ + putchar('\n'); \ + fflush(stdout); \ + ClrBits(TabEnt->Width); \ +} while (0) + +#define SETVALUE(x) do { \ + *pa++ = RunLength + (x); \ + printf("SETVALUE: %d\t%d\n", RunLength + (x), a0); \ + a0 += x; \ + RunLength = 0; \ +} while (0) +#else +#define LOOKUP8(wid,tab,eoflab) do { \ + NeedBits8(wid,eoflab); \ + TabEnt = tab + GetBits(wid); \ + ClrBits(TabEnt->Width); \ +} while (0) +#define LOOKUP16(wid,tab,eoflab) do { \ + NeedBits16(wid,eoflab); \ + TabEnt = tab + GetBits(wid); \ + ClrBits(TabEnt->Width); \ +} while (0) + +/* + * Append a run to the run length array for the + * current row and reset decoding state. + */ +#define SETVALUE(x) do { \ + *pa++ = RunLength + (x); \ + a0 += (x); \ + RunLength = 0; \ +} while (0) +#endif + +/* + * Synchronize input decoding at the start of each + * row by scanning for an EOL (if appropriate) and + * skipping any trash data that might be present + * after a decoding error. Note that the decoding + * done elsewhere that recognizes an EOL only consumes + * 11 consecutive zero bits. This means that if EOLcnt + * is non-zero then we still need to scan for the final flag + * bit that is part of the EOL code. + */ +#define SYNC_EOL(eoflab) do { \ + if (EOLcnt == 0) { \ + for (;;) { \ + NeedBits16(11,eoflab); \ + if (GetBits(11) == 0) \ + break; \ + ClrBits(1); \ + } \ + } \ + for (;;) { \ + NeedBits8(8,eoflab); \ + if (GetBits(8)) \ + break; \ + ClrBits(8); \ + } \ + while (GetBits(1) == 0) \ + ClrBits(1); \ + ClrBits(1); /* EOL bit */ \ + EOLcnt = 0; /* reset EOL counter/flag */ \ +} while (0) + +/* + * Cleanup the array of runs after decoding a row. + * We adjust final runs to insure the user buffer is not + * overwritten and/or undecoded area is white filled. + */ +#define CLEANUP_RUNS() do { \ + if (RunLength) \ + SETVALUE(0); \ + if (a0 != lastx) { \ + badlength(a0, lastx); \ + while (a0 > lastx && pa > thisrun) \ + a0 -= *--pa; \ + if (a0 < lastx) { \ + if (a0 < 0) \ + a0 = 0; \ + if ((pa-thisrun)&1) \ + SETVALUE(0); \ + SETVALUE(lastx - a0); \ + } else if (a0 > lastx) { \ + SETVALUE(lastx); \ + SETVALUE(0); \ + } \ + } \ +} while (0) + +/* + * Decode a line of 1D-encoded data. + * + * The line expanders are written as macros so that they can be reused + * but still have direct access to the local variables of the "calling" + * function. + * + * Note that unlike the original version we have to explicitly test for + * a0 >= lastx after each black/white run is decoded. This is because + * the original code depended on the input data being zero-padded to + * insure the decoder recognized an EOL before running out of data. + */ +#define EXPAND1D(eoflab) do { \ + for (;;) { \ + for (;;) { \ + LOOKUP16(12, TIFFFaxWhiteTable, eof1d); \ + switch (TabEnt->State) { \ + case S_EOL: \ + EOLcnt = 1; \ + goto done1d; \ + case S_TermW: \ + SETVALUE(TabEnt->Param); \ + goto doneWhite1d; \ + case S_MakeUpW: \ + case S_MakeUp: \ + a0 += TabEnt->Param; \ + RunLength += TabEnt->Param; \ + break; \ + default: \ + unexpected("WhiteTable", a0); \ + goto done1d; \ + } \ + } \ + doneWhite1d: \ + if (a0 >= lastx) \ + goto done1d; \ + for (;;) { \ + LOOKUP16(13, TIFFFaxBlackTable, eof1d); \ + switch (TabEnt->State) { \ + case S_EOL: \ + EOLcnt = 1; \ + goto done1d; \ + case S_TermB: \ + SETVALUE(TabEnt->Param); \ + goto doneBlack1d; \ + case S_MakeUpB: \ + case S_MakeUp: \ + a0 += TabEnt->Param; \ + RunLength += TabEnt->Param; \ + break; \ + default: \ + unexpected("BlackTable", a0); \ + goto done1d; \ + } \ + } \ + doneBlack1d: \ + if (a0 >= lastx) \ + goto done1d; \ + if( *(pa-1) == 0 && *(pa-2) == 0 ) \ + pa -= 2; \ + } \ +eof1d: \ + prematureEOF(a0); \ + CLEANUP_RUNS(); \ + goto eoflab; \ +done1d: \ + CLEANUP_RUNS(); \ +} while (0) + +/* + * Update the value of b1 using the array + * of runs for the reference line. + */ +#define CHECK_b1 do { \ + if (pa != thisrun) while (b1 <= a0 && b1 < lastx) { \ + b1 += pb[0] + pb[1]; \ + pb += 2; \ + } \ +} while (0) + +/* + * Expand a row of 2D-encoded data. + */ +#define EXPAND2D(eoflab) do { \ + while (a0 < lastx) { \ + LOOKUP8(7, TIFFFaxMainTable, eof2d); \ + switch (TabEnt->State) { \ + case S_Pass: \ + CHECK_b1; \ + b1 += *pb++; \ + RunLength += b1 - a0; \ + a0 = b1; \ + b1 += *pb++; \ + break; \ + case S_Horiz: \ + if ((pa-thisrun)&1) { \ + for (;;) { /* black first */ \ + LOOKUP16(13, TIFFFaxBlackTable, eof2d); \ + switch (TabEnt->State) { \ + case S_TermB: \ + SETVALUE(TabEnt->Param); \ + goto doneWhite2da; \ + case S_MakeUpB: \ + case S_MakeUp: \ + a0 += TabEnt->Param; \ + RunLength += TabEnt->Param; \ + break; \ + default: \ + goto badBlack2d; \ + } \ + } \ + doneWhite2da:; \ + for (;;) { /* then white */ \ + LOOKUP16(12, TIFFFaxWhiteTable, eof2d); \ + switch (TabEnt->State) { \ + case S_TermW: \ + SETVALUE(TabEnt->Param); \ + goto doneBlack2da; \ + case S_MakeUpW: \ + case S_MakeUp: \ + a0 += TabEnt->Param; \ + RunLength += TabEnt->Param; \ + break; \ + default: \ + goto badWhite2d; \ + } \ + } \ + doneBlack2da:; \ + } else { \ + for (;;) { /* white first */ \ + LOOKUP16(12, TIFFFaxWhiteTable, eof2d); \ + switch (TabEnt->State) { \ + case S_TermW: \ + SETVALUE(TabEnt->Param); \ + goto doneWhite2db; \ + case S_MakeUpW: \ + case S_MakeUp: \ + a0 += TabEnt->Param; \ + RunLength += TabEnt->Param; \ + break; \ + default: \ + goto badWhite2d; \ + } \ + } \ + doneWhite2db:; \ + for (;;) { /* then black */ \ + LOOKUP16(13, TIFFFaxBlackTable, eof2d); \ + switch (TabEnt->State) { \ + case S_TermB: \ + SETVALUE(TabEnt->Param); \ + goto doneBlack2db; \ + case S_MakeUpB: \ + case S_MakeUp: \ + a0 += TabEnt->Param; \ + RunLength += TabEnt->Param; \ + break; \ + default: \ + goto badBlack2d; \ + } \ + } \ + doneBlack2db:; \ + } \ + CHECK_b1; \ + break; \ + case S_V0: \ + CHECK_b1; \ + SETVALUE(b1 - a0); \ + b1 += *pb++; \ + break; \ + case S_VR: \ + CHECK_b1; \ + SETVALUE(b1 - a0 + TabEnt->Param); \ + b1 += *pb++; \ + break; \ + case S_VL: \ + CHECK_b1; \ + SETVALUE(b1 - a0 - TabEnt->Param); \ + b1 -= *--pb; \ + break; \ + case S_Ext: \ + *pa++ = lastx - a0; \ + extension(a0); \ + goto eol2d; \ + case S_EOL: \ + *pa++ = lastx - a0; \ + NeedBits8(4,eof2d); \ + if (GetBits(4)) \ + unexpected("EOL", a0); \ + ClrBits(4); \ + EOLcnt = 1; \ + goto eol2d; \ + default: \ + badMain2d: \ + unexpected("MainTable", a0); \ + goto eol2d; \ + badBlack2d: \ + unexpected("BlackTable", a0); \ + goto eol2d; \ + badWhite2d: \ + unexpected("WhiteTable", a0); \ + goto eol2d; \ + eof2d: \ + prematureEOF(a0); \ + CLEANUP_RUNS(); \ + goto eoflab; \ + } \ + } \ + if (RunLength) { \ + if (RunLength + a0 < lastx) { \ + /* expect a final V0 */ \ + NeedBits8(1,eof2d); \ + if (!GetBits(1)) \ + goto badMain2d; \ + ClrBits(1); \ + } \ + SETVALUE(0); \ + } \ +eol2d: \ + CLEANUP_RUNS(); \ +} while (0) +#endif /* _FAX3_ */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tif_fax3sm.c b/reactos/dll/3rdparty/libtiff/tif_fax3sm.c new file mode 100644 index 00000000000..822191ecf4d --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tif_fax3sm.c @@ -0,0 +1,1260 @@ +/* WARNING, this file was automatically generated by the + mkg3states program */ +#include "tiff.h" +#include "tif_fax3.h" + const TIFFFaxTabEnt TIFFFaxMainTable[128] = { +{12,7,0},{3,1,0},{5,3,1},{3,1,0},{2,3,0},{3,1,0},{4,3,1},{3,1,0},{1,4,0},{3,1,0}, +{5,3,1},{3,1,0},{2,3,0},{3,1,0},{4,3,1},{3,1,0},{5,6,2},{3,1,0},{5,3,1},{3,1,0}, +{2,3,0},{3,1,0},{4,3,1},{3,1,0},{1,4,0},{3,1,0},{5,3,1},{3,1,0},{2,3,0},{3,1,0}, +{4,3,1},{3,1,0},{5,7,3},{3,1,0},{5,3,1},{3,1,0},{2,3,0},{3,1,0},{4,3,1},{3,1,0}, +{1,4,0},{3,1,0},{5,3,1},{3,1,0},{2,3,0},{3,1,0},{4,3,1},{3,1,0},{4,6,2},{3,1,0}, +{5,3,1},{3,1,0},{2,3,0},{3,1,0},{4,3,1},{3,1,0},{1,4,0},{3,1,0},{5,3,1},{3,1,0}, +{2,3,0},{3,1,0},{4,3,1},{3,1,0},{6,7,0},{3,1,0},{5,3,1},{3,1,0},{2,3,0},{3,1,0}, +{4,3,1},{3,1,0},{1,4,0},{3,1,0},{5,3,1},{3,1,0},{2,3,0},{3,1,0},{4,3,1},{3,1,0}, +{5,6,2},{3,1,0},{5,3,1},{3,1,0},{2,3,0},{3,1,0},{4,3,1},{3,1,0},{1,4,0},{3,1,0}, +{5,3,1},{3,1,0},{2,3,0},{3,1,0},{4,3,1},{3,1,0},{4,7,3},{3,1,0},{5,3,1},{3,1,0}, +{2,3,0},{3,1,0},{4,3,1},{3,1,0},{1,4,0},{3,1,0},{5,3,1},{3,1,0},{2,3,0},{3,1,0}, +{4,3,1},{3,1,0},{4,6,2},{3,1,0},{5,3,1},{3,1,0},{2,3,0},{3,1,0},{4,3,1},{3,1,0}, +{1,4,0},{3,1,0},{5,3,1},{3,1,0},{2,3,0},{3,1,0},{4,3,1},{3,1,0} +}; + const TIFFFaxTabEnt TIFFFaxWhiteTable[4096] = { +{12,11,0},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128}, +{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5}, +{7,8,39},{7,6,16},{9,8,576},{7,4,6},{7,7,19},{7,5,8},{7,8,55},{9,5,64},{7,5,10},{7,4,4}, +{7,4,2},{7,4,7},{7,8,45},{7,4,3},{7,5,11},{7,4,5},{7,8,53},{7,5,9},{9,8,448},{7,4,6}, +{7,8,35},{9,5,128},{7,8,51},{7,6,15},{7,8,63},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3}, +{9,9,1472},{7,4,5},{7,8,43},{7,6,17},{9,9,1216},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64}, +{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,29},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9}, +{9,6,1664},{7,4,6},{7,8,33},{9,5,128},{7,8,49},{7,6,14},{7,8,61},{7,4,4},{7,4,2},{7,4,7}, +{7,8,47},{7,4,3},{7,8,59},{7,4,5},{7,8,41},{7,6,16},{9,9,960},{7,4,6},{7,8,31},{7,5,8}, +{7,8,57},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5}, +{7,7,26},{7,5,9},{9,9,704},{7,4,6},{7,8,37},{9,5,128},{7,7,25},{7,6,15},{9,8,320},{7,4,4}, +{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6}, +{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{11,11,1792},{7,4,3}, +{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14}, +{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,40},{7,6,16}, +{9,9,832},{7,4,6},{7,7,19},{7,5,8},{7,8,56},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7}, +{7,8,46},{7,4,3},{7,5,11},{7,4,5},{7,8,54},{7,5,9},{9,8,512},{7,4,6},{7,8,36},{9,5,128}, +{7,8,52},{7,6,15},{7,8,0},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1600},{7,4,5}, +{7,8,44},{7,6,17},{9,9,1344},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4}, +{7,4,2},{7,4,7},{7,8,30},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6}, +{7,8,34},{9,5,128},{7,8,50},{7,6,14},{7,8,62},{7,4,4},{7,4,2},{7,4,7},{7,8,48},{7,4,3}, +{7,8,60},{7,4,5},{7,8,42},{7,6,16},{9,9,1088},{7,4,6},{7,8,32},{7,5,8},{7,8,58},{9,5,64}, +{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9}, +{9,8,640},{7,4,6},{7,8,38},{9,5,128},{7,7,25},{7,6,15},{9,8,384},{7,4,4},{7,4,2},{7,4,7}, +{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8}, +{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{0,0,0},{7,4,3},{7,5,11},{7,4,5}, +{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4}, +{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,39},{7,6,16},{9,8,576},{7,4,6}, +{7,7,19},{7,5,8},{7,8,55},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,45},{7,4,3}, +{7,5,11},{7,4,5},{7,8,53},{7,5,9},{9,8,448},{7,4,6},{7,8,35},{9,5,128},{7,8,51},{7,6,15}, +{7,8,63},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1536},{7,4,5},{7,8,43},{7,6,17}, +{9,9,1280},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7}, +{7,8,29},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,33},{9,5,128}, +{7,8,49},{7,6,14},{7,8,61},{7,4,4},{7,4,2},{7,4,7},{7,8,47},{7,4,3},{7,8,59},{7,4,5}, +{7,8,41},{7,6,16},{9,9,1024},{7,4,6},{7,8,31},{7,5,8},{7,8,57},{9,5,64},{7,5,10},{7,4,4}, +{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,9,768},{7,4,6}, +{7,8,37},{9,5,128},{7,7,25},{7,6,15},{9,8,320},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3}, +{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64}, +{7,5,10},{7,4,4},{7,4,2},{7,4,7},{11,11,1856},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9}, +{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7}, +{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,40},{7,6,16},{9,9,896},{7,4,6},{7,7,19},{7,5,8}, +{7,8,56},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,46},{7,4,3},{7,5,11},{7,4,5}, +{7,8,54},{7,5,9},{9,8,512},{7,4,6},{7,8,36},{9,5,128},{7,8,52},{7,6,15},{7,8,0},{7,4,4}, +{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1728},{7,4,5},{7,8,44},{7,6,17},{9,9,1408},{7,4,6}, +{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,30},{7,4,3}, +{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,34},{9,5,128},{7,8,50},{7,6,14}, +{7,8,62},{7,4,4},{7,4,2},{7,4,7},{7,8,48},{7,4,3},{7,8,60},{7,4,5},{7,8,42},{7,6,16}, +{9,9,1152},{7,4,6},{7,8,32},{7,5,8},{7,8,58},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7}, +{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,8,640},{7,4,6},{7,8,38},{9,5,128}, +{7,7,25},{7,6,15},{9,8,384},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5}, +{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4}, +{7,4,2},{7,4,7},{0,0,0},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6}, +{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3}, +{7,7,27},{7,4,5},{7,8,39},{7,6,16},{9,8,576},{7,4,6},{7,7,19},{7,5,8},{7,8,55},{9,5,64}, +{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,45},{7,4,3},{7,5,11},{7,4,5},{7,8,53},{7,5,9}, +{9,8,448},{7,4,6},{7,8,35},{9,5,128},{7,8,51},{7,6,15},{7,8,63},{7,4,4},{7,4,2},{7,4,7}, +{7,6,13},{7,4,3},{9,9,1472},{7,4,5},{7,8,43},{7,6,17},{9,9,1216},{7,4,6},{7,6,1},{7,5,8}, +{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,29},{7,4,3},{7,5,11},{7,4,5}, +{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,33},{9,5,128},{7,8,49},{7,6,14},{7,8,61},{7,4,4}, +{7,4,2},{7,4,7},{7,8,47},{7,4,3},{7,8,59},{7,4,5},{7,8,41},{7,6,16},{9,9,960},{7,4,6}, +{7,8,31},{7,5,8},{7,8,57},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3}, +{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,9,704},{7,4,6},{7,8,37},{9,5,128},{7,7,25},{7,6,15}, +{9,8,320},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17}, +{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7}, +{11,12,2112},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128}, +{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5}, +{7,8,40},{7,6,16},{9,9,832},{7,4,6},{7,7,19},{7,5,8},{7,8,56},{9,5,64},{7,5,10},{7,4,4}, +{7,4,2},{7,4,7},{7,8,46},{7,4,3},{7,5,11},{7,4,5},{7,8,54},{7,5,9},{9,8,512},{7,4,6}, +{7,8,36},{9,5,128},{7,8,52},{7,6,15},{7,8,0},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3}, +{9,9,1600},{7,4,5},{7,8,44},{7,6,17},{9,9,1344},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64}, +{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,30},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9}, +{9,6,1664},{7,4,6},{7,8,34},{9,5,128},{7,8,50},{7,6,14},{7,8,62},{7,4,4},{7,4,2},{7,4,7}, +{7,8,48},{7,4,3},{7,8,60},{7,4,5},{7,8,42},{7,6,16},{9,9,1088},{7,4,6},{7,8,32},{7,5,8}, +{7,8,58},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5}, +{7,7,26},{7,5,9},{9,8,640},{7,4,6},{7,8,38},{9,5,128},{7,7,25},{7,6,15},{9,8,384},{7,4,4}, +{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6}, +{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{0,0,0},{7,4,3}, +{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14}, +{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,39},{7,6,16}, +{9,8,576},{7,4,6},{7,7,19},{7,5,8},{7,8,55},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7}, +{7,8,45},{7,4,3},{7,5,11},{7,4,5},{7,8,53},{7,5,9},{9,8,448},{7,4,6},{7,8,35},{9,5,128}, +{7,8,51},{7,6,15},{7,8,63},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1536},{7,4,5}, +{7,8,43},{7,6,17},{9,9,1280},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4}, +{7,4,2},{7,4,7},{7,8,29},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6}, +{7,8,33},{9,5,128},{7,8,49},{7,6,14},{7,8,61},{7,4,4},{7,4,2},{7,4,7},{7,8,47},{7,4,3}, +{7,8,59},{7,4,5},{7,8,41},{7,6,16},{9,9,1024},{7,4,6},{7,8,31},{7,5,8},{7,8,57},{9,5,64}, +{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9}, +{9,9,768},{7,4,6},{7,8,37},{9,5,128},{7,7,25},{7,6,15},{9,8,320},{7,4,4},{7,4,2},{7,4,7}, +{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8}, +{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{11,12,2368},{7,4,3},{7,5,11},{7,4,5}, +{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4}, +{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,40},{7,6,16},{9,9,896},{7,4,6}, +{7,7,19},{7,5,8},{7,8,56},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,46},{7,4,3}, +{7,5,11},{7,4,5},{7,8,54},{7,5,9},{9,8,512},{7,4,6},{7,8,36},{9,5,128},{7,8,52},{7,6,15}, +{7,8,0},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1728},{7,4,5},{7,8,44},{7,6,17}, +{9,9,1408},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7}, +{7,8,30},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,34},{9,5,128}, +{7,8,50},{7,6,14},{7,8,62},{7,4,4},{7,4,2},{7,4,7},{7,8,48},{7,4,3},{7,8,60},{7,4,5}, +{7,8,42},{7,6,16},{9,9,1152},{7,4,6},{7,8,32},{7,5,8},{7,8,58},{9,5,64},{7,5,10},{7,4,4}, +{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,8,640},{7,4,6}, +{7,8,38},{9,5,128},{7,7,25},{7,6,15},{9,8,384},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3}, +{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64}, +{7,5,10},{7,4,4},{7,4,2},{7,4,7},{0,0,0},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9}, +{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7}, +{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,39},{7,6,16},{9,8,576},{7,4,6},{7,7,19},{7,5,8}, +{7,8,55},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,45},{7,4,3},{7,5,11},{7,4,5}, +{7,8,53},{7,5,9},{9,8,448},{7,4,6},{7,8,35},{9,5,128},{7,8,51},{7,6,15},{7,8,63},{7,4,4}, +{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1472},{7,4,5},{7,8,43},{7,6,17},{9,9,1216},{7,4,6}, +{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,29},{7,4,3}, +{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,33},{9,5,128},{7,8,49},{7,6,14}, +{7,8,61},{7,4,4},{7,4,2},{7,4,7},{7,8,47},{7,4,3},{7,8,59},{7,4,5},{7,8,41},{7,6,16}, +{9,9,960},{7,4,6},{7,8,31},{7,5,8},{7,8,57},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7}, +{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,9,704},{7,4,6},{7,8,37},{9,5,128}, +{7,7,25},{7,6,15},{9,8,320},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5}, +{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4}, +{7,4,2},{7,4,7},{11,12,1984},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6}, +{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3}, +{7,7,27},{7,4,5},{7,8,40},{7,6,16},{9,9,832},{7,4,6},{7,7,19},{7,5,8},{7,8,56},{9,5,64}, +{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,46},{7,4,3},{7,5,11},{7,4,5},{7,8,54},{7,5,9}, +{9,8,512},{7,4,6},{7,8,36},{9,5,128},{7,8,52},{7,6,15},{7,8,0},{7,4,4},{7,4,2},{7,4,7}, +{7,6,13},{7,4,3},{9,9,1600},{7,4,5},{7,8,44},{7,6,17},{9,9,1344},{7,4,6},{7,6,1},{7,5,8}, +{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,30},{7,4,3},{7,5,11},{7,4,5}, +{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,34},{9,5,128},{7,8,50},{7,6,14},{7,8,62},{7,4,4}, +{7,4,2},{7,4,7},{7,8,48},{7,4,3},{7,8,60},{7,4,5},{7,8,42},{7,6,16},{9,9,1088},{7,4,6}, +{7,8,32},{7,5,8},{7,8,58},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3}, +{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,8,640},{7,4,6},{7,8,38},{9,5,128},{7,7,25},{7,6,15}, +{9,8,384},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17}, +{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7}, +{0,0,0},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128}, +{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5}, +{7,8,39},{7,6,16},{9,8,576},{7,4,6},{7,7,19},{7,5,8},{7,8,55},{9,5,64},{7,5,10},{7,4,4}, +{7,4,2},{7,4,7},{7,8,45},{7,4,3},{7,5,11},{7,4,5},{7,8,53},{7,5,9},{9,8,448},{7,4,6}, +{7,8,35},{9,5,128},{7,8,51},{7,6,15},{7,8,63},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3}, +{9,9,1536},{7,4,5},{7,8,43},{7,6,17},{9,9,1280},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64}, +{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,29},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9}, +{9,6,1664},{7,4,6},{7,8,33},{9,5,128},{7,8,49},{7,6,14},{7,8,61},{7,4,4},{7,4,2},{7,4,7}, +{7,8,47},{7,4,3},{7,8,59},{7,4,5},{7,8,41},{7,6,16},{9,9,1024},{7,4,6},{7,8,31},{7,5,8}, +{7,8,57},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5}, +{7,7,26},{7,5,9},{9,9,768},{7,4,6},{7,8,37},{9,5,128},{7,7,25},{7,6,15},{9,8,320},{7,4,4}, +{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6}, +{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{11,11,1920},{7,4,3}, +{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14}, +{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,40},{7,6,16}, +{9,9,896},{7,4,6},{7,7,19},{7,5,8},{7,8,56},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7}, +{7,8,46},{7,4,3},{7,5,11},{7,4,5},{7,8,54},{7,5,9},{9,8,512},{7,4,6},{7,8,36},{9,5,128}, +{7,8,52},{7,6,15},{7,8,0},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1728},{7,4,5}, +{7,8,44},{7,6,17},{9,9,1408},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4}, +{7,4,2},{7,4,7},{7,8,30},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6}, +{7,8,34},{9,5,128},{7,8,50},{7,6,14},{7,8,62},{7,4,4},{7,4,2},{7,4,7},{7,8,48},{7,4,3}, +{7,8,60},{7,4,5},{7,8,42},{7,6,16},{9,9,1152},{7,4,6},{7,8,32},{7,5,8},{7,8,58},{9,5,64}, +{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9}, +{9,8,640},{7,4,6},{7,8,38},{9,5,128},{7,7,25},{7,6,15},{9,8,384},{7,4,4},{7,4,2},{7,4,7}, +{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8}, +{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{0,0,0},{7,4,3},{7,5,11},{7,4,5}, +{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4}, +{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,39},{7,6,16},{9,8,576},{7,4,6}, +{7,7,19},{7,5,8},{7,8,55},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,45},{7,4,3}, +{7,5,11},{7,4,5},{7,8,53},{7,5,9},{9,8,448},{7,4,6},{7,8,35},{9,5,128},{7,8,51},{7,6,15}, +{7,8,63},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1472},{7,4,5},{7,8,43},{7,6,17}, +{9,9,1216},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7}, +{7,8,29},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,33},{9,5,128}, +{7,8,49},{7,6,14},{7,8,61},{7,4,4},{7,4,2},{7,4,7},{7,8,47},{7,4,3},{7,8,59},{7,4,5}, +{7,8,41},{7,6,16},{9,9,960},{7,4,6},{7,8,31},{7,5,8},{7,8,57},{9,5,64},{7,5,10},{7,4,4}, +{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,9,704},{7,4,6}, +{7,8,37},{9,5,128},{7,7,25},{7,6,15},{9,8,320},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3}, +{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64}, +{7,5,10},{7,4,4},{7,4,2},{7,4,7},{11,12,2240},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9}, +{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7}, +{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,40},{7,6,16},{9,9,832},{7,4,6},{7,7,19},{7,5,8}, +{7,8,56},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,46},{7,4,3},{7,5,11},{7,4,5}, +{7,8,54},{7,5,9},{9,8,512},{7,4,6},{7,8,36},{9,5,128},{7,8,52},{7,6,15},{7,8,0},{7,4,4}, +{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1600},{7,4,5},{7,8,44},{7,6,17},{9,9,1344},{7,4,6}, +{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,30},{7,4,3}, +{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,34},{9,5,128},{7,8,50},{7,6,14}, +{7,8,62},{7,4,4},{7,4,2},{7,4,7},{7,8,48},{7,4,3},{7,8,60},{7,4,5},{7,8,42},{7,6,16}, +{9,9,1088},{7,4,6},{7,8,32},{7,5,8},{7,8,58},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7}, +{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,8,640},{7,4,6},{7,8,38},{9,5,128}, +{7,7,25},{7,6,15},{9,8,384},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5}, +{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4}, +{7,4,2},{7,4,7},{0,0,0},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6}, +{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3}, +{7,7,27},{7,4,5},{7,8,39},{7,6,16},{9,8,576},{7,4,6},{7,7,19},{7,5,8},{7,8,55},{9,5,64}, +{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,45},{7,4,3},{7,5,11},{7,4,5},{7,8,53},{7,5,9}, +{9,8,448},{7,4,6},{7,8,35},{9,5,128},{7,8,51},{7,6,15},{7,8,63},{7,4,4},{7,4,2},{7,4,7}, +{7,6,13},{7,4,3},{9,9,1536},{7,4,5},{7,8,43},{7,6,17},{9,9,1280},{7,4,6},{7,6,1},{7,5,8}, +{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,29},{7,4,3},{7,5,11},{7,4,5}, +{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,33},{9,5,128},{7,8,49},{7,6,14},{7,8,61},{7,4,4}, +{7,4,2},{7,4,7},{7,8,47},{7,4,3},{7,8,59},{7,4,5},{7,8,41},{7,6,16},{9,9,1024},{7,4,6}, +{7,8,31},{7,5,8},{7,8,57},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3}, +{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,9,768},{7,4,6},{7,8,37},{9,5,128},{7,7,25},{7,6,15}, +{9,8,320},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17}, +{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7}, +{11,12,2496},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128}, +{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5}, +{7,8,40},{7,6,16},{9,9,896},{7,4,6},{7,7,19},{7,5,8},{7,8,56},{9,5,64},{7,5,10},{7,4,4}, +{7,4,2},{7,4,7},{7,8,46},{7,4,3},{7,5,11},{7,4,5},{7,8,54},{7,5,9},{9,8,512},{7,4,6}, +{7,8,36},{9,5,128},{7,8,52},{7,6,15},{7,8,0},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3}, +{9,9,1728},{7,4,5},{7,8,44},{7,6,17},{9,9,1408},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64}, +{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,30},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9}, +{9,6,1664},{7,4,6},{7,8,34},{9,5,128},{7,8,50},{7,6,14},{7,8,62},{7,4,4},{7,4,2},{7,4,7}, +{7,8,48},{7,4,3},{7,8,60},{7,4,5},{7,8,42},{7,6,16},{9,9,1152},{7,4,6},{7,8,32},{7,5,8}, +{7,8,58},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5}, +{7,7,26},{7,5,9},{9,8,640},{7,4,6},{7,8,38},{9,5,128},{7,7,25},{7,6,15},{9,8,384},{7,4,4}, +{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6}, +{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{12,11,0},{7,4,3}, +{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14}, +{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,39},{7,6,16}, +{9,8,576},{7,4,6},{7,7,19},{7,5,8},{7,8,55},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7}, +{7,8,45},{7,4,3},{7,5,11},{7,4,5},{7,8,53},{7,5,9},{9,8,448},{7,4,6},{7,8,35},{9,5,128}, +{7,8,51},{7,6,15},{7,8,63},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1472},{7,4,5}, +{7,8,43},{7,6,17},{9,9,1216},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4}, +{7,4,2},{7,4,7},{7,8,29},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6}, +{7,8,33},{9,5,128},{7,8,49},{7,6,14},{7,8,61},{7,4,4},{7,4,2},{7,4,7},{7,8,47},{7,4,3}, +{7,8,59},{7,4,5},{7,8,41},{7,6,16},{9,9,960},{7,4,6},{7,8,31},{7,5,8},{7,8,57},{9,5,64}, +{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9}, +{9,9,704},{7,4,6},{7,8,37},{9,5,128},{7,7,25},{7,6,15},{9,8,320},{7,4,4},{7,4,2},{7,4,7}, +{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8}, +{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{11,11,1792},{7,4,3},{7,5,11},{7,4,5}, +{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4}, +{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,40},{7,6,16},{9,9,832},{7,4,6}, +{7,7,19},{7,5,8},{7,8,56},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,46},{7,4,3}, +{7,5,11},{7,4,5},{7,8,54},{7,5,9},{9,8,512},{7,4,6},{7,8,36},{9,5,128},{7,8,52},{7,6,15}, +{7,8,0},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1600},{7,4,5},{7,8,44},{7,6,17}, +{9,9,1344},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7}, +{7,8,30},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,34},{9,5,128}, +{7,8,50},{7,6,14},{7,8,62},{7,4,4},{7,4,2},{7,4,7},{7,8,48},{7,4,3},{7,8,60},{7,4,5}, +{7,8,42},{7,6,16},{9,9,1088},{7,4,6},{7,8,32},{7,5,8},{7,8,58},{9,5,64},{7,5,10},{7,4,4}, +{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,8,640},{7,4,6}, +{7,8,38},{9,5,128},{7,7,25},{7,6,15},{9,8,384},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3}, +{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64}, +{7,5,10},{7,4,4},{7,4,2},{7,4,7},{0,0,0},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9}, +{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7}, +{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,39},{7,6,16},{9,8,576},{7,4,6},{7,7,19},{7,5,8}, +{7,8,55},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,45},{7,4,3},{7,5,11},{7,4,5}, +{7,8,53},{7,5,9},{9,8,448},{7,4,6},{7,8,35},{9,5,128},{7,8,51},{7,6,15},{7,8,63},{7,4,4}, +{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1536},{7,4,5},{7,8,43},{7,6,17},{9,9,1280},{7,4,6}, +{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,29},{7,4,3}, +{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,33},{9,5,128},{7,8,49},{7,6,14}, +{7,8,61},{7,4,4},{7,4,2},{7,4,7},{7,8,47},{7,4,3},{7,8,59},{7,4,5},{7,8,41},{7,6,16}, +{9,9,1024},{7,4,6},{7,8,31},{7,5,8},{7,8,57},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7}, +{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,9,768},{7,4,6},{7,8,37},{9,5,128}, +{7,7,25},{7,6,15},{9,8,320},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5}, +{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4}, +{7,4,2},{7,4,7},{11,11,1856},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6}, +{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3}, +{7,7,27},{7,4,5},{7,8,40},{7,6,16},{9,9,896},{7,4,6},{7,7,19},{7,5,8},{7,8,56},{9,5,64}, +{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,46},{7,4,3},{7,5,11},{7,4,5},{7,8,54},{7,5,9}, +{9,8,512},{7,4,6},{7,8,36},{9,5,128},{7,8,52},{7,6,15},{7,8,0},{7,4,4},{7,4,2},{7,4,7}, +{7,6,13},{7,4,3},{9,9,1728},{7,4,5},{7,8,44},{7,6,17},{9,9,1408},{7,4,6},{7,6,1},{7,5,8}, +{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,30},{7,4,3},{7,5,11},{7,4,5}, +{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,34},{9,5,128},{7,8,50},{7,6,14},{7,8,62},{7,4,4}, +{7,4,2},{7,4,7},{7,8,48},{7,4,3},{7,8,60},{7,4,5},{7,8,42},{7,6,16},{9,9,1152},{7,4,6}, +{7,8,32},{7,5,8},{7,8,58},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3}, +{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,8,640},{7,4,6},{7,8,38},{9,5,128},{7,7,25},{7,6,15}, +{9,8,384},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17}, +{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7}, +{0,0,0},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128}, +{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5}, +{7,8,39},{7,6,16},{9,8,576},{7,4,6},{7,7,19},{7,5,8},{7,8,55},{9,5,64},{7,5,10},{7,4,4}, +{7,4,2},{7,4,7},{7,8,45},{7,4,3},{7,5,11},{7,4,5},{7,8,53},{7,5,9},{9,8,448},{7,4,6}, +{7,8,35},{9,5,128},{7,8,51},{7,6,15},{7,8,63},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3}, +{9,9,1472},{7,4,5},{7,8,43},{7,6,17},{9,9,1216},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64}, +{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,29},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9}, +{9,6,1664},{7,4,6},{7,8,33},{9,5,128},{7,8,49},{7,6,14},{7,8,61},{7,4,4},{7,4,2},{7,4,7}, +{7,8,47},{7,4,3},{7,8,59},{7,4,5},{7,8,41},{7,6,16},{9,9,960},{7,4,6},{7,8,31},{7,5,8}, +{7,8,57},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5}, +{7,7,26},{7,5,9},{9,9,704},{7,4,6},{7,8,37},{9,5,128},{7,7,25},{7,6,15},{9,8,320},{7,4,4}, +{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6}, +{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{11,12,2176},{7,4,3}, +{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14}, +{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,40},{7,6,16}, +{9,9,832},{7,4,6},{7,7,19},{7,5,8},{7,8,56},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7}, +{7,8,46},{7,4,3},{7,5,11},{7,4,5},{7,8,54},{7,5,9},{9,8,512},{7,4,6},{7,8,36},{9,5,128}, +{7,8,52},{7,6,15},{7,8,0},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1600},{7,4,5}, +{7,8,44},{7,6,17},{9,9,1344},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4}, +{7,4,2},{7,4,7},{7,8,30},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6}, +{7,8,34},{9,5,128},{7,8,50},{7,6,14},{7,8,62},{7,4,4},{7,4,2},{7,4,7},{7,8,48},{7,4,3}, +{7,8,60},{7,4,5},{7,8,42},{7,6,16},{9,9,1088},{7,4,6},{7,8,32},{7,5,8},{7,8,58},{9,5,64}, +{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9}, +{9,8,640},{7,4,6},{7,8,38},{9,5,128},{7,7,25},{7,6,15},{9,8,384},{7,4,4},{7,4,2},{7,4,7}, +{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8}, +{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{0,0,0},{7,4,3},{7,5,11},{7,4,5}, +{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4}, +{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,39},{7,6,16},{9,8,576},{7,4,6}, +{7,7,19},{7,5,8},{7,8,55},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,45},{7,4,3}, +{7,5,11},{7,4,5},{7,8,53},{7,5,9},{9,8,448},{7,4,6},{7,8,35},{9,5,128},{7,8,51},{7,6,15}, +{7,8,63},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1536},{7,4,5},{7,8,43},{7,6,17}, +{9,9,1280},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7}, +{7,8,29},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,33},{9,5,128}, +{7,8,49},{7,6,14},{7,8,61},{7,4,4},{7,4,2},{7,4,7},{7,8,47},{7,4,3},{7,8,59},{7,4,5}, +{7,8,41},{7,6,16},{9,9,1024},{7,4,6},{7,8,31},{7,5,8},{7,8,57},{9,5,64},{7,5,10},{7,4,4}, +{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,9,768},{7,4,6}, +{7,8,37},{9,5,128},{7,7,25},{7,6,15},{9,8,320},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3}, +{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64}, +{7,5,10},{7,4,4},{7,4,2},{7,4,7},{11,12,2432},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9}, +{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7}, +{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,40},{7,6,16},{9,9,896},{7,4,6},{7,7,19},{7,5,8}, +{7,8,56},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,46},{7,4,3},{7,5,11},{7,4,5}, +{7,8,54},{7,5,9},{9,8,512},{7,4,6},{7,8,36},{9,5,128},{7,8,52},{7,6,15},{7,8,0},{7,4,4}, +{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1728},{7,4,5},{7,8,44},{7,6,17},{9,9,1408},{7,4,6}, +{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,30},{7,4,3}, +{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,34},{9,5,128},{7,8,50},{7,6,14}, +{7,8,62},{7,4,4},{7,4,2},{7,4,7},{7,8,48},{7,4,3},{7,8,60},{7,4,5},{7,8,42},{7,6,16}, +{9,9,1152},{7,4,6},{7,8,32},{7,5,8},{7,8,58},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7}, +{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,8,640},{7,4,6},{7,8,38},{9,5,128}, +{7,7,25},{7,6,15},{9,8,384},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5}, +{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4}, +{7,4,2},{7,4,7},{0,0,0},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6}, +{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3}, +{7,7,27},{7,4,5},{7,8,39},{7,6,16},{9,8,576},{7,4,6},{7,7,19},{7,5,8},{7,8,55},{9,5,64}, +{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,45},{7,4,3},{7,5,11},{7,4,5},{7,8,53},{7,5,9}, +{9,8,448},{7,4,6},{7,8,35},{9,5,128},{7,8,51},{7,6,15},{7,8,63},{7,4,4},{7,4,2},{7,4,7}, +{7,6,13},{7,4,3},{9,9,1472},{7,4,5},{7,8,43},{7,6,17},{9,9,1216},{7,4,6},{7,6,1},{7,5,8}, +{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,29},{7,4,3},{7,5,11},{7,4,5}, +{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,33},{9,5,128},{7,8,49},{7,6,14},{7,8,61},{7,4,4}, +{7,4,2},{7,4,7},{7,8,47},{7,4,3},{7,8,59},{7,4,5},{7,8,41},{7,6,16},{9,9,960},{7,4,6}, +{7,8,31},{7,5,8},{7,8,57},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3}, +{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,9,704},{7,4,6},{7,8,37},{9,5,128},{7,7,25},{7,6,15}, +{9,8,320},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17}, +{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7}, +{11,12,2048},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128}, +{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5}, +{7,8,40},{7,6,16},{9,9,832},{7,4,6},{7,7,19},{7,5,8},{7,8,56},{9,5,64},{7,5,10},{7,4,4}, +{7,4,2},{7,4,7},{7,8,46},{7,4,3},{7,5,11},{7,4,5},{7,8,54},{7,5,9},{9,8,512},{7,4,6}, +{7,8,36},{9,5,128},{7,8,52},{7,6,15},{7,8,0},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3}, +{9,9,1600},{7,4,5},{7,8,44},{7,6,17},{9,9,1344},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64}, +{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,30},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9}, +{9,6,1664},{7,4,6},{7,8,34},{9,5,128},{7,8,50},{7,6,14},{7,8,62},{7,4,4},{7,4,2},{7,4,7}, +{7,8,48},{7,4,3},{7,8,60},{7,4,5},{7,8,42},{7,6,16},{9,9,1088},{7,4,6},{7,8,32},{7,5,8}, +{7,8,58},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5}, +{7,7,26},{7,5,9},{9,8,640},{7,4,6},{7,8,38},{9,5,128},{7,7,25},{7,6,15},{9,8,384},{7,4,4}, +{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6}, +{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{0,0,0},{7,4,3}, +{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14}, +{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,39},{7,6,16}, +{9,8,576},{7,4,6},{7,7,19},{7,5,8},{7,8,55},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7}, +{7,8,45},{7,4,3},{7,5,11},{7,4,5},{7,8,53},{7,5,9},{9,8,448},{7,4,6},{7,8,35},{9,5,128}, +{7,8,51},{7,6,15},{7,8,63},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1536},{7,4,5}, +{7,8,43},{7,6,17},{9,9,1280},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4}, +{7,4,2},{7,4,7},{7,8,29},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6}, +{7,8,33},{9,5,128},{7,8,49},{7,6,14},{7,8,61},{7,4,4},{7,4,2},{7,4,7},{7,8,47},{7,4,3}, +{7,8,59},{7,4,5},{7,8,41},{7,6,16},{9,9,1024},{7,4,6},{7,8,31},{7,5,8},{7,8,57},{9,5,64}, +{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9}, +{9,9,768},{7,4,6},{7,8,37},{9,5,128},{7,7,25},{7,6,15},{9,8,320},{7,4,4},{7,4,2},{7,4,7}, +{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8}, +{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{11,11,1920},{7,4,3},{7,5,11},{7,4,5}, +{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4}, +{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,40},{7,6,16},{9,9,896},{7,4,6}, +{7,7,19},{7,5,8},{7,8,56},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,46},{7,4,3}, +{7,5,11},{7,4,5},{7,8,54},{7,5,9},{9,8,512},{7,4,6},{7,8,36},{9,5,128},{7,8,52},{7,6,15}, +{7,8,0},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1728},{7,4,5},{7,8,44},{7,6,17}, +{9,9,1408},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7}, +{7,8,30},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,34},{9,5,128}, +{7,8,50},{7,6,14},{7,8,62},{7,4,4},{7,4,2},{7,4,7},{7,8,48},{7,4,3},{7,8,60},{7,4,5}, +{7,8,42},{7,6,16},{9,9,1152},{7,4,6},{7,8,32},{7,5,8},{7,8,58},{9,5,64},{7,5,10},{7,4,4}, +{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,8,640},{7,4,6}, +{7,8,38},{9,5,128},{7,7,25},{7,6,15},{9,8,384},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3}, +{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64}, +{7,5,10},{7,4,4},{7,4,2},{7,4,7},{0,0,0},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9}, +{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7}, +{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,39},{7,6,16},{9,8,576},{7,4,6},{7,7,19},{7,5,8}, +{7,8,55},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,45},{7,4,3},{7,5,11},{7,4,5}, +{7,8,53},{7,5,9},{9,8,448},{7,4,6},{7,8,35},{9,5,128},{7,8,51},{7,6,15},{7,8,63},{7,4,4}, +{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1472},{7,4,5},{7,8,43},{7,6,17},{9,9,1216},{7,4,6}, +{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,29},{7,4,3}, +{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,33},{9,5,128},{7,8,49},{7,6,14}, +{7,8,61},{7,4,4},{7,4,2},{7,4,7},{7,8,47},{7,4,3},{7,8,59},{7,4,5},{7,8,41},{7,6,16}, +{9,9,960},{7,4,6},{7,8,31},{7,5,8},{7,8,57},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7}, +{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,9,704},{7,4,6},{7,8,37},{9,5,128}, +{7,7,25},{7,6,15},{9,8,320},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5}, +{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4}, +{7,4,2},{7,4,7},{11,12,2304},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6}, +{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3}, +{7,7,27},{7,4,5},{7,8,40},{7,6,16},{9,9,832},{7,4,6},{7,7,19},{7,5,8},{7,8,56},{9,5,64}, +{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,46},{7,4,3},{7,5,11},{7,4,5},{7,8,54},{7,5,9}, +{9,8,512},{7,4,6},{7,8,36},{9,5,128},{7,8,52},{7,6,15},{7,8,0},{7,4,4},{7,4,2},{7,4,7}, +{7,6,13},{7,4,3},{9,9,1600},{7,4,5},{7,8,44},{7,6,17},{9,9,1344},{7,4,6},{7,6,1},{7,5,8}, +{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,30},{7,4,3},{7,5,11},{7,4,5}, +{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,34},{9,5,128},{7,8,50},{7,6,14},{7,8,62},{7,4,4}, +{7,4,2},{7,4,7},{7,8,48},{7,4,3},{7,8,60},{7,4,5},{7,8,42},{7,6,16},{9,9,1088},{7,4,6}, +{7,8,32},{7,5,8},{7,8,58},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3}, +{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,8,640},{7,4,6},{7,8,38},{9,5,128},{7,7,25},{7,6,15}, +{9,8,384},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17}, +{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7}, +{0,0,0},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128}, +{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5}, +{7,8,39},{7,6,16},{9,8,576},{7,4,6},{7,7,19},{7,5,8},{7,8,55},{9,5,64},{7,5,10},{7,4,4}, +{7,4,2},{7,4,7},{7,8,45},{7,4,3},{7,5,11},{7,4,5},{7,8,53},{7,5,9},{9,8,448},{7,4,6}, +{7,8,35},{9,5,128},{7,8,51},{7,6,15},{7,8,63},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3}, +{9,9,1536},{7,4,5},{7,8,43},{7,6,17},{9,9,1280},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64}, +{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,29},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9}, +{9,6,1664},{7,4,6},{7,8,33},{9,5,128},{7,8,49},{7,6,14},{7,8,61},{7,4,4},{7,4,2},{7,4,7}, +{7,8,47},{7,4,3},{7,8,59},{7,4,5},{7,8,41},{7,6,16},{9,9,1024},{7,4,6},{7,8,31},{7,5,8}, +{7,8,57},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5}, +{7,7,26},{7,5,9},{9,9,768},{7,4,6},{7,8,37},{9,5,128},{7,7,25},{7,6,15},{9,8,320},{7,4,4}, +{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6}, +{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{11,12,2560},{7,4,3}, +{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14}, +{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,40},{7,6,16}, +{9,9,896},{7,4,6},{7,7,19},{7,5,8},{7,8,56},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7}, +{7,8,46},{7,4,3},{7,5,11},{7,4,5},{7,8,54},{7,5,9},{9,8,512},{7,4,6},{7,8,36},{9,5,128}, +{7,8,52},{7,6,15},{7,8,0},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1728},{7,4,5}, +{7,8,44},{7,6,17},{9,9,1408},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4}, +{7,4,2},{7,4,7},{7,8,30},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6}, +{7,8,34},{9,5,128},{7,8,50},{7,6,14},{7,8,62},{7,4,4},{7,4,2},{7,4,7},{7,8,48},{7,4,3}, +{7,8,60},{7,4,5},{7,8,42},{7,6,16},{9,9,1152},{7,4,6},{7,8,32},{7,5,8},{7,8,58},{9,5,64}, +{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9}, +{9,8,640},{7,4,6},{7,8,38},{9,5,128},{7,7,25},{7,6,15},{9,8,384},{7,4,4},{7,4,2},{7,4,7}, +{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8}, +{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7} +}; + const TIFFFaxTabEnt TIFFFaxBlackTable[8192] = { +{12,11,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,9,15},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,18},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,17},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,11,1792},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,11,23},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,20},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,11,25},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,12,128},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,12,56},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,12,30},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,11,1856},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,57},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,11,21},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,54},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,9,15},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,52},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,48},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{11,12,2112},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,12,44},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,36},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,12,384},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,28},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,12,60},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,40},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,12,2368},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,16},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{10,10,64},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,9,15},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,18},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,10,17},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{11,12,1984},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,50},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,12,34},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,13,1664},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,26},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,13,1408},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,32},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,11,1920},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,12,61},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,42},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{10,13,1024},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,9,15},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{10,13,768},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,12,62},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,12,2240},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,46},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,12,38},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,13,512},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,11,19},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,24},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,22},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{11,12,2496},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,10,16},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,0},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,10,64},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{12,11,0},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,9,15},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,10,18},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,17},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,11,1792},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,23},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,20},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,11,25},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{10,12,192},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,13,1280},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,12,31},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{11,11,1856},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,58},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,11,21},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,13,896},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,9,15},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,13,640},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,49},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,12,2176},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,12,45},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,37},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{10,12,448},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,29},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{10,13,1536},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,12,41},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,12,2432},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,16},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,10,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,10,64},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,9,15},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,18},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,17},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{11,12,2048},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,12,51},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,35},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,12,320},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,27},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,12,59},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,33},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,11,1920},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,12,256},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,43},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{10,13,1152},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,9,15},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,55},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,12,63},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{11,12,2304},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,47},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,12,39},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,53},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,19},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,24},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,22},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,12,2560},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,10,16},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,0},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{10,10,64},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{12,11,0},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,9,15},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,10,18},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,10,17},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,11,1792},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,23},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,11,20},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,25},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{10,12,128},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,56},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,30},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{11,11,1856},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,12,57},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,21},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,54},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,9,15},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,12,52},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,48},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,12,2112},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,44},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,36},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{10,12,384},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,12,28},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,60},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,12,40},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{11,12,2368},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,16},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,10,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,10,64},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,9,15},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,18},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,17},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,12,1984},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,12,50},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,34},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{10,13,1728},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,26},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{10,13,1472},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,12,32},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,11,1920},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,61},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,12,42},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,13,1088},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,9,15},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,13,832},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,62},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{11,12,2240},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,12,46},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,38},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,13,576},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,19},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,11,24},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,22},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,12,2496},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,16},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{10,10,64},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{12,11,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,9,15},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,18},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,10,17},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{11,11,1792},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,23},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,11,20},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,25},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,12,192},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,13,1344},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,31},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,11,1856},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,12,58},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,21},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{10,13,960},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,9,15},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{10,13,704},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,12,49},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,12,2176},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,45},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,12,37},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,12,448},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,12,29},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,13,1600},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,41},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{11,12,2432},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,10,16},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,0},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,10,64},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,9,15},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,10,18},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,17},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,12,2048},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,51},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,35},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{10,12,320},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,12,27},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,59},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,12,33},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{11,11,1920},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,12,256},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,12,43},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,13,1216},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,9,15},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,55},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,63},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,12,2304},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,12,47},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,39},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,12,53},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,19},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,11,24},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,11,22},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,12,2560},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,16},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2},{8,10,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2}, +{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,10,64},{8,2,3}, +{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2}, +{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3}, +{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2}, +{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3}, +{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2}, +{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3}, +{8,3,4},{8,2,2} +}; +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tif_flush.c b/reactos/dll/3rdparty/libtiff/tif_flush.c new file mode 100644 index 00000000000..7ecc4d8345d --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tif_flush.c @@ -0,0 +1,74 @@ +/* $Header: /cvs/maptools/cvsroot/libtiff/libtiff/tif_flush.c,v 1.3.2.1 2010-06-08 18:50:42 bfriesen Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library. + */ +#include "tiffiop.h" + +int +TIFFFlush(TIFF* tif) +{ + + if (tif->tif_mode != O_RDONLY) { + if (!TIFFFlushData(tif)) + return (0); + if ((tif->tif_flags & TIFF_DIRTYDIRECT) && + !TIFFWriteDirectory(tif)) + return (0); + } + return (1); +} + +/* + * Flush buffered data to the file. + * + * Frank Warmerdam'2000: I modified this to return 1 if TIFF_BEENWRITING + * is not set, so that TIFFFlush() will proceed to write out the directory. + * The documentation says returning 1 is an error indicator, but not having + * been writing isn't exactly a an error. Hopefully this doesn't cause + * problems for other people. + */ +int +TIFFFlushData(TIFF* tif) +{ + if ((tif->tif_flags & TIFF_BEENWRITING) == 0) + return (0); + if (tif->tif_flags & TIFF_POSTENCODE) { + tif->tif_flags &= ~TIFF_POSTENCODE; + if (!(*tif->tif_postencode)(tif)) + return (0); + } + return (TIFFFlushData1(tif)); +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tif_getimage.c b/reactos/dll/3rdparty/libtiff/tif_getimage.c new file mode 100644 index 00000000000..38455fbc074 --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tif_getimage.c @@ -0,0 +1,2676 @@ +/* $Id: tif_getimage.c,v 1.63.2.4 2010-06-08 18:50:42 bfriesen Exp $ */ + +/* + * Copyright (c) 1991-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library + * + * Read and return a packed RGBA image. + */ +#include "tiffiop.h" +#include + +static int gtTileContig(TIFFRGBAImage*, uint32*, uint32, uint32); +static int gtTileSeparate(TIFFRGBAImage*, uint32*, uint32, uint32); +static int gtStripContig(TIFFRGBAImage*, uint32*, uint32, uint32); +static int gtStripSeparate(TIFFRGBAImage*, uint32*, uint32, uint32); +static int PickContigCase(TIFFRGBAImage*); +static int PickSeparateCase(TIFFRGBAImage*); +static const char photoTag[] = "PhotometricInterpretation"; + +/* + * Helper constants used in Orientation tag handling + */ +#define FLIP_VERTICALLY 0x01 +#define FLIP_HORIZONTALLY 0x02 + +/* + * Color conversion constants. We will define display types here. + */ + +TIFFDisplay display_sRGB = { + { /* XYZ -> luminance matrix */ + { 3.2410F, -1.5374F, -0.4986F }, + { -0.9692F, 1.8760F, 0.0416F }, + { 0.0556F, -0.2040F, 1.0570F } + }, + 100.0F, 100.0F, 100.0F, /* Light o/p for reference white */ + 255, 255, 255, /* Pixel values for ref. white */ + 1.0F, 1.0F, 1.0F, /* Residual light o/p for black pixel */ + 2.4F, 2.4F, 2.4F, /* Gamma values for the three guns */ +}; + +/* + * Check the image to see if TIFFReadRGBAImage can deal with it. + * 1/0 is returned according to whether or not the image can + * be handled. If 0 is returned, emsg contains the reason + * why it is being rejected. + */ +int +TIFFRGBAImageOK(TIFF* tif, char emsg[1024]) +{ + TIFFDirectory* td = &tif->tif_dir; + uint16 photometric; + int colorchannels; + + if (!tif->tif_decodestatus) { + sprintf(emsg, "Sorry, requested compression method is not configured"); + return (0); + } + switch (td->td_bitspersample) { + case 1: + case 2: + case 4: + case 8: + case 16: + break; + default: + sprintf(emsg, "Sorry, can not handle images with %d-bit samples", + td->td_bitspersample); + return (0); + } + colorchannels = td->td_samplesperpixel - td->td_extrasamples; + if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric)) { + switch (colorchannels) { + case 1: + photometric = PHOTOMETRIC_MINISBLACK; + break; + case 3: + photometric = PHOTOMETRIC_RGB; + break; + default: + sprintf(emsg, "Missing needed %s tag", photoTag); + return (0); + } + } + switch (photometric) { + case PHOTOMETRIC_MINISWHITE: + case PHOTOMETRIC_MINISBLACK: + case PHOTOMETRIC_PALETTE: + if (td->td_planarconfig == PLANARCONFIG_CONTIG + && td->td_samplesperpixel != 1 + && td->td_bitspersample < 8 ) { + sprintf(emsg, + "Sorry, can not handle contiguous data with %s=%d, " + "and %s=%d and Bits/Sample=%d", + photoTag, photometric, + "Samples/pixel", td->td_samplesperpixel, + td->td_bitspersample); + return (0); + } + /* + * We should likely validate that any extra samples are either + * to be ignored, or are alpha, and if alpha we should try to use + * them. But for now we won't bother with this. + */ + break; + case PHOTOMETRIC_YCBCR: + /* + * TODO: if at all meaningful and useful, make more complete + * support check here, or better still, refactor to let supporting + * code decide whether there is support and what meaningfull + * error to return + */ + break; + case PHOTOMETRIC_RGB: + if (colorchannels < 3) { + sprintf(emsg, "Sorry, can not handle RGB image with %s=%d", + "Color channels", colorchannels); + return (0); + } + break; + case PHOTOMETRIC_SEPARATED: + { + uint16 inkset; + TIFFGetFieldDefaulted(tif, TIFFTAG_INKSET, &inkset); + if (inkset != INKSET_CMYK) { + sprintf(emsg, + "Sorry, can not handle separated image with %s=%d", + "InkSet", inkset); + return 0; + } + if (td->td_samplesperpixel < 4) { + sprintf(emsg, + "Sorry, can not handle separated image with %s=%d", + "Samples/pixel", td->td_samplesperpixel); + return 0; + } + break; + } + case PHOTOMETRIC_LOGL: + if (td->td_compression != COMPRESSION_SGILOG) { + sprintf(emsg, "Sorry, LogL data must have %s=%d", + "Compression", COMPRESSION_SGILOG); + return (0); + } + break; + case PHOTOMETRIC_LOGLUV: + if (td->td_compression != COMPRESSION_SGILOG && + td->td_compression != COMPRESSION_SGILOG24) { + sprintf(emsg, "Sorry, LogLuv data must have %s=%d or %d", + "Compression", COMPRESSION_SGILOG, COMPRESSION_SGILOG24); + return (0); + } + if (td->td_planarconfig != PLANARCONFIG_CONTIG) { + sprintf(emsg, "Sorry, can not handle LogLuv images with %s=%d", + "Planarconfiguration", td->td_planarconfig); + return (0); + } + break; + case PHOTOMETRIC_CIELAB: + break; + default: + sprintf(emsg, "Sorry, can not handle image with %s=%d", + photoTag, photometric); + return (0); + } + return (1); +} + +void +TIFFRGBAImageEnd(TIFFRGBAImage* img) +{ + if (img->Map) + _TIFFfree(img->Map), img->Map = NULL; + if (img->BWmap) + _TIFFfree(img->BWmap), img->BWmap = NULL; + if (img->PALmap) + _TIFFfree(img->PALmap), img->PALmap = NULL; + if (img->ycbcr) + _TIFFfree(img->ycbcr), img->ycbcr = NULL; + if (img->cielab) + _TIFFfree(img->cielab), img->cielab = NULL; + if( img->redcmap ) { + _TIFFfree( img->redcmap ); + _TIFFfree( img->greencmap ); + _TIFFfree( img->bluecmap ); + } +} + +static int +isCCITTCompression(TIFF* tif) +{ + uint16 compress; + TIFFGetField(tif, TIFFTAG_COMPRESSION, &compress); + return (compress == COMPRESSION_CCITTFAX3 || + compress == COMPRESSION_CCITTFAX4 || + compress == COMPRESSION_CCITTRLE || + compress == COMPRESSION_CCITTRLEW); +} + +int +TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024]) +{ + uint16* sampleinfo; + uint16 extrasamples; + uint16 planarconfig; + uint16 compress; + int colorchannels; + uint16 *red_orig, *green_orig, *blue_orig; + int n_color; + + /* Initialize to normal values */ + img->row_offset = 0; + img->col_offset = 0; + img->redcmap = NULL; + img->greencmap = NULL; + img->bluecmap = NULL; + img->req_orientation = ORIENTATION_BOTLEFT; /* It is the default */ + + img->tif = tif; + img->stoponerr = stop; + TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &img->bitspersample); + switch (img->bitspersample) { + case 1: + case 2: + case 4: + case 8: + case 16: + break; + default: + sprintf(emsg, "Sorry, can not handle images with %d-bit samples", + img->bitspersample); + return (0); + } + img->alpha = 0; + TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &img->samplesperpixel); + TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES, + &extrasamples, &sampleinfo); + if (extrasamples >= 1) + { + switch (sampleinfo[0]) { + case EXTRASAMPLE_UNSPECIFIED: /* Workaround for some images without */ + if (img->samplesperpixel > 3) /* correct info about alpha channel */ + img->alpha = EXTRASAMPLE_ASSOCALPHA; + break; + case EXTRASAMPLE_ASSOCALPHA: /* data is pre-multiplied */ + case EXTRASAMPLE_UNASSALPHA: /* data is not pre-multiplied */ + img->alpha = sampleinfo[0]; + break; + } + } + +#ifdef DEFAULT_EXTRASAMPLE_AS_ALPHA + if( !TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &img->photometric)) + img->photometric = PHOTOMETRIC_MINISWHITE; + + if( extrasamples == 0 + && img->samplesperpixel == 4 + && img->photometric == PHOTOMETRIC_RGB ) + { + img->alpha = EXTRASAMPLE_ASSOCALPHA; + extrasamples = 1; + } +#endif + + colorchannels = img->samplesperpixel - extrasamples; + TIFFGetFieldDefaulted(tif, TIFFTAG_COMPRESSION, &compress); + TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, &planarconfig); + if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &img->photometric)) { + switch (colorchannels) { + case 1: + if (isCCITTCompression(tif)) + img->photometric = PHOTOMETRIC_MINISWHITE; + else + img->photometric = PHOTOMETRIC_MINISBLACK; + break; + case 3: + img->photometric = PHOTOMETRIC_RGB; + break; + default: + sprintf(emsg, "Missing needed %s tag", photoTag); + return (0); + } + } + switch (img->photometric) { + case PHOTOMETRIC_PALETTE: + if (!TIFFGetField(tif, TIFFTAG_COLORMAP, + &red_orig, &green_orig, &blue_orig)) { + sprintf(emsg, "Missing required \"Colormap\" tag"); + return (0); + } + + /* copy the colormaps so we can modify them */ + n_color = (1L << img->bitspersample); + img->redcmap = (uint16 *) _TIFFmalloc(sizeof(uint16)*n_color); + img->greencmap = (uint16 *) _TIFFmalloc(sizeof(uint16)*n_color); + img->bluecmap = (uint16 *) _TIFFmalloc(sizeof(uint16)*n_color); + if( !img->redcmap || !img->greencmap || !img->bluecmap ) { + sprintf(emsg, "Out of memory for colormap copy"); + return (0); + } + + _TIFFmemcpy( img->redcmap, red_orig, n_color * 2 ); + _TIFFmemcpy( img->greencmap, green_orig, n_color * 2 ); + _TIFFmemcpy( img->bluecmap, blue_orig, n_color * 2 ); + + /* fall thru... */ + case PHOTOMETRIC_MINISWHITE: + case PHOTOMETRIC_MINISBLACK: + if (planarconfig == PLANARCONFIG_CONTIG + && img->samplesperpixel != 1 + && img->bitspersample < 8 ) { + sprintf(emsg, + "Sorry, can not handle contiguous data with %s=%d, " + "and %s=%d and Bits/Sample=%d", + photoTag, img->photometric, + "Samples/pixel", img->samplesperpixel, + img->bitspersample); + return (0); + } + break; + case PHOTOMETRIC_YCBCR: + /* It would probably be nice to have a reality check here. */ + if (planarconfig == PLANARCONFIG_CONTIG) + /* can rely on libjpeg to convert to RGB */ + /* XXX should restore current state on exit */ + switch (compress) { + case COMPRESSION_JPEG: + /* + * TODO: when complete tests verify complete desubsampling + * and YCbCr handling, remove use of TIFFTAG_JPEGCOLORMODE in + * favor of tif_getimage.c native handling + */ + TIFFSetField(tif, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB); + img->photometric = PHOTOMETRIC_RGB; + break; + default: + /* do nothing */; + break; + } + /* + * TODO: if at all meaningful and useful, make more complete + * support check here, or better still, refactor to let supporting + * code decide whether there is support and what meaningfull + * error to return + */ + break; + case PHOTOMETRIC_RGB: + if (colorchannels < 3) { + sprintf(emsg, "Sorry, can not handle RGB image with %s=%d", + "Color channels", colorchannels); + return (0); + } + break; + case PHOTOMETRIC_SEPARATED: + { + uint16 inkset; + TIFFGetFieldDefaulted(tif, TIFFTAG_INKSET, &inkset); + if (inkset != INKSET_CMYK) { + sprintf(emsg, "Sorry, can not handle separated image with %s=%d", + "InkSet", inkset); + return (0); + } + if (img->samplesperpixel < 4) { + sprintf(emsg, "Sorry, can not handle separated image with %s=%d", + "Samples/pixel", img->samplesperpixel); + return (0); + } + } + break; + case PHOTOMETRIC_LOGL: + if (compress != COMPRESSION_SGILOG) { + sprintf(emsg, "Sorry, LogL data must have %s=%d", + "Compression", COMPRESSION_SGILOG); + return (0); + } + TIFFSetField(tif, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_8BIT); + img->photometric = PHOTOMETRIC_MINISBLACK; /* little white lie */ + img->bitspersample = 8; + break; + case PHOTOMETRIC_LOGLUV: + if (compress != COMPRESSION_SGILOG && compress != COMPRESSION_SGILOG24) { + sprintf(emsg, "Sorry, LogLuv data must have %s=%d or %d", + "Compression", COMPRESSION_SGILOG, COMPRESSION_SGILOG24); + return (0); + } + if (planarconfig != PLANARCONFIG_CONTIG) { + sprintf(emsg, "Sorry, can not handle LogLuv images with %s=%d", + "Planarconfiguration", planarconfig); + return (0); + } + TIFFSetField(tif, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_8BIT); + img->photometric = PHOTOMETRIC_RGB; /* little white lie */ + img->bitspersample = 8; + break; + case PHOTOMETRIC_CIELAB: + break; + default: + sprintf(emsg, "Sorry, can not handle image with %s=%d", + photoTag, img->photometric); + return (0); + } + img->Map = NULL; + img->BWmap = NULL; + img->PALmap = NULL; + img->ycbcr = NULL; + img->cielab = NULL; + TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &img->width); + TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &img->height); + TIFFGetFieldDefaulted(tif, TIFFTAG_ORIENTATION, &img->orientation); + img->isContig = + !(planarconfig == PLANARCONFIG_SEPARATE && colorchannels > 1); + if (img->isContig) { + if (!PickContigCase(img)) { + sprintf(emsg, "Sorry, can not handle image"); + return 0; + } + } else { + if (!PickSeparateCase(img)) { + sprintf(emsg, "Sorry, can not handle image"); + return 0; + } + } + return 1; +} + +int +TIFFRGBAImageGet(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) +{ + if (img->get == NULL) { + TIFFErrorExt(img->tif->tif_clientdata, TIFFFileName(img->tif), "No \"get\" routine setup"); + return (0); + } + if (img->put.any == NULL) { + TIFFErrorExt(img->tif->tif_clientdata, TIFFFileName(img->tif), + "No \"put\" routine setupl; probably can not handle image format"); + return (0); + } + return (*img->get)(img, raster, w, h); +} + +/* + * Read the specified image into an ABGR-format rastertaking in account + * specified orientation. + */ +int +TIFFReadRGBAImageOriented(TIFF* tif, + uint32 rwidth, uint32 rheight, uint32* raster, + int orientation, int stop) +{ + char emsg[1024] = ""; + TIFFRGBAImage img; + int ok; + + if (TIFFRGBAImageOK(tif, emsg) && TIFFRGBAImageBegin(&img, tif, stop, emsg)) { + img.req_orientation = orientation; + /* XXX verify rwidth and rheight against width and height */ + ok = TIFFRGBAImageGet(&img, raster+(rheight-img.height)*rwidth, + rwidth, img.height); + TIFFRGBAImageEnd(&img); + } else { + TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", emsg); + ok = 0; + } + return (ok); +} + +/* + * Read the specified image into an ABGR-format raster. Use bottom left + * origin for raster by default. + */ +int +TIFFReadRGBAImage(TIFF* tif, + uint32 rwidth, uint32 rheight, uint32* raster, int stop) +{ + return TIFFReadRGBAImageOriented(tif, rwidth, rheight, raster, + ORIENTATION_BOTLEFT, stop); +} + +static int +setorientation(TIFFRGBAImage* img) +{ + switch (img->orientation) { + case ORIENTATION_TOPLEFT: + case ORIENTATION_LEFTTOP: + if (img->req_orientation == ORIENTATION_TOPRIGHT || + img->req_orientation == ORIENTATION_RIGHTTOP) + return FLIP_HORIZONTALLY; + else if (img->req_orientation == ORIENTATION_BOTRIGHT || + img->req_orientation == ORIENTATION_RIGHTBOT) + return FLIP_HORIZONTALLY | FLIP_VERTICALLY; + else if (img->req_orientation == ORIENTATION_BOTLEFT || + img->req_orientation == ORIENTATION_LEFTBOT) + return FLIP_VERTICALLY; + else + return 0; + case ORIENTATION_TOPRIGHT: + case ORIENTATION_RIGHTTOP: + if (img->req_orientation == ORIENTATION_TOPLEFT || + img->req_orientation == ORIENTATION_LEFTTOP) + return FLIP_HORIZONTALLY; + else if (img->req_orientation == ORIENTATION_BOTRIGHT || + img->req_orientation == ORIENTATION_RIGHTBOT) + return FLIP_VERTICALLY; + else if (img->req_orientation == ORIENTATION_BOTLEFT || + img->req_orientation == ORIENTATION_LEFTBOT) + return FLIP_HORIZONTALLY | FLIP_VERTICALLY; + else + return 0; + case ORIENTATION_BOTRIGHT: + case ORIENTATION_RIGHTBOT: + if (img->req_orientation == ORIENTATION_TOPLEFT || + img->req_orientation == ORIENTATION_LEFTTOP) + return FLIP_HORIZONTALLY | FLIP_VERTICALLY; + else if (img->req_orientation == ORIENTATION_TOPRIGHT || + img->req_orientation == ORIENTATION_RIGHTTOP) + return FLIP_VERTICALLY; + else if (img->req_orientation == ORIENTATION_BOTLEFT || + img->req_orientation == ORIENTATION_LEFTBOT) + return FLIP_HORIZONTALLY; + else + return 0; + case ORIENTATION_BOTLEFT: + case ORIENTATION_LEFTBOT: + if (img->req_orientation == ORIENTATION_TOPLEFT || + img->req_orientation == ORIENTATION_LEFTTOP) + return FLIP_VERTICALLY; + else if (img->req_orientation == ORIENTATION_TOPRIGHT || + img->req_orientation == ORIENTATION_RIGHTTOP) + return FLIP_HORIZONTALLY | FLIP_VERTICALLY; + else if (img->req_orientation == ORIENTATION_BOTRIGHT || + img->req_orientation == ORIENTATION_RIGHTBOT) + return FLIP_HORIZONTALLY; + else + return 0; + default: /* NOTREACHED */ + return 0; + } +} + +/* + * Get an tile-organized image that has + * PlanarConfiguration contiguous if SamplesPerPixel > 1 + * or + * SamplesPerPixel == 1 + */ +static int +gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) +{ + TIFF* tif = img->tif; + tileContigRoutine put = img->put.contig; + uint32 col, row, y, rowstoread; + uint32 pos; + uint32 tw, th; + unsigned char* buf; + int32 fromskew, toskew; + uint32 nrow; + int ret = 1, flip; + + buf = (unsigned char*) _TIFFmalloc(TIFFTileSize(tif)); + if (buf == 0) { + TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for tile buffer"); + return (0); + } + _TIFFmemset(buf, 0, TIFFTileSize(tif)); + TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw); + TIFFGetField(tif, TIFFTAG_TILELENGTH, &th); + + flip = setorientation(img); + if (flip & FLIP_VERTICALLY) { + y = h - 1; + toskew = -(int32)(tw + w); + } + else { + y = 0; + toskew = -(int32)(tw - w); + } + + for (row = 0; row < h; row += nrow) + { + rowstoread = th - (row + img->row_offset) % th; + nrow = (row + rowstoread > h ? h - row : rowstoread); + for (col = 0; col < w; col += tw) + { + if (TIFFReadTile(tif, buf, col+img->col_offset, + row+img->row_offset, 0, 0) < 0 && img->stoponerr) + { + ret = 0; + break; + } + + pos = ((row+img->row_offset) % th) * TIFFTileRowSize(tif); + + if (col + tw > w) + { + /* + * Tile is clipped horizontally. Calculate + * visible portion and skewing factors. + */ + uint32 npix = w - col; + fromskew = tw - npix; + (*put)(img, raster+y*w+col, col, y, + npix, nrow, fromskew, toskew + fromskew, buf + pos); + } + else + { + (*put)(img, raster+y*w+col, col, y, tw, nrow, 0, toskew, buf + pos); + } + } + + y += (flip & FLIP_VERTICALLY ? -(int32) nrow : (int32) nrow); + } + _TIFFfree(buf); + + if (flip & FLIP_HORIZONTALLY) { + uint32 line; + + for (line = 0; line < h; line++) { + uint32 *left = raster + (line * w); + uint32 *right = left + w - 1; + + while ( left < right ) { + uint32 temp = *left; + *left = *right; + *right = temp; + left++, right--; + } + } + } + + return (ret); +} + +/* + * Get an tile-organized image that has + * SamplesPerPixel > 1 + * PlanarConfiguration separated + * We assume that all such images are RGB. + */ +static int +gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) +{ + TIFF* tif = img->tif; + tileSeparateRoutine put = img->put.separate; + uint32 col, row, y, rowstoread; + uint32 pos; + uint32 tw, th; + unsigned char* buf; + unsigned char* p0; + unsigned char* p1; + unsigned char* p2; + unsigned char* pa; + tsize_t tilesize; + int32 fromskew, toskew; + int alpha = img->alpha; + uint32 nrow; + int ret = 1, flip; + + tilesize = TIFFTileSize(tif); + buf = (unsigned char*) _TIFFmalloc((alpha?4:3)*tilesize); + if (buf == 0) { + TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for tile buffer"); + return (0); + } + _TIFFmemset(buf, 0, (alpha?4:3)*tilesize); + p0 = buf; + p1 = p0 + tilesize; + p2 = p1 + tilesize; + pa = (alpha?(p2+tilesize):NULL); + TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw); + TIFFGetField(tif, TIFFTAG_TILELENGTH, &th); + + flip = setorientation(img); + if (flip & FLIP_VERTICALLY) { + y = h - 1; + toskew = -(int32)(tw + w); + } + else { + y = 0; + toskew = -(int32)(tw - w); + } + + for (row = 0; row < h; row += nrow) + { + rowstoread = th - (row + img->row_offset) % th; + nrow = (row + rowstoread > h ? h - row : rowstoread); + for (col = 0; col < w; col += tw) + { + if (TIFFReadTile(tif, p0, col+img->col_offset, + row+img->row_offset,0,0) < 0 && img->stoponerr) + { + ret = 0; + break; + } + if (TIFFReadTile(tif, p1, col+img->col_offset, + row+img->row_offset,0,1) < 0 && img->stoponerr) + { + ret = 0; + break; + } + if (TIFFReadTile(tif, p2, col+img->col_offset, + row+img->row_offset,0,2) < 0 && img->stoponerr) + { + ret = 0; + break; + } + if (alpha) + { + if (TIFFReadTile(tif,pa,col+img->col_offset, + row+img->row_offset,0,3) < 0 && img->stoponerr) + { + ret = 0; + break; + } + } + + pos = ((row+img->row_offset) % th) * TIFFTileRowSize(tif); + + if (col + tw > w) + { + /* + * Tile is clipped horizontally. Calculate + * visible portion and skewing factors. + */ + uint32 npix = w - col; + fromskew = tw - npix; + (*put)(img, raster+y*w+col, col, y, + npix, nrow, fromskew, toskew + fromskew, + p0 + pos, p1 + pos, p2 + pos, (alpha?(pa+pos):NULL)); + } else { + (*put)(img, raster+y*w+col, col, y, + tw, nrow, 0, toskew, p0 + pos, p1 + pos, p2 + pos, (alpha?(pa+pos):NULL)); + } + } + + y += (flip & FLIP_VERTICALLY ?-(int32) nrow : (int32) nrow); + } + + if (flip & FLIP_HORIZONTALLY) { + uint32 line; + + for (line = 0; line < h; line++) { + uint32 *left = raster + (line * w); + uint32 *right = left + w - 1; + + while ( left < right ) { + uint32 temp = *left; + *left = *right; + *right = temp; + left++, right--; + } + } + } + + _TIFFfree(buf); + return (ret); +} + +/* + * Get a strip-organized image that has + * PlanarConfiguration contiguous if SamplesPerPixel > 1 + * or + * SamplesPerPixel == 1 + */ +static int +gtStripContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) +{ + TIFF* tif = img->tif; + tileContigRoutine put = img->put.contig; + uint32 row, y, nrow, nrowsub, rowstoread; + uint32 pos; + unsigned char* buf; + uint32 rowsperstrip; + uint16 subsamplinghor,subsamplingver; + uint32 imagewidth = img->width; + tsize_t scanline; + int32 fromskew, toskew; + int ret = 1, flip; + + buf = (unsigned char*) _TIFFmalloc(TIFFStripSize(tif)); + if (buf == 0) { + TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for strip buffer"); + return (0); + } + _TIFFmemset(buf, 0, TIFFStripSize(tif)); + + flip = setorientation(img); + if (flip & FLIP_VERTICALLY) { + y = h - 1; + toskew = -(int32)(w + w); + } else { + y = 0; + toskew = -(int32)(w - w); + } + + TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip); + TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRSUBSAMPLING, &subsamplinghor, &subsamplingver); + scanline = TIFFNewScanlineSize(tif); + fromskew = (w < imagewidth ? imagewidth - w : 0); + for (row = 0; row < h; row += nrow) + { + rowstoread = rowsperstrip - (row + img->row_offset) % rowsperstrip; + nrow = (row + rowstoread > h ? h - row : rowstoread); + nrowsub = nrow; + if ((nrowsub%subsamplingver)!=0) + nrowsub+=subsamplingver-nrowsub%subsamplingver; + if (TIFFReadEncodedStrip(tif, + TIFFComputeStrip(tif,row+img->row_offset, 0), + buf, + ((row + img->row_offset)%rowsperstrip + nrowsub) * scanline) < 0 + && img->stoponerr) + { + ret = 0; + break; + } + + pos = ((row + img->row_offset) % rowsperstrip) * scanline; + (*put)(img, raster+y*w, 0, y, w, nrow, fromskew, toskew, buf + pos); + y += (flip & FLIP_VERTICALLY ? -(int32) nrow : (int32) nrow); + } + + if (flip & FLIP_HORIZONTALLY) { + uint32 line; + + for (line = 0; line < h; line++) { + uint32 *left = raster + (line * w); + uint32 *right = left + w - 1; + + while ( left < right ) { + uint32 temp = *left; + *left = *right; + *right = temp; + left++, right--; + } + } + } + + _TIFFfree(buf); + return (ret); +} + +/* + * Get a strip-organized image with + * SamplesPerPixel > 1 + * PlanarConfiguration separated + * We assume that all such images are RGB. + */ +static int +gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) +{ + TIFF* tif = img->tif; + tileSeparateRoutine put = img->put.separate; + unsigned char *buf; + unsigned char *p0, *p1, *p2, *pa; + uint32 row, y, nrow, rowstoread; + uint32 pos; + tsize_t scanline; + uint32 rowsperstrip, offset_row; + uint32 imagewidth = img->width; + tsize_t stripsize; + int32 fromskew, toskew; + int alpha = img->alpha; + int ret = 1, flip; + + stripsize = TIFFStripSize(tif); + p0 = buf = (unsigned char *)_TIFFmalloc((alpha?4:3)*stripsize); + if (buf == 0) { + TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for tile buffer"); + return (0); + } + _TIFFmemset(buf, 0, (alpha?4:3)*stripsize); + p1 = p0 + stripsize; + p2 = p1 + stripsize; + pa = (alpha?(p2+stripsize):NULL); + + flip = setorientation(img); + if (flip & FLIP_VERTICALLY) { + y = h - 1; + toskew = -(int32)(w + w); + } + else { + y = 0; + toskew = -(int32)(w - w); + } + + TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip); + scanline = TIFFScanlineSize(tif); + fromskew = (w < imagewidth ? imagewidth - w : 0); + for (row = 0; row < h; row += nrow) + { + rowstoread = rowsperstrip - (row + img->row_offset) % rowsperstrip; + nrow = (row + rowstoread > h ? h - row : rowstoread); + offset_row = row + img->row_offset; + if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 0), + p0, ((row + img->row_offset)%rowsperstrip + nrow) * scanline) < 0 + && img->stoponerr) + { + ret = 0; + break; + } + if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 1), + p1, ((row + img->row_offset)%rowsperstrip + nrow) * scanline) < 0 + && img->stoponerr) + { + ret = 0; + break; + } + if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 2), + p2, ((row + img->row_offset)%rowsperstrip + nrow) * scanline) < 0 + && img->stoponerr) + { + ret = 0; + break; + } + if (alpha) + { + if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 3), + pa, ((row + img->row_offset)%rowsperstrip + nrow) * scanline) < 0 + && img->stoponerr) + { + ret = 0; + break; + } + } + + pos = ((row + img->row_offset) % rowsperstrip) * scanline; + (*put)(img, raster+y*w, 0, y, w, nrow, fromskew, toskew, p0 + pos, p1 + pos, + p2 + pos, (alpha?(pa+pos):NULL)); + y += (flip & FLIP_VERTICALLY ? -(int32) nrow : (int32) nrow); + } + + if (flip & FLIP_HORIZONTALLY) { + uint32 line; + + for (line = 0; line < h; line++) { + uint32 *left = raster + (line * w); + uint32 *right = left + w - 1; + + while ( left < right ) { + uint32 temp = *left; + *left = *right; + *right = temp; + left++, right--; + } + } + } + + _TIFFfree(buf); + return (ret); +} + +/* + * The following routines move decoded data returned + * from the TIFF library into rasters filled with packed + * ABGR pixels (i.e. suitable for passing to lrecwrite.) + * + * The routines have been created according to the most + * important cases and optimized. PickContigCase and + * PickSeparateCase analyze the parameters and select + * the appropriate "get" and "put" routine to use. + */ +#define REPEAT8(op) REPEAT4(op); REPEAT4(op) +#define REPEAT4(op) REPEAT2(op); REPEAT2(op) +#define REPEAT2(op) op; op +#define CASE8(x,op) \ + switch (x) { \ + case 7: op; case 6: op; case 5: op; \ + case 4: op; case 3: op; case 2: op; \ + case 1: op; \ + } +#define CASE4(x,op) switch (x) { case 3: op; case 2: op; case 1: op; } +#define NOP + +#define UNROLL8(w, op1, op2) { \ + uint32 _x; \ + for (_x = w; _x >= 8; _x -= 8) { \ + op1; \ + REPEAT8(op2); \ + } \ + if (_x > 0) { \ + op1; \ + CASE8(_x,op2); \ + } \ +} +#define UNROLL4(w, op1, op2) { \ + uint32 _x; \ + for (_x = w; _x >= 4; _x -= 4) { \ + op1; \ + REPEAT4(op2); \ + } \ + if (_x > 0) { \ + op1; \ + CASE4(_x,op2); \ + } \ +} +#define UNROLL2(w, op1, op2) { \ + uint32 _x; \ + for (_x = w; _x >= 2; _x -= 2) { \ + op1; \ + REPEAT2(op2); \ + } \ + if (_x) { \ + op1; \ + op2; \ + } \ +} + +#define SKEW(r,g,b,skew) { r += skew; g += skew; b += skew; } +#define SKEW4(r,g,b,a,skew) { r += skew; g += skew; b += skew; a+= skew; } + +#define A1 (((uint32)0xffL)<<24) +#define PACK(r,g,b) \ + ((uint32)(r)|((uint32)(g)<<8)|((uint32)(b)<<16)|A1) +#define PACK4(r,g,b,a) \ + ((uint32)(r)|((uint32)(g)<<8)|((uint32)(b)<<16)|((uint32)(a)<<24)) +#define W2B(v) (((v)>>8)&0xff) +#define PACKW(r,g,b) \ + ((uint32)W2B(r)|((uint32)W2B(g)<<8)|((uint32)W2B(b)<<16)|A1) +#define PACKW4(r,g,b,a) \ + ((uint32)W2B(r)|((uint32)W2B(g)<<8)|((uint32)W2B(b)<<16)|((uint32)W2B(a)<<24)) + +#define DECLAREContigPutFunc(name) \ +static void name(\ + TIFFRGBAImage* img, \ + uint32* cp, \ + uint32 x, uint32 y, \ + uint32 w, uint32 h, \ + int32 fromskew, int32 toskew, \ + unsigned char* pp \ +) + +/* + * 8-bit palette => colormap/RGB + */ +DECLAREContigPutFunc(put8bitcmaptile) +{ + uint32** PALmap = img->PALmap; + int samplesperpixel = img->samplesperpixel; + + (void) y; + while (h-- > 0) { + for (x = w; x-- > 0;) + { + *cp++ = PALmap[*pp][0]; + pp += samplesperpixel; + } + cp += toskew; + pp += fromskew; + } +} + +/* + * 4-bit palette => colormap/RGB + */ +DECLAREContigPutFunc(put4bitcmaptile) +{ + uint32** PALmap = img->PALmap; + + (void) x; (void) y; + fromskew /= 2; + while (h-- > 0) { + uint32* bw; + UNROLL2(w, bw = PALmap[*pp++], *cp++ = *bw++); + cp += toskew; + pp += fromskew; + } +} + +/* + * 2-bit palette => colormap/RGB + */ +DECLAREContigPutFunc(put2bitcmaptile) +{ + uint32** PALmap = img->PALmap; + + (void) x; (void) y; + fromskew /= 4; + while (h-- > 0) { + uint32* bw; + UNROLL4(w, bw = PALmap[*pp++], *cp++ = *bw++); + cp += toskew; + pp += fromskew; + } +} + +/* + * 1-bit palette => colormap/RGB + */ +DECLAREContigPutFunc(put1bitcmaptile) +{ + uint32** PALmap = img->PALmap; + + (void) x; (void) y; + fromskew /= 8; + while (h-- > 0) { + uint32* bw; + UNROLL8(w, bw = PALmap[*pp++], *cp++ = *bw++); + cp += toskew; + pp += fromskew; + } +} + +/* + * 8-bit greyscale => colormap/RGB + */ +DECLAREContigPutFunc(putgreytile) +{ + int samplesperpixel = img->samplesperpixel; + uint32** BWmap = img->BWmap; + + (void) y; + while (h-- > 0) { + for (x = w; x-- > 0;) + { + *cp++ = BWmap[*pp][0]; + pp += samplesperpixel; + } + cp += toskew; + pp += fromskew; + } +} + +/* + * 16-bit greyscale => colormap/RGB + */ +DECLAREContigPutFunc(put16bitbwtile) +{ + int samplesperpixel = img->samplesperpixel; + uint32** BWmap = img->BWmap; + + (void) y; + while (h-- > 0) { + uint16 *wp = (uint16 *) pp; + + for (x = w; x-- > 0;) + { + /* use high order byte of 16bit value */ + + *cp++ = BWmap[*wp >> 8][0]; + pp += 2 * samplesperpixel; + wp += samplesperpixel; + } + cp += toskew; + pp += fromskew; + } +} + +/* + * 1-bit bilevel => colormap/RGB + */ +DECLAREContigPutFunc(put1bitbwtile) +{ + uint32** BWmap = img->BWmap; + + (void) x; (void) y; + fromskew /= 8; + while (h-- > 0) { + uint32* bw; + UNROLL8(w, bw = BWmap[*pp++], *cp++ = *bw++); + cp += toskew; + pp += fromskew; + } +} + +/* + * 2-bit greyscale => colormap/RGB + */ +DECLAREContigPutFunc(put2bitbwtile) +{ + uint32** BWmap = img->BWmap; + + (void) x; (void) y; + fromskew /= 4; + while (h-- > 0) { + uint32* bw; + UNROLL4(w, bw = BWmap[*pp++], *cp++ = *bw++); + cp += toskew; + pp += fromskew; + } +} + +/* + * 4-bit greyscale => colormap/RGB + */ +DECLAREContigPutFunc(put4bitbwtile) +{ + uint32** BWmap = img->BWmap; + + (void) x; (void) y; + fromskew /= 2; + while (h-- > 0) { + uint32* bw; + UNROLL2(w, bw = BWmap[*pp++], *cp++ = *bw++); + cp += toskew; + pp += fromskew; + } +} + +/* + * 8-bit packed samples, no Map => RGB + */ +DECLAREContigPutFunc(putRGBcontig8bittile) +{ + int samplesperpixel = img->samplesperpixel; + + (void) x; (void) y; + fromskew *= samplesperpixel; + while (h-- > 0) { + UNROLL8(w, NOP, + *cp++ = PACK(pp[0], pp[1], pp[2]); + pp += samplesperpixel); + cp += toskew; + pp += fromskew; + } +} + +/* + * 8-bit packed samples => RGBA w/ associated alpha + * (known to have Map == NULL) + */ +DECLAREContigPutFunc(putRGBAAcontig8bittile) +{ + int samplesperpixel = img->samplesperpixel; + + (void) x; (void) y; + fromskew *= samplesperpixel; + while (h-- > 0) { + UNROLL8(w, NOP, + *cp++ = PACK4(pp[0], pp[1], pp[2], pp[3]); + pp += samplesperpixel); + cp += toskew; + pp += fromskew; + } +} + +/* + * 8-bit packed samples => RGBA w/ unassociated alpha + * (known to have Map == NULL) + */ +DECLAREContigPutFunc(putRGBUAcontig8bittile) +{ + int samplesperpixel = img->samplesperpixel; + (void) y; + fromskew *= samplesperpixel; + while (h-- > 0) { + uint32 r, g, b, a; + for (x = w; x-- > 0;) { + a = pp[3]; + r = (a*pp[0] + 127) / 255; + g = (a*pp[1] + 127) / 255; + b = (a*pp[2] + 127) / 255; + *cp++ = PACK4(r,g,b,a); + pp += samplesperpixel; + } + cp += toskew; + pp += fromskew; + } +} + +/* + * 16-bit packed samples => RGB + */ +DECLAREContigPutFunc(putRGBcontig16bittile) +{ + int samplesperpixel = img->samplesperpixel; + uint16 *wp = (uint16 *)pp; + (void) y; + fromskew *= samplesperpixel; + while (h-- > 0) { + for (x = w; x-- > 0;) { + *cp++ = PACKW(wp[0],wp[1],wp[2]); + wp += samplesperpixel; + } + cp += toskew; + wp += fromskew; + } +} + +/* + * 16-bit packed samples => RGBA w/ associated alpha + * (known to have Map == NULL) + */ +DECLAREContigPutFunc(putRGBAAcontig16bittile) +{ + int samplesperpixel = img->samplesperpixel; + uint16 *wp = (uint16 *)pp; + (void) y; + fromskew *= samplesperpixel; + while (h-- > 0) { + for (x = w; x-- > 0;) { + *cp++ = PACKW4(wp[0],wp[1],wp[2],wp[3]); + wp += samplesperpixel; + } + cp += toskew; + wp += fromskew; + } +} + +/* + * 16-bit packed samples => RGBA w/ unassociated alpha + * (known to have Map == NULL) + */ +DECLAREContigPutFunc(putRGBUAcontig16bittile) +{ + int samplesperpixel = img->samplesperpixel; + uint16 *wp = (uint16 *)pp; + (void) y; + fromskew *= samplesperpixel; + while (h-- > 0) { + uint32 r,g,b,a; + for (x = w; x-- > 0;) { + a = W2B(wp[3]); + r = (a*W2B(wp[0]) + 127) / 255; + g = (a*W2B(wp[1]) + 127) / 255; + b = (a*W2B(wp[2]) + 127) / 255; + *cp++ = PACK4(r,g,b,a); + wp += samplesperpixel; + } + cp += toskew; + wp += fromskew; + } +} + +/* + * 8-bit packed CMYK samples w/o Map => RGB + * + * NB: The conversion of CMYK->RGB is *very* crude. + */ +DECLAREContigPutFunc(putRGBcontig8bitCMYKtile) +{ + int samplesperpixel = img->samplesperpixel; + uint16 r, g, b, k; + + (void) x; (void) y; + fromskew *= samplesperpixel; + while (h-- > 0) { + UNROLL8(w, NOP, + k = 255 - pp[3]; + r = (k*(255-pp[0]))/255; + g = (k*(255-pp[1]))/255; + b = (k*(255-pp[2]))/255; + *cp++ = PACK(r, g, b); + pp += samplesperpixel); + cp += toskew; + pp += fromskew; + } +} + +/* + * 8-bit packed CMYK samples w/Map => RGB + * + * NB: The conversion of CMYK->RGB is *very* crude. + */ +DECLAREContigPutFunc(putRGBcontig8bitCMYKMaptile) +{ + int samplesperpixel = img->samplesperpixel; + TIFFRGBValue* Map = img->Map; + uint16 r, g, b, k; + + (void) y; + fromskew *= samplesperpixel; + while (h-- > 0) { + for (x = w; x-- > 0;) { + k = 255 - pp[3]; + r = (k*(255-pp[0]))/255; + g = (k*(255-pp[1]))/255; + b = (k*(255-pp[2]))/255; + *cp++ = PACK(Map[r], Map[g], Map[b]); + pp += samplesperpixel; + } + pp += fromskew; + cp += toskew; + } +} + +#define DECLARESepPutFunc(name) \ +static void name(\ + TIFFRGBAImage* img,\ + uint32* cp,\ + uint32 x, uint32 y, \ + uint32 w, uint32 h,\ + int32 fromskew, int32 toskew,\ + unsigned char* r, unsigned char* g, unsigned char* b, unsigned char* a\ +) + +/* + * 8-bit unpacked samples => RGB + */ +DECLARESepPutFunc(putRGBseparate8bittile) +{ + (void) img; (void) x; (void) y; (void) a; + while (h-- > 0) { + UNROLL8(w, NOP, *cp++ = PACK(*r++, *g++, *b++)); + SKEW(r, g, b, fromskew); + cp += toskew; + } +} + +/* + * 8-bit unpacked samples => RGBA w/ associated alpha + */ +DECLARESepPutFunc(putRGBAAseparate8bittile) +{ + (void) img; (void) x; (void) y; + while (h-- > 0) { + UNROLL8(w, NOP, *cp++ = PACK4(*r++, *g++, *b++, *a++)); + SKEW4(r, g, b, a, fromskew); + cp += toskew; + } +} + +/* + * 8-bit unpacked samples => RGBA w/ unassociated alpha + */ +DECLARESepPutFunc(putRGBUAseparate8bittile) +{ + (void) img; (void) y; + while (h-- > 0) { + uint32 rv, gv, bv, av; + for (x = w; x-- > 0;) { + av = *a++; + rv = (av* *r++ + 127) / 255; + gv = (av* *g++ + 127) / 255; + bv = (av* *b++ + 127) / 255; + *cp++ = PACK4(rv,gv,bv,av); + } + SKEW4(r, g, b, a, fromskew); + cp += toskew; + } +} + +/* + * 16-bit unpacked samples => RGB + */ +DECLARESepPutFunc(putRGBseparate16bittile) +{ + uint16 *wr = (uint16*) r; + uint16 *wg = (uint16*) g; + uint16 *wb = (uint16*) b; + (void) img; (void) y; (void) a; + while (h-- > 0) { + for (x = 0; x < w; x++) + *cp++ = PACKW(*wr++,*wg++,*wb++); + SKEW(wr, wg, wb, fromskew); + cp += toskew; + } +} + +/* + * 16-bit unpacked samples => RGBA w/ associated alpha + */ +DECLARESepPutFunc(putRGBAAseparate16bittile) +{ + uint16 *wr = (uint16*) r; + uint16 *wg = (uint16*) g; + uint16 *wb = (uint16*) b; + uint16 *wa = (uint16*) a; + (void) img; (void) y; + while (h-- > 0) { + for (x = 0; x < w; x++) + *cp++ = PACKW4(*wr++,*wg++,*wb++,*wa++); + SKEW4(wr, wg, wb, wa, fromskew); + cp += toskew; + } +} + +/* + * 16-bit unpacked samples => RGBA w/ unassociated alpha + */ +DECLARESepPutFunc(putRGBUAseparate16bittile) +{ + uint16 *wr = (uint16*) r; + uint16 *wg = (uint16*) g; + uint16 *wb = (uint16*) b; + uint16 *wa = (uint16*) a; + (void) img; (void) y; + while (h-- > 0) { + uint32 r,g,b,a; + for (x = w; x-- > 0;) { + a = W2B(*wa++); + r = (a*W2B(*wr++) + 127) / 255; + g = (a*W2B(*wg++) + 127) / 255; + b = (a*W2B(*wb++) + 127) / 255; + *cp++ = PACK4(r,g,b,a); + } + SKEW4(wr, wg, wb, wa, fromskew); + cp += toskew; + } +} + +/* + * 8-bit packed CIE L*a*b 1976 samples => RGB + */ +DECLAREContigPutFunc(putcontig8bitCIELab) +{ + float X, Y, Z; + uint32 r, g, b; + (void) y; + fromskew *= 3; + while (h-- > 0) { + for (x = w; x-- > 0;) { + TIFFCIELabToXYZ(img->cielab, + (unsigned char)pp[0], + (signed char)pp[1], + (signed char)pp[2], + &X, &Y, &Z); + TIFFXYZToRGB(img->cielab, X, Y, Z, &r, &g, &b); + *cp++ = PACK(r, g, b); + pp += 3; + } + cp += toskew; + pp += fromskew; + } +} + +/* + * YCbCr -> RGB conversion and packing routines. + */ + +#define YCbCrtoRGB(dst, Y) { \ + uint32 r, g, b; \ + TIFFYCbCrtoRGB(img->ycbcr, (Y), Cb, Cr, &r, &g, &b); \ + dst = PACK(r, g, b); \ +} + +/* + * 8-bit packed YCbCr samples => RGB + * This function is generic for different sampling sizes, + * and can handle blocks sizes that aren't multiples of the + * sampling size. However, it is substantially less optimized + * than the specific sampling cases. It is used as a fallback + * for difficult blocks. + */ +#ifdef notdef +static void putcontig8bitYCbCrGenericTile( + TIFFRGBAImage* img, + uint32* cp, + uint32 x, uint32 y, + uint32 w, uint32 h, + int32 fromskew, int32 toskew, + unsigned char* pp, + int h_group, + int v_group ) + +{ + uint32* cp1 = cp+w+toskew; + uint32* cp2 = cp1+w+toskew; + uint32* cp3 = cp2+w+toskew; + int32 incr = 3*w+4*toskew; + int32 Cb, Cr; + int group_size = v_group * h_group + 2; + + (void) y; + fromskew = (fromskew * group_size) / h_group; + + for( yy = 0; yy < h; yy++ ) + { + unsigned char *pp_line; + int y_line_group = yy / v_group; + int y_remainder = yy - y_line_group * v_group; + + pp_line = pp + v_line_group * + + + for( xx = 0; xx < w; xx++ ) + { + Cb = pp + } + } + for (; h >= 4; h -= 4) { + x = w>>2; + do { + Cb = pp[16]; + Cr = pp[17]; + + YCbCrtoRGB(cp [0], pp[ 0]); + YCbCrtoRGB(cp [1], pp[ 1]); + YCbCrtoRGB(cp [2], pp[ 2]); + YCbCrtoRGB(cp [3], pp[ 3]); + YCbCrtoRGB(cp1[0], pp[ 4]); + YCbCrtoRGB(cp1[1], pp[ 5]); + YCbCrtoRGB(cp1[2], pp[ 6]); + YCbCrtoRGB(cp1[3], pp[ 7]); + YCbCrtoRGB(cp2[0], pp[ 8]); + YCbCrtoRGB(cp2[1], pp[ 9]); + YCbCrtoRGB(cp2[2], pp[10]); + YCbCrtoRGB(cp2[3], pp[11]); + YCbCrtoRGB(cp3[0], pp[12]); + YCbCrtoRGB(cp3[1], pp[13]); + YCbCrtoRGB(cp3[2], pp[14]); + YCbCrtoRGB(cp3[3], pp[15]); + + cp += 4, cp1 += 4, cp2 += 4, cp3 += 4; + pp += 18; + } while (--x); + cp += incr, cp1 += incr, cp2 += incr, cp3 += incr; + pp += fromskew; + } +} +#endif + +/* + * 8-bit packed YCbCr samples w/ 4,4 subsampling => RGB + */ +DECLAREContigPutFunc(putcontig8bitYCbCr44tile) +{ + uint32* cp1 = cp+w+toskew; + uint32* cp2 = cp1+w+toskew; + uint32* cp3 = cp2+w+toskew; + int32 incr = 3*w+4*toskew; + + (void) y; + /* adjust fromskew */ + fromskew = (fromskew * 18) / 4; + if ((h & 3) == 0 && (w & 3) == 0) { + for (; h >= 4; h -= 4) { + x = w>>2; + do { + int32 Cb = pp[16]; + int32 Cr = pp[17]; + + YCbCrtoRGB(cp [0], pp[ 0]); + YCbCrtoRGB(cp [1], pp[ 1]); + YCbCrtoRGB(cp [2], pp[ 2]); + YCbCrtoRGB(cp [3], pp[ 3]); + YCbCrtoRGB(cp1[0], pp[ 4]); + YCbCrtoRGB(cp1[1], pp[ 5]); + YCbCrtoRGB(cp1[2], pp[ 6]); + YCbCrtoRGB(cp1[3], pp[ 7]); + YCbCrtoRGB(cp2[0], pp[ 8]); + YCbCrtoRGB(cp2[1], pp[ 9]); + YCbCrtoRGB(cp2[2], pp[10]); + YCbCrtoRGB(cp2[3], pp[11]); + YCbCrtoRGB(cp3[0], pp[12]); + YCbCrtoRGB(cp3[1], pp[13]); + YCbCrtoRGB(cp3[2], pp[14]); + YCbCrtoRGB(cp3[3], pp[15]); + + cp += 4, cp1 += 4, cp2 += 4, cp3 += 4; + pp += 18; + } while (--x); + cp += incr, cp1 += incr, cp2 += incr, cp3 += incr; + pp += fromskew; + } + } else { + while (h > 0) { + for (x = w; x > 0;) { + int32 Cb = pp[16]; + int32 Cr = pp[17]; + switch (x) { + default: + switch (h) { + default: YCbCrtoRGB(cp3[3], pp[15]); /* FALLTHROUGH */ + case 3: YCbCrtoRGB(cp2[3], pp[11]); /* FALLTHROUGH */ + case 2: YCbCrtoRGB(cp1[3], pp[ 7]); /* FALLTHROUGH */ + case 1: YCbCrtoRGB(cp [3], pp[ 3]); /* FALLTHROUGH */ + } /* FALLTHROUGH */ + case 3: + switch (h) { + default: YCbCrtoRGB(cp3[2], pp[14]); /* FALLTHROUGH */ + case 3: YCbCrtoRGB(cp2[2], pp[10]); /* FALLTHROUGH */ + case 2: YCbCrtoRGB(cp1[2], pp[ 6]); /* FALLTHROUGH */ + case 1: YCbCrtoRGB(cp [2], pp[ 2]); /* FALLTHROUGH */ + } /* FALLTHROUGH */ + case 2: + switch (h) { + default: YCbCrtoRGB(cp3[1], pp[13]); /* FALLTHROUGH */ + case 3: YCbCrtoRGB(cp2[1], pp[ 9]); /* FALLTHROUGH */ + case 2: YCbCrtoRGB(cp1[1], pp[ 5]); /* FALLTHROUGH */ + case 1: YCbCrtoRGB(cp [1], pp[ 1]); /* FALLTHROUGH */ + } /* FALLTHROUGH */ + case 1: + switch (h) { + default: YCbCrtoRGB(cp3[0], pp[12]); /* FALLTHROUGH */ + case 3: YCbCrtoRGB(cp2[0], pp[ 8]); /* FALLTHROUGH */ + case 2: YCbCrtoRGB(cp1[0], pp[ 4]); /* FALLTHROUGH */ + case 1: YCbCrtoRGB(cp [0], pp[ 0]); /* FALLTHROUGH */ + } /* FALLTHROUGH */ + } + if (x < 4) { + cp += x; cp1 += x; cp2 += x; cp3 += x; + x = 0; + } + else { + cp += 4; cp1 += 4; cp2 += 4; cp3 += 4; + x -= 4; + } + pp += 18; + } + if (h <= 4) + break; + h -= 4; + cp += incr, cp1 += incr, cp2 += incr, cp3 += incr; + pp += fromskew; + } + } +} + +/* + * 8-bit packed YCbCr samples w/ 4,2 subsampling => RGB + */ +DECLAREContigPutFunc(putcontig8bitYCbCr42tile) +{ + uint32* cp1 = cp+w+toskew; + int32 incr = 2*toskew+w; + + (void) y; + fromskew = (fromskew * 10) / 4; + if ((h & 3) == 0 && (w & 1) == 0) { + for (; h >= 2; h -= 2) { + x = w>>2; + do { + int32 Cb = pp[8]; + int32 Cr = pp[9]; + + YCbCrtoRGB(cp [0], pp[0]); + YCbCrtoRGB(cp [1], pp[1]); + YCbCrtoRGB(cp [2], pp[2]); + YCbCrtoRGB(cp [3], pp[3]); + YCbCrtoRGB(cp1[0], pp[4]); + YCbCrtoRGB(cp1[1], pp[5]); + YCbCrtoRGB(cp1[2], pp[6]); + YCbCrtoRGB(cp1[3], pp[7]); + + cp += 4, cp1 += 4; + pp += 10; + } while (--x); + cp += incr, cp1 += incr; + pp += fromskew; + } + } else { + while (h > 0) { + for (x = w; x > 0;) { + int32 Cb = pp[8]; + int32 Cr = pp[9]; + switch (x) { + default: + switch (h) { + default: YCbCrtoRGB(cp1[3], pp[ 7]); /* FALLTHROUGH */ + case 1: YCbCrtoRGB(cp [3], pp[ 3]); /* FALLTHROUGH */ + } /* FALLTHROUGH */ + case 3: + switch (h) { + default: YCbCrtoRGB(cp1[2], pp[ 6]); /* FALLTHROUGH */ + case 1: YCbCrtoRGB(cp [2], pp[ 2]); /* FALLTHROUGH */ + } /* FALLTHROUGH */ + case 2: + switch (h) { + default: YCbCrtoRGB(cp1[1], pp[ 5]); /* FALLTHROUGH */ + case 1: YCbCrtoRGB(cp [1], pp[ 1]); /* FALLTHROUGH */ + } /* FALLTHROUGH */ + case 1: + switch (h) { + default: YCbCrtoRGB(cp1[0], pp[ 4]); /* FALLTHROUGH */ + case 1: YCbCrtoRGB(cp [0], pp[ 0]); /* FALLTHROUGH */ + } /* FALLTHROUGH */ + } + if (x < 4) { + cp += x; cp1 += x; + x = 0; + } + else { + cp += 4; cp1 += 4; + x -= 4; + } + pp += 10; + } + if (h <= 2) + break; + h -= 2; + cp += incr, cp1 += incr; + pp += fromskew; + } + } +} + +/* + * 8-bit packed YCbCr samples w/ 4,1 subsampling => RGB + */ +DECLAREContigPutFunc(putcontig8bitYCbCr41tile) +{ + (void) y; + /* XXX adjust fromskew */ + do { + x = w>>2; + do { + int32 Cb = pp[4]; + int32 Cr = pp[5]; + + YCbCrtoRGB(cp [0], pp[0]); + YCbCrtoRGB(cp [1], pp[1]); + YCbCrtoRGB(cp [2], pp[2]); + YCbCrtoRGB(cp [3], pp[3]); + + cp += 4; + pp += 6; + } while (--x); + + if( (w&3) != 0 ) + { + int32 Cb = pp[4]; + int32 Cr = pp[5]; + + switch( (w&3) ) { + case 3: YCbCrtoRGB(cp [2], pp[2]); + case 2: YCbCrtoRGB(cp [1], pp[1]); + case 1: YCbCrtoRGB(cp [0], pp[0]); + case 0: break; + } + + cp += (w&3); + pp += 6; + } + + cp += toskew; + pp += fromskew; + } while (--h); + +} + +/* + * 8-bit packed YCbCr samples w/ 2,2 subsampling => RGB + */ +DECLAREContigPutFunc(putcontig8bitYCbCr22tile) +{ + uint32* cp2; + (void) y; + fromskew = (fromskew / 2) * 6; + cp2 = cp+w+toskew; + while (h>=2) { + x = w; + while (x>=2) { + uint32 Cb = pp[4]; + uint32 Cr = pp[5]; + YCbCrtoRGB(cp[0], pp[0]); + YCbCrtoRGB(cp[1], pp[1]); + YCbCrtoRGB(cp2[0], pp[2]); + YCbCrtoRGB(cp2[1], pp[3]); + cp += 2; + cp2 += 2; + pp += 6; + x -= 2; + } + if (x==1) { + uint32 Cb = pp[4]; + uint32 Cr = pp[5]; + YCbCrtoRGB(cp[0], pp[0]); + YCbCrtoRGB(cp2[0], pp[2]); + cp ++ ; + cp2 ++ ; + pp += 6; + } + cp += toskew*2+w; + cp2 += toskew*2+w; + pp += fromskew; + h-=2; + } + if (h==1) { + x = w; + while (x>=2) { + uint32 Cb = pp[4]; + uint32 Cr = pp[5]; + YCbCrtoRGB(cp[0], pp[0]); + YCbCrtoRGB(cp[1], pp[1]); + cp += 2; + cp2 += 2; + pp += 6; + x -= 2; + } + if (x==1) { + uint32 Cb = pp[4]; + uint32 Cr = pp[5]; + YCbCrtoRGB(cp[0], pp[0]); + } + } +} + +/* + * 8-bit packed YCbCr samples w/ 2,1 subsampling => RGB + */ +DECLAREContigPutFunc(putcontig8bitYCbCr21tile) +{ + (void) y; + fromskew = (fromskew * 4) / 2; + do { + x = w>>1; + do { + int32 Cb = pp[2]; + int32 Cr = pp[3]; + + YCbCrtoRGB(cp[0], pp[0]); + YCbCrtoRGB(cp[1], pp[1]); + + cp += 2; + pp += 4; + } while (--x); + + if( (w&1) != 0 ) + { + int32 Cb = pp[2]; + int32 Cr = pp[3]; + + YCbCrtoRGB(cp[0], pp[0]); + + cp += 1; + pp += 4; + } + + cp += toskew; + pp += fromskew; + } while (--h); +} + +/* + * 8-bit packed YCbCr samples w/ 1,2 subsampling => RGB + */ +DECLAREContigPutFunc(putcontig8bitYCbCr12tile) +{ + uint32* cp2; + (void) y; + fromskew = (fromskew / 2) * 4; + cp2 = cp+w+toskew; + while (h>=2) { + x = w; + do { + uint32 Cb = pp[2]; + uint32 Cr = pp[3]; + YCbCrtoRGB(cp[0], pp[0]); + YCbCrtoRGB(cp2[0], pp[1]); + cp ++; + cp2 ++; + pp += 4; + } while (--x); + cp += toskew*2+w; + cp2 += toskew*2+w; + pp += fromskew; + h-=2; + } + if (h==1) { + x = w; + do { + uint32 Cb = pp[2]; + uint32 Cr = pp[3]; + YCbCrtoRGB(cp[0], pp[0]); + cp ++; + pp += 4; + } while (--x); + } +} + +/* + * 8-bit packed YCbCr samples w/ no subsampling => RGB + */ +DECLAREContigPutFunc(putcontig8bitYCbCr11tile) +{ + (void) y; + fromskew *= 3; + do { + x = w; /* was x = w>>1; patched 2000/09/25 warmerda@home.com */ + do { + int32 Cb = pp[1]; + int32 Cr = pp[2]; + + YCbCrtoRGB(*cp++, pp[0]); + + pp += 3; + } while (--x); + cp += toskew; + pp += fromskew; + } while (--h); +} + +/* + * 8-bit packed YCbCr samples w/ no subsampling => RGB + */ +DECLARESepPutFunc(putseparate8bitYCbCr11tile) +{ + (void) y; + (void) a; + /* TODO: naming of input vars is still off, change obfuscating declaration inside define, or resolve obfuscation */ + while (h-- > 0) { + x = w; + do { + uint32 dr, dg, db; + TIFFYCbCrtoRGB(img->ycbcr,*r++,*g++,*b++,&dr,&dg,&db); + *cp++ = PACK(dr,dg,db); + } while (--x); + SKEW(r, g, b, fromskew); + cp += toskew; + } +} +#undef YCbCrtoRGB + +static int +initYCbCrConversion(TIFFRGBAImage* img) +{ + static char module[] = "initYCbCrConversion"; + + float *luma, *refBlackWhite; + + if (img->ycbcr == NULL) { + img->ycbcr = (TIFFYCbCrToRGB*) _TIFFmalloc( + TIFFroundup(sizeof (TIFFYCbCrToRGB), sizeof (long)) + + 4*256*sizeof (TIFFRGBValue) + + 2*256*sizeof (int) + + 3*256*sizeof (int32) + ); + if (img->ycbcr == NULL) { + TIFFErrorExt(img->tif->tif_clientdata, module, + "No space for YCbCr->RGB conversion state"); + return (0); + } + } + + TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRCOEFFICIENTS, &luma); + TIFFGetFieldDefaulted(img->tif, TIFFTAG_REFERENCEBLACKWHITE, + &refBlackWhite); + if (TIFFYCbCrToRGBInit(img->ycbcr, luma, refBlackWhite) < 0) + return(0); + return (1); +} + +static tileContigRoutine +initCIELabConversion(TIFFRGBAImage* img) +{ + static char module[] = "initCIELabConversion"; + + float *whitePoint; + float refWhite[3]; + + if (!img->cielab) { + img->cielab = (TIFFCIELabToRGB *) + _TIFFmalloc(sizeof(TIFFCIELabToRGB)); + if (!img->cielab) { + TIFFErrorExt(img->tif->tif_clientdata, module, + "No space for CIE L*a*b*->RGB conversion state."); + return NULL; + } + } + + TIFFGetFieldDefaulted(img->tif, TIFFTAG_WHITEPOINT, &whitePoint); + refWhite[1] = 100.0F; + refWhite[0] = whitePoint[0] / whitePoint[1] * refWhite[1]; + refWhite[2] = (1.0F - whitePoint[0] - whitePoint[1]) + / whitePoint[1] * refWhite[1]; + if (TIFFCIELabToRGBInit(img->cielab, &display_sRGB, refWhite) < 0) { + TIFFErrorExt(img->tif->tif_clientdata, module, + "Failed to initialize CIE L*a*b*->RGB conversion state."); + _TIFFfree(img->cielab); + return NULL; + } + + return putcontig8bitCIELab; +} + +/* + * Greyscale images with less than 8 bits/sample are handled + * with a table to avoid lots of shifts and masks. The table + * is setup so that put*bwtile (below) can retrieve 8/bitspersample + * pixel values simply by indexing into the table with one + * number. + */ +static int +makebwmap(TIFFRGBAImage* img) +{ + TIFFRGBValue* Map = img->Map; + int bitspersample = img->bitspersample; + int nsamples = 8 / bitspersample; + int i; + uint32* p; + + if( nsamples == 0 ) + nsamples = 1; + + img->BWmap = (uint32**) _TIFFmalloc( + 256*sizeof (uint32 *)+(256*nsamples*sizeof(uint32))); + if (img->BWmap == NULL) { + TIFFErrorExt(img->tif->tif_clientdata, TIFFFileName(img->tif), "No space for B&W mapping table"); + return (0); + } + p = (uint32*)(img->BWmap + 256); + for (i = 0; i < 256; i++) { + TIFFRGBValue c; + img->BWmap[i] = p; + switch (bitspersample) { +#define GREY(x) c = Map[x]; *p++ = PACK(c,c,c); + case 1: + GREY(i>>7); + GREY((i>>6)&1); + GREY((i>>5)&1); + GREY((i>>4)&1); + GREY((i>>3)&1); + GREY((i>>2)&1); + GREY((i>>1)&1); + GREY(i&1); + break; + case 2: + GREY(i>>6); + GREY((i>>4)&3); + GREY((i>>2)&3); + GREY(i&3); + break; + case 4: + GREY(i>>4); + GREY(i&0xf); + break; + case 8: + case 16: + GREY(i); + break; + } +#undef GREY + } + return (1); +} + +/* + * Construct a mapping table to convert from the range + * of the data samples to [0,255] --for display. This + * process also handles inverting B&W images when needed. + */ +static int +setupMap(TIFFRGBAImage* img) +{ + int32 x, range; + + range = (int32)((1L<bitspersample)-1); + + /* treat 16 bit the same as eight bit */ + if( img->bitspersample == 16 ) + range = (int32) 255; + + img->Map = (TIFFRGBValue*) _TIFFmalloc((range+1) * sizeof (TIFFRGBValue)); + if (img->Map == NULL) { + TIFFErrorExt(img->tif->tif_clientdata, TIFFFileName(img->tif), + "No space for photometric conversion table"); + return (0); + } + if (img->photometric == PHOTOMETRIC_MINISWHITE) { + for (x = 0; x <= range; x++) + img->Map[x] = (TIFFRGBValue) (((range - x) * 255) / range); + } else { + for (x = 0; x <= range; x++) + img->Map[x] = (TIFFRGBValue) ((x * 255) / range); + } + if (img->bitspersample <= 16 && + (img->photometric == PHOTOMETRIC_MINISBLACK || + img->photometric == PHOTOMETRIC_MINISWHITE)) { + /* + * Use photometric mapping table to construct + * unpacking tables for samples <= 8 bits. + */ + if (!makebwmap(img)) + return (0); + /* no longer need Map, free it */ + _TIFFfree(img->Map), img->Map = NULL; + } + return (1); +} + +static int +checkcmap(TIFFRGBAImage* img) +{ + uint16* r = img->redcmap; + uint16* g = img->greencmap; + uint16* b = img->bluecmap; + long n = 1L<bitspersample; + + while (n-- > 0) + if (*r++ >= 256 || *g++ >= 256 || *b++ >= 256) + return (16); + return (8); +} + +static void +cvtcmap(TIFFRGBAImage* img) +{ + uint16* r = img->redcmap; + uint16* g = img->greencmap; + uint16* b = img->bluecmap; + long i; + + for (i = (1L<bitspersample)-1; i >= 0; i--) { +#define CVT(x) ((uint16)((x)>>8)) + r[i] = CVT(r[i]); + g[i] = CVT(g[i]); + b[i] = CVT(b[i]); +#undef CVT + } +} + +/* + * Palette images with <= 8 bits/sample are handled + * with a table to avoid lots of shifts and masks. The table + * is setup so that put*cmaptile (below) can retrieve 8/bitspersample + * pixel values simply by indexing into the table with one + * number. + */ +static int +makecmap(TIFFRGBAImage* img) +{ + int bitspersample = img->bitspersample; + int nsamples = 8 / bitspersample; + uint16* r = img->redcmap; + uint16* g = img->greencmap; + uint16* b = img->bluecmap; + uint32 *p; + int i; + + img->PALmap = (uint32**) _TIFFmalloc( + 256*sizeof (uint32 *)+(256*nsamples*sizeof(uint32))); + if (img->PALmap == NULL) { + TIFFErrorExt(img->tif->tif_clientdata, TIFFFileName(img->tif), "No space for Palette mapping table"); + return (0); + } + p = (uint32*)(img->PALmap + 256); + for (i = 0; i < 256; i++) { + TIFFRGBValue c; + img->PALmap[i] = p; +#define CMAP(x) c = (TIFFRGBValue) x; *p++ = PACK(r[c]&0xff, g[c]&0xff, b[c]&0xff); + switch (bitspersample) { + case 1: + CMAP(i>>7); + CMAP((i>>6)&1); + CMAP((i>>5)&1); + CMAP((i>>4)&1); + CMAP((i>>3)&1); + CMAP((i>>2)&1); + CMAP((i>>1)&1); + CMAP(i&1); + break; + case 2: + CMAP(i>>6); + CMAP((i>>4)&3); + CMAP((i>>2)&3); + CMAP(i&3); + break; + case 4: + CMAP(i>>4); + CMAP(i&0xf); + break; + case 8: + CMAP(i); + break; + } +#undef CMAP + } + return (1); +} + +/* + * Construct any mapping table used + * by the associated put routine. + */ +static int +buildMap(TIFFRGBAImage* img) +{ + switch (img->photometric) { + case PHOTOMETRIC_RGB: + case PHOTOMETRIC_YCBCR: + case PHOTOMETRIC_SEPARATED: + if (img->bitspersample == 8) + break; + /* fall thru... */ + case PHOTOMETRIC_MINISBLACK: + case PHOTOMETRIC_MINISWHITE: + if (!setupMap(img)) + return (0); + break; + case PHOTOMETRIC_PALETTE: + /* + * Convert 16-bit colormap to 8-bit (unless it looks + * like an old-style 8-bit colormap). + */ + if (checkcmap(img) == 16) + cvtcmap(img); + else + TIFFWarningExt(img->tif->tif_clientdata, TIFFFileName(img->tif), "Assuming 8-bit colormap"); + /* + * Use mapping table and colormap to construct + * unpacking tables for samples < 8 bits. + */ + if (img->bitspersample <= 8 && !makecmap(img)) + return (0); + break; + } + return (1); +} + +/* + * Select the appropriate conversion routine for packed data. + */ +static int +PickContigCase(TIFFRGBAImage* img) +{ + img->get = TIFFIsTiled(img->tif) ? gtTileContig : gtStripContig; + img->put.contig = NULL; + switch (img->photometric) { + case PHOTOMETRIC_RGB: + switch (img->bitspersample) { + case 8: + if (img->alpha == EXTRASAMPLE_ASSOCALPHA) + img->put.contig = putRGBAAcontig8bittile; + else if (img->alpha == EXTRASAMPLE_UNASSALPHA) + { + img->put.contig = putRGBUAcontig8bittile; + } + else + img->put.contig = putRGBcontig8bittile; + break; + case 16: + if (img->alpha == EXTRASAMPLE_ASSOCALPHA) + { + img->put.contig = putRGBAAcontig16bittile; + } + else if (img->alpha == EXTRASAMPLE_UNASSALPHA) + { + img->put.contig = putRGBUAcontig16bittile; + } + else + { + img->put.contig = putRGBcontig16bittile; + } + break; + } + break; + case PHOTOMETRIC_SEPARATED: + if (buildMap(img)) { + if (img->bitspersample == 8) { + if (!img->Map) + img->put.contig = putRGBcontig8bitCMYKtile; + else + img->put.contig = putRGBcontig8bitCMYKMaptile; + } + } + break; + case PHOTOMETRIC_PALETTE: + if (buildMap(img)) { + switch (img->bitspersample) { + case 8: + img->put.contig = put8bitcmaptile; + break; + case 4: + img->put.contig = put4bitcmaptile; + break; + case 2: + img->put.contig = put2bitcmaptile; + break; + case 1: + img->put.contig = put1bitcmaptile; + break; + } + } + break; + case PHOTOMETRIC_MINISWHITE: + case PHOTOMETRIC_MINISBLACK: + if (buildMap(img)) { + switch (img->bitspersample) { + case 16: + img->put.contig = put16bitbwtile; + break; + case 8: + img->put.contig = putgreytile; + break; + case 4: + img->put.contig = put4bitbwtile; + break; + case 2: + img->put.contig = put2bitbwtile; + break; + case 1: + img->put.contig = put1bitbwtile; + break; + } + } + break; + case PHOTOMETRIC_YCBCR: + if (img->bitspersample == 8) + { + if (initYCbCrConversion(img)!=0) + { + /* + * The 6.0 spec says that subsampling must be + * one of 1, 2, or 4, and that vertical subsampling + * must always be <= horizontal subsampling; so + * there are only a few possibilities and we just + * enumerate the cases. + * Joris: added support for the [1,2] case, nonetheless, to accomodate + * some OJPEG files + */ + uint16 SubsamplingHor; + uint16 SubsamplingVer; + TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRSUBSAMPLING, &SubsamplingHor, &SubsamplingVer); + switch ((SubsamplingHor<<4)|SubsamplingVer) { + case 0x44: + img->put.contig = putcontig8bitYCbCr44tile; + break; + case 0x42: + img->put.contig = putcontig8bitYCbCr42tile; + break; + case 0x41: + img->put.contig = putcontig8bitYCbCr41tile; + break; + case 0x22: + img->put.contig = putcontig8bitYCbCr22tile; + break; + case 0x21: + img->put.contig = putcontig8bitYCbCr21tile; + break; + case 0x12: + img->put.contig = putcontig8bitYCbCr12tile; + break; + case 0x11: + img->put.contig = putcontig8bitYCbCr11tile; + break; + } + } + } + break; + case PHOTOMETRIC_CIELAB: + if (buildMap(img)) { + if (img->bitspersample == 8) + img->put.contig = initCIELabConversion(img); + break; + } + } + return ((img->get!=NULL) && (img->put.contig!=NULL)); +} + +/* + * Select the appropriate conversion routine for unpacked data. + * + * NB: we assume that unpacked single channel data is directed + * to the "packed routines. + */ +static int +PickSeparateCase(TIFFRGBAImage* img) +{ + img->get = TIFFIsTiled(img->tif) ? gtTileSeparate : gtStripSeparate; + img->put.separate = NULL; + switch (img->photometric) { + case PHOTOMETRIC_RGB: + switch (img->bitspersample) { + case 8: + if (img->alpha == EXTRASAMPLE_ASSOCALPHA) + img->put.separate = putRGBAAseparate8bittile; + else if (img->alpha == EXTRASAMPLE_UNASSALPHA) + { + img->put.separate = putRGBUAseparate8bittile; + } + else + img->put.separate = putRGBseparate8bittile; + break; + case 16: + if (img->alpha == EXTRASAMPLE_ASSOCALPHA) + { + img->put.separate = putRGBAAseparate16bittile; + } + else if (img->alpha == EXTRASAMPLE_UNASSALPHA) + { + img->put.separate = putRGBUAseparate16bittile; + } + else + { + img->put.separate = putRGBseparate16bittile; + } + break; + } + break; + case PHOTOMETRIC_YCBCR: + if ((img->bitspersample==8) && (img->samplesperpixel==3)) + { + if (initYCbCrConversion(img)!=0) + { + uint16 hs, vs; + TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRSUBSAMPLING, &hs, &vs); + switch ((hs<<4)|vs) { + case 0x11: + img->put.separate = putseparate8bitYCbCr11tile; + break; + /* TODO: add other cases here */ + } + } + } + break; + } + return ((img->get!=NULL) && (img->put.separate!=NULL)); +} + +/* + * Read a whole strip off data from the file, and convert to RGBA form. + * If this is the last strip, then it will only contain the portion of + * the strip that is actually within the image space. The result is + * organized in bottom to top form. + */ + + +int +TIFFReadRGBAStrip(TIFF* tif, uint32 row, uint32 * raster ) + +{ + char emsg[1024] = ""; + TIFFRGBAImage img; + int ok; + uint32 rowsperstrip, rows_to_read; + + if( TIFFIsTiled( tif ) ) + { + TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), + "Can't use TIFFReadRGBAStrip() with tiled file."); + return (0); + } + + TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip); + if( (row % rowsperstrip) != 0 ) + { + TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), + "Row passed to TIFFReadRGBAStrip() must be first in a strip."); + return (0); + } + + if (TIFFRGBAImageOK(tif, emsg) && TIFFRGBAImageBegin(&img, tif, 0, emsg)) { + + img.row_offset = row; + img.col_offset = 0; + + if( row + rowsperstrip > img.height ) + rows_to_read = img.height - row; + else + rows_to_read = rowsperstrip; + + ok = TIFFRGBAImageGet(&img, raster, img.width, rows_to_read ); + + TIFFRGBAImageEnd(&img); + } else { + TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", emsg); + ok = 0; + } + + return (ok); +} + +/* + * Read a whole tile off data from the file, and convert to RGBA form. + * The returned RGBA data is organized from bottom to top of tile, + * and may include zeroed areas if the tile extends off the image. + */ + +int +TIFFReadRGBATile(TIFF* tif, uint32 col, uint32 row, uint32 * raster) + +{ + char emsg[1024] = ""; + TIFFRGBAImage img; + int ok; + uint32 tile_xsize, tile_ysize; + uint32 read_xsize, read_ysize; + uint32 i_row; + + /* + * Verify that our request is legal - on a tile file, and on a + * tile boundary. + */ + + if( !TIFFIsTiled( tif ) ) + { + TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), + "Can't use TIFFReadRGBATile() with stripped file."); + return (0); + } + + TIFFGetFieldDefaulted(tif, TIFFTAG_TILEWIDTH, &tile_xsize); + TIFFGetFieldDefaulted(tif, TIFFTAG_TILELENGTH, &tile_ysize); + if( (col % tile_xsize) != 0 || (row % tile_ysize) != 0 ) + { + TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), + "Row/col passed to TIFFReadRGBATile() must be top" + "left corner of a tile."); + return (0); + } + + /* + * Setup the RGBA reader. + */ + + if (!TIFFRGBAImageOK(tif, emsg) + || !TIFFRGBAImageBegin(&img, tif, 0, emsg)) { + TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", emsg); + return( 0 ); + } + + /* + * The TIFFRGBAImageGet() function doesn't allow us to get off the + * edge of the image, even to fill an otherwise valid tile. So we + * figure out how much we can read, and fix up the tile buffer to + * a full tile configuration afterwards. + */ + + if( row + tile_ysize > img.height ) + read_ysize = img.height - row; + else + read_ysize = tile_ysize; + + if( col + tile_xsize > img.width ) + read_xsize = img.width - col; + else + read_xsize = tile_xsize; + + /* + * Read the chunk of imagery. + */ + + img.row_offset = row; + img.col_offset = col; + + ok = TIFFRGBAImageGet(&img, raster, read_xsize, read_ysize ); + + TIFFRGBAImageEnd(&img); + + /* + * If our read was incomplete we will need to fix up the tile by + * shifting the data around as if a full tile of data is being returned. + * + * This is all the more complicated because the image is organized in + * bottom to top format. + */ + + if( read_xsize == tile_xsize && read_ysize == tile_ysize ) + return( ok ); + + for( i_row = 0; i_row < read_ysize; i_row++ ) { + memmove( raster + (tile_ysize - i_row - 1) * tile_xsize, + raster + (read_ysize - i_row - 1) * read_xsize, + read_xsize * sizeof(uint32) ); + _TIFFmemset( raster + (tile_ysize - i_row - 1) * tile_xsize+read_xsize, + 0, sizeof(uint32) * (tile_xsize - read_xsize) ); + } + + for( i_row = read_ysize; i_row < tile_ysize; i_row++ ) { + _TIFFmemset( raster + (tile_ysize - i_row - 1) * tile_xsize, + 0, sizeof(uint32) * tile_xsize ); + } + + return (ok); +} + +/* vim: set ts=8 sts=8 sw=8 noet: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tif_jbig.c b/reactos/dll/3rdparty/libtiff/tif_jbig.c new file mode 100644 index 00000000000..c92ee3de6c8 --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tif_jbig.c @@ -0,0 +1,385 @@ +/* $Id: tif_jbig.c,v 1.2.2.3 2010-06-08 18:50:42 bfriesen Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library. + * + * JBIG Compression Algorithm Support. + * Contributed by Lee Howard + * + */ + +#include "tiffiop.h" + +#ifdef JBIG_SUPPORT +#include "jbig.h" + +typedef struct +{ + uint32 recvparams; /* encoded Class 2 session params */ + char* subaddress; /* subaddress string */ + uint32 recvtime; /* time spend receiving in seconds */ + char* faxdcs; /* encoded fax parameters (DCS, Table 2/T.30) */ + + TIFFVGetMethod vgetparent; + TIFFVSetMethod vsetparent; +} JBIGState; + +#define GetJBIGState(tif) ((JBIGState*)(tif)->tif_data) + +#define FIELD_RECVPARAMS (FIELD_CODEC+0) +#define FIELD_SUBADDRESS (FIELD_CODEC+1) +#define FIELD_RECVTIME (FIELD_CODEC+2) +#define FIELD_FAXDCS (FIELD_CODEC+3) + +static const TIFFFieldInfo jbigFieldInfo[] = +{ + {TIFFTAG_FAXRECVPARAMS, 1, 1, TIFF_LONG, FIELD_RECVPARAMS, TRUE, FALSE, "FaxRecvParams"}, + {TIFFTAG_FAXSUBADDRESS, -1, -1, TIFF_ASCII, FIELD_SUBADDRESS, TRUE, FALSE, "FaxSubAddress"}, + {TIFFTAG_FAXRECVTIME, 1, 1, TIFF_LONG, FIELD_RECVTIME, TRUE, FALSE, "FaxRecvTime"}, + {TIFFTAG_FAXDCS, -1, -1, TIFF_ASCII, FIELD_FAXDCS, TRUE, FALSE, "FaxDcs"}, +}; + +static int JBIGSetupDecode(TIFF* tif) +{ + if (TIFFNumberOfStrips(tif) != 1) + { + TIFFError("JBIG", "Multistrip images not supported in decoder"); + return 0; + } + + return 1; +} + +static int JBIGDecode(TIFF* tif, tidata_t buffer, tsize_t size, tsample_t s) +{ + struct jbg_dec_state decoder; + int decodeStatus = 0; + unsigned char* pImage = NULL; + (void) size, (void) s; + + if (isFillOrder(tif, tif->tif_dir.td_fillorder)) + { + TIFFReverseBits(tif->tif_rawdata, tif->tif_rawdatasize); + } + + jbg_dec_init(&decoder); + +#if defined(HAVE_JBG_NEWLEN) + jbg_newlen(tif->tif_rawdata, tif->tif_rawdatasize); + /* + * I do not check the return status of jbg_newlen because even if this + * function fails it does not necessarily mean that decoding the image + * will fail. It is generally only needed for received fax images + * that do not contain the actual length of the image in the BIE + * header. I do not log when an error occurs because that will cause + * problems when converting JBIG encoded TIFF's to + * PostScript. As long as the actual image length is contained in the + * BIE header jbg_dec_in should succeed. + */ +#endif /* HAVE_JBG_NEWLEN */ + + decodeStatus = jbg_dec_in(&decoder, tif->tif_rawdata, + tif->tif_rawdatasize, NULL); + if (JBG_EOK != decodeStatus) + { + /* + * XXX: JBG_EN constant was defined in pre-2.0 releases of the + * JBIG-KIT. Since the 2.0 the error reporting functions were + * changed. We will handle both cases here. + */ + TIFFError("JBIG", "Error (%d) decoding: %s", decodeStatus, +#if defined(JBG_EN) + jbg_strerror(decodeStatus, JBG_EN) +#else + jbg_strerror(decodeStatus) +#endif + ); + return 0; + } + + pImage = jbg_dec_getimage(&decoder, 0); + _TIFFmemcpy(buffer, pImage, jbg_dec_getsize(&decoder)); + jbg_dec_free(&decoder); + return 1; +} + +static int JBIGSetupEncode(TIFF* tif) +{ + if (TIFFNumberOfStrips(tif) != 1) + { + TIFFError("JBIG", "Multistrip images not supported in encoder"); + return 0; + } + + return 1; +} + +static int JBIGCopyEncodedData(TIFF* tif, tidata_t pp, tsize_t cc, tsample_t s) +{ + (void) s; + while (cc > 0) + { + tsize_t n = cc; + + if (tif->tif_rawcc + n > tif->tif_rawdatasize) + { + n = tif->tif_rawdatasize - tif->tif_rawcc; + } + + assert(n > 0); + _TIFFmemcpy(tif->tif_rawcp, pp, n); + tif->tif_rawcp += n; + tif->tif_rawcc += n; + pp += n; + cc -= n; + if (tif->tif_rawcc >= tif->tif_rawdatasize && + !TIFFFlushData1(tif)) + { + return (-1); + } + } + + return (1); +} + +static void JBIGOutputBie(unsigned char* buffer, size_t len, void *userData) +{ + TIFF* tif = (TIFF*)userData; + + if (isFillOrder(tif, tif->tif_dir.td_fillorder)) + { + TIFFReverseBits(buffer, len); + } + + JBIGCopyEncodedData(tif, buffer, len, 0); +} + +static int JBIGEncode(TIFF* tif, tidata_t buffer, tsize_t size, tsample_t s) +{ + TIFFDirectory* dir = &tif->tif_dir; + struct jbg_enc_state encoder; + + (void) size, (void) s; + + jbg_enc_init(&encoder, + dir->td_imagewidth, + dir->td_imagelength, + 1, + &buffer, + JBIGOutputBie, + tif); + /* + * jbg_enc_out does the "real" encoding. As data is encoded, + * JBIGOutputBie is called, which writes the data to the directory. + */ + jbg_enc_out(&encoder); + jbg_enc_free(&encoder); + + return 1; +} + +static void JBIGCleanup(TIFF* tif) +{ + JBIGState *sp = GetJBIGState(tif); + + assert(sp != 0); + + tif->tif_tagmethods.vgetfield = sp->vgetparent; + tif->tif_tagmethods.vsetfield = sp->vsetparent; + + _TIFFfree(tif->tif_data); + tif->tif_data = NULL; + + _TIFFSetDefaultCompressionState(tif); +} + +static void JBIGPrintDir(TIFF* tif, FILE* fd, long flags) +{ + JBIGState* codec = GetJBIGState(tif); + (void)flags; + + if (TIFFFieldSet(tif, FIELD_RECVPARAMS)) + { + fprintf(fd, + " Fax Receive Parameters: %08lx\n", + (unsigned long)codec->recvparams); + } + + if (TIFFFieldSet(tif, FIELD_SUBADDRESS)) + { + fprintf(fd, + " Fax SubAddress: %s\n", + codec->subaddress); + } + + if (TIFFFieldSet(tif, FIELD_RECVTIME)) + { + fprintf(fd, + " Fax Receive Time: %lu secs\n", + (unsigned long)codec->recvtime); + } + + if (TIFFFieldSet(tif, FIELD_FAXDCS)) + { + fprintf(fd, + " Fax DCS: %s\n", + codec->faxdcs); + } +} + +static int JBIGVGetField(TIFF* tif, ttag_t tag, va_list ap) +{ + JBIGState* codec = GetJBIGState(tif); + + switch (tag) + { + case TIFFTAG_FAXRECVPARAMS: + *va_arg(ap, uint32*) = codec->recvparams; + break; + + case TIFFTAG_FAXSUBADDRESS: + *va_arg(ap, char**) = codec->subaddress; + break; + + case TIFFTAG_FAXRECVTIME: + *va_arg(ap, uint32*) = codec->recvtime; + break; + + case TIFFTAG_FAXDCS: + *va_arg(ap, char**) = codec->faxdcs; + break; + + default: + return (*codec->vgetparent)(tif, tag, ap); + } + + return 1; +} + +static int JBIGVSetField(TIFF* tif, ttag_t tag, va_list ap) +{ + JBIGState* codec = GetJBIGState(tif); + + switch (tag) + { + case TIFFTAG_FAXRECVPARAMS: + codec->recvparams = va_arg(ap, uint32); + break; + + case TIFFTAG_FAXSUBADDRESS: + _TIFFsetString(&codec->subaddress, va_arg(ap, char*)); + break; + + case TIFFTAG_FAXRECVTIME: + codec->recvtime = va_arg(ap, uint32); + break; + + case TIFFTAG_FAXDCS: + _TIFFsetString(&codec->faxdcs, va_arg(ap, char*)); + break; + + default: + return (*codec->vsetparent)(tif, tag, ap); + } + + TIFFSetFieldBit(tif, _TIFFFieldWithTag(tif, tag)->field_bit); + tif->tif_flags |= TIFF_DIRTYDIRECT; + return 1; +} + +int TIFFInitJBIG(TIFF* tif, int scheme) +{ + JBIGState* codec = NULL; + + assert(scheme == COMPRESSION_JBIG); + + /* + * Merge codec-specific tag information. + */ + if (!_TIFFMergeFieldInfo(tif, jbigFieldInfo, + TIFFArrayCount(jbigFieldInfo))) { + TIFFErrorExt(tif->tif_clientdata, "TIFFInitJBIG", + "Merging JBIG codec-specific tags failed"); + return 0; + } + + /* Allocate memory for the JBIGState structure.*/ + tif->tif_data = (tdata_t)_TIFFmalloc(sizeof(JBIGState)); + if (tif->tif_data == NULL) + { + TIFFError("TIFFInitJBIG", "Not enough memory for JBIGState"); + return 0; + } + _TIFFmemset(tif->tif_data, 0, sizeof(JBIGState)); + codec = GetJBIGState(tif); + + /* Initialize codec private fields */ + codec->recvparams = 0; + codec->subaddress = NULL; + codec->faxdcs = NULL; + codec->recvtime = 0; + + /* + * Override parent get/set field methods. + */ + codec->vgetparent = tif->tif_tagmethods.vgetfield; + codec->vsetparent = tif->tif_tagmethods.vsetfield; + tif->tif_tagmethods.vgetfield = JBIGVGetField; + tif->tif_tagmethods.vsetfield = JBIGVSetField; + tif->tif_tagmethods.printdir = JBIGPrintDir; + + /* + * These flags are set so the JBIG Codec can control when to reverse + * bits and when not to and to allow the jbig decoder and bit reverser + * to write to memory when necessary. + */ + tif->tif_flags |= TIFF_NOBITREV; + tif->tif_flags &= ~TIFF_MAPPED; + + /* Setup the function pointers for encode, decode, and cleanup. */ + tif->tif_setupdecode = JBIGSetupDecode; + tif->tif_decodestrip = JBIGDecode; + + tif->tif_setupencode = JBIGSetupEncode; + tif->tif_encodestrip = JBIGEncode; + + tif->tif_cleanup = JBIGCleanup; + + return 1; +} + +#endif /* JBIG_SUPPORT */ + +/* vim: set ts=8 sts=8 sw=8 noet: */ + +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tif_jpeg.c b/reactos/dll/3rdparty/libtiff/tif_jpeg.c new file mode 100644 index 00000000000..a967827e749 --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tif_jpeg.c @@ -0,0 +1,2065 @@ +/* $Id: tif_jpeg.c,v 1.50.2.9 2010-06-14 02:47:16 fwarmerdam Exp $ */ + +/* + * Copyright (c) 1994-1997 Sam Leffler + * Copyright (c) 1994-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#define WIN32_LEAN_AND_MEAN +#define VC_EXTRALEAN + +#include "tiffiop.h" +#ifdef JPEG_SUPPORT + +/* + * TIFF Library + * + * JPEG Compression support per TIFF Technical Note #2 + * (*not* per the original TIFF 6.0 spec). + * + * This file is simply an interface to the libjpeg library written by + * the Independent JPEG Group. You need release 5 or later of the IJG + * code, which you can find on the Internet at ftp.uu.net:/graphics/jpeg/. + * + * Contributed by Tom Lane . + */ +#include + +int TIFFFillStrip(TIFF*, tstrip_t); +int TIFFFillTile(TIFF*, ttile_t); + +/* We undefine FAR to avoid conflict with JPEG definition */ + +#ifdef FAR +#undef FAR +#endif + +/* + Libjpeg's jmorecfg.h defines INT16 and INT32, but only if XMD_H is + not defined. Unfortunately, the MinGW and Borland compilers include + a typedef for INT32, which causes a conflict. MSVC does not include + a conficting typedef given the headers which are included. +*/ +#if defined(__BORLANDC__) || defined(__MINGW32__) +# define XMD_H 1 +#endif + +/* + The windows RPCNDR.H file defines boolean, but defines it with the + unsigned char size. You should compile JPEG library using appropriate + definitions in jconfig.h header, but many users compile library in wrong + way. That causes errors of the following type: + + "JPEGLib: JPEG parameter struct mismatch: library thinks size is 432, + caller expects 464" + + For such users we wil fix the problem here. See install.doc file from + the JPEG library distribution for details. +*/ + +/* Define "boolean" as unsigned char, not int, per Windows custom. */ +#if defined(WIN32) && !defined(__MINGW32__) +# ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */ + typedef unsigned char boolean; +# endif +# define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */ +#endif + +#include "jpeglib.h" +#include "jerror.h" + +/* + * We are using width_in_blocks which is supposed to be private to + * libjpeg. Unfortunately, the libjpeg delivered with Cygwin has + * renamed this member to width_in_data_units. Since the header has + * also renamed a define, use that unique define name in order to + * detect the problem header and adjust to suit. + */ +#if defined(D_MAX_DATA_UNITS_IN_MCU) +#define width_in_blocks width_in_data_units +#endif + +/* + * On some machines it may be worthwhile to use _setjmp or sigsetjmp + * in place of plain setjmp. These macros will make it easier. + */ +#define SETJMP(jbuf) setjmp(jbuf) +#define LONGJMP(jbuf,code) longjmp(jbuf,code) +#define JMP_BUF jmp_buf + +typedef struct jpeg_destination_mgr jpeg_destination_mgr; +typedef struct jpeg_source_mgr jpeg_source_mgr; +typedef struct jpeg_error_mgr jpeg_error_mgr; + +/* + * State block for each open TIFF file using + * libjpeg to do JPEG compression/decompression. + * + * libjpeg's visible state is either a jpeg_compress_struct + * or jpeg_decompress_struct depending on which way we + * are going. comm can be used to refer to the fields + * which are common to both. + * + * NB: cinfo is required to be the first member of JPEGState, + * so we can safely cast JPEGState* -> jpeg_xxx_struct* + * and vice versa! + */ +typedef struct { + union { + struct jpeg_compress_struct c; + struct jpeg_decompress_struct d; + struct jpeg_common_struct comm; + } cinfo; /* NB: must be first */ + int cinfo_initialized; + + jpeg_error_mgr err; /* libjpeg error manager */ + JMP_BUF exit_jmpbuf; /* for catching libjpeg failures */ + /* + * The following two members could be a union, but + * they're small enough that it's not worth the effort. + */ + jpeg_destination_mgr dest; /* data dest for compression */ + jpeg_source_mgr src; /* data source for decompression */ + /* private state */ + TIFF* tif; /* back link needed by some code */ + uint16 photometric; /* copy of PhotometricInterpretation */ + uint16 h_sampling; /* luminance sampling factors */ + uint16 v_sampling; + tsize_t bytesperline; /* decompressed bytes per scanline */ + /* pointers to intermediate buffers when processing downsampled data */ + JSAMPARRAY ds_buffer[MAX_COMPONENTS]; + int scancount; /* number of "scanlines" accumulated */ + int samplesperclump; + + TIFFVGetMethod vgetparent; /* super-class method */ + TIFFVSetMethod vsetparent; /* super-class method */ + TIFFPrintMethod printdir; /* super-class method */ + TIFFStripMethod defsparent; /* super-class method */ + TIFFTileMethod deftparent; /* super-class method */ + /* pseudo-tag fields */ + void* jpegtables; /* JPEGTables tag value, or NULL */ + uint32 jpegtables_length; /* number of bytes in same */ + int jpegquality; /* Compression quality level */ + int jpegcolormode; /* Auto RGB<=>YCbCr convert? */ + int jpegtablesmode; /* What to put in JPEGTables */ + + int ycbcrsampling_fetched; + uint32 recvparams; /* encoded Class 2 session params */ + char* subaddress; /* subaddress string */ + uint32 recvtime; /* time spent receiving (secs) */ + char* faxdcs; /* encoded fax parameters (DCS, Table 2/T.30) */ +} JPEGState; + +#define JState(tif) ((JPEGState*)(tif)->tif_data) + +static int JPEGDecode(TIFF*, tidata_t, tsize_t, tsample_t); +static int JPEGDecodeRaw(TIFF*, tidata_t, tsize_t, tsample_t); +static int JPEGEncode(TIFF*, tidata_t, tsize_t, tsample_t); +static int JPEGEncodeRaw(TIFF*, tidata_t, tsize_t, tsample_t); +static int JPEGInitializeLibJPEG( TIFF * tif, + int force_encode, int force_decode ); + +#define FIELD_JPEGTABLES (FIELD_CODEC+0) +#define FIELD_RECVPARAMS (FIELD_CODEC+1) +#define FIELD_SUBADDRESS (FIELD_CODEC+2) +#define FIELD_RECVTIME (FIELD_CODEC+3) +#define FIELD_FAXDCS (FIELD_CODEC+4) + +static const TIFFFieldInfo jpegFieldInfo[] = { + { TIFFTAG_JPEGTABLES, -3,-3, TIFF_UNDEFINED, FIELD_JPEGTABLES, + FALSE, TRUE, "JPEGTables" }, + { TIFFTAG_JPEGQUALITY, 0, 0, TIFF_ANY, FIELD_PSEUDO, + TRUE, FALSE, "" }, + { TIFFTAG_JPEGCOLORMODE, 0, 0, TIFF_ANY, FIELD_PSEUDO, + FALSE, FALSE, "" }, + { TIFFTAG_JPEGTABLESMODE, 0, 0, TIFF_ANY, FIELD_PSEUDO, + FALSE, FALSE, "" }, + /* Specific for JPEG in faxes */ + { TIFFTAG_FAXRECVPARAMS, 1, 1, TIFF_LONG, FIELD_RECVPARAMS, + TRUE, FALSE, "FaxRecvParams" }, + { TIFFTAG_FAXSUBADDRESS, -1,-1, TIFF_ASCII, FIELD_SUBADDRESS, + TRUE, FALSE, "FaxSubAddress" }, + { TIFFTAG_FAXRECVTIME, 1, 1, TIFF_LONG, FIELD_RECVTIME, + TRUE, FALSE, "FaxRecvTime" }, + { TIFFTAG_FAXDCS, -1, -1, TIFF_ASCII, FIELD_FAXDCS, + TRUE, FALSE, "FaxDcs" }, +}; +#define N(a) (sizeof (a) / sizeof (a[0])) + +/* + * libjpeg interface layer. + * + * We use setjmp/longjmp to return control to libtiff + * when a fatal error is encountered within the JPEG + * library. We also direct libjpeg error and warning + * messages through the appropriate libtiff handlers. + */ + +/* + * Error handling routines (these replace corresponding + * IJG routines from jerror.c). These are used for both + * compression and decompression. + */ +static void +TIFFjpeg_error_exit(j_common_ptr cinfo) +{ + JPEGState *sp = (JPEGState *) cinfo; /* NB: cinfo assumed first */ + char buffer[JMSG_LENGTH_MAX]; + + (*cinfo->err->format_message) (cinfo, buffer); + TIFFErrorExt(sp->tif->tif_clientdata, "JPEGLib", "%s", buffer); /* display the error message */ + jpeg_abort(cinfo); /* clean up libjpeg state */ + LONGJMP(sp->exit_jmpbuf, 1); /* return to libtiff caller */ +} + +/* + * This routine is invoked only for warning messages, + * since error_exit does its own thing and trace_level + * is never set > 0. + */ +static void +TIFFjpeg_output_message(j_common_ptr cinfo) +{ + char buffer[JMSG_LENGTH_MAX]; + + (*cinfo->err->format_message) (cinfo, buffer); + TIFFWarningExt(((JPEGState *) cinfo)->tif->tif_clientdata, "JPEGLib", "%s", buffer); +} + +/* + * Interface routines. This layer of routines exists + * primarily to limit side-effects from using setjmp. + * Also, normal/error returns are converted into return + * values per libtiff practice. + */ +#define CALLJPEG(sp, fail, op) (SETJMP((sp)->exit_jmpbuf) ? (fail) : (op)) +#define CALLVJPEG(sp, op) CALLJPEG(sp, 0, ((op),1)) + +static int +TIFFjpeg_create_compress(JPEGState* sp) +{ + /* initialize JPEG error handling */ + sp->cinfo.c.err = jpeg_std_error(&sp->err); + sp->err.error_exit = TIFFjpeg_error_exit; + sp->err.output_message = TIFFjpeg_output_message; + + return CALLVJPEG(sp, jpeg_create_compress(&sp->cinfo.c)); +} + +static int +TIFFjpeg_create_decompress(JPEGState* sp) +{ + /* initialize JPEG error handling */ + sp->cinfo.d.err = jpeg_std_error(&sp->err); + sp->err.error_exit = TIFFjpeg_error_exit; + sp->err.output_message = TIFFjpeg_output_message; + + return CALLVJPEG(sp, jpeg_create_decompress(&sp->cinfo.d)); +} + +static int +TIFFjpeg_set_defaults(JPEGState* sp) +{ + return CALLVJPEG(sp, jpeg_set_defaults(&sp->cinfo.c)); +} + +static int +TIFFjpeg_set_colorspace(JPEGState* sp, J_COLOR_SPACE colorspace) +{ + return CALLVJPEG(sp, jpeg_set_colorspace(&sp->cinfo.c, colorspace)); +} + +static int +TIFFjpeg_set_quality(JPEGState* sp, int quality, boolean force_baseline) +{ + return CALLVJPEG(sp, + jpeg_set_quality(&sp->cinfo.c, quality, force_baseline)); +} + +static int +TIFFjpeg_suppress_tables(JPEGState* sp, boolean suppress) +{ + return CALLVJPEG(sp, jpeg_suppress_tables(&sp->cinfo.c, suppress)); +} + +static int +TIFFjpeg_start_compress(JPEGState* sp, boolean write_all_tables) +{ + return CALLVJPEG(sp, + jpeg_start_compress(&sp->cinfo.c, write_all_tables)); +} + +static int +TIFFjpeg_write_scanlines(JPEGState* sp, JSAMPARRAY scanlines, int num_lines) +{ + return CALLJPEG(sp, -1, (int) jpeg_write_scanlines(&sp->cinfo.c, + scanlines, (JDIMENSION) num_lines)); +} + +static int +TIFFjpeg_write_raw_data(JPEGState* sp, JSAMPIMAGE data, int num_lines) +{ + return CALLJPEG(sp, -1, (int) jpeg_write_raw_data(&sp->cinfo.c, + data, (JDIMENSION) num_lines)); +} + +static int +TIFFjpeg_finish_compress(JPEGState* sp) +{ + return CALLVJPEG(sp, jpeg_finish_compress(&sp->cinfo.c)); +} + +static int +TIFFjpeg_write_tables(JPEGState* sp) +{ + return CALLVJPEG(sp, jpeg_write_tables(&sp->cinfo.c)); +} + +static int +TIFFjpeg_read_header(JPEGState* sp, boolean require_image) +{ + return CALLJPEG(sp, -1, jpeg_read_header(&sp->cinfo.d, require_image)); +} + +static int +TIFFjpeg_start_decompress(JPEGState* sp) +{ + return CALLVJPEG(sp, jpeg_start_decompress(&sp->cinfo.d)); +} + +static int +TIFFjpeg_read_scanlines(JPEGState* sp, JSAMPARRAY scanlines, int max_lines) +{ + return CALLJPEG(sp, -1, (int) jpeg_read_scanlines(&sp->cinfo.d, + scanlines, (JDIMENSION) max_lines)); +} + +static int +TIFFjpeg_read_raw_data(JPEGState* sp, JSAMPIMAGE data, int max_lines) +{ + return CALLJPEG(sp, -1, (int) jpeg_read_raw_data(&sp->cinfo.d, + data, (JDIMENSION) max_lines)); +} + +static int +TIFFjpeg_finish_decompress(JPEGState* sp) +{ + return CALLJPEG(sp, -1, (int) jpeg_finish_decompress(&sp->cinfo.d)); +} + +static int +TIFFjpeg_abort(JPEGState* sp) +{ + return CALLVJPEG(sp, jpeg_abort(&sp->cinfo.comm)); +} + +static int +TIFFjpeg_destroy(JPEGState* sp) +{ + return CALLVJPEG(sp, jpeg_destroy(&sp->cinfo.comm)); +} + +static JSAMPARRAY +TIFFjpeg_alloc_sarray(JPEGState* sp, int pool_id, + JDIMENSION samplesperrow, JDIMENSION numrows) +{ + return CALLJPEG(sp, (JSAMPARRAY) NULL, + (*sp->cinfo.comm.mem->alloc_sarray) + (&sp->cinfo.comm, pool_id, samplesperrow, numrows)); +} + +/* + * JPEG library destination data manager. + * These routines direct compressed data from libjpeg into the + * libtiff output buffer. + */ + +static void +std_init_destination(j_compress_ptr cinfo) +{ + JPEGState* sp = (JPEGState*) cinfo; + TIFF* tif = sp->tif; + + sp->dest.next_output_byte = (JOCTET*) tif->tif_rawdata; + sp->dest.free_in_buffer = (size_t) tif->tif_rawdatasize; +} + +static boolean +std_empty_output_buffer(j_compress_ptr cinfo) +{ + JPEGState* sp = (JPEGState*) cinfo; + TIFF* tif = sp->tif; + + /* the entire buffer has been filled */ + tif->tif_rawcc = tif->tif_rawdatasize; + TIFFFlushData1(tif); + sp->dest.next_output_byte = (JOCTET*) tif->tif_rawdata; + sp->dest.free_in_buffer = (size_t) tif->tif_rawdatasize; + + return (TRUE); +} + +static void +std_term_destination(j_compress_ptr cinfo) +{ + JPEGState* sp = (JPEGState*) cinfo; + TIFF* tif = sp->tif; + + tif->tif_rawcp = (tidata_t) sp->dest.next_output_byte; + tif->tif_rawcc = + tif->tif_rawdatasize - (tsize_t) sp->dest.free_in_buffer; + /* NB: libtiff does the final buffer flush */ +} + +static void +TIFFjpeg_data_dest(JPEGState* sp, TIFF* tif) +{ + (void) tif; + sp->cinfo.c.dest = &sp->dest; + sp->dest.init_destination = std_init_destination; + sp->dest.empty_output_buffer = std_empty_output_buffer; + sp->dest.term_destination = std_term_destination; +} + +/* + * Alternate destination manager for outputting to JPEGTables field. + */ + +static void +tables_init_destination(j_compress_ptr cinfo) +{ + JPEGState* sp = (JPEGState*) cinfo; + + /* while building, jpegtables_length is allocated buffer size */ + sp->dest.next_output_byte = (JOCTET*) sp->jpegtables; + sp->dest.free_in_buffer = (size_t) sp->jpegtables_length; +} + +static boolean +tables_empty_output_buffer(j_compress_ptr cinfo) +{ + JPEGState* sp = (JPEGState*) cinfo; + void* newbuf; + + /* the entire buffer has been filled; enlarge it by 1000 bytes */ + newbuf = _TIFFrealloc((tdata_t) sp->jpegtables, + (tsize_t) (sp->jpegtables_length + 1000)); + if (newbuf == NULL) + ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 100); + sp->dest.next_output_byte = (JOCTET*) newbuf + sp->jpegtables_length; + sp->dest.free_in_buffer = (size_t) 1000; + sp->jpegtables = newbuf; + sp->jpegtables_length += 1000; + return (TRUE); +} + +static void +tables_term_destination(j_compress_ptr cinfo) +{ + JPEGState* sp = (JPEGState*) cinfo; + + /* set tables length to number of bytes actually emitted */ + sp->jpegtables_length -= sp->dest.free_in_buffer; +} + +static int +TIFFjpeg_tables_dest(JPEGState* sp, TIFF* tif) +{ + (void) tif; + /* + * Allocate a working buffer for building tables. + * Initial size is 1000 bytes, which is usually adequate. + */ + if (sp->jpegtables) + _TIFFfree(sp->jpegtables); + sp->jpegtables_length = 1000; + sp->jpegtables = (void*) _TIFFmalloc((tsize_t) sp->jpegtables_length); + if (sp->jpegtables == NULL) { + sp->jpegtables_length = 0; + TIFFErrorExt(sp->tif->tif_clientdata, "TIFFjpeg_tables_dest", "No space for JPEGTables"); + return (0); + } + sp->cinfo.c.dest = &sp->dest; + sp->dest.init_destination = tables_init_destination; + sp->dest.empty_output_buffer = tables_empty_output_buffer; + sp->dest.term_destination = tables_term_destination; + return (1); +} + +/* + * JPEG library source data manager. + * These routines supply compressed data to libjpeg. + */ + +static void +std_init_source(j_decompress_ptr cinfo) +{ + JPEGState* sp = (JPEGState*) cinfo; + TIFF* tif = sp->tif; + + sp->src.next_input_byte = (const JOCTET*) tif->tif_rawdata; + sp->src.bytes_in_buffer = (size_t) tif->tif_rawcc; +} + +static boolean +std_fill_input_buffer(j_decompress_ptr cinfo) +{ + JPEGState* sp = (JPEGState* ) cinfo; + static const JOCTET dummy_EOI[2] = { 0xFF, JPEG_EOI }; + + /* + * Should never get here since entire strip/tile is + * read into memory before the decompressor is called, + * and thus was supplied by init_source. + */ + WARNMS(cinfo, JWRN_JPEG_EOF); + /* insert a fake EOI marker */ + sp->src.next_input_byte = dummy_EOI; + sp->src.bytes_in_buffer = 2; + return (TRUE); +} + +static void +std_skip_input_data(j_decompress_ptr cinfo, long num_bytes) +{ + JPEGState* sp = (JPEGState*) cinfo; + + if (num_bytes > 0) { + if (num_bytes > (long) sp->src.bytes_in_buffer) { + /* oops, buffer overrun */ + (void) std_fill_input_buffer(cinfo); + } else { + sp->src.next_input_byte += (size_t) num_bytes; + sp->src.bytes_in_buffer -= (size_t) num_bytes; + } + } +} + +static void +std_term_source(j_decompress_ptr cinfo) +{ + /* No work necessary here */ + /* Or must we update tif->tif_rawcp, tif->tif_rawcc ??? */ + /* (if so, need empty tables_term_source!) */ + (void) cinfo; +} + +static void +TIFFjpeg_data_src(JPEGState* sp, TIFF* tif) +{ + (void) tif; + sp->cinfo.d.src = &sp->src; + sp->src.init_source = std_init_source; + sp->src.fill_input_buffer = std_fill_input_buffer; + sp->src.skip_input_data = std_skip_input_data; + sp->src.resync_to_restart = jpeg_resync_to_restart; + sp->src.term_source = std_term_source; + sp->src.bytes_in_buffer = 0; /* for safety */ + sp->src.next_input_byte = NULL; +} + +/* + * Alternate source manager for reading from JPEGTables. + * We can share all the code except for the init routine. + */ + +static void +tables_init_source(j_decompress_ptr cinfo) +{ + JPEGState* sp = (JPEGState*) cinfo; + + sp->src.next_input_byte = (const JOCTET*) sp->jpegtables; + sp->src.bytes_in_buffer = (size_t) sp->jpegtables_length; +} + +static void +TIFFjpeg_tables_src(JPEGState* sp, TIFF* tif) +{ + TIFFjpeg_data_src(sp, tif); + sp->src.init_source = tables_init_source; +} + +/* + * Allocate downsampled-data buffers needed for downsampled I/O. + * We use values computed in jpeg_start_compress or jpeg_start_decompress. + * We use libjpeg's allocator so that buffers will be released automatically + * when done with strip/tile. + * This is also a handy place to compute samplesperclump, bytesperline. + */ +static int +alloc_downsampled_buffers(TIFF* tif, jpeg_component_info* comp_info, + int num_components) +{ + JPEGState* sp = JState(tif); + int ci; + jpeg_component_info* compptr; + JSAMPARRAY buf; + int samples_per_clump = 0; + + for (ci = 0, compptr = comp_info; ci < num_components; + ci++, compptr++) { + samples_per_clump += compptr->h_samp_factor * + compptr->v_samp_factor; + buf = TIFFjpeg_alloc_sarray(sp, JPOOL_IMAGE, + compptr->width_in_blocks * DCTSIZE, + (JDIMENSION) (compptr->v_samp_factor*DCTSIZE)); + if (buf == NULL) + return (0); + sp->ds_buffer[ci] = buf; + } + sp->samplesperclump = samples_per_clump; + return (1); +} + + +/* + * JPEG Decoding. + */ + +static int +JPEGSetupDecode(TIFF* tif) +{ + JPEGState* sp = JState(tif); + TIFFDirectory *td = &tif->tif_dir; + + JPEGInitializeLibJPEG( tif, 0, 1 ); + + assert(sp != NULL); + assert(sp->cinfo.comm.is_decompressor); + + /* Read JPEGTables if it is present */ + if (TIFFFieldSet(tif,FIELD_JPEGTABLES)) { + TIFFjpeg_tables_src(sp, tif); + if(TIFFjpeg_read_header(sp,FALSE) != JPEG_HEADER_TABLES_ONLY) { + TIFFErrorExt(tif->tif_clientdata, "JPEGSetupDecode", "Bogus JPEGTables field"); + return (0); + } + } + + /* Grab parameters that are same for all strips/tiles */ + sp->photometric = td->td_photometric; + switch (sp->photometric) { + case PHOTOMETRIC_YCBCR: + sp->h_sampling = td->td_ycbcrsubsampling[0]; + sp->v_sampling = td->td_ycbcrsubsampling[1]; + break; + default: + /* TIFF 6.0 forbids subsampling of all other color spaces */ + sp->h_sampling = 1; + sp->v_sampling = 1; + break; + } + + /* Set up for reading normal data */ + TIFFjpeg_data_src(sp, tif); + tif->tif_postdecode = _TIFFNoPostDecode; /* override byte swapping */ + return (1); +} + +/* + * Set up for decoding a strip or tile. + */ +static int +JPEGPreDecode(TIFF* tif, tsample_t s) +{ + JPEGState *sp = JState(tif); + TIFFDirectory *td = &tif->tif_dir; + static const char module[] = "JPEGPreDecode"; + uint32 segment_width, segment_height; + int downsampled_output; + int ci; + + assert(sp != NULL); + assert(sp->cinfo.comm.is_decompressor); + /* + * Reset decoder state from any previous strip/tile, + * in case application didn't read the whole strip. + */ + if (!TIFFjpeg_abort(sp)) + return (0); + /* + * Read the header for this strip/tile. + */ + if (TIFFjpeg_read_header(sp, TRUE) != JPEG_HEADER_OK) + return (0); + /* + * Check image parameters and set decompression parameters. + */ + segment_width = td->td_imagewidth; + segment_height = td->td_imagelength - tif->tif_row; + if (isTiled(tif)) { + segment_width = td->td_tilewidth; + segment_height = td->td_tilelength; + sp->bytesperline = TIFFTileRowSize(tif); + } else { + if (segment_height > td->td_rowsperstrip) + segment_height = td->td_rowsperstrip; + sp->bytesperline = TIFFOldScanlineSize(tif); + } + if (td->td_planarconfig == PLANARCONFIG_SEPARATE && s > 0) { + /* + * For PC 2, scale down the expected strip/tile size + * to match a downsampled component + */ + segment_width = TIFFhowmany(segment_width, sp->h_sampling); + segment_height = TIFFhowmany(segment_height, sp->v_sampling); + } + if (sp->cinfo.d.image_width < segment_width || + sp->cinfo.d.image_height < segment_height) { + TIFFWarningExt(tif->tif_clientdata, module, + "Improper JPEG strip/tile size, " + "expected %dx%d, got %dx%d", + segment_width, segment_height, + sp->cinfo.d.image_width, + sp->cinfo.d.image_height); + } + if (sp->cinfo.d.image_width > segment_width || + sp->cinfo.d.image_height > segment_height) { + /* + * This case could be dangerous, if the strip or tile size has + * been reported as less than the amount of data jpeg will + * return, some potential security issues arise. Catch this + * case and error out. + */ + TIFFErrorExt(tif->tif_clientdata, module, + "JPEG strip/tile size exceeds expected dimensions," + " expected %dx%d, got %dx%d", + segment_width, segment_height, + sp->cinfo.d.image_width, sp->cinfo.d.image_height); + return (0); + } + if (sp->cinfo.d.num_components != + (td->td_planarconfig == PLANARCONFIG_CONTIG ? + td->td_samplesperpixel : 1)) { + TIFFErrorExt(tif->tif_clientdata, module, "Improper JPEG component count"); + return (0); + } +#ifdef JPEG_LIB_MK1 + if (12 != td->td_bitspersample && 8 != td->td_bitspersample) { + TIFFErrorExt(tif->tif_clientdata, module, "Improper JPEG data precision"); + return (0); + } + sp->cinfo.d.data_precision = td->td_bitspersample; + sp->cinfo.d.bits_in_jsample = td->td_bitspersample; +#else + if (sp->cinfo.d.data_precision != td->td_bitspersample) { + TIFFErrorExt(tif->tif_clientdata, module, "Improper JPEG data precision"); + return (0); + } +#endif + if (td->td_planarconfig == PLANARCONFIG_CONTIG) { + /* Component 0 should have expected sampling factors */ + if (sp->cinfo.d.comp_info[0].h_samp_factor != sp->h_sampling || + sp->cinfo.d.comp_info[0].v_samp_factor != sp->v_sampling) { + TIFFWarningExt(tif->tif_clientdata, module, + "Improper JPEG sampling factors %d,%d\n" + "Apparently should be %d,%d.", + sp->cinfo.d.comp_info[0].h_samp_factor, + sp->cinfo.d.comp_info[0].v_samp_factor, + sp->h_sampling, sp->v_sampling); + + /* + * There are potential security issues here + * for decoders that have already allocated + * buffers based on the expected sampling + * factors. Lets check the sampling factors + * dont exceed what we were expecting. + */ + if (sp->cinfo.d.comp_info[0].h_samp_factor + > sp->h_sampling + || sp->cinfo.d.comp_info[0].v_samp_factor + > sp->v_sampling) { + TIFFErrorExt(tif->tif_clientdata, + module, + "Cannot honour JPEG sampling factors" + " that exceed those specified."); + return (0); + } + + /* + * XXX: Files written by the Intergraph software + * has different sampling factors stored in the + * TIFF tags and in the JPEG structures. We will + * try to deduce Intergraph files by the presense + * of the tag 33918. + */ + if (!_TIFFFindFieldInfo(tif, 33918, TIFF_ANY)) { + TIFFWarningExt(tif->tif_clientdata, module, + "Decompressor will try reading with " + "sampling %d,%d.", + sp->cinfo.d.comp_info[0].h_samp_factor, + sp->cinfo.d.comp_info[0].v_samp_factor); + + sp->h_sampling = (uint16) + sp->cinfo.d.comp_info[0].h_samp_factor; + sp->v_sampling = (uint16) + sp->cinfo.d.comp_info[0].v_samp_factor; + } + } + /* Rest should have sampling factors 1,1 */ + for (ci = 1; ci < sp->cinfo.d.num_components; ci++) { + if (sp->cinfo.d.comp_info[ci].h_samp_factor != 1 || + sp->cinfo.d.comp_info[ci].v_samp_factor != 1) { + TIFFErrorExt(tif->tif_clientdata, module, "Improper JPEG sampling factors"); + return (0); + } + } + } else { + /* PC 2's single component should have sampling factors 1,1 */ + if (sp->cinfo.d.comp_info[0].h_samp_factor != 1 || + sp->cinfo.d.comp_info[0].v_samp_factor != 1) { + TIFFErrorExt(tif->tif_clientdata, module, "Improper JPEG sampling factors"); + return (0); + } + } + downsampled_output = FALSE; + if (td->td_planarconfig == PLANARCONFIG_CONTIG && + sp->photometric == PHOTOMETRIC_YCBCR && + sp->jpegcolormode == JPEGCOLORMODE_RGB) { + /* Convert YCbCr to RGB */ + sp->cinfo.d.jpeg_color_space = JCS_YCbCr; + sp->cinfo.d.out_color_space = JCS_RGB; + } else { + /* Suppress colorspace handling */ + sp->cinfo.d.jpeg_color_space = JCS_UNKNOWN; + sp->cinfo.d.out_color_space = JCS_UNKNOWN; + if (td->td_planarconfig == PLANARCONFIG_CONTIG && + (sp->h_sampling != 1 || sp->v_sampling != 1)) + downsampled_output = TRUE; + /* XXX what about up-sampling? */ + } + if (downsampled_output) { + /* Need to use raw-data interface to libjpeg */ + sp->cinfo.d.raw_data_out = TRUE; + tif->tif_decoderow = JPEGDecodeRaw; + tif->tif_decodestrip = JPEGDecodeRaw; + tif->tif_decodetile = JPEGDecodeRaw; + } else { + /* Use normal interface to libjpeg */ + sp->cinfo.d.raw_data_out = FALSE; + tif->tif_decoderow = JPEGDecode; + tif->tif_decodestrip = JPEGDecode; + tif->tif_decodetile = JPEGDecode; + } + /* Start JPEG decompressor */ + if (!TIFFjpeg_start_decompress(sp)) + return (0); + /* Allocate downsampled-data buffers if needed */ + if (downsampled_output) { + if (!alloc_downsampled_buffers(tif, sp->cinfo.d.comp_info, + sp->cinfo.d.num_components)) + return (0); + sp->scancount = DCTSIZE; /* mark buffer empty */ + } + return (1); +} + +/* + * Decode a chunk of pixels. + * "Standard" case: returned data is not downsampled. + */ +/*ARGSUSED*/ static int +JPEGDecode(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s) +{ + JPEGState *sp = JState(tif); + tsize_t nrows; + (void) s; + + nrows = cc / sp->bytesperline; + if (cc % sp->bytesperline) + TIFFWarningExt(tif->tif_clientdata, tif->tif_name, "fractional scanline not read"); + + if( nrows > (int) sp->cinfo.d.image_height ) + nrows = sp->cinfo.d.image_height; + + /* data is expected to be read in multiples of a scanline */ + if (nrows) + { + JSAMPROW line_work_buf = NULL; + + /* + ** For 6B, only use temporary buffer for 12 bit imagery. + ** For Mk1 always use it. + */ +#if !defined(JPEG_LIB_MK1) + if( sp->cinfo.d.data_precision == 12 ) +#endif + { + line_work_buf = (JSAMPROW) + _TIFFmalloc(sizeof(short) * sp->cinfo.d.output_width + * sp->cinfo.d.num_components ); + } + + do { + if( line_work_buf != NULL ) + { + /* + ** In the MK1 case, we aways read into a 16bit buffer, and then + ** pack down to 12bit or 8bit. In 6B case we only read into 16 + ** bit buffer for 12bit data, which we need to repack. + */ + if (TIFFjpeg_read_scanlines(sp, &line_work_buf, 1) != 1) + return (0); + + if( sp->cinfo.d.data_precision == 12 ) + { + int value_pairs = (sp->cinfo.d.output_width + * sp->cinfo.d.num_components) / 2; + int iPair; + + for( iPair = 0; iPair < value_pairs; iPair++ ) + { + unsigned char *out_ptr = + ((unsigned char *) buf) + iPair * 3; + JSAMPLE *in_ptr = line_work_buf + iPair * 2; + + out_ptr[0] = (in_ptr[0] & 0xff0) >> 4; + out_ptr[1] = ((in_ptr[0] & 0xf) << 4) + | ((in_ptr[1] & 0xf00) >> 8); + out_ptr[2] = ((in_ptr[1] & 0xff) >> 0); + } + } + else if( sp->cinfo.d.data_precision == 8 ) + { + int value_count = (sp->cinfo.d.output_width + * sp->cinfo.d.num_components); + int iValue; + + for( iValue = 0; iValue < value_count; iValue++ ) + { + ((unsigned char *) buf)[iValue] = + line_work_buf[iValue] & 0xff; + } + } + } + else + { + /* + ** In the libjpeg6b 8bit case. We read directly into the + ** TIFF buffer. + */ + JSAMPROW bufptr = (JSAMPROW)buf; + + if (TIFFjpeg_read_scanlines(sp, &bufptr, 1) != 1) + return (0); + } + + ++tif->tif_row; + buf += sp->bytesperline; + cc -= sp->bytesperline; + } while (--nrows > 0); + + if( line_work_buf != NULL ) + _TIFFfree( line_work_buf ); + } + + /* Close down the decompressor if we've finished the strip or tile. */ + return sp->cinfo.d.output_scanline < sp->cinfo.d.output_height + || TIFFjpeg_finish_decompress(sp); +} + +/* + * Decode a chunk of pixels. + * Returned data is downsampled per sampling factors. + */ +/*ARGSUSED*/ static int +JPEGDecodeRaw(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s) +{ + JPEGState *sp = JState(tif); + tsize_t nrows; + (void) s; + + /* data is expected to be read in multiples of a scanline */ + if ( (nrows = sp->cinfo.d.image_height) ) { + /* Cb,Cr both have sampling factors 1, so this is correct */ + JDIMENSION clumps_per_line = sp->cinfo.d.comp_info[1].downsampled_width; + int samples_per_clump = sp->samplesperclump; + +#ifdef JPEG_LIB_MK1 + unsigned short* tmpbuf = _TIFFmalloc(sizeof(unsigned short) * + sp->cinfo.d.output_width * + sp->cinfo.d.num_components); +#endif + + do { + jpeg_component_info *compptr; + int ci, clumpoffset; + + /* Reload downsampled-data buffer if needed */ + if (sp->scancount >= DCTSIZE) { + int n = sp->cinfo.d.max_v_samp_factor * DCTSIZE; + if (TIFFjpeg_read_raw_data(sp, sp->ds_buffer, n) != n) + return (0); + sp->scancount = 0; + } + /* + * Fastest way to unseparate data is to make one pass + * over the scanline for each row of each component. + */ + clumpoffset = 0; /* first sample in clump */ + for (ci = 0, compptr = sp->cinfo.d.comp_info; + ci < sp->cinfo.d.num_components; + ci++, compptr++) { + int hsamp = compptr->h_samp_factor; + int vsamp = compptr->v_samp_factor; + int ypos; + + for (ypos = 0; ypos < vsamp; ypos++) { + JSAMPLE *inptr = sp->ds_buffer[ci][sp->scancount*vsamp + ypos]; +#ifdef JPEG_LIB_MK1 + JSAMPLE *outptr = (JSAMPLE*)tmpbuf + clumpoffset; +#else + JSAMPLE *outptr = (JSAMPLE*)buf + clumpoffset; +#endif + JDIMENSION nclump; + + if (hsamp == 1) { + /* fast path for at least Cb and Cr */ + for (nclump = clumps_per_line; nclump-- > 0; ) { + outptr[0] = *inptr++; + outptr += samples_per_clump; + } + } else { + int xpos; + + /* general case */ + for (nclump = clumps_per_line; nclump-- > 0; ) { + for (xpos = 0; xpos < hsamp; xpos++) + outptr[xpos] = *inptr++; + outptr += samples_per_clump; + } + } + clumpoffset += hsamp; + } + } + +#ifdef JPEG_LIB_MK1 + { + if (sp->cinfo.d.data_precision == 8) + { + int i=0; + int len = sp->cinfo.d.output_width * sp->cinfo.d.num_components; + for (i=0; icinfo.d.output_width + * sp->cinfo.d.num_components) / 2; + int iPair; + for( iPair = 0; iPair < value_pairs; iPair++ ) + { + unsigned char *out_ptr = ((unsigned char *) buf) + iPair * 3; + JSAMPLE *in_ptr = tmpbuf + iPair * 2; + out_ptr[0] = (in_ptr[0] & 0xff0) >> 4; + out_ptr[1] = ((in_ptr[0] & 0xf) << 4) + | ((in_ptr[1] & 0xf00) >> 8); + out_ptr[2] = ((in_ptr[1] & 0xff) >> 0); + } + } + } +#endif + + sp->scancount ++; + tif->tif_row += sp->v_sampling; + /* increment/decrement of buf and cc is still incorrect, but should not matter + * TODO: resolve this */ + buf += sp->bytesperline; + cc -= sp->bytesperline; + nrows -= sp->v_sampling; + } while (nrows > 0); + +#ifdef JPEG_LIB_MK1 + _TIFFfree(tmpbuf); +#endif + + } + + /* Close down the decompressor if done. */ + return sp->cinfo.d.output_scanline < sp->cinfo.d.output_height + || TIFFjpeg_finish_decompress(sp); +} + + +/* + * JPEG Encoding. + */ + +static void +unsuppress_quant_table (JPEGState* sp, int tblno) +{ + JQUANT_TBL* qtbl; + + if ((qtbl = sp->cinfo.c.quant_tbl_ptrs[tblno]) != NULL) + qtbl->sent_table = FALSE; +} + +static void +unsuppress_huff_table (JPEGState* sp, int tblno) +{ + JHUFF_TBL* htbl; + + if ((htbl = sp->cinfo.c.dc_huff_tbl_ptrs[tblno]) != NULL) + htbl->sent_table = FALSE; + if ((htbl = sp->cinfo.c.ac_huff_tbl_ptrs[tblno]) != NULL) + htbl->sent_table = FALSE; +} + +static int +prepare_JPEGTables(TIFF* tif) +{ + JPEGState* sp = JState(tif); + + JPEGInitializeLibJPEG( tif, 0, 0 ); + + /* Initialize quant tables for current quality setting */ + if (!TIFFjpeg_set_quality(sp, sp->jpegquality, FALSE)) + return (0); + /* Mark only the tables we want for output */ + /* NB: chrominance tables are currently used only with YCbCr */ + if (!TIFFjpeg_suppress_tables(sp, TRUE)) + return (0); + if (sp->jpegtablesmode & JPEGTABLESMODE_QUANT) { + unsuppress_quant_table(sp, 0); + if (sp->photometric == PHOTOMETRIC_YCBCR) + unsuppress_quant_table(sp, 1); + } + if (sp->jpegtablesmode & JPEGTABLESMODE_HUFF) { + unsuppress_huff_table(sp, 0); + if (sp->photometric == PHOTOMETRIC_YCBCR) + unsuppress_huff_table(sp, 1); + } + /* Direct libjpeg output into jpegtables */ + if (!TIFFjpeg_tables_dest(sp, tif)) + return (0); + /* Emit tables-only datastream */ + if (!TIFFjpeg_write_tables(sp)) + return (0); + + return (1); +} + +static int +JPEGSetupEncode(TIFF* tif) +{ + JPEGState* sp = JState(tif); + TIFFDirectory *td = &tif->tif_dir; + static const char module[] = "JPEGSetupEncode"; + + JPEGInitializeLibJPEG( tif, 1, 0 ); + + assert(sp != NULL); + assert(!sp->cinfo.comm.is_decompressor); + + /* + * Initialize all JPEG parameters to default values. + * Note that jpeg_set_defaults needs legal values for + * in_color_space and input_components. + */ + sp->cinfo.c.in_color_space = JCS_UNKNOWN; + sp->cinfo.c.input_components = 1; + if (!TIFFjpeg_set_defaults(sp)) + return (0); + /* Set per-file parameters */ + sp->photometric = td->td_photometric; + switch (sp->photometric) { + case PHOTOMETRIC_YCBCR: + sp->h_sampling = td->td_ycbcrsubsampling[0]; + sp->v_sampling = td->td_ycbcrsubsampling[1]; + /* + * A ReferenceBlackWhite field *must* be present since the + * default value is inappropriate for YCbCr. Fill in the + * proper value if application didn't set it. + */ + { + float *ref; + if (!TIFFGetField(tif, TIFFTAG_REFERENCEBLACKWHITE, + &ref)) { + float refbw[6]; + long top = 1L << td->td_bitspersample; + refbw[0] = 0; + refbw[1] = (float)(top-1L); + refbw[2] = (float)(top>>1); + refbw[3] = refbw[1]; + refbw[4] = refbw[2]; + refbw[5] = refbw[1]; + TIFFSetField(tif, TIFFTAG_REFERENCEBLACKWHITE, + refbw); + } + } + break; + case PHOTOMETRIC_PALETTE: /* disallowed by Tech Note */ + case PHOTOMETRIC_MASK: + TIFFErrorExt(tif->tif_clientdata, module, + "PhotometricInterpretation %d not allowed for JPEG", + (int) sp->photometric); + return (0); + default: + /* TIFF 6.0 forbids subsampling of all other color spaces */ + sp->h_sampling = 1; + sp->v_sampling = 1; + break; + } + + /* Verify miscellaneous parameters */ + + /* + * This would need work if libtiff ever supports different + * depths for different components, or if libjpeg ever supports + * run-time selection of depth. Neither is imminent. + */ +#ifdef JPEG_LIB_MK1 + /* BITS_IN_JSAMPLE now permits 8 and 12 --- dgilbert */ + if (td->td_bitspersample != 8 && td->td_bitspersample != 12) +#else + if (td->td_bitspersample != BITS_IN_JSAMPLE ) +#endif + { + TIFFErrorExt(tif->tif_clientdata, module, "BitsPerSample %d not allowed for JPEG", + (int) td->td_bitspersample); + return (0); + } + sp->cinfo.c.data_precision = td->td_bitspersample; +#ifdef JPEG_LIB_MK1 + sp->cinfo.c.bits_in_jsample = td->td_bitspersample; +#endif + if (isTiled(tif)) { + if ((td->td_tilelength % (sp->v_sampling * DCTSIZE)) != 0) { + TIFFErrorExt(tif->tif_clientdata, module, + "JPEG tile height must be multiple of %d", + sp->v_sampling * DCTSIZE); + return (0); + } + if ((td->td_tilewidth % (sp->h_sampling * DCTSIZE)) != 0) { + TIFFErrorExt(tif->tif_clientdata, module, + "JPEG tile width must be multiple of %d", + sp->h_sampling * DCTSIZE); + return (0); + } + } else { + if (td->td_rowsperstrip < td->td_imagelength && + (td->td_rowsperstrip % (sp->v_sampling * DCTSIZE)) != 0) { + TIFFErrorExt(tif->tif_clientdata, module, + "RowsPerStrip must be multiple of %d for JPEG", + sp->v_sampling * DCTSIZE); + return (0); + } + } + + /* Create a JPEGTables field if appropriate */ + if (sp->jpegtablesmode & (JPEGTABLESMODE_QUANT|JPEGTABLESMODE_HUFF)) { + if( sp->jpegtables == NULL + || memcmp(sp->jpegtables,"\0\0\0\0\0\0\0\0\0",8) == 0 ) + { + if (!prepare_JPEGTables(tif)) + return (0); + /* Mark the field present */ + /* Can't use TIFFSetField since BEENWRITING is already set! */ + tif->tif_flags |= TIFF_DIRTYDIRECT; + TIFFSetFieldBit(tif, FIELD_JPEGTABLES); + } + } else { + /* We do not support application-supplied JPEGTables, */ + /* so mark the field not present */ + TIFFClrFieldBit(tif, FIELD_JPEGTABLES); + } + + /* Direct libjpeg output to libtiff's output buffer */ + TIFFjpeg_data_dest(sp, tif); + + return (1); +} + +/* + * Set encoding state at the start of a strip or tile. + */ +static int +JPEGPreEncode(TIFF* tif, tsample_t s) +{ + JPEGState *sp = JState(tif); + TIFFDirectory *td = &tif->tif_dir; + static const char module[] = "JPEGPreEncode"; + uint32 segment_width, segment_height; + int downsampled_input; + + assert(sp != NULL); + assert(!sp->cinfo.comm.is_decompressor); + /* + * Set encoding parameters for this strip/tile. + */ + if (isTiled(tif)) { + segment_width = td->td_tilewidth; + segment_height = td->td_tilelength; + sp->bytesperline = TIFFTileRowSize(tif); + } else { + segment_width = td->td_imagewidth; + segment_height = td->td_imagelength - tif->tif_row; + if (segment_height > td->td_rowsperstrip) + segment_height = td->td_rowsperstrip; + sp->bytesperline = TIFFOldScanlineSize(tif); + } + if (td->td_planarconfig == PLANARCONFIG_SEPARATE && s > 0) { + /* for PC 2, scale down the strip/tile size + * to match a downsampled component + */ + segment_width = TIFFhowmany(segment_width, sp->h_sampling); + segment_height = TIFFhowmany(segment_height, sp->v_sampling); + } + if (segment_width > 65535 || segment_height > 65535) { + TIFFErrorExt(tif->tif_clientdata, module, "Strip/tile too large for JPEG"); + return (0); + } + sp->cinfo.c.image_width = segment_width; + sp->cinfo.c.image_height = segment_height; + downsampled_input = FALSE; + if (td->td_planarconfig == PLANARCONFIG_CONTIG) { + sp->cinfo.c.input_components = td->td_samplesperpixel; + if (sp->photometric == PHOTOMETRIC_YCBCR) { + if (sp->jpegcolormode == JPEGCOLORMODE_RGB) { + sp->cinfo.c.in_color_space = JCS_RGB; + } else { + sp->cinfo.c.in_color_space = JCS_YCbCr; + if (sp->h_sampling != 1 || sp->v_sampling != 1) + downsampled_input = TRUE; + } + if (!TIFFjpeg_set_colorspace(sp, JCS_YCbCr)) + return (0); + /* + * Set Y sampling factors; + * we assume jpeg_set_colorspace() set the rest to 1 + */ + sp->cinfo.c.comp_info[0].h_samp_factor = sp->h_sampling; + sp->cinfo.c.comp_info[0].v_samp_factor = sp->v_sampling; + } else { + sp->cinfo.c.in_color_space = JCS_UNKNOWN; + if (!TIFFjpeg_set_colorspace(sp, JCS_UNKNOWN)) + return (0); + /* jpeg_set_colorspace set all sampling factors to 1 */ + } + } else { + sp->cinfo.c.input_components = 1; + sp->cinfo.c.in_color_space = JCS_UNKNOWN; + if (!TIFFjpeg_set_colorspace(sp, JCS_UNKNOWN)) + return (0); + sp->cinfo.c.comp_info[0].component_id = s; + /* jpeg_set_colorspace() set sampling factors to 1 */ + if (sp->photometric == PHOTOMETRIC_YCBCR && s > 0) { + sp->cinfo.c.comp_info[0].quant_tbl_no = 1; + sp->cinfo.c.comp_info[0].dc_tbl_no = 1; + sp->cinfo.c.comp_info[0].ac_tbl_no = 1; + } + } + /* ensure libjpeg won't write any extraneous markers */ + sp->cinfo.c.write_JFIF_header = FALSE; + sp->cinfo.c.write_Adobe_marker = FALSE; + /* set up table handling correctly */ + if (!TIFFjpeg_set_quality(sp, sp->jpegquality, FALSE)) + return (0); + if (! (sp->jpegtablesmode & JPEGTABLESMODE_QUANT)) { + unsuppress_quant_table(sp, 0); + unsuppress_quant_table(sp, 1); + } + if (sp->jpegtablesmode & JPEGTABLESMODE_HUFF) + sp->cinfo.c.optimize_coding = FALSE; + else + sp->cinfo.c.optimize_coding = TRUE; + if (downsampled_input) { + /* Need to use raw-data interface to libjpeg */ + sp->cinfo.c.raw_data_in = TRUE; + tif->tif_encoderow = JPEGEncodeRaw; + tif->tif_encodestrip = JPEGEncodeRaw; + tif->tif_encodetile = JPEGEncodeRaw; + } else { + /* Use normal interface to libjpeg */ + sp->cinfo.c.raw_data_in = FALSE; + tif->tif_encoderow = JPEGEncode; + tif->tif_encodestrip = JPEGEncode; + tif->tif_encodetile = JPEGEncode; + } + /* Start JPEG compressor */ + if (!TIFFjpeg_start_compress(sp, FALSE)) + return (0); + /* Allocate downsampled-data buffers if needed */ + if (downsampled_input) { + if (!alloc_downsampled_buffers(tif, sp->cinfo.c.comp_info, + sp->cinfo.c.num_components)) + return (0); + } + sp->scancount = 0; + + return (1); +} + +/* + * Encode a chunk of pixels. + * "Standard" case: incoming data is not downsampled. + */ +static int +JPEGEncode(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s) +{ + JPEGState *sp = JState(tif); + tsize_t nrows; + JSAMPROW bufptr[1]; + + (void) s; + assert(sp != NULL); + /* data is expected to be supplied in multiples of a scanline */ + nrows = cc / sp->bytesperline; + if (cc % sp->bytesperline) + TIFFWarningExt(tif->tif_clientdata, tif->tif_name, "fractional scanline discarded"); + + /* The last strip will be limited to image size */ + if( !isTiled(tif) && tif->tif_row+nrows > tif->tif_dir.td_imagelength ) + nrows = tif->tif_dir.td_imagelength - tif->tif_row; + + while (nrows-- > 0) { + bufptr[0] = (JSAMPROW) buf; + if (TIFFjpeg_write_scanlines(sp, bufptr, 1) != 1) + return (0); + if (nrows > 0) + tif->tif_row++; + buf += sp->bytesperline; + } + return (1); +} + +/* + * Encode a chunk of pixels. + * Incoming data is expected to be downsampled per sampling factors. + */ +static int +JPEGEncodeRaw(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s) +{ + JPEGState *sp = JState(tif); + JSAMPLE* inptr; + JSAMPLE* outptr; + tsize_t nrows; + JDIMENSION clumps_per_line, nclump; + int clumpoffset, ci, xpos, ypos; + jpeg_component_info* compptr; + int samples_per_clump = sp->samplesperclump; + tsize_t bytesperclumpline; + + (void) s; + assert(sp != NULL); + /* data is expected to be supplied in multiples of a clumpline */ + /* a clumpline is equivalent to v_sampling desubsampled scanlines */ + /* TODO: the following calculation of bytesperclumpline, should substitute calculation of sp->bytesperline, except that it is per v_sampling lines */ + bytesperclumpline = (((sp->cinfo.c.image_width+sp->h_sampling-1)/sp->h_sampling) + *(sp->h_sampling*sp->v_sampling+2)*sp->cinfo.c.data_precision+7) + /8; + + nrows = ( cc / bytesperclumpline ) * sp->v_sampling; + if (cc % bytesperclumpline) + TIFFWarningExt(tif->tif_clientdata, tif->tif_name, "fractional scanline discarded"); + + /* Cb,Cr both have sampling factors 1, so this is correct */ + clumps_per_line = sp->cinfo.c.comp_info[1].downsampled_width; + + while (nrows > 0) { + /* + * Fastest way to separate the data is to make one pass + * over the scanline for each row of each component. + */ + clumpoffset = 0; /* first sample in clump */ + for (ci = 0, compptr = sp->cinfo.c.comp_info; + ci < sp->cinfo.c.num_components; + ci++, compptr++) { + int hsamp = compptr->h_samp_factor; + int vsamp = compptr->v_samp_factor; + int padding = (int) (compptr->width_in_blocks * DCTSIZE - + clumps_per_line * hsamp); + for (ypos = 0; ypos < vsamp; ypos++) { + inptr = ((JSAMPLE*) buf) + clumpoffset; + outptr = sp->ds_buffer[ci][sp->scancount*vsamp + ypos]; + if (hsamp == 1) { + /* fast path for at least Cb and Cr */ + for (nclump = clumps_per_line; nclump-- > 0; ) { + *outptr++ = inptr[0]; + inptr += samples_per_clump; + } + } else { + /* general case */ + for (nclump = clumps_per_line; nclump-- > 0; ) { + for (xpos = 0; xpos < hsamp; xpos++) + *outptr++ = inptr[xpos]; + inptr += samples_per_clump; + } + } + /* pad each scanline as needed */ + for (xpos = 0; xpos < padding; xpos++) { + *outptr = outptr[-1]; + outptr++; + } + clumpoffset += hsamp; + } + } + sp->scancount++; + if (sp->scancount >= DCTSIZE) { + int n = sp->cinfo.c.max_v_samp_factor * DCTSIZE; + if (TIFFjpeg_write_raw_data(sp, sp->ds_buffer, n) != n) + return (0); + sp->scancount = 0; + } + tif->tif_row += sp->v_sampling; + buf += sp->bytesperline; + nrows -= sp->v_sampling; + } + return (1); +} + +/* + * Finish up at the end of a strip or tile. + */ +static int +JPEGPostEncode(TIFF* tif) +{ + JPEGState *sp = JState(tif); + + if (sp->scancount > 0) { + /* + * Need to emit a partial bufferload of downsampled data. + * Pad the data vertically. + */ + int ci, ypos, n; + jpeg_component_info* compptr; + + for (ci = 0, compptr = sp->cinfo.c.comp_info; + ci < sp->cinfo.c.num_components; + ci++, compptr++) { + int vsamp = compptr->v_samp_factor; + tsize_t row_width = compptr->width_in_blocks * DCTSIZE + * sizeof(JSAMPLE); + for (ypos = sp->scancount * vsamp; + ypos < DCTSIZE * vsamp; ypos++) { + _TIFFmemcpy((tdata_t)sp->ds_buffer[ci][ypos], + (tdata_t)sp->ds_buffer[ci][ypos-1], + row_width); + + } + } + n = sp->cinfo.c.max_v_samp_factor * DCTSIZE; + if (TIFFjpeg_write_raw_data(sp, sp->ds_buffer, n) != n) + return (0); + } + + return (TIFFjpeg_finish_compress(JState(tif))); +} + +static void +JPEGCleanup(TIFF* tif) +{ + JPEGState *sp = JState(tif); + + assert(sp != 0); + + tif->tif_tagmethods.vgetfield = sp->vgetparent; + tif->tif_tagmethods.vsetfield = sp->vsetparent; + tif->tif_tagmethods.printdir = sp->printdir; + + if( sp->cinfo_initialized ) + TIFFjpeg_destroy(sp); /* release libjpeg resources */ + if (sp->jpegtables) /* tag value */ + _TIFFfree(sp->jpegtables); + _TIFFfree(tif->tif_data); /* release local state */ + tif->tif_data = NULL; + + _TIFFSetDefaultCompressionState(tif); +} + +static void +JPEGResetUpsampled( TIFF* tif ) +{ + JPEGState* sp = JState(tif); + TIFFDirectory* td = &tif->tif_dir; + + /* + * Mark whether returned data is up-sampled or not so TIFFStripSize + * and TIFFTileSize return values that reflect the true amount of + * data. + */ + tif->tif_flags &= ~TIFF_UPSAMPLED; + if (td->td_planarconfig == PLANARCONFIG_CONTIG) { + if (td->td_photometric == PHOTOMETRIC_YCBCR && + sp->jpegcolormode == JPEGCOLORMODE_RGB) { + tif->tif_flags |= TIFF_UPSAMPLED; + } else { +#ifdef notdef + if (td->td_ycbcrsubsampling[0] != 1 || + td->td_ycbcrsubsampling[1] != 1) + ; /* XXX what about up-sampling? */ +#endif + } + } + + /* + * Must recalculate cached tile size in case sampling state changed. + * Should we really be doing this now if image size isn't set? + */ + if( tif->tif_tilesize > 0 ) + tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tsize_t) -1; + + if(tif->tif_scanlinesize > 0 ) + tif->tif_scanlinesize = TIFFScanlineSize(tif); +} + +static int +JPEGVSetField(TIFF* tif, ttag_t tag, va_list ap) +{ + JPEGState* sp = JState(tif); + const TIFFFieldInfo* fip; + uint32 v32; + + assert(sp != NULL); + + switch (tag) { + case TIFFTAG_JPEGTABLES: + v32 = va_arg(ap, uint32); + if (v32 == 0) { + /* XXX */ + return (0); + } + _TIFFsetByteArray(&sp->jpegtables, va_arg(ap, void*), + (long) v32); + sp->jpegtables_length = v32; + TIFFSetFieldBit(tif, FIELD_JPEGTABLES); + break; + case TIFFTAG_JPEGQUALITY: + sp->jpegquality = va_arg(ap, int); + return (1); /* pseudo tag */ + case TIFFTAG_JPEGCOLORMODE: + sp->jpegcolormode = va_arg(ap, int); + JPEGResetUpsampled( tif ); + return (1); /* pseudo tag */ + case TIFFTAG_PHOTOMETRIC: + { + int ret_value = (*sp->vsetparent)(tif, tag, ap); + JPEGResetUpsampled( tif ); + return ret_value; + } + case TIFFTAG_JPEGTABLESMODE: + sp->jpegtablesmode = va_arg(ap, int); + return (1); /* pseudo tag */ + case TIFFTAG_YCBCRSUBSAMPLING: + /* mark the fact that we have a real ycbcrsubsampling! */ + sp->ycbcrsampling_fetched = 1; + /* should we be recomputing upsampling info here? */ + return (*sp->vsetparent)(tif, tag, ap); + case TIFFTAG_FAXRECVPARAMS: + sp->recvparams = va_arg(ap, uint32); + break; + case TIFFTAG_FAXSUBADDRESS: + _TIFFsetString(&sp->subaddress, va_arg(ap, char*)); + break; + case TIFFTAG_FAXRECVTIME: + sp->recvtime = va_arg(ap, uint32); + break; + case TIFFTAG_FAXDCS: + _TIFFsetString(&sp->faxdcs, va_arg(ap, char*)); + break; + default: + return (*sp->vsetparent)(tif, tag, ap); + } + + if ((fip = _TIFFFieldWithTag(tif, tag))) { + TIFFSetFieldBit(tif, fip->field_bit); + } else { + return (0); + } + + tif->tif_flags |= TIFF_DIRTYDIRECT; + return (1); +} + +/* + * Some JPEG-in-TIFF produces do not emit the YCBCRSUBSAMPLING values in + * the TIFF tags, but still use non-default (2,2) values within the jpeg + * data stream itself. In order for TIFF applications to work properly + * - for instance to get the strip buffer size right - it is imperative + * that the subsampling be available before we start reading the image + * data normally. This function will attempt to load the first strip in + * order to get the sampling values from the jpeg data stream. Various + * hacks are various places are done to ensure this function gets called + * before the td_ycbcrsubsampling values are used from the directory structure, + * including calling TIFFGetField() for the YCBCRSUBSAMPLING field from + * TIFFStripSize(), and the printing code in tif_print.c. + * + * Note that JPEGPreDeocode() will produce a fairly loud warning when the + * discovered sampling does not match the default sampling (2,2) or whatever + * was actually in the tiff tags. + * + * Problems: + * o This code will cause one whole strip/tile of compressed data to be + * loaded just to get the tags right, even if the imagery is never read. + * It would be more efficient to just load a bit of the header, and + * initialize things from that. + * + * See the bug in bugzilla for details: + * + * http://bugzilla.remotesensing.org/show_bug.cgi?id=168 + * + * Frank Warmerdam, July 2002 + */ + +static void +JPEGFixupTestSubsampling( TIFF * tif ) +{ +#ifdef CHECK_JPEG_YCBCR_SUBSAMPLING + JPEGState *sp = JState(tif); + TIFFDirectory *td = &tif->tif_dir; + + JPEGInitializeLibJPEG( tif, 0, 0 ); + + /* + * Some JPEG-in-TIFF files don't provide the ycbcrsampling tags, + * and use a sampling schema other than the default 2,2. To handle + * this we actually have to scan the header of a strip or tile of + * jpeg data to get the sampling. + */ + if( !sp->cinfo.comm.is_decompressor + || sp->ycbcrsampling_fetched + || td->td_photometric != PHOTOMETRIC_YCBCR ) + return; + + sp->ycbcrsampling_fetched = 1; + if( TIFFIsTiled( tif ) ) + { + if( !TIFFFillTile( tif, 0 ) ) + return; + } + else + { + if( !TIFFFillStrip( tif, 0 ) ) + return; + } + + TIFFSetField( tif, TIFFTAG_YCBCRSUBSAMPLING, + (uint16) sp->h_sampling, (uint16) sp->v_sampling ); + + /* + ** We want to clear the loaded strip so the application has time + ** to set JPEGCOLORMODE or other behavior modifiers. This essentially + ** undoes the JPEGPreDecode triggers by TIFFFileStrip(). (#1936) + */ + tif->tif_curstrip = -1; + +#endif /* CHECK_JPEG_YCBCR_SUBSAMPLING */ +} + +static int +JPEGVGetField(TIFF* tif, ttag_t tag, va_list ap) +{ + JPEGState* sp = JState(tif); + + assert(sp != NULL); + + switch (tag) { + case TIFFTAG_JPEGTABLES: + *va_arg(ap, uint32*) = sp->jpegtables_length; + *va_arg(ap, void**) = sp->jpegtables; + break; + case TIFFTAG_JPEGQUALITY: + *va_arg(ap, int*) = sp->jpegquality; + break; + case TIFFTAG_JPEGCOLORMODE: + *va_arg(ap, int*) = sp->jpegcolormode; + break; + case TIFFTAG_JPEGTABLESMODE: + *va_arg(ap, int*) = sp->jpegtablesmode; + break; + case TIFFTAG_YCBCRSUBSAMPLING: + JPEGFixupTestSubsampling( tif ); + return (*sp->vgetparent)(tif, tag, ap); + case TIFFTAG_FAXRECVPARAMS: + *va_arg(ap, uint32*) = sp->recvparams; + break; + case TIFFTAG_FAXSUBADDRESS: + *va_arg(ap, char**) = sp->subaddress; + break; + case TIFFTAG_FAXRECVTIME: + *va_arg(ap, uint32*) = sp->recvtime; + break; + case TIFFTAG_FAXDCS: + *va_arg(ap, char**) = sp->faxdcs; + break; + default: + return (*sp->vgetparent)(tif, tag, ap); + } + return (1); +} + +static void +JPEGPrintDir(TIFF* tif, FILE* fd, long flags) +{ + JPEGState* sp = JState(tif); + + assert(sp != NULL); + + (void) flags; + if (TIFFFieldSet(tif,FIELD_JPEGTABLES)) + fprintf(fd, " JPEG Tables: (%lu bytes)\n", + (unsigned long) sp->jpegtables_length); + if (TIFFFieldSet(tif,FIELD_RECVPARAMS)) + fprintf(fd, " Fax Receive Parameters: %08lx\n", + (unsigned long) sp->recvparams); + if (TIFFFieldSet(tif,FIELD_SUBADDRESS)) + fprintf(fd, " Fax SubAddress: %s\n", sp->subaddress); + if (TIFFFieldSet(tif,FIELD_RECVTIME)) + fprintf(fd, " Fax Receive Time: %lu secs\n", + (unsigned long) sp->recvtime); + if (TIFFFieldSet(tif,FIELD_FAXDCS)) + fprintf(fd, " Fax DCS: %s\n", sp->faxdcs); +} + +static uint32 +JPEGDefaultStripSize(TIFF* tif, uint32 s) +{ + JPEGState* sp = JState(tif); + TIFFDirectory *td = &tif->tif_dir; + + s = (*sp->defsparent)(tif, s); + if (s < td->td_imagelength) + s = TIFFroundup(s, td->td_ycbcrsubsampling[1] * DCTSIZE); + return (s); +} + +static void +JPEGDefaultTileSize(TIFF* tif, uint32* tw, uint32* th) +{ + JPEGState* sp = JState(tif); + TIFFDirectory *td = &tif->tif_dir; + + (*sp->deftparent)(tif, tw, th); + *tw = TIFFroundup(*tw, td->td_ycbcrsubsampling[0] * DCTSIZE); + *th = TIFFroundup(*th, td->td_ycbcrsubsampling[1] * DCTSIZE); +} + +/* + * The JPEG library initialized used to be done in TIFFInitJPEG(), but + * now that we allow a TIFF file to be opened in update mode it is necessary + * to have some way of deciding whether compression or decompression is + * desired other than looking at tif->tif_mode. We accomplish this by + * examining {TILE/STRIP}BYTECOUNTS to see if there is a non-zero entry. + * If so, we assume decompression is desired. + * + * This is tricky, because TIFFInitJPEG() is called while the directory is + * being read, and generally speaking the BYTECOUNTS tag won't have been read + * at that point. So we try to defer jpeg library initialization till we + * do have that tag ... basically any access that might require the compressor + * or decompressor that occurs after the reading of the directory. + * + * In an ideal world compressors or decompressors would be setup + * at the point where a single tile or strip was accessed (for read or write) + * so that stuff like update of missing tiles, or replacement of tiles could + * be done. However, we aren't trying to crack that nut just yet ... + * + * NFW, Feb 3rd, 2003. + */ + +static int JPEGInitializeLibJPEG( TIFF * tif, int force_encode, int force_decode ) +{ + JPEGState* sp = JState(tif); + uint32 *byte_counts = NULL; + int data_is_empty = TRUE; + int decompress; + + + if(sp->cinfo_initialized) + { + if( force_encode && sp->cinfo.comm.is_decompressor ) + TIFFjpeg_destroy( sp ); + else if( force_decode && !sp->cinfo.comm.is_decompressor ) + TIFFjpeg_destroy( sp ); + else + return 1; + + sp->cinfo_initialized = 0; + } + + /* + * Do we have tile data already? Make sure we initialize the + * the state in decompressor mode if we have tile data, even if we + * are not in read-only file access mode. + */ + if( TIFFIsTiled( tif ) + && TIFFGetField( tif, TIFFTAG_TILEBYTECOUNTS, &byte_counts ) + && byte_counts != NULL ) + { + data_is_empty = byte_counts[0] == 0; + } + if( !TIFFIsTiled( tif ) + && TIFFGetField( tif, TIFFTAG_STRIPBYTECOUNTS, &byte_counts) + && byte_counts != NULL ) + { + data_is_empty = byte_counts[0] == 0; + } + + if( force_decode ) + decompress = 1; + else if( force_encode ) + decompress = 0; + else if( tif->tif_mode == O_RDONLY ) + decompress = 1; + else if( data_is_empty ) + decompress = 0; + else + decompress = 1; + + /* + * Initialize libjpeg. + */ + if ( decompress ) { + if (!TIFFjpeg_create_decompress(sp)) + return (0); + + } else { + if (!TIFFjpeg_create_compress(sp)) + return (0); + } + + sp->cinfo_initialized = TRUE; + + return 1; +} + +int +TIFFInitJPEG(TIFF* tif, int scheme) +{ + JPEGState* sp; + + assert(scheme == COMPRESSION_JPEG); + + /* + * Merge codec-specific tag information. + */ + if (!_TIFFMergeFieldInfo(tif, jpegFieldInfo, N(jpegFieldInfo))) { + TIFFErrorExt(tif->tif_clientdata, + "TIFFInitJPEG", + "Merging JPEG codec-specific tags failed"); + return 0; + } + + /* + * Allocate state block so tag methods have storage to record values. + */ + tif->tif_data = (tidata_t) _TIFFmalloc(sizeof (JPEGState)); + + if (tif->tif_data == NULL) { + TIFFErrorExt(tif->tif_clientdata, + "TIFFInitJPEG", "No space for JPEG state block"); + return 0; + } + _TIFFmemset(tif->tif_data, 0, sizeof(JPEGState)); + + sp = JState(tif); + sp->tif = tif; /* back link */ + + /* + * Override parent get/set field methods. + */ + sp->vgetparent = tif->tif_tagmethods.vgetfield; + tif->tif_tagmethods.vgetfield = JPEGVGetField; /* hook for codec tags */ + sp->vsetparent = tif->tif_tagmethods.vsetfield; + tif->tif_tagmethods.vsetfield = JPEGVSetField; /* hook for codec tags */ + sp->printdir = tif->tif_tagmethods.printdir; + tif->tif_tagmethods.printdir = JPEGPrintDir; /* hook for codec tags */ + + /* Default values for codec-specific fields */ + sp->jpegtables = NULL; + sp->jpegtables_length = 0; + sp->jpegquality = 75; /* Default IJG quality */ + sp->jpegcolormode = JPEGCOLORMODE_RAW; + sp->jpegtablesmode = JPEGTABLESMODE_QUANT | JPEGTABLESMODE_HUFF; + + sp->recvparams = 0; + sp->subaddress = NULL; + sp->faxdcs = NULL; + + sp->ycbcrsampling_fetched = 0; + + /* + * Install codec methods. + */ + tif->tif_setupdecode = JPEGSetupDecode; + tif->tif_predecode = JPEGPreDecode; + tif->tif_decoderow = JPEGDecode; + tif->tif_decodestrip = JPEGDecode; + tif->tif_decodetile = JPEGDecode; + tif->tif_setupencode = JPEGSetupEncode; + tif->tif_preencode = JPEGPreEncode; + tif->tif_postencode = JPEGPostEncode; + tif->tif_encoderow = JPEGEncode; + tif->tif_encodestrip = JPEGEncode; + tif->tif_encodetile = JPEGEncode; + tif->tif_cleanup = JPEGCleanup; + sp->defsparent = tif->tif_defstripsize; + tif->tif_defstripsize = JPEGDefaultStripSize; + sp->deftparent = tif->tif_deftilesize; + tif->tif_deftilesize = JPEGDefaultTileSize; + tif->tif_flags |= TIFF_NOBITREV; /* no bit reversal, please */ + + sp->cinfo_initialized = FALSE; + + /* + ** Create a JPEGTables field if no directory has yet been created. + ** We do this just to ensure that sufficient space is reserved for + ** the JPEGTables field. It will be properly created the right + ** size later. + */ + if( tif->tif_diroff == 0 ) + { +#define SIZE_OF_JPEGTABLES 2000 +/* +The following line assumes incorrectly that all JPEG-in-TIFF files will have +a JPEGTABLES tag generated and causes null-filled JPEGTABLES tags to be written +when the JPEG data is placed with TIFFWriteRawStrip. The field bit should be +set, anyway, later when actual JPEGTABLES header is generated, so removing it +here hopefully is harmless. + TIFFSetFieldBit(tif, FIELD_JPEGTABLES); +*/ + sp->jpegtables_length = SIZE_OF_JPEGTABLES; + sp->jpegtables = (void *) _TIFFmalloc(sp->jpegtables_length); + _TIFFmemset(sp->jpegtables, 0, SIZE_OF_JPEGTABLES); +#undef SIZE_OF_JPEGTABLES + } + + /* + * Mark the TIFFTAG_YCBCRSAMPLES as present even if it is not + * see: JPEGFixupTestSubsampling(). + */ + TIFFSetFieldBit( tif, FIELD_YCBCRSUBSAMPLING ); + + return 1; +} +#endif /* JPEG_SUPPORT */ + +/* vim: set ts=8 sts=8 sw=8 noet: */ + +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tif_luv.c b/reactos/dll/3rdparty/libtiff/tif_luv.c new file mode 100644 index 00000000000..eb622b9b0bf --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tif_luv.c @@ -0,0 +1,1629 @@ +/* $Id: tif_luv.c,v 1.17.2.4 2010-06-08 18:50:42 bfriesen Exp $ */ + +/* + * Copyright (c) 1997 Greg Ward Larson + * Copyright (c) 1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler, Greg Larson and Silicon Graphics may not be used in any + * advertising or publicity relating to the software without the specific, + * prior written permission of Sam Leffler, Greg Larson and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER, GREG LARSON OR SILICON GRAPHICS BE LIABLE + * FOR ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include "tiffiop.h" +#ifdef LOGLUV_SUPPORT + +/* + * TIFF Library. + * LogLuv compression support for high dynamic range images. + * + * Contributed by Greg Larson. + * + * LogLuv image support uses the TIFF library to store 16 or 10-bit + * log luminance values with 8 bits each of u and v or a 14-bit index. + * + * The codec can take as input and produce as output 32-bit IEEE float values + * as well as 16-bit integer values. A 16-bit luminance is interpreted + * as a sign bit followed by a 15-bit integer that is converted + * to and from a linear magnitude using the transformation: + * + * L = 2^( (Le+.5)/256 - 64 ) # real from 15-bit + * + * Le = floor( 256*(log2(L) + 64) ) # 15-bit from real + * + * The actual conversion to world luminance units in candelas per sq. meter + * requires an additional multiplier, which is stored in the TIFFTAG_STONITS. + * This value is usually set such that a reasonable exposure comes from + * clamping decoded luminances above 1 to 1 in the displayed image. + * + * The 16-bit values for u and v may be converted to real values by dividing + * each by 32768. (This allows for negative values, which aren't useful as + * far as we know, but are left in case of future improvements in human + * color vision.) + * + * Conversion from (u,v), which is actually the CIE (u',v') system for + * you color scientists, is accomplished by the following transformation: + * + * u = 4*x / (-2*x + 12*y + 3) + * v = 9*y / (-2*x + 12*y + 3) + * + * x = 9*u / (6*u - 16*v + 12) + * y = 4*v / (6*u - 16*v + 12) + * + * This process is greatly simplified by passing 32-bit IEEE floats + * for each of three CIE XYZ coordinates. The codec then takes care + * of conversion to and from LogLuv, though the application is still + * responsible for interpreting the TIFFTAG_STONITS calibration factor. + * + * By definition, a CIE XYZ vector of [1 1 1] corresponds to a neutral white + * point of (x,y)=(1/3,1/3). However, most color systems assume some other + * white point, such as D65, and an absolute color conversion to XYZ then + * to another color space with a different white point may introduce an + * unwanted color cast to the image. It is often desirable, therefore, to + * perform a white point conversion that maps the input white to [1 1 1] + * in XYZ, then record the original white point using the TIFFTAG_WHITEPOINT + * tag value. A decoder that demands absolute color calibration may use + * this white point tag to get back the original colors, but usually it + * will be ignored and the new white point will be used instead that + * matches the output color space. + * + * Pixel information is compressed into one of two basic encodings, depending + * on the setting of the compression tag, which is one of COMPRESSION_SGILOG + * or COMPRESSION_SGILOG24. For COMPRESSION_SGILOG, greyscale data is + * stored as: + * + * 1 15 + * |-+---------------| + * + * COMPRESSION_SGILOG color data is stored as: + * + * 1 15 8 8 + * |-+---------------|--------+--------| + * S Le ue ve + * + * For the 24-bit COMPRESSION_SGILOG24 color format, the data is stored as: + * + * 10 14 + * |----------|--------------| + * Le' Ce + * + * There is no sign bit in the 24-bit case, and the (u,v) chromaticity is + * encoded as an index for optimal color resolution. The 10 log bits are + * defined by the following conversions: + * + * L = 2^((Le'+.5)/64 - 12) # real from 10-bit + * + * Le' = floor( 64*(log2(L) + 12) ) # 10-bit from real + * + * The 10 bits of the smaller format may be converted into the 15 bits of + * the larger format by multiplying by 4 and adding 13314. Obviously, + * a smaller range of magnitudes is covered (about 5 orders of magnitude + * instead of 38), and the lack of a sign bit means that negative luminances + * are not allowed. (Well, they aren't allowed in the real world, either, + * but they are useful for certain types of image processing.) + * + * The desired user format is controlled by the setting the internal + * pseudo tag TIFFTAG_SGILOGDATAFMT to one of: + * SGILOGDATAFMT_FLOAT = IEEE 32-bit float XYZ values + * SGILOGDATAFMT_16BIT = 16-bit integer encodings of logL, u and v + * Raw data i/o is also possible using: + * SGILOGDATAFMT_RAW = 32-bit unsigned integer with encoded pixel + * In addition, the following decoding is provided for ease of display: + * SGILOGDATAFMT_8BIT = 8-bit default RGB gamma-corrected values + * + * For grayscale images, we provide the following data formats: + * SGILOGDATAFMT_FLOAT = IEEE 32-bit float Y values + * SGILOGDATAFMT_16BIT = 16-bit integer w/ encoded luminance + * SGILOGDATAFMT_8BIT = 8-bit gray monitor values + * + * Note that the COMPRESSION_SGILOG applies a simple run-length encoding + * scheme by separating the logL, u and v bytes for each row and applying + * a PackBits type of compression. Since the 24-bit encoding is not + * adaptive, the 32-bit color format takes less space in many cases. + * + * Further control is provided over the conversion from higher-resolution + * formats to final encoded values through the pseudo tag + * TIFFTAG_SGILOGENCODE: + * SGILOGENCODE_NODITHER = do not dither encoded values + * SGILOGENCODE_RANDITHER = apply random dithering during encoding + * + * The default value of this tag is SGILOGENCODE_NODITHER for + * COMPRESSION_SGILOG to maximize run-length encoding and + * SGILOGENCODE_RANDITHER for COMPRESSION_SGILOG24 to turn + * quantization errors into noise. + */ + +#include +#include +#include + +/* + * State block for each open TIFF + * file using LogLuv compression/decompression. + */ +typedef struct logLuvState LogLuvState; + +struct logLuvState { + int user_datafmt; /* user data format */ + int encode_meth; /* encoding method */ + int pixel_size; /* bytes per pixel */ + + tidata_t* tbuf; /* translation buffer */ + int tbuflen; /* buffer length */ + void (*tfunc)(LogLuvState*, tidata_t, int); + + TIFFVSetMethod vgetparent; /* super-class method */ + TIFFVSetMethod vsetparent; /* super-class method */ +}; + +#define DecoderState(tif) ((LogLuvState*) (tif)->tif_data) +#define EncoderState(tif) ((LogLuvState*) (tif)->tif_data) + +#define SGILOGDATAFMT_UNKNOWN -1 + +#define MINRUN 4 /* minimum run length */ + +/* + * Decode a string of 16-bit gray pixels. + */ +static int +LogL16Decode(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s) +{ + LogLuvState* sp = DecoderState(tif); + int shft, i, npixels; + unsigned char* bp; + int16* tp; + int16 b; + int cc, rc; + + assert(s == 0); + assert(sp != NULL); + + npixels = occ / sp->pixel_size; + + if (sp->user_datafmt == SGILOGDATAFMT_16BIT) + tp = (int16*) op; + else { + assert(sp->tbuflen >= npixels); + tp = (int16*) sp->tbuf; + } + _TIFFmemset((tdata_t) tp, 0, npixels*sizeof (tp[0])); + + bp = (unsigned char*) tif->tif_rawcp; + cc = tif->tif_rawcc; + /* get each byte string */ + for (shft = 2*8; (shft -= 8) >= 0; ) { + for (i = 0; i < npixels && cc > 0; ) + if (*bp >= 128) { /* run */ + rc = *bp++ + (2-128); + b = (int16)(*bp++ << shft); + cc -= 2; + while (rc-- && i < npixels) + tp[i++] |= b; + } else { /* non-run */ + rc = *bp++; /* nul is noop */ + while (--cc && rc-- && i < npixels) + tp[i++] |= (int16)*bp++ << shft; + } + if (i != npixels) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "LogL16Decode: Not enough data at row %d (short %d pixels)", + tif->tif_row, npixels - i); + tif->tif_rawcp = (tidata_t) bp; + tif->tif_rawcc = cc; + return (0); + } + } + (*sp->tfunc)(sp, op, npixels); + tif->tif_rawcp = (tidata_t) bp; + tif->tif_rawcc = cc; + return (1); +} + +/* + * Decode a string of 24-bit pixels. + */ +static int +LogLuvDecode24(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s) +{ + LogLuvState* sp = DecoderState(tif); + int cc, i, npixels; + unsigned char* bp; + uint32* tp; + + assert(s == 0); + assert(sp != NULL); + + npixels = occ / sp->pixel_size; + + if (sp->user_datafmt == SGILOGDATAFMT_RAW) + tp = (uint32 *)op; + else { + assert(sp->tbuflen >= npixels); + tp = (uint32 *) sp->tbuf; + } + /* copy to array of uint32 */ + bp = (unsigned char*) tif->tif_rawcp; + cc = tif->tif_rawcc; + for (i = 0; i < npixels && cc > 0; i++) { + tp[i] = bp[0] << 16 | bp[1] << 8 | bp[2]; + bp += 3; + cc -= 3; + } + tif->tif_rawcp = (tidata_t) bp; + tif->tif_rawcc = cc; + if (i != npixels) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "LogLuvDecode24: Not enough data at row %d (short %d pixels)", + tif->tif_row, npixels - i); + return (0); + } + (*sp->tfunc)(sp, op, npixels); + return (1); +} + +/* + * Decode a string of 32-bit pixels. + */ +static int +LogLuvDecode32(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s) +{ + LogLuvState* sp; + int shft, i, npixels; + unsigned char* bp; + uint32* tp; + uint32 b; + int cc, rc; + + assert(s == 0); + sp = DecoderState(tif); + assert(sp != NULL); + + npixels = occ / sp->pixel_size; + + if (sp->user_datafmt == SGILOGDATAFMT_RAW) + tp = (uint32*) op; + else { + assert(sp->tbuflen >= npixels); + tp = (uint32*) sp->tbuf; + } + _TIFFmemset((tdata_t) tp, 0, npixels*sizeof (tp[0])); + + bp = (unsigned char*) tif->tif_rawcp; + cc = tif->tif_rawcc; + /* get each byte string */ + for (shft = 4*8; (shft -= 8) >= 0; ) { + for (i = 0; i < npixels && cc > 0; ) + if (*bp >= 128) { /* run */ + rc = *bp++ + (2-128); + b = (uint32)*bp++ << shft; + cc -= 2; + while (rc-- && i < npixels) + tp[i++] |= b; + } else { /* non-run */ + rc = *bp++; /* nul is noop */ + while (--cc && rc-- && i < npixels) + tp[i++] |= (uint32)*bp++ << shft; + } + if (i != npixels) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "LogLuvDecode32: Not enough data at row %d (short %d pixels)", + tif->tif_row, npixels - i); + tif->tif_rawcp = (tidata_t) bp; + tif->tif_rawcc = cc; + return (0); + } + } + (*sp->tfunc)(sp, op, npixels); + tif->tif_rawcp = (tidata_t) bp; + tif->tif_rawcc = cc; + return (1); +} + +/* + * Decode a strip of pixels. We break it into rows to + * maintain synchrony with the encode algorithm, which + * is row by row. + */ +static int +LogLuvDecodeStrip(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s) +{ + tsize_t rowlen = TIFFScanlineSize(tif); + + assert(cc%rowlen == 0); + while (cc && (*tif->tif_decoderow)(tif, bp, rowlen, s)) + bp += rowlen, cc -= rowlen; + return (cc == 0); +} + +/* + * Decode a tile of pixels. We break it into rows to + * maintain synchrony with the encode algorithm, which + * is row by row. + */ +static int +LogLuvDecodeTile(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s) +{ + tsize_t rowlen = TIFFTileRowSize(tif); + + assert(cc%rowlen == 0); + while (cc && (*tif->tif_decoderow)(tif, bp, rowlen, s)) + bp += rowlen, cc -= rowlen; + return (cc == 0); +} + +/* + * Encode a row of 16-bit pixels. + */ +static int +LogL16Encode(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s) +{ + LogLuvState* sp = EncoderState(tif); + int shft, i, j, npixels; + tidata_t op; + int16* tp; + int16 b; + int occ, rc=0, mask, beg; + + assert(s == 0); + assert(sp != NULL); + npixels = cc / sp->pixel_size; + + if (sp->user_datafmt == SGILOGDATAFMT_16BIT) + tp = (int16*) bp; + else { + tp = (int16*) sp->tbuf; + assert(sp->tbuflen >= npixels); + (*sp->tfunc)(sp, bp, npixels); + } + /* compress each byte string */ + op = tif->tif_rawcp; + occ = tif->tif_rawdatasize - tif->tif_rawcc; + for (shft = 2*8; (shft -= 8) >= 0; ) + for (i = 0; i < npixels; i += rc) { + if (occ < 4) { + tif->tif_rawcp = op; + tif->tif_rawcc = tif->tif_rawdatasize - occ; + if (!TIFFFlushData1(tif)) + return (-1); + op = tif->tif_rawcp; + occ = tif->tif_rawdatasize - tif->tif_rawcc; + } + mask = 0xff << shft; /* find next run */ + for (beg = i; beg < npixels; beg += rc) { + b = (int16) (tp[beg] & mask); + rc = 1; + while (rc < 127+2 && beg+rc < npixels && + (tp[beg+rc] & mask) == b) + rc++; + if (rc >= MINRUN) + break; /* long enough */ + } + if (beg-i > 1 && beg-i < MINRUN) { + b = (int16) (tp[i] & mask);/*check short run */ + j = i+1; + while ((tp[j++] & mask) == b) + if (j == beg) { + *op++ = (tidataval_t)(128-2+j-i); + *op++ = (tidataval_t) (b >> shft); + occ -= 2; + i = beg; + break; + } + } + while (i < beg) { /* write out non-run */ + if ((j = beg-i) > 127) j = 127; + if (occ < j+3) { + tif->tif_rawcp = op; + tif->tif_rawcc = tif->tif_rawdatasize - occ; + if (!TIFFFlushData1(tif)) + return (-1); + op = tif->tif_rawcp; + occ = tif->tif_rawdatasize - tif->tif_rawcc; + } + *op++ = (tidataval_t) j; occ--; + while (j--) { + *op++ = (tidataval_t) (tp[i++] >> shft & 0xff); + occ--; + } + } + if (rc >= MINRUN) { /* write out run */ + *op++ = (tidataval_t) (128-2+rc); + *op++ = (tidataval_t) (tp[beg] >> shft & 0xff); + occ -= 2; + } else + rc = 0; + } + tif->tif_rawcp = op; + tif->tif_rawcc = tif->tif_rawdatasize - occ; + + return (1); +} + +/* + * Encode a row of 24-bit pixels. + */ +static int +LogLuvEncode24(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s) +{ + LogLuvState* sp = EncoderState(tif); + int i, npixels, occ; + tidata_t op; + uint32* tp; + + assert(s == 0); + assert(sp != NULL); + npixels = cc / sp->pixel_size; + + if (sp->user_datafmt == SGILOGDATAFMT_RAW) + tp = (uint32*) bp; + else { + tp = (uint32*) sp->tbuf; + assert(sp->tbuflen >= npixels); + (*sp->tfunc)(sp, bp, npixels); + } + /* write out encoded pixels */ + op = tif->tif_rawcp; + occ = tif->tif_rawdatasize - tif->tif_rawcc; + for (i = npixels; i--; ) { + if (occ < 3) { + tif->tif_rawcp = op; + tif->tif_rawcc = tif->tif_rawdatasize - occ; + if (!TIFFFlushData1(tif)) + return (-1); + op = tif->tif_rawcp; + occ = tif->tif_rawdatasize - tif->tif_rawcc; + } + *op++ = (tidataval_t)(*tp >> 16); + *op++ = (tidataval_t)(*tp >> 8 & 0xff); + *op++ = (tidataval_t)(*tp++ & 0xff); + occ -= 3; + } + tif->tif_rawcp = op; + tif->tif_rawcc = tif->tif_rawdatasize - occ; + + return (1); +} + +/* + * Encode a row of 32-bit pixels. + */ +static int +LogLuvEncode32(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s) +{ + LogLuvState* sp = EncoderState(tif); + int shft, i, j, npixels; + tidata_t op; + uint32* tp; + uint32 b; + int occ, rc=0, mask, beg; + + assert(s == 0); + assert(sp != NULL); + + npixels = cc / sp->pixel_size; + + if (sp->user_datafmt == SGILOGDATAFMT_RAW) + tp = (uint32*) bp; + else { + tp = (uint32*) sp->tbuf; + assert(sp->tbuflen >= npixels); + (*sp->tfunc)(sp, bp, npixels); + } + /* compress each byte string */ + op = tif->tif_rawcp; + occ = tif->tif_rawdatasize - tif->tif_rawcc; + for (shft = 4*8; (shft -= 8) >= 0; ) + for (i = 0; i < npixels; i += rc) { + if (occ < 4) { + tif->tif_rawcp = op; + tif->tif_rawcc = tif->tif_rawdatasize - occ; + if (!TIFFFlushData1(tif)) + return (-1); + op = tif->tif_rawcp; + occ = tif->tif_rawdatasize - tif->tif_rawcc; + } + mask = 0xff << shft; /* find next run */ + for (beg = i; beg < npixels; beg += rc) { + b = tp[beg] & mask; + rc = 1; + while (rc < 127+2 && beg+rc < npixels && + (tp[beg+rc] & mask) == b) + rc++; + if (rc >= MINRUN) + break; /* long enough */ + } + if (beg-i > 1 && beg-i < MINRUN) { + b = tp[i] & mask; /* check short run */ + j = i+1; + while ((tp[j++] & mask) == b) + if (j == beg) { + *op++ = (tidataval_t)(128-2+j-i); + *op++ = (tidataval_t)(b >> shft); + occ -= 2; + i = beg; + break; + } + } + while (i < beg) { /* write out non-run */ + if ((j = beg-i) > 127) j = 127; + if (occ < j+3) { + tif->tif_rawcp = op; + tif->tif_rawcc = tif->tif_rawdatasize - occ; + if (!TIFFFlushData1(tif)) + return (-1); + op = tif->tif_rawcp; + occ = tif->tif_rawdatasize - tif->tif_rawcc; + } + *op++ = (tidataval_t) j; occ--; + while (j--) { + *op++ = (tidataval_t)(tp[i++] >> shft & 0xff); + occ--; + } + } + if (rc >= MINRUN) { /* write out run */ + *op++ = (tidataval_t) (128-2+rc); + *op++ = (tidataval_t)(tp[beg] >> shft & 0xff); + occ -= 2; + } else + rc = 0; + } + tif->tif_rawcp = op; + tif->tif_rawcc = tif->tif_rawdatasize - occ; + + return (1); +} + +/* + * Encode a strip of pixels. We break it into rows to + * avoid encoding runs across row boundaries. + */ +static int +LogLuvEncodeStrip(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s) +{ + tsize_t rowlen = TIFFScanlineSize(tif); + + assert(cc%rowlen == 0); + while (cc && (*tif->tif_encoderow)(tif, bp, rowlen, s) == 1) + bp += rowlen, cc -= rowlen; + return (cc == 0); +} + +/* + * Encode a tile of pixels. We break it into rows to + * avoid encoding runs across row boundaries. + */ +static int +LogLuvEncodeTile(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s) +{ + tsize_t rowlen = TIFFTileRowSize(tif); + + assert(cc%rowlen == 0); + while (cc && (*tif->tif_encoderow)(tif, bp, rowlen, s) == 1) + bp += rowlen, cc -= rowlen; + return (cc == 0); +} + +/* + * Encode/Decode functions for converting to and from user formats. + */ + +#include "uvcode.h" + +#ifndef UVSCALE +#define U_NEU 0.210526316 +#define V_NEU 0.473684211 +#define UVSCALE 410. +#endif + +#ifndef M_LN2 +#define M_LN2 0.69314718055994530942 +#endif +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#define log2(x) ((1./M_LN2)*log(x)) +#define exp2(x) exp(M_LN2*(x)) + +#define itrunc(x,m) ((m)==SGILOGENCODE_NODITHER ? \ + (int)(x) : \ + (int)((x) + rand()*(1./RAND_MAX) - .5)) + +#if !LOGLUV_PUBLIC +static +#endif +double +LogL16toY(int p16) /* compute luminance from 16-bit LogL */ +{ + int Le = p16 & 0x7fff; + double Y; + + if (!Le) + return (0.); + Y = exp(M_LN2/256.*(Le+.5) - M_LN2*64.); + return (!(p16 & 0x8000) ? Y : -Y); +} + +#if !LOGLUV_PUBLIC +static +#endif +int +LogL16fromY(double Y, int em) /* get 16-bit LogL from Y */ +{ + if (Y >= 1.8371976e19) + return (0x7fff); + if (Y <= -1.8371976e19) + return (0xffff); + if (Y > 5.4136769e-20) + return itrunc(256.*(log2(Y) + 64.), em); + if (Y < -5.4136769e-20) + return (~0x7fff | itrunc(256.*(log2(-Y) + 64.), em)); + return (0); +} + +static void +L16toY(LogLuvState* sp, tidata_t op, int n) +{ + int16* l16 = (int16*) sp->tbuf; + float* yp = (float*) op; + + while (n-- > 0) + *yp++ = (float)LogL16toY(*l16++); +} + +static void +L16toGry(LogLuvState* sp, tidata_t op, int n) +{ + int16* l16 = (int16*) sp->tbuf; + uint8* gp = (uint8*) op; + + while (n-- > 0) { + double Y = LogL16toY(*l16++); + *gp++ = (uint8) ((Y <= 0.) ? 0 : (Y >= 1.) ? 255 : (int)(256.*sqrt(Y))); + } +} + +static void +L16fromY(LogLuvState* sp, tidata_t op, int n) +{ + int16* l16 = (int16*) sp->tbuf; + float* yp = (float*) op; + + while (n-- > 0) + *l16++ = (int16) (LogL16fromY(*yp++, sp->encode_meth)); +} + +#if !LOGLUV_PUBLIC +static +#endif +void +XYZtoRGB24(float xyz[3], uint8 rgb[3]) +{ + double r, g, b; + /* assume CCIR-709 primaries */ + r = 2.690*xyz[0] + -1.276*xyz[1] + -0.414*xyz[2]; + g = -1.022*xyz[0] + 1.978*xyz[1] + 0.044*xyz[2]; + b = 0.061*xyz[0] + -0.224*xyz[1] + 1.163*xyz[2]; + /* assume 2.0 gamma for speed */ + /* could use integer sqrt approx., but this is probably faster */ + rgb[0] = (uint8)((r<=0.) ? 0 : (r >= 1.) ? 255 : (int)(256.*sqrt(r))); + rgb[1] = (uint8)((g<=0.) ? 0 : (g >= 1.) ? 255 : (int)(256.*sqrt(g))); + rgb[2] = (uint8)((b<=0.) ? 0 : (b >= 1.) ? 255 : (int)(256.*sqrt(b))); +} + +#if !LOGLUV_PUBLIC +static +#endif +double +LogL10toY(int p10) /* compute luminance from 10-bit LogL */ +{ + if (p10 == 0) + return (0.); + return (exp(M_LN2/64.*(p10+.5) - M_LN2*12.)); +} + +#if !LOGLUV_PUBLIC +static +#endif +int +LogL10fromY(double Y, int em) /* get 10-bit LogL from Y */ +{ + if (Y >= 15.742) + return (0x3ff); + else if (Y <= .00024283) + return (0); + else + return itrunc(64.*(log2(Y) + 12.), em); +} + +#define NANGLES 100 +#define uv2ang(u, v) ( (NANGLES*.499999999/M_PI) \ + * atan2((v)-V_NEU,(u)-U_NEU) + .5*NANGLES ) + +static int +oog_encode(double u, double v) /* encode out-of-gamut chroma */ +{ + static int oog_table[NANGLES]; + static int initialized = 0; + register int i; + + if (!initialized) { /* set up perimeter table */ + double eps[NANGLES], ua, va, ang, epsa; + int ui, vi, ustep; + for (i = NANGLES; i--; ) + eps[i] = 2.; + for (vi = UV_NVS; vi--; ) { + va = UV_VSTART + (vi+.5)*UV_SQSIZ; + ustep = uv_row[vi].nus-1; + if (vi == UV_NVS-1 || vi == 0 || ustep <= 0) + ustep = 1; + for (ui = uv_row[vi].nus-1; ui >= 0; ui -= ustep) { + ua = uv_row[vi].ustart + (ui+.5)*UV_SQSIZ; + ang = uv2ang(ua, va); + i = (int) ang; + epsa = fabs(ang - (i+.5)); + if (epsa < eps[i]) { + oog_table[i] = uv_row[vi].ncum + ui; + eps[i] = epsa; + } + } + } + for (i = NANGLES; i--; ) /* fill any holes */ + if (eps[i] > 1.5) { + int i1, i2; + for (i1 = 1; i1 < NANGLES/2; i1++) + if (eps[(i+i1)%NANGLES] < 1.5) + break; + for (i2 = 1; i2 < NANGLES/2; i2++) + if (eps[(i+NANGLES-i2)%NANGLES] < 1.5) + break; + if (i1 < i2) + oog_table[i] = + oog_table[(i+i1)%NANGLES]; + else + oog_table[i] = + oog_table[(i+NANGLES-i2)%NANGLES]; + } + initialized = 1; + } + i = (int) uv2ang(u, v); /* look up hue angle */ + return (oog_table[i]); +} + +#undef uv2ang +#undef NANGLES + +#if !LOGLUV_PUBLIC +static +#endif +int +uv_encode(double u, double v, int em) /* encode (u',v') coordinates */ +{ + register int vi, ui; + + if (v < UV_VSTART) + return oog_encode(u, v); + vi = itrunc((v - UV_VSTART)*(1./UV_SQSIZ), em); + if (vi >= UV_NVS) + return oog_encode(u, v); + if (u < uv_row[vi].ustart) + return oog_encode(u, v); + ui = itrunc((u - uv_row[vi].ustart)*(1./UV_SQSIZ), em); + if (ui >= uv_row[vi].nus) + return oog_encode(u, v); + + return (uv_row[vi].ncum + ui); +} + +#if !LOGLUV_PUBLIC +static +#endif +int +uv_decode(double *up, double *vp, int c) /* decode (u',v') index */ +{ + int upper, lower; + register int ui, vi; + + if (c < 0 || c >= UV_NDIVS) + return (-1); + lower = 0; /* binary search */ + upper = UV_NVS; + while (upper - lower > 1) { + vi = (lower + upper) >> 1; + ui = c - uv_row[vi].ncum; + if (ui > 0) + lower = vi; + else if (ui < 0) + upper = vi; + else { + lower = vi; + break; + } + } + vi = lower; + ui = c - uv_row[vi].ncum; + *up = uv_row[vi].ustart + (ui+.5)*UV_SQSIZ; + *vp = UV_VSTART + (vi+.5)*UV_SQSIZ; + return (0); +} + +#if !LOGLUV_PUBLIC +static +#endif +void +LogLuv24toXYZ(uint32 p, float XYZ[3]) +{ + int Ce; + double L, u, v, s, x, y; + /* decode luminance */ + L = LogL10toY(p>>14 & 0x3ff); + if (L <= 0.) { + XYZ[0] = XYZ[1] = XYZ[2] = 0.; + return; + } + /* decode color */ + Ce = p & 0x3fff; + if (uv_decode(&u, &v, Ce) < 0) { + u = U_NEU; v = V_NEU; + } + s = 1./(6.*u - 16.*v + 12.); + x = 9.*u * s; + y = 4.*v * s; + /* convert to XYZ */ + XYZ[0] = (float)(x/y * L); + XYZ[1] = (float)L; + XYZ[2] = (float)((1.-x-y)/y * L); +} + +#if !LOGLUV_PUBLIC +static +#endif +uint32 +LogLuv24fromXYZ(float XYZ[3], int em) +{ + int Le, Ce; + double u, v, s; + /* encode luminance */ + Le = LogL10fromY(XYZ[1], em); + /* encode color */ + s = XYZ[0] + 15.*XYZ[1] + 3.*XYZ[2]; + if (!Le || s <= 0.) { + u = U_NEU; + v = V_NEU; + } else { + u = 4.*XYZ[0] / s; + v = 9.*XYZ[1] / s; + } + Ce = uv_encode(u, v, em); + if (Ce < 0) /* never happens */ + Ce = uv_encode(U_NEU, V_NEU, SGILOGENCODE_NODITHER); + /* combine encodings */ + return (Le << 14 | Ce); +} + +static void +Luv24toXYZ(LogLuvState* sp, tidata_t op, int n) +{ + uint32* luv = (uint32*) sp->tbuf; + float* xyz = (float*) op; + + while (n-- > 0) { + LogLuv24toXYZ(*luv, xyz); + xyz += 3; + luv++; + } +} + +static void +Luv24toLuv48(LogLuvState* sp, tidata_t op, int n) +{ + uint32* luv = (uint32*) sp->tbuf; + int16* luv3 = (int16*) op; + + while (n-- > 0) { + double u, v; + + *luv3++ = (int16)((*luv >> 12 & 0xffd) + 13314); + if (uv_decode(&u, &v, *luv&0x3fff) < 0) { + u = U_NEU; + v = V_NEU; + } + *luv3++ = (int16)(u * (1L<<15)); + *luv3++ = (int16)(v * (1L<<15)); + luv++; + } +} + +static void +Luv24toRGB(LogLuvState* sp, tidata_t op, int n) +{ + uint32* luv = (uint32*) sp->tbuf; + uint8* rgb = (uint8*) op; + + while (n-- > 0) { + float xyz[3]; + + LogLuv24toXYZ(*luv++, xyz); + XYZtoRGB24(xyz, rgb); + rgb += 3; + } +} + +static void +Luv24fromXYZ(LogLuvState* sp, tidata_t op, int n) +{ + uint32* luv = (uint32*) sp->tbuf; + float* xyz = (float*) op; + + while (n-- > 0) { + *luv++ = LogLuv24fromXYZ(xyz, sp->encode_meth); + xyz += 3; + } +} + +static void +Luv24fromLuv48(LogLuvState* sp, tidata_t op, int n) +{ + uint32* luv = (uint32*) sp->tbuf; + int16* luv3 = (int16*) op; + + while (n-- > 0) { + int Le, Ce; + + if (luv3[0] <= 0) + Le = 0; + else if (luv3[0] >= (1<<12)+3314) + Le = (1<<10) - 1; + else if (sp->encode_meth == SGILOGENCODE_NODITHER) + Le = (luv3[0]-3314) >> 2; + else + Le = itrunc(.25*(luv3[0]-3314.), sp->encode_meth); + + Ce = uv_encode((luv3[1]+.5)/(1<<15), (luv3[2]+.5)/(1<<15), + sp->encode_meth); + if (Ce < 0) /* never happens */ + Ce = uv_encode(U_NEU, V_NEU, SGILOGENCODE_NODITHER); + *luv++ = (uint32)Le << 14 | Ce; + luv3 += 3; + } +} + +#if !LOGLUV_PUBLIC +static +#endif +void +LogLuv32toXYZ(uint32 p, float XYZ[3]) +{ + double L, u, v, s, x, y; + /* decode luminance */ + L = LogL16toY((int)p >> 16); + if (L <= 0.) { + XYZ[0] = XYZ[1] = XYZ[2] = 0.; + return; + } + /* decode color */ + u = 1./UVSCALE * ((p>>8 & 0xff) + .5); + v = 1./UVSCALE * ((p & 0xff) + .5); + s = 1./(6.*u - 16.*v + 12.); + x = 9.*u * s; + y = 4.*v * s; + /* convert to XYZ */ + XYZ[0] = (float)(x/y * L); + XYZ[1] = (float)L; + XYZ[2] = (float)((1.-x-y)/y * L); +} + +#if !LOGLUV_PUBLIC +static +#endif +uint32 +LogLuv32fromXYZ(float XYZ[3], int em) +{ + unsigned int Le, ue, ve; + double u, v, s; + /* encode luminance */ + Le = (unsigned int)LogL16fromY(XYZ[1], em); + /* encode color */ + s = XYZ[0] + 15.*XYZ[1] + 3.*XYZ[2]; + if (!Le || s <= 0.) { + u = U_NEU; + v = V_NEU; + } else { + u = 4.*XYZ[0] / s; + v = 9.*XYZ[1] / s; + } + if (u <= 0.) ue = 0; + else ue = itrunc(UVSCALE*u, em); + if (ue > 255) ue = 255; + if (v <= 0.) ve = 0; + else ve = itrunc(UVSCALE*v, em); + if (ve > 255) ve = 255; + /* combine encodings */ + return (Le << 16 | ue << 8 | ve); +} + +static void +Luv32toXYZ(LogLuvState* sp, tidata_t op, int n) +{ + uint32* luv = (uint32*) sp->tbuf; + float* xyz = (float*) op; + + while (n-- > 0) { + LogLuv32toXYZ(*luv++, xyz); + xyz += 3; + } +} + +static void +Luv32toLuv48(LogLuvState* sp, tidata_t op, int n) +{ + uint32* luv = (uint32*) sp->tbuf; + int16* luv3 = (int16*) op; + + while (n-- > 0) { + double u, v; + + *luv3++ = (int16)(*luv >> 16); + u = 1./UVSCALE * ((*luv>>8 & 0xff) + .5); + v = 1./UVSCALE * ((*luv & 0xff) + .5); + *luv3++ = (int16)(u * (1L<<15)); + *luv3++ = (int16)(v * (1L<<15)); + luv++; + } +} + +static void +Luv32toRGB(LogLuvState* sp, tidata_t op, int n) +{ + uint32* luv = (uint32*) sp->tbuf; + uint8* rgb = (uint8*) op; + + while (n-- > 0) { + float xyz[3]; + + LogLuv32toXYZ(*luv++, xyz); + XYZtoRGB24(xyz, rgb); + rgb += 3; + } +} + +static void +Luv32fromXYZ(LogLuvState* sp, tidata_t op, int n) +{ + uint32* luv = (uint32*) sp->tbuf; + float* xyz = (float*) op; + + while (n-- > 0) { + *luv++ = LogLuv32fromXYZ(xyz, sp->encode_meth); + xyz += 3; + } +} + +static void +Luv32fromLuv48(LogLuvState* sp, tidata_t op, int n) +{ + uint32* luv = (uint32*) sp->tbuf; + int16* luv3 = (int16*) op; + + if (sp->encode_meth == SGILOGENCODE_NODITHER) { + while (n-- > 0) { + *luv++ = (uint32)luv3[0] << 16 | + (luv3[1]*(uint32)(UVSCALE+.5) >> 7 & 0xff00) | + (luv3[2]*(uint32)(UVSCALE+.5) >> 15 & 0xff); + luv3 += 3; + } + return; + } + while (n-- > 0) { + *luv++ = (uint32)luv3[0] << 16 | + (itrunc(luv3[1]*(UVSCALE/(1<<15)), sp->encode_meth) << 8 & 0xff00) | + (itrunc(luv3[2]*(UVSCALE/(1<<15)), sp->encode_meth) & 0xff); + luv3 += 3; + } +} + +static void +_logLuvNop(LogLuvState* sp, tidata_t op, int n) +{ + (void) sp; (void) op; (void) n; +} + +static int +LogL16GuessDataFmt(TIFFDirectory *td) +{ +#define PACK(s,b,f) (((b)<<6)|((s)<<3)|(f)) + switch (PACK(td->td_samplesperpixel, td->td_bitspersample, td->td_sampleformat)) { + case PACK(1, 32, SAMPLEFORMAT_IEEEFP): + return (SGILOGDATAFMT_FLOAT); + case PACK(1, 16, SAMPLEFORMAT_VOID): + case PACK(1, 16, SAMPLEFORMAT_INT): + case PACK(1, 16, SAMPLEFORMAT_UINT): + return (SGILOGDATAFMT_16BIT); + case PACK(1, 8, SAMPLEFORMAT_VOID): + case PACK(1, 8, SAMPLEFORMAT_UINT): + return (SGILOGDATAFMT_8BIT); + } +#undef PACK + return (SGILOGDATAFMT_UNKNOWN); +} + +static uint32 +multiply(size_t m1, size_t m2) +{ + uint32 bytes = m1 * m2; + + if (m1 && bytes / m1 != m2) + bytes = 0; + + return bytes; +} + +static int +LogL16InitState(TIFF* tif) +{ + TIFFDirectory *td = &tif->tif_dir; + LogLuvState* sp = DecoderState(tif); + static const char module[] = "LogL16InitState"; + + assert(sp != NULL); + assert(td->td_photometric == PHOTOMETRIC_LOGL); + + /* for some reason, we can't do this in TIFFInitLogL16 */ + if (sp->user_datafmt == SGILOGDATAFMT_UNKNOWN) + sp->user_datafmt = LogL16GuessDataFmt(td); + switch (sp->user_datafmt) { + case SGILOGDATAFMT_FLOAT: + sp->pixel_size = sizeof (float); + break; + case SGILOGDATAFMT_16BIT: + sp->pixel_size = sizeof (int16); + break; + case SGILOGDATAFMT_8BIT: + sp->pixel_size = sizeof (uint8); + break; + default: + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "No support for converting user data format to LogL"); + return (0); + } + if( isTiled(tif) ) + sp->tbuflen = multiply(td->td_tilewidth, td->td_tilelength); + else + sp->tbuflen = multiply(td->td_imagewidth, td->td_rowsperstrip); + if (multiply(sp->tbuflen, sizeof (int16)) == 0 || + (sp->tbuf = (tidata_t*) _TIFFmalloc(sp->tbuflen * sizeof (int16))) == NULL) { + TIFFErrorExt(tif->tif_clientdata, module, "%s: No space for SGILog translation buffer", + tif->tif_name); + return (0); + } + return (1); +} + +static int +LogLuvGuessDataFmt(TIFFDirectory *td) +{ + int guess; + + /* + * If the user didn't tell us their datafmt, + * take our best guess from the bitspersample. + */ +#define PACK(a,b) (((a)<<3)|(b)) + switch (PACK(td->td_bitspersample, td->td_sampleformat)) { + case PACK(32, SAMPLEFORMAT_IEEEFP): + guess = SGILOGDATAFMT_FLOAT; + break; + case PACK(32, SAMPLEFORMAT_VOID): + case PACK(32, SAMPLEFORMAT_UINT): + case PACK(32, SAMPLEFORMAT_INT): + guess = SGILOGDATAFMT_RAW; + break; + case PACK(16, SAMPLEFORMAT_VOID): + case PACK(16, SAMPLEFORMAT_INT): + case PACK(16, SAMPLEFORMAT_UINT): + guess = SGILOGDATAFMT_16BIT; + break; + case PACK( 8, SAMPLEFORMAT_VOID): + case PACK( 8, SAMPLEFORMAT_UINT): + guess = SGILOGDATAFMT_8BIT; + break; + default: + guess = SGILOGDATAFMT_UNKNOWN; + break; +#undef PACK + } + /* + * Double-check samples per pixel. + */ + switch (td->td_samplesperpixel) { + case 1: + if (guess != SGILOGDATAFMT_RAW) + guess = SGILOGDATAFMT_UNKNOWN; + break; + case 3: + if (guess == SGILOGDATAFMT_RAW) + guess = SGILOGDATAFMT_UNKNOWN; + break; + default: + guess = SGILOGDATAFMT_UNKNOWN; + break; + } + return (guess); +} + +static int +LogLuvInitState(TIFF* tif) +{ + TIFFDirectory* td = &tif->tif_dir; + LogLuvState* sp = DecoderState(tif); + static const char module[] = "LogLuvInitState"; + + assert(sp != NULL); + assert(td->td_photometric == PHOTOMETRIC_LOGLUV); + + /* for some reason, we can't do this in TIFFInitLogLuv */ + if (td->td_planarconfig != PLANARCONFIG_CONTIG) { + TIFFErrorExt(tif->tif_clientdata, module, + "SGILog compression cannot handle non-contiguous data"); + return (0); + } + if (sp->user_datafmt == SGILOGDATAFMT_UNKNOWN) + sp->user_datafmt = LogLuvGuessDataFmt(td); + switch (sp->user_datafmt) { + case SGILOGDATAFMT_FLOAT: + sp->pixel_size = 3*sizeof (float); + break; + case SGILOGDATAFMT_16BIT: + sp->pixel_size = 3*sizeof (int16); + break; + case SGILOGDATAFMT_RAW: + sp->pixel_size = sizeof (uint32); + break; + case SGILOGDATAFMT_8BIT: + sp->pixel_size = 3*sizeof (uint8); + break; + default: + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "No support for converting user data format to LogLuv"); + return (0); + } + if( isTiled(tif) ) + sp->tbuflen = multiply(td->td_tilewidth, td->td_tilelength); + else + sp->tbuflen = multiply(td->td_imagewidth, td->td_rowsperstrip); + if (multiply(sp->tbuflen, sizeof (uint32)) == 0 || + (sp->tbuf = (tidata_t*) _TIFFmalloc(sp->tbuflen * sizeof (uint32))) == NULL) { + TIFFErrorExt(tif->tif_clientdata, module, "%s: No space for SGILog translation buffer", + tif->tif_name); + return (0); + } + return (1); +} + +static int +LogLuvSetupDecode(TIFF* tif) +{ + LogLuvState* sp = DecoderState(tif); + TIFFDirectory* td = &tif->tif_dir; + + tif->tif_postdecode = _TIFFNoPostDecode; + switch (td->td_photometric) { + case PHOTOMETRIC_LOGLUV: + if (!LogLuvInitState(tif)) + break; + if (td->td_compression == COMPRESSION_SGILOG24) { + tif->tif_decoderow = LogLuvDecode24; + switch (sp->user_datafmt) { + case SGILOGDATAFMT_FLOAT: + sp->tfunc = Luv24toXYZ; + break; + case SGILOGDATAFMT_16BIT: + sp->tfunc = Luv24toLuv48; + break; + case SGILOGDATAFMT_8BIT: + sp->tfunc = Luv24toRGB; + break; + } + } else { + tif->tif_decoderow = LogLuvDecode32; + switch (sp->user_datafmt) { + case SGILOGDATAFMT_FLOAT: + sp->tfunc = Luv32toXYZ; + break; + case SGILOGDATAFMT_16BIT: + sp->tfunc = Luv32toLuv48; + break; + case SGILOGDATAFMT_8BIT: + sp->tfunc = Luv32toRGB; + break; + } + } + return (1); + case PHOTOMETRIC_LOGL: + if (!LogL16InitState(tif)) + break; + tif->tif_decoderow = LogL16Decode; + switch (sp->user_datafmt) { + case SGILOGDATAFMT_FLOAT: + sp->tfunc = L16toY; + break; + case SGILOGDATAFMT_8BIT: + sp->tfunc = L16toGry; + break; + } + return (1); + default: + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Inappropriate photometric interpretation %d for SGILog compression; %s", + td->td_photometric, "must be either LogLUV or LogL"); + break; + } + return (0); +} + +static int +LogLuvSetupEncode(TIFF* tif) +{ + LogLuvState* sp = EncoderState(tif); + TIFFDirectory* td = &tif->tif_dir; + + switch (td->td_photometric) { + case PHOTOMETRIC_LOGLUV: + if (!LogLuvInitState(tif)) + break; + if (td->td_compression == COMPRESSION_SGILOG24) { + tif->tif_encoderow = LogLuvEncode24; + switch (sp->user_datafmt) { + case SGILOGDATAFMT_FLOAT: + sp->tfunc = Luv24fromXYZ; + break; + case SGILOGDATAFMT_16BIT: + sp->tfunc = Luv24fromLuv48; + break; + case SGILOGDATAFMT_RAW: + break; + default: + goto notsupported; + } + } else { + tif->tif_encoderow = LogLuvEncode32; + switch (sp->user_datafmt) { + case SGILOGDATAFMT_FLOAT: + sp->tfunc = Luv32fromXYZ; + break; + case SGILOGDATAFMT_16BIT: + sp->tfunc = Luv32fromLuv48; + break; + case SGILOGDATAFMT_RAW: + break; + default: + goto notsupported; + } + } + break; + case PHOTOMETRIC_LOGL: + if (!LogL16InitState(tif)) + break; + tif->tif_encoderow = LogL16Encode; + switch (sp->user_datafmt) { + case SGILOGDATAFMT_FLOAT: + sp->tfunc = L16fromY; + break; + case SGILOGDATAFMT_16BIT: + break; + default: + goto notsupported; + } + break; + default: + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Inappropriate photometric interpretation %d for SGILog compression; %s", + td->td_photometric, "must be either LogLUV or LogL"); + break; + } + return (1); +notsupported: + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "SGILog compression supported only for %s, or raw data", + td->td_photometric == PHOTOMETRIC_LOGL ? "Y, L" : "XYZ, Luv"); + return (0); +} + +static void +LogLuvClose(TIFF* tif) +{ + TIFFDirectory *td = &tif->tif_dir; + + /* + * For consistency, we always want to write out the same + * bitspersample and sampleformat for our TIFF file, + * regardless of the data format being used by the application. + * Since this routine is called after tags have been set but + * before they have been recorded in the file, we reset them here. + */ + td->td_samplesperpixel = + (td->td_photometric == PHOTOMETRIC_LOGL) ? 1 : 3; + td->td_bitspersample = 16; + td->td_sampleformat = SAMPLEFORMAT_INT; +} + +static void +LogLuvCleanup(TIFF* tif) +{ + LogLuvState* sp = (LogLuvState *)tif->tif_data; + + assert(sp != 0); + + tif->tif_tagmethods.vgetfield = sp->vgetparent; + tif->tif_tagmethods.vsetfield = sp->vsetparent; + + if (sp->tbuf) + _TIFFfree(sp->tbuf); + _TIFFfree(sp); + tif->tif_data = NULL; + + _TIFFSetDefaultCompressionState(tif); +} + +static int +LogLuvVSetField(TIFF* tif, ttag_t tag, va_list ap) +{ + LogLuvState* sp = DecoderState(tif); + int bps, fmt; + + switch (tag) { + case TIFFTAG_SGILOGDATAFMT: + sp->user_datafmt = va_arg(ap, int); + /* + * Tweak the TIFF header so that the rest of libtiff knows what + * size of data will be passed between app and library, and + * assume that the app knows what it is doing and is not + * confused by these header manipulations... + */ + switch (sp->user_datafmt) { + case SGILOGDATAFMT_FLOAT: + bps = 32, fmt = SAMPLEFORMAT_IEEEFP; + break; + case SGILOGDATAFMT_16BIT: + bps = 16, fmt = SAMPLEFORMAT_INT; + break; + case SGILOGDATAFMT_RAW: + bps = 32, fmt = SAMPLEFORMAT_UINT; + TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1); + break; + case SGILOGDATAFMT_8BIT: + bps = 8, fmt = SAMPLEFORMAT_UINT; + break; + default: + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Unknown data format %d for LogLuv compression", + sp->user_datafmt); + return (0); + } + TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bps); + TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, fmt); + /* + * Must recalculate sizes should bits/sample change. + */ + tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tsize_t) -1; + tif->tif_scanlinesize = TIFFScanlineSize(tif); + return (1); + case TIFFTAG_SGILOGENCODE: + sp->encode_meth = va_arg(ap, int); + if (sp->encode_meth != SGILOGENCODE_NODITHER && + sp->encode_meth != SGILOGENCODE_RANDITHER) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Unknown encoding %d for LogLuv compression", + sp->encode_meth); + return (0); + } + return (1); + default: + return (*sp->vsetparent)(tif, tag, ap); + } +} + +static int +LogLuvVGetField(TIFF* tif, ttag_t tag, va_list ap) +{ + LogLuvState *sp = (LogLuvState *)tif->tif_data; + + switch (tag) { + case TIFFTAG_SGILOGDATAFMT: + *va_arg(ap, int*) = sp->user_datafmt; + return (1); + default: + return (*sp->vgetparent)(tif, tag, ap); + } +} + +static const TIFFFieldInfo LogLuvFieldInfo[] = { + { TIFFTAG_SGILOGDATAFMT, 0, 0, TIFF_SHORT, FIELD_PSEUDO, + TRUE, FALSE, "SGILogDataFmt"}, + { TIFFTAG_SGILOGENCODE, 0, 0, TIFF_SHORT, FIELD_PSEUDO, + TRUE, FALSE, "SGILogEncode"} +}; + +int +TIFFInitSGILog(TIFF* tif, int scheme) +{ + static const char module[] = "TIFFInitSGILog"; + LogLuvState* sp; + + assert(scheme == COMPRESSION_SGILOG24 || scheme == COMPRESSION_SGILOG); + + /* + * Merge codec-specific tag information. + */ + if (!_TIFFMergeFieldInfo(tif, LogLuvFieldInfo, + TIFFArrayCount(LogLuvFieldInfo))) { + TIFFErrorExt(tif->tif_clientdata, module, + "Merging SGILog codec-specific tags failed"); + return 0; + } + + /* + * Allocate state block so tag methods have storage to record values. + */ + tif->tif_data = (tidata_t) _TIFFmalloc(sizeof (LogLuvState)); + if (tif->tif_data == NULL) + goto bad; + sp = (LogLuvState*) tif->tif_data; + _TIFFmemset((tdata_t)sp, 0, sizeof (*sp)); + sp->user_datafmt = SGILOGDATAFMT_UNKNOWN; + sp->encode_meth = (scheme == COMPRESSION_SGILOG24) ? + SGILOGENCODE_RANDITHER : SGILOGENCODE_NODITHER; + sp->tfunc = _logLuvNop; + + /* + * Install codec methods. + * NB: tif_decoderow & tif_encoderow are filled + * in at setup time. + */ + tif->tif_setupdecode = LogLuvSetupDecode; + tif->tif_decodestrip = LogLuvDecodeStrip; + tif->tif_decodetile = LogLuvDecodeTile; + tif->tif_setupencode = LogLuvSetupEncode; + tif->tif_encodestrip = LogLuvEncodeStrip; + tif->tif_encodetile = LogLuvEncodeTile; + tif->tif_close = LogLuvClose; + tif->tif_cleanup = LogLuvCleanup; + + /* + * Override parent get/set field methods. + */ + sp->vgetparent = tif->tif_tagmethods.vgetfield; + tif->tif_tagmethods.vgetfield = LogLuvVGetField; /* hook for codec tags */ + sp->vsetparent = tif->tif_tagmethods.vsetfield; + tif->tif_tagmethods.vsetfield = LogLuvVSetField; /* hook for codec tags */ + + return (1); +bad: + TIFFErrorExt(tif->tif_clientdata, module, + "%s: No space for LogLuv state block", tif->tif_name); + return (0); +} +#endif /* LOGLUV_SUPPORT */ + +/* vim: set ts=8 sts=8 sw=8 noet: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tif_lzw.c b/reactos/dll/3rdparty/libtiff/tif_lzw.c new file mode 100644 index 00000000000..d423866359e --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tif_lzw.c @@ -0,0 +1,1129 @@ +/* $Id: tif_lzw.c,v 1.29.2.6 2010-06-08 18:50:42 bfriesen Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include "tiffiop.h" +#ifdef LZW_SUPPORT +/* + * TIFF Library. + * Rev 5.0 Lempel-Ziv & Welch Compression Support + * + * This code is derived from the compress program whose code is + * derived from software contributed to Berkeley by James A. Woods, + * derived from original work by Spencer Thomas and Joseph Orost. + * + * The original Berkeley copyright notice appears below in its entirety. + */ +#include "tif_predict.h" + +#include + +/* + * NB: The 5.0 spec describes a different algorithm than Aldus + * implements. Specifically, Aldus does code length transitions + * one code earlier than should be done (for real LZW). + * Earlier versions of this library implemented the correct + * LZW algorithm, but emitted codes in a bit order opposite + * to the TIFF spec. Thus, to maintain compatibility w/ Aldus + * we interpret MSB-LSB ordered codes to be images written w/ + * old versions of this library, but otherwise adhere to the + * Aldus "off by one" algorithm. + * + * Future revisions to the TIFF spec are expected to "clarify this issue". + */ +#define LZW_COMPAT /* include backwards compatibility code */ +/* + * Each strip of data is supposed to be terminated by a CODE_EOI. + * If the following #define is included, the decoder will also + * check for end-of-strip w/o seeing this code. This makes the + * library more robust, but also slower. + */ +#define LZW_CHECKEOS /* include checks for strips w/o EOI code */ + +#define MAXCODE(n) ((1L<<(n))-1) +/* + * The TIFF spec specifies that encoded bit + * strings range from 9 to 12 bits. + */ +#define BITS_MIN 9 /* start with 9 bits */ +#define BITS_MAX 12 /* max of 12 bit strings */ +/* predefined codes */ +#define CODE_CLEAR 256 /* code to clear string table */ +#define CODE_EOI 257 /* end-of-information code */ +#define CODE_FIRST 258 /* first free code entry */ +#define CODE_MAX MAXCODE(BITS_MAX) +#define HSIZE 9001L /* 91% occupancy */ +#define HSHIFT (13-8) +#ifdef LZW_COMPAT +/* NB: +1024 is for compatibility with old files */ +#define CSIZE (MAXCODE(BITS_MAX)+1024L) +#else +#define CSIZE (MAXCODE(BITS_MAX)+1L) +#endif + +/* + * State block for each open TIFF file using LZW + * compression/decompression. Note that the predictor + * state block must be first in this data structure. + */ +typedef struct { + TIFFPredictorState predict; /* predictor super class */ + + unsigned short nbits; /* # of bits/code */ + unsigned short maxcode; /* maximum code for lzw_nbits */ + unsigned short free_ent; /* next free entry in hash table */ + long nextdata; /* next bits of i/o */ + long nextbits; /* # of valid bits in lzw_nextdata */ + + int rw_mode; /* preserve rw_mode from init */ +} LZWBaseState; + +#define lzw_nbits base.nbits +#define lzw_maxcode base.maxcode +#define lzw_free_ent base.free_ent +#define lzw_nextdata base.nextdata +#define lzw_nextbits base.nextbits + +/* + * Encoding-specific state. + */ +typedef uint16 hcode_t; /* codes fit in 16 bits */ +typedef struct { + long hash; + hcode_t code; +} hash_t; + +/* + * Decoding-specific state. + */ +typedef struct code_ent { + struct code_ent *next; + unsigned short length; /* string len, including this token */ + unsigned char value; /* data value */ + unsigned char firstchar; /* first token of string */ +} code_t; + +typedef int (*decodeFunc)(TIFF*, tidata_t, tsize_t, tsample_t); + +typedef struct { + LZWBaseState base; + + /* Decoding specific data */ + long dec_nbitsmask; /* lzw_nbits 1 bits, right adjusted */ + long dec_restart; /* restart count */ +#ifdef LZW_CHECKEOS + long dec_bitsleft; /* available bits in raw data */ +#endif + decodeFunc dec_decode; /* regular or backwards compatible */ + code_t* dec_codep; /* current recognized code */ + code_t* dec_oldcodep; /* previously recognized code */ + code_t* dec_free_entp; /* next free entry */ + code_t* dec_maxcodep; /* max available entry */ + code_t* dec_codetab; /* kept separate for small machines */ + + /* Encoding specific data */ + int enc_oldcode; /* last code encountered */ + long enc_checkpoint; /* point at which to clear table */ +#define CHECK_GAP 10000 /* enc_ratio check interval */ + long enc_ratio; /* current compression ratio */ + long enc_incount; /* (input) data bytes encoded */ + long enc_outcount; /* encoded (output) bytes */ + tidata_t enc_rawlimit; /* bound on tif_rawdata buffer */ + hash_t* enc_hashtab; /* kept separate for small machines */ +} LZWCodecState; + +#define LZWState(tif) ((LZWBaseState*) (tif)->tif_data) +#define DecoderState(tif) ((LZWCodecState*) LZWState(tif)) +#define EncoderState(tif) ((LZWCodecState*) LZWState(tif)) + +static int LZWDecode(TIFF*, tidata_t, tsize_t, tsample_t); +#ifdef LZW_COMPAT +static int LZWDecodeCompat(TIFF*, tidata_t, tsize_t, tsample_t); +#endif +static void cl_hash(LZWCodecState*); + +/* + * LZW Decoder. + */ + +#ifdef LZW_CHECKEOS +/* + * This check shouldn't be necessary because each + * strip is suppose to be terminated with CODE_EOI. + */ +#define NextCode(_tif, _sp, _bp, _code, _get) { \ + if ((_sp)->dec_bitsleft < nbits) { \ + TIFFWarningExt(_tif->tif_clientdata, _tif->tif_name, \ + "LZWDecode: Strip %d not terminated with EOI code", \ + _tif->tif_curstrip); \ + _code = CODE_EOI; \ + } else { \ + _get(_sp,_bp,_code); \ + (_sp)->dec_bitsleft -= nbits; \ + } \ +} +#else +#define NextCode(tif, sp, bp, code, get) get(sp, bp, code) +#endif + +static int +LZWSetupDecode(TIFF* tif) +{ + LZWCodecState* sp = DecoderState(tif); + static const char module[] = " LZWSetupDecode"; + int code; + + if( sp == NULL ) + { + /* + * Allocate state block so tag methods have storage to record + * values. + */ + tif->tif_data = (tidata_t) _TIFFmalloc(sizeof(LZWCodecState)); + if (tif->tif_data == NULL) + { + TIFFErrorExt(tif->tif_clientdata, "LZWPreDecode", "No space for LZW state block"); + return (0); + } + + DecoderState(tif)->dec_codetab = NULL; + DecoderState(tif)->dec_decode = NULL; + + /* + * Setup predictor setup. + */ + (void) TIFFPredictorInit(tif); + + sp = DecoderState(tif); + } + + assert(sp != NULL); + + if (sp->dec_codetab == NULL) { + sp->dec_codetab = (code_t*)_TIFFmalloc(CSIZE*sizeof (code_t)); + if (sp->dec_codetab == NULL) { + TIFFErrorExt(tif->tif_clientdata, module, + "No space for LZW code table"); + return (0); + } + /* + * Pre-load the table. + */ + code = 255; + do { + sp->dec_codetab[code].value = code; + sp->dec_codetab[code].firstchar = code; + sp->dec_codetab[code].length = 1; + sp->dec_codetab[code].next = NULL; + } while (code--); + /* + * Zero-out the unused entries + */ + _TIFFmemset(&sp->dec_codetab[CODE_CLEAR], 0, + (CODE_FIRST - CODE_CLEAR) * sizeof (code_t)); + } + return (1); +} + +/* + * Setup state for decoding a strip. + */ +static int +LZWPreDecode(TIFF* tif, tsample_t s) +{ + LZWCodecState *sp = DecoderState(tif); + + (void) s; + assert(sp != NULL); + if( sp->dec_codetab == NULL ) + { + tif->tif_setupdecode( tif ); + } + + /* + * Check for old bit-reversed codes. + */ + if (tif->tif_rawdata[0] == 0 && (tif->tif_rawdata[1] & 0x1)) { +#ifdef LZW_COMPAT + if (!sp->dec_decode) { + TIFFWarningExt(tif->tif_clientdata, tif->tif_name, + "Old-style LZW codes, convert file"); + /* + * Override default decoding methods with + * ones that deal with the old coding. + * Otherwise the predictor versions set + * above will call the compatibility routines + * through the dec_decode method. + */ + tif->tif_decoderow = LZWDecodeCompat; + tif->tif_decodestrip = LZWDecodeCompat; + tif->tif_decodetile = LZWDecodeCompat; + /* + * If doing horizontal differencing, must + * re-setup the predictor logic since we + * switched the basic decoder methods... + */ + (*tif->tif_setupdecode)(tif); + sp->dec_decode = LZWDecodeCompat; + } + sp->lzw_maxcode = MAXCODE(BITS_MIN); +#else /* !LZW_COMPAT */ + if (!sp->dec_decode) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Old-style LZW codes not supported"); + sp->dec_decode = LZWDecode; + } + return (0); +#endif/* !LZW_COMPAT */ + } else { + sp->lzw_maxcode = MAXCODE(BITS_MIN)-1; + sp->dec_decode = LZWDecode; + } + sp->lzw_nbits = BITS_MIN; + sp->lzw_nextbits = 0; + sp->lzw_nextdata = 0; + + sp->dec_restart = 0; + sp->dec_nbitsmask = MAXCODE(BITS_MIN); +#ifdef LZW_CHECKEOS + sp->dec_bitsleft = tif->tif_rawcc << 3; +#endif + sp->dec_free_entp = sp->dec_codetab + CODE_FIRST; + /* + * Zero entries that are not yet filled in. We do + * this to guard against bogus input data that causes + * us to index into undefined entries. If you can + * come up with a way to safely bounds-check input codes + * while decoding then you can remove this operation. + */ + _TIFFmemset(sp->dec_free_entp, 0, (CSIZE-CODE_FIRST)*sizeof (code_t)); + sp->dec_oldcodep = &sp->dec_codetab[-1]; + sp->dec_maxcodep = &sp->dec_codetab[sp->dec_nbitsmask-1]; + return (1); +} + +/* + * Decode a "hunk of data". + */ +#define GetNextCode(sp, bp, code) { \ + nextdata = (nextdata<<8) | *(bp)++; \ + nextbits += 8; \ + if (nextbits < nbits) { \ + nextdata = (nextdata<<8) | *(bp)++; \ + nextbits += 8; \ + } \ + code = (hcode_t)((nextdata >> (nextbits-nbits)) & nbitsmask); \ + nextbits -= nbits; \ +} + +static void +codeLoop(TIFF* tif) +{ + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "LZWDecode: Bogus encoding, loop in the code table; scanline %d", + tif->tif_row); +} + +static int +LZWDecode(TIFF* tif, tidata_t op0, tsize_t occ0, tsample_t s) +{ + LZWCodecState *sp = DecoderState(tif); + char *op = (char*) op0; + long occ = (long) occ0; + char *tp; + unsigned char *bp; + hcode_t code; + int len; + long nbits, nextbits, nextdata, nbitsmask; + code_t *codep, *free_entp, *maxcodep, *oldcodep; + + (void) s; + assert(sp != NULL); + assert(sp->dec_codetab != NULL); + /* + * Restart interrupted output operation. + */ + if (sp->dec_restart) { + long residue; + + codep = sp->dec_codep; + residue = codep->length - sp->dec_restart; + if (residue > occ) { + /* + * Residue from previous decode is sufficient + * to satisfy decode request. Skip to the + * start of the decoded string, place decoded + * values in the output buffer, and return. + */ + sp->dec_restart += occ; + do { + codep = codep->next; + } while (--residue > occ && codep); + if (codep) { + tp = op + occ; + do { + *--tp = codep->value; + codep = codep->next; + } while (--occ && codep); + } + return (1); + } + /* + * Residue satisfies only part of the decode request. + */ + op += residue, occ -= residue; + tp = op; + do { + int t; + --tp; + t = codep->value; + codep = codep->next; + *tp = t; + } while (--residue && codep); + sp->dec_restart = 0; + } + + bp = (unsigned char *)tif->tif_rawcp; + nbits = sp->lzw_nbits; + nextdata = sp->lzw_nextdata; + nextbits = sp->lzw_nextbits; + nbitsmask = sp->dec_nbitsmask; + oldcodep = sp->dec_oldcodep; + free_entp = sp->dec_free_entp; + maxcodep = sp->dec_maxcodep; + + while (occ > 0) { + NextCode(tif, sp, bp, code, GetNextCode); + if (code == CODE_EOI) + break; + if (code == CODE_CLEAR) { + free_entp = sp->dec_codetab + CODE_FIRST; + _TIFFmemset(free_entp, 0, + (CSIZE - CODE_FIRST) * sizeof (code_t)); + nbits = BITS_MIN; + nbitsmask = MAXCODE(BITS_MIN); + maxcodep = sp->dec_codetab + nbitsmask-1; + NextCode(tif, sp, bp, code, GetNextCode); + if (code == CODE_EOI) + break; + if (code == CODE_CLEAR) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "LZWDecode: Corrupted LZW table at scanline %d", + tif->tif_row); + return (0); + } + *op++ = (char)code, occ--; + oldcodep = sp->dec_codetab + code; + continue; + } + codep = sp->dec_codetab + code; + + /* + * Add the new entry to the code table. + */ + if (free_entp < &sp->dec_codetab[0] || + free_entp >= &sp->dec_codetab[CSIZE]) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "LZWDecode: Corrupted LZW table at scanline %d", + tif->tif_row); + return (0); + } + + free_entp->next = oldcodep; + if (free_entp->next < &sp->dec_codetab[0] || + free_entp->next >= &sp->dec_codetab[CSIZE]) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "LZWDecode: Corrupted LZW table at scanline %d", + tif->tif_row); + return (0); + } + free_entp->firstchar = free_entp->next->firstchar; + free_entp->length = free_entp->next->length+1; + free_entp->value = (codep < free_entp) ? + codep->firstchar : free_entp->firstchar; + if (++free_entp > maxcodep) { + if (++nbits > BITS_MAX) /* should not happen */ + nbits = BITS_MAX; + nbitsmask = MAXCODE(nbits); + maxcodep = sp->dec_codetab + nbitsmask-1; + } + oldcodep = codep; + if (code >= 256) { + /* + * Code maps to a string, copy string + * value to output (written in reverse). + */ + if(codep->length == 0) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "LZWDecode: Wrong length of decoded string: " + "data probably corrupted at scanline %d", + tif->tif_row); + return (0); + } + if (codep->length > occ) { + /* + * String is too long for decode buffer, + * locate portion that will fit, copy to + * the decode buffer, and setup restart + * logic for the next decoding call. + */ + sp->dec_codep = codep; + do { + codep = codep->next; + } while (codep && codep->length > occ); + if (codep) { + sp->dec_restart = occ; + tp = op + occ; + do { + *--tp = codep->value; + codep = codep->next; + } while (--occ && codep); + if (codep) + codeLoop(tif); + } + break; + } + len = codep->length; + tp = op + len; + do { + int t; + --tp; + t = codep->value; + codep = codep->next; + *tp = t; + } while (codep && tp > op); + if (codep) { + codeLoop(tif); + break; + } + op += len, occ -= len; + } else + *op++ = (char)code, occ--; + } + + tif->tif_rawcp = (tidata_t) bp; + sp->lzw_nbits = (unsigned short) nbits; + sp->lzw_nextdata = nextdata; + sp->lzw_nextbits = nextbits; + sp->dec_nbitsmask = nbitsmask; + sp->dec_oldcodep = oldcodep; + sp->dec_free_entp = free_entp; + sp->dec_maxcodep = maxcodep; + + if (occ > 0) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "LZWDecode: Not enough data at scanline %d (short %ld bytes)", + tif->tif_row, occ); + return (0); + } + return (1); +} + +#ifdef LZW_COMPAT +/* + * Decode a "hunk of data" for old images. + */ +#define GetNextCodeCompat(sp, bp, code) { \ + nextdata |= (unsigned long) *(bp)++ << nextbits; \ + nextbits += 8; \ + if (nextbits < nbits) { \ + nextdata |= (unsigned long) *(bp)++ << nextbits;\ + nextbits += 8; \ + } \ + code = (hcode_t)(nextdata & nbitsmask); \ + nextdata >>= nbits; \ + nextbits -= nbits; \ +} + +static int +LZWDecodeCompat(TIFF* tif, tidata_t op0, tsize_t occ0, tsample_t s) +{ + LZWCodecState *sp = DecoderState(tif); + char *op = (char*) op0; + long occ = (long) occ0; + char *tp; + unsigned char *bp; + int code, nbits; + long nextbits, nextdata, nbitsmask; + code_t *codep, *free_entp, *maxcodep, *oldcodep; + + (void) s; + assert(sp != NULL); + /* + * Restart interrupted output operation. + */ + if (sp->dec_restart) { + long residue; + + codep = sp->dec_codep; + residue = codep->length - sp->dec_restart; + if (residue > occ) { + /* + * Residue from previous decode is sufficient + * to satisfy decode request. Skip to the + * start of the decoded string, place decoded + * values in the output buffer, and return. + */ + sp->dec_restart += occ; + do { + codep = codep->next; + } while (--residue > occ); + tp = op + occ; + do { + *--tp = codep->value; + codep = codep->next; + } while (--occ); + return (1); + } + /* + * Residue satisfies only part of the decode request. + */ + op += residue, occ -= residue; + tp = op; + do { + *--tp = codep->value; + codep = codep->next; + } while (--residue); + sp->dec_restart = 0; + } + + bp = (unsigned char *)tif->tif_rawcp; + nbits = sp->lzw_nbits; + nextdata = sp->lzw_nextdata; + nextbits = sp->lzw_nextbits; + nbitsmask = sp->dec_nbitsmask; + oldcodep = sp->dec_oldcodep; + free_entp = sp->dec_free_entp; + maxcodep = sp->dec_maxcodep; + + while (occ > 0) { + NextCode(tif, sp, bp, code, GetNextCodeCompat); + if (code == CODE_EOI) + break; + if (code == CODE_CLEAR) { + free_entp = sp->dec_codetab + CODE_FIRST; + _TIFFmemset(free_entp, 0, + (CSIZE - CODE_FIRST) * sizeof (code_t)); + nbits = BITS_MIN; + nbitsmask = MAXCODE(BITS_MIN); + maxcodep = sp->dec_codetab + nbitsmask; + NextCode(tif, sp, bp, code, GetNextCodeCompat); + if (code == CODE_EOI) + break; + if (code == CODE_CLEAR) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "LZWDecode: Corrupted LZW table at scanline %d", + tif->tif_row); + return (0); + } + *op++ = code, occ--; + oldcodep = sp->dec_codetab + code; + continue; + } + codep = sp->dec_codetab + code; + + /* + * Add the new entry to the code table. + */ + if (free_entp < &sp->dec_codetab[0] || + free_entp >= &sp->dec_codetab[CSIZE]) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "LZWDecodeCompat: Corrupted LZW table at scanline %d", + tif->tif_row); + return (0); + } + + free_entp->next = oldcodep; + if (free_entp->next < &sp->dec_codetab[0] || + free_entp->next >= &sp->dec_codetab[CSIZE]) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "LZWDecodeCompat: Corrupted LZW table at scanline %d", + tif->tif_row); + return (0); + } + free_entp->firstchar = free_entp->next->firstchar; + free_entp->length = free_entp->next->length+1; + free_entp->value = (codep < free_entp) ? + codep->firstchar : free_entp->firstchar; + if (++free_entp > maxcodep) { + if (++nbits > BITS_MAX) /* should not happen */ + nbits = BITS_MAX; + nbitsmask = MAXCODE(nbits); + maxcodep = sp->dec_codetab + nbitsmask; + } + oldcodep = codep; + if (code >= 256) { + char *op_orig = op; + /* + * Code maps to a string, copy string + * value to output (written in reverse). + */ + if(codep->length == 0) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "LZWDecodeCompat: Wrong length of decoded " + "string: data probably corrupted at scanline %d", + tif->tif_row); + return (0); + } + if (codep->length > occ) { + /* + * String is too long for decode buffer, + * locate portion that will fit, copy to + * the decode buffer, and setup restart + * logic for the next decoding call. + */ + sp->dec_codep = codep; + do { + codep = codep->next; + } while (codep->length > occ); + sp->dec_restart = occ; + tp = op + occ; + do { + *--tp = codep->value; + codep = codep->next; + } while (--occ); + break; + } + op += codep->length, occ -= codep->length; + tp = op; + do { + *--tp = codep->value; + } while( (codep = codep->next) != NULL && tp > op_orig); + } else + *op++ = code, occ--; + } + + tif->tif_rawcp = (tidata_t) bp; + sp->lzw_nbits = nbits; + sp->lzw_nextdata = nextdata; + sp->lzw_nextbits = nextbits; + sp->dec_nbitsmask = nbitsmask; + sp->dec_oldcodep = oldcodep; + sp->dec_free_entp = free_entp; + sp->dec_maxcodep = maxcodep; + + if (occ > 0) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "LZWDecodeCompat: Not enough data at scanline %d (short %ld bytes)", + tif->tif_row, occ); + return (0); + } + return (1); +} +#endif /* LZW_COMPAT */ + +/* + * LZW Encoding. + */ + +static int +LZWSetupEncode(TIFF* tif) +{ + LZWCodecState* sp = EncoderState(tif); + static const char module[] = "LZWSetupEncode"; + + assert(sp != NULL); + sp->enc_hashtab = (hash_t*) _TIFFmalloc(HSIZE*sizeof (hash_t)); + if (sp->enc_hashtab == NULL) { + TIFFErrorExt(tif->tif_clientdata, module, "No space for LZW hash table"); + return (0); + } + return (1); +} + +/* + * Reset encoding state at the start of a strip. + */ +static int +LZWPreEncode(TIFF* tif, tsample_t s) +{ + LZWCodecState *sp = EncoderState(tif); + + (void) s; + assert(sp != NULL); + + if( sp->enc_hashtab == NULL ) + { + tif->tif_setupencode( tif ); + } + + sp->lzw_nbits = BITS_MIN; + sp->lzw_maxcode = MAXCODE(BITS_MIN); + sp->lzw_free_ent = CODE_FIRST; + sp->lzw_nextbits = 0; + sp->lzw_nextdata = 0; + sp->enc_checkpoint = CHECK_GAP; + sp->enc_ratio = 0; + sp->enc_incount = 0; + sp->enc_outcount = 0; + /* + * The 4 here insures there is space for 2 max-sized + * codes in LZWEncode and LZWPostDecode. + */ + sp->enc_rawlimit = tif->tif_rawdata + tif->tif_rawdatasize-1 - 4; + cl_hash(sp); /* clear hash table */ + sp->enc_oldcode = (hcode_t) -1; /* generates CODE_CLEAR in LZWEncode */ + return (1); +} + +#define CALCRATIO(sp, rat) { \ + if (incount > 0x007fffff) { /* NB: shift will overflow */\ + rat = outcount >> 8; \ + rat = (rat == 0 ? 0x7fffffff : incount/rat); \ + } else \ + rat = (incount<<8) / outcount; \ +} +#define PutNextCode(op, c) { \ + nextdata = (nextdata << nbits) | c; \ + nextbits += nbits; \ + *op++ = (unsigned char)(nextdata >> (nextbits-8)); \ + nextbits -= 8; \ + if (nextbits >= 8) { \ + *op++ = (unsigned char)(nextdata >> (nextbits-8)); \ + nextbits -= 8; \ + } \ + outcount += nbits; \ +} + +/* + * Encode a chunk of pixels. + * + * Uses an open addressing double hashing (no chaining) on the + * prefix code/next character combination. We do a variant of + * Knuth's algorithm D (vol. 3, sec. 6.4) along with G. Knott's + * relatively-prime secondary probe. Here, the modular division + * first probe is gives way to a faster exclusive-or manipulation. + * Also do block compression with an adaptive reset, whereby the + * code table is cleared when the compression ratio decreases, + * but after the table fills. The variable-length output codes + * are re-sized at this point, and a CODE_CLEAR is generated + * for the decoder. + */ +static int +LZWEncode(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s) +{ + register LZWCodecState *sp = EncoderState(tif); + register long fcode; + register hash_t *hp; + register int h, c; + hcode_t ent; + long disp; + long incount, outcount, checkpoint; + long nextdata, nextbits; + int free_ent, maxcode, nbits; + tidata_t op, limit; + + (void) s; + if (sp == NULL) + return (0); + + assert(sp->enc_hashtab != NULL); + + /* + * Load local state. + */ + incount = sp->enc_incount; + outcount = sp->enc_outcount; + checkpoint = sp->enc_checkpoint; + nextdata = sp->lzw_nextdata; + nextbits = sp->lzw_nextbits; + free_ent = sp->lzw_free_ent; + maxcode = sp->lzw_maxcode; + nbits = sp->lzw_nbits; + op = tif->tif_rawcp; + limit = sp->enc_rawlimit; + ent = sp->enc_oldcode; + + if (ent == (hcode_t) -1 && cc > 0) { + /* + * NB: This is safe because it can only happen + * at the start of a strip where we know there + * is space in the data buffer. + */ + PutNextCode(op, CODE_CLEAR); + ent = *bp++; cc--; incount++; + } + while (cc > 0) { + c = *bp++; cc--; incount++; + fcode = ((long)c << BITS_MAX) + ent; + h = (c << HSHIFT) ^ ent; /* xor hashing */ +#ifdef _WINDOWS + /* + * Check hash index for an overflow. + */ + if (h >= HSIZE) + h -= HSIZE; +#endif + hp = &sp->enc_hashtab[h]; + if (hp->hash == fcode) { + ent = hp->code; + continue; + } + if (hp->hash >= 0) { + /* + * Primary hash failed, check secondary hash. + */ + disp = HSIZE - h; + if (h == 0) + disp = 1; + do { + /* + * Avoid pointer arithmetic 'cuz of + * wraparound problems with segments. + */ + if ((h -= disp) < 0) + h += HSIZE; + hp = &sp->enc_hashtab[h]; + if (hp->hash == fcode) { + ent = hp->code; + goto hit; + } + } while (hp->hash >= 0); + } + /* + * New entry, emit code and add to table. + */ + /* + * Verify there is space in the buffer for the code + * and any potential Clear code that might be emitted + * below. The value of limit is setup so that there + * are at least 4 bytes free--room for 2 codes. + */ + if (op > limit) { + tif->tif_rawcc = (tsize_t)(op - tif->tif_rawdata); + TIFFFlushData1(tif); + op = tif->tif_rawdata; + } + PutNextCode(op, ent); + ent = c; + hp->code = free_ent++; + hp->hash = fcode; + if (free_ent == CODE_MAX-1) { + /* table is full, emit clear code and reset */ + cl_hash(sp); + sp->enc_ratio = 0; + incount = 0; + outcount = 0; + free_ent = CODE_FIRST; + PutNextCode(op, CODE_CLEAR); + nbits = BITS_MIN; + maxcode = MAXCODE(BITS_MIN); + } else { + /* + * If the next entry is going to be too big for + * the code size, then increase it, if possible. + */ + if (free_ent > maxcode) { + nbits++; + assert(nbits <= BITS_MAX); + maxcode = (int) MAXCODE(nbits); + } else if (incount >= checkpoint) { + long rat; + /* + * Check compression ratio and, if things seem + * to be slipping, clear the hash table and + * reset state. The compression ratio is a + * 24+8-bit fractional number. + */ + checkpoint = incount+CHECK_GAP; + CALCRATIO(sp, rat); + if (rat <= sp->enc_ratio) { + cl_hash(sp); + sp->enc_ratio = 0; + incount = 0; + outcount = 0; + free_ent = CODE_FIRST; + PutNextCode(op, CODE_CLEAR); + nbits = BITS_MIN; + maxcode = MAXCODE(BITS_MIN); + } else + sp->enc_ratio = rat; + } + } + hit: + ; + } + + /* + * Restore global state. + */ + sp->enc_incount = incount; + sp->enc_outcount = outcount; + sp->enc_checkpoint = checkpoint; + sp->enc_oldcode = ent; + sp->lzw_nextdata = nextdata; + sp->lzw_nextbits = nextbits; + sp->lzw_free_ent = free_ent; + sp->lzw_maxcode = maxcode; + sp->lzw_nbits = nbits; + tif->tif_rawcp = op; + return (1); +} + +/* + * Finish off an encoded strip by flushing the last + * string and tacking on an End Of Information code. + */ +static int +LZWPostEncode(TIFF* tif) +{ + register LZWCodecState *sp = EncoderState(tif); + tidata_t op = tif->tif_rawcp; + long nextbits = sp->lzw_nextbits; + long nextdata = sp->lzw_nextdata; + long outcount = sp->enc_outcount; + int nbits = sp->lzw_nbits; + + if (op > sp->enc_rawlimit) { + tif->tif_rawcc = (tsize_t)(op - tif->tif_rawdata); + TIFFFlushData1(tif); + op = tif->tif_rawdata; + } + if (sp->enc_oldcode != (hcode_t) -1) { + PutNextCode(op, sp->enc_oldcode); + sp->enc_oldcode = (hcode_t) -1; + } + PutNextCode(op, CODE_EOI); + if (nextbits > 0) + *op++ = (unsigned char)(nextdata << (8-nextbits)); + tif->tif_rawcc = (tsize_t)(op - tif->tif_rawdata); + return (1); +} + +/* + * Reset encoding hash table. + */ +static void +cl_hash(LZWCodecState* sp) +{ + register hash_t *hp = &sp->enc_hashtab[HSIZE-1]; + register long i = HSIZE-8; + + do { + i -= 8; + hp[-7].hash = -1; + hp[-6].hash = -1; + hp[-5].hash = -1; + hp[-4].hash = -1; + hp[-3].hash = -1; + hp[-2].hash = -1; + hp[-1].hash = -1; + hp[ 0].hash = -1; + hp -= 8; + } while (i >= 0); + for (i += 8; i > 0; i--, hp--) + hp->hash = -1; +} + +static void +LZWCleanup(TIFF* tif) +{ + (void)TIFFPredictorCleanup(tif); + + assert(tif->tif_data != 0); + + if (DecoderState(tif)->dec_codetab) + _TIFFfree(DecoderState(tif)->dec_codetab); + + if (EncoderState(tif)->enc_hashtab) + _TIFFfree(EncoderState(tif)->enc_hashtab); + + _TIFFfree(tif->tif_data); + tif->tif_data = NULL; + + _TIFFSetDefaultCompressionState(tif); +} + +int +TIFFInitLZW(TIFF* tif, int scheme) +{ + assert(scheme == COMPRESSION_LZW); + /* + * Allocate state block so tag methods have storage to record values. + */ + tif->tif_data = (tidata_t) _TIFFmalloc(sizeof (LZWCodecState)); + if (tif->tif_data == NULL) + goto bad; + DecoderState(tif)->dec_codetab = NULL; + DecoderState(tif)->dec_decode = NULL; + EncoderState(tif)->enc_hashtab = NULL; + LZWState(tif)->rw_mode = tif->tif_mode; + + /* + * Install codec methods. + */ + tif->tif_setupdecode = LZWSetupDecode; + tif->tif_predecode = LZWPreDecode; + tif->tif_decoderow = LZWDecode; + tif->tif_decodestrip = LZWDecode; + tif->tif_decodetile = LZWDecode; + tif->tif_setupencode = LZWSetupEncode; + tif->tif_preencode = LZWPreEncode; + tif->tif_postencode = LZWPostEncode; + tif->tif_encoderow = LZWEncode; + tif->tif_encodestrip = LZWEncode; + tif->tif_encodetile = LZWEncode; + tif->tif_cleanup = LZWCleanup; + /* + * Setup predictor setup. + */ + (void) TIFFPredictorInit(tif); + return (1); +bad: + TIFFErrorExt(tif->tif_clientdata, "TIFFInitLZW", + "No space for LZW state block"); + return (0); +} + +/* + * Copyright (c) 1985, 1986 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * James A. Woods, derived from original work by Spencer Thomas + * and Joseph Orost. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ +#endif /* LZW_SUPPORT */ + +/* vim: set ts=8 sts=8 sw=8 noet: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tif_next.c b/reactos/dll/3rdparty/libtiff/tif_next.c new file mode 100644 index 00000000000..d7652bb4c13 --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tif_next.c @@ -0,0 +1,154 @@ +/* $Id: tif_next.c,v 1.8.2.1 2010-06-08 18:50:42 bfriesen Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include "tiffiop.h" +#ifdef NEXT_SUPPORT +/* + * TIFF Library. + * + * NeXT 2-bit Grey Scale Compression Algorithm Support + */ + +#define SETPIXEL(op, v) { \ + switch (npixels++ & 3) { \ + case 0: op[0] = (unsigned char) ((v) << 6); break; \ + case 1: op[0] |= (v) << 4; break; \ + case 2: op[0] |= (v) << 2; break; \ + case 3: *op++ |= (v); break; \ + } \ +} + +#define LITERALROW 0x00 +#define LITERALSPAN 0x40 +#define WHITE ((1<<2)-1) + +static int +NeXTDecode(TIFF* tif, tidata_t buf, tsize_t occ, tsample_t s) +{ + unsigned char *bp, *op; + tsize_t cc; + tidata_t row; + tsize_t scanline, n; + + (void) s; + /* + * Each scanline is assumed to start off as all + * white (we assume a PhotometricInterpretation + * of ``min-is-black''). + */ + for (op = buf, cc = occ; cc-- > 0;) + *op++ = 0xff; + + bp = (unsigned char *)tif->tif_rawcp; + cc = tif->tif_rawcc; + scanline = tif->tif_scanlinesize; + for (row = buf; occ > 0; occ -= scanline, row += scanline) { + n = *bp++, cc--; + switch (n) { + case LITERALROW: + /* + * The entire scanline is given as literal values. + */ + if (cc < scanline) + goto bad; + _TIFFmemcpy(row, bp, scanline); + bp += scanline; + cc -= scanline; + break; + case LITERALSPAN: { + tsize_t off; + /* + * The scanline has a literal span that begins at some + * offset. + */ + off = (bp[0] * 256) + bp[1]; + n = (bp[2] * 256) + bp[3]; + if (cc < 4+n || off+n > scanline) + goto bad; + _TIFFmemcpy(row+off, bp+4, n); + bp += 4+n; + cc -= 4+n; + break; + } + default: { + uint32 npixels = 0, grey; + uint32 imagewidth = tif->tif_dir.td_imagewidth; + + /* + * The scanline is composed of a sequence of constant + * color ``runs''. We shift into ``run mode'' and + * interpret bytes as codes of the form + * until we've filled the scanline. + */ + op = row; + for (;;) { + grey = (n>>6) & 0x3; + n &= 0x3f; + /* + * Ensure the run does not exceed the scanline + * bounds, potentially resulting in a security + * issue. + */ + while (n-- > 0 && npixels < imagewidth) + SETPIXEL(op, grey); + if (npixels >= imagewidth) + break; + if (cc == 0) + goto bad; + n = *bp++, cc--; + } + break; + } + } + } + tif->tif_rawcp = (tidata_t) bp; + tif->tif_rawcc = cc; + return (1); +bad: + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "NeXTDecode: Not enough data for scanline %ld", + (long) tif->tif_row); + return (0); +} + +int +TIFFInitNeXT(TIFF* tif, int scheme) +{ + (void) scheme; + tif->tif_decoderow = NeXTDecode; + tif->tif_decodestrip = NeXTDecode; + tif->tif_decodetile = NeXTDecode; + return (1); +} +#endif /* NEXT_SUPPORT */ + +/* vim: set ts=8 sts=8 sw=8 noet: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tif_ojpeg.c b/reactos/dll/3rdparty/libtiff/tif_ojpeg.c new file mode 100644 index 00000000000..9ae856cfdef --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tif_ojpeg.c @@ -0,0 +1,2438 @@ +/* $Id: tif_ojpeg.c,v 1.24.2.6 2010-06-08 23:29:51 bfriesen Exp $ */ + +/* WARNING: The type of JPEG encapsulation defined by the TIFF Version 6.0 + specification is now totally obsolete and deprecated for new applications and + images. This file was was created solely in order to read unconverted images + still present on some users' computer systems. It will never be extended + to write such files. Writing new-style JPEG compressed TIFFs is implemented + in tif_jpeg.c. + + The code is carefully crafted to robustly read all gathered JPEG-in-TIFF + testfiles, and anticipate as much as possible all other... But still, it may + fail on some. If you encounter problems, please report them on the TIFF + mailing list and/or to Joris Van Damme . + + Please read the file called "TIFF Technical Note #2" if you need to be + convinced this compression scheme is bad and breaks TIFF. That document + is linked to from the LibTiff site + and from AWare Systems' TIFF section + . It is also absorbed + in Adobe's specification supplements, marked "draft" up to this day, but + supported by the TIFF community. + + This file interfaces with Release 6B of the JPEG Library written by the + Independent JPEG Group. Previous versions of this file required a hack inside + the LibJpeg library. This version no longer requires that. Remember to + remove the hack if you update from the old version. + + Copyright (c) Joris Van Damme + Copyright (c) AWare Systems + + The licence agreement for this file is the same as the rest of the LibTiff + library. + + IN NO EVENT SHALL JORIS VAN DAMME OR AWARE SYSTEMS BE LIABLE FOR + ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + OF THIS SOFTWARE. + + Joris Van Damme and/or AWare Systems may be available for custom + developement. If you like what you see, and need anything similar or related, + contact . +*/ + +/* What is what, and what is not? + + This decoder starts with an input stream, that is essentially the JpegInterchangeFormat + stream, if any, followed by the strile data, if any. This stream is read in + OJPEGReadByte and related functions. + + It analyzes the start of this stream, until it encounters non-marker data, i.e. + compressed image data. Some of the header markers it sees have no actual content, + like the SOI marker, and APP/COM markers that really shouldn't even be there. Some + other markers do have content, and the valuable bits and pieces of information + in these markers are saved, checking all to verify that the stream is more or + less within expected bounds. This happens inside the OJPEGReadHeaderInfoSecStreamXxx + functions. + + Some OJPEG imagery contains no valid JPEG header markers. This situation is picked + up on if we've seen no SOF marker when we're at the start of the compressed image + data. In this case, the tables are read from JpegXxxTables tags, and the other + bits and pieces of information is initialized to its most basic value. This is + implemented in the OJPEGReadHeaderInfoSecTablesXxx functions. + + When this is complete, a good and valid JPEG header can be assembled, and this is + passed through to LibJpeg. When that's done, the remainder of the input stream, i.e. + the compressed image data, can be passed through unchanged. This is done in + OJPEGWriteStream functions. + + LibTiff rightly expects to know the subsampling values before decompression. Just like + in new-style JPEG-in-TIFF, though, or even more so, actually, the YCbCrsubsampling + tag is notoriously unreliable. To correct these tag values with the ones inside + the JPEG stream, the first part of the input stream is pre-scanned in + OJPEGSubsamplingCorrect, making no note of any other data, reporting no warnings + or errors, up to the point where either these values are read, or it's clear they + aren't there. This means that some of the data is read twice, but we feel speed + in correcting these values is important enough to warrant this sacrifice. Allthough + there is currently no define or other configuration mechanism to disable this behaviour, + the actual header scanning is build to robustly respond with error report if it + should encounter an uncorrected mismatch of subsampling values. See + OJPEGReadHeaderInfoSecStreamSof. + + The restart interval and restart markers are the most tricky part... The restart + interval can be specified in a tag. It can also be set inside the input JPEG stream. + It can be used inside the input JPEG stream. If reading from strile data, we've + consistenly discovered the need to insert restart markers in between the different + striles, as is also probably the most likely interpretation of the original TIFF 6.0 + specification. With all this setting of interval, and actual use of markers that is not + predictable at the time of valid JPEG header assembly, the restart thing may turn + out the Achilles heel of this implementation. Fortunately, most OJPEG writer vendors + succeed in reading back what they write, which may be the reason why we've been able + to discover ways that seem to work. + + Some special provision is made for planarconfig separate OJPEG files. These seem + to consistently contain header info, a SOS marker, a plane, SOS marker, plane, SOS, + and plane. This may or may not be a valid JPEG configuration, we don't know and don't + care. We want LibTiff to be able to access the planes individually, without huge + buffering inside LibJpeg, anyway. So we compose headers to feed to LibJpeg, in this + case, that allow us to pass a single plane such that LibJpeg sees a valid + single-channel JPEG stream. Locating subsequent SOS markers, and thus subsequent + planes, is done inside OJPEGReadSecondarySos. + + The benefit of the scheme is... that it works, basically. We know of no other that + does. It works without checking software tag, or otherwise going about things in an + OJPEG flavor specific manner. Instead, it is a single scheme, that covers the cases + with and without JpegInterchangeFormat, with and without striles, with part of + the header in JpegInterchangeFormat and remainder in first strile, etc. It is forgiving + and robust, may likely work with OJPEG flavors we've not seen yet, and makes most out + of the data. + + Another nice side-effect is that a complete JPEG single valid stream is build if + planarconfig is not separate (vast majority). We may one day use that to build + converters to JPEG, and/or to new-style JPEG compression inside TIFF. + + A dissadvantage is the lack of random access to the individual striles. This is the + reason for much of the complicated restart-and-position stuff inside OJPEGPreDecode. + Applications would do well accessing all striles in order, as this will result in + a single sequential scan of the input stream, and no restarting of LibJpeg decoding + session. +*/ + + +#include "tiffiop.h" +#ifdef OJPEG_SUPPORT + +/* Configuration defines here are: + * JPEG_ENCAP_EXTERNAL: The normal way to call libjpeg, uses longjump. In some environments, + * like eg LibTiffDelphi, this is not possible. For this reason, the actual calls to + * libjpeg, with longjump stuff, are encapsulated in dedicated functions. When + * JPEG_ENCAP_EXTERNAL is defined, these encapsulating functions are declared external + * to this unit, and can be defined elsewhere to use stuff other then longjump. + * The default mode, without JPEG_ENCAP_EXTERNAL, implements the call encapsulators + * here, internally, with normal longjump. + * SETJMP, LONGJMP, JMP_BUF: On some machines/environments a longjump equivalent is + * conviniently available, but still it may be worthwhile to use _setjmp or sigsetjmp + * in place of plain setjmp. These macros will make it easier. It is useless + * to fiddle with these if you define JPEG_ENCAP_EXTERNAL. + * OJPEG_BUFFER: Define the size of the desired buffer here. Should be small enough so as to guarantee + * instant processing, optimal streaming and optimal use of processor cache, but also big + * enough so as to not result in significant call overhead. It should be at least a few + * bytes to accomodate some structures (this is verified in asserts), but it would not be + * sensible to make it this small anyway, and it should be at most 64K since it is indexed + * with uint16. We recommend 2K. + * EGYPTIANWALK: You could also define EGYPTIANWALK here, but it is not used anywhere and has + * absolutely no effect. That is why most people insist the EGYPTIANWALK is a bit silly. + */ + +/* #define LIBJPEG_ENCAP_EXTERNAL */ +#define SETJMP(jbuf) setjmp(jbuf) +#define LONGJMP(jbuf,code) longjmp(jbuf,code) +#define JMP_BUF jmp_buf +#define OJPEG_BUFFER 2048 +/* define EGYPTIANWALK */ + +#define JPEG_MARKER_SOF0 0xC0 +#define JPEG_MARKER_SOF1 0xC1 +#define JPEG_MARKER_SOF3 0xC3 +#define JPEG_MARKER_DHT 0xC4 +#define JPEG_MARKER_RST0 0XD0 +#define JPEG_MARKER_SOI 0xD8 +#define JPEG_MARKER_EOI 0xD9 +#define JPEG_MARKER_SOS 0xDA +#define JPEG_MARKER_DQT 0xDB +#define JPEG_MARKER_DRI 0xDD +#define JPEG_MARKER_APP0 0xE0 +#define JPEG_MARKER_COM 0xFE + +#define FIELD_OJPEG_JPEGINTERCHANGEFORMAT (FIELD_CODEC+0) +#define FIELD_OJPEG_JPEGINTERCHANGEFORMATLENGTH (FIELD_CODEC+1) +#define FIELD_OJPEG_JPEGQTABLES (FIELD_CODEC+2) +#define FIELD_OJPEG_JPEGDCTABLES (FIELD_CODEC+3) +#define FIELD_OJPEG_JPEGACTABLES (FIELD_CODEC+4) +#define FIELD_OJPEG_JPEGPROC (FIELD_CODEC+5) +#define FIELD_OJPEG_JPEGRESTARTINTERVAL (FIELD_CODEC+6) +#define FIELD_OJPEG_COUNT 7 + +static const TIFFFieldInfo ojpeg_field_info[] = { + {TIFFTAG_JPEGIFOFFSET,1,1,TIFF_LONG,FIELD_OJPEG_JPEGINTERCHANGEFORMAT,TRUE,FALSE,"JpegInterchangeFormat"}, + {TIFFTAG_JPEGIFBYTECOUNT,1,1,TIFF_LONG,FIELD_OJPEG_JPEGINTERCHANGEFORMATLENGTH,TRUE,FALSE,"JpegInterchangeFormatLength"}, + {TIFFTAG_JPEGQTABLES,TIFF_VARIABLE,TIFF_VARIABLE,TIFF_LONG,FIELD_OJPEG_JPEGQTABLES,FALSE,TRUE,"JpegQTables"}, + {TIFFTAG_JPEGDCTABLES,TIFF_VARIABLE,TIFF_VARIABLE,TIFF_LONG,FIELD_OJPEG_JPEGDCTABLES,FALSE,TRUE,"JpegDcTables"}, + {TIFFTAG_JPEGACTABLES,TIFF_VARIABLE,TIFF_VARIABLE,TIFF_LONG,FIELD_OJPEG_JPEGACTABLES,FALSE,TRUE,"JpegAcTables"}, + {TIFFTAG_JPEGPROC,1,1,TIFF_SHORT,FIELD_OJPEG_JPEGPROC,FALSE,FALSE,"JpegProc"}, + {TIFFTAG_JPEGRESTARTINTERVAL,1,1,TIFF_SHORT,FIELD_OJPEG_JPEGRESTARTINTERVAL,FALSE,FALSE,"JpegRestartInterval"}, +}; + +#ifndef LIBJPEG_ENCAP_EXTERNAL +#include +#endif + +#include "jpeglib.h" +#include "jerror.h" + +typedef struct jpeg_error_mgr jpeg_error_mgr; +typedef struct jpeg_common_struct jpeg_common_struct; +typedef struct jpeg_decompress_struct jpeg_decompress_struct; +typedef struct jpeg_source_mgr jpeg_source_mgr; + +typedef enum { + osibsNotSetYet, + osibsJpegInterchangeFormat, + osibsStrile, + osibsEof +} OJPEGStateInBufferSource; + +typedef enum { + ososSoi, + ososQTable0,ososQTable1,ososQTable2,ososQTable3, + ososDcTable0,ososDcTable1,ososDcTable2,ososDcTable3, + ososAcTable0,ososAcTable1,ososAcTable2,ososAcTable3, + ososDri, + ososSof, + ososSos, + ososCompressed, + ososRst, + ososEoi +} OJPEGStateOutState; + +typedef struct { + TIFF* tif; + #ifndef LIBJPEG_ENCAP_EXTERNAL + JMP_BUF exit_jmpbuf; + #endif + TIFFVGetMethod vgetparent; + TIFFVSetMethod vsetparent; + toff_t file_size; + uint32 image_width; + uint32 image_length; + uint32 strile_width; + uint32 strile_length; + uint32 strile_length_total; + uint8 samples_per_pixel; + uint8 plane_sample_offset; + uint8 samples_per_pixel_per_plane; + toff_t jpeg_interchange_format; + toff_t jpeg_interchange_format_length; + uint8 jpeg_proc; + uint8 subsamplingcorrect; + uint8 subsamplingcorrect_done; + uint8 subsampling_tag; + uint8 subsampling_hor; + uint8 subsampling_ver; + uint8 subsampling_force_desubsampling_inside_decompression; + uint8 qtable_offset_count; + uint8 dctable_offset_count; + uint8 actable_offset_count; + toff_t qtable_offset[3]; + toff_t dctable_offset[3]; + toff_t actable_offset[3]; + uint8* qtable[4]; + uint8* dctable[4]; + uint8* actable[4]; + uint16 restart_interval; + uint8 restart_index; + uint8 sof_log; + uint8 sof_marker_id; + uint32 sof_x; + uint32 sof_y; + uint8 sof_c[3]; + uint8 sof_hv[3]; + uint8 sof_tq[3]; + uint8 sos_cs[3]; + uint8 sos_tda[3]; + struct { + uint8 log; + OJPEGStateInBufferSource in_buffer_source; + tstrile_t in_buffer_next_strile; + toff_t in_buffer_file_pos; + toff_t in_buffer_file_togo; + } sos_end[3]; + uint8 readheader_done; + uint8 writeheader_done; + tsample_t write_cursample; + tstrile_t write_curstrile; + uint8 libjpeg_session_active; + uint8 libjpeg_jpeg_query_style; + jpeg_error_mgr libjpeg_jpeg_error_mgr; + jpeg_decompress_struct libjpeg_jpeg_decompress_struct; + jpeg_source_mgr libjpeg_jpeg_source_mgr; + uint8 subsampling_convert_log; + uint32 subsampling_convert_ylinelen; + uint32 subsampling_convert_ylines; + uint32 subsampling_convert_clinelen; + uint32 subsampling_convert_clines; + uint32 subsampling_convert_ybuflen; + uint32 subsampling_convert_cbuflen; + uint32 subsampling_convert_ycbcrbuflen; + uint8* subsampling_convert_ycbcrbuf; + uint8* subsampling_convert_ybuf; + uint8* subsampling_convert_cbbuf; + uint8* subsampling_convert_crbuf; + uint32 subsampling_convert_ycbcrimagelen; + uint8** subsampling_convert_ycbcrimage; + uint32 subsampling_convert_clinelenout; + uint32 subsampling_convert_state; + uint32 bytes_per_line; /* if the codec outputs subsampled data, a 'line' in bytes_per_line */ + uint32 lines_per_strile; /* and lines_per_strile means subsampling_ver desubsampled rows */ + OJPEGStateInBufferSource in_buffer_source; + tstrile_t in_buffer_next_strile; + tstrile_t in_buffer_strile_count; + toff_t in_buffer_file_pos; + uint8 in_buffer_file_pos_log; + toff_t in_buffer_file_togo; + uint16 in_buffer_togo; + uint8* in_buffer_cur; + uint8 in_buffer[OJPEG_BUFFER]; + OJPEGStateOutState out_state; + uint8 out_buffer[OJPEG_BUFFER]; + uint8* skip_buffer; +} OJPEGState; + +static int OJPEGVGetField(TIFF* tif, ttag_t tag, va_list ap); +static int OJPEGVSetField(TIFF* tif, ttag_t tag, va_list ap); +static void OJPEGPrintDir(TIFF* tif, FILE* fd, long flags); + +static int OJPEGSetupDecode(TIFF* tif); +static int OJPEGPreDecode(TIFF* tif, tsample_t s); +static int OJPEGPreDecodeSkipRaw(TIFF* tif); +static int OJPEGPreDecodeSkipScanlines(TIFF* tif); +static int OJPEGDecode(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s); +static int OJPEGDecodeRaw(TIFF* tif, tidata_t buf, tsize_t cc); +static int OJPEGDecodeScanlines(TIFF* tif, tidata_t buf, tsize_t cc); +static void OJPEGPostDecode(TIFF* tif, tidata_t buf, tsize_t cc); +static int OJPEGSetupEncode(TIFF* tif); +static int OJPEGPreEncode(TIFF* tif, tsample_t s); +static int OJPEGEncode(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s); +static int OJPEGPostEncode(TIFF* tif); +static void OJPEGCleanup(TIFF* tif); + +static void OJPEGSubsamplingCorrect(TIFF* tif); +static int OJPEGReadHeaderInfo(TIFF* tif); +static int OJPEGReadSecondarySos(TIFF* tif, tsample_t s); +static int OJPEGWriteHeaderInfo(TIFF* tif); +static void OJPEGLibjpegSessionAbort(TIFF* tif); + +static int OJPEGReadHeaderInfoSec(TIFF* tif); +static int OJPEGReadHeaderInfoSecStreamDri(TIFF* tif); +static int OJPEGReadHeaderInfoSecStreamDqt(TIFF* tif); +static int OJPEGReadHeaderInfoSecStreamDht(TIFF* tif); +static int OJPEGReadHeaderInfoSecStreamSof(TIFF* tif, uint8 marker_id); +static int OJPEGReadHeaderInfoSecStreamSos(TIFF* tif); +static int OJPEGReadHeaderInfoSecTablesQTable(TIFF* tif); +static int OJPEGReadHeaderInfoSecTablesDcTable(TIFF* tif); +static int OJPEGReadHeaderInfoSecTablesAcTable(TIFF* tif); + +static int OJPEGReadBufferFill(OJPEGState* sp); +static int OJPEGReadByte(OJPEGState* sp, uint8* byte); +static int OJPEGReadBytePeek(OJPEGState* sp, uint8* byte); +static void OJPEGReadByteAdvance(OJPEGState* sp); +static int OJPEGReadWord(OJPEGState* sp, uint16* word); +static int OJPEGReadBlock(OJPEGState* sp, uint16 len, void* mem); +static void OJPEGReadSkip(OJPEGState* sp, uint16 len); + +static int OJPEGWriteStream(TIFF* tif, void** mem, uint32* len); +static void OJPEGWriteStreamSoi(TIFF* tif, void** mem, uint32* len); +static void OJPEGWriteStreamQTable(TIFF* tif, uint8 table_index, void** mem, uint32* len); +static void OJPEGWriteStreamDcTable(TIFF* tif, uint8 table_index, void** mem, uint32* len); +static void OJPEGWriteStreamAcTable(TIFF* tif, uint8 table_index, void** mem, uint32* len); +static void OJPEGWriteStreamDri(TIFF* tif, void** mem, uint32* len); +static void OJPEGWriteStreamSof(TIFF* tif, void** mem, uint32* len); +static void OJPEGWriteStreamSos(TIFF* tif, void** mem, uint32* len); +static int OJPEGWriteStreamCompressed(TIFF* tif, void** mem, uint32* len); +static void OJPEGWriteStreamRst(TIFF* tif, void** mem, uint32* len); +static void OJPEGWriteStreamEoi(TIFF* tif, void** mem, uint32* len); + +#ifdef LIBJPEG_ENCAP_EXTERNAL +extern int jpeg_create_decompress_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo); +extern int jpeg_read_header_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, uint8 require_image); +extern int jpeg_start_decompress_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo); +extern int jpeg_read_scanlines_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, void* scanlines, uint32 max_lines); +extern int jpeg_read_raw_data_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, void* data, uint32 max_lines); +extern void jpeg_encap_unwind(TIFF* tif); +#else +static int jpeg_create_decompress_encap(OJPEGState* sp, jpeg_decompress_struct* j); +static int jpeg_read_header_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, uint8 require_image); +static int jpeg_start_decompress_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo); +static int jpeg_read_scanlines_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, void* scanlines, uint32 max_lines); +static int jpeg_read_raw_data_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, void* data, uint32 max_lines); +static void jpeg_encap_unwind(TIFF* tif); +#endif + +static void OJPEGLibjpegJpegErrorMgrOutputMessage(jpeg_common_struct* cinfo); +static void OJPEGLibjpegJpegErrorMgrErrorExit(jpeg_common_struct* cinfo); +static void OJPEGLibjpegJpegSourceMgrInitSource(jpeg_decompress_struct* cinfo); +static boolean OJPEGLibjpegJpegSourceMgrFillInputBuffer(jpeg_decompress_struct* cinfo); +static void OJPEGLibjpegJpegSourceMgrSkipInputData(jpeg_decompress_struct* cinfo, long num_bytes); +static boolean OJPEGLibjpegJpegSourceMgrResyncToRestart(jpeg_decompress_struct* cinfo, int desired); +static void OJPEGLibjpegJpegSourceMgrTermSource(jpeg_decompress_struct* cinfo); + +int +TIFFInitOJPEG(TIFF* tif, int scheme) +{ + static const char module[]="TIFFInitOJPEG"; + OJPEGState* sp; + + assert(scheme==COMPRESSION_OJPEG); + + /* + * Merge codec-specific tag information. + */ + if (!_TIFFMergeFieldInfo(tif,ojpeg_field_info,FIELD_OJPEG_COUNT)) { + TIFFErrorExt(tif->tif_clientdata, module, + "Merging Old JPEG codec-specific tags failed"); + return 0; + } + + /* state block */ + sp=_TIFFmalloc(sizeof(OJPEGState)); + if (sp==NULL) + { + TIFFErrorExt(tif->tif_clientdata,module,"No space for OJPEG state block"); + return(0); + } + _TIFFmemset(sp,0,sizeof(OJPEGState)); + sp->tif=tif; + sp->jpeg_proc=1; + sp->subsampling_hor=2; + sp->subsampling_ver=2; + TIFFSetField(tif,TIFFTAG_YCBCRSUBSAMPLING,2,2); + /* tif codec methods */ + tif->tif_setupdecode=OJPEGSetupDecode; + tif->tif_predecode=OJPEGPreDecode; + tif->tif_postdecode=OJPEGPostDecode; + tif->tif_decoderow=OJPEGDecode; + tif->tif_decodestrip=OJPEGDecode; + tif->tif_decodetile=OJPEGDecode; + tif->tif_setupencode=OJPEGSetupEncode; + tif->tif_preencode=OJPEGPreEncode; + tif->tif_postencode=OJPEGPostEncode; + tif->tif_encoderow=OJPEGEncode; + tif->tif_encodestrip=OJPEGEncode; + tif->tif_encodetile=OJPEGEncode; + tif->tif_cleanup=OJPEGCleanup; + tif->tif_data=(tidata_t)sp; + /* tif tag methods */ + sp->vgetparent=tif->tif_tagmethods.vgetfield; + tif->tif_tagmethods.vgetfield=OJPEGVGetField; + sp->vsetparent=tif->tif_tagmethods.vsetfield; + tif->tif_tagmethods.vsetfield=OJPEGVSetField; + tif->tif_tagmethods.printdir=OJPEGPrintDir; + /* Some OJPEG files don't have strip or tile offsets or bytecounts tags. + Some others do, but have totally meaningless or corrupt values + in these tags. In these cases, the JpegInterchangeFormat stream is + reliable. In any case, this decoder reads the compressed data itself, + from the most reliable locations, and we need to notify encapsulating + LibTiff not to read raw strips or tiles for us. */ + tif->tif_flags|=TIFF_NOREADRAW; + return(1); +} + +static int +OJPEGVGetField(TIFF* tif, ttag_t tag, va_list ap) +{ + OJPEGState* sp=(OJPEGState*)tif->tif_data; + switch(tag) + { + case TIFFTAG_JPEGIFOFFSET: + *va_arg(ap,uint32*)=(uint32)sp->jpeg_interchange_format; + break; + case TIFFTAG_JPEGIFBYTECOUNT: + *va_arg(ap,uint32*)=(uint32)sp->jpeg_interchange_format_length; + break; + case TIFFTAG_YCBCRSUBSAMPLING: + if (sp->subsamplingcorrect_done==0) + OJPEGSubsamplingCorrect(tif); + *va_arg(ap,uint16*)=(uint16)sp->subsampling_hor; + *va_arg(ap,uint16*)=(uint16)sp->subsampling_ver; + break; + case TIFFTAG_JPEGQTABLES: + *va_arg(ap,uint32*)=(uint32)sp->qtable_offset_count; + *va_arg(ap,void**)=(void*)sp->qtable_offset; + break; + case TIFFTAG_JPEGDCTABLES: + *va_arg(ap,uint32*)=(uint32)sp->dctable_offset_count; + *va_arg(ap,void**)=(void*)sp->dctable_offset; + break; + case TIFFTAG_JPEGACTABLES: + *va_arg(ap,uint32*)=(uint32)sp->actable_offset_count; + *va_arg(ap,void**)=(void*)sp->actable_offset; + break; + case TIFFTAG_JPEGPROC: + *va_arg(ap,uint16*)=(uint16)sp->jpeg_proc; + break; + case TIFFTAG_JPEGRESTARTINTERVAL: + *va_arg(ap,uint16*)=sp->restart_interval; + break; + default: + return (*sp->vgetparent)(tif,tag,ap); + } + return (1); +} + +static int +OJPEGVSetField(TIFF* tif, ttag_t tag, va_list ap) +{ + static const char module[]="OJPEGVSetField"; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + uint32 ma; + uint32* mb; + uint32 n; + switch(tag) + { + case TIFFTAG_JPEGIFOFFSET: + sp->jpeg_interchange_format=(toff_t)va_arg(ap,uint32); + break; + case TIFFTAG_JPEGIFBYTECOUNT: + sp->jpeg_interchange_format_length=(toff_t)va_arg(ap,uint32); + break; + case TIFFTAG_YCBCRSUBSAMPLING: + sp->subsampling_tag=1; + sp->subsampling_hor=(uint8)va_arg(ap,int); + sp->subsampling_ver=(uint8)va_arg(ap,int); + tif->tif_dir.td_ycbcrsubsampling[0]=sp->subsampling_hor; + tif->tif_dir.td_ycbcrsubsampling[1]=sp->subsampling_ver; + break; + case TIFFTAG_JPEGQTABLES: + ma=va_arg(ap,uint32); + if (ma!=0) + { + if (ma>3) + { + TIFFErrorExt(tif->tif_clientdata,module,"JpegQTables tag has incorrect count"); + return(0); + } + sp->qtable_offset_count=(uint8)ma; + mb=va_arg(ap,uint32*); + for (n=0; nqtable_offset[n]=(toff_t)mb[n]; + } + break; + case TIFFTAG_JPEGDCTABLES: + ma=va_arg(ap,uint32); + if (ma!=0) + { + if (ma>3) + { + TIFFErrorExt(tif->tif_clientdata,module,"JpegDcTables tag has incorrect count"); + return(0); + } + sp->dctable_offset_count=(uint8)ma; + mb=va_arg(ap,uint32*); + for (n=0; ndctable_offset[n]=(toff_t)mb[n]; + } + break; + case TIFFTAG_JPEGACTABLES: + ma=va_arg(ap,uint32); + if (ma!=0) + { + if (ma>3) + { + TIFFErrorExt(tif->tif_clientdata,module,"JpegAcTables tag has incorrect count"); + return(0); + } + sp->actable_offset_count=(uint8)ma; + mb=va_arg(ap,uint32*); + for (n=0; nactable_offset[n]=(toff_t)mb[n]; + } + break; + case TIFFTAG_JPEGPROC: + sp->jpeg_proc=(uint8)va_arg(ap,uint32); + break; + case TIFFTAG_JPEGRESTARTINTERVAL: + sp->restart_interval=(uint16)va_arg(ap,uint32); + break; + default: + return (*sp->vsetparent)(tif,tag,ap); + } + TIFFSetFieldBit(tif,_TIFFFieldWithTag(tif,tag)->field_bit); + tif->tif_flags|=TIFF_DIRTYDIRECT; + return(1); +} + +static void +OJPEGPrintDir(TIFF* tif, FILE* fd, long flags) +{ + OJPEGState* sp=(OJPEGState*)tif->tif_data; + uint8 m; + (void)flags; + assert(sp!=NULL); + if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGINTERCHANGEFORMAT)) + fprintf(fd," JpegInterchangeFormat: %lu\n",(unsigned long)sp->jpeg_interchange_format); + if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGINTERCHANGEFORMATLENGTH)) + fprintf(fd," JpegInterchangeFormatLength: %lu\n",(unsigned long)sp->jpeg_interchange_format_length); + if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGQTABLES)) + { + fprintf(fd," JpegQTables:"); + for (m=0; mqtable_offset_count; m++) + fprintf(fd," %lu",(unsigned long)sp->qtable_offset[m]); + fprintf(fd,"\n"); + } + if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGDCTABLES)) + { + fprintf(fd," JpegDcTables:"); + for (m=0; mdctable_offset_count; m++) + fprintf(fd," %lu",(unsigned long)sp->dctable_offset[m]); + fprintf(fd,"\n"); + } + if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGACTABLES)) + { + fprintf(fd," JpegAcTables:"); + for (m=0; mactable_offset_count; m++) + fprintf(fd," %lu",(unsigned long)sp->actable_offset[m]); + fprintf(fd,"\n"); + } + if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGPROC)) + fprintf(fd," JpegProc: %u\n",(unsigned int)sp->jpeg_proc); + if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGRESTARTINTERVAL)) + fprintf(fd," JpegRestartInterval: %u\n",(unsigned int)sp->restart_interval); +} + +static int +OJPEGSetupDecode(TIFF* tif) +{ + static const char module[]="OJPEGSetupDecode"; + TIFFWarningExt(tif->tif_clientdata,module,"Depreciated and troublesome old-style JPEG compression mode, please convert to new-style JPEG compression and notify vendor of writing software"); + return(1); +} + +static int +OJPEGPreDecode(TIFF* tif, tsample_t s) +{ + OJPEGState* sp=(OJPEGState*)tif->tif_data; + tstrile_t m; + if (sp->subsamplingcorrect_done==0) + OJPEGSubsamplingCorrect(tif); + if (sp->readheader_done==0) + { + if (OJPEGReadHeaderInfo(tif)==0) + return(0); + } + if (sp->sos_end[s].log==0) + { + if (OJPEGReadSecondarySos(tif,s)==0) + return(0); + } + if isTiled(tif) + m=(tstrile_t)tif->tif_curtile; + else + m=(tstrile_t)tif->tif_curstrip; + if ((sp->writeheader_done!=0) && ((sp->write_cursample!=s) || (sp->write_curstrile>m))) + { + if (sp->libjpeg_session_active!=0) + OJPEGLibjpegSessionAbort(tif); + sp->writeheader_done=0; + } + if (sp->writeheader_done==0) + { + sp->plane_sample_offset=s; + sp->write_cursample=s; + sp->write_curstrile=s*tif->tif_dir.td_stripsperimage; + if ((sp->in_buffer_file_pos_log==0) || + (sp->in_buffer_file_pos-sp->in_buffer_togo!=sp->sos_end[s].in_buffer_file_pos)) + { + sp->in_buffer_source=sp->sos_end[s].in_buffer_source; + sp->in_buffer_next_strile=sp->sos_end[s].in_buffer_next_strile; + sp->in_buffer_file_pos=sp->sos_end[s].in_buffer_file_pos; + sp->in_buffer_file_pos_log=0; + sp->in_buffer_file_togo=sp->sos_end[s].in_buffer_file_togo; + sp->in_buffer_togo=0; + sp->in_buffer_cur=0; + } + if (OJPEGWriteHeaderInfo(tif)==0) + return(0); + } + while (sp->write_curstrilelibjpeg_jpeg_query_style==0) + { + if (OJPEGPreDecodeSkipRaw(tif)==0) + return(0); + } + else + { + if (OJPEGPreDecodeSkipScanlines(tif)==0) + return(0); + } + sp->write_curstrile++; + } + return(1); +} + +static int +OJPEGPreDecodeSkipRaw(TIFF* tif) +{ + OJPEGState* sp=(OJPEGState*)tif->tif_data; + uint32 m; + m=sp->lines_per_strile; + if (sp->subsampling_convert_state!=0) + { + if (sp->subsampling_convert_clines-sp->subsampling_convert_state>=m) + { + sp->subsampling_convert_state+=m; + if (sp->subsampling_convert_state==sp->subsampling_convert_clines) + sp->subsampling_convert_state=0; + return(1); + } + m-=sp->subsampling_convert_clines-sp->subsampling_convert_state; + sp->subsampling_convert_state=0; + } + while (m>=sp->subsampling_convert_clines) + { + if (jpeg_read_raw_data_encap(sp,&(sp->libjpeg_jpeg_decompress_struct),sp->subsampling_convert_ycbcrimage,sp->subsampling_ver*8)==0) + return(0); + m-=sp->subsampling_convert_clines; + } + if (m>0) + { + if (jpeg_read_raw_data_encap(sp,&(sp->libjpeg_jpeg_decompress_struct),sp->subsampling_convert_ycbcrimage,sp->subsampling_ver*8)==0) + return(0); + sp->subsampling_convert_state=m; + } + return(1); +} + +static int +OJPEGPreDecodeSkipScanlines(TIFF* tif) +{ + static const char module[]="OJPEGPreDecodeSkipScanlines"; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + uint32 m; + if (sp->skip_buffer==NULL) + { + sp->skip_buffer=_TIFFmalloc(sp->bytes_per_line); + if (sp->skip_buffer==NULL) + { + TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); + return(0); + } + } + for (m=0; mlines_per_strile; m++) + { + if (jpeg_read_scanlines_encap(sp,&(sp->libjpeg_jpeg_decompress_struct),&sp->skip_buffer,1)==0) + return(0); + } + return(1); +} + +static int +OJPEGDecode(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s) +{ + OJPEGState* sp=(OJPEGState*)tif->tif_data; + (void)s; + if (sp->libjpeg_jpeg_query_style==0) + { + if (OJPEGDecodeRaw(tif,buf,cc)==0) + return(0); + } + else + { + if (OJPEGDecodeScanlines(tif,buf,cc)==0) + return(0); + } + return(1); +} + +static int +OJPEGDecodeRaw(TIFF* tif, tidata_t buf, tsize_t cc) +{ + static const char module[]="OJPEGDecodeRaw"; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + uint8* m; + uint32 n; + uint8* oy; + uint8* ocb; + uint8* ocr; + uint8* p; + uint32 q; + uint8* r; + uint8 sx,sy; + if (cc%sp->bytes_per_line!=0) + { + TIFFErrorExt(tif->tif_clientdata,module,"Fractional scanline not read"); + return(0); + } + assert(cc>0); + m=buf; + n=cc; + do + { + if (sp->subsampling_convert_state==0) + { + if (jpeg_read_raw_data_encap(sp,&(sp->libjpeg_jpeg_decompress_struct),sp->subsampling_convert_ycbcrimage,sp->subsampling_ver*8)==0) + return(0); + } + oy=sp->subsampling_convert_ybuf+sp->subsampling_convert_state*sp->subsampling_ver*sp->subsampling_convert_ylinelen; + ocb=sp->subsampling_convert_cbbuf+sp->subsampling_convert_state*sp->subsampling_convert_clinelen; + ocr=sp->subsampling_convert_crbuf+sp->subsampling_convert_state*sp->subsampling_convert_clinelen; + p=m; + for (q=0; qsubsampling_convert_clinelenout; q++) + { + r=oy; + for (sy=0; sysubsampling_ver; sy++) + { + for (sx=0; sxsubsampling_hor; sx++) + *p++=*r++; + r+=sp->subsampling_convert_ylinelen-sp->subsampling_hor; + } + oy+=sp->subsampling_hor; + *p++=*ocb++; + *p++=*ocr++; + } + sp->subsampling_convert_state++; + if (sp->subsampling_convert_state==sp->subsampling_convert_clines) + sp->subsampling_convert_state=0; + m+=sp->bytes_per_line; + n-=sp->bytes_per_line; + } while(n>0); + return(1); +} + +static int +OJPEGDecodeScanlines(TIFF* tif, tidata_t buf, tsize_t cc) +{ + static const char module[]="OJPEGDecodeScanlines"; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + uint8* m; + uint32 n; + if (cc%sp->bytes_per_line!=0) + { + TIFFErrorExt(tif->tif_clientdata,module,"Fractional scanline not read"); + return(0); + } + assert(cc>0); + m=buf; + n=cc; + do + { + if (jpeg_read_scanlines_encap(sp,&(sp->libjpeg_jpeg_decompress_struct),&m,1)==0) + return(0); + m+=sp->bytes_per_line; + n-=sp->bytes_per_line; + } while(n>0); + return(1); +} + +static void +OJPEGPostDecode(TIFF* tif, tidata_t buf, tsize_t cc) +{ + OJPEGState* sp=(OJPEGState*)tif->tif_data; + (void)buf; + (void)cc; + sp->write_curstrile++; + if (sp->write_curstrile%tif->tif_dir.td_stripsperimage==0) + { + assert(sp->libjpeg_session_active!=0); + OJPEGLibjpegSessionAbort(tif); + sp->writeheader_done=0; + } +} + +static int +OJPEGSetupEncode(TIFF* tif) +{ + static const char module[]="OJPEGSetupEncode"; + TIFFErrorExt(tif->tif_clientdata,module,"OJPEG encoding not supported; use new-style JPEG compression instead"); + return(0); +} + +static int +OJPEGPreEncode(TIFF* tif, tsample_t s) +{ + static const char module[]="OJPEGPreEncode"; + (void)s; + TIFFErrorExt(tif->tif_clientdata,module,"OJPEG encoding not supported; use new-style JPEG compression instead"); + return(0); +} + +static int +OJPEGEncode(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s) +{ + static const char module[]="OJPEGEncode"; + (void)buf; + (void)cc; + (void)s; + TIFFErrorExt(tif->tif_clientdata,module,"OJPEG encoding not supported; use new-style JPEG compression instead"); + return(0); +} + +static int +OJPEGPostEncode(TIFF* tif) +{ + static const char module[]="OJPEGPostEncode"; + TIFFErrorExt(tif->tif_clientdata,module,"OJPEG encoding not supported; use new-style JPEG compression instead"); + return(0); +} + +static void +OJPEGCleanup(TIFF* tif) +{ + OJPEGState* sp=(OJPEGState*)tif->tif_data; + if (sp!=0) + { + tif->tif_tagmethods.vgetfield=sp->vgetparent; + tif->tif_tagmethods.vsetfield=sp->vsetparent; + if (sp->qtable[0]!=0) + _TIFFfree(sp->qtable[0]); + if (sp->qtable[1]!=0) + _TIFFfree(sp->qtable[1]); + if (sp->qtable[2]!=0) + _TIFFfree(sp->qtable[2]); + if (sp->qtable[3]!=0) + _TIFFfree(sp->qtable[3]); + if (sp->dctable[0]!=0) + _TIFFfree(sp->dctable[0]); + if (sp->dctable[1]!=0) + _TIFFfree(sp->dctable[1]); + if (sp->dctable[2]!=0) + _TIFFfree(sp->dctable[2]); + if (sp->dctable[3]!=0) + _TIFFfree(sp->dctable[3]); + if (sp->actable[0]!=0) + _TIFFfree(sp->actable[0]); + if (sp->actable[1]!=0) + _TIFFfree(sp->actable[1]); + if (sp->actable[2]!=0) + _TIFFfree(sp->actable[2]); + if (sp->actable[3]!=0) + _TIFFfree(sp->actable[3]); + if (sp->libjpeg_session_active!=0) + OJPEGLibjpegSessionAbort(tif); + if (sp->subsampling_convert_ycbcrbuf!=0) + _TIFFfree(sp->subsampling_convert_ycbcrbuf); + if (sp->subsampling_convert_ycbcrimage!=0) + _TIFFfree(sp->subsampling_convert_ycbcrimage); + if (sp->skip_buffer!=0) + _TIFFfree(sp->skip_buffer); + _TIFFfree(sp); + tif->tif_data=NULL; + _TIFFSetDefaultCompressionState(tif); + } +} + +static void +OJPEGSubsamplingCorrect(TIFF* tif) +{ + static const char module[]="OJPEGSubsamplingCorrect"; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + uint8 mh; + uint8 mv; + assert(sp->subsamplingcorrect_done==0); + if ((tif->tif_dir.td_samplesperpixel!=3) || ((tif->tif_dir.td_photometric!=PHOTOMETRIC_YCBCR) && + (tif->tif_dir.td_photometric!=PHOTOMETRIC_ITULAB))) + { + if (sp->subsampling_tag!=0) + TIFFWarningExt(tif->tif_clientdata,module,"Subsampling tag not appropriate for this Photometric and/or SamplesPerPixel"); + sp->subsampling_hor=1; + sp->subsampling_ver=1; + sp->subsampling_force_desubsampling_inside_decompression=0; + } + else + { + sp->subsamplingcorrect_done=1; + mh=sp->subsampling_hor; + mv=sp->subsampling_ver; + sp->subsamplingcorrect=1; + OJPEGReadHeaderInfoSec(tif); + if (sp->subsampling_force_desubsampling_inside_decompression!=0) + { + sp->subsampling_hor=1; + sp->subsampling_ver=1; + } + sp->subsamplingcorrect=0; + if (((sp->subsampling_hor!=mh) || (sp->subsampling_ver!=mv)) && (sp->subsampling_force_desubsampling_inside_decompression==0)) + { + if (sp->subsampling_tag==0) + TIFFWarningExt(tif->tif_clientdata,module,"Subsampling tag is not set, yet subsampling inside JPEG data [%d,%d] does not match default values [2,2]; assuming subsampling inside JPEG data is correct",sp->subsampling_hor,sp->subsampling_ver); + else + TIFFWarningExt(tif->tif_clientdata,module,"Subsampling inside JPEG data [%d,%d] does not match subsampling tag values [%d,%d]; assuming subsampling inside JPEG data is correct",sp->subsampling_hor,sp->subsampling_ver,mh,mv); + } + if (sp->subsampling_force_desubsampling_inside_decompression!=0) + { + if (sp->subsampling_tag==0) + TIFFWarningExt(tif->tif_clientdata,module,"Subsampling tag is not set, yet subsampling inside JPEG data does not match default values [2,2] (nor any other values allowed in TIFF); assuming subsampling inside JPEG data is correct and desubsampling inside JPEG decompression"); + else + TIFFWarningExt(tif->tif_clientdata,module,"Subsampling inside JPEG data does not match subsampling tag values [%d,%d] (nor any other values allowed in TIFF); assuming subsampling inside JPEG data is correct and desubsampling inside JPEG decompression",mh,mv); + } + if (sp->subsampling_force_desubsampling_inside_decompression==0) + { + if (sp->subsampling_horsubsampling_ver) + TIFFWarningExt(tif->tif_clientdata,module,"Subsampling values [%d,%d] are not allowed in TIFF",sp->subsampling_hor,sp->subsampling_ver); + } + } + sp->subsamplingcorrect_done=1; +} + +static int +OJPEGReadHeaderInfo(TIFF* tif) +{ + static const char module[]="OJPEGReadHeaderInfo"; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + assert(sp->readheader_done==0); + sp->image_width=tif->tif_dir.td_imagewidth; + sp->image_length=tif->tif_dir.td_imagelength; + if isTiled(tif) + { + sp->strile_width=tif->tif_dir.td_tilewidth; + sp->strile_length=tif->tif_dir.td_tilelength; + sp->strile_length_total=((sp->image_length+sp->strile_length-1)/sp->strile_length)*sp->strile_length; + } + else + { + sp->strile_width=sp->image_width; + sp->strile_length=tif->tif_dir.td_rowsperstrip; + sp->strile_length_total=sp->image_length; + } + sp->samples_per_pixel=tif->tif_dir.td_samplesperpixel; + if (sp->samples_per_pixel==1) + { + sp->plane_sample_offset=0; + sp->samples_per_pixel_per_plane=sp->samples_per_pixel; + sp->subsampling_hor=1; + sp->subsampling_ver=1; + } + else + { + if (sp->samples_per_pixel!=3) + { + TIFFErrorExt(tif->tif_clientdata,module,"SamplesPerPixel %d not supported for this compression scheme",sp->samples_per_pixel); + return(0); + } + sp->plane_sample_offset=0; + if (tif->tif_dir.td_planarconfig==PLANARCONFIG_CONTIG) + sp->samples_per_pixel_per_plane=3; + else + sp->samples_per_pixel_per_plane=1; + } + if (sp->strile_lengthimage_length) + { + if (sp->strile_length%(sp->subsampling_ver*8)!=0) + { + TIFFErrorExt(tif->tif_clientdata,module,"Incompatible vertical subsampling and image strip/tile length"); + return(0); + } + sp->restart_interval=((sp->strile_width+sp->subsampling_hor*8-1)/(sp->subsampling_hor*8))*(sp->strile_length/(sp->subsampling_ver*8)); + } + if (OJPEGReadHeaderInfoSec(tif)==0) + return(0); + sp->sos_end[0].log=1; + sp->sos_end[0].in_buffer_source=sp->in_buffer_source; + sp->sos_end[0].in_buffer_next_strile=sp->in_buffer_next_strile; + sp->sos_end[0].in_buffer_file_pos=sp->in_buffer_file_pos-sp->in_buffer_togo; + sp->sos_end[0].in_buffer_file_togo=sp->in_buffer_file_togo+sp->in_buffer_togo; + sp->readheader_done=1; + return(1); +} + +static int +OJPEGReadSecondarySos(TIFF* tif, tsample_t s) +{ + OJPEGState* sp=(OJPEGState*)tif->tif_data; + uint8 m; + assert(s>0); + assert(s<3); + assert(sp->sos_end[0].log!=0); + assert(sp->sos_end[s].log==0); + sp->plane_sample_offset=s-1; + while(sp->sos_end[sp->plane_sample_offset].log==0) + sp->plane_sample_offset--; + sp->in_buffer_source=sp->sos_end[sp->plane_sample_offset].in_buffer_source; + sp->in_buffer_next_strile=sp->sos_end[sp->plane_sample_offset].in_buffer_next_strile; + sp->in_buffer_file_pos=sp->sos_end[sp->plane_sample_offset].in_buffer_file_pos; + sp->in_buffer_file_pos_log=0; + sp->in_buffer_file_togo=sp->sos_end[sp->plane_sample_offset].in_buffer_file_togo; + sp->in_buffer_togo=0; + sp->in_buffer_cur=0; + while(sp->plane_sample_offsetplane_sample_offset++; + if (OJPEGReadHeaderInfoSecStreamSos(tif)==0) + return(0); + sp->sos_end[sp->plane_sample_offset].log=1; + sp->sos_end[sp->plane_sample_offset].in_buffer_source=sp->in_buffer_source; + sp->sos_end[sp->plane_sample_offset].in_buffer_next_strile=sp->in_buffer_next_strile; + sp->sos_end[sp->plane_sample_offset].in_buffer_file_pos=sp->in_buffer_file_pos-sp->in_buffer_togo; + sp->sos_end[sp->plane_sample_offset].in_buffer_file_togo=sp->in_buffer_file_togo+sp->in_buffer_togo; + } + return(1); +} + +static int +OJPEGWriteHeaderInfo(TIFF* tif) +{ + static const char module[]="OJPEGWriteHeaderInfo"; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + uint8** m; + uint32 n; + assert(sp->libjpeg_session_active==0); + sp->out_state=ososSoi; + sp->restart_index=0; + jpeg_std_error(&(sp->libjpeg_jpeg_error_mgr)); + sp->libjpeg_jpeg_error_mgr.output_message=OJPEGLibjpegJpegErrorMgrOutputMessage; + sp->libjpeg_jpeg_error_mgr.error_exit=OJPEGLibjpegJpegErrorMgrErrorExit; + sp->libjpeg_jpeg_decompress_struct.err=&(sp->libjpeg_jpeg_error_mgr); + sp->libjpeg_jpeg_decompress_struct.client_data=(void*)tif; + if (jpeg_create_decompress_encap(sp,&(sp->libjpeg_jpeg_decompress_struct))==0) + return(0); + sp->libjpeg_session_active=1; + sp->libjpeg_jpeg_source_mgr.bytes_in_buffer=0; + sp->libjpeg_jpeg_source_mgr.init_source=OJPEGLibjpegJpegSourceMgrInitSource; + sp->libjpeg_jpeg_source_mgr.fill_input_buffer=OJPEGLibjpegJpegSourceMgrFillInputBuffer; + sp->libjpeg_jpeg_source_mgr.skip_input_data=OJPEGLibjpegJpegSourceMgrSkipInputData; + sp->libjpeg_jpeg_source_mgr.resync_to_restart=OJPEGLibjpegJpegSourceMgrResyncToRestart; + sp->libjpeg_jpeg_source_mgr.term_source=OJPEGLibjpegJpegSourceMgrTermSource; + sp->libjpeg_jpeg_decompress_struct.src=&(sp->libjpeg_jpeg_source_mgr); + if (jpeg_read_header_encap(sp,&(sp->libjpeg_jpeg_decompress_struct),1)==0) + return(0); + if ((sp->subsampling_force_desubsampling_inside_decompression==0) && (sp->samples_per_pixel_per_plane>1)) + { + sp->libjpeg_jpeg_decompress_struct.raw_data_out=1; +#if JPEG_LIB_VERSION >= 70 + sp->libjpeg_jpeg_decompress_struct.do_fancy_upsampling=FALSE; +#endif + sp->libjpeg_jpeg_query_style=0; + if (sp->subsampling_convert_log==0) + { + assert(sp->subsampling_convert_ycbcrbuf==0); + assert(sp->subsampling_convert_ycbcrimage==0); + sp->subsampling_convert_ylinelen=((sp->strile_width+sp->subsampling_hor*8-1)/(sp->subsampling_hor*8)*sp->subsampling_hor*8); + sp->subsampling_convert_ylines=sp->subsampling_ver*8; + sp->subsampling_convert_clinelen=sp->subsampling_convert_ylinelen/sp->subsampling_hor; + sp->subsampling_convert_clines=8; + sp->subsampling_convert_ybuflen=sp->subsampling_convert_ylinelen*sp->subsampling_convert_ylines; + sp->subsampling_convert_cbuflen=sp->subsampling_convert_clinelen*sp->subsampling_convert_clines; + sp->subsampling_convert_ycbcrbuflen=sp->subsampling_convert_ybuflen+2*sp->subsampling_convert_cbuflen; + sp->subsampling_convert_ycbcrbuf=_TIFFmalloc(sp->subsampling_convert_ycbcrbuflen); + if (sp->subsampling_convert_ycbcrbuf==0) + { + TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); + return(0); + } + sp->subsampling_convert_ybuf=sp->subsampling_convert_ycbcrbuf; + sp->subsampling_convert_cbbuf=sp->subsampling_convert_ybuf+sp->subsampling_convert_ybuflen; + sp->subsampling_convert_crbuf=sp->subsampling_convert_cbbuf+sp->subsampling_convert_cbuflen; + sp->subsampling_convert_ycbcrimagelen=3+sp->subsampling_convert_ylines+2*sp->subsampling_convert_clines; + sp->subsampling_convert_ycbcrimage=_TIFFmalloc(sp->subsampling_convert_ycbcrimagelen*sizeof(uint8*)); + if (sp->subsampling_convert_ycbcrimage==0) + { + TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); + return(0); + } + m=sp->subsampling_convert_ycbcrimage; + *m++=(uint8*)(sp->subsampling_convert_ycbcrimage+3); + *m++=(uint8*)(sp->subsampling_convert_ycbcrimage+3+sp->subsampling_convert_ylines); + *m++=(uint8*)(sp->subsampling_convert_ycbcrimage+3+sp->subsampling_convert_ylines+sp->subsampling_convert_clines); + for (n=0; nsubsampling_convert_ylines; n++) + *m++=sp->subsampling_convert_ybuf+n*sp->subsampling_convert_ylinelen; + for (n=0; nsubsampling_convert_clines; n++) + *m++=sp->subsampling_convert_cbbuf+n*sp->subsampling_convert_clinelen; + for (n=0; nsubsampling_convert_clines; n++) + *m++=sp->subsampling_convert_crbuf+n*sp->subsampling_convert_clinelen; + sp->subsampling_convert_clinelenout=((sp->strile_width+sp->subsampling_hor-1)/sp->subsampling_hor); + sp->subsampling_convert_state=0; + sp->bytes_per_line=sp->subsampling_convert_clinelenout*(sp->subsampling_ver*sp->subsampling_hor+2); + sp->lines_per_strile=((sp->strile_length+sp->subsampling_ver-1)/sp->subsampling_ver); + sp->subsampling_convert_log=1; + } + } + else + { + sp->libjpeg_jpeg_decompress_struct.jpeg_color_space=JCS_UNKNOWN; + sp->libjpeg_jpeg_decompress_struct.out_color_space=JCS_UNKNOWN; + sp->libjpeg_jpeg_query_style=1; + sp->bytes_per_line=sp->samples_per_pixel_per_plane*sp->strile_width; + sp->lines_per_strile=sp->strile_length; + } + if (jpeg_start_decompress_encap(sp,&(sp->libjpeg_jpeg_decompress_struct))==0) + return(0); + sp->writeheader_done=1; + return(1); +} + +static void +OJPEGLibjpegSessionAbort(TIFF* tif) +{ + OJPEGState* sp=(OJPEGState*)tif->tif_data; + assert(sp->libjpeg_session_active!=0); + jpeg_destroy((jpeg_common_struct*)(&(sp->libjpeg_jpeg_decompress_struct))); + sp->libjpeg_session_active=0; +} + +static int +OJPEGReadHeaderInfoSec(TIFF* tif) +{ + static const char module[]="OJPEGReadHeaderInfoSec"; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + uint8 m; + uint16 n; + uint8 o; + if (sp->file_size==0) + sp->file_size=TIFFGetFileSize(tif); + if (sp->jpeg_interchange_format!=0) + { + if (sp->jpeg_interchange_format>=sp->file_size) + { + sp->jpeg_interchange_format=0; + sp->jpeg_interchange_format_length=0; + } + else + { + if ((sp->jpeg_interchange_format_length==0) || (sp->jpeg_interchange_format+sp->jpeg_interchange_format_length>sp->file_size)) + sp->jpeg_interchange_format_length=sp->file_size-sp->jpeg_interchange_format; + } + } + sp->in_buffer_source=osibsNotSetYet; + sp->in_buffer_next_strile=0; + sp->in_buffer_strile_count=tif->tif_dir.td_nstrips; + sp->in_buffer_file_togo=0; + sp->in_buffer_togo=0; + do + { + if (OJPEGReadBytePeek(sp,&m)==0) + return(0); + if (m!=255) + break; + OJPEGReadByteAdvance(sp); + do + { + if (OJPEGReadByte(sp,&m)==0) + return(0); + } while(m==255); + switch(m) + { + case JPEG_MARKER_SOI: + /* this type of marker has no data, and should be skipped */ + break; + case JPEG_MARKER_COM: + case JPEG_MARKER_APP0: + case JPEG_MARKER_APP0+1: + case JPEG_MARKER_APP0+2: + case JPEG_MARKER_APP0+3: + case JPEG_MARKER_APP0+4: + case JPEG_MARKER_APP0+5: + case JPEG_MARKER_APP0+6: + case JPEG_MARKER_APP0+7: + case JPEG_MARKER_APP0+8: + case JPEG_MARKER_APP0+9: + case JPEG_MARKER_APP0+10: + case JPEG_MARKER_APP0+11: + case JPEG_MARKER_APP0+12: + case JPEG_MARKER_APP0+13: + case JPEG_MARKER_APP0+14: + case JPEG_MARKER_APP0+15: + /* this type of marker has data, but it has no use to us (and no place here) and should be skipped */ + if (OJPEGReadWord(sp,&n)==0) + return(0); + if (n<2) + { + if (sp->subsamplingcorrect==0) + TIFFErrorExt(tif->tif_clientdata,module,"Corrupt JPEG data"); + return(0); + } + if (n>2) + OJPEGReadSkip(sp,n-2); + break; + case JPEG_MARKER_DRI: + if (OJPEGReadHeaderInfoSecStreamDri(tif)==0) + return(0); + break; + case JPEG_MARKER_DQT: + if (OJPEGReadHeaderInfoSecStreamDqt(tif)==0) + return(0); + break; + case JPEG_MARKER_DHT: + if (OJPEGReadHeaderInfoSecStreamDht(tif)==0) + return(0); + break; + case JPEG_MARKER_SOF0: + case JPEG_MARKER_SOF1: + case JPEG_MARKER_SOF3: + if (OJPEGReadHeaderInfoSecStreamSof(tif,m)==0) + return(0); + if (sp->subsamplingcorrect!=0) + return(1); + break; + case JPEG_MARKER_SOS: + if (sp->subsamplingcorrect!=0) + return(1); + assert(sp->plane_sample_offset==0); + if (OJPEGReadHeaderInfoSecStreamSos(tif)==0) + return(0); + break; + default: + TIFFErrorExt(tif->tif_clientdata,module,"Unknown marker type %d in JPEG data",m); + return(0); + } + } while(m!=JPEG_MARKER_SOS); + if (sp->subsamplingcorrect) + return(1); + if (sp->sof_log==0) + { + if (OJPEGReadHeaderInfoSecTablesQTable(tif)==0) + return(0); + sp->sof_marker_id=JPEG_MARKER_SOF0; + for (o=0; osamples_per_pixel; o++) + sp->sof_c[o]=o; + sp->sof_hv[0]=((sp->subsampling_hor<<4)|sp->subsampling_ver); + for (o=1; osamples_per_pixel; o++) + sp->sof_hv[o]=17; + sp->sof_x=sp->strile_width; + sp->sof_y=sp->strile_length_total; + sp->sof_log=1; + if (OJPEGReadHeaderInfoSecTablesDcTable(tif)==0) + return(0); + if (OJPEGReadHeaderInfoSecTablesAcTable(tif)==0) + return(0); + for (o=1; osamples_per_pixel; o++) + sp->sos_cs[o]=o; + } + return(1); +} + +static int +OJPEGReadHeaderInfoSecStreamDri(TIFF* tif) +{ + /* this could easilly cause trouble in some cases... but no such cases have occured sofar */ + static const char module[]="OJPEGReadHeaderInfoSecStreamDri"; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + uint16 m; + if (OJPEGReadWord(sp,&m)==0) + return(0); + if (m!=4) + { + TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DRI marker in JPEG data"); + return(0); + } + if (OJPEGReadWord(sp,&m)==0) + return(0); + sp->restart_interval=m; + return(1); +} + +static int +OJPEGReadHeaderInfoSecStreamDqt(TIFF* tif) +{ + /* this is a table marker, and it is to be saved as a whole for exact pushing on the jpeg stream later on */ + static const char module[]="OJPEGReadHeaderInfoSecStreamDqt"; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + uint16 m; + uint32 na; + uint8* nb; + uint8 o; + if (OJPEGReadWord(sp,&m)==0) + return(0); + if (m<=2) + { + if (sp->subsamplingcorrect==0) + TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DQT marker in JPEG data"); + return(0); + } + if (sp->subsamplingcorrect!=0) + OJPEGReadSkip(sp,m-2); + else + { + m-=2; + do + { + if (m<65) + { + TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DQT marker in JPEG data"); + return(0); + } + na=sizeof(uint32)+69; + nb=_TIFFmalloc(na); + if (nb==0) + { + TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); + return(0); + } + *(uint32*)nb=na; + nb[sizeof(uint32)]=255; + nb[sizeof(uint32)+1]=JPEG_MARKER_DQT; + nb[sizeof(uint32)+2]=0; + nb[sizeof(uint32)+3]=67; + if (OJPEGReadBlock(sp,65,&nb[sizeof(uint32)+4])==0) + return(0); + o=nb[sizeof(uint32)+4]&15; + if (3tif_clientdata,module,"Corrupt DQT marker in JPEG data"); + return(0); + } + if (sp->qtable[o]!=0) + _TIFFfree(sp->qtable[o]); + sp->qtable[o]=nb; + m-=65; + } while(m>0); + } + return(1); +} + +static int +OJPEGReadHeaderInfoSecStreamDht(TIFF* tif) +{ + /* this is a table marker, and it is to be saved as a whole for exact pushing on the jpeg stream later on */ + /* TODO: the following assumes there is only one table in this marker... but i'm not quite sure that assumption is guaranteed correct */ + static const char module[]="OJPEGReadHeaderInfoSecStreamDht"; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + uint16 m; + uint32 na; + uint8* nb; + uint8 o; + if (OJPEGReadWord(sp,&m)==0) + return(0); + if (m<=2) + { + if (sp->subsamplingcorrect==0) + TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DHT marker in JPEG data"); + return(0); + } + if (sp->subsamplingcorrect!=0) + { + OJPEGReadSkip(sp,m-2); + } + else + { + na=sizeof(uint32)+2+m; + nb=_TIFFmalloc(na); + if (nb==0) + { + TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); + return(0); + } + *(uint32*)nb=na; + nb[sizeof(uint32)]=255; + nb[sizeof(uint32)+1]=JPEG_MARKER_DHT; + nb[sizeof(uint32)+2]=(m>>8); + nb[sizeof(uint32)+3]=(m&255); + if (OJPEGReadBlock(sp,m-2,&nb[sizeof(uint32)+4])==0) + return(0); + o=nb[sizeof(uint32)+4]; + if ((o&240)==0) + { + if (3tif_clientdata,module,"Corrupt DHT marker in JPEG data"); + return(0); + } + if (sp->dctable[o]!=0) + _TIFFfree(sp->dctable[o]); + sp->dctable[o]=nb; + } + else + { + if ((o&240)!=16) + { + TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DHT marker in JPEG data"); + return(0); + } + o&=15; + if (3tif_clientdata,module,"Corrupt DHT marker in JPEG data"); + return(0); + } + if (sp->actable[o]!=0) + _TIFFfree(sp->actable[o]); + sp->actable[o]=nb; + } + } + return(1); +} + +static int +OJPEGReadHeaderInfoSecStreamSof(TIFF* tif, uint8 marker_id) +{ + /* this marker needs to be checked, and part of its data needs to be saved for regeneration later on */ + static const char module[]="OJPEGReadHeaderInfoSecStreamSof"; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + uint16 m; + uint16 n; + uint8 o; + uint16 p; + uint16 q; + if (sp->sof_log!=0) + { + TIFFErrorExt(tif->tif_clientdata,module,"Corrupt JPEG data"); + return(0); + } + if (sp->subsamplingcorrect==0) + sp->sof_marker_id=marker_id; + /* Lf: data length */ + if (OJPEGReadWord(sp,&m)==0) + return(0); + if (m<11) + { + if (sp->subsamplingcorrect==0) + TIFFErrorExt(tif->tif_clientdata,module,"Corrupt SOF marker in JPEG data"); + return(0); + } + m-=8; + if (m%3!=0) + { + if (sp->subsamplingcorrect==0) + TIFFErrorExt(tif->tif_clientdata,module,"Corrupt SOF marker in JPEG data"); + return(0); + } + n=m/3; + if (sp->subsamplingcorrect==0) + { + if (n!=sp->samples_per_pixel) + { + TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data indicates unexpected number of samples"); + return(0); + } + } + /* P: Sample precision */ + if (OJPEGReadByte(sp,&o)==0) + return(0); + if (o!=8) + { + if (sp->subsamplingcorrect==0) + TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data indicates unexpected number of bits per sample"); + return(0); + } + /* Y: Number of lines, X: Number of samples per line */ + if (sp->subsamplingcorrect) + OJPEGReadSkip(sp,4); + else + { + /* TODO: probably best to also add check on allowed upper bound, especially x, may cause buffer overflow otherwise i think */ + /* Y: Number of lines */ + if (OJPEGReadWord(sp,&p)==0) + return(0); + if ((pimage_length) && (pstrile_length_total)) + { + TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data indicates unexpected height"); + return(0); + } + sp->sof_y=p; + /* X: Number of samples per line */ + if (OJPEGReadWord(sp,&p)==0) + return(0); + if ((pimage_width) && (pstrile_width)) + { + TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data indicates unexpected width"); + return(0); + } + sp->sof_x=p; + } + /* Nf: Number of image components in frame */ + if (OJPEGReadByte(sp,&o)==0) + return(0); + if (o!=n) + { + if (sp->subsamplingcorrect==0) + TIFFErrorExt(tif->tif_clientdata,module,"Corrupt SOF marker in JPEG data"); + return(0); + } + /* per component stuff */ + /* TODO: double-check that flow implies that n cannot be as big as to make us overflow sof_c, sof_hv and sof_tq arrays */ + for (q=0; qsubsamplingcorrect==0) + sp->sof_c[q]=o; + /* H: Horizontal sampling factor, and V: Vertical sampling factor */ + if (OJPEGReadByte(sp,&o)==0) + return(0); + if (sp->subsamplingcorrect!=0) + { + if (q==0) + { + sp->subsampling_hor=(o>>4); + sp->subsampling_ver=(o&15); + if (((sp->subsampling_hor!=1) && (sp->subsampling_hor!=2) && (sp->subsampling_hor!=4)) || + ((sp->subsampling_ver!=1) && (sp->subsampling_ver!=2) && (sp->subsampling_ver!=4))) + sp->subsampling_force_desubsampling_inside_decompression=1; + } + else + { + if (o!=17) + sp->subsampling_force_desubsampling_inside_decompression=1; + } + } + else + { + sp->sof_hv[q]=o; + if (sp->subsampling_force_desubsampling_inside_decompression==0) + { + if (q==0) + { + if (o!=((sp->subsampling_hor<<4)|sp->subsampling_ver)) + { + TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data indicates unexpected subsampling values"); + return(0); + } + } + else + { + if (o!=17) + { + TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data indicates unexpected subsampling values"); + return(0); + } + } + } + } + /* Tq: Quantization table destination selector */ + if (OJPEGReadByte(sp,&o)==0) + return(0); + if (sp->subsamplingcorrect==0) + sp->sof_tq[q]=o; + } + if (sp->subsamplingcorrect==0) + sp->sof_log=1; + return(1); +} + +static int +OJPEGReadHeaderInfoSecStreamSos(TIFF* tif) +{ + /* this marker needs to be checked, and part of its data needs to be saved for regeneration later on */ + static const char module[]="OJPEGReadHeaderInfoSecStreamSos"; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + uint16 m; + uint8 n; + uint8 o; + assert(sp->subsamplingcorrect==0); + if (sp->sof_log==0) + { + TIFFErrorExt(tif->tif_clientdata,module,"Corrupt SOS marker in JPEG data"); + return(0); + } + /* Ls */ + if (OJPEGReadWord(sp,&m)==0) + return(0); + if (m!=6+sp->samples_per_pixel_per_plane*2) + { + TIFFErrorExt(tif->tif_clientdata,module,"Corrupt SOS marker in JPEG data"); + return(0); + } + /* Ns */ + if (OJPEGReadByte(sp,&n)==0) + return(0); + if (n!=sp->samples_per_pixel_per_plane) + { + TIFFErrorExt(tif->tif_clientdata,module,"Corrupt SOS marker in JPEG data"); + return(0); + } + /* Cs, Td, and Ta */ + for (o=0; osamples_per_pixel_per_plane; o++) + { + /* Cs */ + if (OJPEGReadByte(sp,&n)==0) + return(0); + sp->sos_cs[sp->plane_sample_offset+o]=n; + /* Td and Ta */ + if (OJPEGReadByte(sp,&n)==0) + return(0); + sp->sos_tda[sp->plane_sample_offset+o]=n; + } + /* skip Ss, Se, Ah, en Al -> no check, as per Tom Lane recommendation, as per LibJpeg source */ + OJPEGReadSkip(sp,3); + return(1); +} + +static int +OJPEGReadHeaderInfoSecTablesQTable(TIFF* tif) +{ + static const char module[]="OJPEGReadHeaderInfoSecTablesQTable"; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + uint8 m; + uint8 n; + uint32 oa; + uint8* ob; + uint32 p; + if (sp->qtable_offset[0]==0) + { + TIFFErrorExt(tif->tif_clientdata,module,"Missing JPEG tables"); + return(0); + } + sp->in_buffer_file_pos_log=0; + for (m=0; msamples_per_pixel; m++) + { + if ((sp->qtable_offset[m]!=0) && ((m==0) || (sp->qtable_offset[m]!=sp->qtable_offset[m-1]))) + { + for (n=0; nqtable_offset[m]==sp->qtable_offset[n]) + { + TIFFErrorExt(tif->tif_clientdata,module,"Corrupt JpegQTables tag value"); + return(0); + } + } + oa=sizeof(uint32)+69; + ob=_TIFFmalloc(oa); + if (ob==0) + { + TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); + return(0); + } + *(uint32*)ob=oa; + ob[sizeof(uint32)]=255; + ob[sizeof(uint32)+1]=JPEG_MARKER_DQT; + ob[sizeof(uint32)+2]=0; + ob[sizeof(uint32)+3]=67; + ob[sizeof(uint32)+4]=m; + TIFFSeekFile(tif,sp->qtable_offset[m],SEEK_SET); + p=TIFFReadFile(tif,&ob[sizeof(uint32)+5],64); + if (p!=64) + return(0); + sp->qtable[m]=ob; + sp->sof_tq[m]=m; + } + else + sp->sof_tq[m]=sp->sof_tq[m-1]; + } + return(1); +} + +static int +OJPEGReadHeaderInfoSecTablesDcTable(TIFF* tif) +{ + static const char module[]="OJPEGReadHeaderInfoSecTablesDcTable"; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + uint8 m; + uint8 n; + uint8 o[16]; + uint32 p; + uint32 q; + uint32 ra; + uint8* rb; + if (sp->dctable_offset[0]==0) + { + TIFFErrorExt(tif->tif_clientdata,module,"Missing JPEG tables"); + return(0); + } + sp->in_buffer_file_pos_log=0; + for (m=0; msamples_per_pixel; m++) + { + if ((sp->dctable_offset[m]!=0) && ((m==0) || (sp->dctable_offset[m]!=sp->dctable_offset[m-1]))) + { + for (n=0; ndctable_offset[m]==sp->dctable_offset[n]) + { + TIFFErrorExt(tif->tif_clientdata,module,"Corrupt JpegDcTables tag value"); + return(0); + } + } + TIFFSeekFile(tif,sp->dctable_offset[m],SEEK_SET); + p=TIFFReadFile(tif,o,16); + if (p!=16) + return(0); + q=0; + for (n=0; n<16; n++) + q+=o[n]; + ra=sizeof(uint32)+21+q; + rb=_TIFFmalloc(ra); + if (rb==0) + { + TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); + return(0); + } + *(uint32*)rb=ra; + rb[sizeof(uint32)]=255; + rb[sizeof(uint32)+1]=JPEG_MARKER_DHT; + rb[sizeof(uint32)+2]=((19+q)>>8); + rb[sizeof(uint32)+3]=((19+q)&255); + rb[sizeof(uint32)+4]=m; + for (n=0; n<16; n++) + rb[sizeof(uint32)+5+n]=o[n]; + p=TIFFReadFile(tif,&(rb[sizeof(uint32)+21]),q); + if (p!=q) + return(0); + sp->dctable[m]=rb; + sp->sos_tda[m]=(m<<4); + } + else + sp->sos_tda[m]=sp->sos_tda[m-1]; + } + return(1); +} + +static int +OJPEGReadHeaderInfoSecTablesAcTable(TIFF* tif) +{ + static const char module[]="OJPEGReadHeaderInfoSecTablesAcTable"; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + uint8 m; + uint8 n; + uint8 o[16]; + uint32 p; + uint32 q; + uint32 ra; + uint8* rb; + if (sp->actable_offset[0]==0) + { + TIFFErrorExt(tif->tif_clientdata,module,"Missing JPEG tables"); + return(0); + } + sp->in_buffer_file_pos_log=0; + for (m=0; msamples_per_pixel; m++) + { + if ((sp->actable_offset[m]!=0) && ((m==0) || (sp->actable_offset[m]!=sp->actable_offset[m-1]))) + { + for (n=0; nactable_offset[m]==sp->actable_offset[n]) + { + TIFFErrorExt(tif->tif_clientdata,module,"Corrupt JpegAcTables tag value"); + return(0); + } + } + TIFFSeekFile(tif,sp->actable_offset[m],SEEK_SET); + p=TIFFReadFile(tif,o,16); + if (p!=16) + return(0); + q=0; + for (n=0; n<16; n++) + q+=o[n]; + ra=sizeof(uint32)+21+q; + rb=_TIFFmalloc(ra); + if (rb==0) + { + TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); + return(0); + } + *(uint32*)rb=ra; + rb[sizeof(uint32)]=255; + rb[sizeof(uint32)+1]=JPEG_MARKER_DHT; + rb[sizeof(uint32)+2]=((19+q)>>8); + rb[sizeof(uint32)+3]=((19+q)&255); + rb[sizeof(uint32)+4]=(16|m); + for (n=0; n<16; n++) + rb[sizeof(uint32)+5+n]=o[n]; + p=TIFFReadFile(tif,&(rb[sizeof(uint32)+21]),q); + if (p!=q) + return(0); + sp->actable[m]=rb; + sp->sos_tda[m]=(sp->sos_tda[m]|m); + } + else + sp->sos_tda[m]=(sp->sos_tda[m]|(sp->sos_tda[m-1]&15)); + } + return(1); +} + +static int +OJPEGReadBufferFill(OJPEGState* sp) +{ + uint16 m; + tsize_t n; + /* TODO: double-check: when subsamplingcorrect is set, no call to TIFFErrorExt or TIFFWarningExt should be made + * in any other case, seek or read errors should be passed through */ + do + { + if (sp->in_buffer_file_togo!=0) + { + if (sp->in_buffer_file_pos_log==0) + { + TIFFSeekFile(sp->tif,sp->in_buffer_file_pos,SEEK_SET); + sp->in_buffer_file_pos_log=1; + } + m=OJPEG_BUFFER; + if (m>sp->in_buffer_file_togo) + m=(uint16)sp->in_buffer_file_togo; + n=TIFFReadFile(sp->tif,sp->in_buffer,(tsize_t)m); + if (n==0) + return(0); + assert(n>0); + assert(n<=OJPEG_BUFFER); + assert(n<65536); + assert((uint16)n<=sp->in_buffer_file_togo); + m=(uint16)n; + sp->in_buffer_togo=m; + sp->in_buffer_cur=sp->in_buffer; + sp->in_buffer_file_togo-=m; + sp->in_buffer_file_pos+=m; + break; + } + sp->in_buffer_file_pos_log=0; + switch(sp->in_buffer_source) + { + case osibsNotSetYet: + if (sp->jpeg_interchange_format!=0) + { + sp->in_buffer_file_pos=sp->jpeg_interchange_format; + sp->in_buffer_file_togo=sp->jpeg_interchange_format_length; + } + sp->in_buffer_source=osibsJpegInterchangeFormat; + break; + case osibsJpegInterchangeFormat: + sp->in_buffer_source=osibsStrile; + case osibsStrile: + if (sp->in_buffer_next_strile==sp->in_buffer_strile_count) + sp->in_buffer_source=osibsEof; + else + { + if (sp->tif->tif_dir.td_stripoffset == 0) { + TIFFErrorExt(sp->tif->tif_clientdata,sp->tif->tif_name,"Strip offsets are missing"); + return(0); + } + sp->in_buffer_file_pos=sp->tif->tif_dir.td_stripoffset[sp->in_buffer_next_strile]; + if (sp->in_buffer_file_pos!=0) + { + if (sp->in_buffer_file_pos>=sp->file_size) + sp->in_buffer_file_pos=0; + else + { + sp->in_buffer_file_togo=sp->tif->tif_dir.td_stripbytecount[sp->in_buffer_next_strile]; + if (sp->in_buffer_file_togo==0) + sp->in_buffer_file_pos=0; + else if (sp->in_buffer_file_pos+sp->in_buffer_file_togo>sp->file_size) + sp->in_buffer_file_togo=sp->file_size-sp->in_buffer_file_pos; + } + } + sp->in_buffer_next_strile++; + } + break; + default: + return(0); + } + } while (1); + return(1); +} + +static int +OJPEGReadByte(OJPEGState* sp, uint8* byte) +{ + if (sp->in_buffer_togo==0) + { + if (OJPEGReadBufferFill(sp)==0) + return(0); + assert(sp->in_buffer_togo>0); + } + *byte=*(sp->in_buffer_cur); + sp->in_buffer_cur++; + sp->in_buffer_togo--; + return(1); +} + +static int +OJPEGReadBytePeek(OJPEGState* sp, uint8* byte) +{ + if (sp->in_buffer_togo==0) + { + if (OJPEGReadBufferFill(sp)==0) + return(0); + assert(sp->in_buffer_togo>0); + } + *byte=*(sp->in_buffer_cur); + return(1); +} + +static void +OJPEGReadByteAdvance(OJPEGState* sp) +{ + assert(sp->in_buffer_togo>0); + sp->in_buffer_cur++; + sp->in_buffer_togo--; +} + +static int +OJPEGReadWord(OJPEGState* sp, uint16* word) +{ + uint8 m; + if (OJPEGReadByte(sp,&m)==0) + return(0); + *word=(m<<8); + if (OJPEGReadByte(sp,&m)==0) + return(0); + *word|=m; + return(1); +} + +static int +OJPEGReadBlock(OJPEGState* sp, uint16 len, void* mem) +{ + uint16 mlen; + uint8* mmem; + uint16 n; + assert(len>0); + mlen=len; + mmem=mem; + do + { + if (sp->in_buffer_togo==0) + { + if (OJPEGReadBufferFill(sp)==0) + return(0); + assert(sp->in_buffer_togo>0); + } + n=mlen; + if (n>sp->in_buffer_togo) + n=sp->in_buffer_togo; + _TIFFmemcpy(mmem,sp->in_buffer_cur,n); + sp->in_buffer_cur+=n; + sp->in_buffer_togo-=n; + mlen-=n; + mmem+=n; + } while(mlen>0); + return(1); +} + +static void +OJPEGReadSkip(OJPEGState* sp, uint16 len) +{ + uint16 m; + uint16 n; + m=len; + n=m; + if (n>sp->in_buffer_togo) + n=sp->in_buffer_togo; + sp->in_buffer_cur+=n; + sp->in_buffer_togo-=n; + m-=n; + if (m>0) + { + assert(sp->in_buffer_togo==0); + n=m; + if (n>sp->in_buffer_file_togo) + n=sp->in_buffer_file_togo; + sp->in_buffer_file_pos+=n; + sp->in_buffer_file_togo-=n; + sp->in_buffer_file_pos_log=0; + /* we don't skip past jpeginterchangeformat/strile block... + * if that is asked from us, we're dealing with totally bazurk + * data anyway, and we've not seen this happening on any + * testfile, so we might as well likely cause some other + * meaningless error to be passed at some later time + */ + } +} + +static int +OJPEGWriteStream(TIFF* tif, void** mem, uint32* len) +{ + OJPEGState* sp=(OJPEGState*)tif->tif_data; + *len=0; + do + { + assert(sp->out_state<=ososEoi); + switch(sp->out_state) + { + case ososSoi: + OJPEGWriteStreamSoi(tif,mem,len); + break; + case ososQTable0: + OJPEGWriteStreamQTable(tif,0,mem,len); + break; + case ososQTable1: + OJPEGWriteStreamQTable(tif,1,mem,len); + break; + case ososQTable2: + OJPEGWriteStreamQTable(tif,2,mem,len); + break; + case ososQTable3: + OJPEGWriteStreamQTable(tif,3,mem,len); + break; + case ososDcTable0: + OJPEGWriteStreamDcTable(tif,0,mem,len); + break; + case ososDcTable1: + OJPEGWriteStreamDcTable(tif,1,mem,len); + break; + case ososDcTable2: + OJPEGWriteStreamDcTable(tif,2,mem,len); + break; + case ososDcTable3: + OJPEGWriteStreamDcTable(tif,3,mem,len); + break; + case ososAcTable0: + OJPEGWriteStreamAcTable(tif,0,mem,len); + break; + case ososAcTable1: + OJPEGWriteStreamAcTable(tif,1,mem,len); + break; + case ososAcTable2: + OJPEGWriteStreamAcTable(tif,2,mem,len); + break; + case ososAcTable3: + OJPEGWriteStreamAcTable(tif,3,mem,len); + break; + case ososDri: + OJPEGWriteStreamDri(tif,mem,len); + break; + case ososSof: + OJPEGWriteStreamSof(tif,mem,len); + break; + case ososSos: + OJPEGWriteStreamSos(tif,mem,len); + break; + case ososCompressed: + if (OJPEGWriteStreamCompressed(tif,mem,len)==0) + return(0); + break; + case ososRst: + OJPEGWriteStreamRst(tif,mem,len); + break; + case ososEoi: + OJPEGWriteStreamEoi(tif,mem,len); + break; + } + } while (*len==0); + return(1); +} + +static void +OJPEGWriteStreamSoi(TIFF* tif, void** mem, uint32* len) +{ + OJPEGState* sp=(OJPEGState*)tif->tif_data; + assert(OJPEG_BUFFER>=2); + sp->out_buffer[0]=255; + sp->out_buffer[1]=JPEG_MARKER_SOI; + *len=2; + *mem=(void*)sp->out_buffer; + sp->out_state++; +} + +static void +OJPEGWriteStreamQTable(TIFF* tif, uint8 table_index, void** mem, uint32* len) +{ + OJPEGState* sp=(OJPEGState*)tif->tif_data; + if (sp->qtable[table_index]!=0) + { + *mem=(void*)(sp->qtable[table_index]+sizeof(uint32)); + *len=*((uint32*)sp->qtable[table_index])-sizeof(uint32); + } + sp->out_state++; +} + +static void +OJPEGWriteStreamDcTable(TIFF* tif, uint8 table_index, void** mem, uint32* len) +{ + OJPEGState* sp=(OJPEGState*)tif->tif_data; + if (sp->dctable[table_index]!=0) + { + *mem=(void*)(sp->dctable[table_index]+sizeof(uint32)); + *len=*((uint32*)sp->dctable[table_index])-sizeof(uint32); + } + sp->out_state++; +} + +static void +OJPEGWriteStreamAcTable(TIFF* tif, uint8 table_index, void** mem, uint32* len) +{ + OJPEGState* sp=(OJPEGState*)tif->tif_data; + if (sp->actable[table_index]!=0) + { + *mem=(void*)(sp->actable[table_index]+sizeof(uint32)); + *len=*((uint32*)sp->actable[table_index])-sizeof(uint32); + } + sp->out_state++; +} + +static void +OJPEGWriteStreamDri(TIFF* tif, void** mem, uint32* len) +{ + OJPEGState* sp=(OJPEGState*)tif->tif_data; + assert(OJPEG_BUFFER>=6); + if (sp->restart_interval!=0) + { + sp->out_buffer[0]=255; + sp->out_buffer[1]=JPEG_MARKER_DRI; + sp->out_buffer[2]=0; + sp->out_buffer[3]=4; + sp->out_buffer[4]=(sp->restart_interval>>8); + sp->out_buffer[5]=(sp->restart_interval&255); + *len=6; + *mem=(void*)sp->out_buffer; + } + sp->out_state++; +} + +static void +OJPEGWriteStreamSof(TIFF* tif, void** mem, uint32* len) +{ + OJPEGState* sp=(OJPEGState*)tif->tif_data; + uint8 m; + assert(OJPEG_BUFFER>=2+8+sp->samples_per_pixel_per_plane*3); + assert(255>=8+sp->samples_per_pixel_per_plane*3); + sp->out_buffer[0]=255; + sp->out_buffer[1]=sp->sof_marker_id; + /* Lf */ + sp->out_buffer[2]=0; + sp->out_buffer[3]=8+sp->samples_per_pixel_per_plane*3; + /* P */ + sp->out_buffer[4]=8; + /* Y */ + sp->out_buffer[5]=(sp->sof_y>>8); + sp->out_buffer[6]=(sp->sof_y&255); + /* X */ + sp->out_buffer[7]=(sp->sof_x>>8); + sp->out_buffer[8]=(sp->sof_x&255); + /* Nf */ + sp->out_buffer[9]=sp->samples_per_pixel_per_plane; + for (m=0; msamples_per_pixel_per_plane; m++) + { + /* C */ + sp->out_buffer[10+m*3]=sp->sof_c[sp->plane_sample_offset+m]; + /* H and V */ + sp->out_buffer[10+m*3+1]=sp->sof_hv[sp->plane_sample_offset+m]; + /* Tq */ + sp->out_buffer[10+m*3+2]=sp->sof_tq[sp->plane_sample_offset+m]; + } + *len=10+sp->samples_per_pixel_per_plane*3; + *mem=(void*)sp->out_buffer; + sp->out_state++; +} + +static void +OJPEGWriteStreamSos(TIFF* tif, void** mem, uint32* len) +{ + OJPEGState* sp=(OJPEGState*)tif->tif_data; + uint8 m; + assert(OJPEG_BUFFER>=2+6+sp->samples_per_pixel_per_plane*2); + assert(255>=6+sp->samples_per_pixel_per_plane*2); + sp->out_buffer[0]=255; + sp->out_buffer[1]=JPEG_MARKER_SOS; + /* Ls */ + sp->out_buffer[2]=0; + sp->out_buffer[3]=6+sp->samples_per_pixel_per_plane*2; + /* Ns */ + sp->out_buffer[4]=sp->samples_per_pixel_per_plane; + for (m=0; msamples_per_pixel_per_plane; m++) + { + /* Cs */ + sp->out_buffer[5+m*2]=sp->sos_cs[sp->plane_sample_offset+m]; + /* Td and Ta */ + sp->out_buffer[5+m*2+1]=sp->sos_tda[sp->plane_sample_offset+m]; + } + /* Ss */ + sp->out_buffer[5+sp->samples_per_pixel_per_plane*2]=0; + /* Se */ + sp->out_buffer[5+sp->samples_per_pixel_per_plane*2+1]=63; + /* Ah and Al */ + sp->out_buffer[5+sp->samples_per_pixel_per_plane*2+2]=0; + *len=8+sp->samples_per_pixel_per_plane*2; + *mem=(void*)sp->out_buffer; + sp->out_state++; +} + +static int +OJPEGWriteStreamCompressed(TIFF* tif, void** mem, uint32* len) +{ + OJPEGState* sp=(OJPEGState*)tif->tif_data; + if (sp->in_buffer_togo==0) + { + if (OJPEGReadBufferFill(sp)==0) + return(0); + assert(sp->in_buffer_togo>0); + } + *len=sp->in_buffer_togo; + *mem=(void*)sp->in_buffer_cur; + sp->in_buffer_togo=0; + if (sp->in_buffer_file_togo==0) + { + switch(sp->in_buffer_source) + { + case osibsStrile: + if (sp->in_buffer_next_strilein_buffer_strile_count) + sp->out_state=ososRst; + else + sp->out_state=ososEoi; + break; + case osibsEof: + sp->out_state=ososEoi; + break; + default: + break; + } + } + return(1); +} + +static void +OJPEGWriteStreamRst(TIFF* tif, void** mem, uint32* len) +{ + OJPEGState* sp=(OJPEGState*)tif->tif_data; + assert(OJPEG_BUFFER>=2); + sp->out_buffer[0]=255; + sp->out_buffer[1]=JPEG_MARKER_RST0+sp->restart_index; + sp->restart_index++; + if (sp->restart_index==8) + sp->restart_index=0; + *len=2; + *mem=(void*)sp->out_buffer; + sp->out_state=ososCompressed; +} + +static void +OJPEGWriteStreamEoi(TIFF* tif, void** mem, uint32* len) +{ + OJPEGState* sp=(OJPEGState*)tif->tif_data; + assert(OJPEG_BUFFER>=2); + sp->out_buffer[0]=255; + sp->out_buffer[1]=JPEG_MARKER_EOI; + *len=2; + *mem=(void*)sp->out_buffer; +} + +#ifndef LIBJPEG_ENCAP_EXTERNAL +static int +jpeg_create_decompress_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo) +{ + return(SETJMP(sp->exit_jmpbuf)?0:(jpeg_create_decompress(cinfo),1)); +} +#endif + +#ifndef LIBJPEG_ENCAP_EXTERNAL +static int +jpeg_read_header_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, uint8 require_image) +{ + return(SETJMP(sp->exit_jmpbuf)?0:(jpeg_read_header(cinfo,require_image),1)); +} +#endif + +#ifndef LIBJPEG_ENCAP_EXTERNAL +static int +jpeg_start_decompress_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo) +{ + return(SETJMP(sp->exit_jmpbuf)?0:(jpeg_start_decompress(cinfo),1)); +} +#endif + +#ifndef LIBJPEG_ENCAP_EXTERNAL +static int +jpeg_read_scanlines_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, void* scanlines, uint32 max_lines) +{ + return(SETJMP(sp->exit_jmpbuf)?0:(jpeg_read_scanlines(cinfo,scanlines,max_lines),1)); +} +#endif + +#ifndef LIBJPEG_ENCAP_EXTERNAL +static int +jpeg_read_raw_data_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, void* data, uint32 max_lines) +{ + return(SETJMP(sp->exit_jmpbuf)?0:(jpeg_read_raw_data(cinfo,data,max_lines),1)); +} +#endif + +#ifndef LIBJPEG_ENCAP_EXTERNAL +static void +jpeg_encap_unwind(TIFF* tif) +{ + OJPEGState* sp=(OJPEGState*)tif->tif_data; + LONGJMP(sp->exit_jmpbuf,1); +} +#endif + +static void +OJPEGLibjpegJpegErrorMgrOutputMessage(jpeg_common_struct* cinfo) +{ + char buffer[JMSG_LENGTH_MAX]; + (*cinfo->err->format_message)(cinfo,buffer); + TIFFWarningExt(((TIFF*)(cinfo->client_data))->tif_clientdata,"LibJpeg", "%s", buffer); +} + +static void +OJPEGLibjpegJpegErrorMgrErrorExit(jpeg_common_struct* cinfo) +{ + char buffer[JMSG_LENGTH_MAX]; + (*cinfo->err->format_message)(cinfo,buffer); + TIFFErrorExt(((TIFF*)(cinfo->client_data))->tif_clientdata,"LibJpeg", "%s", buffer); + jpeg_encap_unwind((TIFF*)(cinfo->client_data)); +} + +static void +OJPEGLibjpegJpegSourceMgrInitSource(jpeg_decompress_struct* cinfo) +{ + (void)cinfo; +} + +static boolean +OJPEGLibjpegJpegSourceMgrFillInputBuffer(jpeg_decompress_struct* cinfo) +{ + TIFF* tif=(TIFF*)cinfo->client_data; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + void* mem=0; + uint32 len=0; + if (OJPEGWriteStream(tif,&mem,&len)==0) + { + TIFFErrorExt(tif->tif_clientdata,"LibJpeg","Premature end of JPEG data"); + jpeg_encap_unwind(tif); + } + sp->libjpeg_jpeg_source_mgr.bytes_in_buffer=len; + sp->libjpeg_jpeg_source_mgr.next_input_byte=mem; + return(1); +} + +static void +OJPEGLibjpegJpegSourceMgrSkipInputData(jpeg_decompress_struct* cinfo, long num_bytes) +{ + TIFF* tif=(TIFF*)cinfo->client_data; + (void)num_bytes; + TIFFErrorExt(tif->tif_clientdata,"LibJpeg","Unexpected error"); + jpeg_encap_unwind(tif); +} + +static boolean +OJPEGLibjpegJpegSourceMgrResyncToRestart(jpeg_decompress_struct* cinfo, int desired) +{ + TIFF* tif=(TIFF*)cinfo->client_data; + (void)desired; + TIFFErrorExt(tif->tif_clientdata,"LibJpeg","Unexpected error"); + jpeg_encap_unwind(tif); + return(0); +} + +static void +OJPEGLibjpegJpegSourceMgrTermSource(jpeg_decompress_struct* cinfo) +{ + (void)cinfo; +} + +#endif + + +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tif_open.c b/reactos/dll/3rdparty/libtiff/tif_open.c new file mode 100644 index 00000000000..3b3b2ce67ba --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tif_open.c @@ -0,0 +1,695 @@ +/* $Id: tif_open.c,v 1.33.2.1 2010-06-08 18:50:42 bfriesen Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library. + */ +#include "tiffiop.h" + +static const long typemask[13] = { + (long)0L, /* TIFF_NOTYPE */ + (long)0x000000ffL, /* TIFF_BYTE */ + (long)0xffffffffL, /* TIFF_ASCII */ + (long)0x0000ffffL, /* TIFF_SHORT */ + (long)0xffffffffL, /* TIFF_LONG */ + (long)0xffffffffL, /* TIFF_RATIONAL */ + (long)0x000000ffL, /* TIFF_SBYTE */ + (long)0x000000ffL, /* TIFF_UNDEFINED */ + (long)0x0000ffffL, /* TIFF_SSHORT */ + (long)0xffffffffL, /* TIFF_SLONG */ + (long)0xffffffffL, /* TIFF_SRATIONAL */ + (long)0xffffffffL, /* TIFF_FLOAT */ + (long)0xffffffffL, /* TIFF_DOUBLE */ +}; +static const int bigTypeshift[13] = { + 0, /* TIFF_NOTYPE */ + 24, /* TIFF_BYTE */ + 0, /* TIFF_ASCII */ + 16, /* TIFF_SHORT */ + 0, /* TIFF_LONG */ + 0, /* TIFF_RATIONAL */ + 24, /* TIFF_SBYTE */ + 24, /* TIFF_UNDEFINED */ + 16, /* TIFF_SSHORT */ + 0, /* TIFF_SLONG */ + 0, /* TIFF_SRATIONAL */ + 0, /* TIFF_FLOAT */ + 0, /* TIFF_DOUBLE */ +}; +static const int litTypeshift[13] = { + 0, /* TIFF_NOTYPE */ + 0, /* TIFF_BYTE */ + 0, /* TIFF_ASCII */ + 0, /* TIFF_SHORT */ + 0, /* TIFF_LONG */ + 0, /* TIFF_RATIONAL */ + 0, /* TIFF_SBYTE */ + 0, /* TIFF_UNDEFINED */ + 0, /* TIFF_SSHORT */ + 0, /* TIFF_SLONG */ + 0, /* TIFF_SRATIONAL */ + 0, /* TIFF_FLOAT */ + 0, /* TIFF_DOUBLE */ +}; + +/* + * Dummy functions to fill the omitted client procedures. + */ +static int +_tiffDummyMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize) +{ + (void) fd; (void) pbase; (void) psize; + return (0); +} + +static void +_tiffDummyUnmapProc(thandle_t fd, tdata_t base, toff_t size) +{ + (void) fd; (void) base; (void) size; +} + +/* + * Initialize the shift & mask tables, and the + * byte swapping state according to the file + * contents and the machine architecture. + */ +static void +TIFFInitOrder(TIFF* tif, int magic) +{ + tif->tif_typemask = typemask; + if (magic == TIFF_BIGENDIAN) { + tif->tif_typeshift = bigTypeshift; +#ifndef WORDS_BIGENDIAN + tif->tif_flags |= TIFF_SWAB; +#endif + } else { + tif->tif_typeshift = litTypeshift; +#ifdef WORDS_BIGENDIAN + tif->tif_flags |= TIFF_SWAB; +#endif + } +} + +int +_TIFFgetMode(const char* mode, const char* module) +{ + int m = -1; + + switch (mode[0]) { + case 'r': + m = O_RDONLY; + if (mode[1] == '+') + m = O_RDWR; + break; + case 'w': + case 'a': + m = O_RDWR|O_CREAT; + if (mode[0] == 'w') + m |= O_TRUNC; + break; + default: + TIFFErrorExt(0, module, "\"%s\": Bad mode", mode); + break; + } + return (m); +} + +TIFF* +TIFFClientOpen( + const char* name, const char* mode, + thandle_t clientdata, + TIFFReadWriteProc readproc, + TIFFReadWriteProc writeproc, + TIFFSeekProc seekproc, + TIFFCloseProc closeproc, + TIFFSizeProc sizeproc, + TIFFMapFileProc mapproc, + TIFFUnmapFileProc unmapproc +) +{ + static const char module[] = "TIFFClientOpen"; + TIFF *tif; + int m; + const char* cp; + + m = _TIFFgetMode(mode, module); + if (m == -1) + goto bad2; + tif = (TIFF *)_TIFFmalloc(sizeof (TIFF) + strlen(name) + 1); + if (tif == NULL) { + TIFFErrorExt(clientdata, module, "%s: Out of memory (TIFF structure)", name); + goto bad2; + } + _TIFFmemset(tif, 0, sizeof (*tif)); + tif->tif_name = (char *)tif + sizeof (TIFF); + strcpy(tif->tif_name, name); + tif->tif_mode = m &~ (O_CREAT|O_TRUNC); + tif->tif_curdir = (tdir_t) -1; /* non-existent directory */ + tif->tif_curoff = 0; + tif->tif_curstrip = (tstrip_t) -1; /* invalid strip */ + tif->tif_row = (uint32) -1; /* read/write pre-increment */ + tif->tif_clientdata = clientdata; + if (!readproc || !writeproc || !seekproc || !closeproc || !sizeproc) { + TIFFErrorExt(clientdata, module, + "One of the client procedures is NULL pointer."); + goto bad2; + } + tif->tif_readproc = readproc; + tif->tif_writeproc = writeproc; + tif->tif_seekproc = seekproc; + tif->tif_closeproc = closeproc; + tif->tif_sizeproc = sizeproc; + if (mapproc) + tif->tif_mapproc = mapproc; + else + tif->tif_mapproc = _tiffDummyMapProc; + if (unmapproc) + tif->tif_unmapproc = unmapproc; + else + tif->tif_unmapproc = _tiffDummyUnmapProc; + _TIFFSetDefaultCompressionState(tif); /* setup default state */ + /* + * Default is to return data MSB2LSB and enable the + * use of memory-mapped files and strip chopping when + * a file is opened read-only. + */ + tif->tif_flags = FILLORDER_MSB2LSB; + if (m == O_RDONLY ) + tif->tif_flags |= TIFF_MAPPED; + +#ifdef STRIPCHOP_DEFAULT + if (m == O_RDONLY || m == O_RDWR) + tif->tif_flags |= STRIPCHOP_DEFAULT; +#endif + + /* + * Process library-specific flags in the open mode string. + * The following flags may be used to control intrinsic library + * behaviour that may or may not be desirable (usually for + * compatibility with some application that claims to support + * TIFF but only supports some braindead idea of what the + * vendor thinks TIFF is): + * + * 'l' use little-endian byte order for creating a file + * 'b' use big-endian byte order for creating a file + * 'L' read/write information using LSB2MSB bit order + * 'B' read/write information using MSB2LSB bit order + * 'H' read/write information using host bit order + * 'M' enable use of memory-mapped files when supported + * 'm' disable use of memory-mapped files + * 'C' enable strip chopping support when reading + * 'c' disable strip chopping support + * 'h' read TIFF header only, do not load the first IFD + * + * The use of the 'l' and 'b' flags is strongly discouraged. + * These flags are provided solely because numerous vendors, + * typically on the PC, do not correctly support TIFF; they + * only support the Intel little-endian byte order. This + * support is not configured by default because it supports + * the violation of the TIFF spec that says that readers *MUST* + * support both byte orders. It is strongly recommended that + * you not use this feature except to deal with busted apps + * that write invalid TIFF. And even in those cases you should + * bang on the vendors to fix their software. + * + * The 'L', 'B', and 'H' flags are intended for applications + * that can optimize operations on data by using a particular + * bit order. By default the library returns data in MSB2LSB + * bit order for compatibiltiy with older versions of this + * library. Returning data in the bit order of the native cpu + * makes the most sense but also requires applications to check + * the value of the FillOrder tag; something they probably do + * not do right now. + * + * The 'M' and 'm' flags are provided because some virtual memory + * systems exhibit poor behaviour when large images are mapped. + * These options permit clients to control the use of memory-mapped + * files on a per-file basis. + * + * The 'C' and 'c' flags are provided because the library support + * for chopping up large strips into multiple smaller strips is not + * application-transparent and as such can cause problems. The 'c' + * option permits applications that only want to look at the tags, + * for example, to get the unadulterated TIFF tag information. + */ + for (cp = mode; *cp; cp++) + switch (*cp) { + case 'b': +#ifndef WORDS_BIGENDIAN + if (m&O_CREAT) + tif->tif_flags |= TIFF_SWAB; +#endif + break; + case 'l': +#ifdef WORDS_BIGENDIAN + if ((m&O_CREAT)) + tif->tif_flags |= TIFF_SWAB; +#endif + break; + case 'B': + tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) | + FILLORDER_MSB2LSB; + break; + case 'L': + tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) | + FILLORDER_LSB2MSB; + break; + case 'H': + tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) | + HOST_FILLORDER; + break; + case 'M': + if (m == O_RDONLY) + tif->tif_flags |= TIFF_MAPPED; + break; + case 'm': + if (m == O_RDONLY) + tif->tif_flags &= ~TIFF_MAPPED; + break; + case 'C': + if (m == O_RDONLY) + tif->tif_flags |= TIFF_STRIPCHOP; + break; + case 'c': + if (m == O_RDONLY) + tif->tif_flags &= ~TIFF_STRIPCHOP; + break; + case 'h': + tif->tif_flags |= TIFF_HEADERONLY; + break; + } + /* + * Read in TIFF header. + */ + if (tif->tif_mode & O_TRUNC || + !ReadOK(tif, &tif->tif_header, sizeof (TIFFHeader))) { + if (tif->tif_mode == O_RDONLY) { + TIFFErrorExt(tif->tif_clientdata, name, + "Cannot read TIFF header"); + goto bad; + } + /* + * Setup header and write. + */ +#ifdef WORDS_BIGENDIAN + tif->tif_header.tiff_magic = tif->tif_flags & TIFF_SWAB + ? TIFF_LITTLEENDIAN : TIFF_BIGENDIAN; +#else + tif->tif_header.tiff_magic = tif->tif_flags & TIFF_SWAB + ? TIFF_BIGENDIAN : TIFF_LITTLEENDIAN; +#endif + tif->tif_header.tiff_version = TIFF_VERSION; + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabShort(&tif->tif_header.tiff_version); + tif->tif_header.tiff_diroff = 0; /* filled in later */ + + + /* + * The doc for "fopen" for some STD_C_LIBs says that if you + * open a file for modify ("+"), then you must fseek (or + * fflush?) between any freads and fwrites. This is not + * necessary on most systems, but has been shown to be needed + * on Solaris. + */ + TIFFSeekFile( tif, 0, SEEK_SET ); + + if (!WriteOK(tif, &tif->tif_header, sizeof (TIFFHeader))) { + TIFFErrorExt(tif->tif_clientdata, name, + "Error writing TIFF header"); + goto bad; + } + /* + * Setup the byte order handling. + */ + TIFFInitOrder(tif, tif->tif_header.tiff_magic); + /* + * Setup default directory. + */ + if (!TIFFDefaultDirectory(tif)) + goto bad; + tif->tif_diroff = 0; + tif->tif_dirlist = NULL; + tif->tif_dirlistsize = 0; + tif->tif_dirnumber = 0; + return (tif); + } + /* + * Setup the byte order handling. + */ + if (tif->tif_header.tiff_magic != TIFF_BIGENDIAN && + tif->tif_header.tiff_magic != TIFF_LITTLEENDIAN +#if MDI_SUPPORT + && +#if HOST_BIGENDIAN + tif->tif_header.tiff_magic != MDI_BIGENDIAN +#else + tif->tif_header.tiff_magic != MDI_LITTLEENDIAN +#endif + ) { + TIFFErrorExt(tif->tif_clientdata, name, + "Not a TIFF or MDI file, bad magic number %d (0x%x)", +#else + ) { + TIFFErrorExt(tif->tif_clientdata, name, + "Not a TIFF file, bad magic number %d (0x%x)", +#endif + tif->tif_header.tiff_magic, + tif->tif_header.tiff_magic); + goto bad; + } + TIFFInitOrder(tif, tif->tif_header.tiff_magic); + /* + * Swap header if required. + */ + if (tif->tif_flags & TIFF_SWAB) { + TIFFSwabShort(&tif->tif_header.tiff_version); + TIFFSwabLong(&tif->tif_header.tiff_diroff); + } + /* + * Now check version (if needed, it's been byte-swapped). + * Note that this isn't actually a version number, it's a + * magic number that doesn't change (stupid). + */ + if (tif->tif_header.tiff_version == TIFF_BIGTIFF_VERSION) { + TIFFErrorExt(tif->tif_clientdata, name, + "This is a BigTIFF file. This format not supported\n" + "by this version of libtiff." ); + goto bad; + } + if (tif->tif_header.tiff_version != TIFF_VERSION) { + TIFFErrorExt(tif->tif_clientdata, name, + "Not a TIFF file, bad version number %d (0x%x)", + tif->tif_header.tiff_version, + tif->tif_header.tiff_version); + goto bad; + } + tif->tif_flags |= TIFF_MYBUFFER; + tif->tif_rawcp = tif->tif_rawdata = 0; + tif->tif_rawdatasize = 0; + + /* + * Sometimes we do not want to read the first directory (for example, + * it may be broken) and want to proceed to other directories. I this + * case we use the TIFF_HEADERONLY flag to open file and return + * immediately after reading TIFF header. + */ + if (tif->tif_flags & TIFF_HEADERONLY) + return (tif); + + /* + * Setup initial directory. + */ + switch (mode[0]) { + case 'r': + tif->tif_nextdiroff = tif->tif_header.tiff_diroff; + /* + * Try to use a memory-mapped file if the client + * has not explicitly suppressed usage with the + * 'm' flag in the open mode (see above). + */ + if ((tif->tif_flags & TIFF_MAPPED) && + !TIFFMapFileContents(tif, (tdata_t*) &tif->tif_base, &tif->tif_size)) + tif->tif_flags &= ~TIFF_MAPPED; + if (TIFFReadDirectory(tif)) { + tif->tif_rawcc = -1; + tif->tif_flags |= TIFF_BUFFERSETUP; + return (tif); + } + break; + case 'a': + /* + * New directories are automatically append + * to the end of the directory chain when they + * are written out (see TIFFWriteDirectory). + */ + if (!TIFFDefaultDirectory(tif)) + goto bad; + return (tif); + } +bad: + tif->tif_mode = O_RDONLY; /* XXX avoid flush */ + TIFFCleanup(tif); +bad2: + return ((TIFF*)0); +} + +/* + * Query functions to access private data. + */ + +/* + * Return open file's name. + */ +const char * +TIFFFileName(TIFF* tif) +{ + return (tif->tif_name); +} + +/* + * Set the file name. + */ +const char * +TIFFSetFileName(TIFF* tif, const char *name) +{ + const char* old_name = tif->tif_name; + tif->tif_name = (char *)name; + return (old_name); +} + +/* + * Return open file's I/O descriptor. + */ +int +TIFFFileno(TIFF* tif) +{ + return (tif->tif_fd); +} + +/* + * Set open file's I/O descriptor, and return previous value. + */ +int +TIFFSetFileno(TIFF* tif, int fd) +{ + int old_fd = tif->tif_fd; + tif->tif_fd = fd; + return old_fd; +} + +/* + * Return open file's clientdata. + */ +thandle_t +TIFFClientdata(TIFF* tif) +{ + return (tif->tif_clientdata); +} + +/* + * Set open file's clientdata, and return previous value. + */ +thandle_t +TIFFSetClientdata(TIFF* tif, thandle_t newvalue) +{ + thandle_t m = tif->tif_clientdata; + tif->tif_clientdata = newvalue; + return m; +} + +/* + * Return read/write mode. + */ +int +TIFFGetMode(TIFF* tif) +{ + return (tif->tif_mode); +} + +/* + * Return read/write mode. + */ +int +TIFFSetMode(TIFF* tif, int mode) +{ + int old_mode = tif->tif_mode; + tif->tif_mode = mode; + return (old_mode); +} + +/* + * Return nonzero if file is organized in + * tiles; zero if organized as strips. + */ +int +TIFFIsTiled(TIFF* tif) +{ + return (isTiled(tif)); +} + +/* + * Return current row being read/written. + */ +uint32 +TIFFCurrentRow(TIFF* tif) +{ + return (tif->tif_row); +} + +/* + * Return index of the current directory. + */ +tdir_t +TIFFCurrentDirectory(TIFF* tif) +{ + return (tif->tif_curdir); +} + +/* + * Return current strip. + */ +tstrip_t +TIFFCurrentStrip(TIFF* tif) +{ + return (tif->tif_curstrip); +} + +/* + * Return current tile. + */ +ttile_t +TIFFCurrentTile(TIFF* tif) +{ + return (tif->tif_curtile); +} + +/* + * Return nonzero if the file has byte-swapped data. + */ +int +TIFFIsByteSwapped(TIFF* tif) +{ + return ((tif->tif_flags & TIFF_SWAB) != 0); +} + +/* + * Return nonzero if the data is returned up-sampled. + */ +int +TIFFIsUpSampled(TIFF* tif) +{ + return (isUpSampled(tif)); +} + +/* + * Return nonzero if the data is returned in MSB-to-LSB bit order. + */ +int +TIFFIsMSB2LSB(TIFF* tif) +{ + return (isFillOrder(tif, FILLORDER_MSB2LSB)); +} + +/* + * Return nonzero if given file was written in big-endian order. + */ +int +TIFFIsBigEndian(TIFF* tif) +{ + return (tif->tif_header.tiff_magic == TIFF_BIGENDIAN); +} + +/* + * Return pointer to file read method. + */ +TIFFReadWriteProc +TIFFGetReadProc(TIFF* tif) +{ + return (tif->tif_readproc); +} + +/* + * Return pointer to file write method. + */ +TIFFReadWriteProc +TIFFGetWriteProc(TIFF* tif) +{ + return (tif->tif_writeproc); +} + +/* + * Return pointer to file seek method. + */ +TIFFSeekProc +TIFFGetSeekProc(TIFF* tif) +{ + return (tif->tif_seekproc); +} + +/* + * Return pointer to file close method. + */ +TIFFCloseProc +TIFFGetCloseProc(TIFF* tif) +{ + return (tif->tif_closeproc); +} + +/* + * Return pointer to file size requesting method. + */ +TIFFSizeProc +TIFFGetSizeProc(TIFF* tif) +{ + return (tif->tif_sizeproc); +} + +/* + * Return pointer to memory mapping method. + */ +TIFFMapFileProc +TIFFGetMapFileProc(TIFF* tif) +{ + return (tif->tif_mapproc); +} + +/* + * Return pointer to memory unmapping method. + */ +TIFFUnmapFileProc +TIFFGetUnmapFileProc(TIFF* tif) +{ + return (tif->tif_unmapproc); +} + +/* vim: set ts=8 sts=8 sw=8 noet: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tif_packbits.c b/reactos/dll/3rdparty/libtiff/tif_packbits.c new file mode 100644 index 00000000000..ee095f568e8 --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tif_packbits.c @@ -0,0 +1,300 @@ +/* $Id: tif_packbits.c,v 1.13.2.2 2010-06-08 18:50:42 bfriesen Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include "tiffiop.h" +#ifdef PACKBITS_SUPPORT +/* + * TIFF Library. + * + * PackBits Compression Algorithm Support + */ +#include + +static int +PackBitsPreEncode(TIFF* tif, tsample_t s) +{ + (void) s; + + if (!(tif->tif_data = (tidata_t)_TIFFmalloc(sizeof(tsize_t)))) + return (0); + /* + * Calculate the scanline/tile-width size in bytes. + */ + if (isTiled(tif)) + *(tsize_t*)tif->tif_data = TIFFTileRowSize(tif); + else + *(tsize_t*)tif->tif_data = TIFFScanlineSize(tif); + return (1); +} + +static int +PackBitsPostEncode(TIFF* tif) +{ + if (tif->tif_data) + _TIFFfree(tif->tif_data); + return (1); +} + +/* + * NB: tidata is the type representing *(tidata_t); + * if tidata_t is made signed then this type must + * be adjusted accordingly. + */ +typedef unsigned char tidata; + +/* + * Encode a run of pixels. + */ +static int +PackBitsEncode(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s) +{ + unsigned char* bp = (unsigned char*) buf; + tidata_t op, ep, lastliteral; + long n, slop; + int b; + enum { BASE, LITERAL, RUN, LITERAL_RUN } state; + + (void) s; + op = tif->tif_rawcp; + ep = tif->tif_rawdata + tif->tif_rawdatasize; + state = BASE; + lastliteral = 0; + while (cc > 0) { + /* + * Find the longest string of identical bytes. + */ + b = *bp++, cc--, n = 1; + for (; cc > 0 && b == *bp; cc--, bp++) + n++; + again: + if (op + 2 >= ep) { /* insure space for new data */ + /* + * Be careful about writing the last + * literal. Must write up to that point + * and then copy the remainder to the + * front of the buffer. + */ + if (state == LITERAL || state == LITERAL_RUN) { + slop = op - lastliteral; + tif->tif_rawcc += lastliteral - tif->tif_rawcp; + if (!TIFFFlushData1(tif)) + return (-1); + op = tif->tif_rawcp; + while (slop-- > 0) + *op++ = *lastliteral++; + lastliteral = tif->tif_rawcp; + } else { + tif->tif_rawcc += op - tif->tif_rawcp; + if (!TIFFFlushData1(tif)) + return (-1); + op = tif->tif_rawcp; + } + } + switch (state) { + case BASE: /* initial state, set run/literal */ + if (n > 1) { + state = RUN; + if (n > 128) { + *op++ = (tidata) -127; + *op++ = (tidataval_t) b; + n -= 128; + goto again; + } + *op++ = (tidataval_t)(-(n-1)); + *op++ = (tidataval_t) b; + } else { + lastliteral = op; + *op++ = 0; + *op++ = (tidataval_t) b; + state = LITERAL; + } + break; + case LITERAL: /* last object was literal string */ + if (n > 1) { + state = LITERAL_RUN; + if (n > 128) { + *op++ = (tidata) -127; + *op++ = (tidataval_t) b; + n -= 128; + goto again; + } + *op++ = (tidataval_t)(-(n-1)); /* encode run */ + *op++ = (tidataval_t) b; + } else { /* extend literal */ + if (++(*lastliteral) == 127) + state = BASE; + *op++ = (tidataval_t) b; + } + break; + case RUN: /* last object was run */ + if (n > 1) { + if (n > 128) { + *op++ = (tidata) -127; + *op++ = (tidataval_t) b; + n -= 128; + goto again; + } + *op++ = (tidataval_t)(-(n-1)); + *op++ = (tidataval_t) b; + } else { + lastliteral = op; + *op++ = 0; + *op++ = (tidataval_t) b; + state = LITERAL; + } + break; + case LITERAL_RUN: /* literal followed by a run */ + /* + * Check to see if previous run should + * be converted to a literal, in which + * case we convert literal-run-literal + * to a single literal. + */ + if (n == 1 && op[-2] == (tidata) -1 && + *lastliteral < 126) { + state = (((*lastliteral) += 2) == 127 ? + BASE : LITERAL); + op[-2] = op[-1]; /* replicate */ + } else + state = RUN; + goto again; + } + } + tif->tif_rawcc += op - tif->tif_rawcp; + tif->tif_rawcp = op; + return (1); +} + +/* + * Encode a rectangular chunk of pixels. We break it up + * into row-sized pieces to insure that encoded runs do + * not span rows. Otherwise, there can be problems with + * the decoder if data is read, for example, by scanlines + * when it was encoded by strips. + */ +static int +PackBitsEncodeChunk(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s) +{ + tsize_t rowsize = *(tsize_t*)tif->tif_data; + + while ((long)cc > 0) { + int chunk = rowsize; + + if( cc < chunk ) + chunk = cc; + + if (PackBitsEncode(tif, bp, chunk, s) < 0) + return (-1); + bp += chunk; + cc -= chunk; + } + return (1); +} + +static int +PackBitsDecode(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s) +{ + char *bp; + tsize_t cc; + long n; + int b; + + (void) s; + bp = (char*) tif->tif_rawcp; + cc = tif->tif_rawcc; + while (cc > 0 && (long)occ > 0) { + n = (long) *bp++, cc--; + /* + * Watch out for compilers that + * don't sign extend chars... + */ + if (n >= 128) + n -= 256; + if (n < 0) { /* replicate next byte -n+1 times */ + if (n == -128) /* nop */ + continue; + n = -n + 1; + if( occ < n ) + { + TIFFWarningExt(tif->tif_clientdata, tif->tif_name, + "PackBitsDecode: discarding %ld bytes " + "to avoid buffer overrun", + n - occ); + n = occ; + } + occ -= n; + b = *bp++, cc--; + while (n-- > 0) + *op++ = (tidataval_t) b; + } else { /* copy next n+1 bytes literally */ + if (occ < n + 1) + { + TIFFWarningExt(tif->tif_clientdata, tif->tif_name, + "PackBitsDecode: discarding %ld bytes " + "to avoid buffer overrun", + n - occ + 1); + n = occ - 1; + } + _TIFFmemcpy(op, bp, ++n); + op += n; occ -= n; + bp += n; cc -= n; + } + } + tif->tif_rawcp = (tidata_t) bp; + tif->tif_rawcc = cc; + if (occ > 0) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "PackBitsDecode: Not enough data for scanline %ld", + (long) tif->tif_row); + return (0); + } + return (1); +} + +int +TIFFInitPackBits(TIFF* tif, int scheme) +{ + (void) scheme; + tif->tif_decoderow = PackBitsDecode; + tif->tif_decodestrip = PackBitsDecode; + tif->tif_decodetile = PackBitsDecode; + tif->tif_preencode = PackBitsPreEncode; + tif->tif_postencode = PackBitsPostEncode; + tif->tif_encoderow = PackBitsEncode; + tif->tif_encodestrip = PackBitsEncodeChunk; + tif->tif_encodetile = PackBitsEncodeChunk; + return (1); +} +#endif /* PACKBITS_SUPPORT */ + +/* vim: set ts=8 sts=8 sw=8 noet: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tif_pixarlog.c b/reactos/dll/3rdparty/libtiff/tif_pixarlog.c new file mode 100644 index 00000000000..ed8eb4026ff --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tif_pixarlog.c @@ -0,0 +1,1371 @@ +/* $Id: tif_pixarlog.c,v 1.15.2.4 2010-06-08 18:50:42 bfriesen Exp $ */ + +/* + * Copyright (c) 1996-1997 Sam Leffler + * Copyright (c) 1996 Pixar + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Pixar, Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Pixar, Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL PIXAR, SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include "tiffiop.h" +#ifdef PIXARLOG_SUPPORT + +/* + * TIFF Library. + * PixarLog Compression Support + * + * Contributed by Dan McCoy. + * + * PixarLog film support uses the TIFF library to store companded + * 11 bit values into a tiff file, which are compressed using the + * zip compressor. + * + * The codec can take as input and produce as output 32-bit IEEE float values + * as well as 16-bit or 8-bit unsigned integer values. + * + * On writing any of the above are converted into the internal + * 11-bit log format. In the case of 8 and 16 bit values, the + * input is assumed to be unsigned linear color values that represent + * the range 0-1. In the case of IEEE values, the 0-1 range is assumed to + * be the normal linear color range, in addition over 1 values are + * accepted up to a value of about 25.0 to encode "hot" hightlights and such. + * The encoding is lossless for 8-bit values, slightly lossy for the + * other bit depths. The actual color precision should be better + * than the human eye can perceive with extra room to allow for + * error introduced by further image computation. As with any quantized + * color format, it is possible to perform image calculations which + * expose the quantization error. This format should certainly be less + * susceptable to such errors than standard 8-bit encodings, but more + * susceptable than straight 16-bit or 32-bit encodings. + * + * On reading the internal format is converted to the desired output format. + * The program can request which format it desires by setting the internal + * pseudo tag TIFFTAG_PIXARLOGDATAFMT to one of these possible values: + * PIXARLOGDATAFMT_FLOAT = provide IEEE float values. + * PIXARLOGDATAFMT_16BIT = provide unsigned 16-bit integer values + * PIXARLOGDATAFMT_8BIT = provide unsigned 8-bit integer values + * + * alternately PIXARLOGDATAFMT_8BITABGR provides unsigned 8-bit integer + * values with the difference that if there are exactly three or four channels + * (rgb or rgba) it swaps the channel order (bgr or abgr). + * + * PIXARLOGDATAFMT_11BITLOG provides the internal encoding directly + * packed in 16-bit values. However no tools are supplied for interpreting + * these values. + * + * "hot" (over 1.0) areas written in floating point get clamped to + * 1.0 in the integer data types. + * + * When the file is closed after writing, the bit depth and sample format + * are set always to appear as if 8-bit data has been written into it. + * That way a naive program unaware of the particulars of the encoding + * gets the format it is most likely able to handle. + * + * The codec does it's own horizontal differencing step on the coded + * values so the libraries predictor stuff should be turned off. + * The codec also handle byte swapping the encoded values as necessary + * since the library does not have the information necessary + * to know the bit depth of the raw unencoded buffer. + * + */ + +#include "tif_predict.h" +#include "zlib.h" + +#include +#include +#include + +/* Tables for converting to/from 11 bit coded values */ + +#define TSIZE 2048 /* decode table size (11-bit tokens) */ +#define TSIZEP1 2049 /* Plus one for slop */ +#define ONE 1250 /* token value of 1.0 exactly */ +#define RATIO 1.004 /* nominal ratio for log part */ + +#define CODE_MASK 0x7ff /* 11 bits. */ + +static float Fltsize; +static float LogK1, LogK2; + +#define REPEAT(n, op) { int i; i=n; do { i--; op; } while (i>0); } + +static void +horizontalAccumulateF(uint16 *wp, int n, int stride, float *op, + float *ToLinearF) +{ + register unsigned int cr, cg, cb, ca, mask; + register float t0, t1, t2, t3; + + if (n >= stride) { + mask = CODE_MASK; + if (stride == 3) { + t0 = ToLinearF[cr = wp[0]]; + t1 = ToLinearF[cg = wp[1]]; + t2 = ToLinearF[cb = wp[2]]; + op[0] = t0; + op[1] = t1; + op[2] = t2; + n -= 3; + while (n > 0) { + wp += 3; + op += 3; + n -= 3; + t0 = ToLinearF[(cr += wp[0]) & mask]; + t1 = ToLinearF[(cg += wp[1]) & mask]; + t2 = ToLinearF[(cb += wp[2]) & mask]; + op[0] = t0; + op[1] = t1; + op[2] = t2; + } + } else if (stride == 4) { + t0 = ToLinearF[cr = wp[0]]; + t1 = ToLinearF[cg = wp[1]]; + t2 = ToLinearF[cb = wp[2]]; + t3 = ToLinearF[ca = wp[3]]; + op[0] = t0; + op[1] = t1; + op[2] = t2; + op[3] = t3; + n -= 4; + while (n > 0) { + wp += 4; + op += 4; + n -= 4; + t0 = ToLinearF[(cr += wp[0]) & mask]; + t1 = ToLinearF[(cg += wp[1]) & mask]; + t2 = ToLinearF[(cb += wp[2]) & mask]; + t3 = ToLinearF[(ca += wp[3]) & mask]; + op[0] = t0; + op[1] = t1; + op[2] = t2; + op[3] = t3; + } + } else { + REPEAT(stride, *op = ToLinearF[*wp&mask]; wp++; op++) + n -= stride; + while (n > 0) { + REPEAT(stride, + wp[stride] += *wp; *op = ToLinearF[*wp&mask]; wp++; op++) + n -= stride; + } + } + } +} + +static void +horizontalAccumulate12(uint16 *wp, int n, int stride, int16 *op, + float *ToLinearF) +{ + register unsigned int cr, cg, cb, ca, mask; + register float t0, t1, t2, t3; + +#define SCALE12 2048.0F +#define CLAMP12(t) (((t) < 3071) ? (uint16) (t) : 3071) + + if (n >= stride) { + mask = CODE_MASK; + if (stride == 3) { + t0 = ToLinearF[cr = wp[0]] * SCALE12; + t1 = ToLinearF[cg = wp[1]] * SCALE12; + t2 = ToLinearF[cb = wp[2]] * SCALE12; + op[0] = CLAMP12(t0); + op[1] = CLAMP12(t1); + op[2] = CLAMP12(t2); + n -= 3; + while (n > 0) { + wp += 3; + op += 3; + n -= 3; + t0 = ToLinearF[(cr += wp[0]) & mask] * SCALE12; + t1 = ToLinearF[(cg += wp[1]) & mask] * SCALE12; + t2 = ToLinearF[(cb += wp[2]) & mask] * SCALE12; + op[0] = CLAMP12(t0); + op[1] = CLAMP12(t1); + op[2] = CLAMP12(t2); + } + } else if (stride == 4) { + t0 = ToLinearF[cr = wp[0]] * SCALE12; + t1 = ToLinearF[cg = wp[1]] * SCALE12; + t2 = ToLinearF[cb = wp[2]] * SCALE12; + t3 = ToLinearF[ca = wp[3]] * SCALE12; + op[0] = CLAMP12(t0); + op[1] = CLAMP12(t1); + op[2] = CLAMP12(t2); + op[3] = CLAMP12(t3); + n -= 4; + while (n > 0) { + wp += 4; + op += 4; + n -= 4; + t0 = ToLinearF[(cr += wp[0]) & mask] * SCALE12; + t1 = ToLinearF[(cg += wp[1]) & mask] * SCALE12; + t2 = ToLinearF[(cb += wp[2]) & mask] * SCALE12; + t3 = ToLinearF[(ca += wp[3]) & mask] * SCALE12; + op[0] = CLAMP12(t0); + op[1] = CLAMP12(t1); + op[2] = CLAMP12(t2); + op[3] = CLAMP12(t3); + } + } else { + REPEAT(stride, t0 = ToLinearF[*wp&mask] * SCALE12; + *op = CLAMP12(t0); wp++; op++) + n -= stride; + while (n > 0) { + REPEAT(stride, + wp[stride] += *wp; t0 = ToLinearF[wp[stride]&mask]*SCALE12; + *op = CLAMP12(t0); wp++; op++) + n -= stride; + } + } + } +} + +static void +horizontalAccumulate16(uint16 *wp, int n, int stride, uint16 *op, + uint16 *ToLinear16) +{ + register unsigned int cr, cg, cb, ca, mask; + + if (n >= stride) { + mask = CODE_MASK; + if (stride == 3) { + op[0] = ToLinear16[cr = wp[0]]; + op[1] = ToLinear16[cg = wp[1]]; + op[2] = ToLinear16[cb = wp[2]]; + n -= 3; + while (n > 0) { + wp += 3; + op += 3; + n -= 3; + op[0] = ToLinear16[(cr += wp[0]) & mask]; + op[1] = ToLinear16[(cg += wp[1]) & mask]; + op[2] = ToLinear16[(cb += wp[2]) & mask]; + } + } else if (stride == 4) { + op[0] = ToLinear16[cr = wp[0]]; + op[1] = ToLinear16[cg = wp[1]]; + op[2] = ToLinear16[cb = wp[2]]; + op[3] = ToLinear16[ca = wp[3]]; + n -= 4; + while (n > 0) { + wp += 4; + op += 4; + n -= 4; + op[0] = ToLinear16[(cr += wp[0]) & mask]; + op[1] = ToLinear16[(cg += wp[1]) & mask]; + op[2] = ToLinear16[(cb += wp[2]) & mask]; + op[3] = ToLinear16[(ca += wp[3]) & mask]; + } + } else { + REPEAT(stride, *op = ToLinear16[*wp&mask]; wp++; op++) + n -= stride; + while (n > 0) { + REPEAT(stride, + wp[stride] += *wp; *op = ToLinear16[*wp&mask]; wp++; op++) + n -= stride; + } + } + } +} + +/* + * Returns the log encoded 11-bit values with the horizontal + * differencing undone. + */ +static void +horizontalAccumulate11(uint16 *wp, int n, int stride, uint16 *op) +{ + register unsigned int cr, cg, cb, ca, mask; + + if (n >= stride) { + mask = CODE_MASK; + if (stride == 3) { + op[0] = cr = wp[0]; op[1] = cg = wp[1]; op[2] = cb = wp[2]; + n -= 3; + while (n > 0) { + wp += 3; + op += 3; + n -= 3; + op[0] = (cr += wp[0]) & mask; + op[1] = (cg += wp[1]) & mask; + op[2] = (cb += wp[2]) & mask; + } + } else if (stride == 4) { + op[0] = cr = wp[0]; op[1] = cg = wp[1]; + op[2] = cb = wp[2]; op[3] = ca = wp[3]; + n -= 4; + while (n > 0) { + wp += 4; + op += 4; + n -= 4; + op[0] = (cr += wp[0]) & mask; + op[1] = (cg += wp[1]) & mask; + op[2] = (cb += wp[2]) & mask; + op[3] = (ca += wp[3]) & mask; + } + } else { + REPEAT(stride, *op = *wp&mask; wp++; op++) + n -= stride; + while (n > 0) { + REPEAT(stride, + wp[stride] += *wp; *op = *wp&mask; wp++; op++) + n -= stride; + } + } + } +} + +static void +horizontalAccumulate8(uint16 *wp, int n, int stride, unsigned char *op, + unsigned char *ToLinear8) +{ + register unsigned int cr, cg, cb, ca, mask; + + if (n >= stride) { + mask = CODE_MASK; + if (stride == 3) { + op[0] = ToLinear8[cr = wp[0]]; + op[1] = ToLinear8[cg = wp[1]]; + op[2] = ToLinear8[cb = wp[2]]; + n -= 3; + while (n > 0) { + n -= 3; + wp += 3; + op += 3; + op[0] = ToLinear8[(cr += wp[0]) & mask]; + op[1] = ToLinear8[(cg += wp[1]) & mask]; + op[2] = ToLinear8[(cb += wp[2]) & mask]; + } + } else if (stride == 4) { + op[0] = ToLinear8[cr = wp[0]]; + op[1] = ToLinear8[cg = wp[1]]; + op[2] = ToLinear8[cb = wp[2]]; + op[3] = ToLinear8[ca = wp[3]]; + n -= 4; + while (n > 0) { + n -= 4; + wp += 4; + op += 4; + op[0] = ToLinear8[(cr += wp[0]) & mask]; + op[1] = ToLinear8[(cg += wp[1]) & mask]; + op[2] = ToLinear8[(cb += wp[2]) & mask]; + op[3] = ToLinear8[(ca += wp[3]) & mask]; + } + } else { + REPEAT(stride, *op = ToLinear8[*wp&mask]; wp++; op++) + n -= stride; + while (n > 0) { + REPEAT(stride, + wp[stride] += *wp; *op = ToLinear8[*wp&mask]; wp++; op++) + n -= stride; + } + } + } +} + + +static void +horizontalAccumulate8abgr(uint16 *wp, int n, int stride, unsigned char *op, + unsigned char *ToLinear8) +{ + register unsigned int cr, cg, cb, ca, mask; + register unsigned char t0, t1, t2, t3; + + if (n >= stride) { + mask = CODE_MASK; + if (stride == 3) { + op[0] = 0; + t1 = ToLinear8[cb = wp[2]]; + t2 = ToLinear8[cg = wp[1]]; + t3 = ToLinear8[cr = wp[0]]; + op[1] = t1; + op[2] = t2; + op[3] = t3; + n -= 3; + while (n > 0) { + n -= 3; + wp += 3; + op += 4; + op[0] = 0; + t1 = ToLinear8[(cb += wp[2]) & mask]; + t2 = ToLinear8[(cg += wp[1]) & mask]; + t3 = ToLinear8[(cr += wp[0]) & mask]; + op[1] = t1; + op[2] = t2; + op[3] = t3; + } + } else if (stride == 4) { + t0 = ToLinear8[ca = wp[3]]; + t1 = ToLinear8[cb = wp[2]]; + t2 = ToLinear8[cg = wp[1]]; + t3 = ToLinear8[cr = wp[0]]; + op[0] = t0; + op[1] = t1; + op[2] = t2; + op[3] = t3; + n -= 4; + while (n > 0) { + n -= 4; + wp += 4; + op += 4; + t0 = ToLinear8[(ca += wp[3]) & mask]; + t1 = ToLinear8[(cb += wp[2]) & mask]; + t2 = ToLinear8[(cg += wp[1]) & mask]; + t3 = ToLinear8[(cr += wp[0]) & mask]; + op[0] = t0; + op[1] = t1; + op[2] = t2; + op[3] = t3; + } + } else { + REPEAT(stride, *op = ToLinear8[*wp&mask]; wp++; op++) + n -= stride; + while (n > 0) { + REPEAT(stride, + wp[stride] += *wp; *op = ToLinear8[*wp&mask]; wp++; op++) + n -= stride; + } + } + } +} + +/* + * State block for each open TIFF + * file using PixarLog compression/decompression. + */ +typedef struct { + TIFFPredictorState predict; + z_stream stream; + uint16 *tbuf; + uint16 stride; + int state; + int user_datafmt; + int quality; +#define PLSTATE_INIT 1 + + TIFFVSetMethod vgetparent; /* super-class method */ + TIFFVSetMethod vsetparent; /* super-class method */ + + float *ToLinearF; + uint16 *ToLinear16; + unsigned char *ToLinear8; + uint16 *FromLT2; + uint16 *From14; /* Really for 16-bit data, but we shift down 2 */ + uint16 *From8; + +} PixarLogState; + +static int +PixarLogMakeTables(PixarLogState *sp) +{ + +/* + * We make several tables here to convert between various external + * representations (float, 16-bit, and 8-bit) and the internal + * 11-bit companded representation. The 11-bit representation has two + * distinct regions. A linear bottom end up through .018316 in steps + * of about .000073, and a region of constant ratio up to about 25. + * These floating point numbers are stored in the main table ToLinearF. + * All other tables are derived from this one. The tables (and the + * ratios) are continuous at the internal seam. + */ + + int nlin, lt2size; + int i, j; + double b, c, linstep, v; + float *ToLinearF; + uint16 *ToLinear16; + unsigned char *ToLinear8; + uint16 *FromLT2; + uint16 *From14; /* Really for 16-bit data, but we shift down 2 */ + uint16 *From8; + + c = log(RATIO); + nlin = (int)(1./c); /* nlin must be an integer */ + c = 1./nlin; + b = exp(-c*ONE); /* multiplicative scale factor [b*exp(c*ONE) = 1] */ + linstep = b*c*exp(1.); + + LogK1 = (float)(1./c); /* if (v >= 2) token = k1*log(v*k2) */ + LogK2 = (float)(1./b); + lt2size = (int)(2./linstep) + 1; + FromLT2 = (uint16 *)_TIFFmalloc(lt2size*sizeof(uint16)); + From14 = (uint16 *)_TIFFmalloc(16384*sizeof(uint16)); + From8 = (uint16 *)_TIFFmalloc(256*sizeof(uint16)); + ToLinearF = (float *)_TIFFmalloc(TSIZEP1 * sizeof(float)); + ToLinear16 = (uint16 *)_TIFFmalloc(TSIZEP1 * sizeof(uint16)); + ToLinear8 = (unsigned char *)_TIFFmalloc(TSIZEP1 * sizeof(unsigned char)); + if (FromLT2 == NULL || From14 == NULL || From8 == NULL || + ToLinearF == NULL || ToLinear16 == NULL || ToLinear8 == NULL) { + if (FromLT2) _TIFFfree(FromLT2); + if (From14) _TIFFfree(From14); + if (From8) _TIFFfree(From8); + if (ToLinearF) _TIFFfree(ToLinearF); + if (ToLinear16) _TIFFfree(ToLinear16); + if (ToLinear8) _TIFFfree(ToLinear8); + sp->FromLT2 = NULL; + sp->From14 = NULL; + sp->From8 = NULL; + sp->ToLinearF = NULL; + sp->ToLinear16 = NULL; + sp->ToLinear8 = NULL; + return 0; + } + + j = 0; + + for (i = 0; i < nlin; i++) { + v = i * linstep; + ToLinearF[j++] = (float)v; + } + + for (i = nlin; i < TSIZE; i++) + ToLinearF[j++] = (float)(b*exp(c*i)); + + ToLinearF[2048] = ToLinearF[2047]; + + for (i = 0; i < TSIZEP1; i++) { + v = ToLinearF[i]*65535.0 + 0.5; + ToLinear16[i] = (v > 65535.0) ? 65535 : (uint16)v; + v = ToLinearF[i]*255.0 + 0.5; + ToLinear8[i] = (v > 255.0) ? 255 : (unsigned char)v; + } + + j = 0; + for (i = 0; i < lt2size; i++) { + if ((i*linstep)*(i*linstep) > ToLinearF[j]*ToLinearF[j+1]) + j++; + FromLT2[i] = j; + } + + /* + * Since we lose info anyway on 16-bit data, we set up a 14-bit + * table and shift 16-bit values down two bits on input. + * saves a little table space. + */ + j = 0; + for (i = 0; i < 16384; i++) { + while ((i/16383.)*(i/16383.) > ToLinearF[j]*ToLinearF[j+1]) + j++; + From14[i] = j; + } + + j = 0; + for (i = 0; i < 256; i++) { + while ((i/255.)*(i/255.) > ToLinearF[j]*ToLinearF[j+1]) + j++; + From8[i] = j; + } + + Fltsize = (float)(lt2size/2); + + sp->ToLinearF = ToLinearF; + sp->ToLinear16 = ToLinear16; + sp->ToLinear8 = ToLinear8; + sp->FromLT2 = FromLT2; + sp->From14 = From14; + sp->From8 = From8; + + return 1; +} + +#define DecoderState(tif) ((PixarLogState*) (tif)->tif_data) +#define EncoderState(tif) ((PixarLogState*) (tif)->tif_data) + +static int PixarLogEncode(TIFF*, tidata_t, tsize_t, tsample_t); +static int PixarLogDecode(TIFF*, tidata_t, tsize_t, tsample_t); + +#define PIXARLOGDATAFMT_UNKNOWN -1 + +static int +PixarLogGuessDataFmt(TIFFDirectory *td) +{ + int guess = PIXARLOGDATAFMT_UNKNOWN; + int format = td->td_sampleformat; + + /* If the user didn't tell us his datafmt, + * take our best guess from the bitspersample. + */ + switch (td->td_bitspersample) { + case 32: + if (format == SAMPLEFORMAT_IEEEFP) + guess = PIXARLOGDATAFMT_FLOAT; + break; + case 16: + if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_UINT) + guess = PIXARLOGDATAFMT_16BIT; + break; + case 12: + if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_INT) + guess = PIXARLOGDATAFMT_12BITPICIO; + break; + case 11: + if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_UINT) + guess = PIXARLOGDATAFMT_11BITLOG; + break; + case 8: + if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_UINT) + guess = PIXARLOGDATAFMT_8BIT; + break; + } + + return guess; +} + +static uint32 +multiply(size_t m1, size_t m2) +{ + uint32 bytes = m1 * m2; + + if (m1 && bytes / m1 != m2) + bytes = 0; + + return bytes; +} + +static int +PixarLogSetupDecode(TIFF* tif) +{ + TIFFDirectory *td = &tif->tif_dir; + PixarLogState* sp = DecoderState(tif); + tsize_t tbuf_size; + static const char module[] = "PixarLogSetupDecode"; + + assert(sp != NULL); + + /* Make sure no byte swapping happens on the data + * after decompression. */ + tif->tif_postdecode = _TIFFNoPostDecode; + + /* for some reason, we can't do this in TIFFInitPixarLog */ + + sp->stride = (td->td_planarconfig == PLANARCONFIG_CONTIG ? + td->td_samplesperpixel : 1); + tbuf_size = multiply(multiply(multiply(sp->stride, td->td_imagewidth), + td->td_rowsperstrip), sizeof(uint16)); + if (tbuf_size == 0) + return (0); + sp->tbuf = (uint16 *) _TIFFmalloc(tbuf_size); + if (sp->tbuf == NULL) + return (0); + if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN) + sp->user_datafmt = PixarLogGuessDataFmt(td); + if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN) { + TIFFErrorExt(tif->tif_clientdata, module, + "PixarLog compression can't handle bits depth/data format combination (depth: %d)", + td->td_bitspersample); + return (0); + } + + if (inflateInit(&sp->stream) != Z_OK) { + TIFFErrorExt(tif->tif_clientdata, module, "%s: %s", tif->tif_name, sp->stream.msg); + return (0); + } else { + sp->state |= PLSTATE_INIT; + return (1); + } +} + +/* + * Setup state for decoding a strip. + */ +static int +PixarLogPreDecode(TIFF* tif, tsample_t s) +{ + PixarLogState* sp = DecoderState(tif); + + (void) s; + assert(sp != NULL); + sp->stream.next_in = tif->tif_rawdata; + sp->stream.avail_in = tif->tif_rawcc; + return (inflateReset(&sp->stream) == Z_OK); +} + +static int +PixarLogDecode(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s) +{ + TIFFDirectory *td = &tif->tif_dir; + PixarLogState* sp = DecoderState(tif); + static const char module[] = "PixarLogDecode"; + int i, nsamples, llen; + uint16 *up; + + switch (sp->user_datafmt) { + case PIXARLOGDATAFMT_FLOAT: + nsamples = occ / sizeof(float); /* XXX float == 32 bits */ + break; + case PIXARLOGDATAFMT_16BIT: + case PIXARLOGDATAFMT_12BITPICIO: + case PIXARLOGDATAFMT_11BITLOG: + nsamples = occ / sizeof(uint16); /* XXX uint16 == 16 bits */ + break; + case PIXARLOGDATAFMT_8BIT: + case PIXARLOGDATAFMT_8BITABGR: + nsamples = occ; + break; + default: + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "%d bit input not supported in PixarLog", + td->td_bitspersample); + return 0; + } + + llen = sp->stride * td->td_imagewidth; + + (void) s; + assert(sp != NULL); + sp->stream.next_out = (unsigned char *) sp->tbuf; + sp->stream.avail_out = nsamples * sizeof(uint16); + do { + int state = inflate(&sp->stream, Z_PARTIAL_FLUSH); + if (state == Z_STREAM_END) { + break; /* XXX */ + } + if (state == Z_DATA_ERROR) { + TIFFErrorExt(tif->tif_clientdata, module, + "%s: Decoding error at scanline %d, %s", + tif->tif_name, tif->tif_row, sp->stream.msg); + if (inflateSync(&sp->stream) != Z_OK) + return (0); + continue; + } + if (state != Z_OK) { + TIFFErrorExt(tif->tif_clientdata, module, "%s: zlib error: %s", + tif->tif_name, sp->stream.msg); + return (0); + } + } while (sp->stream.avail_out > 0); + + /* hopefully, we got all the bytes we needed */ + if (sp->stream.avail_out != 0) { + TIFFErrorExt(tif->tif_clientdata, module, + "%s: Not enough data at scanline %d (short %d bytes)", + tif->tif_name, tif->tif_row, sp->stream.avail_out); + return (0); + } + + up = sp->tbuf; + /* Swap bytes in the data if from a different endian machine. */ + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabArrayOfShort(up, nsamples); + + /* + * if llen is not an exact multiple of nsamples, the decode operation + * may overflow the output buffer, so truncate it enough to prevent + * that but still salvage as much data as possible. + */ + if (nsamples % llen) { + TIFFWarningExt(tif->tif_clientdata, module, + "%s: stride %d is not a multiple of sample count, " + "%d, data truncated.", tif->tif_name, llen, nsamples); + nsamples -= nsamples % llen; + } + + for (i = 0; i < nsamples; i += llen, up += llen) { + switch (sp->user_datafmt) { + case PIXARLOGDATAFMT_FLOAT: + horizontalAccumulateF(up, llen, sp->stride, + (float *)op, sp->ToLinearF); + op += llen * sizeof(float); + break; + case PIXARLOGDATAFMT_16BIT: + horizontalAccumulate16(up, llen, sp->stride, + (uint16 *)op, sp->ToLinear16); + op += llen * sizeof(uint16); + break; + case PIXARLOGDATAFMT_12BITPICIO: + horizontalAccumulate12(up, llen, sp->stride, + (int16 *)op, sp->ToLinearF); + op += llen * sizeof(int16); + break; + case PIXARLOGDATAFMT_11BITLOG: + horizontalAccumulate11(up, llen, sp->stride, + (uint16 *)op); + op += llen * sizeof(uint16); + break; + case PIXARLOGDATAFMT_8BIT: + horizontalAccumulate8(up, llen, sp->stride, + (unsigned char *)op, sp->ToLinear8); + op += llen * sizeof(unsigned char); + break; + case PIXARLOGDATAFMT_8BITABGR: + horizontalAccumulate8abgr(up, llen, sp->stride, + (unsigned char *)op, sp->ToLinear8); + op += llen * sizeof(unsigned char); + break; + default: + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "PixarLogDecode: unsupported bits/sample: %d", + td->td_bitspersample); + return (0); + } + } + + return (1); +} + +static int +PixarLogSetupEncode(TIFF* tif) +{ + TIFFDirectory *td = &tif->tif_dir; + PixarLogState* sp = EncoderState(tif); + tsize_t tbuf_size; + static const char module[] = "PixarLogSetupEncode"; + + assert(sp != NULL); + + /* for some reason, we can't do this in TIFFInitPixarLog */ + + sp->stride = (td->td_planarconfig == PLANARCONFIG_CONTIG ? + td->td_samplesperpixel : 1); + tbuf_size = multiply(multiply(multiply(sp->stride, td->td_imagewidth), + td->td_rowsperstrip), sizeof(uint16)); + if (tbuf_size == 0) + return (0); + sp->tbuf = (uint16 *) _TIFFmalloc(tbuf_size); + if (sp->tbuf == NULL) + return (0); + if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN) + sp->user_datafmt = PixarLogGuessDataFmt(td); + if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN) { + TIFFErrorExt(tif->tif_clientdata, module, "PixarLog compression can't handle %d bit linear encodings", td->td_bitspersample); + return (0); + } + + if (deflateInit(&sp->stream, sp->quality) != Z_OK) { + TIFFErrorExt(tif->tif_clientdata, module, "%s: %s", tif->tif_name, sp->stream.msg); + return (0); + } else { + sp->state |= PLSTATE_INIT; + return (1); + } +} + +/* + * Reset encoding state at the start of a strip. + */ +static int +PixarLogPreEncode(TIFF* tif, tsample_t s) +{ + PixarLogState *sp = EncoderState(tif); + + (void) s; + assert(sp != NULL); + sp->stream.next_out = tif->tif_rawdata; + sp->stream.avail_out = tif->tif_rawdatasize; + return (deflateReset(&sp->stream) == Z_OK); +} + +static void +horizontalDifferenceF(float *ip, int n, int stride, uint16 *wp, uint16 *FromLT2) +{ + + int32 r1, g1, b1, a1, r2, g2, b2, a2, mask; + float fltsize = Fltsize; + +#define CLAMP(v) ( (v<(float)0.) ? 0 \ + : (v<(float)2.) ? FromLT2[(int)(v*fltsize)] \ + : (v>(float)24.2) ? 2047 \ + : LogK1*log(v*LogK2) + 0.5 ) + + mask = CODE_MASK; + if (n >= stride) { + if (stride == 3) { + r2 = wp[0] = (uint16) CLAMP(ip[0]); + g2 = wp[1] = (uint16) CLAMP(ip[1]); + b2 = wp[2] = (uint16) CLAMP(ip[2]); + n -= 3; + while (n > 0) { + n -= 3; + wp += 3; + ip += 3; + r1 = (int32) CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1; + g1 = (int32) CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1; + b1 = (int32) CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1; + } + } else if (stride == 4) { + r2 = wp[0] = (uint16) CLAMP(ip[0]); + g2 = wp[1] = (uint16) CLAMP(ip[1]); + b2 = wp[2] = (uint16) CLAMP(ip[2]); + a2 = wp[3] = (uint16) CLAMP(ip[3]); + n -= 4; + while (n > 0) { + n -= 4; + wp += 4; + ip += 4; + r1 = (int32) CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1; + g1 = (int32) CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1; + b1 = (int32) CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1; + a1 = (int32) CLAMP(ip[3]); wp[3] = (a1-a2) & mask; a2 = a1; + } + } else { + ip += n - 1; /* point to last one */ + wp += n - 1; /* point to last one */ + n -= stride; + while (n > 0) { + REPEAT(stride, wp[0] = (uint16) CLAMP(ip[0]); + wp[stride] -= wp[0]; + wp[stride] &= mask; + wp--; ip--) + n -= stride; + } + REPEAT(stride, wp[0] = (uint16) CLAMP(ip[0]); wp--; ip--) + } + } +} + +static void +horizontalDifference16(unsigned short *ip, int n, int stride, + unsigned short *wp, uint16 *From14) +{ + register int r1, g1, b1, a1, r2, g2, b2, a2, mask; + +/* assumption is unsigned pixel values */ +#undef CLAMP +#define CLAMP(v) From14[(v) >> 2] + + mask = CODE_MASK; + if (n >= stride) { + if (stride == 3) { + r2 = wp[0] = CLAMP(ip[0]); g2 = wp[1] = CLAMP(ip[1]); + b2 = wp[2] = CLAMP(ip[2]); + n -= 3; + while (n > 0) { + n -= 3; + wp += 3; + ip += 3; + r1 = CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1; + g1 = CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1; + b1 = CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1; + } + } else if (stride == 4) { + r2 = wp[0] = CLAMP(ip[0]); g2 = wp[1] = CLAMP(ip[1]); + b2 = wp[2] = CLAMP(ip[2]); a2 = wp[3] = CLAMP(ip[3]); + n -= 4; + while (n > 0) { + n -= 4; + wp += 4; + ip += 4; + r1 = CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1; + g1 = CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1; + b1 = CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1; + a1 = CLAMP(ip[3]); wp[3] = (a1-a2) & mask; a2 = a1; + } + } else { + ip += n - 1; /* point to last one */ + wp += n - 1; /* point to last one */ + n -= stride; + while (n > 0) { + REPEAT(stride, wp[0] = CLAMP(ip[0]); + wp[stride] -= wp[0]; + wp[stride] &= mask; + wp--; ip--) + n -= stride; + } + REPEAT(stride, wp[0] = CLAMP(ip[0]); wp--; ip--) + } + } +} + + +static void +horizontalDifference8(unsigned char *ip, int n, int stride, + unsigned short *wp, uint16 *From8) +{ + register int r1, g1, b1, a1, r2, g2, b2, a2, mask; + +#undef CLAMP +#define CLAMP(v) (From8[(v)]) + + mask = CODE_MASK; + if (n >= stride) { + if (stride == 3) { + r2 = wp[0] = CLAMP(ip[0]); g2 = wp[1] = CLAMP(ip[1]); + b2 = wp[2] = CLAMP(ip[2]); + n -= 3; + while (n > 0) { + n -= 3; + r1 = CLAMP(ip[3]); wp[3] = (r1-r2) & mask; r2 = r1; + g1 = CLAMP(ip[4]); wp[4] = (g1-g2) & mask; g2 = g1; + b1 = CLAMP(ip[5]); wp[5] = (b1-b2) & mask; b2 = b1; + wp += 3; + ip += 3; + } + } else if (stride == 4) { + r2 = wp[0] = CLAMP(ip[0]); g2 = wp[1] = CLAMP(ip[1]); + b2 = wp[2] = CLAMP(ip[2]); a2 = wp[3] = CLAMP(ip[3]); + n -= 4; + while (n > 0) { + n -= 4; + r1 = CLAMP(ip[4]); wp[4] = (r1-r2) & mask; r2 = r1; + g1 = CLAMP(ip[5]); wp[5] = (g1-g2) & mask; g2 = g1; + b1 = CLAMP(ip[6]); wp[6] = (b1-b2) & mask; b2 = b1; + a1 = CLAMP(ip[7]); wp[7] = (a1-a2) & mask; a2 = a1; + wp += 4; + ip += 4; + } + } else { + wp += n + stride - 1; /* point to last one */ + ip += n + stride - 1; /* point to last one */ + n -= stride; + while (n > 0) { + REPEAT(stride, wp[0] = CLAMP(ip[0]); + wp[stride] -= wp[0]; + wp[stride] &= mask; + wp--; ip--) + n -= stride; + } + REPEAT(stride, wp[0] = CLAMP(ip[0]); wp--; ip--) + } + } +} + +/* + * Encode a chunk of pixels. + */ +static int +PixarLogEncode(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s) +{ + TIFFDirectory *td = &tif->tif_dir; + PixarLogState *sp = EncoderState(tif); + static const char module[] = "PixarLogEncode"; + int i, n, llen; + unsigned short * up; + + (void) s; + + switch (sp->user_datafmt) { + case PIXARLOGDATAFMT_FLOAT: + n = cc / sizeof(float); /* XXX float == 32 bits */ + break; + case PIXARLOGDATAFMT_16BIT: + case PIXARLOGDATAFMT_12BITPICIO: + case PIXARLOGDATAFMT_11BITLOG: + n = cc / sizeof(uint16); /* XXX uint16 == 16 bits */ + break; + case PIXARLOGDATAFMT_8BIT: + case PIXARLOGDATAFMT_8BITABGR: + n = cc; + break; + default: + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "%d bit input not supported in PixarLog", + td->td_bitspersample); + return 0; + } + + llen = sp->stride * td->td_imagewidth; + + for (i = 0, up = sp->tbuf; i < n; i += llen, up += llen) { + switch (sp->user_datafmt) { + case PIXARLOGDATAFMT_FLOAT: + horizontalDifferenceF((float *)bp, llen, + sp->stride, up, sp->FromLT2); + bp += llen * sizeof(float); + break; + case PIXARLOGDATAFMT_16BIT: + horizontalDifference16((uint16 *)bp, llen, + sp->stride, up, sp->From14); + bp += llen * sizeof(uint16); + break; + case PIXARLOGDATAFMT_8BIT: + horizontalDifference8((unsigned char *)bp, llen, + sp->stride, up, sp->From8); + bp += llen * sizeof(unsigned char); + break; + default: + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "%d bit input not supported in PixarLog", + td->td_bitspersample); + return 0; + } + } + + sp->stream.next_in = (unsigned char *) sp->tbuf; + sp->stream.avail_in = n * sizeof(uint16); + + do { + if (deflate(&sp->stream, Z_NO_FLUSH) != Z_OK) { + TIFFErrorExt(tif->tif_clientdata, module, "%s: Encoder error: %s", + tif->tif_name, sp->stream.msg); + return (0); + } + if (sp->stream.avail_out == 0) { + tif->tif_rawcc = tif->tif_rawdatasize; + TIFFFlushData1(tif); + sp->stream.next_out = tif->tif_rawdata; + sp->stream.avail_out = tif->tif_rawdatasize; + } + } while (sp->stream.avail_in > 0); + return (1); +} + +/* + * Finish off an encoded strip by flushing the last + * string and tacking on an End Of Information code. + */ + +static int +PixarLogPostEncode(TIFF* tif) +{ + PixarLogState *sp = EncoderState(tif); + static const char module[] = "PixarLogPostEncode"; + int state; + + sp->stream.avail_in = 0; + + do { + state = deflate(&sp->stream, Z_FINISH); + switch (state) { + case Z_STREAM_END: + case Z_OK: + if (sp->stream.avail_out != (uint32)tif->tif_rawdatasize) { + tif->tif_rawcc = + tif->tif_rawdatasize - sp->stream.avail_out; + TIFFFlushData1(tif); + sp->stream.next_out = tif->tif_rawdata; + sp->stream.avail_out = tif->tif_rawdatasize; + } + break; + default: + TIFFErrorExt(tif->tif_clientdata, module, "%s: zlib error: %s", + tif->tif_name, sp->stream.msg); + return (0); + } + } while (state != Z_STREAM_END); + return (1); +} + +static void +PixarLogClose(TIFF* tif) +{ + TIFFDirectory *td = &tif->tif_dir; + + /* In a really sneaky maneuver, on close, we covertly modify both + * bitspersample and sampleformat in the directory to indicate + * 8-bit linear. This way, the decode "just works" even for + * readers that don't know about PixarLog, or how to set + * the PIXARLOGDATFMT pseudo-tag. + */ + td->td_bitspersample = 8; + td->td_sampleformat = SAMPLEFORMAT_UINT; +} + +static void +PixarLogCleanup(TIFF* tif) +{ + PixarLogState* sp = (PixarLogState*) tif->tif_data; + + assert(sp != 0); + + (void)TIFFPredictorCleanup(tif); + + tif->tif_tagmethods.vgetfield = sp->vgetparent; + tif->tif_tagmethods.vsetfield = sp->vsetparent; + + if (sp->FromLT2) _TIFFfree(sp->FromLT2); + if (sp->From14) _TIFFfree(sp->From14); + if (sp->From8) _TIFFfree(sp->From8); + if (sp->ToLinearF) _TIFFfree(sp->ToLinearF); + if (sp->ToLinear16) _TIFFfree(sp->ToLinear16); + if (sp->ToLinear8) _TIFFfree(sp->ToLinear8); + if (sp->state&PLSTATE_INIT) { + if (tif->tif_mode == O_RDONLY) + inflateEnd(&sp->stream); + else + deflateEnd(&sp->stream); + } + if (sp->tbuf) + _TIFFfree(sp->tbuf); + _TIFFfree(sp); + tif->tif_data = NULL; + + _TIFFSetDefaultCompressionState(tif); +} + +static int +PixarLogVSetField(TIFF* tif, ttag_t tag, va_list ap) +{ + PixarLogState *sp = (PixarLogState *)tif->tif_data; + int result; + static const char module[] = "PixarLogVSetField"; + + switch (tag) { + case TIFFTAG_PIXARLOGQUALITY: + sp->quality = va_arg(ap, int); + if (tif->tif_mode != O_RDONLY && (sp->state&PLSTATE_INIT)) { + if (deflateParams(&sp->stream, + sp->quality, Z_DEFAULT_STRATEGY) != Z_OK) { + TIFFErrorExt(tif->tif_clientdata, module, "%s: zlib error: %s", + tif->tif_name, sp->stream.msg); + return (0); + } + } + return (1); + case TIFFTAG_PIXARLOGDATAFMT: + sp->user_datafmt = va_arg(ap, int); + /* Tweak the TIFF header so that the rest of libtiff knows what + * size of data will be passed between app and library, and + * assume that the app knows what it is doing and is not + * confused by these header manipulations... + */ + switch (sp->user_datafmt) { + case PIXARLOGDATAFMT_8BIT: + case PIXARLOGDATAFMT_8BITABGR: + TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8); + TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT); + break; + case PIXARLOGDATAFMT_11BITLOG: + TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16); + TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT); + break; + case PIXARLOGDATAFMT_12BITPICIO: + TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16); + TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_INT); + break; + case PIXARLOGDATAFMT_16BIT: + TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16); + TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT); + break; + case PIXARLOGDATAFMT_FLOAT: + TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 32); + TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP); + break; + } + /* + * Must recalculate sizes should bits/sample change. + */ + tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tsize_t) -1; + tif->tif_scanlinesize = TIFFScanlineSize(tif); + result = 1; /* NB: pseudo tag */ + break; + default: + result = (*sp->vsetparent)(tif, tag, ap); + } + return (result); +} + +static int +PixarLogVGetField(TIFF* tif, ttag_t tag, va_list ap) +{ + PixarLogState *sp = (PixarLogState *)tif->tif_data; + + switch (tag) { + case TIFFTAG_PIXARLOGQUALITY: + *va_arg(ap, int*) = sp->quality; + break; + case TIFFTAG_PIXARLOGDATAFMT: + *va_arg(ap, int*) = sp->user_datafmt; + break; + default: + return (*sp->vgetparent)(tif, tag, ap); + } + return (1); +} + +static const TIFFFieldInfo pixarlogFieldInfo[] = { + {TIFFTAG_PIXARLOGDATAFMT,0,0,TIFF_ANY, FIELD_PSEUDO,FALSE,FALSE,""}, + {TIFFTAG_PIXARLOGQUALITY,0,0,TIFF_ANY, FIELD_PSEUDO,FALSE,FALSE,""} +}; + +int +TIFFInitPixarLog(TIFF* tif, int scheme) +{ + static const char module[] = "TIFFInitPixarLog"; + + PixarLogState* sp; + + assert(scheme == COMPRESSION_PIXARLOG); + + /* + * Merge codec-specific tag information. + */ + if (!_TIFFMergeFieldInfo(tif, pixarlogFieldInfo, + TIFFArrayCount(pixarlogFieldInfo))) { + TIFFErrorExt(tif->tif_clientdata, module, + "Merging PixarLog codec-specific tags failed"); + return 0; + } + + /* + * Allocate state block so tag methods have storage to record values. + */ + tif->tif_data = (tidata_t) _TIFFmalloc(sizeof (PixarLogState)); + if (tif->tif_data == NULL) + goto bad; + sp = (PixarLogState*) tif->tif_data; + _TIFFmemset(sp, 0, sizeof (*sp)); + sp->stream.data_type = Z_BINARY; + sp->user_datafmt = PIXARLOGDATAFMT_UNKNOWN; + + /* + * Install codec methods. + */ + tif->tif_setupdecode = PixarLogSetupDecode; + tif->tif_predecode = PixarLogPreDecode; + tif->tif_decoderow = PixarLogDecode; + tif->tif_decodestrip = PixarLogDecode; + tif->tif_decodetile = PixarLogDecode; + tif->tif_setupencode = PixarLogSetupEncode; + tif->tif_preencode = PixarLogPreEncode; + tif->tif_postencode = PixarLogPostEncode; + tif->tif_encoderow = PixarLogEncode; + tif->tif_encodestrip = PixarLogEncode; + tif->tif_encodetile = PixarLogEncode; + tif->tif_close = PixarLogClose; + tif->tif_cleanup = PixarLogCleanup; + + /* Override SetField so we can handle our private pseudo-tag */ + sp->vgetparent = tif->tif_tagmethods.vgetfield; + tif->tif_tagmethods.vgetfield = PixarLogVGetField; /* hook for codec tags */ + sp->vsetparent = tif->tif_tagmethods.vsetfield; + tif->tif_tagmethods.vsetfield = PixarLogVSetField; /* hook for codec tags */ + + /* Default values for codec-specific fields */ + sp->quality = Z_DEFAULT_COMPRESSION; /* default comp. level */ + sp->state = 0; + + /* we don't wish to use the predictor, + * the default is none, which predictor value 1 + */ + (void) TIFFPredictorInit(tif); + + /* + * build the companding tables + */ + PixarLogMakeTables(sp); + + return (1); +bad: + TIFFErrorExt(tif->tif_clientdata, module, + "No space for PixarLog state block"); + return (0); +} +#endif /* PIXARLOG_SUPPORT */ + +/* vim: set ts=8 sts=8 sw=8 noet: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tif_predict.c b/reactos/dll/3rdparty/libtiff/tif_predict.c new file mode 100644 index 00000000000..bbc221f27f9 --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tif_predict.c @@ -0,0 +1,736 @@ +/* $Id: tif_predict.c,v 1.11.2.4 2010-06-08 18:50:42 bfriesen Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library. + * + * Predictor Tag Support (used by multiple codecs). + */ +#include "tiffiop.h" +#include "tif_predict.h" + +#define PredictorState(tif) ((TIFFPredictorState*) (tif)->tif_data) + +static void horAcc8(TIFF*, tidata_t, tsize_t); +static void horAcc16(TIFF*, tidata_t, tsize_t); +static void horAcc32(TIFF*, tidata_t, tsize_t); +static void swabHorAcc16(TIFF*, tidata_t, tsize_t); +static void swabHorAcc32(TIFF*, tidata_t, tsize_t); +static void horDiff8(TIFF*, tidata_t, tsize_t); +static void horDiff16(TIFF*, tidata_t, tsize_t); +static void horDiff32(TIFF*, tidata_t, tsize_t); +static void fpAcc(TIFF*, tidata_t, tsize_t); +static void fpDiff(TIFF*, tidata_t, tsize_t); +static int PredictorDecodeRow(TIFF*, tidata_t, tsize_t, tsample_t); +static int PredictorDecodeTile(TIFF*, tidata_t, tsize_t, tsample_t); +static int PredictorEncodeRow(TIFF*, tidata_t, tsize_t, tsample_t); +static int PredictorEncodeTile(TIFF*, tidata_t, tsize_t, tsample_t); + +static int +PredictorSetup(TIFF* tif) +{ + static const char module[] = "PredictorSetup"; + + TIFFPredictorState* sp = PredictorState(tif); + TIFFDirectory* td = &tif->tif_dir; + + switch (sp->predictor) /* no differencing */ + { + case PREDICTOR_NONE: + return 1; + case PREDICTOR_HORIZONTAL: + if (td->td_bitspersample != 8 + && td->td_bitspersample != 16 + && td->td_bitspersample != 32) { + TIFFErrorExt(tif->tif_clientdata, module, + "Horizontal differencing \"Predictor\" not supported with %d-bit samples", + td->td_bitspersample); + return 0; + } + break; + case PREDICTOR_FLOATINGPOINT: + if (td->td_sampleformat != SAMPLEFORMAT_IEEEFP) { + TIFFErrorExt(tif->tif_clientdata, module, + "Floating point \"Predictor\" not supported with %d data format", + td->td_sampleformat); + return 0; + } + break; + default: + TIFFErrorExt(tif->tif_clientdata, module, + "\"Predictor\" value %d not supported", + sp->predictor); + return 0; + } + sp->stride = (td->td_planarconfig == PLANARCONFIG_CONTIG ? + td->td_samplesperpixel : 1); + /* + * Calculate the scanline/tile-width size in bytes. + */ + if (isTiled(tif)) + sp->rowsize = TIFFTileRowSize(tif); + else + sp->rowsize = TIFFScanlineSize(tif); + + return 1; +} + +static int +PredictorSetupDecode(TIFF* tif) +{ + TIFFPredictorState* sp = PredictorState(tif); + TIFFDirectory* td = &tif->tif_dir; + + if (!(*sp->setupdecode)(tif) || !PredictorSetup(tif)) + return 0; + + if (sp->predictor == 2) { + switch (td->td_bitspersample) { + case 8: sp->decodepfunc = horAcc8; break; + case 16: sp->decodepfunc = horAcc16; break; + case 32: sp->decodepfunc = horAcc32; break; + } + /* + * Override default decoding method with one that does the + * predictor stuff. + */ + if( tif->tif_decoderow != PredictorDecodeRow ) + { + sp->decoderow = tif->tif_decoderow; + tif->tif_decoderow = PredictorDecodeRow; + sp->decodestrip = tif->tif_decodestrip; + tif->tif_decodestrip = PredictorDecodeTile; + sp->decodetile = tif->tif_decodetile; + tif->tif_decodetile = PredictorDecodeTile; + } + /* + * If the data is horizontally differenced 16-bit data that + * requires byte-swapping, then it must be byte swapped before + * the accumulation step. We do this with a special-purpose + * routine and override the normal post decoding logic that + * the library setup when the directory was read. + */ + if (tif->tif_flags & TIFF_SWAB) { + if (sp->decodepfunc == horAcc16) { + sp->decodepfunc = swabHorAcc16; + tif->tif_postdecode = _TIFFNoPostDecode; + } else if (sp->decodepfunc == horAcc32) { + sp->decodepfunc = swabHorAcc32; + tif->tif_postdecode = _TIFFNoPostDecode; + } + } + } + + else if (sp->predictor == 3) { + sp->decodepfunc = fpAcc; + /* + * Override default decoding method with one that does the + * predictor stuff. + */ + if( tif->tif_decoderow != PredictorDecodeRow ) + { + sp->decoderow = tif->tif_decoderow; + tif->tif_decoderow = PredictorDecodeRow; + sp->decodestrip = tif->tif_decodestrip; + tif->tif_decodestrip = PredictorDecodeTile; + sp->decodetile = tif->tif_decodetile; + tif->tif_decodetile = PredictorDecodeTile; + } + /* + * The data should not be swapped outside of the floating + * point predictor, the accumulation routine should return + * byres in the native order. + */ + if (tif->tif_flags & TIFF_SWAB) { + tif->tif_postdecode = _TIFFNoPostDecode; + } + /* + * Allocate buffer to keep the decoded bytes before + * rearranging in the ight order + */ + } + + return 1; +} + +static int +PredictorSetupEncode(TIFF* tif) +{ + TIFFPredictorState* sp = PredictorState(tif); + TIFFDirectory* td = &tif->tif_dir; + + if (!(*sp->setupencode)(tif) || !PredictorSetup(tif)) + return 0; + + if (sp->predictor == 2) { + switch (td->td_bitspersample) { + case 8: sp->encodepfunc = horDiff8; break; + case 16: sp->encodepfunc = horDiff16; break; + case 32: sp->encodepfunc = horDiff32; break; + } + /* + * Override default encoding method with one that does the + * predictor stuff. + */ + if( tif->tif_encoderow != PredictorEncodeRow ) + { + sp->encoderow = tif->tif_encoderow; + tif->tif_encoderow = PredictorEncodeRow; + sp->encodestrip = tif->tif_encodestrip; + tif->tif_encodestrip = PredictorEncodeTile; + sp->encodetile = tif->tif_encodetile; + tif->tif_encodetile = PredictorEncodeTile; + } + } + + else if (sp->predictor == 3) { + sp->encodepfunc = fpDiff; + /* + * Override default encoding method with one that does the + * predictor stuff. + */ + if( tif->tif_encoderow != PredictorEncodeRow ) + { + sp->encoderow = tif->tif_encoderow; + tif->tif_encoderow = PredictorEncodeRow; + sp->encodestrip = tif->tif_encodestrip; + tif->tif_encodestrip = PredictorEncodeTile; + sp->encodetile = tif->tif_encodetile; + tif->tif_encodetile = PredictorEncodeTile; + } + } + + return 1; +} + +#define REPEAT4(n, op) \ + switch (n) { \ + default: { int i; for (i = n-4; i > 0; i--) { op; } } \ + case 4: op; \ + case 3: op; \ + case 2: op; \ + case 1: op; \ + case 0: ; \ + } + +static void +horAcc8(TIFF* tif, tidata_t cp0, tsize_t cc) +{ + tsize_t stride = PredictorState(tif)->stride; + + char* cp = (char*) cp0; + if (cc > stride) { + cc -= stride; + /* + * Pipeline the most common cases. + */ + if (stride == 3) { + unsigned int cr = cp[0]; + unsigned int cg = cp[1]; + unsigned int cb = cp[2]; + do { + cc -= 3, cp += 3; + cp[0] = (char) (cr += cp[0]); + cp[1] = (char) (cg += cp[1]); + cp[2] = (char) (cb += cp[2]); + } while ((int32) cc > 0); + } else if (stride == 4) { + unsigned int cr = cp[0]; + unsigned int cg = cp[1]; + unsigned int cb = cp[2]; + unsigned int ca = cp[3]; + do { + cc -= 4, cp += 4; + cp[0] = (char) (cr += cp[0]); + cp[1] = (char) (cg += cp[1]); + cp[2] = (char) (cb += cp[2]); + cp[3] = (char) (ca += cp[3]); + } while ((int32) cc > 0); + } else { + do { + REPEAT4(stride, cp[stride] = + (char) (cp[stride] + *cp); cp++) + cc -= stride; + } while ((int32) cc > 0); + } + } +} + +static void +swabHorAcc16(TIFF* tif, tidata_t cp0, tsize_t cc) +{ + tsize_t stride = PredictorState(tif)->stride; + uint16* wp = (uint16*) cp0; + tsize_t wc = cc / 2; + + if (wc > stride) { + TIFFSwabArrayOfShort(wp, wc); + wc -= stride; + do { + REPEAT4(stride, wp[stride] += wp[0]; wp++) + wc -= stride; + } while ((int32) wc > 0); + } +} + +static void +horAcc16(TIFF* tif, tidata_t cp0, tsize_t cc) +{ + tsize_t stride = PredictorState(tif)->stride; + uint16* wp = (uint16*) cp0; + tsize_t wc = cc / 2; + + if (wc > stride) { + wc -= stride; + do { + REPEAT4(stride, wp[stride] += wp[0]; wp++) + wc -= stride; + } while ((int32) wc > 0); + } +} + +static void +swabHorAcc32(TIFF* tif, tidata_t cp0, tsize_t cc) +{ + tsize_t stride = PredictorState(tif)->stride; + uint32* wp = (uint32*) cp0; + tsize_t wc = cc / 4; + + if (wc > stride) { + TIFFSwabArrayOfLong(wp, wc); + wc -= stride; + do { + REPEAT4(stride, wp[stride] += wp[0]; wp++) + wc -= stride; + } while ((int32) wc > 0); + } +} + +static void +horAcc32(TIFF* tif, tidata_t cp0, tsize_t cc) +{ + tsize_t stride = PredictorState(tif)->stride; + uint32* wp = (uint32*) cp0; + tsize_t wc = cc / 4; + + if (wc > stride) { + wc -= stride; + do { + REPEAT4(stride, wp[stride] += wp[0]; wp++) + wc -= stride; + } while ((int32) wc > 0); + } +} + +/* + * Floating point predictor accumulation routine. + */ +static void +fpAcc(TIFF* tif, tidata_t cp0, tsize_t cc) +{ + tsize_t stride = PredictorState(tif)->stride; + uint32 bps = tif->tif_dir.td_bitspersample / 8; + tsize_t wc = cc / bps; + tsize_t count = cc; + uint8 *cp = (uint8 *) cp0; + uint8 *tmp = (uint8 *)_TIFFmalloc(cc); + + if (!tmp) + return; + + while (count > stride) { + REPEAT4(stride, cp[stride] += cp[0]; cp++) + count -= stride; + } + + _TIFFmemcpy(tmp, cp0, cc); + cp = (uint8 *) cp0; + for (count = 0; count < wc; count++) { + uint32 byte; + for (byte = 0; byte < bps; byte++) { +#if WORDS_BIGENDIAN + cp[bps * count + byte] = tmp[byte * wc + count]; +#else + cp[bps * count + byte] = + tmp[(bps - byte - 1) * wc + count]; +#endif + } + } + _TIFFfree(tmp); +} + +/* + * Decode a scanline and apply the predictor routine. + */ +static int +PredictorDecodeRow(TIFF* tif, tidata_t op0, tsize_t occ0, tsample_t s) +{ + TIFFPredictorState *sp = PredictorState(tif); + + assert(sp != NULL); + assert(sp->decoderow != NULL); + assert(sp->decodepfunc != NULL); + + if ((*sp->decoderow)(tif, op0, occ0, s)) { + (*sp->decodepfunc)(tif, op0, occ0); + return 1; + } else + return 0; +} + +/* + * Decode a tile/strip and apply the predictor routine. + * Note that horizontal differencing must be done on a + * row-by-row basis. The width of a "row" has already + * been calculated at pre-decode time according to the + * strip/tile dimensions. + */ +static int +PredictorDecodeTile(TIFF* tif, tidata_t op0, tsize_t occ0, tsample_t s) +{ + TIFFPredictorState *sp = PredictorState(tif); + + assert(sp != NULL); + assert(sp->decodetile != NULL); + + if ((*sp->decodetile)(tif, op0, occ0, s)) { + tsize_t rowsize = sp->rowsize; + assert(rowsize > 0); + assert(sp->decodepfunc != NULL); + while ((long)occ0 > 0) { + (*sp->decodepfunc)(tif, op0, (tsize_t) rowsize); + occ0 -= rowsize; + op0 += rowsize; + } + return 1; + } else + return 0; +} + +static void +horDiff8(TIFF* tif, tidata_t cp0, tsize_t cc) +{ + TIFFPredictorState* sp = PredictorState(tif); + tsize_t stride = sp->stride; + char* cp = (char*) cp0; + + if (cc > stride) { + cc -= stride; + /* + * Pipeline the most common cases. + */ + if (stride == 3) { + int r1, g1, b1; + int r2 = cp[0]; + int g2 = cp[1]; + int b2 = cp[2]; + do { + r1 = cp[3]; cp[3] = r1-r2; r2 = r1; + g1 = cp[4]; cp[4] = g1-g2; g2 = g1; + b1 = cp[5]; cp[5] = b1-b2; b2 = b1; + cp += 3; + } while ((int32)(cc -= 3) > 0); + } else if (stride == 4) { + int r1, g1, b1, a1; + int r2 = cp[0]; + int g2 = cp[1]; + int b2 = cp[2]; + int a2 = cp[3]; + do { + r1 = cp[4]; cp[4] = r1-r2; r2 = r1; + g1 = cp[5]; cp[5] = g1-g2; g2 = g1; + b1 = cp[6]; cp[6] = b1-b2; b2 = b1; + a1 = cp[7]; cp[7] = a1-a2; a2 = a1; + cp += 4; + } while ((int32)(cc -= 4) > 0); + } else { + cp += cc - 1; + do { + REPEAT4(stride, cp[stride] -= cp[0]; cp--) + } while ((int32)(cc -= stride) > 0); + } + } +} + +static void +horDiff16(TIFF* tif, tidata_t cp0, tsize_t cc) +{ + TIFFPredictorState* sp = PredictorState(tif); + tsize_t stride = sp->stride; + int16 *wp = (int16*) cp0; + tsize_t wc = cc/2; + + if (wc > stride) { + wc -= stride; + wp += wc - 1; + do { + REPEAT4(stride, wp[stride] -= wp[0]; wp--) + wc -= stride; + } while ((int32) wc > 0); + } +} + +static void +horDiff32(TIFF* tif, tidata_t cp0, tsize_t cc) +{ + TIFFPredictorState* sp = PredictorState(tif); + tsize_t stride = sp->stride; + int32 *wp = (int32*) cp0; + tsize_t wc = cc/4; + + if (wc > stride) { + wc -= stride; + wp += wc - 1; + do { + REPEAT4(stride, wp[stride] -= wp[0]; wp--) + wc -= stride; + } while ((int32) wc > 0); + } +} + +/* + * Floating point predictor differencing routine. + */ +static void +fpDiff(TIFF* tif, tidata_t cp0, tsize_t cc) +{ + tsize_t stride = PredictorState(tif)->stride; + uint32 bps = tif->tif_dir.td_bitspersample / 8; + tsize_t wc = cc / bps; + tsize_t count; + uint8 *cp = (uint8 *) cp0; + uint8 *tmp = (uint8 *)_TIFFmalloc(cc); + + if (!tmp) + return; + + _TIFFmemcpy(tmp, cp0, cc); + for (count = 0; count < wc; count++) { + uint32 byte; + for (byte = 0; byte < bps; byte++) { +#if WORDS_BIGENDIAN + cp[byte * wc + count] = tmp[bps * count + byte]; +#else + cp[(bps - byte - 1) * wc + count] = + tmp[bps * count + byte]; +#endif + } + } + _TIFFfree(tmp); + + cp = (uint8 *) cp0; + cp += cc - stride - 1; + for (count = cc; count > stride; count -= stride) + REPEAT4(stride, cp[stride] -= cp[0]; cp--) +} + +static int +PredictorEncodeRow(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s) +{ + TIFFPredictorState *sp = PredictorState(tif); + + assert(sp != NULL); + assert(sp->encodepfunc != NULL); + assert(sp->encoderow != NULL); + + /* XXX horizontal differencing alters user's data XXX */ + (*sp->encodepfunc)(tif, bp, cc); + return (*sp->encoderow)(tif, bp, cc, s); +} + +static int +PredictorEncodeTile(TIFF* tif, tidata_t bp0, tsize_t cc0, tsample_t s) +{ + static const char module[] = "PredictorEncodeTile"; + TIFFPredictorState *sp = PredictorState(tif); + uint8 *working_copy; + tsize_t cc = cc0, rowsize; + unsigned char* bp; + int result_code; + + assert(sp != NULL); + assert(sp->encodepfunc != NULL); + assert(sp->encodetile != NULL); + + /* + * Do predictor manipulation in a working buffer to avoid altering + * the callers buffer. http://trac.osgeo.org/gdal/ticket/1965 + */ + working_copy = (uint8*) _TIFFmalloc(cc0); + if( working_copy == NULL ) + { + TIFFErrorExt(tif->tif_clientdata, module, + "Out of memory allocating %d byte temp buffer.", + cc0 ); + return 0; + } + memcpy( working_copy, bp0, cc0 ); + bp = working_copy; + + rowsize = sp->rowsize; + assert(rowsize > 0); + assert((cc0%rowsize)==0); + while (cc > 0) { + (*sp->encodepfunc)(tif, bp, rowsize); + cc -= rowsize; + bp += rowsize; + } + result_code = (*sp->encodetile)(tif, working_copy, cc0, s); + + _TIFFfree( working_copy ); + + return result_code; +} + +#define FIELD_PREDICTOR (FIELD_CODEC+0) /* XXX */ + +static const TIFFFieldInfo predictFieldInfo[] = { + { TIFFTAG_PREDICTOR, 1, 1, TIFF_SHORT, FIELD_PREDICTOR, + FALSE, FALSE, "Predictor" }, +}; + +static int +PredictorVSetField(TIFF* tif, ttag_t tag, va_list ap) +{ + TIFFPredictorState *sp = PredictorState(tif); + + assert(sp != NULL); + assert(sp->vsetparent != NULL); + + switch (tag) { + case TIFFTAG_PREDICTOR: + sp->predictor = (uint16) va_arg(ap, int); + TIFFSetFieldBit(tif, FIELD_PREDICTOR); + break; + default: + return (*sp->vsetparent)(tif, tag, ap); + } + tif->tif_flags |= TIFF_DIRTYDIRECT; + return 1; +} + +static int +PredictorVGetField(TIFF* tif, ttag_t tag, va_list ap) +{ + TIFFPredictorState *sp = PredictorState(tif); + + assert(sp != NULL); + assert(sp->vgetparent != NULL); + + switch (tag) { + case TIFFTAG_PREDICTOR: + *va_arg(ap, uint16*) = sp->predictor; + break; + default: + return (*sp->vgetparent)(tif, tag, ap); + } + return 1; +} + +static void +PredictorPrintDir(TIFF* tif, FILE* fd, long flags) +{ + TIFFPredictorState* sp = PredictorState(tif); + + (void) flags; + if (TIFFFieldSet(tif,FIELD_PREDICTOR)) { + fprintf(fd, " Predictor: "); + switch (sp->predictor) { + case 1: fprintf(fd, "none "); break; + case 2: fprintf(fd, "horizontal differencing "); break; + case 3: fprintf(fd, "floating point predictor "); break; + } + fprintf(fd, "%u (0x%x)\n", sp->predictor, sp->predictor); + } + if (sp->printdir) + (*sp->printdir)(tif, fd, flags); +} + +int +TIFFPredictorInit(TIFF* tif) +{ + TIFFPredictorState* sp = PredictorState(tif); + + assert(sp != 0); + + /* + * Merge codec-specific tag information. + */ + if (!_TIFFMergeFieldInfo(tif, predictFieldInfo, + TIFFArrayCount(predictFieldInfo))) { + TIFFErrorExt(tif->tif_clientdata, "TIFFPredictorInit", + "Merging Predictor codec-specific tags failed"); + return 0; + } + + /* + * Override parent get/set field methods. + */ + sp->vgetparent = tif->tif_tagmethods.vgetfield; + tif->tif_tagmethods.vgetfield = + PredictorVGetField;/* hook for predictor tag */ + sp->vsetparent = tif->tif_tagmethods.vsetfield; + tif->tif_tagmethods.vsetfield = + PredictorVSetField;/* hook for predictor tag */ + sp->printdir = tif->tif_tagmethods.printdir; + tif->tif_tagmethods.printdir = + PredictorPrintDir; /* hook for predictor tag */ + + sp->setupdecode = tif->tif_setupdecode; + tif->tif_setupdecode = PredictorSetupDecode; + sp->setupencode = tif->tif_setupencode; + tif->tif_setupencode = PredictorSetupEncode; + + sp->predictor = 1; /* default value */ + sp->encodepfunc = NULL; /* no predictor routine */ + sp->decodepfunc = NULL; /* no predictor routine */ + return 1; +} + +int +TIFFPredictorCleanup(TIFF* tif) +{ + TIFFPredictorState* sp = PredictorState(tif); + + assert(sp != 0); + + tif->tif_tagmethods.vgetfield = sp->vgetparent; + tif->tif_tagmethods.vsetfield = sp->vsetparent; + tif->tif_tagmethods.printdir = sp->printdir; + tif->tif_setupdecode = sp->setupdecode; + tif->tif_setupencode = sp->setupencode; + + return 1; +} + +/* vim: set ts=8 sts=8 sw=8 noet: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tif_predict.h b/reactos/dll/3rdparty/libtiff/tif_predict.h new file mode 100644 index 00000000000..da0ad9892b0 --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tif_predict.h @@ -0,0 +1,77 @@ +/* $Id: tif_predict.h,v 1.3.2.2 2010-06-08 18:50:42 bfriesen Exp $ */ + +/* + * Copyright (c) 1995-1997 Sam Leffler + * Copyright (c) 1995-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _TIFFPREDICT_ +#define _TIFFPREDICT_ +/* + * ``Library-private'' Support for the Predictor Tag + */ + +/* + * Codecs that want to support the Predictor tag must place + * this structure first in their private state block so that + * the predictor code can cast tif_data to find its state. + */ +typedef struct { + int predictor; /* predictor tag value */ + int stride; /* sample stride over data */ + tsize_t rowsize; /* tile/strip row size */ + + TIFFCodeMethod encoderow; /* parent codec encode/decode row */ + TIFFCodeMethod encodestrip; /* parent codec encode/decode strip */ + TIFFCodeMethod encodetile; /* parent codec encode/decode tile */ + TIFFPostMethod encodepfunc; /* horizontal differencer */ + + TIFFCodeMethod decoderow; /* parent codec encode/decode row */ + TIFFCodeMethod decodestrip; /* parent codec encode/decode strip */ + TIFFCodeMethod decodetile; /* parent codec encode/decode tile */ + TIFFPostMethod decodepfunc; /* horizontal accumulator */ + + TIFFVGetMethod vgetparent; /* super-class method */ + TIFFVSetMethod vsetparent; /* super-class method */ + TIFFPrintMethod printdir; /* super-class method */ + TIFFBoolMethod setupdecode; /* super-class method */ + TIFFBoolMethod setupencode; /* super-class method */ +} TIFFPredictorState; + +#if defined(__cplusplus) +extern "C" { +#endif +extern int TIFFPredictorInit(TIFF*); +extern int TIFFPredictorCleanup(TIFF*); +#if defined(__cplusplus) +} +#endif +#endif /* _TIFFPREDICT_ */ + +/* vim: set ts=8 sts=8 sw=8 noet: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tif_print.c b/reactos/dll/3rdparty/libtiff/tif_print.c new file mode 100644 index 00000000000..eb4b1e70c3e --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tif_print.c @@ -0,0 +1,646 @@ +/* $Id: tif_print.c,v 1.36.2.4 2010-06-08 18:50:42 bfriesen Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library. + * + * Directory Printing Support + */ +#include "tiffiop.h" +#include +#include +#include + +static const char *photoNames[] = { + "min-is-white", /* PHOTOMETRIC_MINISWHITE */ + "min-is-black", /* PHOTOMETRIC_MINISBLACK */ + "RGB color", /* PHOTOMETRIC_RGB */ + "palette color (RGB from colormap)", /* PHOTOMETRIC_PALETTE */ + "transparency mask", /* PHOTOMETRIC_MASK */ + "separated", /* PHOTOMETRIC_SEPARATED */ + "YCbCr", /* PHOTOMETRIC_YCBCR */ + "7 (0x7)", + "CIE L*a*b*", /* PHOTOMETRIC_CIELAB */ +}; +#define NPHOTONAMES (sizeof (photoNames) / sizeof (photoNames[0])) + +static const char *orientNames[] = { + "0 (0x0)", + "row 0 top, col 0 lhs", /* ORIENTATION_TOPLEFT */ + "row 0 top, col 0 rhs", /* ORIENTATION_TOPRIGHT */ + "row 0 bottom, col 0 rhs", /* ORIENTATION_BOTRIGHT */ + "row 0 bottom, col 0 lhs", /* ORIENTATION_BOTLEFT */ + "row 0 lhs, col 0 top", /* ORIENTATION_LEFTTOP */ + "row 0 rhs, col 0 top", /* ORIENTATION_RIGHTTOP */ + "row 0 rhs, col 0 bottom", /* ORIENTATION_RIGHTBOT */ + "row 0 lhs, col 0 bottom", /* ORIENTATION_LEFTBOT */ +}; +#define NORIENTNAMES (sizeof (orientNames) / sizeof (orientNames[0])) + +static void +_TIFFPrintField(FILE* fd, const TIFFFieldInfo *fip, + uint32 value_count, void *raw_data) +{ + uint32 j; + + fprintf(fd, " %s: ", fip->field_name); + + for(j = 0; j < value_count; j++) { + if(fip->field_type == TIFF_BYTE) + fprintf(fd, "%u", ((uint8 *) raw_data)[j]); + else if(fip->field_type == TIFF_UNDEFINED) + fprintf(fd, "0x%x", + (unsigned int) ((unsigned char *) raw_data)[j]); + else if(fip->field_type == TIFF_SBYTE) + fprintf(fd, "%d", ((int8 *) raw_data)[j]); + else if(fip->field_type == TIFF_SHORT) + fprintf(fd, "%u", ((uint16 *) raw_data)[j]); + else if(fip->field_type == TIFF_SSHORT) + fprintf(fd, "%d", ((int16 *) raw_data)[j]); + else if(fip->field_type == TIFF_LONG) + fprintf(fd, "%lu", + (unsigned long)((uint32 *) raw_data)[j]); + else if(fip->field_type == TIFF_SLONG) + fprintf(fd, "%ld", (long)((int32 *) raw_data)[j]); + else if(fip->field_type == TIFF_RATIONAL + || fip->field_type == TIFF_SRATIONAL + || fip->field_type == TIFF_FLOAT) + fprintf(fd, "%f", ((float *) raw_data)[j]); + else if(fip->field_type == TIFF_IFD) + fprintf(fd, "0x%ulx", ((uint32 *) raw_data)[j]); + else if(fip->field_type == TIFF_ASCII) { + fprintf(fd, "%s", (char *) raw_data); + break; + } + else if(fip->field_type == TIFF_DOUBLE) + fprintf(fd, "%f", ((double *) raw_data)[j]); + else if(fip->field_type == TIFF_FLOAT) + fprintf(fd, "%f", ((float *)raw_data)[j]); + else { + fprintf(fd, ""); + break; + } + + if(j < value_count - 1) + fprintf(fd, ","); + } + + fprintf(fd, "\n"); +} + +static int +_TIFFPrettyPrintField(TIFF* tif, FILE* fd, ttag_t tag, + uint32 value_count, void *raw_data) +{ + TIFFDirectory *td = &tif->tif_dir; + + switch (tag) + { + case TIFFTAG_INKSET: + fprintf(fd, " Ink Set: "); + switch (*((uint16*)raw_data)) { + case INKSET_CMYK: + fprintf(fd, "CMYK\n"); + break; + default: + fprintf(fd, "%u (0x%x)\n", + *((uint16*)raw_data), + *((uint16*)raw_data)); + break; + } + return 1; + case TIFFTAG_DOTRANGE: + fprintf(fd, " Dot Range: %u-%u\n", + ((uint16*)raw_data)[0], ((uint16*)raw_data)[1]); + return 1; + case TIFFTAG_WHITEPOINT: + fprintf(fd, " White Point: %g-%g\n", + ((float *)raw_data)[0], ((float *)raw_data)[1]); return 1; + case TIFFTAG_REFERENCEBLACKWHITE: + { + uint16 i; + + fprintf(fd, " Reference Black/White:\n"); + for (i = 0; i < 3; i++) + fprintf(fd, " %2d: %5g %5g\n", i, + ((float *)raw_data)[2*i+0], + ((float *)raw_data)[2*i+1]); + return 1; + } + case TIFFTAG_XMLPACKET: + { + uint32 i; + + fprintf(fd, " XMLPacket (XMP Metadata):\n" ); + for(i = 0; i < value_count; i++) + fputc(((char *)raw_data)[i], fd); + fprintf( fd, "\n" ); + return 1; + } + case TIFFTAG_RICHTIFFIPTC: + /* + * XXX: for some weird reason RichTIFFIPTC tag + * defined as array of LONG values. + */ + fprintf(fd, + " RichTIFFIPTC Data: , %lu bytes\n", + (unsigned long) value_count * 4); + return 1; + case TIFFTAG_PHOTOSHOP: + fprintf(fd, " Photoshop Data: , %lu bytes\n", + (unsigned long) value_count); + return 1; + case TIFFTAG_ICCPROFILE: + fprintf(fd, " ICC Profile: , %lu bytes\n", + (unsigned long) value_count); + return 1; + case TIFFTAG_STONITS: + fprintf(fd, + " Sample to Nits conversion factor: %.4e\n", + *((double*)raw_data)); + return 1; + } + + return 0; +} + +/* + * Print the contents of the current directory + * to the specified stdio file stream. + */ +void +TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags) +{ + TIFFDirectory *td = &tif->tif_dir; + char *sep; + uint16 i; + long l, n; + + fprintf(fd, "TIFF Directory at offset 0x%lx (%lu)\n", + (unsigned long)tif->tif_diroff, (unsigned long)tif->tif_diroff); + if (TIFFFieldSet(tif,FIELD_SUBFILETYPE)) { + fprintf(fd, " Subfile Type:"); + sep = " "; + if (td->td_subfiletype & FILETYPE_REDUCEDIMAGE) { + fprintf(fd, "%sreduced-resolution image", sep); + sep = "/"; + } + if (td->td_subfiletype & FILETYPE_PAGE) { + fprintf(fd, "%smulti-page document", sep); + sep = "/"; + } + if (td->td_subfiletype & FILETYPE_MASK) + fprintf(fd, "%stransparency mask", sep); + fprintf(fd, " (%lu = 0x%lx)\n", + (long) td->td_subfiletype, (long) td->td_subfiletype); + } + if (TIFFFieldSet(tif,FIELD_IMAGEDIMENSIONS)) { + fprintf(fd, " Image Width: %lu Image Length: %lu", + (unsigned long) td->td_imagewidth, (unsigned long) td->td_imagelength); + if (TIFFFieldSet(tif,FIELD_IMAGEDEPTH)) + fprintf(fd, " Image Depth: %lu", + (unsigned long) td->td_imagedepth); + fprintf(fd, "\n"); + } + if (TIFFFieldSet(tif,FIELD_TILEDIMENSIONS)) { + fprintf(fd, " Tile Width: %lu Tile Length: %lu", + (unsigned long) td->td_tilewidth, (unsigned long) td->td_tilelength); + if (TIFFFieldSet(tif,FIELD_TILEDEPTH)) + fprintf(fd, " Tile Depth: %lu", + (unsigned long) td->td_tiledepth); + fprintf(fd, "\n"); + } + if (TIFFFieldSet(tif,FIELD_RESOLUTION)) { + fprintf(fd, " Resolution: %g, %g", + td->td_xresolution, td->td_yresolution); + if (TIFFFieldSet(tif,FIELD_RESOLUTIONUNIT)) { + switch (td->td_resolutionunit) { + case RESUNIT_NONE: + fprintf(fd, " (unitless)"); + break; + case RESUNIT_INCH: + fprintf(fd, " pixels/inch"); + break; + case RESUNIT_CENTIMETER: + fprintf(fd, " pixels/cm"); + break; + default: + fprintf(fd, " (unit %u = 0x%x)", + td->td_resolutionunit, + td->td_resolutionunit); + break; + } + } + fprintf(fd, "\n"); + } + if (TIFFFieldSet(tif,FIELD_POSITION)) + fprintf(fd, " Position: %g, %g\n", + td->td_xposition, td->td_yposition); + if (TIFFFieldSet(tif,FIELD_BITSPERSAMPLE)) + fprintf(fd, " Bits/Sample: %u\n", td->td_bitspersample); + if (TIFFFieldSet(tif,FIELD_SAMPLEFORMAT)) { + fprintf(fd, " Sample Format: "); + switch (td->td_sampleformat) { + case SAMPLEFORMAT_VOID: + fprintf(fd, "void\n"); + break; + case SAMPLEFORMAT_INT: + fprintf(fd, "signed integer\n"); + break; + case SAMPLEFORMAT_UINT: + fprintf(fd, "unsigned integer\n"); + break; + case SAMPLEFORMAT_IEEEFP: + fprintf(fd, "IEEE floating point\n"); + break; + case SAMPLEFORMAT_COMPLEXINT: + fprintf(fd, "complex signed integer\n"); + break; + case SAMPLEFORMAT_COMPLEXIEEEFP: + fprintf(fd, "complex IEEE floating point\n"); + break; + default: + fprintf(fd, "%u (0x%x)\n", + td->td_sampleformat, td->td_sampleformat); + break; + } + } + if (TIFFFieldSet(tif,FIELD_COMPRESSION)) { + const TIFFCodec* c = TIFFFindCODEC(td->td_compression); + fprintf(fd, " Compression Scheme: "); + if (c) + fprintf(fd, "%s\n", c->name); + else + fprintf(fd, "%u (0x%x)\n", + td->td_compression, td->td_compression); + } + if (TIFFFieldSet(tif,FIELD_PHOTOMETRIC)) { + fprintf(fd, " Photometric Interpretation: "); + if (td->td_photometric < NPHOTONAMES) + fprintf(fd, "%s\n", photoNames[td->td_photometric]); + else { + switch (td->td_photometric) { + case PHOTOMETRIC_LOGL: + fprintf(fd, "CIE Log2(L)\n"); + break; + case PHOTOMETRIC_LOGLUV: + fprintf(fd, "CIE Log2(L) (u',v')\n"); + break; + default: + fprintf(fd, "%u (0x%x)\n", + td->td_photometric, td->td_photometric); + break; + } + } + } + if (TIFFFieldSet(tif,FIELD_EXTRASAMPLES) && td->td_extrasamples) { + fprintf(fd, " Extra Samples: %u<", td->td_extrasamples); + sep = ""; + for (i = 0; i < td->td_extrasamples; i++) { + switch (td->td_sampleinfo[i]) { + case EXTRASAMPLE_UNSPECIFIED: + fprintf(fd, "%sunspecified", sep); + break; + case EXTRASAMPLE_ASSOCALPHA: + fprintf(fd, "%sassoc-alpha", sep); + break; + case EXTRASAMPLE_UNASSALPHA: + fprintf(fd, "%sunassoc-alpha", sep); + break; + default: + fprintf(fd, "%s%u (0x%x)", sep, + td->td_sampleinfo[i], td->td_sampleinfo[i]); + break; + } + sep = ", "; + } + fprintf(fd, ">\n"); + } + if (TIFFFieldSet(tif,FIELD_INKNAMES)) { + char* cp; + fprintf(fd, " Ink Names: "); + i = td->td_samplesperpixel; + sep = ""; + for (cp = td->td_inknames; i > 0; cp = strchr(cp,'\0')+1, i--) { + fputs(sep, fd); + _TIFFprintAscii(fd, cp); + sep = ", "; + } + fputs("\n", fd); + } + if (TIFFFieldSet(tif,FIELD_THRESHHOLDING)) { + fprintf(fd, " Thresholding: "); + switch (td->td_threshholding) { + case THRESHHOLD_BILEVEL: + fprintf(fd, "bilevel art scan\n"); + break; + case THRESHHOLD_HALFTONE: + fprintf(fd, "halftone or dithered scan\n"); + break; + case THRESHHOLD_ERRORDIFFUSE: + fprintf(fd, "error diffused\n"); + break; + default: + fprintf(fd, "%u (0x%x)\n", + td->td_threshholding, td->td_threshholding); + break; + } + } + if (TIFFFieldSet(tif,FIELD_FILLORDER)) { + fprintf(fd, " FillOrder: "); + switch (td->td_fillorder) { + case FILLORDER_MSB2LSB: + fprintf(fd, "msb-to-lsb\n"); + break; + case FILLORDER_LSB2MSB: + fprintf(fd, "lsb-to-msb\n"); + break; + default: + fprintf(fd, "%u (0x%x)\n", + td->td_fillorder, td->td_fillorder); + break; + } + } + if (TIFFFieldSet(tif,FIELD_YCBCRSUBSAMPLING)) + { + /* + * For hacky reasons (see tif_jpeg.c - JPEGFixupTestSubsampling), + * we need to fetch this rather than trust what is in our + * structures. + */ + uint16 subsampling[2]; + + TIFFGetField( tif, TIFFTAG_YCBCRSUBSAMPLING, + subsampling + 0, subsampling + 1 ); + fprintf(fd, " YCbCr Subsampling: %u, %u\n", + subsampling[0], subsampling[1] ); + } + if (TIFFFieldSet(tif,FIELD_YCBCRPOSITIONING)) { + fprintf(fd, " YCbCr Positioning: "); + switch (td->td_ycbcrpositioning) { + case YCBCRPOSITION_CENTERED: + fprintf(fd, "centered\n"); + break; + case YCBCRPOSITION_COSITED: + fprintf(fd, "cosited\n"); + break; + default: + fprintf(fd, "%u (0x%x)\n", + td->td_ycbcrpositioning, td->td_ycbcrpositioning); + break; + } + } + if (TIFFFieldSet(tif,FIELD_HALFTONEHINTS)) + fprintf(fd, " Halftone Hints: light %u dark %u\n", + td->td_halftonehints[0], td->td_halftonehints[1]); + if (TIFFFieldSet(tif,FIELD_ORIENTATION)) { + fprintf(fd, " Orientation: "); + if (td->td_orientation < NORIENTNAMES) + fprintf(fd, "%s\n", orientNames[td->td_orientation]); + else + fprintf(fd, "%u (0x%x)\n", + td->td_orientation, td->td_orientation); + } + if (TIFFFieldSet(tif,FIELD_SAMPLESPERPIXEL)) + fprintf(fd, " Samples/Pixel: %u\n", td->td_samplesperpixel); + if (TIFFFieldSet(tif,FIELD_ROWSPERSTRIP)) { + fprintf(fd, " Rows/Strip: "); + if (td->td_rowsperstrip == (uint32) -1) + fprintf(fd, "(infinite)\n"); + else + fprintf(fd, "%lu\n", (unsigned long) td->td_rowsperstrip); + } + if (TIFFFieldSet(tif,FIELD_MINSAMPLEVALUE)) + fprintf(fd, " Min Sample Value: %u\n", td->td_minsamplevalue); + if (TIFFFieldSet(tif,FIELD_MAXSAMPLEVALUE)) + fprintf(fd, " Max Sample Value: %u\n", td->td_maxsamplevalue); + if (TIFFFieldSet(tif,FIELD_SMINSAMPLEVALUE)) + fprintf(fd, " SMin Sample Value: %g\n", + td->td_sminsamplevalue); + if (TIFFFieldSet(tif,FIELD_SMAXSAMPLEVALUE)) + fprintf(fd, " SMax Sample Value: %g\n", + td->td_smaxsamplevalue); + if (TIFFFieldSet(tif,FIELD_PLANARCONFIG)) { + fprintf(fd, " Planar Configuration: "); + switch (td->td_planarconfig) { + case PLANARCONFIG_CONTIG: + fprintf(fd, "single image plane\n"); + break; + case PLANARCONFIG_SEPARATE: + fprintf(fd, "separate image planes\n"); + break; + default: + fprintf(fd, "%u (0x%x)\n", + td->td_planarconfig, td->td_planarconfig); + break; + } + } + if (TIFFFieldSet(tif,FIELD_PAGENUMBER)) + fprintf(fd, " Page Number: %u-%u\n", + td->td_pagenumber[0], td->td_pagenumber[1]); + if (TIFFFieldSet(tif,FIELD_COLORMAP)) { + fprintf(fd, " Color Map: "); + if (flags & TIFFPRINT_COLORMAP) { + fprintf(fd, "\n"); + n = 1L<td_bitspersample; + for (l = 0; l < n; l++) + fprintf(fd, " %5lu: %5u %5u %5u\n", + l, + td->td_colormap[0][l], + td->td_colormap[1][l], + td->td_colormap[2][l]); + } else + fprintf(fd, "(present)\n"); + } + if (TIFFFieldSet(tif,FIELD_TRANSFERFUNCTION)) { + fprintf(fd, " Transfer Function: "); + if (flags & TIFFPRINT_CURVES) { + fprintf(fd, "\n"); + n = 1L<td_bitspersample; + for (l = 0; l < n; l++) { + fprintf(fd, " %2lu: %5u", + l, td->td_transferfunction[0][l]); + for (i = 1; i < td->td_samplesperpixel; i++) + fprintf(fd, " %5u", + td->td_transferfunction[i][l]); + fputc('\n', fd); + } + } else + fprintf(fd, "(present)\n"); + } + if (TIFFFieldSet(tif, FIELD_SUBIFD) && (td->td_subifd)) { + fprintf(fd, " SubIFD Offsets:"); + for (i = 0; i < td->td_nsubifd; i++) + fprintf(fd, " %5lu", (long) td->td_subifd[i]); + fputc('\n', fd); + } + + /* + ** Custom tag support. + */ + { + int i; + short count; + + count = (short) TIFFGetTagListCount(tif); + for(i = 0; i < count; i++) { + ttag_t tag = TIFFGetTagListEntry(tif, i); + const TIFFFieldInfo *fip; + uint32 value_count; + int mem_alloc = 0; + void *raw_data; + + fip = TIFFFieldWithTag(tif, tag); + if(fip == NULL) + continue; + + if(fip->field_passcount) { + if(TIFFGetField(tif, tag, &value_count, &raw_data) != 1) + continue; + } else { + if (fip->field_readcount == TIFF_VARIABLE + || fip->field_readcount == TIFF_VARIABLE2) + value_count = 1; + else if (fip->field_readcount == TIFF_SPP) + value_count = td->td_samplesperpixel; + else + value_count = fip->field_readcount; + if ((fip->field_type == TIFF_ASCII + || fip->field_readcount == TIFF_VARIABLE + || fip->field_readcount == TIFF_VARIABLE2 + || fip->field_readcount == TIFF_SPP + || value_count > 1) + && fip->field_tag != TIFFTAG_PAGENUMBER + && fip->field_tag != TIFFTAG_HALFTONEHINTS + && fip->field_tag != TIFFTAG_YCBCRSUBSAMPLING + && fip->field_tag != TIFFTAG_DOTRANGE) { + if(TIFFGetField(tif, tag, &raw_data) != 1) + continue; + } else if (fip->field_tag != TIFFTAG_PAGENUMBER + && fip->field_tag != TIFFTAG_HALFTONEHINTS + && fip->field_tag != TIFFTAG_YCBCRSUBSAMPLING + && fip->field_tag != TIFFTAG_DOTRANGE) { + raw_data = _TIFFmalloc( + _TIFFDataSize(fip->field_type) + * value_count); + mem_alloc = 1; + if(TIFFGetField(tif, tag, raw_data) != 1) { + _TIFFfree(raw_data); + continue; + } + } else { + /* + * XXX: Should be fixed and removed, see the + * notes related to TIFFTAG_PAGENUMBER, + * TIFFTAG_HALFTONEHINTS, + * TIFFTAG_YCBCRSUBSAMPLING and + * TIFFTAG_DOTRANGE tags in tif_dir.c. */ + char *tmp; + raw_data = _TIFFmalloc( + _TIFFDataSize(fip->field_type) + * value_count); + tmp = raw_data; + mem_alloc = 1; + if(TIFFGetField(tif, tag, tmp, + tmp + _TIFFDataSize(fip->field_type)) != 1) { + _TIFFfree(raw_data); + continue; + } + } + } + + /* + * Catch the tags which needs to be specially handled and + * pretty print them. If tag not handled in + * _TIFFPrettyPrintField() fall down and print it as any other + * tag. + */ + if (_TIFFPrettyPrintField(tif, fd, tag, value_count, raw_data)) { + if(mem_alloc) + _TIFFfree(raw_data); + continue; + } + else + _TIFFPrintField(fd, fip, value_count, raw_data); + + if(mem_alloc) + _TIFFfree(raw_data); + } + } + + if (tif->tif_tagmethods.printdir) + (*tif->tif_tagmethods.printdir)(tif, fd, flags); + if ((flags & TIFFPRINT_STRIPS) && + TIFFFieldSet(tif,FIELD_STRIPOFFSETS)) { + tstrip_t s; + + fprintf(fd, " %lu %s:\n", + (long) td->td_nstrips, + isTiled(tif) ? "Tiles" : "Strips"); + for (s = 0; s < td->td_nstrips; s++) + fprintf(fd, " %3lu: [%8lu, %8lu]\n", + (unsigned long) s, + (unsigned long) td->td_stripoffset[s], + (unsigned long) td->td_stripbytecount[s]); + } +} + +void +_TIFFprintAscii(FILE* fd, const char* cp) +{ + for (; *cp != '\0'; cp++) { + const char* tp; + + if (isprint((int)*cp)) { + fputc(*cp, fd); + continue; + } + for (tp = "\tt\bb\rr\nn\vv"; *tp; tp++) + if (*tp++ == *cp) + break; + if (*tp) + fprintf(fd, "\\%c", *tp); + else + fprintf(fd, "\\%03o", *cp & 0xff); + } +} + +void +_TIFFprintAsciiTag(FILE* fd, const char* name, const char* value) +{ + fprintf(fd, " %s: \"", name); + _TIFFprintAscii(fd, value); + fprintf(fd, "\"\n"); +} + +/* vim: set ts=8 sts=8 sw=8 noet: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tif_read.c b/reactos/dll/3rdparty/libtiff/tif_read.c new file mode 100644 index 00000000000..8ac0ae66cb9 --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tif_read.c @@ -0,0 +1,750 @@ +/* $Id: tif_read.c,v 1.16.2.3 2010-06-09 14:32:47 bfriesen Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library. + * Scanline-oriented Read Support + */ +#include "tiffiop.h" +#include + + int TIFFFillStrip(TIFF*, tstrip_t); + int TIFFFillTile(TIFF*, ttile_t); +static int TIFFStartStrip(TIFF*, tstrip_t); +static int TIFFStartTile(TIFF*, ttile_t); +static int TIFFCheckRead(TIFF*, int); + +#define NOSTRIP ((tstrip_t) -1) /* undefined state */ +#define NOTILE ((ttile_t) -1) /* undefined state */ + +/* + * Seek to a random row+sample in a file. + */ +static int +TIFFSeek(TIFF* tif, uint32 row, tsample_t sample) +{ + register TIFFDirectory *td = &tif->tif_dir; + tstrip_t strip; + + if (row >= td->td_imagelength) { /* out of range */ + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "%lu: Row out of range, max %lu", + (unsigned long) row, + (unsigned long) td->td_imagelength); + return (0); + } + if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { + if (sample >= td->td_samplesperpixel) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "%lu: Sample out of range, max %lu", + (unsigned long) sample, (unsigned long) td->td_samplesperpixel); + return (0); + } + strip = sample*td->td_stripsperimage + row/td->td_rowsperstrip; + } else + strip = row / td->td_rowsperstrip; + if (strip != tif->tif_curstrip) { /* different strip, refill */ + if (!TIFFFillStrip(tif, strip)) + return (0); + } else if (row < tif->tif_row) { + /* + * Moving backwards within the same strip: backup + * to the start and then decode forward (below). + * + * NB: If you're planning on lots of random access within a + * strip, it's better to just read and decode the entire + * strip, and then access the decoded data in a random fashion. + */ + if (!TIFFStartStrip(tif, strip)) + return (0); + } + if (row != tif->tif_row) { + /* + * Seek forward to the desired row. + */ + if (!(*tif->tif_seek)(tif, row - tif->tif_row)) + return (0); + tif->tif_row = row; + } + return (1); +} + +int +TIFFReadScanline(TIFF* tif, tdata_t buf, uint32 row, tsample_t sample) +{ + int e; + + if (!TIFFCheckRead(tif, 0)) + return (-1); + if( (e = TIFFSeek(tif, row, sample)) != 0) { + /* + * Decompress desired row into user buffer. + */ + e = (*tif->tif_decoderow) + (tif, (tidata_t) buf, tif->tif_scanlinesize, sample); + + /* we are now poised at the beginning of the next row */ + tif->tif_row = row + 1; + + if (e) + (*tif->tif_postdecode)(tif, (tidata_t) buf, + tif->tif_scanlinesize); + } + return (e > 0 ? 1 : -1); +} + +/* + * Read a strip of data and decompress the specified + * amount into the user-supplied buffer. + */ +tsize_t +TIFFReadEncodedStrip(TIFF* tif, tstrip_t strip, tdata_t buf, tsize_t size) +{ + TIFFDirectory *td = &tif->tif_dir; + uint32 nrows; + tsize_t stripsize; + tstrip_t sep_strip, strips_per_sep; + + if (!TIFFCheckRead(tif, 0)) + return (-1); + if (strip >= td->td_nstrips) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "%ld: Strip out of range, max %ld", + (long) strip, (long) td->td_nstrips); + return (-1); + } + /* + * Calculate the strip size according to the number of + * rows in the strip (check for truncated last strip on any + * of the separations). + */ + if( td->td_rowsperstrip >= td->td_imagelength ) + strips_per_sep = 1; + else + strips_per_sep = (td->td_imagelength+td->td_rowsperstrip-1) + / td->td_rowsperstrip; + + sep_strip = strip % strips_per_sep; + + if (sep_strip != strips_per_sep-1 || + (nrows = td->td_imagelength % td->td_rowsperstrip) == 0) + nrows = td->td_rowsperstrip; + + stripsize = TIFFVStripSize(tif, nrows); + if (size == (tsize_t) -1) + size = stripsize; + else if (size > stripsize) + size = stripsize; + if (TIFFFillStrip(tif, strip) + && (*tif->tif_decodestrip)(tif, (tidata_t) buf, size, + (tsample_t)(strip / td->td_stripsperimage)) > 0 ) { + (*tif->tif_postdecode)(tif, (tidata_t) buf, size); + return (size); + } else + return ((tsize_t) -1); +} + +static tsize_t +TIFFReadRawStrip1(TIFF* tif, + tstrip_t strip, tdata_t buf, tsize_t size, const char* module) +{ + TIFFDirectory *td = &tif->tif_dir; + + assert((tif->tif_flags&TIFF_NOREADRAW)==0); + if (!isMapped(tif)) { + tsize_t cc; + + if (!SeekOK(tif, td->td_stripoffset[strip])) { + TIFFErrorExt(tif->tif_clientdata, module, + "%s: Seek error at scanline %lu, strip %lu", + tif->tif_name, + (unsigned long) tif->tif_row, (unsigned long) strip); + return (-1); + } + cc = TIFFReadFile(tif, buf, size); + if (cc != size) { + TIFFErrorExt(tif->tif_clientdata, module, + "%s: Read error at scanline %lu; got %lu bytes, expected %lu", + tif->tif_name, + (unsigned long) tif->tif_row, + (unsigned long) cc, + (unsigned long) size); + return (-1); + } + } else { + if (td->td_stripoffset[strip] + size > tif->tif_size) { + TIFFErrorExt(tif->tif_clientdata, module, + "%s: Read error at scanline %lu, strip %lu; got %lu bytes, expected %lu", + tif->tif_name, + (unsigned long) tif->tif_row, + (unsigned long) strip, + (unsigned long) tif->tif_size - td->td_stripoffset[strip], + (unsigned long) size); + return (-1); + } + _TIFFmemcpy(buf, tif->tif_base + td->td_stripoffset[strip], + size); + } + return (size); +} + +/* + * Read a strip of data from the file. + */ +tsize_t +TIFFReadRawStrip(TIFF* tif, tstrip_t strip, tdata_t buf, tsize_t size) +{ + static const char module[] = "TIFFReadRawStrip"; + TIFFDirectory *td = &tif->tif_dir; + /* + * FIXME: butecount should have tsize_t type, but for now libtiff + * defines tsize_t as a signed 32-bit integer and we are losing + * ability to read arrays larger than 2^31 bytes. So we are using + * uint32 instead of tsize_t here. + */ + uint32 bytecount; + + if (!TIFFCheckRead(tif, 0)) + return ((tsize_t) -1); + if (strip >= td->td_nstrips) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "%lu: Strip out of range, max %lu", + (unsigned long) strip, + (unsigned long) td->td_nstrips); + return ((tsize_t) -1); + } + if (tif->tif_flags&TIFF_NOREADRAW) + { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Compression scheme does not support access to raw uncompressed data"); + return ((tsize_t) -1); + } + bytecount = td->td_stripbytecount[strip]; + if (bytecount <= 0) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "%lu: Invalid strip byte count, strip %lu", + (unsigned long) bytecount, (unsigned long) strip); + return ((tsize_t) -1); + } + if (size != (tsize_t)-1 && (uint32)size < bytecount) + bytecount = size; + return (TIFFReadRawStrip1(tif, strip, buf, bytecount, module)); +} + +/* + * Read the specified strip and setup for decoding. The data buffer is + * expanded, as necessary, to hold the strip's data. + */ +int +TIFFFillStrip(TIFF* tif, tstrip_t strip) +{ + static const char module[] = "TIFFFillStrip"; + TIFFDirectory *td = &tif->tif_dir; + + if ((tif->tif_flags&TIFF_NOREADRAW)==0) + { + /* + * FIXME: butecount should have tsize_t type, but for now + * libtiff defines tsize_t as a signed 32-bit integer and we + * are losing ability to read arrays larger than 2^31 bytes. + * So we are using uint32 instead of tsize_t here. + */ + uint32 bytecount = td->td_stripbytecount[strip]; + if (bytecount <= 0) { + TIFFErrorExt(tif->tif_clientdata, module, + "%s: Invalid strip byte count %lu, strip %lu", + tif->tif_name, (unsigned long) bytecount, + (unsigned long) strip); + return (0); + } + if (isMapped(tif) && + (isFillOrder(tif, td->td_fillorder) + || (tif->tif_flags & TIFF_NOBITREV))) { + /* + * The image is mapped into memory and we either don't + * need to flip bits or the compression routine is + * going to handle this operation itself. In this + * case, avoid copying the raw data and instead just + * reference the data from the memory mapped file + * image. This assumes that the decompression + * routines do not modify the contents of the raw data + * buffer (if they try to, the application will get a + * fault since the file is mapped read-only). + */ + if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) + _TIFFfree(tif->tif_rawdata); + tif->tif_flags &= ~TIFF_MYBUFFER; + /* + * We must check for overflow, potentially causing + * an OOB read. Instead of simple + * + * td->td_stripoffset[strip]+bytecount > tif->tif_size + * + * comparison (which can overflow) we do the following + * two comparisons: + */ + if (bytecount > tif->tif_size || + td->td_stripoffset[strip] > tif->tif_size - bytecount) { + /* + * This error message might seem strange, but + * it's what would happen if a read were done + * instead. + */ + TIFFErrorExt(tif->tif_clientdata, module, + + "%s: Read error on strip %lu; " + "got %lu bytes, expected %lu", + tif->tif_name, (unsigned long) strip, + (unsigned long) tif->tif_size - td->td_stripoffset[strip], + (unsigned long) bytecount); + tif->tif_curstrip = NOSTRIP; + return (0); + } + tif->tif_rawdatasize = bytecount; + tif->tif_rawdata = tif->tif_base + td->td_stripoffset[strip]; + } else { + /* + * Expand raw data buffer, if needed, to hold data + * strip coming from file (perhaps should set upper + * bound on the size of a buffer we'll use?). + */ + if (bytecount > (uint32)tif->tif_rawdatasize) { + tif->tif_curstrip = NOSTRIP; + if ((tif->tif_flags & TIFF_MYBUFFER) == 0) { + TIFFErrorExt(tif->tif_clientdata, + module, + "%s: Data buffer too small to hold strip %lu", + tif->tif_name, + (unsigned long) strip); + return (0); + } + if (!TIFFReadBufferSetup(tif, 0, + TIFFroundup(bytecount, 1024))) + return (0); + } + if ((uint32)TIFFReadRawStrip1(tif, strip, + (unsigned char *)tif->tif_rawdata, + bytecount, module) != bytecount) + return (0); + if (!isFillOrder(tif, td->td_fillorder) && + (tif->tif_flags & TIFF_NOBITREV) == 0) + TIFFReverseBits(tif->tif_rawdata, bytecount); + } + } + return (TIFFStartStrip(tif, strip)); +} + +/* + * Tile-oriented Read Support + * Contributed by Nancy Cam (Silicon Graphics). + */ + +/* + * Read and decompress a tile of data. The + * tile is selected by the (x,y,z,s) coordinates. + */ +tsize_t +TIFFReadTile(TIFF* tif, + tdata_t buf, uint32 x, uint32 y, uint32 z, tsample_t s) +{ + if (!TIFFCheckRead(tif, 1) || !TIFFCheckTile(tif, x, y, z, s)) + return (-1); + return (TIFFReadEncodedTile(tif, + TIFFComputeTile(tif, x, y, z, s), buf, (tsize_t) -1)); +} + +/* + * Read a tile of data and decompress the specified + * amount into the user-supplied buffer. + */ +tsize_t +TIFFReadEncodedTile(TIFF* tif, ttile_t tile, tdata_t buf, tsize_t size) +{ + TIFFDirectory *td = &tif->tif_dir; + tsize_t tilesize = tif->tif_tilesize; + + if (!TIFFCheckRead(tif, 1)) + return (-1); + if (tile >= td->td_nstrips) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "%ld: Tile out of range, max %ld", + (long) tile, (unsigned long) td->td_nstrips); + return (-1); + } + if (size == (tsize_t) -1) + size = tilesize; + else if (size > tilesize) + size = tilesize; + if (TIFFFillTile(tif, tile) && (*tif->tif_decodetile)(tif, + (tidata_t) buf, size, (tsample_t)(tile/td->td_stripsperimage))) { + (*tif->tif_postdecode)(tif, (tidata_t) buf, size); + return (size); + } else + return (-1); +} + +static tsize_t +TIFFReadRawTile1(TIFF* tif, + ttile_t tile, tdata_t buf, tsize_t size, const char* module) +{ + TIFFDirectory *td = &tif->tif_dir; + + assert((tif->tif_flags&TIFF_NOREADRAW)==0); + if (!isMapped(tif)) { + tsize_t cc; + + if (!SeekOK(tif, td->td_stripoffset[tile])) { + TIFFErrorExt(tif->tif_clientdata, module, + "%s: Seek error at row %ld, col %ld, tile %ld", + tif->tif_name, + (long) tif->tif_row, + (long) tif->tif_col, + (long) tile); + return ((tsize_t) -1); + } + cc = TIFFReadFile(tif, buf, size); + if (cc != size) { + TIFFErrorExt(tif->tif_clientdata, module, + "%s: Read error at row %ld, col %ld; got %lu bytes, expected %lu", + tif->tif_name, + (long) tif->tif_row, + (long) tif->tif_col, + (unsigned long) cc, + (unsigned long) size); + return ((tsize_t) -1); + } + } else { + if (td->td_stripoffset[tile] + size > tif->tif_size) { + TIFFErrorExt(tif->tif_clientdata, module, + "%s: Read error at row %ld, col %ld, tile %ld; got %lu bytes, expected %lu", + tif->tif_name, + (long) tif->tif_row, + (long) tif->tif_col, + (long) tile, + (unsigned long) tif->tif_size - td->td_stripoffset[tile], + (unsigned long) size); + return ((tsize_t) -1); + } + _TIFFmemcpy(buf, tif->tif_base + td->td_stripoffset[tile], size); + } + return (size); +} + +/* + * Read a tile of data from the file. + */ +tsize_t +TIFFReadRawTile(TIFF* tif, ttile_t tile, tdata_t buf, tsize_t size) +{ + static const char module[] = "TIFFReadRawTile"; + TIFFDirectory *td = &tif->tif_dir; + /* + * FIXME: butecount should have tsize_t type, but for now libtiff + * defines tsize_t as a signed 32-bit integer and we are losing + * ability to read arrays larger than 2^31 bytes. So we are using + * uint32 instead of tsize_t here. + */ + uint32 bytecount; + + if (!TIFFCheckRead(tif, 1)) + return ((tsize_t) -1); + if (tile >= td->td_nstrips) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "%lu: Tile out of range, max %lu", + (unsigned long) tile, (unsigned long) td->td_nstrips); + return ((tsize_t) -1); + } + if (tif->tif_flags&TIFF_NOREADRAW) + { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Compression scheme does not support access to raw uncompressed data"); + return ((tsize_t) -1); + } + bytecount = td->td_stripbytecount[tile]; + if (size != (tsize_t) -1 && (uint32)size < bytecount) + bytecount = size; + return (TIFFReadRawTile1(tif, tile, buf, bytecount, module)); +} + +/* + * Read the specified tile and setup for decoding. The data buffer is + * expanded, as necessary, to hold the tile's data. + */ +int +TIFFFillTile(TIFF* tif, ttile_t tile) +{ + static const char module[] = "TIFFFillTile"; + TIFFDirectory *td = &tif->tif_dir; + + if ((tif->tif_flags&TIFF_NOREADRAW)==0) + { + /* + * FIXME: butecount should have tsize_t type, but for now + * libtiff defines tsize_t as a signed 32-bit integer and we + * are losing ability to read arrays larger than 2^31 bytes. + * So we are using uint32 instead of tsize_t here. + */ + uint32 bytecount = td->td_stripbytecount[tile]; + if (bytecount <= 0) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "%lu: Invalid tile byte count, tile %lu", + (unsigned long) bytecount, (unsigned long) tile); + return (0); + } + if (isMapped(tif) && + (isFillOrder(tif, td->td_fillorder) + || (tif->tif_flags & TIFF_NOBITREV))) { + /* + * The image is mapped into memory and we either don't + * need to flip bits or the compression routine is + * going to handle this operation itself. In this + * case, avoid copying the raw data and instead just + * reference the data from the memory mapped file + * image. This assumes that the decompression + * routines do not modify the contents of the raw data + * buffer (if they try to, the application will get a + * fault since the file is mapped read-only). + */ + if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) + _TIFFfree(tif->tif_rawdata); + tif->tif_flags &= ~TIFF_MYBUFFER; + /* + * We must check for overflow, potentially causing + * an OOB read. Instead of simple + * + * td->td_stripoffset[tile]+bytecount > tif->tif_size + * + * comparison (which can overflow) we do the following + * two comparisons: + */ + if (bytecount > tif->tif_size || + td->td_stripoffset[tile] > tif->tif_size - bytecount) { + tif->tif_curtile = NOTILE; + return (0); + } + tif->tif_rawdatasize = bytecount; + tif->tif_rawdata = + tif->tif_base + td->td_stripoffset[tile]; + } else { + /* + * Expand raw data buffer, if needed, to hold data + * tile coming from file (perhaps should set upper + * bound on the size of a buffer we'll use?). + */ + if (bytecount > (uint32)tif->tif_rawdatasize) { + tif->tif_curtile = NOTILE; + if ((tif->tif_flags & TIFF_MYBUFFER) == 0) { + TIFFErrorExt(tif->tif_clientdata, + module, + "%s: Data buffer too small to hold tile %ld", + tif->tif_name, + (long) tile); + return (0); + } + if (!TIFFReadBufferSetup(tif, 0, + TIFFroundup(bytecount, 1024))) + return (0); + } + if ((uint32)TIFFReadRawTile1(tif, tile, + (unsigned char *)tif->tif_rawdata, + bytecount, module) != bytecount) + return (0); + if (!isFillOrder(tif, td->td_fillorder) && + (tif->tif_flags & TIFF_NOBITREV) == 0) + TIFFReverseBits(tif->tif_rawdata, bytecount); + } + } + return (TIFFStartTile(tif, tile)); +} + +/* + * Setup the raw data buffer in preparation for + * reading a strip of raw data. If the buffer + * is specified as zero, then a buffer of appropriate + * size is allocated by the library. Otherwise, + * the client must guarantee that the buffer is + * large enough to hold any individual strip of + * raw data. + */ +int +TIFFReadBufferSetup(TIFF* tif, tdata_t bp, tsize_t size) +{ + static const char module[] = "TIFFReadBufferSetup"; + + assert((tif->tif_flags&TIFF_NOREADRAW)==0); + if (tif->tif_rawdata) { + if (tif->tif_flags & TIFF_MYBUFFER) + _TIFFfree(tif->tif_rawdata); + tif->tif_rawdata = NULL; + } + + if (bp) { + tif->tif_rawdatasize = size; + tif->tif_rawdata = (tidata_t) bp; + tif->tif_flags &= ~TIFF_MYBUFFER; + } else { + tif->tif_rawdatasize = TIFFroundup(size, 1024); + if (tif->tif_rawdatasize > 0) + tif->tif_rawdata = (tidata_t) _TIFFmalloc(tif->tif_rawdatasize); + tif->tif_flags |= TIFF_MYBUFFER; + } + if ((tif->tif_rawdata == NULL) || (tif->tif_rawdatasize == 0)) { + TIFFErrorExt(tif->tif_clientdata, module, + "%s: No space for data buffer at scanline %ld", + tif->tif_name, (long) tif->tif_row); + tif->tif_rawdatasize = 0; + return (0); + } + return (1); +} + +/* + * Set state to appear as if a + * strip has just been read in. + */ +static int +TIFFStartStrip(TIFF* tif, tstrip_t strip) +{ + TIFFDirectory *td = &tif->tif_dir; + + if ((tif->tif_flags & TIFF_CODERSETUP) == 0) { + if (!(*tif->tif_setupdecode)(tif)) + return (0); + tif->tif_flags |= TIFF_CODERSETUP; + } + tif->tif_curstrip = strip; + tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip; + if (tif->tif_flags&TIFF_NOREADRAW) + { + tif->tif_rawcp = NULL; + tif->tif_rawcc = 0; + } + else + { + tif->tif_rawcp = tif->tif_rawdata; + tif->tif_rawcc = td->td_stripbytecount[strip]; + } + return ((*tif->tif_predecode)(tif, + (tsample_t)(strip / td->td_stripsperimage))); +} + +/* + * Set state to appear as if a + * tile has just been read in. + */ +static int +TIFFStartTile(TIFF* tif, ttile_t tile) +{ + TIFFDirectory *td = &tif->tif_dir; + + if ((tif->tif_flags & TIFF_CODERSETUP) == 0) { + if (!(*tif->tif_setupdecode)(tif)) + return (0); + tif->tif_flags |= TIFF_CODERSETUP; + } + tif->tif_curtile = tile; + tif->tif_row = + (tile % TIFFhowmany(td->td_imagewidth, td->td_tilewidth)) * + td->td_tilelength; + tif->tif_col = + (tile % TIFFhowmany(td->td_imagelength, td->td_tilelength)) * + td->td_tilewidth; + if (tif->tif_flags&TIFF_NOREADRAW) + { + tif->tif_rawcp = NULL; + tif->tif_rawcc = 0; + } + else + { + tif->tif_rawcp = tif->tif_rawdata; + tif->tif_rawcc = td->td_stripbytecount[tile]; + } + return ((*tif->tif_predecode)(tif, + (tsample_t)(tile/td->td_stripsperimage))); +} + +static int +TIFFCheckRead(TIFF* tif, int tiles) +{ + if (tif->tif_mode == O_WRONLY) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "File not open for reading"); + return (0); + } + if (tiles ^ isTiled(tif)) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, tiles ? + "Can not read tiles from a stripped image" : + "Can not read scanlines from a tiled image"); + return (0); + } + return (1); +} + +void +_TIFFNoPostDecode(TIFF* tif, tidata_t buf, tsize_t cc) +{ + (void) tif; (void) buf; (void) cc; +} + +void +_TIFFSwab16BitData(TIFF* tif, tidata_t buf, tsize_t cc) +{ + (void) tif; + assert((cc & 1) == 0); + TIFFSwabArrayOfShort((uint16*) buf, cc/2); +} + +void +_TIFFSwab24BitData(TIFF* tif, tidata_t buf, tsize_t cc) +{ + (void) tif; + assert((cc % 3) == 0); + TIFFSwabArrayOfTriples((uint8*) buf, cc/3); +} + +void +_TIFFSwab32BitData(TIFF* tif, tidata_t buf, tsize_t cc) +{ + (void) tif; + assert((cc & 3) == 0); + TIFFSwabArrayOfLong((uint32*) buf, cc/4); +} + +void +_TIFFSwab64BitData(TIFF* tif, tidata_t buf, tsize_t cc) +{ + (void) tif; + assert((cc & 7) == 0); + TIFFSwabArrayOfDouble((double*) buf, cc/8); +} + +/* vim: set ts=8 sts=8 sw=8 noet: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tif_strip.c b/reactos/dll/3rdparty/libtiff/tif_strip.c new file mode 100644 index 00000000000..63dec6bdace --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tif_strip.c @@ -0,0 +1,370 @@ +/* $Id: tif_strip.c,v 1.19.2.1 2010-06-08 18:50:43 bfriesen Exp $ */ + +/* + * Copyright (c) 1991-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library. + * + * Strip-organized Image Support Routines. + */ +#include "tiffiop.h" + +static uint32 +summarize(TIFF* tif, size_t summand1, size_t summand2, const char* where) +{ + /* + * XXX: We are using casting to uint32 here, bacause sizeof(size_t) + * may be larger than sizeof(uint32) on 64-bit architectures. + */ + uint32 bytes = summand1 + summand2; + + if (bytes - summand1 != summand2) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Integer overflow in %s", where); + bytes = 0; + } + + return (bytes); +} + +static uint32 +multiply(TIFF* tif, size_t nmemb, size_t elem_size, const char* where) +{ + uint32 bytes = nmemb * elem_size; + + if (elem_size && bytes / elem_size != nmemb) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Integer overflow in %s", where); + bytes = 0; + } + + return (bytes); +} + +/* + * Compute which strip a (row,sample) value is in. + */ +tstrip_t +TIFFComputeStrip(TIFF* tif, uint32 row, tsample_t sample) +{ + TIFFDirectory *td = &tif->tif_dir; + tstrip_t strip; + + strip = row / td->td_rowsperstrip; + if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { + if (sample >= td->td_samplesperpixel) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "%lu: Sample out of range, max %lu", + (unsigned long) sample, (unsigned long) td->td_samplesperpixel); + return ((tstrip_t) 0); + } + strip += sample*td->td_stripsperimage; + } + return (strip); +} + +/* + * Compute how many strips are in an image. + */ +tstrip_t +TIFFNumberOfStrips(TIFF* tif) +{ + TIFFDirectory *td = &tif->tif_dir; + tstrip_t nstrips; + + nstrips = (td->td_rowsperstrip == (uint32) -1 ? 1 : + TIFFhowmany(td->td_imagelength, td->td_rowsperstrip)); + if (td->td_planarconfig == PLANARCONFIG_SEPARATE) + nstrips = multiply(tif, nstrips, td->td_samplesperpixel, + "TIFFNumberOfStrips"); + return (nstrips); +} + +/* + * Compute the # bytes in a variable height, row-aligned strip. + */ +tsize_t +TIFFVStripSize(TIFF* tif, uint32 nrows) +{ + TIFFDirectory *td = &tif->tif_dir; + + if (nrows == (uint32) -1) + nrows = td->td_imagelength; + if (td->td_planarconfig == PLANARCONFIG_CONTIG && + td->td_photometric == PHOTOMETRIC_YCBCR && + !isUpSampled(tif)) { + /* + * Packed YCbCr data contain one Cb+Cr for every + * HorizontalSampling*VerticalSampling Y values. + * Must also roundup width and height when calculating + * since images that are not a multiple of the + * horizontal/vertical subsampling area include + * YCbCr data for the extended image. + */ + uint16 ycbcrsubsampling[2]; + tsize_t w, scanline, samplingarea; + + TIFFGetField( tif, TIFFTAG_YCBCRSUBSAMPLING, + ycbcrsubsampling + 0, + ycbcrsubsampling + 1 ); + + samplingarea = ycbcrsubsampling[0]*ycbcrsubsampling[1]; + if (samplingarea == 0) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Invalid YCbCr subsampling"); + return 0; + } + + w = TIFFroundup(td->td_imagewidth, ycbcrsubsampling[0]); + scanline = TIFFhowmany8(multiply(tif, w, td->td_bitspersample, + "TIFFVStripSize")); + nrows = TIFFroundup(nrows, ycbcrsubsampling[1]); + /* NB: don't need TIFFhowmany here 'cuz everything is rounded */ + scanline = multiply(tif, nrows, scanline, "TIFFVStripSize"); + return ((tsize_t) + summarize(tif, scanline, + multiply(tif, 2, scanline / samplingarea, + "TIFFVStripSize"), "TIFFVStripSize")); + } else + return ((tsize_t) multiply(tif, nrows, TIFFScanlineSize(tif), + "TIFFVStripSize")); +} + + +/* + * Compute the # bytes in a raw strip. + */ +tsize_t +TIFFRawStripSize(TIFF* tif, tstrip_t strip) +{ + TIFFDirectory* td = &tif->tif_dir; + tsize_t bytecount = td->td_stripbytecount[strip]; + + if (bytecount <= 0) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "%lu: Invalid strip byte count, strip %lu", + (unsigned long) bytecount, (unsigned long) strip); + bytecount = (tsize_t) -1; + } + + return bytecount; +} + +/* + * Compute the # bytes in a (row-aligned) strip. + * + * Note that if RowsPerStrip is larger than the + * recorded ImageLength, then the strip size is + * truncated to reflect the actual space required + * to hold the strip. + */ +tsize_t +TIFFStripSize(TIFF* tif) +{ + TIFFDirectory* td = &tif->tif_dir; + uint32 rps = td->td_rowsperstrip; + if (rps > td->td_imagelength) + rps = td->td_imagelength; + return (TIFFVStripSize(tif, rps)); +} + +/* + * Compute a default strip size based on the image + * characteristics and a requested value. If the + * request is <1 then we choose a strip size according + * to certain heuristics. + */ +uint32 +TIFFDefaultStripSize(TIFF* tif, uint32 request) +{ + return (*tif->tif_defstripsize)(tif, request); +} + +uint32 +_TIFFDefaultStripSize(TIFF* tif, uint32 s) +{ + if ((int32) s < 1) { + /* + * If RowsPerStrip is unspecified, try to break the + * image up into strips that are approximately + * STRIP_SIZE_DEFAULT bytes long. + */ + tsize_t scanline = TIFFScanlineSize(tif); + s = (uint32)STRIP_SIZE_DEFAULT / (scanline == 0 ? 1 : scanline); + if (s == 0) /* very wide images */ + s = 1; + } + return (s); +} + +/* + * Return the number of bytes to read/write in a call to + * one of the scanline-oriented i/o routines. Note that + * this number may be 1/samples-per-pixel if data is + * stored as separate planes. + */ +tsize_t +TIFFScanlineSize(TIFF* tif) +{ + TIFFDirectory *td = &tif->tif_dir; + tsize_t scanline; + + if (td->td_planarconfig == PLANARCONFIG_CONTIG) { + if (td->td_photometric == PHOTOMETRIC_YCBCR + && !isUpSampled(tif)) { + uint16 ycbcrsubsampling[2]; + + TIFFGetField(tif, TIFFTAG_YCBCRSUBSAMPLING, + ycbcrsubsampling + 0, + ycbcrsubsampling + 1); + + if (ycbcrsubsampling[0] == 0) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Invalid YCbCr subsampling"); + return 0; + } + + scanline = TIFFroundup(td->td_imagewidth, + ycbcrsubsampling[0]); + scanline = TIFFhowmany8(multiply(tif, scanline, + td->td_bitspersample, + "TIFFScanlineSize")); + return ((tsize_t) + summarize(tif, scanline, + multiply(tif, 2, + scanline / ycbcrsubsampling[0], + "TIFFVStripSize"), + "TIFFVStripSize")); + } else { + scanline = multiply(tif, td->td_imagewidth, + td->td_samplesperpixel, + "TIFFScanlineSize"); + } + } else + scanline = td->td_imagewidth; + return ((tsize_t) TIFFhowmany8(multiply(tif, scanline, + td->td_bitspersample, + "TIFFScanlineSize"))); +} + +/* + * Some stuff depends on this older version of TIFFScanlineSize + * TODO: resolve this + */ +tsize_t +TIFFOldScanlineSize(TIFF* tif) +{ + TIFFDirectory *td = &tif->tif_dir; + tsize_t scanline; + + scanline = multiply (tif, td->td_bitspersample, td->td_imagewidth, + "TIFFScanlineSize"); + if (td->td_planarconfig == PLANARCONFIG_CONTIG) + scanline = multiply (tif, scanline, td->td_samplesperpixel, + "TIFFScanlineSize"); + return ((tsize_t) TIFFhowmany8(scanline)); +} + +/* + * Return the number of bytes to read/write in a call to + * one of the scanline-oriented i/o routines. Note that + * this number may be 1/samples-per-pixel if data is + * stored as separate planes. + * The ScanlineSize in case of YCbCrSubsampling is defined as the + * strip size divided by the strip height, i.e. the size of a pack of vertical + * subsampling lines divided by vertical subsampling. It should thus make + * sense when multiplied by a multiple of vertical subsampling. + * Some stuff depends on this newer version of TIFFScanlineSize + * TODO: resolve this + */ +tsize_t +TIFFNewScanlineSize(TIFF* tif) +{ + TIFFDirectory *td = &tif->tif_dir; + tsize_t scanline; + + if (td->td_planarconfig == PLANARCONFIG_CONTIG) { + if (td->td_photometric == PHOTOMETRIC_YCBCR + && !isUpSampled(tif)) { + uint16 ycbcrsubsampling[2]; + + TIFFGetField(tif, TIFFTAG_YCBCRSUBSAMPLING, + ycbcrsubsampling + 0, + ycbcrsubsampling + 1); + + if (ycbcrsubsampling[0]*ycbcrsubsampling[1] == 0) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Invalid YCbCr subsampling"); + return 0; + } + + return((tsize_t) ((((td->td_imagewidth+ycbcrsubsampling[0]-1) + /ycbcrsubsampling[0]) + *(ycbcrsubsampling[0]*ycbcrsubsampling[1]+2) + *td->td_bitspersample+7) + /8)/ycbcrsubsampling[1]); + + } else { + scanline = multiply(tif, td->td_imagewidth, + td->td_samplesperpixel, + "TIFFScanlineSize"); + } + } else + scanline = td->td_imagewidth; + return ((tsize_t) TIFFhowmany8(multiply(tif, scanline, + td->td_bitspersample, + "TIFFScanlineSize"))); +} + +/* + * Return the number of bytes required to store a complete + * decoded and packed raster scanline (as opposed to the + * I/O size returned by TIFFScanlineSize which may be less + * if data is store as separate planes). + */ +tsize_t +TIFFRasterScanlineSize(TIFF* tif) +{ + TIFFDirectory *td = &tif->tif_dir; + tsize_t scanline; + + scanline = multiply (tif, td->td_bitspersample, td->td_imagewidth, + "TIFFRasterScanlineSize"); + if (td->td_planarconfig == PLANARCONFIG_CONTIG) { + scanline = multiply (tif, scanline, td->td_samplesperpixel, + "TIFFRasterScanlineSize"); + return ((tsize_t) TIFFhowmany8(scanline)); + } else + return ((tsize_t) multiply (tif, TIFFhowmany8(scanline), + td->td_samplesperpixel, + "TIFFRasterScanlineSize")); +} + +/* vim: set ts=8 sts=8 sw=8 noet: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tif_swab.c b/reactos/dll/3rdparty/libtiff/tif_swab.c new file mode 100644 index 00000000000..e4f1a6d1e23 --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tif_swab.c @@ -0,0 +1,242 @@ +/* $Id: tif_swab.c,v 1.4.2.1 2010-06-08 18:50:43 bfriesen Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library Bit & Byte Swapping Support. + * + * XXX We assume short = 16-bits and long = 32-bits XXX + */ +#include "tiffiop.h" + +#ifndef TIFFSwabShort +void +TIFFSwabShort(uint16* wp) +{ + register unsigned char* cp = (unsigned char*) wp; + unsigned char t; + + t = cp[1]; cp[1] = cp[0]; cp[0] = t; +} +#endif + +#ifndef TIFFSwabLong +void +TIFFSwabLong(uint32* lp) +{ + register unsigned char* cp = (unsigned char*) lp; + unsigned char t; + + t = cp[3]; cp[3] = cp[0]; cp[0] = t; + t = cp[2]; cp[2] = cp[1]; cp[1] = t; +} +#endif + +#ifndef TIFFSwabArrayOfShort +void +TIFFSwabArrayOfShort(uint16* wp, register unsigned long n) +{ + register unsigned char* cp; + register unsigned char t; + + /* XXX unroll loop some */ + while (n-- > 0) { + cp = (unsigned char*) wp; + t = cp[1]; cp[1] = cp[0]; cp[0] = t; + wp++; + } +} +#endif + +#ifndef TIFFSwabArrayOfTriples +void +TIFFSwabArrayOfTriples(uint8* tp, unsigned long n) +{ + unsigned char* cp; + unsigned char t; + + /* XXX unroll loop some */ + while (n-- > 0) { + cp = (unsigned char*) tp; + t = cp[2]; cp[2] = cp[0]; cp[0] = t; + tp += 3; + } +} +#endif + +#ifndef TIFFSwabArrayOfLong +void +TIFFSwabArrayOfLong(register uint32* lp, register unsigned long n) +{ + register unsigned char *cp; + register unsigned char t; + + /* XXX unroll loop some */ + while (n-- > 0) { + cp = (unsigned char *)lp; + t = cp[3]; cp[3] = cp[0]; cp[0] = t; + t = cp[2]; cp[2] = cp[1]; cp[1] = t; + lp++; + } +} +#endif + +#ifndef TIFFSwabDouble +void +TIFFSwabDouble(double *dp) +{ + register uint32* lp = (uint32*) dp; + uint32 t; + + TIFFSwabArrayOfLong(lp, 2); + t = lp[0]; lp[0] = lp[1]; lp[1] = t; +} +#endif + +#ifndef TIFFSwabArrayOfDouble +void +TIFFSwabArrayOfDouble(double* dp, register unsigned long n) +{ + register uint32* lp = (uint32*) dp; + register uint32 t; + + TIFFSwabArrayOfLong(lp, n + n); + while (n-- > 0) { + t = lp[0]; lp[0] = lp[1]; lp[1] = t; + lp += 2; + } +} +#endif + +/* + * Bit reversal tables. TIFFBitRevTable[] gives + * the bit reversed value of . Used in various + * places in the library when the FillOrder requires + * bit reversal of byte values (e.g. CCITT Fax 3 + * encoding/decoding). TIFFNoBitRevTable is provided + * for algorithms that want an equivalent table that + * do not reverse bit values. + */ +static const unsigned char TIFFBitRevTable[256] = { + 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, + 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, + 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, + 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, + 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, + 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, + 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, + 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, + 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, + 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, + 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, + 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, + 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, + 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, + 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, + 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, + 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, + 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, + 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, + 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, + 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, + 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, + 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, + 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, + 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, + 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, + 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, + 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, + 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, + 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, + 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, + 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff +}; +static const unsigned char TIFFNoBitRevTable[256] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, +}; + +const unsigned char* +TIFFGetBitRevTable(int reversed) +{ + return (reversed ? TIFFBitRevTable : TIFFNoBitRevTable); +} + +void +TIFFReverseBits(register unsigned char* cp, register unsigned long n) +{ + for (; n > 8; n -= 8) { + cp[0] = TIFFBitRevTable[cp[0]]; + cp[1] = TIFFBitRevTable[cp[1]]; + cp[2] = TIFFBitRevTable[cp[2]]; + cp[3] = TIFFBitRevTable[cp[3]]; + cp[4] = TIFFBitRevTable[cp[4]]; + cp[5] = TIFFBitRevTable[cp[5]]; + cp[6] = TIFFBitRevTable[cp[6]]; + cp[7] = TIFFBitRevTable[cp[7]]; + cp += 8; + } + while (n-- > 0) + *cp = TIFFBitRevTable[*cp], cp++; +} + +/* vim: set ts=8 sts=8 sw=8 noet: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tif_thunder.c b/reactos/dll/3rdparty/libtiff/tif_thunder.c new file mode 100644 index 00000000000..8e7a1258415 --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tif_thunder.c @@ -0,0 +1,165 @@ +/* $Id: tif_thunder.c,v 1.5.2.1 2010-06-08 18:50:43 bfriesen Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include "tiffiop.h" +#ifdef THUNDER_SUPPORT +/* + * TIFF Library. + * + * ThunderScan 4-bit Compression Algorithm Support + */ + +/* + * ThunderScan uses an encoding scheme designed for + * 4-bit pixel values. Data is encoded in bytes, with + * each byte split into a 2-bit code word and a 6-bit + * data value. The encoding gives raw data, runs of + * pixels, or pixel values encoded as a delta from the + * previous pixel value. For the latter, either 2-bit + * or 3-bit delta values are used, with the deltas packed + * into a single byte. + */ +#define THUNDER_DATA 0x3f /* mask for 6-bit data */ +#define THUNDER_CODE 0xc0 /* mask for 2-bit code word */ +/* code values */ +#define THUNDER_RUN 0x00 /* run of pixels w/ encoded count */ +#define THUNDER_2BITDELTAS 0x40 /* 3 pixels w/ encoded 2-bit deltas */ +#define DELTA2_SKIP 2 /* skip code for 2-bit deltas */ +#define THUNDER_3BITDELTAS 0x80 /* 2 pixels w/ encoded 3-bit deltas */ +#define DELTA3_SKIP 4 /* skip code for 3-bit deltas */ +#define THUNDER_RAW 0xc0 /* raw data encoded */ + +static const int twobitdeltas[4] = { 0, 1, 0, -1 }; +static const int threebitdeltas[8] = { 0, 1, 2, 3, 0, -3, -2, -1 }; + +#define SETPIXEL(op, v) { \ + lastpixel = (v) & 0xf; \ + if (npixels++ & 1) \ + *op++ |= lastpixel; \ + else \ + op[0] = (tidataval_t) (lastpixel << 4); \ +} + +static int +ThunderDecode(TIFF* tif, tidata_t op, tsize_t maxpixels) +{ + register unsigned char *bp; + register tsize_t cc; + unsigned int lastpixel; + tsize_t npixels; + + bp = (unsigned char *)tif->tif_rawcp; + cc = tif->tif_rawcc; + lastpixel = 0; + npixels = 0; + while (cc > 0 && npixels < maxpixels) { + int n, delta; + + n = *bp++, cc--; + switch (n & THUNDER_CODE) { + case THUNDER_RUN: /* pixel run */ + /* + * Replicate the last pixel n times, + * where n is the lower-order 6 bits. + */ + if (npixels & 1) { + op[0] |= lastpixel; + lastpixel = *op++; npixels++; n--; + } else + lastpixel |= lastpixel << 4; + npixels += n; + if (npixels < maxpixels) { + for (; n > 0; n -= 2) + *op++ = (tidataval_t) lastpixel; + } + if (n == -1) + *--op &= 0xf0; + lastpixel &= 0xf; + break; + case THUNDER_2BITDELTAS: /* 2-bit deltas */ + if ((delta = ((n >> 4) & 3)) != DELTA2_SKIP) + SETPIXEL(op, lastpixel + twobitdeltas[delta]); + if ((delta = ((n >> 2) & 3)) != DELTA2_SKIP) + SETPIXEL(op, lastpixel + twobitdeltas[delta]); + if ((delta = (n & 3)) != DELTA2_SKIP) + SETPIXEL(op, lastpixel + twobitdeltas[delta]); + break; + case THUNDER_3BITDELTAS: /* 3-bit deltas */ + if ((delta = ((n >> 3) & 7)) != DELTA3_SKIP) + SETPIXEL(op, lastpixel + threebitdeltas[delta]); + if ((delta = (n & 7)) != DELTA3_SKIP) + SETPIXEL(op, lastpixel + threebitdeltas[delta]); + break; + case THUNDER_RAW: /* raw data */ + SETPIXEL(op, n); + break; + } + } + tif->tif_rawcp = (tidata_t) bp; + tif->tif_rawcc = cc; + if (npixels != maxpixels) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "ThunderDecode: %s data at scanline %ld (%lu != %lu)", + npixels < maxpixels ? "Not enough" : "Too much", + (long) tif->tif_row, (long) npixels, (long) maxpixels); + return (0); + } + return (1); +} + +static int +ThunderDecodeRow(TIFF* tif, tidata_t buf, tsize_t occ, tsample_t s) +{ + tidata_t row = buf; + + (void) s; + while ((long)occ > 0) { + if (!ThunderDecode(tif, row, tif->tif_dir.td_imagewidth)) + return (0); + occ -= tif->tif_scanlinesize; + row += tif->tif_scanlinesize; + } + return (1); +} + +int +TIFFInitThunderScan(TIFF* tif, int scheme) +{ + (void) scheme; + tif->tif_decoderow = ThunderDecodeRow; + tif->tif_decodestrip = ThunderDecodeRow; + return (1); +} +#endif /* THUNDER_SUPPORT */ + +/* vim: set ts=8 sts=8 sw=8 noet: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tif_tile.c b/reactos/dll/3rdparty/libtiff/tif_tile.c new file mode 100644 index 00000000000..d8379e61b30 --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tif_tile.c @@ -0,0 +1,280 @@ +/* $Id: tif_tile.c,v 1.12.2.1 2010-06-08 18:50:43 bfriesen Exp $ */ + +/* + * Copyright (c) 1991-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library. + * + * Tiled Image Support Routines. + */ +#include "tiffiop.h" + +static uint32 +summarize(TIFF* tif, size_t summand1, size_t summand2, const char* where) +{ + /* + * XXX: We are using casting to uint32 here, because sizeof(size_t) + * may be larger than sizeof(uint32) on 64-bit architectures. + */ + uint32 bytes = summand1 + summand2; + + if (bytes - summand1 != summand2) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Integer overflow in %s", where); + bytes = 0; + } + + return (bytes); +} + +static uint32 +multiply(TIFF* tif, size_t nmemb, size_t elem_size, const char* where) +{ + uint32 bytes = nmemb * elem_size; + + if (elem_size && bytes / elem_size != nmemb) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Integer overflow in %s", where); + bytes = 0; + } + + return (bytes); +} + +/* + * Compute which tile an (x,y,z,s) value is in. + */ +ttile_t +TIFFComputeTile(TIFF* tif, uint32 x, uint32 y, uint32 z, tsample_t s) +{ + TIFFDirectory *td = &tif->tif_dir; + uint32 dx = td->td_tilewidth; + uint32 dy = td->td_tilelength; + uint32 dz = td->td_tiledepth; + ttile_t tile = 1; + + if (td->td_imagedepth == 1) + z = 0; + if (dx == (uint32) -1) + dx = td->td_imagewidth; + if (dy == (uint32) -1) + dy = td->td_imagelength; + if (dz == (uint32) -1) + dz = td->td_imagedepth; + if (dx != 0 && dy != 0 && dz != 0) { + uint32 xpt = TIFFhowmany(td->td_imagewidth, dx); + uint32 ypt = TIFFhowmany(td->td_imagelength, dy); + uint32 zpt = TIFFhowmany(td->td_imagedepth, dz); + + if (td->td_planarconfig == PLANARCONFIG_SEPARATE) + tile = (xpt*ypt*zpt)*s + + (xpt*ypt)*(z/dz) + + xpt*(y/dy) + + x/dx; + else + tile = (xpt*ypt)*(z/dz) + xpt*(y/dy) + x/dx; + } + return (tile); +} + +/* + * Check an (x,y,z,s) coordinate + * against the image bounds. + */ +int +TIFFCheckTile(TIFF* tif, uint32 x, uint32 y, uint32 z, tsample_t s) +{ + TIFFDirectory *td = &tif->tif_dir; + + if (x >= td->td_imagewidth) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "%lu: Col out of range, max %lu", + (unsigned long) x, + (unsigned long) (td->td_imagewidth - 1)); + return (0); + } + if (y >= td->td_imagelength) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "%lu: Row out of range, max %lu", + (unsigned long) y, + (unsigned long) (td->td_imagelength - 1)); + return (0); + } + if (z >= td->td_imagedepth) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "%lu: Depth out of range, max %lu", + (unsigned long) z, + (unsigned long) (td->td_imagedepth - 1)); + return (0); + } + if (td->td_planarconfig == PLANARCONFIG_SEPARATE && + s >= td->td_samplesperpixel) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "%lu: Sample out of range, max %lu", + (unsigned long) s, + (unsigned long) (td->td_samplesperpixel - 1)); + return (0); + } + return (1); +} + +/* + * Compute how many tiles are in an image. + */ +ttile_t +TIFFNumberOfTiles(TIFF* tif) +{ + TIFFDirectory *td = &tif->tif_dir; + uint32 dx = td->td_tilewidth; + uint32 dy = td->td_tilelength; + uint32 dz = td->td_tiledepth; + ttile_t ntiles; + + if (dx == (uint32) -1) + dx = td->td_imagewidth; + if (dy == (uint32) -1) + dy = td->td_imagelength; + if (dz == (uint32) -1) + dz = td->td_imagedepth; + ntiles = (dx == 0 || dy == 0 || dz == 0) ? 0 : + multiply(tif, multiply(tif, TIFFhowmany(td->td_imagewidth, dx), + TIFFhowmany(td->td_imagelength, dy), + "TIFFNumberOfTiles"), + TIFFhowmany(td->td_imagedepth, dz), "TIFFNumberOfTiles"); + if (td->td_planarconfig == PLANARCONFIG_SEPARATE) + ntiles = multiply(tif, ntiles, td->td_samplesperpixel, + "TIFFNumberOfTiles"); + return (ntiles); +} + +/* + * Compute the # bytes in each row of a tile. + */ +tsize_t +TIFFTileRowSize(TIFF* tif) +{ + TIFFDirectory *td = &tif->tif_dir; + tsize_t rowsize; + + if (td->td_tilelength == 0 || td->td_tilewidth == 0) + return ((tsize_t) 0); + rowsize = multiply(tif, td->td_bitspersample, td->td_tilewidth, + "TIFFTileRowSize"); + if (td->td_planarconfig == PLANARCONFIG_CONTIG) + rowsize = multiply(tif, rowsize, td->td_samplesperpixel, + "TIFFTileRowSize"); + return ((tsize_t) TIFFhowmany8(rowsize)); +} + +/* + * Compute the # bytes in a variable length, row-aligned tile. + */ +tsize_t +TIFFVTileSize(TIFF* tif, uint32 nrows) +{ + TIFFDirectory *td = &tif->tif_dir; + tsize_t tilesize; + + if (td->td_tilelength == 0 || td->td_tilewidth == 0 || + td->td_tiledepth == 0) + return ((tsize_t) 0); + if (td->td_planarconfig == PLANARCONFIG_CONTIG && + td->td_photometric == PHOTOMETRIC_YCBCR && + !isUpSampled(tif)) { + /* + * Packed YCbCr data contain one Cb+Cr for every + * HorizontalSampling*VerticalSampling Y values. + * Must also roundup width and height when calculating + * since images that are not a multiple of the + * horizontal/vertical subsampling area include + * YCbCr data for the extended image. + */ + tsize_t w = + TIFFroundup(td->td_tilewidth, td->td_ycbcrsubsampling[0]); + tsize_t rowsize = + TIFFhowmany8(multiply(tif, w, td->td_bitspersample, + "TIFFVTileSize")); + tsize_t samplingarea = + td->td_ycbcrsubsampling[0]*td->td_ycbcrsubsampling[1]; + if (samplingarea == 0) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Invalid YCbCr subsampling"); + return 0; + } + nrows = TIFFroundup(nrows, td->td_ycbcrsubsampling[1]); + /* NB: don't need TIFFhowmany here 'cuz everything is rounded */ + tilesize = multiply(tif, nrows, rowsize, "TIFFVTileSize"); + tilesize = summarize(tif, tilesize, + multiply(tif, 2, tilesize / samplingarea, + "TIFFVTileSize"), + "TIFFVTileSize"); + } else + tilesize = multiply(tif, nrows, TIFFTileRowSize(tif), + "TIFFVTileSize"); + return ((tsize_t) + multiply(tif, tilesize, td->td_tiledepth, "TIFFVTileSize")); +} + +/* + * Compute the # bytes in a row-aligned tile. + */ +tsize_t +TIFFTileSize(TIFF* tif) +{ + return (TIFFVTileSize(tif, tif->tif_dir.td_tilelength)); +} + +/* + * Compute a default tile size based on the image + * characteristics and a requested value. If a + * request is <1 then we choose a size according + * to certain heuristics. + */ +void +TIFFDefaultTileSize(TIFF* tif, uint32* tw, uint32* th) +{ + (*tif->tif_deftilesize)(tif, tw, th); +} + +void +_TIFFDefaultTileSize(TIFF* tif, uint32* tw, uint32* th) +{ + (void) tif; + if (*(int32*) tw < 1) + *tw = 256; + if (*(int32*) th < 1) + *th = 256; + /* roundup to a multiple of 16 per the spec */ + if (*tw & 0xf) + *tw = TIFFroundup(*tw, 16); + if (*th & 0xf) + *th = TIFFroundup(*th, 16); +} + +/* vim: set ts=8 sts=8 sw=8 noet: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tif_version.c b/reactos/dll/3rdparty/libtiff/tif_version.c new file mode 100644 index 00000000000..218dab566e7 --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tif_version.c @@ -0,0 +1,40 @@ +/* $Header: /cvs/maptools/cvsroot/libtiff/libtiff/tif_version.c,v 1.2.2.1 2010-06-08 18:50:43 bfriesen Exp $ */ +/* + * Copyright (c) 1992-1997 Sam Leffler + * Copyright (c) 1992-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ +#include "tiffiop.h" + +static const char TIFFVersion[] = TIFFLIB_VERSION_STR; + +const char* +TIFFGetVersion(void) +{ + return (TIFFVersion); +} +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tif_warning.c b/reactos/dll/3rdparty/libtiff/tif_warning.c new file mode 100644 index 00000000000..fe974d909ff --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tif_warning.c @@ -0,0 +1,81 @@ +/* $Header: /cvs/maptools/cvsroot/libtiff/libtiff/tif_warning.c,v 1.2.2.1 2010-06-08 18:50:43 bfriesen Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library. + */ +#include "tiffiop.h" + +TIFFErrorHandlerExt _TIFFwarningHandlerExt = NULL; + +TIFFErrorHandler +TIFFSetWarningHandler(TIFFErrorHandler handler) +{ + TIFFErrorHandler prev = _TIFFwarningHandler; + _TIFFwarningHandler = handler; + return (prev); +} + +TIFFErrorHandlerExt +TIFFSetWarningHandlerExt(TIFFErrorHandlerExt handler) +{ + TIFFErrorHandlerExt prev = _TIFFwarningHandlerExt; + _TIFFwarningHandlerExt = handler; + return (prev); +} + +void +TIFFWarning(const char* module, const char* fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + if (_TIFFwarningHandler) + (*_TIFFwarningHandler)(module, fmt, ap); + if (_TIFFwarningHandlerExt) + (*_TIFFwarningHandlerExt)(0, module, fmt, ap); + va_end(ap); +} + +void +TIFFWarningExt(thandle_t fd, const char* module, const char* fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + if (_TIFFwarningHandler) + (*_TIFFwarningHandler)(module, fmt, ap); + if (_TIFFwarningHandlerExt) + (*_TIFFwarningHandlerExt)(fd, module, fmt, ap); + va_end(ap); +} + + +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tif_win32.c b/reactos/dll/3rdparty/libtiff/tif_win32.c new file mode 100644 index 00000000000..2ab944b12cf --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tif_win32.c @@ -0,0 +1,408 @@ +/* $Id: tif_win32.c,v 1.21.2.1 2010-06-08 18:50:43 bfriesen Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library Win32-specific Routines. Adapted from tif_unix.c 4/5/95 by + * Scott Wagner (wagner@itek.com), Itek Graphix, Rochester, NY USA + */ +#include "tiffiop.h" + +#include + +static tsize_t +_tiffReadProc(thandle_t fd, tdata_t buf, tsize_t size) +{ + DWORD dwSizeRead; + if (!ReadFile(fd, buf, size, &dwSizeRead, NULL)) + return(0); + return ((tsize_t) dwSizeRead); +} + +static tsize_t +_tiffWriteProc(thandle_t fd, tdata_t buf, tsize_t size) +{ + DWORD dwSizeWritten; + if (!WriteFile(fd, buf, size, &dwSizeWritten, NULL)) + return(0); + return ((tsize_t) dwSizeWritten); +} + +static toff_t +_tiffSeekProc(thandle_t fd, toff_t off, int whence) +{ + ULARGE_INTEGER li; + DWORD dwMoveMethod; + + li.QuadPart = off; + + switch(whence) + { + case SEEK_SET: + dwMoveMethod = FILE_BEGIN; + break; + case SEEK_CUR: + dwMoveMethod = FILE_CURRENT; + break; + case SEEK_END: + dwMoveMethod = FILE_END; + break; + default: + dwMoveMethod = FILE_BEGIN; + break; + } + return ((toff_t)SetFilePointer(fd, (LONG) li.LowPart, + (PLONG)&li.HighPart, dwMoveMethod)); +} + +static int +_tiffCloseProc(thandle_t fd) +{ + return (CloseHandle(fd) ? 0 : -1); +} + +static toff_t +_tiffSizeProc(thandle_t fd) +{ + return ((toff_t)GetFileSize(fd, NULL)); +} + +static int +_tiffDummyMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize) +{ + (void) fd; + (void) pbase; + (void) psize; + return (0); +} + +/* + * From "Hermann Josef Hill" : + * + * Windows uses both a handle and a pointer for file mapping, + * but according to the SDK documentation and Richter's book + * "Advanced Windows Programming" it is safe to free the handle + * after obtaining the file mapping pointer + * + * This removes a nasty OS dependency and cures a problem + * with Visual C++ 5.0 + */ +static int +_tiffMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize) +{ + toff_t size; + HANDLE hMapFile; + + if ((size = _tiffSizeProc(fd)) == 0xFFFFFFFF) + return (0); + hMapFile = CreateFileMapping(fd, NULL, PAGE_READONLY, 0, size, NULL); + if (hMapFile == NULL) + return (0); + *pbase = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0); + CloseHandle(hMapFile); + if (*pbase == NULL) + return (0); + *psize = size; + return(1); +} + +static void +_tiffDummyUnmapProc(thandle_t fd, tdata_t base, toff_t size) +{ + (void) fd; + (void) base; + (void) size; +} + +static void +_tiffUnmapProc(thandle_t fd, tdata_t base, toff_t size) +{ + UnmapViewOfFile(base); +} + +/* + * Open a TIFF file descriptor for read/writing. + * Note that TIFFFdOpen and TIFFOpen recognise the character 'u' in the mode + * string, which forces the file to be opened unmapped. + */ +TIFF* +TIFFFdOpen(int ifd, const char* name, const char* mode) +{ + TIFF* tif; + BOOL fSuppressMap = (mode[1] == 'u' || (mode[1]!=0 && mode[2] == 'u')); + + tif = TIFFClientOpen(name, mode, (thandle_t)ifd, + _tiffReadProc, _tiffWriteProc, + _tiffSeekProc, _tiffCloseProc, _tiffSizeProc, + fSuppressMap ? _tiffDummyMapProc : _tiffMapProc, + fSuppressMap ? _tiffDummyUnmapProc : _tiffUnmapProc); + if (tif) + tif->tif_fd = ifd; + return (tif); +} + +#ifndef _WIN32_WCE + +/* + * Open a TIFF file for read/writing. + */ +TIFF* +TIFFOpen(const char* name, const char* mode) +{ + static const char module[] = "TIFFOpen"; + thandle_t fd; + int m; + DWORD dwMode; + TIFF* tif; + + m = _TIFFgetMode(mode, module); + + switch(m) + { + case O_RDONLY: + dwMode = OPEN_EXISTING; + break; + case O_RDWR: + dwMode = OPEN_ALWAYS; + break; + case O_RDWR|O_CREAT: + dwMode = OPEN_ALWAYS; + break; + case O_RDWR|O_TRUNC: + dwMode = CREATE_ALWAYS; + break; + case O_RDWR|O_CREAT|O_TRUNC: + dwMode = CREATE_ALWAYS; + break; + default: + return ((TIFF*)0); + } + fd = (thandle_t)CreateFileA(name, + (m == O_RDONLY)?GENERIC_READ:(GENERIC_READ | GENERIC_WRITE), + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, dwMode, + (m == O_RDONLY)?FILE_ATTRIBUTE_READONLY:FILE_ATTRIBUTE_NORMAL, + NULL); + if (fd == INVALID_HANDLE_VALUE) { + TIFFErrorExt(0, module, "%s: Cannot open", name); + return ((TIFF *)0); + } + + tif = TIFFFdOpen((int)fd, name, mode); + if(!tif) + CloseHandle(fd); + return tif; +} + +/* + * Open a TIFF file with a Unicode filename, for read/writing. + */ +TIFF* +TIFFOpenW(const wchar_t* name, const char* mode) +{ + static const char module[] = "TIFFOpenW"; + thandle_t fd; + int m; + DWORD dwMode; + int mbsize; + char *mbname; + TIFF *tif; + + m = _TIFFgetMode(mode, module); + + switch(m) { + case O_RDONLY: dwMode = OPEN_EXISTING; break; + case O_RDWR: dwMode = OPEN_ALWAYS; break; + case O_RDWR|O_CREAT: dwMode = OPEN_ALWAYS; break; + case O_RDWR|O_TRUNC: dwMode = CREATE_ALWAYS; break; + case O_RDWR|O_CREAT|O_TRUNC: dwMode = CREATE_ALWAYS; break; + default: return ((TIFF*)0); + } + + fd = (thandle_t)CreateFileW(name, + (m == O_RDONLY)?GENERIC_READ:(GENERIC_READ|GENERIC_WRITE), + FILE_SHARE_READ, NULL, dwMode, + (m == O_RDONLY)?FILE_ATTRIBUTE_READONLY:FILE_ATTRIBUTE_NORMAL, + NULL); + if (fd == INVALID_HANDLE_VALUE) { + TIFFErrorExt(0, module, "%S: Cannot open", name); + return ((TIFF *)0); + } + + mbname = NULL; + mbsize = WideCharToMultiByte(CP_ACP, 0, name, -1, NULL, 0, NULL, NULL); + if (mbsize > 0) { + mbname = (char *)_TIFFmalloc(mbsize); + if (!mbname) { + TIFFErrorExt(0, module, + "Can't allocate space for filename conversion buffer"); + return ((TIFF*)0); + } + + WideCharToMultiByte(CP_ACP, 0, name, -1, mbname, mbsize, + NULL, NULL); + } + + tif = TIFFFdOpen((int)fd, + (mbname != NULL) ? mbname : "", mode); + if(!tif) + CloseHandle(fd); + + _TIFFfree(mbname); + + return tif; +} + +#endif /* ndef _WIN32_WCE */ + + +tdata_t +_TIFFmalloc(tsize_t s) +{ + return ((tdata_t)GlobalAlloc(GMEM_FIXED, s)); +} + +void +_TIFFfree(tdata_t p) +{ + GlobalFree(p); + return; +} + +tdata_t +_TIFFrealloc(tdata_t p, tsize_t s) +{ + void* pvTmp; + tsize_t old; + + if(p == NULL) + return ((tdata_t)GlobalAlloc(GMEM_FIXED, s)); + + old = GlobalSize(p); + + if (old>=s) { + if ((pvTmp = GlobalAlloc(GMEM_FIXED, s)) != NULL) { + CopyMemory(pvTmp, p, s); + GlobalFree(p); + } + } else { + if ((pvTmp = GlobalAlloc(GMEM_FIXED, s)) != NULL) { + CopyMemory(pvTmp, p, old); + GlobalFree(p); + } + } + return ((tdata_t)pvTmp); +} + +void +_TIFFmemset(void* p, int v, tsize_t c) +{ + FillMemory(p, c, (BYTE)v); +} + +void +_TIFFmemcpy(void* d, const tdata_t s, tsize_t c) +{ + CopyMemory(d, s, c); +} + +int +_TIFFmemcmp(const tdata_t p1, const tdata_t p2, tsize_t c) +{ + register const BYTE *pb1 = (const BYTE *) p1; + register const BYTE *pb2 = (const BYTE *) p2; + register DWORD dwTmp = c; + register int iTmp; + for (iTmp = 0; dwTmp-- && !iTmp; iTmp = (int)*pb1++ - (int)*pb2++) + ; + return (iTmp); +} + +#ifndef _WIN32_WCE + +static void +Win32WarningHandler(const char* module, const char* fmt, va_list ap) +{ +#ifndef TIF_PLATFORM_CONSOLE + LPTSTR szTitle; + LPTSTR szTmp; + LPCTSTR szTitleText = "%s Warning"; + LPCTSTR szDefaultModule = "LIBTIFF"; + LPCTSTR szTmpModule = (module == NULL) ? szDefaultModule : module; + if ((szTitle = (LPTSTR)LocalAlloc(LMEM_FIXED, (strlen(szTmpModule) + + strlen(szTitleText) + strlen(fmt) + 128)*sizeof(char))) == NULL) + return; + sprintf(szTitle, szTitleText, szTmpModule); + szTmp = szTitle + (strlen(szTitle)+2)*sizeof(char); + vsprintf(szTmp, fmt, ap); + MessageBoxA(GetFocus(), szTmp, szTitle, MB_OK | MB_ICONINFORMATION); + LocalFree(szTitle); + return; +#else + if (module != NULL) + fprintf(stderr, "%s: ", module); + fprintf(stderr, "Warning, "); + vfprintf(stderr, fmt, ap); + fprintf(stderr, ".\n"); +#endif +} +TIFFErrorHandler _TIFFwarningHandler = Win32WarningHandler; + +static void +Win32ErrorHandler(const char* module, const char* fmt, va_list ap) +{ +#ifndef TIF_PLATFORM_CONSOLE + LPTSTR szTitle; + LPTSTR szTmp; + LPCTSTR szTitleText = "%s Error"; + LPCTSTR szDefaultModule = "LIBTIFF"; + LPCTSTR szTmpModule = (module == NULL) ? szDefaultModule : module; + if ((szTitle = (LPTSTR)LocalAlloc(LMEM_FIXED, (strlen(szTmpModule) + + strlen(szTitleText) + strlen(fmt) + 128)*sizeof(char))) == NULL) + return; + sprintf(szTitle, szTitleText, szTmpModule); + szTmp = szTitle + (strlen(szTitle)+2)*sizeof(char); + vsprintf(szTmp, fmt, ap); + MessageBoxA(GetFocus(), szTmp, szTitle, MB_OK | MB_ICONEXCLAMATION); + LocalFree(szTitle); + return; +#else + if (module != NULL) + fprintf(stderr, "%s: ", module); + vfprintf(stderr, fmt, ap); + fprintf(stderr, ".\n"); +#endif +} +TIFFErrorHandler _TIFFerrorHandler = Win32ErrorHandler; + +#endif /* ndef _WIN32_WCE */ + +/* vim: set ts=8 sts=8 sw=8 noet: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tif_write.c b/reactos/dll/3rdparty/libtiff/tif_write.c new file mode 100644 index 00000000000..bd084181d0a --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tif_write.c @@ -0,0 +1,718 @@ +/* $Id: tif_write.c,v 1.22.2.5 2010-06-08 18:50:43 bfriesen Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * TIFF Library. + * + * Scanline-oriented Write Support + */ +#include "tiffiop.h" +#include + +#define STRIPINCR 20 /* expansion factor on strip array */ + +#define WRITECHECKSTRIPS(tif, module) \ + (((tif)->tif_flags&TIFF_BEENWRITING) || TIFFWriteCheck((tif),0,module)) +#define WRITECHECKTILES(tif, module) \ + (((tif)->tif_flags&TIFF_BEENWRITING) || TIFFWriteCheck((tif),1,module)) +#define BUFFERCHECK(tif) \ + ((((tif)->tif_flags & TIFF_BUFFERSETUP) && tif->tif_rawdata) || \ + TIFFWriteBufferSetup((tif), NULL, (tsize_t) -1)) + +static int TIFFGrowStrips(TIFF*, int, const char*); +static int TIFFAppendToStrip(TIFF*, tstrip_t, tidata_t, tsize_t); + +int +TIFFWriteScanline(TIFF* tif, tdata_t buf, uint32 row, tsample_t sample) +{ + static const char module[] = "TIFFWriteScanline"; + register TIFFDirectory *td; + int status, imagegrew = 0; + tstrip_t strip; + + if (!WRITECHECKSTRIPS(tif, module)) + return (-1); + /* + * Handle delayed allocation of data buffer. This + * permits it to be sized more intelligently (using + * directory information). + */ + if (!BUFFERCHECK(tif)) + return (-1); + td = &tif->tif_dir; + /* + * Extend image length if needed + * (but only for PlanarConfig=1). + */ + if (row >= td->td_imagelength) { /* extend image */ + if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Can not change \"ImageLength\" when using separate planes"); + return (-1); + } + td->td_imagelength = row+1; + imagegrew = 1; + } + /* + * Calculate strip and check for crossings. + */ + if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { + if (sample >= td->td_samplesperpixel) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "%d: Sample out of range, max %d", + sample, td->td_samplesperpixel); + return (-1); + } + strip = sample*td->td_stripsperimage + row/td->td_rowsperstrip; + } else + strip = row / td->td_rowsperstrip; + /* + * Check strip array to make sure there's space. We don't support + * dynamically growing files that have data organized in separate + * bitplanes because it's too painful. In that case we require that + * the imagelength be set properly before the first write (so that the + * strips array will be fully allocated above). + */ + if (strip >= td->td_nstrips && !TIFFGrowStrips(tif, 1, module)) + return (-1); + if (strip != tif->tif_curstrip) { + /* + * Changing strips -- flush any data present. + */ + if (!TIFFFlushData(tif)) + return (-1); + tif->tif_curstrip = strip; + /* + * Watch out for a growing image. The value of strips/image + * will initially be 1 (since it can't be deduced until the + * imagelength is known). + */ + if (strip >= td->td_stripsperimage && imagegrew) + td->td_stripsperimage = + TIFFhowmany(td->td_imagelength,td->td_rowsperstrip); + tif->tif_row = + (strip % td->td_stripsperimage) * td->td_rowsperstrip; + if ((tif->tif_flags & TIFF_CODERSETUP) == 0) { + if (!(*tif->tif_setupencode)(tif)) + return (-1); + tif->tif_flags |= TIFF_CODERSETUP; + } + + tif->tif_rawcc = 0; + tif->tif_rawcp = tif->tif_rawdata; + + if( td->td_stripbytecount[strip] > 0 ) + { + /* if we are writing over existing tiles, zero length */ + td->td_stripbytecount[strip] = 0; + + /* this forces TIFFAppendToStrip() to do a seek */ + tif->tif_curoff = 0; + } + + if (!(*tif->tif_preencode)(tif, sample)) + return (-1); + tif->tif_flags |= TIFF_POSTENCODE; + } + /* + * Ensure the write is either sequential or at the + * beginning of a strip (or that we can randomly + * access the data -- i.e. no encoding). + */ + if (row != tif->tif_row) { + if (row < tif->tif_row) { + /* + * Moving backwards within the same strip: + * backup to the start and then decode + * forward (below). + */ + tif->tif_row = (strip % td->td_stripsperimage) * + td->td_rowsperstrip; + tif->tif_rawcp = tif->tif_rawdata; + } + /* + * Seek forward to the desired row. + */ + if (!(*tif->tif_seek)(tif, row - tif->tif_row)) + return (-1); + tif->tif_row = row; + } + + /* swab if needed - note that source buffer will be altered */ + tif->tif_postdecode( tif, (tidata_t) buf, tif->tif_scanlinesize ); + + status = (*tif->tif_encoderow)(tif, (tidata_t) buf, + tif->tif_scanlinesize, sample); + + /* we are now poised at the beginning of the next row */ + tif->tif_row = row + 1; + return (status); +} + +/* + * Encode the supplied data and write it to the + * specified strip. + * + * NB: Image length must be setup before writing. + */ +tsize_t +TIFFWriteEncodedStrip(TIFF* tif, tstrip_t strip, tdata_t data, tsize_t cc) +{ + static const char module[] = "TIFFWriteEncodedStrip"; + TIFFDirectory *td = &tif->tif_dir; + tsample_t sample; + + if (!WRITECHECKSTRIPS(tif, module)) + return ((tsize_t) -1); + /* + * Check strip array to make sure there's space. + * We don't support dynamically growing files that + * have data organized in separate bitplanes because + * it's too painful. In that case we require that + * the imagelength be set properly before the first + * write (so that the strips array will be fully + * allocated above). + */ + if (strip >= td->td_nstrips) { + if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Can not grow image by strips when using separate planes"); + return ((tsize_t) -1); + } + if (!TIFFGrowStrips(tif, 1, module)) + return ((tsize_t) -1); + td->td_stripsperimage = + TIFFhowmany(td->td_imagelength, td->td_rowsperstrip); + } + /* + * Handle delayed allocation of data buffer. This + * permits it to be sized according to the directory + * info. + */ + if (!BUFFERCHECK(tif)) + return ((tsize_t) -1); + tif->tif_curstrip = strip; + tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip; + if ((tif->tif_flags & TIFF_CODERSETUP) == 0) { + if (!(*tif->tif_setupencode)(tif)) + return ((tsize_t) -1); + tif->tif_flags |= TIFF_CODERSETUP; + } + + tif->tif_rawcc = 0; + tif->tif_rawcp = tif->tif_rawdata; + + if( td->td_stripbytecount[strip] > 0 ) + { + /* Force TIFFAppendToStrip() to consider placing data at end + of file. */ + tif->tif_curoff = 0; + } + + tif->tif_flags &= ~TIFF_POSTENCODE; + sample = (tsample_t)(strip / td->td_stripsperimage); + if (!(*tif->tif_preencode)(tif, sample)) + return ((tsize_t) -1); + + /* swab if needed - note that source buffer will be altered */ + tif->tif_postdecode( tif, (tidata_t) data, cc ); + + if (!(*tif->tif_encodestrip)(tif, (tidata_t) data, cc, sample)) + return ((tsize_t) 0); + if (!(*tif->tif_postencode)(tif)) + return ((tsize_t) -1); + if (!isFillOrder(tif, td->td_fillorder) && + (tif->tif_flags & TIFF_NOBITREV) == 0) + TIFFReverseBits(tif->tif_rawdata, tif->tif_rawcc); + if (tif->tif_rawcc > 0 && + !TIFFAppendToStrip(tif, strip, tif->tif_rawdata, tif->tif_rawcc)) + return ((tsize_t) -1); + tif->tif_rawcc = 0; + tif->tif_rawcp = tif->tif_rawdata; + return (cc); +} + +/* + * Write the supplied data to the specified strip. + * + * NB: Image length must be setup before writing. + */ +tsize_t +TIFFWriteRawStrip(TIFF* tif, tstrip_t strip, tdata_t data, tsize_t cc) +{ + static const char module[] = "TIFFWriteRawStrip"; + TIFFDirectory *td = &tif->tif_dir; + + if (!WRITECHECKSTRIPS(tif, module)) + return ((tsize_t) -1); + /* + * Check strip array to make sure there's space. + * We don't support dynamically growing files that + * have data organized in separate bitplanes because + * it's too painful. In that case we require that + * the imagelength be set properly before the first + * write (so that the strips array will be fully + * allocated above). + */ + if (strip >= td->td_nstrips) { + if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Can not grow image by strips when using separate planes"); + return ((tsize_t) -1); + } + /* + * Watch out for a growing image. The value of + * strips/image will initially be 1 (since it + * can't be deduced until the imagelength is known). + */ + if (strip >= td->td_stripsperimage) + td->td_stripsperimage = + TIFFhowmany(td->td_imagelength,td->td_rowsperstrip); + if (!TIFFGrowStrips(tif, 1, module)) + return ((tsize_t) -1); + } + tif->tif_curstrip = strip; + tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip; + return (TIFFAppendToStrip(tif, strip, (tidata_t) data, cc) ? + cc : (tsize_t) -1); +} + +/* + * Write and compress a tile of data. The + * tile is selected by the (x,y,z,s) coordinates. + */ +tsize_t +TIFFWriteTile(TIFF* tif, + tdata_t buf, uint32 x, uint32 y, uint32 z, tsample_t s) +{ + if (!TIFFCheckTile(tif, x, y, z, s)) + return (-1); + /* + * NB: A tile size of -1 is used instead of tif_tilesize knowing + * that TIFFWriteEncodedTile will clamp this to the tile size. + * This is done because the tile size may not be defined until + * after the output buffer is setup in TIFFWriteBufferSetup. + */ + return (TIFFWriteEncodedTile(tif, + TIFFComputeTile(tif, x, y, z, s), buf, (tsize_t) -1)); +} + +/* + * Encode the supplied data and write it to the + * specified tile. There must be space for the + * data. The function clamps individual writes + * to a tile to the tile size, but does not (and + * can not) check that multiple writes to the same + * tile do not write more than tile size data. + * + * NB: Image length must be setup before writing; this + * interface does not support automatically growing + * the image on each write (as TIFFWriteScanline does). + */ +tsize_t +TIFFWriteEncodedTile(TIFF* tif, ttile_t tile, tdata_t data, tsize_t cc) +{ + static const char module[] = "TIFFWriteEncodedTile"; + TIFFDirectory *td; + tsample_t sample; + + if (!WRITECHECKTILES(tif, module)) + return ((tsize_t) -1); + td = &tif->tif_dir; + if (tile >= td->td_nstrips) { + TIFFErrorExt(tif->tif_clientdata, module, "%s: Tile %lu out of range, max %lu", + tif->tif_name, (unsigned long) tile, (unsigned long) td->td_nstrips); + return ((tsize_t) -1); + } + /* + * Handle delayed allocation of data buffer. This + * permits it to be sized more intelligently (using + * directory information). + */ + if (!BUFFERCHECK(tif)) + return ((tsize_t) -1); + tif->tif_curtile = tile; + + tif->tif_rawcc = 0; + tif->tif_rawcp = tif->tif_rawdata; + + if( td->td_stripbytecount[tile] > 0 ) + { + /* Force TIFFAppendToStrip() to consider placing data at end + of file. */ + tif->tif_curoff = 0; + } + + /* + * Compute tiles per row & per column to compute + * current row and column + */ + tif->tif_row = (tile % TIFFhowmany(td->td_imagelength, td->td_tilelength)) + * td->td_tilelength; + tif->tif_col = (tile % TIFFhowmany(td->td_imagewidth, td->td_tilewidth)) + * td->td_tilewidth; + + if ((tif->tif_flags & TIFF_CODERSETUP) == 0) { + if (!(*tif->tif_setupencode)(tif)) + return ((tsize_t) -1); + tif->tif_flags |= TIFF_CODERSETUP; + } + tif->tif_flags &= ~TIFF_POSTENCODE; + sample = (tsample_t)(tile/td->td_stripsperimage); + if (!(*tif->tif_preencode)(tif, sample)) + return ((tsize_t) -1); + /* + * Clamp write amount to the tile size. This is mostly + * done so that callers can pass in some large number + * (e.g. -1) and have the tile size used instead. + */ + if ( cc < 1 || cc > tif->tif_tilesize) + cc = tif->tif_tilesize; + + /* swab if needed - note that source buffer will be altered */ + tif->tif_postdecode( tif, (tidata_t) data, cc ); + + if (!(*tif->tif_encodetile)(tif, (tidata_t) data, cc, sample)) + return ((tsize_t) 0); + if (!(*tif->tif_postencode)(tif)) + return ((tsize_t) -1); + if (!isFillOrder(tif, td->td_fillorder) && + (tif->tif_flags & TIFF_NOBITREV) == 0) + TIFFReverseBits((unsigned char *)tif->tif_rawdata, tif->tif_rawcc); + if (tif->tif_rawcc > 0 && !TIFFAppendToStrip(tif, tile, + tif->tif_rawdata, tif->tif_rawcc)) + return ((tsize_t) -1); + tif->tif_rawcc = 0; + tif->tif_rawcp = tif->tif_rawdata; + return (cc); +} + +/* + * Write the supplied data to the specified strip. + * There must be space for the data; we don't check + * if strips overlap! + * + * NB: Image length must be setup before writing; this + * interface does not support automatically growing + * the image on each write (as TIFFWriteScanline does). + */ +tsize_t +TIFFWriteRawTile(TIFF* tif, ttile_t tile, tdata_t data, tsize_t cc) +{ + static const char module[] = "TIFFWriteRawTile"; + + if (!WRITECHECKTILES(tif, module)) + return ((tsize_t) -1); + if (tile >= tif->tif_dir.td_nstrips) { + TIFFErrorExt(tif->tif_clientdata, module, "%s: Tile %lu out of range, max %lu", + tif->tif_name, (unsigned long) tile, + (unsigned long) tif->tif_dir.td_nstrips); + return ((tsize_t) -1); + } + return (TIFFAppendToStrip(tif, tile, (tidata_t) data, cc) ? + cc : (tsize_t) -1); +} + +#define isUnspecified(tif, f) \ + (TIFFFieldSet(tif,f) && (tif)->tif_dir.td_imagelength == 0) + +int +TIFFSetupStrips(TIFF* tif) +{ + TIFFDirectory* td = &tif->tif_dir; + + if (isTiled(tif)) + td->td_stripsperimage = + isUnspecified(tif, FIELD_TILEDIMENSIONS) ? + td->td_samplesperpixel : TIFFNumberOfTiles(tif); + else + td->td_stripsperimage = + isUnspecified(tif, FIELD_ROWSPERSTRIP) ? + td->td_samplesperpixel : TIFFNumberOfStrips(tif); + td->td_nstrips = td->td_stripsperimage; + if (td->td_planarconfig == PLANARCONFIG_SEPARATE) + td->td_stripsperimage /= td->td_samplesperpixel; + td->td_stripoffset = (uint32 *) + _TIFFmalloc(td->td_nstrips * sizeof (uint32)); + td->td_stripbytecount = (uint32 *) + _TIFFmalloc(td->td_nstrips * sizeof (uint32)); + if (td->td_stripoffset == NULL || td->td_stripbytecount == NULL) + return (0); + /* + * Place data at the end-of-file + * (by setting offsets to zero). + */ + _TIFFmemset(td->td_stripoffset, 0, td->td_nstrips*sizeof (uint32)); + _TIFFmemset(td->td_stripbytecount, 0, td->td_nstrips*sizeof (uint32)); + TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS); + TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS); + return (1); +} +#undef isUnspecified + +/* + * Verify file is writable and that the directory + * information is setup properly. In doing the latter + * we also "freeze" the state of the directory so + * that important information is not changed. + */ +int +TIFFWriteCheck(TIFF* tif, int tiles, const char* module) +{ + if (tif->tif_mode == O_RDONLY) { + TIFFErrorExt(tif->tif_clientdata, module, "%s: File not open for writing", + tif->tif_name); + return (0); + } + if (tiles ^ isTiled(tif)) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, tiles ? + "Can not write tiles to a stripped image" : + "Can not write scanlines to a tiled image"); + return (0); + } + + /* + * On the first write verify all the required information + * has been setup and initialize any data structures that + * had to wait until directory information was set. + * Note that a lot of our work is assumed to remain valid + * because we disallow any of the important parameters + * from changing after we start writing (i.e. once + * TIFF_BEENWRITING is set, TIFFSetField will only allow + * the image's length to be changed). + */ + if (!TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS)) { + TIFFErrorExt(tif->tif_clientdata, module, + "%s: Must set \"ImageWidth\" before writing data", + tif->tif_name); + return (0); + } + if (tif->tif_dir.td_samplesperpixel == 1) { + /* + * Planarconfiguration is irrelevant in case of single band + * images and need not be included. We will set it anyway, + * because this field is used in other parts of library even + * in the single band case. + */ + if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG)) + tif->tif_dir.td_planarconfig = PLANARCONFIG_CONTIG; + } else { + if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG)) { + TIFFErrorExt(tif->tif_clientdata, module, + "%s: Must set \"PlanarConfiguration\" before writing data", + tif->tif_name); + return (0); + } + } + if (tif->tif_dir.td_stripoffset == NULL && !TIFFSetupStrips(tif)) { + tif->tif_dir.td_nstrips = 0; + TIFFErrorExt(tif->tif_clientdata, module, "%s: No space for %s arrays", + tif->tif_name, isTiled(tif) ? "tile" : "strip"); + return (0); + } + tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tsize_t) -1; + tif->tif_scanlinesize = TIFFScanlineSize(tif); + tif->tif_flags |= TIFF_BEENWRITING; + return (1); +} + +/* + * Setup the raw data buffer used for encoding. + */ +int +TIFFWriteBufferSetup(TIFF* tif, tdata_t bp, tsize_t size) +{ + static const char module[] = "TIFFWriteBufferSetup"; + + if (tif->tif_rawdata) { + if (tif->tif_flags & TIFF_MYBUFFER) { + _TIFFfree(tif->tif_rawdata); + tif->tif_flags &= ~TIFF_MYBUFFER; + } + tif->tif_rawdata = NULL; + } + if (size == (tsize_t) -1) { + size = (isTiled(tif) ? + tif->tif_tilesize : TIFFStripSize(tif)); + /* + * Make raw data buffer at least 8K + */ + if (size < 8*1024) + size = 8*1024; + bp = NULL; /* NB: force malloc */ + } + if (bp == NULL) { + bp = _TIFFmalloc(size); + if (bp == NULL) { + TIFFErrorExt(tif->tif_clientdata, module, "%s: No space for output buffer", + tif->tif_name); + return (0); + } + tif->tif_flags |= TIFF_MYBUFFER; + } else + tif->tif_flags &= ~TIFF_MYBUFFER; + tif->tif_rawdata = (tidata_t) bp; + tif->tif_rawdatasize = size; + tif->tif_rawcc = 0; + tif->tif_rawcp = tif->tif_rawdata; + tif->tif_flags |= TIFF_BUFFERSETUP; + return (1); +} + +/* + * Grow the strip data structures by delta strips. + */ +static int +TIFFGrowStrips(TIFF* tif, int delta, const char* module) +{ + TIFFDirectory *td = &tif->tif_dir; + uint32 *new_stripoffset, *new_stripbytecount; + + assert(td->td_planarconfig == PLANARCONFIG_CONTIG); + new_stripoffset = (uint32*)_TIFFrealloc(td->td_stripoffset, + (td->td_nstrips + delta) * sizeof (uint32)); + new_stripbytecount = (uint32*)_TIFFrealloc(td->td_stripbytecount, + (td->td_nstrips + delta) * sizeof (uint32)); + if (new_stripoffset == NULL || new_stripbytecount == NULL) { + if (new_stripoffset) + _TIFFfree(new_stripoffset); + if (new_stripbytecount) + _TIFFfree(new_stripbytecount); + td->td_nstrips = 0; + TIFFErrorExt(tif->tif_clientdata, module, "%s: No space to expand strip arrays", + tif->tif_name); + return (0); + } + td->td_stripoffset = new_stripoffset; + td->td_stripbytecount = new_stripbytecount; + _TIFFmemset(td->td_stripoffset + td->td_nstrips, + 0, delta*sizeof (uint32)); + _TIFFmemset(td->td_stripbytecount + td->td_nstrips, + 0, delta*sizeof (uint32)); + td->td_nstrips += delta; + return (1); +} + +/* + * Append the data to the specified strip. + */ +static int +TIFFAppendToStrip(TIFF* tif, tstrip_t strip, tidata_t data, tsize_t cc) +{ + static const char module[] = "TIFFAppendToStrip"; + TIFFDirectory *td = &tif->tif_dir; + + if (td->td_stripoffset[strip] == 0 || tif->tif_curoff == 0) { + assert(td->td_nstrips > 0); + + if( td->td_stripbytecount[strip] != 0 + && td->td_stripoffset[strip] != 0 + && td->td_stripbytecount[strip] >= cc ) + { + /* + * There is already tile data on disk, and the new tile + * data we have to will fit in the same space. The only + * aspect of this that is risky is that there could be + * more data to append to this strip before we are done + * depending on how we are getting called. + */ + if (!SeekOK(tif, td->td_stripoffset[strip])) { + TIFFErrorExt(tif->tif_clientdata, module, + "Seek error at scanline %lu", + (unsigned long)tif->tif_row); + return (0); + } + } + else + { + /* + * Seek to end of file, and set that as our location to + * write this strip. + */ + td->td_stripoffset[strip] = TIFFSeekFile(tif, 0, SEEK_END); + } + + tif->tif_curoff = td->td_stripoffset[strip]; + + /* + * We are starting a fresh strip/tile, so set the size to zero. + */ + td->td_stripbytecount[strip] = 0; + } + + if (!WriteOK(tif, data, cc)) { + TIFFErrorExt(tif->tif_clientdata, module, "Write error at scanline %lu", + (unsigned long) tif->tif_row); + return (0); + } + tif->tif_curoff = tif->tif_curoff+cc; + td->td_stripbytecount[strip] += cc; + return (1); +} + +/* + * Internal version of TIFFFlushData that can be + * called by ``encodestrip routines'' w/o concern + * for infinite recursion. + */ +int +TIFFFlushData1(TIFF* tif) +{ + if (tif->tif_rawcc > 0) { + if (!isFillOrder(tif, tif->tif_dir.td_fillorder) && + (tif->tif_flags & TIFF_NOBITREV) == 0) + TIFFReverseBits((unsigned char *)tif->tif_rawdata, + tif->tif_rawcc); + if (!TIFFAppendToStrip(tif, + isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip, + tif->tif_rawdata, tif->tif_rawcc)) + return (0); + tif->tif_rawcc = 0; + tif->tif_rawcp = tif->tif_rawdata; + } + return (1); +} + +/* + * Set the current write offset. This should only be + * used to set the offset to a known previous location + * (very carefully), or to 0 so that the next write gets + * appended to the end of the file. + */ +void +TIFFSetWriteOffset(TIFF* tif, toff_t off) +{ + tif->tif_curoff = off; +} + +/* vim: set ts=8 sts=8 sw=8 noet: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tif_zip.c b/reactos/dll/3rdparty/libtiff/tif_zip.c new file mode 100644 index 00000000000..15091f8daaf --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tif_zip.c @@ -0,0 +1,419 @@ +/* $Id: tif_zip.c,v 1.11.2.4 2010-06-08 18:50:43 bfriesen Exp $ */ + +/* + * Copyright (c) 1995-1997 Sam Leffler + * Copyright (c) 1995-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include "tiffiop.h" +#ifdef ZIP_SUPPORT +/* + * TIFF Library. + * + * ZIP (aka Deflate) Compression Support + * + * This file is simply an interface to the zlib library written by + * Jean-loup Gailly and Mark Adler. You must use version 1.0 or later + * of the library: this code assumes the 1.0 API and also depends on + * the ability to write the zlib header multiple times (one per strip) + * which was not possible with versions prior to 0.95. Note also that + * older versions of this codec avoided this bug by supressing the header + * entirely. This means that files written with the old library cannot + * be read; they should be converted to a different compression scheme + * and then reconverted. + * + * The data format used by the zlib library is described in the files + * zlib-3.1.doc, deflate-1.1.doc and gzip-4.1.doc, available in the + * directory ftp://ftp.uu.net/pub/archiving/zip/doc. The library was + * last found at ftp://ftp.uu.net/pub/archiving/zip/zlib/zlib-0.99.tar.gz. + */ +#include "tif_predict.h" +#include "zlib.h" + +#include + +/* + * Sigh, ZLIB_VERSION is defined as a string so there's no + * way to do a proper check here. Instead we guess based + * on the presence of #defines that were added between the + * 0.95 and 1.0 distributions. + */ +#if !defined(Z_NO_COMPRESSION) || !defined(Z_DEFLATED) +#error "Antiquated ZLIB software; you must use version 1.0 or later" +#endif + +/* + * State block for each open TIFF + * file using ZIP compression/decompression. + */ +typedef struct { + TIFFPredictorState predict; + z_stream stream; + int zipquality; /* compression level */ + int state; /* state flags */ +#define ZSTATE_INIT_DECODE 0x01 +#define ZSTATE_INIT_ENCODE 0x02 + + TIFFVGetMethod vgetparent; /* super-class method */ + TIFFVSetMethod vsetparent; /* super-class method */ +} ZIPState; + +#define ZState(tif) ((ZIPState*) (tif)->tif_data) +#define DecoderState(tif) ZState(tif) +#define EncoderState(tif) ZState(tif) + +static int ZIPEncode(TIFF*, tidata_t, tsize_t, tsample_t); +static int ZIPDecode(TIFF*, tidata_t, tsize_t, tsample_t); + +static int +ZIPSetupDecode(TIFF* tif) +{ + ZIPState* sp = DecoderState(tif); + static const char module[] = "ZIPSetupDecode"; + + assert(sp != NULL); + + /* if we were last encoding, terminate this mode */ + if (sp->state & ZSTATE_INIT_ENCODE) { + deflateEnd(&sp->stream); + sp->state = 0; + } + + if (inflateInit(&sp->stream) != Z_OK) { + TIFFErrorExt(tif->tif_clientdata, module, "%s: %s", tif->tif_name, sp->stream.msg); + return (0); + } else { + sp->state |= ZSTATE_INIT_DECODE; + return (1); + } +} + +/* + * Setup state for decoding a strip. + */ +static int +ZIPPreDecode(TIFF* tif, tsample_t s) +{ + ZIPState* sp = DecoderState(tif); + + (void) s; + assert(sp != NULL); + + if( (sp->state & ZSTATE_INIT_DECODE) == 0 ) + tif->tif_setupdecode( tif ); + + sp->stream.next_in = tif->tif_rawdata; + sp->stream.avail_in = tif->tif_rawcc; + return (inflateReset(&sp->stream) == Z_OK); +} + +static int +ZIPDecode(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s) +{ + ZIPState* sp = DecoderState(tif); + static const char module[] = "ZIPDecode"; + + (void) s; + assert(sp != NULL); + assert(sp->state == ZSTATE_INIT_DECODE); + + sp->stream.next_out = op; + sp->stream.avail_out = occ; + do { + int state = inflate(&sp->stream, Z_PARTIAL_FLUSH); + if (state == Z_STREAM_END) + break; + if (state == Z_DATA_ERROR) { + TIFFErrorExt(tif->tif_clientdata, module, + "%s: Decoding error at scanline %d, %s", + tif->tif_name, tif->tif_row, sp->stream.msg); + if (inflateSync(&sp->stream) != Z_OK) + return (0); + continue; + } + if (state != Z_OK) { + TIFFErrorExt(tif->tif_clientdata, module, "%s: zlib error: %s", + tif->tif_name, sp->stream.msg); + return (0); + } + } while (sp->stream.avail_out > 0); + if (sp->stream.avail_out != 0) { + TIFFErrorExt(tif->tif_clientdata, module, + "%s: Not enough data at scanline %d (short %d bytes)", + tif->tif_name, tif->tif_row, sp->stream.avail_out); + return (0); + } + return (1); +} + +static int +ZIPSetupEncode(TIFF* tif) +{ + ZIPState* sp = EncoderState(tif); + static const char module[] = "ZIPSetupEncode"; + + assert(sp != NULL); + if (sp->state & ZSTATE_INIT_DECODE) { + inflateEnd(&sp->stream); + sp->state = 0; + } + + if (deflateInit(&sp->stream, sp->zipquality) != Z_OK) { + TIFFErrorExt(tif->tif_clientdata, module, "%s: %s", tif->tif_name, sp->stream.msg); + return (0); + } else { + sp->state |= ZSTATE_INIT_ENCODE; + return (1); + } +} + +/* + * Reset encoding state at the start of a strip. + */ +static int +ZIPPreEncode(TIFF* tif, tsample_t s) +{ + ZIPState *sp = EncoderState(tif); + + (void) s; + assert(sp != NULL); + if( sp->state != ZSTATE_INIT_ENCODE ) + tif->tif_setupencode( tif ); + + sp->stream.next_out = tif->tif_rawdata; + sp->stream.avail_out = tif->tif_rawdatasize; + return (deflateReset(&sp->stream) == Z_OK); +} + +/* + * Encode a chunk of pixels. + */ +static int +ZIPEncode(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s) +{ + ZIPState *sp = EncoderState(tif); + static const char module[] = "ZIPEncode"; + + assert(sp != NULL); + assert(sp->state == ZSTATE_INIT_ENCODE); + + (void) s; + sp->stream.next_in = bp; + sp->stream.avail_in = cc; + do { + if (deflate(&sp->stream, Z_NO_FLUSH) != Z_OK) { + TIFFErrorExt(tif->tif_clientdata, module, "%s: Encoder error: %s", + tif->tif_name, sp->stream.msg); + return (0); + } + if (sp->stream.avail_out == 0) { + tif->tif_rawcc = tif->tif_rawdatasize; + TIFFFlushData1(tif); + sp->stream.next_out = tif->tif_rawdata; + sp->stream.avail_out = tif->tif_rawdatasize; + } + } while (sp->stream.avail_in > 0); + return (1); +} + +/* + * Finish off an encoded strip by flushing the last + * string and tacking on an End Of Information code. + */ +static int +ZIPPostEncode(TIFF* tif) +{ + ZIPState *sp = EncoderState(tif); + static const char module[] = "ZIPPostEncode"; + int state; + + sp->stream.avail_in = 0; + do { + state = deflate(&sp->stream, Z_FINISH); + switch (state) { + case Z_STREAM_END: + case Z_OK: + if ((int)sp->stream.avail_out != (int)tif->tif_rawdatasize) + { + tif->tif_rawcc = + tif->tif_rawdatasize - sp->stream.avail_out; + TIFFFlushData1(tif); + sp->stream.next_out = tif->tif_rawdata; + sp->stream.avail_out = tif->tif_rawdatasize; + } + break; + default: + TIFFErrorExt(tif->tif_clientdata, module, "%s: zlib error: %s", + tif->tif_name, sp->stream.msg); + return (0); + } + } while (state != Z_STREAM_END); + return (1); +} + +static void +ZIPCleanup(TIFF* tif) +{ + ZIPState* sp = ZState(tif); + + assert(sp != 0); + + (void)TIFFPredictorCleanup(tif); + + tif->tif_tagmethods.vgetfield = sp->vgetparent; + tif->tif_tagmethods.vsetfield = sp->vsetparent; + + if (sp->state & ZSTATE_INIT_ENCODE) { + deflateEnd(&sp->stream); + sp->state = 0; + } else if( sp->state & ZSTATE_INIT_DECODE) { + inflateEnd(&sp->stream); + sp->state = 0; + } + _TIFFfree(sp); + tif->tif_data = NULL; + + _TIFFSetDefaultCompressionState(tif); +} + +static int +ZIPVSetField(TIFF* tif, ttag_t tag, va_list ap) +{ + ZIPState* sp = ZState(tif); + static const char module[] = "ZIPVSetField"; + + switch (tag) { + case TIFFTAG_ZIPQUALITY: + sp->zipquality = va_arg(ap, int); + if ( sp->state&ZSTATE_INIT_ENCODE ) { + if (deflateParams(&sp->stream, + sp->zipquality, Z_DEFAULT_STRATEGY) != Z_OK) { + TIFFErrorExt(tif->tif_clientdata, module, "%s: zlib error: %s", + tif->tif_name, sp->stream.msg); + return (0); + } + } + return (1); + default: + return (*sp->vsetparent)(tif, tag, ap); + } + /*NOTREACHED*/ +} + +static int +ZIPVGetField(TIFF* tif, ttag_t tag, va_list ap) +{ + ZIPState* sp = ZState(tif); + + switch (tag) { + case TIFFTAG_ZIPQUALITY: + *va_arg(ap, int*) = sp->zipquality; + break; + default: + return (*sp->vgetparent)(tif, tag, ap); + } + return (1); +} + +static const TIFFFieldInfo zipFieldInfo[] = { + { TIFFTAG_ZIPQUALITY, 0, 0, TIFF_ANY, FIELD_PSEUDO, + TRUE, FALSE, "" }, +}; + +int +TIFFInitZIP(TIFF* tif, int scheme) +{ + static const char module[] = "TIFFInitZIP"; + ZIPState* sp; + + assert( (scheme == COMPRESSION_DEFLATE) + || (scheme == COMPRESSION_ADOBE_DEFLATE)); + + /* + * Merge codec-specific tag information. + */ + if (!_TIFFMergeFieldInfo(tif, zipFieldInfo, + TIFFArrayCount(zipFieldInfo))) { + TIFFErrorExt(tif->tif_clientdata, module, + "Merging Deflate codec-specific tags failed"); + return 0; + } + + /* + * Allocate state block so tag methods have storage to record values. + */ + tif->tif_data = (tidata_t) _TIFFmalloc(sizeof (ZIPState)); + if (tif->tif_data == NULL) + goto bad; + sp = ZState(tif); + sp->stream.zalloc = NULL; + sp->stream.zfree = NULL; + sp->stream.opaque = NULL; + sp->stream.data_type = Z_BINARY; + + /* + * Override parent get/set field methods. + */ + sp->vgetparent = tif->tif_tagmethods.vgetfield; + tif->tif_tagmethods.vgetfield = ZIPVGetField; /* hook for codec tags */ + sp->vsetparent = tif->tif_tagmethods.vsetfield; + tif->tif_tagmethods.vsetfield = ZIPVSetField; /* hook for codec tags */ + + /* Default values for codec-specific fields */ + sp->zipquality = Z_DEFAULT_COMPRESSION; /* default comp. level */ + sp->state = 0; + + /* + * Install codec methods. + */ + tif->tif_setupdecode = ZIPSetupDecode; + tif->tif_predecode = ZIPPreDecode; + tif->tif_decoderow = ZIPDecode; + tif->tif_decodestrip = ZIPDecode; + tif->tif_decodetile = ZIPDecode; + tif->tif_setupencode = ZIPSetupEncode; + tif->tif_preencode = ZIPPreEncode; + tif->tif_postencode = ZIPPostEncode; + tif->tif_encoderow = ZIPEncode; + tif->tif_encodestrip = ZIPEncode; + tif->tif_encodetile = ZIPEncode; + tif->tif_cleanup = ZIPCleanup; + /* + * Setup predictor setup. + */ + (void) TIFFPredictorInit(tif); + return (1); +bad: + TIFFErrorExt(tif->tif_clientdata, module, + "No space for ZIP state block"); + return (0); +} +#endif /* ZIP_SUPORT */ + +/* vim: set ts=8 sts=8 sw=8 noet: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tiff.h b/reactos/dll/3rdparty/libtiff/tiff.h new file mode 100644 index 00000000000..0d4ab9f819f --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tiff.h @@ -0,0 +1,654 @@ +/* $Id: tiff.h,v 1.43.2.1 2010-06-08 18:50:43 bfriesen Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _TIFF_ +#define _TIFF_ + +#include "tiffconf.h" + +/* + * Tag Image File Format (TIFF) + * + * Based on Rev 6.0 from: + * Developer's Desk + * Aldus Corporation + * 411 First Ave. South + * Suite 200 + * Seattle, WA 98104 + * 206-622-5500 + * + * (http://partners.adobe.com/asn/developer/PDFS/TN/TIFF6.pdf) + * + * For Big TIFF design notes see the following link + * http://www.remotesensing.org/libtiff/bigtiffdesign.html + */ +#define TIFF_VERSION 42 +#define TIFF_BIGTIFF_VERSION 43 + +#define TIFF_BIGENDIAN 0x4d4d +#define TIFF_LITTLEENDIAN 0x4949 +#define MDI_LITTLEENDIAN 0x5045 +#define MDI_BIGENDIAN 0x4550 +/* + * Intrinsic data types required by the file format: + * + * 8-bit quantities int8/uint8 + * 16-bit quantities int16/uint16 + * 32-bit quantities int32/uint32 + * strings unsigned char* + */ + +#ifndef HAVE_INT8 +typedef signed char int8; /* NB: non-ANSI compilers may not grok */ +#endif +typedef unsigned char uint8; +#ifndef HAVE_INT16 +typedef short int16; +#endif +typedef unsigned short uint16; /* sizeof (uint16) must == 2 */ +#if SIZEOF_INT == 4 +#ifndef HAVE_INT32 +typedef int int32; +#endif +typedef unsigned int uint32; /* sizeof (uint32) must == 4 */ +#elif SIZEOF_LONG == 4 +#ifndef HAVE_INT32 +typedef long int32; +#endif +typedef unsigned long uint32; /* sizeof (uint32) must == 4 */ +#endif + +/* For TIFFReassignTagToIgnore */ +enum TIFFIgnoreSense /* IGNORE tag table */ +{ + TIS_STORE, + TIS_EXTRACT, + TIS_EMPTY +}; + +/* + * TIFF header. + */ +typedef struct { + uint16 tiff_magic; /* magic number (defines byte order) */ +#define TIFF_MAGIC_SIZE 2 + uint16 tiff_version; /* TIFF version number */ +#define TIFF_VERSION_SIZE 2 + uint32 tiff_diroff; /* byte offset to first directory */ +#define TIFF_DIROFFSET_SIZE 4 +} TIFFHeader; + + +/* + * TIFF Image File Directories are comprised of a table of field + * descriptors of the form shown below. The table is sorted in + * ascending order by tag. The values associated with each entry are + * disjoint and may appear anywhere in the file (so long as they are + * placed on a word boundary). + * + * If the value is 4 bytes or less, then it is placed in the offset + * field to save space. If the value is less than 4 bytes, it is + * left-justified in the offset field. + */ +typedef struct { + uint16 tdir_tag; /* see below */ + uint16 tdir_type; /* data type; see below */ + uint32 tdir_count; /* number of items; length in spec */ + uint32 tdir_offset; /* byte offset to field data */ +} TIFFDirEntry; + +/* + * NB: In the comments below, + * - items marked with a + are obsoleted by revision 5.0, + * - items marked with a ! are introduced in revision 6.0. + * - items marked with a % are introduced post revision 6.0. + * - items marked with a $ are obsoleted by revision 6.0. + * - items marked with a & are introduced by Adobe DNG specification. + */ + +/* + * Tag data type information. + * + * Note: RATIONALs are the ratio of two 32-bit integer values. + */ +typedef enum { + TIFF_NOTYPE = 0, /* placeholder */ + TIFF_BYTE = 1, /* 8-bit unsigned integer */ + TIFF_ASCII = 2, /* 8-bit bytes w/ last byte null */ + TIFF_SHORT = 3, /* 16-bit unsigned integer */ + TIFF_LONG = 4, /* 32-bit unsigned integer */ + TIFF_RATIONAL = 5, /* 64-bit unsigned fraction */ + TIFF_SBYTE = 6, /* !8-bit signed integer */ + TIFF_UNDEFINED = 7, /* !8-bit untyped data */ + TIFF_SSHORT = 8, /* !16-bit signed integer */ + TIFF_SLONG = 9, /* !32-bit signed integer */ + TIFF_SRATIONAL = 10, /* !64-bit signed fraction */ + TIFF_FLOAT = 11, /* !32-bit IEEE floating point */ + TIFF_DOUBLE = 12, /* !64-bit IEEE floating point */ + TIFF_IFD = 13 /* %32-bit unsigned integer (offset) */ +} TIFFDataType; + +/* + * TIFF Tag Definitions. + */ +#define TIFFTAG_SUBFILETYPE 254 /* subfile data descriptor */ +#define FILETYPE_REDUCEDIMAGE 0x1 /* reduced resolution version */ +#define FILETYPE_PAGE 0x2 /* one page of many */ +#define FILETYPE_MASK 0x4 /* transparency mask */ +#define TIFFTAG_OSUBFILETYPE 255 /* +kind of data in subfile */ +#define OFILETYPE_IMAGE 1 /* full resolution image data */ +#define OFILETYPE_REDUCEDIMAGE 2 /* reduced size image data */ +#define OFILETYPE_PAGE 3 /* one page of many */ +#define TIFFTAG_IMAGEWIDTH 256 /* image width in pixels */ +#define TIFFTAG_IMAGELENGTH 257 /* image height in pixels */ +#define TIFFTAG_BITSPERSAMPLE 258 /* bits per channel (sample) */ +#define TIFFTAG_COMPRESSION 259 /* data compression technique */ +#define COMPRESSION_NONE 1 /* dump mode */ +#define COMPRESSION_CCITTRLE 2 /* CCITT modified Huffman RLE */ +#define COMPRESSION_CCITTFAX3 3 /* CCITT Group 3 fax encoding */ +#define COMPRESSION_CCITT_T4 3 /* CCITT T.4 (TIFF 6 name) */ +#define COMPRESSION_CCITTFAX4 4 /* CCITT Group 4 fax encoding */ +#define COMPRESSION_CCITT_T6 4 /* CCITT T.6 (TIFF 6 name) */ +#define COMPRESSION_LZW 5 /* Lempel-Ziv & Welch */ +#define COMPRESSION_OJPEG 6 /* !6.0 JPEG */ +#define COMPRESSION_JPEG 7 /* %JPEG DCT compression */ +#define COMPRESSION_NEXT 32766 /* NeXT 2-bit RLE */ +#define COMPRESSION_CCITTRLEW 32771 /* #1 w/ word alignment */ +#define COMPRESSION_PACKBITS 32773 /* Macintosh RLE */ +#define COMPRESSION_THUNDERSCAN 32809 /* ThunderScan RLE */ +/* codes 32895-32898 are reserved for ANSI IT8 TIFF/IT */ +#define COMPRESSION_DCS 32947 /* Kodak DCS encoding */ +#define COMPRESSION_JBIG 34661 /* ISO JBIG */ +#define COMPRESSION_SGILOG 34676 /* SGI Log Luminance RLE */ +#define COMPRESSION_SGILOG24 34677 /* SGI Log 24-bit packed */ +#define COMPRESSION_JP2000 34712 /* Leadtools JPEG2000 */ +#define TIFFTAG_PHOTOMETRIC 262 /* photometric interpretation */ +#define PHOTOMETRIC_MINISWHITE 0 /* min value is white */ +#define PHOTOMETRIC_MINISBLACK 1 /* min value is black */ +#define PHOTOMETRIC_RGB 2 /* RGB color model */ +#define PHOTOMETRIC_PALETTE 3 /* color map indexed */ +#define PHOTOMETRIC_MASK 4 /* $holdout mask */ +#define PHOTOMETRIC_SEPARATED 5 /* !color separations */ +#define PHOTOMETRIC_YCBCR 6 /* !CCIR 601 */ +#define PHOTOMETRIC_CIELAB 8 /* !1976 CIE L*a*b* */ +#define PHOTOMETRIC_ICCLAB 9 /* ICC L*a*b* [Adobe TIFF Technote 4] */ +#define PHOTOMETRIC_ITULAB 10 /* ITU L*a*b* */ +#define PHOTOMETRIC_LOGL 32844 /* CIE Log2(L) */ +#define PHOTOMETRIC_LOGLUV 32845 /* CIE Log2(L) (u',v') */ +#define TIFFTAG_THRESHHOLDING 263 /* +thresholding used on data */ +#define THRESHHOLD_BILEVEL 1 /* b&w art scan */ +#define THRESHHOLD_HALFTONE 2 /* or dithered scan */ +#define THRESHHOLD_ERRORDIFFUSE 3 /* usually floyd-steinberg */ +#define TIFFTAG_CELLWIDTH 264 /* +dithering matrix width */ +#define TIFFTAG_CELLLENGTH 265 /* +dithering matrix height */ +#define TIFFTAG_FILLORDER 266 /* data order within a byte */ +#define FILLORDER_MSB2LSB 1 /* most significant -> least */ +#define FILLORDER_LSB2MSB 2 /* least significant -> most */ +#define TIFFTAG_DOCUMENTNAME 269 /* name of doc. image is from */ +#define TIFFTAG_IMAGEDESCRIPTION 270 /* info about image */ +#define TIFFTAG_MAKE 271 /* scanner manufacturer name */ +#define TIFFTAG_MODEL 272 /* scanner model name/number */ +#define TIFFTAG_STRIPOFFSETS 273 /* offsets to data strips */ +#define TIFFTAG_ORIENTATION 274 /* +image orientation */ +#define ORIENTATION_TOPLEFT 1 /* row 0 top, col 0 lhs */ +#define ORIENTATION_TOPRIGHT 2 /* row 0 top, col 0 rhs */ +#define ORIENTATION_BOTRIGHT 3 /* row 0 bottom, col 0 rhs */ +#define ORIENTATION_BOTLEFT 4 /* row 0 bottom, col 0 lhs */ +#define ORIENTATION_LEFTTOP 5 /* row 0 lhs, col 0 top */ +#define ORIENTATION_RIGHTTOP 6 /* row 0 rhs, col 0 top */ +#define ORIENTATION_RIGHTBOT 7 /* row 0 rhs, col 0 bottom */ +#define ORIENTATION_LEFTBOT 8 /* row 0 lhs, col 0 bottom */ +#define TIFFTAG_SAMPLESPERPIXEL 277 /* samples per pixel */ +#define TIFFTAG_ROWSPERSTRIP 278 /* rows per strip of data */ +#define TIFFTAG_STRIPBYTECOUNTS 279 /* bytes counts for strips */ +#define TIFFTAG_MINSAMPLEVALUE 280 /* +minimum sample value */ +#define TIFFTAG_MAXSAMPLEVALUE 281 /* +maximum sample value */ +#define TIFFTAG_XRESOLUTION 282 /* pixels/resolution in x */ +#define TIFFTAG_YRESOLUTION 283 /* pixels/resolution in y */ +#define TIFFTAG_PLANARCONFIG 284 /* storage organization */ +#define PLANARCONFIG_CONTIG 1 /* single image plane */ +#define PLANARCONFIG_SEPARATE 2 /* separate planes of data */ +#define TIFFTAG_PAGENAME 285 /* page name image is from */ +#define TIFFTAG_XPOSITION 286 /* x page offset of image lhs */ +#define TIFFTAG_YPOSITION 287 /* y page offset of image lhs */ +#define TIFFTAG_FREEOFFSETS 288 /* +byte offset to free block */ +#define TIFFTAG_FREEBYTECOUNTS 289 /* +sizes of free blocks */ +#define TIFFTAG_GRAYRESPONSEUNIT 290 /* $gray scale curve accuracy */ +#define GRAYRESPONSEUNIT_10S 1 /* tenths of a unit */ +#define GRAYRESPONSEUNIT_100S 2 /* hundredths of a unit */ +#define GRAYRESPONSEUNIT_1000S 3 /* thousandths of a unit */ +#define GRAYRESPONSEUNIT_10000S 4 /* ten-thousandths of a unit */ +#define GRAYRESPONSEUNIT_100000S 5 /* hundred-thousandths */ +#define TIFFTAG_GRAYRESPONSECURVE 291 /* $gray scale response curve */ +#define TIFFTAG_GROUP3OPTIONS 292 /* 32 flag bits */ +#define TIFFTAG_T4OPTIONS 292 /* TIFF 6.0 proper name alias */ +#define GROUP3OPT_2DENCODING 0x1 /* 2-dimensional coding */ +#define GROUP3OPT_UNCOMPRESSED 0x2 /* data not compressed */ +#define GROUP3OPT_FILLBITS 0x4 /* fill to byte boundary */ +#define TIFFTAG_GROUP4OPTIONS 293 /* 32 flag bits */ +#define TIFFTAG_T6OPTIONS 293 /* TIFF 6.0 proper name */ +#define GROUP4OPT_UNCOMPRESSED 0x2 /* data not compressed */ +#define TIFFTAG_RESOLUTIONUNIT 296 /* units of resolutions */ +#define RESUNIT_NONE 1 /* no meaningful units */ +#define RESUNIT_INCH 2 /* english */ +#define RESUNIT_CENTIMETER 3 /* metric */ +#define TIFFTAG_PAGENUMBER 297 /* page numbers of multi-page */ +#define TIFFTAG_COLORRESPONSEUNIT 300 /* $color curve accuracy */ +#define COLORRESPONSEUNIT_10S 1 /* tenths of a unit */ +#define COLORRESPONSEUNIT_100S 2 /* hundredths of a unit */ +#define COLORRESPONSEUNIT_1000S 3 /* thousandths of a unit */ +#define COLORRESPONSEUNIT_10000S 4 /* ten-thousandths of a unit */ +#define COLORRESPONSEUNIT_100000S 5 /* hundred-thousandths */ +#define TIFFTAG_TRANSFERFUNCTION 301 /* !colorimetry info */ +#define TIFFTAG_SOFTWARE 305 /* name & release */ +#define TIFFTAG_DATETIME 306 /* creation date and time */ +#define TIFFTAG_ARTIST 315 /* creator of image */ +#define TIFFTAG_HOSTCOMPUTER 316 /* machine where created */ +#define TIFFTAG_PREDICTOR 317 /* prediction scheme w/ LZW */ +#define PREDICTOR_NONE 1 /* no prediction scheme used */ +#define PREDICTOR_HORIZONTAL 2 /* horizontal differencing */ +#define PREDICTOR_FLOATINGPOINT 3 /* floating point predictor */ +#define TIFFTAG_WHITEPOINT 318 /* image white point */ +#define TIFFTAG_PRIMARYCHROMATICITIES 319 /* !primary chromaticities */ +#define TIFFTAG_COLORMAP 320 /* RGB map for pallette image */ +#define TIFFTAG_HALFTONEHINTS 321 /* !highlight+shadow info */ +#define TIFFTAG_TILEWIDTH 322 /* !tile width in pixels */ +#define TIFFTAG_TILELENGTH 323 /* !tile height in pixels */ +#define TIFFTAG_TILEOFFSETS 324 /* !offsets to data tiles */ +#define TIFFTAG_TILEBYTECOUNTS 325 /* !byte counts for tiles */ +#define TIFFTAG_BADFAXLINES 326 /* lines w/ wrong pixel count */ +#define TIFFTAG_CLEANFAXDATA 327 /* regenerated line info */ +#define CLEANFAXDATA_CLEAN 0 /* no errors detected */ +#define CLEANFAXDATA_REGENERATED 1 /* receiver regenerated lines */ +#define CLEANFAXDATA_UNCLEAN 2 /* uncorrected errors exist */ +#define TIFFTAG_CONSECUTIVEBADFAXLINES 328 /* max consecutive bad lines */ +#define TIFFTAG_SUBIFD 330 /* subimage descriptors */ +#define TIFFTAG_INKSET 332 /* !inks in separated image */ +#define INKSET_CMYK 1 /* !cyan-magenta-yellow-black color */ +#define INKSET_MULTIINK 2 /* !multi-ink or hi-fi color */ +#define TIFFTAG_INKNAMES 333 /* !ascii names of inks */ +#define TIFFTAG_NUMBEROFINKS 334 /* !number of inks */ +#define TIFFTAG_DOTRANGE 336 /* !0% and 100% dot codes */ +#define TIFFTAG_TARGETPRINTER 337 /* !separation target */ +#define TIFFTAG_EXTRASAMPLES 338 /* !info about extra samples */ +#define EXTRASAMPLE_UNSPECIFIED 0 /* !unspecified data */ +#define EXTRASAMPLE_ASSOCALPHA 1 /* !associated alpha data */ +#define EXTRASAMPLE_UNASSALPHA 2 /* !unassociated alpha data */ +#define TIFFTAG_SAMPLEFORMAT 339 /* !data sample format */ +#define SAMPLEFORMAT_UINT 1 /* !unsigned integer data */ +#define SAMPLEFORMAT_INT 2 /* !signed integer data */ +#define SAMPLEFORMAT_IEEEFP 3 /* !IEEE floating point data */ +#define SAMPLEFORMAT_VOID 4 /* !untyped data */ +#define SAMPLEFORMAT_COMPLEXINT 5 /* !complex signed int */ +#define SAMPLEFORMAT_COMPLEXIEEEFP 6 /* !complex ieee floating */ +#define TIFFTAG_SMINSAMPLEVALUE 340 /* !variable MinSampleValue */ +#define TIFFTAG_SMAXSAMPLEVALUE 341 /* !variable MaxSampleValue */ +#define TIFFTAG_CLIPPATH 343 /* %ClipPath + [Adobe TIFF technote 2] */ +#define TIFFTAG_XCLIPPATHUNITS 344 /* %XClipPathUnits + [Adobe TIFF technote 2] */ +#define TIFFTAG_YCLIPPATHUNITS 345 /* %YClipPathUnits + [Adobe TIFF technote 2] */ +#define TIFFTAG_INDEXED 346 /* %Indexed + [Adobe TIFF Technote 3] */ +#define TIFFTAG_JPEGTABLES 347 /* %JPEG table stream */ +#define TIFFTAG_OPIPROXY 351 /* %OPI Proxy [Adobe TIFF technote] */ +/* + * Tags 512-521 are obsoleted by Technical Note #2 which specifies a + * revised JPEG-in-TIFF scheme. + */ +#define TIFFTAG_JPEGPROC 512 /* !JPEG processing algorithm */ +#define JPEGPROC_BASELINE 1 /* !baseline sequential */ +#define JPEGPROC_LOSSLESS 14 /* !Huffman coded lossless */ +#define TIFFTAG_JPEGIFOFFSET 513 /* !pointer to SOI marker */ +#define TIFFTAG_JPEGIFBYTECOUNT 514 /* !JFIF stream length */ +#define TIFFTAG_JPEGRESTARTINTERVAL 515 /* !restart interval length */ +#define TIFFTAG_JPEGLOSSLESSPREDICTORS 517 /* !lossless proc predictor */ +#define TIFFTAG_JPEGPOINTTRANSFORM 518 /* !lossless point transform */ +#define TIFFTAG_JPEGQTABLES 519 /* !Q matrice offsets */ +#define TIFFTAG_JPEGDCTABLES 520 /* !DCT table offsets */ +#define TIFFTAG_JPEGACTABLES 521 /* !AC coefficient offsets */ +#define TIFFTAG_YCBCRCOEFFICIENTS 529 /* !RGB -> YCbCr transform */ +#define TIFFTAG_YCBCRSUBSAMPLING 530 /* !YCbCr subsampling factors */ +#define TIFFTAG_YCBCRPOSITIONING 531 /* !subsample positioning */ +#define YCBCRPOSITION_CENTERED 1 /* !as in PostScript Level 2 */ +#define YCBCRPOSITION_COSITED 2 /* !as in CCIR 601-1 */ +#define TIFFTAG_REFERENCEBLACKWHITE 532 /* !colorimetry info */ +#define TIFFTAG_XMLPACKET 700 /* %XML packet + [Adobe XMP Specification, + January 2004 */ +#define TIFFTAG_OPIIMAGEID 32781 /* %OPI ImageID + [Adobe TIFF technote] */ +/* tags 32952-32956 are private tags registered to Island Graphics */ +#define TIFFTAG_REFPTS 32953 /* image reference points */ +#define TIFFTAG_REGIONTACKPOINT 32954 /* region-xform tack point */ +#define TIFFTAG_REGIONWARPCORNERS 32955 /* warp quadrilateral */ +#define TIFFTAG_REGIONAFFINE 32956 /* affine transformation mat */ +/* tags 32995-32999 are private tags registered to SGI */ +#define TIFFTAG_MATTEING 32995 /* $use ExtraSamples */ +#define TIFFTAG_DATATYPE 32996 /* $use SampleFormat */ +#define TIFFTAG_IMAGEDEPTH 32997 /* z depth of image */ +#define TIFFTAG_TILEDEPTH 32998 /* z depth/data tile */ +/* tags 33300-33309 are private tags registered to Pixar */ +/* + * TIFFTAG_PIXAR_IMAGEFULLWIDTH and TIFFTAG_PIXAR_IMAGEFULLLENGTH + * are set when an image has been cropped out of a larger image. + * They reflect the size of the original uncropped image. + * The TIFFTAG_XPOSITION and TIFFTAG_YPOSITION can be used + * to determine the position of the smaller image in the larger one. + */ +#define TIFFTAG_PIXAR_IMAGEFULLWIDTH 33300 /* full image size in x */ +#define TIFFTAG_PIXAR_IMAGEFULLLENGTH 33301 /* full image size in y */ + /* Tags 33302-33306 are used to identify special image modes and data + * used by Pixar's texture formats. + */ +#define TIFFTAG_PIXAR_TEXTUREFORMAT 33302 /* texture map format */ +#define TIFFTAG_PIXAR_WRAPMODES 33303 /* s & t wrap modes */ +#define TIFFTAG_PIXAR_FOVCOT 33304 /* cotan(fov) for env. maps */ +#define TIFFTAG_PIXAR_MATRIX_WORLDTOSCREEN 33305 +#define TIFFTAG_PIXAR_MATRIX_WORLDTOCAMERA 33306 +/* tag 33405 is a private tag registered to Eastman Kodak */ +#define TIFFTAG_WRITERSERIALNUMBER 33405 /* device serial number */ +/* tag 33432 is listed in the 6.0 spec w/ unknown ownership */ +#define TIFFTAG_COPYRIGHT 33432 /* copyright string */ +/* IPTC TAG from RichTIFF specifications */ +#define TIFFTAG_RICHTIFFIPTC 33723 +/* 34016-34029 are reserved for ANSI IT8 TIFF/IT */ +#define TIFFTAG_STONITS 37439 /* Sample value to Nits */ +/* tag 34929 is a private tag registered to FedEx */ +#define TIFFTAG_FEDEX_EDR 34929 /* unknown use */ +#define TIFFTAG_INTEROPERABILITYIFD 40965 /* Pointer to Interoperability private directory */ +/* Adobe Digital Negative (DNG) format tags */ +#define TIFFTAG_DNGVERSION 50706 /* &DNG version number */ +#define TIFFTAG_DNGBACKWARDVERSION 50707 /* &DNG compatibility version */ +#define TIFFTAG_UNIQUECAMERAMODEL 50708 /* &name for the camera model */ +#define TIFFTAG_LOCALIZEDCAMERAMODEL 50709 /* &localized camera model + name */ +#define TIFFTAG_CFAPLANECOLOR 50710 /* &CFAPattern->LinearRaw space + mapping */ +#define TIFFTAG_CFALAYOUT 50711 /* &spatial layout of the CFA */ +#define TIFFTAG_LINEARIZATIONTABLE 50712 /* &lookup table description */ +#define TIFFTAG_BLACKLEVELREPEATDIM 50713 /* &repeat pattern size for + the BlackLevel tag */ +#define TIFFTAG_BLACKLEVEL 50714 /* &zero light encoding level */ +#define TIFFTAG_BLACKLEVELDELTAH 50715 /* &zero light encoding level + differences (columns) */ +#define TIFFTAG_BLACKLEVELDELTAV 50716 /* &zero light encoding level + differences (rows) */ +#define TIFFTAG_WHITELEVEL 50717 /* &fully saturated encoding + level */ +#define TIFFTAG_DEFAULTSCALE 50718 /* &default scale factors */ +#define TIFFTAG_DEFAULTCROPORIGIN 50719 /* &origin of the final image + area */ +#define TIFFTAG_DEFAULTCROPSIZE 50720 /* &size of the final image + area */ +#define TIFFTAG_COLORMATRIX1 50721 /* &XYZ->reference color space + transformation matrix 1 */ +#define TIFFTAG_COLORMATRIX2 50722 /* &XYZ->reference color space + transformation matrix 2 */ +#define TIFFTAG_CAMERACALIBRATION1 50723 /* &calibration matrix 1 */ +#define TIFFTAG_CAMERACALIBRATION2 50724 /* &calibration matrix 2 */ +#define TIFFTAG_REDUCTIONMATRIX1 50725 /* &dimensionality reduction + matrix 1 */ +#define TIFFTAG_REDUCTIONMATRIX2 50726 /* &dimensionality reduction + matrix 2 */ +#define TIFFTAG_ANALOGBALANCE 50727 /* &gain applied the stored raw + values*/ +#define TIFFTAG_ASSHOTNEUTRAL 50728 /* &selected white balance in + linear reference space */ +#define TIFFTAG_ASSHOTWHITEXY 50729 /* &selected white balance in + x-y chromaticity + coordinates */ +#define TIFFTAG_BASELINEEXPOSURE 50730 /* &how much to move the zero + point */ +#define TIFFTAG_BASELINENOISE 50731 /* &relative noise level */ +#define TIFFTAG_BASELINESHARPNESS 50732 /* &relative amount of + sharpening */ +#define TIFFTAG_BAYERGREENSPLIT 50733 /* &how closely the values of + the green pixels in the + blue/green rows track the + values of the green pixels + in the red/green rows */ +#define TIFFTAG_LINEARRESPONSELIMIT 50734 /* &non-linear encoding range */ +#define TIFFTAG_CAMERASERIALNUMBER 50735 /* &camera's serial number */ +#define TIFFTAG_LENSINFO 50736 /* info about the lens */ +#define TIFFTAG_CHROMABLURRADIUS 50737 /* &chroma blur radius */ +#define TIFFTAG_ANTIALIASSTRENGTH 50738 /* &relative strength of the + camera's anti-alias filter */ +#define TIFFTAG_SHADOWSCALE 50739 /* &used by Adobe Camera Raw */ +#define TIFFTAG_DNGPRIVATEDATA 50740 /* &manufacturer's private data */ +#define TIFFTAG_MAKERNOTESAFETY 50741 /* &whether the EXIF MakerNote + tag is safe to preserve + along with the rest of the + EXIF data */ +#define TIFFTAG_CALIBRATIONILLUMINANT1 50778 /* &illuminant 1 */ +#define TIFFTAG_CALIBRATIONILLUMINANT2 50779 /* &illuminant 2 */ +#define TIFFTAG_BESTQUALITYSCALE 50780 /* &best quality multiplier */ +#define TIFFTAG_RAWDATAUNIQUEID 50781 /* &unique identifier for + the raw image data */ +#define TIFFTAG_ORIGINALRAWFILENAME 50827 /* &file name of the original + raw file */ +#define TIFFTAG_ORIGINALRAWFILEDATA 50828 /* &contents of the original + raw file */ +#define TIFFTAG_ACTIVEAREA 50829 /* &active (non-masked) pixels + of the sensor */ +#define TIFFTAG_MASKEDAREAS 50830 /* &list of coordinates + of fully masked pixels */ +#define TIFFTAG_ASSHOTICCPROFILE 50831 /* &these two tags used to */ +#define TIFFTAG_ASSHOTPREPROFILEMATRIX 50832 /* map cameras's color space + into ICC profile space */ +#define TIFFTAG_CURRENTICCPROFILE 50833 /* & */ +#define TIFFTAG_CURRENTPREPROFILEMATRIX 50834 /* & */ +/* tag 65535 is an undefined tag used by Eastman Kodak */ +#define TIFFTAG_DCSHUESHIFTVALUES 65535 /* hue shift correction data */ + +/* + * The following are ``pseudo tags'' that can be used to control + * codec-specific functionality. These tags are not written to file. + * Note that these values start at 0xffff+1 so that they'll never + * collide with Aldus-assigned tags. + * + * If you want your private pseudo tags ``registered'' (i.e. added to + * this file), please post a bug report via the tracking system at + * http://www.remotesensing.org/libtiff/bugs.html with the appropriate + * C definitions to add. + */ +#define TIFFTAG_FAXMODE 65536 /* Group 3/4 format control */ +#define FAXMODE_CLASSIC 0x0000 /* default, include RTC */ +#define FAXMODE_NORTC 0x0001 /* no RTC at end of data */ +#define FAXMODE_NOEOL 0x0002 /* no EOL code at end of row */ +#define FAXMODE_BYTEALIGN 0x0004 /* byte align row */ +#define FAXMODE_WORDALIGN 0x0008 /* word align row */ +#define FAXMODE_CLASSF FAXMODE_NORTC /* TIFF Class F */ +#define TIFFTAG_JPEGQUALITY 65537 /* Compression quality level */ +/* Note: quality level is on the IJG 0-100 scale. Default value is 75 */ +#define TIFFTAG_JPEGCOLORMODE 65538 /* Auto RGB<=>YCbCr convert? */ +#define JPEGCOLORMODE_RAW 0x0000 /* no conversion (default) */ +#define JPEGCOLORMODE_RGB 0x0001 /* do auto conversion */ +#define TIFFTAG_JPEGTABLESMODE 65539 /* What to put in JPEGTables */ +#define JPEGTABLESMODE_QUANT 0x0001 /* include quantization tbls */ +#define JPEGTABLESMODE_HUFF 0x0002 /* include Huffman tbls */ +/* Note: default is JPEGTABLESMODE_QUANT | JPEGTABLESMODE_HUFF */ +#define TIFFTAG_FAXFILLFUNC 65540 /* G3/G4 fill function */ +#define TIFFTAG_PIXARLOGDATAFMT 65549 /* PixarLogCodec I/O data sz */ +#define PIXARLOGDATAFMT_8BIT 0 /* regular u_char samples */ +#define PIXARLOGDATAFMT_8BITABGR 1 /* ABGR-order u_chars */ +#define PIXARLOGDATAFMT_11BITLOG 2 /* 11-bit log-encoded (raw) */ +#define PIXARLOGDATAFMT_12BITPICIO 3 /* as per PICIO (1.0==2048) */ +#define PIXARLOGDATAFMT_16BIT 4 /* signed short samples */ +#define PIXARLOGDATAFMT_FLOAT 5 /* IEEE float samples */ +/* 65550-65556 are allocated to Oceana Matrix */ +#define TIFFTAG_DCSIMAGERTYPE 65550 /* imager model & filter */ +#define DCSIMAGERMODEL_M3 0 /* M3 chip (1280 x 1024) */ +#define DCSIMAGERMODEL_M5 1 /* M5 chip (1536 x 1024) */ +#define DCSIMAGERMODEL_M6 2 /* M6 chip (3072 x 2048) */ +#define DCSIMAGERFILTER_IR 0 /* infrared filter */ +#define DCSIMAGERFILTER_MONO 1 /* monochrome filter */ +#define DCSIMAGERFILTER_CFA 2 /* color filter array */ +#define DCSIMAGERFILTER_OTHER 3 /* other filter */ +#define TIFFTAG_DCSINTERPMODE 65551 /* interpolation mode */ +#define DCSINTERPMODE_NORMAL 0x0 /* whole image, default */ +#define DCSINTERPMODE_PREVIEW 0x1 /* preview of image (384x256) */ +#define TIFFTAG_DCSBALANCEARRAY 65552 /* color balance values */ +#define TIFFTAG_DCSCORRECTMATRIX 65553 /* color correction values */ +#define TIFFTAG_DCSGAMMA 65554 /* gamma value */ +#define TIFFTAG_DCSTOESHOULDERPTS 65555 /* toe & shoulder points */ +#define TIFFTAG_DCSCALIBRATIONFD 65556 /* calibration file desc */ +/* Note: quality level is on the ZLIB 1-9 scale. Default value is -1 */ +#define TIFFTAG_ZIPQUALITY 65557 /* compression quality level */ +#define TIFFTAG_PIXARLOGQUALITY 65558 /* PixarLog uses same scale */ +/* 65559 is allocated to Oceana Matrix */ +#define TIFFTAG_DCSCLIPRECTANGLE 65559 /* area of image to acquire */ +#define TIFFTAG_SGILOGDATAFMT 65560 /* SGILog user data format */ +#define SGILOGDATAFMT_FLOAT 0 /* IEEE float samples */ +#define SGILOGDATAFMT_16BIT 1 /* 16-bit samples */ +#define SGILOGDATAFMT_RAW 2 /* uninterpreted data */ +#define SGILOGDATAFMT_8BIT 3 /* 8-bit RGB monitor values */ +#define TIFFTAG_SGILOGENCODE 65561 /* SGILog data encoding control*/ +#define SGILOGENCODE_NODITHER 0 /* do not dither encoded values*/ +#define SGILOGENCODE_RANDITHER 1 /* randomly dither encd values */ + +/* + * EXIF tags + */ +#define EXIFTAG_EXPOSURETIME 33434 /* Exposure time */ +#define EXIFTAG_FNUMBER 33437 /* F number */ +#define EXIFTAG_EXPOSUREPROGRAM 34850 /* Exposure program */ +#define EXIFTAG_SPECTRALSENSITIVITY 34852 /* Spectral sensitivity */ +#define EXIFTAG_ISOSPEEDRATINGS 34855 /* ISO speed rating */ +#define EXIFTAG_OECF 34856 /* Optoelectric conversion + factor */ +#define EXIFTAG_EXIFVERSION 36864 /* Exif version */ +#define EXIFTAG_DATETIMEORIGINAL 36867 /* Date and time of original + data generation */ +#define EXIFTAG_DATETIMEDIGITIZED 36868 /* Date and time of digital + data generation */ +#define EXIFTAG_COMPONENTSCONFIGURATION 37121 /* Meaning of each component */ +#define EXIFTAG_COMPRESSEDBITSPERPIXEL 37122 /* Image compression mode */ +#define EXIFTAG_SHUTTERSPEEDVALUE 37377 /* Shutter speed */ +#define EXIFTAG_APERTUREVALUE 37378 /* Aperture */ +#define EXIFTAG_BRIGHTNESSVALUE 37379 /* Brightness */ +#define EXIFTAG_EXPOSUREBIASVALUE 37380 /* Exposure bias */ +#define EXIFTAG_MAXAPERTUREVALUE 37381 /* Maximum lens aperture */ +#define EXIFTAG_SUBJECTDISTANCE 37382 /* Subject distance */ +#define EXIFTAG_METERINGMODE 37383 /* Metering mode */ +#define EXIFTAG_LIGHTSOURCE 37384 /* Light source */ +#define EXIFTAG_FLASH 37385 /* Flash */ +#define EXIFTAG_FOCALLENGTH 37386 /* Lens focal length */ +#define EXIFTAG_SUBJECTAREA 37396 /* Subject area */ +#define EXIFTAG_MAKERNOTE 37500 /* Manufacturer notes */ +#define EXIFTAG_USERCOMMENT 37510 /* User comments */ +#define EXIFTAG_SUBSECTIME 37520 /* DateTime subseconds */ +#define EXIFTAG_SUBSECTIMEORIGINAL 37521 /* DateTimeOriginal subseconds */ +#define EXIFTAG_SUBSECTIMEDIGITIZED 37522 /* DateTimeDigitized subseconds */ +#define EXIFTAG_FLASHPIXVERSION 40960 /* Supported Flashpix version */ +#define EXIFTAG_COLORSPACE 40961 /* Color space information */ +#define EXIFTAG_PIXELXDIMENSION 40962 /* Valid image width */ +#define EXIFTAG_PIXELYDIMENSION 40963 /* Valid image height */ +#define EXIFTAG_RELATEDSOUNDFILE 40964 /* Related audio file */ +#define EXIFTAG_FLASHENERGY 41483 /* Flash energy */ +#define EXIFTAG_SPATIALFREQUENCYRESPONSE 41484 /* Spatial frequency response */ +#define EXIFTAG_FOCALPLANEXRESOLUTION 41486 /* Focal plane X resolution */ +#define EXIFTAG_FOCALPLANEYRESOLUTION 41487 /* Focal plane Y resolution */ +#define EXIFTAG_FOCALPLANERESOLUTIONUNIT 41488 /* Focal plane resolution unit */ +#define EXIFTAG_SUBJECTLOCATION 41492 /* Subject location */ +#define EXIFTAG_EXPOSUREINDEX 41493 /* Exposure index */ +#define EXIFTAG_SENSINGMETHOD 41495 /* Sensing method */ +#define EXIFTAG_FILESOURCE 41728 /* File source */ +#define EXIFTAG_SCENETYPE 41729 /* Scene type */ +#define EXIFTAG_CFAPATTERN 41730 /* CFA pattern */ +#define EXIFTAG_CUSTOMRENDERED 41985 /* Custom image processing */ +#define EXIFTAG_EXPOSUREMODE 41986 /* Exposure mode */ +#define EXIFTAG_WHITEBALANCE 41987 /* White balance */ +#define EXIFTAG_DIGITALZOOMRATIO 41988 /* Digital zoom ratio */ +#define EXIFTAG_FOCALLENGTHIN35MMFILM 41989 /* Focal length in 35 mm film */ +#define EXIFTAG_SCENECAPTURETYPE 41990 /* Scene capture type */ +#define EXIFTAG_GAINCONTROL 41991 /* Gain control */ +#define EXIFTAG_CONTRAST 41992 /* Contrast */ +#define EXIFTAG_SATURATION 41993 /* Saturation */ +#define EXIFTAG_SHARPNESS 41994 /* Sharpness */ +#define EXIFTAG_DEVICESETTINGDESCRIPTION 41995 /* Device settings description */ +#define EXIFTAG_SUBJECTDISTANCERANGE 41996 /* Subject distance range */ +#define EXIFTAG_GAINCONTROL 41991 /* Gain control */ +#define EXIFTAG_GAINCONTROL 41991 /* Gain control */ +#define EXIFTAG_IMAGEUNIQUEID 42016 /* Unique image ID */ + +#endif /* _TIFF_ */ + +/* vim: set ts=8 sts=8 sw=8 noet: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tiffconf.h b/reactos/dll/3rdparty/libtiff/tiffconf.h new file mode 100644 index 00000000000..b7d59e0712d --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tiffconf.h @@ -0,0 +1,103 @@ +/* + Configuration defines for installed libtiff. + This file maintained for backward compatibility. Do not use definitions + from this file in your programs. +*/ + +#ifndef _TIFFCONF_ +#define _TIFFCONF_ + +/* Define to 1 if the system has the type `int16'. */ +//#define HAVE_INT16 1 + +/* Define to 1 if the system has the type `int32'. */ +//#define HAVE_INT32 1 + +/* Define to 1 if the system has the type `int8'. */ +//#define HAVE_INT8 1 + +/* The size of a `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of a `long', as computed by sizeof. */ +#define SIZEOF_LONG 4 + +/* Compatibility stuff. */ + +/* Define as 0 or 1 according to the floating point format suported by the + machine */ +#define HAVE_IEEEFP 1 + +/* Set the native cpu bit order (FILLORDER_LSB2MSB or FILLORDER_MSB2LSB) */ +#define HOST_FILLORDER FILLORDER_LSB2MSB + +/* Native cpu byte order: 1 if big-endian (Motorola) or 0 if little-endian + (Intel) */ +#define HOST_BIGENDIAN 0 + +/* Support CCITT Group 3 & 4 algorithms */ +#define CCITT_SUPPORT 1 + +/* Support JPEG compression (requires IJG JPEG library) */ +// undef JPEG_SUPPORT + +/* Support JBIG compression (requires JBIG-KIT library) */ +// #undef JBIG_SUPPORT + +/* Support LogLuv high dynamic range encoding */ +#define LOGLUV_SUPPORT 1 + +/* Support LZW algorithm */ +#define LZW_SUPPORT 1 + +/* Support NeXT 2-bit RLE algorithm */ +#define NEXT_SUPPORT 1 + +/* Support Old JPEG compresson (read contrib/ojpeg/README first! Compilation + fails with unpatched IJG JPEG library) */ +// #undef OJPEG_SUPPORT + +/* Support Macintosh PackBits algorithm */ +#define PACKBITS_SUPPORT 1 + +/* Support Pixar log-format algorithm (requires Zlib) */ + #define PIXARLOG_SUPPORT 1 + +/* Support ThunderScan 4-bit RLE algorithm */ +#define THUNDER_SUPPORT 1 + +/* Support Deflate compression */ +#define ZIP_SUPPORT 1 + +/* Support strip chopping (whether or not to convert single-strip uncompressed + images to mutiple strips of ~8Kb to reduce memory usage) */ +#define STRIPCHOP_DEFAULT TIFF_STRIPCHOP + +/* Enable SubIFD tag (330) support */ +#define SUBIFD_SUPPORT 1 + +/* Treat extra sample as alpha (default enabled). The RGBA interface will + treat a fourth sample with no EXTRASAMPLE_ value as being ASSOCALPHA. Many + packages produce RGBA files but don't mark the alpha properly. */ +#define DEFAULT_EXTRASAMPLE_AS_ALPHA 1 + +/* Pick up YCbCr subsampling info from the JPEG data stream to support files + lacking the tag (default enabled). */ +#define CHECK_JPEG_YCBCR_SUBSAMPLING 1 + +/* Support MS MDI magic number files as TIFF */ +#define MDI_SUPPORT 1 + +/* + * Feature support definitions. + * XXX: These macros are obsoleted. Don't use them in your apps! + * Macros stays here for backward compatibility and should be always defined. + */ +#define COLORIMETRY_SUPPORT +#define YCBCR_SUPPORT +#define CMYK_SUPPORT +#define ICC_SUPPORT +#define PHOTOSHOP_SUPPORT +#define IPTC_SUPPORT + +#endif /* _TIFFCONF_ */ diff --git a/reactos/dll/3rdparty/libtiff/tiffconf.vc.h b/reactos/dll/3rdparty/libtiff/tiffconf.vc.h new file mode 100644 index 00000000000..3d14847a277 --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tiffconf.vc.h @@ -0,0 +1,116 @@ +/* + Configuration defines for installed libtiff. + This file maintained for backward compatibility. Do not use definitions + from this file in your programs. +*/ + +#ifndef _TIFFCONF_ +#define _TIFFCONF_ + +/* Define to 1 if the system has the type `int16'. */ +/* #undef HAVE_INT16 */ + +/* Define to 1 if the system has the type `int32'. */ +/* #undef HAVE_INT32 */ + +/* Define to 1 if the system has the type `int8'. */ +/* #undef HAVE_INT8 */ + +/* The size of a `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of a `long', as computed by sizeof. */ +#define SIZEOF_LONG 4 + +/* Signed 64-bit type formatter */ +#define TIFF_INT64_FORMAT "%I64d" + +/* Signed 64-bit type */ +#define TIFF_INT64_T signed __int64 + +/* Unsigned 64-bit type formatter */ +#define TIFF_UINT64_FORMAT "%I64u" + +/* Unsigned 64-bit type */ +#define TIFF_UINT64_T unsigned __int64 + +/* Compatibility stuff. */ + +/* Define as 0 or 1 according to the floating point format suported by the + machine */ +#define HAVE_IEEEFP 1 + +/* Set the native cpu bit order (FILLORDER_LSB2MSB or FILLORDER_MSB2LSB) */ +#define HOST_FILLORDER FILLORDER_LSB2MSB + +/* Native cpu byte order: 1 if big-endian (Motorola) or 0 if little-endian + (Intel) */ +#define HOST_BIGENDIAN 0 + +/* Support CCITT Group 3 & 4 algorithms */ +#define CCITT_SUPPORT 1 + +/* Support JPEG compression (requires IJG JPEG library) */ +/* #undef JPEG_SUPPORT */ + +/* Support LogLuv high dynamic range encoding */ +#define LOGLUV_SUPPORT 1 + +/* Support LZW algorithm */ +#define LZW_SUPPORT 1 + +/* Support NeXT 2-bit RLE algorithm */ +#define NEXT_SUPPORT 1 + +/* Support Old JPEG compresson (read contrib/ojpeg/README first! Compilation + fails with unpatched IJG JPEG library) */ +/* #undef OJPEG_SUPPORT */ + +/* Support Macintosh PackBits algorithm */ +#define PACKBITS_SUPPORT 1 + +/* Support Pixar log-format algorithm (requires Zlib) */ +/* #undef PIXARLOG_SUPPORT */ + +/* Support ThunderScan 4-bit RLE algorithm */ +#define THUNDER_SUPPORT 1 + +/* Support Deflate compression */ +/* #undef ZIP_SUPPORT */ + +/* Support strip chopping (whether or not to convert single-strip uncompressed + images to mutiple strips of ~8Kb to reduce memory usage) */ +#define STRIPCHOP_DEFAULT TIFF_STRIPCHOP + +/* Enable SubIFD tag (330) support */ +#define SUBIFD_SUPPORT 1 + +/* Treat extra sample as alpha (default enabled). The RGBA interface will + treat a fourth sample with no EXTRASAMPLE_ value as being ASSOCALPHA. Many + packages produce RGBA files but don't mark the alpha properly. */ +#define DEFAULT_EXTRASAMPLE_AS_ALPHA 1 + +/* Pick up YCbCr subsampling info from the JPEG data stream to support files + lacking the tag (default enabled). */ +#define CHECK_JPEG_YCBCR_SUBSAMPLING 1 + +/* + * Feature support definitions. + * XXX: These macros are obsoleted. Don't use them in your apps! + * Macros stays here for backward compatibility and should be always defined. + */ +#define COLORIMETRY_SUPPORT +#define YCBCR_SUPPORT +#define CMYK_SUPPORT +#define ICC_SUPPORT +#define PHOTOSHOP_SUPPORT +#define IPTC_SUPPORT + +#endif /* _TIFFCONF_ */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tiffio.h b/reactos/dll/3rdparty/libtiff/tiffio.h new file mode 100644 index 00000000000..06ec25c8298 --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tiffio.h @@ -0,0 +1,526 @@ +/* $Id: tiffio.h,v 1.56.2.4 2010-06-08 18:50:43 bfriesen Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _TIFFIO_ +#define _TIFFIO_ + +/* + * TIFF I/O Library Definitions. + */ +#include "tiff.h" +#include "tiffvers.h" + +/* + * TIFF is defined as an incomplete type to hide the + * library's internal data structures from clients. + */ +typedef struct tiff TIFF; + +/* + * The following typedefs define the intrinsic size of + * data types used in the *exported* interfaces. These + * definitions depend on the proper definition of types + * in tiff.h. Note also that the varargs interface used + * to pass tag types and values uses the types defined in + * tiff.h directly. + * + * NB: ttag_t is unsigned int and not unsigned short because + * ANSI C requires that the type before the ellipsis be a + * promoted type (i.e. one of int, unsigned int, pointer, + * or double) and because we defined pseudo-tags that are + * outside the range of legal Aldus-assigned tags. + * NB: tsize_t is int32 and not uint32 because some functions + * return -1. + * NB: toff_t is not off_t for many reasons; TIFFs max out at + * 32-bit file offsets being the most important, and to ensure + * that it is unsigned, rather than signed. + */ +typedef uint32 ttag_t; /* directory tag */ +typedef uint16 tdir_t; /* directory index */ +typedef uint16 tsample_t; /* sample number */ +typedef uint32 tstrile_t; /* strip or tile number */ +typedef tstrile_t tstrip_t; /* strip number */ +typedef tstrile_t ttile_t; /* tile number */ +typedef int32 tsize_t; /* i/o size in bytes */ +typedef void* tdata_t; /* image data ref */ +typedef uint32 toff_t; /* file offset */ + +#if !defined(__WIN32__) && (defined(_WIN32) || defined(WIN32)) +#define __WIN32__ +#endif + +/* + * On windows you should define USE_WIN32_FILEIO if you are using tif_win32.c + * or AVOID_WIN32_FILEIO if you are using something else (like tif_unix.c). + * + * By default tif_unix.c is assumed. + */ + +#if defined(_WINDOWS) || defined(__WIN32__) || defined(_Windows) +# if !defined(__CYGWIN) && !defined(AVOID_WIN32_FILEIO) && !defined(USE_WIN32_FILEIO) +# define AVOID_WIN32_FILEIO +# endif +#endif + +#if defined(USE_WIN32_FILEIO) +# define VC_EXTRALEAN +# include +# ifdef __WIN32__ +DECLARE_HANDLE(thandle_t); /* Win32 file handle */ +# else +typedef HFILE thandle_t; /* client data handle */ +# endif /* __WIN32__ */ +#else +typedef void* thandle_t; /* client data handle */ +#endif /* USE_WIN32_FILEIO */ + +/* + * Flags to pass to TIFFPrintDirectory to control + * printing of data structures that are potentially + * very large. Bit-or these flags to enable printing + * multiple items. + */ +#define TIFFPRINT_NONE 0x0 /* no extra info */ +#define TIFFPRINT_STRIPS 0x1 /* strips/tiles info */ +#define TIFFPRINT_CURVES 0x2 /* color/gray response curves */ +#define TIFFPRINT_COLORMAP 0x4 /* colormap */ +#define TIFFPRINT_JPEGQTABLES 0x100 /* JPEG Q matrices */ +#define TIFFPRINT_JPEGACTABLES 0x200 /* JPEG AC tables */ +#define TIFFPRINT_JPEGDCTABLES 0x200 /* JPEG DC tables */ + +/* + * Colour conversion stuff + */ + +/* reference white */ +#define D65_X0 (95.0470F) +#define D65_Y0 (100.0F) +#define D65_Z0 (108.8827F) + +#define D50_X0 (96.4250F) +#define D50_Y0 (100.0F) +#define D50_Z0 (82.4680F) + +/* Structure for holding information about a display device. */ + +typedef unsigned char TIFFRGBValue; /* 8-bit samples */ + +typedef struct { + float d_mat[3][3]; /* XYZ -> luminance matrix */ + float d_YCR; /* Light o/p for reference white */ + float d_YCG; + float d_YCB; + uint32 d_Vrwr; /* Pixel values for ref. white */ + uint32 d_Vrwg; + uint32 d_Vrwb; + float d_Y0R; /* Residual light for black pixel */ + float d_Y0G; + float d_Y0B; + float d_gammaR; /* Gamma values for the three guns */ + float d_gammaG; + float d_gammaB; +} TIFFDisplay; + +typedef struct { /* YCbCr->RGB support */ + TIFFRGBValue* clamptab; /* range clamping table */ + int* Cr_r_tab; + int* Cb_b_tab; + int32* Cr_g_tab; + int32* Cb_g_tab; + int32* Y_tab; +} TIFFYCbCrToRGB; + +typedef struct { /* CIE Lab 1976->RGB support */ + int range; /* Size of conversion table */ +#define CIELABTORGB_TABLE_RANGE 1500 + float rstep, gstep, bstep; + float X0, Y0, Z0; /* Reference white point */ + TIFFDisplay display; + float Yr2r[CIELABTORGB_TABLE_RANGE + 1]; /* Conversion of Yr to r */ + float Yg2g[CIELABTORGB_TABLE_RANGE + 1]; /* Conversion of Yg to g */ + float Yb2b[CIELABTORGB_TABLE_RANGE + 1]; /* Conversion of Yb to b */ +} TIFFCIELabToRGB; + +/* + * RGBA-style image support. + */ +typedef struct _TIFFRGBAImage TIFFRGBAImage; +/* + * The image reading and conversion routines invoke + * ``put routines'' to copy/image/whatever tiles of + * raw image data. A default set of routines are + * provided to convert/copy raw image data to 8-bit + * packed ABGR format rasters. Applications can supply + * alternate routines that unpack the data into a + * different format or, for example, unpack the data + * and draw the unpacked raster on the display. + */ +typedef void (*tileContigRoutine) + (TIFFRGBAImage*, uint32*, uint32, uint32, uint32, uint32, int32, int32, + unsigned char*); +typedef void (*tileSeparateRoutine) + (TIFFRGBAImage*, uint32*, uint32, uint32, uint32, uint32, int32, int32, + unsigned char*, unsigned char*, unsigned char*, unsigned char*); +/* + * RGBA-reader state. + */ +struct _TIFFRGBAImage { + TIFF* tif; /* image handle */ + int stoponerr; /* stop on read error */ + int isContig; /* data is packed/separate */ + int alpha; /* type of alpha data present */ + uint32 width; /* image width */ + uint32 height; /* image height */ + uint16 bitspersample; /* image bits/sample */ + uint16 samplesperpixel; /* image samples/pixel */ + uint16 orientation; /* image orientation */ + uint16 req_orientation; /* requested orientation */ + uint16 photometric; /* image photometric interp */ + uint16* redcmap; /* colormap pallete */ + uint16* greencmap; + uint16* bluecmap; + /* get image data routine */ + int (*get)(TIFFRGBAImage*, uint32*, uint32, uint32); + /* put decoded strip/tile */ + union { + void (*any)(TIFFRGBAImage*); + tileContigRoutine contig; + tileSeparateRoutine separate; + } put; + TIFFRGBValue* Map; /* sample mapping array */ + uint32** BWmap; /* black&white map */ + uint32** PALmap; /* palette image map */ + TIFFYCbCrToRGB* ycbcr; /* YCbCr conversion state */ + TIFFCIELabToRGB* cielab; /* CIE L*a*b conversion state */ + + int row_offset; + int col_offset; +}; + +/* + * Macros for extracting components from the + * packed ABGR form returned by TIFFReadRGBAImage. + */ +#define TIFFGetR(abgr) ((abgr) & 0xff) +#define TIFFGetG(abgr) (((abgr) >> 8) & 0xff) +#define TIFFGetB(abgr) (((abgr) >> 16) & 0xff) +#define TIFFGetA(abgr) (((abgr) >> 24) & 0xff) + +/* + * A CODEC is a software package that implements decoding, + * encoding, or decoding+encoding of a compression algorithm. + * The library provides a collection of builtin codecs. + * More codecs may be registered through calls to the library + * and/or the builtin implementations may be overridden. + */ +typedef int (*TIFFInitMethod)(TIFF*, int); +typedef struct { + char* name; + uint16 scheme; + TIFFInitMethod init; +} TIFFCodec; + +#include +#include + +/* share internal LogLuv conversion routines? */ +#ifndef LOGLUV_PUBLIC +#define LOGLUV_PUBLIC 1 +#endif + +#if !defined(__GNUC__) && !defined(__attribute__) +# define __attribute__(x) /*nothing*/ +#endif + +#if defined(c_plusplus) || defined(__cplusplus) +extern "C" { +#endif +typedef void (*TIFFErrorHandler)(const char*, const char*, va_list); +typedef void (*TIFFErrorHandlerExt)(thandle_t, const char*, const char*, va_list); +typedef tsize_t (*TIFFReadWriteProc)(thandle_t, tdata_t, tsize_t); +typedef toff_t (*TIFFSeekProc)(thandle_t, toff_t, int); +typedef int (*TIFFCloseProc)(thandle_t); +typedef toff_t (*TIFFSizeProc)(thandle_t); +typedef int (*TIFFMapFileProc)(thandle_t, tdata_t*, toff_t*); +typedef void (*TIFFUnmapFileProc)(thandle_t, tdata_t, toff_t); +typedef void (*TIFFExtendProc)(TIFF*); + +extern const char* TIFFGetVersion(void); + +extern const TIFFCodec* TIFFFindCODEC(uint16); +extern TIFFCodec* TIFFRegisterCODEC(uint16, const char*, TIFFInitMethod); +extern void TIFFUnRegisterCODEC(TIFFCodec*); +extern int TIFFIsCODECConfigured(uint16); +extern TIFFCodec* TIFFGetConfiguredCODECs(void); + +/* + * Auxiliary functions. + */ + +extern tdata_t _TIFFmalloc(tsize_t); +extern tdata_t _TIFFrealloc(tdata_t, tsize_t); +extern void _TIFFmemset(tdata_t, int, tsize_t); +extern void _TIFFmemcpy(tdata_t, const tdata_t, tsize_t); +extern int _TIFFmemcmp(const tdata_t, const tdata_t, tsize_t); +extern void _TIFFfree(tdata_t); + +/* +** Stuff, related to tag handling and creating custom tags. +*/ +extern int TIFFGetTagListCount( TIFF * ); +extern ttag_t TIFFGetTagListEntry( TIFF *, int tag_index ); + +#define TIFF_ANY TIFF_NOTYPE /* for field descriptor searching */ +#define TIFF_VARIABLE -1 /* marker for variable length tags */ +#define TIFF_SPP -2 /* marker for SamplesPerPixel tags */ +#define TIFF_VARIABLE2 -3 /* marker for uint32 var-length tags */ + +#define FIELD_CUSTOM 65 + +typedef struct { + ttag_t field_tag; /* field's tag */ + short field_readcount; /* read count/TIFF_VARIABLE/TIFF_SPP */ + short field_writecount; /* write count/TIFF_VARIABLE */ + TIFFDataType field_type; /* type of associated data */ + unsigned short field_bit; /* bit in fieldsset bit vector */ + unsigned char field_oktochange; /* if true, can change while writing */ + unsigned char field_passcount; /* if true, pass dir count on set */ + char *field_name; /* ASCII name */ +} TIFFFieldInfo; + +typedef struct _TIFFTagValue { + const TIFFFieldInfo *info; + int count; + void *value; +} TIFFTagValue; + +extern void TIFFMergeFieldInfo(TIFF*, const TIFFFieldInfo[], int); +extern const TIFFFieldInfo* TIFFFindFieldInfo(TIFF*, ttag_t, TIFFDataType); +extern const TIFFFieldInfo* TIFFFindFieldInfoByName(TIFF* , const char *, + TIFFDataType); +extern const TIFFFieldInfo* TIFFFieldWithTag(TIFF*, ttag_t); +extern const TIFFFieldInfo* TIFFFieldWithName(TIFF*, const char *); + +typedef int (*TIFFVSetMethod)(TIFF*, ttag_t, va_list); +typedef int (*TIFFVGetMethod)(TIFF*, ttag_t, va_list); +typedef void (*TIFFPrintMethod)(TIFF*, FILE*, long); + +typedef struct { + TIFFVSetMethod vsetfield; /* tag set routine */ + TIFFVGetMethod vgetfield; /* tag get routine */ + TIFFPrintMethod printdir; /* directory print routine */ +} TIFFTagMethods; + +extern TIFFTagMethods *TIFFAccessTagMethods( TIFF * ); +extern void *TIFFGetClientInfo( TIFF *, const char * ); +extern void TIFFSetClientInfo( TIFF *, void *, const char * ); + +extern void TIFFCleanup(TIFF*); +extern void TIFFClose(TIFF*); +extern int TIFFFlush(TIFF*); +extern int TIFFFlushData(TIFF*); +extern int TIFFGetField(TIFF*, ttag_t, ...); +extern int TIFFVGetField(TIFF*, ttag_t, va_list); +extern int TIFFGetFieldDefaulted(TIFF*, ttag_t, ...); +extern int TIFFVGetFieldDefaulted(TIFF*, ttag_t, va_list); +extern int TIFFReadDirectory(TIFF*); +extern int TIFFReadCustomDirectory(TIFF*, toff_t, const TIFFFieldInfo[], + size_t); +extern int TIFFReadEXIFDirectory(TIFF*, toff_t); +extern tsize_t TIFFScanlineSize(TIFF*); +extern tsize_t TIFFOldScanlineSize(TIFF*); +extern tsize_t TIFFNewScanlineSize(TIFF*); +extern tsize_t TIFFRasterScanlineSize(TIFF*); +extern tsize_t TIFFStripSize(TIFF*); +extern tsize_t TIFFRawStripSize(TIFF*, tstrip_t); +extern tsize_t TIFFVStripSize(TIFF*, uint32); +extern tsize_t TIFFTileRowSize(TIFF*); +extern tsize_t TIFFTileSize(TIFF*); +extern tsize_t TIFFVTileSize(TIFF*, uint32); +extern uint32 TIFFDefaultStripSize(TIFF*, uint32); +extern void TIFFDefaultTileSize(TIFF*, uint32*, uint32*); +extern int TIFFFileno(TIFF*); +extern int TIFFSetFileno(TIFF*, int); +extern thandle_t TIFFClientdata(TIFF*); +extern thandle_t TIFFSetClientdata(TIFF*, thandle_t); +extern int TIFFGetMode(TIFF*); +extern int TIFFSetMode(TIFF*, int); +extern int TIFFIsTiled(TIFF*); +extern int TIFFIsByteSwapped(TIFF*); +extern int TIFFIsUpSampled(TIFF*); +extern int TIFFIsMSB2LSB(TIFF*); +extern int TIFFIsBigEndian(TIFF*); +extern TIFFReadWriteProc TIFFGetReadProc(TIFF*); +extern TIFFReadWriteProc TIFFGetWriteProc(TIFF*); +extern TIFFSeekProc TIFFGetSeekProc(TIFF*); +extern TIFFCloseProc TIFFGetCloseProc(TIFF*); +extern TIFFSizeProc TIFFGetSizeProc(TIFF*); +extern TIFFMapFileProc TIFFGetMapFileProc(TIFF*); +extern TIFFUnmapFileProc TIFFGetUnmapFileProc(TIFF*); +extern uint32 TIFFCurrentRow(TIFF*); +extern tdir_t TIFFCurrentDirectory(TIFF*); +extern tdir_t TIFFNumberOfDirectories(TIFF*); +extern uint32 TIFFCurrentDirOffset(TIFF*); +extern tstrip_t TIFFCurrentStrip(TIFF*); +extern ttile_t TIFFCurrentTile(TIFF*); +extern int TIFFReadBufferSetup(TIFF*, tdata_t, tsize_t); +extern int TIFFWriteBufferSetup(TIFF*, tdata_t, tsize_t); +extern int TIFFSetupStrips(TIFF *); +extern int TIFFWriteCheck(TIFF*, int, const char *); +extern void TIFFFreeDirectory(TIFF*); +extern int TIFFCreateDirectory(TIFF*); +extern int TIFFLastDirectory(TIFF*); +extern int TIFFSetDirectory(TIFF*, tdir_t); +extern int TIFFSetSubDirectory(TIFF*, uint32); +extern int TIFFUnlinkDirectory(TIFF*, tdir_t); +extern int TIFFSetField(TIFF*, ttag_t, ...); +extern int TIFFVSetField(TIFF*, ttag_t, va_list); +extern int TIFFWriteDirectory(TIFF *); +extern int TIFFCheckpointDirectory(TIFF *); +extern int TIFFRewriteDirectory(TIFF *); +extern int TIFFReassignTagToIgnore(enum TIFFIgnoreSense, int); + +#if defined(c_plusplus) || defined(__cplusplus) +extern void TIFFPrintDirectory(TIFF*, FILE*, long = 0); +extern int TIFFReadScanline(TIFF*, tdata_t, uint32, tsample_t = 0); +extern int TIFFWriteScanline(TIFF*, tdata_t, uint32, tsample_t = 0); +extern int TIFFReadRGBAImage(TIFF*, uint32, uint32, uint32*, int = 0); +extern int TIFFReadRGBAImageOriented(TIFF*, uint32, uint32, uint32*, + int = ORIENTATION_BOTLEFT, int = 0); +#else +extern void TIFFPrintDirectory(TIFF*, FILE*, long); +extern int TIFFReadScanline(TIFF*, tdata_t, uint32, tsample_t); +extern int TIFFWriteScanline(TIFF*, tdata_t, uint32, tsample_t); +extern int TIFFReadRGBAImage(TIFF*, uint32, uint32, uint32*, int); +extern int TIFFReadRGBAImageOriented(TIFF*, uint32, uint32, uint32*, int, int); +#endif + +extern int TIFFReadRGBAStrip(TIFF*, tstrip_t, uint32 * ); +extern int TIFFReadRGBATile(TIFF*, uint32, uint32, uint32 * ); +extern int TIFFRGBAImageOK(TIFF*, char [1024]); +extern int TIFFRGBAImageBegin(TIFFRGBAImage*, TIFF*, int, char [1024]); +extern int TIFFRGBAImageGet(TIFFRGBAImage*, uint32*, uint32, uint32); +extern void TIFFRGBAImageEnd(TIFFRGBAImage*); +extern TIFF* TIFFOpen(const char*, const char*); +# ifdef __WIN32__ +extern TIFF* TIFFOpenW(const wchar_t*, const char*); +# endif /* __WIN32__ */ +extern TIFF* TIFFFdOpen(int, const char*, const char*); +extern TIFF* TIFFClientOpen(const char*, const char*, + thandle_t, + TIFFReadWriteProc, TIFFReadWriteProc, + TIFFSeekProc, TIFFCloseProc, + TIFFSizeProc, + TIFFMapFileProc, TIFFUnmapFileProc); +extern const char* TIFFFileName(TIFF*); +extern const char* TIFFSetFileName(TIFF*, const char *); +extern void TIFFError(const char*, const char*, ...) __attribute__((format (printf,2,3))); +extern void TIFFErrorExt(thandle_t, const char*, const char*, ...) __attribute__((format (printf,3,4))); +extern void TIFFWarning(const char*, const char*, ...) __attribute__((format (printf,2,3))); +extern void TIFFWarningExt(thandle_t, const char*, const char*, ...) __attribute__((format (printf,3,4))); +extern TIFFErrorHandler TIFFSetErrorHandler(TIFFErrorHandler); +extern TIFFErrorHandlerExt TIFFSetErrorHandlerExt(TIFFErrorHandlerExt); +extern TIFFErrorHandler TIFFSetWarningHandler(TIFFErrorHandler); +extern TIFFErrorHandlerExt TIFFSetWarningHandlerExt(TIFFErrorHandlerExt); +extern TIFFExtendProc TIFFSetTagExtender(TIFFExtendProc); +extern ttile_t TIFFComputeTile(TIFF*, uint32, uint32, uint32, tsample_t); +extern int TIFFCheckTile(TIFF*, uint32, uint32, uint32, tsample_t); +extern ttile_t TIFFNumberOfTiles(TIFF*); +extern tsize_t TIFFReadTile(TIFF*, + tdata_t, uint32, uint32, uint32, tsample_t); +extern tsize_t TIFFWriteTile(TIFF*, + tdata_t, uint32, uint32, uint32, tsample_t); +extern tstrip_t TIFFComputeStrip(TIFF*, uint32, tsample_t); +extern tstrip_t TIFFNumberOfStrips(TIFF*); +extern tsize_t TIFFReadEncodedStrip(TIFF*, tstrip_t, tdata_t, tsize_t); +extern tsize_t TIFFReadRawStrip(TIFF*, tstrip_t, tdata_t, tsize_t); +extern tsize_t TIFFReadEncodedTile(TIFF*, ttile_t, tdata_t, tsize_t); +extern tsize_t TIFFReadRawTile(TIFF*, ttile_t, tdata_t, tsize_t); +extern tsize_t TIFFWriteEncodedStrip(TIFF*, tstrip_t, tdata_t, tsize_t); +extern tsize_t TIFFWriteRawStrip(TIFF*, tstrip_t, tdata_t, tsize_t); +extern tsize_t TIFFWriteEncodedTile(TIFF*, ttile_t, tdata_t, tsize_t); +extern tsize_t TIFFWriteRawTile(TIFF*, ttile_t, tdata_t, tsize_t); +extern int TIFFDataWidth(TIFFDataType); /* table of tag datatype widths */ +extern void TIFFSetWriteOffset(TIFF*, toff_t); +extern void TIFFSwabShort(uint16*); +extern void TIFFSwabLong(uint32*); +extern void TIFFSwabDouble(double*); +extern void TIFFSwabArrayOfShort(uint16*, unsigned long); +extern void TIFFSwabArrayOfTriples(uint8*, unsigned long); +extern void TIFFSwabArrayOfLong(uint32*, unsigned long); +extern void TIFFSwabArrayOfDouble(double*, unsigned long); +extern void TIFFReverseBits(unsigned char *, unsigned long); +extern const unsigned char* TIFFGetBitRevTable(int); + +#ifdef LOGLUV_PUBLIC +#define U_NEU 0.210526316 +#define V_NEU 0.473684211 +#define UVSCALE 410. +extern double LogL16toY(int); +extern double LogL10toY(int); +extern void XYZtoRGB24(float*, uint8*); +extern int uv_decode(double*, double*, int); +extern void LogLuv24toXYZ(uint32, float*); +extern void LogLuv32toXYZ(uint32, float*); +#if defined(c_plusplus) || defined(__cplusplus) +extern int LogL16fromY(double, int = SGILOGENCODE_NODITHER); +extern int LogL10fromY(double, int = SGILOGENCODE_NODITHER); +extern int uv_encode(double, double, int = SGILOGENCODE_NODITHER); +extern uint32 LogLuv24fromXYZ(float*, int = SGILOGENCODE_NODITHER); +extern uint32 LogLuv32fromXYZ(float*, int = SGILOGENCODE_NODITHER); +#else +extern int LogL16fromY(double, int); +extern int LogL10fromY(double, int); +extern int uv_encode(double, double, int); +extern uint32 LogLuv24fromXYZ(float*, int); +extern uint32 LogLuv32fromXYZ(float*, int); +#endif +#endif /* LOGLUV_PUBLIC */ + +extern int TIFFCIELabToRGBInit(TIFFCIELabToRGB*, TIFFDisplay *, float*); +extern void TIFFCIELabToXYZ(TIFFCIELabToRGB *, uint32, int32, int32, + float *, float *, float *); +extern void TIFFXYZToRGB(TIFFCIELabToRGB *, float, float, float, + uint32 *, uint32 *, uint32 *); + +extern int TIFFYCbCrToRGBInit(TIFFYCbCrToRGB*, float*, float*); +extern void TIFFYCbCrtoRGB(TIFFYCbCrToRGB *, uint32, int32, int32, + uint32 *, uint32 *, uint32 *); + +#if defined(c_plusplus) || defined(__cplusplus) +} +#endif + +#endif /* _TIFFIO_ */ + +/* vim: set ts=8 sts=8 sw=8 noet: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tiffio.hxx b/reactos/dll/3rdparty/libtiff/tiffio.hxx new file mode 100644 index 00000000000..ee3fd32c742 --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tiffio.hxx @@ -0,0 +1,49 @@ +/* $Id: tiffio.hxx,v 1.1.2.1 2010-06-08 18:50:43 bfriesen Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _TIFFIO_HXX_ +#define _TIFFIO_HXX_ + +/* + * TIFF I/O library definitions which provide C++ streams API. + */ + +#include +#include "tiff.h" + +extern TIFF* TIFFStreamOpen(const char*, std::ostream *); +extern TIFF* TIFFStreamOpen(const char*, std::istream *); + +#endif /* _TIFFIO_HXX_ */ + +/* vim: set ts=8 sts=8 sw=8 noet: */ +/* + * Local Variables: + * mode: c++ + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tiffiop.h b/reactos/dll/3rdparty/libtiff/tiffiop.h new file mode 100644 index 00000000000..a064039f6b8 --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tiffiop.h @@ -0,0 +1,350 @@ +/* $Id: tiffiop.h,v 1.51.2.6 2010-06-12 02:55:16 bfriesen Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _TIFFIOP_ +#define _TIFFIOP_ +/* + * ``Library-private'' definitions. + */ + +#include "tif_config.h" + +#ifdef HAVE_FCNTL_H +# include +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +#ifdef HAVE_STRING_H +# include +#endif + +#ifdef HAVE_ASSERT_H +# include +#else +# define assert(x) +#endif + +#ifdef HAVE_SEARCH_H +# include +#else +extern void *lfind(const void *, const void *, size_t *, size_t, + int (*)(const void *, const void *)); +#endif + +/* + Libtiff itself does not require a 64-bit type, but bundled TIFF + utilities may use it. +*/ +typedef TIFF_INT64_T int64; +typedef TIFF_UINT64_T uint64; + +#include "tiffio.h" +#include "tif_dir.h" + +#ifndef STRIP_SIZE_DEFAULT +# define STRIP_SIZE_DEFAULT 8192 +#endif + +#define streq(a,b) (strcmp(a,b) == 0) + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +typedef struct client_info { + struct client_info *next; + void *data; + char *name; +} TIFFClientInfoLink; + +/* + * Typedefs for ``method pointers'' used internally. + */ +typedef unsigned char tidataval_t; /* internal image data value type */ +typedef tidataval_t* tidata_t; /* reference to internal image data */ + +typedef void (*TIFFVoidMethod)(TIFF*); +typedef int (*TIFFBoolMethod)(TIFF*); +typedef int (*TIFFPreMethod)(TIFF*, tsample_t); +typedef int (*TIFFCodeMethod)(TIFF*, tidata_t, tsize_t, tsample_t); +typedef int (*TIFFSeekMethod)(TIFF*, uint32); +typedef void (*TIFFPostMethod)(TIFF*, tidata_t, tsize_t); +typedef uint32 (*TIFFStripMethod)(TIFF*, uint32); +typedef void (*TIFFTileMethod)(TIFF*, uint32*, uint32*); + +struct tiff { + char* tif_name; /* name of open file */ + int tif_fd; /* open file descriptor */ + int tif_mode; /* open mode (O_*) */ + uint32 tif_flags; +#define TIFF_FILLORDER 0x00003 /* natural bit fill order for machine */ +#define TIFF_DIRTYHEADER 0x00004 /* header must be written on close */ +#define TIFF_DIRTYDIRECT 0x00008 /* current directory must be written */ +#define TIFF_BUFFERSETUP 0x00010 /* data buffers setup */ +#define TIFF_CODERSETUP 0x00020 /* encoder/decoder setup done */ +#define TIFF_BEENWRITING 0x00040 /* written 1+ scanlines to file */ +#define TIFF_SWAB 0x00080 /* byte swap file information */ +#define TIFF_NOBITREV 0x00100 /* inhibit bit reversal logic */ +#define TIFF_MYBUFFER 0x00200 /* my raw data buffer; free on close */ +#define TIFF_ISTILED 0x00400 /* file is tile, not strip- based */ +#define TIFF_MAPPED 0x00800 /* file is mapped into memory */ +#define TIFF_POSTENCODE 0x01000 /* need call to postencode routine */ +#define TIFF_INSUBIFD 0x02000 /* currently writing a subifd */ +#define TIFF_UPSAMPLED 0x04000 /* library is doing data up-sampling */ +#define TIFF_STRIPCHOP 0x08000 /* enable strip chopping support */ +#define TIFF_HEADERONLY 0x10000 /* read header only, do not process */ + /* the first directory */ +#define TIFF_NOREADRAW 0x20000 /* skip reading of raw uncompressed */ + /* image data */ +#define TIFF_INCUSTOMIFD 0x40000 /* currently writing a custom IFD */ + toff_t tif_diroff; /* file offset of current directory */ + toff_t tif_nextdiroff; /* file offset of following directory */ + toff_t* tif_dirlist; /* list of offsets to already seen */ + /* directories to prevent IFD looping */ + tsize_t tif_dirlistsize;/* number of entires in offset list */ + uint16 tif_dirnumber; /* number of already seen directories */ + TIFFDirectory tif_dir; /* internal rep of current directory */ + TIFFDirectory tif_customdir; /* custom IFDs are separated from + the main ones */ + TIFFHeader tif_header; /* file's header block */ + const int* tif_typeshift; /* data type shift counts */ + const long* tif_typemask; /* data type masks */ + uint32 tif_row; /* current scanline */ + tdir_t tif_curdir; /* current directory (index) */ + tstrip_t tif_curstrip; /* current strip for read/write */ + toff_t tif_curoff; /* current offset for read/write */ + toff_t tif_dataoff; /* current offset for writing dir */ +/* SubIFD support */ + uint16 tif_nsubifd; /* remaining subifds to write */ + toff_t tif_subifdoff; /* offset for patching SubIFD link */ +/* tiling support */ + uint32 tif_col; /* current column (offset by row too) */ + ttile_t tif_curtile; /* current tile for read/write */ + tsize_t tif_tilesize; /* # of bytes in a tile */ +/* compression scheme hooks */ + int tif_decodestatus; + TIFFBoolMethod tif_setupdecode;/* called once before predecode */ + TIFFPreMethod tif_predecode; /* pre- row/strip/tile decoding */ + TIFFBoolMethod tif_setupencode;/* called once before preencode */ + int tif_encodestatus; + TIFFPreMethod tif_preencode; /* pre- row/strip/tile encoding */ + TIFFBoolMethod tif_postencode; /* post- row/strip/tile encoding */ + TIFFCodeMethod tif_decoderow; /* scanline decoding routine */ + TIFFCodeMethod tif_encoderow; /* scanline encoding routine */ + TIFFCodeMethod tif_decodestrip;/* strip decoding routine */ + TIFFCodeMethod tif_encodestrip;/* strip encoding routine */ + TIFFCodeMethod tif_decodetile; /* tile decoding routine */ + TIFFCodeMethod tif_encodetile; /* tile encoding routine */ + TIFFVoidMethod tif_close; /* cleanup-on-close routine */ + TIFFSeekMethod tif_seek; /* position within a strip routine */ + TIFFVoidMethod tif_cleanup; /* cleanup state routine */ + TIFFStripMethod tif_defstripsize;/* calculate/constrain strip size */ + TIFFTileMethod tif_deftilesize;/* calculate/constrain tile size */ + tidata_t tif_data; /* compression scheme private data */ +/* input/output buffering */ + tsize_t tif_scanlinesize;/* # of bytes in a scanline */ + tsize_t tif_scanlineskew;/* scanline skew for reading strips */ + tidata_t tif_rawdata; /* raw data buffer */ + tsize_t tif_rawdatasize;/* # of bytes in raw data buffer */ + tidata_t tif_rawcp; /* current spot in raw buffer */ + tsize_t tif_rawcc; /* bytes unread from raw buffer */ +/* memory-mapped file support */ + tidata_t tif_base; /* base of mapped file */ + toff_t tif_size; /* size of mapped file region (bytes) + FIXME: it should be tsize_t */ + TIFFMapFileProc tif_mapproc; /* map file method */ + TIFFUnmapFileProc tif_unmapproc;/* unmap file method */ +/* input/output callback methods */ + thandle_t tif_clientdata; /* callback parameter */ + TIFFReadWriteProc tif_readproc; /* read method */ + TIFFReadWriteProc tif_writeproc;/* write method */ + TIFFSeekProc tif_seekproc; /* lseek method */ + TIFFCloseProc tif_closeproc; /* close method */ + TIFFSizeProc tif_sizeproc; /* filesize method */ +/* post-decoding support */ + TIFFPostMethod tif_postdecode; /* post decoding routine */ +/* tag support */ + TIFFFieldInfo** tif_fieldinfo; /* sorted table of registered tags */ + size_t tif_nfields; /* # entries in registered tag table */ + const TIFFFieldInfo *tif_foundfield;/* cached pointer to already found tag */ + TIFFTagMethods tif_tagmethods; /* tag get/set/print routines */ + TIFFClientInfoLink *tif_clientinfo; /* extra client information. */ +}; + +#define isPseudoTag(t) (t > 0xffff) /* is tag value normal or pseudo */ + +#define isTiled(tif) (((tif)->tif_flags & TIFF_ISTILED) != 0) +#define isMapped(tif) (((tif)->tif_flags & TIFF_MAPPED) != 0) +#define isFillOrder(tif, o) (((tif)->tif_flags & (o)) != 0) +#define isUpSampled(tif) (((tif)->tif_flags & TIFF_UPSAMPLED) != 0) +#define TIFFReadFile(tif, buf, size) \ + ((*(tif)->tif_readproc)((tif)->tif_clientdata,buf,size)) +#define TIFFWriteFile(tif, buf, size) \ + ((*(tif)->tif_writeproc)((tif)->tif_clientdata,buf,size)) +#define TIFFSeekFile(tif, off, whence) \ + ((*(tif)->tif_seekproc)((tif)->tif_clientdata,(toff_t)(off),whence)) +#define TIFFCloseFile(tif) \ + ((*(tif)->tif_closeproc)((tif)->tif_clientdata)) +#define TIFFGetFileSize(tif) \ + ((*(tif)->tif_sizeproc)((tif)->tif_clientdata)) +#define TIFFMapFileContents(tif, paddr, psize) \ + ((*(tif)->tif_mapproc)((tif)->tif_clientdata,paddr,psize)) +#define TIFFUnmapFileContents(tif, addr, size) \ + ((*(tif)->tif_unmapproc)((tif)->tif_clientdata,addr,size)) + +/* + * Default Read/Seek/Write definitions. + */ +#ifndef ReadOK +#define ReadOK(tif, buf, size) \ + (TIFFReadFile(tif, (tdata_t) buf, (tsize_t)(size)) == (tsize_t)(size)) +#endif +#ifndef SeekOK +#define SeekOK(tif, off) \ + (TIFFSeekFile(tif, (toff_t) off, SEEK_SET) == (toff_t) off) +#endif +#ifndef WriteOK +#define WriteOK(tif, buf, size) \ + (TIFFWriteFile(tif, (tdata_t) buf, (tsize_t) size) == (tsize_t) size) +#endif + +/* NB: the uint32 casts are to silence certain ANSI-C compilers */ +#define TIFFhowmany(x, y) (((uint32)x < (0xffffffff - (uint32)(y-1))) ? \ + ((((uint32)(x))+(((uint32)(y))-1))/((uint32)(y))) : \ + 0U) +#define TIFFhowmany8(x) (((x)&0x07)?((uint32)(x)>>3)+1:(uint32)(x)>>3) +#define TIFFroundup(x, y) (TIFFhowmany(x,y)*(y)) + +/* Safe multiply which returns zero if there is an integer overflow */ +#define TIFFSafeMultiply(t,v,m) ((((t)m != (t)0) && (((t)((v*m)/m)) == (t)v)) ? (t)(v*m) : (t)0) + +#define TIFFmax(A,B) ((A)>(B)?(A):(B)) +#define TIFFmin(A,B) ((A)<(B)?(A):(B)) + +#define TIFFArrayCount(a) (sizeof (a) / sizeof ((a)[0])) + +#if defined(__cplusplus) +extern "C" { +#endif +extern int _TIFFgetMode(const char*, const char*); +extern int _TIFFNoRowEncode(TIFF*, tidata_t, tsize_t, tsample_t); +extern int _TIFFNoStripEncode(TIFF*, tidata_t, tsize_t, tsample_t); +extern int _TIFFNoTileEncode(TIFF*, tidata_t, tsize_t, tsample_t); +extern int _TIFFNoRowDecode(TIFF*, tidata_t, tsize_t, tsample_t); +extern int _TIFFNoStripDecode(TIFF*, tidata_t, tsize_t, tsample_t); +extern int _TIFFNoTileDecode(TIFF*, tidata_t, tsize_t, tsample_t); +extern void _TIFFNoPostDecode(TIFF*, tidata_t, tsize_t); +extern int _TIFFNoPreCode (TIFF*, tsample_t); +extern int _TIFFNoSeek(TIFF*, uint32); +extern void _TIFFSwab16BitData(TIFF*, tidata_t, tsize_t); +extern void _TIFFSwab24BitData(TIFF*, tidata_t, tsize_t); +extern void _TIFFSwab32BitData(TIFF*, tidata_t, tsize_t); +extern void _TIFFSwab64BitData(TIFF*, tidata_t, tsize_t); +extern int TIFFFlushData1(TIFF*); +extern int TIFFDefaultDirectory(TIFF*); +extern void _TIFFSetDefaultCompressionState(TIFF*); +extern int TIFFSetCompressionScheme(TIFF*, int); +extern int TIFFSetDefaultCompressionState(TIFF*); +extern uint32 _TIFFDefaultStripSize(TIFF*, uint32); +extern void _TIFFDefaultTileSize(TIFF*, uint32*, uint32*); +extern int _TIFFDataSize(TIFFDataType); + +extern void _TIFFsetByteArray(void**, void*, uint32); +extern void _TIFFsetString(char**, char*); +extern void _TIFFsetShortArray(uint16**, uint16*, uint32); +extern void _TIFFsetLongArray(uint32**, uint32*, uint32); +extern void _TIFFsetFloatArray(float**, float*, uint32); +extern void _TIFFsetDoubleArray(double**, double*, uint32); + +extern void _TIFFprintAscii(FILE*, const char*); +extern void _TIFFprintAsciiTag(FILE*, const char*, const char*); + +extern TIFFErrorHandler _TIFFwarningHandler; +extern TIFFErrorHandler _TIFFerrorHandler; +extern TIFFErrorHandlerExt _TIFFwarningHandlerExt; +extern TIFFErrorHandlerExt _TIFFerrorHandlerExt; + +extern tdata_t _TIFFCheckMalloc(TIFF*, size_t, size_t, const char*); +extern tdata_t _TIFFCheckRealloc(TIFF*, tdata_t, size_t, size_t, const char*); + +extern int TIFFInitDumpMode(TIFF*, int); +#ifdef PACKBITS_SUPPORT +extern int TIFFInitPackBits(TIFF*, int); +#endif +#ifdef CCITT_SUPPORT +extern int TIFFInitCCITTRLE(TIFF*, int), TIFFInitCCITTRLEW(TIFF*, int); +extern int TIFFInitCCITTFax3(TIFF*, int), TIFFInitCCITTFax4(TIFF*, int); +#endif +#ifdef THUNDER_SUPPORT +extern int TIFFInitThunderScan(TIFF*, int); +#endif +#ifdef NEXT_SUPPORT +extern int TIFFInitNeXT(TIFF*, int); +#endif +#ifdef LZW_SUPPORT +extern int TIFFInitLZW(TIFF*, int); +#endif +#ifdef OJPEG_SUPPORT +extern int TIFFInitOJPEG(TIFF*, int); +#endif +#ifdef JPEG_SUPPORT +extern int TIFFInitJPEG(TIFF*, int); +#endif +#ifdef JBIG_SUPPORT +extern int TIFFInitJBIG(TIFF*, int); +#endif +#ifdef ZIP_SUPPORT +extern int TIFFInitZIP(TIFF*, int); +#endif +#ifdef PIXARLOG_SUPPORT +extern int TIFFInitPixarLog(TIFF*, int); +#endif +#ifdef LOGLUV_SUPPORT +extern int TIFFInitSGILog(TIFF*, int); +#endif +#ifdef VMS +extern const TIFFCodec _TIFFBuiltinCODECS[]; +#else +extern TIFFCodec _TIFFBuiltinCODECS[]; +#endif + +#if defined(__cplusplus) +} +#endif +#endif /* _TIFFIOP_ */ + +/* vim: set ts=8 sts=8 sw=8 noet: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/3rdparty/libtiff/tiffvers.h b/reactos/dll/3rdparty/libtiff/tiffvers.h new file mode 100644 index 00000000000..314a22a0ae9 --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/tiffvers.h @@ -0,0 +1,9 @@ +#define TIFFLIB_VERSION_STR "LIBTIFF, Version 3.9.4\nCopyright (c) 1988-1996 Sam Leffler\nCopyright (c) 1991-1996 Silicon Graphics, Inc." +/* + * This define can be used in code that requires + * compilation-related definitions specific to a + * version or versions of the library. Runtime + * version checking should be done based on the + * string returned by TIFFGetVersion. + */ +#define TIFFLIB_VERSION 20100615 diff --git a/reactos/dll/3rdparty/libtiff/uvcode.h b/reactos/dll/3rdparty/libtiff/uvcode.h new file mode 100644 index 00000000000..50f11d7e0ae --- /dev/null +++ b/reactos/dll/3rdparty/libtiff/uvcode.h @@ -0,0 +1,180 @@ +/* Version 1.0 generated April 7, 1997 by Greg Ward Larson, SGI */ +#define UV_SQSIZ (float)0.003500 +#define UV_NDIVS 16289 +#define UV_VSTART (float)0.016940 +#define UV_NVS 163 +static struct { + float ustart; + short nus, ncum; +} uv_row[UV_NVS] = { + { (float)0.247663, 4, 0 }, + { (float)0.243779, 6, 4 }, + { (float)0.241684, 7, 10 }, + { (float)0.237874, 9, 17 }, + { (float)0.235906, 10, 26 }, + { (float)0.232153, 12, 36 }, + { (float)0.228352, 14, 48 }, + { (float)0.226259, 15, 62 }, + { (float)0.222371, 17, 77 }, + { (float)0.220410, 18, 94 }, + { (float)0.214710, 21, 112 }, + { (float)0.212714, 22, 133 }, + { (float)0.210721, 23, 155 }, + { (float)0.204976, 26, 178 }, + { (float)0.202986, 27, 204 }, + { (float)0.199245, 29, 231 }, + { (float)0.195525, 31, 260 }, + { (float)0.193560, 32, 291 }, + { (float)0.189878, 34, 323 }, + { (float)0.186216, 36, 357 }, + { (float)0.186216, 36, 393 }, + { (float)0.182592, 38, 429 }, + { (float)0.179003, 40, 467 }, + { (float)0.175466, 42, 507 }, + { (float)0.172001, 44, 549 }, + { (float)0.172001, 44, 593 }, + { (float)0.168612, 46, 637 }, + { (float)0.168612, 46, 683 }, + { (float)0.163575, 49, 729 }, + { (float)0.158642, 52, 778 }, + { (float)0.158642, 52, 830 }, + { (float)0.158642, 52, 882 }, + { (float)0.153815, 55, 934 }, + { (float)0.153815, 55, 989 }, + { (float)0.149097, 58, 1044 }, + { (float)0.149097, 58, 1102 }, + { (float)0.142746, 62, 1160 }, + { (float)0.142746, 62, 1222 }, + { (float)0.142746, 62, 1284 }, + { (float)0.138270, 65, 1346 }, + { (float)0.138270, 65, 1411 }, + { (float)0.138270, 65, 1476 }, + { (float)0.132166, 69, 1541 }, + { (float)0.132166, 69, 1610 }, + { (float)0.126204, 73, 1679 }, + { (float)0.126204, 73, 1752 }, + { (float)0.126204, 73, 1825 }, + { (float)0.120381, 77, 1898 }, + { (float)0.120381, 77, 1975 }, + { (float)0.120381, 77, 2052 }, + { (float)0.120381, 77, 2129 }, + { (float)0.112962, 82, 2206 }, + { (float)0.112962, 82, 2288 }, + { (float)0.112962, 82, 2370 }, + { (float)0.107450, 86, 2452 }, + { (float)0.107450, 86, 2538 }, + { (float)0.107450, 86, 2624 }, + { (float)0.107450, 86, 2710 }, + { (float)0.100343, 91, 2796 }, + { (float)0.100343, 91, 2887 }, + { (float)0.100343, 91, 2978 }, + { (float)0.095126, 95, 3069 }, + { (float)0.095126, 95, 3164 }, + { (float)0.095126, 95, 3259 }, + { (float)0.095126, 95, 3354 }, + { (float)0.088276, 100, 3449 }, + { (float)0.088276, 100, 3549 }, + { (float)0.088276, 100, 3649 }, + { (float)0.088276, 100, 3749 }, + { (float)0.081523, 105, 3849 }, + { (float)0.081523, 105, 3954 }, + { (float)0.081523, 105, 4059 }, + { (float)0.081523, 105, 4164 }, + { (float)0.074861, 110, 4269 }, + { (float)0.074861, 110, 4379 }, + { (float)0.074861, 110, 4489 }, + { (float)0.074861, 110, 4599 }, + { (float)0.068290, 115, 4709 }, + { (float)0.068290, 115, 4824 }, + { (float)0.068290, 115, 4939 }, + { (float)0.068290, 115, 5054 }, + { (float)0.063573, 119, 5169 }, + { (float)0.063573, 119, 5288 }, + { (float)0.063573, 119, 5407 }, + { (float)0.063573, 119, 5526 }, + { (float)0.057219, 124, 5645 }, + { (float)0.057219, 124, 5769 }, + { (float)0.057219, 124, 5893 }, + { (float)0.057219, 124, 6017 }, + { (float)0.050985, 129, 6141 }, + { (float)0.050985, 129, 6270 }, + { (float)0.050985, 129, 6399 }, + { (float)0.050985, 129, 6528 }, + { (float)0.050985, 129, 6657 }, + { (float)0.044859, 134, 6786 }, + { (float)0.044859, 134, 6920 }, + { (float)0.044859, 134, 7054 }, + { (float)0.044859, 134, 7188 }, + { (float)0.040571, 138, 7322 }, + { (float)0.040571, 138, 7460 }, + { (float)0.040571, 138, 7598 }, + { (float)0.040571, 138, 7736 }, + { (float)0.036339, 142, 7874 }, + { (float)0.036339, 142, 8016 }, + { (float)0.036339, 142, 8158 }, + { (float)0.036339, 142, 8300 }, + { (float)0.032139, 146, 8442 }, + { (float)0.032139, 146, 8588 }, + { (float)0.032139, 146, 8734 }, + { (float)0.032139, 146, 8880 }, + { (float)0.027947, 150, 9026 }, + { (float)0.027947, 150, 9176 }, + { (float)0.027947, 150, 9326 }, + { (float)0.023739, 154, 9476 }, + { (float)0.023739, 154, 9630 }, + { (float)0.023739, 154, 9784 }, + { (float)0.023739, 154, 9938 }, + { (float)0.019504, 158, 10092 }, + { (float)0.019504, 158, 10250 }, + { (float)0.019504, 158, 10408 }, + { (float)0.016976, 161, 10566 }, + { (float)0.016976, 161, 10727 }, + { (float)0.016976, 161, 10888 }, + { (float)0.016976, 161, 11049 }, + { (float)0.012639, 165, 11210 }, + { (float)0.012639, 165, 11375 }, + { (float)0.012639, 165, 11540 }, + { (float)0.009991, 168, 11705 }, + { (float)0.009991, 168, 11873 }, + { (float)0.009991, 168, 12041 }, + { (float)0.009016, 170, 12209 }, + { (float)0.009016, 170, 12379 }, + { (float)0.009016, 170, 12549 }, + { (float)0.006217, 173, 12719 }, + { (float)0.006217, 173, 12892 }, + { (float)0.005097, 175, 13065 }, + { (float)0.005097, 175, 13240 }, + { (float)0.005097, 175, 13415 }, + { (float)0.003909, 177, 13590 }, + { (float)0.003909, 177, 13767 }, + { (float)0.002340, 177, 13944 }, + { (float)0.002389, 170, 14121 }, + { (float)0.001068, 164, 14291 }, + { (float)0.001653, 157, 14455 }, + { (float)0.000717, 150, 14612 }, + { (float)0.001614, 143, 14762 }, + { (float)0.000270, 136, 14905 }, + { (float)0.000484, 129, 15041 }, + { (float)0.001103, 123, 15170 }, + { (float)0.001242, 115, 15293 }, + { (float)0.001188, 109, 15408 }, + { (float)0.001011, 103, 15517 }, + { (float)0.000709, 97, 15620 }, + { (float)0.000301, 89, 15717 }, + { (float)0.002416, 82, 15806 }, + { (float)0.003251, 76, 15888 }, + { (float)0.003246, 69, 15964 }, + { (float)0.004141, 62, 16033 }, + { (float)0.005963, 55, 16095 }, + { (float)0.008839, 47, 16150 }, + { (float)0.010490, 40, 16197 }, + { (float)0.016994, 31, 16237 }, + { (float)0.023659, 21, 16268 }, +}; +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/dll/win32/windowscodecs/windowscodecs.rbuild b/reactos/dll/win32/windowscodecs/windowscodecs.rbuild index 5ea644345e4..7c74900ee34 100644 --- a/reactos/dll/win32/windowscodecs/windowscodecs.rbuild +++ b/reactos/dll/win32/windowscodecs/windowscodecs.rbuild @@ -1,9 +1,12 @@ - + . include/reactos/wine include/reactos/libs/libjpeg + include/reactos/libs/zlib + include/reactos/libs/libpng + include/reactos/libs/libtiff 0x600 diff --git a/reactos/include/reactos/libs/libjpeg/cderror.h b/reactos/include/reactos/libs/libjpeg/cderror.h index 70435e161c0..e19c475c5c5 100644 --- a/reactos/include/reactos/libs/libjpeg/cderror.h +++ b/reactos/include/reactos/libs/libjpeg/cderror.h @@ -2,6 +2,7 @@ * cderror.h * * Copyright (C) 1994-1997, Thomas G. Lane. + * Modified 2009 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -45,6 +46,7 @@ JMESSAGE(JERR_BMP_BADHEADER, "Invalid BMP file: bad header length") JMESSAGE(JERR_BMP_BADPLANES, "Invalid BMP file: biPlanes not equal to 1") JMESSAGE(JERR_BMP_COLORSPACE, "BMP output must be grayscale or RGB") JMESSAGE(JERR_BMP_COMPRESSED, "Sorry, compressed BMPs not yet supported") +JMESSAGE(JERR_BMP_EMPTY, "Empty BMP image") JMESSAGE(JERR_BMP_NOT, "Not a BMP file - does not start with BM") JMESSAGE(JTRC_BMP, "%ux%u 24-bit BMP image") JMESSAGE(JTRC_BMP_MAPPED, "%ux%u 8-bit colormapped BMP image") diff --git a/reactos/include/reactos/libs/libjpeg/cdjpeg.h b/reactos/include/reactos/libs/libjpeg/cdjpeg.h index a9abd5471c5..ed024ac3ae8 100644 --- a/reactos/include/reactos/libs/libjpeg/cdjpeg.h +++ b/reactos/include/reactos/libs/libjpeg/cdjpeg.h @@ -104,6 +104,7 @@ typedef struct cdjpeg_progress_mgr * cd_progress_ptr; #define jinit_write_targa jIWrTarga #define read_quant_tables RdQTables #define read_scan_script RdScnScript +#define set_quality_ratings SetQRates #define set_quant_slots SetQSlots #define set_sample_factors SetSFacts #define read_color_map RdCMap @@ -116,39 +117,41 @@ typedef struct cdjpeg_progress_mgr * cd_progress_ptr; /* Module selection routines for I/O modules. */ -EXTERN_1(cjpeg_source_ptr) jinit_read_bmp JPP((j_compress_ptr cinfo)); -EXTERN_1(djpeg_dest_ptr) jinit_write_bmp JPP((j_decompress_ptr cinfo, +EXTERN(cjpeg_source_ptr) jinit_read_bmp JPP((j_compress_ptr cinfo)); +EXTERN(djpeg_dest_ptr) jinit_write_bmp JPP((j_decompress_ptr cinfo, boolean is_os2)); -EXTERN_1(cjpeg_source_ptr) jinit_read_gif JPP((j_compress_ptr cinfo)); -EXTERN_1(djpeg_dest_ptr) jinit_write_gif JPP((j_decompress_ptr cinfo)); -EXTERN_1(cjpeg_source_ptr) jinit_read_ppm JPP((j_compress_ptr cinfo)); -EXTERN_1(djpeg_dest_ptr) jinit_write_ppm JPP((j_decompress_ptr cinfo)); -EXTERN_1(cjpeg_source_ptr) jinit_read_rle JPP((j_compress_ptr cinfo)); -EXTERN_1(djpeg_dest_ptr) jinit_write_rle JPP((j_decompress_ptr cinfo)); -EXTERN_1(cjpeg_source_ptr) jinit_read_targa JPP((j_compress_ptr cinfo)); -EXTERN_1(djpeg_dest_ptr) jinit_write_targa JPP((j_decompress_ptr cinfo)); +EXTERN(cjpeg_source_ptr) jinit_read_gif JPP((j_compress_ptr cinfo)); +EXTERN(djpeg_dest_ptr) jinit_write_gif JPP((j_decompress_ptr cinfo)); +EXTERN(cjpeg_source_ptr) jinit_read_ppm JPP((j_compress_ptr cinfo)); +EXTERN(djpeg_dest_ptr) jinit_write_ppm JPP((j_decompress_ptr cinfo)); +EXTERN(cjpeg_source_ptr) jinit_read_rle JPP((j_compress_ptr cinfo)); +EXTERN(djpeg_dest_ptr) jinit_write_rle JPP((j_decompress_ptr cinfo)); +EXTERN(cjpeg_source_ptr) jinit_read_targa JPP((j_compress_ptr cinfo)); +EXTERN(djpeg_dest_ptr) jinit_write_targa JPP((j_decompress_ptr cinfo)); /* cjpeg support routines (in rdswitch.c) */ -EXTERN_1(boolean) read_quant_tables JPP((j_compress_ptr cinfo, char * filename, - int scale_factor, boolean force_baseline)); -EXTERN_1(boolean) read_scan_script JPP((j_compress_ptr cinfo, char * filename)); -EXTERN_1(boolean) set_quant_slots JPP((j_compress_ptr cinfo, char *arg)); -EXTERN_1(boolean) set_sample_factors JPP((j_compress_ptr cinfo, char *arg)); +EXTERN(boolean) read_quant_tables JPP((j_compress_ptr cinfo, char * filename, + boolean force_baseline)); +EXTERN(boolean) read_scan_script JPP((j_compress_ptr cinfo, char * filename)); +EXTERN(boolean) set_quality_ratings JPP((j_compress_ptr cinfo, char *arg, + boolean force_baseline)); +EXTERN(boolean) set_quant_slots JPP((j_compress_ptr cinfo, char *arg)); +EXTERN(boolean) set_sample_factors JPP((j_compress_ptr cinfo, char *arg)); /* djpeg support routines (in rdcolmap.c) */ -EXTERN_1(void) read_color_map JPP((j_decompress_ptr cinfo, FILE * infile)); +EXTERN(void) read_color_map JPP((j_decompress_ptr cinfo, FILE * infile)); /* common support routines (in cdjpeg.c) */ -EXTERN_1(void) enable_signal_catcher JPP((j_common_ptr cinfo)); -EXTERN_1(void) start_progress_monitor JPP((j_common_ptr cinfo, +EXTERN(void) enable_signal_catcher JPP((j_common_ptr cinfo)); +EXTERN(void) start_progress_monitor JPP((j_common_ptr cinfo, cd_progress_ptr progress)); -EXTERN_1(void) end_progress_monitor JPP((j_common_ptr cinfo)); -EXTERN_1(boolean) keymatch JPP((char * arg, const char * keyword, int minchars)); -EXTERN_1(FILE *) read_stdin JPP((void)); -EXTERN_1(FILE *) write_stdout JPP((void)); +EXTERN(void) end_progress_monitor JPP((j_common_ptr cinfo)); +EXTERN(boolean) keymatch JPP((char * arg, const char * keyword, int minchars)); +EXTERN(FILE *) read_stdin JPP((void)); +EXTERN(FILE *) write_stdout JPP((void)); /* miscellaneous useful macros */ diff --git a/reactos/include/reactos/libs/libjpeg/jchuff.h b/reactos/include/reactos/libs/libjpeg/jchuff.h deleted file mode 100644 index a9599fc1e6f..00000000000 --- a/reactos/include/reactos/libs/libjpeg/jchuff.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * jchuff.h - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains declarations for Huffman entropy encoding routines - * that are shared between the sequential encoder (jchuff.c) and the - * progressive encoder (jcphuff.c). No other modules need to see these. - */ - -/* The legal range of a DCT coefficient is - * -1024 .. +1023 for 8-bit data; - * -16384 .. +16383 for 12-bit data. - * Hence the magnitude should always fit in 10 or 14 bits respectively. - */ - -#if BITS_IN_JSAMPLE == 8 -#define MAX_COEF_BITS 10 -#else -#define MAX_COEF_BITS 14 -#endif - -/* Derived data constructed for each Huffman table */ - -typedef struct { - unsigned int ehufco[256]; /* code for each symbol */ - char ehufsi[256]; /* length of code for each symbol */ - /* If no code has been allocated for a symbol S, ehufsi[S] contains 0 */ -} c_derived_tbl; - -/* Short forms of external names for systems with brain-damaged linkers. */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jpeg_make_c_derived_tbl jMkCDerived -#define jpeg_gen_optimal_table jGenOptTbl -#endif /* NEED_SHORT_EXTERNAL_NAMES */ - -/* Expand a Huffman table definition into the derived format */ -EXTERN(void) jpeg_make_c_derived_tbl - JPP((j_compress_ptr cinfo, boolean isDC, int tblno, - c_derived_tbl ** pdtbl)); - -/* Generate an optimal table definition given the specified counts */ -EXTERN(void) jpeg_gen_optimal_table - JPP((j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[])); diff --git a/reactos/include/reactos/libs/libjpeg/jconfig.h b/reactos/include/reactos/libs/libjpeg/jconfig.h index d19b12e3145..99172ce91c2 100644 --- a/reactos/include/reactos/libs/libjpeg/jconfig.h +++ b/reactos/include/reactos/libs/libjpeg/jconfig.h @@ -1,6 +1,9 @@ #define HAVE_PROTOTYPES #define HAVE_UNSIGNED_CHAR +#define HAVE_STDDEF_H +#define HAVE_STDLIB_H + #ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */ typedef unsigned char boolean; #endif @@ -12,3 +15,4 @@ typedef unsigned char boolean; #undef NEED_SHORT_EXTERNAL_NAMES #undef INCOMPLETE_TYPES_BROKEN +// typedef long INT32; diff --git a/reactos/include/reactos/libs/libjpeg/jdct.h b/reactos/include/reactos/libs/libjpeg/jdct.h index 04192a266ae..360dec80c94 100644 --- a/reactos/include/reactos/libs/libjpeg/jdct.h +++ b/reactos/include/reactos/libs/libjpeg/jdct.h @@ -14,11 +14,16 @@ /* - * A forward DCT routine is given a pointer to a work area of type DCTELEM[]; - * the DCT is to be performed in-place in that buffer. Type DCTELEM is int - * for 8-bit samples, INT32 for 12-bit samples. (NOTE: Floating-point DCT - * implementations use an array of type FAST_FLOAT, instead.) - * The DCT inputs are expected to be signed (range +-CENTERJSAMPLE). + * A forward DCT routine is given a pointer to an input sample array and + * a pointer to a work area of type DCTELEM[]; the DCT is to be performed + * in-place in that buffer. Type DCTELEM is int for 8-bit samples, INT32 + * for 12-bit samples. (NOTE: Floating-point DCT implementations use an + * array of type FAST_FLOAT, instead.) + * The input data is to be fetched from the sample array starting at a + * specified column. (Any row offset needed will be applied to the array + * pointer before it is passed to the FDCT code.) + * Note that the number of samples fetched by the FDCT routine is + * DCT_h_scaled_size * DCT_v_scaled_size. * The DCT outputs are returned scaled up by a factor of 8; they therefore * have a range of +-8K for 8-bit data, +-128K for 12-bit data. This * convention improves accuracy in integer implementations and saves some @@ -32,8 +37,12 @@ typedef int DCTELEM; /* 16 or 32 bits is fine */ typedef INT32 DCTELEM; /* must have 32 bits */ #endif -typedef JMETHOD(void, forward_DCT_method_ptr, (DCTELEM * data)); -typedef JMETHOD(void, float_DCT_method_ptr, (FAST_FLOAT * data)); +typedef JMETHOD(void, forward_DCT_method_ptr, (DCTELEM * data, + JSAMPARRAY sample_data, + JDIMENSION start_col)); +typedef JMETHOD(void, float_DCT_method_ptr, (FAST_FLOAT * data, + JSAMPARRAY sample_data, + JDIMENSION start_col)); /* @@ -44,7 +53,7 @@ typedef JMETHOD(void, float_DCT_method_ptr, (FAST_FLOAT * data)); * sample array starting at a specified column. (Any row offset needed will * be applied to the array pointer before it is passed to the IDCT code.) * Note that the number of samples emitted by the IDCT routine is - * DCT_scaled_size * DCT_scaled_size. + * DCT_h_scaled_size * DCT_v_scaled_size. */ /* typedef inverse_DCT_method_ptr is declared in jpegint.h */ @@ -84,19 +93,143 @@ typedef FAST_FLOAT FLOAT_MULT_TYPE; /* preferred floating type */ #define jpeg_fdct_islow jFDislow #define jpeg_fdct_ifast jFDifast #define jpeg_fdct_float jFDfloat +#define jpeg_fdct_7x7 jFD7x7 +#define jpeg_fdct_6x6 jFD6x6 +#define jpeg_fdct_5x5 jFD5x5 +#define jpeg_fdct_4x4 jFD4x4 +#define jpeg_fdct_3x3 jFD3x3 +#define jpeg_fdct_2x2 jFD2x2 +#define jpeg_fdct_1x1 jFD1x1 +#define jpeg_fdct_9x9 jFD9x9 +#define jpeg_fdct_10x10 jFD10x10 +#define jpeg_fdct_11x11 jFD11x11 +#define jpeg_fdct_12x12 jFD12x12 +#define jpeg_fdct_13x13 jFD13x13 +#define jpeg_fdct_14x14 jFD14x14 +#define jpeg_fdct_15x15 jFD15x15 +#define jpeg_fdct_16x16 jFD16x16 +#define jpeg_fdct_16x8 jFD16x8 +#define jpeg_fdct_14x7 jFD14x7 +#define jpeg_fdct_12x6 jFD12x6 +#define jpeg_fdct_10x5 jFD10x5 +#define jpeg_fdct_8x4 jFD8x4 +#define jpeg_fdct_6x3 jFD6x3 +#define jpeg_fdct_4x2 jFD4x2 +#define jpeg_fdct_2x1 jFD2x1 +#define jpeg_fdct_8x16 jFD8x16 +#define jpeg_fdct_7x14 jFD7x14 +#define jpeg_fdct_6x12 jFD6x12 +#define jpeg_fdct_5x10 jFD5x10 +#define jpeg_fdct_4x8 jFD4x8 +#define jpeg_fdct_3x6 jFD3x6 +#define jpeg_fdct_2x4 jFD2x4 +#define jpeg_fdct_1x2 jFD1x2 #define jpeg_idct_islow jRDislow #define jpeg_idct_ifast jRDifast #define jpeg_idct_float jRDfloat +#define jpeg_idct_7x7 jRD7x7 +#define jpeg_idct_6x6 jRD6x6 +#define jpeg_idct_5x5 jRD5x5 #define jpeg_idct_4x4 jRD4x4 +#define jpeg_idct_3x3 jRD3x3 #define jpeg_idct_2x2 jRD2x2 #define jpeg_idct_1x1 jRD1x1 +#define jpeg_idct_9x9 jRD9x9 +#define jpeg_idct_10x10 jRD10x10 +#define jpeg_idct_11x11 jRD11x11 +#define jpeg_idct_12x12 jRD12x12 +#define jpeg_idct_13x13 jRD13x13 +#define jpeg_idct_14x14 jRD14x14 +#define jpeg_idct_15x15 jRD15x15 +#define jpeg_idct_16x16 jRD16x16 +#define jpeg_idct_16x8 jRD16x8 +#define jpeg_idct_14x7 jRD14x7 +#define jpeg_idct_12x6 jRD12x6 +#define jpeg_idct_10x5 jRD10x5 +#define jpeg_idct_8x4 jRD8x4 +#define jpeg_idct_6x3 jRD6x3 +#define jpeg_idct_4x2 jRD4x2 +#define jpeg_idct_2x1 jRD2x1 +#define jpeg_idct_8x16 jRD8x16 +#define jpeg_idct_7x14 jRD7x14 +#define jpeg_idct_6x12 jRD6x12 +#define jpeg_idct_5x10 jRD5x10 +#define jpeg_idct_4x8 jRD4x8 +#define jpeg_idct_3x6 jRD3x8 +#define jpeg_idct_2x4 jRD2x4 +#define jpeg_idct_1x2 jRD1x2 #endif /* NEED_SHORT_EXTERNAL_NAMES */ /* Extern declarations for the forward and inverse DCT routines. */ -EXTERN(void) jpeg_fdct_islow JPP((DCTELEM * data)); -EXTERN(void) jpeg_fdct_ifast JPP((DCTELEM * data)); -EXTERN(void) jpeg_fdct_float JPP((FAST_FLOAT * data)); +EXTERN(void) jpeg_fdct_islow + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_ifast + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_float + JPP((FAST_FLOAT * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_7x7 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_6x6 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_5x5 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_4x4 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_3x3 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_2x2 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_1x1 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_9x9 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_10x10 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_11x11 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_12x12 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_13x13 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_14x14 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_15x15 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_16x16 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_16x8 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_14x7 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_12x6 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_10x5 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_8x4 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_6x3 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_4x2 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_2x1 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_8x16 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_7x14 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_6x12 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_5x10 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_4x8 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_3x6 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_2x4 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); +EXTERN(void) jpeg_fdct_1x2 + JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); EXTERN(void) jpeg_idct_islow JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, @@ -107,15 +240,99 @@ EXTERN(void) jpeg_idct_ifast EXTERN(void) jpeg_idct_float JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_7x7 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_6x6 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_5x5 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_4x4 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_3x3 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_2x2 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_1x1 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_9x9 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_10x10 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_11x11 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_12x12 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_13x13 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_14x14 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_15x15 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_16x16 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_16x8 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_14x7 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_12x6 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_10x5 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_8x4 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_6x3 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_4x2 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_2x1 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_8x16 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_7x14 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_6x12 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_5x10 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_4x8 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_3x6 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_2x4 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); +EXTERN(void) jpeg_idct_1x2 + JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); /* diff --git a/reactos/include/reactos/libs/libjpeg/jdhuff.h b/reactos/include/reactos/libs/libjpeg/jdhuff.h deleted file mode 100644 index ae19b6cafd7..00000000000 --- a/reactos/include/reactos/libs/libjpeg/jdhuff.h +++ /dev/null @@ -1,201 +0,0 @@ -/* - * jdhuff.h - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains declarations for Huffman entropy decoding routines - * that are shared between the sequential decoder (jdhuff.c) and the - * progressive decoder (jdphuff.c). No other modules need to see these. - */ - -/* Short forms of external names for systems with brain-damaged linkers. */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jpeg_make_d_derived_tbl jMkDDerived -#define jpeg_fill_bit_buffer jFilBitBuf -#define jpeg_huff_decode jHufDecode -#endif /* NEED_SHORT_EXTERNAL_NAMES */ - - -/* Derived data constructed for each Huffman table */ - -#define HUFF_LOOKAHEAD 8 /* # of bits of lookahead */ - -typedef struct { - /* Basic tables: (element [0] of each array is unused) */ - INT32 maxcode[18]; /* largest code of length k (-1 if none) */ - /* (maxcode[17] is a sentinel to ensure jpeg_huff_decode terminates) */ - INT32 valoffset[17]; /* huffval[] offset for codes of length k */ - /* valoffset[k] = huffval[] index of 1st symbol of code length k, less - * the smallest code of length k; so given a code of length k, the - * corresponding symbol is huffval[code + valoffset[k]] - */ - - /* Link to public Huffman table (needed only in jpeg_huff_decode) */ - JHUFF_TBL *pub; - - /* Lookahead tables: indexed by the next HUFF_LOOKAHEAD bits of - * the input data stream. If the next Huffman code is no more - * than HUFF_LOOKAHEAD bits long, we can obtain its length and - * the corresponding symbol directly from these tables. - */ - int look_nbits[1< 32 bits on your machine, and shifting/masking longs is - * reasonably fast, making bit_buf_type be long and setting BIT_BUF_SIZE - * appropriately should be a win. Unfortunately we can't define the size - * with something like #define BIT_BUF_SIZE (sizeof(bit_buf_type)*8) - * because not all machines measure sizeof in 8-bit bytes. - */ - -typedef struct { /* Bitreading state saved across MCUs */ - bit_buf_type get_buffer; /* current bit-extraction buffer */ - int bits_left; /* # of unused bits in it */ -} bitread_perm_state; - -typedef struct { /* Bitreading working state within an MCU */ - /* Current data source location */ - /* We need a copy, rather than munging the original, in case of suspension */ - const JOCTET * next_input_byte; /* => next byte to read from source */ - size_t bytes_in_buffer; /* # of bytes remaining in source buffer */ - /* Bit input buffer --- note these values are kept in register variables, - * not in this struct, inside the inner loops. - */ - bit_buf_type get_buffer; /* current bit-extraction buffer */ - int bits_left; /* # of unused bits in it */ - /* Pointer needed by jpeg_fill_bit_buffer. */ - j_decompress_ptr cinfo; /* back link to decompress master record */ -} bitread_working_state; - -/* Macros to declare and load/save bitread local variables. */ -#define BITREAD_STATE_VARS \ - register bit_buf_type get_buffer; \ - register int bits_left; \ - bitread_working_state br_state - -#define BITREAD_LOAD_STATE(cinfop,permstate) \ - br_state.cinfo = cinfop; \ - br_state.next_input_byte = cinfop->src->next_input_byte; \ - br_state.bytes_in_buffer = cinfop->src->bytes_in_buffer; \ - get_buffer = permstate.get_buffer; \ - bits_left = permstate.bits_left; - -#define BITREAD_SAVE_STATE(cinfop,permstate) \ - cinfop->src->next_input_byte = br_state.next_input_byte; \ - cinfop->src->bytes_in_buffer = br_state.bytes_in_buffer; \ - permstate.get_buffer = get_buffer; \ - permstate.bits_left = bits_left - -/* - * These macros provide the in-line portion of bit fetching. - * Use CHECK_BIT_BUFFER to ensure there are N bits in get_buffer - * before using GET_BITS, PEEK_BITS, or DROP_BITS. - * The variables get_buffer and bits_left are assumed to be locals, - * but the state struct might not be (jpeg_huff_decode needs this). - * CHECK_BIT_BUFFER(state,n,action); - * Ensure there are N bits in get_buffer; if suspend, take action. - * val = GET_BITS(n); - * Fetch next N bits. - * val = PEEK_BITS(n); - * Fetch next N bits without removing them from the buffer. - * DROP_BITS(n); - * Discard next N bits. - * The value N should be a simple variable, not an expression, because it - * is evaluated multiple times. - */ - -#define CHECK_BIT_BUFFER(state,nbits,action) \ - { if (bits_left < (nbits)) { \ - if (! jpeg_fill_bit_buffer(&(state),get_buffer,bits_left,nbits)) \ - { action; } \ - get_buffer = (state).get_buffer; bits_left = (state).bits_left; } } - -#define GET_BITS(nbits) \ - (((int) (get_buffer >> (bits_left -= (nbits)))) & ((1<<(nbits))-1)) - -#define PEEK_BITS(nbits) \ - (((int) (get_buffer >> (bits_left - (nbits)))) & ((1<<(nbits))-1)) - -#define DROP_BITS(nbits) \ - (bits_left -= (nbits)) - -/* Load up the bit buffer to a depth of at least nbits */ -EXTERN(boolean) jpeg_fill_bit_buffer - JPP((bitread_working_state * state, register bit_buf_type get_buffer, - register int bits_left, int nbits)); - - -/* - * Code for extracting next Huffman-coded symbol from input bit stream. - * Again, this is time-critical and we make the main paths be macros. - * - * We use a lookahead table to process codes of up to HUFF_LOOKAHEAD bits - * without looping. Usually, more than 95% of the Huffman codes will be 8 - * or fewer bits long. The few overlength codes are handled with a loop, - * which need not be inline code. - * - * Notes about the HUFF_DECODE macro: - * 1. Near the end of the data segment, we may fail to get enough bits - * for a lookahead. In that case, we do it the hard way. - * 2. If the lookahead table contains no entry, the next code must be - * more than HUFF_LOOKAHEAD bits long. - * 3. jpeg_huff_decode returns -1 if forced to suspend. - */ - -#define HUFF_DECODE(result,state,htbl,failaction,slowlabel) \ -{ register int nb, look; \ - if (bits_left < HUFF_LOOKAHEAD) { \ - if (! jpeg_fill_bit_buffer(&state,get_buffer,bits_left, 0)) {failaction;} \ - get_buffer = state.get_buffer; bits_left = state.bits_left; \ - if (bits_left < HUFF_LOOKAHEAD) { \ - nb = 1; goto slowlabel; \ - } \ - } \ - look = PEEK_BITS(HUFF_LOOKAHEAD); \ - if ((nb = htbl->look_nbits[look]) != 0) { \ - DROP_BITS(nb); \ - result = htbl->look_sym[look]; \ - } else { \ - nb = HUFF_LOOKAHEAD+1; \ -slowlabel: \ - if ((result=jpeg_huff_decode(&state,get_buffer,bits_left,htbl,nb)) < 0) \ - { failaction; } \ - get_buffer = state.get_buffer; bits_left = state.bits_left; \ - } \ -} - -/* Out-of-line case for Huffman code fetching */ -EXTERN(int) jpeg_huff_decode - JPP((bitread_working_state * state, register bit_buf_type get_buffer, - register int bits_left, d_derived_tbl * htbl, int min_bits)); diff --git a/reactos/include/reactos/libs/libjpeg/jerror.h b/reactos/include/reactos/libs/libjpeg/jerror.h index fcdf6a83d46..1cfb2b19d85 100644 --- a/reactos/include/reactos/libs/libjpeg/jerror.h +++ b/reactos/include/reactos/libs/libjpeg/jerror.h @@ -2,6 +2,7 @@ * jerror.h * * Copyright (C) 1994-1997, Thomas G. Lane. + * Modified 1997-2009 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -39,17 +40,15 @@ typedef enum { JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */ /* For maintenance convenience, list is alphabetical by message code name */ -JMESSAGE(JERR_ARITH_NOTIMPL, - "Sorry, there are legal restrictions on arithmetic coding") JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix") JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix") JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode") JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS") JMESSAGE(JERR_BAD_CROP_SPEC, "Invalid crop request") JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range") -JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported") +JMESSAGE(JERR_BAD_DCTSIZE, "DCT scaled block size %dx%d not supported") JMESSAGE(JERR_BAD_DROP_SAMPLING, - "Component index %d: mismatching sampling ratio %d:%d, %d:%d, %c") + "Component index %d: mismatching sampling ratio %d:%d, %d:%d, %c") JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition") JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace") JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace") @@ -96,6 +95,7 @@ JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data") JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change") JMESSAGE(JERR_NOTIMPL, "Not implemented yet") JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time") +JMESSAGE(JERR_NO_ARITH_TABLE, "Arithmetic table 0x%02x was not defined") JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported") JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined") JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image") @@ -173,6 +173,7 @@ JMESSAGE(JTRC_UNKNOWN_IDS, JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u") JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u") JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d") +JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code") JMESSAGE(JWRN_BOGUS_PROGRESSION, "Inconsistent progression sequence for component %d coefficient %d") JMESSAGE(JWRN_EXTRANEOUS_DATA, diff --git a/reactos/include/reactos/libs/libjpeg/jmorecfg.h b/reactos/include/reactos/libs/libjpeg/jmorecfg.h index 41b329ef306..a9478f460bd 100644 --- a/reactos/include/reactos/libs/libjpeg/jmorecfg.h +++ b/reactos/include/reactos/libs/libjpeg/jmorecfg.h @@ -2,6 +2,7 @@ * jmorecfg.h * * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 1997-2009 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -134,7 +135,6 @@ typedef char JOCTET; */ /* UINT8 must hold at least the values 0..255. */ -#ifndef HAVE_ALL_INTS #ifdef HAVE_UNSIGNED_CHAR typedef unsigned char UINT8; @@ -162,11 +162,15 @@ typedef short INT16; /* INT32 must hold at least signed 32-bit values. */ -#if !defined(XMD_H) && !defined(_WIN32) /* X11/xmd.h correctly defines INT32 */ +#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */ +#ifndef _BASETSD_H_ /* Microsoft defines it in basetsd.h */ +#ifndef _BASETSD_H /* MinGW is slightly different */ +#ifndef QGLOBAL_H /* Qt defines it in qglobal.h */ typedef long INT32; #endif - -#endif /* HAVE_ALL_INTS */ +#endif +#endif +#endif /* Datatype used for image dimensions. The JPEG standard only supports * images up to 64K*64K due to 16-bit fields in SOF markers. Therefore @@ -187,63 +191,14 @@ typedef unsigned int JDIMENSION; * or code profilers that require it. */ -#ifdef _WIN32 -# if defined(ALL_STATIC) -# if defined(JPEG_DLL) -# undef JPEG_DLL -# endif -# if !defined(JPEG_STATIC) -# define JPEG_STATIC -# endif -# endif -# if defined(JPEG_DLL) -# if defined(JPEG_STATIC) -# undef JPEG_STATIC -# endif -# endif -# if defined(JPEG_DLL) -/* building a DLL */ -# define JPEG_IMPEXP __declspec(dllexport) -# elif defined(JPEG_STATIC) -/* building or linking to a static library */ -# define JPEG_IMPEXP -# else -/* linking to the DLL */ -# define JPEG_IMPEXP __declspec(dllimport) -# endif -# if !defined(JPEG_API) -# define JPEG_API __cdecl -# endif -/* The only remaining magic that is necessary for cygwin */ -#elif defined(__CYGWIN__) -# if !defined(JPEG_IMPEXP) -# define JPEG_IMPEXP -# endif -# if !defined(JPEG_API) -# define JPEG_API __cdecl -# endif -#endif - -/* Ensure our magic doesn't hurt other platforms */ -#if !defined(JPEG_IMPEXP) -# define JPEG_IMPEXP -#endif -#if !defined(JPEG_API) -# define JPEG_API -#endif - /* a function called through method pointers: */ -#define METHODDEF(type) static type +#define METHODDEF(type) static type /* a function used only in its module: */ -#define LOCAL(type) static type +#define LOCAL(type) static type /* a function referenced thru EXTERNs: */ -#define GLOBAL(type) type JPEG_API +#define GLOBAL(type) type /* a reference to a GLOBAL function: */ -#ifndef EXTERN -# define EXTERN(type) extern JPEG_IMPEXP type JPEG_API -/* a reference to a "GLOBAL" function exported by sourcefiles of utility progs */ -#endif /* EXTERN */ -#define EXTERN_1(type) extern type JPEG_API +#define EXTERN(type) extern type /* This macro is used to declare a "method", that is, a function pointer. @@ -265,16 +220,12 @@ typedef unsigned int JDIMENSION; * explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol. */ -/* jmorecfg.h line 220 */ -/* HJH modification: several of the windows header files already define FAR - because of this, the code below was changed so that it only tinkers with - the FAR define if FAR is still undefined */ #ifndef FAR - #ifdef NEED_FAR_POINTERS - #define FAR far - #else - #define FAR - #endif +#ifdef NEED_FAR_POINTERS +#define FAR far +#else +#define FAR +#endif #endif @@ -318,8 +269,6 @@ typedef int boolean; * (You may HAVE to do that if your compiler doesn't like null source files.) */ -/* Arithmetic coding is unsupported for legal reasons. Complaints to IBM. */ - /* Capability options common to encoder and decoder: */ #define DCT_ISLOW_SUPPORTED /* slow but accurate integer algorithm */ @@ -328,9 +277,10 @@ typedef int boolean; /* Encoder capability options: */ -#undef C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#define C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ #define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ #define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define DCT_SCALING_SUPPORTED /* Input rescaling via DCT? (Requires DCT_ISLOW)*/ #define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */ /* Note: if you selected 12-bit data precision, it is dangerous to turn off * ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit @@ -344,12 +294,12 @@ typedef int boolean; /* Decoder capability options: */ -#undef D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ +#define D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ #define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ #define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ +#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */ #define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */ #define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */ -#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */ #undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */ #define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */ #define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */ diff --git a/reactos/include/reactos/libs/libjpeg/jpegint.h b/reactos/include/reactos/libs/libjpeg/jpegint.h index 95b00d405ca..0c27a4e4a03 100644 --- a/reactos/include/reactos/libs/libjpeg/jpegint.h +++ b/reactos/include/reactos/libs/libjpeg/jpegint.h @@ -2,6 +2,7 @@ * jpegint.h * * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 1997-2009 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -99,14 +100,16 @@ struct jpeg_downsampler { }; /* Forward DCT (also controls coefficient quantization) */ +typedef JMETHOD(void, forward_DCT_ptr, + (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY sample_data, JBLOCKROW coef_blocks, + JDIMENSION start_row, JDIMENSION start_col, + JDIMENSION num_blocks)); + struct jpeg_forward_dct { JMETHOD(void, start_pass, (j_compress_ptr cinfo)); - /* perhaps this should be an array??? */ - JMETHOD(void, forward_DCT, (j_compress_ptr cinfo, - jpeg_component_info * compptr, - JSAMPARRAY sample_data, JBLOCKROW coef_blocks, - JDIMENSION start_row, JDIMENSION start_col, - JDIMENSION num_blocks)); + /* It is useful to allow each component to have a separate FDCT method. */ + forward_DCT_ptr forward_DCT[MAX_COMPONENTS]; }; /* Entropy encoding */ @@ -210,10 +213,6 @@ struct jpeg_entropy_decoder { JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); JMETHOD(boolean, decode_mcu, (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)); - - /* This is here to share code between baseline and progressive decoders; */ - /* other modules probably should not use it */ - boolean insufficient_data; /* set TRUE after emitting warning */ }; /* Inverse DCT (also performs dequantization) */ @@ -303,7 +302,7 @@ struct jpeg_color_quantizer { #define jinit_downsampler jIDownsampler #define jinit_forward_dct jIFDCT #define jinit_huff_encoder jIHEncoder -#define jinit_phuff_encoder jIPHEncoder +#define jinit_arith_encoder jIAEncoder #define jinit_marker_writer jIMWriter #define jinit_master_decompress jIDMaster #define jinit_d_main_controller jIDMainC @@ -312,7 +311,7 @@ struct jpeg_color_quantizer { #define jinit_input_controller jIInCtlr #define jinit_marker_reader jIMReader #define jinit_huff_decoder jIHDecoder -#define jinit_phuff_decoder jIPHDecoder +#define jinit_arith_decoder jIADecoder #define jinit_inverse_dct jIIDCT #define jinit_upsampler jIUpsampler #define jinit_color_deconverter jIDColor @@ -327,6 +326,13 @@ struct jpeg_color_quantizer { #define jzero_far jZeroFar #define jpeg_zigzag_order jZIGTable #define jpeg_natural_order jZAGTable +#define jpeg_natural_order7 jZAGTable7 +#define jpeg_natural_order6 jZAGTable6 +#define jpeg_natural_order5 jZAGTable5 +#define jpeg_natural_order4 jZAGTable4 +#define jpeg_natural_order3 jZAGTable3 +#define jpeg_natural_order2 jZAGTable2 +#define jpeg_aritab jAriTab #endif /* NEED_SHORT_EXTERNAL_NAMES */ @@ -344,7 +350,7 @@ EXTERN(void) jinit_color_converter JPP((j_compress_ptr cinfo)); EXTERN(void) jinit_downsampler JPP((j_compress_ptr cinfo)); EXTERN(void) jinit_forward_dct JPP((j_compress_ptr cinfo)); EXTERN(void) jinit_huff_encoder JPP((j_compress_ptr cinfo)); -EXTERN(void) jinit_phuff_encoder JPP((j_compress_ptr cinfo)); +EXTERN(void) jinit_arith_encoder JPP((j_compress_ptr cinfo)); EXTERN(void) jinit_marker_writer JPP((j_compress_ptr cinfo)); /* Decompression module initialization routines */ EXTERN(void) jinit_master_decompress JPP((j_decompress_ptr cinfo)); @@ -357,7 +363,7 @@ EXTERN(void) jinit_d_post_controller JPP((j_decompress_ptr cinfo, EXTERN(void) jinit_input_controller JPP((j_decompress_ptr cinfo)); EXTERN(void) jinit_marker_reader JPP((j_decompress_ptr cinfo)); EXTERN(void) jinit_huff_decoder JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_phuff_decoder JPP((j_decompress_ptr cinfo)); +EXTERN(void) jinit_arith_decoder JPP((j_decompress_ptr cinfo)); EXTERN(void) jinit_inverse_dct JPP((j_decompress_ptr cinfo)); EXTERN(void) jinit_upsampler JPP((j_decompress_ptr cinfo)); EXTERN(void) jinit_color_deconverter JPP((j_decompress_ptr cinfo)); @@ -381,6 +387,15 @@ EXTERN(void) jzero_far JPP((void FAR * target, size_t bytestozero)); extern const int jpeg_zigzag_order[]; /* natural coef order to zigzag order */ #endif extern const int jpeg_natural_order[]; /* zigzag coef order to natural order */ +extern const int jpeg_natural_order7[]; /* zz to natural order for 7x7 block */ +extern const int jpeg_natural_order6[]; /* zz to natural order for 6x6 block */ +extern const int jpeg_natural_order5[]; /* zz to natural order for 5x5 block */ +extern const int jpeg_natural_order4[]; /* zz to natural order for 4x4 block */ +extern const int jpeg_natural_order3[]; /* zz to natural order for 3x3 block */ +extern const int jpeg_natural_order2[]; /* zz to natural order for 2x2 block */ + +/* Arithmetic coding probability estimation tables in jaricom.c */ +extern const INT32 jpeg_aritab[]; /* Suppress undefined-structure complaints if necessary. */ diff --git a/reactos/include/reactos/libs/libjpeg/jpeglib.h b/reactos/include/reactos/libs/libjpeg/jpeglib.h index 2091dbebf94..5039d4bf4c4 100644 --- a/reactos/include/reactos/libs/libjpeg/jpeglib.h +++ b/reactos/include/reactos/libs/libjpeg/jpeglib.h @@ -2,6 +2,7 @@ * jpeglib.h * * Copyright (C) 1991-1998, Thomas G. Lane. + * Modified 2002-2009 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -13,10 +14,6 @@ #ifndef JPEGLIB_H #define JPEGLIB_H -#ifdef __cplusplus -extern "C" { -#endif - /* * First we include the configuration files that record how this * installation of the JPEG library is set up. jconfig.h can be @@ -29,15 +26,18 @@ extern "C" { #endif #include "jmorecfg.h" /* seldom changed options */ + #ifdef __cplusplus +#ifndef DONT_USE_EXTERN_C extern "C" { -#endif /* __cplusplus */ +#endif +#endif /* Version ID for the JPEG library. - * Might be useful for tests like "#if JPEG_LIB_VERSION >= 60". + * Might be useful for tests like "#if JPEG_LIB_VERSION >= 80". */ -#define JPEG_LIB_VERSION 62 /* Version 6b */ +#define JPEG_LIB_VERSION 80 /* Version 8.0 */ /* Various constants determining the sizes of things. @@ -145,18 +145,18 @@ typedef struct { */ JDIMENSION width_in_blocks; JDIMENSION height_in_blocks; - /* Size of a DCT block in samples. Always DCTSIZE for compression. - * For decompression this is the size of the output from one DCT block, - * reflecting any scaling we choose to apply during the IDCT step. - * Values of 1,2,4,8 are likely to be supported. Note that different - * components may receive different IDCT scalings. + /* Size of a DCT block in samples, + * reflecting any scaling we choose to apply during the DCT step. + * Values from 1 to 16 are supported. + * Note that different components may receive different DCT scalings. */ - int DCT_scaled_size; + int DCT_h_scaled_size; + int DCT_v_scaled_size; /* The downsampled dimensions are the component's actual, unpadded number - * of samples at the main buffer (preprocessing/compression interface), thus - * downsampled_width = ceil(image_width * Hi/Hmax) - * and similarly for height. For decompression, IDCT scaling is included, so - * downsampled_width = ceil(image_width * Hi/Hmax * DCT_scaled_size/DCTSIZE) + * of samples at the main buffer (preprocessing/compression interface); + * DCT scaling is included, so + * downsampled_width = ceil(image_width * Hi/Hmax * DCT_h_scaled_size/DCTSIZE) + * and similarly for height. */ JDIMENSION downsampled_width; /* actual width in samples */ JDIMENSION downsampled_height; /* actual height in samples */ @@ -171,7 +171,7 @@ typedef struct { int MCU_width; /* number of blocks per MCU, horizontally */ int MCU_height; /* number of blocks per MCU, vertically */ int MCU_blocks; /* MCU_width * MCU_height */ - int MCU_sample_width; /* MCU width in samples, MCU_width*DCT_scaled_size */ + int MCU_sample_width; /* MCU width in samples: MCU_width * DCT_h_scaled_size */ int last_col_width; /* # of non-dummy blocks across in last MCU */ int last_row_height; /* # of non-dummy blocks down in last MCU */ @@ -298,6 +298,17 @@ struct jpeg_compress_struct { * helper routines to simplify changing parameters. */ + unsigned int scale_num, scale_denom; /* fraction by which to scale image */ + + JDIMENSION jpeg_width; /* scaled JPEG image width */ + JDIMENSION jpeg_height; /* scaled JPEG image height */ + /* Dimensions of actual JPEG image that will be written to file, + * derived from input dimensions by scaling factors above. + * These fields are computed by jpeg_start_compress(). + * You can also use jpeg_calc_jpeg_dimensions() to determine these values + * in advance of calling jpeg_start_compress(). + */ + int data_precision; /* bits of precision in image data */ int num_components; /* # of color components in JPEG image */ @@ -305,14 +316,17 @@ struct jpeg_compress_struct { jpeg_component_info * comp_info; /* comp_info[i] describes component that appears i'th in SOF */ - + JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; - /* ptrs to coefficient quantization tables, or NULL if not defined */ - + int q_scale_factor[NUM_QUANT_TBLS]; + /* ptrs to coefficient quantization tables, or NULL if not defined, + * and corresponding scale factors (percentage, initialized 100). + */ + JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; /* ptrs to Huffman coding tables, or NULL if not defined */ - + UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ @@ -328,6 +342,7 @@ struct jpeg_compress_struct { boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ boolean optimize_coding; /* TRUE=optimize entropy encoding parms */ boolean CCIR601_sampling; /* TRUE=first samples are cosited */ + boolean do_fancy_downsampling; /* TRUE=apply fancy downsampling */ int smoothing_factor; /* 1..100, or 0 for no input smoothing */ J_DCT_METHOD dct_method; /* DCT algorithm selector */ @@ -371,6 +386,9 @@ struct jpeg_compress_struct { int max_h_samp_factor; /* largest h_samp_factor */ int max_v_samp_factor; /* largest v_samp_factor */ + int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */ + int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */ + JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coef ctlr */ /* The coefficient controller receives data in units of MCU rows as defined * for fully interleaved scans (whether the JPEG file is interleaved or not). @@ -396,6 +414,10 @@ struct jpeg_compress_struct { int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ + int block_size; /* the basic DCT block size: 1..16 */ + const int * natural_order; /* natural-order position array */ + int lim_Se; /* min( Se, DCTSIZE2-1 ) */ + /* * Links to compression subobjects (methods and private variables of modules) */ @@ -542,6 +564,7 @@ struct jpeg_decompress_struct { jpeg_component_info * comp_info; /* comp_info[i] describes component that appears i'th in SOF */ + boolean is_baseline; /* TRUE if Baseline SOF0 encountered */ boolean progressive_mode; /* TRUE if SOFn specifies progressive mode */ boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ @@ -582,7 +605,8 @@ struct jpeg_decompress_struct { int max_h_samp_factor; /* largest h_samp_factor */ int max_v_samp_factor; /* largest v_samp_factor */ - int min_DCT_scaled_size; /* smallest DCT_scaled_size of any component */ + int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */ + int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */ JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */ /* The coefficient controller's input and output progress is measured in @@ -590,7 +614,7 @@ struct jpeg_decompress_struct { * in fully interleaved JPEG scans, but are used whether the scan is * interleaved or not. We define an iMCU row as v_samp_factor DCT block * rows of each component. Therefore, the IDCT output contains - * v_samp_factor*DCT_scaled_size sample rows of a component per iMCU row. + * v_samp_factor*DCT_v_scaled_size sample rows of a component per iMCU row. */ JSAMPLE * sample_range_limit; /* table for fast range-limiting */ @@ -614,6 +638,12 @@ struct jpeg_decompress_struct { int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ + /* These fields are derived from Se of first SOS marker. + */ + int block_size; /* the basic DCT block size: 1..16 */ + const int * natural_order; /* natural-order position array for entropy decode */ + int lim_Se; /* min( Se, DCTSIZE2-1 ) for entropy decode */ + /* This field is shared between entropy decoder and marker parser. * It is either zero or the code of a JPEG marker that has been * read from the data source, but has not yet been processed. @@ -843,11 +873,14 @@ typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo)); #define jpeg_destroy_decompress jDestDecompress #define jpeg_stdio_dest jStdDest #define jpeg_stdio_src jStdSrc +#define jpeg_mem_dest jMemDest +#define jpeg_mem_src jMemSrc #define jpeg_set_defaults jSetDefaults #define jpeg_set_colorspace jSetColorspace #define jpeg_default_colorspace jDefColorspace #define jpeg_set_quality jSetQuality #define jpeg_set_linear_quality jSetLQuality +#define jpeg_default_qtables jDefQTables #define jpeg_add_quant_table jAddQuantTable #define jpeg_quality_scaling jQualityScaling #define jpeg_simple_progression jSimProgress @@ -857,6 +890,7 @@ typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo)); #define jpeg_start_compress jStrtCompress #define jpeg_write_scanlines jWrtScanlines #define jpeg_finish_compress jFinCompress +#define jpeg_calc_jpeg_dimensions jCjpegDimensions #define jpeg_write_raw_data jWrtRawData #define jpeg_write_marker jWrtMarker #define jpeg_write_m_header jWrtMHeader @@ -873,6 +907,7 @@ typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo)); #define jpeg_input_complete jInComplete #define jpeg_new_colormap jNewCMap #define jpeg_consume_input jConsumeInput +#define jpeg_core_output_dimensions jCoreDimensions #define jpeg_calc_output_dimensions jCalcDimensions #define jpeg_save_markers jSaveMarkers #define jpeg_set_marker_processor jSetMarker @@ -917,6 +952,14 @@ EXTERN(void) jpeg_destroy_decompress JPP((j_decompress_ptr cinfo)); EXTERN(void) jpeg_stdio_dest JPP((j_compress_ptr cinfo, FILE * outfile)); EXTERN(void) jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile)); +/* Data source and destination managers: memory buffers. */ +EXTERN(void) jpeg_mem_dest JPP((j_compress_ptr cinfo, + unsigned char ** outbuffer, + unsigned long * outsize)); +EXTERN(void) jpeg_mem_src JPP((j_decompress_ptr cinfo, + unsigned char * inbuffer, + unsigned long insize)); + /* Default parameter setup for compression */ EXTERN(void) jpeg_set_defaults JPP((j_compress_ptr cinfo)); /* Compression parameter setup aids */ @@ -928,6 +971,8 @@ EXTERN(void) jpeg_set_quality JPP((j_compress_ptr cinfo, int quality, EXTERN(void) jpeg_set_linear_quality JPP((j_compress_ptr cinfo, int scale_factor, boolean force_baseline)); +EXTERN(void) jpeg_default_qtables JPP((j_compress_ptr cinfo, + boolean force_baseline)); EXTERN(void) jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl, const unsigned int *basic_table, int scale_factor, @@ -947,12 +992,15 @@ EXTERN(JDIMENSION) jpeg_write_scanlines JPP((j_compress_ptr cinfo, JDIMENSION num_lines)); EXTERN(void) jpeg_finish_compress JPP((j_compress_ptr cinfo)); +/* Precalculate JPEG dimensions for current compression parameters. */ +EXTERN(void) jpeg_calc_jpeg_dimensions JPP((j_compress_ptr cinfo)); + /* Replaces jpeg_write_scanlines when writing raw downsampled data. */ EXTERN(JDIMENSION) jpeg_write_raw_data JPP((j_compress_ptr cinfo, JSAMPIMAGE data, JDIMENSION num_lines)); -/* Write a special marker. See libjpeg.doc concerning safe usage. */ +/* Write a special marker. See libjpeg.txt concerning safe usage. */ EXTERN(void) jpeg_write_marker JPP((j_compress_ptr cinfo, int marker, const JOCTET * dataptr, unsigned int datalen)); @@ -1006,6 +1054,7 @@ EXTERN(int) jpeg_consume_input JPP((j_decompress_ptr cinfo)); #define JPEG_SCAN_COMPLETED 4 /* Completed last iMCU row of a scan */ /* Precalculate output dimensions for current decompression parameters. */ +EXTERN(void) jpeg_core_output_dimensions JPP((j_decompress_ptr cinfo)); EXTERN(void) jpeg_calc_output_dimensions JPP((j_decompress_ptr cinfo)); /* Control saving of COM and APPn markers into marker_list. */ @@ -1087,9 +1136,6 @@ struct jpeg_color_quantizer { long dummy; }; #endif /* JPEG_INTERNALS */ #endif /* INCOMPLETE_TYPES_BROKEN */ -#ifdef __cplusplus -} -#endif /* * The JPEG library modules define JPEG_INTERNALS before including this file. @@ -1104,7 +1150,9 @@ struct jpeg_color_quantizer { long dummy; }; #endif #ifdef __cplusplus +#ifndef DONT_USE_EXTERN_C } #endif +#endif #endif /* JPEGLIB_H */ diff --git a/reactos/include/reactos/libs/libjpeg/jversion.h b/reactos/include/reactos/libs/libjpeg/jversion.h index 6472c58d351..70c8b6fe176 100644 --- a/reactos/include/reactos/libs/libjpeg/jversion.h +++ b/reactos/include/reactos/libs/libjpeg/jversion.h @@ -1,7 +1,7 @@ /* * jversion.h * - * Copyright (C) 1991-1998, Thomas G. Lane. + * Copyright (C) 1991-2010, Thomas G. Lane, Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -9,6 +9,6 @@ */ -#define JVERSION "6b 27-Mar-1998" +#define JVERSION "8b 16-May-2010" -#define JCOPYRIGHT "Copyright (C) 1998, Thomas G. Lane" +#define JCOPYRIGHT "Copyright (C) 2010, Thomas G. Lane, Guido Vollbeding" diff --git a/reactos/include/reactos/libs/libjpeg/libjpeg.reactos.diff b/reactos/include/reactos/libs/libjpeg/libjpeg.reactos.diff deleted file mode 100644 index 93cfa54eae2..00000000000 --- a/reactos/include/reactos/libs/libjpeg/libjpeg.reactos.diff +++ /dev/null @@ -1,12 +0,0 @@ -Index: include/reactos/libs/libjpeg/jmorecfg.h -=================================================================== ---- include/reactos/libs/libjpeg/jmorecfg.h (revision 42441) -+++ include/reactos/libs/libjpeg/jmorecfg.h (working copy) -@@ -24,7 +24,6 @@ - - #if (defined (_MSC_VER) && (_MSC_VER >= 800)) - #define HAVE_UNSIGNED_CHAR --#define HAVE_ALL_INTS - #define EXTERN(type) extern type __cdecl - #endif - diff --git a/reactos/include/reactos/libs/libjpeg/transupp.h b/reactos/include/reactos/libs/libjpeg/transupp.h index 00b6a8412d2..7c16c19c440 100644 --- a/reactos/include/reactos/libs/libjpeg/transupp.h +++ b/reactos/include/reactos/libs/libjpeg/transupp.h @@ -1,7 +1,7 @@ /* * transupp.h * - * Copyright (C) 1997-2001, Thomas G. Lane. + * Copyright (C) 1997-2009, Thomas G. Lane, Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -58,9 +58,14 @@ * dimensions to keep the lower right crop corner unchanged. (Thus, the * output image covers at least the requested region, but may cover more.) * - * If both crop and a rotate/flip transform are requested, the crop is applied - * last --- that is, the crop region is specified in terms of the destination - * image. + * We also provide a lossless-resize option, which is kind of a lossless-crop + * operation in the DCT coefficient block domain - it discards higher-order + * coefficients and losslessly preserves lower-order coefficients of a + * sub-block. + * + * Rotate/flip transform, resize, and crop can be requested together in a + * single invocation. The crop is applied last --- that is, the crop region + * is specified in terms of the destination image after transform/resize. * * We also offer a "force to grayscale" option, which simply discards the * chrominance channels of a YCbCr image. This is lossless in the sense that @@ -96,8 +101,7 @@ typedef enum { JXFORM_TRANSVERSE, /* transpose across UR-to-LL axis */ JXFORM_ROT_90, /* 90-degree clockwise rotation */ JXFORM_ROT_180, /* 180-degree rotation */ - JXFORM_ROT_270, /* 270-degree clockwise (or 90 ccw) */ - JXFORM_DROP /* drop */ + JXFORM_ROT_270 /* 270-degree clockwise (or 90 ccw) */ } JXFORM_CODE; /* @@ -137,10 +141,6 @@ typedef struct { JDIMENSION crop_yoffset; /* Y offset of selected region */ JCROP_CODE crop_yoffset_set; /* (negative measures from bottom edge) */ - /* Drop parameters: set by caller for drop request */ - j_decompress_ptr drop_ptr; - jvirt_barray_ptr * drop_coef_arrays; - /* Internal workspace: caller should not touch these */ int num_components; /* # of components in workspace */ jvirt_barray_ptr * workspace_coef_arrays; /* workspace for transformations */ @@ -148,45 +148,43 @@ typedef struct { JDIMENSION output_height; JDIMENSION x_crop_offset; /* destination crop offsets measured in iMCUs */ JDIMENSION y_crop_offset; - JDIMENSION drop_width; /* drop dimensions measured in iMCUs */ - JDIMENSION drop_height; - int max_h_samp_factor; /* destination iMCU size */ - int max_v_samp_factor; + int iMCU_sample_width; /* destination iMCU size */ + int iMCU_sample_height; } jpeg_transform_info; #if TRANSFORMS_SUPPORTED /* Parse a crop specification (written in X11 geometry style) */ -EXTERN_1(boolean) jtransform_parse_crop_spec +EXTERN(boolean) jtransform_parse_crop_spec JPP((jpeg_transform_info *info, const char *spec)); /* Request any required workspace */ -EXTERN_1(void) jtransform_request_workspace +EXTERN(boolean) jtransform_request_workspace JPP((j_decompress_ptr srcinfo, jpeg_transform_info *info)); /* Adjust output image parameters */ -EXTERN_1(jvirt_barray_ptr *) jtransform_adjust_parameters +EXTERN(jvirt_barray_ptr *) jtransform_adjust_parameters JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo, jvirt_barray_ptr *src_coef_arrays, jpeg_transform_info *info)); /* Execute the actual transformation, if any */ -EXTERN_1(void) jtransform_execute_transform +EXTERN(void) jtransform_execute_transform JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo, jvirt_barray_ptr *src_coef_arrays, jpeg_transform_info *info)); /* Determine whether lossless transformation is perfectly * possible for a specified image and transformation. */ -EXTERN_1(boolean) jtransform_perfect_transform - JPP((JDIMENSION image_width, JDIMENSION image_height, - int MCU_width, int MCU_height, - JXFORM_CODE transform)); +EXTERN(boolean) jtransform_perfect_transform + JPP((JDIMENSION image_width, JDIMENSION image_height, + int MCU_width, int MCU_height, + JXFORM_CODE transform)); /* jtransform_execute_transform used to be called * jtransform_execute_transformation, but some compilers complain about * routine names that long. This macro is here to avoid breaking any * old source code that uses the original name... */ -#define jtransform_execute_transformation jtransform_execute_transform +#define jtransform_execute_transformation jtransform_execute_transform #endif /* TRANSFORMS_SUPPORTED */ @@ -198,16 +196,15 @@ EXTERN_1(boolean) jtransform_perfect_transform typedef enum { JCOPYOPT_NONE, /* copy no optional markers */ JCOPYOPT_COMMENTS, /* copy only comment (COM) markers */ - JCOPYOPT_ALL, /* copy all optional markers */ - JCOPYOPT_EXIF /* copy Exif APP1 marker */ + JCOPYOPT_ALL /* copy all optional markers */ } JCOPY_OPTION; #define JCOPYOPT_DEFAULT JCOPYOPT_COMMENTS /* recommended default */ /* Setup decompression object to save desired markers in memory */ -EXTERN_1(void) jcopy_markers_setup +EXTERN(void) jcopy_markers_setup JPP((j_decompress_ptr srcinfo, JCOPY_OPTION option)); /* Copy markers saved in the given source object to the destination object */ -EXTERN_1(void) jcopy_markers_execute +EXTERN(void) jcopy_markers_execute JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo, JCOPY_OPTION option)); diff --git a/reactos/include/reactos/libs/libpng/png.h b/reactos/include/reactos/libs/libpng/png.h new file mode 100644 index 00000000000..842f3fc951b --- /dev/null +++ b/reactos/include/reactos/libs/libpng/png.h @@ -0,0 +1,2701 @@ + +/* png.h - header file for PNG reference library + * + * libpng version 1.4.3 - June 26, 2010 + * Copyright (c) 1998-2010 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license (See LICENSE, below) + * + * Authors and maintainers: + * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat + * libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger + * libpng versions 0.97, January 1998, through 1.4.3 - June 26, 2010: Glenn + * See also "Contributing Authors", below. + * + * Note about libpng version numbers: + * + * Due to various miscommunications, unforeseen code incompatibilities + * and occasional factors outside the authors' control, version numbering + * on the library has not always been consistent and straightforward. + * The following table summarizes matters since version 0.89c, which was + * the first widely used release: + * + * source png.h png.h shared-lib + * version string int version + * ------- ------ ----- ---------- + * 0.89c "1.0 beta 3" 0.89 89 1.0.89 + * 0.90 "1.0 beta 4" 0.90 90 0.90 [should have been 2.0.90] + * 0.95 "1.0 beta 5" 0.95 95 0.95 [should have been 2.0.95] + * 0.96 "1.0 beta 6" 0.96 96 0.96 [should have been 2.0.96] + * 0.97b "1.00.97 beta 7" 1.00.97 97 1.0.1 [should have been 2.0.97] + * 0.97c 0.97 97 2.0.97 + * 0.98 0.98 98 2.0.98 + * 0.99 0.99 98 2.0.99 + * 0.99a-m 0.99 99 2.0.99 + * 1.00 1.00 100 2.1.0 [100 should be 10000] + * 1.0.0 (from here on, the 100 2.1.0 [100 should be 10000] + * 1.0.1 png.h string is 10001 2.1.0 + * 1.0.1a-e identical to the 10002 from here on, the shared library + * 1.0.2 source version) 10002 is 2.V where V is the source code + * 1.0.2a-b 10003 version, except as noted. + * 1.0.3 10003 + * 1.0.3a-d 10004 + * 1.0.4 10004 + * 1.0.4a-f 10005 + * 1.0.5 (+ 2 patches) 10005 + * 1.0.5a-d 10006 + * 1.0.5e-r 10100 (not source compatible) + * 1.0.5s-v 10006 (not binary compatible) + * 1.0.6 (+ 3 patches) 10006 (still binary incompatible) + * 1.0.6d-f 10007 (still binary incompatible) + * 1.0.6g 10007 + * 1.0.6h 10007 10.6h (testing xy.z so-numbering) + * 1.0.6i 10007 10.6i + * 1.0.6j 10007 2.1.0.6j (incompatible with 1.0.0) + * 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 (binary compatible) + * 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 (binary compatible) + * 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible) + * 1.0.7 1 10007 (still compatible) + * 1.0.8beta1-4 1 10008 2.1.0.8beta1-4 + * 1.0.8rc1 1 10008 2.1.0.8rc1 + * 1.0.8 1 10008 2.1.0.8 + * 1.0.9beta1-6 1 10009 2.1.0.9beta1-6 + * 1.0.9rc1 1 10009 2.1.0.9rc1 + * 1.0.9beta7-10 1 10009 2.1.0.9beta7-10 + * 1.0.9rc2 1 10009 2.1.0.9rc2 + * 1.0.9 1 10009 2.1.0.9 + * 1.0.10beta1 1 10010 2.1.0.10beta1 + * 1.0.10rc1 1 10010 2.1.0.10rc1 + * 1.0.10 1 10010 2.1.0.10 + * 1.0.11beta1-3 1 10011 2.1.0.11beta1-3 + * 1.0.11rc1 1 10011 2.1.0.11rc1 + * 1.0.11 1 10011 2.1.0.11 + * 1.0.12beta1-2 2 10012 2.1.0.12beta1-2 + * 1.0.12rc1 2 10012 2.1.0.12rc1 + * 1.0.12 2 10012 2.1.0.12 + * 1.1.0a-f - 10100 2.1.1.0a-f (branch abandoned) + * 1.2.0beta1-2 2 10200 2.1.2.0beta1-2 + * 1.2.0beta3-5 3 10200 3.1.2.0beta3-5 + * 1.2.0rc1 3 10200 3.1.2.0rc1 + * 1.2.0 3 10200 3.1.2.0 + * 1.2.1beta1-4 3 10201 3.1.2.1beta1-4 + * 1.2.1rc1-2 3 10201 3.1.2.1rc1-2 + * 1.2.1 3 10201 3.1.2.1 + * 1.2.2beta1-6 12 10202 12.so.0.1.2.2beta1-6 + * 1.0.13beta1 10 10013 10.so.0.1.0.13beta1 + * 1.0.13rc1 10 10013 10.so.0.1.0.13rc1 + * 1.2.2rc1 12 10202 12.so.0.1.2.2rc1 + * 1.0.13 10 10013 10.so.0.1.0.13 + * 1.2.2 12 10202 12.so.0.1.2.2 + * 1.2.3rc1-6 12 10203 12.so.0.1.2.3rc1-6 + * 1.2.3 12 10203 12.so.0.1.2.3 + * 1.2.4beta1-3 13 10204 12.so.0.1.2.4beta1-3 + * 1.0.14rc1 13 10014 10.so.0.1.0.14rc1 + * 1.2.4rc1 13 10204 12.so.0.1.2.4rc1 + * 1.0.14 10 10014 10.so.0.1.0.14 + * 1.2.4 13 10204 12.so.0.1.2.4 + * 1.2.5beta1-2 13 10205 12.so.0.1.2.5beta1-2 + * 1.0.15rc1-3 10 10015 10.so.0.1.0.15rc1-3 + * 1.2.5rc1-3 13 10205 12.so.0.1.2.5rc1-3 + * 1.0.15 10 10015 10.so.0.1.0.15 + * 1.2.5 13 10205 12.so.0.1.2.5 + * 1.2.6beta1-4 13 10206 12.so.0.1.2.6beta1-4 + * 1.0.16 10 10016 10.so.0.1.0.16 + * 1.2.6 13 10206 12.so.0.1.2.6 + * 1.2.7beta1-2 13 10207 12.so.0.1.2.7beta1-2 + * 1.0.17rc1 10 10017 12.so.0.1.0.17rc1 + * 1.2.7rc1 13 10207 12.so.0.1.2.7rc1 + * 1.0.17 10 10017 12.so.0.1.0.17 + * 1.2.7 13 10207 12.so.0.1.2.7 + * 1.2.8beta1-5 13 10208 12.so.0.1.2.8beta1-5 + * 1.0.18rc1-5 10 10018 12.so.0.1.0.18rc1-5 + * 1.2.8rc1-5 13 10208 12.so.0.1.2.8rc1-5 + * 1.0.18 10 10018 12.so.0.1.0.18 + * 1.2.8 13 10208 12.so.0.1.2.8 + * 1.2.9beta1-3 13 10209 12.so.0.1.2.9beta1-3 + * 1.2.9beta4-11 13 10209 12.so.0.9[.0] + * 1.2.9rc1 13 10209 12.so.0.9[.0] + * 1.2.9 13 10209 12.so.0.9[.0] + * 1.2.10beta1-7 13 10210 12.so.0.10[.0] + * 1.2.10rc1-2 13 10210 12.so.0.10[.0] + * 1.2.10 13 10210 12.so.0.10[.0] + * 1.4.0beta1-5 14 10400 14.so.0.0[.0] + * 1.2.11beta1-4 13 10211 12.so.0.11[.0] + * 1.4.0beta7-8 14 10400 14.so.0.0[.0] + * 1.2.11 13 10211 12.so.0.11[.0] + * 1.2.12 13 10212 12.so.0.12[.0] + * 1.4.0beta9-14 14 10400 14.so.0.0[.0] + * 1.2.13 13 10213 12.so.0.13[.0] + * 1.4.0beta15-36 14 10400 14.so.0.0[.0] + * 1.4.0beta37-87 14 10400 14.so.14.0[.0] + * 1.4.0rc01 14 10400 14.so.14.0[.0] + * 1.4.0beta88-109 14 10400 14.so.14.0[.0] + * 1.4.0rc02-08 14 10400 14.so.14.0[.0] + * 1.4.0 14 10400 14.so.14.0[.0] + * 1.4.1beta01-03 14 10401 14.so.14.1[.0] + * 1.4.1rc01 14 10401 14.so.14.1[.0] + * 1.4.1beta04-12 14 10401 14.so.14.1[.0] + * 1.4.1rc02-04 14 10401 14.so.14.1[.0] + * 1.4.1 14 10401 14.so.14.1[.0] + * 1.4.2beta01 14 10402 14.so.14.2[.0] + * 1.4.2rc02-06 14 10402 14.so.14.2[.0] + * 1.4.2 14 10402 14.so.14.2[.0] + * 1.4.3beta01-05 14 10403 14.so.14.3[.0] + * 1.4.3rc01-03 14 10403 14.so.14.3[.0] + * 1.4.3 14 10403 14.so.14.3[.0] + * + * Henceforth the source version will match the shared-library major + * and minor numbers; the shared-library major version number will be + * used for changes in backward compatibility, as it is intended. The + * PNG_LIBPNG_VER macro, which is not used within libpng but is available + * for applications, is an unsigned integer of the form xyyzz corresponding + * to the source version x.y.z (leading zeros in y and z). Beta versions + * were given the previous public release number plus a letter, until + * version 1.0.6j; from then on they were given the upcoming public + * release number plus "betaNN" or "rcN". + * + * Binary incompatibility exists only when applications make direct access + * to the info_ptr or png_ptr members through png.h, and the compiled + * application is loaded with a different version of the library. + * + * DLLNUM will change each time there are forward or backward changes + * in binary compatibility (e.g., when a new feature is added). + * + * See libpng.txt or libpng.3 for more information. The PNG specification + * is available as a W3C Recommendation and as an ISO Specification, + * defines should NOT be changed. + */ +#define PNG_INFO_gAMA 0x0001 +#define PNG_INFO_sBIT 0x0002 +#define PNG_INFO_cHRM 0x0004 +#define PNG_INFO_PLTE 0x0008 +#define PNG_INFO_tRNS 0x0010 +#define PNG_INFO_bKGD 0x0020 +#define PNG_INFO_hIST 0x0040 +#define PNG_INFO_pHYs 0x0080 +#define PNG_INFO_oFFs 0x0100 +#define PNG_INFO_tIME 0x0200 +#define PNG_INFO_pCAL 0x0400 +#define PNG_INFO_sRGB 0x0800 /* GR-P, 0.96a */ +#define PNG_INFO_iCCP 0x1000 /* ESR, 1.0.6 */ +#define PNG_INFO_sPLT 0x2000 /* ESR, 1.0.6 */ +#define PNG_INFO_sCAL 0x4000 /* ESR, 1.0.6 */ +#define PNG_INFO_IDAT 0x8000L /* ESR, 1.0.6 */ + +/* This is used for the transformation routines, as some of them + * change these values for the row. It also should enable using + * the routines for other purposes. + */ +typedef struct png_row_info_struct +{ + png_uint_32 width; /* width of row */ + png_size_t rowbytes; /* number of bytes in row */ + png_byte color_type; /* color type of row */ + png_byte bit_depth; /* bit depth of row */ + png_byte channels; /* number of channels (1, 2, 3, or 4) */ + png_byte pixel_depth; /* bits per pixel (depth * channels) */ +} png_row_info; + +typedef png_row_info FAR * png_row_infop; +typedef png_row_info FAR * FAR * png_row_infopp; + +/* These are the function types for the I/O functions and for the functions + * that allow the user to override the default I/O functions with his or her + * own. The png_error_ptr type should match that of user-supplied warning + * and error functions, while the png_rw_ptr type should match that of the + * user read/write data functions. + */ +typedef struct png_struct_def png_struct; +typedef png_struct FAR * png_structp; + +typedef void (PNGAPI *png_error_ptr) PNGARG((png_structp, png_const_charp)); +typedef void (PNGAPI *png_rw_ptr) PNGARG((png_structp, png_bytep, png_size_t)); +typedef void (PNGAPI *png_flush_ptr) PNGARG((png_structp)); +typedef void (PNGAPI *png_read_status_ptr) PNGARG((png_structp, png_uint_32, + int)); +typedef void (PNGAPI *png_write_status_ptr) PNGARG((png_structp, png_uint_32, + int)); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +typedef void (PNGAPI *png_progressive_info_ptr) PNGARG((png_structp, + png_infop)); +typedef void (PNGAPI *png_progressive_end_ptr) PNGARG((png_structp, png_infop)); +typedef void (PNGAPI *png_progressive_row_ptr) PNGARG((png_structp, png_bytep, + png_uint_32, int)); +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +typedef void (PNGAPI *png_user_transform_ptr) PNGARG((png_structp, + png_row_infop, png_bytep)); +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +typedef int (PNGAPI *png_user_chunk_ptr) PNGARG((png_structp, + png_unknown_chunkp)); +#endif +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED +typedef void (PNGAPI *png_unknown_chunk_ptr) PNGARG((png_structp)); +#endif +#ifdef PNG_SETJMP_SUPPORTED +/* This must match the function definition in , and the + * application must include this before png.h to obtain the definition + * of jmp_buf. + */ +typedef void (PNGAPI *png_longjmp_ptr) PNGARG((jmp_buf, int)); +#endif + +/* Transform masks for the high-level interface */ +#define PNG_TRANSFORM_IDENTITY 0x0000 /* read and write */ +#define PNG_TRANSFORM_STRIP_16 0x0001 /* read only */ +#define PNG_TRANSFORM_STRIP_ALPHA 0x0002 /* read only */ +#define PNG_TRANSFORM_PACKING 0x0004 /* read and write */ +#define PNG_TRANSFORM_PACKSWAP 0x0008 /* read and write */ +#define PNG_TRANSFORM_EXPAND 0x0010 /* read only */ +#define PNG_TRANSFORM_INVERT_MONO 0x0020 /* read and write */ +#define PNG_TRANSFORM_SHIFT 0x0040 /* read and write */ +#define PNG_TRANSFORM_BGR 0x0080 /* read and write */ +#define PNG_TRANSFORM_SWAP_ALPHA 0x0100 /* read and write */ +#define PNG_TRANSFORM_SWAP_ENDIAN 0x0200 /* read and write */ +#define PNG_TRANSFORM_INVERT_ALPHA 0x0400 /* read and write */ +#define PNG_TRANSFORM_STRIP_FILLER 0x0800 /* write only */ +/* Added to libpng-1.2.34 */ +#define PNG_TRANSFORM_STRIP_FILLER_BEFORE PNG_TRANSFORM_STRIP_FILLER +#define PNG_TRANSFORM_STRIP_FILLER_AFTER 0x1000 /* write only */ +/* Added to libpng-1.4.0 */ +#define PNG_TRANSFORM_GRAY_TO_RGB 0x2000 /* read only */ + +/* Flags for MNG supported features */ +#define PNG_FLAG_MNG_EMPTY_PLTE 0x01 +#define PNG_FLAG_MNG_FILTER_64 0x04 +#define PNG_ALL_MNG_FEATURES 0x05 + +typedef png_voidp (*png_malloc_ptr) PNGARG((png_structp, png_alloc_size_t)); +typedef void (*png_free_ptr) PNGARG((png_structp, png_voidp)); + +/* The structure that holds the information to read and write PNG files. + * The only people who need to care about what is inside of this are the + * people who will be modifying the library for their own special needs. + * It should NOT be accessed directly by an application, except to store + * the jmp_buf. + */ + +struct png_struct_def +{ +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf jmpbuf PNG_DEPSTRUCT; /* used in png_error */ + png_longjmp_ptr longjmp_fn PNG_DEPSTRUCT;/* setjmp non-local goto + function. */ +#endif + png_error_ptr error_fn PNG_DEPSTRUCT; /* function for printing + errors and aborting */ + png_error_ptr warning_fn PNG_DEPSTRUCT; /* function for printing + warnings */ + png_voidp error_ptr PNG_DEPSTRUCT; /* user supplied struct for + error functions */ + png_rw_ptr write_data_fn PNG_DEPSTRUCT; /* function for writing + output data */ + png_rw_ptr read_data_fn PNG_DEPSTRUCT; /* function for reading + input data */ + png_voidp io_ptr PNG_DEPSTRUCT; /* ptr to application struct + for I/O functions */ + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + png_user_transform_ptr read_user_transform_fn PNG_DEPSTRUCT; /* user read + transform */ +#endif + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED + png_user_transform_ptr write_user_transform_fn PNG_DEPSTRUCT; /* user write + transform */ +#endif + +/* These were added in libpng-1.0.2 */ +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) + png_voidp user_transform_ptr PNG_DEPSTRUCT; /* user supplied struct + for user transform */ + png_byte user_transform_depth PNG_DEPSTRUCT; /* bit depth of user + transformed pixels */ + png_byte user_transform_channels PNG_DEPSTRUCT; /* channels in user + transformed pixels */ +#endif +#endif + + png_uint_32 mode PNG_DEPSTRUCT; /* tells us where we are in + the PNG file */ + png_uint_32 flags PNG_DEPSTRUCT; /* flags indicating various + things to libpng */ + png_uint_32 transformations PNG_DEPSTRUCT; /* which transformations + to perform */ + + z_stream zstream PNG_DEPSTRUCT; /* pointer to decompression + structure (below) */ + png_bytep zbuf PNG_DEPSTRUCT; /* buffer for zlib */ + png_size_t zbuf_size PNG_DEPSTRUCT; /* size of zbuf */ + int zlib_level PNG_DEPSTRUCT; /* holds zlib compression level */ + int zlib_method PNG_DEPSTRUCT; /* holds zlib compression method */ + int zlib_window_bits PNG_DEPSTRUCT; /* holds zlib compression window + bits */ + int zlib_mem_level PNG_DEPSTRUCT; /* holds zlib compression memory + level */ + int zlib_strategy PNG_DEPSTRUCT; /* holds zlib compression + strategy */ + + png_uint_32 width PNG_DEPSTRUCT; /* width of image in pixels */ + png_uint_32 height PNG_DEPSTRUCT; /* height of image in pixels */ + png_uint_32 num_rows PNG_DEPSTRUCT; /* number of rows in current pass */ + png_uint_32 usr_width PNG_DEPSTRUCT; /* width of row at start of write */ + png_size_t rowbytes PNG_DEPSTRUCT; /* size of row in bytes */ +#if 0 /* Replaced with the following in libpng-1.4.1 */ + png_size_t irowbytes PNG_DEPSTRUCT; +#endif +/* Added in libpng-1.4.1 */ +#ifdef PNG_USER_LIMITS_SUPPORTED + /* Total memory that a zTXt, sPLT, iTXt, iCCP, or unknown chunk + * can occupy when decompressed. 0 means unlimited. + * We will change the typedef from png_size_t to png_alloc_size_t + * in libpng-1.6.0 + */ + png_alloc_size_t user_chunk_malloc_max PNG_DEPSTRUCT; +#endif + png_uint_32 iwidth PNG_DEPSTRUCT; /* width of current interlaced + row in pixels */ + png_uint_32 row_number PNG_DEPSTRUCT; /* current row in interlace pass */ + png_bytep prev_row PNG_DEPSTRUCT; /* buffer to save previous + (unfiltered) row */ + png_bytep row_buf PNG_DEPSTRUCT; /* buffer to save current + (unfiltered) row */ + png_bytep sub_row PNG_DEPSTRUCT; /* buffer to save "sub" row + when filtering */ + png_bytep up_row PNG_DEPSTRUCT; /* buffer to save "up" row + when filtering */ + png_bytep avg_row PNG_DEPSTRUCT; /* buffer to save "avg" row + when filtering */ + png_bytep paeth_row PNG_DEPSTRUCT; /* buffer to save "Paeth" row + when filtering */ + png_row_info row_info PNG_DEPSTRUCT; /* used for transformation + routines */ + + png_uint_32 idat_size PNG_DEPSTRUCT; /* current IDAT size for read */ + png_uint_32 crc PNG_DEPSTRUCT; /* current chunk CRC value */ + png_colorp palette PNG_DEPSTRUCT; /* palette from the input file */ + png_uint_16 num_palette PNG_DEPSTRUCT; /* number of color entries in + palette */ + png_uint_16 num_trans PNG_DEPSTRUCT; /* number of transparency values */ + png_byte chunk_name[5] PNG_DEPSTRUCT; /* null-terminated name of current + chunk */ + png_byte compression PNG_DEPSTRUCT; /* file compression type + (always 0) */ + png_byte filter PNG_DEPSTRUCT; /* file filter type (always 0) */ + png_byte interlaced PNG_DEPSTRUCT; /* PNG_INTERLACE_NONE, + PNG_INTERLACE_ADAM7 */ + png_byte pass PNG_DEPSTRUCT; /* current interlace pass (0 - 6) */ + png_byte do_filter PNG_DEPSTRUCT; /* row filter flags (see + PNG_FILTER_ below ) */ + png_byte color_type PNG_DEPSTRUCT; /* color type of file */ + png_byte bit_depth PNG_DEPSTRUCT; /* bit depth of file */ + png_byte usr_bit_depth PNG_DEPSTRUCT; /* bit depth of users row */ + png_byte pixel_depth PNG_DEPSTRUCT; /* number of bits per pixel */ + png_byte channels PNG_DEPSTRUCT; /* number of channels in file */ + png_byte usr_channels PNG_DEPSTRUCT; /* channels at start of write */ + png_byte sig_bytes PNG_DEPSTRUCT; /* magic bytes read/written from + start of file */ + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) + png_uint_16 filler PNG_DEPSTRUCT; /* filler bytes for pixel + expansion */ +#endif + +#ifdef PNG_bKGD_SUPPORTED + png_byte background_gamma_type PNG_DEPSTRUCT; +# ifdef PNG_FLOATING_POINT_SUPPORTED + float background_gamma PNG_DEPSTRUCT; +# endif + png_color_16 background PNG_DEPSTRUCT; /* background color in + screen gamma space */ +#ifdef PNG_READ_GAMMA_SUPPORTED + png_color_16 background_1 PNG_DEPSTRUCT; /* background normalized + to gamma 1.0 */ +#endif +#endif /* PNG_bKGD_SUPPORTED */ + +#ifdef PNG_WRITE_FLUSH_SUPPORTED + png_flush_ptr output_flush_fn PNG_DEPSTRUCT; /* Function for flushing + output */ + png_uint_32 flush_dist PNG_DEPSTRUCT; /* how many rows apart to flush, + 0 - no flush */ + png_uint_32 flush_rows PNG_DEPSTRUCT; /* number of rows written since + last flush */ +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + int gamma_shift PNG_DEPSTRUCT; /* number of "insignificant" bits + 16-bit gamma */ +#ifdef PNG_FLOATING_POINT_SUPPORTED + float gamma PNG_DEPSTRUCT; /* file gamma value */ + float screen_gamma PNG_DEPSTRUCT; /* screen gamma value + (display_exponent) */ +#endif +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + png_bytep gamma_table PNG_DEPSTRUCT; /* gamma table for 8-bit + depth files */ + png_bytep gamma_from_1 PNG_DEPSTRUCT; /* converts from 1.0 to screen */ + png_bytep gamma_to_1 PNG_DEPSTRUCT; /* converts from file to 1.0 */ + png_uint_16pp gamma_16_table PNG_DEPSTRUCT; /* gamma table for 16-bit + depth files */ + png_uint_16pp gamma_16_from_1 PNG_DEPSTRUCT; /* converts from 1.0 to + screen */ + png_uint_16pp gamma_16_to_1 PNG_DEPSTRUCT; /* converts from file to 1.0 */ +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_sBIT_SUPPORTED) + png_color_8 sig_bit PNG_DEPSTRUCT; /* significant bits in each + available channel */ +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) + png_color_8 shift PNG_DEPSTRUCT; /* shift for significant bit + tranformation */ +#endif + +#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) \ + || defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + png_bytep trans_alpha PNG_DEPSTRUCT; /* alpha values for + paletted files */ + png_color_16 trans_color PNG_DEPSTRUCT; /* transparent color for + non-paletted files */ +#endif + + png_read_status_ptr read_row_fn PNG_DEPSTRUCT; /* called after each + row is decoded */ + png_write_status_ptr write_row_fn PNG_DEPSTRUCT; /* called after each + row is encoded */ +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED + png_progressive_info_ptr info_fn PNG_DEPSTRUCT; /* called after header + data fully read */ + png_progressive_row_ptr row_fn PNG_DEPSTRUCT; /* called after each + prog. row is decoded */ + png_progressive_end_ptr end_fn PNG_DEPSTRUCT; /* called after image + is complete */ + png_bytep save_buffer_ptr PNG_DEPSTRUCT; /* current location in + save_buffer */ + png_bytep save_buffer PNG_DEPSTRUCT; /* buffer for previously + read data */ + png_bytep current_buffer_ptr PNG_DEPSTRUCT; /* current location in + current_buffer */ + png_bytep current_buffer PNG_DEPSTRUCT; /* buffer for recently + used data */ + png_uint_32 push_length PNG_DEPSTRUCT; /* size of current input + chunk */ + png_uint_32 skip_length PNG_DEPSTRUCT; /* bytes to skip in + input data */ + png_size_t save_buffer_size PNG_DEPSTRUCT; /* amount of data now + in save_buffer */ + png_size_t save_buffer_max PNG_DEPSTRUCT; /* total size of + save_buffer */ + png_size_t buffer_size PNG_DEPSTRUCT; /* total amount of + available input data */ + png_size_t current_buffer_size PNG_DEPSTRUCT; /* amount of data now + in current_buffer */ + int process_mode PNG_DEPSTRUCT; /* what push library + is currently doing */ + int cur_palette PNG_DEPSTRUCT; /* current push library + palette index */ + +# ifdef PNG_TEXT_SUPPORTED + png_size_t current_text_size PNG_DEPSTRUCT; /* current size of + text input data */ + png_size_t current_text_left PNG_DEPSTRUCT; /* how much text left + to read in input */ + png_charp current_text PNG_DEPSTRUCT; /* current text chunk + buffer */ + png_charp current_text_ptr PNG_DEPSTRUCT; /* current location + in current_text */ +# endif /* PNG_PROGRESSIVE_READ_SUPPORTED && PNG_TEXT_SUPPORTED */ + +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + +#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__) +/* For the Borland special 64K segment handler */ + png_bytepp offset_table_ptr PNG_DEPSTRUCT; + png_bytep offset_table PNG_DEPSTRUCT; + png_uint_16 offset_table_number PNG_DEPSTRUCT; + png_uint_16 offset_table_count PNG_DEPSTRUCT; + png_uint_16 offset_table_count_free PNG_DEPSTRUCT; +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED + png_bytep palette_lookup PNG_DEPSTRUCT; /* lookup table for quantizing */ + png_bytep quantize_index PNG_DEPSTRUCT; /* index translation for palette + files */ +#endif + +#if defined(PNG_READ_QUANTIZE_SUPPORTED) || defined(PNG_hIST_SUPPORTED) + png_uint_16p hist PNG_DEPSTRUCT; /* histogram */ +#endif + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + png_byte heuristic_method PNG_DEPSTRUCT; /* heuristic for row + filter selection */ + png_byte num_prev_filters PNG_DEPSTRUCT; /* number of weights + for previous rows */ + png_bytep prev_filters PNG_DEPSTRUCT; /* filter type(s) of + previous row(s) */ + png_uint_16p filter_weights PNG_DEPSTRUCT; /* weight(s) for previous + line(s) */ + png_uint_16p inv_filter_weights PNG_DEPSTRUCT; /* 1/weight(s) for + previous line(s) */ + png_uint_16p filter_costs PNG_DEPSTRUCT; /* relative filter + calculation cost */ + png_uint_16p inv_filter_costs PNG_DEPSTRUCT; /* 1/relative filter + calculation cost */ +#endif + +#ifdef PNG_TIME_RFC1123_SUPPORTED + png_charp time_buffer PNG_DEPSTRUCT; /* String to hold RFC 1123 time text */ +#endif + +/* New members added in libpng-1.0.6 */ + + png_uint_32 free_me PNG_DEPSTRUCT; /* flags items libpng is + responsible for freeing */ + +#ifdef PNG_USER_CHUNKS_SUPPORTED + png_voidp user_chunk_ptr PNG_DEPSTRUCT; + png_user_chunk_ptr read_user_chunk_fn PNG_DEPSTRUCT; /* user read + chunk handler */ +#endif + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + int num_chunk_list PNG_DEPSTRUCT; + png_bytep chunk_list PNG_DEPSTRUCT; +#endif + +/* New members added in libpng-1.0.3 */ +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + png_byte rgb_to_gray_status PNG_DEPSTRUCT; + /* These were changed from png_byte in libpng-1.0.6 */ + png_uint_16 rgb_to_gray_red_coeff PNG_DEPSTRUCT; + png_uint_16 rgb_to_gray_green_coeff PNG_DEPSTRUCT; + png_uint_16 rgb_to_gray_blue_coeff PNG_DEPSTRUCT; +#endif + +/* New member added in libpng-1.0.4 (renamed in 1.0.9) */ +#if defined(PNG_MNG_FEATURES_SUPPORTED) || \ + defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \ + defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) +/* Changed from png_byte to png_uint_32 at version 1.2.0 */ + png_uint_32 mng_features_permitted PNG_DEPSTRUCT; +#endif + +/* New member added in libpng-1.0.7 */ +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + png_fixed_point int_gamma PNG_DEPSTRUCT; +#endif + +/* New member added in libpng-1.0.9, ifdef'ed out in 1.0.12, enabled in 1.2.0 */ +#ifdef PNG_MNG_FEATURES_SUPPORTED + png_byte filter_type PNG_DEPSTRUCT; +#endif + +/* New members added in libpng-1.2.0 */ + +/* New members added in libpng-1.0.2 but first enabled by default in 1.2.0 */ +#ifdef PNG_USER_MEM_SUPPORTED + png_voidp mem_ptr PNG_DEPSTRUCT; /* user supplied struct for + mem functions */ + png_malloc_ptr malloc_fn PNG_DEPSTRUCT; /* function for + allocating memory */ + png_free_ptr free_fn PNG_DEPSTRUCT; /* function for + freeing memory */ +#endif + +/* New member added in libpng-1.0.13 and 1.2.0 */ + png_bytep big_row_buf PNG_DEPSTRUCT; /* buffer to save current + (unfiltered) row */ + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +/* The following three members were added at version 1.0.14 and 1.2.4 */ + png_bytep quantize_sort PNG_DEPSTRUCT; /* working sort array */ + png_bytep index_to_palette PNG_DEPSTRUCT; /* where the original + index currently is + in the palette */ + png_bytep palette_to_index PNG_DEPSTRUCT; /* which original index + points to this + palette color */ +#endif + +/* New members added in libpng-1.0.16 and 1.2.6 */ + png_byte compression_type PNG_DEPSTRUCT; + +#ifdef PNG_USER_LIMITS_SUPPORTED + png_uint_32 user_width_max PNG_DEPSTRUCT; + png_uint_32 user_height_max PNG_DEPSTRUCT; + /* Added in libpng-1.4.0: Total number of sPLT, text, and unknown + * chunks that can be stored (0 means unlimited). + */ + png_uint_32 user_chunk_cache_max PNG_DEPSTRUCT; +#endif + +/* New member added in libpng-1.0.25 and 1.2.17 */ +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED + /* Storage for unknown chunk that the library doesn't recognize. */ + png_unknown_chunk unknown_chunk PNG_DEPSTRUCT; +#endif + +/* New members added in libpng-1.2.26 */ + png_uint_32 old_big_row_buf_size PNG_DEPSTRUCT; + png_uint_32 old_prev_row_size PNG_DEPSTRUCT; + +/* New member added in libpng-1.2.30 */ + png_charp chunkdata PNG_DEPSTRUCT; /* buffer for reading chunk data */ + +#ifdef PNG_IO_STATE_SUPPORTED +/* New member added in libpng-1.4.0 */ + png_uint_32 io_state PNG_DEPSTRUCT; +#endif +}; + + +/* This triggers a compiler error in png.c, if png.c and png.h + * do not agree upon the version number. + */ +typedef png_structp version_1_4_3; + +typedef png_struct FAR * FAR * png_structpp; + +/* Here are the function definitions most commonly used. This is not + * the place to find out how to use libpng. See libpng.txt for the + * full explanation, see example.c for the summary. This just provides + * a simple one line description of the use of each function. + */ + +/* Returns the version number of the library */ +extern PNG_EXPORT(png_uint_32,png_access_version_number) PNGARG((void)); + +/* Tell lib we have already handled the first magic bytes. + * Handling more than 8 bytes from the beginning of the file is an error. + */ +extern PNG_EXPORT(void,png_set_sig_bytes) PNGARG((png_structp png_ptr, + int num_bytes)); + +/* Check sig[start] through sig[start + num_to_check - 1] to see if it's a + * PNG file. Returns zero if the supplied bytes match the 8-byte PNG + * signature, and non-zero otherwise. Having num_to_check == 0 or + * start > 7 will always fail (ie return non-zero). + */ +extern PNG_EXPORT(int,png_sig_cmp) PNGARG((png_bytep sig, png_size_t start, + png_size_t num_to_check)); + +/* Simple signature checking function. This is the same as calling + * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n). + */ +#define png_check_sig(sig,n) !png_sig_cmp((sig), 0, (n)) + +/* Allocate and initialize png_ptr struct for reading, and any other memory. */ +extern PNG_EXPORT(png_structp,png_create_read_struct) + PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn)) PNG_ALLOCATED; + +/* Allocate and initialize png_ptr struct for writing, and any other memory */ +extern PNG_EXPORT(png_structp,png_create_write_struct) + PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn)) PNG_ALLOCATED; + +extern PNG_EXPORT(png_size_t,png_get_compression_buffer_size) + PNGARG((png_structp png_ptr)); + +extern PNG_EXPORT(void,png_set_compression_buffer_size) + PNGARG((png_structp png_ptr, png_size_t size)); + +/* Moved from pngconf.h in 1.4.0 and modified to ensure setjmp/longjmp + * match up. + */ +#ifdef PNG_SETJMP_SUPPORTED +/* This function returns the jmp_buf built in to *png_ptr. It must be + * supplied with an appropriate 'longjmp' function to use on that jmp_buf + * unless the default error function is overridden in which case NULL is + * acceptable. The size of the jmp_buf is checked against the actual size + * allocated by the library - the call will return NULL on a mismatch + * indicating an ABI mismatch. + */ +extern PNG_EXPORT(jmp_buf*, png_set_longjmp_fn) + PNGARG((png_structp png_ptr, png_longjmp_ptr longjmp_fn, size_t + jmp_buf_size)); +# define png_jmpbuf(png_ptr) \ + (*png_set_longjmp_fn((png_ptr), longjmp, sizeof (jmp_buf))) +#else +# define png_jmpbuf(png_ptr) \ + (LIBPNG_WAS_COMPILED_WITH__PNG_NO_SETJMP) +#endif + +#ifdef PNG_READ_SUPPORTED +/* Reset the compression stream */ +extern PNG_EXPORT(int,png_reset_zstream) PNGARG((png_structp png_ptr)); +#endif + +/* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */ +#ifdef PNG_USER_MEM_SUPPORTED +extern PNG_EXPORT(png_structp,png_create_read_struct_2) + PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn)) PNG_ALLOCATED; +extern PNG_EXPORT(png_structp,png_create_write_struct_2) + PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn)) PNG_ALLOCATED; +#endif + +/* Write the PNG file signature. */ +extern PNG_EXPORT(void,png_write_sig) PNGARG((png_structp png_ptr)); + +/* Write a PNG chunk - size, type, (optional) data, CRC. */ +extern PNG_EXPORT(void,png_write_chunk) PNGARG((png_structp png_ptr, + png_bytep chunk_name, png_bytep data, png_size_t length)); + +/* Write the start of a PNG chunk - length and chunk name. */ +extern PNG_EXPORT(void,png_write_chunk_start) PNGARG((png_structp png_ptr, + png_bytep chunk_name, png_uint_32 length)); + +/* Write the data of a PNG chunk started with png_write_chunk_start(). */ +extern PNG_EXPORT(void,png_write_chunk_data) PNGARG((png_structp png_ptr, + png_bytep data, png_size_t length)); + +/* Finish a chunk started with png_write_chunk_start() (includes CRC). */ +extern PNG_EXPORT(void,png_write_chunk_end) PNGARG((png_structp png_ptr)); + +/* Allocate and initialize the info structure */ +extern PNG_EXPORT(png_infop,png_create_info_struct) + PNGARG((png_structp png_ptr)) PNG_ALLOCATED; + +extern PNG_EXPORT(void,png_info_init_3) PNGARG((png_infopp info_ptr, + png_size_t png_info_struct_size)); + +/* Writes all the PNG information before the image. */ +extern PNG_EXPORT(void,png_write_info_before_PLTE) PNGARG((png_structp png_ptr, + png_infop info_ptr)); +extern PNG_EXPORT(void,png_write_info) PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the information before the actual image data. */ +extern PNG_EXPORT(void,png_read_info) PNGARG((png_structp png_ptr, + png_infop info_ptr)); +#endif + +#ifdef PNG_TIME_RFC1123_SUPPORTED +extern PNG_EXPORT(png_charp,png_convert_to_rfc1123) + PNGARG((png_structp png_ptr, png_timep ptime)); +#endif + +#ifdef PNG_CONVERT_tIME_SUPPORTED +/* Convert from a struct tm to png_time */ +extern PNG_EXPORT(void,png_convert_from_struct_tm) PNGARG((png_timep ptime, + struct tm FAR * ttime)); + +/* Convert from time_t to png_time. Uses gmtime() */ +extern PNG_EXPORT(void,png_convert_from_time_t) PNGARG((png_timep ptime, + time_t ttime)); +#endif /* PNG_CONVERT_tIME_SUPPORTED */ + +#ifdef PNG_READ_EXPAND_SUPPORTED +/* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */ +extern PNG_EXPORT(void,png_set_expand) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(void,png_set_expand_gray_1_2_4_to_8) PNGARG((png_structp + png_ptr)); +extern PNG_EXPORT(void,png_set_palette_to_rgb) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(void,png_set_tRNS_to_alpha) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* Use blue, green, red order for pixels. */ +extern PNG_EXPORT(void,png_set_bgr) PNGARG((png_structp png_ptr)); +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED +/* Expand the grayscale to 24-bit RGB if necessary. */ +extern PNG_EXPORT(void,png_set_gray_to_rgb) PNGARG((png_structp png_ptr)); +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +/* Reduce RGB to grayscale. */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_rgb_to_gray) PNGARG((png_structp png_ptr, + int error_action, double red, double green )); +#endif +extern PNG_EXPORT(void,png_set_rgb_to_gray_fixed) PNGARG((png_structp png_ptr, + int error_action, png_fixed_point red, png_fixed_point green )); +extern PNG_EXPORT(png_byte,png_get_rgb_to_gray_status) PNGARG((png_structp + png_ptr)); +#endif + +extern PNG_EXPORT(void,png_build_grayscale_palette) PNGARG((int bit_depth, + png_colorp palette)); + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED +extern PNG_EXPORT(void,png_set_strip_alpha) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +extern PNG_EXPORT(void,png_set_swap_alpha) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +extern PNG_EXPORT(void,png_set_invert_alpha) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) +/* Add a filler byte to 8-bit Gray or 24-bit RGB images. */ +extern PNG_EXPORT(void,png_set_filler) PNGARG((png_structp png_ptr, + png_uint_32 filler, int flags)); +/* The values of the PNG_FILLER_ defines should NOT be changed */ +#define PNG_FILLER_BEFORE 0 +#define PNG_FILLER_AFTER 1 +/* Add an alpha byte to 8-bit Gray or 24-bit RGB images. */ +extern PNG_EXPORT(void,png_set_add_alpha) PNGARG((png_structp png_ptr, + png_uint_32 filler, int flags)); +#endif /* PNG_READ_FILLER_SUPPORTED || PNG_WRITE_FILLER_SUPPORTED */ + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* Swap bytes in 16-bit depth files. */ +extern PNG_EXPORT(void,png_set_swap) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) +/* Use 1 byte per pixel in 1, 2, or 4-bit depth files. */ +extern PNG_EXPORT(void,png_set_packing) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) || \ + defined(PNG_WRITE_PACKSWAP_SUPPORTED) +/* Swap packing order of pixels in bytes. */ +extern PNG_EXPORT(void,png_set_packswap) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) +/* Converts files to legal bit depths. */ +extern PNG_EXPORT(void,png_set_shift) PNGARG((png_structp png_ptr, + png_color_8p true_bits)); +#endif + +#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ + defined(PNG_WRITE_INTERLACING_SUPPORTED) +/* Have the code handle the interlacing. Returns the number of passes. */ +extern PNG_EXPORT(int,png_set_interlace_handling) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +/* Invert monochrome files */ +extern PNG_EXPORT(void,png_set_invert_mono) PNGARG((png_structp png_ptr)); +#endif + +#ifdef PNG_READ_BACKGROUND_SUPPORTED +/* Handle alpha and tRNS by replacing with a background color. */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_background) PNGARG((png_structp png_ptr, + png_color_16p background_color, int background_gamma_code, + int need_expand, double background_gamma)); +#endif +#define PNG_BACKGROUND_GAMMA_UNKNOWN 0 +#define PNG_BACKGROUND_GAMMA_SCREEN 1 +#define PNG_BACKGROUND_GAMMA_FILE 2 +#define PNG_BACKGROUND_GAMMA_UNIQUE 3 +#endif + +#ifdef PNG_READ_16_TO_8_SUPPORTED +/* Strip the second byte of information from a 16-bit depth file. */ +extern PNG_EXPORT(void,png_set_strip_16) PNGARG((png_structp png_ptr)); +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +/* Turn on quantizing, and reduce the palette to the number of colors + * available. Prior to libpng-1.4.2, this was png_set_dither(). + */ +extern PNG_EXPORT(void,png_set_quantize) PNGARG((png_structp png_ptr, + png_colorp palette, int num_palette, int maximum_colors, + png_uint_16p histogram, int full_quantize)); +#endif +/* This migration aid will be removed from libpng-1.5.0 */ +#define png_set_dither png_set_quantize + +#ifdef PNG_READ_GAMMA_SUPPORTED +/* Handle gamma correction. Screen_gamma=(display_exponent) */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_gamma) PNGARG((png_structp png_ptr, + double screen_gamma, double default_file_gamma)); +#endif +#endif + + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +/* Set how many lines between output flushes - 0 for no flushing */ +extern PNG_EXPORT(void,png_set_flush) PNGARG((png_structp png_ptr, int nrows)); +/* Flush the current PNG output buffer */ +extern PNG_EXPORT(void,png_write_flush) PNGARG((png_structp png_ptr)); +#endif + +/* Optional update palette with requested transformations */ +extern PNG_EXPORT(void,png_start_read_image) PNGARG((png_structp png_ptr)); + +/* Optional call to update the users info structure */ +extern PNG_EXPORT(void,png_read_update_info) PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read one or more rows of image data. */ +extern PNG_EXPORT(void,png_read_rows) PNGARG((png_structp png_ptr, + png_bytepp row, png_bytepp display_row, png_uint_32 num_rows)); +#endif + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read a row of data. */ +extern PNG_EXPORT(void,png_read_row) PNGARG((png_structp png_ptr, + png_bytep row, + png_bytep display_row)); +#endif + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the whole image into memory at once. */ +extern PNG_EXPORT(void,png_read_image) PNGARG((png_structp png_ptr, + png_bytepp image)); +#endif + +/* Write a row of image data */ +extern PNG_EXPORT(void,png_write_row) PNGARG((png_structp png_ptr, + png_bytep row)); + +/* Write a few rows of image data */ +extern PNG_EXPORT(void,png_write_rows) PNGARG((png_structp png_ptr, + png_bytepp row, png_uint_32 num_rows)); + +/* Write the image data */ +extern PNG_EXPORT(void,png_write_image) PNGARG((png_structp png_ptr, + png_bytepp image)); + +/* Write the end of the PNG file. */ +extern PNG_EXPORT(void,png_write_end) PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the end of the PNG file. */ +extern PNG_EXPORT(void,png_read_end) PNGARG((png_structp png_ptr, + png_infop info_ptr)); +#endif + +/* Free any memory associated with the png_info_struct */ +extern PNG_EXPORT(void,png_destroy_info_struct) PNGARG((png_structp png_ptr, + png_infopp info_ptr_ptr)); + +/* Free any memory associated with the png_struct and the png_info_structs */ +extern PNG_EXPORT(void,png_destroy_read_struct) PNGARG((png_structpp + png_ptr_ptr, png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr)); + +/* Free any memory associated with the png_struct and the png_info_structs */ +extern PNG_EXPORT(void,png_destroy_write_struct) + PNGARG((png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)); + +/* Set the libpng method of handling chunk CRC errors */ +extern PNG_EXPORT(void,png_set_crc_action) PNGARG((png_structp png_ptr, + int crit_action, int ancil_action)); + +/* Values for png_set_crc_action() to say how to handle CRC errors in + * ancillary and critical chunks, and whether to use the data contained + * therein. Note that it is impossible to "discard" data in a critical + * chunk. For versions prior to 0.90, the action was always error/quit, + * whereas in version 0.90 and later, the action for CRC errors in ancillary + * chunks is warn/discard. These values should NOT be changed. + * + * value action:critical action:ancillary + */ +#define PNG_CRC_DEFAULT 0 /* error/quit warn/discard data */ +#define PNG_CRC_ERROR_QUIT 1 /* error/quit error/quit */ +#define PNG_CRC_WARN_DISCARD 2 /* (INVALID) warn/discard data */ +#define PNG_CRC_WARN_USE 3 /* warn/use data warn/use data */ +#define PNG_CRC_QUIET_USE 4 /* quiet/use data quiet/use data */ +#define PNG_CRC_NO_CHANGE 5 /* use current value use current value */ + +/* These functions give the user control over the scan-line filtering in + * libpng and the compression methods used by zlib. These functions are + * mainly useful for testing, as the defaults should work with most users. + * Those users who are tight on memory or want faster performance at the + * expense of compression can modify them. See the compression library + * header file (zlib.h) for an explination of the compression functions. + */ + +/* Set the filtering method(s) used by libpng. Currently, the only valid + * value for "method" is 0. + */ +extern PNG_EXPORT(void,png_set_filter) PNGARG((png_structp png_ptr, int method, + int filters)); + +/* Flags for png_set_filter() to say which filters to use. The flags + * are chosen so that they don't conflict with real filter types + * below, in case they are supplied instead of the #defined constants. + * These values should NOT be changed. + */ +#define PNG_NO_FILTERS 0x00 +#define PNG_FILTER_NONE 0x08 +#define PNG_FILTER_SUB 0x10 +#define PNG_FILTER_UP 0x20 +#define PNG_FILTER_AVG 0x40 +#define PNG_FILTER_PAETH 0x80 +#define PNG_ALL_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP | \ + PNG_FILTER_AVG | PNG_FILTER_PAETH) + +/* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now. + * These defines should NOT be changed. + */ +#define PNG_FILTER_VALUE_NONE 0 +#define PNG_FILTER_VALUE_SUB 1 +#define PNG_FILTER_VALUE_UP 2 +#define PNG_FILTER_VALUE_AVG 3 +#define PNG_FILTER_VALUE_PAETH 4 +#define PNG_FILTER_VALUE_LAST 5 + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* EXPERIMENTAL */ +/* The "heuristic_method" is given by one of the PNG_FILTER_HEURISTIC_ + * defines, either the default (minimum-sum-of-absolute-differences), or + * the experimental method (weighted-minimum-sum-of-absolute-differences). + * + * Weights are factors >= 1.0, indicating how important it is to keep the + * filter type consistent between rows. Larger numbers mean the current + * filter is that many times as likely to be the same as the "num_weights" + * previous filters. This is cumulative for each previous row with a weight. + * There needs to be "num_weights" values in "filter_weights", or it can be + * NULL if the weights aren't being specified. Weights have no influence on + * the selection of the first row filter. Well chosen weights can (in theory) + * improve the compression for a given image. + * + * Costs are factors >= 1.0 indicating the relative decoding costs of a + * filter type. Higher costs indicate more decoding expense, and are + * therefore less likely to be selected over a filter with lower computational + * costs. There needs to be a value in "filter_costs" for each valid filter + * type (given by PNG_FILTER_VALUE_LAST), or it can be NULL if you aren't + * setting the costs. Costs try to improve the speed of decompression without + * unduly increasing the compressed image size. + * + * A negative weight or cost indicates the default value is to be used, and + * values in the range [0.0, 1.0) indicate the value is to remain unchanged. + * The default values for both weights and costs are currently 1.0, but may + * change if good general weighting/cost heuristics can be found. If both + * the weights and costs are set to 1.0, this degenerates the WEIGHTED method + * to the UNWEIGHTED method, but with added encoding time/computation. + */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_filter_heuristics) PNGARG((png_structp png_ptr, + int heuristic_method, int num_weights, png_doublep filter_weights, + png_doublep filter_costs)); +#endif +#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ + +/* Heuristic used for row filter selection. These defines should NOT be + * changed. + */ +#define PNG_FILTER_HEURISTIC_DEFAULT 0 /* Currently "UNWEIGHTED" */ +#define PNG_FILTER_HEURISTIC_UNWEIGHTED 1 /* Used by libpng < 0.95 */ +#define PNG_FILTER_HEURISTIC_WEIGHTED 2 /* Experimental feature */ +#define PNG_FILTER_HEURISTIC_LAST 3 /* Not a valid value */ + +/* Set the library compression level. Currently, valid values range from + * 0 - 9, corresponding directly to the zlib compression levels 0 - 9 + * (0 - no compression, 9 - "maximal" compression). Note that tests have + * shown that zlib compression levels 3-6 usually perform as well as level 9 + * for PNG images, and do considerably fewer caclulations. In the future, + * these values may not correspond directly to the zlib compression levels. + */ +extern PNG_EXPORT(void,png_set_compression_level) PNGARG((png_structp png_ptr, + int level)); + +extern PNG_EXPORT(void,png_set_compression_mem_level) + PNGARG((png_structp png_ptr, int mem_level)); + +extern PNG_EXPORT(void,png_set_compression_strategy) + PNGARG((png_structp png_ptr, int strategy)); + +extern PNG_EXPORT(void,png_set_compression_window_bits) + PNGARG((png_structp png_ptr, int window_bits)); + +extern PNG_EXPORT(void,png_set_compression_method) PNGARG((png_structp png_ptr, + int method)); + +/* These next functions are called for input/output, memory, and error + * handling. They are in the file pngrio.c, pngwio.c, and pngerror.c, + * and call standard C I/O routines such as fread(), fwrite(), and + * fprintf(). These functions can be made to use other I/O routines + * at run time for those applications that need to handle I/O in a + * different manner by calling png_set_???_fn(). See libpng.txt for + * more information. + */ + +#ifdef PNG_STDIO_SUPPORTED +/* Initialize the input/output for the PNG file to the default functions. */ +extern PNG_EXPORT(void,png_init_io) PNGARG((png_structp png_ptr, + png_FILE_p fp)); +#endif + +/* Replace the (error and abort), and warning functions with user + * supplied functions. If no messages are to be printed you must still + * write and use replacement functions. The replacement error_fn should + * still do a longjmp to the last setjmp location if you are using this + * method of error handling. If error_fn or warning_fn is NULL, the + * default function will be used. + */ + +extern PNG_EXPORT(void,png_set_error_fn) PNGARG((png_structp png_ptr, + png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn)); + +/* Return the user pointer associated with the error functions */ +extern PNG_EXPORT(png_voidp,png_get_error_ptr) PNGARG((png_structp png_ptr)); + +/* Replace the default data output functions with a user supplied one(s). + * If buffered output is not used, then output_flush_fn can be set to NULL. + * If PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile time + * output_flush_fn will be ignored (and thus can be NULL). + * It is probably a mistake to use NULL for output_flush_fn if + * write_data_fn is not also NULL unless you have built libpng with + * PNG_WRITE_FLUSH_SUPPORTED undefined, because in this case libpng's + * default flush function, which uses the standard *FILE structure, will + * be used. + */ +extern PNG_EXPORT(void,png_set_write_fn) PNGARG((png_structp png_ptr, + png_voidp io_ptr, png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)); + +/* Replace the default data input function with a user supplied one. */ +extern PNG_EXPORT(void,png_set_read_fn) PNGARG((png_structp png_ptr, + png_voidp io_ptr, png_rw_ptr read_data_fn)); + +/* Return the user pointer associated with the I/O functions */ +extern PNG_EXPORT(png_voidp,png_get_io_ptr) PNGARG((png_structp png_ptr)); + +extern PNG_EXPORT(void,png_set_read_status_fn) PNGARG((png_structp png_ptr, + png_read_status_ptr read_row_fn)); + +extern PNG_EXPORT(void,png_set_write_status_fn) PNGARG((png_structp png_ptr, + png_write_status_ptr write_row_fn)); + +#ifdef PNG_USER_MEM_SUPPORTED +/* Replace the default memory allocation functions with user supplied one(s). */ +extern PNG_EXPORT(void,png_set_mem_fn) PNGARG((png_structp png_ptr, + png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn)); +/* Return the user pointer associated with the memory functions */ +extern PNG_EXPORT(png_voidp,png_get_mem_ptr) PNGARG((png_structp png_ptr)); +#endif + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED +extern PNG_EXPORT(void,png_set_read_user_transform_fn) PNGARG((png_structp + png_ptr, png_user_transform_ptr read_user_transform_fn)); +#endif + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED +extern PNG_EXPORT(void,png_set_write_user_transform_fn) PNGARG((png_structp + png_ptr, png_user_transform_ptr write_user_transform_fn)); +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +extern PNG_EXPORT(void,png_set_user_transform_info) PNGARG((png_structp + png_ptr, png_voidp user_transform_ptr, int user_transform_depth, + int user_transform_channels)); +/* Return the user pointer associated with the user transform functions */ +extern PNG_EXPORT(png_voidp,png_get_user_transform_ptr) + PNGARG((png_structp png_ptr)); +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +extern PNG_EXPORT(void,png_set_read_user_chunk_fn) PNGARG((png_structp png_ptr, + png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn)); +extern PNG_EXPORT(png_voidp,png_get_user_chunk_ptr) PNGARG((png_structp + png_ptr)); +#endif + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +/* Sets the function callbacks for the push reader, and a pointer to a + * user-defined structure available to the callback functions. + */ +extern PNG_EXPORT(void,png_set_progressive_read_fn) PNGARG((png_structp png_ptr, + png_voidp progressive_ptr, + png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn, + png_progressive_end_ptr end_fn)); + +/* Returns the user pointer associated with the push read functions */ +extern PNG_EXPORT(png_voidp,png_get_progressive_ptr) + PNGARG((png_structp png_ptr)); + +/* Function to be called when data becomes available */ +extern PNG_EXPORT(void,png_process_data) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_bytep buffer, png_size_t buffer_size)); + +/* Function that combines rows. Not very much different than the + * png_combine_row() call. Is this even used????? + */ +extern PNG_EXPORT(void,png_progressive_combine_row) PNGARG((png_structp png_ptr, + png_bytep old_row, png_bytep new_row)); +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + +extern PNG_EXPORT(png_voidp,png_malloc) PNGARG((png_structp png_ptr, + png_alloc_size_t size)) PNG_ALLOCATED; +/* Added at libpng version 1.4.0 */ +extern PNG_EXPORT(png_voidp,png_calloc) PNGARG((png_structp png_ptr, + png_alloc_size_t size)) PNG_ALLOCATED; + +/* Added at libpng version 1.2.4 */ +extern PNG_EXPORT(png_voidp,png_malloc_warn) PNGARG((png_structp png_ptr, + png_alloc_size_t size)) PNG_ALLOCATED; + +/* Frees a pointer allocated by png_malloc() */ +extern PNG_EXPORT(void,png_free) PNGARG((png_structp png_ptr, png_voidp ptr)); + +/* Free data that was allocated internally */ +extern PNG_EXPORT(void,png_free_data) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 free_me, int num)); +/* Reassign responsibility for freeing existing data, whether allocated + * by libpng or by the application */ +extern PNG_EXPORT(void,png_data_freer) PNGARG((png_structp png_ptr, + png_infop info_ptr, int freer, png_uint_32 mask)); +/* Assignments for png_data_freer */ +#define PNG_DESTROY_WILL_FREE_DATA 1 +#define PNG_SET_WILL_FREE_DATA 1 +#define PNG_USER_WILL_FREE_DATA 2 +/* Flags for png_ptr->free_me and info_ptr->free_me */ +#define PNG_FREE_HIST 0x0008 +#define PNG_FREE_ICCP 0x0010 +#define PNG_FREE_SPLT 0x0020 +#define PNG_FREE_ROWS 0x0040 +#define PNG_FREE_PCAL 0x0080 +#define PNG_FREE_SCAL 0x0100 +#define PNG_FREE_UNKN 0x0200 +#define PNG_FREE_LIST 0x0400 +#define PNG_FREE_PLTE 0x1000 +#define PNG_FREE_TRNS 0x2000 +#define PNG_FREE_TEXT 0x4000 +#define PNG_FREE_ALL 0x7fff +#define PNG_FREE_MUL 0x4220 /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */ + +#ifdef PNG_USER_MEM_SUPPORTED +extern PNG_EXPORT(png_voidp,png_malloc_default) PNGARG((png_structp png_ptr, + png_alloc_size_t size)) PNG_ALLOCATED; +extern PNG_EXPORT(void,png_free_default) PNGARG((png_structp png_ptr, + png_voidp ptr)); +#endif + +#ifndef PNG_NO_ERROR_TEXT +/* Fatal error in PNG image of libpng - can't continue */ +extern PNG_EXPORT(void,png_error) PNGARG((png_structp png_ptr, + png_const_charp error_message)) PNG_NORETURN; + +/* The same, but the chunk name is prepended to the error string. */ +extern PNG_EXPORT(void,png_chunk_error) PNGARG((png_structp png_ptr, + png_const_charp error_message)) PNG_NORETURN; + +#else +/* Fatal error in PNG image of libpng - can't continue */ +extern PNG_EXPORT(void,png_err) PNGARG((png_structp png_ptr)) PNG_NORETURN; +#endif + +/* Non-fatal error in libpng. Can continue, but may have a problem. */ +extern PNG_EXPORT(void,png_warning) PNGARG((png_structp png_ptr, + png_const_charp warning_message)); + +/* Non-fatal error in libpng, chunk name is prepended to message. */ +extern PNG_EXPORT(void,png_chunk_warning) PNGARG((png_structp png_ptr, + png_const_charp warning_message)); + +#ifdef PNG_BENIGN_ERRORS_SUPPORTED +/* Benign error in libpng. Can continue, but may have a problem. + * User can choose whether to handle as a fatal error or as a warning. */ +extern PNG_EXPORT(void,png_benign_error) PNGARG((png_structp png_ptr, + png_const_charp warning_message)); + +/* Same, chunk name is prepended to message. */ +extern PNG_EXPORT(void,png_chunk_benign_error) PNGARG((png_structp png_ptr, + png_const_charp warning_message)); + +extern PNG_EXPORT(void,png_set_benign_errors) PNGARG((png_structp + png_ptr, int allowed)); +#endif + +/* The png_set_ functions are for storing values in the png_info_struct. + * Similarly, the png_get_ calls are used to read values from the + * png_info_struct, either storing the parameters in the passed variables, or + * setting pointers into the png_info_struct where the data is stored. The + * png_get_ functions return a non-zero value if the data was available + * in info_ptr, or return zero and do not change any of the parameters if the + * data was not available. + * + * These functions should be used instead of directly accessing png_info + * to avoid problems with future changes in the size and internal layout of + * png_info_struct. + */ +/* Returns "flag" if chunk data is valid in info_ptr. */ +extern PNG_EXPORT(png_uint_32,png_get_valid) PNGARG((png_structp png_ptr, +png_infop info_ptr, png_uint_32 flag)); + +/* Returns number of bytes needed to hold a transformed row. */ +extern PNG_EXPORT(png_size_t,png_get_rowbytes) PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +#ifdef PNG_INFO_IMAGE_SUPPORTED +/* Returns row_pointers, which is an array of pointers to scanlines that was + * returned from png_read_png(). + */ +extern PNG_EXPORT(png_bytepp,png_get_rows) PNGARG((png_structp png_ptr, +png_infop info_ptr)); +/* Set row_pointers, which is an array of pointers to scanlines for use + * by png_write_png(). + */ +extern PNG_EXPORT(void,png_set_rows) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_bytepp row_pointers)); +#endif + +/* Returns number of color channels in image. */ +extern PNG_EXPORT(png_byte,png_get_channels) PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +#ifdef PNG_EASY_ACCESS_SUPPORTED +/* Returns image width in pixels. */ +extern PNG_EXPORT(png_uint_32, png_get_image_width) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image height in pixels. */ +extern PNG_EXPORT(png_uint_32, png_get_image_height) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image bit_depth. */ +extern PNG_EXPORT(png_byte, png_get_bit_depth) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image color_type. */ +extern PNG_EXPORT(png_byte, png_get_color_type) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image filter_type. */ +extern PNG_EXPORT(png_byte, png_get_filter_type) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image interlace_type. */ +extern PNG_EXPORT(png_byte, png_get_interlace_type) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image compression_type. */ +extern PNG_EXPORT(png_byte, png_get_compression_type) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image resolution in pixels per meter, from pHYs chunk data. */ +extern PNG_EXPORT(png_uint_32, png_get_pixels_per_meter) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_uint_32, png_get_x_pixels_per_meter) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_uint_32, png_get_y_pixels_per_meter) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns pixel aspect ratio, computed from pHYs chunk data. */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(float, png_get_pixel_aspect_ratio) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +#endif + +/* Returns image x, y offset in pixels or microns, from oFFs chunk data. */ +extern PNG_EXPORT(png_int_32, png_get_x_offset_pixels) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_int_32, png_get_y_offset_pixels) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_int_32, png_get_x_offset_microns) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_int_32, png_get_y_offset_microns) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +#endif /* PNG_EASY_ACCESS_SUPPORTED */ + +/* Returns pointer to signature string read from PNG header */ +extern PNG_EXPORT(png_bytep,png_get_signature) PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +#ifdef PNG_bKGD_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_bKGD) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_color_16p *background)); +#endif + +#ifdef PNG_bKGD_SUPPORTED +extern PNG_EXPORT(void,png_set_bKGD) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_color_16p background)); +#endif + +#ifdef PNG_cHRM_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_cHRM) PNGARG((png_structp png_ptr, + png_infop info_ptr, double *white_x, double *white_y, double *red_x, + double *red_y, double *green_x, double *green_y, double *blue_x, + double *blue_y)); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_cHRM_fixed) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_fixed_point *int_white_x, png_fixed_point + *int_white_y, png_fixed_point *int_red_x, png_fixed_point *int_red_y, + png_fixed_point *int_green_x, png_fixed_point *int_green_y, png_fixed_point + *int_blue_x, png_fixed_point *int_blue_y)); +#endif +#endif + +#ifdef PNG_cHRM_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_cHRM) PNGARG((png_structp png_ptr, + png_infop info_ptr, double white_x, double white_y, double red_x, + double red_y, double green_x, double green_y, double blue_x, double blue_y)); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_cHRM_fixed) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_fixed_point int_white_x, png_fixed_point int_white_y, + png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point + int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x, + png_fixed_point int_blue_y)); +#endif +#endif + +#ifdef PNG_gAMA_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_gAMA) PNGARG((png_structp png_ptr, + png_infop info_ptr, double *file_gamma)); +#endif +extern PNG_EXPORT(png_uint_32,png_get_gAMA_fixed) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_fixed_point *int_file_gamma)); +#endif + +#ifdef PNG_gAMA_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_gAMA) PNGARG((png_structp png_ptr, + png_infop info_ptr, double file_gamma)); +#endif +extern PNG_EXPORT(void,png_set_gAMA_fixed) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_fixed_point int_file_gamma)); +#endif + +#ifdef PNG_hIST_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_hIST) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_16p *hist)); +#endif + +#ifdef PNG_hIST_SUPPORTED +extern PNG_EXPORT(void,png_set_hIST) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_16p hist)); +#endif + +extern PNG_EXPORT(png_uint_32,png_get_IHDR) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 *width, png_uint_32 *height, + int *bit_depth, int *color_type, int *interlace_method, + int *compression_method, int *filter_method)); + +extern PNG_EXPORT(void,png_set_IHDR) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_method, int compression_method, + int filter_method)); + +#ifdef PNG_oFFs_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_oFFs) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_int_32 *offset_x, png_int_32 *offset_y, + int *unit_type)); +#endif + +#ifdef PNG_oFFs_SUPPORTED +extern PNG_EXPORT(void,png_set_oFFs) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_int_32 offset_x, png_int_32 offset_y, + int unit_type)); +#endif + +#ifdef PNG_pCAL_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_pCAL) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_charp *purpose, png_int_32 *X0, png_int_32 *X1, + int *type, int *nparams, png_charp *units, png_charpp *params)); +#endif + +#ifdef PNG_pCAL_SUPPORTED +extern PNG_EXPORT(void,png_set_pCAL) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_charp purpose, png_int_32 X0, png_int_32 X1, + int type, int nparams, png_charp units, png_charpp params)); +#endif + +#ifdef PNG_pHYs_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_pHYs) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)); +#endif + +#ifdef PNG_pHYs_SUPPORTED +extern PNG_EXPORT(void,png_set_pHYs) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 res_x, png_uint_32 res_y, int unit_type)); +#endif + +extern PNG_EXPORT(png_uint_32,png_get_PLTE) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_colorp *palette, int *num_palette)); + +extern PNG_EXPORT(void,png_set_PLTE) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_colorp palette, int num_palette)); + +#ifdef PNG_sBIT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_sBIT) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_color_8p *sig_bit)); +#endif + +#ifdef PNG_sBIT_SUPPORTED +extern PNG_EXPORT(void,png_set_sBIT) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_color_8p sig_bit)); +#endif + +#ifdef PNG_sRGB_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_sRGB) PNGARG((png_structp png_ptr, + png_infop info_ptr, int *intent)); +#endif + +#ifdef PNG_sRGB_SUPPORTED +extern PNG_EXPORT(void,png_set_sRGB) PNGARG((png_structp png_ptr, + png_infop info_ptr, int intent)); +extern PNG_EXPORT(void,png_set_sRGB_gAMA_and_cHRM) PNGARG((png_structp png_ptr, + png_infop info_ptr, int intent)); +#endif + +#ifdef PNG_iCCP_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_iCCP) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_charpp name, int *compression_type, + png_charpp profile, png_uint_32 *proflen)); + /* Note to maintainer: profile should be png_bytepp */ +#endif + +#ifdef PNG_iCCP_SUPPORTED +extern PNG_EXPORT(void,png_set_iCCP) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_charp name, int compression_type, + png_charp profile, png_uint_32 proflen)); + /* Note to maintainer: profile should be png_bytep */ +#endif + +#ifdef PNG_sPLT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_sPLT) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_sPLT_tpp entries)); +#endif + +#ifdef PNG_sPLT_SUPPORTED +extern PNG_EXPORT(void,png_set_sPLT) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_sPLT_tp entries, int nentries)); +#endif + +#ifdef PNG_TEXT_SUPPORTED +/* png_get_text also returns the number of text chunks in *num_text */ +extern PNG_EXPORT(png_uint_32,png_get_text) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_textp *text_ptr, int *num_text)); +#endif + +/* Note while png_set_text() will accept a structure whose text, + * language, and translated keywords are NULL pointers, the structure + * returned by png_get_text will always contain regular + * zero-terminated C strings. They might be empty strings but + * they will never be NULL pointers. + */ + +#ifdef PNG_TEXT_SUPPORTED +extern PNG_EXPORT(void,png_set_text) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_textp text_ptr, int num_text)); +#endif + +#ifdef PNG_tIME_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_tIME) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_timep *mod_time)); +#endif + +#ifdef PNG_tIME_SUPPORTED +extern PNG_EXPORT(void,png_set_tIME) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_timep mod_time)); +#endif + +#ifdef PNG_tRNS_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_tRNS) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_bytep *trans_alpha, int *num_trans, + png_color_16p *trans_color)); +#endif + +#ifdef PNG_tRNS_SUPPORTED +extern PNG_EXPORT(void,png_set_tRNS) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_bytep trans_alpha, int num_trans, + png_color_16p trans_color)); +#endif + +#ifdef PNG_tRNS_SUPPORTED +#endif + +#ifdef PNG_sCAL_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_sCAL) PNGARG((png_structp png_ptr, + png_infop info_ptr, int *unit, double *width, double *height)); +#else +#ifdef PNG_FIXED_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_sCAL_s) PNGARG((png_structp png_ptr, + png_infop info_ptr, int *unit, png_charpp swidth, png_charpp sheight)); +#endif +#endif +#endif /* PNG_sCAL_SUPPORTED */ + +#ifdef PNG_sCAL_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_sCAL) PNGARG((png_structp png_ptr, + png_infop info_ptr, int unit, double width, double height)); +#else +#ifdef PNG_FIXED_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_sCAL_s) PNGARG((png_structp png_ptr, + png_infop info_ptr, int unit, png_charp swidth, png_charp sheight)); +#endif +#endif +#endif /* PNG_sCAL_SUPPORTED || PNG_WRITE_sCAL_SUPPORTED */ + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +/* Provide a list of chunks and how they are to be handled, if the built-in + handling or default unknown chunk handling is not desired. Any chunks not + listed will be handled in the default manner. The IHDR and IEND chunks + must not be listed. + keep = 0: follow default behaviour + = 1: do not keep + = 2: keep only if safe-to-copy + = 3: keep even if unsafe-to-copy +*/ +extern PNG_EXPORT(void, png_set_keep_unknown_chunks) PNGARG((png_structp + png_ptr, int keep, png_bytep chunk_list, int num_chunks)); +PNG_EXPORT(int,png_handle_as_unknown) PNGARG((png_structp png_ptr, png_bytep + chunk_name)); +#endif +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED +extern PNG_EXPORT(void, png_set_unknown_chunks) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns)); +extern PNG_EXPORT(void, png_set_unknown_chunk_location) + PNGARG((png_structp png_ptr, png_infop info_ptr, int chunk, int location)); +extern PNG_EXPORT(png_uint_32,png_get_unknown_chunks) PNGARG((png_structp + png_ptr, png_infop info_ptr, png_unknown_chunkpp entries)); +#endif + +/* Png_free_data() will turn off the "valid" flag for anything it frees. + * If you need to turn it off for a chunk that your application has freed, + * you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK); + */ +extern PNG_EXPORT(void, png_set_invalid) PNGARG((png_structp png_ptr, + png_infop info_ptr, int mask)); + +#ifdef PNG_INFO_IMAGE_SUPPORTED +/* The "params" pointer is currently not used and is for future expansion. */ +extern PNG_EXPORT(void, png_read_png) PNGARG((png_structp png_ptr, + png_infop info_ptr, + int transforms, + png_voidp params)); +extern PNG_EXPORT(void, png_write_png) PNGARG((png_structp png_ptr, + png_infop info_ptr, + int transforms, + png_voidp params)); +#endif + +extern PNG_EXPORT(png_charp,png_get_copyright) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(png_charp,png_get_header_ver) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(png_charp,png_get_header_version) PNGARG((png_structp + png_ptr)); +extern PNG_EXPORT(png_charp,png_get_libpng_ver) PNGARG((png_structp png_ptr)); + +#ifdef PNG_MNG_FEATURES_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_permit_mng_features) PNGARG((png_structp + png_ptr, png_uint_32 mng_features_permitted)); +#endif + +/* For use in png_set_keep_unknown, added to version 1.2.6 */ +#define PNG_HANDLE_CHUNK_AS_DEFAULT 0 +#define PNG_HANDLE_CHUNK_NEVER 1 +#define PNG_HANDLE_CHUNK_IF_SAFE 2 +#define PNG_HANDLE_CHUNK_ALWAYS 3 + +/* Strip the prepended error numbers ("#nnn ") from error and warning + * messages before passing them to the error or warning handler. + */ +#ifdef PNG_ERROR_NUMBERS_SUPPORTED +extern PNG_EXPORT(void,png_set_strip_error_numbers) PNGARG((png_structp + png_ptr, png_uint_32 strip_mode)); +#endif + +/* Added in libpng-1.2.6 */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +extern PNG_EXPORT(void,png_set_user_limits) PNGARG((png_structp + png_ptr, png_uint_32 user_width_max, png_uint_32 user_height_max)); +extern PNG_EXPORT(png_uint_32,png_get_user_width_max) PNGARG((png_structp + png_ptr)); +extern PNG_EXPORT(png_uint_32,png_get_user_height_max) PNGARG((png_structp + png_ptr)); +/* Added in libpng-1.4.0 */ +extern PNG_EXPORT(void,png_set_chunk_cache_max) PNGARG((png_structp + png_ptr, png_uint_32 user_chunk_cache_max)); +extern PNG_EXPORT(png_uint_32,png_get_chunk_cache_max) + PNGARG((png_structp png_ptr)); +/* Added in libpng-1.4.1 */ +extern PNG_EXPORT(void,png_set_chunk_malloc_max) PNGARG((png_structp + png_ptr, png_alloc_size_t user_chunk_cache_max)); +extern PNG_EXPORT(png_alloc_size_t,png_get_chunk_malloc_max) + PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_INCH_CONVERSIONS) && defined(PNG_FLOATING_POINT_SUPPORTED) +PNG_EXPORT(png_uint_32,png_get_pixels_per_inch) PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +PNG_EXPORT(png_uint_32,png_get_x_pixels_per_inch) PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +PNG_EXPORT(png_uint_32,png_get_y_pixels_per_inch) PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +PNG_EXPORT(float,png_get_x_offset_inches) PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +PNG_EXPORT(float,png_get_y_offset_inches) PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +#ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(png_uint_32,png_get_pHYs_dpi) PNGARG((png_structp png_ptr, +png_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)); +#endif /* PNG_pHYs_SUPPORTED */ +#endif /* PNG_INCH_CONVERSIONS && PNG_FLOATING_POINT_SUPPORTED */ + +/* Added in libpng-1.4.0 */ +#ifdef PNG_IO_STATE_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_io_state) PNGARG((png_structp png_ptr)); + +extern PNG_EXPORT(png_bytep,png_get_io_chunk_name) + PNGARG((png_structp png_ptr)); + +/* The flags returned by png_get_io_state() are the following: */ +#define PNG_IO_NONE 0x0000 /* no I/O at this moment */ +#define PNG_IO_READING 0x0001 /* currently reading */ +#define PNG_IO_WRITING 0x0002 /* currently writing */ +#define PNG_IO_SIGNATURE 0x0010 /* currently at the file signature */ +#define PNG_IO_CHUNK_HDR 0x0020 /* currently at the chunk header */ +#define PNG_IO_CHUNK_DATA 0x0040 /* currently at the chunk data */ +#define PNG_IO_CHUNK_CRC 0x0080 /* currently at the chunk crc */ +#define PNG_IO_MASK_OP 0x000f /* current operation: reading/writing */ +#define PNG_IO_MASK_LOC 0x00f0 /* current location: sig/hdr/data/crc */ +#endif /* ?PNG_IO_STATE_SUPPORTED */ + +/* Maintainer: Put new public prototypes here ^, in libpng.3, and project + * defs + */ + +#ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED +/* With these routines we avoid an integer divide, which will be slower on + * most machines. However, it does take more operations than the corresponding + * divide method, so it may be slower on a few RISC systems. There are two + * shifts (by 8 or 16 bits) and an addition, versus a single integer divide. + * + * Note that the rounding factors are NOT supposed to be the same! 128 and + * 32768 are correct for the NODIV code; 127 and 32767 are correct for the + * standard method. + * + * [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ] + */ + + /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */ + +# define png_composite(composite, fg, alpha, bg) \ + { png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) \ + * (png_uint_16)(alpha) \ + + (png_uint_16)(bg)*(png_uint_16)(255 \ + - (png_uint_16)(alpha)) + (png_uint_16)128); \ + (composite) = (png_byte)((temp + (temp >> 8)) >> 8); } + +# define png_composite_16(composite, fg, alpha, bg) \ + { png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) \ + * (png_uint_32)(alpha) \ + + (png_uint_32)(bg)*(png_uint_32)(65535L \ + - (png_uint_32)(alpha)) + (png_uint_32)32768L); \ + (composite) = (png_uint_16)((temp + (temp >> 16)) >> 16); } + +#else /* Standard method using integer division */ + +# define png_composite(composite, fg, alpha, bg) \ + (composite) = (png_byte)(((png_uint_16)(fg) * (png_uint_16)(alpha) + \ + (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \ + (png_uint_16)127) / 255) + +# define png_composite_16(composite, fg, alpha, bg) \ + (composite) = (png_uint_16)(((png_uint_32)(fg) * (png_uint_32)(alpha) + \ + (png_uint_32)(bg)*(png_uint_32)(65535L - (png_uint_32)(alpha)) + \ + (png_uint_32)32767) / (png_uint_32)65535L) +#endif /* PNG_READ_COMPOSITE_NODIV_SUPPORTED */ + +#ifdef PNG_USE_READ_MACROS +/* Inline macros to do direct reads of bytes from the input buffer. + * The png_get_int_32() routine assumes we are using two's complement + * format for negative values, which is almost certainly true. + */ +/* We could make special-case BIG_ENDIAN macros that do direct reads here */ +# define png_get_uint_32(buf) \ + (((png_uint_32)(*(buf)) << 24) + \ + ((png_uint_32)(*((buf) + 1)) << 16) + \ + ((png_uint_32)(*((buf) + 2)) << 8) + \ + ((png_uint_32)(*((buf) + 3)))) +# define png_get_uint_16(buf) \ + (((png_uint_32)(*(buf)) << 8) + \ + ((png_uint_32)(*((buf) + 1)))) +#ifdef PNG_GET_INT_32_SUPPORTED +# define png_get_int_32(buf) \ + (((png_int_32)(*(buf)) << 24) + \ + ((png_int_32)(*((buf) + 1)) << 16) + \ + ((png_int_32)(*((buf) + 2)) << 8) + \ + ((png_int_32)(*((buf) + 3)))) +#endif +#else +extern PNG_EXPORT(png_uint_32,png_get_uint_32) PNGARG((png_bytep buf)); +extern PNG_EXPORT(png_uint_16,png_get_uint_16) PNGARG((png_bytep buf)); +#ifdef PNG_GET_INT_32_SUPPORTED +extern PNG_EXPORT(png_int_32,png_get_int_32) PNGARG((png_bytep buf)); +#endif +#endif +extern PNG_EXPORT(png_uint_32,png_get_uint_31) + PNGARG((png_structp png_ptr, png_bytep buf)); +/* No png_get_int_16 -- may be added if there's a real need for it. */ + +/* Place a 32-bit number into a buffer in PNG byte order (big-endian). */ +extern PNG_EXPORT(void,png_save_uint_32) + PNGARG((png_bytep buf, png_uint_32 i)); +extern PNG_EXPORT(void,png_save_int_32) + PNGARG((png_bytep buf, png_int_32 i)); + +/* Place a 16-bit number into a buffer in PNG byte order. + * The parameter is declared unsigned int, not png_uint_16, + * just to avoid potential problems on pre-ANSI C compilers. + */ +extern PNG_EXPORT(void,png_save_uint_16) + PNGARG((png_bytep buf, unsigned int i)); +/* No png_save_int_16 -- may be added if there's a real need for it. */ + +/* ************************************************************************* */ + +/* Various modes of operation. Note that after an init, mode is set to + * zero automatically when the structure is created. + */ +#define PNG_HAVE_IHDR 0x01 +#define PNG_HAVE_PLTE 0x02 +#define PNG_HAVE_IDAT 0x04 +#define PNG_AFTER_IDAT 0x08 /* Have complete zlib datastream */ +#define PNG_HAVE_IEND 0x10 +#define PNG_HAVE_gAMA 0x20 +#define PNG_HAVE_cHRM 0x40 + +#ifdef __cplusplus +} +#endif + +#endif /* PNG_VERSION_INFO_ONLY */ +/* Do not put anything past this line */ +#endif /* PNG_H */ diff --git a/reactos/include/reactos/libs/libpng/pngconf.h b/reactos/include/reactos/libs/libpng/pngconf.h new file mode 100644 index 00000000000..0c1065cfb47 --- /dev/null +++ b/reactos/include/reactos/libs/libpng/pngconf.h @@ -0,0 +1,1525 @@ + +/* pngconf.h - machine configurable file for libpng + * + * libpng version 1.4.3 - June 26, 2010 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2010 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + */ + +/* Any machine specific code is near the front of this file, so if you + * are configuring libpng for a machine, you may want to read the section + * starting here down to where it starts to typedef png_color, png_text, + * and png_info. + */ + +#ifndef PNGCONF_H +#define PNGCONF_H + +#ifndef PNG_NO_LIMITS_H +# include +#endif + +/* Added at libpng-1.2.9 */ + +/* config.h is created by and PNG_CONFIGURE_LIBPNG is set by the "configure" + * script. + */ +#ifdef PNG_CONFIGURE_LIBPNG +# ifdef HAVE_CONFIG_H +# include "config.h" +# endif +#endif + +/* + * Added at libpng-1.2.8 + * + * PNG_USER_CONFIG has to be defined on the compiler command line. This + * includes the resource compiler for Windows DLL configurations. + */ +#ifdef PNG_USER_CONFIG +# ifndef PNG_USER_PRIVATEBUILD +# define PNG_USER_PRIVATEBUILD +# endif +# include "pngusr.h" +#endif + +/* + * If you create a private DLL you need to define in "pngusr.h" the followings: + * #define PNG_USER_PRIVATEBUILD + * e.g. #define PNG_USER_PRIVATEBUILD "Build by MyCompany for xyz reasons." + * #define PNG_USER_DLLFNAME_POSTFIX + * e.g. // private DLL "libpng13gx.dll" + * #define PNG_USER_DLLFNAME_POSTFIX "gx" + * + * The following macros are also at your disposal if you want to complete the + * DLL VERSIONINFO structure. + * - PNG_USER_VERSIONINFO_COMMENTS + * - PNG_USER_VERSIONINFO_COMPANYNAME + * - PNG_USER_VERSIONINFO_LEGALTRADEMARKS + */ + +#ifdef __STDC__ +# ifdef SPECIALBUILD +# pragma message("PNG_LIBPNG_SPECIALBUILD (and deprecated SPECIALBUILD)\ + are now LIBPNG reserved macros. Use PNG_USER_PRIVATEBUILD instead.") +# endif + +# ifdef PRIVATEBUILD +# pragma message("PRIVATEBUILD is deprecated.\ + Use PNG_USER_PRIVATEBUILD instead.") +# define PNG_USER_PRIVATEBUILD PRIVATEBUILD +# endif +#endif /* __STDC__ */ + +/* End of material added to libpng-1.2.8 */ + +#ifndef PNG_VERSION_INFO_ONLY + +/* This is the size of the compression buffer, and thus the size of + * an IDAT chunk. Make this whatever size you feel is best for your + * machine. One of these will be allocated per png_struct. When this + * is full, it writes the data to the disk, and does some other + * calculations. Making this an extremely small size will slow + * the library down, but you may want to experiment to determine + * where it becomes significant, if you are concerned with memory + * usage. Note that zlib allocates at least 32Kb also. For readers, + * this describes the size of the buffer available to read the data in. + * Unless this gets smaller than the size of a row (compressed), + * it should not make much difference how big this is. + */ + +#ifndef PNG_ZBUF_SIZE +# define PNG_ZBUF_SIZE 8192 +#endif + +/* Enable if you want a write-only libpng */ + +#ifndef PNG_NO_READ_SUPPORTED +# define PNG_READ_SUPPORTED +#endif + +/* Enable if you want a read-only libpng */ + +#ifndef PNG_NO_WRITE_SUPPORTED +# define PNG_WRITE_SUPPORTED +#endif + +/* Enabled in 1.4.0. */ +#ifdef PNG_ALLOW_BENIGN_ERRORS +# define png_benign_error png_warning +# define png_chunk_benign_error png_chunk_warning +#else +# ifndef PNG_BENIGN_ERRORS_SUPPORTED +# define png_benign_error png_error +# define png_chunk_benign_error png_chunk_error +# endif +#endif + +/* Added at libpng version 1.4.0 */ +#if !defined(PNG_NO_WARNINGS) && !defined(PNG_WARNINGS_SUPPORTED) +# define PNG_WARNINGS_SUPPORTED +#endif + +/* Added at libpng version 1.4.0 */ +#if !defined(PNG_NO_ERROR_TEXT) && !defined(PNG_ERROR_TEXT_SUPPORTED) +# define PNG_ERROR_TEXT_SUPPORTED +#endif + +/* Added at libpng version 1.4.0 */ +#if !defined(PNG_NO_CHECK_cHRM) && !defined(PNG_CHECK_cHRM_SUPPORTED) +# define PNG_CHECK_cHRM_SUPPORTED +#endif + +/* Added at libpng version 1.4.0 */ +#if !defined(PNG_NO_ALIGNED_MEMORY) && !defined(PNG_ALIGNED_MEMORY_SUPPORTED) +# define PNG_ALIGNED_MEMORY_SUPPORTED +#endif + +/* Enabled by default in 1.2.0. You can disable this if you don't need to + support PNGs that are embedded in MNG datastreams */ +#ifndef PNG_NO_MNG_FEATURES +# ifndef PNG_MNG_FEATURES_SUPPORTED +# define PNG_MNG_FEATURES_SUPPORTED +# endif +#endif + +/* Added at libpng version 1.4.0 */ +#ifndef PNG_NO_FLOATING_POINT_SUPPORTED +# ifndef PNG_FLOATING_POINT_SUPPORTED +# define PNG_FLOATING_POINT_SUPPORTED +# endif +#endif + +/* Added at libpng-1.4.0beta49 for testing (this test is no longer used + in libpng and png_calloc() is always present) + */ +#define PNG_CALLOC_SUPPORTED + +/* If you are running on a machine where you cannot allocate more + * than 64K of memory at once, uncomment this. While libpng will not + * normally need that much memory in a chunk (unless you load up a very + * large file), zlib needs to know how big of a chunk it can use, and + * libpng thus makes sure to check any memory allocation to verify it + * will fit into memory. +#define PNG_MAX_MALLOC_64K + */ +#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K) +# define PNG_MAX_MALLOC_64K +#endif + +/* Special munging to support doing things the 'cygwin' way: + * 'Normal' png-on-win32 defines/defaults: + * PNG_BUILD_DLL -- building dll + * PNG_USE_DLL -- building an application, linking to dll + * (no define) -- building static library, or building an + * application and linking to the static lib + * 'Cygwin' defines/defaults: + * PNG_BUILD_DLL -- (ignored) building the dll + * (no define) -- (ignored) building an application, linking to the dll + * PNG_STATIC -- (ignored) building the static lib, or building an + * application that links to the static lib. + * ALL_STATIC -- (ignored) building various static libs, or building an + * application that links to the static libs. + * Thus, + * a cygwin user should define either PNG_BUILD_DLL or PNG_STATIC, and + * this bit of #ifdefs will define the 'correct' config variables based on + * that. If a cygwin user *wants* to define 'PNG_USE_DLL' that's okay, but + * unnecessary. + * + * Also, the precedence order is: + * ALL_STATIC (since we can't #undef something outside our namespace) + * PNG_BUILD_DLL + * PNG_STATIC + * (nothing) == PNG_USE_DLL + * + * CYGWIN (2002-01-20): The preceding is now obsolete. With the advent + * of auto-import in binutils, we no longer need to worry about + * __declspec(dllexport) / __declspec(dllimport) and friends. Therefore, + * we don't need to worry about PNG_STATIC or ALL_STATIC when it comes + * to __declspec() stuff. However, we DO need to worry about + * PNG_BUILD_DLL and PNG_STATIC because those change some defaults + * such as CONSOLE_IO. + */ +#ifdef __CYGWIN__ +# ifdef ALL_STATIC +# ifdef PNG_BUILD_DLL +# undef PNG_BUILD_DLL +# endif +# ifdef PNG_USE_DLL +# undef PNG_USE_DLL +# endif +# ifdef PNG_DLL +# undef PNG_DLL +# endif +# ifndef PNG_STATIC +# define PNG_STATIC +# endif +# else +# ifdef PNG_BUILD_DLL +# ifdef PNG_STATIC +# undef PNG_STATIC +# endif +# ifdef PNG_USE_DLL +# undef PNG_USE_DLL +# endif +# ifndef PNG_DLL +# define PNG_DLL +# endif +# else +# ifdef PNG_STATIC +# ifdef PNG_USE_DLL +# undef PNG_USE_DLL +# endif +# ifdef PNG_DLL +# undef PNG_DLL +# endif +# else +# ifndef PNG_USE_DLL +# define PNG_USE_DLL +# endif +# ifndef PNG_DLL +# define PNG_DLL +# endif +# endif +# endif +# endif +#endif + +/* This protects us against compilers that run on a windowing system + * and thus don't have or would rather us not use the stdio types: + * stdin, stdout, and stderr. The only one currently used is stderr + * in png_error() and png_warning(). #defining PNG_NO_CONSOLE_IO will + * prevent these from being compiled and used. #defining PNG_NO_STDIO + * will also prevent these, plus will prevent the entire set of stdio + * macros and functions (FILE *, printf, etc.) from being compiled and used, + * unless (PNG_DEBUG > 0) has been #defined. + * + * #define PNG_NO_CONSOLE_IO + * #define PNG_NO_STDIO + */ + +#if !defined(PNG_NO_STDIO) && !defined(PNG_STDIO_SUPPORTED) +# define PNG_STDIO_SUPPORTED +#endif + + +#ifdef PNG_BUILD_DLL +# if !defined(PNG_CONSOLE_IO_SUPPORTED) && !defined(PNG_NO_CONSOLE_IO) +# define PNG_NO_CONSOLE_IO +# endif +#endif + +# ifdef PNG_NO_STDIO +# ifndef PNG_NO_CONSOLE_IO +# define PNG_NO_CONSOLE_IO +# endif +# ifdef PNG_DEBUG +# if (PNG_DEBUG > 0) +# include +# endif +# endif +# else +# include +# endif + +#if !(defined PNG_NO_CONSOLE_IO) && !defined(PNG_CONSOLE_IO_SUPPORTED) +# define PNG_CONSOLE_IO_SUPPORTED +#endif + +/* This macro protects us against machines that don't have function + * prototypes (ie K&R style headers). If your compiler does not handle + * function prototypes, define this macro and use the included ansi2knr. + * I've always been able to use _NO_PROTO as the indicator, but you may + * need to drag the empty declaration out in front of here, or change the + * ifdef to suit your own needs. + */ +#ifndef PNGARG + +#ifdef OF /* zlib prototype munger */ +# define PNGARG(arglist) OF(arglist) +#else + +#ifdef _NO_PROTO +# define PNGARG(arglist) () +#else +# define PNGARG(arglist) arglist +#endif /* _NO_PROTO */ + +#endif /* OF */ + +#endif /* PNGARG */ + +/* Try to determine if we are compiling on a Mac. Note that testing for + * just __MWERKS__ is not good enough, because the Codewarrior is now used + * on non-Mac platforms. + */ +#ifndef MACOS +# if (defined(__MWERKS__) && defined(macintosh)) || defined(applec) || \ + defined(THINK_C) || defined(__SC__) || defined(TARGET_OS_MAC) +# define MACOS +# endif +#endif + +/* Enough people need this for various reasons to include it here */ +#if !defined(MACOS) && !defined(RISCOS) +# include +#endif + +/* PNG_SETJMP_NOT_SUPPORTED and PNG_NO_SETJMP_SUPPORTED are deprecated. */ +#if !defined(PNG_NO_SETJMP) && \ + !defined(PNG_SETJMP_NOT_SUPPORTED) && !defined(PNG_NO_SETJMP_SUPPORTED) +# define PNG_SETJMP_SUPPORTED +#endif + +#ifdef PNG_SETJMP_SUPPORTED +/* This is an attempt to force a single setjmp behaviour on Linux. If + * the X config stuff didn't define _BSD_SOURCE we wouldn't need this. + * + * You can bypass this test if you know that your application uses exactly + * the same setjmp.h that was included when libpng was built. Only define + * PNG_SKIP_SETJMP_CHECK while building your application, prior to the + * application's '#include "png.h"'. Don't define PNG_SKIP_SETJMP_CHECK + * while building a separate libpng library for general use. + */ + +# ifndef PNG_SKIP_SETJMP_CHECK +# ifdef __linux__ +# ifdef _BSD_SOURCE +# define PNG_SAVE_BSD_SOURCE +# undef _BSD_SOURCE +# endif +# ifdef _SETJMP_H + /* If you encounter a compiler error here, see the explanation + * near the end of INSTALL. + */ + __pngconf.h__ in libpng already includes setjmp.h; + __dont__ include it again.; +# endif +# endif /* __linux__ */ +# endif /* PNG_SKIP_SETJMP_CHECK */ + + /* Include setjmp.h for error handling */ +# include + +# ifdef __linux__ +# ifdef PNG_SAVE_BSD_SOURCE +# ifdef _BSD_SOURCE +# undef _BSD_SOURCE +# endif +# define _BSD_SOURCE +# undef PNG_SAVE_BSD_SOURCE +# endif +# endif /* __linux__ */ +#endif /* PNG_SETJMP_SUPPORTED */ + +#ifdef BSD +# include +#else +# include +#endif + +/* Other defines for things like memory and the like can go here. */ + +/* This controls how fine the quantizing gets. As this allocates + * a largish chunk of memory (32K), those who are not as concerned + * with quantizing quality can decrease some or all of these. + */ + +/* Prior to libpng-1.4.2, these were PNG_DITHER_*_BITS + * These migration aids will be removed from libpng-1.5.0. + */ +#ifdef PNG_DITHER_RED_BITS +# define PNG_QUANTIZE_RED_BITS PNG_DITHER_RED_BITS +#endif +#ifdef PNG_DITHER_GREEN_BITS +# define PNG_QUANTIZE_GREEN_BITS PNG_DITHER_GREEN_BITS +#endif +#ifdef PNG_DITHER_BLUE_BITS +# define PNG_QUANTIZE_BLUE_BITS PNG_DITHER_BLUE_BITS +#endif + +#ifndef PNG_QUANTIZE_RED_BITS +# define PNG_QUANTIZE_RED_BITS 5 +#endif +#ifndef PNG_QUANTIZE_GREEN_BITS +# define PNG_QUANTIZE_GREEN_BITS 5 +#endif +#ifndef PNG_QUANTIZE_BLUE_BITS +# define PNG_QUANTIZE_BLUE_BITS 5 +#endif + +/* This controls how fine the gamma correction becomes when you + * are only interested in 8 bits anyway. Increasing this value + * results in more memory being used, and more pow() functions + * being called to fill in the gamma tables. Don't set this value + * less then 8, and even that may not work (I haven't tested it). + */ + +#ifndef PNG_MAX_GAMMA_8 +# define PNG_MAX_GAMMA_8 11 +#endif + +/* This controls how much a difference in gamma we can tolerate before + * we actually start doing gamma conversion. + */ +#ifndef PNG_GAMMA_THRESHOLD +# define PNG_GAMMA_THRESHOLD 0.05 +#endif + +/* The following uses const char * instead of char * for error + * and warning message functions, so some compilers won't complain. + * If you do not want to use const, define PNG_NO_CONST here. + */ + +#ifndef PNG_CONST +# ifndef PNG_NO_CONST +# define PNG_CONST const +# else +# define PNG_CONST +# endif +#endif + +/* The following defines give you the ability to remove code from the + * library that you will not be using. I wish I could figure out how to + * automate this, but I can't do that without making it seriously hard + * on the users. So if you are not using an ability, change the #define + * to and #undef, and that part of the library will not be compiled. If + * your linker can't find a function, you may want to make sure the + * ability is defined here. Some of these depend upon some others being + * defined. I haven't figured out all the interactions here, so you may + * have to experiment awhile to get everything to compile. If you are + * creating or using a shared library, you probably shouldn't touch this, + * as it will affect the size of the structures, and this will cause bad + * things to happen if the library and/or application ever change. + */ + +/* Any features you will not be using can be undef'ed here */ + +/* GR-P, 0.96a: Set "*TRANSFORMS_SUPPORTED as default but allow user + * to turn it off with PNG_NO_READ|WRITE_TRANSFORMS on the compile line, + * then pick and choose which ones to define without having to edit this + * file. It is safe to use the PNG_NO_READ|WRITE_TRANSFORMS + * if you only want to have a png-compliant reader/writer but don't need + * any of the extra transformations. This saves about 80 kbytes in a + * typical installation of the library. (PNG_NO_* form added in version + * 1.0.1c, for consistency; PNG_*_TRANSFORMS_NOT_SUPPORTED deprecated in + * 1.4.0) + */ + +/* Ignore attempt to turn off both floating and fixed point support */ +#if !defined(PNG_FLOATING_POINT_SUPPORTED) || \ + !defined(PNG_NO_FIXED_POINT_SUPPORTED) +# define PNG_FIXED_POINT_SUPPORTED +#endif + +#ifdef PNG_READ_SUPPORTED + +/* PNG_READ_TRANSFORMS_NOT_SUPPORTED is deprecated. */ +#if !defined(PNG_READ_TRANSFORMS_NOT_SUPPORTED) && \ + !defined(PNG_NO_READ_TRANSFORMS) +# define PNG_READ_TRANSFORMS_SUPPORTED +#endif + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED +# ifndef PNG_NO_READ_EXPAND +# define PNG_READ_EXPAND_SUPPORTED +# endif +# ifndef PNG_NO_READ_SHIFT +# define PNG_READ_SHIFT_SUPPORTED +# endif +# ifndef PNG_NO_READ_PACK +# define PNG_READ_PACK_SUPPORTED +# endif +# ifndef PNG_NO_READ_BGR +# define PNG_READ_BGR_SUPPORTED +# endif +# ifndef PNG_NO_READ_SWAP +# define PNG_READ_SWAP_SUPPORTED +# endif +# ifndef PNG_NO_READ_PACKSWAP +# define PNG_READ_PACKSWAP_SUPPORTED +# endif +# ifndef PNG_NO_READ_INVERT +# define PNG_READ_INVERT_SUPPORTED +# endif +# ifndef PNG_NO_READ_QUANTIZE + /* Prior to libpng-1.4.0 this was PNG_READ_DITHER_SUPPORTED */ +# ifndef PNG_NO_READ_DITHER /* This migration aid will be removed */ +# define PNG_READ_QUANTIZE_SUPPORTED +# endif +# endif +# ifndef PNG_NO_READ_BACKGROUND +# define PNG_READ_BACKGROUND_SUPPORTED +# endif +# ifndef PNG_NO_READ_16_TO_8 +# define PNG_READ_16_TO_8_SUPPORTED +# endif +# ifndef PNG_NO_READ_FILLER +# define PNG_READ_FILLER_SUPPORTED +# endif +# ifndef PNG_NO_READ_GAMMA +# define PNG_READ_GAMMA_SUPPORTED +# endif +# ifndef PNG_NO_READ_GRAY_TO_RGB +# define PNG_READ_GRAY_TO_RGB_SUPPORTED +# endif +# ifndef PNG_NO_READ_SWAP_ALPHA +# define PNG_READ_SWAP_ALPHA_SUPPORTED +# endif +# ifndef PNG_NO_READ_INVERT_ALPHA +# define PNG_READ_INVERT_ALPHA_SUPPORTED +# endif +# ifndef PNG_NO_READ_STRIP_ALPHA +# define PNG_READ_STRIP_ALPHA_SUPPORTED +# endif +# ifndef PNG_NO_READ_USER_TRANSFORM +# define PNG_READ_USER_TRANSFORM_SUPPORTED +# endif +# ifndef PNG_NO_READ_RGB_TO_GRAY +# define PNG_READ_RGB_TO_GRAY_SUPPORTED +# endif +#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ + +/* PNG_PROGRESSIVE_READ_NOT_SUPPORTED is deprecated. */ +#if !defined(PNG_NO_PROGRESSIVE_READ) && \ + !defined(PNG_PROGRESSIVE_READ_NOT_SUPPORTED) /* if you don't do progressive */ +# define PNG_PROGRESSIVE_READ_SUPPORTED /* reading. This is not talking */ +#endif /* about interlacing capability! You'll */ + /* still have interlacing unless you change the following define: */ + +#define PNG_READ_INTERLACING_SUPPORTED /* required for PNG-compliant decoders */ + +/* PNG_NO_SEQUENTIAL_READ_SUPPORTED is deprecated. */ +#if !defined(PNG_NO_SEQUENTIAL_READ) && \ + !defined(PNG_SEQUENTIAL_READ_SUPPORTED) && \ + !defined(PNG_NO_SEQUENTIAL_READ_SUPPORTED) +# define PNG_SEQUENTIAL_READ_SUPPORTED +#endif + +#ifndef PNG_NO_READ_COMPOSITE_NODIV +# ifndef PNG_NO_READ_COMPOSITED_NODIV /* libpng-1.0.x misspelling */ +# define PNG_READ_COMPOSITE_NODIV_SUPPORTED /* well tested on Intel, SGI */ +# endif +#endif + +#if !defined(PNG_NO_GET_INT_32) || defined(PNG_READ_oFFS_SUPPORTED) || \ + defined(PNG_READ_pCAL_SUPPORTED) +# ifndef PNG_GET_INT_32_SUPPORTED +# define PNG_GET_INT_32_SUPPORTED +# endif +#endif + +#endif /* PNG_READ_SUPPORTED */ + +#ifdef PNG_WRITE_SUPPORTED + +/* PNG_WRITE_TRANSFORMS_NOT_SUPPORTED is deprecated. */ +#if !defined(PNG_WRITE_TRANSFORMS_NOT_SUPPORTED) && \ + !defined(PNG_NO_WRITE_TRANSFORMS) +# define PNG_WRITE_TRANSFORMS_SUPPORTED +#endif + +#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED +# ifndef PNG_NO_WRITE_SHIFT +# define PNG_WRITE_SHIFT_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_PACK +# define PNG_WRITE_PACK_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_BGR +# define PNG_WRITE_BGR_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_SWAP +# define PNG_WRITE_SWAP_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_PACKSWAP +# define PNG_WRITE_PACKSWAP_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_INVERT +# define PNG_WRITE_INVERT_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_FILLER +# define PNG_WRITE_FILLER_SUPPORTED /* same as WRITE_STRIP_ALPHA */ +# endif +# ifndef PNG_NO_WRITE_SWAP_ALPHA +# define PNG_WRITE_SWAP_ALPHA_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_INVERT_ALPHA +# define PNG_WRITE_INVERT_ALPHA_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_USER_TRANSFORM +# define PNG_WRITE_USER_TRANSFORM_SUPPORTED +# endif +#endif /* PNG_WRITE_TRANSFORMS_SUPPORTED */ + +#if !defined(PNG_NO_WRITE_INTERLACING_SUPPORTED) && \ + !defined(PNG_WRITE_INTERLACING_SUPPORTED) + /* This is not required for PNG-compliant encoders, but can cause + * trouble if left undefined + */ +# define PNG_WRITE_INTERLACING_SUPPORTED +#endif + +#if !defined(PNG_NO_WRITE_WEIGHTED_FILTER) && \ + !defined(PNG_WRITE_WEIGHTED_FILTER) && \ + defined(PNG_FLOATING_POINT_SUPPORTED) +# define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED +#endif + +#ifndef PNG_NO_WRITE_FLUSH +# define PNG_WRITE_FLUSH_SUPPORTED +#endif + +#if !defined(PNG_NO_SAVE_INT_32) || defined(PNG_WRITE_oFFS_SUPPORTED) || \ + defined(PNG_WRITE_pCAL_SUPPORTED) +# ifndef PNG_SAVE_INT_32_SUPPORTED +# define PNG_SAVE_INT_32_SUPPORTED +# endif +#endif + +#endif /* PNG_WRITE_SUPPORTED */ + +#define PNG_NO_ERROR_NUMBERS + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +# ifndef PNG_NO_USER_TRANSFORM_PTR +# define PNG_USER_TRANSFORM_PTR_SUPPORTED +# endif +#endif + +#if defined(PNG_STDIO_SUPPORTED) && !defined(PNG_TIME_RFC1123_SUPPORTED) +# define PNG_TIME_RFC1123_SUPPORTED +#endif + +/* This adds extra functions in pngget.c for accessing data from the + * info pointer (added in version 0.99) + * png_get_image_width() + * png_get_image_height() + * png_get_bit_depth() + * png_get_color_type() + * png_get_compression_type() + * png_get_filter_type() + * png_get_interlace_type() + * png_get_pixel_aspect_ratio() + * png_get_pixels_per_meter() + * png_get_x_offset_pixels() + * png_get_y_offset_pixels() + * png_get_x_offset_microns() + * png_get_y_offset_microns() + */ +#if !defined(PNG_NO_EASY_ACCESS) && !defined(PNG_EASY_ACCESS_SUPPORTED) +# define PNG_EASY_ACCESS_SUPPORTED +#endif + +/* Added at libpng-1.2.0 */ +#if !defined(PNG_NO_USER_MEM) && !defined(PNG_USER_MEM_SUPPORTED) +# define PNG_USER_MEM_SUPPORTED +#endif + +/* Added at libpng-1.2.6 */ +#ifndef PNG_NO_SET_USER_LIMITS +# ifndef PNG_SET_USER_LIMITS_SUPPORTED +# define PNG_SET_USER_LIMITS_SUPPORTED +# endif + /* Feature added at libpng-1.4.0, this flag added at 1.4.1 */ +# ifndef PNG_SET_CHUNK_CACHE_LIMIT_SUPPORTED +# define PNG_SET_CHUNK_CACHE_LIMIT_SUPPORTED +# endif + /* Feature added at libpng-1.4.1, this flag added at 1.4.1 */ +# ifndef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED +# define PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED +# endif +#endif + +/* Added at libpng-1.2.43 */ +#ifndef PNG_USER_LIMITS_SUPPORTED +# ifndef PNG_NO_USER_LIMITS +# define PNG_USER_LIMITS_SUPPORTED +# endif +#endif + +/* Added at libpng-1.0.16 and 1.2.6. To accept all valid PNGs no matter + * how large, set these two limits to 0x7fffffffL + */ +#ifndef PNG_USER_WIDTH_MAX +# define PNG_USER_WIDTH_MAX 1000000L +#endif +#ifndef PNG_USER_HEIGHT_MAX +# define PNG_USER_HEIGHT_MAX 1000000L +#endif + +/* Added at libpng-1.2.43. To accept all valid PNGs no matter + * how large, set these two limits to 0. + */ +#ifndef PNG_USER_CHUNK_CACHE_MAX +# define PNG_USER_CHUNK_CACHE_MAX 0 +#endif + +/* Added at libpng-1.2.43 */ +#ifndef PNG_USER_CHUNK_MALLOC_MAX +# define PNG_USER_CHUNK_MALLOC_MAX 0 +#endif + +/* Added at libpng-1.4.0 */ +#if !defined(PNG_NO_IO_STATE) && !defined(PNG_IO_STATE_SUPPORTED) +# define PNG_IO_STATE_SUPPORTED +#endif + +#ifndef PNG_LITERAL_SHARP +# define PNG_LITERAL_SHARP 0x23 +#endif +#ifndef PNG_LITERAL_LEFT_SQUARE_BRACKET +# define PNG_LITERAL_LEFT_SQUARE_BRACKET 0x5b +#endif +#ifndef PNG_LITERAL_RIGHT_SQUARE_BRACKET +# define PNG_LITERAL_RIGHT_SQUARE_BRACKET 0x5d +#endif +#ifndef PNG_STRING_NEWLINE +#define PNG_STRING_NEWLINE "\n" +#endif + +/* These are currently experimental features, define them if you want */ + +/* Very little testing */ +/* +#ifdef PNG_READ_SUPPORTED +# ifndef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED +# define PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED +# endif +#endif +*/ + +/* This is only for PowerPC big-endian and 680x0 systems */ +/* some testing */ +/* +#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED +# define PNG_READ_BIG_ENDIAN_SUPPORTED +#endif +*/ + +#if !defined(PNG_NO_USE_READ_MACROS) && !defined(PNG_USE_READ_MACROS) +# define PNG_USE_READ_MACROS +#endif + +/* Buggy compilers (e.g., gcc 2.7.2.2) need PNG_NO_POINTER_INDEXING */ + +#if !defined(PNG_NO_POINTER_INDEXING) && \ + !defined(PNG_POINTER_INDEXING_SUPPORTED) +# define PNG_POINTER_INDEXING_SUPPORTED +#endif + + +/* Any chunks you are not interested in, you can undef here. The + * ones that allocate memory may be expecially important (hIST, + * tEXt, zTXt, tRNS, pCAL). Others will just save time and make png_info + * a bit smaller. + */ + +/* The size of the png_text structure changed in libpng-1.0.6 when + * iTXt support was added. iTXt support was turned off by default through + * libpng-1.2.x, to support old apps that malloc the png_text structure + * instead of calling png_set_text() and letting libpng malloc it. It + * was turned on by default in libpng-1.4.0. + */ + +/* PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED is deprecated. */ +#if defined(PNG_READ_SUPPORTED) && \ + !defined(PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \ + !defined(PNG_NO_READ_ANCILLARY_CHUNKS) +# define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED +#endif + +/* PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED is deprecated. */ +#if defined(PNG_WRITE_SUPPORTED) && \ + !defined(PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \ + !defined(PNG_NO_WRITE_ANCILLARY_CHUNKS) +# define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED +#endif + +#ifdef PNG_READ_ANCILLARY_CHUNKS_SUPPORTED + +#ifdef PNG_NO_READ_TEXT +# define PNG_NO_READ_iTXt +# define PNG_NO_READ_tEXt +# define PNG_NO_READ_zTXt +#endif + +#ifndef PNG_NO_READ_bKGD +# define PNG_READ_bKGD_SUPPORTED +# define PNG_bKGD_SUPPORTED +#endif +#ifndef PNG_NO_READ_cHRM +# define PNG_READ_cHRM_SUPPORTED +# define PNG_cHRM_SUPPORTED +#endif +#ifndef PNG_NO_READ_gAMA +# define PNG_READ_gAMA_SUPPORTED +# define PNG_gAMA_SUPPORTED +#endif +#ifndef PNG_NO_READ_hIST +# define PNG_READ_hIST_SUPPORTED +# define PNG_hIST_SUPPORTED +#endif +#ifndef PNG_NO_READ_iCCP +# define PNG_READ_iCCP_SUPPORTED +# define PNG_iCCP_SUPPORTED +#endif +#ifndef PNG_NO_READ_iTXt +# ifndef PNG_READ_iTXt_SUPPORTED +# define PNG_READ_iTXt_SUPPORTED +# endif +# ifndef PNG_iTXt_SUPPORTED +# define PNG_iTXt_SUPPORTED +# endif +#endif +#ifndef PNG_NO_READ_oFFs +# define PNG_READ_oFFs_SUPPORTED +# define PNG_oFFs_SUPPORTED +#endif +#ifndef PNG_NO_READ_pCAL +# define PNG_READ_pCAL_SUPPORTED +# define PNG_pCAL_SUPPORTED +#endif +#ifndef PNG_NO_READ_sCAL +# define PNG_READ_sCAL_SUPPORTED +# define PNG_sCAL_SUPPORTED +#endif +#ifndef PNG_NO_READ_pHYs +# define PNG_READ_pHYs_SUPPORTED +# define PNG_pHYs_SUPPORTED +#endif +#ifndef PNG_NO_READ_sBIT +# define PNG_READ_sBIT_SUPPORTED +# define PNG_sBIT_SUPPORTED +#endif +#ifndef PNG_NO_READ_sPLT +# define PNG_READ_sPLT_SUPPORTED +# define PNG_sPLT_SUPPORTED +#endif +#ifndef PNG_NO_READ_sRGB +# define PNG_READ_sRGB_SUPPORTED +# define PNG_sRGB_SUPPORTED +#endif +#ifndef PNG_NO_READ_tEXt +# define PNG_READ_tEXt_SUPPORTED +# define PNG_tEXt_SUPPORTED +#endif +#ifndef PNG_NO_READ_tIME +# define PNG_READ_tIME_SUPPORTED +# define PNG_tIME_SUPPORTED +#endif +#ifndef PNG_NO_READ_tRNS +# define PNG_READ_tRNS_SUPPORTED +# define PNG_tRNS_SUPPORTED +#endif +#ifndef PNG_NO_READ_zTXt +# define PNG_READ_zTXt_SUPPORTED +# define PNG_zTXt_SUPPORTED +#endif +#ifndef PNG_NO_READ_OPT_PLTE +# define PNG_READ_OPT_PLTE_SUPPORTED /* only affects support of the */ +#endif /* optional PLTE chunk in RGB and RGBA images */ +#if defined(PNG_READ_iTXt_SUPPORTED) || defined(PNG_READ_tEXt_SUPPORTED) || \ + defined(PNG_READ_zTXt_SUPPORTED) +# define PNG_READ_TEXT_SUPPORTED +# define PNG_TEXT_SUPPORTED +#endif + +#endif /* PNG_READ_ANCILLARY_CHUNKS_SUPPORTED */ + +#ifndef PNG_NO_READ_UNKNOWN_CHUNKS +# ifndef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED +# define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED +# endif +# ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED +# define PNG_UNKNOWN_CHUNKS_SUPPORTED +# endif +# ifndef PNG_READ_USER_CHUNKS_SUPPORTED +# define PNG_READ_USER_CHUNKS_SUPPORTED +# endif +#endif +#ifndef PNG_NO_READ_USER_CHUNKS +# ifndef PNG_READ_USER_CHUNKS_SUPPORTED +# define PNG_READ_USER_CHUNKS_SUPPORTED +# endif +# ifndef PNG_USER_CHUNKS_SUPPORTED +# define PNG_USER_CHUNKS_SUPPORTED +# endif +#endif +#ifndef PNG_NO_HANDLE_AS_UNKNOWN +# ifndef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +# define PNG_HANDLE_AS_UNKNOWN_SUPPORTED +# endif +#endif + +#ifdef PNG_WRITE_SUPPORTED +#ifdef PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED + +#ifdef PNG_NO_WRITE_TEXT +# define PNG_NO_WRITE_iTXt +# define PNG_NO_WRITE_tEXt +# define PNG_NO_WRITE_zTXt +#endif +#ifndef PNG_NO_WRITE_bKGD +# define PNG_WRITE_bKGD_SUPPORTED +# ifndef PNG_bKGD_SUPPORTED +# define PNG_bKGD_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_cHRM +# define PNG_WRITE_cHRM_SUPPORTED +# ifndef PNG_cHRM_SUPPORTED +# define PNG_cHRM_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_gAMA +# define PNG_WRITE_gAMA_SUPPORTED +# ifndef PNG_gAMA_SUPPORTED +# define PNG_gAMA_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_hIST +# define PNG_WRITE_hIST_SUPPORTED +# ifndef PNG_hIST_SUPPORTED +# define PNG_hIST_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_iCCP +# define PNG_WRITE_iCCP_SUPPORTED +# ifndef PNG_iCCP_SUPPORTED +# define PNG_iCCP_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_iTXt +# ifndef PNG_WRITE_iTXt_SUPPORTED +# define PNG_WRITE_iTXt_SUPPORTED +# endif +# ifndef PNG_iTXt_SUPPORTED +# define PNG_iTXt_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_oFFs +# define PNG_WRITE_oFFs_SUPPORTED +# ifndef PNG_oFFs_SUPPORTED +# define PNG_oFFs_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_pCAL +# define PNG_WRITE_pCAL_SUPPORTED +# ifndef PNG_pCAL_SUPPORTED +# define PNG_pCAL_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_sCAL +# define PNG_WRITE_sCAL_SUPPORTED +# ifndef PNG_sCAL_SUPPORTED +# define PNG_sCAL_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_pHYs +# define PNG_WRITE_pHYs_SUPPORTED +# ifndef PNG_pHYs_SUPPORTED +# define PNG_pHYs_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_sBIT +# define PNG_WRITE_sBIT_SUPPORTED +# ifndef PNG_sBIT_SUPPORTED +# define PNG_sBIT_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_sPLT +# define PNG_WRITE_sPLT_SUPPORTED +# ifndef PNG_sPLT_SUPPORTED +# define PNG_sPLT_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_sRGB +# define PNG_WRITE_sRGB_SUPPORTED +# ifndef PNG_sRGB_SUPPORTED +# define PNG_sRGB_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_tEXt +# define PNG_WRITE_tEXt_SUPPORTED +# ifndef PNG_tEXt_SUPPORTED +# define PNG_tEXt_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_tIME +# define PNG_WRITE_tIME_SUPPORTED +# ifndef PNG_tIME_SUPPORTED +# define PNG_tIME_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_tRNS +# define PNG_WRITE_tRNS_SUPPORTED +# ifndef PNG_tRNS_SUPPORTED +# define PNG_tRNS_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_zTXt +# define PNG_WRITE_zTXt_SUPPORTED +# ifndef PNG_zTXt_SUPPORTED +# define PNG_zTXt_SUPPORTED +# endif +#endif +#if defined(PNG_WRITE_iTXt_SUPPORTED) || defined(PNG_WRITE_tEXt_SUPPORTED) || \ + defined(PNG_WRITE_zTXt_SUPPORTED) +# define PNG_WRITE_TEXT_SUPPORTED +# ifndef PNG_TEXT_SUPPORTED +# define PNG_TEXT_SUPPORTED +# endif +#endif + +#ifdef PNG_WRITE_tIME_SUPPORTED +# ifndef PNG_NO_CONVERT_tIME +# ifndef _WIN32_WCE +/* The "tm" structure is not supported on WindowsCE */ +# ifndef PNG_CONVERT_tIME_SUPPORTED +# define PNG_CONVERT_tIME_SUPPORTED +# endif +# endif +# endif +#endif + +#endif /* PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED */ + +#ifndef PNG_NO_WRITE_FILTER +# ifndef PNG_WRITE_FILTER_SUPPORTED +# define PNG_WRITE_FILTER_SUPPORTED +# endif +#endif + +#ifndef PNG_NO_WRITE_UNKNOWN_CHUNKS +# define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED +# ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED +# define PNG_UNKNOWN_CHUNKS_SUPPORTED +# endif +#endif +#ifndef PNG_NO_HANDLE_AS_UNKNOWN +# ifndef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +# define PNG_HANDLE_AS_UNKNOWN_SUPPORTED +# endif +#endif +#endif /* PNG_WRITE_SUPPORTED */ + +/* Turn this off to disable png_read_png() and + * png_write_png() and leave the row_pointers member + * out of the info structure. + */ +#ifndef PNG_NO_INFO_IMAGE +# define PNG_INFO_IMAGE_SUPPORTED +#endif + +/* Need the time information for converting tIME chunks */ +#ifdef PNG_CONVERT_tIME_SUPPORTED + /* "time.h" functions are not supported on WindowsCE */ +# include +#endif + +/* Some typedefs to get us started. These should be safe on most of the + * common platforms. The typedefs should be at least as large as the + * numbers suggest (a png_uint_32 must be at least 32 bits long), but they + * don't have to be exactly that size. Some compilers dislike passing + * unsigned shorts as function parameters, so you may be better off using + * unsigned int for png_uint_16. + */ + +#if defined(INT_MAX) && (INT_MAX > 0x7ffffffeL) +typedef unsigned int png_uint_32; +typedef int png_int_32; +#else +typedef unsigned long png_uint_32; +typedef long png_int_32; +#endif +typedef unsigned short png_uint_16; +typedef short png_int_16; +typedef unsigned char png_byte; + +#ifdef PNG_NO_SIZE_T + typedef unsigned int png_size_t; +#else + typedef size_t png_size_t; +#endif +#define png_sizeof(x) sizeof(x) + +/* The following is needed for medium model support. It cannot be in the + * pngpriv.h header. Needs modification for other compilers besides + * MSC. Model independent support declares all arrays and pointers to be + * large using the far keyword. The zlib version used must also support + * model independent data. As of version zlib 1.0.4, the necessary changes + * have been made in zlib. The USE_FAR_KEYWORD define triggers other + * changes that are needed. (Tim Wegner) + */ + +/* Separate compiler dependencies (problem here is that zlib.h always + * defines FAR. (SJT) + */ +#ifdef __BORLANDC__ +# if defined(__LARGE__) || defined(__HUGE__) || defined(__COMPACT__) +# define LDATA 1 +# else +# define LDATA 0 +# endif + /* GRR: why is Cygwin in here? Cygwin is not Borland C... */ +# if !defined(__WIN32__) && !defined(__FLAT__) && !defined(__CYGWIN__) +# define PNG_MAX_MALLOC_64K +# if (LDATA != 1) +# ifndef FAR +# define FAR __far +# endif +# define USE_FAR_KEYWORD +# endif /* LDATA != 1 */ + /* Possibly useful for moving data out of default segment. + * Uncomment it if you want. Could also define FARDATA as + * const if your compiler supports it. (SJT) +# define FARDATA FAR + */ +# endif /* __WIN32__, __FLAT__, __CYGWIN__ */ +#endif /* __BORLANDC__ */ + + +/* Suggest testing for specific compiler first before testing for + * FAR. The Watcom compiler defines both __MEDIUM__ and M_I86MM, + * making reliance oncertain keywords suspect. (SJT) + */ + +/* MSC Medium model */ +#ifdef FAR +# ifdef M_I86MM +# define USE_FAR_KEYWORD +# define FARDATA FAR +# include +# endif +#endif + +/* SJT: default case */ +#ifndef FAR +# define FAR +#endif + +/* At this point FAR is always defined */ +#ifndef FARDATA +# define FARDATA +#endif + +/* Typedef for floating-point numbers that are converted + to fixed-point with a multiple of 100,000, e.g., int_gamma */ +typedef png_int_32 png_fixed_point; + +/* Add typedefs for pointers */ +typedef void FAR * png_voidp; +typedef png_byte FAR * png_bytep; +typedef png_uint_32 FAR * png_uint_32p; +typedef png_int_32 FAR * png_int_32p; +typedef png_uint_16 FAR * png_uint_16p; +typedef png_int_16 FAR * png_int_16p; +typedef PNG_CONST char FAR * png_const_charp; +typedef char FAR * png_charp; +typedef png_fixed_point FAR * png_fixed_point_p; + +#ifndef PNG_NO_STDIO +typedef FILE * png_FILE_p; +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double FAR * png_doublep; +#endif + +/* Pointers to pointers; i.e. arrays */ +typedef png_byte FAR * FAR * png_bytepp; +typedef png_uint_32 FAR * FAR * png_uint_32pp; +typedef png_int_32 FAR * FAR * png_int_32pp; +typedef png_uint_16 FAR * FAR * png_uint_16pp; +typedef png_int_16 FAR * FAR * png_int_16pp; +typedef PNG_CONST char FAR * FAR * png_const_charpp; +typedef char FAR * FAR * png_charpp; +typedef png_fixed_point FAR * FAR * png_fixed_point_pp; +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double FAR * FAR * png_doublepp; +#endif + +/* Pointers to pointers to pointers; i.e., pointer to array */ +typedef char FAR * FAR * FAR * png_charppp; + +/* Define PNG_BUILD_DLL if the module being built is a Windows + * LIBPNG DLL. + * + * Define PNG_USE_DLL if you want to *link* to the Windows LIBPNG DLL. + * It is equivalent to Microsoft predefined macro _DLL that is + * automatically defined when you compile using the share + * version of the CRT (C Run-Time library) + * + * The cygwin mods make this behavior a little different: + * Define PNG_BUILD_DLL if you are building a dll for use with cygwin + * Define PNG_STATIC if you are building a static library for use with cygwin, + * -or- if you are building an application that you want to link to the + * static library. + * PNG_USE_DLL is defined by default (no user action needed) unless one of + * the other flags is defined. + */ + +#if !defined(PNG_DLL) && (defined(PNG_BUILD_DLL) || defined(PNG_USE_DLL)) +# define PNG_DLL +#endif + +#ifdef __CYGWIN__ +# undef PNGAPI +# define PNGAPI __cdecl +# undef PNG_IMPEXP +# define PNG_IMPEXP +#endif + +#define PNG_USE_LOCAL_ARRAYS /* Not used in libpng, defined for legacy apps */ + +/* If you define PNGAPI, e.g., with compiler option "-DPNGAPI=__stdcall", + * you may get warnings regarding the linkage of png_zalloc and png_zfree. + * Don't ignore those warnings; you must also reset the default calling + * convention in your compiler to match your PNGAPI, and you must build + * zlib and your applications the same way you build libpng. + */ + +#if defined(__MINGW32__) && !defined(PNG_MODULEDEF) +# ifndef PNG_NO_MODULEDEF +# define PNG_NO_MODULEDEF +# endif +#endif + +#if !defined(PNG_IMPEXP) && defined(PNG_BUILD_DLL) && !defined(PNG_NO_MODULEDEF) +# define PNG_IMPEXP +#endif + +#if defined(PNG_DLL) || defined(_DLL) || defined(__DLL__ ) || \ + (( defined(_Windows) || defined(_WINDOWS) || \ + defined(WIN32) || defined(_WIN32) || defined(__WIN32__) )) + +# ifndef PNGAPI +# if defined(__GNUC__) || (defined (_MSC_VER) && (_MSC_VER >= 800)) +# define PNGAPI __cdecl +# else +# define PNGAPI _cdecl +# endif +# endif + +# if !defined(PNG_IMPEXP) && (!defined(PNG_DLL) || \ + 0 /* WINCOMPILER_WITH_NO_SUPPORT_FOR_DECLIMPEXP */) +# define PNG_IMPEXP +# endif + +# ifndef PNG_IMPEXP + +# define PNG_EXPORT_TYPE1(type,symbol) PNG_IMPEXP type PNGAPI symbol +# define PNG_EXPORT_TYPE2(type,symbol) type PNG_IMPEXP PNGAPI symbol + + /* Borland/Microsoft */ +# if defined(_MSC_VER) || defined(__BORLANDC__) +# if (_MSC_VER >= 800) || (__BORLANDC__ >= 0x500) +# define PNG_EXPORT PNG_EXPORT_TYPE1 +# else +# define PNG_EXPORT PNG_EXPORT_TYPE2 +# ifdef PNG_BUILD_DLL +# define PNG_IMPEXP __export +# else +# define PNG_IMPEXP /*__import */ /* doesn't exist AFAIK in VC++ */ +# endif /* Exists in Borland C++ for + C++ classes (== huge) */ +# endif +# endif + +# ifndef PNG_IMPEXP +# ifdef PNG_BUILD_DLL +# define PNG_IMPEXP __declspec(dllexport) +# else +# define PNG_IMPEXP __declspec(dllimport) +# endif +# endif +# endif /* PNG_IMPEXP */ +#else /* !(DLL || non-cygwin WINDOWS) */ +# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__) +# ifndef PNGAPI +# define PNGAPI _System +# endif +# else +# if 0 /* ... other platforms, with other meanings */ +# endif +# endif +#endif + +#ifndef PNGAPI +# define PNGAPI +#endif +#ifndef PNG_IMPEXP +# define PNG_IMPEXP +#endif + +#ifdef PNG_BUILDSYMS +# ifndef PNG_EXPORT +# define PNG_EXPORT(type,symbol) PNG_FUNCTION_EXPORT symbol END +# endif +#endif + +#ifndef PNG_EXPORT +# define PNG_EXPORT(type,symbol) PNG_IMPEXP type PNGAPI symbol +#endif + +/* Support for compiler specific function attributes. These are used + * so that where compiler support is available incorrect use of API + * functions in png.h will generate compiler warnings. + * + * Added at libpng-1.2.41. + */ + +#ifndef PNG_NO_PEDANTIC_WARNINGS +# ifndef PNG_PEDANTIC_WARNINGS_SUPPORTED +# define PNG_PEDANTIC_WARNINGS_SUPPORTED +# endif +#endif + +#ifdef PNG_PEDANTIC_WARNINGS_SUPPORTED +/* Support for compiler specific function attributes. These are used + * so that where compiler support is available incorrect use of API + * functions in png.h will generate compiler warnings. Added at libpng + * version 1.2.41. + */ +# ifdef __GNUC__ +# ifndef PNG_USE_RESULT +# define PNG_USE_RESULT __attribute__((__warn_unused_result__)) +# endif +# ifndef PNG_NORETURN +# define PNG_NORETURN __attribute__((__noreturn__)) +# endif +# ifndef PNG_ALLOCATED +# define PNG_ALLOCATED __attribute__((__malloc__)) +# endif + + /* This specifically protects structure members that should only be + * accessed from within the library, therefore should be empty during + * a library build. + */ +# ifndef PNG_DEPRECATED +# define PNG_DEPRECATED __attribute__((__deprecated__)) +# endif +# ifndef PNG_DEPSTRUCT +# define PNG_DEPSTRUCT __attribute__((__deprecated__)) +# endif +# ifndef PNG_PRIVATE +# if 0 /* Doesn't work so we use deprecated instead*/ +# define PNG_PRIVATE \ + __attribute__((warning("This function is not exported by libpng."))) +# else +# define PNG_PRIVATE \ + __attribute__((__deprecated__)) +# endif +# endif /* PNG_PRIVATE */ +# endif /* __GNUC__ */ +#endif /* PNG_PEDANTIC_WARNINGS */ + +#ifndef PNG_DEPRECATED +# define PNG_DEPRECATED /* Use of this function is deprecated */ +#endif +#ifndef PNG_USE_RESULT +# define PNG_USE_RESULT /* The result of this function must be checked */ +#endif +#ifndef PNG_NORETURN +# define PNG_NORETURN /* This function does not return */ +#endif +#ifndef PNG_ALLOCATED +# define PNG_ALLOCATED /* The result of the function is new memory */ +#endif +#ifndef PNG_DEPSTRUCT +# define PNG_DEPSTRUCT /* Access to this struct member is deprecated */ +#endif +#ifndef PNG_PRIVATE +# define PNG_PRIVATE /* This is a private libpng function */ +#endif + +/* Users may want to use these so they are not private. Any library + * functions that are passed far data must be model-independent. + */ + +/* memory model/platform independent fns */ +#ifndef PNG_ABORT +# ifdef _WINDOWS_ +# define PNG_ABORT() ExitProcess(0) +# else +# define PNG_ABORT() abort() +# endif +#endif + +#ifdef USE_FAR_KEYWORD +/* Use this to make far-to-near assignments */ +# define CHECK 1 +# define NOCHECK 0 +# define CVT_PTR(ptr) (png_far_to_near(png_ptr,ptr,CHECK)) +# define CVT_PTR_NOCHECK(ptr) (png_far_to_near(png_ptr,ptr,NOCHECK)) +# define png_strcpy _fstrcpy +# define png_strncpy _fstrncpy /* Added to v 1.2.6 */ +# define png_strlen _fstrlen +# define png_memcmp _fmemcmp /* SJT: added */ +# define png_memcpy _fmemcpy +# define png_memset _fmemset +# define png_sprintf sprintf +#else +# ifdef _WINDOWS_ /* Favor Windows over C runtime fns */ +# define CVT_PTR(ptr) (ptr) +# define CVT_PTR_NOCHECK(ptr) (ptr) +# define png_strcpy lstrcpyA +# define png_strncpy lstrcpynA +# define png_strlen lstrlenA +# define png_memcmp memcmp +# define png_memcpy CopyMemory +# define png_memset memset +# define png_sprintf wsprintfA +# else +# define CVT_PTR(ptr) (ptr) +# define CVT_PTR_NOCHECK(ptr) (ptr) +# define png_strcpy strcpy +# define png_strncpy strncpy /* Added to v 1.2.6 */ +# define png_strlen strlen +# define png_memcmp memcmp /* SJT: added */ +# define png_memcpy memcpy +# define png_memset memset +# define png_sprintf sprintf +# ifndef PNG_NO_SNPRINTF +# ifdef _MSC_VER +# define png_snprintf _snprintf /* Added to v 1.2.19 */ +# define png_snprintf2 _snprintf +# define png_snprintf6 _snprintf +# else +# define png_snprintf snprintf /* Added to v 1.2.19 */ +# define png_snprintf2 snprintf +# define png_snprintf6 snprintf +# endif +# else + /* You don't have or don't want to use snprintf(). Caution: Using + * sprintf instead of snprintf exposes your application to accidental + * or malevolent buffer overflows. If you don't have snprintf() + * as a general rule you should provide one (you can get one from + * Portable OpenSSH). + */ +# define png_snprintf(s1,n,fmt,x1) sprintf(s1,fmt,x1) +# define png_snprintf2(s1,n,fmt,x1,x2) sprintf(s1,fmt,x1,x2) +# define png_snprintf6(s1,n,fmt,x1,x2,x3,x4,x5,x6) \ + sprintf(s1,fmt,x1,x2,x3,x4,x5,x6) +# endif +# endif +#endif + +/* png_alloc_size_t is guaranteed to be no smaller than png_size_t, + * and no smaller than png_uint_32. Casts from png_size_t or png_uint_32 + * to png_alloc_size_t are not necessary; in fact, it is recommended + * not to use them at all so that the compiler can complain when something + * turns out to be problematic. + * Casts in the other direction (from png_alloc_size_t to png_size_t or + * png_uint_32) should be explicitly applied; however, we do not expect + * to encounter practical situations that require such conversions. + */ +#if defined(__TURBOC__) && !defined(__FLAT__) +# define png_mem_alloc farmalloc +# define png_mem_free farfree + typedef unsigned long png_alloc_size_t; +#else +# if defined(_MSC_VER) && defined(MAXSEG_64K) +# define png_mem_alloc(s) halloc(s, 1) +# define png_mem_free hfree + typedef unsigned long png_alloc_size_t; +# else +# if defined(_WINDOWS_) && (!defined(INT_MAX) || INT_MAX <= 0x7ffffffeL) +# define png_mem_alloc(s) HeapAlloc(GetProcessHeap(), 0, s) +# define png_mem_free(p) HeapFree(GetProcessHeap(), 0, p) + typedef DWORD png_alloc_size_t; +# else +# define png_mem_alloc malloc +# define png_mem_free free + typedef png_size_t png_alloc_size_t; +# endif +# endif +#endif +/* End of memory model/platform independent support */ + +/* Just a little check that someone hasn't tried to define something + * contradictory. + */ +#if (PNG_ZBUF_SIZE > 65536L) && defined(PNG_MAX_MALLOC_64K) +# undef PNG_ZBUF_SIZE +# define PNG_ZBUF_SIZE 65536L +#endif + + +/* Added at libpng-1.2.8 */ +#endif /* PNG_VERSION_INFO_ONLY */ + +#endif /* PNGCONF_H */ diff --git a/reactos/include/reactos/libs/libpng/pngpriv.h b/reactos/include/reactos/libs/libpng/pngpriv.h new file mode 100644 index 00000000000..19b797c7447 --- /dev/null +++ b/reactos/include/reactos/libs/libpng/pngpriv.h @@ -0,0 +1,956 @@ + +/* pngpriv.h - private declarations for use inside libpng + * + * libpng version 1.4.3 - June 26, 2010 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2010 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +/* The symbols declared in this file (including the functions declared + * as PNG_EXTERN) are PRIVATE. They are not part of the libpng public + * interface, and are not recommended for use by regular applications. + * Some of them may become public in the future; others may stay private, + * change in an incompatible way, or even disappear. + * Although the libpng users are not forbidden to include this header, + * they should be well aware of the issues that may arise from doing so. + */ + +#ifndef PNGPRIV_H +#define PNGPRIV_H + +#ifndef PNG_VERSION_INFO_ONLY + +#include + +/* The functions exported by PNG_EXTERN are internal functions, which + * aren't usually used outside the library (as far as I know), so it is + * debatable if they should be exported at all. In the future, when it + * is possible to have run-time registry of chunk-handling functions, + * some of these will be made available again. +#define PNG_EXTERN extern + */ +#define PNG_EXTERN + +/* Other defines specific to compilers can go here. Try to keep + * them inside an appropriate ifdef/endif pair for portability. + */ + +#ifdef PNG_FLOATING_POINT_SUPPORTED +# ifdef MACOS + /* We need to check that hasn't already been included earlier + * as it seems it doesn't agree with , yet we should really use + * if possible. + */ +# if !defined(__MATH_H__) && !defined(__MATH_H) && !defined(__cmath__) +# include +# endif +# else +# include +# endif +# if defined(_AMIGA) && defined(__SASC) && defined(_M68881) + /* Amiga SAS/C: We must include builtin FPU functions when compiling using + * MATH=68881 + */ +# include +# endif +#endif + +/* Codewarrior on NT has linking problems without this. */ +#if (defined(__MWERKS__) && defined(WIN32)) || defined(__STDC__) +# define PNG_ALWAYS_EXTERN +#endif + +/* This provides the non-ANSI (far) memory allocation routines. */ +#if defined(__TURBOC__) && defined(__MSDOS__) +# include +# include +#endif + +#if defined(WIN32) || defined(_Windows) || defined(_WINDOWS) || \ + defined(_WIN32) || defined(__WIN32__) +# include /* defines _WINDOWS_ macro */ +/* I have no idea why is this necessary... */ +# ifdef _MSC_VER +# include +# endif +#endif + +/* Various modes of operation. Note that after an init, mode is set to + * zero automatically when the structure is created. + */ +#define PNG_HAVE_IHDR 0x01 +#define PNG_HAVE_PLTE 0x02 +#define PNG_HAVE_IDAT 0x04 +#define PNG_AFTER_IDAT 0x08 /* Have complete zlib datastream */ +#define PNG_HAVE_IEND 0x10 +#define PNG_HAVE_gAMA 0x20 +#define PNG_HAVE_cHRM 0x40 +#define PNG_HAVE_sRGB 0x80 +#define PNG_HAVE_CHUNK_HEADER 0x100 +#define PNG_WROTE_tIME 0x200 +#define PNG_WROTE_INFO_BEFORE_PLTE 0x400 +#define PNG_BACKGROUND_IS_GRAY 0x800 +#define PNG_HAVE_PNG_SIGNATURE 0x1000 +#define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000 /* Have another chunk after IDAT */ + +/* Flags for the transformations the PNG library does on the image data */ +#define PNG_BGR 0x0001 +#define PNG_INTERLACE 0x0002 +#define PNG_PACK 0x0004 +#define PNG_SHIFT 0x0008 +#define PNG_SWAP_BYTES 0x0010 +#define PNG_INVERT_MONO 0x0020 +#define PNG_QUANTIZE 0x0040 /* formerly PNG_DITHER */ +#define PNG_BACKGROUND 0x0080 +#define PNG_BACKGROUND_EXPAND 0x0100 + /* 0x0200 unused */ +#define PNG_16_TO_8 0x0400 +#define PNG_RGBA 0x0800 +#define PNG_EXPAND 0x1000 +#define PNG_GAMMA 0x2000 +#define PNG_GRAY_TO_RGB 0x4000 +#define PNG_FILLER 0x8000L +#define PNG_PACKSWAP 0x10000L +#define PNG_SWAP_ALPHA 0x20000L +#define PNG_STRIP_ALPHA 0x40000L +#define PNG_INVERT_ALPHA 0x80000L +#define PNG_USER_TRANSFORM 0x100000L +#define PNG_RGB_TO_GRAY_ERR 0x200000L +#define PNG_RGB_TO_GRAY_WARN 0x400000L +#define PNG_RGB_TO_GRAY 0x600000L /* two bits, RGB_TO_GRAY_ERR|WARN */ + /* 0x800000L Unused */ +#define PNG_ADD_ALPHA 0x1000000L /* Added to libpng-1.2.7 */ +#define PNG_EXPAND_tRNS 0x2000000L /* Added to libpng-1.2.9 */ + /* 0x4000000L unused */ + /* 0x8000000L unused */ + /* 0x10000000L unused */ + /* 0x20000000L unused */ + /* 0x40000000L unused */ + +/* Flags for png_create_struct */ +#define PNG_STRUCT_PNG 0x0001 +#define PNG_STRUCT_INFO 0x0002 + +/* Scaling factor for filter heuristic weighting calculations */ +#define PNG_WEIGHT_SHIFT 8 +#define PNG_WEIGHT_FACTOR (1<<(PNG_WEIGHT_SHIFT)) +#define PNG_COST_SHIFT 3 +#define PNG_COST_FACTOR (1<<(PNG_COST_SHIFT)) + +/* Flags for the png_ptr->flags rather than declaring a byte for each one */ +#define PNG_FLAG_ZLIB_CUSTOM_STRATEGY 0x0001 +#define PNG_FLAG_ZLIB_CUSTOM_LEVEL 0x0002 +#define PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL 0x0004 +#define PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS 0x0008 +#define PNG_FLAG_ZLIB_CUSTOM_METHOD 0x0010 +#define PNG_FLAG_ZLIB_FINISHED 0x0020 +#define PNG_FLAG_ROW_INIT 0x0040 +#define PNG_FLAG_FILLER_AFTER 0x0080 +#define PNG_FLAG_CRC_ANCILLARY_USE 0x0100 +#define PNG_FLAG_CRC_ANCILLARY_NOWARN 0x0200 +#define PNG_FLAG_CRC_CRITICAL_USE 0x0400 +#define PNG_FLAG_CRC_CRITICAL_IGNORE 0x0800 + /* 0x1000 unused */ + /* 0x2000 unused */ + /* 0x4000 unused */ +#define PNG_FLAG_KEEP_UNKNOWN_CHUNKS 0x8000L +#define PNG_FLAG_KEEP_UNSAFE_CHUNKS 0x10000L +#define PNG_FLAG_LIBRARY_MISMATCH 0x20000L +#define PNG_FLAG_STRIP_ERROR_NUMBERS 0x40000L +#define PNG_FLAG_STRIP_ERROR_TEXT 0x80000L +#define PNG_FLAG_MALLOC_NULL_MEM_OK 0x100000L +#define PNG_FLAG_ADD_ALPHA 0x200000L /* Added to libpng-1.2.8 */ +#define PNG_FLAG_STRIP_ALPHA 0x400000L /* Added to libpng-1.2.8 */ +#define PNG_FLAG_BENIGN_ERRORS_WARN 0x800000L /* Added to libpng-1.4.0 */ + /* 0x1000000L unused */ + /* 0x2000000L unused */ + /* 0x4000000L unused */ + /* 0x8000000L unused */ + /* 0x10000000L unused */ + /* 0x20000000L unused */ + /* 0x40000000L unused */ + +#define PNG_FLAG_CRC_ANCILLARY_MASK (PNG_FLAG_CRC_ANCILLARY_USE | \ + PNG_FLAG_CRC_ANCILLARY_NOWARN) + +#define PNG_FLAG_CRC_CRITICAL_MASK (PNG_FLAG_CRC_CRITICAL_USE | \ + PNG_FLAG_CRC_CRITICAL_IGNORE) + +#define PNG_FLAG_CRC_MASK (PNG_FLAG_CRC_ANCILLARY_MASK | \ + PNG_FLAG_CRC_CRITICAL_MASK) + +/* Save typing and make code easier to understand */ + +#define PNG_COLOR_DIST(c1, c2) (abs((int)((c1).red) - (int)((c2).red)) + \ + abs((int)((c1).green) - (int)((c2).green)) + \ + abs((int)((c1).blue) - (int)((c2).blue))) + +/* Added to libpng-1.2.6 JB */ +#define PNG_ROWBYTES(pixel_bits, width) \ + ((pixel_bits) >= 8 ? \ + ((png_size_t)(width) * (((png_size_t)(pixel_bits)) >> 3)) : \ + (( ((png_size_t)(width) * ((png_size_t)(pixel_bits))) + 7) >> 3) ) + +/* PNG_OUT_OF_RANGE returns true if value is outside the range + * ideal-delta..ideal+delta. Each argument is evaluated twice. + * "ideal" and "delta" should be constants, normally simple + * integers, "value" a variable. Added to libpng-1.2.6 JB + */ +#define PNG_OUT_OF_RANGE(value, ideal, delta) \ + ( (value) < (ideal)-(delta) || (value) > (ideal)+(delta) ) + +/* Constant strings for known chunk types. If you need to add a chunk, + * define the name here, and add an invocation of the macro wherever it's + * needed. + */ +#define PNG_IHDR PNG_CONST png_byte png_IHDR[5] = { 73, 72, 68, 82, '\0'} +#define PNG_IDAT PNG_CONST png_byte png_IDAT[5] = { 73, 68, 65, 84, '\0'} +#define PNG_IEND PNG_CONST png_byte png_IEND[5] = { 73, 69, 78, 68, '\0'} +#define PNG_PLTE PNG_CONST png_byte png_PLTE[5] = { 80, 76, 84, 69, '\0'} +#define PNG_bKGD PNG_CONST png_byte png_bKGD[5] = { 98, 75, 71, 68, '\0'} +#define PNG_cHRM PNG_CONST png_byte png_cHRM[5] = { 99, 72, 82, 77, '\0'} +#define PNG_gAMA PNG_CONST png_byte png_gAMA[5] = {103, 65, 77, 65, '\0'} +#define PNG_hIST PNG_CONST png_byte png_hIST[5] = {104, 73, 83, 84, '\0'} +#define PNG_iCCP PNG_CONST png_byte png_iCCP[5] = {105, 67, 67, 80, '\0'} +#define PNG_iTXt PNG_CONST png_byte png_iTXt[5] = {105, 84, 88, 116, '\0'} +#define PNG_oFFs PNG_CONST png_byte png_oFFs[5] = {111, 70, 70, 115, '\0'} +#define PNG_pCAL PNG_CONST png_byte png_pCAL[5] = {112, 67, 65, 76, '\0'} +#define PNG_sCAL PNG_CONST png_byte png_sCAL[5] = {115, 67, 65, 76, '\0'} +#define PNG_pHYs PNG_CONST png_byte png_pHYs[5] = {112, 72, 89, 115, '\0'} +#define PNG_sBIT PNG_CONST png_byte png_sBIT[5] = {115, 66, 73, 84, '\0'} +#define PNG_sPLT PNG_CONST png_byte png_sPLT[5] = {115, 80, 76, 84, '\0'} +#define PNG_sRGB PNG_CONST png_byte png_sRGB[5] = {115, 82, 71, 66, '\0'} +#define PNG_sTER PNG_CONST png_byte png_sTER[5] = {115, 84, 69, 82, '\0'} +#define PNG_tEXt PNG_CONST png_byte png_tEXt[5] = {116, 69, 88, 116, '\0'} +#define PNG_tIME PNG_CONST png_byte png_tIME[5] = {116, 73, 77, 69, '\0'} +#define PNG_tRNS PNG_CONST png_byte png_tRNS[5] = {116, 82, 78, 83, '\0'} +#define PNG_zTXt PNG_CONST png_byte png_zTXt[5] = {122, 84, 88, 116, '\0'} + + +/* Inhibit C++ name-mangling for libpng functions but not for system calls. */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* These functions are used internally in the code. They generally + * shouldn't be used unless you are writing code to add or replace some + * functionality in libpng. More information about most functions can + * be found in the files where the functions are located. + */ + +/* Allocate memory for an internal libpng struct */ +PNG_EXTERN png_voidp png_create_struct PNGARG((int type)); + +/* Free memory from internal libpng struct */ +PNG_EXTERN void png_destroy_struct PNGARG((png_voidp struct_ptr)); + +PNG_EXTERN png_voidp png_create_struct_2 PNGARG((int type, png_malloc_ptr + malloc_fn, png_voidp mem_ptr)); +PNG_EXTERN void png_destroy_struct_2 PNGARG((png_voidp struct_ptr, + png_free_ptr free_fn, png_voidp mem_ptr)); + +/* Free any memory that info_ptr points to and reset struct. */ +PNG_EXTERN void png_info_destroy PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +/* Function to allocate memory for zlib. PNGAPI is disallowed. */ +PNG_EXTERN voidpf png_zalloc PNGARG((voidpf png_ptr, uInt items, uInt size)); + +/* Function to free memory for zlib. PNGAPI is disallowed. */ +PNG_EXTERN void png_zfree PNGARG((voidpf png_ptr, voidpf ptr)); + +/* Next four functions are used internally as callbacks. PNGAPI is required + * but not PNG_EXPORT. PNGAPI added at libpng version 1.2.3. */ + +PNG_EXTERN void PNGAPI png_default_read_data PNGARG((png_structp png_ptr, + png_bytep data, png_size_t length)); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +PNG_EXTERN void PNGAPI png_push_fill_buffer PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t length)); +#endif + +PNG_EXTERN void PNGAPI png_default_write_data PNGARG((png_structp png_ptr, + png_bytep data, png_size_t length)); + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +#ifdef PNG_STDIO_SUPPORTED +PNG_EXTERN void PNGAPI png_default_flush PNGARG((png_structp png_ptr)); +#endif +#endif + +/* Reset the CRC variable */ +PNG_EXTERN void png_reset_crc PNGARG((png_structp png_ptr)); + +/* Write the "data" buffer to whatever output you are using */ +PNG_EXTERN void png_write_data PNGARG((png_structp png_ptr, png_bytep data, + png_size_t length)); + +/* Read the chunk header (length + type name) */ +PNG_EXTERN png_uint_32 png_read_chunk_header PNGARG((png_structp png_ptr)); + +/* Read data from whatever input you are using into the "data" buffer */ +PNG_EXTERN void png_read_data PNGARG((png_structp png_ptr, png_bytep data, + png_size_t length)); + +/* Read bytes into buf, and update png_ptr->crc */ +PNG_EXTERN void png_crc_read PNGARG((png_structp png_ptr, png_bytep buf, + png_size_t length)); + +/* Decompress data in a chunk that uses compression */ +#if defined(PNG_zTXt_SUPPORTED) || defined(PNG_iTXt_SUPPORTED) || \ + defined(PNG_iCCP_SUPPORTED) || defined(PNG_sPLT_SUPPORTED) +PNG_EXTERN void png_decompress_chunk PNGARG((png_structp png_ptr, + int comp_type, png_size_t chunklength, png_size_t prefix_length, + png_size_t *data_length)); +#endif + +/* Read "skip" bytes, read the file crc, and (optionally) verify png_ptr->crc */ +PNG_EXTERN int png_crc_finish PNGARG((png_structp png_ptr, png_uint_32 skip)); + +/* Read the CRC from the file and compare it to the libpng calculated CRC */ +PNG_EXTERN int png_crc_error PNGARG((png_structp png_ptr)); + +/* Calculate the CRC over a section of data. Note that we are only + * passing a maximum of 64K on systems that have this as a memory limit, + * since this is the maximum buffer size we can specify. + */ +PNG_EXTERN void png_calculate_crc PNGARG((png_structp png_ptr, png_bytep ptr, + png_size_t length)); + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +PNG_EXTERN void png_flush PNGARG((png_structp png_ptr)); +#endif + +/* Write various chunks */ + +/* Write the IHDR chunk, and update the png_struct with the necessary + * information. + */ +PNG_EXTERN void png_write_IHDR PNGARG((png_structp png_ptr, png_uint_32 width, + png_uint_32 height, + int bit_depth, int color_type, int compression_method, int filter_method, + int interlace_method)); + +PNG_EXTERN void png_write_PLTE PNGARG((png_structp png_ptr, png_colorp palette, + png_uint_32 num_pal)); + +PNG_EXTERN void png_write_IDAT PNGARG((png_structp png_ptr, png_bytep data, + png_size_t length)); + +PNG_EXTERN void png_write_IEND PNGARG((png_structp png_ptr)); + +#ifdef PNG_WRITE_gAMA_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +PNG_EXTERN void png_write_gAMA PNGARG((png_structp png_ptr, double file_gamma)); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +PNG_EXTERN void png_write_gAMA_fixed PNGARG((png_structp png_ptr, + png_fixed_point file_gamma)); +#endif +#endif + +#ifdef PNG_WRITE_sBIT_SUPPORTED +PNG_EXTERN void png_write_sBIT PNGARG((png_structp png_ptr, png_color_8p sbit, + int color_type)); +#endif + +#ifdef PNG_WRITE_cHRM_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +PNG_EXTERN void png_write_cHRM PNGARG((png_structp png_ptr, + double white_x, double white_y, + double red_x, double red_y, double green_x, double green_y, + double blue_x, double blue_y)); +#endif +PNG_EXTERN void png_write_cHRM_fixed PNGARG((png_structp png_ptr, + png_fixed_point int_white_x, png_fixed_point int_white_y, + png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point + int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x, + png_fixed_point int_blue_y)); +#endif + +#ifdef PNG_WRITE_sRGB_SUPPORTED +PNG_EXTERN void png_write_sRGB PNGARG((png_structp png_ptr, + int intent)); +#endif + +#ifdef PNG_WRITE_iCCP_SUPPORTED +PNG_EXTERN void png_write_iCCP PNGARG((png_structp png_ptr, + png_charp name, int compression_type, + png_charp profile, int proflen)); + /* Note to maintainer: profile should be png_bytep */ +#endif + +#ifdef PNG_WRITE_sPLT_SUPPORTED +PNG_EXTERN void png_write_sPLT PNGARG((png_structp png_ptr, + png_sPLT_tp palette)); +#endif + +#ifdef PNG_WRITE_tRNS_SUPPORTED +PNG_EXTERN void png_write_tRNS PNGARG((png_structp png_ptr, png_bytep trans, + png_color_16p values, int number, int color_type)); +#endif + +#ifdef PNG_WRITE_bKGD_SUPPORTED +PNG_EXTERN void png_write_bKGD PNGARG((png_structp png_ptr, + png_color_16p values, int color_type)); +#endif + +#ifdef PNG_WRITE_hIST_SUPPORTED +PNG_EXTERN void png_write_hIST PNGARG((png_structp png_ptr, png_uint_16p hist, + int num_hist)); +#endif + +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \ + defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) +PNG_EXTERN png_size_t png_check_keyword PNGARG((png_structp png_ptr, + png_charp key, png_charpp new_key)); +#endif + +#ifdef PNG_WRITE_tEXt_SUPPORTED +PNG_EXTERN void png_write_tEXt PNGARG((png_structp png_ptr, png_charp key, + png_charp text, png_size_t text_len)); +#endif + +#ifdef PNG_WRITE_zTXt_SUPPORTED +PNG_EXTERN void png_write_zTXt PNGARG((png_structp png_ptr, png_charp key, + png_charp text, png_size_t text_len, int compression)); +#endif + +#ifdef PNG_WRITE_iTXt_SUPPORTED +PNG_EXTERN void png_write_iTXt PNGARG((png_structp png_ptr, + int compression, png_charp key, png_charp lang, png_charp lang_key, + png_charp text)); +#endif + +#ifdef PNG_TEXT_SUPPORTED /* Added at version 1.0.14 and 1.2.4 */ +PNG_EXTERN int png_set_text_2 PNGARG((png_structp png_ptr, + png_infop info_ptr, png_textp text_ptr, int num_text)); +#endif + +#ifdef PNG_WRITE_oFFs_SUPPORTED +PNG_EXTERN void png_write_oFFs PNGARG((png_structp png_ptr, + png_int_32 x_offset, png_int_32 y_offset, int unit_type)); +#endif + +#ifdef PNG_WRITE_pCAL_SUPPORTED +PNG_EXTERN void png_write_pCAL PNGARG((png_structp png_ptr, png_charp purpose, + png_int_32 X0, png_int_32 X1, int type, int nparams, + png_charp units, png_charpp params)); +#endif + +#ifdef PNG_WRITE_pHYs_SUPPORTED +PNG_EXTERN void png_write_pHYs PNGARG((png_structp png_ptr, + png_uint_32 x_pixels_per_unit, png_uint_32 y_pixels_per_unit, + int unit_type)); +#endif + +#ifdef PNG_WRITE_tIME_SUPPORTED +PNG_EXTERN void png_write_tIME PNGARG((png_structp png_ptr, + png_timep mod_time)); +#endif + +#ifdef PNG_WRITE_sCAL_SUPPORTED +#if defined(PNG_FLOATING_POINT_SUPPORTED) && defined(PNG_STDIO_SUPPORTED) +PNG_EXTERN void png_write_sCAL PNGARG((png_structp png_ptr, + int unit, double width, double height)); +#else +#ifdef PNG_FIXED_POINT_SUPPORTED +PNG_EXTERN void png_write_sCAL_s PNGARG((png_structp png_ptr, + int unit, png_charp width, png_charp height)); +#endif +#endif +#endif + +/* Called when finished processing a row of data */ +PNG_EXTERN void png_write_finish_row PNGARG((png_structp png_ptr)); + +/* Internal use only. Called before first row of data */ +PNG_EXTERN void png_write_start_row PNGARG((png_structp png_ptr)); + +#ifdef PNG_READ_GAMMA_SUPPORTED +PNG_EXTERN void png_build_gamma_table PNGARG((png_structp png_ptr, + png_byte bit_depth)); +#endif + +/* Combine a row of data, dealing with alpha, etc. if requested */ +PNG_EXTERN void png_combine_row PNGARG((png_structp png_ptr, png_bytep row, + int mask)); + +#ifdef PNG_READ_INTERLACING_SUPPORTED +/* Expand an interlaced row */ +/* OLD pre-1.0.9 interface: +PNG_EXTERN void png_do_read_interlace PNGARG((png_row_infop row_info, + png_bytep row, int pass, png_uint_32 transformations)); + */ +PNG_EXTERN void png_do_read_interlace PNGARG((png_structp png_ptr)); +#endif + +/* GRR TO DO (2.0 or whenever): simplify other internal calling interfaces */ + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED +/* Grab pixels out of a row for an interlaced pass */ +PNG_EXTERN void png_do_write_interlace PNGARG((png_row_infop row_info, + png_bytep row, int pass)); +#endif + +/* Unfilter a row */ +PNG_EXTERN void png_read_filter_row PNGARG((png_structp png_ptr, + png_row_infop row_info, png_bytep row, png_bytep prev_row, int filter)); + +/* Choose the best filter to use and filter the row data */ +PNG_EXTERN void png_write_find_filter PNGARG((png_structp png_ptr, + png_row_infop row_info)); + +/* Write out the filtered row. */ +PNG_EXTERN void png_write_filtered_row PNGARG((png_structp png_ptr, + png_bytep filtered_row)); +/* Finish a row while reading, dealing with interlacing passes, etc. */ +PNG_EXTERN void png_read_finish_row PNGARG((png_structp png_ptr)); + +/* Initialize the row buffers, etc. */ +PNG_EXTERN void png_read_start_row PNGARG((png_structp png_ptr)); +/* Optional call to update the users info structure */ +PNG_EXTERN void png_read_transform_info PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +/* These are the functions that do the transformations */ +#ifdef PNG_READ_FILLER_SUPPORTED +PNG_EXTERN void png_do_read_filler PNGARG((png_row_infop row_info, + png_bytep row, png_uint_32 filler, png_uint_32 flags)); +#endif + +#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED +PNG_EXTERN void png_do_read_swap_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED +PNG_EXTERN void png_do_write_swap_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED +PNG_EXTERN void png_do_read_invert_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED +PNG_EXTERN void png_do_write_invert_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#if defined(PNG_WRITE_FILLER_SUPPORTED) || \ + defined(PNG_READ_STRIP_ALPHA_SUPPORTED) +PNG_EXTERN void png_do_strip_filler PNGARG((png_row_infop row_info, + png_bytep row, png_uint_32 flags)); +#endif + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +PNG_EXTERN void png_do_swap PNGARG((png_row_infop row_info, png_bytep row)); +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) || \ + defined(PNG_WRITE_PACKSWAP_SUPPORTED) +PNG_EXTERN void png_do_packswap PNGARG((png_row_infop row_info, png_bytep row)); +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +PNG_EXTERN int png_do_rgb_to_gray PNGARG((png_structp png_ptr, png_row_infop + row_info, png_bytep row)); +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED +PNG_EXTERN void png_do_gray_to_rgb PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#ifdef PNG_READ_PACK_SUPPORTED +PNG_EXTERN void png_do_unpack PNGARG((png_row_infop row_info, png_bytep row)); +#endif + +#ifdef PNG_READ_SHIFT_SUPPORTED +PNG_EXTERN void png_do_unshift PNGARG((png_row_infop row_info, png_bytep row, + png_color_8p sig_bits)); +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +PNG_EXTERN void png_do_invert PNGARG((png_row_infop row_info, png_bytep row)); +#endif + +#ifdef PNG_READ_16_TO_8_SUPPORTED +PNG_EXTERN void png_do_chop PNGARG((png_row_infop row_info, png_bytep row)); +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +PNG_EXTERN void png_do_quantize PNGARG((png_row_infop row_info, + png_bytep row, png_bytep palette_lookup, png_bytep quantize_lookup)); + +# ifdef PNG_CORRECT_PALETTE_SUPPORTED +PNG_EXTERN void png_correct_palette PNGARG((png_structp png_ptr, + png_colorp palette, int num_palette)); +# endif +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +PNG_EXTERN void png_do_bgr PNGARG((png_row_infop row_info, png_bytep row)); +#endif + +#ifdef PNG_WRITE_PACK_SUPPORTED +PNG_EXTERN void png_do_pack PNGARG((png_row_infop row_info, + png_bytep row, png_uint_32 bit_depth)); +#endif + +#ifdef PNG_WRITE_SHIFT_SUPPORTED +PNG_EXTERN void png_do_shift PNGARG((png_row_infop row_info, png_bytep row, + png_color_8p bit_depth)); +#endif + +#ifdef PNG_READ_BACKGROUND_SUPPORTED +#ifdef PNG_READ_GAMMA_SUPPORTED +PNG_EXTERN void png_do_background PNGARG((png_row_infop row_info, png_bytep row, + png_color_16p trans_color, png_color_16p background, + png_color_16p background_1, + png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1, + png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1, + png_uint_16pp gamma_16_to_1, int gamma_shift)); +#else +PNG_EXTERN void png_do_background PNGARG((png_row_infop row_info, png_bytep row, + png_color_16p trans_color, png_color_16p background)); +#endif +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED +PNG_EXTERN void png_do_gamma PNGARG((png_row_infop row_info, png_bytep row, + png_bytep gamma_table, png_uint_16pp gamma_16_table, + int gamma_shift)); +#endif + +#ifdef PNG_READ_EXPAND_SUPPORTED +PNG_EXTERN void png_do_expand_palette PNGARG((png_row_infop row_info, + png_bytep row, png_colorp palette, png_bytep trans, int num_trans)); +PNG_EXTERN void png_do_expand PNGARG((png_row_infop row_info, + png_bytep row, png_color_16p trans_value)); +#endif + +/* The following decodes the appropriate chunks, and does error correction, + * then calls the appropriate callback for the chunk if it is valid. + */ + +/* Decode the IHDR chunk */ +PNG_EXTERN void png_handle_IHDR PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +PNG_EXTERN void png_handle_PLTE PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +PNG_EXTERN void png_handle_IEND PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); + +#ifdef PNG_READ_bKGD_SUPPORTED +PNG_EXTERN void png_handle_bKGD PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_cHRM_SUPPORTED +PNG_EXTERN void png_handle_cHRM PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_gAMA_SUPPORTED +PNG_EXTERN void png_handle_gAMA PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_hIST_SUPPORTED +PNG_EXTERN void png_handle_hIST PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_iCCP_SUPPORTED +extern void png_handle_iCCP PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif /* PNG_READ_iCCP_SUPPORTED */ + +#ifdef PNG_READ_iTXt_SUPPORTED +PNG_EXTERN void png_handle_iTXt PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_oFFs_SUPPORTED +PNG_EXTERN void png_handle_oFFs PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_pCAL_SUPPORTED +PNG_EXTERN void png_handle_pCAL PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_pHYs_SUPPORTED +PNG_EXTERN void png_handle_pHYs PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_sBIT_SUPPORTED +PNG_EXTERN void png_handle_sBIT PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_sCAL_SUPPORTED +PNG_EXTERN void png_handle_sCAL PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_sPLT_SUPPORTED +extern void png_handle_sPLT PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif /* PNG_READ_sPLT_SUPPORTED */ + +#ifdef PNG_READ_sRGB_SUPPORTED +PNG_EXTERN void png_handle_sRGB PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_tEXt_SUPPORTED +PNG_EXTERN void png_handle_tEXt PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_tIME_SUPPORTED +PNG_EXTERN void png_handle_tIME PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_tRNS_SUPPORTED +PNG_EXTERN void png_handle_tRNS PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_zTXt_SUPPORTED +PNG_EXTERN void png_handle_zTXt PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +PNG_EXTERN void png_handle_unknown PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); + +PNG_EXTERN void png_check_chunk_name PNGARG((png_structp png_ptr, + png_bytep chunk_name)); + +/* Handle the transformations for reading and writing */ +PNG_EXTERN void png_do_read_transformations PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_do_write_transformations PNGARG((png_structp png_ptr)); + +PNG_EXTERN void png_init_read_transformations PNGARG((png_structp png_ptr)); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +PNG_EXTERN void png_push_read_chunk PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_read_sig PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_check_crc PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_crc_skip PNGARG((png_structp png_ptr, + png_uint_32 length)); +PNG_EXTERN void png_push_crc_finish PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_save_buffer PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_restore_buffer PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t buffer_length)); +PNG_EXTERN void png_push_read_IDAT PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_process_IDAT_data PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t buffer_length)); +PNG_EXTERN void png_push_process_row PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_handle_unknown PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_have_info PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_have_end PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_have_row PNGARG((png_structp png_ptr, png_bytep row)); +PNG_EXTERN void png_push_read_end PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_process_some_data PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_read_push_finish_row PNGARG((png_structp png_ptr)); +#ifdef PNG_READ_tEXt_SUPPORTED +PNG_EXTERN void png_push_handle_tEXt PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_read_tEXt PNGARG((png_structp png_ptr, + png_infop info_ptr)); +#endif +#ifdef PNG_READ_zTXt_SUPPORTED +PNG_EXTERN void png_push_handle_zTXt PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_read_zTXt PNGARG((png_structp png_ptr, + png_infop info_ptr)); +#endif +#ifdef PNG_READ_iTXt_SUPPORTED +PNG_EXTERN void png_push_handle_iTXt PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_read_iTXt PNGARG((png_structp png_ptr, + png_infop info_ptr)); +#endif + +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + +#ifdef PNG_MNG_FEATURES_SUPPORTED +PNG_EXTERN void png_do_read_intrapixel PNGARG((png_row_infop row_info, + png_bytep row)); +PNG_EXTERN void png_do_write_intrapixel PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +/* Added at libpng version 1.4.0 */ +#ifdef PNG_cHRM_SUPPORTED +PNG_EXTERN int png_check_cHRM_fixed PNGARG((png_structp png_ptr, + png_fixed_point int_white_x, png_fixed_point int_white_y, + png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point + int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x, + png_fixed_point int_blue_y)); +#endif + +#ifdef PNG_cHRM_SUPPORTED +#ifdef PNG_CHECK_cHRM_SUPPORTED +/* Added at libpng version 1.2.34 and 1.4.0 */ +PNG_EXTERN void png_64bit_product PNGARG((long v1, long v2, + unsigned long *hi_product, unsigned long *lo_product)); +#endif +#endif + +/* Added at libpng version 1.4.0 */ +PNG_EXTERN void png_check_IHDR PNGARG((png_structp png_ptr, + png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_type, int compression_type, + int filter_type)); + +/* Free all memory used by the read (old method - NOT DLL EXPORTED) */ +extern void png_read_destroy PNGARG((png_structp png_ptr, png_infop info_ptr, + png_infop end_info_ptr)); + +/* Free any memory used in png_ptr struct (old method - NOT DLL EXPORTED) */ +extern void png_write_destroy PNGARG((png_structp png_ptr)); + +#ifdef USE_FAR_KEYWORD /* memory model conversion function */ +extern void *png_far_to_near PNGARG((png_structp png_ptr,png_voidp ptr, + int check)); +#endif /* USE_FAR_KEYWORD */ + +/* Define PNG_DEBUG at compile time for debugging information. Higher + * numbers for PNG_DEBUG mean more debugging information. This has + * only been added since version 0.95 so it is not implemented throughout + * libpng yet, but more support will be added as needed. + */ +#ifdef PNG_DEBUG +#if (PNG_DEBUG > 0) +#if !defined(PNG_DEBUG_FILE) && defined(_MSC_VER) +#include +#if (PNG_DEBUG > 1) +#ifndef _DEBUG +# define _DEBUG +#endif +#ifndef png_debug +#define png_debug(l,m) _RPT0(_CRT_WARN,m PNG_STRING_NEWLINE) +#endif +#ifndef png_debug1 +#define png_debug1(l,m,p1) _RPT1(_CRT_WARN,m PNG_STRING_NEWLINE,p1) +#endif +#ifndef png_debug2 +#define png_debug2(l,m,p1,p2) _RPT2(_CRT_WARN,m PNG_STRING_NEWLINE,p1,p2) +#endif +#endif +#else /* PNG_DEBUG_FILE || !_MSC_VER */ +#ifndef PNG_DEBUG_FILE +#define PNG_DEBUG_FILE stderr +#endif /* PNG_DEBUG_FILE */ + +#if (PNG_DEBUG > 1) +/* Note: ["%s"m PNG_STRING_NEWLINE] probably does not work on + * non-ISO compilers + */ +# ifdef __STDC__ +# ifndef png_debug +# define png_debug(l,m) \ + { \ + int num_tabs=l; \ + fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":"")))); \ + } +# endif +# ifndef png_debug1 +# define png_debug1(l,m,p1) \ + { \ + int num_tabs=l; \ + fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1); \ + } +# endif +# ifndef png_debug2 +# define png_debug2(l,m,p1,p2) \ + { \ + int num_tabs=l; \ + fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1,p2); \ + } +# endif +# else /* __STDC __ */ +# ifndef png_debug +# define png_debug(l,m) \ + { \ + int num_tabs=l; \ + char format[256]; \ + snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \ + m,PNG_STRING_NEWLINE); \ + fprintf(PNG_DEBUG_FILE,format); \ + } +# endif +# ifndef png_debug1 +# define png_debug1(l,m,p1) \ + { \ + int num_tabs=l; \ + char format[256]; \ + snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \ + m,PNG_STRING_NEWLINE); \ + fprintf(PNG_DEBUG_FILE,format,p1); \ + } +# endif +# ifndef png_debug2 +# define png_debug2(l,m,p1,p2) \ + { \ + int num_tabs=l; \ + char format[256]; \ + snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \ + m,PNG_STRING_NEWLINE); \ + fprintf(PNG_DEBUG_FILE,format,p1,p2); \ + } +# endif +# endif /* __STDC __ */ +#endif /* (PNG_DEBUG > 1) */ + +#endif /* _MSC_VER */ +#endif /* (PNG_DEBUG > 0) */ +#endif /* PNG_DEBUG */ +#ifndef png_debug +#define png_debug(l, m) +#endif +#ifndef png_debug1 +#define png_debug1(l, m, p1) +#endif +#ifndef png_debug2 +#define png_debug2(l, m, p1, p2) +#endif + +/* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */ + +#ifdef __cplusplus +} +#endif + +#endif /* PNG_VERSION_INFO_ONLY */ +#endif /* PNGPRIV_H */ diff --git a/reactos/include/reactos/libs/libtiff/t4.h b/reactos/include/reactos/libs/libtiff/t4.h new file mode 100644 index 00000000000..870704ffe8a --- /dev/null +++ b/reactos/include/reactos/libs/libtiff/t4.h @@ -0,0 +1,292 @@ +/* $Id: t4.h,v 1.1.1.1.2.1 2010-06-08 18:50:41 bfriesen Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _T4_ +#define _T4_ +/* + * CCITT T.4 1D Huffman runlength codes and + * related definitions. Given the small sizes + * of these tables it does not seem + * worthwhile to make code & length 8 bits. + */ +typedef struct tableentry { + unsigned short length; /* bit length of g3 code */ + unsigned short code; /* g3 code */ + short runlen; /* run length in bits */ +} tableentry; + +#define EOL 0x001 /* EOL code value - 0000 0000 0000 1 */ + +/* status values returned instead of a run length */ +#define G3CODE_EOL -1 /* NB: ACT_EOL - ACT_WRUNT */ +#define G3CODE_INVALID -2 /* NB: ACT_INVALID - ACT_WRUNT */ +#define G3CODE_EOF -3 /* end of input data */ +#define G3CODE_INCOMP -4 /* incomplete run code */ + +/* + * Note that these tables are ordered such that the + * index into the table is known to be either the + * run length, or (run length / 64) + a fixed offset. + * + * NB: The G3CODE_INVALID entries are only used + * during state generation (see mkg3states.c). + */ +#ifdef G3CODES +const tableentry TIFFFaxWhiteCodes[] = { + { 8, 0x35, 0 }, /* 0011 0101 */ + { 6, 0x7, 1 }, /* 0001 11 */ + { 4, 0x7, 2 }, /* 0111 */ + { 4, 0x8, 3 }, /* 1000 */ + { 4, 0xB, 4 }, /* 1011 */ + { 4, 0xC, 5 }, /* 1100 */ + { 4, 0xE, 6 }, /* 1110 */ + { 4, 0xF, 7 }, /* 1111 */ + { 5, 0x13, 8 }, /* 1001 1 */ + { 5, 0x14, 9 }, /* 1010 0 */ + { 5, 0x7, 10 }, /* 0011 1 */ + { 5, 0x8, 11 }, /* 0100 0 */ + { 6, 0x8, 12 }, /* 0010 00 */ + { 6, 0x3, 13 }, /* 0000 11 */ + { 6, 0x34, 14 }, /* 1101 00 */ + { 6, 0x35, 15 }, /* 1101 01 */ + { 6, 0x2A, 16 }, /* 1010 10 */ + { 6, 0x2B, 17 }, /* 1010 11 */ + { 7, 0x27, 18 }, /* 0100 111 */ + { 7, 0xC, 19 }, /* 0001 100 */ + { 7, 0x8, 20 }, /* 0001 000 */ + { 7, 0x17, 21 }, /* 0010 111 */ + { 7, 0x3, 22 }, /* 0000 011 */ + { 7, 0x4, 23 }, /* 0000 100 */ + { 7, 0x28, 24 }, /* 0101 000 */ + { 7, 0x2B, 25 }, /* 0101 011 */ + { 7, 0x13, 26 }, /* 0010 011 */ + { 7, 0x24, 27 }, /* 0100 100 */ + { 7, 0x18, 28 }, /* 0011 000 */ + { 8, 0x2, 29 }, /* 0000 0010 */ + { 8, 0x3, 30 }, /* 0000 0011 */ + { 8, 0x1A, 31 }, /* 0001 1010 */ + { 8, 0x1B, 32 }, /* 0001 1011 */ + { 8, 0x12, 33 }, /* 0001 0010 */ + { 8, 0x13, 34 }, /* 0001 0011 */ + { 8, 0x14, 35 }, /* 0001 0100 */ + { 8, 0x15, 36 }, /* 0001 0101 */ + { 8, 0x16, 37 }, /* 0001 0110 */ + { 8, 0x17, 38 }, /* 0001 0111 */ + { 8, 0x28, 39 }, /* 0010 1000 */ + { 8, 0x29, 40 }, /* 0010 1001 */ + { 8, 0x2A, 41 }, /* 0010 1010 */ + { 8, 0x2B, 42 }, /* 0010 1011 */ + { 8, 0x2C, 43 }, /* 0010 1100 */ + { 8, 0x2D, 44 }, /* 0010 1101 */ + { 8, 0x4, 45 }, /* 0000 0100 */ + { 8, 0x5, 46 }, /* 0000 0101 */ + { 8, 0xA, 47 }, /* 0000 1010 */ + { 8, 0xB, 48 }, /* 0000 1011 */ + { 8, 0x52, 49 }, /* 0101 0010 */ + { 8, 0x53, 50 }, /* 0101 0011 */ + { 8, 0x54, 51 }, /* 0101 0100 */ + { 8, 0x55, 52 }, /* 0101 0101 */ + { 8, 0x24, 53 }, /* 0010 0100 */ + { 8, 0x25, 54 }, /* 0010 0101 */ + { 8, 0x58, 55 }, /* 0101 1000 */ + { 8, 0x59, 56 }, /* 0101 1001 */ + { 8, 0x5A, 57 }, /* 0101 1010 */ + { 8, 0x5B, 58 }, /* 0101 1011 */ + { 8, 0x4A, 59 }, /* 0100 1010 */ + { 8, 0x4B, 60 }, /* 0100 1011 */ + { 8, 0x32, 61 }, /* 0011 0010 */ + { 8, 0x33, 62 }, /* 0011 0011 */ + { 8, 0x34, 63 }, /* 0011 0100 */ + { 5, 0x1B, 64 }, /* 1101 1 */ + { 5, 0x12, 128 }, /* 1001 0 */ + { 6, 0x17, 192 }, /* 0101 11 */ + { 7, 0x37, 256 }, /* 0110 111 */ + { 8, 0x36, 320 }, /* 0011 0110 */ + { 8, 0x37, 384 }, /* 0011 0111 */ + { 8, 0x64, 448 }, /* 0110 0100 */ + { 8, 0x65, 512 }, /* 0110 0101 */ + { 8, 0x68, 576 }, /* 0110 1000 */ + { 8, 0x67, 640 }, /* 0110 0111 */ + { 9, 0xCC, 704 }, /* 0110 0110 0 */ + { 9, 0xCD, 768 }, /* 0110 0110 1 */ + { 9, 0xD2, 832 }, /* 0110 1001 0 */ + { 9, 0xD3, 896 }, /* 0110 1001 1 */ + { 9, 0xD4, 960 }, /* 0110 1010 0 */ + { 9, 0xD5, 1024 }, /* 0110 1010 1 */ + { 9, 0xD6, 1088 }, /* 0110 1011 0 */ + { 9, 0xD7, 1152 }, /* 0110 1011 1 */ + { 9, 0xD8, 1216 }, /* 0110 1100 0 */ + { 9, 0xD9, 1280 }, /* 0110 1100 1 */ + { 9, 0xDA, 1344 }, /* 0110 1101 0 */ + { 9, 0xDB, 1408 }, /* 0110 1101 1 */ + { 9, 0x98, 1472 }, /* 0100 1100 0 */ + { 9, 0x99, 1536 }, /* 0100 1100 1 */ + { 9, 0x9A, 1600 }, /* 0100 1101 0 */ + { 6, 0x18, 1664 }, /* 0110 00 */ + { 9, 0x9B, 1728 }, /* 0100 1101 1 */ + { 11, 0x8, 1792 }, /* 0000 0001 000 */ + { 11, 0xC, 1856 }, /* 0000 0001 100 */ + { 11, 0xD, 1920 }, /* 0000 0001 101 */ + { 12, 0x12, 1984 }, /* 0000 0001 0010 */ + { 12, 0x13, 2048 }, /* 0000 0001 0011 */ + { 12, 0x14, 2112 }, /* 0000 0001 0100 */ + { 12, 0x15, 2176 }, /* 0000 0001 0101 */ + { 12, 0x16, 2240 }, /* 0000 0001 0110 */ + { 12, 0x17, 2304 }, /* 0000 0001 0111 */ + { 12, 0x1C, 2368 }, /* 0000 0001 1100 */ + { 12, 0x1D, 2432 }, /* 0000 0001 1101 */ + { 12, 0x1E, 2496 }, /* 0000 0001 1110 */ + { 12, 0x1F, 2560 }, /* 0000 0001 1111 */ + { 12, 0x1, G3CODE_EOL }, /* 0000 0000 0001 */ + { 9, 0x1, G3CODE_INVALID }, /* 0000 0000 1 */ + { 10, 0x1, G3CODE_INVALID }, /* 0000 0000 01 */ + { 11, 0x1, G3CODE_INVALID }, /* 0000 0000 001 */ + { 12, 0x0, G3CODE_INVALID }, /* 0000 0000 0000 */ +}; + +const tableentry TIFFFaxBlackCodes[] = { + { 10, 0x37, 0 }, /* 0000 1101 11 */ + { 3, 0x2, 1 }, /* 010 */ + { 2, 0x3, 2 }, /* 11 */ + { 2, 0x2, 3 }, /* 10 */ + { 3, 0x3, 4 }, /* 011 */ + { 4, 0x3, 5 }, /* 0011 */ + { 4, 0x2, 6 }, /* 0010 */ + { 5, 0x3, 7 }, /* 0001 1 */ + { 6, 0x5, 8 }, /* 0001 01 */ + { 6, 0x4, 9 }, /* 0001 00 */ + { 7, 0x4, 10 }, /* 0000 100 */ + { 7, 0x5, 11 }, /* 0000 101 */ + { 7, 0x7, 12 }, /* 0000 111 */ + { 8, 0x4, 13 }, /* 0000 0100 */ + { 8, 0x7, 14 }, /* 0000 0111 */ + { 9, 0x18, 15 }, /* 0000 1100 0 */ + { 10, 0x17, 16 }, /* 0000 0101 11 */ + { 10, 0x18, 17 }, /* 0000 0110 00 */ + { 10, 0x8, 18 }, /* 0000 0010 00 */ + { 11, 0x67, 19 }, /* 0000 1100 111 */ + { 11, 0x68, 20 }, /* 0000 1101 000 */ + { 11, 0x6C, 21 }, /* 0000 1101 100 */ + { 11, 0x37, 22 }, /* 0000 0110 111 */ + { 11, 0x28, 23 }, /* 0000 0101 000 */ + { 11, 0x17, 24 }, /* 0000 0010 111 */ + { 11, 0x18, 25 }, /* 0000 0011 000 */ + { 12, 0xCA, 26 }, /* 0000 1100 1010 */ + { 12, 0xCB, 27 }, /* 0000 1100 1011 */ + { 12, 0xCC, 28 }, /* 0000 1100 1100 */ + { 12, 0xCD, 29 }, /* 0000 1100 1101 */ + { 12, 0x68, 30 }, /* 0000 0110 1000 */ + { 12, 0x69, 31 }, /* 0000 0110 1001 */ + { 12, 0x6A, 32 }, /* 0000 0110 1010 */ + { 12, 0x6B, 33 }, /* 0000 0110 1011 */ + { 12, 0xD2, 34 }, /* 0000 1101 0010 */ + { 12, 0xD3, 35 }, /* 0000 1101 0011 */ + { 12, 0xD4, 36 }, /* 0000 1101 0100 */ + { 12, 0xD5, 37 }, /* 0000 1101 0101 */ + { 12, 0xD6, 38 }, /* 0000 1101 0110 */ + { 12, 0xD7, 39 }, /* 0000 1101 0111 */ + { 12, 0x6C, 40 }, /* 0000 0110 1100 */ + { 12, 0x6D, 41 }, /* 0000 0110 1101 */ + { 12, 0xDA, 42 }, /* 0000 1101 1010 */ + { 12, 0xDB, 43 }, /* 0000 1101 1011 */ + { 12, 0x54, 44 }, /* 0000 0101 0100 */ + { 12, 0x55, 45 }, /* 0000 0101 0101 */ + { 12, 0x56, 46 }, /* 0000 0101 0110 */ + { 12, 0x57, 47 }, /* 0000 0101 0111 */ + { 12, 0x64, 48 }, /* 0000 0110 0100 */ + { 12, 0x65, 49 }, /* 0000 0110 0101 */ + { 12, 0x52, 50 }, /* 0000 0101 0010 */ + { 12, 0x53, 51 }, /* 0000 0101 0011 */ + { 12, 0x24, 52 }, /* 0000 0010 0100 */ + { 12, 0x37, 53 }, /* 0000 0011 0111 */ + { 12, 0x38, 54 }, /* 0000 0011 1000 */ + { 12, 0x27, 55 }, /* 0000 0010 0111 */ + { 12, 0x28, 56 }, /* 0000 0010 1000 */ + { 12, 0x58, 57 }, /* 0000 0101 1000 */ + { 12, 0x59, 58 }, /* 0000 0101 1001 */ + { 12, 0x2B, 59 }, /* 0000 0010 1011 */ + { 12, 0x2C, 60 }, /* 0000 0010 1100 */ + { 12, 0x5A, 61 }, /* 0000 0101 1010 */ + { 12, 0x66, 62 }, /* 0000 0110 0110 */ + { 12, 0x67, 63 }, /* 0000 0110 0111 */ + { 10, 0xF, 64 }, /* 0000 0011 11 */ + { 12, 0xC8, 128 }, /* 0000 1100 1000 */ + { 12, 0xC9, 192 }, /* 0000 1100 1001 */ + { 12, 0x5B, 256 }, /* 0000 0101 1011 */ + { 12, 0x33, 320 }, /* 0000 0011 0011 */ + { 12, 0x34, 384 }, /* 0000 0011 0100 */ + { 12, 0x35, 448 }, /* 0000 0011 0101 */ + { 13, 0x6C, 512 }, /* 0000 0011 0110 0 */ + { 13, 0x6D, 576 }, /* 0000 0011 0110 1 */ + { 13, 0x4A, 640 }, /* 0000 0010 0101 0 */ + { 13, 0x4B, 704 }, /* 0000 0010 0101 1 */ + { 13, 0x4C, 768 }, /* 0000 0010 0110 0 */ + { 13, 0x4D, 832 }, /* 0000 0010 0110 1 */ + { 13, 0x72, 896 }, /* 0000 0011 1001 0 */ + { 13, 0x73, 960 }, /* 0000 0011 1001 1 */ + { 13, 0x74, 1024 }, /* 0000 0011 1010 0 */ + { 13, 0x75, 1088 }, /* 0000 0011 1010 1 */ + { 13, 0x76, 1152 }, /* 0000 0011 1011 0 */ + { 13, 0x77, 1216 }, /* 0000 0011 1011 1 */ + { 13, 0x52, 1280 }, /* 0000 0010 1001 0 */ + { 13, 0x53, 1344 }, /* 0000 0010 1001 1 */ + { 13, 0x54, 1408 }, /* 0000 0010 1010 0 */ + { 13, 0x55, 1472 }, /* 0000 0010 1010 1 */ + { 13, 0x5A, 1536 }, /* 0000 0010 1101 0 */ + { 13, 0x5B, 1600 }, /* 0000 0010 1101 1 */ + { 13, 0x64, 1664 }, /* 0000 0011 0010 0 */ + { 13, 0x65, 1728 }, /* 0000 0011 0010 1 */ + { 11, 0x8, 1792 }, /* 0000 0001 000 */ + { 11, 0xC, 1856 }, /* 0000 0001 100 */ + { 11, 0xD, 1920 }, /* 0000 0001 101 */ + { 12, 0x12, 1984 }, /* 0000 0001 0010 */ + { 12, 0x13, 2048 }, /* 0000 0001 0011 */ + { 12, 0x14, 2112 }, /* 0000 0001 0100 */ + { 12, 0x15, 2176 }, /* 0000 0001 0101 */ + { 12, 0x16, 2240 }, /* 0000 0001 0110 */ + { 12, 0x17, 2304 }, /* 0000 0001 0111 */ + { 12, 0x1C, 2368 }, /* 0000 0001 1100 */ + { 12, 0x1D, 2432 }, /* 0000 0001 1101 */ + { 12, 0x1E, 2496 }, /* 0000 0001 1110 */ + { 12, 0x1F, 2560 }, /* 0000 0001 1111 */ + { 12, 0x1, G3CODE_EOL }, /* 0000 0000 0001 */ + { 9, 0x1, G3CODE_INVALID }, /* 0000 0000 1 */ + { 10, 0x1, G3CODE_INVALID }, /* 0000 0000 01 */ + { 11, 0x1, G3CODE_INVALID }, /* 0000 0000 001 */ + { 12, 0x0, G3CODE_INVALID }, /* 0000 0000 0000 */ +}; +#else +extern const tableentry TIFFFaxWhiteCodes[]; +extern const tableentry TIFFFaxBlackCodes[]; +#endif +#endif /* _T4_ */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/include/reactos/libs/libtiff/tif_config.h b/reactos/include/reactos/libs/libtiff/tif_config.h new file mode 100644 index 00000000000..4dd77dd8cf1 --- /dev/null +++ b/reactos/include/reactos/libs/libtiff/tif_config.h @@ -0,0 +1,63 @@ +/* Define to 1 if you have the header file. */ +#define HAVE_ASSERT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define as 0 or 1 according to the floating point format suported by the + machine */ +#define HAVE_IEEEFP 1 + +/* Define to 1 if you have the `jbg_newlen' function. */ +#define HAVE_JBG_NEWLEN 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_IO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SEARCH_H 1 + +/* Define to 1 if you have the `setmode' function. */ +#define HAVE_SETMODE 1 + +/* The size of a `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of a `long', as computed by sizeof. */ +#define SIZEOF_LONG 4 + +/* Signed 64-bit type */ +#define TIFF_INT64_T signed __int64 + +/* Unsigned 64-bit type */ +#define TIFF_UINT64_T unsigned __int64 + +/* Set the native cpu bit order */ +#define HOST_FILLORDER FILLORDER_LSB2MSB + +/* Define to 1 if your processor stores words with the most significant byte + first (like Motorola and SPARC, unlike Intel and VAX). */ +/* #undef WORDS_BIGENDIAN */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +# ifndef inline +# define inline __inline +# endif +#endif + +#define lfind _lfind +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/include/reactos/libs/libtiff/tif_config.vc.h b/reactos/include/reactos/libs/libtiff/tif_config.vc.h new file mode 100644 index 00000000000..4dd77dd8cf1 --- /dev/null +++ b/reactos/include/reactos/libs/libtiff/tif_config.vc.h @@ -0,0 +1,63 @@ +/* Define to 1 if you have the header file. */ +#define HAVE_ASSERT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define as 0 or 1 according to the floating point format suported by the + machine */ +#define HAVE_IEEEFP 1 + +/* Define to 1 if you have the `jbg_newlen' function. */ +#define HAVE_JBG_NEWLEN 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_IO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SEARCH_H 1 + +/* Define to 1 if you have the `setmode' function. */ +#define HAVE_SETMODE 1 + +/* The size of a `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of a `long', as computed by sizeof. */ +#define SIZEOF_LONG 4 + +/* Signed 64-bit type */ +#define TIFF_INT64_T signed __int64 + +/* Unsigned 64-bit type */ +#define TIFF_UINT64_T unsigned __int64 + +/* Set the native cpu bit order */ +#define HOST_FILLORDER FILLORDER_LSB2MSB + +/* Define to 1 if your processor stores words with the most significant byte + first (like Motorola and SPARC, unlike Intel and VAX). */ +/* #undef WORDS_BIGENDIAN */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +# ifndef inline +# define inline __inline +# endif +#endif + +#define lfind _lfind +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/include/reactos/libs/libtiff/tif_dir.h b/reactos/include/reactos/libs/libtiff/tif_dir.h new file mode 100644 index 00000000000..515af19942c --- /dev/null +++ b/reactos/include/reactos/libs/libtiff/tif_dir.h @@ -0,0 +1,211 @@ +/* $Id: tif_dir.h,v 1.30.2.3 2010-06-09 21:15:27 bfriesen Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _TIFFDIR_ +#define _TIFFDIR_ +/* + * ``Library-private'' Directory-related Definitions. + */ + +/* + * Internal format of a TIFF directory entry. + */ +typedef struct { +#define FIELD_SETLONGS 4 + /* bit vector of fields that are set */ + unsigned long td_fieldsset[FIELD_SETLONGS]; + + uint32 td_imagewidth, td_imagelength, td_imagedepth; + uint32 td_tilewidth, td_tilelength, td_tiledepth; + uint32 td_subfiletype; + uint16 td_bitspersample; + uint16 td_sampleformat; + uint16 td_compression; + uint16 td_photometric; + uint16 td_threshholding; + uint16 td_fillorder; + uint16 td_orientation; + uint16 td_samplesperpixel; + uint32 td_rowsperstrip; + uint16 td_minsamplevalue, td_maxsamplevalue; + double td_sminsamplevalue, td_smaxsamplevalue; + float td_xresolution, td_yresolution; + uint16 td_resolutionunit; + uint16 td_planarconfig; + float td_xposition, td_yposition; + uint16 td_pagenumber[2]; + uint16* td_colormap[3]; + uint16 td_halftonehints[2]; + uint16 td_extrasamples; + uint16* td_sampleinfo; + /* even though the name is misleading, td_stripsperimage is the number + * of striles (=strips or tiles) per plane, and td_nstrips the total + * number of striles */ + tstrile_t td_stripsperimage; + tstrile_t td_nstrips; /* size of offset & bytecount arrays */ + toff_t* td_stripoffset; + toff_t* td_stripbytecount; /* FIXME: it should be tsize_t array */ + int td_stripbytecountsorted; /* is the bytecount array sorted ascending? */ + uint16 td_nsubifd; + uint32* td_subifd; + /* YCbCr parameters */ + uint16 td_ycbcrsubsampling[2]; + uint16 td_ycbcrpositioning; + /* Colorimetry parameters */ + float* td_refblackwhite; + uint16* td_transferfunction[3]; + /* CMYK parameters */ + int td_inknameslen; + char* td_inknames; + + int td_customValueCount; + TIFFTagValue *td_customValues; +} TIFFDirectory; + +/* + * Field flags used to indicate fields that have + * been set in a directory, and to reference fields + * when manipulating a directory. + */ + +/* + * FIELD_IGNORE is used to signify tags that are to + * be processed but otherwise ignored. This permits + * antiquated tags to be quietly read and discarded. + * Note that a bit *is* allocated for ignored tags; + * this is understood by the directory reading logic + * which uses this fact to avoid special-case handling + */ +#define FIELD_IGNORE 0 + +/* multi-item fields */ +#define FIELD_IMAGEDIMENSIONS 1 +#define FIELD_TILEDIMENSIONS 2 +#define FIELD_RESOLUTION 3 +#define FIELD_POSITION 4 + +/* single-item fields */ +#define FIELD_SUBFILETYPE 5 +#define FIELD_BITSPERSAMPLE 6 +#define FIELD_COMPRESSION 7 +#define FIELD_PHOTOMETRIC 8 +#define FIELD_THRESHHOLDING 9 +#define FIELD_FILLORDER 10 +#define FIELD_ORIENTATION 15 +#define FIELD_SAMPLESPERPIXEL 16 +#define FIELD_ROWSPERSTRIP 17 +#define FIELD_MINSAMPLEVALUE 18 +#define FIELD_MAXSAMPLEVALUE 19 +#define FIELD_PLANARCONFIG 20 +#define FIELD_RESOLUTIONUNIT 22 +#define FIELD_PAGENUMBER 23 +#define FIELD_STRIPBYTECOUNTS 24 +#define FIELD_STRIPOFFSETS 25 +#define FIELD_COLORMAP 26 +#define FIELD_EXTRASAMPLES 31 +#define FIELD_SAMPLEFORMAT 32 +#define FIELD_SMINSAMPLEVALUE 33 +#define FIELD_SMAXSAMPLEVALUE 34 +#define FIELD_IMAGEDEPTH 35 +#define FIELD_TILEDEPTH 36 +#define FIELD_HALFTONEHINTS 37 +#define FIELD_YCBCRSUBSAMPLING 39 +#define FIELD_YCBCRPOSITIONING 40 +#define FIELD_REFBLACKWHITE 41 +#define FIELD_TRANSFERFUNCTION 44 +#define FIELD_INKNAMES 46 +#define FIELD_SUBIFD 49 +/* FIELD_CUSTOM (see tiffio.h) 65 */ +/* end of support for well-known tags; codec-private tags follow */ +#define FIELD_CODEC 66 /* base of codec-private tags */ + + +/* + * Pseudo-tags don't normally need field bits since they + * are not written to an output file (by definition). + * The library also has express logic to always query a + * codec for a pseudo-tag so allocating a field bit for + * one is a waste. If codec wants to promote the notion + * of a pseudo-tag being ``set'' or ``unset'' then it can + * do using internal state flags without polluting the + * field bit space defined for real tags. + */ +#define FIELD_PSEUDO 0 + +#define FIELD_LAST (32*FIELD_SETLONGS-1) + +#define TIFFExtractData(tif, type, v) \ + ((uint32) ((tif)->tif_header.tiff_magic == TIFF_BIGENDIAN ? \ + ((v) >> (tif)->tif_typeshift[type]) & (tif)->tif_typemask[type] : \ + (v) & (tif)->tif_typemask[type])) +#define TIFFInsertData(tif, type, v) \ + ((uint32) ((tif)->tif_header.tiff_magic == TIFF_BIGENDIAN ? \ + ((v) & (tif)->tif_typemask[type]) << (tif)->tif_typeshift[type] : \ + (v) & (tif)->tif_typemask[type])) + + +#define BITn(n) (((unsigned long)1L)<<((n)&0x1f)) +#define BITFIELDn(tif, n) ((tif)->tif_dir.td_fieldsset[(n)/32]) +#define TIFFFieldSet(tif, field) (BITFIELDn(tif, field) & BITn(field)) +#define TIFFSetFieldBit(tif, field) (BITFIELDn(tif, field) |= BITn(field)) +#define TIFFClrFieldBit(tif, field) (BITFIELDn(tif, field) &= ~BITn(field)) + +#define FieldSet(fields, f) (fields[(f)/32] & BITn(f)) +#define ResetFieldBit(fields, f) (fields[(f)/32] &= ~BITn(f)) + +#if defined(__cplusplus) +extern "C" { +#endif +extern const TIFFFieldInfo *_TIFFGetFieldInfo(size_t *); +extern const TIFFFieldInfo *_TIFFGetExifFieldInfo(size_t *); +extern void _TIFFSetupFieldInfo(TIFF*, const TIFFFieldInfo[], size_t); +extern int _TIFFMergeFieldInfo(TIFF*, const TIFFFieldInfo[], int); +extern void _TIFFPrintFieldInfo(TIFF*, FILE*); +extern TIFFDataType _TIFFSampleToTagType(TIFF*); +extern const TIFFFieldInfo* _TIFFFindOrRegisterFieldInfo( TIFF *tif, + ttag_t tag, + TIFFDataType dt ); +extern TIFFFieldInfo* _TIFFCreateAnonFieldInfo( TIFF *tif, ttag_t tag, + TIFFDataType dt ); + +#define _TIFFFindFieldInfo TIFFFindFieldInfo +#define _TIFFFindFieldInfoByName TIFFFindFieldInfoByName +#define _TIFFFieldWithTag TIFFFieldWithTag +#define _TIFFFieldWithName TIFFFieldWithName + +#if defined(__cplusplus) +} +#endif +#endif /* _TIFFDIR_ */ + +/* vim: set ts=8 sts=8 sw=8 noet: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/include/reactos/libs/libtiff/tif_fax3.h b/reactos/include/reactos/libs/libtiff/tif_fax3.h new file mode 100644 index 00000000000..40718bcfa71 --- /dev/null +++ b/reactos/include/reactos/libs/libtiff/tif_fax3.h @@ -0,0 +1,532 @@ +/* $Id: tif_fax3.h,v 1.5.2.1 2010-06-08 18:50:42 bfriesen Exp $ */ + +/* + * Copyright (c) 1990-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _FAX3_ +#define _FAX3_ +/* + * TIFF Library. + * + * CCITT Group 3 (T.4) and Group 4 (T.6) Decompression Support. + * + * Decoder support is derived, with permission, from the code + * in Frank Cringle's viewfax program; + * Copyright (C) 1990, 1995 Frank D. Cringle. + */ +#include "tiff.h" + +/* + * To override the default routine used to image decoded + * spans one can use the pseduo tag TIFFTAG_FAXFILLFUNC. + * The routine must have the type signature given below; + * for example: + * + * fillruns(unsigned char* buf, uint32* runs, uint32* erun, uint32 lastx) + * + * where buf is place to set the bits, runs is the array of b&w run + * lengths (white then black), erun is the last run in the array, and + * lastx is the width of the row in pixels. Fill routines can assume + * the run array has room for at least lastx runs and can overwrite + * data in the run array as needed (e.g. to append zero runs to bring + * the count up to a nice multiple). + */ +typedef void (*TIFFFaxFillFunc)(unsigned char*, uint32*, uint32*, uint32); + +/* + * The default run filler; made external for other decoders. + */ +#if defined(__cplusplus) +extern "C" { +#endif +extern void _TIFFFax3fillruns(unsigned char*, uint32*, uint32*, uint32); +#if defined(__cplusplus) +} +#endif + + +/* finite state machine codes */ +#define S_Null 0 +#define S_Pass 1 +#define S_Horiz 2 +#define S_V0 3 +#define S_VR 4 +#define S_VL 5 +#define S_Ext 6 +#define S_TermW 7 +#define S_TermB 8 +#define S_MakeUpW 9 +#define S_MakeUpB 10 +#define S_MakeUp 11 +#define S_EOL 12 + +typedef struct { /* state table entry */ + unsigned char State; /* see above */ + unsigned char Width; /* width of code in bits */ + uint32 Param; /* unsigned 32-bit run length in bits */ +} TIFFFaxTabEnt; + +extern const TIFFFaxTabEnt TIFFFaxMainTable[]; +extern const TIFFFaxTabEnt TIFFFaxWhiteTable[]; +extern const TIFFFaxTabEnt TIFFFaxBlackTable[]; + +/* + * The following macros define the majority of the G3/G4 decoder + * algorithm using the state tables defined elsewhere. To build + * a decoder you need some setup code and some glue code. Note + * that you may also need/want to change the way the NeedBits* + * macros get input data if, for example, you know the data to be + * decoded is properly aligned and oriented (doing so before running + * the decoder can be a big performance win). + * + * Consult the decoder in the TIFF library for an idea of what you + * need to define and setup to make use of these definitions. + * + * NB: to enable a debugging version of these macros define FAX3_DEBUG + * before including this file. Trace output goes to stdout. + */ + +#ifndef EndOfData +#define EndOfData() (cp >= ep) +#endif +/* + * Need <=8 or <=16 bits of input data. Unlike viewfax we + * cannot use/assume a word-aligned, properly bit swizzled + * input data set because data may come from an arbitrarily + * aligned, read-only source such as a memory-mapped file. + * Note also that the viewfax decoder does not check for + * running off the end of the input data buffer. This is + * possible for G3-encoded data because it prescans the input + * data to count EOL markers, but can cause problems for G4 + * data. In any event, we don't prescan and must watch for + * running out of data since we can't permit the library to + * scan past the end of the input data buffer. + * + * Finally, note that we must handle remaindered data at the end + * of a strip specially. The coder asks for a fixed number of + * bits when scanning for the next code. This may be more bits + * than are actually present in the data stream. If we appear + * to run out of data but still have some number of valid bits + * remaining then we makeup the requested amount with zeros and + * return successfully. If the returned data is incorrect then + * we should be called again and get a premature EOF error; + * otherwise we should get the right answer. + */ +#ifndef NeedBits8 +#define NeedBits8(n,eoflab) do { \ + if (BitsAvail < (n)) { \ + if (EndOfData()) { \ + if (BitsAvail == 0) /* no valid bits */ \ + goto eoflab; \ + BitsAvail = (n); /* pad with zeros */ \ + } else { \ + BitAcc |= ((uint32) bitmap[*cp++])<>= (n); \ +} while (0) + +#ifdef FAX3_DEBUG +static const char* StateNames[] = { + "Null ", + "Pass ", + "Horiz ", + "V0 ", + "VR ", + "VL ", + "Ext ", + "TermW ", + "TermB ", + "MakeUpW", + "MakeUpB", + "MakeUp ", + "EOL ", +}; +#define DEBUG_SHOW putchar(BitAcc & (1 << t) ? '1' : '0') +#define LOOKUP8(wid,tab,eoflab) do { \ + int t; \ + NeedBits8(wid,eoflab); \ + TabEnt = tab + GetBits(wid); \ + printf("%08lX/%d: %s%5d\t", (long) BitAcc, BitsAvail, \ + StateNames[TabEnt->State], TabEnt->Param); \ + for (t = 0; t < TabEnt->Width; t++) \ + DEBUG_SHOW; \ + putchar('\n'); \ + fflush(stdout); \ + ClrBits(TabEnt->Width); \ +} while (0) +#define LOOKUP16(wid,tab,eoflab) do { \ + int t; \ + NeedBits16(wid,eoflab); \ + TabEnt = tab + GetBits(wid); \ + printf("%08lX/%d: %s%5d\t", (long) BitAcc, BitsAvail, \ + StateNames[TabEnt->State], TabEnt->Param); \ + for (t = 0; t < TabEnt->Width; t++) \ + DEBUG_SHOW; \ + putchar('\n'); \ + fflush(stdout); \ + ClrBits(TabEnt->Width); \ +} while (0) + +#define SETVALUE(x) do { \ + *pa++ = RunLength + (x); \ + printf("SETVALUE: %d\t%d\n", RunLength + (x), a0); \ + a0 += x; \ + RunLength = 0; \ +} while (0) +#else +#define LOOKUP8(wid,tab,eoflab) do { \ + NeedBits8(wid,eoflab); \ + TabEnt = tab + GetBits(wid); \ + ClrBits(TabEnt->Width); \ +} while (0) +#define LOOKUP16(wid,tab,eoflab) do { \ + NeedBits16(wid,eoflab); \ + TabEnt = tab + GetBits(wid); \ + ClrBits(TabEnt->Width); \ +} while (0) + +/* + * Append a run to the run length array for the + * current row and reset decoding state. + */ +#define SETVALUE(x) do { \ + *pa++ = RunLength + (x); \ + a0 += (x); \ + RunLength = 0; \ +} while (0) +#endif + +/* + * Synchronize input decoding at the start of each + * row by scanning for an EOL (if appropriate) and + * skipping any trash data that might be present + * after a decoding error. Note that the decoding + * done elsewhere that recognizes an EOL only consumes + * 11 consecutive zero bits. This means that if EOLcnt + * is non-zero then we still need to scan for the final flag + * bit that is part of the EOL code. + */ +#define SYNC_EOL(eoflab) do { \ + if (EOLcnt == 0) { \ + for (;;) { \ + NeedBits16(11,eoflab); \ + if (GetBits(11) == 0) \ + break; \ + ClrBits(1); \ + } \ + } \ + for (;;) { \ + NeedBits8(8,eoflab); \ + if (GetBits(8)) \ + break; \ + ClrBits(8); \ + } \ + while (GetBits(1) == 0) \ + ClrBits(1); \ + ClrBits(1); /* EOL bit */ \ + EOLcnt = 0; /* reset EOL counter/flag */ \ +} while (0) + +/* + * Cleanup the array of runs after decoding a row. + * We adjust final runs to insure the user buffer is not + * overwritten and/or undecoded area is white filled. + */ +#define CLEANUP_RUNS() do { \ + if (RunLength) \ + SETVALUE(0); \ + if (a0 != lastx) { \ + badlength(a0, lastx); \ + while (a0 > lastx && pa > thisrun) \ + a0 -= *--pa; \ + if (a0 < lastx) { \ + if (a0 < 0) \ + a0 = 0; \ + if ((pa-thisrun)&1) \ + SETVALUE(0); \ + SETVALUE(lastx - a0); \ + } else if (a0 > lastx) { \ + SETVALUE(lastx); \ + SETVALUE(0); \ + } \ + } \ +} while (0) + +/* + * Decode a line of 1D-encoded data. + * + * The line expanders are written as macros so that they can be reused + * but still have direct access to the local variables of the "calling" + * function. + * + * Note that unlike the original version we have to explicitly test for + * a0 >= lastx after each black/white run is decoded. This is because + * the original code depended on the input data being zero-padded to + * insure the decoder recognized an EOL before running out of data. + */ +#define EXPAND1D(eoflab) do { \ + for (;;) { \ + for (;;) { \ + LOOKUP16(12, TIFFFaxWhiteTable, eof1d); \ + switch (TabEnt->State) { \ + case S_EOL: \ + EOLcnt = 1; \ + goto done1d; \ + case S_TermW: \ + SETVALUE(TabEnt->Param); \ + goto doneWhite1d; \ + case S_MakeUpW: \ + case S_MakeUp: \ + a0 += TabEnt->Param; \ + RunLength += TabEnt->Param; \ + break; \ + default: \ + unexpected("WhiteTable", a0); \ + goto done1d; \ + } \ + } \ + doneWhite1d: \ + if (a0 >= lastx) \ + goto done1d; \ + for (;;) { \ + LOOKUP16(13, TIFFFaxBlackTable, eof1d); \ + switch (TabEnt->State) { \ + case S_EOL: \ + EOLcnt = 1; \ + goto done1d; \ + case S_TermB: \ + SETVALUE(TabEnt->Param); \ + goto doneBlack1d; \ + case S_MakeUpB: \ + case S_MakeUp: \ + a0 += TabEnt->Param; \ + RunLength += TabEnt->Param; \ + break; \ + default: \ + unexpected("BlackTable", a0); \ + goto done1d; \ + } \ + } \ + doneBlack1d: \ + if (a0 >= lastx) \ + goto done1d; \ + if( *(pa-1) == 0 && *(pa-2) == 0 ) \ + pa -= 2; \ + } \ +eof1d: \ + prematureEOF(a0); \ + CLEANUP_RUNS(); \ + goto eoflab; \ +done1d: \ + CLEANUP_RUNS(); \ +} while (0) + +/* + * Update the value of b1 using the array + * of runs for the reference line. + */ +#define CHECK_b1 do { \ + if (pa != thisrun) while (b1 <= a0 && b1 < lastx) { \ + b1 += pb[0] + pb[1]; \ + pb += 2; \ + } \ +} while (0) + +/* + * Expand a row of 2D-encoded data. + */ +#define EXPAND2D(eoflab) do { \ + while (a0 < lastx) { \ + LOOKUP8(7, TIFFFaxMainTable, eof2d); \ + switch (TabEnt->State) { \ + case S_Pass: \ + CHECK_b1; \ + b1 += *pb++; \ + RunLength += b1 - a0; \ + a0 = b1; \ + b1 += *pb++; \ + break; \ + case S_Horiz: \ + if ((pa-thisrun)&1) { \ + for (;;) { /* black first */ \ + LOOKUP16(13, TIFFFaxBlackTable, eof2d); \ + switch (TabEnt->State) { \ + case S_TermB: \ + SETVALUE(TabEnt->Param); \ + goto doneWhite2da; \ + case S_MakeUpB: \ + case S_MakeUp: \ + a0 += TabEnt->Param; \ + RunLength += TabEnt->Param; \ + break; \ + default: \ + goto badBlack2d; \ + } \ + } \ + doneWhite2da:; \ + for (;;) { /* then white */ \ + LOOKUP16(12, TIFFFaxWhiteTable, eof2d); \ + switch (TabEnt->State) { \ + case S_TermW: \ + SETVALUE(TabEnt->Param); \ + goto doneBlack2da; \ + case S_MakeUpW: \ + case S_MakeUp: \ + a0 += TabEnt->Param; \ + RunLength += TabEnt->Param; \ + break; \ + default: \ + goto badWhite2d; \ + } \ + } \ + doneBlack2da:; \ + } else { \ + for (;;) { /* white first */ \ + LOOKUP16(12, TIFFFaxWhiteTable, eof2d); \ + switch (TabEnt->State) { \ + case S_TermW: \ + SETVALUE(TabEnt->Param); \ + goto doneWhite2db; \ + case S_MakeUpW: \ + case S_MakeUp: \ + a0 += TabEnt->Param; \ + RunLength += TabEnt->Param; \ + break; \ + default: \ + goto badWhite2d; \ + } \ + } \ + doneWhite2db:; \ + for (;;) { /* then black */ \ + LOOKUP16(13, TIFFFaxBlackTable, eof2d); \ + switch (TabEnt->State) { \ + case S_TermB: \ + SETVALUE(TabEnt->Param); \ + goto doneBlack2db; \ + case S_MakeUpB: \ + case S_MakeUp: \ + a0 += TabEnt->Param; \ + RunLength += TabEnt->Param; \ + break; \ + default: \ + goto badBlack2d; \ + } \ + } \ + doneBlack2db:; \ + } \ + CHECK_b1; \ + break; \ + case S_V0: \ + CHECK_b1; \ + SETVALUE(b1 - a0); \ + b1 += *pb++; \ + break; \ + case S_VR: \ + CHECK_b1; \ + SETVALUE(b1 - a0 + TabEnt->Param); \ + b1 += *pb++; \ + break; \ + case S_VL: \ + CHECK_b1; \ + SETVALUE(b1 - a0 - TabEnt->Param); \ + b1 -= *--pb; \ + break; \ + case S_Ext: \ + *pa++ = lastx - a0; \ + extension(a0); \ + goto eol2d; \ + case S_EOL: \ + *pa++ = lastx - a0; \ + NeedBits8(4,eof2d); \ + if (GetBits(4)) \ + unexpected("EOL", a0); \ + ClrBits(4); \ + EOLcnt = 1; \ + goto eol2d; \ + default: \ + badMain2d: \ + unexpected("MainTable", a0); \ + goto eol2d; \ + badBlack2d: \ + unexpected("BlackTable", a0); \ + goto eol2d; \ + badWhite2d: \ + unexpected("WhiteTable", a0); \ + goto eol2d; \ + eof2d: \ + prematureEOF(a0); \ + CLEANUP_RUNS(); \ + goto eoflab; \ + } \ + } \ + if (RunLength) { \ + if (RunLength + a0 < lastx) { \ + /* expect a final V0 */ \ + NeedBits8(1,eof2d); \ + if (!GetBits(1)) \ + goto badMain2d; \ + ClrBits(1); \ + } \ + SETVALUE(0); \ + } \ +eol2d: \ + CLEANUP_RUNS(); \ +} while (0) +#endif /* _FAX3_ */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/include/reactos/libs/libtiff/tif_predict.h b/reactos/include/reactos/libs/libtiff/tif_predict.h new file mode 100644 index 00000000000..da0ad9892b0 --- /dev/null +++ b/reactos/include/reactos/libs/libtiff/tif_predict.h @@ -0,0 +1,77 @@ +/* $Id: tif_predict.h,v 1.3.2.2 2010-06-08 18:50:42 bfriesen Exp $ */ + +/* + * Copyright (c) 1995-1997 Sam Leffler + * Copyright (c) 1995-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _TIFFPREDICT_ +#define _TIFFPREDICT_ +/* + * ``Library-private'' Support for the Predictor Tag + */ + +/* + * Codecs that want to support the Predictor tag must place + * this structure first in their private state block so that + * the predictor code can cast tif_data to find its state. + */ +typedef struct { + int predictor; /* predictor tag value */ + int stride; /* sample stride over data */ + tsize_t rowsize; /* tile/strip row size */ + + TIFFCodeMethod encoderow; /* parent codec encode/decode row */ + TIFFCodeMethod encodestrip; /* parent codec encode/decode strip */ + TIFFCodeMethod encodetile; /* parent codec encode/decode tile */ + TIFFPostMethod encodepfunc; /* horizontal differencer */ + + TIFFCodeMethod decoderow; /* parent codec encode/decode row */ + TIFFCodeMethod decodestrip; /* parent codec encode/decode strip */ + TIFFCodeMethod decodetile; /* parent codec encode/decode tile */ + TIFFPostMethod decodepfunc; /* horizontal accumulator */ + + TIFFVGetMethod vgetparent; /* super-class method */ + TIFFVSetMethod vsetparent; /* super-class method */ + TIFFPrintMethod printdir; /* super-class method */ + TIFFBoolMethod setupdecode; /* super-class method */ + TIFFBoolMethod setupencode; /* super-class method */ +} TIFFPredictorState; + +#if defined(__cplusplus) +extern "C" { +#endif +extern int TIFFPredictorInit(TIFF*); +extern int TIFFPredictorCleanup(TIFF*); +#if defined(__cplusplus) +} +#endif +#endif /* _TIFFPREDICT_ */ + +/* vim: set ts=8 sts=8 sw=8 noet: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/include/reactos/libs/libtiff/tiff.h b/reactos/include/reactos/libs/libtiff/tiff.h new file mode 100644 index 00000000000..0d4ab9f819f --- /dev/null +++ b/reactos/include/reactos/libs/libtiff/tiff.h @@ -0,0 +1,654 @@ +/* $Id: tiff.h,v 1.43.2.1 2010-06-08 18:50:43 bfriesen Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _TIFF_ +#define _TIFF_ + +#include "tiffconf.h" + +/* + * Tag Image File Format (TIFF) + * + * Based on Rev 6.0 from: + * Developer's Desk + * Aldus Corporation + * 411 First Ave. South + * Suite 200 + * Seattle, WA 98104 + * 206-622-5500 + * + * (http://partners.adobe.com/asn/developer/PDFS/TN/TIFF6.pdf) + * + * For Big TIFF design notes see the following link + * http://www.remotesensing.org/libtiff/bigtiffdesign.html + */ +#define TIFF_VERSION 42 +#define TIFF_BIGTIFF_VERSION 43 + +#define TIFF_BIGENDIAN 0x4d4d +#define TIFF_LITTLEENDIAN 0x4949 +#define MDI_LITTLEENDIAN 0x5045 +#define MDI_BIGENDIAN 0x4550 +/* + * Intrinsic data types required by the file format: + * + * 8-bit quantities int8/uint8 + * 16-bit quantities int16/uint16 + * 32-bit quantities int32/uint32 + * strings unsigned char* + */ + +#ifndef HAVE_INT8 +typedef signed char int8; /* NB: non-ANSI compilers may not grok */ +#endif +typedef unsigned char uint8; +#ifndef HAVE_INT16 +typedef short int16; +#endif +typedef unsigned short uint16; /* sizeof (uint16) must == 2 */ +#if SIZEOF_INT == 4 +#ifndef HAVE_INT32 +typedef int int32; +#endif +typedef unsigned int uint32; /* sizeof (uint32) must == 4 */ +#elif SIZEOF_LONG == 4 +#ifndef HAVE_INT32 +typedef long int32; +#endif +typedef unsigned long uint32; /* sizeof (uint32) must == 4 */ +#endif + +/* For TIFFReassignTagToIgnore */ +enum TIFFIgnoreSense /* IGNORE tag table */ +{ + TIS_STORE, + TIS_EXTRACT, + TIS_EMPTY +}; + +/* + * TIFF header. + */ +typedef struct { + uint16 tiff_magic; /* magic number (defines byte order) */ +#define TIFF_MAGIC_SIZE 2 + uint16 tiff_version; /* TIFF version number */ +#define TIFF_VERSION_SIZE 2 + uint32 tiff_diroff; /* byte offset to first directory */ +#define TIFF_DIROFFSET_SIZE 4 +} TIFFHeader; + + +/* + * TIFF Image File Directories are comprised of a table of field + * descriptors of the form shown below. The table is sorted in + * ascending order by tag. The values associated with each entry are + * disjoint and may appear anywhere in the file (so long as they are + * placed on a word boundary). + * + * If the value is 4 bytes or less, then it is placed in the offset + * field to save space. If the value is less than 4 bytes, it is + * left-justified in the offset field. + */ +typedef struct { + uint16 tdir_tag; /* see below */ + uint16 tdir_type; /* data type; see below */ + uint32 tdir_count; /* number of items; length in spec */ + uint32 tdir_offset; /* byte offset to field data */ +} TIFFDirEntry; + +/* + * NB: In the comments below, + * - items marked with a + are obsoleted by revision 5.0, + * - items marked with a ! are introduced in revision 6.0. + * - items marked with a % are introduced post revision 6.0. + * - items marked with a $ are obsoleted by revision 6.0. + * - items marked with a & are introduced by Adobe DNG specification. + */ + +/* + * Tag data type information. + * + * Note: RATIONALs are the ratio of two 32-bit integer values. + */ +typedef enum { + TIFF_NOTYPE = 0, /* placeholder */ + TIFF_BYTE = 1, /* 8-bit unsigned integer */ + TIFF_ASCII = 2, /* 8-bit bytes w/ last byte null */ + TIFF_SHORT = 3, /* 16-bit unsigned integer */ + TIFF_LONG = 4, /* 32-bit unsigned integer */ + TIFF_RATIONAL = 5, /* 64-bit unsigned fraction */ + TIFF_SBYTE = 6, /* !8-bit signed integer */ + TIFF_UNDEFINED = 7, /* !8-bit untyped data */ + TIFF_SSHORT = 8, /* !16-bit signed integer */ + TIFF_SLONG = 9, /* !32-bit signed integer */ + TIFF_SRATIONAL = 10, /* !64-bit signed fraction */ + TIFF_FLOAT = 11, /* !32-bit IEEE floating point */ + TIFF_DOUBLE = 12, /* !64-bit IEEE floating point */ + TIFF_IFD = 13 /* %32-bit unsigned integer (offset) */ +} TIFFDataType; + +/* + * TIFF Tag Definitions. + */ +#define TIFFTAG_SUBFILETYPE 254 /* subfile data descriptor */ +#define FILETYPE_REDUCEDIMAGE 0x1 /* reduced resolution version */ +#define FILETYPE_PAGE 0x2 /* one page of many */ +#define FILETYPE_MASK 0x4 /* transparency mask */ +#define TIFFTAG_OSUBFILETYPE 255 /* +kind of data in subfile */ +#define OFILETYPE_IMAGE 1 /* full resolution image data */ +#define OFILETYPE_REDUCEDIMAGE 2 /* reduced size image data */ +#define OFILETYPE_PAGE 3 /* one page of many */ +#define TIFFTAG_IMAGEWIDTH 256 /* image width in pixels */ +#define TIFFTAG_IMAGELENGTH 257 /* image height in pixels */ +#define TIFFTAG_BITSPERSAMPLE 258 /* bits per channel (sample) */ +#define TIFFTAG_COMPRESSION 259 /* data compression technique */ +#define COMPRESSION_NONE 1 /* dump mode */ +#define COMPRESSION_CCITTRLE 2 /* CCITT modified Huffman RLE */ +#define COMPRESSION_CCITTFAX3 3 /* CCITT Group 3 fax encoding */ +#define COMPRESSION_CCITT_T4 3 /* CCITT T.4 (TIFF 6 name) */ +#define COMPRESSION_CCITTFAX4 4 /* CCITT Group 4 fax encoding */ +#define COMPRESSION_CCITT_T6 4 /* CCITT T.6 (TIFF 6 name) */ +#define COMPRESSION_LZW 5 /* Lempel-Ziv & Welch */ +#define COMPRESSION_OJPEG 6 /* !6.0 JPEG */ +#define COMPRESSION_JPEG 7 /* %JPEG DCT compression */ +#define COMPRESSION_NEXT 32766 /* NeXT 2-bit RLE */ +#define COMPRESSION_CCITTRLEW 32771 /* #1 w/ word alignment */ +#define COMPRESSION_PACKBITS 32773 /* Macintosh RLE */ +#define COMPRESSION_THUNDERSCAN 32809 /* ThunderScan RLE */ +/* codes 32895-32898 are reserved for ANSI IT8 TIFF/IT */ +#define COMPRESSION_DCS 32947 /* Kodak DCS encoding */ +#define COMPRESSION_JBIG 34661 /* ISO JBIG */ +#define COMPRESSION_SGILOG 34676 /* SGI Log Luminance RLE */ +#define COMPRESSION_SGILOG24 34677 /* SGI Log 24-bit packed */ +#define COMPRESSION_JP2000 34712 /* Leadtools JPEG2000 */ +#define TIFFTAG_PHOTOMETRIC 262 /* photometric interpretation */ +#define PHOTOMETRIC_MINISWHITE 0 /* min value is white */ +#define PHOTOMETRIC_MINISBLACK 1 /* min value is black */ +#define PHOTOMETRIC_RGB 2 /* RGB color model */ +#define PHOTOMETRIC_PALETTE 3 /* color map indexed */ +#define PHOTOMETRIC_MASK 4 /* $holdout mask */ +#define PHOTOMETRIC_SEPARATED 5 /* !color separations */ +#define PHOTOMETRIC_YCBCR 6 /* !CCIR 601 */ +#define PHOTOMETRIC_CIELAB 8 /* !1976 CIE L*a*b* */ +#define PHOTOMETRIC_ICCLAB 9 /* ICC L*a*b* [Adobe TIFF Technote 4] */ +#define PHOTOMETRIC_ITULAB 10 /* ITU L*a*b* */ +#define PHOTOMETRIC_LOGL 32844 /* CIE Log2(L) */ +#define PHOTOMETRIC_LOGLUV 32845 /* CIE Log2(L) (u',v') */ +#define TIFFTAG_THRESHHOLDING 263 /* +thresholding used on data */ +#define THRESHHOLD_BILEVEL 1 /* b&w art scan */ +#define THRESHHOLD_HALFTONE 2 /* or dithered scan */ +#define THRESHHOLD_ERRORDIFFUSE 3 /* usually floyd-steinberg */ +#define TIFFTAG_CELLWIDTH 264 /* +dithering matrix width */ +#define TIFFTAG_CELLLENGTH 265 /* +dithering matrix height */ +#define TIFFTAG_FILLORDER 266 /* data order within a byte */ +#define FILLORDER_MSB2LSB 1 /* most significant -> least */ +#define FILLORDER_LSB2MSB 2 /* least significant -> most */ +#define TIFFTAG_DOCUMENTNAME 269 /* name of doc. image is from */ +#define TIFFTAG_IMAGEDESCRIPTION 270 /* info about image */ +#define TIFFTAG_MAKE 271 /* scanner manufacturer name */ +#define TIFFTAG_MODEL 272 /* scanner model name/number */ +#define TIFFTAG_STRIPOFFSETS 273 /* offsets to data strips */ +#define TIFFTAG_ORIENTATION 274 /* +image orientation */ +#define ORIENTATION_TOPLEFT 1 /* row 0 top, col 0 lhs */ +#define ORIENTATION_TOPRIGHT 2 /* row 0 top, col 0 rhs */ +#define ORIENTATION_BOTRIGHT 3 /* row 0 bottom, col 0 rhs */ +#define ORIENTATION_BOTLEFT 4 /* row 0 bottom, col 0 lhs */ +#define ORIENTATION_LEFTTOP 5 /* row 0 lhs, col 0 top */ +#define ORIENTATION_RIGHTTOP 6 /* row 0 rhs, col 0 top */ +#define ORIENTATION_RIGHTBOT 7 /* row 0 rhs, col 0 bottom */ +#define ORIENTATION_LEFTBOT 8 /* row 0 lhs, col 0 bottom */ +#define TIFFTAG_SAMPLESPERPIXEL 277 /* samples per pixel */ +#define TIFFTAG_ROWSPERSTRIP 278 /* rows per strip of data */ +#define TIFFTAG_STRIPBYTECOUNTS 279 /* bytes counts for strips */ +#define TIFFTAG_MINSAMPLEVALUE 280 /* +minimum sample value */ +#define TIFFTAG_MAXSAMPLEVALUE 281 /* +maximum sample value */ +#define TIFFTAG_XRESOLUTION 282 /* pixels/resolution in x */ +#define TIFFTAG_YRESOLUTION 283 /* pixels/resolution in y */ +#define TIFFTAG_PLANARCONFIG 284 /* storage organization */ +#define PLANARCONFIG_CONTIG 1 /* single image plane */ +#define PLANARCONFIG_SEPARATE 2 /* separate planes of data */ +#define TIFFTAG_PAGENAME 285 /* page name image is from */ +#define TIFFTAG_XPOSITION 286 /* x page offset of image lhs */ +#define TIFFTAG_YPOSITION 287 /* y page offset of image lhs */ +#define TIFFTAG_FREEOFFSETS 288 /* +byte offset to free block */ +#define TIFFTAG_FREEBYTECOUNTS 289 /* +sizes of free blocks */ +#define TIFFTAG_GRAYRESPONSEUNIT 290 /* $gray scale curve accuracy */ +#define GRAYRESPONSEUNIT_10S 1 /* tenths of a unit */ +#define GRAYRESPONSEUNIT_100S 2 /* hundredths of a unit */ +#define GRAYRESPONSEUNIT_1000S 3 /* thousandths of a unit */ +#define GRAYRESPONSEUNIT_10000S 4 /* ten-thousandths of a unit */ +#define GRAYRESPONSEUNIT_100000S 5 /* hundred-thousandths */ +#define TIFFTAG_GRAYRESPONSECURVE 291 /* $gray scale response curve */ +#define TIFFTAG_GROUP3OPTIONS 292 /* 32 flag bits */ +#define TIFFTAG_T4OPTIONS 292 /* TIFF 6.0 proper name alias */ +#define GROUP3OPT_2DENCODING 0x1 /* 2-dimensional coding */ +#define GROUP3OPT_UNCOMPRESSED 0x2 /* data not compressed */ +#define GROUP3OPT_FILLBITS 0x4 /* fill to byte boundary */ +#define TIFFTAG_GROUP4OPTIONS 293 /* 32 flag bits */ +#define TIFFTAG_T6OPTIONS 293 /* TIFF 6.0 proper name */ +#define GROUP4OPT_UNCOMPRESSED 0x2 /* data not compressed */ +#define TIFFTAG_RESOLUTIONUNIT 296 /* units of resolutions */ +#define RESUNIT_NONE 1 /* no meaningful units */ +#define RESUNIT_INCH 2 /* english */ +#define RESUNIT_CENTIMETER 3 /* metric */ +#define TIFFTAG_PAGENUMBER 297 /* page numbers of multi-page */ +#define TIFFTAG_COLORRESPONSEUNIT 300 /* $color curve accuracy */ +#define COLORRESPONSEUNIT_10S 1 /* tenths of a unit */ +#define COLORRESPONSEUNIT_100S 2 /* hundredths of a unit */ +#define COLORRESPONSEUNIT_1000S 3 /* thousandths of a unit */ +#define COLORRESPONSEUNIT_10000S 4 /* ten-thousandths of a unit */ +#define COLORRESPONSEUNIT_100000S 5 /* hundred-thousandths */ +#define TIFFTAG_TRANSFERFUNCTION 301 /* !colorimetry info */ +#define TIFFTAG_SOFTWARE 305 /* name & release */ +#define TIFFTAG_DATETIME 306 /* creation date and time */ +#define TIFFTAG_ARTIST 315 /* creator of image */ +#define TIFFTAG_HOSTCOMPUTER 316 /* machine where created */ +#define TIFFTAG_PREDICTOR 317 /* prediction scheme w/ LZW */ +#define PREDICTOR_NONE 1 /* no prediction scheme used */ +#define PREDICTOR_HORIZONTAL 2 /* horizontal differencing */ +#define PREDICTOR_FLOATINGPOINT 3 /* floating point predictor */ +#define TIFFTAG_WHITEPOINT 318 /* image white point */ +#define TIFFTAG_PRIMARYCHROMATICITIES 319 /* !primary chromaticities */ +#define TIFFTAG_COLORMAP 320 /* RGB map for pallette image */ +#define TIFFTAG_HALFTONEHINTS 321 /* !highlight+shadow info */ +#define TIFFTAG_TILEWIDTH 322 /* !tile width in pixels */ +#define TIFFTAG_TILELENGTH 323 /* !tile height in pixels */ +#define TIFFTAG_TILEOFFSETS 324 /* !offsets to data tiles */ +#define TIFFTAG_TILEBYTECOUNTS 325 /* !byte counts for tiles */ +#define TIFFTAG_BADFAXLINES 326 /* lines w/ wrong pixel count */ +#define TIFFTAG_CLEANFAXDATA 327 /* regenerated line info */ +#define CLEANFAXDATA_CLEAN 0 /* no errors detected */ +#define CLEANFAXDATA_REGENERATED 1 /* receiver regenerated lines */ +#define CLEANFAXDATA_UNCLEAN 2 /* uncorrected errors exist */ +#define TIFFTAG_CONSECUTIVEBADFAXLINES 328 /* max consecutive bad lines */ +#define TIFFTAG_SUBIFD 330 /* subimage descriptors */ +#define TIFFTAG_INKSET 332 /* !inks in separated image */ +#define INKSET_CMYK 1 /* !cyan-magenta-yellow-black color */ +#define INKSET_MULTIINK 2 /* !multi-ink or hi-fi color */ +#define TIFFTAG_INKNAMES 333 /* !ascii names of inks */ +#define TIFFTAG_NUMBEROFINKS 334 /* !number of inks */ +#define TIFFTAG_DOTRANGE 336 /* !0% and 100% dot codes */ +#define TIFFTAG_TARGETPRINTER 337 /* !separation target */ +#define TIFFTAG_EXTRASAMPLES 338 /* !info about extra samples */ +#define EXTRASAMPLE_UNSPECIFIED 0 /* !unspecified data */ +#define EXTRASAMPLE_ASSOCALPHA 1 /* !associated alpha data */ +#define EXTRASAMPLE_UNASSALPHA 2 /* !unassociated alpha data */ +#define TIFFTAG_SAMPLEFORMAT 339 /* !data sample format */ +#define SAMPLEFORMAT_UINT 1 /* !unsigned integer data */ +#define SAMPLEFORMAT_INT 2 /* !signed integer data */ +#define SAMPLEFORMAT_IEEEFP 3 /* !IEEE floating point data */ +#define SAMPLEFORMAT_VOID 4 /* !untyped data */ +#define SAMPLEFORMAT_COMPLEXINT 5 /* !complex signed int */ +#define SAMPLEFORMAT_COMPLEXIEEEFP 6 /* !complex ieee floating */ +#define TIFFTAG_SMINSAMPLEVALUE 340 /* !variable MinSampleValue */ +#define TIFFTAG_SMAXSAMPLEVALUE 341 /* !variable MaxSampleValue */ +#define TIFFTAG_CLIPPATH 343 /* %ClipPath + [Adobe TIFF technote 2] */ +#define TIFFTAG_XCLIPPATHUNITS 344 /* %XClipPathUnits + [Adobe TIFF technote 2] */ +#define TIFFTAG_YCLIPPATHUNITS 345 /* %YClipPathUnits + [Adobe TIFF technote 2] */ +#define TIFFTAG_INDEXED 346 /* %Indexed + [Adobe TIFF Technote 3] */ +#define TIFFTAG_JPEGTABLES 347 /* %JPEG table stream */ +#define TIFFTAG_OPIPROXY 351 /* %OPI Proxy [Adobe TIFF technote] */ +/* + * Tags 512-521 are obsoleted by Technical Note #2 which specifies a + * revised JPEG-in-TIFF scheme. + */ +#define TIFFTAG_JPEGPROC 512 /* !JPEG processing algorithm */ +#define JPEGPROC_BASELINE 1 /* !baseline sequential */ +#define JPEGPROC_LOSSLESS 14 /* !Huffman coded lossless */ +#define TIFFTAG_JPEGIFOFFSET 513 /* !pointer to SOI marker */ +#define TIFFTAG_JPEGIFBYTECOUNT 514 /* !JFIF stream length */ +#define TIFFTAG_JPEGRESTARTINTERVAL 515 /* !restart interval length */ +#define TIFFTAG_JPEGLOSSLESSPREDICTORS 517 /* !lossless proc predictor */ +#define TIFFTAG_JPEGPOINTTRANSFORM 518 /* !lossless point transform */ +#define TIFFTAG_JPEGQTABLES 519 /* !Q matrice offsets */ +#define TIFFTAG_JPEGDCTABLES 520 /* !DCT table offsets */ +#define TIFFTAG_JPEGACTABLES 521 /* !AC coefficient offsets */ +#define TIFFTAG_YCBCRCOEFFICIENTS 529 /* !RGB -> YCbCr transform */ +#define TIFFTAG_YCBCRSUBSAMPLING 530 /* !YCbCr subsampling factors */ +#define TIFFTAG_YCBCRPOSITIONING 531 /* !subsample positioning */ +#define YCBCRPOSITION_CENTERED 1 /* !as in PostScript Level 2 */ +#define YCBCRPOSITION_COSITED 2 /* !as in CCIR 601-1 */ +#define TIFFTAG_REFERENCEBLACKWHITE 532 /* !colorimetry info */ +#define TIFFTAG_XMLPACKET 700 /* %XML packet + [Adobe XMP Specification, + January 2004 */ +#define TIFFTAG_OPIIMAGEID 32781 /* %OPI ImageID + [Adobe TIFF technote] */ +/* tags 32952-32956 are private tags registered to Island Graphics */ +#define TIFFTAG_REFPTS 32953 /* image reference points */ +#define TIFFTAG_REGIONTACKPOINT 32954 /* region-xform tack point */ +#define TIFFTAG_REGIONWARPCORNERS 32955 /* warp quadrilateral */ +#define TIFFTAG_REGIONAFFINE 32956 /* affine transformation mat */ +/* tags 32995-32999 are private tags registered to SGI */ +#define TIFFTAG_MATTEING 32995 /* $use ExtraSamples */ +#define TIFFTAG_DATATYPE 32996 /* $use SampleFormat */ +#define TIFFTAG_IMAGEDEPTH 32997 /* z depth of image */ +#define TIFFTAG_TILEDEPTH 32998 /* z depth/data tile */ +/* tags 33300-33309 are private tags registered to Pixar */ +/* + * TIFFTAG_PIXAR_IMAGEFULLWIDTH and TIFFTAG_PIXAR_IMAGEFULLLENGTH + * are set when an image has been cropped out of a larger image. + * They reflect the size of the original uncropped image. + * The TIFFTAG_XPOSITION and TIFFTAG_YPOSITION can be used + * to determine the position of the smaller image in the larger one. + */ +#define TIFFTAG_PIXAR_IMAGEFULLWIDTH 33300 /* full image size in x */ +#define TIFFTAG_PIXAR_IMAGEFULLLENGTH 33301 /* full image size in y */ + /* Tags 33302-33306 are used to identify special image modes and data + * used by Pixar's texture formats. + */ +#define TIFFTAG_PIXAR_TEXTUREFORMAT 33302 /* texture map format */ +#define TIFFTAG_PIXAR_WRAPMODES 33303 /* s & t wrap modes */ +#define TIFFTAG_PIXAR_FOVCOT 33304 /* cotan(fov) for env. maps */ +#define TIFFTAG_PIXAR_MATRIX_WORLDTOSCREEN 33305 +#define TIFFTAG_PIXAR_MATRIX_WORLDTOCAMERA 33306 +/* tag 33405 is a private tag registered to Eastman Kodak */ +#define TIFFTAG_WRITERSERIALNUMBER 33405 /* device serial number */ +/* tag 33432 is listed in the 6.0 spec w/ unknown ownership */ +#define TIFFTAG_COPYRIGHT 33432 /* copyright string */ +/* IPTC TAG from RichTIFF specifications */ +#define TIFFTAG_RICHTIFFIPTC 33723 +/* 34016-34029 are reserved for ANSI IT8 TIFF/IT */ +#define TIFFTAG_STONITS 37439 /* Sample value to Nits */ +/* tag 34929 is a private tag registered to FedEx */ +#define TIFFTAG_FEDEX_EDR 34929 /* unknown use */ +#define TIFFTAG_INTEROPERABILITYIFD 40965 /* Pointer to Interoperability private directory */ +/* Adobe Digital Negative (DNG) format tags */ +#define TIFFTAG_DNGVERSION 50706 /* &DNG version number */ +#define TIFFTAG_DNGBACKWARDVERSION 50707 /* &DNG compatibility version */ +#define TIFFTAG_UNIQUECAMERAMODEL 50708 /* &name for the camera model */ +#define TIFFTAG_LOCALIZEDCAMERAMODEL 50709 /* &localized camera model + name */ +#define TIFFTAG_CFAPLANECOLOR 50710 /* &CFAPattern->LinearRaw space + mapping */ +#define TIFFTAG_CFALAYOUT 50711 /* &spatial layout of the CFA */ +#define TIFFTAG_LINEARIZATIONTABLE 50712 /* &lookup table description */ +#define TIFFTAG_BLACKLEVELREPEATDIM 50713 /* &repeat pattern size for + the BlackLevel tag */ +#define TIFFTAG_BLACKLEVEL 50714 /* &zero light encoding level */ +#define TIFFTAG_BLACKLEVELDELTAH 50715 /* &zero light encoding level + differences (columns) */ +#define TIFFTAG_BLACKLEVELDELTAV 50716 /* &zero light encoding level + differences (rows) */ +#define TIFFTAG_WHITELEVEL 50717 /* &fully saturated encoding + level */ +#define TIFFTAG_DEFAULTSCALE 50718 /* &default scale factors */ +#define TIFFTAG_DEFAULTCROPORIGIN 50719 /* &origin of the final image + area */ +#define TIFFTAG_DEFAULTCROPSIZE 50720 /* &size of the final image + area */ +#define TIFFTAG_COLORMATRIX1 50721 /* &XYZ->reference color space + transformation matrix 1 */ +#define TIFFTAG_COLORMATRIX2 50722 /* &XYZ->reference color space + transformation matrix 2 */ +#define TIFFTAG_CAMERACALIBRATION1 50723 /* &calibration matrix 1 */ +#define TIFFTAG_CAMERACALIBRATION2 50724 /* &calibration matrix 2 */ +#define TIFFTAG_REDUCTIONMATRIX1 50725 /* &dimensionality reduction + matrix 1 */ +#define TIFFTAG_REDUCTIONMATRIX2 50726 /* &dimensionality reduction + matrix 2 */ +#define TIFFTAG_ANALOGBALANCE 50727 /* &gain applied the stored raw + values*/ +#define TIFFTAG_ASSHOTNEUTRAL 50728 /* &selected white balance in + linear reference space */ +#define TIFFTAG_ASSHOTWHITEXY 50729 /* &selected white balance in + x-y chromaticity + coordinates */ +#define TIFFTAG_BASELINEEXPOSURE 50730 /* &how much to move the zero + point */ +#define TIFFTAG_BASELINENOISE 50731 /* &relative noise level */ +#define TIFFTAG_BASELINESHARPNESS 50732 /* &relative amount of + sharpening */ +#define TIFFTAG_BAYERGREENSPLIT 50733 /* &how closely the values of + the green pixels in the + blue/green rows track the + values of the green pixels + in the red/green rows */ +#define TIFFTAG_LINEARRESPONSELIMIT 50734 /* &non-linear encoding range */ +#define TIFFTAG_CAMERASERIALNUMBER 50735 /* &camera's serial number */ +#define TIFFTAG_LENSINFO 50736 /* info about the lens */ +#define TIFFTAG_CHROMABLURRADIUS 50737 /* &chroma blur radius */ +#define TIFFTAG_ANTIALIASSTRENGTH 50738 /* &relative strength of the + camera's anti-alias filter */ +#define TIFFTAG_SHADOWSCALE 50739 /* &used by Adobe Camera Raw */ +#define TIFFTAG_DNGPRIVATEDATA 50740 /* &manufacturer's private data */ +#define TIFFTAG_MAKERNOTESAFETY 50741 /* &whether the EXIF MakerNote + tag is safe to preserve + along with the rest of the + EXIF data */ +#define TIFFTAG_CALIBRATIONILLUMINANT1 50778 /* &illuminant 1 */ +#define TIFFTAG_CALIBRATIONILLUMINANT2 50779 /* &illuminant 2 */ +#define TIFFTAG_BESTQUALITYSCALE 50780 /* &best quality multiplier */ +#define TIFFTAG_RAWDATAUNIQUEID 50781 /* &unique identifier for + the raw image data */ +#define TIFFTAG_ORIGINALRAWFILENAME 50827 /* &file name of the original + raw file */ +#define TIFFTAG_ORIGINALRAWFILEDATA 50828 /* &contents of the original + raw file */ +#define TIFFTAG_ACTIVEAREA 50829 /* &active (non-masked) pixels + of the sensor */ +#define TIFFTAG_MASKEDAREAS 50830 /* &list of coordinates + of fully masked pixels */ +#define TIFFTAG_ASSHOTICCPROFILE 50831 /* &these two tags used to */ +#define TIFFTAG_ASSHOTPREPROFILEMATRIX 50832 /* map cameras's color space + into ICC profile space */ +#define TIFFTAG_CURRENTICCPROFILE 50833 /* & */ +#define TIFFTAG_CURRENTPREPROFILEMATRIX 50834 /* & */ +/* tag 65535 is an undefined tag used by Eastman Kodak */ +#define TIFFTAG_DCSHUESHIFTVALUES 65535 /* hue shift correction data */ + +/* + * The following are ``pseudo tags'' that can be used to control + * codec-specific functionality. These tags are not written to file. + * Note that these values start at 0xffff+1 so that they'll never + * collide with Aldus-assigned tags. + * + * If you want your private pseudo tags ``registered'' (i.e. added to + * this file), please post a bug report via the tracking system at + * http://www.remotesensing.org/libtiff/bugs.html with the appropriate + * C definitions to add. + */ +#define TIFFTAG_FAXMODE 65536 /* Group 3/4 format control */ +#define FAXMODE_CLASSIC 0x0000 /* default, include RTC */ +#define FAXMODE_NORTC 0x0001 /* no RTC at end of data */ +#define FAXMODE_NOEOL 0x0002 /* no EOL code at end of row */ +#define FAXMODE_BYTEALIGN 0x0004 /* byte align row */ +#define FAXMODE_WORDALIGN 0x0008 /* word align row */ +#define FAXMODE_CLASSF FAXMODE_NORTC /* TIFF Class F */ +#define TIFFTAG_JPEGQUALITY 65537 /* Compression quality level */ +/* Note: quality level is on the IJG 0-100 scale. Default value is 75 */ +#define TIFFTAG_JPEGCOLORMODE 65538 /* Auto RGB<=>YCbCr convert? */ +#define JPEGCOLORMODE_RAW 0x0000 /* no conversion (default) */ +#define JPEGCOLORMODE_RGB 0x0001 /* do auto conversion */ +#define TIFFTAG_JPEGTABLESMODE 65539 /* What to put in JPEGTables */ +#define JPEGTABLESMODE_QUANT 0x0001 /* include quantization tbls */ +#define JPEGTABLESMODE_HUFF 0x0002 /* include Huffman tbls */ +/* Note: default is JPEGTABLESMODE_QUANT | JPEGTABLESMODE_HUFF */ +#define TIFFTAG_FAXFILLFUNC 65540 /* G3/G4 fill function */ +#define TIFFTAG_PIXARLOGDATAFMT 65549 /* PixarLogCodec I/O data sz */ +#define PIXARLOGDATAFMT_8BIT 0 /* regular u_char samples */ +#define PIXARLOGDATAFMT_8BITABGR 1 /* ABGR-order u_chars */ +#define PIXARLOGDATAFMT_11BITLOG 2 /* 11-bit log-encoded (raw) */ +#define PIXARLOGDATAFMT_12BITPICIO 3 /* as per PICIO (1.0==2048) */ +#define PIXARLOGDATAFMT_16BIT 4 /* signed short samples */ +#define PIXARLOGDATAFMT_FLOAT 5 /* IEEE float samples */ +/* 65550-65556 are allocated to Oceana Matrix */ +#define TIFFTAG_DCSIMAGERTYPE 65550 /* imager model & filter */ +#define DCSIMAGERMODEL_M3 0 /* M3 chip (1280 x 1024) */ +#define DCSIMAGERMODEL_M5 1 /* M5 chip (1536 x 1024) */ +#define DCSIMAGERMODEL_M6 2 /* M6 chip (3072 x 2048) */ +#define DCSIMAGERFILTER_IR 0 /* infrared filter */ +#define DCSIMAGERFILTER_MONO 1 /* monochrome filter */ +#define DCSIMAGERFILTER_CFA 2 /* color filter array */ +#define DCSIMAGERFILTER_OTHER 3 /* other filter */ +#define TIFFTAG_DCSINTERPMODE 65551 /* interpolation mode */ +#define DCSINTERPMODE_NORMAL 0x0 /* whole image, default */ +#define DCSINTERPMODE_PREVIEW 0x1 /* preview of image (384x256) */ +#define TIFFTAG_DCSBALANCEARRAY 65552 /* color balance values */ +#define TIFFTAG_DCSCORRECTMATRIX 65553 /* color correction values */ +#define TIFFTAG_DCSGAMMA 65554 /* gamma value */ +#define TIFFTAG_DCSTOESHOULDERPTS 65555 /* toe & shoulder points */ +#define TIFFTAG_DCSCALIBRATIONFD 65556 /* calibration file desc */ +/* Note: quality level is on the ZLIB 1-9 scale. Default value is -1 */ +#define TIFFTAG_ZIPQUALITY 65557 /* compression quality level */ +#define TIFFTAG_PIXARLOGQUALITY 65558 /* PixarLog uses same scale */ +/* 65559 is allocated to Oceana Matrix */ +#define TIFFTAG_DCSCLIPRECTANGLE 65559 /* area of image to acquire */ +#define TIFFTAG_SGILOGDATAFMT 65560 /* SGILog user data format */ +#define SGILOGDATAFMT_FLOAT 0 /* IEEE float samples */ +#define SGILOGDATAFMT_16BIT 1 /* 16-bit samples */ +#define SGILOGDATAFMT_RAW 2 /* uninterpreted data */ +#define SGILOGDATAFMT_8BIT 3 /* 8-bit RGB monitor values */ +#define TIFFTAG_SGILOGENCODE 65561 /* SGILog data encoding control*/ +#define SGILOGENCODE_NODITHER 0 /* do not dither encoded values*/ +#define SGILOGENCODE_RANDITHER 1 /* randomly dither encd values */ + +/* + * EXIF tags + */ +#define EXIFTAG_EXPOSURETIME 33434 /* Exposure time */ +#define EXIFTAG_FNUMBER 33437 /* F number */ +#define EXIFTAG_EXPOSUREPROGRAM 34850 /* Exposure program */ +#define EXIFTAG_SPECTRALSENSITIVITY 34852 /* Spectral sensitivity */ +#define EXIFTAG_ISOSPEEDRATINGS 34855 /* ISO speed rating */ +#define EXIFTAG_OECF 34856 /* Optoelectric conversion + factor */ +#define EXIFTAG_EXIFVERSION 36864 /* Exif version */ +#define EXIFTAG_DATETIMEORIGINAL 36867 /* Date and time of original + data generation */ +#define EXIFTAG_DATETIMEDIGITIZED 36868 /* Date and time of digital + data generation */ +#define EXIFTAG_COMPONENTSCONFIGURATION 37121 /* Meaning of each component */ +#define EXIFTAG_COMPRESSEDBITSPERPIXEL 37122 /* Image compression mode */ +#define EXIFTAG_SHUTTERSPEEDVALUE 37377 /* Shutter speed */ +#define EXIFTAG_APERTUREVALUE 37378 /* Aperture */ +#define EXIFTAG_BRIGHTNESSVALUE 37379 /* Brightness */ +#define EXIFTAG_EXPOSUREBIASVALUE 37380 /* Exposure bias */ +#define EXIFTAG_MAXAPERTUREVALUE 37381 /* Maximum lens aperture */ +#define EXIFTAG_SUBJECTDISTANCE 37382 /* Subject distance */ +#define EXIFTAG_METERINGMODE 37383 /* Metering mode */ +#define EXIFTAG_LIGHTSOURCE 37384 /* Light source */ +#define EXIFTAG_FLASH 37385 /* Flash */ +#define EXIFTAG_FOCALLENGTH 37386 /* Lens focal length */ +#define EXIFTAG_SUBJECTAREA 37396 /* Subject area */ +#define EXIFTAG_MAKERNOTE 37500 /* Manufacturer notes */ +#define EXIFTAG_USERCOMMENT 37510 /* User comments */ +#define EXIFTAG_SUBSECTIME 37520 /* DateTime subseconds */ +#define EXIFTAG_SUBSECTIMEORIGINAL 37521 /* DateTimeOriginal subseconds */ +#define EXIFTAG_SUBSECTIMEDIGITIZED 37522 /* DateTimeDigitized subseconds */ +#define EXIFTAG_FLASHPIXVERSION 40960 /* Supported Flashpix version */ +#define EXIFTAG_COLORSPACE 40961 /* Color space information */ +#define EXIFTAG_PIXELXDIMENSION 40962 /* Valid image width */ +#define EXIFTAG_PIXELYDIMENSION 40963 /* Valid image height */ +#define EXIFTAG_RELATEDSOUNDFILE 40964 /* Related audio file */ +#define EXIFTAG_FLASHENERGY 41483 /* Flash energy */ +#define EXIFTAG_SPATIALFREQUENCYRESPONSE 41484 /* Spatial frequency response */ +#define EXIFTAG_FOCALPLANEXRESOLUTION 41486 /* Focal plane X resolution */ +#define EXIFTAG_FOCALPLANEYRESOLUTION 41487 /* Focal plane Y resolution */ +#define EXIFTAG_FOCALPLANERESOLUTIONUNIT 41488 /* Focal plane resolution unit */ +#define EXIFTAG_SUBJECTLOCATION 41492 /* Subject location */ +#define EXIFTAG_EXPOSUREINDEX 41493 /* Exposure index */ +#define EXIFTAG_SENSINGMETHOD 41495 /* Sensing method */ +#define EXIFTAG_FILESOURCE 41728 /* File source */ +#define EXIFTAG_SCENETYPE 41729 /* Scene type */ +#define EXIFTAG_CFAPATTERN 41730 /* CFA pattern */ +#define EXIFTAG_CUSTOMRENDERED 41985 /* Custom image processing */ +#define EXIFTAG_EXPOSUREMODE 41986 /* Exposure mode */ +#define EXIFTAG_WHITEBALANCE 41987 /* White balance */ +#define EXIFTAG_DIGITALZOOMRATIO 41988 /* Digital zoom ratio */ +#define EXIFTAG_FOCALLENGTHIN35MMFILM 41989 /* Focal length in 35 mm film */ +#define EXIFTAG_SCENECAPTURETYPE 41990 /* Scene capture type */ +#define EXIFTAG_GAINCONTROL 41991 /* Gain control */ +#define EXIFTAG_CONTRAST 41992 /* Contrast */ +#define EXIFTAG_SATURATION 41993 /* Saturation */ +#define EXIFTAG_SHARPNESS 41994 /* Sharpness */ +#define EXIFTAG_DEVICESETTINGDESCRIPTION 41995 /* Device settings description */ +#define EXIFTAG_SUBJECTDISTANCERANGE 41996 /* Subject distance range */ +#define EXIFTAG_GAINCONTROL 41991 /* Gain control */ +#define EXIFTAG_GAINCONTROL 41991 /* Gain control */ +#define EXIFTAG_IMAGEUNIQUEID 42016 /* Unique image ID */ + +#endif /* _TIFF_ */ + +/* vim: set ts=8 sts=8 sw=8 noet: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/include/reactos/libs/libtiff/tiffconf.h b/reactos/include/reactos/libs/libtiff/tiffconf.h new file mode 100644 index 00000000000..b7d59e0712d --- /dev/null +++ b/reactos/include/reactos/libs/libtiff/tiffconf.h @@ -0,0 +1,103 @@ +/* + Configuration defines for installed libtiff. + This file maintained for backward compatibility. Do not use definitions + from this file in your programs. +*/ + +#ifndef _TIFFCONF_ +#define _TIFFCONF_ + +/* Define to 1 if the system has the type `int16'. */ +//#define HAVE_INT16 1 + +/* Define to 1 if the system has the type `int32'. */ +//#define HAVE_INT32 1 + +/* Define to 1 if the system has the type `int8'. */ +//#define HAVE_INT8 1 + +/* The size of a `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of a `long', as computed by sizeof. */ +#define SIZEOF_LONG 4 + +/* Compatibility stuff. */ + +/* Define as 0 or 1 according to the floating point format suported by the + machine */ +#define HAVE_IEEEFP 1 + +/* Set the native cpu bit order (FILLORDER_LSB2MSB or FILLORDER_MSB2LSB) */ +#define HOST_FILLORDER FILLORDER_LSB2MSB + +/* Native cpu byte order: 1 if big-endian (Motorola) or 0 if little-endian + (Intel) */ +#define HOST_BIGENDIAN 0 + +/* Support CCITT Group 3 & 4 algorithms */ +#define CCITT_SUPPORT 1 + +/* Support JPEG compression (requires IJG JPEG library) */ +// undef JPEG_SUPPORT + +/* Support JBIG compression (requires JBIG-KIT library) */ +// #undef JBIG_SUPPORT + +/* Support LogLuv high dynamic range encoding */ +#define LOGLUV_SUPPORT 1 + +/* Support LZW algorithm */ +#define LZW_SUPPORT 1 + +/* Support NeXT 2-bit RLE algorithm */ +#define NEXT_SUPPORT 1 + +/* Support Old JPEG compresson (read contrib/ojpeg/README first! Compilation + fails with unpatched IJG JPEG library) */ +// #undef OJPEG_SUPPORT + +/* Support Macintosh PackBits algorithm */ +#define PACKBITS_SUPPORT 1 + +/* Support Pixar log-format algorithm (requires Zlib) */ + #define PIXARLOG_SUPPORT 1 + +/* Support ThunderScan 4-bit RLE algorithm */ +#define THUNDER_SUPPORT 1 + +/* Support Deflate compression */ +#define ZIP_SUPPORT 1 + +/* Support strip chopping (whether or not to convert single-strip uncompressed + images to mutiple strips of ~8Kb to reduce memory usage) */ +#define STRIPCHOP_DEFAULT TIFF_STRIPCHOP + +/* Enable SubIFD tag (330) support */ +#define SUBIFD_SUPPORT 1 + +/* Treat extra sample as alpha (default enabled). The RGBA interface will + treat a fourth sample with no EXTRASAMPLE_ value as being ASSOCALPHA. Many + packages produce RGBA files but don't mark the alpha properly. */ +#define DEFAULT_EXTRASAMPLE_AS_ALPHA 1 + +/* Pick up YCbCr subsampling info from the JPEG data stream to support files + lacking the tag (default enabled). */ +#define CHECK_JPEG_YCBCR_SUBSAMPLING 1 + +/* Support MS MDI magic number files as TIFF */ +#define MDI_SUPPORT 1 + +/* + * Feature support definitions. + * XXX: These macros are obsoleted. Don't use them in your apps! + * Macros stays here for backward compatibility and should be always defined. + */ +#define COLORIMETRY_SUPPORT +#define YCBCR_SUPPORT +#define CMYK_SUPPORT +#define ICC_SUPPORT +#define PHOTOSHOP_SUPPORT +#define IPTC_SUPPORT + +#endif /* _TIFFCONF_ */ diff --git a/reactos/include/reactos/libs/libtiff/tiffconf.vc.h b/reactos/include/reactos/libs/libtiff/tiffconf.vc.h new file mode 100644 index 00000000000..3d14847a277 --- /dev/null +++ b/reactos/include/reactos/libs/libtiff/tiffconf.vc.h @@ -0,0 +1,116 @@ +/* + Configuration defines for installed libtiff. + This file maintained for backward compatibility. Do not use definitions + from this file in your programs. +*/ + +#ifndef _TIFFCONF_ +#define _TIFFCONF_ + +/* Define to 1 if the system has the type `int16'. */ +/* #undef HAVE_INT16 */ + +/* Define to 1 if the system has the type `int32'. */ +/* #undef HAVE_INT32 */ + +/* Define to 1 if the system has the type `int8'. */ +/* #undef HAVE_INT8 */ + +/* The size of a `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of a `long', as computed by sizeof. */ +#define SIZEOF_LONG 4 + +/* Signed 64-bit type formatter */ +#define TIFF_INT64_FORMAT "%I64d" + +/* Signed 64-bit type */ +#define TIFF_INT64_T signed __int64 + +/* Unsigned 64-bit type formatter */ +#define TIFF_UINT64_FORMAT "%I64u" + +/* Unsigned 64-bit type */ +#define TIFF_UINT64_T unsigned __int64 + +/* Compatibility stuff. */ + +/* Define as 0 or 1 according to the floating point format suported by the + machine */ +#define HAVE_IEEEFP 1 + +/* Set the native cpu bit order (FILLORDER_LSB2MSB or FILLORDER_MSB2LSB) */ +#define HOST_FILLORDER FILLORDER_LSB2MSB + +/* Native cpu byte order: 1 if big-endian (Motorola) or 0 if little-endian + (Intel) */ +#define HOST_BIGENDIAN 0 + +/* Support CCITT Group 3 & 4 algorithms */ +#define CCITT_SUPPORT 1 + +/* Support JPEG compression (requires IJG JPEG library) */ +/* #undef JPEG_SUPPORT */ + +/* Support LogLuv high dynamic range encoding */ +#define LOGLUV_SUPPORT 1 + +/* Support LZW algorithm */ +#define LZW_SUPPORT 1 + +/* Support NeXT 2-bit RLE algorithm */ +#define NEXT_SUPPORT 1 + +/* Support Old JPEG compresson (read contrib/ojpeg/README first! Compilation + fails with unpatched IJG JPEG library) */ +/* #undef OJPEG_SUPPORT */ + +/* Support Macintosh PackBits algorithm */ +#define PACKBITS_SUPPORT 1 + +/* Support Pixar log-format algorithm (requires Zlib) */ +/* #undef PIXARLOG_SUPPORT */ + +/* Support ThunderScan 4-bit RLE algorithm */ +#define THUNDER_SUPPORT 1 + +/* Support Deflate compression */ +/* #undef ZIP_SUPPORT */ + +/* Support strip chopping (whether or not to convert single-strip uncompressed + images to mutiple strips of ~8Kb to reduce memory usage) */ +#define STRIPCHOP_DEFAULT TIFF_STRIPCHOP + +/* Enable SubIFD tag (330) support */ +#define SUBIFD_SUPPORT 1 + +/* Treat extra sample as alpha (default enabled). The RGBA interface will + treat a fourth sample with no EXTRASAMPLE_ value as being ASSOCALPHA. Many + packages produce RGBA files but don't mark the alpha properly. */ +#define DEFAULT_EXTRASAMPLE_AS_ALPHA 1 + +/* Pick up YCbCr subsampling info from the JPEG data stream to support files + lacking the tag (default enabled). */ +#define CHECK_JPEG_YCBCR_SUBSAMPLING 1 + +/* + * Feature support definitions. + * XXX: These macros are obsoleted. Don't use them in your apps! + * Macros stays here for backward compatibility and should be always defined. + */ +#define COLORIMETRY_SUPPORT +#define YCBCR_SUPPORT +#define CMYK_SUPPORT +#define ICC_SUPPORT +#define PHOTOSHOP_SUPPORT +#define IPTC_SUPPORT + +#endif /* _TIFFCONF_ */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/include/reactos/libs/libtiff/tiffio.h b/reactos/include/reactos/libs/libtiff/tiffio.h new file mode 100644 index 00000000000..06ec25c8298 --- /dev/null +++ b/reactos/include/reactos/libs/libtiff/tiffio.h @@ -0,0 +1,526 @@ +/* $Id: tiffio.h,v 1.56.2.4 2010-06-08 18:50:43 bfriesen Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _TIFFIO_ +#define _TIFFIO_ + +/* + * TIFF I/O Library Definitions. + */ +#include "tiff.h" +#include "tiffvers.h" + +/* + * TIFF is defined as an incomplete type to hide the + * library's internal data structures from clients. + */ +typedef struct tiff TIFF; + +/* + * The following typedefs define the intrinsic size of + * data types used in the *exported* interfaces. These + * definitions depend on the proper definition of types + * in tiff.h. Note also that the varargs interface used + * to pass tag types and values uses the types defined in + * tiff.h directly. + * + * NB: ttag_t is unsigned int and not unsigned short because + * ANSI C requires that the type before the ellipsis be a + * promoted type (i.e. one of int, unsigned int, pointer, + * or double) and because we defined pseudo-tags that are + * outside the range of legal Aldus-assigned tags. + * NB: tsize_t is int32 and not uint32 because some functions + * return -1. + * NB: toff_t is not off_t for many reasons; TIFFs max out at + * 32-bit file offsets being the most important, and to ensure + * that it is unsigned, rather than signed. + */ +typedef uint32 ttag_t; /* directory tag */ +typedef uint16 tdir_t; /* directory index */ +typedef uint16 tsample_t; /* sample number */ +typedef uint32 tstrile_t; /* strip or tile number */ +typedef tstrile_t tstrip_t; /* strip number */ +typedef tstrile_t ttile_t; /* tile number */ +typedef int32 tsize_t; /* i/o size in bytes */ +typedef void* tdata_t; /* image data ref */ +typedef uint32 toff_t; /* file offset */ + +#if !defined(__WIN32__) && (defined(_WIN32) || defined(WIN32)) +#define __WIN32__ +#endif + +/* + * On windows you should define USE_WIN32_FILEIO if you are using tif_win32.c + * or AVOID_WIN32_FILEIO if you are using something else (like tif_unix.c). + * + * By default tif_unix.c is assumed. + */ + +#if defined(_WINDOWS) || defined(__WIN32__) || defined(_Windows) +# if !defined(__CYGWIN) && !defined(AVOID_WIN32_FILEIO) && !defined(USE_WIN32_FILEIO) +# define AVOID_WIN32_FILEIO +# endif +#endif + +#if defined(USE_WIN32_FILEIO) +# define VC_EXTRALEAN +# include +# ifdef __WIN32__ +DECLARE_HANDLE(thandle_t); /* Win32 file handle */ +# else +typedef HFILE thandle_t; /* client data handle */ +# endif /* __WIN32__ */ +#else +typedef void* thandle_t; /* client data handle */ +#endif /* USE_WIN32_FILEIO */ + +/* + * Flags to pass to TIFFPrintDirectory to control + * printing of data structures that are potentially + * very large. Bit-or these flags to enable printing + * multiple items. + */ +#define TIFFPRINT_NONE 0x0 /* no extra info */ +#define TIFFPRINT_STRIPS 0x1 /* strips/tiles info */ +#define TIFFPRINT_CURVES 0x2 /* color/gray response curves */ +#define TIFFPRINT_COLORMAP 0x4 /* colormap */ +#define TIFFPRINT_JPEGQTABLES 0x100 /* JPEG Q matrices */ +#define TIFFPRINT_JPEGACTABLES 0x200 /* JPEG AC tables */ +#define TIFFPRINT_JPEGDCTABLES 0x200 /* JPEG DC tables */ + +/* + * Colour conversion stuff + */ + +/* reference white */ +#define D65_X0 (95.0470F) +#define D65_Y0 (100.0F) +#define D65_Z0 (108.8827F) + +#define D50_X0 (96.4250F) +#define D50_Y0 (100.0F) +#define D50_Z0 (82.4680F) + +/* Structure for holding information about a display device. */ + +typedef unsigned char TIFFRGBValue; /* 8-bit samples */ + +typedef struct { + float d_mat[3][3]; /* XYZ -> luminance matrix */ + float d_YCR; /* Light o/p for reference white */ + float d_YCG; + float d_YCB; + uint32 d_Vrwr; /* Pixel values for ref. white */ + uint32 d_Vrwg; + uint32 d_Vrwb; + float d_Y0R; /* Residual light for black pixel */ + float d_Y0G; + float d_Y0B; + float d_gammaR; /* Gamma values for the three guns */ + float d_gammaG; + float d_gammaB; +} TIFFDisplay; + +typedef struct { /* YCbCr->RGB support */ + TIFFRGBValue* clamptab; /* range clamping table */ + int* Cr_r_tab; + int* Cb_b_tab; + int32* Cr_g_tab; + int32* Cb_g_tab; + int32* Y_tab; +} TIFFYCbCrToRGB; + +typedef struct { /* CIE Lab 1976->RGB support */ + int range; /* Size of conversion table */ +#define CIELABTORGB_TABLE_RANGE 1500 + float rstep, gstep, bstep; + float X0, Y0, Z0; /* Reference white point */ + TIFFDisplay display; + float Yr2r[CIELABTORGB_TABLE_RANGE + 1]; /* Conversion of Yr to r */ + float Yg2g[CIELABTORGB_TABLE_RANGE + 1]; /* Conversion of Yg to g */ + float Yb2b[CIELABTORGB_TABLE_RANGE + 1]; /* Conversion of Yb to b */ +} TIFFCIELabToRGB; + +/* + * RGBA-style image support. + */ +typedef struct _TIFFRGBAImage TIFFRGBAImage; +/* + * The image reading and conversion routines invoke + * ``put routines'' to copy/image/whatever tiles of + * raw image data. A default set of routines are + * provided to convert/copy raw image data to 8-bit + * packed ABGR format rasters. Applications can supply + * alternate routines that unpack the data into a + * different format or, for example, unpack the data + * and draw the unpacked raster on the display. + */ +typedef void (*tileContigRoutine) + (TIFFRGBAImage*, uint32*, uint32, uint32, uint32, uint32, int32, int32, + unsigned char*); +typedef void (*tileSeparateRoutine) + (TIFFRGBAImage*, uint32*, uint32, uint32, uint32, uint32, int32, int32, + unsigned char*, unsigned char*, unsigned char*, unsigned char*); +/* + * RGBA-reader state. + */ +struct _TIFFRGBAImage { + TIFF* tif; /* image handle */ + int stoponerr; /* stop on read error */ + int isContig; /* data is packed/separate */ + int alpha; /* type of alpha data present */ + uint32 width; /* image width */ + uint32 height; /* image height */ + uint16 bitspersample; /* image bits/sample */ + uint16 samplesperpixel; /* image samples/pixel */ + uint16 orientation; /* image orientation */ + uint16 req_orientation; /* requested orientation */ + uint16 photometric; /* image photometric interp */ + uint16* redcmap; /* colormap pallete */ + uint16* greencmap; + uint16* bluecmap; + /* get image data routine */ + int (*get)(TIFFRGBAImage*, uint32*, uint32, uint32); + /* put decoded strip/tile */ + union { + void (*any)(TIFFRGBAImage*); + tileContigRoutine contig; + tileSeparateRoutine separate; + } put; + TIFFRGBValue* Map; /* sample mapping array */ + uint32** BWmap; /* black&white map */ + uint32** PALmap; /* palette image map */ + TIFFYCbCrToRGB* ycbcr; /* YCbCr conversion state */ + TIFFCIELabToRGB* cielab; /* CIE L*a*b conversion state */ + + int row_offset; + int col_offset; +}; + +/* + * Macros for extracting components from the + * packed ABGR form returned by TIFFReadRGBAImage. + */ +#define TIFFGetR(abgr) ((abgr) & 0xff) +#define TIFFGetG(abgr) (((abgr) >> 8) & 0xff) +#define TIFFGetB(abgr) (((abgr) >> 16) & 0xff) +#define TIFFGetA(abgr) (((abgr) >> 24) & 0xff) + +/* + * A CODEC is a software package that implements decoding, + * encoding, or decoding+encoding of a compression algorithm. + * The library provides a collection of builtin codecs. + * More codecs may be registered through calls to the library + * and/or the builtin implementations may be overridden. + */ +typedef int (*TIFFInitMethod)(TIFF*, int); +typedef struct { + char* name; + uint16 scheme; + TIFFInitMethod init; +} TIFFCodec; + +#include +#include + +/* share internal LogLuv conversion routines? */ +#ifndef LOGLUV_PUBLIC +#define LOGLUV_PUBLIC 1 +#endif + +#if !defined(__GNUC__) && !defined(__attribute__) +# define __attribute__(x) /*nothing*/ +#endif + +#if defined(c_plusplus) || defined(__cplusplus) +extern "C" { +#endif +typedef void (*TIFFErrorHandler)(const char*, const char*, va_list); +typedef void (*TIFFErrorHandlerExt)(thandle_t, const char*, const char*, va_list); +typedef tsize_t (*TIFFReadWriteProc)(thandle_t, tdata_t, tsize_t); +typedef toff_t (*TIFFSeekProc)(thandle_t, toff_t, int); +typedef int (*TIFFCloseProc)(thandle_t); +typedef toff_t (*TIFFSizeProc)(thandle_t); +typedef int (*TIFFMapFileProc)(thandle_t, tdata_t*, toff_t*); +typedef void (*TIFFUnmapFileProc)(thandle_t, tdata_t, toff_t); +typedef void (*TIFFExtendProc)(TIFF*); + +extern const char* TIFFGetVersion(void); + +extern const TIFFCodec* TIFFFindCODEC(uint16); +extern TIFFCodec* TIFFRegisterCODEC(uint16, const char*, TIFFInitMethod); +extern void TIFFUnRegisterCODEC(TIFFCodec*); +extern int TIFFIsCODECConfigured(uint16); +extern TIFFCodec* TIFFGetConfiguredCODECs(void); + +/* + * Auxiliary functions. + */ + +extern tdata_t _TIFFmalloc(tsize_t); +extern tdata_t _TIFFrealloc(tdata_t, tsize_t); +extern void _TIFFmemset(tdata_t, int, tsize_t); +extern void _TIFFmemcpy(tdata_t, const tdata_t, tsize_t); +extern int _TIFFmemcmp(const tdata_t, const tdata_t, tsize_t); +extern void _TIFFfree(tdata_t); + +/* +** Stuff, related to tag handling and creating custom tags. +*/ +extern int TIFFGetTagListCount( TIFF * ); +extern ttag_t TIFFGetTagListEntry( TIFF *, int tag_index ); + +#define TIFF_ANY TIFF_NOTYPE /* for field descriptor searching */ +#define TIFF_VARIABLE -1 /* marker for variable length tags */ +#define TIFF_SPP -2 /* marker for SamplesPerPixel tags */ +#define TIFF_VARIABLE2 -3 /* marker for uint32 var-length tags */ + +#define FIELD_CUSTOM 65 + +typedef struct { + ttag_t field_tag; /* field's tag */ + short field_readcount; /* read count/TIFF_VARIABLE/TIFF_SPP */ + short field_writecount; /* write count/TIFF_VARIABLE */ + TIFFDataType field_type; /* type of associated data */ + unsigned short field_bit; /* bit in fieldsset bit vector */ + unsigned char field_oktochange; /* if true, can change while writing */ + unsigned char field_passcount; /* if true, pass dir count on set */ + char *field_name; /* ASCII name */ +} TIFFFieldInfo; + +typedef struct _TIFFTagValue { + const TIFFFieldInfo *info; + int count; + void *value; +} TIFFTagValue; + +extern void TIFFMergeFieldInfo(TIFF*, const TIFFFieldInfo[], int); +extern const TIFFFieldInfo* TIFFFindFieldInfo(TIFF*, ttag_t, TIFFDataType); +extern const TIFFFieldInfo* TIFFFindFieldInfoByName(TIFF* , const char *, + TIFFDataType); +extern const TIFFFieldInfo* TIFFFieldWithTag(TIFF*, ttag_t); +extern const TIFFFieldInfo* TIFFFieldWithName(TIFF*, const char *); + +typedef int (*TIFFVSetMethod)(TIFF*, ttag_t, va_list); +typedef int (*TIFFVGetMethod)(TIFF*, ttag_t, va_list); +typedef void (*TIFFPrintMethod)(TIFF*, FILE*, long); + +typedef struct { + TIFFVSetMethod vsetfield; /* tag set routine */ + TIFFVGetMethod vgetfield; /* tag get routine */ + TIFFPrintMethod printdir; /* directory print routine */ +} TIFFTagMethods; + +extern TIFFTagMethods *TIFFAccessTagMethods( TIFF * ); +extern void *TIFFGetClientInfo( TIFF *, const char * ); +extern void TIFFSetClientInfo( TIFF *, void *, const char * ); + +extern void TIFFCleanup(TIFF*); +extern void TIFFClose(TIFF*); +extern int TIFFFlush(TIFF*); +extern int TIFFFlushData(TIFF*); +extern int TIFFGetField(TIFF*, ttag_t, ...); +extern int TIFFVGetField(TIFF*, ttag_t, va_list); +extern int TIFFGetFieldDefaulted(TIFF*, ttag_t, ...); +extern int TIFFVGetFieldDefaulted(TIFF*, ttag_t, va_list); +extern int TIFFReadDirectory(TIFF*); +extern int TIFFReadCustomDirectory(TIFF*, toff_t, const TIFFFieldInfo[], + size_t); +extern int TIFFReadEXIFDirectory(TIFF*, toff_t); +extern tsize_t TIFFScanlineSize(TIFF*); +extern tsize_t TIFFOldScanlineSize(TIFF*); +extern tsize_t TIFFNewScanlineSize(TIFF*); +extern tsize_t TIFFRasterScanlineSize(TIFF*); +extern tsize_t TIFFStripSize(TIFF*); +extern tsize_t TIFFRawStripSize(TIFF*, tstrip_t); +extern tsize_t TIFFVStripSize(TIFF*, uint32); +extern tsize_t TIFFTileRowSize(TIFF*); +extern tsize_t TIFFTileSize(TIFF*); +extern tsize_t TIFFVTileSize(TIFF*, uint32); +extern uint32 TIFFDefaultStripSize(TIFF*, uint32); +extern void TIFFDefaultTileSize(TIFF*, uint32*, uint32*); +extern int TIFFFileno(TIFF*); +extern int TIFFSetFileno(TIFF*, int); +extern thandle_t TIFFClientdata(TIFF*); +extern thandle_t TIFFSetClientdata(TIFF*, thandle_t); +extern int TIFFGetMode(TIFF*); +extern int TIFFSetMode(TIFF*, int); +extern int TIFFIsTiled(TIFF*); +extern int TIFFIsByteSwapped(TIFF*); +extern int TIFFIsUpSampled(TIFF*); +extern int TIFFIsMSB2LSB(TIFF*); +extern int TIFFIsBigEndian(TIFF*); +extern TIFFReadWriteProc TIFFGetReadProc(TIFF*); +extern TIFFReadWriteProc TIFFGetWriteProc(TIFF*); +extern TIFFSeekProc TIFFGetSeekProc(TIFF*); +extern TIFFCloseProc TIFFGetCloseProc(TIFF*); +extern TIFFSizeProc TIFFGetSizeProc(TIFF*); +extern TIFFMapFileProc TIFFGetMapFileProc(TIFF*); +extern TIFFUnmapFileProc TIFFGetUnmapFileProc(TIFF*); +extern uint32 TIFFCurrentRow(TIFF*); +extern tdir_t TIFFCurrentDirectory(TIFF*); +extern tdir_t TIFFNumberOfDirectories(TIFF*); +extern uint32 TIFFCurrentDirOffset(TIFF*); +extern tstrip_t TIFFCurrentStrip(TIFF*); +extern ttile_t TIFFCurrentTile(TIFF*); +extern int TIFFReadBufferSetup(TIFF*, tdata_t, tsize_t); +extern int TIFFWriteBufferSetup(TIFF*, tdata_t, tsize_t); +extern int TIFFSetupStrips(TIFF *); +extern int TIFFWriteCheck(TIFF*, int, const char *); +extern void TIFFFreeDirectory(TIFF*); +extern int TIFFCreateDirectory(TIFF*); +extern int TIFFLastDirectory(TIFF*); +extern int TIFFSetDirectory(TIFF*, tdir_t); +extern int TIFFSetSubDirectory(TIFF*, uint32); +extern int TIFFUnlinkDirectory(TIFF*, tdir_t); +extern int TIFFSetField(TIFF*, ttag_t, ...); +extern int TIFFVSetField(TIFF*, ttag_t, va_list); +extern int TIFFWriteDirectory(TIFF *); +extern int TIFFCheckpointDirectory(TIFF *); +extern int TIFFRewriteDirectory(TIFF *); +extern int TIFFReassignTagToIgnore(enum TIFFIgnoreSense, int); + +#if defined(c_plusplus) || defined(__cplusplus) +extern void TIFFPrintDirectory(TIFF*, FILE*, long = 0); +extern int TIFFReadScanline(TIFF*, tdata_t, uint32, tsample_t = 0); +extern int TIFFWriteScanline(TIFF*, tdata_t, uint32, tsample_t = 0); +extern int TIFFReadRGBAImage(TIFF*, uint32, uint32, uint32*, int = 0); +extern int TIFFReadRGBAImageOriented(TIFF*, uint32, uint32, uint32*, + int = ORIENTATION_BOTLEFT, int = 0); +#else +extern void TIFFPrintDirectory(TIFF*, FILE*, long); +extern int TIFFReadScanline(TIFF*, tdata_t, uint32, tsample_t); +extern int TIFFWriteScanline(TIFF*, tdata_t, uint32, tsample_t); +extern int TIFFReadRGBAImage(TIFF*, uint32, uint32, uint32*, int); +extern int TIFFReadRGBAImageOriented(TIFF*, uint32, uint32, uint32*, int, int); +#endif + +extern int TIFFReadRGBAStrip(TIFF*, tstrip_t, uint32 * ); +extern int TIFFReadRGBATile(TIFF*, uint32, uint32, uint32 * ); +extern int TIFFRGBAImageOK(TIFF*, char [1024]); +extern int TIFFRGBAImageBegin(TIFFRGBAImage*, TIFF*, int, char [1024]); +extern int TIFFRGBAImageGet(TIFFRGBAImage*, uint32*, uint32, uint32); +extern void TIFFRGBAImageEnd(TIFFRGBAImage*); +extern TIFF* TIFFOpen(const char*, const char*); +# ifdef __WIN32__ +extern TIFF* TIFFOpenW(const wchar_t*, const char*); +# endif /* __WIN32__ */ +extern TIFF* TIFFFdOpen(int, const char*, const char*); +extern TIFF* TIFFClientOpen(const char*, const char*, + thandle_t, + TIFFReadWriteProc, TIFFReadWriteProc, + TIFFSeekProc, TIFFCloseProc, + TIFFSizeProc, + TIFFMapFileProc, TIFFUnmapFileProc); +extern const char* TIFFFileName(TIFF*); +extern const char* TIFFSetFileName(TIFF*, const char *); +extern void TIFFError(const char*, const char*, ...) __attribute__((format (printf,2,3))); +extern void TIFFErrorExt(thandle_t, const char*, const char*, ...) __attribute__((format (printf,3,4))); +extern void TIFFWarning(const char*, const char*, ...) __attribute__((format (printf,2,3))); +extern void TIFFWarningExt(thandle_t, const char*, const char*, ...) __attribute__((format (printf,3,4))); +extern TIFFErrorHandler TIFFSetErrorHandler(TIFFErrorHandler); +extern TIFFErrorHandlerExt TIFFSetErrorHandlerExt(TIFFErrorHandlerExt); +extern TIFFErrorHandler TIFFSetWarningHandler(TIFFErrorHandler); +extern TIFFErrorHandlerExt TIFFSetWarningHandlerExt(TIFFErrorHandlerExt); +extern TIFFExtendProc TIFFSetTagExtender(TIFFExtendProc); +extern ttile_t TIFFComputeTile(TIFF*, uint32, uint32, uint32, tsample_t); +extern int TIFFCheckTile(TIFF*, uint32, uint32, uint32, tsample_t); +extern ttile_t TIFFNumberOfTiles(TIFF*); +extern tsize_t TIFFReadTile(TIFF*, + tdata_t, uint32, uint32, uint32, tsample_t); +extern tsize_t TIFFWriteTile(TIFF*, + tdata_t, uint32, uint32, uint32, tsample_t); +extern tstrip_t TIFFComputeStrip(TIFF*, uint32, tsample_t); +extern tstrip_t TIFFNumberOfStrips(TIFF*); +extern tsize_t TIFFReadEncodedStrip(TIFF*, tstrip_t, tdata_t, tsize_t); +extern tsize_t TIFFReadRawStrip(TIFF*, tstrip_t, tdata_t, tsize_t); +extern tsize_t TIFFReadEncodedTile(TIFF*, ttile_t, tdata_t, tsize_t); +extern tsize_t TIFFReadRawTile(TIFF*, ttile_t, tdata_t, tsize_t); +extern tsize_t TIFFWriteEncodedStrip(TIFF*, tstrip_t, tdata_t, tsize_t); +extern tsize_t TIFFWriteRawStrip(TIFF*, tstrip_t, tdata_t, tsize_t); +extern tsize_t TIFFWriteEncodedTile(TIFF*, ttile_t, tdata_t, tsize_t); +extern tsize_t TIFFWriteRawTile(TIFF*, ttile_t, tdata_t, tsize_t); +extern int TIFFDataWidth(TIFFDataType); /* table of tag datatype widths */ +extern void TIFFSetWriteOffset(TIFF*, toff_t); +extern void TIFFSwabShort(uint16*); +extern void TIFFSwabLong(uint32*); +extern void TIFFSwabDouble(double*); +extern void TIFFSwabArrayOfShort(uint16*, unsigned long); +extern void TIFFSwabArrayOfTriples(uint8*, unsigned long); +extern void TIFFSwabArrayOfLong(uint32*, unsigned long); +extern void TIFFSwabArrayOfDouble(double*, unsigned long); +extern void TIFFReverseBits(unsigned char *, unsigned long); +extern const unsigned char* TIFFGetBitRevTable(int); + +#ifdef LOGLUV_PUBLIC +#define U_NEU 0.210526316 +#define V_NEU 0.473684211 +#define UVSCALE 410. +extern double LogL16toY(int); +extern double LogL10toY(int); +extern void XYZtoRGB24(float*, uint8*); +extern int uv_decode(double*, double*, int); +extern void LogLuv24toXYZ(uint32, float*); +extern void LogLuv32toXYZ(uint32, float*); +#if defined(c_plusplus) || defined(__cplusplus) +extern int LogL16fromY(double, int = SGILOGENCODE_NODITHER); +extern int LogL10fromY(double, int = SGILOGENCODE_NODITHER); +extern int uv_encode(double, double, int = SGILOGENCODE_NODITHER); +extern uint32 LogLuv24fromXYZ(float*, int = SGILOGENCODE_NODITHER); +extern uint32 LogLuv32fromXYZ(float*, int = SGILOGENCODE_NODITHER); +#else +extern int LogL16fromY(double, int); +extern int LogL10fromY(double, int); +extern int uv_encode(double, double, int); +extern uint32 LogLuv24fromXYZ(float*, int); +extern uint32 LogLuv32fromXYZ(float*, int); +#endif +#endif /* LOGLUV_PUBLIC */ + +extern int TIFFCIELabToRGBInit(TIFFCIELabToRGB*, TIFFDisplay *, float*); +extern void TIFFCIELabToXYZ(TIFFCIELabToRGB *, uint32, int32, int32, + float *, float *, float *); +extern void TIFFXYZToRGB(TIFFCIELabToRGB *, float, float, float, + uint32 *, uint32 *, uint32 *); + +extern int TIFFYCbCrToRGBInit(TIFFYCbCrToRGB*, float*, float*); +extern void TIFFYCbCrtoRGB(TIFFYCbCrToRGB *, uint32, int32, int32, + uint32 *, uint32 *, uint32 *); + +#if defined(c_plusplus) || defined(__cplusplus) +} +#endif + +#endif /* _TIFFIO_ */ + +/* vim: set ts=8 sts=8 sw=8 noet: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/include/reactos/libs/libtiff/tiffio.hxx b/reactos/include/reactos/libs/libtiff/tiffio.hxx new file mode 100644 index 00000000000..ee3fd32c742 --- /dev/null +++ b/reactos/include/reactos/libs/libtiff/tiffio.hxx @@ -0,0 +1,49 @@ +/* $Id: tiffio.hxx,v 1.1.2.1 2010-06-08 18:50:43 bfriesen Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _TIFFIO_HXX_ +#define _TIFFIO_HXX_ + +/* + * TIFF I/O library definitions which provide C++ streams API. + */ + +#include +#include "tiff.h" + +extern TIFF* TIFFStreamOpen(const char*, std::ostream *); +extern TIFF* TIFFStreamOpen(const char*, std::istream *); + +#endif /* _TIFFIO_HXX_ */ + +/* vim: set ts=8 sts=8 sw=8 noet: */ +/* + * Local Variables: + * mode: c++ + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/include/reactos/libs/libtiff/tiffiop.h b/reactos/include/reactos/libs/libtiff/tiffiop.h new file mode 100644 index 00000000000..a064039f6b8 --- /dev/null +++ b/reactos/include/reactos/libs/libtiff/tiffiop.h @@ -0,0 +1,350 @@ +/* $Id: tiffiop.h,v 1.51.2.6 2010-06-12 02:55:16 bfriesen Exp $ */ + +/* + * Copyright (c) 1988-1997 Sam Leffler + * Copyright (c) 1991-1997 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _TIFFIOP_ +#define _TIFFIOP_ +/* + * ``Library-private'' definitions. + */ + +#include "tif_config.h" + +#ifdef HAVE_FCNTL_H +# include +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +#ifdef HAVE_STRING_H +# include +#endif + +#ifdef HAVE_ASSERT_H +# include +#else +# define assert(x) +#endif + +#ifdef HAVE_SEARCH_H +# include +#else +extern void *lfind(const void *, const void *, size_t *, size_t, + int (*)(const void *, const void *)); +#endif + +/* + Libtiff itself does not require a 64-bit type, but bundled TIFF + utilities may use it. +*/ +typedef TIFF_INT64_T int64; +typedef TIFF_UINT64_T uint64; + +#include "tiffio.h" +#include "tif_dir.h" + +#ifndef STRIP_SIZE_DEFAULT +# define STRIP_SIZE_DEFAULT 8192 +#endif + +#define streq(a,b) (strcmp(a,b) == 0) + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +typedef struct client_info { + struct client_info *next; + void *data; + char *name; +} TIFFClientInfoLink; + +/* + * Typedefs for ``method pointers'' used internally. + */ +typedef unsigned char tidataval_t; /* internal image data value type */ +typedef tidataval_t* tidata_t; /* reference to internal image data */ + +typedef void (*TIFFVoidMethod)(TIFF*); +typedef int (*TIFFBoolMethod)(TIFF*); +typedef int (*TIFFPreMethod)(TIFF*, tsample_t); +typedef int (*TIFFCodeMethod)(TIFF*, tidata_t, tsize_t, tsample_t); +typedef int (*TIFFSeekMethod)(TIFF*, uint32); +typedef void (*TIFFPostMethod)(TIFF*, tidata_t, tsize_t); +typedef uint32 (*TIFFStripMethod)(TIFF*, uint32); +typedef void (*TIFFTileMethod)(TIFF*, uint32*, uint32*); + +struct tiff { + char* tif_name; /* name of open file */ + int tif_fd; /* open file descriptor */ + int tif_mode; /* open mode (O_*) */ + uint32 tif_flags; +#define TIFF_FILLORDER 0x00003 /* natural bit fill order for machine */ +#define TIFF_DIRTYHEADER 0x00004 /* header must be written on close */ +#define TIFF_DIRTYDIRECT 0x00008 /* current directory must be written */ +#define TIFF_BUFFERSETUP 0x00010 /* data buffers setup */ +#define TIFF_CODERSETUP 0x00020 /* encoder/decoder setup done */ +#define TIFF_BEENWRITING 0x00040 /* written 1+ scanlines to file */ +#define TIFF_SWAB 0x00080 /* byte swap file information */ +#define TIFF_NOBITREV 0x00100 /* inhibit bit reversal logic */ +#define TIFF_MYBUFFER 0x00200 /* my raw data buffer; free on close */ +#define TIFF_ISTILED 0x00400 /* file is tile, not strip- based */ +#define TIFF_MAPPED 0x00800 /* file is mapped into memory */ +#define TIFF_POSTENCODE 0x01000 /* need call to postencode routine */ +#define TIFF_INSUBIFD 0x02000 /* currently writing a subifd */ +#define TIFF_UPSAMPLED 0x04000 /* library is doing data up-sampling */ +#define TIFF_STRIPCHOP 0x08000 /* enable strip chopping support */ +#define TIFF_HEADERONLY 0x10000 /* read header only, do not process */ + /* the first directory */ +#define TIFF_NOREADRAW 0x20000 /* skip reading of raw uncompressed */ + /* image data */ +#define TIFF_INCUSTOMIFD 0x40000 /* currently writing a custom IFD */ + toff_t tif_diroff; /* file offset of current directory */ + toff_t tif_nextdiroff; /* file offset of following directory */ + toff_t* tif_dirlist; /* list of offsets to already seen */ + /* directories to prevent IFD looping */ + tsize_t tif_dirlistsize;/* number of entires in offset list */ + uint16 tif_dirnumber; /* number of already seen directories */ + TIFFDirectory tif_dir; /* internal rep of current directory */ + TIFFDirectory tif_customdir; /* custom IFDs are separated from + the main ones */ + TIFFHeader tif_header; /* file's header block */ + const int* tif_typeshift; /* data type shift counts */ + const long* tif_typemask; /* data type masks */ + uint32 tif_row; /* current scanline */ + tdir_t tif_curdir; /* current directory (index) */ + tstrip_t tif_curstrip; /* current strip for read/write */ + toff_t tif_curoff; /* current offset for read/write */ + toff_t tif_dataoff; /* current offset for writing dir */ +/* SubIFD support */ + uint16 tif_nsubifd; /* remaining subifds to write */ + toff_t tif_subifdoff; /* offset for patching SubIFD link */ +/* tiling support */ + uint32 tif_col; /* current column (offset by row too) */ + ttile_t tif_curtile; /* current tile for read/write */ + tsize_t tif_tilesize; /* # of bytes in a tile */ +/* compression scheme hooks */ + int tif_decodestatus; + TIFFBoolMethod tif_setupdecode;/* called once before predecode */ + TIFFPreMethod tif_predecode; /* pre- row/strip/tile decoding */ + TIFFBoolMethod tif_setupencode;/* called once before preencode */ + int tif_encodestatus; + TIFFPreMethod tif_preencode; /* pre- row/strip/tile encoding */ + TIFFBoolMethod tif_postencode; /* post- row/strip/tile encoding */ + TIFFCodeMethod tif_decoderow; /* scanline decoding routine */ + TIFFCodeMethod tif_encoderow; /* scanline encoding routine */ + TIFFCodeMethod tif_decodestrip;/* strip decoding routine */ + TIFFCodeMethod tif_encodestrip;/* strip encoding routine */ + TIFFCodeMethod tif_decodetile; /* tile decoding routine */ + TIFFCodeMethod tif_encodetile; /* tile encoding routine */ + TIFFVoidMethod tif_close; /* cleanup-on-close routine */ + TIFFSeekMethod tif_seek; /* position within a strip routine */ + TIFFVoidMethod tif_cleanup; /* cleanup state routine */ + TIFFStripMethod tif_defstripsize;/* calculate/constrain strip size */ + TIFFTileMethod tif_deftilesize;/* calculate/constrain tile size */ + tidata_t tif_data; /* compression scheme private data */ +/* input/output buffering */ + tsize_t tif_scanlinesize;/* # of bytes in a scanline */ + tsize_t tif_scanlineskew;/* scanline skew for reading strips */ + tidata_t tif_rawdata; /* raw data buffer */ + tsize_t tif_rawdatasize;/* # of bytes in raw data buffer */ + tidata_t tif_rawcp; /* current spot in raw buffer */ + tsize_t tif_rawcc; /* bytes unread from raw buffer */ +/* memory-mapped file support */ + tidata_t tif_base; /* base of mapped file */ + toff_t tif_size; /* size of mapped file region (bytes) + FIXME: it should be tsize_t */ + TIFFMapFileProc tif_mapproc; /* map file method */ + TIFFUnmapFileProc tif_unmapproc;/* unmap file method */ +/* input/output callback methods */ + thandle_t tif_clientdata; /* callback parameter */ + TIFFReadWriteProc tif_readproc; /* read method */ + TIFFReadWriteProc tif_writeproc;/* write method */ + TIFFSeekProc tif_seekproc; /* lseek method */ + TIFFCloseProc tif_closeproc; /* close method */ + TIFFSizeProc tif_sizeproc; /* filesize method */ +/* post-decoding support */ + TIFFPostMethod tif_postdecode; /* post decoding routine */ +/* tag support */ + TIFFFieldInfo** tif_fieldinfo; /* sorted table of registered tags */ + size_t tif_nfields; /* # entries in registered tag table */ + const TIFFFieldInfo *tif_foundfield;/* cached pointer to already found tag */ + TIFFTagMethods tif_tagmethods; /* tag get/set/print routines */ + TIFFClientInfoLink *tif_clientinfo; /* extra client information. */ +}; + +#define isPseudoTag(t) (t > 0xffff) /* is tag value normal or pseudo */ + +#define isTiled(tif) (((tif)->tif_flags & TIFF_ISTILED) != 0) +#define isMapped(tif) (((tif)->tif_flags & TIFF_MAPPED) != 0) +#define isFillOrder(tif, o) (((tif)->tif_flags & (o)) != 0) +#define isUpSampled(tif) (((tif)->tif_flags & TIFF_UPSAMPLED) != 0) +#define TIFFReadFile(tif, buf, size) \ + ((*(tif)->tif_readproc)((tif)->tif_clientdata,buf,size)) +#define TIFFWriteFile(tif, buf, size) \ + ((*(tif)->tif_writeproc)((tif)->tif_clientdata,buf,size)) +#define TIFFSeekFile(tif, off, whence) \ + ((*(tif)->tif_seekproc)((tif)->tif_clientdata,(toff_t)(off),whence)) +#define TIFFCloseFile(tif) \ + ((*(tif)->tif_closeproc)((tif)->tif_clientdata)) +#define TIFFGetFileSize(tif) \ + ((*(tif)->tif_sizeproc)((tif)->tif_clientdata)) +#define TIFFMapFileContents(tif, paddr, psize) \ + ((*(tif)->tif_mapproc)((tif)->tif_clientdata,paddr,psize)) +#define TIFFUnmapFileContents(tif, addr, size) \ + ((*(tif)->tif_unmapproc)((tif)->tif_clientdata,addr,size)) + +/* + * Default Read/Seek/Write definitions. + */ +#ifndef ReadOK +#define ReadOK(tif, buf, size) \ + (TIFFReadFile(tif, (tdata_t) buf, (tsize_t)(size)) == (tsize_t)(size)) +#endif +#ifndef SeekOK +#define SeekOK(tif, off) \ + (TIFFSeekFile(tif, (toff_t) off, SEEK_SET) == (toff_t) off) +#endif +#ifndef WriteOK +#define WriteOK(tif, buf, size) \ + (TIFFWriteFile(tif, (tdata_t) buf, (tsize_t) size) == (tsize_t) size) +#endif + +/* NB: the uint32 casts are to silence certain ANSI-C compilers */ +#define TIFFhowmany(x, y) (((uint32)x < (0xffffffff - (uint32)(y-1))) ? \ + ((((uint32)(x))+(((uint32)(y))-1))/((uint32)(y))) : \ + 0U) +#define TIFFhowmany8(x) (((x)&0x07)?((uint32)(x)>>3)+1:(uint32)(x)>>3) +#define TIFFroundup(x, y) (TIFFhowmany(x,y)*(y)) + +/* Safe multiply which returns zero if there is an integer overflow */ +#define TIFFSafeMultiply(t,v,m) ((((t)m != (t)0) && (((t)((v*m)/m)) == (t)v)) ? (t)(v*m) : (t)0) + +#define TIFFmax(A,B) ((A)>(B)?(A):(B)) +#define TIFFmin(A,B) ((A)<(B)?(A):(B)) + +#define TIFFArrayCount(a) (sizeof (a) / sizeof ((a)[0])) + +#if defined(__cplusplus) +extern "C" { +#endif +extern int _TIFFgetMode(const char*, const char*); +extern int _TIFFNoRowEncode(TIFF*, tidata_t, tsize_t, tsample_t); +extern int _TIFFNoStripEncode(TIFF*, tidata_t, tsize_t, tsample_t); +extern int _TIFFNoTileEncode(TIFF*, tidata_t, tsize_t, tsample_t); +extern int _TIFFNoRowDecode(TIFF*, tidata_t, tsize_t, tsample_t); +extern int _TIFFNoStripDecode(TIFF*, tidata_t, tsize_t, tsample_t); +extern int _TIFFNoTileDecode(TIFF*, tidata_t, tsize_t, tsample_t); +extern void _TIFFNoPostDecode(TIFF*, tidata_t, tsize_t); +extern int _TIFFNoPreCode (TIFF*, tsample_t); +extern int _TIFFNoSeek(TIFF*, uint32); +extern void _TIFFSwab16BitData(TIFF*, tidata_t, tsize_t); +extern void _TIFFSwab24BitData(TIFF*, tidata_t, tsize_t); +extern void _TIFFSwab32BitData(TIFF*, tidata_t, tsize_t); +extern void _TIFFSwab64BitData(TIFF*, tidata_t, tsize_t); +extern int TIFFFlushData1(TIFF*); +extern int TIFFDefaultDirectory(TIFF*); +extern void _TIFFSetDefaultCompressionState(TIFF*); +extern int TIFFSetCompressionScheme(TIFF*, int); +extern int TIFFSetDefaultCompressionState(TIFF*); +extern uint32 _TIFFDefaultStripSize(TIFF*, uint32); +extern void _TIFFDefaultTileSize(TIFF*, uint32*, uint32*); +extern int _TIFFDataSize(TIFFDataType); + +extern void _TIFFsetByteArray(void**, void*, uint32); +extern void _TIFFsetString(char**, char*); +extern void _TIFFsetShortArray(uint16**, uint16*, uint32); +extern void _TIFFsetLongArray(uint32**, uint32*, uint32); +extern void _TIFFsetFloatArray(float**, float*, uint32); +extern void _TIFFsetDoubleArray(double**, double*, uint32); + +extern void _TIFFprintAscii(FILE*, const char*); +extern void _TIFFprintAsciiTag(FILE*, const char*, const char*); + +extern TIFFErrorHandler _TIFFwarningHandler; +extern TIFFErrorHandler _TIFFerrorHandler; +extern TIFFErrorHandlerExt _TIFFwarningHandlerExt; +extern TIFFErrorHandlerExt _TIFFerrorHandlerExt; + +extern tdata_t _TIFFCheckMalloc(TIFF*, size_t, size_t, const char*); +extern tdata_t _TIFFCheckRealloc(TIFF*, tdata_t, size_t, size_t, const char*); + +extern int TIFFInitDumpMode(TIFF*, int); +#ifdef PACKBITS_SUPPORT +extern int TIFFInitPackBits(TIFF*, int); +#endif +#ifdef CCITT_SUPPORT +extern int TIFFInitCCITTRLE(TIFF*, int), TIFFInitCCITTRLEW(TIFF*, int); +extern int TIFFInitCCITTFax3(TIFF*, int), TIFFInitCCITTFax4(TIFF*, int); +#endif +#ifdef THUNDER_SUPPORT +extern int TIFFInitThunderScan(TIFF*, int); +#endif +#ifdef NEXT_SUPPORT +extern int TIFFInitNeXT(TIFF*, int); +#endif +#ifdef LZW_SUPPORT +extern int TIFFInitLZW(TIFF*, int); +#endif +#ifdef OJPEG_SUPPORT +extern int TIFFInitOJPEG(TIFF*, int); +#endif +#ifdef JPEG_SUPPORT +extern int TIFFInitJPEG(TIFF*, int); +#endif +#ifdef JBIG_SUPPORT +extern int TIFFInitJBIG(TIFF*, int); +#endif +#ifdef ZIP_SUPPORT +extern int TIFFInitZIP(TIFF*, int); +#endif +#ifdef PIXARLOG_SUPPORT +extern int TIFFInitPixarLog(TIFF*, int); +#endif +#ifdef LOGLUV_SUPPORT +extern int TIFFInitSGILog(TIFF*, int); +#endif +#ifdef VMS +extern const TIFFCodec _TIFFBuiltinCODECS[]; +#else +extern TIFFCodec _TIFFBuiltinCODECS[]; +#endif + +#if defined(__cplusplus) +} +#endif +#endif /* _TIFFIOP_ */ + +/* vim: set ts=8 sts=8 sw=8 noet: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/include/reactos/libs/libtiff/tiffvers.h b/reactos/include/reactos/libs/libtiff/tiffvers.h new file mode 100644 index 00000000000..314a22a0ae9 --- /dev/null +++ b/reactos/include/reactos/libs/libtiff/tiffvers.h @@ -0,0 +1,9 @@ +#define TIFFLIB_VERSION_STR "LIBTIFF, Version 3.9.4\nCopyright (c) 1988-1996 Sam Leffler\nCopyright (c) 1991-1996 Silicon Graphics, Inc." +/* + * This define can be used in code that requires + * compilation-related definitions specific to a + * version or versions of the library. Runtime + * version checking should be done based on the + * string returned by TIFFGetVersion. + */ +#define TIFFLIB_VERSION 20100615 diff --git a/reactos/include/reactos/libs/libtiff/uvcode.h b/reactos/include/reactos/libs/libtiff/uvcode.h new file mode 100644 index 00000000000..50f11d7e0ae --- /dev/null +++ b/reactos/include/reactos/libs/libtiff/uvcode.h @@ -0,0 +1,180 @@ +/* Version 1.0 generated April 7, 1997 by Greg Ward Larson, SGI */ +#define UV_SQSIZ (float)0.003500 +#define UV_NDIVS 16289 +#define UV_VSTART (float)0.016940 +#define UV_NVS 163 +static struct { + float ustart; + short nus, ncum; +} uv_row[UV_NVS] = { + { (float)0.247663, 4, 0 }, + { (float)0.243779, 6, 4 }, + { (float)0.241684, 7, 10 }, + { (float)0.237874, 9, 17 }, + { (float)0.235906, 10, 26 }, + { (float)0.232153, 12, 36 }, + { (float)0.228352, 14, 48 }, + { (float)0.226259, 15, 62 }, + { (float)0.222371, 17, 77 }, + { (float)0.220410, 18, 94 }, + { (float)0.214710, 21, 112 }, + { (float)0.212714, 22, 133 }, + { (float)0.210721, 23, 155 }, + { (float)0.204976, 26, 178 }, + { (float)0.202986, 27, 204 }, + { (float)0.199245, 29, 231 }, + { (float)0.195525, 31, 260 }, + { (float)0.193560, 32, 291 }, + { (float)0.189878, 34, 323 }, + { (float)0.186216, 36, 357 }, + { (float)0.186216, 36, 393 }, + { (float)0.182592, 38, 429 }, + { (float)0.179003, 40, 467 }, + { (float)0.175466, 42, 507 }, + { (float)0.172001, 44, 549 }, + { (float)0.172001, 44, 593 }, + { (float)0.168612, 46, 637 }, + { (float)0.168612, 46, 683 }, + { (float)0.163575, 49, 729 }, + { (float)0.158642, 52, 778 }, + { (float)0.158642, 52, 830 }, + { (float)0.158642, 52, 882 }, + { (float)0.153815, 55, 934 }, + { (float)0.153815, 55, 989 }, + { (float)0.149097, 58, 1044 }, + { (float)0.149097, 58, 1102 }, + { (float)0.142746, 62, 1160 }, + { (float)0.142746, 62, 1222 }, + { (float)0.142746, 62, 1284 }, + { (float)0.138270, 65, 1346 }, + { (float)0.138270, 65, 1411 }, + { (float)0.138270, 65, 1476 }, + { (float)0.132166, 69, 1541 }, + { (float)0.132166, 69, 1610 }, + { (float)0.126204, 73, 1679 }, + { (float)0.126204, 73, 1752 }, + { (float)0.126204, 73, 1825 }, + { (float)0.120381, 77, 1898 }, + { (float)0.120381, 77, 1975 }, + { (float)0.120381, 77, 2052 }, + { (float)0.120381, 77, 2129 }, + { (float)0.112962, 82, 2206 }, + { (float)0.112962, 82, 2288 }, + { (float)0.112962, 82, 2370 }, + { (float)0.107450, 86, 2452 }, + { (float)0.107450, 86, 2538 }, + { (float)0.107450, 86, 2624 }, + { (float)0.107450, 86, 2710 }, + { (float)0.100343, 91, 2796 }, + { (float)0.100343, 91, 2887 }, + { (float)0.100343, 91, 2978 }, + { (float)0.095126, 95, 3069 }, + { (float)0.095126, 95, 3164 }, + { (float)0.095126, 95, 3259 }, + { (float)0.095126, 95, 3354 }, + { (float)0.088276, 100, 3449 }, + { (float)0.088276, 100, 3549 }, + { (float)0.088276, 100, 3649 }, + { (float)0.088276, 100, 3749 }, + { (float)0.081523, 105, 3849 }, + { (float)0.081523, 105, 3954 }, + { (float)0.081523, 105, 4059 }, + { (float)0.081523, 105, 4164 }, + { (float)0.074861, 110, 4269 }, + { (float)0.074861, 110, 4379 }, + { (float)0.074861, 110, 4489 }, + { (float)0.074861, 110, 4599 }, + { (float)0.068290, 115, 4709 }, + { (float)0.068290, 115, 4824 }, + { (float)0.068290, 115, 4939 }, + { (float)0.068290, 115, 5054 }, + { (float)0.063573, 119, 5169 }, + { (float)0.063573, 119, 5288 }, + { (float)0.063573, 119, 5407 }, + { (float)0.063573, 119, 5526 }, + { (float)0.057219, 124, 5645 }, + { (float)0.057219, 124, 5769 }, + { (float)0.057219, 124, 5893 }, + { (float)0.057219, 124, 6017 }, + { (float)0.050985, 129, 6141 }, + { (float)0.050985, 129, 6270 }, + { (float)0.050985, 129, 6399 }, + { (float)0.050985, 129, 6528 }, + { (float)0.050985, 129, 6657 }, + { (float)0.044859, 134, 6786 }, + { (float)0.044859, 134, 6920 }, + { (float)0.044859, 134, 7054 }, + { (float)0.044859, 134, 7188 }, + { (float)0.040571, 138, 7322 }, + { (float)0.040571, 138, 7460 }, + { (float)0.040571, 138, 7598 }, + { (float)0.040571, 138, 7736 }, + { (float)0.036339, 142, 7874 }, + { (float)0.036339, 142, 8016 }, + { (float)0.036339, 142, 8158 }, + { (float)0.036339, 142, 8300 }, + { (float)0.032139, 146, 8442 }, + { (float)0.032139, 146, 8588 }, + { (float)0.032139, 146, 8734 }, + { (float)0.032139, 146, 8880 }, + { (float)0.027947, 150, 9026 }, + { (float)0.027947, 150, 9176 }, + { (float)0.027947, 150, 9326 }, + { (float)0.023739, 154, 9476 }, + { (float)0.023739, 154, 9630 }, + { (float)0.023739, 154, 9784 }, + { (float)0.023739, 154, 9938 }, + { (float)0.019504, 158, 10092 }, + { (float)0.019504, 158, 10250 }, + { (float)0.019504, 158, 10408 }, + { (float)0.016976, 161, 10566 }, + { (float)0.016976, 161, 10727 }, + { (float)0.016976, 161, 10888 }, + { (float)0.016976, 161, 11049 }, + { (float)0.012639, 165, 11210 }, + { (float)0.012639, 165, 11375 }, + { (float)0.012639, 165, 11540 }, + { (float)0.009991, 168, 11705 }, + { (float)0.009991, 168, 11873 }, + { (float)0.009991, 168, 12041 }, + { (float)0.009016, 170, 12209 }, + { (float)0.009016, 170, 12379 }, + { (float)0.009016, 170, 12549 }, + { (float)0.006217, 173, 12719 }, + { (float)0.006217, 173, 12892 }, + { (float)0.005097, 175, 13065 }, + { (float)0.005097, 175, 13240 }, + { (float)0.005097, 175, 13415 }, + { (float)0.003909, 177, 13590 }, + { (float)0.003909, 177, 13767 }, + { (float)0.002340, 177, 13944 }, + { (float)0.002389, 170, 14121 }, + { (float)0.001068, 164, 14291 }, + { (float)0.001653, 157, 14455 }, + { (float)0.000717, 150, 14612 }, + { (float)0.001614, 143, 14762 }, + { (float)0.000270, 136, 14905 }, + { (float)0.000484, 129, 15041 }, + { (float)0.001103, 123, 15170 }, + { (float)0.001242, 115, 15293 }, + { (float)0.001188, 109, 15408 }, + { (float)0.001011, 103, 15517 }, + { (float)0.000709, 97, 15620 }, + { (float)0.000301, 89, 15717 }, + { (float)0.002416, 82, 15806 }, + { (float)0.003251, 76, 15888 }, + { (float)0.003246, 69, 15964 }, + { (float)0.004141, 62, 16033 }, + { (float)0.005963, 55, 16095 }, + { (float)0.008839, 47, 16150 }, + { (float)0.010490, 40, 16197 }, + { (float)0.016994, 31, 16237 }, + { (float)0.023659, 21, 16268 }, +}; +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/reactos/include/reactos/libs/zlib/crc32.h b/reactos/include/reactos/libs/zlib/crc32.h new file mode 100644 index 00000000000..8053b6117c0 --- /dev/null +++ b/reactos/include/reactos/libs/zlib/crc32.h @@ -0,0 +1,441 @@ +/* crc32.h -- tables for rapid CRC calculation + * Generated automatically by crc32.c + */ + +local const unsigned long FAR crc_table[TBLS][256] = +{ + { + 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, + 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, + 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, + 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, + 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, + 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, + 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, + 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, + 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, + 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, + 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, + 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, + 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, + 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, + 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, + 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, + 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, + 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, + 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, + 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, + 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, + 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, + 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, + 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, + 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, + 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, + 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, + 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, + 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, + 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, + 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, + 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, + 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, + 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, + 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, + 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, + 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, + 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, + 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, + 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, + 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, + 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, + 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, + 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, + 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, + 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, + 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, + 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, + 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, + 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, + 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, + 0x2d02ef8dUL +#ifdef BYFOUR + }, + { + 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, + 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, + 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, + 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, + 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, + 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, + 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, + 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, + 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, + 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, + 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, + 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, + 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, + 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, + 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, + 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, + 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, + 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, + 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, + 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, + 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, + 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, + 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, + 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, + 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, + 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, + 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, + 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, + 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, + 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, + 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, + 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, + 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, + 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, + 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, + 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, + 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, + 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, + 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, + 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, + 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, + 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, + 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, + 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, + 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, + 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, + 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, + 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, + 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, + 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, + 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, + 0x9324fd72UL + }, + { + 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, + 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, + 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, + 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, + 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, + 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, + 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, + 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, + 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, + 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, + 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, + 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, + 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, + 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, + 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, + 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, + 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, + 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, + 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, + 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, + 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, + 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, + 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, + 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, + 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, + 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, + 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, + 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, + 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, + 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, + 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, + 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, + 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, + 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, + 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, + 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, + 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, + 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, + 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, + 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, + 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, + 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, + 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, + 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, + 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, + 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, + 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, + 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, + 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, + 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, + 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, + 0xbe9834edUL + }, + { + 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, + 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, + 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, + 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, + 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, + 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, + 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, + 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, + 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, + 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, + 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, + 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, + 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, + 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, + 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, + 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, + 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, + 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, + 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, + 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, + 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, + 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, + 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, + 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, + 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, + 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, + 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, + 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, + 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, + 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, + 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, + 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, + 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, + 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, + 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, + 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, + 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, + 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, + 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, + 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, + 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, + 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, + 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, + 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, + 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, + 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, + 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, + 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, + 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, + 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, + 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, + 0xde0506f1UL + }, + { + 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, + 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, + 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, + 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, + 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, + 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, + 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, + 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, + 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, + 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, + 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, + 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, + 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, + 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, + 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, + 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, + 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, + 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, + 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, + 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, + 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, + 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, + 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, + 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, + 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, + 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, + 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, + 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, + 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, + 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, + 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, + 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, + 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, + 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, + 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, + 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, + 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, + 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, + 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, + 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, + 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, + 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, + 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, + 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, + 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, + 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, + 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, + 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, + 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, + 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, + 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, + 0x8def022dUL + }, + { + 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, + 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, + 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, + 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, + 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, + 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, + 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, + 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, + 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, + 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, + 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, + 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, + 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, + 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, + 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, + 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, + 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, + 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, + 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, + 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, + 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, + 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, + 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, + 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, + 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, + 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, + 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, + 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, + 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, + 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, + 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, + 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, + 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, + 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, + 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, + 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, + 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, + 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, + 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, + 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, + 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, + 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, + 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, + 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, + 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, + 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, + 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, + 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, + 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, + 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, + 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, + 0x72fd2493UL + }, + { + 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, + 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, + 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, + 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, + 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, + 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, + 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, + 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, + 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, + 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, + 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, + 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, + 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, + 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, + 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, + 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, + 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, + 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, + 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, + 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, + 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, + 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, + 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, + 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, + 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, + 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, + 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, + 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, + 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, + 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, + 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, + 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, + 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, + 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, + 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, + 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, + 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, + 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, + 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, + 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, + 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, + 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, + 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, + 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, + 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, + 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, + 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, + 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, + 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, + 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, + 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, + 0xed3498beUL + }, + { + 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, + 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, + 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, + 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, + 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, + 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, + 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, + 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, + 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, + 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, + 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, + 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, + 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, + 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, + 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, + 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, + 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, + 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, + 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, + 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, + 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, + 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, + 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, + 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, + 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, + 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, + 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, + 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, + 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, + 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, + 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, + 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, + 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, + 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, + 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, + 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, + 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, + 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, + 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, + 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, + 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, + 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, + 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, + 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, + 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, + 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, + 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, + 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, + 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, + 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, + 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, + 0xf10605deUL +#endif + } +}; diff --git a/reactos/include/reactos/libs/zlib/deflate.h b/reactos/include/reactos/libs/zlib/deflate.h new file mode 100644 index 00000000000..9488c490659 --- /dev/null +++ b/reactos/include/reactos/libs/zlib/deflate.h @@ -0,0 +1,342 @@ +/* deflate.h -- internal compression state + * Copyright (C) 1995-2010 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id: deflate.h 47933 2010-07-03 22:34:05Z dreimer $ */ + +#ifndef DEFLATE_H +#define DEFLATE_H + +#include "zutil.h" + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer creation by deflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip encoding + should be left enabled. */ +#ifndef NO_GZIP +# define GZIP +#endif + +/* =========================================================================== + * Internal compression state. + */ + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +#define MAX_BITS 15 +/* All codes must not exceed MAX_BITS bits */ + +#define INIT_STATE 42 +#define EXTRA_STATE 69 +#define NAME_STATE 73 +#define COMMENT_STATE 91 +#define HCRC_STATE 103 +#define BUSY_STATE 113 +#define FINISH_STATE 666 +/* Stream status */ + + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} FAR ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + static_tree_desc *stat_desc; /* the corresponding static tree */ +} FAR tree_desc; + +typedef ush Pos; +typedef Pos FAR Posf; +typedef unsigned IPos; + +/* A Pos is an index in the character window. We use short instead of int to + * save space in the various tables. IPos is used only for parameter passing. + */ + +typedef struct internal_state { + z_streamp strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Bytef *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ + Bytef *pending_out; /* next pending byte to output to the stream */ + uInt pending; /* nb of bytes in the pending buffer */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + gz_headerp gzhead; /* gzip header information to write */ + uInt gzindex; /* where in extra, name, or comment */ + Byte method; /* STORED (for zip only) or DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ + + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ + + Bytef *window; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. Also, it limits + * the window size to 64K, which is quite useful on MSDOS. + * To do: use the user input buffer as sliding window. + */ + + ulg window_size; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + Posf *prev; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + Posf *head; /* Heads of the hash chains or NIL. */ + + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ + + uInt hash_shift; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + long block_start; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ + + uInt prev_length; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + uInt max_chain_length; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + uInt max_lazy_match; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ +# define max_insert_length max_lazy_match + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + uInt good_match; + /* Use a faster search when the previous match is longer than this */ + + int nice_match; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + /* Didn't use ct_data typedef below to supress compiler warning */ + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ + + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + uch depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + uchf *l_buf; /* buffer for literals or lengths */ + + uInt lit_bufsize; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + uInt last_lit; /* running index in l_buf */ + + ushf *d_buf; + /* Buffer for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + uInt matches; /* number of string matches in current block */ + int last_eob_len; /* bit length of EOB code for last block */ + +#ifdef DEBUG + ulg compressed_len; /* total bit length of compressed file mod 2^32 */ + ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ +#endif + + ush bi_buf; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + int bi_valid; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + + ulg high_water; + /* High water mark offset in window for initialized bytes -- bytes above + * this are set to zero in order to avoid memory check warnings when + * longest match routines access bytes past the input. This is then + * updated to the new high water mark. + */ + +} FAR deflate_state; + +/* Output a byte on the stream. + * IN assertion: there is enough room in pending_buf. + */ +#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} + + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + +#define WIN_INIT MAX_MATCH +/* Number of bytes after end of data in window to initialize in order to avoid + memory checker errors from longest match routines */ + + /* in trees.c */ +void ZLIB_INTERNAL _tr_init OF((deflate_state *s)); +int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); +void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf, + ulg stored_len, int last)); +void ZLIB_INTERNAL _tr_align OF((deflate_state *s)); +void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, + ulg stored_len, int last)); + +#define d_code(dist) \ + ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. _dist_code[256] and _dist_code[257] are never + * used. + */ + +#ifndef DEBUG +/* Inline versions of _tr_tally for speed: */ + +#if defined(GEN_TREES_H) || !defined(STDC) + extern uch ZLIB_INTERNAL _length_code[]; + extern uch ZLIB_INTERNAL _dist_code[]; +#else + extern const uch ZLIB_INTERNAL _length_code[]; + extern const uch ZLIB_INTERNAL _dist_code[]; +#endif + +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->last_lit] = 0; \ + s->l_buf[s->last_lit++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (length); \ + ush dist = (distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +#else +# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) +# define _tr_tally_dist(s, distance, length, flush) \ + flush = _tr_tally(s, distance, length) +#endif + +#endif /* DEFLATE_H */ diff --git a/reactos/include/reactos/libs/zlib/gzguts.h b/reactos/include/reactos/libs/zlib/gzguts.h new file mode 100644 index 00000000000..aa075e75ea6 --- /dev/null +++ b/reactos/include/reactos/libs/zlib/gzguts.h @@ -0,0 +1,135 @@ +/* gzguts.h -- zlib internal header definitions for gz* operations + * Copyright (C) 2004, 2005, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifdef _LARGEFILE64_SOURCE +# ifndef _LARGEFILE_SOURCE +# define _LARGEFILE_SOURCE 1 +# endif +# ifdef _FILE_OFFSET_BITS +# undef _FILE_OFFSET_BITS +# endif +#endif + +#if ((__GNUC__-0) * 10 + __GNUC_MINOR__-0 >= 33) && !defined(NO_VIZ) +# define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) +#else +# define ZLIB_INTERNAL +#endif + +#include +#include "zlib.h" +#ifdef STDC +# include +# include +# include +#endif +#include + +#ifdef NO_DEFLATE /* for compatibility with old definition */ +# define NO_GZCOMPRESS +#endif + +#ifdef _WIN32 +# include +#endif + +#ifdef _MSC_VER +# define vsnprintf _vsnprintf +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +/* gz* functions always use library allocation functions */ +#ifndef STDC + extern voidp malloc OF((uInt size)); + extern void free OF((voidpf ptr)); +#endif + +/* get errno and strerror definition */ +#if defined UNDER_CE +# include +# define zstrerror() gz_strwinerror((DWORD)GetLastError()) +#else +# ifdef STDC +# include +# define zstrerror() strerror(errno) +# else +# define zstrerror() "stdio error (consult errno)" +# endif +#endif + +/* provide prototypes for these when building zlib without LFS */ +#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); + ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); +#endif + +/* default i/o buffer size -- double this for output when reading */ +#define GZBUFSIZE 8192 + +/* gzip modes, also provide a little integrity check on the passed structure */ +#define GZ_NONE 0 +#define GZ_READ 7247 +#define GZ_WRITE 31153 +#define GZ_APPEND 1 /* mode set to GZ_WRITE after the file is opened */ + +/* values for gz_state how */ +#define LOOK 0 /* look for a gzip header */ +#define COPY 1 /* copy input directly */ +#define GZIP 2 /* decompress a gzip stream */ + +/* internal gzip file state data structure */ +typedef struct { + /* used for both reading and writing */ + int mode; /* see gzip modes above */ + int fd; /* file descriptor */ + char *path; /* path or fd for error messages */ + z_off64_t pos; /* current position in uncompressed data */ + unsigned size; /* buffer size, zero if not allocated yet */ + unsigned want; /* requested buffer size, default is GZBUFSIZE */ + unsigned char *in; /* input buffer */ + unsigned char *out; /* output buffer (double-sized when reading) */ + unsigned char *next; /* next output data to deliver or write */ + /* just for reading */ + unsigned have; /* amount of output data unused at next */ + int eof; /* true if end of input file reached */ + z_off64_t start; /* where the gzip data started, for rewinding */ + z_off64_t raw; /* where the raw data started, for seeking */ + int how; /* 0: get header, 1: copy, 2: decompress */ + int direct; /* true if last read direct, false if gzip */ + /* just for writing */ + int level; /* compression level */ + int strategy; /* compression strategy */ + /* seek request */ + z_off64_t skip; /* amount to skip (already rewound if backwards) */ + int seek; /* true if seek request pending */ + /* error information */ + int err; /* error code */ + char *msg; /* error message */ + /* zlib inflate or deflate stream */ + z_stream strm; /* stream structure in-place (not a pointer) */ +} gz_state; +typedef gz_state FAR *gz_statep; + +/* shared functions */ +void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *)); +#if defined UNDER_CE +char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error)); +#endif + +/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t + value -- needed when comparing unsigned to z_off64_t, which is signed + (possible z_off64_t types off_t, off64_t, and long are all signed) */ +#ifdef INT_MAX +# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX) +#else +unsigned ZLIB_INTERNAL gz_intmax OF((void)); +# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax()) +#endif diff --git a/reactos/include/reactos/libs/zlib/inffast.h b/reactos/include/reactos/libs/zlib/inffast.h new file mode 100644 index 00000000000..e5c1aa4ca8c --- /dev/null +++ b/reactos/include/reactos/libs/zlib/inffast.h @@ -0,0 +1,11 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2003, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/reactos/include/reactos/libs/zlib/inffixed.h b/reactos/include/reactos/libs/zlib/inffixed.h new file mode 100644 index 00000000000..75ed4b5978d --- /dev/null +++ b/reactos/include/reactos/libs/zlib/inffixed.h @@ -0,0 +1,94 @@ + /* inffixed.h -- table for decoding fixed codes + * Generated automatically by makefixed(). + */ + + /* WARNING: this file should *not* be used by applications. It + is part of the implementation of the compression library and + is subject to change. Applications should only use zlib.h. + */ + + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} + }; + + static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} + }; diff --git a/reactos/include/reactos/libs/zlib/inflate.h b/reactos/include/reactos/libs/zlib/inflate.h new file mode 100644 index 00000000000..95f4986d400 --- /dev/null +++ b/reactos/include/reactos/libs/zlib/inflate.h @@ -0,0 +1,122 @@ +/* inflate.h -- internal inflate state definition + * Copyright (C) 1995-2009 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer decoding by inflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip decoding + should be left enabled. */ +#ifndef NO_GZIP +# define GUNZIP +#endif + +/* Possible inflate modes between inflate() calls */ +typedef enum { + HEAD, /* i: waiting for magic header */ + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY_, /* i/o: same as COPY below, but only first time in */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN_, /* i: same as LEN below, but only first time in */ + LEN, /* i: waiting for length/lit/eob code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ + LENGTH, /* i: waiting for 32-bit length (gzip) */ + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to BAD or MEM on error -- not shown for clarity) + + Process header: + HEAD -> (gzip) or (zlib) or (raw) + (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT -> + HCRC -> TYPE + (zlib) -> DICTID or TYPE + DICTID -> DICT -> TYPE + (raw) -> TYPEDO + Read deflate blocks: + TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK + STORED -> COPY_ -> COPY -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN_ + LEN_ -> LEN + Read deflate codes in fixed or dynamic block: + LEN -> LENEXT or LIT or TYPE + LENEXT -> DIST -> DISTEXT -> MATCH -> LEN + LIT -> LEN + Process trailer: + CHECK -> LENGTH -> DONE + */ + +/* state maintained between inflate() calls. Approximately 10K bytes. */ +struct inflate_state { + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags (0 if zlib) */ + unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + gz_headerp head; /* where to save gzip header information */ + /* sliding window */ + unsigned wbits; /* log base 2 of requested window size */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned wnext; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + /* bit accumulator */ + unsigned long hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + /* for string and stored block copying */ + unsigned length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + /* for table and code decoding */ + unsigned extra; /* extra bits needed */ + /* fixed and dynamic code tables */ + code const FAR *lencode; /* starting table for length/literal codes */ + code const FAR *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code FAR *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ + int sane; /* if false, allow invalid distance too far */ + int back; /* bits back of last unprocessed length/lit */ + unsigned was; /* initial length of match */ +}; diff --git a/reactos/include/reactos/libs/zlib/inftrees.h b/reactos/include/reactos/libs/zlib/inftrees.h new file mode 100644 index 00000000000..baa53a0b1a1 --- /dev/null +++ b/reactos/include/reactos/libs/zlib/inftrees.h @@ -0,0 +1,62 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2005, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ +} code; + +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 0001eeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ + +/* Maximum size of the dynamic table. The maximum number of code structures is + 1444, which is the sum of 852 for literal/length codes and 592 for distance + codes. These values were found by exhaustive searches using the program + examples/enough.c found in the zlib distribtution. The arguments to that + program are the number of symbols, the initial root table size, and the + maximum bit length of a code. "enough 286 9 15" for literal/length codes + returns returns 852, and "enough 30 6 15" for distance codes returns 592. + The initial root table size (9 or 6) is found in the fifth argument of the + inflate_table() calls in inflate.c and infback.c. If the root table size is + changed, then these maximum sizes would be need to be recalculated and + updated. */ +#define ENOUGH_LENS 852 +#define ENOUGH_DISTS 592 +#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS) + +/* Type of code to build for inflate_table() */ +typedef enum { + CODES, + LENS, + DISTS +} codetype; + +int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); diff --git a/reactos/include/reactos/libs/zlib/trees.h b/reactos/include/reactos/libs/zlib/trees.h new file mode 100644 index 00000000000..d35639d82a2 --- /dev/null +++ b/reactos/include/reactos/libs/zlib/trees.h @@ -0,0 +1,128 @@ +/* header created automatically with -DGEN_TREES_H */ + +local const ct_data static_ltree[L_CODES+2] = { +{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, +{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, +{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, +{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, +{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, +{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, +{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, +{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, +{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, +{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, +{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, +{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, +{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, +{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, +{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, +{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, +{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, +{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, +{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, +{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, +{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, +{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, +{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, +{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, +{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, +{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, +{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, +{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, +{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, +{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, +{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, +{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, +{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, +{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, +{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, +{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, +{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, +{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, +{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, +{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, +{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, +{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, +{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, +{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, +{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, +{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, +{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, +{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, +{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, +{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, +{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, +{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, +{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, +{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, +{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, +{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, +{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, +{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} +}; + +local const ct_data static_dtree[D_CODES] = { +{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, +{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, +{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, +{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, +{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, +{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} +}; + +const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, +10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, +12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, +18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 +}; + +const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, +13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, +17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, +19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, +21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, +22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 +}; + +local const int base_length[LENGTH_CODES] = { +0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, +64, 80, 96, 112, 128, 160, 192, 224, 0 +}; + +local const int base_dist[D_CODES] = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 +}; + diff --git a/reactos/include/reactos/libs/zlib/zconf.h b/reactos/include/reactos/libs/zlib/zconf.h new file mode 100644 index 00000000000..685d5d75ee6 --- /dev/null +++ b/reactos/include/reactos/libs/zlib/zconf.h @@ -0,0 +1,428 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2010 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: zconf.h 47691 2010-06-08 01:37:58Z tkreuzer $ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". + */ +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ + +/* all linked symbols */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define deflate z_deflate +# define deflateBound z_deflateBound +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzgetc z_gzgetc +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# define gzprintf z_gzprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzwrite z_gzwrite +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetHeader z_inflateGetHeader +# define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateUndermine z_inflateUndermine +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# define uncompress z_uncompress +# define zError z_zError +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +# define Byte z_Byte +# define Bytef z_Bytef +# define alloc_func z_alloc_func +# define charf z_charf +# define free_func z_free_func +# define gzFile z_gzFile +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# define in_func z_in_func +# define intf z_intf +# define out_func z_out_func +# define uInt z_uInt +# define uIntf z_uIntf +# define uLong z_uLong +# define uLongf z_uLongf +# define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# define gz_header_s z_gz_header_s +# define internal_state z_internal_state + +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H +#endif + +#ifdef STDC +# include /* for off_t */ +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# include /* for SEEK_* and off_t */ +# ifdef VMS +# include /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +#endif + +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif + +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 +# define z_off64_t off64_t +#else +# define z_off64_t z_off_t +#endif + +#if defined(__OS400__) +# define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/reactos/include/reactos/libs/zlib/zlib.h b/reactos/include/reactos/libs/zlib/zlib.h new file mode 100644 index 00000000000..bfbba83e8ee --- /dev/null +++ b/reactos/include/reactos/libs/zlib/zlib.h @@ -0,0 +1,1613 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.5, April 19th, 2010 + + Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.5" +#define ZLIB_VERNUM 0x1250 +#define ZLIB_VER_MAJOR 1 +#define ZLIB_VER_MINOR 2 +#define ZLIB_VER_REVISION 5 +#define ZLIB_VER_SUBREVISION 0 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed data. + This version of the library supports only one compression method (deflation) + but other algorithms will be added later and will have the same stream + interface. + + Compression can be done in a single step if the buffers are large enough, + or can be done by repeated calls of the compression function. In the latter + case, the application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip streams in memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never crash + even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has dropped + to zero. It must update next_out and avail_out when avail_out has dropped + to zero. The application must initialize zalloc, zfree and opaque before + calling the init function. All other fields are set by the compression + library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this if + the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers + returned by zalloc for objects of exactly 65536 bytes *must* have their + offset normalized to zero. The default allocation function provided by this + library ensures this (see zutil.c). To reduce memory requirements and avoid + any allocation of 64K objects, at the expense of compression ratio, compile + the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or progress + reports. After compression, total_in holds the total size of the + uncompressed data and may be saved for use in the decompressor (particularly + if the decompressor wants to decompress everything in a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +#define Z_TREES 6 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field (though see inflate()) */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is not + compatible with the zlib.h header file used by the application. This check + is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. If + zalloc and zfree are set to Z_NULL, deflateInit updates them to use default + allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at all + (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION + requests a default compromise between speed and compression (currently + equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if level is not a valid compression level, or + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). msg is set to null + if there is no error message. deflateInit does not perform any compression: + this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). Some + output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating avail_in or avail_out accordingly; avail_out should + never be zero before the call. The application can consume the compressed + output when it wants, for example when the output buffer is full (avail_out + == 0), or after each call of deflate(). If deflate returns Z_OK and with + zero avail_out, it must be called again after making room in the output + buffer because there might be more output pending. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumulate before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In + particular avail_in is zero after the call if enough output space has been + provided before the call.) Flushing may degrade compression for some + compression algorithms and so it should be used only when necessary. This + completes the current deflate block and follows it with an empty stored block + that is three bits plus filler bits to the next byte, followed by four bytes + (00 00 ff ff). + + If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the + output buffer, but the output is not aligned to a byte boundary. All of the + input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. + This completes the current deflate block and follows it with an empty fixed + codes block that is 10 bits long. This assures that enough bytes are output + in order for the decompressor to finish the block before the empty fixed code + block. + + If flush is set to Z_BLOCK, a deflate block is completed and emitted, as + for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to + seven bits of the current block are held to be written as the next byte after + the next deflate block is completed. In this case, the decompressor may not + be provided enough bits at this point in order to complete decompression of + the data provided so far to the compressor. It may need to wait for the next + block to be emitted. This is for advanced applications that need to control + the emission of deflate blocks. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there was + enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the stream + are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least the + value returned by deflateBound (see below). If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered + binary. This field is only for information purposes and does not affect the + compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was Z_NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not + fatal, and deflate() can be called again with more input and more output + space to continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, msg + may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the + exact value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit() does not process any header information -- that is deferred + until inflate() is called. +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing will + resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there is + no more input data or no more space in the output buffer (see below about + the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating the next_* and avail_* values accordingly. The + application can consume the uncompressed output when it wants, for example + when the output buffer is full (avail_out == 0), or after each call of + inflate(). If inflate returns Z_OK and with zero avail_out, it must be + called again after making room in the output buffer because there might be + more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, + Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() + stop if and when it gets to the next deflate block boundary. When decoding + the zlib or gzip format, this will cause inflate() to return immediately + after the header and before the first block. When doing a raw inflate, + inflate() will go ahead and process the first block, and will return when it + gets to the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + Also to assist in this, on return inflate() will set strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 if + inflate() is currently decoding the last block in the deflate stream, plus + 128 if inflate() returned immediately after decoding an end-of-block code or + decoding the complete header up to just before the first byte of the deflate + stream. The end-of-block will not be indicated until all of the uncompressed + data from that block has been written to strm->next_out. The number of + unused bits may in general be greater than seven, except when bit 7 of + data_type is set, in which case the number of unused bits will be less than + eight. data_type is set as noted here every time inflate() returns for all + flush options, and so can be used to determine the amount of currently + consumed input in bits. + + The Z_TREES option behaves as Z_BLOCK does, but it also returns when the + end of each deflate block header is reached, before any actual data in that + block is decoded. This allows the caller to determine the length of the + deflate block header for later use in random access within a deflate block. + 256 is added to the value of strm->data_type when inflate() returns + immediately after reaching the end of the deflate block header. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step (a + single call of inflate), the parameter flush should be set to Z_FINISH. In + this case all pending input is processed and all pending output is flushed; + avail_out must be large enough to hold all the uncompressed data. (The size + of the uncompressed data may have been saved by the compressor for this + purpose.) The next operation on this stream must be inflateEnd to deallocate + the decompression state. The use of Z_FINISH is never required, but can be + used to inform inflate that a faster approach may be used for the single + inflate() call. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the only effect of the flush parameter in this implementation + is on the return value of inflate(), as noted below, or when it returns early + because Z_BLOCK or Z_TREES is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the adler32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the adler32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() can decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically, if requested when + initializing with inflateInit2(). Any information contained in the gzip + header is not retained, so applications that need that information should + instead use raw inflate, see inflateInit2() below, or inflateBack() and + perform their own processing of the gzip header and trailer. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value), Z_STREAM_ERROR if the stream structure was inconsistent (for example + next_in or next_out was Z_NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is possible or if there was not enough room in the + output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may + then call inflateSync() to look for a good compression block if a partial + recovery of the data is desired. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by the + caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute an adler32 check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), no + header crc, and the operating system will be set to 255 (unknown). If a + gzip stream is being written, strm->adler is a crc32 instead of an adler32. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but is + slow and reduces compression ratio; memLevel=9 uses maximum memory for + optimal speed. The default value is 8. See zconf.h for total memory usage + as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as + fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The + strategy parameter only affects the compression ratio but not the + correctness of the compressed output even if it is not set appropriately. + Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler + decoder for special applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid + method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is + incompatible with the version assumed by the caller (ZLIB_VERSION). msg is + set to null if there is no error message. deflateInit2 does not perform any + compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any call + of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size + provided in deflateInit or deflateInit2. Thus the strings most likely to be + useful should be put at the end of the dictionary, not at the front. In + addition, the current implementation of deflate will use at most the window + size minus 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + adler32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and can + consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. The + stream will keep the same compression level and any other attributes that + may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different strategy. + If the compression level is changed, the input available so far is + compressed with the old level (and may be flushed); the new level will take + effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to be + compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR if + strm->avail_out was zero. +*/ + +ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain)); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() or + deflateInit2(), and after deflateSetHeader(), if used. This would be used + to allocate an output buffer for deflation in a single pass, and so would be + called before deflate(). +*/ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the bits + leftover from a previous deflate stream when appending to it. As such, this + function can only be used for raw deflate, and must be used before the first + deflate() call after a deflateInit2() or deflateReset(). bits must be less + than or equal to 16, and that many of the least significant bits of value + will be inserted in the output. + + deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, + gz_headerp head)); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to 255, with no extra, name, or comment + fields. The gzip header is returned to the default state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be zero to request that inflate use the window size in + the zlib header of the compressed stream. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an adler32 or a crc32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a + crc32 instead of an adler32. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit2 does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit2() does not process any header information -- that is + deferred until inflate() is called. +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called + immediately after inflateInit2() or inflateReset() and before any call of + inflate() to set the dictionary. The application must insure that the + dictionary that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been + found, or Z_STREAM_ERROR if the stream structure was inconsistent. In the + success case, the application may save the current current value of total_in + which indicates where valid compressed data was found. In the error case, + the application may repeatedly call inflateSync, providing more input each + time, until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. The + stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, + int windowBits)); +/* + This function is the same as inflateReset, but it also permits changing + the wrap and window size requests. The windowBits parameter is interpreted + the same as it is for inflateInit2. + + inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL), or if + the windowBits parameter is invalid. +*/ + +ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + If bits is negative, then the input stream bit buffer is emptied. Then + inflatePrime() can be called again to put bits in the buffer. This is used + to clear out bits leftover after feeding inflate a block description prior + to feeding inflate codes. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); +/* + This function returns two values, one in the lower 16 bits of the return + value, and the other in the remaining upper bits, obtained by shifting the + return value down 16 bits. If the upper value is -1 and the lower value is + zero, then inflate() is currently decoding information outside of a block. + If the upper value is -1 and the lower value is non-zero, then inflate is in + the middle of a stored block, with the lower value equaling the number of + bytes from the input remaining to copy. If the upper value is not -1, then + it is the number of bits back from the current bit position in the input of + the code (literal or length/distance pair) currently being processed. In + that case the lower value is the number of bytes already emitted for that + code. + + A code is being processed if inflate is waiting for more input to complete + decoding of the code, or if it has completed decoding but is waiting for + more output space to write the literal or match data. + + inflateMark() is used to mark locations in the input data for random + access, which may be at bit positions, and to note those cases where the + output of a code may span boundaries of random access blocks. The current + location in the input stream can be determined from avail_in and data_type + as noted in the description for the Z_BLOCK flush parameter for inflate. + + inflateMark returns the value noted above or -1 << 16 if the provided + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + gz_headerp head)); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be + used to force inflate() to return immediately after header processing is + complete and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When any + of extra, name, or comment are not Z_NULL and the respective field is not + present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the paramaters are invalid, Z_MEM_ERROR if the internal state could not be + allocated, or Z_VERSION_ERROR if the version of the library does not match + the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is more efficient than inflate() for + file i/o applications in that it avoids copying between the output and the + sliding window by simply making the window itself the output buffer. This + function trusts the application to not change the output buffer passed by + the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free the + allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects only + the raw deflate stream to decompress. This is different from the normal + behavior of inflate(), which expects either a zlib or gzip header and + trailer around the deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero--buf is ignored in that + case--and inflateBack() will return a buffer error. inflateBack() will call + out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() + should return zero on success, or non-zero on failure. If out() returns + non-zero, inflateBack() will return with an error. Neither in() nor out() + are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format error + in the deflate stream (in which case strm->msg is set to indicate the nature + of the error), or Z_STREAM_ERROR if the stream was not properly initialized. + In the case of Z_BUF_ERROR, an input or output error can be distinguished + using strm->next_in which will be Z_NULL only if in() returned an error. If + strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning + non-zero. (in() will always be called before out(), so strm->next_in is + assured to be defined if out() returns non-zero.) Note that inflateBack() + cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the basic + stream-oriented functions. To simplify the interface, some default options + are assumed (compression level and memory usage, standard memory allocation + functions). The source code of these utility functions can be modified if + you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before a + compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be large enough to hold the entire + uncompressed data. (The size of the uncompressed data must have been saved + previously by the compressor and transmitted to the decompressor by some + mechanism outside the scope of this compression library.) Upon exit, destLen + is the actual size of the uncompressed buffer. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. +*/ + + + /* gzip file access functions */ + +/* + This library supports reading and writing files in gzip (.gz) format with + an interface similar to that of stdio, using the functions that start with + "gz". The gzip format is different from the zlib format. gzip is a gzip + wrapper, documented in RFC 1952, wrapped around a deflate stream. +*/ + +typedef voidp gzFile; /* opaque gzip file descriptor */ + +/* +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); + + Opens a gzip (.gz) file for reading or writing. The mode parameter is as + in fopen ("rb" or "wb") but can also include a compression level ("wb9") or + a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only + compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' + for fixed code compression as in "wb9F". (See the description of + deflateInit2 for more information about the strategy parameter.) Also "a" + can be used instead of "w" to request that the gzip stream that will be + written be appended to the file. "+" will result in an error, since reading + and writing to the same gzip file is not supported. + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened, if there was + insufficient memory to allocate the gzFile state, or if an invalid mode was + specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). + errno can be checked to determine if the reason gzopen failed was that the + file could not be opened. +*/ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen associates a gzFile with the file descriptor fd. File descriptors + are obtained from calls like open, dup, creat, pipe or fileno (if the file + has been previously opened with fopen). The mode parameter is as in gzopen. + + The next call of gzclose on the returned gzFile will also close the file + descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor + fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, + mode);. The duplicated descriptor should be saved to avoid a leak, since + gzdopen does not close fd if it fails. + + gzdopen returns NULL if there was insufficient memory to allocate the + gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not + provided, or '+' was provided), or if fd is -1. The file descriptor is not + used until the next gz* read, write, seek, or close operation, so gzdopen + will not detect if fd is invalid (unless fd is -1). +*/ + +ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); +/* + Set the internal buffer size used by this library's functions. The + default buffer size is 8192 bytes. This function must be called after + gzopen() or gzdopen(), and before any other calls that read or write the + file. The buffer memory allocation is always deferred to the first read or + write. Two buffers are allocated, either both of the specified size when + writing, or one of the specified size and the other twice that size when + reading. A larger buffer size of, for example, 64K or 128K bytes will + noticeably increase the speed of decompression (reading). + + The new buffer size also affects the maximum length for gzprintf(). + + gzbuffer() returns 0 on success, or -1 on failure, such as being called + too late. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. If + the input file was not in gzip format, gzread copies the given number of + bytes into the buffer. + + After reaching the end of a gzip stream in the input, gzread will continue + to read, looking for another gzip stream, or failing that, reading the rest + of the input file directly without decompression. The entire input file + will be read if gzread is called until it returns less than the requested + len. + + gzread returns the number of uncompressed bytes actually read, less than + len for end of file, or -1 for error. +*/ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes written or 0 in case of + error. +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the arguments to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written, or 0 in case of error. The number of + uncompressed bytes written is limited to 8191, or one less than the buffer + size given to gzbuffer(). The caller should assure that this limit is not + exceeded. If it is exceeded, then gzprintf() will return an error (0) with + nothing written. In this case, there may also be a buffer overflow with + unpredictable consequences, which is possible only if zlib was compiled with + the insecure functions sprintf() or vsprintf() because the secure snprintf() + or vsnprintf() functions were not available. This can be determined using + zlibCompileFlags(). +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or a + newline character is read and transferred to buf, or an end-of-file + condition is encountered. If any characters are read or if len == 1, the + string is terminated with a null character. If no characters are read due + to an end-of-file or len < 1, then the buffer is left untouched. + + gzgets returns buf which is a null-terminated string, or it returns NULL + for end-of-file or in case of error. If there was an error, the contents at + buf are indeterminate. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. gzputc + returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte or -1 + in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read as the first character + on the next read. At least one character of push-back is allowed. + gzungetc() returns the character pushed, or -1 on failure. gzungetc() will + fail if c is -1, and may fail if a character has been pushed but not read + yet. If gzungetc is used immediately after gzopen or gzdopen, at least the + output buffer size of pushed characters is allowed. (See gzbuffer above.) + The pushed character will be discarded if the stream is repositioned with + gzseek() or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter flush + is as in the deflate() function. The return value is the zlib error number + (see function gzerror below). gzflush is only permitted when writing. + + If the flush parameter is Z_FINISH, the remaining data is written and the + gzip stream is completed in the output. If gzwrite() is called again, a new + gzip stream will be started in the output. gzread() is able to read such + concatented gzip streams. + + gzflush should be called only when strictly necessary because it will + degrade compression if called too often. +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); + + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); + + Returns the starting position for the next gzread or gzwrite on the given + compressed file. This position represents a number of bytes in the + uncompressed data stream, and is zero when starting, even if appending or + reading a gzip stream from the middle of a file using gzdopen(). + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); + + Returns the current offset in the file being read or written. This offset + includes the count of bytes that precede the gzip stream, for example when + appending or when using gzdopen() for reading. When reading, the offset + does not include as yet unused buffered input. This information can be used + for a progress indicator. On error, gzoffset() returns -1. +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns true (1) if the end-of-file indicator has been set while reading, + false (0) otherwise. Note that the end-of-file indicator is set only if the + read tried to go past the end of the input, but came up short. Therefore, + just like feof(), gzeof() may return false even if there is no more data to + read, in the event that the last read request was for the exact number of + bytes remaining in the input file. This will happen if the input file size + is an exact multiple of the buffer size. + + If gzeof() returns true, then the read functions will return no more data, + unless the end-of-file indicator is reset by gzclearerr() and the input file + has grown since the previous end of file was detected. +*/ + +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Returns true (1) if file is being copied directly while reading, or false + (0) if file is a gzip stream being decompressed. This state can change from + false to true while reading the input file if the end of a gzip stream is + reached, but is followed by data that is not another gzip stream. + + If the input file is empty, gzdirect() will return true, since the input + does not contain a gzip stream. + + If gzdirect() is used immediately after gzopen() or gzdopen() it will + cause buffers to be allocated to allow reading the file to determine if it + is a gzip file. Therefore if gzbuffer() is used, it should be called before + gzdirect(). +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file and + deallocates the (de)compression state. Note that once file is closed, you + cannot call gzerror with file, since its structures have been deallocated. + gzclose must not be called more than once on the same file, just as free + must not be called more than once on the same allocation. + + gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a + file operation error, or Z_OK on success. +*/ + +ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); +ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); +/* + Same as gzclose(), but gzclose_r() is only for use when reading, and + gzclose_w() is only for use when writing or appending. The advantage to + using these instead of gzclose() is that they avoid linking in zlib + compression or decompression code that is not used when only reading or only + writing respectively. If gzclose() is used, then both compression and + decompression code will be included the application when linking to a static + zlib library. +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the given + compressed file. errnum is set to zlib error number. If an error occurred + in the file system and not in the compression library, errnum is set to + Z_ERRNO and the application may consult errno to get the exact error code. + + The application must not modify the returned string. Future calls to + this function may invalidate the previously returned string. If file is + closed, then the string previously returned by gzerror will no longer be + available. + + gzerror() should be used to distinguish errors from end-of-file for those + functions above that do not distinguish those cases in their return values. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the compression + library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is Z_NULL, this function returns the + required initial value for the checksum. + + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. + + Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +/* +ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, + z_off_t len2)); + + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. If buf is Z_NULL, this function returns the required + initial value for the for the crc. Pre- and post-conditioning (one's + complement) is performed within this function so it shouldn't be done by the + application. + + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +/* +ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) +#define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, sizeof(z_stream)) + +/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or + * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if + * both are true, the application gets the *64 functions, and the regular + * functions are changed to 64 bits) -- in case these are set on systems + * without large file support, _LFS64_LARGEFILE must also be true + */ +#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); + ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); +#endif + +#if !defined(ZLIB_INTERNAL) && _FILE_OFFSET_BITS-0 == 64 && _LFS64_LARGEFILE-0 +# define gzopen gzopen64 +# define gzseek gzseek64 +# define gztell gztell64 +# define gzoffset gzoffset64 +# define adler32_combine adler32_combine64 +# define crc32_combine crc32_combine64 +# ifdef _LARGEFILE64_SOURCE + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +# endif +#else + ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); +#endif + +/* hack for buggy compilers */ +#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; +#endif + +/* undocumented functions */ +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); +ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/reactos/include/reactos/libs/zlib/zutil.h b/reactos/include/reactos/libs/zlib/zutil.h new file mode 100644 index 00000000000..643a8bf74d0 --- /dev/null +++ b/reactos/include/reactos/libs/zlib/zutil.h @@ -0,0 +1,274 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2010 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id: zutil.h 47933 2010-07-03 22:34:05Z dreimer $ */ + +#ifndef ZUTIL_H +#define ZUTIL_H + +#if ((__GNUC__-0) * 10 + __GNUC_MINOR__-0 >= 33) && !defined(NO_VIZ) +# define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) +#else +# define ZLIB_INTERNAL +#endif + +#include "zlib.h" + +#ifdef STDC +# if !(defined(_WIN32_WCE) && defined(_MSC_VER)) +# include +# endif +# include +# include +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = (char*)ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) +# define OS_CODE 0x00 +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif +# else /* MSC or DJGPP */ +# include +# endif +#endif + +#ifdef AMIGA +# define OS_CODE 0x01 +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 0x02 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 0x05 +#endif + +#ifdef OS2 +# define OS_CODE 0x06 +# ifdef M_I86 +# include +# endif +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 0x07 +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +#endif + +#ifdef TOPS20 +# define OS_CODE 0x0a +#endif + +#ifdef WIN32 +# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ +# define OS_CODE 0x0b +# endif +#endif + +#ifdef __50SERIES /* Prime/PRIMOS */ +# define OS_CODE 0x0f +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX +# if defined(_WIN32_WCE) +# define fdopen(fd,mode) NULL /* No fdopen() */ +# ifndef _PTRDIFF_T_DEFINED + typedef int ptrdiff_t; +# define _PTRDIFF_T_DEFINED +# endif +# else +# define fdopen(fd,type) _fdopen(fd,type) +# endif +#endif + +#if defined(__BORLANDC__) + #pragma warn -8004 + #pragma warn -8008 + #pragma warn -8066 +#endif + +/* provide prototypes for these when building zlib without LFS */ +#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0 + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +#endif + + /* common defaults */ + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#if defined(__CYGWIN__) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#ifndef HAVE_VSNPRINTF +# ifdef MSDOS + /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), + but for now we just assume it doesn't. */ +# define NO_vsnprintf +# endif +# ifdef __TURBOC__ +# define NO_vsnprintf +# endif +# ifdef WIN32 + /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ +# if !defined(vsnprintf) && !defined(NO_vsnprintf) +# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 ) +# define vsnprintf _vsnprintf +# endif +# endif +# endif +# ifdef __SASC +# define NO_vsnprintf +# endif +#endif +#ifdef VMS +# define NO_vsnprintf +#endif + +#if defined(pyr) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef DEBUG +# include + extern int ZLIB_INTERNAL z_verbose; + extern void ZLIB_INTERNAL z_error OF((char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + + +voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, + unsigned size)); +void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +#endif /* ZUTIL_H */ diff --git a/reactos/include/reactos/wine/config.h b/reactos/include/reactos/wine/config.h index d0e2e778758..95686aceef7 100644 --- a/reactos/include/reactos/wine/config.h +++ b/reactos/include/reactos/wine/config.h @@ -605,6 +605,21 @@ #define HAVE_STRNCASECMP 1 #endif +/* Define to 1 if you have the header file. */ +#define HAVE_TIFFIO_H 1 + +/* Define to the soname of the libtiff library. */ +#define SONAME_LIBTIFF 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_PNG_H 1 + +/* Define to 1 if libpng has the png_set_expand_gray_1_2_4_to_8 function. */ +#define HAVE_PNG_SET_EXPAND_GRAY_1_2_4_TO_8 1 + +/* Define to the soname of the libpng library. */ +#define SONAME_LIBPNG 1 + /* Define to 1 if `direction' is member of `struct ff_effect'. */ /* #undef HAVE_STRUCT_FF_EFFECT_DIRECTION */ From a71a4c79435d01460f42c2887445c03f97c8d6bc Mon Sep 17 00:00:00 2001 From: Daniel Reimer Date: Mon, 12 Jul 2010 19:07:39 +0000 Subject: [PATCH 29/43] Forgot to remove the old libpng. svn path=/trunk/; revision=48015 --- rosapps/lib/libpng/docs/ANNOUNCE | 62 - rosapps/lib/libpng/docs/CHANGES | 2041 ---------- rosapps/lib/libpng/docs/INSTALL | 219 -- rosapps/lib/libpng/docs/KNOWNBUG | 22 - rosapps/lib/libpng/docs/LICENSE | 109 - rosapps/lib/libpng/docs/README | 263 -- rosapps/lib/libpng/docs/TODO | 24 - rosapps/lib/libpng/docs/Y2KINFO | 55 - rosapps/lib/libpng/docs/example.c | 814 ---- rosapps/lib/libpng/docs/libpng-1.2.24.txt | 2851 -------------- rosapps/lib/libpng/libpng.rbuild | 27 - rosapps/lib/libpng/png.c | 798 ---- rosapps/lib/libpng/png.h | 3549 ----------------- rosapps/lib/libpng/pngconf.h | 1481 ------- rosapps/lib/libpng/pngerror.c | 343 -- rosapps/lib/libpng/pnggccrd.c | 101 - rosapps/lib/libpng/pngget.c | 901 ----- rosapps/lib/libpng/pngmem.c | 608 --- rosapps/lib/libpng/pngpread.c | 1586 -------- rosapps/lib/libpng/pngread.c | 1473 ------- rosapps/lib/libpng/pngrio.c | 167 - rosapps/lib/libpng/pngrtran.c | 4284 --------------------- rosapps/lib/libpng/pngrutil.c | 3164 --------------- rosapps/lib/libpng/pngset.c | 1250 ------ rosapps/lib/libpng/pngtest.c | 1556 -------- rosapps/lib/libpng/pngtrans.c | 662 ---- rosapps/lib/libpng/pngvcrd.c | 1 - rosapps/lib/libpng/pngwio.c | 234 -- rosapps/lib/libpng/pngwrite.c | 1516 -------- rosapps/lib/libpng/pngwtran.c | 572 --- rosapps/lib/libpng/pngwutil.c | 2792 -------------- 31 files changed, 33525 deletions(-) delete mode 100644 rosapps/lib/libpng/docs/ANNOUNCE delete mode 100644 rosapps/lib/libpng/docs/CHANGES delete mode 100644 rosapps/lib/libpng/docs/INSTALL delete mode 100644 rosapps/lib/libpng/docs/KNOWNBUG delete mode 100644 rosapps/lib/libpng/docs/LICENSE delete mode 100644 rosapps/lib/libpng/docs/README delete mode 100644 rosapps/lib/libpng/docs/TODO delete mode 100644 rosapps/lib/libpng/docs/Y2KINFO delete mode 100644 rosapps/lib/libpng/docs/example.c delete mode 100644 rosapps/lib/libpng/docs/libpng-1.2.24.txt delete mode 100644 rosapps/lib/libpng/libpng.rbuild delete mode 100644 rosapps/lib/libpng/png.c delete mode 100644 rosapps/lib/libpng/png.h delete mode 100644 rosapps/lib/libpng/pngconf.h delete mode 100644 rosapps/lib/libpng/pngerror.c delete mode 100644 rosapps/lib/libpng/pnggccrd.c delete mode 100644 rosapps/lib/libpng/pngget.c delete mode 100644 rosapps/lib/libpng/pngmem.c delete mode 100644 rosapps/lib/libpng/pngpread.c delete mode 100644 rosapps/lib/libpng/pngread.c delete mode 100644 rosapps/lib/libpng/pngrio.c delete mode 100644 rosapps/lib/libpng/pngrtran.c delete mode 100644 rosapps/lib/libpng/pngrutil.c delete mode 100644 rosapps/lib/libpng/pngset.c delete mode 100644 rosapps/lib/libpng/pngtest.c delete mode 100644 rosapps/lib/libpng/pngtrans.c delete mode 100644 rosapps/lib/libpng/pngvcrd.c delete mode 100644 rosapps/lib/libpng/pngwio.c delete mode 100644 rosapps/lib/libpng/pngwrite.c delete mode 100644 rosapps/lib/libpng/pngwtran.c delete mode 100644 rosapps/lib/libpng/pngwutil.c diff --git a/rosapps/lib/libpng/docs/ANNOUNCE b/rosapps/lib/libpng/docs/ANNOUNCE deleted file mode 100644 index c49c7b6bd61..00000000000 --- a/rosapps/lib/libpng/docs/ANNOUNCE +++ /dev/null @@ -1,62 +0,0 @@ - -Libpng 1.2.24 - December 14, 2007 - -This is a public release of libpng, intended for use in production codes. - -Files available for download: - -Source files with LF line endings (for Unix/Linux) and with a -"configure" script - - libpng-1.2.24.tar.gz - libpng-1.2.24.tar.bz2 - -Source files with LF line endings (for Unix/Linux) without the -"configure" script - - libpng-1.2.24-no-config.tar.gz - libpng-1.2.24-no-config.tar.bz2 - -Source files with CRLF line endings (for Windows), without the -"configure" script - - lpng1224.zip - lpng1224.tar.bz2 - -Project files - - libpng-1.2.24-project-netware.zip - libpng-1.2.24-project-wince.zip - -Other information: - - libpng-1.2.24-README.txt - libpng-1.2.24-KNOWNBUGS.txt - libpng-1.2.24-LICENSE.txt - libpng-1.2.24-Y2K-compliance.txt - -Changes since the last public release (1.2.23): - -version 1.2.24 [December 14, 2007] - - Moved misplaced test for malloc failure in png_set_sPLT(). This bug was - introduced in libpng-1.2.20. - Ifdef out avg_row etc from png.h and pngwrite.c when PNG_NO_WRITE_FILTER - Do not use png_ptr->free_fn and png_ptr->mem_fn in png_destroy_read_struct() - when png_ptr is NULL (Marshall Clow). - Updated handling of symbol prefixes in Makefile.am and configure.ac (Mike - Frysinger). - Removed a useless test and fixed incorrect test in png_set_cHRM_fixed() - (David Hill). - Make sure not to redefine _BSD_SOURCE in pngconf.h - Revised gather.sh and makefile.std in contrib/pngminim to avoid compiling - unused files. - - - -Send comments/corrections/commendations to png-mng-implement at lists.sf.net -(subscription required; visit -https://lists.sourceforge.net/lists/listinfo/png-mng-implement -to subscribe) or to glennrp at users.sourceforge.net - -Glenn R-P diff --git a/rosapps/lib/libpng/docs/CHANGES b/rosapps/lib/libpng/docs/CHANGES deleted file mode 100644 index a6e5856aa04..00000000000 --- a/rosapps/lib/libpng/docs/CHANGES +++ /dev/null @@ -1,2041 +0,0 @@ - -CHANGES - changes for libpng - -version 0.2 - added reader into png.h - fixed small problems in stub file - -version 0.3 - added pull reader - split up pngwrite.c to several files - added pnglib.txt - added example.c - cleaned up writer, adding a few new transformations - fixed some bugs in writer - interfaced with zlib 0.5 - added K&R support - added check for 64 KB blocks for 16 bit machines - -version 0.4 - cleaned up code and commented code - simplified time handling into png_time - created png_color_16 and png_color_8 to handle color needs - cleaned up color type defines - fixed various bugs - made various names more consistent - interfaced with zlib 0.71 - cleaned up zTXt reader and writer (using zlib's Reset functions) - split transformations into pngrtran.c and pngwtran.c - -version 0.5 - interfaced with zlib 0.8 - fixed many reading and writing bugs - saved using 3 spaces instead of tabs - -version 0.6 - added png_large_malloc() and png_large_free() - added png_size_t - cleaned up some compiler warnings - added png_start_read_image() - -version 0.7 - cleaned up lots of bugs - finished dithering and other stuff - added test program - changed name from pnglib to libpng - -version 0.71 [June, 1995] - changed pngtest.png for zlib 0.93 - fixed error in libpng.txt and example.c - -version 0.8 - cleaned up some bugs - added png_set_filler() - split up pngstub.c into pngmem.c, pngio.c, and pngerror.c - added #define's to remove unwanted code - moved png_info_init() to png.c - added old_size into png_realloc() - added functions to manually set filtering and compression info - changed compression parameters based on image type - optimized filter selection code - added version info - changed external functions passing floats to doubles (k&r problems?) - put all the configurable stuff in pngconf.h - enabled png_set_shift to work with paletted images on read - added png_read_update_info() - updates info structure with - transformations - -version 0.81 [August, 1995] - incorporated Tim Wegner's medium model code (thanks, Tim) - -version 0.82 [September, 1995] - [unspecified changes] - -version 0.85 [December, 1995] - added more medium model code (almost everything's a far) - added i/o, error, and memory callback functions - fixed some bugs (16 bit, 4 bit interlaced, etc.) - added first run progressive reader (barely tested) - -version 0.86 [January, 1996] - fixed bugs - improved documentation - -version 0.87 [January, 1996] - fixed medium model bugs - fixed other bugs introduced in 0.85 and 0.86 - added some minor documentation - -version 0.88 [January, 1996] - fixed progressive bugs - replaced tabs with spaces - cleaned up documentation - added callbacks for read/write and warning/error functions - -version 0.89 [July, 1996] - added new initialization API to make libpng work better with shared libs - we now have png_create_read_struct(), png_create_write_struct(), - png_create_info_struct(), png_destroy_read_struct(), and - png_destroy_write_struct() instead of the separate calls to - malloc and png_read_init(), png_info_init(), and png_write_init() - changed warning/error callback functions to fix bug - this means you - should use the new initialization API if you were using the old - png_set_message_fn() calls, and that the old API no longer exists - so that people are aware that they need to change their code - changed filter selection API to allow selection of multiple filters - since it didn't work in previous versions of libpng anyways - optimized filter selection code - fixed png_set_background() to allow using an arbitrary RGB color for - paletted images - fixed gamma and background correction for paletted images, so - png_correct_palette is not needed unless you are correcting an - external palette (you will need to #define PNG_CORRECT_PALETTE_SUPPORTED - in pngconf.h) - if nobody uses this, it may disappear in the future. - fixed bug with Borland 64K memory allocation (Alexander Lehmann) - fixed bug in interlace handling (Smarasderagd, I think) - added more error checking for writing and image to reduce invalid files - separated read and write functions so that they won't both be linked - into a binary when only reading or writing functionality is used - new pngtest image also has interlacing and zTXt - updated documentation to reflect new API - -version 0.90 [January, 1997] - made CRC errors/warnings on critical and ancillary chunks configurable - libpng will use the zlib CRC routines by (compile-time) default - changed DOS small/medium model memory support - needs zlib 1.04 (Tim Wegner) - added external C++ wrapper statements to png.h (Gilles Dauphin) - allow PNG file to be read when some or all of file signature has already - been read from the beginning of the stream. ****This affects the size - of info_struct and invalidates all programs that use a shared libpng**** - fixed png_filler() declarations - fixed? background color conversions - fixed order of error function pointers to match documentation - current chunk name is now available in png_struct to reduce the number - of nearly identical error messages (will simplify multi-lingual - support when available) - try to get ready for unknown-chunk callback functions: - - previously read critical chunks are flagged, so the chunk handling - routines can determine if the chunk is in the right place - - all chunk handling routines have the same prototypes, so we will - be able to handle all chunks via a callback mechanism - try to fix Linux "setjmp" buffer size problems - removed png_large_malloc, png_large_free, and png_realloc functions. - -version 0.95 [March, 1997] - fixed bug in pngwutil.c allocating "up_row" twice and "avg_row" never - fixed bug in PNG file signature compares when start != 0 - changed parameter type of png_set_filler(...filler...) from png_byte - to png_uint_32 - added test for MACOS to ensure that both math.h and fp.h are not #included - added macros for libpng to be compiled as a Windows DLL (Andreas Kupries) - added "packswap" transformation, which changes the endianness of - packed-pixel bytes (Kevin Bracey) - added "strip_alpha" transformation, which removes the alpha channel of - input images without using it (not necessarily a good idea) - added "swap_alpha" transformation, which puts the alpha channel in front - of the color bytes instead of after - removed all implicit variable tests which assume NULL == 0 (I think) - changed several variables to "png_size_t" to show 16/32-bit limitations - added new pCAL chunk read/write support - added experimental filter selection weighting (Greg Roelofs) - removed old png_set_rgbx() and png_set_xrgb() functions that have been - obsolete for about 2 years now (use png_set_filler() instead) - added macros to read 16- and 32-bit ints directly from buffer, to be - used only on those systems that support it (namely PowerPC and 680x0) - With some testing, this may become the default for MACOS/PPC systems. - only calculate CRC on data if we are going to use it - added macros for zTXt compression type PNG_zTXt_COMPRESSION_??? - added macros for simple libpng debugging output selectable at compile time - removed PNG_READ_END_MODE in progressive reader (Smarasderagd) - more description of info_struct in libpng.txt and png.h - more instructions in example.c - more chunk types tested in pngtest.c - renamed pngrcb.c to pngset.c, and all png_read_ functions to be - png_set_. We now have corresponding png_get_ - functions in pngget.c to get information in info_ptr. This isolates - the application from the internal organization of png_info_struct - (good for shared library implementations). - -version 0.96 [May, 1997] - fixed serious bug with < 8bpp images introduced in 0.95 - fixed 256-color transparency bug (Greg Roelofs) - fixed up documentation (Greg Roelofs, Laszlo Nyul) - fixed "error" in pngconf.h for Linux setjmp() behaviour - fixed DOS medium model support (Tim Wegner) - fixed png_check_keyword() for case with error in static string text - added read of CRC after IEND chunk for embedded PNGs (Laszlo Nyul) - added typecasts to quiet compiler errors - added more debugging info - -version 0.97 [January, 1998] - removed PNG_USE_OWN_CRC capability - relocated png_set_crc_action from pngrutil.c to pngrtran.c - fixed typecasts of "new_key", etc. (Andreas Dilger) - added RFC 1152 [sic] date support - fixed bug in gamma handling of 4-bit grayscale - added 2-bit grayscale gamma handling (Glenn R-P) - added more typecasts. 65536L becomes (png_uint_32)65536L, etc. (Glenn R-P) - minor corrections in libpng.txt - added simple sRGB support (Glenn R-P) - easier conditional compiling, e.g. define PNG_READ/WRITE_NOT_FULLY_SUPPORTED; - all configurable options can be selected from command-line instead - of having to edit pngconf.h (Glenn R-P) - fixed memory leak in pngwrite.c (free info_ptr->text) (Glenn R-P) - added more conditions for png_do_background, to avoid changing - black pixels to background when a background is supplied and - no pixels are transparent - repaired PNG_NO_STDIO behaviour - tested NODIV support and made it default behaviour (Greg Roelofs) - added "-m" option and PNGTEST_DEBUG_MEMORY to pngtest (John Bowler) - regularized version numbering scheme and bumped shared-library major - version number to 2 to avoid problems with libpng 0.89 apps (Greg Roelofs) - -version 0.98 [January, 1998] - cleaned up some typos in libpng.txt and in code documentation - fixed memory leaks in pCAL chunk processing (Glenn R-P and John Bowler) - cosmetic change "display_gamma" to "screen_gamma" in pngrtran.c - changed recommendation about file_gamma for PC images to .51 from .45, - in example.c and libpng.txt, added comments to distinguish between - screen_gamma, viewing_gamma, and display_gamma. - changed all references to RFC1152 to read RFC1123 and changed the - PNG_TIME_RFC1152_SUPPORTED macro to PNG_TIME_RFC1123_SUPPORTED - added png_invert_alpha capability (Glenn R-P -- suggestion by Jon Vincent) - changed srgb_intent from png_byte to int to avoid compiler bugs - -version 0.99 [January 30, 1998] - free info_ptr->text instead of end_info_ptr->text in pngread.c (John Bowler) - fixed a longstanding "packswap" bug in pngtrans.c - fixed some inconsistencies in pngconf.h that prevented compiling with - PNG_READ_GAMMA_SUPPORTED and PNG_READ_hIST_SUPPORTED undefined - fixed some typos and made other minor rearrangement of libpng.txt (Andreas) - changed recommendation about file_gamma for PC images to .50 from .51 in - example.c and libpng.txt, and changed file_gamma for sRGB images to .45 - added a number of functions to access information from the png structure - png_get_image_height(), etc. (Glenn R-P, suggestion by Brad Pettit) - added TARGET_MACOS similar to zlib-1.0.8 - define PNG_ALWAYS_EXTERN when __MWERKS__ && WIN32 are defined - added type casting to all png_malloc() function calls -version 0.99a [January 31, 1998] - Added type casts and parentheses to all returns that return a value.(Tim W.) -version 0.99b [February 4, 1998] - Added type cast png_uint_32 on malloc function calls where needed. - Changed type of num_hist from png_uint_32 to int (same as num_palette). - Added checks for rowbytes overflow, in case png_size_t is less than 32 bits. - Renamed makefile.elf to makefile.lnx. -version 0.99c [February 7, 1998] - More type casting. Removed erroneous overflow test in pngmem.c. - Added png_buffered_memcpy() and png_buffered_memset(), apply them to rowbytes. - Added UNIX manual pages libpng.3 (incorporating libpng.txt) and png.5. -version 0.99d [February 11, 1998] - Renamed "far_to_near()" "png_far_to_near()" - Revised libpng.3 - Version 99c "buffered" operations didn't work as intended. Replaced them - with png_memcpy_check() and png_memset_check(). - Added many "if (png_ptr == NULL) return" to quell compiler warnings about - unused png_ptr, mostly in pngget.c and pngset.c. - Check for overlength tRNS chunk present when indexed-color PLTE is read. - Cleaned up spelling errors in libpng.3/libpng.txt - Corrected a problem with png_get_tRNS() which returned undefined trans array -version 0.99e [February 28, 1998] - Corrected png_get_tRNS() again. - Add parentheses for easier reading of pngget.c, fixed "||" should be "&&". - Touched up example.c to make more of it compileable, although the entire - file still can't be compiled (Willem van Schaik) - Fixed a bug in png_do_shift() (Bryan Tsai) - Added a space in png.h prototype for png_write_chunk_start() - Replaced pngtest.png with one created with zlib 1.1.1 - Changed pngtest to report PASS even when file size is different (Jean-loup G.) - Corrected some logic errors in png_do_invert_alpha() (Chris Patterson) -version 0.99f [March 5, 1998] - Corrected a bug in pngpread() introduced in version 99c (Kevin Bracey) - Moved makefiles into a "scripts" directory, and added INSTALL instruction file - Added makefile.os2 and pngos2.def (A. Zabolotny) and makefile.s2x (W. Sebok) - Added pointers to "note on libpng versions" in makefile.lnx and README - Added row callback feature when reading and writing nonprogressive rows - and added a test of this feature in pngtest.c - Added user transform callbacks, with test of the feature in pngtest.c -version 0.99g [March 6, 1998, morning] - Minor changes to pngtest.c to suppress compiler warnings. - Removed "beta" language from documentation. -version 0.99h [March 6, 1998, evening] - Minor changes to previous minor changes to pngtest.c - Changed PNG_READ_NOT_FULLY_SUPPORTED to PNG_READ_TRANSFORMS_NOT_SUPPORTED - and added PNG_PROGRESSIVE_READ_NOT_SUPPORTED macro - Added user transform capability - -version 1.00 [March 7, 1998] - Changed several typedefs in pngrutil.c - Added makefile.wat (Pawel Mrochen), updated makefile.tc3 (Willem van Schaik) - replaced "while(1)" with "for(;;)" - added PNGARG() to prototypes in pngtest.c and removed some prototypes - updated some of the makefiles (Tom Lane) - changed some typedefs (s_start, etc.) in pngrutil.c - fixed dimensions of "short_months" array in pngwrite.c - Replaced ansi2knr.c with the one from jpeg-v6 - -version 1.0.0 [March 8, 1998] - Changed name from 1.00 to 1.0.0 (Adam Costello) - Added smakefile.ppc (with SCOPTIONS.ppc) for Amiga PPC (Andreas Kleinert) -version 1.0.0a [March 9, 1998] - Fixed three bugs in pngrtran.c to make gamma+background handling consistent - (Greg Roelofs) - Changed format of the PNG_LIBPNG_VER integer to xyyzz instead of xyz - for major, minor, and bugfix releases. This is 10001. (Adam Costello, - Tom Lane) - Make months range from 1-12 in png_convert_to_rfc1123 -version 1.0.0b [March 13, 1998] - Quieted compiler complaints about two empty "for" loops in pngrutil.c - Minor changes to makefile.s2x - Removed #ifdef/#endif around a png_free() in pngread.c - -version 1.0.1 [March 14, 1998] - Changed makefile.s2x to reduce security risk of using a relative pathname - Fixed some typos in the documentation (Greg). - Fixed a problem with value of "channels" returned by png_read_update_info() -version 1.0.1a [April 21, 1998] - Optimized Paeth calculations by replacing abs() function calls with intrinsics - plus other loop optimizations. Improves avg decoding speed by about 20%. - Commented out i386istic "align" compiler flags in makefile.lnx. - Reduced the default warning level in some makefiles, to make them consistent. - Removed references to IJG and JPEG in the ansi2knr.c copyright statement. - Fixed a bug in png_do_strip_filler with XXRRGGBB => RRGGBB transformation. - Added grayscale and 16-bit capability to png_do_read_filler(). - Fixed a bug in pngset.c, introduced in version 0.99c, that sets rowbytes - too large when writing an image with bit_depth < 8 (Bob Dellaca). - Corrected some bugs in the experimental weighted filtering heuristics. - Moved a misplaced pngrutil code block that truncates tRNS if it has more - than num_palette entries -- test was done before num_palette was defined. - Fixed a png_convert_to_rfc1123() bug that converts day 31 to 0 (Steve Eddins). - Changed compiler flags in makefile.wat for better optimization (Pawel Mrochen). -version 1.0.1b [May 2, 1998] - Relocated png_do_gray_to_rgb() within png_do_read_transformations() (Greg). - Relocated the png_composite macros from pngrtran.c to png.h (Greg). - Added makefile.sco (contributed by Mike Hopkirk). - Fixed two bugs (missing definitions of "istop") introduced in libpng-1.0.1a. - Fixed a bug in pngrtran.c that would set channels=5 under some circumstances. - More work on the Paeth-filtering, achieving imperceptible speedup (A Kleinert). - More work on loop optimization which may help when compiled with C++ compilers. - Added warnings when people try to use transforms they've defined out. - Collapsed 4 "i" and "c" loops into single "i" loops in pngrtran and pngwtran. - Revised paragraph about png_set_expand() in libpng.txt and libpng.3 (Greg) -version 1.0.1c [May 11, 1998] - Fixed a bug in pngrtran.c (introduced in libpng-1.0.1a) where the masks for - filler bytes should have been 0xff instead of 0xf. - Added max_pixel_depth=32 in pngrutil.c when using FILLER with palette images. - Moved PNG_WRITE_WEIGHTED_FILTER_SUPPORTED and PNG_WRITE_FLUSH_SUPPORTED - out of the PNG_WRITE_TRANSFORMS_NOT_SUPPORTED block of pngconf.h - Added "PNG_NO_WRITE_TRANSFORMS" etc., as alternatives for *_NOT_SUPPORTED, - for consistency, in pngconf.h - Added individual "ifndef PNG_NO_[CAPABILITY]" in pngconf.h to make it easier - to remove unwanted capabilities via the compile line - Made some corrections to grammar (which, it's) in documentation (Greg). - Corrected example.c, use of row_pointers in png_write_image(). -version 1.0.1d [May 24, 1998] - Corrected several statements that used side effects illegally in pngrutil.c - and pngtrans.c, that were introduced in version 1.0.1b - Revised png_read_rows() to avoid repeated if-testing for NULL (A Kleinert) - More corrections to example.c, use of row_pointers in png_write_image() - and png_read_rows(). - Added pngdll.mak and pngdef.pas to scripts directory, contributed by - Bob Dellaca, to make a png32bd.dll with Borland C++ 4.5 - Fixed error in example.c with png_set_text: num_text is 3, not 2 (Guido V.) - Changed several loops from count-down to count-up, for consistency. -version 1.0.1e [June 6, 1998] - Revised libpng.txt and libpng.3 description of png_set_read|write_fn(), and - added warnings when people try to set png_read_fn and png_write_fn in - the same structure. - Added a test such that png_do_gamma will be done when num_trans==0 - for truecolor images that have defined a background. This corrects an - error that was introduced in libpng-0.90 that can cause gamma processing - to be skipped. - Added tests in png.h to include "trans" and "trans_values" in structures - when PNG_READ_BACKGROUND_SUPPORTED or PNG_READ_EXPAND_SUPPORTED is defined. - Add png_free(png_ptr->time_buffer) in png_destroy_read_struct() - Moved png_convert_to_rfc_1123() from pngwrite.c to png.c - Added capability for user-provided malloc_fn() and free_fn() functions, - and revised pngtest.c to demonstrate their use, replacing the - PNGTEST_DEBUG_MEM feature. - Added makefile.w32, for Microsoft C++ 4.0 and later (Tim Wegner). - -version 1.0.2 [June 14, 1998] - Fixed two bugs in makefile.bor . -version 1.0.2a [December 30, 1998] - Replaced and extended code that was removed from png_set_filler() in 1.0.1a. - Fixed a bug in png_do_filler() that made it fail to write filler bytes in - the left-most pixel of each row (Kevin Bracey). - Changed "static pngcharp tIME_string" to "static char tIME_string[30]" - in pngtest.c (Duncan Simpson). - Fixed a bug in pngtest.c that caused pngtest to try to write a tIME chunk - even when no tIME chunk was present in the source file. - Fixed a problem in pngrutil.c: gray_to_rgb didn't always work with 16-bit. - Fixed a problem in png_read_push_finish_row(), which would not skip some - passes that it should skip, for images that are less than 3 pixels high. - Interchanged the order of calls to png_do_swap() and png_do_shift() - in pngwtran.c (John Cromer). - Added #ifdef PNG_DEBUG/#endif surrounding use of PNG_DEBUG in png.h . - Changed "bad adaptive filter type" from error to warning in pngrutil.c . - Fixed a documentation error about default filtering with 8-bit indexed-color. - Separated the PNG_NO_STDIO macro into PNG_NO_STDIO and PNG_NO_CONSOLE_IO - (L. Peter Deutsch). - Added png_set_rgb_to_gray() and png_get_rgb_to_gray_status() functions. - Added png_get_copyright() and png_get_header_version() functions. - Revised comments on png_set_progressive_read_fn() in libpng.txt and example.c - Added information about debugging in libpng.txt and libpng.3 . - Changed "ln -sf" to "ln -s -f" in makefile.s2x, makefile.lnx, and makefile.sco. - Removed lines after Dynamic Dependencies" in makefile.aco . - Revised makefile.dec to make a shared library (Jeremie Petit). - Removed trailing blanks from all files. -version 1.0.2a [January 6, 1999] - Removed misplaced #endif and #ifdef PNG_NO_EXTERN near the end of png.h - Added "if" tests to silence complaints about unused png_ptr in png.h and png.c - Changed "check_if_png" function in example.c to return true (nonzero) if PNG. - Changed libpng.txt to demonstrate png_sig_cmp() instead of png_check_sig() - which is obsolete. - -version 1.0.3 [January 14, 1999] - Added makefile.hux, for Hewlett Packard HPUX 10.20 and 11.00 (Jim Rice) - Added a statement of Y2K compliance in png.h, libpng.3, and Y2KINFO. -version 1.0.3a [August 12, 1999] - Added check for PNG_READ_INTERLACE_SUPPORTED in pngread.c; issue a warning - if an attempt is made to read an interlaced image when it's not supported. - Added check if png_ptr->trans is defined before freeing it in pngread.c - Modified the Y2K statement to include versions back to version 0.71 - Fixed a bug in the check for valid IHDR bit_depth/color_types in pngrutil.c - Modified makefile.wat (added -zp8 flag, ".symbolic", changed some comments) - Replaced leading blanks with tab characters in makefile.hux - Changed "dworkin.wustl.edu" to "ccrc.wustl.edu" in various documents. - Changed (float)red and (float)green to (double)red, (double)green - in png_set_rgb_to_gray() to avoid "promotion" problems in AIX. - Fixed a bug in pngconf.h that omitted when PNG_DEBUG==0 (K Bracey). - Reformatted libpng.3 and libpngpf.3 with proper fonts (script by J. vanZandt). - Updated documentation to refer to the PNG-1.2 specification. - Removed ansi2knr.c and left pointers to the latest source for ansi2knr.c - in makefile.knr, INSTALL, and README (L. Peter Deutsch) - Fixed bugs in calculation of the length of rowbytes when adding alpha - channels to 16-bit images, in pngrtran.c (Chris Nokleberg) - Added function png_set_user_transform_info() to store user_transform_ptr, - user_depth, and user_channels into the png_struct, and a function - png_get_user_transform_ptr() to retrieve the pointer (Chris Nokleberg) - Added function png_set_empty_plte_permitted() to make libpng useable - in MNG applications. - Corrected the typedef for png_free_ptr in png.h (Jesse Jones). - Correct gamma with srgb is 45455 instead of 45000 in pngrutil.c, to be - consistent with PNG-1.2, and allow variance of 500 before complaining. - Added assembler code contributed by Intel in file pngvcrd.c and modified - makefile.w32 to use it (Nirav Chhatrapati, INTEL Corporation, Gilles Vollant) - Changed "ln -s -f" to "ln -f -s" in the makefiles to make Solaris happy. - Added some aliases for png_set_expand() in pngrtran.c, namely - png_set_expand_PLTE(), png_set_expand_depth(), and png_set_expand_tRNS() - (Greg Roelofs, in "PNG: The Definitive Guide"). - Added makefile.beo for BEOS on X86, contributed by Sander Stok. -version 1.0.3b [August 26, 1999] - Replaced 2147483647L several places with PNG_MAX_UINT macro, defined in png.h - Changed leading blanks to tabs in all makefiles. - Define PNG_USE_PNGVCRD in makefile.w32, to get MMX assembler code. - Made alternate versions of png_set_expand() in pngrtran.c, namely - png_set_gray_1_2_4_to_8, png_set_palette_to_rgb, and png_set_tRNS_to_alpha - (Greg Roelofs, in "PNG: The Definitive Guide"). Deleted the 1.0.3a aliases. - Relocated start of 'extern "C"' block in png.h so it doesn't include pngconf.h - Revised calculation of num_blocks in pngmem.c to avoid a potentially - negative shift distance, whose results are undefined in the C language. - Added a check in pngset.c to prevent writing multiple tIME chunks. - Added a check in pngwrite.c to detect invalid small window_bits sizes. -version 1.0.3d [September 4, 1999] - Fixed type casting of igamma in pngrutil.c - Added new png_expand functions to scripts/pngdef.pas and pngos2.def - Added a demo read_user_transform_fn that examines the row filters in pngtest.c - -version 1.0.4 [September 24, 1999] - Define PNG_ALWAYS_EXTERN in pngconf.h if __STDC__ is defined - Delete #define PNG_INTERNAL and include "png.h" from pngasmrd.h - Made several minor corrections to pngtest.c - Renamed the makefiles with longer but more user friendly extensions. - Copied the PNG copyright and license to a separate LICENSE file. - Revised documentation, png.h, and example.c to remove reference to - "viewing_gamma" which no longer appears in the PNG specification. - Revised pngvcrd.c to use MMX code for interlacing only on the final pass. - Updated pngvcrd.c to use the faster C filter algorithms from libpng-1.0.1a - Split makefile.win32vc into two versions, makefile.vcawin32 (uses MMX - assembler code) and makefile.vcwin32 (doesn't). - Added a CPU timing report to pngtest.c (enabled by defining PNGTEST_TIMING) - Added a copy of pngnow.png to the distribution. -version 1.0.4a [September 25, 1999] - Increase max_pixel_depth in pngrutil.c if a user transform needs it. - Changed several division operations to right-shifts in pngvcrd.c -version 1.0.4b [September 30, 1999] - Added parentheses in line 3732 of pngvcrd.c - Added a comment in makefile.linux warning about buggy -O3 in pgcc 2.95.1 -version 1.0.4c [October 1, 1999] - Added a "png_check_version" function in png.c and pngtest.c that will generate - a helpful compiler error if an old png.h is found in the search path. - Changed type of png_user_transform_depth|channels from int to png_byte. -version 1.0.4d [October 6, 1999] - Changed 0.45 to 0.45455 in png_set_sRGB() - Removed unused PLTE entries from pngnow.png - Re-enabled some parts of pngvcrd.c (png_combine_row) that work properly. -version 1.0.4e [October 10, 1999] - Fixed sign error in pngvcrd.c (Greg Roelofs) - Replaced some instances of memcpy with simple assignments in pngvcrd (GR-P) -version 1.0.4f [October 15, 1999] - Surrounded example.c code with #if 0 .. #endif to prevent people from - inadvertently trying to compile it. - Changed png_get_header_version() from a function to a macro in png.h - Added type casting mostly in pngrtran.c and pngwtran.c - Removed some pointless "ptr = NULL" in pngmem.c - Added a "contrib" directory containing the source code from Greg's book. - -version 1.0.5 [October 15, 1999] - Minor editing of the INSTALL and README files. -version 1.0.5a [October 23, 1999] - Added contrib/pngsuite and contrib/pngminus (Willem van Schaik) - Fixed a typo in the png_set_sRGB() function call in example.c (Jan Nijtmans) - Further optimization and bugfix of pngvcrd.c - Revised pngset.c so that it does not allocate or free memory in the user's - text_ptr structure. Instead, it makes its own copy. - Created separate write_end_info_struct in pngtest.c for a more severe test. - Added code in pngwrite.c to free info_ptr->text[i].key to stop a memory leak. -version 1.0.5b [November 23, 1999] - Moved PNG_FLAG_HAVE_CHUNK_HEADER, PNG_FLAG_BACKGROUND_IS_GRAY and - PNG_FLAG_WROTE_tIME from flags to mode. - Added png_write_info_before_PLTE() function. - Fixed some typecasting in contrib/gregbook/*.c - Updated scripts/makevms.com and added makevms.com to contrib/gregbook - and contrib/pngminus (Martin Zinser) -version 1.0.5c [November 26, 1999] - Moved png_get_header_version from png.h to png.c, to accommodate ansi2knr. - Removed all global arrays (according to PNG_NO_GLOBAL_ARRAYS macro), to - accommodate making DLL's: Moved usr_png_ver from global variable to function - png_get_header_ver() in png.c. Moved png_sig to png_sig_bytes in png.c and - eliminated use of png_sig in pngwutil.c. Moved the various png_CHNK arrays - into pngtypes.h. Eliminated use of global png_pass arrays. Declared the - png_CHNK and png_pass arrays to be "const". Made the global arrays - available to applications (although none are used in libpng itself) when - PNG_NO_GLOBAL_ARRAYS is not defined or when PNG_GLOBAL_ARRAYS is defined. - Removed some extraneous "-I" from contrib/pngminus/makefile.std - Changed the PNG_sRGB_INTENT macros in png.h to be consistent with PNG-1.2. - Change PNG_SRGB_INTENT to PNG_sRGB_INTENT in libpng.txt and libpng.3 -version 1.0.5d [November 29, 1999] - Add type cast (png_const_charp) two places in png.c - Eliminated pngtypes.h; use macros instead to declare PNG_CHNK arrays. - Renamed "PNG_GLOBAL_ARRAYS" to "PNG_USE_GLOBAL_ARRAYS" and made available - to applications a macro "PNG_USE_LOCAL_ARRAYS". - #ifdef out all the new declarations when PNG_USE_GLOBAL_ARRAYS is defined. - Added PNG_EXPORT_VAR macro to accommodate making DLL's. -version 1.0.5e [November 30, 1999] - Added iCCP, iTXt, and sPLT support; added "lang" member to the png_text - structure; refactored the inflate/deflate support to make adding new chunks - with trailing compressed parts easier in the future, and added new functions - png_free_iCCP, png_free_pCAL, png_free_sPLT, png_free_text, png_get_iCCP, - png_get_spalettes, png_set_iCCP, png_set_spalettes (Eric S. Raymond). - NOTE: Applications that write text chunks MUST define png_text->lang - before calling png_set_text(). It must be set to NULL if you want to - write tEXt or zTXt chunks. If you want your application to be able to - run with older versions of libpng, use - - #ifdef PNG_iTXt_SUPPORTED - png_text[i].lang = NULL; - #endif - - Changed png_get_oFFs() and png_set_oFFs() to use signed rather than unsigned - offsets (Eric S. Raymond). - Combined PNG_READ_cHNK_SUPPORTED and PNG_WRITE_cHNK_SUPPORTED macros into - PNG_cHNK_SUPPORTED and combined the three types of PNG_text_SUPPORTED - macros, leaving the separate macros also available. - Removed comments on #endifs at the end of many short, non-nested #if-blocks. -version 1.0.5f [December 6, 1999] - Changed makefile.solaris to issue a warning about potential problems when - the ucb "ld" is in the path ahead of the ccs "ld". - Removed "- [date]" from the "synopsis" line in libpng.3 and libpngpf.3. - Added sCAL chunk support (Eric S. Raymond). -version 1.0.5g [December 7, 1999] - Fixed "png_free_spallettes" typo in png.h - Added code to handle new chunks in pngpread.c - Moved PNG_CHNK string macro definitions outside of PNG_NO_EXTERN block - Added "translated_key" to png_text structure and png_write_iTXt(). - Added code in pngwrite.c to work around a newly discovered zlib bug. -version 1.0.5h [December 10, 1999] - NOTE: regarding the note for version 1.0.5e, the following must also - be included in your code: - png_text[i].translated_key = NULL; - Unknown chunk handling is now supported. - Option to eliminate all floating point support was added. Some new - fixed-point functions such as png_set_gAMA_fixed() were added. - Expanded tabs and removed trailing blanks in source files. -version 1.0.5i [December 13, 1999] - Added some type casts to silence compiler warnings. - Renamed "png_free_spalette" to "png_free_spalettes" for consistency. - Removed leading blanks from a #define in pngvcrd.c - Added some parameters to the new png_set_keep_unknown_chunks() function. - Added a test for up->location != 0 in the first instance of writing - unknown chunks in pngwrite.c - Changed "num" to "i" in png_free_spalettes() and png_free_unknowns() to - prevent recursion. - Added png_free_hIST() function. - Various patches to fix bugs in the sCAL and integer cHRM processing, - and to add some convenience macros for use with sCAL. -version 1.0.5j [December 21, 1999] - Changed "unit" parameter of png_write_sCAL from png_byte to int, to work - around buggy compilers. - Added new type "png_fixed_point" for integers that hold float*100000 values - Restored backward compatibility of tEXt/zTXt chunk processing: - Restored the first four members of png_text to the same order as v.1.0.5d. - Added members "lang_key" and "itxt_length" to png_text struct. Set - text_length=0 when "text" contains iTXt data. Use the "compression" - member to distinguish among tEXt/zTXt/iTXt types. Added - PNG_ITXT_COMPRESSION_NONE (1) and PNG_ITXT_COMPRESSION_zTXt(2) macros. - The "Note" above, about backward incompatibility of libpng-1.0.5e, no - longer applies. - Fixed png_read|write_iTXt() to read|write parameters in the right order, - and to write the iTXt chunk after IDAT if it appears in the end_ptr. - Added pnggccrd.c, version of pngvcrd.c Intel assembler for gcc (Greg Roelofs) - Reversed the order of trying to write floating-point and fixed-point gAMA. -version 1.0.5k [December 27, 1999] - Added many parentheses, e.g., "if (a && b & c)" becomes "if (a && (b & c))" - Added png_handle_as_unknown() function (Glenn) - Added png_free_chunk_list() function and chunk_list and num_chunk_list members - of png_ptr. - Eliminated erroneous warnings about multiple sPLT chunks and sPLT-after-PLTE. - Fixed a libpng-1.0.5h bug in pngrutil.c that was issuing erroneous warnings - about ignoring incorrect gAMA with sRGB (gAMA was in fact not ignored) - Added png_free_tRNS(); png_set_tRNS() now malloc's its own trans array (ESR). - Define png_get_int_32 when oFFs chunk is supported as well as when pCAL is. - Changed type of proflen from png_int_32 to png_uint_32 in png_get_iCCP(). -version 1.0.5l [January 1, 2000] - Added functions png_set_read_user_chunk_fn() and png_get_user_chunk_ptr() - for setting a callback function to handle unknown chunks and for - retrieving the associated user pointer (Glenn). -version 1.0.5m [January 7, 2000] - Added high-level functions png_read_png(), png_write_png(), png_free_pixels(). -version 1.0.5n [January 9, 2000] - Added png_free_PLTE() function, and modified png_set_PLTE() to malloc its - own memory for info_ptr->palette. This makes it safe for the calling - application to free its copy of the palette any time after it calls - png_set_PLTE(). -version 1.0.5o [January 20, 2000] - Cosmetic changes only (removed some trailing blanks and TABs) -version 1.0.5p [January 31, 2000] - Renamed pngdll.mak to makefile.bd32 - Cosmetic changes in pngtest.c -version 1.0.5q [February 5, 2000] - Relocated the makefile.solaris warning about PATH problems. - Fixed pngvcrd.c bug by pushing/popping registers in mmxsupport (Bruce Oberg) - Revised makefile.gcmmx - Added PNG_SETJMP_SUPPORTED, PNG_SETJMP_NOT_SUPPORTED, and PNG_ABORT() macros -version 1.0.5r [February 7, 2000] - Removed superfluous prototype for png_get_itxt from png.h - Fixed a bug in pngrtran.c that improperly expanded the background color. - Return *num_text=0 from png_get_text() when appropriate, and fix documentation - of png_get_text() in libpng.txt/libpng.3. -version 1.0.5s [February 18, 2000] - Added "png_jmp_env()" macro to pngconf.h, to help people migrate to the - new error handler that's planned for the next libpng release, and changed - example.c, pngtest.c, and contrib programs to use this macro. - Revised some of the DLL-export macros in pngconf.h (Greg Roelofs) - Fixed a bug in png_read_png() that caused it to fail to expand some images - that it should have expanded. - Fixed some mistakes in the unused and undocumented INCH_CONVERSIONS functions - in pngget.c - Changed the allocation of palette, history, and trans arrays back to - the version 1.0.5 method (linking instead of copying) which restores - backward compatibility with version 1.0.5. Added some remarks about - that in example.c. Added "free_me" member to info_ptr and png_ptr - and added png_free_data() function. - Updated makefile.linux and makefile.gccmmx to make directories conditionally. - Made cosmetic changes to pngasmrd.h - Added png_set_rows() and png_get_rows(), for use with png_read|write_png(). - Modified png_read_png() to allocate info_ptr->row_pointers only if it - hasn't already been allocated. -version 1.0.5t [March 4, 2000] - Changed png_jmp_env() migration aiding macro to png_jmpbuf(). - Fixed "interlace" typo (should be "interlaced") in contrib/gregbook/read2-x.c - Fixed bug with use of PNG_BEFORE_IHDR bit in png_ptr->mode, introduced when - PNG_FLAG_HAVE_CHUNK_HEADER was moved into png_ptr->mode in version 1.0.5b - Files in contrib/gregbook were revised to use png_jmpbuf() and to select - a 24-bit visual if one is available, and to allow abbreviated options. - Files in contrib/pngminus were revised to use the png_jmpbuf() macro. - Removed spaces in makefile.linux and makefile.gcmmx, introduced in 1.0.5s -version 1.0.5u [March 5, 2000] - Simplified the code that detects old png.h in png.c and pngtest.c - Renamed png_spalette (_p, _pp) to png_sPLT_t (_tp, _tpp) - Increased precision of rgb_to_gray calculations from 8 to 15 bits and - added png_set_rgb_to_gray_fixed() function. - Added makefile.bc32 (32-bit Borland C++, C mode) -version 1.0.5v [March 11, 2000] - Added some parentheses to the png_jmpbuf macro definition. - Updated references to the zlib home page, which has moved to freesoftware.com. - Corrected bugs in documentation regarding png_read_row() and png_write_row(). - Updated documentation of png_rgb_to_gray calculations in libpng.3/libpng.txt. - Renamed makefile.borland,turboc3 back to makefile.bor,tc3 as in version 1.0.3, - revised borland makefiles; added makefile.ibmvac3 and makefile.gcc (Cosmin) - -version 1.0.6 [March 20, 2000] - Minor revisions of makefile.bor, libpng.txt, and gregbook/rpng2-win.c - Added makefile.sggcc (SGI IRIX with gcc) -version 1.0.6d [April 7, 2000] - Changed sprintf() to strcpy() in png_write_sCAL_s() to work without STDIO - Added data_length parameter to png_decompress_chunk() function - Revised documentation to remove reference to abandoned png_free_chnk functions - Fixed an error in png_rgb_to_gray_fixed() - Revised example.c, usage of png_destroy_write_struct(). - Renamed makefile.ibmvac3 to makefile.ibmc, added libpng.icc IBM project file - Added a check for info_ptr->free_me&PNG_FREE_TEXT when freeing text in png.c - Simplify png_sig_bytes() function to remove use of non-ISO-C strdup(). -version 1.0.6e [April 9, 2000] - Added png_data_freer() function. - In the code that checks for over-length tRNS chunks, added check of - info_ptr->num_trans as well as png_ptr->num_trans (Matthias Benckmann) - Minor revisions of libpng.txt/libpng.3. - Check for existing data and free it if the free_me flag is set, in png_set_*() - and png_handle_*(). - Only define PNG_WEIGHTED_FILTERS_SUPPORTED when PNG_FLOATING_POINT_SUPPORTED - is defined. - Changed several instances of PNG_NO_CONSOLE_ID to PNG_NO_STDIO in pngrutil.c - and mentioned the purposes of the two macros in libpng.txt/libpng.3. -version 1.0.6f [April 14, 2000] - Revised png_set_iCCP() and png_set_rows() to avoid prematurely freeing data. - Add checks in png_set_text() for NULL members of the input text structure. - Revised libpng.txt/libpng.3. - Removed superfluous prototype for png_set_itxt from png.h - Removed "else" from pngread.c, after png_error(), and changed "0" to "length". - Changed several png_errors about malformed ancillary chunks to png_warnings. -version 1.0.6g [April 24, 2000] - Added png_pass-* arrays to pnggccrd.c when PNG_USE_LOCAL_ARRAYS is defined. - Relocated paragraph about png_set_background() in libpng.3/libpng.txt - and other revisions (Matthias Benckmann) - Relocated info_ptr->free_me, png_ptr->free_me, and other info_ptr and - png_ptr members to restore binary compatibility with libpng-1.0.5 - (breaks compatibility with libpng-1.0.6). -version 1.0.6h [April 24, 2000] - Changed shared library so-number pattern from 2.x.y.z to xy.z (this builds - libpng.so.10 & libpng.so.10.6h instead of libpng.so.2 & libpng.so.2.1.0.6h) - This is a temporary change for test purposes. -version 1.0.6i [May 2, 2000] - Rearranged some members at the end of png_info and png_struct, to put - unknown_chunks_num and free_me within the original size of the png_structs - and free_me, png_read_user_fn, and png_free_fn within the original png_info, - because some old applications allocate the structs directly instead of - using png_create_*(). - Added documentation of user memory functions in libpng.txt/libpng.3 - Modified png_read_png so that it will use user_allocated row_pointers - if present, unless free_me directs that it be freed, and added description - of the use of png_set_rows() and png_get_rows() in libpng.txt/libpng.3. - Added PNG_LEGACY_SUPPORTED macro, and #ifdef out all new (since version - 1.00) members of png_struct and png_info, to regain binary compatibility - when you define this macro. Capabilities lost in this event - are user transforms (new in version 1.0.0),the user transform pointer - (new in version 1.0.2), rgb_to_gray (new in 1.0.5), iCCP, sCAL, sPLT, - the high-level interface, and unknown chunks support (all new in 1.0.6). - This was necessary because of old applications that allocate the structs - directly as authors were instructed to do in libpng-0.88 and earlier, - instead of using png_create_*(). - Added modes PNG_CREATED_READ_STRUCT and PNG_CREATED_WRITE_STRUCT which - can be used to detect codes that directly allocate the structs, and - code to check these modes in png_read_init() and png_write_init() and - generate a libpng error if the modes aren't set and PNG_LEGACY_SUPPORTED - was not defined. - Added makefile.intel and updated makefile.watcom (Pawel Mrochen) -version 1.0.6j [May 3, 2000] - Overloaded png_read_init() and png_write_init() with macros that convert - calls to png_read_init_2() or png_write_init_2() that check the version - and structure sizes. -version 1.0.7beta11 [May 7, 2000] - Removed the new PNG_CREATED_READ_STRUCT and PNG_CREATED_WRITE_STRUCT modes - which are no longer used. - Eliminated the three new members of png_text when PNG_LEGACY_SUPPORTED is - defined or when neither PNG_READ_iTXt_SUPPORTED nor PNG_WRITE_iTXT_SUPPORTED - is defined. - Made PNG_NO_READ|WRITE_iTXt the default setting, to avoid memory - overrun when old applications fill the info_ptr->text structure directly. - Added PNGAPI macro, and added it to the definitions of all exported functions. - Relocated version macro definitions ahead of the includes of zlib.h and - pngconf.h in png.h. -version 1.0.7beta12 [May 12, 2000] - Revised pngset.c to avoid a problem with expanding the png_debug macro. - Deleted some extraneous defines from pngconf.h - Made PNG_NO_CONSOLE_IO the default condition when PNG_BUILD_DLL is defined. - Use MSC _RPTn debugging instead of fprintf if _MSC_VER is defined. - Added png_access_version_number() function. - Check for mask&PNG_FREE_CHNK (for TEXT, SCAL, PCAL) in png_free_data(). - Expanded libpng.3/libpng.txt information about png_data_freer(). -version 1.0.7beta14 [May 17, 2000] (beta13 was not published) - Changed pnggccrd.c and pngvcrd.c to handle bad adaptive filter types as - warnings instead of errors, as pngrutil.c does. - Set the PNG_INFO_IDAT valid flag in png_set_rows() so png_write_png() - will actually write IDATs. - Made the default PNG_USE_LOCAL_ARRAYS depend on PNG_DLL instead of WIN32. - Make png_free_data() ignore its final parameter except when freeing data - that can have multiple instances (text, sPLT, unknowns). - Fixed a new bug in png_set_rows(). - Removed info_ptr->valid tests from png_free_data(), as in version 1.0.5. - Added png_set_invalid() function. - Fixed incorrect illustrations of png_destroy_write_struct() in example.c. -version 1.0.7beta15 [May 30, 2000] - Revised the deliberately erroneous Linux setjmp code in pngconf.h to produce - fewer error messages. - Rearranged checks for Z_OK to check the most likely path first in pngpread.c - and pngwutil.c. - Added checks in pngtest.c for png_create_*() returning NULL, and mentioned - in libpng.txt/libpng.3 the need for applications to check this. - Changed names of png_default_*() functions in pngtest to pngtest_*(). - Changed return type of png_get_x|y_offset_*() from png_uint_32 to png_int_32. - Fixed some bugs in the unused PNG_INCH_CONVERSIONS functions in pngget.c - Set each pointer to NULL after freeing it in png_free_data(). - Worked around a problem in pngconf.h; AIX's strings.h defines an "index" - macro that conflicts with libpng's png_color_16.index. (Dimitri Papadapoulos) - Added "msvc" directory with MSVC++ project files (Simon-Pierre Cadieux). -version 1.0.7beta16 [June 4, 2000] - Revised the workaround of AIX string.h "index" bug. - Added a check for overlength PLTE chunk in pngrutil.c. - Added PNG_NO_POINTER_INDEXING macro to use array-indexing instead of pointer - indexing in pngrutil.c and pngwutil.c to accommodate a buggy compiler. - Added a warning in png_decompress_chunk() when it runs out of data, e.g. - when it tries to read an erroneous PhotoShop iCCP chunk. - Added PNG_USE_DLL macro. - Revised the copyright/disclaimer/license notice. - Added contrib/msvctest directory -version 1.0.7rc1 [June 9, 2000] - Corrected the definition of PNG_TRANSFORM_INVERT_ALPHA (0x0400 not 0x0200) - Added contrib/visupng directory (Willem van Schaik) -version 1.0.7beta18 [June 23, 2000] - Revised PNGAPI definition, and pngvcrd.c to work with __GCC__ - and do not redefine PNGAPI if it is passed in via a compiler directive. - Revised visupng/PngFile.c to remove returns from within the Try block. - Removed leading underscores from "_PNG_H" and "_PNG_SAVE_BSD_SOURCE" macros. - Updated contrib/visupng/cexcept.h to version 1.0.0. - Fixed bugs in pngwrite.c and pngwutil.c that prevented writing iCCP chunks. -version 1.0.7rc2 [June 28, 2000] - Updated license to include disclaimers required by UCITA. - Fixed "DJBPP" typo in pnggccrd.c introduced in beta18. - -version 1.0.7 [July 1, 2000] - Revised the definition of "trans_values" in libpng.3/libpng.txt -version 1.0.8beta1 [July 8, 2000] - Added png_free(png_ptr, key) two places in pngpread.c to stop memory leaks. - Changed PNG_NO_STDIO to PNG_NO_CONSOLE_IO, several places in pngrutil.c and - pngwutil.c. - Changed PNG_EXPORT_VAR to use PNG_IMPEXP, in pngconf.h. - Removed unused "#include " from png.c - Added WindowsCE support. - Revised pnggccrd.c to work with gcc-2.95.2 and in the Cygwin environment. -version 1.0.8beta2 [July 10, 2000] - Added project files to the wince directory and made further revisions - of pngtest.c, pngrio.c, and pngwio.c in support of WindowsCE. -version 1.0.8beta3 [July 11, 2000] - Only set the PNG_FLAG_FREE_TRNS or PNG_FREE_TRNS flag in png_handle_tRNS() - for indexed-color input files to avoid potential double-freeing trans array - under some unusual conditions; problem was introduced in version 1.0.6f. - Further revisions to pngtest.c and files in the wince subdirectory. -version 1.0.8beta4 [July 14, 2000] - Added the files pngbar.png and pngbar.jpg to the distribution. - Added makefile.cygwin, and cygwin support in pngconf.h - Added PNG_NO_ZALLOC_ZERO macro (makes png_zalloc skip zeroing memory) -version 1.0.8rc1 [July 16, 2000] - Revised png_debug() macros and statements to eliminate compiler warnings. - -version 1.0.8 [July 24, 2000] - Added png_flush() in pngwrite.c, after png_write_IEND(). - Updated makefile.hpux to build a shared library. -version 1.0.9beta1 [November 10, 2000] - Fixed typo in scripts/makefile.hpux - Updated makevms.com in scripts and contrib/* and contrib/* (Martin Zinser) - Fixed seqence-point bug in contrib/pngminus/png2pnm (Martin Zinser) - Changed "cdrom.com" in documentation to "libpng.org" - Revised pnggccrd.c to get it all working, and updated makefile.gcmmx (Greg). - Changed type of "params" from voidp to png_voidp in png_read|write_png(). - Make sure PNGAPI and PNG_IMPEXP are defined in pngconf.h. - Revised the 3 instances of WRITEFILE in pngtest.c. - Relocated "msvc" and "wince" project subdirectories into "dll" subdirectory. - Updated png.rc in dll/msvc project - Revised makefile.dec to define and use LIBPATH and INCPATH - Increased size of global png_libpng_ver[] array from 12 to 18 chars. - Made global png_libpng_ver[], png_sig[] and png_pass_*[] arrays const. - Removed duplicate png_crc_finish() from png_handle_bKGD() function. - Added a warning when application calls png_read_update_info() multiple times. - Revised makefile.cygwin - Fixed bugs in iCCP support in pngrutil.c and pngwutil.c. - Replaced png_set_empty_plte_permitted() with png_permit_mng_features(). -version 1.0.9beta2 [November 19, 2000] - Renamed the "dll" subdirectory "projects". - Added borland project files to "projects" subdirectory. - Set VS_FF_PRERELEASE and VS_FF_PATCHED flags in msvc/png.rc when appropriate. - Add error message in png_set_compression_buffer_size() when malloc fails. -version 1.0.9beta3 [November 23, 2000] - Revised PNG_LIBPNG_BUILD_TYPE macro in png.h, used in the msvc project. - Removed the png_flush() in pngwrite.c that crashes some applications - that don't set png_output_flush_fn. - Added makefile.macosx and makefile.aix to scripts directory. -version 1.0.9beta4 [December 1, 2000] - Change png_chunk_warning to png_warning in png_check_keyword(). - Increased the first part of msg buffer from 16 to 18 in png_chunk_error(). -version 1.0.9beta5 [December 15, 2000] - Added support for filter method 64 (for PNG datastreams embedded in MNG). -version 1.0.9beta6 [December 18, 2000] - Revised png_set_filter() to accept filter method 64 when appropriate. - Added new PNG_HAVE_PNG_SIGNATURE bit to png_ptr->mode and use it to - help prevent applications from using MNG features in PNG datastreams. - Added png_permit_mng_features() function. - Revised libpng.3/libpng.txt. Changed "filter type" to "filter method". -version 1.0.9rc1 [December 23, 2000] - Revised test for PNG_HAVE_PNG_SIGNATURE in pngrutil.c - Fixed error handling of unknown compression type in png_decompress_chunk(). - In pngconf.h, define __cdecl when _MSC_VER is defined. -version 1.0.9beta7 [December 28, 2000] - Changed PNG_TEXT_COMPRESSION_zTXt to PNG_COMPRESSION_TYPE_BASE several places. - Revised memory management in png_set_hIST and png_handle_hIST in a backward - compatible manner. PLTE and tRNS were revised similarly. - Revised the iCCP chunk reader to ignore trailing garbage. -version 1.0.9beta8 [January 12, 2001] - Moved pngasmrd.h into pngconf.h. - Improved handling of out-of-spec garbage iCCP chunks generated by PhotoShop. -version 1.0.9beta9 [January 15, 2001] - Added png_set_invalid, png_permit_mng_features, and png_mmx_supported to - wince and msvc project module definition files. - Minor revision of makefile.cygwin. - Fixed bug with progressive reading of narrow interlaced images in pngpread.c -version 1.0.9beta10 [January 16, 2001] - Do not typedef png_FILE_p in pngconf.h when PNG_NO_STDIO is defined. - Fixed "png_mmx_supported" typo in project definition files. -version 1.0.9beta11 [January 19, 2001] - Updated makefile.sgi to make shared library. - Removed png_mmx_support() function and disabled PNG_MNG_FEATURES_SUPPORTED - by default, for the benefit of DLL forward compatibility. These will - be re-enabled in version 1.2.0. -version 1.0.9rc2 [January 22, 2001] - Revised cygwin support. - -version 1.0.9 [January 31, 2001] - Added check of cygwin's ALL_STATIC in pngconf.h - Added "-nommx" parameter to contrib/gregbook/rpng2-win and rpng2-x demos. -version 1.0.10beta1 [March 14, 2001] - Revised makefile.dec, makefile.sgi, and makefile.sggcc; added makefile.hpgcc. - Reformatted libpng.3 to eliminate bad line breaks. - Added checks for _mmx_supported in the read_filter_row function of pnggccrd.c - Added prototype for png_mmx_support() near the top of pnggccrd.c - Moved some error checking from png_handle_IHDR to png_set_IHDR. - Added PNG_NO_READ_SUPPORTED and PNG_NO_WRITE_SUPPORTED macros. - Revised png_mmx_support() function in pnggccrd.c - Restored version 1.0.8 PNG_WRITE_EMPTY_PLTE_SUPPORTED behavior in pngwutil.c - Fixed memory leak in contrib/visupng/PngFile.c - Fixed bugs in png_combine_row() in pnggccrd.c and pngvcrd.c (C version) - Added warnings when retrieving or setting gamma=0. - Increased the first part of msg buffer from 16 to 18 in png_chunk_warning(). -version 1.0.10rc1 [March 23, 2001] - Changed all instances of memcpy, strcpy, and strlen to png_memcpy, png_strcpy, - and png_strlen. - Revised png_mmx_supported() function in pnggccrd.c to return proper value. - Fixed bug in progressive reading (pngpread.c) with small images (height < 8). - -version 1.0.10 [March 30, 2001] - Deleted extraneous space (introduced in 1.0.9) from line 42 of makefile.cygwin - Added beos project files (Chris Herborth) -version 1.0.11beta1 [April 3, 2001] - Added type casts on several png_malloc() calls (Dimitri Papadapoulos). - Removed a no-longer needed AIX work-around from pngconf.h - Changed several "//" single-line comments to C-style in pnggccrd.c -version 1.0.11beta2 [April 11, 2001] - Removed PNGAPI from several functions whose prototypes did not have PNGAPI. - Updated scripts/pngos2.def -version 1.0.11beta3 [April 14, 2001] - Added checking the results of many instances of png_malloc() for NULL -version 1.0.11beta4 [April 20, 2001] - Undid the changes from version 1.0.11beta3. Added a check for NULL return - from user's malloc_fn(). - Removed some useless type casts of the NULL pointer. - Added makefile.netbsd - -version 1.0.11 [April 27, 2001] - Revised makefile.netbsd -version 1.0.12beta1 [May 14, 2001] - Test for Windows platform in pngconf.h when including malloc.h (Emmanuel Blot) - Updated makefile.cygwin and handling of Cygwin's ALL_STATIC in pngconf.h - Added some never-to-be-executed code in pnggccrd.c to quiet compiler warnings. - Eliminated the png_error about apps using png_read|write_init(). Instead, - libpng will reallocate the png_struct and info_struct if they are too small. - This retains future binary compatibility for old applications written for - libpng-0.88 and earlier. -version 1.2.0beta1 [May 6, 2001] - Bumped DLLNUM to 2. - Re-enabled PNG_MNG_FEATURES_SUPPORTED and enabled PNG_ASSEMBLER_CODE_SUPPORTED - by default. - Added runtime selection of MMX features. - Added png_set_strip_error_numbers function and related macros. -version 1.2.0beta2 [May 7, 2001] - Finished merging 1.2.0beta1 with version 1.0.11 - Added a check for attempts to read or write PLTE in grayscale PNG datastreams. -version 1.2.0beta3 [May 17, 2001] - Enabled user memory function by default. - Modified png_create_struct so it passes user mem_ptr to user memory allocator. - Increased png_mng_features flag from png_byte to png_uint_32. - Bumped shared-library (so-number) and dll-number to 3. -version 1.2.0beta4 [June 23, 2001] - Check for missing profile length field in iCCP chunk and free chunk_data - in case of truncated iCCP chunk. - Bumped shared-library number to 3 in makefile.sgi and makefile.sggcc - Bumped dll-number from 2 to 3 in makefile.cygwin - Revised contrib/gregbook/rpng*-x.c to avoid a memory leak and to exit cleanly - if user attempts to run it on an 8-bit display. - Updated contrib/gregbook - Use png_malloc instead of png_zalloc to allocate palette in pngset.c - Updated makefile.ibmc - Added some typecasts to eliminate gcc 3.0 warnings. Changed prototypes - of png_write_oFFS width and height from png_uint_32 to png_int_32. - Updated example.c - Revised prototypes for png_debug_malloc and png_debug_free in pngtest.c -version 1.2.0beta5 [August 8, 2001] - Revised contrib/gregbook - Revised makefile.gcmmx - Revised pnggccrd.c to conditionally compile some thread-unsafe code only - when PNG_THREAD_UNSAFE_OK is defined. - Added tests to prevent pngwutil.c from writing a bKGD or tRNS chunk with - value exceeding 2^bit_depth-1 - Revised makefile.sgi and makefile.sggcc - Replaced calls to fprintf(stderr,...) with png_warning() in pnggccrd.c - Removed restriction that do_invert_mono only operate on 1-bit opaque files - -version 1.2.0 [September 1, 2001] - Changed a png_warning() to png_debug() in pnggccrd.c - Fixed contrib/gregbook/rpng-x.c, rpng2-x.c to avoid crash with XFreeGC(). -version 1.2.1beta1 [October 19, 2001] - Revised makefile.std in contrib/pngminus - Include background_1 in png_struct regardless of gamma support. - Revised makefile.netbsd and makefile.macosx, added makefile.darwin. - Revised example.c to provide more details about using row_callback(). -version 1.2.1beta2 [October 25, 2001] - Added type cast to each NULL appearing in a function call, except for - WINCE functions. - Added makefile.so9. -version 1.2.1beta3 [October 27, 2001] - Removed type casts from all NULLs. - Simplified png_create_struct_2(). -version 1.2.1beta4 [November 7, 2001] - Revised png_create_info_struct() and png_creat_struct_2(). - Added error message if png_write_info() was omitted. - Type cast NULLs appearing in function calls when _NO_PROTO or - PNG_TYPECAST_NULL is defined. -version 1.2.1rc1 [November 24, 2001] - Type cast NULLs appearing in function calls except when PNG_NO_TYPECAST_NULL - is defined. - Changed typecast of "size" argument to png_size_t in pngmem.c calls to - the user malloc_fn, to agree with the prototype in png.h - Added a pop/push operation to pnggccrd.c, to preserve Eflag (Maxim Sobolev) - Updated makefile.sgi to recognize LIBPATH and INCPATH. - Updated various makefiles so "make clean" does not remove previous major - version of the shared library. -version 1.2.1rc2 [December 4, 2001] - Always allocate 256-entry internal palette, hist, and trans arrays, to - avoid out-of-bounds memory reference caused by invalid PNG datastreams. - Added a check for prefix_length > data_length in iCCP chunk handler. - -version 1.2.1 [December 7, 2001] - None. -version 1.2.2beta1 [February 22, 2002] - Fixed a bug with reading the length of iCCP profiles (Larry Reeves). - Revised makefile.linux, makefile.gcmmx, and makefile.sgi to generate - libpng.a, libpng12.so (not libpng.so.3), and libpng12/png.h - Revised makefile.darwin to remove "-undefined suppress" option. - Added checks for gamma and chromaticity values over 21474.83, which exceed - the limit for PNG unsigned 32-bit integers when encoded. - Revised calls to png_create_read_struct() and png_create_write_struct() - for simpler debugging. - Revised png_zalloc() so zlib handles errors (uses PNG_FLAG_MALLOC_NULL_MEM_OK) -version 1.2.2beta2 [February 23, 2002] - Check chunk_length and idat_size for invalid (over PNG_MAX_UINT) lengths. - Check for invalid image dimensions in png_get_IHDR. - Added missing "fi;" in the install target of the SGI makefiles. - Added install-static to all makefiles that make shared libraries. - Always do gamma compensation when image is partially transparent. -version 1.2.2beta3 [March 7, 2002] - Compute background.gray and background_1.gray even when color_type is RGB - in case image gets reduced to gray later. - Modified shared-library makefiles to install pkgconfig/libpngNN.pc. - Export (with PNGAPI) png_zalloc, png_zfree, and png_handle_as_unknown - Removed unused png_write_destroy_info prototype from png.h - Eliminated incorrect use of width_mmx from pnggccrd.c in pixel_bytes == 8 case - Added install-shared target to all makefiles that make shared libraries. - Stopped a double free of palette, hist, and trans when not using free_me. - Added makefile.32sunu for Sun Ultra 32 and makefile.64sunu for Sun Ultra 64. -version 1.2.2beta4 [March 8, 2002] - Compute background.gray and background_1.gray even when color_type is RGB - in case image gets reduced to gray later (Jason Summers). - Relocated a misplaced /bin/rm in the "install-shared" makefile targets - Added PNG_1_0_X macro which can be used to build a 1.0.x-compatible library. -version 1.2.2beta5 [March 26, 2002] - Added missing PNGAPI to several function definitions. - Check for invalid bit_depth or color_type in png_get_IHDR(), and - check for missing PLTE or IHDR in png_push_read_chunk() (Matthias Clasen). - Revised iTXt support to accept NULL for lang and lang_key. - Compute gamma for color components of background even when color_type is gray. - Changed "()" to "{}" in scripts/libpng.pc.in. - Revised makefiles to put png.h and pngconf.h only in $prefix/include/libpngNN - Revised makefiles to make symlink to libpng.so.NN in addition to libpngNN.so -version 1.2.2beta6 [March 31, 2002] -version 1.0.13beta1 [March 31, 2002] - Prevent png_zalloc() from trying to memset memory that it failed to acquire. - Add typecasts of PNG_MAX_UINT in pngset_cHRM_fixed() (Matt Holgate). - Ensure that the right function (user or default) is used to free the - png_struct after an error in png_create_read_struct_2(). -version 1.2.2rc1 [April 7, 2002] -version 1.0.13rc1 [April 7, 2002] - Save the ebx register in pnggccrd.c (Sami Farin) - Add "mem_ptr = png_ptr->mem_ptr" in png_destroy_write_struct() (Paul Gardner). - Updated makefiles to put headers in include/libpng and remove old include/*.h. - -version 1.2.2 [April 15, 2002] -version 1.0.13 [April 15, 2002] - Revised description of png_set_filter() in libpng.3/libpng.txt. - Revised makefile.netbsd and added makefile.neNNbsd and makefile.freebsd -version 1.0.13patch01 [April 17, 2002] -version 1.2.2patch01 [April 17, 2002] - Changed ${PNGMAJ}.${PNGVER} bug to ${PNGVER} in makefile.sgi and makefile.sggcc - Fixed VER -> PNGVER typo in makefile.macosx and added install-static to install - Added install: target to makefile.32sunu and makefile.64sunu -version 1.0.13patch03 [April 18, 2002] -version 1.2.2patch03 [April 18, 2002] - Revised 15 makefiles to link libpng.a to libpngNN.a and the include libpng - subdirectory to libpngNN subdirectory without the full pathname. - Moved generation of libpng.pc from "install" to "all" in 15 makefiles. -version 1.2.3rc1 [April 28, 2002] - Added install-man target to 15 makefiles (Dimitri Papadopolous-Orfanos). - Added $(DESTDIR) feature to 24 makefiles (Tim Mooney) - Fixed bug with $prefix, should be $(prefix) in makefile.hpux. - Updated cygwin-specific portion of pngconf.h and revised makefile.cygwin - Added a link from libpngNN.pc to libpng.pc in 15 makefiles. - Added links from include/libpngNN/*.h to include/*.h in 24 makefiles. - Revised makefile.darwin to make relative links without full pathname. - Added setjmp() at the end of png_create_*_struct_2() in case user forgets - to put one in their application. - Restored png_zalloc() and png_zfree() prototypes to version 1.2.1 and - removed them from module definition files. -version 1.2.3rc2 [May 1, 2002] - Fixed bug in reporting number of channels in pngget.c and pngset.c, - that was introduced in version 1.2.2beta5. - Exported png_zalloc(), png_zfree(), png_default_read(), png_default_write(), - png_default_flush(), and png_push_fill_buffer() and included them in - module definition files. - Added "libpng.pc" dependency to the "install-shared" target in 15 makefiles. -version 1.2.3rc3 [May 1, 2002] - Revised prototype for png_default_flush() - Remove old libpng.pc and libpngNN.pc before installing new ones. -version 1.2.3rc4 [May 2, 2002] - Typos in *.def files (png_default_read|write -> png_default_read|write_data) - In makefiles, changed rm libpng.NN.pc to rm libpngNN.pc - Added libpng-config and libpngNN-config and modified makefiles to install them. - Changed $(MANPATH) to $(DESTDIR)$(MANPATH) in makefiles - Added "Win32 DLL VB" configuration to projects/msvc/libpng.dsp -version 1.2.3rc5 [May 11, 2002] - Changed "error" and "message" in prototypes to "error_message" and - "warning_message" to avoid namespace conflict. - Revised 15 makefiles to build libpng-config from libpng-config-*.in - Once more restored png_zalloc and png_zfree to regular nonexported form. - Restored png_default_read|write_data, png_default_flush, png_read_fill_buffer - to nonexported form, but with PNGAPI, and removed them from module def files. -version 1.2.3rc6 [May 14, 2002] - Removed "PNGAPI" from png_zalloc() and png_zfree() in png.c - Changed "Gz" to "Gd" in projects/msvc/libpng.dsp and zlib.dsp. - Removed leftover libpng-config "sed" script from four makefiles. - Revised libpng-config creating script in 16 makefiles. - -version 1.2.3 [May 22, 2002] - Revised libpng-config target in makefile.cygwin. - Removed description of png_set_mem_fn() from documentation. - Revised makefile.freebsd. - Minor cosmetic changes to 15 makefiles, e.g., $(DI) = $(DESTDIR)/$(INCDIR). - Revised projects/msvc/README.txt - Changed -lpng to -lpngNN in LDFLAGS in several makefiles. -version 1.2.4beta1 [May 24, 2002] - Added libpng.pc and libpng-config to "all:" target in 16 makefiles. - Fixed bug in 16 makefiles: $(DESTDIR)/$(LIBPATH) to $(DESTDIR)$(LIBPATH) - Added missing "\" before closing double quote in makefile.gcmmx. - Plugged various memory leaks; added png_malloc_warn() and png_set_text_2() - functions. -version 1.2.4beta2 [June 25, 2002] - Plugged memory leak of png_ptr->current_text (Matt Holgate). - Check for buffer overflow before reading CRC in pngpread.c (Warwick Allison) - Added -soname to the loader flags in makefile.dec, makefile.sgi, and - makefile.sggcc. - Added "test-installed" target to makefile.linux, makefile.gcmmx, - makefile.sgi, and makefile.sggcc. -version 1.2.4beta3 [June 28, 2002] - Plugged memory leak of row_buf in pngtest.c when there is a png_error(). - Detect buffer overflow in pngpread.c when IDAT is corrupted with extra data. - Added "test-installed" target to makefile.32sunu, makefile.64sunu, - makefile.beos, makefile.darwin, makefile.dec, makefile.macosx, - makefile.solaris, makefile.hpux, makefile.hpgcc, and makefile.so9. -version 1.2.4rc1 and 1.0.14rc1 [July 2, 2002] - Added "test-installed" target to makefile.cygwin and makefile.sco. - Revised pnggccrd.c to be able to back out version 1.0.x via PNG_1_0_X macro. - -version 1.2.4 and 1.0.14 [July 8, 2002] - Changed png_warning() to png_error() when width is too large to process. -version 1.2.4patch01 [July 20, 2002] - Revised makefile.cygwin to use DLL number 12 instead of 13. -version 1.2.5beta1 [August 6, 2002] - Added code to contrib/gregbook/readpng2.c to ignore unused chunks. - Replaced toucan.png in contrib/gregbook (it has been corrupt since 1.0.11) - Removed some stray *.o files from contrib/gregbook. - Changed png_error() to png_warning() about "Too much data" in pngpread.c - and about "Extra compressed data" in pngrutil.c. - Prevent png_ptr->pass from exceeding 7 in png_push_finish_row(). - Updated makefile.hpgcc - Updated png.c and pnggccrd.c handling of return from png_mmx_support() -version 1.2.5beta2 [August 15, 2002] - Only issue png_warning() about "Too much data" in pngpread.c when avail_in - is nonzero. - Updated makefiles to install a separate libpng.so.3 with its own rpath. -version 1.2.5rc1 and 1.0.15rc1 [August 24, 2002] - Revised makefiles to not remove previous minor versions of shared libraries. -version 1.2.5rc2 and 1.0.15rc2 [September 16, 2002] - Revised 13 makefiles to remove "-lz" and "-L$(ZLIBLIB)", etc., from shared - library loader directive. - Added missing "$OBJSDLL" line to makefile.gcmmx. - Added missing "; fi" to makefile.32sunu. -version 1.2.5rc3 and 1.0.15rc3 [September 18, 2002] - Revised libpng-config script. - -version 1.2.5 and 1.0.15 [October 3, 2002] - Revised makefile.macosx, makefile.darwin, makefile.hpgcc, and makefile.hpux, - and makefile.aix. - Relocated two misplaced PNGAPI lines in pngtest.c -version 1.2.6beta1 [October 22, 2002] - Commented out warning about uninitialized mmx_support in pnggccrd.c. - Changed "IBMCPP__" flag to "__IBMCPP__" in pngconf.h. - Relocated two more misplaced PNGAPI lines in pngtest.c - Fixed memory overrun bug in png_do_read_filler() with 16-bit datastreams, - introduced in version 1.0.2. - Revised makefile.macosx, makefile.dec, makefile.aix, and makefile.32sunu. -version 1.2.6beta2 [November 1, 2002] - Added libpng-config "--ldopts" output. - Added "AR=ar" and "ARFLAGS=rc" and changed "ar rc" to "$(AR) $(ARFLAGS)" - in makefiles. -version 1.2.6beta3 [July 18, 2004] - Reverted makefile changes from version 1.2.6beta2 and some of the changes - from version 1.2.6beta1; these will be postponed until version 1.2.7. - Version 1.2.6 is going to be a simple bugfix release. - Changed the one instance of "ln -sf" to "ln -f -s" in each Sun makefile. - Fixed potential overrun in pngerror.c by using strncpy instead of memcpy. - Added "#!/bin/sh" at the top of configure, for recognition of the - 'x' flag under Cygwin (Cosmin). - Optimized vacuous tests that silence compiler warnings, in png.c (Cosmin). - Added support for PNG_USER_CONFIG, in pngconf.h (Cosmin). - Fixed the special memory handler for Borland C under DOS, in pngmem.c - (Cosmin). - Removed some spurious assignments in pngrutil.c (Cosmin). - Replaced 65536 with 65536L, and 0xffff with 0xffffL, to silence warnings - on 16-bit platforms (Cosmin). - Enclosed shift op expressions in parentheses, to silence warnings (Cosmin). - Used proper type png_fixed_point, to avoid problems on 16-bit platforms, - in png_handle_sRGB() (Cosmin). - Added compression_type to png_struct, and optimized the window size - inside the deflate stream (Cosmin). - Fixed definition of isnonalpha(), in pngerror.c and pngrutil.c (Cosmin). - Fixed handling of unknown chunks that come after IDAT (Cosmin). - Allowed png_error() and png_warning() to work even if png_ptr == NULL - (Cosmin). - Replaced row_info->rowbytes with row_bytes in png_write_find_filter() - (Cosmin). - Fixed definition of PNG_LIBPNG_VER_DLLNUM (Simon-Pierre). - Used PNG_LIBPNG_VER and PNG_LIBPNG_VER_STRING instead of the hardcoded - values in png.c (Simon-Pierre, Cosmin). - Initialized png_libpng_ver[] with PNG_LIBPNG_VER_STRING (Simon-Pierre). - Replaced PNG_LIBPNG_VER_MAJOR with PNG_LIBPNG_VER_DLLNUM in png.rc - (Simon-Pierre). - Moved the definition of PNG_HEADER_VERSION_STRING near the definitions - of the other PNG_LIBPNG_VER_... symbols in png.h (Cosmin). - Relocated #ifndef PNGAPI guards in pngconf.h (Simon-Pierre, Cosmin). - Updated scripts/makefile.vc(a)win32 (Cosmin). - Updated the MSVC project (Simon-Pierre, Cosmin). - Updated the Borland C++ Builder project (Cosmin). - Avoided access to asm_flags in pngvcrd.c, if PNG_1_0_X is defined (Cosmin). - Commented out warning about uninitialized mmx_support in pngvcrd.c (Cosmin). - Removed scripts/makefile.bd32 and scripts/pngdef.pas (Cosmin). - Added extra guard around inclusion of Turbo C memory headers, in pngconf.h - (Cosmin). - Renamed projects/msvc/ to projects/visualc6/, and projects/borland/ to - projects/cbuilder5/ (Cosmin). - Moved projects/visualc6/png32ms.def to scripts/pngw32.def, - and projects/visualc6/png.rc to scripts/pngw32.rc (Cosmin). - Added projects/visualc6/pngtest.dsp; removed contrib/msvctest/ (Cosmin). - Changed line endings to DOS style in cbuilder5 and visualc6 files, even - in the tar.* distributions (Cosmin). - Updated contrib/visupng/VisualPng.dsp (Cosmin). - Updated contrib/visupng/cexcept.h to version 2.0.0 (Cosmin). - Added a separate distribution with "configure" and supporting files (Junichi). -version 1.2.6beta4 [July 28, 2004] - Added user ability to change png_size_t via a PNG_SIZE_T macro. - Added png_sizeof() and png_convert_size() functions. - Added PNG_SIZE_MAX (maximum value of a png_size_t variable. - Added check in png_malloc_default() for (size_t)size != (png_uint_32)size - which would indicate an overflow. - Changed sPLT failure action from png_error to png_warning and abandon chunk. - Changed sCAL and iCCP failures from png_error to png_warning and abandon. - Added png_get_uint_31(png_ptr, buf) function. - Added PNG_UINT_32_MAX macro. - Renamed PNG_MAX_UINT to PNG_UINT_31_MAX. - Made png_zalloc() issue a png_warning and return NULL on potential - overflow. - Turn on PNG_NO_ZALLOC_ZERO by default in version 1.2.x - Revised "clobber list" in pnggccrd.c so it will compile under gcc-3.4. - Revised Borland portion of png_malloc() to return NULL or issue - png_error() according to setting of PNG_FLAG_MALLOC_NULL_MEM_OK. - Added PNG_NO_SEQUENTIAL_READ_SUPPORTED macro to conditionally remove - sequential read support. - Added some "#if PNG_WRITE_SUPPORTED" blocks. - #ifdef'ed out some redundancy in png_malloc_default(). - Use png_malloc instead of png_zalloc to allocate the pallete. -version 1.0.16rc1 and 1.2.6rc1 [August 4, 2004] - Fixed buffer overflow vulnerability in png_handle_tRNS() - Fixed integer arithmetic overflow vulnerability in png_read_png(). - Fixed some harmless bugs in png_handle_sBIT, etc, that would cause - duplicate chunk types to go undetected. - Fixed some timestamps in the -config version - Rearranged order of processing of color types in png_handle_tRNS(). - Added ROWBYTES macro to calculate rowbytes without integer overflow. - Updated makefile.darwin and removed makefile.macosx from scripts directory. - Imposed default one million column, one-million row limits on the image - dimensions, and added png_set_user_limits() function to override them. - Revised use of PNG_SET_USER_LIMITS_SUPPORTED macro. - Fixed wrong cast of returns from png_get_user_width|height_max(). - Changed some "keep the compiler happy" from empty statements to returns, - Revised libpng.txt to remove 1.2.x stuff from the 1.0.x distribution -version 1.0.16rc2 and 1.2.6rc2 [August 7, 2004] - Revised makefile.darwin and makefile.solaris. Removed makefile.macosx. - Revised pngtest's png_debug_malloc() to use png_malloc() instead of - png_malloc_default() which is not supposed to be exported. - Fixed off-by-one error in one of the conversions to PNG_ROWBYTES() in - pngpread.c. Bug was introduced in 1.2.6rc1. - Fixed bug in RGB to RGBX transformation introduced in 1.2.6rc1. - Fixed old bug in RGB to Gray transformation. - Fixed problem with 64-bit compilers by casting arguments to abs() - to png_int_32. - Changed "ln -sf" to "ln -f -s" in three makefiles (solaris, sco, so9). - Changed "HANDLE_CHUNK_*" to "PNG_HANDLE_CHUNK_*" (Cosmin) - Added "-@/bin/rm -f $(DL)/$(LIBNAME).so.$(PNGMAJ)" to 15 *NIX makefiles. - Added code to update the row_info->colortype in png_do_read_filler() (MSB). -version 1.0.16rc3 and 1.2.6rc3 [August 9, 2004] - Eliminated use of "abs()" in testing cHRM and gAMA values, to avoid - trouble with some 64-bit compilers. Created PNG_OUT_OF_RANGE() macro. - Revised documentation of png_set_keep_unknown_chunks(). - Check handle_as_unknown status in pngpread.c, as in pngread.c previously. - Moved "PNG_HANDLE_CHUNK_*" macros out of PNG_INTERNAL section of png.h - Added "rim" definitions for CONST4 and CONST6 in pnggccrd.c -version 1.0.16rc4 and 1.2.6rc4 [August 10, 2004] - Fixed mistake in pngtest.c introduced in 1.2.6rc2 (declaration of - "pinfo" was out of place). -version 1.0.16rc5 and 1.2.6rc5 [August 10, 2004] - Moved "PNG_HANDLE_CHUNK_*" macros out of PNG_ASSEMBLER_CODE_SUPPORTED - section of png.h where they were inadvertently placed in version rc3. - -version 1.2.6 and 1.0.16 [August 15, 2004] - Revised pngtest so memory allocation testing is only done when PNG_DEBUG==1. -version 1.2.7beta1 [August 26, 2004] - Removed unused pngasmrd.h file. - Removed references to uu.net for archived files. Added references to - PNG Spec (second edition) and the PNG ISO/IEC Standard. - Added "test-dd" target in 15 makefiles, to run pngtest in DESTDIR. - Fixed bug with "optimized window size" in the IDAT datastream, that - causes libpng to write PNG files with incorrect zlib header bytes. -version 1.2.7beta2 [August 28, 2004] - Fixed bug with sCAL chunk and big-endian machines (David Munro). - Undid new code added in 1.2.6rc2 to update the color_type in - png_set_filler(). - Added png_set_add_alpha() that updates color type. -version 1.0.17rc1 and 1.2.7rc1 [September 4, 2004] - Revised png_set_strip_filler() to not remove alpha if color_type has alpha. - -version 1.2.7 and 1.0.17 [September 12, 2004] - Added makefile.hp64 - Changed projects/msvc/png32ms.def to scripts/png32ms.def in makefile.cygwin -version 1.2.8beta1 [November 1, 2004] - Fixed bug in png_text_compress() that would fail to complete a large block. - Fixed bug, introduced in libpng-1.2.7, that overruns a buffer during - strip alpha operation in png_do_strip_filler(). - Added PNG_1_2_X definition in pngconf.h - #ifdef out png_info_init in png.c and png_read_init in pngread.c (as of 1.3.0) -version 1.2.8beta2 [November 2, 2004] - Reduce color_type to a nonalpha type after strip alpha operation in - png_do_strip_filler(). -version 1.2.8beta3 [November 3, 2004] - Revised definitions of PNG_MAX_UINT_32, PNG_MAX_SIZE, and PNG_MAXSUM -version 1.2.8beta4 [November 12, 2004] - Fixed (again) definition of PNG_LIBPNG_VER_DLLNUM in png.h (Cosmin). - Added PNG_LIBPNG_BUILD_PRIVATE in png.h (Cosmin). - Set png_ptr->zstream.data_type to Z_BINARY, to avoid unnecessary detection - of data type in deflate (Cosmin). - Deprecated but continue to support SPECIALBUILD and PRIVATEBUILD in favor of - PNG_LIBPNG_BUILD_SPECIAL_STRING and PNG_LIBPNG_BUILD_PRIVATE_STRING. -version 1.2.8beta5 [November 20, 2004] - Use png_ptr->flags instead of png_ptr->transformations to pass - PNG_STRIP_ALPHA info to png_do_strip_filler(), to preserve ABI - compatibility. - Revised handling of SPECIALBUILD, PRIVATEBUILD, - PNG_LIBPNG_BUILD_SPECIAL_STRING and PNG_LIBPNG_BUILD_PRIVATE_STRING. -version 1.2.8rc1 [November 24, 2004] - Moved handling of BUILD macros from pngconf.h to png.h - Added definition of PNG_LIBPNG_BASE_TYPE in png.h, inadvertently - omitted from beta5. - Revised scripts/pngw32.rc - Despammed mailing addresses by masking "@" with "at". - Inadvertently installed a supposedly faster test version of pngrutil.c -version 1.2.8rc2 [November 26, 2004] - Added two missing "\" in png.h - Change tests in pngread.c and pngpread.c to - if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA)) - png_do_read_transformations(png_ptr); -version 1.2.8rc3 [November 28, 2004] - Reverted pngrutil.c to version libpng-1.2.8beta5. - Added scripts/makefile.elf with supporting code in pngconf.h for symbol - versioning (John Bowler). -version 1.2.8rc4 [November 29, 2004] - Added projects/visualc7 (Simon-pierre). -version 1.2.8rc5 [November 29, 2004] - Fixed new typo in scripts/pngw32.rc - -version 1.2.8 [December 3, 2004] - Removed projects/visualc7, added projects/visualc71. - -version 1.2.9beta1 [February 21, 2006] - - Initialized some structure members in pngwutil.c to avoid gcc-4.0.0 complaints - Revised man page and libpng.txt to make it clear that one should not call - png_read_end or png_write_end after png_read_png or png_write_png. - Updated references to png-mng-implement mailing list. - Fixed an incorrect typecast in pngrutil.c - Added PNG_NO_READ_SUPPORTED conditional for making a write-only library. - Added PNG_NO_WRITE_INTERLACING_SUPPORTED conditional. - Optimized alpha-inversion loops in pngwtran.c - Moved test for nonzero gamma outside of png_build_gamma_table() in pngrtran.c - Make sure num_trans is <= 256 before copying data in png_set_tRNS(). - Make sure num_palette is <= 256 before copying data in png_set_PLTE(). - Interchanged order of write_swap_alpha and write_invert_alpha transforms. - Added parentheses in the definition of PNG_LIBPNG_BUILD_TYPE (Cosmin). - Optimized zlib window flag (CINFO) in contrib/pngsuite/*.png (Cosmin). - Updated scripts/makefile.bc32 for Borland C++ 5.6 (Cosmin). - Exported png_get_uint_32, png_save_uint_32, png_get_uint_16, png_save_uint_16, - png_get_int_32, png_save_int_32, png_get_uint_31 (Cosmin). - Added type cast (png_byte) in png_write_sCAL() (Cosmin). - Fixed scripts/makefile.cygwin (Christian Biesinger, Cosmin). - Default iTXt support was inadvertently enabled. - -version 1.2.9beta2 [February 21, 2006] - - Check for png_rgb_to_gray and png_gray_to_rgb read transformations before - checking for png_read_dither in pngrtran.c - Revised checking of chromaticity limits to accommodate extended RGB - colorspace (John Denker). - Changed line endings in some of the project files to CRLF, even in the - "Unix" tar distributions (Cosmin). - Made png_get_int_32 and png_save_int_32 always available (Cosmin). - Updated scripts/pngos2.def, scripts/pngw32.def and projects/wince/png32ce.def - with the newly exported functions. - Eliminated distributions without the "configure" script. - Updated INSTALL instructions. - -version 1.2.9beta3 [February 24, 2006] - - Fixed CRCRLF line endings in contrib/visupng/VisualPng.dsp - Made libpng.pc respect EXEC_PREFIX (D. P. Kreil, J. Bowler) - Removed reference to pngasmrd.h from Makefile.am - Renamed CHANGES to ChangeLog. - Renamed LICENSE to COPYING. - Renamed ANNOUNCE to NEWS. - Created AUTHORS file. - -version 1.2.9beta4 [March 3, 2006] - - Changed definition of PKGCONFIG from $prefix/lib to $libdir in configure.ac - Reverted to filenames LICENSE and ANNOUNCE; removed AUTHORS and COPYING. - Removed newline from the end of some error and warning messages. - Removed test for sqrt() from configure.ac and configure. - Made swap tables in pngtrans.c PNG_CONST (Carlo Bramix). - Disabled default iTXt support that was inadvertently enabled in - libpng-1.2.9beta1. - Added "OS2" to list of systems that don't need underscores, in pnggccrd.c - Removed libpng version and date from *.c files. - -version 1.2.9beta5 [March 4, 2006] - Removed trailing blanks from source files. - Put version and date of latest change in each source file, and changed - copyright year accordingly. - More cleanup of configure.ac, Makefile.ac, and associated scripts. - Restored scripts/makefile.elf which was inadvertently deleted. - -version 1.2.9beta6 [March 6, 2006] - Fixed typo (RELEASE) in configuration files. - -version 1.2.9beta7 [March 7, 2006] - Removed libpng.vers and libpng.sym from libpng12_la_SOURCES in Makefile.am - Fixed inconsistent #ifdef's around png_sig_bytes() and png_set_sCAL_s() - in png.h. - Updated makefile.elf as suggested by debian. - Made cosmetic changes to some makefiles, adding LN_SF and other macros. - Made some makefiles accept "exec_prefix". - -version 1.2.9beta8 [March 9, 2006] - Fixed some "#if defined (..." which should be "#if defined(..." - Bug introduced in libpng-1.2.8. - Fixed inconsistency in definition of png_default_read_data() - Restored blank that was lost from makefile.sggcc "clean" target in beta7. - Revised calculation of "current" and "major" for irix in ltmain.sh - Changed "mkdir" to "MKDIR_P" in some makefiles. - Separated PNG_EXPAND and PNG_EXPAND_tRNS. - Added png_set_expand_gray_1_2_4_to_8() and deprecated - png_set_gray_1_2_4_to_8() which also expands tRNS to alpha. - -version 1.2.9beta9 [March 10, 2006] - Include "config.h" in pngconf.h when available. - Added some checks for NULL png_ptr or NULL info_ptr (timeless) - -version 1.2.9beta10 [March 20, 2006] - Removed extra CR from contrib/visualpng/VisualPng.dsw (Cosmin) - Made pnggccrd.c PIC-compliant (Christian Aichinger). - Added makefile.mingw (Wolfgang Glas). - Revised pngconf.h MMX checking. - -version 1.2.9beta11 [March 22, 2006] - Fixed out-of-order declaration in pngwrite.c that was introduced in beta9 - Simplified some makefiles by using LIBSO, LIBSOMAJ, and LIBSOVER macros. - -version 1.2.9rc1 [March 31, 2006] - Defined PNG_USER_PRIVATEBUILD when including "pngusr.h" (Cosmin). - Removed nonsensical assertion check from pngtest.c (Cosmin). - -version 1.2.9 [April 14, 2006] - Revised makefile.beos and added "none" selector in ltmain.sh - -version 1.2.10beta1 [April 15, 2006] - Renamed "config.h" to "png_conf.h" and revised Makefile.am to add - -DPNG_BUILDING_LIBPNG to compile directive, and modified pngconf.h - to include png_conf.h only when PNG_BUILDING_LIBPNG is defined. - -version 1.2.10beta2 [April 15, 2006] - Manually updated Makefile.in and configure. Changed png_conf.h.in - back to config.h. - -version 1.2.10beta3 [April 15, 2006] - Change png_conf.h back to config.h in pngconf.h. - -version 1.2.10beta4 [April 16, 2006] - Change PNG_BUILDING_LIBPNG to PNG_CONFIGURE_LIBPNG in config/Makefile*. - -version 1.2.10beta5 [April 16, 2006] - Added a configure check for compiling assembler code in pnggccrd.c - -version 1.2.10beta6 [April 17, 2006] - Revised the configure check for pnggccrd.c - Moved -DPNG_CONFIGURE_LIBPNG into @LIBPNG_DEFINES@ - Added @LIBPNG_DEFINES@ to arguments when building libpng.sym - -version 1.2.10beta7 [April 18, 2006] - Change "exec_prefix=$prefix" to "exec_prefix=$(prefix)" in makefiles. - -version 1.2.10rc1 [April 19, 2006] - Ensure pngconf.h doesn't define both PNG_USE_PNGGCCRD and PNG_USE_PNGVCRD - Fixed "LN_FS" typo in makefile.sco and makefile.solaris. - -version 1.2.10rc2 [April 20, 2006] - Added a backslash between -DPNG_CONFIGURE_LIBPNG and -DPNG_NO_ASSEMBLER_CODE - in configure.ac and configure - Made the configure warning about versioned symbols less arrogant. - -version 1.2.10rc3 [April 21, 2006] - Added a note in libpng.txt that png_set_sig_bytes(8) can be used when - writing an embedded PNG without the 8-byte signature. - Revised makefiles and configure to avoid making links to libpng.so.* - -version 1.2.10 [April 23, 2006] - Reverted configure to "rc2" state. - -version 1.2.11beta1 [May 31, 2006] - scripts/libpng.pc.in contained "configure" style version info and would - not work with makefiles. - The shared-library makefiles were linking to libpng.so.0 instead of - libpng.so.3 compatibility as the library. - -version 1.2.11beta2 [June 2, 2006] - Increased sprintf buffer from 50 to 52 chars in pngrutil.c to avoid - buffer overflow. - Fixed bug in example.c (png_set_palette_rgb -> png_set_palette_to_rgb) - -version 1.2.11beta3 [June 5, 2006] - Prepended "#! /bin/sh" to ltmail.sh and contrib/pngminus/*.sh (Cosmin). - Removed the accidental leftover Makefile.in~ (Cosmin). - Avoided potential buffer overflow and optimized buffer in - png_write_sCAL(), png_write_sCAL_s() (Cosmin). - Removed the include directories and libraries from CFLAGS and LDFLAGS - in scripts/makefile.gcc (Nelson A. de Oliveira, Cosmin). - -version 1.2.11beta4 [June 6, 2006] - Allow zero-length IDAT chunks after the entire zlib datastream, but not - after another intervening chunk type. - -version 1.0.19rc1, 1.2.11rc1 [June 13, 2006] - Deleted extraneous square brackets from [config.h] in configure.ac - -version 1.0.19rc2, 1.2.11rc2 [June 14, 2006] - Added prototypes for PNG_INCH_CONVERSIONS functions to png.h - Revised INSTALL and autogen.sh - Fixed typo in several makefiles (-W1 should be -Wl) - Added typedef for png_int_32 and png_uint_32 on 64-bit systems. - -version 1.0.19rc3, 1.2.11rc3 [June 15, 2006] - Removed the new typedefs for 64-bit systems (delay until version 1.4.0) - Added one zero element to png_gamma_shift[] array in pngrtran.c to avoid - reading out of bounds. - -version 1.0.19rc4, 1.2.11rc4 [June 15, 2006] - Really removed the new typedefs for 64-bit systems. - -version 1.0.19rc5, 1.2.11rc5 [June 22, 2006] - Removed png_sig_bytes entry from scripts/pngw32.def - -version 1.0.19, 1.2.11 [June 26, 2006] - None. - -version 1.0.20, 1.2.12 [June 27, 2006] - Really increased sprintf buffer from 50 to 52 chars in pngrutil.c to avoid - buffer overflow. - -version 1.2.13beta1 [October 2, 2006] - Removed AC_FUNC_MALLOC from configure.ac - Work around Intel-Mac compiler bug by setting PNG_NO_MMX_CODE in pngconf.h - Change "logical" to "bitwise" throughout documentation. - Detect and fix attempt to write wrong iCCP profile length. - -version 1.0.21, 1.2.13 [November 14, 2006] - Fix potential buffer overflow in sPLT chunk handler. - Fix Makefile.am to not try to link to noexistent files. - Check all exported functions for NULL png_ptr. - -version 1.2.14beta1 [November 17, 2006] - Relocated three misplaced tests for NULL png_ptr. - Built Makefile.in with automake-1.9.6 instead of 1.9.2. - Build configure with autoconf-2.60 instead of 2.59 - -version 1.2.14beta2 [November 17, 2006] - Added some typecasts in png_zalloc(). - -version 1.2.14rc1 [November 20, 2006] - Changed "strtod" to "png_strtod" in pngrutil.c - -version 1.0.22, 1.2.14 [November 27, 2006] - Added missing "$(srcdir)" in Makefile.am and Makefile.in - -version 1.2.15beta1 [December 3, 2006] - Generated configure with autoconf-2.61 instead of 2.60 - Revised configure.ac to update libpng.pc and libpng-config. - -version 1.2.15beta2 [December 3, 2006] - Always export MMX asm functions, just stubs if not building pnggccrd.c - -version 1.2.15beta3 [December 4, 2006] - Add "png_bytep" typecast to profile while calculating length in pngwutil.c - -version 1.2.15beta4 [December 7, 2006] - Added scripts/CMakeLists.txt - Changed PNG_NO_ASSEMBLER_CODE to PNG_NO_MMX_CODE in scripts, like 1.4.0beta - -version 1.2.15beta5 [December 7, 2006] - Changed some instances of PNG_ASSEMBLER_* to PNG_MMX_* in pnggccrd.c - Revised scripts/CMakeLists.txt - -version 1.2.15beta6 [December 13, 2006] - Revised scripts/CMakeLists.txt and configure.ac - -version 1.2.15rc1 [December 18, 2006] - Revised scripts/CMakeLists.txt - -version 1.2.15rc2 [December 21, 2006] - Added conditional #undef jmpbuf in pngtest.c to undo #define in AIX headers. - Added scripts/makefile.nommx - -version 1.2.15rc3 [December 25, 2006] - Fixed shared library numbering error that was introduced in 1.2.15beta6. - -version 1.2.15rc4 [December 27, 2006] - Fixed handling of rgb_to_gray when png_ptr->color.gray isn't set. - -version 1.2.15rc5 [December 31, 2006] - Revised handling of rgb_to_gray. - -version 1.0.23, 1.2.15 [January 5, 2007] - Added some (unsigned long) typecasts in pngtest.c to avoid printing errors. - -version 1.2.16beta1 [January 6, 2007] - Fix bugs in makefile.nommx - -version 1.2.16beta2 [January 16, 2007] - Revised scripts/CMakeLists.txt - -version 1.0.24, 1.2.16 [January 31, 2007] - No changes. - -version 1.2.17beta1 [March 6, 2007] - Revised scripts/CMakeLists.txt to install both shared and static libraries. - Deleted a redundant line from pngset.c. - -version 1.2.17beta2 [April 26, 2007] - Relocated misplaced test for png_ptr == NULL in pngpread.c - Change "==" to "&" for testing PNG_RGB_TO_GRAY_ERR & PNG_RGB_TO_GRAY_WARN - flags. - Changed remaining instances of PNG_ASSEMBLER_* to PNG_MMX_* - Added pngerror() when write_IHDR fails in deflateInit2(). - Added "const" to some array declarations. - Mention examples of libpng usage in the libpng*.txt and libpng.3 documents. - -version 1.2.17rc1 [May 4, 2007] - No changes. - -version 1.2.17rc2 [May 8, 2007] - Moved several PNG_HAVE_* macros out of PNG_INTERNAL because applications - calling set_unknown_chunk_location() need them. - Changed transformation flag from PNG_EXPAND_tRNS to PNG_EXPAND in - png_set_expand_gray_1_2_4_to_8(). - Added png_ptr->unknown_chunk to hold working unknown chunk data, so it - can be free'ed in case of error. Revised unknown chunk handling in - pngrutil.c and pngpread.c to use this structure. - -version 1.2.17rc3 [May 8, 2007] - Revised symbol-handling in configure script. - -version 1.2.17rc4 [May 10, 2007] - Revised unknown chunk handling to avoid storing unknown critical chunks. - -version 1.0.25 [May 15, 2007] -version 1.2.17 [May 15, 2007] - Added "png_ptr->num_trans=0" before error return in png_handle_tRNS, - to eliminate a vulnerability (CVE-2007-2445, CERT VU#684664) - -version 1.0.26 [May 15, 2007] -version 1.2.18 [May 15, 2007] - Reverted the libpng-1.2.17rc3 change to symbol-handling in configure script - -version 1.2.19beta1 [May 18, 2007] - Changed "const static" to "static PNG_CONST" everywhere, mostly undoing - change of libpng-1.2.17beta2. Changed other "const" to "PNG_CONST" - Changed some handling of unused parameters, to avoid compiler warnings. - "if (unused == NULL) return;" becomes "unused = unused". - -version 1.2.19beta2 [May 18, 2007] - Only use the valid bits of tRNS value in png_do_expand() (Brian Cartier) - -version 1.2.19beta3 [May 19, 2007] - Add some "png_byte" typecasts in png_check_keyword() and write new_key - instead of key in zTXt chunk (Kevin Ryde). - -version 1.2.19beta4 [May 21, 2007] - Add png_snprintf() function and use it in place of sprint() for improved - defense against buffer overflows. - -version 1.2.19beta5 [May 21, 2007] - Fixed png_handle_tRNS() to only use the valid bits of tRNS value. - Changed handling of more unused parameters, to avoid compiler warnings. - Removed some PNG_CONST in pngwutil.c to avoid compiler warnings. - -version 1.2.19beta6 [May 22, 2007] - Added some #ifdef PNG_MMX_CODE_SUPPORTED where needed in pngvcrd.c - Added a special "_MSC_VER" case that defines png_snprintf to _snprintf - -version 1.2.19beta7 [May 22, 2007] - Squelched png_squelch_warnings() in pnggccrd.c and added an - #ifdef PNG_MMX_CODE_SUPPORTED block around the declarations that caused - the warnings that png_squelch_warnings was squelching. - -version 1.2.19beta8 [May 22, 2007] - Removed __MMX__ from test in pngconf.h. - -version 1.2.19beta9 [May 23, 2007] - Made png_squelch_warnings() available via PNG_SQUELCH_WARNINGS macro. - Revised png_squelch_warnings() so it might work. - Updated makefile.sgcc and makefile.solaris; added makefile.solaris-x86. - -version 1.2.19beta10 [May 24, 2007] - Resquelched png_squelch_warnings(), use "__attribute__((used))" instead. - -version 1.2.19beta11 [May 28, 2007] - Return 0 from png_get_sPLT() and png_get_unknown_chunks() if png_ptr is NULL; - changed three remaining instances of png_strcpy() to png_strncpy() (David - Hill). - Make test for NULL row_buf at the beginning of png_do_read_transformations - unconditional. - -version 1.2.19beta12 [May 28, 2007] - Revised pnggccrd.c. - -version 1.2.19beta13 [June 14, 2007] - Prefer PNG_USE_PNGVCRD when _MSC_VER is defined in pngconf.h - -version 1.2.19beta14 [June 16, 2007] - Fix bug with handling of 16-bit transparency, introduced in 1.2.19beta2 - -version 1.2.19beta15 [June 17, 2007] - Revised pnggccrd.c. - -version 1.2.19beta16 [June 18, 2007] - Revised pnggccrd.c again. - Updated contrib/gregbook. - Changed '#include "pnggccrd.c"' to 'include "$srcdir/pnggccrd.c"' - in configure.ac - -version 1.2.19beta17 [June 19, 2007] - Revised many of the makefiles, to set -DPNG_NO_MMX_CODE where needed - and to not use -O3 unless -DPNG_NO_MMX_CODE is also set. - -version 1.2.19beta18 [June 23, 2007] - Replaced some C++ style comments with C style comments in pnggccrd.c. - Copied optimized C code from pnggccrd.c to pngrutil.c, removed dependency - on pnggccrd.o from many makefiles. - Added sl and dylib to list of extensions be installed by Makefile.am - -version 1.2.19beta19 [June 28, 2007] - Fixed testing PNG_RGB_TO_GRAY_ERR & PNG_RGB_TO_GRAY_WARN in pngrtran.c - More cleanup of pnggccrd.c and pngvcrd.c - -version 1.2.19beta20 [June 29, 2007] - Rebuilt Makefile.in and configure using libtool-1.5.24. - Fixed typo in pnggccrd.c - -version 1.2.19beta21 [June 30, 2007] - More revision of pnggccrd.c - Added "test" target to Makefile.in and Makefile.am - -version 1.2.19beta22 [July 3, 2007] - Added info about pngrutil/pnggccrd/pngvcrd to png_get_header_version() - Fix type definition of dummy_value_a, b in pnggccrd.c - -version 1.2.19beta23 [July 10, 2007] - Revert change to type definition of dummy_value_a, b in pnggccrd.c - Make sure __PIC__ is defined in pnggccrd.c when PIC is defined. - Require gcc-4.1 or better to use PNG_HAVE_MMX_FILTER_ROW on x86_64 platforms - -version 1.2.19beta24 [July 14, 2007] - Added PNG_NO_READ_FILTER, PNG_NO_WRITE_FILTER, PNG_NO_WARNING macros. - Added contrib/pngminim to demonstrate building minimal encoder and decoder - -version 1.2.19beta25 [July 15, 2007] - Removed the new PNG_NO_READ_FILTER macro since it would make the library - unable to read valid PNG files, and filtering is at the heart of the - PNG format. - -version 1.2.19beta26 [July 16, 2007] - Changed "png_free(str)" to "png_free(png_ptr,str)" in pngrutil.c WinCE - code (Yves Piguet). This bug was introduced in libpng-1.2.14. - Updated scripts/CMakeLists.txt - Relocated a misplaced #endif in pnggccrd.c - -version 1.2.19beta27 [July 17, 2007] - Fixed incorrect stride and number of bytes copied (was 4 instead of - 6 bytes) in the cleanup loop of pnggccrd.c and pngvcrd.c for handling - the end of 48-bit interlaced rows (Glenn R-P). - -version 1.2.19beta28 [July 19, 2007] - Removed requirement for gcc-4.1 or better to use PNG_HAVE_MMX_FILTER_ROW - on x86_64 platforms - Added png_warning() in pngrutil.c for short iCCP, iTXt, sPLT, or zTXT chunks. - Revised pngtest.c so warnings are displayed regardless of PNG_NO_STDIO. - -version 1.2.19beta29 [July 20, 2007] - Fix typo in pnggccrd.c (%%eax should be %%ax in secondloop48) - -version 1.2.19beta30 [July 26, 2007] - Revised pnggccrd.c - -version 1.2.19beta31 [July 27, 2007] - Fix typos in pnggccrd.c - -version 1.0.27rc1 and 1.2.19rc1 [July 31, 2007] - Disable PNG_MMX_CODE_SUPPORTED when PNG_ASSEMBLER_CODE_SUPPORTED is off. - Enable PNG_MMX_READ_FILTER_* by default, except when gcc-3.x is being - used (they were inadvertently disabled in libpng-1.2.19beta23). - Fix some debugging statements in pnggccrd.c and pngrutil.c - Added information about disabling the MMX code in libpng documentation. - -version 1.0.27rc2 and 1.2.19rc2 [August 4, 2007] - Removed some "#if 0" blocks. - Made a global struct local in pngvcrd.c to make it thread safe. - Issue a png_error() if application attempts to transform a row tht - has not been initialized. - -version 1.0.27rc3 and 1.2.19rc3 [August 9, 2007] - Slightly revised pngvcrd.c - -version 1.0.27rc4 and 1.2.19rc4 [August 9, 2007] - Revised pnggccrd.c debugging change of rc1, which was broken. - Revised scripts/CMakeLists.txt - Change default to PNG_NO_GLOBAL_ARRAYS for MSVC. - Turn off PNG_FLAG_ROW_INIT flag when setting transforms that expand pixels. - -version 1.0.27rc5 and 1.2.19rc5 [August 10, 2007] - Fix typo (missing '"') in pnggccrd.c - Revise handling of png_strtod in recent versions of WINCE - -version 1.0.27rc6 and 1.2.19rc6 [August 15, 2007] - Fix typo (missing ',') in contrib/gregbook/readpng2.c - Undid row initialization error exit added to rc2 and rc4. - -version 1.0.27 and 1.2.19 [August 18, 2007] - Conditionally restored row initialization error exit. - -version 1.2.20beta01 [August 19, 2007] - Fixed problem with compiling pnggccrd.c on Intel-Apple platforms. - Changed png_malloc() to png_malloc_warn() in png_set_sPLT(). - Added PNG_NO_ERROR_TEXT feature, with demo in contrib/pngminim - Removed define PNG_WARN_UNINITIALIZED_ROW 1 /* 0: warning; 1: error */ - because it caused some trouble. - -version 1.2.20beta02 [August 20, 2007] - Avoid compiling pnggccrd.c on Intel-Apple platforms. - -version 1.2.20beta03 [August 20, 2007] - Added "/D PNG_NO_MMX_CODE" to the non-mmx builds of projects/visualc6 - and visualc71. - -version 1.2.20beta04 [August 21, 2007] - Revised pngvcrd.c for improved efficiency (Steve Snyder). - -version 1.2.20rc1 [August 23, 2007] - Revised pngconf.h to set PNG_NO_MMX_CODE for gcc-3.x compilers. - -version 1.2.20rc2 [August 27, 2007] - Revised scripts/CMakeLists.txt - Revised #ifdefs to ensure one and only one of pnggccrd.c, pngvcrd.c, - or part of pngrutil.c is selected. - -version 1.2.20rc3 [August 30, 2007] - Remove a little more code in pngwutil.c when PNG_NO_WRITE_FILTER is selected. - Added /D _CRT_SECURE_NO_WARNINGS to visual6c and visualc71 projects. - Compile png_mmx_support() in png.c even when PNG_NO_MMX_CODE is defined. - Restored a "superfluous" #ifdef that was removed from 1.2.20rc2 pnggccrd.c, - breaking the png_mmx_support() function. - -version 1.2.20rc4 [September 1, 2007] - Removed Intel contributions (MMX, Optimized C). - -version 1.2.20rc5 [September 2, 2007] - Restored configure and Makefile.in to rc3 and put a snippet of code in - pnggccrd.c, to ensure configure makes the same PNG_NO_MMX_CODE selection - -version 1.2.20rc6 [September 2, 2007] - Fixed bugs in scripts/CMakeLists.txt - Removed pngvcrd.c references from msvc projects. - -version 1.0.28 and 1.2.20 [September 8, 2007] - Removed "(NO READ SUPPORT)" from png_get_header_version() string. - -version 1.2.21beta1 [September 14, 2007] - Fixed various mistakes reported by George Cook and Jeff Phillips: - logical vs bitwise NOT in pngrtran.c, bug introduced in 1.2.19rc2 - 16-bit cheap transparency expansion, bug introduced in 1.2.19beta2 - errors with sizeof(unknown_chunk.name), bugs introduced in 1.2.19beta11 - <= compare with unsigned var in pngset.c, should be ==. - -version 1.2.21beta2 [September 18, 2007] - Removed some extraneous typecasts. - -version 1.2.21rc1 [September 25, 2007] - Fixed potential out-of-bounds reads in png_handle_pCAL() and - png_handle_ztXt() ("flayer" results reported by Tavis Ormandy). - -version 1.2.21rc2 [September 26, 2007] - Fixed potential out-of-bounds reads in png_handle_sCAL(), - png_handle_iTXt(), and png_push_read_tEXt(). - Remove some PNG_CONST declarations from pngwutil.c to avoid compiler warnings - Revised makefiles to update paths in libpng.pc properly. - -version 1.2.21rc3 [September 27, 2007] - Revised makefiles to update "Libs" in libpng.pc properly. - -version 1.0.29 and 1.2.21rc3 [October 4, 2007] - No changes. - -version 1.2.22beta1 [October 4, 2007] - Again, fixed logical vs bitwise NOT in pngrtran.c, bug introduced - in 1.2.19rc2 - -version 1.2.22beta2 [October 5, 2007] - Fixed string length error in pngset.c (caused crashes while decoding iCCP) - Add terminating NULL after each instance of png_strncpy(). - -version 1.2.22beta3 [October 6, 2007] - Fix two off-by-one terminating NULL after png_strncpy(). - -version 1.2.22beta4 [October 7, 2007] - Changed some 0 to '\0'. - -version 1.0.30rc1 and 1.2.22rc1 [October 8, 2007] - No changes. - -version 1.0.30 and 1.2.22 [October 13, 2007] - No changes. - -version 1.2.23beta01 [October 15, 2007] - Reduced number of invocations of png_strlen() in pngset.c. - Changed [azAZ09_] to [_abcde...89] in Makefile.am for better localization. - -version 1.2.23beta02 [October 16, 2007] - Eliminated png_strncpy() and png_strcpy() (Pierre Poissinger) - Changed $AN to $(AN) in Makefile.am. - -version 1.2.23beta03 [October 16, 2007] - Fixed off-by-one error in pngset.c - Restore statement to set last character of buffer to \0 in pngerror.c - -version 1.2.23beta04 [October 23, 2007] - Reject attempt to set all-zero cHRM values. - -version 1.2.23beta05 [October 26, 2007] - Add missing quotes in projects/visualc6, lost in version 1.2.20rc3 - -version 1.2.23rc01 [November 2, 2007] - No changes. - -version 1.2.23 [November 6, 2007] - No changes. - -version 1.2.24beta01 [November 19, 2007] - Moved misplaced test for malloc failure in png_set_sPLT(). This bug was - introduced in libpng-1.2.20beta01. - Ifdef out avg_row etc from png.h and pngwrite.c when PNG_NO_WRITE_FILTER - Do not use png_ptr->free_fn and png_ptr->mem_fn in png_destroy_read_struct() - when png_ptr is NULL (Marshall Clow). - Updated handling of symbol prefixes in Makefile.am and configure.ac (Mike - Frysinger). - -version 1.2.24beta02 [November 30, 2007] - Removed a useless test and fixed incorrect test in png_set_cHRM_fixed() - (David Hill). - -version 1.2.24rc01 [December 7, 2007] - No changes. - -version 1.2.24 [December 14, 2007] - Make sure not to redefine _BSD_SOURCE in pngconf.h - Revised gather.sh and makefile.std in contrib/pngminim to avoid compiling - unused files. - -Send comments/corrections/commendations to png-mng-implement at lists.sf.net -(subscription required; visit -https://lists.sourceforge.net/lists/listinfo/png-mng-implement -to subscribe) -or to glennrp at users.sourceforge.net - -Glenn R-P diff --git a/rosapps/lib/libpng/docs/INSTALL b/rosapps/lib/libpng/docs/INSTALL deleted file mode 100644 index ff9c9f29eee..00000000000 --- a/rosapps/lib/libpng/docs/INSTALL +++ /dev/null @@ -1,219 +0,0 @@ - -Installing libpng version 1.2.24 - December 14, 2007 - -On Unix/Linux and similar systems, you can simply type - - ./configure [--prefix=/path] - make check - make install - -and ignore the rest of this document. - -If configure does not work on your system and you have a reasonably -up-to-date set of tools, running ./autogen.sh before running ./configure -may fix the problem. You can also run the individual commands in -autogen.sh with the --force option, if supported by your version of -the tools. If you run 'libtoolize --force', though, this will replace -the distributed, patched, version of ltmain.sh with an unpatched version -and your shared library builds may fail to produce libraries with the -correct version numbers. - -Instead, you can use one of the custom-built makefiles in the -"scripts" directory - - cp scripts/makefile.system makefile - make test - make install - -Or you can use one of the "projects" in the "projects" directory. - -If you want to use "cmake" (see www.cmake.org), copy CMakeLists.txt -from the "scripts" directory to this directory and type - - cmake . [-DPNG_MMX=YES] -DCMAKE_INSTALL_PREFIX=/path - make - make install - -Before installing libpng, you must first install zlib, if it -is not already on your system. zlib can usually be found -wherever you got libpng. zlib can be placed in another directory, -at the same level as libpng. - -If your system already has a preinstalled zlib you will still need -to have access to the zlib.h and zconf.h include files that -correspond to the version of zlib that's installed. - -You can rename the directories that you downloaded (they -might be called "libpng-1.2.24" or "lpng109" and "zlib-1.2.1" -or "zlib121") so that you have directories called "zlib" and "libpng". - -Your directory structure should look like this: - - .. (the parent directory) - libpng (this directory) - INSTALL (this file) - README - *.h - *.c - contrib - gregbook - pngminus - pngsuite - visupng - projects - beos - c5builder (Borland) - visualc6 (msvc) - netware.txt - wince.txt - scripts - makefile.* - pngtest.png - etc. - zlib - README - *.h - *.c - contrib - etc. - -If the line endings in the files look funny, you may wish to get the other -distribution of libpng. It is available in both tar.gz (UNIX style line -endings) and zip (DOS style line endings) formats. - -If you are building libpng with MSVC, you can enter the -libpng projects\visualc6 directory and follow the instructions in -projects\visualc6\README.txt. - -You can build libpng for WindowsCE by downloading and installing -the projects\wince directory as instructed in the projects\wince.txt file, and -then following the instructions in the README* files. Similarly, you can -build libpng for Netware or Beos as instructed in projects\netware.txt -or projects\beos. - -Else enter the zlib directory and follow the instructions in zlib/README, -then come back here and run "configure" or choose the appropriate -makefile.sys in the scripts directory. - -The files that are presently available in the scripts directory -include - - CMakeLists.txt => "cmake" script - makefile.std => Generic UNIX makefile (cc, creates static libpng.a) - makefile.elf => Linux/ELF makefile symbol versioning, - gcc, creates libpng12.so.0.1.2.24) - makefile.linux => Linux/ELF makefile - (gcc, creates libpng12.so.0.1.2.24) - makefile.gcc => Generic makefile (gcc, creates static libpng.a) - makefile.knr => Archaic UNIX Makefile that converts files with - ansi2knr (Requires ansi2knr.c from - ftp://ftp.cs.wisc.edu/ghost) - makefile.aix => AIX/gcc makefile - makefile.cygwin => Cygwin/gcc makefile - makefile.darwin => Darwin makefile, can use on MacosX - makefile.dec => DEC Alpha UNIX makefile - makefile.freebsd => FreeBSD makefile - makefile.hpgcc => HPUX makefile using gcc - makefile.hpux => HPUX (10.20 and 11.00) makefile - makefile.hp64 => HPUX (10.20 and 11.00) makefile, 64-bit - makefile.ibmc => IBM C/C++ version 3.x for Win32 and OS/2 (static) - makefile.intel => Intel C/C++ version 4.0 and later - libpng.icc => Project file for IBM VisualAge/C++ version 4.0 or later - makefile.netbsd => NetBSD/cc makefile, uses PNGGCCRD, makes libpng.so. - makefile.ne12bsd => NetBSD/cc makefile, uses PNGGCCRD, - makes libpng12.so - makefile.openbsd => OpenBSD makefile - makefile.sgi => Silicon Graphics IRIX makefile (cc, creates static lib) - makefile.sggcc => Silicon Graphics (gcc, - creates libpng12.so.0.1.2.24) - makefile.sunos => Sun makefile - makefile.solaris => Solaris 2.X makefile (gcc, - creates libpng12.so.0.1.2.24) - makefile.solaris-x86 => Solaris/intelMMX 2.X makefile (gcc, - creates libpng12.so.0.1.2.24) - makefile.so9 => Solaris 9 makefile (gcc, - creates libpng12.so.0.1.2.24) - makefile.32sunu => Sun Ultra 32-bit makefile - makefile.64sunu => Sun Ultra 64-bit makefile - makefile.sco => For SCO OSr5 ELF and Unixware 7 with Native cc - makefile.mips => MIPS makefile - makefile.acorn => Acorn makefile - makefile.amiga => Amiga makefile - smakefile.ppc => AMIGA smakefile for SAS C V6.58/7.00 PPC compiler - (Requires SCOPTIONS, copied from scripts/SCOPTIONS.ppc) - makefile.atari => Atari makefile - makefile.beos => BEOS makefile for X86 - makefile.bor => Borland makefile (uses bcc) - makefile.bc32 => 32-bit Borland C++ (all modules compiled in C mode) - makefile.tc3 => Turbo C 3.0 makefile - makefile.dj2 => DJGPP 2 makefile - makefile.msc => Microsoft C makefile - makefile.vcwin32 => makefile for Microsoft Visual C++ 4.0 and later - makefile.os2 => OS/2 Makefile (gcc and emx, requires pngos2.def) - pngos2.def => OS/2 module definition file used by makefile.os2 - makefile.watcom => Watcom 10a+ Makefile, 32-bit flat memory model - makevms.com => VMS build script - descrip.mms => VMS makefile for MMS or MMK - SCOPTIONS.ppc => Used with smakefile.ppc - -Copy the file (or files) that you need from the -scripts directory into this directory, for example - - MSDOS example: copy scripts\makefile.msc makefile - UNIX example: cp scripts/makefile.std makefile - -Read the makefile to see if you need to change any source or -target directories to match your preferences. - -Then read pngconf.h to see if you want to make any configuration -changes. - -Then just run "make" which will create the libpng library in -this directory and "make test" which will run a quick test that reads -the "pngtest.png" file and writes a "pngout.png" file that should be -identical to it. Look for "9782 zero samples" in the output of the -test. For more confidence, you can run another test by typing -"pngtest pngnow.png" and looking for "289 zero samples" in the output. -Also, you can run "pngtest -m contrib/pngsuite/*.png" and compare -your output with the result shown in contrib/pngsuite/README. - -Most of the makefiles will allow you to run "make install" to -put the library in its final resting place (if you want to -do that, run "make install" in the zlib directory first if necessary). -Some also allow you to run "make test-installed" after you have -run "make install". - -If you encounter a compiler error message complaining about the -lines - __png.h__ already includes setjmp.h; - __dont__ include it again.; -This means you have compiled another module that includes setjmp.h, -which is hazardous because the two modules might not include exactly -the same setjmp.h. If you are sure that you know what you are doing -and that they are exactly the same, then you can comment out or -delete the two lines. Better yet, use the cexcept interface -instead, as demonstrated in contrib/visupng of the libpng distribution. - -Further information can be found in the README and libpng.txt -files, in the individual makefiles, in png.h, and the manual pages -libpng.3 and png.5. - - -Using the ./configure script -- 16 December 2002. -================================================= - - -The ./configure script should work compatibly with what scripts/makefile.* -did, however there are some options you need to add to configure explicitly, -which previously was done semi-automatically (if you didn't edit -scripts/makefile.* yourself, that is) - - -CFLAGS="-Wall -O -funroll-loops \ --malign-loops=2 -malign-functions=2" ./configure --prefix=/usr/include \ ---with-pkgconfigdir=/usr/lib/pkgconfig --includedir=/usr/include - -You can alternatively specify --includedir=/usr/include, /usr/local/include, -/usr/include/png12, or whatever. - - diff --git a/rosapps/lib/libpng/docs/KNOWNBUG b/rosapps/lib/libpng/docs/KNOWNBUG deleted file mode 100644 index d39dd1ec313..00000000000 --- a/rosapps/lib/libpng/docs/KNOWNBUG +++ /dev/null @@ -1,22 +0,0 @@ - -Known bugs in libpng version 1.2.24 - -1. February 23, 2006: The custom makefiles don't build libpng with -lz. - - STATUS: This is a subject of debate. The change will probably be made - as a part of a major overhaul of the makefiles in libpng version 1.4.0. - -2. February 24, 2006: The Makefile generated by the "configure" script - fails to install symbolic links - libpng12.so => libpng12.so.0.1.2.9betaN - that are generated by the custom makefiles. - -3. September 4, 2007: There is a report that pngtest crashes on MacOS 10. - - STATUS: workarounds are - 1) Compile without optimization (crashes are observed with - -arch i386 and -O2 or -O3, using gcc-4.0.1). - 2) Compile pngtest.c with PNG_DEBUG defined (the bug goes away if - you try to look at it). - 3) Ignore the crash. The library itself seems to be OK. - diff --git a/rosapps/lib/libpng/docs/LICENSE b/rosapps/lib/libpng/docs/LICENSE deleted file mode 100644 index 6b81b55a63c..00000000000 --- a/rosapps/lib/libpng/docs/LICENSE +++ /dev/null @@ -1,109 +0,0 @@ - -This copy of the libpng notices is provided for your convenience. In case of -any discrepancy between this copy and the notices in the file png.h that is -included in the libpng distribution, the latter shall prevail. - -COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: - -If you modify libpng you may insert additional notices immediately following -this sentence. - -libpng versions 1.2.6, August 15, 2004, through 1.2.24, December 14, 2007, are -Copyright (c) 2004, 2006-2007 Glenn Randers-Pehrson, and are -distributed according to the same disclaimer and license as libpng-1.2.5 -with the following individual added to the list of Contributing Authors - - Cosmin Truta - -libpng versions 1.0.7, July 1, 2000, through 1.2.5 - October 3, 2002, are -Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are -distributed according to the same disclaimer and license as libpng-1.0.6 -with the following individuals added to the list of Contributing Authors - - Simon-Pierre Cadieux - Eric S. Raymond - Gilles Vollant - -and with the following additions to the disclaimer: - - There is no warranty against interference with your enjoyment of the - library or against infringement. There is no warranty that our - efforts or the library will fulfill any of your particular purposes - or needs. This library is provided with all faults, and the entire - risk of satisfactory quality, performance, accuracy, and effort is with - the user. - -libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are -Copyright (c) 1998, 1999 Glenn Randers-Pehrson, and are -distributed according to the same disclaimer and license as libpng-0.96, -with the following individuals added to the list of Contributing Authors: - - Tom Lane - Glenn Randers-Pehrson - Willem van Schaik - -libpng versions 0.89, June 1996, through 0.96, May 1997, are -Copyright (c) 1996, 1997 Andreas Dilger -Distributed according to the same disclaimer and license as libpng-0.88, -with the following individuals added to the list of Contributing Authors: - - John Bowler - Kevin Bracey - Sam Bushell - Magnus Holmgren - Greg Roelofs - Tom Tanner - -libpng versions 0.5, May 1995, through 0.88, January 1996, are -Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. - -For the purposes of this copyright and license, "Contributing Authors" -is defined as the following set of individuals: - - Andreas Dilger - Dave Martindale - Guy Eric Schalnat - Paul Schmidt - Tim Wegner - -The PNG Reference Library is supplied "AS IS". The Contributing Authors -and Group 42, Inc. disclaim all warranties, expressed or implied, -including, without limitation, the warranties of merchantability and of -fitness for any purpose. The Contributing Authors and Group 42, Inc. -assume no liability for direct, indirect, incidental, special, exemplary, -or consequential damages, which may result from the use of the PNG -Reference Library, even if advised of the possibility of such damage. - -Permission is hereby granted to use, copy, modify, and distribute this -source code, or portions hereof, for any purpose, without fee, subject -to the following restrictions: - -1. The origin of this source code must not be misrepresented. - -2. Altered versions must be plainly marked as such and must not - be misrepresented as being the original source. - -3. This Copyright notice may not be removed or altered from any - source or altered source distribution. - -The Contributing Authors and Group 42, Inc. specifically permit, without -fee, and encourage the use of this source code as a component to -supporting the PNG file format in commercial products. If you use this -source code in a product, acknowledgment is not required but would be -appreciated. - - -A "png_get_copyright" function is available, for convenient use in "about" -boxes and the like: - - printf("%s",png_get_copyright(NULL)); - -Also, the PNG logo (in PNG format, of course) is supplied in the -files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31). - -Libpng is OSI Certified Open Source Software. OSI Certified Open Source is a -certification mark of the Open Source Initiative. - -Glenn Randers-Pehrson -glennrp at users.sourceforge.net -December 14, 2007 diff --git a/rosapps/lib/libpng/docs/README b/rosapps/lib/libpng/docs/README deleted file mode 100644 index 6f84c69f0d8..00000000000 --- a/rosapps/lib/libpng/docs/README +++ /dev/null @@ -1,263 +0,0 @@ -README for libpng version 1.2.24 - December 14, 2007 (shared library 12.0) -See the note about version numbers near the top of png.h - -See INSTALL for instructions on how to install libpng. - -Libpng comes in several distribution formats. Get libpng-*.tar.gz -or libpng-*.tar.bz2 if you want UNIX-style line endings in the text -files, or lpng*.zip if you want DOS-style line endings. - -Version 0.89 was the first official release of libpng. Don't let the -fact that it's the first release fool you. The libpng library has been in -extensive use and testing since mid-1995. By late 1997 it had -finally gotten to the stage where there hadn't been significant -changes to the API in some time, and people have a bad feeling about -libraries with versions < 1.0. Version 1.0.0 was released in -March 1998. - -**** -Note that some of the changes to the png_info structure render this -version of the library binary incompatible with libpng-0.89 or -earlier versions if you are using a shared library. The type of the -"filler" parameter for png_set_filler() has changed from png_byte to -png_uint_32, which will affect shared-library applications that use -this function. - -To avoid problems with changes to the internals of png_info_struct, -new APIs have been made available in 0.95 to avoid direct application -access to info_ptr. These functions are the png_set_ and -png_get_ functions. These functions should be used when -accessing/storing the info_struct data, rather than manipulating it -directly, to avoid such problems in the future. - -It is important to note that the APIs do not make current programs -that access the info struct directly incompatible with the new -library. However, it is strongly suggested that new programs use -the new APIs (as shown in example.c and pngtest.c), and older programs -be converted to the new format, to facilitate upgrades in the future. -**** - -Additions since 0.90 include the ability to compile libpng as a -Windows DLL, and new APIs for accessing data in the info struct. -Experimental functions include the ability to set weighting and cost -factors for row filter selection, direct reads of integers from buffers -on big-endian processors that support misaligned data access, faster -methods of doing alpha composition, and more accurate 16->8 bit color -conversion. - -The additions since 0.89 include the ability to read from a PNG stream -which has had some (or all) of the signature bytes read by the calling -application. This also allows the reading of embedded PNG streams that -do not have the PNG file signature. As well, it is now possible to set -the library action on the detection of chunk CRC errors. It is possible -to set different actions based on whether the CRC error occurred in a -critical or an ancillary chunk. - -The changes made to the library, and bugs fixed are based on discussions -on the PNG-implement mailing list -and not on material submitted privately to Guy, Andreas, or Glenn. They will -forward any good suggestions to the list. - -For a detailed description on using libpng, read libpng.txt. For -examples of libpng in a program, see example.c and pngtest.c. For usage -information and restrictions (what little they are) on libpng, see -png.h. For a description on using zlib (the compression library used by -libpng) and zlib's restrictions, see zlib.h - -I have included a general makefile, as well as several machine and -compiler specific ones, but you may have to modify one for your own needs. - -You should use zlib 1.0.4 or later to run this, but it MAY work with -versions as old as zlib 0.95. Even so, there are bugs in older zlib -versions which can cause the output of invalid compression streams for -some images. You will definitely need zlib 1.0.4 or later if you are -taking advantage of the MS-DOS "far" structure allocation for the small -and medium memory models. You should also note that zlib is a -compression library that is useful for more things than just PNG files. -You can use zlib as a drop-in replacement for fread() and fwrite() if -you are so inclined. - -zlib should be available at the same place that libpng is, or at. -ftp://ftp.info-zip.org/pub/infozip/zlib - -You may also want a copy of the PNG specification. It is available -as an RFC, a W3C Recommendation, and an ISO/IEC Standard. You can find -these at http://www.libpng.org/pub/png/documents/ - -This code is currently being archived at libpng.sf.net in the -[DOWNLOAD] area, and on CompuServe, Lib 20 (PNG SUPPORT) -at GO GRAPHSUP. If you can't find it in any of those places, -e-mail me, and I'll help you find it. - -If you have any code changes, requests, problems, etc., please e-mail -them to me. Also, I'd appreciate any make files or project files, -and any modifications you needed to make to get libpng to compile, -along with a #define variable to tell what compiler/system you are on. -If you needed to add transformations to libpng, or wish libpng would -provide the image in a different way, drop me a note (and code, if -possible), so I can consider supporting the transformation. -Finally, if you get any warning messages when compiling libpng -(note: not zlib), and they are easy to fix, I'd appreciate the -fix. Please mention "libpng" somewhere in the subject line. Thanks. - -This release was created and will be supported by myself (of course -based in a large way on Guy's and Andreas' earlier work), and the PNG group. - -Send comments/corrections/commendations to png-mng-implement at lists.sf.net -(subscription required; visit -https://lists.sourceforge.net/lists/listinfo/png-mng-implement -to subscribe) or to glennrp at users.sourceforge.net - -You can't reach Guy, the original libpng author, at the addresses -given in previous versions of this document. He and Andreas will read mail -addressed to the png-implement list, however. - -Please do not send general questions about PNG. Send them to -the (png-mng-misc at lists.sourceforge.net, subscription required, visit -https://lists.sourceforge.net/lists/listinfo/png-mng-implement to subscribe) -On the other hand, -please do not send libpng questions to that address, send them to me -or to the png-implement list. I'll -get them in the end anyway. If you have a question about something -in the PNG specification that is related to using libpng, send it -to me. Send me any questions that start with "I was using libpng, -and ...". If in doubt, send questions to me. I'll bounce them -to others, if necessary. - -Please do not send suggestions on how to change PNG. We have -been discussing PNG for twelve years now, and it is official and -finished. If you have suggestions for libpng, however, I'll -gladly listen. Even if your suggestion is not used immediately, -it may be used later. - -Files in this distribution: - - ANNOUNCE => Announcement of this version, with recent changes - CHANGES => Description of changes between libpng versions - KNOWNBUG => List of known bugs and deficiencies - LICENSE => License to use and redistribute libpng - README => This file - TODO => Things not implemented in the current library - Y2KINFO => Statement of Y2K compliance - example.c => Example code for using libpng functions - libpng-*-*-diff.txt => Diff from previous release - libpng.3 => manual page for libpng (includes libpng.txt) - libpng.txt => Description of libpng and its functions - libpngpf.3 => manual page for libpng's private functions - png.5 => manual page for the PNG format - png.c => Basic interface functions common to library - png.h => Library function and interface declarations - pngconf.h => System specific library configuration - pngerror.c => Error/warning message I/O functions - pngget.c => Functions for retrieving info from struct - pngmem.c => Memory handling functions - pngbar.png => PNG logo, 88x31 - pngnow.png => PNG logo, 98x31 - pngpread.c => Progressive reading functions - pngread.c => Read data/helper high-level functions - pngrio.c => Lowest-level data read I/O functions - pngrtran.c => Read data transformation functions - pngrutil.c => Read data utility functions - pngset.c => Functions for storing data into the info_struct - pngtest.c => Library test program - pngtest.png => Library test sample image - pngtrans.c => Common data transformation functions - pngwio.c => Lowest-level write I/O functions - pngwrite.c => High-level write functions - pngwtran.c => Write data transformations - pngwutil.c => Write utility functions - contrib => Contributions - gregbook => source code for PNG reading and writing, from - Greg Roelofs' "PNG: The Definitive Guide", - O'Reilly, 1999 - msvctest => Builds and runs pngtest using a MSVC workspace - pngminus => Simple pnm2png and png2pnm programs - pngsuite => Test images - visupng => Contains a MSVC workspace for VisualPng - projects => Contains project files and workspaces for building DLL - beos => Contains a Beos workspace for building libpng - c5builder => Contains a Borland workspace for building libpng - and zlib - visualc6 => Contains a Microsoft Visual C++ (MSVC) workspace - for building libpng and zlib - netware.txt => Contains instructions for downloading a set of - project files for building libpng and zlib on - Netware. - wince.txt => Contains instructions for downloading a Microsoft - Visual C++ (Windows CD Toolkit) workspace for - building libpng and zlib on WindowsCE - scripts => Directory containing scripts for building libpng: - descrip.mms => VMS makefile for MMS or MMK - makefile.std => Generic UNIX makefile (cc, creates static libpng.a) - makefile.elf => Linux/ELF makefile symbol versioning, - gcc, creates libpng12.so.0.1.2.24) - makefile.linux => Linux/ELF makefile - (gcc, creates libpng12.so.0.1.2.24) - makefile.gcmmx => Linux/ELF makefile - (gcc, creates libpng12.so.0.1.2.24, - uses assembler code tuned for Intel MMX platform) - makefile.gcc => Generic makefile (gcc, creates static libpng.a) - makefile.knr => Archaic UNIX Makefile that converts files with - ansi2knr (Requires ansi2knr.c from - ftp://ftp.cs.wisc.edu/ghost) - makefile.aix => AIX makefile - makefile.cygwin => Cygwin/gcc makefile - makefile.darwin => Darwin makefile - makefile.dec => DEC Alpha UNIX makefile - makefile.freebsd => FreeBSD makefile - makefile.hpgcc => HPUX makefile using gcc - makefile.hpux => HPUX (10.20 and 11.00) makefile - makefile.hp64 => HPUX (10.20 and 11.00) makefile, 64 bit - makefile.ibmc => IBM C/C++ version 3.x for Win32 and OS/2 (static) - makefile.intel => Intel C/C++ version 4.0 and later - libpng.icc => Project file, IBM VisualAge/C++ 4.0 or later - makefile.netbsd => NetBSD/cc makefile, PNGGCCRD, makes libpng.so. - makefile.ne12bsd => NetBSD/cc makefile, PNGGCCRD, makes libpng12.so - makefile.openbsd => OpenBSD makefile - makefile.sgi => Silicon Graphics IRIX (cc, creates static lib) - makefile.sggcc => Silicon Graphics - (gcc, creates libpng12.so.0.1.2.24) - makefile.sunos => Sun makefile - makefile.solaris => Solaris 2.X makefile - (gcc, creates libpng12.so.0.1.2.24) - makefile.so9 => Solaris 9 makefile - (gcc, creates libpng12.so.0.1.2.24) - makefile.32sunu => Sun Ultra 32-bit makefile - makefile.64sunu => Sun Ultra 64-bit makefile - makefile.sco => For SCO OSr5 ELF and Unixware 7 with Native cc - makefile.mips => MIPS makefile - makefile.acorn => Acorn makefile - makefile.amiga => Amiga makefile - smakefile.ppc => AMIGA smakefile for SAS C V6.58/7.00 PPC - compiler (Requires SCOPTIONS, copied from - scripts/SCOPTIONS.ppc) - makefile.atari => Atari makefile - makefile.beos => BEOS makefile for X86 - makefile.bor => Borland makefile (uses bcc) - makefile.bc32 => 32-bit Borland C++ (all modules compiled in C mode) - makefile.tc3 => Turbo C 3.0 makefile - makefile.dj2 => DJGPP 2 makefile - makefile.msc => Microsoft C makefile - makefile.vcawin32=> makefile for Microsoft Visual C++ 5.0 and - later (uses assembler code tuned for Intel MMX - platform) - makefile.vcwin32 => makefile for Microsoft Visual C++ 4.0 and - later (does not use assembler code) - makefile.os2 => OS/2 Makefile (gcc and emx, requires pngos2.def) - pngos2.def => OS/2 module definition file used by makefile.os2 - makefile.watcom => Watcom 10a+ Makefile, 32-bit flat memory model - makevms.com => VMS build script - SCOPTIONS.ppc => Used with smakefile.ppc - -Good luck, and happy coding. - --Glenn Randers-Pehrson (current maintainer) - Internet: glennrp at users.sourceforge.net - --Andreas Eric Dilger (former maintainer, 1996-1997) - Internet: adilger at enel.ucalgary.ca - Web: http://www-mddsp.enel.ucalgary.ca/People/adilger/ - --Guy Eric Schalnat (original author and former maintainer, 1995-1996) - (formerly of Group 42, Inc) - Internet: gschal at infinet.com diff --git a/rosapps/lib/libpng/docs/TODO b/rosapps/lib/libpng/docs/TODO deleted file mode 100644 index a5f639577dd..00000000000 --- a/rosapps/lib/libpng/docs/TODO +++ /dev/null @@ -1,24 +0,0 @@ -TODO - list of things to do for libpng: - -Final bug fixes. -Improve API by hiding the png_struct and png_info structs. -Finish work on the no-floating-point version (including gamma compensation) -Better C++ wrapper/full C++ implementation? -Fix problem with C++ and EXTERN "C". -cHRM transformation. -Improve setjmp/longjmp usage or remove it in favor of returning error codes. -Add "grayscale->palette" transformation and "palette->grayscale" detection. -Improved dithering. -Multi-lingual error and warning message support. -Complete sRGB transformation (presently it simply uses gamma=0.45455). -Man pages for function calls. -Better documentation. -Better filter selection - (counting huffman bits/precompression? filter inertia? filter costs?). -Histogram creation. -Text conversion between different code pages (Latin-1 -> Mac and DOS). -Should we always malloc 2^bit_depth PLTE/tRNS/hIST entries for safety? -Build gamma tables using fixed point (and do away with floating point entirely). -Use greater precision when changing to linear gamma for compositing against - background and doing rgb-to-gray transformation. -Investigate pre-incremented loop counters and other loop constructions. diff --git a/rosapps/lib/libpng/docs/Y2KINFO b/rosapps/lib/libpng/docs/Y2KINFO deleted file mode 100644 index 829b511e45c..00000000000 --- a/rosapps/lib/libpng/docs/Y2KINFO +++ /dev/null @@ -1,55 +0,0 @@ - Y2K compliance in libpng: - ========================= - - December 14, 2007 - - Since the PNG Development group is an ad-hoc body, we can't make - an official declaration. - - This is your unofficial assurance that libpng from version 0.71 and - upward through 1.2.24 are Y2K compliant. It is my belief that earlier - versions were also Y2K compliant. - - Libpng only has three year fields. One is a 2-byte unsigned integer - that will hold years up to 65535. The other two hold the date in text - format, and will hold years up to 9999. - - The integer is - "png_uint_16 year" in png_time_struct. - - The strings are - "png_charp time_buffer" in png_struct and - "near_time_buffer", which is a local character string in png.c. - - There are seven time-related functions: - - png_convert_to_rfc_1123() in png.c - (formerly png_convert_to_rfc_1152() in error) - png_convert_from_struct_tm() in pngwrite.c, called in pngwrite.c - png_convert_from_time_t() in pngwrite.c - png_get_tIME() in pngget.c - png_handle_tIME() in pngrutil.c, called in pngread.c - png_set_tIME() in pngset.c - png_write_tIME() in pngwutil.c, called in pngwrite.c - - All appear to handle dates properly in a Y2K environment. The - png_convert_from_time_t() function calls gmtime() to convert from system - clock time, which returns (year - 1900), which we properly convert to - the full 4-digit year. There is a possibility that applications using - libpng are not passing 4-digit years into the png_convert_to_rfc_1123() - function, or that they are incorrectly passing only a 2-digit year - instead of "year - 1900" into the png_convert_from_struct_tm() function, - but this is not under our control. The libpng documentation has always - stated that it works with 4-digit years, and the APIs have been - documented as such. - - The tIME chunk itself is also Y2K compliant. It uses a 2-byte unsigned - integer to hold the year, and can hold years as large as 65535. - - zlib, upon which libpng depends, is also Y2K compliant. It contains - no date-related code. - - - Glenn Randers-Pehrson - libpng maintainer - PNG Development Group diff --git a/rosapps/lib/libpng/docs/example.c b/rosapps/lib/libpng/docs/example.c deleted file mode 100644 index 08158731a69..00000000000 --- a/rosapps/lib/libpng/docs/example.c +++ /dev/null @@ -1,814 +0,0 @@ - -#if 0 /* in case someone actually tries to compile this */ - -/* example.c - an example of using libpng - * Last changed in libpng 1.2.1 December 7, 2001. - * This file has been placed in the public domain by the authors. - * Maintained 1998-2007 Glenn Randers-Pehrson - * Maintained 1996, 1997 Andreas Dilger) - * Written 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - */ - -/* This is an example of how to use libpng to read and write PNG files. - * The file libpng.txt is much more verbose then this. If you have not - * read it, do so first. This was designed to be a starting point of an - * implementation. This is not officially part of libpng, is hereby placed - * in the public domain, and therefore does not require a copyright notice. - * - * This file does not currently compile, because it is missing certain - * parts, like allocating memory to hold an image. You will have to - * supply these parts to get it to compile. For an example of a minimal - * working PNG reader/writer, see pngtest.c, included in this distribution; - * see also the programs in the contrib directory. - */ - -#include "png.h" - - /* The png_jmpbuf() macro, used in error handling, became available in - * libpng version 1.0.6. If you want to be able to run your code with older - * versions of libpng, you must define the macro yourself (but only if it - * is not already defined by libpng!). - */ - -#ifndef png_jmpbuf -# define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) -#endif - -/* Check to see if a file is a PNG file using png_sig_cmp(). png_sig_cmp() - * returns zero if the image is a PNG and nonzero if it isn't a PNG. - * - * The function check_if_png() shown here, but not used, returns nonzero (true) - * if the file can be opened and is a PNG, 0 (false) otherwise. - * - * If this call is successful, and you are going to keep the file open, - * you should call png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK); once - * you have created the png_ptr, so that libpng knows your application - * has read that many bytes from the start of the file. Make sure you - * don't call png_set_sig_bytes() with more than 8 bytes read or give it - * an incorrect number of bytes read, or you will either have read too - * many bytes (your fault), or you are telling libpng to read the wrong - * number of magic bytes (also your fault). - * - * Many applications already read the first 2 or 4 bytes from the start - * of the image to determine the file type, so it would be easiest just - * to pass the bytes to png_sig_cmp() or even skip that if you know - * you have a PNG file, and call png_set_sig_bytes(). - */ -#define PNG_BYTES_TO_CHECK 4 -int check_if_png(char *file_name, FILE **fp) -{ - char buf[PNG_BYTES_TO_CHECK]; - - /* Open the prospective PNG file. */ - if ((*fp = fopen(file_name, "rb")) == NULL) - return 0; - - /* Read in some of the signature bytes */ - if (fread(buf, 1, PNG_BYTES_TO_CHECK, *fp) != PNG_BYTES_TO_CHECK) - return 0; - - /* Compare the first PNG_BYTES_TO_CHECK bytes of the signature. - Return nonzero (true) if they match */ - - return(!png_sig_cmp(buf, (png_size_t)0, PNG_BYTES_TO_CHECK)); -} - -/* Read a PNG file. You may want to return an error code if the read - * fails (depending upon the failure). There are two "prototypes" given - * here - one where we are given the filename, and we need to open the - * file, and the other where we are given an open file (possibly with - * some or all of the magic bytes read - see comments above). - */ -#ifdef open_file /* prototype 1 */ -void read_png(char *file_name) /* We need to open the file */ -{ - png_structp png_ptr; - png_infop info_ptr; - unsigned int sig_read = 0; - png_uint_32 width, height; - int bit_depth, color_type, interlace_type; - FILE *fp; - - if ((fp = fopen(file_name, "rb")) == NULL) - return (ERROR); -#else no_open_file /* prototype 2 */ -void read_png(FILE *fp, unsigned int sig_read) /* file is already open */ -{ - png_structp png_ptr; - png_infop info_ptr; - png_uint_32 width, height; - int bit_depth, color_type, interlace_type; -#endif no_open_file /* only use one prototype! */ - - /* Create and initialize the png_struct with the desired error handler - * functions. If you want to use the default stderr and longjump method, - * you can supply NULL for the last three parameters. We also supply the - * the compiler header file version, so that we know if the application - * was compiled with a compatible version of the library. REQUIRED - */ - png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, - png_voidp user_error_ptr, user_error_fn, user_warning_fn); - - if (png_ptr == NULL) - { - fclose(fp); - return (ERROR); - } - - /* Allocate/initialize the memory for image information. REQUIRED. */ - info_ptr = png_create_info_struct(png_ptr); - if (info_ptr == NULL) - { - fclose(fp); - png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL); - return (ERROR); - } - - /* Set error handling if you are using the setjmp/longjmp method (this is - * the normal method of doing things with libpng). REQUIRED unless you - * set up your own error handlers in the png_create_read_struct() earlier. - */ - - if (setjmp(png_jmpbuf(png_ptr))) - { - /* Free all of the memory associated with the png_ptr and info_ptr */ - png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); - fclose(fp); - /* If we get here, we had a problem reading the file */ - return (ERROR); - } - - /* One of the following I/O initialization methods is REQUIRED */ -#ifdef streams /* PNG file I/O method 1 */ - /* Set up the input control if you are using standard C streams */ - png_init_io(png_ptr, fp); - -#else no_streams /* PNG file I/O method 2 */ - /* If you are using replacement read functions, instead of calling - * png_init_io() here you would call: - */ - png_set_read_fn(png_ptr, (void *)user_io_ptr, user_read_fn); - /* where user_io_ptr is a structure you want available to the callbacks */ -#endif no_streams /* Use only one I/O method! */ - - /* If we have already read some of the signature */ - png_set_sig_bytes(png_ptr, sig_read); - -#ifdef hilevel - /* - * If you have enough memory to read in the entire image at once, - * and you need to specify only transforms that can be controlled - * with one of the PNG_TRANSFORM_* bits (this presently excludes - * dithering, filling, setting background, and doing gamma - * adjustment), then you can read the entire image (including - * pixels) into the info structure with this call: - */ - png_read_png(png_ptr, info_ptr, png_transforms, png_voidp_NULL); -#else - /* OK, you're doing it the hard way, with the lower-level functions */ - - /* The call to png_read_info() gives us all of the information from the - * PNG file before the first IDAT (image data chunk). REQUIRED - */ - png_read_info(png_ptr, info_ptr); - - png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, - &interlace_type, int_p_NULL, int_p_NULL); - -/* Set up the data transformations you want. Note that these are all - * optional. Only call them if you want/need them. Many of the - * transformations only work on specific types of images, and many - * are mutually exclusive. - */ - - /* tell libpng to strip 16 bit/color files down to 8 bits/color */ - png_set_strip_16(png_ptr); - - /* Strip alpha bytes from the input data without combining with the - * background (not recommended). - */ - png_set_strip_alpha(png_ptr); - - /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single - * byte into separate bytes (useful for paletted and grayscale images). - */ - png_set_packing(png_ptr); - - /* Change the order of packed pixels to least significant bit first - * (not useful if you are using png_set_packing). */ - png_set_packswap(png_ptr); - - /* Expand paletted colors into true RGB triplets */ - if (color_type == PNG_COLOR_TYPE_PALETTE) - png_set_palette_to_rgb(png_ptr); - - /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */ - if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) - png_set_gray_1_2_4_to_8(png_ptr); - - /* Expand paletted or RGB images with transparency to full alpha channels - * so the data will be available as RGBA quartets. - */ - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) - png_set_tRNS_to_alpha(png_ptr); - - /* Set the background color to draw transparent and alpha images over. - * It is possible to set the red, green, and blue components directly - * for paletted images instead of supplying a palette index. Note that - * even if the PNG file supplies a background, you are not required to - * use it - you should use the (solid) application background if it has one. - */ - - png_color_16 my_background, *image_background; - - if (png_get_bKGD(png_ptr, info_ptr, &image_background)) - png_set_background(png_ptr, image_background, - PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); - else - png_set_background(png_ptr, &my_background, - PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); - - /* Some suggestions as to how to get a screen gamma value */ - - /* Note that screen gamma is the display_exponent, which includes - * the CRT_exponent and any correction for viewing conditions */ - if (/* We have a user-defined screen gamma value */) - { - screen_gamma = user-defined screen_gamma; - } - /* This is one way that applications share the same screen gamma value */ - else if ((gamma_str = getenv("SCREEN_GAMMA")) != NULL) - { - screen_gamma = atof(gamma_str); - } - /* If we don't have another value */ - else - { - screen_gamma = 2.2; /* A good guess for a PC monitors in a dimly - lit room */ - screen_gamma = 1.7 or 1.0; /* A good guess for Mac systems */ - } - - /* Tell libpng to handle the gamma conversion for you. The final call - * is a good guess for PC generated images, but it should be configurable - * by the user at run time by the user. It is strongly suggested that - * your application support gamma correction. - */ - - int intent; - - if (png_get_sRGB(png_ptr, info_ptr, &intent)) - png_set_gamma(png_ptr, screen_gamma, 0.45455); - else - { - double image_gamma; - if (png_get_gAMA(png_ptr, info_ptr, &image_gamma)) - png_set_gamma(png_ptr, screen_gamma, image_gamma); - else - png_set_gamma(png_ptr, screen_gamma, 0.45455); - } - - /* Dither RGB files down to 8 bit palette or reduce palettes - * to the number of colors available on your screen. - */ - if (color_type & PNG_COLOR_MASK_COLOR) - { - int num_palette; - png_colorp palette; - - /* This reduces the image to the application supplied palette */ - if (/* we have our own palette */) - { - /* An array of colors to which the image should be dithered */ - png_color std_color_cube[MAX_SCREEN_COLORS]; - - png_set_dither(png_ptr, std_color_cube, MAX_SCREEN_COLORS, - MAX_SCREEN_COLORS, png_uint_16p_NULL, 0); - } - /* This reduces the image to the palette supplied in the file */ - else if (png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette)) - { - png_uint_16p histogram = NULL; - - png_get_hIST(png_ptr, info_ptr, &histogram); - - png_set_dither(png_ptr, palette, num_palette, - max_screen_colors, histogram, 0); - } - } - - /* invert monochrome files to have 0 as white and 1 as black */ - png_set_invert_mono(png_ptr); - - /* If you want to shift the pixel values from the range [0,255] or - * [0,65535] to the original [0,7] or [0,31], or whatever range the - * colors were originally in: - */ - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT)) - { - png_color_8p sig_bit; - - png_get_sBIT(png_ptr, info_ptr, &sig_bit); - png_set_shift(png_ptr, sig_bit); - } - - /* flip the RGB pixels to BGR (or RGBA to BGRA) */ - if (color_type & PNG_COLOR_MASK_COLOR) - png_set_bgr(png_ptr); - - /* swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */ - png_set_swap_alpha(png_ptr); - - /* swap bytes of 16 bit files to least significant byte first */ - png_set_swap(png_ptr); - - /* Add filler (or alpha) byte (before/after each RGB triplet) */ - png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); - - /* Turn on interlace handling. REQUIRED if you are not using - * png_read_image(). To see how to handle interlacing passes, - * see the png_read_row() method below: - */ - number_passes = png_set_interlace_handling(png_ptr); - - /* Optional call to gamma correct and add the background to the palette - * and update info structure. REQUIRED if you are expecting libpng to - * update the palette for you (ie you selected such a transform above). - */ - png_read_update_info(png_ptr, info_ptr); - - /* Allocate the memory to hold the image using the fields of info_ptr. */ - - /* The easiest way to read the image: */ - png_bytep row_pointers[height]; - - for (row = 0; row < height; row++) - { - row_pointers[row] = png_malloc(png_ptr, png_get_rowbytes(png_ptr, - info_ptr)); - } - - /* Now it's time to read the image. One of these methods is REQUIRED */ -#ifdef entire /* Read the entire image in one go */ - png_read_image(png_ptr, row_pointers); - -#else no_entire /* Read the image one or more scanlines at a time */ - /* The other way to read images - deal with interlacing: */ - - for (pass = 0; pass < number_passes; pass++) - { -#ifdef single /* Read the image a single row at a time */ - for (y = 0; y < height; y++) - { - png_read_rows(png_ptr, &row_pointers[y], png_bytepp_NULL, 1); - } - -#else no_single /* Read the image several rows at a time */ - for (y = 0; y < height; y += number_of_rows) - { -#ifdef sparkle /* Read the image using the "sparkle" effect. */ - png_read_rows(png_ptr, &row_pointers[y], png_bytepp_NULL, - number_of_rows); -#else no_sparkle /* Read the image using the "rectangle" effect */ - png_read_rows(png_ptr, png_bytepp_NULL, &row_pointers[y], - number_of_rows); -#endif no_sparkle /* use only one of these two methods */ - } - - /* if you want to display the image after every pass, do - so here */ -#endif no_single /* use only one of these two methods */ - } -#endif no_entire /* use only one of these two methods */ - - /* read rest of file, and get additional chunks in info_ptr - REQUIRED */ - png_read_end(png_ptr, info_ptr); -#endif hilevel - - /* At this point you have read the entire image */ - - /* clean up after the read, and free any memory allocated - REQUIRED */ - png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); - - /* close the file */ - fclose(fp); - - /* that's it */ - return (OK); -} - -/* progressively read a file */ - -int -initialize_png_reader(png_structp *png_ptr, png_infop *info_ptr) -{ - /* Create and initialize the png_struct with the desired error handler - * functions. If you want to use the default stderr and longjump method, - * you can supply NULL for the last three parameters. We also check that - * the library version is compatible in case we are using dynamically - * linked libraries. - */ - *png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, - png_voidp user_error_ptr, user_error_fn, user_warning_fn); - - if (*png_ptr == NULL) - { - *info_ptr = NULL; - return (ERROR); - } - - *info_ptr = png_create_info_struct(png_ptr); - - if (*info_ptr == NULL) - { - png_destroy_read_struct(png_ptr, info_ptr, png_infopp_NULL); - return (ERROR); - } - - if (setjmp(png_jmpbuf((*png_ptr)))) - { - png_destroy_read_struct(png_ptr, info_ptr, png_infopp_NULL); - return (ERROR); - } - - /* This one's new. You will need to provide all three - * function callbacks, even if you aren't using them all. - * If you aren't using all functions, you can specify NULL - * parameters. Even when all three functions are NULL, - * you need to call png_set_progressive_read_fn(). - * These functions shouldn't be dependent on global or - * static variables if you are decoding several images - * simultaneously. You should store stream specific data - * in a separate struct, given as the second parameter, - * and retrieve the pointer from inside the callbacks using - * the function png_get_progressive_ptr(png_ptr). - */ - png_set_progressive_read_fn(*png_ptr, (void *)stream_data, - info_callback, row_callback, end_callback); - - return (OK); -} - -int -process_data(png_structp *png_ptr, png_infop *info_ptr, - png_bytep buffer, png_uint_32 length) -{ - if (setjmp(png_jmpbuf((*png_ptr)))) - { - /* Free the png_ptr and info_ptr memory on error */ - png_destroy_read_struct(png_ptr, info_ptr, png_infopp_NULL); - return (ERROR); - } - - /* This one's new also. Simply give it chunks of data as - * they arrive from the data stream (in order, of course). - * On Segmented machines, don't give it any more than 64K. - * The library seems to run fine with sizes of 4K, although - * you can give it much less if necessary (I assume you can - * give it chunks of 1 byte, but I haven't tried with less - * than 256 bytes yet). When this function returns, you may - * want to display any rows that were generated in the row - * callback, if you aren't already displaying them there. - */ - png_process_data(*png_ptr, *info_ptr, buffer, length); - return (OK); -} - -info_callback(png_structp png_ptr, png_infop info) -{ -/* do any setup here, including setting any of the transformations - * mentioned in the Reading PNG files section. For now, you _must_ - * call either png_start_read_image() or png_read_update_info() - * after all the transformations are set (even if you don't set - * any). You may start getting rows before png_process_data() - * returns, so this is your last chance to prepare for that. - */ -} - -row_callback(png_structp png_ptr, png_bytep new_row, - png_uint_32 row_num, int pass) -{ -/* - * This function is called for every row in the image. If the - * image is interlaced, and you turned on the interlace handler, - * this function will be called for every row in every pass. - * - * In this function you will receive a pointer to new row data from - * libpng called new_row that is to replace a corresponding row (of - * the same data format) in a buffer allocated by your application. - * - * The new row data pointer new_row may be NULL, indicating there is - * no new data to be replaced (in cases of interlace loading). - * - * If new_row is not NULL then you need to call - * png_progressive_combine_row() to replace the corresponding row as - * shown below: - */ - /* Check if row_num is in bounds. */ - if((row_num >= 0) && (row_num < height)) - { - /* Get pointer to corresponding row in our - * PNG read buffer. - */ - png_bytep old_row = ((png_bytep *)our_data)[row_num]; - - /* If both rows are allocated then copy the new row - * data to the corresponding row data. - */ - if((old_row != NULL) && (new_row != NULL)) - png_progressive_combine_row(png_ptr, old_row, new_row); - } -/* - * The rows and passes are called in order, so you don't really - * need the row_num and pass, but I'm supplying them because it - * may make your life easier. - * - * For the non-NULL rows of interlaced images, you must call - * png_progressive_combine_row() passing in the new row and the - * old row, as demonstrated above. You can call this function for - * NULL rows (it will just return) and for non-interlaced images - * (it just does the png_memcpy for you) if it will make the code - * easier. Thus, you can just do this for all cases: - */ - - png_progressive_combine_row(png_ptr, old_row, new_row); - -/* where old_row is what was displayed for previous rows. Note - * that the first pass (pass == 0 really) will completely cover - * the old row, so the rows do not have to be initialized. After - * the first pass (and only for interlaced images), you will have - * to pass the current row as new_row, and the function will combine - * the old row and the new row. - */ -} - -end_callback(png_structp png_ptr, png_infop info) -{ -/* this function is called when the whole image has been read, - * including any chunks after the image (up to and including - * the IEND). You will usually have the same info chunk as you - * had in the header, although some data may have been added - * to the comments and time fields. - * - * Most people won't do much here, perhaps setting a flag that - * marks the image as finished. - */ -} - -/* write a png file */ -void write_png(char *file_name /* , ... other image information ... */) -{ - FILE *fp; - png_structp png_ptr; - png_infop info_ptr; - png_colorp palette; - - /* open the file */ - fp = fopen(file_name, "wb"); - if (fp == NULL) - return (ERROR); - - /* Create and initialize the png_struct with the desired error handler - * functions. If you want to use the default stderr and longjump method, - * you can supply NULL for the last three parameters. We also check that - * the library version is compatible with the one used at compile time, - * in case we are using dynamically linked libraries. REQUIRED. - */ - png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, - png_voidp user_error_ptr, user_error_fn, user_warning_fn); - - if (png_ptr == NULL) - { - fclose(fp); - return (ERROR); - } - - /* Allocate/initialize the image information data. REQUIRED */ - info_ptr = png_create_info_struct(png_ptr); - if (info_ptr == NULL) - { - fclose(fp); - png_destroy_write_struct(&png_ptr, png_infopp_NULL); - return (ERROR); - } - - /* Set error handling. REQUIRED if you aren't supplying your own - * error handling functions in the png_create_write_struct() call. - */ - if (setjmp(png_jmpbuf(png_ptr))) - { - /* If we get here, we had a problem reading the file */ - fclose(fp); - png_destroy_write_struct(&png_ptr, &info_ptr); - return (ERROR); - } - - /* One of the following I/O initialization functions is REQUIRED */ -#ifdef streams /* I/O initialization method 1 */ - /* set up the output control if you are using standard C streams */ - png_init_io(png_ptr, fp); -#else no_streams /* I/O initialization method 2 */ - /* If you are using replacement read functions, instead of calling - * png_init_io() here you would call */ - png_set_write_fn(png_ptr, (void *)user_io_ptr, user_write_fn, - user_IO_flush_function); - /* where user_io_ptr is a structure you want available to the callbacks */ -#endif no_streams /* only use one initialization method */ - -#ifdef hilevel - /* This is the easy way. Use it if you already have all the - * image info living info in the structure. You could "|" many - * PNG_TRANSFORM flags into the png_transforms integer here. - */ - png_write_png(png_ptr, info_ptr, png_transforms, png_voidp_NULL); -#else - /* This is the hard way */ - - /* Set the image information here. Width and height are up to 2^31, - * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on - * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY, - * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB, - * or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or - * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST - * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED - */ - png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, PNG_COLOR_TYPE_???, - PNG_INTERLACE_????, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); - - /* set the palette if there is one. REQUIRED for indexed-color images */ - palette = (png_colorp)png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH - * png_sizeof (png_color)); - /* ... set palette colors ... */ - png_set_PLTE(png_ptr, info_ptr, palette, PNG_MAX_PALETTE_LENGTH); - /* You must not free palette here, because png_set_PLTE only makes a link to - the palette that you malloced. Wait until you are about to destroy - the png structure. */ - - /* optional significant bit chunk */ - /* if we are dealing with a grayscale image then */ - sig_bit.gray = true_bit_depth; - /* otherwise, if we are dealing with a color image then */ - sig_bit.red = true_red_bit_depth; - sig_bit.green = true_green_bit_depth; - sig_bit.blue = true_blue_bit_depth; - /* if the image has an alpha channel then */ - sig_bit.alpha = true_alpha_bit_depth; - png_set_sBIT(png_ptr, info_ptr, sig_bit); - - - /* Optional gamma chunk is strongly suggested if you have any guess - * as to the correct gamma of the image. - */ - png_set_gAMA(png_ptr, info_ptr, gamma); - - /* Optionally write comments into the image */ - text_ptr[0].key = "Title"; - text_ptr[0].text = "Mona Lisa"; - text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE; - text_ptr[1].key = "Author"; - text_ptr[1].text = "Leonardo DaVinci"; - text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE; - text_ptr[2].key = "Description"; - text_ptr[2].text = ""; - text_ptr[2].compression = PNG_TEXT_COMPRESSION_zTXt; -#ifdef PNG_iTXt_SUPPORTED - text_ptr[0].lang = NULL; - text_ptr[1].lang = NULL; - text_ptr[2].lang = NULL; -#endif - png_set_text(png_ptr, info_ptr, text_ptr, 3); - - /* other optional chunks like cHRM, bKGD, tRNS, tIME, oFFs, pHYs, */ - /* note that if sRGB is present the gAMA and cHRM chunks must be ignored - * on read and must be written in accordance with the sRGB profile */ - - /* Write the file header information. REQUIRED */ - png_write_info(png_ptr, info_ptr); - - /* If you want, you can write the info in two steps, in case you need to - * write your private chunk ahead of PLTE: - * - * png_write_info_before_PLTE(write_ptr, write_info_ptr); - * write_my_chunk(); - * png_write_info(png_ptr, info_ptr); - * - * However, given the level of known- and unknown-chunk support in 1.1.0 - * and up, this should no longer be necessary. - */ - - /* Once we write out the header, the compression type on the text - * chunks gets changed to PNG_TEXT_COMPRESSION_NONE_WR or - * PNG_TEXT_COMPRESSION_zTXt_WR, so it doesn't get written out again - * at the end. - */ - - /* set up the transformations you want. Note that these are - * all optional. Only call them if you want them. - */ - - /* invert monochrome pixels */ - png_set_invert_mono(png_ptr); - - /* Shift the pixels up to a legal bit depth and fill in - * as appropriate to correctly scale the image. - */ - png_set_shift(png_ptr, &sig_bit); - - /* pack pixels into bytes */ - png_set_packing(png_ptr); - - /* swap location of alpha bytes from ARGB to RGBA */ - png_set_swap_alpha(png_ptr); - - /* Get rid of filler (OR ALPHA) bytes, pack XRGB/RGBX/ARGB/RGBA into - * RGB (4 channels -> 3 channels). The second parameter is not used. - */ - png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); - - /* flip BGR pixels to RGB */ - png_set_bgr(png_ptr); - - /* swap bytes of 16-bit files to most significant byte first */ - png_set_swap(png_ptr); - - /* swap bits of 1, 2, 4 bit packed pixel formats */ - png_set_packswap(png_ptr); - - /* turn on interlace handling if you are not using png_write_image() */ - if (interlacing) - number_passes = png_set_interlace_handling(png_ptr); - else - number_passes = 1; - - /* The easiest way to write the image (you may have a different memory - * layout, however, so choose what fits your needs best). You need to - * use the first method if you aren't handling interlacing yourself. - */ - png_uint_32 k, height, width; - png_byte image[height][width*bytes_per_pixel]; - png_bytep row_pointers[height]; - - if (height > PNG_UINT_32_MAX/png_sizeof(png_bytep)) - png_error (png_ptr, "Image is too tall to process in memory"); - - for (k = 0; k < height; k++) - row_pointers[k] = image + k*width*bytes_per_pixel; - - /* One of the following output methods is REQUIRED */ -#ifdef entire /* write out the entire image data in one call */ - png_write_image(png_ptr, row_pointers); - - /* the other way to write the image - deal with interlacing */ - -#else no_entire /* write out the image data by one or more scanlines */ - /* The number of passes is either 1 for non-interlaced images, - * or 7 for interlaced images. - */ - for (pass = 0; pass < number_passes; pass++) - { - /* Write a few rows at a time. */ - png_write_rows(png_ptr, &row_pointers[first_row], number_of_rows); - - /* If you are only writing one row at a time, this works */ - for (y = 0; y < height; y++) - { - png_write_rows(png_ptr, &row_pointers[y], 1); - } - } -#endif no_entire /* use only one output method */ - - /* You can write optional chunks like tEXt, zTXt, and tIME at the end - * as well. Shouldn't be necessary in 1.1.0 and up as all the public - * chunks are supported and you can use png_set_unknown_chunks() to - * register unknown chunks into the info structure to be written out. - */ - - /* It is REQUIRED to call this to finish writing the rest of the file */ - png_write_end(png_ptr, info_ptr); -#endif hilevel - - /* If you png_malloced a palette, free it here (don't free info_ptr->palette, - as recommended in versions 1.0.5m and earlier of this example; if - libpng mallocs info_ptr->palette, libpng will free it). If you - allocated it with malloc() instead of png_malloc(), use free() instead - of png_free(). */ - png_free(png_ptr, palette); - palette=NULL; - - /* Similarly, if you png_malloced any data that you passed in with - png_set_something(), such as a hist or trans array, free it here, - when you can be sure that libpng is through with it. */ - png_free(png_ptr, trans); - trans=NULL; - - /* clean up after the write, and free any memory allocated */ - png_destroy_write_struct(&png_ptr, &info_ptr); - - /* close the file */ - fclose(fp); - - /* that's it */ - return (OK); -} - -#endif /* if 0 */ diff --git a/rosapps/lib/libpng/docs/libpng-1.2.24.txt b/rosapps/lib/libpng/docs/libpng-1.2.24.txt deleted file mode 100644 index 5b8dc53b970..00000000000 --- a/rosapps/lib/libpng/docs/libpng-1.2.24.txt +++ /dev/null @@ -1,2851 +0,0 @@ -libpng.txt - A description on how to use and modify libpng - - libpng version 1.2.24 - December 14, 2007 - Updated and distributed by Glenn Randers-Pehrson - - Copyright (c) 1998-2007 Glenn Randers-Pehrson - For conditions of distribution and use, see copyright - notice in png.h. - - based on: - - libpng 1.0 beta 6 version 0.96 May 28, 1997 - Updated and distributed by Andreas Dilger - Copyright (c) 1996, 1997 Andreas Dilger - - libpng 1.0 beta 2 - version 0.88 January 26, 1996 - For conditions of distribution and use, see copyright - notice in png.h. Copyright (c) 1995, 1996 Guy Eric - Schalnat, Group 42, Inc. - - Updated/rewritten per request in the libpng FAQ - Copyright (c) 1995, 1996 Frank J. T. Wojcik - December 18, 1995 & January 20, 1996 - -I. Introduction - -This file describes how to use and modify the PNG reference library -(known as libpng) for your own use. There are five sections to this -file: introduction, structures, reading, writing, and modification and -configuration notes for various special platforms. In addition to this -file, example.c is a good starting point for using the library, as -it is heavily commented and should include everything most people -will need. We assume that libpng is already installed; see the -INSTALL file for instructions on how to install libpng. - -For examples of libpng usage, see the files "example.c", "pngtest.c", -and the files in the "contrib" directory, all of which are included in the -libpng distribution. - -Libpng was written as a companion to the PNG specification, as a way -of reducing the amount of time and effort it takes to support the PNG -file format in application programs. - -The PNG specification (second edition), November 2003, is available as -a W3C Recommendation and as an ISO Standard (ISO/IEC 15948:2003 (E)) at - - -The PNG-1.0 specification is available -as RFC 2083 and as a -W3C Recommendation . Some -additional chunks are described in the special-purpose public chunks -documents at . - -Other information -about PNG, and the latest version of libpng, can be found at the PNG home -page, . - -Most users will not have to modify the library significantly; advanced -users may want to modify it more. All attempts were made to make it as -complete as possible, while keeping the code easy to understand. -Currently, this library only supports C. Support for other languages -is being considered. - -Libpng has been designed to handle multiple sessions at one time, -to be easily modifiable, to be portable to the vast majority of -machines (ANSI, K&R, 16-, 32-, and 64-bit) available, and to be easy -to use. The ultimate goal of libpng is to promote the acceptance of -the PNG file format in whatever way possible. While there is still -work to be done (see the TODO file), libpng should cover the -majority of the needs of its users. - -Libpng uses zlib for its compression and decompression of PNG files. -Further information about zlib, and the latest version of zlib, can -be found at the zlib home page, . -The zlib compression utility is a general purpose utility that is -useful for more than PNG files, and can be used without libpng. -See the documentation delivered with zlib for more details. -You can usually find the source files for the zlib utility wherever you -find the libpng source files. - -Libpng is thread safe, provided the threads are using different -instances of the structures. Each thread should have its own -png_struct and png_info instances, and thus its own image. -Libpng does not protect itself against two threads using the -same instance of a structure. - -II. Structures - -There are two main structures that are important to libpng, png_struct -and png_info. The first, png_struct, is an internal structure that -will not, for the most part, be used by a user except as the first -variable passed to every libpng function call. - -The png_info structure is designed to provide information about the -PNG file. At one time, the fields of png_info were intended to be -directly accessible to the user. However, this tended to cause problems -with applications using dynamically loaded libraries, and as a result -a set of interface functions for png_info (the png_get_*() and png_set_*() -functions) was developed. The fields of png_info are still available for -older applications, but it is suggested that applications use the new -interfaces if at all possible. - -Applications that do make direct access to the members of png_struct (except -for png_ptr->jmpbuf) must be recompiled whenever the library is updated, -and applications that make direct access to the members of png_info must -be recompiled if they were compiled or loaded with libpng version 1.0.6, -in which the members were in a different order. In version 1.0.7, the -members of the png_info structure reverted to the old order, as they were -in versions 0.97c through 1.0.5. Starting with version 2.0.0, both -structures are going to be hidden, and the contents of the structures will -only be accessible through the png_get/png_set functions. - -The png.h header file is an invaluable reference for programming with libpng. -And while I'm on the topic, make sure you include the libpng header file: - -#include - -III. Reading - -We'll now walk you through the possible functions to call when reading -in a PNG file sequentially, briefly explaining the syntax and purpose -of each one. See example.c and png.h for more detail. While -progressive reading is covered in the next section, you will still -need some of the functions discussed in this section to read a PNG -file. - -Setup - -You will want to do the I/O initialization(*) before you get into libpng, -so if it doesn't work, you don't have much to undo. Of course, you -will also want to insure that you are, in fact, dealing with a PNG -file. Libpng provides a simple check to see if a file is a PNG file. -To use it, pass in the first 1 to 8 bytes of the file to the function -png_sig_cmp(), and it will return 0 if the bytes match the corresponding -bytes of the PNG signature, or nonzero otherwise. Of course, the more bytes -you pass in, the greater the accuracy of the prediction. - -If you are intending to keep the file pointer open for use in libpng, -you must ensure you don't read more than 8 bytes from the beginning -of the file, and you also have to make a call to png_set_sig_bytes_read() -with the number of bytes you read from the beginning. Libpng will -then only check the bytes (if any) that your program didn't read. - -(*): If you are not using the standard I/O functions, you will need -to replace them with custom functions. See the discussion under -Customizing libpng. - - - FILE *fp = fopen(file_name, "rb"); - if (!fp) - { - return (ERROR); - } - fread(header, 1, number, fp); - is_png = !png_sig_cmp(header, 0, number); - if (!is_png) - { - return (NOT_PNG); - } - - -Next, png_struct and png_info need to be allocated and initialized. In -order to ensure that the size of these structures is correct even with a -dynamically linked libpng, there are functions to initialize and -allocate the structures. We also pass the library version, optional -pointers to error handling functions, and a pointer to a data struct for -use by the error functions, if necessary (the pointer and functions can -be NULL if the default error handlers are to be used). See the section -on Changes to Libpng below regarding the old initialization functions. -The structure allocation functions quietly return NULL if they fail to -create the structure, so your application should check for that. - - png_structp png_ptr = png_create_read_struct - (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, - user_error_fn, user_warning_fn); - if (!png_ptr) - return (ERROR); - - png_infop info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) - { - png_destroy_read_struct(&png_ptr, - (png_infopp)NULL, (png_infopp)NULL); - return (ERROR); - } - - png_infop end_info = png_create_info_struct(png_ptr); - if (!end_info) - { - png_destroy_read_struct(&png_ptr, &info_ptr, - (png_infopp)NULL); - return (ERROR); - } - -If you want to use your own memory allocation routines, -define PNG_USER_MEM_SUPPORTED and use -png_create_read_struct_2() instead of png_create_read_struct(): - - png_structp png_ptr = png_create_read_struct_2 - (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, - user_error_fn, user_warning_fn, (png_voidp) - user_mem_ptr, user_malloc_fn, user_free_fn); - -The error handling routines passed to png_create_read_struct() -and the memory alloc/free routines passed to png_create_struct_2() -are only necessary if you are not using the libpng supplied error -handling and memory alloc/free functions. - -When libpng encounters an error, it expects to longjmp back -to your routine. Therefore, you will need to call setjmp and pass -your png_jmpbuf(png_ptr). If you read the file from different -routines, you will need to update the jmpbuf field every time you enter -a new routine that will call a png_*() function. - -See your documentation of setjmp/longjmp for your compiler for more -information on setjmp/longjmp. See the discussion on libpng error -handling in the Customizing Libpng section below for more information -on the libpng error handling. If an error occurs, and libpng longjmp's -back to your setjmp, you will want to call png_destroy_read_struct() to -free any memory. - - if (setjmp(png_jmpbuf(png_ptr))) - { - png_destroy_read_struct(&png_ptr, &info_ptr, - &end_info); - fclose(fp); - return (ERROR); - } - -If you would rather avoid the complexity of setjmp/longjmp issues, -you can compile libpng with PNG_SETJMP_NOT_SUPPORTED, in which case -errors will result in a call to PNG_ABORT() which defaults to abort(). - -Now you need to set up the input code. The default for libpng is to -use the C function fread(). If you use this, you will need to pass a -valid FILE * in the function png_init_io(). Be sure that the file is -opened in binary mode. If you wish to handle reading data in another -way, you need not call the png_init_io() function, but you must then -implement the libpng I/O methods discussed in the Customizing Libpng -section below. - - png_init_io(png_ptr, fp); - -If you had previously opened the file and read any of the signature from -the beginning in order to see if this was a PNG file, you need to let -libpng know that there are some bytes missing from the start of the file. - - png_set_sig_bytes(png_ptr, number); - -Setting up callback code - -You can set up a callback function to handle any unknown chunks in the -input stream. You must supply the function - - read_chunk_callback(png_ptr ptr, - png_unknown_chunkp chunk); - { - /* The unknown chunk structure contains your - chunk data: */ - png_byte name[5]; - png_byte *data; - png_size_t size; - /* Note that libpng has already taken care of - the CRC handling */ - - /* put your code here. Return one of the - following: */ - - return (-n); /* chunk had an error */ - return (0); /* did not recognize */ - return (n); /* success */ - } - -(You can give your function another name that you like instead of -"read_chunk_callback") - -To inform libpng about your function, use - - png_set_read_user_chunk_fn(png_ptr, user_chunk_ptr, - read_chunk_callback); - -This names not only the callback function, but also a user pointer that -you can retrieve with - - png_get_user_chunk_ptr(png_ptr); - -At this point, you can set up a callback function that will be -called after each row has been read, which you can use to control -a progress meter or the like. It's demonstrated in pngtest.c. -You must supply a function - - void read_row_callback(png_ptr ptr, png_uint_32 row, - int pass); - { - /* put your code here */ - } - -(You can give it another name that you like instead of "read_row_callback") - -To inform libpng about your function, use - - png_set_read_status_fn(png_ptr, read_row_callback); - -Width and height limits - -The PNG specification allows the width and height of an image to be as -large as 2^31-1 (0x7fffffff), or about 2.147 billion rows and columns. -Since very few applications really need to process such large images, -we have imposed an arbitrary 1-million limit on rows and columns. -Larger images will be rejected immediately with a png_error() call. If -you wish to override this limit, you can use - - png_set_user_limits(png_ptr, width_max, height_max); - -to set your own limits, or use width_max = height_max = 0x7fffffffL -to allow all valid dimensions (libpng may reject some very large images -anyway because of potential buffer overflow conditions). - -You should put this statement after you create the PNG structure and -before calling png_read_info(), png_read_png(), or png_process_data(). -If you need to retrieve the limits that are being applied, use - - width_max = png_get_user_width_max(png_ptr); - height_max = png_get_user_height_max(png_ptr); - -Unknown-chunk handling - -Now you get to set the way the library processes unknown chunks in the -input PNG stream. Both known and unknown chunks will be read. Normal -behavior is that known chunks will be parsed into information in -various info_ptr members; unknown chunks will be discarded. To change -this, you can call: - - png_set_keep_unknown_chunks(png_ptr, keep, - chunk_list, num_chunks); - keep - 0: do not handle as unknown - 1: do not keep - 2: keep only if safe-to-copy - 3: keep even if unsafe-to-copy - You can use these definitions: - PNG_HANDLE_CHUNK_AS_DEFAULT 0 - PNG_HANDLE_CHUNK_NEVER 1 - PNG_HANDLE_CHUNK_IF_SAFE 2 - PNG_HANDLE_CHUNK_ALWAYS 3 - chunk_list - list of chunks affected (a byte string, - five bytes per chunk, NULL or '\0' if - num_chunks is 0) - num_chunks - number of chunks affected; if 0, all - unknown chunks are affected. If nonzero, - only the chunks in the list are affected - -Unknown chunks declared in this way will be saved as raw data onto a -list of png_unknown_chunk structures. If a chunk that is normally -known to libpng is named in the list, it will be handled as unknown, -according to the "keep" directive. If a chunk is named in successive -instances of png_set_keep_unknown_chunks(), the final instance will -take precedence. The IHDR and IEND chunks should not be named in -chunk_list; if they are, libpng will process them normally anyway. - -The high-level read interface - -At this point there are two ways to proceed; through the high-level -read interface, or through a sequence of low-level read operations. -You can use the high-level interface if (a) you are willing to read -the entire image into memory, and (b) the input transformations -you want to do are limited to the following set: - - PNG_TRANSFORM_IDENTITY No transformation - PNG_TRANSFORM_STRIP_16 Strip 16-bit samples to - 8 bits - PNG_TRANSFORM_STRIP_ALPHA Discard the alpha channel - PNG_TRANSFORM_PACKING Expand 1, 2 and 4-bit - samples to bytes - PNG_TRANSFORM_PACKSWAP Change order of packed - pixels to LSB first - PNG_TRANSFORM_EXPAND Perform set_expand() - PNG_TRANSFORM_INVERT_MONO Invert monochrome images - PNG_TRANSFORM_SHIFT Normalize pixels to the - sBIT depth - PNG_TRANSFORM_BGR Flip RGB to BGR, RGBA - to BGRA - PNG_TRANSFORM_SWAP_ALPHA Flip RGBA to ARGB or GA - to AG - PNG_TRANSFORM_INVERT_ALPHA Change alpha from opacity - to transparency - PNG_TRANSFORM_SWAP_ENDIAN Byte-swap 16-bit samples - -(This excludes setting a background color, doing gamma transformation, -dithering, and setting filler.) If this is the case, simply do this: - - png_read_png(png_ptr, info_ptr, png_transforms, NULL) - -where png_transforms is an integer containing the bitwise OR of -some set of transformation flags. This call is equivalent to png_read_info(), -followed the set of transformations indicated by the transform mask, -then png_read_image(), and finally png_read_end(). - -(The final parameter of this call is not yet used. Someday it might point -to transformation parameters required by some future input transform.) - -You must use png_transforms and not call any png_set_transform() functions -when you use png_read_png(). - -After you have called png_read_png(), you can retrieve the image data -with - - row_pointers = png_get_rows(png_ptr, info_ptr); - -where row_pointers is an array of pointers to the pixel data for each row: - - png_bytep row_pointers[height]; - -If you know your image size and pixel size ahead of time, you can allocate -row_pointers prior to calling png_read_png() with - - if (height > PNG_UINT_32_MAX/png_sizeof(png_byte)) - png_error (png_ptr, - "Image is too tall to process in memory"); - if (width > PNG_UINT_32_MAX/pixel_size) - png_error (png_ptr, - "Image is too wide to process in memory"); - row_pointers = png_malloc(png_ptr, - height*png_sizeof(png_bytep)); - for (int i=0; i) and -png_get_(png_ptr, info_ptr, ...) functions return non-zero if the -data has been read, or zero if it is missing. The parameters to the -png_get_ are set directly if they are simple data types, or a pointer -into the info_ptr is returned for any complex types. - - png_get_PLTE(png_ptr, info_ptr, &palette, - &num_palette); - palette - the palette for the file - (array of png_color) - num_palette - number of entries in the palette - - png_get_gAMA(png_ptr, info_ptr, &gamma); - gamma - the gamma the file is written - at (PNG_INFO_gAMA) - - png_get_sRGB(png_ptr, info_ptr, &srgb_intent); - srgb_intent - the rendering intent (PNG_INFO_sRGB) - The presence of the sRGB chunk - means that the pixel data is in the - sRGB color space. This chunk also - implies specific values of gAMA and - cHRM. - - png_get_iCCP(png_ptr, info_ptr, &name, - &compression_type, &profile, &proflen); - name - The profile name. - compression - The compression type; always - PNG_COMPRESSION_TYPE_BASE for PNG 1.0. - You may give NULL to this argument to - ignore it. - profile - International Color Consortium color - profile data. May contain NULs. - proflen - length of profile data in bytes. - - png_get_sBIT(png_ptr, info_ptr, &sig_bit); - sig_bit - the number of significant bits for - (PNG_INFO_sBIT) each of the gray, - red, green, and blue channels, - whichever are appropriate for the - given color type (png_color_16) - - png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, - &trans_values); - trans - array of transparent entries for - palette (PNG_INFO_tRNS) - trans_values - graylevel or color sample values of - the single transparent color for - non-paletted images (PNG_INFO_tRNS) - num_trans - number of transparent entries - (PNG_INFO_tRNS) - - png_get_hIST(png_ptr, info_ptr, &hist); - (PNG_INFO_hIST) - hist - histogram of palette (array of - png_uint_16) - - png_get_tIME(png_ptr, info_ptr, &mod_time); - mod_time - time image was last modified - (PNG_VALID_tIME) - - png_get_bKGD(png_ptr, info_ptr, &background); - background - background color (PNG_VALID_bKGD) - valid 16-bit red, green and blue - values, regardless of color_type - - num_comments = png_get_text(png_ptr, info_ptr, - &text_ptr, &num_text); - num_comments - number of comments - text_ptr - array of png_text holding image - comments - text_ptr[i].compression - type of compression used - on "text" PNG_TEXT_COMPRESSION_NONE - PNG_TEXT_COMPRESSION_zTXt - PNG_ITXT_COMPRESSION_NONE - PNG_ITXT_COMPRESSION_zTXt - text_ptr[i].key - keyword for comment. Must contain - 1-79 characters. - text_ptr[i].text - text comments for current - keyword. Can be empty. - text_ptr[i].text_length - length of text string, - after decompression, 0 for iTXt - text_ptr[i].itxt_length - length of itxt string, - after decompression, 0 for tEXt/zTXt - text_ptr[i].lang - language of comment (empty - string for unknown). - text_ptr[i].lang_key - keyword in UTF-8 - (empty string for unknown). - num_text - number of comments (same as - num_comments; you can put NULL here - to avoid the duplication) - Note while png_set_text() will accept text, language, - and translated keywords that can be NULL pointers, the - structure returned by png_get_text will always contain - regular zero-terminated C strings. They might be - empty strings but they will never be NULL pointers. - - num_spalettes = png_get_sPLT(png_ptr, info_ptr, - &palette_ptr); - palette_ptr - array of palette structures holding - contents of one or more sPLT chunks - read. - num_spalettes - number of sPLT chunks read. - - png_get_oFFs(png_ptr, info_ptr, &offset_x, &offset_y, - &unit_type); - offset_x - positive offset from the left edge - of the screen - offset_y - positive offset from the top edge - of the screen - unit_type - PNG_OFFSET_PIXEL, PNG_OFFSET_MICROMETER - - png_get_pHYs(png_ptr, info_ptr, &res_x, &res_y, - &unit_type); - res_x - pixels/unit physical resolution in - x direction - res_y - pixels/unit physical resolution in - x direction - unit_type - PNG_RESOLUTION_UNKNOWN, - PNG_RESOLUTION_METER - - png_get_sCAL(png_ptr, info_ptr, &unit, &width, - &height) - unit - physical scale units (an integer) - width - width of a pixel in physical scale units - height - height of a pixel in physical scale units - (width and height are doubles) - - png_get_sCAL_s(png_ptr, info_ptr, &unit, &width, - &height) - unit - physical scale units (an integer) - width - width of a pixel in physical scale units - height - height of a pixel in physical scale units - (width and height are strings like "2.54") - - num_unknown_chunks = png_get_unknown_chunks(png_ptr, - info_ptr, &unknowns) - unknowns - array of png_unknown_chunk - structures holding unknown chunks - unknowns[i].name - name of unknown chunk - unknowns[i].data - data of unknown chunk - unknowns[i].size - size of unknown chunk's data - unknowns[i].location - position of chunk in file - - The value of "i" corresponds to the order in which the - chunks were read from the PNG file or inserted with the - png_set_unknown_chunks() function. - -The data from the pHYs chunk can be retrieved in several convenient -forms: - - res_x = png_get_x_pixels_per_meter(png_ptr, - info_ptr) - res_y = png_get_y_pixels_per_meter(png_ptr, - info_ptr) - res_x_and_y = png_get_pixels_per_meter(png_ptr, - info_ptr) - res_x = png_get_x_pixels_per_inch(png_ptr, - info_ptr) - res_y = png_get_y_pixels_per_inch(png_ptr, - info_ptr) - res_x_and_y = png_get_pixels_per_inch(png_ptr, - info_ptr) - aspect_ratio = png_get_pixel_aspect_ratio(png_ptr, - info_ptr) - - (Each of these returns 0 [signifying "unknown"] if - the data is not present or if res_x is 0; - res_x_and_y is 0 if res_x != res_y) - -The data from the oFFs chunk can be retrieved in several convenient -forms: - - x_offset = png_get_x_offset_microns(png_ptr, info_ptr); - y_offset = png_get_y_offset_microns(png_ptr, info_ptr); - x_offset = png_get_x_offset_inches(png_ptr, info_ptr); - y_offset = png_get_y_offset_inches(png_ptr, info_ptr); - - (Each of these returns 0 [signifying "unknown" if both - x and y are 0] if the data is not present or if the - chunk is present but the unit is the pixel) - -For more information, see the png_info definition in png.h and the -PNG specification for chunk contents. Be careful with trusting -rowbytes, as some of the transformations could increase the space -needed to hold a row (expand, filler, gray_to_rgb, etc.). -See png_read_update_info(), below. - -A quick word about text_ptr and num_text. PNG stores comments in -keyword/text pairs, one pair per chunk, with no limit on the number -of text chunks, and a 2^31 byte limit on their size. While there are -suggested keywords, there is no requirement to restrict the use to these -strings. It is strongly suggested that keywords and text be sensible -to humans (that's the point), so don't use abbreviations. Non-printing -symbols are not allowed. See the PNG specification for more details. -There is also no requirement to have text after the keyword. - -Keywords should be limited to 79 Latin-1 characters without leading or -trailing spaces, but non-consecutive spaces are allowed within the -keyword. It is possible to have the same keyword any number of times. -The text_ptr is an array of png_text structures, each holding a -pointer to a language string, a pointer to a keyword and a pointer to -a text string. The text string, language code, and translated -keyword may be empty or NULL pointers. The keyword/text -pairs are put into the array in the order that they are received. -However, some or all of the text chunks may be after the image, so, to -make sure you have read all the text chunks, don't mess with these -until after you read the stuff after the image. This will be -mentioned again below in the discussion that goes with png_read_end(). - -Input transformations - -After you've read the header information, you can set up the library -to handle any special transformations of the image data. The various -ways to transform the data will be described in the order that they -should occur. This is important, as some of these change the color -type and/or bit depth of the data, and some others only work on -certain color types and bit depths. Even though each transformation -checks to see if it has data that it can do something with, you should -make sure to only enable a transformation if it will be valid for the -data. For example, don't swap red and blue on grayscale data. - -The colors used for the background and transparency values should be -supplied in the same format/depth as the current image data. They -are stored in the same format/depth as the image data in a bKGD or tRNS -chunk, so this is what libpng expects for this data. The colors are -transformed to keep in sync with the image data when an application -calls the png_read_update_info() routine (see below). - -Data will be decoded into the supplied row buffers packed into bytes -unless the library has been told to transform it into another format. -For example, 4 bit/pixel paletted or grayscale data will be returned -2 pixels/byte with the leftmost pixel in the high-order bits of the -byte, unless png_set_packing() is called. 8-bit RGB data will be stored -in RGB RGB RGB format unless png_set_filler() or png_set_add_alpha() -is called to insert filler bytes, either before or after each RGB triplet. -16-bit RGB data will be returned RRGGBB RRGGBB, with the most significant -byte of the color value first, unless png_set_strip_16() is called to -transform it to regular RGB RGB triplets, or png_set_filler() or -png_set_add alpha() is called to insert filler bytes, either before or -after each RRGGBB triplet. Similarly, 8-bit or 16-bit grayscale data can -be modified with -png_set_filler(), png_set_add_alpha(), or png_set_strip_16(). - -The following code transforms grayscale images of less than 8 to 8 bits, -changes paletted images to RGB, and adds a full alpha channel if there is -transparency information in a tRNS chunk. This is most useful on -grayscale images with bit depths of 2 or 4 or if there is a multiple-image -viewing application that wishes to treat all images in the same way. - - if (color_type == PNG_COLOR_TYPE_PALETTE) - png_set_palette_to_rgb(png_ptr); - - if (color_type == PNG_COLOR_TYPE_GRAY && - bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png_ptr); - - if (png_get_valid(png_ptr, info_ptr, - PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr); - -These three functions are actually aliases for png_set_expand(), added -in libpng version 1.0.4, with the function names expanded to improve code -readability. In some future version they may actually do different -things. - -As of libpng version 1.2.9, png_set_expand_gray_1_2_4_to_8() was -added. It expands the sample depth without changing tRNS to alpha. -At the same time, png_set_gray_1_2_4_to_8() was deprecated, and it -will be removed from a future version. - -PNG can have files with 16 bits per channel. If you only can handle -8 bits per channel, this will strip the pixels down to 8 bit. - - if (bit_depth == 16) - png_set_strip_16(png_ptr); - -If, for some reason, you don't need the alpha channel on an image, -and you want to remove it rather than combining it with the background -(but the image author certainly had in mind that you *would* combine -it with the background, so that's what you should probably do): - - if (color_type & PNG_COLOR_MASK_ALPHA) - png_set_strip_alpha(png_ptr); - -In PNG files, the alpha channel in an image -is the level of opacity. If you need the alpha channel in an image to -be the level of transparency instead of opacity, you can invert the -alpha channel (or the tRNS chunk data) after it's read, so that 0 is -fully opaque and 255 (in 8-bit or paletted images) or 65535 (in 16-bit -images) is fully transparent, with - - png_set_invert_alpha(png_ptr); - -PNG files pack pixels of bit depths 1, 2, and 4 into bytes as small as -they can, resulting in, for example, 8 pixels per byte for 1 bit -files. This code expands to 1 pixel per byte without changing the -values of the pixels: - - if (bit_depth < 8) - png_set_packing(png_ptr); - -PNG files have possible bit depths of 1, 2, 4, 8, and 16. All pixels -stored in a PNG image have been "scaled" or "shifted" up to the next -higher possible bit depth (e.g. from 5 bits/sample in the range [0,31] to -8 bits/sample in the range [0, 255]). However, it is also possible to -convert the PNG pixel data back to the original bit depth of the image. -This call reduces the pixels back down to the original bit depth: - - png_color_8p sig_bit; - - if (png_get_sBIT(png_ptr, info_ptr, &sig_bit)) - png_set_shift(png_ptr, sig_bit); - -PNG files store 3-color pixels in red, green, blue order. This code -changes the storage of the pixels to blue, green, red: - - if (color_type == PNG_COLOR_TYPE_RGB || - color_type == PNG_COLOR_TYPE_RGB_ALPHA) - png_set_bgr(png_ptr); - -PNG files store RGB pixels packed into 3 or 6 bytes. This code expands them -into 4 or 8 bytes for windowing systems that need them in this format: - - if (color_type == PNG_COLOR_TYPE_RGB) - png_set_filler(png_ptr, filler, PNG_FILLER_BEFORE); - -where "filler" is the 8 or 16-bit number to fill with, and the location is -either PNG_FILLER_BEFORE or PNG_FILLER_AFTER, depending upon whether -you want the filler before the RGB or after. This transformation -does not affect images that already have full alpha channels. To add an -opaque alpha channel, use filler=0xff or 0xffff and PNG_FILLER_AFTER which -will generate RGBA pixels. - -Note that png_set_filler() does not change the color type. If you want -to do that, you can add a true alpha channel with - - if (color_type == PNG_COLOR_TYPE_RGB || - color_type == PNG_COLOR_TYPE_GRAY) - png_set_add_alpha(png_ptr, filler, PNG_FILLER_AFTER); - -where "filler" contains the alpha value to assign to each pixel. -This function was added in libpng-1.2.7. - -If you are reading an image with an alpha channel, and you need the -data as ARGB instead of the normal PNG format RGBA: - - if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) - png_set_swap_alpha(png_ptr); - -For some uses, you may want a grayscale image to be represented as -RGB. This code will do that conversion: - - if (color_type == PNG_COLOR_TYPE_GRAY || - color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - png_set_gray_to_rgb(png_ptr); - -Conversely, you can convert an RGB or RGBA image to grayscale or grayscale -with alpha. - - if (color_type == PNG_COLOR_TYPE_RGB || - color_type == PNG_COLOR_TYPE_RGB_ALPHA) - png_set_rgb_to_gray_fixed(png_ptr, error_action, - int red_weight, int green_weight); - - error_action = 1: silently do the conversion - error_action = 2: issue a warning if the original - image has any pixel where - red != green or red != blue - error_action = 3: issue an error and abort the - conversion if the original - image has any pixel where - red != green or red != blue - - red_weight: weight of red component times 100000 - green_weight: weight of green component times 100000 - If either weight is negative, default - weights (21268, 71514) are used. - -If you have set error_action = 1 or 2, you can -later check whether the image really was gray, after processing -the image rows, with the png_get_rgb_to_gray_status(png_ptr) function. -It will return a png_byte that is zero if the image was gray or -1 if there were any non-gray pixels. bKGD and sBIT data -will be silently converted to grayscale, using the green channel -data, regardless of the error_action setting. - -With red_weight+green_weight<=100000, -the normalized graylevel is computed: - - int rw = red_weight * 65536; - int gw = green_weight * 65536; - int bw = 65536 - (rw + gw); - gray = (rw*red + gw*green + bw*blue)/65536; - -The default values approximate those recommended in the Charles -Poynton's Color FAQ, -Copyright (c) 1998-01-04 Charles Poynton - - Y = 0.212671 * R + 0.715160 * G + 0.072169 * B - -Libpng approximates this with - - Y = 0.21268 * R + 0.7151 * G + 0.07217 * B - -which can be expressed with integers as - - Y = (6969 * R + 23434 * G + 2365 * B)/32768 - -The calculation is done in a linear colorspace, if the image gamma -is known. - -If you have a grayscale and you are using png_set_expand_depth(), -png_set_expand(), or png_set_gray_to_rgb to change to truecolor or to -a higher bit-depth, you must either supply the background color as a gray -value at the original file bit-depth (need_expand = 1) or else supply the -background color as an RGB triplet at the final, expanded bit depth -(need_expand = 0). Similarly, if you are reading a paletted image, you -must either supply the background color as a palette index (need_expand = 1) -or as an RGB triplet that may or may not be in the palette (need_expand = 0). - - png_color_16 my_background; - png_color_16p image_background; - - if (png_get_bKGD(png_ptr, info_ptr, &image_background)) - png_set_background(png_ptr, image_background, - PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); - else - png_set_background(png_ptr, &my_background, - PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); - -The png_set_background() function tells libpng to composite images -with alpha or simple transparency against the supplied background -color. If the PNG file contains a bKGD chunk (PNG_INFO_bKGD valid), -you may use this color, or supply another color more suitable for -the current display (e.g., the background color from a web page). You -need to tell libpng whether the color is in the gamma space of the -display (PNG_BACKGROUND_GAMMA_SCREEN for colors you supply), the file -(PNG_BACKGROUND_GAMMA_FILE for colors from the bKGD chunk), or one -that is neither of these gammas (PNG_BACKGROUND_GAMMA_UNIQUE - I don't -know why anyone would use this, but it's here). - -To properly display PNG images on any kind of system, the application needs -to know what the display gamma is. Ideally, the user will know this, and -the application will allow them to set it. One method of allowing the user -to set the display gamma separately for each system is to check for a -SCREEN_GAMMA or DISPLAY_GAMMA environment variable, which will hopefully be -correctly set. - -Note that display_gamma is the overall gamma correction required to produce -pleasing results, which depends on the lighting conditions in the surrounding -environment. In a dim or brightly lit room, no compensation other than -the physical gamma exponent of the monitor is needed, while in a dark room -a slightly smaller exponent is better. - - double gamma, screen_gamma; - - if (/* We have a user-defined screen - gamma value */) - { - screen_gamma = user_defined_screen_gamma; - } - /* One way that applications can share the same - screen gamma value */ - else if ((gamma_str = getenv("SCREEN_GAMMA")) - != NULL) - { - screen_gamma = (double)atof(gamma_str); - } - /* If we don't have another value */ - else - { - screen_gamma = 2.2; /* A good guess for a - PC monitor in a bright office or a dim room */ - screen_gamma = 2.0; /* A good guess for a - PC monitor in a dark room */ - screen_gamma = 1.7 or 1.0; /* A good - guess for Mac systems */ - } - -The png_set_gamma() function handles gamma transformations of the data. -Pass both the file gamma and the current screen_gamma. If the file does -not have a gamma value, you can pass one anyway if you have an idea what -it is (usually 0.45455 is a good guess for GIF images on PCs). Note -that file gammas are inverted from screen gammas. See the discussions -on gamma in the PNG specification for an excellent description of what -gamma is, and why all applications should support it. It is strongly -recommended that PNG viewers support gamma correction. - - if (png_get_gAMA(png_ptr, info_ptr, &gamma)) - png_set_gamma(png_ptr, screen_gamma, gamma); - else - png_set_gamma(png_ptr, screen_gamma, 0.45455); - -If you need to reduce an RGB file to a paletted file, or if a paletted -file has more entries then will fit on your screen, png_set_dither() -will do that. Note that this is a simple match dither that merely -finds the closest color available. This should work fairly well with -optimized palettes, and fairly badly with linear color cubes. If you -pass a palette that is larger then maximum_colors, the file will -reduce the number of colors in the palette so it will fit into -maximum_colors. If there is a histogram, it will use it to make -more intelligent choices when reducing the palette. If there is no -histogram, it may not do as good a job. - - if (color_type & PNG_COLOR_MASK_COLOR) - { - if (png_get_valid(png_ptr, info_ptr, - PNG_INFO_PLTE)) - { - png_uint_16p histogram = NULL; - - png_get_hIST(png_ptr, info_ptr, - &histogram); - png_set_dither(png_ptr, palette, num_palette, - max_screen_colors, histogram, 1); - } - else - { - png_color std_color_cube[MAX_SCREEN_COLORS] = - { ... colors ... }; - - png_set_dither(png_ptr, std_color_cube, - MAX_SCREEN_COLORS, MAX_SCREEN_COLORS, - NULL,0); - } - } - -PNG files describe monochrome as black being zero and white being one. -The following code will reverse this (make black be one and white be -zero): - - if (bit_depth == 1 && color_type == PNG_COLOR_TYPE_GRAY) - png_set_invert_mono(png_ptr); - -This function can also be used to invert grayscale and gray-alpha images: - - if (color_type == PNG_COLOR_TYPE_GRAY || - color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - png_set_invert_mono(png_ptr); - -PNG files store 16 bit pixels in network byte order (big-endian, -ie. most significant bits first). This code changes the storage to the -other way (little-endian, i.e. least significant bits first, the -way PCs store them): - - if (bit_depth == 16) - png_set_swap(png_ptr); - -If you are using packed-pixel images (1, 2, or 4 bits/pixel), and you -need to change the order the pixels are packed into bytes, you can use: - - if (bit_depth < 8) - png_set_packswap(png_ptr); - -Finally, you can write your own transformation function if none of -the existing ones meets your needs. This is done by setting a callback -with - - png_set_read_user_transform_fn(png_ptr, - read_transform_fn); - -You must supply the function - - void read_transform_fn(png_ptr ptr, row_info_ptr - row_info, png_bytep data) - -See pngtest.c for a working example. Your function will be called -after all of the other transformations have been processed. - -You can also set up a pointer to a user structure for use by your -callback function, and you can inform libpng that your transform -function will change the number of channels or bit depth with the -function - - png_set_user_transform_info(png_ptr, user_ptr, - user_depth, user_channels); - -The user's application, not libpng, is responsible for allocating and -freeing any memory required for the user structure. - -You can retrieve the pointer via the function -png_get_user_transform_ptr(). For example: - - voidp read_user_transform_ptr = - png_get_user_transform_ptr(png_ptr); - -The last thing to handle is interlacing; this is covered in detail below, -but you must call the function here if you want libpng to handle expansion -of the interlaced image. - - number_of_passes = png_set_interlace_handling(png_ptr); - -After setting the transformations, libpng can update your png_info -structure to reflect any transformations you've requested with this -call. This is most useful to update the info structure's rowbytes -field so you can use it to allocate your image memory. This function -will also update your palette with the correct screen_gamma and -background if these have been given with the calls above. - - png_read_update_info(png_ptr, info_ptr); - -After you call png_read_update_info(), you can allocate any -memory you need to hold the image. The row data is simply -raw byte data for all forms of images. As the actual allocation -varies among applications, no example will be given. If you -are allocating one large chunk, you will need to build an -array of pointers to each row, as it will be needed for some -of the functions below. - -Reading image data - -After you've allocated memory, you can read the image data. -The simplest way to do this is in one function call. If you are -allocating enough memory to hold the whole image, you can just -call png_read_image() and libpng will read in all the image data -and put it in the memory area supplied. You will need to pass in -an array of pointers to each row. - -This function automatically handles interlacing, so you don't need -to call png_set_interlace_handling() or call this function multiple -times, or any of that other stuff necessary with png_read_rows(). - - png_read_image(png_ptr, row_pointers); - -where row_pointers is: - - png_bytep row_pointers[height]; - -You can point to void or char or whatever you use for pixels. - -If you don't want to read in the whole image at once, you can -use png_read_rows() instead. If there is no interlacing (check -interlace_type == PNG_INTERLACE_NONE), this is simple: - - png_read_rows(png_ptr, row_pointers, NULL, - number_of_rows); - -where row_pointers is the same as in the png_read_image() call. - -If you are doing this just one row at a time, you can do this with -a single row_pointer instead of an array of row_pointers: - - png_bytep row_pointer = row; - png_read_row(png_ptr, row_pointer, NULL); - -If the file is interlaced (interlace_type != 0 in the IHDR chunk), things -get somewhat harder. The only current (PNG Specification version 1.2) -interlacing type for PNG is (interlace_type == PNG_INTERLACE_ADAM7) -is a somewhat complicated 2D interlace scheme, known as Adam7, that -breaks down an image into seven smaller images of varying size, based -on an 8x8 grid. - -libpng can fill out those images or it can give them to you "as is". -If you want them filled out, there are two ways to do that. The one -mentioned in the PNG specification is to expand each pixel to cover -those pixels that have not been read yet (the "rectangle" method). -This results in a blocky image for the first pass, which gradually -smooths out as more pixels are read. The other method is the "sparkle" -method, where pixels are drawn only in their final locations, with the -rest of the image remaining whatever colors they were initialized to -before the start of the read. The first method usually looks better, -but tends to be slower, as there are more pixels to put in the rows. - -If you don't want libpng to handle the interlacing details, just call -png_read_rows() seven times to read in all seven images. Each of the -images is a valid image by itself, or they can all be combined on an -8x8 grid to form a single image (although if you intend to combine them -you would be far better off using the libpng interlace handling). - -The first pass will return an image 1/8 as wide as the entire image -(every 8th column starting in column 0) and 1/8 as high as the original -(every 8th row starting in row 0), the second will be 1/8 as wide -(starting in column 4) and 1/8 as high (also starting in row 0). The -third pass will be 1/4 as wide (every 4th pixel starting in column 0) and -1/8 as high (every 8th row starting in row 4), and the fourth pass will -be 1/4 as wide and 1/4 as high (every 4th column starting in column 2, -and every 4th row starting in row 0). The fifth pass will return an -image 1/2 as wide, and 1/4 as high (starting at column 0 and row 2), -while the sixth pass will be 1/2 as wide and 1/2 as high as the original -(starting in column 1 and row 0). The seventh and final pass will be as -wide as the original, and 1/2 as high, containing all of the odd -numbered scanlines. Phew! - -If you want libpng to expand the images, call this before calling -png_start_read_image() or png_read_update_info(): - - if (interlace_type == PNG_INTERLACE_ADAM7) - number_of_passes - = png_set_interlace_handling(png_ptr); - -This will return the number of passes needed. Currently, this -is seven, but may change if another interlace type is added. -This function can be called even if the file is not interlaced, -where it will return one pass. - -If you are not going to display the image after each pass, but are -going to wait until the entire image is read in, use the sparkle -effect. This effect is faster and the end result of either method -is exactly the same. If you are planning on displaying the image -after each pass, the "rectangle" effect is generally considered the -better looking one. - -If you only want the "sparkle" effect, just call png_read_rows() as -normal, with the third parameter NULL. Make sure you make pass over -the image number_of_passes times, and you don't change the data in the -rows between calls. You can change the locations of the data, just -not the data. Each pass only writes the pixels appropriate for that -pass, and assumes the data from previous passes is still valid. - - png_read_rows(png_ptr, row_pointers, NULL, - number_of_rows); - -If you only want the first effect (the rectangles), do the same as -before except pass the row buffer in the third parameter, and leave -the second parameter NULL. - - png_read_rows(png_ptr, NULL, row_pointers, - number_of_rows); - -Finishing a sequential read - -After you are finished reading the image through the -low-level interface, you can finish reading the file. If you are -interested in comments or time, which may be stored either before or -after the image data, you should pass the separate png_info struct if -you want to keep the comments from before and after the image -separate. If you are not interested, you can pass NULL. - - png_read_end(png_ptr, end_info); - -When you are done, you can free all memory allocated by libpng like this: - - png_destroy_read_struct(&png_ptr, &info_ptr, - &end_info); - -It is also possible to individually free the info_ptr members that -point to libpng-allocated storage with the following function: - - png_free_data(png_ptr, info_ptr, mask, seq) - mask - identifies data to be freed, a mask - containing the bitwise OR of one or - more of - PNG_FREE_PLTE, PNG_FREE_TRNS, - PNG_FREE_HIST, PNG_FREE_ICCP, - PNG_FREE_PCAL, PNG_FREE_ROWS, - PNG_FREE_SCAL, PNG_FREE_SPLT, - PNG_FREE_TEXT, PNG_FREE_UNKN, - or simply PNG_FREE_ALL - seq - sequence number of item to be freed - (-1 for all items) - -This function may be safely called when the relevant storage has -already been freed, or has not yet been allocated, or was allocated -by the user and not by libpng, and will in those -cases do nothing. The "seq" parameter is ignored if only one item -of the selected data type, such as PLTE, is allowed. If "seq" is not --1, and multiple items are allowed for the data type identified in -the mask, such as text or sPLT, only the n'th item in the structure -is freed, where n is "seq". - -The default behavior is only to free data that was allocated internally -by libpng. This can be changed, so that libpng will not free the data, -or so that it will free data that was allocated by the user with png_malloc() -or png_zalloc() and passed in via a png_set_*() function, with - - png_data_freer(png_ptr, info_ptr, freer, mask) - mask - which data elements are affected - same choices as in png_free_data() - freer - one of - PNG_DESTROY_WILL_FREE_DATA - PNG_SET_WILL_FREE_DATA - PNG_USER_WILL_FREE_DATA - -This function only affects data that has already been allocated. -You can call this function after reading the PNG data but before calling -any png_set_*() functions, to control whether the user or the png_set_*() -function is responsible for freeing any existing data that might be present, -and again after the png_set_*() functions to control whether the user -or png_destroy_*() is supposed to free the data. When the user assumes -responsibility for libpng-allocated data, the application must use -png_free() to free it, and when the user transfers responsibility to libpng -for data that the user has allocated, the user must have used png_malloc() -or png_zalloc() to allocate it. - -If you allocated your row_pointers in a single block, as suggested above in -the description of the high level read interface, you must not transfer -responsibility for freeing it to the png_set_rows or png_read_destroy function, -because they would also try to free the individual row_pointers[i]. - -If you allocated text_ptr.text, text_ptr.lang, and text_ptr.translated_keyword -separately, do not transfer responsibility for freeing text_ptr to libpng, -because when libpng fills a png_text structure it combines these members with -the key member, and png_free_data() will free only text_ptr.key. Similarly, -if you transfer responsibility for free'ing text_ptr from libpng to your -application, your application must not separately free those members. - -The png_free_data() function will turn off the "valid" flag for anything -it frees. If you need to turn the flag off for a chunk that was freed by your -application instead of by libpng, you can use - - png_set_invalid(png_ptr, info_ptr, mask); - mask - identifies the chunks to be made invalid, - containing the bitwise OR of one or - more of - PNG_INFO_gAMA, PNG_INFO_sBIT, - PNG_INFO_cHRM, PNG_INFO_PLTE, - PNG_INFO_tRNS, PNG_INFO_bKGD, - PNG_INFO_hIST, PNG_INFO_pHYs, - PNG_INFO_oFFs, PNG_INFO_tIME, - PNG_INFO_pCAL, PNG_INFO_sRGB, - PNG_INFO_iCCP, PNG_INFO_sPLT, - PNG_INFO_sCAL, PNG_INFO_IDAT - -For a more compact example of reading a PNG image, see the file example.c. - -Reading PNG files progressively - -The progressive reader is slightly different then the non-progressive -reader. Instead of calling png_read_info(), png_read_rows(), and -png_read_end(), you make one call to png_process_data(), which calls -callbacks when it has the info, a row, or the end of the image. You -set up these callbacks with png_set_progressive_read_fn(). You don't -have to worry about the input/output functions of libpng, as you are -giving the library the data directly in png_process_data(). I will -assume that you have read the section on reading PNG files above, -so I will only highlight the differences (although I will show -all of the code). - -png_structp png_ptr; -png_infop info_ptr; - - /* An example code fragment of how you would - initialize the progressive reader in your - application. */ - int - initialize_png_reader() - { - png_ptr = png_create_read_struct - (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, - user_error_fn, user_warning_fn); - if (!png_ptr) - return (ERROR); - info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) - { - png_destroy_read_struct(&png_ptr, (png_infopp)NULL, - (png_infopp)NULL); - return (ERROR); - } - - if (setjmp(png_jmpbuf(png_ptr))) - { - png_destroy_read_struct(&png_ptr, &info_ptr, - (png_infopp)NULL); - return (ERROR); - } - - /* This one's new. You can provide functions - to be called when the header info is valid, - when each row is completed, and when the image - is finished. If you aren't using all functions, - you can specify NULL parameters. Even when all - three functions are NULL, you need to call - png_set_progressive_read_fn(). You can use - any struct as the user_ptr (cast to a void pointer - for the function call), and retrieve the pointer - from inside the callbacks using the function - - png_get_progressive_ptr(png_ptr); - - which will return a void pointer, which you have - to cast appropriately. - */ - png_set_progressive_read_fn(png_ptr, (void *)user_ptr, - info_callback, row_callback, end_callback); - - return 0; - } - - /* A code fragment that you call as you receive blocks - of data */ - int - process_data(png_bytep buffer, png_uint_32 length) - { - if (setjmp(png_jmpbuf(png_ptr))) - { - png_destroy_read_struct(&png_ptr, &info_ptr, - (png_infopp)NULL); - return (ERROR); - } - - /* This one's new also. Simply give it a chunk - of data from the file stream (in order, of - course). On machines with segmented memory - models machines, don't give it any more than - 64K. The library seems to run fine with sizes - of 4K. Although you can give it much less if - necessary (I assume you can give it chunks of - 1 byte, I haven't tried less then 256 bytes - yet). When this function returns, you may - want to display any rows that were generated - in the row callback if you don't already do - so there. - */ - png_process_data(png_ptr, info_ptr, buffer, length); - return 0; - } - - /* This function is called (as set by - png_set_progressive_read_fn() above) when enough data - has been supplied so all of the header has been - read. - */ - void - info_callback(png_structp png_ptr, png_infop info) - { - /* Do any setup here, including setting any of - the transformations mentioned in the Reading - PNG files section. For now, you _must_ call - either png_start_read_image() or - png_read_update_info() after all the - transformations are set (even if you don't set - any). You may start getting rows before - png_process_data() returns, so this is your - last chance to prepare for that. - */ - } - - /* This function is called when each row of image - data is complete */ - void - row_callback(png_structp png_ptr, png_bytep new_row, - png_uint_32 row_num, int pass) - { - /* If the image is interlaced, and you turned - on the interlace handler, this function will - be called for every row in every pass. Some - of these rows will not be changed from the - previous pass. When the row is not changed, - the new_row variable will be NULL. The rows - and passes are called in order, so you don't - really need the row_num and pass, but I'm - supplying them because it may make your life - easier. - - For the non-NULL rows of interlaced images, - you must call png_progressive_combine_row() - passing in the row and the old row. You can - call this function for NULL rows (it will just - return) and for non-interlaced images (it just - does the memcpy for you) if it will make the - code easier. Thus, you can just do this for - all cases: - */ - - png_progressive_combine_row(png_ptr, old_row, - new_row); - - /* where old_row is what was displayed for - previously for the row. Note that the first - pass (pass == 0, really) will completely cover - the old row, so the rows do not have to be - initialized. After the first pass (and only - for interlaced images), you will have to pass - the current row, and the function will combine - the old row and the new row. - */ - } - - void - end_callback(png_structp png_ptr, png_infop info) - { - /* This function is called after the whole image - has been read, including any chunks after the - image (up to and including the IEND). You - will usually have the same info chunk as you - had in the header, although some data may have - been added to the comments and time fields. - - Most people won't do much here, perhaps setting - a flag that marks the image as finished. - */ - } - - - -IV. Writing - -Much of this is very similar to reading. However, everything of -importance is repeated here, so you won't have to constantly look -back up in the reading section to understand writing. - -Setup - -You will want to do the I/O initialization before you get into libpng, -so if it doesn't work, you don't have anything to undo. If you are not -using the standard I/O functions, you will need to replace them with -custom writing functions. See the discussion under Customizing libpng. - - FILE *fp = fopen(file_name, "wb"); - if (!fp) - { - return (ERROR); - } - -Next, png_struct and png_info need to be allocated and initialized. -As these can be both relatively large, you may not want to store these -on the stack, unless you have stack space to spare. Of course, you -will want to check if they return NULL. If you are also reading, -you won't want to name your read structure and your write structure -both "png_ptr"; you can call them anything you like, such as -"read_ptr" and "write_ptr". Look at pngtest.c, for example. - - png_structp png_ptr = png_create_write_struct - (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, - user_error_fn, user_warning_fn); - if (!png_ptr) - return (ERROR); - - png_infop info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) - { - png_destroy_write_struct(&png_ptr, - (png_infopp)NULL); - return (ERROR); - } - -If you want to use your own memory allocation routines, -define PNG_USER_MEM_SUPPORTED and use -png_create_write_struct_2() instead of png_create_write_struct(): - - png_structp png_ptr = png_create_write_struct_2 - (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, - user_error_fn, user_warning_fn, (png_voidp) - user_mem_ptr, user_malloc_fn, user_free_fn); - -After you have these structures, you will need to set up the -error handling. When libpng encounters an error, it expects to -longjmp() back to your routine. Therefore, you will need to call -setjmp() and pass the png_jmpbuf(png_ptr). If you -write the file from different routines, you will need to update -the png_jmpbuf(png_ptr) every time you enter a new routine that will -call a png_*() function. See your documentation of setjmp/longjmp -for your compiler for more information on setjmp/longjmp. See -the discussion on libpng error handling in the Customizing Libpng -section below for more information on the libpng error handling. - - if (setjmp(png_jmpbuf(png_ptr))) - { - png_destroy_write_struct(&png_ptr, &info_ptr); - fclose(fp); - return (ERROR); - } - ... - return; - -If you would rather avoid the complexity of setjmp/longjmp issues, -you can compile libpng with PNG_SETJMP_NOT_SUPPORTED, in which case -errors will result in a call to PNG_ABORT() which defaults to abort(). - -Now you need to set up the output code. The default for libpng is to -use the C function fwrite(). If you use this, you will need to pass a -valid FILE * in the function png_init_io(). Be sure that the file is -opened in binary mode. Again, if you wish to handle writing data in -another way, see the discussion on libpng I/O handling in the Customizing -Libpng section below. - - png_init_io(png_ptr, fp); - -If you are embedding your PNG into a datastream such as MNG, and don't -want libpng to write the 8-byte signature, or if you have already -written the signature in your application, use - - png_set_sig_bytes(png_ptr, 8); - -to inform libpng that it should not write a signature. - -Write callbacks - -At this point, you can set up a callback function that will be -called after each row has been written, which you can use to control -a progress meter or the like. It's demonstrated in pngtest.c. -You must supply a function - - void write_row_callback(png_ptr, png_uint_32 row, - int pass); - { - /* put your code here */ - } - -(You can give it another name that you like instead of "write_row_callback") - -To inform libpng about your function, use - - png_set_write_status_fn(png_ptr, write_row_callback); - -You now have the option of modifying how the compression library will -run. The following functions are mainly for testing, but may be useful -in some cases, like if you need to write PNG files extremely fast and -are willing to give up some compression, or if you want to get the -maximum possible compression at the expense of slower writing. If you -have no special needs in this area, let the library do what it wants by -not calling this function at all, as it has been tuned to deliver a good -speed/compression ratio. The second parameter to png_set_filter() is -the filter method, for which the only valid values are 0 (as of the -July 1999 PNG specification, version 1.2) or 64 (if you are writing -a PNG datastream that is to be embedded in a MNG datastream). The third -parameter is a flag that indicates which filter type(s) are to be tested -for each scanline. See the PNG specification for details on the specific filter -types. - - - /* turn on or off filtering, and/or choose - specific filters. You can use either a single - PNG_FILTER_VALUE_NAME or the bitwise OR of one - or more PNG_FILTER_NAME masks. */ - png_set_filter(png_ptr, 0, - PNG_FILTER_NONE | PNG_FILTER_VALUE_NONE | - PNG_FILTER_SUB | PNG_FILTER_VALUE_SUB | - PNG_FILTER_UP | PNG_FILTER_VALUE_UP | - PNG_FILTER_AVE | PNG_FILTER_VALUE_AVE | - PNG_FILTER_PAETH | PNG_FILTER_VALUE_PAETH| - PNG_ALL_FILTERS); - -If an application -wants to start and stop using particular filters during compression, -it should start out with all of the filters (to ensure that the previous -row of pixels will be stored in case it's needed later), and then add -and remove them after the start of compression. - -If you are writing a PNG datastream that is to be embedded in a MNG -datastream, the second parameter can be either 0 or 64. - -The png_set_compression_*() functions interface to the zlib compression -library, and should mostly be ignored unless you really know what you are -doing. The only generally useful call is png_set_compression_level() -which changes how much time zlib spends on trying to compress the image -data. See the Compression Library (zlib.h and algorithm.txt, distributed -with zlib) for details on the compression levels. - - /* set the zlib compression level */ - png_set_compression_level(png_ptr, - Z_BEST_COMPRESSION); - - /* set other zlib parameters */ - png_set_compression_mem_level(png_ptr, 8); - png_set_compression_strategy(png_ptr, - Z_DEFAULT_STRATEGY); - png_set_compression_window_bits(png_ptr, 15); - png_set_compression_method(png_ptr, 8); - png_set_compression_buffer_size(png_ptr, 8192) - -extern PNG_EXPORT(void,png_set_zbuf_size) - -Setting the contents of info for output - -You now need to fill in the png_info structure with all the data you -wish to write before the actual image. Note that the only thing you -are allowed to write after the image is the text chunks and the time -chunk (as of PNG Specification 1.2, anyway). See png_write_end() and -the latest PNG specification for more information on that. If you -wish to write them before the image, fill them in now, and flag that -data as being valid. If you want to wait until after the data, don't -fill them until png_write_end(). For all the fields in png_info and -their data types, see png.h. For explanations of what the fields -contain, see the PNG specification. - -Some of the more important parts of the png_info are: - - png_set_IHDR(png_ptr, info_ptr, width, height, - bit_depth, color_type, interlace_type, - compression_type, filter_method) - width - holds the width of the image - in pixels (up to 2^31). - height - holds the height of the image - in pixels (up to 2^31). - bit_depth - holds the bit depth of one of the - image channels. - (valid values are 1, 2, 4, 8, 16 - and depend also on the - color_type. See also significant - bits (sBIT) below). - color_type - describes which color/alpha - channels are present. - PNG_COLOR_TYPE_GRAY - (bit depths 1, 2, 4, 8, 16) - PNG_COLOR_TYPE_GRAY_ALPHA - (bit depths 8, 16) - PNG_COLOR_TYPE_PALETTE - (bit depths 1, 2, 4, 8) - PNG_COLOR_TYPE_RGB - (bit_depths 8, 16) - PNG_COLOR_TYPE_RGB_ALPHA - (bit_depths 8, 16) - - PNG_COLOR_MASK_PALETTE - PNG_COLOR_MASK_COLOR - PNG_COLOR_MASK_ALPHA - - interlace_type - PNG_INTERLACE_NONE or - PNG_INTERLACE_ADAM7 - compression_type - (must be - PNG_COMPRESSION_TYPE_DEFAULT) - filter_method - (must be PNG_FILTER_TYPE_DEFAULT - or, if you are writing a PNG to - be embedded in a MNG datastream, - can also be - PNG_INTRAPIXEL_DIFFERENCING) - - png_set_PLTE(png_ptr, info_ptr, palette, - num_palette); - palette - the palette for the file - (array of png_color) - num_palette - number of entries in the palette - - png_set_gAMA(png_ptr, info_ptr, gamma); - gamma - the gamma the image was created - at (PNG_INFO_gAMA) - - png_set_sRGB(png_ptr, info_ptr, srgb_intent); - srgb_intent - the rendering intent - (PNG_INFO_sRGB) The presence of - the sRGB chunk means that the pixel - data is in the sRGB color space. - This chunk also implies specific - values of gAMA and cHRM. Rendering - intent is the CSS-1 property that - has been defined by the International - Color Consortium - (http://www.color.org). - It can be one of - PNG_sRGB_INTENT_SATURATION, - PNG_sRGB_INTENT_PERCEPTUAL, - PNG_sRGB_INTENT_ABSOLUTE, or - PNG_sRGB_INTENT_RELATIVE. - - - png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, - srgb_intent); - srgb_intent - the rendering intent - (PNG_INFO_sRGB) The presence of the - sRGB chunk means that the pixel - data is in the sRGB color space. - This function also causes gAMA and - cHRM chunks with the specific values - that are consistent with sRGB to be - written. - - png_set_iCCP(png_ptr, info_ptr, name, compression_type, - profile, proflen); - name - The profile name. - compression - The compression type; always - PNG_COMPRESSION_TYPE_BASE for PNG 1.0. - You may give NULL to this argument to - ignore it. - profile - International Color Consortium color - profile data. May contain NULs. - proflen - length of profile data in bytes. - - png_set_sBIT(png_ptr, info_ptr, sig_bit); - sig_bit - the number of significant bits for - (PNG_INFO_sBIT) each of the gray, red, - green, and blue channels, whichever are - appropriate for the given color type - (png_color_16) - - png_set_tRNS(png_ptr, info_ptr, trans, num_trans, - trans_values); - trans - array of transparent entries for - palette (PNG_INFO_tRNS) - trans_values - graylevel or color sample values of - the single transparent color for - non-paletted images (PNG_INFO_tRNS) - num_trans - number of transparent entries - (PNG_INFO_tRNS) - - png_set_hIST(png_ptr, info_ptr, hist); - (PNG_INFO_hIST) - hist - histogram of palette (array of - png_uint_16) - - png_set_tIME(png_ptr, info_ptr, mod_time); - mod_time - time image was last modified - (PNG_VALID_tIME) - - png_set_bKGD(png_ptr, info_ptr, background); - background - background color (PNG_VALID_bKGD) - - png_set_text(png_ptr, info_ptr, text_ptr, num_text); - text_ptr - array of png_text holding image - comments - text_ptr[i].compression - type of compression used - on "text" PNG_TEXT_COMPRESSION_NONE - PNG_TEXT_COMPRESSION_zTXt - PNG_ITXT_COMPRESSION_NONE - PNG_ITXT_COMPRESSION_zTXt - text_ptr[i].key - keyword for comment. Must contain - 1-79 characters. - text_ptr[i].text - text comments for current - keyword. Can be NULL or empty. - text_ptr[i].text_length - length of text string, - after decompression, 0 for iTXt - text_ptr[i].itxt_length - length of itxt string, - after decompression, 0 for tEXt/zTXt - text_ptr[i].lang - language of comment (NULL or - empty for unknown). - text_ptr[i].translated_keyword - keyword in UTF-8 (NULL - or empty for unknown). - num_text - number of comments - - png_set_sPLT(png_ptr, info_ptr, &palette_ptr, - num_spalettes); - palette_ptr - array of png_sPLT_struct structures - to be added to the list of palettes - in the info structure. - num_spalettes - number of palette structures to be - added. - - png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, - unit_type); - offset_x - positive offset from the left - edge of the screen - offset_y - positive offset from the top - edge of the screen - unit_type - PNG_OFFSET_PIXEL, PNG_OFFSET_MICROMETER - - png_set_pHYs(png_ptr, info_ptr, res_x, res_y, - unit_type); - res_x - pixels/unit physical resolution - in x direction - res_y - pixels/unit physical resolution - in y direction - unit_type - PNG_RESOLUTION_UNKNOWN, - PNG_RESOLUTION_METER - - png_set_sCAL(png_ptr, info_ptr, unit, width, height) - unit - physical scale units (an integer) - width - width of a pixel in physical scale units - height - height of a pixel in physical scale units - (width and height are doubles) - - png_set_sCAL_s(png_ptr, info_ptr, unit, width, height) - unit - physical scale units (an integer) - width - width of a pixel in physical scale units - height - height of a pixel in physical scale units - (width and height are strings like "2.54") - - png_set_unknown_chunks(png_ptr, info_ptr, &unknowns, - num_unknowns) - unknowns - array of png_unknown_chunk - structures holding unknown chunks - unknowns[i].name - name of unknown chunk - unknowns[i].data - data of unknown chunk - unknowns[i].size - size of unknown chunk's data - unknowns[i].location - position to write chunk in file - 0: do not write chunk - PNG_HAVE_IHDR: before PLTE - PNG_HAVE_PLTE: before IDAT - PNG_AFTER_IDAT: after IDAT - -The "location" member is set automatically according to -what part of the output file has already been written. -You can change its value after calling png_set_unknown_chunks() -as demonstrated in pngtest.c. Within each of the "locations", -the chunks are sequenced according to their position in the -structure (that is, the value of "i", which is the order in which -the chunk was either read from the input file or defined with -png_set_unknown_chunks). - -A quick word about text and num_text. text is an array of png_text -structures. num_text is the number of valid structures in the array. -Each png_text structure holds a language code, a keyword, a text value, -and a compression type. - -The compression types have the same valid numbers as the compression -types of the image data. Currently, the only valid number is zero. -However, you can store text either compressed or uncompressed, unlike -images, which always have to be compressed. So if you don't want the -text compressed, set the compression type to PNG_TEXT_COMPRESSION_NONE. -Because tEXt and zTXt chunks don't have a language field, if you -specify PNG_TEXT_COMPRESSION_NONE or PNG_TEXT_COMPRESSION_zTXt -any language code or translated keyword will not be written out. - -Until text gets around 1000 bytes, it is not worth compressing it. -After the text has been written out to the file, the compression type -is set to PNG_TEXT_COMPRESSION_NONE_WR or PNG_TEXT_COMPRESSION_zTXt_WR, -so that it isn't written out again at the end (in case you are calling -png_write_end() with the same struct. - -The keywords that are given in the PNG Specification are: - - Title Short (one line) title or - caption for image - Author Name of image's creator - Description Description of image (possibly long) - Copyright Copyright notice - Creation Time Time of original image creation - (usually RFC 1123 format, see below) - Software Software used to create the image - Disclaimer Legal disclaimer - Warning Warning of nature of content - Source Device used to create the image - Comment Miscellaneous comment; conversion - from other image format - -The keyword-text pairs work like this. Keywords should be short -simple descriptions of what the comment is about. Some typical -keywords are found in the PNG specification, as is some recommendations -on keywords. You can repeat keywords in a file. You can even write -some text before the image and some after. For example, you may want -to put a description of the image before the image, but leave the -disclaimer until after, so viewers working over modem connections -don't have to wait for the disclaimer to go over the modem before -they start seeing the image. Finally, keywords should be full -words, not abbreviations. Keywords and text are in the ISO 8859-1 -(Latin-1) character set (a superset of regular ASCII) and can not -contain NUL characters, and should not contain control or other -unprintable characters. To make the comments widely readable, stick -with basic ASCII, and avoid machine specific character set extensions -like the IBM-PC character set. The keyword must be present, but -you can leave off the text string on non-compressed pairs. -Compressed pairs must have a text string, as only the text string -is compressed anyway, so the compression would be meaningless. - -PNG supports modification time via the png_time structure. Two -conversion routines are provided, png_convert_from_time_t() for -time_t and png_convert_from_struct_tm() for struct tm. The -time_t routine uses gmtime(). You don't have to use either of -these, but if you wish to fill in the png_time structure directly, -you should provide the time in universal time (GMT) if possible -instead of your local time. Note that the year number is the full -year (e.g. 1998, rather than 98 - PNG is year 2000 compliant!), and -that months start with 1. - -If you want to store the time of the original image creation, you should -use a plain tEXt chunk with the "Creation Time" keyword. This is -necessary because the "creation time" of a PNG image is somewhat vague, -depending on whether you mean the PNG file, the time the image was -created in a non-PNG format, a still photo from which the image was -scanned, or possibly the subject matter itself. In order to facilitate -machine-readable dates, it is recommended that the "Creation Time" -tEXt chunk use RFC 1123 format dates (e.g. "22 May 1997 18:07:10 GMT"), -although this isn't a requirement. Unlike the tIME chunk, the -"Creation Time" tEXt chunk is not expected to be automatically changed -by the software. To facilitate the use of RFC 1123 dates, a function -png_convert_to_rfc1123(png_timep) is provided to convert from PNG -time to an RFC 1123 format string. - -Writing unknown chunks - -You can use the png_set_unknown_chunks function to queue up chunks -for writing. You give it a chunk name, raw data, and a size; that's -all there is to it. The chunks will be written by the next following -png_write_info_before_PLTE, png_write_info, or png_write_end function. -Any chunks previously read into the info structure's unknown-chunk -list will also be written out in a sequence that satisfies the PNG -specification's ordering rules. - -The high-level write interface - -At this point there are two ways to proceed; through the high-level -write interface, or through a sequence of low-level write operations. -You can use the high-level interface if your image data is present -in the info structure. All defined output -transformations are permitted, enabled by the following masks. - - PNG_TRANSFORM_IDENTITY No transformation - PNG_TRANSFORM_PACKING Pack 1, 2 and 4-bit samples - PNG_TRANSFORM_PACKSWAP Change order of packed - pixels to LSB first - PNG_TRANSFORM_INVERT_MONO Invert monochrome images - PNG_TRANSFORM_SHIFT Normalize pixels to the - sBIT depth - PNG_TRANSFORM_BGR Flip RGB to BGR, RGBA - to BGRA - PNG_TRANSFORM_SWAP_ALPHA Flip RGBA to ARGB or GA - to AG - PNG_TRANSFORM_INVERT_ALPHA Change alpha from opacity - to transparency - PNG_TRANSFORM_SWAP_ENDIAN Byte-swap 16-bit samples - PNG_TRANSFORM_STRIP_FILLER Strip out filler bytes. - -If you have valid image data in the info structure (you can use -png_set_rows() to put image data in the info structure), simply do this: - - png_write_png(png_ptr, info_ptr, png_transforms, NULL) - -where png_transforms is an integer containing the bitwise OR of some set of -transformation flags. This call is equivalent to png_write_info(), -followed the set of transformations indicated by the transform mask, -then png_write_image(), and finally png_write_end(). - -(The final parameter of this call is not yet used. Someday it might point -to transformation parameters required by some future output transform.) - -You must use png_transforms and not call any png_set_transform() functions -when you use png_write_png(). - -The low-level write interface - -If you are going the low-level route instead, you are now ready to -write all the file information up to the actual image data. You do -this with a call to png_write_info(). - - png_write_info(png_ptr, info_ptr); - -Note that there is one transformation you may need to do before -png_write_info(). In PNG files, the alpha channel in an image is the -level of opacity. If your data is supplied as a level of -transparency, you can invert the alpha channel before you write it, so -that 0 is fully transparent and 255 (in 8-bit or paletted images) or -65535 (in 16-bit images) is fully opaque, with - - png_set_invert_alpha(png_ptr); - -This must appear before png_write_info() instead of later with the -other transformations because in the case of paletted images the tRNS -chunk data has to be inverted before the tRNS chunk is written. If -your image is not a paletted image, the tRNS data (which in such cases -represents a single color to be rendered as transparent) won't need to -be changed, and you can safely do this transformation after your -png_write_info() call. - -If you need to write a private chunk that you want to appear before -the PLTE chunk when PLTE is present, you can write the PNG info in -two steps, and insert code to write your own chunk between them: - - png_write_info_before_PLTE(png_ptr, info_ptr); - png_set_unknown_chunks(png_ptr, info_ptr, ...); - png_write_info(png_ptr, info_ptr); - -After you've written the file information, you can set up the library -to handle any special transformations of the image data. The various -ways to transform the data will be described in the order that they -should occur. This is important, as some of these change the color -type and/or bit depth of the data, and some others only work on -certain color types and bit depths. Even though each transformation -checks to see if it has data that it can do something with, you should -make sure to only enable a transformation if it will be valid for the -data. For example, don't swap red and blue on grayscale data. - -PNG files store RGB pixels packed into 3 or 6 bytes. This code tells -the library to strip input data that has 4 or 8 bytes per pixel down -to 3 or 6 bytes (or strip 2 or 4-byte grayscale+filler data to 1 or 2 -bytes per pixel). - - png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); - -where the 0 is unused, and the location is either PNG_FILLER_BEFORE or -PNG_FILLER_AFTER, depending upon whether the filler byte in the pixel -is stored XRGB or RGBX. - -PNG files pack pixels of bit depths 1, 2, and 4 into bytes as small as -they can, resulting in, for example, 8 pixels per byte for 1 bit files. -If the data is supplied at 1 pixel per byte, use this code, which will -correctly pack the pixels into a single byte: - - png_set_packing(png_ptr); - -PNG files reduce possible bit depths to 1, 2, 4, 8, and 16. If your -data is of another bit depth, you can write an sBIT chunk into the -file so that decoders can recover the original data if desired. - - /* Set the true bit depth of the image data */ - if (color_type & PNG_COLOR_MASK_COLOR) - { - sig_bit.red = true_bit_depth; - sig_bit.green = true_bit_depth; - sig_bit.blue = true_bit_depth; - } - else - { - sig_bit.gray = true_bit_depth; - } - if (color_type & PNG_COLOR_MASK_ALPHA) - { - sig_bit.alpha = true_bit_depth; - } - - png_set_sBIT(png_ptr, info_ptr, &sig_bit); - -If the data is stored in the row buffer in a bit depth other than -one supported by PNG (e.g. 3 bit data in the range 0-7 for a 4-bit PNG), -this will scale the values to appear to be the correct bit depth as -is required by PNG. - - png_set_shift(png_ptr, &sig_bit); - -PNG files store 16 bit pixels in network byte order (big-endian, -ie. most significant bits first). This code would be used if they are -supplied the other way (little-endian, i.e. least significant bits -first, the way PCs store them): - - if (bit_depth > 8) - png_set_swap(png_ptr); - -If you are using packed-pixel images (1, 2, or 4 bits/pixel), and you -need to change the order the pixels are packed into bytes, you can use: - - if (bit_depth < 8) - png_set_packswap(png_ptr); - -PNG files store 3 color pixels in red, green, blue order. This code -would be used if they are supplied as blue, green, red: - - png_set_bgr(png_ptr); - -PNG files describe monochrome as black being zero and white being -one. This code would be used if the pixels are supplied with this reversed -(black being one and white being zero): - - png_set_invert_mono(png_ptr); - -Finally, you can write your own transformation function if none of -the existing ones meets your needs. This is done by setting a callback -with - - png_set_write_user_transform_fn(png_ptr, - write_transform_fn); - -You must supply the function - - void write_transform_fn(png_ptr ptr, row_info_ptr - row_info, png_bytep data) - -See pngtest.c for a working example. Your function will be called -before any of the other transformations are processed. - -You can also set up a pointer to a user structure for use by your -callback function. - - png_set_user_transform_info(png_ptr, user_ptr, 0, 0); - -The user_channels and user_depth parameters of this function are ignored -when writing; you can set them to zero as shown. - -You can retrieve the pointer via the function png_get_user_transform_ptr(). -For example: - - voidp write_user_transform_ptr = - png_get_user_transform_ptr(png_ptr); - -It is possible to have libpng flush any pending output, either manually, -or automatically after a certain number of lines have been written. To -flush the output stream a single time call: - - png_write_flush(png_ptr); - -and to have libpng flush the output stream periodically after a certain -number of scanlines have been written, call: - - png_set_flush(png_ptr, nrows); - -Note that the distance between rows is from the last time png_write_flush() -was called, or the first row of the image if it has never been called. -So if you write 50 lines, and then png_set_flush 25, it will flush the -output on the next scanline, and every 25 lines thereafter, unless -png_write_flush() is called before 25 more lines have been written. -If nrows is too small (less than about 10 lines for a 640 pixel wide -RGB image) the image compression may decrease noticeably (although this -may be acceptable for real-time applications). Infrequent flushing will -only degrade the compression performance by a few percent over images -that do not use flushing. - -Writing the image data - -That's it for the transformations. Now you can write the image data. -The simplest way to do this is in one function call. If you have the -whole image in memory, you can just call png_write_image() and libpng -will write the image. You will need to pass in an array of pointers to -each row. This function automatically handles interlacing, so you don't -need to call png_set_interlace_handling() or call this function multiple -times, or any of that other stuff necessary with png_write_rows(). - - png_write_image(png_ptr, row_pointers); - -where row_pointers is: - - png_byte *row_pointers[height]; - -You can point to void or char or whatever you use for pixels. - -If you don't want to write the whole image at once, you can -use png_write_rows() instead. If the file is not interlaced, -this is simple: - - png_write_rows(png_ptr, row_pointers, - number_of_rows); - -row_pointers is the same as in the png_write_image() call. - -If you are just writing one row at a time, you can do this with -a single row_pointer instead of an array of row_pointers: - - png_bytep row_pointer = row; - - png_write_row(png_ptr, row_pointer); - -When the file is interlaced, things can get a good deal more -complicated. The only currently (as of the PNG Specification -version 1.2, dated July 1999) defined interlacing scheme for PNG files -is the "Adam7" interlace scheme, that breaks down an -image into seven smaller images of varying size. libpng will build -these images for you, or you can do them yourself. If you want to -build them yourself, see the PNG specification for details of which -pixels to write when. - -If you don't want libpng to handle the interlacing details, just -use png_set_interlace_handling() and call png_write_rows() the -correct number of times to write all seven sub-images. - -If you want libpng to build the sub-images, call this before you start -writing any rows: - - number_of_passes = - png_set_interlace_handling(png_ptr); - -This will return the number of passes needed. Currently, this -is seven, but may change if another interlace type is added. - -Then write the complete image number_of_passes times. - - png_write_rows(png_ptr, row_pointers, - number_of_rows); - -As some of these rows are not used, and thus return immediately, -you may want to read about interlacing in the PNG specification, -and only update the rows that are actually used. - -Finishing a sequential write - -After you are finished writing the image, you should finish writing -the file. If you are interested in writing comments or time, you should -pass an appropriately filled png_info pointer. If you are not interested, -you can pass NULL. - - png_write_end(png_ptr, info_ptr); - -When you are done, you can free all memory used by libpng like this: - - png_destroy_write_struct(&png_ptr, &info_ptr); - -It is also possible to individually free the info_ptr members that -point to libpng-allocated storage with the following function: - - png_free_data(png_ptr, info_ptr, mask, seq) - mask - identifies data to be freed, a mask - containing the bitwise OR of one or - more of - PNG_FREE_PLTE, PNG_FREE_TRNS, - PNG_FREE_HIST, PNG_FREE_ICCP, - PNG_FREE_PCAL, PNG_FREE_ROWS, - PNG_FREE_SCAL, PNG_FREE_SPLT, - PNG_FREE_TEXT, PNG_FREE_UNKN, - or simply PNG_FREE_ALL - seq - sequence number of item to be freed - (-1 for all items) - -This function may be safely called when the relevant storage has -already been freed, or has not yet been allocated, or was allocated -by the user and not by libpng, and will in those -cases do nothing. The "seq" parameter is ignored if only one item -of the selected data type, such as PLTE, is allowed. If "seq" is not --1, and multiple items are allowed for the data type identified in -the mask, such as text or sPLT, only the n'th item in the structure -is freed, where n is "seq". - -If you allocated data such as a palette that you passed -in to libpng with png_set_*, you must not free it until just before the call to -png_destroy_write_struct(). - -The default behavior is only to free data that was allocated internally -by libpng. This can be changed, so that libpng will not free the data, -or so that it will free data that was allocated by the user with png_malloc() -or png_zalloc() and passed in via a png_set_*() function, with - - png_data_freer(png_ptr, info_ptr, freer, mask) - mask - which data elements are affected - same choices as in png_free_data() - freer - one of - PNG_DESTROY_WILL_FREE_DATA - PNG_SET_WILL_FREE_DATA - PNG_USER_WILL_FREE_DATA - -For example, to transfer responsibility for some data from a read structure -to a write structure, you could use - - png_data_freer(read_ptr, read_info_ptr, - PNG_USER_WILL_FREE_DATA, - PNG_FREE_PLTE|PNG_FREE_tRNS|PNG_FREE_hIST) - png_data_freer(write_ptr, write_info_ptr, - PNG_DESTROY_WILL_FREE_DATA, - PNG_FREE_PLTE|PNG_FREE_tRNS|PNG_FREE_hIST) - -thereby briefly reassigning responsibility for freeing to the user but -immediately afterwards reassigning it once more to the write_destroy -function. Having done this, it would then be safe to destroy the read -structure and continue to use the PLTE, tRNS, and hIST data in the write -structure. - -This function only affects data that has already been allocated. -You can call this function before calling after the png_set_*() functions -to control whether the user or png_destroy_*() is supposed to free the data. -When the user assumes responsibility for libpng-allocated data, the -application must use -png_free() to free it, and when the user transfers responsibility to libpng -for data that the user has allocated, the user must have used png_malloc() -or png_zalloc() to allocate it. - -If you allocated text_ptr.text, text_ptr.lang, and text_ptr.translated_keyword -separately, do not transfer responsibility for freeing text_ptr to libpng, -because when libpng fills a png_text structure it combines these members with -the key member, and png_free_data() will free only text_ptr.key. Similarly, -if you transfer responsibility for free'ing text_ptr from libpng to your -application, your application must not separately free those members. -For a more compact example of writing a PNG image, see the file example.c. - -V. Modifying/Customizing libpng: - -There are two issues here. The first is changing how libpng does -standard things like memory allocation, input/output, and error handling. -The second deals with more complicated things like adding new chunks, -adding new transformations, and generally changing how libpng works. -Both of those are compile-time issues; that is, they are generally -determined at the time the code is written, and there is rarely a need -to provide the user with a means of changing them. - -Memory allocation, input/output, and error handling - -All of the memory allocation, input/output, and error handling in libpng -goes through callbacks that are user-settable. The default routines are -in pngmem.c, pngrio.c, pngwio.c, and pngerror.c, respectively. To change -these functions, call the appropriate png_set_*_fn() function. - -Memory allocation is done through the functions png_malloc() -and png_free(). These currently just call the standard C functions. If -your pointers can't access more then 64K at a time, you will want to set -MAXSEG_64K in zlib.h. Since it is unlikely that the method of handling -memory allocation on a platform will change between applications, these -functions must be modified in the library at compile time. If you prefer -to use a different method of allocating and freeing data, you can use -png_create_read_struct_2() or png_create_write_struct_2() to register -your own functions as described above. -These functions also provide a void pointer that can be retrieved via - - mem_ptr=png_get_mem_ptr(png_ptr); - -Your replacement memory functions must have prototypes as follows: - - png_voidp malloc_fn(png_structp png_ptr, - png_size_t size); - void free_fn(png_structp png_ptr, png_voidp ptr); - -Your malloc_fn() must return NULL in case of failure. The png_malloc() -function will normally call png_error() if it receives a NULL from the -system memory allocator or from your replacement malloc_fn(). - -Input/Output in libpng is done through png_read() and png_write(), -which currently just call fread() and fwrite(). The FILE * is stored in -png_struct and is initialized via png_init_io(). If you wish to change -the method of I/O, the library supplies callbacks that you can set -through the function png_set_read_fn() and png_set_write_fn() at run -time, instead of calling the png_init_io() function. These functions -also provide a void pointer that can be retrieved via the function -png_get_io_ptr(). For example: - - png_set_read_fn(png_structp read_ptr, - voidp read_io_ptr, png_rw_ptr read_data_fn) - - png_set_write_fn(png_structp write_ptr, - voidp write_io_ptr, png_rw_ptr write_data_fn, - png_flush_ptr output_flush_fn); - - voidp read_io_ptr = png_get_io_ptr(read_ptr); - voidp write_io_ptr = png_get_io_ptr(write_ptr); - -The replacement I/O functions must have prototypes as follows: - - void user_read_data(png_structp png_ptr, - png_bytep data, png_size_t length); - void user_write_data(png_structp png_ptr, - png_bytep data, png_size_t length); - void user_flush_data(png_structp png_ptr); - -Supplying NULL for the read, write, or flush functions sets them back -to using the default C stream functions. It is an error to read from -a write stream, and vice versa. - -Error handling in libpng is done through png_error() and png_warning(). -Errors handled through png_error() are fatal, meaning that png_error() -should never return to its caller. Currently, this is handled via -setjmp() and longjmp() (unless you have compiled libpng with -PNG_SETJMP_NOT_SUPPORTED, in which case it is handled via PNG_ABORT()), -but you could change this to do things like exit() if you should wish. - -On non-fatal errors, png_warning() is called -to print a warning message, and then control returns to the calling code. -By default png_error() and png_warning() print a message on stderr via -fprintf() unless the library is compiled with PNG_NO_CONSOLE_IO defined -(because you don't want the messages) or PNG_NO_STDIO defined (because -fprintf() isn't available). If you wish to change the behavior of the error -functions, you will need to set up your own message callbacks. These -functions are normally supplied at the time that the png_struct is created. -It is also possible to redirect errors and warnings to your own replacement -functions after png_create_*_struct() has been called by calling: - - png_set_error_fn(png_structp png_ptr, - png_voidp error_ptr, png_error_ptr error_fn, - png_error_ptr warning_fn); - - png_voidp error_ptr = png_get_error_ptr(png_ptr); - -If NULL is supplied for either error_fn or warning_fn, then the libpng -default function will be used, calling fprintf() and/or longjmp() if a -problem is encountered. The replacement error functions should have -parameters as follows: - - void user_error_fn(png_structp png_ptr, - png_const_charp error_msg); - void user_warning_fn(png_structp png_ptr, - png_const_charp warning_msg); - -The motivation behind using setjmp() and longjmp() is the C++ throw and -catch exception handling methods. This makes the code much easier to write, -as there is no need to check every return code of every function call. -However, there are some uncertainties about the status of local variables -after a longjmp, so the user may want to be careful about doing anything after -setjmp returns non-zero besides returning itself. Consult your compiler -documentation for more details. For an alternative approach, you may wish -to use the "cexcept" facility (see http://cexcept.sourceforge.net). - -Custom chunks - -If you need to read or write custom chunks, you may need to get deeper -into the libpng code. The library now has mechanisms for storing -and writing chunks of unknown type; you can even declare callbacks -for custom chunks. However, this may not be good enough if the -library code itself needs to know about interactions between your -chunk and existing `intrinsic' chunks. - -If you need to write a new intrinsic chunk, first read the PNG -specification. Acquire a first level of -understanding of how it works. Pay particular attention to the -sections that describe chunk names, and look at how other chunks were -designed, so you can do things similarly. Second, check out the -sections of libpng that read and write chunks. Try to find a chunk -that is similar to yours and use it as a template. More details can -be found in the comments inside the code. It is best to handle unknown -chunks in a generic method, via callback functions, instead of by -modifying libpng functions. - -If you wish to write your own transformation for the data, look through -the part of the code that does the transformations, and check out some of -the simpler ones to get an idea of how they work. Try to find a similar -transformation to the one you want to add and copy off of it. More details -can be found in the comments inside the code itself. - -Configuring for 16 bit platforms - -You will want to look into zconf.h to tell zlib (and thus libpng) that -it cannot allocate more then 64K at a time. Even if you can, the memory -won't be accessible. So limit zlib and libpng to 64K by defining MAXSEG_64K. - -Configuring for DOS - -For DOS users who only have access to the lower 640K, you will -have to limit zlib's memory usage via a png_set_compression_mem_level() -call. See zlib.h or zconf.h in the zlib library for more information. - -Configuring for Medium Model - -Libpng's support for medium model has been tested on most of the popular -compilers. Make sure MAXSEG_64K gets defined, USE_FAR_KEYWORD gets -defined, and FAR gets defined to far in pngconf.h, and you should be -all set. Everything in the library (except for zlib's structure) is -expecting far data. You must use the typedefs with the p or pp on -the end for pointers (or at least look at them and be careful). Make -note that the rows of data are defined as png_bytepp, which is an -unsigned char far * far *. - -Configuring for gui/windowing platforms: - -You will need to write new error and warning functions that use the GUI -interface, as described previously, and set them to be the error and -warning functions at the time that png_create_*_struct() is called, -in order to have them available during the structure initialization. -They can be changed later via png_set_error_fn(). On some compilers, -you may also have to change the memory allocators (png_malloc, etc.). - -Configuring for compiler xxx: - -All includes for libpng are in pngconf.h. If you need to add/change/delete -an include, this is the place to do it. The includes that are not -needed outside libpng are protected by the PNG_INTERNAL definition, -which is only defined for those routines inside libpng itself. The -files in libpng proper only include png.h, which includes pngconf.h. - -Configuring zlib: - -There are special functions to configure the compression. Perhaps the -most useful one changes the compression level, which currently uses -input compression values in the range 0 - 9. The library normally -uses the default compression level (Z_DEFAULT_COMPRESSION = 6). Tests -have shown that for a large majority of images, compression values in -the range 3-6 compress nearly as well as higher levels, and do so much -faster. For online applications it may be desirable to have maximum speed -(Z_BEST_SPEED = 1). With versions of zlib after v0.99, you can also -specify no compression (Z_NO_COMPRESSION = 0), but this would create -files larger than just storing the raw bitmap. You can specify the -compression level by calling: - - png_set_compression_level(png_ptr, level); - -Another useful one is to reduce the memory level used by the library. -The memory level defaults to 8, but it can be lowered if you are -short on memory (running DOS, for example, where you only have 640K). -Note that the memory level does have an effect on compression; among -other things, lower levels will result in sections of incompressible -data being emitted in smaller stored blocks, with a correspondingly -larger relative overhead of up to 15% in the worst case. - - png_set_compression_mem_level(png_ptr, level); - -The other functions are for configuring zlib. They are not recommended -for normal use and may result in writing an invalid PNG file. See -zlib.h for more information on what these mean. - - png_set_compression_strategy(png_ptr, - strategy); - png_set_compression_window_bits(png_ptr, - window_bits); - png_set_compression_method(png_ptr, method); - png_set_compression_buffer_size(png_ptr, size); - -Controlling row filtering - -If you want to control whether libpng uses filtering or not, which -filters are used, and how it goes about picking row filters, you -can call one of these functions. The selection and configuration -of row filters can have a significant impact on the size and -encoding speed and a somewhat lesser impact on the decoding speed -of an image. Filtering is enabled by default for RGB and grayscale -images (with and without alpha), but not for paletted images nor -for any images with bit depths less than 8 bits/pixel. - -The 'method' parameter sets the main filtering method, which is -currently only '0' in the PNG 1.2 specification. The 'filters' -parameter sets which filter(s), if any, should be used for each -scanline. Possible values are PNG_ALL_FILTERS and PNG_NO_FILTERS -to turn filtering on and off, respectively. - -Individual filter types are PNG_FILTER_NONE, PNG_FILTER_SUB, -PNG_FILTER_UP, PNG_FILTER_AVG, PNG_FILTER_PAETH, which can be bitwise -ORed together with '|' to specify one or more filters to use. -These filters are described in more detail in the PNG specification. -If you intend to change the filter type during the course of writing -the image, you should start with flags set for all of the filters -you intend to use so that libpng can initialize its internal -structures appropriately for all of the filter types. (Note that this -means the first row must always be adaptively filtered, because libpng -currently does not allocate the filter buffers until png_write_row() -is called for the first time.) - - filters = PNG_FILTER_NONE | PNG_FILTER_SUB - PNG_FILTER_UP | PNG_FILTER_AVE | - PNG_FILTER_PAETH | PNG_ALL_FILTERS; - - png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, - filters); - The second parameter can also be - PNG_INTRAPIXEL_DIFFERENCING if you are - writing a PNG to be embedded in a MNG - datastream. This parameter must be the - same as the value of filter_method used - in png_set_IHDR(). - -It is also possible to influence how libpng chooses from among the -available filters. This is done in one or both of two ways - by -telling it how important it is to keep the same filter for successive -rows, and by telling it the relative computational costs of the filters. - - double weights[3] = {1.5, 1.3, 1.1}, - costs[PNG_FILTER_VALUE_LAST] = - {1.0, 1.3, 1.3, 1.5, 1.7}; - - png_set_filter_heuristics(png_ptr, - PNG_FILTER_HEURISTIC_WEIGHTED, 3, - weights, costs); - -The weights are multiplying factors that indicate to libpng that the -row filter should be the same for successive rows unless another row filter -is that many times better than the previous filter. In the above example, -if the previous 3 filters were SUB, SUB, NONE, the SUB filter could have a -"sum of absolute differences" 1.5 x 1.3 times higher than other filters -and still be chosen, while the NONE filter could have a sum 1.1 times -higher than other filters and still be chosen. Unspecified weights are -taken to be 1.0, and the specified weights should probably be declining -like those above in order to emphasize recent filters over older filters. - -The filter costs specify for each filter type a relative decoding cost -to be considered when selecting row filters. This means that filters -with higher costs are less likely to be chosen over filters with lower -costs, unless their "sum of absolute differences" is that much smaller. -The costs do not necessarily reflect the exact computational speeds of -the various filters, since this would unduly influence the final image -size. - -Note that the numbers above were invented purely for this example and -are given only to help explain the function usage. Little testing has -been done to find optimum values for either the costs or the weights. - -Removing unwanted object code - -There are a bunch of #define's in pngconf.h that control what parts of -libpng are compiled. All the defines end in _SUPPORTED. If you are -never going to use a capability, you can change the #define to #undef -before recompiling libpng and save yourself code and data space, or -you can turn off individual capabilities with defines that begin with -PNG_NO_. - -You can also turn all of the transforms and ancillary chunk capabilities -off en masse with compiler directives that define -PNG_NO_READ[or WRITE]_TRANSFORMS, or PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS, -or all four, -along with directives to turn on any of the capabilities that you do -want. The PNG_NO_READ[or WRITE]_TRANSFORMS directives disable -the extra transformations but still leave the library fully capable of reading -and writing PNG files with all known public chunks -Use of the PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS directive -produces a library that is incapable of reading or writing ancillary chunks. -If you are not using the progressive reading capability, you can -turn that off with PNG_NO_PROGRESSIVE_READ (don't confuse -this with the INTERLACING capability, which you'll still have). - -All the reading and writing specific code are in separate files, so the -linker should only grab the files it needs. However, if you want to -make sure, or if you are building a stand alone library, all the -reading files start with pngr and all the writing files start with -pngw. The files that don't match either (like png.c, pngtrans.c, etc.) -are used for both reading and writing, and always need to be included. -The progressive reader is in pngpread.c - -If you are creating or distributing a dynamically linked library (a .so -or DLL file), you should not remove or disable any parts of the library, -as this will cause applications linked with different versions of the -library to fail if they call functions not available in your library. -The size of the library itself should not be an issue, because only -those sections that are actually used will be loaded into memory. - -Requesting debug printout - -The macro definition PNG_DEBUG can be used to request debugging -printout. Set it to an integer value in the range 0 to 3. Higher -numbers result in increasing amounts of debugging information. The -information is printed to the "stderr" file, unless another file -name is specified in the PNG_DEBUG_FILE macro definition. - -When PNG_DEBUG > 0, the following functions (macros) become available: - - png_debug(level, message) - png_debug1(level, message, p1) - png_debug2(level, message, p1, p2) - -in which "level" is compared to PNG_DEBUG to decide whether to print -the message, "message" is the formatted string to be printed, -and p1 and p2 are parameters that are to be embedded in the string -according to printf-style formatting directives. For example, - - png_debug1(2, "foo=%d\n", foo); - -is expanded to - - if(PNG_DEBUG > 2) - fprintf(PNG_DEBUG_FILE, "foo=%d\n", foo); - -When PNG_DEBUG is defined but is zero, the macros aren't defined, but you -can still use PNG_DEBUG to control your own debugging: - - #ifdef PNG_DEBUG - fprintf(stderr, ... - #endif - -When PNG_DEBUG = 1, the macros are defined, but only png_debug statements -having level = 0 will be printed. There aren't any such statements in -this version of libpng, but if you insert some they will be printed. - -VII. MNG support - -The MNG specification (available at http://www.libpng.org/pub/mng) allows -certain extensions to PNG for PNG images that are embedded in MNG datastreams. -Libpng can support some of these extensions. To enable them, use the -png_permit_mng_features() function: - - feature_set = png_permit_mng_features(png_ptr, mask) - mask is a png_uint_32 containing the bitwise OR of the - features you want to enable. These include - PNG_FLAG_MNG_EMPTY_PLTE - PNG_FLAG_MNG_FILTER_64 - PNG_ALL_MNG_FEATURES - feature_set is a png_uint_32 that is the bitwise AND of - your mask with the set of MNG features that is - supported by the version of libpng that you are using. - -It is an error to use this function when reading or writing a standalone -PNG file with the PNG 8-byte signature. The PNG datastream must be wrapped -in a MNG datastream. As a minimum, it must have the MNG 8-byte signature -and the MHDR and MEND chunks. Libpng does not provide support for these -or any other MNG chunks; your application must provide its own support for -them. You may wish to consider using libmng (available at -http://www.libmng.com) instead. - -VIII. Changes to Libpng from version 0.88 - -It should be noted that versions of libpng later than 0.96 are not -distributed by the original libpng author, Guy Schalnat, nor by -Andreas Dilger, who had taken over from Guy during 1996 and 1997, and -distributed versions 0.89 through 0.96, but rather by another member -of the original PNG Group, Glenn Randers-Pehrson. Guy and Andreas are -still alive and well, but they have moved on to other things. - -The old libpng functions png_read_init(), png_write_init(), -png_info_init(), png_read_destroy(), and png_write_destroy() have been -moved to PNG_INTERNAL in version 0.95 to discourage their use. These -functions will be removed from libpng version 2.0.0. - -The preferred method of creating and initializing the libpng structures is -via the png_create_read_struct(), png_create_write_struct(), and -png_create_info_struct() because they isolate the size of the structures -from the application, allow version error checking, and also allow the -use of custom error handling routines during the initialization, which -the old functions do not. The functions png_read_destroy() and -png_write_destroy() do not actually free the memory that libpng -allocated for these structs, but just reset the data structures, so they -can be used instead of png_destroy_read_struct() and -png_destroy_write_struct() if you feel there is too much system overhead -allocating and freeing the png_struct for each image read. - -Setting the error callbacks via png_set_message_fn() before -png_read_init() as was suggested in libpng-0.88 is no longer supported -because this caused applications that do not use custom error functions -to fail if the png_ptr was not initialized to zero. It is still possible -to set the error callbacks AFTER png_read_init(), or to change them with -png_set_error_fn(), which is essentially the same function, but with a new -name to force compilation errors with applications that try to use the old -method. - -Starting with version 1.0.7, you can find out which version of the library -you are using at run-time: - - png_uint_32 libpng_vn = png_access_version_number(); - -The number libpng_vn is constructed from the major version, minor -version with leading zero, and release number with leading zero, -(e.g., libpng_vn for version 1.0.7 is 10007). - -You can also check which version of png.h you used when compiling your -application: - - png_uint_32 application_vn = PNG_LIBPNG_VER; - -IX. Y2K Compliance in libpng - -December 14, 2007 - -Since the PNG Development group is an ad-hoc body, we can't make -an official declaration. - -This is your unofficial assurance that libpng from version 0.71 and -upward through 1.2.24 are Y2K compliant. It is my belief that earlier -versions were also Y2K compliant. - -Libpng only has three year fields. One is a 2-byte unsigned integer that -will hold years up to 65535. The other two hold the date in text -format, and will hold years up to 9999. - -The integer is - "png_uint_16 year" in png_time_struct. - -The strings are - "png_charp time_buffer" in png_struct and - "near_time_buffer", which is a local character string in png.c. - -There are seven time-related functions: - - png_convert_to_rfc_1123() in png.c - (formerly png_convert_to_rfc_1152() in error) - png_convert_from_struct_tm() in pngwrite.c, called - in pngwrite.c - png_convert_from_time_t() in pngwrite.c - png_get_tIME() in pngget.c - png_handle_tIME() in pngrutil.c, called in pngread.c - png_set_tIME() in pngset.c - png_write_tIME() in pngwutil.c, called in pngwrite.c - -All appear to handle dates properly in a Y2K environment. The -png_convert_from_time_t() function calls gmtime() to convert from system -clock time, which returns (year - 1900), which we properly convert to -the full 4-digit year. There is a possibility that applications using -libpng are not passing 4-digit years into the png_convert_to_rfc_1123() -function, or that they are incorrectly passing only a 2-digit year -instead of "year - 1900" into the png_convert_from_struct_tm() function, -but this is not under our control. The libpng documentation has always -stated that it works with 4-digit years, and the APIs have been -documented as such. - -The tIME chunk itself is also Y2K compliant. It uses a 2-byte unsigned -integer to hold the year, and can hold years as large as 65535. - -zlib, upon which libpng depends, is also Y2K compliant. It contains -no date-related code. - - - Glenn Randers-Pehrson - libpng maintainer - PNG Development Group diff --git a/rosapps/lib/libpng/libpng.rbuild b/rosapps/lib/libpng/libpng.rbuild deleted file mode 100644 index aa2fb25ff86..00000000000 --- a/rosapps/lib/libpng/libpng.rbuild +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - . - lib/3rdparty/zlib - png.c - pngerror.c - pnggccrd.c - pngget.c - pngmem.c - pngpread.c - pngread.c - pngrio.c - pngrtran.c - pngrutil.c - pngset.c - pngtest.c - pngtrans.c - pngvcrd.c - pngwio.c - pngwrite.c - pngwtran.c - pngwutil.c - \ No newline at end of file diff --git a/rosapps/lib/libpng/png.c b/rosapps/lib/libpng/png.c deleted file mode 100644 index 4d25559cf1d..00000000000 --- a/rosapps/lib/libpng/png.c +++ /dev/null @@ -1,798 +0,0 @@ - -/* png.c - location for general purpose libpng functions - * - * Last changed in libpng 1.2.21 October 4, 2007 - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2007 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - */ - -#define PNG_INTERNAL -#define PNG_NO_EXTERN -#include "png.h" - -/* Generate a compiler error if there is an old png.h in the search path. */ -typedef version_1_2_24 Your_png_h_is_not_version_1_2_24; - -/* Version information for C files. This had better match the version - * string defined in png.h. */ - -#ifdef PNG_USE_GLOBAL_ARRAYS -/* png_libpng_ver was changed to a function in version 1.0.5c */ -PNG_CONST char png_libpng_ver[18] = PNG_LIBPNG_VER_STRING; - -#ifdef PNG_READ_SUPPORTED - -/* png_sig was changed to a function in version 1.0.5c */ -/* Place to hold the signature string for a PNG file. */ -PNG_CONST png_byte FARDATA png_sig[8] = {137, 80, 78, 71, 13, 10, 26, 10}; -#endif /* PNG_READ_SUPPORTED */ - -/* Invoke global declarations for constant strings for known chunk types */ -PNG_IHDR; -PNG_IDAT; -PNG_IEND; -PNG_PLTE; -PNG_bKGD; -PNG_cHRM; -PNG_gAMA; -PNG_hIST; -PNG_iCCP; -PNG_iTXt; -PNG_oFFs; -PNG_pCAL; -PNG_sCAL; -PNG_pHYs; -PNG_sBIT; -PNG_sPLT; -PNG_sRGB; -PNG_tEXt; -PNG_tIME; -PNG_tRNS; -PNG_zTXt; - -#ifdef PNG_READ_SUPPORTED -/* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - -/* start of interlace block */ -PNG_CONST int FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; - -/* offset to next interlace block */ -PNG_CONST int FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; - -/* start of interlace block in the y direction */ -PNG_CONST int FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1}; - -/* offset to next interlace block in the y direction */ -PNG_CONST int FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2}; - -/* Height of interlace block. This is not currently used - if you need - * it, uncomment it here and in png.h -PNG_CONST int FARDATA png_pass_height[] = {8, 8, 4, 4, 2, 2, 1}; -*/ - -/* Mask to determine which pixels are valid in a pass */ -PNG_CONST int FARDATA png_pass_mask[] = {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff}; - -/* Mask to determine which pixels to overwrite while displaying */ -PNG_CONST int FARDATA png_pass_dsp_mask[] - = {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff}; - -#endif /* PNG_READ_SUPPORTED */ -#endif /* PNG_USE_GLOBAL_ARRAYS */ - -/* Tells libpng that we have already handled the first "num_bytes" bytes - * of the PNG file signature. If the PNG data is embedded into another - * stream we can set num_bytes = 8 so that libpng will not attempt to read - * or write any of the magic bytes before it starts on the IHDR. - */ - -#ifdef PNG_READ_SUPPORTED -void PNGAPI -png_set_sig_bytes(png_structp png_ptr, int num_bytes) -{ - if(png_ptr == NULL) return; - png_debug(1, "in png_set_sig_bytes\n"); - if (num_bytes > 8) - png_error(png_ptr, "Too many bytes for PNG signature."); - - png_ptr->sig_bytes = (png_byte)(num_bytes < 0 ? 0 : num_bytes); -} - -/* Checks whether the supplied bytes match the PNG signature. We allow - * checking less than the full 8-byte signature so that those apps that - * already read the first few bytes of a file to determine the file type - * can simply check the remaining bytes for extra assurance. Returns - * an integer less than, equal to, or greater than zero if sig is found, - * respectively, to be less than, to match, or be greater than the correct - * PNG signature (this is the same behaviour as strcmp, memcmp, etc). - */ -int PNGAPI -png_sig_cmp(png_bytep sig, png_size_t start, png_size_t num_to_check) -{ - png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; - if (num_to_check > 8) - num_to_check = 8; - else if (num_to_check < 1) - return (-1); - - if (start > 7) - return (-1); - - if (start + num_to_check > 8) - num_to_check = 8 - start; - - return ((int)(png_memcmp(&sig[start], &png_signature[start], num_to_check))); -} - -#if defined(PNG_1_0_X) || defined(PNG_1_2_X) -/* (Obsolete) function to check signature bytes. It does not allow one - * to check a partial signature. This function might be removed in the - * future - use png_sig_cmp(). Returns true (nonzero) if the file is PNG. - */ -int PNGAPI -png_check_sig(png_bytep sig, int num) -{ - return ((int)!png_sig_cmp(sig, (png_size_t)0, (png_size_t)num)); -} -#endif -#endif /* PNG_READ_SUPPORTED */ - -#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) -/* Function to allocate memory for zlib and clear it to 0. */ -#ifdef PNG_1_0_X -voidpf PNGAPI -#else -voidpf /* private */ -#endif -png_zalloc(voidpf png_ptr, uInt items, uInt size) -{ - png_voidp ptr; - png_structp p=(png_structp)png_ptr; - png_uint_32 save_flags=p->flags; - png_uint_32 num_bytes; - - if(png_ptr == NULL) return (NULL); - if (items > PNG_UINT_32_MAX/size) - { - png_warning (p, "Potential overflow in png_zalloc()"); - return (NULL); - } - num_bytes = (png_uint_32)items * size; - - p->flags|=PNG_FLAG_MALLOC_NULL_MEM_OK; - ptr = (png_voidp)png_malloc((png_structp)png_ptr, num_bytes); - p->flags=save_flags; - -#if defined(PNG_1_0_X) && !defined(PNG_NO_ZALLOC_ZERO) - if (ptr == NULL) - return ((voidpf)ptr); - - if (num_bytes > (png_uint_32)0x8000L) - { - png_memset(ptr, 0, (png_size_t)0x8000L); - png_memset((png_bytep)ptr + (png_size_t)0x8000L, 0, - (png_size_t)(num_bytes - (png_uint_32)0x8000L)); - } - else - { - png_memset(ptr, 0, (png_size_t)num_bytes); - } -#endif - return ((voidpf)ptr); -} - -/* function to free memory for zlib */ -#ifdef PNG_1_0_X -void PNGAPI -#else -void /* private */ -#endif -png_zfree(voidpf png_ptr, voidpf ptr) -{ - png_free((png_structp)png_ptr, (png_voidp)ptr); -} - -/* Reset the CRC variable to 32 bits of 1's. Care must be taken - * in case CRC is > 32 bits to leave the top bits 0. - */ -void /* PRIVATE */ -png_reset_crc(png_structp png_ptr) -{ - png_ptr->crc = crc32(0, Z_NULL, 0); -} - -/* Calculate the CRC over a section of data. We can only pass as - * much data to this routine as the largest single buffer size. We - * also check that this data will actually be used before going to the - * trouble of calculating it. - */ -void /* PRIVATE */ -png_calculate_crc(png_structp png_ptr, png_bytep ptr, png_size_t length) -{ - int need_crc = 1; - - if (png_ptr->chunk_name[0] & 0x20) /* ancillary */ - { - if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) == - (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN)) - need_crc = 0; - } - else /* critical */ - { - if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) - need_crc = 0; - } - - if (need_crc) - png_ptr->crc = crc32(png_ptr->crc, ptr, (uInt)length); -} - -/* Allocate the memory for an info_struct for the application. We don't - * really need the png_ptr, but it could potentially be useful in the - * future. This should be used in favour of malloc(png_sizeof(png_info)) - * and png_info_init() so that applications that want to use a shared - * libpng don't have to be recompiled if png_info changes size. - */ -png_infop PNGAPI -png_create_info_struct(png_structp png_ptr) -{ - png_infop info_ptr; - - png_debug(1, "in png_create_info_struct\n"); - if(png_ptr == NULL) return (NULL); -#ifdef PNG_USER_MEM_SUPPORTED - info_ptr = (png_infop)png_create_struct_2(PNG_STRUCT_INFO, - png_ptr->malloc_fn, png_ptr->mem_ptr); -#else - info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO); -#endif - if (info_ptr != NULL) - png_info_init_3(&info_ptr, png_sizeof(png_info)); - - return (info_ptr); -} - -/* This function frees the memory associated with a single info struct. - * Normally, one would use either png_destroy_read_struct() or - * png_destroy_write_struct() to free an info struct, but this may be - * useful for some applications. - */ -void PNGAPI -png_destroy_info_struct(png_structp png_ptr, png_infopp info_ptr_ptr) -{ - png_infop info_ptr = NULL; - if(png_ptr == NULL) return; - - png_debug(1, "in png_destroy_info_struct\n"); - if (info_ptr_ptr != NULL) - info_ptr = *info_ptr_ptr; - - if (info_ptr != NULL) - { - png_info_destroy(png_ptr, info_ptr); - -#ifdef PNG_USER_MEM_SUPPORTED - png_destroy_struct_2((png_voidp)info_ptr, png_ptr->free_fn, - png_ptr->mem_ptr); -#else - png_destroy_struct((png_voidp)info_ptr); -#endif - *info_ptr_ptr = NULL; - } -} - -/* Initialize the info structure. This is now an internal function (0.89) - * and applications using it are urged to use png_create_info_struct() - * instead. - */ -#if defined(PNG_1_0_X) || defined(PNG_1_2_X) -#undef png_info_init -void PNGAPI -png_info_init(png_infop info_ptr) -{ - /* We only come here via pre-1.0.12-compiled applications */ - png_info_init_3(&info_ptr, 0); -} -#endif - -void PNGAPI -png_info_init_3(png_infopp ptr_ptr, png_size_t png_info_struct_size) -{ - png_infop info_ptr = *ptr_ptr; - - if(info_ptr == NULL) return; - - png_debug(1, "in png_info_init_3\n"); - - if(png_sizeof(png_info) > png_info_struct_size) - { - png_destroy_struct(info_ptr); - info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO); - *ptr_ptr = info_ptr; - } - - /* set everything to 0 */ - png_memset(info_ptr, 0, png_sizeof (png_info)); -} - -#ifdef PNG_FREE_ME_SUPPORTED -void PNGAPI -png_data_freer(png_structp png_ptr, png_infop info_ptr, - int freer, png_uint_32 mask) -{ - png_debug(1, "in png_data_freer\n"); - if (png_ptr == NULL || info_ptr == NULL) - return; - if(freer == PNG_DESTROY_WILL_FREE_DATA) - info_ptr->free_me |= mask; - else if(freer == PNG_USER_WILL_FREE_DATA) - info_ptr->free_me &= ~mask; - else - png_warning(png_ptr, - "Unknown freer parameter in png_data_freer."); -} -#endif - -void PNGAPI -png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask, - int num) -{ - png_debug(1, "in png_free_data\n"); - if (png_ptr == NULL || info_ptr == NULL) - return; - -#if defined(PNG_TEXT_SUPPORTED) -/* free text item num or (if num == -1) all text items */ -#ifdef PNG_FREE_ME_SUPPORTED -if ((mask & PNG_FREE_TEXT) & info_ptr->free_me) -#else -if (mask & PNG_FREE_TEXT) -#endif -{ - if (num != -1) - { - if (info_ptr->text && info_ptr->text[num].key) - { - png_free(png_ptr, info_ptr->text[num].key); - info_ptr->text[num].key = NULL; - } - } - else - { - int i; - for (i = 0; i < info_ptr->num_text; i++) - png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, i); - png_free(png_ptr, info_ptr->text); - info_ptr->text = NULL; - info_ptr->num_text=0; - } -} -#endif - -#if defined(PNG_tRNS_SUPPORTED) -/* free any tRNS entry */ -#ifdef PNG_FREE_ME_SUPPORTED -if ((mask & PNG_FREE_TRNS) & info_ptr->free_me) -#else -if ((mask & PNG_FREE_TRNS) && (png_ptr->flags & PNG_FLAG_FREE_TRNS)) -#endif -{ - png_free(png_ptr, info_ptr->trans); - info_ptr->valid &= ~PNG_INFO_tRNS; -#ifndef PNG_FREE_ME_SUPPORTED - png_ptr->flags &= ~PNG_FLAG_FREE_TRNS; -#endif - info_ptr->trans = NULL; -} -#endif - -#if defined(PNG_sCAL_SUPPORTED) -/* free any sCAL entry */ -#ifdef PNG_FREE_ME_SUPPORTED -if ((mask & PNG_FREE_SCAL) & info_ptr->free_me) -#else -if (mask & PNG_FREE_SCAL) -#endif -{ -#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED) - png_free(png_ptr, info_ptr->scal_s_width); - png_free(png_ptr, info_ptr->scal_s_height); - info_ptr->scal_s_width = NULL; - info_ptr->scal_s_height = NULL; -#endif - info_ptr->valid &= ~PNG_INFO_sCAL; -} -#endif - -#if defined(PNG_pCAL_SUPPORTED) -/* free any pCAL entry */ -#ifdef PNG_FREE_ME_SUPPORTED -if ((mask & PNG_FREE_PCAL) & info_ptr->free_me) -#else -if (mask & PNG_FREE_PCAL) -#endif -{ - png_free(png_ptr, info_ptr->pcal_purpose); - png_free(png_ptr, info_ptr->pcal_units); - info_ptr->pcal_purpose = NULL; - info_ptr->pcal_units = NULL; - if (info_ptr->pcal_params != NULL) - { - int i; - for (i = 0; i < (int)info_ptr->pcal_nparams; i++) - { - png_free(png_ptr, info_ptr->pcal_params[i]); - info_ptr->pcal_params[i]=NULL; - } - png_free(png_ptr, info_ptr->pcal_params); - info_ptr->pcal_params = NULL; - } - info_ptr->valid &= ~PNG_INFO_pCAL; -} -#endif - -#if defined(PNG_iCCP_SUPPORTED) -/* free any iCCP entry */ -#ifdef PNG_FREE_ME_SUPPORTED -if ((mask & PNG_FREE_ICCP) & info_ptr->free_me) -#else -if (mask & PNG_FREE_ICCP) -#endif -{ - png_free(png_ptr, info_ptr->iccp_name); - png_free(png_ptr, info_ptr->iccp_profile); - info_ptr->iccp_name = NULL; - info_ptr->iccp_profile = NULL; - info_ptr->valid &= ~PNG_INFO_iCCP; -} -#endif - -#if defined(PNG_sPLT_SUPPORTED) -/* free a given sPLT entry, or (if num == -1) all sPLT entries */ -#ifdef PNG_FREE_ME_SUPPORTED -if ((mask & PNG_FREE_SPLT) & info_ptr->free_me) -#else -if (mask & PNG_FREE_SPLT) -#endif -{ - if (num != -1) - { - if(info_ptr->splt_palettes) - { - png_free(png_ptr, info_ptr->splt_palettes[num].name); - png_free(png_ptr, info_ptr->splt_palettes[num].entries); - info_ptr->splt_palettes[num].name = NULL; - info_ptr->splt_palettes[num].entries = NULL; - } - } - else - { - if(info_ptr->splt_palettes_num) - { - int i; - for (i = 0; i < (int)info_ptr->splt_palettes_num; i++) - png_free_data(png_ptr, info_ptr, PNG_FREE_SPLT, i); - - png_free(png_ptr, info_ptr->splt_palettes); - info_ptr->splt_palettes = NULL; - info_ptr->splt_palettes_num = 0; - } - info_ptr->valid &= ~PNG_INFO_sPLT; - } -} -#endif - -#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) - if(png_ptr->unknown_chunk.data) - { - png_free(png_ptr, png_ptr->unknown_chunk.data); - png_ptr->unknown_chunk.data = NULL; - } -#ifdef PNG_FREE_ME_SUPPORTED -if ((mask & PNG_FREE_UNKN) & info_ptr->free_me) -#else -if (mask & PNG_FREE_UNKN) -#endif -{ - if (num != -1) - { - if(info_ptr->unknown_chunks) - { - png_free(png_ptr, info_ptr->unknown_chunks[num].data); - info_ptr->unknown_chunks[num].data = NULL; - } - } - else - { - int i; - - if(info_ptr->unknown_chunks_num) - { - for (i = 0; i < (int)info_ptr->unknown_chunks_num; i++) - png_free_data(png_ptr, info_ptr, PNG_FREE_UNKN, i); - - png_free(png_ptr, info_ptr->unknown_chunks); - info_ptr->unknown_chunks = NULL; - info_ptr->unknown_chunks_num = 0; - } - } -} -#endif - -#if defined(PNG_hIST_SUPPORTED) -/* free any hIST entry */ -#ifdef PNG_FREE_ME_SUPPORTED -if ((mask & PNG_FREE_HIST) & info_ptr->free_me) -#else -if ((mask & PNG_FREE_HIST) && (png_ptr->flags & PNG_FLAG_FREE_HIST)) -#endif -{ - png_free(png_ptr, info_ptr->hist); - info_ptr->hist = NULL; - info_ptr->valid &= ~PNG_INFO_hIST; -#ifndef PNG_FREE_ME_SUPPORTED - png_ptr->flags &= ~PNG_FLAG_FREE_HIST; -#endif -} -#endif - -/* free any PLTE entry that was internally allocated */ -#ifdef PNG_FREE_ME_SUPPORTED -if ((mask & PNG_FREE_PLTE) & info_ptr->free_me) -#else -if ((mask & PNG_FREE_PLTE) && (png_ptr->flags & PNG_FLAG_FREE_PLTE)) -#endif -{ - png_zfree(png_ptr, info_ptr->palette); - info_ptr->palette = NULL; - info_ptr->valid &= ~PNG_INFO_PLTE; -#ifndef PNG_FREE_ME_SUPPORTED - png_ptr->flags &= ~PNG_FLAG_FREE_PLTE; -#endif - info_ptr->num_palette = 0; -} - -#if defined(PNG_INFO_IMAGE_SUPPORTED) -/* free any image bits attached to the info structure */ -#ifdef PNG_FREE_ME_SUPPORTED -if ((mask & PNG_FREE_ROWS) & info_ptr->free_me) -#else -if (mask & PNG_FREE_ROWS) -#endif -{ - if(info_ptr->row_pointers) - { - int row; - for (row = 0; row < (int)info_ptr->height; row++) - { - png_free(png_ptr, info_ptr->row_pointers[row]); - info_ptr->row_pointers[row]=NULL; - } - png_free(png_ptr, info_ptr->row_pointers); - info_ptr->row_pointers=NULL; - } - info_ptr->valid &= ~PNG_INFO_IDAT; -} -#endif - -#ifdef PNG_FREE_ME_SUPPORTED - if(num == -1) - info_ptr->free_me &= ~mask; - else - info_ptr->free_me &= ~(mask & ~PNG_FREE_MUL); -#endif -} - -/* This is an internal routine to free any memory that the info struct is - * pointing to before re-using it or freeing the struct itself. Recall - * that png_free() checks for NULL pointers for us. - */ -void /* PRIVATE */ -png_info_destroy(png_structp png_ptr, png_infop info_ptr) -{ - png_debug(1, "in png_info_destroy\n"); - - png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); - -#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) - if (png_ptr->num_chunk_list) - { - png_free(png_ptr, png_ptr->chunk_list); - png_ptr->chunk_list=NULL; - png_ptr->num_chunk_list=0; - } -#endif - - png_info_init_3(&info_ptr, png_sizeof(png_info)); -} -#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ - -/* This function returns a pointer to the io_ptr associated with the user - * functions. The application should free any memory associated with this - * pointer before png_write_destroy() or png_read_destroy() are called. - */ -png_voidp PNGAPI -png_get_io_ptr(png_structp png_ptr) -{ - if(png_ptr == NULL) return (NULL); - return (png_ptr->io_ptr); -} - -#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) -#if !defined(PNG_NO_STDIO) -/* Initialize the default input/output functions for the PNG file. If you - * use your own read or write routines, you can call either png_set_read_fn() - * or png_set_write_fn() instead of png_init_io(). If you have defined - * PNG_NO_STDIO, you must use a function of your own because "FILE *" isn't - * necessarily available. - */ -void PNGAPI -png_init_io(png_structp png_ptr, png_FILE_p fp) -{ - png_debug(1, "in png_init_io\n"); - if(png_ptr == NULL) return; - png_ptr->io_ptr = (png_voidp)fp; -} -#endif - -#if defined(PNG_TIME_RFC1123_SUPPORTED) -/* Convert the supplied time into an RFC 1123 string suitable for use in - * a "Creation Time" or other text-based time string. - */ -png_charp PNGAPI -png_convert_to_rfc1123(png_structp png_ptr, png_timep ptime) -{ - static PNG_CONST char short_months[12][4] = - {"Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; - - if(png_ptr == NULL) return (NULL); - if (png_ptr->time_buffer == NULL) - { - png_ptr->time_buffer = (png_charp)png_malloc(png_ptr, (png_uint_32)(29* - png_sizeof(char))); - } - -#if defined(_WIN32_WCE) - { - wchar_t time_buf[29]; - wsprintf(time_buf, TEXT("%d %S %d %02d:%02d:%02d +0000"), - ptime->day % 32, short_months[(ptime->month - 1) % 12], - ptime->year, ptime->hour % 24, ptime->minute % 60, - ptime->second % 61); - WideCharToMultiByte(CP_ACP, 0, time_buf, -1, png_ptr->time_buffer, 29, - NULL, NULL); - } -#else -#ifdef USE_FAR_KEYWORD - { - char near_time_buf[29]; - png_snprintf6(near_time_buf,29,"%d %s %d %02d:%02d:%02d +0000", - ptime->day % 32, short_months[(ptime->month - 1) % 12], - ptime->year, ptime->hour % 24, ptime->minute % 60, - ptime->second % 61); - png_memcpy(png_ptr->time_buffer, near_time_buf, - 29*png_sizeof(char)); - } -#else - png_snprintf6(png_ptr->time_buffer,29,"%d %s %d %02d:%02d:%02d +0000", - ptime->day % 32, short_months[(ptime->month - 1) % 12], - ptime->year, ptime->hour % 24, ptime->minute % 60, - ptime->second % 61); -#endif -#endif /* _WIN32_WCE */ - return ((png_charp)png_ptr->time_buffer); -} -#endif /* PNG_TIME_RFC1123_SUPPORTED */ - -#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ - -png_charp PNGAPI -png_get_copyright(png_structp png_ptr) -{ - png_ptr = png_ptr; /* silence compiler warning about unused png_ptr */ - return ((png_charp) "\n libpng version 1.2.24 - December 14, 2007\n\ - Copyright (c) 1998-2007 Glenn Randers-Pehrson\n\ - Copyright (c) 1996-1997 Andreas Dilger\n\ - Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.\n"); -} - -/* The following return the library version as a short string in the - * format 1.0.0 through 99.99.99zz. To get the version of *.h files - * used with your application, print out PNG_LIBPNG_VER_STRING, which - * is defined in png.h. - * Note: now there is no difference between png_get_libpng_ver() and - * png_get_header_ver(). Due to the version_nn_nn_nn typedef guard, - * it is guaranteed that png.c uses the correct version of png.h. - */ -png_charp PNGAPI -png_get_libpng_ver(png_structp png_ptr) -{ - /* Version of *.c files used when building libpng */ - png_ptr = png_ptr; /* silence compiler warning about unused png_ptr */ - return ((png_charp) PNG_LIBPNG_VER_STRING); -} - -png_charp PNGAPI -png_get_header_ver(png_structp png_ptr) -{ - /* Version of *.h files used when building libpng */ - png_ptr = png_ptr; /* silence compiler warning about unused png_ptr */ - return ((png_charp) PNG_LIBPNG_VER_STRING); -} - -png_charp PNGAPI -png_get_header_version(png_structp png_ptr) -{ - /* Returns longer string containing both version and date */ - png_ptr = png_ptr; /* silence compiler warning about unused png_ptr */ - return ((png_charp) PNG_HEADER_VERSION_STRING -#ifndef PNG_READ_SUPPORTED - " (NO READ SUPPORT)" -#endif - "\n"); -} - -#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) -#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED -int PNGAPI -png_handle_as_unknown(png_structp png_ptr, png_bytep chunk_name) -{ - /* check chunk_name and return "keep" value if it's on the list, else 0 */ - int i; - png_bytep p; - if(png_ptr == NULL || chunk_name == NULL || png_ptr->num_chunk_list<=0) - return 0; - p=png_ptr->chunk_list+png_ptr->num_chunk_list*5-5; - for (i = png_ptr->num_chunk_list; i; i--, p-=5) - if (!png_memcmp(chunk_name, p, 4)) - return ((int)*(p+4)); - return 0; -} -#endif - -/* This function, added to libpng-1.0.6g, is untested. */ -int PNGAPI -png_reset_zstream(png_structp png_ptr) -{ - if (png_ptr == NULL) return Z_STREAM_ERROR; - return (inflateReset(&png_ptr->zstream)); -} -#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ - -/* This function was added to libpng-1.0.7 */ -png_uint_32 PNGAPI -png_access_version_number(void) -{ - /* Version of *.c files used when building libpng */ - return((png_uint_32) PNG_LIBPNG_VER); -} - - -#if defined(PNG_READ_SUPPORTED) && defined(PNG_ASSEMBLER_CODE_SUPPORTED) -#if !defined(PNG_1_0_X) -/* this function was added to libpng 1.2.0 */ -int PNGAPI -png_mmx_support(void) -{ - /* obsolete, to be removed from libpng-1.4.0 */ - return -1; -} -#endif /* PNG_1_0_X */ -#endif /* PNG_READ_SUPPORTED && PNG_ASSEMBLER_CODE_SUPPORTED */ - -#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) -#ifdef PNG_SIZE_T -/* Added at libpng version 1.2.6 */ - PNG_EXTERN png_size_t PNGAPI png_convert_size PNGARG((size_t size)); -png_size_t PNGAPI -png_convert_size(size_t size) -{ - if (size > (png_size_t)-1) - PNG_ABORT(); /* We haven't got access to png_ptr, so no png_error() */ - return ((png_size_t)size); -} -#endif /* PNG_SIZE_T */ -#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ diff --git a/rosapps/lib/libpng/png.h b/rosapps/lib/libpng/png.h deleted file mode 100644 index 3ac393ea343..00000000000 --- a/rosapps/lib/libpng/png.h +++ /dev/null @@ -1,3549 +0,0 @@ - -/* png.h - header file for PNG reference library - * - * libpng version 1.2.24 - December 14, 2007 - * Copyright (c) 1998-2007 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * Authors and maintainers: - * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat - * libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger - * libpng versions 0.97, January 1998, through 1.2.24 - December 14, 2007: Glenn - * See also "Contributing Authors", below. - * - * Note about libpng version numbers: - * - * Due to various miscommunications, unforeseen code incompatibilities - * and occasional factors outside the authors' control, version numbering - * on the library has not always been consistent and straightforward. - * The following table summarizes matters since version 0.89c, which was - * the first widely used release: - * - * source png.h png.h shared-lib - * version string int version - * ------- ------ ----- ---------- - * 0.89c "1.0 beta 3" 0.89 89 1.0.89 - * 0.90 "1.0 beta 4" 0.90 90 0.90 [should have been 2.0.90] - * 0.95 "1.0 beta 5" 0.95 95 0.95 [should have been 2.0.95] - * 0.96 "1.0 beta 6" 0.96 96 0.96 [should have been 2.0.96] - * 0.97b "1.00.97 beta 7" 1.00.97 97 1.0.1 [should have been 2.0.97] - * 0.97c 0.97 97 2.0.97 - * 0.98 0.98 98 2.0.98 - * 0.99 0.99 98 2.0.99 - * 0.99a-m 0.99 99 2.0.99 - * 1.00 1.00 100 2.1.0 [100 should be 10000] - * 1.0.0 (from here on, the 100 2.1.0 [100 should be 10000] - * 1.0.1 png.h string is 10001 2.1.0 - * 1.0.1a-e identical to the 10002 from here on, the shared library - * 1.0.2 source version) 10002 is 2.V where V is the source code - * 1.0.2a-b 10003 version, except as noted. - * 1.0.3 10003 - * 1.0.3a-d 10004 - * 1.0.4 10004 - * 1.0.4a-f 10005 - * 1.0.5 (+ 2 patches) 10005 - * 1.0.5a-d 10006 - * 1.0.5e-r 10100 (not source compatible) - * 1.0.5s-v 10006 (not binary compatible) - * 1.0.6 (+ 3 patches) 10006 (still binary incompatible) - * 1.0.6d-f 10007 (still binary incompatible) - * 1.0.6g 10007 - * 1.0.6h 10007 10.6h (testing xy.z so-numbering) - * 1.0.6i 10007 10.6i - * 1.0.6j 10007 2.1.0.6j (incompatible with 1.0.0) - * 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 (binary compatible) - * 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 (binary compatible) - * 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible) - * 1.0.7 1 10007 (still compatible) - * 1.0.8beta1-4 1 10008 2.1.0.8beta1-4 - * 1.0.8rc1 1 10008 2.1.0.8rc1 - * 1.0.8 1 10008 2.1.0.8 - * 1.0.9beta1-6 1 10009 2.1.0.9beta1-6 - * 1.0.9rc1 1 10009 2.1.0.9rc1 - * 1.0.9beta7-10 1 10009 2.1.0.9beta7-10 - * 1.0.9rc2 1 10009 2.1.0.9rc2 - * 1.0.9 1 10009 2.1.0.9 - * 1.0.10beta1 1 10010 2.1.0.10beta1 - * 1.0.10rc1 1 10010 2.1.0.10rc1 - * 1.0.10 1 10010 2.1.0.10 - * 1.0.11beta1-3 1 10011 2.1.0.11beta1-3 - * 1.0.11rc1 1 10011 2.1.0.11rc1 - * 1.0.11 1 10011 2.1.0.11 - * 1.0.12beta1-2 2 10012 2.1.0.12beta1-2 - * 1.0.12rc1 2 10012 2.1.0.12rc1 - * 1.0.12 2 10012 2.1.0.12 - * 1.1.0a-f - 10100 2.1.1.0a-f (branch abandoned) - * 1.2.0beta1-2 2 10200 2.1.2.0beta1-2 - * 1.2.0beta3-5 3 10200 3.1.2.0beta3-5 - * 1.2.0rc1 3 10200 3.1.2.0rc1 - * 1.2.0 3 10200 3.1.2.0 - * 1.2.1beta1-4 3 10201 3.1.2.1beta1-4 - * 1.2.1rc1-2 3 10201 3.1.2.1rc1-2 - * 1.2.1 3 10201 3.1.2.1 - * 1.2.2beta1-6 12 10202 12.so.0.1.2.2beta1-6 - * 1.0.13beta1 10 10013 10.so.0.1.0.13beta1 - * 1.0.13rc1 10 10013 10.so.0.1.0.13rc1 - * 1.2.2rc1 12 10202 12.so.0.1.2.2rc1 - * 1.0.13 10 10013 10.so.0.1.0.13 - * 1.2.2 12 10202 12.so.0.1.2.2 - * 1.2.3rc1-6 12 10203 12.so.0.1.2.3rc1-6 - * 1.2.3 12 10203 12.so.0.1.2.3 - * 1.2.4beta1-3 13 10204 12.so.0.1.2.4beta1-3 - * 1.0.14rc1 13 10014 10.so.0.1.0.14rc1 - * 1.2.4rc1 13 10204 12.so.0.1.2.4rc1 - * 1.0.14 10 10014 10.so.0.1.0.14 - * 1.2.4 13 10204 12.so.0.1.2.4 - * 1.2.5beta1-2 13 10205 12.so.0.1.2.5beta1-2 - * 1.0.15rc1-3 10 10015 10.so.0.1.0.15rc1-3 - * 1.2.5rc1-3 13 10205 12.so.0.1.2.5rc1-3 - * 1.0.15 10 10015 10.so.0.1.0.15 - * 1.2.5 13 10205 12.so.0.1.2.5 - * 1.2.6beta1-4 13 10206 12.so.0.1.2.6beta1-4 - * 1.0.16 10 10016 10.so.0.1.0.16 - * 1.2.6 13 10206 12.so.0.1.2.6 - * 1.2.7beta1-2 13 10207 12.so.0.1.2.7beta1-2 - * 1.0.17rc1 10 10017 10.so.0.1.0.17rc1 - * 1.2.7rc1 13 10207 12.so.0.1.2.7rc1 - * 1.0.17 10 10017 10.so.0.1.0.17 - * 1.2.7 13 10207 12.so.0.1.2.7 - * 1.2.8beta1-5 13 10208 12.so.0.1.2.8beta1-5 - * 1.0.18rc1-5 10 10018 10.so.0.1.0.18rc1-5 - * 1.2.8rc1-5 13 10208 12.so.0.1.2.8rc1-5 - * 1.0.18 10 10018 10.so.0.1.0.18 - * 1.2.8 13 10208 12.so.0.1.2.8 - * 1.2.9beta1-3 13 10209 12.so.0.1.2.9beta1-3 - * 1.2.9beta4-11 13 10209 12.so.0.9[.0] - * 1.2.9rc1 13 10209 12.so.0.9[.0] - * 1.2.9 13 10209 12.so.0.9[.0] - * 1.2.10beta1-8 13 10210 12.so.0.10[.0] - * 1.2.10rc1-3 13 10210 12.so.0.10[.0] - * 1.2.10 13 10210 12.so.0.10[.0] - * 1.2.11beta1-4 13 10211 12.so.0.11[.0] - * 1.0.19rc1-5 10 10019 10.so.0.19[.0] - * 1.2.11rc1-5 13 10211 12.so.0.11[.0] - * 1.0.19 10 10019 10.so.0.19[.0] - * 1.2.11 13 10211 12.so.0.11[.0] - * 1.0.20 10 10020 10.so.0.20[.0] - * 1.2.12 13 10212 12.so.0.12[.0] - * 1.2.13beta1 13 10213 12.so.0.13[.0] - * 1.0.21 10 10021 10.so.0.21[.0] - * 1.2.13 13 10213 12.so.0.13[.0] - * 1.2.14beta1-2 13 10214 12.so.0.14[.0] - * 1.0.22rc1 10 10022 10.so.0.22[.0] - * 1.2.14rc1 13 10214 12.so.0.14[.0] - * 1.0.22 10 10022 10.so.0.22[.0] - * 1.2.14 13 10214 12.so.0.14[.0] - * 1.2.15beta1-6 13 10215 12.so.0.15[.0] - * 1.0.23rc1-5 10 10023 10.so.0.23[.0] - * 1.2.15rc1-5 13 10215 12.so.0.15[.0] - * 1.0.23 10 10023 10.so.0.23[.0] - * 1.2.15 13 10215 12.so.0.15[.0] - * 1.2.16beta1-2 13 10216 12.so.0.16[.0] - * 1.2.16rc1 13 10216 12.so.0.16[.0] - * 1.0.24 10 10024 10.so.0.24[.0] - * 1.2.16 13 10216 12.so.0.16[.0] - * 1.2.17beta1-2 13 10217 12.so.0.17[.0] - * 1.0.25rc1 10 10025 10.so.0.25[.0] - * 1.2.17rc1-3 13 10217 12.so.0.17[.0] - * 1.0.25 10 10025 10.so.0.25[.0] - * 1.2.17 13 10217 12.so.0.17[.0] - * 1.0.26 10 10026 10.so.0.26[.0] - * 1.2.18 13 10218 12.so.0.18[.0] - * 1.2.19beta1-31 13 10219 12.so.0.19[.0] - * 1.0.27rc1-6 10 10027 10.so.0.27[.0] - * 1.2.19rc1-6 13 10219 12.so.0.19[.0] - * 1.0.27 10 10027 10.so.0.27[.0] - * 1.2.19 13 10219 12.so.0.19[.0] - * 1.2.20beta01-04 13 10220 12.so.0.20[.0] - * 1.0.28rc1-6 10 10028 10.so.0.28[.0] - * 1.2.20rc1-6 13 10220 12.so.0.20[.0] - * 1.0.28 10 10028 10.so.0.28[.0] - * 1.2.20 13 10220 12.so.0.20[.0] - * 1.2.21beta1-2 13 10221 12.so.0.21[.0] - * 1.2.21rc1-3 13 10221 12.so.0.21[.0] - * 1.0.29 10 10029 10.so.0.29[.0] - * 1.2.21 13 10221 12.so.0.21[.0] - * 1.2.22beta1-4 13 10222 12.so.0.22[.0] - * 1.0.30rc1 10 10030 10.so.0.30[.0] - * 1.2.22rc1 13 10222 12.so.0.22[.0] - * 1.0.30 10 10030 10.so.0.30[.0] - * 1.2.22 13 10222 12.so.0.22[.0] - * 1.2.23beta01-05 13 10223 12.so.0.23[.0] - * 1.2.23rc01 13 10223 12.so.0.23[.0] - * 1.2.23 13 10223 12.so.0.23[.0] - * 1.2.24beta01-02 13 10224 12.so.0.24[.0] - * 1.2.24rc01 13 10224 12.so.0.24[.0] - * 1.2.24 13 10224 12.so.0.24[.0] - * - * Henceforth the source version will match the shared-library major - * and minor numbers; the shared-library major version number will be - * used for changes in backward compatibility, as it is intended. The - * PNG_LIBPNG_VER macro, which is not used within libpng but is available - * for applications, is an unsigned integer of the form xyyzz corresponding - * to the source version x.y.z (leading zeros in y and z). Beta versions - * were given the previous public release number plus a letter, until - * version 1.0.6j; from then on they were given the upcoming public - * release number plus "betaNN" or "rcN". - * - * Binary incompatibility exists only when applications make direct access - * to the info_ptr or png_ptr members through png.h, and the compiled - * application is loaded with a different version of the library. - * - * DLLNUM will change each time there are forward or backward changes - * in binary compatibility (e.g., when a new feature is added). - * - * See libpng.txt or libpng.3 for more information. The PNG specification - * is available as a W3C Recommendation and as an ISO Specification, - * defines should NOT be changed. - */ -#define PNG_INFO_gAMA 0x0001 -#define PNG_INFO_sBIT 0x0002 -#define PNG_INFO_cHRM 0x0004 -#define PNG_INFO_PLTE 0x0008 -#define PNG_INFO_tRNS 0x0010 -#define PNG_INFO_bKGD 0x0020 -#define PNG_INFO_hIST 0x0040 -#define PNG_INFO_pHYs 0x0080 -#define PNG_INFO_oFFs 0x0100 -#define PNG_INFO_tIME 0x0200 -#define PNG_INFO_pCAL 0x0400 -#define PNG_INFO_sRGB 0x0800 /* GR-P, 0.96a */ -#define PNG_INFO_iCCP 0x1000 /* ESR, 1.0.6 */ -#define PNG_INFO_sPLT 0x2000 /* ESR, 1.0.6 */ -#define PNG_INFO_sCAL 0x4000 /* ESR, 1.0.6 */ -#define PNG_INFO_IDAT 0x8000L /* ESR, 1.0.6 */ - -/* This is used for the transformation routines, as some of them - * change these values for the row. It also should enable using - * the routines for other purposes. - */ -typedef struct png_row_info_struct -{ - png_uint_32 width; /* width of row */ - png_uint_32 rowbytes; /* number of bytes in row */ - png_byte color_type; /* color type of row */ - png_byte bit_depth; /* bit depth of row */ - png_byte channels; /* number of channels (1, 2, 3, or 4) */ - png_byte pixel_depth; /* bits per pixel (depth * channels) */ -} png_row_info; - -typedef png_row_info FAR * png_row_infop; -typedef png_row_info FAR * FAR * png_row_infopp; - -/* These are the function types for the I/O functions and for the functions - * that allow the user to override the default I/O functions with his or her - * own. The png_error_ptr type should match that of user-supplied warning - * and error functions, while the png_rw_ptr type should match that of the - * user read/write data functions. - */ -typedef struct png_struct_def png_struct; -typedef png_struct FAR * png_structp; - -typedef void (PNGAPI *png_error_ptr) PNGARG((png_structp, png_const_charp)); -typedef void (PNGAPI *png_rw_ptr) PNGARG((png_structp, png_bytep, png_size_t)); -typedef void (PNGAPI *png_flush_ptr) PNGARG((png_structp)); -typedef void (PNGAPI *png_read_status_ptr) PNGARG((png_structp, png_uint_32, - int)); -typedef void (PNGAPI *png_write_status_ptr) PNGARG((png_structp, png_uint_32, - int)); - -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED -typedef void (PNGAPI *png_progressive_info_ptr) PNGARG((png_structp, png_infop)); -typedef void (PNGAPI *png_progressive_end_ptr) PNGARG((png_structp, png_infop)); -typedef void (PNGAPI *png_progressive_row_ptr) PNGARG((png_structp, png_bytep, - png_uint_32, int)); -#endif - -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_LEGACY_SUPPORTED) -typedef void (PNGAPI *png_user_transform_ptr) PNGARG((png_structp, - png_row_infop, png_bytep)); -#endif - -#if defined(PNG_USER_CHUNKS_SUPPORTED) -typedef int (PNGAPI *png_user_chunk_ptr) PNGARG((png_structp, png_unknown_chunkp)); -#endif -#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) -typedef void (PNGAPI *png_unknown_chunk_ptr) PNGARG((png_structp)); -#endif - -/* Transform masks for the high-level interface */ -#define PNG_TRANSFORM_IDENTITY 0x0000 /* read and write */ -#define PNG_TRANSFORM_STRIP_16 0x0001 /* read only */ -#define PNG_TRANSFORM_STRIP_ALPHA 0x0002 /* read only */ -#define PNG_TRANSFORM_PACKING 0x0004 /* read and write */ -#define PNG_TRANSFORM_PACKSWAP 0x0008 /* read and write */ -#define PNG_TRANSFORM_EXPAND 0x0010 /* read only */ -#define PNG_TRANSFORM_INVERT_MONO 0x0020 /* read and write */ -#define PNG_TRANSFORM_SHIFT 0x0040 /* read and write */ -#define PNG_TRANSFORM_BGR 0x0080 /* read and write */ -#define PNG_TRANSFORM_SWAP_ALPHA 0x0100 /* read and write */ -#define PNG_TRANSFORM_SWAP_ENDIAN 0x0200 /* read and write */ -#define PNG_TRANSFORM_INVERT_ALPHA 0x0400 /* read and write */ -#define PNG_TRANSFORM_STRIP_FILLER 0x0800 /* WRITE only */ - -/* Flags for MNG supported features */ -#define PNG_FLAG_MNG_EMPTY_PLTE 0x01 -#define PNG_FLAG_MNG_FILTER_64 0x04 -#define PNG_ALL_MNG_FEATURES 0x05 - -typedef png_voidp (*png_malloc_ptr) PNGARG((png_structp, png_size_t)); -typedef void (*png_free_ptr) PNGARG((png_structp, png_voidp)); - -/* The structure that holds the information to read and write PNG files. - * The only people who need to care about what is inside of this are the - * people who will be modifying the library for their own special needs. - * It should NOT be accessed directly by an application, except to store - * the jmp_buf. - */ - -struct png_struct_def -{ -#ifdef PNG_SETJMP_SUPPORTED - jmp_buf jmpbuf; /* used in png_error */ -#endif - png_error_ptr error_fn; /* function for printing errors and aborting */ - png_error_ptr warning_fn; /* function for printing warnings */ - png_voidp error_ptr; /* user supplied struct for error functions */ - png_rw_ptr write_data_fn; /* function for writing output data */ - png_rw_ptr read_data_fn; /* function for reading input data */ - png_voidp io_ptr; /* ptr to application struct for I/O functions */ - -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) - png_user_transform_ptr read_user_transform_fn; /* user read transform */ -#endif - -#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) - png_user_transform_ptr write_user_transform_fn; /* user write transform */ -#endif - -/* These were added in libpng-1.0.2 */ -#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) - png_voidp user_transform_ptr; /* user supplied struct for user transform */ - png_byte user_transform_depth; /* bit depth of user transformed pixels */ - png_byte user_transform_channels; /* channels in user transformed pixels */ -#endif -#endif - - png_uint_32 mode; /* tells us where we are in the PNG file */ - png_uint_32 flags; /* flags indicating various things to libpng */ - png_uint_32 transformations; /* which transformations to perform */ - - z_stream zstream; /* pointer to decompression structure (below) */ - png_bytep zbuf; /* buffer for zlib */ - png_size_t zbuf_size; /* size of zbuf */ - int zlib_level; /* holds zlib compression level */ - int zlib_method; /* holds zlib compression method */ - int zlib_window_bits; /* holds zlib compression window bits */ - int zlib_mem_level; /* holds zlib compression memory level */ - int zlib_strategy; /* holds zlib compression strategy */ - - png_uint_32 width; /* width of image in pixels */ - png_uint_32 height; /* height of image in pixels */ - png_uint_32 num_rows; /* number of rows in current pass */ - png_uint_32 usr_width; /* width of row at start of write */ - png_uint_32 rowbytes; /* size of row in bytes */ - png_uint_32 irowbytes; /* size of current interlaced row in bytes */ - png_uint_32 iwidth; /* width of current interlaced row in pixels */ - png_uint_32 row_number; /* current row in interlace pass */ - png_bytep prev_row; /* buffer to save previous (unfiltered) row */ - png_bytep row_buf; /* buffer to save current (unfiltered) row */ -#ifndef PNG_NO_WRITE_FILTERING - png_bytep sub_row; /* buffer to save "sub" row when filtering */ - png_bytep up_row; /* buffer to save "up" row when filtering */ - png_bytep avg_row; /* buffer to save "avg" row when filtering */ - png_bytep paeth_row; /* buffer to save "Paeth" row when filtering */ -#endif - png_row_info row_info; /* used for transformation routines */ - - png_uint_32 idat_size; /* current IDAT size for read */ - png_uint_32 crc; /* current chunk CRC value */ - png_colorp palette; /* palette from the input file */ - png_uint_16 num_palette; /* number of color entries in palette */ - png_uint_16 num_trans; /* number of transparency values */ - png_byte chunk_name[5]; /* null-terminated name of current chunk */ - png_byte compression; /* file compression type (always 0) */ - png_byte filter; /* file filter type (always 0) */ - png_byte interlaced; /* PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */ - png_byte pass; /* current interlace pass (0 - 6) */ - png_byte do_filter; /* row filter flags (see PNG_FILTER_ below ) */ - png_byte color_type; /* color type of file */ - png_byte bit_depth; /* bit depth of file */ - png_byte usr_bit_depth; /* bit depth of users row */ - png_byte pixel_depth; /* number of bits per pixel */ - png_byte channels; /* number of channels in file */ - png_byte usr_channels; /* channels at start of write */ - png_byte sig_bytes; /* magic bytes read/written from start of file */ - -#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) -#ifdef PNG_LEGACY_SUPPORTED - png_byte filler; /* filler byte for pixel expansion */ -#else - png_uint_16 filler; /* filler bytes for pixel expansion */ -#endif -#endif - -#if defined(PNG_bKGD_SUPPORTED) - png_byte background_gamma_type; -# ifdef PNG_FLOATING_POINT_SUPPORTED - float background_gamma; -# endif - png_color_16 background; /* background color in screen gamma space */ -#if defined(PNG_READ_GAMMA_SUPPORTED) - png_color_16 background_1; /* background normalized to gamma 1.0 */ -#endif -#endif /* PNG_bKGD_SUPPORTED */ - -#if defined(PNG_WRITE_FLUSH_SUPPORTED) - png_flush_ptr output_flush_fn;/* Function for flushing output */ - png_uint_32 flush_dist; /* how many rows apart to flush, 0 - no flush */ - png_uint_32 flush_rows; /* number of rows written since last flush */ -#endif - -#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - int gamma_shift; /* number of "insignificant" bits 16-bit gamma */ -#ifdef PNG_FLOATING_POINT_SUPPORTED - float gamma; /* file gamma value */ - float screen_gamma; /* screen gamma value (display_exponent) */ -#endif -#endif - -#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - png_bytep gamma_table; /* gamma table for 8-bit depth files */ - png_bytep gamma_from_1; /* converts from 1.0 to screen */ - png_bytep gamma_to_1; /* converts from file to 1.0 */ - png_uint_16pp gamma_16_table; /* gamma table for 16-bit depth files */ - png_uint_16pp gamma_16_from_1; /* converts from 1.0 to screen */ - png_uint_16pp gamma_16_to_1; /* converts from file to 1.0 */ -#endif - -#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_sBIT_SUPPORTED) - png_color_8 sig_bit; /* significant bits in each available channel */ -#endif - -#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) - png_color_8 shift; /* shift for significant bit tranformation */ -#endif - -#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) \ - || defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - png_bytep trans; /* transparency values for paletted files */ - png_color_16 trans_values; /* transparency values for non-paletted files */ -#endif - - png_read_status_ptr read_row_fn; /* called after each row is decoded */ - png_write_status_ptr write_row_fn; /* called after each row is encoded */ -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED - png_progressive_info_ptr info_fn; /* called after header data fully read */ - png_progressive_row_ptr row_fn; /* called after each prog. row is decoded */ - png_progressive_end_ptr end_fn; /* called after image is complete */ - png_bytep save_buffer_ptr; /* current location in save_buffer */ - png_bytep save_buffer; /* buffer for previously read data */ - png_bytep current_buffer_ptr; /* current location in current_buffer */ - png_bytep current_buffer; /* buffer for recently used data */ - png_uint_32 push_length; /* size of current input chunk */ - png_uint_32 skip_length; /* bytes to skip in input data */ - png_size_t save_buffer_size; /* amount of data now in save_buffer */ - png_size_t save_buffer_max; /* total size of save_buffer */ - png_size_t buffer_size; /* total amount of available input data */ - png_size_t current_buffer_size; /* amount of data now in current_buffer */ - int process_mode; /* what push library is currently doing */ - int cur_palette; /* current push library palette index */ - -# if defined(PNG_TEXT_SUPPORTED) - png_size_t current_text_size; /* current size of text input data */ - png_size_t current_text_left; /* how much text left to read in input */ - png_charp current_text; /* current text chunk buffer */ - png_charp current_text_ptr; /* current location in current_text */ -# endif /* PNG_TEXT_SUPPORTED */ -#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ - -#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__) -/* for the Borland special 64K segment handler */ - png_bytepp offset_table_ptr; - png_bytep offset_table; - png_uint_16 offset_table_number; - png_uint_16 offset_table_count; - png_uint_16 offset_table_count_free; -#endif - -#if defined(PNG_READ_DITHER_SUPPORTED) - png_bytep palette_lookup; /* lookup table for dithering */ - png_bytep dither_index; /* index translation for palette files */ -#endif - -#if defined(PNG_READ_DITHER_SUPPORTED) || defined(PNG_hIST_SUPPORTED) - png_uint_16p hist; /* histogram */ -#endif - -#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - png_byte heuristic_method; /* heuristic for row filter selection */ - png_byte num_prev_filters; /* number of weights for previous rows */ - png_bytep prev_filters; /* filter type(s) of previous row(s) */ - png_uint_16p filter_weights; /* weight(s) for previous line(s) */ - png_uint_16p inv_filter_weights; /* 1/weight(s) for previous line(s) */ - png_uint_16p filter_costs; /* relative filter calculation cost */ - png_uint_16p inv_filter_costs; /* 1/relative filter calculation cost */ -#endif - -#if defined(PNG_TIME_RFC1123_SUPPORTED) - png_charp time_buffer; /* String to hold RFC 1123 time text */ -#endif - -/* New members added in libpng-1.0.6 */ - -#ifdef PNG_FREE_ME_SUPPORTED - png_uint_32 free_me; /* flags items libpng is responsible for freeing */ -#endif - -#if defined(PNG_USER_CHUNKS_SUPPORTED) - png_voidp user_chunk_ptr; - png_user_chunk_ptr read_user_chunk_fn; /* user read chunk handler */ -#endif - -#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) - int num_chunk_list; - png_bytep chunk_list; -#endif - -/* New members added in libpng-1.0.3 */ -#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) - png_byte rgb_to_gray_status; - /* These were changed from png_byte in libpng-1.0.6 */ - png_uint_16 rgb_to_gray_red_coeff; - png_uint_16 rgb_to_gray_green_coeff; - png_uint_16 rgb_to_gray_blue_coeff; -#endif - -/* New member added in libpng-1.0.4 (renamed in 1.0.9) */ -#if defined(PNG_MNG_FEATURES_SUPPORTED) || \ - defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \ - defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) -/* changed from png_byte to png_uint_32 at version 1.2.0 */ -#ifdef PNG_1_0_X - png_byte mng_features_permitted; -#else - png_uint_32 mng_features_permitted; -#endif /* PNG_1_0_X */ -#endif - -/* New member added in libpng-1.0.7 */ -#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - png_fixed_point int_gamma; -#endif - -/* New member added in libpng-1.0.9, ifdef'ed out in 1.0.12, enabled in 1.2.0 */ -#if defined(PNG_MNG_FEATURES_SUPPORTED) - png_byte filter_type; -#endif - -#if defined(PNG_1_0_X) -/* New member added in libpng-1.0.10, ifdef'ed out in 1.2.0 */ - png_uint_32 row_buf_size; -#endif - -/* New members added in libpng-1.2.0 */ -#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) -# if !defined(PNG_1_0_X) -# if defined(PNG_MMX_CODE_SUPPORTED) - png_byte mmx_bitdepth_threshold; - png_uint_32 mmx_rowbytes_threshold; -# endif - png_uint_32 asm_flags; -# endif -#endif - -/* New members added in libpng-1.0.2 but first enabled by default in 1.2.0 */ -#ifdef PNG_USER_MEM_SUPPORTED - png_voidp mem_ptr; /* user supplied struct for mem functions */ - png_malloc_ptr malloc_fn; /* function for allocating memory */ - png_free_ptr free_fn; /* function for freeing memory */ -#endif - -/* New member added in libpng-1.0.13 and 1.2.0 */ - png_bytep big_row_buf; /* buffer to save current (unfiltered) row */ - -#if defined(PNG_READ_DITHER_SUPPORTED) -/* The following three members were added at version 1.0.14 and 1.2.4 */ - png_bytep dither_sort; /* working sort array */ - png_bytep index_to_palette; /* where the original index currently is */ - /* in the palette */ - png_bytep palette_to_index; /* which original index points to this */ - /* palette color */ -#endif - -/* New members added in libpng-1.0.16 and 1.2.6 */ - png_byte compression_type; - -#ifdef PNG_SET_USER_LIMITS_SUPPORTED - png_uint_32 user_width_max; - png_uint_32 user_height_max; -#endif - -/* New member added in libpng-1.0.25 and 1.2.17 */ -#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) - /* storage for unknown chunk that the library doesn't recognize. */ - png_unknown_chunk unknown_chunk; -#endif -}; - - -/* This triggers a compiler error in png.c, if png.c and png.h - * do not agree upon the version number. - */ -typedef png_structp version_1_2_24; - -typedef png_struct FAR * FAR * png_structpp; - -/* Here are the function definitions most commonly used. This is not - * the place to find out how to use libpng. See libpng.txt for the - * full explanation, see example.c for the summary. This just provides - * a simple one line description of the use of each function. - */ - -/* Returns the version number of the library */ -extern PNG_EXPORT(png_uint_32,png_access_version_number) PNGARG((void)); - -/* Tell lib we have already handled the first magic bytes. - * Handling more than 8 bytes from the beginning of the file is an error. - */ -extern PNG_EXPORT(void,png_set_sig_bytes) PNGARG((png_structp png_ptr, - int num_bytes)); - -/* Check sig[start] through sig[start + num_to_check - 1] to see if it's a - * PNG file. Returns zero if the supplied bytes match the 8-byte PNG - * signature, and non-zero otherwise. Having num_to_check == 0 or - * start > 7 will always fail (ie return non-zero). - */ -extern PNG_EXPORT(int,png_sig_cmp) PNGARG((png_bytep sig, png_size_t start, - png_size_t num_to_check)); - -/* Simple signature checking function. This is the same as calling - * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n). - */ -extern PNG_EXPORT(int,png_check_sig) PNGARG((png_bytep sig, int num)); - -/* Allocate and initialize png_ptr struct for reading, and any other memory. */ -extern PNG_EXPORT(png_structp,png_create_read_struct) - PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn)); - -/* Allocate and initialize png_ptr struct for writing, and any other memory */ -extern PNG_EXPORT(png_structp,png_create_write_struct) - PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn)); - -#ifdef PNG_WRITE_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_compression_buffer_size) - PNGARG((png_structp png_ptr)); -#endif - -#ifdef PNG_WRITE_SUPPORTED -extern PNG_EXPORT(void,png_set_compression_buffer_size) - PNGARG((png_structp png_ptr, png_uint_32 size)); -#endif - -/* Reset the compression stream */ -extern PNG_EXPORT(int,png_reset_zstream) PNGARG((png_structp png_ptr)); - -/* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */ -#ifdef PNG_USER_MEM_SUPPORTED -extern PNG_EXPORT(png_structp,png_create_read_struct_2) - PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, - png_malloc_ptr malloc_fn, png_free_ptr free_fn)); -extern PNG_EXPORT(png_structp,png_create_write_struct_2) - PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, - png_malloc_ptr malloc_fn, png_free_ptr free_fn)); -#endif - -/* Write a PNG chunk - size, type, (optional) data, CRC. */ -extern PNG_EXPORT(void,png_write_chunk) PNGARG((png_structp png_ptr, - png_bytep chunk_name, png_bytep data, png_size_t length)); - -/* Write the start of a PNG chunk - length and chunk name. */ -extern PNG_EXPORT(void,png_write_chunk_start) PNGARG((png_structp png_ptr, - png_bytep chunk_name, png_uint_32 length)); - -/* Write the data of a PNG chunk started with png_write_chunk_start(). */ -extern PNG_EXPORT(void,png_write_chunk_data) PNGARG((png_structp png_ptr, - png_bytep data, png_size_t length)); - -/* Finish a chunk started with png_write_chunk_start() (includes CRC). */ -extern PNG_EXPORT(void,png_write_chunk_end) PNGARG((png_structp png_ptr)); - -/* Allocate and initialize the info structure */ -extern PNG_EXPORT(png_infop,png_create_info_struct) - PNGARG((png_structp png_ptr)); - -#if defined(PNG_1_0_X) || defined (PNG_1_2_X) -/* Initialize the info structure (old interface - DEPRECATED) */ -extern PNG_EXPORT(void,png_info_init) PNGARG((png_infop info_ptr)); -#undef png_info_init -#define png_info_init(info_ptr) png_info_init_3(&info_ptr,\ - png_sizeof(png_info)); -#endif - -extern PNG_EXPORT(void,png_info_init_3) PNGARG((png_infopp info_ptr, - png_size_t png_info_struct_size)); - -/* Writes all the PNG information before the image. */ -extern PNG_EXPORT(void,png_write_info_before_PLTE) PNGARG((png_structp png_ptr, - png_infop info_ptr)); -extern PNG_EXPORT(void,png_write_info) PNGARG((png_structp png_ptr, - png_infop info_ptr)); - -#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED -/* read the information before the actual image data. */ -extern PNG_EXPORT(void,png_read_info) PNGARG((png_structp png_ptr, - png_infop info_ptr)); -#endif - -#if defined(PNG_TIME_RFC1123_SUPPORTED) -extern PNG_EXPORT(png_charp,png_convert_to_rfc1123) - PNGARG((png_structp png_ptr, png_timep ptime)); -#endif - -#if !defined(_WIN32_WCE) -/* "time.h" functions are not supported on WindowsCE */ -#if defined(PNG_WRITE_tIME_SUPPORTED) -/* convert from a struct tm to png_time */ -extern PNG_EXPORT(void,png_convert_from_struct_tm) PNGARG((png_timep ptime, - struct tm FAR * ttime)); - -/* convert from time_t to png_time. Uses gmtime() */ -extern PNG_EXPORT(void,png_convert_from_time_t) PNGARG((png_timep ptime, - time_t ttime)); -#endif /* PNG_WRITE_tIME_SUPPORTED */ -#endif /* _WIN32_WCE */ - -#if defined(PNG_READ_EXPAND_SUPPORTED) -/* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */ -extern PNG_EXPORT(void,png_set_expand) PNGARG((png_structp png_ptr)); -#if !defined(PNG_1_0_X) -extern PNG_EXPORT(void,png_set_expand_gray_1_2_4_to_8) PNGARG((png_structp - png_ptr)); -#endif -extern PNG_EXPORT(void,png_set_palette_to_rgb) PNGARG((png_structp png_ptr)); -extern PNG_EXPORT(void,png_set_tRNS_to_alpha) PNGARG((png_structp png_ptr)); -#if defined(PNG_1_0_X) || defined (PNG_1_2_X) -/* Deprecated */ -extern PNG_EXPORT(void,png_set_gray_1_2_4_to_8) PNGARG((png_structp png_ptr)); -#endif -#endif - -#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) -/* Use blue, green, red order for pixels. */ -extern PNG_EXPORT(void,png_set_bgr) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) -/* Expand the grayscale to 24-bit RGB if necessary. */ -extern PNG_EXPORT(void,png_set_gray_to_rgb) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) -/* Reduce RGB to grayscale. */ -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_rgb_to_gray) PNGARG((png_structp png_ptr, - int error_action, double red, double green )); -#endif -extern PNG_EXPORT(void,png_set_rgb_to_gray_fixed) PNGARG((png_structp png_ptr, - int error_action, png_fixed_point red, png_fixed_point green )); -extern PNG_EXPORT(png_byte,png_get_rgb_to_gray_status) PNGARG((png_structp - png_ptr)); -#endif - -extern PNG_EXPORT(void,png_build_grayscale_palette) PNGARG((int bit_depth, - png_colorp palette)); - -#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) -extern PNG_EXPORT(void,png_set_strip_alpha) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ - defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) -extern PNG_EXPORT(void,png_set_swap_alpha) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ - defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) -extern PNG_EXPORT(void,png_set_invert_alpha) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) -/* Add a filler byte to 8-bit Gray or 24-bit RGB images. */ -extern PNG_EXPORT(void,png_set_filler) PNGARG((png_structp png_ptr, - png_uint_32 filler, int flags)); -/* The values of the PNG_FILLER_ defines should NOT be changed */ -#define PNG_FILLER_BEFORE 0 -#define PNG_FILLER_AFTER 1 -/* Add an alpha byte to 8-bit Gray or 24-bit RGB images. */ -#if !defined(PNG_1_0_X) -extern PNG_EXPORT(void,png_set_add_alpha) PNGARG((png_structp png_ptr, - png_uint_32 filler, int flags)); -#endif -#endif /* PNG_READ_FILLER_SUPPORTED || PNG_WRITE_FILLER_SUPPORTED */ - -#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) -/* Swap bytes in 16-bit depth files. */ -extern PNG_EXPORT(void,png_set_swap) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) -/* Use 1 byte per pixel in 1, 2, or 4-bit depth files. */ -extern PNG_EXPORT(void,png_set_packing) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_PACKSWAP_SUPPORTED) || defined(PNG_WRITE_PACKSWAP_SUPPORTED) -/* Swap packing order of pixels in bytes. */ -extern PNG_EXPORT(void,png_set_packswap) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) -/* Converts files to legal bit depths. */ -extern PNG_EXPORT(void,png_set_shift) PNGARG((png_structp png_ptr, - png_color_8p true_bits)); -#endif - -#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ - defined(PNG_WRITE_INTERLACING_SUPPORTED) -/* Have the code handle the interlacing. Returns the number of passes. */ -extern PNG_EXPORT(int,png_set_interlace_handling) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) -/* Invert monochrome files */ -extern PNG_EXPORT(void,png_set_invert_mono) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_BACKGROUND_SUPPORTED) -/* Handle alpha and tRNS by replacing with a background color. */ -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_background) PNGARG((png_structp png_ptr, - png_color_16p background_color, int background_gamma_code, - int need_expand, double background_gamma)); -#endif -#define PNG_BACKGROUND_GAMMA_UNKNOWN 0 -#define PNG_BACKGROUND_GAMMA_SCREEN 1 -#define PNG_BACKGROUND_GAMMA_FILE 2 -#define PNG_BACKGROUND_GAMMA_UNIQUE 3 -#endif - -#if defined(PNG_READ_16_TO_8_SUPPORTED) -/* strip the second byte of information from a 16-bit depth file. */ -extern PNG_EXPORT(void,png_set_strip_16) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_DITHER_SUPPORTED) -/* Turn on dithering, and reduce the palette to the number of colors available. */ -extern PNG_EXPORT(void,png_set_dither) PNGARG((png_structp png_ptr, - png_colorp palette, int num_palette, int maximum_colors, - png_uint_16p histogram, int full_dither)); -#endif - -#if defined(PNG_READ_GAMMA_SUPPORTED) -/* Handle gamma correction. Screen_gamma=(display_exponent) */ -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_gamma) PNGARG((png_structp png_ptr, - double screen_gamma, double default_file_gamma)); -#endif -#endif - -#if defined(PNG_1_0_X) || defined (PNG_1_2_X) -#if defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \ - defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) -/* Permit or disallow empty PLTE (0: not permitted, 1: permitted) */ -/* Deprecated and will be removed. Use png_permit_mng_features() instead. */ -extern PNG_EXPORT(void,png_permit_empty_plte) PNGARG((png_structp png_ptr, - int empty_plte_permitted)); -#endif -#endif - -#if defined(PNG_WRITE_FLUSH_SUPPORTED) -/* Set how many lines between output flushes - 0 for no flushing */ -extern PNG_EXPORT(void,png_set_flush) PNGARG((png_structp png_ptr, int nrows)); -/* Flush the current PNG output buffer */ -extern PNG_EXPORT(void,png_write_flush) PNGARG((png_structp png_ptr)); -#endif - -/* optional update palette with requested transformations */ -extern PNG_EXPORT(void,png_start_read_image) PNGARG((png_structp png_ptr)); - -/* optional call to update the users info structure */ -extern PNG_EXPORT(void,png_read_update_info) PNGARG((png_structp png_ptr, - png_infop info_ptr)); - -#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED -/* read one or more rows of image data. */ -extern PNG_EXPORT(void,png_read_rows) PNGARG((png_structp png_ptr, - png_bytepp row, png_bytepp display_row, png_uint_32 num_rows)); -#endif - -#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED -/* read a row of data. */ -extern PNG_EXPORT(void,png_read_row) PNGARG((png_structp png_ptr, - png_bytep row, - png_bytep display_row)); -#endif - -#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED -/* read the whole image into memory at once. */ -extern PNG_EXPORT(void,png_read_image) PNGARG((png_structp png_ptr, - png_bytepp image)); -#endif - -/* write a row of image data */ -extern PNG_EXPORT(void,png_write_row) PNGARG((png_structp png_ptr, - png_bytep row)); - -/* write a few rows of image data */ -extern PNG_EXPORT(void,png_write_rows) PNGARG((png_structp png_ptr, - png_bytepp row, png_uint_32 num_rows)); - -/* write the image data */ -extern PNG_EXPORT(void,png_write_image) PNGARG((png_structp png_ptr, - png_bytepp image)); - -/* writes the end of the PNG file. */ -extern PNG_EXPORT(void,png_write_end) PNGARG((png_structp png_ptr, - png_infop info_ptr)); - -#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED -/* read the end of the PNG file. */ -extern PNG_EXPORT(void,png_read_end) PNGARG((png_structp png_ptr, - png_infop info_ptr)); -#endif - -/* free any memory associated with the png_info_struct */ -extern PNG_EXPORT(void,png_destroy_info_struct) PNGARG((png_structp png_ptr, - png_infopp info_ptr_ptr)); - -/* free any memory associated with the png_struct and the png_info_structs */ -extern PNG_EXPORT(void,png_destroy_read_struct) PNGARG((png_structpp - png_ptr_ptr, png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr)); - -/* free all memory used by the read (old method - NOT DLL EXPORTED) */ -extern void png_read_destroy PNGARG((png_structp png_ptr, png_infop info_ptr, - png_infop end_info_ptr)); - -/* free any memory associated with the png_struct and the png_info_structs */ -extern PNG_EXPORT(void,png_destroy_write_struct) - PNGARG((png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)); - -/* free any memory used in png_ptr struct (old method - NOT DLL EXPORTED) */ -extern void png_write_destroy PNGARG((png_structp png_ptr)); - -/* set the libpng method of handling chunk CRC errors */ -extern PNG_EXPORT(void,png_set_crc_action) PNGARG((png_structp png_ptr, - int crit_action, int ancil_action)); - -/* Values for png_set_crc_action() to say how to handle CRC errors in - * ancillary and critical chunks, and whether to use the data contained - * therein. Note that it is impossible to "discard" data in a critical - * chunk. For versions prior to 0.90, the action was always error/quit, - * whereas in version 0.90 and later, the action for CRC errors in ancillary - * chunks is warn/discard. These values should NOT be changed. - * - * value action:critical action:ancillary - */ -#define PNG_CRC_DEFAULT 0 /* error/quit warn/discard data */ -#define PNG_CRC_ERROR_QUIT 1 /* error/quit error/quit */ -#define PNG_CRC_WARN_DISCARD 2 /* (INVALID) warn/discard data */ -#define PNG_CRC_WARN_USE 3 /* warn/use data warn/use data */ -#define PNG_CRC_QUIET_USE 4 /* quiet/use data quiet/use data */ -#define PNG_CRC_NO_CHANGE 5 /* use current value use current value */ - -/* These functions give the user control over the scan-line filtering in - * libpng and the compression methods used by zlib. These functions are - * mainly useful for testing, as the defaults should work with most users. - * Those users who are tight on memory or want faster performance at the - * expense of compression can modify them. See the compression library - * header file (zlib.h) for an explination of the compression functions. - */ - -/* set the filtering method(s) used by libpng. Currently, the only valid - * value for "method" is 0. - */ -extern PNG_EXPORT(void,png_set_filter) PNGARG((png_structp png_ptr, int method, - int filters)); - -/* Flags for png_set_filter() to say which filters to use. The flags - * are chosen so that they don't conflict with real filter types - * below, in case they are supplied instead of the #defined constants. - * These values should NOT be changed. - */ -#define PNG_NO_FILTERS 0x00 -#define PNG_FILTER_NONE 0x08 -#define PNG_FILTER_SUB 0x10 -#define PNG_FILTER_UP 0x20 -#define PNG_FILTER_AVG 0x40 -#define PNG_FILTER_PAETH 0x80 -#define PNG_ALL_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP | \ - PNG_FILTER_AVG | PNG_FILTER_PAETH) - -/* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now. - * These defines should NOT be changed. - */ -#define PNG_FILTER_VALUE_NONE 0 -#define PNG_FILTER_VALUE_SUB 1 -#define PNG_FILTER_VALUE_UP 2 -#define PNG_FILTER_VALUE_AVG 3 -#define PNG_FILTER_VALUE_PAETH 4 -#define PNG_FILTER_VALUE_LAST 5 - -#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) /* EXPERIMENTAL */ -/* The "heuristic_method" is given by one of the PNG_FILTER_HEURISTIC_ - * defines, either the default (minimum-sum-of-absolute-differences), or - * the experimental method (weighted-minimum-sum-of-absolute-differences). - * - * Weights are factors >= 1.0, indicating how important it is to keep the - * filter type consistent between rows. Larger numbers mean the current - * filter is that many times as likely to be the same as the "num_weights" - * previous filters. This is cumulative for each previous row with a weight. - * There needs to be "num_weights" values in "filter_weights", or it can be - * NULL if the weights aren't being specified. Weights have no influence on - * the selection of the first row filter. Well chosen weights can (in theory) - * improve the compression for a given image. - * - * Costs are factors >= 1.0 indicating the relative decoding costs of a - * filter type. Higher costs indicate more decoding expense, and are - * therefore less likely to be selected over a filter with lower computational - * costs. There needs to be a value in "filter_costs" for each valid filter - * type (given by PNG_FILTER_VALUE_LAST), or it can be NULL if you aren't - * setting the costs. Costs try to improve the speed of decompression without - * unduly increasing the compressed image size. - * - * A negative weight or cost indicates the default value is to be used, and - * values in the range [0.0, 1.0) indicate the value is to remain unchanged. - * The default values for both weights and costs are currently 1.0, but may - * change if good general weighting/cost heuristics can be found. If both - * the weights and costs are set to 1.0, this degenerates the WEIGHTED method - * to the UNWEIGHTED method, but with added encoding time/computation. - */ -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_filter_heuristics) PNGARG((png_structp png_ptr, - int heuristic_method, int num_weights, png_doublep filter_weights, - png_doublep filter_costs)); -#endif -#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ - -/* Heuristic used for row filter selection. These defines should NOT be - * changed. - */ -#define PNG_FILTER_HEURISTIC_DEFAULT 0 /* Currently "UNWEIGHTED" */ -#define PNG_FILTER_HEURISTIC_UNWEIGHTED 1 /* Used by libpng < 0.95 */ -#define PNG_FILTER_HEURISTIC_WEIGHTED 2 /* Experimental feature */ -#define PNG_FILTER_HEURISTIC_LAST 3 /* Not a valid value */ - -/* Set the library compression level. Currently, valid values range from - * 0 - 9, corresponding directly to the zlib compression levels 0 - 9 - * (0 - no compression, 9 - "maximal" compression). Note that tests have - * shown that zlib compression levels 3-6 usually perform as well as level 9 - * for PNG images, and do considerably fewer caclulations. In the future, - * these values may not correspond directly to the zlib compression levels. - */ -extern PNG_EXPORT(void,png_set_compression_level) PNGARG((png_structp png_ptr, - int level)); - -extern PNG_EXPORT(void,png_set_compression_mem_level) - PNGARG((png_structp png_ptr, int mem_level)); - -extern PNG_EXPORT(void,png_set_compression_strategy) - PNGARG((png_structp png_ptr, int strategy)); - -extern PNG_EXPORT(void,png_set_compression_window_bits) - PNGARG((png_structp png_ptr, int window_bits)); - -extern PNG_EXPORT(void,png_set_compression_method) PNGARG((png_structp png_ptr, - int method)); - -/* These next functions are called for input/output, memory, and error - * handling. They are in the file pngrio.c, pngwio.c, and pngerror.c, - * and call standard C I/O routines such as fread(), fwrite(), and - * fprintf(). These functions can be made to use other I/O routines - * at run time for those applications that need to handle I/O in a - * different manner by calling png_set_???_fn(). See libpng.txt for - * more information. - */ - -#if !defined(PNG_NO_STDIO) -/* Initialize the input/output for the PNG file to the default functions. */ -extern PNG_EXPORT(void,png_init_io) PNGARG((png_structp png_ptr, png_FILE_p fp)); -#endif - -/* Replace the (error and abort), and warning functions with user - * supplied functions. If no messages are to be printed you must still - * write and use replacement functions. The replacement error_fn should - * still do a longjmp to the last setjmp location if you are using this - * method of error handling. If error_fn or warning_fn is NULL, the - * default function will be used. - */ - -extern PNG_EXPORT(void,png_set_error_fn) PNGARG((png_structp png_ptr, - png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn)); - -/* Return the user pointer associated with the error functions */ -extern PNG_EXPORT(png_voidp,png_get_error_ptr) PNGARG((png_structp png_ptr)); - -/* Replace the default data output functions with a user supplied one(s). - * If buffered output is not used, then output_flush_fn can be set to NULL. - * If PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile time - * output_flush_fn will be ignored (and thus can be NULL). - */ -extern PNG_EXPORT(void,png_set_write_fn) PNGARG((png_structp png_ptr, - png_voidp io_ptr, png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)); - -/* Replace the default data input function with a user supplied one. */ -extern PNG_EXPORT(void,png_set_read_fn) PNGARG((png_structp png_ptr, - png_voidp io_ptr, png_rw_ptr read_data_fn)); - -/* Return the user pointer associated with the I/O functions */ -extern PNG_EXPORT(png_voidp,png_get_io_ptr) PNGARG((png_structp png_ptr)); - -extern PNG_EXPORT(void,png_set_read_status_fn) PNGARG((png_structp png_ptr, - png_read_status_ptr read_row_fn)); - -extern PNG_EXPORT(void,png_set_write_status_fn) PNGARG((png_structp png_ptr, - png_write_status_ptr write_row_fn)); - -#ifdef PNG_USER_MEM_SUPPORTED -/* Replace the default memory allocation functions with user supplied one(s). */ -extern PNG_EXPORT(void,png_set_mem_fn) PNGARG((png_structp png_ptr, - png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn)); -/* Return the user pointer associated with the memory functions */ -extern PNG_EXPORT(png_voidp,png_get_mem_ptr) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_LEGACY_SUPPORTED) -extern PNG_EXPORT(void,png_set_read_user_transform_fn) PNGARG((png_structp - png_ptr, png_user_transform_ptr read_user_transform_fn)); -#endif - -#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_LEGACY_SUPPORTED) -extern PNG_EXPORT(void,png_set_write_user_transform_fn) PNGARG((png_structp - png_ptr, png_user_transform_ptr write_user_transform_fn)); -#endif - -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_LEGACY_SUPPORTED) -extern PNG_EXPORT(void,png_set_user_transform_info) PNGARG((png_structp - png_ptr, png_voidp user_transform_ptr, int user_transform_depth, - int user_transform_channels)); -/* Return the user pointer associated with the user transform functions */ -extern PNG_EXPORT(png_voidp,png_get_user_transform_ptr) - PNGARG((png_structp png_ptr)); -#endif - -#ifdef PNG_USER_CHUNKS_SUPPORTED -extern PNG_EXPORT(void,png_set_read_user_chunk_fn) PNGARG((png_structp png_ptr, - png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn)); -extern PNG_EXPORT(png_voidp,png_get_user_chunk_ptr) PNGARG((png_structp - png_ptr)); -#endif - -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED -/* Sets the function callbacks for the push reader, and a pointer to a - * user-defined structure available to the callback functions. - */ -extern PNG_EXPORT(void,png_set_progressive_read_fn) PNGARG((png_structp png_ptr, - png_voidp progressive_ptr, - png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn, - png_progressive_end_ptr end_fn)); - -/* returns the user pointer associated with the push read functions */ -extern PNG_EXPORT(png_voidp,png_get_progressive_ptr) - PNGARG((png_structp png_ptr)); - -/* function to be called when data becomes available */ -extern PNG_EXPORT(void,png_process_data) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_bytep buffer, png_size_t buffer_size)); - -/* function that combines rows. Not very much different than the - * png_combine_row() call. Is this even used????? - */ -extern PNG_EXPORT(void,png_progressive_combine_row) PNGARG((png_structp png_ptr, - png_bytep old_row, png_bytep new_row)); -#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ - -extern PNG_EXPORT(png_voidp,png_malloc) PNGARG((png_structp png_ptr, - png_uint_32 size)); - -#if defined(PNG_1_0_X) -# define png_malloc_warn png_malloc -#else -/* Added at libpng version 1.2.4 */ -extern PNG_EXPORT(png_voidp,png_malloc_warn) PNGARG((png_structp png_ptr, - png_uint_32 size)); -#endif - -/* frees a pointer allocated by png_malloc() */ -extern PNG_EXPORT(void,png_free) PNGARG((png_structp png_ptr, png_voidp ptr)); - -#if defined(PNG_1_0_X) -/* Function to allocate memory for zlib. */ -extern PNG_EXPORT(voidpf,png_zalloc) PNGARG((voidpf png_ptr, uInt items, - uInt size)); - -/* Function to free memory for zlib */ -extern PNG_EXPORT(void,png_zfree) PNGARG((voidpf png_ptr, voidpf ptr)); -#endif - -/* Free data that was allocated internally */ -extern PNG_EXPORT(void,png_free_data) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 free_me, int num)); -#ifdef PNG_FREE_ME_SUPPORTED -/* Reassign responsibility for freeing existing data, whether allocated - * by libpng or by the application */ -extern PNG_EXPORT(void,png_data_freer) PNGARG((png_structp png_ptr, - png_infop info_ptr, int freer, png_uint_32 mask)); -#endif -/* assignments for png_data_freer */ -#define PNG_DESTROY_WILL_FREE_DATA 1 -#define PNG_SET_WILL_FREE_DATA 1 -#define PNG_USER_WILL_FREE_DATA 2 -/* Flags for png_ptr->free_me and info_ptr->free_me */ -#define PNG_FREE_HIST 0x0008 -#define PNG_FREE_ICCP 0x0010 -#define PNG_FREE_SPLT 0x0020 -#define PNG_FREE_ROWS 0x0040 -#define PNG_FREE_PCAL 0x0080 -#define PNG_FREE_SCAL 0x0100 -#define PNG_FREE_UNKN 0x0200 -#define PNG_FREE_LIST 0x0400 -#define PNG_FREE_PLTE 0x1000 -#define PNG_FREE_TRNS 0x2000 -#define PNG_FREE_TEXT 0x4000 -#define PNG_FREE_ALL 0x7fff -#define PNG_FREE_MUL 0x4220 /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */ - -#ifdef PNG_USER_MEM_SUPPORTED -extern PNG_EXPORT(png_voidp,png_malloc_default) PNGARG((png_structp png_ptr, - png_uint_32 size)); -extern PNG_EXPORT(void,png_free_default) PNGARG((png_structp png_ptr, - png_voidp ptr)); -#endif - -extern PNG_EXPORT(png_voidp,png_memcpy_check) PNGARG((png_structp png_ptr, - png_voidp s1, png_voidp s2, png_uint_32 size)); - -extern PNG_EXPORT(png_voidp,png_memset_check) PNGARG((png_structp png_ptr, - png_voidp s1, int value, png_uint_32 size)); - -#if defined(USE_FAR_KEYWORD) /* memory model conversion function */ -extern void *png_far_to_near PNGARG((png_structp png_ptr,png_voidp ptr, - int check)); -#endif /* USE_FAR_KEYWORD */ - -#ifndef PNG_NO_ERROR_TEXT -/* Fatal error in PNG image of libpng - can't continue */ -extern PNG_EXPORT(void,png_error) PNGARG((png_structp png_ptr, - png_const_charp error_message)); - -/* The same, but the chunk name is prepended to the error string. */ -extern PNG_EXPORT(void,png_chunk_error) PNGARG((png_structp png_ptr, - png_const_charp error_message)); -#else -/* Fatal error in PNG image of libpng - can't continue */ -extern PNG_EXPORT(void,png_err) PNGARG((png_structp png_ptr)); -#endif - -#ifndef PNG_NO_WARNINGS -/* Non-fatal error in libpng. Can continue, but may have a problem. */ -extern PNG_EXPORT(void,png_warning) PNGARG((png_structp png_ptr, - png_const_charp warning_message)); - -#ifdef PNG_READ_SUPPORTED -/* Non-fatal error in libpng, chunk name is prepended to message. */ -extern PNG_EXPORT(void,png_chunk_warning) PNGARG((png_structp png_ptr, - png_const_charp warning_message)); -#endif /* PNG_READ_SUPPORTED */ -#endif /* PNG_NO_WARNINGS */ - -/* The png_set_ functions are for storing values in the png_info_struct. - * Similarly, the png_get_ calls are used to read values from the - * png_info_struct, either storing the parameters in the passed variables, or - * setting pointers into the png_info_struct where the data is stored. The - * png_get_ functions return a non-zero value if the data was available - * in info_ptr, or return zero and do not change any of the parameters if the - * data was not available. - * - * These functions should be used instead of directly accessing png_info - * to avoid problems with future changes in the size and internal layout of - * png_info_struct. - */ -/* Returns "flag" if chunk data is valid in info_ptr. */ -extern PNG_EXPORT(png_uint_32,png_get_valid) PNGARG((png_structp png_ptr, -png_infop info_ptr, png_uint_32 flag)); - -/* Returns number of bytes needed to hold a transformed row. */ -extern PNG_EXPORT(png_uint_32,png_get_rowbytes) PNGARG((png_structp png_ptr, -png_infop info_ptr)); - -#if defined(PNG_INFO_IMAGE_SUPPORTED) -/* Returns row_pointers, which is an array of pointers to scanlines that was -returned from png_read_png(). */ -extern PNG_EXPORT(png_bytepp,png_get_rows) PNGARG((png_structp png_ptr, -png_infop info_ptr)); -/* Set row_pointers, which is an array of pointers to scanlines for use -by png_write_png(). */ -extern PNG_EXPORT(void,png_set_rows) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_bytepp row_pointers)); -#endif - -/* Returns number of color channels in image. */ -extern PNG_EXPORT(png_byte,png_get_channels) PNGARG((png_structp png_ptr, -png_infop info_ptr)); - -#ifdef PNG_EASY_ACCESS_SUPPORTED -/* Returns image width in pixels. */ -extern PNG_EXPORT(png_uint_32, png_get_image_width) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -/* Returns image height in pixels. */ -extern PNG_EXPORT(png_uint_32, png_get_image_height) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -/* Returns image bit_depth. */ -extern PNG_EXPORT(png_byte, png_get_bit_depth) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -/* Returns image color_type. */ -extern PNG_EXPORT(png_byte, png_get_color_type) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -/* Returns image filter_type. */ -extern PNG_EXPORT(png_byte, png_get_filter_type) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -/* Returns image interlace_type. */ -extern PNG_EXPORT(png_byte, png_get_interlace_type) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -/* Returns image compression_type. */ -extern PNG_EXPORT(png_byte, png_get_compression_type) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -/* Returns image resolution in pixels per meter, from pHYs chunk data. */ -extern PNG_EXPORT(png_uint_32, png_get_pixels_per_meter) PNGARG((png_structp -png_ptr, png_infop info_ptr)); -extern PNG_EXPORT(png_uint_32, png_get_x_pixels_per_meter) PNGARG((png_structp -png_ptr, png_infop info_ptr)); -extern PNG_EXPORT(png_uint_32, png_get_y_pixels_per_meter) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -/* Returns pixel aspect ratio, computed from pHYs chunk data. */ -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(float, png_get_pixel_aspect_ratio) PNGARG((png_structp -png_ptr, png_infop info_ptr)); -#endif - -/* Returns image x, y offset in pixels or microns, from oFFs chunk data. */ -extern PNG_EXPORT(png_int_32, png_get_x_offset_pixels) PNGARG((png_structp -png_ptr, png_infop info_ptr)); -extern PNG_EXPORT(png_int_32, png_get_y_offset_pixels) PNGARG((png_structp -png_ptr, png_infop info_ptr)); -extern PNG_EXPORT(png_int_32, png_get_x_offset_microns) PNGARG((png_structp -png_ptr, png_infop info_ptr)); -extern PNG_EXPORT(png_int_32, png_get_y_offset_microns) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -#endif /* PNG_EASY_ACCESS_SUPPORTED */ - -/* Returns pointer to signature string read from PNG header */ -extern PNG_EXPORT(png_bytep,png_get_signature) PNGARG((png_structp png_ptr, -png_infop info_ptr)); - -#if defined(PNG_bKGD_SUPPORTED) -extern PNG_EXPORT(png_uint_32,png_get_bKGD) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_color_16p *background)); -#endif - -#if defined(PNG_bKGD_SUPPORTED) -extern PNG_EXPORT(void,png_set_bKGD) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_color_16p background)); -#endif - -#if defined(PNG_cHRM_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_cHRM) PNGARG((png_structp png_ptr, - png_infop info_ptr, double *white_x, double *white_y, double *red_x, - double *red_y, double *green_x, double *green_y, double *blue_x, - double *blue_y)); -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_cHRM_fixed) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_fixed_point *int_white_x, png_fixed_point - *int_white_y, png_fixed_point *int_red_x, png_fixed_point *int_red_y, - png_fixed_point *int_green_x, png_fixed_point *int_green_y, png_fixed_point - *int_blue_x, png_fixed_point *int_blue_y)); -#endif -#endif - -#if defined(PNG_cHRM_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_cHRM) PNGARG((png_structp png_ptr, - png_infop info_ptr, double white_x, double white_y, double red_x, - double red_y, double green_x, double green_y, double blue_x, double blue_y)); -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_cHRM_fixed) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_fixed_point int_white_x, png_fixed_point int_white_y, - png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point - int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x, - png_fixed_point int_blue_y)); -#endif -#endif - -#if defined(PNG_gAMA_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_gAMA) PNGARG((png_structp png_ptr, - png_infop info_ptr, double *file_gamma)); -#endif -extern PNG_EXPORT(png_uint_32,png_get_gAMA_fixed) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_fixed_point *int_file_gamma)); -#endif - -#if defined(PNG_gAMA_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_gAMA) PNGARG((png_structp png_ptr, - png_infop info_ptr, double file_gamma)); -#endif -extern PNG_EXPORT(void,png_set_gAMA_fixed) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_fixed_point int_file_gamma)); -#endif - -#if defined(PNG_hIST_SUPPORTED) -extern PNG_EXPORT(png_uint_32,png_get_hIST) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_16p *hist)); -#endif - -#if defined(PNG_hIST_SUPPORTED) -extern PNG_EXPORT(void,png_set_hIST) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_16p hist)); -#endif - -extern PNG_EXPORT(png_uint_32,png_get_IHDR) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 *width, png_uint_32 *height, - int *bit_depth, int *color_type, int *interlace_method, - int *compression_method, int *filter_method)); - -extern PNG_EXPORT(void,png_set_IHDR) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 width, png_uint_32 height, int bit_depth, - int color_type, int interlace_method, int compression_method, - int filter_method)); - -#if defined(PNG_oFFs_SUPPORTED) -extern PNG_EXPORT(png_uint_32,png_get_oFFs) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_int_32 *offset_x, png_int_32 *offset_y, - int *unit_type)); -#endif - -#if defined(PNG_oFFs_SUPPORTED) -extern PNG_EXPORT(void,png_set_oFFs) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_int_32 offset_x, png_int_32 offset_y, - int unit_type)); -#endif - -#if defined(PNG_pCAL_SUPPORTED) -extern PNG_EXPORT(png_uint_32,png_get_pCAL) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_charp *purpose, png_int_32 *X0, png_int_32 *X1, - int *type, int *nparams, png_charp *units, png_charpp *params)); -#endif - -#if defined(PNG_pCAL_SUPPORTED) -extern PNG_EXPORT(void,png_set_pCAL) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_charp purpose, png_int_32 X0, png_int_32 X1, - int type, int nparams, png_charp units, png_charpp params)); -#endif - -#if defined(PNG_pHYs_SUPPORTED) -extern PNG_EXPORT(png_uint_32,png_get_pHYs) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)); -#endif - -#if defined(PNG_pHYs_SUPPORTED) -extern PNG_EXPORT(void,png_set_pHYs) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 res_x, png_uint_32 res_y, int unit_type)); -#endif - -extern PNG_EXPORT(png_uint_32,png_get_PLTE) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_colorp *palette, int *num_palette)); - -extern PNG_EXPORT(void,png_set_PLTE) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_colorp palette, int num_palette)); - -#if defined(PNG_sBIT_SUPPORTED) -extern PNG_EXPORT(png_uint_32,png_get_sBIT) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_color_8p *sig_bit)); -#endif - -#if defined(PNG_sBIT_SUPPORTED) -extern PNG_EXPORT(void,png_set_sBIT) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_color_8p sig_bit)); -#endif - -#if defined(PNG_sRGB_SUPPORTED) -extern PNG_EXPORT(png_uint_32,png_get_sRGB) PNGARG((png_structp png_ptr, - png_infop info_ptr, int *intent)); -#endif - -#if defined(PNG_sRGB_SUPPORTED) -extern PNG_EXPORT(void,png_set_sRGB) PNGARG((png_structp png_ptr, - png_infop info_ptr, int intent)); -extern PNG_EXPORT(void,png_set_sRGB_gAMA_and_cHRM) PNGARG((png_structp png_ptr, - png_infop info_ptr, int intent)); -#endif - -#if defined(PNG_iCCP_SUPPORTED) -extern PNG_EXPORT(png_uint_32,png_get_iCCP) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_charpp name, int *compression_type, - png_charpp profile, png_uint_32 *proflen)); - /* Note to maintainer: profile should be png_bytepp */ -#endif - -#if defined(PNG_iCCP_SUPPORTED) -extern PNG_EXPORT(void,png_set_iCCP) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_charp name, int compression_type, - png_charp profile, png_uint_32 proflen)); - /* Note to maintainer: profile should be png_bytep */ -#endif - -#if defined(PNG_sPLT_SUPPORTED) -extern PNG_EXPORT(png_uint_32,png_get_sPLT) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_sPLT_tpp entries)); -#endif - -#if defined(PNG_sPLT_SUPPORTED) -extern PNG_EXPORT(void,png_set_sPLT) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_sPLT_tp entries, int nentries)); -#endif - -#if defined(PNG_TEXT_SUPPORTED) -/* png_get_text also returns the number of text chunks in *num_text */ -extern PNG_EXPORT(png_uint_32,png_get_text) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_textp *text_ptr, int *num_text)); -#endif - -/* - * Note while png_set_text() will accept a structure whose text, - * language, and translated keywords are NULL pointers, the structure - * returned by png_get_text will always contain regular - * zero-terminated C strings. They might be empty strings but - * they will never be NULL pointers. - */ - -#if defined(PNG_TEXT_SUPPORTED) -extern PNG_EXPORT(void,png_set_text) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_textp text_ptr, int num_text)); -#endif - -#if defined(PNG_tIME_SUPPORTED) -extern PNG_EXPORT(png_uint_32,png_get_tIME) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_timep *mod_time)); -#endif - -#if defined(PNG_tIME_SUPPORTED) -extern PNG_EXPORT(void,png_set_tIME) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_timep mod_time)); -#endif - -#if defined(PNG_tRNS_SUPPORTED) -extern PNG_EXPORT(png_uint_32,png_get_tRNS) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_bytep *trans, int *num_trans, - png_color_16p *trans_values)); -#endif - -#if defined(PNG_tRNS_SUPPORTED) -extern PNG_EXPORT(void,png_set_tRNS) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_bytep trans, int num_trans, - png_color_16p trans_values)); -#endif - -#if defined(PNG_tRNS_SUPPORTED) -#endif - -#if defined(PNG_sCAL_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_sCAL) PNGARG((png_structp png_ptr, - png_infop info_ptr, int *unit, double *width, double *height)); -#else -#ifdef PNG_FIXED_POINT_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_sCAL_s) PNGARG((png_structp png_ptr, - png_infop info_ptr, int *unit, png_charpp swidth, png_charpp sheight)); -#endif -#endif -#endif /* PNG_sCAL_SUPPORTED */ - -#if defined(PNG_sCAL_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_sCAL) PNGARG((png_structp png_ptr, - png_infop info_ptr, int unit, double width, double height)); -#else -#ifdef PNG_FIXED_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_sCAL_s) PNGARG((png_structp png_ptr, - png_infop info_ptr, int unit, png_charp swidth, png_charp sheight)); -#endif -#endif -#endif /* PNG_sCAL_SUPPORTED || PNG_WRITE_sCAL_SUPPORTED */ - -#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) -/* provide a list of chunks and how they are to be handled, if the built-in - handling or default unknown chunk handling is not desired. Any chunks not - listed will be handled in the default manner. The IHDR and IEND chunks - must not be listed. - keep = 0: follow default behaviour - = 1: do not keep - = 2: keep only if safe-to-copy - = 3: keep even if unsafe-to-copy -*/ -extern PNG_EXPORT(void, png_set_keep_unknown_chunks) PNGARG((png_structp - png_ptr, int keep, png_bytep chunk_list, int num_chunks)); -extern PNG_EXPORT(void, png_set_unknown_chunks) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns)); -extern PNG_EXPORT(void, png_set_unknown_chunk_location) - PNGARG((png_structp png_ptr, png_infop info_ptr, int chunk, int location)); -extern PNG_EXPORT(png_uint_32,png_get_unknown_chunks) PNGARG((png_structp - png_ptr, png_infop info_ptr, png_unknown_chunkpp entries)); -#endif -#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED -PNG_EXPORT(int,png_handle_as_unknown) PNGARG((png_structp png_ptr, png_bytep - chunk_name)); -#endif - -/* Png_free_data() will turn off the "valid" flag for anything it frees. - If you need to turn it off for a chunk that your application has freed, - you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK); */ -extern PNG_EXPORT(void, png_set_invalid) PNGARG((png_structp png_ptr, - png_infop info_ptr, int mask)); - -#if defined(PNG_INFO_IMAGE_SUPPORTED) -/* The "params" pointer is currently not used and is for future expansion. */ -extern PNG_EXPORT(void, png_read_png) PNGARG((png_structp png_ptr, - png_infop info_ptr, - int transforms, - png_voidp params)); -extern PNG_EXPORT(void, png_write_png) PNGARG((png_structp png_ptr, - png_infop info_ptr, - int transforms, - png_voidp params)); -#endif - -/* Define PNG_DEBUG at compile time for debugging information. Higher - * numbers for PNG_DEBUG mean more debugging information. This has - * only been added since version 0.95 so it is not implemented throughout - * libpng yet, but more support will be added as needed. - */ -#ifdef PNG_DEBUG -#if (PNG_DEBUG > 0) -#if !defined(PNG_DEBUG_FILE) && defined(_MSC_VER) -#include -#if (PNG_DEBUG > 1) -#define png_debug(l,m) _RPT0(_CRT_WARN,m) -#define png_debug1(l,m,p1) _RPT1(_CRT_WARN,m,p1) -#define png_debug2(l,m,p1,p2) _RPT2(_CRT_WARN,m,p1,p2) -#endif -#else /* PNG_DEBUG_FILE || !_MSC_VER */ -#ifndef PNG_DEBUG_FILE -#define PNG_DEBUG_FILE stderr -#endif /* PNG_DEBUG_FILE */ -#if (PNG_DEBUG > 1) -#define png_debug(l,m) \ -{ \ - int num_tabs=l; \ - fprintf(PNG_DEBUG_FILE,"%s"m,(num_tabs==1 ? "\t" : \ - (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":"")))); \ -} -#define png_debug1(l,m,p1) \ -{ \ - int num_tabs=l; \ - fprintf(PNG_DEBUG_FILE,"%s"m,(num_tabs==1 ? "\t" : \ - (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1); \ -} -#define png_debug2(l,m,p1,p2) \ -{ \ - int num_tabs=l; \ - fprintf(PNG_DEBUG_FILE,"%s"m,(num_tabs==1 ? "\t" : \ - (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1,p2); \ -} -#endif /* (PNG_DEBUG > 1) */ -#endif /* _MSC_VER */ -#endif /* (PNG_DEBUG > 0) */ -#endif /* PNG_DEBUG */ -#ifndef png_debug -#define png_debug(l, m) -#endif -#ifndef png_debug1 -#define png_debug1(l, m, p1) -#endif -#ifndef png_debug2 -#define png_debug2(l, m, p1, p2) -#endif - -extern PNG_EXPORT(png_charp,png_get_copyright) PNGARG((png_structp png_ptr)); -extern PNG_EXPORT(png_charp,png_get_header_ver) PNGARG((png_structp png_ptr)); -extern PNG_EXPORT(png_charp,png_get_header_version) PNGARG((png_structp png_ptr)); -extern PNG_EXPORT(png_charp,png_get_libpng_ver) PNGARG((png_structp png_ptr)); - -#ifdef PNG_MNG_FEATURES_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_permit_mng_features) PNGARG((png_structp - png_ptr, png_uint_32 mng_features_permitted)); -#endif - -/* For use in png_set_keep_unknown, added to version 1.2.6 */ -#define PNG_HANDLE_CHUNK_AS_DEFAULT 0 -#define PNG_HANDLE_CHUNK_NEVER 1 -#define PNG_HANDLE_CHUNK_IF_SAFE 2 -#define PNG_HANDLE_CHUNK_ALWAYS 3 - -/* Added to version 1.2.0 */ -#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) -#if defined(PNG_MMX_CODE_SUPPORTED) -#define PNG_ASM_FLAG_MMX_SUPPORT_COMPILED 0x01 /* not user-settable */ -#define PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU 0x02 /* not user-settable */ -#define PNG_ASM_FLAG_MMX_READ_COMBINE_ROW 0x04 -#define PNG_ASM_FLAG_MMX_READ_INTERLACE 0x08 -#define PNG_ASM_FLAG_MMX_READ_FILTER_SUB 0x10 -#define PNG_ASM_FLAG_MMX_READ_FILTER_UP 0x20 -#define PNG_ASM_FLAG_MMX_READ_FILTER_AVG 0x40 -#define PNG_ASM_FLAG_MMX_READ_FILTER_PAETH 0x80 -#define PNG_ASM_FLAGS_INITIALIZED 0x80000000 /* not user-settable */ - -#define PNG_MMX_READ_FLAGS ( PNG_ASM_FLAG_MMX_READ_COMBINE_ROW \ - | PNG_ASM_FLAG_MMX_READ_INTERLACE \ - | PNG_ASM_FLAG_MMX_READ_FILTER_SUB \ - | PNG_ASM_FLAG_MMX_READ_FILTER_UP \ - | PNG_ASM_FLAG_MMX_READ_FILTER_AVG \ - | PNG_ASM_FLAG_MMX_READ_FILTER_PAETH ) -#define PNG_MMX_WRITE_FLAGS ( 0 ) - -#define PNG_MMX_FLAGS ( PNG_ASM_FLAG_MMX_SUPPORT_COMPILED \ - | PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU \ - | PNG_MMX_READ_FLAGS \ - | PNG_MMX_WRITE_FLAGS ) - -#define PNG_SELECT_READ 1 -#define PNG_SELECT_WRITE 2 -#endif /* PNG_MMX_CODE_SUPPORTED */ - -#if !defined(PNG_1_0_X) -/* pngget.c */ -extern PNG_EXPORT(png_uint_32,png_get_mmx_flagmask) - PNGARG((int flag_select, int *compilerID)); - -/* pngget.c */ -extern PNG_EXPORT(png_uint_32,png_get_asm_flagmask) - PNGARG((int flag_select)); - -/* pngget.c */ -extern PNG_EXPORT(png_uint_32,png_get_asm_flags) - PNGARG((png_structp png_ptr)); - -/* pngget.c */ -extern PNG_EXPORT(png_byte,png_get_mmx_bitdepth_threshold) - PNGARG((png_structp png_ptr)); - -/* pngget.c */ -extern PNG_EXPORT(png_uint_32,png_get_mmx_rowbytes_threshold) - PNGARG((png_structp png_ptr)); - -/* pngset.c */ -extern PNG_EXPORT(void,png_set_asm_flags) - PNGARG((png_structp png_ptr, png_uint_32 asm_flags)); - -/* pngset.c */ -extern PNG_EXPORT(void,png_set_mmx_thresholds) - PNGARG((png_structp png_ptr, png_byte mmx_bitdepth_threshold, - png_uint_32 mmx_rowbytes_threshold)); - -#endif /* PNG_1_0_X */ - -#if !defined(PNG_1_0_X) -/* png.c, pnggccrd.c, or pngvcrd.c */ -extern PNG_EXPORT(int,png_mmx_support) PNGARG((void)); -#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */ - -/* Strip the prepended error numbers ("#nnn ") from error and warning - * messages before passing them to the error or warning handler. */ -#ifdef PNG_ERROR_NUMBERS_SUPPORTED -extern PNG_EXPORT(void,png_set_strip_error_numbers) PNGARG((png_structp - png_ptr, png_uint_32 strip_mode)); -#endif - -#endif /* PNG_1_0_X */ - -/* Added at libpng-1.2.6 */ -#ifdef PNG_SET_USER_LIMITS_SUPPORTED -extern PNG_EXPORT(void,png_set_user_limits) PNGARG((png_structp - png_ptr, png_uint_32 user_width_max, png_uint_32 user_height_max)); -extern PNG_EXPORT(png_uint_32,png_get_user_width_max) PNGARG((png_structp - png_ptr)); -extern PNG_EXPORT(png_uint_32,png_get_user_height_max) PNGARG((png_structp - png_ptr)); -#endif - -/* Maintainer: Put new public prototypes here ^, in libpng.3, and project defs */ - -#ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED -/* With these routines we avoid an integer divide, which will be slower on - * most machines. However, it does take more operations than the corresponding - * divide method, so it may be slower on a few RISC systems. There are two - * shifts (by 8 or 16 bits) and an addition, versus a single integer divide. - * - * Note that the rounding factors are NOT supposed to be the same! 128 and - * 32768 are correct for the NODIV code; 127 and 32767 are correct for the - * standard method. - * - * [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ] - */ - - /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */ - -# define png_composite(composite, fg, alpha, bg) \ - { png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) * (png_uint_16)(alpha) \ - + (png_uint_16)(bg)*(png_uint_16)(255 - \ - (png_uint_16)(alpha)) + (png_uint_16)128); \ - (composite) = (png_byte)((temp + (temp >> 8)) >> 8); } - -# define png_composite_16(composite, fg, alpha, bg) \ - { png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) * (png_uint_32)(alpha) \ - + (png_uint_32)(bg)*(png_uint_32)(65535L - \ - (png_uint_32)(alpha)) + (png_uint_32)32768L); \ - (composite) = (png_uint_16)((temp + (temp >> 16)) >> 16); } - -#else /* standard method using integer division */ - -# define png_composite(composite, fg, alpha, bg) \ - (composite) = (png_byte)(((png_uint_16)(fg) * (png_uint_16)(alpha) + \ - (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \ - (png_uint_16)127) / 255) - -# define png_composite_16(composite, fg, alpha, bg) \ - (composite) = (png_uint_16)(((png_uint_32)(fg) * (png_uint_32)(alpha) + \ - (png_uint_32)(bg)*(png_uint_32)(65535L - (png_uint_32)(alpha)) + \ - (png_uint_32)32767) / (png_uint_32)65535L) - -#endif /* PNG_READ_COMPOSITE_NODIV_SUPPORTED */ - -/* Inline macros to do direct reads of bytes from the input buffer. These - * require that you are using an architecture that uses PNG byte ordering - * (MSB first) and supports unaligned data storage. I think that PowerPC - * in big-endian mode and 680x0 are the only ones that will support this. - * The x86 line of processors definitely do not. The png_get_int_32() - * routine also assumes we are using two's complement format for negative - * values, which is almost certainly true. - */ -#if defined(PNG_READ_BIG_ENDIAN_SUPPORTED) -# define png_get_uint_32(buf) ( *((png_uint_32p) (buf))) -# define png_get_uint_16(buf) ( *((png_uint_16p) (buf))) -# define png_get_int_32(buf) ( *((png_int_32p) (buf))) -#else -extern PNG_EXPORT(png_uint_32,png_get_uint_32) PNGARG((png_bytep buf)); -extern PNG_EXPORT(png_uint_16,png_get_uint_16) PNGARG((png_bytep buf)); -extern PNG_EXPORT(png_int_32,png_get_int_32) PNGARG((png_bytep buf)); -#endif /* !PNG_READ_BIG_ENDIAN_SUPPORTED */ -extern PNG_EXPORT(png_uint_32,png_get_uint_31) - PNGARG((png_structp png_ptr, png_bytep buf)); -/* No png_get_int_16 -- may be added if there's a real need for it. */ - -/* Place a 32-bit number into a buffer in PNG byte order (big-endian). - */ -extern PNG_EXPORT(void,png_save_uint_32) - PNGARG((png_bytep buf, png_uint_32 i)); -extern PNG_EXPORT(void,png_save_int_32) - PNGARG((png_bytep buf, png_int_32 i)); - -/* Place a 16-bit number into a buffer in PNG byte order. - * The parameter is declared unsigned int, not png_uint_16, - * just to avoid potential problems on pre-ANSI C compilers. - */ -extern PNG_EXPORT(void,png_save_uint_16) - PNGARG((png_bytep buf, unsigned int i)); -/* No png_save_int_16 -- may be added if there's a real need for it. */ - -/* ************************************************************************* */ - -/* These next functions are used internally in the code. They generally - * shouldn't be used unless you are writing code to add or replace some - * functionality in libpng. More information about most functions can - * be found in the files where the functions are located. - */ - - -/* Various modes of operation, that are visible to applications because - * they are used for unknown chunk location. - */ -#define PNG_HAVE_IHDR 0x01 -#define PNG_HAVE_PLTE 0x02 -#define PNG_HAVE_IDAT 0x04 -#define PNG_AFTER_IDAT 0x08 /* Have complete zlib datastream */ -#define PNG_HAVE_IEND 0x10 - -#if defined(PNG_INTERNAL) - -/* More modes of operation. Note that after an init, mode is set to - * zero automatically when the structure is created. - */ -#define PNG_HAVE_gAMA 0x20 -#define PNG_HAVE_cHRM 0x40 -#define PNG_HAVE_sRGB 0x80 -#define PNG_HAVE_CHUNK_HEADER 0x100 -#define PNG_WROTE_tIME 0x200 -#define PNG_WROTE_INFO_BEFORE_PLTE 0x400 -#define PNG_BACKGROUND_IS_GRAY 0x800 -#define PNG_HAVE_PNG_SIGNATURE 0x1000 -#define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000 /* Have another chunk after IDAT */ - -/* flags for the transformations the PNG library does on the image data */ -#define PNG_BGR 0x0001 -#define PNG_INTERLACE 0x0002 -#define PNG_PACK 0x0004 -#define PNG_SHIFT 0x0008 -#define PNG_SWAP_BYTES 0x0010 -#define PNG_INVERT_MONO 0x0020 -#define PNG_DITHER 0x0040 -#define PNG_BACKGROUND 0x0080 -#define PNG_BACKGROUND_EXPAND 0x0100 - /* 0x0200 unused */ -#define PNG_16_TO_8 0x0400 -#define PNG_RGBA 0x0800 -#define PNG_EXPAND 0x1000 -#define PNG_GAMMA 0x2000 -#define PNG_GRAY_TO_RGB 0x4000 -#define PNG_FILLER 0x8000L -#define PNG_PACKSWAP 0x10000L -#define PNG_SWAP_ALPHA 0x20000L -#define PNG_STRIP_ALPHA 0x40000L -#define PNG_INVERT_ALPHA 0x80000L -#define PNG_USER_TRANSFORM 0x100000L -#define PNG_RGB_TO_GRAY_ERR 0x200000L -#define PNG_RGB_TO_GRAY_WARN 0x400000L -#define PNG_RGB_TO_GRAY 0x600000L /* two bits, RGB_TO_GRAY_ERR|WARN */ - /* 0x800000L Unused */ -#define PNG_ADD_ALPHA 0x1000000L /* Added to libpng-1.2.7 */ -#define PNG_EXPAND_tRNS 0x2000000L /* Added to libpng-1.2.9 */ - /* 0x4000000L unused */ - /* 0x8000000L unused */ - /* 0x10000000L unused */ - /* 0x20000000L unused */ - /* 0x40000000L unused */ - -/* flags for png_create_struct */ -#define PNG_STRUCT_PNG 0x0001 -#define PNG_STRUCT_INFO 0x0002 - -/* Scaling factor for filter heuristic weighting calculations */ -#define PNG_WEIGHT_SHIFT 8 -#define PNG_WEIGHT_FACTOR (1<<(PNG_WEIGHT_SHIFT)) -#define PNG_COST_SHIFT 3 -#define PNG_COST_FACTOR (1<<(PNG_COST_SHIFT)) - -/* flags for the png_ptr->flags rather than declaring a byte for each one */ -#define PNG_FLAG_ZLIB_CUSTOM_STRATEGY 0x0001 -#define PNG_FLAG_ZLIB_CUSTOM_LEVEL 0x0002 -#define PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL 0x0004 -#define PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS 0x0008 -#define PNG_FLAG_ZLIB_CUSTOM_METHOD 0x0010 -#define PNG_FLAG_ZLIB_FINISHED 0x0020 -#define PNG_FLAG_ROW_INIT 0x0040 -#define PNG_FLAG_FILLER_AFTER 0x0080 -#define PNG_FLAG_CRC_ANCILLARY_USE 0x0100 -#define PNG_FLAG_CRC_ANCILLARY_NOWARN 0x0200 -#define PNG_FLAG_CRC_CRITICAL_USE 0x0400 -#define PNG_FLAG_CRC_CRITICAL_IGNORE 0x0800 -#define PNG_FLAG_FREE_PLTE 0x1000 -#define PNG_FLAG_FREE_TRNS 0x2000 -#define PNG_FLAG_FREE_HIST 0x4000 -#define PNG_FLAG_KEEP_UNKNOWN_CHUNKS 0x8000L -#define PNG_FLAG_KEEP_UNSAFE_CHUNKS 0x10000L -#define PNG_FLAG_LIBRARY_MISMATCH 0x20000L -#define PNG_FLAG_STRIP_ERROR_NUMBERS 0x40000L -#define PNG_FLAG_STRIP_ERROR_TEXT 0x80000L -#define PNG_FLAG_MALLOC_NULL_MEM_OK 0x100000L -#define PNG_FLAG_ADD_ALPHA 0x200000L /* Added to libpng-1.2.8 */ -#define PNG_FLAG_STRIP_ALPHA 0x400000L /* Added to libpng-1.2.8 */ - /* 0x800000L unused */ - /* 0x1000000L unused */ - /* 0x2000000L unused */ - /* 0x4000000L unused */ - /* 0x8000000L unused */ - /* 0x10000000L unused */ - /* 0x20000000L unused */ - /* 0x40000000L unused */ - -#define PNG_FLAG_CRC_ANCILLARY_MASK (PNG_FLAG_CRC_ANCILLARY_USE | \ - PNG_FLAG_CRC_ANCILLARY_NOWARN) - -#define PNG_FLAG_CRC_CRITICAL_MASK (PNG_FLAG_CRC_CRITICAL_USE | \ - PNG_FLAG_CRC_CRITICAL_IGNORE) - -#define PNG_FLAG_CRC_MASK (PNG_FLAG_CRC_ANCILLARY_MASK | \ - PNG_FLAG_CRC_CRITICAL_MASK) - -/* save typing and make code easier to understand */ - -#define PNG_COLOR_DIST(c1, c2) (abs((int)((c1).red) - (int)((c2).red)) + \ - abs((int)((c1).green) - (int)((c2).green)) + \ - abs((int)((c1).blue) - (int)((c2).blue))) - -/* Added to libpng-1.2.6 JB */ -#define PNG_ROWBYTES(pixel_bits, width) \ - ((pixel_bits) >= 8 ? \ - ((width) * (((png_uint_32)(pixel_bits)) >> 3)) : \ - (( ((width) * ((png_uint_32)(pixel_bits))) + 7) >> 3) ) - -/* PNG_OUT_OF_RANGE returns true if value is outside the range - ideal-delta..ideal+delta. Each argument is evaluated twice. - "ideal" and "delta" should be constants, normally simple - integers, "value" a variable. Added to libpng-1.2.6 JB */ -#define PNG_OUT_OF_RANGE(value, ideal, delta) \ - ( (value) < (ideal)-(delta) || (value) > (ideal)+(delta) ) - -/* variables declared in png.c - only it needs to define PNG_NO_EXTERN */ -#if !defined(PNG_NO_EXTERN) || defined(PNG_ALWAYS_EXTERN) -/* place to hold the signature string for a PNG file. */ -#ifdef PNG_USE_GLOBAL_ARRAYS - PNG_EXPORT_VAR (PNG_CONST png_byte FARDATA) png_sig[8]; -#else -#endif -#endif /* PNG_NO_EXTERN */ - -/* Constant strings for known chunk types. If you need to add a chunk, - * define the name here, and add an invocation of the macro in png.c and - * wherever it's needed. - */ -#define PNG_IHDR png_byte png_IHDR[5] = { 73, 72, 68, 82, '\0'} -#define PNG_IDAT png_byte png_IDAT[5] = { 73, 68, 65, 84, '\0'} -#define PNG_IEND png_byte png_IEND[5] = { 73, 69, 78, 68, '\0'} -#define PNG_PLTE png_byte png_PLTE[5] = { 80, 76, 84, 69, '\0'} -#define PNG_bKGD png_byte png_bKGD[5] = { 98, 75, 71, 68, '\0'} -#define PNG_cHRM png_byte png_cHRM[5] = { 99, 72, 82, 77, '\0'} -#define PNG_gAMA png_byte png_gAMA[5] = {103, 65, 77, 65, '\0'} -#define PNG_hIST png_byte png_hIST[5] = {104, 73, 83, 84, '\0'} -#define PNG_iCCP png_byte png_iCCP[5] = {105, 67, 67, 80, '\0'} -#define PNG_iTXt png_byte png_iTXt[5] = {105, 84, 88, 116, '\0'} -#define PNG_oFFs png_byte png_oFFs[5] = {111, 70, 70, 115, '\0'} -#define PNG_pCAL png_byte png_pCAL[5] = {112, 67, 65, 76, '\0'} -#define PNG_sCAL png_byte png_sCAL[5] = {115, 67, 65, 76, '\0'} -#define PNG_pHYs png_byte png_pHYs[5] = {112, 72, 89, 115, '\0'} -#define PNG_sBIT png_byte png_sBIT[5] = {115, 66, 73, 84, '\0'} -#define PNG_sPLT png_byte png_sPLT[5] = {115, 80, 76, 84, '\0'} -#define PNG_sRGB png_byte png_sRGB[5] = {115, 82, 71, 66, '\0'} -#define PNG_tEXt png_byte png_tEXt[5] = {116, 69, 88, 116, '\0'} -#define PNG_tIME png_byte png_tIME[5] = {116, 73, 77, 69, '\0'} -#define PNG_tRNS png_byte png_tRNS[5] = {116, 82, 78, 83, '\0'} -#define PNG_zTXt png_byte png_zTXt[5] = {122, 84, 88, 116, '\0'} - -#ifdef PNG_USE_GLOBAL_ARRAYS -PNG_EXPORT_VAR (png_byte FARDATA) png_IHDR[5]; -PNG_EXPORT_VAR (png_byte FARDATA) png_IDAT[5]; -PNG_EXPORT_VAR (png_byte FARDATA) png_IEND[5]; -PNG_EXPORT_VAR (png_byte FARDATA) png_PLTE[5]; -PNG_EXPORT_VAR (png_byte FARDATA) png_bKGD[5]; -PNG_EXPORT_VAR (png_byte FARDATA) png_cHRM[5]; -PNG_EXPORT_VAR (png_byte FARDATA) png_gAMA[5]; -PNG_EXPORT_VAR (png_byte FARDATA) png_hIST[5]; -PNG_EXPORT_VAR (png_byte FARDATA) png_iCCP[5]; -PNG_EXPORT_VAR (png_byte FARDATA) png_iTXt[5]; -PNG_EXPORT_VAR (png_byte FARDATA) png_oFFs[5]; -PNG_EXPORT_VAR (png_byte FARDATA) png_pCAL[5]; -PNG_EXPORT_VAR (png_byte FARDATA) png_sCAL[5]; -PNG_EXPORT_VAR (png_byte FARDATA) png_pHYs[5]; -PNG_EXPORT_VAR (png_byte FARDATA) png_sBIT[5]; -PNG_EXPORT_VAR (png_byte FARDATA) png_sPLT[5]; -PNG_EXPORT_VAR (png_byte FARDATA) png_sRGB[5]; -PNG_EXPORT_VAR (png_byte FARDATA) png_tEXt[5]; -PNG_EXPORT_VAR (png_byte FARDATA) png_tIME[5]; -PNG_EXPORT_VAR (png_byte FARDATA) png_tRNS[5]; -PNG_EXPORT_VAR (png_byte FARDATA) png_zTXt[5]; -#endif /* PNG_USE_GLOBAL_ARRAYS */ - -#if defined(PNG_1_0_X) || defined (PNG_1_2_X) -/* Initialize png_ptr struct for reading, and allocate any other memory. - * (old interface - DEPRECATED - use png_create_read_struct instead). - */ -extern PNG_EXPORT(void,png_read_init) PNGARG((png_structp png_ptr)); -#undef png_read_init -#define png_read_init(png_ptr) png_read_init_3(&png_ptr, \ - PNG_LIBPNG_VER_STRING, png_sizeof(png_struct)); -#endif - -extern PNG_EXPORT(void,png_read_init_3) PNGARG((png_structpp ptr_ptr, - png_const_charp user_png_ver, png_size_t png_struct_size)); -#if defined(PNG_1_0_X) || defined (PNG_1_2_X) -extern PNG_EXPORT(void,png_read_init_2) PNGARG((png_structp png_ptr, - png_const_charp user_png_ver, png_size_t png_struct_size, png_size_t - png_info_size)); -#endif - -#if defined(PNG_1_0_X) || defined (PNG_1_2_X) -/* Initialize png_ptr struct for writing, and allocate any other memory. - * (old interface - DEPRECATED - use png_create_write_struct instead). - */ -extern PNG_EXPORT(void,png_write_init) PNGARG((png_structp png_ptr)); -#undef png_write_init -#define png_write_init(png_ptr) png_write_init_3(&png_ptr, \ - PNG_LIBPNG_VER_STRING, png_sizeof(png_struct)); -#endif - -extern PNG_EXPORT(void,png_write_init_3) PNGARG((png_structpp ptr_ptr, - png_const_charp user_png_ver, png_size_t png_struct_size)); -extern PNG_EXPORT(void,png_write_init_2) PNGARG((png_structp png_ptr, - png_const_charp user_png_ver, png_size_t png_struct_size, png_size_t - png_info_size)); - -/* Allocate memory for an internal libpng struct */ -PNG_EXTERN png_voidp png_create_struct PNGARG((int type)); - -/* Free memory from internal libpng struct */ -PNG_EXTERN void png_destroy_struct PNGARG((png_voidp struct_ptr)); - -PNG_EXTERN png_voidp png_create_struct_2 PNGARG((int type, png_malloc_ptr - malloc_fn, png_voidp mem_ptr)); -PNG_EXTERN void png_destroy_struct_2 PNGARG((png_voidp struct_ptr, - png_free_ptr free_fn, png_voidp mem_ptr)); - -/* Free any memory that info_ptr points to and reset struct. */ -PNG_EXTERN void png_info_destroy PNGARG((png_structp png_ptr, - png_infop info_ptr)); - -#ifndef PNG_1_0_X -/* Function to allocate memory for zlib. */ -PNG_EXTERN voidpf png_zalloc PNGARG((voidpf png_ptr, uInt items, uInt size)); - -/* Function to free memory for zlib */ -PNG_EXTERN void png_zfree PNGARG((voidpf png_ptr, voidpf ptr)); - -#ifdef PNG_SIZE_T -/* Function to convert a sizeof an item to png_sizeof item */ - PNG_EXTERN png_size_t PNGAPI png_convert_size PNGARG((size_t size)); -#endif - -/* Next four functions are used internally as callbacks. PNGAPI is required - * but not PNG_EXPORT. PNGAPI added at libpng version 1.2.3. */ - -PNG_EXTERN void PNGAPI png_default_read_data PNGARG((png_structp png_ptr, - png_bytep data, png_size_t length)); - -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED -PNG_EXTERN void PNGAPI png_push_fill_buffer PNGARG((png_structp png_ptr, - png_bytep buffer, png_size_t length)); -#endif - -PNG_EXTERN void PNGAPI png_default_write_data PNGARG((png_structp png_ptr, - png_bytep data, png_size_t length)); - -#if defined(PNG_WRITE_FLUSH_SUPPORTED) -#if !defined(PNG_NO_STDIO) -PNG_EXTERN void PNGAPI png_default_flush PNGARG((png_structp png_ptr)); -#endif -#endif -#else /* PNG_1_0_X */ -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED -PNG_EXTERN void png_push_fill_buffer PNGARG((png_structp png_ptr, - png_bytep buffer, png_size_t length)); -#endif -#endif /* PNG_1_0_X */ - -/* Reset the CRC variable */ -PNG_EXTERN void png_reset_crc PNGARG((png_structp png_ptr)); - -/* Write the "data" buffer to whatever output you are using. */ -PNG_EXTERN void png_write_data PNGARG((png_structp png_ptr, png_bytep data, - png_size_t length)); - -/* Read data from whatever input you are using into the "data" buffer */ -PNG_EXTERN void png_read_data PNGARG((png_structp png_ptr, png_bytep data, - png_size_t length)); - -/* Read bytes into buf, and update png_ptr->crc */ -PNG_EXTERN void png_crc_read PNGARG((png_structp png_ptr, png_bytep buf, - png_size_t length)); - -/* Decompress data in a chunk that uses compression */ -#if defined(PNG_zTXt_SUPPORTED) || defined(PNG_iTXt_SUPPORTED) || \ - defined(PNG_iCCP_SUPPORTED) || defined(PNG_sPLT_SUPPORTED) -PNG_EXTERN png_charp png_decompress_chunk PNGARG((png_structp png_ptr, - int comp_type, png_charp chunkdata, png_size_t chunklength, - png_size_t prefix_length, png_size_t *data_length)); -#endif - -/* Read "skip" bytes, read the file crc, and (optionally) verify png_ptr->crc */ -PNG_EXTERN int png_crc_finish PNGARG((png_structp png_ptr, png_uint_32 skip)); - -/* Read the CRC from the file and compare it to the libpng calculated CRC */ -PNG_EXTERN int png_crc_error PNGARG((png_structp png_ptr)); - -/* Calculate the CRC over a section of data. Note that we are only - * passing a maximum of 64K on systems that have this as a memory limit, - * since this is the maximum buffer size we can specify. - */ -PNG_EXTERN void png_calculate_crc PNGARG((png_structp png_ptr, png_bytep ptr, - png_size_t length)); - -#if defined(PNG_WRITE_FLUSH_SUPPORTED) -PNG_EXTERN void png_flush PNGARG((png_structp png_ptr)); -#endif - -/* simple function to write the signature */ -PNG_EXTERN void png_write_sig PNGARG((png_structp png_ptr)); - -/* write various chunks */ - -/* Write the IHDR chunk, and update the png_struct with the necessary - * information. - */ -PNG_EXTERN void png_write_IHDR PNGARG((png_structp png_ptr, png_uint_32 width, - png_uint_32 height, - int bit_depth, int color_type, int compression_method, int filter_method, - int interlace_method)); - -PNG_EXTERN void png_write_PLTE PNGARG((png_structp png_ptr, png_colorp palette, - png_uint_32 num_pal)); - -PNG_EXTERN void png_write_IDAT PNGARG((png_structp png_ptr, png_bytep data, - png_size_t length)); - -PNG_EXTERN void png_write_IEND PNGARG((png_structp png_ptr)); - -#if defined(PNG_WRITE_gAMA_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED -PNG_EXTERN void png_write_gAMA PNGARG((png_structp png_ptr, double file_gamma)); -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED -PNG_EXTERN void png_write_gAMA_fixed PNGARG((png_structp png_ptr, png_fixed_point - file_gamma)); -#endif -#endif - -#if defined(PNG_WRITE_sBIT_SUPPORTED) -PNG_EXTERN void png_write_sBIT PNGARG((png_structp png_ptr, png_color_8p sbit, - int color_type)); -#endif - -#if defined(PNG_WRITE_cHRM_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED -PNG_EXTERN void png_write_cHRM PNGARG((png_structp png_ptr, - double white_x, double white_y, - double red_x, double red_y, double green_x, double green_y, - double blue_x, double blue_y)); -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED -PNG_EXTERN void png_write_cHRM_fixed PNGARG((png_structp png_ptr, - png_fixed_point int_white_x, png_fixed_point int_white_y, - png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point - int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x, - png_fixed_point int_blue_y)); -#endif -#endif - -#if defined(PNG_WRITE_sRGB_SUPPORTED) -PNG_EXTERN void png_write_sRGB PNGARG((png_structp png_ptr, - int intent)); -#endif - -#if defined(PNG_WRITE_iCCP_SUPPORTED) -PNG_EXTERN void png_write_iCCP PNGARG((png_structp png_ptr, - png_charp name, int compression_type, - png_charp profile, int proflen)); - /* Note to maintainer: profile should be png_bytep */ -#endif - -#if defined(PNG_WRITE_sPLT_SUPPORTED) -PNG_EXTERN void png_write_sPLT PNGARG((png_structp png_ptr, - png_sPLT_tp palette)); -#endif - -#if defined(PNG_WRITE_tRNS_SUPPORTED) -PNG_EXTERN void png_write_tRNS PNGARG((png_structp png_ptr, png_bytep trans, - png_color_16p values, int number, int color_type)); -#endif - -#if defined(PNG_WRITE_bKGD_SUPPORTED) -PNG_EXTERN void png_write_bKGD PNGARG((png_structp png_ptr, - png_color_16p values, int color_type)); -#endif - -#if defined(PNG_WRITE_hIST_SUPPORTED) -PNG_EXTERN void png_write_hIST PNGARG((png_structp png_ptr, png_uint_16p hist, - int num_hist)); -#endif - -#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \ - defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) -PNG_EXTERN png_size_t png_check_keyword PNGARG((png_structp png_ptr, - png_charp key, png_charpp new_key)); -#endif - -#if defined(PNG_WRITE_tEXt_SUPPORTED) -PNG_EXTERN void png_write_tEXt PNGARG((png_structp png_ptr, png_charp key, - png_charp text, png_size_t text_len)); -#endif - -#if defined(PNG_WRITE_zTXt_SUPPORTED) -PNG_EXTERN void png_write_zTXt PNGARG((png_structp png_ptr, png_charp key, - png_charp text, png_size_t text_len, int compression)); -#endif - -#if defined(PNG_WRITE_iTXt_SUPPORTED) -PNG_EXTERN void png_write_iTXt PNGARG((png_structp png_ptr, - int compression, png_charp key, png_charp lang, png_charp lang_key, - png_charp text)); -#endif - -#if defined(PNG_TEXT_SUPPORTED) /* Added at version 1.0.14 and 1.2.4 */ -PNG_EXTERN int png_set_text_2 PNGARG((png_structp png_ptr, - png_infop info_ptr, png_textp text_ptr, int num_text)); -#endif - -#if defined(PNG_WRITE_oFFs_SUPPORTED) -PNG_EXTERN void png_write_oFFs PNGARG((png_structp png_ptr, - png_int_32 x_offset, png_int_32 y_offset, int unit_type)); -#endif - -#if defined(PNG_WRITE_pCAL_SUPPORTED) -PNG_EXTERN void png_write_pCAL PNGARG((png_structp png_ptr, png_charp purpose, - png_int_32 X0, png_int_32 X1, int type, int nparams, - png_charp units, png_charpp params)); -#endif - -#if defined(PNG_WRITE_pHYs_SUPPORTED) -PNG_EXTERN void png_write_pHYs PNGARG((png_structp png_ptr, - png_uint_32 x_pixels_per_unit, png_uint_32 y_pixels_per_unit, - int unit_type)); -#endif - -#if defined(PNG_WRITE_tIME_SUPPORTED) -PNG_EXTERN void png_write_tIME PNGARG((png_structp png_ptr, - png_timep mod_time)); -#endif - -#if defined(PNG_WRITE_sCAL_SUPPORTED) -#if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO) -PNG_EXTERN void png_write_sCAL PNGARG((png_structp png_ptr, - int unit, double width, double height)); -#else -#ifdef PNG_FIXED_POINT_SUPPORTED -PNG_EXTERN void png_write_sCAL_s PNGARG((png_structp png_ptr, - int unit, png_charp width, png_charp height)); -#endif -#endif -#endif - -/* Called when finished processing a row of data */ -PNG_EXTERN void png_write_finish_row PNGARG((png_structp png_ptr)); - -/* Internal use only. Called before first row of data */ -PNG_EXTERN void png_write_start_row PNGARG((png_structp png_ptr)); - -#if defined(PNG_READ_GAMMA_SUPPORTED) -PNG_EXTERN void png_build_gamma_table PNGARG((png_structp png_ptr)); -#endif - -/* combine a row of data, dealing with alpha, etc. if requested */ -PNG_EXTERN void png_combine_row PNGARG((png_structp png_ptr, png_bytep row, - int mask)); - -#if defined(PNG_READ_INTERLACING_SUPPORTED) -/* expand an interlaced row */ -/* OLD pre-1.0.9 interface: -PNG_EXTERN void png_do_read_interlace PNGARG((png_row_infop row_info, - png_bytep row, int pass, png_uint_32 transformations)); - */ -PNG_EXTERN void png_do_read_interlace PNGARG((png_structp png_ptr)); -#endif - -/* GRR TO DO (2.0 or whenever): simplify other internal calling interfaces */ - -#if defined(PNG_WRITE_INTERLACING_SUPPORTED) -/* grab pixels out of a row for an interlaced pass */ -PNG_EXTERN void png_do_write_interlace PNGARG((png_row_infop row_info, - png_bytep row, int pass)); -#endif - -/* unfilter a row */ -PNG_EXTERN void png_read_filter_row PNGARG((png_structp png_ptr, - png_row_infop row_info, png_bytep row, png_bytep prev_row, int filter)); - -/* Choose the best filter to use and filter the row data */ -PNG_EXTERN void png_write_find_filter PNGARG((png_structp png_ptr, - png_row_infop row_info)); - -/* Write out the filtered row. */ -PNG_EXTERN void png_write_filtered_row PNGARG((png_structp png_ptr, - png_bytep filtered_row)); -/* finish a row while reading, dealing with interlacing passes, etc. */ -PNG_EXTERN void png_read_finish_row PNGARG((png_structp png_ptr)); - -/* initialize the row buffers, etc. */ -PNG_EXTERN void png_read_start_row PNGARG((png_structp png_ptr)); -/* optional call to update the users info structure */ -PNG_EXTERN void png_read_transform_info PNGARG((png_structp png_ptr, - png_infop info_ptr)); - -/* these are the functions that do the transformations */ -#if defined(PNG_READ_FILLER_SUPPORTED) -PNG_EXTERN void png_do_read_filler PNGARG((png_row_infop row_info, - png_bytep row, png_uint_32 filler, png_uint_32 flags)); -#endif - -#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) -PNG_EXTERN void png_do_read_swap_alpha PNGARG((png_row_infop row_info, - png_bytep row)); -#endif - -#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) -PNG_EXTERN void png_do_write_swap_alpha PNGARG((png_row_infop row_info, - png_bytep row)); -#endif - -#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) -PNG_EXTERN void png_do_read_invert_alpha PNGARG((png_row_infop row_info, - png_bytep row)); -#endif - -#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) -PNG_EXTERN void png_do_write_invert_alpha PNGARG((png_row_infop row_info, - png_bytep row)); -#endif - -#if defined(PNG_WRITE_FILLER_SUPPORTED) || \ - defined(PNG_READ_STRIP_ALPHA_SUPPORTED) -PNG_EXTERN void png_do_strip_filler PNGARG((png_row_infop row_info, - png_bytep row, png_uint_32 flags)); -#endif - -#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) -PNG_EXTERN void png_do_swap PNGARG((png_row_infop row_info, png_bytep row)); -#endif - -#if defined(PNG_READ_PACKSWAP_SUPPORTED) || defined(PNG_WRITE_PACKSWAP_SUPPORTED) -PNG_EXTERN void png_do_packswap PNGARG((png_row_infop row_info, png_bytep row)); -#endif - -#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) -PNG_EXTERN int png_do_rgb_to_gray PNGARG((png_structp png_ptr, png_row_infop - row_info, png_bytep row)); -#endif - -#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) -PNG_EXTERN void png_do_gray_to_rgb PNGARG((png_row_infop row_info, - png_bytep row)); -#endif - -#if defined(PNG_READ_PACK_SUPPORTED) -PNG_EXTERN void png_do_unpack PNGARG((png_row_infop row_info, png_bytep row)); -#endif - -#if defined(PNG_READ_SHIFT_SUPPORTED) -PNG_EXTERN void png_do_unshift PNGARG((png_row_infop row_info, png_bytep row, - png_color_8p sig_bits)); -#endif - -#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) -PNG_EXTERN void png_do_invert PNGARG((png_row_infop row_info, png_bytep row)); -#endif - -#if defined(PNG_READ_16_TO_8_SUPPORTED) -PNG_EXTERN void png_do_chop PNGARG((png_row_infop row_info, png_bytep row)); -#endif - -#if defined(PNG_READ_DITHER_SUPPORTED) -PNG_EXTERN void png_do_dither PNGARG((png_row_infop row_info, - png_bytep row, png_bytep palette_lookup, png_bytep dither_lookup)); - -# if defined(PNG_CORRECT_PALETTE_SUPPORTED) -PNG_EXTERN void png_correct_palette PNGARG((png_structp png_ptr, - png_colorp palette, int num_palette)); -# endif -#endif - -#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) -PNG_EXTERN void png_do_bgr PNGARG((png_row_infop row_info, png_bytep row)); -#endif - -#if defined(PNG_WRITE_PACK_SUPPORTED) -PNG_EXTERN void png_do_pack PNGARG((png_row_infop row_info, - png_bytep row, png_uint_32 bit_depth)); -#endif - -#if defined(PNG_WRITE_SHIFT_SUPPORTED) -PNG_EXTERN void png_do_shift PNGARG((png_row_infop row_info, png_bytep row, - png_color_8p bit_depth)); -#endif - -#if defined(PNG_READ_BACKGROUND_SUPPORTED) -#if defined(PNG_READ_GAMMA_SUPPORTED) -PNG_EXTERN void png_do_background PNGARG((png_row_infop row_info, png_bytep row, - png_color_16p trans_values, png_color_16p background, - png_color_16p background_1, - png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1, - png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1, - png_uint_16pp gamma_16_to_1, int gamma_shift)); -#else -PNG_EXTERN void png_do_background PNGARG((png_row_infop row_info, png_bytep row, - png_color_16p trans_values, png_color_16p background)); -#endif -#endif - -#if defined(PNG_READ_GAMMA_SUPPORTED) -PNG_EXTERN void png_do_gamma PNGARG((png_row_infop row_info, png_bytep row, - png_bytep gamma_table, png_uint_16pp gamma_16_table, - int gamma_shift)); -#endif - -#if defined(PNG_READ_EXPAND_SUPPORTED) -PNG_EXTERN void png_do_expand_palette PNGARG((png_row_infop row_info, - png_bytep row, png_colorp palette, png_bytep trans, int num_trans)); -PNG_EXTERN void png_do_expand PNGARG((png_row_infop row_info, - png_bytep row, png_color_16p trans_value)); -#endif - -/* The following decodes the appropriate chunks, and does error correction, - * then calls the appropriate callback for the chunk if it is valid. - */ - -/* decode the IHDR chunk */ -PNG_EXTERN void png_handle_IHDR PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -PNG_EXTERN void png_handle_PLTE PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -PNG_EXTERN void png_handle_IEND PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); - -#if defined(PNG_READ_bKGD_SUPPORTED) -PNG_EXTERN void png_handle_bKGD PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#if defined(PNG_READ_cHRM_SUPPORTED) -PNG_EXTERN void png_handle_cHRM PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#if defined(PNG_READ_gAMA_SUPPORTED) -PNG_EXTERN void png_handle_gAMA PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#if defined(PNG_READ_hIST_SUPPORTED) -PNG_EXTERN void png_handle_hIST PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#if defined(PNG_READ_iCCP_SUPPORTED) -extern void png_handle_iCCP PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif /* PNG_READ_iCCP_SUPPORTED */ - -#if defined(PNG_READ_iTXt_SUPPORTED) -PNG_EXTERN void png_handle_iTXt PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#if defined(PNG_READ_oFFs_SUPPORTED) -PNG_EXTERN void png_handle_oFFs PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#if defined(PNG_READ_pCAL_SUPPORTED) -PNG_EXTERN void png_handle_pCAL PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#if defined(PNG_READ_pHYs_SUPPORTED) -PNG_EXTERN void png_handle_pHYs PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#if defined(PNG_READ_sBIT_SUPPORTED) -PNG_EXTERN void png_handle_sBIT PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#if defined(PNG_READ_sCAL_SUPPORTED) -PNG_EXTERN void png_handle_sCAL PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#if defined(PNG_READ_sPLT_SUPPORTED) -extern void png_handle_sPLT PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif /* PNG_READ_sPLT_SUPPORTED */ - -#if defined(PNG_READ_sRGB_SUPPORTED) -PNG_EXTERN void png_handle_sRGB PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#if defined(PNG_READ_tEXt_SUPPORTED) -PNG_EXTERN void png_handle_tEXt PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#if defined(PNG_READ_tIME_SUPPORTED) -PNG_EXTERN void png_handle_tIME PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#if defined(PNG_READ_tRNS_SUPPORTED) -PNG_EXTERN void png_handle_tRNS PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#if defined(PNG_READ_zTXt_SUPPORTED) -PNG_EXTERN void png_handle_zTXt PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -PNG_EXTERN void png_handle_unknown PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 length)); - -PNG_EXTERN void png_check_chunk_name PNGARG((png_structp png_ptr, - png_bytep chunk_name)); - -/* handle the transformations for reading and writing */ -PNG_EXTERN void png_do_read_transformations PNGARG((png_structp png_ptr)); -PNG_EXTERN void png_do_write_transformations PNGARG((png_structp png_ptr)); - -PNG_EXTERN void png_init_read_transformations PNGARG((png_structp png_ptr)); - -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED -PNG_EXTERN void png_push_read_chunk PNGARG((png_structp png_ptr, - png_infop info_ptr)); -PNG_EXTERN void png_push_read_sig PNGARG((png_structp png_ptr, - png_infop info_ptr)); -PNG_EXTERN void png_push_check_crc PNGARG((png_structp png_ptr)); -PNG_EXTERN void png_push_crc_skip PNGARG((png_structp png_ptr, - png_uint_32 length)); -PNG_EXTERN void png_push_crc_finish PNGARG((png_structp png_ptr)); -PNG_EXTERN void png_push_save_buffer PNGARG((png_structp png_ptr)); -PNG_EXTERN void png_push_restore_buffer PNGARG((png_structp png_ptr, - png_bytep buffer, png_size_t buffer_length)); -PNG_EXTERN void png_push_read_IDAT PNGARG((png_structp png_ptr)); -PNG_EXTERN void png_process_IDAT_data PNGARG((png_structp png_ptr, - png_bytep buffer, png_size_t buffer_length)); -PNG_EXTERN void png_push_process_row PNGARG((png_structp png_ptr)); -PNG_EXTERN void png_push_handle_unknown PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 length)); -PNG_EXTERN void png_push_have_info PNGARG((png_structp png_ptr, - png_infop info_ptr)); -PNG_EXTERN void png_push_have_end PNGARG((png_structp png_ptr, - png_infop info_ptr)); -PNG_EXTERN void png_push_have_row PNGARG((png_structp png_ptr, png_bytep row)); -PNG_EXTERN void png_push_read_end PNGARG((png_structp png_ptr, - png_infop info_ptr)); -PNG_EXTERN void png_process_some_data PNGARG((png_structp png_ptr, - png_infop info_ptr)); -PNG_EXTERN void png_read_push_finish_row PNGARG((png_structp png_ptr)); -#if defined(PNG_READ_tEXt_SUPPORTED) -PNG_EXTERN void png_push_handle_tEXt PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 length)); -PNG_EXTERN void png_push_read_tEXt PNGARG((png_structp png_ptr, - png_infop info_ptr)); -#endif -#if defined(PNG_READ_zTXt_SUPPORTED) -PNG_EXTERN void png_push_handle_zTXt PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 length)); -PNG_EXTERN void png_push_read_zTXt PNGARG((png_structp png_ptr, - png_infop info_ptr)); -#endif -#if defined(PNG_READ_iTXt_SUPPORTED) -PNG_EXTERN void png_push_handle_iTXt PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 length)); -PNG_EXTERN void png_push_read_iTXt PNGARG((png_structp png_ptr, - png_infop info_ptr)); -#endif - -#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ - -#ifdef PNG_MNG_FEATURES_SUPPORTED -PNG_EXTERN void png_do_read_intrapixel PNGARG((png_row_infop row_info, - png_bytep row)); -PNG_EXTERN void png_do_write_intrapixel PNGARG((png_row_infop row_info, - png_bytep row)); -#endif - -#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) -#if defined(PNG_MMX_CODE_SUPPORTED) -/* png.c */ /* PRIVATE */ -PNG_EXTERN void png_init_mmx_flags PNGARG((png_structp png_ptr)); -#endif -#endif - -#if defined(PNG_INCH_CONVERSIONS) && defined(PNG_FLOATING_POINT_SUPPORTED) -PNG_EXTERN png_uint_32 png_get_pixels_per_inch PNGARG((png_structp png_ptr, -png_infop info_ptr)); - -PNG_EXTERN png_uint_32 png_get_x_pixels_per_inch PNGARG((png_structp png_ptr, -png_infop info_ptr)); - -PNG_EXTERN png_uint_32 png_get_y_pixels_per_inch PNGARG((png_structp png_ptr, -png_infop info_ptr)); - -PNG_EXTERN float png_get_x_offset_inches PNGARG((png_structp png_ptr, -png_infop info_ptr)); - -PNG_EXTERN float png_get_y_offset_inches PNGARG((png_structp png_ptr, -png_infop info_ptr)); - -#if defined(PNG_pHYs_SUPPORTED) -PNG_EXTERN png_uint_32 png_get_pHYs_dpi PNGARG((png_structp png_ptr, -png_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)); -#endif /* PNG_pHYs_SUPPORTED */ -#endif /* PNG_INCH_CONVERSIONS && PNG_FLOATING_POINT_SUPPORTED */ - -/* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */ - -#endif /* PNG_INTERNAL */ - -#ifdef __cplusplus -} -#endif - -#endif /* PNG_VERSION_INFO_ONLY */ -/* do not put anything past this line */ -#endif /* PNG_H */ diff --git a/rosapps/lib/libpng/pngconf.h b/rosapps/lib/libpng/pngconf.h deleted file mode 100644 index c40507446fe..00000000000 --- a/rosapps/lib/libpng/pngconf.h +++ /dev/null @@ -1,1481 +0,0 @@ - -/* pngconf.h - machine configurable file for libpng - * - * libpng version 1.2.24 - December 14, 2007 - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2007 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - */ - -/* Any machine specific code is near the front of this file, so if you - * are configuring libpng for a machine, you may want to read the section - * starting here down to where it starts to typedef png_color, png_text, - * and png_info. - */ - -#ifndef PNGCONF_H -#define PNGCONF_H - -#define PNG_1_2_X - -/* - * PNG_USER_CONFIG has to be defined on the compiler command line. This - * includes the resource compiler for Windows DLL configurations. - */ -#ifdef PNG_USER_CONFIG -# ifndef PNG_USER_PRIVATEBUILD -# define PNG_USER_PRIVATEBUILD -# endif -#include "pngusr.h" -#endif - -/* PNG_CONFIGURE_LIBPNG is set by the "configure" script. */ -#ifdef PNG_CONFIGURE_LIBPNG -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#endif - -/* - * Added at libpng-1.2.8 - * - * If you create a private DLL you need to define in "pngusr.h" the followings: - * #define PNG_USER_PRIVATEBUILD - * e.g. #define PNG_USER_PRIVATEBUILD "Build by MyCompany for xyz reasons." - * #define PNG_USER_DLLFNAME_POSTFIX - * e.g. // private DLL "libpng13gx.dll" - * #define PNG_USER_DLLFNAME_POSTFIX "gx" - * - * The following macros are also at your disposal if you want to complete the - * DLL VERSIONINFO structure. - * - PNG_USER_VERSIONINFO_COMMENTS - * - PNG_USER_VERSIONINFO_COMPANYNAME - * - PNG_USER_VERSIONINFO_LEGALTRADEMARKS - */ - -#ifdef __STDC__ -#ifdef SPECIALBUILD -# pragma message("PNG_LIBPNG_SPECIALBUILD (and deprecated SPECIALBUILD)\ - are now LIBPNG reserved macros. Use PNG_USER_PRIVATEBUILD instead.") -#endif - -#ifdef PRIVATEBUILD -# pragma message("PRIVATEBUILD is deprecated.\ - Use PNG_USER_PRIVATEBUILD instead.") -# define PNG_USER_PRIVATEBUILD PRIVATEBUILD -#endif -#endif /* __STDC__ */ - -#ifndef PNG_VERSION_INFO_ONLY - -/* End of material added to libpng-1.2.8 */ - -/* Added at libpng-1.2.19, removed at libpng-1.2.20 because it caused trouble - Restored at libpng-1.2.21 */ -#if !defined(PNG_NO_WARN_UNINITIALIZED_ROW) && \ - !defined(PNG_WARN_UNINITIALIZED_ROW) -# define PNG_WARN_UNINITIALIZED_ROW 1 -#endif -/* End of material added at libpng-1.2.19/1.2.21 */ - -/* This is the size of the compression buffer, and thus the size of - * an IDAT chunk. Make this whatever size you feel is best for your - * machine. One of these will be allocated per png_struct. When this - * is full, it writes the data to the disk, and does some other - * calculations. Making this an extremely small size will slow - * the library down, but you may want to experiment to determine - * where it becomes significant, if you are concerned with memory - * usage. Note that zlib allocates at least 32Kb also. For readers, - * this describes the size of the buffer available to read the data in. - * Unless this gets smaller than the size of a row (compressed), - * it should not make much difference how big this is. - */ - -#ifndef PNG_ZBUF_SIZE -# define PNG_ZBUF_SIZE 8192 -#endif - -/* Enable if you want a write-only libpng */ - -#ifndef PNG_NO_READ_SUPPORTED -# define PNG_READ_SUPPORTED -#endif - -/* Enable if you want a read-only libpng */ - -#ifndef PNG_NO_WRITE_SUPPORTED -# define PNG_WRITE_SUPPORTED -#endif - -/* Enabled by default in 1.2.0. You can disable this if you don't need to - support PNGs that are embedded in MNG datastreams */ -#if !defined(PNG_1_0_X) && !defined(PNG_NO_MNG_FEATURES) -# ifndef PNG_MNG_FEATURES_SUPPORTED -# define PNG_MNG_FEATURES_SUPPORTED -# endif -#endif - -#ifndef PNG_NO_FLOATING_POINT_SUPPORTED -# ifndef PNG_FLOATING_POINT_SUPPORTED -# define PNG_FLOATING_POINT_SUPPORTED -# endif -#endif - -/* If you are running on a machine where you cannot allocate more - * than 64K of memory at once, uncomment this. While libpng will not - * normally need that much memory in a chunk (unless you load up a very - * large file), zlib needs to know how big of a chunk it can use, and - * libpng thus makes sure to check any memory allocation to verify it - * will fit into memory. -#define PNG_MAX_MALLOC_64K - */ -#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K) -# define PNG_MAX_MALLOC_64K -#endif - -/* Special munging to support doing things the 'cygwin' way: - * 'Normal' png-on-win32 defines/defaults: - * PNG_BUILD_DLL -- building dll - * PNG_USE_DLL -- building an application, linking to dll - * (no define) -- building static library, or building an - * application and linking to the static lib - * 'Cygwin' defines/defaults: - * PNG_BUILD_DLL -- (ignored) building the dll - * (no define) -- (ignored) building an application, linking to the dll - * PNG_STATIC -- (ignored) building the static lib, or building an - * application that links to the static lib. - * ALL_STATIC -- (ignored) building various static libs, or building an - * application that links to the static libs. - * Thus, - * a cygwin user should define either PNG_BUILD_DLL or PNG_STATIC, and - * this bit of #ifdefs will define the 'correct' config variables based on - * that. If a cygwin user *wants* to define 'PNG_USE_DLL' that's okay, but - * unnecessary. - * - * Also, the precedence order is: - * ALL_STATIC (since we can't #undef something outside our namespace) - * PNG_BUILD_DLL - * PNG_STATIC - * (nothing) == PNG_USE_DLL - * - * CYGWIN (2002-01-20): The preceding is now obsolete. With the advent - * of auto-import in binutils, we no longer need to worry about - * __declspec(dllexport) / __declspec(dllimport) and friends. Therefore, - * we don't need to worry about PNG_STATIC or ALL_STATIC when it comes - * to __declspec() stuff. However, we DO need to worry about - * PNG_BUILD_DLL and PNG_STATIC because those change some defaults - * such as CONSOLE_IO and whether GLOBAL_ARRAYS are allowed. - */ -#if defined(__CYGWIN__) -# if defined(ALL_STATIC) -# if defined(PNG_BUILD_DLL) -# undef PNG_BUILD_DLL -# endif -# if defined(PNG_USE_DLL) -# undef PNG_USE_DLL -# endif -# if defined(PNG_DLL) -# undef PNG_DLL -# endif -# if !defined(PNG_STATIC) -# define PNG_STATIC -# endif -# else -# if defined (PNG_BUILD_DLL) -# if defined(PNG_STATIC) -# undef PNG_STATIC -# endif -# if defined(PNG_USE_DLL) -# undef PNG_USE_DLL -# endif -# if !defined(PNG_DLL) -# define PNG_DLL -# endif -# else -# if defined(PNG_STATIC) -# if defined(PNG_USE_DLL) -# undef PNG_USE_DLL -# endif -# if defined(PNG_DLL) -# undef PNG_DLL -# endif -# else -# if !defined(PNG_USE_DLL) -# define PNG_USE_DLL -# endif -# if !defined(PNG_DLL) -# define PNG_DLL -# endif -# endif -# endif -# endif -#endif - -/* This protects us against compilers that run on a windowing system - * and thus don't have or would rather us not use the stdio types: - * stdin, stdout, and stderr. The only one currently used is stderr - * in png_error() and png_warning(). #defining PNG_NO_CONSOLE_IO will - * prevent these from being compiled and used. #defining PNG_NO_STDIO - * will also prevent these, plus will prevent the entire set of stdio - * macros and functions (FILE *, printf, etc.) from being compiled and used, - * unless (PNG_DEBUG > 0) has been #defined. - * - * #define PNG_NO_CONSOLE_IO - * #define PNG_NO_STDIO - */ - -#if defined(_WIN32_WCE) -# include - /* Console I/O functions are not supported on WindowsCE */ -# define PNG_NO_CONSOLE_IO -# ifdef PNG_DEBUG -# undef PNG_DEBUG -# endif -#endif - -#ifdef PNG_BUILD_DLL -# ifndef PNG_CONSOLE_IO_SUPPORTED -# ifndef PNG_NO_CONSOLE_IO -# define PNG_NO_CONSOLE_IO -# endif -# endif -#endif - -# ifdef PNG_NO_STDIO -# ifndef PNG_NO_CONSOLE_IO -# define PNG_NO_CONSOLE_IO -# endif -# ifdef PNG_DEBUG -# if (PNG_DEBUG > 0) -# include -# endif -# endif -# else -# if !defined(_WIN32_WCE) -/* "stdio.h" functions are not supported on WindowsCE */ -# include -# endif -# endif - -/* This macro protects us against machines that don't have function - * prototypes (ie K&R style headers). If your compiler does not handle - * function prototypes, define this macro and use the included ansi2knr. - * I've always been able to use _NO_PROTO as the indicator, but you may - * need to drag the empty declaration out in front of here, or change the - * ifdef to suit your own needs. - */ -#ifndef PNGARG - -#ifdef OF /* zlib prototype munger */ -# define PNGARG(arglist) OF(arglist) -#else - -#ifdef _NO_PROTO -# define PNGARG(arglist) () -# ifndef PNG_TYPECAST_NULL -# define PNG_TYPECAST_NULL -# endif -#else -# define PNGARG(arglist) arglist -#endif /* _NO_PROTO */ - - -#endif /* OF */ - -#endif /* PNGARG */ - -/* Try to determine if we are compiling on a Mac. Note that testing for - * just __MWERKS__ is not good enough, because the Codewarrior is now used - * on non-Mac platforms. - */ -#ifndef MACOS -# if (defined(__MWERKS__) && defined(macintosh)) || defined(applec) || \ - defined(THINK_C) || defined(__SC__) || defined(TARGET_OS_MAC) -# define MACOS -# endif -#endif - -/* enough people need this for various reasons to include it here */ -#if !defined(MACOS) && !defined(RISCOS) && !defined(_WIN32_WCE) -# include -#endif - -#if !defined(PNG_SETJMP_NOT_SUPPORTED) && !defined(PNG_NO_SETJMP_SUPPORTED) -# define PNG_SETJMP_SUPPORTED -#endif - -#ifdef PNG_SETJMP_SUPPORTED -/* This is an attempt to force a single setjmp behaviour on Linux. If - * the X config stuff didn't define _BSD_SOURCE we wouldn't need this. - */ - -# ifdef __linux__ -# ifdef _BSD_SOURCE -# define PNG_SAVE_BSD_SOURCE -# undef _BSD_SOURCE -# endif -# ifdef _SETJMP_H - /* If you encounter a compiler error here, see the explanation - * near the end of INSTALL. - */ - __pngconf.h__ already includes setjmp.h; - __dont__ include it again.; -# endif -# endif /* __linux__ */ - - /* include setjmp.h for error handling */ -# include - -# ifdef __linux__ -# ifdef PNG_SAVE_BSD_SOURCE -# ifndef _BSD_SOURCE -# define _BSD_SOURCE -# endif -# undef PNG_SAVE_BSD_SOURCE -# endif -# endif /* __linux__ */ -#endif /* PNG_SETJMP_SUPPORTED */ - -#ifdef BSD -# include -#else -# include -#endif - -/* Other defines for things like memory and the like can go here. */ -#ifdef PNG_INTERNAL - -#include - -/* The functions exported by PNG_EXTERN are PNG_INTERNAL functions, which - * aren't usually used outside the library (as far as I know), so it is - * debatable if they should be exported at all. In the future, when it is - * possible to have run-time registry of chunk-handling functions, some of - * these will be made available again. -#define PNG_EXTERN extern - */ -#define PNG_EXTERN - -/* Other defines specific to compilers can go here. Try to keep - * them inside an appropriate ifdef/endif pair for portability. - */ - -#if defined(PNG_FLOATING_POINT_SUPPORTED) -# if defined(MACOS) - /* We need to check that hasn't already been included earlier - * as it seems it doesn't agree with , yet we should really use - * if possible. - */ -# if !defined(__MATH_H__) && !defined(__MATH_H) && !defined(__cmath__) -# include -# endif -# else -# include -# endif -# if defined(_AMIGA) && defined(__SASC) && defined(_M68881) - /* Amiga SAS/C: We must include builtin FPU functions when compiling using - * MATH=68881 - */ -# include -# endif -#endif - -/* Codewarrior on NT has linking problems without this. */ -#if (defined(__MWERKS__) && defined(WIN32)) || defined(__STDC__) -# define PNG_ALWAYS_EXTERN -#endif - -/* This provides the non-ANSI (far) memory allocation routines. */ -#if defined(__TURBOC__) && defined(__MSDOS__) -# include -# include -#endif - -/* I have no idea why is this necessary... */ -#if defined(_MSC_VER) && (defined(WIN32) || defined(_Windows) || \ - defined(_WINDOWS) || defined(_WIN32) || defined(__WIN32__)) -# include -#endif - -/* This controls how fine the dithering gets. As this allocates - * a largish chunk of memory (32K), those who are not as concerned - * with dithering quality can decrease some or all of these. - */ -#ifndef PNG_DITHER_RED_BITS -# define PNG_DITHER_RED_BITS 5 -#endif -#ifndef PNG_DITHER_GREEN_BITS -# define PNG_DITHER_GREEN_BITS 5 -#endif -#ifndef PNG_DITHER_BLUE_BITS -# define PNG_DITHER_BLUE_BITS 5 -#endif - -/* This controls how fine the gamma correction becomes when you - * are only interested in 8 bits anyway. Increasing this value - * results in more memory being used, and more pow() functions - * being called to fill in the gamma tables. Don't set this value - * less then 8, and even that may not work (I haven't tested it). - */ - -#ifndef PNG_MAX_GAMMA_8 -# define PNG_MAX_GAMMA_8 11 -#endif - -/* This controls how much a difference in gamma we can tolerate before - * we actually start doing gamma conversion. - */ -#ifndef PNG_GAMMA_THRESHOLD -# define PNG_GAMMA_THRESHOLD 0.05 -#endif - -#endif /* PNG_INTERNAL */ - -/* The following uses const char * instead of char * for error - * and warning message functions, so some compilers won't complain. - * If you do not want to use const, define PNG_NO_CONST here. - */ - -#ifndef PNG_NO_CONST -# define PNG_CONST const -#else -# define PNG_CONST -#endif - -/* The following defines give you the ability to remove code from the - * library that you will not be using. I wish I could figure out how to - * automate this, but I can't do that without making it seriously hard - * on the users. So if you are not using an ability, change the #define - * to and #undef, and that part of the library will not be compiled. If - * your linker can't find a function, you may want to make sure the - * ability is defined here. Some of these depend upon some others being - * defined. I haven't figured out all the interactions here, so you may - * have to experiment awhile to get everything to compile. If you are - * creating or using a shared library, you probably shouldn't touch this, - * as it will affect the size of the structures, and this will cause bad - * things to happen if the library and/or application ever change. - */ - -/* Any features you will not be using can be undef'ed here */ - -/* GR-P, 0.96a: Set "*TRANSFORMS_SUPPORTED as default but allow user - * to turn it off with "*TRANSFORMS_NOT_SUPPORTED" or *PNG_NO_*_TRANSFORMS - * on the compile line, then pick and choose which ones to define without - * having to edit this file. It is safe to use the *TRANSFORMS_NOT_SUPPORTED - * if you only want to have a png-compliant reader/writer but don't need - * any of the extra transformations. This saves about 80 kbytes in a - * typical installation of the library. (PNG_NO_* form added in version - * 1.0.1c, for consistency) - */ - -/* The size of the png_text structure changed in libpng-1.0.6 when - * iTXt support was added. iTXt support was turned off by default through - * libpng-1.2.x, to support old apps that malloc the png_text structure - * instead of calling png_set_text() and letting libpng malloc it. It - * was turned on by default in libpng-1.3.0. - */ - -#if defined(PNG_1_0_X) || defined (PNG_1_2_X) -# ifndef PNG_NO_iTXt_SUPPORTED -# define PNG_NO_iTXt_SUPPORTED -# endif -# ifndef PNG_NO_READ_iTXt -# define PNG_NO_READ_iTXt -# endif -# ifndef PNG_NO_WRITE_iTXt -# define PNG_NO_WRITE_iTXt -# endif -#endif - -#if !defined(PNG_NO_iTXt_SUPPORTED) -# if !defined(PNG_READ_iTXt_SUPPORTED) && !defined(PNG_NO_READ_iTXt) -# define PNG_READ_iTXt -# endif -# if !defined(PNG_WRITE_iTXt_SUPPORTED) && !defined(PNG_NO_WRITE_iTXt) -# define PNG_WRITE_iTXt -# endif -#endif - -/* The following support, added after version 1.0.0, can be turned off here en - * masse by defining PNG_LEGACY_SUPPORTED in case you need binary compatibility - * with old applications that require the length of png_struct and png_info - * to remain unchanged. - */ - -#ifdef PNG_LEGACY_SUPPORTED -# define PNG_NO_FREE_ME -# define PNG_NO_READ_UNKNOWN_CHUNKS -# define PNG_NO_WRITE_UNKNOWN_CHUNKS -# define PNG_NO_READ_USER_CHUNKS -# define PNG_NO_READ_iCCP -# define PNG_NO_WRITE_iCCP -# define PNG_NO_READ_iTXt -# define PNG_NO_WRITE_iTXt -# define PNG_NO_READ_sCAL -# define PNG_NO_WRITE_sCAL -# define PNG_NO_READ_sPLT -# define PNG_NO_WRITE_sPLT -# define PNG_NO_INFO_IMAGE -# define PNG_NO_READ_RGB_TO_GRAY -# define PNG_NO_READ_USER_TRANSFORM -# define PNG_NO_WRITE_USER_TRANSFORM -# define PNG_NO_USER_MEM -# define PNG_NO_READ_EMPTY_PLTE -# define PNG_NO_MNG_FEATURES -# define PNG_NO_FIXED_POINT_SUPPORTED -#endif - -/* Ignore attempt to turn off both floating and fixed point support */ -#if !defined(PNG_FLOATING_POINT_SUPPORTED) || \ - !defined(PNG_NO_FIXED_POINT_SUPPORTED) -# define PNG_FIXED_POINT_SUPPORTED -#endif - -#ifndef PNG_NO_FREE_ME -# define PNG_FREE_ME_SUPPORTED -#endif - -#if defined(PNG_READ_SUPPORTED) - -#if !defined(PNG_READ_TRANSFORMS_NOT_SUPPORTED) && \ - !defined(PNG_NO_READ_TRANSFORMS) -# define PNG_READ_TRANSFORMS_SUPPORTED -#endif - -#ifdef PNG_READ_TRANSFORMS_SUPPORTED -# ifndef PNG_NO_READ_EXPAND -# define PNG_READ_EXPAND_SUPPORTED -# endif -# ifndef PNG_NO_READ_SHIFT -# define PNG_READ_SHIFT_SUPPORTED -# endif -# ifndef PNG_NO_READ_PACK -# define PNG_READ_PACK_SUPPORTED -# endif -# ifndef PNG_NO_READ_BGR -# define PNG_READ_BGR_SUPPORTED -# endif -# ifndef PNG_NO_READ_SWAP -# define PNG_READ_SWAP_SUPPORTED -# endif -# ifndef PNG_NO_READ_PACKSWAP -# define PNG_READ_PACKSWAP_SUPPORTED -# endif -# ifndef PNG_NO_READ_INVERT -# define PNG_READ_INVERT_SUPPORTED -# endif -# ifndef PNG_NO_READ_DITHER -# define PNG_READ_DITHER_SUPPORTED -# endif -# ifndef PNG_NO_READ_BACKGROUND -# define PNG_READ_BACKGROUND_SUPPORTED -# endif -# ifndef PNG_NO_READ_16_TO_8 -# define PNG_READ_16_TO_8_SUPPORTED -# endif -# ifndef PNG_NO_READ_FILLER -# define PNG_READ_FILLER_SUPPORTED -# endif -# ifndef PNG_NO_READ_GAMMA -# define PNG_READ_GAMMA_SUPPORTED -# endif -# ifndef PNG_NO_READ_GRAY_TO_RGB -# define PNG_READ_GRAY_TO_RGB_SUPPORTED -# endif -# ifndef PNG_NO_READ_SWAP_ALPHA -# define PNG_READ_SWAP_ALPHA_SUPPORTED -# endif -# ifndef PNG_NO_READ_INVERT_ALPHA -# define PNG_READ_INVERT_ALPHA_SUPPORTED -# endif -# ifndef PNG_NO_READ_STRIP_ALPHA -# define PNG_READ_STRIP_ALPHA_SUPPORTED -# endif -# ifndef PNG_NO_READ_USER_TRANSFORM -# define PNG_READ_USER_TRANSFORM_SUPPORTED -# endif -# ifndef PNG_NO_READ_RGB_TO_GRAY -# define PNG_READ_RGB_TO_GRAY_SUPPORTED -# endif -#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ - -#if !defined(PNG_NO_PROGRESSIVE_READ) && \ - !defined(PNG_PROGRESSIVE_READ_SUPPORTED) /* if you don't do progressive */ -# define PNG_PROGRESSIVE_READ_SUPPORTED /* reading. This is not talking */ -#endif /* about interlacing capability! You'll */ - /* still have interlacing unless you change the following line: */ - -#define PNG_READ_INTERLACING_SUPPORTED /* required in PNG-compliant decoders */ - -#ifndef PNG_NO_READ_COMPOSITE_NODIV -# ifndef PNG_NO_READ_COMPOSITED_NODIV /* libpng-1.0.x misspelling */ -# define PNG_READ_COMPOSITE_NODIV_SUPPORTED /* well tested on Intel, SGI */ -# endif -#endif - -#if defined(PNG_1_0_X) || defined (PNG_1_2_X) -/* Deprecated, will be removed from version 2.0.0. - Use PNG_MNG_FEATURES_SUPPORTED instead. */ -#ifndef PNG_NO_READ_EMPTY_PLTE -# define PNG_READ_EMPTY_PLTE_SUPPORTED -#endif -#endif - -#endif /* PNG_READ_SUPPORTED */ - -#if defined(PNG_WRITE_SUPPORTED) - -# if !defined(PNG_WRITE_TRANSFORMS_NOT_SUPPORTED) && \ - !defined(PNG_NO_WRITE_TRANSFORMS) -# define PNG_WRITE_TRANSFORMS_SUPPORTED -#endif - -#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED -# ifndef PNG_NO_WRITE_SHIFT -# define PNG_WRITE_SHIFT_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_PACK -# define PNG_WRITE_PACK_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_BGR -# define PNG_WRITE_BGR_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_SWAP -# define PNG_WRITE_SWAP_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_PACKSWAP -# define PNG_WRITE_PACKSWAP_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_INVERT -# define PNG_WRITE_INVERT_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_FILLER -# define PNG_WRITE_FILLER_SUPPORTED /* same as WRITE_STRIP_ALPHA */ -# endif -# ifndef PNG_NO_WRITE_SWAP_ALPHA -# define PNG_WRITE_SWAP_ALPHA_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_INVERT_ALPHA -# define PNG_WRITE_INVERT_ALPHA_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_USER_TRANSFORM -# define PNG_WRITE_USER_TRANSFORM_SUPPORTED -# endif -#endif /* PNG_WRITE_TRANSFORMS_SUPPORTED */ - -#if !defined(PNG_NO_WRITE_INTERLACING_SUPPORTED) && \ - !defined(PNG_WRITE_INTERLACING_SUPPORTED) -#define PNG_WRITE_INTERLACING_SUPPORTED /* not required for PNG-compliant - encoders, but can cause trouble - if left undefined */ -#endif - -#if !defined(PNG_NO_WRITE_WEIGHTED_FILTER) && \ - !defined(PNG_WRITE_WEIGHTED_FILTER) && \ - defined(PNG_FLOATING_POINT_SUPPORTED) -# define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED -#endif - -#ifndef PNG_NO_WRITE_FLUSH -# define PNG_WRITE_FLUSH_SUPPORTED -#endif - -#if defined(PNG_1_0_X) || defined (PNG_1_2_X) -/* Deprecated, see PNG_MNG_FEATURES_SUPPORTED, above */ -#ifndef PNG_NO_WRITE_EMPTY_PLTE -# define PNG_WRITE_EMPTY_PLTE_SUPPORTED -#endif -#endif - -#endif /* PNG_WRITE_SUPPORTED */ - -#ifndef PNG_1_0_X -# ifndef PNG_NO_ERROR_NUMBERS -# define PNG_ERROR_NUMBERS_SUPPORTED -# endif -#endif /* PNG_1_0_X */ - -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) -# ifndef PNG_NO_USER_TRANSFORM_PTR -# define PNG_USER_TRANSFORM_PTR_SUPPORTED -# endif -#endif - -#ifndef PNG_NO_STDIO -# define PNG_TIME_RFC1123_SUPPORTED -#endif - -/* This adds extra functions in pngget.c for accessing data from the - * info pointer (added in version 0.99) - * png_get_image_width() - * png_get_image_height() - * png_get_bit_depth() - * png_get_color_type() - * png_get_compression_type() - * png_get_filter_type() - * png_get_interlace_type() - * png_get_pixel_aspect_ratio() - * png_get_pixels_per_meter() - * png_get_x_offset_pixels() - * png_get_y_offset_pixels() - * png_get_x_offset_microns() - * png_get_y_offset_microns() - */ -#if !defined(PNG_NO_EASY_ACCESS) && !defined(PNG_EASY_ACCESS_SUPPORTED) -# define PNG_EASY_ACCESS_SUPPORTED -#endif - -/* PNG_ASSEMBLER_CODE was enabled by default in version 1.2.0 - * and removed from version 1.2.20. The following will be removed - * from libpng-1.4.0 -*/ - -#if defined(PNG_READ_SUPPORTED) && !defined(PNG_NO_OPTIMIZED_CODE) -# ifndef PNG_OPTIMIZED_CODE_SUPPORTED -# define PNG_OPTIMIZED_CODE_SUPPORTED -# endif -#endif - -#if defined(PNG_READ_SUPPORTED) && !defined(PNG_NO_ASSEMBLER_CODE) -# ifndef PNG_ASSEMBLER_CODE_SUPPORTED -# define PNG_ASSEMBLER_CODE_SUPPORTED -# endif - -# if defined(__GNUC__) && defined(__x86_64__) && (__GNUC__ < 4) - /* work around 64-bit gcc compiler bugs in gcc-3.x */ -# if !defined(PNG_MMX_CODE_SUPPORTED) && !defined(PNG_NO_MMX_CODE) -# define PNG_NO_MMX_CODE -# endif -# endif - -# if defined(__APPLE__) -# if !defined(PNG_MMX_CODE_SUPPORTED) && !defined(PNG_NO_MMX_CODE) -# define PNG_NO_MMX_CODE -# endif -# endif - -# if (defined(__MWERKS__) && ((__MWERKS__ < 0x0900) || macintosh)) -# if !defined(PNG_MMX_CODE_SUPPORTED) && !defined(PNG_NO_MMX_CODE) -# define PNG_NO_MMX_CODE -# endif -# endif - -# if !defined(PNG_MMX_CODE_SUPPORTED) && !defined(PNG_NO_MMX_CODE) -# define PNG_MMX_CODE_SUPPORTED -# endif - -#endif -/* end of obsolete code to be removed from libpng-1.4.0 */ - -#if !defined(PNG_1_0_X) -#if !defined(PNG_NO_USER_MEM) && !defined(PNG_USER_MEM_SUPPORTED) -# define PNG_USER_MEM_SUPPORTED -#endif -#endif /* PNG_1_0_X */ - -/* Added at libpng-1.2.6 */ -#if !defined(PNG_1_0_X) -#ifndef PNG_SET_USER_LIMITS_SUPPORTED -#if !defined(PNG_NO_SET_USER_LIMITS) && !defined(PNG_SET_USER_LIMITS_SUPPORTED) -# define PNG_SET_USER_LIMITS_SUPPORTED -#endif -#endif -#endif /* PNG_1_0_X */ - -/* Added at libpng-1.0.16 and 1.2.6. To accept all valid PNGS no matter - * how large, set these limits to 0x7fffffffL - */ -#ifndef PNG_USER_WIDTH_MAX -# define PNG_USER_WIDTH_MAX 1000000L -#endif -#ifndef PNG_USER_HEIGHT_MAX -# define PNG_USER_HEIGHT_MAX 1000000L -#endif - -/* These are currently experimental features, define them if you want */ - -/* very little testing */ -/* -#ifdef PNG_READ_SUPPORTED -# ifndef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED -# define PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED -# endif -#endif -*/ - -/* This is only for PowerPC big-endian and 680x0 systems */ -/* some testing */ -/* -#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED -# define PNG_READ_BIG_ENDIAN_SUPPORTED -#endif -*/ - -/* Buggy compilers (e.g., gcc 2.7.2.2) need this */ -/* -#define PNG_NO_POINTER_INDEXING -*/ - -/* These functions are turned off by default, as they will be phased out. */ -/* -#define PNG_USELESS_TESTS_SUPPORTED -#define PNG_CORRECT_PALETTE_SUPPORTED -*/ - -/* Any chunks you are not interested in, you can undef here. The - * ones that allocate memory may be expecially important (hIST, - * tEXt, zTXt, tRNS, pCAL). Others will just save time and make png_info - * a bit smaller. - */ - -#if defined(PNG_READ_SUPPORTED) && \ - !defined(PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \ - !defined(PNG_NO_READ_ANCILLARY_CHUNKS) -# define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED -#endif - -#if defined(PNG_WRITE_SUPPORTED) && \ - !defined(PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \ - !defined(PNG_NO_WRITE_ANCILLARY_CHUNKS) -# define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED -#endif - -#ifdef PNG_READ_ANCILLARY_CHUNKS_SUPPORTED - -#ifdef PNG_NO_READ_TEXT -# define PNG_NO_READ_iTXt -# define PNG_NO_READ_tEXt -# define PNG_NO_READ_zTXt -#endif -#ifndef PNG_NO_READ_bKGD -# define PNG_READ_bKGD_SUPPORTED -# define PNG_bKGD_SUPPORTED -#endif -#ifndef PNG_NO_READ_cHRM -# define PNG_READ_cHRM_SUPPORTED -# define PNG_cHRM_SUPPORTED -#endif -#ifndef PNG_NO_READ_gAMA -# define PNG_READ_gAMA_SUPPORTED -# define PNG_gAMA_SUPPORTED -#endif -#ifndef PNG_NO_READ_hIST -# define PNG_READ_hIST_SUPPORTED -# define PNG_hIST_SUPPORTED -#endif -#ifndef PNG_NO_READ_iCCP -# define PNG_READ_iCCP_SUPPORTED -# define PNG_iCCP_SUPPORTED -#endif -#ifndef PNG_NO_READ_iTXt -# ifndef PNG_READ_iTXt_SUPPORTED -# define PNG_READ_iTXt_SUPPORTED -# endif -# ifndef PNG_iTXt_SUPPORTED -# define PNG_iTXt_SUPPORTED -# endif -#endif -#ifndef PNG_NO_READ_oFFs -# define PNG_READ_oFFs_SUPPORTED -# define PNG_oFFs_SUPPORTED -#endif -#ifndef PNG_NO_READ_pCAL -# define PNG_READ_pCAL_SUPPORTED -# define PNG_pCAL_SUPPORTED -#endif -#ifndef PNG_NO_READ_sCAL -# define PNG_READ_sCAL_SUPPORTED -# define PNG_sCAL_SUPPORTED -#endif -#ifndef PNG_NO_READ_pHYs -# define PNG_READ_pHYs_SUPPORTED -# define PNG_pHYs_SUPPORTED -#endif -#ifndef PNG_NO_READ_sBIT -# define PNG_READ_sBIT_SUPPORTED -# define PNG_sBIT_SUPPORTED -#endif -#ifndef PNG_NO_READ_sPLT -# define PNG_READ_sPLT_SUPPORTED -# define PNG_sPLT_SUPPORTED -#endif -#ifndef PNG_NO_READ_sRGB -# define PNG_READ_sRGB_SUPPORTED -# define PNG_sRGB_SUPPORTED -#endif -#ifndef PNG_NO_READ_tEXt -# define PNG_READ_tEXt_SUPPORTED -# define PNG_tEXt_SUPPORTED -#endif -#ifndef PNG_NO_READ_tIME -# define PNG_READ_tIME_SUPPORTED -# define PNG_tIME_SUPPORTED -#endif -#ifndef PNG_NO_READ_tRNS -# define PNG_READ_tRNS_SUPPORTED -# define PNG_tRNS_SUPPORTED -#endif -#ifndef PNG_NO_READ_zTXt -# define PNG_READ_zTXt_SUPPORTED -# define PNG_zTXt_SUPPORTED -#endif -#ifndef PNG_NO_READ_UNKNOWN_CHUNKS -# define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED -# ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED -# define PNG_UNKNOWN_CHUNKS_SUPPORTED -# endif -# ifndef PNG_NO_HANDLE_AS_UNKNOWN -# define PNG_HANDLE_AS_UNKNOWN_SUPPORTED -# endif -#endif -#if !defined(PNG_NO_READ_USER_CHUNKS) && \ - defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) -# define PNG_READ_USER_CHUNKS_SUPPORTED -# define PNG_USER_CHUNKS_SUPPORTED -# ifdef PNG_NO_READ_UNKNOWN_CHUNKS -# undef PNG_NO_READ_UNKNOWN_CHUNKS -# endif -# ifdef PNG_NO_HANDLE_AS_UNKNOWN -# undef PNG_NO_HANDLE_AS_UNKNOWN -# endif -#endif -#ifndef PNG_NO_READ_OPT_PLTE -# define PNG_READ_OPT_PLTE_SUPPORTED /* only affects support of the */ -#endif /* optional PLTE chunk in RGB and RGBA images */ -#if defined(PNG_READ_iTXt_SUPPORTED) || defined(PNG_READ_tEXt_SUPPORTED) || \ - defined(PNG_READ_zTXt_SUPPORTED) -# define PNG_READ_TEXT_SUPPORTED -# define PNG_TEXT_SUPPORTED -#endif - -#endif /* PNG_READ_ANCILLARY_CHUNKS_SUPPORTED */ - -#ifdef PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED - -#ifdef PNG_NO_WRITE_TEXT -# define PNG_NO_WRITE_iTXt -# define PNG_NO_WRITE_tEXt -# define PNG_NO_WRITE_zTXt -#endif -#ifndef PNG_NO_WRITE_bKGD -# define PNG_WRITE_bKGD_SUPPORTED -# ifndef PNG_bKGD_SUPPORTED -# define PNG_bKGD_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_cHRM -# define PNG_WRITE_cHRM_SUPPORTED -# ifndef PNG_cHRM_SUPPORTED -# define PNG_cHRM_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_gAMA -# define PNG_WRITE_gAMA_SUPPORTED -# ifndef PNG_gAMA_SUPPORTED -# define PNG_gAMA_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_hIST -# define PNG_WRITE_hIST_SUPPORTED -# ifndef PNG_hIST_SUPPORTED -# define PNG_hIST_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_iCCP -# define PNG_WRITE_iCCP_SUPPORTED -# ifndef PNG_iCCP_SUPPORTED -# define PNG_iCCP_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_iTXt -# ifndef PNG_WRITE_iTXt_SUPPORTED -# define PNG_WRITE_iTXt_SUPPORTED -# endif -# ifndef PNG_iTXt_SUPPORTED -# define PNG_iTXt_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_oFFs -# define PNG_WRITE_oFFs_SUPPORTED -# ifndef PNG_oFFs_SUPPORTED -# define PNG_oFFs_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_pCAL -# define PNG_WRITE_pCAL_SUPPORTED -# ifndef PNG_pCAL_SUPPORTED -# define PNG_pCAL_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_sCAL -# define PNG_WRITE_sCAL_SUPPORTED -# ifndef PNG_sCAL_SUPPORTED -# define PNG_sCAL_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_pHYs -# define PNG_WRITE_pHYs_SUPPORTED -# ifndef PNG_pHYs_SUPPORTED -# define PNG_pHYs_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_sBIT -# define PNG_WRITE_sBIT_SUPPORTED -# ifndef PNG_sBIT_SUPPORTED -# define PNG_sBIT_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_sPLT -# define PNG_WRITE_sPLT_SUPPORTED -# ifndef PNG_sPLT_SUPPORTED -# define PNG_sPLT_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_sRGB -# define PNG_WRITE_sRGB_SUPPORTED -# ifndef PNG_sRGB_SUPPORTED -# define PNG_sRGB_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_tEXt -# define PNG_WRITE_tEXt_SUPPORTED -# ifndef PNG_tEXt_SUPPORTED -# define PNG_tEXt_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_tIME -# define PNG_WRITE_tIME_SUPPORTED -# ifndef PNG_tIME_SUPPORTED -# define PNG_tIME_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_tRNS -# define PNG_WRITE_tRNS_SUPPORTED -# ifndef PNG_tRNS_SUPPORTED -# define PNG_tRNS_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_zTXt -# define PNG_WRITE_zTXt_SUPPORTED -# ifndef PNG_zTXt_SUPPORTED -# define PNG_zTXt_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_UNKNOWN_CHUNKS -# define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED -# ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED -# define PNG_UNKNOWN_CHUNKS_SUPPORTED -# endif -# ifndef PNG_NO_HANDLE_AS_UNKNOWN -# ifndef PNG_HANDLE_AS_UNKNOWN_SUPPORTED -# define PNG_HANDLE_AS_UNKNOWN_SUPPORTED -# endif -# endif -#endif -#if defined(PNG_WRITE_iTXt_SUPPORTED) || defined(PNG_WRITE_tEXt_SUPPORTED) || \ - defined(PNG_WRITE_zTXt_SUPPORTED) -# define PNG_WRITE_TEXT_SUPPORTED -# ifndef PNG_TEXT_SUPPORTED -# define PNG_TEXT_SUPPORTED -# endif -#endif - -#endif /* PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED */ - -/* Turn this off to disable png_read_png() and - * png_write_png() and leave the row_pointers member - * out of the info structure. - */ -#ifndef PNG_NO_INFO_IMAGE -# define PNG_INFO_IMAGE_SUPPORTED -#endif - -/* need the time information for reading tIME chunks */ -#if defined(PNG_tIME_SUPPORTED) -# if !defined(_WIN32_WCE) - /* "time.h" functions are not supported on WindowsCE */ -# include -# endif -#endif - -/* Some typedefs to get us started. These should be safe on most of the - * common platforms. The typedefs should be at least as large as the - * numbers suggest (a png_uint_32 must be at least 32 bits long), but they - * don't have to be exactly that size. Some compilers dislike passing - * unsigned shorts as function parameters, so you may be better off using - * unsigned int for png_uint_16. Likewise, for 64-bit systems, you may - * want to have unsigned int for png_uint_32 instead of unsigned long. - */ - -typedef unsigned long png_uint_32; -typedef long png_int_32; -typedef unsigned short png_uint_16; -typedef short png_int_16; -typedef unsigned char png_byte; - -/* This is usually size_t. It is typedef'ed just in case you need it to - change (I'm not sure if you will or not, so I thought I'd be safe) */ -#ifdef PNG_SIZE_T - typedef PNG_SIZE_T png_size_t; -# define png_sizeof(x) png_convert_size(sizeof (x)) -#else - typedef size_t png_size_t; -# define png_sizeof(x) sizeof (x) -#endif - -/* The following is needed for medium model support. It cannot be in the - * PNG_INTERNAL section. Needs modification for other compilers besides - * MSC. Model independent support declares all arrays and pointers to be - * large using the far keyword. The zlib version used must also support - * model independent data. As of version zlib 1.0.4, the necessary changes - * have been made in zlib. The USE_FAR_KEYWORD define triggers other - * changes that are needed. (Tim Wegner) - */ - -/* Separate compiler dependencies (problem here is that zlib.h always - defines FAR. (SJT) */ -#ifdef __BORLANDC__ -# if defined(__LARGE__) || defined(__HUGE__) || defined(__COMPACT__) -# define LDATA 1 -# else -# define LDATA 0 -# endif - /* GRR: why is Cygwin in here? Cygwin is not Borland C... */ -# if !defined(__WIN32__) && !defined(__FLAT__) && !defined(__CYGWIN__) -# define PNG_MAX_MALLOC_64K -# if (LDATA != 1) -# ifndef FAR -# define FAR __far -# endif -# define USE_FAR_KEYWORD -# endif /* LDATA != 1 */ - /* Possibly useful for moving data out of default segment. - * Uncomment it if you want. Could also define FARDATA as - * const if your compiler supports it. (SJT) -# define FARDATA FAR - */ -# endif /* __WIN32__, __FLAT__, __CYGWIN__ */ -#endif /* __BORLANDC__ */ - - -/* Suggest testing for specific compiler first before testing for - * FAR. The Watcom compiler defines both __MEDIUM__ and M_I86MM, - * making reliance oncertain keywords suspect. (SJT) - */ - -/* MSC Medium model */ -#if defined(FAR) -# if defined(M_I86MM) -# define USE_FAR_KEYWORD -# define FARDATA FAR -# include -# endif -#endif - -/* SJT: default case */ -#ifndef FAR -# define FAR -#endif - -/* At this point FAR is always defined */ -#ifndef FARDATA -# define FARDATA -#endif - -/* Typedef for floating-point numbers that are converted - to fixed-point with a multiple of 100,000, e.g., int_gamma */ -typedef png_int_32 png_fixed_point; - -/* Add typedefs for pointers */ -typedef void FAR * png_voidp; -typedef png_byte FAR * png_bytep; -typedef png_uint_32 FAR * png_uint_32p; -typedef png_int_32 FAR * png_int_32p; -typedef png_uint_16 FAR * png_uint_16p; -typedef png_int_16 FAR * png_int_16p; -typedef PNG_CONST char FAR * png_const_charp; -typedef char FAR * png_charp; -typedef png_fixed_point FAR * png_fixed_point_p; - -#ifndef PNG_NO_STDIO -#if defined(_WIN32_WCE) -typedef HANDLE png_FILE_p; -#else -typedef FILE * png_FILE_p; -#endif -#endif - -#ifdef PNG_FLOATING_POINT_SUPPORTED -typedef double FAR * png_doublep; -#endif - -/* Pointers to pointers; i.e. arrays */ -typedef png_byte FAR * FAR * png_bytepp; -typedef png_uint_32 FAR * FAR * png_uint_32pp; -typedef png_int_32 FAR * FAR * png_int_32pp; -typedef png_uint_16 FAR * FAR * png_uint_16pp; -typedef png_int_16 FAR * FAR * png_int_16pp; -typedef PNG_CONST char FAR * FAR * png_const_charpp; -typedef char FAR * FAR * png_charpp; -typedef png_fixed_point FAR * FAR * png_fixed_point_pp; -#ifdef PNG_FLOATING_POINT_SUPPORTED -typedef double FAR * FAR * png_doublepp; -#endif - -/* Pointers to pointers to pointers; i.e., pointer to array */ -typedef char FAR * FAR * FAR * png_charppp; - -#if defined(PNG_1_0_X) || defined(PNG_1_2_X) -/* SPC - Is this stuff deprecated? */ -/* It'll be removed as of libpng-1.3.0 - GR-P */ -/* libpng typedefs for types in zlib. If zlib changes - * or another compression library is used, then change these. - * Eliminates need to change all the source files. - */ -typedef charf * png_zcharp; -typedef charf * FAR * png_zcharpp; -typedef z_stream FAR * png_zstreamp; -#endif /* (PNG_1_0_X) || defined(PNG_1_2_X) */ - -/* - * Define PNG_BUILD_DLL if the module being built is a Windows - * LIBPNG DLL. - * - * Define PNG_USE_DLL if you want to *link* to the Windows LIBPNG DLL. - * It is equivalent to Microsoft predefined macro _DLL that is - * automatically defined when you compile using the share - * version of the CRT (C Run-Time library) - * - * The cygwin mods make this behavior a little different: - * Define PNG_BUILD_DLL if you are building a dll for use with cygwin - * Define PNG_STATIC if you are building a static library for use with cygwin, - * -or- if you are building an application that you want to link to the - * static library. - * PNG_USE_DLL is defined by default (no user action needed) unless one of - * the other flags is defined. - */ - -#if !defined(PNG_DLL) && (defined(PNG_BUILD_DLL) || defined(PNG_USE_DLL)) -# define PNG_DLL -#endif -/* If CYGWIN, then disallow GLOBAL ARRAYS unless building a static lib. - * When building a static lib, default to no GLOBAL ARRAYS, but allow - * command-line override - */ -#if defined(__CYGWIN__) -# if !defined(PNG_STATIC) -# if defined(PNG_USE_GLOBAL_ARRAYS) -# undef PNG_USE_GLOBAL_ARRAYS -# endif -# if !defined(PNG_USE_LOCAL_ARRAYS) -# define PNG_USE_LOCAL_ARRAYS -# endif -# else -# if defined(PNG_USE_LOCAL_ARRAYS) || defined(PNG_NO_GLOBAL_ARRAYS) -# if defined(PNG_USE_GLOBAL_ARRAYS) -# undef PNG_USE_GLOBAL_ARRAYS -# endif -# endif -# endif -# if !defined(PNG_USE_LOCAL_ARRAYS) && !defined(PNG_USE_GLOBAL_ARRAYS) -# define PNG_USE_LOCAL_ARRAYS -# endif -#endif - -/* Do not use global arrays (helps with building DLL's) - * They are no longer used in libpng itself, since version 1.0.5c, - * but might be required for some pre-1.0.5c applications. - */ -#if !defined(PNG_USE_LOCAL_ARRAYS) && !defined(PNG_USE_GLOBAL_ARRAYS) -# if defined(PNG_NO_GLOBAL_ARRAYS) || \ - (defined(__GNUC__) && defined(PNG_DLL)) || defined(_MSC_VER) -# define PNG_USE_LOCAL_ARRAYS -# else -# define PNG_USE_GLOBAL_ARRAYS -# endif -#endif - -#if defined(__CYGWIN__) -# undef PNGAPI -# define PNGAPI __cdecl -# undef PNG_IMPEXP -# define PNG_IMPEXP -#endif - -/* If you define PNGAPI, e.g., with compiler option "-DPNGAPI=__stdcall", - * you may get warnings regarding the linkage of png_zalloc and png_zfree. - * Don't ignore those warnings; you must also reset the default calling - * convention in your compiler to match your PNGAPI, and you must build - * zlib and your applications the same way you build libpng. - */ - -#if defined(__MINGW32__) && !defined(PNG_MODULEDEF) -# ifndef PNG_NO_MODULEDEF -# define PNG_NO_MODULEDEF -# endif -#endif - -#if !defined(PNG_IMPEXP) && defined(PNG_BUILD_DLL) && !defined(PNG_NO_MODULEDEF) -# define PNG_IMPEXP -#endif - -#if defined(PNG_DLL) || defined(_DLL) || defined(__DLL__ ) || \ - (( defined(_Windows) || defined(_WINDOWS) || \ - defined(WIN32) || defined(_WIN32) || defined(__WIN32__) )) - -# ifndef PNGAPI -# if defined(__GNUC__) || (defined (_MSC_VER) && (_MSC_VER >= 800)) -# define PNGAPI __cdecl -# else -# define PNGAPI _cdecl -# endif -# endif - -# if !defined(PNG_IMPEXP) && (!defined(PNG_DLL) || \ - 0 /* WINCOMPILER_WITH_NO_SUPPORT_FOR_DECLIMPEXP */) -# define PNG_IMPEXP -# endif - -# if !defined(PNG_IMPEXP) - -# define PNG_EXPORT_TYPE1(type,symbol) PNG_IMPEXP type PNGAPI symbol -# define PNG_EXPORT_TYPE2(type,symbol) type PNG_IMPEXP PNGAPI symbol - - /* Borland/Microsoft */ -# if defined(_MSC_VER) || defined(__BORLANDC__) -# if (_MSC_VER >= 800) || (__BORLANDC__ >= 0x500) -# define PNG_EXPORT PNG_EXPORT_TYPE1 -# else -# define PNG_EXPORT PNG_EXPORT_TYPE2 -# if defined(PNG_BUILD_DLL) -# define PNG_IMPEXP __export -# else -# define PNG_IMPEXP /*__import */ /* doesn't exist AFAIK in - VC++ */ -# endif /* Exists in Borland C++ for - C++ classes (== huge) */ -# endif -# endif - -# if !defined(PNG_IMPEXP) -# if defined(PNG_BUILD_DLL) -# define PNG_IMPEXP __declspec(dllexport) -# else -# define PNG_IMPEXP __declspec(dllimport) -# endif -# endif -# endif /* PNG_IMPEXP */ -#else /* !(DLL || non-cygwin WINDOWS) */ -# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__) -# ifndef PNGAPI -# define PNGAPI _System -# endif -# else -# if 0 /* ... other platforms, with other meanings */ -# endif -# endif -#endif - -#ifndef PNGAPI -# define PNGAPI -#endif -#ifndef PNG_IMPEXP -# define PNG_IMPEXP -#endif - -#ifdef PNG_BUILDSYMS -# ifndef PNG_EXPORT -# define PNG_EXPORT(type,symbol) PNG_FUNCTION_EXPORT symbol END -# endif -# ifdef PNG_USE_GLOBAL_ARRAYS -# ifndef PNG_EXPORT_VAR -# define PNG_EXPORT_VAR(type) PNG_DATA_EXPORT -# endif -# endif -#endif - -#ifndef PNG_EXPORT -# define PNG_EXPORT(type,symbol) PNG_IMPEXP type PNGAPI symbol -#endif - -#ifdef PNG_USE_GLOBAL_ARRAYS -# ifndef PNG_EXPORT_VAR -# define PNG_EXPORT_VAR(type) extern PNG_IMPEXP type -# endif -#endif - -/* User may want to use these so they are not in PNG_INTERNAL. Any library - * functions that are passed far data must be model independent. - */ - -#ifndef PNG_ABORT -# define PNG_ABORT() abort() -#endif - -#ifdef PNG_SETJMP_SUPPORTED -# define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) -#else -# define png_jmpbuf(png_ptr) \ - (LIBPNG_WAS_COMPILED_WITH__PNG_SETJMP_NOT_SUPPORTED) -#endif - -#if defined(USE_FAR_KEYWORD) /* memory model independent fns */ -/* use this to make far-to-near assignments */ -# define CHECK 1 -# define NOCHECK 0 -# define CVT_PTR(ptr) (png_far_to_near(png_ptr,ptr,CHECK)) -# define CVT_PTR_NOCHECK(ptr) (png_far_to_near(png_ptr,ptr,NOCHECK)) -# define png_snprintf _fsnprintf /* Added to v 1.2.19 */ -# define png_strlen _fstrlen -# define png_memcmp _fmemcmp /* SJT: added */ -# define png_memcpy _fmemcpy -# define png_memset _fmemset -#else /* use the usual functions */ -# define CVT_PTR(ptr) (ptr) -# define CVT_PTR_NOCHECK(ptr) (ptr) -# ifndef PNG_NO_SNPRINTF -# ifdef _MSC_VER -# define png_snprintf _snprintf /* Added to v 1.2.19 */ -# define png_snprintf2 _snprintf -# define png_snprintf6 _snprintf -# else -# define png_snprintf snprintf /* Added to v 1.2.19 */ -# define png_snprintf2 snprintf -# define png_snprintf6 snprintf -# endif -# else - /* You don't have or don't want to use snprintf(). Caution: Using - * sprintf instead of snprintf exposes your application to accidental - * or malevolent buffer overflows. If you don't have snprintf() - * as a general rule you should provide one (you can get one from - * Portable OpenSSH). */ -# define png_snprintf(s1,n,fmt,x1) sprintf(s1,fmt,x1) -# define png_snprintf2(s1,n,fmt,x1,x2) sprintf(s1,fmt,x1,x2) -# define png_snprintf6(s1,n,fmt,x1,x2,x3,x4,x5,x6) \ - sprintf(s1,fmt,x1,x2,x3,x4,x5,x6) -# endif -# define png_strlen strlen -# define png_memcmp memcmp /* SJT: added */ -# define png_memcpy memcpy -# define png_memset memset -#endif -/* End of memory model independent support */ - -/* Just a little check that someone hasn't tried to define something - * contradictory. - */ -#if (PNG_ZBUF_SIZE > 65536L) && defined(PNG_MAX_MALLOC_64K) -# undef PNG_ZBUF_SIZE -# define PNG_ZBUF_SIZE 65536L -#endif - -/* Added at libpng-1.2.8 */ -#endif /* PNG_VERSION_INFO_ONLY */ - -#endif /* PNGCONF_H */ diff --git a/rosapps/lib/libpng/pngerror.c b/rosapps/lib/libpng/pngerror.c deleted file mode 100644 index b364fc00af4..00000000000 --- a/rosapps/lib/libpng/pngerror.c +++ /dev/null @@ -1,343 +0,0 @@ - -/* pngerror.c - stub functions for i/o and memory allocation - * - * Last changed in libpng 1.2.22 [October 13, 2007] - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2007 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This file provides a location for all error handling. Users who - * need special error handling are expected to write replacement functions - * and use png_set_error_fn() to use those functions. See the instructions - * at each function. - */ - -#define PNG_INTERNAL -#include "png.h" - -#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) -static void /* PRIVATE */ -png_default_error PNGARG((png_structp png_ptr, - png_const_charp error_message)); -#ifndef PNG_NO_WARNINGS -static void /* PRIVATE */ -png_default_warning PNGARG((png_structp png_ptr, - png_const_charp warning_message)); -#endif /* PNG_NO_WARNINGS */ - -/* This function is called whenever there is a fatal error. This function - * should not be changed. If there is a need to handle errors differently, - * you should supply a replacement error function and use png_set_error_fn() - * to replace the error function at run-time. - */ -#ifndef PNG_NO_ERROR_TEXT -void PNGAPI -png_error(png_structp png_ptr, png_const_charp error_message) -{ -#ifdef PNG_ERROR_NUMBERS_SUPPORTED - char msg[16]; - if (png_ptr != NULL) - { - if (png_ptr->flags& - (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) - { - if (*error_message == '#') - { - int offset; - for (offset=1; offset<15; offset++) - if (*(error_message+offset) == ' ') - break; - if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT) - { - int i; - for (i=0; iflags&PNG_FLAG_STRIP_ERROR_TEXT) - { - msg[0]='0'; - msg[1]='\0'; - error_message=msg; - } - } - } - } -#endif - if (png_ptr != NULL && png_ptr->error_fn != NULL) - (*(png_ptr->error_fn))(png_ptr, error_message); - - /* If the custom handler doesn't exist, or if it returns, - use the default handler, which will not return. */ - png_default_error(png_ptr, error_message); -} -#else -void PNGAPI -png_err(png_structp png_ptr) -{ - if (png_ptr != NULL && png_ptr->error_fn != NULL) - (*(png_ptr->error_fn))(png_ptr, '\0'); - - /* If the custom handler doesn't exist, or if it returns, - use the default handler, which will not return. */ - png_default_error(png_ptr, '\0'); -} -#endif /* PNG_NO_ERROR_TEXT */ - -#ifndef PNG_NO_WARNINGS -/* This function is called whenever there is a non-fatal error. This function - * should not be changed. If there is a need to handle warnings differently, - * you should supply a replacement warning function and use - * png_set_error_fn() to replace the warning function at run-time. - */ -void PNGAPI -png_warning(png_structp png_ptr, png_const_charp warning_message) -{ - int offset = 0; - if (png_ptr != NULL) - { -#ifdef PNG_ERROR_NUMBERS_SUPPORTED - if (png_ptr->flags& - (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) -#endif - { - if (*warning_message == '#') - { - for (offset=1; offset<15; offset++) - if (*(warning_message+offset) == ' ') - break; - } - } - if (png_ptr != NULL && png_ptr->warning_fn != NULL) - (*(png_ptr->warning_fn))(png_ptr, warning_message+offset); - } - else - png_default_warning(png_ptr, warning_message+offset); -} -#endif /* PNG_NO_WARNINGS */ - - -/* These utilities are used internally to build an error message that relates - * to the current chunk. The chunk name comes from png_ptr->chunk_name, - * this is used to prefix the message. The message is limited in length - * to 63 bytes, the name characters are output as hex digits wrapped in [] - * if the character is invalid. - */ -#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) -static PNG_CONST char png_digit[16] = { - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - 'A', 'B', 'C', 'D', 'E', 'F' -}; - -#define PNG_MAX_ERROR_TEXT 64 - -#if !defined(PNG_NO_WARNINGS) || !defined(PNG_NO_ERROR_TEXT) -static void /* PRIVATE */ -png_format_buffer(png_structp png_ptr, png_charp buffer, png_const_charp - error_message) -{ - int iout = 0, iin = 0; - - while (iin < 4) - { - int c = png_ptr->chunk_name[iin++]; - if (isnonalpha(c)) - { - buffer[iout++] = '['; - buffer[iout++] = png_digit[(c & 0xf0) >> 4]; - buffer[iout++] = png_digit[c & 0x0f]; - buffer[iout++] = ']'; - } - else - { - buffer[iout++] = (png_byte)c; - } - } - - if (error_message == NULL) - buffer[iout] = '\0'; - else - { - buffer[iout++] = ':'; - buffer[iout++] = ' '; - png_memcpy(buffer+iout, error_message, PNG_MAX_ERROR_TEXT); - buffer[iout+PNG_MAX_ERROR_TEXT-1] = '\0'; - } -} - -#ifdef PNG_READ_SUPPORTED -void PNGAPI -png_chunk_error(png_structp png_ptr, png_const_charp error_message) -{ - char msg[18+PNG_MAX_ERROR_TEXT]; - if (png_ptr == NULL) - png_error(png_ptr, error_message); - else - { - png_format_buffer(png_ptr, msg, error_message); - png_error(png_ptr, msg); - } -} -#endif /* PNG_READ_SUPPORTED */ -#endif /* !defined(PNG_NO_WARNINGS) || !defined(PNG_NO_ERROR_TEXT) */ - -#ifndef PNG_NO_WARNINGS -void PNGAPI -png_chunk_warning(png_structp png_ptr, png_const_charp warning_message) -{ - char msg[18+PNG_MAX_ERROR_TEXT]; - if (png_ptr == NULL) - png_warning(png_ptr, warning_message); - else - { - png_format_buffer(png_ptr, msg, warning_message); - png_warning(png_ptr, msg); - } -} -#endif /* PNG_NO_WARNINGS */ - - -/* This is the default error handling function. Note that replacements for - * this function MUST NOT RETURN, or the program will likely crash. This - * function is used by default, or if the program supplies NULL for the - * error function pointer in png_set_error_fn(). - */ -static void /* PRIVATE */ -png_default_error(png_structp png_ptr, png_const_charp error_message) -{ -#ifndef PNG_NO_CONSOLE_IO -#ifdef PNG_ERROR_NUMBERS_SUPPORTED - if (*error_message == '#') - { - int offset; - char error_number[16]; - for (offset=0; offset<15; offset++) - { - error_number[offset] = *(error_message+offset+1); - if (*(error_message+offset) == ' ') - break; - } - if((offset > 1) && (offset < 15)) - { - error_number[offset-1]='\0'; - fprintf(stderr, "libpng error no. %s: %s\n", error_number, - error_message+offset); - } - else - fprintf(stderr, "libpng error: %s, offset=%d\n", error_message,offset); - } - else -#endif - fprintf(stderr, "libpng error: %s\n", error_message); -#endif - -#ifdef PNG_SETJMP_SUPPORTED - if (png_ptr) - { -# ifdef USE_FAR_KEYWORD - { - jmp_buf jmpbuf; - png_memcpy(jmpbuf, png_ptr->jmpbuf, png_sizeof(jmp_buf)); - longjmp(jmpbuf, 1); - } -# else - longjmp(png_ptr->jmpbuf, 1); -# endif - } -#else - PNG_ABORT(); -#endif -#ifdef PNG_NO_CONSOLE_IO - error_message = error_message; /* make compiler happy */ -#endif -} - -#ifndef PNG_NO_WARNINGS -/* This function is called when there is a warning, but the library thinks - * it can continue anyway. Replacement functions don't have to do anything - * here if you don't want them to. In the default configuration, png_ptr is - * not used, but it is passed in case it may be useful. - */ -static void /* PRIVATE */ -png_default_warning(png_structp png_ptr, png_const_charp warning_message) -{ -#ifndef PNG_NO_CONSOLE_IO -# ifdef PNG_ERROR_NUMBERS_SUPPORTED - if (*warning_message == '#') - { - int offset; - char warning_number[16]; - for (offset=0; offset<15; offset++) - { - warning_number[offset]=*(warning_message+offset+1); - if (*(warning_message+offset) == ' ') - break; - } - if((offset > 1) && (offset < 15)) - { - warning_number[offset-1]='\0'; - fprintf(stderr, "libpng warning no. %s: %s\n", warning_number, - warning_message+offset); - } - else - fprintf(stderr, "libpng warning: %s\n", warning_message); - } - else -# endif - fprintf(stderr, "libpng warning: %s\n", warning_message); -#else - warning_message = warning_message; /* make compiler happy */ -#endif - png_ptr = png_ptr; /* make compiler happy */ -} -#endif /* PNG_NO_WARNINGS */ - -/* This function is called when the application wants to use another method - * of handling errors and warnings. Note that the error function MUST NOT - * return to the calling routine or serious problems will occur. The return - * method used in the default routine calls longjmp(png_ptr->jmpbuf, 1) - */ -void PNGAPI -png_set_error_fn(png_structp png_ptr, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warning_fn) -{ - if (png_ptr == NULL) - return; - png_ptr->error_ptr = error_ptr; - png_ptr->error_fn = error_fn; - png_ptr->warning_fn = warning_fn; -} - - -/* This function returns a pointer to the error_ptr associated with the user - * functions. The application should free any memory associated with this - * pointer before png_write_destroy and png_read_destroy are called. - */ -png_voidp PNGAPI -png_get_error_ptr(png_structp png_ptr) -{ - if (png_ptr == NULL) - return NULL; - return ((png_voidp)png_ptr->error_ptr); -} - - -#ifdef PNG_ERROR_NUMBERS_SUPPORTED -void PNGAPI -png_set_strip_error_numbers(png_structp png_ptr, png_uint_32 strip_mode) -{ - if(png_ptr != NULL) - { - png_ptr->flags &= - ((~(PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT))&strip_mode); - } -} -#endif -#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/rosapps/lib/libpng/pnggccrd.c b/rosapps/lib/libpng/pnggccrd.c deleted file mode 100644 index a7248d6ca64..00000000000 --- a/rosapps/lib/libpng/pnggccrd.c +++ /dev/null @@ -1,101 +0,0 @@ -/* pnggccrd.c was removed from libpng-1.2.20. */ - -/* This code snippet is for use by configure's compilation test. */ - -#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) && \ - defined(PNG_MMX_CODE_SUPPORTED) -int PNGAPI png_dummy_mmx_support(void); - -static int _mmx_supported = 2; // 0: no MMX; 1: MMX supported; 2: not tested - -int PNGAPI -png_dummy_mmx_support(void) __attribute__((noinline)); - -int PNGAPI -png_dummy_mmx_support(void) -{ - int result; -#if defined(PNG_MMX_CODE_SUPPORTED) // superfluous, but what the heck - __asm__ __volatile__ ( -#if defined(__x86_64__) - "pushq %%rbx \n\t" // rbx gets clobbered by CPUID instruction - "pushq %%rcx \n\t" // so does rcx... - "pushq %%rdx \n\t" // ...and rdx (but rcx & rdx safe on Linux) - "pushfq \n\t" // save Eflag to stack - "popq %%rax \n\t" // get Eflag from stack into rax - "movq %%rax, %%rcx \n\t" // make another copy of Eflag in rcx - "xorl $0x200000, %%eax \n\t" // toggle ID bit in Eflag (i.e., bit 21) - "pushq %%rax \n\t" // save modified Eflag back to stack - "popfq \n\t" // restore modified value to Eflag reg - "pushfq \n\t" // save Eflag to stack - "popq %%rax \n\t" // get Eflag from stack - "pushq %%rcx \n\t" // save original Eflag to stack - "popfq \n\t" // restore original Eflag -#else - "pushl %%ebx \n\t" // ebx gets clobbered by CPUID instruction - "pushl %%ecx \n\t" // so does ecx... - "pushl %%edx \n\t" // ...and edx (but ecx & edx safe on Linux) - "pushfl \n\t" // save Eflag to stack - "popl %%eax \n\t" // get Eflag from stack into eax - "movl %%eax, %%ecx \n\t" // make another copy of Eflag in ecx - "xorl $0x200000, %%eax \n\t" // toggle ID bit in Eflag (i.e., bit 21) - "pushl %%eax \n\t" // save modified Eflag back to stack - "popfl \n\t" // restore modified value to Eflag reg - "pushfl \n\t" // save Eflag to stack - "popl %%eax \n\t" // get Eflag from stack - "pushl %%ecx \n\t" // save original Eflag to stack - "popfl \n\t" // restore original Eflag -#endif - "xorl %%ecx, %%eax \n\t" // compare new Eflag with original Eflag - "jz 0f \n\t" // if same, CPUID instr. is not supported - - "xorl %%eax, %%eax \n\t" // set eax to zero -// ".byte 0x0f, 0xa2 \n\t" // CPUID instruction (two-byte opcode) - "cpuid \n\t" // get the CPU identification info - "cmpl $1, %%eax \n\t" // make sure eax return non-zero value - "jl 0f \n\t" // if eax is zero, MMX is not supported - - "xorl %%eax, %%eax \n\t" // set eax to zero and... - "incl %%eax \n\t" // ...increment eax to 1. This pair is - // faster than the instruction "mov eax, 1" - "cpuid \n\t" // get the CPU identification info again - "andl $0x800000, %%edx \n\t" // mask out all bits but MMX bit (23) - "cmpl $0, %%edx \n\t" // 0 = MMX not supported - "jz 0f \n\t" // non-zero = yes, MMX IS supported - - "movl $1, %%eax \n\t" // set return value to 1 - "jmp 1f \n\t" // DONE: have MMX support - - "0: \n\t" // .NOT_SUPPORTED: target label for jump instructions - "movl $0, %%eax \n\t" // set return value to 0 - "1: \n\t" // .RETURN: target label for jump instructions -#if defined(__x86_64__) - "popq %%rdx \n\t" // restore rdx - "popq %%rcx \n\t" // restore rcx - "popq %%rbx \n\t" // restore rbx -#else - "popl %%edx \n\t" // restore edx - "popl %%ecx \n\t" // restore ecx - "popl %%ebx \n\t" // restore ebx -#endif - -// "ret \n\t" // DONE: no MMX support - // (fall through to standard C "ret") - - : "=a" (result) // output list - - : // any variables used on input (none) - - // no clobber list -// , "%ebx", "%ecx", "%edx" // GRR: we handle these manually -// , "memory" // if write to a variable gcc thought was in a reg -// , "cc" // "condition codes" (flag bits) - ); - _mmx_supported = result; -#else - _mmx_supported = 0; -#endif /* PNG_MMX_CODE_SUPPORTED */ - - return _mmx_supported; -} -#endif diff --git a/rosapps/lib/libpng/pngget.c b/rosapps/lib/libpng/pngget.c deleted file mode 100644 index a0e90bb6a4f..00000000000 --- a/rosapps/lib/libpng/pngget.c +++ /dev/null @@ -1,901 +0,0 @@ - -/* pngget.c - retrieval of values from info struct - * - * Last changed in libpng 1.2.15 January 5, 2007 - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2007 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - */ - -#define PNG_INTERNAL -#include "png.h" - -#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) - -png_uint_32 PNGAPI -png_get_valid(png_structp png_ptr, png_infop info_ptr, png_uint_32 flag) -{ - if (png_ptr != NULL && info_ptr != NULL) - return(info_ptr->valid & flag); - else - return(0); -} - -png_uint_32 PNGAPI -png_get_rowbytes(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) - return(info_ptr->rowbytes); - else - return(0); -} - -#if defined(PNG_INFO_IMAGE_SUPPORTED) -png_bytepp PNGAPI -png_get_rows(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) - return(info_ptr->row_pointers); - else - return(0); -} -#endif - -#ifdef PNG_EASY_ACCESS_SUPPORTED -/* easy access to info, added in libpng-0.99 */ -png_uint_32 PNGAPI -png_get_image_width(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) - { - return info_ptr->width; - } - return (0); -} - -png_uint_32 PNGAPI -png_get_image_height(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) - { - return info_ptr->height; - } - return (0); -} - -png_byte PNGAPI -png_get_bit_depth(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) - { - return info_ptr->bit_depth; - } - return (0); -} - -png_byte PNGAPI -png_get_color_type(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) - { - return info_ptr->color_type; - } - return (0); -} - -png_byte PNGAPI -png_get_filter_type(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) - { - return info_ptr->filter_type; - } - return (0); -} - -png_byte PNGAPI -png_get_interlace_type(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) - { - return info_ptr->interlace_type; - } - return (0); -} - -png_byte PNGAPI -png_get_compression_type(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) - { - return info_ptr->compression_type; - } - return (0); -} - -png_uint_32 PNGAPI -png_get_x_pixels_per_meter(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) -#if defined(PNG_pHYs_SUPPORTED) - if (info_ptr->valid & PNG_INFO_pHYs) - { - png_debug1(1, "in %s retrieval function\n", "png_get_x_pixels_per_meter"); - if(info_ptr->phys_unit_type != PNG_RESOLUTION_METER) - return (0); - else return (info_ptr->x_pixels_per_unit); - } -#else - return (0); -#endif - return (0); -} - -png_uint_32 PNGAPI -png_get_y_pixels_per_meter(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) -#if defined(PNG_pHYs_SUPPORTED) - if (info_ptr->valid & PNG_INFO_pHYs) - { - png_debug1(1, "in %s retrieval function\n", "png_get_y_pixels_per_meter"); - if(info_ptr->phys_unit_type != PNG_RESOLUTION_METER) - return (0); - else return (info_ptr->y_pixels_per_unit); - } -#else - return (0); -#endif - return (0); -} - -png_uint_32 PNGAPI -png_get_pixels_per_meter(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) -#if defined(PNG_pHYs_SUPPORTED) - if (info_ptr->valid & PNG_INFO_pHYs) - { - png_debug1(1, "in %s retrieval function\n", "png_get_pixels_per_meter"); - if(info_ptr->phys_unit_type != PNG_RESOLUTION_METER || - info_ptr->x_pixels_per_unit != info_ptr->y_pixels_per_unit) - return (0); - else return (info_ptr->x_pixels_per_unit); - } -#else - return (0); -#endif - return (0); -} - -#ifdef PNG_FLOATING_POINT_SUPPORTED -float PNGAPI -png_get_pixel_aspect_ratio(png_structp png_ptr, png_infop info_ptr) - { - if (png_ptr != NULL && info_ptr != NULL) -#if defined(PNG_pHYs_SUPPORTED) - if (info_ptr->valid & PNG_INFO_pHYs) - { - png_debug1(1, "in %s retrieval function\n", "png_get_aspect_ratio"); - if (info_ptr->x_pixels_per_unit == 0) - return ((float)0.0); - else - return ((float)((float)info_ptr->y_pixels_per_unit - /(float)info_ptr->x_pixels_per_unit)); - } -#else - return (0.0); -#endif - return ((float)0.0); -} -#endif - -png_int_32 PNGAPI -png_get_x_offset_microns(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) -#if defined(PNG_oFFs_SUPPORTED) - if (info_ptr->valid & PNG_INFO_oFFs) - { - png_debug1(1, "in %s retrieval function\n", "png_get_x_offset_microns"); - if(info_ptr->offset_unit_type != PNG_OFFSET_MICROMETER) - return (0); - else return (info_ptr->x_offset); - } -#else - return (0); -#endif - return (0); -} - -png_int_32 PNGAPI -png_get_y_offset_microns(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) -#if defined(PNG_oFFs_SUPPORTED) - if (info_ptr->valid & PNG_INFO_oFFs) - { - png_debug1(1, "in %s retrieval function\n", "png_get_y_offset_microns"); - if(info_ptr->offset_unit_type != PNG_OFFSET_MICROMETER) - return (0); - else return (info_ptr->y_offset); - } -#else - return (0); -#endif - return (0); -} - -png_int_32 PNGAPI -png_get_x_offset_pixels(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) -#if defined(PNG_oFFs_SUPPORTED) - if (info_ptr->valid & PNG_INFO_oFFs) - { - png_debug1(1, "in %s retrieval function\n", "png_get_x_offset_microns"); - if(info_ptr->offset_unit_type != PNG_OFFSET_PIXEL) - return (0); - else return (info_ptr->x_offset); - } -#else - return (0); -#endif - return (0); -} - -png_int_32 PNGAPI -png_get_y_offset_pixels(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) -#if defined(PNG_oFFs_SUPPORTED) - if (info_ptr->valid & PNG_INFO_oFFs) - { - png_debug1(1, "in %s retrieval function\n", "png_get_y_offset_microns"); - if(info_ptr->offset_unit_type != PNG_OFFSET_PIXEL) - return (0); - else return (info_ptr->y_offset); - } -#else - return (0); -#endif - return (0); -} - -#if defined(PNG_INCH_CONVERSIONS) && defined(PNG_FLOATING_POINT_SUPPORTED) -png_uint_32 PNGAPI -png_get_pixels_per_inch(png_structp png_ptr, png_infop info_ptr) -{ - return ((png_uint_32)((float)png_get_pixels_per_meter(png_ptr, info_ptr) - *.0254 +.5)); -} - -png_uint_32 PNGAPI -png_get_x_pixels_per_inch(png_structp png_ptr, png_infop info_ptr) -{ - return ((png_uint_32)((float)png_get_x_pixels_per_meter(png_ptr, info_ptr) - *.0254 +.5)); -} - -png_uint_32 PNGAPI -png_get_y_pixels_per_inch(png_structp png_ptr, png_infop info_ptr) -{ - return ((png_uint_32)((float)png_get_y_pixels_per_meter(png_ptr, info_ptr) - *.0254 +.5)); -} - -float PNGAPI -png_get_x_offset_inches(png_structp png_ptr, png_infop info_ptr) -{ - return ((float)png_get_x_offset_microns(png_ptr, info_ptr) - *.00003937); -} - -float PNGAPI -png_get_y_offset_inches(png_structp png_ptr, png_infop info_ptr) -{ - return ((float)png_get_y_offset_microns(png_ptr, info_ptr) - *.00003937); -} - -#if defined(PNG_pHYs_SUPPORTED) -png_uint_32 PNGAPI -png_get_pHYs_dpi(png_structp png_ptr, png_infop info_ptr, - png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type) -{ - png_uint_32 retval = 0; - - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) - { - png_debug1(1, "in %s retrieval function\n", "pHYs"); - if (res_x != NULL) - { - *res_x = info_ptr->x_pixels_per_unit; - retval |= PNG_INFO_pHYs; - } - if (res_y != NULL) - { - *res_y = info_ptr->y_pixels_per_unit; - retval |= PNG_INFO_pHYs; - } - if (unit_type != NULL) - { - *unit_type = (int)info_ptr->phys_unit_type; - retval |= PNG_INFO_pHYs; - if(*unit_type == 1) - { - if (res_x != NULL) *res_x = (png_uint_32)(*res_x * .0254 + .50); - if (res_y != NULL) *res_y = (png_uint_32)(*res_y * .0254 + .50); - } - } - } - return (retval); -} -#endif /* PNG_pHYs_SUPPORTED */ -#endif /* PNG_INCH_CONVERSIONS && PNG_FLOATING_POINT_SUPPORTED */ - -/* png_get_channels really belongs in here, too, but it's been around longer */ - -#endif /* PNG_EASY_ACCESS_SUPPORTED */ - -png_byte PNGAPI -png_get_channels(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) - return(info_ptr->channels); - else - return (0); -} - -png_bytep PNGAPI -png_get_signature(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) - return(info_ptr->signature); - else - return (NULL); -} - -#if defined(PNG_bKGD_SUPPORTED) -png_uint_32 PNGAPI -png_get_bKGD(png_structp png_ptr, png_infop info_ptr, - png_color_16p *background) -{ - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD) - && background != NULL) - { - png_debug1(1, "in %s retrieval function\n", "bKGD"); - *background = &(info_ptr->background); - return (PNG_INFO_bKGD); - } - return (0); -} -#endif - -#if defined(PNG_cHRM_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED -png_uint_32 PNGAPI -png_get_cHRM(png_structp png_ptr, png_infop info_ptr, - double *white_x, double *white_y, double *red_x, double *red_y, - double *green_x, double *green_y, double *blue_x, double *blue_y) -{ - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)) - { - png_debug1(1, "in %s retrieval function\n", "cHRM"); - if (white_x != NULL) - *white_x = (double)info_ptr->x_white; - if (white_y != NULL) - *white_y = (double)info_ptr->y_white; - if (red_x != NULL) - *red_x = (double)info_ptr->x_red; - if (red_y != NULL) - *red_y = (double)info_ptr->y_red; - if (green_x != NULL) - *green_x = (double)info_ptr->x_green; - if (green_y != NULL) - *green_y = (double)info_ptr->y_green; - if (blue_x != NULL) - *blue_x = (double)info_ptr->x_blue; - if (blue_y != NULL) - *blue_y = (double)info_ptr->y_blue; - return (PNG_INFO_cHRM); - } - return (0); -} -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED -png_uint_32 PNGAPI -png_get_cHRM_fixed(png_structp png_ptr, png_infop info_ptr, - png_fixed_point *white_x, png_fixed_point *white_y, png_fixed_point *red_x, - png_fixed_point *red_y, png_fixed_point *green_x, png_fixed_point *green_y, - png_fixed_point *blue_x, png_fixed_point *blue_y) -{ - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)) - { - png_debug1(1, "in %s retrieval function\n", "cHRM"); - if (white_x != NULL) - *white_x = info_ptr->int_x_white; - if (white_y != NULL) - *white_y = info_ptr->int_y_white; - if (red_x != NULL) - *red_x = info_ptr->int_x_red; - if (red_y != NULL) - *red_y = info_ptr->int_y_red; - if (green_x != NULL) - *green_x = info_ptr->int_x_green; - if (green_y != NULL) - *green_y = info_ptr->int_y_green; - if (blue_x != NULL) - *blue_x = info_ptr->int_x_blue; - if (blue_y != NULL) - *blue_y = info_ptr->int_y_blue; - return (PNG_INFO_cHRM); - } - return (0); -} -#endif -#endif - -#if defined(PNG_gAMA_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED -png_uint_32 PNGAPI -png_get_gAMA(png_structp png_ptr, png_infop info_ptr, double *file_gamma) -{ - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA) - && file_gamma != NULL) - { - png_debug1(1, "in %s retrieval function\n", "gAMA"); - *file_gamma = (double)info_ptr->gamma; - return (PNG_INFO_gAMA); - } - return (0); -} -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED -png_uint_32 PNGAPI -png_get_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, - png_fixed_point *int_file_gamma) -{ - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA) - && int_file_gamma != NULL) - { - png_debug1(1, "in %s retrieval function\n", "gAMA"); - *int_file_gamma = info_ptr->int_gamma; - return (PNG_INFO_gAMA); - } - return (0); -} -#endif -#endif - -#if defined(PNG_sRGB_SUPPORTED) -png_uint_32 PNGAPI -png_get_sRGB(png_structp png_ptr, png_infop info_ptr, int *file_srgb_intent) -{ - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB) - && file_srgb_intent != NULL) - { - png_debug1(1, "in %s retrieval function\n", "sRGB"); - *file_srgb_intent = (int)info_ptr->srgb_intent; - return (PNG_INFO_sRGB); - } - return (0); -} -#endif - -#if defined(PNG_iCCP_SUPPORTED) -png_uint_32 PNGAPI -png_get_iCCP(png_structp png_ptr, png_infop info_ptr, - png_charpp name, int *compression_type, - png_charpp profile, png_uint_32 *proflen) -{ - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP) - && name != NULL && profile != NULL && proflen != NULL) - { - png_debug1(1, "in %s retrieval function\n", "iCCP"); - *name = info_ptr->iccp_name; - *profile = info_ptr->iccp_profile; - /* compression_type is a dummy so the API won't have to change - if we introduce multiple compression types later. */ - *proflen = (int)info_ptr->iccp_proflen; - *compression_type = (int)info_ptr->iccp_compression; - return (PNG_INFO_iCCP); - } - return (0); -} -#endif - -#if defined(PNG_sPLT_SUPPORTED) -png_uint_32 PNGAPI -png_get_sPLT(png_structp png_ptr, png_infop info_ptr, - png_sPLT_tpp spalettes) -{ - if (png_ptr != NULL && info_ptr != NULL && spalettes != NULL) - { - *spalettes = info_ptr->splt_palettes; - return ((png_uint_32)info_ptr->splt_palettes_num); - } - return (0); -} -#endif - -#if defined(PNG_hIST_SUPPORTED) -png_uint_32 PNGAPI -png_get_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_16p *hist) -{ - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST) - && hist != NULL) - { - png_debug1(1, "in %s retrieval function\n", "hIST"); - *hist = info_ptr->hist; - return (PNG_INFO_hIST); - } - return (0); -} -#endif - -png_uint_32 PNGAPI -png_get_IHDR(png_structp png_ptr, png_infop info_ptr, - png_uint_32 *width, png_uint_32 *height, int *bit_depth, - int *color_type, int *interlace_type, int *compression_type, - int *filter_type) - -{ - if (png_ptr != NULL && info_ptr != NULL && width != NULL && height != NULL && - bit_depth != NULL && color_type != NULL) - { - png_debug1(1, "in %s retrieval function\n", "IHDR"); - *width = info_ptr->width; - *height = info_ptr->height; - *bit_depth = info_ptr->bit_depth; - if (info_ptr->bit_depth < 1 || info_ptr->bit_depth > 16) - png_error(png_ptr, "Invalid bit depth"); - *color_type = info_ptr->color_type; - if (info_ptr->color_type > 6) - png_error(png_ptr, "Invalid color type"); - if (compression_type != NULL) - *compression_type = info_ptr->compression_type; - if (filter_type != NULL) - *filter_type = info_ptr->filter_type; - if (interlace_type != NULL) - *interlace_type = info_ptr->interlace_type; - - /* check for potential overflow of rowbytes */ - if (*width == 0 || *width > PNG_UINT_31_MAX) - png_error(png_ptr, "Invalid image width"); - if (*height == 0 || *height > PNG_UINT_31_MAX) - png_error(png_ptr, "Invalid image height"); - if (info_ptr->width > (PNG_UINT_32_MAX - >> 3) /* 8-byte RGBA pixels */ - - 64 /* bigrowbuf hack */ - - 1 /* filter byte */ - - 7*8 /* rounding of width to multiple of 8 pixels */ - - 8) /* extra max_pixel_depth pad */ - { - png_warning(png_ptr, - "Width too large for libpng to process image data."); - } - return (1); - } - return (0); -} - -#if defined(PNG_oFFs_SUPPORTED) -png_uint_32 PNGAPI -png_get_oFFs(png_structp png_ptr, png_infop info_ptr, - png_int_32 *offset_x, png_int_32 *offset_y, int *unit_type) -{ - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs) - && offset_x != NULL && offset_y != NULL && unit_type != NULL) - { - png_debug1(1, "in %s retrieval function\n", "oFFs"); - *offset_x = info_ptr->x_offset; - *offset_y = info_ptr->y_offset; - *unit_type = (int)info_ptr->offset_unit_type; - return (PNG_INFO_oFFs); - } - return (0); -} -#endif - -#if defined(PNG_pCAL_SUPPORTED) -png_uint_32 PNGAPI -png_get_pCAL(png_structp png_ptr, png_infop info_ptr, - png_charp *purpose, png_int_32 *X0, png_int_32 *X1, int *type, int *nparams, - png_charp *units, png_charpp *params) -{ - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL) - && purpose != NULL && X0 != NULL && X1 != NULL && type != NULL && - nparams != NULL && units != NULL && params != NULL) - { - png_debug1(1, "in %s retrieval function\n", "pCAL"); - *purpose = info_ptr->pcal_purpose; - *X0 = info_ptr->pcal_X0; - *X1 = info_ptr->pcal_X1; - *type = (int)info_ptr->pcal_type; - *nparams = (int)info_ptr->pcal_nparams; - *units = info_ptr->pcal_units; - *params = info_ptr->pcal_params; - return (PNG_INFO_pCAL); - } - return (0); -} -#endif - -#if defined(PNG_sCAL_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED -png_uint_32 PNGAPI -png_get_sCAL(png_structp png_ptr, png_infop info_ptr, - int *unit, double *width, double *height) -{ - if (png_ptr != NULL && info_ptr != NULL && - (info_ptr->valid & PNG_INFO_sCAL)) - { - *unit = info_ptr->scal_unit; - *width = info_ptr->scal_pixel_width; - *height = info_ptr->scal_pixel_height; - return (PNG_INFO_sCAL); - } - return(0); -} -#else -#ifdef PNG_FIXED_POINT_SUPPORTED -png_uint_32 PNGAPI -png_get_sCAL_s(png_structp png_ptr, png_infop info_ptr, - int *unit, png_charpp width, png_charpp height) -{ - if (png_ptr != NULL && info_ptr != NULL && - (info_ptr->valid & PNG_INFO_sCAL)) - { - *unit = info_ptr->scal_unit; - *width = info_ptr->scal_s_width; - *height = info_ptr->scal_s_height; - return (PNG_INFO_sCAL); - } - return(0); -} -#endif -#endif -#endif - -#if defined(PNG_pHYs_SUPPORTED) -png_uint_32 PNGAPI -png_get_pHYs(png_structp png_ptr, png_infop info_ptr, - png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type) -{ - png_uint_32 retval = 0; - - if (png_ptr != NULL && info_ptr != NULL && - (info_ptr->valid & PNG_INFO_pHYs)) - { - png_debug1(1, "in %s retrieval function\n", "pHYs"); - if (res_x != NULL) - { - *res_x = info_ptr->x_pixels_per_unit; - retval |= PNG_INFO_pHYs; - } - if (res_y != NULL) - { - *res_y = info_ptr->y_pixels_per_unit; - retval |= PNG_INFO_pHYs; - } - if (unit_type != NULL) - { - *unit_type = (int)info_ptr->phys_unit_type; - retval |= PNG_INFO_pHYs; - } - } - return (retval); -} -#endif - -png_uint_32 PNGAPI -png_get_PLTE(png_structp png_ptr, png_infop info_ptr, png_colorp *palette, - int *num_palette) -{ - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_PLTE) - && palette != NULL) - { - png_debug1(1, "in %s retrieval function\n", "PLTE"); - *palette = info_ptr->palette; - *num_palette = info_ptr->num_palette; - png_debug1(3, "num_palette = %d\n", *num_palette); - return (PNG_INFO_PLTE); - } - return (0); -} - -#if defined(PNG_sBIT_SUPPORTED) -png_uint_32 PNGAPI -png_get_sBIT(png_structp png_ptr, png_infop info_ptr, png_color_8p *sig_bit) -{ - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT) - && sig_bit != NULL) - { - png_debug1(1, "in %s retrieval function\n", "sBIT"); - *sig_bit = &(info_ptr->sig_bit); - return (PNG_INFO_sBIT); - } - return (0); -} -#endif - -#if defined(PNG_TEXT_SUPPORTED) -png_uint_32 PNGAPI -png_get_text(png_structp png_ptr, png_infop info_ptr, png_textp *text_ptr, - int *num_text) -{ - if (png_ptr != NULL && info_ptr != NULL && info_ptr->num_text > 0) - { - png_debug1(1, "in %s retrieval function\n", - (png_ptr->chunk_name[0] == '\0' ? "text" - : (png_const_charp)png_ptr->chunk_name)); - if (text_ptr != NULL) - *text_ptr = info_ptr->text; - if (num_text != NULL) - *num_text = info_ptr->num_text; - return ((png_uint_32)info_ptr->num_text); - } - if (num_text != NULL) - *num_text = 0; - return(0); -} -#endif - -#if defined(PNG_tIME_SUPPORTED) -png_uint_32 PNGAPI -png_get_tIME(png_structp png_ptr, png_infop info_ptr, png_timep *mod_time) -{ - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME) - && mod_time != NULL) - { - png_debug1(1, "in %s retrieval function\n", "tIME"); - *mod_time = &(info_ptr->mod_time); - return (PNG_INFO_tIME); - } - return (0); -} -#endif - -#if defined(PNG_tRNS_SUPPORTED) -png_uint_32 PNGAPI -png_get_tRNS(png_structp png_ptr, png_infop info_ptr, - png_bytep *trans, int *num_trans, png_color_16p *trans_values) -{ - png_uint_32 retval = 0; - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) - { - png_debug1(1, "in %s retrieval function\n", "tRNS"); - if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - { - if (trans != NULL) - { - *trans = info_ptr->trans; - retval |= PNG_INFO_tRNS; - } - if (trans_values != NULL) - *trans_values = &(info_ptr->trans_values); - } - else /* if (info_ptr->color_type != PNG_COLOR_TYPE_PALETTE) */ - { - if (trans_values != NULL) - { - *trans_values = &(info_ptr->trans_values); - retval |= PNG_INFO_tRNS; - } - if(trans != NULL) - *trans = NULL; - } - if(num_trans != NULL) - { - *num_trans = info_ptr->num_trans; - retval |= PNG_INFO_tRNS; - } - } - return (retval); -} -#endif - -#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) -png_uint_32 PNGAPI -png_get_unknown_chunks(png_structp png_ptr, png_infop info_ptr, - png_unknown_chunkpp unknowns) -{ - if (png_ptr != NULL && info_ptr != NULL && unknowns != NULL) - { - *unknowns = info_ptr->unknown_chunks; - return ((png_uint_32)info_ptr->unknown_chunks_num); - } - return (0); -} -#endif - -#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) -png_byte PNGAPI -png_get_rgb_to_gray_status (png_structp png_ptr) -{ - return (png_byte)(png_ptr? png_ptr->rgb_to_gray_status : 0); -} -#endif - -#if defined(PNG_USER_CHUNKS_SUPPORTED) -png_voidp PNGAPI -png_get_user_chunk_ptr(png_structp png_ptr) -{ - return (png_ptr? png_ptr->user_chunk_ptr : NULL); -} -#endif - -#ifdef PNG_WRITE_SUPPORTED -png_uint_32 PNGAPI -png_get_compression_buffer_size(png_structp png_ptr) -{ - return (png_uint_32)(png_ptr? png_ptr->zbuf_size : 0L); -} -#endif - -#ifdef PNG_ASSEMBLER_CODE_SUPPORTED -#ifndef PNG_1_0_X -/* this function was added to libpng 1.2.0 and should exist by default */ -png_uint_32 PNGAPI -png_get_asm_flags (png_structp png_ptr) -{ - /* obsolete, to be removed from libpng-1.4.0 */ - return (png_ptr? 0L: 0L); -} - -/* this function was added to libpng 1.2.0 and should exist by default */ -png_uint_32 PNGAPI -png_get_asm_flagmask (int flag_select) -{ - /* obsolete, to be removed from libpng-1.4.0 */ - flag_select=flag_select; - return 0L; -} - - /* GRR: could add this: && defined(PNG_MMX_CODE_SUPPORTED) */ -/* this function was added to libpng 1.2.0 */ -png_uint_32 PNGAPI -png_get_mmx_flagmask (int flag_select, int *compilerID) -{ - /* obsolete, to be removed from libpng-1.4.0 */ - flag_select=flag_select; - *compilerID = -1; /* unknown (i.e., no asm/MMX code compiled) */ - return 0L; -} - -/* this function was added to libpng 1.2.0 */ -png_byte PNGAPI -png_get_mmx_bitdepth_threshold (png_structp png_ptr) -{ - /* obsolete, to be removed from libpng-1.4.0 */ - return (png_ptr? 0: 0); -} - -/* this function was added to libpng 1.2.0 */ -png_uint_32 PNGAPI -png_get_mmx_rowbytes_threshold (png_structp png_ptr) -{ - /* obsolete, to be removed from libpng-1.4.0 */ - return (png_ptr? 0L: 0L); -} -#endif /* ?PNG_1_0_X */ -#endif /* ?PNG_ASSEMBLER_CODE_SUPPORTED */ - -#ifdef PNG_SET_USER_LIMITS_SUPPORTED -/* these functions were added to libpng 1.2.6 */ -png_uint_32 PNGAPI -png_get_user_width_max (png_structp png_ptr) -{ - return (png_ptr? png_ptr->user_width_max : 0); -} -png_uint_32 PNGAPI -png_get_user_height_max (png_structp png_ptr) -{ - return (png_ptr? png_ptr->user_height_max : 0); -} -#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */ - - -#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/rosapps/lib/libpng/pngmem.c b/rosapps/lib/libpng/pngmem.c deleted file mode 100644 index 248060f3817..00000000000 --- a/rosapps/lib/libpng/pngmem.c +++ /dev/null @@ -1,608 +0,0 @@ - -/* pngmem.c - stub functions for memory allocation - * - * Last changed in libpng 1.2.13 November 13, 2006 - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2006 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This file provides a location for all memory allocation. Users who - * need special memory handling are expected to supply replacement - * functions for png_malloc() and png_free(), and to use - * png_create_read_struct_2() and png_create_write_struct_2() to - * identify the replacement functions. - */ - -#define PNG_INTERNAL -#include "png.h" - -#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) - -/* Borland DOS special memory handler */ -#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__) -/* if you change this, be sure to change the one in png.h also */ - -/* Allocate memory for a png_struct. The malloc and memset can be replaced - by a single call to calloc() if this is thought to improve performance. */ -png_voidp /* PRIVATE */ -png_create_struct(int type) -{ -#ifdef PNG_USER_MEM_SUPPORTED - return (png_create_struct_2(type, png_malloc_ptr_NULL, png_voidp_NULL)); -} - -/* Alternate version of png_create_struct, for use with user-defined malloc. */ -png_voidp /* PRIVATE */ -png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr) -{ -#endif /* PNG_USER_MEM_SUPPORTED */ - png_size_t size; - png_voidp struct_ptr; - - if (type == PNG_STRUCT_INFO) - size = png_sizeof(png_info); - else if (type == PNG_STRUCT_PNG) - size = png_sizeof(png_struct); - else - return (png_get_copyright(NULL)); - -#ifdef PNG_USER_MEM_SUPPORTED - if(malloc_fn != NULL) - { - png_struct dummy_struct; - png_structp png_ptr = &dummy_struct; - png_ptr->mem_ptr=mem_ptr; - struct_ptr = (*(malloc_fn))(png_ptr, (png_uint_32)size); - } - else -#endif /* PNG_USER_MEM_SUPPORTED */ - struct_ptr = (png_voidp)farmalloc(size); - if (struct_ptr != NULL) - png_memset(struct_ptr, 0, size); - return (struct_ptr); -} - -/* Free memory allocated by a png_create_struct() call */ -void /* PRIVATE */ -png_destroy_struct(png_voidp struct_ptr) -{ -#ifdef PNG_USER_MEM_SUPPORTED - png_destroy_struct_2(struct_ptr, png_free_ptr_NULL, png_voidp_NULL); -} - -/* Free memory allocated by a png_create_struct() call */ -void /* PRIVATE */ -png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn, - png_voidp mem_ptr) -{ -#endif - if (struct_ptr != NULL) - { -#ifdef PNG_USER_MEM_SUPPORTED - if(free_fn != NULL) - { - png_struct dummy_struct; - png_structp png_ptr = &dummy_struct; - png_ptr->mem_ptr=mem_ptr; - (*(free_fn))(png_ptr, struct_ptr); - return; - } -#endif /* PNG_USER_MEM_SUPPORTED */ - farfree (struct_ptr); - } -} - -/* Allocate memory. For reasonable files, size should never exceed - * 64K. However, zlib may allocate more then 64K if you don't tell - * it not to. See zconf.h and png.h for more information. zlib does - * need to allocate exactly 64K, so whatever you call here must - * have the ability to do that. - * - * Borland seems to have a problem in DOS mode for exactly 64K. - * It gives you a segment with an offset of 8 (perhaps to store its - * memory stuff). zlib doesn't like this at all, so we have to - * detect and deal with it. This code should not be needed in - * Windows or OS/2 modes, and only in 16 bit mode. This code has - * been updated by Alexander Lehmann for version 0.89 to waste less - * memory. - * - * Note that we can't use png_size_t for the "size" declaration, - * since on some systems a png_size_t is a 16-bit quantity, and as a - * result, we would be truncating potentially larger memory requests - * (which should cause a fatal error) and introducing major problems. - */ - -png_voidp PNGAPI -png_malloc(png_structp png_ptr, png_uint_32 size) -{ - png_voidp ret; - - if (png_ptr == NULL || size == 0) - return (NULL); - -#ifdef PNG_USER_MEM_SUPPORTED - if(png_ptr->malloc_fn != NULL) - ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size)); - else - ret = (png_malloc_default(png_ptr, size)); - if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) - png_error(png_ptr, "Out of memory!"); - return (ret); -} - -png_voidp PNGAPI -png_malloc_default(png_structp png_ptr, png_uint_32 size) -{ - png_voidp ret; -#endif /* PNG_USER_MEM_SUPPORTED */ - - if (png_ptr == NULL || size == 0) - return (NULL); - -#ifdef PNG_MAX_MALLOC_64K - if (size > (png_uint_32)65536L) - { - png_warning(png_ptr, "Cannot Allocate > 64K"); - ret = NULL; - } - else -#endif - - if (size != (size_t)size) - ret = NULL; - else if (size == (png_uint_32)65536L) - { - if (png_ptr->offset_table == NULL) - { - /* try to see if we need to do any of this fancy stuff */ - ret = farmalloc(size); - if (ret == NULL || ((png_size_t)ret & 0xffff)) - { - int num_blocks; - png_uint_32 total_size; - png_bytep table; - int i; - png_byte huge * hptr; - - if (ret != NULL) - { - farfree(ret); - ret = NULL; - } - - if(png_ptr->zlib_window_bits > 14) - num_blocks = (int)(1 << (png_ptr->zlib_window_bits - 14)); - else - num_blocks = 1; - if (png_ptr->zlib_mem_level >= 7) - num_blocks += (int)(1 << (png_ptr->zlib_mem_level - 7)); - else - num_blocks++; - - total_size = ((png_uint_32)65536L) * (png_uint_32)num_blocks+16; - - table = farmalloc(total_size); - - if (table == NULL) - { -#ifndef PNG_USER_MEM_SUPPORTED - if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) - png_error(png_ptr, "Out Of Memory."); /* Note "O" and "M" */ - else - png_warning(png_ptr, "Out Of Memory."); -#endif - return (NULL); - } - - if ((png_size_t)table & 0xfff0) - { -#ifndef PNG_USER_MEM_SUPPORTED - if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) - png_error(png_ptr, - "Farmalloc didn't return normalized pointer"); - else - png_warning(png_ptr, - "Farmalloc didn't return normalized pointer"); -#endif - return (NULL); - } - - png_ptr->offset_table = table; - png_ptr->offset_table_ptr = farmalloc(num_blocks * - png_sizeof (png_bytep)); - - if (png_ptr->offset_table_ptr == NULL) - { -#ifndef PNG_USER_MEM_SUPPORTED - if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) - png_error(png_ptr, "Out Of memory."); /* Note "O" and "M" */ - else - png_warning(png_ptr, "Out Of memory."); -#endif - return (NULL); - } - - hptr = (png_byte huge *)table; - if ((png_size_t)hptr & 0xf) - { - hptr = (png_byte huge *)((long)(hptr) & 0xfffffff0L); - hptr = hptr + 16L; /* "hptr += 16L" fails on Turbo C++ 3.0 */ - } - for (i = 0; i < num_blocks; i++) - { - png_ptr->offset_table_ptr[i] = (png_bytep)hptr; - hptr = hptr + (png_uint_32)65536L; /* "+=" fails on TC++3.0 */ - } - - png_ptr->offset_table_number = num_blocks; - png_ptr->offset_table_count = 0; - png_ptr->offset_table_count_free = 0; - } - } - - if (png_ptr->offset_table_count >= png_ptr->offset_table_number) - { -#ifndef PNG_USER_MEM_SUPPORTED - if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) - png_error(png_ptr, "Out of Memory."); /* Note "o" and "M" */ - else - png_warning(png_ptr, "Out of Memory."); -#endif - return (NULL); - } - - ret = png_ptr->offset_table_ptr[png_ptr->offset_table_count++]; - } - else - ret = farmalloc(size); - -#ifndef PNG_USER_MEM_SUPPORTED - if (ret == NULL) - { - if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) - png_error(png_ptr, "Out of memory."); /* Note "o" and "m" */ - else - png_warning(png_ptr, "Out of memory."); /* Note "o" and "m" */ - } -#endif - - return (ret); -} - -/* free a pointer allocated by png_malloc(). In the default - configuration, png_ptr is not used, but is passed in case it - is needed. If ptr is NULL, return without taking any action. */ -void PNGAPI -png_free(png_structp png_ptr, png_voidp ptr) -{ - if (png_ptr == NULL || ptr == NULL) - return; - -#ifdef PNG_USER_MEM_SUPPORTED - if (png_ptr->free_fn != NULL) - { - (*(png_ptr->free_fn))(png_ptr, ptr); - return; - } - else png_free_default(png_ptr, ptr); -} - -void PNGAPI -png_free_default(png_structp png_ptr, png_voidp ptr) -{ -#endif /* PNG_USER_MEM_SUPPORTED */ - - if(png_ptr == NULL) return; - - if (png_ptr->offset_table != NULL) - { - int i; - - for (i = 0; i < png_ptr->offset_table_count; i++) - { - if (ptr == png_ptr->offset_table_ptr[i]) - { - ptr = NULL; - png_ptr->offset_table_count_free++; - break; - } - } - if (png_ptr->offset_table_count_free == png_ptr->offset_table_count) - { - farfree(png_ptr->offset_table); - farfree(png_ptr->offset_table_ptr); - png_ptr->offset_table = NULL; - png_ptr->offset_table_ptr = NULL; - } - } - - if (ptr != NULL) - { - farfree(ptr); - } -} - -#else /* Not the Borland DOS special memory handler */ - -/* Allocate memory for a png_struct or a png_info. The malloc and - memset can be replaced by a single call to calloc() if this is thought - to improve performance noticably. */ -png_voidp /* PRIVATE */ -png_create_struct(int type) -{ -#ifdef PNG_USER_MEM_SUPPORTED - return (png_create_struct_2(type, png_malloc_ptr_NULL, png_voidp_NULL)); -} - -/* Allocate memory for a png_struct or a png_info. The malloc and - memset can be replaced by a single call to calloc() if this is thought - to improve performance noticably. */ -png_voidp /* PRIVATE */ -png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr) -{ -#endif /* PNG_USER_MEM_SUPPORTED */ - png_size_t size; - png_voidp struct_ptr; - - if (type == PNG_STRUCT_INFO) - size = png_sizeof(png_info); - else if (type == PNG_STRUCT_PNG) - size = png_sizeof(png_struct); - else - return (NULL); - -#ifdef PNG_USER_MEM_SUPPORTED - if(malloc_fn != NULL) - { - png_struct dummy_struct; - png_structp png_ptr = &dummy_struct; - png_ptr->mem_ptr=mem_ptr; - struct_ptr = (*(malloc_fn))(png_ptr, size); - if (struct_ptr != NULL) - png_memset(struct_ptr, 0, size); - return (struct_ptr); - } -#endif /* PNG_USER_MEM_SUPPORTED */ - -#if defined(__TURBOC__) && !defined(__FLAT__) - struct_ptr = (png_voidp)farmalloc(size); -#else -# if defined(_MSC_VER) && defined(MAXSEG_64K) - struct_ptr = (png_voidp)halloc(size,1); -# else - struct_ptr = (png_voidp)malloc(size); -# endif -#endif - if (struct_ptr != NULL) - png_memset(struct_ptr, 0, size); - - return (struct_ptr); -} - - -/* Free memory allocated by a png_create_struct() call */ -void /* PRIVATE */ -png_destroy_struct(png_voidp struct_ptr) -{ -#ifdef PNG_USER_MEM_SUPPORTED - png_destroy_struct_2(struct_ptr, png_free_ptr_NULL, png_voidp_NULL); -} - -/* Free memory allocated by a png_create_struct() call */ -void /* PRIVATE */ -png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn, - png_voidp mem_ptr) -{ -#endif /* PNG_USER_MEM_SUPPORTED */ - if (struct_ptr != NULL) - { -#ifdef PNG_USER_MEM_SUPPORTED - if(free_fn != NULL) - { - png_struct dummy_struct; - png_structp png_ptr = &dummy_struct; - png_ptr->mem_ptr=mem_ptr; - (*(free_fn))(png_ptr, struct_ptr); - return; - } -#endif /* PNG_USER_MEM_SUPPORTED */ -#if defined(__TURBOC__) && !defined(__FLAT__) - farfree(struct_ptr); -#else -# if defined(_MSC_VER) && defined(MAXSEG_64K) - hfree(struct_ptr); -# else - free(struct_ptr); -# endif -#endif - } -} - -/* Allocate memory. For reasonable files, size should never exceed - 64K. However, zlib may allocate more then 64K if you don't tell - it not to. See zconf.h and png.h for more information. zlib does - need to allocate exactly 64K, so whatever you call here must - have the ability to do that. */ - -png_voidp PNGAPI -png_malloc(png_structp png_ptr, png_uint_32 size) -{ - png_voidp ret; - -#ifdef PNG_USER_MEM_SUPPORTED - if (png_ptr == NULL || size == 0) - return (NULL); - - if(png_ptr->malloc_fn != NULL) - ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size)); - else - ret = (png_malloc_default(png_ptr, size)); - if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) - png_error(png_ptr, "Out of Memory!"); - return (ret); -} - -png_voidp PNGAPI -png_malloc_default(png_structp png_ptr, png_uint_32 size) -{ - png_voidp ret; -#endif /* PNG_USER_MEM_SUPPORTED */ - - if (png_ptr == NULL || size == 0) - return (NULL); - -#ifdef PNG_MAX_MALLOC_64K - if (size > (png_uint_32)65536L) - { -#ifndef PNG_USER_MEM_SUPPORTED - if(png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) - png_error(png_ptr, "Cannot Allocate > 64K"); - else -#endif - return NULL; - } -#endif - - /* Check for overflow */ -#if defined(__TURBOC__) && !defined(__FLAT__) - if (size != (unsigned long)size) - ret = NULL; - else - ret = farmalloc(size); -#else -# if defined(_MSC_VER) && defined(MAXSEG_64K) - if (size != (unsigned long)size) - ret = NULL; - else - ret = halloc(size, 1); -# else - if (size != (size_t)size) - ret = NULL; - else - ret = malloc((size_t)size); -# endif -#endif - -#ifndef PNG_USER_MEM_SUPPORTED - if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) - png_error(png_ptr, "Out of Memory"); -#endif - - return (ret); -} - -/* Free a pointer allocated by png_malloc(). If ptr is NULL, return - without taking any action. */ -void PNGAPI -png_free(png_structp png_ptr, png_voidp ptr) -{ - if (png_ptr == NULL || ptr == NULL) - return; - -#ifdef PNG_USER_MEM_SUPPORTED - if (png_ptr->free_fn != NULL) - { - (*(png_ptr->free_fn))(png_ptr, ptr); - return; - } - else png_free_default(png_ptr, ptr); -} -void PNGAPI -png_free_default(png_structp png_ptr, png_voidp ptr) -{ - if (png_ptr == NULL || ptr == NULL) - return; - -#endif /* PNG_USER_MEM_SUPPORTED */ - -#if defined(__TURBOC__) && !defined(__FLAT__) - farfree(ptr); -#else -# if defined(_MSC_VER) && defined(MAXSEG_64K) - hfree(ptr); -# else - free(ptr); -# endif -#endif -} - -#endif /* Not Borland DOS special memory handler */ - -#if defined(PNG_1_0_X) -# define png_malloc_warn png_malloc -#else -/* This function was added at libpng version 1.2.3. The png_malloc_warn() - * function will set up png_malloc() to issue a png_warning and return NULL - * instead of issuing a png_error, if it fails to allocate the requested - * memory. - */ -png_voidp PNGAPI -png_malloc_warn(png_structp png_ptr, png_uint_32 size) -{ - png_voidp ptr; - png_uint_32 save_flags; - if(png_ptr == NULL) return (NULL); - - save_flags=png_ptr->flags; - png_ptr->flags|=PNG_FLAG_MALLOC_NULL_MEM_OK; - ptr = (png_voidp)png_malloc((png_structp)png_ptr, size); - png_ptr->flags=save_flags; - return(ptr); -} -#endif - -png_voidp PNGAPI -png_memcpy_check (png_structp png_ptr, png_voidp s1, png_voidp s2, - png_uint_32 length) -{ - png_size_t size; - - size = (png_size_t)length; - if ((png_uint_32)size != length) - png_error(png_ptr,"Overflow in png_memcpy_check."); - - return(png_memcpy (s1, s2, size)); -} - -png_voidp PNGAPI -png_memset_check (png_structp png_ptr, png_voidp s1, int value, - png_uint_32 length) -{ - png_size_t size; - - size = (png_size_t)length; - if ((png_uint_32)size != length) - png_error(png_ptr,"Overflow in png_memset_check."); - - return (png_memset (s1, value, size)); - -} - -#ifdef PNG_USER_MEM_SUPPORTED -/* This function is called when the application wants to use another method - * of allocating and freeing memory. - */ -void PNGAPI -png_set_mem_fn(png_structp png_ptr, png_voidp mem_ptr, png_malloc_ptr - malloc_fn, png_free_ptr free_fn) -{ - if(png_ptr != NULL) { - png_ptr->mem_ptr = mem_ptr; - png_ptr->malloc_fn = malloc_fn; - png_ptr->free_fn = free_fn; - } -} - -/* This function returns a pointer to the mem_ptr associated with the user - * functions. The application should free any memory associated with this - * pointer before png_write_destroy and png_read_destroy are called. - */ -png_voidp PNGAPI -png_get_mem_ptr(png_structp png_ptr) -{ - if(png_ptr == NULL) return (NULL); - return ((png_voidp)png_ptr->mem_ptr); -} -#endif /* PNG_USER_MEM_SUPPORTED */ -#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/rosapps/lib/libpng/pngpread.c b/rosapps/lib/libpng/pngpread.c deleted file mode 100644 index 8f4b7d1795c..00000000000 --- a/rosapps/lib/libpng/pngpread.c +++ /dev/null @@ -1,1586 +0,0 @@ - -/* pngpread.c - read a png file in push mode - * - * Last changed in libpng 1.2.23 [November 6, 2007] - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2007 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - */ - -#define PNG_INTERNAL -#include "png.h" - -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED - -/* push model modes */ -#define PNG_READ_SIG_MODE 0 -#define PNG_READ_CHUNK_MODE 1 -#define PNG_READ_IDAT_MODE 2 -#define PNG_SKIP_MODE 3 -#define PNG_READ_tEXt_MODE 4 -#define PNG_READ_zTXt_MODE 5 -#define PNG_READ_DONE_MODE 6 -#define PNG_READ_iTXt_MODE 7 -#define PNG_ERROR_MODE 8 - -void PNGAPI -png_process_data(png_structp png_ptr, png_infop info_ptr, - png_bytep buffer, png_size_t buffer_size) -{ - if(png_ptr == NULL) return; - png_push_restore_buffer(png_ptr, buffer, buffer_size); - - while (png_ptr->buffer_size) - { - png_process_some_data(png_ptr, info_ptr); - } -} - -/* What we do with the incoming data depends on what we were previously - * doing before we ran out of data... - */ -void /* PRIVATE */ -png_process_some_data(png_structp png_ptr, png_infop info_ptr) -{ - if(png_ptr == NULL) return; - switch (png_ptr->process_mode) - { - case PNG_READ_SIG_MODE: - { - png_push_read_sig(png_ptr, info_ptr); - break; - } - case PNG_READ_CHUNK_MODE: - { - png_push_read_chunk(png_ptr, info_ptr); - break; - } - case PNG_READ_IDAT_MODE: - { - png_push_read_IDAT(png_ptr); - break; - } -#if defined(PNG_READ_tEXt_SUPPORTED) - case PNG_READ_tEXt_MODE: - { - png_push_read_tEXt(png_ptr, info_ptr); - break; - } -#endif -#if defined(PNG_READ_zTXt_SUPPORTED) - case PNG_READ_zTXt_MODE: - { - png_push_read_zTXt(png_ptr, info_ptr); - break; - } -#endif -#if defined(PNG_READ_iTXt_SUPPORTED) - case PNG_READ_iTXt_MODE: - { - png_push_read_iTXt(png_ptr, info_ptr); - break; - } -#endif - case PNG_SKIP_MODE: - { - png_push_crc_finish(png_ptr); - break; - } - default: - { - png_ptr->buffer_size = 0; - break; - } - } -} - -/* Read any remaining signature bytes from the stream and compare them with - * the correct PNG signature. It is possible that this routine is called - * with bytes already read from the signature, either because they have been - * checked by the calling application, or because of multiple calls to this - * routine. - */ -void /* PRIVATE */ -png_push_read_sig(png_structp png_ptr, png_infop info_ptr) -{ - png_size_t num_checked = png_ptr->sig_bytes, - num_to_check = 8 - num_checked; - - if (png_ptr->buffer_size < num_to_check) - { - num_to_check = png_ptr->buffer_size; - } - - png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]), - num_to_check); - png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes+num_to_check); - - if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check)) - { - if (num_checked < 4 && - png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) - png_error(png_ptr, "Not a PNG file"); - else - png_error(png_ptr, "PNG file corrupted by ASCII conversion"); - } - else - { - if (png_ptr->sig_bytes >= 8) - { - png_ptr->process_mode = PNG_READ_CHUNK_MODE; - } - } -} - -void /* PRIVATE */ -png_push_read_chunk(png_structp png_ptr, png_infop info_ptr) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_CONST PNG_IHDR; - PNG_CONST PNG_IDAT; - PNG_CONST PNG_IEND; - PNG_CONST PNG_PLTE; -#if defined(PNG_READ_bKGD_SUPPORTED) - PNG_CONST PNG_bKGD; -#endif -#if defined(PNG_READ_cHRM_SUPPORTED) - PNG_CONST PNG_cHRM; -#endif -#if defined(PNG_READ_gAMA_SUPPORTED) - PNG_CONST PNG_gAMA; -#endif -#if defined(PNG_READ_hIST_SUPPORTED) - PNG_CONST PNG_hIST; -#endif -#if defined(PNG_READ_iCCP_SUPPORTED) - PNG_CONST PNG_iCCP; -#endif -#if defined(PNG_READ_iTXt_SUPPORTED) - PNG_CONST PNG_iTXt; -#endif -#if defined(PNG_READ_oFFs_SUPPORTED) - PNG_CONST PNG_oFFs; -#endif -#if defined(PNG_READ_pCAL_SUPPORTED) - PNG_CONST PNG_pCAL; -#endif -#if defined(PNG_READ_pHYs_SUPPORTED) - PNG_CONST PNG_pHYs; -#endif -#if defined(PNG_READ_sBIT_SUPPORTED) - PNG_CONST PNG_sBIT; -#endif -#if defined(PNG_READ_sCAL_SUPPORTED) - PNG_CONST PNG_sCAL; -#endif -#if defined(PNG_READ_sRGB_SUPPORTED) - PNG_CONST PNG_sRGB; -#endif -#if defined(PNG_READ_sPLT_SUPPORTED) - PNG_CONST PNG_sPLT; -#endif -#if defined(PNG_READ_tEXt_SUPPORTED) - PNG_CONST PNG_tEXt; -#endif -#if defined(PNG_READ_tIME_SUPPORTED) - PNG_CONST PNG_tIME; -#endif -#if defined(PNG_READ_tRNS_SUPPORTED) - PNG_CONST PNG_tRNS; -#endif -#if defined(PNG_READ_zTXt_SUPPORTED) - PNG_CONST PNG_zTXt; -#endif -#endif /* PNG_USE_LOCAL_ARRAYS */ - /* First we make sure we have enough data for the 4 byte chunk name - * and the 4 byte chunk length before proceeding with decoding the - * chunk data. To fully decode each of these chunks, we also make - * sure we have enough data in the buffer for the 4 byte CRC at the - * end of every chunk (except IDAT, which is handled separately). - */ - if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER)) - { - png_byte chunk_length[4]; - - if (png_ptr->buffer_size < 8) - { - png_push_save_buffer(png_ptr); - return; - } - - png_push_fill_buffer(png_ptr, chunk_length, 4); - png_ptr->push_length = png_get_uint_31(png_ptr,chunk_length); - png_reset_crc(png_ptr); - png_crc_read(png_ptr, png_ptr->chunk_name, 4); - png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; - } - - if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) - if(png_ptr->mode & PNG_AFTER_IDAT) - png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT; - - if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length); - } - else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length); - - png_ptr->process_mode = PNG_READ_DONE_MODE; - png_push_have_end(png_ptr, info_ptr); - } -#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED - else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) - png_ptr->mode |= PNG_HAVE_IDAT; - png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length); - if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) - png_ptr->mode |= PNG_HAVE_PLTE; - else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) - { - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before IDAT"); - else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && - !(png_ptr->mode & PNG_HAVE_PLTE)) - png_error(png_ptr, "Missing PLTE before IDAT"); - } - } -#endif - else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length); - } - else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) - { - /* If we reach an IDAT chunk, this means we have read all of the - * header chunks, and we can start reading the image (or if this - * is called after the image has been read - we have an error). - */ - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before IDAT"); - else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && - !(png_ptr->mode & PNG_HAVE_PLTE)) - png_error(png_ptr, "Missing PLTE before IDAT"); - - if (png_ptr->mode & PNG_HAVE_IDAT) - { - if (!(png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) - if (png_ptr->push_length == 0) - return; - - if (png_ptr->mode & PNG_AFTER_IDAT) - png_error(png_ptr, "Too many IDAT's found"); - } - - png_ptr->idat_size = png_ptr->push_length; - png_ptr->mode |= PNG_HAVE_IDAT; - png_ptr->process_mode = PNG_READ_IDAT_MODE; - png_push_have_info(png_ptr, info_ptr); - png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes; - png_ptr->zstream.next_out = png_ptr->row_buf; - return; - } -#if defined(PNG_READ_gAMA_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_sBIT_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_cHRM_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_sRGB_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_iCCP_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_sPLT_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_tRNS_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_bKGD_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_hIST_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_pHYs_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_oFFs_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_pCAL_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_sCAL_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_tIME_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_tEXt_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_push_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_zTXt_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_push_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length); - } -#endif -#if defined(PNG_READ_iTXt_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_push_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length); - } -#endif - else - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - png_push_handle_unknown(png_ptr, info_ptr, png_ptr->push_length); - } - - png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; -} - -void /* PRIVATE */ -png_push_crc_skip(png_structp png_ptr, png_uint_32 skip) -{ - png_ptr->process_mode = PNG_SKIP_MODE; - png_ptr->skip_length = skip; -} - -void /* PRIVATE */ -png_push_crc_finish(png_structp png_ptr) -{ - if (png_ptr->skip_length && png_ptr->save_buffer_size) - { - png_size_t save_size; - - if (png_ptr->skip_length < (png_uint_32)png_ptr->save_buffer_size) - save_size = (png_size_t)png_ptr->skip_length; - else - save_size = png_ptr->save_buffer_size; - - png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size); - - png_ptr->skip_length -= save_size; - png_ptr->buffer_size -= save_size; - png_ptr->save_buffer_size -= save_size; - png_ptr->save_buffer_ptr += save_size; - } - if (png_ptr->skip_length && png_ptr->current_buffer_size) - { - png_size_t save_size; - - if (png_ptr->skip_length < (png_uint_32)png_ptr->current_buffer_size) - save_size = (png_size_t)png_ptr->skip_length; - else - save_size = png_ptr->current_buffer_size; - - png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size); - - png_ptr->skip_length -= save_size; - png_ptr->buffer_size -= save_size; - png_ptr->current_buffer_size -= save_size; - png_ptr->current_buffer_ptr += save_size; - } - if (!png_ptr->skip_length) - { - if (png_ptr->buffer_size < 4) - { - png_push_save_buffer(png_ptr); - return; - } - - png_crc_finish(png_ptr, 0); - png_ptr->process_mode = PNG_READ_CHUNK_MODE; - } -} - -void PNGAPI -png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length) -{ - png_bytep ptr; - - if(png_ptr == NULL) return; - ptr = buffer; - if (png_ptr->save_buffer_size) - { - png_size_t save_size; - - if (length < png_ptr->save_buffer_size) - save_size = length; - else - save_size = png_ptr->save_buffer_size; - - png_memcpy(ptr, png_ptr->save_buffer_ptr, save_size); - length -= save_size; - ptr += save_size; - png_ptr->buffer_size -= save_size; - png_ptr->save_buffer_size -= save_size; - png_ptr->save_buffer_ptr += save_size; - } - if (length && png_ptr->current_buffer_size) - { - png_size_t save_size; - - if (length < png_ptr->current_buffer_size) - save_size = length; - else - save_size = png_ptr->current_buffer_size; - - png_memcpy(ptr, png_ptr->current_buffer_ptr, save_size); - png_ptr->buffer_size -= save_size; - png_ptr->current_buffer_size -= save_size; - png_ptr->current_buffer_ptr += save_size; - } -} - -void /* PRIVATE */ -png_push_save_buffer(png_structp png_ptr) -{ - if (png_ptr->save_buffer_size) - { - if (png_ptr->save_buffer_ptr != png_ptr->save_buffer) - { - png_size_t i,istop; - png_bytep sp; - png_bytep dp; - - istop = png_ptr->save_buffer_size; - for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer; - i < istop; i++, sp++, dp++) - { - *dp = *sp; - } - } - } - if (png_ptr->save_buffer_size + png_ptr->current_buffer_size > - png_ptr->save_buffer_max) - { - png_size_t new_max; - png_bytep old_buffer; - - if (png_ptr->save_buffer_size > PNG_SIZE_MAX - - (png_ptr->current_buffer_size + 256)) - { - png_error(png_ptr, "Potential overflow of save_buffer"); - } - new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256; - old_buffer = png_ptr->save_buffer; - png_ptr->save_buffer = (png_bytep)png_malloc(png_ptr, - (png_uint_32)new_max); - png_memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size); - png_free(png_ptr, old_buffer); - png_ptr->save_buffer_max = new_max; - } - if (png_ptr->current_buffer_size) - { - png_memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size, - png_ptr->current_buffer_ptr, png_ptr->current_buffer_size); - png_ptr->save_buffer_size += png_ptr->current_buffer_size; - png_ptr->current_buffer_size = 0; - } - png_ptr->save_buffer_ptr = png_ptr->save_buffer; - png_ptr->buffer_size = 0; -} - -void /* PRIVATE */ -png_push_restore_buffer(png_structp png_ptr, png_bytep buffer, - png_size_t buffer_length) -{ - png_ptr->current_buffer = buffer; - png_ptr->current_buffer_size = buffer_length; - png_ptr->buffer_size = buffer_length + png_ptr->save_buffer_size; - png_ptr->current_buffer_ptr = png_ptr->current_buffer; -} - -void /* PRIVATE */ -png_push_read_IDAT(png_structp png_ptr) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_CONST PNG_IDAT; -#endif - if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER)) - { - png_byte chunk_length[4]; - - if (png_ptr->buffer_size < 8) - { - png_push_save_buffer(png_ptr); - return; - } - - png_push_fill_buffer(png_ptr, chunk_length, 4); - png_ptr->push_length = png_get_uint_31(png_ptr,chunk_length); - png_reset_crc(png_ptr); - png_crc_read(png_ptr, png_ptr->chunk_name, 4); - png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; - - if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) - { - png_ptr->process_mode = PNG_READ_CHUNK_MODE; - if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) - png_error(png_ptr, "Not enough compressed data"); - return; - } - - png_ptr->idat_size = png_ptr->push_length; - } - if (png_ptr->idat_size && png_ptr->save_buffer_size) - { - png_size_t save_size; - - if (png_ptr->idat_size < (png_uint_32)png_ptr->save_buffer_size) - { - save_size = (png_size_t)png_ptr->idat_size; - /* check for overflow */ - if((png_uint_32)save_size != png_ptr->idat_size) - png_error(png_ptr, "save_size overflowed in pngpread"); - } - else - save_size = png_ptr->save_buffer_size; - - png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size); - if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) - png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size); - png_ptr->idat_size -= save_size; - png_ptr->buffer_size -= save_size; - png_ptr->save_buffer_size -= save_size; - png_ptr->save_buffer_ptr += save_size; - } - if (png_ptr->idat_size && png_ptr->current_buffer_size) - { - png_size_t save_size; - - if (png_ptr->idat_size < (png_uint_32)png_ptr->current_buffer_size) - { - save_size = (png_size_t)png_ptr->idat_size; - /* check for overflow */ - if((png_uint_32)save_size != png_ptr->idat_size) - png_error(png_ptr, "save_size overflowed in pngpread"); - } - else - save_size = png_ptr->current_buffer_size; - - png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size); - if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) - png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size); - - png_ptr->idat_size -= save_size; - png_ptr->buffer_size -= save_size; - png_ptr->current_buffer_size -= save_size; - png_ptr->current_buffer_ptr += save_size; - } - if (!png_ptr->idat_size) - { - if (png_ptr->buffer_size < 4) - { - png_push_save_buffer(png_ptr); - return; - } - - png_crc_finish(png_ptr, 0); - png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; - png_ptr->mode |= PNG_AFTER_IDAT; - } -} - -void /* PRIVATE */ -png_process_IDAT_data(png_structp png_ptr, png_bytep buffer, - png_size_t buffer_length) -{ - int ret; - - if ((png_ptr->flags & PNG_FLAG_ZLIB_FINISHED) && buffer_length) - png_error(png_ptr, "Extra compression data"); - - png_ptr->zstream.next_in = buffer; - png_ptr->zstream.avail_in = (uInt)buffer_length; - for(;;) - { - ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); - if (ret != Z_OK) - { - if (ret == Z_STREAM_END) - { - if (png_ptr->zstream.avail_in) - png_error(png_ptr, "Extra compressed data"); - if (!(png_ptr->zstream.avail_out)) - { - png_push_process_row(png_ptr); - } - - png_ptr->mode |= PNG_AFTER_IDAT; - png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; - break; - } - else if (ret == Z_BUF_ERROR) - break; - else - png_error(png_ptr, "Decompression Error"); - } - if (!(png_ptr->zstream.avail_out)) - { - if (( -#if defined(PNG_READ_INTERLACING_SUPPORTED) - png_ptr->interlaced && png_ptr->pass > 6) || - (!png_ptr->interlaced && -#endif - png_ptr->row_number == png_ptr->num_rows)) - { - if (png_ptr->zstream.avail_in) - png_warning(png_ptr, "Too much data in IDAT chunks"); - png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; - break; - } - png_push_process_row(png_ptr); - png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes; - png_ptr->zstream.next_out = png_ptr->row_buf; - } - else - break; - } -} - -void /* PRIVATE */ -png_push_process_row(png_structp png_ptr) -{ - png_ptr->row_info.color_type = png_ptr->color_type; - png_ptr->row_info.width = png_ptr->iwidth; - png_ptr->row_info.channels = png_ptr->channels; - png_ptr->row_info.bit_depth = png_ptr->bit_depth; - png_ptr->row_info.pixel_depth = png_ptr->pixel_depth; - - png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, - png_ptr->row_info.width); - - png_read_filter_row(png_ptr, &(png_ptr->row_info), - png_ptr->row_buf + 1, png_ptr->prev_row + 1, - (int)(png_ptr->row_buf[0])); - - png_memcpy_check(png_ptr, png_ptr->prev_row, png_ptr->row_buf, - png_ptr->rowbytes + 1); - - if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA)) - png_do_read_transformations(png_ptr); - -#if defined(PNG_READ_INTERLACING_SUPPORTED) - /* blow up interlaced rows to full size */ - if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) - { - if (png_ptr->pass < 6) -/* old interface (pre-1.0.9): - png_do_read_interlace(&(png_ptr->row_info), - png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations); - */ - png_do_read_interlace(png_ptr); - - switch (png_ptr->pass) - { - case 0: - { - int i; - for (i = 0; i < 8 && png_ptr->pass == 0; i++) - { - png_push_have_row(png_ptr, png_ptr->row_buf + 1); - png_read_push_finish_row(png_ptr); /* updates png_ptr->pass */ - } - if (png_ptr->pass == 2) /* pass 1 might be empty */ - { - for (i = 0; i < 4 && png_ptr->pass == 2; i++) - { - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - } - if (png_ptr->pass == 4 && png_ptr->height <= 4) - { - for (i = 0; i < 2 && png_ptr->pass == 4; i++) - { - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - } - if (png_ptr->pass == 6 && png_ptr->height <= 4) - { - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - break; - } - case 1: - { - int i; - for (i = 0; i < 8 && png_ptr->pass == 1; i++) - { - png_push_have_row(png_ptr, png_ptr->row_buf + 1); - png_read_push_finish_row(png_ptr); - } - if (png_ptr->pass == 2) /* skip top 4 generated rows */ - { - for (i = 0; i < 4 && png_ptr->pass == 2; i++) - { - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - } - break; - } - case 2: - { - int i; - for (i = 0; i < 4 && png_ptr->pass == 2; i++) - { - png_push_have_row(png_ptr, png_ptr->row_buf + 1); - png_read_push_finish_row(png_ptr); - } - for (i = 0; i < 4 && png_ptr->pass == 2; i++) - { - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - if (png_ptr->pass == 4) /* pass 3 might be empty */ - { - for (i = 0; i < 2 && png_ptr->pass == 4; i++) - { - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - } - break; - } - case 3: - { - int i; - for (i = 0; i < 4 && png_ptr->pass == 3; i++) - { - png_push_have_row(png_ptr, png_ptr->row_buf + 1); - png_read_push_finish_row(png_ptr); - } - if (png_ptr->pass == 4) /* skip top two generated rows */ - { - for (i = 0; i < 2 && png_ptr->pass == 4; i++) - { - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - } - break; - } - case 4: - { - int i; - for (i = 0; i < 2 && png_ptr->pass == 4; i++) - { - png_push_have_row(png_ptr, png_ptr->row_buf + 1); - png_read_push_finish_row(png_ptr); - } - for (i = 0; i < 2 && png_ptr->pass == 4; i++) - { - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - if (png_ptr->pass == 6) /* pass 5 might be empty */ - { - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - break; - } - case 5: - { - int i; - for (i = 0; i < 2 && png_ptr->pass == 5; i++) - { - png_push_have_row(png_ptr, png_ptr->row_buf + 1); - png_read_push_finish_row(png_ptr); - } - if (png_ptr->pass == 6) /* skip top generated row */ - { - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - break; - } - case 6: - { - png_push_have_row(png_ptr, png_ptr->row_buf + 1); - png_read_push_finish_row(png_ptr); - if (png_ptr->pass != 6) - break; - png_push_have_row(png_ptr, png_bytep_NULL); - png_read_push_finish_row(png_ptr); - } - } - } - else -#endif - { - png_push_have_row(png_ptr, png_ptr->row_buf + 1); - png_read_push_finish_row(png_ptr); - } -} - -void /* PRIVATE */ -png_read_push_finish_row(png_structp png_ptr) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - - /* start of interlace block */ - PNG_CONST int FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; - - /* offset to next interlace block */ - PNG_CONST int FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; - - /* start of interlace block in the y direction */ - PNG_CONST int FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1}; - - /* offset to next interlace block in the y direction */ - PNG_CONST int FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2}; - - /* Height of interlace block. This is not currently used - if you need - * it, uncomment it here and in png.h - PNG_CONST int FARDATA png_pass_height[] = {8, 8, 4, 4, 2, 2, 1}; - */ -#endif - - png_ptr->row_number++; - if (png_ptr->row_number < png_ptr->num_rows) - return; - - if (png_ptr->interlaced) - { - png_ptr->row_number = 0; - png_memset_check(png_ptr, png_ptr->prev_row, 0, - png_ptr->rowbytes + 1); - do - { - png_ptr->pass++; - if ((png_ptr->pass == 1 && png_ptr->width < 5) || - (png_ptr->pass == 3 && png_ptr->width < 3) || - (png_ptr->pass == 5 && png_ptr->width < 2)) - png_ptr->pass++; - - if (png_ptr->pass > 7) - png_ptr->pass--; - if (png_ptr->pass >= 7) - break; - - png_ptr->iwidth = (png_ptr->width + - png_pass_inc[png_ptr->pass] - 1 - - png_pass_start[png_ptr->pass]) / - png_pass_inc[png_ptr->pass]; - - png_ptr->irowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, - png_ptr->iwidth) + 1; - - if (png_ptr->transformations & PNG_INTERLACE) - break; - - png_ptr->num_rows = (png_ptr->height + - png_pass_yinc[png_ptr->pass] - 1 - - png_pass_ystart[png_ptr->pass]) / - png_pass_yinc[png_ptr->pass]; - - } while (png_ptr->iwidth == 0 || png_ptr->num_rows == 0); - } -} - -#if defined(PNG_READ_tEXt_SUPPORTED) -void /* PRIVATE */ -png_push_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 - length) -{ - if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) - { - png_error(png_ptr, "Out of place tEXt"); - info_ptr = info_ptr; /* to quiet some compiler warnings */ - } - -#ifdef PNG_MAX_MALLOC_64K - png_ptr->skip_length = 0; /* This may not be necessary */ - - if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */ - { - png_warning(png_ptr, "tEXt chunk too large to fit in memory"); - png_ptr->skip_length = length - (png_uint_32)65535L; - length = (png_uint_32)65535L; - } -#endif - - png_ptr->current_text = (png_charp)png_malloc(png_ptr, - (png_uint_32)(length+1)); - png_ptr->current_text[length] = '\0'; - png_ptr->current_text_ptr = png_ptr->current_text; - png_ptr->current_text_size = (png_size_t)length; - png_ptr->current_text_left = (png_size_t)length; - png_ptr->process_mode = PNG_READ_tEXt_MODE; -} - -void /* PRIVATE */ -png_push_read_tEXt(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr->buffer_size && png_ptr->current_text_left) - { - png_size_t text_size; - - if (png_ptr->buffer_size < png_ptr->current_text_left) - text_size = png_ptr->buffer_size; - else - text_size = png_ptr->current_text_left; - png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); - png_ptr->current_text_left -= text_size; - png_ptr->current_text_ptr += text_size; - } - if (!(png_ptr->current_text_left)) - { - png_textp text_ptr; - png_charp text; - png_charp key; - int ret; - - if (png_ptr->buffer_size < 4) - { - png_push_save_buffer(png_ptr); - return; - } - - png_push_crc_finish(png_ptr); - -#if defined(PNG_MAX_MALLOC_64K) - if (png_ptr->skip_length) - return; -#endif - - key = png_ptr->current_text; - - for (text = key; *text; text++) - /* empty loop */ ; - - if (text < key + png_ptr->current_text_size) - text++; - - text_ptr = (png_textp)png_malloc(png_ptr, - (png_uint_32)png_sizeof(png_text)); - text_ptr->compression = PNG_TEXT_COMPRESSION_NONE; - text_ptr->key = key; -#ifdef PNG_iTXt_SUPPORTED - text_ptr->lang = NULL; - text_ptr->lang_key = NULL; -#endif - text_ptr->text = text; - - ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); - - png_free(png_ptr, key); - png_free(png_ptr, text_ptr); - png_ptr->current_text = NULL; - - if (ret) - png_warning(png_ptr, "Insufficient memory to store text chunk."); - } -} -#endif - -#if defined(PNG_READ_zTXt_SUPPORTED) -void /* PRIVATE */ -png_push_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 - length) -{ - if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) - { - png_error(png_ptr, "Out of place zTXt"); - info_ptr = info_ptr; /* to quiet some compiler warnings */ - } - -#ifdef PNG_MAX_MALLOC_64K - /* We can't handle zTXt chunks > 64K, since we don't have enough space - * to be able to store the uncompressed data. Actually, the threshold - * is probably around 32K, but it isn't as definite as 64K is. - */ - if (length > (png_uint_32)65535L) - { - png_warning(png_ptr, "zTXt chunk too large to fit in memory"); - png_push_crc_skip(png_ptr, length); - return; - } -#endif - - png_ptr->current_text = (png_charp)png_malloc(png_ptr, - (png_uint_32)(length+1)); - png_ptr->current_text[length] = '\0'; - png_ptr->current_text_ptr = png_ptr->current_text; - png_ptr->current_text_size = (png_size_t)length; - png_ptr->current_text_left = (png_size_t)length; - png_ptr->process_mode = PNG_READ_zTXt_MODE; -} - -void /* PRIVATE */ -png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr->buffer_size && png_ptr->current_text_left) - { - png_size_t text_size; - - if (png_ptr->buffer_size < (png_uint_32)png_ptr->current_text_left) - text_size = png_ptr->buffer_size; - else - text_size = png_ptr->current_text_left; - png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); - png_ptr->current_text_left -= text_size; - png_ptr->current_text_ptr += text_size; - } - if (!(png_ptr->current_text_left)) - { - png_textp text_ptr; - png_charp text; - png_charp key; - int ret; - png_size_t text_size, key_size; - - if (png_ptr->buffer_size < 4) - { - png_push_save_buffer(png_ptr); - return; - } - - png_push_crc_finish(png_ptr); - - key = png_ptr->current_text; - - for (text = key; *text; text++) - /* empty loop */ ; - - /* zTXt can't have zero text */ - if (text >= key + png_ptr->current_text_size) - { - png_ptr->current_text = NULL; - png_free(png_ptr, key); - return; - } - - text++; - - if (*text != PNG_TEXT_COMPRESSION_zTXt) /* check compression byte */ - { - png_ptr->current_text = NULL; - png_free(png_ptr, key); - return; - } - - text++; - - png_ptr->zstream.next_in = (png_bytep )text; - png_ptr->zstream.avail_in = (uInt)(png_ptr->current_text_size - - (text - key)); - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - - key_size = text - key; - text_size = 0; - text = NULL; - ret = Z_STREAM_END; - - while (png_ptr->zstream.avail_in) - { - ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); - if (ret != Z_OK && ret != Z_STREAM_END) - { - inflateReset(&png_ptr->zstream); - png_ptr->zstream.avail_in = 0; - png_ptr->current_text = NULL; - png_free(png_ptr, key); - png_free(png_ptr, text); - return; - } - if (!(png_ptr->zstream.avail_out) || ret == Z_STREAM_END) - { - if (text == NULL) - { - text = (png_charp)png_malloc(png_ptr, - (png_uint_32)(png_ptr->zbuf_size - png_ptr->zstream.avail_out - + key_size + 1)); - png_memcpy(text + key_size, png_ptr->zbuf, - png_ptr->zbuf_size - png_ptr->zstream.avail_out); - png_memcpy(text, key, key_size); - text_size = key_size + png_ptr->zbuf_size - - png_ptr->zstream.avail_out; - *(text + text_size) = '\0'; - } - else - { - png_charp tmp; - - tmp = text; - text = (png_charp)png_malloc(png_ptr, text_size + - (png_uint_32)(png_ptr->zbuf_size - png_ptr->zstream.avail_out - + 1)); - png_memcpy(text, tmp, text_size); - png_free(png_ptr, tmp); - png_memcpy(text + text_size, png_ptr->zbuf, - png_ptr->zbuf_size - png_ptr->zstream.avail_out); - text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out; - *(text + text_size) = '\0'; - } - if (ret != Z_STREAM_END) - { - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - } - } - else - { - break; - } - - if (ret == Z_STREAM_END) - break; - } - - inflateReset(&png_ptr->zstream); - png_ptr->zstream.avail_in = 0; - - if (ret != Z_STREAM_END) - { - png_ptr->current_text = NULL; - png_free(png_ptr, key); - png_free(png_ptr, text); - return; - } - - png_ptr->current_text = NULL; - png_free(png_ptr, key); - key = text; - text += key_size; - - text_ptr = (png_textp)png_malloc(png_ptr, - (png_uint_32)png_sizeof(png_text)); - text_ptr->compression = PNG_TEXT_COMPRESSION_zTXt; - text_ptr->key = key; -#ifdef PNG_iTXt_SUPPORTED - text_ptr->lang = NULL; - text_ptr->lang_key = NULL; -#endif - text_ptr->text = text; - - ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); - - png_free(png_ptr, key); - png_free(png_ptr, text_ptr); - - if (ret) - png_warning(png_ptr, "Insufficient memory to store text chunk."); - } -} -#endif - -#if defined(PNG_READ_iTXt_SUPPORTED) -void /* PRIVATE */ -png_push_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 - length) -{ - if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) - { - png_error(png_ptr, "Out of place iTXt"); - info_ptr = info_ptr; /* to quiet some compiler warnings */ - } - -#ifdef PNG_MAX_MALLOC_64K - png_ptr->skip_length = 0; /* This may not be necessary */ - - if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */ - { - png_warning(png_ptr, "iTXt chunk too large to fit in memory"); - png_ptr->skip_length = length - (png_uint_32)65535L; - length = (png_uint_32)65535L; - } -#endif - - png_ptr->current_text = (png_charp)png_malloc(png_ptr, - (png_uint_32)(length+1)); - png_ptr->current_text[length] = '\0'; - png_ptr->current_text_ptr = png_ptr->current_text; - png_ptr->current_text_size = (png_size_t)length; - png_ptr->current_text_left = (png_size_t)length; - png_ptr->process_mode = PNG_READ_iTXt_MODE; -} - -void /* PRIVATE */ -png_push_read_iTXt(png_structp png_ptr, png_infop info_ptr) -{ - - if (png_ptr->buffer_size && png_ptr->current_text_left) - { - png_size_t text_size; - - if (png_ptr->buffer_size < png_ptr->current_text_left) - text_size = png_ptr->buffer_size; - else - text_size = png_ptr->current_text_left; - png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); - png_ptr->current_text_left -= text_size; - png_ptr->current_text_ptr += text_size; - } - if (!(png_ptr->current_text_left)) - { - png_textp text_ptr; - png_charp key; - int comp_flag; - png_charp lang; - png_charp lang_key; - png_charp text; - int ret; - - if (png_ptr->buffer_size < 4) - { - png_push_save_buffer(png_ptr); - return; - } - - png_push_crc_finish(png_ptr); - -#if defined(PNG_MAX_MALLOC_64K) - if (png_ptr->skip_length) - return; -#endif - - key = png_ptr->current_text; - - for (lang = key; *lang; lang++) - /* empty loop */ ; - - if (lang < key + png_ptr->current_text_size - 3) - lang++; - - comp_flag = *lang++; - lang++; /* skip comp_type, always zero */ - - for (lang_key = lang; *lang_key; lang_key++) - /* empty loop */ ; - lang_key++; /* skip NUL separator */ - - text=lang_key; - if (lang_key < key + png_ptr->current_text_size - 1) - { - for (; *text; text++) - /* empty loop */ ; - } - - if (text < key + png_ptr->current_text_size) - text++; - - text_ptr = (png_textp)png_malloc(png_ptr, - (png_uint_32)png_sizeof(png_text)); - text_ptr->compression = comp_flag + 2; - text_ptr->key = key; - text_ptr->lang = lang; - text_ptr->lang_key = lang_key; - text_ptr->text = text; - text_ptr->text_length = 0; - text_ptr->itxt_length = png_strlen(text); - - ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); - - png_ptr->current_text = NULL; - - png_free(png_ptr, text_ptr); - if (ret) - png_warning(png_ptr, "Insufficient memory to store iTXt chunk."); - } -} -#endif - -/* This function is called when we haven't found a handler for this - * chunk. If there isn't a problem with the chunk itself (ie a bad chunk - * name or a critical chunk), the chunk is (currently) silently ignored. - */ -void /* PRIVATE */ -png_push_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 - length) -{ - png_uint_32 skip=0; - png_check_chunk_name(png_ptr, png_ptr->chunk_name); - - if (!(png_ptr->chunk_name[0] & 0x20)) - { -#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) - if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != - PNG_HANDLE_CHUNK_ALWAYS -#if defined(PNG_READ_USER_CHUNKS_SUPPORTED) - && png_ptr->read_user_chunk_fn == NULL -#endif - ) -#endif - png_chunk_error(png_ptr, "unknown critical chunk"); - - info_ptr = info_ptr; /* to quiet some compiler warnings */ - } - -#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) - if (png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) - { -#ifdef PNG_MAX_MALLOC_64K - if (length > (png_uint_32)65535L) - { - png_warning(png_ptr, "unknown chunk too large to fit in memory"); - skip = length - (png_uint_32)65535L; - length = (png_uint_32)65535L; - } -#endif - png_memcpy((png_charp)png_ptr->unknown_chunk.name, - (png_charp)png_ptr->chunk_name, - png_sizeof(png_ptr->unknown_chunk.name)); - png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name)-1]='\0'; - - png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length); - png_ptr->unknown_chunk.size = (png_size_t)length; - png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length); -#if defined(PNG_READ_USER_CHUNKS_SUPPORTED) - if(png_ptr->read_user_chunk_fn != NULL) - { - /* callback to user unknown chunk handler */ - int ret; - ret = (*(png_ptr->read_user_chunk_fn)) - (png_ptr, &png_ptr->unknown_chunk); - if (ret < 0) - png_chunk_error(png_ptr, "error in user chunk"); - if (ret == 0) - { - if (!(png_ptr->chunk_name[0] & 0x20)) - if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != - PNG_HANDLE_CHUNK_ALWAYS) - png_chunk_error(png_ptr, "unknown critical chunk"); - png_set_unknown_chunks(png_ptr, info_ptr, - &png_ptr->unknown_chunk, 1); - } - } -#else - png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1); -#endif - png_free(png_ptr, png_ptr->unknown_chunk.data); - png_ptr->unknown_chunk.data = NULL; - } - else -#endif - skip=length; - png_push_crc_skip(png_ptr, skip); -} - -void /* PRIVATE */ -png_push_have_info(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr->info_fn != NULL) - (*(png_ptr->info_fn))(png_ptr, info_ptr); -} - -void /* PRIVATE */ -png_push_have_end(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr->end_fn != NULL) - (*(png_ptr->end_fn))(png_ptr, info_ptr); -} - -void /* PRIVATE */ -png_push_have_row(png_structp png_ptr, png_bytep row) -{ - if (png_ptr->row_fn != NULL) - (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number, - (int)png_ptr->pass); -} - -void PNGAPI -png_progressive_combine_row (png_structp png_ptr, - png_bytep old_row, png_bytep new_row) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_CONST int FARDATA png_pass_dsp_mask[7] = - {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff}; -#endif - if(png_ptr == NULL) return; - if (new_row != NULL) /* new_row must == png_ptr->row_buf here. */ - png_combine_row(png_ptr, old_row, png_pass_dsp_mask[png_ptr->pass]); -} - -void PNGAPI -png_set_progressive_read_fn(png_structp png_ptr, png_voidp progressive_ptr, - png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn, - png_progressive_end_ptr end_fn) -{ - if(png_ptr == NULL) return; - png_ptr->info_fn = info_fn; - png_ptr->row_fn = row_fn; - png_ptr->end_fn = end_fn; - - png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer); -} - -png_voidp PNGAPI -png_get_progressive_ptr(png_structp png_ptr) -{ - if(png_ptr == NULL) return (NULL); - return png_ptr->io_ptr; -} -#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ diff --git a/rosapps/lib/libpng/pngread.c b/rosapps/lib/libpng/pngread.c deleted file mode 100644 index 5de5e563550..00000000000 --- a/rosapps/lib/libpng/pngread.c +++ /dev/null @@ -1,1473 +0,0 @@ - -/* pngread.c - read a PNG file - * - * Last changed in libpng 1.2.24 December 14, 2007 - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2007 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This file contains routines that an application calls directly to - * read a PNG file or stream. - */ - -#define PNG_INTERNAL -#include "png.h" - -#if defined(PNG_READ_SUPPORTED) - -/* Create a PNG structure for reading, and allocate any memory needed. */ -png_structp PNGAPI -png_create_read_struct(png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn) -{ - -#ifdef PNG_USER_MEM_SUPPORTED - return (png_create_read_struct_2(user_png_ver, error_ptr, error_fn, - warn_fn, png_voidp_NULL, png_malloc_ptr_NULL, png_free_ptr_NULL)); -} - -/* Alternate create PNG structure for reading, and allocate any memory needed. */ -png_structp PNGAPI -png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, - png_malloc_ptr malloc_fn, png_free_ptr free_fn) -{ -#endif /* PNG_USER_MEM_SUPPORTED */ - - png_structp png_ptr; - -#ifdef PNG_SETJMP_SUPPORTED -#ifdef USE_FAR_KEYWORD - jmp_buf jmpbuf; -#endif -#endif - - int i; - - png_debug(1, "in png_create_read_struct\n"); -#ifdef PNG_USER_MEM_SUPPORTED - png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG, - (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr); -#else - png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); -#endif - if (png_ptr == NULL) - return (NULL); - - /* added at libpng-1.2.6 */ -#ifdef PNG_SET_USER_LIMITS_SUPPORTED - png_ptr->user_width_max=PNG_USER_WIDTH_MAX; - png_ptr->user_height_max=PNG_USER_HEIGHT_MAX; -#endif - -#ifdef PNG_SETJMP_SUPPORTED -#ifdef USE_FAR_KEYWORD - if (setjmp(jmpbuf)) -#else - if (setjmp(png_ptr->jmpbuf)) -#endif - { - png_free(png_ptr, png_ptr->zbuf); - png_ptr->zbuf=NULL; -#ifdef PNG_USER_MEM_SUPPORTED - png_destroy_struct_2((png_voidp)png_ptr, - (png_free_ptr)free_fn, (png_voidp)mem_ptr); -#else - png_destroy_struct((png_voidp)png_ptr); -#endif - return (NULL); - } -#ifdef USE_FAR_KEYWORD - png_memcpy(png_ptr->jmpbuf,jmpbuf,png_sizeof(jmp_buf)); -#endif -#endif - -#ifdef PNG_USER_MEM_SUPPORTED - png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn); -#endif - - png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn); - - i=0; - do - { - if(user_png_ver[i] != png_libpng_ver[i]) - png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; - } while (png_libpng_ver[i++]); - - if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) - { - /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so - * we must recompile any applications that use any older library version. - * For versions after libpng 1.0, we will be compatible, so we need - * only check the first digit. - */ - if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] || - (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) || - (user_png_ver[0] == '0' && user_png_ver[2] < '9')) - { -#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) - char msg[80]; - if (user_png_ver) - { - png_snprintf(msg, 80, - "Application was compiled with png.h from libpng-%.20s", - user_png_ver); - png_warning(png_ptr, msg); - } - png_snprintf(msg, 80, - "Application is running with png.c from libpng-%.20s", - png_libpng_ver); - png_warning(png_ptr, msg); -#endif -#ifdef PNG_ERROR_NUMBERS_SUPPORTED - png_ptr->flags=0; -#endif - png_error(png_ptr, - "Incompatible libpng version in application and library"); - } - } - - /* initialize zbuf - compression buffer */ - png_ptr->zbuf_size = PNG_ZBUF_SIZE; - png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, - (png_uint_32)png_ptr->zbuf_size); - png_ptr->zstream.zalloc = png_zalloc; - png_ptr->zstream.zfree = png_zfree; - png_ptr->zstream.opaque = (voidpf)png_ptr; - - switch (inflateInit(&png_ptr->zstream)) - { - case Z_OK: /* Do nothing */ break; - case Z_MEM_ERROR: - case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory error"); break; - case Z_VERSION_ERROR: png_error(png_ptr, "zlib version error"); break; - default: png_error(png_ptr, "Unknown zlib error"); - } - - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - - png_set_read_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL); - -#ifdef PNG_SETJMP_SUPPORTED -/* Applications that neglect to set up their own setjmp() and then encounter - a png_error() will longjmp here. Since the jmpbuf is then meaningless we - abort instead of returning. */ -#ifdef USE_FAR_KEYWORD - if (setjmp(jmpbuf)) - PNG_ABORT(); - png_memcpy(png_ptr->jmpbuf,jmpbuf,png_sizeof(jmp_buf)); -#else - if (setjmp(png_ptr->jmpbuf)) - PNG_ABORT(); -#endif -#endif - return (png_ptr); -} - -#if defined(PNG_1_0_X) || defined(PNG_1_2_X) -/* Initialize PNG structure for reading, and allocate any memory needed. - This interface is deprecated in favour of the png_create_read_struct(), - and it will disappear as of libpng-1.3.0. */ -#undef png_read_init -void PNGAPI -png_read_init(png_structp png_ptr) -{ - /* We only come here via pre-1.0.7-compiled applications */ - png_read_init_2(png_ptr, "1.0.6 or earlier", 0, 0); -} - -void PNGAPI -png_read_init_2(png_structp png_ptr, png_const_charp user_png_ver, - png_size_t png_struct_size, png_size_t png_info_size) -{ - /* We only come here via pre-1.0.12-compiled applications */ - if(png_ptr == NULL) return; -#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) - if(png_sizeof(png_struct) > png_struct_size || - png_sizeof(png_info) > png_info_size) - { - char msg[80]; - png_ptr->warning_fn=NULL; - if (user_png_ver) - { - png_snprintf(msg, 80, - "Application was compiled with png.h from libpng-%.20s", - user_png_ver); - png_warning(png_ptr, msg); - } - png_snprintf(msg, 80, - "Application is running with png.c from libpng-%.20s", - png_libpng_ver); - png_warning(png_ptr, msg); - } -#endif - if(png_sizeof(png_struct) > png_struct_size) - { - png_ptr->error_fn=NULL; -#ifdef PNG_ERROR_NUMBERS_SUPPORTED - png_ptr->flags=0; -#endif - png_error(png_ptr, - "The png struct allocated by the application for reading is too small."); - } - if(png_sizeof(png_info) > png_info_size) - { - png_ptr->error_fn=NULL; -#ifdef PNG_ERROR_NUMBERS_SUPPORTED - png_ptr->flags=0; -#endif - png_error(png_ptr, - "The info struct allocated by application for reading is too small."); - } - png_read_init_3(&png_ptr, user_png_ver, png_struct_size); -} -#endif /* PNG_1_0_X || PNG_1_2_X */ - -void PNGAPI -png_read_init_3(png_structpp ptr_ptr, png_const_charp user_png_ver, - png_size_t png_struct_size) -{ -#ifdef PNG_SETJMP_SUPPORTED - jmp_buf tmp_jmp; /* to save current jump buffer */ -#endif - - int i=0; - - png_structp png_ptr=*ptr_ptr; - - if(png_ptr == NULL) return; - - do - { - if(user_png_ver[i] != png_libpng_ver[i]) - { -#ifdef PNG_LEGACY_SUPPORTED - png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; -#else - png_ptr->warning_fn=NULL; - png_warning(png_ptr, - "Application uses deprecated png_read_init() and should be recompiled."); - break; -#endif - } - } while (png_libpng_ver[i++]); - - png_debug(1, "in png_read_init_3\n"); - -#ifdef PNG_SETJMP_SUPPORTED - /* save jump buffer and error functions */ - png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof (jmp_buf)); -#endif - - if(png_sizeof(png_struct) > png_struct_size) - { - png_destroy_struct(png_ptr); - *ptr_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); - png_ptr = *ptr_ptr; - } - - /* reset all variables to 0 */ - png_memset(png_ptr, 0, png_sizeof (png_struct)); - -#ifdef PNG_SETJMP_SUPPORTED - /* restore jump buffer */ - png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof (jmp_buf)); -#endif - - /* added at libpng-1.2.6 */ -#ifdef PNG_SET_USER_LIMITS_SUPPORTED - png_ptr->user_width_max=PNG_USER_WIDTH_MAX; - png_ptr->user_height_max=PNG_USER_HEIGHT_MAX; -#endif - - /* initialize zbuf - compression buffer */ - png_ptr->zbuf_size = PNG_ZBUF_SIZE; - png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, - (png_uint_32)png_ptr->zbuf_size); - png_ptr->zstream.zalloc = png_zalloc; - png_ptr->zstream.zfree = png_zfree; - png_ptr->zstream.opaque = (voidpf)png_ptr; - - switch (inflateInit(&png_ptr->zstream)) - { - case Z_OK: /* Do nothing */ break; - case Z_MEM_ERROR: - case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory"); break; - case Z_VERSION_ERROR: png_error(png_ptr, "zlib version"); break; - default: png_error(png_ptr, "Unknown zlib error"); - } - - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - - png_set_read_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL); -} - -#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED -/* Read the information before the actual image data. This has been - * changed in v0.90 to allow reading a file that already has the magic - * bytes read from the stream. You can tell libpng how many bytes have - * been read from the beginning of the stream (up to the maximum of 8) - * via png_set_sig_bytes(), and we will only check the remaining bytes - * here. The application can then have access to the signature bytes we - * read if it is determined that this isn't a valid PNG file. - */ -void PNGAPI -png_read_info(png_structp png_ptr, png_infop info_ptr) -{ - if(png_ptr == NULL) return; - png_debug(1, "in png_read_info\n"); - /* If we haven't checked all of the PNG signature bytes, do so now. */ - if (png_ptr->sig_bytes < 8) - { - png_size_t num_checked = png_ptr->sig_bytes, - num_to_check = 8 - num_checked; - - png_read_data(png_ptr, &(info_ptr->signature[num_checked]), num_to_check); - png_ptr->sig_bytes = 8; - - if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check)) - { - if (num_checked < 4 && - png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) - png_error(png_ptr, "Not a PNG file"); - else - png_error(png_ptr, "PNG file corrupted by ASCII conversion"); - } - if (num_checked < 3) - png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; - } - - for(;;) - { -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_CONST PNG_IHDR; - PNG_CONST PNG_IDAT; - PNG_CONST PNG_IEND; - PNG_CONST PNG_PLTE; -#if defined(PNG_READ_bKGD_SUPPORTED) - PNG_CONST PNG_bKGD; -#endif -#if defined(PNG_READ_cHRM_SUPPORTED) - PNG_CONST PNG_cHRM; -#endif -#if defined(PNG_READ_gAMA_SUPPORTED) - PNG_CONST PNG_gAMA; -#endif -#if defined(PNG_READ_hIST_SUPPORTED) - PNG_CONST PNG_hIST; -#endif -#if defined(PNG_READ_iCCP_SUPPORTED) - PNG_CONST PNG_iCCP; -#endif -#if defined(PNG_READ_iTXt_SUPPORTED) - PNG_CONST PNG_iTXt; -#endif -#if defined(PNG_READ_oFFs_SUPPORTED) - PNG_CONST PNG_oFFs; -#endif -#if defined(PNG_READ_pCAL_SUPPORTED) - PNG_CONST PNG_pCAL; -#endif -#if defined(PNG_READ_pHYs_SUPPORTED) - PNG_CONST PNG_pHYs; -#endif -#if defined(PNG_READ_sBIT_SUPPORTED) - PNG_CONST PNG_sBIT; -#endif -#if defined(PNG_READ_sCAL_SUPPORTED) - PNG_CONST PNG_sCAL; -#endif -#if defined(PNG_READ_sPLT_SUPPORTED) - PNG_CONST PNG_sPLT; -#endif -#if defined(PNG_READ_sRGB_SUPPORTED) - PNG_CONST PNG_sRGB; -#endif -#if defined(PNG_READ_tEXt_SUPPORTED) - PNG_CONST PNG_tEXt; -#endif -#if defined(PNG_READ_tIME_SUPPORTED) - PNG_CONST PNG_tIME; -#endif -#if defined(PNG_READ_tRNS_SUPPORTED) - PNG_CONST PNG_tRNS; -#endif -#if defined(PNG_READ_zTXt_SUPPORTED) - PNG_CONST PNG_zTXt; -#endif -#endif /* PNG_USE_LOCAL_ARRAYS */ - png_byte chunk_length[4]; - png_uint_32 length; - - png_read_data(png_ptr, chunk_length, 4); - length = png_get_uint_31(png_ptr,chunk_length); - - png_reset_crc(png_ptr); - png_crc_read(png_ptr, png_ptr->chunk_name, 4); - - png_debug2(0, "Reading %s chunk, length=%lu.\n", png_ptr->chunk_name, - length); - - /* This should be a binary subdivision search or a hash for - * matching the chunk name rather than a linear search. - */ - if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) - if(png_ptr->mode & PNG_AFTER_IDAT) - png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT; - - if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4)) - png_handle_IHDR(png_ptr, info_ptr, length); - else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4)) - png_handle_IEND(png_ptr, info_ptr, length); -#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED - else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name)) - { - if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) - png_ptr->mode |= PNG_HAVE_IDAT; - png_handle_unknown(png_ptr, info_ptr, length); - if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) - png_ptr->mode |= PNG_HAVE_PLTE; - else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) - { - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before IDAT"); - else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && - !(png_ptr->mode & PNG_HAVE_PLTE)) - png_error(png_ptr, "Missing PLTE before IDAT"); - break; - } - } -#endif - else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) - png_handle_PLTE(png_ptr, info_ptr, length); - else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) - { - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before IDAT"); - else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && - !(png_ptr->mode & PNG_HAVE_PLTE)) - png_error(png_ptr, "Missing PLTE before IDAT"); - - png_ptr->idat_size = length; - png_ptr->mode |= PNG_HAVE_IDAT; - break; - } -#if defined(PNG_READ_bKGD_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4)) - png_handle_bKGD(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_cHRM_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4)) - png_handle_cHRM(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_gAMA_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4)) - png_handle_gAMA(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_hIST_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4)) - png_handle_hIST(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_oFFs_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4)) - png_handle_oFFs(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_pCAL_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4)) - png_handle_pCAL(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_sCAL_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4)) - png_handle_sCAL(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_pHYs_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4)) - png_handle_pHYs(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_sBIT_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4)) - png_handle_sBIT(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_sRGB_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4)) - png_handle_sRGB(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_iCCP_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4)) - png_handle_iCCP(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_sPLT_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4)) - png_handle_sPLT(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_tEXt_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4)) - png_handle_tEXt(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_tIME_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4)) - png_handle_tIME(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_tRNS_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4)) - png_handle_tRNS(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_zTXt_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4)) - png_handle_zTXt(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_iTXt_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4)) - png_handle_iTXt(png_ptr, info_ptr, length); -#endif - else - png_handle_unknown(png_ptr, info_ptr, length); - } -} -#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ - -/* optional call to update the users info_ptr structure */ -void PNGAPI -png_read_update_info(png_structp png_ptr, png_infop info_ptr) -{ - png_debug(1, "in png_read_update_info\n"); - if(png_ptr == NULL) return; - if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) - png_read_start_row(png_ptr); - else - png_warning(png_ptr, - "Ignoring extra png_read_update_info() call; row buffer not reallocated"); - png_read_transform_info(png_ptr, info_ptr); -} - -#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED -/* Initialize palette, background, etc, after transformations - * are set, but before any reading takes place. This allows - * the user to obtain a gamma-corrected palette, for example. - * If the user doesn't call this, we will do it ourselves. - */ -void PNGAPI -png_start_read_image(png_structp png_ptr) -{ - png_debug(1, "in png_start_read_image\n"); - if(png_ptr == NULL) return; - if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) - png_read_start_row(png_ptr); -} -#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ - -#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED -void PNGAPI -png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_CONST PNG_IDAT; - PNG_CONST int png_pass_dsp_mask[7] = {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, - 0xff}; - PNG_CONST int png_pass_mask[7] = {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff}; -#endif - int ret; - if(png_ptr == NULL) return; - png_debug2(1, "in png_read_row (row %lu, pass %d)\n", - png_ptr->row_number, png_ptr->pass); - if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) - png_read_start_row(png_ptr); - if (png_ptr->row_number == 0 && png_ptr->pass == 0) - { - /* check for transforms that have been set but were defined out */ -#if defined(PNG_WRITE_INVERT_SUPPORTED) && !defined(PNG_READ_INVERT_SUPPORTED) - if (png_ptr->transformations & PNG_INVERT_MONO) - png_warning(png_ptr, "PNG_READ_INVERT_SUPPORTED is not defined."); -#endif -#if defined(PNG_WRITE_FILLER_SUPPORTED) && !defined(PNG_READ_FILLER_SUPPORTED) - if (png_ptr->transformations & PNG_FILLER) - png_warning(png_ptr, "PNG_READ_FILLER_SUPPORTED is not defined."); -#endif -#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) && !defined(PNG_READ_PACKSWAP_SUPPORTED) - if (png_ptr->transformations & PNG_PACKSWAP) - png_warning(png_ptr, "PNG_READ_PACKSWAP_SUPPORTED is not defined."); -#endif -#if defined(PNG_WRITE_PACK_SUPPORTED) && !defined(PNG_READ_PACK_SUPPORTED) - if (png_ptr->transformations & PNG_PACK) - png_warning(png_ptr, "PNG_READ_PACK_SUPPORTED is not defined."); -#endif -#if defined(PNG_WRITE_SHIFT_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) - if (png_ptr->transformations & PNG_SHIFT) - png_warning(png_ptr, "PNG_READ_SHIFT_SUPPORTED is not defined."); -#endif -#if defined(PNG_WRITE_BGR_SUPPORTED) && !defined(PNG_READ_BGR_SUPPORTED) - if (png_ptr->transformations & PNG_BGR) - png_warning(png_ptr, "PNG_READ_BGR_SUPPORTED is not defined."); -#endif -#if defined(PNG_WRITE_SWAP_SUPPORTED) && !defined(PNG_READ_SWAP_SUPPORTED) - if (png_ptr->transformations & PNG_SWAP_BYTES) - png_warning(png_ptr, "PNG_READ_SWAP_SUPPORTED is not defined."); -#endif - } - -#if defined(PNG_READ_INTERLACING_SUPPORTED) - /* if interlaced and we do not need a new row, combine row and return */ - if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) - { - switch (png_ptr->pass) - { - case 0: - if (png_ptr->row_number & 0x07) - { - if (dsp_row != NULL) - png_combine_row(png_ptr, dsp_row, - png_pass_dsp_mask[png_ptr->pass]); - png_read_finish_row(png_ptr); - return; - } - break; - case 1: - if ((png_ptr->row_number & 0x07) || png_ptr->width < 5) - { - if (dsp_row != NULL) - png_combine_row(png_ptr, dsp_row, - png_pass_dsp_mask[png_ptr->pass]); - png_read_finish_row(png_ptr); - return; - } - break; - case 2: - if ((png_ptr->row_number & 0x07) != 4) - { - if (dsp_row != NULL && (png_ptr->row_number & 4)) - png_combine_row(png_ptr, dsp_row, - png_pass_dsp_mask[png_ptr->pass]); - png_read_finish_row(png_ptr); - return; - } - break; - case 3: - if ((png_ptr->row_number & 3) || png_ptr->width < 3) - { - if (dsp_row != NULL) - png_combine_row(png_ptr, dsp_row, - png_pass_dsp_mask[png_ptr->pass]); - png_read_finish_row(png_ptr); - return; - } - break; - case 4: - if ((png_ptr->row_number & 3) != 2) - { - if (dsp_row != NULL && (png_ptr->row_number & 2)) - png_combine_row(png_ptr, dsp_row, - png_pass_dsp_mask[png_ptr->pass]); - png_read_finish_row(png_ptr); - return; - } - break; - case 5: - if ((png_ptr->row_number & 1) || png_ptr->width < 2) - { - if (dsp_row != NULL) - png_combine_row(png_ptr, dsp_row, - png_pass_dsp_mask[png_ptr->pass]); - png_read_finish_row(png_ptr); - return; - } - break; - case 6: - if (!(png_ptr->row_number & 1)) - { - png_read_finish_row(png_ptr); - return; - } - break; - } - } -#endif - - if (!(png_ptr->mode & PNG_HAVE_IDAT)) - png_error(png_ptr, "Invalid attempt to read row data"); - - png_ptr->zstream.next_out = png_ptr->row_buf; - png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes; - do - { - if (!(png_ptr->zstream.avail_in)) - { - while (!png_ptr->idat_size) - { - png_byte chunk_length[4]; - - png_crc_finish(png_ptr, 0); - - png_read_data(png_ptr, chunk_length, 4); - png_ptr->idat_size = png_get_uint_31(png_ptr,chunk_length); - - png_reset_crc(png_ptr); - png_crc_read(png_ptr, png_ptr->chunk_name, 4); - if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) - png_error(png_ptr, "Not enough image data"); - } - png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size; - png_ptr->zstream.next_in = png_ptr->zbuf; - if (png_ptr->zbuf_size > png_ptr->idat_size) - png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size; - png_crc_read(png_ptr, png_ptr->zbuf, - (png_size_t)png_ptr->zstream.avail_in); - png_ptr->idat_size -= png_ptr->zstream.avail_in; - } - ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); - if (ret == Z_STREAM_END) - { - if (png_ptr->zstream.avail_out || png_ptr->zstream.avail_in || - png_ptr->idat_size) - png_error(png_ptr, "Extra compressed data"); - png_ptr->mode |= PNG_AFTER_IDAT; - png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; - break; - } - if (ret != Z_OK) - png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg : - "Decompression error"); - - } while (png_ptr->zstream.avail_out); - - png_ptr->row_info.color_type = png_ptr->color_type; - png_ptr->row_info.width = png_ptr->iwidth; - png_ptr->row_info.channels = png_ptr->channels; - png_ptr->row_info.bit_depth = png_ptr->bit_depth; - png_ptr->row_info.pixel_depth = png_ptr->pixel_depth; - png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, - png_ptr->row_info.width); - - if(png_ptr->row_buf[0]) - png_read_filter_row(png_ptr, &(png_ptr->row_info), - png_ptr->row_buf + 1, png_ptr->prev_row + 1, - (int)(png_ptr->row_buf[0])); - - png_memcpy_check(png_ptr, png_ptr->prev_row, png_ptr->row_buf, - png_ptr->rowbytes + 1); - -#if defined(PNG_MNG_FEATURES_SUPPORTED) - if((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && - (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING)) - { - /* Intrapixel differencing */ - png_do_read_intrapixel(&(png_ptr->row_info), png_ptr->row_buf + 1); - } -#endif - - - if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA)) - png_do_read_transformations(png_ptr); - -#if defined(PNG_READ_INTERLACING_SUPPORTED) - /* blow up interlaced rows to full size */ - if (png_ptr->interlaced && - (png_ptr->transformations & PNG_INTERLACE)) - { - if (png_ptr->pass < 6) -/* old interface (pre-1.0.9): - png_do_read_interlace(&(png_ptr->row_info), - png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations); - */ - png_do_read_interlace(png_ptr); - - if (dsp_row != NULL) - png_combine_row(png_ptr, dsp_row, - png_pass_dsp_mask[png_ptr->pass]); - if (row != NULL) - png_combine_row(png_ptr, row, - png_pass_mask[png_ptr->pass]); - } - else -#endif - { - if (row != NULL) - png_combine_row(png_ptr, row, 0xff); - if (dsp_row != NULL) - png_combine_row(png_ptr, dsp_row, 0xff); - } - png_read_finish_row(png_ptr); - - if (png_ptr->read_row_fn != NULL) - (*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass); -} -#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ - -#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED -/* Read one or more rows of image data. If the image is interlaced, - * and png_set_interlace_handling() has been called, the rows need to - * contain the contents of the rows from the previous pass. If the - * image has alpha or transparency, and png_handle_alpha()[*] has been - * called, the rows contents must be initialized to the contents of the - * screen. - * - * "row" holds the actual image, and pixels are placed in it - * as they arrive. If the image is displayed after each pass, it will - * appear to "sparkle" in. "display_row" can be used to display a - * "chunky" progressive image, with finer detail added as it becomes - * available. If you do not want this "chunky" display, you may pass - * NULL for display_row. If you do not want the sparkle display, and - * you have not called png_handle_alpha(), you may pass NULL for rows. - * If you have called png_handle_alpha(), and the image has either an - * alpha channel or a transparency chunk, you must provide a buffer for - * rows. In this case, you do not have to provide a display_row buffer - * also, but you may. If the image is not interlaced, or if you have - * not called png_set_interlace_handling(), the display_row buffer will - * be ignored, so pass NULL to it. - * - * [*] png_handle_alpha() does not exist yet, as of this version of libpng - */ - -void PNGAPI -png_read_rows(png_structp png_ptr, png_bytepp row, - png_bytepp display_row, png_uint_32 num_rows) -{ - png_uint_32 i; - png_bytepp rp; - png_bytepp dp; - - png_debug(1, "in png_read_rows\n"); - if(png_ptr == NULL) return; - rp = row; - dp = display_row; - if (rp != NULL && dp != NULL) - for (i = 0; i < num_rows; i++) - { - png_bytep rptr = *rp++; - png_bytep dptr = *dp++; - - png_read_row(png_ptr, rptr, dptr); - } - else if(rp != NULL) - for (i = 0; i < num_rows; i++) - { - png_bytep rptr = *rp; - png_read_row(png_ptr, rptr, png_bytep_NULL); - rp++; - } - else if(dp != NULL) - for (i = 0; i < num_rows; i++) - { - png_bytep dptr = *dp; - png_read_row(png_ptr, png_bytep_NULL, dptr); - dp++; - } -} -#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ - -#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED -/* Read the entire image. If the image has an alpha channel or a tRNS - * chunk, and you have called png_handle_alpha()[*], you will need to - * initialize the image to the current image that PNG will be overlaying. - * We set the num_rows again here, in case it was incorrectly set in - * png_read_start_row() by a call to png_read_update_info() or - * png_start_read_image() if png_set_interlace_handling() wasn't called - * prior to either of these functions like it should have been. You can - * only call this function once. If you desire to have an image for - * each pass of a interlaced image, use png_read_rows() instead. - * - * [*] png_handle_alpha() does not exist yet, as of this version of libpng - */ -void PNGAPI -png_read_image(png_structp png_ptr, png_bytepp image) -{ - png_uint_32 i,image_height; - int pass, j; - png_bytepp rp; - - png_debug(1, "in png_read_image\n"); - if(png_ptr == NULL) return; - -#ifdef PNG_READ_INTERLACING_SUPPORTED - pass = png_set_interlace_handling(png_ptr); -#else - if (png_ptr->interlaced) - png_error(png_ptr, - "Cannot read interlaced image -- interlace handler disabled."); - pass = 1; -#endif - - - image_height=png_ptr->height; - png_ptr->num_rows = image_height; /* Make sure this is set correctly */ - - for (j = 0; j < pass; j++) - { - rp = image; - for (i = 0; i < image_height; i++) - { - png_read_row(png_ptr, *rp, png_bytep_NULL); - rp++; - } - } -} -#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ - -#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED -/* Read the end of the PNG file. Will not read past the end of the - * file, will verify the end is accurate, and will read any comments - * or time information at the end of the file, if info is not NULL. - */ -void PNGAPI -png_read_end(png_structp png_ptr, png_infop info_ptr) -{ - png_byte chunk_length[4]; - png_uint_32 length; - - png_debug(1, "in png_read_end\n"); - if(png_ptr == NULL) return; - png_crc_finish(png_ptr, 0); /* Finish off CRC from last IDAT chunk */ - - do - { -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_CONST PNG_IHDR; - PNG_CONST PNG_IDAT; - PNG_CONST PNG_IEND; - PNG_CONST PNG_PLTE; -#if defined(PNG_READ_bKGD_SUPPORTED) - PNG_CONST PNG_bKGD; -#endif -#if defined(PNG_READ_cHRM_SUPPORTED) - PNG_CONST PNG_cHRM; -#endif -#if defined(PNG_READ_gAMA_SUPPORTED) - PNG_CONST PNG_gAMA; -#endif -#if defined(PNG_READ_hIST_SUPPORTED) - PNG_CONST PNG_hIST; -#endif -#if defined(PNG_READ_iCCP_SUPPORTED) - PNG_CONST PNG_iCCP; -#endif -#if defined(PNG_READ_iTXt_SUPPORTED) - PNG_CONST PNG_iTXt; -#endif -#if defined(PNG_READ_oFFs_SUPPORTED) - PNG_CONST PNG_oFFs; -#endif -#if defined(PNG_READ_pCAL_SUPPORTED) - PNG_CONST PNG_pCAL; -#endif -#if defined(PNG_READ_pHYs_SUPPORTED) - PNG_CONST PNG_pHYs; -#endif -#if defined(PNG_READ_sBIT_SUPPORTED) - PNG_CONST PNG_sBIT; -#endif -#if defined(PNG_READ_sCAL_SUPPORTED) - PNG_CONST PNG_sCAL; -#endif -#if defined(PNG_READ_sPLT_SUPPORTED) - PNG_CONST PNG_sPLT; -#endif -#if defined(PNG_READ_sRGB_SUPPORTED) - PNG_CONST PNG_sRGB; -#endif -#if defined(PNG_READ_tEXt_SUPPORTED) - PNG_CONST PNG_tEXt; -#endif -#if defined(PNG_READ_tIME_SUPPORTED) - PNG_CONST PNG_tIME; -#endif -#if defined(PNG_READ_tRNS_SUPPORTED) - PNG_CONST PNG_tRNS; -#endif -#if defined(PNG_READ_zTXt_SUPPORTED) - PNG_CONST PNG_zTXt; -#endif -#endif /* PNG_USE_LOCAL_ARRAYS */ - - png_read_data(png_ptr, chunk_length, 4); - length = png_get_uint_31(png_ptr,chunk_length); - - png_reset_crc(png_ptr); - png_crc_read(png_ptr, png_ptr->chunk_name, 4); - - png_debug1(0, "Reading %s chunk.\n", png_ptr->chunk_name); - - if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4)) - png_handle_IHDR(png_ptr, info_ptr, length); - else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4)) - png_handle_IEND(png_ptr, info_ptr, length); -#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED - else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name)) - { - if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) - { - if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) - png_error(png_ptr, "Too many IDAT's found"); - } - png_handle_unknown(png_ptr, info_ptr, length); - if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) - png_ptr->mode |= PNG_HAVE_PLTE; - } -#endif - else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) - { - /* Zero length IDATs are legal after the last IDAT has been - * read, but not after other chunks have been read. - */ - if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) - png_error(png_ptr, "Too many IDAT's found"); - png_crc_finish(png_ptr, length); - } - else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) - png_handle_PLTE(png_ptr, info_ptr, length); -#if defined(PNG_READ_bKGD_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4)) - png_handle_bKGD(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_cHRM_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4)) - png_handle_cHRM(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_gAMA_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4)) - png_handle_gAMA(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_hIST_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4)) - png_handle_hIST(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_oFFs_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4)) - png_handle_oFFs(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_pCAL_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4)) - png_handle_pCAL(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_sCAL_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4)) - png_handle_sCAL(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_pHYs_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4)) - png_handle_pHYs(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_sBIT_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4)) - png_handle_sBIT(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_sRGB_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4)) - png_handle_sRGB(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_iCCP_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4)) - png_handle_iCCP(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_sPLT_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4)) - png_handle_sPLT(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_tEXt_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4)) - png_handle_tEXt(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_tIME_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4)) - png_handle_tIME(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_tRNS_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4)) - png_handle_tRNS(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_zTXt_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4)) - png_handle_zTXt(png_ptr, info_ptr, length); -#endif -#if defined(PNG_READ_iTXt_SUPPORTED) - else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4)) - png_handle_iTXt(png_ptr, info_ptr, length); -#endif - else - png_handle_unknown(png_ptr, info_ptr, length); - } while (!(png_ptr->mode & PNG_HAVE_IEND)); -} -#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ - -/* free all memory used by the read */ -void PNGAPI -png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr, - png_infopp end_info_ptr_ptr) -{ - png_structp png_ptr = NULL; - png_infop info_ptr = NULL, end_info_ptr = NULL; -#ifdef PNG_USER_MEM_SUPPORTED - png_free_ptr free_fn = NULL; - png_voidp mem_ptr = NULL; -#endif - - png_debug(1, "in png_destroy_read_struct\n"); - if (png_ptr_ptr != NULL) - { - png_ptr = *png_ptr_ptr; -#ifdef PNG_USER_MEM_SUPPORTED - free_fn = png_ptr->free_fn; - mem_ptr = png_ptr->mem_ptr; -#endif - } - - if (info_ptr_ptr != NULL) - info_ptr = *info_ptr_ptr; - - if (end_info_ptr_ptr != NULL) - end_info_ptr = *end_info_ptr_ptr; - - png_read_destroy(png_ptr, info_ptr, end_info_ptr); - - if (info_ptr != NULL) - { -#if defined(PNG_TEXT_SUPPORTED) - png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, -1); -#endif - -#ifdef PNG_USER_MEM_SUPPORTED - png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn, - (png_voidp)mem_ptr); -#else - png_destroy_struct((png_voidp)info_ptr); -#endif - *info_ptr_ptr = NULL; - } - - if (end_info_ptr != NULL) - { -#if defined(PNG_READ_TEXT_SUPPORTED) - png_free_data(png_ptr, end_info_ptr, PNG_FREE_TEXT, -1); -#endif -#ifdef PNG_USER_MEM_SUPPORTED - png_destroy_struct_2((png_voidp)end_info_ptr, (png_free_ptr)free_fn, - (png_voidp)mem_ptr); -#else - png_destroy_struct((png_voidp)end_info_ptr); -#endif - *end_info_ptr_ptr = NULL; - } - - if (png_ptr != NULL) - { -#ifdef PNG_USER_MEM_SUPPORTED - png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn, - (png_voidp)mem_ptr); -#else - png_destroy_struct((png_voidp)png_ptr); -#endif - *png_ptr_ptr = NULL; - } -} - -/* free all memory used by the read (old method) */ -void /* PRIVATE */ -png_read_destroy(png_structp png_ptr, png_infop info_ptr, png_infop end_info_ptr) -{ -#ifdef PNG_SETJMP_SUPPORTED - jmp_buf tmp_jmp; -#endif - png_error_ptr error_fn; - png_error_ptr warning_fn; - png_voidp error_ptr; -#ifdef PNG_USER_MEM_SUPPORTED - png_free_ptr free_fn; -#endif - - png_debug(1, "in png_read_destroy\n"); - if (info_ptr != NULL) - png_info_destroy(png_ptr, info_ptr); - - if (end_info_ptr != NULL) - png_info_destroy(png_ptr, end_info_ptr); - - png_free(png_ptr, png_ptr->zbuf); - png_free(png_ptr, png_ptr->big_row_buf); - png_free(png_ptr, png_ptr->prev_row); -#if defined(PNG_READ_DITHER_SUPPORTED) - png_free(png_ptr, png_ptr->palette_lookup); - png_free(png_ptr, png_ptr->dither_index); -#endif -#if defined(PNG_READ_GAMMA_SUPPORTED) - png_free(png_ptr, png_ptr->gamma_table); -#endif -#if defined(PNG_READ_BACKGROUND_SUPPORTED) - png_free(png_ptr, png_ptr->gamma_from_1); - png_free(png_ptr, png_ptr->gamma_to_1); -#endif -#ifdef PNG_FREE_ME_SUPPORTED - if (png_ptr->free_me & PNG_FREE_PLTE) - png_zfree(png_ptr, png_ptr->palette); - png_ptr->free_me &= ~PNG_FREE_PLTE; -#else - if (png_ptr->flags & PNG_FLAG_FREE_PLTE) - png_zfree(png_ptr, png_ptr->palette); - png_ptr->flags &= ~PNG_FLAG_FREE_PLTE; -#endif -#if defined(PNG_tRNS_SUPPORTED) || \ - defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) -#ifdef PNG_FREE_ME_SUPPORTED - if (png_ptr->free_me & PNG_FREE_TRNS) - png_free(png_ptr, png_ptr->trans); - png_ptr->free_me &= ~PNG_FREE_TRNS; -#else - if (png_ptr->flags & PNG_FLAG_FREE_TRNS) - png_free(png_ptr, png_ptr->trans); - png_ptr->flags &= ~PNG_FLAG_FREE_TRNS; -#endif -#endif -#if defined(PNG_READ_hIST_SUPPORTED) -#ifdef PNG_FREE_ME_SUPPORTED - if (png_ptr->free_me & PNG_FREE_HIST) - png_free(png_ptr, png_ptr->hist); - png_ptr->free_me &= ~PNG_FREE_HIST; -#else - if (png_ptr->flags & PNG_FLAG_FREE_HIST) - png_free(png_ptr, png_ptr->hist); - png_ptr->flags &= ~PNG_FLAG_FREE_HIST; -#endif -#endif -#if defined(PNG_READ_GAMMA_SUPPORTED) - if (png_ptr->gamma_16_table != NULL) - { - int i; - int istop = (1 << (8 - png_ptr->gamma_shift)); - for (i = 0; i < istop; i++) - { - png_free(png_ptr, png_ptr->gamma_16_table[i]); - } - png_free(png_ptr, png_ptr->gamma_16_table); - } -#if defined(PNG_READ_BACKGROUND_SUPPORTED) - if (png_ptr->gamma_16_from_1 != NULL) - { - int i; - int istop = (1 << (8 - png_ptr->gamma_shift)); - for (i = 0; i < istop; i++) - { - png_free(png_ptr, png_ptr->gamma_16_from_1[i]); - } - png_free(png_ptr, png_ptr->gamma_16_from_1); - } - if (png_ptr->gamma_16_to_1 != NULL) - { - int i; - int istop = (1 << (8 - png_ptr->gamma_shift)); - for (i = 0; i < istop; i++) - { - png_free(png_ptr, png_ptr->gamma_16_to_1[i]); - } - png_free(png_ptr, png_ptr->gamma_16_to_1); - } -#endif -#endif -#if defined(PNG_TIME_RFC1123_SUPPORTED) - png_free(png_ptr, png_ptr->time_buffer); -#endif - - inflateEnd(&png_ptr->zstream); -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED - png_free(png_ptr, png_ptr->save_buffer); -#endif - -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED -#ifdef PNG_TEXT_SUPPORTED - png_free(png_ptr, png_ptr->current_text); -#endif /* PNG_TEXT_SUPPORTED */ -#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ - - /* Save the important info out of the png_struct, in case it is - * being used again. - */ -#ifdef PNG_SETJMP_SUPPORTED - png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof (jmp_buf)); -#endif - - error_fn = png_ptr->error_fn; - warning_fn = png_ptr->warning_fn; - error_ptr = png_ptr->error_ptr; -#ifdef PNG_USER_MEM_SUPPORTED - free_fn = png_ptr->free_fn; -#endif - - png_memset(png_ptr, 0, png_sizeof (png_struct)); - - png_ptr->error_fn = error_fn; - png_ptr->warning_fn = warning_fn; - png_ptr->error_ptr = error_ptr; -#ifdef PNG_USER_MEM_SUPPORTED - png_ptr->free_fn = free_fn; -#endif - -#ifdef PNG_SETJMP_SUPPORTED - png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof (jmp_buf)); -#endif - -} - -void PNGAPI -png_set_read_status_fn(png_structp png_ptr, png_read_status_ptr read_row_fn) -{ - if(png_ptr == NULL) return; - png_ptr->read_row_fn = read_row_fn; -} - - -#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED -#if defined(PNG_INFO_IMAGE_SUPPORTED) -void PNGAPI -png_read_png(png_structp png_ptr, png_infop info_ptr, - int transforms, - voidp params) -{ - int row; - - if(png_ptr == NULL) return; -#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) - /* invert the alpha channel from opacity to transparency - */ - if (transforms & PNG_TRANSFORM_INVERT_ALPHA) - png_set_invert_alpha(png_ptr); -#endif - - /* png_read_info() gives us all of the information from the - * PNG file before the first IDAT (image data chunk). - */ - png_read_info(png_ptr, info_ptr); - if (info_ptr->height > PNG_UINT_32_MAX/png_sizeof(png_bytep)) - png_error(png_ptr,"Image is too high to process with png_read_png()"); - - /* -------------- image transformations start here ------------------- */ - -#if defined(PNG_READ_16_TO_8_SUPPORTED) - /* tell libpng to strip 16 bit/color files down to 8 bits per color - */ - if (transforms & PNG_TRANSFORM_STRIP_16) - png_set_strip_16(png_ptr); -#endif - -#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) - /* Strip alpha bytes from the input data without combining with - * the background (not recommended). - */ - if (transforms & PNG_TRANSFORM_STRIP_ALPHA) - png_set_strip_alpha(png_ptr); -#endif - -#if defined(PNG_READ_PACK_SUPPORTED) && !defined(PNG_READ_EXPAND_SUPPORTED) - /* Extract multiple pixels with bit depths of 1, 2, or 4 from a single - * byte into separate bytes (useful for paletted and grayscale images). - */ - if (transforms & PNG_TRANSFORM_PACKING) - png_set_packing(png_ptr); -#endif - -#if defined(PNG_READ_PACKSWAP_SUPPORTED) - /* Change the order of packed pixels to least significant bit first - * (not useful if you are using png_set_packing). - */ - if (transforms & PNG_TRANSFORM_PACKSWAP) - png_set_packswap(png_ptr); -#endif - -#if defined(PNG_READ_EXPAND_SUPPORTED) - /* Expand paletted colors into true RGB triplets - * Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel - * Expand paletted or RGB images with transparency to full alpha - * channels so the data will be available as RGBA quartets. - */ - if (transforms & PNG_TRANSFORM_EXPAND) - if ((png_ptr->bit_depth < 8) || - (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) || - (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))) - png_set_expand(png_ptr); -#endif - - /* We don't handle background color or gamma transformation or dithering. - */ - -#if defined(PNG_READ_INVERT_SUPPORTED) - /* invert monochrome files to have 0 as white and 1 as black - */ - if (transforms & PNG_TRANSFORM_INVERT_MONO) - png_set_invert_mono(png_ptr); -#endif - -#if defined(PNG_READ_SHIFT_SUPPORTED) - /* If you want to shift the pixel values from the range [0,255] or - * [0,65535] to the original [0,7] or [0,31], or whatever range the - * colors were originally in: - */ - if ((transforms & PNG_TRANSFORM_SHIFT) - && png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT)) - { - png_color_8p sig_bit; - - png_get_sBIT(png_ptr, info_ptr, &sig_bit); - png_set_shift(png_ptr, sig_bit); - } -#endif - -#if defined(PNG_READ_BGR_SUPPORTED) - /* flip the RGB pixels to BGR (or RGBA to BGRA) - */ - if (transforms & PNG_TRANSFORM_BGR) - png_set_bgr(png_ptr); -#endif - -#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) - /* swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) - */ - if (transforms & PNG_TRANSFORM_SWAP_ALPHA) - png_set_swap_alpha(png_ptr); -#endif - -#if defined(PNG_READ_SWAP_SUPPORTED) - /* swap bytes of 16 bit files to least significant byte first - */ - if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) - png_set_swap(png_ptr); -#endif - - /* We don't handle adding filler bytes */ - - /* Optional call to gamma correct and add the background to the palette - * and update info structure. REQUIRED if you are expecting libpng to - * update the palette for you (i.e., you selected such a transform above). - */ - png_read_update_info(png_ptr, info_ptr); - - /* -------------- image transformations end here ------------------- */ - -#ifdef PNG_FREE_ME_SUPPORTED - png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); -#endif - if(info_ptr->row_pointers == NULL) - { - info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr, - info_ptr->height * png_sizeof(png_bytep)); -#ifdef PNG_FREE_ME_SUPPORTED - info_ptr->free_me |= PNG_FREE_ROWS; -#endif - for (row = 0; row < (int)info_ptr->height; row++) - { - info_ptr->row_pointers[row] = (png_bytep)png_malloc(png_ptr, - png_get_rowbytes(png_ptr, info_ptr)); - } - } - - png_read_image(png_ptr, info_ptr->row_pointers); - info_ptr->valid |= PNG_INFO_IDAT; - - /* read rest of file, and get additional chunks in info_ptr - REQUIRED */ - png_read_end(png_ptr, info_ptr); - - transforms = transforms; /* quiet compiler warnings */ - params = params; - -} -#endif /* PNG_INFO_IMAGE_SUPPORTED */ -#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */ -#endif /* PNG_READ_SUPPORTED */ diff --git a/rosapps/lib/libpng/pngrio.c b/rosapps/lib/libpng/pngrio.c deleted file mode 100644 index 7d2522f1f86..00000000000 --- a/rosapps/lib/libpng/pngrio.c +++ /dev/null @@ -1,167 +0,0 @@ - -/* pngrio.c - functions for data input - * - * Last changed in libpng 1.2.13 November 13, 2006 - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2006 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This file provides a location for all input. Users who need - * special handling are expected to write a function that has the same - * arguments as this and performs a similar function, but that possibly - * has a different input method. Note that you shouldn't change this - * function, but rather write a replacement function and then make - * libpng use it at run time with png_set_read_fn(...). - */ - -#define PNG_INTERNAL -#include "png.h" - -#if defined(PNG_READ_SUPPORTED) - -/* Read the data from whatever input you are using. The default routine - reads from a file pointer. Note that this routine sometimes gets called - with very small lengths, so you should implement some kind of simple - buffering if you are using unbuffered reads. This should never be asked - to read more then 64K on a 16 bit machine. */ -void /* PRIVATE */ -png_read_data(png_structp png_ptr, png_bytep data, png_size_t length) -{ - png_debug1(4,"reading %d bytes\n", (int)length); - if (png_ptr->read_data_fn != NULL) - (*(png_ptr->read_data_fn))(png_ptr, data, length); - else - png_error(png_ptr, "Call to NULL read function"); -} - -#if !defined(PNG_NO_STDIO) -/* This is the function that does the actual reading of data. If you are - not reading from a standard C stream, you should create a replacement - read_data function and use it at run time with png_set_read_fn(), rather - than changing the library. */ -#ifndef USE_FAR_KEYWORD -void PNGAPI -png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) -{ - png_size_t check; - - if(png_ptr == NULL) return; - /* fread() returns 0 on error, so it is OK to store this in a png_size_t - * instead of an int, which is what fread() actually returns. - */ -#if defined(_WIN32_WCE) - if ( !ReadFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) ) - check = 0; -#else - check = (png_size_t)fread(data, (png_size_t)1, length, - (png_FILE_p)png_ptr->io_ptr); -#endif - - if (check != length) - png_error(png_ptr, "Read Error"); -} -#else -/* this is the model-independent version. Since the standard I/O library - can't handle far buffers in the medium and small models, we have to copy - the data. -*/ - -#define NEAR_BUF_SIZE 1024 -#define MIN(a,b) (a <= b ? a : b) - -static void PNGAPI -png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) -{ - int check; - png_byte *n_data; - png_FILE_p io_ptr; - - if(png_ptr == NULL) return; - /* Check if data really is near. If so, use usual code. */ - n_data = (png_byte *)CVT_PTR_NOCHECK(data); - io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); - if ((png_bytep)n_data == data) - { -#if defined(_WIN32_WCE) - if ( !ReadFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) ) - check = 0; -#else - check = fread(n_data, 1, length, io_ptr); -#endif - } - else - { - png_byte buf[NEAR_BUF_SIZE]; - png_size_t read, remaining, err; - check = 0; - remaining = length; - do - { - read = MIN(NEAR_BUF_SIZE, remaining); -#if defined(_WIN32_WCE) - if ( !ReadFile((HANDLE)(io_ptr), buf, read, &err, NULL) ) - err = 0; -#else - err = fread(buf, (png_size_t)1, read, io_ptr); -#endif - png_memcpy(data, buf, read); /* copy far buffer to near buffer */ - if(err != read) - break; - else - check += err; - data += read; - remaining -= read; - } - while (remaining != 0); - } - if ((png_uint_32)check != (png_uint_32)length) - png_error(png_ptr, "read Error"); -} -#endif -#endif - -/* This function allows the application to supply a new input function - for libpng if standard C streams aren't being used. - - This function takes as its arguments: - png_ptr - pointer to a png input data structure - io_ptr - pointer to user supplied structure containing info about - the input functions. May be NULL. - read_data_fn - pointer to a new input function that takes as its - arguments a pointer to a png_struct, a pointer to - a location where input data can be stored, and a 32-bit - unsigned int that is the number of bytes to be read. - To exit and output any fatal error messages the new write - function should call png_error(png_ptr, "Error msg"). */ -void PNGAPI -png_set_read_fn(png_structp png_ptr, png_voidp io_ptr, - png_rw_ptr read_data_fn) -{ - if(png_ptr == NULL) return; - png_ptr->io_ptr = io_ptr; - -#if !defined(PNG_NO_STDIO) - if (read_data_fn != NULL) - png_ptr->read_data_fn = read_data_fn; - else - png_ptr->read_data_fn = png_default_read_data; -#else - png_ptr->read_data_fn = read_data_fn; -#endif - - /* It is an error to write to a read device */ - if (png_ptr->write_data_fn != NULL) - { - png_ptr->write_data_fn = NULL; - png_warning(png_ptr, - "It's an error to set both read_data_fn and write_data_fn in the "); - png_warning(png_ptr, - "same structure. Resetting write_data_fn to NULL."); - } - -#if defined(PNG_WRITE_FLUSH_SUPPORTED) - png_ptr->output_flush_fn = NULL; -#endif -} -#endif /* PNG_READ_SUPPORTED */ diff --git a/rosapps/lib/libpng/pngrtran.c b/rosapps/lib/libpng/pngrtran.c deleted file mode 100644 index cda392154e5..00000000000 --- a/rosapps/lib/libpng/pngrtran.c +++ /dev/null @@ -1,4284 +0,0 @@ - -/* pngrtran.c - transforms the data in a row for PNG readers - * - * Last changed in libpng 1.2.22 [October 13, 2007] - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2007 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This file contains functions optionally called by an application - * in order to tell libpng how to handle data when reading a PNG. - * Transformations that are used in both reading and writing are - * in pngtrans.c. - */ - -#define PNG_INTERNAL -#include "png.h" - -#if defined(PNG_READ_SUPPORTED) - -/* Set the action on getting a CRC error for an ancillary or critical chunk. */ -void PNGAPI -png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action) -{ - png_debug(1, "in png_set_crc_action\n"); - /* Tell libpng how we react to CRC errors in critical chunks */ - if(png_ptr == NULL) return; - switch (crit_action) - { - case PNG_CRC_NO_CHANGE: /* leave setting as is */ - break; - case PNG_CRC_WARN_USE: /* warn/use data */ - png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; - png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE; - break; - case PNG_CRC_QUIET_USE: /* quiet/use data */ - png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; - png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE | - PNG_FLAG_CRC_CRITICAL_IGNORE; - break; - case PNG_CRC_WARN_DISCARD: /* not a valid action for critical data */ - png_warning(png_ptr, "Can't discard critical data on CRC error."); - case PNG_CRC_ERROR_QUIT: /* error/quit */ - case PNG_CRC_DEFAULT: - default: - png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; - break; - } - - switch (ancil_action) - { - case PNG_CRC_NO_CHANGE: /* leave setting as is */ - break; - case PNG_CRC_WARN_USE: /* warn/use data */ - png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; - png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE; - break; - case PNG_CRC_QUIET_USE: /* quiet/use data */ - png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; - png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE | - PNG_FLAG_CRC_ANCILLARY_NOWARN; - break; - case PNG_CRC_ERROR_QUIT: /* error/quit */ - png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; - png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN; - break; - case PNG_CRC_WARN_DISCARD: /* warn/discard data */ - case PNG_CRC_DEFAULT: - default: - png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; - break; - } -} - -#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ - defined(PNG_FLOATING_POINT_SUPPORTED) -/* handle alpha and tRNS via a background color */ -void PNGAPI -png_set_background(png_structp png_ptr, - png_color_16p background_color, int background_gamma_code, - int need_expand, double background_gamma) -{ - png_debug(1, "in png_set_background\n"); - if(png_ptr == NULL) return; - if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN) - { - png_warning(png_ptr, "Application must supply a known background gamma"); - return; - } - - png_ptr->transformations |= PNG_BACKGROUND; - png_memcpy(&(png_ptr->background), background_color, - png_sizeof(png_color_16)); - png_ptr->background_gamma = (float)background_gamma; - png_ptr->background_gamma_type = (png_byte)(background_gamma_code); - png_ptr->transformations |= (need_expand ? PNG_BACKGROUND_EXPAND : 0); -} -#endif - -#if defined(PNG_READ_16_TO_8_SUPPORTED) -/* strip 16 bit depth files to 8 bit depth */ -void PNGAPI -png_set_strip_16(png_structp png_ptr) -{ - png_debug(1, "in png_set_strip_16\n"); - if(png_ptr == NULL) return; - png_ptr->transformations |= PNG_16_TO_8; -} -#endif - -#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) -void PNGAPI -png_set_strip_alpha(png_structp png_ptr) -{ - png_debug(1, "in png_set_strip_alpha\n"); - if(png_ptr == NULL) return; - png_ptr->flags |= PNG_FLAG_STRIP_ALPHA; -} -#endif - -#if defined(PNG_READ_DITHER_SUPPORTED) -/* Dither file to 8 bit. Supply a palette, the current number - * of elements in the palette, the maximum number of elements - * allowed, and a histogram if possible. If the current number - * of colors is greater then the maximum number, the palette will be - * modified to fit in the maximum number. "full_dither" indicates - * whether we need a dithering cube set up for RGB images, or if we - * simply are reducing the number of colors in a paletted image. - */ - -typedef struct png_dsort_struct -{ - struct png_dsort_struct FAR * next; - png_byte left; - png_byte right; -} png_dsort; -typedef png_dsort FAR * png_dsortp; -typedef png_dsort FAR * FAR * png_dsortpp; - -void PNGAPI -png_set_dither(png_structp png_ptr, png_colorp palette, - int num_palette, int maximum_colors, png_uint_16p histogram, - int full_dither) -{ - png_debug(1, "in png_set_dither\n"); - if(png_ptr == NULL) return; - png_ptr->transformations |= PNG_DITHER; - - if (!full_dither) - { - int i; - - png_ptr->dither_index = (png_bytep)png_malloc(png_ptr, - (png_uint_32)(num_palette * png_sizeof (png_byte))); - for (i = 0; i < num_palette; i++) - png_ptr->dither_index[i] = (png_byte)i; - } - - if (num_palette > maximum_colors) - { - if (histogram != NULL) - { - /* This is easy enough, just throw out the least used colors. - Perhaps not the best solution, but good enough. */ - - int i; - - /* initialize an array to sort colors */ - png_ptr->dither_sort = (png_bytep)png_malloc(png_ptr, - (png_uint_32)(num_palette * png_sizeof (png_byte))); - - /* initialize the dither_sort array */ - for (i = 0; i < num_palette; i++) - png_ptr->dither_sort[i] = (png_byte)i; - - /* Find the least used palette entries by starting a - bubble sort, and running it until we have sorted - out enough colors. Note that we don't care about - sorting all the colors, just finding which are - least used. */ - - for (i = num_palette - 1; i >= maximum_colors; i--) - { - int done; /* to stop early if the list is pre-sorted */ - int j; - - done = 1; - for (j = 0; j < i; j++) - { - if (histogram[png_ptr->dither_sort[j]] - < histogram[png_ptr->dither_sort[j + 1]]) - { - png_byte t; - - t = png_ptr->dither_sort[j]; - png_ptr->dither_sort[j] = png_ptr->dither_sort[j + 1]; - png_ptr->dither_sort[j + 1] = t; - done = 0; - } - } - if (done) - break; - } - - /* swap the palette around, and set up a table, if necessary */ - if (full_dither) - { - int j = num_palette; - - /* put all the useful colors within the max, but don't - move the others */ - for (i = 0; i < maximum_colors; i++) - { - if ((int)png_ptr->dither_sort[i] >= maximum_colors) - { - do - j--; - while ((int)png_ptr->dither_sort[j] >= maximum_colors); - palette[i] = palette[j]; - } - } - } - else - { - int j = num_palette; - - /* move all the used colors inside the max limit, and - develop a translation table */ - for (i = 0; i < maximum_colors; i++) - { - /* only move the colors we need to */ - if ((int)png_ptr->dither_sort[i] >= maximum_colors) - { - png_color tmp_color; - - do - j--; - while ((int)png_ptr->dither_sort[j] >= maximum_colors); - - tmp_color = palette[j]; - palette[j] = palette[i]; - palette[i] = tmp_color; - /* indicate where the color went */ - png_ptr->dither_index[j] = (png_byte)i; - png_ptr->dither_index[i] = (png_byte)j; - } - } - - /* find closest color for those colors we are not using */ - for (i = 0; i < num_palette; i++) - { - if ((int)png_ptr->dither_index[i] >= maximum_colors) - { - int min_d, k, min_k, d_index; - - /* find the closest color to one we threw out */ - d_index = png_ptr->dither_index[i]; - min_d = PNG_COLOR_DIST(palette[d_index], palette[0]); - for (k = 1, min_k = 0; k < maximum_colors; k++) - { - int d; - - d = PNG_COLOR_DIST(palette[d_index], palette[k]); - - if (d < min_d) - { - min_d = d; - min_k = k; - } - } - /* point to closest color */ - png_ptr->dither_index[i] = (png_byte)min_k; - } - } - } - png_free(png_ptr, png_ptr->dither_sort); - png_ptr->dither_sort=NULL; - } - else - { - /* This is much harder to do simply (and quickly). Perhaps - we need to go through a median cut routine, but those - don't always behave themselves with only a few colors - as input. So we will just find the closest two colors, - and throw out one of them (chosen somewhat randomly). - [We don't understand this at all, so if someone wants to - work on improving it, be our guest - AED, GRP] - */ - int i; - int max_d; - int num_new_palette; - png_dsortp t; - png_dsortpp hash; - - t=NULL; - - /* initialize palette index arrays */ - png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr, - (png_uint_32)(num_palette * png_sizeof (png_byte))); - png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr, - (png_uint_32)(num_palette * png_sizeof (png_byte))); - - /* initialize the sort array */ - for (i = 0; i < num_palette; i++) - { - png_ptr->index_to_palette[i] = (png_byte)i; - png_ptr->palette_to_index[i] = (png_byte)i; - } - - hash = (png_dsortpp)png_malloc(png_ptr, (png_uint_32)(769 * - png_sizeof (png_dsortp))); - for (i = 0; i < 769; i++) - hash[i] = NULL; -/* png_memset(hash, 0, 769 * png_sizeof (png_dsortp)); */ - - num_new_palette = num_palette; - - /* initial wild guess at how far apart the farthest pixel - pair we will be eliminating will be. Larger - numbers mean more areas will be allocated, Smaller - numbers run the risk of not saving enough data, and - having to do this all over again. - - I have not done extensive checking on this number. - */ - max_d = 96; - - while (num_new_palette > maximum_colors) - { - for (i = 0; i < num_new_palette - 1; i++) - { - int j; - - for (j = i + 1; j < num_new_palette; j++) - { - int d; - - d = PNG_COLOR_DIST(palette[i], palette[j]); - - if (d <= max_d) - { - - t = (png_dsortp)png_malloc_warn(png_ptr, - (png_uint_32)(png_sizeof(png_dsort))); - if (t == NULL) - break; - t->next = hash[d]; - t->left = (png_byte)i; - t->right = (png_byte)j; - hash[d] = t; - } - } - if (t == NULL) - break; - } - - if (t != NULL) - for (i = 0; i <= max_d; i++) - { - if (hash[i] != NULL) - { - png_dsortp p; - - for (p = hash[i]; p; p = p->next) - { - if ((int)png_ptr->index_to_palette[p->left] - < num_new_palette && - (int)png_ptr->index_to_palette[p->right] - < num_new_palette) - { - int j, next_j; - - if (num_new_palette & 0x01) - { - j = p->left; - next_j = p->right; - } - else - { - j = p->right; - next_j = p->left; - } - - num_new_palette--; - palette[png_ptr->index_to_palette[j]] - = palette[num_new_palette]; - if (!full_dither) - { - int k; - - for (k = 0; k < num_palette; k++) - { - if (png_ptr->dither_index[k] == - png_ptr->index_to_palette[j]) - png_ptr->dither_index[k] = - png_ptr->index_to_palette[next_j]; - if ((int)png_ptr->dither_index[k] == - num_new_palette) - png_ptr->dither_index[k] = - png_ptr->index_to_palette[j]; - } - } - - png_ptr->index_to_palette[png_ptr->palette_to_index - [num_new_palette]] = png_ptr->index_to_palette[j]; - png_ptr->palette_to_index[png_ptr->index_to_palette[j]] - = png_ptr->palette_to_index[num_new_palette]; - - png_ptr->index_to_palette[j] = (png_byte)num_new_palette; - png_ptr->palette_to_index[num_new_palette] = (png_byte)j; - } - if (num_new_palette <= maximum_colors) - break; - } - if (num_new_palette <= maximum_colors) - break; - } - } - - for (i = 0; i < 769; i++) - { - if (hash[i] != NULL) - { - png_dsortp p = hash[i]; - while (p) - { - t = p->next; - png_free(png_ptr, p); - p = t; - } - } - hash[i] = 0; - } - max_d += 96; - } - png_free(png_ptr, hash); - png_free(png_ptr, png_ptr->palette_to_index); - png_free(png_ptr, png_ptr->index_to_palette); - png_ptr->palette_to_index=NULL; - png_ptr->index_to_palette=NULL; - } - num_palette = maximum_colors; - } - if (png_ptr->palette == NULL) - { - png_ptr->palette = palette; - } - png_ptr->num_palette = (png_uint_16)num_palette; - - if (full_dither) - { - int i; - png_bytep distance; - int total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS + - PNG_DITHER_BLUE_BITS; - int num_red = (1 << PNG_DITHER_RED_BITS); - int num_green = (1 << PNG_DITHER_GREEN_BITS); - int num_blue = (1 << PNG_DITHER_BLUE_BITS); - png_size_t num_entries = ((png_size_t)1 << total_bits); - - png_ptr->palette_lookup = (png_bytep )png_malloc(png_ptr, - (png_uint_32)(num_entries * png_sizeof (png_byte))); - - png_memset(png_ptr->palette_lookup, 0, num_entries * - png_sizeof (png_byte)); - - distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries * - png_sizeof(png_byte))); - - png_memset(distance, 0xff, num_entries * png_sizeof(png_byte)); - - for (i = 0; i < num_palette; i++) - { - int ir, ig, ib; - int r = (palette[i].red >> (8 - PNG_DITHER_RED_BITS)); - int g = (palette[i].green >> (8 - PNG_DITHER_GREEN_BITS)); - int b = (palette[i].blue >> (8 - PNG_DITHER_BLUE_BITS)); - - for (ir = 0; ir < num_red; ir++) - { - /* int dr = abs(ir - r); */ - int dr = ((ir > r) ? ir - r : r - ir); - int index_r = (ir << (PNG_DITHER_BLUE_BITS + PNG_DITHER_GREEN_BITS)); - - for (ig = 0; ig < num_green; ig++) - { - /* int dg = abs(ig - g); */ - int dg = ((ig > g) ? ig - g : g - ig); - int dt = dr + dg; - int dm = ((dr > dg) ? dr : dg); - int index_g = index_r | (ig << PNG_DITHER_BLUE_BITS); - - for (ib = 0; ib < num_blue; ib++) - { - int d_index = index_g | ib; - /* int db = abs(ib - b); */ - int db = ((ib > b) ? ib - b : b - ib); - int dmax = ((dm > db) ? dm : db); - int d = dmax + dt + db; - - if (d < (int)distance[d_index]) - { - distance[d_index] = (png_byte)d; - png_ptr->palette_lookup[d_index] = (png_byte)i; - } - } - } - } - } - - png_free(png_ptr, distance); - } -} -#endif - -#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) -/* Transform the image from the file_gamma to the screen_gamma. We - * only do transformations on images where the file_gamma and screen_gamma - * are not close reciprocals, otherwise it slows things down slightly, and - * also needlessly introduces small errors. - * - * We will turn off gamma transformation later if no semitransparent entries - * are present in the tRNS array for palette images. We can't do it here - * because we don't necessarily have the tRNS chunk yet. - */ -void PNGAPI -png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma) -{ - png_debug(1, "in png_set_gamma\n"); - if(png_ptr == NULL) return; - if ((fabs(scrn_gamma * file_gamma - 1.0) > PNG_GAMMA_THRESHOLD) || - (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) || - (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)) - png_ptr->transformations |= PNG_GAMMA; - png_ptr->gamma = (float)file_gamma; - png_ptr->screen_gamma = (float)scrn_gamma; -} -#endif - -#if defined(PNG_READ_EXPAND_SUPPORTED) -/* Expand paletted images to RGB, expand grayscale images of - * less than 8-bit depth to 8-bit depth, and expand tRNS chunks - * to alpha channels. - */ -void PNGAPI -png_set_expand(png_structp png_ptr) -{ - png_debug(1, "in png_set_expand\n"); - if(png_ptr == NULL) return; - png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); -#ifdef PNG_WARN_UNINITIALIZED_ROW - png_ptr->flags &= ~PNG_FLAG_ROW_INIT; -#endif -} - -/* GRR 19990627: the following three functions currently are identical - * to png_set_expand(). However, it is entirely reasonable that someone - * might wish to expand an indexed image to RGB but *not* expand a single, - * fully transparent palette entry to a full alpha channel--perhaps instead - * convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace - * the transparent color with a particular RGB value, or drop tRNS entirely. - * IOW, a future version of the library may make the transformations flag - * a bit more fine-grained, with separate bits for each of these three - * functions. - * - * More to the point, these functions make it obvious what libpng will be - * doing, whereas "expand" can (and does) mean any number of things. - * - * GRP 20060307: In libpng-1.4.0, png_set_gray_1_2_4_to_8() was modified - * to expand only the sample depth but not to expand the tRNS to alpha. - */ - -/* Expand paletted images to RGB. */ -void PNGAPI -png_set_palette_to_rgb(png_structp png_ptr) -{ - png_debug(1, "in png_set_palette_to_rgb\n"); - if(png_ptr == NULL) return; - png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); -#ifdef PNG_WARN_UNINITIALIZED_ROW - png_ptr->flags &= ~PNG_FLAG_ROW_INIT; -#endif -} - -#if !defined(PNG_1_0_X) -/* Expand grayscale images of less than 8-bit depth to 8 bits. */ -void PNGAPI -png_set_expand_gray_1_2_4_to_8(png_structp png_ptr) -{ - png_debug(1, "in png_set_expand_gray_1_2_4_to_8\n"); - if(png_ptr == NULL) return; - png_ptr->transformations |= PNG_EXPAND; -#ifdef PNG_WARN_UNINITIALIZED_ROW - png_ptr->flags &= ~PNG_FLAG_ROW_INIT; -#endif -} -#endif - -#if defined(PNG_1_0_X) || defined(PNG_1_2_X) -/* Expand grayscale images of less than 8-bit depth to 8 bits. */ -/* Deprecated as of libpng-1.2.9 */ -void PNGAPI -png_set_gray_1_2_4_to_8(png_structp png_ptr) -{ - png_debug(1, "in png_set_gray_1_2_4_to_8\n"); - if(png_ptr == NULL) return; - png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); -} -#endif - - -/* Expand tRNS chunks to alpha channels. */ -void PNGAPI -png_set_tRNS_to_alpha(png_structp png_ptr) -{ - png_debug(1, "in png_set_tRNS_to_alpha\n"); - png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); -#ifdef PNG_WARN_UNINITIALIZED_ROW - png_ptr->flags &= ~PNG_FLAG_ROW_INIT; -#endif -} -#endif /* defined(PNG_READ_EXPAND_SUPPORTED) */ - -#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) -void PNGAPI -png_set_gray_to_rgb(png_structp png_ptr) -{ - png_debug(1, "in png_set_gray_to_rgb\n"); - png_ptr->transformations |= PNG_GRAY_TO_RGB; -#ifdef PNG_WARN_UNINITIALIZED_ROW - png_ptr->flags &= ~PNG_FLAG_ROW_INIT; -#endif -} -#endif - -#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) -#if defined(PNG_FLOATING_POINT_SUPPORTED) -/* Convert a RGB image to a grayscale of the same width. This allows us, - * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image. - */ - -void PNGAPI -png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red, - double green) -{ - int red_fixed = (int)((float)red*100000.0 + 0.5); - int green_fixed = (int)((float)green*100000.0 + 0.5); - if(png_ptr == NULL) return; - png_set_rgb_to_gray_fixed(png_ptr, error_action, red_fixed, green_fixed); -} -#endif - -void PNGAPI -png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action, - png_fixed_point red, png_fixed_point green) -{ - png_debug(1, "in png_set_rgb_to_gray\n"); - if(png_ptr == NULL) return; - switch(error_action) - { - case 1: png_ptr->transformations |= PNG_RGB_TO_GRAY; - break; - case 2: png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN; - break; - case 3: png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR; - } - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) -#if defined(PNG_READ_EXPAND_SUPPORTED) - png_ptr->transformations |= PNG_EXPAND; -#else - { - png_warning(png_ptr, "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED."); - png_ptr->transformations &= ~PNG_RGB_TO_GRAY; - } -#endif - { - png_uint_16 red_int, green_int; - if(red < 0 || green < 0) - { - red_int = 6968; /* .212671 * 32768 + .5 */ - green_int = 23434; /* .715160 * 32768 + .5 */ - } - else if(red + green < 100000L) - { - red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L); - green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L); - } - else - { - png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients"); - red_int = 6968; - green_int = 23434; - } - png_ptr->rgb_to_gray_red_coeff = red_int; - png_ptr->rgb_to_gray_green_coeff = green_int; - png_ptr->rgb_to_gray_blue_coeff = (png_uint_16)(32768-red_int-green_int); - } -} -#endif - -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_LEGACY_SUPPORTED) -void PNGAPI -png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr - read_user_transform_fn) -{ - png_debug(1, "in png_set_read_user_transform_fn\n"); - if(png_ptr == NULL) return; -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) - png_ptr->transformations |= PNG_USER_TRANSFORM; - png_ptr->read_user_transform_fn = read_user_transform_fn; -#endif -#ifdef PNG_LEGACY_SUPPORTED - if(read_user_transform_fn) - png_warning(png_ptr, - "This version of libpng does not support user transforms"); -#endif -} -#endif - -/* Initialize everything needed for the read. This includes modifying - * the palette. - */ -void /* PRIVATE */ -png_init_read_transformations(png_structp png_ptr) -{ - png_debug(1, "in png_init_read_transformations\n"); -#if defined(PNG_USELESS_TESTS_SUPPORTED) - if(png_ptr != NULL) -#endif - { -#if defined(PNG_READ_BACKGROUND_SUPPORTED) || defined(PNG_READ_SHIFT_SUPPORTED) \ - || defined(PNG_READ_GAMMA_SUPPORTED) - int color_type = png_ptr->color_type; -#endif - -#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) - -#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) - /* Detect gray background and attempt to enable optimization - * for gray --> RGB case */ - /* Note: if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or - * RGB_ALPHA (in which case need_expand is superfluous anyway), the - * background color might actually be gray yet not be flagged as such. - * This is not a problem for the current code, which uses - * PNG_BACKGROUND_IS_GRAY only to decide when to do the - * png_do_gray_to_rgb() transformation. - */ - if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && - !(color_type & PNG_COLOR_MASK_COLOR)) - { - png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; - } else if ((png_ptr->transformations & PNG_BACKGROUND) && - !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) && - (png_ptr->transformations & PNG_GRAY_TO_RGB) && - png_ptr->background.red == png_ptr->background.green && - png_ptr->background.red == png_ptr->background.blue) - { - png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; - png_ptr->background.gray = png_ptr->background.red; - } -#endif - - if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && - (png_ptr->transformations & PNG_EXPAND)) - { - if (!(color_type & PNG_COLOR_MASK_COLOR)) /* i.e., GRAY or GRAY_ALPHA */ - { - /* expand background and tRNS chunks */ - switch (png_ptr->bit_depth) - { - case 1: - png_ptr->background.gray *= (png_uint_16)0xff; - png_ptr->background.red = png_ptr->background.green - = png_ptr->background.blue = png_ptr->background.gray; - if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) - { - png_ptr->trans_values.gray *= (png_uint_16)0xff; - png_ptr->trans_values.red = png_ptr->trans_values.green - = png_ptr->trans_values.blue = png_ptr->trans_values.gray; - } - break; - case 2: - png_ptr->background.gray *= (png_uint_16)0x55; - png_ptr->background.red = png_ptr->background.green - = png_ptr->background.blue = png_ptr->background.gray; - if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) - { - png_ptr->trans_values.gray *= (png_uint_16)0x55; - png_ptr->trans_values.red = png_ptr->trans_values.green - = png_ptr->trans_values.blue = png_ptr->trans_values.gray; - } - break; - case 4: - png_ptr->background.gray *= (png_uint_16)0x11; - png_ptr->background.red = png_ptr->background.green - = png_ptr->background.blue = png_ptr->background.gray; - if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) - { - png_ptr->trans_values.gray *= (png_uint_16)0x11; - png_ptr->trans_values.red = png_ptr->trans_values.green - = png_ptr->trans_values.blue = png_ptr->trans_values.gray; - } - break; - case 8: - case 16: - png_ptr->background.red = png_ptr->background.green - = png_ptr->background.blue = png_ptr->background.gray; - break; - } - } - else if (color_type == PNG_COLOR_TYPE_PALETTE) - { - png_ptr->background.red = - png_ptr->palette[png_ptr->background.index].red; - png_ptr->background.green = - png_ptr->palette[png_ptr->background.index].green; - png_ptr->background.blue = - png_ptr->palette[png_ptr->background.index].blue; - -#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) - if (png_ptr->transformations & PNG_INVERT_ALPHA) - { -#if defined(PNG_READ_EXPAND_SUPPORTED) - if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) -#endif - { - /* invert the alpha channel (in tRNS) unless the pixels are - going to be expanded, in which case leave it for later */ - int i,istop; - istop=(int)png_ptr->num_trans; - for (i=0; itrans[i] = (png_byte)(255 - png_ptr->trans[i]); - } - } -#endif - - } - } -#endif - -#if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED) - png_ptr->background_1 = png_ptr->background; -#endif -#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) - - if ((color_type == PNG_COLOR_TYPE_PALETTE && png_ptr->num_trans != 0) - && (fabs(png_ptr->screen_gamma * png_ptr->gamma - 1.0) - < PNG_GAMMA_THRESHOLD)) - { - int i,k; - k=0; - for (i=0; inum_trans; i++) - { - if (png_ptr->trans[i] != 0 && png_ptr->trans[i] != 0xff) - k=1; /* partial transparency is present */ - } - if (k == 0) - png_ptr->transformations &= ~PNG_GAMMA; - } - - if ((png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY)) && - png_ptr->gamma != 0.0) - { - png_build_gamma_table(png_ptr); -#if defined(PNG_READ_BACKGROUND_SUPPORTED) - if (png_ptr->transformations & PNG_BACKGROUND) - { - if (color_type == PNG_COLOR_TYPE_PALETTE) - { - /* could skip if no transparency and - */ - png_color back, back_1; - png_colorp palette = png_ptr->palette; - int num_palette = png_ptr->num_palette; - int i; - if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE) - { - back.red = png_ptr->gamma_table[png_ptr->background.red]; - back.green = png_ptr->gamma_table[png_ptr->background.green]; - back.blue = png_ptr->gamma_table[png_ptr->background.blue]; - - back_1.red = png_ptr->gamma_to_1[png_ptr->background.red]; - back_1.green = png_ptr->gamma_to_1[png_ptr->background.green]; - back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue]; - } - else - { - double g, gs; - - switch (png_ptr->background_gamma_type) - { - case PNG_BACKGROUND_GAMMA_SCREEN: - g = (png_ptr->screen_gamma); - gs = 1.0; - break; - case PNG_BACKGROUND_GAMMA_FILE: - g = 1.0 / (png_ptr->gamma); - gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); - break; - case PNG_BACKGROUND_GAMMA_UNIQUE: - g = 1.0 / (png_ptr->background_gamma); - gs = 1.0 / (png_ptr->background_gamma * - png_ptr->screen_gamma); - break; - default: - g = 1.0; /* back_1 */ - gs = 1.0; /* back */ - } - - if ( fabs(gs - 1.0) < PNG_GAMMA_THRESHOLD) - { - back.red = (png_byte)png_ptr->background.red; - back.green = (png_byte)png_ptr->background.green; - back.blue = (png_byte)png_ptr->background.blue; - } - else - { - back.red = (png_byte)(pow( - (double)png_ptr->background.red/255, gs) * 255.0 + .5); - back.green = (png_byte)(pow( - (double)png_ptr->background.green/255, gs) * 255.0 + .5); - back.blue = (png_byte)(pow( - (double)png_ptr->background.blue/255, gs) * 255.0 + .5); - } - - back_1.red = (png_byte)(pow( - (double)png_ptr->background.red/255, g) * 255.0 + .5); - back_1.green = (png_byte)(pow( - (double)png_ptr->background.green/255, g) * 255.0 + .5); - back_1.blue = (png_byte)(pow( - (double)png_ptr->background.blue/255, g) * 255.0 + .5); - } - for (i = 0; i < num_palette; i++) - { - if (i < (int)png_ptr->num_trans && png_ptr->trans[i] != 0xff) - { - if (png_ptr->trans[i] == 0) - { - palette[i] = back; - } - else /* if (png_ptr->trans[i] != 0xff) */ - { - png_byte v, w; - - v = png_ptr->gamma_to_1[palette[i].red]; - png_composite(w, v, png_ptr->trans[i], back_1.red); - palette[i].red = png_ptr->gamma_from_1[w]; - - v = png_ptr->gamma_to_1[palette[i].green]; - png_composite(w, v, png_ptr->trans[i], back_1.green); - palette[i].green = png_ptr->gamma_from_1[w]; - - v = png_ptr->gamma_to_1[palette[i].blue]; - png_composite(w, v, png_ptr->trans[i], back_1.blue); - palette[i].blue = png_ptr->gamma_from_1[w]; - } - } - else - { - palette[i].red = png_ptr->gamma_table[palette[i].red]; - palette[i].green = png_ptr->gamma_table[palette[i].green]; - palette[i].blue = png_ptr->gamma_table[palette[i].blue]; - } - } - } - /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */ - else - /* color_type != PNG_COLOR_TYPE_PALETTE */ - { - double m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1); - double g = 1.0; - double gs = 1.0; - - switch (png_ptr->background_gamma_type) - { - case PNG_BACKGROUND_GAMMA_SCREEN: - g = (png_ptr->screen_gamma); - gs = 1.0; - break; - case PNG_BACKGROUND_GAMMA_FILE: - g = 1.0 / (png_ptr->gamma); - gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); - break; - case PNG_BACKGROUND_GAMMA_UNIQUE: - g = 1.0 / (png_ptr->background_gamma); - gs = 1.0 / (png_ptr->background_gamma * - png_ptr->screen_gamma); - break; - } - - png_ptr->background_1.gray = (png_uint_16)(pow( - (double)png_ptr->background.gray / m, g) * m + .5); - png_ptr->background.gray = (png_uint_16)(pow( - (double)png_ptr->background.gray / m, gs) * m + .5); - - if ((png_ptr->background.red != png_ptr->background.green) || - (png_ptr->background.red != png_ptr->background.blue) || - (png_ptr->background.red != png_ptr->background.gray)) - { - /* RGB or RGBA with color background */ - png_ptr->background_1.red = (png_uint_16)(pow( - (double)png_ptr->background.red / m, g) * m + .5); - png_ptr->background_1.green = (png_uint_16)(pow( - (double)png_ptr->background.green / m, g) * m + .5); - png_ptr->background_1.blue = (png_uint_16)(pow( - (double)png_ptr->background.blue / m, g) * m + .5); - png_ptr->background.red = (png_uint_16)(pow( - (double)png_ptr->background.red / m, gs) * m + .5); - png_ptr->background.green = (png_uint_16)(pow( - (double)png_ptr->background.green / m, gs) * m + .5); - png_ptr->background.blue = (png_uint_16)(pow( - (double)png_ptr->background.blue / m, gs) * m + .5); - } - else - { - /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */ - png_ptr->background_1.red = png_ptr->background_1.green - = png_ptr->background_1.blue = png_ptr->background_1.gray; - png_ptr->background.red = png_ptr->background.green - = png_ptr->background.blue = png_ptr->background.gray; - } - } - } - else - /* transformation does not include PNG_BACKGROUND */ -#endif /* PNG_READ_BACKGROUND_SUPPORTED */ - if (color_type == PNG_COLOR_TYPE_PALETTE) - { - png_colorp palette = png_ptr->palette; - int num_palette = png_ptr->num_palette; - int i; - - for (i = 0; i < num_palette; i++) - { - palette[i].red = png_ptr->gamma_table[palette[i].red]; - palette[i].green = png_ptr->gamma_table[palette[i].green]; - palette[i].blue = png_ptr->gamma_table[palette[i].blue]; - } - } - } -#if defined(PNG_READ_BACKGROUND_SUPPORTED) - else -#endif -#endif /* PNG_READ_GAMMA_SUPPORTED && PNG_FLOATING_POINT_SUPPORTED */ -#if defined(PNG_READ_BACKGROUND_SUPPORTED) - /* No GAMMA transformation */ - if ((png_ptr->transformations & PNG_BACKGROUND) && - (color_type == PNG_COLOR_TYPE_PALETTE)) - { - int i; - int istop = (int)png_ptr->num_trans; - png_color back; - png_colorp palette = png_ptr->palette; - - back.red = (png_byte)png_ptr->background.red; - back.green = (png_byte)png_ptr->background.green; - back.blue = (png_byte)png_ptr->background.blue; - - for (i = 0; i < istop; i++) - { - if (png_ptr->trans[i] == 0) - { - palette[i] = back; - } - else if (png_ptr->trans[i] != 0xff) - { - /* The png_composite() macro is defined in png.h */ - png_composite(palette[i].red, palette[i].red, - png_ptr->trans[i], back.red); - png_composite(palette[i].green, palette[i].green, - png_ptr->trans[i], back.green); - png_composite(palette[i].blue, palette[i].blue, - png_ptr->trans[i], back.blue); - } - } - } -#endif /* PNG_READ_BACKGROUND_SUPPORTED */ - -#if defined(PNG_READ_SHIFT_SUPPORTED) - if ((png_ptr->transformations & PNG_SHIFT) && - (color_type == PNG_COLOR_TYPE_PALETTE)) - { - png_uint_16 i; - png_uint_16 istop = png_ptr->num_palette; - int sr = 8 - png_ptr->sig_bit.red; - int sg = 8 - png_ptr->sig_bit.green; - int sb = 8 - png_ptr->sig_bit.blue; - - if (sr < 0 || sr > 8) - sr = 0; - if (sg < 0 || sg > 8) - sg = 0; - if (sb < 0 || sb > 8) - sb = 0; - for (i = 0; i < istop; i++) - { - png_ptr->palette[i].red >>= sr; - png_ptr->palette[i].green >>= sg; - png_ptr->palette[i].blue >>= sb; - } - } -#endif /* PNG_READ_SHIFT_SUPPORTED */ - } -#if !defined(PNG_READ_GAMMA_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) \ - && !defined(PNG_READ_BACKGROUND_SUPPORTED) - if(png_ptr) - return; -#endif -} - -/* Modify the info structure to reflect the transformations. The - * info should be updated so a PNG file could be written with it, - * assuming the transformations result in valid PNG data. - */ -void /* PRIVATE */ -png_read_transform_info(png_structp png_ptr, png_infop info_ptr) -{ - png_debug(1, "in png_read_transform_info\n"); -#if defined(PNG_READ_EXPAND_SUPPORTED) - if (png_ptr->transformations & PNG_EXPAND) - { - if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - { - if (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND_tRNS)) - info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA; - else - info_ptr->color_type = PNG_COLOR_TYPE_RGB; - info_ptr->bit_depth = 8; - info_ptr->num_trans = 0; - } - else - { - if (png_ptr->num_trans) - { - if (png_ptr->transformations & PNG_EXPAND_tRNS) - info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; - else - info_ptr->color_type |= PNG_COLOR_MASK_COLOR; - } - if (info_ptr->bit_depth < 8) - info_ptr->bit_depth = 8; - info_ptr->num_trans = 0; - } - } -#endif - -#if defined(PNG_READ_BACKGROUND_SUPPORTED) - if (png_ptr->transformations & PNG_BACKGROUND) - { - info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA; - info_ptr->num_trans = 0; - info_ptr->background = png_ptr->background; - } -#endif - -#if defined(PNG_READ_GAMMA_SUPPORTED) - if (png_ptr->transformations & PNG_GAMMA) - { -#ifdef PNG_FLOATING_POINT_SUPPORTED - info_ptr->gamma = png_ptr->gamma; -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED - info_ptr->int_gamma = png_ptr->int_gamma; -#endif - } -#endif - -#if defined(PNG_READ_16_TO_8_SUPPORTED) - if ((png_ptr->transformations & PNG_16_TO_8) && (info_ptr->bit_depth == 16)) - info_ptr->bit_depth = 8; -#endif - -#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) - if (png_ptr->transformations & PNG_GRAY_TO_RGB) - info_ptr->color_type |= PNG_COLOR_MASK_COLOR; -#endif - -#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) - if (png_ptr->transformations & PNG_RGB_TO_GRAY) - info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR; -#endif - -#if defined(PNG_READ_DITHER_SUPPORTED) - if (png_ptr->transformations & PNG_DITHER) - { - if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || - (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) && - png_ptr->palette_lookup && info_ptr->bit_depth == 8) - { - info_ptr->color_type = PNG_COLOR_TYPE_PALETTE; - } - } -#endif - -#if defined(PNG_READ_PACK_SUPPORTED) - if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8)) - info_ptr->bit_depth = 8; -#endif - - if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - info_ptr->channels = 1; - else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) - info_ptr->channels = 3; - else - info_ptr->channels = 1; - -#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) - if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA) - info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA; -#endif - - if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) - info_ptr->channels++; - -#if defined(PNG_READ_FILLER_SUPPORTED) - /* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */ - if ((png_ptr->transformations & PNG_FILLER) && - ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || - (info_ptr->color_type == PNG_COLOR_TYPE_GRAY))) - { - info_ptr->channels++; - /* if adding a true alpha channel not just filler */ -#if !defined(PNG_1_0_X) - if (png_ptr->transformations & PNG_ADD_ALPHA) - info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; -#endif - } -#endif - -#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \ -defined(PNG_READ_USER_TRANSFORM_SUPPORTED) - if(png_ptr->transformations & PNG_USER_TRANSFORM) - { - if(info_ptr->bit_depth < png_ptr->user_transform_depth) - info_ptr->bit_depth = png_ptr->user_transform_depth; - if(info_ptr->channels < png_ptr->user_transform_channels) - info_ptr->channels = png_ptr->user_transform_channels; - } -#endif - - info_ptr->pixel_depth = (png_byte)(info_ptr->channels * - info_ptr->bit_depth); - - info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth,info_ptr->width); - -#if !defined(PNG_READ_EXPAND_SUPPORTED) - if(png_ptr) - return; -#endif -} - -/* Transform the row. The order of transformations is significant, - * and is very touchy. If you add a transformation, take care to - * decide how it fits in with the other transformations here. - */ -void /* PRIVATE */ -png_do_read_transformations(png_structp png_ptr) -{ - png_debug(1, "in png_do_read_transformations\n"); - if (png_ptr->row_buf == NULL) - { -#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) - char msg[50]; - - png_snprintf2(msg, 50, - "NULL row buffer for row %ld, pass %d", png_ptr->row_number, - png_ptr->pass); - png_error(png_ptr, msg); -#else - png_error(png_ptr, "NULL row buffer"); -#endif - } -#ifdef PNG_WARN_UNINITIALIZED_ROW - if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) - /* Application has failed to call either png_read_start_image() - * or png_read_update_info() after setting transforms that expand - * pixels. This check added to libpng-1.2.19 */ -#if (PNG_WARN_UNINITIALIZED_ROW==1) - png_error(png_ptr, "Uninitialized row"); -#else - png_warning(png_ptr, "Uninitialized row"); -#endif -#endif - -#if defined(PNG_READ_EXPAND_SUPPORTED) - if (png_ptr->transformations & PNG_EXPAND) - { - if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE) - { - png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1, - png_ptr->palette, png_ptr->trans, png_ptr->num_trans); - } - else - { - if (png_ptr->num_trans && - (png_ptr->transformations & PNG_EXPAND_tRNS)) - png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1, - &(png_ptr->trans_values)); - else - png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1, - NULL); - } - } -#endif - -#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) - if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA) - png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, - PNG_FLAG_FILLER_AFTER | (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)); -#endif - -#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) - if (png_ptr->transformations & PNG_RGB_TO_GRAY) - { - int rgb_error = - png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info), png_ptr->row_buf + 1); - if(rgb_error) - { - png_ptr->rgb_to_gray_status=1; - if((png_ptr->transformations & PNG_RGB_TO_GRAY) == - PNG_RGB_TO_GRAY_WARN) - png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel"); - if((png_ptr->transformations & PNG_RGB_TO_GRAY) == - PNG_RGB_TO_GRAY_ERR) - png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel"); - } - } -#endif - -/* -From Andreas Dilger e-mail to png-implement, 26 March 1998: - - In most cases, the "simple transparency" should be done prior to doing - gray-to-RGB, or you will have to test 3x as many bytes to check if a - pixel is transparent. You would also need to make sure that the - transparency information is upgraded to RGB. - - To summarize, the current flow is: - - Gray + simple transparency -> compare 1 or 2 gray bytes and composite - with background "in place" if transparent, - convert to RGB if necessary - - Gray + alpha -> composite with gray background and remove alpha bytes, - convert to RGB if necessary - - To support RGB backgrounds for gray images we need: - - Gray + simple transparency -> convert to RGB + simple transparency, compare - 3 or 6 bytes and composite with background - "in place" if transparent (3x compare/pixel - compared to doing composite with gray bkgrnd) - - Gray + alpha -> convert to RGB + alpha, composite with background and - remove alpha bytes (3x float operations/pixel - compared with composite on gray background) - - Greg's change will do this. The reason it wasn't done before is for - performance, as this increases the per-pixel operations. If we would check - in advance if the background was gray or RGB, and position the gray-to-RGB - transform appropriately, then it would save a lot of work/time. - */ - -#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) - /* if gray -> RGB, do so now only if background is non-gray; else do later - * for performance reasons */ - if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && - !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) - png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1); -#endif - -#if defined(PNG_READ_BACKGROUND_SUPPORTED) - if ((png_ptr->transformations & PNG_BACKGROUND) && - ((png_ptr->num_trans != 0 ) || - (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) - png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1, - &(png_ptr->trans_values), &(png_ptr->background) -#if defined(PNG_READ_GAMMA_SUPPORTED) - , &(png_ptr->background_1), - png_ptr->gamma_table, png_ptr->gamma_from_1, - png_ptr->gamma_to_1, png_ptr->gamma_16_table, - png_ptr->gamma_16_from_1, png_ptr->gamma_16_to_1, - png_ptr->gamma_shift -#endif -); -#endif - -#if defined(PNG_READ_GAMMA_SUPPORTED) - if ((png_ptr->transformations & PNG_GAMMA) && -#if defined(PNG_READ_BACKGROUND_SUPPORTED) - !((png_ptr->transformations & PNG_BACKGROUND) && - ((png_ptr->num_trans != 0) || - (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) && -#endif - (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)) - png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1, - png_ptr->gamma_table, png_ptr->gamma_16_table, - png_ptr->gamma_shift); -#endif - -#if defined(PNG_READ_16_TO_8_SUPPORTED) - if (png_ptr->transformations & PNG_16_TO_8) - png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1); -#endif - -#if defined(PNG_READ_DITHER_SUPPORTED) - if (png_ptr->transformations & PNG_DITHER) - { - png_do_dither((png_row_infop)&(png_ptr->row_info), png_ptr->row_buf + 1, - png_ptr->palette_lookup, png_ptr->dither_index); - if(png_ptr->row_info.rowbytes == (png_uint_32)0) - png_error(png_ptr, "png_do_dither returned rowbytes=0"); - } -#endif - -#if defined(PNG_READ_INVERT_SUPPORTED) - if (png_ptr->transformations & PNG_INVERT_MONO) - png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1); -#endif - -#if defined(PNG_READ_SHIFT_SUPPORTED) - if (png_ptr->transformations & PNG_SHIFT) - png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1, - &(png_ptr->shift)); -#endif - -#if defined(PNG_READ_PACK_SUPPORTED) - if (png_ptr->transformations & PNG_PACK) - png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1); -#endif - -#if defined(PNG_READ_BGR_SUPPORTED) - if (png_ptr->transformations & PNG_BGR) - png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1); -#endif - -#if defined(PNG_READ_PACKSWAP_SUPPORTED) - if (png_ptr->transformations & PNG_PACKSWAP) - png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1); -#endif - -#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) - /* if gray -> RGB, do so now only if we did not do so above */ - if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && - (png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) - png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1); -#endif - -#if defined(PNG_READ_FILLER_SUPPORTED) - if (png_ptr->transformations & PNG_FILLER) - png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, - (png_uint_32)png_ptr->filler, png_ptr->flags); -#endif - -#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) - if (png_ptr->transformations & PNG_INVERT_ALPHA) - png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); -#endif - -#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) - if (png_ptr->transformations & PNG_SWAP_ALPHA) - png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); -#endif - -#if defined(PNG_READ_SWAP_SUPPORTED) - if (png_ptr->transformations & PNG_SWAP_BYTES) - png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1); -#endif - -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) - if (png_ptr->transformations & PNG_USER_TRANSFORM) - { - if(png_ptr->read_user_transform_fn != NULL) - (*(png_ptr->read_user_transform_fn)) /* user read transform function */ - (png_ptr, /* png_ptr */ - &(png_ptr->row_info), /* row_info: */ - /* png_uint_32 width; width of row */ - /* png_uint_32 rowbytes; number of bytes in row */ - /* png_byte color_type; color type of pixels */ - /* png_byte bit_depth; bit depth of samples */ - /* png_byte channels; number of channels (1-4) */ - /* png_byte pixel_depth; bits per pixel (depth*channels) */ - png_ptr->row_buf + 1); /* start of pixel data for row */ -#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) - if(png_ptr->user_transform_depth) - png_ptr->row_info.bit_depth = png_ptr->user_transform_depth; - if(png_ptr->user_transform_channels) - png_ptr->row_info.channels = png_ptr->user_transform_channels; -#endif - png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth * - png_ptr->row_info.channels); - png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, - png_ptr->row_info.width); - } -#endif - -} - -#if defined(PNG_READ_PACK_SUPPORTED) -/* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel, - * without changing the actual values. Thus, if you had a row with - * a bit depth of 1, you would end up with bytes that only contained - * the numbers 0 or 1. If you would rather they contain 0 and 255, use - * png_do_shift() after this. - */ -void /* PRIVATE */ -png_do_unpack(png_row_infop row_info, png_bytep row) -{ - png_debug(1, "in png_do_unpack\n"); -#if defined(PNG_USELESS_TESTS_SUPPORTED) - if (row != NULL && row_info != NULL && row_info->bit_depth < 8) -#else - if (row_info->bit_depth < 8) -#endif - { - png_uint_32 i; - png_uint_32 row_width=row_info->width; - - switch (row_info->bit_depth) - { - case 1: - { - png_bytep sp = row + (png_size_t)((row_width - 1) >> 3); - png_bytep dp = row + (png_size_t)row_width - 1; - png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07); - for (i = 0; i < row_width; i++) - { - *dp = (png_byte)((*sp >> shift) & 0x01); - if (shift == 7) - { - shift = 0; - sp--; - } - else - shift++; - - dp--; - } - break; - } - case 2: - { - - png_bytep sp = row + (png_size_t)((row_width - 1) >> 2); - png_bytep dp = row + (png_size_t)row_width - 1; - png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); - for (i = 0; i < row_width; i++) - { - *dp = (png_byte)((*sp >> shift) & 0x03); - if (shift == 6) - { - shift = 0; - sp--; - } - else - shift += 2; - - dp--; - } - break; - } - case 4: - { - png_bytep sp = row + (png_size_t)((row_width - 1) >> 1); - png_bytep dp = row + (png_size_t)row_width - 1; - png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); - for (i = 0; i < row_width; i++) - { - *dp = (png_byte)((*sp >> shift) & 0x0f); - if (shift == 4) - { - shift = 0; - sp--; - } - else - shift = 4; - - dp--; - } - break; - } - } - row_info->bit_depth = 8; - row_info->pixel_depth = (png_byte)(8 * row_info->channels); - row_info->rowbytes = row_width * row_info->channels; - } -} -#endif - -#if defined(PNG_READ_SHIFT_SUPPORTED) -/* Reverse the effects of png_do_shift. This routine merely shifts the - * pixels back to their significant bits values. Thus, if you have - * a row of bit depth 8, but only 5 are significant, this will shift - * the values back to 0 through 31. - */ -void /* PRIVATE */ -png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits) -{ - png_debug(1, "in png_do_unshift\n"); - if ( -#if defined(PNG_USELESS_TESTS_SUPPORTED) - row != NULL && row_info != NULL && sig_bits != NULL && -#endif - row_info->color_type != PNG_COLOR_TYPE_PALETTE) - { - int shift[4]; - int channels = 0; - int c; - png_uint_16 value = 0; - png_uint_32 row_width = row_info->width; - - if (row_info->color_type & PNG_COLOR_MASK_COLOR) - { - shift[channels++] = row_info->bit_depth - sig_bits->red; - shift[channels++] = row_info->bit_depth - sig_bits->green; - shift[channels++] = row_info->bit_depth - sig_bits->blue; - } - else - { - shift[channels++] = row_info->bit_depth - sig_bits->gray; - } - if (row_info->color_type & PNG_COLOR_MASK_ALPHA) - { - shift[channels++] = row_info->bit_depth - sig_bits->alpha; - } - - for (c = 0; c < channels; c++) - { - if (shift[c] <= 0) - shift[c] = 0; - else - value = 1; - } - - if (!value) - return; - - switch (row_info->bit_depth) - { - case 2: - { - png_bytep bp; - png_uint_32 i; - png_uint_32 istop = row_info->rowbytes; - - for (bp = row, i = 0; i < istop; i++) - { - *bp >>= 1; - *bp++ &= 0x55; - } - break; - } - case 4: - { - png_bytep bp = row; - png_uint_32 i; - png_uint_32 istop = row_info->rowbytes; - png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) | - (png_byte)((int)0xf >> shift[0])); - - for (i = 0; i < istop; i++) - { - *bp >>= shift[0]; - *bp++ &= mask; - } - break; - } - case 8: - { - png_bytep bp = row; - png_uint_32 i; - png_uint_32 istop = row_width * channels; - - for (i = 0; i < istop; i++) - { - *bp++ >>= shift[i%channels]; - } - break; - } - case 16: - { - png_bytep bp = row; - png_uint_32 i; - png_uint_32 istop = channels * row_width; - - for (i = 0; i < istop; i++) - { - value = (png_uint_16)((*bp << 8) + *(bp + 1)); - value >>= shift[i%channels]; - *bp++ = (png_byte)(value >> 8); - *bp++ = (png_byte)(value & 0xff); - } - break; - } - } - } -} -#endif - -#if defined(PNG_READ_16_TO_8_SUPPORTED) -/* chop rows of bit depth 16 down to 8 */ -void /* PRIVATE */ -png_do_chop(png_row_infop row_info, png_bytep row) -{ - png_debug(1, "in png_do_chop\n"); -#if defined(PNG_USELESS_TESTS_SUPPORTED) - if (row != NULL && row_info != NULL && row_info->bit_depth == 16) -#else - if (row_info->bit_depth == 16) -#endif - { - png_bytep sp = row; - png_bytep dp = row; - png_uint_32 i; - png_uint_32 istop = row_info->width * row_info->channels; - - for (i = 0; i> 8)) >> 8; - * - * Approximate calculation with shift/add instead of multiply/divide: - * *dp = ((((png_uint_32)(*sp) << 8) | - * (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8; - * - * What we actually do to avoid extra shifting and conversion: - */ - - *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0); -#else - /* Simply discard the low order byte */ - *dp = *sp; -#endif - } - row_info->bit_depth = 8; - row_info->pixel_depth = (png_byte)(8 * row_info->channels); - row_info->rowbytes = row_info->width * row_info->channels; - } -} -#endif - -#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) -void /* PRIVATE */ -png_do_read_swap_alpha(png_row_infop row_info, png_bytep row) -{ - png_debug(1, "in png_do_read_swap_alpha\n"); -#if defined(PNG_USELESS_TESTS_SUPPORTED) - if (row != NULL && row_info != NULL) -#endif - { - png_uint_32 row_width = row_info->width; - if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - { - /* This converts from RGBA to ARGB */ - if (row_info->bit_depth == 8) - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_byte save; - png_uint_32 i; - - for (i = 0; i < row_width; i++) - { - save = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = save; - } - } - /* This converts from RRGGBBAA to AARRGGBB */ - else - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_byte save[2]; - png_uint_32 i; - - for (i = 0; i < row_width; i++) - { - save[0] = *(--sp); - save[1] = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = save[0]; - *(--dp) = save[1]; - } - } - } - else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - { - /* This converts from GA to AG */ - if (row_info->bit_depth == 8) - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_byte save; - png_uint_32 i; - - for (i = 0; i < row_width; i++) - { - save = *(--sp); - *(--dp) = *(--sp); - *(--dp) = save; - } - } - /* This converts from GGAA to AAGG */ - else - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_byte save[2]; - png_uint_32 i; - - for (i = 0; i < row_width; i++) - { - save[0] = *(--sp); - save[1] = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = save[0]; - *(--dp) = save[1]; - } - } - } - } -} -#endif - -#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) -void /* PRIVATE */ -png_do_read_invert_alpha(png_row_infop row_info, png_bytep row) -{ - png_debug(1, "in png_do_read_invert_alpha\n"); -#if defined(PNG_USELESS_TESTS_SUPPORTED) - if (row != NULL && row_info != NULL) -#endif - { - png_uint_32 row_width = row_info->width; - if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - { - /* This inverts the alpha channel in RGBA */ - if (row_info->bit_depth == 8) - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_uint_32 i; - - for (i = 0; i < row_width; i++) - { - *(--dp) = (png_byte)(255 - *(--sp)); - -/* This does nothing: - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - We can replace it with: -*/ - sp-=3; - dp=sp; - } - } - /* This inverts the alpha channel in RRGGBBAA */ - else - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_uint_32 i; - - for (i = 0; i < row_width; i++) - { - *(--dp) = (png_byte)(255 - *(--sp)); - *(--dp) = (png_byte)(255 - *(--sp)); - -/* This does nothing: - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - We can replace it with: -*/ - sp-=6; - dp=sp; - } - } - } - else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - { - /* This inverts the alpha channel in GA */ - if (row_info->bit_depth == 8) - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_uint_32 i; - - for (i = 0; i < row_width; i++) - { - *(--dp) = (png_byte)(255 - *(--sp)); - *(--dp) = *(--sp); - } - } - /* This inverts the alpha channel in GGAA */ - else - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_uint_32 i; - - for (i = 0; i < row_width; i++) - { - *(--dp) = (png_byte)(255 - *(--sp)); - *(--dp) = (png_byte)(255 - *(--sp)); -/* - *(--dp) = *(--sp); - *(--dp) = *(--sp); -*/ - sp-=2; - dp=sp; - } - } - } - } -} -#endif - -#if defined(PNG_READ_FILLER_SUPPORTED) -/* Add filler channel if we have RGB color */ -void /* PRIVATE */ -png_do_read_filler(png_row_infop row_info, png_bytep row, - png_uint_32 filler, png_uint_32 flags) -{ - png_uint_32 i; - png_uint_32 row_width = row_info->width; - - png_byte hi_filler = (png_byte)((filler>>8) & 0xff); - png_byte lo_filler = (png_byte)(filler & 0xff); - - png_debug(1, "in png_do_read_filler\n"); - if ( -#if defined(PNG_USELESS_TESTS_SUPPORTED) - row != NULL && row_info != NULL && -#endif - row_info->color_type == PNG_COLOR_TYPE_GRAY) - { - if(row_info->bit_depth == 8) - { - /* This changes the data from G to GX */ - if (flags & PNG_FLAG_FILLER_AFTER) - { - png_bytep sp = row + (png_size_t)row_width; - png_bytep dp = sp + (png_size_t)row_width; - for (i = 1; i < row_width; i++) - { - *(--dp) = lo_filler; - *(--dp) = *(--sp); - } - *(--dp) = lo_filler; - row_info->channels = 2; - row_info->pixel_depth = 16; - row_info->rowbytes = row_width * 2; - } - /* This changes the data from G to XG */ - else - { - png_bytep sp = row + (png_size_t)row_width; - png_bytep dp = sp + (png_size_t)row_width; - for (i = 0; i < row_width; i++) - { - *(--dp) = *(--sp); - *(--dp) = lo_filler; - } - row_info->channels = 2; - row_info->pixel_depth = 16; - row_info->rowbytes = row_width * 2; - } - } - else if(row_info->bit_depth == 16) - { - /* This changes the data from GG to GGXX */ - if (flags & PNG_FLAG_FILLER_AFTER) - { - png_bytep sp = row + (png_size_t)row_width * 2; - png_bytep dp = sp + (png_size_t)row_width * 2; - for (i = 1; i < row_width; i++) - { - *(--dp) = hi_filler; - *(--dp) = lo_filler; - *(--dp) = *(--sp); - *(--dp) = *(--sp); - } - *(--dp) = hi_filler; - *(--dp) = lo_filler; - row_info->channels = 2; - row_info->pixel_depth = 32; - row_info->rowbytes = row_width * 4; - } - /* This changes the data from GG to XXGG */ - else - { - png_bytep sp = row + (png_size_t)row_width * 2; - png_bytep dp = sp + (png_size_t)row_width * 2; - for (i = 0; i < row_width; i++) - { - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = hi_filler; - *(--dp) = lo_filler; - } - row_info->channels = 2; - row_info->pixel_depth = 32; - row_info->rowbytes = row_width * 4; - } - } - } /* COLOR_TYPE == GRAY */ - else if (row_info->color_type == PNG_COLOR_TYPE_RGB) - { - if(row_info->bit_depth == 8) - { - /* This changes the data from RGB to RGBX */ - if (flags & PNG_FLAG_FILLER_AFTER) - { - png_bytep sp = row + (png_size_t)row_width * 3; - png_bytep dp = sp + (png_size_t)row_width; - for (i = 1; i < row_width; i++) - { - *(--dp) = lo_filler; - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - } - *(--dp) = lo_filler; - row_info->channels = 4; - row_info->pixel_depth = 32; - row_info->rowbytes = row_width * 4; - } - /* This changes the data from RGB to XRGB */ - else - { - png_bytep sp = row + (png_size_t)row_width * 3; - png_bytep dp = sp + (png_size_t)row_width; - for (i = 0; i < row_width; i++) - { - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = lo_filler; - } - row_info->channels = 4; - row_info->pixel_depth = 32; - row_info->rowbytes = row_width * 4; - } - } - else if(row_info->bit_depth == 16) - { - /* This changes the data from RRGGBB to RRGGBBXX */ - if (flags & PNG_FLAG_FILLER_AFTER) - { - png_bytep sp = row + (png_size_t)row_width * 6; - png_bytep dp = sp + (png_size_t)row_width * 2; - for (i = 1; i < row_width; i++) - { - *(--dp) = hi_filler; - *(--dp) = lo_filler; - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - } - *(--dp) = hi_filler; - *(--dp) = lo_filler; - row_info->channels = 4; - row_info->pixel_depth = 64; - row_info->rowbytes = row_width * 8; - } - /* This changes the data from RRGGBB to XXRRGGBB */ - else - { - png_bytep sp = row + (png_size_t)row_width * 6; - png_bytep dp = sp + (png_size_t)row_width * 2; - for (i = 0; i < row_width; i++) - { - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = hi_filler; - *(--dp) = lo_filler; - } - row_info->channels = 4; - row_info->pixel_depth = 64; - row_info->rowbytes = row_width * 8; - } - } - } /* COLOR_TYPE == RGB */ -} -#endif - -#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) -/* expand grayscale files to RGB, with or without alpha */ -void /* PRIVATE */ -png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) -{ - png_uint_32 i; - png_uint_32 row_width = row_info->width; - - png_debug(1, "in png_do_gray_to_rgb\n"); - if (row_info->bit_depth >= 8 && -#if defined(PNG_USELESS_TESTS_SUPPORTED) - row != NULL && row_info != NULL && -#endif - !(row_info->color_type & PNG_COLOR_MASK_COLOR)) - { - if (row_info->color_type == PNG_COLOR_TYPE_GRAY) - { - if (row_info->bit_depth == 8) - { - png_bytep sp = row + (png_size_t)row_width - 1; - png_bytep dp = sp + (png_size_t)row_width * 2; - for (i = 0; i < row_width; i++) - { - *(dp--) = *sp; - *(dp--) = *sp; - *(dp--) = *(sp--); - } - } - else - { - png_bytep sp = row + (png_size_t)row_width * 2 - 1; - png_bytep dp = sp + (png_size_t)row_width * 4; - for (i = 0; i < row_width; i++) - { - *(dp--) = *sp; - *(dp--) = *(sp - 1); - *(dp--) = *sp; - *(dp--) = *(sp - 1); - *(dp--) = *(sp--); - *(dp--) = *(sp--); - } - } - } - else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - { - if (row_info->bit_depth == 8) - { - png_bytep sp = row + (png_size_t)row_width * 2 - 1; - png_bytep dp = sp + (png_size_t)row_width * 2; - for (i = 0; i < row_width; i++) - { - *(dp--) = *(sp--); - *(dp--) = *sp; - *(dp--) = *sp; - *(dp--) = *(sp--); - } - } - else - { - png_bytep sp = row + (png_size_t)row_width * 4 - 1; - png_bytep dp = sp + (png_size_t)row_width * 4; - for (i = 0; i < row_width; i++) - { - *(dp--) = *(sp--); - *(dp--) = *(sp--); - *(dp--) = *sp; - *(dp--) = *(sp - 1); - *(dp--) = *sp; - *(dp--) = *(sp - 1); - *(dp--) = *(sp--); - *(dp--) = *(sp--); - } - } - } - row_info->channels += (png_byte)2; - row_info->color_type |= PNG_COLOR_MASK_COLOR; - row_info->pixel_depth = (png_byte)(row_info->channels * - row_info->bit_depth); - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width); - } -} -#endif - -#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) -/* reduce RGB files to grayscale, with or without alpha - * using the equation given in Poynton's ColorFAQ at - * - * Copyright (c) 1998-01-04 Charles Poynton poynton at inforamp.net - * - * Y = 0.212671 * R + 0.715160 * G + 0.072169 * B - * - * We approximate this with - * - * Y = 0.21268 * R + 0.7151 * G + 0.07217 * B - * - * which can be expressed with integers as - * - * Y = (6969 * R + 23434 * G + 2365 * B)/32768 - * - * The calculation is to be done in a linear colorspace. - * - * Other integer coefficents can be used via png_set_rgb_to_gray(). - */ -int /* PRIVATE */ -png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row) - -{ - png_uint_32 i; - - png_uint_32 row_width = row_info->width; - int rgb_error = 0; - - png_debug(1, "in png_do_rgb_to_gray\n"); - if ( -#if defined(PNG_USELESS_TESTS_SUPPORTED) - row != NULL && row_info != NULL && -#endif - (row_info->color_type & PNG_COLOR_MASK_COLOR)) - { - png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff; - png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff; - png_uint_32 bc = png_ptr->rgb_to_gray_blue_coeff; - - if (row_info->color_type == PNG_COLOR_TYPE_RGB) - { - if (row_info->bit_depth == 8) - { -#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) - { - png_bytep sp = row; - png_bytep dp = row; - - for (i = 0; i < row_width; i++) - { - png_byte red = png_ptr->gamma_to_1[*(sp++)]; - png_byte green = png_ptr->gamma_to_1[*(sp++)]; - png_byte blue = png_ptr->gamma_to_1[*(sp++)]; - if(red != green || red != blue) - { - rgb_error |= 1; - *(dp++) = png_ptr->gamma_from_1[ - (rc*red+gc*green+bc*blue)>>15]; - } - else - *(dp++) = *(sp-1); - } - } - else -#endif - { - png_bytep sp = row; - png_bytep dp = row; - for (i = 0; i < row_width; i++) - { - png_byte red = *(sp++); - png_byte green = *(sp++); - png_byte blue = *(sp++); - if(red != green || red != blue) - { - rgb_error |= 1; - *(dp++) = (png_byte)((rc*red+gc*green+bc*blue)>>15); - } - else - *(dp++) = *(sp-1); - } - } - } - - else /* RGB bit_depth == 16 */ - { -#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - if (png_ptr->gamma_16_to_1 != NULL && - png_ptr->gamma_16_from_1 != NULL) - { - png_bytep sp = row; - png_bytep dp = row; - for (i = 0; i < row_width; i++) - { - png_uint_16 red, green, blue, w; - - red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; - green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; - blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; - - if(red == green && red == blue) - w = red; - else - { - png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >> - png_ptr->gamma_shift][red>>8]; - png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >> - png_ptr->gamma_shift][green>>8]; - png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >> - png_ptr->gamma_shift][blue>>8]; - png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_1 - + bc*blue_1)>>15); - w = png_ptr->gamma_16_from_1[(gray16&0xff) >> - png_ptr->gamma_shift][gray16 >> 8]; - rgb_error |= 1; - } - - *(dp++) = (png_byte)((w>>8) & 0xff); - *(dp++) = (png_byte)(w & 0xff); - } - } - else -#endif - { - png_bytep sp = row; - png_bytep dp = row; - for (i = 0; i < row_width; i++) - { - png_uint_16 red, green, blue, gray16; - - red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; - green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; - blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; - - if(red != green || red != blue) - rgb_error |= 1; - gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15); - *(dp++) = (png_byte)((gray16>>8) & 0xff); - *(dp++) = (png_byte)(gray16 & 0xff); - } - } - } - } - if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - { - if (row_info->bit_depth == 8) - { -#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) - { - png_bytep sp = row; - png_bytep dp = row; - for (i = 0; i < row_width; i++) - { - png_byte red = png_ptr->gamma_to_1[*(sp++)]; - png_byte green = png_ptr->gamma_to_1[*(sp++)]; - png_byte blue = png_ptr->gamma_to_1[*(sp++)]; - if(red != green || red != blue) - rgb_error |= 1; - *(dp++) = png_ptr->gamma_from_1 - [(rc*red + gc*green + bc*blue)>>15]; - *(dp++) = *(sp++); /* alpha */ - } - } - else -#endif - { - png_bytep sp = row; - png_bytep dp = row; - for (i = 0; i < row_width; i++) - { - png_byte red = *(sp++); - png_byte green = *(sp++); - png_byte blue = *(sp++); - if(red != green || red != blue) - rgb_error |= 1; - *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15); - *(dp++) = *(sp++); /* alpha */ - } - } - } - else /* RGBA bit_depth == 16 */ - { -#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - if (png_ptr->gamma_16_to_1 != NULL && - png_ptr->gamma_16_from_1 != NULL) - { - png_bytep sp = row; - png_bytep dp = row; - for (i = 0; i < row_width; i++) - { - png_uint_16 red, green, blue, w; - - red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; - green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; - blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2; - - if(red == green && red == blue) - w = red; - else - { - png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >> - png_ptr->gamma_shift][red>>8]; - png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >> - png_ptr->gamma_shift][green>>8]; - png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >> - png_ptr->gamma_shift][blue>>8]; - png_uint_16 gray16 = (png_uint_16)((rc * red_1 - + gc * green_1 + bc * blue_1)>>15); - w = png_ptr->gamma_16_from_1[(gray16&0xff) >> - png_ptr->gamma_shift][gray16 >> 8]; - rgb_error |= 1; - } - - *(dp++) = (png_byte)((w>>8) & 0xff); - *(dp++) = (png_byte)(w & 0xff); - *(dp++) = *(sp++); /* alpha */ - *(dp++) = *(sp++); - } - } - else -#endif - { - png_bytep sp = row; - png_bytep dp = row; - for (i = 0; i < row_width; i++) - { - png_uint_16 red, green, blue, gray16; - red = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2; - green = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2; - blue = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2; - if(red != green || red != blue) - rgb_error |= 1; - gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15); - *(dp++) = (png_byte)((gray16>>8) & 0xff); - *(dp++) = (png_byte)(gray16 & 0xff); - *(dp++) = *(sp++); /* alpha */ - *(dp++) = *(sp++); - } - } - } - } - row_info->channels -= (png_byte)2; - row_info->color_type &= ~PNG_COLOR_MASK_COLOR; - row_info->pixel_depth = (png_byte)(row_info->channels * - row_info->bit_depth); - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width); - } - return rgb_error; -} -#endif - -/* Build a grayscale palette. Palette is assumed to be 1 << bit_depth - * large of png_color. This lets grayscale images be treated as - * paletted. Most useful for gamma correction and simplification - * of code. - */ -void PNGAPI -png_build_grayscale_palette(int bit_depth, png_colorp palette) -{ - int num_palette; - int color_inc; - int i; - int v; - - png_debug(1, "in png_do_build_grayscale_palette\n"); - if (palette == NULL) - return; - - switch (bit_depth) - { - case 1: - num_palette = 2; - color_inc = 0xff; - break; - case 2: - num_palette = 4; - color_inc = 0x55; - break; - case 4: - num_palette = 16; - color_inc = 0x11; - break; - case 8: - num_palette = 256; - color_inc = 1; - break; - default: - num_palette = 0; - color_inc = 0; - break; - } - - for (i = 0, v = 0; i < num_palette; i++, v += color_inc) - { - palette[i].red = (png_byte)v; - palette[i].green = (png_byte)v; - palette[i].blue = (png_byte)v; - } -} - -/* This function is currently unused. Do we really need it? */ -#if defined(PNG_READ_DITHER_SUPPORTED) && defined(PNG_CORRECT_PALETTE_SUPPORTED) -void /* PRIVATE */ -png_correct_palette(png_structp png_ptr, png_colorp palette, - int num_palette) -{ - png_debug(1, "in png_correct_palette\n"); -#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ - defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED) - if (png_ptr->transformations & (PNG_GAMMA | PNG_BACKGROUND)) - { - png_color back, back_1; - - if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE) - { - back.red = png_ptr->gamma_table[png_ptr->background.red]; - back.green = png_ptr->gamma_table[png_ptr->background.green]; - back.blue = png_ptr->gamma_table[png_ptr->background.blue]; - - back_1.red = png_ptr->gamma_to_1[png_ptr->background.red]; - back_1.green = png_ptr->gamma_to_1[png_ptr->background.green]; - back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue]; - } - else - { - double g; - - g = 1.0 / (png_ptr->background_gamma * png_ptr->screen_gamma); - - if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_SCREEN || - fabs(g - 1.0) < PNG_GAMMA_THRESHOLD) - { - back.red = png_ptr->background.red; - back.green = png_ptr->background.green; - back.blue = png_ptr->background.blue; - } - else - { - back.red = - (png_byte)(pow((double)png_ptr->background.red/255, g) * - 255.0 + 0.5); - back.green = - (png_byte)(pow((double)png_ptr->background.green/255, g) * - 255.0 + 0.5); - back.blue = - (png_byte)(pow((double)png_ptr->background.blue/255, g) * - 255.0 + 0.5); - } - - g = 1.0 / png_ptr->background_gamma; - - back_1.red = - (png_byte)(pow((double)png_ptr->background.red/255, g) * - 255.0 + 0.5); - back_1.green = - (png_byte)(pow((double)png_ptr->background.green/255, g) * - 255.0 + 0.5); - back_1.blue = - (png_byte)(pow((double)png_ptr->background.blue/255, g) * - 255.0 + 0.5); - } - - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - { - png_uint_32 i; - - for (i = 0; i < (png_uint_32)num_palette; i++) - { - if (i < png_ptr->num_trans && png_ptr->trans[i] == 0) - { - palette[i] = back; - } - else if (i < png_ptr->num_trans && png_ptr->trans[i] != 0xff) - { - png_byte v, w; - - v = png_ptr->gamma_to_1[png_ptr->palette[i].red]; - png_composite(w, v, png_ptr->trans[i], back_1.red); - palette[i].red = png_ptr->gamma_from_1[w]; - - v = png_ptr->gamma_to_1[png_ptr->palette[i].green]; - png_composite(w, v, png_ptr->trans[i], back_1.green); - palette[i].green = png_ptr->gamma_from_1[w]; - - v = png_ptr->gamma_to_1[png_ptr->palette[i].blue]; - png_composite(w, v, png_ptr->trans[i], back_1.blue); - palette[i].blue = png_ptr->gamma_from_1[w]; - } - else - { - palette[i].red = png_ptr->gamma_table[palette[i].red]; - palette[i].green = png_ptr->gamma_table[palette[i].green]; - palette[i].blue = png_ptr->gamma_table[palette[i].blue]; - } - } - } - else - { - int i; - - for (i = 0; i < num_palette; i++) - { - if (palette[i].red == (png_byte)png_ptr->trans_values.gray) - { - palette[i] = back; - } - else - { - palette[i].red = png_ptr->gamma_table[palette[i].red]; - palette[i].green = png_ptr->gamma_table[palette[i].green]; - palette[i].blue = png_ptr->gamma_table[palette[i].blue]; - } - } - } - } - else -#endif -#if defined(PNG_READ_GAMMA_SUPPORTED) - if (png_ptr->transformations & PNG_GAMMA) - { - int i; - - for (i = 0; i < num_palette; i++) - { - palette[i].red = png_ptr->gamma_table[palette[i].red]; - palette[i].green = png_ptr->gamma_table[palette[i].green]; - palette[i].blue = png_ptr->gamma_table[palette[i].blue]; - } - } -#if defined(PNG_READ_BACKGROUND_SUPPORTED) - else -#endif -#endif -#if defined(PNG_READ_BACKGROUND_SUPPORTED) - if (png_ptr->transformations & PNG_BACKGROUND) - { - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - { - png_color back; - - back.red = (png_byte)png_ptr->background.red; - back.green = (png_byte)png_ptr->background.green; - back.blue = (png_byte)png_ptr->background.blue; - - for (i = 0; i < (int)png_ptr->num_trans; i++) - { - if (png_ptr->trans[i] == 0) - { - palette[i].red = back.red; - palette[i].green = back.green; - palette[i].blue = back.blue; - } - else if (png_ptr->trans[i] != 0xff) - { - png_composite(palette[i].red, png_ptr->palette[i].red, - png_ptr->trans[i], back.red); - png_composite(palette[i].green, png_ptr->palette[i].green, - png_ptr->trans[i], back.green); - png_composite(palette[i].blue, png_ptr->palette[i].blue, - png_ptr->trans[i], back.blue); - } - } - } - else /* assume grayscale palette (what else could it be?) */ - { - int i; - - for (i = 0; i < num_palette; i++) - { - if (i == (png_byte)png_ptr->trans_values.gray) - { - palette[i].red = (png_byte)png_ptr->background.red; - palette[i].green = (png_byte)png_ptr->background.green; - palette[i].blue = (png_byte)png_ptr->background.blue; - } - } - } - } -#endif -} -#endif - -#if defined(PNG_READ_BACKGROUND_SUPPORTED) -/* Replace any alpha or transparency with the supplied background color. - * "background" is already in the screen gamma, while "background_1" is - * at a gamma of 1.0. Paletted files have already been taken care of. - */ -void /* PRIVATE */ -png_do_background(png_row_infop row_info, png_bytep row, - png_color_16p trans_values, png_color_16p background -#if defined(PNG_READ_GAMMA_SUPPORTED) - , png_color_16p background_1, - png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1, - png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1, - png_uint_16pp gamma_16_to_1, int gamma_shift -#endif - ) -{ - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width=row_info->width; - int shift; - - png_debug(1, "in png_do_background\n"); - if (background != NULL && -#if defined(PNG_USELESS_TESTS_SUPPORTED) - row != NULL && row_info != NULL && -#endif - (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) || - (row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_values))) - { - switch (row_info->color_type) - { - case PNG_COLOR_TYPE_GRAY: - { - switch (row_info->bit_depth) - { - case 1: - { - sp = row; - shift = 7; - for (i = 0; i < row_width; i++) - { - if ((png_uint_16)((*sp >> shift) & 0x01) - == trans_values->gray) - { - *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff); - *sp |= (png_byte)(background->gray << shift); - } - if (!shift) - { - shift = 7; - sp++; - } - else - shift--; - } - break; - } - case 2: - { -#if defined(PNG_READ_GAMMA_SUPPORTED) - if (gamma_table != NULL) - { - sp = row; - shift = 6; - for (i = 0; i < row_width; i++) - { - if ((png_uint_16)((*sp >> shift) & 0x03) - == trans_values->gray) - { - *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); - *sp |= (png_byte)(background->gray << shift); - } - else - { - png_byte p = (png_byte)((*sp >> shift) & 0x03); - png_byte g = (png_byte)((gamma_table [p | (p << 2) | - (p << 4) | (p << 6)] >> 6) & 0x03); - *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); - *sp |= (png_byte)(g << shift); - } - if (!shift) - { - shift = 6; - sp++; - } - else - shift -= 2; - } - } - else -#endif - { - sp = row; - shift = 6; - for (i = 0; i < row_width; i++) - { - if ((png_uint_16)((*sp >> shift) & 0x03) - == trans_values->gray) - { - *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); - *sp |= (png_byte)(background->gray << shift); - } - if (!shift) - { - shift = 6; - sp++; - } - else - shift -= 2; - } - } - break; - } - case 4: - { -#if defined(PNG_READ_GAMMA_SUPPORTED) - if (gamma_table != NULL) - { - sp = row; - shift = 4; - for (i = 0; i < row_width; i++) - { - if ((png_uint_16)((*sp >> shift) & 0x0f) - == trans_values->gray) - { - *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); - *sp |= (png_byte)(background->gray << shift); - } - else - { - png_byte p = (png_byte)((*sp >> shift) & 0x0f); - png_byte g = (png_byte)((gamma_table[p | - (p << 4)] >> 4) & 0x0f); - *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); - *sp |= (png_byte)(g << shift); - } - if (!shift) - { - shift = 4; - sp++; - } - else - shift -= 4; - } - } - else -#endif - { - sp = row; - shift = 4; - for (i = 0; i < row_width; i++) - { - if ((png_uint_16)((*sp >> shift) & 0x0f) - == trans_values->gray) - { - *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); - *sp |= (png_byte)(background->gray << shift); - } - if (!shift) - { - shift = 4; - sp++; - } - else - shift -= 4; - } - } - break; - } - case 8: - { -#if defined(PNG_READ_GAMMA_SUPPORTED) - if (gamma_table != NULL) - { - sp = row; - for (i = 0; i < row_width; i++, sp++) - { - if (*sp == trans_values->gray) - { - *sp = (png_byte)background->gray; - } - else - { - *sp = gamma_table[*sp]; - } - } - } - else -#endif - { - sp = row; - for (i = 0; i < row_width; i++, sp++) - { - if (*sp == trans_values->gray) - { - *sp = (png_byte)background->gray; - } - } - } - break; - } - case 16: - { -#if defined(PNG_READ_GAMMA_SUPPORTED) - if (gamma_16 != NULL) - { - sp = row; - for (i = 0; i < row_width; i++, sp += 2) - { - png_uint_16 v; - - v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - if (v == trans_values->gray) - { - /* background is already in screen gamma */ - *sp = (png_byte)((background->gray >> 8) & 0xff); - *(sp + 1) = (png_byte)(background->gray & 0xff); - } - else - { - v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - } - } - } - else -#endif - { - sp = row; - for (i = 0; i < row_width; i++, sp += 2) - { - png_uint_16 v; - - v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - if (v == trans_values->gray) - { - *sp = (png_byte)((background->gray >> 8) & 0xff); - *(sp + 1) = (png_byte)(background->gray & 0xff); - } - } - } - break; - } - } - break; - } - case PNG_COLOR_TYPE_RGB: - { - if (row_info->bit_depth == 8) - { -#if defined(PNG_READ_GAMMA_SUPPORTED) - if (gamma_table != NULL) - { - sp = row; - for (i = 0; i < row_width; i++, sp += 3) - { - if (*sp == trans_values->red && - *(sp + 1) == trans_values->green && - *(sp + 2) == trans_values->blue) - { - *sp = (png_byte)background->red; - *(sp + 1) = (png_byte)background->green; - *(sp + 2) = (png_byte)background->blue; - } - else - { - *sp = gamma_table[*sp]; - *(sp + 1) = gamma_table[*(sp + 1)]; - *(sp + 2) = gamma_table[*(sp + 2)]; - } - } - } - else -#endif - { - sp = row; - for (i = 0; i < row_width; i++, sp += 3) - { - if (*sp == trans_values->red && - *(sp + 1) == trans_values->green && - *(sp + 2) == trans_values->blue) - { - *sp = (png_byte)background->red; - *(sp + 1) = (png_byte)background->green; - *(sp + 2) = (png_byte)background->blue; - } - } - } - } - else /* if (row_info->bit_depth == 16) */ - { -#if defined(PNG_READ_GAMMA_SUPPORTED) - if (gamma_16 != NULL) - { - sp = row; - for (i = 0; i < row_width; i++, sp += 6) - { - png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); - png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5)); - if (r == trans_values->red && g == trans_values->green && - b == trans_values->blue) - { - /* background is already in screen gamma */ - *sp = (png_byte)((background->red >> 8) & 0xff); - *(sp + 1) = (png_byte)(background->red & 0xff); - *(sp + 2) = (png_byte)((background->green >> 8) & 0xff); - *(sp + 3) = (png_byte)(background->green & 0xff); - *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff); - *(sp + 5) = (png_byte)(background->blue & 0xff); - } - else - { - png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; - *(sp + 2) = (png_byte)((v >> 8) & 0xff); - *(sp + 3) = (png_byte)(v & 0xff); - v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; - *(sp + 4) = (png_byte)((v >> 8) & 0xff); - *(sp + 5) = (png_byte)(v & 0xff); - } - } - } - else -#endif - { - sp = row; - for (i = 0; i < row_width; i++, sp += 6) - { - png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp+1)); - png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); - png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5)); - - if (r == trans_values->red && g == trans_values->green && - b == trans_values->blue) - { - *sp = (png_byte)((background->red >> 8) & 0xff); - *(sp + 1) = (png_byte)(background->red & 0xff); - *(sp + 2) = (png_byte)((background->green >> 8) & 0xff); - *(sp + 3) = (png_byte)(background->green & 0xff); - *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff); - *(sp + 5) = (png_byte)(background->blue & 0xff); - } - } - } - } - break; - } - case PNG_COLOR_TYPE_GRAY_ALPHA: - { - if (row_info->bit_depth == 8) - { -#if defined(PNG_READ_GAMMA_SUPPORTED) - if (gamma_to_1 != NULL && gamma_from_1 != NULL && - gamma_table != NULL) - { - sp = row; - dp = row; - for (i = 0; i < row_width; i++, sp += 2, dp++) - { - png_uint_16 a = *(sp + 1); - - if (a == 0xff) - { - *dp = gamma_table[*sp]; - } - else if (a == 0) - { - /* background is already in screen gamma */ - *dp = (png_byte)background->gray; - } - else - { - png_byte v, w; - - v = gamma_to_1[*sp]; - png_composite(w, v, a, background_1->gray); - *dp = gamma_from_1[w]; - } - } - } - else -#endif - { - sp = row; - dp = row; - for (i = 0; i < row_width; i++, sp += 2, dp++) - { - png_byte a = *(sp + 1); - - if (a == 0xff) - { - *dp = *sp; - } -#if defined(PNG_READ_GAMMA_SUPPORTED) - else if (a == 0) - { - *dp = (png_byte)background->gray; - } - else - { - png_composite(*dp, *sp, a, background_1->gray); - } -#else - *dp = (png_byte)background->gray; -#endif - } - } - } - else /* if (png_ptr->bit_depth == 16) */ - { -#if defined(PNG_READ_GAMMA_SUPPORTED) - if (gamma_16 != NULL && gamma_16_from_1 != NULL && - gamma_16_to_1 != NULL) - { - sp = row; - dp = row; - for (i = 0; i < row_width; i++, sp += 4, dp += 2) - { - png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); - - if (a == (png_uint_16)0xffff) - { - png_uint_16 v; - - v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; - *dp = (png_byte)((v >> 8) & 0xff); - *(dp + 1) = (png_byte)(v & 0xff); - } -#if defined(PNG_READ_GAMMA_SUPPORTED) - else if (a == 0) -#else - else -#endif - { - /* background is already in screen gamma */ - *dp = (png_byte)((background->gray >> 8) & 0xff); - *(dp + 1) = (png_byte)(background->gray & 0xff); - } -#if defined(PNG_READ_GAMMA_SUPPORTED) - else - { - png_uint_16 g, v, w; - - g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; - png_composite_16(v, g, a, background_1->gray); - w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8]; - *dp = (png_byte)((w >> 8) & 0xff); - *(dp + 1) = (png_byte)(w & 0xff); - } -#endif - } - } - else -#endif - { - sp = row; - dp = row; - for (i = 0; i < row_width; i++, sp += 4, dp += 2) - { - png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3)); - if (a == (png_uint_16)0xffff) - { - png_memcpy(dp, sp, 2); - } -#if defined(PNG_READ_GAMMA_SUPPORTED) - else if (a == 0) -#else - else -#endif - { - *dp = (png_byte)((background->gray >> 8) & 0xff); - *(dp + 1) = (png_byte)(background->gray & 0xff); - } -#if defined(PNG_READ_GAMMA_SUPPORTED) - else - { - png_uint_16 g, v; - - g = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - png_composite_16(v, g, a, background_1->gray); - *dp = (png_byte)((v >> 8) & 0xff); - *(dp + 1) = (png_byte)(v & 0xff); - } -#endif - } - } - } - break; - } - case PNG_COLOR_TYPE_RGB_ALPHA: - { - if (row_info->bit_depth == 8) - { -#if defined(PNG_READ_GAMMA_SUPPORTED) - if (gamma_to_1 != NULL && gamma_from_1 != NULL && - gamma_table != NULL) - { - sp = row; - dp = row; - for (i = 0; i < row_width; i++, sp += 4, dp += 3) - { - png_byte a = *(sp + 3); - - if (a == 0xff) - { - *dp = gamma_table[*sp]; - *(dp + 1) = gamma_table[*(sp + 1)]; - *(dp + 2) = gamma_table[*(sp + 2)]; - } - else if (a == 0) - { - /* background is already in screen gamma */ - *dp = (png_byte)background->red; - *(dp + 1) = (png_byte)background->green; - *(dp + 2) = (png_byte)background->blue; - } - else - { - png_byte v, w; - - v = gamma_to_1[*sp]; - png_composite(w, v, a, background_1->red); - *dp = gamma_from_1[w]; - v = gamma_to_1[*(sp + 1)]; - png_composite(w, v, a, background_1->green); - *(dp + 1) = gamma_from_1[w]; - v = gamma_to_1[*(sp + 2)]; - png_composite(w, v, a, background_1->blue); - *(dp + 2) = gamma_from_1[w]; - } - } - } - else -#endif - { - sp = row; - dp = row; - for (i = 0; i < row_width; i++, sp += 4, dp += 3) - { - png_byte a = *(sp + 3); - - if (a == 0xff) - { - *dp = *sp; - *(dp + 1) = *(sp + 1); - *(dp + 2) = *(sp + 2); - } - else if (a == 0) - { - *dp = (png_byte)background->red; - *(dp + 1) = (png_byte)background->green; - *(dp + 2) = (png_byte)background->blue; - } - else - { - png_composite(*dp, *sp, a, background->red); - png_composite(*(dp + 1), *(sp + 1), a, - background->green); - png_composite(*(dp + 2), *(sp + 2), a, - background->blue); - } - } - } - } - else /* if (row_info->bit_depth == 16) */ - { -#if defined(PNG_READ_GAMMA_SUPPORTED) - if (gamma_16 != NULL && gamma_16_from_1 != NULL && - gamma_16_to_1 != NULL) - { - sp = row; - dp = row; - for (i = 0; i < row_width; i++, sp += 8, dp += 6) - { - png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) - << 8) + (png_uint_16)(*(sp + 7))); - if (a == (png_uint_16)0xffff) - { - png_uint_16 v; - - v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; - *dp = (png_byte)((v >> 8) & 0xff); - *(dp + 1) = (png_byte)(v & 0xff); - v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; - *(dp + 2) = (png_byte)((v >> 8) & 0xff); - *(dp + 3) = (png_byte)(v & 0xff); - v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; - *(dp + 4) = (png_byte)((v >> 8) & 0xff); - *(dp + 5) = (png_byte)(v & 0xff); - } - else if (a == 0) - { - /* background is already in screen gamma */ - *dp = (png_byte)((background->red >> 8) & 0xff); - *(dp + 1) = (png_byte)(background->red & 0xff); - *(dp + 2) = (png_byte)((background->green >> 8) & 0xff); - *(dp + 3) = (png_byte)(background->green & 0xff); - *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff); - *(dp + 5) = (png_byte)(background->blue & 0xff); - } - else - { - png_uint_16 v, w, x; - - v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; - png_composite_16(w, v, a, background_1->red); - x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; - *dp = (png_byte)((x >> 8) & 0xff); - *(dp + 1) = (png_byte)(x & 0xff); - v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)]; - png_composite_16(w, v, a, background_1->green); - x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; - *(dp + 2) = (png_byte)((x >> 8) & 0xff); - *(dp + 3) = (png_byte)(x & 0xff); - v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)]; - png_composite_16(w, v, a, background_1->blue); - x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8]; - *(dp + 4) = (png_byte)((x >> 8) & 0xff); - *(dp + 5) = (png_byte)(x & 0xff); - } - } - } - else -#endif - { - sp = row; - dp = row; - for (i = 0; i < row_width; i++, sp += 8, dp += 6) - { - png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) - << 8) + (png_uint_16)(*(sp + 7))); - if (a == (png_uint_16)0xffff) - { - png_memcpy(dp, sp, 6); - } - else if (a == 0) - { - *dp = (png_byte)((background->red >> 8) & 0xff); - *(dp + 1) = (png_byte)(background->red & 0xff); - *(dp + 2) = (png_byte)((background->green >> 8) & 0xff); - *(dp + 3) = (png_byte)(background->green & 0xff); - *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff); - *(dp + 5) = (png_byte)(background->blue & 0xff); - } - else - { - png_uint_16 v; - - png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) - + *(sp + 3)); - png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) - + *(sp + 5)); - - png_composite_16(v, r, a, background->red); - *dp = (png_byte)((v >> 8) & 0xff); - *(dp + 1) = (png_byte)(v & 0xff); - png_composite_16(v, g, a, background->green); - *(dp + 2) = (png_byte)((v >> 8) & 0xff); - *(dp + 3) = (png_byte)(v & 0xff); - png_composite_16(v, b, a, background->blue); - *(dp + 4) = (png_byte)((v >> 8) & 0xff); - *(dp + 5) = (png_byte)(v & 0xff); - } - } - } - } - break; - } - } - - if (row_info->color_type & PNG_COLOR_MASK_ALPHA) - { - row_info->color_type &= ~PNG_COLOR_MASK_ALPHA; - row_info->channels--; - row_info->pixel_depth = (png_byte)(row_info->channels * - row_info->bit_depth); - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width); - } - } -} -#endif - -#if defined(PNG_READ_GAMMA_SUPPORTED) -/* Gamma correct the image, avoiding the alpha channel. Make sure - * you do this after you deal with the transparency issue on grayscale - * or RGB images. If your bit depth is 8, use gamma_table, if it - * is 16, use gamma_16_table and gamma_shift. Build these with - * build_gamma_table(). - */ -void /* PRIVATE */ -png_do_gamma(png_row_infop row_info, png_bytep row, - png_bytep gamma_table, png_uint_16pp gamma_16_table, - int gamma_shift) -{ - png_bytep sp; - png_uint_32 i; - png_uint_32 row_width=row_info->width; - - png_debug(1, "in png_do_gamma\n"); - if ( -#if defined(PNG_USELESS_TESTS_SUPPORTED) - row != NULL && row_info != NULL && -#endif - ((row_info->bit_depth <= 8 && gamma_table != NULL) || - (row_info->bit_depth == 16 && gamma_16_table != NULL))) - { - switch (row_info->color_type) - { - case PNG_COLOR_TYPE_RGB: - { - if (row_info->bit_depth == 8) - { - sp = row; - for (i = 0; i < row_width; i++) - { - *sp = gamma_table[*sp]; - sp++; - *sp = gamma_table[*sp]; - sp++; - *sp = gamma_table[*sp]; - sp++; - } - } - else /* if (row_info->bit_depth == 16) */ - { - sp = row; - for (i = 0; i < row_width; i++) - { - png_uint_16 v; - - v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - sp += 2; - v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - sp += 2; - v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - sp += 2; - } - } - break; - } - case PNG_COLOR_TYPE_RGB_ALPHA: - { - if (row_info->bit_depth == 8) - { - sp = row; - for (i = 0; i < row_width; i++) - { - *sp = gamma_table[*sp]; - sp++; - *sp = gamma_table[*sp]; - sp++; - *sp = gamma_table[*sp]; - sp++; - sp++; - } - } - else /* if (row_info->bit_depth == 16) */ - { - sp = row; - for (i = 0; i < row_width; i++) - { - png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - sp += 2; - v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - sp += 2; - v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - sp += 4; - } - } - break; - } - case PNG_COLOR_TYPE_GRAY_ALPHA: - { - if (row_info->bit_depth == 8) - { - sp = row; - for (i = 0; i < row_width; i++) - { - *sp = gamma_table[*sp]; - sp += 2; - } - } - else /* if (row_info->bit_depth == 16) */ - { - sp = row; - for (i = 0; i < row_width; i++) - { - png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - sp += 4; - } - } - break; - } - case PNG_COLOR_TYPE_GRAY: - { - if (row_info->bit_depth == 2) - { - sp = row; - for (i = 0; i < row_width; i += 4) - { - int a = *sp & 0xc0; - int b = *sp & 0x30; - int c = *sp & 0x0c; - int d = *sp & 0x03; - - *sp = (png_byte)( - ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)]) ) & 0xc0)| - ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)| - ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)| - ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) )); - sp++; - } - } - if (row_info->bit_depth == 4) - { - sp = row; - for (i = 0; i < row_width; i += 2) - { - int msb = *sp & 0xf0; - int lsb = *sp & 0x0f; - - *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0) - | (((int)gamma_table[(lsb << 4) | lsb]) >> 4)); - sp++; - } - } - else if (row_info->bit_depth == 8) - { - sp = row; - for (i = 0; i < row_width; i++) - { - *sp = gamma_table[*sp]; - sp++; - } - } - else if (row_info->bit_depth == 16) - { - sp = row; - for (i = 0; i < row_width; i++) - { - png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - sp += 2; - } - } - break; - } - } - } -} -#endif - -#if defined(PNG_READ_EXPAND_SUPPORTED) -/* Expands a palette row to an RGB or RGBA row depending - * upon whether you supply trans and num_trans. - */ -void /* PRIVATE */ -png_do_expand_palette(png_row_infop row_info, png_bytep row, - png_colorp palette, png_bytep trans, int num_trans) -{ - int shift, value; - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width=row_info->width; - - png_debug(1, "in png_do_expand_palette\n"); - if ( -#if defined(PNG_USELESS_TESTS_SUPPORTED) - row != NULL && row_info != NULL && -#endif - row_info->color_type == PNG_COLOR_TYPE_PALETTE) - { - if (row_info->bit_depth < 8) - { - switch (row_info->bit_depth) - { - case 1: - { - sp = row + (png_size_t)((row_width - 1) >> 3); - dp = row + (png_size_t)row_width - 1; - shift = 7 - (int)((row_width + 7) & 0x07); - for (i = 0; i < row_width; i++) - { - if ((*sp >> shift) & 0x01) - *dp = 1; - else - *dp = 0; - if (shift == 7) - { - shift = 0; - sp--; - } - else - shift++; - - dp--; - } - break; - } - case 2: - { - sp = row + (png_size_t)((row_width - 1) >> 2); - dp = row + (png_size_t)row_width - 1; - shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); - for (i = 0; i < row_width; i++) - { - value = (*sp >> shift) & 0x03; - *dp = (png_byte)value; - if (shift == 6) - { - shift = 0; - sp--; - } - else - shift += 2; - - dp--; - } - break; - } - case 4: - { - sp = row + (png_size_t)((row_width - 1) >> 1); - dp = row + (png_size_t)row_width - 1; - shift = (int)((row_width & 0x01) << 2); - for (i = 0; i < row_width; i++) - { - value = (*sp >> shift) & 0x0f; - *dp = (png_byte)value; - if (shift == 4) - { - shift = 0; - sp--; - } - else - shift += 4; - - dp--; - } - break; - } - } - row_info->bit_depth = 8; - row_info->pixel_depth = 8; - row_info->rowbytes = row_width; - } - switch (row_info->bit_depth) - { - case 8: - { - if (trans != NULL) - { - sp = row + (png_size_t)row_width - 1; - dp = row + (png_size_t)(row_width << 2) - 1; - - for (i = 0; i < row_width; i++) - { - if ((int)(*sp) >= num_trans) - *dp-- = 0xff; - else - *dp-- = trans[*sp]; - *dp-- = palette[*sp].blue; - *dp-- = palette[*sp].green; - *dp-- = palette[*sp].red; - sp--; - } - row_info->bit_depth = 8; - row_info->pixel_depth = 32; - row_info->rowbytes = row_width * 4; - row_info->color_type = 6; - row_info->channels = 4; - } - else - { - sp = row + (png_size_t)row_width - 1; - dp = row + (png_size_t)(row_width * 3) - 1; - - for (i = 0; i < row_width; i++) - { - *dp-- = palette[*sp].blue; - *dp-- = palette[*sp].green; - *dp-- = palette[*sp].red; - sp--; - } - row_info->bit_depth = 8; - row_info->pixel_depth = 24; - row_info->rowbytes = row_width * 3; - row_info->color_type = 2; - row_info->channels = 3; - } - break; - } - } - } -} - -/* If the bit depth < 8, it is expanded to 8. Also, if the already - * expanded transparency value is supplied, an alpha channel is built. - */ -void /* PRIVATE */ -png_do_expand(png_row_infop row_info, png_bytep row, - png_color_16p trans_value) -{ - int shift, value; - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width=row_info->width; - - png_debug(1, "in png_do_expand\n"); -#if defined(PNG_USELESS_TESTS_SUPPORTED) - if (row != NULL && row_info != NULL) -#endif - { - if (row_info->color_type == PNG_COLOR_TYPE_GRAY) - { - png_uint_16 gray = (png_uint_16)(trans_value ? trans_value->gray : 0); - - if (row_info->bit_depth < 8) - { - switch (row_info->bit_depth) - { - case 1: - { - gray = (png_uint_16)((gray&0x01)*0xff); - sp = row + (png_size_t)((row_width - 1) >> 3); - dp = row + (png_size_t)row_width - 1; - shift = 7 - (int)((row_width + 7) & 0x07); - for (i = 0; i < row_width; i++) - { - if ((*sp >> shift) & 0x01) - *dp = 0xff; - else - *dp = 0; - if (shift == 7) - { - shift = 0; - sp--; - } - else - shift++; - - dp--; - } - break; - } - case 2: - { - gray = (png_uint_16)((gray&0x03)*0x55); - sp = row + (png_size_t)((row_width - 1) >> 2); - dp = row + (png_size_t)row_width - 1; - shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); - for (i = 0; i < row_width; i++) - { - value = (*sp >> shift) & 0x03; - *dp = (png_byte)(value | (value << 2) | (value << 4) | - (value << 6)); - if (shift == 6) - { - shift = 0; - sp--; - } - else - shift += 2; - - dp--; - } - break; - } - case 4: - { - gray = (png_uint_16)((gray&0x0f)*0x11); - sp = row + (png_size_t)((row_width - 1) >> 1); - dp = row + (png_size_t)row_width - 1; - shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); - for (i = 0; i < row_width; i++) - { - value = (*sp >> shift) & 0x0f; - *dp = (png_byte)(value | (value << 4)); - if (shift == 4) - { - shift = 0; - sp--; - } - else - shift = 4; - - dp--; - } - break; - } - } - row_info->bit_depth = 8; - row_info->pixel_depth = 8; - row_info->rowbytes = row_width; - } - - if (trans_value != NULL) - { - if (row_info->bit_depth == 8) - { - gray = gray & 0xff; - sp = row + (png_size_t)row_width - 1; - dp = row + (png_size_t)(row_width << 1) - 1; - for (i = 0; i < row_width; i++) - { - if (*sp == gray) - *dp-- = 0; - else - *dp-- = 0xff; - *dp-- = *sp--; - } - } - else if (row_info->bit_depth == 16) - { - png_byte gray_high = (gray >> 8) & 0xff; - png_byte gray_low = gray & 0xff; - sp = row + row_info->rowbytes - 1; - dp = row + (row_info->rowbytes << 1) - 1; - for (i = 0; i < row_width; i++) - { - if (*(sp-1) == gray_high && *(sp) == gray_low) - { - *dp-- = 0; - *dp-- = 0; - } - else - { - *dp-- = 0xff; - *dp-- = 0xff; - } - *dp-- = *sp--; - *dp-- = *sp--; - } - } - row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA; - row_info->channels = 2; - row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1); - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, - row_width); - } - } - else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value) - { - if (row_info->bit_depth == 8) - { - png_byte red = trans_value->red & 0xff; - png_byte green = trans_value->green & 0xff; - png_byte blue = trans_value->blue & 0xff; - sp = row + (png_size_t)row_info->rowbytes - 1; - dp = row + (png_size_t)(row_width << 2) - 1; - for (i = 0; i < row_width; i++) - { - if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue) - *dp-- = 0; - else - *dp-- = 0xff; - *dp-- = *sp--; - *dp-- = *sp--; - *dp-- = *sp--; - } - } - else if (row_info->bit_depth == 16) - { - png_byte red_high = (trans_value->red >> 8) & 0xff; - png_byte green_high = (trans_value->green >> 8) & 0xff; - png_byte blue_high = (trans_value->blue >> 8) & 0xff; - png_byte red_low = trans_value->red & 0xff; - png_byte green_low = trans_value->green & 0xff; - png_byte blue_low = trans_value->blue & 0xff; - sp = row + row_info->rowbytes - 1; - dp = row + (png_size_t)(row_width << 3) - 1; - for (i = 0; i < row_width; i++) - { - if (*(sp - 5) == red_high && - *(sp - 4) == red_low && - *(sp - 3) == green_high && - *(sp - 2) == green_low && - *(sp - 1) == blue_high && - *(sp ) == blue_low) - { - *dp-- = 0; - *dp-- = 0; - } - else - { - *dp-- = 0xff; - *dp-- = 0xff; - } - *dp-- = *sp--; - *dp-- = *sp--; - *dp-- = *sp--; - *dp-- = *sp--; - *dp-- = *sp--; - *dp-- = *sp--; - } - } - row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA; - row_info->channels = 4; - row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2); - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width); - } - } -} -#endif - -#if defined(PNG_READ_DITHER_SUPPORTED) -void /* PRIVATE */ -png_do_dither(png_row_infop row_info, png_bytep row, - png_bytep palette_lookup, png_bytep dither_lookup) -{ - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width=row_info->width; - - png_debug(1, "in png_do_dither\n"); -#if defined(PNG_USELESS_TESTS_SUPPORTED) - if (row != NULL && row_info != NULL) -#endif - { - if (row_info->color_type == PNG_COLOR_TYPE_RGB && - palette_lookup && row_info->bit_depth == 8) - { - int r, g, b, p; - sp = row; - dp = row; - for (i = 0; i < row_width; i++) - { - r = *sp++; - g = *sp++; - b = *sp++; - - /* this looks real messy, but the compiler will reduce - it down to a reasonable formula. For example, with - 5 bits per color, we get: - p = (((r >> 3) & 0x1f) << 10) | - (((g >> 3) & 0x1f) << 5) | - ((b >> 3) & 0x1f); - */ - p = (((r >> (8 - PNG_DITHER_RED_BITS)) & - ((1 << PNG_DITHER_RED_BITS) - 1)) << - (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) | - (((g >> (8 - PNG_DITHER_GREEN_BITS)) & - ((1 << PNG_DITHER_GREEN_BITS) - 1)) << - (PNG_DITHER_BLUE_BITS)) | - ((b >> (8 - PNG_DITHER_BLUE_BITS)) & - ((1 << PNG_DITHER_BLUE_BITS) - 1)); - - *dp++ = palette_lookup[p]; - } - row_info->color_type = PNG_COLOR_TYPE_PALETTE; - row_info->channels = 1; - row_info->pixel_depth = row_info->bit_depth; - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width); - } - else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA && - palette_lookup != NULL && row_info->bit_depth == 8) - { - int r, g, b, p; - sp = row; - dp = row; - for (i = 0; i < row_width; i++) - { - r = *sp++; - g = *sp++; - b = *sp++; - sp++; - - p = (((r >> (8 - PNG_DITHER_RED_BITS)) & - ((1 << PNG_DITHER_RED_BITS) - 1)) << - (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) | - (((g >> (8 - PNG_DITHER_GREEN_BITS)) & - ((1 << PNG_DITHER_GREEN_BITS) - 1)) << - (PNG_DITHER_BLUE_BITS)) | - ((b >> (8 - PNG_DITHER_BLUE_BITS)) & - ((1 << PNG_DITHER_BLUE_BITS) - 1)); - - *dp++ = palette_lookup[p]; - } - row_info->color_type = PNG_COLOR_TYPE_PALETTE; - row_info->channels = 1; - row_info->pixel_depth = row_info->bit_depth; - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width); - } - else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE && - dither_lookup && row_info->bit_depth == 8) - { - sp = row; - for (i = 0; i < row_width; i++, sp++) - { - *sp = dither_lookup[*sp]; - } - } - } -} -#endif - -#ifdef PNG_FLOATING_POINT_SUPPORTED -#if defined(PNG_READ_GAMMA_SUPPORTED) -static PNG_CONST int png_gamma_shift[] = - {0x10, 0x21, 0x42, 0x84, 0x110, 0x248, 0x550, 0xff0, 0x00}; - -/* We build the 8- or 16-bit gamma tables here. Note that for 16-bit - * tables, we don't make a full table if we are reducing to 8-bit in - * the future. Note also how the gamma_16 tables are segmented so that - * we don't need to allocate > 64K chunks for a full 16-bit table. - */ -void /* PRIVATE */ -png_build_gamma_table(png_structp png_ptr) -{ - png_debug(1, "in png_build_gamma_table\n"); - - if (png_ptr->bit_depth <= 8) - { - int i; - double g; - - if (png_ptr->screen_gamma > .000001) - g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); - else - g = 1.0; - - png_ptr->gamma_table = (png_bytep)png_malloc(png_ptr, - (png_uint_32)256); - - for (i = 0; i < 256; i++) - { - png_ptr->gamma_table[i] = (png_byte)(pow((double)i / 255.0, - g) * 255.0 + .5); - } - -#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ - defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) - if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY)) - { - - g = 1.0 / (png_ptr->gamma); - - png_ptr->gamma_to_1 = (png_bytep)png_malloc(png_ptr, - (png_uint_32)256); - - for (i = 0; i < 256; i++) - { - png_ptr->gamma_to_1[i] = (png_byte)(pow((double)i / 255.0, - g) * 255.0 + .5); - } - - - png_ptr->gamma_from_1 = (png_bytep)png_malloc(png_ptr, - (png_uint_32)256); - - if(png_ptr->screen_gamma > 0.000001) - g = 1.0 / png_ptr->screen_gamma; - else - g = png_ptr->gamma; /* probably doing rgb_to_gray */ - - for (i = 0; i < 256; i++) - { - png_ptr->gamma_from_1[i] = (png_byte)(pow((double)i / 255.0, - g) * 255.0 + .5); - - } - } -#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */ - } - else - { - double g; - int i, j, shift, num; - int sig_bit; - png_uint_32 ig; - - if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) - { - sig_bit = (int)png_ptr->sig_bit.red; - if ((int)png_ptr->sig_bit.green > sig_bit) - sig_bit = png_ptr->sig_bit.green; - if ((int)png_ptr->sig_bit.blue > sig_bit) - sig_bit = png_ptr->sig_bit.blue; - } - else - { - sig_bit = (int)png_ptr->sig_bit.gray; - } - - if (sig_bit > 0) - shift = 16 - sig_bit; - else - shift = 0; - - if (png_ptr->transformations & PNG_16_TO_8) - { - if (shift < (16 - PNG_MAX_GAMMA_8)) - shift = (16 - PNG_MAX_GAMMA_8); - } - - if (shift > 8) - shift = 8; - if (shift < 0) - shift = 0; - - png_ptr->gamma_shift = (png_byte)shift; - - num = (1 << (8 - shift)); - - if (png_ptr->screen_gamma > .000001) - g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); - else - g = 1.0; - - png_ptr->gamma_16_table = (png_uint_16pp)png_malloc(png_ptr, - (png_uint_32)(num * png_sizeof (png_uint_16p))); - - if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND)) - { - double fin, fout; - png_uint_32 last, max; - - for (i = 0; i < num; i++) - { - png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr, - (png_uint_32)(256 * png_sizeof (png_uint_16))); - } - - g = 1.0 / g; - last = 0; - for (i = 0; i < 256; i++) - { - fout = ((double)i + 0.5) / 256.0; - fin = pow(fout, g); - max = (png_uint_32)(fin * (double)((png_uint_32)num << 8)); - while (last <= max) - { - png_ptr->gamma_16_table[(int)(last & (0xff >> shift))] - [(int)(last >> (8 - shift))] = (png_uint_16)( - (png_uint_16)i | ((png_uint_16)i << 8)); - last++; - } - } - while (last < ((png_uint_32)num << 8)) - { - png_ptr->gamma_16_table[(int)(last & (0xff >> shift))] - [(int)(last >> (8 - shift))] = (png_uint_16)65535L; - last++; - } - } - else - { - for (i = 0; i < num; i++) - { - png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr, - (png_uint_32)(256 * png_sizeof (png_uint_16))); - - ig = (((png_uint_32)i * (png_uint_32)png_gamma_shift[shift]) >> 4); - for (j = 0; j < 256; j++) - { - png_ptr->gamma_16_table[i][j] = - (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) / - 65535.0, g) * 65535.0 + .5); - } - } - } - -#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ - defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) - if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY)) - { - - g = 1.0 / (png_ptr->gamma); - - png_ptr->gamma_16_to_1 = (png_uint_16pp)png_malloc(png_ptr, - (png_uint_32)(num * png_sizeof (png_uint_16p ))); - - for (i = 0; i < num; i++) - { - png_ptr->gamma_16_to_1[i] = (png_uint_16p)png_malloc(png_ptr, - (png_uint_32)(256 * png_sizeof (png_uint_16))); - - ig = (((png_uint_32)i * - (png_uint_32)png_gamma_shift[shift]) >> 4); - for (j = 0; j < 256; j++) - { - png_ptr->gamma_16_to_1[i][j] = - (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) / - 65535.0, g) * 65535.0 + .5); - } - } - - if(png_ptr->screen_gamma > 0.000001) - g = 1.0 / png_ptr->screen_gamma; - else - g = png_ptr->gamma; /* probably doing rgb_to_gray */ - - png_ptr->gamma_16_from_1 = (png_uint_16pp)png_malloc(png_ptr, - (png_uint_32)(num * png_sizeof (png_uint_16p))); - - for (i = 0; i < num; i++) - { - png_ptr->gamma_16_from_1[i] = (png_uint_16p)png_malloc(png_ptr, - (png_uint_32)(256 * png_sizeof (png_uint_16))); - - ig = (((png_uint_32)i * - (png_uint_32)png_gamma_shift[shift]) >> 4); - for (j = 0; j < 256; j++) - { - png_ptr->gamma_16_from_1[i][j] = - (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) / - 65535.0, g) * 65535.0 + .5); - } - } - } -#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */ - } -} -#endif -/* To do: install integer version of png_build_gamma_table here */ -#endif - -#if defined(PNG_MNG_FEATURES_SUPPORTED) -/* undoes intrapixel differencing */ -void /* PRIVATE */ -png_do_read_intrapixel(png_row_infop row_info, png_bytep row) -{ - png_debug(1, "in png_do_read_intrapixel\n"); - if ( -#if defined(PNG_USELESS_TESTS_SUPPORTED) - row != NULL && row_info != NULL && -#endif - (row_info->color_type & PNG_COLOR_MASK_COLOR)) - { - int bytes_per_pixel; - png_uint_32 row_width = row_info->width; - if (row_info->bit_depth == 8) - { - png_bytep rp; - png_uint_32 i; - - if (row_info->color_type == PNG_COLOR_TYPE_RGB) - bytes_per_pixel = 3; - else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - bytes_per_pixel = 4; - else - return; - - for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) - { - *(rp) = (png_byte)((256 + *rp + *(rp+1))&0xff); - *(rp+2) = (png_byte)((256 + *(rp+2) + *(rp+1))&0xff); - } - } - else if (row_info->bit_depth == 16) - { - png_bytep rp; - png_uint_32 i; - - if (row_info->color_type == PNG_COLOR_TYPE_RGB) - bytes_per_pixel = 6; - else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - bytes_per_pixel = 8; - else - return; - - for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) - { - png_uint_32 s0 = (*(rp ) << 8) | *(rp+1); - png_uint_32 s1 = (*(rp+2) << 8) | *(rp+3); - png_uint_32 s2 = (*(rp+4) << 8) | *(rp+5); - png_uint_32 red = (png_uint_32)((s0+s1+65536L) & 0xffffL); - png_uint_32 blue = (png_uint_32)((s2+s1+65536L) & 0xffffL); - *(rp ) = (png_byte)((red >> 8) & 0xff); - *(rp+1) = (png_byte)(red & 0xff); - *(rp+4) = (png_byte)((blue >> 8) & 0xff); - *(rp+5) = (png_byte)(blue & 0xff); - } - } - } -} -#endif /* PNG_MNG_FEATURES_SUPPORTED */ -#endif /* PNG_READ_SUPPORTED */ diff --git a/rosapps/lib/libpng/pngrutil.c b/rosapps/lib/libpng/pngrutil.c deleted file mode 100644 index 5e40aca481e..00000000000 --- a/rosapps/lib/libpng/pngrutil.c +++ /dev/null @@ -1,3164 +0,0 @@ - -/* pngrutil.c - utilities to read a PNG file - * - * Last changed in libpng 1.2.23 [November 6, 2007] - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2007 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This file contains routines that are only called from within - * libpng itself during the course of reading an image. - */ - -#define PNG_INTERNAL -#include "png.h" - -#if defined(PNG_READ_SUPPORTED) - -#if defined(_WIN32_WCE) && (_WIN32_WCE<0x500) -# define WIN32_WCE_OLD -#endif - -#ifdef PNG_FLOATING_POINT_SUPPORTED -# if defined(WIN32_WCE_OLD) -/* strtod() function is not supported on WindowsCE */ -__inline double png_strtod(png_structp png_ptr, PNG_CONST char *nptr, char **endptr) -{ - double result = 0; - int len; - wchar_t *str, *end; - - len = MultiByteToWideChar(CP_ACP, 0, nptr, -1, NULL, 0); - str = (wchar_t *)png_malloc(png_ptr, len * sizeof(wchar_t)); - if ( NULL != str ) - { - MultiByteToWideChar(CP_ACP, 0, nptr, -1, str, len); - result = wcstod(str, &end); - len = WideCharToMultiByte(CP_ACP, 0, end, -1, NULL, 0, NULL, NULL); - *endptr = (char *)nptr + (png_strlen(nptr) - len + 1); - png_free(png_ptr, str); - } - return result; -} -# else -# define png_strtod(p,a,b) strtod(a,b) -# endif -#endif - -png_uint_32 PNGAPI -png_get_uint_31(png_structp png_ptr, png_bytep buf) -{ - png_uint_32 i = png_get_uint_32(buf); - if (i > PNG_UINT_31_MAX) - png_error(png_ptr, "PNG unsigned integer out of range."); - return (i); -} -#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED -/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */ -png_uint_32 PNGAPI -png_get_uint_32(png_bytep buf) -{ - png_uint_32 i = ((png_uint_32)(*buf) << 24) + - ((png_uint_32)(*(buf + 1)) << 16) + - ((png_uint_32)(*(buf + 2)) << 8) + - (png_uint_32)(*(buf + 3)); - - return (i); -} - -/* Grab a signed 32-bit integer from a buffer in big-endian format. The - * data is stored in the PNG file in two's complement format, and it is - * assumed that the machine format for signed integers is the same. */ -png_int_32 PNGAPI -png_get_int_32(png_bytep buf) -{ - png_int_32 i = ((png_int_32)(*buf) << 24) + - ((png_int_32)(*(buf + 1)) << 16) + - ((png_int_32)(*(buf + 2)) << 8) + - (png_int_32)(*(buf + 3)); - - return (i); -} - -/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */ -png_uint_16 PNGAPI -png_get_uint_16(png_bytep buf) -{ - png_uint_16 i = (png_uint_16)(((png_uint_16)(*buf) << 8) + - (png_uint_16)(*(buf + 1))); - - return (i); -} -#endif /* PNG_READ_BIG_ENDIAN_SUPPORTED */ - -/* Read data, and (optionally) run it through the CRC. */ -void /* PRIVATE */ -png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length) -{ - if(png_ptr == NULL) return; - png_read_data(png_ptr, buf, length); - png_calculate_crc(png_ptr, buf, length); -} - -/* Optionally skip data and then check the CRC. Depending on whether we - are reading a ancillary or critical chunk, and how the program has set - things up, we may calculate the CRC on the data and print a message. - Returns '1' if there was a CRC error, '0' otherwise. */ -int /* PRIVATE */ -png_crc_finish(png_structp png_ptr, png_uint_32 skip) -{ - png_size_t i; - png_size_t istop = png_ptr->zbuf_size; - - for (i = (png_size_t)skip; i > istop; i -= istop) - { - png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); - } - if (i) - { - png_crc_read(png_ptr, png_ptr->zbuf, i); - } - - if (png_crc_error(png_ptr)) - { - if (((png_ptr->chunk_name[0] & 0x20) && /* Ancillary */ - !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) || - (!(png_ptr->chunk_name[0] & 0x20) && /* Critical */ - (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE))) - { - png_chunk_warning(png_ptr, "CRC error"); - } - else - { - png_chunk_error(png_ptr, "CRC error"); - } - return (1); - } - - return (0); -} - -/* Compare the CRC stored in the PNG file with that calculated by libpng from - the data it has read thus far. */ -int /* PRIVATE */ -png_crc_error(png_structp png_ptr) -{ - png_byte crc_bytes[4]; - png_uint_32 crc; - int need_crc = 1; - - if (png_ptr->chunk_name[0] & 0x20) /* ancillary */ - { - if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) == - (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN)) - need_crc = 0; - } - else /* critical */ - { - if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) - need_crc = 0; - } - - png_read_data(png_ptr, crc_bytes, 4); - - if (need_crc) - { - crc = png_get_uint_32(crc_bytes); - return ((int)(crc != png_ptr->crc)); - } - else - return (0); -} - -#if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \ - defined(PNG_READ_iCCP_SUPPORTED) -/* - * Decompress trailing data in a chunk. The assumption is that chunkdata - * points at an allocated area holding the contents of a chunk with a - * trailing compressed part. What we get back is an allocated area - * holding the original prefix part and an uncompressed version of the - * trailing part (the malloc area passed in is freed). - */ -png_charp /* PRIVATE */ -png_decompress_chunk(png_structp png_ptr, int comp_type, - png_charp chunkdata, png_size_t chunklength, - png_size_t prefix_size, png_size_t *newlength) -{ - static PNG_CONST char msg[] = "Error decoding compressed text"; - png_charp text; - png_size_t text_size; - - if (comp_type == PNG_COMPRESSION_TYPE_BASE) - { - int ret = Z_OK; - png_ptr->zstream.next_in = (png_bytep)(chunkdata + prefix_size); - png_ptr->zstream.avail_in = (uInt)(chunklength - prefix_size); - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - - text_size = 0; - text = NULL; - - while (png_ptr->zstream.avail_in) - { - ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); - if (ret != Z_OK && ret != Z_STREAM_END) - { - if (png_ptr->zstream.msg != NULL) - png_warning(png_ptr, png_ptr->zstream.msg); - else - png_warning(png_ptr, msg); - inflateReset(&png_ptr->zstream); - png_ptr->zstream.avail_in = 0; - - if (text == NULL) - { - text_size = prefix_size + png_sizeof(msg) + 1; - text = (png_charp)png_malloc_warn(png_ptr, text_size); - if (text == NULL) - { - png_free(png_ptr,chunkdata); - png_error(png_ptr,"Not enough memory to decompress chunk"); - } - png_memcpy(text, chunkdata, prefix_size); - } - - text[text_size - 1] = 0x00; - - /* Copy what we can of the error message into the text chunk */ - text_size = (png_size_t)(chunklength - (text - chunkdata) - 1); - text_size = png_sizeof(msg) > text_size ? text_size : - png_sizeof(msg); - png_memcpy(text + prefix_size, msg, text_size + 1); - break; - } - if (!png_ptr->zstream.avail_out || ret == Z_STREAM_END) - { - if (text == NULL) - { - text_size = prefix_size + - png_ptr->zbuf_size - png_ptr->zstream.avail_out; - text = (png_charp)png_malloc_warn(png_ptr, text_size + 1); - if (text == NULL) - { - png_free(png_ptr,chunkdata); - png_error(png_ptr,"Not enough memory to decompress chunk."); - } - png_memcpy(text + prefix_size, png_ptr->zbuf, - text_size - prefix_size); - png_memcpy(text, chunkdata, prefix_size); - *(text + text_size) = 0x00; - } - else - { - png_charp tmp; - - tmp = text; - text = (png_charp)png_malloc_warn(png_ptr, - (png_uint_32)(text_size + - png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1)); - if (text == NULL) - { - png_free(png_ptr, tmp); - png_free(png_ptr, chunkdata); - png_error(png_ptr,"Not enough memory to decompress chunk.."); - } - png_memcpy(text, tmp, text_size); - png_free(png_ptr, tmp); - png_memcpy(text + text_size, png_ptr->zbuf, - (png_ptr->zbuf_size - png_ptr->zstream.avail_out)); - text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out; - *(text + text_size) = 0x00; - } - if (ret == Z_STREAM_END) - break; - else - { - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - } - } - } - if (ret != Z_STREAM_END) - { -#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) - char umsg[52]; - - if (ret == Z_BUF_ERROR) - png_snprintf(umsg, 52, - "Buffer error in compressed datastream in %s chunk", - png_ptr->chunk_name); - else if (ret == Z_DATA_ERROR) - png_snprintf(umsg, 52, - "Data error in compressed datastream in %s chunk", - png_ptr->chunk_name); - else - png_snprintf(umsg, 52, - "Incomplete compressed datastream in %s chunk", - png_ptr->chunk_name); - png_warning(png_ptr, umsg); -#else - png_warning(png_ptr, - "Incomplete compressed datastream in chunk other than IDAT"); -#endif - text_size=prefix_size; - if (text == NULL) - { - text = (png_charp)png_malloc_warn(png_ptr, text_size+1); - if (text == NULL) - { - png_free(png_ptr, chunkdata); - png_error(png_ptr,"Not enough memory for text."); - } - png_memcpy(text, chunkdata, prefix_size); - } - *(text + text_size) = 0x00; - } - - inflateReset(&png_ptr->zstream); - png_ptr->zstream.avail_in = 0; - - png_free(png_ptr, chunkdata); - chunkdata = text; - *newlength=text_size; - } - else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */ - { -#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) - char umsg[50]; - - png_snprintf(umsg, 50, - "Unknown zTXt compression type %d", comp_type); - png_warning(png_ptr, umsg); -#else - png_warning(png_ptr, "Unknown zTXt compression type"); -#endif - - *(chunkdata + prefix_size) = 0x00; - *newlength=prefix_size; - } - - return chunkdata; -} -#endif - -/* read and check the IDHR chunk */ -void /* PRIVATE */ -png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -{ - png_byte buf[13]; - png_uint_32 width, height; - int bit_depth, color_type, compression_type, filter_type; - int interlace_type; - - png_debug(1, "in png_handle_IHDR\n"); - - if (png_ptr->mode & PNG_HAVE_IHDR) - png_error(png_ptr, "Out of place IHDR"); - - /* check the length */ - if (length != 13) - png_error(png_ptr, "Invalid IHDR chunk"); - - png_ptr->mode |= PNG_HAVE_IHDR; - - png_crc_read(png_ptr, buf, 13); - png_crc_finish(png_ptr, 0); - - width = png_get_uint_31(png_ptr, buf); - height = png_get_uint_31(png_ptr, buf + 4); - bit_depth = buf[8]; - color_type = buf[9]; - compression_type = buf[10]; - filter_type = buf[11]; - interlace_type = buf[12]; - - /* set internal variables */ - png_ptr->width = width; - png_ptr->height = height; - png_ptr->bit_depth = (png_byte)bit_depth; - png_ptr->interlaced = (png_byte)interlace_type; - png_ptr->color_type = (png_byte)color_type; -#if defined(PNG_MNG_FEATURES_SUPPORTED) - png_ptr->filter_type = (png_byte)filter_type; -#endif - png_ptr->compression_type = (png_byte)compression_type; - - /* find number of channels */ - switch (png_ptr->color_type) - { - case PNG_COLOR_TYPE_GRAY: - case PNG_COLOR_TYPE_PALETTE: - png_ptr->channels = 1; - break; - case PNG_COLOR_TYPE_RGB: - png_ptr->channels = 3; - break; - case PNG_COLOR_TYPE_GRAY_ALPHA: - png_ptr->channels = 2; - break; - case PNG_COLOR_TYPE_RGB_ALPHA: - png_ptr->channels = 4; - break; - } - - /* set up other useful info */ - png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth * - png_ptr->channels); - png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->width); - png_debug1(3,"bit_depth = %d\n", png_ptr->bit_depth); - png_debug1(3,"channels = %d\n", png_ptr->channels); - png_debug1(3,"rowbytes = %lu\n", png_ptr->rowbytes); - png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, - color_type, interlace_type, compression_type, filter_type); -} - -/* read and check the palette */ -void /* PRIVATE */ -png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -{ - png_color palette[PNG_MAX_PALETTE_LENGTH]; - int num, i; -#ifndef PNG_NO_POINTER_INDEXING - png_colorp pal_ptr; -#endif - - png_debug(1, "in png_handle_PLTE\n"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before PLTE"); - else if (png_ptr->mode & PNG_HAVE_IDAT) - { - png_warning(png_ptr, "Invalid PLTE after IDAT"); - png_crc_finish(png_ptr, length); - return; - } - else if (png_ptr->mode & PNG_HAVE_PLTE) - png_error(png_ptr, "Duplicate PLTE chunk"); - - png_ptr->mode |= PNG_HAVE_PLTE; - - if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR)) - { - png_warning(png_ptr, - "Ignoring PLTE chunk in grayscale PNG"); - png_crc_finish(png_ptr, length); - return; - } -#if !defined(PNG_READ_OPT_PLTE_SUPPORTED) - if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE) - { - png_crc_finish(png_ptr, length); - return; - } -#endif - - if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3) - { - if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE) - { - png_warning(png_ptr, "Invalid palette chunk"); - png_crc_finish(png_ptr, length); - return; - } - else - { - png_error(png_ptr, "Invalid palette chunk"); - } - } - - num = (int)length / 3; - -#ifndef PNG_NO_POINTER_INDEXING - for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++) - { - png_byte buf[3]; - - png_crc_read(png_ptr, buf, 3); - pal_ptr->red = buf[0]; - pal_ptr->green = buf[1]; - pal_ptr->blue = buf[2]; - } -#else - for (i = 0; i < num; i++) - { - png_byte buf[3]; - - png_crc_read(png_ptr, buf, 3); - /* don't depend upon png_color being any order */ - palette[i].red = buf[0]; - palette[i].green = buf[1]; - palette[i].blue = buf[2]; - } -#endif - - /* If we actually NEED the PLTE chunk (ie for a paletted image), we do - whatever the normal CRC configuration tells us. However, if we - have an RGB image, the PLTE can be considered ancillary, so - we will act as though it is. */ -#if !defined(PNG_READ_OPT_PLTE_SUPPORTED) - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) -#endif - { - png_crc_finish(png_ptr, 0); - } -#if !defined(PNG_READ_OPT_PLTE_SUPPORTED) - else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */ - { - /* If we don't want to use the data from an ancillary chunk, - we have two options: an error abort, or a warning and we - ignore the data in this chunk (which should be OK, since - it's considered ancillary for a RGB or RGBA image). */ - if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE)) - { - if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) - { - png_chunk_error(png_ptr, "CRC error"); - } - else - { - png_chunk_warning(png_ptr, "CRC error"); - return; - } - } - /* Otherwise, we (optionally) emit a warning and use the chunk. */ - else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) - { - png_chunk_warning(png_ptr, "CRC error"); - } - } -#endif - - png_set_PLTE(png_ptr, info_ptr, palette, num); - -#if defined(PNG_READ_tRNS_SUPPORTED) - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - { - if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) - { - if (png_ptr->num_trans > (png_uint_16)num) - { - png_warning(png_ptr, "Truncating incorrect tRNS chunk length"); - png_ptr->num_trans = (png_uint_16)num; - } - if (info_ptr->num_trans > (png_uint_16)num) - { - png_warning(png_ptr, "Truncating incorrect info tRNS chunk length"); - info_ptr->num_trans = (png_uint_16)num; - } - } - } -#endif - -} - -void /* PRIVATE */ -png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -{ - png_debug(1, "in png_handle_IEND\n"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT)) - { - png_error(png_ptr, "No image in file"); - } - - png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND); - - if (length != 0) - { - png_warning(png_ptr, "Incorrect IEND chunk length"); - } - png_crc_finish(png_ptr, length); - - info_ptr =info_ptr; /* quiet compiler warnings about unused info_ptr */ -} - -#if defined(PNG_READ_gAMA_SUPPORTED) -void /* PRIVATE */ -png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -{ - png_fixed_point igamma; -#ifdef PNG_FLOATING_POINT_SUPPORTED - float file_gamma; -#endif - png_byte buf[4]; - - png_debug(1, "in png_handle_gAMA\n"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before gAMA"); - else if (png_ptr->mode & PNG_HAVE_IDAT) - { - png_warning(png_ptr, "Invalid gAMA after IDAT"); - png_crc_finish(png_ptr, length); - return; - } - else if (png_ptr->mode & PNG_HAVE_PLTE) - /* Should be an error, but we can cope with it */ - png_warning(png_ptr, "Out of place gAMA chunk"); - - if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA) -#if defined(PNG_READ_sRGB_SUPPORTED) - && !(info_ptr->valid & PNG_INFO_sRGB) -#endif - ) - { - png_warning(png_ptr, "Duplicate gAMA chunk"); - png_crc_finish(png_ptr, length); - return; - } - - if (length != 4) - { - png_warning(png_ptr, "Incorrect gAMA chunk length"); - png_crc_finish(png_ptr, length); - return; - } - - png_crc_read(png_ptr, buf, 4); - if (png_crc_finish(png_ptr, 0)) - return; - - igamma = (png_fixed_point)png_get_uint_32(buf); - /* check for zero gamma */ - if (igamma == 0) - { - png_warning(png_ptr, - "Ignoring gAMA chunk with gamma=0"); - return; - } - -#if defined(PNG_READ_sRGB_SUPPORTED) - if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB)) - if (PNG_OUT_OF_RANGE(igamma, 45500L, 500)) - { - png_warning(png_ptr, - "Ignoring incorrect gAMA value when sRGB is also present"); -#ifndef PNG_NO_CONSOLE_IO - fprintf(stderr, "gamma = (%d/100000)\n", (int)igamma); -#endif - return; - } -#endif /* PNG_READ_sRGB_SUPPORTED */ - -#ifdef PNG_FLOATING_POINT_SUPPORTED - file_gamma = (float)igamma / (float)100000.0; -# ifdef PNG_READ_GAMMA_SUPPORTED - png_ptr->gamma = file_gamma; -# endif - png_set_gAMA(png_ptr, info_ptr, file_gamma); -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED - png_set_gAMA_fixed(png_ptr, info_ptr, igamma); -#endif -} -#endif - -#if defined(PNG_READ_sBIT_SUPPORTED) -void /* PRIVATE */ -png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -{ - png_size_t truelen; - png_byte buf[4]; - - png_debug(1, "in png_handle_sBIT\n"); - - buf[0] = buf[1] = buf[2] = buf[3] = 0; - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before sBIT"); - else if (png_ptr->mode & PNG_HAVE_IDAT) - { - png_warning(png_ptr, "Invalid sBIT after IDAT"); - png_crc_finish(png_ptr, length); - return; - } - else if (png_ptr->mode & PNG_HAVE_PLTE) - { - /* Should be an error, but we can cope with it */ - png_warning(png_ptr, "Out of place sBIT chunk"); - } - if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT)) - { - png_warning(png_ptr, "Duplicate sBIT chunk"); - png_crc_finish(png_ptr, length); - return; - } - - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - truelen = 3; - else - truelen = (png_size_t)png_ptr->channels; - - if (length != truelen || length > 4) - { - png_warning(png_ptr, "Incorrect sBIT chunk length"); - png_crc_finish(png_ptr, length); - return; - } - - png_crc_read(png_ptr, buf, truelen); - if (png_crc_finish(png_ptr, 0)) - return; - - if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) - { - png_ptr->sig_bit.red = buf[0]; - png_ptr->sig_bit.green = buf[1]; - png_ptr->sig_bit.blue = buf[2]; - png_ptr->sig_bit.alpha = buf[3]; - } - else - { - png_ptr->sig_bit.gray = buf[0]; - png_ptr->sig_bit.red = buf[0]; - png_ptr->sig_bit.green = buf[0]; - png_ptr->sig_bit.blue = buf[0]; - png_ptr->sig_bit.alpha = buf[1]; - } - png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit)); -} -#endif - -#if defined(PNG_READ_cHRM_SUPPORTED) -void /* PRIVATE */ -png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -{ - png_byte buf[4]; -#ifdef PNG_FLOATING_POINT_SUPPORTED - float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y; -#endif - png_fixed_point int_x_white, int_y_white, int_x_red, int_y_red, int_x_green, - int_y_green, int_x_blue, int_y_blue; - - png_uint_32 uint_x, uint_y; - - png_debug(1, "in png_handle_cHRM\n"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before cHRM"); - else if (png_ptr->mode & PNG_HAVE_IDAT) - { - png_warning(png_ptr, "Invalid cHRM after IDAT"); - png_crc_finish(png_ptr, length); - return; - } - else if (png_ptr->mode & PNG_HAVE_PLTE) - /* Should be an error, but we can cope with it */ - png_warning(png_ptr, "Missing PLTE before cHRM"); - - if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM) -#if defined(PNG_READ_sRGB_SUPPORTED) - && !(info_ptr->valid & PNG_INFO_sRGB) -#endif - ) - { - png_warning(png_ptr, "Duplicate cHRM chunk"); - png_crc_finish(png_ptr, length); - return; - } - - if (length != 32) - { - png_warning(png_ptr, "Incorrect cHRM chunk length"); - png_crc_finish(png_ptr, length); - return; - } - - png_crc_read(png_ptr, buf, 4); - uint_x = png_get_uint_32(buf); - - png_crc_read(png_ptr, buf, 4); - uint_y = png_get_uint_32(buf); - - if (uint_x > 80000L || uint_y > 80000L || - uint_x + uint_y > 100000L) - { - png_warning(png_ptr, "Invalid cHRM white point"); - png_crc_finish(png_ptr, 24); - return; - } - int_x_white = (png_fixed_point)uint_x; - int_y_white = (png_fixed_point)uint_y; - - png_crc_read(png_ptr, buf, 4); - uint_x = png_get_uint_32(buf); - - png_crc_read(png_ptr, buf, 4); - uint_y = png_get_uint_32(buf); - - if (uint_x + uint_y > 100000L) - { - png_warning(png_ptr, "Invalid cHRM red point"); - png_crc_finish(png_ptr, 16); - return; - } - int_x_red = (png_fixed_point)uint_x; - int_y_red = (png_fixed_point)uint_y; - - png_crc_read(png_ptr, buf, 4); - uint_x = png_get_uint_32(buf); - - png_crc_read(png_ptr, buf, 4); - uint_y = png_get_uint_32(buf); - - if (uint_x + uint_y > 100000L) - { - png_warning(png_ptr, "Invalid cHRM green point"); - png_crc_finish(png_ptr, 8); - return; - } - int_x_green = (png_fixed_point)uint_x; - int_y_green = (png_fixed_point)uint_y; - - png_crc_read(png_ptr, buf, 4); - uint_x = png_get_uint_32(buf); - - png_crc_read(png_ptr, buf, 4); - uint_y = png_get_uint_32(buf); - - if (uint_x + uint_y > 100000L) - { - png_warning(png_ptr, "Invalid cHRM blue point"); - png_crc_finish(png_ptr, 0); - return; - } - int_x_blue = (png_fixed_point)uint_x; - int_y_blue = (png_fixed_point)uint_y; - -#ifdef PNG_FLOATING_POINT_SUPPORTED - white_x = (float)int_x_white / (float)100000.0; - white_y = (float)int_y_white / (float)100000.0; - red_x = (float)int_x_red / (float)100000.0; - red_y = (float)int_y_red / (float)100000.0; - green_x = (float)int_x_green / (float)100000.0; - green_y = (float)int_y_green / (float)100000.0; - blue_x = (float)int_x_blue / (float)100000.0; - blue_y = (float)int_y_blue / (float)100000.0; -#endif - -#if defined(PNG_READ_sRGB_SUPPORTED) - if ((info_ptr != NULL) && (info_ptr->valid & PNG_INFO_sRGB)) - { - if (PNG_OUT_OF_RANGE(int_x_white, 31270, 1000) || - PNG_OUT_OF_RANGE(int_y_white, 32900, 1000) || - PNG_OUT_OF_RANGE(int_x_red, 64000L, 1000) || - PNG_OUT_OF_RANGE(int_y_red, 33000, 1000) || - PNG_OUT_OF_RANGE(int_x_green, 30000, 1000) || - PNG_OUT_OF_RANGE(int_y_green, 60000L, 1000) || - PNG_OUT_OF_RANGE(int_x_blue, 15000, 1000) || - PNG_OUT_OF_RANGE(int_y_blue, 6000, 1000)) - { - png_warning(png_ptr, - "Ignoring incorrect cHRM value when sRGB is also present"); -#ifndef PNG_NO_CONSOLE_IO -#ifdef PNG_FLOATING_POINT_SUPPORTED - fprintf(stderr,"wx=%f, wy=%f, rx=%f, ry=%f\n", - white_x, white_y, red_x, red_y); - fprintf(stderr,"gx=%f, gy=%f, bx=%f, by=%f\n", - green_x, green_y, blue_x, blue_y); -#else - fprintf(stderr,"wx=%ld, wy=%ld, rx=%ld, ry=%ld\n", - int_x_white, int_y_white, int_x_red, int_y_red); - fprintf(stderr,"gx=%ld, gy=%ld, bx=%ld, by=%ld\n", - int_x_green, int_y_green, int_x_blue, int_y_blue); -#endif -#endif /* PNG_NO_CONSOLE_IO */ - } - png_crc_finish(png_ptr, 0); - return; - } -#endif /* PNG_READ_sRGB_SUPPORTED */ - -#ifdef PNG_FLOATING_POINT_SUPPORTED - png_set_cHRM(png_ptr, info_ptr, - white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y); -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED - png_set_cHRM_fixed(png_ptr, info_ptr, - int_x_white, int_y_white, int_x_red, int_y_red, int_x_green, - int_y_green, int_x_blue, int_y_blue); -#endif - if (png_crc_finish(png_ptr, 0)) - return; -} -#endif - -#if defined(PNG_READ_sRGB_SUPPORTED) -void /* PRIVATE */ -png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -{ - int intent; - png_byte buf[1]; - - png_debug(1, "in png_handle_sRGB\n"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before sRGB"); - else if (png_ptr->mode & PNG_HAVE_IDAT) - { - png_warning(png_ptr, "Invalid sRGB after IDAT"); - png_crc_finish(png_ptr, length); - return; - } - else if (png_ptr->mode & PNG_HAVE_PLTE) - /* Should be an error, but we can cope with it */ - png_warning(png_ptr, "Out of place sRGB chunk"); - - if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB)) - { - png_warning(png_ptr, "Duplicate sRGB chunk"); - png_crc_finish(png_ptr, length); - return; - } - - if (length != 1) - { - png_warning(png_ptr, "Incorrect sRGB chunk length"); - png_crc_finish(png_ptr, length); - return; - } - - png_crc_read(png_ptr, buf, 1); - if (png_crc_finish(png_ptr, 0)) - return; - - intent = buf[0]; - /* check for bad intent */ - if (intent >= PNG_sRGB_INTENT_LAST) - { - png_warning(png_ptr, "Unknown sRGB intent"); - return; - } - -#if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED) - if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)) - { - png_fixed_point igamma; -#ifdef PNG_FIXED_POINT_SUPPORTED - igamma=info_ptr->int_gamma; -#else -# ifdef PNG_FLOATING_POINT_SUPPORTED - igamma=(png_fixed_point)(info_ptr->gamma * 100000.); -# endif -#endif - if (PNG_OUT_OF_RANGE(igamma, 45500L, 500)) - { - png_warning(png_ptr, - "Ignoring incorrect gAMA value when sRGB is also present"); -#ifndef PNG_NO_CONSOLE_IO -# ifdef PNG_FIXED_POINT_SUPPORTED - fprintf(stderr,"incorrect gamma=(%d/100000)\n",(int)png_ptr->int_gamma); -# else -# ifdef PNG_FLOATING_POINT_SUPPORTED - fprintf(stderr,"incorrect gamma=%f\n",png_ptr->gamma); -# endif -# endif -#endif - } - } -#endif /* PNG_READ_gAMA_SUPPORTED */ - -#ifdef PNG_READ_cHRM_SUPPORTED -#ifdef PNG_FIXED_POINT_SUPPORTED - if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)) - if (PNG_OUT_OF_RANGE(info_ptr->int_x_white, 31270, 1000) || - PNG_OUT_OF_RANGE(info_ptr->int_y_white, 32900, 1000) || - PNG_OUT_OF_RANGE(info_ptr->int_x_red, 64000L, 1000) || - PNG_OUT_OF_RANGE(info_ptr->int_y_red, 33000, 1000) || - PNG_OUT_OF_RANGE(info_ptr->int_x_green, 30000, 1000) || - PNG_OUT_OF_RANGE(info_ptr->int_y_green, 60000L, 1000) || - PNG_OUT_OF_RANGE(info_ptr->int_x_blue, 15000, 1000) || - PNG_OUT_OF_RANGE(info_ptr->int_y_blue, 6000, 1000)) - { - png_warning(png_ptr, - "Ignoring incorrect cHRM value when sRGB is also present"); - } -#endif /* PNG_FIXED_POINT_SUPPORTED */ -#endif /* PNG_READ_cHRM_SUPPORTED */ - - png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent); -} -#endif /* PNG_READ_sRGB_SUPPORTED */ - -#if defined(PNG_READ_iCCP_SUPPORTED) -void /* PRIVATE */ -png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -/* Note: this does not properly handle chunks that are > 64K under DOS */ -{ - png_charp chunkdata; - png_byte compression_type; - png_bytep pC; - png_charp profile; - png_uint_32 skip = 0; - png_uint_32 profile_size, profile_length; - png_size_t slength, prefix_length, data_length; - - png_debug(1, "in png_handle_iCCP\n"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before iCCP"); - else if (png_ptr->mode & PNG_HAVE_IDAT) - { - png_warning(png_ptr, "Invalid iCCP after IDAT"); - png_crc_finish(png_ptr, length); - return; - } - else if (png_ptr->mode & PNG_HAVE_PLTE) - /* Should be an error, but we can cope with it */ - png_warning(png_ptr, "Out of place iCCP chunk"); - - if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP)) - { - png_warning(png_ptr, "Duplicate iCCP chunk"); - png_crc_finish(png_ptr, length); - return; - } - -#ifdef PNG_MAX_MALLOC_64K - if (length > (png_uint_32)65535L) - { - png_warning(png_ptr, "iCCP chunk too large to fit in memory"); - skip = length - (png_uint_32)65535L; - length = (png_uint_32)65535L; - } -#endif - - chunkdata = (png_charp)png_malloc(png_ptr, length + 1); - slength = (png_size_t)length; - png_crc_read(png_ptr, (png_bytep)chunkdata, slength); - - if (png_crc_finish(png_ptr, skip)) - { - png_free(png_ptr, chunkdata); - return; - } - - chunkdata[slength] = 0x00; - - for (profile = chunkdata; *profile; profile++) - /* empty loop to find end of name */ ; - - ++profile; - - /* there should be at least one zero (the compression type byte) - following the separator, and we should be on it */ - if ( profile >= chunkdata + slength - 1) - { - png_free(png_ptr, chunkdata); - png_warning(png_ptr, "Malformed iCCP chunk"); - return; - } - - /* compression_type should always be zero */ - compression_type = *profile++; - if (compression_type) - { - png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk"); - compression_type=0x00; /* Reset it to zero (libpng-1.0.6 through 1.0.8 - wrote nonzero) */ - } - - prefix_length = profile - chunkdata; - chunkdata = png_decompress_chunk(png_ptr, compression_type, chunkdata, - slength, prefix_length, &data_length); - - profile_length = data_length - prefix_length; - - if ( prefix_length > data_length || profile_length < 4) - { - png_free(png_ptr, chunkdata); - png_warning(png_ptr, "Profile size field missing from iCCP chunk"); - return; - } - - /* Check the profile_size recorded in the first 32 bits of the ICC profile */ - pC = (png_bytep)(chunkdata+prefix_length); - profile_size = ((*(pC ))<<24) | - ((*(pC+1))<<16) | - ((*(pC+2))<< 8) | - ((*(pC+3)) ); - - if(profile_size < profile_length) - profile_length = profile_size; - - if(profile_size > profile_length) - { - png_free(png_ptr, chunkdata); - png_warning(png_ptr, "Ignoring truncated iCCP profile."); - return; - } - - png_set_iCCP(png_ptr, info_ptr, chunkdata, compression_type, - chunkdata + prefix_length, profile_length); - png_free(png_ptr, chunkdata); -} -#endif /* PNG_READ_iCCP_SUPPORTED */ - -#if defined(PNG_READ_sPLT_SUPPORTED) -void /* PRIVATE */ -png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -/* Note: this does not properly handle chunks that are > 64K under DOS */ -{ - png_bytep chunkdata; - png_bytep entry_start; - png_sPLT_t new_palette; -#ifdef PNG_NO_POINTER_INDEXING - png_sPLT_entryp pp; -#endif - int data_length, entry_size, i; - png_uint_32 skip = 0; - png_size_t slength; - - png_debug(1, "in png_handle_sPLT\n"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before sPLT"); - else if (png_ptr->mode & PNG_HAVE_IDAT) - { - png_warning(png_ptr, "Invalid sPLT after IDAT"); - png_crc_finish(png_ptr, length); - return; - } - -#ifdef PNG_MAX_MALLOC_64K - if (length > (png_uint_32)65535L) - { - png_warning(png_ptr, "sPLT chunk too large to fit in memory"); - skip = length - (png_uint_32)65535L; - length = (png_uint_32)65535L; - } -#endif - - chunkdata = (png_bytep)png_malloc(png_ptr, length + 1); - slength = (png_size_t)length; - png_crc_read(png_ptr, (png_bytep)chunkdata, slength); - - if (png_crc_finish(png_ptr, skip)) - { - png_free(png_ptr, chunkdata); - return; - } - - chunkdata[slength] = 0x00; - - for (entry_start = chunkdata; *entry_start; entry_start++) - /* empty loop to find end of name */ ; - ++entry_start; - - /* a sample depth should follow the separator, and we should be on it */ - if (entry_start > chunkdata + slength - 2) - { - png_free(png_ptr, chunkdata); - png_warning(png_ptr, "malformed sPLT chunk"); - return; - } - - new_palette.depth = *entry_start++; - entry_size = (new_palette.depth == 8 ? 6 : 10); - data_length = (slength - (entry_start - chunkdata)); - - /* integrity-check the data length */ - if (data_length % entry_size) - { - png_free(png_ptr, chunkdata); - png_warning(png_ptr, "sPLT chunk has bad length"); - return; - } - - new_palette.nentries = (png_int_32) ( data_length / entry_size); - if ((png_uint_32) new_palette.nentries > (png_uint_32) (PNG_SIZE_MAX / - png_sizeof(png_sPLT_entry))) - { - png_warning(png_ptr, "sPLT chunk too long"); - return; - } - new_palette.entries = (png_sPLT_entryp)png_malloc_warn( - png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry)); - if (new_palette.entries == NULL) - { - png_warning(png_ptr, "sPLT chunk requires too much memory"); - return; - } - -#ifndef PNG_NO_POINTER_INDEXING - for (i = 0; i < new_palette.nentries; i++) - { - png_sPLT_entryp pp = new_palette.entries + i; - - if (new_palette.depth == 8) - { - pp->red = *entry_start++; - pp->green = *entry_start++; - pp->blue = *entry_start++; - pp->alpha = *entry_start++; - } - else - { - pp->red = png_get_uint_16(entry_start); entry_start += 2; - pp->green = png_get_uint_16(entry_start); entry_start += 2; - pp->blue = png_get_uint_16(entry_start); entry_start += 2; - pp->alpha = png_get_uint_16(entry_start); entry_start += 2; - } - pp->frequency = png_get_uint_16(entry_start); entry_start += 2; - } -#else - pp = new_palette.entries; - for (i = 0; i < new_palette.nentries; i++) - { - - if (new_palette.depth == 8) - { - pp[i].red = *entry_start++; - pp[i].green = *entry_start++; - pp[i].blue = *entry_start++; - pp[i].alpha = *entry_start++; - } - else - { - pp[i].red = png_get_uint_16(entry_start); entry_start += 2; - pp[i].green = png_get_uint_16(entry_start); entry_start += 2; - pp[i].blue = png_get_uint_16(entry_start); entry_start += 2; - pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2; - } - pp->frequency = png_get_uint_16(entry_start); entry_start += 2; - } -#endif - - /* discard all chunk data except the name and stash that */ - new_palette.name = (png_charp)chunkdata; - - png_set_sPLT(png_ptr, info_ptr, &new_palette, 1); - - png_free(png_ptr, chunkdata); - png_free(png_ptr, new_palette.entries); -} -#endif /* PNG_READ_sPLT_SUPPORTED */ - -#if defined(PNG_READ_tRNS_SUPPORTED) -void /* PRIVATE */ -png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -{ - png_byte readbuf[PNG_MAX_PALETTE_LENGTH]; - int bit_mask; - - png_debug(1, "in png_handle_tRNS\n"); - - /* For non-indexed color, mask off any bits in the tRNS value that - * exceed the bit depth. Some creators were writing extra bits there. - * This is not needed for indexed color. */ - bit_mask = (1 << png_ptr->bit_depth) - 1; - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before tRNS"); - else if (png_ptr->mode & PNG_HAVE_IDAT) - { - png_warning(png_ptr, "Invalid tRNS after IDAT"); - png_crc_finish(png_ptr, length); - return; - } - else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) - { - png_warning(png_ptr, "Duplicate tRNS chunk"); - png_crc_finish(png_ptr, length); - return; - } - - if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) - { - png_byte buf[2]; - - if (length != 2) - { - png_warning(png_ptr, "Incorrect tRNS chunk length"); - png_crc_finish(png_ptr, length); - return; - } - - png_crc_read(png_ptr, buf, 2); - png_ptr->num_trans = 1; - png_ptr->trans_values.gray = png_get_uint_16(buf) & bit_mask; - } - else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) - { - png_byte buf[6]; - - if (length != 6) - { - png_warning(png_ptr, "Incorrect tRNS chunk length"); - png_crc_finish(png_ptr, length); - return; - } - png_crc_read(png_ptr, buf, (png_size_t)length); - png_ptr->num_trans = 1; - png_ptr->trans_values.red = png_get_uint_16(buf) & bit_mask; - png_ptr->trans_values.green = png_get_uint_16(buf + 2) & bit_mask; - png_ptr->trans_values.blue = png_get_uint_16(buf + 4) & bit_mask; - } - else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - { - if (!(png_ptr->mode & PNG_HAVE_PLTE)) - { - /* Should be an error, but we can cope with it. */ - png_warning(png_ptr, "Missing PLTE before tRNS"); - } - if (length > (png_uint_32)png_ptr->num_palette || - length > PNG_MAX_PALETTE_LENGTH) - { - png_warning(png_ptr, "Incorrect tRNS chunk length"); - png_crc_finish(png_ptr, length); - return; - } - if (length == 0) - { - png_warning(png_ptr, "Zero length tRNS chunk"); - png_crc_finish(png_ptr, length); - return; - } - png_crc_read(png_ptr, readbuf, (png_size_t)length); - png_ptr->num_trans = (png_uint_16)length; - } - else - { - png_warning(png_ptr, "tRNS chunk not allowed with alpha channel"); - png_crc_finish(png_ptr, length); - return; - } - - if (png_crc_finish(png_ptr, 0)) - { - png_ptr->num_trans = 0; - return; - } - - png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans, - &(png_ptr->trans_values)); -} -#endif - -#if defined(PNG_READ_bKGD_SUPPORTED) -void /* PRIVATE */ -png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -{ - png_size_t truelen; - png_byte buf[6]; - - png_debug(1, "in png_handle_bKGD\n"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before bKGD"); - else if (png_ptr->mode & PNG_HAVE_IDAT) - { - png_warning(png_ptr, "Invalid bKGD after IDAT"); - png_crc_finish(png_ptr, length); - return; - } - else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && - !(png_ptr->mode & PNG_HAVE_PLTE)) - { - png_warning(png_ptr, "Missing PLTE before bKGD"); - png_crc_finish(png_ptr, length); - return; - } - else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD)) - { - png_warning(png_ptr, "Duplicate bKGD chunk"); - png_crc_finish(png_ptr, length); - return; - } - - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - truelen = 1; - else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) - truelen = 6; - else - truelen = 2; - - if (length != truelen) - { - png_warning(png_ptr, "Incorrect bKGD chunk length"); - png_crc_finish(png_ptr, length); - return; - } - - png_crc_read(png_ptr, buf, truelen); - if (png_crc_finish(png_ptr, 0)) - return; - - /* We convert the index value into RGB components so that we can allow - * arbitrary RGB values for background when we have transparency, and - * so it is easy to determine the RGB values of the background color - * from the info_ptr struct. */ - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - { - png_ptr->background.index = buf[0]; - if(info_ptr->num_palette) - { - if(buf[0] > info_ptr->num_palette) - { - png_warning(png_ptr, "Incorrect bKGD chunk index value"); - return; - } - png_ptr->background.red = - (png_uint_16)png_ptr->palette[buf[0]].red; - png_ptr->background.green = - (png_uint_16)png_ptr->palette[buf[0]].green; - png_ptr->background.blue = - (png_uint_16)png_ptr->palette[buf[0]].blue; - } - } - else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */ - { - png_ptr->background.red = - png_ptr->background.green = - png_ptr->background.blue = - png_ptr->background.gray = png_get_uint_16(buf); - } - else - { - png_ptr->background.red = png_get_uint_16(buf); - png_ptr->background.green = png_get_uint_16(buf + 2); - png_ptr->background.blue = png_get_uint_16(buf + 4); - } - - png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background)); -} -#endif - -#if defined(PNG_READ_hIST_SUPPORTED) -void /* PRIVATE */ -png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -{ - unsigned int num, i; - png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH]; - - png_debug(1, "in png_handle_hIST\n"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before hIST"); - else if (png_ptr->mode & PNG_HAVE_IDAT) - { - png_warning(png_ptr, "Invalid hIST after IDAT"); - png_crc_finish(png_ptr, length); - return; - } - else if (!(png_ptr->mode & PNG_HAVE_PLTE)) - { - png_warning(png_ptr, "Missing PLTE before hIST"); - png_crc_finish(png_ptr, length); - return; - } - else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST)) - { - png_warning(png_ptr, "Duplicate hIST chunk"); - png_crc_finish(png_ptr, length); - return; - } - - num = length / 2 ; - if (num != (unsigned int) png_ptr->num_palette || num > - (unsigned int) PNG_MAX_PALETTE_LENGTH) - { - png_warning(png_ptr, "Incorrect hIST chunk length"); - png_crc_finish(png_ptr, length); - return; - } - - for (i = 0; i < num; i++) - { - png_byte buf[2]; - - png_crc_read(png_ptr, buf, 2); - readbuf[i] = png_get_uint_16(buf); - } - - if (png_crc_finish(png_ptr, 0)) - return; - - png_set_hIST(png_ptr, info_ptr, readbuf); -} -#endif - -#if defined(PNG_READ_pHYs_SUPPORTED) -void /* PRIVATE */ -png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -{ - png_byte buf[9]; - png_uint_32 res_x, res_y; - int unit_type; - - png_debug(1, "in png_handle_pHYs\n"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before pHYs"); - else if (png_ptr->mode & PNG_HAVE_IDAT) - { - png_warning(png_ptr, "Invalid pHYs after IDAT"); - png_crc_finish(png_ptr, length); - return; - } - else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) - { - png_warning(png_ptr, "Duplicate pHYs chunk"); - png_crc_finish(png_ptr, length); - return; - } - - if (length != 9) - { - png_warning(png_ptr, "Incorrect pHYs chunk length"); - png_crc_finish(png_ptr, length); - return; - } - - png_crc_read(png_ptr, buf, 9); - if (png_crc_finish(png_ptr, 0)) - return; - - res_x = png_get_uint_32(buf); - res_y = png_get_uint_32(buf + 4); - unit_type = buf[8]; - png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type); -} -#endif - -#if defined(PNG_READ_oFFs_SUPPORTED) -void /* PRIVATE */ -png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -{ - png_byte buf[9]; - png_int_32 offset_x, offset_y; - int unit_type; - - png_debug(1, "in png_handle_oFFs\n"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before oFFs"); - else if (png_ptr->mode & PNG_HAVE_IDAT) - { - png_warning(png_ptr, "Invalid oFFs after IDAT"); - png_crc_finish(png_ptr, length); - return; - } - else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) - { - png_warning(png_ptr, "Duplicate oFFs chunk"); - png_crc_finish(png_ptr, length); - return; - } - - if (length != 9) - { - png_warning(png_ptr, "Incorrect oFFs chunk length"); - png_crc_finish(png_ptr, length); - return; - } - - png_crc_read(png_ptr, buf, 9); - if (png_crc_finish(png_ptr, 0)) - return; - - offset_x = png_get_int_32(buf); - offset_y = png_get_int_32(buf + 4); - unit_type = buf[8]; - png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type); -} -#endif - -#if defined(PNG_READ_pCAL_SUPPORTED) -/* read the pCAL chunk (described in the PNG Extensions document) */ -void /* PRIVATE */ -png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -{ - png_charp purpose; - png_int_32 X0, X1; - png_byte type, nparams; - png_charp buf, units, endptr; - png_charpp params; - png_size_t slength; - int i; - - png_debug(1, "in png_handle_pCAL\n"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before pCAL"); - else if (png_ptr->mode & PNG_HAVE_IDAT) - { - png_warning(png_ptr, "Invalid pCAL after IDAT"); - png_crc_finish(png_ptr, length); - return; - } - else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL)) - { - png_warning(png_ptr, "Duplicate pCAL chunk"); - png_crc_finish(png_ptr, length); - return; - } - - png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)\n", - length + 1); - purpose = (png_charp)png_malloc_warn(png_ptr, length + 1); - if (purpose == NULL) - { - png_warning(png_ptr, "No memory for pCAL purpose."); - return; - } - slength = (png_size_t)length; - png_crc_read(png_ptr, (png_bytep)purpose, slength); - - if (png_crc_finish(png_ptr, 0)) - { - png_free(png_ptr, purpose); - return; - } - - purpose[slength] = 0x00; /* null terminate the last string */ - - png_debug(3, "Finding end of pCAL purpose string\n"); - for (buf = purpose; *buf; buf++) - /* empty loop */ ; - - endptr = purpose + slength; - - /* We need to have at least 12 bytes after the purpose string - in order to get the parameter information. */ - if (endptr <= buf + 12) - { - png_warning(png_ptr, "Invalid pCAL data"); - png_free(png_ptr, purpose); - return; - } - - png_debug(3, "Reading pCAL X0, X1, type, nparams, and units\n"); - X0 = png_get_int_32((png_bytep)buf+1); - X1 = png_get_int_32((png_bytep)buf+5); - type = buf[9]; - nparams = buf[10]; - units = buf + 11; - - png_debug(3, "Checking pCAL equation type and number of parameters\n"); - /* Check that we have the right number of parameters for known - equation types. */ - if ((type == PNG_EQUATION_LINEAR && nparams != 2) || - (type == PNG_EQUATION_BASE_E && nparams != 3) || - (type == PNG_EQUATION_ARBITRARY && nparams != 3) || - (type == PNG_EQUATION_HYPERBOLIC && nparams != 4)) - { - png_warning(png_ptr, "Invalid pCAL parameters for equation type"); - png_free(png_ptr, purpose); - return; - } - else if (type >= PNG_EQUATION_LAST) - { - png_warning(png_ptr, "Unrecognized equation type for pCAL chunk"); - } - - for (buf = units; *buf; buf++) - /* Empty loop to move past the units string. */ ; - - png_debug(3, "Allocating pCAL parameters array\n"); - params = (png_charpp)png_malloc_warn(png_ptr, (png_uint_32)(nparams - *png_sizeof(png_charp))) ; - if (params == NULL) - { - png_free(png_ptr, purpose); - png_warning(png_ptr, "No memory for pCAL params."); - return; - } - - /* Get pointers to the start of each parameter string. */ - for (i = 0; i < (int)nparams; i++) - { - buf++; /* Skip the null string terminator from previous parameter. */ - - png_debug1(3, "Reading pCAL parameter %d\n", i); - for (params[i] = buf; buf <= endptr && *buf != 0x00; buf++) - /* Empty loop to move past each parameter string */ ; - - /* Make sure we haven't run out of data yet */ - if (buf > endptr) - { - png_warning(png_ptr, "Invalid pCAL data"); - png_free(png_ptr, purpose); - png_free(png_ptr, params); - return; - } - } - - png_set_pCAL(png_ptr, info_ptr, purpose, X0, X1, type, nparams, - units, params); - - png_free(png_ptr, purpose); - png_free(png_ptr, params); -} -#endif - -#if defined(PNG_READ_sCAL_SUPPORTED) -/* read the sCAL chunk */ -void /* PRIVATE */ -png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -{ - png_charp buffer, ep; -#ifdef PNG_FLOATING_POINT_SUPPORTED - double width, height; - png_charp vp; -#else -#ifdef PNG_FIXED_POINT_SUPPORTED - png_charp swidth, sheight; -#endif -#endif - png_size_t slength; - - png_debug(1, "in png_handle_sCAL\n"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before sCAL"); - else if (png_ptr->mode & PNG_HAVE_IDAT) - { - png_warning(png_ptr, "Invalid sCAL after IDAT"); - png_crc_finish(png_ptr, length); - return; - } - else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL)) - { - png_warning(png_ptr, "Duplicate sCAL chunk"); - png_crc_finish(png_ptr, length); - return; - } - - png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)\n", - length + 1); - buffer = (png_charp)png_malloc_warn(png_ptr, length + 1); - if (buffer == NULL) - { - png_warning(png_ptr, "Out of memory while processing sCAL chunk"); - return; - } - slength = (png_size_t)length; - png_crc_read(png_ptr, (png_bytep)buffer, slength); - - if (png_crc_finish(png_ptr, 0)) - { - png_free(png_ptr, buffer); - return; - } - - buffer[slength] = 0x00; /* null terminate the last string */ - - ep = buffer + 1; /* skip unit byte */ - -#ifdef PNG_FLOATING_POINT_SUPPORTED - width = png_strtod(png_ptr, ep, &vp); - if (*vp) - { - png_warning(png_ptr, "malformed width string in sCAL chunk"); - return; - } -#else -#ifdef PNG_FIXED_POINT_SUPPORTED - swidth = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1); - if (swidth == NULL) - { - png_warning(png_ptr, "Out of memory while processing sCAL chunk width"); - return; - } - png_memcpy(swidth, ep, (png_size_t)png_strlen(ep)); -#endif -#endif - - for (ep = buffer; *ep; ep++) - /* empty loop */ ; - ep++; - - if (buffer + slength < ep) - { - png_warning(png_ptr, "Truncated sCAL chunk"); -#if defined(PNG_FIXED_POINT_SUPPORTED) && \ - !defined(PNG_FLOATING_POINT_SUPPORTED) - png_free(png_ptr, swidth); -#endif - png_free(png_ptr, buffer); - return; - } - -#ifdef PNG_FLOATING_POINT_SUPPORTED - height = png_strtod(png_ptr, ep, &vp); - if (*vp) - { - png_warning(png_ptr, "malformed height string in sCAL chunk"); - return; - } -#else -#ifdef PNG_FIXED_POINT_SUPPORTED - sheight = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1); - if (swidth == NULL) - { - png_warning(png_ptr, "Out of memory while processing sCAL chunk height"); - return; - } - png_memcpy(sheight, ep, (png_size_t)png_strlen(ep)); -#endif -#endif - - if (buffer + slength < ep -#ifdef PNG_FLOATING_POINT_SUPPORTED - || width <= 0. || height <= 0. -#endif - ) - { - png_warning(png_ptr, "Invalid sCAL data"); - png_free(png_ptr, buffer); -#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED) - png_free(png_ptr, swidth); - png_free(png_ptr, sheight); -#endif - return; - } - - -#ifdef PNG_FLOATING_POINT_SUPPORTED - png_set_sCAL(png_ptr, info_ptr, buffer[0], width, height); -#else -#ifdef PNG_FIXED_POINT_SUPPORTED - png_set_sCAL_s(png_ptr, info_ptr, buffer[0], swidth, sheight); -#endif -#endif - - png_free(png_ptr, buffer); -#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED) - png_free(png_ptr, swidth); - png_free(png_ptr, sheight); -#endif -} -#endif - -#if defined(PNG_READ_tIME_SUPPORTED) -void /* PRIVATE */ -png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -{ - png_byte buf[7]; - png_time mod_time; - - png_debug(1, "in png_handle_tIME\n"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Out of place tIME chunk"); - else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME)) - { - png_warning(png_ptr, "Duplicate tIME chunk"); - png_crc_finish(png_ptr, length); - return; - } - - if (png_ptr->mode & PNG_HAVE_IDAT) - png_ptr->mode |= PNG_AFTER_IDAT; - - if (length != 7) - { - png_warning(png_ptr, "Incorrect tIME chunk length"); - png_crc_finish(png_ptr, length); - return; - } - - png_crc_read(png_ptr, buf, 7); - if (png_crc_finish(png_ptr, 0)) - return; - - mod_time.second = buf[6]; - mod_time.minute = buf[5]; - mod_time.hour = buf[4]; - mod_time.day = buf[3]; - mod_time.month = buf[2]; - mod_time.year = png_get_uint_16(buf); - - png_set_tIME(png_ptr, info_ptr, &mod_time); -} -#endif - -#if defined(PNG_READ_tEXt_SUPPORTED) -/* Note: this does not properly handle chunks that are > 64K under DOS */ -void /* PRIVATE */ -png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -{ - png_textp text_ptr; - png_charp key; - png_charp text; - png_uint_32 skip = 0; - png_size_t slength; - int ret; - - png_debug(1, "in png_handle_tEXt\n"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before tEXt"); - - if (png_ptr->mode & PNG_HAVE_IDAT) - png_ptr->mode |= PNG_AFTER_IDAT; - -#ifdef PNG_MAX_MALLOC_64K - if (length > (png_uint_32)65535L) - { - png_warning(png_ptr, "tEXt chunk too large to fit in memory"); - skip = length - (png_uint_32)65535L; - length = (png_uint_32)65535L; - } -#endif - - key = (png_charp)png_malloc_warn(png_ptr, length + 1); - if (key == NULL) - { - png_warning(png_ptr, "No memory to process text chunk."); - return; - } - slength = (png_size_t)length; - png_crc_read(png_ptr, (png_bytep)key, slength); - - if (png_crc_finish(png_ptr, skip)) - { - png_free(png_ptr, key); - return; - } - - key[slength] = 0x00; - - for (text = key; *text; text++) - /* empty loop to find end of key */ ; - - if (text != key + slength) - text++; - - text_ptr = (png_textp)png_malloc_warn(png_ptr, - (png_uint_32)png_sizeof(png_text)); - if (text_ptr == NULL) - { - png_warning(png_ptr, "Not enough memory to process text chunk."); - png_free(png_ptr, key); - return; - } - text_ptr->compression = PNG_TEXT_COMPRESSION_NONE; - text_ptr->key = key; -#ifdef PNG_iTXt_SUPPORTED - text_ptr->lang = NULL; - text_ptr->lang_key = NULL; - text_ptr->itxt_length = 0; -#endif - text_ptr->text = text; - text_ptr->text_length = png_strlen(text); - - ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1); - - png_free(png_ptr, key); - png_free(png_ptr, text_ptr); - if (ret) - png_warning(png_ptr, "Insufficient memory to process text chunk."); -} -#endif - -#if defined(PNG_READ_zTXt_SUPPORTED) -/* note: this does not correctly handle chunks that are > 64K under DOS */ -void /* PRIVATE */ -png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -{ - png_textp text_ptr; - png_charp chunkdata; - png_charp text; - int comp_type; - int ret; - png_size_t slength, prefix_len, data_len; - - png_debug(1, "in png_handle_zTXt\n"); - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before zTXt"); - - if (png_ptr->mode & PNG_HAVE_IDAT) - png_ptr->mode |= PNG_AFTER_IDAT; - -#ifdef PNG_MAX_MALLOC_64K - /* We will no doubt have problems with chunks even half this size, but - there is no hard and fast rule to tell us where to stop. */ - if (length > (png_uint_32)65535L) - { - png_warning(png_ptr,"zTXt chunk too large to fit in memory"); - png_crc_finish(png_ptr, length); - return; - } -#endif - - chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); - if (chunkdata == NULL) - { - png_warning(png_ptr,"Out of memory processing zTXt chunk."); - return; - } - slength = (png_size_t)length; - png_crc_read(png_ptr, (png_bytep)chunkdata, slength); - if (png_crc_finish(png_ptr, 0)) - { - png_free(png_ptr, chunkdata); - return; - } - - chunkdata[slength] = 0x00; - - for (text = chunkdata; *text; text++) - /* empty loop */ ; - - /* zTXt must have some text after the chunkdataword */ - if (text >= chunkdata + slength - 2) - { - png_warning(png_ptr, "Truncated zTXt chunk"); - png_free(png_ptr, chunkdata); - return; - } - else - { - comp_type = *(++text); - if (comp_type != PNG_TEXT_COMPRESSION_zTXt) - { - png_warning(png_ptr, "Unknown compression type in zTXt chunk"); - comp_type = PNG_TEXT_COMPRESSION_zTXt; - } - text++; /* skip the compression_method byte */ - } - prefix_len = text - chunkdata; - - chunkdata = (png_charp)png_decompress_chunk(png_ptr, comp_type, chunkdata, - (png_size_t)length, prefix_len, &data_len); - - text_ptr = (png_textp)png_malloc_warn(png_ptr, - (png_uint_32)png_sizeof(png_text)); - if (text_ptr == NULL) - { - png_warning(png_ptr,"Not enough memory to process zTXt chunk."); - png_free(png_ptr, chunkdata); - return; - } - text_ptr->compression = comp_type; - text_ptr->key = chunkdata; -#ifdef PNG_iTXt_SUPPORTED - text_ptr->lang = NULL; - text_ptr->lang_key = NULL; - text_ptr->itxt_length = 0; -#endif - text_ptr->text = chunkdata + prefix_len; - text_ptr->text_length = data_len; - - ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1); - - png_free(png_ptr, text_ptr); - png_free(png_ptr, chunkdata); - if (ret) - png_error(png_ptr, "Insufficient memory to store zTXt chunk."); -} -#endif - -#if defined(PNG_READ_iTXt_SUPPORTED) -/* note: this does not correctly handle chunks that are > 64K under DOS */ -void /* PRIVATE */ -png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -{ - png_textp text_ptr; - png_charp chunkdata; - png_charp key, lang, text, lang_key; - int comp_flag; - int comp_type = 0; - int ret; - png_size_t slength, prefix_len, data_len; - - png_debug(1, "in png_handle_iTXt\n"); - - if (!(png_ptr->mode & PNG_HAVE_IHDR)) - png_error(png_ptr, "Missing IHDR before iTXt"); - - if (png_ptr->mode & PNG_HAVE_IDAT) - png_ptr->mode |= PNG_AFTER_IDAT; - -#ifdef PNG_MAX_MALLOC_64K - /* We will no doubt have problems with chunks even half this size, but - there is no hard and fast rule to tell us where to stop. */ - if (length > (png_uint_32)65535L) - { - png_warning(png_ptr,"iTXt chunk too large to fit in memory"); - png_crc_finish(png_ptr, length); - return; - } -#endif - - chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); - if (chunkdata == NULL) - { - png_warning(png_ptr, "No memory to process iTXt chunk."); - return; - } - slength = (png_size_t)length; - png_crc_read(png_ptr, (png_bytep)chunkdata, slength); - if (png_crc_finish(png_ptr, 0)) - { - png_free(png_ptr, chunkdata); - return; - } - - chunkdata[slength] = 0x00; - - for (lang = chunkdata; *lang; lang++) - /* empty loop */ ; - lang++; /* skip NUL separator */ - - /* iTXt must have a language tag (possibly empty), two compression bytes, - translated keyword (possibly empty), and possibly some text after the - keyword */ - - if (lang >= chunkdata + slength - 3) - { - png_warning(png_ptr, "Truncated iTXt chunk"); - png_free(png_ptr, chunkdata); - return; - } - else - { - comp_flag = *lang++; - comp_type = *lang++; - } - - for (lang_key = lang; *lang_key; lang_key++) - /* empty loop */ ; - lang_key++; /* skip NUL separator */ - - if (lang_key >= chunkdata + slength) - { - png_warning(png_ptr, "Truncated iTXt chunk"); - png_free(png_ptr, chunkdata); - return; - } - - for (text = lang_key; *text; text++) - /* empty loop */ ; - text++; /* skip NUL separator */ - if (text >= chunkdata + slength) - { - png_warning(png_ptr, "Malformed iTXt chunk"); - png_free(png_ptr, chunkdata); - return; - } - - prefix_len = text - chunkdata; - - key=chunkdata; - if (comp_flag) - chunkdata = png_decompress_chunk(png_ptr, comp_type, chunkdata, - (size_t)length, prefix_len, &data_len); - else - data_len=png_strlen(chunkdata + prefix_len); - text_ptr = (png_textp)png_malloc_warn(png_ptr, - (png_uint_32)png_sizeof(png_text)); - if (text_ptr == NULL) - { - png_warning(png_ptr,"Not enough memory to process iTXt chunk."); - png_free(png_ptr, chunkdata); - return; - } - text_ptr->compression = (int)comp_flag + 1; - text_ptr->lang_key = chunkdata+(lang_key-key); - text_ptr->lang = chunkdata+(lang-key); - text_ptr->itxt_length = data_len; - text_ptr->text_length = 0; - text_ptr->key = chunkdata; - text_ptr->text = chunkdata + prefix_len; - - ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1); - - png_free(png_ptr, text_ptr); - png_free(png_ptr, chunkdata); - if (ret) - png_error(png_ptr, "Insufficient memory to store iTXt chunk."); -} -#endif - -/* This function is called when we haven't found a handler for a - chunk. If there isn't a problem with the chunk itself (ie bad - chunk name, CRC, or a critical chunk), the chunk is silently ignored - -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which - case it will be saved away to be written out later. */ -void /* PRIVATE */ -png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) -{ - png_uint_32 skip = 0; - - png_debug(1, "in png_handle_unknown\n"); - - if (png_ptr->mode & PNG_HAVE_IDAT) - { -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_CONST PNG_IDAT; -#endif - if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* not an IDAT */ - png_ptr->mode |= PNG_AFTER_IDAT; - } - - png_check_chunk_name(png_ptr, png_ptr->chunk_name); - - if (!(png_ptr->chunk_name[0] & 0x20)) - { -#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) - if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != - PNG_HANDLE_CHUNK_ALWAYS -#if defined(PNG_READ_USER_CHUNKS_SUPPORTED) - && png_ptr->read_user_chunk_fn == NULL -#endif - ) -#endif - png_chunk_error(png_ptr, "unknown critical chunk"); - } - -#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) - if ((png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) || - (png_ptr->read_user_chunk_fn != NULL)) - { -#ifdef PNG_MAX_MALLOC_64K - if (length > (png_uint_32)65535L) - { - png_warning(png_ptr, "unknown chunk too large to fit in memory"); - skip = length - (png_uint_32)65535L; - length = (png_uint_32)65535L; - } -#endif - png_memcpy((png_charp)png_ptr->unknown_chunk.name, - (png_charp)png_ptr->chunk_name, - png_sizeof(png_ptr->unknown_chunk.name)); - png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name)-1] = '\0'; - png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length); - png_ptr->unknown_chunk.size = (png_size_t)length; - png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length); -#if defined(PNG_READ_USER_CHUNKS_SUPPORTED) - if(png_ptr->read_user_chunk_fn != NULL) - { - /* callback to user unknown chunk handler */ - int ret; - ret = (*(png_ptr->read_user_chunk_fn)) - (png_ptr, &png_ptr->unknown_chunk); - if (ret < 0) - png_chunk_error(png_ptr, "error in user chunk"); - if (ret == 0) - { - if (!(png_ptr->chunk_name[0] & 0x20)) - if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != - PNG_HANDLE_CHUNK_ALWAYS) - png_chunk_error(png_ptr, "unknown critical chunk"); - png_set_unknown_chunks(png_ptr, info_ptr, - &png_ptr->unknown_chunk, 1); - } - } -#else - png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1); -#endif - png_free(png_ptr, png_ptr->unknown_chunk.data); - png_ptr->unknown_chunk.data = NULL; - } - else -#endif - skip = length; - - png_crc_finish(png_ptr, skip); - -#if !defined(PNG_READ_USER_CHUNKS_SUPPORTED) - info_ptr = info_ptr; /* quiet compiler warnings about unused info_ptr */ -#endif -} - -/* This function is called to verify that a chunk name is valid. - This function can't have the "critical chunk check" incorporated - into it, since in the future we will need to be able to call user - functions to handle unknown critical chunks after we check that - the chunk name itself is valid. */ - -#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) - -void /* PRIVATE */ -png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name) -{ - png_debug(1, "in png_check_chunk_name\n"); - if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) || - isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3])) - { - png_chunk_error(png_ptr, "invalid chunk type"); - } -} - -/* Combines the row recently read in with the existing pixels in the - row. This routine takes care of alpha and transparency if requested. - This routine also handles the two methods of progressive display - of interlaced images, depending on the mask value. - The mask value describes which pixels are to be combined with - the row. The pattern always repeats every 8 pixels, so just 8 - bits are needed. A one indicates the pixel is to be combined, - a zero indicates the pixel is to be skipped. This is in addition - to any alpha or transparency value associated with the pixel. If - you want all pixels to be combined, pass 0xff (255) in mask. */ - -void /* PRIVATE */ -png_combine_row(png_structp png_ptr, png_bytep row, int mask) -{ - png_debug(1,"in png_combine_row\n"); - if (mask == 0xff) - { - png_memcpy(row, png_ptr->row_buf + 1, - PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width)); - } - else - { - switch (png_ptr->row_info.pixel_depth) - { - case 1: - { - png_bytep sp = png_ptr->row_buf + 1; - png_bytep dp = row; - int s_inc, s_start, s_end; - int m = 0x80; - int shift; - png_uint_32 i; - png_uint_32 row_width = png_ptr->width; - -#if defined(PNG_READ_PACKSWAP_SUPPORTED) - if (png_ptr->transformations & PNG_PACKSWAP) - { - s_start = 0; - s_end = 7; - s_inc = 1; - } - else -#endif - { - s_start = 7; - s_end = 0; - s_inc = -1; - } - - shift = s_start; - - for (i = 0; i < row_width; i++) - { - if (m & mask) - { - int value; - - value = (*sp >> shift) & 0x01; - *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff); - *dp |= (png_byte)(value << shift); - } - - if (shift == s_end) - { - shift = s_start; - sp++; - dp++; - } - else - shift += s_inc; - - if (m == 1) - m = 0x80; - else - m >>= 1; - } - break; - } - case 2: - { - png_bytep sp = png_ptr->row_buf + 1; - png_bytep dp = row; - int s_start, s_end, s_inc; - int m = 0x80; - int shift; - png_uint_32 i; - png_uint_32 row_width = png_ptr->width; - int value; - -#if defined(PNG_READ_PACKSWAP_SUPPORTED) - if (png_ptr->transformations & PNG_PACKSWAP) - { - s_start = 0; - s_end = 6; - s_inc = 2; - } - else -#endif - { - s_start = 6; - s_end = 0; - s_inc = -2; - } - - shift = s_start; - - for (i = 0; i < row_width; i++) - { - if (m & mask) - { - value = (*sp >> shift) & 0x03; - *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); - *dp |= (png_byte)(value << shift); - } - - if (shift == s_end) - { - shift = s_start; - sp++; - dp++; - } - else - shift += s_inc; - if (m == 1) - m = 0x80; - else - m >>= 1; - } - break; - } - case 4: - { - png_bytep sp = png_ptr->row_buf + 1; - png_bytep dp = row; - int s_start, s_end, s_inc; - int m = 0x80; - int shift; - png_uint_32 i; - png_uint_32 row_width = png_ptr->width; - int value; - -#if defined(PNG_READ_PACKSWAP_SUPPORTED) - if (png_ptr->transformations & PNG_PACKSWAP) - { - s_start = 0; - s_end = 4; - s_inc = 4; - } - else -#endif - { - s_start = 4; - s_end = 0; - s_inc = -4; - } - shift = s_start; - - for (i = 0; i < row_width; i++) - { - if (m & mask) - { - value = (*sp >> shift) & 0xf; - *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); - *dp |= (png_byte)(value << shift); - } - - if (shift == s_end) - { - shift = s_start; - sp++; - dp++; - } - else - shift += s_inc; - if (m == 1) - m = 0x80; - else - m >>= 1; - } - break; - } - default: - { - png_bytep sp = png_ptr->row_buf + 1; - png_bytep dp = row; - png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3); - png_uint_32 i; - png_uint_32 row_width = png_ptr->width; - png_byte m = 0x80; - - - for (i = 0; i < row_width; i++) - { - if (m & mask) - { - png_memcpy(dp, sp, pixel_bytes); - } - - sp += pixel_bytes; - dp += pixel_bytes; - - if (m == 1) - m = 0x80; - else - m >>= 1; - } - break; - } - } - } -} - -#ifdef PNG_READ_INTERLACING_SUPPORTED -/* OLD pre-1.0.9 interface: -void png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, - png_uint_32 transformations) - */ -void /* PRIVATE */ -png_do_read_interlace(png_structp png_ptr) -{ - png_row_infop row_info = &(png_ptr->row_info); - png_bytep row = png_ptr->row_buf + 1; - int pass = png_ptr->pass; - png_uint_32 transformations = png_ptr->transformations; -#ifdef PNG_USE_LOCAL_ARRAYS - /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - /* offset to next interlace block */ - PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; -#endif - - png_debug(1,"in png_do_read_interlace\n"); - if (row != NULL && row_info != NULL) - { - png_uint_32 final_width; - - final_width = row_info->width * png_pass_inc[pass]; - - switch (row_info->pixel_depth) - { - case 1: - { - png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3); - png_bytep dp = row + (png_size_t)((final_width - 1) >> 3); - int sshift, dshift; - int s_start, s_end, s_inc; - int jstop = png_pass_inc[pass]; - png_byte v; - png_uint_32 i; - int j; - -#if defined(PNG_READ_PACKSWAP_SUPPORTED) - if (transformations & PNG_PACKSWAP) - { - sshift = (int)((row_info->width + 7) & 0x07); - dshift = (int)((final_width + 7) & 0x07); - s_start = 7; - s_end = 0; - s_inc = -1; - } - else -#endif - { - sshift = 7 - (int)((row_info->width + 7) & 0x07); - dshift = 7 - (int)((final_width + 7) & 0x07); - s_start = 0; - s_end = 7; - s_inc = 1; - } - - for (i = 0; i < row_info->width; i++) - { - v = (png_byte)((*sp >> sshift) & 0x01); - for (j = 0; j < jstop; j++) - { - *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff); - *dp |= (png_byte)(v << dshift); - if (dshift == s_end) - { - dshift = s_start; - dp--; - } - else - dshift += s_inc; - } - if (sshift == s_end) - { - sshift = s_start; - sp--; - } - else - sshift += s_inc; - } - break; - } - case 2: - { - png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2); - png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2); - int sshift, dshift; - int s_start, s_end, s_inc; - int jstop = png_pass_inc[pass]; - png_uint_32 i; - -#if defined(PNG_READ_PACKSWAP_SUPPORTED) - if (transformations & PNG_PACKSWAP) - { - sshift = (int)(((row_info->width + 3) & 0x03) << 1); - dshift = (int)(((final_width + 3) & 0x03) << 1); - s_start = 6; - s_end = 0; - s_inc = -2; - } - else -#endif - { - sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1); - dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1); - s_start = 0; - s_end = 6; - s_inc = 2; - } - - for (i = 0; i < row_info->width; i++) - { - png_byte v; - int j; - - v = (png_byte)((*sp >> sshift) & 0x03); - for (j = 0; j < jstop; j++) - { - *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff); - *dp |= (png_byte)(v << dshift); - if (dshift == s_end) - { - dshift = s_start; - dp--; - } - else - dshift += s_inc; - } - if (sshift == s_end) - { - sshift = s_start; - sp--; - } - else - sshift += s_inc; - } - break; - } - case 4: - { - png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1); - png_bytep dp = row + (png_size_t)((final_width - 1) >> 1); - int sshift, dshift; - int s_start, s_end, s_inc; - png_uint_32 i; - int jstop = png_pass_inc[pass]; - -#if defined(PNG_READ_PACKSWAP_SUPPORTED) - if (transformations & PNG_PACKSWAP) - { - sshift = (int)(((row_info->width + 1) & 0x01) << 2); - dshift = (int)(((final_width + 1) & 0x01) << 2); - s_start = 4; - s_end = 0; - s_inc = -4; - } - else -#endif - { - sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2); - dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2); - s_start = 0; - s_end = 4; - s_inc = 4; - } - - for (i = 0; i < row_info->width; i++) - { - png_byte v = (png_byte)((*sp >> sshift) & 0xf); - int j; - - for (j = 0; j < jstop; j++) - { - *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff); - *dp |= (png_byte)(v << dshift); - if (dshift == s_end) - { - dshift = s_start; - dp--; - } - else - dshift += s_inc; - } - if (sshift == s_end) - { - sshift = s_start; - sp--; - } - else - sshift += s_inc; - } - break; - } - default: - { - png_size_t pixel_bytes = (row_info->pixel_depth >> 3); - png_bytep sp = row + (png_size_t)(row_info->width - 1) * pixel_bytes; - png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes; - - int jstop = png_pass_inc[pass]; - png_uint_32 i; - - for (i = 0; i < row_info->width; i++) - { - png_byte v[8]; - int j; - - png_memcpy(v, sp, pixel_bytes); - for (j = 0; j < jstop; j++) - { - png_memcpy(dp, v, pixel_bytes); - dp -= pixel_bytes; - } - sp -= pixel_bytes; - } - break; - } - } - row_info->width = final_width; - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,final_width); - } -#if !defined(PNG_READ_PACKSWAP_SUPPORTED) - transformations = transformations; /* silence compiler warning */ -#endif -} -#endif /* PNG_READ_INTERLACING_SUPPORTED */ - -void /* PRIVATE */ -png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row, - png_bytep prev_row, int filter) -{ - png_debug(1, "in png_read_filter_row\n"); - png_debug2(2,"row = %lu, filter = %d\n", png_ptr->row_number, filter); - switch (filter) - { - case PNG_FILTER_VALUE_NONE: - break; - case PNG_FILTER_VALUE_SUB: - { - png_uint_32 i; - png_uint_32 istop = row_info->rowbytes; - png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; - png_bytep rp = row + bpp; - png_bytep lp = row; - - for (i = bpp; i < istop; i++) - { - *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff); - rp++; - } - break; - } - case PNG_FILTER_VALUE_UP: - { - png_uint_32 i; - png_uint_32 istop = row_info->rowbytes; - png_bytep rp = row; - png_bytep pp = prev_row; - - for (i = 0; i < istop; i++) - { - *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); - rp++; - } - break; - } - case PNG_FILTER_VALUE_AVG: - { - png_uint_32 i; - png_bytep rp = row; - png_bytep pp = prev_row; - png_bytep lp = row; - png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; - png_uint_32 istop = row_info->rowbytes - bpp; - - for (i = 0; i < bpp; i++) - { - *rp = (png_byte)(((int)(*rp) + - ((int)(*pp++) / 2 )) & 0xff); - rp++; - } - - for (i = 0; i < istop; i++) - { - *rp = (png_byte)(((int)(*rp) + - (int)(*pp++ + *lp++) / 2 ) & 0xff); - rp++; - } - break; - } - case PNG_FILTER_VALUE_PAETH: - { - png_uint_32 i; - png_bytep rp = row; - png_bytep pp = prev_row; - png_bytep lp = row; - png_bytep cp = prev_row; - png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3; - png_uint_32 istop=row_info->rowbytes - bpp; - - for (i = 0; i < bpp; i++) - { - *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); - rp++; - } - - for (i = 0; i < istop; i++) /* use leftover rp,pp */ - { - int a, b, c, pa, pb, pc, p; - - a = *lp++; - b = *pp++; - c = *cp++; - - p = b - c; - pc = a - c; - -#ifdef PNG_USE_ABS - pa = abs(p); - pb = abs(pc); - pc = abs(p + pc); -#else - pa = p < 0 ? -p : p; - pb = pc < 0 ? -pc : pc; - pc = (p + pc) < 0 ? -(p + pc) : p + pc; -#endif - - /* - if (pa <= pb && pa <= pc) - p = a; - else if (pb <= pc) - p = b; - else - p = c; - */ - - p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; - - *rp = (png_byte)(((int)(*rp) + p) & 0xff); - rp++; - } - break; - } - default: - png_warning(png_ptr, "Ignoring bad adaptive filter type"); - *row=0; - break; - } -} - -void /* PRIVATE */ -png_read_finish_row(png_structp png_ptr) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - - /* start of interlace block */ - PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; - - /* offset to next interlace block */ - PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; - - /* start of interlace block in the y direction */ - PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; - - /* offset to next interlace block in the y direction */ - PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; -#endif - - png_debug(1, "in png_read_finish_row\n"); - png_ptr->row_number++; - if (png_ptr->row_number < png_ptr->num_rows) - return; - - if (png_ptr->interlaced) - { - png_ptr->row_number = 0; - png_memset_check(png_ptr, png_ptr->prev_row, 0, - png_ptr->rowbytes + 1); - do - { - png_ptr->pass++; - if (png_ptr->pass >= 7) - break; - png_ptr->iwidth = (png_ptr->width + - png_pass_inc[png_ptr->pass] - 1 - - png_pass_start[png_ptr->pass]) / - png_pass_inc[png_ptr->pass]; - - png_ptr->irowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, - png_ptr->iwidth) + 1; - - if (!(png_ptr->transformations & PNG_INTERLACE)) - { - png_ptr->num_rows = (png_ptr->height + - png_pass_yinc[png_ptr->pass] - 1 - - png_pass_ystart[png_ptr->pass]) / - png_pass_yinc[png_ptr->pass]; - if (!(png_ptr->num_rows)) - continue; - } - else /* if (png_ptr->transformations & PNG_INTERLACE) */ - break; - } while (png_ptr->iwidth == 0); - - if (png_ptr->pass < 7) - return; - } - - if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) - { -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_CONST PNG_IDAT; -#endif - char extra; - int ret; - - png_ptr->zstream.next_out = (Byte *)&extra; - png_ptr->zstream.avail_out = (uInt)1; - for(;;) - { - if (!(png_ptr->zstream.avail_in)) - { - while (!png_ptr->idat_size) - { - png_byte chunk_length[4]; - - png_crc_finish(png_ptr, 0); - - png_read_data(png_ptr, chunk_length, 4); - png_ptr->idat_size = png_get_uint_31(png_ptr, chunk_length); - png_reset_crc(png_ptr); - png_crc_read(png_ptr, png_ptr->chunk_name, 4); - if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) - png_error(png_ptr, "Not enough image data"); - - } - png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size; - png_ptr->zstream.next_in = png_ptr->zbuf; - if (png_ptr->zbuf_size > png_ptr->idat_size) - png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size; - png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in); - png_ptr->idat_size -= png_ptr->zstream.avail_in; - } - ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); - if (ret == Z_STREAM_END) - { - if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in || - png_ptr->idat_size) - png_warning(png_ptr, "Extra compressed data"); - png_ptr->mode |= PNG_AFTER_IDAT; - png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; - break; - } - if (ret != Z_OK) - png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg : - "Decompression Error"); - - if (!(png_ptr->zstream.avail_out)) - { - png_warning(png_ptr, "Extra compressed data."); - png_ptr->mode |= PNG_AFTER_IDAT; - png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; - break; - } - - } - png_ptr->zstream.avail_out = 0; - } - - if (png_ptr->idat_size || png_ptr->zstream.avail_in) - png_warning(png_ptr, "Extra compression data"); - - inflateReset(&png_ptr->zstream); - - png_ptr->mode |= PNG_AFTER_IDAT; -} - -void /* PRIVATE */ -png_read_start_row(png_structp png_ptr) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - - /* start of interlace block */ - PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; - - /* offset to next interlace block */ - PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; - - /* start of interlace block in the y direction */ - PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; - - /* offset to next interlace block in the y direction */ - PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; -#endif - - int max_pixel_depth; - png_uint_32 row_bytes; - - png_debug(1, "in png_read_start_row\n"); - png_ptr->zstream.avail_in = 0; - png_init_read_transformations(png_ptr); - if (png_ptr->interlaced) - { - if (!(png_ptr->transformations & PNG_INTERLACE)) - png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - - png_pass_ystart[0]) / png_pass_yinc[0]; - else - png_ptr->num_rows = png_ptr->height; - - png_ptr->iwidth = (png_ptr->width + - png_pass_inc[png_ptr->pass] - 1 - - png_pass_start[png_ptr->pass]) / - png_pass_inc[png_ptr->pass]; - - row_bytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->iwidth) + 1; - - png_ptr->irowbytes = (png_size_t)row_bytes; - if((png_uint_32)png_ptr->irowbytes != row_bytes) - png_error(png_ptr, "Rowbytes overflow in png_read_start_row"); - } - else - { - png_ptr->num_rows = png_ptr->height; - png_ptr->iwidth = png_ptr->width; - png_ptr->irowbytes = png_ptr->rowbytes + 1; - } - max_pixel_depth = png_ptr->pixel_depth; - -#if defined(PNG_READ_PACK_SUPPORTED) - if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8) - max_pixel_depth = 8; -#endif - -#if defined(PNG_READ_EXPAND_SUPPORTED) - if (png_ptr->transformations & PNG_EXPAND) - { - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - { - if (png_ptr->num_trans) - max_pixel_depth = 32; - else - max_pixel_depth = 24; - } - else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) - { - if (max_pixel_depth < 8) - max_pixel_depth = 8; - if (png_ptr->num_trans) - max_pixel_depth *= 2; - } - else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) - { - if (png_ptr->num_trans) - { - max_pixel_depth *= 4; - max_pixel_depth /= 3; - } - } - } -#endif - -#if defined(PNG_READ_FILLER_SUPPORTED) - if (png_ptr->transformations & (PNG_FILLER)) - { - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - max_pixel_depth = 32; - else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) - { - if (max_pixel_depth <= 8) - max_pixel_depth = 16; - else - max_pixel_depth = 32; - } - else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) - { - if (max_pixel_depth <= 32) - max_pixel_depth = 32; - else - max_pixel_depth = 64; - } - } -#endif - -#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) - if (png_ptr->transformations & PNG_GRAY_TO_RGB) - { - if ( -#if defined(PNG_READ_EXPAND_SUPPORTED) - (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) || -#endif -#if defined(PNG_READ_FILLER_SUPPORTED) - (png_ptr->transformations & (PNG_FILLER)) || -#endif - png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - { - if (max_pixel_depth <= 16) - max_pixel_depth = 32; - else - max_pixel_depth = 64; - } - else - { - if (max_pixel_depth <= 8) - { - if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - max_pixel_depth = 32; - else - max_pixel_depth = 24; - } - else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - max_pixel_depth = 64; - else - max_pixel_depth = 48; - } - } -#endif - -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \ -defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) - if(png_ptr->transformations & PNG_USER_TRANSFORM) - { - int user_pixel_depth=png_ptr->user_transform_depth* - png_ptr->user_transform_channels; - if(user_pixel_depth > max_pixel_depth) - max_pixel_depth=user_pixel_depth; - } -#endif - - /* align the width on the next larger 8 pixels. Mainly used - for interlacing */ - row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7)); - /* calculate the maximum bytes needed, adding a byte and a pixel - for safety's sake */ - row_bytes = PNG_ROWBYTES(max_pixel_depth,row_bytes) + - 1 + ((max_pixel_depth + 7) >> 3); -#ifdef PNG_MAX_MALLOC_64K - if (row_bytes > (png_uint_32)65536L) - png_error(png_ptr, "This image requires a row greater than 64KB"); -#endif - png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes+64); - png_ptr->row_buf = png_ptr->big_row_buf+32; - -#ifdef PNG_MAX_MALLOC_64K - if ((png_uint_32)png_ptr->rowbytes + 1 > (png_uint_32)65536L) - png_error(png_ptr, "This image requires a row greater than 64KB"); -#endif - if ((png_uint_32)png_ptr->rowbytes > (png_uint_32)(PNG_SIZE_MAX - 1)) - png_error(png_ptr, "Row has too many bytes to allocate in memory."); - png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)( - png_ptr->rowbytes + 1)); - - png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1); - - png_debug1(3, "width = %lu,\n", png_ptr->width); - png_debug1(3, "height = %lu,\n", png_ptr->height); - png_debug1(3, "iwidth = %lu,\n", png_ptr->iwidth); - png_debug1(3, "num_rows = %lu\n", png_ptr->num_rows); - png_debug1(3, "rowbytes = %lu,\n", png_ptr->rowbytes); - png_debug1(3, "irowbytes = %lu,\n", png_ptr->irowbytes); - - png_ptr->flags |= PNG_FLAG_ROW_INIT; -} -#endif /* PNG_READ_SUPPORTED */ diff --git a/rosapps/lib/libpng/pngset.c b/rosapps/lib/libpng/pngset.c deleted file mode 100644 index f8f9b7e3b3e..00000000000 --- a/rosapps/lib/libpng/pngset.c +++ /dev/null @@ -1,1250 +0,0 @@ - -/* pngset.c - storage of image information into info struct - * - * Last changed in libpng 1.2.24 [December 14, 2007] - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2007 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * The functions here are used during reads to store data from the file - * into the info struct, and during writes to store application data - * into the info struct for writing into the file. This abstracts the - * info struct and allows us to change the structure in the future. - */ - -#define PNG_INTERNAL -#include "png.h" - -#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) - -#if defined(PNG_bKGD_SUPPORTED) -void PNGAPI -png_set_bKGD(png_structp png_ptr, png_infop info_ptr, png_color_16p background) -{ - png_debug1(1, "in %s storage function\n", "bKGD"); - if (png_ptr == NULL || info_ptr == NULL) - return; - - png_memcpy(&(info_ptr->background), background, png_sizeof(png_color_16)); - info_ptr->valid |= PNG_INFO_bKGD; -} -#endif - -#if defined(PNG_cHRM_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED -void PNGAPI -png_set_cHRM(png_structp png_ptr, png_infop info_ptr, - double white_x, double white_y, double red_x, double red_y, - double green_x, double green_y, double blue_x, double blue_y) -{ - png_debug1(1, "in %s storage function\n", "cHRM"); - if (png_ptr == NULL || info_ptr == NULL) - return; - if (!(white_x || white_y || red_x || red_y || green_x || green_y || - blue_x || blue_y)) - { - png_warning(png_ptr, - "Ignoring attempt to set all-zero chromaticity values"); - return; - } - if (white_x < 0.0 || white_y < 0.0 || - red_x < 0.0 || red_y < 0.0 || - green_x < 0.0 || green_y < 0.0 || - blue_x < 0.0 || blue_y < 0.0) - { - png_warning(png_ptr, - "Ignoring attempt to set negative chromaticity value"); - return; - } - if (white_x > 21474.83 || white_y > 21474.83 || - red_x > 21474.83 || red_y > 21474.83 || - green_x > 21474.83 || green_y > 21474.83 || - blue_x > 21474.83 || blue_y > 21474.83) - { - png_warning(png_ptr, - "Ignoring attempt to set chromaticity value exceeding 21474.83"); - return; - } - - info_ptr->x_white = (float)white_x; - info_ptr->y_white = (float)white_y; - info_ptr->x_red = (float)red_x; - info_ptr->y_red = (float)red_y; - info_ptr->x_green = (float)green_x; - info_ptr->y_green = (float)green_y; - info_ptr->x_blue = (float)blue_x; - info_ptr->y_blue = (float)blue_y; -#ifdef PNG_FIXED_POINT_SUPPORTED - info_ptr->int_x_white = (png_fixed_point)(white_x*100000.+0.5); - info_ptr->int_y_white = (png_fixed_point)(white_y*100000.+0.5); - info_ptr->int_x_red = (png_fixed_point)( red_x*100000.+0.5); - info_ptr->int_y_red = (png_fixed_point)( red_y*100000.+0.5); - info_ptr->int_x_green = (png_fixed_point)(green_x*100000.+0.5); - info_ptr->int_y_green = (png_fixed_point)(green_y*100000.+0.5); - info_ptr->int_x_blue = (png_fixed_point)( blue_x*100000.+0.5); - info_ptr->int_y_blue = (png_fixed_point)( blue_y*100000.+0.5); -#endif - info_ptr->valid |= PNG_INFO_cHRM; -} -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED -void PNGAPI -png_set_cHRM_fixed(png_structp png_ptr, png_infop info_ptr, - png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x, - png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y, - png_fixed_point blue_x, png_fixed_point blue_y) -{ - png_debug1(1, "in %s storage function\n", "cHRM"); - if (png_ptr == NULL || info_ptr == NULL) - return; - - if (!(white_x || white_y || red_x || red_y || green_x || green_y || - blue_x || blue_y)) - { - png_warning(png_ptr, - "Ignoring attempt to set all-zero chromaticity values"); - return; - } - if (white_x < 0 || white_y < 0 || - red_x < 0 || red_y < 0 || - green_x < 0 || green_y < 0 || - blue_x < 0 || blue_y < 0) - { - png_warning(png_ptr, - "Ignoring attempt to set negative chromaticity value"); - return; - } - if (white_x > (png_fixed_point) PNG_UINT_31_MAX || - white_y > (png_fixed_point) PNG_UINT_31_MAX || - red_x > (png_fixed_point) PNG_UINT_31_MAX || - red_y > (png_fixed_point) PNG_UINT_31_MAX || - green_x > (png_fixed_point) PNG_UINT_31_MAX || - green_y > (png_fixed_point) PNG_UINT_31_MAX || - blue_x > (png_fixed_point) PNG_UINT_31_MAX || - blue_y > (png_fixed_point) PNG_UINT_31_MAX ) - { - png_warning(png_ptr, - "Ignoring attempt to set chromaticity value exceeding 21474.83"); - return; - } - info_ptr->int_x_white = white_x; - info_ptr->int_y_white = white_y; - info_ptr->int_x_red = red_x; - info_ptr->int_y_red = red_y; - info_ptr->int_x_green = green_x; - info_ptr->int_y_green = green_y; - info_ptr->int_x_blue = blue_x; - info_ptr->int_y_blue = blue_y; -#ifdef PNG_FLOATING_POINT_SUPPORTED - info_ptr->x_white = (float)(white_x/100000.); - info_ptr->y_white = (float)(white_y/100000.); - info_ptr->x_red = (float)( red_x/100000.); - info_ptr->y_red = (float)( red_y/100000.); - info_ptr->x_green = (float)(green_x/100000.); - info_ptr->y_green = (float)(green_y/100000.); - info_ptr->x_blue = (float)( blue_x/100000.); - info_ptr->y_blue = (float)( blue_y/100000.); -#endif - info_ptr->valid |= PNG_INFO_cHRM; -} -#endif -#endif - -#if defined(PNG_gAMA_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED -void PNGAPI -png_set_gAMA(png_structp png_ptr, png_infop info_ptr, double file_gamma) -{ - double gamma; - png_debug1(1, "in %s storage function\n", "gAMA"); - if (png_ptr == NULL || info_ptr == NULL) - return; - - /* Check for overflow */ - if (file_gamma > 21474.83) - { - png_warning(png_ptr, "Limiting gamma to 21474.83"); - gamma=21474.83; - } - else - gamma=file_gamma; - info_ptr->gamma = (float)gamma; -#ifdef PNG_FIXED_POINT_SUPPORTED - info_ptr->int_gamma = (int)(gamma*100000.+.5); -#endif - info_ptr->valid |= PNG_INFO_gAMA; - if(gamma == 0.0) - png_warning(png_ptr, "Setting gamma=0"); -} -#endif -void PNGAPI -png_set_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, png_fixed_point - int_gamma) -{ - png_fixed_point gamma; - - png_debug1(1, "in %s storage function\n", "gAMA"); - if (png_ptr == NULL || info_ptr == NULL) - return; - - if (int_gamma > (png_fixed_point) PNG_UINT_31_MAX) - { - png_warning(png_ptr, "Limiting gamma to 21474.83"); - gamma=PNG_UINT_31_MAX; - } - else - { - if (int_gamma < 0) - { - png_warning(png_ptr, "Setting negative gamma to zero"); - gamma=0; - } - else - gamma=int_gamma; - } -#ifdef PNG_FLOATING_POINT_SUPPORTED - info_ptr->gamma = (float)(gamma/100000.); -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED - info_ptr->int_gamma = gamma; -#endif - info_ptr->valid |= PNG_INFO_gAMA; - if(gamma == 0) - png_warning(png_ptr, "Setting gamma=0"); -} -#endif - -#if defined(PNG_hIST_SUPPORTED) -void PNGAPI -png_set_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_16p hist) -{ - int i; - - png_debug1(1, "in %s storage function\n", "hIST"); - if (png_ptr == NULL || info_ptr == NULL) - return; - if (info_ptr->num_palette == 0 || info_ptr->num_palette - > PNG_MAX_PALETTE_LENGTH) - { - png_warning(png_ptr, - "Invalid palette size, hIST allocation skipped."); - return; - } - -#ifdef PNG_FREE_ME_SUPPORTED - png_free_data(png_ptr, info_ptr, PNG_FREE_HIST, 0); -#endif - /* Changed from info->num_palette to PNG_MAX_PALETTE_LENGTH in version - 1.2.1 */ - png_ptr->hist = (png_uint_16p)png_malloc_warn(png_ptr, - (png_uint_32)(PNG_MAX_PALETTE_LENGTH * png_sizeof (png_uint_16))); - if (png_ptr->hist == NULL) - { - png_warning(png_ptr, "Insufficient memory for hIST chunk data."); - return; - } - - for (i = 0; i < info_ptr->num_palette; i++) - png_ptr->hist[i] = hist[i]; - info_ptr->hist = png_ptr->hist; - info_ptr->valid |= PNG_INFO_hIST; - -#ifdef PNG_FREE_ME_SUPPORTED - info_ptr->free_me |= PNG_FREE_HIST; -#else - png_ptr->flags |= PNG_FLAG_FREE_HIST; -#endif -} -#endif - -void PNGAPI -png_set_IHDR(png_structp png_ptr, png_infop info_ptr, - png_uint_32 width, png_uint_32 height, int bit_depth, - int color_type, int interlace_type, int compression_type, - int filter_type) -{ - png_debug1(1, "in %s storage function\n", "IHDR"); - if (png_ptr == NULL || info_ptr == NULL) - return; - - /* check for width and height valid values */ - if (width == 0 || height == 0) - png_error(png_ptr, "Image width or height is zero in IHDR"); -#ifdef PNG_SET_USER_LIMITS_SUPPORTED - if (width > png_ptr->user_width_max || height > png_ptr->user_height_max) - png_error(png_ptr, "image size exceeds user limits in IHDR"); -#else - if (width > PNG_USER_WIDTH_MAX || height > PNG_USER_HEIGHT_MAX) - png_error(png_ptr, "image size exceeds user limits in IHDR"); -#endif - if (width > PNG_UINT_31_MAX || height > PNG_UINT_31_MAX) - png_error(png_ptr, "Invalid image size in IHDR"); - if ( width > (PNG_UINT_32_MAX - >> 3) /* 8-byte RGBA pixels */ - - 64 /* bigrowbuf hack */ - - 1 /* filter byte */ - - 7*8 /* rounding of width to multiple of 8 pixels */ - - 8) /* extra max_pixel_depth pad */ - png_warning(png_ptr, "Width is too large for libpng to process pixels"); - - /* check other values */ - if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 && - bit_depth != 8 && bit_depth != 16) - png_error(png_ptr, "Invalid bit depth in IHDR"); - - if (color_type < 0 || color_type == 1 || - color_type == 5 || color_type > 6) - png_error(png_ptr, "Invalid color type in IHDR"); - - if (((color_type == PNG_COLOR_TYPE_PALETTE) && bit_depth > 8) || - ((color_type == PNG_COLOR_TYPE_RGB || - color_type == PNG_COLOR_TYPE_GRAY_ALPHA || - color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8)) - png_error(png_ptr, "Invalid color type/bit depth combination in IHDR"); - - if (interlace_type >= PNG_INTERLACE_LAST) - png_error(png_ptr, "Unknown interlace method in IHDR"); - - if (compression_type != PNG_COMPRESSION_TYPE_BASE) - png_error(png_ptr, "Unknown compression method in IHDR"); - -#if defined(PNG_MNG_FEATURES_SUPPORTED) - /* Accept filter_method 64 (intrapixel differencing) only if - * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and - * 2. Libpng did not read a PNG signature (this filter_method is only - * used in PNG datastreams that are embedded in MNG datastreams) and - * 3. The application called png_permit_mng_features with a mask that - * included PNG_FLAG_MNG_FILTER_64 and - * 4. The filter_method is 64 and - * 5. The color_type is RGB or RGBA - */ - if((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)&&png_ptr->mng_features_permitted) - png_warning(png_ptr,"MNG features are not allowed in a PNG datastream"); - if(filter_type != PNG_FILTER_TYPE_BASE) - { - if(!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && - (filter_type == PNG_INTRAPIXEL_DIFFERENCING) && - ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) && - (color_type == PNG_COLOR_TYPE_RGB || - color_type == PNG_COLOR_TYPE_RGB_ALPHA))) - png_error(png_ptr, "Unknown filter method in IHDR"); - if(png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) - png_warning(png_ptr, "Invalid filter method in IHDR"); - } -#else - if(filter_type != PNG_FILTER_TYPE_BASE) - png_error(png_ptr, "Unknown filter method in IHDR"); -#endif - - info_ptr->width = width; - info_ptr->height = height; - info_ptr->bit_depth = (png_byte)bit_depth; - info_ptr->color_type =(png_byte) color_type; - info_ptr->compression_type = (png_byte)compression_type; - info_ptr->filter_type = (png_byte)filter_type; - info_ptr->interlace_type = (png_byte)interlace_type; - if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - info_ptr->channels = 1; - else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) - info_ptr->channels = 3; - else - info_ptr->channels = 1; - if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) - info_ptr->channels++; - info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth); - - /* check for potential overflow */ - if (width > (PNG_UINT_32_MAX - >> 3) /* 8-byte RGBA pixels */ - - 64 /* bigrowbuf hack */ - - 1 /* filter byte */ - - 7*8 /* rounding of width to multiple of 8 pixels */ - - 8) /* extra max_pixel_depth pad */ - info_ptr->rowbytes = (png_size_t)0; - else - info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth,width); -} - -#if defined(PNG_oFFs_SUPPORTED) -void PNGAPI -png_set_oFFs(png_structp png_ptr, png_infop info_ptr, - png_int_32 offset_x, png_int_32 offset_y, int unit_type) -{ - png_debug1(1, "in %s storage function\n", "oFFs"); - if (png_ptr == NULL || info_ptr == NULL) - return; - - info_ptr->x_offset = offset_x; - info_ptr->y_offset = offset_y; - info_ptr->offset_unit_type = (png_byte)unit_type; - info_ptr->valid |= PNG_INFO_oFFs; -} -#endif - -#if defined(PNG_pCAL_SUPPORTED) -void PNGAPI -png_set_pCAL(png_structp png_ptr, png_infop info_ptr, - png_charp purpose, png_int_32 X0, png_int_32 X1, int type, int nparams, - png_charp units, png_charpp params) -{ - png_uint_32 length; - int i; - - png_debug1(1, "in %s storage function\n", "pCAL"); - if (png_ptr == NULL || info_ptr == NULL) - return; - - length = png_strlen(purpose) + 1; - png_debug1(3, "allocating purpose for info (%lu bytes)\n", length); - info_ptr->pcal_purpose = (png_charp)png_malloc_warn(png_ptr, length); - if (info_ptr->pcal_purpose == NULL) - { - png_warning(png_ptr, "Insufficient memory for pCAL purpose."); - return; - } - png_memcpy(info_ptr->pcal_purpose, purpose, (png_size_t)length); - - png_debug(3, "storing X0, X1, type, and nparams in info\n"); - info_ptr->pcal_X0 = X0; - info_ptr->pcal_X1 = X1; - info_ptr->pcal_type = (png_byte)type; - info_ptr->pcal_nparams = (png_byte)nparams; - - length = png_strlen(units) + 1; - png_debug1(3, "allocating units for info (%lu bytes)\n", length); - info_ptr->pcal_units = (png_charp)png_malloc_warn(png_ptr, length); - if (info_ptr->pcal_units == NULL) - { - png_warning(png_ptr, "Insufficient memory for pCAL units."); - return; - } - png_memcpy(info_ptr->pcal_units, units, (png_size_t)length); - - info_ptr->pcal_params = (png_charpp)png_malloc_warn(png_ptr, - (png_uint_32)((nparams + 1) * png_sizeof(png_charp))); - if (info_ptr->pcal_params == NULL) - { - png_warning(png_ptr, "Insufficient memory for pCAL params."); - return; - } - - info_ptr->pcal_params[nparams] = NULL; - - for (i = 0; i < nparams; i++) - { - length = png_strlen(params[i]) + 1; - png_debug2(3, "allocating parameter %d for info (%lu bytes)\n", i, length); - info_ptr->pcal_params[i] = (png_charp)png_malloc_warn(png_ptr, length); - if (info_ptr->pcal_params[i] == NULL) - { - png_warning(png_ptr, "Insufficient memory for pCAL parameter."); - return; - } - png_memcpy(info_ptr->pcal_params[i], params[i], (png_size_t)length); - } - - info_ptr->valid |= PNG_INFO_pCAL; -#ifdef PNG_FREE_ME_SUPPORTED - info_ptr->free_me |= PNG_FREE_PCAL; -#endif -} -#endif - -#if defined(PNG_READ_sCAL_SUPPORTED) || defined(PNG_WRITE_sCAL_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED -void PNGAPI -png_set_sCAL(png_structp png_ptr, png_infop info_ptr, - int unit, double width, double height) -{ - png_debug1(1, "in %s storage function\n", "sCAL"); - if (png_ptr == NULL || info_ptr == NULL) - return; - - info_ptr->scal_unit = (png_byte)unit; - info_ptr->scal_pixel_width = width; - info_ptr->scal_pixel_height = height; - - info_ptr->valid |= PNG_INFO_sCAL; -} -#else -#ifdef PNG_FIXED_POINT_SUPPORTED -void PNGAPI -png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr, - int unit, png_charp swidth, png_charp sheight) -{ - png_uint_32 length; - - png_debug1(1, "in %s storage function\n", "sCAL"); - if (png_ptr == NULL || info_ptr == NULL) - return; - - info_ptr->scal_unit = (png_byte)unit; - - length = png_strlen(swidth) + 1; - png_debug1(3, "allocating unit for info (%d bytes)\n", length); - info_ptr->scal_s_width = (png_charp)png_malloc_warn(png_ptr, length); - if (info_ptr->scal_s_width == NULL) - { - png_warning(png_ptr, - "Memory allocation failed while processing sCAL."); - } - png_memcpy(info_ptr->scal_s_width, swidth, (png_size_t)length); - - length = png_strlen(sheight) + 1; - png_debug1(3, "allocating unit for info (%d bytes)\n", length); - info_ptr->scal_s_height = (png_charp)png_malloc_warn(png_ptr, length); - if (info_ptr->scal_s_height == NULL) - { - png_free (png_ptr, info_ptr->scal_s_width); - png_warning(png_ptr, - "Memory allocation failed while processing sCAL."); - } - png_memcpy(info_ptr->scal_s_height, sheight, (png_size_t)length); - - info_ptr->valid |= PNG_INFO_sCAL; -#ifdef PNG_FREE_ME_SUPPORTED - info_ptr->free_me |= PNG_FREE_SCAL; -#endif -} -#endif -#endif -#endif - -#if defined(PNG_pHYs_SUPPORTED) -void PNGAPI -png_set_pHYs(png_structp png_ptr, png_infop info_ptr, - png_uint_32 res_x, png_uint_32 res_y, int unit_type) -{ - png_debug1(1, "in %s storage function\n", "pHYs"); - if (png_ptr == NULL || info_ptr == NULL) - return; - - info_ptr->x_pixels_per_unit = res_x; - info_ptr->y_pixels_per_unit = res_y; - info_ptr->phys_unit_type = (png_byte)unit_type; - info_ptr->valid |= PNG_INFO_pHYs; -} -#endif - -void PNGAPI -png_set_PLTE(png_structp png_ptr, png_infop info_ptr, - png_colorp palette, int num_palette) -{ - - png_debug1(1, "in %s storage function\n", "PLTE"); - if (png_ptr == NULL || info_ptr == NULL) - return; - - if (num_palette < 0 || num_palette > PNG_MAX_PALETTE_LENGTH) - { - if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - png_error(png_ptr, "Invalid palette length"); - else - { - png_warning(png_ptr, "Invalid palette length"); - return; - } - } - - /* - * It may not actually be necessary to set png_ptr->palette here; - * we do it for backward compatibility with the way the png_handle_tRNS - * function used to do the allocation. - */ -#ifdef PNG_FREE_ME_SUPPORTED - png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0); -#endif - - /* Changed in libpng-1.2.1 to allocate PNG_MAX_PALETTE_LENGTH instead - of num_palette entries, - in case of an invalid PNG file that has too-large sample values. */ - png_ptr->palette = (png_colorp)png_malloc(png_ptr, - PNG_MAX_PALETTE_LENGTH * png_sizeof(png_color)); - png_memset(png_ptr->palette, 0, PNG_MAX_PALETTE_LENGTH * - png_sizeof(png_color)); - png_memcpy(png_ptr->palette, palette, num_palette * png_sizeof (png_color)); - info_ptr->palette = png_ptr->palette; - info_ptr->num_palette = png_ptr->num_palette = (png_uint_16)num_palette; - -#ifdef PNG_FREE_ME_SUPPORTED - info_ptr->free_me |= PNG_FREE_PLTE; -#else - png_ptr->flags |= PNG_FLAG_FREE_PLTE; -#endif - - info_ptr->valid |= PNG_INFO_PLTE; -} - -#if defined(PNG_sBIT_SUPPORTED) -void PNGAPI -png_set_sBIT(png_structp png_ptr, png_infop info_ptr, - png_color_8p sig_bit) -{ - png_debug1(1, "in %s storage function\n", "sBIT"); - if (png_ptr == NULL || info_ptr == NULL) - return; - - png_memcpy(&(info_ptr->sig_bit), sig_bit, png_sizeof (png_color_8)); - info_ptr->valid |= PNG_INFO_sBIT; -} -#endif - -#if defined(PNG_sRGB_SUPPORTED) -void PNGAPI -png_set_sRGB(png_structp png_ptr, png_infop info_ptr, int intent) -{ - png_debug1(1, "in %s storage function\n", "sRGB"); - if (png_ptr == NULL || info_ptr == NULL) - return; - - info_ptr->srgb_intent = (png_byte)intent; - info_ptr->valid |= PNG_INFO_sRGB; -} - -void PNGAPI -png_set_sRGB_gAMA_and_cHRM(png_structp png_ptr, png_infop info_ptr, - int intent) -{ -#if defined(PNG_gAMA_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED - float file_gamma; -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED - png_fixed_point int_file_gamma; -#endif -#endif -#if defined(PNG_cHRM_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED - float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y; -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED - png_fixed_point int_white_x, int_white_y, int_red_x, int_red_y, int_green_x, - int_green_y, int_blue_x, int_blue_y; -#endif -#endif - png_debug1(1, "in %s storage function\n", "sRGB_gAMA_and_cHRM"); - if (png_ptr == NULL || info_ptr == NULL) - return; - - png_set_sRGB(png_ptr, info_ptr, intent); - -#if defined(PNG_gAMA_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED - file_gamma = (float).45455; - png_set_gAMA(png_ptr, info_ptr, file_gamma); -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED - int_file_gamma = 45455L; - png_set_gAMA_fixed(png_ptr, info_ptr, int_file_gamma); -#endif -#endif - -#if defined(PNG_cHRM_SUPPORTED) -#ifdef PNG_FIXED_POINT_SUPPORTED - int_white_x = 31270L; - int_white_y = 32900L; - int_red_x = 64000L; - int_red_y = 33000L; - int_green_x = 30000L; - int_green_y = 60000L; - int_blue_x = 15000L; - int_blue_y = 6000L; - - png_set_cHRM_fixed(png_ptr, info_ptr, - int_white_x, int_white_y, int_red_x, int_red_y, int_green_x, int_green_y, - int_blue_x, int_blue_y); -#endif -#ifdef PNG_FLOATING_POINT_SUPPORTED - white_x = (float).3127; - white_y = (float).3290; - red_x = (float).64; - red_y = (float).33; - green_x = (float).30; - green_y = (float).60; - blue_x = (float).15; - blue_y = (float).06; - - png_set_cHRM(png_ptr, info_ptr, - white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y); -#endif -#endif -} -#endif - - -#if defined(PNG_iCCP_SUPPORTED) -void PNGAPI -png_set_iCCP(png_structp png_ptr, png_infop info_ptr, - png_charp name, int compression_type, - png_charp profile, png_uint_32 proflen) -{ - png_charp new_iccp_name; - png_charp new_iccp_profile; - png_uint_32 length; - - png_debug1(1, "in %s storage function\n", "iCCP"); - if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL) - return; - - length = png_strlen(name)+1; - new_iccp_name = (png_charp)png_malloc_warn(png_ptr, length); - if (new_iccp_name == NULL) - { - png_warning(png_ptr, "Insufficient memory to process iCCP chunk."); - return; - } - png_memcpy(new_iccp_name, name, length); - new_iccp_profile = (png_charp)png_malloc_warn(png_ptr, proflen); - if (new_iccp_profile == NULL) - { - png_free (png_ptr, new_iccp_name); - png_warning(png_ptr, "Insufficient memory to process iCCP profile."); - return; - } - png_memcpy(new_iccp_profile, profile, (png_size_t)proflen); - - png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0); - - info_ptr->iccp_proflen = proflen; - info_ptr->iccp_name = new_iccp_name; - info_ptr->iccp_profile = new_iccp_profile; - /* Compression is always zero but is here so the API and info structure - * does not have to change if we introduce multiple compression types */ - info_ptr->iccp_compression = (png_byte)compression_type; -#ifdef PNG_FREE_ME_SUPPORTED - info_ptr->free_me |= PNG_FREE_ICCP; -#endif - info_ptr->valid |= PNG_INFO_iCCP; -} -#endif - -#if defined(PNG_TEXT_SUPPORTED) -void PNGAPI -png_set_text(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr, - int num_text) -{ - int ret; - ret=png_set_text_2(png_ptr, info_ptr, text_ptr, num_text); - if (ret) - png_error(png_ptr, "Insufficient memory to store text"); -} - -int /* PRIVATE */ -png_set_text_2(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr, - int num_text) -{ - int i; - - png_debug1(1, "in %s storage function\n", (png_ptr->chunk_name[0] == '\0' ? - "text" : (png_const_charp)png_ptr->chunk_name)); - - if (png_ptr == NULL || info_ptr == NULL || num_text == 0) - return(0); - - /* Make sure we have enough space in the "text" array in info_struct - * to hold all of the incoming text_ptr objects. - */ - if (info_ptr->num_text + num_text > info_ptr->max_text) - { - if (info_ptr->text != NULL) - { - png_textp old_text; - int old_max; - - old_max = info_ptr->max_text; - info_ptr->max_text = info_ptr->num_text + num_text + 8; - old_text = info_ptr->text; - info_ptr->text = (png_textp)png_malloc_warn(png_ptr, - (png_uint_32)(info_ptr->max_text * png_sizeof (png_text))); - if (info_ptr->text == NULL) - { - png_free(png_ptr, old_text); - return(1); - } - png_memcpy(info_ptr->text, old_text, (png_size_t)(old_max * - png_sizeof(png_text))); - png_free(png_ptr, old_text); - } - else - { - info_ptr->max_text = num_text + 8; - info_ptr->num_text = 0; - info_ptr->text = (png_textp)png_malloc_warn(png_ptr, - (png_uint_32)(info_ptr->max_text * png_sizeof (png_text))); - if (info_ptr->text == NULL) - return(1); -#ifdef PNG_FREE_ME_SUPPORTED - info_ptr->free_me |= PNG_FREE_TEXT; -#endif - } - png_debug1(3, "allocated %d entries for info_ptr->text\n", - info_ptr->max_text); - } - for (i = 0; i < num_text; i++) - { - png_size_t text_length,key_len; - png_size_t lang_len,lang_key_len; - png_textp textp = &(info_ptr->text[info_ptr->num_text]); - - if (text_ptr[i].key == NULL) - continue; - - key_len = png_strlen(text_ptr[i].key); - - if(text_ptr[i].compression <= 0) - { - lang_len = 0; - lang_key_len = 0; - } - else -#ifdef PNG_iTXt_SUPPORTED - { - /* set iTXt data */ - if (text_ptr[i].lang != NULL) - lang_len = png_strlen(text_ptr[i].lang); - else - lang_len = 0; - if (text_ptr[i].lang_key != NULL) - lang_key_len = png_strlen(text_ptr[i].lang_key); - else - lang_key_len = 0; - } -#else - { - png_warning(png_ptr, "iTXt chunk not supported."); - continue; - } -#endif - - if (text_ptr[i].text == NULL || text_ptr[i].text[0] == '\0') - { - text_length = 0; -#ifdef PNG_iTXt_SUPPORTED - if(text_ptr[i].compression > 0) - textp->compression = PNG_ITXT_COMPRESSION_NONE; - else -#endif - textp->compression = PNG_TEXT_COMPRESSION_NONE; - } - else - { - text_length = png_strlen(text_ptr[i].text); - textp->compression = text_ptr[i].compression; - } - - textp->key = (png_charp)png_malloc_warn(png_ptr, - (png_uint_32)(key_len + text_length + lang_len + lang_key_len + 4)); - if (textp->key == NULL) - return(1); - png_debug2(2, "Allocated %lu bytes at %x in png_set_text\n", - (png_uint_32)(key_len + lang_len + lang_key_len + text_length + 4), - (int)textp->key); - - png_memcpy(textp->key, text_ptr[i].key, - (png_size_t)(key_len)); - *(textp->key+key_len) = '\0'; -#ifdef PNG_iTXt_SUPPORTED - if (text_ptr[i].compression > 0) - { - textp->lang=textp->key + key_len + 1; - png_memcpy(textp->lang, text_ptr[i].lang, lang_len); - *(textp->lang+lang_len) = '\0'; - textp->lang_key=textp->lang + lang_len + 1; - png_memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len); - *(textp->lang_key+lang_key_len) = '\0'; - textp->text=textp->lang_key + lang_key_len + 1; - } - else -#endif - { -#ifdef PNG_iTXt_SUPPORTED - textp->lang=NULL; - textp->lang_key=NULL; -#endif - textp->text=textp->key + key_len + 1; - } - if(text_length) - png_memcpy(textp->text, text_ptr[i].text, - (png_size_t)(text_length)); - *(textp->text+text_length) = '\0'; - -#ifdef PNG_iTXt_SUPPORTED - if(textp->compression > 0) - { - textp->text_length = 0; - textp->itxt_length = text_length; - } - else -#endif - { - textp->text_length = text_length; -#ifdef PNG_iTXt_SUPPORTED - textp->itxt_length = 0; -#endif - } - info_ptr->num_text++; - png_debug1(3, "transferred text chunk %d\n", info_ptr->num_text); - } - return(0); -} -#endif - -#if defined(PNG_tIME_SUPPORTED) -void PNGAPI -png_set_tIME(png_structp png_ptr, png_infop info_ptr, png_timep mod_time) -{ - png_debug1(1, "in %s storage function\n", "tIME"); - if (png_ptr == NULL || info_ptr == NULL || - (png_ptr->mode & PNG_WROTE_tIME)) - return; - - png_memcpy(&(info_ptr->mod_time), mod_time, png_sizeof (png_time)); - info_ptr->valid |= PNG_INFO_tIME; -} -#endif - -#if defined(PNG_tRNS_SUPPORTED) -void PNGAPI -png_set_tRNS(png_structp png_ptr, png_infop info_ptr, - png_bytep trans, int num_trans, png_color_16p trans_values) -{ - png_debug1(1, "in %s storage function\n", "tRNS"); - if (png_ptr == NULL || info_ptr == NULL) - return; - - if (trans != NULL) - { - /* - * It may not actually be necessary to set png_ptr->trans here; - * we do it for backward compatibility with the way the png_handle_tRNS - * function used to do the allocation. - */ -#ifdef PNG_FREE_ME_SUPPORTED - png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0); -#endif - /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */ - png_ptr->trans = info_ptr->trans = (png_bytep)png_malloc(png_ptr, - (png_uint_32)PNG_MAX_PALETTE_LENGTH); - if (num_trans <= PNG_MAX_PALETTE_LENGTH) - png_memcpy(info_ptr->trans, trans, (png_size_t)num_trans); -#ifdef PNG_FREE_ME_SUPPORTED - info_ptr->free_me |= PNG_FREE_TRNS; -#else - png_ptr->flags |= PNG_FLAG_FREE_TRNS; -#endif - } - - if (trans_values != NULL) - { - png_memcpy(&(info_ptr->trans_values), trans_values, - png_sizeof(png_color_16)); - if (num_trans == 0) - num_trans = 1; - } - info_ptr->num_trans = (png_uint_16)num_trans; - info_ptr->valid |= PNG_INFO_tRNS; -} -#endif - -#if defined(PNG_sPLT_SUPPORTED) -void PNGAPI -png_set_sPLT(png_structp png_ptr, - png_infop info_ptr, png_sPLT_tp entries, int nentries) -{ - png_sPLT_tp np; - int i; - - if (png_ptr == NULL || info_ptr == NULL) - return; - - np = (png_sPLT_tp)png_malloc_warn(png_ptr, - (info_ptr->splt_palettes_num + nentries) * png_sizeof(png_sPLT_t)); - if (np == NULL) - { - png_warning(png_ptr, "No memory for sPLT palettes."); - return; - } - - png_memcpy(np, info_ptr->splt_palettes, - info_ptr->splt_palettes_num * png_sizeof(png_sPLT_t)); - png_free(png_ptr, info_ptr->splt_palettes); - info_ptr->splt_palettes=NULL; - - for (i = 0; i < nentries; i++) - { - png_sPLT_tp to = np + info_ptr->splt_palettes_num + i; - png_sPLT_tp from = entries + i; - png_uint_32 length; - - length = png_strlen(from->name) + 1; - to->name = (png_charp)png_malloc_warn(png_ptr, length); - if (to->name == NULL) - { - png_warning(png_ptr, - "Out of memory while processing sPLT chunk"); - } - png_memcpy(to->name, from->name, length); - to->entries = (png_sPLT_entryp)png_malloc_warn(png_ptr, - from->nentries * png_sizeof(png_sPLT_entry)); - if (to->entries == NULL) - { - png_warning(png_ptr, - "Out of memory while processing sPLT chunk"); - png_free(png_ptr,to->name); - to->name = NULL; - } - png_memcpy(to->entries, from->entries, - from->nentries * png_sizeof(png_sPLT_entry)); - to->nentries = from->nentries; - to->depth = from->depth; - } - - info_ptr->splt_palettes = np; - info_ptr->splt_palettes_num += nentries; - info_ptr->valid |= PNG_INFO_sPLT; -#ifdef PNG_FREE_ME_SUPPORTED - info_ptr->free_me |= PNG_FREE_SPLT; -#endif -} -#endif /* PNG_sPLT_SUPPORTED */ - -#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) -void PNGAPI -png_set_unknown_chunks(png_structp png_ptr, - png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns) -{ - png_unknown_chunkp np; - int i; - - if (png_ptr == NULL || info_ptr == NULL || num_unknowns == 0) - return; - - np = (png_unknown_chunkp)png_malloc_warn(png_ptr, - (info_ptr->unknown_chunks_num + num_unknowns) * - png_sizeof(png_unknown_chunk)); - if (np == NULL) - { - png_warning(png_ptr, - "Out of memory while processing unknown chunk."); - return; - } - - png_memcpy(np, info_ptr->unknown_chunks, - info_ptr->unknown_chunks_num * png_sizeof(png_unknown_chunk)); - png_free(png_ptr, info_ptr->unknown_chunks); - info_ptr->unknown_chunks=NULL; - - for (i = 0; i < num_unknowns; i++) - { - png_unknown_chunkp to = np + info_ptr->unknown_chunks_num + i; - png_unknown_chunkp from = unknowns + i; - - png_memcpy((png_charp)to->name, - (png_charp)from->name, - png_sizeof(from->name)); - to->name[png_sizeof(to->name)-1] = '\0'; - - to->data = (png_bytep)png_malloc_warn(png_ptr, from->size); - if (to->data == NULL) - { - png_warning(png_ptr, - "Out of memory while processing unknown chunk."); - } - else - { - png_memcpy(to->data, from->data, from->size); - to->size = from->size; - - /* note our location in the read or write sequence */ - to->location = (png_byte)(png_ptr->mode & 0xff); - } - } - - info_ptr->unknown_chunks = np; - info_ptr->unknown_chunks_num += num_unknowns; -#ifdef PNG_FREE_ME_SUPPORTED - info_ptr->free_me |= PNG_FREE_UNKN; -#endif -} -void PNGAPI -png_set_unknown_chunk_location(png_structp png_ptr, png_infop info_ptr, - int chunk, int location) -{ - if(png_ptr != NULL && info_ptr != NULL && chunk >= 0 && chunk < - (int)info_ptr->unknown_chunks_num) - info_ptr->unknown_chunks[chunk].location = (png_byte)location; -} -#endif - -#if defined(PNG_1_0_X) || defined(PNG_1_2_X) -#if defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \ - defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) -void PNGAPI -png_permit_empty_plte (png_structp png_ptr, int empty_plte_permitted) -{ - /* This function is deprecated in favor of png_permit_mng_features() - and will be removed from libpng-1.3.0 */ - png_debug(1, "in png_permit_empty_plte, DEPRECATED.\n"); - if (png_ptr == NULL) - return; - png_ptr->mng_features_permitted = (png_byte) - ((png_ptr->mng_features_permitted & (~PNG_FLAG_MNG_EMPTY_PLTE)) | - ((empty_plte_permitted & PNG_FLAG_MNG_EMPTY_PLTE))); -} -#endif -#endif - -#if defined(PNG_MNG_FEATURES_SUPPORTED) -png_uint_32 PNGAPI -png_permit_mng_features (png_structp png_ptr, png_uint_32 mng_features) -{ - png_debug(1, "in png_permit_mng_features\n"); - if (png_ptr == NULL) - return (png_uint_32)0; - png_ptr->mng_features_permitted = - (png_byte)(mng_features & PNG_ALL_MNG_FEATURES); - return (png_uint_32)png_ptr->mng_features_permitted; -} -#endif - -#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) -void PNGAPI -png_set_keep_unknown_chunks(png_structp png_ptr, int keep, png_bytep - chunk_list, int num_chunks) -{ - png_bytep new_list, p; - int i, old_num_chunks; - if (png_ptr == NULL) - return; - if (num_chunks == 0) - { - if(keep == PNG_HANDLE_CHUNK_ALWAYS || keep == PNG_HANDLE_CHUNK_IF_SAFE) - png_ptr->flags |= PNG_FLAG_KEEP_UNKNOWN_CHUNKS; - else - png_ptr->flags &= ~PNG_FLAG_KEEP_UNKNOWN_CHUNKS; - - if(keep == PNG_HANDLE_CHUNK_ALWAYS) - png_ptr->flags |= PNG_FLAG_KEEP_UNSAFE_CHUNKS; - else - png_ptr->flags &= ~PNG_FLAG_KEEP_UNSAFE_CHUNKS; - return; - } - if (chunk_list == NULL) - return; - old_num_chunks=png_ptr->num_chunk_list; - new_list=(png_bytep)png_malloc(png_ptr, - (png_uint_32)(5*(num_chunks+old_num_chunks))); - if(png_ptr->chunk_list != NULL) - { - png_memcpy(new_list, png_ptr->chunk_list, - (png_size_t)(5*old_num_chunks)); - png_free(png_ptr, png_ptr->chunk_list); - png_ptr->chunk_list=NULL; - } - png_memcpy(new_list+5*old_num_chunks, chunk_list, - (png_size_t)(5*num_chunks)); - for (p=new_list+5*old_num_chunks+4, i=0; inum_chunk_list=old_num_chunks+num_chunks; - png_ptr->chunk_list=new_list; -#ifdef PNG_FREE_ME_SUPPORTED - png_ptr->free_me |= PNG_FREE_LIST; -#endif -} -#endif - -#if defined(PNG_READ_USER_CHUNKS_SUPPORTED) -void PNGAPI -png_set_read_user_chunk_fn(png_structp png_ptr, png_voidp user_chunk_ptr, - png_user_chunk_ptr read_user_chunk_fn) -{ - png_debug(1, "in png_set_read_user_chunk_fn\n"); - if (png_ptr == NULL) - return; - png_ptr->read_user_chunk_fn = read_user_chunk_fn; - png_ptr->user_chunk_ptr = user_chunk_ptr; -} -#endif - -#if defined(PNG_INFO_IMAGE_SUPPORTED) -void PNGAPI -png_set_rows(png_structp png_ptr, png_infop info_ptr, png_bytepp row_pointers) -{ - png_debug1(1, "in %s storage function\n", "rows"); - - if (png_ptr == NULL || info_ptr == NULL) - return; - - if(info_ptr->row_pointers && (info_ptr->row_pointers != row_pointers)) - png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); - info_ptr->row_pointers = row_pointers; - if(row_pointers) - info_ptr->valid |= PNG_INFO_IDAT; -} -#endif - -#ifdef PNG_WRITE_SUPPORTED -void PNGAPI -png_set_compression_buffer_size(png_structp png_ptr, png_uint_32 size) -{ - if (png_ptr == NULL) - return; - if(png_ptr->zbuf) - png_free(png_ptr, png_ptr->zbuf); - png_ptr->zbuf_size = (png_size_t)size; - png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, size); - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; -} -#endif - -void PNGAPI -png_set_invalid(png_structp png_ptr, png_infop info_ptr, int mask) -{ - if (png_ptr && info_ptr) - info_ptr->valid &= ~mask; -} - - -#ifndef PNG_1_0_X -#ifdef PNG_ASSEMBLER_CODE_SUPPORTED -/* function was added to libpng 1.2.0 and should always exist by default */ -void PNGAPI -png_set_asm_flags (png_structp png_ptr, png_uint_32 asm_flags) -{ -/* Obsolete as of libpng-1.2.20 and will be removed from libpng-1.4.0 */ - if (png_ptr != NULL) - png_ptr->asm_flags = 0; -} - -/* this function was added to libpng 1.2.0 */ -void PNGAPI -png_set_mmx_thresholds (png_structp png_ptr, - png_byte mmx_bitdepth_threshold, - png_uint_32 mmx_rowbytes_threshold) -{ -/* Obsolete as of libpng-1.2.20 and will be removed from libpng-1.4.0 */ - if (png_ptr == NULL) - return; -} -#endif /* ?PNG_ASSEMBLER_CODE_SUPPORTED */ - -#ifdef PNG_SET_USER_LIMITS_SUPPORTED -/* this function was added to libpng 1.2.6 */ -void PNGAPI -png_set_user_limits (png_structp png_ptr, png_uint_32 user_width_max, - png_uint_32 user_height_max) -{ - /* Images with dimensions larger than these limits will be - * rejected by png_set_IHDR(). To accept any PNG datastream - * regardless of dimensions, set both limits to 0x7ffffffL. - */ - if(png_ptr == NULL) return; - png_ptr->user_width_max = user_width_max; - png_ptr->user_height_max = user_height_max; -} -#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */ - -#endif /* ?PNG_1_0_X */ -#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/rosapps/lib/libpng/pngtest.c b/rosapps/lib/libpng/pngtest.c deleted file mode 100644 index dd2946bf46f..00000000000 --- a/rosapps/lib/libpng/pngtest.c +++ /dev/null @@ -1,1556 +0,0 @@ - -/* pngtest.c - a simple test program to test libpng - * - * Last changed in libpng 1.2.23 - [November 6, 2007] - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2007 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This program reads in a PNG image, writes it out again, and then - * compares the two files. If the files are identical, this shows that - * the basic chunk handling, filtering, and (de)compression code is working - * properly. It does not currently test all of the transforms, although - * it probably should. - * - * The program will report "FAIL" in certain legitimate cases: - * 1) when the compression level or filter selection method is changed. - * 2) when the maximum IDAT size (PNG_ZBUF_SIZE in pngconf.h) is not 8192. - * 3) unknown unsafe-to-copy ancillary chunks or unknown critical chunks - * exist in the input file. - * 4) others not listed here... - * In these cases, it is best to check with another tool such as "pngcheck" - * to see what the differences between the two files are. - * - * If a filename is given on the command-line, then this file is used - * for the input, rather than the default "pngtest.png". This allows - * testing a wide variety of files easily. You can also test a number - * of files at once by typing "pngtest -m file1.png file2.png ..." - */ - -#include "png.h" - -#if defined(_WIN32_WCE) -# if _WIN32_WCE < 211 - __error__ (f|w)printf functions are not supported on old WindowsCE.; -# endif -# include -# include -# define READFILE(file, data, length, check) \ - if (ReadFile(file, data, length, &check,NULL)) check = 0 -# define WRITEFILE(file, data, length, check)) \ - if (WriteFile(file, data, length, &check, NULL)) check = 0 -# define FCLOSE(file) CloseHandle(file) -#else -# include -# include -# define READFILE(file, data, length, check) \ - check=(png_size_t)fread(data,(png_size_t)1,length,file) -# define WRITEFILE(file, data, length, check) \ - check=(png_size_t)fwrite(data,(png_size_t)1, length, file) -# define FCLOSE(file) fclose(file) -#endif - -#if defined(PNG_NO_STDIO) -# if defined(_WIN32_WCE) - typedef HANDLE png_FILE_p; -# else - typedef FILE * png_FILE_p; -# endif -#endif - -/* Makes pngtest verbose so we can find problems (needs to be before png.h) */ -#ifndef PNG_DEBUG -# define PNG_DEBUG 0 -#endif - -#if !PNG_DEBUG -# define SINGLE_ROWBUF_ALLOC /* makes buffer overruns easier to nail */ -#endif - -/* Turn on CPU timing -#define PNGTEST_TIMING -*/ - -#ifdef PNG_NO_FLOATING_POINT_SUPPORTED -#undef PNGTEST_TIMING -#endif - -#ifdef PNGTEST_TIMING -static float t_start, t_stop, t_decode, t_encode, t_misc; -#include -#endif - -#if defined(PNG_TIME_RFC1123_SUPPORTED) -#define PNG_tIME_STRING_LENGTH 30 -static int tIME_chunk_present=0; -static char tIME_string[PNG_tIME_STRING_LENGTH] = "no tIME chunk present in file"; -#endif - -static int verbose = 0; - -int test_one_file PNGARG((PNG_CONST char *inname, PNG_CONST char *outname)); - -#ifdef __TURBOC__ -#include -#endif - -/* defined so I can write to a file on gui/windowing platforms */ -/* #define STDERR stderr */ -#define STDERR stdout /* for DOS */ - -/* example of using row callbacks to make a simple progress meter */ -static int status_pass=1; -static int status_dots_requested=0; -static int status_dots=1; - -/* In case a system header (e.g., on AIX) defined jmpbuf */ -#ifdef jmpbuf -# undef jmpbuf -#endif - -/* Define png_jmpbuf() in case we are using a pre-1.0.6 version of libpng */ -#ifndef png_jmpbuf -# define png_jmpbuf(png_ptr) png_ptr->jmpbuf -#endif - -void -#ifdef PNG_1_0_X -PNGAPI -#endif -read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass); -void -#ifdef PNG_1_0_X -PNGAPI -#endif -read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass) -{ - if(png_ptr == NULL || row_number > PNG_UINT_31_MAX) return; - if(status_pass != pass) - { - fprintf(stdout,"\n Pass %d: ",pass); - status_pass = pass; - status_dots = 31; - } - status_dots--; - if(status_dots == 0) - { - fprintf(stdout, "\n "); - status_dots=30; - } - fprintf(stdout, "r"); -} - -void -#ifdef PNG_1_0_X -PNGAPI -#endif -write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass); -void -#ifdef PNG_1_0_X -PNGAPI -#endif -write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass) -{ - if(png_ptr == NULL || row_number > PNG_UINT_31_MAX || pass > 7) return; - fprintf(stdout, "w"); -} - - -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) -/* Example of using user transform callback (we don't transform anything, - but merely examine the row filters. We set this to 256 rather than - 5 in case illegal filter values are present.) */ -static png_uint_32 filters_used[256]; -void -#ifdef PNG_1_0_X -PNGAPI -#endif -count_filters(png_structp png_ptr, png_row_infop row_info, png_bytep data); -void -#ifdef PNG_1_0_X -PNGAPI -#endif -count_filters(png_structp png_ptr, png_row_infop row_info, png_bytep data) -{ - if(png_ptr != NULL && row_info != NULL) - ++filters_used[*(data-1)]; -} -#endif - -#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) -/* example of using user transform callback (we don't transform anything, - but merely count the zero samples) */ - -static png_uint_32 zero_samples; - -void -#ifdef PNG_1_0_X -PNGAPI -#endif -count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data); -void -#ifdef PNG_1_0_X -PNGAPI -#endif -count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data) -{ - png_bytep dp = data; - if(png_ptr == NULL)return; - - /* contents of row_info: - * png_uint_32 width width of row - * png_uint_32 rowbytes number of bytes in row - * png_byte color_type color type of pixels - * png_byte bit_depth bit depth of samples - * png_byte channels number of channels (1-4) - * png_byte pixel_depth bits per pixel (depth*channels) - */ - - - /* counts the number of zero samples (or zero pixels if color_type is 3 */ - - if(row_info->color_type == 0 || row_info->color_type == 3) - { - int pos=0; - png_uint_32 n, nstop; - for (n=0, nstop=row_info->width; nbit_depth == 1) - { - if(((*dp << pos++ ) & 0x80) == 0) zero_samples++; - if(pos == 8) - { - pos = 0; - dp++; - } - } - if(row_info->bit_depth == 2) - { - if(((*dp << (pos+=2)) & 0xc0) == 0) zero_samples++; - if(pos == 8) - { - pos = 0; - dp++; - } - } - if(row_info->bit_depth == 4) - { - if(((*dp << (pos+=4)) & 0xf0) == 0) zero_samples++; - if(pos == 8) - { - pos = 0; - dp++; - } - } - if(row_info->bit_depth == 8) - if(*dp++ == 0) zero_samples++; - if(row_info->bit_depth == 16) - { - if((*dp | *(dp+1)) == 0) zero_samples++; - dp+=2; - } - } - } - else /* other color types */ - { - png_uint_32 n, nstop; - int channel; - int color_channels = row_info->channels; - if(row_info->color_type > 3)color_channels--; - - for (n=0, nstop=row_info->width; nbit_depth == 8) - if(*dp++ == 0) zero_samples++; - if(row_info->bit_depth == 16) - { - if((*dp | *(dp+1)) == 0) zero_samples++; - dp+=2; - } - } - if(row_info->color_type > 3) - { - dp++; - if(row_info->bit_depth == 16)dp++; - } - } - } -} -#endif /* PNG_WRITE_USER_TRANSFORM_SUPPORTED */ - -static int wrote_question = 0; - -#if defined(PNG_NO_STDIO) -/* START of code to validate stdio-free compilation */ -/* These copies of the default read/write functions come from pngrio.c and */ -/* pngwio.c. They allow "don't include stdio" testing of the library. */ -/* This is the function that does the actual reading of data. If you are - not reading from a standard C stream, you should create a replacement - read_data function and use it at run time with png_set_read_fn(), rather - than changing the library. */ - -#ifndef USE_FAR_KEYWORD -static void -pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length) -{ - png_size_t check; - - /* fread() returns 0 on error, so it is OK to store this in a png_size_t - * instead of an int, which is what fread() actually returns. - */ - READFILE((png_FILE_p)png_ptr->io_ptr, data, length, check); - - if (check != length) - { - png_error(png_ptr, "Read Error!"); - } -} -#else -/* this is the model-independent version. Since the standard I/O library - can't handle far buffers in the medium and small models, we have to copy - the data. -*/ - -#define NEAR_BUF_SIZE 1024 -#define MIN(a,b) (a <= b ? a : b) - -static void -pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length) -{ - int check; - png_byte *n_data; - png_FILE_p io_ptr; - - /* Check if data really is near. If so, use usual code. */ - n_data = (png_byte *)CVT_PTR_NOCHECK(data); - io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); - if ((png_bytep)n_data == data) - { - READFILE(io_ptr, n_data, length, check); - } - else - { - png_byte buf[NEAR_BUF_SIZE]; - png_size_t read, remaining, err; - check = 0; - remaining = length; - do - { - read = MIN(NEAR_BUF_SIZE, remaining); - READFILE(io_ptr, buf, 1, err); - png_memcpy(data, buf, read); /* copy far buffer to near buffer */ - if(err != read) - break; - else - check += err; - data += read; - remaining -= read; - } - while (remaining != 0); - } - if (check != length) - { - png_error(png_ptr, "read Error"); - } -} -#endif /* USE_FAR_KEYWORD */ - -#if defined(PNG_WRITE_FLUSH_SUPPORTED) -static void -pngtest_flush(png_structp png_ptr) -{ -#if !defined(_WIN32_WCE) - png_FILE_p io_ptr; - io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr)); - if (io_ptr != NULL) - fflush(io_ptr); -#endif -} -#endif - -/* This is the function that does the actual writing of data. If you are - not writing to a standard C stream, you should create a replacement - write_data function and use it at run time with png_set_write_fn(), rather - than changing the library. */ -#ifndef USE_FAR_KEYWORD -static void -pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length) -{ - png_uint_32 check; - - WRITEFILE((png_FILE_p)png_ptr->io_ptr, data, length, check); - if (check != length) - { - png_error(png_ptr, "Write Error"); - } -} -#else -/* this is the model-independent version. Since the standard I/O library - can't handle far buffers in the medium and small models, we have to copy - the data. -*/ - -#define NEAR_BUF_SIZE 1024 -#define MIN(a,b) (a <= b ? a : b) - -static void -pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length) -{ - png_uint_32 check; - png_byte *near_data; /* Needs to be "png_byte *" instead of "png_bytep" */ - png_FILE_p io_ptr; - - /* Check if data really is near. If so, use usual code. */ - near_data = (png_byte *)CVT_PTR_NOCHECK(data); - io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); - if ((png_bytep)near_data == data) - { - WRITEFILE(io_ptr, near_data, length, check); - } - else - { - png_byte buf[NEAR_BUF_SIZE]; - png_size_t written, remaining, err; - check = 0; - remaining = length; - do - { - written = MIN(NEAR_BUF_SIZE, remaining); - png_memcpy(buf, data, written); /* copy far buffer to near buffer */ - WRITEFILE(io_ptr, buf, written, err); - if (err != written) - break; - else - check += err; - data += written; - remaining -= written; - } - while (remaining != 0); - } - if (check != length) - { - png_error(png_ptr, "Write Error"); - } -} -#endif /* USE_FAR_KEYWORD */ -#endif /* PNG_NO_STDIO */ -/* END of code to validate stdio-free compilation */ - -/* This function is called when there is a warning, but the library thinks - * it can continue anyway. Replacement functions don't have to do anything - * here if you don't want to. In the default configuration, png_ptr is - * not used, but it is passed in case it may be useful. - */ -static void -pngtest_warning(png_structp png_ptr, png_const_charp message) -{ - PNG_CONST char *name = "UNKNOWN (ERROR!)"; - if (png_ptr != NULL && png_ptr->error_ptr != NULL) - name = png_ptr->error_ptr; - fprintf(STDERR, "%s: libpng warning: %s\n", name, message); -} - -/* This is the default error handling function. Note that replacements for - * this function MUST NOT RETURN, or the program will likely crash. This - * function is used by default, or if the program supplies NULL for the - * error function pointer in png_set_error_fn(). - */ -static void -pngtest_error(png_structp png_ptr, png_const_charp message) -{ - pngtest_warning(png_ptr, message); - /* We can return because png_error calls the default handler, which is - * actually OK in this case. */ -} - -/* START of code to validate memory allocation and deallocation */ -#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG - -/* Allocate memory. For reasonable files, size should never exceed - 64K. However, zlib may allocate more then 64K if you don't tell - it not to. See zconf.h and png.h for more information. zlib does - need to allocate exactly 64K, so whatever you call here must - have the ability to do that. - - This piece of code can be compiled to validate max 64K allocations - by setting MAXSEG_64K in zlib zconf.h *or* PNG_MAX_MALLOC_64K. */ -typedef struct memory_information -{ - png_uint_32 size; - png_voidp pointer; - struct memory_information FAR *next; -} memory_information; -typedef memory_information FAR *memory_infop; - -static memory_infop pinformation = NULL; -static int current_allocation = 0; -static int maximum_allocation = 0; -static int total_allocation = 0; -static int num_allocations = 0; - -png_voidp png_debug_malloc PNGARG((png_structp png_ptr, png_uint_32 size)); -void png_debug_free PNGARG((png_structp png_ptr, png_voidp ptr)); - -png_voidp -png_debug_malloc(png_structp png_ptr, png_uint_32 size) -{ - - /* png_malloc has already tested for NULL; png_create_struct calls - png_debug_malloc directly, with png_ptr == NULL which is OK */ - - if (size == 0) - return (NULL); - - /* This calls the library allocator twice, once to get the requested - buffer and once to get a new free list entry. */ - { - /* Disable malloc_fn and free_fn */ - memory_infop pinfo; - png_set_mem_fn(png_ptr, NULL, NULL, NULL); - pinfo = (memory_infop)png_malloc(png_ptr, - (png_uint_32)png_sizeof (*pinfo)); - pinfo->size = size; - current_allocation += size; - total_allocation += size; - num_allocations ++; - if (current_allocation > maximum_allocation) - maximum_allocation = current_allocation; - pinfo->pointer = (png_voidp)png_malloc(png_ptr, size); - /* Restore malloc_fn and free_fn */ - png_set_mem_fn(png_ptr, png_voidp_NULL, (png_malloc_ptr)png_debug_malloc, - (png_free_ptr)png_debug_free); - if (size != 0 && pinfo->pointer == NULL) - { - current_allocation -= size; - total_allocation -= size; - png_error(png_ptr, - "out of memory in pngtest->png_debug_malloc."); - } - pinfo->next = pinformation; - pinformation = pinfo; - /* Make sure the caller isn't assuming zeroed memory. */ - png_memset(pinfo->pointer, 0xdd, pinfo->size); - if(verbose) - printf("png_malloc %lu bytes at %x\n",(unsigned long)size, - pinfo->pointer); - return (png_voidp)(pinfo->pointer); - } -} - -/* Free a pointer. It is removed from the list at the same time. */ -void -png_debug_free(png_structp png_ptr, png_voidp ptr) -{ - if (png_ptr == NULL) - fprintf(STDERR, "NULL pointer to png_debug_free.\n"); - if (ptr == 0) - { -#if 0 /* This happens all the time. */ - fprintf(STDERR, "WARNING: freeing NULL pointer\n"); -#endif - return; - } - - /* Unlink the element from the list. */ - { - memory_infop FAR *ppinfo = &pinformation; - for (;;) - { - memory_infop pinfo = *ppinfo; - if (pinfo->pointer == ptr) - { - *ppinfo = pinfo->next; - current_allocation -= pinfo->size; - if (current_allocation < 0) - fprintf(STDERR, "Duplicate free of memory\n"); - /* We must free the list element too, but first kill - the memory that is to be freed. */ - png_memset(ptr, 0x55, pinfo->size); - png_free_default(png_ptr, pinfo); - pinfo=NULL; - break; - } - if (pinfo->next == NULL) - { - fprintf(STDERR, "Pointer %x not found\n", (unsigned int)ptr); - break; - } - ppinfo = &pinfo->next; - } - } - - /* Finally free the data. */ - if(verbose) - printf("Freeing %x\n",ptr); - png_free_default(png_ptr, ptr); - ptr=NULL; -} -#endif /* PNG_USER_MEM_SUPPORTED && PNG_DEBUG */ -/* END of code to test memory allocation/deallocation */ - -/* Test one file */ -int -test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) -{ - static png_FILE_p fpin; - static png_FILE_p fpout; /* "static" prevents setjmp corruption */ - png_structp read_ptr; - png_infop read_info_ptr, end_info_ptr; -#ifdef PNG_WRITE_SUPPORTED - png_structp write_ptr; - png_infop write_info_ptr; - png_infop write_end_info_ptr; -#else - png_structp write_ptr = NULL; - png_infop write_info_ptr = NULL; - png_infop write_end_info_ptr = NULL; -#endif - png_bytep row_buf; - png_uint_32 y; - png_uint_32 width, height; - int num_pass, pass; - int bit_depth, color_type; -#ifdef PNG_SETJMP_SUPPORTED -#ifdef USE_FAR_KEYWORD - jmp_buf jmpbuf; -#endif -#endif - -#if defined(_WIN32_WCE) - TCHAR path[MAX_PATH]; -#endif - char inbuf[256], outbuf[256]; - - row_buf = NULL; - -#if defined(_WIN32_WCE) - MultiByteToWideChar(CP_ACP, 0, inname, -1, path, MAX_PATH); - if ((fpin = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) -#else - if ((fpin = fopen(inname, "rb")) == NULL) -#endif - { - fprintf(STDERR, "Could not find input file %s\n", inname); - return (1); - } - -#if defined(_WIN32_WCE) - MultiByteToWideChar(CP_ACP, 0, outname, -1, path, MAX_PATH); - if ((fpout = CreateFile(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL)) == INVALID_HANDLE_VALUE) -#else - if ((fpout = fopen(outname, "wb")) == NULL) -#endif - { - fprintf(STDERR, "Could not open output file %s\n", outname); - FCLOSE(fpin); - return (1); - } - - png_debug(0, "Allocating read and write structures\n"); -#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG - read_ptr = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, png_voidp_NULL, - png_error_ptr_NULL, png_error_ptr_NULL, png_voidp_NULL, - (png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free); -#else - read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, png_voidp_NULL, - png_error_ptr_NULL, png_error_ptr_NULL); -#endif - png_set_error_fn(read_ptr, (png_voidp)inname, pngtest_error, - pngtest_warning); -#ifdef PNG_WRITE_SUPPORTED -#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG - write_ptr = png_create_write_struct_2(PNG_LIBPNG_VER_STRING, png_voidp_NULL, - png_error_ptr_NULL, png_error_ptr_NULL, png_voidp_NULL, - (png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free); -#else - write_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, png_voidp_NULL, - png_error_ptr_NULL, png_error_ptr_NULL); -#endif - png_set_error_fn(write_ptr, (png_voidp)inname, pngtest_error, - pngtest_warning); -#endif - png_debug(0, "Allocating read_info, write_info and end_info structures\n"); - read_info_ptr = png_create_info_struct(read_ptr); - end_info_ptr = png_create_info_struct(read_ptr); -#ifdef PNG_WRITE_SUPPORTED - write_info_ptr = png_create_info_struct(write_ptr); - write_end_info_ptr = png_create_info_struct(write_ptr); -#endif - -#ifdef PNG_SETJMP_SUPPORTED - png_debug(0, "Setting jmpbuf for read struct\n"); -#ifdef USE_FAR_KEYWORD - if (setjmp(jmpbuf)) -#else - if (setjmp(png_jmpbuf(read_ptr))) -#endif - { - fprintf(STDERR, "%s -> %s: libpng read error\n", inname, outname); - if (row_buf) - png_free(read_ptr, row_buf); - png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); -#ifdef PNG_WRITE_SUPPORTED - png_destroy_info_struct(write_ptr, &write_end_info_ptr); - png_destroy_write_struct(&write_ptr, &write_info_ptr); -#endif - FCLOSE(fpin); - FCLOSE(fpout); - return (1); - } -#ifdef USE_FAR_KEYWORD - png_memcpy(png_jmpbuf(read_ptr),jmpbuf,png_sizeof(jmp_buf)); -#endif - -#ifdef PNG_WRITE_SUPPORTED - png_debug(0, "Setting jmpbuf for write struct\n"); -#ifdef USE_FAR_KEYWORD - if (setjmp(jmpbuf)) -#else - if (setjmp(png_jmpbuf(write_ptr))) -#endif - { - fprintf(STDERR, "%s -> %s: libpng write error\n", inname, outname); - png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); - png_destroy_info_struct(write_ptr, &write_end_info_ptr); -#ifdef PNG_WRITE_SUPPORTED - png_destroy_write_struct(&write_ptr, &write_info_ptr); -#endif - FCLOSE(fpin); - FCLOSE(fpout); - return (1); - } -#ifdef USE_FAR_KEYWORD - png_memcpy(png_jmpbuf(write_ptr),jmpbuf,png_sizeof(jmp_buf)); -#endif -#endif -#endif - - png_debug(0, "Initializing input and output streams\n"); -#if !defined(PNG_NO_STDIO) - png_init_io(read_ptr, fpin); -# ifdef PNG_WRITE_SUPPORTED - png_init_io(write_ptr, fpout); -# endif -#else - png_set_read_fn(read_ptr, (png_voidp)fpin, pngtest_read_data); -# ifdef PNG_WRITE_SUPPORTED - png_set_write_fn(write_ptr, (png_voidp)fpout, pngtest_write_data, -# if defined(PNG_WRITE_FLUSH_SUPPORTED) - pngtest_flush); -# else - NULL); -# endif -# endif -#endif - if(status_dots_requested == 1) - { -#ifdef PNG_WRITE_SUPPORTED - png_set_write_status_fn(write_ptr, write_row_callback); -#endif - png_set_read_status_fn(read_ptr, read_row_callback); - } - else - { -#ifdef PNG_WRITE_SUPPORTED - png_set_write_status_fn(write_ptr, png_write_status_ptr_NULL); -#endif - png_set_read_status_fn(read_ptr, png_read_status_ptr_NULL); - } - -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) - { - int i; - for(i=0; i<256; i++) - filters_used[i]=0; - png_set_read_user_transform_fn(read_ptr, count_filters); - } -#endif -#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) - zero_samples=0; - png_set_write_user_transform_fn(write_ptr, count_zero_samples); -#endif - -#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) -# ifndef PNG_HANDLE_CHUNK_ALWAYS -# define PNG_HANDLE_CHUNK_ALWAYS 3 -# endif - png_set_keep_unknown_chunks(read_ptr, PNG_HANDLE_CHUNK_ALWAYS, - png_bytep_NULL, 0); -#endif -#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) -# ifndef PNG_HANDLE_CHUNK_IF_SAFE -# define PNG_HANDLE_CHUNK_IF_SAFE 2 -# endif - png_set_keep_unknown_chunks(write_ptr, PNG_HANDLE_CHUNK_IF_SAFE, - png_bytep_NULL, 0); -#endif - - png_debug(0, "Reading info struct\n"); - png_read_info(read_ptr, read_info_ptr); - - png_debug(0, "Transferring info struct\n"); - { - int interlace_type, compression_type, filter_type; - - if (png_get_IHDR(read_ptr, read_info_ptr, &width, &height, &bit_depth, - &color_type, &interlace_type, &compression_type, &filter_type)) - { - png_set_IHDR(write_ptr, write_info_ptr, width, height, bit_depth, -#if defined(PNG_WRITE_INTERLACING_SUPPORTED) - color_type, interlace_type, compression_type, filter_type); -#else - color_type, PNG_INTERLACE_NONE, compression_type, filter_type); -#endif - } - } -#if defined(PNG_FIXED_POINT_SUPPORTED) -#if defined(PNG_cHRM_SUPPORTED) - { - png_fixed_point white_x, white_y, red_x, red_y, green_x, green_y, blue_x, - blue_y; - if (png_get_cHRM_fixed(read_ptr, read_info_ptr, &white_x, &white_y, &red_x, - &red_y, &green_x, &green_y, &blue_x, &blue_y)) - { - png_set_cHRM_fixed(write_ptr, write_info_ptr, white_x, white_y, red_x, - red_y, green_x, green_y, blue_x, blue_y); - } - } -#endif -#if defined(PNG_gAMA_SUPPORTED) - { - png_fixed_point gamma; - - if (png_get_gAMA_fixed(read_ptr, read_info_ptr, &gamma)) - { - png_set_gAMA_fixed(write_ptr, write_info_ptr, gamma); - } - } -#endif -#else /* Use floating point versions */ -#if defined(PNG_FLOATING_POINT_SUPPORTED) -#if defined(PNG_cHRM_SUPPORTED) - { - double white_x, white_y, red_x, red_y, green_x, green_y, blue_x, - blue_y; - if (png_get_cHRM(read_ptr, read_info_ptr, &white_x, &white_y, &red_x, - &red_y, &green_x, &green_y, &blue_x, &blue_y)) - { - png_set_cHRM(write_ptr, write_info_ptr, white_x, white_y, red_x, - red_y, green_x, green_y, blue_x, blue_y); - } - } -#endif -#if defined(PNG_gAMA_SUPPORTED) - { - double gamma; - - if (png_get_gAMA(read_ptr, read_info_ptr, &gamma)) - { - png_set_gAMA(write_ptr, write_info_ptr, gamma); - } - } -#endif -#endif /* floating point */ -#endif /* fixed point */ -#if defined(PNG_iCCP_SUPPORTED) - { - png_charp name; - png_charp profile; - png_uint_32 proflen; - int compression_type; - - if (png_get_iCCP(read_ptr, read_info_ptr, &name, &compression_type, - &profile, &proflen)) - { - png_set_iCCP(write_ptr, write_info_ptr, name, compression_type, - profile, proflen); - } - } -#endif -#if defined(PNG_sRGB_SUPPORTED) - { - int intent; - - if (png_get_sRGB(read_ptr, read_info_ptr, &intent)) - { - png_set_sRGB(write_ptr, write_info_ptr, intent); - } - } -#endif - { - png_colorp palette; - int num_palette; - - if (png_get_PLTE(read_ptr, read_info_ptr, &palette, &num_palette)) - { - png_set_PLTE(write_ptr, write_info_ptr, palette, num_palette); - } - } -#if defined(PNG_bKGD_SUPPORTED) - { - png_color_16p background; - - if (png_get_bKGD(read_ptr, read_info_ptr, &background)) - { - png_set_bKGD(write_ptr, write_info_ptr, background); - } - } -#endif -#if defined(PNG_hIST_SUPPORTED) - { - png_uint_16p hist; - - if (png_get_hIST(read_ptr, read_info_ptr, &hist)) - { - png_set_hIST(write_ptr, write_info_ptr, hist); - } - } -#endif -#if defined(PNG_oFFs_SUPPORTED) - { - png_int_32 offset_x, offset_y; - int unit_type; - - if (png_get_oFFs(read_ptr, read_info_ptr,&offset_x,&offset_y,&unit_type)) - { - png_set_oFFs(write_ptr, write_info_ptr, offset_x, offset_y, unit_type); - } - } -#endif -#if defined(PNG_pCAL_SUPPORTED) - { - png_charp purpose, units; - png_charpp params; - png_int_32 X0, X1; - int type, nparams; - - if (png_get_pCAL(read_ptr, read_info_ptr, &purpose, &X0, &X1, &type, - &nparams, &units, ¶ms)) - { - png_set_pCAL(write_ptr, write_info_ptr, purpose, X0, X1, type, - nparams, units, params); - } - } -#endif -#if defined(PNG_pHYs_SUPPORTED) - { - png_uint_32 res_x, res_y; - int unit_type; - - if (png_get_pHYs(read_ptr, read_info_ptr, &res_x, &res_y, &unit_type)) - { - png_set_pHYs(write_ptr, write_info_ptr, res_x, res_y, unit_type); - } - } -#endif -#if defined(PNG_sBIT_SUPPORTED) - { - png_color_8p sig_bit; - - if (png_get_sBIT(read_ptr, read_info_ptr, &sig_bit)) - { - png_set_sBIT(write_ptr, write_info_ptr, sig_bit); - } - } -#endif -#if defined(PNG_sCAL_SUPPORTED) -#ifdef PNG_FLOATING_POINT_SUPPORTED - { - int unit; - double scal_width, scal_height; - - if (png_get_sCAL(read_ptr, read_info_ptr, &unit, &scal_width, - &scal_height)) - { - png_set_sCAL(write_ptr, write_info_ptr, unit, scal_width, scal_height); - } - } -#else -#ifdef PNG_FIXED_POINT_SUPPORTED - { - int unit; - png_charp scal_width, scal_height; - - if (png_get_sCAL_s(read_ptr, read_info_ptr, &unit, &scal_width, - &scal_height)) - { - png_set_sCAL_s(write_ptr, write_info_ptr, unit, scal_width, scal_height); - } - } -#endif -#endif -#endif -#if defined(PNG_TEXT_SUPPORTED) - { - png_textp text_ptr; - int num_text; - - if (png_get_text(read_ptr, read_info_ptr, &text_ptr, &num_text) > 0) - { - png_debug1(0, "Handling %d iTXt/tEXt/zTXt chunks\n", num_text); - png_set_text(write_ptr, write_info_ptr, text_ptr, num_text); - } - } -#endif -#if defined(PNG_tIME_SUPPORTED) - { - png_timep mod_time; - - if (png_get_tIME(read_ptr, read_info_ptr, &mod_time)) - { - png_set_tIME(write_ptr, write_info_ptr, mod_time); -#if defined(PNG_TIME_RFC1123_SUPPORTED) - /* we have to use png_memcpy instead of "=" because the string - pointed to by png_convert_to_rfc1123() gets free'ed before - we use it */ - png_memcpy(tIME_string, - png_convert_to_rfc1123(read_ptr, mod_time), - png_sizeof(tIME_string)); - tIME_string[png_sizeof(tIME_string)-1] = '\0'; - tIME_chunk_present++; -#endif /* PNG_TIME_RFC1123_SUPPORTED */ - } - } -#endif -#if defined(PNG_tRNS_SUPPORTED) - { - png_bytep trans; - int num_trans; - png_color_16p trans_values; - - if (png_get_tRNS(read_ptr, read_info_ptr, &trans, &num_trans, - &trans_values)) - { - png_set_tRNS(write_ptr, write_info_ptr, trans, num_trans, - trans_values); - } - } -#endif -#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) - { - png_unknown_chunkp unknowns; - int num_unknowns = (int)png_get_unknown_chunks(read_ptr, read_info_ptr, - &unknowns); - if (num_unknowns) - { - png_size_t i; - png_set_unknown_chunks(write_ptr, write_info_ptr, unknowns, - num_unknowns); - /* copy the locations from the read_info_ptr. The automatically - generated locations in write_info_ptr are wrong because we - haven't written anything yet */ - for (i = 0; i < (png_size_t)num_unknowns; i++) - png_set_unknown_chunk_location(write_ptr, write_info_ptr, i, - unknowns[i].location); - } - } -#endif - -#ifdef PNG_WRITE_SUPPORTED - png_debug(0, "\nWriting info struct\n"); - -/* If we wanted, we could write info in two steps: - png_write_info_before_PLTE(write_ptr, write_info_ptr); - */ - png_write_info(write_ptr, write_info_ptr); -#endif - -#ifdef SINGLE_ROWBUF_ALLOC - png_debug(0, "\nAllocating row buffer..."); - row_buf = (png_bytep)png_malloc(read_ptr, - png_get_rowbytes(read_ptr, read_info_ptr)); - png_debug1(0, "0x%08lx\n\n", (unsigned long)row_buf); -#endif /* SINGLE_ROWBUF_ALLOC */ - png_debug(0, "Writing row data\n"); - -#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ - defined(PNG_WRITE_INTERLACING_SUPPORTED) - num_pass = png_set_interlace_handling(read_ptr); -# ifdef PNG_WRITE_SUPPORTED - png_set_interlace_handling(write_ptr); -# endif -#else - num_pass=1; -#endif - -#ifdef PNGTEST_TIMING - t_stop = (float)clock(); - t_misc += (t_stop - t_start); - t_start = t_stop; -#endif - for (pass = 0; pass < num_pass; pass++) - { - png_debug1(0, "Writing row data for pass %d\n",pass); - for (y = 0; y < height; y++) - { -#ifndef SINGLE_ROWBUF_ALLOC - png_debug2(0, "\nAllocating row buffer (pass %d, y = %ld)...", pass,y); - row_buf = (png_bytep)png_malloc(read_ptr, - png_get_rowbytes(read_ptr, read_info_ptr)); - png_debug2(0, "0x%08lx (%ld bytes)\n", (unsigned long)row_buf, - png_get_rowbytes(read_ptr, read_info_ptr)); -#endif /* !SINGLE_ROWBUF_ALLOC */ - png_read_rows(read_ptr, (png_bytepp)&row_buf, png_bytepp_NULL, 1); - -#ifdef PNG_WRITE_SUPPORTED -#ifdef PNGTEST_TIMING - t_stop = (float)clock(); - t_decode += (t_stop - t_start); - t_start = t_stop; -#endif - png_write_rows(write_ptr, (png_bytepp)&row_buf, 1); -#ifdef PNGTEST_TIMING - t_stop = (float)clock(); - t_encode += (t_stop - t_start); - t_start = t_stop; -#endif -#endif /* PNG_WRITE_SUPPORTED */ - -#ifndef SINGLE_ROWBUF_ALLOC - png_debug2(0, "Freeing row buffer (pass %d, y = %ld)\n\n", pass, y); - png_free(read_ptr, row_buf); -#endif /* !SINGLE_ROWBUF_ALLOC */ - } - } - -#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) - png_free_data(read_ptr, read_info_ptr, PNG_FREE_UNKN, -1); -#endif -#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) - png_free_data(write_ptr, write_info_ptr, PNG_FREE_UNKN, -1); -#endif - - png_debug(0, "Reading and writing end_info data\n"); - - png_read_end(read_ptr, end_info_ptr); -#if defined(PNG_TEXT_SUPPORTED) - { - png_textp text_ptr; - int num_text; - - if (png_get_text(read_ptr, end_info_ptr, &text_ptr, &num_text) > 0) - { - png_debug1(0, "Handling %d iTXt/tEXt/zTXt chunks\n", num_text); - png_set_text(write_ptr, write_end_info_ptr, text_ptr, num_text); - } - } -#endif -#if defined(PNG_tIME_SUPPORTED) - { - png_timep mod_time; - - if (png_get_tIME(read_ptr, end_info_ptr, &mod_time)) - { - png_set_tIME(write_ptr, write_end_info_ptr, mod_time); -#if defined(PNG_TIME_RFC1123_SUPPORTED) - /* we have to use png_memcpy instead of "=" because the string - pointed to by png_convert_to_rfc1123() gets free'ed before - we use it */ - png_memcpy(tIME_string, - png_convert_to_rfc1123(read_ptr, mod_time), - png_sizeof(tIME_string)); - tIME_string[png_sizeof(tIME_string)-1] = '\0'; - tIME_chunk_present++; -#endif /* PNG_TIME_RFC1123_SUPPORTED */ - } - } -#endif -#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) - { - png_unknown_chunkp unknowns; - int num_unknowns; - num_unknowns = (int)png_get_unknown_chunks(read_ptr, end_info_ptr, - &unknowns); - if (num_unknowns) - { - png_size_t i; - png_set_unknown_chunks(write_ptr, write_end_info_ptr, unknowns, - num_unknowns); - /* copy the locations from the read_info_ptr. The automatically - generated locations in write_end_info_ptr are wrong because we - haven't written the end_info yet */ - for (i = 0; i < (png_size_t)num_unknowns; i++) - png_set_unknown_chunk_location(write_ptr, write_end_info_ptr, i, - unknowns[i].location); - } - } -#endif -#ifdef PNG_WRITE_SUPPORTED - png_write_end(write_ptr, write_end_info_ptr); -#endif - -#ifdef PNG_EASY_ACCESS_SUPPORTED - if(verbose) - { - png_uint_32 iwidth, iheight; - iwidth = png_get_image_width(write_ptr, write_info_ptr); - iheight = png_get_image_height(write_ptr, write_info_ptr); - fprintf(STDERR, "Image width = %lu, height = %lu\n", - (unsigned long)iwidth, (unsigned long)iheight); - } -#endif - - png_debug(0, "Destroying data structs\n"); -#ifdef SINGLE_ROWBUF_ALLOC - png_debug(1, "destroying row_buf for read_ptr\n"); - png_free(read_ptr, row_buf); - row_buf=NULL; -#endif /* SINGLE_ROWBUF_ALLOC */ - png_debug(1, "destroying read_ptr, read_info_ptr, end_info_ptr\n"); - png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); -#ifdef PNG_WRITE_SUPPORTED - png_debug(1, "destroying write_end_info_ptr\n"); - png_destroy_info_struct(write_ptr, &write_end_info_ptr); - png_debug(1, "destroying write_ptr, write_info_ptr\n"); - png_destroy_write_struct(&write_ptr, &write_info_ptr); -#endif - png_debug(0, "Destruction complete.\n"); - - FCLOSE(fpin); - FCLOSE(fpout); - - png_debug(0, "Opening files for comparison\n"); -#if defined(_WIN32_WCE) - MultiByteToWideChar(CP_ACP, 0, inname, -1, path, MAX_PATH); - if ((fpin = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) -#else - if ((fpin = fopen(inname, "rb")) == NULL) -#endif - { - fprintf(STDERR, "Could not find file %s\n", inname); - return (1); - } - -#if defined(_WIN32_WCE) - MultiByteToWideChar(CP_ACP, 0, outname, -1, path, MAX_PATH); - if ((fpout = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) -#else - if ((fpout = fopen(outname, "rb")) == NULL) -#endif - { - fprintf(STDERR, "Could not find file %s\n", outname); - FCLOSE(fpin); - return (1); - } - - for(;;) - { - png_size_t num_in, num_out; - - READFILE(fpin, inbuf, 1, num_in); - READFILE(fpout, outbuf, 1, num_out); - - if (num_in != num_out) - { - fprintf(STDERR, "\nFiles %s and %s are of a different size\n", - inname, outname); - if(wrote_question == 0) - { - fprintf(STDERR, - " Was %s written with the same maximum IDAT chunk size (%d bytes),", - inname,PNG_ZBUF_SIZE); - fprintf(STDERR, - "\n filtering heuristic (libpng default), compression"); - fprintf(STDERR, - " level (zlib default),\n and zlib version (%s)?\n\n", - ZLIB_VERSION); - wrote_question=1; - } - FCLOSE(fpin); - FCLOSE(fpout); - return (0); - } - - if (!num_in) - break; - - if (png_memcmp(inbuf, outbuf, num_in)) - { - fprintf(STDERR, "\nFiles %s and %s are different\n", inname, outname); - if(wrote_question == 0) - { - fprintf(STDERR, - " Was %s written with the same maximum IDAT chunk size (%d bytes),", - inname,PNG_ZBUF_SIZE); - fprintf(STDERR, - "\n filtering heuristic (libpng default), compression"); - fprintf(STDERR, - " level (zlib default),\n and zlib version (%s)?\n\n", - ZLIB_VERSION); - wrote_question=1; - } - FCLOSE(fpin); - FCLOSE(fpout); - return (0); - } - } - - FCLOSE(fpin); - FCLOSE(fpout); - - return (0); -} - -/* input and output filenames */ -#ifdef RISCOS -static PNG_CONST char *inname = "pngtest/png"; -static PNG_CONST char *outname = "pngout/png"; -#else -static PNG_CONST char *inname = "pngtest.png"; -static PNG_CONST char *outname = "pngout.png"; -#endif - -int -main(int argc, char *argv[]) -{ - int multiple = 0; - int ierror = 0; - - fprintf(STDERR, "Testing libpng version %s\n", PNG_LIBPNG_VER_STRING); - fprintf(STDERR, " with zlib version %s\n", ZLIB_VERSION); - fprintf(STDERR,"%s",png_get_copyright(NULL)); - /* Show the version of libpng used in building the library */ - fprintf(STDERR," library (%lu):%s", - (unsigned long)png_access_version_number(), - png_get_header_version(NULL)); - /* Show the version of libpng used in building the application */ - fprintf(STDERR," pngtest (%lu):%s", (unsigned long)PNG_LIBPNG_VER, - PNG_HEADER_VERSION_STRING); - fprintf(STDERR," png_sizeof(png_struct)=%ld, png_sizeof(png_info)=%ld\n", - (long)png_sizeof(png_struct), (long)png_sizeof(png_info)); - - /* Do some consistency checking on the memory allocation settings, I'm - not sure this matters, but it is nice to know, the first of these - tests should be impossible because of the way the macros are set - in pngconf.h */ -#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K) - fprintf(STDERR, " NOTE: Zlib compiled for max 64k, libpng not\n"); -#endif - /* I think the following can happen. */ -#if !defined(MAXSEG_64K) && defined(PNG_MAX_MALLOC_64K) - fprintf(STDERR, " NOTE: libpng compiled for max 64k, zlib not\n"); -#endif - - if (strcmp(png_libpng_ver, PNG_LIBPNG_VER_STRING)) - { - fprintf(STDERR, - "Warning: versions are different between png.h and png.c\n"); - fprintf(STDERR, " png.h version: %s\n", PNG_LIBPNG_VER_STRING); - fprintf(STDERR, " png.c version: %s\n\n", png_libpng_ver); - ++ierror; - } - - if (argc > 1) - { - if (strcmp(argv[1], "-m") == 0) - { - multiple = 1; - status_dots_requested = 0; - } - else if (strcmp(argv[1], "-mv") == 0 || - strcmp(argv[1], "-vm") == 0 ) - { - multiple = 1; - verbose = 1; - status_dots_requested = 1; - } - else if (strcmp(argv[1], "-v") == 0) - { - verbose = 1; - status_dots_requested = 1; - inname = argv[2]; - } - else - { - inname = argv[1]; - status_dots_requested = 0; - } - } - - if (!multiple && argc == 3+verbose) - outname = argv[2+verbose]; - - if ((!multiple && argc > 3+verbose) || (multiple && argc < 2)) - { - fprintf(STDERR, - "usage: %s [infile.png] [outfile.png]\n\t%s -m {infile.png}\n", - argv[0], argv[0]); - fprintf(STDERR, - " reads/writes one PNG file (without -m) or multiple files (-m)\n"); - fprintf(STDERR, - " with -m %s is used as a temporary file\n", outname); - exit(1); - } - - if (multiple) - { - int i; -#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG - int allocation_now = current_allocation; -#endif - for (i=2; isize, - (unsigned int) pinfo->pointer); - pinfo = pinfo->next; - } - } -#endif - } -#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG - fprintf(STDERR, " Current memory allocation: %10d bytes\n", - current_allocation); - fprintf(STDERR, " Maximum memory allocation: %10d bytes\n", - maximum_allocation); - fprintf(STDERR, " Total memory allocation: %10d bytes\n", - total_allocation); - fprintf(STDERR, " Number of allocations: %10d\n", - num_allocations); -#endif - } - else - { - int i; - for (i=0; i<3; ++i) - { - int kerror; -#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG - int allocation_now = current_allocation; -#endif - if (i == 1) status_dots_requested = 1; - else if(verbose == 0)status_dots_requested = 0; - if (i == 0 || verbose == 1 || ierror != 0) - fprintf(STDERR, "Testing %s:",inname); - kerror = test_one_file(inname, outname); - if(kerror == 0) - { - if(verbose == 1 || i == 2) - { -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) - int k; -#endif -#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) - fprintf(STDERR, "\n PASS (%lu zero samples)\n", - (unsigned long)zero_samples); -#else - fprintf(STDERR, " PASS\n"); -#endif -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) - for (k=0; k<256; k++) - if(filters_used[k]) - fprintf(STDERR, " Filter %d was used %lu times\n", - k,(unsigned long)filters_used[k]); -#endif -#if defined(PNG_TIME_RFC1123_SUPPORTED) - if(tIME_chunk_present != 0) - fprintf(STDERR, " tIME = %s\n",tIME_string); -#endif /* PNG_TIME_RFC1123_SUPPORTED */ - } - } - else - { - if(verbose == 0 && i != 2) - fprintf(STDERR, "Testing %s:",inname); - fprintf(STDERR, " FAIL\n"); - ierror += kerror; - } -#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG - if (allocation_now != current_allocation) - fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n", - current_allocation-allocation_now); - if (current_allocation != 0) - { - memory_infop pinfo = pinformation; - - fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n", - current_allocation); - while (pinfo != NULL) - { - fprintf(STDERR," %lu bytes at %x\n", - (unsigned long)pinfo->size, (unsigned int)pinfo->pointer); - pinfo = pinfo->next; - } - } -#endif - } -#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG - fprintf(STDERR, " Current memory allocation: %10d bytes\n", - current_allocation); - fprintf(STDERR, " Maximum memory allocation: %10d bytes\n", - maximum_allocation); - fprintf(STDERR, " Total memory allocation: %10d bytes\n", - total_allocation); - fprintf(STDERR, " Number of allocations: %10d\n", - num_allocations); -#endif - } - -#ifdef PNGTEST_TIMING - t_stop = (float)clock(); - t_misc += (t_stop - t_start); - t_start = t_stop; - fprintf(STDERR," CPU time used = %.3f seconds", - (t_misc+t_decode+t_encode)/(float)CLOCKS_PER_SEC); - fprintf(STDERR," (decoding %.3f,\n", - t_decode/(float)CLOCKS_PER_SEC); - fprintf(STDERR," encoding %.3f ,", - t_encode/(float)CLOCKS_PER_SEC); - fprintf(STDERR," other %.3f seconds)\n\n", - t_misc/(float)CLOCKS_PER_SEC); -#endif - - if (ierror == 0) - fprintf(STDERR, "libpng passes test\n"); - else - fprintf(STDERR, "libpng FAILS test\n"); - return (int)(ierror != 0); -} - -/* Generate a compiler error if there is an old png.h in the search path. */ -typedef version_1_2_24 your_png_h_is_not_version_1_2_24; diff --git a/rosapps/lib/libpng/pngtrans.c b/rosapps/lib/libpng/pngtrans.c deleted file mode 100644 index 1640095020c..00000000000 --- a/rosapps/lib/libpng/pngtrans.c +++ /dev/null @@ -1,662 +0,0 @@ - -/* pngtrans.c - transforms the data in a row (used by both readers and writers) - * - * Last changed in libpng 1.2.17 May 15, 2007 - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2007 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - */ - -#define PNG_INTERNAL -#include "png.h" - -#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) -#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) -/* turn on BGR-to-RGB mapping */ -void PNGAPI -png_set_bgr(png_structp png_ptr) -{ - png_debug(1, "in png_set_bgr\n"); - if(png_ptr == NULL) return; - png_ptr->transformations |= PNG_BGR; -} -#endif - -#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) -/* turn on 16 bit byte swapping */ -void PNGAPI -png_set_swap(png_structp png_ptr) -{ - png_debug(1, "in png_set_swap\n"); - if(png_ptr == NULL) return; - if (png_ptr->bit_depth == 16) - png_ptr->transformations |= PNG_SWAP_BYTES; -} -#endif - -#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) -/* turn on pixel packing */ -void PNGAPI -png_set_packing(png_structp png_ptr) -{ - png_debug(1, "in png_set_packing\n"); - if(png_ptr == NULL) return; - if (png_ptr->bit_depth < 8) - { - png_ptr->transformations |= PNG_PACK; - png_ptr->usr_bit_depth = 8; - } -} -#endif - -#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED) -/* turn on packed pixel swapping */ -void PNGAPI -png_set_packswap(png_structp png_ptr) -{ - png_debug(1, "in png_set_packswap\n"); - if(png_ptr == NULL) return; - if (png_ptr->bit_depth < 8) - png_ptr->transformations |= PNG_PACKSWAP; -} -#endif - -#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) -void PNGAPI -png_set_shift(png_structp png_ptr, png_color_8p true_bits) -{ - png_debug(1, "in png_set_shift\n"); - if(png_ptr == NULL) return; - png_ptr->transformations |= PNG_SHIFT; - png_ptr->shift = *true_bits; -} -#endif - -#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ - defined(PNG_WRITE_INTERLACING_SUPPORTED) -int PNGAPI -png_set_interlace_handling(png_structp png_ptr) -{ - png_debug(1, "in png_set_interlace handling\n"); - if (png_ptr && png_ptr->interlaced) - { - png_ptr->transformations |= PNG_INTERLACE; - return (7); - } - - return (1); -} -#endif - -#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) -/* Add a filler byte on read, or remove a filler or alpha byte on write. - * The filler type has changed in v0.95 to allow future 2-byte fillers - * for 48-bit input data, as well as to avoid problems with some compilers - * that don't like bytes as parameters. - */ -void PNGAPI -png_set_filler(png_structp png_ptr, png_uint_32 filler, int filler_loc) -{ - png_debug(1, "in png_set_filler\n"); - if(png_ptr == NULL) return; - png_ptr->transformations |= PNG_FILLER; - png_ptr->filler = (png_byte)filler; - if (filler_loc == PNG_FILLER_AFTER) - png_ptr->flags |= PNG_FLAG_FILLER_AFTER; - else - png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER; - - /* This should probably go in the "do_read_filler" routine. - * I attempted to do that in libpng-1.0.1a but that caused problems - * so I restored it in libpng-1.0.2a - */ - - if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) - { - png_ptr->usr_channels = 4; - } - - /* Also I added this in libpng-1.0.2a (what happens when we expand - * a less-than-8-bit grayscale to GA? */ - - if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY && png_ptr->bit_depth >= 8) - { - png_ptr->usr_channels = 2; - } -} - -#if !defined(PNG_1_0_X) -/* Added to libpng-1.2.7 */ -void PNGAPI -png_set_add_alpha(png_structp png_ptr, png_uint_32 filler, int filler_loc) -{ - png_debug(1, "in png_set_add_alpha\n"); - if(png_ptr == NULL) return; - png_set_filler(png_ptr, filler, filler_loc); - png_ptr->transformations |= PNG_ADD_ALPHA; -} -#endif - -#endif - -#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ - defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) -void PNGAPI -png_set_swap_alpha(png_structp png_ptr) -{ - png_debug(1, "in png_set_swap_alpha\n"); - if(png_ptr == NULL) return; - png_ptr->transformations |= PNG_SWAP_ALPHA; -} -#endif - -#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ - defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) -void PNGAPI -png_set_invert_alpha(png_structp png_ptr) -{ - png_debug(1, "in png_set_invert_alpha\n"); - if(png_ptr == NULL) return; - png_ptr->transformations |= PNG_INVERT_ALPHA; -} -#endif - -#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) -void PNGAPI -png_set_invert_mono(png_structp png_ptr) -{ - png_debug(1, "in png_set_invert_mono\n"); - if(png_ptr == NULL) return; - png_ptr->transformations |= PNG_INVERT_MONO; -} - -/* invert monochrome grayscale data */ -void /* PRIVATE */ -png_do_invert(png_row_infop row_info, png_bytep row) -{ - png_debug(1, "in png_do_invert\n"); - /* This test removed from libpng version 1.0.13 and 1.2.0: - * if (row_info->bit_depth == 1 && - */ -#if defined(PNG_USELESS_TESTS_SUPPORTED) - if (row == NULL || row_info == NULL) - return; -#endif - if (row_info->color_type == PNG_COLOR_TYPE_GRAY) - { - png_bytep rp = row; - png_uint_32 i; - png_uint_32 istop = row_info->rowbytes; - - for (i = 0; i < istop; i++) - { - *rp = (png_byte)(~(*rp)); - rp++; - } - } - else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && - row_info->bit_depth == 8) - { - png_bytep rp = row; - png_uint_32 i; - png_uint_32 istop = row_info->rowbytes; - - for (i = 0; i < istop; i+=2) - { - *rp = (png_byte)(~(*rp)); - rp+=2; - } - } - else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && - row_info->bit_depth == 16) - { - png_bytep rp = row; - png_uint_32 i; - png_uint_32 istop = row_info->rowbytes; - - for (i = 0; i < istop; i+=4) - { - *rp = (png_byte)(~(*rp)); - *(rp+1) = (png_byte)(~(*(rp+1))); - rp+=4; - } - } -} -#endif - -#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) -/* swaps byte order on 16 bit depth images */ -void /* PRIVATE */ -png_do_swap(png_row_infop row_info, png_bytep row) -{ - png_debug(1, "in png_do_swap\n"); - if ( -#if defined(PNG_USELESS_TESTS_SUPPORTED) - row != NULL && row_info != NULL && -#endif - row_info->bit_depth == 16) - { - png_bytep rp = row; - png_uint_32 i; - png_uint_32 istop= row_info->width * row_info->channels; - - for (i = 0; i < istop; i++, rp += 2) - { - png_byte t = *rp; - *rp = *(rp + 1); - *(rp + 1) = t; - } - } -} -#endif - -#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED) -static PNG_CONST png_byte onebppswaptable[256] = { - 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, - 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, - 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, - 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, - 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, - 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, - 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, - 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, - 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, - 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, - 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, - 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, - 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, - 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, - 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, - 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, - 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, - 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, - 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, - 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, - 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, - 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, - 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, - 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, - 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, - 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, - 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, - 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, - 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, - 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, - 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, - 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF -}; - -static PNG_CONST png_byte twobppswaptable[256] = { - 0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0, - 0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0, - 0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4, - 0x24, 0x64, 0xA4, 0xE4, 0x34, 0x74, 0xB4, 0xF4, - 0x08, 0x48, 0x88, 0xC8, 0x18, 0x58, 0x98, 0xD8, - 0x28, 0x68, 0xA8, 0xE8, 0x38, 0x78, 0xB8, 0xF8, - 0x0C, 0x4C, 0x8C, 0xCC, 0x1C, 0x5C, 0x9C, 0xDC, - 0x2C, 0x6C, 0xAC, 0xEC, 0x3C, 0x7C, 0xBC, 0xFC, - 0x01, 0x41, 0x81, 0xC1, 0x11, 0x51, 0x91, 0xD1, - 0x21, 0x61, 0xA1, 0xE1, 0x31, 0x71, 0xB1, 0xF1, - 0x05, 0x45, 0x85, 0xC5, 0x15, 0x55, 0x95, 0xD5, - 0x25, 0x65, 0xA5, 0xE5, 0x35, 0x75, 0xB5, 0xF5, - 0x09, 0x49, 0x89, 0xC9, 0x19, 0x59, 0x99, 0xD9, - 0x29, 0x69, 0xA9, 0xE9, 0x39, 0x79, 0xB9, 0xF9, - 0x0D, 0x4D, 0x8D, 0xCD, 0x1D, 0x5D, 0x9D, 0xDD, - 0x2D, 0x6D, 0xAD, 0xED, 0x3D, 0x7D, 0xBD, 0xFD, - 0x02, 0x42, 0x82, 0xC2, 0x12, 0x52, 0x92, 0xD2, - 0x22, 0x62, 0xA2, 0xE2, 0x32, 0x72, 0xB2, 0xF2, - 0x06, 0x46, 0x86, 0xC6, 0x16, 0x56, 0x96, 0xD6, - 0x26, 0x66, 0xA6, 0xE6, 0x36, 0x76, 0xB6, 0xF6, - 0x0A, 0x4A, 0x8A, 0xCA, 0x1A, 0x5A, 0x9A, 0xDA, - 0x2A, 0x6A, 0xAA, 0xEA, 0x3A, 0x7A, 0xBA, 0xFA, - 0x0E, 0x4E, 0x8E, 0xCE, 0x1E, 0x5E, 0x9E, 0xDE, - 0x2E, 0x6E, 0xAE, 0xEE, 0x3E, 0x7E, 0xBE, 0xFE, - 0x03, 0x43, 0x83, 0xC3, 0x13, 0x53, 0x93, 0xD3, - 0x23, 0x63, 0xA3, 0xE3, 0x33, 0x73, 0xB3, 0xF3, - 0x07, 0x47, 0x87, 0xC7, 0x17, 0x57, 0x97, 0xD7, - 0x27, 0x67, 0xA7, 0xE7, 0x37, 0x77, 0xB7, 0xF7, - 0x0B, 0x4B, 0x8B, 0xCB, 0x1B, 0x5B, 0x9B, 0xDB, - 0x2B, 0x6B, 0xAB, 0xEB, 0x3B, 0x7B, 0xBB, 0xFB, - 0x0F, 0x4F, 0x8F, 0xCF, 0x1F, 0x5F, 0x9F, 0xDF, - 0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF -}; - -static PNG_CONST png_byte fourbppswaptable[256] = { - 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, - 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0, - 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71, - 0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1, - 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72, - 0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2, - 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73, - 0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3, - 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74, - 0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4, - 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75, - 0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5, - 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76, - 0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6, - 0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77, - 0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7, - 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78, - 0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8, - 0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79, - 0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9, - 0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A, - 0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA, - 0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B, - 0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB, - 0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C, - 0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC, - 0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D, - 0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD, - 0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E, - 0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE, - 0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F, - 0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF -}; - -/* swaps pixel packing order within bytes */ -void /* PRIVATE */ -png_do_packswap(png_row_infop row_info, png_bytep row) -{ - png_debug(1, "in png_do_packswap\n"); - if ( -#if defined(PNG_USELESS_TESTS_SUPPORTED) - row != NULL && row_info != NULL && -#endif - row_info->bit_depth < 8) - { - png_bytep rp, end, table; - - end = row + row_info->rowbytes; - - if (row_info->bit_depth == 1) - table = (png_bytep)onebppswaptable; - else if (row_info->bit_depth == 2) - table = (png_bytep)twobppswaptable; - else if (row_info->bit_depth == 4) - table = (png_bytep)fourbppswaptable; - else - return; - - for (rp = row; rp < end; rp++) - *rp = table[*rp]; - } -} -#endif /* PNG_READ_PACKSWAP_SUPPORTED or PNG_WRITE_PACKSWAP_SUPPORTED */ - -#if defined(PNG_WRITE_FILLER_SUPPORTED) || \ - defined(PNG_READ_STRIP_ALPHA_SUPPORTED) -/* remove filler or alpha byte(s) */ -void /* PRIVATE */ -png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags) -{ - png_debug(1, "in png_do_strip_filler\n"); -#if defined(PNG_USELESS_TESTS_SUPPORTED) - if (row != NULL && row_info != NULL) -#endif - { - png_bytep sp=row; - png_bytep dp=row; - png_uint_32 row_width=row_info->width; - png_uint_32 i; - - if ((row_info->color_type == PNG_COLOR_TYPE_RGB || - (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA && - (flags & PNG_FLAG_STRIP_ALPHA))) && - row_info->channels == 4) - { - if (row_info->bit_depth == 8) - { - /* This converts from RGBX or RGBA to RGB */ - if (flags & PNG_FLAG_FILLER_AFTER) - { - dp+=3; sp+=4; - for (i = 1; i < row_width; i++) - { - *dp++ = *sp++; - *dp++ = *sp++; - *dp++ = *sp++; - sp++; - } - } - /* This converts from XRGB or ARGB to RGB */ - else - { - for (i = 0; i < row_width; i++) - { - sp++; - *dp++ = *sp++; - *dp++ = *sp++; - *dp++ = *sp++; - } - } - row_info->pixel_depth = 24; - row_info->rowbytes = row_width * 3; - } - else /* if (row_info->bit_depth == 16) */ - { - if (flags & PNG_FLAG_FILLER_AFTER) - { - /* This converts from RRGGBBXX or RRGGBBAA to RRGGBB */ - sp += 8; dp += 6; - for (i = 1; i < row_width; i++) - { - /* This could be (although png_memcpy is probably slower): - png_memcpy(dp, sp, 6); - sp += 8; - dp += 6; - */ - - *dp++ = *sp++; - *dp++ = *sp++; - *dp++ = *sp++; - *dp++ = *sp++; - *dp++ = *sp++; - *dp++ = *sp++; - sp += 2; - } - } - else - { - /* This converts from XXRRGGBB or AARRGGBB to RRGGBB */ - for (i = 0; i < row_width; i++) - { - /* This could be (although png_memcpy is probably slower): - png_memcpy(dp, sp, 6); - sp += 8; - dp += 6; - */ - - sp+=2; - *dp++ = *sp++; - *dp++ = *sp++; - *dp++ = *sp++; - *dp++ = *sp++; - *dp++ = *sp++; - *dp++ = *sp++; - } - } - row_info->pixel_depth = 48; - row_info->rowbytes = row_width * 6; - } - row_info->channels = 3; - } - else if ((row_info->color_type == PNG_COLOR_TYPE_GRAY || - (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && - (flags & PNG_FLAG_STRIP_ALPHA))) && - row_info->channels == 2) - { - if (row_info->bit_depth == 8) - { - /* This converts from GX or GA to G */ - if (flags & PNG_FLAG_FILLER_AFTER) - { - for (i = 0; i < row_width; i++) - { - *dp++ = *sp++; - sp++; - } - } - /* This converts from XG or AG to G */ - else - { - for (i = 0; i < row_width; i++) - { - sp++; - *dp++ = *sp++; - } - } - row_info->pixel_depth = 8; - row_info->rowbytes = row_width; - } - else /* if (row_info->bit_depth == 16) */ - { - if (flags & PNG_FLAG_FILLER_AFTER) - { - /* This converts from GGXX or GGAA to GG */ - sp += 4; dp += 2; - for (i = 1; i < row_width; i++) - { - *dp++ = *sp++; - *dp++ = *sp++; - sp += 2; - } - } - else - { - /* This converts from XXGG or AAGG to GG */ - for (i = 0; i < row_width; i++) - { - sp += 2; - *dp++ = *sp++; - *dp++ = *sp++; - } - } - row_info->pixel_depth = 16; - row_info->rowbytes = row_width * 2; - } - row_info->channels = 1; - } - if (flags & PNG_FLAG_STRIP_ALPHA) - row_info->color_type &= ~PNG_COLOR_MASK_ALPHA; - } -} -#endif - -#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) -/* swaps red and blue bytes within a pixel */ -void /* PRIVATE */ -png_do_bgr(png_row_infop row_info, png_bytep row) -{ - png_debug(1, "in png_do_bgr\n"); - if ( -#if defined(PNG_USELESS_TESTS_SUPPORTED) - row != NULL && row_info != NULL && -#endif - (row_info->color_type & PNG_COLOR_MASK_COLOR)) - { - png_uint_32 row_width = row_info->width; - if (row_info->bit_depth == 8) - { - if (row_info->color_type == PNG_COLOR_TYPE_RGB) - { - png_bytep rp; - png_uint_32 i; - - for (i = 0, rp = row; i < row_width; i++, rp += 3) - { - png_byte save = *rp; - *rp = *(rp + 2); - *(rp + 2) = save; - } - } - else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - { - png_bytep rp; - png_uint_32 i; - - for (i = 0, rp = row; i < row_width; i++, rp += 4) - { - png_byte save = *rp; - *rp = *(rp + 2); - *(rp + 2) = save; - } - } - } - else if (row_info->bit_depth == 16) - { - if (row_info->color_type == PNG_COLOR_TYPE_RGB) - { - png_bytep rp; - png_uint_32 i; - - for (i = 0, rp = row; i < row_width; i++, rp += 6) - { - png_byte save = *rp; - *rp = *(rp + 4); - *(rp + 4) = save; - save = *(rp + 1); - *(rp + 1) = *(rp + 5); - *(rp + 5) = save; - } - } - else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - { - png_bytep rp; - png_uint_32 i; - - for (i = 0, rp = row; i < row_width; i++, rp += 8) - { - png_byte save = *rp; - *rp = *(rp + 4); - *(rp + 4) = save; - save = *(rp + 1); - *(rp + 1) = *(rp + 5); - *(rp + 5) = save; - } - } - } - } -} -#endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */ - -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_LEGACY_SUPPORTED) -void PNGAPI -png_set_user_transform_info(png_structp png_ptr, png_voidp - user_transform_ptr, int user_transform_depth, int user_transform_channels) -{ - png_debug(1, "in png_set_user_transform_info\n"); - if(png_ptr == NULL) return; -#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) - png_ptr->user_transform_ptr = user_transform_ptr; - png_ptr->user_transform_depth = (png_byte)user_transform_depth; - png_ptr->user_transform_channels = (png_byte)user_transform_channels; -#else - if(user_transform_ptr || user_transform_depth || user_transform_channels) - png_warning(png_ptr, - "This version of libpng does not support user transform info"); -#endif -} -#endif - -/* This function returns a pointer to the user_transform_ptr associated with - * the user transform functions. The application should free any memory - * associated with this pointer before png_write_destroy and png_read_destroy - * are called. - */ -png_voidp PNGAPI -png_get_user_transform_ptr(png_structp png_ptr) -{ -#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) - if (png_ptr == NULL) return (NULL); - return ((png_voidp)png_ptr->user_transform_ptr); -#else - return (NULL); -#endif -} -#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/rosapps/lib/libpng/pngvcrd.c b/rosapps/lib/libpng/pngvcrd.c deleted file mode 100644 index ce4233efe7e..00000000000 --- a/rosapps/lib/libpng/pngvcrd.c +++ /dev/null @@ -1 +0,0 @@ -/* pnggvrd.c was removed from libpng-1.2.20. */ diff --git a/rosapps/lib/libpng/pngwio.c b/rosapps/lib/libpng/pngwio.c deleted file mode 100644 index 371a4fad624..00000000000 --- a/rosapps/lib/libpng/pngwio.c +++ /dev/null @@ -1,234 +0,0 @@ - -/* pngwio.c - functions for data output - * - * Last changed in libpng 1.2.13 November 13, 2006 - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2006 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This file provides a location for all output. Users who need - * special handling are expected to write functions that have the same - * arguments as these and perform similar functions, but that possibly - * use different output methods. Note that you shouldn't change these - * functions, but rather write replacement functions and then change - * them at run time with png_set_write_fn(...). - */ - -#define PNG_INTERNAL -#include "png.h" -#ifdef PNG_WRITE_SUPPORTED - -/* Write the data to whatever output you are using. The default routine - writes to a file pointer. Note that this routine sometimes gets called - with very small lengths, so you should implement some kind of simple - buffering if you are using unbuffered writes. This should never be asked - to write more than 64K on a 16 bit machine. */ - -void /* PRIVATE */ -png_write_data(png_structp png_ptr, png_bytep data, png_size_t length) -{ - if (png_ptr->write_data_fn != NULL ) - (*(png_ptr->write_data_fn))(png_ptr, data, length); - else - png_error(png_ptr, "Call to NULL write function"); -} - -#if !defined(PNG_NO_STDIO) -/* This is the function that does the actual writing of data. If you are - not writing to a standard C stream, you should create a replacement - write_data function and use it at run time with png_set_write_fn(), rather - than changing the library. */ -#ifndef USE_FAR_KEYWORD -void PNGAPI -png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) -{ - png_uint_32 check; - - if(png_ptr == NULL) return; -#if defined(_WIN32_WCE) - if ( !WriteFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) ) - check = 0; -#else - check = fwrite(data, 1, length, (png_FILE_p)(png_ptr->io_ptr)); -#endif - if (check != length) - png_error(png_ptr, "Write Error"); -} -#else -/* this is the model-independent version. Since the standard I/O library - can't handle far buffers in the medium and small models, we have to copy - the data. -*/ - -#define NEAR_BUF_SIZE 1024 -#define MIN(a,b) (a <= b ? a : b) - -void PNGAPI -png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) -{ - png_uint_32 check; - png_byte *near_data; /* Needs to be "png_byte *" instead of "png_bytep" */ - png_FILE_p io_ptr; - - if(png_ptr == NULL) return; - /* Check if data really is near. If so, use usual code. */ - near_data = (png_byte *)CVT_PTR_NOCHECK(data); - io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); - if ((png_bytep)near_data == data) - { -#if defined(_WIN32_WCE) - if ( !WriteFile(io_ptr, near_data, length, &check, NULL) ) - check = 0; -#else - check = fwrite(near_data, 1, length, io_ptr); -#endif - } - else - { - png_byte buf[NEAR_BUF_SIZE]; - png_size_t written, remaining, err; - check = 0; - remaining = length; - do - { - written = MIN(NEAR_BUF_SIZE, remaining); - png_memcpy(buf, data, written); /* copy far buffer to near buffer */ -#if defined(_WIN32_WCE) - if ( !WriteFile(io_ptr, buf, written, &err, NULL) ) - err = 0; -#else - err = fwrite(buf, 1, written, io_ptr); -#endif - if (err != written) - break; - else - check += err; - data += written; - remaining -= written; - } - while (remaining != 0); - } - if (check != length) - png_error(png_ptr, "Write Error"); -} - -#endif -#endif - -/* This function is called to output any data pending writing (normally - to disk). After png_flush is called, there should be no data pending - writing in any buffers. */ -#if defined(PNG_WRITE_FLUSH_SUPPORTED) -void /* PRIVATE */ -png_flush(png_structp png_ptr) -{ - if (png_ptr->output_flush_fn != NULL) - (*(png_ptr->output_flush_fn))(png_ptr); -} - -#if !defined(PNG_NO_STDIO) -void PNGAPI -png_default_flush(png_structp png_ptr) -{ -#if !defined(_WIN32_WCE) - png_FILE_p io_ptr; -#endif - if(png_ptr == NULL) return; -#if !defined(_WIN32_WCE) - io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr)); - if (io_ptr != NULL) - fflush(io_ptr); -#endif -} -#endif -#endif - -/* This function allows the application to supply new output functions for - libpng if standard C streams aren't being used. - - This function takes as its arguments: - png_ptr - pointer to a png output data structure - io_ptr - pointer to user supplied structure containing info about - the output functions. May be NULL. - write_data_fn - pointer to a new output function that takes as its - arguments a pointer to a png_struct, a pointer to - data to be written, and a 32-bit unsigned int that is - the number of bytes to be written. The new write - function should call png_error(png_ptr, "Error msg") - to exit and output any fatal error messages. - flush_data_fn - pointer to a new flush function that takes as its - arguments a pointer to a png_struct. After a call to - the flush function, there should be no data in any buffers - or pending transmission. If the output method doesn't do - any buffering of ouput, a function prototype must still be - supplied although it doesn't have to do anything. If - PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile - time, output_flush_fn will be ignored, although it must be - supplied for compatibility. */ -void PNGAPI -png_set_write_fn(png_structp png_ptr, png_voidp io_ptr, - png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn) -{ - if(png_ptr == NULL) return; - png_ptr->io_ptr = io_ptr; - -#if !defined(PNG_NO_STDIO) - if (write_data_fn != NULL) - png_ptr->write_data_fn = write_data_fn; - else - png_ptr->write_data_fn = png_default_write_data; -#else - png_ptr->write_data_fn = write_data_fn; -#endif - -#if defined(PNG_WRITE_FLUSH_SUPPORTED) -#if !defined(PNG_NO_STDIO) - if (output_flush_fn != NULL) - png_ptr->output_flush_fn = output_flush_fn; - else - png_ptr->output_flush_fn = png_default_flush; -#else - png_ptr->output_flush_fn = output_flush_fn; -#endif -#endif /* PNG_WRITE_FLUSH_SUPPORTED */ - - /* It is an error to read while writing a png file */ - if (png_ptr->read_data_fn != NULL) - { - png_ptr->read_data_fn = NULL; - png_warning(png_ptr, - "Attempted to set both read_data_fn and write_data_fn in"); - png_warning(png_ptr, - "the same structure. Resetting read_data_fn to NULL."); - } -} - -#if defined(USE_FAR_KEYWORD) -#if defined(_MSC_VER) -void *png_far_to_near(png_structp png_ptr,png_voidp ptr, int check) -{ - void *near_ptr; - void FAR *far_ptr; - FP_OFF(near_ptr) = FP_OFF(ptr); - far_ptr = (void FAR *)near_ptr; - if(check != 0) - if(FP_SEG(ptr) != FP_SEG(far_ptr)) - png_error(png_ptr,"segment lost in conversion"); - return(near_ptr); -} -# else -void *png_far_to_near(png_structp png_ptr,png_voidp ptr, int check) -{ - void *near_ptr; - void FAR *far_ptr; - near_ptr = (void FAR *)ptr; - far_ptr = (void FAR *)near_ptr; - if(check != 0) - if(far_ptr != ptr) - png_error(png_ptr,"segment lost in conversion"); - return(near_ptr); -} -# endif -# endif -#endif /* PNG_WRITE_SUPPORTED */ diff --git a/rosapps/lib/libpng/pngwrite.c b/rosapps/lib/libpng/pngwrite.c deleted file mode 100644 index b1f6a593aae..00000000000 --- a/rosapps/lib/libpng/pngwrite.c +++ /dev/null @@ -1,1516 +0,0 @@ - -/* pngwrite.c - general routines to write a PNG file - * - * Last changed in libpng 1.2.24 December 14, 2007 - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2007 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - */ - -/* get internal access to png.h */ -#define PNG_INTERNAL -#include "png.h" -#ifdef PNG_WRITE_SUPPORTED - -/* Writes all the PNG information. This is the suggested way to use the - * library. If you have a new chunk to add, make a function to write it, - * and put it in the correct location here. If you want the chunk written - * after the image data, put it in png_write_end(). I strongly encourage - * you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing - * the chunk, as that will keep the code from breaking if you want to just - * write a plain PNG file. If you have long comments, I suggest writing - * them in png_write_end(), and compressing them. - */ -void PNGAPI -png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr) -{ - png_debug(1, "in png_write_info_before_PLTE\n"); - if (png_ptr == NULL || info_ptr == NULL) - return; - if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE)) - { - png_write_sig(png_ptr); /* write PNG signature */ -#if defined(PNG_MNG_FEATURES_SUPPORTED) - if((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)&&(png_ptr->mng_features_permitted)) - { - png_warning(png_ptr,"MNG features are not allowed in a PNG datastream"); - png_ptr->mng_features_permitted=0; - } -#endif - /* write IHDR information. */ - png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height, - info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type, - info_ptr->filter_type, -#if defined(PNG_WRITE_INTERLACING_SUPPORTED) - info_ptr->interlace_type); -#else - 0); -#endif - /* the rest of these check to see if the valid field has the appropriate - flag set, and if it does, writes the chunk. */ -#if defined(PNG_WRITE_gAMA_SUPPORTED) - if (info_ptr->valid & PNG_INFO_gAMA) - { -# ifdef PNG_FLOATING_POINT_SUPPORTED - png_write_gAMA(png_ptr, info_ptr->gamma); -#else -#ifdef PNG_FIXED_POINT_SUPPORTED - png_write_gAMA_fixed(png_ptr, info_ptr->int_gamma); -# endif -#endif - } -#endif -#if defined(PNG_WRITE_sRGB_SUPPORTED) - if (info_ptr->valid & PNG_INFO_sRGB) - png_write_sRGB(png_ptr, (int)info_ptr->srgb_intent); -#endif -#if defined(PNG_WRITE_iCCP_SUPPORTED) - if (info_ptr->valid & PNG_INFO_iCCP) - png_write_iCCP(png_ptr, info_ptr->iccp_name, PNG_COMPRESSION_TYPE_BASE, - info_ptr->iccp_profile, (int)info_ptr->iccp_proflen); -#endif -#if defined(PNG_WRITE_sBIT_SUPPORTED) - if (info_ptr->valid & PNG_INFO_sBIT) - png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type); -#endif -#if defined(PNG_WRITE_cHRM_SUPPORTED) - if (info_ptr->valid & PNG_INFO_cHRM) - { -#ifdef PNG_FLOATING_POINT_SUPPORTED - png_write_cHRM(png_ptr, - info_ptr->x_white, info_ptr->y_white, - info_ptr->x_red, info_ptr->y_red, - info_ptr->x_green, info_ptr->y_green, - info_ptr->x_blue, info_ptr->y_blue); -#else -# ifdef PNG_FIXED_POINT_SUPPORTED - png_write_cHRM_fixed(png_ptr, - info_ptr->int_x_white, info_ptr->int_y_white, - info_ptr->int_x_red, info_ptr->int_y_red, - info_ptr->int_x_green, info_ptr->int_y_green, - info_ptr->int_x_blue, info_ptr->int_y_blue); -# endif -#endif - } -#endif -#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) - if (info_ptr->unknown_chunks_num) - { - png_unknown_chunk *up; - - png_debug(5, "writing extra chunks\n"); - - for (up = info_ptr->unknown_chunks; - up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; - up++) - { - int keep=png_handle_as_unknown(png_ptr, up->name); - if (keep != PNG_HANDLE_CHUNK_NEVER && - up->location && !(up->location & PNG_HAVE_PLTE) && - !(up->location & PNG_HAVE_IDAT) && - ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || - (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) - { - png_write_chunk(png_ptr, up->name, up->data, up->size); - } - } - } -#endif - png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE; - } -} - -void PNGAPI -png_write_info(png_structp png_ptr, png_infop info_ptr) -{ -#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) - int i; -#endif - - png_debug(1, "in png_write_info\n"); - - if (png_ptr == NULL || info_ptr == NULL) - return; - - png_write_info_before_PLTE(png_ptr, info_ptr); - - if (info_ptr->valid & PNG_INFO_PLTE) - png_write_PLTE(png_ptr, info_ptr->palette, - (png_uint_32)info_ptr->num_palette); - else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - png_error(png_ptr, "Valid palette required for paletted images"); - -#if defined(PNG_WRITE_tRNS_SUPPORTED) - if (info_ptr->valid & PNG_INFO_tRNS) - { -#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) - /* invert the alpha channel (in tRNS) */ - if ((png_ptr->transformations & PNG_INVERT_ALPHA) && - info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - { - int j; - for (j=0; j<(int)info_ptr->num_trans; j++) - info_ptr->trans[j] = (png_byte)(255 - info_ptr->trans[j]); - } -#endif - png_write_tRNS(png_ptr, info_ptr->trans, &(info_ptr->trans_values), - info_ptr->num_trans, info_ptr->color_type); - } -#endif -#if defined(PNG_WRITE_bKGD_SUPPORTED) - if (info_ptr->valid & PNG_INFO_bKGD) - png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type); -#endif -#if defined(PNG_WRITE_hIST_SUPPORTED) - if (info_ptr->valid & PNG_INFO_hIST) - png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette); -#endif -#if defined(PNG_WRITE_oFFs_SUPPORTED) - if (info_ptr->valid & PNG_INFO_oFFs) - png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset, - info_ptr->offset_unit_type); -#endif -#if defined(PNG_WRITE_pCAL_SUPPORTED) - if (info_ptr->valid & PNG_INFO_pCAL) - png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0, - info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams, - info_ptr->pcal_units, info_ptr->pcal_params); -#endif -#if defined(PNG_WRITE_sCAL_SUPPORTED) - if (info_ptr->valid & PNG_INFO_sCAL) -#if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO) - png_write_sCAL(png_ptr, (int)info_ptr->scal_unit, - info_ptr->scal_pixel_width, info_ptr->scal_pixel_height); -#else -#ifdef PNG_FIXED_POINT_SUPPORTED - png_write_sCAL_s(png_ptr, (int)info_ptr->scal_unit, - info_ptr->scal_s_width, info_ptr->scal_s_height); -#else - png_warning(png_ptr, - "png_write_sCAL not supported; sCAL chunk not written."); -#endif -#endif -#endif -#if defined(PNG_WRITE_pHYs_SUPPORTED) - if (info_ptr->valid & PNG_INFO_pHYs) - png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit, - info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type); -#endif -#if defined(PNG_WRITE_tIME_SUPPORTED) - if (info_ptr->valid & PNG_INFO_tIME) - { - png_write_tIME(png_ptr, &(info_ptr->mod_time)); - png_ptr->mode |= PNG_WROTE_tIME; - } -#endif -#if defined(PNG_WRITE_sPLT_SUPPORTED) - if (info_ptr->valid & PNG_INFO_sPLT) - for (i = 0; i < (int)info_ptr->splt_palettes_num; i++) - png_write_sPLT(png_ptr, info_ptr->splt_palettes + i); -#endif -#if defined(PNG_WRITE_TEXT_SUPPORTED) - /* Check to see if we need to write text chunks */ - for (i = 0; i < info_ptr->num_text; i++) - { - png_debug2(2, "Writing header text chunk %d, type %d\n", i, - info_ptr->text[i].compression); - /* an internationalized chunk? */ - if (info_ptr->text[i].compression > 0) - { -#if defined(PNG_WRITE_iTXt_SUPPORTED) - /* write international chunk */ - png_write_iTXt(png_ptr, - info_ptr->text[i].compression, - info_ptr->text[i].key, - info_ptr->text[i].lang, - info_ptr->text[i].lang_key, - info_ptr->text[i].text); -#else - png_warning(png_ptr, "Unable to write international text"); -#endif - /* Mark this chunk as written */ - info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; - } - /* If we want a compressed text chunk */ - else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_zTXt) - { -#if defined(PNG_WRITE_zTXt_SUPPORTED) - /* write compressed chunk */ - png_write_zTXt(png_ptr, info_ptr->text[i].key, - info_ptr->text[i].text, 0, - info_ptr->text[i].compression); -#else - png_warning(png_ptr, "Unable to write compressed text"); -#endif - /* Mark this chunk as written */ - info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; - } - else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) - { -#if defined(PNG_WRITE_tEXt_SUPPORTED) - /* write uncompressed chunk */ - png_write_tEXt(png_ptr, info_ptr->text[i].key, - info_ptr->text[i].text, - 0); -#else - png_warning(png_ptr, "Unable to write uncompressed text"); -#endif - /* Mark this chunk as written */ - info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; - } - } -#endif -#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) - if (info_ptr->unknown_chunks_num) - { - png_unknown_chunk *up; - - png_debug(5, "writing extra chunks\n"); - - for (up = info_ptr->unknown_chunks; - up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; - up++) - { - int keep=png_handle_as_unknown(png_ptr, up->name); - if (keep != PNG_HANDLE_CHUNK_NEVER && - up->location && (up->location & PNG_HAVE_PLTE) && - !(up->location & PNG_HAVE_IDAT) && - ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || - (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) - { - png_write_chunk(png_ptr, up->name, up->data, up->size); - } - } - } -#endif -} - -/* Writes the end of the PNG file. If you don't want to write comments or - * time information, you can pass NULL for info. If you already wrote these - * in png_write_info(), do not write them again here. If you have long - * comments, I suggest writing them here, and compressing them. - */ -void PNGAPI -png_write_end(png_structp png_ptr, png_infop info_ptr) -{ - png_debug(1, "in png_write_end\n"); - if (png_ptr == NULL) - return; - if (!(png_ptr->mode & PNG_HAVE_IDAT)) - png_error(png_ptr, "No IDATs written into file"); - - /* see if user wants us to write information chunks */ - if (info_ptr != NULL) - { -#if defined(PNG_WRITE_TEXT_SUPPORTED) - int i; /* local index variable */ -#endif -#if defined(PNG_WRITE_tIME_SUPPORTED) - /* check to see if user has supplied a time chunk */ - if ((info_ptr->valid & PNG_INFO_tIME) && - !(png_ptr->mode & PNG_WROTE_tIME)) - png_write_tIME(png_ptr, &(info_ptr->mod_time)); -#endif -#if defined(PNG_WRITE_TEXT_SUPPORTED) - /* loop through comment chunks */ - for (i = 0; i < info_ptr->num_text; i++) - { - png_debug2(2, "Writing trailer text chunk %d, type %d\n", i, - info_ptr->text[i].compression); - /* an internationalized chunk? */ - if (info_ptr->text[i].compression > 0) - { -#if defined(PNG_WRITE_iTXt_SUPPORTED) - /* write international chunk */ - png_write_iTXt(png_ptr, - info_ptr->text[i].compression, - info_ptr->text[i].key, - info_ptr->text[i].lang, - info_ptr->text[i].lang_key, - info_ptr->text[i].text); -#else - png_warning(png_ptr, "Unable to write international text"); -#endif - /* Mark this chunk as written */ - info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; - } - else if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt) - { -#if defined(PNG_WRITE_zTXt_SUPPORTED) - /* write compressed chunk */ - png_write_zTXt(png_ptr, info_ptr->text[i].key, - info_ptr->text[i].text, 0, - info_ptr->text[i].compression); -#else - png_warning(png_ptr, "Unable to write compressed text"); -#endif - /* Mark this chunk as written */ - info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; - } - else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) - { -#if defined(PNG_WRITE_tEXt_SUPPORTED) - /* write uncompressed chunk */ - png_write_tEXt(png_ptr, info_ptr->text[i].key, - info_ptr->text[i].text, 0); -#else - png_warning(png_ptr, "Unable to write uncompressed text"); -#endif - - /* Mark this chunk as written */ - info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; - } - } -#endif -#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) - if (info_ptr->unknown_chunks_num) - { - png_unknown_chunk *up; - - png_debug(5, "writing extra chunks\n"); - - for (up = info_ptr->unknown_chunks; - up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; - up++) - { - int keep=png_handle_as_unknown(png_ptr, up->name); - if (keep != PNG_HANDLE_CHUNK_NEVER && - up->location && (up->location & PNG_AFTER_IDAT) && - ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || - (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) - { - png_write_chunk(png_ptr, up->name, up->data, up->size); - } - } - } -#endif - } - - png_ptr->mode |= PNG_AFTER_IDAT; - - /* write end of PNG file */ - png_write_IEND(png_ptr); -} - -#if defined(PNG_WRITE_tIME_SUPPORTED) -#if !defined(_WIN32_WCE) -/* "time.h" functions are not supported on WindowsCE */ -void PNGAPI -png_convert_from_struct_tm(png_timep ptime, struct tm FAR * ttime) -{ - png_debug(1, "in png_convert_from_struct_tm\n"); - ptime->year = (png_uint_16)(1900 + ttime->tm_year); - ptime->month = (png_byte)(ttime->tm_mon + 1); - ptime->day = (png_byte)ttime->tm_mday; - ptime->hour = (png_byte)ttime->tm_hour; - ptime->minute = (png_byte)ttime->tm_min; - ptime->second = (png_byte)ttime->tm_sec; -} - -void PNGAPI -png_convert_from_time_t(png_timep ptime, time_t ttime) -{ - struct tm *tbuf; - - png_debug(1, "in png_convert_from_time_t\n"); - tbuf = gmtime(&ttime); - png_convert_from_struct_tm(ptime, tbuf); -} -#endif -#endif - -/* Initialize png_ptr structure, and allocate any memory needed */ -png_structp PNGAPI -png_create_write_struct(png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn) -{ -#ifdef PNG_USER_MEM_SUPPORTED - return (png_create_write_struct_2(user_png_ver, error_ptr, error_fn, - warn_fn, png_voidp_NULL, png_malloc_ptr_NULL, png_free_ptr_NULL)); -} - -/* Alternate initialize png_ptr structure, and allocate any memory needed */ -png_structp PNGAPI -png_create_write_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, - png_malloc_ptr malloc_fn, png_free_ptr free_fn) -{ -#endif /* PNG_USER_MEM_SUPPORTED */ - png_structp png_ptr; -#ifdef PNG_SETJMP_SUPPORTED -#ifdef USE_FAR_KEYWORD - jmp_buf jmpbuf; -#endif -#endif - int i; - png_debug(1, "in png_create_write_struct\n"); -#ifdef PNG_USER_MEM_SUPPORTED - png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG, - (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr); -#else - png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); -#endif /* PNG_USER_MEM_SUPPORTED */ - if (png_ptr == NULL) - return (NULL); - - /* added at libpng-1.2.6 */ -#ifdef PNG_SET_USER_LIMITS_SUPPORTED - png_ptr->user_width_max=PNG_USER_WIDTH_MAX; - png_ptr->user_height_max=PNG_USER_HEIGHT_MAX; -#endif - -#ifdef PNG_SETJMP_SUPPORTED -#ifdef USE_FAR_KEYWORD - if (setjmp(jmpbuf)) -#else - if (setjmp(png_ptr->jmpbuf)) -#endif - { - png_free(png_ptr, png_ptr->zbuf); - png_ptr->zbuf=NULL; - png_destroy_struct(png_ptr); - return (NULL); - } -#ifdef USE_FAR_KEYWORD - png_memcpy(png_ptr->jmpbuf,jmpbuf,png_sizeof(jmp_buf)); -#endif -#endif - -#ifdef PNG_USER_MEM_SUPPORTED - png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn); -#endif /* PNG_USER_MEM_SUPPORTED */ - png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn); - - i=0; - do - { - if(user_png_ver[i] != png_libpng_ver[i]) - png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; - } while (png_libpng_ver[i++]); - - if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) - { - /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so - * we must recompile any applications that use any older library version. - * For versions after libpng 1.0, we will be compatible, so we need - * only check the first digit. - */ - if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] || - (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) || - (user_png_ver[0] == '0' && user_png_ver[2] < '9')) - { -#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) - char msg[80]; - if (user_png_ver) - { - png_snprintf(msg, 80, - "Application was compiled with png.h from libpng-%.20s", - user_png_ver); - png_warning(png_ptr, msg); - } - png_snprintf(msg, 80, - "Application is running with png.c from libpng-%.20s", - png_libpng_ver); - png_warning(png_ptr, msg); -#endif -#ifdef PNG_ERROR_NUMBERS_SUPPORTED - png_ptr->flags=0; -#endif - png_error(png_ptr, - "Incompatible libpng version in application and library"); - } - } - - /* initialize zbuf - compression buffer */ - png_ptr->zbuf_size = PNG_ZBUF_SIZE; - png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, - (png_uint_32)png_ptr->zbuf_size); - - png_set_write_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL, - png_flush_ptr_NULL); - -#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT, - 1, png_doublep_NULL, png_doublep_NULL); -#endif - -#ifdef PNG_SETJMP_SUPPORTED -/* Applications that neglect to set up their own setjmp() and then encounter - a png_error() will longjmp here. Since the jmpbuf is then meaningless we - abort instead of returning. */ -#ifdef USE_FAR_KEYWORD - if (setjmp(jmpbuf)) - PNG_ABORT(); - png_memcpy(png_ptr->jmpbuf,jmpbuf,png_sizeof(jmp_buf)); -#else - if (setjmp(png_ptr->jmpbuf)) - PNG_ABORT(); -#endif -#endif - return (png_ptr); -} - -/* Initialize png_ptr structure, and allocate any memory needed */ -#if defined(PNG_1_0_X) || defined(PNG_1_2_X) -/* Deprecated. */ -#undef png_write_init -void PNGAPI -png_write_init(png_structp png_ptr) -{ - /* We only come here via pre-1.0.7-compiled applications */ - png_write_init_2(png_ptr, "1.0.6 or earlier", 0, 0); -} - -void PNGAPI -png_write_init_2(png_structp png_ptr, png_const_charp user_png_ver, - png_size_t png_struct_size, png_size_t png_info_size) -{ - /* We only come here via pre-1.0.12-compiled applications */ - if(png_ptr == NULL) return; -#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) - if(png_sizeof(png_struct) > png_struct_size || - png_sizeof(png_info) > png_info_size) - { - char msg[80]; - png_ptr->warning_fn=NULL; - if (user_png_ver) - { - png_snprintf(msg, 80, - "Application was compiled with png.h from libpng-%.20s", - user_png_ver); - png_warning(png_ptr, msg); - } - png_snprintf(msg, 80, - "Application is running with png.c from libpng-%.20s", - png_libpng_ver); - png_warning(png_ptr, msg); - } -#endif - if(png_sizeof(png_struct) > png_struct_size) - { - png_ptr->error_fn=NULL; -#ifdef PNG_ERROR_NUMBERS_SUPPORTED - png_ptr->flags=0; -#endif - png_error(png_ptr, - "The png struct allocated by the application for writing is too small."); - } - if(png_sizeof(png_info) > png_info_size) - { - png_ptr->error_fn=NULL; -#ifdef PNG_ERROR_NUMBERS_SUPPORTED - png_ptr->flags=0; -#endif - png_error(png_ptr, - "The info struct allocated by the application for writing is too small."); - } - png_write_init_3(&png_ptr, user_png_ver, png_struct_size); -} -#endif /* PNG_1_0_X || PNG_1_2_X */ - - -void PNGAPI -png_write_init_3(png_structpp ptr_ptr, png_const_charp user_png_ver, - png_size_t png_struct_size) -{ - png_structp png_ptr=*ptr_ptr; -#ifdef PNG_SETJMP_SUPPORTED - jmp_buf tmp_jmp; /* to save current jump buffer */ -#endif - - int i = 0; - - if (png_ptr == NULL) - return; - - do - { - if (user_png_ver[i] != png_libpng_ver[i]) - { -#ifdef PNG_LEGACY_SUPPORTED - png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; -#else - png_ptr->warning_fn=NULL; - png_warning(png_ptr, - "Application uses deprecated png_write_init() and should be recompiled."); - break; -#endif - } - } while (png_libpng_ver[i++]); - - png_debug(1, "in png_write_init_3\n"); - -#ifdef PNG_SETJMP_SUPPORTED - /* save jump buffer and error functions */ - png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof (jmp_buf)); -#endif - - if (png_sizeof(png_struct) > png_struct_size) - { - png_destroy_struct(png_ptr); - png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); - *ptr_ptr = png_ptr; - } - - /* reset all variables to 0 */ - png_memset(png_ptr, 0, png_sizeof (png_struct)); - - /* added at libpng-1.2.6 */ -#ifdef PNG_SET_USER_LIMITS_SUPPORTED - png_ptr->user_width_max=PNG_USER_WIDTH_MAX; - png_ptr->user_height_max=PNG_USER_HEIGHT_MAX; -#endif - -#ifdef PNG_SETJMP_SUPPORTED - /* restore jump buffer */ - png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof (jmp_buf)); -#endif - - png_set_write_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL, - png_flush_ptr_NULL); - - /* initialize zbuf - compression buffer */ - png_ptr->zbuf_size = PNG_ZBUF_SIZE; - png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, - (png_uint_32)png_ptr->zbuf_size); - -#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT, - 1, png_doublep_NULL, png_doublep_NULL); -#endif -} - -/* Write a few rows of image data. If the image is interlaced, - * either you will have to write the 7 sub images, or, if you - * have called png_set_interlace_handling(), you will have to - * "write" the image seven times. - */ -void PNGAPI -png_write_rows(png_structp png_ptr, png_bytepp row, - png_uint_32 num_rows) -{ - png_uint_32 i; /* row counter */ - png_bytepp rp; /* row pointer */ - - png_debug(1, "in png_write_rows\n"); - - if (png_ptr == NULL) - return; - - /* loop through the rows */ - for (i = 0, rp = row; i < num_rows; i++, rp++) - { - png_write_row(png_ptr, *rp); - } -} - -/* Write the image. You only need to call this function once, even - * if you are writing an interlaced image. - */ -void PNGAPI -png_write_image(png_structp png_ptr, png_bytepp image) -{ - png_uint_32 i; /* row index */ - int pass, num_pass; /* pass variables */ - png_bytepp rp; /* points to current row */ - - if (png_ptr == NULL) - return; - - png_debug(1, "in png_write_image\n"); -#if defined(PNG_WRITE_INTERLACING_SUPPORTED) - /* intialize interlace handling. If image is not interlaced, - this will set pass to 1 */ - num_pass = png_set_interlace_handling(png_ptr); -#else - num_pass = 1; -#endif - /* loop through passes */ - for (pass = 0; pass < num_pass; pass++) - { - /* loop through image */ - for (i = 0, rp = image; i < png_ptr->height; i++, rp++) - { - png_write_row(png_ptr, *rp); - } - } -} - -/* called by user to write a row of image data */ -void PNGAPI -png_write_row(png_structp png_ptr, png_bytep row) -{ - if (png_ptr == NULL) - return; - png_debug2(1, "in png_write_row (row %ld, pass %d)\n", - png_ptr->row_number, png_ptr->pass); - - /* initialize transformations and other stuff if first time */ - if (png_ptr->row_number == 0 && png_ptr->pass == 0) - { - /* make sure we wrote the header info */ - if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE)) - png_error(png_ptr, - "png_write_info was never called before png_write_row."); - - /* check for transforms that have been set but were defined out */ -#if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED) - if (png_ptr->transformations & PNG_INVERT_MONO) - png_warning(png_ptr, "PNG_WRITE_INVERT_SUPPORTED is not defined."); -#endif -#if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED) - if (png_ptr->transformations & PNG_FILLER) - png_warning(png_ptr, "PNG_WRITE_FILLER_SUPPORTED is not defined."); -#endif -#if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && defined(PNG_READ_PACKSWAP_SUPPORTED) - if (png_ptr->transformations & PNG_PACKSWAP) - png_warning(png_ptr, "PNG_WRITE_PACKSWAP_SUPPORTED is not defined."); -#endif -#if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED) - if (png_ptr->transformations & PNG_PACK) - png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined."); -#endif -#if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED) - if (png_ptr->transformations & PNG_SHIFT) - png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined."); -#endif -#if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED) - if (png_ptr->transformations & PNG_BGR) - png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined."); -#endif -#if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED) - if (png_ptr->transformations & PNG_SWAP_BYTES) - png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined."); -#endif - - png_write_start_row(png_ptr); - } - -#if defined(PNG_WRITE_INTERLACING_SUPPORTED) - /* if interlaced and not interested in row, return */ - if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) - { - switch (png_ptr->pass) - { - case 0: - if (png_ptr->row_number & 0x07) - { - png_write_finish_row(png_ptr); - return; - } - break; - case 1: - if ((png_ptr->row_number & 0x07) || png_ptr->width < 5) - { - png_write_finish_row(png_ptr); - return; - } - break; - case 2: - if ((png_ptr->row_number & 0x07) != 4) - { - png_write_finish_row(png_ptr); - return; - } - break; - case 3: - if ((png_ptr->row_number & 0x03) || png_ptr->width < 3) - { - png_write_finish_row(png_ptr); - return; - } - break; - case 4: - if ((png_ptr->row_number & 0x03) != 2) - { - png_write_finish_row(png_ptr); - return; - } - break; - case 5: - if ((png_ptr->row_number & 0x01) || png_ptr->width < 2) - { - png_write_finish_row(png_ptr); - return; - } - break; - case 6: - if (!(png_ptr->row_number & 0x01)) - { - png_write_finish_row(png_ptr); - return; - } - break; - } - } -#endif - - /* set up row info for transformations */ - png_ptr->row_info.color_type = png_ptr->color_type; - png_ptr->row_info.width = png_ptr->usr_width; - png_ptr->row_info.channels = png_ptr->usr_channels; - png_ptr->row_info.bit_depth = png_ptr->usr_bit_depth; - png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth * - png_ptr->row_info.channels); - - png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, - png_ptr->row_info.width); - - png_debug1(3, "row_info->color_type = %d\n", png_ptr->row_info.color_type); - png_debug1(3, "row_info->width = %lu\n", png_ptr->row_info.width); - png_debug1(3, "row_info->channels = %d\n", png_ptr->row_info.channels); - png_debug1(3, "row_info->bit_depth = %d\n", png_ptr->row_info.bit_depth); - png_debug1(3, "row_info->pixel_depth = %d\n", png_ptr->row_info.pixel_depth); - png_debug1(3, "row_info->rowbytes = %lu\n", png_ptr->row_info.rowbytes); - - /* Copy user's row into buffer, leaving room for filter byte. */ - png_memcpy_check(png_ptr, png_ptr->row_buf + 1, row, - png_ptr->row_info.rowbytes); - -#if defined(PNG_WRITE_INTERLACING_SUPPORTED) - /* handle interlacing */ - if (png_ptr->interlaced && png_ptr->pass < 6 && - (png_ptr->transformations & PNG_INTERLACE)) - { - png_do_write_interlace(&(png_ptr->row_info), - png_ptr->row_buf + 1, png_ptr->pass); - /* this should always get caught above, but still ... */ - if (!(png_ptr->row_info.width)) - { - png_write_finish_row(png_ptr); - return; - } - } -#endif - - /* handle other transformations */ - if (png_ptr->transformations) - png_do_write_transformations(png_ptr); - -#if defined(PNG_MNG_FEATURES_SUPPORTED) - /* Write filter_method 64 (intrapixel differencing) only if - * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and - * 2. Libpng did not write a PNG signature (this filter_method is only - * used in PNG datastreams that are embedded in MNG datastreams) and - * 3. The application called png_permit_mng_features with a mask that - * included PNG_FLAG_MNG_FILTER_64 and - * 4. The filter_method is 64 and - * 5. The color_type is RGB or RGBA - */ - if((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && - (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING)) - { - /* Intrapixel differencing */ - png_do_write_intrapixel(&(png_ptr->row_info), png_ptr->row_buf + 1); - } -#endif - - /* Find a filter if necessary, filter the row and write it out. */ - png_write_find_filter(png_ptr, &(png_ptr->row_info)); - - if (png_ptr->write_row_fn != NULL) - (*(png_ptr->write_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass); -} - -#if defined(PNG_WRITE_FLUSH_SUPPORTED) -/* Set the automatic flush interval or 0 to turn flushing off */ -void PNGAPI -png_set_flush(png_structp png_ptr, int nrows) -{ - png_debug(1, "in png_set_flush\n"); - if (png_ptr == NULL) - return; - png_ptr->flush_dist = (nrows < 0 ? 0 : nrows); -} - -/* flush the current output buffers now */ -void PNGAPI -png_write_flush(png_structp png_ptr) -{ - int wrote_IDAT; - - png_debug(1, "in png_write_flush\n"); - if (png_ptr == NULL) - return; - /* We have already written out all of the data */ - if (png_ptr->row_number >= png_ptr->num_rows) - return; - - do - { - int ret; - - /* compress the data */ - ret = deflate(&png_ptr->zstream, Z_SYNC_FLUSH); - wrote_IDAT = 0; - - /* check for compression errors */ - if (ret != Z_OK) - { - if (png_ptr->zstream.msg != NULL) - png_error(png_ptr, png_ptr->zstream.msg); - else - png_error(png_ptr, "zlib error"); - } - - if (!(png_ptr->zstream.avail_out)) - { - /* write the IDAT and reset the zlib output buffer */ - png_write_IDAT(png_ptr, png_ptr->zbuf, - png_ptr->zbuf_size); - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - wrote_IDAT = 1; - } - } while(wrote_IDAT == 1); - - /* If there is any data left to be output, write it into a new IDAT */ - if (png_ptr->zbuf_size != png_ptr->zstream.avail_out) - { - /* write the IDAT and reset the zlib output buffer */ - png_write_IDAT(png_ptr, png_ptr->zbuf, - png_ptr->zbuf_size - png_ptr->zstream.avail_out); - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - } - png_ptr->flush_rows = 0; - png_flush(png_ptr); -} -#endif /* PNG_WRITE_FLUSH_SUPPORTED */ - -/* free all memory used by the write */ -void PNGAPI -png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr) -{ - png_structp png_ptr = NULL; - png_infop info_ptr = NULL; -#ifdef PNG_USER_MEM_SUPPORTED - png_free_ptr free_fn = NULL; - png_voidp mem_ptr = NULL; -#endif - - png_debug(1, "in png_destroy_write_struct\n"); - if (png_ptr_ptr != NULL) - { - png_ptr = *png_ptr_ptr; -#ifdef PNG_USER_MEM_SUPPORTED - free_fn = png_ptr->free_fn; - mem_ptr = png_ptr->mem_ptr; -#endif - } - - if (info_ptr_ptr != NULL) - info_ptr = *info_ptr_ptr; - - if (info_ptr != NULL) - { - png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); - -#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) - if (png_ptr->num_chunk_list) - { - png_free(png_ptr, png_ptr->chunk_list); - png_ptr->chunk_list=NULL; - png_ptr->num_chunk_list=0; - } -#endif - -#ifdef PNG_USER_MEM_SUPPORTED - png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn, - (png_voidp)mem_ptr); -#else - png_destroy_struct((png_voidp)info_ptr); -#endif - *info_ptr_ptr = NULL; - } - - if (png_ptr != NULL) - { - png_write_destroy(png_ptr); -#ifdef PNG_USER_MEM_SUPPORTED - png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn, - (png_voidp)mem_ptr); -#else - png_destroy_struct((png_voidp)png_ptr); -#endif - *png_ptr_ptr = NULL; - } -} - - -/* Free any memory used in png_ptr struct (old method) */ -void /* PRIVATE */ -png_write_destroy(png_structp png_ptr) -{ -#ifdef PNG_SETJMP_SUPPORTED - jmp_buf tmp_jmp; /* save jump buffer */ -#endif - png_error_ptr error_fn; - png_error_ptr warning_fn; - png_voidp error_ptr; -#ifdef PNG_USER_MEM_SUPPORTED - png_free_ptr free_fn; -#endif - - png_debug(1, "in png_write_destroy\n"); - /* free any memory zlib uses */ - deflateEnd(&png_ptr->zstream); - - /* free our memory. png_free checks NULL for us. */ - png_free(png_ptr, png_ptr->zbuf); - png_free(png_ptr, png_ptr->row_buf); -#ifndef PNG_NO_WRITE_FILTERING - png_free(png_ptr, png_ptr->prev_row); - png_free(png_ptr, png_ptr->sub_row); - png_free(png_ptr, png_ptr->up_row); - png_free(png_ptr, png_ptr->avg_row); - png_free(png_ptr, png_ptr->paeth_row); -#endif - -#if defined(PNG_TIME_RFC1123_SUPPORTED) - png_free(png_ptr, png_ptr->time_buffer); -#endif - -#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - png_free(png_ptr, png_ptr->prev_filters); - png_free(png_ptr, png_ptr->filter_weights); - png_free(png_ptr, png_ptr->inv_filter_weights); - png_free(png_ptr, png_ptr->filter_costs); - png_free(png_ptr, png_ptr->inv_filter_costs); -#endif - -#ifdef PNG_SETJMP_SUPPORTED - /* reset structure */ - png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof (jmp_buf)); -#endif - - error_fn = png_ptr->error_fn; - warning_fn = png_ptr->warning_fn; - error_ptr = png_ptr->error_ptr; -#ifdef PNG_USER_MEM_SUPPORTED - free_fn = png_ptr->free_fn; -#endif - - png_memset(png_ptr, 0, png_sizeof (png_struct)); - - png_ptr->error_fn = error_fn; - png_ptr->warning_fn = warning_fn; - png_ptr->error_ptr = error_ptr; -#ifdef PNG_USER_MEM_SUPPORTED - png_ptr->free_fn = free_fn; -#endif - -#ifdef PNG_SETJMP_SUPPORTED - png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof (jmp_buf)); -#endif -} - -/* Allow the application to select one or more row filters to use. */ -void PNGAPI -png_set_filter(png_structp png_ptr, int method, int filters) -{ - png_debug(1, "in png_set_filter\n"); - if (png_ptr == NULL) - return; -#if defined(PNG_MNG_FEATURES_SUPPORTED) - if((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && - (method == PNG_INTRAPIXEL_DIFFERENCING)) - method = PNG_FILTER_TYPE_BASE; -#endif - if (method == PNG_FILTER_TYPE_BASE) - { - switch (filters & (PNG_ALL_FILTERS | 0x07)) - { -#ifndef PNG_NO_WRITE_FILTER - case 5: - case 6: - case 7: png_warning(png_ptr, "Unknown row filter for method 0"); -#endif /* PNG_NO_WRITE_FILTER */ - case PNG_FILTER_VALUE_NONE: - png_ptr->do_filter=PNG_FILTER_NONE; break; -#ifndef PNG_NO_WRITE_FILTER - case PNG_FILTER_VALUE_SUB: - png_ptr->do_filter=PNG_FILTER_SUB; break; - case PNG_FILTER_VALUE_UP: - png_ptr->do_filter=PNG_FILTER_UP; break; - case PNG_FILTER_VALUE_AVG: - png_ptr->do_filter=PNG_FILTER_AVG; break; - case PNG_FILTER_VALUE_PAETH: - png_ptr->do_filter=PNG_FILTER_PAETH; break; - default: png_ptr->do_filter = (png_byte)filters; break; -#else - default: png_warning(png_ptr, "Unknown row filter for method 0"); -#endif /* PNG_NO_WRITE_FILTER */ - } - - /* If we have allocated the row_buf, this means we have already started - * with the image and we should have allocated all of the filter buffers - * that have been selected. If prev_row isn't already allocated, then - * it is too late to start using the filters that need it, since we - * will be missing the data in the previous row. If an application - * wants to start and stop using particular filters during compression, - * it should start out with all of the filters, and then add and - * remove them after the start of compression. - */ - if (png_ptr->row_buf != NULL) - { -#ifndef PNG_NO_WRITE_FILTER - if ((png_ptr->do_filter & PNG_FILTER_SUB) && png_ptr->sub_row == NULL) - { - png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, - (png_ptr->rowbytes + 1)); - png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB; - } - - if ((png_ptr->do_filter & PNG_FILTER_UP) && png_ptr->up_row == NULL) - { - if (png_ptr->prev_row == NULL) - { - png_warning(png_ptr, "Can't add Up filter after starting"); - png_ptr->do_filter &= ~PNG_FILTER_UP; - } - else - { - png_ptr->up_row = (png_bytep)png_malloc(png_ptr, - (png_ptr->rowbytes + 1)); - png_ptr->up_row[0] = PNG_FILTER_VALUE_UP; - } - } - - if ((png_ptr->do_filter & PNG_FILTER_AVG) && png_ptr->avg_row == NULL) - { - if (png_ptr->prev_row == NULL) - { - png_warning(png_ptr, "Can't add Average filter after starting"); - png_ptr->do_filter &= ~PNG_FILTER_AVG; - } - else - { - png_ptr->avg_row = (png_bytep)png_malloc(png_ptr, - (png_ptr->rowbytes + 1)); - png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG; - } - } - - if ((png_ptr->do_filter & PNG_FILTER_PAETH) && - png_ptr->paeth_row == NULL) - { - if (png_ptr->prev_row == NULL) - { - png_warning(png_ptr, "Can't add Paeth filter after starting"); - png_ptr->do_filter &= (png_byte)(~PNG_FILTER_PAETH); - } - else - { - png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr, - (png_ptr->rowbytes + 1)); - png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH; - } - } - - if (png_ptr->do_filter == PNG_NO_FILTERS) -#endif /* PNG_NO_WRITE_FILTER */ - png_ptr->do_filter = PNG_FILTER_NONE; - } - } - else - png_error(png_ptr, "Unknown custom filter method"); -} - -/* This allows us to influence the way in which libpng chooses the "best" - * filter for the current scanline. While the "minimum-sum-of-absolute- - * differences metric is relatively fast and effective, there is some - * question as to whether it can be improved upon by trying to keep the - * filtered data going to zlib more consistent, hopefully resulting in - * better compression. - */ -#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) /* GRR 970116 */ -void PNGAPI -png_set_filter_heuristics(png_structp png_ptr, int heuristic_method, - int num_weights, png_doublep filter_weights, - png_doublep filter_costs) -{ - int i; - - png_debug(1, "in png_set_filter_heuristics\n"); - if (png_ptr == NULL) - return; - if (heuristic_method >= PNG_FILTER_HEURISTIC_LAST) - { - png_warning(png_ptr, "Unknown filter heuristic method"); - return; - } - - if (heuristic_method == PNG_FILTER_HEURISTIC_DEFAULT) - { - heuristic_method = PNG_FILTER_HEURISTIC_UNWEIGHTED; - } - - if (num_weights < 0 || filter_weights == NULL || - heuristic_method == PNG_FILTER_HEURISTIC_UNWEIGHTED) - { - num_weights = 0; - } - - png_ptr->num_prev_filters = (png_byte)num_weights; - png_ptr->heuristic_method = (png_byte)heuristic_method; - - if (num_weights > 0) - { - if (png_ptr->prev_filters == NULL) - { - png_ptr->prev_filters = (png_bytep)png_malloc(png_ptr, - (png_uint_32)(png_sizeof(png_byte) * num_weights)); - - /* To make sure that the weighting starts out fairly */ - for (i = 0; i < num_weights; i++) - { - png_ptr->prev_filters[i] = 255; - } - } - - if (png_ptr->filter_weights == NULL) - { - png_ptr->filter_weights = (png_uint_16p)png_malloc(png_ptr, - (png_uint_32)(png_sizeof(png_uint_16) * num_weights)); - - png_ptr->inv_filter_weights = (png_uint_16p)png_malloc(png_ptr, - (png_uint_32)(png_sizeof(png_uint_16) * num_weights)); - for (i = 0; i < num_weights; i++) - { - png_ptr->inv_filter_weights[i] = - png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; - } - } - - for (i = 0; i < num_weights; i++) - { - if (filter_weights[i] < 0.0) - { - png_ptr->inv_filter_weights[i] = - png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; - } - else - { - png_ptr->inv_filter_weights[i] = - (png_uint_16)((double)PNG_WEIGHT_FACTOR*filter_weights[i]+0.5); - png_ptr->filter_weights[i] = - (png_uint_16)((double)PNG_WEIGHT_FACTOR/filter_weights[i]+0.5); - } - } - } - - /* If, in the future, there are other filter methods, this would - * need to be based on png_ptr->filter. - */ - if (png_ptr->filter_costs == NULL) - { - png_ptr->filter_costs = (png_uint_16p)png_malloc(png_ptr, - (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST)); - - png_ptr->inv_filter_costs = (png_uint_16p)png_malloc(png_ptr, - (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST)); - - for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) - { - png_ptr->inv_filter_costs[i] = - png_ptr->filter_costs[i] = PNG_COST_FACTOR; - } - } - - /* Here is where we set the relative costs of the different filters. We - * should take the desired compression level into account when setting - * the costs, so that Paeth, for instance, has a high relative cost at low - * compression levels, while it has a lower relative cost at higher - * compression settings. The filter types are in order of increasing - * relative cost, so it would be possible to do this with an algorithm. - */ - for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) - { - if (filter_costs == NULL || filter_costs[i] < 0.0) - { - png_ptr->inv_filter_costs[i] = - png_ptr->filter_costs[i] = PNG_COST_FACTOR; - } - else if (filter_costs[i] >= 1.0) - { - png_ptr->inv_filter_costs[i] = - (png_uint_16)((double)PNG_COST_FACTOR / filter_costs[i] + 0.5); - png_ptr->filter_costs[i] = - (png_uint_16)((double)PNG_COST_FACTOR * filter_costs[i] + 0.5); - } - } -} -#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ - -void PNGAPI -png_set_compression_level(png_structp png_ptr, int level) -{ - png_debug(1, "in png_set_compression_level\n"); - if (png_ptr == NULL) - return; - png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_LEVEL; - png_ptr->zlib_level = level; -} - -void PNGAPI -png_set_compression_mem_level(png_structp png_ptr, int mem_level) -{ - png_debug(1, "in png_set_compression_mem_level\n"); - if (png_ptr == NULL) - return; - png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL; - png_ptr->zlib_mem_level = mem_level; -} - -void PNGAPI -png_set_compression_strategy(png_structp png_ptr, int strategy) -{ - png_debug(1, "in png_set_compression_strategy\n"); - if (png_ptr == NULL) - return; - png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY; - png_ptr->zlib_strategy = strategy; -} - -void PNGAPI -png_set_compression_window_bits(png_structp png_ptr, int window_bits) -{ - if (png_ptr == NULL) - return; - if (window_bits > 15) - png_warning(png_ptr, "Only compression windows <= 32k supported by PNG"); - else if (window_bits < 8) - png_warning(png_ptr, "Only compression windows >= 256 supported by PNG"); -#ifndef WBITS_8_OK - /* avoid libpng bug with 256-byte windows */ - if (window_bits == 8) - { - png_warning(png_ptr, "Compression window is being reset to 512"); - window_bits=9; - } -#endif - png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS; - png_ptr->zlib_window_bits = window_bits; -} - -void PNGAPI -png_set_compression_method(png_structp png_ptr, int method) -{ - png_debug(1, "in png_set_compression_method\n"); - if (png_ptr == NULL) - return; - if (method != 8) - png_warning(png_ptr, "Only compression method 8 is supported by PNG"); - png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_METHOD; - png_ptr->zlib_method = method; -} - -void PNGAPI -png_set_write_status_fn(png_structp png_ptr, png_write_status_ptr write_row_fn) -{ - if (png_ptr == NULL) - return; - png_ptr->write_row_fn = write_row_fn; -} - -#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) -void PNGAPI -png_set_write_user_transform_fn(png_structp png_ptr, png_user_transform_ptr - write_user_transform_fn) -{ - png_debug(1, "in png_set_write_user_transform_fn\n"); - if (png_ptr == NULL) - return; - png_ptr->transformations |= PNG_USER_TRANSFORM; - png_ptr->write_user_transform_fn = write_user_transform_fn; -} -#endif - - -#if defined(PNG_INFO_IMAGE_SUPPORTED) -void PNGAPI -png_write_png(png_structp png_ptr, png_infop info_ptr, - int transforms, voidp params) -{ - if (png_ptr == NULL || info_ptr == NULL) - return; -#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) - /* invert the alpha channel from opacity to transparency */ - if (transforms & PNG_TRANSFORM_INVERT_ALPHA) - png_set_invert_alpha(png_ptr); -#endif - - /* Write the file header information. */ - png_write_info(png_ptr, info_ptr); - - /* ------ these transformations don't touch the info structure ------- */ - -#if defined(PNG_WRITE_INVERT_SUPPORTED) - /* invert monochrome pixels */ - if (transforms & PNG_TRANSFORM_INVERT_MONO) - png_set_invert_mono(png_ptr); -#endif - -#if defined(PNG_WRITE_SHIFT_SUPPORTED) - /* Shift the pixels up to a legal bit depth and fill in - * as appropriate to correctly scale the image. - */ - if ((transforms & PNG_TRANSFORM_SHIFT) - && (info_ptr->valid & PNG_INFO_sBIT)) - png_set_shift(png_ptr, &info_ptr->sig_bit); -#endif - -#if defined(PNG_WRITE_PACK_SUPPORTED) - /* pack pixels into bytes */ - if (transforms & PNG_TRANSFORM_PACKING) - png_set_packing(png_ptr); -#endif - -#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) - /* swap location of alpha bytes from ARGB to RGBA */ - if (transforms & PNG_TRANSFORM_SWAP_ALPHA) - png_set_swap_alpha(png_ptr); -#endif - -#if defined(PNG_WRITE_FILLER_SUPPORTED) - /* Get rid of filler (OR ALPHA) bytes, pack XRGB/RGBX/ARGB/RGBA into - * RGB (4 channels -> 3 channels). The second parameter is not used. - */ - if (transforms & PNG_TRANSFORM_STRIP_FILLER) - png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); -#endif - -#if defined(PNG_WRITE_BGR_SUPPORTED) - /* flip BGR pixels to RGB */ - if (transforms & PNG_TRANSFORM_BGR) - png_set_bgr(png_ptr); -#endif - -#if defined(PNG_WRITE_SWAP_SUPPORTED) - /* swap bytes of 16-bit files to most significant byte first */ - if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) - png_set_swap(png_ptr); -#endif - -#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) - /* swap bits of 1, 2, 4 bit packed pixel formats */ - if (transforms & PNG_TRANSFORM_PACKSWAP) - png_set_packswap(png_ptr); -#endif - - /* ----------------------- end of transformations ------------------- */ - - /* write the bits */ - if (info_ptr->valid & PNG_INFO_IDAT) - png_write_image(png_ptr, info_ptr->row_pointers); - - /* It is REQUIRED to call this to finish writing the rest of the file */ - png_write_end(png_ptr, info_ptr); - - transforms = transforms; /* quiet compiler warnings */ - params = params; -} -#endif -#endif /* PNG_WRITE_SUPPORTED */ diff --git a/rosapps/lib/libpng/pngwtran.c b/rosapps/lib/libpng/pngwtran.c deleted file mode 100644 index 0372fe656ce..00000000000 --- a/rosapps/lib/libpng/pngwtran.c +++ /dev/null @@ -1,572 +0,0 @@ - -/* pngwtran.c - transforms the data in a row for PNG writers - * - * Last changed in libpng 1.2.9 April 14, 2006 - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2006 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - */ - -#define PNG_INTERNAL -#include "png.h" -#ifdef PNG_WRITE_SUPPORTED - -/* Transform the data according to the user's wishes. The order of - * transformations is significant. - */ -void /* PRIVATE */ -png_do_write_transformations(png_structp png_ptr) -{ - png_debug(1, "in png_do_write_transformations\n"); - - if (png_ptr == NULL) - return; - -#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) - if (png_ptr->transformations & PNG_USER_TRANSFORM) - if(png_ptr->write_user_transform_fn != NULL) - (*(png_ptr->write_user_transform_fn)) /* user write transform function */ - (png_ptr, /* png_ptr */ - &(png_ptr->row_info), /* row_info: */ - /* png_uint_32 width; width of row */ - /* png_uint_32 rowbytes; number of bytes in row */ - /* png_byte color_type; color type of pixels */ - /* png_byte bit_depth; bit depth of samples */ - /* png_byte channels; number of channels (1-4) */ - /* png_byte pixel_depth; bits per pixel (depth*channels) */ - png_ptr->row_buf + 1); /* start of pixel data for row */ -#endif -#if defined(PNG_WRITE_FILLER_SUPPORTED) - if (png_ptr->transformations & PNG_FILLER) - png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, - png_ptr->flags); -#endif -#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) - if (png_ptr->transformations & PNG_PACKSWAP) - png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1); -#endif -#if defined(PNG_WRITE_PACK_SUPPORTED) - if (png_ptr->transformations & PNG_PACK) - png_do_pack(&(png_ptr->row_info), png_ptr->row_buf + 1, - (png_uint_32)png_ptr->bit_depth); -#endif -#if defined(PNG_WRITE_SWAP_SUPPORTED) - if (png_ptr->transformations & PNG_SWAP_BYTES) - png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1); -#endif -#if defined(PNG_WRITE_SHIFT_SUPPORTED) - if (png_ptr->transformations & PNG_SHIFT) - png_do_shift(&(png_ptr->row_info), png_ptr->row_buf + 1, - &(png_ptr->shift)); -#endif -#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) - if (png_ptr->transformations & PNG_SWAP_ALPHA) - png_do_write_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); -#endif -#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) - if (png_ptr->transformations & PNG_INVERT_ALPHA) - png_do_write_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); -#endif -#if defined(PNG_WRITE_BGR_SUPPORTED) - if (png_ptr->transformations & PNG_BGR) - png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1); -#endif -#if defined(PNG_WRITE_INVERT_SUPPORTED) - if (png_ptr->transformations & PNG_INVERT_MONO) - png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1); -#endif -} - -#if defined(PNG_WRITE_PACK_SUPPORTED) -/* Pack pixels into bytes. Pass the true bit depth in bit_depth. The - * row_info bit depth should be 8 (one pixel per byte). The channels - * should be 1 (this only happens on grayscale and paletted images). - */ -void /* PRIVATE */ -png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth) -{ - png_debug(1, "in png_do_pack\n"); - if (row_info->bit_depth == 8 && -#if defined(PNG_USELESS_TESTS_SUPPORTED) - row != NULL && row_info != NULL && -#endif - row_info->channels == 1) - { - switch ((int)bit_depth) - { - case 1: - { - png_bytep sp, dp; - int mask, v; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - - sp = row; - dp = row; - mask = 0x80; - v = 0; - - for (i = 0; i < row_width; i++) - { - if (*sp != 0) - v |= mask; - sp++; - if (mask > 1) - mask >>= 1; - else - { - mask = 0x80; - *dp = (png_byte)v; - dp++; - v = 0; - } - } - if (mask != 0x80) - *dp = (png_byte)v; - break; - } - case 2: - { - png_bytep sp, dp; - int shift, v; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - - sp = row; - dp = row; - shift = 6; - v = 0; - for (i = 0; i < row_width; i++) - { - png_byte value; - - value = (png_byte)(*sp & 0x03); - v |= (value << shift); - if (shift == 0) - { - shift = 6; - *dp = (png_byte)v; - dp++; - v = 0; - } - else - shift -= 2; - sp++; - } - if (shift != 6) - *dp = (png_byte)v; - break; - } - case 4: - { - png_bytep sp, dp; - int shift, v; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - - sp = row; - dp = row; - shift = 4; - v = 0; - for (i = 0; i < row_width; i++) - { - png_byte value; - - value = (png_byte)(*sp & 0x0f); - v |= (value << shift); - - if (shift == 0) - { - shift = 4; - *dp = (png_byte)v; - dp++; - v = 0; - } - else - shift -= 4; - - sp++; - } - if (shift != 4) - *dp = (png_byte)v; - break; - } - } - row_info->bit_depth = (png_byte)bit_depth; - row_info->pixel_depth = (png_byte)(bit_depth * row_info->channels); - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, - row_info->width); - } -} -#endif - -#if defined(PNG_WRITE_SHIFT_SUPPORTED) -/* Shift pixel values to take advantage of whole range. Pass the - * true number of bits in bit_depth. The row should be packed - * according to row_info->bit_depth. Thus, if you had a row of - * bit depth 4, but the pixels only had values from 0 to 7, you - * would pass 3 as bit_depth, and this routine would translate the - * data to 0 to 15. - */ -void /* PRIVATE */ -png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth) -{ - png_debug(1, "in png_do_shift\n"); -#if defined(PNG_USELESS_TESTS_SUPPORTED) - if (row != NULL && row_info != NULL && -#else - if ( -#endif - row_info->color_type != PNG_COLOR_TYPE_PALETTE) - { - int shift_start[4], shift_dec[4]; - int channels = 0; - - if (row_info->color_type & PNG_COLOR_MASK_COLOR) - { - shift_start[channels] = row_info->bit_depth - bit_depth->red; - shift_dec[channels] = bit_depth->red; - channels++; - shift_start[channels] = row_info->bit_depth - bit_depth->green; - shift_dec[channels] = bit_depth->green; - channels++; - shift_start[channels] = row_info->bit_depth - bit_depth->blue; - shift_dec[channels] = bit_depth->blue; - channels++; - } - else - { - shift_start[channels] = row_info->bit_depth - bit_depth->gray; - shift_dec[channels] = bit_depth->gray; - channels++; - } - if (row_info->color_type & PNG_COLOR_MASK_ALPHA) - { - shift_start[channels] = row_info->bit_depth - bit_depth->alpha; - shift_dec[channels] = bit_depth->alpha; - channels++; - } - - /* with low row depths, could only be grayscale, so one channel */ - if (row_info->bit_depth < 8) - { - png_bytep bp = row; - png_uint_32 i; - png_byte mask; - png_uint_32 row_bytes = row_info->rowbytes; - - if (bit_depth->gray == 1 && row_info->bit_depth == 2) - mask = 0x55; - else if (row_info->bit_depth == 4 && bit_depth->gray == 3) - mask = 0x11; - else - mask = 0xff; - - for (i = 0; i < row_bytes; i++, bp++) - { - png_uint_16 v; - int j; - - v = *bp; - *bp = 0; - for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0]) - { - if (j > 0) - *bp |= (png_byte)((v << j) & 0xff); - else - *bp |= (png_byte)((v >> (-j)) & mask); - } - } - } - else if (row_info->bit_depth == 8) - { - png_bytep bp = row; - png_uint_32 i; - png_uint_32 istop = channels * row_info->width; - - for (i = 0; i < istop; i++, bp++) - { - - png_uint_16 v; - int j; - int c = (int)(i%channels); - - v = *bp; - *bp = 0; - for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c]) - { - if (j > 0) - *bp |= (png_byte)((v << j) & 0xff); - else - *bp |= (png_byte)((v >> (-j)) & 0xff); - } - } - } - else - { - png_bytep bp; - png_uint_32 i; - png_uint_32 istop = channels * row_info->width; - - for (bp = row, i = 0; i < istop; i++) - { - int c = (int)(i%channels); - png_uint_16 value, v; - int j; - - v = (png_uint_16)(((png_uint_16)(*bp) << 8) + *(bp + 1)); - value = 0; - for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c]) - { - if (j > 0) - value |= (png_uint_16)((v << j) & (png_uint_16)0xffff); - else - value |= (png_uint_16)((v >> (-j)) & (png_uint_16)0xffff); - } - *bp++ = (png_byte)(value >> 8); - *bp++ = (png_byte)(value & 0xff); - } - } - } -} -#endif - -#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) -void /* PRIVATE */ -png_do_write_swap_alpha(png_row_infop row_info, png_bytep row) -{ - png_debug(1, "in png_do_write_swap_alpha\n"); -#if defined(PNG_USELESS_TESTS_SUPPORTED) - if (row != NULL && row_info != NULL) -#endif - { - if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - { - /* This converts from ARGB to RGBA */ - if (row_info->bit_depth == 8) - { - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - for (i = 0, sp = dp = row; i < row_width; i++) - { - png_byte save = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = save; - } - } - /* This converts from AARRGGBB to RRGGBBAA */ - else - { - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - - for (i = 0, sp = dp = row; i < row_width; i++) - { - png_byte save[2]; - save[0] = *(sp++); - save[1] = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = save[0]; - *(dp++) = save[1]; - } - } - } - else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - { - /* This converts from AG to GA */ - if (row_info->bit_depth == 8) - { - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - - for (i = 0, sp = dp = row; i < row_width; i++) - { - png_byte save = *(sp++); - *(dp++) = *(sp++); - *(dp++) = save; - } - } - /* This converts from AAGG to GGAA */ - else - { - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - - for (i = 0, sp = dp = row; i < row_width; i++) - { - png_byte save[2]; - save[0] = *(sp++); - save[1] = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = save[0]; - *(dp++) = save[1]; - } - } - } - } -} -#endif - -#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) -void /* PRIVATE */ -png_do_write_invert_alpha(png_row_infop row_info, png_bytep row) -{ - png_debug(1, "in png_do_write_invert_alpha\n"); -#if defined(PNG_USELESS_TESTS_SUPPORTED) - if (row != NULL && row_info != NULL) -#endif - { - if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - { - /* This inverts the alpha channel in RGBA */ - if (row_info->bit_depth == 8) - { - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - for (i = 0, sp = dp = row; i < row_width; i++) - { - /* does nothing - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - */ - sp+=3; dp = sp; - *(dp++) = (png_byte)(255 - *(sp++)); - } - } - /* This inverts the alpha channel in RRGGBBAA */ - else - { - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - - for (i = 0, sp = dp = row; i < row_width; i++) - { - /* does nothing - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - *(dp++) = *(sp++); - */ - sp+=6; dp = sp; - *(dp++) = (png_byte)(255 - *(sp++)); - *(dp++) = (png_byte)(255 - *(sp++)); - } - } - } - else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - { - /* This inverts the alpha channel in GA */ - if (row_info->bit_depth == 8) - { - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - - for (i = 0, sp = dp = row; i < row_width; i++) - { - *(dp++) = *(sp++); - *(dp++) = (png_byte)(255 - *(sp++)); - } - } - /* This inverts the alpha channel in GGAA */ - else - { - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - - for (i = 0, sp = dp = row; i < row_width; i++) - { - /* does nothing - *(dp++) = *(sp++); - *(dp++) = *(sp++); - */ - sp+=2; dp = sp; - *(dp++) = (png_byte)(255 - *(sp++)); - *(dp++) = (png_byte)(255 - *(sp++)); - } - } - } - } -} -#endif - -#if defined(PNG_MNG_FEATURES_SUPPORTED) -/* undoes intrapixel differencing */ -void /* PRIVATE */ -png_do_write_intrapixel(png_row_infop row_info, png_bytep row) -{ - png_debug(1, "in png_do_write_intrapixel\n"); - if ( -#if defined(PNG_USELESS_TESTS_SUPPORTED) - row != NULL && row_info != NULL && -#endif - (row_info->color_type & PNG_COLOR_MASK_COLOR)) - { - int bytes_per_pixel; - png_uint_32 row_width = row_info->width; - if (row_info->bit_depth == 8) - { - png_bytep rp; - png_uint_32 i; - - if (row_info->color_type == PNG_COLOR_TYPE_RGB) - bytes_per_pixel = 3; - else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - bytes_per_pixel = 4; - else - return; - - for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) - { - *(rp) = (png_byte)((*rp - *(rp+1))&0xff); - *(rp+2) = (png_byte)((*(rp+2) - *(rp+1))&0xff); - } - } - else if (row_info->bit_depth == 16) - { - png_bytep rp; - png_uint_32 i; - - if (row_info->color_type == PNG_COLOR_TYPE_RGB) - bytes_per_pixel = 6; - else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - bytes_per_pixel = 8; - else - return; - - for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) - { - png_uint_32 s0 = (*(rp ) << 8) | *(rp+1); - png_uint_32 s1 = (*(rp+2) << 8) | *(rp+3); - png_uint_32 s2 = (*(rp+4) << 8) | *(rp+5); - png_uint_32 red = (png_uint_32)((s0-s1) & 0xffffL); - png_uint_32 blue = (png_uint_32)((s2-s1) & 0xffffL); - *(rp ) = (png_byte)((red >> 8) & 0xff); - *(rp+1) = (png_byte)(red & 0xff); - *(rp+4) = (png_byte)((blue >> 8) & 0xff); - *(rp+5) = (png_byte)(blue & 0xff); - } - } - } -} -#endif /* PNG_MNG_FEATURES_SUPPORTED */ -#endif /* PNG_WRITE_SUPPORTED */ diff --git a/rosapps/lib/libpng/pngwutil.c b/rosapps/lib/libpng/pngwutil.c deleted file mode 100644 index fef38aef9dd..00000000000 --- a/rosapps/lib/libpng/pngwutil.c +++ /dev/null @@ -1,2792 +0,0 @@ - -/* pngwutil.c - utilities to write a PNG file - * - * Last changed in libpng 1.2.20 Septhember 3, 2007 - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2007 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - */ - -#define PNG_INTERNAL -#include "png.h" -#ifdef PNG_WRITE_SUPPORTED - -/* Place a 32-bit number into a buffer in PNG byte order. We work - * with unsigned numbers for convenience, although one supported - * ancillary chunk uses signed (two's complement) numbers. - */ -void PNGAPI -png_save_uint_32(png_bytep buf, png_uint_32 i) -{ - buf[0] = (png_byte)((i >> 24) & 0xff); - buf[1] = (png_byte)((i >> 16) & 0xff); - buf[2] = (png_byte)((i >> 8) & 0xff); - buf[3] = (png_byte)(i & 0xff); -} - -/* The png_save_int_32 function assumes integers are stored in two's - * complement format. If this isn't the case, then this routine needs to - * be modified to write data in two's complement format. - */ -void PNGAPI -png_save_int_32(png_bytep buf, png_int_32 i) -{ - buf[0] = (png_byte)((i >> 24) & 0xff); - buf[1] = (png_byte)((i >> 16) & 0xff); - buf[2] = (png_byte)((i >> 8) & 0xff); - buf[3] = (png_byte)(i & 0xff); -} - -/* Place a 16-bit number into a buffer in PNG byte order. - * The parameter is declared unsigned int, not png_uint_16, - * just to avoid potential problems on pre-ANSI C compilers. - */ -void PNGAPI -png_save_uint_16(png_bytep buf, unsigned int i) -{ - buf[0] = (png_byte)((i >> 8) & 0xff); - buf[1] = (png_byte)(i & 0xff); -} - -/* Write a PNG chunk all at once. The type is an array of ASCII characters - * representing the chunk name. The array must be at least 4 bytes in - * length, and does not need to be null terminated. To be safe, pass the - * pre-defined chunk names here, and if you need a new one, define it - * where the others are defined. The length is the length of the data. - * All the data must be present. If that is not possible, use the - * png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end() - * functions instead. - */ -void PNGAPI -png_write_chunk(png_structp png_ptr, png_bytep chunk_name, - png_bytep data, png_size_t length) -{ - if(png_ptr == NULL) return; - png_write_chunk_start(png_ptr, chunk_name, (png_uint_32)length); - png_write_chunk_data(png_ptr, data, length); - png_write_chunk_end(png_ptr); -} - -/* Write the start of a PNG chunk. The type is the chunk type. - * The total_length is the sum of the lengths of all the data you will be - * passing in png_write_chunk_data(). - */ -void PNGAPI -png_write_chunk_start(png_structp png_ptr, png_bytep chunk_name, - png_uint_32 length) -{ - png_byte buf[4]; - png_debug2(0, "Writing %s chunk (%lu bytes)\n", chunk_name, length); - if(png_ptr == NULL) return; - - /* write the length */ - png_save_uint_32(buf, length); - png_write_data(png_ptr, buf, (png_size_t)4); - - /* write the chunk name */ - png_write_data(png_ptr, chunk_name, (png_size_t)4); - /* reset the crc and run it over the chunk name */ - png_reset_crc(png_ptr); - png_calculate_crc(png_ptr, chunk_name, (png_size_t)4); -} - -/* Write the data of a PNG chunk started with png_write_chunk_start(). - * Note that multiple calls to this function are allowed, and that the - * sum of the lengths from these calls *must* add up to the total_length - * given to png_write_chunk_start(). - */ -void PNGAPI -png_write_chunk_data(png_structp png_ptr, png_bytep data, png_size_t length) -{ - /* write the data, and run the CRC over it */ - if(png_ptr == NULL) return; - if (data != NULL && length > 0) - { - png_calculate_crc(png_ptr, data, length); - png_write_data(png_ptr, data, length); - } -} - -/* Finish a chunk started with png_write_chunk_start(). */ -void PNGAPI -png_write_chunk_end(png_structp png_ptr) -{ - png_byte buf[4]; - - if(png_ptr == NULL) return; - - /* write the crc */ - png_save_uint_32(buf, png_ptr->crc); - - png_write_data(png_ptr, buf, (png_size_t)4); -} - -/* Simple function to write the signature. If we have already written - * the magic bytes of the signature, or more likely, the PNG stream is - * being embedded into another stream and doesn't need its own signature, - * we should call png_set_sig_bytes() to tell libpng how many of the - * bytes have already been written. - */ -void /* PRIVATE */ -png_write_sig(png_structp png_ptr) -{ - png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; - /* write the rest of the 8 byte signature */ - png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes], - (png_size_t)8 - png_ptr->sig_bytes); - if(png_ptr->sig_bytes < 3) - png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; -} - -#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_iCCP_SUPPORTED) -/* - * This pair of functions encapsulates the operation of (a) compressing a - * text string, and (b) issuing it later as a series of chunk data writes. - * The compression_state structure is shared context for these functions - * set up by the caller in order to make the whole mess thread-safe. - */ - -typedef struct -{ - char *input; /* the uncompressed input data */ - int input_len; /* its length */ - int num_output_ptr; /* number of output pointers used */ - int max_output_ptr; /* size of output_ptr */ - png_charpp output_ptr; /* array of pointers to output */ -} compression_state; - -/* compress given text into storage in the png_ptr structure */ -static int /* PRIVATE */ -png_text_compress(png_structp png_ptr, - png_charp text, png_size_t text_len, int compression, - compression_state *comp) -{ - int ret; - - comp->num_output_ptr = 0; - comp->max_output_ptr = 0; - comp->output_ptr = NULL; - comp->input = NULL; - comp->input_len = 0; - - /* we may just want to pass the text right through */ - if (compression == PNG_TEXT_COMPRESSION_NONE) - { - comp->input = text; - comp->input_len = text_len; - return((int)text_len); - } - - if (compression >= PNG_TEXT_COMPRESSION_LAST) - { -#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) - char msg[50]; - png_snprintf(msg, 50, "Unknown compression type %d", compression); - png_warning(png_ptr, msg); -#else - png_warning(png_ptr, "Unknown compression type"); -#endif - } - - /* We can't write the chunk until we find out how much data we have, - * which means we need to run the compressor first and save the - * output. This shouldn't be a problem, as the vast majority of - * comments should be reasonable, but we will set up an array of - * malloc'd pointers to be sure. - * - * If we knew the application was well behaved, we could simplify this - * greatly by assuming we can always malloc an output buffer large - * enough to hold the compressed text ((1001 * text_len / 1000) + 12) - * and malloc this directly. The only time this would be a bad idea is - * if we can't malloc more than 64K and we have 64K of random input - * data, or if the input string is incredibly large (although this - * wouldn't cause a failure, just a slowdown due to swapping). - */ - - /* set up the compression buffers */ - png_ptr->zstream.avail_in = (uInt)text_len; - png_ptr->zstream.next_in = (Bytef *)text; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - png_ptr->zstream.next_out = (Bytef *)png_ptr->zbuf; - - /* this is the same compression loop as in png_write_row() */ - do - { - /* compress the data */ - ret = deflate(&png_ptr->zstream, Z_NO_FLUSH); - if (ret != Z_OK) - { - /* error */ - if (png_ptr->zstream.msg != NULL) - png_error(png_ptr, png_ptr->zstream.msg); - else - png_error(png_ptr, "zlib error"); - } - /* check to see if we need more room */ - if (!(png_ptr->zstream.avail_out)) - { - /* make sure the output array has room */ - if (comp->num_output_ptr >= comp->max_output_ptr) - { - int old_max; - - old_max = comp->max_output_ptr; - comp->max_output_ptr = comp->num_output_ptr + 4; - if (comp->output_ptr != NULL) - { - png_charpp old_ptr; - - old_ptr = comp->output_ptr; - comp->output_ptr = (png_charpp)png_malloc(png_ptr, - (png_uint_32)(comp->max_output_ptr * - png_sizeof (png_charpp))); - png_memcpy(comp->output_ptr, old_ptr, old_max - * png_sizeof (png_charp)); - png_free(png_ptr, old_ptr); - } - else - comp->output_ptr = (png_charpp)png_malloc(png_ptr, - (png_uint_32)(comp->max_output_ptr * - png_sizeof (png_charp))); - } - - /* save the data */ - comp->output_ptr[comp->num_output_ptr] = (png_charp)png_malloc(png_ptr, - (png_uint_32)png_ptr->zbuf_size); - png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf, - png_ptr->zbuf_size); - comp->num_output_ptr++; - - /* and reset the buffer */ - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - png_ptr->zstream.next_out = png_ptr->zbuf; - } - /* continue until we don't have any more to compress */ - } while (png_ptr->zstream.avail_in); - - /* finish the compression */ - do - { - /* tell zlib we are finished */ - ret = deflate(&png_ptr->zstream, Z_FINISH); - - if (ret == Z_OK) - { - /* check to see if we need more room */ - if (!(png_ptr->zstream.avail_out)) - { - /* check to make sure our output array has room */ - if (comp->num_output_ptr >= comp->max_output_ptr) - { - int old_max; - - old_max = comp->max_output_ptr; - comp->max_output_ptr = comp->num_output_ptr + 4; - if (comp->output_ptr != NULL) - { - png_charpp old_ptr; - - old_ptr = comp->output_ptr; - /* This could be optimized to realloc() */ - comp->output_ptr = (png_charpp)png_malloc(png_ptr, - (png_uint_32)(comp->max_output_ptr * - png_sizeof (png_charpp))); - png_memcpy(comp->output_ptr, old_ptr, - old_max * png_sizeof (png_charp)); - png_free(png_ptr, old_ptr); - } - else - comp->output_ptr = (png_charpp)png_malloc(png_ptr, - (png_uint_32)(comp->max_output_ptr * - png_sizeof (png_charp))); - } - - /* save off the data */ - comp->output_ptr[comp->num_output_ptr] = - (png_charp)png_malloc(png_ptr, (png_uint_32)png_ptr->zbuf_size); - png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf, - png_ptr->zbuf_size); - comp->num_output_ptr++; - - /* and reset the buffer pointers */ - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - png_ptr->zstream.next_out = png_ptr->zbuf; - } - } - else if (ret != Z_STREAM_END) - { - /* we got an error */ - if (png_ptr->zstream.msg != NULL) - png_error(png_ptr, png_ptr->zstream.msg); - else - png_error(png_ptr, "zlib error"); - } - } while (ret != Z_STREAM_END); - - /* text length is number of buffers plus last buffer */ - text_len = png_ptr->zbuf_size * comp->num_output_ptr; - if (png_ptr->zstream.avail_out < png_ptr->zbuf_size) - text_len += png_ptr->zbuf_size - (png_size_t)png_ptr->zstream.avail_out; - - return((int)text_len); -} - -/* ship the compressed text out via chunk writes */ -static void /* PRIVATE */ -png_write_compressed_data_out(png_structp png_ptr, compression_state *comp) -{ - int i; - - /* handle the no-compression case */ - if (comp->input) - { - png_write_chunk_data(png_ptr, (png_bytep)comp->input, - (png_size_t)comp->input_len); - return; - } - - /* write saved output buffers, if any */ - for (i = 0; i < comp->num_output_ptr; i++) - { - png_write_chunk_data(png_ptr,(png_bytep)comp->output_ptr[i], - png_ptr->zbuf_size); - png_free(png_ptr, comp->output_ptr[i]); - comp->output_ptr[i]=NULL; - } - if (comp->max_output_ptr != 0) - png_free(png_ptr, comp->output_ptr); - comp->output_ptr=NULL; - /* write anything left in zbuf */ - if (png_ptr->zstream.avail_out < (png_uint_32)png_ptr->zbuf_size) - png_write_chunk_data(png_ptr, png_ptr->zbuf, - png_ptr->zbuf_size - png_ptr->zstream.avail_out); - - /* reset zlib for another zTXt/iTXt or image data */ - deflateReset(&png_ptr->zstream); - png_ptr->zstream.data_type = Z_BINARY; -} -#endif - -/* Write the IHDR chunk, and update the png_struct with the necessary - * information. Note that the rest of this code depends upon this - * information being correct. - */ -void /* PRIVATE */ -png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height, - int bit_depth, int color_type, int compression_type, int filter_type, - int interlace_type) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_IHDR; -#endif - png_byte buf[13]; /* buffer to store the IHDR info */ - - png_debug(1, "in png_write_IHDR\n"); - /* Check that we have valid input data from the application info */ - switch (color_type) - { - case PNG_COLOR_TYPE_GRAY: - switch (bit_depth) - { - case 1: - case 2: - case 4: - case 8: - case 16: png_ptr->channels = 1; break; - default: png_error(png_ptr,"Invalid bit depth for grayscale image"); - } - break; - case PNG_COLOR_TYPE_RGB: - if (bit_depth != 8 && bit_depth != 16) - png_error(png_ptr, "Invalid bit depth for RGB image"); - png_ptr->channels = 3; - break; - case PNG_COLOR_TYPE_PALETTE: - switch (bit_depth) - { - case 1: - case 2: - case 4: - case 8: png_ptr->channels = 1; break; - default: png_error(png_ptr, "Invalid bit depth for paletted image"); - } - break; - case PNG_COLOR_TYPE_GRAY_ALPHA: - if (bit_depth != 8 && bit_depth != 16) - png_error(png_ptr, "Invalid bit depth for grayscale+alpha image"); - png_ptr->channels = 2; - break; - case PNG_COLOR_TYPE_RGB_ALPHA: - if (bit_depth != 8 && bit_depth != 16) - png_error(png_ptr, "Invalid bit depth for RGBA image"); - png_ptr->channels = 4; - break; - default: - png_error(png_ptr, "Invalid image color type specified"); - } - - if (compression_type != PNG_COMPRESSION_TYPE_BASE) - { - png_warning(png_ptr, "Invalid compression type specified"); - compression_type = PNG_COMPRESSION_TYPE_BASE; - } - - /* Write filter_method 64 (intrapixel differencing) only if - * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and - * 2. Libpng did not write a PNG signature (this filter_method is only - * used in PNG datastreams that are embedded in MNG datastreams) and - * 3. The application called png_permit_mng_features with a mask that - * included PNG_FLAG_MNG_FILTER_64 and - * 4. The filter_method is 64 and - * 5. The color_type is RGB or RGBA - */ - if ( -#if defined(PNG_MNG_FEATURES_SUPPORTED) - !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && - ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) && - (color_type == PNG_COLOR_TYPE_RGB || - color_type == PNG_COLOR_TYPE_RGB_ALPHA) && - (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) && -#endif - filter_type != PNG_FILTER_TYPE_BASE) - { - png_warning(png_ptr, "Invalid filter type specified"); - filter_type = PNG_FILTER_TYPE_BASE; - } - -#ifdef PNG_WRITE_INTERLACING_SUPPORTED - if (interlace_type != PNG_INTERLACE_NONE && - interlace_type != PNG_INTERLACE_ADAM7) - { - png_warning(png_ptr, "Invalid interlace type specified"); - interlace_type = PNG_INTERLACE_ADAM7; - } -#else - interlace_type=PNG_INTERLACE_NONE; -#endif - - /* save off the relevent information */ - png_ptr->bit_depth = (png_byte)bit_depth; - png_ptr->color_type = (png_byte)color_type; - png_ptr->interlaced = (png_byte)interlace_type; -#if defined(PNG_MNG_FEATURES_SUPPORTED) - png_ptr->filter_type = (png_byte)filter_type; -#endif - png_ptr->compression_type = (png_byte)compression_type; - png_ptr->width = width; - png_ptr->height = height; - - png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels); - png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width); - /* set the usr info, so any transformations can modify it */ - png_ptr->usr_width = png_ptr->width; - png_ptr->usr_bit_depth = png_ptr->bit_depth; - png_ptr->usr_channels = png_ptr->channels; - - /* pack the header information into the buffer */ - png_save_uint_32(buf, width); - png_save_uint_32(buf + 4, height); - buf[8] = (png_byte)bit_depth; - buf[9] = (png_byte)color_type; - buf[10] = (png_byte)compression_type; - buf[11] = (png_byte)filter_type; - buf[12] = (png_byte)interlace_type; - - /* write the chunk */ - png_write_chunk(png_ptr, png_IHDR, buf, (png_size_t)13); - - /* initialize zlib with PNG info */ - png_ptr->zstream.zalloc = png_zalloc; - png_ptr->zstream.zfree = png_zfree; - png_ptr->zstream.opaque = (voidpf)png_ptr; - if (!(png_ptr->do_filter)) - { - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE || - png_ptr->bit_depth < 8) - png_ptr->do_filter = PNG_FILTER_NONE; - else - png_ptr->do_filter = PNG_ALL_FILTERS; - } - if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY)) - { - if (png_ptr->do_filter != PNG_FILTER_NONE) - png_ptr->zlib_strategy = Z_FILTERED; - else - png_ptr->zlib_strategy = Z_DEFAULT_STRATEGY; - } - if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_LEVEL)) - png_ptr->zlib_level = Z_DEFAULT_COMPRESSION; - if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL)) - png_ptr->zlib_mem_level = 8; - if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS)) - png_ptr->zlib_window_bits = 15; - if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_METHOD)) - png_ptr->zlib_method = 8; - if (deflateInit2(&png_ptr->zstream, png_ptr->zlib_level, - png_ptr->zlib_method, png_ptr->zlib_window_bits, - png_ptr->zlib_mem_level, png_ptr->zlib_strategy) != Z_OK) - png_error(png_ptr, "zlib failed to initialize compressor"); - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - /* libpng is not interested in zstream.data_type */ - /* set it to a predefined value, to avoid its evaluation inside zlib */ - png_ptr->zstream.data_type = Z_BINARY; - - png_ptr->mode = PNG_HAVE_IHDR; -} - -/* write the palette. We are careful not to trust png_color to be in the - * correct order for PNG, so people can redefine it to any convenient - * structure. - */ -void /* PRIVATE */ -png_write_PLTE(png_structp png_ptr, png_colorp palette, png_uint_32 num_pal) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_PLTE; -#endif - png_uint_32 i; - png_colorp pal_ptr; - png_byte buf[3]; - - png_debug(1, "in png_write_PLTE\n"); - if (( -#if defined(PNG_MNG_FEATURES_SUPPORTED) - !(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) && -#endif - num_pal == 0) || num_pal > 256) - { - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - { - png_error(png_ptr, "Invalid number of colors in palette"); - } - else - { - png_warning(png_ptr, "Invalid number of colors in palette"); - return; - } - } - - if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR)) - { - png_warning(png_ptr, - "Ignoring request to write a PLTE chunk in grayscale PNG"); - return; - } - - png_ptr->num_palette = (png_uint_16)num_pal; - png_debug1(3, "num_palette = %d\n", png_ptr->num_palette); - - png_write_chunk_start(png_ptr, png_PLTE, num_pal * 3); -#ifndef PNG_NO_POINTER_INDEXING - for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++) - { - buf[0] = pal_ptr->red; - buf[1] = pal_ptr->green; - buf[2] = pal_ptr->blue; - png_write_chunk_data(png_ptr, buf, (png_size_t)3); - } -#else - /* This is a little slower but some buggy compilers need to do this instead */ - pal_ptr=palette; - for (i = 0; i < num_pal; i++) - { - buf[0] = pal_ptr[i].red; - buf[1] = pal_ptr[i].green; - buf[2] = pal_ptr[i].blue; - png_write_chunk_data(png_ptr, buf, (png_size_t)3); - } -#endif - png_write_chunk_end(png_ptr); - png_ptr->mode |= PNG_HAVE_PLTE; -} - -/* write an IDAT chunk */ -void /* PRIVATE */ -png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_IDAT; -#endif - png_debug(1, "in png_write_IDAT\n"); - - /* Optimize the CMF field in the zlib stream. */ - /* This hack of the zlib stream is compliant to the stream specification. */ - if (!(png_ptr->mode & PNG_HAVE_IDAT) && - png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE) - { - unsigned int z_cmf = data[0]; /* zlib compression method and flags */ - if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70) - { - /* Avoid memory underflows and multiplication overflows. */ - /* The conditions below are practically always satisfied; - however, they still must be checked. */ - if (length >= 2 && - png_ptr->height < 16384 && png_ptr->width < 16384) - { - png_uint_32 uncompressed_idat_size = png_ptr->height * - ((png_ptr->width * - png_ptr->channels * png_ptr->bit_depth + 15) >> 3); - unsigned int z_cinfo = z_cmf >> 4; - unsigned int half_z_window_size = 1 << (z_cinfo + 7); - while (uncompressed_idat_size <= half_z_window_size && - half_z_window_size >= 256) - { - z_cinfo--; - half_z_window_size >>= 1; - } - z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4); - if (data[0] != (png_byte)z_cmf) - { - data[0] = (png_byte)z_cmf; - data[1] &= 0xe0; - data[1] += (png_byte)(0x1f - ((z_cmf << 8) + data[1]) % 0x1f); - } - } - } - else - png_error(png_ptr, - "Invalid zlib compression method or flags in IDAT"); - } - - png_write_chunk(png_ptr, png_IDAT, data, length); - png_ptr->mode |= PNG_HAVE_IDAT; -} - -/* write an IEND chunk */ -void /* PRIVATE */ -png_write_IEND(png_structp png_ptr) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_IEND; -#endif - png_debug(1, "in png_write_IEND\n"); - png_write_chunk(png_ptr, png_IEND, png_bytep_NULL, - (png_size_t)0); - png_ptr->mode |= PNG_HAVE_IEND; -} - -#if defined(PNG_WRITE_gAMA_SUPPORTED) -/* write a gAMA chunk */ -#ifdef PNG_FLOATING_POINT_SUPPORTED -void /* PRIVATE */ -png_write_gAMA(png_structp png_ptr, double file_gamma) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_gAMA; -#endif - png_uint_32 igamma; - png_byte buf[4]; - - png_debug(1, "in png_write_gAMA\n"); - /* file_gamma is saved in 1/100,000ths */ - igamma = (png_uint_32)(file_gamma * 100000.0 + 0.5); - png_save_uint_32(buf, igamma); - png_write_chunk(png_ptr, png_gAMA, buf, (png_size_t)4); -} -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED -void /* PRIVATE */ -png_write_gAMA_fixed(png_structp png_ptr, png_fixed_point file_gamma) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_gAMA; -#endif - png_byte buf[4]; - - png_debug(1, "in png_write_gAMA\n"); - /* file_gamma is saved in 1/100,000ths */ - png_save_uint_32(buf, (png_uint_32)file_gamma); - png_write_chunk(png_ptr, png_gAMA, buf, (png_size_t)4); -} -#endif -#endif - -#if defined(PNG_WRITE_sRGB_SUPPORTED) -/* write a sRGB chunk */ -void /* PRIVATE */ -png_write_sRGB(png_structp png_ptr, int srgb_intent) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_sRGB; -#endif - png_byte buf[1]; - - png_debug(1, "in png_write_sRGB\n"); - if(srgb_intent >= PNG_sRGB_INTENT_LAST) - png_warning(png_ptr, - "Invalid sRGB rendering intent specified"); - buf[0]=(png_byte)srgb_intent; - png_write_chunk(png_ptr, png_sRGB, buf, (png_size_t)1); -} -#endif - -#if defined(PNG_WRITE_iCCP_SUPPORTED) -/* write an iCCP chunk */ -void /* PRIVATE */ -png_write_iCCP(png_structp png_ptr, png_charp name, int compression_type, - png_charp profile, int profile_len) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_iCCP; -#endif - png_size_t name_len; - png_charp new_name; - compression_state comp; - int embedded_profile_len = 0; - - png_debug(1, "in png_write_iCCP\n"); - - comp.num_output_ptr = 0; - comp.max_output_ptr = 0; - comp.output_ptr = NULL; - comp.input = NULL; - comp.input_len = 0; - - if (name == NULL || (name_len = png_check_keyword(png_ptr, name, - &new_name)) == 0) - { - png_warning(png_ptr, "Empty keyword in iCCP chunk"); - return; - } - - if (compression_type != PNG_COMPRESSION_TYPE_BASE) - png_warning(png_ptr, "Unknown compression type in iCCP chunk"); - - if (profile == NULL) - profile_len = 0; - - if (profile_len > 3) - embedded_profile_len = - ((*( (png_bytep)profile ))<<24) | - ((*( (png_bytep)profile+1))<<16) | - ((*( (png_bytep)profile+2))<< 8) | - ((*( (png_bytep)profile+3)) ); - - if (profile_len < embedded_profile_len) - { - png_warning(png_ptr, - "Embedded profile length too large in iCCP chunk"); - return; - } - - if (profile_len > embedded_profile_len) - { - png_warning(png_ptr, - "Truncating profile to actual length in iCCP chunk"); - profile_len = embedded_profile_len; - } - - if (profile_len) - profile_len = png_text_compress(png_ptr, profile, (png_size_t)profile_len, - PNG_COMPRESSION_TYPE_BASE, &comp); - - /* make sure we include the NULL after the name and the compression type */ - png_write_chunk_start(png_ptr, png_iCCP, - (png_uint_32)name_len+profile_len+2); - new_name[name_len+1]=0x00; - png_write_chunk_data(png_ptr, (png_bytep)new_name, name_len + 2); - - if (profile_len) - png_write_compressed_data_out(png_ptr, &comp); - - png_write_chunk_end(png_ptr); - png_free(png_ptr, new_name); -} -#endif - -#if defined(PNG_WRITE_sPLT_SUPPORTED) -/* write a sPLT chunk */ -void /* PRIVATE */ -png_write_sPLT(png_structp png_ptr, png_sPLT_tp spalette) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_sPLT; -#endif - png_size_t name_len; - png_charp new_name; - png_byte entrybuf[10]; - int entry_size = (spalette->depth == 8 ? 6 : 10); - int palette_size = entry_size * spalette->nentries; - png_sPLT_entryp ep; -#ifdef PNG_NO_POINTER_INDEXING - int i; -#endif - - png_debug(1, "in png_write_sPLT\n"); - if (spalette->name == NULL || (name_len = png_check_keyword(png_ptr, - spalette->name, &new_name))==0) - { - png_warning(png_ptr, "Empty keyword in sPLT chunk"); - return; - } - - /* make sure we include the NULL after the name */ - png_write_chunk_start(png_ptr, png_sPLT, - (png_uint_32)(name_len + 2 + palette_size)); - png_write_chunk_data(png_ptr, (png_bytep)new_name, name_len + 1); - png_write_chunk_data(png_ptr, (png_bytep)&spalette->depth, 1); - - /* loop through each palette entry, writing appropriately */ -#ifndef PNG_NO_POINTER_INDEXING - for (ep = spalette->entries; epentries+spalette->nentries; ep++) - { - if (spalette->depth == 8) - { - entrybuf[0] = (png_byte)ep->red; - entrybuf[1] = (png_byte)ep->green; - entrybuf[2] = (png_byte)ep->blue; - entrybuf[3] = (png_byte)ep->alpha; - png_save_uint_16(entrybuf + 4, ep->frequency); - } - else - { - png_save_uint_16(entrybuf + 0, ep->red); - png_save_uint_16(entrybuf + 2, ep->green); - png_save_uint_16(entrybuf + 4, ep->blue); - png_save_uint_16(entrybuf + 6, ep->alpha); - png_save_uint_16(entrybuf + 8, ep->frequency); - } - png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size); - } -#else - ep=spalette->entries; - for (i=0; i>spalette->nentries; i++) - { - if (spalette->depth == 8) - { - entrybuf[0] = (png_byte)ep[i].red; - entrybuf[1] = (png_byte)ep[i].green; - entrybuf[2] = (png_byte)ep[i].blue; - entrybuf[3] = (png_byte)ep[i].alpha; - png_save_uint_16(entrybuf + 4, ep[i].frequency); - } - else - { - png_save_uint_16(entrybuf + 0, ep[i].red); - png_save_uint_16(entrybuf + 2, ep[i].green); - png_save_uint_16(entrybuf + 4, ep[i].blue); - png_save_uint_16(entrybuf + 6, ep[i].alpha); - png_save_uint_16(entrybuf + 8, ep[i].frequency); - } - png_write_chunk_data(png_ptr, entrybuf, entry_size); - } -#endif - - png_write_chunk_end(png_ptr); - png_free(png_ptr, new_name); -} -#endif - -#if defined(PNG_WRITE_sBIT_SUPPORTED) -/* write the sBIT chunk */ -void /* PRIVATE */ -png_write_sBIT(png_structp png_ptr, png_color_8p sbit, int color_type) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_sBIT; -#endif - png_byte buf[4]; - png_size_t size; - - png_debug(1, "in png_write_sBIT\n"); - /* make sure we don't depend upon the order of PNG_COLOR_8 */ - if (color_type & PNG_COLOR_MASK_COLOR) - { - png_byte maxbits; - - maxbits = (png_byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 : - png_ptr->usr_bit_depth); - if (sbit->red == 0 || sbit->red > maxbits || - sbit->green == 0 || sbit->green > maxbits || - sbit->blue == 0 || sbit->blue > maxbits) - { - png_warning(png_ptr, "Invalid sBIT depth specified"); - return; - } - buf[0] = sbit->red; - buf[1] = sbit->green; - buf[2] = sbit->blue; - size = 3; - } - else - { - if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth) - { - png_warning(png_ptr, "Invalid sBIT depth specified"); - return; - } - buf[0] = sbit->gray; - size = 1; - } - - if (color_type & PNG_COLOR_MASK_ALPHA) - { - if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth) - { - png_warning(png_ptr, "Invalid sBIT depth specified"); - return; - } - buf[size++] = sbit->alpha; - } - - png_write_chunk(png_ptr, png_sBIT, buf, size); -} -#endif - -#if defined(PNG_WRITE_cHRM_SUPPORTED) -/* write the cHRM chunk */ -#ifdef PNG_FLOATING_POINT_SUPPORTED -void /* PRIVATE */ -png_write_cHRM(png_structp png_ptr, double white_x, double white_y, - double red_x, double red_y, double green_x, double green_y, - double blue_x, double blue_y) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_cHRM; -#endif - png_byte buf[32]; - png_uint_32 itemp; - - png_debug(1, "in png_write_cHRM\n"); - /* each value is saved in 1/100,000ths */ - if (white_x < 0 || white_x > 0.8 || white_y < 0 || white_y > 0.8 || - white_x + white_y > 1.0) - { - png_warning(png_ptr, "Invalid cHRM white point specified"); -#if !defined(PNG_NO_CONSOLE_IO) - fprintf(stderr,"white_x=%f, white_y=%f\n",white_x, white_y); -#endif - return; - } - itemp = (png_uint_32)(white_x * 100000.0 + 0.5); - png_save_uint_32(buf, itemp); - itemp = (png_uint_32)(white_y * 100000.0 + 0.5); - png_save_uint_32(buf + 4, itemp); - - if (red_x < 0 || red_y < 0 || red_x + red_y > 1.0) - { - png_warning(png_ptr, "Invalid cHRM red point specified"); - return; - } - itemp = (png_uint_32)(red_x * 100000.0 + 0.5); - png_save_uint_32(buf + 8, itemp); - itemp = (png_uint_32)(red_y * 100000.0 + 0.5); - png_save_uint_32(buf + 12, itemp); - - if (green_x < 0 || green_y < 0 || green_x + green_y > 1.0) - { - png_warning(png_ptr, "Invalid cHRM green point specified"); - return; - } - itemp = (png_uint_32)(green_x * 100000.0 + 0.5); - png_save_uint_32(buf + 16, itemp); - itemp = (png_uint_32)(green_y * 100000.0 + 0.5); - png_save_uint_32(buf + 20, itemp); - - if (blue_x < 0 || blue_y < 0 || blue_x + blue_y > 1.0) - { - png_warning(png_ptr, "Invalid cHRM blue point specified"); - return; - } - itemp = (png_uint_32)(blue_x * 100000.0 + 0.5); - png_save_uint_32(buf + 24, itemp); - itemp = (png_uint_32)(blue_y * 100000.0 + 0.5); - png_save_uint_32(buf + 28, itemp); - - png_write_chunk(png_ptr, png_cHRM, buf, (png_size_t)32); -} -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED -void /* PRIVATE */ -png_write_cHRM_fixed(png_structp png_ptr, png_fixed_point white_x, - png_fixed_point white_y, png_fixed_point red_x, png_fixed_point red_y, - png_fixed_point green_x, png_fixed_point green_y, png_fixed_point blue_x, - png_fixed_point blue_y) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_cHRM; -#endif - png_byte buf[32]; - - png_debug(1, "in png_write_cHRM\n"); - /* each value is saved in 1/100,000ths */ - if (white_x > 80000L || white_y > 80000L || white_x + white_y > 100000L) - { - png_warning(png_ptr, "Invalid fixed cHRM white point specified"); -#if !defined(PNG_NO_CONSOLE_IO) - fprintf(stderr,"white_x=%ld, white_y=%ld\n",white_x, white_y); -#endif - return; - } - png_save_uint_32(buf, (png_uint_32)white_x); - png_save_uint_32(buf + 4, (png_uint_32)white_y); - - if (red_x + red_y > 100000L) - { - png_warning(png_ptr, "Invalid cHRM fixed red point specified"); - return; - } - png_save_uint_32(buf + 8, (png_uint_32)red_x); - png_save_uint_32(buf + 12, (png_uint_32)red_y); - - if (green_x + green_y > 100000L) - { - png_warning(png_ptr, "Invalid fixed cHRM green point specified"); - return; - } - png_save_uint_32(buf + 16, (png_uint_32)green_x); - png_save_uint_32(buf + 20, (png_uint_32)green_y); - - if (blue_x + blue_y > 100000L) - { - png_warning(png_ptr, "Invalid fixed cHRM blue point specified"); - return; - } - png_save_uint_32(buf + 24, (png_uint_32)blue_x); - png_save_uint_32(buf + 28, (png_uint_32)blue_y); - - png_write_chunk(png_ptr, png_cHRM, buf, (png_size_t)32); -} -#endif -#endif - -#if defined(PNG_WRITE_tRNS_SUPPORTED) -/* write the tRNS chunk */ -void /* PRIVATE */ -png_write_tRNS(png_structp png_ptr, png_bytep trans, png_color_16p tran, - int num_trans, int color_type) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_tRNS; -#endif - png_byte buf[6]; - - png_debug(1, "in png_write_tRNS\n"); - if (color_type == PNG_COLOR_TYPE_PALETTE) - { - if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette) - { - png_warning(png_ptr,"Invalid number of transparent colors specified"); - return; - } - /* write the chunk out as it is */ - png_write_chunk(png_ptr, png_tRNS, trans, (png_size_t)num_trans); - } - else if (color_type == PNG_COLOR_TYPE_GRAY) - { - /* one 16 bit value */ - if(tran->gray >= (1 << png_ptr->bit_depth)) - { - png_warning(png_ptr, - "Ignoring attempt to write tRNS chunk out-of-range for bit_depth"); - return; - } - png_save_uint_16(buf, tran->gray); - png_write_chunk(png_ptr, png_tRNS, buf, (png_size_t)2); - } - else if (color_type == PNG_COLOR_TYPE_RGB) - { - /* three 16 bit values */ - png_save_uint_16(buf, tran->red); - png_save_uint_16(buf + 2, tran->green); - png_save_uint_16(buf + 4, tran->blue); - if(png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4])) - { - png_warning(png_ptr, - "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8"); - return; - } - png_write_chunk(png_ptr, png_tRNS, buf, (png_size_t)6); - } - else - { - png_warning(png_ptr, "Can't write tRNS with an alpha channel"); - } -} -#endif - -#if defined(PNG_WRITE_bKGD_SUPPORTED) -/* write the background chunk */ -void /* PRIVATE */ -png_write_bKGD(png_structp png_ptr, png_color_16p back, int color_type) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_bKGD; -#endif - png_byte buf[6]; - - png_debug(1, "in png_write_bKGD\n"); - if (color_type == PNG_COLOR_TYPE_PALETTE) - { - if ( -#if defined(PNG_MNG_FEATURES_SUPPORTED) - (png_ptr->num_palette || - (!(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE))) && -#endif - back->index > png_ptr->num_palette) - { - png_warning(png_ptr, "Invalid background palette index"); - return; - } - buf[0] = back->index; - png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)1); - } - else if (color_type & PNG_COLOR_MASK_COLOR) - { - png_save_uint_16(buf, back->red); - png_save_uint_16(buf + 2, back->green); - png_save_uint_16(buf + 4, back->blue); - if(png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4])) - { - png_warning(png_ptr, - "Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8"); - return; - } - png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)6); - } - else - { - if(back->gray >= (1 << png_ptr->bit_depth)) - { - png_warning(png_ptr, - "Ignoring attempt to write bKGD chunk out-of-range for bit_depth"); - return; - } - png_save_uint_16(buf, back->gray); - png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)2); - } -} -#endif - -#if defined(PNG_WRITE_hIST_SUPPORTED) -/* write the histogram */ -void /* PRIVATE */ -png_write_hIST(png_structp png_ptr, png_uint_16p hist, int num_hist) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_hIST; -#endif - int i; - png_byte buf[3]; - - png_debug(1, "in png_write_hIST\n"); - if (num_hist > (int)png_ptr->num_palette) - { - png_debug2(3, "num_hist = %d, num_palette = %d\n", num_hist, - png_ptr->num_palette); - png_warning(png_ptr, "Invalid number of histogram entries specified"); - return; - } - - png_write_chunk_start(png_ptr, png_hIST, (png_uint_32)(num_hist * 2)); - for (i = 0; i < num_hist; i++) - { - png_save_uint_16(buf, hist[i]); - png_write_chunk_data(png_ptr, buf, (png_size_t)2); - } - png_write_chunk_end(png_ptr); -} -#endif - -#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \ - defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) -/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification, - * and if invalid, correct the keyword rather than discarding the entire - * chunk. The PNG 1.0 specification requires keywords 1-79 characters in - * length, forbids leading or trailing whitespace, multiple internal spaces, - * and the non-break space (0x80) from ISO 8859-1. Returns keyword length. - * - * The new_key is allocated to hold the corrected keyword and must be freed - * by the calling routine. This avoids problems with trying to write to - * static keywords without having to have duplicate copies of the strings. - */ -png_size_t /* PRIVATE */ -png_check_keyword(png_structp png_ptr, png_charp key, png_charpp new_key) -{ - png_size_t key_len; - png_charp kp, dp; - int kflag; - int kwarn=0; - - png_debug(1, "in png_check_keyword\n"); - *new_key = NULL; - - if (key == NULL || (key_len = png_strlen(key)) == 0) - { - png_warning(png_ptr, "zero length keyword"); - return ((png_size_t)0); - } - - png_debug1(2, "Keyword to be checked is '%s'\n", key); - - *new_key = (png_charp)png_malloc_warn(png_ptr, (png_uint_32)(key_len + 2)); - if (*new_key == NULL) - { - png_warning(png_ptr, "Out of memory while procesing keyword"); - return ((png_size_t)0); - } - - /* Replace non-printing characters with a blank and print a warning */ - for (kp = key, dp = *new_key; *kp != '\0'; kp++, dp++) - { - if ((png_byte)*kp < 0x20 || - ((png_byte)*kp > 0x7E && (png_byte)*kp < 0xA1)) - { -#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) - char msg[40]; - - png_snprintf(msg, 40, - "invalid keyword character 0x%02X", (png_byte)*kp); - png_warning(png_ptr, msg); -#else - png_warning(png_ptr, "invalid character in keyword"); -#endif - *dp = ' '; - } - else - { - *dp = *kp; - } - } - *dp = '\0'; - - /* Remove any trailing white space. */ - kp = *new_key + key_len - 1; - if (*kp == ' ') - { - png_warning(png_ptr, "trailing spaces removed from keyword"); - - while (*kp == ' ') - { - *(kp--) = '\0'; - key_len--; - } - } - - /* Remove any leading white space. */ - kp = *new_key; - if (*kp == ' ') - { - png_warning(png_ptr, "leading spaces removed from keyword"); - - while (*kp == ' ') - { - kp++; - key_len--; - } - } - - png_debug1(2, "Checking for multiple internal spaces in '%s'\n", kp); - - /* Remove multiple internal spaces. */ - for (kflag = 0, dp = *new_key; *kp != '\0'; kp++) - { - if (*kp == ' ' && kflag == 0) - { - *(dp++) = *kp; - kflag = 1; - } - else if (*kp == ' ') - { - key_len--; - kwarn=1; - } - else - { - *(dp++) = *kp; - kflag = 0; - } - } - *dp = '\0'; - if(kwarn) - png_warning(png_ptr, "extra interior spaces removed from keyword"); - - if (key_len == 0) - { - png_free(png_ptr, *new_key); - *new_key=NULL; - png_warning(png_ptr, "Zero length keyword"); - } - - if (key_len > 79) - { - png_warning(png_ptr, "keyword length must be 1 - 79 characters"); - new_key[79] = '\0'; - key_len = 79; - } - - return (key_len); -} -#endif - -#if defined(PNG_WRITE_tEXt_SUPPORTED) -/* write a tEXt chunk */ -void /* PRIVATE */ -png_write_tEXt(png_structp png_ptr, png_charp key, png_charp text, - png_size_t text_len) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_tEXt; -#endif - png_size_t key_len; - png_charp new_key; - - png_debug(1, "in png_write_tEXt\n"); - if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0) - { - png_warning(png_ptr, "Empty keyword in tEXt chunk"); - return; - } - - if (text == NULL || *text == '\0') - text_len = 0; - else - text_len = png_strlen(text); - - /* make sure we include the 0 after the key */ - png_write_chunk_start(png_ptr, png_tEXt, (png_uint_32)key_len+text_len+1); - /* - * We leave it to the application to meet PNG-1.0 requirements on the - * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of - * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them. - * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. - */ - png_write_chunk_data(png_ptr, (png_bytep)new_key, key_len + 1); - if (text_len) - png_write_chunk_data(png_ptr, (png_bytep)text, text_len); - - png_write_chunk_end(png_ptr); - png_free(png_ptr, new_key); -} -#endif - -#if defined(PNG_WRITE_zTXt_SUPPORTED) -/* write a compressed text chunk */ -void /* PRIVATE */ -png_write_zTXt(png_structp png_ptr, png_charp key, png_charp text, - png_size_t text_len, int compression) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_zTXt; -#endif - png_size_t key_len; - char buf[1]; - png_charp new_key; - compression_state comp; - - png_debug(1, "in png_write_zTXt\n"); - - comp.num_output_ptr = 0; - comp.max_output_ptr = 0; - comp.output_ptr = NULL; - comp.input = NULL; - comp.input_len = 0; - - if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0) - { - png_warning(png_ptr, "Empty keyword in zTXt chunk"); - return; - } - - if (text == NULL || *text == '\0' || compression==PNG_TEXT_COMPRESSION_NONE) - { - png_write_tEXt(png_ptr, new_key, text, (png_size_t)0); - png_free(png_ptr, new_key); - return; - } - - text_len = png_strlen(text); - - /* compute the compressed data; do it now for the length */ - text_len = png_text_compress(png_ptr, text, text_len, compression, - &comp); - - /* write start of chunk */ - png_write_chunk_start(png_ptr, png_zTXt, (png_uint_32) - (key_len+text_len+2)); - /* write key */ - png_write_chunk_data(png_ptr, (png_bytep)new_key, key_len + 1); - png_free(png_ptr, new_key); - - buf[0] = (png_byte)compression; - /* write compression */ - png_write_chunk_data(png_ptr, (png_bytep)buf, (png_size_t)1); - /* write the compressed data */ - png_write_compressed_data_out(png_ptr, &comp); - - /* close the chunk */ - png_write_chunk_end(png_ptr); -} -#endif - -#if defined(PNG_WRITE_iTXt_SUPPORTED) -/* write an iTXt chunk */ -void /* PRIVATE */ -png_write_iTXt(png_structp png_ptr, int compression, png_charp key, - png_charp lang, png_charp lang_key, png_charp text) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_iTXt; -#endif - png_size_t lang_len, key_len, lang_key_len, text_len; - png_charp new_lang, new_key; - png_byte cbuf[2]; - compression_state comp; - - png_debug(1, "in png_write_iTXt\n"); - - comp.num_output_ptr = 0; - comp.max_output_ptr = 0; - comp.output_ptr = NULL; - comp.input = NULL; - - if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0) - { - png_warning(png_ptr, "Empty keyword in iTXt chunk"); - return; - } - if (lang == NULL || (lang_len = png_check_keyword(png_ptr, lang, &new_lang))==0) - { - png_warning(png_ptr, "Empty language field in iTXt chunk"); - new_lang = NULL; - lang_len = 0; - } - - if (lang_key == NULL) - lang_key_len = 0; - else - lang_key_len = png_strlen(lang_key); - - if (text == NULL) - text_len = 0; - else - text_len = png_strlen(text); - - /* compute the compressed data; do it now for the length */ - text_len = png_text_compress(png_ptr, text, text_len, compression-2, - &comp); - - - /* make sure we include the compression flag, the compression byte, - * and the NULs after the key, lang, and lang_key parts */ - - png_write_chunk_start(png_ptr, png_iTXt, - (png_uint_32)( - 5 /* comp byte, comp flag, terminators for key, lang and lang_key */ - + key_len - + lang_len - + lang_key_len - + text_len)); - - /* - * We leave it to the application to meet PNG-1.0 requirements on the - * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of - * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them. - * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. - */ - png_write_chunk_data(png_ptr, (png_bytep)new_key, key_len + 1); - - /* set the compression flag */ - if (compression == PNG_ITXT_COMPRESSION_NONE || \ - compression == PNG_TEXT_COMPRESSION_NONE) - cbuf[0] = 0; - else /* compression == PNG_ITXT_COMPRESSION_zTXt */ - cbuf[0] = 1; - /* set the compression method */ - cbuf[1] = 0; - png_write_chunk_data(png_ptr, cbuf, 2); - - cbuf[0] = 0; - png_write_chunk_data(png_ptr, (new_lang ? (png_bytep)new_lang : cbuf), lang_len + 1); - png_write_chunk_data(png_ptr, (lang_key ? (png_bytep)lang_key : cbuf), lang_key_len + 1); - png_write_compressed_data_out(png_ptr, &comp); - - png_write_chunk_end(png_ptr); - png_free(png_ptr, new_key); - if (new_lang) - png_free(png_ptr, new_lang); -} -#endif - -#if defined(PNG_WRITE_oFFs_SUPPORTED) -/* write the oFFs chunk */ -void /* PRIVATE */ -png_write_oFFs(png_structp png_ptr, png_int_32 x_offset, png_int_32 y_offset, - int unit_type) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_oFFs; -#endif - png_byte buf[9]; - - png_debug(1, "in png_write_oFFs\n"); - if (unit_type >= PNG_OFFSET_LAST) - png_warning(png_ptr, "Unrecognized unit type for oFFs chunk"); - - png_save_int_32(buf, x_offset); - png_save_int_32(buf + 4, y_offset); - buf[8] = (png_byte)unit_type; - - png_write_chunk(png_ptr, png_oFFs, buf, (png_size_t)9); -} -#endif -#if defined(PNG_WRITE_pCAL_SUPPORTED) -/* write the pCAL chunk (described in the PNG extensions document) */ -void /* PRIVATE */ -png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0, - png_int_32 X1, int type, int nparams, png_charp units, png_charpp params) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_pCAL; -#endif - png_size_t purpose_len, units_len, total_len; - png_uint_32p params_len; - png_byte buf[10]; - png_charp new_purpose; - int i; - - png_debug1(1, "in png_write_pCAL (%d parameters)\n", nparams); - if (type >= PNG_EQUATION_LAST) - png_warning(png_ptr, "Unrecognized equation type for pCAL chunk"); - - purpose_len = png_check_keyword(png_ptr, purpose, &new_purpose) + 1; - png_debug1(3, "pCAL purpose length = %d\n", (int)purpose_len); - units_len = png_strlen(units) + (nparams == 0 ? 0 : 1); - png_debug1(3, "pCAL units length = %d\n", (int)units_len); - total_len = purpose_len + units_len + 10; - - params_len = (png_uint_32p)png_malloc(png_ptr, (png_uint_32)(nparams - *png_sizeof(png_uint_32))); - - /* Find the length of each parameter, making sure we don't count the - null terminator for the last parameter. */ - for (i = 0; i < nparams; i++) - { - params_len[i] = png_strlen(params[i]) + (i == nparams - 1 ? 0 : 1); - png_debug2(3, "pCAL parameter %d length = %lu\n", i, params_len[i]); - total_len += (png_size_t)params_len[i]; - } - - png_debug1(3, "pCAL total length = %d\n", (int)total_len); - png_write_chunk_start(png_ptr, png_pCAL, (png_uint_32)total_len); - png_write_chunk_data(png_ptr, (png_bytep)new_purpose, purpose_len); - png_save_int_32(buf, X0); - png_save_int_32(buf + 4, X1); - buf[8] = (png_byte)type; - buf[9] = (png_byte)nparams; - png_write_chunk_data(png_ptr, buf, (png_size_t)10); - png_write_chunk_data(png_ptr, (png_bytep)units, (png_size_t)units_len); - - png_free(png_ptr, new_purpose); - - for (i = 0; i < nparams; i++) - { - png_write_chunk_data(png_ptr, (png_bytep)params[i], - (png_size_t)params_len[i]); - } - - png_free(png_ptr, params_len); - png_write_chunk_end(png_ptr); -} -#endif - -#if defined(PNG_WRITE_sCAL_SUPPORTED) -/* write the sCAL chunk */ -#if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO) -void /* PRIVATE */ -png_write_sCAL(png_structp png_ptr, int unit, double width, double height) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_sCAL; -#endif - char buf[64]; - png_size_t total_len; - - png_debug(1, "in png_write_sCAL\n"); - - buf[0] = (char)unit; -#if defined(_WIN32_WCE) -/* sprintf() function is not supported on WindowsCE */ - { - wchar_t wc_buf[32]; - size_t wc_len; - swprintf(wc_buf, TEXT("%12.12e"), width); - wc_len = wcslen(wc_buf); - WideCharToMultiByte(CP_ACP, 0, wc_buf, -1, buf + 1, wc_len, NULL, NULL); - total_len = wc_len + 2; - swprintf(wc_buf, TEXT("%12.12e"), height); - wc_len = wcslen(wc_buf); - WideCharToMultiByte(CP_ACP, 0, wc_buf, -1, buf + total_len, wc_len, - NULL, NULL); - total_len += wc_len; - } -#else - png_snprintf(buf + 1, 63, "%12.12e", width); - total_len = 1 + png_strlen(buf + 1) + 1; - png_snprintf(buf + total_len, 64-total_len, "%12.12e", height); - total_len += png_strlen(buf + total_len); -#endif - - png_debug1(3, "sCAL total length = %u\n", (unsigned int)total_len); - png_write_chunk(png_ptr, png_sCAL, (png_bytep)buf, total_len); -} -#else -#ifdef PNG_FIXED_POINT_SUPPORTED -void /* PRIVATE */ -png_write_sCAL_s(png_structp png_ptr, int unit, png_charp width, - png_charp height) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_sCAL; -#endif - png_byte buf[64]; - png_size_t wlen, hlen, total_len; - - png_debug(1, "in png_write_sCAL_s\n"); - - wlen = png_strlen(width); - hlen = png_strlen(height); - total_len = wlen + hlen + 2; - if (total_len > 64) - { - png_warning(png_ptr, "Can't write sCAL (buffer too small)"); - return; - } - - buf[0] = (png_byte)unit; - png_memcpy(buf + 1, width, wlen + 1); /* append the '\0' here */ - png_memcpy(buf + wlen + 2, height, hlen); /* do NOT append the '\0' here */ - - png_debug1(3, "sCAL total length = %u\n", (unsigned int)total_len); - png_write_chunk(png_ptr, png_sCAL, buf, total_len); -} -#endif -#endif -#endif - -#if defined(PNG_WRITE_pHYs_SUPPORTED) -/* write the pHYs chunk */ -void /* PRIVATE */ -png_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit, - png_uint_32 y_pixels_per_unit, - int unit_type) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_pHYs; -#endif - png_byte buf[9]; - - png_debug(1, "in png_write_pHYs\n"); - if (unit_type >= PNG_RESOLUTION_LAST) - png_warning(png_ptr, "Unrecognized unit type for pHYs chunk"); - - png_save_uint_32(buf, x_pixels_per_unit); - png_save_uint_32(buf + 4, y_pixels_per_unit); - buf[8] = (png_byte)unit_type; - - png_write_chunk(png_ptr, png_pHYs, buf, (png_size_t)9); -} -#endif - -#if defined(PNG_WRITE_tIME_SUPPORTED) -/* Write the tIME chunk. Use either png_convert_from_struct_tm() - * or png_convert_from_time_t(), or fill in the structure yourself. - */ -void /* PRIVATE */ -png_write_tIME(png_structp png_ptr, png_timep mod_time) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - PNG_tIME; -#endif - png_byte buf[7]; - - png_debug(1, "in png_write_tIME\n"); - if (mod_time->month > 12 || mod_time->month < 1 || - mod_time->day > 31 || mod_time->day < 1 || - mod_time->hour > 23 || mod_time->second > 60) - { - png_warning(png_ptr, "Invalid time specified for tIME chunk"); - return; - } - - png_save_uint_16(buf, mod_time->year); - buf[2] = mod_time->month; - buf[3] = mod_time->day; - buf[4] = mod_time->hour; - buf[5] = mod_time->minute; - buf[6] = mod_time->second; - - png_write_chunk(png_ptr, png_tIME, buf, (png_size_t)7); -} -#endif - -/* initializes the row writing capability of libpng */ -void /* PRIVATE */ -png_write_start_row(png_structp png_ptr) -{ -#ifdef PNG_WRITE_INTERLACING_SUPPORTED -#ifdef PNG_USE_LOCAL_ARRAYS - /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - - /* start of interlace block */ - int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; - - /* offset to next interlace block */ - int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; - - /* start of interlace block in the y direction */ - int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; - - /* offset to next interlace block in the y direction */ - int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; -#endif -#endif - - png_size_t buf_size; - - png_debug(1, "in png_write_start_row\n"); - buf_size = (png_size_t)(PNG_ROWBYTES( - png_ptr->usr_channels*png_ptr->usr_bit_depth,png_ptr->width)+1); - - /* set up row buffer */ - png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, (png_uint_32)buf_size); - png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE; - -#ifndef PNG_NO_WRITE_FILTERING - /* set up filtering buffer, if using this filter */ - if (png_ptr->do_filter & PNG_FILTER_SUB) - { - png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, - (png_ptr->rowbytes + 1)); - png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB; - } - - /* We only need to keep the previous row if we are using one of these. */ - if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH)) - { - /* set up previous row buffer */ - png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)buf_size); - png_memset(png_ptr->prev_row, 0, buf_size); - - if (png_ptr->do_filter & PNG_FILTER_UP) - { - png_ptr->up_row = (png_bytep)png_malloc(png_ptr, - (png_ptr->rowbytes + 1)); - png_ptr->up_row[0] = PNG_FILTER_VALUE_UP; - } - - if (png_ptr->do_filter & PNG_FILTER_AVG) - { - png_ptr->avg_row = (png_bytep)png_malloc(png_ptr, - (png_ptr->rowbytes + 1)); - png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG; - } - - if (png_ptr->do_filter & PNG_FILTER_PAETH) - { - png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr, - (png_ptr->rowbytes + 1)); - png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH; - } -#endif /* PNG_NO_WRITE_FILTERING */ - } - -#ifdef PNG_WRITE_INTERLACING_SUPPORTED - /* if interlaced, we need to set up width and height of pass */ - if (png_ptr->interlaced) - { - if (!(png_ptr->transformations & PNG_INTERLACE)) - { - png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - - png_pass_ystart[0]) / png_pass_yinc[0]; - png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 - - png_pass_start[0]) / png_pass_inc[0]; - } - else - { - png_ptr->num_rows = png_ptr->height; - png_ptr->usr_width = png_ptr->width; - } - } - else -#endif - { - png_ptr->num_rows = png_ptr->height; - png_ptr->usr_width = png_ptr->width; - } - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - png_ptr->zstream.next_out = png_ptr->zbuf; -} - -/* Internal use only. Called when finished processing a row of data. */ -void /* PRIVATE */ -png_write_finish_row(png_structp png_ptr) -{ -#ifdef PNG_WRITE_INTERLACING_SUPPORTED -#ifdef PNG_USE_LOCAL_ARRAYS - /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - - /* start of interlace block */ - int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; - - /* offset to next interlace block */ - int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; - - /* start of interlace block in the y direction */ - int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; - - /* offset to next interlace block in the y direction */ - int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; -#endif -#endif - - int ret; - - png_debug(1, "in png_write_finish_row\n"); - /* next row */ - png_ptr->row_number++; - - /* see if we are done */ - if (png_ptr->row_number < png_ptr->num_rows) - return; - -#ifdef PNG_WRITE_INTERLACING_SUPPORTED - /* if interlaced, go to next pass */ - if (png_ptr->interlaced) - { - png_ptr->row_number = 0; - if (png_ptr->transformations & PNG_INTERLACE) - { - png_ptr->pass++; - } - else - { - /* loop until we find a non-zero width or height pass */ - do - { - png_ptr->pass++; - if (png_ptr->pass >= 7) - break; - png_ptr->usr_width = (png_ptr->width + - png_pass_inc[png_ptr->pass] - 1 - - png_pass_start[png_ptr->pass]) / - png_pass_inc[png_ptr->pass]; - png_ptr->num_rows = (png_ptr->height + - png_pass_yinc[png_ptr->pass] - 1 - - png_pass_ystart[png_ptr->pass]) / - png_pass_yinc[png_ptr->pass]; - if (png_ptr->transformations & PNG_INTERLACE) - break; - } while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0); - - } - - /* reset the row above the image for the next pass */ - if (png_ptr->pass < 7) - { - if (png_ptr->prev_row != NULL) - png_memset(png_ptr->prev_row, 0, - (png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels* - png_ptr->usr_bit_depth,png_ptr->width))+1); - return; - } - } -#endif - - /* if we get here, we've just written the last row, so we need - to flush the compressor */ - do - { - /* tell the compressor we are done */ - ret = deflate(&png_ptr->zstream, Z_FINISH); - /* check for an error */ - if (ret == Z_OK) - { - /* check to see if we need more room */ - if (!(png_ptr->zstream.avail_out)) - { - png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - } - } - else if (ret != Z_STREAM_END) - { - if (png_ptr->zstream.msg != NULL) - png_error(png_ptr, png_ptr->zstream.msg); - else - png_error(png_ptr, "zlib error"); - } - } while (ret != Z_STREAM_END); - - /* write any extra space */ - if (png_ptr->zstream.avail_out < png_ptr->zbuf_size) - { - png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size - - png_ptr->zstream.avail_out); - } - - deflateReset(&png_ptr->zstream); - png_ptr->zstream.data_type = Z_BINARY; -} - -#if defined(PNG_WRITE_INTERLACING_SUPPORTED) -/* Pick out the correct pixels for the interlace pass. - * The basic idea here is to go through the row with a source - * pointer and a destination pointer (sp and dp), and copy the - * correct pixels for the pass. As the row gets compacted, - * sp will always be >= dp, so we should never overwrite anything. - * See the default: case for the easiest code to understand. - */ -void /* PRIVATE */ -png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) -{ -#ifdef PNG_USE_LOCAL_ARRAYS - /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - - /* start of interlace block */ - int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; - - /* offset to next interlace block */ - int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; -#endif - - png_debug(1, "in png_do_write_interlace\n"); - /* we don't have to do anything on the last pass (6) */ -#if defined(PNG_USELESS_TESTS_SUPPORTED) - if (row != NULL && row_info != NULL && pass < 6) -#else - if (pass < 6) -#endif - { - /* each pixel depth is handled separately */ - switch (row_info->pixel_depth) - { - case 1: - { - png_bytep sp; - png_bytep dp; - int shift; - int d; - int value; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - - dp = row; - d = 0; - shift = 7; - for (i = png_pass_start[pass]; i < row_width; - i += png_pass_inc[pass]) - { - sp = row + (png_size_t)(i >> 3); - value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01; - d |= (value << shift); - - if (shift == 0) - { - shift = 7; - *dp++ = (png_byte)d; - d = 0; - } - else - shift--; - - } - if (shift != 7) - *dp = (png_byte)d; - break; - } - case 2: - { - png_bytep sp; - png_bytep dp; - int shift; - int d; - int value; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - - dp = row; - shift = 6; - d = 0; - for (i = png_pass_start[pass]; i < row_width; - i += png_pass_inc[pass]) - { - sp = row + (png_size_t)(i >> 2); - value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03; - d |= (value << shift); - - if (shift == 0) - { - shift = 6; - *dp++ = (png_byte)d; - d = 0; - } - else - shift -= 2; - } - if (shift != 6) - *dp = (png_byte)d; - break; - } - case 4: - { - png_bytep sp; - png_bytep dp; - int shift; - int d; - int value; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - - dp = row; - shift = 4; - d = 0; - for (i = png_pass_start[pass]; i < row_width; - i += png_pass_inc[pass]) - { - sp = row + (png_size_t)(i >> 1); - value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f; - d |= (value << shift); - - if (shift == 0) - { - shift = 4; - *dp++ = (png_byte)d; - d = 0; - } - else - shift -= 4; - } - if (shift != 4) - *dp = (png_byte)d; - break; - } - default: - { - png_bytep sp; - png_bytep dp; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - png_size_t pixel_bytes; - - /* start at the beginning */ - dp = row; - /* find out how many bytes each pixel takes up */ - pixel_bytes = (row_info->pixel_depth >> 3); - /* loop through the row, only looking at the pixels that - matter */ - for (i = png_pass_start[pass]; i < row_width; - i += png_pass_inc[pass]) - { - /* find out where the original pixel is */ - sp = row + (png_size_t)i * pixel_bytes; - /* move the pixel */ - if (dp != sp) - png_memcpy(dp, sp, pixel_bytes); - /* next pixel */ - dp += pixel_bytes; - } - break; - } - } - /* set new row width */ - row_info->width = (row_info->width + - png_pass_inc[pass] - 1 - - png_pass_start[pass]) / - png_pass_inc[pass]; - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, - row_info->width); - } -} -#endif - -/* This filters the row, chooses which filter to use, if it has not already - * been specified by the application, and then writes the row out with the - * chosen filter. - */ -#define PNG_MAXSUM (((png_uint_32)(-1)) >> 1) -#define PNG_HISHIFT 10 -#define PNG_LOMASK ((png_uint_32)0xffffL) -#define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT)) -void /* PRIVATE */ -png_write_find_filter(png_structp png_ptr, png_row_infop row_info) -{ - png_bytep best_row; -#ifndef PNG_NO_WRITE_FILTER - png_bytep prev_row, row_buf; - png_uint_32 mins, bpp; - png_byte filter_to_do = png_ptr->do_filter; - png_uint_32 row_bytes = row_info->rowbytes; -#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - int num_p_filters = (int)png_ptr->num_prev_filters; -#endif - - png_debug(1, "in png_write_find_filter\n"); - /* find out how many bytes offset each pixel is */ - bpp = (row_info->pixel_depth + 7) >> 3; - - prev_row = png_ptr->prev_row; -#endif - best_row = png_ptr->row_buf; -#ifndef PNG_NO_WRITE_FILTER - row_buf = best_row; - mins = PNG_MAXSUM; - - /* The prediction method we use is to find which method provides the - * smallest value when summing the absolute values of the distances - * from zero, using anything >= 128 as negative numbers. This is known - * as the "minimum sum of absolute differences" heuristic. Other - * heuristics are the "weighted minimum sum of absolute differences" - * (experimental and can in theory improve compression), and the "zlib - * predictive" method (not implemented yet), which does test compressions - * of lines using different filter methods, and then chooses the - * (series of) filter(s) that give minimum compressed data size (VERY - * computationally expensive). - * - * GRR 980525: consider also - * (1) minimum sum of absolute differences from running average (i.e., - * keep running sum of non-absolute differences & count of bytes) - * [track dispersion, too? restart average if dispersion too large?] - * (1b) minimum sum of absolute differences from sliding average, probably - * with window size <= deflate window (usually 32K) - * (2) minimum sum of squared differences from zero or running average - * (i.e., ~ root-mean-square approach) - */ - - - /* We don't need to test the 'no filter' case if this is the only filter - * that has been chosen, as it doesn't actually do anything to the data. - */ - if ((filter_to_do & PNG_FILTER_NONE) && - filter_to_do != PNG_FILTER_NONE) - { - png_bytep rp; - png_uint_32 sum = 0; - png_uint_32 i; - int v; - - for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++) - { - v = *rp; - sum += (v < 128) ? v : 256 - v; - } - -#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - png_uint_32 sumhi, sumlo; - int j; - sumlo = sum & PNG_LOMASK; - sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; /* Gives us some footroom */ - - /* Reduce the sum if we match any of the previous rows */ - for (j = 0; j < num_p_filters; j++) - { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE) - { - sumlo = (sumlo * png_ptr->filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - sumhi = (sumhi * png_ptr->filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } - } - - /* Factor in the cost of this filter (this is here for completeness, - * but it makes no sense to have a "cost" for the NONE filter, as - * it has the minimum possible computational cost - none). - */ - sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> - PNG_COST_SHIFT; - sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> - PNG_COST_SHIFT; - - if (sumhi > PNG_HIMASK) - sum = PNG_MAXSUM; - else - sum = (sumhi << PNG_HISHIFT) + sumlo; - } -#endif - mins = sum; - } - - /* sub filter */ - if (filter_to_do == PNG_FILTER_SUB) - /* it's the only filter so no testing is needed */ - { - png_bytep rp, lp, dp; - png_uint_32 i; - for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; - i++, rp++, dp++) - { - *dp = *rp; - } - for (lp = row_buf + 1; i < row_bytes; - i++, rp++, lp++, dp++) - { - *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); - } - best_row = png_ptr->sub_row; - } - - else if (filter_to_do & PNG_FILTER_SUB) - { - png_bytep rp, dp, lp; - png_uint_32 sum = 0, lmins = mins; - png_uint_32 i; - int v; - -#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - /* We temporarily increase the "minimum sum" by the factor we - * would reduce the sum of this filter, so that we can do the - * early exit comparison without scaling the sum each time. - */ - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int j; - png_uint_32 lmhi, lmlo; - lmlo = lmins & PNG_LOMASK; - lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; - - for (j = 0; j < num_p_filters; j++) - { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB) - { - lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } - } - - lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> - PNG_COST_SHIFT; - lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> - PNG_COST_SHIFT; - - if (lmhi > PNG_HIMASK) - lmins = PNG_MAXSUM; - else - lmins = (lmhi << PNG_HISHIFT) + lmlo; - } -#endif - - for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; - i++, rp++, dp++) - { - v = *dp = *rp; - - sum += (v < 128) ? v : 256 - v; - } - for (lp = row_buf + 1; i < row_bytes; - i++, rp++, lp++, dp++) - { - v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); - - sum += (v < 128) ? v : 256 - v; - - if (sum > lmins) /* We are already worse, don't continue. */ - break; - } - -#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int j; - png_uint_32 sumhi, sumlo; - sumlo = sum & PNG_LOMASK; - sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; - - for (j = 0; j < num_p_filters; j++) - { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB) - { - sumlo = (sumlo * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - sumhi = (sumhi * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } - } - - sumlo = (sumlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> - PNG_COST_SHIFT; - sumhi = (sumhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> - PNG_COST_SHIFT; - - if (sumhi > PNG_HIMASK) - sum = PNG_MAXSUM; - else - sum = (sumhi << PNG_HISHIFT) + sumlo; - } -#endif - - if (sum < mins) - { - mins = sum; - best_row = png_ptr->sub_row; - } - } - - /* up filter */ - if (filter_to_do == PNG_FILTER_UP) - { - png_bytep rp, dp, pp; - png_uint_32 i; - - for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, - pp = prev_row + 1; i < row_bytes; - i++, rp++, pp++, dp++) - { - *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff); - } - best_row = png_ptr->up_row; - } - - else if (filter_to_do & PNG_FILTER_UP) - { - png_bytep rp, dp, pp; - png_uint_32 sum = 0, lmins = mins; - png_uint_32 i; - int v; - - -#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int j; - png_uint_32 lmhi, lmlo; - lmlo = lmins & PNG_LOMASK; - lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; - - for (j = 0; j < num_p_filters; j++) - { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP) - { - lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } - } - - lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> - PNG_COST_SHIFT; - lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> - PNG_COST_SHIFT; - - if (lmhi > PNG_HIMASK) - lmins = PNG_MAXSUM; - else - lmins = (lmhi << PNG_HISHIFT) + lmlo; - } -#endif - - for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, - pp = prev_row + 1; i < row_bytes; i++) - { - v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); - - sum += (v < 128) ? v : 256 - v; - - if (sum > lmins) /* We are already worse, don't continue. */ - break; - } - -#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int j; - png_uint_32 sumhi, sumlo; - sumlo = sum & PNG_LOMASK; - sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; - - for (j = 0; j < num_p_filters; j++) - { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP) - { - sumlo = (sumlo * png_ptr->filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - sumhi = (sumhi * png_ptr->filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } - } - - sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> - PNG_COST_SHIFT; - sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> - PNG_COST_SHIFT; - - if (sumhi > PNG_HIMASK) - sum = PNG_MAXSUM; - else - sum = (sumhi << PNG_HISHIFT) + sumlo; - } -#endif - - if (sum < mins) - { - mins = sum; - best_row = png_ptr->up_row; - } - } - - /* avg filter */ - if (filter_to_do == PNG_FILTER_AVG) - { - png_bytep rp, dp, pp, lp; - png_uint_32 i; - for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, - pp = prev_row + 1; i < bpp; i++) - { - *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); - } - for (lp = row_buf + 1; i < row_bytes; i++) - { - *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) - & 0xff); - } - best_row = png_ptr->avg_row; - } - - else if (filter_to_do & PNG_FILTER_AVG) - { - png_bytep rp, dp, pp, lp; - png_uint_32 sum = 0, lmins = mins; - png_uint_32 i; - int v; - -#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int j; - png_uint_32 lmhi, lmlo; - lmlo = lmins & PNG_LOMASK; - lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; - - for (j = 0; j < num_p_filters; j++) - { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_AVG) - { - lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } - } - - lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> - PNG_COST_SHIFT; - lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> - PNG_COST_SHIFT; - - if (lmhi > PNG_HIMASK) - lmins = PNG_MAXSUM; - else - lmins = (lmhi << PNG_HISHIFT) + lmlo; - } -#endif - - for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, - pp = prev_row + 1; i < bpp; i++) - { - v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); - - sum += (v < 128) ? v : 256 - v; - } - for (lp = row_buf + 1; i < row_bytes; i++) - { - v = *dp++ = - (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) & 0xff); - - sum += (v < 128) ? v : 256 - v; - - if (sum > lmins) /* We are already worse, don't continue. */ - break; - } - -#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int j; - png_uint_32 sumhi, sumlo; - sumlo = sum & PNG_LOMASK; - sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; - - for (j = 0; j < num_p_filters; j++) - { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE) - { - sumlo = (sumlo * png_ptr->filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - sumhi = (sumhi * png_ptr->filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } - } - - sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> - PNG_COST_SHIFT; - sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> - PNG_COST_SHIFT; - - if (sumhi > PNG_HIMASK) - sum = PNG_MAXSUM; - else - sum = (sumhi << PNG_HISHIFT) + sumlo; - } -#endif - - if (sum < mins) - { - mins = sum; - best_row = png_ptr->avg_row; - } - } - - /* Paeth filter */ - if (filter_to_do == PNG_FILTER_PAETH) - { - png_bytep rp, dp, pp, cp, lp; - png_uint_32 i; - for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, - pp = prev_row + 1; i < bpp; i++) - { - *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); - } - - for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) - { - int a, b, c, pa, pb, pc, p; - - b = *pp++; - c = *cp++; - a = *lp++; - - p = b - c; - pc = a - c; - -#ifdef PNG_USE_ABS - pa = abs(p); - pb = abs(pc); - pc = abs(p + pc); -#else - pa = p < 0 ? -p : p; - pb = pc < 0 ? -pc : pc; - pc = (p + pc) < 0 ? -(p + pc) : p + pc; -#endif - - p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; - - *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); - } - best_row = png_ptr->paeth_row; - } - - else if (filter_to_do & PNG_FILTER_PAETH) - { - png_bytep rp, dp, pp, cp, lp; - png_uint_32 sum = 0, lmins = mins; - png_uint_32 i; - int v; - -#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int j; - png_uint_32 lmhi, lmlo; - lmlo = lmins & PNG_LOMASK; - lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; - - for (j = 0; j < num_p_filters; j++) - { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH) - { - lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } - } - - lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> - PNG_COST_SHIFT; - lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> - PNG_COST_SHIFT; - - if (lmhi > PNG_HIMASK) - lmins = PNG_MAXSUM; - else - lmins = (lmhi << PNG_HISHIFT) + lmlo; - } -#endif - - for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, - pp = prev_row + 1; i < bpp; i++) - { - v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); - - sum += (v < 128) ? v : 256 - v; - } - - for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) - { - int a, b, c, pa, pb, pc, p; - - b = *pp++; - c = *cp++; - a = *lp++; - -#ifndef PNG_SLOW_PAETH - p = b - c; - pc = a - c; -#ifdef PNG_USE_ABS - pa = abs(p); - pb = abs(pc); - pc = abs(p + pc); -#else - pa = p < 0 ? -p : p; - pb = pc < 0 ? -pc : pc; - pc = (p + pc) < 0 ? -(p + pc) : p + pc; -#endif - p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; -#else /* PNG_SLOW_PAETH */ - p = a + b - c; - pa = abs(p - a); - pb = abs(p - b); - pc = abs(p - c); - if (pa <= pb && pa <= pc) - p = a; - else if (pb <= pc) - p = b; - else - p = c; -#endif /* PNG_SLOW_PAETH */ - - v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); - - sum += (v < 128) ? v : 256 - v; - - if (sum > lmins) /* We are already worse, don't continue. */ - break; - } - -#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int j; - png_uint_32 sumhi, sumlo; - sumlo = sum & PNG_LOMASK; - sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; - - for (j = 0; j < num_p_filters; j++) - { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH) - { - sumlo = (sumlo * png_ptr->filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - sumhi = (sumhi * png_ptr->filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } - } - - sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> - PNG_COST_SHIFT; - sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> - PNG_COST_SHIFT; - - if (sumhi > PNG_HIMASK) - sum = PNG_MAXSUM; - else - sum = (sumhi << PNG_HISHIFT) + sumlo; - } -#endif - - if (sum < mins) - { - best_row = png_ptr->paeth_row; - } - } -#endif /* PNG_NO_WRITE_FILTER */ - /* Do the actual writing of the filtered row data from the chosen filter. */ - - png_write_filtered_row(png_ptr, best_row); - -#ifndef PNG_NO_WRITE_FILTER -#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) - /* Save the type of filter we picked this time for future calculations */ - if (png_ptr->num_prev_filters > 0) - { - int j; - for (j = 1; j < num_p_filters; j++) - { - png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1]; - } - png_ptr->prev_filters[j] = best_row[0]; - } -#endif -#endif /* PNG_NO_WRITE_FILTER */ -} - - -/* Do the actual writing of a previously filtered row. */ -void /* PRIVATE */ -png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row) -{ - png_debug(1, "in png_write_filtered_row\n"); - png_debug1(2, "filter = %d\n", filtered_row[0]); - /* set up the zlib input buffer */ - - png_ptr->zstream.next_in = filtered_row; - png_ptr->zstream.avail_in = (uInt)png_ptr->row_info.rowbytes + 1; - /* repeat until we have compressed all the data */ - do - { - int ret; /* return of zlib */ - - /* compress the data */ - ret = deflate(&png_ptr->zstream, Z_NO_FLUSH); - /* check for compression errors */ - if (ret != Z_OK) - { - if (png_ptr->zstream.msg != NULL) - png_error(png_ptr, png_ptr->zstream.msg); - else - png_error(png_ptr, "zlib error"); - } - - /* see if it is time to write another IDAT */ - if (!(png_ptr->zstream.avail_out)) - { - /* write the IDAT and reset the zlib output buffer */ - png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - } - /* repeat until all data has been compressed */ - } while (png_ptr->zstream.avail_in); - - /* swap the current and previous rows */ - if (png_ptr->prev_row != NULL) - { - png_bytep tptr; - - tptr = png_ptr->prev_row; - png_ptr->prev_row = png_ptr->row_buf; - png_ptr->row_buf = tptr; - } - - /* finish row - updates counters and flushes zlib if last row */ - png_write_finish_row(png_ptr); - -#if defined(PNG_WRITE_FLUSH_SUPPORTED) - png_ptr->flush_rows++; - - if (png_ptr->flush_dist > 0 && - png_ptr->flush_rows >= png_ptr->flush_dist) - { - png_write_flush(png_ptr); - } -#endif -} -#endif /* PNG_WRITE_SUPPORTED */ From 67f5ef564ff5d63cb3b82b7386e60b3b68d181a8 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Mon, 12 Jul 2010 19:21:11 +0000 Subject: [PATCH 30/43] [PSDK] - Add the missing WSANO_ADDRESS definition svn path=/trunk/; revision=48016 --- reactos/include/psdk/winsock2.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/reactos/include/psdk/winsock2.h b/reactos/include/psdk/winsock2.h index f2243369f3e..537f31c1096 100644 --- a/reactos/include/psdk/winsock2.h +++ b/reactos/include/psdk/winsock2.h @@ -410,6 +410,8 @@ struct protoent { #endif /* !WSABASEERR */ +#define WSANO_ADDRESS WSANO_DATA + #define CF_ACCEPT 0x0000 #define CF_REJECT 0x0001 #define CF_DEFER 0x0002 From 795f1b72e158fef01d562081b01ac986553e8f4e Mon Sep 17 00:00:00 2001 From: Daniel Reimer Date: Mon, 12 Jul 2010 19:25:20 +0000 Subject: [PATCH 31/43] Tidy up tree from duplicate files. svn path=/trunk/; revision=48017 --- reactos/dll/3rdparty/libjpeg/cderror.h | 134 - reactos/dll/3rdparty/libjpeg/cdjpeg.h | 187 -- reactos/dll/3rdparty/libjpeg/jconfig.h | 18 - reactos/dll/3rdparty/libjpeg/jdct.h | 393 --- reactos/dll/3rdparty/libjpeg/jerror.h | 304 -- reactos/dll/3rdparty/libjpeg/jinclude.h | 91 - reactos/dll/3rdparty/libjpeg/jmemsys.h | 198 -- reactos/dll/3rdparty/libjpeg/jmorecfg.h | 375 --- reactos/dll/3rdparty/libjpeg/jpegint.h | 407 --- reactos/dll/3rdparty/libjpeg/jpeglib.h | 1158 -------- reactos/dll/3rdparty/libjpeg/jversion.h | 14 - reactos/dll/3rdparty/libjpeg/libjpeg.rbuild | 2 + reactos/dll/3rdparty/libjpeg/makefile.ansi | 221 -- reactos/dll/3rdparty/libjpeg/transupp.h | 210 -- reactos/dll/3rdparty/libpng/libpng.rbuild | 3 +- reactos/dll/3rdparty/libpng/png.h | 2701 ------------------ reactos/dll/3rdparty/libpng/pngconf.h | 1525 ---------- reactos/dll/3rdparty/libpng/pngpriv.h | 956 ------- reactos/dll/3rdparty/libtiff/libtiff.rbuild | 3 +- reactos/dll/3rdparty/libtiff/t4.h | 292 -- reactos/dll/3rdparty/libtiff/tif_config.h | 63 - reactos/dll/3rdparty/libtiff/tif_config.vc.h | 63 - reactos/dll/3rdparty/libtiff/tif_dir.h | 211 -- reactos/dll/3rdparty/libtiff/tif_fax3.h | 532 ---- reactos/dll/3rdparty/libtiff/tif_predict.h | 77 - reactos/dll/3rdparty/libtiff/tiff.h | 654 ----- reactos/dll/3rdparty/libtiff/tiffconf.h | 103 - reactos/dll/3rdparty/libtiff/tiffconf.vc.h | 116 - reactos/dll/3rdparty/libtiff/tiffio.h | 526 ---- reactos/dll/3rdparty/libtiff/tiffio.hxx | 49 - reactos/dll/3rdparty/libtiff/tiffiop.h | 350 --- reactos/dll/3rdparty/libtiff/tiffvers.h | 9 - reactos/dll/3rdparty/libtiff/uvcode.h | 180 -- 33 files changed, 6 insertions(+), 12119 deletions(-) delete mode 100644 reactos/dll/3rdparty/libjpeg/cderror.h delete mode 100644 reactos/dll/3rdparty/libjpeg/cdjpeg.h delete mode 100644 reactos/dll/3rdparty/libjpeg/jconfig.h delete mode 100644 reactos/dll/3rdparty/libjpeg/jdct.h delete mode 100644 reactos/dll/3rdparty/libjpeg/jerror.h delete mode 100644 reactos/dll/3rdparty/libjpeg/jinclude.h delete mode 100644 reactos/dll/3rdparty/libjpeg/jmemsys.h delete mode 100644 reactos/dll/3rdparty/libjpeg/jmorecfg.h delete mode 100644 reactos/dll/3rdparty/libjpeg/jpegint.h delete mode 100644 reactos/dll/3rdparty/libjpeg/jpeglib.h delete mode 100644 reactos/dll/3rdparty/libjpeg/jversion.h delete mode 100644 reactos/dll/3rdparty/libjpeg/makefile.ansi delete mode 100644 reactos/dll/3rdparty/libjpeg/transupp.h delete mode 100644 reactos/dll/3rdparty/libpng/png.h delete mode 100644 reactos/dll/3rdparty/libpng/pngconf.h delete mode 100644 reactos/dll/3rdparty/libpng/pngpriv.h delete mode 100644 reactos/dll/3rdparty/libtiff/t4.h delete mode 100644 reactos/dll/3rdparty/libtiff/tif_config.h delete mode 100644 reactos/dll/3rdparty/libtiff/tif_config.vc.h delete mode 100644 reactos/dll/3rdparty/libtiff/tif_dir.h delete mode 100644 reactos/dll/3rdparty/libtiff/tif_fax3.h delete mode 100644 reactos/dll/3rdparty/libtiff/tif_predict.h delete mode 100644 reactos/dll/3rdparty/libtiff/tiff.h delete mode 100644 reactos/dll/3rdparty/libtiff/tiffconf.h delete mode 100644 reactos/dll/3rdparty/libtiff/tiffconf.vc.h delete mode 100644 reactos/dll/3rdparty/libtiff/tiffio.h delete mode 100644 reactos/dll/3rdparty/libtiff/tiffio.hxx delete mode 100644 reactos/dll/3rdparty/libtiff/tiffiop.h delete mode 100644 reactos/dll/3rdparty/libtiff/tiffvers.h delete mode 100644 reactos/dll/3rdparty/libtiff/uvcode.h diff --git a/reactos/dll/3rdparty/libjpeg/cderror.h b/reactos/dll/3rdparty/libjpeg/cderror.h deleted file mode 100644 index e19c475c5c5..00000000000 --- a/reactos/dll/3rdparty/libjpeg/cderror.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * cderror.h - * - * Copyright (C) 1994-1997, Thomas G. Lane. - * Modified 2009 by Guido Vollbeding. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file defines the error and message codes for the cjpeg/djpeg - * applications. These strings are not needed as part of the JPEG library - * proper. - * Edit this file to add new codes, or to translate the message strings to - * some other language. - */ - -/* - * To define the enum list of message codes, include this file without - * defining macro JMESSAGE. To create a message string table, include it - * again with a suitable JMESSAGE definition (see jerror.c for an example). - */ -#ifndef JMESSAGE -#ifndef CDERROR_H -#define CDERROR_H -/* First time through, define the enum list */ -#define JMAKE_ENUM_LIST -#else -/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */ -#define JMESSAGE(code,string) -#endif /* CDERROR_H */ -#endif /* JMESSAGE */ - -#ifdef JMAKE_ENUM_LIST - -typedef enum { - -#define JMESSAGE(code,string) code , - -#endif /* JMAKE_ENUM_LIST */ - -JMESSAGE(JMSG_FIRSTADDONCODE=1000, NULL) /* Must be first entry! */ - -#ifdef BMP_SUPPORTED -JMESSAGE(JERR_BMP_BADCMAP, "Unsupported BMP colormap format") -JMESSAGE(JERR_BMP_BADDEPTH, "Only 8- and 24-bit BMP files are supported") -JMESSAGE(JERR_BMP_BADHEADER, "Invalid BMP file: bad header length") -JMESSAGE(JERR_BMP_BADPLANES, "Invalid BMP file: biPlanes not equal to 1") -JMESSAGE(JERR_BMP_COLORSPACE, "BMP output must be grayscale or RGB") -JMESSAGE(JERR_BMP_COMPRESSED, "Sorry, compressed BMPs not yet supported") -JMESSAGE(JERR_BMP_EMPTY, "Empty BMP image") -JMESSAGE(JERR_BMP_NOT, "Not a BMP file - does not start with BM") -JMESSAGE(JTRC_BMP, "%ux%u 24-bit BMP image") -JMESSAGE(JTRC_BMP_MAPPED, "%ux%u 8-bit colormapped BMP image") -JMESSAGE(JTRC_BMP_OS2, "%ux%u 24-bit OS2 BMP image") -JMESSAGE(JTRC_BMP_OS2_MAPPED, "%ux%u 8-bit colormapped OS2 BMP image") -#endif /* BMP_SUPPORTED */ - -#ifdef GIF_SUPPORTED -JMESSAGE(JERR_GIF_BUG, "GIF output got confused") -JMESSAGE(JERR_GIF_CODESIZE, "Bogus GIF codesize %d") -JMESSAGE(JERR_GIF_COLORSPACE, "GIF output must be grayscale or RGB") -JMESSAGE(JERR_GIF_IMAGENOTFOUND, "Too few images in GIF file") -JMESSAGE(JERR_GIF_NOT, "Not a GIF file") -JMESSAGE(JTRC_GIF, "%ux%ux%d GIF image") -JMESSAGE(JTRC_GIF_BADVERSION, - "Warning: unexpected GIF version number '%c%c%c'") -JMESSAGE(JTRC_GIF_EXTENSION, "Ignoring GIF extension block of type 0x%02x") -JMESSAGE(JTRC_GIF_NONSQUARE, "Caution: nonsquare pixels in input") -JMESSAGE(JWRN_GIF_BADDATA, "Corrupt data in GIF file") -JMESSAGE(JWRN_GIF_CHAR, "Bogus char 0x%02x in GIF file, ignoring") -JMESSAGE(JWRN_GIF_ENDCODE, "Premature end of GIF image") -JMESSAGE(JWRN_GIF_NOMOREDATA, "Ran out of GIF bits") -#endif /* GIF_SUPPORTED */ - -#ifdef PPM_SUPPORTED -JMESSAGE(JERR_PPM_COLORSPACE, "PPM output must be grayscale or RGB") -JMESSAGE(JERR_PPM_NONNUMERIC, "Nonnumeric data in PPM file") -JMESSAGE(JERR_PPM_NOT, "Not a PPM/PGM file") -JMESSAGE(JTRC_PGM, "%ux%u PGM image") -JMESSAGE(JTRC_PGM_TEXT, "%ux%u text PGM image") -JMESSAGE(JTRC_PPM, "%ux%u PPM image") -JMESSAGE(JTRC_PPM_TEXT, "%ux%u text PPM image") -#endif /* PPM_SUPPORTED */ - -#ifdef RLE_SUPPORTED -JMESSAGE(JERR_RLE_BADERROR, "Bogus error code from RLE library") -JMESSAGE(JERR_RLE_COLORSPACE, "RLE output must be grayscale or RGB") -JMESSAGE(JERR_RLE_DIMENSIONS, "Image dimensions (%ux%u) too large for RLE") -JMESSAGE(JERR_RLE_EMPTY, "Empty RLE file") -JMESSAGE(JERR_RLE_EOF, "Premature EOF in RLE header") -JMESSAGE(JERR_RLE_MEM, "Insufficient memory for RLE header") -JMESSAGE(JERR_RLE_NOT, "Not an RLE file") -JMESSAGE(JERR_RLE_TOOMANYCHANNELS, "Cannot handle %d output channels for RLE") -JMESSAGE(JERR_RLE_UNSUPPORTED, "Cannot handle this RLE setup") -JMESSAGE(JTRC_RLE, "%ux%u full-color RLE file") -JMESSAGE(JTRC_RLE_FULLMAP, "%ux%u full-color RLE file with map of length %d") -JMESSAGE(JTRC_RLE_GRAY, "%ux%u grayscale RLE file") -JMESSAGE(JTRC_RLE_MAPGRAY, "%ux%u grayscale RLE file with map of length %d") -JMESSAGE(JTRC_RLE_MAPPED, "%ux%u colormapped RLE file with map of length %d") -#endif /* RLE_SUPPORTED */ - -#ifdef TARGA_SUPPORTED -JMESSAGE(JERR_TGA_BADCMAP, "Unsupported Targa colormap format") -JMESSAGE(JERR_TGA_BADPARMS, "Invalid or unsupported Targa file") -JMESSAGE(JERR_TGA_COLORSPACE, "Targa output must be grayscale or RGB") -JMESSAGE(JTRC_TGA, "%ux%u RGB Targa image") -JMESSAGE(JTRC_TGA_GRAY, "%ux%u grayscale Targa image") -JMESSAGE(JTRC_TGA_MAPPED, "%ux%u colormapped Targa image") -#else -JMESSAGE(JERR_TGA_NOTCOMP, "Targa support was not compiled") -#endif /* TARGA_SUPPORTED */ - -JMESSAGE(JERR_BAD_CMAP_FILE, - "Color map file is invalid or of unsupported format") -JMESSAGE(JERR_TOO_MANY_COLORS, - "Output file format cannot handle %d colormap entries") -JMESSAGE(JERR_UNGETC_FAILED, "ungetc failed") -#ifdef TARGA_SUPPORTED -JMESSAGE(JERR_UNKNOWN_FORMAT, - "Unrecognized input file format --- perhaps you need -targa") -#else -JMESSAGE(JERR_UNKNOWN_FORMAT, "Unrecognized input file format") -#endif -JMESSAGE(JERR_UNSUPPORTED_FORMAT, "Unsupported output file format") - -#ifdef JMAKE_ENUM_LIST - - JMSG_LASTADDONCODE -} ADDON_MESSAGE_CODE; - -#undef JMAKE_ENUM_LIST -#endif /* JMAKE_ENUM_LIST */ - -/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */ -#undef JMESSAGE diff --git a/reactos/dll/3rdparty/libjpeg/cdjpeg.h b/reactos/dll/3rdparty/libjpeg/cdjpeg.h deleted file mode 100644 index ed024ac3ae8..00000000000 --- a/reactos/dll/3rdparty/libjpeg/cdjpeg.h +++ /dev/null @@ -1,187 +0,0 @@ -/* - * cdjpeg.h - * - * Copyright (C) 1994-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains common declarations for the sample applications - * cjpeg and djpeg. It is NOT used by the core JPEG library. - */ - -#define JPEG_CJPEG_DJPEG /* define proper options in jconfig.h */ -#define JPEG_INTERNAL_OPTIONS /* cjpeg.c,djpeg.c need to see xxx_SUPPORTED */ -#include "jinclude.h" -#include "jpeglib.h" -#include "jerror.h" /* get library error codes too */ -#include "cderror.h" /* get application-specific error codes */ - - -/* - * Object interface for cjpeg's source file decoding modules - */ - -typedef struct cjpeg_source_struct * cjpeg_source_ptr; - -struct cjpeg_source_struct { - JMETHOD(void, start_input, (j_compress_ptr cinfo, - cjpeg_source_ptr sinfo)); - JMETHOD(JDIMENSION, get_pixel_rows, (j_compress_ptr cinfo, - cjpeg_source_ptr sinfo)); - JMETHOD(void, finish_input, (j_compress_ptr cinfo, - cjpeg_source_ptr sinfo)); - - FILE *input_file; - - JSAMPARRAY buffer; - JDIMENSION buffer_height; -}; - - -/* - * Object interface for djpeg's output file encoding modules - */ - -typedef struct djpeg_dest_struct * djpeg_dest_ptr; - -struct djpeg_dest_struct { - /* start_output is called after jpeg_start_decompress finishes. - * The color map will be ready at this time, if one is needed. - */ - JMETHOD(void, start_output, (j_decompress_ptr cinfo, - djpeg_dest_ptr dinfo)); - /* Emit the specified number of pixel rows from the buffer. */ - JMETHOD(void, put_pixel_rows, (j_decompress_ptr cinfo, - djpeg_dest_ptr dinfo, - JDIMENSION rows_supplied)); - /* Finish up at the end of the image. */ - JMETHOD(void, finish_output, (j_decompress_ptr cinfo, - djpeg_dest_ptr dinfo)); - - /* Target file spec; filled in by djpeg.c after object is created. */ - FILE * output_file; - - /* Output pixel-row buffer. Created by module init or start_output. - * Width is cinfo->output_width * cinfo->output_components; - * height is buffer_height. - */ - JSAMPARRAY buffer; - JDIMENSION buffer_height; -}; - - -/* - * cjpeg/djpeg may need to perform extra passes to convert to or from - * the source/destination file format. The JPEG library does not know - * about these passes, but we'd like them to be counted by the progress - * monitor. We use an expanded progress monitor object to hold the - * additional pass count. - */ - -struct cdjpeg_progress_mgr { - struct jpeg_progress_mgr pub; /* fields known to JPEG library */ - int completed_extra_passes; /* extra passes completed */ - int total_extra_passes; /* total extra */ - /* last printed percentage stored here to avoid multiple printouts */ - int percent_done; -}; - -typedef struct cdjpeg_progress_mgr * cd_progress_ptr; - - -/* Short forms of external names for systems with brain-damaged linkers. */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jinit_read_bmp jIRdBMP -#define jinit_write_bmp jIWrBMP -#define jinit_read_gif jIRdGIF -#define jinit_write_gif jIWrGIF -#define jinit_read_ppm jIRdPPM -#define jinit_write_ppm jIWrPPM -#define jinit_read_rle jIRdRLE -#define jinit_write_rle jIWrRLE -#define jinit_read_targa jIRdTarga -#define jinit_write_targa jIWrTarga -#define read_quant_tables RdQTables -#define read_scan_script RdScnScript -#define set_quality_ratings SetQRates -#define set_quant_slots SetQSlots -#define set_sample_factors SetSFacts -#define read_color_map RdCMap -#define enable_signal_catcher EnSigCatcher -#define start_progress_monitor StProgMon -#define end_progress_monitor EnProgMon -#define read_stdin RdStdin -#define write_stdout WrStdout -#endif /* NEED_SHORT_EXTERNAL_NAMES */ - -/* Module selection routines for I/O modules. */ - -EXTERN(cjpeg_source_ptr) jinit_read_bmp JPP((j_compress_ptr cinfo)); -EXTERN(djpeg_dest_ptr) jinit_write_bmp JPP((j_decompress_ptr cinfo, - boolean is_os2)); -EXTERN(cjpeg_source_ptr) jinit_read_gif JPP((j_compress_ptr cinfo)); -EXTERN(djpeg_dest_ptr) jinit_write_gif JPP((j_decompress_ptr cinfo)); -EXTERN(cjpeg_source_ptr) jinit_read_ppm JPP((j_compress_ptr cinfo)); -EXTERN(djpeg_dest_ptr) jinit_write_ppm JPP((j_decompress_ptr cinfo)); -EXTERN(cjpeg_source_ptr) jinit_read_rle JPP((j_compress_ptr cinfo)); -EXTERN(djpeg_dest_ptr) jinit_write_rle JPP((j_decompress_ptr cinfo)); -EXTERN(cjpeg_source_ptr) jinit_read_targa JPP((j_compress_ptr cinfo)); -EXTERN(djpeg_dest_ptr) jinit_write_targa JPP((j_decompress_ptr cinfo)); - -/* cjpeg support routines (in rdswitch.c) */ - -EXTERN(boolean) read_quant_tables JPP((j_compress_ptr cinfo, char * filename, - boolean force_baseline)); -EXTERN(boolean) read_scan_script JPP((j_compress_ptr cinfo, char * filename)); -EXTERN(boolean) set_quality_ratings JPP((j_compress_ptr cinfo, char *arg, - boolean force_baseline)); -EXTERN(boolean) set_quant_slots JPP((j_compress_ptr cinfo, char *arg)); -EXTERN(boolean) set_sample_factors JPP((j_compress_ptr cinfo, char *arg)); - -/* djpeg support routines (in rdcolmap.c) */ - -EXTERN(void) read_color_map JPP((j_decompress_ptr cinfo, FILE * infile)); - -/* common support routines (in cdjpeg.c) */ - -EXTERN(void) enable_signal_catcher JPP((j_common_ptr cinfo)); -EXTERN(void) start_progress_monitor JPP((j_common_ptr cinfo, - cd_progress_ptr progress)); -EXTERN(void) end_progress_monitor JPP((j_common_ptr cinfo)); -EXTERN(boolean) keymatch JPP((char * arg, const char * keyword, int minchars)); -EXTERN(FILE *) read_stdin JPP((void)); -EXTERN(FILE *) write_stdout JPP((void)); - -/* miscellaneous useful macros */ - -#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */ -#define READ_BINARY "r" -#define WRITE_BINARY "w" -#else -#ifdef VMS /* VMS is very nonstandard */ -#define READ_BINARY "rb", "ctx=stm" -#define WRITE_BINARY "wb", "ctx=stm" -#else /* standard ANSI-compliant case */ -#define READ_BINARY "rb" -#define WRITE_BINARY "wb" -#endif -#endif - -#ifndef EXIT_FAILURE /* define exit() codes if not provided */ -#define EXIT_FAILURE 1 -#endif -#ifndef EXIT_SUCCESS -#ifdef VMS -#define EXIT_SUCCESS 1 /* VMS is very nonstandard */ -#else -#define EXIT_SUCCESS 0 -#endif -#endif -#ifndef EXIT_WARNING -#ifdef VMS -#define EXIT_WARNING 1 /* VMS is very nonstandard */ -#else -#define EXIT_WARNING 2 -#endif -#endif diff --git a/reactos/dll/3rdparty/libjpeg/jconfig.h b/reactos/dll/3rdparty/libjpeg/jconfig.h deleted file mode 100644 index 99172ce91c2..00000000000 --- a/reactos/dll/3rdparty/libjpeg/jconfig.h +++ /dev/null @@ -1,18 +0,0 @@ -#define HAVE_PROTOTYPES -#define HAVE_UNSIGNED_CHAR - -#define HAVE_STDDEF_H -#define HAVE_STDLIB_H - -#ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */ -typedef unsigned char boolean; -#endif -#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */ - -#undef NEED_BSD_STRINGS -#undef NEED_SYS_TYPES_H -#undef NEED_FAR_POINTERS /* we presume a 32-bit flat memory model */ -#undef NEED_SHORT_EXTERNAL_NAMES -#undef INCOMPLETE_TYPES_BROKEN - -// typedef long INT32; diff --git a/reactos/dll/3rdparty/libjpeg/jdct.h b/reactos/dll/3rdparty/libjpeg/jdct.h deleted file mode 100644 index 360dec80c94..00000000000 --- a/reactos/dll/3rdparty/libjpeg/jdct.h +++ /dev/null @@ -1,393 +0,0 @@ -/* - * jdct.h - * - * Copyright (C) 1994-1996, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This include file contains common declarations for the forward and - * inverse DCT modules. These declarations are private to the DCT managers - * (jcdctmgr.c, jddctmgr.c) and the individual DCT algorithms. - * The individual DCT algorithms are kept in separate files to ease - * machine-dependent tuning (e.g., assembly coding). - */ - - -/* - * A forward DCT routine is given a pointer to an input sample array and - * a pointer to a work area of type DCTELEM[]; the DCT is to be performed - * in-place in that buffer. Type DCTELEM is int for 8-bit samples, INT32 - * for 12-bit samples. (NOTE: Floating-point DCT implementations use an - * array of type FAST_FLOAT, instead.) - * The input data is to be fetched from the sample array starting at a - * specified column. (Any row offset needed will be applied to the array - * pointer before it is passed to the FDCT code.) - * Note that the number of samples fetched by the FDCT routine is - * DCT_h_scaled_size * DCT_v_scaled_size. - * The DCT outputs are returned scaled up by a factor of 8; they therefore - * have a range of +-8K for 8-bit data, +-128K for 12-bit data. This - * convention improves accuracy in integer implementations and saves some - * work in floating-point ones. - * Quantization of the output coefficients is done by jcdctmgr.c. - */ - -#if BITS_IN_JSAMPLE == 8 -typedef int DCTELEM; /* 16 or 32 bits is fine */ -#else -typedef INT32 DCTELEM; /* must have 32 bits */ -#endif - -typedef JMETHOD(void, forward_DCT_method_ptr, (DCTELEM * data, - JSAMPARRAY sample_data, - JDIMENSION start_col)); -typedef JMETHOD(void, float_DCT_method_ptr, (FAST_FLOAT * data, - JSAMPARRAY sample_data, - JDIMENSION start_col)); - - -/* - * An inverse DCT routine is given a pointer to the input JBLOCK and a pointer - * to an output sample array. The routine must dequantize the input data as - * well as perform the IDCT; for dequantization, it uses the multiplier table - * pointed to by compptr->dct_table. The output data is to be placed into the - * sample array starting at a specified column. (Any row offset needed will - * be applied to the array pointer before it is passed to the IDCT code.) - * Note that the number of samples emitted by the IDCT routine is - * DCT_h_scaled_size * DCT_v_scaled_size. - */ - -/* typedef inverse_DCT_method_ptr is declared in jpegint.h */ - -/* - * Each IDCT routine has its own ideas about the best dct_table element type. - */ - -typedef MULTIPLIER ISLOW_MULT_TYPE; /* short or int, whichever is faster */ -#if BITS_IN_JSAMPLE == 8 -typedef MULTIPLIER IFAST_MULT_TYPE; /* 16 bits is OK, use short if faster */ -#define IFAST_SCALE_BITS 2 /* fractional bits in scale factors */ -#else -typedef INT32 IFAST_MULT_TYPE; /* need 32 bits for scaled quantizers */ -#define IFAST_SCALE_BITS 13 /* fractional bits in scale factors */ -#endif -typedef FAST_FLOAT FLOAT_MULT_TYPE; /* preferred floating type */ - - -/* - * Each IDCT routine is responsible for range-limiting its results and - * converting them to unsigned form (0..MAXJSAMPLE). The raw outputs could - * be quite far out of range if the input data is corrupt, so a bulletproof - * range-limiting step is required. We use a mask-and-table-lookup method - * to do the combined operations quickly. See the comments with - * prepare_range_limit_table (in jdmaster.c) for more info. - */ - -#define IDCT_range_limit(cinfo) ((cinfo)->sample_range_limit + CENTERJSAMPLE) - -#define RANGE_MASK (MAXJSAMPLE * 4 + 3) /* 2 bits wider than legal samples */ - - -/* Short forms of external names for systems with brain-damaged linkers. */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jpeg_fdct_islow jFDislow -#define jpeg_fdct_ifast jFDifast -#define jpeg_fdct_float jFDfloat -#define jpeg_fdct_7x7 jFD7x7 -#define jpeg_fdct_6x6 jFD6x6 -#define jpeg_fdct_5x5 jFD5x5 -#define jpeg_fdct_4x4 jFD4x4 -#define jpeg_fdct_3x3 jFD3x3 -#define jpeg_fdct_2x2 jFD2x2 -#define jpeg_fdct_1x1 jFD1x1 -#define jpeg_fdct_9x9 jFD9x9 -#define jpeg_fdct_10x10 jFD10x10 -#define jpeg_fdct_11x11 jFD11x11 -#define jpeg_fdct_12x12 jFD12x12 -#define jpeg_fdct_13x13 jFD13x13 -#define jpeg_fdct_14x14 jFD14x14 -#define jpeg_fdct_15x15 jFD15x15 -#define jpeg_fdct_16x16 jFD16x16 -#define jpeg_fdct_16x8 jFD16x8 -#define jpeg_fdct_14x7 jFD14x7 -#define jpeg_fdct_12x6 jFD12x6 -#define jpeg_fdct_10x5 jFD10x5 -#define jpeg_fdct_8x4 jFD8x4 -#define jpeg_fdct_6x3 jFD6x3 -#define jpeg_fdct_4x2 jFD4x2 -#define jpeg_fdct_2x1 jFD2x1 -#define jpeg_fdct_8x16 jFD8x16 -#define jpeg_fdct_7x14 jFD7x14 -#define jpeg_fdct_6x12 jFD6x12 -#define jpeg_fdct_5x10 jFD5x10 -#define jpeg_fdct_4x8 jFD4x8 -#define jpeg_fdct_3x6 jFD3x6 -#define jpeg_fdct_2x4 jFD2x4 -#define jpeg_fdct_1x2 jFD1x2 -#define jpeg_idct_islow jRDislow -#define jpeg_idct_ifast jRDifast -#define jpeg_idct_float jRDfloat -#define jpeg_idct_7x7 jRD7x7 -#define jpeg_idct_6x6 jRD6x6 -#define jpeg_idct_5x5 jRD5x5 -#define jpeg_idct_4x4 jRD4x4 -#define jpeg_idct_3x3 jRD3x3 -#define jpeg_idct_2x2 jRD2x2 -#define jpeg_idct_1x1 jRD1x1 -#define jpeg_idct_9x9 jRD9x9 -#define jpeg_idct_10x10 jRD10x10 -#define jpeg_idct_11x11 jRD11x11 -#define jpeg_idct_12x12 jRD12x12 -#define jpeg_idct_13x13 jRD13x13 -#define jpeg_idct_14x14 jRD14x14 -#define jpeg_idct_15x15 jRD15x15 -#define jpeg_idct_16x16 jRD16x16 -#define jpeg_idct_16x8 jRD16x8 -#define jpeg_idct_14x7 jRD14x7 -#define jpeg_idct_12x6 jRD12x6 -#define jpeg_idct_10x5 jRD10x5 -#define jpeg_idct_8x4 jRD8x4 -#define jpeg_idct_6x3 jRD6x3 -#define jpeg_idct_4x2 jRD4x2 -#define jpeg_idct_2x1 jRD2x1 -#define jpeg_idct_8x16 jRD8x16 -#define jpeg_idct_7x14 jRD7x14 -#define jpeg_idct_6x12 jRD6x12 -#define jpeg_idct_5x10 jRD5x10 -#define jpeg_idct_4x8 jRD4x8 -#define jpeg_idct_3x6 jRD3x8 -#define jpeg_idct_2x4 jRD2x4 -#define jpeg_idct_1x2 jRD1x2 -#endif /* NEED_SHORT_EXTERNAL_NAMES */ - -/* Extern declarations for the forward and inverse DCT routines. */ - -EXTERN(void) jpeg_fdct_islow - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_ifast - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_float - JPP((FAST_FLOAT * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_7x7 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_6x6 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_5x5 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_4x4 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_3x3 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_2x2 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_1x1 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_9x9 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_10x10 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_11x11 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_12x12 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_13x13 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_14x14 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_15x15 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_16x16 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_16x8 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_14x7 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_12x6 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_10x5 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_8x4 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_6x3 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_4x2 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_2x1 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_8x16 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_7x14 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_6x12 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_5x10 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_4x8 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_3x6 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_2x4 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); -EXTERN(void) jpeg_fdct_1x2 - JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)); - -EXTERN(void) jpeg_idct_islow - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_ifast - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_float - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_7x7 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_6x6 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_5x5 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_4x4 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_3x3 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_2x2 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_1x1 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_9x9 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_10x10 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_11x11 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_12x12 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_13x13 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_14x14 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_15x15 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_16x16 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_16x8 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_14x7 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_12x6 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_10x5 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_8x4 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_6x3 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_4x2 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_2x1 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_8x16 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_7x14 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_6x12 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_5x10 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_4x8 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_3x6 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_2x4 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); -EXTERN(void) jpeg_idct_1x2 - JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); - - -/* - * Macros for handling fixed-point arithmetic; these are used by many - * but not all of the DCT/IDCT modules. - * - * All values are expected to be of type INT32. - * Fractional constants are scaled left by CONST_BITS bits. - * CONST_BITS is defined within each module using these macros, - * and may differ from one module to the next. - */ - -#define ONE ((INT32) 1) -#define CONST_SCALE (ONE << CONST_BITS) - -/* Convert a positive real constant to an integer scaled by CONST_SCALE. - * Caution: some C compilers fail to reduce "FIX(constant)" at compile time, - * thus causing a lot of useless floating-point operations at run time. - */ - -#define FIX(x) ((INT32) ((x) * CONST_SCALE + 0.5)) - -/* Descale and correctly round an INT32 value that's scaled by N bits. - * We assume RIGHT_SHIFT rounds towards minus infinity, so adding - * the fudge factor is correct for either sign of X. - */ - -#define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n) - -/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. - * This macro is used only when the two inputs will actually be no more than - * 16 bits wide, so that a 16x16->32 bit multiply can be used instead of a - * full 32x32 multiply. This provides a useful speedup on many machines. - * Unfortunately there is no way to specify a 16x16->32 multiply portably - * in C, but some C compilers will do the right thing if you provide the - * correct combination of casts. - */ - -#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ -#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT16) (const))) -#endif -#ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */ -#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT32) (const))) -#endif - -#ifndef MULTIPLY16C16 /* default definition */ -#define MULTIPLY16C16(var,const) ((var) * (const)) -#endif - -/* Same except both inputs are variables. */ - -#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ -#define MULTIPLY16V16(var1,var2) (((INT16) (var1)) * ((INT16) (var2))) -#endif - -#ifndef MULTIPLY16V16 /* default definition */ -#define MULTIPLY16V16(var1,var2) ((var1) * (var2)) -#endif diff --git a/reactos/dll/3rdparty/libjpeg/jerror.h b/reactos/dll/3rdparty/libjpeg/jerror.h deleted file mode 100644 index 1cfb2b19d85..00000000000 --- a/reactos/dll/3rdparty/libjpeg/jerror.h +++ /dev/null @@ -1,304 +0,0 @@ -/* - * jerror.h - * - * Copyright (C) 1994-1997, Thomas G. Lane. - * Modified 1997-2009 by Guido Vollbeding. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file defines the error and message codes for the JPEG library. - * Edit this file to add new codes, or to translate the message strings to - * some other language. - * A set of error-reporting macros are defined too. Some applications using - * the JPEG library may wish to include this file to get the error codes - * and/or the macros. - */ - -/* - * To define the enum list of message codes, include this file without - * defining macro JMESSAGE. To create a message string table, include it - * again with a suitable JMESSAGE definition (see jerror.c for an example). - */ -#ifndef JMESSAGE -#ifndef JERROR_H -/* First time through, define the enum list */ -#define JMAKE_ENUM_LIST -#else -/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */ -#define JMESSAGE(code,string) -#endif /* JERROR_H */ -#endif /* JMESSAGE */ - -#ifdef JMAKE_ENUM_LIST - -typedef enum { - -#define JMESSAGE(code,string) code , - -#endif /* JMAKE_ENUM_LIST */ - -JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */ - -/* For maintenance convenience, list is alphabetical by message code name */ -JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix") -JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix") -JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode") -JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS") -JMESSAGE(JERR_BAD_CROP_SPEC, "Invalid crop request") -JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range") -JMESSAGE(JERR_BAD_DCTSIZE, "DCT scaled block size %dx%d not supported") -JMESSAGE(JERR_BAD_DROP_SAMPLING, - "Component index %d: mismatching sampling ratio %d:%d, %d:%d, %c") -JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition") -JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace") -JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace") -JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length") -JMESSAGE(JERR_BAD_LIB_VERSION, - "Wrong JPEG library version: library is %d, caller expects %d") -JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan") -JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d") -JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d") -JMESSAGE(JERR_BAD_PROGRESSION, - "Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d") -JMESSAGE(JERR_BAD_PROG_SCRIPT, - "Invalid progressive parameters at scan script entry %d") -JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors") -JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d") -JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d") -JMESSAGE(JERR_BAD_STRUCT_SIZE, - "JPEG parameter struct mismatch: library thinks size is %u, caller expects %u") -JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access") -JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small") -JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here") -JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet") -JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d") -JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request") -JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d") -JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x") -JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d") -JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d") -JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)") -JMESSAGE(JERR_EMS_READ, "Read from EMS failed") -JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed") -JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan") -JMESSAGE(JERR_FILE_READ, "Input file read error") -JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?") -JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet") -JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow") -JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry") -JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels") -JMESSAGE(JERR_INPUT_EMPTY, "Empty input file") -JMESSAGE(JERR_INPUT_EOF, "Premature end of input file") -JMESSAGE(JERR_MISMATCHED_QUANT_TABLE, - "Cannot transcode due to multiple use of quantization table %d") -JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data") -JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change") -JMESSAGE(JERR_NOTIMPL, "Not implemented yet") -JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time") -JMESSAGE(JERR_NO_ARITH_TABLE, "Arithmetic table 0x%02x was not defined") -JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported") -JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined") -JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image") -JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined") -JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x") -JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)") -JMESSAGE(JERR_QUANT_COMPONENTS, - "Cannot quantize more than %d color components") -JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors") -JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors") -JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers") -JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker") -JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x") -JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers") -JMESSAGE(JERR_SOS_NO_SOF, "Invalid JPEG file structure: SOS before SOF") -JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s") -JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file") -JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file") -JMESSAGE(JERR_TFILE_WRITE, - "Write failed on temporary file --- out of disk space?") -JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines") -JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x") -JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up") -JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation") -JMESSAGE(JERR_XMS_READ, "Read from XMS failed") -JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed") -JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT) -JMESSAGE(JMSG_VERSION, JVERSION) -JMESSAGE(JTRC_16BIT_TABLES, - "Caution: quantization tables are too coarse for baseline JPEG") -JMESSAGE(JTRC_ADOBE, - "Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d") -JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u") -JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u") -JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x") -JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x") -JMESSAGE(JTRC_DQT, "Define Quantization Table %d precision %d") -JMESSAGE(JTRC_DRI, "Define Restart Interval %u") -JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u") -JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u") -JMESSAGE(JTRC_EOI, "End Of Image") -JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d") -JMESSAGE(JTRC_JFIF, "JFIF APP0 marker: version %d.%02d, density %dx%d %d") -JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE, - "Warning: thumbnail image size does not match data length %u") -JMESSAGE(JTRC_JFIF_EXTENSION, - "JFIF extension marker: type 0x%02x, length %u") -JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image") -JMESSAGE(JTRC_MISC_MARKER, "Miscellaneous marker 0x%02x, length %u") -JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x") -JMESSAGE(JTRC_QUANTVALS, " %4u %4u %4u %4u %4u %4u %4u %4u") -JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors") -JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors") -JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization") -JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d") -JMESSAGE(JTRC_RST, "RST%d") -JMESSAGE(JTRC_SMOOTH_NOTIMPL, - "Smoothing not supported with nonstandard sampling ratios") -JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d") -JMESSAGE(JTRC_SOF_COMPONENT, " Component %d: %dhx%dv q=%d") -JMESSAGE(JTRC_SOI, "Start of Image") -JMESSAGE(JTRC_SOS, "Start Of Scan: %d components") -JMESSAGE(JTRC_SOS_COMPONENT, " Component %d: dc=%d ac=%d") -JMESSAGE(JTRC_SOS_PARAMS, " Ss=%d, Se=%d, Ah=%d, Al=%d") -JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s") -JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s") -JMESSAGE(JTRC_THUMB_JPEG, - "JFIF extension marker: JPEG-compressed thumbnail image, length %u") -JMESSAGE(JTRC_THUMB_PALETTE, - "JFIF extension marker: palette thumbnail image, length %u") -JMESSAGE(JTRC_THUMB_RGB, - "JFIF extension marker: RGB thumbnail image, length %u") -JMESSAGE(JTRC_UNKNOWN_IDS, - "Unrecognized component IDs %d %d %d, assuming YCbCr") -JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u") -JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u") -JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d") -JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code") -JMESSAGE(JWRN_BOGUS_PROGRESSION, - "Inconsistent progression sequence for component %d coefficient %d") -JMESSAGE(JWRN_EXTRANEOUS_DATA, - "Corrupt JPEG data: %u extraneous bytes before marker 0x%02x") -JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment") -JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code") -JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d") -JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file") -JMESSAGE(JWRN_MUST_RESYNC, - "Corrupt JPEG data: found marker 0x%02x instead of RST%d") -JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG") -JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines") - -#ifdef JMAKE_ENUM_LIST - - JMSG_LASTMSGCODE -} J_MESSAGE_CODE; - -#undef JMAKE_ENUM_LIST -#endif /* JMAKE_ENUM_LIST */ - -/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */ -#undef JMESSAGE - - -#ifndef JERROR_H -#define JERROR_H - -/* Macros to simplify using the error and trace message stuff */ -/* The first parameter is either type of cinfo pointer */ - -/* Fatal errors (print message and exit) */ -#define ERREXIT(cinfo,code) \ - ((cinfo)->err->msg_code = (code), \ - (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) -#define ERREXIT1(cinfo,code,p1) \ - ((cinfo)->err->msg_code = (code), \ - (cinfo)->err->msg_parm.i[0] = (p1), \ - (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) -#define ERREXIT2(cinfo,code,p1,p2) \ - ((cinfo)->err->msg_code = (code), \ - (cinfo)->err->msg_parm.i[0] = (p1), \ - (cinfo)->err->msg_parm.i[1] = (p2), \ - (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) -#define ERREXIT3(cinfo,code,p1,p2,p3) \ - ((cinfo)->err->msg_code = (code), \ - (cinfo)->err->msg_parm.i[0] = (p1), \ - (cinfo)->err->msg_parm.i[1] = (p2), \ - (cinfo)->err->msg_parm.i[2] = (p3), \ - (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) -#define ERREXIT4(cinfo,code,p1,p2,p3,p4) \ - ((cinfo)->err->msg_code = (code), \ - (cinfo)->err->msg_parm.i[0] = (p1), \ - (cinfo)->err->msg_parm.i[1] = (p2), \ - (cinfo)->err->msg_parm.i[2] = (p3), \ - (cinfo)->err->msg_parm.i[3] = (p4), \ - (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) -#define ERREXIT6(cinfo,code,p1,p2,p3,p4,p5,p6) \ - ((cinfo)->err->msg_code = (code), \ - (cinfo)->err->msg_parm.i[0] = (p1), \ - (cinfo)->err->msg_parm.i[1] = (p2), \ - (cinfo)->err->msg_parm.i[2] = (p3), \ - (cinfo)->err->msg_parm.i[3] = (p4), \ - (cinfo)->err->msg_parm.i[4] = (p5), \ - (cinfo)->err->msg_parm.i[5] = (p6), \ - (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) -#define ERREXITS(cinfo,code,str) \ - ((cinfo)->err->msg_code = (code), \ - strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ - (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) - -#define MAKESTMT(stuff) do { stuff } while (0) - -/* Nonfatal errors (we can keep going, but the data is probably corrupt) */ -#define WARNMS(cinfo,code) \ - ((cinfo)->err->msg_code = (code), \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) -#define WARNMS1(cinfo,code,p1) \ - ((cinfo)->err->msg_code = (code), \ - (cinfo)->err->msg_parm.i[0] = (p1), \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) -#define WARNMS2(cinfo,code,p1,p2) \ - ((cinfo)->err->msg_code = (code), \ - (cinfo)->err->msg_parm.i[0] = (p1), \ - (cinfo)->err->msg_parm.i[1] = (p2), \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) - -/* Informational/debugging messages */ -#define TRACEMS(cinfo,lvl,code) \ - ((cinfo)->err->msg_code = (code), \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) -#define TRACEMS1(cinfo,lvl,code,p1) \ - ((cinfo)->err->msg_code = (code), \ - (cinfo)->err->msg_parm.i[0] = (p1), \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) -#define TRACEMS2(cinfo,lvl,code,p1,p2) \ - ((cinfo)->err->msg_code = (code), \ - (cinfo)->err->msg_parm.i[0] = (p1), \ - (cinfo)->err->msg_parm.i[1] = (p2), \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) -#define TRACEMS3(cinfo,lvl,code,p1,p2,p3) \ - MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ - _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \ - (cinfo)->err->msg_code = (code); \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) -#define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) \ - MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ - _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ - (cinfo)->err->msg_code = (code); \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) -#define TRACEMS5(cinfo,lvl,code,p1,p2,p3,p4,p5) \ - MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ - _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ - _mp[4] = (p5); \ - (cinfo)->err->msg_code = (code); \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) -#define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) \ - MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ - _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ - _mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \ - (cinfo)->err->msg_code = (code); \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) -#define TRACEMSS(cinfo,lvl,code,str) \ - ((cinfo)->err->msg_code = (code), \ - strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) - -#endif /* JERROR_H */ diff --git a/reactos/dll/3rdparty/libjpeg/jinclude.h b/reactos/dll/3rdparty/libjpeg/jinclude.h deleted file mode 100644 index 0a4f15146ae..00000000000 --- a/reactos/dll/3rdparty/libjpeg/jinclude.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * jinclude.h - * - * Copyright (C) 1991-1994, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file exists to provide a single place to fix any problems with - * including the wrong system include files. (Common problems are taken - * care of by the standard jconfig symbols, but on really weird systems - * you may have to edit this file.) - * - * NOTE: this file is NOT intended to be included by applications using the - * JPEG library. Most applications need only include jpeglib.h. - */ - - -/* Include auto-config file to find out which system include files we need. */ - -#include "jconfig.h" /* auto configuration options */ -#define JCONFIG_INCLUDED /* so that jpeglib.h doesn't do it again */ - -/* - * We need the NULL macro and size_t typedef. - * On an ANSI-conforming system it is sufficient to include . - * Otherwise, we get them from or ; we may have to - * pull in as well. - * Note that the core JPEG library does not require ; - * only the default error handler and data source/destination modules do. - * But we must pull it in because of the references to FILE in jpeglib.h. - * You can remove those references if you want to compile without . - */ - -#ifdef HAVE_STDDEF_H -#include -#endif - -#ifdef HAVE_STDLIB_H -#include -#endif - -#ifdef NEED_SYS_TYPES_H -#include -#endif - -#include - -/* - * We need memory copying and zeroing functions, plus strncpy(). - * ANSI and System V implementations declare these in . - * BSD doesn't have the mem() functions, but it does have bcopy()/bzero(). - * Some systems may declare memset and memcpy in . - * - * NOTE: we assume the size parameters to these functions are of type size_t. - * Change the casts in these macros if not! - */ - -#ifdef NEED_BSD_STRINGS - -#include -#define MEMZERO(target,size) bzero((void *)(target), (size_t)(size)) -#define MEMCOPY(dest,src,size) bcopy((const void *)(src), (void *)(dest), (size_t)(size)) - -#else /* not BSD, assume ANSI/SysV string lib */ - -#include -#define MEMZERO(target,size) memset((void *)(target), 0, (size_t)(size)) -#define MEMCOPY(dest,src,size) memcpy((void *)(dest), (const void *)(src), (size_t)(size)) - -#endif - -/* - * In ANSI C, and indeed any rational implementation, size_t is also the - * type returned by sizeof(). However, it seems there are some irrational - * implementations out there, in which sizeof() returns an int even though - * size_t is defined as long or unsigned long. To ensure consistent results - * we always use this SIZEOF() macro in place of using sizeof() directly. - */ - -#define SIZEOF(object) ((size_t) sizeof(object)) - -/* - * The modules that use fread() and fwrite() always invoke them through - * these macros. On some systems you may need to twiddle the argument casts. - * CAUTION: argument order is different from underlying functions! - */ - -#define JFREAD(file,buf,sizeofbuf) \ - ((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) -#define JFWRITE(file,buf,sizeofbuf) \ - ((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) diff --git a/reactos/dll/3rdparty/libjpeg/jmemsys.h b/reactos/dll/3rdparty/libjpeg/jmemsys.h deleted file mode 100644 index 6c3c6d348f2..00000000000 --- a/reactos/dll/3rdparty/libjpeg/jmemsys.h +++ /dev/null @@ -1,198 +0,0 @@ -/* - * jmemsys.h - * - * Copyright (C) 1992-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This include file defines the interface between the system-independent - * and system-dependent portions of the JPEG memory manager. No other - * modules need include it. (The system-independent portion is jmemmgr.c; - * there are several different versions of the system-dependent portion.) - * - * This file works as-is for the system-dependent memory managers supplied - * in the IJG distribution. You may need to modify it if you write a - * custom memory manager. If system-dependent changes are needed in - * this file, the best method is to #ifdef them based on a configuration - * symbol supplied in jconfig.h, as we have done with USE_MSDOS_MEMMGR - * and USE_MAC_MEMMGR. - */ - - -/* Short forms of external names for systems with brain-damaged linkers. */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jpeg_get_small jGetSmall -#define jpeg_free_small jFreeSmall -#define jpeg_get_large jGetLarge -#define jpeg_free_large jFreeLarge -#define jpeg_mem_available jMemAvail -#define jpeg_open_backing_store jOpenBackStore -#define jpeg_mem_init jMemInit -#define jpeg_mem_term jMemTerm -#endif /* NEED_SHORT_EXTERNAL_NAMES */ - - -/* - * These two functions are used to allocate and release small chunks of - * memory. (Typically the total amount requested through jpeg_get_small is - * no more than 20K or so; this will be requested in chunks of a few K each.) - * Behavior should be the same as for the standard library functions malloc - * and free; in particular, jpeg_get_small must return NULL on failure. - * On most systems, these ARE malloc and free. jpeg_free_small is passed the - * size of the object being freed, just in case it's needed. - * On an 80x86 machine using small-data memory model, these manage near heap. - */ - -EXTERN(void *) jpeg_get_small JPP((j_common_ptr cinfo, size_t sizeofobject)); -EXTERN(void) jpeg_free_small JPP((j_common_ptr cinfo, void * object, - size_t sizeofobject)); - -/* - * These two functions are used to allocate and release large chunks of - * memory (up to the total free space designated by jpeg_mem_available). - * The interface is the same as above, except that on an 80x86 machine, - * far pointers are used. On most other machines these are identical to - * the jpeg_get/free_small routines; but we keep them separate anyway, - * in case a different allocation strategy is desirable for large chunks. - */ - -EXTERN(void FAR *) jpeg_get_large JPP((j_common_ptr cinfo, - size_t sizeofobject)); -EXTERN(void) jpeg_free_large JPP((j_common_ptr cinfo, void FAR * object, - size_t sizeofobject)); - -/* - * The macro MAX_ALLOC_CHUNK designates the maximum number of bytes that may - * be requested in a single call to jpeg_get_large (and jpeg_get_small for that - * matter, but that case should never come into play). This macro is needed - * to model the 64Kb-segment-size limit of far addressing on 80x86 machines. - * On those machines, we expect that jconfig.h will provide a proper value. - * On machines with 32-bit flat address spaces, any large constant may be used. - * - * NB: jmemmgr.c expects that MAX_ALLOC_CHUNK will be representable as type - * size_t and will be a multiple of sizeof(align_type). - */ - -#ifndef MAX_ALLOC_CHUNK /* may be overridden in jconfig.h */ -#define MAX_ALLOC_CHUNK 1000000000L -#endif - -/* - * This routine computes the total space still available for allocation by - * jpeg_get_large. If more space than this is needed, backing store will be - * used. NOTE: any memory already allocated must not be counted. - * - * There is a minimum space requirement, corresponding to the minimum - * feasible buffer sizes; jmemmgr.c will request that much space even if - * jpeg_mem_available returns zero. The maximum space needed, enough to hold - * all working storage in memory, is also passed in case it is useful. - * Finally, the total space already allocated is passed. If no better - * method is available, cinfo->mem->max_memory_to_use - already_allocated - * is often a suitable calculation. - * - * It is OK for jpeg_mem_available to underestimate the space available - * (that'll just lead to more backing-store access than is really necessary). - * However, an overestimate will lead to failure. Hence it's wise to subtract - * a slop factor from the true available space. 5% should be enough. - * - * On machines with lots of virtual memory, any large constant may be returned. - * Conversely, zero may be returned to always use the minimum amount of memory. - */ - -EXTERN(long) jpeg_mem_available JPP((j_common_ptr cinfo, - long min_bytes_needed, - long max_bytes_needed, - long already_allocated)); - - -/* - * This structure holds whatever state is needed to access a single - * backing-store object. The read/write/close method pointers are called - * by jmemmgr.c to manipulate the backing-store object; all other fields - * are private to the system-dependent backing store routines. - */ - -#define TEMP_NAME_LENGTH 64 /* max length of a temporary file's name */ - - -#ifdef USE_MSDOS_MEMMGR /* DOS-specific junk */ - -typedef unsigned short XMSH; /* type of extended-memory handles */ -typedef unsigned short EMSH; /* type of expanded-memory handles */ - -typedef union { - short file_handle; /* DOS file handle if it's a temp file */ - XMSH xms_handle; /* handle if it's a chunk of XMS */ - EMSH ems_handle; /* handle if it's a chunk of EMS */ -} handle_union; - -#endif /* USE_MSDOS_MEMMGR */ - -#ifdef USE_MAC_MEMMGR /* Mac-specific junk */ -#include -#endif /* USE_MAC_MEMMGR */ - - -typedef struct backing_store_struct * backing_store_ptr; - -typedef struct backing_store_struct { - /* Methods for reading/writing/closing this backing-store object */ - JMETHOD(void, read_backing_store, (j_common_ptr cinfo, - backing_store_ptr info, - void FAR * buffer_address, - long file_offset, long byte_count)); - JMETHOD(void, write_backing_store, (j_common_ptr cinfo, - backing_store_ptr info, - void FAR * buffer_address, - long file_offset, long byte_count)); - JMETHOD(void, close_backing_store, (j_common_ptr cinfo, - backing_store_ptr info)); - - /* Private fields for system-dependent backing-store management */ -#ifdef USE_MSDOS_MEMMGR - /* For the MS-DOS manager (jmemdos.c), we need: */ - handle_union handle; /* reference to backing-store storage object */ - char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */ -#else -#ifdef USE_MAC_MEMMGR - /* For the Mac manager (jmemmac.c), we need: */ - short temp_file; /* file reference number to temp file */ - FSSpec tempSpec; /* the FSSpec for the temp file */ - char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */ -#else - /* For a typical implementation with temp files, we need: */ - FILE * temp_file; /* stdio reference to temp file */ - char temp_name[TEMP_NAME_LENGTH]; /* name of temp file */ -#endif -#endif -} backing_store_info; - - -/* - * Initial opening of a backing-store object. This must fill in the - * read/write/close pointers in the object. The read/write routines - * may take an error exit if the specified maximum file size is exceeded. - * (If jpeg_mem_available always returns a large value, this routine can - * just take an error exit.) - */ - -EXTERN(void) jpeg_open_backing_store JPP((j_common_ptr cinfo, - backing_store_ptr info, - long total_bytes_needed)); - - -/* - * These routines take care of any system-dependent initialization and - * cleanup required. jpeg_mem_init will be called before anything is - * allocated (and, therefore, nothing in cinfo is of use except the error - * manager pointer). It should return a suitable default value for - * max_memory_to_use; this may subsequently be overridden by the surrounding - * application. (Note that max_memory_to_use is only important if - * jpeg_mem_available chooses to consult it ... no one else will.) - * jpeg_mem_term may assume that all requested memory has been freed and that - * all opened backing-store objects have been closed. - */ - -EXTERN(long) jpeg_mem_init JPP((j_common_ptr cinfo)); -EXTERN(void) jpeg_mem_term JPP((j_common_ptr cinfo)); diff --git a/reactos/dll/3rdparty/libjpeg/jmorecfg.h b/reactos/dll/3rdparty/libjpeg/jmorecfg.h deleted file mode 100644 index a9478f460bd..00000000000 --- a/reactos/dll/3rdparty/libjpeg/jmorecfg.h +++ /dev/null @@ -1,375 +0,0 @@ -/* - * jmorecfg.h - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * Modified 1997-2009 by Guido Vollbeding. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains additional configuration options that customize the - * JPEG software for special applications or support machine-dependent - * optimizations. Most users will not need to touch this file. - */ - - -/* - * Define BITS_IN_JSAMPLE as either - * 8 for 8-bit sample values (the usual setting) - * 12 for 12-bit sample values - * Only 8 and 12 are legal data precisions for lossy JPEG according to the - * JPEG standard, and the IJG code does not support anything else! - * We do not support run-time selection of data precision, sorry. - */ - -#define BITS_IN_JSAMPLE 8 /* use 8 or 12 */ - -#if (defined (_MSC_VER) && (_MSC_VER >= 800)) -#define HAVE_UNSIGNED_CHAR -#define EXTERN(type) extern type __cdecl -#endif - -/* - * Maximum number of components (color channels) allowed in JPEG image. - * To meet the letter of the JPEG spec, set this to 255. However, darn - * few applications need more than 4 channels (maybe 5 for CMYK + alpha - * mask). We recommend 10 as a reasonable compromise; use 4 if you are - * really short on memory. (Each allowed component costs a hundred or so - * bytes of storage, whether actually used in an image or not.) - */ - -#define MAX_COMPONENTS 10 /* maximum number of image components */ - - -/* - * Basic data types. - * You may need to change these if you have a machine with unusual data - * type sizes; for example, "char" not 8 bits, "short" not 16 bits, - * or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits, - * but it had better be at least 16. - */ - -/* Representation of a single sample (pixel element value). - * We frequently allocate large arrays of these, so it's important to keep - * them small. But if you have memory to burn and access to char or short - * arrays is very slow on your hardware, you might want to change these. - */ - -#if BITS_IN_JSAMPLE == 8 -/* JSAMPLE should be the smallest type that will hold the values 0..255. - * You can use a signed char by having GETJSAMPLE mask it with 0xFF. - */ - -#ifdef HAVE_UNSIGNED_CHAR - -typedef unsigned char JSAMPLE; -#define GETJSAMPLE(value) ((int) (value)) - -#else /* not HAVE_UNSIGNED_CHAR */ - -typedef char JSAMPLE; -#ifdef CHAR_IS_UNSIGNED -#define GETJSAMPLE(value) ((int) (value)) -#else -#define GETJSAMPLE(value) ((int) (value) & 0xFF) -#endif /* CHAR_IS_UNSIGNED */ - -#endif /* HAVE_UNSIGNED_CHAR */ - -#define MAXJSAMPLE 255 -#define CENTERJSAMPLE 128 - -#endif /* BITS_IN_JSAMPLE == 8 */ - - -#if BITS_IN_JSAMPLE == 12 -/* JSAMPLE should be the smallest type that will hold the values 0..4095. - * On nearly all machines "short" will do nicely. - */ - -typedef short JSAMPLE; -#define GETJSAMPLE(value) ((int) (value)) - -#define MAXJSAMPLE 4095 -#define CENTERJSAMPLE 2048 - -#endif /* BITS_IN_JSAMPLE == 12 */ - - -/* Representation of a DCT frequency coefficient. - * This should be a signed value of at least 16 bits; "short" is usually OK. - * Again, we allocate large arrays of these, but you can change to int - * if you have memory to burn and "short" is really slow. - */ - -typedef short JCOEF; - - -/* Compressed datastreams are represented as arrays of JOCTET. - * These must be EXACTLY 8 bits wide, at least once they are written to - * external storage. Note that when using the stdio data source/destination - * managers, this is also the data type passed to fread/fwrite. - */ - -#ifdef HAVE_UNSIGNED_CHAR - -typedef unsigned char JOCTET; -#define GETJOCTET(value) (value) - -#else /* not HAVE_UNSIGNED_CHAR */ - -typedef char JOCTET; -#ifdef CHAR_IS_UNSIGNED -#define GETJOCTET(value) (value) -#else -#define GETJOCTET(value) ((value) & 0xFF) -#endif /* CHAR_IS_UNSIGNED */ - -#endif /* HAVE_UNSIGNED_CHAR */ - - -/* These typedefs are used for various table entries and so forth. - * They must be at least as wide as specified; but making them too big - * won't cost a huge amount of memory, so we don't provide special - * extraction code like we did for JSAMPLE. (In other words, these - * typedefs live at a different point on the speed/space tradeoff curve.) - */ - -/* UINT8 must hold at least the values 0..255. */ - -#ifdef HAVE_UNSIGNED_CHAR -typedef unsigned char UINT8; -#else /* not HAVE_UNSIGNED_CHAR */ -#ifdef CHAR_IS_UNSIGNED -typedef char UINT8; -#else /* not CHAR_IS_UNSIGNED */ -typedef short UINT8; -#endif /* CHAR_IS_UNSIGNED */ -#endif /* HAVE_UNSIGNED_CHAR */ - -/* UINT16 must hold at least the values 0..65535. */ - -#ifdef HAVE_UNSIGNED_SHORT -typedef unsigned short UINT16; -#else /* not HAVE_UNSIGNED_SHORT */ -typedef unsigned int UINT16; -#endif /* HAVE_UNSIGNED_SHORT */ - -/* INT16 must hold at least the values -32768..32767. */ - -#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */ -typedef short INT16; -#endif - -/* INT32 must hold at least signed 32-bit values. */ - -#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */ -#ifndef _BASETSD_H_ /* Microsoft defines it in basetsd.h */ -#ifndef _BASETSD_H /* MinGW is slightly different */ -#ifndef QGLOBAL_H /* Qt defines it in qglobal.h */ -typedef long INT32; -#endif -#endif -#endif -#endif - -/* Datatype used for image dimensions. The JPEG standard only supports - * images up to 64K*64K due to 16-bit fields in SOF markers. Therefore - * "unsigned int" is sufficient on all machines. However, if you need to - * handle larger images and you don't mind deviating from the spec, you - * can change this datatype. - */ - -typedef unsigned int JDIMENSION; - -#define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */ - - -/* These macros are used in all function definitions and extern declarations. - * You could modify them if you need to change function linkage conventions; - * in particular, you'll need to do that to make the library a Windows DLL. - * Another application is to make all functions global for use with debuggers - * or code profilers that require it. - */ - -/* a function called through method pointers: */ -#define METHODDEF(type) static type -/* a function used only in its module: */ -#define LOCAL(type) static type -/* a function referenced thru EXTERNs: */ -#define GLOBAL(type) type -/* a reference to a GLOBAL function: */ -#define EXTERN(type) extern type - - -/* This macro is used to declare a "method", that is, a function pointer. - * We want to supply prototype parameters if the compiler can cope. - * Note that the arglist parameter must be parenthesized! - * Again, you can customize this if you need special linkage keywords. - */ - -#ifdef HAVE_PROTOTYPES -#define JMETHOD(type,methodname,arglist) type (*methodname) arglist -#else -#define JMETHOD(type,methodname,arglist) type (*methodname) () -#endif - - -/* Here is the pseudo-keyword for declaring pointers that must be "far" - * on 80x86 machines. Most of the specialized coding for 80x86 is handled - * by just saying "FAR *" where such a pointer is needed. In a few places - * explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol. - */ - -#ifndef FAR -#ifdef NEED_FAR_POINTERS -#define FAR far -#else -#define FAR -#endif -#endif - - -/* - * On a few systems, type boolean and/or its values FALSE, TRUE may appear - * in standard header files. Or you may have conflicts with application- - * specific header files that you want to include together with these files. - * Defining HAVE_BOOLEAN before including jpeglib.h should make it work. - */ - -#ifndef HAVE_BOOLEAN -typedef int boolean; -#endif -#ifndef FALSE /* in case these macros already exist */ -#define FALSE 0 /* values of boolean */ -#endif -#ifndef TRUE -#define TRUE 1 -#endif - - -/* - * The remaining options affect code selection within the JPEG library, - * but they don't need to be visible to most applications using the library. - * To minimize application namespace pollution, the symbols won't be - * defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined. - */ - -#ifdef JPEG_INTERNALS -#define JPEG_INTERNAL_OPTIONS -#endif - -#ifdef JPEG_INTERNAL_OPTIONS - - -/* - * These defines indicate whether to include various optional functions. - * Undefining some of these symbols will produce a smaller but less capable - * library. Note that you can leave certain source files out of the - * compilation/linking process if you've #undef'd the corresponding symbols. - * (You may HAVE to do that if your compiler doesn't like null source files.) - */ - -/* Capability options common to encoder and decoder: */ - -#define DCT_ISLOW_SUPPORTED /* slow but accurate integer algorithm */ -#define DCT_IFAST_SUPPORTED /* faster, less accurate integer method */ -#define DCT_FLOAT_SUPPORTED /* floating-point: accurate, fast on fast HW */ - -/* Encoder capability options: */ - -#define C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ -#define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ -#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ -#define DCT_SCALING_SUPPORTED /* Input rescaling via DCT? (Requires DCT_ISLOW)*/ -#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */ -/* Note: if you selected 12-bit data precision, it is dangerous to turn off - * ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit - * precision, so jchuff.c normally uses entropy optimization to compute - * usable tables for higher precision. If you don't want to do optimization, - * you'll have to supply different default Huffman tables. - * The exact same statements apply for progressive JPEG: the default tables - * don't work for progressive mode. (This may get fixed, however.) - */ -#define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */ - -/* Decoder capability options: */ - -#define D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ -#define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ -#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ -#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */ -#define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */ -#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */ -#undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */ -#define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */ -#define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */ -#define QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */ - -/* more capability options later, no doubt */ - - -/* - * Ordering of RGB data in scanlines passed to or from the application. - * If your application wants to deal with data in the order B,G,R, just - * change these macros. You can also deal with formats such as R,G,B,X - * (one extra byte per pixel) by changing RGB_PIXELSIZE. Note that changing - * the offsets will also change the order in which colormap data is organized. - * RESTRICTIONS: - * 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats. - * 2. These macros only affect RGB<=>YCbCr color conversion, so they are not - * useful if you are using JPEG color spaces other than YCbCr or grayscale. - * 3. The color quantizer modules will not behave desirably if RGB_PIXELSIZE - * is not 3 (they don't understand about dummy color components!). So you - * can't use color quantization if you change that value. - */ - -#define RGB_RED 0 /* Offset of Red in an RGB scanline element */ -#define RGB_GREEN 1 /* Offset of Green */ -#define RGB_BLUE 2 /* Offset of Blue */ -#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */ - - -/* Definitions for speed-related optimizations. */ - - -/* If your compiler supports inline functions, define INLINE - * as the inline keyword; otherwise define it as empty. - */ - -#ifndef INLINE -#ifdef __GNUC__ /* for instance, GNU C knows about inline */ -#define INLINE __inline__ -#endif -#ifndef INLINE -#define INLINE /* default is to define it as empty */ -#endif -#endif - - -/* On some machines (notably 68000 series) "int" is 32 bits, but multiplying - * two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER - * as short on such a machine. MULTIPLIER must be at least 16 bits wide. - */ - -#ifndef MULTIPLIER -#define MULTIPLIER int /* type for fastest integer multiply */ -#endif - - -/* FAST_FLOAT should be either float or double, whichever is done faster - * by your compiler. (Note that this type is only used in the floating point - * DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.) - * Typically, float is faster in ANSI C compilers, while double is faster in - * pre-ANSI compilers (because they insist on converting to double anyway). - * The code below therefore chooses float if we have ANSI-style prototypes. - */ - -#ifndef FAST_FLOAT -#ifdef HAVE_PROTOTYPES -#define FAST_FLOAT float -#else -#define FAST_FLOAT double -#endif -#endif - -#endif /* JPEG_INTERNAL_OPTIONS */ diff --git a/reactos/dll/3rdparty/libjpeg/jpegint.h b/reactos/dll/3rdparty/libjpeg/jpegint.h deleted file mode 100644 index 0c27a4e4a03..00000000000 --- a/reactos/dll/3rdparty/libjpeg/jpegint.h +++ /dev/null @@ -1,407 +0,0 @@ -/* - * jpegint.h - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * Modified 1997-2009 by Guido Vollbeding. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file provides common declarations for the various JPEG modules. - * These declarations are considered internal to the JPEG library; most - * applications using the library shouldn't need to include this file. - */ - - -/* Declarations for both compression & decompression */ - -typedef enum { /* Operating modes for buffer controllers */ - JBUF_PASS_THRU, /* Plain stripwise operation */ - /* Remaining modes require a full-image buffer to have been created */ - JBUF_SAVE_SOURCE, /* Run source subobject only, save output */ - JBUF_CRANK_DEST, /* Run dest subobject only, using saved data */ - JBUF_SAVE_AND_PASS /* Run both subobjects, save output */ -} J_BUF_MODE; - -/* Values of global_state field (jdapi.c has some dependencies on ordering!) */ -#define CSTATE_START 100 /* after create_compress */ -#define CSTATE_SCANNING 101 /* start_compress done, write_scanlines OK */ -#define CSTATE_RAW_OK 102 /* start_compress done, write_raw_data OK */ -#define CSTATE_WRCOEFS 103 /* jpeg_write_coefficients done */ -#define DSTATE_START 200 /* after create_decompress */ -#define DSTATE_INHEADER 201 /* reading header markers, no SOS yet */ -#define DSTATE_READY 202 /* found SOS, ready for start_decompress */ -#define DSTATE_PRELOAD 203 /* reading multiscan file in start_decompress*/ -#define DSTATE_PRESCAN 204 /* performing dummy pass for 2-pass quant */ -#define DSTATE_SCANNING 205 /* start_decompress done, read_scanlines OK */ -#define DSTATE_RAW_OK 206 /* start_decompress done, read_raw_data OK */ -#define DSTATE_BUFIMAGE 207 /* expecting jpeg_start_output */ -#define DSTATE_BUFPOST 208 /* looking for SOS/EOI in jpeg_finish_output */ -#define DSTATE_RDCOEFS 209 /* reading file in jpeg_read_coefficients */ -#define DSTATE_STOPPING 210 /* looking for EOI in jpeg_finish_decompress */ - - -/* Declarations for compression modules */ - -/* Master control module */ -struct jpeg_comp_master { - JMETHOD(void, prepare_for_pass, (j_compress_ptr cinfo)); - JMETHOD(void, pass_startup, (j_compress_ptr cinfo)); - JMETHOD(void, finish_pass, (j_compress_ptr cinfo)); - - /* State variables made visible to other modules */ - boolean call_pass_startup; /* True if pass_startup must be called */ - boolean is_last_pass; /* True during last pass */ -}; - -/* Main buffer control (downsampled-data buffer) */ -struct jpeg_c_main_controller { - JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); - JMETHOD(void, process_data, (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, - JDIMENSION in_rows_avail)); -}; - -/* Compression preprocessing (downsampling input buffer control) */ -struct jpeg_c_prep_controller { - JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); - JMETHOD(void, pre_process_data, (j_compress_ptr cinfo, - JSAMPARRAY input_buf, - JDIMENSION *in_row_ctr, - JDIMENSION in_rows_avail, - JSAMPIMAGE output_buf, - JDIMENSION *out_row_group_ctr, - JDIMENSION out_row_groups_avail)); -}; - -/* Coefficient buffer control */ -struct jpeg_c_coef_controller { - JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); - JMETHOD(boolean, compress_data, (j_compress_ptr cinfo, - JSAMPIMAGE input_buf)); -}; - -/* Colorspace conversion */ -struct jpeg_color_converter { - JMETHOD(void, start_pass, (j_compress_ptr cinfo)); - JMETHOD(void, color_convert, (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JSAMPIMAGE output_buf, - JDIMENSION output_row, int num_rows)); -}; - -/* Downsampling */ -struct jpeg_downsampler { - JMETHOD(void, start_pass, (j_compress_ptr cinfo)); - JMETHOD(void, downsample, (j_compress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION in_row_index, - JSAMPIMAGE output_buf, - JDIMENSION out_row_group_index)); - - boolean need_context_rows; /* TRUE if need rows above & below */ -}; - -/* Forward DCT (also controls coefficient quantization) */ -typedef JMETHOD(void, forward_DCT_ptr, - (j_compress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY sample_data, JBLOCKROW coef_blocks, - JDIMENSION start_row, JDIMENSION start_col, - JDIMENSION num_blocks)); - -struct jpeg_forward_dct { - JMETHOD(void, start_pass, (j_compress_ptr cinfo)); - /* It is useful to allow each component to have a separate FDCT method. */ - forward_DCT_ptr forward_DCT[MAX_COMPONENTS]; -}; - -/* Entropy encoding */ -struct jpeg_entropy_encoder { - JMETHOD(void, start_pass, (j_compress_ptr cinfo, boolean gather_statistics)); - JMETHOD(boolean, encode_mcu, (j_compress_ptr cinfo, JBLOCKROW *MCU_data)); - JMETHOD(void, finish_pass, (j_compress_ptr cinfo)); -}; - -/* Marker writing */ -struct jpeg_marker_writer { - JMETHOD(void, write_file_header, (j_compress_ptr cinfo)); - JMETHOD(void, write_frame_header, (j_compress_ptr cinfo)); - JMETHOD(void, write_scan_header, (j_compress_ptr cinfo)); - JMETHOD(void, write_file_trailer, (j_compress_ptr cinfo)); - JMETHOD(void, write_tables_only, (j_compress_ptr cinfo)); - /* These routines are exported to allow insertion of extra markers */ - /* Probably only COM and APPn markers should be written this way */ - JMETHOD(void, write_marker_header, (j_compress_ptr cinfo, int marker, - unsigned int datalen)); - JMETHOD(void, write_marker_byte, (j_compress_ptr cinfo, int val)); -}; - - -/* Declarations for decompression modules */ - -/* Master control module */ -struct jpeg_decomp_master { - JMETHOD(void, prepare_for_output_pass, (j_decompress_ptr cinfo)); - JMETHOD(void, finish_output_pass, (j_decompress_ptr cinfo)); - - /* State variables made visible to other modules */ - boolean is_dummy_pass; /* True during 1st pass for 2-pass quant */ -}; - -/* Input control module */ -struct jpeg_input_controller { - JMETHOD(int, consume_input, (j_decompress_ptr cinfo)); - JMETHOD(void, reset_input_controller, (j_decompress_ptr cinfo)); - JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo)); - JMETHOD(void, finish_input_pass, (j_decompress_ptr cinfo)); - - /* State variables made visible to other modules */ - boolean has_multiple_scans; /* True if file has multiple scans */ - boolean eoi_reached; /* True when EOI has been consumed */ -}; - -/* Main buffer control (downsampled-data buffer) */ -struct jpeg_d_main_controller { - JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)); - JMETHOD(void, process_data, (j_decompress_ptr cinfo, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail)); -}; - -/* Coefficient buffer control */ -struct jpeg_d_coef_controller { - JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo)); - JMETHOD(int, consume_data, (j_decompress_ptr cinfo)); - JMETHOD(void, start_output_pass, (j_decompress_ptr cinfo)); - JMETHOD(int, decompress_data, (j_decompress_ptr cinfo, - JSAMPIMAGE output_buf)); - /* Pointer to array of coefficient virtual arrays, or NULL if none */ - jvirt_barray_ptr *coef_arrays; -}; - -/* Decompression postprocessing (color quantization buffer control) */ -struct jpeg_d_post_controller { - JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)); - JMETHOD(void, post_process_data, (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, - JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, - JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail)); -}; - -/* Marker reading & parsing */ -struct jpeg_marker_reader { - JMETHOD(void, reset_marker_reader, (j_decompress_ptr cinfo)); - /* Read markers until SOS or EOI. - * Returns same codes as are defined for jpeg_consume_input: - * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. - */ - JMETHOD(int, read_markers, (j_decompress_ptr cinfo)); - /* Read a restart marker --- exported for use by entropy decoder only */ - jpeg_marker_parser_method read_restart_marker; - - /* State of marker reader --- nominally internal, but applications - * supplying COM or APPn handlers might like to know the state. - */ - boolean saw_SOI; /* found SOI? */ - boolean saw_SOF; /* found SOF? */ - int next_restart_num; /* next restart number expected (0-7) */ - unsigned int discarded_bytes; /* # of bytes skipped looking for a marker */ -}; - -/* Entropy decoding */ -struct jpeg_entropy_decoder { - JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); - JMETHOD(boolean, decode_mcu, (j_decompress_ptr cinfo, - JBLOCKROW *MCU_data)); -}; - -/* Inverse DCT (also performs dequantization) */ -typedef JMETHOD(void, inverse_DCT_method_ptr, - (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col)); - -struct jpeg_inverse_dct { - JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); - /* It is useful to allow each component to have a separate IDCT method. */ - inverse_DCT_method_ptr inverse_DCT[MAX_COMPONENTS]; -}; - -/* Upsampling (note that upsampler must also call color converter) */ -struct jpeg_upsampler { - JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); - JMETHOD(void, upsample, (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, - JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, - JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail)); - - boolean need_context_rows; /* TRUE if need rows above & below */ -}; - -/* Colorspace conversion */ -struct jpeg_color_deconverter { - JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); - JMETHOD(void, color_convert, (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION input_row, - JSAMPARRAY output_buf, int num_rows)); -}; - -/* Color quantization or color precision reduction */ -struct jpeg_color_quantizer { - JMETHOD(void, start_pass, (j_decompress_ptr cinfo, boolean is_pre_scan)); - JMETHOD(void, color_quantize, (j_decompress_ptr cinfo, - JSAMPARRAY input_buf, JSAMPARRAY output_buf, - int num_rows)); - JMETHOD(void, finish_pass, (j_decompress_ptr cinfo)); - JMETHOD(void, new_color_map, (j_decompress_ptr cinfo)); -}; - - -/* Miscellaneous useful macros */ - -#undef MAX -#define MAX(a,b) ((a) > (b) ? (a) : (b)) -#undef MIN -#define MIN(a,b) ((a) < (b) ? (a) : (b)) - - -/* We assume that right shift corresponds to signed division by 2 with - * rounding towards minus infinity. This is correct for typical "arithmetic - * shift" instructions that shift in copies of the sign bit. But some - * C compilers implement >> with an unsigned shift. For these machines you - * must define RIGHT_SHIFT_IS_UNSIGNED. - * RIGHT_SHIFT provides a proper signed right shift of an INT32 quantity. - * It is only applied with constant shift counts. SHIFT_TEMPS must be - * included in the variables of any routine using RIGHT_SHIFT. - */ - -#ifdef RIGHT_SHIFT_IS_UNSIGNED -#define SHIFT_TEMPS INT32 shift_temp; -#define RIGHT_SHIFT(x,shft) \ - ((shift_temp = (x)) < 0 ? \ - (shift_temp >> (shft)) | ((~((INT32) 0)) << (32-(shft))) : \ - (shift_temp >> (shft))) -#else -#define SHIFT_TEMPS -#define RIGHT_SHIFT(x,shft) ((x) >> (shft)) -#endif - - -/* Short forms of external names for systems with brain-damaged linkers. */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jinit_compress_master jICompress -#define jinit_c_master_control jICMaster -#define jinit_c_main_controller jICMainC -#define jinit_c_prep_controller jICPrepC -#define jinit_c_coef_controller jICCoefC -#define jinit_color_converter jICColor -#define jinit_downsampler jIDownsampler -#define jinit_forward_dct jIFDCT -#define jinit_huff_encoder jIHEncoder -#define jinit_arith_encoder jIAEncoder -#define jinit_marker_writer jIMWriter -#define jinit_master_decompress jIDMaster -#define jinit_d_main_controller jIDMainC -#define jinit_d_coef_controller jIDCoefC -#define jinit_d_post_controller jIDPostC -#define jinit_input_controller jIInCtlr -#define jinit_marker_reader jIMReader -#define jinit_huff_decoder jIHDecoder -#define jinit_arith_decoder jIADecoder -#define jinit_inverse_dct jIIDCT -#define jinit_upsampler jIUpsampler -#define jinit_color_deconverter jIDColor -#define jinit_1pass_quantizer jI1Quant -#define jinit_2pass_quantizer jI2Quant -#define jinit_merged_upsampler jIMUpsampler -#define jinit_memory_mgr jIMemMgr -#define jdiv_round_up jDivRound -#define jround_up jRound -#define jcopy_sample_rows jCopySamples -#define jcopy_block_row jCopyBlocks -#define jzero_far jZeroFar -#define jpeg_zigzag_order jZIGTable -#define jpeg_natural_order jZAGTable -#define jpeg_natural_order7 jZAGTable7 -#define jpeg_natural_order6 jZAGTable6 -#define jpeg_natural_order5 jZAGTable5 -#define jpeg_natural_order4 jZAGTable4 -#define jpeg_natural_order3 jZAGTable3 -#define jpeg_natural_order2 jZAGTable2 -#define jpeg_aritab jAriTab -#endif /* NEED_SHORT_EXTERNAL_NAMES */ - - -/* Compression module initialization routines */ -EXTERN(void) jinit_compress_master JPP((j_compress_ptr cinfo)); -EXTERN(void) jinit_c_master_control JPP((j_compress_ptr cinfo, - boolean transcode_only)); -EXTERN(void) jinit_c_main_controller JPP((j_compress_ptr cinfo, - boolean need_full_buffer)); -EXTERN(void) jinit_c_prep_controller JPP((j_compress_ptr cinfo, - boolean need_full_buffer)); -EXTERN(void) jinit_c_coef_controller JPP((j_compress_ptr cinfo, - boolean need_full_buffer)); -EXTERN(void) jinit_color_converter JPP((j_compress_ptr cinfo)); -EXTERN(void) jinit_downsampler JPP((j_compress_ptr cinfo)); -EXTERN(void) jinit_forward_dct JPP((j_compress_ptr cinfo)); -EXTERN(void) jinit_huff_encoder JPP((j_compress_ptr cinfo)); -EXTERN(void) jinit_arith_encoder JPP((j_compress_ptr cinfo)); -EXTERN(void) jinit_marker_writer JPP((j_compress_ptr cinfo)); -/* Decompression module initialization routines */ -EXTERN(void) jinit_master_decompress JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_d_main_controller JPP((j_decompress_ptr cinfo, - boolean need_full_buffer)); -EXTERN(void) jinit_d_coef_controller JPP((j_decompress_ptr cinfo, - boolean need_full_buffer)); -EXTERN(void) jinit_d_post_controller JPP((j_decompress_ptr cinfo, - boolean need_full_buffer)); -EXTERN(void) jinit_input_controller JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_marker_reader JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_huff_decoder JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_arith_decoder JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_inverse_dct JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_upsampler JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_color_deconverter JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_1pass_quantizer JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_2pass_quantizer JPP((j_decompress_ptr cinfo)); -EXTERN(void) jinit_merged_upsampler JPP((j_decompress_ptr cinfo)); -/* Memory manager initialization */ -EXTERN(void) jinit_memory_mgr JPP((j_common_ptr cinfo)); - -/* Utility routines in jutils.c */ -EXTERN(long) jdiv_round_up JPP((long a, long b)); -EXTERN(long) jround_up JPP((long a, long b)); -EXTERN(void) jcopy_sample_rows JPP((JSAMPARRAY input_array, int source_row, - JSAMPARRAY output_array, int dest_row, - int num_rows, JDIMENSION num_cols)); -EXTERN(void) jcopy_block_row JPP((JBLOCKROW input_row, JBLOCKROW output_row, - JDIMENSION num_blocks)); -EXTERN(void) jzero_far JPP((void FAR * target, size_t bytestozero)); -/* Constant tables in jutils.c */ -#if 0 /* This table is not actually needed in v6a */ -extern const int jpeg_zigzag_order[]; /* natural coef order to zigzag order */ -#endif -extern const int jpeg_natural_order[]; /* zigzag coef order to natural order */ -extern const int jpeg_natural_order7[]; /* zz to natural order for 7x7 block */ -extern const int jpeg_natural_order6[]; /* zz to natural order for 6x6 block */ -extern const int jpeg_natural_order5[]; /* zz to natural order for 5x5 block */ -extern const int jpeg_natural_order4[]; /* zz to natural order for 4x4 block */ -extern const int jpeg_natural_order3[]; /* zz to natural order for 3x3 block */ -extern const int jpeg_natural_order2[]; /* zz to natural order for 2x2 block */ - -/* Arithmetic coding probability estimation tables in jaricom.c */ -extern const INT32 jpeg_aritab[]; - -/* Suppress undefined-structure complaints if necessary. */ - -#ifdef INCOMPLETE_TYPES_BROKEN -#ifndef AM_MEMORY_MANAGER /* only jmemmgr.c defines these */ -struct jvirt_sarray_control { long dummy; }; -struct jvirt_barray_control { long dummy; }; -#endif -#endif /* INCOMPLETE_TYPES_BROKEN */ diff --git a/reactos/dll/3rdparty/libjpeg/jpeglib.h b/reactos/dll/3rdparty/libjpeg/jpeglib.h deleted file mode 100644 index 5039d4bf4c4..00000000000 --- a/reactos/dll/3rdparty/libjpeg/jpeglib.h +++ /dev/null @@ -1,1158 +0,0 @@ -/* - * jpeglib.h - * - * Copyright (C) 1991-1998, Thomas G. Lane. - * Modified 2002-2009 by Guido Vollbeding. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file defines the application interface for the JPEG library. - * Most applications using the library need only include this file, - * and perhaps jerror.h if they want to know the exact error codes. - */ - -#ifndef JPEGLIB_H -#define JPEGLIB_H - -/* - * First we include the configuration files that record how this - * installation of the JPEG library is set up. jconfig.h can be - * generated automatically for many systems. jmorecfg.h contains - * manual configuration options that most people need not worry about. - */ - -#ifndef JCONFIG_INCLUDED /* in case jinclude.h already did */ -#include "jconfig.h" /* widely used configuration options */ -#endif -#include "jmorecfg.h" /* seldom changed options */ - - -#ifdef __cplusplus -#ifndef DONT_USE_EXTERN_C -extern "C" { -#endif -#endif - -/* Version ID for the JPEG library. - * Might be useful for tests like "#if JPEG_LIB_VERSION >= 80". - */ - -#define JPEG_LIB_VERSION 80 /* Version 8.0 */ - - -/* Various constants determining the sizes of things. - * All of these are specified by the JPEG standard, so don't change them - * if you want to be compatible. - */ - -#define DCTSIZE 8 /* The basic DCT block is 8x8 samples */ -#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ -#define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */ -#define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */ -#define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */ -#define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */ -#define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */ -/* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard; - * the PostScript DCT filter can emit files with many more than 10 blocks/MCU. - * If you happen to run across such a file, you can up D_MAX_BLOCKS_IN_MCU - * to handle it. We even let you do this from the jconfig.h file. However, - * we strongly discourage changing C_MAX_BLOCKS_IN_MCU; just because Adobe - * sometimes emits noncompliant files doesn't mean you should too. - */ -#define C_MAX_BLOCKS_IN_MCU 10 /* compressor's limit on blocks per MCU */ -#ifndef D_MAX_BLOCKS_IN_MCU -#define D_MAX_BLOCKS_IN_MCU 10 /* decompressor's limit on blocks per MCU */ -#endif - - -/* Data structures for images (arrays of samples and of DCT coefficients). - * On 80x86 machines, the image arrays are too big for near pointers, - * but the pointer arrays can fit in near memory. - */ - -typedef JSAMPLE FAR *JSAMPROW; /* ptr to one image row of pixel samples. */ -typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */ -typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */ - -typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */ -typedef JBLOCK FAR *JBLOCKROW; /* pointer to one row of coefficient blocks */ -typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */ -typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */ - -typedef JCOEF FAR *JCOEFPTR; /* useful in a couple of places */ - - -/* Types for JPEG compression parameters and working tables. */ - - -/* DCT coefficient quantization tables. */ - -typedef struct { - /* This array gives the coefficient quantizers in natural array order - * (not the zigzag order in which they are stored in a JPEG DQT marker). - * CAUTION: IJG versions prior to v6a kept this array in zigzag order. - */ - UINT16 quantval[DCTSIZE2]; /* quantization step for each coefficient */ - /* This field is used only during compression. It's initialized FALSE when - * the table is created, and set TRUE when it's been output to the file. - * You could suppress output of a table by setting this to TRUE. - * (See jpeg_suppress_tables for an example.) - */ - boolean sent_table; /* TRUE when table has been output */ -} JQUANT_TBL; - - -/* Huffman coding tables. */ - -typedef struct { - /* These two fields directly represent the contents of a JPEG DHT marker */ - UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ - /* length k bits; bits[0] is unused */ - UINT8 huffval[256]; /* The symbols, in order of incr code length */ - /* This field is used only during compression. It's initialized FALSE when - * the table is created, and set TRUE when it's been output to the file. - * You could suppress output of a table by setting this to TRUE. - * (See jpeg_suppress_tables for an example.) - */ - boolean sent_table; /* TRUE when table has been output */ -} JHUFF_TBL; - - -/* Basic info about one component (color channel). */ - -typedef struct { - /* These values are fixed over the whole image. */ - /* For compression, they must be supplied by parameter setup; */ - /* for decompression, they are read from the SOF marker. */ - int component_id; /* identifier for this component (0..255) */ - int component_index; /* its index in SOF or cinfo->comp_info[] */ - int h_samp_factor; /* horizontal sampling factor (1..4) */ - int v_samp_factor; /* vertical sampling factor (1..4) */ - int quant_tbl_no; /* quantization table selector (0..3) */ - /* These values may vary between scans. */ - /* For compression, they must be supplied by parameter setup; */ - /* for decompression, they are read from the SOS marker. */ - /* The decompressor output side may not use these variables. */ - int dc_tbl_no; /* DC entropy table selector (0..3) */ - int ac_tbl_no; /* AC entropy table selector (0..3) */ - - /* Remaining fields should be treated as private by applications. */ - - /* These values are computed during compression or decompression startup: */ - /* Component's size in DCT blocks. - * Any dummy blocks added to complete an MCU are not counted; therefore - * these values do not depend on whether a scan is interleaved or not. - */ - JDIMENSION width_in_blocks; - JDIMENSION height_in_blocks; - /* Size of a DCT block in samples, - * reflecting any scaling we choose to apply during the DCT step. - * Values from 1 to 16 are supported. - * Note that different components may receive different DCT scalings. - */ - int DCT_h_scaled_size; - int DCT_v_scaled_size; - /* The downsampled dimensions are the component's actual, unpadded number - * of samples at the main buffer (preprocessing/compression interface); - * DCT scaling is included, so - * downsampled_width = ceil(image_width * Hi/Hmax * DCT_h_scaled_size/DCTSIZE) - * and similarly for height. - */ - JDIMENSION downsampled_width; /* actual width in samples */ - JDIMENSION downsampled_height; /* actual height in samples */ - /* This flag is used only for decompression. In cases where some of the - * components will be ignored (eg grayscale output from YCbCr image), - * we can skip most computations for the unused components. - */ - boolean component_needed; /* do we need the value of this component? */ - - /* These values are computed before starting a scan of the component. */ - /* The decompressor output side may not use these variables. */ - int MCU_width; /* number of blocks per MCU, horizontally */ - int MCU_height; /* number of blocks per MCU, vertically */ - int MCU_blocks; /* MCU_width * MCU_height */ - int MCU_sample_width; /* MCU width in samples: MCU_width * DCT_h_scaled_size */ - int last_col_width; /* # of non-dummy blocks across in last MCU */ - int last_row_height; /* # of non-dummy blocks down in last MCU */ - - /* Saved quantization table for component; NULL if none yet saved. - * See jdinput.c comments about the need for this information. - * This field is currently used only for decompression. - */ - JQUANT_TBL * quant_table; - - /* Private per-component storage for DCT or IDCT subsystem. */ - void * dct_table; -} jpeg_component_info; - - -/* The script for encoding a multiple-scan file is an array of these: */ - -typedef struct { - int comps_in_scan; /* number of components encoded in this scan */ - int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */ - int Ss, Se; /* progressive JPEG spectral selection parms */ - int Ah, Al; /* progressive JPEG successive approx. parms */ -} jpeg_scan_info; - -/* The decompressor can save APPn and COM markers in a list of these: */ - -typedef struct jpeg_marker_struct FAR * jpeg_saved_marker_ptr; - -struct jpeg_marker_struct { - jpeg_saved_marker_ptr next; /* next in list, or NULL */ - UINT8 marker; /* marker code: JPEG_COM, or JPEG_APP0+n */ - unsigned int original_length; /* # bytes of data in the file */ - unsigned int data_length; /* # bytes of data saved at data[] */ - JOCTET FAR * data; /* the data contained in the marker */ - /* the marker length word is not counted in data_length or original_length */ -}; - -/* Known color spaces. */ - -typedef enum { - JCS_UNKNOWN, /* error/unspecified */ - JCS_GRAYSCALE, /* monochrome */ - JCS_RGB, /* red/green/blue */ - JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */ - JCS_CMYK, /* C/M/Y/K */ - JCS_YCCK /* Y/Cb/Cr/K */ -} J_COLOR_SPACE; - -/* DCT/IDCT algorithm options. */ - -typedef enum { - JDCT_ISLOW, /* slow but accurate integer algorithm */ - JDCT_IFAST, /* faster, less accurate integer method */ - JDCT_FLOAT /* floating-point: accurate, fast on fast HW */ -} J_DCT_METHOD; - -#ifndef JDCT_DEFAULT /* may be overridden in jconfig.h */ -#define JDCT_DEFAULT JDCT_ISLOW -#endif -#ifndef JDCT_FASTEST /* may be overridden in jconfig.h */ -#define JDCT_FASTEST JDCT_IFAST -#endif - -/* Dithering options for decompression. */ - -typedef enum { - JDITHER_NONE, /* no dithering */ - JDITHER_ORDERED, /* simple ordered dither */ - JDITHER_FS /* Floyd-Steinberg error diffusion dither */ -} J_DITHER_MODE; - - -/* Common fields between JPEG compression and decompression master structs. */ - -#define jpeg_common_fields \ - struct jpeg_error_mgr * err; /* Error handler module */\ - struct jpeg_memory_mgr * mem; /* Memory manager module */\ - struct jpeg_progress_mgr * progress; /* Progress monitor, or NULL if none */\ - void * client_data; /* Available for use by application */\ - boolean is_decompressor; /* So common code can tell which is which */\ - int global_state /* For checking call sequence validity */ - -/* Routines that are to be used by both halves of the library are declared - * to receive a pointer to this structure. There are no actual instances of - * jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct. - */ -struct jpeg_common_struct { - jpeg_common_fields; /* Fields common to both master struct types */ - /* Additional fields follow in an actual jpeg_compress_struct or - * jpeg_decompress_struct. All three structs must agree on these - * initial fields! (This would be a lot cleaner in C++.) - */ -}; - -typedef struct jpeg_common_struct * j_common_ptr; -typedef struct jpeg_compress_struct * j_compress_ptr; -typedef struct jpeg_decompress_struct * j_decompress_ptr; - - -/* Master record for a compression instance */ - -struct jpeg_compress_struct { - jpeg_common_fields; /* Fields shared with jpeg_decompress_struct */ - - /* Destination for compressed data */ - struct jpeg_destination_mgr * dest; - - /* Description of source image --- these fields must be filled in by - * outer application before starting compression. in_color_space must - * be correct before you can even call jpeg_set_defaults(). - */ - - JDIMENSION image_width; /* input image width */ - JDIMENSION image_height; /* input image height */ - int input_components; /* # of color components in input image */ - J_COLOR_SPACE in_color_space; /* colorspace of input image */ - - double input_gamma; /* image gamma of input image */ - - /* Compression parameters --- these fields must be set before calling - * jpeg_start_compress(). We recommend calling jpeg_set_defaults() to - * initialize everything to reasonable defaults, then changing anything - * the application specifically wants to change. That way you won't get - * burnt when new parameters are added. Also note that there are several - * helper routines to simplify changing parameters. - */ - - unsigned int scale_num, scale_denom; /* fraction by which to scale image */ - - JDIMENSION jpeg_width; /* scaled JPEG image width */ - JDIMENSION jpeg_height; /* scaled JPEG image height */ - /* Dimensions of actual JPEG image that will be written to file, - * derived from input dimensions by scaling factors above. - * These fields are computed by jpeg_start_compress(). - * You can also use jpeg_calc_jpeg_dimensions() to determine these values - * in advance of calling jpeg_start_compress(). - */ - - int data_precision; /* bits of precision in image data */ - - int num_components; /* # of color components in JPEG image */ - J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ - - jpeg_component_info * comp_info; - /* comp_info[i] describes component that appears i'th in SOF */ - - JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; - int q_scale_factor[NUM_QUANT_TBLS]; - /* ptrs to coefficient quantization tables, or NULL if not defined, - * and corresponding scale factors (percentage, initialized 100). - */ - - JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; - JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; - /* ptrs to Huffman coding tables, or NULL if not defined */ - - UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ - UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ - UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ - - int num_scans; /* # of entries in scan_info array */ - const jpeg_scan_info * scan_info; /* script for multi-scan file, or NULL */ - /* The default value of scan_info is NULL, which causes a single-scan - * sequential JPEG file to be emitted. To create a multi-scan file, - * set num_scans and scan_info to point to an array of scan definitions. - */ - - boolean raw_data_in; /* TRUE=caller supplies downsampled data */ - boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ - boolean optimize_coding; /* TRUE=optimize entropy encoding parms */ - boolean CCIR601_sampling; /* TRUE=first samples are cosited */ - boolean do_fancy_downsampling; /* TRUE=apply fancy downsampling */ - int smoothing_factor; /* 1..100, or 0 for no input smoothing */ - J_DCT_METHOD dct_method; /* DCT algorithm selector */ - - /* The restart interval can be specified in absolute MCUs by setting - * restart_interval, or in MCU rows by setting restart_in_rows - * (in which case the correct restart_interval will be figured - * for each scan). - */ - unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */ - int restart_in_rows; /* if > 0, MCU rows per restart interval */ - - /* Parameters controlling emission of special markers. */ - - boolean write_JFIF_header; /* should a JFIF marker be written? */ - UINT8 JFIF_major_version; /* What to write for the JFIF version number */ - UINT8 JFIF_minor_version; - /* These three values are not used by the JPEG code, merely copied */ - /* into the JFIF APP0 marker. density_unit can be 0 for unknown, */ - /* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */ - /* ratio is defined by X_density/Y_density even when density_unit=0. */ - UINT8 density_unit; /* JFIF code for pixel size units */ - UINT16 X_density; /* Horizontal pixel density */ - UINT16 Y_density; /* Vertical pixel density */ - boolean write_Adobe_marker; /* should an Adobe marker be written? */ - - /* State variable: index of next scanline to be written to - * jpeg_write_scanlines(). Application may use this to control its - * processing loop, e.g., "while (next_scanline < image_height)". - */ - - JDIMENSION next_scanline; /* 0 .. image_height-1 */ - - /* Remaining fields are known throughout compressor, but generally - * should not be touched by a surrounding application. - */ - - /* - * These fields are computed during compression startup - */ - boolean progressive_mode; /* TRUE if scan script uses progressive mode */ - int max_h_samp_factor; /* largest h_samp_factor */ - int max_v_samp_factor; /* largest v_samp_factor */ - - int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */ - int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */ - - JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coef ctlr */ - /* The coefficient controller receives data in units of MCU rows as defined - * for fully interleaved scans (whether the JPEG file is interleaved or not). - * There are v_samp_factor * DCTSIZE sample rows of each component in an - * "iMCU" (interleaved MCU) row. - */ - - /* - * These fields are valid during any one scan. - * They describe the components and MCUs actually appearing in the scan. - */ - int comps_in_scan; /* # of JPEG components in this scan */ - jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; - /* *cur_comp_info[i] describes component that appears i'th in SOS */ - - JDIMENSION MCUs_per_row; /* # of MCUs across the image */ - JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ - - int blocks_in_MCU; /* # of DCT blocks per MCU */ - int MCU_membership[C_MAX_BLOCKS_IN_MCU]; - /* MCU_membership[i] is index in cur_comp_info of component owning */ - /* i'th block in an MCU */ - - int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ - - int block_size; /* the basic DCT block size: 1..16 */ - const int * natural_order; /* natural-order position array */ - int lim_Se; /* min( Se, DCTSIZE2-1 ) */ - - /* - * Links to compression subobjects (methods and private variables of modules) - */ - struct jpeg_comp_master * master; - struct jpeg_c_main_controller * main; - struct jpeg_c_prep_controller * prep; - struct jpeg_c_coef_controller * coef; - struct jpeg_marker_writer * marker; - struct jpeg_color_converter * cconvert; - struct jpeg_downsampler * downsample; - struct jpeg_forward_dct * fdct; - struct jpeg_entropy_encoder * entropy; - jpeg_scan_info * script_space; /* workspace for jpeg_simple_progression */ - int script_space_size; -}; - - -/* Master record for a decompression instance */ - -struct jpeg_decompress_struct { - jpeg_common_fields; /* Fields shared with jpeg_compress_struct */ - - /* Source of compressed data */ - struct jpeg_source_mgr * src; - - /* Basic description of image --- filled in by jpeg_read_header(). */ - /* Application may inspect these values to decide how to process image. */ - - JDIMENSION image_width; /* nominal image width (from SOF marker) */ - JDIMENSION image_height; /* nominal image height */ - int num_components; /* # of color components in JPEG image */ - J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ - - /* Decompression processing parameters --- these fields must be set before - * calling jpeg_start_decompress(). Note that jpeg_read_header() initializes - * them to default values. - */ - - J_COLOR_SPACE out_color_space; /* colorspace for output */ - - unsigned int scale_num, scale_denom; /* fraction by which to scale image */ - - double output_gamma; /* image gamma wanted in output */ - - boolean buffered_image; /* TRUE=multiple output passes */ - boolean raw_data_out; /* TRUE=downsampled data wanted */ - - J_DCT_METHOD dct_method; /* IDCT algorithm selector */ - boolean do_fancy_upsampling; /* TRUE=apply fancy upsampling */ - boolean do_block_smoothing; /* TRUE=apply interblock smoothing */ - - boolean quantize_colors; /* TRUE=colormapped output wanted */ - /* the following are ignored if not quantize_colors: */ - J_DITHER_MODE dither_mode; /* type of color dithering to use */ - boolean two_pass_quantize; /* TRUE=use two-pass color quantization */ - int desired_number_of_colors; /* max # colors to use in created colormap */ - /* these are significant only in buffered-image mode: */ - boolean enable_1pass_quant; /* enable future use of 1-pass quantizer */ - boolean enable_external_quant;/* enable future use of external colormap */ - boolean enable_2pass_quant; /* enable future use of 2-pass quantizer */ - - /* Description of actual output image that will be returned to application. - * These fields are computed by jpeg_start_decompress(). - * You can also use jpeg_calc_output_dimensions() to determine these values - * in advance of calling jpeg_start_decompress(). - */ - - JDIMENSION output_width; /* scaled image width */ - JDIMENSION output_height; /* scaled image height */ - int out_color_components; /* # of color components in out_color_space */ - int output_components; /* # of color components returned */ - /* output_components is 1 (a colormap index) when quantizing colors; - * otherwise it equals out_color_components. - */ - int rec_outbuf_height; /* min recommended height of scanline buffer */ - /* If the buffer passed to jpeg_read_scanlines() is less than this many rows - * high, space and time will be wasted due to unnecessary data copying. - * Usually rec_outbuf_height will be 1 or 2, at most 4. - */ - - /* When quantizing colors, the output colormap is described by these fields. - * The application can supply a colormap by setting colormap non-NULL before - * calling jpeg_start_decompress; otherwise a colormap is created during - * jpeg_start_decompress or jpeg_start_output. - * The map has out_color_components rows and actual_number_of_colors columns. - */ - int actual_number_of_colors; /* number of entries in use */ - JSAMPARRAY colormap; /* The color map as a 2-D pixel array */ - - /* State variables: these variables indicate the progress of decompression. - * The application may examine these but must not modify them. - */ - - /* Row index of next scanline to be read from jpeg_read_scanlines(). - * Application may use this to control its processing loop, e.g., - * "while (output_scanline < output_height)". - */ - JDIMENSION output_scanline; /* 0 .. output_height-1 */ - - /* Current input scan number and number of iMCU rows completed in scan. - * These indicate the progress of the decompressor input side. - */ - int input_scan_number; /* Number of SOS markers seen so far */ - JDIMENSION input_iMCU_row; /* Number of iMCU rows completed */ - - /* The "output scan number" is the notional scan being displayed by the - * output side. The decompressor will not allow output scan/row number - * to get ahead of input scan/row, but it can fall arbitrarily far behind. - */ - int output_scan_number; /* Nominal scan number being displayed */ - JDIMENSION output_iMCU_row; /* Number of iMCU rows read */ - - /* Current progression status. coef_bits[c][i] indicates the precision - * with which component c's DCT coefficient i (in zigzag order) is known. - * It is -1 when no data has yet been received, otherwise it is the point - * transform (shift) value for the most recent scan of the coefficient - * (thus, 0 at completion of the progression). - * This pointer is NULL when reading a non-progressive file. - */ - int (*coef_bits)[DCTSIZE2]; /* -1 or current Al value for each coef */ - - /* Internal JPEG parameters --- the application usually need not look at - * these fields. Note that the decompressor output side may not use - * any parameters that can change between scans. - */ - - /* Quantization and Huffman tables are carried forward across input - * datastreams when processing abbreviated JPEG datastreams. - */ - - JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; - /* ptrs to coefficient quantization tables, or NULL if not defined */ - - JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; - JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; - /* ptrs to Huffman coding tables, or NULL if not defined */ - - /* These parameters are never carried across datastreams, since they - * are given in SOF/SOS markers or defined to be reset by SOI. - */ - - int data_precision; /* bits of precision in image data */ - - jpeg_component_info * comp_info; - /* comp_info[i] describes component that appears i'th in SOF */ - - boolean is_baseline; /* TRUE if Baseline SOF0 encountered */ - boolean progressive_mode; /* TRUE if SOFn specifies progressive mode */ - boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ - - UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ - UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ - UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ - - unsigned int restart_interval; /* MCUs per restart interval, or 0 for no restart */ - - /* These fields record data obtained from optional markers recognized by - * the JPEG library. - */ - boolean saw_JFIF_marker; /* TRUE iff a JFIF APP0 marker was found */ - /* Data copied from JFIF marker; only valid if saw_JFIF_marker is TRUE: */ - UINT8 JFIF_major_version; /* JFIF version number */ - UINT8 JFIF_minor_version; - UINT8 density_unit; /* JFIF code for pixel size units */ - UINT16 X_density; /* Horizontal pixel density */ - UINT16 Y_density; /* Vertical pixel density */ - boolean saw_Adobe_marker; /* TRUE iff an Adobe APP14 marker was found */ - UINT8 Adobe_transform; /* Color transform code from Adobe marker */ - - boolean CCIR601_sampling; /* TRUE=first samples are cosited */ - - /* Aside from the specific data retained from APPn markers known to the - * library, the uninterpreted contents of any or all APPn and COM markers - * can be saved in a list for examination by the application. - */ - jpeg_saved_marker_ptr marker_list; /* Head of list of saved markers */ - - /* Remaining fields are known throughout decompressor, but generally - * should not be touched by a surrounding application. - */ - - /* - * These fields are computed during decompression startup - */ - int max_h_samp_factor; /* largest h_samp_factor */ - int max_v_samp_factor; /* largest v_samp_factor */ - - int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */ - int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */ - - JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */ - /* The coefficient controller's input and output progress is measured in - * units of "iMCU" (interleaved MCU) rows. These are the same as MCU rows - * in fully interleaved JPEG scans, but are used whether the scan is - * interleaved or not. We define an iMCU row as v_samp_factor DCT block - * rows of each component. Therefore, the IDCT output contains - * v_samp_factor*DCT_v_scaled_size sample rows of a component per iMCU row. - */ - - JSAMPLE * sample_range_limit; /* table for fast range-limiting */ - - /* - * These fields are valid during any one scan. - * They describe the components and MCUs actually appearing in the scan. - * Note that the decompressor output side must not use these fields. - */ - int comps_in_scan; /* # of JPEG components in this scan */ - jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; - /* *cur_comp_info[i] describes component that appears i'th in SOS */ - - JDIMENSION MCUs_per_row; /* # of MCUs across the image */ - JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ - - int blocks_in_MCU; /* # of DCT blocks per MCU */ - int MCU_membership[D_MAX_BLOCKS_IN_MCU]; - /* MCU_membership[i] is index in cur_comp_info of component owning */ - /* i'th block in an MCU */ - - int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ - - /* These fields are derived from Se of first SOS marker. - */ - int block_size; /* the basic DCT block size: 1..16 */ - const int * natural_order; /* natural-order position array for entropy decode */ - int lim_Se; /* min( Se, DCTSIZE2-1 ) for entropy decode */ - - /* This field is shared between entropy decoder and marker parser. - * It is either zero or the code of a JPEG marker that has been - * read from the data source, but has not yet been processed. - */ - int unread_marker; - - /* - * Links to decompression subobjects (methods, private variables of modules) - */ - struct jpeg_decomp_master * master; - struct jpeg_d_main_controller * main; - struct jpeg_d_coef_controller * coef; - struct jpeg_d_post_controller * post; - struct jpeg_input_controller * inputctl; - struct jpeg_marker_reader * marker; - struct jpeg_entropy_decoder * entropy; - struct jpeg_inverse_dct * idct; - struct jpeg_upsampler * upsample; - struct jpeg_color_deconverter * cconvert; - struct jpeg_color_quantizer * cquantize; -}; - - -/* "Object" declarations for JPEG modules that may be supplied or called - * directly by the surrounding application. - * As with all objects in the JPEG library, these structs only define the - * publicly visible methods and state variables of a module. Additional - * private fields may exist after the public ones. - */ - - -/* Error handler object */ - -struct jpeg_error_mgr { - /* Error exit handler: does not return to caller */ - JMETHOD(void, error_exit, (j_common_ptr cinfo)); - /* Conditionally emit a trace or warning message */ - JMETHOD(void, emit_message, (j_common_ptr cinfo, int msg_level)); - /* Routine that actually outputs a trace or error message */ - JMETHOD(void, output_message, (j_common_ptr cinfo)); - /* Format a message string for the most recent JPEG error or message */ - JMETHOD(void, format_message, (j_common_ptr cinfo, char * buffer)); -#define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */ - /* Reset error state variables at start of a new image */ - JMETHOD(void, reset_error_mgr, (j_common_ptr cinfo)); - - /* The message ID code and any parameters are saved here. - * A message can have one string parameter or up to 8 int parameters. - */ - int msg_code; -#define JMSG_STR_PARM_MAX 80 - union { - int i[8]; - char s[JMSG_STR_PARM_MAX]; - } msg_parm; - - /* Standard state variables for error facility */ - - int trace_level; /* max msg_level that will be displayed */ - - /* For recoverable corrupt-data errors, we emit a warning message, - * but keep going unless emit_message chooses to abort. emit_message - * should count warnings in num_warnings. The surrounding application - * can check for bad data by seeing if num_warnings is nonzero at the - * end of processing. - */ - long num_warnings; /* number of corrupt-data warnings */ - - /* These fields point to the table(s) of error message strings. - * An application can change the table pointer to switch to a different - * message list (typically, to change the language in which errors are - * reported). Some applications may wish to add additional error codes - * that will be handled by the JPEG library error mechanism; the second - * table pointer is used for this purpose. - * - * First table includes all errors generated by JPEG library itself. - * Error code 0 is reserved for a "no such error string" message. - */ - const char * const * jpeg_message_table; /* Library errors */ - int last_jpeg_message; /* Table contains strings 0..last_jpeg_message */ - /* Second table can be added by application (see cjpeg/djpeg for example). - * It contains strings numbered first_addon_message..last_addon_message. - */ - const char * const * addon_message_table; /* Non-library errors */ - int first_addon_message; /* code for first string in addon table */ - int last_addon_message; /* code for last string in addon table */ -}; - - -/* Progress monitor object */ - -struct jpeg_progress_mgr { - JMETHOD(void, progress_monitor, (j_common_ptr cinfo)); - - long pass_counter; /* work units completed in this pass */ - long pass_limit; /* total number of work units in this pass */ - int completed_passes; /* passes completed so far */ - int total_passes; /* total number of passes expected */ -}; - - -/* Data destination object for compression */ - -struct jpeg_destination_mgr { - JOCTET * next_output_byte; /* => next byte to write in buffer */ - size_t free_in_buffer; /* # of byte spaces remaining in buffer */ - - JMETHOD(void, init_destination, (j_compress_ptr cinfo)); - JMETHOD(boolean, empty_output_buffer, (j_compress_ptr cinfo)); - JMETHOD(void, term_destination, (j_compress_ptr cinfo)); -}; - - -/* Data source object for decompression */ - -struct jpeg_source_mgr { - const JOCTET * next_input_byte; /* => next byte to read from buffer */ - size_t bytes_in_buffer; /* # of bytes remaining in buffer */ - - JMETHOD(void, init_source, (j_decompress_ptr cinfo)); - JMETHOD(boolean, fill_input_buffer, (j_decompress_ptr cinfo)); - JMETHOD(void, skip_input_data, (j_decompress_ptr cinfo, long num_bytes)); - JMETHOD(boolean, resync_to_restart, (j_decompress_ptr cinfo, int desired)); - JMETHOD(void, term_source, (j_decompress_ptr cinfo)); -}; - - -/* Memory manager object. - * Allocates "small" objects (a few K total), "large" objects (tens of K), - * and "really big" objects (virtual arrays with backing store if needed). - * The memory manager does not allow individual objects to be freed; rather, - * each created object is assigned to a pool, and whole pools can be freed - * at once. This is faster and more convenient than remembering exactly what - * to free, especially where malloc()/free() are not too speedy. - * NB: alloc routines never return NULL. They exit to error_exit if not - * successful. - */ - -#define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */ -#define JPOOL_IMAGE 1 /* lasts until done with image/datastream */ -#define JPOOL_NUMPOOLS 2 - -typedef struct jvirt_sarray_control * jvirt_sarray_ptr; -typedef struct jvirt_barray_control * jvirt_barray_ptr; - - -struct jpeg_memory_mgr { - /* Method pointers */ - JMETHOD(void *, alloc_small, (j_common_ptr cinfo, int pool_id, - size_t sizeofobject)); - JMETHOD(void FAR *, alloc_large, (j_common_ptr cinfo, int pool_id, - size_t sizeofobject)); - JMETHOD(JSAMPARRAY, alloc_sarray, (j_common_ptr cinfo, int pool_id, - JDIMENSION samplesperrow, - JDIMENSION numrows)); - JMETHOD(JBLOCKARRAY, alloc_barray, (j_common_ptr cinfo, int pool_id, - JDIMENSION blocksperrow, - JDIMENSION numrows)); - JMETHOD(jvirt_sarray_ptr, request_virt_sarray, (j_common_ptr cinfo, - int pool_id, - boolean pre_zero, - JDIMENSION samplesperrow, - JDIMENSION numrows, - JDIMENSION maxaccess)); - JMETHOD(jvirt_barray_ptr, request_virt_barray, (j_common_ptr cinfo, - int pool_id, - boolean pre_zero, - JDIMENSION blocksperrow, - JDIMENSION numrows, - JDIMENSION maxaccess)); - JMETHOD(void, realize_virt_arrays, (j_common_ptr cinfo)); - JMETHOD(JSAMPARRAY, access_virt_sarray, (j_common_ptr cinfo, - jvirt_sarray_ptr ptr, - JDIMENSION start_row, - JDIMENSION num_rows, - boolean writable)); - JMETHOD(JBLOCKARRAY, access_virt_barray, (j_common_ptr cinfo, - jvirt_barray_ptr ptr, - JDIMENSION start_row, - JDIMENSION num_rows, - boolean writable)); - JMETHOD(void, free_pool, (j_common_ptr cinfo, int pool_id)); - JMETHOD(void, self_destruct, (j_common_ptr cinfo)); - - /* Limit on memory allocation for this JPEG object. (Note that this is - * merely advisory, not a guaranteed maximum; it only affects the space - * used for virtual-array buffers.) May be changed by outer application - * after creating the JPEG object. - */ - long max_memory_to_use; - - /* Maximum allocation request accepted by alloc_large. */ - long max_alloc_chunk; -}; - - -/* Routine signature for application-supplied marker processing methods. - * Need not pass marker code since it is stored in cinfo->unread_marker. - */ -typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo)); - - -/* Declarations for routines called by application. - * The JPP macro hides prototype parameters from compilers that can't cope. - * Note JPP requires double parentheses. - */ - -#ifdef HAVE_PROTOTYPES -#define JPP(arglist) arglist -#else -#define JPP(arglist) () -#endif - - -/* Short forms of external names for systems with brain-damaged linkers. - * We shorten external names to be unique in the first six letters, which - * is good enough for all known systems. - * (If your compiler itself needs names to be unique in less than 15 - * characters, you are out of luck. Get a better compiler.) - */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jpeg_std_error jStdError -#define jpeg_CreateCompress jCreaCompress -#define jpeg_CreateDecompress jCreaDecompress -#define jpeg_destroy_compress jDestCompress -#define jpeg_destroy_decompress jDestDecompress -#define jpeg_stdio_dest jStdDest -#define jpeg_stdio_src jStdSrc -#define jpeg_mem_dest jMemDest -#define jpeg_mem_src jMemSrc -#define jpeg_set_defaults jSetDefaults -#define jpeg_set_colorspace jSetColorspace -#define jpeg_default_colorspace jDefColorspace -#define jpeg_set_quality jSetQuality -#define jpeg_set_linear_quality jSetLQuality -#define jpeg_default_qtables jDefQTables -#define jpeg_add_quant_table jAddQuantTable -#define jpeg_quality_scaling jQualityScaling -#define jpeg_simple_progression jSimProgress -#define jpeg_suppress_tables jSuppressTables -#define jpeg_alloc_quant_table jAlcQTable -#define jpeg_alloc_huff_table jAlcHTable -#define jpeg_start_compress jStrtCompress -#define jpeg_write_scanlines jWrtScanlines -#define jpeg_finish_compress jFinCompress -#define jpeg_calc_jpeg_dimensions jCjpegDimensions -#define jpeg_write_raw_data jWrtRawData -#define jpeg_write_marker jWrtMarker -#define jpeg_write_m_header jWrtMHeader -#define jpeg_write_m_byte jWrtMByte -#define jpeg_write_tables jWrtTables -#define jpeg_read_header jReadHeader -#define jpeg_start_decompress jStrtDecompress -#define jpeg_read_scanlines jReadScanlines -#define jpeg_finish_decompress jFinDecompress -#define jpeg_read_raw_data jReadRawData -#define jpeg_has_multiple_scans jHasMultScn -#define jpeg_start_output jStrtOutput -#define jpeg_finish_output jFinOutput -#define jpeg_input_complete jInComplete -#define jpeg_new_colormap jNewCMap -#define jpeg_consume_input jConsumeInput -#define jpeg_core_output_dimensions jCoreDimensions -#define jpeg_calc_output_dimensions jCalcDimensions -#define jpeg_save_markers jSaveMarkers -#define jpeg_set_marker_processor jSetMarker -#define jpeg_read_coefficients jReadCoefs -#define jpeg_write_coefficients jWrtCoefs -#define jpeg_copy_critical_parameters jCopyCrit -#define jpeg_abort_compress jAbrtCompress -#define jpeg_abort_decompress jAbrtDecompress -#define jpeg_abort jAbort -#define jpeg_destroy jDestroy -#define jpeg_resync_to_restart jResyncRestart -#endif /* NEED_SHORT_EXTERNAL_NAMES */ - - -/* Default error-management setup */ -EXTERN(struct jpeg_error_mgr *) jpeg_std_error - JPP((struct jpeg_error_mgr * err)); - -/* Initialization of JPEG compression objects. - * jpeg_create_compress() and jpeg_create_decompress() are the exported - * names that applications should call. These expand to calls on - * jpeg_CreateCompress and jpeg_CreateDecompress with additional information - * passed for version mismatch checking. - * NB: you must set up the error-manager BEFORE calling jpeg_create_xxx. - */ -#define jpeg_create_compress(cinfo) \ - jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \ - (size_t) sizeof(struct jpeg_compress_struct)) -#define jpeg_create_decompress(cinfo) \ - jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \ - (size_t) sizeof(struct jpeg_decompress_struct)) -EXTERN(void) jpeg_CreateCompress JPP((j_compress_ptr cinfo, - int version, size_t structsize)); -EXTERN(void) jpeg_CreateDecompress JPP((j_decompress_ptr cinfo, - int version, size_t structsize)); -/* Destruction of JPEG compression objects */ -EXTERN(void) jpeg_destroy_compress JPP((j_compress_ptr cinfo)); -EXTERN(void) jpeg_destroy_decompress JPP((j_decompress_ptr cinfo)); - -/* Standard data source and destination managers: stdio streams. */ -/* Caller is responsible for opening the file before and closing after. */ -EXTERN(void) jpeg_stdio_dest JPP((j_compress_ptr cinfo, FILE * outfile)); -EXTERN(void) jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile)); - -/* Data source and destination managers: memory buffers. */ -EXTERN(void) jpeg_mem_dest JPP((j_compress_ptr cinfo, - unsigned char ** outbuffer, - unsigned long * outsize)); -EXTERN(void) jpeg_mem_src JPP((j_decompress_ptr cinfo, - unsigned char * inbuffer, - unsigned long insize)); - -/* Default parameter setup for compression */ -EXTERN(void) jpeg_set_defaults JPP((j_compress_ptr cinfo)); -/* Compression parameter setup aids */ -EXTERN(void) jpeg_set_colorspace JPP((j_compress_ptr cinfo, - J_COLOR_SPACE colorspace)); -EXTERN(void) jpeg_default_colorspace JPP((j_compress_ptr cinfo)); -EXTERN(void) jpeg_set_quality JPP((j_compress_ptr cinfo, int quality, - boolean force_baseline)); -EXTERN(void) jpeg_set_linear_quality JPP((j_compress_ptr cinfo, - int scale_factor, - boolean force_baseline)); -EXTERN(void) jpeg_default_qtables JPP((j_compress_ptr cinfo, - boolean force_baseline)); -EXTERN(void) jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl, - const unsigned int *basic_table, - int scale_factor, - boolean force_baseline)); -EXTERN(int) jpeg_quality_scaling JPP((int quality)); -EXTERN(void) jpeg_simple_progression JPP((j_compress_ptr cinfo)); -EXTERN(void) jpeg_suppress_tables JPP((j_compress_ptr cinfo, - boolean suppress)); -EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table JPP((j_common_ptr cinfo)); -EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table JPP((j_common_ptr cinfo)); - -/* Main entry points for compression */ -EXTERN(void) jpeg_start_compress JPP((j_compress_ptr cinfo, - boolean write_all_tables)); -EXTERN(JDIMENSION) jpeg_write_scanlines JPP((j_compress_ptr cinfo, - JSAMPARRAY scanlines, - JDIMENSION num_lines)); -EXTERN(void) jpeg_finish_compress JPP((j_compress_ptr cinfo)); - -/* Precalculate JPEG dimensions for current compression parameters. */ -EXTERN(void) jpeg_calc_jpeg_dimensions JPP((j_compress_ptr cinfo)); - -/* Replaces jpeg_write_scanlines when writing raw downsampled data. */ -EXTERN(JDIMENSION) jpeg_write_raw_data JPP((j_compress_ptr cinfo, - JSAMPIMAGE data, - JDIMENSION num_lines)); - -/* Write a special marker. See libjpeg.txt concerning safe usage. */ -EXTERN(void) jpeg_write_marker - JPP((j_compress_ptr cinfo, int marker, - const JOCTET * dataptr, unsigned int datalen)); -/* Same, but piecemeal. */ -EXTERN(void) jpeg_write_m_header - JPP((j_compress_ptr cinfo, int marker, unsigned int datalen)); -EXTERN(void) jpeg_write_m_byte - JPP((j_compress_ptr cinfo, int val)); - -/* Alternate compression function: just write an abbreviated table file */ -EXTERN(void) jpeg_write_tables JPP((j_compress_ptr cinfo)); - -/* Decompression startup: read start of JPEG datastream to see what's there */ -EXTERN(int) jpeg_read_header JPP((j_decompress_ptr cinfo, - boolean require_image)); -/* Return value is one of: */ -#define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */ -#define JPEG_HEADER_OK 1 /* Found valid image datastream */ -#define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */ -/* If you pass require_image = TRUE (normal case), you need not check for - * a TABLES_ONLY return code; an abbreviated file will cause an error exit. - * JPEG_SUSPENDED is only possible if you use a data source module that can - * give a suspension return (the stdio source module doesn't). - */ - -/* Main entry points for decompression */ -EXTERN(boolean) jpeg_start_decompress JPP((j_decompress_ptr cinfo)); -EXTERN(JDIMENSION) jpeg_read_scanlines JPP((j_decompress_ptr cinfo, - JSAMPARRAY scanlines, - JDIMENSION max_lines)); -EXTERN(boolean) jpeg_finish_decompress JPP((j_decompress_ptr cinfo)); - -/* Replaces jpeg_read_scanlines when reading raw downsampled data. */ -EXTERN(JDIMENSION) jpeg_read_raw_data JPP((j_decompress_ptr cinfo, - JSAMPIMAGE data, - JDIMENSION max_lines)); - -/* Additional entry points for buffered-image mode. */ -EXTERN(boolean) jpeg_has_multiple_scans JPP((j_decompress_ptr cinfo)); -EXTERN(boolean) jpeg_start_output JPP((j_decompress_ptr cinfo, - int scan_number)); -EXTERN(boolean) jpeg_finish_output JPP((j_decompress_ptr cinfo)); -EXTERN(boolean) jpeg_input_complete JPP((j_decompress_ptr cinfo)); -EXTERN(void) jpeg_new_colormap JPP((j_decompress_ptr cinfo)); -EXTERN(int) jpeg_consume_input JPP((j_decompress_ptr cinfo)); -/* Return value is one of: */ -/* #define JPEG_SUSPENDED 0 Suspended due to lack of input data */ -#define JPEG_REACHED_SOS 1 /* Reached start of new scan */ -#define JPEG_REACHED_EOI 2 /* Reached end of image */ -#define JPEG_ROW_COMPLETED 3 /* Completed one iMCU row */ -#define JPEG_SCAN_COMPLETED 4 /* Completed last iMCU row of a scan */ - -/* Precalculate output dimensions for current decompression parameters. */ -EXTERN(void) jpeg_core_output_dimensions JPP((j_decompress_ptr cinfo)); -EXTERN(void) jpeg_calc_output_dimensions JPP((j_decompress_ptr cinfo)); - -/* Control saving of COM and APPn markers into marker_list. */ -EXTERN(void) jpeg_save_markers - JPP((j_decompress_ptr cinfo, int marker_code, - unsigned int length_limit)); - -/* Install a special processing method for COM or APPn markers. */ -EXTERN(void) jpeg_set_marker_processor - JPP((j_decompress_ptr cinfo, int marker_code, - jpeg_marker_parser_method routine)); - -/* Read or write raw DCT coefficients --- useful for lossless transcoding. */ -EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients JPP((j_decompress_ptr cinfo)); -EXTERN(void) jpeg_write_coefficients JPP((j_compress_ptr cinfo, - jvirt_barray_ptr * coef_arrays)); -EXTERN(void) jpeg_copy_critical_parameters JPP((j_decompress_ptr srcinfo, - j_compress_ptr dstinfo)); - -/* If you choose to abort compression or decompression before completing - * jpeg_finish_(de)compress, then you need to clean up to release memory, - * temporary files, etc. You can just call jpeg_destroy_(de)compress - * if you're done with the JPEG object, but if you want to clean it up and - * reuse it, call this: - */ -EXTERN(void) jpeg_abort_compress JPP((j_compress_ptr cinfo)); -EXTERN(void) jpeg_abort_decompress JPP((j_decompress_ptr cinfo)); - -/* Generic versions of jpeg_abort and jpeg_destroy that work on either - * flavor of JPEG object. These may be more convenient in some places. - */ -EXTERN(void) jpeg_abort JPP((j_common_ptr cinfo)); -EXTERN(void) jpeg_destroy JPP((j_common_ptr cinfo)); - -/* Default restart-marker-resync procedure for use by data source modules */ -EXTERN(boolean) jpeg_resync_to_restart JPP((j_decompress_ptr cinfo, - int desired)); - - -/* These marker codes are exported since applications and data source modules - * are likely to want to use them. - */ - -#define JPEG_RST0 0xD0 /* RST0 marker code */ -#define JPEG_EOI 0xD9 /* EOI marker code */ -#define JPEG_APP0 0xE0 /* APP0 marker code */ -#define JPEG_COM 0xFE /* COM marker code */ - - -/* If we have a brain-damaged compiler that emits warnings (or worse, errors) - * for structure definitions that are never filled in, keep it quiet by - * supplying dummy definitions for the various substructures. - */ - -#ifdef INCOMPLETE_TYPES_BROKEN -#ifndef JPEG_INTERNALS /* will be defined in jpegint.h */ -struct jvirt_sarray_control { long dummy; }; -struct jvirt_barray_control { long dummy; }; -struct jpeg_comp_master { long dummy; }; -struct jpeg_c_main_controller { long dummy; }; -struct jpeg_c_prep_controller { long dummy; }; -struct jpeg_c_coef_controller { long dummy; }; -struct jpeg_marker_writer { long dummy; }; -struct jpeg_color_converter { long dummy; }; -struct jpeg_downsampler { long dummy; }; -struct jpeg_forward_dct { long dummy; }; -struct jpeg_entropy_encoder { long dummy; }; -struct jpeg_decomp_master { long dummy; }; -struct jpeg_d_main_controller { long dummy; }; -struct jpeg_d_coef_controller { long dummy; }; -struct jpeg_d_post_controller { long dummy; }; -struct jpeg_input_controller { long dummy; }; -struct jpeg_marker_reader { long dummy; }; -struct jpeg_entropy_decoder { long dummy; }; -struct jpeg_inverse_dct { long dummy; }; -struct jpeg_upsampler { long dummy; }; -struct jpeg_color_deconverter { long dummy; }; -struct jpeg_color_quantizer { long dummy; }; -#endif /* JPEG_INTERNALS */ -#endif /* INCOMPLETE_TYPES_BROKEN */ - - -/* - * The JPEG library modules define JPEG_INTERNALS before including this file. - * The internal structure declarations are read only when that is true. - * Applications using the library should not include jpegint.h, but may wish - * to include jerror.h. - */ - -#ifdef JPEG_INTERNALS -#include "jpegint.h" /* fetch private declarations */ -#include "jerror.h" /* fetch error codes too */ -#endif - -#ifdef __cplusplus -#ifndef DONT_USE_EXTERN_C -} -#endif -#endif - -#endif /* JPEGLIB_H */ diff --git a/reactos/dll/3rdparty/libjpeg/jversion.h b/reactos/dll/3rdparty/libjpeg/jversion.h deleted file mode 100644 index 70c8b6fe176..00000000000 --- a/reactos/dll/3rdparty/libjpeg/jversion.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * jversion.h - * - * Copyright (C) 1991-2010, Thomas G. Lane, Guido Vollbeding. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains software version identification. - */ - - -#define JVERSION "8b 16-May-2010" - -#define JCOPYRIGHT "Copyright (C) 2010, Thomas G. Lane, Guido Vollbeding" diff --git a/reactos/dll/3rdparty/libjpeg/libjpeg.rbuild b/reactos/dll/3rdparty/libjpeg/libjpeg.rbuild index 5916c5de7ee..7baac85f6d4 100644 --- a/reactos/dll/3rdparty/libjpeg/libjpeg.rbuild +++ b/reactos/dll/3rdparty/libjpeg/libjpeg.rbuild @@ -7,6 +7,8 @@ mainptr . + include/reactos/libs/libjpeg + include/reactos/libs/zlib jaricom.c jcapimin.c jcapistd.c diff --git a/reactos/dll/3rdparty/libjpeg/makefile.ansi b/reactos/dll/3rdparty/libjpeg/makefile.ansi deleted file mode 100644 index 7d0499f8f49..00000000000 --- a/reactos/dll/3rdparty/libjpeg/makefile.ansi +++ /dev/null @@ -1,221 +0,0 @@ -# Makefile for Independent JPEG Group's software - -# This makefile is suitable for Unix-like systems with ANSI-capable compilers. -# If you have a non-ANSI compiler, makefile.unix is a better starting point. - -# Read installation instructions before saying "make" !! - -# The name of your C compiler: -CC= cc - -# You may need to adjust these cc options: -CFLAGS= -O -# Generally, we recommend defining any configuration symbols in jconfig.h, -# NOT via -D switches here. - -# Link-time cc options: -LDFLAGS= - -# To link any special libraries, add the necessary -l commands here. -LDLIBS= - -# Put here the object file name for the correct system-dependent memory -# manager file. For Unix this is usually jmemnobs.o, but you may want -# to use jmemansi.o or jmemname.o if you have limited swap space. -SYSDEPMEM= jmemnobs.o - -# miscellaneous OS-dependent stuff -# linker -LN= $(CC) -# file deletion command -RM= rm -f -# library (.a) file creation command -AR= ar rc -# second step in .a creation (use "touch" if not needed) -AR2= ranlib - -# End of configurable options. - - -# source files: JPEG library proper -LIBSOURCES= jaricom.c jcapimin.c jcapistd.c jcarith.c jccoefct.c jccolor.c \ - jcdctmgr.c jchuff.c jcinit.c jcmainct.c jcmarker.c jcmaster.c \ - jcomapi.c jcparam.c jcprepct.c jcsample.c jctrans.c jdapimin.c \ - jdapistd.c jdarith.c jdatadst.c jdatasrc.c jdcoefct.c jdcolor.c \ - jddctmgr.c jdhuff.c jdinput.c jdmainct.c jdmarker.c jdmaster.c \ - jdmerge.c jdpostct.c jdsample.c jdtrans.c jerror.c jfdctflt.c \ - jfdctfst.c jfdctint.c jidctflt.c jidctfst.c jidctint.c jquant1.c \ - jquant2.c jutils.c jmemmgr.c -# memmgr back ends: compile only one of these into a working library -SYSDEPSOURCES= jmemansi.c jmemname.c jmemnobs.c jmemdos.c jmemmac.c -# source files: cjpeg/djpeg/jpegtran applications, also rdjpgcom/wrjpgcom -APPSOURCES= cjpeg.c djpeg.c jpegtran.c rdjpgcom.c wrjpgcom.c cdjpeg.c \ - rdcolmap.c rdswitch.c transupp.c rdppm.c wrppm.c rdgif.c wrgif.c \ - rdtarga.c wrtarga.c rdbmp.c wrbmp.c rdrle.c wrrle.c -SOURCES= $(LIBSOURCES) $(SYSDEPSOURCES) $(APPSOURCES) -# files included by source files -INCLUDES= jdct.h jerror.h jinclude.h jmemsys.h jmorecfg.h jpegint.h \ - jpeglib.h jversion.h cdjpeg.h cderror.h transupp.h -# documentation, test, and support files -DOCS= README install.txt usage.txt cjpeg.1 djpeg.1 jpegtran.1 rdjpgcom.1 \ - wrjpgcom.1 wizard.txt example.c libjpeg.txt structure.txt \ - coderules.txt filelist.txt change.log -MKFILES= configure Makefile.in makefile.ansi makefile.unix makefile.bcc \ - makefile.mc6 makefile.dj makefile.wat makefile.vc makejdsw.vc6 \ - makeadsw.vc6 makejdep.vc6 makejdsp.vc6 makejmak.vc6 makecdep.vc6 \ - makecdsp.vc6 makecmak.vc6 makeddep.vc6 makeddsp.vc6 makedmak.vc6 \ - maketdep.vc6 maketdsp.vc6 maketmak.vc6 makerdep.vc6 makerdsp.vc6 \ - makermak.vc6 makewdep.vc6 makewdsp.vc6 makewmak.vc6 makejsln.v10 \ - makeasln.v10 makejvcx.v10 makejfil.v10 makecvcx.v10 makecfil.v10 \ - makedvcx.v10 makedfil.v10 maketvcx.v10 maketfil.v10 makervcx.v10 \ - makerfil.v10 makewvcx.v10 makewfil.v10 makeproj.mac makcjpeg.st \ - makdjpeg.st makljpeg.st maktjpeg.st makefile.manx makefile.sas \ - makefile.mms makefile.vms makvms.opt -CONFIGFILES= jconfig.cfg jconfig.bcc jconfig.mc6 jconfig.dj jconfig.wat \ - jconfig.vc jconfig.mac jconfig.st jconfig.manx jconfig.sas \ - jconfig.vms -CONFIGUREFILES= config.guess config.sub install-sh ltmain.sh depcomp missing -OTHERFILES= jconfig.txt ckconfig.c ansi2knr.c ansi2knr.1 jmemdosa.asm \ - libjpeg.map -TESTFILES= testorig.jpg testimg.ppm testimg.bmp testimg.jpg testprog.jpg \ - testimgp.jpg -DISTFILES= $(DOCS) $(MKFILES) $(CONFIGFILES) $(SOURCES) $(INCLUDES) \ - $(CONFIGUREFILES) $(OTHERFILES) $(TESTFILES) -# library object files common to compression and decompression -COMOBJECTS= jaricom.o jcomapi.o jutils.o jerror.o jmemmgr.o $(SYSDEPMEM) -# compression library object files -CLIBOBJECTS= jcapimin.o jcapistd.o jcarith.o jctrans.o jcparam.o \ - jdatadst.o jcinit.o jcmaster.o jcmarker.o jcmainct.o jcprepct.o \ - jccoefct.o jccolor.o jcsample.o jchuff.o jcdctmgr.o jfdctfst.o \ - jfdctflt.o jfdctint.o -# decompression library object files -DLIBOBJECTS= jdapimin.o jdapistd.o jdarith.o jdtrans.o jdatasrc.o \ - jdmaster.o jdinput.o jdmarker.o jdhuff.o jdmainct.o \ - jdcoefct.o jdpostct.o jddctmgr.o jidctfst.o jidctflt.o \ - jidctint.o jdsample.o jdcolor.o jquant1.o jquant2.o jdmerge.o -# These objectfiles are included in libjpeg.a -LIBOBJECTS= $(CLIBOBJECTS) $(DLIBOBJECTS) $(COMOBJECTS) -# object files for sample applications (excluding library files) -COBJECTS= cjpeg.o rdppm.o rdgif.o rdtarga.o rdrle.o rdbmp.o rdswitch.o \ - cdjpeg.o -DOBJECTS= djpeg.o wrppm.o wrgif.o wrtarga.o wrrle.o wrbmp.o rdcolmap.o \ - cdjpeg.o -TROBJECTS= jpegtran.o rdswitch.o cdjpeg.o transupp.o - - -all: libjpeg.a cjpeg djpeg jpegtran rdjpgcom wrjpgcom - -libjpeg.a: $(LIBOBJECTS) - $(RM) libjpeg.a - $(AR) libjpeg.a $(LIBOBJECTS) - $(AR2) libjpeg.a - -cjpeg: $(COBJECTS) libjpeg.a - $(LN) $(LDFLAGS) -o cjpeg $(COBJECTS) libjpeg.a $(LDLIBS) - -djpeg: $(DOBJECTS) libjpeg.a - $(LN) $(LDFLAGS) -o djpeg $(DOBJECTS) libjpeg.a $(LDLIBS) - -jpegtran: $(TROBJECTS) libjpeg.a - $(LN) $(LDFLAGS) -o jpegtran $(TROBJECTS) libjpeg.a $(LDLIBS) - -rdjpgcom: rdjpgcom.o - $(LN) $(LDFLAGS) -o rdjpgcom rdjpgcom.o $(LDLIBS) - -wrjpgcom: wrjpgcom.o - $(LN) $(LDFLAGS) -o wrjpgcom wrjpgcom.o $(LDLIBS) - -jconfig.h: jconfig.txt - echo You must prepare a system-dependent jconfig.h file. - echo Please read the installation directions in install.txt. - exit 1 - -clean: - $(RM) *.o cjpeg djpeg jpegtran libjpeg.a rdjpgcom wrjpgcom - $(RM) core testout* - -test: cjpeg djpeg jpegtran - $(RM) testout* - ./djpeg -dct int -ppm -outfile testout.ppm testorig.jpg - ./djpeg -dct int -bmp -colors 256 -outfile testout.bmp testorig.jpg - ./cjpeg -dct int -outfile testout.jpg testimg.ppm - ./djpeg -dct int -ppm -outfile testoutp.ppm testprog.jpg - ./cjpeg -dct int -progressive -opt -outfile testoutp.jpg testimg.ppm - ./jpegtran -outfile testoutt.jpg testprog.jpg - cmp testimg.ppm testout.ppm - cmp testimg.bmp testout.bmp - cmp testimg.jpg testout.jpg - cmp testimg.ppm testoutp.ppm - cmp testimgp.jpg testoutp.jpg - cmp testorig.jpg testoutt.jpg - - -jaricom.o: jaricom.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h -jcapimin.o: jcapimin.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h -jcapistd.o: jcapistd.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h -jcarith.o: jcarith.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h -jccoefct.o: jccoefct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h -jccolor.o: jccolor.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h -jcdctmgr.o: jcdctmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h -jchuff.o: jchuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h -jcinit.o: jcinit.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h -jcmainct.o: jcmainct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h -jcmarker.o: jcmarker.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h -jcmaster.o: jcmaster.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h -jcomapi.o: jcomapi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h -jcparam.o: jcparam.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h -jcprepct.o: jcprepct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h -jcsample.o: jcsample.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h -jctrans.o: jctrans.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h -jdapimin.o: jdapimin.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h -jdapistd.o: jdapistd.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h -jdarith.o: jdarith.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h -jdatadst.o: jdatadst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h -jdatasrc.o: jdatasrc.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h -jdcoefct.o: jdcoefct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h -jdcolor.o: jdcolor.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h -jddctmgr.o: jddctmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h -jdhuff.o: jdhuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h -jdinput.o: jdinput.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h -jdmainct.o: jdmainct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h -jdmarker.o: jdmarker.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h -jdmaster.o: jdmaster.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h -jdmerge.o: jdmerge.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h -jdpostct.o: jdpostct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h -jdsample.o: jdsample.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h -jdtrans.o: jdtrans.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h -jerror.o: jerror.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jversion.h jerror.h -jfdctflt.o: jfdctflt.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h -jfdctfst.o: jfdctfst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h -jfdctint.o: jfdctint.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h -jidctflt.o: jidctflt.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h -jidctfst.o: jidctfst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h -jidctint.o: jidctint.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h -jquant1.o: jquant1.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h -jquant2.o: jquant2.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h -jutils.o: jutils.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h -jmemmgr.o: jmemmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h -jmemansi.o: jmemansi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h -jmemname.o: jmemname.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h -jmemnobs.o: jmemnobs.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h -jmemdos.o: jmemdos.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h -jmemmac.o: jmemmac.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h -cjpeg.o: cjpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h jversion.h -djpeg.o: djpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h jversion.h -jpegtran.o: jpegtran.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h transupp.h jversion.h -rdjpgcom.o: rdjpgcom.c jinclude.h jconfig.h -wrjpgcom.o: wrjpgcom.c jinclude.h jconfig.h -cdjpeg.o: cdjpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h -rdcolmap.o: rdcolmap.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h -rdswitch.o: rdswitch.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h -transupp.o: transupp.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h transupp.h -rdppm.o: rdppm.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h -wrppm.o: wrppm.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h -rdgif.o: rdgif.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h -wrgif.o: wrgif.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h -rdtarga.o: rdtarga.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h -wrtarga.o: wrtarga.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h -rdbmp.o: rdbmp.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h -wrbmp.o: wrbmp.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h -rdrle.o: rdrle.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h -wrrle.o: wrrle.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h diff --git a/reactos/dll/3rdparty/libjpeg/transupp.h b/reactos/dll/3rdparty/libjpeg/transupp.h deleted file mode 100644 index 7c16c19c440..00000000000 --- a/reactos/dll/3rdparty/libjpeg/transupp.h +++ /dev/null @@ -1,210 +0,0 @@ -/* - * transupp.h - * - * Copyright (C) 1997-2009, Thomas G. Lane, Guido Vollbeding. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains declarations for image transformation routines and - * other utility code used by the jpegtran sample application. These are - * NOT part of the core JPEG library. But we keep these routines separate - * from jpegtran.c to ease the task of maintaining jpegtran-like programs - * that have other user interfaces. - * - * NOTE: all the routines declared here have very specific requirements - * about when they are to be executed during the reading and writing of the - * source and destination files. See the comments in transupp.c, or see - * jpegtran.c for an example of correct usage. - */ - -/* If you happen not to want the image transform support, disable it here */ -#ifndef TRANSFORMS_SUPPORTED -#define TRANSFORMS_SUPPORTED 1 /* 0 disables transform code */ -#endif - -/* - * Although rotating and flipping data expressed as DCT coefficients is not - * hard, there is an asymmetry in the JPEG format specification for images - * whose dimensions aren't multiples of the iMCU size. The right and bottom - * image edges are padded out to the next iMCU boundary with junk data; but - * no padding is possible at the top and left edges. If we were to flip - * the whole image including the pad data, then pad garbage would become - * visible at the top and/or left, and real pixels would disappear into the - * pad margins --- perhaps permanently, since encoders & decoders may not - * bother to preserve DCT blocks that appear to be completely outside the - * nominal image area. So, we have to exclude any partial iMCUs from the - * basic transformation. - * - * Transpose is the only transformation that can handle partial iMCUs at the - * right and bottom edges completely cleanly. flip_h can flip partial iMCUs - * at the bottom, but leaves any partial iMCUs at the right edge untouched. - * Similarly flip_v leaves any partial iMCUs at the bottom edge untouched. - * The other transforms are defined as combinations of these basic transforms - * and process edge blocks in a way that preserves the equivalence. - * - * The "trim" option causes untransformable partial iMCUs to be dropped; - * this is not strictly lossless, but it usually gives the best-looking - * result for odd-size images. Note that when this option is active, - * the expected mathematical equivalences between the transforms may not hold. - * (For example, -rot 270 -trim trims only the bottom edge, but -rot 90 -trim - * followed by -rot 180 -trim trims both edges.) - * - * We also offer a lossless-crop option, which discards data outside a given - * image region but losslessly preserves what is inside. Like the rotate and - * flip transforms, lossless crop is restricted by the JPEG format: the upper - * left corner of the selected region must fall on an iMCU boundary. If this - * does not hold for the given crop parameters, we silently move the upper left - * corner up and/or left to make it so, simultaneously increasing the region - * dimensions to keep the lower right crop corner unchanged. (Thus, the - * output image covers at least the requested region, but may cover more.) - * - * We also provide a lossless-resize option, which is kind of a lossless-crop - * operation in the DCT coefficient block domain - it discards higher-order - * coefficients and losslessly preserves lower-order coefficients of a - * sub-block. - * - * Rotate/flip transform, resize, and crop can be requested together in a - * single invocation. The crop is applied last --- that is, the crop region - * is specified in terms of the destination image after transform/resize. - * - * We also offer a "force to grayscale" option, which simply discards the - * chrominance channels of a YCbCr image. This is lossless in the sense that - * the luminance channel is preserved exactly. It's not the same kind of - * thing as the rotate/flip transformations, but it's convenient to handle it - * as part of this package, mainly because the transformation routines have to - * be aware of the option to know how many components to work on. - */ - - -/* Short forms of external names for systems with brain-damaged linkers. */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jtransform_parse_crop_spec jTrParCrop -#define jtransform_request_workspace jTrRequest -#define jtransform_adjust_parameters jTrAdjust -#define jtransform_execute_transform jTrExec -#define jtransform_perfect_transform jTrPerfect -#define jcopy_markers_setup jCMrkSetup -#define jcopy_markers_execute jCMrkExec -#endif /* NEED_SHORT_EXTERNAL_NAMES */ - - -/* - * Codes for supported types of image transformations. - */ - -typedef enum { - JXFORM_NONE, /* no transformation */ - JXFORM_FLIP_H, /* horizontal flip */ - JXFORM_FLIP_V, /* vertical flip */ - JXFORM_TRANSPOSE, /* transpose across UL-to-LR axis */ - JXFORM_TRANSVERSE, /* transpose across UR-to-LL axis */ - JXFORM_ROT_90, /* 90-degree clockwise rotation */ - JXFORM_ROT_180, /* 180-degree rotation */ - JXFORM_ROT_270 /* 270-degree clockwise (or 90 ccw) */ -} JXFORM_CODE; - -/* - * Codes for crop parameters, which can individually be unspecified, - * positive, or negative. (Negative width or height makes no sense, though.) - */ - -typedef enum { - JCROP_UNSET, - JCROP_POS, - JCROP_NEG -} JCROP_CODE; - -/* - * Transform parameters struct. - * NB: application must not change any elements of this struct after - * calling jtransform_request_workspace. - */ - -typedef struct { - /* Options: set by caller */ - JXFORM_CODE transform; /* image transform operator */ - boolean perfect; /* if TRUE, fail if partial MCUs are requested */ - boolean trim; /* if TRUE, trim partial MCUs as needed */ - boolean force_grayscale; /* if TRUE, convert color image to grayscale */ - boolean crop; /* if TRUE, crop source image */ - - /* Crop parameters: application need not set these unless crop is TRUE. - * These can be filled in by jtransform_parse_crop_spec(). - */ - JDIMENSION crop_width; /* Width of selected region */ - JCROP_CODE crop_width_set; - JDIMENSION crop_height; /* Height of selected region */ - JCROP_CODE crop_height_set; - JDIMENSION crop_xoffset; /* X offset of selected region */ - JCROP_CODE crop_xoffset_set; /* (negative measures from right edge) */ - JDIMENSION crop_yoffset; /* Y offset of selected region */ - JCROP_CODE crop_yoffset_set; /* (negative measures from bottom edge) */ - - /* Internal workspace: caller should not touch these */ - int num_components; /* # of components in workspace */ - jvirt_barray_ptr * workspace_coef_arrays; /* workspace for transformations */ - JDIMENSION output_width; /* cropped destination dimensions */ - JDIMENSION output_height; - JDIMENSION x_crop_offset; /* destination crop offsets measured in iMCUs */ - JDIMENSION y_crop_offset; - int iMCU_sample_width; /* destination iMCU size */ - int iMCU_sample_height; -} jpeg_transform_info; - - -#if TRANSFORMS_SUPPORTED - -/* Parse a crop specification (written in X11 geometry style) */ -EXTERN(boolean) jtransform_parse_crop_spec - JPP((jpeg_transform_info *info, const char *spec)); -/* Request any required workspace */ -EXTERN(boolean) jtransform_request_workspace - JPP((j_decompress_ptr srcinfo, jpeg_transform_info *info)); -/* Adjust output image parameters */ -EXTERN(jvirt_barray_ptr *) jtransform_adjust_parameters - JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo, - jvirt_barray_ptr *src_coef_arrays, - jpeg_transform_info *info)); -/* Execute the actual transformation, if any */ -EXTERN(void) jtransform_execute_transform - JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo, - jvirt_barray_ptr *src_coef_arrays, - jpeg_transform_info *info)); -/* Determine whether lossless transformation is perfectly - * possible for a specified image and transformation. - */ -EXTERN(boolean) jtransform_perfect_transform - JPP((JDIMENSION image_width, JDIMENSION image_height, - int MCU_width, int MCU_height, - JXFORM_CODE transform)); - -/* jtransform_execute_transform used to be called - * jtransform_execute_transformation, but some compilers complain about - * routine names that long. This macro is here to avoid breaking any - * old source code that uses the original name... - */ -#define jtransform_execute_transformation jtransform_execute_transform - -#endif /* TRANSFORMS_SUPPORTED */ - - -/* - * Support for copying optional markers from source to destination file. - */ - -typedef enum { - JCOPYOPT_NONE, /* copy no optional markers */ - JCOPYOPT_COMMENTS, /* copy only comment (COM) markers */ - JCOPYOPT_ALL /* copy all optional markers */ -} JCOPY_OPTION; - -#define JCOPYOPT_DEFAULT JCOPYOPT_COMMENTS /* recommended default */ - -/* Setup decompression object to save desired markers in memory */ -EXTERN(void) jcopy_markers_setup - JPP((j_decompress_ptr srcinfo, JCOPY_OPTION option)); -/* Copy markers saved in the given source object to the destination object */ -EXTERN(void) jcopy_markers_execute - JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo, - JCOPY_OPTION option)); diff --git a/reactos/dll/3rdparty/libpng/libpng.rbuild b/reactos/dll/3rdparty/libpng/libpng.rbuild index 806d418cdbc..d9960db6d30 100644 --- a/reactos/dll/3rdparty/libpng/libpng.rbuild +++ b/reactos/dll/3rdparty/libpng/libpng.rbuild @@ -6,7 +6,8 @@ . - lib/3rdparty/zlib + include/reactos/libs/zlib + include/reactos/libs/libpng zlib png.c pngerror.c diff --git a/reactos/dll/3rdparty/libpng/png.h b/reactos/dll/3rdparty/libpng/png.h deleted file mode 100644 index 842f3fc951b..00000000000 --- a/reactos/dll/3rdparty/libpng/png.h +++ /dev/null @@ -1,2701 +0,0 @@ - -/* png.h - header file for PNG reference library - * - * libpng version 1.4.3 - June 26, 2010 - * Copyright (c) 1998-2010 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This code is released under the libpng license (See LICENSE, below) - * - * Authors and maintainers: - * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat - * libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger - * libpng versions 0.97, January 1998, through 1.4.3 - June 26, 2010: Glenn - * See also "Contributing Authors", below. - * - * Note about libpng version numbers: - * - * Due to various miscommunications, unforeseen code incompatibilities - * and occasional factors outside the authors' control, version numbering - * on the library has not always been consistent and straightforward. - * The following table summarizes matters since version 0.89c, which was - * the first widely used release: - * - * source png.h png.h shared-lib - * version string int version - * ------- ------ ----- ---------- - * 0.89c "1.0 beta 3" 0.89 89 1.0.89 - * 0.90 "1.0 beta 4" 0.90 90 0.90 [should have been 2.0.90] - * 0.95 "1.0 beta 5" 0.95 95 0.95 [should have been 2.0.95] - * 0.96 "1.0 beta 6" 0.96 96 0.96 [should have been 2.0.96] - * 0.97b "1.00.97 beta 7" 1.00.97 97 1.0.1 [should have been 2.0.97] - * 0.97c 0.97 97 2.0.97 - * 0.98 0.98 98 2.0.98 - * 0.99 0.99 98 2.0.99 - * 0.99a-m 0.99 99 2.0.99 - * 1.00 1.00 100 2.1.0 [100 should be 10000] - * 1.0.0 (from here on, the 100 2.1.0 [100 should be 10000] - * 1.0.1 png.h string is 10001 2.1.0 - * 1.0.1a-e identical to the 10002 from here on, the shared library - * 1.0.2 source version) 10002 is 2.V where V is the source code - * 1.0.2a-b 10003 version, except as noted. - * 1.0.3 10003 - * 1.0.3a-d 10004 - * 1.0.4 10004 - * 1.0.4a-f 10005 - * 1.0.5 (+ 2 patches) 10005 - * 1.0.5a-d 10006 - * 1.0.5e-r 10100 (not source compatible) - * 1.0.5s-v 10006 (not binary compatible) - * 1.0.6 (+ 3 patches) 10006 (still binary incompatible) - * 1.0.6d-f 10007 (still binary incompatible) - * 1.0.6g 10007 - * 1.0.6h 10007 10.6h (testing xy.z so-numbering) - * 1.0.6i 10007 10.6i - * 1.0.6j 10007 2.1.0.6j (incompatible with 1.0.0) - * 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 (binary compatible) - * 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 (binary compatible) - * 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible) - * 1.0.7 1 10007 (still compatible) - * 1.0.8beta1-4 1 10008 2.1.0.8beta1-4 - * 1.0.8rc1 1 10008 2.1.0.8rc1 - * 1.0.8 1 10008 2.1.0.8 - * 1.0.9beta1-6 1 10009 2.1.0.9beta1-6 - * 1.0.9rc1 1 10009 2.1.0.9rc1 - * 1.0.9beta7-10 1 10009 2.1.0.9beta7-10 - * 1.0.9rc2 1 10009 2.1.0.9rc2 - * 1.0.9 1 10009 2.1.0.9 - * 1.0.10beta1 1 10010 2.1.0.10beta1 - * 1.0.10rc1 1 10010 2.1.0.10rc1 - * 1.0.10 1 10010 2.1.0.10 - * 1.0.11beta1-3 1 10011 2.1.0.11beta1-3 - * 1.0.11rc1 1 10011 2.1.0.11rc1 - * 1.0.11 1 10011 2.1.0.11 - * 1.0.12beta1-2 2 10012 2.1.0.12beta1-2 - * 1.0.12rc1 2 10012 2.1.0.12rc1 - * 1.0.12 2 10012 2.1.0.12 - * 1.1.0a-f - 10100 2.1.1.0a-f (branch abandoned) - * 1.2.0beta1-2 2 10200 2.1.2.0beta1-2 - * 1.2.0beta3-5 3 10200 3.1.2.0beta3-5 - * 1.2.0rc1 3 10200 3.1.2.0rc1 - * 1.2.0 3 10200 3.1.2.0 - * 1.2.1beta1-4 3 10201 3.1.2.1beta1-4 - * 1.2.1rc1-2 3 10201 3.1.2.1rc1-2 - * 1.2.1 3 10201 3.1.2.1 - * 1.2.2beta1-6 12 10202 12.so.0.1.2.2beta1-6 - * 1.0.13beta1 10 10013 10.so.0.1.0.13beta1 - * 1.0.13rc1 10 10013 10.so.0.1.0.13rc1 - * 1.2.2rc1 12 10202 12.so.0.1.2.2rc1 - * 1.0.13 10 10013 10.so.0.1.0.13 - * 1.2.2 12 10202 12.so.0.1.2.2 - * 1.2.3rc1-6 12 10203 12.so.0.1.2.3rc1-6 - * 1.2.3 12 10203 12.so.0.1.2.3 - * 1.2.4beta1-3 13 10204 12.so.0.1.2.4beta1-3 - * 1.0.14rc1 13 10014 10.so.0.1.0.14rc1 - * 1.2.4rc1 13 10204 12.so.0.1.2.4rc1 - * 1.0.14 10 10014 10.so.0.1.0.14 - * 1.2.4 13 10204 12.so.0.1.2.4 - * 1.2.5beta1-2 13 10205 12.so.0.1.2.5beta1-2 - * 1.0.15rc1-3 10 10015 10.so.0.1.0.15rc1-3 - * 1.2.5rc1-3 13 10205 12.so.0.1.2.5rc1-3 - * 1.0.15 10 10015 10.so.0.1.0.15 - * 1.2.5 13 10205 12.so.0.1.2.5 - * 1.2.6beta1-4 13 10206 12.so.0.1.2.6beta1-4 - * 1.0.16 10 10016 10.so.0.1.0.16 - * 1.2.6 13 10206 12.so.0.1.2.6 - * 1.2.7beta1-2 13 10207 12.so.0.1.2.7beta1-2 - * 1.0.17rc1 10 10017 12.so.0.1.0.17rc1 - * 1.2.7rc1 13 10207 12.so.0.1.2.7rc1 - * 1.0.17 10 10017 12.so.0.1.0.17 - * 1.2.7 13 10207 12.so.0.1.2.7 - * 1.2.8beta1-5 13 10208 12.so.0.1.2.8beta1-5 - * 1.0.18rc1-5 10 10018 12.so.0.1.0.18rc1-5 - * 1.2.8rc1-5 13 10208 12.so.0.1.2.8rc1-5 - * 1.0.18 10 10018 12.so.0.1.0.18 - * 1.2.8 13 10208 12.so.0.1.2.8 - * 1.2.9beta1-3 13 10209 12.so.0.1.2.9beta1-3 - * 1.2.9beta4-11 13 10209 12.so.0.9[.0] - * 1.2.9rc1 13 10209 12.so.0.9[.0] - * 1.2.9 13 10209 12.so.0.9[.0] - * 1.2.10beta1-7 13 10210 12.so.0.10[.0] - * 1.2.10rc1-2 13 10210 12.so.0.10[.0] - * 1.2.10 13 10210 12.so.0.10[.0] - * 1.4.0beta1-5 14 10400 14.so.0.0[.0] - * 1.2.11beta1-4 13 10211 12.so.0.11[.0] - * 1.4.0beta7-8 14 10400 14.so.0.0[.0] - * 1.2.11 13 10211 12.so.0.11[.0] - * 1.2.12 13 10212 12.so.0.12[.0] - * 1.4.0beta9-14 14 10400 14.so.0.0[.0] - * 1.2.13 13 10213 12.so.0.13[.0] - * 1.4.0beta15-36 14 10400 14.so.0.0[.0] - * 1.4.0beta37-87 14 10400 14.so.14.0[.0] - * 1.4.0rc01 14 10400 14.so.14.0[.0] - * 1.4.0beta88-109 14 10400 14.so.14.0[.0] - * 1.4.0rc02-08 14 10400 14.so.14.0[.0] - * 1.4.0 14 10400 14.so.14.0[.0] - * 1.4.1beta01-03 14 10401 14.so.14.1[.0] - * 1.4.1rc01 14 10401 14.so.14.1[.0] - * 1.4.1beta04-12 14 10401 14.so.14.1[.0] - * 1.4.1rc02-04 14 10401 14.so.14.1[.0] - * 1.4.1 14 10401 14.so.14.1[.0] - * 1.4.2beta01 14 10402 14.so.14.2[.0] - * 1.4.2rc02-06 14 10402 14.so.14.2[.0] - * 1.4.2 14 10402 14.so.14.2[.0] - * 1.4.3beta01-05 14 10403 14.so.14.3[.0] - * 1.4.3rc01-03 14 10403 14.so.14.3[.0] - * 1.4.3 14 10403 14.so.14.3[.0] - * - * Henceforth the source version will match the shared-library major - * and minor numbers; the shared-library major version number will be - * used for changes in backward compatibility, as it is intended. The - * PNG_LIBPNG_VER macro, which is not used within libpng but is available - * for applications, is an unsigned integer of the form xyyzz corresponding - * to the source version x.y.z (leading zeros in y and z). Beta versions - * were given the previous public release number plus a letter, until - * version 1.0.6j; from then on they were given the upcoming public - * release number plus "betaNN" or "rcN". - * - * Binary incompatibility exists only when applications make direct access - * to the info_ptr or png_ptr members through png.h, and the compiled - * application is loaded with a different version of the library. - * - * DLLNUM will change each time there are forward or backward changes - * in binary compatibility (e.g., when a new feature is added). - * - * See libpng.txt or libpng.3 for more information. The PNG specification - * is available as a W3C Recommendation and as an ISO Specification, - * defines should NOT be changed. - */ -#define PNG_INFO_gAMA 0x0001 -#define PNG_INFO_sBIT 0x0002 -#define PNG_INFO_cHRM 0x0004 -#define PNG_INFO_PLTE 0x0008 -#define PNG_INFO_tRNS 0x0010 -#define PNG_INFO_bKGD 0x0020 -#define PNG_INFO_hIST 0x0040 -#define PNG_INFO_pHYs 0x0080 -#define PNG_INFO_oFFs 0x0100 -#define PNG_INFO_tIME 0x0200 -#define PNG_INFO_pCAL 0x0400 -#define PNG_INFO_sRGB 0x0800 /* GR-P, 0.96a */ -#define PNG_INFO_iCCP 0x1000 /* ESR, 1.0.6 */ -#define PNG_INFO_sPLT 0x2000 /* ESR, 1.0.6 */ -#define PNG_INFO_sCAL 0x4000 /* ESR, 1.0.6 */ -#define PNG_INFO_IDAT 0x8000L /* ESR, 1.0.6 */ - -/* This is used for the transformation routines, as some of them - * change these values for the row. It also should enable using - * the routines for other purposes. - */ -typedef struct png_row_info_struct -{ - png_uint_32 width; /* width of row */ - png_size_t rowbytes; /* number of bytes in row */ - png_byte color_type; /* color type of row */ - png_byte bit_depth; /* bit depth of row */ - png_byte channels; /* number of channels (1, 2, 3, or 4) */ - png_byte pixel_depth; /* bits per pixel (depth * channels) */ -} png_row_info; - -typedef png_row_info FAR * png_row_infop; -typedef png_row_info FAR * FAR * png_row_infopp; - -/* These are the function types for the I/O functions and for the functions - * that allow the user to override the default I/O functions with his or her - * own. The png_error_ptr type should match that of user-supplied warning - * and error functions, while the png_rw_ptr type should match that of the - * user read/write data functions. - */ -typedef struct png_struct_def png_struct; -typedef png_struct FAR * png_structp; - -typedef void (PNGAPI *png_error_ptr) PNGARG((png_structp, png_const_charp)); -typedef void (PNGAPI *png_rw_ptr) PNGARG((png_structp, png_bytep, png_size_t)); -typedef void (PNGAPI *png_flush_ptr) PNGARG((png_structp)); -typedef void (PNGAPI *png_read_status_ptr) PNGARG((png_structp, png_uint_32, - int)); -typedef void (PNGAPI *png_write_status_ptr) PNGARG((png_structp, png_uint_32, - int)); - -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED -typedef void (PNGAPI *png_progressive_info_ptr) PNGARG((png_structp, - png_infop)); -typedef void (PNGAPI *png_progressive_end_ptr) PNGARG((png_structp, png_infop)); -typedef void (PNGAPI *png_progressive_row_ptr) PNGARG((png_structp, png_bytep, - png_uint_32, int)); -#endif - -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) -typedef void (PNGAPI *png_user_transform_ptr) PNGARG((png_structp, - png_row_infop, png_bytep)); -#endif - -#ifdef PNG_USER_CHUNKS_SUPPORTED -typedef int (PNGAPI *png_user_chunk_ptr) PNGARG((png_structp, - png_unknown_chunkp)); -#endif -#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED -typedef void (PNGAPI *png_unknown_chunk_ptr) PNGARG((png_structp)); -#endif -#ifdef PNG_SETJMP_SUPPORTED -/* This must match the function definition in , and the - * application must include this before png.h to obtain the definition - * of jmp_buf. - */ -typedef void (PNGAPI *png_longjmp_ptr) PNGARG((jmp_buf, int)); -#endif - -/* Transform masks for the high-level interface */ -#define PNG_TRANSFORM_IDENTITY 0x0000 /* read and write */ -#define PNG_TRANSFORM_STRIP_16 0x0001 /* read only */ -#define PNG_TRANSFORM_STRIP_ALPHA 0x0002 /* read only */ -#define PNG_TRANSFORM_PACKING 0x0004 /* read and write */ -#define PNG_TRANSFORM_PACKSWAP 0x0008 /* read and write */ -#define PNG_TRANSFORM_EXPAND 0x0010 /* read only */ -#define PNG_TRANSFORM_INVERT_MONO 0x0020 /* read and write */ -#define PNG_TRANSFORM_SHIFT 0x0040 /* read and write */ -#define PNG_TRANSFORM_BGR 0x0080 /* read and write */ -#define PNG_TRANSFORM_SWAP_ALPHA 0x0100 /* read and write */ -#define PNG_TRANSFORM_SWAP_ENDIAN 0x0200 /* read and write */ -#define PNG_TRANSFORM_INVERT_ALPHA 0x0400 /* read and write */ -#define PNG_TRANSFORM_STRIP_FILLER 0x0800 /* write only */ -/* Added to libpng-1.2.34 */ -#define PNG_TRANSFORM_STRIP_FILLER_BEFORE PNG_TRANSFORM_STRIP_FILLER -#define PNG_TRANSFORM_STRIP_FILLER_AFTER 0x1000 /* write only */ -/* Added to libpng-1.4.0 */ -#define PNG_TRANSFORM_GRAY_TO_RGB 0x2000 /* read only */ - -/* Flags for MNG supported features */ -#define PNG_FLAG_MNG_EMPTY_PLTE 0x01 -#define PNG_FLAG_MNG_FILTER_64 0x04 -#define PNG_ALL_MNG_FEATURES 0x05 - -typedef png_voidp (*png_malloc_ptr) PNGARG((png_structp, png_alloc_size_t)); -typedef void (*png_free_ptr) PNGARG((png_structp, png_voidp)); - -/* The structure that holds the information to read and write PNG files. - * The only people who need to care about what is inside of this are the - * people who will be modifying the library for their own special needs. - * It should NOT be accessed directly by an application, except to store - * the jmp_buf. - */ - -struct png_struct_def -{ -#ifdef PNG_SETJMP_SUPPORTED - jmp_buf jmpbuf PNG_DEPSTRUCT; /* used in png_error */ - png_longjmp_ptr longjmp_fn PNG_DEPSTRUCT;/* setjmp non-local goto - function. */ -#endif - png_error_ptr error_fn PNG_DEPSTRUCT; /* function for printing - errors and aborting */ - png_error_ptr warning_fn PNG_DEPSTRUCT; /* function for printing - warnings */ - png_voidp error_ptr PNG_DEPSTRUCT; /* user supplied struct for - error functions */ - png_rw_ptr write_data_fn PNG_DEPSTRUCT; /* function for writing - output data */ - png_rw_ptr read_data_fn PNG_DEPSTRUCT; /* function for reading - input data */ - png_voidp io_ptr PNG_DEPSTRUCT; /* ptr to application struct - for I/O functions */ - -#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED - png_user_transform_ptr read_user_transform_fn PNG_DEPSTRUCT; /* user read - transform */ -#endif - -#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED - png_user_transform_ptr write_user_transform_fn PNG_DEPSTRUCT; /* user write - transform */ -#endif - -/* These were added in libpng-1.0.2 */ -#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) - png_voidp user_transform_ptr PNG_DEPSTRUCT; /* user supplied struct - for user transform */ - png_byte user_transform_depth PNG_DEPSTRUCT; /* bit depth of user - transformed pixels */ - png_byte user_transform_channels PNG_DEPSTRUCT; /* channels in user - transformed pixels */ -#endif -#endif - - png_uint_32 mode PNG_DEPSTRUCT; /* tells us where we are in - the PNG file */ - png_uint_32 flags PNG_DEPSTRUCT; /* flags indicating various - things to libpng */ - png_uint_32 transformations PNG_DEPSTRUCT; /* which transformations - to perform */ - - z_stream zstream PNG_DEPSTRUCT; /* pointer to decompression - structure (below) */ - png_bytep zbuf PNG_DEPSTRUCT; /* buffer for zlib */ - png_size_t zbuf_size PNG_DEPSTRUCT; /* size of zbuf */ - int zlib_level PNG_DEPSTRUCT; /* holds zlib compression level */ - int zlib_method PNG_DEPSTRUCT; /* holds zlib compression method */ - int zlib_window_bits PNG_DEPSTRUCT; /* holds zlib compression window - bits */ - int zlib_mem_level PNG_DEPSTRUCT; /* holds zlib compression memory - level */ - int zlib_strategy PNG_DEPSTRUCT; /* holds zlib compression - strategy */ - - png_uint_32 width PNG_DEPSTRUCT; /* width of image in pixels */ - png_uint_32 height PNG_DEPSTRUCT; /* height of image in pixels */ - png_uint_32 num_rows PNG_DEPSTRUCT; /* number of rows in current pass */ - png_uint_32 usr_width PNG_DEPSTRUCT; /* width of row at start of write */ - png_size_t rowbytes PNG_DEPSTRUCT; /* size of row in bytes */ -#if 0 /* Replaced with the following in libpng-1.4.1 */ - png_size_t irowbytes PNG_DEPSTRUCT; -#endif -/* Added in libpng-1.4.1 */ -#ifdef PNG_USER_LIMITS_SUPPORTED - /* Total memory that a zTXt, sPLT, iTXt, iCCP, or unknown chunk - * can occupy when decompressed. 0 means unlimited. - * We will change the typedef from png_size_t to png_alloc_size_t - * in libpng-1.6.0 - */ - png_alloc_size_t user_chunk_malloc_max PNG_DEPSTRUCT; -#endif - png_uint_32 iwidth PNG_DEPSTRUCT; /* width of current interlaced - row in pixels */ - png_uint_32 row_number PNG_DEPSTRUCT; /* current row in interlace pass */ - png_bytep prev_row PNG_DEPSTRUCT; /* buffer to save previous - (unfiltered) row */ - png_bytep row_buf PNG_DEPSTRUCT; /* buffer to save current - (unfiltered) row */ - png_bytep sub_row PNG_DEPSTRUCT; /* buffer to save "sub" row - when filtering */ - png_bytep up_row PNG_DEPSTRUCT; /* buffer to save "up" row - when filtering */ - png_bytep avg_row PNG_DEPSTRUCT; /* buffer to save "avg" row - when filtering */ - png_bytep paeth_row PNG_DEPSTRUCT; /* buffer to save "Paeth" row - when filtering */ - png_row_info row_info PNG_DEPSTRUCT; /* used for transformation - routines */ - - png_uint_32 idat_size PNG_DEPSTRUCT; /* current IDAT size for read */ - png_uint_32 crc PNG_DEPSTRUCT; /* current chunk CRC value */ - png_colorp palette PNG_DEPSTRUCT; /* palette from the input file */ - png_uint_16 num_palette PNG_DEPSTRUCT; /* number of color entries in - palette */ - png_uint_16 num_trans PNG_DEPSTRUCT; /* number of transparency values */ - png_byte chunk_name[5] PNG_DEPSTRUCT; /* null-terminated name of current - chunk */ - png_byte compression PNG_DEPSTRUCT; /* file compression type - (always 0) */ - png_byte filter PNG_DEPSTRUCT; /* file filter type (always 0) */ - png_byte interlaced PNG_DEPSTRUCT; /* PNG_INTERLACE_NONE, - PNG_INTERLACE_ADAM7 */ - png_byte pass PNG_DEPSTRUCT; /* current interlace pass (0 - 6) */ - png_byte do_filter PNG_DEPSTRUCT; /* row filter flags (see - PNG_FILTER_ below ) */ - png_byte color_type PNG_DEPSTRUCT; /* color type of file */ - png_byte bit_depth PNG_DEPSTRUCT; /* bit depth of file */ - png_byte usr_bit_depth PNG_DEPSTRUCT; /* bit depth of users row */ - png_byte pixel_depth PNG_DEPSTRUCT; /* number of bits per pixel */ - png_byte channels PNG_DEPSTRUCT; /* number of channels in file */ - png_byte usr_channels PNG_DEPSTRUCT; /* channels at start of write */ - png_byte sig_bytes PNG_DEPSTRUCT; /* magic bytes read/written from - start of file */ - -#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) - png_uint_16 filler PNG_DEPSTRUCT; /* filler bytes for pixel - expansion */ -#endif - -#ifdef PNG_bKGD_SUPPORTED - png_byte background_gamma_type PNG_DEPSTRUCT; -# ifdef PNG_FLOATING_POINT_SUPPORTED - float background_gamma PNG_DEPSTRUCT; -# endif - png_color_16 background PNG_DEPSTRUCT; /* background color in - screen gamma space */ -#ifdef PNG_READ_GAMMA_SUPPORTED - png_color_16 background_1 PNG_DEPSTRUCT; /* background normalized - to gamma 1.0 */ -#endif -#endif /* PNG_bKGD_SUPPORTED */ - -#ifdef PNG_WRITE_FLUSH_SUPPORTED - png_flush_ptr output_flush_fn PNG_DEPSTRUCT; /* Function for flushing - output */ - png_uint_32 flush_dist PNG_DEPSTRUCT; /* how many rows apart to flush, - 0 - no flush */ - png_uint_32 flush_rows PNG_DEPSTRUCT; /* number of rows written since - last flush */ -#endif - -#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - int gamma_shift PNG_DEPSTRUCT; /* number of "insignificant" bits - 16-bit gamma */ -#ifdef PNG_FLOATING_POINT_SUPPORTED - float gamma PNG_DEPSTRUCT; /* file gamma value */ - float screen_gamma PNG_DEPSTRUCT; /* screen gamma value - (display_exponent) */ -#endif -#endif - -#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - png_bytep gamma_table PNG_DEPSTRUCT; /* gamma table for 8-bit - depth files */ - png_bytep gamma_from_1 PNG_DEPSTRUCT; /* converts from 1.0 to screen */ - png_bytep gamma_to_1 PNG_DEPSTRUCT; /* converts from file to 1.0 */ - png_uint_16pp gamma_16_table PNG_DEPSTRUCT; /* gamma table for 16-bit - depth files */ - png_uint_16pp gamma_16_from_1 PNG_DEPSTRUCT; /* converts from 1.0 to - screen */ - png_uint_16pp gamma_16_to_1 PNG_DEPSTRUCT; /* converts from file to 1.0 */ -#endif - -#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_sBIT_SUPPORTED) - png_color_8 sig_bit PNG_DEPSTRUCT; /* significant bits in each - available channel */ -#endif - -#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) - png_color_8 shift PNG_DEPSTRUCT; /* shift for significant bit - tranformation */ -#endif - -#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) \ - || defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - png_bytep trans_alpha PNG_DEPSTRUCT; /* alpha values for - paletted files */ - png_color_16 trans_color PNG_DEPSTRUCT; /* transparent color for - non-paletted files */ -#endif - - png_read_status_ptr read_row_fn PNG_DEPSTRUCT; /* called after each - row is decoded */ - png_write_status_ptr write_row_fn PNG_DEPSTRUCT; /* called after each - row is encoded */ -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED - png_progressive_info_ptr info_fn PNG_DEPSTRUCT; /* called after header - data fully read */ - png_progressive_row_ptr row_fn PNG_DEPSTRUCT; /* called after each - prog. row is decoded */ - png_progressive_end_ptr end_fn PNG_DEPSTRUCT; /* called after image - is complete */ - png_bytep save_buffer_ptr PNG_DEPSTRUCT; /* current location in - save_buffer */ - png_bytep save_buffer PNG_DEPSTRUCT; /* buffer for previously - read data */ - png_bytep current_buffer_ptr PNG_DEPSTRUCT; /* current location in - current_buffer */ - png_bytep current_buffer PNG_DEPSTRUCT; /* buffer for recently - used data */ - png_uint_32 push_length PNG_DEPSTRUCT; /* size of current input - chunk */ - png_uint_32 skip_length PNG_DEPSTRUCT; /* bytes to skip in - input data */ - png_size_t save_buffer_size PNG_DEPSTRUCT; /* amount of data now - in save_buffer */ - png_size_t save_buffer_max PNG_DEPSTRUCT; /* total size of - save_buffer */ - png_size_t buffer_size PNG_DEPSTRUCT; /* total amount of - available input data */ - png_size_t current_buffer_size PNG_DEPSTRUCT; /* amount of data now - in current_buffer */ - int process_mode PNG_DEPSTRUCT; /* what push library - is currently doing */ - int cur_palette PNG_DEPSTRUCT; /* current push library - palette index */ - -# ifdef PNG_TEXT_SUPPORTED - png_size_t current_text_size PNG_DEPSTRUCT; /* current size of - text input data */ - png_size_t current_text_left PNG_DEPSTRUCT; /* how much text left - to read in input */ - png_charp current_text PNG_DEPSTRUCT; /* current text chunk - buffer */ - png_charp current_text_ptr PNG_DEPSTRUCT; /* current location - in current_text */ -# endif /* PNG_PROGRESSIVE_READ_SUPPORTED && PNG_TEXT_SUPPORTED */ - -#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ - -#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__) -/* For the Borland special 64K segment handler */ - png_bytepp offset_table_ptr PNG_DEPSTRUCT; - png_bytep offset_table PNG_DEPSTRUCT; - png_uint_16 offset_table_number PNG_DEPSTRUCT; - png_uint_16 offset_table_count PNG_DEPSTRUCT; - png_uint_16 offset_table_count_free PNG_DEPSTRUCT; -#endif - -#ifdef PNG_READ_QUANTIZE_SUPPORTED - png_bytep palette_lookup PNG_DEPSTRUCT; /* lookup table for quantizing */ - png_bytep quantize_index PNG_DEPSTRUCT; /* index translation for palette - files */ -#endif - -#if defined(PNG_READ_QUANTIZE_SUPPORTED) || defined(PNG_hIST_SUPPORTED) - png_uint_16p hist PNG_DEPSTRUCT; /* histogram */ -#endif - -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED - png_byte heuristic_method PNG_DEPSTRUCT; /* heuristic for row - filter selection */ - png_byte num_prev_filters PNG_DEPSTRUCT; /* number of weights - for previous rows */ - png_bytep prev_filters PNG_DEPSTRUCT; /* filter type(s) of - previous row(s) */ - png_uint_16p filter_weights PNG_DEPSTRUCT; /* weight(s) for previous - line(s) */ - png_uint_16p inv_filter_weights PNG_DEPSTRUCT; /* 1/weight(s) for - previous line(s) */ - png_uint_16p filter_costs PNG_DEPSTRUCT; /* relative filter - calculation cost */ - png_uint_16p inv_filter_costs PNG_DEPSTRUCT; /* 1/relative filter - calculation cost */ -#endif - -#ifdef PNG_TIME_RFC1123_SUPPORTED - png_charp time_buffer PNG_DEPSTRUCT; /* String to hold RFC 1123 time text */ -#endif - -/* New members added in libpng-1.0.6 */ - - png_uint_32 free_me PNG_DEPSTRUCT; /* flags items libpng is - responsible for freeing */ - -#ifdef PNG_USER_CHUNKS_SUPPORTED - png_voidp user_chunk_ptr PNG_DEPSTRUCT; - png_user_chunk_ptr read_user_chunk_fn PNG_DEPSTRUCT; /* user read - chunk handler */ -#endif - -#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED - int num_chunk_list PNG_DEPSTRUCT; - png_bytep chunk_list PNG_DEPSTRUCT; -#endif - -/* New members added in libpng-1.0.3 */ -#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED - png_byte rgb_to_gray_status PNG_DEPSTRUCT; - /* These were changed from png_byte in libpng-1.0.6 */ - png_uint_16 rgb_to_gray_red_coeff PNG_DEPSTRUCT; - png_uint_16 rgb_to_gray_green_coeff PNG_DEPSTRUCT; - png_uint_16 rgb_to_gray_blue_coeff PNG_DEPSTRUCT; -#endif - -/* New member added in libpng-1.0.4 (renamed in 1.0.9) */ -#if defined(PNG_MNG_FEATURES_SUPPORTED) || \ - defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \ - defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) -/* Changed from png_byte to png_uint_32 at version 1.2.0 */ - png_uint_32 mng_features_permitted PNG_DEPSTRUCT; -#endif - -/* New member added in libpng-1.0.7 */ -#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - png_fixed_point int_gamma PNG_DEPSTRUCT; -#endif - -/* New member added in libpng-1.0.9, ifdef'ed out in 1.0.12, enabled in 1.2.0 */ -#ifdef PNG_MNG_FEATURES_SUPPORTED - png_byte filter_type PNG_DEPSTRUCT; -#endif - -/* New members added in libpng-1.2.0 */ - -/* New members added in libpng-1.0.2 but first enabled by default in 1.2.0 */ -#ifdef PNG_USER_MEM_SUPPORTED - png_voidp mem_ptr PNG_DEPSTRUCT; /* user supplied struct for - mem functions */ - png_malloc_ptr malloc_fn PNG_DEPSTRUCT; /* function for - allocating memory */ - png_free_ptr free_fn PNG_DEPSTRUCT; /* function for - freeing memory */ -#endif - -/* New member added in libpng-1.0.13 and 1.2.0 */ - png_bytep big_row_buf PNG_DEPSTRUCT; /* buffer to save current - (unfiltered) row */ - -#ifdef PNG_READ_QUANTIZE_SUPPORTED -/* The following three members were added at version 1.0.14 and 1.2.4 */ - png_bytep quantize_sort PNG_DEPSTRUCT; /* working sort array */ - png_bytep index_to_palette PNG_DEPSTRUCT; /* where the original - index currently is - in the palette */ - png_bytep palette_to_index PNG_DEPSTRUCT; /* which original index - points to this - palette color */ -#endif - -/* New members added in libpng-1.0.16 and 1.2.6 */ - png_byte compression_type PNG_DEPSTRUCT; - -#ifdef PNG_USER_LIMITS_SUPPORTED - png_uint_32 user_width_max PNG_DEPSTRUCT; - png_uint_32 user_height_max PNG_DEPSTRUCT; - /* Added in libpng-1.4.0: Total number of sPLT, text, and unknown - * chunks that can be stored (0 means unlimited). - */ - png_uint_32 user_chunk_cache_max PNG_DEPSTRUCT; -#endif - -/* New member added in libpng-1.0.25 and 1.2.17 */ -#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED - /* Storage for unknown chunk that the library doesn't recognize. */ - png_unknown_chunk unknown_chunk PNG_DEPSTRUCT; -#endif - -/* New members added in libpng-1.2.26 */ - png_uint_32 old_big_row_buf_size PNG_DEPSTRUCT; - png_uint_32 old_prev_row_size PNG_DEPSTRUCT; - -/* New member added in libpng-1.2.30 */ - png_charp chunkdata PNG_DEPSTRUCT; /* buffer for reading chunk data */ - -#ifdef PNG_IO_STATE_SUPPORTED -/* New member added in libpng-1.4.0 */ - png_uint_32 io_state PNG_DEPSTRUCT; -#endif -}; - - -/* This triggers a compiler error in png.c, if png.c and png.h - * do not agree upon the version number. - */ -typedef png_structp version_1_4_3; - -typedef png_struct FAR * FAR * png_structpp; - -/* Here are the function definitions most commonly used. This is not - * the place to find out how to use libpng. See libpng.txt for the - * full explanation, see example.c for the summary. This just provides - * a simple one line description of the use of each function. - */ - -/* Returns the version number of the library */ -extern PNG_EXPORT(png_uint_32,png_access_version_number) PNGARG((void)); - -/* Tell lib we have already handled the first magic bytes. - * Handling more than 8 bytes from the beginning of the file is an error. - */ -extern PNG_EXPORT(void,png_set_sig_bytes) PNGARG((png_structp png_ptr, - int num_bytes)); - -/* Check sig[start] through sig[start + num_to_check - 1] to see if it's a - * PNG file. Returns zero if the supplied bytes match the 8-byte PNG - * signature, and non-zero otherwise. Having num_to_check == 0 or - * start > 7 will always fail (ie return non-zero). - */ -extern PNG_EXPORT(int,png_sig_cmp) PNGARG((png_bytep sig, png_size_t start, - png_size_t num_to_check)); - -/* Simple signature checking function. This is the same as calling - * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n). - */ -#define png_check_sig(sig,n) !png_sig_cmp((sig), 0, (n)) - -/* Allocate and initialize png_ptr struct for reading, and any other memory. */ -extern PNG_EXPORT(png_structp,png_create_read_struct) - PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn)) PNG_ALLOCATED; - -/* Allocate and initialize png_ptr struct for writing, and any other memory */ -extern PNG_EXPORT(png_structp,png_create_write_struct) - PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn)) PNG_ALLOCATED; - -extern PNG_EXPORT(png_size_t,png_get_compression_buffer_size) - PNGARG((png_structp png_ptr)); - -extern PNG_EXPORT(void,png_set_compression_buffer_size) - PNGARG((png_structp png_ptr, png_size_t size)); - -/* Moved from pngconf.h in 1.4.0 and modified to ensure setjmp/longjmp - * match up. - */ -#ifdef PNG_SETJMP_SUPPORTED -/* This function returns the jmp_buf built in to *png_ptr. It must be - * supplied with an appropriate 'longjmp' function to use on that jmp_buf - * unless the default error function is overridden in which case NULL is - * acceptable. The size of the jmp_buf is checked against the actual size - * allocated by the library - the call will return NULL on a mismatch - * indicating an ABI mismatch. - */ -extern PNG_EXPORT(jmp_buf*, png_set_longjmp_fn) - PNGARG((png_structp png_ptr, png_longjmp_ptr longjmp_fn, size_t - jmp_buf_size)); -# define png_jmpbuf(png_ptr) \ - (*png_set_longjmp_fn((png_ptr), longjmp, sizeof (jmp_buf))) -#else -# define png_jmpbuf(png_ptr) \ - (LIBPNG_WAS_COMPILED_WITH__PNG_NO_SETJMP) -#endif - -#ifdef PNG_READ_SUPPORTED -/* Reset the compression stream */ -extern PNG_EXPORT(int,png_reset_zstream) PNGARG((png_structp png_ptr)); -#endif - -/* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */ -#ifdef PNG_USER_MEM_SUPPORTED -extern PNG_EXPORT(png_structp,png_create_read_struct_2) - PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, - png_malloc_ptr malloc_fn, png_free_ptr free_fn)) PNG_ALLOCATED; -extern PNG_EXPORT(png_structp,png_create_write_struct_2) - PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, - png_malloc_ptr malloc_fn, png_free_ptr free_fn)) PNG_ALLOCATED; -#endif - -/* Write the PNG file signature. */ -extern PNG_EXPORT(void,png_write_sig) PNGARG((png_structp png_ptr)); - -/* Write a PNG chunk - size, type, (optional) data, CRC. */ -extern PNG_EXPORT(void,png_write_chunk) PNGARG((png_structp png_ptr, - png_bytep chunk_name, png_bytep data, png_size_t length)); - -/* Write the start of a PNG chunk - length and chunk name. */ -extern PNG_EXPORT(void,png_write_chunk_start) PNGARG((png_structp png_ptr, - png_bytep chunk_name, png_uint_32 length)); - -/* Write the data of a PNG chunk started with png_write_chunk_start(). */ -extern PNG_EXPORT(void,png_write_chunk_data) PNGARG((png_structp png_ptr, - png_bytep data, png_size_t length)); - -/* Finish a chunk started with png_write_chunk_start() (includes CRC). */ -extern PNG_EXPORT(void,png_write_chunk_end) PNGARG((png_structp png_ptr)); - -/* Allocate and initialize the info structure */ -extern PNG_EXPORT(png_infop,png_create_info_struct) - PNGARG((png_structp png_ptr)) PNG_ALLOCATED; - -extern PNG_EXPORT(void,png_info_init_3) PNGARG((png_infopp info_ptr, - png_size_t png_info_struct_size)); - -/* Writes all the PNG information before the image. */ -extern PNG_EXPORT(void,png_write_info_before_PLTE) PNGARG((png_structp png_ptr, - png_infop info_ptr)); -extern PNG_EXPORT(void,png_write_info) PNGARG((png_structp png_ptr, - png_infop info_ptr)); - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -/* Read the information before the actual image data. */ -extern PNG_EXPORT(void,png_read_info) PNGARG((png_structp png_ptr, - png_infop info_ptr)); -#endif - -#ifdef PNG_TIME_RFC1123_SUPPORTED -extern PNG_EXPORT(png_charp,png_convert_to_rfc1123) - PNGARG((png_structp png_ptr, png_timep ptime)); -#endif - -#ifdef PNG_CONVERT_tIME_SUPPORTED -/* Convert from a struct tm to png_time */ -extern PNG_EXPORT(void,png_convert_from_struct_tm) PNGARG((png_timep ptime, - struct tm FAR * ttime)); - -/* Convert from time_t to png_time. Uses gmtime() */ -extern PNG_EXPORT(void,png_convert_from_time_t) PNGARG((png_timep ptime, - time_t ttime)); -#endif /* PNG_CONVERT_tIME_SUPPORTED */ - -#ifdef PNG_READ_EXPAND_SUPPORTED -/* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */ -extern PNG_EXPORT(void,png_set_expand) PNGARG((png_structp png_ptr)); -extern PNG_EXPORT(void,png_set_expand_gray_1_2_4_to_8) PNGARG((png_structp - png_ptr)); -extern PNG_EXPORT(void,png_set_palette_to_rgb) PNGARG((png_structp png_ptr)); -extern PNG_EXPORT(void,png_set_tRNS_to_alpha) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) -/* Use blue, green, red order for pixels. */ -extern PNG_EXPORT(void,png_set_bgr) PNGARG((png_structp png_ptr)); -#endif - -#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED -/* Expand the grayscale to 24-bit RGB if necessary. */ -extern PNG_EXPORT(void,png_set_gray_to_rgb) PNGARG((png_structp png_ptr)); -#endif - -#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED -/* Reduce RGB to grayscale. */ -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_rgb_to_gray) PNGARG((png_structp png_ptr, - int error_action, double red, double green )); -#endif -extern PNG_EXPORT(void,png_set_rgb_to_gray_fixed) PNGARG((png_structp png_ptr, - int error_action, png_fixed_point red, png_fixed_point green )); -extern PNG_EXPORT(png_byte,png_get_rgb_to_gray_status) PNGARG((png_structp - png_ptr)); -#endif - -extern PNG_EXPORT(void,png_build_grayscale_palette) PNGARG((int bit_depth, - png_colorp palette)); - -#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED -extern PNG_EXPORT(void,png_set_strip_alpha) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ - defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) -extern PNG_EXPORT(void,png_set_swap_alpha) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ - defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) -extern PNG_EXPORT(void,png_set_invert_alpha) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) -/* Add a filler byte to 8-bit Gray or 24-bit RGB images. */ -extern PNG_EXPORT(void,png_set_filler) PNGARG((png_structp png_ptr, - png_uint_32 filler, int flags)); -/* The values of the PNG_FILLER_ defines should NOT be changed */ -#define PNG_FILLER_BEFORE 0 -#define PNG_FILLER_AFTER 1 -/* Add an alpha byte to 8-bit Gray or 24-bit RGB images. */ -extern PNG_EXPORT(void,png_set_add_alpha) PNGARG((png_structp png_ptr, - png_uint_32 filler, int flags)); -#endif /* PNG_READ_FILLER_SUPPORTED || PNG_WRITE_FILLER_SUPPORTED */ - -#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) -/* Swap bytes in 16-bit depth files. */ -extern PNG_EXPORT(void,png_set_swap) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) -/* Use 1 byte per pixel in 1, 2, or 4-bit depth files. */ -extern PNG_EXPORT(void,png_set_packing) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_PACKSWAP_SUPPORTED) || \ - defined(PNG_WRITE_PACKSWAP_SUPPORTED) -/* Swap packing order of pixels in bytes. */ -extern PNG_EXPORT(void,png_set_packswap) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) -/* Converts files to legal bit depths. */ -extern PNG_EXPORT(void,png_set_shift) PNGARG((png_structp png_ptr, - png_color_8p true_bits)); -#endif - -#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ - defined(PNG_WRITE_INTERLACING_SUPPORTED) -/* Have the code handle the interlacing. Returns the number of passes. */ -extern PNG_EXPORT(int,png_set_interlace_handling) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) -/* Invert monochrome files */ -extern PNG_EXPORT(void,png_set_invert_mono) PNGARG((png_structp png_ptr)); -#endif - -#ifdef PNG_READ_BACKGROUND_SUPPORTED -/* Handle alpha and tRNS by replacing with a background color. */ -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_background) PNGARG((png_structp png_ptr, - png_color_16p background_color, int background_gamma_code, - int need_expand, double background_gamma)); -#endif -#define PNG_BACKGROUND_GAMMA_UNKNOWN 0 -#define PNG_BACKGROUND_GAMMA_SCREEN 1 -#define PNG_BACKGROUND_GAMMA_FILE 2 -#define PNG_BACKGROUND_GAMMA_UNIQUE 3 -#endif - -#ifdef PNG_READ_16_TO_8_SUPPORTED -/* Strip the second byte of information from a 16-bit depth file. */ -extern PNG_EXPORT(void,png_set_strip_16) PNGARG((png_structp png_ptr)); -#endif - -#ifdef PNG_READ_QUANTIZE_SUPPORTED -/* Turn on quantizing, and reduce the palette to the number of colors - * available. Prior to libpng-1.4.2, this was png_set_dither(). - */ -extern PNG_EXPORT(void,png_set_quantize) PNGARG((png_structp png_ptr, - png_colorp palette, int num_palette, int maximum_colors, - png_uint_16p histogram, int full_quantize)); -#endif -/* This migration aid will be removed from libpng-1.5.0 */ -#define png_set_dither png_set_quantize - -#ifdef PNG_READ_GAMMA_SUPPORTED -/* Handle gamma correction. Screen_gamma=(display_exponent) */ -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_gamma) PNGARG((png_structp png_ptr, - double screen_gamma, double default_file_gamma)); -#endif -#endif - - -#ifdef PNG_WRITE_FLUSH_SUPPORTED -/* Set how many lines between output flushes - 0 for no flushing */ -extern PNG_EXPORT(void,png_set_flush) PNGARG((png_structp png_ptr, int nrows)); -/* Flush the current PNG output buffer */ -extern PNG_EXPORT(void,png_write_flush) PNGARG((png_structp png_ptr)); -#endif - -/* Optional update palette with requested transformations */ -extern PNG_EXPORT(void,png_start_read_image) PNGARG((png_structp png_ptr)); - -/* Optional call to update the users info structure */ -extern PNG_EXPORT(void,png_read_update_info) PNGARG((png_structp png_ptr, - png_infop info_ptr)); - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -/* Read one or more rows of image data. */ -extern PNG_EXPORT(void,png_read_rows) PNGARG((png_structp png_ptr, - png_bytepp row, png_bytepp display_row, png_uint_32 num_rows)); -#endif - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -/* Read a row of data. */ -extern PNG_EXPORT(void,png_read_row) PNGARG((png_structp png_ptr, - png_bytep row, - png_bytep display_row)); -#endif - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -/* Read the whole image into memory at once. */ -extern PNG_EXPORT(void,png_read_image) PNGARG((png_structp png_ptr, - png_bytepp image)); -#endif - -/* Write a row of image data */ -extern PNG_EXPORT(void,png_write_row) PNGARG((png_structp png_ptr, - png_bytep row)); - -/* Write a few rows of image data */ -extern PNG_EXPORT(void,png_write_rows) PNGARG((png_structp png_ptr, - png_bytepp row, png_uint_32 num_rows)); - -/* Write the image data */ -extern PNG_EXPORT(void,png_write_image) PNGARG((png_structp png_ptr, - png_bytepp image)); - -/* Write the end of the PNG file. */ -extern PNG_EXPORT(void,png_write_end) PNGARG((png_structp png_ptr, - png_infop info_ptr)); - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -/* Read the end of the PNG file. */ -extern PNG_EXPORT(void,png_read_end) PNGARG((png_structp png_ptr, - png_infop info_ptr)); -#endif - -/* Free any memory associated with the png_info_struct */ -extern PNG_EXPORT(void,png_destroy_info_struct) PNGARG((png_structp png_ptr, - png_infopp info_ptr_ptr)); - -/* Free any memory associated with the png_struct and the png_info_structs */ -extern PNG_EXPORT(void,png_destroy_read_struct) PNGARG((png_structpp - png_ptr_ptr, png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr)); - -/* Free any memory associated with the png_struct and the png_info_structs */ -extern PNG_EXPORT(void,png_destroy_write_struct) - PNGARG((png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)); - -/* Set the libpng method of handling chunk CRC errors */ -extern PNG_EXPORT(void,png_set_crc_action) PNGARG((png_structp png_ptr, - int crit_action, int ancil_action)); - -/* Values for png_set_crc_action() to say how to handle CRC errors in - * ancillary and critical chunks, and whether to use the data contained - * therein. Note that it is impossible to "discard" data in a critical - * chunk. For versions prior to 0.90, the action was always error/quit, - * whereas in version 0.90 and later, the action for CRC errors in ancillary - * chunks is warn/discard. These values should NOT be changed. - * - * value action:critical action:ancillary - */ -#define PNG_CRC_DEFAULT 0 /* error/quit warn/discard data */ -#define PNG_CRC_ERROR_QUIT 1 /* error/quit error/quit */ -#define PNG_CRC_WARN_DISCARD 2 /* (INVALID) warn/discard data */ -#define PNG_CRC_WARN_USE 3 /* warn/use data warn/use data */ -#define PNG_CRC_QUIET_USE 4 /* quiet/use data quiet/use data */ -#define PNG_CRC_NO_CHANGE 5 /* use current value use current value */ - -/* These functions give the user control over the scan-line filtering in - * libpng and the compression methods used by zlib. These functions are - * mainly useful for testing, as the defaults should work with most users. - * Those users who are tight on memory or want faster performance at the - * expense of compression can modify them. See the compression library - * header file (zlib.h) for an explination of the compression functions. - */ - -/* Set the filtering method(s) used by libpng. Currently, the only valid - * value for "method" is 0. - */ -extern PNG_EXPORT(void,png_set_filter) PNGARG((png_structp png_ptr, int method, - int filters)); - -/* Flags for png_set_filter() to say which filters to use. The flags - * are chosen so that they don't conflict with real filter types - * below, in case they are supplied instead of the #defined constants. - * These values should NOT be changed. - */ -#define PNG_NO_FILTERS 0x00 -#define PNG_FILTER_NONE 0x08 -#define PNG_FILTER_SUB 0x10 -#define PNG_FILTER_UP 0x20 -#define PNG_FILTER_AVG 0x40 -#define PNG_FILTER_PAETH 0x80 -#define PNG_ALL_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP | \ - PNG_FILTER_AVG | PNG_FILTER_PAETH) - -/* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now. - * These defines should NOT be changed. - */ -#define PNG_FILTER_VALUE_NONE 0 -#define PNG_FILTER_VALUE_SUB 1 -#define PNG_FILTER_VALUE_UP 2 -#define PNG_FILTER_VALUE_AVG 3 -#define PNG_FILTER_VALUE_PAETH 4 -#define PNG_FILTER_VALUE_LAST 5 - -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* EXPERIMENTAL */ -/* The "heuristic_method" is given by one of the PNG_FILTER_HEURISTIC_ - * defines, either the default (minimum-sum-of-absolute-differences), or - * the experimental method (weighted-minimum-sum-of-absolute-differences). - * - * Weights are factors >= 1.0, indicating how important it is to keep the - * filter type consistent between rows. Larger numbers mean the current - * filter is that many times as likely to be the same as the "num_weights" - * previous filters. This is cumulative for each previous row with a weight. - * There needs to be "num_weights" values in "filter_weights", or it can be - * NULL if the weights aren't being specified. Weights have no influence on - * the selection of the first row filter. Well chosen weights can (in theory) - * improve the compression for a given image. - * - * Costs are factors >= 1.0 indicating the relative decoding costs of a - * filter type. Higher costs indicate more decoding expense, and are - * therefore less likely to be selected over a filter with lower computational - * costs. There needs to be a value in "filter_costs" for each valid filter - * type (given by PNG_FILTER_VALUE_LAST), or it can be NULL if you aren't - * setting the costs. Costs try to improve the speed of decompression without - * unduly increasing the compressed image size. - * - * A negative weight or cost indicates the default value is to be used, and - * values in the range [0.0, 1.0) indicate the value is to remain unchanged. - * The default values for both weights and costs are currently 1.0, but may - * change if good general weighting/cost heuristics can be found. If both - * the weights and costs are set to 1.0, this degenerates the WEIGHTED method - * to the UNWEIGHTED method, but with added encoding time/computation. - */ -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_filter_heuristics) PNGARG((png_structp png_ptr, - int heuristic_method, int num_weights, png_doublep filter_weights, - png_doublep filter_costs)); -#endif -#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ - -/* Heuristic used for row filter selection. These defines should NOT be - * changed. - */ -#define PNG_FILTER_HEURISTIC_DEFAULT 0 /* Currently "UNWEIGHTED" */ -#define PNG_FILTER_HEURISTIC_UNWEIGHTED 1 /* Used by libpng < 0.95 */ -#define PNG_FILTER_HEURISTIC_WEIGHTED 2 /* Experimental feature */ -#define PNG_FILTER_HEURISTIC_LAST 3 /* Not a valid value */ - -/* Set the library compression level. Currently, valid values range from - * 0 - 9, corresponding directly to the zlib compression levels 0 - 9 - * (0 - no compression, 9 - "maximal" compression). Note that tests have - * shown that zlib compression levels 3-6 usually perform as well as level 9 - * for PNG images, and do considerably fewer caclulations. In the future, - * these values may not correspond directly to the zlib compression levels. - */ -extern PNG_EXPORT(void,png_set_compression_level) PNGARG((png_structp png_ptr, - int level)); - -extern PNG_EXPORT(void,png_set_compression_mem_level) - PNGARG((png_structp png_ptr, int mem_level)); - -extern PNG_EXPORT(void,png_set_compression_strategy) - PNGARG((png_structp png_ptr, int strategy)); - -extern PNG_EXPORT(void,png_set_compression_window_bits) - PNGARG((png_structp png_ptr, int window_bits)); - -extern PNG_EXPORT(void,png_set_compression_method) PNGARG((png_structp png_ptr, - int method)); - -/* These next functions are called for input/output, memory, and error - * handling. They are in the file pngrio.c, pngwio.c, and pngerror.c, - * and call standard C I/O routines such as fread(), fwrite(), and - * fprintf(). These functions can be made to use other I/O routines - * at run time for those applications that need to handle I/O in a - * different manner by calling png_set_???_fn(). See libpng.txt for - * more information. - */ - -#ifdef PNG_STDIO_SUPPORTED -/* Initialize the input/output for the PNG file to the default functions. */ -extern PNG_EXPORT(void,png_init_io) PNGARG((png_structp png_ptr, - png_FILE_p fp)); -#endif - -/* Replace the (error and abort), and warning functions with user - * supplied functions. If no messages are to be printed you must still - * write and use replacement functions. The replacement error_fn should - * still do a longjmp to the last setjmp location if you are using this - * method of error handling. If error_fn or warning_fn is NULL, the - * default function will be used. - */ - -extern PNG_EXPORT(void,png_set_error_fn) PNGARG((png_structp png_ptr, - png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn)); - -/* Return the user pointer associated with the error functions */ -extern PNG_EXPORT(png_voidp,png_get_error_ptr) PNGARG((png_structp png_ptr)); - -/* Replace the default data output functions with a user supplied one(s). - * If buffered output is not used, then output_flush_fn can be set to NULL. - * If PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile time - * output_flush_fn will be ignored (and thus can be NULL). - * It is probably a mistake to use NULL for output_flush_fn if - * write_data_fn is not also NULL unless you have built libpng with - * PNG_WRITE_FLUSH_SUPPORTED undefined, because in this case libpng's - * default flush function, which uses the standard *FILE structure, will - * be used. - */ -extern PNG_EXPORT(void,png_set_write_fn) PNGARG((png_structp png_ptr, - png_voidp io_ptr, png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)); - -/* Replace the default data input function with a user supplied one. */ -extern PNG_EXPORT(void,png_set_read_fn) PNGARG((png_structp png_ptr, - png_voidp io_ptr, png_rw_ptr read_data_fn)); - -/* Return the user pointer associated with the I/O functions */ -extern PNG_EXPORT(png_voidp,png_get_io_ptr) PNGARG((png_structp png_ptr)); - -extern PNG_EXPORT(void,png_set_read_status_fn) PNGARG((png_structp png_ptr, - png_read_status_ptr read_row_fn)); - -extern PNG_EXPORT(void,png_set_write_status_fn) PNGARG((png_structp png_ptr, - png_write_status_ptr write_row_fn)); - -#ifdef PNG_USER_MEM_SUPPORTED -/* Replace the default memory allocation functions with user supplied one(s). */ -extern PNG_EXPORT(void,png_set_mem_fn) PNGARG((png_structp png_ptr, - png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn)); -/* Return the user pointer associated with the memory functions */ -extern PNG_EXPORT(png_voidp,png_get_mem_ptr) PNGARG((png_structp png_ptr)); -#endif - -#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED -extern PNG_EXPORT(void,png_set_read_user_transform_fn) PNGARG((png_structp - png_ptr, png_user_transform_ptr read_user_transform_fn)); -#endif - -#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED -extern PNG_EXPORT(void,png_set_write_user_transform_fn) PNGARG((png_structp - png_ptr, png_user_transform_ptr write_user_transform_fn)); -#endif - -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) -extern PNG_EXPORT(void,png_set_user_transform_info) PNGARG((png_structp - png_ptr, png_voidp user_transform_ptr, int user_transform_depth, - int user_transform_channels)); -/* Return the user pointer associated with the user transform functions */ -extern PNG_EXPORT(png_voidp,png_get_user_transform_ptr) - PNGARG((png_structp png_ptr)); -#endif - -#ifdef PNG_USER_CHUNKS_SUPPORTED -extern PNG_EXPORT(void,png_set_read_user_chunk_fn) PNGARG((png_structp png_ptr, - png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn)); -extern PNG_EXPORT(png_voidp,png_get_user_chunk_ptr) PNGARG((png_structp - png_ptr)); -#endif - -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED -/* Sets the function callbacks for the push reader, and a pointer to a - * user-defined structure available to the callback functions. - */ -extern PNG_EXPORT(void,png_set_progressive_read_fn) PNGARG((png_structp png_ptr, - png_voidp progressive_ptr, - png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn, - png_progressive_end_ptr end_fn)); - -/* Returns the user pointer associated with the push read functions */ -extern PNG_EXPORT(png_voidp,png_get_progressive_ptr) - PNGARG((png_structp png_ptr)); - -/* Function to be called when data becomes available */ -extern PNG_EXPORT(void,png_process_data) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_bytep buffer, png_size_t buffer_size)); - -/* Function that combines rows. Not very much different than the - * png_combine_row() call. Is this even used????? - */ -extern PNG_EXPORT(void,png_progressive_combine_row) PNGARG((png_structp png_ptr, - png_bytep old_row, png_bytep new_row)); -#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ - -extern PNG_EXPORT(png_voidp,png_malloc) PNGARG((png_structp png_ptr, - png_alloc_size_t size)) PNG_ALLOCATED; -/* Added at libpng version 1.4.0 */ -extern PNG_EXPORT(png_voidp,png_calloc) PNGARG((png_structp png_ptr, - png_alloc_size_t size)) PNG_ALLOCATED; - -/* Added at libpng version 1.2.4 */ -extern PNG_EXPORT(png_voidp,png_malloc_warn) PNGARG((png_structp png_ptr, - png_alloc_size_t size)) PNG_ALLOCATED; - -/* Frees a pointer allocated by png_malloc() */ -extern PNG_EXPORT(void,png_free) PNGARG((png_structp png_ptr, png_voidp ptr)); - -/* Free data that was allocated internally */ -extern PNG_EXPORT(void,png_free_data) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 free_me, int num)); -/* Reassign responsibility for freeing existing data, whether allocated - * by libpng or by the application */ -extern PNG_EXPORT(void,png_data_freer) PNGARG((png_structp png_ptr, - png_infop info_ptr, int freer, png_uint_32 mask)); -/* Assignments for png_data_freer */ -#define PNG_DESTROY_WILL_FREE_DATA 1 -#define PNG_SET_WILL_FREE_DATA 1 -#define PNG_USER_WILL_FREE_DATA 2 -/* Flags for png_ptr->free_me and info_ptr->free_me */ -#define PNG_FREE_HIST 0x0008 -#define PNG_FREE_ICCP 0x0010 -#define PNG_FREE_SPLT 0x0020 -#define PNG_FREE_ROWS 0x0040 -#define PNG_FREE_PCAL 0x0080 -#define PNG_FREE_SCAL 0x0100 -#define PNG_FREE_UNKN 0x0200 -#define PNG_FREE_LIST 0x0400 -#define PNG_FREE_PLTE 0x1000 -#define PNG_FREE_TRNS 0x2000 -#define PNG_FREE_TEXT 0x4000 -#define PNG_FREE_ALL 0x7fff -#define PNG_FREE_MUL 0x4220 /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */ - -#ifdef PNG_USER_MEM_SUPPORTED -extern PNG_EXPORT(png_voidp,png_malloc_default) PNGARG((png_structp png_ptr, - png_alloc_size_t size)) PNG_ALLOCATED; -extern PNG_EXPORT(void,png_free_default) PNGARG((png_structp png_ptr, - png_voidp ptr)); -#endif - -#ifndef PNG_NO_ERROR_TEXT -/* Fatal error in PNG image of libpng - can't continue */ -extern PNG_EXPORT(void,png_error) PNGARG((png_structp png_ptr, - png_const_charp error_message)) PNG_NORETURN; - -/* The same, but the chunk name is prepended to the error string. */ -extern PNG_EXPORT(void,png_chunk_error) PNGARG((png_structp png_ptr, - png_const_charp error_message)) PNG_NORETURN; - -#else -/* Fatal error in PNG image of libpng - can't continue */ -extern PNG_EXPORT(void,png_err) PNGARG((png_structp png_ptr)) PNG_NORETURN; -#endif - -/* Non-fatal error in libpng. Can continue, but may have a problem. */ -extern PNG_EXPORT(void,png_warning) PNGARG((png_structp png_ptr, - png_const_charp warning_message)); - -/* Non-fatal error in libpng, chunk name is prepended to message. */ -extern PNG_EXPORT(void,png_chunk_warning) PNGARG((png_structp png_ptr, - png_const_charp warning_message)); - -#ifdef PNG_BENIGN_ERRORS_SUPPORTED -/* Benign error in libpng. Can continue, but may have a problem. - * User can choose whether to handle as a fatal error or as a warning. */ -extern PNG_EXPORT(void,png_benign_error) PNGARG((png_structp png_ptr, - png_const_charp warning_message)); - -/* Same, chunk name is prepended to message. */ -extern PNG_EXPORT(void,png_chunk_benign_error) PNGARG((png_structp png_ptr, - png_const_charp warning_message)); - -extern PNG_EXPORT(void,png_set_benign_errors) PNGARG((png_structp - png_ptr, int allowed)); -#endif - -/* The png_set_ functions are for storing values in the png_info_struct. - * Similarly, the png_get_ calls are used to read values from the - * png_info_struct, either storing the parameters in the passed variables, or - * setting pointers into the png_info_struct where the data is stored. The - * png_get_ functions return a non-zero value if the data was available - * in info_ptr, or return zero and do not change any of the parameters if the - * data was not available. - * - * These functions should be used instead of directly accessing png_info - * to avoid problems with future changes in the size and internal layout of - * png_info_struct. - */ -/* Returns "flag" if chunk data is valid in info_ptr. */ -extern PNG_EXPORT(png_uint_32,png_get_valid) PNGARG((png_structp png_ptr, -png_infop info_ptr, png_uint_32 flag)); - -/* Returns number of bytes needed to hold a transformed row. */ -extern PNG_EXPORT(png_size_t,png_get_rowbytes) PNGARG((png_structp png_ptr, -png_infop info_ptr)); - -#ifdef PNG_INFO_IMAGE_SUPPORTED -/* Returns row_pointers, which is an array of pointers to scanlines that was - * returned from png_read_png(). - */ -extern PNG_EXPORT(png_bytepp,png_get_rows) PNGARG((png_structp png_ptr, -png_infop info_ptr)); -/* Set row_pointers, which is an array of pointers to scanlines for use - * by png_write_png(). - */ -extern PNG_EXPORT(void,png_set_rows) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_bytepp row_pointers)); -#endif - -/* Returns number of color channels in image. */ -extern PNG_EXPORT(png_byte,png_get_channels) PNGARG((png_structp png_ptr, -png_infop info_ptr)); - -#ifdef PNG_EASY_ACCESS_SUPPORTED -/* Returns image width in pixels. */ -extern PNG_EXPORT(png_uint_32, png_get_image_width) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -/* Returns image height in pixels. */ -extern PNG_EXPORT(png_uint_32, png_get_image_height) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -/* Returns image bit_depth. */ -extern PNG_EXPORT(png_byte, png_get_bit_depth) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -/* Returns image color_type. */ -extern PNG_EXPORT(png_byte, png_get_color_type) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -/* Returns image filter_type. */ -extern PNG_EXPORT(png_byte, png_get_filter_type) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -/* Returns image interlace_type. */ -extern PNG_EXPORT(png_byte, png_get_interlace_type) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -/* Returns image compression_type. */ -extern PNG_EXPORT(png_byte, png_get_compression_type) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -/* Returns image resolution in pixels per meter, from pHYs chunk data. */ -extern PNG_EXPORT(png_uint_32, png_get_pixels_per_meter) PNGARG((png_structp -png_ptr, png_infop info_ptr)); -extern PNG_EXPORT(png_uint_32, png_get_x_pixels_per_meter) PNGARG((png_structp -png_ptr, png_infop info_ptr)); -extern PNG_EXPORT(png_uint_32, png_get_y_pixels_per_meter) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -/* Returns pixel aspect ratio, computed from pHYs chunk data. */ -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(float, png_get_pixel_aspect_ratio) PNGARG((png_structp -png_ptr, png_infop info_ptr)); -#endif - -/* Returns image x, y offset in pixels or microns, from oFFs chunk data. */ -extern PNG_EXPORT(png_int_32, png_get_x_offset_pixels) PNGARG((png_structp -png_ptr, png_infop info_ptr)); -extern PNG_EXPORT(png_int_32, png_get_y_offset_pixels) PNGARG((png_structp -png_ptr, png_infop info_ptr)); -extern PNG_EXPORT(png_int_32, png_get_x_offset_microns) PNGARG((png_structp -png_ptr, png_infop info_ptr)); -extern PNG_EXPORT(png_int_32, png_get_y_offset_microns) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -#endif /* PNG_EASY_ACCESS_SUPPORTED */ - -/* Returns pointer to signature string read from PNG header */ -extern PNG_EXPORT(png_bytep,png_get_signature) PNGARG((png_structp png_ptr, -png_infop info_ptr)); - -#ifdef PNG_bKGD_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_bKGD) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_color_16p *background)); -#endif - -#ifdef PNG_bKGD_SUPPORTED -extern PNG_EXPORT(void,png_set_bKGD) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_color_16p background)); -#endif - -#ifdef PNG_cHRM_SUPPORTED -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_cHRM) PNGARG((png_structp png_ptr, - png_infop info_ptr, double *white_x, double *white_y, double *red_x, - double *red_y, double *green_x, double *green_y, double *blue_x, - double *blue_y)); -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_cHRM_fixed) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_fixed_point *int_white_x, png_fixed_point - *int_white_y, png_fixed_point *int_red_x, png_fixed_point *int_red_y, - png_fixed_point *int_green_x, png_fixed_point *int_green_y, png_fixed_point - *int_blue_x, png_fixed_point *int_blue_y)); -#endif -#endif - -#ifdef PNG_cHRM_SUPPORTED -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_cHRM) PNGARG((png_structp png_ptr, - png_infop info_ptr, double white_x, double white_y, double red_x, - double red_y, double green_x, double green_y, double blue_x, double blue_y)); -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_cHRM_fixed) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_fixed_point int_white_x, png_fixed_point int_white_y, - png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point - int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x, - png_fixed_point int_blue_y)); -#endif -#endif - -#ifdef PNG_gAMA_SUPPORTED -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_gAMA) PNGARG((png_structp png_ptr, - png_infop info_ptr, double *file_gamma)); -#endif -extern PNG_EXPORT(png_uint_32,png_get_gAMA_fixed) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_fixed_point *int_file_gamma)); -#endif - -#ifdef PNG_gAMA_SUPPORTED -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_gAMA) PNGARG((png_structp png_ptr, - png_infop info_ptr, double file_gamma)); -#endif -extern PNG_EXPORT(void,png_set_gAMA_fixed) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_fixed_point int_file_gamma)); -#endif - -#ifdef PNG_hIST_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_hIST) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_16p *hist)); -#endif - -#ifdef PNG_hIST_SUPPORTED -extern PNG_EXPORT(void,png_set_hIST) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_16p hist)); -#endif - -extern PNG_EXPORT(png_uint_32,png_get_IHDR) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 *width, png_uint_32 *height, - int *bit_depth, int *color_type, int *interlace_method, - int *compression_method, int *filter_method)); - -extern PNG_EXPORT(void,png_set_IHDR) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 width, png_uint_32 height, int bit_depth, - int color_type, int interlace_method, int compression_method, - int filter_method)); - -#ifdef PNG_oFFs_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_oFFs) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_int_32 *offset_x, png_int_32 *offset_y, - int *unit_type)); -#endif - -#ifdef PNG_oFFs_SUPPORTED -extern PNG_EXPORT(void,png_set_oFFs) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_int_32 offset_x, png_int_32 offset_y, - int unit_type)); -#endif - -#ifdef PNG_pCAL_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_pCAL) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_charp *purpose, png_int_32 *X0, png_int_32 *X1, - int *type, int *nparams, png_charp *units, png_charpp *params)); -#endif - -#ifdef PNG_pCAL_SUPPORTED -extern PNG_EXPORT(void,png_set_pCAL) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_charp purpose, png_int_32 X0, png_int_32 X1, - int type, int nparams, png_charp units, png_charpp params)); -#endif - -#ifdef PNG_pHYs_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_pHYs) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)); -#endif - -#ifdef PNG_pHYs_SUPPORTED -extern PNG_EXPORT(void,png_set_pHYs) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 res_x, png_uint_32 res_y, int unit_type)); -#endif - -extern PNG_EXPORT(png_uint_32,png_get_PLTE) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_colorp *palette, int *num_palette)); - -extern PNG_EXPORT(void,png_set_PLTE) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_colorp palette, int num_palette)); - -#ifdef PNG_sBIT_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_sBIT) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_color_8p *sig_bit)); -#endif - -#ifdef PNG_sBIT_SUPPORTED -extern PNG_EXPORT(void,png_set_sBIT) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_color_8p sig_bit)); -#endif - -#ifdef PNG_sRGB_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_sRGB) PNGARG((png_structp png_ptr, - png_infop info_ptr, int *intent)); -#endif - -#ifdef PNG_sRGB_SUPPORTED -extern PNG_EXPORT(void,png_set_sRGB) PNGARG((png_structp png_ptr, - png_infop info_ptr, int intent)); -extern PNG_EXPORT(void,png_set_sRGB_gAMA_and_cHRM) PNGARG((png_structp png_ptr, - png_infop info_ptr, int intent)); -#endif - -#ifdef PNG_iCCP_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_iCCP) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_charpp name, int *compression_type, - png_charpp profile, png_uint_32 *proflen)); - /* Note to maintainer: profile should be png_bytepp */ -#endif - -#ifdef PNG_iCCP_SUPPORTED -extern PNG_EXPORT(void,png_set_iCCP) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_charp name, int compression_type, - png_charp profile, png_uint_32 proflen)); - /* Note to maintainer: profile should be png_bytep */ -#endif - -#ifdef PNG_sPLT_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_sPLT) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_sPLT_tpp entries)); -#endif - -#ifdef PNG_sPLT_SUPPORTED -extern PNG_EXPORT(void,png_set_sPLT) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_sPLT_tp entries, int nentries)); -#endif - -#ifdef PNG_TEXT_SUPPORTED -/* png_get_text also returns the number of text chunks in *num_text */ -extern PNG_EXPORT(png_uint_32,png_get_text) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_textp *text_ptr, int *num_text)); -#endif - -/* Note while png_set_text() will accept a structure whose text, - * language, and translated keywords are NULL pointers, the structure - * returned by png_get_text will always contain regular - * zero-terminated C strings. They might be empty strings but - * they will never be NULL pointers. - */ - -#ifdef PNG_TEXT_SUPPORTED -extern PNG_EXPORT(void,png_set_text) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_textp text_ptr, int num_text)); -#endif - -#ifdef PNG_tIME_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_tIME) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_timep *mod_time)); -#endif - -#ifdef PNG_tIME_SUPPORTED -extern PNG_EXPORT(void,png_set_tIME) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_timep mod_time)); -#endif - -#ifdef PNG_tRNS_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_tRNS) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_bytep *trans_alpha, int *num_trans, - png_color_16p *trans_color)); -#endif - -#ifdef PNG_tRNS_SUPPORTED -extern PNG_EXPORT(void,png_set_tRNS) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_bytep trans_alpha, int num_trans, - png_color_16p trans_color)); -#endif - -#ifdef PNG_tRNS_SUPPORTED -#endif - -#ifdef PNG_sCAL_SUPPORTED -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_sCAL) PNGARG((png_structp png_ptr, - png_infop info_ptr, int *unit, double *width, double *height)); -#else -#ifdef PNG_FIXED_POINT_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_sCAL_s) PNGARG((png_structp png_ptr, - png_infop info_ptr, int *unit, png_charpp swidth, png_charpp sheight)); -#endif -#endif -#endif /* PNG_sCAL_SUPPORTED */ - -#ifdef PNG_sCAL_SUPPORTED -#ifdef PNG_FLOATING_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_sCAL) PNGARG((png_structp png_ptr, - png_infop info_ptr, int unit, double width, double height)); -#else -#ifdef PNG_FIXED_POINT_SUPPORTED -extern PNG_EXPORT(void,png_set_sCAL_s) PNGARG((png_structp png_ptr, - png_infop info_ptr, int unit, png_charp swidth, png_charp sheight)); -#endif -#endif -#endif /* PNG_sCAL_SUPPORTED || PNG_WRITE_sCAL_SUPPORTED */ - -#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED -/* Provide a list of chunks and how they are to be handled, if the built-in - handling or default unknown chunk handling is not desired. Any chunks not - listed will be handled in the default manner. The IHDR and IEND chunks - must not be listed. - keep = 0: follow default behaviour - = 1: do not keep - = 2: keep only if safe-to-copy - = 3: keep even if unsafe-to-copy -*/ -extern PNG_EXPORT(void, png_set_keep_unknown_chunks) PNGARG((png_structp - png_ptr, int keep, png_bytep chunk_list, int num_chunks)); -PNG_EXPORT(int,png_handle_as_unknown) PNGARG((png_structp png_ptr, png_bytep - chunk_name)); -#endif -#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED -extern PNG_EXPORT(void, png_set_unknown_chunks) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns)); -extern PNG_EXPORT(void, png_set_unknown_chunk_location) - PNGARG((png_structp png_ptr, png_infop info_ptr, int chunk, int location)); -extern PNG_EXPORT(png_uint_32,png_get_unknown_chunks) PNGARG((png_structp - png_ptr, png_infop info_ptr, png_unknown_chunkpp entries)); -#endif - -/* Png_free_data() will turn off the "valid" flag for anything it frees. - * If you need to turn it off for a chunk that your application has freed, - * you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK); - */ -extern PNG_EXPORT(void, png_set_invalid) PNGARG((png_structp png_ptr, - png_infop info_ptr, int mask)); - -#ifdef PNG_INFO_IMAGE_SUPPORTED -/* The "params" pointer is currently not used and is for future expansion. */ -extern PNG_EXPORT(void, png_read_png) PNGARG((png_structp png_ptr, - png_infop info_ptr, - int transforms, - png_voidp params)); -extern PNG_EXPORT(void, png_write_png) PNGARG((png_structp png_ptr, - png_infop info_ptr, - int transforms, - png_voidp params)); -#endif - -extern PNG_EXPORT(png_charp,png_get_copyright) PNGARG((png_structp png_ptr)); -extern PNG_EXPORT(png_charp,png_get_header_ver) PNGARG((png_structp png_ptr)); -extern PNG_EXPORT(png_charp,png_get_header_version) PNGARG((png_structp - png_ptr)); -extern PNG_EXPORT(png_charp,png_get_libpng_ver) PNGARG((png_structp png_ptr)); - -#ifdef PNG_MNG_FEATURES_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_permit_mng_features) PNGARG((png_structp - png_ptr, png_uint_32 mng_features_permitted)); -#endif - -/* For use in png_set_keep_unknown, added to version 1.2.6 */ -#define PNG_HANDLE_CHUNK_AS_DEFAULT 0 -#define PNG_HANDLE_CHUNK_NEVER 1 -#define PNG_HANDLE_CHUNK_IF_SAFE 2 -#define PNG_HANDLE_CHUNK_ALWAYS 3 - -/* Strip the prepended error numbers ("#nnn ") from error and warning - * messages before passing them to the error or warning handler. - */ -#ifdef PNG_ERROR_NUMBERS_SUPPORTED -extern PNG_EXPORT(void,png_set_strip_error_numbers) PNGARG((png_structp - png_ptr, png_uint_32 strip_mode)); -#endif - -/* Added in libpng-1.2.6 */ -#ifdef PNG_SET_USER_LIMITS_SUPPORTED -extern PNG_EXPORT(void,png_set_user_limits) PNGARG((png_structp - png_ptr, png_uint_32 user_width_max, png_uint_32 user_height_max)); -extern PNG_EXPORT(png_uint_32,png_get_user_width_max) PNGARG((png_structp - png_ptr)); -extern PNG_EXPORT(png_uint_32,png_get_user_height_max) PNGARG((png_structp - png_ptr)); -/* Added in libpng-1.4.0 */ -extern PNG_EXPORT(void,png_set_chunk_cache_max) PNGARG((png_structp - png_ptr, png_uint_32 user_chunk_cache_max)); -extern PNG_EXPORT(png_uint_32,png_get_chunk_cache_max) - PNGARG((png_structp png_ptr)); -/* Added in libpng-1.4.1 */ -extern PNG_EXPORT(void,png_set_chunk_malloc_max) PNGARG((png_structp - png_ptr, png_alloc_size_t user_chunk_cache_max)); -extern PNG_EXPORT(png_alloc_size_t,png_get_chunk_malloc_max) - PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_INCH_CONVERSIONS) && defined(PNG_FLOATING_POINT_SUPPORTED) -PNG_EXPORT(png_uint_32,png_get_pixels_per_inch) PNGARG((png_structp png_ptr, -png_infop info_ptr)); - -PNG_EXPORT(png_uint_32,png_get_x_pixels_per_inch) PNGARG((png_structp png_ptr, -png_infop info_ptr)); - -PNG_EXPORT(png_uint_32,png_get_y_pixels_per_inch) PNGARG((png_structp png_ptr, -png_infop info_ptr)); - -PNG_EXPORT(float,png_get_x_offset_inches) PNGARG((png_structp png_ptr, -png_infop info_ptr)); - -PNG_EXPORT(float,png_get_y_offset_inches) PNGARG((png_structp png_ptr, -png_infop info_ptr)); - -#ifdef PNG_pHYs_SUPPORTED -PNG_EXPORT(png_uint_32,png_get_pHYs_dpi) PNGARG((png_structp png_ptr, -png_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)); -#endif /* PNG_pHYs_SUPPORTED */ -#endif /* PNG_INCH_CONVERSIONS && PNG_FLOATING_POINT_SUPPORTED */ - -/* Added in libpng-1.4.0 */ -#ifdef PNG_IO_STATE_SUPPORTED -extern PNG_EXPORT(png_uint_32,png_get_io_state) PNGARG((png_structp png_ptr)); - -extern PNG_EXPORT(png_bytep,png_get_io_chunk_name) - PNGARG((png_structp png_ptr)); - -/* The flags returned by png_get_io_state() are the following: */ -#define PNG_IO_NONE 0x0000 /* no I/O at this moment */ -#define PNG_IO_READING 0x0001 /* currently reading */ -#define PNG_IO_WRITING 0x0002 /* currently writing */ -#define PNG_IO_SIGNATURE 0x0010 /* currently at the file signature */ -#define PNG_IO_CHUNK_HDR 0x0020 /* currently at the chunk header */ -#define PNG_IO_CHUNK_DATA 0x0040 /* currently at the chunk data */ -#define PNG_IO_CHUNK_CRC 0x0080 /* currently at the chunk crc */ -#define PNG_IO_MASK_OP 0x000f /* current operation: reading/writing */ -#define PNG_IO_MASK_LOC 0x00f0 /* current location: sig/hdr/data/crc */ -#endif /* ?PNG_IO_STATE_SUPPORTED */ - -/* Maintainer: Put new public prototypes here ^, in libpng.3, and project - * defs - */ - -#ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED -/* With these routines we avoid an integer divide, which will be slower on - * most machines. However, it does take more operations than the corresponding - * divide method, so it may be slower on a few RISC systems. There are two - * shifts (by 8 or 16 bits) and an addition, versus a single integer divide. - * - * Note that the rounding factors are NOT supposed to be the same! 128 and - * 32768 are correct for the NODIV code; 127 and 32767 are correct for the - * standard method. - * - * [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ] - */ - - /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */ - -# define png_composite(composite, fg, alpha, bg) \ - { png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) \ - * (png_uint_16)(alpha) \ - + (png_uint_16)(bg)*(png_uint_16)(255 \ - - (png_uint_16)(alpha)) + (png_uint_16)128); \ - (composite) = (png_byte)((temp + (temp >> 8)) >> 8); } - -# define png_composite_16(composite, fg, alpha, bg) \ - { png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) \ - * (png_uint_32)(alpha) \ - + (png_uint_32)(bg)*(png_uint_32)(65535L \ - - (png_uint_32)(alpha)) + (png_uint_32)32768L); \ - (composite) = (png_uint_16)((temp + (temp >> 16)) >> 16); } - -#else /* Standard method using integer division */ - -# define png_composite(composite, fg, alpha, bg) \ - (composite) = (png_byte)(((png_uint_16)(fg) * (png_uint_16)(alpha) + \ - (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \ - (png_uint_16)127) / 255) - -# define png_composite_16(composite, fg, alpha, bg) \ - (composite) = (png_uint_16)(((png_uint_32)(fg) * (png_uint_32)(alpha) + \ - (png_uint_32)(bg)*(png_uint_32)(65535L - (png_uint_32)(alpha)) + \ - (png_uint_32)32767) / (png_uint_32)65535L) -#endif /* PNG_READ_COMPOSITE_NODIV_SUPPORTED */ - -#ifdef PNG_USE_READ_MACROS -/* Inline macros to do direct reads of bytes from the input buffer. - * The png_get_int_32() routine assumes we are using two's complement - * format for negative values, which is almost certainly true. - */ -/* We could make special-case BIG_ENDIAN macros that do direct reads here */ -# define png_get_uint_32(buf) \ - (((png_uint_32)(*(buf)) << 24) + \ - ((png_uint_32)(*((buf) + 1)) << 16) + \ - ((png_uint_32)(*((buf) + 2)) << 8) + \ - ((png_uint_32)(*((buf) + 3)))) -# define png_get_uint_16(buf) \ - (((png_uint_32)(*(buf)) << 8) + \ - ((png_uint_32)(*((buf) + 1)))) -#ifdef PNG_GET_INT_32_SUPPORTED -# define png_get_int_32(buf) \ - (((png_int_32)(*(buf)) << 24) + \ - ((png_int_32)(*((buf) + 1)) << 16) + \ - ((png_int_32)(*((buf) + 2)) << 8) + \ - ((png_int_32)(*((buf) + 3)))) -#endif -#else -extern PNG_EXPORT(png_uint_32,png_get_uint_32) PNGARG((png_bytep buf)); -extern PNG_EXPORT(png_uint_16,png_get_uint_16) PNGARG((png_bytep buf)); -#ifdef PNG_GET_INT_32_SUPPORTED -extern PNG_EXPORT(png_int_32,png_get_int_32) PNGARG((png_bytep buf)); -#endif -#endif -extern PNG_EXPORT(png_uint_32,png_get_uint_31) - PNGARG((png_structp png_ptr, png_bytep buf)); -/* No png_get_int_16 -- may be added if there's a real need for it. */ - -/* Place a 32-bit number into a buffer in PNG byte order (big-endian). */ -extern PNG_EXPORT(void,png_save_uint_32) - PNGARG((png_bytep buf, png_uint_32 i)); -extern PNG_EXPORT(void,png_save_int_32) - PNGARG((png_bytep buf, png_int_32 i)); - -/* Place a 16-bit number into a buffer in PNG byte order. - * The parameter is declared unsigned int, not png_uint_16, - * just to avoid potential problems on pre-ANSI C compilers. - */ -extern PNG_EXPORT(void,png_save_uint_16) - PNGARG((png_bytep buf, unsigned int i)); -/* No png_save_int_16 -- may be added if there's a real need for it. */ - -/* ************************************************************************* */ - -/* Various modes of operation. Note that after an init, mode is set to - * zero automatically when the structure is created. - */ -#define PNG_HAVE_IHDR 0x01 -#define PNG_HAVE_PLTE 0x02 -#define PNG_HAVE_IDAT 0x04 -#define PNG_AFTER_IDAT 0x08 /* Have complete zlib datastream */ -#define PNG_HAVE_IEND 0x10 -#define PNG_HAVE_gAMA 0x20 -#define PNG_HAVE_cHRM 0x40 - -#ifdef __cplusplus -} -#endif - -#endif /* PNG_VERSION_INFO_ONLY */ -/* Do not put anything past this line */ -#endif /* PNG_H */ diff --git a/reactos/dll/3rdparty/libpng/pngconf.h b/reactos/dll/3rdparty/libpng/pngconf.h deleted file mode 100644 index 0c1065cfb47..00000000000 --- a/reactos/dll/3rdparty/libpng/pngconf.h +++ /dev/null @@ -1,1525 +0,0 @@ - -/* pngconf.h - machine configurable file for libpng - * - * libpng version 1.4.3 - June 26, 2010 - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2010 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This code is released under the libpng license. - * For conditions of distribution and use, see the disclaimer - * and license in png.h - * - */ - -/* Any machine specific code is near the front of this file, so if you - * are configuring libpng for a machine, you may want to read the section - * starting here down to where it starts to typedef png_color, png_text, - * and png_info. - */ - -#ifndef PNGCONF_H -#define PNGCONF_H - -#ifndef PNG_NO_LIMITS_H -# include -#endif - -/* Added at libpng-1.2.9 */ - -/* config.h is created by and PNG_CONFIGURE_LIBPNG is set by the "configure" - * script. - */ -#ifdef PNG_CONFIGURE_LIBPNG -# ifdef HAVE_CONFIG_H -# include "config.h" -# endif -#endif - -/* - * Added at libpng-1.2.8 - * - * PNG_USER_CONFIG has to be defined on the compiler command line. This - * includes the resource compiler for Windows DLL configurations. - */ -#ifdef PNG_USER_CONFIG -# ifndef PNG_USER_PRIVATEBUILD -# define PNG_USER_PRIVATEBUILD -# endif -# include "pngusr.h" -#endif - -/* - * If you create a private DLL you need to define in "pngusr.h" the followings: - * #define PNG_USER_PRIVATEBUILD - * e.g. #define PNG_USER_PRIVATEBUILD "Build by MyCompany for xyz reasons." - * #define PNG_USER_DLLFNAME_POSTFIX - * e.g. // private DLL "libpng13gx.dll" - * #define PNG_USER_DLLFNAME_POSTFIX "gx" - * - * The following macros are also at your disposal if you want to complete the - * DLL VERSIONINFO structure. - * - PNG_USER_VERSIONINFO_COMMENTS - * - PNG_USER_VERSIONINFO_COMPANYNAME - * - PNG_USER_VERSIONINFO_LEGALTRADEMARKS - */ - -#ifdef __STDC__ -# ifdef SPECIALBUILD -# pragma message("PNG_LIBPNG_SPECIALBUILD (and deprecated SPECIALBUILD)\ - are now LIBPNG reserved macros. Use PNG_USER_PRIVATEBUILD instead.") -# endif - -# ifdef PRIVATEBUILD -# pragma message("PRIVATEBUILD is deprecated.\ - Use PNG_USER_PRIVATEBUILD instead.") -# define PNG_USER_PRIVATEBUILD PRIVATEBUILD -# endif -#endif /* __STDC__ */ - -/* End of material added to libpng-1.2.8 */ - -#ifndef PNG_VERSION_INFO_ONLY - -/* This is the size of the compression buffer, and thus the size of - * an IDAT chunk. Make this whatever size you feel is best for your - * machine. One of these will be allocated per png_struct. When this - * is full, it writes the data to the disk, and does some other - * calculations. Making this an extremely small size will slow - * the library down, but you may want to experiment to determine - * where it becomes significant, if you are concerned with memory - * usage. Note that zlib allocates at least 32Kb also. For readers, - * this describes the size of the buffer available to read the data in. - * Unless this gets smaller than the size of a row (compressed), - * it should not make much difference how big this is. - */ - -#ifndef PNG_ZBUF_SIZE -# define PNG_ZBUF_SIZE 8192 -#endif - -/* Enable if you want a write-only libpng */ - -#ifndef PNG_NO_READ_SUPPORTED -# define PNG_READ_SUPPORTED -#endif - -/* Enable if you want a read-only libpng */ - -#ifndef PNG_NO_WRITE_SUPPORTED -# define PNG_WRITE_SUPPORTED -#endif - -/* Enabled in 1.4.0. */ -#ifdef PNG_ALLOW_BENIGN_ERRORS -# define png_benign_error png_warning -# define png_chunk_benign_error png_chunk_warning -#else -# ifndef PNG_BENIGN_ERRORS_SUPPORTED -# define png_benign_error png_error -# define png_chunk_benign_error png_chunk_error -# endif -#endif - -/* Added at libpng version 1.4.0 */ -#if !defined(PNG_NO_WARNINGS) && !defined(PNG_WARNINGS_SUPPORTED) -# define PNG_WARNINGS_SUPPORTED -#endif - -/* Added at libpng version 1.4.0 */ -#if !defined(PNG_NO_ERROR_TEXT) && !defined(PNG_ERROR_TEXT_SUPPORTED) -# define PNG_ERROR_TEXT_SUPPORTED -#endif - -/* Added at libpng version 1.4.0 */ -#if !defined(PNG_NO_CHECK_cHRM) && !defined(PNG_CHECK_cHRM_SUPPORTED) -# define PNG_CHECK_cHRM_SUPPORTED -#endif - -/* Added at libpng version 1.4.0 */ -#if !defined(PNG_NO_ALIGNED_MEMORY) && !defined(PNG_ALIGNED_MEMORY_SUPPORTED) -# define PNG_ALIGNED_MEMORY_SUPPORTED -#endif - -/* Enabled by default in 1.2.0. You can disable this if you don't need to - support PNGs that are embedded in MNG datastreams */ -#ifndef PNG_NO_MNG_FEATURES -# ifndef PNG_MNG_FEATURES_SUPPORTED -# define PNG_MNG_FEATURES_SUPPORTED -# endif -#endif - -/* Added at libpng version 1.4.0 */ -#ifndef PNG_NO_FLOATING_POINT_SUPPORTED -# ifndef PNG_FLOATING_POINT_SUPPORTED -# define PNG_FLOATING_POINT_SUPPORTED -# endif -#endif - -/* Added at libpng-1.4.0beta49 for testing (this test is no longer used - in libpng and png_calloc() is always present) - */ -#define PNG_CALLOC_SUPPORTED - -/* If you are running on a machine where you cannot allocate more - * than 64K of memory at once, uncomment this. While libpng will not - * normally need that much memory in a chunk (unless you load up a very - * large file), zlib needs to know how big of a chunk it can use, and - * libpng thus makes sure to check any memory allocation to verify it - * will fit into memory. -#define PNG_MAX_MALLOC_64K - */ -#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K) -# define PNG_MAX_MALLOC_64K -#endif - -/* Special munging to support doing things the 'cygwin' way: - * 'Normal' png-on-win32 defines/defaults: - * PNG_BUILD_DLL -- building dll - * PNG_USE_DLL -- building an application, linking to dll - * (no define) -- building static library, or building an - * application and linking to the static lib - * 'Cygwin' defines/defaults: - * PNG_BUILD_DLL -- (ignored) building the dll - * (no define) -- (ignored) building an application, linking to the dll - * PNG_STATIC -- (ignored) building the static lib, or building an - * application that links to the static lib. - * ALL_STATIC -- (ignored) building various static libs, or building an - * application that links to the static libs. - * Thus, - * a cygwin user should define either PNG_BUILD_DLL or PNG_STATIC, and - * this bit of #ifdefs will define the 'correct' config variables based on - * that. If a cygwin user *wants* to define 'PNG_USE_DLL' that's okay, but - * unnecessary. - * - * Also, the precedence order is: - * ALL_STATIC (since we can't #undef something outside our namespace) - * PNG_BUILD_DLL - * PNG_STATIC - * (nothing) == PNG_USE_DLL - * - * CYGWIN (2002-01-20): The preceding is now obsolete. With the advent - * of auto-import in binutils, we no longer need to worry about - * __declspec(dllexport) / __declspec(dllimport) and friends. Therefore, - * we don't need to worry about PNG_STATIC or ALL_STATIC when it comes - * to __declspec() stuff. However, we DO need to worry about - * PNG_BUILD_DLL and PNG_STATIC because those change some defaults - * such as CONSOLE_IO. - */ -#ifdef __CYGWIN__ -# ifdef ALL_STATIC -# ifdef PNG_BUILD_DLL -# undef PNG_BUILD_DLL -# endif -# ifdef PNG_USE_DLL -# undef PNG_USE_DLL -# endif -# ifdef PNG_DLL -# undef PNG_DLL -# endif -# ifndef PNG_STATIC -# define PNG_STATIC -# endif -# else -# ifdef PNG_BUILD_DLL -# ifdef PNG_STATIC -# undef PNG_STATIC -# endif -# ifdef PNG_USE_DLL -# undef PNG_USE_DLL -# endif -# ifndef PNG_DLL -# define PNG_DLL -# endif -# else -# ifdef PNG_STATIC -# ifdef PNG_USE_DLL -# undef PNG_USE_DLL -# endif -# ifdef PNG_DLL -# undef PNG_DLL -# endif -# else -# ifndef PNG_USE_DLL -# define PNG_USE_DLL -# endif -# ifndef PNG_DLL -# define PNG_DLL -# endif -# endif -# endif -# endif -#endif - -/* This protects us against compilers that run on a windowing system - * and thus don't have or would rather us not use the stdio types: - * stdin, stdout, and stderr. The only one currently used is stderr - * in png_error() and png_warning(). #defining PNG_NO_CONSOLE_IO will - * prevent these from being compiled and used. #defining PNG_NO_STDIO - * will also prevent these, plus will prevent the entire set of stdio - * macros and functions (FILE *, printf, etc.) from being compiled and used, - * unless (PNG_DEBUG > 0) has been #defined. - * - * #define PNG_NO_CONSOLE_IO - * #define PNG_NO_STDIO - */ - -#if !defined(PNG_NO_STDIO) && !defined(PNG_STDIO_SUPPORTED) -# define PNG_STDIO_SUPPORTED -#endif - - -#ifdef PNG_BUILD_DLL -# if !defined(PNG_CONSOLE_IO_SUPPORTED) && !defined(PNG_NO_CONSOLE_IO) -# define PNG_NO_CONSOLE_IO -# endif -#endif - -# ifdef PNG_NO_STDIO -# ifndef PNG_NO_CONSOLE_IO -# define PNG_NO_CONSOLE_IO -# endif -# ifdef PNG_DEBUG -# if (PNG_DEBUG > 0) -# include -# endif -# endif -# else -# include -# endif - -#if !(defined PNG_NO_CONSOLE_IO) && !defined(PNG_CONSOLE_IO_SUPPORTED) -# define PNG_CONSOLE_IO_SUPPORTED -#endif - -/* This macro protects us against machines that don't have function - * prototypes (ie K&R style headers). If your compiler does not handle - * function prototypes, define this macro and use the included ansi2knr. - * I've always been able to use _NO_PROTO as the indicator, but you may - * need to drag the empty declaration out in front of here, or change the - * ifdef to suit your own needs. - */ -#ifndef PNGARG - -#ifdef OF /* zlib prototype munger */ -# define PNGARG(arglist) OF(arglist) -#else - -#ifdef _NO_PROTO -# define PNGARG(arglist) () -#else -# define PNGARG(arglist) arglist -#endif /* _NO_PROTO */ - -#endif /* OF */ - -#endif /* PNGARG */ - -/* Try to determine if we are compiling on a Mac. Note that testing for - * just __MWERKS__ is not good enough, because the Codewarrior is now used - * on non-Mac platforms. - */ -#ifndef MACOS -# if (defined(__MWERKS__) && defined(macintosh)) || defined(applec) || \ - defined(THINK_C) || defined(__SC__) || defined(TARGET_OS_MAC) -# define MACOS -# endif -#endif - -/* Enough people need this for various reasons to include it here */ -#if !defined(MACOS) && !defined(RISCOS) -# include -#endif - -/* PNG_SETJMP_NOT_SUPPORTED and PNG_NO_SETJMP_SUPPORTED are deprecated. */ -#if !defined(PNG_NO_SETJMP) && \ - !defined(PNG_SETJMP_NOT_SUPPORTED) && !defined(PNG_NO_SETJMP_SUPPORTED) -# define PNG_SETJMP_SUPPORTED -#endif - -#ifdef PNG_SETJMP_SUPPORTED -/* This is an attempt to force a single setjmp behaviour on Linux. If - * the X config stuff didn't define _BSD_SOURCE we wouldn't need this. - * - * You can bypass this test if you know that your application uses exactly - * the same setjmp.h that was included when libpng was built. Only define - * PNG_SKIP_SETJMP_CHECK while building your application, prior to the - * application's '#include "png.h"'. Don't define PNG_SKIP_SETJMP_CHECK - * while building a separate libpng library for general use. - */ - -# ifndef PNG_SKIP_SETJMP_CHECK -# ifdef __linux__ -# ifdef _BSD_SOURCE -# define PNG_SAVE_BSD_SOURCE -# undef _BSD_SOURCE -# endif -# ifdef _SETJMP_H - /* If you encounter a compiler error here, see the explanation - * near the end of INSTALL. - */ - __pngconf.h__ in libpng already includes setjmp.h; - __dont__ include it again.; -# endif -# endif /* __linux__ */ -# endif /* PNG_SKIP_SETJMP_CHECK */ - - /* Include setjmp.h for error handling */ -# include - -# ifdef __linux__ -# ifdef PNG_SAVE_BSD_SOURCE -# ifdef _BSD_SOURCE -# undef _BSD_SOURCE -# endif -# define _BSD_SOURCE -# undef PNG_SAVE_BSD_SOURCE -# endif -# endif /* __linux__ */ -#endif /* PNG_SETJMP_SUPPORTED */ - -#ifdef BSD -# include -#else -# include -#endif - -/* Other defines for things like memory and the like can go here. */ - -/* This controls how fine the quantizing gets. As this allocates - * a largish chunk of memory (32K), those who are not as concerned - * with quantizing quality can decrease some or all of these. - */ - -/* Prior to libpng-1.4.2, these were PNG_DITHER_*_BITS - * These migration aids will be removed from libpng-1.5.0. - */ -#ifdef PNG_DITHER_RED_BITS -# define PNG_QUANTIZE_RED_BITS PNG_DITHER_RED_BITS -#endif -#ifdef PNG_DITHER_GREEN_BITS -# define PNG_QUANTIZE_GREEN_BITS PNG_DITHER_GREEN_BITS -#endif -#ifdef PNG_DITHER_BLUE_BITS -# define PNG_QUANTIZE_BLUE_BITS PNG_DITHER_BLUE_BITS -#endif - -#ifndef PNG_QUANTIZE_RED_BITS -# define PNG_QUANTIZE_RED_BITS 5 -#endif -#ifndef PNG_QUANTIZE_GREEN_BITS -# define PNG_QUANTIZE_GREEN_BITS 5 -#endif -#ifndef PNG_QUANTIZE_BLUE_BITS -# define PNG_QUANTIZE_BLUE_BITS 5 -#endif - -/* This controls how fine the gamma correction becomes when you - * are only interested in 8 bits anyway. Increasing this value - * results in more memory being used, and more pow() functions - * being called to fill in the gamma tables. Don't set this value - * less then 8, and even that may not work (I haven't tested it). - */ - -#ifndef PNG_MAX_GAMMA_8 -# define PNG_MAX_GAMMA_8 11 -#endif - -/* This controls how much a difference in gamma we can tolerate before - * we actually start doing gamma conversion. - */ -#ifndef PNG_GAMMA_THRESHOLD -# define PNG_GAMMA_THRESHOLD 0.05 -#endif - -/* The following uses const char * instead of char * for error - * and warning message functions, so some compilers won't complain. - * If you do not want to use const, define PNG_NO_CONST here. - */ - -#ifndef PNG_CONST -# ifndef PNG_NO_CONST -# define PNG_CONST const -# else -# define PNG_CONST -# endif -#endif - -/* The following defines give you the ability to remove code from the - * library that you will not be using. I wish I could figure out how to - * automate this, but I can't do that without making it seriously hard - * on the users. So if you are not using an ability, change the #define - * to and #undef, and that part of the library will not be compiled. If - * your linker can't find a function, you may want to make sure the - * ability is defined here. Some of these depend upon some others being - * defined. I haven't figured out all the interactions here, so you may - * have to experiment awhile to get everything to compile. If you are - * creating or using a shared library, you probably shouldn't touch this, - * as it will affect the size of the structures, and this will cause bad - * things to happen if the library and/or application ever change. - */ - -/* Any features you will not be using can be undef'ed here */ - -/* GR-P, 0.96a: Set "*TRANSFORMS_SUPPORTED as default but allow user - * to turn it off with PNG_NO_READ|WRITE_TRANSFORMS on the compile line, - * then pick and choose which ones to define without having to edit this - * file. It is safe to use the PNG_NO_READ|WRITE_TRANSFORMS - * if you only want to have a png-compliant reader/writer but don't need - * any of the extra transformations. This saves about 80 kbytes in a - * typical installation of the library. (PNG_NO_* form added in version - * 1.0.1c, for consistency; PNG_*_TRANSFORMS_NOT_SUPPORTED deprecated in - * 1.4.0) - */ - -/* Ignore attempt to turn off both floating and fixed point support */ -#if !defined(PNG_FLOATING_POINT_SUPPORTED) || \ - !defined(PNG_NO_FIXED_POINT_SUPPORTED) -# define PNG_FIXED_POINT_SUPPORTED -#endif - -#ifdef PNG_READ_SUPPORTED - -/* PNG_READ_TRANSFORMS_NOT_SUPPORTED is deprecated. */ -#if !defined(PNG_READ_TRANSFORMS_NOT_SUPPORTED) && \ - !defined(PNG_NO_READ_TRANSFORMS) -# define PNG_READ_TRANSFORMS_SUPPORTED -#endif - -#ifdef PNG_READ_TRANSFORMS_SUPPORTED -# ifndef PNG_NO_READ_EXPAND -# define PNG_READ_EXPAND_SUPPORTED -# endif -# ifndef PNG_NO_READ_SHIFT -# define PNG_READ_SHIFT_SUPPORTED -# endif -# ifndef PNG_NO_READ_PACK -# define PNG_READ_PACK_SUPPORTED -# endif -# ifndef PNG_NO_READ_BGR -# define PNG_READ_BGR_SUPPORTED -# endif -# ifndef PNG_NO_READ_SWAP -# define PNG_READ_SWAP_SUPPORTED -# endif -# ifndef PNG_NO_READ_PACKSWAP -# define PNG_READ_PACKSWAP_SUPPORTED -# endif -# ifndef PNG_NO_READ_INVERT -# define PNG_READ_INVERT_SUPPORTED -# endif -# ifndef PNG_NO_READ_QUANTIZE - /* Prior to libpng-1.4.0 this was PNG_READ_DITHER_SUPPORTED */ -# ifndef PNG_NO_READ_DITHER /* This migration aid will be removed */ -# define PNG_READ_QUANTIZE_SUPPORTED -# endif -# endif -# ifndef PNG_NO_READ_BACKGROUND -# define PNG_READ_BACKGROUND_SUPPORTED -# endif -# ifndef PNG_NO_READ_16_TO_8 -# define PNG_READ_16_TO_8_SUPPORTED -# endif -# ifndef PNG_NO_READ_FILLER -# define PNG_READ_FILLER_SUPPORTED -# endif -# ifndef PNG_NO_READ_GAMMA -# define PNG_READ_GAMMA_SUPPORTED -# endif -# ifndef PNG_NO_READ_GRAY_TO_RGB -# define PNG_READ_GRAY_TO_RGB_SUPPORTED -# endif -# ifndef PNG_NO_READ_SWAP_ALPHA -# define PNG_READ_SWAP_ALPHA_SUPPORTED -# endif -# ifndef PNG_NO_READ_INVERT_ALPHA -# define PNG_READ_INVERT_ALPHA_SUPPORTED -# endif -# ifndef PNG_NO_READ_STRIP_ALPHA -# define PNG_READ_STRIP_ALPHA_SUPPORTED -# endif -# ifndef PNG_NO_READ_USER_TRANSFORM -# define PNG_READ_USER_TRANSFORM_SUPPORTED -# endif -# ifndef PNG_NO_READ_RGB_TO_GRAY -# define PNG_READ_RGB_TO_GRAY_SUPPORTED -# endif -#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ - -/* PNG_PROGRESSIVE_READ_NOT_SUPPORTED is deprecated. */ -#if !defined(PNG_NO_PROGRESSIVE_READ) && \ - !defined(PNG_PROGRESSIVE_READ_NOT_SUPPORTED) /* if you don't do progressive */ -# define PNG_PROGRESSIVE_READ_SUPPORTED /* reading. This is not talking */ -#endif /* about interlacing capability! You'll */ - /* still have interlacing unless you change the following define: */ - -#define PNG_READ_INTERLACING_SUPPORTED /* required for PNG-compliant decoders */ - -/* PNG_NO_SEQUENTIAL_READ_SUPPORTED is deprecated. */ -#if !defined(PNG_NO_SEQUENTIAL_READ) && \ - !defined(PNG_SEQUENTIAL_READ_SUPPORTED) && \ - !defined(PNG_NO_SEQUENTIAL_READ_SUPPORTED) -# define PNG_SEQUENTIAL_READ_SUPPORTED -#endif - -#ifndef PNG_NO_READ_COMPOSITE_NODIV -# ifndef PNG_NO_READ_COMPOSITED_NODIV /* libpng-1.0.x misspelling */ -# define PNG_READ_COMPOSITE_NODIV_SUPPORTED /* well tested on Intel, SGI */ -# endif -#endif - -#if !defined(PNG_NO_GET_INT_32) || defined(PNG_READ_oFFS_SUPPORTED) || \ - defined(PNG_READ_pCAL_SUPPORTED) -# ifndef PNG_GET_INT_32_SUPPORTED -# define PNG_GET_INT_32_SUPPORTED -# endif -#endif - -#endif /* PNG_READ_SUPPORTED */ - -#ifdef PNG_WRITE_SUPPORTED - -/* PNG_WRITE_TRANSFORMS_NOT_SUPPORTED is deprecated. */ -#if !defined(PNG_WRITE_TRANSFORMS_NOT_SUPPORTED) && \ - !defined(PNG_NO_WRITE_TRANSFORMS) -# define PNG_WRITE_TRANSFORMS_SUPPORTED -#endif - -#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED -# ifndef PNG_NO_WRITE_SHIFT -# define PNG_WRITE_SHIFT_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_PACK -# define PNG_WRITE_PACK_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_BGR -# define PNG_WRITE_BGR_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_SWAP -# define PNG_WRITE_SWAP_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_PACKSWAP -# define PNG_WRITE_PACKSWAP_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_INVERT -# define PNG_WRITE_INVERT_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_FILLER -# define PNG_WRITE_FILLER_SUPPORTED /* same as WRITE_STRIP_ALPHA */ -# endif -# ifndef PNG_NO_WRITE_SWAP_ALPHA -# define PNG_WRITE_SWAP_ALPHA_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_INVERT_ALPHA -# define PNG_WRITE_INVERT_ALPHA_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_USER_TRANSFORM -# define PNG_WRITE_USER_TRANSFORM_SUPPORTED -# endif -#endif /* PNG_WRITE_TRANSFORMS_SUPPORTED */ - -#if !defined(PNG_NO_WRITE_INTERLACING_SUPPORTED) && \ - !defined(PNG_WRITE_INTERLACING_SUPPORTED) - /* This is not required for PNG-compliant encoders, but can cause - * trouble if left undefined - */ -# define PNG_WRITE_INTERLACING_SUPPORTED -#endif - -#if !defined(PNG_NO_WRITE_WEIGHTED_FILTER) && \ - !defined(PNG_WRITE_WEIGHTED_FILTER) && \ - defined(PNG_FLOATING_POINT_SUPPORTED) -# define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED -#endif - -#ifndef PNG_NO_WRITE_FLUSH -# define PNG_WRITE_FLUSH_SUPPORTED -#endif - -#if !defined(PNG_NO_SAVE_INT_32) || defined(PNG_WRITE_oFFS_SUPPORTED) || \ - defined(PNG_WRITE_pCAL_SUPPORTED) -# ifndef PNG_SAVE_INT_32_SUPPORTED -# define PNG_SAVE_INT_32_SUPPORTED -# endif -#endif - -#endif /* PNG_WRITE_SUPPORTED */ - -#define PNG_NO_ERROR_NUMBERS - -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) -# ifndef PNG_NO_USER_TRANSFORM_PTR -# define PNG_USER_TRANSFORM_PTR_SUPPORTED -# endif -#endif - -#if defined(PNG_STDIO_SUPPORTED) && !defined(PNG_TIME_RFC1123_SUPPORTED) -# define PNG_TIME_RFC1123_SUPPORTED -#endif - -/* This adds extra functions in pngget.c for accessing data from the - * info pointer (added in version 0.99) - * png_get_image_width() - * png_get_image_height() - * png_get_bit_depth() - * png_get_color_type() - * png_get_compression_type() - * png_get_filter_type() - * png_get_interlace_type() - * png_get_pixel_aspect_ratio() - * png_get_pixels_per_meter() - * png_get_x_offset_pixels() - * png_get_y_offset_pixels() - * png_get_x_offset_microns() - * png_get_y_offset_microns() - */ -#if !defined(PNG_NO_EASY_ACCESS) && !defined(PNG_EASY_ACCESS_SUPPORTED) -# define PNG_EASY_ACCESS_SUPPORTED -#endif - -/* Added at libpng-1.2.0 */ -#if !defined(PNG_NO_USER_MEM) && !defined(PNG_USER_MEM_SUPPORTED) -# define PNG_USER_MEM_SUPPORTED -#endif - -/* Added at libpng-1.2.6 */ -#ifndef PNG_NO_SET_USER_LIMITS -# ifndef PNG_SET_USER_LIMITS_SUPPORTED -# define PNG_SET_USER_LIMITS_SUPPORTED -# endif - /* Feature added at libpng-1.4.0, this flag added at 1.4.1 */ -# ifndef PNG_SET_CHUNK_CACHE_LIMIT_SUPPORTED -# define PNG_SET_CHUNK_CACHE_LIMIT_SUPPORTED -# endif - /* Feature added at libpng-1.4.1, this flag added at 1.4.1 */ -# ifndef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED -# define PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED -# endif -#endif - -/* Added at libpng-1.2.43 */ -#ifndef PNG_USER_LIMITS_SUPPORTED -# ifndef PNG_NO_USER_LIMITS -# define PNG_USER_LIMITS_SUPPORTED -# endif -#endif - -/* Added at libpng-1.0.16 and 1.2.6. To accept all valid PNGs no matter - * how large, set these two limits to 0x7fffffffL - */ -#ifndef PNG_USER_WIDTH_MAX -# define PNG_USER_WIDTH_MAX 1000000L -#endif -#ifndef PNG_USER_HEIGHT_MAX -# define PNG_USER_HEIGHT_MAX 1000000L -#endif - -/* Added at libpng-1.2.43. To accept all valid PNGs no matter - * how large, set these two limits to 0. - */ -#ifndef PNG_USER_CHUNK_CACHE_MAX -# define PNG_USER_CHUNK_CACHE_MAX 0 -#endif - -/* Added at libpng-1.2.43 */ -#ifndef PNG_USER_CHUNK_MALLOC_MAX -# define PNG_USER_CHUNK_MALLOC_MAX 0 -#endif - -/* Added at libpng-1.4.0 */ -#if !defined(PNG_NO_IO_STATE) && !defined(PNG_IO_STATE_SUPPORTED) -# define PNG_IO_STATE_SUPPORTED -#endif - -#ifndef PNG_LITERAL_SHARP -# define PNG_LITERAL_SHARP 0x23 -#endif -#ifndef PNG_LITERAL_LEFT_SQUARE_BRACKET -# define PNG_LITERAL_LEFT_SQUARE_BRACKET 0x5b -#endif -#ifndef PNG_LITERAL_RIGHT_SQUARE_BRACKET -# define PNG_LITERAL_RIGHT_SQUARE_BRACKET 0x5d -#endif -#ifndef PNG_STRING_NEWLINE -#define PNG_STRING_NEWLINE "\n" -#endif - -/* These are currently experimental features, define them if you want */ - -/* Very little testing */ -/* -#ifdef PNG_READ_SUPPORTED -# ifndef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED -# define PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED -# endif -#endif -*/ - -/* This is only for PowerPC big-endian and 680x0 systems */ -/* some testing */ -/* -#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED -# define PNG_READ_BIG_ENDIAN_SUPPORTED -#endif -*/ - -#if !defined(PNG_NO_USE_READ_MACROS) && !defined(PNG_USE_READ_MACROS) -# define PNG_USE_READ_MACROS -#endif - -/* Buggy compilers (e.g., gcc 2.7.2.2) need PNG_NO_POINTER_INDEXING */ - -#if !defined(PNG_NO_POINTER_INDEXING) && \ - !defined(PNG_POINTER_INDEXING_SUPPORTED) -# define PNG_POINTER_INDEXING_SUPPORTED -#endif - - -/* Any chunks you are not interested in, you can undef here. The - * ones that allocate memory may be expecially important (hIST, - * tEXt, zTXt, tRNS, pCAL). Others will just save time and make png_info - * a bit smaller. - */ - -/* The size of the png_text structure changed in libpng-1.0.6 when - * iTXt support was added. iTXt support was turned off by default through - * libpng-1.2.x, to support old apps that malloc the png_text structure - * instead of calling png_set_text() and letting libpng malloc it. It - * was turned on by default in libpng-1.4.0. - */ - -/* PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED is deprecated. */ -#if defined(PNG_READ_SUPPORTED) && \ - !defined(PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \ - !defined(PNG_NO_READ_ANCILLARY_CHUNKS) -# define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED -#endif - -/* PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED is deprecated. */ -#if defined(PNG_WRITE_SUPPORTED) && \ - !defined(PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \ - !defined(PNG_NO_WRITE_ANCILLARY_CHUNKS) -# define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED -#endif - -#ifdef PNG_READ_ANCILLARY_CHUNKS_SUPPORTED - -#ifdef PNG_NO_READ_TEXT -# define PNG_NO_READ_iTXt -# define PNG_NO_READ_tEXt -# define PNG_NO_READ_zTXt -#endif - -#ifndef PNG_NO_READ_bKGD -# define PNG_READ_bKGD_SUPPORTED -# define PNG_bKGD_SUPPORTED -#endif -#ifndef PNG_NO_READ_cHRM -# define PNG_READ_cHRM_SUPPORTED -# define PNG_cHRM_SUPPORTED -#endif -#ifndef PNG_NO_READ_gAMA -# define PNG_READ_gAMA_SUPPORTED -# define PNG_gAMA_SUPPORTED -#endif -#ifndef PNG_NO_READ_hIST -# define PNG_READ_hIST_SUPPORTED -# define PNG_hIST_SUPPORTED -#endif -#ifndef PNG_NO_READ_iCCP -# define PNG_READ_iCCP_SUPPORTED -# define PNG_iCCP_SUPPORTED -#endif -#ifndef PNG_NO_READ_iTXt -# ifndef PNG_READ_iTXt_SUPPORTED -# define PNG_READ_iTXt_SUPPORTED -# endif -# ifndef PNG_iTXt_SUPPORTED -# define PNG_iTXt_SUPPORTED -# endif -#endif -#ifndef PNG_NO_READ_oFFs -# define PNG_READ_oFFs_SUPPORTED -# define PNG_oFFs_SUPPORTED -#endif -#ifndef PNG_NO_READ_pCAL -# define PNG_READ_pCAL_SUPPORTED -# define PNG_pCAL_SUPPORTED -#endif -#ifndef PNG_NO_READ_sCAL -# define PNG_READ_sCAL_SUPPORTED -# define PNG_sCAL_SUPPORTED -#endif -#ifndef PNG_NO_READ_pHYs -# define PNG_READ_pHYs_SUPPORTED -# define PNG_pHYs_SUPPORTED -#endif -#ifndef PNG_NO_READ_sBIT -# define PNG_READ_sBIT_SUPPORTED -# define PNG_sBIT_SUPPORTED -#endif -#ifndef PNG_NO_READ_sPLT -# define PNG_READ_sPLT_SUPPORTED -# define PNG_sPLT_SUPPORTED -#endif -#ifndef PNG_NO_READ_sRGB -# define PNG_READ_sRGB_SUPPORTED -# define PNG_sRGB_SUPPORTED -#endif -#ifndef PNG_NO_READ_tEXt -# define PNG_READ_tEXt_SUPPORTED -# define PNG_tEXt_SUPPORTED -#endif -#ifndef PNG_NO_READ_tIME -# define PNG_READ_tIME_SUPPORTED -# define PNG_tIME_SUPPORTED -#endif -#ifndef PNG_NO_READ_tRNS -# define PNG_READ_tRNS_SUPPORTED -# define PNG_tRNS_SUPPORTED -#endif -#ifndef PNG_NO_READ_zTXt -# define PNG_READ_zTXt_SUPPORTED -# define PNG_zTXt_SUPPORTED -#endif -#ifndef PNG_NO_READ_OPT_PLTE -# define PNG_READ_OPT_PLTE_SUPPORTED /* only affects support of the */ -#endif /* optional PLTE chunk in RGB and RGBA images */ -#if defined(PNG_READ_iTXt_SUPPORTED) || defined(PNG_READ_tEXt_SUPPORTED) || \ - defined(PNG_READ_zTXt_SUPPORTED) -# define PNG_READ_TEXT_SUPPORTED -# define PNG_TEXT_SUPPORTED -#endif - -#endif /* PNG_READ_ANCILLARY_CHUNKS_SUPPORTED */ - -#ifndef PNG_NO_READ_UNKNOWN_CHUNKS -# ifndef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED -# define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED -# endif -# ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED -# define PNG_UNKNOWN_CHUNKS_SUPPORTED -# endif -# ifndef PNG_READ_USER_CHUNKS_SUPPORTED -# define PNG_READ_USER_CHUNKS_SUPPORTED -# endif -#endif -#ifndef PNG_NO_READ_USER_CHUNKS -# ifndef PNG_READ_USER_CHUNKS_SUPPORTED -# define PNG_READ_USER_CHUNKS_SUPPORTED -# endif -# ifndef PNG_USER_CHUNKS_SUPPORTED -# define PNG_USER_CHUNKS_SUPPORTED -# endif -#endif -#ifndef PNG_NO_HANDLE_AS_UNKNOWN -# ifndef PNG_HANDLE_AS_UNKNOWN_SUPPORTED -# define PNG_HANDLE_AS_UNKNOWN_SUPPORTED -# endif -#endif - -#ifdef PNG_WRITE_SUPPORTED -#ifdef PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED - -#ifdef PNG_NO_WRITE_TEXT -# define PNG_NO_WRITE_iTXt -# define PNG_NO_WRITE_tEXt -# define PNG_NO_WRITE_zTXt -#endif -#ifndef PNG_NO_WRITE_bKGD -# define PNG_WRITE_bKGD_SUPPORTED -# ifndef PNG_bKGD_SUPPORTED -# define PNG_bKGD_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_cHRM -# define PNG_WRITE_cHRM_SUPPORTED -# ifndef PNG_cHRM_SUPPORTED -# define PNG_cHRM_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_gAMA -# define PNG_WRITE_gAMA_SUPPORTED -# ifndef PNG_gAMA_SUPPORTED -# define PNG_gAMA_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_hIST -# define PNG_WRITE_hIST_SUPPORTED -# ifndef PNG_hIST_SUPPORTED -# define PNG_hIST_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_iCCP -# define PNG_WRITE_iCCP_SUPPORTED -# ifndef PNG_iCCP_SUPPORTED -# define PNG_iCCP_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_iTXt -# ifndef PNG_WRITE_iTXt_SUPPORTED -# define PNG_WRITE_iTXt_SUPPORTED -# endif -# ifndef PNG_iTXt_SUPPORTED -# define PNG_iTXt_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_oFFs -# define PNG_WRITE_oFFs_SUPPORTED -# ifndef PNG_oFFs_SUPPORTED -# define PNG_oFFs_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_pCAL -# define PNG_WRITE_pCAL_SUPPORTED -# ifndef PNG_pCAL_SUPPORTED -# define PNG_pCAL_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_sCAL -# define PNG_WRITE_sCAL_SUPPORTED -# ifndef PNG_sCAL_SUPPORTED -# define PNG_sCAL_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_pHYs -# define PNG_WRITE_pHYs_SUPPORTED -# ifndef PNG_pHYs_SUPPORTED -# define PNG_pHYs_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_sBIT -# define PNG_WRITE_sBIT_SUPPORTED -# ifndef PNG_sBIT_SUPPORTED -# define PNG_sBIT_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_sPLT -# define PNG_WRITE_sPLT_SUPPORTED -# ifndef PNG_sPLT_SUPPORTED -# define PNG_sPLT_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_sRGB -# define PNG_WRITE_sRGB_SUPPORTED -# ifndef PNG_sRGB_SUPPORTED -# define PNG_sRGB_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_tEXt -# define PNG_WRITE_tEXt_SUPPORTED -# ifndef PNG_tEXt_SUPPORTED -# define PNG_tEXt_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_tIME -# define PNG_WRITE_tIME_SUPPORTED -# ifndef PNG_tIME_SUPPORTED -# define PNG_tIME_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_tRNS -# define PNG_WRITE_tRNS_SUPPORTED -# ifndef PNG_tRNS_SUPPORTED -# define PNG_tRNS_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_zTXt -# define PNG_WRITE_zTXt_SUPPORTED -# ifndef PNG_zTXt_SUPPORTED -# define PNG_zTXt_SUPPORTED -# endif -#endif -#if defined(PNG_WRITE_iTXt_SUPPORTED) || defined(PNG_WRITE_tEXt_SUPPORTED) || \ - defined(PNG_WRITE_zTXt_SUPPORTED) -# define PNG_WRITE_TEXT_SUPPORTED -# ifndef PNG_TEXT_SUPPORTED -# define PNG_TEXT_SUPPORTED -# endif -#endif - -#ifdef PNG_WRITE_tIME_SUPPORTED -# ifndef PNG_NO_CONVERT_tIME -# ifndef _WIN32_WCE -/* The "tm" structure is not supported on WindowsCE */ -# ifndef PNG_CONVERT_tIME_SUPPORTED -# define PNG_CONVERT_tIME_SUPPORTED -# endif -# endif -# endif -#endif - -#endif /* PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED */ - -#ifndef PNG_NO_WRITE_FILTER -# ifndef PNG_WRITE_FILTER_SUPPORTED -# define PNG_WRITE_FILTER_SUPPORTED -# endif -#endif - -#ifndef PNG_NO_WRITE_UNKNOWN_CHUNKS -# define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED -# ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED -# define PNG_UNKNOWN_CHUNKS_SUPPORTED -# endif -#endif -#ifndef PNG_NO_HANDLE_AS_UNKNOWN -# ifndef PNG_HANDLE_AS_UNKNOWN_SUPPORTED -# define PNG_HANDLE_AS_UNKNOWN_SUPPORTED -# endif -#endif -#endif /* PNG_WRITE_SUPPORTED */ - -/* Turn this off to disable png_read_png() and - * png_write_png() and leave the row_pointers member - * out of the info structure. - */ -#ifndef PNG_NO_INFO_IMAGE -# define PNG_INFO_IMAGE_SUPPORTED -#endif - -/* Need the time information for converting tIME chunks */ -#ifdef PNG_CONVERT_tIME_SUPPORTED - /* "time.h" functions are not supported on WindowsCE */ -# include -#endif - -/* Some typedefs to get us started. These should be safe on most of the - * common platforms. The typedefs should be at least as large as the - * numbers suggest (a png_uint_32 must be at least 32 bits long), but they - * don't have to be exactly that size. Some compilers dislike passing - * unsigned shorts as function parameters, so you may be better off using - * unsigned int for png_uint_16. - */ - -#if defined(INT_MAX) && (INT_MAX > 0x7ffffffeL) -typedef unsigned int png_uint_32; -typedef int png_int_32; -#else -typedef unsigned long png_uint_32; -typedef long png_int_32; -#endif -typedef unsigned short png_uint_16; -typedef short png_int_16; -typedef unsigned char png_byte; - -#ifdef PNG_NO_SIZE_T - typedef unsigned int png_size_t; -#else - typedef size_t png_size_t; -#endif -#define png_sizeof(x) sizeof(x) - -/* The following is needed for medium model support. It cannot be in the - * pngpriv.h header. Needs modification for other compilers besides - * MSC. Model independent support declares all arrays and pointers to be - * large using the far keyword. The zlib version used must also support - * model independent data. As of version zlib 1.0.4, the necessary changes - * have been made in zlib. The USE_FAR_KEYWORD define triggers other - * changes that are needed. (Tim Wegner) - */ - -/* Separate compiler dependencies (problem here is that zlib.h always - * defines FAR. (SJT) - */ -#ifdef __BORLANDC__ -# if defined(__LARGE__) || defined(__HUGE__) || defined(__COMPACT__) -# define LDATA 1 -# else -# define LDATA 0 -# endif - /* GRR: why is Cygwin in here? Cygwin is not Borland C... */ -# if !defined(__WIN32__) && !defined(__FLAT__) && !defined(__CYGWIN__) -# define PNG_MAX_MALLOC_64K -# if (LDATA != 1) -# ifndef FAR -# define FAR __far -# endif -# define USE_FAR_KEYWORD -# endif /* LDATA != 1 */ - /* Possibly useful for moving data out of default segment. - * Uncomment it if you want. Could also define FARDATA as - * const if your compiler supports it. (SJT) -# define FARDATA FAR - */ -# endif /* __WIN32__, __FLAT__, __CYGWIN__ */ -#endif /* __BORLANDC__ */ - - -/* Suggest testing for specific compiler first before testing for - * FAR. The Watcom compiler defines both __MEDIUM__ and M_I86MM, - * making reliance oncertain keywords suspect. (SJT) - */ - -/* MSC Medium model */ -#ifdef FAR -# ifdef M_I86MM -# define USE_FAR_KEYWORD -# define FARDATA FAR -# include -# endif -#endif - -/* SJT: default case */ -#ifndef FAR -# define FAR -#endif - -/* At this point FAR is always defined */ -#ifndef FARDATA -# define FARDATA -#endif - -/* Typedef for floating-point numbers that are converted - to fixed-point with a multiple of 100,000, e.g., int_gamma */ -typedef png_int_32 png_fixed_point; - -/* Add typedefs for pointers */ -typedef void FAR * png_voidp; -typedef png_byte FAR * png_bytep; -typedef png_uint_32 FAR * png_uint_32p; -typedef png_int_32 FAR * png_int_32p; -typedef png_uint_16 FAR * png_uint_16p; -typedef png_int_16 FAR * png_int_16p; -typedef PNG_CONST char FAR * png_const_charp; -typedef char FAR * png_charp; -typedef png_fixed_point FAR * png_fixed_point_p; - -#ifndef PNG_NO_STDIO -typedef FILE * png_FILE_p; -#endif - -#ifdef PNG_FLOATING_POINT_SUPPORTED -typedef double FAR * png_doublep; -#endif - -/* Pointers to pointers; i.e. arrays */ -typedef png_byte FAR * FAR * png_bytepp; -typedef png_uint_32 FAR * FAR * png_uint_32pp; -typedef png_int_32 FAR * FAR * png_int_32pp; -typedef png_uint_16 FAR * FAR * png_uint_16pp; -typedef png_int_16 FAR * FAR * png_int_16pp; -typedef PNG_CONST char FAR * FAR * png_const_charpp; -typedef char FAR * FAR * png_charpp; -typedef png_fixed_point FAR * FAR * png_fixed_point_pp; -#ifdef PNG_FLOATING_POINT_SUPPORTED -typedef double FAR * FAR * png_doublepp; -#endif - -/* Pointers to pointers to pointers; i.e., pointer to array */ -typedef char FAR * FAR * FAR * png_charppp; - -/* Define PNG_BUILD_DLL if the module being built is a Windows - * LIBPNG DLL. - * - * Define PNG_USE_DLL if you want to *link* to the Windows LIBPNG DLL. - * It is equivalent to Microsoft predefined macro _DLL that is - * automatically defined when you compile using the share - * version of the CRT (C Run-Time library) - * - * The cygwin mods make this behavior a little different: - * Define PNG_BUILD_DLL if you are building a dll for use with cygwin - * Define PNG_STATIC if you are building a static library for use with cygwin, - * -or- if you are building an application that you want to link to the - * static library. - * PNG_USE_DLL is defined by default (no user action needed) unless one of - * the other flags is defined. - */ - -#if !defined(PNG_DLL) && (defined(PNG_BUILD_DLL) || defined(PNG_USE_DLL)) -# define PNG_DLL -#endif - -#ifdef __CYGWIN__ -# undef PNGAPI -# define PNGAPI __cdecl -# undef PNG_IMPEXP -# define PNG_IMPEXP -#endif - -#define PNG_USE_LOCAL_ARRAYS /* Not used in libpng, defined for legacy apps */ - -/* If you define PNGAPI, e.g., with compiler option "-DPNGAPI=__stdcall", - * you may get warnings regarding the linkage of png_zalloc and png_zfree. - * Don't ignore those warnings; you must also reset the default calling - * convention in your compiler to match your PNGAPI, and you must build - * zlib and your applications the same way you build libpng. - */ - -#if defined(__MINGW32__) && !defined(PNG_MODULEDEF) -# ifndef PNG_NO_MODULEDEF -# define PNG_NO_MODULEDEF -# endif -#endif - -#if !defined(PNG_IMPEXP) && defined(PNG_BUILD_DLL) && !defined(PNG_NO_MODULEDEF) -# define PNG_IMPEXP -#endif - -#if defined(PNG_DLL) || defined(_DLL) || defined(__DLL__ ) || \ - (( defined(_Windows) || defined(_WINDOWS) || \ - defined(WIN32) || defined(_WIN32) || defined(__WIN32__) )) - -# ifndef PNGAPI -# if defined(__GNUC__) || (defined (_MSC_VER) && (_MSC_VER >= 800)) -# define PNGAPI __cdecl -# else -# define PNGAPI _cdecl -# endif -# endif - -# if !defined(PNG_IMPEXP) && (!defined(PNG_DLL) || \ - 0 /* WINCOMPILER_WITH_NO_SUPPORT_FOR_DECLIMPEXP */) -# define PNG_IMPEXP -# endif - -# ifndef PNG_IMPEXP - -# define PNG_EXPORT_TYPE1(type,symbol) PNG_IMPEXP type PNGAPI symbol -# define PNG_EXPORT_TYPE2(type,symbol) type PNG_IMPEXP PNGAPI symbol - - /* Borland/Microsoft */ -# if defined(_MSC_VER) || defined(__BORLANDC__) -# if (_MSC_VER >= 800) || (__BORLANDC__ >= 0x500) -# define PNG_EXPORT PNG_EXPORT_TYPE1 -# else -# define PNG_EXPORT PNG_EXPORT_TYPE2 -# ifdef PNG_BUILD_DLL -# define PNG_IMPEXP __export -# else -# define PNG_IMPEXP /*__import */ /* doesn't exist AFAIK in VC++ */ -# endif /* Exists in Borland C++ for - C++ classes (== huge) */ -# endif -# endif - -# ifndef PNG_IMPEXP -# ifdef PNG_BUILD_DLL -# define PNG_IMPEXP __declspec(dllexport) -# else -# define PNG_IMPEXP __declspec(dllimport) -# endif -# endif -# endif /* PNG_IMPEXP */ -#else /* !(DLL || non-cygwin WINDOWS) */ -# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__) -# ifndef PNGAPI -# define PNGAPI _System -# endif -# else -# if 0 /* ... other platforms, with other meanings */ -# endif -# endif -#endif - -#ifndef PNGAPI -# define PNGAPI -#endif -#ifndef PNG_IMPEXP -# define PNG_IMPEXP -#endif - -#ifdef PNG_BUILDSYMS -# ifndef PNG_EXPORT -# define PNG_EXPORT(type,symbol) PNG_FUNCTION_EXPORT symbol END -# endif -#endif - -#ifndef PNG_EXPORT -# define PNG_EXPORT(type,symbol) PNG_IMPEXP type PNGAPI symbol -#endif - -/* Support for compiler specific function attributes. These are used - * so that where compiler support is available incorrect use of API - * functions in png.h will generate compiler warnings. - * - * Added at libpng-1.2.41. - */ - -#ifndef PNG_NO_PEDANTIC_WARNINGS -# ifndef PNG_PEDANTIC_WARNINGS_SUPPORTED -# define PNG_PEDANTIC_WARNINGS_SUPPORTED -# endif -#endif - -#ifdef PNG_PEDANTIC_WARNINGS_SUPPORTED -/* Support for compiler specific function attributes. These are used - * so that where compiler support is available incorrect use of API - * functions in png.h will generate compiler warnings. Added at libpng - * version 1.2.41. - */ -# ifdef __GNUC__ -# ifndef PNG_USE_RESULT -# define PNG_USE_RESULT __attribute__((__warn_unused_result__)) -# endif -# ifndef PNG_NORETURN -# define PNG_NORETURN __attribute__((__noreturn__)) -# endif -# ifndef PNG_ALLOCATED -# define PNG_ALLOCATED __attribute__((__malloc__)) -# endif - - /* This specifically protects structure members that should only be - * accessed from within the library, therefore should be empty during - * a library build. - */ -# ifndef PNG_DEPRECATED -# define PNG_DEPRECATED __attribute__((__deprecated__)) -# endif -# ifndef PNG_DEPSTRUCT -# define PNG_DEPSTRUCT __attribute__((__deprecated__)) -# endif -# ifndef PNG_PRIVATE -# if 0 /* Doesn't work so we use deprecated instead*/ -# define PNG_PRIVATE \ - __attribute__((warning("This function is not exported by libpng."))) -# else -# define PNG_PRIVATE \ - __attribute__((__deprecated__)) -# endif -# endif /* PNG_PRIVATE */ -# endif /* __GNUC__ */ -#endif /* PNG_PEDANTIC_WARNINGS */ - -#ifndef PNG_DEPRECATED -# define PNG_DEPRECATED /* Use of this function is deprecated */ -#endif -#ifndef PNG_USE_RESULT -# define PNG_USE_RESULT /* The result of this function must be checked */ -#endif -#ifndef PNG_NORETURN -# define PNG_NORETURN /* This function does not return */ -#endif -#ifndef PNG_ALLOCATED -# define PNG_ALLOCATED /* The result of the function is new memory */ -#endif -#ifndef PNG_DEPSTRUCT -# define PNG_DEPSTRUCT /* Access to this struct member is deprecated */ -#endif -#ifndef PNG_PRIVATE -# define PNG_PRIVATE /* This is a private libpng function */ -#endif - -/* Users may want to use these so they are not private. Any library - * functions that are passed far data must be model-independent. - */ - -/* memory model/platform independent fns */ -#ifndef PNG_ABORT -# ifdef _WINDOWS_ -# define PNG_ABORT() ExitProcess(0) -# else -# define PNG_ABORT() abort() -# endif -#endif - -#ifdef USE_FAR_KEYWORD -/* Use this to make far-to-near assignments */ -# define CHECK 1 -# define NOCHECK 0 -# define CVT_PTR(ptr) (png_far_to_near(png_ptr,ptr,CHECK)) -# define CVT_PTR_NOCHECK(ptr) (png_far_to_near(png_ptr,ptr,NOCHECK)) -# define png_strcpy _fstrcpy -# define png_strncpy _fstrncpy /* Added to v 1.2.6 */ -# define png_strlen _fstrlen -# define png_memcmp _fmemcmp /* SJT: added */ -# define png_memcpy _fmemcpy -# define png_memset _fmemset -# define png_sprintf sprintf -#else -# ifdef _WINDOWS_ /* Favor Windows over C runtime fns */ -# define CVT_PTR(ptr) (ptr) -# define CVT_PTR_NOCHECK(ptr) (ptr) -# define png_strcpy lstrcpyA -# define png_strncpy lstrcpynA -# define png_strlen lstrlenA -# define png_memcmp memcmp -# define png_memcpy CopyMemory -# define png_memset memset -# define png_sprintf wsprintfA -# else -# define CVT_PTR(ptr) (ptr) -# define CVT_PTR_NOCHECK(ptr) (ptr) -# define png_strcpy strcpy -# define png_strncpy strncpy /* Added to v 1.2.6 */ -# define png_strlen strlen -# define png_memcmp memcmp /* SJT: added */ -# define png_memcpy memcpy -# define png_memset memset -# define png_sprintf sprintf -# ifndef PNG_NO_SNPRINTF -# ifdef _MSC_VER -# define png_snprintf _snprintf /* Added to v 1.2.19 */ -# define png_snprintf2 _snprintf -# define png_snprintf6 _snprintf -# else -# define png_snprintf snprintf /* Added to v 1.2.19 */ -# define png_snprintf2 snprintf -# define png_snprintf6 snprintf -# endif -# else - /* You don't have or don't want to use snprintf(). Caution: Using - * sprintf instead of snprintf exposes your application to accidental - * or malevolent buffer overflows. If you don't have snprintf() - * as a general rule you should provide one (you can get one from - * Portable OpenSSH). - */ -# define png_snprintf(s1,n,fmt,x1) sprintf(s1,fmt,x1) -# define png_snprintf2(s1,n,fmt,x1,x2) sprintf(s1,fmt,x1,x2) -# define png_snprintf6(s1,n,fmt,x1,x2,x3,x4,x5,x6) \ - sprintf(s1,fmt,x1,x2,x3,x4,x5,x6) -# endif -# endif -#endif - -/* png_alloc_size_t is guaranteed to be no smaller than png_size_t, - * and no smaller than png_uint_32. Casts from png_size_t or png_uint_32 - * to png_alloc_size_t are not necessary; in fact, it is recommended - * not to use them at all so that the compiler can complain when something - * turns out to be problematic. - * Casts in the other direction (from png_alloc_size_t to png_size_t or - * png_uint_32) should be explicitly applied; however, we do not expect - * to encounter practical situations that require such conversions. - */ -#if defined(__TURBOC__) && !defined(__FLAT__) -# define png_mem_alloc farmalloc -# define png_mem_free farfree - typedef unsigned long png_alloc_size_t; -#else -# if defined(_MSC_VER) && defined(MAXSEG_64K) -# define png_mem_alloc(s) halloc(s, 1) -# define png_mem_free hfree - typedef unsigned long png_alloc_size_t; -# else -# if defined(_WINDOWS_) && (!defined(INT_MAX) || INT_MAX <= 0x7ffffffeL) -# define png_mem_alloc(s) HeapAlloc(GetProcessHeap(), 0, s) -# define png_mem_free(p) HeapFree(GetProcessHeap(), 0, p) - typedef DWORD png_alloc_size_t; -# else -# define png_mem_alloc malloc -# define png_mem_free free - typedef png_size_t png_alloc_size_t; -# endif -# endif -#endif -/* End of memory model/platform independent support */ - -/* Just a little check that someone hasn't tried to define something - * contradictory. - */ -#if (PNG_ZBUF_SIZE > 65536L) && defined(PNG_MAX_MALLOC_64K) -# undef PNG_ZBUF_SIZE -# define PNG_ZBUF_SIZE 65536L -#endif - - -/* Added at libpng-1.2.8 */ -#endif /* PNG_VERSION_INFO_ONLY */ - -#endif /* PNGCONF_H */ diff --git a/reactos/dll/3rdparty/libpng/pngpriv.h b/reactos/dll/3rdparty/libpng/pngpriv.h deleted file mode 100644 index 19b797c7447..00000000000 --- a/reactos/dll/3rdparty/libpng/pngpriv.h +++ /dev/null @@ -1,956 +0,0 @@ - -/* pngpriv.h - private declarations for use inside libpng - * - * libpng version 1.4.3 - June 26, 2010 - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2010 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This code is released under the libpng license. - * For conditions of distribution and use, see the disclaimer - * and license in png.h - */ - -/* The symbols declared in this file (including the functions declared - * as PNG_EXTERN) are PRIVATE. They are not part of the libpng public - * interface, and are not recommended for use by regular applications. - * Some of them may become public in the future; others may stay private, - * change in an incompatible way, or even disappear. - * Although the libpng users are not forbidden to include this header, - * they should be well aware of the issues that may arise from doing so. - */ - -#ifndef PNGPRIV_H -#define PNGPRIV_H - -#ifndef PNG_VERSION_INFO_ONLY - -#include - -/* The functions exported by PNG_EXTERN are internal functions, which - * aren't usually used outside the library (as far as I know), so it is - * debatable if they should be exported at all. In the future, when it - * is possible to have run-time registry of chunk-handling functions, - * some of these will be made available again. -#define PNG_EXTERN extern - */ -#define PNG_EXTERN - -/* Other defines specific to compilers can go here. Try to keep - * them inside an appropriate ifdef/endif pair for portability. - */ - -#ifdef PNG_FLOATING_POINT_SUPPORTED -# ifdef MACOS - /* We need to check that hasn't already been included earlier - * as it seems it doesn't agree with , yet we should really use - * if possible. - */ -# if !defined(__MATH_H__) && !defined(__MATH_H) && !defined(__cmath__) -# include -# endif -# else -# include -# endif -# if defined(_AMIGA) && defined(__SASC) && defined(_M68881) - /* Amiga SAS/C: We must include builtin FPU functions when compiling using - * MATH=68881 - */ -# include -# endif -#endif - -/* Codewarrior on NT has linking problems without this. */ -#if (defined(__MWERKS__) && defined(WIN32)) || defined(__STDC__) -# define PNG_ALWAYS_EXTERN -#endif - -/* This provides the non-ANSI (far) memory allocation routines. */ -#if defined(__TURBOC__) && defined(__MSDOS__) -# include -# include -#endif - -#if defined(WIN32) || defined(_Windows) || defined(_WINDOWS) || \ - defined(_WIN32) || defined(__WIN32__) -# include /* defines _WINDOWS_ macro */ -/* I have no idea why is this necessary... */ -# ifdef _MSC_VER -# include -# endif -#endif - -/* Various modes of operation. Note that after an init, mode is set to - * zero automatically when the structure is created. - */ -#define PNG_HAVE_IHDR 0x01 -#define PNG_HAVE_PLTE 0x02 -#define PNG_HAVE_IDAT 0x04 -#define PNG_AFTER_IDAT 0x08 /* Have complete zlib datastream */ -#define PNG_HAVE_IEND 0x10 -#define PNG_HAVE_gAMA 0x20 -#define PNG_HAVE_cHRM 0x40 -#define PNG_HAVE_sRGB 0x80 -#define PNG_HAVE_CHUNK_HEADER 0x100 -#define PNG_WROTE_tIME 0x200 -#define PNG_WROTE_INFO_BEFORE_PLTE 0x400 -#define PNG_BACKGROUND_IS_GRAY 0x800 -#define PNG_HAVE_PNG_SIGNATURE 0x1000 -#define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000 /* Have another chunk after IDAT */ - -/* Flags for the transformations the PNG library does on the image data */ -#define PNG_BGR 0x0001 -#define PNG_INTERLACE 0x0002 -#define PNG_PACK 0x0004 -#define PNG_SHIFT 0x0008 -#define PNG_SWAP_BYTES 0x0010 -#define PNG_INVERT_MONO 0x0020 -#define PNG_QUANTIZE 0x0040 /* formerly PNG_DITHER */ -#define PNG_BACKGROUND 0x0080 -#define PNG_BACKGROUND_EXPAND 0x0100 - /* 0x0200 unused */ -#define PNG_16_TO_8 0x0400 -#define PNG_RGBA 0x0800 -#define PNG_EXPAND 0x1000 -#define PNG_GAMMA 0x2000 -#define PNG_GRAY_TO_RGB 0x4000 -#define PNG_FILLER 0x8000L -#define PNG_PACKSWAP 0x10000L -#define PNG_SWAP_ALPHA 0x20000L -#define PNG_STRIP_ALPHA 0x40000L -#define PNG_INVERT_ALPHA 0x80000L -#define PNG_USER_TRANSFORM 0x100000L -#define PNG_RGB_TO_GRAY_ERR 0x200000L -#define PNG_RGB_TO_GRAY_WARN 0x400000L -#define PNG_RGB_TO_GRAY 0x600000L /* two bits, RGB_TO_GRAY_ERR|WARN */ - /* 0x800000L Unused */ -#define PNG_ADD_ALPHA 0x1000000L /* Added to libpng-1.2.7 */ -#define PNG_EXPAND_tRNS 0x2000000L /* Added to libpng-1.2.9 */ - /* 0x4000000L unused */ - /* 0x8000000L unused */ - /* 0x10000000L unused */ - /* 0x20000000L unused */ - /* 0x40000000L unused */ - -/* Flags for png_create_struct */ -#define PNG_STRUCT_PNG 0x0001 -#define PNG_STRUCT_INFO 0x0002 - -/* Scaling factor for filter heuristic weighting calculations */ -#define PNG_WEIGHT_SHIFT 8 -#define PNG_WEIGHT_FACTOR (1<<(PNG_WEIGHT_SHIFT)) -#define PNG_COST_SHIFT 3 -#define PNG_COST_FACTOR (1<<(PNG_COST_SHIFT)) - -/* Flags for the png_ptr->flags rather than declaring a byte for each one */ -#define PNG_FLAG_ZLIB_CUSTOM_STRATEGY 0x0001 -#define PNG_FLAG_ZLIB_CUSTOM_LEVEL 0x0002 -#define PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL 0x0004 -#define PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS 0x0008 -#define PNG_FLAG_ZLIB_CUSTOM_METHOD 0x0010 -#define PNG_FLAG_ZLIB_FINISHED 0x0020 -#define PNG_FLAG_ROW_INIT 0x0040 -#define PNG_FLAG_FILLER_AFTER 0x0080 -#define PNG_FLAG_CRC_ANCILLARY_USE 0x0100 -#define PNG_FLAG_CRC_ANCILLARY_NOWARN 0x0200 -#define PNG_FLAG_CRC_CRITICAL_USE 0x0400 -#define PNG_FLAG_CRC_CRITICAL_IGNORE 0x0800 - /* 0x1000 unused */ - /* 0x2000 unused */ - /* 0x4000 unused */ -#define PNG_FLAG_KEEP_UNKNOWN_CHUNKS 0x8000L -#define PNG_FLAG_KEEP_UNSAFE_CHUNKS 0x10000L -#define PNG_FLAG_LIBRARY_MISMATCH 0x20000L -#define PNG_FLAG_STRIP_ERROR_NUMBERS 0x40000L -#define PNG_FLAG_STRIP_ERROR_TEXT 0x80000L -#define PNG_FLAG_MALLOC_NULL_MEM_OK 0x100000L -#define PNG_FLAG_ADD_ALPHA 0x200000L /* Added to libpng-1.2.8 */ -#define PNG_FLAG_STRIP_ALPHA 0x400000L /* Added to libpng-1.2.8 */ -#define PNG_FLAG_BENIGN_ERRORS_WARN 0x800000L /* Added to libpng-1.4.0 */ - /* 0x1000000L unused */ - /* 0x2000000L unused */ - /* 0x4000000L unused */ - /* 0x8000000L unused */ - /* 0x10000000L unused */ - /* 0x20000000L unused */ - /* 0x40000000L unused */ - -#define PNG_FLAG_CRC_ANCILLARY_MASK (PNG_FLAG_CRC_ANCILLARY_USE | \ - PNG_FLAG_CRC_ANCILLARY_NOWARN) - -#define PNG_FLAG_CRC_CRITICAL_MASK (PNG_FLAG_CRC_CRITICAL_USE | \ - PNG_FLAG_CRC_CRITICAL_IGNORE) - -#define PNG_FLAG_CRC_MASK (PNG_FLAG_CRC_ANCILLARY_MASK | \ - PNG_FLAG_CRC_CRITICAL_MASK) - -/* Save typing and make code easier to understand */ - -#define PNG_COLOR_DIST(c1, c2) (abs((int)((c1).red) - (int)((c2).red)) + \ - abs((int)((c1).green) - (int)((c2).green)) + \ - abs((int)((c1).blue) - (int)((c2).blue))) - -/* Added to libpng-1.2.6 JB */ -#define PNG_ROWBYTES(pixel_bits, width) \ - ((pixel_bits) >= 8 ? \ - ((png_size_t)(width) * (((png_size_t)(pixel_bits)) >> 3)) : \ - (( ((png_size_t)(width) * ((png_size_t)(pixel_bits))) + 7) >> 3) ) - -/* PNG_OUT_OF_RANGE returns true if value is outside the range - * ideal-delta..ideal+delta. Each argument is evaluated twice. - * "ideal" and "delta" should be constants, normally simple - * integers, "value" a variable. Added to libpng-1.2.6 JB - */ -#define PNG_OUT_OF_RANGE(value, ideal, delta) \ - ( (value) < (ideal)-(delta) || (value) > (ideal)+(delta) ) - -/* Constant strings for known chunk types. If you need to add a chunk, - * define the name here, and add an invocation of the macro wherever it's - * needed. - */ -#define PNG_IHDR PNG_CONST png_byte png_IHDR[5] = { 73, 72, 68, 82, '\0'} -#define PNG_IDAT PNG_CONST png_byte png_IDAT[5] = { 73, 68, 65, 84, '\0'} -#define PNG_IEND PNG_CONST png_byte png_IEND[5] = { 73, 69, 78, 68, '\0'} -#define PNG_PLTE PNG_CONST png_byte png_PLTE[5] = { 80, 76, 84, 69, '\0'} -#define PNG_bKGD PNG_CONST png_byte png_bKGD[5] = { 98, 75, 71, 68, '\0'} -#define PNG_cHRM PNG_CONST png_byte png_cHRM[5] = { 99, 72, 82, 77, '\0'} -#define PNG_gAMA PNG_CONST png_byte png_gAMA[5] = {103, 65, 77, 65, '\0'} -#define PNG_hIST PNG_CONST png_byte png_hIST[5] = {104, 73, 83, 84, '\0'} -#define PNG_iCCP PNG_CONST png_byte png_iCCP[5] = {105, 67, 67, 80, '\0'} -#define PNG_iTXt PNG_CONST png_byte png_iTXt[5] = {105, 84, 88, 116, '\0'} -#define PNG_oFFs PNG_CONST png_byte png_oFFs[5] = {111, 70, 70, 115, '\0'} -#define PNG_pCAL PNG_CONST png_byte png_pCAL[5] = {112, 67, 65, 76, '\0'} -#define PNG_sCAL PNG_CONST png_byte png_sCAL[5] = {115, 67, 65, 76, '\0'} -#define PNG_pHYs PNG_CONST png_byte png_pHYs[5] = {112, 72, 89, 115, '\0'} -#define PNG_sBIT PNG_CONST png_byte png_sBIT[5] = {115, 66, 73, 84, '\0'} -#define PNG_sPLT PNG_CONST png_byte png_sPLT[5] = {115, 80, 76, 84, '\0'} -#define PNG_sRGB PNG_CONST png_byte png_sRGB[5] = {115, 82, 71, 66, '\0'} -#define PNG_sTER PNG_CONST png_byte png_sTER[5] = {115, 84, 69, 82, '\0'} -#define PNG_tEXt PNG_CONST png_byte png_tEXt[5] = {116, 69, 88, 116, '\0'} -#define PNG_tIME PNG_CONST png_byte png_tIME[5] = {116, 73, 77, 69, '\0'} -#define PNG_tRNS PNG_CONST png_byte png_tRNS[5] = {116, 82, 78, 83, '\0'} -#define PNG_zTXt PNG_CONST png_byte png_zTXt[5] = {122, 84, 88, 116, '\0'} - - -/* Inhibit C++ name-mangling for libpng functions but not for system calls. */ -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -/* These functions are used internally in the code. They generally - * shouldn't be used unless you are writing code to add or replace some - * functionality in libpng. More information about most functions can - * be found in the files where the functions are located. - */ - -/* Allocate memory for an internal libpng struct */ -PNG_EXTERN png_voidp png_create_struct PNGARG((int type)); - -/* Free memory from internal libpng struct */ -PNG_EXTERN void png_destroy_struct PNGARG((png_voidp struct_ptr)); - -PNG_EXTERN png_voidp png_create_struct_2 PNGARG((int type, png_malloc_ptr - malloc_fn, png_voidp mem_ptr)); -PNG_EXTERN void png_destroy_struct_2 PNGARG((png_voidp struct_ptr, - png_free_ptr free_fn, png_voidp mem_ptr)); - -/* Free any memory that info_ptr points to and reset struct. */ -PNG_EXTERN void png_info_destroy PNGARG((png_structp png_ptr, - png_infop info_ptr)); - -/* Function to allocate memory for zlib. PNGAPI is disallowed. */ -PNG_EXTERN voidpf png_zalloc PNGARG((voidpf png_ptr, uInt items, uInt size)); - -/* Function to free memory for zlib. PNGAPI is disallowed. */ -PNG_EXTERN void png_zfree PNGARG((voidpf png_ptr, voidpf ptr)); - -/* Next four functions are used internally as callbacks. PNGAPI is required - * but not PNG_EXPORT. PNGAPI added at libpng version 1.2.3. */ - -PNG_EXTERN void PNGAPI png_default_read_data PNGARG((png_structp png_ptr, - png_bytep data, png_size_t length)); - -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED -PNG_EXTERN void PNGAPI png_push_fill_buffer PNGARG((png_structp png_ptr, - png_bytep buffer, png_size_t length)); -#endif - -PNG_EXTERN void PNGAPI png_default_write_data PNGARG((png_structp png_ptr, - png_bytep data, png_size_t length)); - -#ifdef PNG_WRITE_FLUSH_SUPPORTED -#ifdef PNG_STDIO_SUPPORTED -PNG_EXTERN void PNGAPI png_default_flush PNGARG((png_structp png_ptr)); -#endif -#endif - -/* Reset the CRC variable */ -PNG_EXTERN void png_reset_crc PNGARG((png_structp png_ptr)); - -/* Write the "data" buffer to whatever output you are using */ -PNG_EXTERN void png_write_data PNGARG((png_structp png_ptr, png_bytep data, - png_size_t length)); - -/* Read the chunk header (length + type name) */ -PNG_EXTERN png_uint_32 png_read_chunk_header PNGARG((png_structp png_ptr)); - -/* Read data from whatever input you are using into the "data" buffer */ -PNG_EXTERN void png_read_data PNGARG((png_structp png_ptr, png_bytep data, - png_size_t length)); - -/* Read bytes into buf, and update png_ptr->crc */ -PNG_EXTERN void png_crc_read PNGARG((png_structp png_ptr, png_bytep buf, - png_size_t length)); - -/* Decompress data in a chunk that uses compression */ -#if defined(PNG_zTXt_SUPPORTED) || defined(PNG_iTXt_SUPPORTED) || \ - defined(PNG_iCCP_SUPPORTED) || defined(PNG_sPLT_SUPPORTED) -PNG_EXTERN void png_decompress_chunk PNGARG((png_structp png_ptr, - int comp_type, png_size_t chunklength, png_size_t prefix_length, - png_size_t *data_length)); -#endif - -/* Read "skip" bytes, read the file crc, and (optionally) verify png_ptr->crc */ -PNG_EXTERN int png_crc_finish PNGARG((png_structp png_ptr, png_uint_32 skip)); - -/* Read the CRC from the file and compare it to the libpng calculated CRC */ -PNG_EXTERN int png_crc_error PNGARG((png_structp png_ptr)); - -/* Calculate the CRC over a section of data. Note that we are only - * passing a maximum of 64K on systems that have this as a memory limit, - * since this is the maximum buffer size we can specify. - */ -PNG_EXTERN void png_calculate_crc PNGARG((png_structp png_ptr, png_bytep ptr, - png_size_t length)); - -#ifdef PNG_WRITE_FLUSH_SUPPORTED -PNG_EXTERN void png_flush PNGARG((png_structp png_ptr)); -#endif - -/* Write various chunks */ - -/* Write the IHDR chunk, and update the png_struct with the necessary - * information. - */ -PNG_EXTERN void png_write_IHDR PNGARG((png_structp png_ptr, png_uint_32 width, - png_uint_32 height, - int bit_depth, int color_type, int compression_method, int filter_method, - int interlace_method)); - -PNG_EXTERN void png_write_PLTE PNGARG((png_structp png_ptr, png_colorp palette, - png_uint_32 num_pal)); - -PNG_EXTERN void png_write_IDAT PNGARG((png_structp png_ptr, png_bytep data, - png_size_t length)); - -PNG_EXTERN void png_write_IEND PNGARG((png_structp png_ptr)); - -#ifdef PNG_WRITE_gAMA_SUPPORTED -#ifdef PNG_FLOATING_POINT_SUPPORTED -PNG_EXTERN void png_write_gAMA PNGARG((png_structp png_ptr, double file_gamma)); -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED -PNG_EXTERN void png_write_gAMA_fixed PNGARG((png_structp png_ptr, - png_fixed_point file_gamma)); -#endif -#endif - -#ifdef PNG_WRITE_sBIT_SUPPORTED -PNG_EXTERN void png_write_sBIT PNGARG((png_structp png_ptr, png_color_8p sbit, - int color_type)); -#endif - -#ifdef PNG_WRITE_cHRM_SUPPORTED -#ifdef PNG_FLOATING_POINT_SUPPORTED -PNG_EXTERN void png_write_cHRM PNGARG((png_structp png_ptr, - double white_x, double white_y, - double red_x, double red_y, double green_x, double green_y, - double blue_x, double blue_y)); -#endif -PNG_EXTERN void png_write_cHRM_fixed PNGARG((png_structp png_ptr, - png_fixed_point int_white_x, png_fixed_point int_white_y, - png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point - int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x, - png_fixed_point int_blue_y)); -#endif - -#ifdef PNG_WRITE_sRGB_SUPPORTED -PNG_EXTERN void png_write_sRGB PNGARG((png_structp png_ptr, - int intent)); -#endif - -#ifdef PNG_WRITE_iCCP_SUPPORTED -PNG_EXTERN void png_write_iCCP PNGARG((png_structp png_ptr, - png_charp name, int compression_type, - png_charp profile, int proflen)); - /* Note to maintainer: profile should be png_bytep */ -#endif - -#ifdef PNG_WRITE_sPLT_SUPPORTED -PNG_EXTERN void png_write_sPLT PNGARG((png_structp png_ptr, - png_sPLT_tp palette)); -#endif - -#ifdef PNG_WRITE_tRNS_SUPPORTED -PNG_EXTERN void png_write_tRNS PNGARG((png_structp png_ptr, png_bytep trans, - png_color_16p values, int number, int color_type)); -#endif - -#ifdef PNG_WRITE_bKGD_SUPPORTED -PNG_EXTERN void png_write_bKGD PNGARG((png_structp png_ptr, - png_color_16p values, int color_type)); -#endif - -#ifdef PNG_WRITE_hIST_SUPPORTED -PNG_EXTERN void png_write_hIST PNGARG((png_structp png_ptr, png_uint_16p hist, - int num_hist)); -#endif - -#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \ - defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) -PNG_EXTERN png_size_t png_check_keyword PNGARG((png_structp png_ptr, - png_charp key, png_charpp new_key)); -#endif - -#ifdef PNG_WRITE_tEXt_SUPPORTED -PNG_EXTERN void png_write_tEXt PNGARG((png_structp png_ptr, png_charp key, - png_charp text, png_size_t text_len)); -#endif - -#ifdef PNG_WRITE_zTXt_SUPPORTED -PNG_EXTERN void png_write_zTXt PNGARG((png_structp png_ptr, png_charp key, - png_charp text, png_size_t text_len, int compression)); -#endif - -#ifdef PNG_WRITE_iTXt_SUPPORTED -PNG_EXTERN void png_write_iTXt PNGARG((png_structp png_ptr, - int compression, png_charp key, png_charp lang, png_charp lang_key, - png_charp text)); -#endif - -#ifdef PNG_TEXT_SUPPORTED /* Added at version 1.0.14 and 1.2.4 */ -PNG_EXTERN int png_set_text_2 PNGARG((png_structp png_ptr, - png_infop info_ptr, png_textp text_ptr, int num_text)); -#endif - -#ifdef PNG_WRITE_oFFs_SUPPORTED -PNG_EXTERN void png_write_oFFs PNGARG((png_structp png_ptr, - png_int_32 x_offset, png_int_32 y_offset, int unit_type)); -#endif - -#ifdef PNG_WRITE_pCAL_SUPPORTED -PNG_EXTERN void png_write_pCAL PNGARG((png_structp png_ptr, png_charp purpose, - png_int_32 X0, png_int_32 X1, int type, int nparams, - png_charp units, png_charpp params)); -#endif - -#ifdef PNG_WRITE_pHYs_SUPPORTED -PNG_EXTERN void png_write_pHYs PNGARG((png_structp png_ptr, - png_uint_32 x_pixels_per_unit, png_uint_32 y_pixels_per_unit, - int unit_type)); -#endif - -#ifdef PNG_WRITE_tIME_SUPPORTED -PNG_EXTERN void png_write_tIME PNGARG((png_structp png_ptr, - png_timep mod_time)); -#endif - -#ifdef PNG_WRITE_sCAL_SUPPORTED -#if defined(PNG_FLOATING_POINT_SUPPORTED) && defined(PNG_STDIO_SUPPORTED) -PNG_EXTERN void png_write_sCAL PNGARG((png_structp png_ptr, - int unit, double width, double height)); -#else -#ifdef PNG_FIXED_POINT_SUPPORTED -PNG_EXTERN void png_write_sCAL_s PNGARG((png_structp png_ptr, - int unit, png_charp width, png_charp height)); -#endif -#endif -#endif - -/* Called when finished processing a row of data */ -PNG_EXTERN void png_write_finish_row PNGARG((png_structp png_ptr)); - -/* Internal use only. Called before first row of data */ -PNG_EXTERN void png_write_start_row PNGARG((png_structp png_ptr)); - -#ifdef PNG_READ_GAMMA_SUPPORTED -PNG_EXTERN void png_build_gamma_table PNGARG((png_structp png_ptr, - png_byte bit_depth)); -#endif - -/* Combine a row of data, dealing with alpha, etc. if requested */ -PNG_EXTERN void png_combine_row PNGARG((png_structp png_ptr, png_bytep row, - int mask)); - -#ifdef PNG_READ_INTERLACING_SUPPORTED -/* Expand an interlaced row */ -/* OLD pre-1.0.9 interface: -PNG_EXTERN void png_do_read_interlace PNGARG((png_row_infop row_info, - png_bytep row, int pass, png_uint_32 transformations)); - */ -PNG_EXTERN void png_do_read_interlace PNGARG((png_structp png_ptr)); -#endif - -/* GRR TO DO (2.0 or whenever): simplify other internal calling interfaces */ - -#ifdef PNG_WRITE_INTERLACING_SUPPORTED -/* Grab pixels out of a row for an interlaced pass */ -PNG_EXTERN void png_do_write_interlace PNGARG((png_row_infop row_info, - png_bytep row, int pass)); -#endif - -/* Unfilter a row */ -PNG_EXTERN void png_read_filter_row PNGARG((png_structp png_ptr, - png_row_infop row_info, png_bytep row, png_bytep prev_row, int filter)); - -/* Choose the best filter to use and filter the row data */ -PNG_EXTERN void png_write_find_filter PNGARG((png_structp png_ptr, - png_row_infop row_info)); - -/* Write out the filtered row. */ -PNG_EXTERN void png_write_filtered_row PNGARG((png_structp png_ptr, - png_bytep filtered_row)); -/* Finish a row while reading, dealing with interlacing passes, etc. */ -PNG_EXTERN void png_read_finish_row PNGARG((png_structp png_ptr)); - -/* Initialize the row buffers, etc. */ -PNG_EXTERN void png_read_start_row PNGARG((png_structp png_ptr)); -/* Optional call to update the users info structure */ -PNG_EXTERN void png_read_transform_info PNGARG((png_structp png_ptr, - png_infop info_ptr)); - -/* These are the functions that do the transformations */ -#ifdef PNG_READ_FILLER_SUPPORTED -PNG_EXTERN void png_do_read_filler PNGARG((png_row_infop row_info, - png_bytep row, png_uint_32 filler, png_uint_32 flags)); -#endif - -#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED -PNG_EXTERN void png_do_read_swap_alpha PNGARG((png_row_infop row_info, - png_bytep row)); -#endif - -#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED -PNG_EXTERN void png_do_write_swap_alpha PNGARG((png_row_infop row_info, - png_bytep row)); -#endif - -#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED -PNG_EXTERN void png_do_read_invert_alpha PNGARG((png_row_infop row_info, - png_bytep row)); -#endif - -#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED -PNG_EXTERN void png_do_write_invert_alpha PNGARG((png_row_infop row_info, - png_bytep row)); -#endif - -#if defined(PNG_WRITE_FILLER_SUPPORTED) || \ - defined(PNG_READ_STRIP_ALPHA_SUPPORTED) -PNG_EXTERN void png_do_strip_filler PNGARG((png_row_infop row_info, - png_bytep row, png_uint_32 flags)); -#endif - -#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) -PNG_EXTERN void png_do_swap PNGARG((png_row_infop row_info, png_bytep row)); -#endif - -#if defined(PNG_READ_PACKSWAP_SUPPORTED) || \ - defined(PNG_WRITE_PACKSWAP_SUPPORTED) -PNG_EXTERN void png_do_packswap PNGARG((png_row_infop row_info, png_bytep row)); -#endif - -#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED -PNG_EXTERN int png_do_rgb_to_gray PNGARG((png_structp png_ptr, png_row_infop - row_info, png_bytep row)); -#endif - -#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED -PNG_EXTERN void png_do_gray_to_rgb PNGARG((png_row_infop row_info, - png_bytep row)); -#endif - -#ifdef PNG_READ_PACK_SUPPORTED -PNG_EXTERN void png_do_unpack PNGARG((png_row_infop row_info, png_bytep row)); -#endif - -#ifdef PNG_READ_SHIFT_SUPPORTED -PNG_EXTERN void png_do_unshift PNGARG((png_row_infop row_info, png_bytep row, - png_color_8p sig_bits)); -#endif - -#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) -PNG_EXTERN void png_do_invert PNGARG((png_row_infop row_info, png_bytep row)); -#endif - -#ifdef PNG_READ_16_TO_8_SUPPORTED -PNG_EXTERN void png_do_chop PNGARG((png_row_infop row_info, png_bytep row)); -#endif - -#ifdef PNG_READ_QUANTIZE_SUPPORTED -PNG_EXTERN void png_do_quantize PNGARG((png_row_infop row_info, - png_bytep row, png_bytep palette_lookup, png_bytep quantize_lookup)); - -# ifdef PNG_CORRECT_PALETTE_SUPPORTED -PNG_EXTERN void png_correct_palette PNGARG((png_structp png_ptr, - png_colorp palette, int num_palette)); -# endif -#endif - -#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) -PNG_EXTERN void png_do_bgr PNGARG((png_row_infop row_info, png_bytep row)); -#endif - -#ifdef PNG_WRITE_PACK_SUPPORTED -PNG_EXTERN void png_do_pack PNGARG((png_row_infop row_info, - png_bytep row, png_uint_32 bit_depth)); -#endif - -#ifdef PNG_WRITE_SHIFT_SUPPORTED -PNG_EXTERN void png_do_shift PNGARG((png_row_infop row_info, png_bytep row, - png_color_8p bit_depth)); -#endif - -#ifdef PNG_READ_BACKGROUND_SUPPORTED -#ifdef PNG_READ_GAMMA_SUPPORTED -PNG_EXTERN void png_do_background PNGARG((png_row_infop row_info, png_bytep row, - png_color_16p trans_color, png_color_16p background, - png_color_16p background_1, - png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1, - png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1, - png_uint_16pp gamma_16_to_1, int gamma_shift)); -#else -PNG_EXTERN void png_do_background PNGARG((png_row_infop row_info, png_bytep row, - png_color_16p trans_color, png_color_16p background)); -#endif -#endif - -#ifdef PNG_READ_GAMMA_SUPPORTED -PNG_EXTERN void png_do_gamma PNGARG((png_row_infop row_info, png_bytep row, - png_bytep gamma_table, png_uint_16pp gamma_16_table, - int gamma_shift)); -#endif - -#ifdef PNG_READ_EXPAND_SUPPORTED -PNG_EXTERN void png_do_expand_palette PNGARG((png_row_infop row_info, - png_bytep row, png_colorp palette, png_bytep trans, int num_trans)); -PNG_EXTERN void png_do_expand PNGARG((png_row_infop row_info, - png_bytep row, png_color_16p trans_value)); -#endif - -/* The following decodes the appropriate chunks, and does error correction, - * then calls the appropriate callback for the chunk if it is valid. - */ - -/* Decode the IHDR chunk */ -PNG_EXTERN void png_handle_IHDR PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -PNG_EXTERN void png_handle_PLTE PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -PNG_EXTERN void png_handle_IEND PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); - -#ifdef PNG_READ_bKGD_SUPPORTED -PNG_EXTERN void png_handle_bKGD PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#ifdef PNG_READ_cHRM_SUPPORTED -PNG_EXTERN void png_handle_cHRM PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#ifdef PNG_READ_gAMA_SUPPORTED -PNG_EXTERN void png_handle_gAMA PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#ifdef PNG_READ_hIST_SUPPORTED -PNG_EXTERN void png_handle_hIST PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#ifdef PNG_READ_iCCP_SUPPORTED -extern void png_handle_iCCP PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif /* PNG_READ_iCCP_SUPPORTED */ - -#ifdef PNG_READ_iTXt_SUPPORTED -PNG_EXTERN void png_handle_iTXt PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#ifdef PNG_READ_oFFs_SUPPORTED -PNG_EXTERN void png_handle_oFFs PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#ifdef PNG_READ_pCAL_SUPPORTED -PNG_EXTERN void png_handle_pCAL PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#ifdef PNG_READ_pHYs_SUPPORTED -PNG_EXTERN void png_handle_pHYs PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#ifdef PNG_READ_sBIT_SUPPORTED -PNG_EXTERN void png_handle_sBIT PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#ifdef PNG_READ_sCAL_SUPPORTED -PNG_EXTERN void png_handle_sCAL PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#ifdef PNG_READ_sPLT_SUPPORTED -extern void png_handle_sPLT PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif /* PNG_READ_sPLT_SUPPORTED */ - -#ifdef PNG_READ_sRGB_SUPPORTED -PNG_EXTERN void png_handle_sRGB PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#ifdef PNG_READ_tEXt_SUPPORTED -PNG_EXTERN void png_handle_tEXt PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#ifdef PNG_READ_tIME_SUPPORTED -PNG_EXTERN void png_handle_tIME PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#ifdef PNG_READ_tRNS_SUPPORTED -PNG_EXTERN void png_handle_tRNS PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -#ifdef PNG_READ_zTXt_SUPPORTED -PNG_EXTERN void png_handle_zTXt PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#endif - -PNG_EXTERN void png_handle_unknown PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 length)); - -PNG_EXTERN void png_check_chunk_name PNGARG((png_structp png_ptr, - png_bytep chunk_name)); - -/* Handle the transformations for reading and writing */ -PNG_EXTERN void png_do_read_transformations PNGARG((png_structp png_ptr)); -PNG_EXTERN void png_do_write_transformations PNGARG((png_structp png_ptr)); - -PNG_EXTERN void png_init_read_transformations PNGARG((png_structp png_ptr)); - -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED -PNG_EXTERN void png_push_read_chunk PNGARG((png_structp png_ptr, - png_infop info_ptr)); -PNG_EXTERN void png_push_read_sig PNGARG((png_structp png_ptr, - png_infop info_ptr)); -PNG_EXTERN void png_push_check_crc PNGARG((png_structp png_ptr)); -PNG_EXTERN void png_push_crc_skip PNGARG((png_structp png_ptr, - png_uint_32 length)); -PNG_EXTERN void png_push_crc_finish PNGARG((png_structp png_ptr)); -PNG_EXTERN void png_push_save_buffer PNGARG((png_structp png_ptr)); -PNG_EXTERN void png_push_restore_buffer PNGARG((png_structp png_ptr, - png_bytep buffer, png_size_t buffer_length)); -PNG_EXTERN void png_push_read_IDAT PNGARG((png_structp png_ptr)); -PNG_EXTERN void png_process_IDAT_data PNGARG((png_structp png_ptr, - png_bytep buffer, png_size_t buffer_length)); -PNG_EXTERN void png_push_process_row PNGARG((png_structp png_ptr)); -PNG_EXTERN void png_push_handle_unknown PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 length)); -PNG_EXTERN void png_push_have_info PNGARG((png_structp png_ptr, - png_infop info_ptr)); -PNG_EXTERN void png_push_have_end PNGARG((png_structp png_ptr, - png_infop info_ptr)); -PNG_EXTERN void png_push_have_row PNGARG((png_structp png_ptr, png_bytep row)); -PNG_EXTERN void png_push_read_end PNGARG((png_structp png_ptr, - png_infop info_ptr)); -PNG_EXTERN void png_process_some_data PNGARG((png_structp png_ptr, - png_infop info_ptr)); -PNG_EXTERN void png_read_push_finish_row PNGARG((png_structp png_ptr)); -#ifdef PNG_READ_tEXt_SUPPORTED -PNG_EXTERN void png_push_handle_tEXt PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 length)); -PNG_EXTERN void png_push_read_tEXt PNGARG((png_structp png_ptr, - png_infop info_ptr)); -#endif -#ifdef PNG_READ_zTXt_SUPPORTED -PNG_EXTERN void png_push_handle_zTXt PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 length)); -PNG_EXTERN void png_push_read_zTXt PNGARG((png_structp png_ptr, - png_infop info_ptr)); -#endif -#ifdef PNG_READ_iTXt_SUPPORTED -PNG_EXTERN void png_push_handle_iTXt PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 length)); -PNG_EXTERN void png_push_read_iTXt PNGARG((png_structp png_ptr, - png_infop info_ptr)); -#endif - -#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ - -#ifdef PNG_MNG_FEATURES_SUPPORTED -PNG_EXTERN void png_do_read_intrapixel PNGARG((png_row_infop row_info, - png_bytep row)); -PNG_EXTERN void png_do_write_intrapixel PNGARG((png_row_infop row_info, - png_bytep row)); -#endif - -/* Added at libpng version 1.4.0 */ -#ifdef PNG_cHRM_SUPPORTED -PNG_EXTERN int png_check_cHRM_fixed PNGARG((png_structp png_ptr, - png_fixed_point int_white_x, png_fixed_point int_white_y, - png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point - int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x, - png_fixed_point int_blue_y)); -#endif - -#ifdef PNG_cHRM_SUPPORTED -#ifdef PNG_CHECK_cHRM_SUPPORTED -/* Added at libpng version 1.2.34 and 1.4.0 */ -PNG_EXTERN void png_64bit_product PNGARG((long v1, long v2, - unsigned long *hi_product, unsigned long *lo_product)); -#endif -#endif - -/* Added at libpng version 1.4.0 */ -PNG_EXTERN void png_check_IHDR PNGARG((png_structp png_ptr, - png_uint_32 width, png_uint_32 height, int bit_depth, - int color_type, int interlace_type, int compression_type, - int filter_type)); - -/* Free all memory used by the read (old method - NOT DLL EXPORTED) */ -extern void png_read_destroy PNGARG((png_structp png_ptr, png_infop info_ptr, - png_infop end_info_ptr)); - -/* Free any memory used in png_ptr struct (old method - NOT DLL EXPORTED) */ -extern void png_write_destroy PNGARG((png_structp png_ptr)); - -#ifdef USE_FAR_KEYWORD /* memory model conversion function */ -extern void *png_far_to_near PNGARG((png_structp png_ptr,png_voidp ptr, - int check)); -#endif /* USE_FAR_KEYWORD */ - -/* Define PNG_DEBUG at compile time for debugging information. Higher - * numbers for PNG_DEBUG mean more debugging information. This has - * only been added since version 0.95 so it is not implemented throughout - * libpng yet, but more support will be added as needed. - */ -#ifdef PNG_DEBUG -#if (PNG_DEBUG > 0) -#if !defined(PNG_DEBUG_FILE) && defined(_MSC_VER) -#include -#if (PNG_DEBUG > 1) -#ifndef _DEBUG -# define _DEBUG -#endif -#ifndef png_debug -#define png_debug(l,m) _RPT0(_CRT_WARN,m PNG_STRING_NEWLINE) -#endif -#ifndef png_debug1 -#define png_debug1(l,m,p1) _RPT1(_CRT_WARN,m PNG_STRING_NEWLINE,p1) -#endif -#ifndef png_debug2 -#define png_debug2(l,m,p1,p2) _RPT2(_CRT_WARN,m PNG_STRING_NEWLINE,p1,p2) -#endif -#endif -#else /* PNG_DEBUG_FILE || !_MSC_VER */ -#ifndef PNG_DEBUG_FILE -#define PNG_DEBUG_FILE stderr -#endif /* PNG_DEBUG_FILE */ - -#if (PNG_DEBUG > 1) -/* Note: ["%s"m PNG_STRING_NEWLINE] probably does not work on - * non-ISO compilers - */ -# ifdef __STDC__ -# ifndef png_debug -# define png_debug(l,m) \ - { \ - int num_tabs=l; \ - fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \ - (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":"")))); \ - } -# endif -# ifndef png_debug1 -# define png_debug1(l,m,p1) \ - { \ - int num_tabs=l; \ - fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \ - (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1); \ - } -# endif -# ifndef png_debug2 -# define png_debug2(l,m,p1,p2) \ - { \ - int num_tabs=l; \ - fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \ - (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1,p2); \ - } -# endif -# else /* __STDC __ */ -# ifndef png_debug -# define png_debug(l,m) \ - { \ - int num_tabs=l; \ - char format[256]; \ - snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \ - (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \ - m,PNG_STRING_NEWLINE); \ - fprintf(PNG_DEBUG_FILE,format); \ - } -# endif -# ifndef png_debug1 -# define png_debug1(l,m,p1) \ - { \ - int num_tabs=l; \ - char format[256]; \ - snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \ - (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \ - m,PNG_STRING_NEWLINE); \ - fprintf(PNG_DEBUG_FILE,format,p1); \ - } -# endif -# ifndef png_debug2 -# define png_debug2(l,m,p1,p2) \ - { \ - int num_tabs=l; \ - char format[256]; \ - snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \ - (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \ - m,PNG_STRING_NEWLINE); \ - fprintf(PNG_DEBUG_FILE,format,p1,p2); \ - } -# endif -# endif /* __STDC __ */ -#endif /* (PNG_DEBUG > 1) */ - -#endif /* _MSC_VER */ -#endif /* (PNG_DEBUG > 0) */ -#endif /* PNG_DEBUG */ -#ifndef png_debug -#define png_debug(l, m) -#endif -#ifndef png_debug1 -#define png_debug1(l, m, p1) -#endif -#ifndef png_debug2 -#define png_debug2(l, m, p1, p2) -#endif - -/* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */ - -#ifdef __cplusplus -} -#endif - -#endif /* PNG_VERSION_INFO_ONLY */ -#endif /* PNGPRIV_H */ diff --git a/reactos/dll/3rdparty/libtiff/libtiff.rbuild b/reactos/dll/3rdparty/libtiff/libtiff.rbuild index cb3ea02447a..415f5b64ee3 100644 --- a/reactos/dll/3rdparty/libtiff/libtiff.rbuild +++ b/reactos/dll/3rdparty/libtiff/libtiff.rbuild @@ -6,7 +6,8 @@ . - lib/3rdparty/zlib + include/reactos/libs/zlib + include/reactos/libs/libtiff user32 zlib mkg3states.c diff --git a/reactos/dll/3rdparty/libtiff/t4.h b/reactos/dll/3rdparty/libtiff/t4.h deleted file mode 100644 index 870704ffe8a..00000000000 --- a/reactos/dll/3rdparty/libtiff/t4.h +++ /dev/null @@ -1,292 +0,0 @@ -/* $Id: t4.h,v 1.1.1.1.2.1 2010-06-08 18:50:41 bfriesen Exp $ */ - -/* - * Copyright (c) 1988-1997 Sam Leffler - * Copyright (c) 1991-1997 Silicon Graphics, Inc. - * - * Permission to use, copy, modify, distribute, and sell this software and - * its documentation for any purpose is hereby granted without fee, provided - * that (i) the above copyright notices and this permission notice appear in - * all copies of the software and related documentation, and (ii) the names of - * Sam Leffler and Silicon Graphics may not be used in any advertising or - * publicity relating to the software without the specific, prior written - * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * - * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR - * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, - * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -#ifndef _T4_ -#define _T4_ -/* - * CCITT T.4 1D Huffman runlength codes and - * related definitions. Given the small sizes - * of these tables it does not seem - * worthwhile to make code & length 8 bits. - */ -typedef struct tableentry { - unsigned short length; /* bit length of g3 code */ - unsigned short code; /* g3 code */ - short runlen; /* run length in bits */ -} tableentry; - -#define EOL 0x001 /* EOL code value - 0000 0000 0000 1 */ - -/* status values returned instead of a run length */ -#define G3CODE_EOL -1 /* NB: ACT_EOL - ACT_WRUNT */ -#define G3CODE_INVALID -2 /* NB: ACT_INVALID - ACT_WRUNT */ -#define G3CODE_EOF -3 /* end of input data */ -#define G3CODE_INCOMP -4 /* incomplete run code */ - -/* - * Note that these tables are ordered such that the - * index into the table is known to be either the - * run length, or (run length / 64) + a fixed offset. - * - * NB: The G3CODE_INVALID entries are only used - * during state generation (see mkg3states.c). - */ -#ifdef G3CODES -const tableentry TIFFFaxWhiteCodes[] = { - { 8, 0x35, 0 }, /* 0011 0101 */ - { 6, 0x7, 1 }, /* 0001 11 */ - { 4, 0x7, 2 }, /* 0111 */ - { 4, 0x8, 3 }, /* 1000 */ - { 4, 0xB, 4 }, /* 1011 */ - { 4, 0xC, 5 }, /* 1100 */ - { 4, 0xE, 6 }, /* 1110 */ - { 4, 0xF, 7 }, /* 1111 */ - { 5, 0x13, 8 }, /* 1001 1 */ - { 5, 0x14, 9 }, /* 1010 0 */ - { 5, 0x7, 10 }, /* 0011 1 */ - { 5, 0x8, 11 }, /* 0100 0 */ - { 6, 0x8, 12 }, /* 0010 00 */ - { 6, 0x3, 13 }, /* 0000 11 */ - { 6, 0x34, 14 }, /* 1101 00 */ - { 6, 0x35, 15 }, /* 1101 01 */ - { 6, 0x2A, 16 }, /* 1010 10 */ - { 6, 0x2B, 17 }, /* 1010 11 */ - { 7, 0x27, 18 }, /* 0100 111 */ - { 7, 0xC, 19 }, /* 0001 100 */ - { 7, 0x8, 20 }, /* 0001 000 */ - { 7, 0x17, 21 }, /* 0010 111 */ - { 7, 0x3, 22 }, /* 0000 011 */ - { 7, 0x4, 23 }, /* 0000 100 */ - { 7, 0x28, 24 }, /* 0101 000 */ - { 7, 0x2B, 25 }, /* 0101 011 */ - { 7, 0x13, 26 }, /* 0010 011 */ - { 7, 0x24, 27 }, /* 0100 100 */ - { 7, 0x18, 28 }, /* 0011 000 */ - { 8, 0x2, 29 }, /* 0000 0010 */ - { 8, 0x3, 30 }, /* 0000 0011 */ - { 8, 0x1A, 31 }, /* 0001 1010 */ - { 8, 0x1B, 32 }, /* 0001 1011 */ - { 8, 0x12, 33 }, /* 0001 0010 */ - { 8, 0x13, 34 }, /* 0001 0011 */ - { 8, 0x14, 35 }, /* 0001 0100 */ - { 8, 0x15, 36 }, /* 0001 0101 */ - { 8, 0x16, 37 }, /* 0001 0110 */ - { 8, 0x17, 38 }, /* 0001 0111 */ - { 8, 0x28, 39 }, /* 0010 1000 */ - { 8, 0x29, 40 }, /* 0010 1001 */ - { 8, 0x2A, 41 }, /* 0010 1010 */ - { 8, 0x2B, 42 }, /* 0010 1011 */ - { 8, 0x2C, 43 }, /* 0010 1100 */ - { 8, 0x2D, 44 }, /* 0010 1101 */ - { 8, 0x4, 45 }, /* 0000 0100 */ - { 8, 0x5, 46 }, /* 0000 0101 */ - { 8, 0xA, 47 }, /* 0000 1010 */ - { 8, 0xB, 48 }, /* 0000 1011 */ - { 8, 0x52, 49 }, /* 0101 0010 */ - { 8, 0x53, 50 }, /* 0101 0011 */ - { 8, 0x54, 51 }, /* 0101 0100 */ - { 8, 0x55, 52 }, /* 0101 0101 */ - { 8, 0x24, 53 }, /* 0010 0100 */ - { 8, 0x25, 54 }, /* 0010 0101 */ - { 8, 0x58, 55 }, /* 0101 1000 */ - { 8, 0x59, 56 }, /* 0101 1001 */ - { 8, 0x5A, 57 }, /* 0101 1010 */ - { 8, 0x5B, 58 }, /* 0101 1011 */ - { 8, 0x4A, 59 }, /* 0100 1010 */ - { 8, 0x4B, 60 }, /* 0100 1011 */ - { 8, 0x32, 61 }, /* 0011 0010 */ - { 8, 0x33, 62 }, /* 0011 0011 */ - { 8, 0x34, 63 }, /* 0011 0100 */ - { 5, 0x1B, 64 }, /* 1101 1 */ - { 5, 0x12, 128 }, /* 1001 0 */ - { 6, 0x17, 192 }, /* 0101 11 */ - { 7, 0x37, 256 }, /* 0110 111 */ - { 8, 0x36, 320 }, /* 0011 0110 */ - { 8, 0x37, 384 }, /* 0011 0111 */ - { 8, 0x64, 448 }, /* 0110 0100 */ - { 8, 0x65, 512 }, /* 0110 0101 */ - { 8, 0x68, 576 }, /* 0110 1000 */ - { 8, 0x67, 640 }, /* 0110 0111 */ - { 9, 0xCC, 704 }, /* 0110 0110 0 */ - { 9, 0xCD, 768 }, /* 0110 0110 1 */ - { 9, 0xD2, 832 }, /* 0110 1001 0 */ - { 9, 0xD3, 896 }, /* 0110 1001 1 */ - { 9, 0xD4, 960 }, /* 0110 1010 0 */ - { 9, 0xD5, 1024 }, /* 0110 1010 1 */ - { 9, 0xD6, 1088 }, /* 0110 1011 0 */ - { 9, 0xD7, 1152 }, /* 0110 1011 1 */ - { 9, 0xD8, 1216 }, /* 0110 1100 0 */ - { 9, 0xD9, 1280 }, /* 0110 1100 1 */ - { 9, 0xDA, 1344 }, /* 0110 1101 0 */ - { 9, 0xDB, 1408 }, /* 0110 1101 1 */ - { 9, 0x98, 1472 }, /* 0100 1100 0 */ - { 9, 0x99, 1536 }, /* 0100 1100 1 */ - { 9, 0x9A, 1600 }, /* 0100 1101 0 */ - { 6, 0x18, 1664 }, /* 0110 00 */ - { 9, 0x9B, 1728 }, /* 0100 1101 1 */ - { 11, 0x8, 1792 }, /* 0000 0001 000 */ - { 11, 0xC, 1856 }, /* 0000 0001 100 */ - { 11, 0xD, 1920 }, /* 0000 0001 101 */ - { 12, 0x12, 1984 }, /* 0000 0001 0010 */ - { 12, 0x13, 2048 }, /* 0000 0001 0011 */ - { 12, 0x14, 2112 }, /* 0000 0001 0100 */ - { 12, 0x15, 2176 }, /* 0000 0001 0101 */ - { 12, 0x16, 2240 }, /* 0000 0001 0110 */ - { 12, 0x17, 2304 }, /* 0000 0001 0111 */ - { 12, 0x1C, 2368 }, /* 0000 0001 1100 */ - { 12, 0x1D, 2432 }, /* 0000 0001 1101 */ - { 12, 0x1E, 2496 }, /* 0000 0001 1110 */ - { 12, 0x1F, 2560 }, /* 0000 0001 1111 */ - { 12, 0x1, G3CODE_EOL }, /* 0000 0000 0001 */ - { 9, 0x1, G3CODE_INVALID }, /* 0000 0000 1 */ - { 10, 0x1, G3CODE_INVALID }, /* 0000 0000 01 */ - { 11, 0x1, G3CODE_INVALID }, /* 0000 0000 001 */ - { 12, 0x0, G3CODE_INVALID }, /* 0000 0000 0000 */ -}; - -const tableentry TIFFFaxBlackCodes[] = { - { 10, 0x37, 0 }, /* 0000 1101 11 */ - { 3, 0x2, 1 }, /* 010 */ - { 2, 0x3, 2 }, /* 11 */ - { 2, 0x2, 3 }, /* 10 */ - { 3, 0x3, 4 }, /* 011 */ - { 4, 0x3, 5 }, /* 0011 */ - { 4, 0x2, 6 }, /* 0010 */ - { 5, 0x3, 7 }, /* 0001 1 */ - { 6, 0x5, 8 }, /* 0001 01 */ - { 6, 0x4, 9 }, /* 0001 00 */ - { 7, 0x4, 10 }, /* 0000 100 */ - { 7, 0x5, 11 }, /* 0000 101 */ - { 7, 0x7, 12 }, /* 0000 111 */ - { 8, 0x4, 13 }, /* 0000 0100 */ - { 8, 0x7, 14 }, /* 0000 0111 */ - { 9, 0x18, 15 }, /* 0000 1100 0 */ - { 10, 0x17, 16 }, /* 0000 0101 11 */ - { 10, 0x18, 17 }, /* 0000 0110 00 */ - { 10, 0x8, 18 }, /* 0000 0010 00 */ - { 11, 0x67, 19 }, /* 0000 1100 111 */ - { 11, 0x68, 20 }, /* 0000 1101 000 */ - { 11, 0x6C, 21 }, /* 0000 1101 100 */ - { 11, 0x37, 22 }, /* 0000 0110 111 */ - { 11, 0x28, 23 }, /* 0000 0101 000 */ - { 11, 0x17, 24 }, /* 0000 0010 111 */ - { 11, 0x18, 25 }, /* 0000 0011 000 */ - { 12, 0xCA, 26 }, /* 0000 1100 1010 */ - { 12, 0xCB, 27 }, /* 0000 1100 1011 */ - { 12, 0xCC, 28 }, /* 0000 1100 1100 */ - { 12, 0xCD, 29 }, /* 0000 1100 1101 */ - { 12, 0x68, 30 }, /* 0000 0110 1000 */ - { 12, 0x69, 31 }, /* 0000 0110 1001 */ - { 12, 0x6A, 32 }, /* 0000 0110 1010 */ - { 12, 0x6B, 33 }, /* 0000 0110 1011 */ - { 12, 0xD2, 34 }, /* 0000 1101 0010 */ - { 12, 0xD3, 35 }, /* 0000 1101 0011 */ - { 12, 0xD4, 36 }, /* 0000 1101 0100 */ - { 12, 0xD5, 37 }, /* 0000 1101 0101 */ - { 12, 0xD6, 38 }, /* 0000 1101 0110 */ - { 12, 0xD7, 39 }, /* 0000 1101 0111 */ - { 12, 0x6C, 40 }, /* 0000 0110 1100 */ - { 12, 0x6D, 41 }, /* 0000 0110 1101 */ - { 12, 0xDA, 42 }, /* 0000 1101 1010 */ - { 12, 0xDB, 43 }, /* 0000 1101 1011 */ - { 12, 0x54, 44 }, /* 0000 0101 0100 */ - { 12, 0x55, 45 }, /* 0000 0101 0101 */ - { 12, 0x56, 46 }, /* 0000 0101 0110 */ - { 12, 0x57, 47 }, /* 0000 0101 0111 */ - { 12, 0x64, 48 }, /* 0000 0110 0100 */ - { 12, 0x65, 49 }, /* 0000 0110 0101 */ - { 12, 0x52, 50 }, /* 0000 0101 0010 */ - { 12, 0x53, 51 }, /* 0000 0101 0011 */ - { 12, 0x24, 52 }, /* 0000 0010 0100 */ - { 12, 0x37, 53 }, /* 0000 0011 0111 */ - { 12, 0x38, 54 }, /* 0000 0011 1000 */ - { 12, 0x27, 55 }, /* 0000 0010 0111 */ - { 12, 0x28, 56 }, /* 0000 0010 1000 */ - { 12, 0x58, 57 }, /* 0000 0101 1000 */ - { 12, 0x59, 58 }, /* 0000 0101 1001 */ - { 12, 0x2B, 59 }, /* 0000 0010 1011 */ - { 12, 0x2C, 60 }, /* 0000 0010 1100 */ - { 12, 0x5A, 61 }, /* 0000 0101 1010 */ - { 12, 0x66, 62 }, /* 0000 0110 0110 */ - { 12, 0x67, 63 }, /* 0000 0110 0111 */ - { 10, 0xF, 64 }, /* 0000 0011 11 */ - { 12, 0xC8, 128 }, /* 0000 1100 1000 */ - { 12, 0xC9, 192 }, /* 0000 1100 1001 */ - { 12, 0x5B, 256 }, /* 0000 0101 1011 */ - { 12, 0x33, 320 }, /* 0000 0011 0011 */ - { 12, 0x34, 384 }, /* 0000 0011 0100 */ - { 12, 0x35, 448 }, /* 0000 0011 0101 */ - { 13, 0x6C, 512 }, /* 0000 0011 0110 0 */ - { 13, 0x6D, 576 }, /* 0000 0011 0110 1 */ - { 13, 0x4A, 640 }, /* 0000 0010 0101 0 */ - { 13, 0x4B, 704 }, /* 0000 0010 0101 1 */ - { 13, 0x4C, 768 }, /* 0000 0010 0110 0 */ - { 13, 0x4D, 832 }, /* 0000 0010 0110 1 */ - { 13, 0x72, 896 }, /* 0000 0011 1001 0 */ - { 13, 0x73, 960 }, /* 0000 0011 1001 1 */ - { 13, 0x74, 1024 }, /* 0000 0011 1010 0 */ - { 13, 0x75, 1088 }, /* 0000 0011 1010 1 */ - { 13, 0x76, 1152 }, /* 0000 0011 1011 0 */ - { 13, 0x77, 1216 }, /* 0000 0011 1011 1 */ - { 13, 0x52, 1280 }, /* 0000 0010 1001 0 */ - { 13, 0x53, 1344 }, /* 0000 0010 1001 1 */ - { 13, 0x54, 1408 }, /* 0000 0010 1010 0 */ - { 13, 0x55, 1472 }, /* 0000 0010 1010 1 */ - { 13, 0x5A, 1536 }, /* 0000 0010 1101 0 */ - { 13, 0x5B, 1600 }, /* 0000 0010 1101 1 */ - { 13, 0x64, 1664 }, /* 0000 0011 0010 0 */ - { 13, 0x65, 1728 }, /* 0000 0011 0010 1 */ - { 11, 0x8, 1792 }, /* 0000 0001 000 */ - { 11, 0xC, 1856 }, /* 0000 0001 100 */ - { 11, 0xD, 1920 }, /* 0000 0001 101 */ - { 12, 0x12, 1984 }, /* 0000 0001 0010 */ - { 12, 0x13, 2048 }, /* 0000 0001 0011 */ - { 12, 0x14, 2112 }, /* 0000 0001 0100 */ - { 12, 0x15, 2176 }, /* 0000 0001 0101 */ - { 12, 0x16, 2240 }, /* 0000 0001 0110 */ - { 12, 0x17, 2304 }, /* 0000 0001 0111 */ - { 12, 0x1C, 2368 }, /* 0000 0001 1100 */ - { 12, 0x1D, 2432 }, /* 0000 0001 1101 */ - { 12, 0x1E, 2496 }, /* 0000 0001 1110 */ - { 12, 0x1F, 2560 }, /* 0000 0001 1111 */ - { 12, 0x1, G3CODE_EOL }, /* 0000 0000 0001 */ - { 9, 0x1, G3CODE_INVALID }, /* 0000 0000 1 */ - { 10, 0x1, G3CODE_INVALID }, /* 0000 0000 01 */ - { 11, 0x1, G3CODE_INVALID }, /* 0000 0000 001 */ - { 12, 0x0, G3CODE_INVALID }, /* 0000 0000 0000 */ -}; -#else -extern const tableentry TIFFFaxWhiteCodes[]; -extern const tableentry TIFFFaxBlackCodes[]; -#endif -#endif /* _T4_ */ -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/reactos/dll/3rdparty/libtiff/tif_config.h b/reactos/dll/3rdparty/libtiff/tif_config.h deleted file mode 100644 index 4dd77dd8cf1..00000000000 --- a/reactos/dll/3rdparty/libtiff/tif_config.h +++ /dev/null @@ -1,63 +0,0 @@ -/* Define to 1 if you have the header file. */ -#define HAVE_ASSERT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_FCNTL_H 1 - -/* Define as 0 or 1 according to the floating point format suported by the - machine */ -#define HAVE_IEEEFP 1 - -/* Define to 1 if you have the `jbg_newlen' function. */ -#define HAVE_JBG_NEWLEN 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_IO_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SEARCH_H 1 - -/* Define to 1 if you have the `setmode' function. */ -#define HAVE_SETMODE 1 - -/* The size of a `int', as computed by sizeof. */ -#define SIZEOF_INT 4 - -/* The size of a `long', as computed by sizeof. */ -#define SIZEOF_LONG 4 - -/* Signed 64-bit type */ -#define TIFF_INT64_T signed __int64 - -/* Unsigned 64-bit type */ -#define TIFF_UINT64_T unsigned __int64 - -/* Set the native cpu bit order */ -#define HOST_FILLORDER FILLORDER_LSB2MSB - -/* Define to 1 if your processor stores words with the most significant byte - first (like Motorola and SPARC, unlike Intel and VAX). */ -/* #undef WORDS_BIGENDIAN */ - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -# ifndef inline -# define inline __inline -# endif -#endif - -#define lfind _lfind -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/reactos/dll/3rdparty/libtiff/tif_config.vc.h b/reactos/dll/3rdparty/libtiff/tif_config.vc.h deleted file mode 100644 index 4dd77dd8cf1..00000000000 --- a/reactos/dll/3rdparty/libtiff/tif_config.vc.h +++ /dev/null @@ -1,63 +0,0 @@ -/* Define to 1 if you have the header file. */ -#define HAVE_ASSERT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_FCNTL_H 1 - -/* Define as 0 or 1 according to the floating point format suported by the - machine */ -#define HAVE_IEEEFP 1 - -/* Define to 1 if you have the `jbg_newlen' function. */ -#define HAVE_JBG_NEWLEN 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_IO_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SEARCH_H 1 - -/* Define to 1 if you have the `setmode' function. */ -#define HAVE_SETMODE 1 - -/* The size of a `int', as computed by sizeof. */ -#define SIZEOF_INT 4 - -/* The size of a `long', as computed by sizeof. */ -#define SIZEOF_LONG 4 - -/* Signed 64-bit type */ -#define TIFF_INT64_T signed __int64 - -/* Unsigned 64-bit type */ -#define TIFF_UINT64_T unsigned __int64 - -/* Set the native cpu bit order */ -#define HOST_FILLORDER FILLORDER_LSB2MSB - -/* Define to 1 if your processor stores words with the most significant byte - first (like Motorola and SPARC, unlike Intel and VAX). */ -/* #undef WORDS_BIGENDIAN */ - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -# ifndef inline -# define inline __inline -# endif -#endif - -#define lfind _lfind -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/reactos/dll/3rdparty/libtiff/tif_dir.h b/reactos/dll/3rdparty/libtiff/tif_dir.h deleted file mode 100644 index 515af19942c..00000000000 --- a/reactos/dll/3rdparty/libtiff/tif_dir.h +++ /dev/null @@ -1,211 +0,0 @@ -/* $Id: tif_dir.h,v 1.30.2.3 2010-06-09 21:15:27 bfriesen Exp $ */ - -/* - * Copyright (c) 1988-1997 Sam Leffler - * Copyright (c) 1991-1997 Silicon Graphics, Inc. - * - * Permission to use, copy, modify, distribute, and sell this software and - * its documentation for any purpose is hereby granted without fee, provided - * that (i) the above copyright notices and this permission notice appear in - * all copies of the software and related documentation, and (ii) the names of - * Sam Leffler and Silicon Graphics may not be used in any advertising or - * publicity relating to the software without the specific, prior written - * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * - * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR - * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, - * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -#ifndef _TIFFDIR_ -#define _TIFFDIR_ -/* - * ``Library-private'' Directory-related Definitions. - */ - -/* - * Internal format of a TIFF directory entry. - */ -typedef struct { -#define FIELD_SETLONGS 4 - /* bit vector of fields that are set */ - unsigned long td_fieldsset[FIELD_SETLONGS]; - - uint32 td_imagewidth, td_imagelength, td_imagedepth; - uint32 td_tilewidth, td_tilelength, td_tiledepth; - uint32 td_subfiletype; - uint16 td_bitspersample; - uint16 td_sampleformat; - uint16 td_compression; - uint16 td_photometric; - uint16 td_threshholding; - uint16 td_fillorder; - uint16 td_orientation; - uint16 td_samplesperpixel; - uint32 td_rowsperstrip; - uint16 td_minsamplevalue, td_maxsamplevalue; - double td_sminsamplevalue, td_smaxsamplevalue; - float td_xresolution, td_yresolution; - uint16 td_resolutionunit; - uint16 td_planarconfig; - float td_xposition, td_yposition; - uint16 td_pagenumber[2]; - uint16* td_colormap[3]; - uint16 td_halftonehints[2]; - uint16 td_extrasamples; - uint16* td_sampleinfo; - /* even though the name is misleading, td_stripsperimage is the number - * of striles (=strips or tiles) per plane, and td_nstrips the total - * number of striles */ - tstrile_t td_stripsperimage; - tstrile_t td_nstrips; /* size of offset & bytecount arrays */ - toff_t* td_stripoffset; - toff_t* td_stripbytecount; /* FIXME: it should be tsize_t array */ - int td_stripbytecountsorted; /* is the bytecount array sorted ascending? */ - uint16 td_nsubifd; - uint32* td_subifd; - /* YCbCr parameters */ - uint16 td_ycbcrsubsampling[2]; - uint16 td_ycbcrpositioning; - /* Colorimetry parameters */ - float* td_refblackwhite; - uint16* td_transferfunction[3]; - /* CMYK parameters */ - int td_inknameslen; - char* td_inknames; - - int td_customValueCount; - TIFFTagValue *td_customValues; -} TIFFDirectory; - -/* - * Field flags used to indicate fields that have - * been set in a directory, and to reference fields - * when manipulating a directory. - */ - -/* - * FIELD_IGNORE is used to signify tags that are to - * be processed but otherwise ignored. This permits - * antiquated tags to be quietly read and discarded. - * Note that a bit *is* allocated for ignored tags; - * this is understood by the directory reading logic - * which uses this fact to avoid special-case handling - */ -#define FIELD_IGNORE 0 - -/* multi-item fields */ -#define FIELD_IMAGEDIMENSIONS 1 -#define FIELD_TILEDIMENSIONS 2 -#define FIELD_RESOLUTION 3 -#define FIELD_POSITION 4 - -/* single-item fields */ -#define FIELD_SUBFILETYPE 5 -#define FIELD_BITSPERSAMPLE 6 -#define FIELD_COMPRESSION 7 -#define FIELD_PHOTOMETRIC 8 -#define FIELD_THRESHHOLDING 9 -#define FIELD_FILLORDER 10 -#define FIELD_ORIENTATION 15 -#define FIELD_SAMPLESPERPIXEL 16 -#define FIELD_ROWSPERSTRIP 17 -#define FIELD_MINSAMPLEVALUE 18 -#define FIELD_MAXSAMPLEVALUE 19 -#define FIELD_PLANARCONFIG 20 -#define FIELD_RESOLUTIONUNIT 22 -#define FIELD_PAGENUMBER 23 -#define FIELD_STRIPBYTECOUNTS 24 -#define FIELD_STRIPOFFSETS 25 -#define FIELD_COLORMAP 26 -#define FIELD_EXTRASAMPLES 31 -#define FIELD_SAMPLEFORMAT 32 -#define FIELD_SMINSAMPLEVALUE 33 -#define FIELD_SMAXSAMPLEVALUE 34 -#define FIELD_IMAGEDEPTH 35 -#define FIELD_TILEDEPTH 36 -#define FIELD_HALFTONEHINTS 37 -#define FIELD_YCBCRSUBSAMPLING 39 -#define FIELD_YCBCRPOSITIONING 40 -#define FIELD_REFBLACKWHITE 41 -#define FIELD_TRANSFERFUNCTION 44 -#define FIELD_INKNAMES 46 -#define FIELD_SUBIFD 49 -/* FIELD_CUSTOM (see tiffio.h) 65 */ -/* end of support for well-known tags; codec-private tags follow */ -#define FIELD_CODEC 66 /* base of codec-private tags */ - - -/* - * Pseudo-tags don't normally need field bits since they - * are not written to an output file (by definition). - * The library also has express logic to always query a - * codec for a pseudo-tag so allocating a field bit for - * one is a waste. If codec wants to promote the notion - * of a pseudo-tag being ``set'' or ``unset'' then it can - * do using internal state flags without polluting the - * field bit space defined for real tags. - */ -#define FIELD_PSEUDO 0 - -#define FIELD_LAST (32*FIELD_SETLONGS-1) - -#define TIFFExtractData(tif, type, v) \ - ((uint32) ((tif)->tif_header.tiff_magic == TIFF_BIGENDIAN ? \ - ((v) >> (tif)->tif_typeshift[type]) & (tif)->tif_typemask[type] : \ - (v) & (tif)->tif_typemask[type])) -#define TIFFInsertData(tif, type, v) \ - ((uint32) ((tif)->tif_header.tiff_magic == TIFF_BIGENDIAN ? \ - ((v) & (tif)->tif_typemask[type]) << (tif)->tif_typeshift[type] : \ - (v) & (tif)->tif_typemask[type])) - - -#define BITn(n) (((unsigned long)1L)<<((n)&0x1f)) -#define BITFIELDn(tif, n) ((tif)->tif_dir.td_fieldsset[(n)/32]) -#define TIFFFieldSet(tif, field) (BITFIELDn(tif, field) & BITn(field)) -#define TIFFSetFieldBit(tif, field) (BITFIELDn(tif, field) |= BITn(field)) -#define TIFFClrFieldBit(tif, field) (BITFIELDn(tif, field) &= ~BITn(field)) - -#define FieldSet(fields, f) (fields[(f)/32] & BITn(f)) -#define ResetFieldBit(fields, f) (fields[(f)/32] &= ~BITn(f)) - -#if defined(__cplusplus) -extern "C" { -#endif -extern const TIFFFieldInfo *_TIFFGetFieldInfo(size_t *); -extern const TIFFFieldInfo *_TIFFGetExifFieldInfo(size_t *); -extern void _TIFFSetupFieldInfo(TIFF*, const TIFFFieldInfo[], size_t); -extern int _TIFFMergeFieldInfo(TIFF*, const TIFFFieldInfo[], int); -extern void _TIFFPrintFieldInfo(TIFF*, FILE*); -extern TIFFDataType _TIFFSampleToTagType(TIFF*); -extern const TIFFFieldInfo* _TIFFFindOrRegisterFieldInfo( TIFF *tif, - ttag_t tag, - TIFFDataType dt ); -extern TIFFFieldInfo* _TIFFCreateAnonFieldInfo( TIFF *tif, ttag_t tag, - TIFFDataType dt ); - -#define _TIFFFindFieldInfo TIFFFindFieldInfo -#define _TIFFFindFieldInfoByName TIFFFindFieldInfoByName -#define _TIFFFieldWithTag TIFFFieldWithTag -#define _TIFFFieldWithName TIFFFieldWithName - -#if defined(__cplusplus) -} -#endif -#endif /* _TIFFDIR_ */ - -/* vim: set ts=8 sts=8 sw=8 noet: */ -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/reactos/dll/3rdparty/libtiff/tif_fax3.h b/reactos/dll/3rdparty/libtiff/tif_fax3.h deleted file mode 100644 index 40718bcfa71..00000000000 --- a/reactos/dll/3rdparty/libtiff/tif_fax3.h +++ /dev/null @@ -1,532 +0,0 @@ -/* $Id: tif_fax3.h,v 1.5.2.1 2010-06-08 18:50:42 bfriesen Exp $ */ - -/* - * Copyright (c) 1990-1997 Sam Leffler - * Copyright (c) 1991-1997 Silicon Graphics, Inc. - * - * Permission to use, copy, modify, distribute, and sell this software and - * its documentation for any purpose is hereby granted without fee, provided - * that (i) the above copyright notices and this permission notice appear in - * all copies of the software and related documentation, and (ii) the names of - * Sam Leffler and Silicon Graphics may not be used in any advertising or - * publicity relating to the software without the specific, prior written - * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * - * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR - * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, - * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -#ifndef _FAX3_ -#define _FAX3_ -/* - * TIFF Library. - * - * CCITT Group 3 (T.4) and Group 4 (T.6) Decompression Support. - * - * Decoder support is derived, with permission, from the code - * in Frank Cringle's viewfax program; - * Copyright (C) 1990, 1995 Frank D. Cringle. - */ -#include "tiff.h" - -/* - * To override the default routine used to image decoded - * spans one can use the pseduo tag TIFFTAG_FAXFILLFUNC. - * The routine must have the type signature given below; - * for example: - * - * fillruns(unsigned char* buf, uint32* runs, uint32* erun, uint32 lastx) - * - * where buf is place to set the bits, runs is the array of b&w run - * lengths (white then black), erun is the last run in the array, and - * lastx is the width of the row in pixels. Fill routines can assume - * the run array has room for at least lastx runs and can overwrite - * data in the run array as needed (e.g. to append zero runs to bring - * the count up to a nice multiple). - */ -typedef void (*TIFFFaxFillFunc)(unsigned char*, uint32*, uint32*, uint32); - -/* - * The default run filler; made external for other decoders. - */ -#if defined(__cplusplus) -extern "C" { -#endif -extern void _TIFFFax3fillruns(unsigned char*, uint32*, uint32*, uint32); -#if defined(__cplusplus) -} -#endif - - -/* finite state machine codes */ -#define S_Null 0 -#define S_Pass 1 -#define S_Horiz 2 -#define S_V0 3 -#define S_VR 4 -#define S_VL 5 -#define S_Ext 6 -#define S_TermW 7 -#define S_TermB 8 -#define S_MakeUpW 9 -#define S_MakeUpB 10 -#define S_MakeUp 11 -#define S_EOL 12 - -typedef struct { /* state table entry */ - unsigned char State; /* see above */ - unsigned char Width; /* width of code in bits */ - uint32 Param; /* unsigned 32-bit run length in bits */ -} TIFFFaxTabEnt; - -extern const TIFFFaxTabEnt TIFFFaxMainTable[]; -extern const TIFFFaxTabEnt TIFFFaxWhiteTable[]; -extern const TIFFFaxTabEnt TIFFFaxBlackTable[]; - -/* - * The following macros define the majority of the G3/G4 decoder - * algorithm using the state tables defined elsewhere. To build - * a decoder you need some setup code and some glue code. Note - * that you may also need/want to change the way the NeedBits* - * macros get input data if, for example, you know the data to be - * decoded is properly aligned and oriented (doing so before running - * the decoder can be a big performance win). - * - * Consult the decoder in the TIFF library for an idea of what you - * need to define and setup to make use of these definitions. - * - * NB: to enable a debugging version of these macros define FAX3_DEBUG - * before including this file. Trace output goes to stdout. - */ - -#ifndef EndOfData -#define EndOfData() (cp >= ep) -#endif -/* - * Need <=8 or <=16 bits of input data. Unlike viewfax we - * cannot use/assume a word-aligned, properly bit swizzled - * input data set because data may come from an arbitrarily - * aligned, read-only source such as a memory-mapped file. - * Note also that the viewfax decoder does not check for - * running off the end of the input data buffer. This is - * possible for G3-encoded data because it prescans the input - * data to count EOL markers, but can cause problems for G4 - * data. In any event, we don't prescan and must watch for - * running out of data since we can't permit the library to - * scan past the end of the input data buffer. - * - * Finally, note that we must handle remaindered data at the end - * of a strip specially. The coder asks for a fixed number of - * bits when scanning for the next code. This may be more bits - * than are actually present in the data stream. If we appear - * to run out of data but still have some number of valid bits - * remaining then we makeup the requested amount with zeros and - * return successfully. If the returned data is incorrect then - * we should be called again and get a premature EOF error; - * otherwise we should get the right answer. - */ -#ifndef NeedBits8 -#define NeedBits8(n,eoflab) do { \ - if (BitsAvail < (n)) { \ - if (EndOfData()) { \ - if (BitsAvail == 0) /* no valid bits */ \ - goto eoflab; \ - BitsAvail = (n); /* pad with zeros */ \ - } else { \ - BitAcc |= ((uint32) bitmap[*cp++])<>= (n); \ -} while (0) - -#ifdef FAX3_DEBUG -static const char* StateNames[] = { - "Null ", - "Pass ", - "Horiz ", - "V0 ", - "VR ", - "VL ", - "Ext ", - "TermW ", - "TermB ", - "MakeUpW", - "MakeUpB", - "MakeUp ", - "EOL ", -}; -#define DEBUG_SHOW putchar(BitAcc & (1 << t) ? '1' : '0') -#define LOOKUP8(wid,tab,eoflab) do { \ - int t; \ - NeedBits8(wid,eoflab); \ - TabEnt = tab + GetBits(wid); \ - printf("%08lX/%d: %s%5d\t", (long) BitAcc, BitsAvail, \ - StateNames[TabEnt->State], TabEnt->Param); \ - for (t = 0; t < TabEnt->Width; t++) \ - DEBUG_SHOW; \ - putchar('\n'); \ - fflush(stdout); \ - ClrBits(TabEnt->Width); \ -} while (0) -#define LOOKUP16(wid,tab,eoflab) do { \ - int t; \ - NeedBits16(wid,eoflab); \ - TabEnt = tab + GetBits(wid); \ - printf("%08lX/%d: %s%5d\t", (long) BitAcc, BitsAvail, \ - StateNames[TabEnt->State], TabEnt->Param); \ - for (t = 0; t < TabEnt->Width; t++) \ - DEBUG_SHOW; \ - putchar('\n'); \ - fflush(stdout); \ - ClrBits(TabEnt->Width); \ -} while (0) - -#define SETVALUE(x) do { \ - *pa++ = RunLength + (x); \ - printf("SETVALUE: %d\t%d\n", RunLength + (x), a0); \ - a0 += x; \ - RunLength = 0; \ -} while (0) -#else -#define LOOKUP8(wid,tab,eoflab) do { \ - NeedBits8(wid,eoflab); \ - TabEnt = tab + GetBits(wid); \ - ClrBits(TabEnt->Width); \ -} while (0) -#define LOOKUP16(wid,tab,eoflab) do { \ - NeedBits16(wid,eoflab); \ - TabEnt = tab + GetBits(wid); \ - ClrBits(TabEnt->Width); \ -} while (0) - -/* - * Append a run to the run length array for the - * current row and reset decoding state. - */ -#define SETVALUE(x) do { \ - *pa++ = RunLength + (x); \ - a0 += (x); \ - RunLength = 0; \ -} while (0) -#endif - -/* - * Synchronize input decoding at the start of each - * row by scanning for an EOL (if appropriate) and - * skipping any trash data that might be present - * after a decoding error. Note that the decoding - * done elsewhere that recognizes an EOL only consumes - * 11 consecutive zero bits. This means that if EOLcnt - * is non-zero then we still need to scan for the final flag - * bit that is part of the EOL code. - */ -#define SYNC_EOL(eoflab) do { \ - if (EOLcnt == 0) { \ - for (;;) { \ - NeedBits16(11,eoflab); \ - if (GetBits(11) == 0) \ - break; \ - ClrBits(1); \ - } \ - } \ - for (;;) { \ - NeedBits8(8,eoflab); \ - if (GetBits(8)) \ - break; \ - ClrBits(8); \ - } \ - while (GetBits(1) == 0) \ - ClrBits(1); \ - ClrBits(1); /* EOL bit */ \ - EOLcnt = 0; /* reset EOL counter/flag */ \ -} while (0) - -/* - * Cleanup the array of runs after decoding a row. - * We adjust final runs to insure the user buffer is not - * overwritten and/or undecoded area is white filled. - */ -#define CLEANUP_RUNS() do { \ - if (RunLength) \ - SETVALUE(0); \ - if (a0 != lastx) { \ - badlength(a0, lastx); \ - while (a0 > lastx && pa > thisrun) \ - a0 -= *--pa; \ - if (a0 < lastx) { \ - if (a0 < 0) \ - a0 = 0; \ - if ((pa-thisrun)&1) \ - SETVALUE(0); \ - SETVALUE(lastx - a0); \ - } else if (a0 > lastx) { \ - SETVALUE(lastx); \ - SETVALUE(0); \ - } \ - } \ -} while (0) - -/* - * Decode a line of 1D-encoded data. - * - * The line expanders are written as macros so that they can be reused - * but still have direct access to the local variables of the "calling" - * function. - * - * Note that unlike the original version we have to explicitly test for - * a0 >= lastx after each black/white run is decoded. This is because - * the original code depended on the input data being zero-padded to - * insure the decoder recognized an EOL before running out of data. - */ -#define EXPAND1D(eoflab) do { \ - for (;;) { \ - for (;;) { \ - LOOKUP16(12, TIFFFaxWhiteTable, eof1d); \ - switch (TabEnt->State) { \ - case S_EOL: \ - EOLcnt = 1; \ - goto done1d; \ - case S_TermW: \ - SETVALUE(TabEnt->Param); \ - goto doneWhite1d; \ - case S_MakeUpW: \ - case S_MakeUp: \ - a0 += TabEnt->Param; \ - RunLength += TabEnt->Param; \ - break; \ - default: \ - unexpected("WhiteTable", a0); \ - goto done1d; \ - } \ - } \ - doneWhite1d: \ - if (a0 >= lastx) \ - goto done1d; \ - for (;;) { \ - LOOKUP16(13, TIFFFaxBlackTable, eof1d); \ - switch (TabEnt->State) { \ - case S_EOL: \ - EOLcnt = 1; \ - goto done1d; \ - case S_TermB: \ - SETVALUE(TabEnt->Param); \ - goto doneBlack1d; \ - case S_MakeUpB: \ - case S_MakeUp: \ - a0 += TabEnt->Param; \ - RunLength += TabEnt->Param; \ - break; \ - default: \ - unexpected("BlackTable", a0); \ - goto done1d; \ - } \ - } \ - doneBlack1d: \ - if (a0 >= lastx) \ - goto done1d; \ - if( *(pa-1) == 0 && *(pa-2) == 0 ) \ - pa -= 2; \ - } \ -eof1d: \ - prematureEOF(a0); \ - CLEANUP_RUNS(); \ - goto eoflab; \ -done1d: \ - CLEANUP_RUNS(); \ -} while (0) - -/* - * Update the value of b1 using the array - * of runs for the reference line. - */ -#define CHECK_b1 do { \ - if (pa != thisrun) while (b1 <= a0 && b1 < lastx) { \ - b1 += pb[0] + pb[1]; \ - pb += 2; \ - } \ -} while (0) - -/* - * Expand a row of 2D-encoded data. - */ -#define EXPAND2D(eoflab) do { \ - while (a0 < lastx) { \ - LOOKUP8(7, TIFFFaxMainTable, eof2d); \ - switch (TabEnt->State) { \ - case S_Pass: \ - CHECK_b1; \ - b1 += *pb++; \ - RunLength += b1 - a0; \ - a0 = b1; \ - b1 += *pb++; \ - break; \ - case S_Horiz: \ - if ((pa-thisrun)&1) { \ - for (;;) { /* black first */ \ - LOOKUP16(13, TIFFFaxBlackTable, eof2d); \ - switch (TabEnt->State) { \ - case S_TermB: \ - SETVALUE(TabEnt->Param); \ - goto doneWhite2da; \ - case S_MakeUpB: \ - case S_MakeUp: \ - a0 += TabEnt->Param; \ - RunLength += TabEnt->Param; \ - break; \ - default: \ - goto badBlack2d; \ - } \ - } \ - doneWhite2da:; \ - for (;;) { /* then white */ \ - LOOKUP16(12, TIFFFaxWhiteTable, eof2d); \ - switch (TabEnt->State) { \ - case S_TermW: \ - SETVALUE(TabEnt->Param); \ - goto doneBlack2da; \ - case S_MakeUpW: \ - case S_MakeUp: \ - a0 += TabEnt->Param; \ - RunLength += TabEnt->Param; \ - break; \ - default: \ - goto badWhite2d; \ - } \ - } \ - doneBlack2da:; \ - } else { \ - for (;;) { /* white first */ \ - LOOKUP16(12, TIFFFaxWhiteTable, eof2d); \ - switch (TabEnt->State) { \ - case S_TermW: \ - SETVALUE(TabEnt->Param); \ - goto doneWhite2db; \ - case S_MakeUpW: \ - case S_MakeUp: \ - a0 += TabEnt->Param; \ - RunLength += TabEnt->Param; \ - break; \ - default: \ - goto badWhite2d; \ - } \ - } \ - doneWhite2db:; \ - for (;;) { /* then black */ \ - LOOKUP16(13, TIFFFaxBlackTable, eof2d); \ - switch (TabEnt->State) { \ - case S_TermB: \ - SETVALUE(TabEnt->Param); \ - goto doneBlack2db; \ - case S_MakeUpB: \ - case S_MakeUp: \ - a0 += TabEnt->Param; \ - RunLength += TabEnt->Param; \ - break; \ - default: \ - goto badBlack2d; \ - } \ - } \ - doneBlack2db:; \ - } \ - CHECK_b1; \ - break; \ - case S_V0: \ - CHECK_b1; \ - SETVALUE(b1 - a0); \ - b1 += *pb++; \ - break; \ - case S_VR: \ - CHECK_b1; \ - SETVALUE(b1 - a0 + TabEnt->Param); \ - b1 += *pb++; \ - break; \ - case S_VL: \ - CHECK_b1; \ - SETVALUE(b1 - a0 - TabEnt->Param); \ - b1 -= *--pb; \ - break; \ - case S_Ext: \ - *pa++ = lastx - a0; \ - extension(a0); \ - goto eol2d; \ - case S_EOL: \ - *pa++ = lastx - a0; \ - NeedBits8(4,eof2d); \ - if (GetBits(4)) \ - unexpected("EOL", a0); \ - ClrBits(4); \ - EOLcnt = 1; \ - goto eol2d; \ - default: \ - badMain2d: \ - unexpected("MainTable", a0); \ - goto eol2d; \ - badBlack2d: \ - unexpected("BlackTable", a0); \ - goto eol2d; \ - badWhite2d: \ - unexpected("WhiteTable", a0); \ - goto eol2d; \ - eof2d: \ - prematureEOF(a0); \ - CLEANUP_RUNS(); \ - goto eoflab; \ - } \ - } \ - if (RunLength) { \ - if (RunLength + a0 < lastx) { \ - /* expect a final V0 */ \ - NeedBits8(1,eof2d); \ - if (!GetBits(1)) \ - goto badMain2d; \ - ClrBits(1); \ - } \ - SETVALUE(0); \ - } \ -eol2d: \ - CLEANUP_RUNS(); \ -} while (0) -#endif /* _FAX3_ */ -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/reactos/dll/3rdparty/libtiff/tif_predict.h b/reactos/dll/3rdparty/libtiff/tif_predict.h deleted file mode 100644 index da0ad9892b0..00000000000 --- a/reactos/dll/3rdparty/libtiff/tif_predict.h +++ /dev/null @@ -1,77 +0,0 @@ -/* $Id: tif_predict.h,v 1.3.2.2 2010-06-08 18:50:42 bfriesen Exp $ */ - -/* - * Copyright (c) 1995-1997 Sam Leffler - * Copyright (c) 1995-1997 Silicon Graphics, Inc. - * - * Permission to use, copy, modify, distribute, and sell this software and - * its documentation for any purpose is hereby granted without fee, provided - * that (i) the above copyright notices and this permission notice appear in - * all copies of the software and related documentation, and (ii) the names of - * Sam Leffler and Silicon Graphics may not be used in any advertising or - * publicity relating to the software without the specific, prior written - * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * - * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR - * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, - * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -#ifndef _TIFFPREDICT_ -#define _TIFFPREDICT_ -/* - * ``Library-private'' Support for the Predictor Tag - */ - -/* - * Codecs that want to support the Predictor tag must place - * this structure first in their private state block so that - * the predictor code can cast tif_data to find its state. - */ -typedef struct { - int predictor; /* predictor tag value */ - int stride; /* sample stride over data */ - tsize_t rowsize; /* tile/strip row size */ - - TIFFCodeMethod encoderow; /* parent codec encode/decode row */ - TIFFCodeMethod encodestrip; /* parent codec encode/decode strip */ - TIFFCodeMethod encodetile; /* parent codec encode/decode tile */ - TIFFPostMethod encodepfunc; /* horizontal differencer */ - - TIFFCodeMethod decoderow; /* parent codec encode/decode row */ - TIFFCodeMethod decodestrip; /* parent codec encode/decode strip */ - TIFFCodeMethod decodetile; /* parent codec encode/decode tile */ - TIFFPostMethod decodepfunc; /* horizontal accumulator */ - - TIFFVGetMethod vgetparent; /* super-class method */ - TIFFVSetMethod vsetparent; /* super-class method */ - TIFFPrintMethod printdir; /* super-class method */ - TIFFBoolMethod setupdecode; /* super-class method */ - TIFFBoolMethod setupencode; /* super-class method */ -} TIFFPredictorState; - -#if defined(__cplusplus) -extern "C" { -#endif -extern int TIFFPredictorInit(TIFF*); -extern int TIFFPredictorCleanup(TIFF*); -#if defined(__cplusplus) -} -#endif -#endif /* _TIFFPREDICT_ */ - -/* vim: set ts=8 sts=8 sw=8 noet: */ -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/reactos/dll/3rdparty/libtiff/tiff.h b/reactos/dll/3rdparty/libtiff/tiff.h deleted file mode 100644 index 0d4ab9f819f..00000000000 --- a/reactos/dll/3rdparty/libtiff/tiff.h +++ /dev/null @@ -1,654 +0,0 @@ -/* $Id: tiff.h,v 1.43.2.1 2010-06-08 18:50:43 bfriesen Exp $ */ - -/* - * Copyright (c) 1988-1997 Sam Leffler - * Copyright (c) 1991-1997 Silicon Graphics, Inc. - * - * Permission to use, copy, modify, distribute, and sell this software and - * its documentation for any purpose is hereby granted without fee, provided - * that (i) the above copyright notices and this permission notice appear in - * all copies of the software and related documentation, and (ii) the names of - * Sam Leffler and Silicon Graphics may not be used in any advertising or - * publicity relating to the software without the specific, prior written - * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * - * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR - * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, - * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -#ifndef _TIFF_ -#define _TIFF_ - -#include "tiffconf.h" - -/* - * Tag Image File Format (TIFF) - * - * Based on Rev 6.0 from: - * Developer's Desk - * Aldus Corporation - * 411 First Ave. South - * Suite 200 - * Seattle, WA 98104 - * 206-622-5500 - * - * (http://partners.adobe.com/asn/developer/PDFS/TN/TIFF6.pdf) - * - * For Big TIFF design notes see the following link - * http://www.remotesensing.org/libtiff/bigtiffdesign.html - */ -#define TIFF_VERSION 42 -#define TIFF_BIGTIFF_VERSION 43 - -#define TIFF_BIGENDIAN 0x4d4d -#define TIFF_LITTLEENDIAN 0x4949 -#define MDI_LITTLEENDIAN 0x5045 -#define MDI_BIGENDIAN 0x4550 -/* - * Intrinsic data types required by the file format: - * - * 8-bit quantities int8/uint8 - * 16-bit quantities int16/uint16 - * 32-bit quantities int32/uint32 - * strings unsigned char* - */ - -#ifndef HAVE_INT8 -typedef signed char int8; /* NB: non-ANSI compilers may not grok */ -#endif -typedef unsigned char uint8; -#ifndef HAVE_INT16 -typedef short int16; -#endif -typedef unsigned short uint16; /* sizeof (uint16) must == 2 */ -#if SIZEOF_INT == 4 -#ifndef HAVE_INT32 -typedef int int32; -#endif -typedef unsigned int uint32; /* sizeof (uint32) must == 4 */ -#elif SIZEOF_LONG == 4 -#ifndef HAVE_INT32 -typedef long int32; -#endif -typedef unsigned long uint32; /* sizeof (uint32) must == 4 */ -#endif - -/* For TIFFReassignTagToIgnore */ -enum TIFFIgnoreSense /* IGNORE tag table */ -{ - TIS_STORE, - TIS_EXTRACT, - TIS_EMPTY -}; - -/* - * TIFF header. - */ -typedef struct { - uint16 tiff_magic; /* magic number (defines byte order) */ -#define TIFF_MAGIC_SIZE 2 - uint16 tiff_version; /* TIFF version number */ -#define TIFF_VERSION_SIZE 2 - uint32 tiff_diroff; /* byte offset to first directory */ -#define TIFF_DIROFFSET_SIZE 4 -} TIFFHeader; - - -/* - * TIFF Image File Directories are comprised of a table of field - * descriptors of the form shown below. The table is sorted in - * ascending order by tag. The values associated with each entry are - * disjoint and may appear anywhere in the file (so long as they are - * placed on a word boundary). - * - * If the value is 4 bytes or less, then it is placed in the offset - * field to save space. If the value is less than 4 bytes, it is - * left-justified in the offset field. - */ -typedef struct { - uint16 tdir_tag; /* see below */ - uint16 tdir_type; /* data type; see below */ - uint32 tdir_count; /* number of items; length in spec */ - uint32 tdir_offset; /* byte offset to field data */ -} TIFFDirEntry; - -/* - * NB: In the comments below, - * - items marked with a + are obsoleted by revision 5.0, - * - items marked with a ! are introduced in revision 6.0. - * - items marked with a % are introduced post revision 6.0. - * - items marked with a $ are obsoleted by revision 6.0. - * - items marked with a & are introduced by Adobe DNG specification. - */ - -/* - * Tag data type information. - * - * Note: RATIONALs are the ratio of two 32-bit integer values. - */ -typedef enum { - TIFF_NOTYPE = 0, /* placeholder */ - TIFF_BYTE = 1, /* 8-bit unsigned integer */ - TIFF_ASCII = 2, /* 8-bit bytes w/ last byte null */ - TIFF_SHORT = 3, /* 16-bit unsigned integer */ - TIFF_LONG = 4, /* 32-bit unsigned integer */ - TIFF_RATIONAL = 5, /* 64-bit unsigned fraction */ - TIFF_SBYTE = 6, /* !8-bit signed integer */ - TIFF_UNDEFINED = 7, /* !8-bit untyped data */ - TIFF_SSHORT = 8, /* !16-bit signed integer */ - TIFF_SLONG = 9, /* !32-bit signed integer */ - TIFF_SRATIONAL = 10, /* !64-bit signed fraction */ - TIFF_FLOAT = 11, /* !32-bit IEEE floating point */ - TIFF_DOUBLE = 12, /* !64-bit IEEE floating point */ - TIFF_IFD = 13 /* %32-bit unsigned integer (offset) */ -} TIFFDataType; - -/* - * TIFF Tag Definitions. - */ -#define TIFFTAG_SUBFILETYPE 254 /* subfile data descriptor */ -#define FILETYPE_REDUCEDIMAGE 0x1 /* reduced resolution version */ -#define FILETYPE_PAGE 0x2 /* one page of many */ -#define FILETYPE_MASK 0x4 /* transparency mask */ -#define TIFFTAG_OSUBFILETYPE 255 /* +kind of data in subfile */ -#define OFILETYPE_IMAGE 1 /* full resolution image data */ -#define OFILETYPE_REDUCEDIMAGE 2 /* reduced size image data */ -#define OFILETYPE_PAGE 3 /* one page of many */ -#define TIFFTAG_IMAGEWIDTH 256 /* image width in pixels */ -#define TIFFTAG_IMAGELENGTH 257 /* image height in pixels */ -#define TIFFTAG_BITSPERSAMPLE 258 /* bits per channel (sample) */ -#define TIFFTAG_COMPRESSION 259 /* data compression technique */ -#define COMPRESSION_NONE 1 /* dump mode */ -#define COMPRESSION_CCITTRLE 2 /* CCITT modified Huffman RLE */ -#define COMPRESSION_CCITTFAX3 3 /* CCITT Group 3 fax encoding */ -#define COMPRESSION_CCITT_T4 3 /* CCITT T.4 (TIFF 6 name) */ -#define COMPRESSION_CCITTFAX4 4 /* CCITT Group 4 fax encoding */ -#define COMPRESSION_CCITT_T6 4 /* CCITT T.6 (TIFF 6 name) */ -#define COMPRESSION_LZW 5 /* Lempel-Ziv & Welch */ -#define COMPRESSION_OJPEG 6 /* !6.0 JPEG */ -#define COMPRESSION_JPEG 7 /* %JPEG DCT compression */ -#define COMPRESSION_NEXT 32766 /* NeXT 2-bit RLE */ -#define COMPRESSION_CCITTRLEW 32771 /* #1 w/ word alignment */ -#define COMPRESSION_PACKBITS 32773 /* Macintosh RLE */ -#define COMPRESSION_THUNDERSCAN 32809 /* ThunderScan RLE */ -/* codes 32895-32898 are reserved for ANSI IT8 TIFF/IT */ -#define COMPRESSION_DCS 32947 /* Kodak DCS encoding */ -#define COMPRESSION_JBIG 34661 /* ISO JBIG */ -#define COMPRESSION_SGILOG 34676 /* SGI Log Luminance RLE */ -#define COMPRESSION_SGILOG24 34677 /* SGI Log 24-bit packed */ -#define COMPRESSION_JP2000 34712 /* Leadtools JPEG2000 */ -#define TIFFTAG_PHOTOMETRIC 262 /* photometric interpretation */ -#define PHOTOMETRIC_MINISWHITE 0 /* min value is white */ -#define PHOTOMETRIC_MINISBLACK 1 /* min value is black */ -#define PHOTOMETRIC_RGB 2 /* RGB color model */ -#define PHOTOMETRIC_PALETTE 3 /* color map indexed */ -#define PHOTOMETRIC_MASK 4 /* $holdout mask */ -#define PHOTOMETRIC_SEPARATED 5 /* !color separations */ -#define PHOTOMETRIC_YCBCR 6 /* !CCIR 601 */ -#define PHOTOMETRIC_CIELAB 8 /* !1976 CIE L*a*b* */ -#define PHOTOMETRIC_ICCLAB 9 /* ICC L*a*b* [Adobe TIFF Technote 4] */ -#define PHOTOMETRIC_ITULAB 10 /* ITU L*a*b* */ -#define PHOTOMETRIC_LOGL 32844 /* CIE Log2(L) */ -#define PHOTOMETRIC_LOGLUV 32845 /* CIE Log2(L) (u',v') */ -#define TIFFTAG_THRESHHOLDING 263 /* +thresholding used on data */ -#define THRESHHOLD_BILEVEL 1 /* b&w art scan */ -#define THRESHHOLD_HALFTONE 2 /* or dithered scan */ -#define THRESHHOLD_ERRORDIFFUSE 3 /* usually floyd-steinberg */ -#define TIFFTAG_CELLWIDTH 264 /* +dithering matrix width */ -#define TIFFTAG_CELLLENGTH 265 /* +dithering matrix height */ -#define TIFFTAG_FILLORDER 266 /* data order within a byte */ -#define FILLORDER_MSB2LSB 1 /* most significant -> least */ -#define FILLORDER_LSB2MSB 2 /* least significant -> most */ -#define TIFFTAG_DOCUMENTNAME 269 /* name of doc. image is from */ -#define TIFFTAG_IMAGEDESCRIPTION 270 /* info about image */ -#define TIFFTAG_MAKE 271 /* scanner manufacturer name */ -#define TIFFTAG_MODEL 272 /* scanner model name/number */ -#define TIFFTAG_STRIPOFFSETS 273 /* offsets to data strips */ -#define TIFFTAG_ORIENTATION 274 /* +image orientation */ -#define ORIENTATION_TOPLEFT 1 /* row 0 top, col 0 lhs */ -#define ORIENTATION_TOPRIGHT 2 /* row 0 top, col 0 rhs */ -#define ORIENTATION_BOTRIGHT 3 /* row 0 bottom, col 0 rhs */ -#define ORIENTATION_BOTLEFT 4 /* row 0 bottom, col 0 lhs */ -#define ORIENTATION_LEFTTOP 5 /* row 0 lhs, col 0 top */ -#define ORIENTATION_RIGHTTOP 6 /* row 0 rhs, col 0 top */ -#define ORIENTATION_RIGHTBOT 7 /* row 0 rhs, col 0 bottom */ -#define ORIENTATION_LEFTBOT 8 /* row 0 lhs, col 0 bottom */ -#define TIFFTAG_SAMPLESPERPIXEL 277 /* samples per pixel */ -#define TIFFTAG_ROWSPERSTRIP 278 /* rows per strip of data */ -#define TIFFTAG_STRIPBYTECOUNTS 279 /* bytes counts for strips */ -#define TIFFTAG_MINSAMPLEVALUE 280 /* +minimum sample value */ -#define TIFFTAG_MAXSAMPLEVALUE 281 /* +maximum sample value */ -#define TIFFTAG_XRESOLUTION 282 /* pixels/resolution in x */ -#define TIFFTAG_YRESOLUTION 283 /* pixels/resolution in y */ -#define TIFFTAG_PLANARCONFIG 284 /* storage organization */ -#define PLANARCONFIG_CONTIG 1 /* single image plane */ -#define PLANARCONFIG_SEPARATE 2 /* separate planes of data */ -#define TIFFTAG_PAGENAME 285 /* page name image is from */ -#define TIFFTAG_XPOSITION 286 /* x page offset of image lhs */ -#define TIFFTAG_YPOSITION 287 /* y page offset of image lhs */ -#define TIFFTAG_FREEOFFSETS 288 /* +byte offset to free block */ -#define TIFFTAG_FREEBYTECOUNTS 289 /* +sizes of free blocks */ -#define TIFFTAG_GRAYRESPONSEUNIT 290 /* $gray scale curve accuracy */ -#define GRAYRESPONSEUNIT_10S 1 /* tenths of a unit */ -#define GRAYRESPONSEUNIT_100S 2 /* hundredths of a unit */ -#define GRAYRESPONSEUNIT_1000S 3 /* thousandths of a unit */ -#define GRAYRESPONSEUNIT_10000S 4 /* ten-thousandths of a unit */ -#define GRAYRESPONSEUNIT_100000S 5 /* hundred-thousandths */ -#define TIFFTAG_GRAYRESPONSECURVE 291 /* $gray scale response curve */ -#define TIFFTAG_GROUP3OPTIONS 292 /* 32 flag bits */ -#define TIFFTAG_T4OPTIONS 292 /* TIFF 6.0 proper name alias */ -#define GROUP3OPT_2DENCODING 0x1 /* 2-dimensional coding */ -#define GROUP3OPT_UNCOMPRESSED 0x2 /* data not compressed */ -#define GROUP3OPT_FILLBITS 0x4 /* fill to byte boundary */ -#define TIFFTAG_GROUP4OPTIONS 293 /* 32 flag bits */ -#define TIFFTAG_T6OPTIONS 293 /* TIFF 6.0 proper name */ -#define GROUP4OPT_UNCOMPRESSED 0x2 /* data not compressed */ -#define TIFFTAG_RESOLUTIONUNIT 296 /* units of resolutions */ -#define RESUNIT_NONE 1 /* no meaningful units */ -#define RESUNIT_INCH 2 /* english */ -#define RESUNIT_CENTIMETER 3 /* metric */ -#define TIFFTAG_PAGENUMBER 297 /* page numbers of multi-page */ -#define TIFFTAG_COLORRESPONSEUNIT 300 /* $color curve accuracy */ -#define COLORRESPONSEUNIT_10S 1 /* tenths of a unit */ -#define COLORRESPONSEUNIT_100S 2 /* hundredths of a unit */ -#define COLORRESPONSEUNIT_1000S 3 /* thousandths of a unit */ -#define COLORRESPONSEUNIT_10000S 4 /* ten-thousandths of a unit */ -#define COLORRESPONSEUNIT_100000S 5 /* hundred-thousandths */ -#define TIFFTAG_TRANSFERFUNCTION 301 /* !colorimetry info */ -#define TIFFTAG_SOFTWARE 305 /* name & release */ -#define TIFFTAG_DATETIME 306 /* creation date and time */ -#define TIFFTAG_ARTIST 315 /* creator of image */ -#define TIFFTAG_HOSTCOMPUTER 316 /* machine where created */ -#define TIFFTAG_PREDICTOR 317 /* prediction scheme w/ LZW */ -#define PREDICTOR_NONE 1 /* no prediction scheme used */ -#define PREDICTOR_HORIZONTAL 2 /* horizontal differencing */ -#define PREDICTOR_FLOATINGPOINT 3 /* floating point predictor */ -#define TIFFTAG_WHITEPOINT 318 /* image white point */ -#define TIFFTAG_PRIMARYCHROMATICITIES 319 /* !primary chromaticities */ -#define TIFFTAG_COLORMAP 320 /* RGB map for pallette image */ -#define TIFFTAG_HALFTONEHINTS 321 /* !highlight+shadow info */ -#define TIFFTAG_TILEWIDTH 322 /* !tile width in pixels */ -#define TIFFTAG_TILELENGTH 323 /* !tile height in pixels */ -#define TIFFTAG_TILEOFFSETS 324 /* !offsets to data tiles */ -#define TIFFTAG_TILEBYTECOUNTS 325 /* !byte counts for tiles */ -#define TIFFTAG_BADFAXLINES 326 /* lines w/ wrong pixel count */ -#define TIFFTAG_CLEANFAXDATA 327 /* regenerated line info */ -#define CLEANFAXDATA_CLEAN 0 /* no errors detected */ -#define CLEANFAXDATA_REGENERATED 1 /* receiver regenerated lines */ -#define CLEANFAXDATA_UNCLEAN 2 /* uncorrected errors exist */ -#define TIFFTAG_CONSECUTIVEBADFAXLINES 328 /* max consecutive bad lines */ -#define TIFFTAG_SUBIFD 330 /* subimage descriptors */ -#define TIFFTAG_INKSET 332 /* !inks in separated image */ -#define INKSET_CMYK 1 /* !cyan-magenta-yellow-black color */ -#define INKSET_MULTIINK 2 /* !multi-ink or hi-fi color */ -#define TIFFTAG_INKNAMES 333 /* !ascii names of inks */ -#define TIFFTAG_NUMBEROFINKS 334 /* !number of inks */ -#define TIFFTAG_DOTRANGE 336 /* !0% and 100% dot codes */ -#define TIFFTAG_TARGETPRINTER 337 /* !separation target */ -#define TIFFTAG_EXTRASAMPLES 338 /* !info about extra samples */ -#define EXTRASAMPLE_UNSPECIFIED 0 /* !unspecified data */ -#define EXTRASAMPLE_ASSOCALPHA 1 /* !associated alpha data */ -#define EXTRASAMPLE_UNASSALPHA 2 /* !unassociated alpha data */ -#define TIFFTAG_SAMPLEFORMAT 339 /* !data sample format */ -#define SAMPLEFORMAT_UINT 1 /* !unsigned integer data */ -#define SAMPLEFORMAT_INT 2 /* !signed integer data */ -#define SAMPLEFORMAT_IEEEFP 3 /* !IEEE floating point data */ -#define SAMPLEFORMAT_VOID 4 /* !untyped data */ -#define SAMPLEFORMAT_COMPLEXINT 5 /* !complex signed int */ -#define SAMPLEFORMAT_COMPLEXIEEEFP 6 /* !complex ieee floating */ -#define TIFFTAG_SMINSAMPLEVALUE 340 /* !variable MinSampleValue */ -#define TIFFTAG_SMAXSAMPLEVALUE 341 /* !variable MaxSampleValue */ -#define TIFFTAG_CLIPPATH 343 /* %ClipPath - [Adobe TIFF technote 2] */ -#define TIFFTAG_XCLIPPATHUNITS 344 /* %XClipPathUnits - [Adobe TIFF technote 2] */ -#define TIFFTAG_YCLIPPATHUNITS 345 /* %YClipPathUnits - [Adobe TIFF technote 2] */ -#define TIFFTAG_INDEXED 346 /* %Indexed - [Adobe TIFF Technote 3] */ -#define TIFFTAG_JPEGTABLES 347 /* %JPEG table stream */ -#define TIFFTAG_OPIPROXY 351 /* %OPI Proxy [Adobe TIFF technote] */ -/* - * Tags 512-521 are obsoleted by Technical Note #2 which specifies a - * revised JPEG-in-TIFF scheme. - */ -#define TIFFTAG_JPEGPROC 512 /* !JPEG processing algorithm */ -#define JPEGPROC_BASELINE 1 /* !baseline sequential */ -#define JPEGPROC_LOSSLESS 14 /* !Huffman coded lossless */ -#define TIFFTAG_JPEGIFOFFSET 513 /* !pointer to SOI marker */ -#define TIFFTAG_JPEGIFBYTECOUNT 514 /* !JFIF stream length */ -#define TIFFTAG_JPEGRESTARTINTERVAL 515 /* !restart interval length */ -#define TIFFTAG_JPEGLOSSLESSPREDICTORS 517 /* !lossless proc predictor */ -#define TIFFTAG_JPEGPOINTTRANSFORM 518 /* !lossless point transform */ -#define TIFFTAG_JPEGQTABLES 519 /* !Q matrice offsets */ -#define TIFFTAG_JPEGDCTABLES 520 /* !DCT table offsets */ -#define TIFFTAG_JPEGACTABLES 521 /* !AC coefficient offsets */ -#define TIFFTAG_YCBCRCOEFFICIENTS 529 /* !RGB -> YCbCr transform */ -#define TIFFTAG_YCBCRSUBSAMPLING 530 /* !YCbCr subsampling factors */ -#define TIFFTAG_YCBCRPOSITIONING 531 /* !subsample positioning */ -#define YCBCRPOSITION_CENTERED 1 /* !as in PostScript Level 2 */ -#define YCBCRPOSITION_COSITED 2 /* !as in CCIR 601-1 */ -#define TIFFTAG_REFERENCEBLACKWHITE 532 /* !colorimetry info */ -#define TIFFTAG_XMLPACKET 700 /* %XML packet - [Adobe XMP Specification, - January 2004 */ -#define TIFFTAG_OPIIMAGEID 32781 /* %OPI ImageID - [Adobe TIFF technote] */ -/* tags 32952-32956 are private tags registered to Island Graphics */ -#define TIFFTAG_REFPTS 32953 /* image reference points */ -#define TIFFTAG_REGIONTACKPOINT 32954 /* region-xform tack point */ -#define TIFFTAG_REGIONWARPCORNERS 32955 /* warp quadrilateral */ -#define TIFFTAG_REGIONAFFINE 32956 /* affine transformation mat */ -/* tags 32995-32999 are private tags registered to SGI */ -#define TIFFTAG_MATTEING 32995 /* $use ExtraSamples */ -#define TIFFTAG_DATATYPE 32996 /* $use SampleFormat */ -#define TIFFTAG_IMAGEDEPTH 32997 /* z depth of image */ -#define TIFFTAG_TILEDEPTH 32998 /* z depth/data tile */ -/* tags 33300-33309 are private tags registered to Pixar */ -/* - * TIFFTAG_PIXAR_IMAGEFULLWIDTH and TIFFTAG_PIXAR_IMAGEFULLLENGTH - * are set when an image has been cropped out of a larger image. - * They reflect the size of the original uncropped image. - * The TIFFTAG_XPOSITION and TIFFTAG_YPOSITION can be used - * to determine the position of the smaller image in the larger one. - */ -#define TIFFTAG_PIXAR_IMAGEFULLWIDTH 33300 /* full image size in x */ -#define TIFFTAG_PIXAR_IMAGEFULLLENGTH 33301 /* full image size in y */ - /* Tags 33302-33306 are used to identify special image modes and data - * used by Pixar's texture formats. - */ -#define TIFFTAG_PIXAR_TEXTUREFORMAT 33302 /* texture map format */ -#define TIFFTAG_PIXAR_WRAPMODES 33303 /* s & t wrap modes */ -#define TIFFTAG_PIXAR_FOVCOT 33304 /* cotan(fov) for env. maps */ -#define TIFFTAG_PIXAR_MATRIX_WORLDTOSCREEN 33305 -#define TIFFTAG_PIXAR_MATRIX_WORLDTOCAMERA 33306 -/* tag 33405 is a private tag registered to Eastman Kodak */ -#define TIFFTAG_WRITERSERIALNUMBER 33405 /* device serial number */ -/* tag 33432 is listed in the 6.0 spec w/ unknown ownership */ -#define TIFFTAG_COPYRIGHT 33432 /* copyright string */ -/* IPTC TAG from RichTIFF specifications */ -#define TIFFTAG_RICHTIFFIPTC 33723 -/* 34016-34029 are reserved for ANSI IT8 TIFF/IT */ -#define TIFFTAG_STONITS 37439 /* Sample value to Nits */ -/* tag 34929 is a private tag registered to FedEx */ -#define TIFFTAG_FEDEX_EDR 34929 /* unknown use */ -#define TIFFTAG_INTEROPERABILITYIFD 40965 /* Pointer to Interoperability private directory */ -/* Adobe Digital Negative (DNG) format tags */ -#define TIFFTAG_DNGVERSION 50706 /* &DNG version number */ -#define TIFFTAG_DNGBACKWARDVERSION 50707 /* &DNG compatibility version */ -#define TIFFTAG_UNIQUECAMERAMODEL 50708 /* &name for the camera model */ -#define TIFFTAG_LOCALIZEDCAMERAMODEL 50709 /* &localized camera model - name */ -#define TIFFTAG_CFAPLANECOLOR 50710 /* &CFAPattern->LinearRaw space - mapping */ -#define TIFFTAG_CFALAYOUT 50711 /* &spatial layout of the CFA */ -#define TIFFTAG_LINEARIZATIONTABLE 50712 /* &lookup table description */ -#define TIFFTAG_BLACKLEVELREPEATDIM 50713 /* &repeat pattern size for - the BlackLevel tag */ -#define TIFFTAG_BLACKLEVEL 50714 /* &zero light encoding level */ -#define TIFFTAG_BLACKLEVELDELTAH 50715 /* &zero light encoding level - differences (columns) */ -#define TIFFTAG_BLACKLEVELDELTAV 50716 /* &zero light encoding level - differences (rows) */ -#define TIFFTAG_WHITELEVEL 50717 /* &fully saturated encoding - level */ -#define TIFFTAG_DEFAULTSCALE 50718 /* &default scale factors */ -#define TIFFTAG_DEFAULTCROPORIGIN 50719 /* &origin of the final image - area */ -#define TIFFTAG_DEFAULTCROPSIZE 50720 /* &size of the final image - area */ -#define TIFFTAG_COLORMATRIX1 50721 /* &XYZ->reference color space - transformation matrix 1 */ -#define TIFFTAG_COLORMATRIX2 50722 /* &XYZ->reference color space - transformation matrix 2 */ -#define TIFFTAG_CAMERACALIBRATION1 50723 /* &calibration matrix 1 */ -#define TIFFTAG_CAMERACALIBRATION2 50724 /* &calibration matrix 2 */ -#define TIFFTAG_REDUCTIONMATRIX1 50725 /* &dimensionality reduction - matrix 1 */ -#define TIFFTAG_REDUCTIONMATRIX2 50726 /* &dimensionality reduction - matrix 2 */ -#define TIFFTAG_ANALOGBALANCE 50727 /* &gain applied the stored raw - values*/ -#define TIFFTAG_ASSHOTNEUTRAL 50728 /* &selected white balance in - linear reference space */ -#define TIFFTAG_ASSHOTWHITEXY 50729 /* &selected white balance in - x-y chromaticity - coordinates */ -#define TIFFTAG_BASELINEEXPOSURE 50730 /* &how much to move the zero - point */ -#define TIFFTAG_BASELINENOISE 50731 /* &relative noise level */ -#define TIFFTAG_BASELINESHARPNESS 50732 /* &relative amount of - sharpening */ -#define TIFFTAG_BAYERGREENSPLIT 50733 /* &how closely the values of - the green pixels in the - blue/green rows track the - values of the green pixels - in the red/green rows */ -#define TIFFTAG_LINEARRESPONSELIMIT 50734 /* &non-linear encoding range */ -#define TIFFTAG_CAMERASERIALNUMBER 50735 /* &camera's serial number */ -#define TIFFTAG_LENSINFO 50736 /* info about the lens */ -#define TIFFTAG_CHROMABLURRADIUS 50737 /* &chroma blur radius */ -#define TIFFTAG_ANTIALIASSTRENGTH 50738 /* &relative strength of the - camera's anti-alias filter */ -#define TIFFTAG_SHADOWSCALE 50739 /* &used by Adobe Camera Raw */ -#define TIFFTAG_DNGPRIVATEDATA 50740 /* &manufacturer's private data */ -#define TIFFTAG_MAKERNOTESAFETY 50741 /* &whether the EXIF MakerNote - tag is safe to preserve - along with the rest of the - EXIF data */ -#define TIFFTAG_CALIBRATIONILLUMINANT1 50778 /* &illuminant 1 */ -#define TIFFTAG_CALIBRATIONILLUMINANT2 50779 /* &illuminant 2 */ -#define TIFFTAG_BESTQUALITYSCALE 50780 /* &best quality multiplier */ -#define TIFFTAG_RAWDATAUNIQUEID 50781 /* &unique identifier for - the raw image data */ -#define TIFFTAG_ORIGINALRAWFILENAME 50827 /* &file name of the original - raw file */ -#define TIFFTAG_ORIGINALRAWFILEDATA 50828 /* &contents of the original - raw file */ -#define TIFFTAG_ACTIVEAREA 50829 /* &active (non-masked) pixels - of the sensor */ -#define TIFFTAG_MASKEDAREAS 50830 /* &list of coordinates - of fully masked pixels */ -#define TIFFTAG_ASSHOTICCPROFILE 50831 /* &these two tags used to */ -#define TIFFTAG_ASSHOTPREPROFILEMATRIX 50832 /* map cameras's color space - into ICC profile space */ -#define TIFFTAG_CURRENTICCPROFILE 50833 /* & */ -#define TIFFTAG_CURRENTPREPROFILEMATRIX 50834 /* & */ -/* tag 65535 is an undefined tag used by Eastman Kodak */ -#define TIFFTAG_DCSHUESHIFTVALUES 65535 /* hue shift correction data */ - -/* - * The following are ``pseudo tags'' that can be used to control - * codec-specific functionality. These tags are not written to file. - * Note that these values start at 0xffff+1 so that they'll never - * collide with Aldus-assigned tags. - * - * If you want your private pseudo tags ``registered'' (i.e. added to - * this file), please post a bug report via the tracking system at - * http://www.remotesensing.org/libtiff/bugs.html with the appropriate - * C definitions to add. - */ -#define TIFFTAG_FAXMODE 65536 /* Group 3/4 format control */ -#define FAXMODE_CLASSIC 0x0000 /* default, include RTC */ -#define FAXMODE_NORTC 0x0001 /* no RTC at end of data */ -#define FAXMODE_NOEOL 0x0002 /* no EOL code at end of row */ -#define FAXMODE_BYTEALIGN 0x0004 /* byte align row */ -#define FAXMODE_WORDALIGN 0x0008 /* word align row */ -#define FAXMODE_CLASSF FAXMODE_NORTC /* TIFF Class F */ -#define TIFFTAG_JPEGQUALITY 65537 /* Compression quality level */ -/* Note: quality level is on the IJG 0-100 scale. Default value is 75 */ -#define TIFFTAG_JPEGCOLORMODE 65538 /* Auto RGB<=>YCbCr convert? */ -#define JPEGCOLORMODE_RAW 0x0000 /* no conversion (default) */ -#define JPEGCOLORMODE_RGB 0x0001 /* do auto conversion */ -#define TIFFTAG_JPEGTABLESMODE 65539 /* What to put in JPEGTables */ -#define JPEGTABLESMODE_QUANT 0x0001 /* include quantization tbls */ -#define JPEGTABLESMODE_HUFF 0x0002 /* include Huffman tbls */ -/* Note: default is JPEGTABLESMODE_QUANT | JPEGTABLESMODE_HUFF */ -#define TIFFTAG_FAXFILLFUNC 65540 /* G3/G4 fill function */ -#define TIFFTAG_PIXARLOGDATAFMT 65549 /* PixarLogCodec I/O data sz */ -#define PIXARLOGDATAFMT_8BIT 0 /* regular u_char samples */ -#define PIXARLOGDATAFMT_8BITABGR 1 /* ABGR-order u_chars */ -#define PIXARLOGDATAFMT_11BITLOG 2 /* 11-bit log-encoded (raw) */ -#define PIXARLOGDATAFMT_12BITPICIO 3 /* as per PICIO (1.0==2048) */ -#define PIXARLOGDATAFMT_16BIT 4 /* signed short samples */ -#define PIXARLOGDATAFMT_FLOAT 5 /* IEEE float samples */ -/* 65550-65556 are allocated to Oceana Matrix */ -#define TIFFTAG_DCSIMAGERTYPE 65550 /* imager model & filter */ -#define DCSIMAGERMODEL_M3 0 /* M3 chip (1280 x 1024) */ -#define DCSIMAGERMODEL_M5 1 /* M5 chip (1536 x 1024) */ -#define DCSIMAGERMODEL_M6 2 /* M6 chip (3072 x 2048) */ -#define DCSIMAGERFILTER_IR 0 /* infrared filter */ -#define DCSIMAGERFILTER_MONO 1 /* monochrome filter */ -#define DCSIMAGERFILTER_CFA 2 /* color filter array */ -#define DCSIMAGERFILTER_OTHER 3 /* other filter */ -#define TIFFTAG_DCSINTERPMODE 65551 /* interpolation mode */ -#define DCSINTERPMODE_NORMAL 0x0 /* whole image, default */ -#define DCSINTERPMODE_PREVIEW 0x1 /* preview of image (384x256) */ -#define TIFFTAG_DCSBALANCEARRAY 65552 /* color balance values */ -#define TIFFTAG_DCSCORRECTMATRIX 65553 /* color correction values */ -#define TIFFTAG_DCSGAMMA 65554 /* gamma value */ -#define TIFFTAG_DCSTOESHOULDERPTS 65555 /* toe & shoulder points */ -#define TIFFTAG_DCSCALIBRATIONFD 65556 /* calibration file desc */ -/* Note: quality level is on the ZLIB 1-9 scale. Default value is -1 */ -#define TIFFTAG_ZIPQUALITY 65557 /* compression quality level */ -#define TIFFTAG_PIXARLOGQUALITY 65558 /* PixarLog uses same scale */ -/* 65559 is allocated to Oceana Matrix */ -#define TIFFTAG_DCSCLIPRECTANGLE 65559 /* area of image to acquire */ -#define TIFFTAG_SGILOGDATAFMT 65560 /* SGILog user data format */ -#define SGILOGDATAFMT_FLOAT 0 /* IEEE float samples */ -#define SGILOGDATAFMT_16BIT 1 /* 16-bit samples */ -#define SGILOGDATAFMT_RAW 2 /* uninterpreted data */ -#define SGILOGDATAFMT_8BIT 3 /* 8-bit RGB monitor values */ -#define TIFFTAG_SGILOGENCODE 65561 /* SGILog data encoding control*/ -#define SGILOGENCODE_NODITHER 0 /* do not dither encoded values*/ -#define SGILOGENCODE_RANDITHER 1 /* randomly dither encd values */ - -/* - * EXIF tags - */ -#define EXIFTAG_EXPOSURETIME 33434 /* Exposure time */ -#define EXIFTAG_FNUMBER 33437 /* F number */ -#define EXIFTAG_EXPOSUREPROGRAM 34850 /* Exposure program */ -#define EXIFTAG_SPECTRALSENSITIVITY 34852 /* Spectral sensitivity */ -#define EXIFTAG_ISOSPEEDRATINGS 34855 /* ISO speed rating */ -#define EXIFTAG_OECF 34856 /* Optoelectric conversion - factor */ -#define EXIFTAG_EXIFVERSION 36864 /* Exif version */ -#define EXIFTAG_DATETIMEORIGINAL 36867 /* Date and time of original - data generation */ -#define EXIFTAG_DATETIMEDIGITIZED 36868 /* Date and time of digital - data generation */ -#define EXIFTAG_COMPONENTSCONFIGURATION 37121 /* Meaning of each component */ -#define EXIFTAG_COMPRESSEDBITSPERPIXEL 37122 /* Image compression mode */ -#define EXIFTAG_SHUTTERSPEEDVALUE 37377 /* Shutter speed */ -#define EXIFTAG_APERTUREVALUE 37378 /* Aperture */ -#define EXIFTAG_BRIGHTNESSVALUE 37379 /* Brightness */ -#define EXIFTAG_EXPOSUREBIASVALUE 37380 /* Exposure bias */ -#define EXIFTAG_MAXAPERTUREVALUE 37381 /* Maximum lens aperture */ -#define EXIFTAG_SUBJECTDISTANCE 37382 /* Subject distance */ -#define EXIFTAG_METERINGMODE 37383 /* Metering mode */ -#define EXIFTAG_LIGHTSOURCE 37384 /* Light source */ -#define EXIFTAG_FLASH 37385 /* Flash */ -#define EXIFTAG_FOCALLENGTH 37386 /* Lens focal length */ -#define EXIFTAG_SUBJECTAREA 37396 /* Subject area */ -#define EXIFTAG_MAKERNOTE 37500 /* Manufacturer notes */ -#define EXIFTAG_USERCOMMENT 37510 /* User comments */ -#define EXIFTAG_SUBSECTIME 37520 /* DateTime subseconds */ -#define EXIFTAG_SUBSECTIMEORIGINAL 37521 /* DateTimeOriginal subseconds */ -#define EXIFTAG_SUBSECTIMEDIGITIZED 37522 /* DateTimeDigitized subseconds */ -#define EXIFTAG_FLASHPIXVERSION 40960 /* Supported Flashpix version */ -#define EXIFTAG_COLORSPACE 40961 /* Color space information */ -#define EXIFTAG_PIXELXDIMENSION 40962 /* Valid image width */ -#define EXIFTAG_PIXELYDIMENSION 40963 /* Valid image height */ -#define EXIFTAG_RELATEDSOUNDFILE 40964 /* Related audio file */ -#define EXIFTAG_FLASHENERGY 41483 /* Flash energy */ -#define EXIFTAG_SPATIALFREQUENCYRESPONSE 41484 /* Spatial frequency response */ -#define EXIFTAG_FOCALPLANEXRESOLUTION 41486 /* Focal plane X resolution */ -#define EXIFTAG_FOCALPLANEYRESOLUTION 41487 /* Focal plane Y resolution */ -#define EXIFTAG_FOCALPLANERESOLUTIONUNIT 41488 /* Focal plane resolution unit */ -#define EXIFTAG_SUBJECTLOCATION 41492 /* Subject location */ -#define EXIFTAG_EXPOSUREINDEX 41493 /* Exposure index */ -#define EXIFTAG_SENSINGMETHOD 41495 /* Sensing method */ -#define EXIFTAG_FILESOURCE 41728 /* File source */ -#define EXIFTAG_SCENETYPE 41729 /* Scene type */ -#define EXIFTAG_CFAPATTERN 41730 /* CFA pattern */ -#define EXIFTAG_CUSTOMRENDERED 41985 /* Custom image processing */ -#define EXIFTAG_EXPOSUREMODE 41986 /* Exposure mode */ -#define EXIFTAG_WHITEBALANCE 41987 /* White balance */ -#define EXIFTAG_DIGITALZOOMRATIO 41988 /* Digital zoom ratio */ -#define EXIFTAG_FOCALLENGTHIN35MMFILM 41989 /* Focal length in 35 mm film */ -#define EXIFTAG_SCENECAPTURETYPE 41990 /* Scene capture type */ -#define EXIFTAG_GAINCONTROL 41991 /* Gain control */ -#define EXIFTAG_CONTRAST 41992 /* Contrast */ -#define EXIFTAG_SATURATION 41993 /* Saturation */ -#define EXIFTAG_SHARPNESS 41994 /* Sharpness */ -#define EXIFTAG_DEVICESETTINGDESCRIPTION 41995 /* Device settings description */ -#define EXIFTAG_SUBJECTDISTANCERANGE 41996 /* Subject distance range */ -#define EXIFTAG_GAINCONTROL 41991 /* Gain control */ -#define EXIFTAG_GAINCONTROL 41991 /* Gain control */ -#define EXIFTAG_IMAGEUNIQUEID 42016 /* Unique image ID */ - -#endif /* _TIFF_ */ - -/* vim: set ts=8 sts=8 sw=8 noet: */ -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/reactos/dll/3rdparty/libtiff/tiffconf.h b/reactos/dll/3rdparty/libtiff/tiffconf.h deleted file mode 100644 index b7d59e0712d..00000000000 --- a/reactos/dll/3rdparty/libtiff/tiffconf.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - Configuration defines for installed libtiff. - This file maintained for backward compatibility. Do not use definitions - from this file in your programs. -*/ - -#ifndef _TIFFCONF_ -#define _TIFFCONF_ - -/* Define to 1 if the system has the type `int16'. */ -//#define HAVE_INT16 1 - -/* Define to 1 if the system has the type `int32'. */ -//#define HAVE_INT32 1 - -/* Define to 1 if the system has the type `int8'. */ -//#define HAVE_INT8 1 - -/* The size of a `int', as computed by sizeof. */ -#define SIZEOF_INT 4 - -/* The size of a `long', as computed by sizeof. */ -#define SIZEOF_LONG 4 - -/* Compatibility stuff. */ - -/* Define as 0 or 1 according to the floating point format suported by the - machine */ -#define HAVE_IEEEFP 1 - -/* Set the native cpu bit order (FILLORDER_LSB2MSB or FILLORDER_MSB2LSB) */ -#define HOST_FILLORDER FILLORDER_LSB2MSB - -/* Native cpu byte order: 1 if big-endian (Motorola) or 0 if little-endian - (Intel) */ -#define HOST_BIGENDIAN 0 - -/* Support CCITT Group 3 & 4 algorithms */ -#define CCITT_SUPPORT 1 - -/* Support JPEG compression (requires IJG JPEG library) */ -// undef JPEG_SUPPORT - -/* Support JBIG compression (requires JBIG-KIT library) */ -// #undef JBIG_SUPPORT - -/* Support LogLuv high dynamic range encoding */ -#define LOGLUV_SUPPORT 1 - -/* Support LZW algorithm */ -#define LZW_SUPPORT 1 - -/* Support NeXT 2-bit RLE algorithm */ -#define NEXT_SUPPORT 1 - -/* Support Old JPEG compresson (read contrib/ojpeg/README first! Compilation - fails with unpatched IJG JPEG library) */ -// #undef OJPEG_SUPPORT - -/* Support Macintosh PackBits algorithm */ -#define PACKBITS_SUPPORT 1 - -/* Support Pixar log-format algorithm (requires Zlib) */ - #define PIXARLOG_SUPPORT 1 - -/* Support ThunderScan 4-bit RLE algorithm */ -#define THUNDER_SUPPORT 1 - -/* Support Deflate compression */ -#define ZIP_SUPPORT 1 - -/* Support strip chopping (whether or not to convert single-strip uncompressed - images to mutiple strips of ~8Kb to reduce memory usage) */ -#define STRIPCHOP_DEFAULT TIFF_STRIPCHOP - -/* Enable SubIFD tag (330) support */ -#define SUBIFD_SUPPORT 1 - -/* Treat extra sample as alpha (default enabled). The RGBA interface will - treat a fourth sample with no EXTRASAMPLE_ value as being ASSOCALPHA. Many - packages produce RGBA files but don't mark the alpha properly. */ -#define DEFAULT_EXTRASAMPLE_AS_ALPHA 1 - -/* Pick up YCbCr subsampling info from the JPEG data stream to support files - lacking the tag (default enabled). */ -#define CHECK_JPEG_YCBCR_SUBSAMPLING 1 - -/* Support MS MDI magic number files as TIFF */ -#define MDI_SUPPORT 1 - -/* - * Feature support definitions. - * XXX: These macros are obsoleted. Don't use them in your apps! - * Macros stays here for backward compatibility and should be always defined. - */ -#define COLORIMETRY_SUPPORT -#define YCBCR_SUPPORT -#define CMYK_SUPPORT -#define ICC_SUPPORT -#define PHOTOSHOP_SUPPORT -#define IPTC_SUPPORT - -#endif /* _TIFFCONF_ */ diff --git a/reactos/dll/3rdparty/libtiff/tiffconf.vc.h b/reactos/dll/3rdparty/libtiff/tiffconf.vc.h deleted file mode 100644 index 3d14847a277..00000000000 --- a/reactos/dll/3rdparty/libtiff/tiffconf.vc.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - Configuration defines for installed libtiff. - This file maintained for backward compatibility. Do not use definitions - from this file in your programs. -*/ - -#ifndef _TIFFCONF_ -#define _TIFFCONF_ - -/* Define to 1 if the system has the type `int16'. */ -/* #undef HAVE_INT16 */ - -/* Define to 1 if the system has the type `int32'. */ -/* #undef HAVE_INT32 */ - -/* Define to 1 if the system has the type `int8'. */ -/* #undef HAVE_INT8 */ - -/* The size of a `int', as computed by sizeof. */ -#define SIZEOF_INT 4 - -/* The size of a `long', as computed by sizeof. */ -#define SIZEOF_LONG 4 - -/* Signed 64-bit type formatter */ -#define TIFF_INT64_FORMAT "%I64d" - -/* Signed 64-bit type */ -#define TIFF_INT64_T signed __int64 - -/* Unsigned 64-bit type formatter */ -#define TIFF_UINT64_FORMAT "%I64u" - -/* Unsigned 64-bit type */ -#define TIFF_UINT64_T unsigned __int64 - -/* Compatibility stuff. */ - -/* Define as 0 or 1 according to the floating point format suported by the - machine */ -#define HAVE_IEEEFP 1 - -/* Set the native cpu bit order (FILLORDER_LSB2MSB or FILLORDER_MSB2LSB) */ -#define HOST_FILLORDER FILLORDER_LSB2MSB - -/* Native cpu byte order: 1 if big-endian (Motorola) or 0 if little-endian - (Intel) */ -#define HOST_BIGENDIAN 0 - -/* Support CCITT Group 3 & 4 algorithms */ -#define CCITT_SUPPORT 1 - -/* Support JPEG compression (requires IJG JPEG library) */ -/* #undef JPEG_SUPPORT */ - -/* Support LogLuv high dynamic range encoding */ -#define LOGLUV_SUPPORT 1 - -/* Support LZW algorithm */ -#define LZW_SUPPORT 1 - -/* Support NeXT 2-bit RLE algorithm */ -#define NEXT_SUPPORT 1 - -/* Support Old JPEG compresson (read contrib/ojpeg/README first! Compilation - fails with unpatched IJG JPEG library) */ -/* #undef OJPEG_SUPPORT */ - -/* Support Macintosh PackBits algorithm */ -#define PACKBITS_SUPPORT 1 - -/* Support Pixar log-format algorithm (requires Zlib) */ -/* #undef PIXARLOG_SUPPORT */ - -/* Support ThunderScan 4-bit RLE algorithm */ -#define THUNDER_SUPPORT 1 - -/* Support Deflate compression */ -/* #undef ZIP_SUPPORT */ - -/* Support strip chopping (whether or not to convert single-strip uncompressed - images to mutiple strips of ~8Kb to reduce memory usage) */ -#define STRIPCHOP_DEFAULT TIFF_STRIPCHOP - -/* Enable SubIFD tag (330) support */ -#define SUBIFD_SUPPORT 1 - -/* Treat extra sample as alpha (default enabled). The RGBA interface will - treat a fourth sample with no EXTRASAMPLE_ value as being ASSOCALPHA. Many - packages produce RGBA files but don't mark the alpha properly. */ -#define DEFAULT_EXTRASAMPLE_AS_ALPHA 1 - -/* Pick up YCbCr subsampling info from the JPEG data stream to support files - lacking the tag (default enabled). */ -#define CHECK_JPEG_YCBCR_SUBSAMPLING 1 - -/* - * Feature support definitions. - * XXX: These macros are obsoleted. Don't use them in your apps! - * Macros stays here for backward compatibility and should be always defined. - */ -#define COLORIMETRY_SUPPORT -#define YCBCR_SUPPORT -#define CMYK_SUPPORT -#define ICC_SUPPORT -#define PHOTOSHOP_SUPPORT -#define IPTC_SUPPORT - -#endif /* _TIFFCONF_ */ -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/reactos/dll/3rdparty/libtiff/tiffio.h b/reactos/dll/3rdparty/libtiff/tiffio.h deleted file mode 100644 index 06ec25c8298..00000000000 --- a/reactos/dll/3rdparty/libtiff/tiffio.h +++ /dev/null @@ -1,526 +0,0 @@ -/* $Id: tiffio.h,v 1.56.2.4 2010-06-08 18:50:43 bfriesen Exp $ */ - -/* - * Copyright (c) 1988-1997 Sam Leffler - * Copyright (c) 1991-1997 Silicon Graphics, Inc. - * - * Permission to use, copy, modify, distribute, and sell this software and - * its documentation for any purpose is hereby granted without fee, provided - * that (i) the above copyright notices and this permission notice appear in - * all copies of the software and related documentation, and (ii) the names of - * Sam Leffler and Silicon Graphics may not be used in any advertising or - * publicity relating to the software without the specific, prior written - * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * - * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR - * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, - * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -#ifndef _TIFFIO_ -#define _TIFFIO_ - -/* - * TIFF I/O Library Definitions. - */ -#include "tiff.h" -#include "tiffvers.h" - -/* - * TIFF is defined as an incomplete type to hide the - * library's internal data structures from clients. - */ -typedef struct tiff TIFF; - -/* - * The following typedefs define the intrinsic size of - * data types used in the *exported* interfaces. These - * definitions depend on the proper definition of types - * in tiff.h. Note also that the varargs interface used - * to pass tag types and values uses the types defined in - * tiff.h directly. - * - * NB: ttag_t is unsigned int and not unsigned short because - * ANSI C requires that the type before the ellipsis be a - * promoted type (i.e. one of int, unsigned int, pointer, - * or double) and because we defined pseudo-tags that are - * outside the range of legal Aldus-assigned tags. - * NB: tsize_t is int32 and not uint32 because some functions - * return -1. - * NB: toff_t is not off_t for many reasons; TIFFs max out at - * 32-bit file offsets being the most important, and to ensure - * that it is unsigned, rather than signed. - */ -typedef uint32 ttag_t; /* directory tag */ -typedef uint16 tdir_t; /* directory index */ -typedef uint16 tsample_t; /* sample number */ -typedef uint32 tstrile_t; /* strip or tile number */ -typedef tstrile_t tstrip_t; /* strip number */ -typedef tstrile_t ttile_t; /* tile number */ -typedef int32 tsize_t; /* i/o size in bytes */ -typedef void* tdata_t; /* image data ref */ -typedef uint32 toff_t; /* file offset */ - -#if !defined(__WIN32__) && (defined(_WIN32) || defined(WIN32)) -#define __WIN32__ -#endif - -/* - * On windows you should define USE_WIN32_FILEIO if you are using tif_win32.c - * or AVOID_WIN32_FILEIO if you are using something else (like tif_unix.c). - * - * By default tif_unix.c is assumed. - */ - -#if defined(_WINDOWS) || defined(__WIN32__) || defined(_Windows) -# if !defined(__CYGWIN) && !defined(AVOID_WIN32_FILEIO) && !defined(USE_WIN32_FILEIO) -# define AVOID_WIN32_FILEIO -# endif -#endif - -#if defined(USE_WIN32_FILEIO) -# define VC_EXTRALEAN -# include -# ifdef __WIN32__ -DECLARE_HANDLE(thandle_t); /* Win32 file handle */ -# else -typedef HFILE thandle_t; /* client data handle */ -# endif /* __WIN32__ */ -#else -typedef void* thandle_t; /* client data handle */ -#endif /* USE_WIN32_FILEIO */ - -/* - * Flags to pass to TIFFPrintDirectory to control - * printing of data structures that are potentially - * very large. Bit-or these flags to enable printing - * multiple items. - */ -#define TIFFPRINT_NONE 0x0 /* no extra info */ -#define TIFFPRINT_STRIPS 0x1 /* strips/tiles info */ -#define TIFFPRINT_CURVES 0x2 /* color/gray response curves */ -#define TIFFPRINT_COLORMAP 0x4 /* colormap */ -#define TIFFPRINT_JPEGQTABLES 0x100 /* JPEG Q matrices */ -#define TIFFPRINT_JPEGACTABLES 0x200 /* JPEG AC tables */ -#define TIFFPRINT_JPEGDCTABLES 0x200 /* JPEG DC tables */ - -/* - * Colour conversion stuff - */ - -/* reference white */ -#define D65_X0 (95.0470F) -#define D65_Y0 (100.0F) -#define D65_Z0 (108.8827F) - -#define D50_X0 (96.4250F) -#define D50_Y0 (100.0F) -#define D50_Z0 (82.4680F) - -/* Structure for holding information about a display device. */ - -typedef unsigned char TIFFRGBValue; /* 8-bit samples */ - -typedef struct { - float d_mat[3][3]; /* XYZ -> luminance matrix */ - float d_YCR; /* Light o/p for reference white */ - float d_YCG; - float d_YCB; - uint32 d_Vrwr; /* Pixel values for ref. white */ - uint32 d_Vrwg; - uint32 d_Vrwb; - float d_Y0R; /* Residual light for black pixel */ - float d_Y0G; - float d_Y0B; - float d_gammaR; /* Gamma values for the three guns */ - float d_gammaG; - float d_gammaB; -} TIFFDisplay; - -typedef struct { /* YCbCr->RGB support */ - TIFFRGBValue* clamptab; /* range clamping table */ - int* Cr_r_tab; - int* Cb_b_tab; - int32* Cr_g_tab; - int32* Cb_g_tab; - int32* Y_tab; -} TIFFYCbCrToRGB; - -typedef struct { /* CIE Lab 1976->RGB support */ - int range; /* Size of conversion table */ -#define CIELABTORGB_TABLE_RANGE 1500 - float rstep, gstep, bstep; - float X0, Y0, Z0; /* Reference white point */ - TIFFDisplay display; - float Yr2r[CIELABTORGB_TABLE_RANGE + 1]; /* Conversion of Yr to r */ - float Yg2g[CIELABTORGB_TABLE_RANGE + 1]; /* Conversion of Yg to g */ - float Yb2b[CIELABTORGB_TABLE_RANGE + 1]; /* Conversion of Yb to b */ -} TIFFCIELabToRGB; - -/* - * RGBA-style image support. - */ -typedef struct _TIFFRGBAImage TIFFRGBAImage; -/* - * The image reading and conversion routines invoke - * ``put routines'' to copy/image/whatever tiles of - * raw image data. A default set of routines are - * provided to convert/copy raw image data to 8-bit - * packed ABGR format rasters. Applications can supply - * alternate routines that unpack the data into a - * different format or, for example, unpack the data - * and draw the unpacked raster on the display. - */ -typedef void (*tileContigRoutine) - (TIFFRGBAImage*, uint32*, uint32, uint32, uint32, uint32, int32, int32, - unsigned char*); -typedef void (*tileSeparateRoutine) - (TIFFRGBAImage*, uint32*, uint32, uint32, uint32, uint32, int32, int32, - unsigned char*, unsigned char*, unsigned char*, unsigned char*); -/* - * RGBA-reader state. - */ -struct _TIFFRGBAImage { - TIFF* tif; /* image handle */ - int stoponerr; /* stop on read error */ - int isContig; /* data is packed/separate */ - int alpha; /* type of alpha data present */ - uint32 width; /* image width */ - uint32 height; /* image height */ - uint16 bitspersample; /* image bits/sample */ - uint16 samplesperpixel; /* image samples/pixel */ - uint16 orientation; /* image orientation */ - uint16 req_orientation; /* requested orientation */ - uint16 photometric; /* image photometric interp */ - uint16* redcmap; /* colormap pallete */ - uint16* greencmap; - uint16* bluecmap; - /* get image data routine */ - int (*get)(TIFFRGBAImage*, uint32*, uint32, uint32); - /* put decoded strip/tile */ - union { - void (*any)(TIFFRGBAImage*); - tileContigRoutine contig; - tileSeparateRoutine separate; - } put; - TIFFRGBValue* Map; /* sample mapping array */ - uint32** BWmap; /* black&white map */ - uint32** PALmap; /* palette image map */ - TIFFYCbCrToRGB* ycbcr; /* YCbCr conversion state */ - TIFFCIELabToRGB* cielab; /* CIE L*a*b conversion state */ - - int row_offset; - int col_offset; -}; - -/* - * Macros for extracting components from the - * packed ABGR form returned by TIFFReadRGBAImage. - */ -#define TIFFGetR(abgr) ((abgr) & 0xff) -#define TIFFGetG(abgr) (((abgr) >> 8) & 0xff) -#define TIFFGetB(abgr) (((abgr) >> 16) & 0xff) -#define TIFFGetA(abgr) (((abgr) >> 24) & 0xff) - -/* - * A CODEC is a software package that implements decoding, - * encoding, or decoding+encoding of a compression algorithm. - * The library provides a collection of builtin codecs. - * More codecs may be registered through calls to the library - * and/or the builtin implementations may be overridden. - */ -typedef int (*TIFFInitMethod)(TIFF*, int); -typedef struct { - char* name; - uint16 scheme; - TIFFInitMethod init; -} TIFFCodec; - -#include -#include - -/* share internal LogLuv conversion routines? */ -#ifndef LOGLUV_PUBLIC -#define LOGLUV_PUBLIC 1 -#endif - -#if !defined(__GNUC__) && !defined(__attribute__) -# define __attribute__(x) /*nothing*/ -#endif - -#if defined(c_plusplus) || defined(__cplusplus) -extern "C" { -#endif -typedef void (*TIFFErrorHandler)(const char*, const char*, va_list); -typedef void (*TIFFErrorHandlerExt)(thandle_t, const char*, const char*, va_list); -typedef tsize_t (*TIFFReadWriteProc)(thandle_t, tdata_t, tsize_t); -typedef toff_t (*TIFFSeekProc)(thandle_t, toff_t, int); -typedef int (*TIFFCloseProc)(thandle_t); -typedef toff_t (*TIFFSizeProc)(thandle_t); -typedef int (*TIFFMapFileProc)(thandle_t, tdata_t*, toff_t*); -typedef void (*TIFFUnmapFileProc)(thandle_t, tdata_t, toff_t); -typedef void (*TIFFExtendProc)(TIFF*); - -extern const char* TIFFGetVersion(void); - -extern const TIFFCodec* TIFFFindCODEC(uint16); -extern TIFFCodec* TIFFRegisterCODEC(uint16, const char*, TIFFInitMethod); -extern void TIFFUnRegisterCODEC(TIFFCodec*); -extern int TIFFIsCODECConfigured(uint16); -extern TIFFCodec* TIFFGetConfiguredCODECs(void); - -/* - * Auxiliary functions. - */ - -extern tdata_t _TIFFmalloc(tsize_t); -extern tdata_t _TIFFrealloc(tdata_t, tsize_t); -extern void _TIFFmemset(tdata_t, int, tsize_t); -extern void _TIFFmemcpy(tdata_t, const tdata_t, tsize_t); -extern int _TIFFmemcmp(const tdata_t, const tdata_t, tsize_t); -extern void _TIFFfree(tdata_t); - -/* -** Stuff, related to tag handling and creating custom tags. -*/ -extern int TIFFGetTagListCount( TIFF * ); -extern ttag_t TIFFGetTagListEntry( TIFF *, int tag_index ); - -#define TIFF_ANY TIFF_NOTYPE /* for field descriptor searching */ -#define TIFF_VARIABLE -1 /* marker for variable length tags */ -#define TIFF_SPP -2 /* marker for SamplesPerPixel tags */ -#define TIFF_VARIABLE2 -3 /* marker for uint32 var-length tags */ - -#define FIELD_CUSTOM 65 - -typedef struct { - ttag_t field_tag; /* field's tag */ - short field_readcount; /* read count/TIFF_VARIABLE/TIFF_SPP */ - short field_writecount; /* write count/TIFF_VARIABLE */ - TIFFDataType field_type; /* type of associated data */ - unsigned short field_bit; /* bit in fieldsset bit vector */ - unsigned char field_oktochange; /* if true, can change while writing */ - unsigned char field_passcount; /* if true, pass dir count on set */ - char *field_name; /* ASCII name */ -} TIFFFieldInfo; - -typedef struct _TIFFTagValue { - const TIFFFieldInfo *info; - int count; - void *value; -} TIFFTagValue; - -extern void TIFFMergeFieldInfo(TIFF*, const TIFFFieldInfo[], int); -extern const TIFFFieldInfo* TIFFFindFieldInfo(TIFF*, ttag_t, TIFFDataType); -extern const TIFFFieldInfo* TIFFFindFieldInfoByName(TIFF* , const char *, - TIFFDataType); -extern const TIFFFieldInfo* TIFFFieldWithTag(TIFF*, ttag_t); -extern const TIFFFieldInfo* TIFFFieldWithName(TIFF*, const char *); - -typedef int (*TIFFVSetMethod)(TIFF*, ttag_t, va_list); -typedef int (*TIFFVGetMethod)(TIFF*, ttag_t, va_list); -typedef void (*TIFFPrintMethod)(TIFF*, FILE*, long); - -typedef struct { - TIFFVSetMethod vsetfield; /* tag set routine */ - TIFFVGetMethod vgetfield; /* tag get routine */ - TIFFPrintMethod printdir; /* directory print routine */ -} TIFFTagMethods; - -extern TIFFTagMethods *TIFFAccessTagMethods( TIFF * ); -extern void *TIFFGetClientInfo( TIFF *, const char * ); -extern void TIFFSetClientInfo( TIFF *, void *, const char * ); - -extern void TIFFCleanup(TIFF*); -extern void TIFFClose(TIFF*); -extern int TIFFFlush(TIFF*); -extern int TIFFFlushData(TIFF*); -extern int TIFFGetField(TIFF*, ttag_t, ...); -extern int TIFFVGetField(TIFF*, ttag_t, va_list); -extern int TIFFGetFieldDefaulted(TIFF*, ttag_t, ...); -extern int TIFFVGetFieldDefaulted(TIFF*, ttag_t, va_list); -extern int TIFFReadDirectory(TIFF*); -extern int TIFFReadCustomDirectory(TIFF*, toff_t, const TIFFFieldInfo[], - size_t); -extern int TIFFReadEXIFDirectory(TIFF*, toff_t); -extern tsize_t TIFFScanlineSize(TIFF*); -extern tsize_t TIFFOldScanlineSize(TIFF*); -extern tsize_t TIFFNewScanlineSize(TIFF*); -extern tsize_t TIFFRasterScanlineSize(TIFF*); -extern tsize_t TIFFStripSize(TIFF*); -extern tsize_t TIFFRawStripSize(TIFF*, tstrip_t); -extern tsize_t TIFFVStripSize(TIFF*, uint32); -extern tsize_t TIFFTileRowSize(TIFF*); -extern tsize_t TIFFTileSize(TIFF*); -extern tsize_t TIFFVTileSize(TIFF*, uint32); -extern uint32 TIFFDefaultStripSize(TIFF*, uint32); -extern void TIFFDefaultTileSize(TIFF*, uint32*, uint32*); -extern int TIFFFileno(TIFF*); -extern int TIFFSetFileno(TIFF*, int); -extern thandle_t TIFFClientdata(TIFF*); -extern thandle_t TIFFSetClientdata(TIFF*, thandle_t); -extern int TIFFGetMode(TIFF*); -extern int TIFFSetMode(TIFF*, int); -extern int TIFFIsTiled(TIFF*); -extern int TIFFIsByteSwapped(TIFF*); -extern int TIFFIsUpSampled(TIFF*); -extern int TIFFIsMSB2LSB(TIFF*); -extern int TIFFIsBigEndian(TIFF*); -extern TIFFReadWriteProc TIFFGetReadProc(TIFF*); -extern TIFFReadWriteProc TIFFGetWriteProc(TIFF*); -extern TIFFSeekProc TIFFGetSeekProc(TIFF*); -extern TIFFCloseProc TIFFGetCloseProc(TIFF*); -extern TIFFSizeProc TIFFGetSizeProc(TIFF*); -extern TIFFMapFileProc TIFFGetMapFileProc(TIFF*); -extern TIFFUnmapFileProc TIFFGetUnmapFileProc(TIFF*); -extern uint32 TIFFCurrentRow(TIFF*); -extern tdir_t TIFFCurrentDirectory(TIFF*); -extern tdir_t TIFFNumberOfDirectories(TIFF*); -extern uint32 TIFFCurrentDirOffset(TIFF*); -extern tstrip_t TIFFCurrentStrip(TIFF*); -extern ttile_t TIFFCurrentTile(TIFF*); -extern int TIFFReadBufferSetup(TIFF*, tdata_t, tsize_t); -extern int TIFFWriteBufferSetup(TIFF*, tdata_t, tsize_t); -extern int TIFFSetupStrips(TIFF *); -extern int TIFFWriteCheck(TIFF*, int, const char *); -extern void TIFFFreeDirectory(TIFF*); -extern int TIFFCreateDirectory(TIFF*); -extern int TIFFLastDirectory(TIFF*); -extern int TIFFSetDirectory(TIFF*, tdir_t); -extern int TIFFSetSubDirectory(TIFF*, uint32); -extern int TIFFUnlinkDirectory(TIFF*, tdir_t); -extern int TIFFSetField(TIFF*, ttag_t, ...); -extern int TIFFVSetField(TIFF*, ttag_t, va_list); -extern int TIFFWriteDirectory(TIFF *); -extern int TIFFCheckpointDirectory(TIFF *); -extern int TIFFRewriteDirectory(TIFF *); -extern int TIFFReassignTagToIgnore(enum TIFFIgnoreSense, int); - -#if defined(c_plusplus) || defined(__cplusplus) -extern void TIFFPrintDirectory(TIFF*, FILE*, long = 0); -extern int TIFFReadScanline(TIFF*, tdata_t, uint32, tsample_t = 0); -extern int TIFFWriteScanline(TIFF*, tdata_t, uint32, tsample_t = 0); -extern int TIFFReadRGBAImage(TIFF*, uint32, uint32, uint32*, int = 0); -extern int TIFFReadRGBAImageOriented(TIFF*, uint32, uint32, uint32*, - int = ORIENTATION_BOTLEFT, int = 0); -#else -extern void TIFFPrintDirectory(TIFF*, FILE*, long); -extern int TIFFReadScanline(TIFF*, tdata_t, uint32, tsample_t); -extern int TIFFWriteScanline(TIFF*, tdata_t, uint32, tsample_t); -extern int TIFFReadRGBAImage(TIFF*, uint32, uint32, uint32*, int); -extern int TIFFReadRGBAImageOriented(TIFF*, uint32, uint32, uint32*, int, int); -#endif - -extern int TIFFReadRGBAStrip(TIFF*, tstrip_t, uint32 * ); -extern int TIFFReadRGBATile(TIFF*, uint32, uint32, uint32 * ); -extern int TIFFRGBAImageOK(TIFF*, char [1024]); -extern int TIFFRGBAImageBegin(TIFFRGBAImage*, TIFF*, int, char [1024]); -extern int TIFFRGBAImageGet(TIFFRGBAImage*, uint32*, uint32, uint32); -extern void TIFFRGBAImageEnd(TIFFRGBAImage*); -extern TIFF* TIFFOpen(const char*, const char*); -# ifdef __WIN32__ -extern TIFF* TIFFOpenW(const wchar_t*, const char*); -# endif /* __WIN32__ */ -extern TIFF* TIFFFdOpen(int, const char*, const char*); -extern TIFF* TIFFClientOpen(const char*, const char*, - thandle_t, - TIFFReadWriteProc, TIFFReadWriteProc, - TIFFSeekProc, TIFFCloseProc, - TIFFSizeProc, - TIFFMapFileProc, TIFFUnmapFileProc); -extern const char* TIFFFileName(TIFF*); -extern const char* TIFFSetFileName(TIFF*, const char *); -extern void TIFFError(const char*, const char*, ...) __attribute__((format (printf,2,3))); -extern void TIFFErrorExt(thandle_t, const char*, const char*, ...) __attribute__((format (printf,3,4))); -extern void TIFFWarning(const char*, const char*, ...) __attribute__((format (printf,2,3))); -extern void TIFFWarningExt(thandle_t, const char*, const char*, ...) __attribute__((format (printf,3,4))); -extern TIFFErrorHandler TIFFSetErrorHandler(TIFFErrorHandler); -extern TIFFErrorHandlerExt TIFFSetErrorHandlerExt(TIFFErrorHandlerExt); -extern TIFFErrorHandler TIFFSetWarningHandler(TIFFErrorHandler); -extern TIFFErrorHandlerExt TIFFSetWarningHandlerExt(TIFFErrorHandlerExt); -extern TIFFExtendProc TIFFSetTagExtender(TIFFExtendProc); -extern ttile_t TIFFComputeTile(TIFF*, uint32, uint32, uint32, tsample_t); -extern int TIFFCheckTile(TIFF*, uint32, uint32, uint32, tsample_t); -extern ttile_t TIFFNumberOfTiles(TIFF*); -extern tsize_t TIFFReadTile(TIFF*, - tdata_t, uint32, uint32, uint32, tsample_t); -extern tsize_t TIFFWriteTile(TIFF*, - tdata_t, uint32, uint32, uint32, tsample_t); -extern tstrip_t TIFFComputeStrip(TIFF*, uint32, tsample_t); -extern tstrip_t TIFFNumberOfStrips(TIFF*); -extern tsize_t TIFFReadEncodedStrip(TIFF*, tstrip_t, tdata_t, tsize_t); -extern tsize_t TIFFReadRawStrip(TIFF*, tstrip_t, tdata_t, tsize_t); -extern tsize_t TIFFReadEncodedTile(TIFF*, ttile_t, tdata_t, tsize_t); -extern tsize_t TIFFReadRawTile(TIFF*, ttile_t, tdata_t, tsize_t); -extern tsize_t TIFFWriteEncodedStrip(TIFF*, tstrip_t, tdata_t, tsize_t); -extern tsize_t TIFFWriteRawStrip(TIFF*, tstrip_t, tdata_t, tsize_t); -extern tsize_t TIFFWriteEncodedTile(TIFF*, ttile_t, tdata_t, tsize_t); -extern tsize_t TIFFWriteRawTile(TIFF*, ttile_t, tdata_t, tsize_t); -extern int TIFFDataWidth(TIFFDataType); /* table of tag datatype widths */ -extern void TIFFSetWriteOffset(TIFF*, toff_t); -extern void TIFFSwabShort(uint16*); -extern void TIFFSwabLong(uint32*); -extern void TIFFSwabDouble(double*); -extern void TIFFSwabArrayOfShort(uint16*, unsigned long); -extern void TIFFSwabArrayOfTriples(uint8*, unsigned long); -extern void TIFFSwabArrayOfLong(uint32*, unsigned long); -extern void TIFFSwabArrayOfDouble(double*, unsigned long); -extern void TIFFReverseBits(unsigned char *, unsigned long); -extern const unsigned char* TIFFGetBitRevTable(int); - -#ifdef LOGLUV_PUBLIC -#define U_NEU 0.210526316 -#define V_NEU 0.473684211 -#define UVSCALE 410. -extern double LogL16toY(int); -extern double LogL10toY(int); -extern void XYZtoRGB24(float*, uint8*); -extern int uv_decode(double*, double*, int); -extern void LogLuv24toXYZ(uint32, float*); -extern void LogLuv32toXYZ(uint32, float*); -#if defined(c_plusplus) || defined(__cplusplus) -extern int LogL16fromY(double, int = SGILOGENCODE_NODITHER); -extern int LogL10fromY(double, int = SGILOGENCODE_NODITHER); -extern int uv_encode(double, double, int = SGILOGENCODE_NODITHER); -extern uint32 LogLuv24fromXYZ(float*, int = SGILOGENCODE_NODITHER); -extern uint32 LogLuv32fromXYZ(float*, int = SGILOGENCODE_NODITHER); -#else -extern int LogL16fromY(double, int); -extern int LogL10fromY(double, int); -extern int uv_encode(double, double, int); -extern uint32 LogLuv24fromXYZ(float*, int); -extern uint32 LogLuv32fromXYZ(float*, int); -#endif -#endif /* LOGLUV_PUBLIC */ - -extern int TIFFCIELabToRGBInit(TIFFCIELabToRGB*, TIFFDisplay *, float*); -extern void TIFFCIELabToXYZ(TIFFCIELabToRGB *, uint32, int32, int32, - float *, float *, float *); -extern void TIFFXYZToRGB(TIFFCIELabToRGB *, float, float, float, - uint32 *, uint32 *, uint32 *); - -extern int TIFFYCbCrToRGBInit(TIFFYCbCrToRGB*, float*, float*); -extern void TIFFYCbCrtoRGB(TIFFYCbCrToRGB *, uint32, int32, int32, - uint32 *, uint32 *, uint32 *); - -#if defined(c_plusplus) || defined(__cplusplus) -} -#endif - -#endif /* _TIFFIO_ */ - -/* vim: set ts=8 sts=8 sw=8 noet: */ -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/reactos/dll/3rdparty/libtiff/tiffio.hxx b/reactos/dll/3rdparty/libtiff/tiffio.hxx deleted file mode 100644 index ee3fd32c742..00000000000 --- a/reactos/dll/3rdparty/libtiff/tiffio.hxx +++ /dev/null @@ -1,49 +0,0 @@ -/* $Id: tiffio.hxx,v 1.1.2.1 2010-06-08 18:50:43 bfriesen Exp $ */ - -/* - * Copyright (c) 1988-1997 Sam Leffler - * Copyright (c) 1991-1997 Silicon Graphics, Inc. - * - * Permission to use, copy, modify, distribute, and sell this software and - * its documentation for any purpose is hereby granted without fee, provided - * that (i) the above copyright notices and this permission notice appear in - * all copies of the software and related documentation, and (ii) the names of - * Sam Leffler and Silicon Graphics may not be used in any advertising or - * publicity relating to the software without the specific, prior written - * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * - * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR - * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, - * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -#ifndef _TIFFIO_HXX_ -#define _TIFFIO_HXX_ - -/* - * TIFF I/O library definitions which provide C++ streams API. - */ - -#include -#include "tiff.h" - -extern TIFF* TIFFStreamOpen(const char*, std::ostream *); -extern TIFF* TIFFStreamOpen(const char*, std::istream *); - -#endif /* _TIFFIO_HXX_ */ - -/* vim: set ts=8 sts=8 sw=8 noet: */ -/* - * Local Variables: - * mode: c++ - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/reactos/dll/3rdparty/libtiff/tiffiop.h b/reactos/dll/3rdparty/libtiff/tiffiop.h deleted file mode 100644 index a064039f6b8..00000000000 --- a/reactos/dll/3rdparty/libtiff/tiffiop.h +++ /dev/null @@ -1,350 +0,0 @@ -/* $Id: tiffiop.h,v 1.51.2.6 2010-06-12 02:55:16 bfriesen Exp $ */ - -/* - * Copyright (c) 1988-1997 Sam Leffler - * Copyright (c) 1991-1997 Silicon Graphics, Inc. - * - * Permission to use, copy, modify, distribute, and sell this software and - * its documentation for any purpose is hereby granted without fee, provided - * that (i) the above copyright notices and this permission notice appear in - * all copies of the software and related documentation, and (ii) the names of - * Sam Leffler and Silicon Graphics may not be used in any advertising or - * publicity relating to the software without the specific, prior written - * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * - * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR - * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, - * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -#ifndef _TIFFIOP_ -#define _TIFFIOP_ -/* - * ``Library-private'' definitions. - */ - -#include "tif_config.h" - -#ifdef HAVE_FCNTL_H -# include -#endif - -#ifdef HAVE_SYS_TYPES_H -# include -#endif - -#ifdef HAVE_STRING_H -# include -#endif - -#ifdef HAVE_ASSERT_H -# include -#else -# define assert(x) -#endif - -#ifdef HAVE_SEARCH_H -# include -#else -extern void *lfind(const void *, const void *, size_t *, size_t, - int (*)(const void *, const void *)); -#endif - -/* - Libtiff itself does not require a 64-bit type, but bundled TIFF - utilities may use it. -*/ -typedef TIFF_INT64_T int64; -typedef TIFF_UINT64_T uint64; - -#include "tiffio.h" -#include "tif_dir.h" - -#ifndef STRIP_SIZE_DEFAULT -# define STRIP_SIZE_DEFAULT 8192 -#endif - -#define streq(a,b) (strcmp(a,b) == 0) - -#ifndef TRUE -#define TRUE 1 -#define FALSE 0 -#endif - -typedef struct client_info { - struct client_info *next; - void *data; - char *name; -} TIFFClientInfoLink; - -/* - * Typedefs for ``method pointers'' used internally. - */ -typedef unsigned char tidataval_t; /* internal image data value type */ -typedef tidataval_t* tidata_t; /* reference to internal image data */ - -typedef void (*TIFFVoidMethod)(TIFF*); -typedef int (*TIFFBoolMethod)(TIFF*); -typedef int (*TIFFPreMethod)(TIFF*, tsample_t); -typedef int (*TIFFCodeMethod)(TIFF*, tidata_t, tsize_t, tsample_t); -typedef int (*TIFFSeekMethod)(TIFF*, uint32); -typedef void (*TIFFPostMethod)(TIFF*, tidata_t, tsize_t); -typedef uint32 (*TIFFStripMethod)(TIFF*, uint32); -typedef void (*TIFFTileMethod)(TIFF*, uint32*, uint32*); - -struct tiff { - char* tif_name; /* name of open file */ - int tif_fd; /* open file descriptor */ - int tif_mode; /* open mode (O_*) */ - uint32 tif_flags; -#define TIFF_FILLORDER 0x00003 /* natural bit fill order for machine */ -#define TIFF_DIRTYHEADER 0x00004 /* header must be written on close */ -#define TIFF_DIRTYDIRECT 0x00008 /* current directory must be written */ -#define TIFF_BUFFERSETUP 0x00010 /* data buffers setup */ -#define TIFF_CODERSETUP 0x00020 /* encoder/decoder setup done */ -#define TIFF_BEENWRITING 0x00040 /* written 1+ scanlines to file */ -#define TIFF_SWAB 0x00080 /* byte swap file information */ -#define TIFF_NOBITREV 0x00100 /* inhibit bit reversal logic */ -#define TIFF_MYBUFFER 0x00200 /* my raw data buffer; free on close */ -#define TIFF_ISTILED 0x00400 /* file is tile, not strip- based */ -#define TIFF_MAPPED 0x00800 /* file is mapped into memory */ -#define TIFF_POSTENCODE 0x01000 /* need call to postencode routine */ -#define TIFF_INSUBIFD 0x02000 /* currently writing a subifd */ -#define TIFF_UPSAMPLED 0x04000 /* library is doing data up-sampling */ -#define TIFF_STRIPCHOP 0x08000 /* enable strip chopping support */ -#define TIFF_HEADERONLY 0x10000 /* read header only, do not process */ - /* the first directory */ -#define TIFF_NOREADRAW 0x20000 /* skip reading of raw uncompressed */ - /* image data */ -#define TIFF_INCUSTOMIFD 0x40000 /* currently writing a custom IFD */ - toff_t tif_diroff; /* file offset of current directory */ - toff_t tif_nextdiroff; /* file offset of following directory */ - toff_t* tif_dirlist; /* list of offsets to already seen */ - /* directories to prevent IFD looping */ - tsize_t tif_dirlistsize;/* number of entires in offset list */ - uint16 tif_dirnumber; /* number of already seen directories */ - TIFFDirectory tif_dir; /* internal rep of current directory */ - TIFFDirectory tif_customdir; /* custom IFDs are separated from - the main ones */ - TIFFHeader tif_header; /* file's header block */ - const int* tif_typeshift; /* data type shift counts */ - const long* tif_typemask; /* data type masks */ - uint32 tif_row; /* current scanline */ - tdir_t tif_curdir; /* current directory (index) */ - tstrip_t tif_curstrip; /* current strip for read/write */ - toff_t tif_curoff; /* current offset for read/write */ - toff_t tif_dataoff; /* current offset for writing dir */ -/* SubIFD support */ - uint16 tif_nsubifd; /* remaining subifds to write */ - toff_t tif_subifdoff; /* offset for patching SubIFD link */ -/* tiling support */ - uint32 tif_col; /* current column (offset by row too) */ - ttile_t tif_curtile; /* current tile for read/write */ - tsize_t tif_tilesize; /* # of bytes in a tile */ -/* compression scheme hooks */ - int tif_decodestatus; - TIFFBoolMethod tif_setupdecode;/* called once before predecode */ - TIFFPreMethod tif_predecode; /* pre- row/strip/tile decoding */ - TIFFBoolMethod tif_setupencode;/* called once before preencode */ - int tif_encodestatus; - TIFFPreMethod tif_preencode; /* pre- row/strip/tile encoding */ - TIFFBoolMethod tif_postencode; /* post- row/strip/tile encoding */ - TIFFCodeMethod tif_decoderow; /* scanline decoding routine */ - TIFFCodeMethod tif_encoderow; /* scanline encoding routine */ - TIFFCodeMethod tif_decodestrip;/* strip decoding routine */ - TIFFCodeMethod tif_encodestrip;/* strip encoding routine */ - TIFFCodeMethod tif_decodetile; /* tile decoding routine */ - TIFFCodeMethod tif_encodetile; /* tile encoding routine */ - TIFFVoidMethod tif_close; /* cleanup-on-close routine */ - TIFFSeekMethod tif_seek; /* position within a strip routine */ - TIFFVoidMethod tif_cleanup; /* cleanup state routine */ - TIFFStripMethod tif_defstripsize;/* calculate/constrain strip size */ - TIFFTileMethod tif_deftilesize;/* calculate/constrain tile size */ - tidata_t tif_data; /* compression scheme private data */ -/* input/output buffering */ - tsize_t tif_scanlinesize;/* # of bytes in a scanline */ - tsize_t tif_scanlineskew;/* scanline skew for reading strips */ - tidata_t tif_rawdata; /* raw data buffer */ - tsize_t tif_rawdatasize;/* # of bytes in raw data buffer */ - tidata_t tif_rawcp; /* current spot in raw buffer */ - tsize_t tif_rawcc; /* bytes unread from raw buffer */ -/* memory-mapped file support */ - tidata_t tif_base; /* base of mapped file */ - toff_t tif_size; /* size of mapped file region (bytes) - FIXME: it should be tsize_t */ - TIFFMapFileProc tif_mapproc; /* map file method */ - TIFFUnmapFileProc tif_unmapproc;/* unmap file method */ -/* input/output callback methods */ - thandle_t tif_clientdata; /* callback parameter */ - TIFFReadWriteProc tif_readproc; /* read method */ - TIFFReadWriteProc tif_writeproc;/* write method */ - TIFFSeekProc tif_seekproc; /* lseek method */ - TIFFCloseProc tif_closeproc; /* close method */ - TIFFSizeProc tif_sizeproc; /* filesize method */ -/* post-decoding support */ - TIFFPostMethod tif_postdecode; /* post decoding routine */ -/* tag support */ - TIFFFieldInfo** tif_fieldinfo; /* sorted table of registered tags */ - size_t tif_nfields; /* # entries in registered tag table */ - const TIFFFieldInfo *tif_foundfield;/* cached pointer to already found tag */ - TIFFTagMethods tif_tagmethods; /* tag get/set/print routines */ - TIFFClientInfoLink *tif_clientinfo; /* extra client information. */ -}; - -#define isPseudoTag(t) (t > 0xffff) /* is tag value normal or pseudo */ - -#define isTiled(tif) (((tif)->tif_flags & TIFF_ISTILED) != 0) -#define isMapped(tif) (((tif)->tif_flags & TIFF_MAPPED) != 0) -#define isFillOrder(tif, o) (((tif)->tif_flags & (o)) != 0) -#define isUpSampled(tif) (((tif)->tif_flags & TIFF_UPSAMPLED) != 0) -#define TIFFReadFile(tif, buf, size) \ - ((*(tif)->tif_readproc)((tif)->tif_clientdata,buf,size)) -#define TIFFWriteFile(tif, buf, size) \ - ((*(tif)->tif_writeproc)((tif)->tif_clientdata,buf,size)) -#define TIFFSeekFile(tif, off, whence) \ - ((*(tif)->tif_seekproc)((tif)->tif_clientdata,(toff_t)(off),whence)) -#define TIFFCloseFile(tif) \ - ((*(tif)->tif_closeproc)((tif)->tif_clientdata)) -#define TIFFGetFileSize(tif) \ - ((*(tif)->tif_sizeproc)((tif)->tif_clientdata)) -#define TIFFMapFileContents(tif, paddr, psize) \ - ((*(tif)->tif_mapproc)((tif)->tif_clientdata,paddr,psize)) -#define TIFFUnmapFileContents(tif, addr, size) \ - ((*(tif)->tif_unmapproc)((tif)->tif_clientdata,addr,size)) - -/* - * Default Read/Seek/Write definitions. - */ -#ifndef ReadOK -#define ReadOK(tif, buf, size) \ - (TIFFReadFile(tif, (tdata_t) buf, (tsize_t)(size)) == (tsize_t)(size)) -#endif -#ifndef SeekOK -#define SeekOK(tif, off) \ - (TIFFSeekFile(tif, (toff_t) off, SEEK_SET) == (toff_t) off) -#endif -#ifndef WriteOK -#define WriteOK(tif, buf, size) \ - (TIFFWriteFile(tif, (tdata_t) buf, (tsize_t) size) == (tsize_t) size) -#endif - -/* NB: the uint32 casts are to silence certain ANSI-C compilers */ -#define TIFFhowmany(x, y) (((uint32)x < (0xffffffff - (uint32)(y-1))) ? \ - ((((uint32)(x))+(((uint32)(y))-1))/((uint32)(y))) : \ - 0U) -#define TIFFhowmany8(x) (((x)&0x07)?((uint32)(x)>>3)+1:(uint32)(x)>>3) -#define TIFFroundup(x, y) (TIFFhowmany(x,y)*(y)) - -/* Safe multiply which returns zero if there is an integer overflow */ -#define TIFFSafeMultiply(t,v,m) ((((t)m != (t)0) && (((t)((v*m)/m)) == (t)v)) ? (t)(v*m) : (t)0) - -#define TIFFmax(A,B) ((A)>(B)?(A):(B)) -#define TIFFmin(A,B) ((A)<(B)?(A):(B)) - -#define TIFFArrayCount(a) (sizeof (a) / sizeof ((a)[0])) - -#if defined(__cplusplus) -extern "C" { -#endif -extern int _TIFFgetMode(const char*, const char*); -extern int _TIFFNoRowEncode(TIFF*, tidata_t, tsize_t, tsample_t); -extern int _TIFFNoStripEncode(TIFF*, tidata_t, tsize_t, tsample_t); -extern int _TIFFNoTileEncode(TIFF*, tidata_t, tsize_t, tsample_t); -extern int _TIFFNoRowDecode(TIFF*, tidata_t, tsize_t, tsample_t); -extern int _TIFFNoStripDecode(TIFF*, tidata_t, tsize_t, tsample_t); -extern int _TIFFNoTileDecode(TIFF*, tidata_t, tsize_t, tsample_t); -extern void _TIFFNoPostDecode(TIFF*, tidata_t, tsize_t); -extern int _TIFFNoPreCode (TIFF*, tsample_t); -extern int _TIFFNoSeek(TIFF*, uint32); -extern void _TIFFSwab16BitData(TIFF*, tidata_t, tsize_t); -extern void _TIFFSwab24BitData(TIFF*, tidata_t, tsize_t); -extern void _TIFFSwab32BitData(TIFF*, tidata_t, tsize_t); -extern void _TIFFSwab64BitData(TIFF*, tidata_t, tsize_t); -extern int TIFFFlushData1(TIFF*); -extern int TIFFDefaultDirectory(TIFF*); -extern void _TIFFSetDefaultCompressionState(TIFF*); -extern int TIFFSetCompressionScheme(TIFF*, int); -extern int TIFFSetDefaultCompressionState(TIFF*); -extern uint32 _TIFFDefaultStripSize(TIFF*, uint32); -extern void _TIFFDefaultTileSize(TIFF*, uint32*, uint32*); -extern int _TIFFDataSize(TIFFDataType); - -extern void _TIFFsetByteArray(void**, void*, uint32); -extern void _TIFFsetString(char**, char*); -extern void _TIFFsetShortArray(uint16**, uint16*, uint32); -extern void _TIFFsetLongArray(uint32**, uint32*, uint32); -extern void _TIFFsetFloatArray(float**, float*, uint32); -extern void _TIFFsetDoubleArray(double**, double*, uint32); - -extern void _TIFFprintAscii(FILE*, const char*); -extern void _TIFFprintAsciiTag(FILE*, const char*, const char*); - -extern TIFFErrorHandler _TIFFwarningHandler; -extern TIFFErrorHandler _TIFFerrorHandler; -extern TIFFErrorHandlerExt _TIFFwarningHandlerExt; -extern TIFFErrorHandlerExt _TIFFerrorHandlerExt; - -extern tdata_t _TIFFCheckMalloc(TIFF*, size_t, size_t, const char*); -extern tdata_t _TIFFCheckRealloc(TIFF*, tdata_t, size_t, size_t, const char*); - -extern int TIFFInitDumpMode(TIFF*, int); -#ifdef PACKBITS_SUPPORT -extern int TIFFInitPackBits(TIFF*, int); -#endif -#ifdef CCITT_SUPPORT -extern int TIFFInitCCITTRLE(TIFF*, int), TIFFInitCCITTRLEW(TIFF*, int); -extern int TIFFInitCCITTFax3(TIFF*, int), TIFFInitCCITTFax4(TIFF*, int); -#endif -#ifdef THUNDER_SUPPORT -extern int TIFFInitThunderScan(TIFF*, int); -#endif -#ifdef NEXT_SUPPORT -extern int TIFFInitNeXT(TIFF*, int); -#endif -#ifdef LZW_SUPPORT -extern int TIFFInitLZW(TIFF*, int); -#endif -#ifdef OJPEG_SUPPORT -extern int TIFFInitOJPEG(TIFF*, int); -#endif -#ifdef JPEG_SUPPORT -extern int TIFFInitJPEG(TIFF*, int); -#endif -#ifdef JBIG_SUPPORT -extern int TIFFInitJBIG(TIFF*, int); -#endif -#ifdef ZIP_SUPPORT -extern int TIFFInitZIP(TIFF*, int); -#endif -#ifdef PIXARLOG_SUPPORT -extern int TIFFInitPixarLog(TIFF*, int); -#endif -#ifdef LOGLUV_SUPPORT -extern int TIFFInitSGILog(TIFF*, int); -#endif -#ifdef VMS -extern const TIFFCodec _TIFFBuiltinCODECS[]; -#else -extern TIFFCodec _TIFFBuiltinCODECS[]; -#endif - -#if defined(__cplusplus) -} -#endif -#endif /* _TIFFIOP_ */ - -/* vim: set ts=8 sts=8 sw=8 noet: */ -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/reactos/dll/3rdparty/libtiff/tiffvers.h b/reactos/dll/3rdparty/libtiff/tiffvers.h deleted file mode 100644 index 314a22a0ae9..00000000000 --- a/reactos/dll/3rdparty/libtiff/tiffvers.h +++ /dev/null @@ -1,9 +0,0 @@ -#define TIFFLIB_VERSION_STR "LIBTIFF, Version 3.9.4\nCopyright (c) 1988-1996 Sam Leffler\nCopyright (c) 1991-1996 Silicon Graphics, Inc." -/* - * This define can be used in code that requires - * compilation-related definitions specific to a - * version or versions of the library. Runtime - * version checking should be done based on the - * string returned by TIFFGetVersion. - */ -#define TIFFLIB_VERSION 20100615 diff --git a/reactos/dll/3rdparty/libtiff/uvcode.h b/reactos/dll/3rdparty/libtiff/uvcode.h deleted file mode 100644 index 50f11d7e0ae..00000000000 --- a/reactos/dll/3rdparty/libtiff/uvcode.h +++ /dev/null @@ -1,180 +0,0 @@ -/* Version 1.0 generated April 7, 1997 by Greg Ward Larson, SGI */ -#define UV_SQSIZ (float)0.003500 -#define UV_NDIVS 16289 -#define UV_VSTART (float)0.016940 -#define UV_NVS 163 -static struct { - float ustart; - short nus, ncum; -} uv_row[UV_NVS] = { - { (float)0.247663, 4, 0 }, - { (float)0.243779, 6, 4 }, - { (float)0.241684, 7, 10 }, - { (float)0.237874, 9, 17 }, - { (float)0.235906, 10, 26 }, - { (float)0.232153, 12, 36 }, - { (float)0.228352, 14, 48 }, - { (float)0.226259, 15, 62 }, - { (float)0.222371, 17, 77 }, - { (float)0.220410, 18, 94 }, - { (float)0.214710, 21, 112 }, - { (float)0.212714, 22, 133 }, - { (float)0.210721, 23, 155 }, - { (float)0.204976, 26, 178 }, - { (float)0.202986, 27, 204 }, - { (float)0.199245, 29, 231 }, - { (float)0.195525, 31, 260 }, - { (float)0.193560, 32, 291 }, - { (float)0.189878, 34, 323 }, - { (float)0.186216, 36, 357 }, - { (float)0.186216, 36, 393 }, - { (float)0.182592, 38, 429 }, - { (float)0.179003, 40, 467 }, - { (float)0.175466, 42, 507 }, - { (float)0.172001, 44, 549 }, - { (float)0.172001, 44, 593 }, - { (float)0.168612, 46, 637 }, - { (float)0.168612, 46, 683 }, - { (float)0.163575, 49, 729 }, - { (float)0.158642, 52, 778 }, - { (float)0.158642, 52, 830 }, - { (float)0.158642, 52, 882 }, - { (float)0.153815, 55, 934 }, - { (float)0.153815, 55, 989 }, - { (float)0.149097, 58, 1044 }, - { (float)0.149097, 58, 1102 }, - { (float)0.142746, 62, 1160 }, - { (float)0.142746, 62, 1222 }, - { (float)0.142746, 62, 1284 }, - { (float)0.138270, 65, 1346 }, - { (float)0.138270, 65, 1411 }, - { (float)0.138270, 65, 1476 }, - { (float)0.132166, 69, 1541 }, - { (float)0.132166, 69, 1610 }, - { (float)0.126204, 73, 1679 }, - { (float)0.126204, 73, 1752 }, - { (float)0.126204, 73, 1825 }, - { (float)0.120381, 77, 1898 }, - { (float)0.120381, 77, 1975 }, - { (float)0.120381, 77, 2052 }, - { (float)0.120381, 77, 2129 }, - { (float)0.112962, 82, 2206 }, - { (float)0.112962, 82, 2288 }, - { (float)0.112962, 82, 2370 }, - { (float)0.107450, 86, 2452 }, - { (float)0.107450, 86, 2538 }, - { (float)0.107450, 86, 2624 }, - { (float)0.107450, 86, 2710 }, - { (float)0.100343, 91, 2796 }, - { (float)0.100343, 91, 2887 }, - { (float)0.100343, 91, 2978 }, - { (float)0.095126, 95, 3069 }, - { (float)0.095126, 95, 3164 }, - { (float)0.095126, 95, 3259 }, - { (float)0.095126, 95, 3354 }, - { (float)0.088276, 100, 3449 }, - { (float)0.088276, 100, 3549 }, - { (float)0.088276, 100, 3649 }, - { (float)0.088276, 100, 3749 }, - { (float)0.081523, 105, 3849 }, - { (float)0.081523, 105, 3954 }, - { (float)0.081523, 105, 4059 }, - { (float)0.081523, 105, 4164 }, - { (float)0.074861, 110, 4269 }, - { (float)0.074861, 110, 4379 }, - { (float)0.074861, 110, 4489 }, - { (float)0.074861, 110, 4599 }, - { (float)0.068290, 115, 4709 }, - { (float)0.068290, 115, 4824 }, - { (float)0.068290, 115, 4939 }, - { (float)0.068290, 115, 5054 }, - { (float)0.063573, 119, 5169 }, - { (float)0.063573, 119, 5288 }, - { (float)0.063573, 119, 5407 }, - { (float)0.063573, 119, 5526 }, - { (float)0.057219, 124, 5645 }, - { (float)0.057219, 124, 5769 }, - { (float)0.057219, 124, 5893 }, - { (float)0.057219, 124, 6017 }, - { (float)0.050985, 129, 6141 }, - { (float)0.050985, 129, 6270 }, - { (float)0.050985, 129, 6399 }, - { (float)0.050985, 129, 6528 }, - { (float)0.050985, 129, 6657 }, - { (float)0.044859, 134, 6786 }, - { (float)0.044859, 134, 6920 }, - { (float)0.044859, 134, 7054 }, - { (float)0.044859, 134, 7188 }, - { (float)0.040571, 138, 7322 }, - { (float)0.040571, 138, 7460 }, - { (float)0.040571, 138, 7598 }, - { (float)0.040571, 138, 7736 }, - { (float)0.036339, 142, 7874 }, - { (float)0.036339, 142, 8016 }, - { (float)0.036339, 142, 8158 }, - { (float)0.036339, 142, 8300 }, - { (float)0.032139, 146, 8442 }, - { (float)0.032139, 146, 8588 }, - { (float)0.032139, 146, 8734 }, - { (float)0.032139, 146, 8880 }, - { (float)0.027947, 150, 9026 }, - { (float)0.027947, 150, 9176 }, - { (float)0.027947, 150, 9326 }, - { (float)0.023739, 154, 9476 }, - { (float)0.023739, 154, 9630 }, - { (float)0.023739, 154, 9784 }, - { (float)0.023739, 154, 9938 }, - { (float)0.019504, 158, 10092 }, - { (float)0.019504, 158, 10250 }, - { (float)0.019504, 158, 10408 }, - { (float)0.016976, 161, 10566 }, - { (float)0.016976, 161, 10727 }, - { (float)0.016976, 161, 10888 }, - { (float)0.016976, 161, 11049 }, - { (float)0.012639, 165, 11210 }, - { (float)0.012639, 165, 11375 }, - { (float)0.012639, 165, 11540 }, - { (float)0.009991, 168, 11705 }, - { (float)0.009991, 168, 11873 }, - { (float)0.009991, 168, 12041 }, - { (float)0.009016, 170, 12209 }, - { (float)0.009016, 170, 12379 }, - { (float)0.009016, 170, 12549 }, - { (float)0.006217, 173, 12719 }, - { (float)0.006217, 173, 12892 }, - { (float)0.005097, 175, 13065 }, - { (float)0.005097, 175, 13240 }, - { (float)0.005097, 175, 13415 }, - { (float)0.003909, 177, 13590 }, - { (float)0.003909, 177, 13767 }, - { (float)0.002340, 177, 13944 }, - { (float)0.002389, 170, 14121 }, - { (float)0.001068, 164, 14291 }, - { (float)0.001653, 157, 14455 }, - { (float)0.000717, 150, 14612 }, - { (float)0.001614, 143, 14762 }, - { (float)0.000270, 136, 14905 }, - { (float)0.000484, 129, 15041 }, - { (float)0.001103, 123, 15170 }, - { (float)0.001242, 115, 15293 }, - { (float)0.001188, 109, 15408 }, - { (float)0.001011, 103, 15517 }, - { (float)0.000709, 97, 15620 }, - { (float)0.000301, 89, 15717 }, - { (float)0.002416, 82, 15806 }, - { (float)0.003251, 76, 15888 }, - { (float)0.003246, 69, 15964 }, - { (float)0.004141, 62, 16033 }, - { (float)0.005963, 55, 16095 }, - { (float)0.008839, 47, 16150 }, - { (float)0.010490, 40, 16197 }, - { (float)0.016994, 31, 16237 }, - { (float)0.023659, 21, 16268 }, -}; -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ From 6ce27e86b9b5f15af7e3fec4dd0d3b740a816fcc Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Mon, 12 Jul 2010 19:36:42 +0000 Subject: [PATCH 32/43] [DNSAPI] - Merge r45450 from aicom-network-branch svn path=/trunk/; revision=48018 --- reactos/dll/win32/dnsapi/dnsapi.rbuild | 2 +- reactos/dll/win32/dnsapi/dnsapi.spec | 2 ++ .../win32/dnsapi/dnsapi/{free.c => memory.c} | 26 +++++++++++++++++-- 3 files changed, 27 insertions(+), 3 deletions(-) rename reactos/dll/win32/dnsapi/dnsapi/{free.c => memory.c} (64%) diff --git a/reactos/dll/win32/dnsapi/dnsapi.rbuild b/reactos/dll/win32/dnsapi/dnsapi.rbuild index 4c0e31d73b2..bda940fc642 100644 --- a/reactos/dll/win32/dnsapi/dnsapi.rbuild +++ b/reactos/dll/win32/dnsapi/dnsapi.rbuild @@ -12,7 +12,7 @@ adns.c context.c - free.c + memory.c names.c query.c record.c diff --git a/reactos/dll/win32/dnsapi/dnsapi.spec b/reactos/dll/win32/dnsapi/dnsapi.spec index 47eb2d0e0cd..4c739916a5b 100644 --- a/reactos/dll/win32/dnsapi/dnsapi.spec +++ b/reactos/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/reactos/dll/win32/dnsapi/dnsapi/free.c b/reactos/dll/win32/dnsapi/dnsapi/memory.c similarity index 64% rename from reactos/dll/win32/dnsapi/dnsapi/free.c rename to reactos/dll/win32/dnsapi/dnsapi/memory.c index 5bfffa60a60..5d3e6fec263 100644 --- a/reactos/dll/win32/dnsapi/dnsapi/free.c +++ b/reactos/dll/win32/dnsapi/dnsapi/memory.c @@ -1,7 +1,7 @@ /* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries - * FILE: lib/dnsapi/dnsapi/free.c + * FILE: lib/dnsapi/dnsapi/memory.c * PURPOSE: DNSAPI functions built on the ADNS library. * PROGRAMER: Art Yerkes * UPDATE HISTORY: @@ -13,6 +13,29 @@ #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) @@ -32,4 +55,3 @@ DnsFree(PVOID Data, break; } } - From c88bff245c300b15b11274ca0818366320485270 Mon Sep 17 00:00:00 2001 From: Daniel Reimer Date: Mon, 12 Jul 2010 19:55:52 +0000 Subject: [PATCH 33/43] Thanks to Samuel Serapion and his trout, explaining me my fault. svn path=/trunk/; revision=48019 --- reactos/include/reactos/wine/config.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/reactos/include/reactos/wine/config.h b/reactos/include/reactos/wine/config.h index 95686aceef7..7cc40103902 100644 --- a/reactos/include/reactos/wine/config.h +++ b/reactos/include/reactos/wine/config.h @@ -609,7 +609,7 @@ #define HAVE_TIFFIO_H 1 /* Define to the soname of the libtiff library. */ -#define SONAME_LIBTIFF 1 +#define SONAME_LIBTIFF "libtiff" /* Define to 1 if you have the header file. */ #define HAVE_PNG_H 1 @@ -618,7 +618,7 @@ #define HAVE_PNG_SET_EXPAND_GRAY_1_2_4_TO_8 1 /* Define to the soname of the libpng library. */ -#define SONAME_LIBPNG 1 +#define SONAME_LIBPNG "libpng" /* Define to 1 if `direction' is member of `struct ff_effect'. */ /* #undef HAVE_STRUCT_FF_EFFECT_DIRECTION */ From a37a8bfe92eda8d6bf6dc7149dd27ceff59f89b7 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Mon, 12 Jul 2010 22:56:37 +0000 Subject: [PATCH 34/43] [AFD] - Implement IOCTL_AFD_GET_TDI_HANDLES svn path=/trunk/; revision=48020 --- reactos/drivers/network/afd/afd/main.c | 27 ++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/reactos/drivers/network/afd/afd/main.c b/reactos/drivers/network/afd/afd/main.c index 95da3c054bf..03598f008c1 100644 --- a/reactos/drivers/network/afd/afd/main.c +++ b/reactos/drivers/network/afd/afd/main.c @@ -213,6 +213,30 @@ AfdSetDisconnectDataSize(PDEVICE_OBJECT DeviceObject, PIRP Irp, return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, 0); } +static NTSTATUS NTAPI +AfdGetTdiHandles(PDEVICE_OBJECT DeviceObject, PIRP Irp, + PIO_STACK_LOCATION IrpSp) +{ + PFILE_OBJECT FileObject = IrpSp->FileObject; + PAFD_FCB FCB = FileObject->FsContext; + PULONG HandleFlags = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer; + PAFD_TDI_HANDLE_DATA HandleData = Irp->UserBuffer; + + if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp); + + if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG) || + IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(*HandleData)) + return UnlockAndMaybeComplete(FCB, STATUS_BUFFER_TOO_SMALL, Irp, 0); + + if ((*HandleFlags) & AFD_ADDRESS_HANDLE) + HandleData->TdiAddressHandle = FCB->AddressFile.Handle; + + if ((*HandleFlags) & AFD_CONNECTION_HANDLE) + HandleData->TdiConnectionHandle = FCB->Connection.Handle; + + return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, 0); +} + static NTSTATUS NTAPI AfdCreateSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) { @@ -694,8 +718,7 @@ AfdDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp) return AfdSetDisconnectOptionsSize(DeviceObject, Irp, IrpSp); case IOCTL_AFD_GET_TDI_HANDLES: - DbgPrint("IOCTL_AFD_GET_TDI_HANDLES is UNIMPLEMENTED!\n"); - break; + return AfdGetTdiHandles(DeviceObject, Irp, IrpSp); case IOCTL_AFD_DEFER_ACCEPT: DbgPrint("IOCTL_AFD_DEFER_ACCEPT is UNIMPLEMENTED!\n"); From 17f5ddd1e0a68677aa1f4e1318203952a2718119 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Tue, 13 Jul 2010 00:54:52 +0000 Subject: [PATCH 35/43] [WS2_32] - Update the catalog ID when we locate the matching provider - mswsock from aicom-network-branch can successfully create sockets now svn path=/trunk/; revision=48023 --- reactos/dll/win32/ws2_32/misc/catalog.c | 1 + 1 file changed, 1 insertion(+) diff --git a/reactos/dll/win32/ws2_32/misc/catalog.c b/reactos/dll/win32/ws2_32/misc/catalog.c index 0dc13c41de3..53de8b5e970 100644 --- a/reactos/dll/win32/ws2_32/misc/catalog.c +++ b/reactos/dll/win32/ws2_32/misc/catalog.c @@ -146,6 +146,7 @@ LocateProvider(LPWSAPROTOCOL_INFOW lpProtocolInfo) (lpProtocolInfo->iSocketType == SOCK_RAW))) { //LeaveCriticalSection(&CatalogLock); + lpProtocolInfo->dwCatalogEntryId = Provider->ProtocolInfo.dwCatalogEntryId; WS_DbgPrint(MID_TRACE, ("Returning provider at (0x%X).\n", Provider)); return Provider; } From e393257fc358481764b4e78a05704473ca0c8a0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Tue, 13 Jul 2010 21:38:34 +0000 Subject: [PATCH 36/43] [USER32] - Partly merge 48026 svn path=/trunk/; revision=48031 --- reactos/dll/win32/user32/windows/cursoricon.c | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/reactos/dll/win32/user32/windows/cursoricon.c b/reactos/dll/win32/user32/windows/cursoricon.c index 3729adbf852..5e01fe99614 100644 --- a/reactos/dll/win32/user32/windows/cursoricon.c +++ b/reactos/dll/win32/user32/windows/cursoricon.c @@ -1393,6 +1393,7 @@ HICON WINAPI CreateIconIndirect(PICONINFO iconinfo) { BITMAP ColorBitmap; BITMAP MaskBitmap; + ICONINFO safeIconInfo; if(!iconinfo) { @@ -1400,13 +1401,15 @@ HICON WINAPI CreateIconIndirect(PICONINFO iconinfo) return (HICON)0; } - if(!GetObjectW(iconinfo->hbmMask, sizeof(BITMAP), &MaskBitmap)) + safeIconInfo = *iconinfo; + + if(!GetObjectW(safeIconInfo.hbmMask, sizeof(BITMAP), &MaskBitmap)) { return (HICON)0; } /* Try to get color bitmap */ - if (GetObjectW(iconinfo->hbmColor, sizeof(BITMAP), &ColorBitmap)) + if (GetObjectW(safeIconInfo.hbmColor, sizeof(BITMAP), &ColorBitmap)) { /* Compare size of color and mask bitmap*/ if (ColorBitmap.bmWidth != MaskBitmap.bmWidth || @@ -1416,8 +1419,22 @@ HICON WINAPI CreateIconIndirect(PICONINFO iconinfo) SetLastError(ERROR_INVALID_PARAMETER); return (HICON)0; } + /* Test if they are inverted */ + if(ColorBitmap.bmBitsPixel == 1) + { + if(MaskBitmap.bmBitsPixel != 1) + { + safeIconInfo.hbmMask = iconinfo->hbmColor; + safeIconInfo.hbmColor = iconinfo->hbmMask; + } + else + { + /* Wine tests say so */ + safeIconInfo.hbmColor = NULL; + } + } } - return (HICON)NtUserCreateCursorIconHandle(iconinfo, TRUE); + return (HICON)NtUserCreateCursorIconHandle(&safeIconInfo, TRUE); } /****************************************************************************** From 4cc98d4c149b87d6ad765af73baef5cab03dc1df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Wed, 14 Jul 2010 09:54:44 +0000 Subject: [PATCH 37/43] [USER32] - There is no exported "CopyCursor", it's a macro. - There is no "NtUserCreateCursorIconHandle" function in win32k. Use correct functions to create a cursorIcon handle. - Bring in WINE's CreateIconIndirect [WIN32K] - Dereference CursorIcon Object in NtUserCallOneParam - Shared Icons need their bitmaps to be unowned svn path=/trunk/; revision=48034 --- reactos/dll/win32/user32/user32.pspec | 1 - reactos/dll/win32/user32/windows/cursoricon.c | 183 ++++++++++++------ .../win32/win32k/ntuser/cursoricon.c | 15 +- .../win32/win32k/ntuser/simplecall.c | 5 +- 4 files changed, 142 insertions(+), 62 deletions(-) diff --git a/reactos/dll/win32/user32/user32.pspec b/reactos/dll/win32/user32/user32.pspec index d58fb951d1b..8170f9c5f82 100644 --- a/reactos/dll/win32/user32/user32.pspec +++ b/reactos/dll/win32/user32/user32.pspec @@ -759,7 +759,6 @@ ; @ stdcall CharNextExW(long wstr long) ; @ stdcall CharPrevExW(long wstr wstr long) ; @ stub ClientThreadConnect -@ stdcall CopyCursor(long) ; In msdn it is written, that function is available, but in win 2k3 r2 it is absent ; @ stub EnumDisplayDeviceModesA ;(str long ptr long) ; @ stub EnumDisplayDeviceModesW ;(wstr long ptr long) ; @ stdcall GetMenuIndex(ptr ptr) diff --git a/reactos/dll/win32/user32/windows/cursoricon.c b/reactos/dll/win32/user32/windows/cursoricon.c index 5e01fe99614..52a22a47c18 100644 --- a/reactos/dll/win32/user32/windows/cursoricon.c +++ b/reactos/dll/win32/user32/windows/cursoricon.c @@ -67,6 +67,25 @@ static CRITICAL_SECTION_DEBUG critsect_debug = }; static CRITICAL_SECTION IconCrst = { &critsect_debug, -1, 0, 0, 0, 0 }; +/*********************************************************************** + * CreateCursorIconHandle + * + * Creates a handle with everything in there + */ +static +HICON +CreateCursorIconHandle( PICONINFO IconInfo ) +{ + HICON hIcon = (HICON)NtUserCallOneParam(0, //FIXME ? + ONEPARAM_ROUTINE_CREATECURICONHANDLE); + if(!hIcon) + return NULL; + + NtUserSetCursorContents(hIcon, IconInfo); + return hIcon; +} + + /*********************************************************************** * map_fileW @@ -563,7 +582,7 @@ static HICON CURSORICON_CreateIconFromBMI( BITMAPINFO *bmi, IconInfo.hbmColor = color; IconInfo.hbmMask = mask; - return NtUserCreateCursorIconHandle(&IconInfo, FALSE); + return CreateCursorIconHandle(&IconInfo); } @@ -1386,55 +1405,120 @@ BOOL WINAPI GetIconInfo(HICON hIcon, PICONINFO iconinfo) return NtUserGetIconInfo(hIcon, iconinfo, 0, 0, 0, 0); } +/* copy an icon bitmap, even when it can't be selected into a DC */ +/* helper for CreateIconIndirect */ +static void stretch_blt_icon( HDC hdc_dst, int dst_x, int dst_y, int dst_width, int dst_height, + HBITMAP src, int width, int height ) +{ + HDC hdc = CreateCompatibleDC( 0 ); + + if (!SelectObject( hdc, src )) /* do it the hard way */ + { + BITMAPINFO *info; + void *bits; + + if (!(info = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET( BITMAPINFO, bmiColors[256] )))) return; + info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + info->bmiHeader.biWidth = width; + info->bmiHeader.biHeight = height; + info->bmiHeader.biPlanes = GetDeviceCaps( hdc_dst, PLANES ); + info->bmiHeader.biBitCount = GetDeviceCaps( hdc_dst, BITSPIXEL ); + info->bmiHeader.biCompression = BI_RGB; + info->bmiHeader.biSizeImage = height * get_dib_width_bytes( width, info->bmiHeader.biBitCount ); + info->bmiHeader.biXPelsPerMeter = 0; + info->bmiHeader.biYPelsPerMeter = 0; + info->bmiHeader.biClrUsed = 0; + info->bmiHeader.biClrImportant = 0; + bits = HeapAlloc( GetProcessHeap(), 0, info->bmiHeader.biSizeImage ); + if (bits && GetDIBits( hdc, src, 0, height, bits, info, DIB_RGB_COLORS )) + StretchDIBits( hdc_dst, dst_x, dst_y, dst_width, dst_height, + 0, 0, width, height, bits, info, DIB_RGB_COLORS, SRCCOPY ); + + HeapFree( GetProcessHeap(), 0, bits ); + HeapFree( GetProcessHeap(), 0, info ); + } + else StretchBlt( hdc_dst, dst_x, dst_y, dst_width, dst_height, hdc, 0, 0, width, height, SRCCOPY ); + + DeleteDC( hdc ); +} + /********************************************************************** * CreateIconIndirect (USER32.@) */ HICON WINAPI CreateIconIndirect(PICONINFO iconinfo) { - BITMAP ColorBitmap; - BITMAP MaskBitmap; - ICONINFO safeIconInfo; + BITMAP bmpXor, bmpAnd; + HBITMAP color = 0, mask; + int width, height; + HDC hdc; + ICONINFO iinfo; - if(!iconinfo) - { - SetLastError(ERROR_INVALID_PARAMETER); - return (HICON)0; - } + TRACE("color %p, mask %p, hotspot %ux%u, fIcon %d\n", + iconinfo->hbmColor, iconinfo->hbmMask, + iconinfo->xHotspot, iconinfo->yHotspot, iconinfo->fIcon); - safeIconInfo = *iconinfo; + if (!iconinfo->hbmMask) return 0; - if(!GetObjectW(safeIconInfo.hbmMask, sizeof(BITMAP), &MaskBitmap)) - { - return (HICON)0; - } + GetObjectW( iconinfo->hbmMask, sizeof(bmpAnd), &bmpAnd ); + TRACE("mask: width %d, height %d, width bytes %d, planes %u, bpp %u\n", + bmpAnd.bmWidth, bmpAnd.bmHeight, bmpAnd.bmWidthBytes, + bmpAnd.bmPlanes, bmpAnd.bmBitsPixel); - /* Try to get color bitmap */ - if (GetObjectW(safeIconInfo.hbmColor, sizeof(BITMAP), &ColorBitmap)) - { - /* Compare size of color and mask bitmap*/ - if (ColorBitmap.bmWidth != MaskBitmap.bmWidth || - ColorBitmap.bmHeight != MaskBitmap.bmHeight) - { - ERR("Color and mask size are different!"); - SetLastError(ERROR_INVALID_PARAMETER); - return (HICON)0; - } - /* Test if they are inverted */ - if(ColorBitmap.bmBitsPixel == 1) - { - if(MaskBitmap.bmBitsPixel != 1) - { - safeIconInfo.hbmMask = iconinfo->hbmColor; - safeIconInfo.hbmColor = iconinfo->hbmMask; - } - else - { - /* Wine tests say so */ - safeIconInfo.hbmColor = NULL; - } - } - } - return (HICON)NtUserCreateCursorIconHandle(&safeIconInfo, TRUE); + if (iconinfo->hbmColor) + { + GetObjectW( iconinfo->hbmColor, sizeof(bmpXor), &bmpXor ); + TRACE("color: width %d, height %d, width bytes %d, planes %u, bpp %u\n", + bmpXor.bmWidth, bmpXor.bmHeight, bmpXor.bmWidthBytes, + bmpXor.bmPlanes, bmpXor.bmBitsPixel); + + width = bmpXor.bmWidth; + height = bmpXor.bmHeight; + if (bmpXor.bmPlanes * bmpXor.bmBitsPixel != 1) + { + color = CreateCompatibleBitmap( screen_dc, width, height ); + mask = CreateBitmap( width, height, 1, 1, NULL ); + } + else mask = CreateBitmap( width, height * 2, 1, 1, NULL ); + } + else + { + width = bmpAnd.bmWidth; + height = bmpAnd.bmHeight; + mask = CreateBitmap( width, height, 1, 1, NULL ); + } + + hdc = CreateCompatibleDC( 0 ); + SelectObject( hdc, mask ); + stretch_blt_icon( hdc, 0, 0, width, height, iconinfo->hbmMask, bmpAnd.bmWidth, bmpAnd.bmHeight ); + + if (color) + { + SelectObject( hdc, color ); + stretch_blt_icon( hdc, 0, 0, width, height, iconinfo->hbmColor, width, height ); + } + else if (iconinfo->hbmColor) + { + stretch_blt_icon( hdc, 0, height, width, height, iconinfo->hbmColor, width, height ); + } + else height /= 2; + + DeleteDC( hdc ); + + iinfo.hbmColor = color ; + iinfo.hbmMask = mask ; + iinfo.fIcon = iconinfo->fIcon; + if (iinfo.fIcon) + { + iinfo.xHotspot = width / 2; + iinfo.yHotspot = height / 2; + } + else + { + iinfo.xHotspot = iconinfo->xHotspot; + iinfo.yHotspot = iconinfo->yHotspot; + } + + return CreateCursorIconHandle(&iinfo); } /****************************************************************************** @@ -2047,23 +2131,6 @@ GetCursorPos(LPPOINT lpPoint) return res; } -#undef CopyCursor -/* - * @implemented - */ -HCURSOR -WINAPI -CopyCursor(HCURSOR pcur) -{ - ICONINFO IconInfo; - - if(GetIconInfo((HANDLE)pcur, &IconInfo)) - { - return (HCURSOR)NtUserCreateCursorIconHandle(&IconInfo, FALSE); - } - return (HCURSOR)0; -} - /* INTERNAL ******************************************************************/ /* This callback routine is called directly after switching to gui mode */ diff --git a/reactos/subsystems/win32/win32k/ntuser/cursoricon.c b/reactos/subsystems/win32/win32k/ntuser/cursoricon.c index f740d327ce9..03f4431e18f 100644 --- a/reactos/subsystems/win32/win32k/ntuser/cursoricon.c +++ b/reactos/subsystems/win32/win32k/ntuser/cursoricon.c @@ -1030,11 +1030,13 @@ NtUserSetCursorContents( } /* Delete old bitmaps */ - if (CurIcon->IconInfo.hbmColor != IconInfo.hbmColor) + if ((CurIcon->IconInfo.hbmColor) + && (CurIcon->IconInfo.hbmColor != IconInfo.hbmColor)) { GreDeleteObject(CurIcon->IconInfo.hbmColor); } - if (CurIcon->IconInfo.hbmMask != IconInfo.hbmMask) + if ((CurIcon->IconInfo.hbmMask) + && (CurIcon->IconInfo.hbmMask != IconInfo.hbmMask)) { GreDeleteObject(CurIcon->IconInfo.hbmMask); } @@ -1226,6 +1228,15 @@ NtUserSetCursorIconData( } done: + if(Ret) + { + /* This icon is shared now */ + GDIOBJ_SetOwnership(CurIcon->IconInfo.hbmMask, NULL); + if(CurIcon->IconInfo.hbmColor) + { + GDIOBJ_SetOwnership(CurIcon->IconInfo.hbmColor, NULL); + } + } UserDereferenceObject(CurIcon); RETURN(Ret); diff --git a/reactos/subsystems/win32/win32k/ntuser/simplecall.c b/reactos/subsystems/win32/win32k/ntuser/simplecall.c index f46a75da2aa..d25ead5dc46 100644 --- a/reactos/subsystems/win32/win32k/ntuser/simplecall.c +++ b/reactos/subsystems/win32/win32k/ntuser/simplecall.c @@ -195,6 +195,7 @@ NtUserCallOneParam( case ONEPARAM_ROUTINE_CREATECURICONHANDLE: { PCURICON_OBJECT CurIcon; + DWORD_PTR Result ; if (!(CurIcon = IntCreateCurIconHandle())) { @@ -202,7 +203,9 @@ NtUserCallOneParam( RETURN(0); } - RETURN((DWORD_PTR)CurIcon->Self); + Result = (DWORD_PTR)CurIcon->Self; + UserDereferenceObject(CurIcon); + RETURN(Result); } case ONEPARAM_ROUTINE_GETCURSORPOSITION: From 98b46cd0c4cd6e0b4be36fdf6c4f41a598d7fa81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Wed, 14 Jul 2010 10:23:13 +0000 Subject: [PATCH 38/43] Bye bye NtUserCreateCursorHandle. Thanks GedMurphy for explaining me how to suppress that. Please clean win32k after this commit. svn path=/trunk/; revision=48035 --- reactos/include/reactos/win32k/ntuser.h | 7 -- .../win32/win32k/ntuser/cursoricon.c | 79 ------------------- reactos/subsystems/win32/win32k/w32ksvc.db | 1 - 3 files changed, 87 deletions(-) diff --git a/reactos/include/reactos/win32k/ntuser.h b/reactos/include/reactos/win32k/ntuser.h index 778cd3da469..fec4e9b437d 100644 --- a/reactos/include/reactos/win32k/ntuser.h +++ b/reactos/include/reactos/win32k/ntuser.h @@ -3165,13 +3165,6 @@ NtUserBuildMenuItemList( ULONG nBufSize, DWORD Reserved); -/* Use ONEPARAM_ROUTINE_CREATEEMPTYCURSOROBJECT (0x21) ? */ -HANDLE -NTAPI -NtUserCreateCursorIconHandle( - PICONINFO IconInfo, - BOOL Indirect); - /* Should be done in usermode and use NtUserGetCPD. */ ULONG_PTR diff --git a/reactos/subsystems/win32/win32k/ntuser/cursoricon.c b/reactos/subsystems/win32/win32k/ntuser/cursoricon.c index 03f4431e18f..03f00530dee 100644 --- a/reactos/subsystems/win32/win32k/ntuser/cursoricon.c +++ b/reactos/subsystems/win32/win32k/ntuser/cursoricon.c @@ -491,85 +491,6 @@ IntCleanupCurIcons(struct _EPROCESS *Process, PPROCESSINFO Win32Process) } -/* - * @implemented - */ -HANDLE -APIENTRY -NtUserCreateCursorIconHandle(PICONINFO IconInfo OPTIONAL, BOOL Indirect) -{ - PCURICON_OBJECT CurIcon; - PSURFACE psurfBmp; - NTSTATUS Status; - HANDLE Ret; - DECLARE_RETURN(HANDLE); - - DPRINT("Enter NtUserCreateCursorIconHandle\n"); - UserEnterExclusive(); - - if (!(CurIcon = IntCreateCurIconHandle())) - { - SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); - RETURN((HANDLE)0); - } - - Ret = CurIcon->Self; - - if (IconInfo) - { - Status = MmCopyFromCaller(&CurIcon->IconInfo, IconInfo, sizeof(ICONINFO)); - if (NT_SUCCESS(Status)) - { - /* Copy bitmaps and size info */ - if (Indirect) - { - // FIXME: WTF? - CurIcon->IconInfo.hbmMask = BITMAP_CopyBitmap(CurIcon->IconInfo.hbmMask); - CurIcon->IconInfo.hbmColor = BITMAP_CopyBitmap(CurIcon->IconInfo.hbmColor); - } - if (CurIcon->IconInfo.hbmColor && - (psurfBmp = SURFACE_LockSurface(CurIcon->IconInfo.hbmColor))) - { - CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx; - CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy; - SURFACE_UnlockSurface(psurfBmp); - GDIOBJ_SetOwnership(CurIcon->IconInfo.hbmColor, NULL); - } - if (CurIcon->IconInfo.hbmMask && - (psurfBmp = SURFACE_LockSurface(CurIcon->IconInfo.hbmMask))) - { - if (CurIcon->IconInfo.hbmColor == NULL) - { - CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx; - CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy >> 1; - } - SURFACE_UnlockSurface(psurfBmp); - GDIOBJ_SetOwnership(CurIcon->IconInfo.hbmMask, NULL); - } - - /* Calculate icon hotspot */ - if (CurIcon->IconInfo.fIcon == TRUE) - { - CurIcon->IconInfo.xHotspot = CurIcon->Size.cx >> 1; - CurIcon->IconInfo.yHotspot = CurIcon->Size.cy >> 1; - } - } - else - { - SetLastNtError(Status); - /* FIXME - Don't exit here */ - } - } - - UserDereferenceObject(CurIcon); - RETURN(Ret); - -CLEANUP: - DPRINT("Leave NtUserCreateCursorIconHandle, ret=%i\n",_ret_); - UserLeave(); - END_CLEANUP; -} - /* * @implemented */ diff --git a/reactos/subsystems/win32/win32k/w32ksvc.db b/reactos/subsystems/win32/win32k/w32ksvc.db index 0b90145a90f..00701aa1f28 100644 --- a/reactos/subsystems/win32/win32k/w32ksvc.db +++ b/reactos/subsystems/win32/win32k/w32ksvc.db @@ -683,7 +683,6 @@ NtGdiOffsetViewportOrgEx 4 NtGdiOffsetWindowOrgEx 4 # NtUserBuildMenuItemList 4 -NtUserCreateCursorIconHandle 2 NtUserGetMenuDefaultItem 3 NtUserGetLastInputInfo 1 NtUserGetMinMaxInfo 3 From 06f1bc2133ae9b6385055fa9eaec437e170a61d4 Mon Sep 17 00:00:00 2001 From: Daniel Reimer Date: Wed, 14 Jul 2010 10:59:32 +0000 Subject: [PATCH 39/43] Bug 5501: [PATCH] Adding Wing32 support by Carlo Bramini svn path=/trunk/; revision=48036 --- reactos/boot/bootdata/packages/reactos.dff | 63 +++++---- reactos/dll/win32/win32.rbuild | 3 + reactos/dll/win32/wing32/wing32.c | 141 +++++++++++++++++++++ reactos/dll/win32/wing32/wing32.rbuild | 11 ++ reactos/dll/win32/wing32/wing32.spec | 10 ++ 5 files changed, 200 insertions(+), 28 deletions(-) create mode 100644 reactos/dll/win32/wing32/wing32.c create mode 100644 reactos/dll/win32/wing32/wing32.rbuild create mode 100644 reactos/dll/win32/wing32/wing32.spec diff --git a/reactos/boot/bootdata/packages/reactos.dff b/reactos/boot/bootdata/packages/reactos.dff index a9b97bb2c02..8019828ae15 100644 --- a/reactos/boot/bootdata/packages/reactos.dff +++ b/reactos/boot/bootdata/packages/reactos.dff @@ -44,9 +44,8 @@ base\applications\cmdutils\reg\reg.exe 1 base\applications\cmdutils\xcopy\xcopy.exe 1 base\applications\control\control.exe 1 base\applications\dxdiag\dxdiag.exe 1 +base\applications\extrac32\extrac32.exe 1 base\applications\fontview\fontview.exe 1 -base\applications\mscutils\devmgmt\devmgmt.exe 1 -base\applications\mscutils\eventvwr\eventvwr.exe 1 base\applications\games\solitaire\sol.exe 1 base\applications\games\spider\spider.exe 1 base\applications\games\winemine\winemine.exe 1 @@ -57,16 +56,20 @@ base\applications\logoff\logoff.exe 1 base\applications\magnify\magnify.exe 1 base\applications\mplay32\mplay32.exe 1 base\applications\msconfig\msconfig.exe 1 +base\applications\mscutils\devmgmt\devmgmt.exe 1 +base\applications\mscutils\eventvwr\eventvwr.exe 1 +base\applications\mscutils\servman\servman.exe 1 base\applications\mstsc\mstsc.exe 1 base\applications\network\arp\arp.exe 1 base\applications\network\dwnl\dwnl.exe 1 -base\applications\network\route\route.exe 1 base\applications\network\finger\finger.exe 1 base\applications\network\ftp\ftp.exe 1 base\applications\network\ipconfig\ipconfig.exe 1 +base\applications\network\net\net.exe 1 base\applications\network\netstat\netstat.exe 1 base\applications\network\nslookup\nslookup.exe 1 base\applications\network\ping\ping.exe 1 +base\applications\network\route\route.exe 1 base\applications\network\telnet\telnet.exe 1 base\applications\network\tracert\tracert.exe 1 base\applications\network\whois\whois.exe 1 @@ -79,7 +82,6 @@ base\applications\regedt32\regedt32.exe 1 base\applications\sc\sc.exe 1 base\applications\screensavers\3dtext\3dtext.scr 1 base\applications\screensavers\logon\logon.scr 1 -base\applications\mscutils\servman\servman.exe 1 base\applications\shutdown\shutdown.exe 1 base\applications\sndrec32\sndrec32.exe 1 base\applications\sndvol32\sndvol32.exe 1 @@ -93,12 +95,12 @@ base\services\audiosrv\audiosrv.exe 1 base\services\eventlog\eventlog.exe 1 base\services\rpcss\rpcss.exe 1 base\services\spoolsv\spoolsv.exe 1 +base\services\svchost\svchost.exe 1 base\services\tcpsvcs\tcpsvcs.exe 1 -base\services\telnetd\telnetd.exe 1 base\services\tcpsvcs\quotes 5 +base\services\telnetd\telnetd.exe 1 base\services\umpnpmgr\umpnpmgr.exe 1 base\services\wlansvc\wlansvc.exe 1 -base\services\svchost\svchost.exe 1 base\setup\setup\setup.exe 1 base\setup\vmwinst\vmwinst.exe 1 @@ -111,6 +113,7 @@ base\shell\explorer-new\explorer_new.exe 4 optional base\system\autochk\autochk.exe 1 base\system\bootok\bootok.exe 1 +base\system\expand\expand.exe 1 base\system\format\format.exe 1 base\system\lsass\lsass.exe 1 base\system\msiexec\msiexec.exe 1 @@ -118,19 +121,17 @@ base\system\regsvr32\regsvr32.exe 1 base\system\rundll32\rundll32.exe 1 base\system\runonce\runonce.exe 1 base\system\services\services.exe 1 +base\system\smss\smss.exe 1 base\system\userinit\userinit.exe 1 base\system\winlogon\winlogon.exe 1 -base\system\expand\expand.exe 1 -base\system\smss\smss.exe 1 - ; Dynamic Link Libraries -dll\3rdparty\mesa32\mesa32.dll 1 +dll\3rdparty\dxtn\dxtn.dll 1 optional dll\3rdparty\libjpeg\libjpeg.dll 1 dll\3rdparty\libpng\libpng.dll 1 dll\3rdparty\libtiff\libtiff.dll 1 dll\3rdparty\libxslt\libxslt.dll 1 -dll\3rdparty\dxtn\dxtn.dll 1 optional +dll\3rdparty\mesa32\mesa32.dll 1 dll\cpl\access\access.cpl 1 dll\cpl\appwiz\appwiz.cpl 1 @@ -153,6 +154,8 @@ dll\cpl\timedate\timedate.cpl 1 dll\directx\amstream\amstream.dll 1 ;dll\directx\bdaplgin\bdaplgin.ax 1 +dll\directx\d3d8thk\d3d8thk.dll 1 +dll\directx\devenum\devenum.dll 1 dll\directx\dinput\dinput.dll 1 dll\directx\dinput8\dinput8.dll 1 dll\directx\dmusic\dmusic.dll 1 @@ -160,19 +163,17 @@ dll\directx\dplay\dplay.dll 1 dll\directx\dplayx\dplayx.dll 1 dll\directx\dsound\dsound.dll 1 dll\directx\dxdiagn\dxdiagn.dll 1 -dll\directx\wine\ddraw\ddraw.dll 1 -dll\directx\d3d8thk\d3d8thk.dll 1 -dll\directx\devenum\devenum.dll 1 dll\directx\ksproxy\ksproxy.ax 1 dll\directx\ksuser\ksuser.dll 1 dll\directx\msdmo\msdmo.dll 1 ;dll\directx\msdvbnp\msdvbnp.ax 1 ;dll\directx\msvidctl\msvidctl.dll 1 -dll\directx\quartz\quartz.dll 1 dll\directx\qedit\qedit.dll 1 +dll\directx\quartz\quartz.dll 1 +dll\directx\wine\ddraw\ddraw.dll 1 dll\directx\wine\d3d8\d3d8.dll 1 -dll\directx\wine\wined3d\wined3d.dll 1 dll\directx\wine\d3d9\d3d9.dll 1 +dll\directx\wine\wined3d\wined3d.dll 1 dll\keyboard\kbda1\kbda1.dll 1 dll\keyboard\kbda2\kbda2.dll 1 @@ -182,12 +183,12 @@ dll\keyboard\kbdarme\kbdarme.dll 1 dll\keyboard\kbdarmw\kbdarmw.dll 1 dll\keyboard\kbdaze\kbdaze.dll 1 dll\keyboard\kbdazel\kbdazel.dll 1 +dll\keyboard\kbdbe\kbdbe.dll 1 +dll\keyboard\kbdbga\kbdbga.dll 1 dll\keyboard\kbdbgm\kbdbgm.dll 1 dll\keyboard\kbdbgt\kbdbgt.dll 1 dll\keyboard\kbdblr\kbdblr.dll 1 dll\keyboard\kbdbr\kbdbr.dll 1 -dll\keyboard\kbdbga\kbdbga.dll 1 -dll\keyboard\kbdbe\kbdbe.dll 1 dll\keyboard\kbdbur\kbdbur.dll 1 dll\keyboard\kbdcan\kbdcan.dll 1 dll\keyboard\kbdcr\kbdcr.dll 1 @@ -203,8 +204,8 @@ dll\keyboard\kbdfr\kbdfr.dll 1 dll\keyboard\kbdgeo\kbdgeo.dll 1 dll\keyboard\kbdgerg\kbdgerg.dll 1 dll\keyboard\kbdgneo\kbdgneo.dll 1 -dll\keyboard\kbdgrist\kbdgrist.dll 1 dll\keyboard\kbdgr\kbdgr.dll 1 +dll\keyboard\kbdgrist\kbdgrist.dll 1 dll\keyboard\kbdhe\kbdhe.dll 1 dll\keyboard\kbdheb\kbdheb.dll 1 dll\keyboard\kbdhu\kbdhu.dll 1 @@ -218,6 +219,7 @@ dll\keyboard\kbdir\kbdir.dll 1 dll\keyboard\kbdit\kbdit.dll 1 dll\keyboard\kbdja\kbdja.dll 1 dll\keyboard\kbdkaz\kbdkaz.dll 1 +dll\keyboard\kbdko\kbdko.dll 1 dll\keyboard\kbdla\kbdla.dll 1 dll\keyboard\kbdlt1\kbdlt1.dll 1 dll\keyboard\kbdlv\kbdlv.dll 1 @@ -252,16 +254,15 @@ dll\keyboard\kbduzb\kbduzb.dll 1 dll\keyboard\kbdvntc\kbdvntc.dll 1 dll\keyboard\kbdycc\kbdycc.dll 1 dll\keyboard\kbdycl\kbdycl.dll 1 -dll\keyboard\kbdko\kbdko.dll 1 dll\ntdll\ntdll.dll 1 dll\win32\acledit\acledit.dll 1 dll\win32\aclui\aclui.dll 1 dll\win32\activeds\activeds.dll 1 +dll\win32\actxprxy\actxprxy.dll 1 dll\win32\advapi32\advapi32.dll 1 dll\win32\advpack\advpack.dll 1 -dll\win32\actxprxy\actxprxy.dll 1 dll\win32\atl\atl.dll 1 dll\win32\authz\authz.dll 1 dll\win32\avicap32\avicap32.dll 1 @@ -287,10 +288,10 @@ dll\win32\cryptnet\cryptnet.dll 1 dll\win32\cryptui\cryptui.dll 1 dll\win32\dbghelp\dbghelp.dll 1 dll\win32\dciman32\dciman32.dll 1 -dll\win32\dwmapi\dwmapi.dll 1 dll\win32\devmgr\devmgr.dll 1 dll\win32\dhcpcsvc\dhcpcsvc.dll 1 dll\win32\dnsapi\dnsapi.dll 1 +dll\win32\dwmapi\dwmapi.dll 1 dll\win32\faultrep\faultrep.dll 1 dll\win32\fmifs\fmifs.dll 1 dll\win32\fusion\fusion.dll 1 @@ -320,6 +321,7 @@ dll\win32\kernel32\kernel32.dll 1 dll\win32\loadperf\loadperf.dll 1 dll\win32\localspl\localspl.dll 1 dll\win32\localui\localui.dll 1 +dll\win32\lpk\lpk.dll 1 dll\win32\lsasrv\lsasrv.dll 1 dll\win32\lz32\lz32.dll 1 dll\win32\mapi32\mapi32.dll 1 @@ -399,8 +401,8 @@ dll\win32\query\query.dll 1 dll\win32\rasadhlp\rasadhlp.dll 1 dll\win32\rasapi32\rasapi32.dll 1 dll\win32\rasdlg\rasdlg.dll 1 -dll\win32\resutils\resutils.dll 1 dll\win32\rasman\rasman.dll 1 +dll\win32\resutils\resutils.dll 1 dll\win32\riched20\riched20.dll 1 dll\win32\riched32\riched32.dll 1 dll\win32\rpcrt4\rpcrt4.dll 1 @@ -425,6 +427,7 @@ dll\win32\shimgvw\shimgvw.dll 1 dll\win32\shlwapi\shlwapi.dll 1 dll\win32\slbcsp\slbcsp.dll 1 dll\win32\smdll\smdll.dll 1 +dll\win32\sndblst\sndblst.dll 1 dll\win32\snmpapi\snmpapi.dll 1 dll\win32\softpub\softpub.dll 1 dll\win32\spoolss\spoolss.dll 1 @@ -452,16 +455,19 @@ dll\win32\usp10\usp10.dll 1 dll\win32\uxtheme\uxtheme.dll 1 dll\win32\vdmdbg\vdmdbg.dll 1 dll\win32\version\version.dll 1 +dll\win32\wdmaud.drv\wdmaud.drv 1 dll\win32\windowscodecs\windowscodecs.dll 1 dll\win32\winemp3.acm\winemp3.acm 1 dll\win32\winfax\winfax.dll 1 +dll\win32\wing32\wing32.dll 1 dll\win32\winhttp\winhttp.dll 1 dll\win32\wininet\wininet.dll 1 dll\win32\winmm\winmm.dll 1 +dll\win32\winmm\midimap\midimap.dll 1 dll\win32\winspool\winspool.drv 1 dll\win32\winsta\winsta.dll 1 -dll\win32\wlanapi\wlanapi.dll 1 dll\win32\wintrust\wintrust.dll 1 +dll\win32\wlanapi\wlanapi.dll 1 dll\win32\wldap32\wldap32.dll 1 dll\win32\wmi\wmi.dll 1 dll\win32\ws2_32\ws2_32.dll 1 @@ -476,18 +482,19 @@ dll\win32\xinput1_2\xinput1_2.dll 1 dll\win32\xinput1_3\xinput1_3.dll 1 dll\win32\xinput9_1_0\xinput9_1_0.dll 1 dll\win32\xmllite\xmllite.dll 1 -dll\win32\winmm\midimap\midimap.dll 1 -dll\win32\wdmaud.drv\wdmaud.drv 1 ; Shell Extensions dll\shellext\deskadp\deskadp.dll 1 dll\shellext\deskmon\deskmon.dll 1 +dll\shellext\devcpux\devcpux.dll 1 +dll\shellext\fontext\fontext.dll 1 +dll\shellext\slayer\slayer.dll 1 ; Drivers -drivers\base\bootvid\bootvid.dll 1 drivers\base\beep\beep.sys 2 -drivers\base\null\null.sys 2 +drivers\base\bootvid\bootvid.dll 1 drivers\base\nmidebug\nmidebug.sys 2 +drivers\base\null\null.sys 2 drivers\battery\battc\battc.sys 2 diff --git a/reactos/dll/win32/win32.rbuild b/reactos/dll/win32/win32.rbuild index 02b8f89475d..5cd3d741736 100644 --- a/reactos/dll/win32/win32.rbuild +++ b/reactos/dll/win32/win32.rbuild @@ -604,6 +604,9 @@ + + + diff --git a/reactos/dll/win32/wing32/wing32.c b/reactos/dll/win32/wing32/wing32.c new file mode 100644 index 00000000000..b8ea30c5d53 --- /dev/null +++ b/reactos/dll/win32/wing32/wing32.c @@ -0,0 +1,141 @@ +/* + * WinG support + * + * Copyright 2007 Dmitry Timoshkov + * + * 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 + */ + +#define WIN32_LEAN_AND_MEAN +#include + +/*********************************************************************** + * WinGCreateDC (WING32.@) + */ +HDC CALLBACK WinGCreateDC( void ) +{ + return CreateCompatibleDC( NULL ); +} + +/*********************************************************************** + * WinGRecommendDIBFormat (WING32.@) + */ +BOOL CALLBACK WinGRecommendDIBFormat( BITMAPINFO *bmi ) +{ + if (!bmi) return FALSE; + + bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmi->bmiHeader.biWidth = 320; + bmi->bmiHeader.biHeight = -1; + bmi->bmiHeader.biPlanes = 1; + bmi->bmiHeader.biBitCount = 8; + bmi->bmiHeader.biCompression = BI_RGB; + bmi->bmiHeader.biSizeImage = 0; + bmi->bmiHeader.biXPelsPerMeter = 0; + bmi->bmiHeader.biYPelsPerMeter = 0; + bmi->bmiHeader.biClrUsed = 0; + bmi->bmiHeader.biClrImportant = 0; + + return TRUE; +} + +/*********************************************************************** + * WinGCreateBitmap (WING32.@) + */ +HBITMAP CALLBACK WinGCreateBitmap( HDC hdc, BITMAPINFO *bmi, void **bits ) +{ + return CreateDIBSection( hdc, bmi, 0, bits, 0, 0 ); +} + +/*********************************************************************** + * WinGGetDIBPointer (WING32.@) + */ +void * CALLBACK WinGGetDIBPointer( HBITMAP hbmp, BITMAPINFO *bmi ) +{ + DIBSECTION ds; + + if (GetObject( hbmp, sizeof(ds), &ds ) == sizeof(ds)) + { + if (bmi != NULL) + memcpy( &bmi->bmiHeader, &ds.dsBmih, sizeof(*bmi) ); + + return ds.dsBm.bmBits; + } + return NULL; +} + +/*********************************************************************** + * WinGSetDIBColorTable (WING32.@) + */ +UINT CALLBACK WinGSetDIBColorTable( HDC hdc, UINT start, UINT end, RGBQUAD *colors ) +{ + return SetDIBColorTable( hdc, start, end, colors ); +} + +/*********************************************************************** + * WinGGetDIBColorTable (WING32.@) + */ +UINT CALLBACK WinGGetDIBColorTable( HDC hdc, UINT start, UINT end, RGBQUAD *colors ) +{ + return GetDIBColorTable( hdc, start, end, colors ); +} + +/*********************************************************************** + * WinGCreateHalfTonePalette (WING32.@) + */ +HPALETTE CALLBACK WinGCreateHalfTonePalette( void ) +{ + HDC hdc; + HPALETTE hpal; + + hdc = GetDC( NULL ); + hpal = CreateHalftonePalette( hdc ); + ReleaseDC( NULL, hdc ); + + return hpal; +} + +/*********************************************************************** + * WinGCreateHalfToneBrush (WING32.@) + */ +HBRUSH CALLBACK WinGCreateHalfToneBrush( HDC hdc, COLORREF color, INT type ) +{ + return CreateSolidBrush( color ); +} + +/*********************************************************************** + * WinGStretchBlt (WING32.@) + */ +BOOL CALLBACK WinGStretchBlt( HDC hdcDst, INT xDst, INT yDst, INT widthDst, INT heightDst, + HDC hdcSrc, INT xSrc, INT ySrc, INT widthSrc, INT heightSrc ) +{ + int old_blt_mode; + BOOL ret; + + old_blt_mode = SetStretchBltMode( hdcDst, COLORONCOLOR ); + ret = StretchBlt( hdcDst, xDst, yDst, widthDst, heightDst, + hdcSrc, xSrc, ySrc, widthSrc, heightSrc, SRCCOPY ); + SetStretchBltMode( hdcDst, old_blt_mode ); + return ret; +} + +/*********************************************************************** + * WinGBitBlt (WING32.@) + */ +BOOL CALLBACK WinGBitBlt( HDC hdcDst, INT xDst, INT yDst, INT width, + INT height, HDC hdcSrc, INT xSrc, INT ySrc ) +{ + return BitBlt( hdcDst, xDst, yDst, width, height, hdcSrc, xSrc, ySrc, SRCCOPY ); +} diff --git a/reactos/dll/win32/wing32/wing32.rbuild b/reactos/dll/win32/wing32/wing32.rbuild new file mode 100644 index 00000000000..4b18189a82a --- /dev/null +++ b/reactos/dll/win32/wing32/wing32.rbuild @@ -0,0 +1,11 @@ + + + + + + user32 + gdi32 + wing32.c + --add-stdcall-alias + + diff --git a/reactos/dll/win32/wing32/wing32.spec b/reactos/dll/win32/wing32/wing32.spec new file mode 100644 index 00000000000..67d3bb88a20 --- /dev/null +++ b/reactos/dll/win32/wing32/wing32.spec @@ -0,0 +1,10 @@ +@ stdcall WinGBitBlt(long long long long long long long long) +@ stdcall WinGCreateBitmap(long ptr ptr) +@ stdcall WinGCreateDC() +@ stdcall WinGCreateHalfToneBrush(long long long) +@ stdcall WinGCreateHalfTonePalette() +@ stdcall WinGGetDIBColorTable(long long long ptr) +@ stdcall WinGGetDIBPointer(long ptr) +@ stdcall WinGRecommendDIBFormat(ptr) +@ stdcall WinGSetDIBColorTable(long long long ptr) +@ stdcall WinGStretchBlt(long long long long long long long long long long) From 89324d249387751083dca702144b575a9017db80 Mon Sep 17 00:00:00 2001 From: Daniel Reimer Date: Wed, 14 Jul 2010 11:00:31 +0000 Subject: [PATCH 40/43] Bye, old Downloader. svn path=/trunk/; revision=48037 --- reactos/base/applications/applications.rbuild | 3 - .../base/applications/downloader/download.c | 402 -------- .../applications/downloader/downloader.rbuild | 26 - .../applications/downloader/downloader.rc | 10 - .../applications/downloader/downloader.xml | 326 ------- .../applications/downloader/lang/bg-BG.rc | 60 -- .../applications/downloader/lang/de-DE.rc | 61 -- .../applications/downloader/lang/el-GR.rc | 61 -- .../applications/downloader/lang/en-US.rc | 61 -- .../applications/downloader/lang/es-ES.rc | 66 -- .../applications/downloader/lang/fr-FR.rc | 61 -- .../applications/downloader/lang/id-ID.rc | 61 -- .../applications/downloader/lang/it-IT.rc | 61 -- .../applications/downloader/lang/ja-JP.rc | 61 -- .../applications/downloader/lang/lt-LT.rc | 63 -- .../applications/downloader/lang/no-NO.rc | 61 -- .../applications/downloader/lang/pl-PL.rc | 68 -- .../applications/downloader/lang/ru-RU.rc | 63 -- .../applications/downloader/lang/sk-SK.rc | 67 -- .../applications/downloader/lang/uk-UA.rc | 69 -- reactos/base/applications/downloader/main.c | 922 ------------------ .../applications/downloader/patches/d2fix.c | 36 - .../base/applications/downloader/resources.h | 71 -- .../applications/downloader/resources/0.bmp | Bin 822 -> 0 bytes .../applications/downloader/resources/1.bmp | Bin 822 -> 0 bytes .../applications/downloader/resources/10.bmp | Bin 824 -> 0 bytes .../applications/downloader/resources/11.bmp | Bin 1080 -> 0 bytes .../applications/downloader/resources/12.bmp | Bin 1080 -> 0 bytes .../applications/downloader/resources/13.bmp | Bin 1080 -> 0 bytes .../applications/downloader/resources/2.bmp | Bin 822 -> 0 bytes .../applications/downloader/resources/3.bmp | Bin 822 -> 0 bytes .../applications/downloader/resources/4.bmp | Bin 822 -> 0 bytes .../applications/downloader/resources/5.bmp | Bin 822 -> 0 bytes .../applications/downloader/resources/6.bmp | Bin 822 -> 0 bytes .../applications/downloader/resources/7.bmp | Bin 822 -> 0 bytes .../applications/downloader/resources/8.bmp | Bin 822 -> 0 bytes .../applications/downloader/resources/9.bmp | Bin 824 -> 0 bytes .../downloader/resources/download.bmp | Bin 13914 -> 0 bytes .../downloader/resources/help.ico | Bin 9774 -> 0 bytes .../downloader/resources/logo.bmp | Bin 17414 -> 0 bytes .../downloader/resources/main.ico | Bin 43302 -> 0 bytes .../downloader/resources/preferences.ico | Bin 9774 -> 0 bytes .../downloader/resources/underline.bmp | Bin 170 -> 0 bytes .../downloader/resources/uninstall.bmp | Bin 13914 -> 0 bytes .../downloader/resources/update.ico | Bin 9774 -> 0 bytes reactos/base/applications/downloader/rsrc.rc | 41 - .../base/applications/downloader/structures.h | 26 - reactos/base/applications/downloader/xml.c | 237 ----- 48 files changed, 3044 deletions(-) delete mode 100644 reactos/base/applications/downloader/download.c delete mode 100644 reactos/base/applications/downloader/downloader.rbuild delete mode 100644 reactos/base/applications/downloader/downloader.rc delete mode 100644 reactos/base/applications/downloader/downloader.xml delete mode 100644 reactos/base/applications/downloader/lang/bg-BG.rc delete mode 100644 reactos/base/applications/downloader/lang/de-DE.rc delete mode 100644 reactos/base/applications/downloader/lang/el-GR.rc delete mode 100644 reactos/base/applications/downloader/lang/en-US.rc delete mode 100644 reactos/base/applications/downloader/lang/es-ES.rc delete mode 100644 reactos/base/applications/downloader/lang/fr-FR.rc delete mode 100644 reactos/base/applications/downloader/lang/id-ID.rc delete mode 100644 reactos/base/applications/downloader/lang/it-IT.rc delete mode 100644 reactos/base/applications/downloader/lang/ja-JP.rc delete mode 100644 reactos/base/applications/downloader/lang/lt-LT.rc delete mode 100644 reactos/base/applications/downloader/lang/no-NO.rc delete mode 100644 reactos/base/applications/downloader/lang/pl-PL.rc delete mode 100644 reactos/base/applications/downloader/lang/ru-RU.rc delete mode 100644 reactos/base/applications/downloader/lang/sk-SK.rc delete mode 100644 reactos/base/applications/downloader/lang/uk-UA.rc delete mode 100644 reactos/base/applications/downloader/main.c delete mode 100644 reactos/base/applications/downloader/patches/d2fix.c delete mode 100644 reactos/base/applications/downloader/resources.h delete mode 100644 reactos/base/applications/downloader/resources/0.bmp delete mode 100644 reactos/base/applications/downloader/resources/1.bmp delete mode 100644 reactos/base/applications/downloader/resources/10.bmp delete mode 100644 reactos/base/applications/downloader/resources/11.bmp delete mode 100644 reactos/base/applications/downloader/resources/12.bmp delete mode 100644 reactos/base/applications/downloader/resources/13.bmp delete mode 100644 reactos/base/applications/downloader/resources/2.bmp delete mode 100644 reactos/base/applications/downloader/resources/3.bmp delete mode 100644 reactos/base/applications/downloader/resources/4.bmp delete mode 100644 reactos/base/applications/downloader/resources/5.bmp delete mode 100644 reactos/base/applications/downloader/resources/6.bmp delete mode 100644 reactos/base/applications/downloader/resources/7.bmp delete mode 100644 reactos/base/applications/downloader/resources/8.bmp delete mode 100644 reactos/base/applications/downloader/resources/9.bmp delete mode 100644 reactos/base/applications/downloader/resources/download.bmp delete mode 100644 reactos/base/applications/downloader/resources/help.ico delete mode 100644 reactos/base/applications/downloader/resources/logo.bmp delete mode 100644 reactos/base/applications/downloader/resources/main.ico delete mode 100644 reactos/base/applications/downloader/resources/preferences.ico delete mode 100644 reactos/base/applications/downloader/resources/underline.bmp delete mode 100644 reactos/base/applications/downloader/resources/uninstall.bmp delete mode 100644 reactos/base/applications/downloader/resources/update.ico delete mode 100644 reactos/base/applications/downloader/rsrc.rc delete mode 100644 reactos/base/applications/downloader/structures.h delete mode 100644 reactos/base/applications/downloader/xml.c diff --git a/reactos/base/applications/applications.rbuild b/reactos/base/applications/applications.rbuild index d3c202051fb..232b44c0868 100644 --- a/reactos/base/applications/applications.rbuild +++ b/reactos/base/applications/applications.rbuild @@ -16,9 +16,6 @@ - - - diff --git a/reactos/base/applications/downloader/download.c b/reactos/base/applications/downloader/download.c deleted file mode 100644 index 9755287796a..00000000000 --- a/reactos/base/applications/downloader/download.c +++ /dev/null @@ -1,402 +0,0 @@ -/* PROJECT: ReactOS Downloader (was GetFirefox) - * LICENSE: GPL - See COPYING in the top level directory - * FILE: base/applications/downloader/download.c - * PURPOSE: Displaying a download dialog - * COPYRIGHT: Copyright 2001 John R. Sheets (for CodeWeavers) - * Copyright 2004 Mike McCormack (for CodeWeavers) - * Copyright 2005 Ge van Geldorp (gvg@reactos.org) - * Copyright 2007 Dmitry Chapyshev (lentind@yandex.ru) - */ -/* - * Based on Wine dlls/shdocvw/shdocvw_main.c - * - * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#define COBJMACROS -#define WIN32_NO_STATUS -#include -#include -#include -#include -#include - -#include "resources.h" -#include "structures.h" - -#define NDEBUG -#include - -extern struct Application* SelectedApplication; -extern WCHAR Strings [STRING_COUNT][MAX_STRING_LENGHT]; - -typedef struct _IBindStatusCallbackImpl -{ - const IBindStatusCallbackVtbl *vtbl; - LONG ref; - HWND hDialog; - BOOL *pbCancelled; -} IBindStatusCallbackImpl; - -static HRESULT WINAPI -dlQueryInterface(IBindStatusCallback* This, REFIID riid, void** ppvObject) -{ - if (NULL == ppvObject) - { - return E_POINTER; - } - - if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IBindStatusCallback)) - { - IBindStatusCallback_AddRef( This ); - *ppvObject = This; - return S_OK; - } - - return E_NOINTERFACE; -} - -static ULONG WINAPI -dlAddRef(IBindStatusCallback* iface) -{ - IBindStatusCallbackImpl *This = (IBindStatusCallbackImpl *) iface; - - return InterlockedIncrement(&This->ref); -} - -static ULONG WINAPI -dlRelease(IBindStatusCallback* iface) -{ - IBindStatusCallbackImpl *This = (IBindStatusCallbackImpl *) iface; - DWORD ref = InterlockedDecrement(&This->ref); - - if( !ref ) - { - DestroyWindow( This->hDialog ); - HeapFree(GetProcessHeap(), 0, This); - } - - return ref; -} - -static HRESULT WINAPI -dlOnStartBinding(IBindStatusCallback* iface, DWORD dwReserved, IBinding* pib) -{ - DPRINT1("OnStartBinding not implemented\n"); - - return S_OK; -} - -static HRESULT WINAPI -dlGetPriority(IBindStatusCallback* iface, LONG* pnPriority) -{ - DPRINT1("GetPriority not implemented\n"); - - return S_OK; -} - -static HRESULT WINAPI -dlOnLowResource( IBindStatusCallback* iface, DWORD reserved) -{ - DPRINT1("OnLowResource not implemented\n"); - - return S_OK; -} - -static HRESULT WINAPI -dlOnProgress(IBindStatusCallback* iface, ULONG ulProgress, - ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText) -{ - IBindStatusCallbackImpl *This = (IBindStatusCallbackImpl *) iface; - HWND Item; - LONG r; - WCHAR OldText[100]; - - Item = GetDlgItem(This->hDialog, IDC_PROGRESS); - if (NULL != Item && 0 != ulProgressMax) - { - SendMessageW(Item, PBM_SETPOS, ((ULONGLONG)ulProgress * 100) / ulProgressMax, 0); - } - - Item = GetDlgItem(This->hDialog, IDC_STATUS); - if (NULL != Item && NULL != szStatusText) - { - SendMessageW(Item, WM_GETTEXT, sizeof(OldText) / sizeof(OldText[0]), - (LPARAM) OldText); - if (sizeof(OldText) / sizeof(OldText[0]) - 1 <= wcslen(OldText) || 0 != wcscmp(OldText, szStatusText)) - { - SendMessageW(Item, WM_SETTEXT, 0, (LPARAM) szStatusText); - } - } - - SetLastError(0); - r = GetWindowLongPtrW(This->hDialog, GWLP_USERDATA); - if (0 != r || 0 != GetLastError()) - { - *This->pbCancelled = TRUE; - DPRINT("Cancelled\n"); - return E_ABORT; - } - - return S_OK; -} - -static HRESULT WINAPI -dlOnStopBinding(IBindStatusCallback* iface, HRESULT hresult, LPCWSTR szError) -{ - DPRINT1("OnStopBinding not implemented\n"); - - return S_OK; -} - -static HRESULT WINAPI -dlGetBindInfo(IBindStatusCallback* iface, DWORD* grfBINDF, BINDINFO* pbindinfo) -{ - DPRINT1("GetBindInfo not implemented\n"); - - return S_OK; -} - -static HRESULT WINAPI -dlOnDataAvailable(IBindStatusCallback* iface, DWORD grfBSCF, - DWORD dwSize, FORMATETC* pformatetc, STGMEDIUM* pstgmed) -{ - DPRINT1("OnDataAvailable implemented\n"); - - return S_OK; -} - -static HRESULT WINAPI -dlOnObjectAvailable(IBindStatusCallback* iface, REFIID riid, IUnknown* punk) -{ - DPRINT1("OnObjectAvailable implemented\n"); - - return S_OK; -} - -static const IBindStatusCallbackVtbl dlVtbl = -{ - dlQueryInterface, - dlAddRef, - dlRelease, - dlOnStartBinding, - dlGetPriority, - dlOnLowResource, - dlOnProgress, - dlOnStopBinding, - dlGetBindInfo, - dlOnDataAvailable, - dlOnObjectAvailable -}; - -static IBindStatusCallback* -CreateDl(HWND Dlg, BOOL *pbCancelled) -{ - IBindStatusCallbackImpl *This; - - This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IBindStatusCallbackImpl)); - if (!This) - return NULL; - - This->vtbl = &dlVtbl; - This->ref = 1; - This->hDialog = Dlg; - This->pbCancelled = pbCancelled; - - return (IBindStatusCallback*) This; -} - -static DWORD WINAPI -ThreadFunc(LPVOID Context) -{ - //static const WCHAR szUrl[] = DownloadUrl; - IBindStatusCallback *dl; - WCHAR path[MAX_PATH]; - LPWSTR p; - STARTUPINFOW si; - PROCESS_INFORMATION pi; - HWND Dlg = (HWND) Context; - DWORD r; - BOOL bCancelled = FALSE; - BOOL bTempfile = FALSE; - HKEY hKey; - DWORD dwSize = MAX_PATH; - - /* built the path for the download */ - p = wcsrchr(SelectedApplication->Location, L'/'); - if (NULL == p) - { - goto end; - } - - /* Create default download path */ - if (GetWindowsDirectory(path, sizeof(path) / sizeof(WCHAR))) - { - WCHAR DPath[256]; - int i; - for (i = 0; i < 4; i++) - { - if (i == 3) - { - DPath[i] = '\0'; - break; - } - DPath[i] = path[i]; - } - LoadString(GetModuleHandle(NULL), IDS_DOWNLOAD_FOLDER, path, sizeof(path) / sizeof(WCHAR)); - wcscat((LPWSTR)DPath, path); - wcscpy(path, DPath); - } - - if (RegOpenKey(HKEY_LOCAL_MACHINE, - TEXT("Software\\ReactOS\\Downloader"), - &hKey) == ERROR_SUCCESS) - { - if ((RegQueryValueEx(hKey, - L"DownloadFolder", - NULL, - NULL, - (LPBYTE)&path, - &dwSize) != ERROR_SUCCESS) && (path[0] == 0)) - { - goto end; - } - } - - if (GetFileAttributes(path) == 0xFFFFFFFF) - if (!CreateDirectory((LPCTSTR)path,NULL)) - { - goto end; - } - wcscat(path, L"\\"); - wcscat(path, p + 1); - - /* download it */ - bTempfile = TRUE; - dl = CreateDl(Context, &bCancelled); - r = URLDownloadToFileW(NULL, SelectedApplication->Location, path, 0, dl); - if (NULL != dl) - { - IBindStatusCallback_Release(dl); - } - if (S_OK != r) - { - MessageBoxW(0,Strings[IDS_DOWNLOAD_ERROR],0,0); - goto end; - } - else if (bCancelled) - { - goto end; - } - ShowWindow(Dlg, SW_HIDE); - - /* run it */ - memset(&si, 0, sizeof(si)); - si.cb = sizeof(si); - r = CreateProcessW(path, NULL, NULL, NULL, 0, 0, NULL, NULL, &si, &pi); - if (0 == r) - { - goto end; - } - CloseHandle(pi.hThread); - WaitForSingleObject(pi.hProcess, INFINITE); - CloseHandle(pi.hProcess); - - end: - if (bTempfile) - { - if (bCancelled) - DeleteFileW(path); - else - { - DWORD dwSize = sizeof(DWORD); - DWORD dwValue, dwType = REG_DWORD; - if (RegQueryValueEx(hKey, - L"DeleteInstaller", - NULL, - &dwType, - (LPBYTE)&dwValue, - &dwSize) == ERROR_SUCCESS) - if (dwValue == 0x1) - DeleteFileW(path); - RegCloseKey(hKey); - } - } - EndDialog(Dlg, 0); - return 0; -} - -INT_PTR CALLBACK -DownloadProc(HWND Dlg, UINT Msg, WPARAM wParam, LPARAM lParam) -{ - HANDLE Thread; - DWORD ThreadId; - HWND Item; - - switch (Msg) - { - case WM_INITDIALOG:/* - Icon = LoadIconW((HINSTANCE) GetWindowLongPtr(Dlg, GWLP_HINSTANCE), - MAKEINTRESOURCEW(IDI_ICON_MAIN)); - if (NULL != Icon) - { - SendMessageW(Dlg, WM_SETICON, ICON_BIG, (LPARAM) Icon); - SendMessageW(Dlg, WM_SETICON, ICON_SMALL, (LPARAM) Icon); - }*/ - SetWindowLongPtrW(Dlg, GWLP_USERDATA, 0); - Item = GetDlgItem(Dlg, IDC_PROGRESS); - if (NULL != Item) - { - SendMessageW(Item, PBM_SETRANGE, 0, MAKELPARAM(0,100)); - SendMessageW(Item, PBM_SETPOS, 0, 0); - }/* - Item = GetDlgItem(Dlg, IDC_REMOVE); - if (NULL != Item) - { - if (GetShortcutName(ShortcutName) && - INVALID_FILE_ATTRIBUTES != GetFileAttributesW(ShortcutName)) - { - SendMessageW(Item, BM_SETCHECK, BST_CHECKED, 0); - } - else - { - SendMessageW(Item, BM_SETCHECK, BST_UNCHECKED, 0); - ShowWindow(Item, SW_HIDE); - } - }*/ - Thread = CreateThread(NULL, 0, ThreadFunc, Dlg, 0, &ThreadId); - if (NULL == Thread) - { - return FALSE; - } - CloseHandle(Thread); - return TRUE; - - case WM_COMMAND: - if (wParam == IDCANCEL) - { - SetWindowLongPtrW(Dlg, GWLP_USERDATA, 1); - PostMessage(Dlg, WM_CLOSE, 0, 0); - } - return FALSE; - - case WM_CLOSE: - EndDialog(Dlg, 0); - return TRUE; - - default: - return FALSE; - } -} diff --git a/reactos/base/applications/downloader/downloader.rbuild b/reactos/base/applications/downloader/downloader.rbuild deleted file mode 100644 index b45df064ce0..00000000000 --- a/reactos/base/applications/downloader/downloader.rbuild +++ /dev/null @@ -1,26 +0,0 @@ - - - -downloader.xml - - . - . - - advapi32 - ntdll - user32 - gdi32 - shell32 - comctl32 - msimg32 - shlwapi - urlmon - uuid - expat - - main.c - xml.c - download.c - downloader.rc - - diff --git a/reactos/base/applications/downloader/downloader.rc b/reactos/base/applications/downloader/downloader.rc deleted file mode 100644 index e4cdb19724a..00000000000 --- a/reactos/base/applications/downloader/downloader.rc +++ /dev/null @@ -1,10 +0,0 @@ -#include -#include "resources.h" - -#define REACTOS_STR_FILE_DESCRIPTION "Download !\0" -#define REACTOS_STR_INTERNAL_NAME "downloader\0" -#define REACTOS_STR_ORIGINAL_FILENAME "downloader.exe\0" - -#include - -#include "rsrc.rc" diff --git a/reactos/base/applications/downloader/downloader.xml b/reactos/base/applications/downloader/downloader.xml deleted file mode 100644 index 867204bac7d..00000000000 --- a/reactos/base/applications/downloader/downloader.xml +++ /dev/null @@ -1,326 +0,0 @@ - - - - Mozilla Firefox (2.0.0.20) - MPL/GPL/LGPL - 2.0.0.20 - The most popular and one of the best free Web Browsers out there. - http://releases.mozilla.org/pub/mozilla.org/firefox/releases/2.0.0.20/win32/en-US/Firefox%20Setup%202.0.0.20.exe - - - Mozilla Firefox (3.0.11) - MPL/GPL/LGPL - 3.0.11 - The most popular and one of the best free Web Browsers out there. - http://releases.mozilla.org/pub/mozilla.org/firefox/releases/3.0.11/win32/en-US/Firefox%20Setup%203.0.11.exe - - - Opera - Freeware - 9.63 - The popular Opera Browser with many advanced features and including a Mail and BitTorrent client. - http://ftp.opera.com/pub/opera/win/963/en/Opera_963_classic_Setup.exe - - - AbyssX1 2.6 - Freeware - 2.6 - Abyss Web Server enables you to host your Web sites on your computer. It supports secure SSL/TLS connections (HTTPS) as well as a wide range of Web technologies. It can also run advanced PHP, Perl, Python, ASP, ASP.NET, and Ruby on Rails Web applications, which can be backed by databases such as MySQL, SQLite, MS SQL Server, MS Access, or Oracle - http://www.aprelium.com/data/abwsx1.exe - - - Mozilla Thunderbird (2.0.0.19) - MPL/GPL/LGPL - 2.0.0.19 - The most popular and one of the best free Mail Clients out there. - http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/2.0.0.19/win32/en-US/Thunderbird%20Setup%202.0.0.19.exe - - - SeaMonkey (1.1.16) - 1.1.16 - Mozilla Suite is alive. This is the one and only Browser, Mail, Chat, and Composer bundle you will ever need. - http://ftp.df.lth.se/mozilla/seamonkey/releases/1.1.16/seamonkey-1.1.16.en-US.win32.installer.exe - - - The Off By One Web Browser - The Off By One Browser is a very small and fast web browser with full HTML 3.2 support. - http://offbyone.com/offbyone/images/OffByOneSetup.exe - - - mIRC - Shareware - 6.35 - The most popular client for the Internet Relay Chat (IRC) - http://mirc.bigchief.dk/mirc635.exe - - - This tool allows you to access your Windows shared folders/printers with ReactOS. - http://svn.reactos.org/packages/samba-tng.exe - - - Miranda IM - 0.7.4 - Open source multiprotocol instant messaging application - May not work completely. - http://ovh.dl.sourceforge.net/sourceforge/miranda/miranda-im-v0.7.4-unicode.exe - - - PuTTY version 0.60 - MIT - 0.60 - A free SSH, Telnet, rlogin, and raw TCP client. - http://the.earth.li/~sgtatham/putty/latest/x86/putty-0.60-installer.exe - - - - - "AbiWord 2.6.4 (remove only)" - 2.6.4 - Word processor. - http://www.abiword.org/downloads/abiword/2.6.4/Windows/abiword-setup-2.6.4.exe - - - SoftMakerOff08 - 2008 - Shareware - SoftMaker Office 2008 comes with the following applications: TextMaker 2008: Reads and writes all Microsoft Word files without a hitch. PlanMaker 2008, the fully Excel-compatible spreadsheet. SoftMaker Presentations 2008, fully compatible with Microsoft PowerPoint. - http://www.softmaker.net/down/ofw08ev.exe - - - TextMaker Viewer 2009 - TMViewer09 - Freeware - A light viewer which lets you open, view, and print documents created with Microsoft Word 6.0 to 2007, TextMaker as well as OpenDocument and other common office file formats. - http://www.softmaker.net/down/TMViewerSetup.exe - - - OpenOffice.org 2.4.2 - 2.4.2 - THE Open Source Office Suite. - http://ftp.plusline.de/OpenOffice/stable/2.4.2/OOo_2.4.2_Win32Intel_install_wJRE_en-US.exe - - - OpenOffice.org 3.0.1 - 3.0.1 - THE Open Source Office Suite. - http://ftp.tu-chemnitz.de/pub/openoffice/stable/3.0.1/OOo_3.0.1_Win32Intel_install_en-US.exe - - - - - IrfanView (remove only) - 4.23 - Viewer for all kinds of graphics/audio files/video files. - http://irfanview.tuwien.ac.at/iview423_setup.exe - - - 4.22 - Additional Plugins for supporting more file types. - http://irfanview.tuwien.ac.at/plugins/irfanview_plugins_422_setup.exe - - - Tux Paint 0.9.19 - 0.9.19 - An Open Source bitmap graphics editor geared towards young children. - http://ovh.dl.sourceforge.net/sourceforge/tuxpaint/tuxpaint-0.9.19-win32-installer.exe - - - GlidewrapZbag - 0.84c - glidewrapper needed to run Diablo 2 on ReactOS. - http://www.zeckensack.de/glide/archive/GlideWrapper084c.exe - - - - - msxml3 - 3.0 - MSXML3 is needed for some MSI Installers. - http://download.microsoft.com/download/8/8/8/888f34b7-4f54-4f06-8dac-fa29b19f33dd/msxml3.msi - - - mfc40 - 4.0 - MFC 4 is needed by some applications - http://download.microsoft.com/download/ole/ole2v/3.5/w351/en-us/ole2v.exe - - - vb5run - 5.0 - Visual Basic 5 Runtime - http://download.microsoft.com/download/vb50pro/utility/1/win98/en-us/msvbvm50.exe - - - vb6run - 6.0 - Visual Basic 6 Runtime - http://download.microsoft.com/download/vb60pro/install/6/win98me/en-us/vbrun60.exe - - - vc6run - 6.0 - Visual Studio 6 Runtime - http://download.microsoft.com/download/vc60pro/update/1/w9xnt4/en-us/vc6redistsetup_enu.exe - - - vc2005run - 7.0 - Visual Studio 2005 Runtime - http://download.microsoft.com/download/d/3/4/d342efa6-3266-4157-a2ec-5174867be706/vcredist_x86.exe - - - vc2005sp1run - 7.1 - Visual Studio 2005 Runtime SP1 - http://download.microsoft.com/download/e/1/c/e1c773de-73ba-494a-a5ba-f24906ecf088/vcredist_x86.exe - - - vc2008run - 8.0 - Visual Studio 2008 Runtime - http://download.microsoft.com/download/1/1/1/1116b75a-9ec3-481a-a3c8-1777b5381140/vcredist_x86.exe - - - - - smplayer - 0.6.7 - SMPlayer - http://dfn.dl.sourceforge.net/sourceforge/smplayer/smplayer_0.6.7_setup.exe - - - vlc0.8.0 - GPL - 0.8.0 - VLC media player is a highly portable multimedia player for various audio and video formats (MPEG-1, MPEG-2, MPEG-4, DivX, mp3, ogg, ...) as well as DVDs, VCDs, and various streaming protocols. - http://download.videolan.org/pub/videolan/vlc/0.8.0/win32/vlc-0.8.0-win32.exe - - - - - ReactOS Build Environment 1.4.4 - 1.4.4 - Allows you to build the ReactOS Source. For more instructions see ReactOS wiki. - http://ovh.dl.sourceforge.net/sourceforge/reactos/RosBE-1.4.4.exe - - - MinGW 5.1.3 - 5.1.3 - A Port of the GNU toolchain with GCC, GDB, GNU make, etc. - http://ovh.dl.sourceforge.net/sourceforge/mingw/MinGW-5.1.3.exe - - - SciTE 1.78 - 1.78 - GPL - SciTE is a SCIntilla based Text Editor. Originally built to demonstrate Scintilla, it has grown to be a generally useful editor with facilities for building and running programs. - http://fastbull.dl.sourceforge.net/sourceforge/scintilla/Sc178.exe - - - FreeBASIC 0.18.4b - 0.18.4b - Open Source BASIC Compiler. The BASIC syntax is compatible to QBASIC. - http://ovh.dl.sourceforge.net/sourceforge/fbc/FreeBASIC-v0.18.4b-win32.exe - - - - - ScummVM 0.11.1 - 0.11.1 - SamNMax, Day of Tentacle, etc on ReactOS - http://ovh.dl.sourceforge.net/sourceforge/scummvm/scummvm-0.11.1-win32.exe - - - Diablo II Shareware - 1.4 - Diablo 2 Shareware. zeckensack's glide wrapper is req. to run it. - http://ftp.freenet.de./pub/filepilot/windows/spiele/diabloiidemo.exe - GlidewrapZbag - http://svn.reactos.org/downloads/d2fix.exe - - - Nice Clone of Chip's Challenge originally made for the Atari Lynx. Includes free CCLP2 Graphics Pack, so you dont need the copyrighted Original. - http://www.muppetlabs.com/~breadbox/pub/software/tworld/tworld-1.3.0-win32-CCLP2.exe - - - OpenTTD 0.7.1 - 0.7.1 - Open Source clone of the "Transport Tycoon Deluxe" game engine. You either need a copy of Transport Tycoon or have to manually download and set up the OpenGFX files. - http://binaries.openttd.org/releases/0.7.1/openttd-0.7.1-windows-win32.exe - - - LBreakout2 2.4.1 - 2.4.1 - Breakout Clone using SDL libs. - http://ovh.dl.sourceforge.net/sourceforge/lgames/lbreakout2-2.4.1-win32.exe - - - LGeneral 1.1 - 1.1 - Panzer General Clone using SDL libs. - http://ovh.dl.sourceforge.net/sourceforge/lgames/lgeneral-1.1-win32.exe - - - LMarbles 1.0.6 - 1.0.6 - Atomix Clone using SDL libs. - http://ovh.dl.sourceforge.net/sourceforge/lgames/lmarbles-1.0.6-win32.exe - - - WinBoard 4.2.7b - 4.2.7b - GPL 3 - WinBoard is a graphical chessboard for the Windows/ReactOS that can serve as a user interface for GNU Chess, Crafty, and other chess engines, for the Internet Chess Servers, and for electronic mail correspondence chess. - http://ftp.gnu.org/gnu/winboard/winboard-4_2_7b.exe - - - - - - - - - - - 7-Zip 4.57 - 4.57 - Utility to create and open 7zip, zip, tar, rar and other archive files. - http://ovh.dl.sourceforge.net/sourceforge/sevenzip/7z457.exe - - - µTorrent - 1.8 - Small and fast BitTorrent Client - http://download.utorrent.com/1.8.2/utorrent-1.8.2.upx.exe - - - Audiograbber 1.83 SE - 1.83 SE - A very good CD Ripper/Audio File Converter. - http://www.audiograbber.de/files/4898276276/agsetup183se.exe - - - - - 5.10.00.3610 - Unzip in the "ReactOS" folder then restart ReactOS twice. - http://svn.reactos.org/packages/ac97_vbox.exe - - - - - 1.2.13 - Needed for many Open Source Games to run. You need 7-Zip or a similar Utility to extract it. - http://www.libsdl.org/release/SDL-1.2.13-win32.zip - - - 1.2.8 - Needed for some Open Source Games to run. You need 7-Zip or a similar Utility to extract it. - http://www.libsdl.org/projects/SDL_mixer/release/SDL_mixer-1.2.8-win32.zip - - - 0.72 - DOSBox is a DOS emulator. - http://ovh.dl.sourceforge.net/sourceforge/dosbox/DOSBox0.72-win32-installer.exe - - - diff --git a/reactos/base/applications/downloader/lang/bg-BG.rc b/reactos/base/applications/downloader/lang/bg-BG.rc deleted file mode 100644 index ee1a13978e5..00000000000 --- a/reactos/base/applications/downloader/lang/bg-BG.rc +++ /dev/null @@ -1,60 +0,0 @@ -LANGUAGE LANG_BULGARIAN, SUBLANG_DEFAULT - -IDD_DOWNLOAD DIALOG LOADONCALL MOVEABLE DISCARDABLE 0, 0, 220, 76 -STYLE DS_CENTER | WS_BORDER | WS_CAPTION | WS_POPUP | WS_SYSMENU | WS_VISIBLE -CAPTION "Ñâàëÿíå..." -FONT 8, "MS Shell Dlg" -BEGIN - CONTROL "Progress1",IDC_PROGRESS,"msctls_progress32",WS_BORDER|PBS_SMOOTH,10,10,200,12 - LTEXT "", IDC_STATUS, 10, 30, 200, 10, SS_CENTER - PUSHBUTTON "Îòêàç", IDCANCEL, 85, 58, 50, 15, WS_GROUP | WS_TABSTOP -END - -IDD_PROF DIALOGEX 6, 6, 267, 110 -STYLE DS_CENTER | WS_BORDER | WS_CAPTION | WS_POPUP | WS_SYSMENU | WS_VISIBLE -CAPTION "Ïðåäïî÷èòàíèÿ" -FONT 8, "MS Shell Dlg" -BEGIN - LTEXT "Ïàïêà çà ñâàëÿíå:", -1, 6, 10, 144, 8 - EDITTEXT IDC_DOWNLOAD_FOLDER_EDIT, 6, 20, 205, 14, WS_VISIBLE | WS_TABSTOP - PUSHBUTTON "&Èçáîð...", IDC_CHOOSE_BUTTON, 216, 20, 45, 14 - AUTOCHECKBOX "&Èçòðèâàíå íà èíñòàëàöèîííèòå ôàéëîâå ñëåä ñëàãàíåòî", IDC_DELINST_FILES_CHECKBOX, 8, 40, 210, 10, WS_GROUP - LTEXT "Ñúðâúð ñ îáíîâÿâàíèÿ:", -1, 6, 55, 140, 8 - EDITTEXT IDC_UPDATE_SERVER_EDIT, 6, 65, 255, 14, WS_VISIBLE | WS_TABSTOP - DEFPUSHBUTTON "&Äîáðå", IDOK, 147, 90, 54, 15 - PUSHBUTTON "&Îòêàç", IDCANCEL, 207, 90, 54, 15 -END - -STRINGTABLE DISCARDABLE -BEGIN - IDS_WINDOW_TITLE "Ñâàëè! - Ñâàëÿ÷úò íà ÐåàêòÎÑ" - IDS_WELCOME_TITLE "Ñâàëÿ÷úò íà ÐåàêòÎÑ âè ïðèâåòñòâà" - IDS_WELCOME "Èçáåðåòå ðàçäåë îòëÿâî. Òîâà å èçäàíèå 1.1." - IDS_NO_APP_TITLE "Íå å èçáðàíî ïðèëîæåíèå" - IDS_NO_APP "Èçáåðåòå ïðèëîæåíèå, ïðåäè äà íàòèñíåòî êëàâèøà „Ñâàëÿíå”. Àêî èìàòå íóæäà îò ïîìîù, íàòèñíåòå âúïðîñèòåëíàòà â ãîðíèÿ äåñåí úãúë." - IDS_UPDATE_TITLE "Îáíîâÿâàíå" - IDS_UPDATE "Òàçè âúçìîæíîñò âñå îùå íå å ãîòîâà." - IDS_HELP_TITLE "Ïîìîù" - IDS_HELP "Èçáåðåòå ðàçäåë îòëÿâî, ñëåä òîâà èçáåðåòå ïðèëîæåíèå è íàòèñíåòå „Ñâàëÿíå”. Çà äà îñúâðåìåíèòå ñâåäåíèÿòà çà ïðèëîæåíèåòî, íàòèñíåòå êîï÷åòî äî „Íàïðåä”." - IDS_NO_APPS "Çà ñúæàëåíèå â òîçè ðàçäåë âñå îùå íÿìà ïðèëîæåíèÿ. Ìîæåòå äà ïîìîãíåòå è äà äîáàâèòå îùå ïðèëîæåíèÿ." - IDS_CHOOSE_APP "Èçáåðåòå ïðèëîæåíèå." - IDS_CHOOSE_SUB "Èçáåðåòå ïîäðàçäåë." - IDS_CHOOSE_CATEGORY "Èçáåðåòå ðàçäåë." - IDS_CHOOSE_BOTH "Èçáåðåòå ïîäðàçäåë èëè ïðèëîæåíèå." - IDS_XMLERROR_1 "Xml ôàéëúò íå å îòêðèò !" - IDS_XMLERROR_2 "Ðàçáîðúò íà XML ôàéëà å íåóñïåøåí!" - IDS_DOWNLOAD_ERROR "Ñâàëÿíåòî íà ôàéëà íåâúçìîæíî.\nÏðîâåðåòå âðúçêàòà ñè ñ èíòåðíåò." - IDS_VERSION "Èçäàíèå: " - IDS_LICENCE "Ðàçðåøèòåëíî: " - IDS_MAINTAINER "Ïîääúðæàù: " - IDS_APPS_TITLE "Ïðèëîæåíèÿ" - IDS_CATS_TITLE "Ðàçäåëè" - IDS_CHOOSE_FOLDER "Èçáåðåòå ïàïêàòà..." - IDS_NOTCREATE_REGKEY "Íåóñïåøíî ñúçäàâàíå íà êëþ÷ â ðåãèñòúðà." - IDS_DOWNLOAD_FOLDER "Ñâàëÿ÷" - IDS_UNABLECREATE_FOLDER "Íåóñïåøíî ñúçäàâàíå íà ïàïêà ñ òîâà èìå!" - IDS_UPDATE_URL "http://svn.reactos.org" - TTT_HELPBUTTON, "Ïîìîù çà ñâàëÿ÷à" - TTT_UPDATEBUTTON, "Âñå îùå íå å ãîòîâî" - TTT_PROFBUTTON, "Ïîçâîëÿâà íàñòðîéêà íà ñâàëÿ÷à" -END diff --git a/reactos/base/applications/downloader/lang/de-DE.rc b/reactos/base/applications/downloader/lang/de-DE.rc deleted file mode 100644 index 0b29796491c..00000000000 --- a/reactos/base/applications/downloader/lang/de-DE.rc +++ /dev/null @@ -1,61 +0,0 @@ -LANGUAGE LANG_GERMAN, SUBLANG_NEUTRAL - -IDD_DOWNLOAD DIALOGEX LOADONCALL MOVEABLE DISCARDABLE 0, 0, 220, 76 -STYLE DS_SHELLFONT | DS_CENTER | WS_BORDER | WS_CAPTION | WS_POPUP | WS_SYSMENU | WS_VISIBLE -CAPTION "Download..." -FONT 8, "MS Shell Dlg" -BEGIN - CONTROL "Progress1",IDC_PROGRESS,"msctls_progress32",WS_BORDER|PBS_SMOOTH,10,10,200,12 - LTEXT "", IDC_STATUS, 10, 30, 200, 10, SS_CENTER - PUSHBUTTON "Abbrechen", IDCANCEL, 85, 58, 50, 15, WS_GROUP | WS_TABSTOP -END - -IDD_PROF DIALOGEX 6, 6, 267, 110 -STYLE DS_SHELLFONT | DS_CENTER | WS_BORDER | WS_CAPTION | WS_POPUP | WS_SYSMENU | WS_VISIBLE -CAPTION "Einstellungen" -FONT 8, "MS Shell Dlg" -BEGIN - LTEXT "Downloadordner:", -1, 6, 10, 140, 8 - EDITTEXT IDC_DOWNLOAD_FOLDER_EDIT, 6, 20, 205, 14, WS_VISIBLE | WS_TABSTOP - PUSHBUTTON "W&ähle...", IDC_CHOOSE_BUTTON, 216, 20, 45, 14 - AUTOCHECKBOX "&Installationsdateien nach dem Setup löschen", IDC_DELINST_FILES_CHECKBOX, 8, 40, 210, 10, WS_GROUP - LTEXT "Updateserver:", -1, 6, 55, 140, 8 - EDITTEXT IDC_UPDATE_SERVER_EDIT, 6, 65, 255, 14, WS_VISIBLE | WS_TABSTOP - DEFPUSHBUTTON "&OK", IDOK, 147, 90, 54, 15 - PUSHBUTTON "&Abbrechen", IDCANCEL, 207, 90, 54, 15 -END - -STRINGTABLE DISCARDABLE -BEGIN - IDS_WINDOW_TITLE "Download ! - ReactOS Downloader" - IDS_WELCOME_TITLE "Willkommen im ReactOS Downloader" - IDS_WELCOME "Bitte wählen Sie links eine Kategorie. Dies ist Version 1.1." - IDS_NO_APP_TITLE "Keine Anwendung ausgewählt" - IDS_NO_APP "Bitte wählen Sie eine Anwendung aus, bevor Sie die Download-Schaltfläche betätigen. Wenn Sie Hilfe benötigen, drücken Sie die Hilfe-Schaltfläche in der oberen rechten Ecke." - IDS_UPDATE_TITLE "Update" - IDS_UPDATE "Diese Funktion wurde noch nicht implementiert." - IDS_HELP_TITLE "Hilfe" - IDS_HELP "Wählen Sie links eine Kategorie, wählen Sie eine Anwendung und drücken Sie die Download-Schaltfläche. Um die Anwendungsinformationen zu aktualisieren, drücken Sie die Schaltfläche neben der Hilfe-Schaltfläche." - IDS_NO_APPS "In dieser Kategorie sind bisher noch keine Anwendungen. Sie können helfen, indem Sie Anwendungen hinzufügen." - IDS_CHOOSE_APP "Bitte wählen Sie eine Anwendung." - IDS_CHOOSE_SUB "Bitte wählen Sie eine Unterkategorie." - IDS_CHOOSE_CATEGORY "Bitte wählen Sie eine Kategorie." - IDS_CHOOSE_BOTH "Bitte wählen Sie eine Unterkategorie oder eine Anwendung." - IDS_XMLERROR_1 "XML-Datei nicht gefunden!" - IDS_XMLERROR_2 "XML-Datei kann nicht verarbeitet werden!" - IDS_DOWNLOAD_ERROR "Die Datei konnte nicht heruntergeladen werden.\nBitte prüfen sie, ob eine Verbindung zum Internet besteht." - IDS_VERSION "Version: " - IDS_LICENCE "Lizenz: " - IDS_MAINTAINER "Maintainer: " - IDS_APPS_TITLE "Anwendungen" - IDS_CATS_TITLE "Kategorien" - IDS_CHOOSE_FOLDER "Bitte wählen Sie den Ordner aus..." - IDS_NOTCREATE_REGKEY "Registryschlüssel könnte nicht erstellt werden." - IDS_DOWNLOAD_FOLDER "Downloader" - IDS_UNABLECREATE_FOLDER "Es konnte kein Ordner mit diesem Namen erstellt werden!" - IDS_UPDATE_URL "http://svn.reactos.org" - IDS_INSTALL_DEP "%s wird benötigt, um %s ausführen zu können. Soll %s jetzt installiert werden?" - TTT_HELPBUTTON "Hilfe über den Downloader" - TTT_UPDATEBUTTON "Noch nicht vorhanden" - TTT_PROFBUTTON "Konfiguriert den Downloader" -END diff --git a/reactos/base/applications/downloader/lang/el-GR.rc b/reactos/base/applications/downloader/lang/el-GR.rc deleted file mode 100644 index ad044670b60..00000000000 --- a/reactos/base/applications/downloader/lang/el-GR.rc +++ /dev/null @@ -1,61 +0,0 @@ -LANGUAGE LANG_GREEK, SUBLANG_DEFAULT - -IDD_DOWNLOAD DIALOGEX LOADONCALL MOVEABLE DISCARDABLE 0, 0, 220, 76 -STYLE DS_SHELLFONT | DS_CENTER | WS_BORDER | WS_CAPTION | WS_POPUP | WS_SYSMENU | WS_VISIBLE -CAPTION "Download..." -FONT 8, "MS Shell Dlg" -BEGIN - CONTROL "Progress1",IDC_PROGRESS,"msctls_progress32",WS_BORDER|PBS_SMOOTH,10,10,200,12 - LTEXT "", IDC_STATUS, 10, 30, 200, 10, SS_CENTER - PUSHBUTTON "¢êõñï", IDCANCEL, 85, 58, 50, 15, WS_GROUP | WS_TABSTOP -END - -IDD_PROF DIALOGEX 6, 6, 267, 110 -STYLE DS_SHELLFONT | DS_CENTER | WS_BORDER | WS_CAPTION | WS_POPUP | WS_SYSMENU | WS_VISIBLE -CAPTION "ÐñïôéìÞóåéò" -FONT 8, "MS Shell Dlg" -BEGIN - LTEXT "ÖÜêåëïò ËÞøåùí:", -1, 6, 10, 140, 8 - EDITTEXT IDC_DOWNLOAD_FOLDER_EDIT, 6, 20, 205, 14, WS_VISIBLE | WS_TABSTOP - PUSHBUTTON "Å&ðéëïãÞ...", IDC_CHOOSE_BUTTON, 216, 20, 45, 14 - AUTOCHECKBOX "&ÄéáãñáöÞ áñ÷åßùí åãêáôÜóôáóçò ìåôÜ ôçí åãêáôÜóôáóç", IDC_DELINST_FILES_CHECKBOX, 8, 40, 210, 10, WS_GROUP - LTEXT "ÄéáêïìéóôÞò åíçìåñþóåùí:", -1, 6, 55, 140, 8 - EDITTEXT IDC_UPDATE_SERVER_EDIT, 6, 65, 255, 14, WS_VISIBLE | WS_TABSTOP - DEFPUSHBUTTON "&OK", IDOK, 147, 90, 54, 15 - PUSHBUTTON "&¢êõñï", IDCANCEL, 207, 90, 54, 15 -END - -STRINGTABLE DISCARDABLE -BEGIN - IDS_WINDOW_TITLE "Download ! - ReactOS Downloader" - IDS_WELCOME_TITLE "Êáëþò Þëèáôå óôïí ReactOS Downloader" - IDS_WELCOME "Ðáñáêáëþ åðéëÝîôå êáôçãïñßá óôá áñéóôåñÜ. ÁõôÞ åßíáé ç Ýêäïóç 1.1." - IDS_NO_APP_TITLE "Äåí åðéëÝ÷èçêå åöáñìïãÞ" - IDS_NO_APP "Please select a Application before you click the download button, if you need assistance please click on the question mark button on the top right corner." - IDS_UPDATE_TITLE "ÅíçìÝñùóç" - IDS_UPDATE "Sorry this feature is not implemented yet." - IDS_HELP_TITLE "ÂïÞèåéá" - IDS_HELP "ÅðéëÝîôå êáôçãïñßá óôá áñéóôåñÜ, ìåôÜ åðéëÝîôå ìéá åöáñìïãÞ êáé ðáôÞóôå ôï êïõìðß download. To update the application information click the button next to the help button." - IDS_NO_APPS "Sorry, there no applications in this category yet. You can help and add more applications." - IDS_CHOOSE_APP "Ðáñáêáëþ åðéëÝîôå ìéá åöáñìïãÞ." - IDS_CHOOSE_SUB "Ðáñáêáëþ åðéëÝîôå ìéá õðïêáôçãïñßá." - IDS_CHOOSE_CATEGORY "Ðáñáêáëþ åðéëÝîôå ìéá êáôçãïñßá." - IDS_CHOOSE_BOTH "Ðáñáêáëþ åðéëÝîôå ìéá õðïêáôçãïñßá Þ ìéá åöáñìïãÞ." - IDS_XMLERROR_1 "Äå âñÝèçêå ôï áñ÷åßï xml !" - IDS_XMLERROR_2 "Could not parse the xml file !" - IDS_DOWNLOAD_ERROR "Äåí Þôáí äõíáôü ôï êáôÝâáóìá ôïõ áñ÷åßïõ.\nÐáñáêáëïýìå åëÝîôå ôçí internet óýíäåóÞ óáò." - IDS_VERSION "¸êäïóç: " - IDS_LICENCE "¢äåéá: " - IDS_MAINTAINER "Maintainer: " - IDS_APPS_TITLE "ÅöáñìïãÝò" - IDS_CATS_TITLE "Êáôçãïñßåò" - IDS_CHOOSE_FOLDER "Ðáñáêáëþ, åðéëÝîôå ôïí êáôÜëïãï..." - IDS_NOTCREATE_REGKEY "Could not create the registry key." - IDS_DOWNLOAD_FOLDER "Downloader" - IDS_UNABLECREATE_FOLDER "Unable to create a folder with this name!" - IDS_UPDATE_URL "http://svn.reactos.org" - IDS_INSTALL_DEP "%s åßíáé áðáéôïýìåíï ãéá ôçí åêôÝëåóç ôïõ %s. Íá åãêáôáóôáèåß ôï %s ôþñá;" - TTT_HELPBUTTON "Âñåßôå âïÞèåéá ãéá ôïí downloader" - TTT_UPDATEBUTTON "¼÷é áêüìá äéáèÝóéìï" - TTT_PROFBUTTON "Let you configure the downloader" -END diff --git a/reactos/base/applications/downloader/lang/en-US.rc b/reactos/base/applications/downloader/lang/en-US.rc deleted file mode 100644 index a8276806e5c..00000000000 --- a/reactos/base/applications/downloader/lang/en-US.rc +++ /dev/null @@ -1,61 +0,0 @@ -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US - -IDD_DOWNLOAD DIALOGEX LOADONCALL MOVEABLE DISCARDABLE 0, 0, 220, 76 -STYLE DS_SHELLFONT | DS_CENTER | WS_BORDER | WS_CAPTION | WS_POPUP | WS_SYSMENU | WS_VISIBLE -CAPTION "Download..." -FONT 8, "MS Shell Dlg" -BEGIN - CONTROL "Progress1",IDC_PROGRESS,"msctls_progress32",WS_BORDER|PBS_SMOOTH,10,10,200,12 - LTEXT "", IDC_STATUS, 10, 30, 200, 10, SS_CENTER - PUSHBUTTON "Cancel", IDCANCEL, 85, 58, 50, 15, WS_GROUP | WS_TABSTOP -END - -IDD_PROF DIALOGEX 6, 6, 267, 110 -STYLE DS_SHELLFONT | DS_CENTER | WS_BORDER | WS_CAPTION | WS_POPUP | WS_SYSMENU | WS_VISIBLE -CAPTION "Preferences" -FONT 8, "MS Shell Dlg" -BEGIN - LTEXT "Download folder:", -1, 6, 10, 140, 8 - EDITTEXT IDC_DOWNLOAD_FOLDER_EDIT, 6, 20, 205, 14, WS_VISIBLE | WS_TABSTOP - PUSHBUTTON "C&hoose...", IDC_CHOOSE_BUTTON, 216, 20, 45, 14 - AUTOCHECKBOX "&Delete installation files after setup", IDC_DELINST_FILES_CHECKBOX, 8, 40, 210, 10, WS_GROUP - LTEXT "Update server:", -1, 6, 55, 140, 8 - EDITTEXT IDC_UPDATE_SERVER_EDIT, 6, 65, 255, 14, WS_VISIBLE | WS_TABSTOP - DEFPUSHBUTTON "&OK", IDOK, 147, 90, 54, 15 - PUSHBUTTON "&Cancel", IDCANCEL, 207, 90, 54, 15 -END - -STRINGTABLE DISCARDABLE -BEGIN - IDS_WINDOW_TITLE "Download ! - ReactOS Downloader" - IDS_WELCOME_TITLE "Welcome to the ReactOS Downloader" - IDS_WELCOME "Please choose a category on the left. This is version 1.1." - IDS_NO_APP_TITLE "No application selected" - IDS_NO_APP "Please select a Application before you click the download button, if you need assistance please click on the question mark button on the top right corner." - IDS_UPDATE_TITLE "Update" - IDS_UPDATE "Sorry this feature is not implemented yet." - IDS_HELP_TITLE "Help" - IDS_HELP "Choose a category on the left, then choose a application and click the download button. To update the application information click the button next to the help button." - IDS_NO_APPS "Sorry, there no applications in this category yet. You can help and add more applications." - IDS_CHOOSE_APP "Please choose an application." - IDS_CHOOSE_SUB "Please choose a subcategory." - IDS_CHOOSE_CATEGORY "Please choose a category." - IDS_CHOOSE_BOTH "Please choose a subcategory or an application." - IDS_XMLERROR_1 "Could not find the xml file !" - IDS_XMLERROR_2 "Could not parse the xml file !" - IDS_DOWNLOAD_ERROR "Unable to download the file.\nPlease check your internet connection." - IDS_VERSION "Version: " - IDS_LICENCE "Licence: " - IDS_MAINTAINER "Maintainer: " - IDS_APPS_TITLE "Applications" - IDS_CATS_TITLE "Categories" - IDS_CHOOSE_FOLDER "Please, choose the folder..." - IDS_NOTCREATE_REGKEY "Could not create the registry key." - IDS_DOWNLOAD_FOLDER "Downloader" - IDS_UNABLECREATE_FOLDER "Unable to create a folder with this name!" - IDS_UPDATE_URL "http://svn.reactos.org" - IDS_INSTALL_DEP "%s is required to run %s. Should %s be installed now?" - TTT_HELPBUTTON "Get help about the downloader" - TTT_UPDATEBUTTON "Not yet available" - TTT_PROFBUTTON "Let you configure the downloader" -END diff --git a/reactos/base/applications/downloader/lang/es-ES.rc b/reactos/base/applications/downloader/lang/es-ES.rc deleted file mode 100644 index fca06075ecc..00000000000 --- a/reactos/base/applications/downloader/lang/es-ES.rc +++ /dev/null @@ -1,66 +0,0 @@ -/* - *Spanish Language resource file - * Actualizado Javier Remacha 2007-12-01,2007-12-31 - */ - -LANGUAGE LANG_SPANISH, SUBLANG_NEUTRAL - -IDD_DOWNLOAD DIALOGEX LOADONCALL MOVEABLE DISCARDABLE 0, 0, 220, 76 -STYLE DS_SHELLFONT | DS_CENTER | WS_BORDER | WS_CAPTION | WS_POPUP | WS_SYSMENU | WS_VISIBLE -CAPTION "Descargar..." -FONT 8, "MS Shell Dlg" -BEGIN - CONTROL "Progress1",IDC_PROGRESS,"msctls_progress32",WS_BORDER|PBS_SMOOTH,10,10,200,12 - LTEXT "", IDC_STATUS, 10, 30, 200, 10, SS_CENTER - PUSHBUTTON "Cancelar", IDCANCEL, 85, 58, 50, 15, WS_GROUP | WS_TABSTOP -END - -IDD_PROF DIALOGEX 6, 6, 267, 110 -STYLE DS_SHELLFONT | DS_CENTER | WS_BORDER | WS_CAPTION | WS_POPUP | WS_SYSMENU | WS_VISIBLE -CAPTION "Preferencias" -FONT 8, "MS Shell Dlg" -BEGIN - LTEXT "Carpeta de descarga:", -1, 6, 10, 140, 8 - EDITTEXT IDC_DOWNLOAD_FOLDER_EDIT, 6, 20, 205, 14, WS_VISIBLE | WS_TABSTOP - PUSHBUTTON "&Seleccionar...", IDC_CHOOSE_BUTTON, 216, 20, 45, 14 - AUTOCHECKBOX "&Borrar archivos de instalación tras la instalación", IDC_DELINST_FILES_CHECKBOX, 8, 40, 210, 10, WS_GROUP - LTEXT "Actualizar servidor:", -1, 6, 55, 140, 8 - EDITTEXT IDC_UPDATE_SERVER_EDIT, 6, 65, 255, 14, WS_VISIBLE | WS_TABSTOP - DEFPUSHBUTTON "&Aceptar", IDOK, 147, 90, 54, 15 - PUSHBUTTON "&Cancelar", IDCANCEL, 207, 90, 54, 15 -END - -STRINGTABLE DISCARDABLE -BEGIN - IDS_WINDOW_TITLE "¡Descargar! - Descargador de ReactOS" - IDS_WELCOME_TITLE "Bienvenido al descargador de ReactOS" - IDS_WELCOME "Por favor selecciona una categoría de la izquierda. Esta es la versión 1.1." - IDS_NO_APP_TITLE "Ninguna aplicación seleccionada" - IDS_NO_APP "Por favor seleccione una Aplicación antes de pulsar el botón de Descarga, si necesita asistencia por favor pulsa el botón con la interrogación en la esquina superior derecha." - IDS_UPDATE_TITLE "Actualizar" - IDS_UPDATE "Perdón esta característica no a sido implementada todavía." - IDS_HELP_TITLE "Ayuda" - IDS_HELP "Selecciona una categoría de la izquierda, entonces selecciona una aplicación y pulsa el botón de descargar. Para actualizar la información de la aplicación pulsa el botón junto al botón de ayuda." - IDS_NO_APPS "Perdón, aun no hay ninguna aplicación en esta categoría. Puedes ayudar y añadir más aplicaciones." - IDS_CHOOSE_APP "Por favor selecciona una aplicación." - IDS_CHOOSE_SUB "Por favor selecciona una subcategoría." - IDS_CHOOSE_CATEGORY "Por favor selecciona una categoría." - IDS_CHOOSE_BOTH "Por favor selecciona una subcategoria o una aplicación." - IDS_XMLERROR_1 "¡No se a encontrado el archivo xml!" - IDS_XMLERROR_2 "¡No se ha podido analizar el archivo xml!" - IDS_DOWNLOAD_ERROR "Imposible descargar el archivo.\nPor favor verifica tu conexión a internet." - IDS_VERSION "Versión: " - IDS_LICENCE "Licencia: " - IDS_MAINTAINER "Mantenido por: " - IDS_APPS_TITLE "Aplicaciones" - IDS_CATS_TITLE "Categorias" - IDS_CHOOSE_FOLDER "Por favor, seleccione la carpeta..." - IDS_NOTCREATE_REGKEY "No se puede crear la llave del registro." - IDS_DOWNLOAD_FOLDER "Downloader" - IDS_UNABLECREATE_FOLDER "¡Imposible crear una carpeta con este nombre!" - IDS_UPDATE_URL "http://svn.reactos.org" - IDS_INSTALL_DEP "%s en necesario para ejecutar %s. ¿Desea instalar %s ahora?" - TTT_HELPBUTTON "Obtenga ayuda acerca de Downloader" - TTT_UPDATEBUTTON "No disponible todavía" - TTT_PROFBUTTON "Le permite configurar Downloader" -END diff --git a/reactos/base/applications/downloader/lang/fr-FR.rc b/reactos/base/applications/downloader/lang/fr-FR.rc deleted file mode 100644 index c434600726b..00000000000 --- a/reactos/base/applications/downloader/lang/fr-FR.rc +++ /dev/null @@ -1,61 +0,0 @@ -LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL - -IDD_DOWNLOAD DIALOGEX LOADONCALL MOVEABLE DISCARDABLE 0, 0, 220, 76 -STYLE DS_SHELLFONT | DS_CENTER | WS_BORDER | WS_CAPTION | WS_POPUP | WS_SYSMENU | WS_VISIBLE -CAPTION "Téléchargement..." -FONT 8, "MS Shell Dlg" -BEGIN - CONTROL "Progress1",IDC_PROGRESS,"msctls_progress32",WS_BORDER|PBS_SMOOTH,10,10,200,12 - LTEXT "", IDC_STATUS, 10, 30, 200, 10, SS_CENTER - PUSHBUTTON "Annuler", IDCANCEL, 85, 58, 50, 15, WS_GROUP | WS_TABSTOP -END - -IDD_PROF DIALOGEX 6, 6, 267, 110 -STYLE DS_SHELLFONT | DS_CENTER | WS_BORDER | WS_CAPTION | WS_POPUP | WS_SYSMENU | WS_VISIBLE -CAPTION "Préférences" -FONT 8, "MS Shell Dlg" -BEGIN - LTEXT "Répertoire de téléchargement :", -1, 6, 10, 140, 8 - EDITTEXT IDC_DOWNLOAD_FOLDER_EDIT, 6, 20, 205, 14, WS_VISIBLE | WS_TABSTOP - PUSHBUTTON "C&hoisir...", IDC_CHOOSE_BUTTON, 216, 20, 45, 14 - AUTOCHECKBOX "Supprimer les fichiers après l'installation", IDC_DELINST_FILES_CHECKBOX, 8, 40, 210, 10, WS_GROUP - LTEXT "Serveur de mise-à-jour :", -1, 6, 55, 140, 8 - EDITTEXT IDC_UPDATE_SERVER_EDIT, 6, 65, 255, 14, WS_VISIBLE | WS_TABSTOP - DEFPUSHBUTTON "&OK", IDOK, 147, 90, 54, 15 - PUSHBUTTON "Annuler", IDCANCEL, 207, 90, 54, 15 -END - -STRINGTABLE DISCARDABLE -BEGIN - IDS_WINDOW_TITLE "Télécharger ! - Téléchargeur de ReactOS" - IDS_WELCOME_TITLE "Bienvenue dans le Téléchargeur de ReactOS" - IDS_WELCOME "Veuillez choisir une catégorie sur la gauche. C'est la version 1.1." - IDS_NO_APP_TITLE "Aucune application selectionnée" - IDS_NO_APP "Veuillez sélectionner une application avant de cliquer sur le bouton Télécharger, si vous avez besoin d'aide, veuillez cliquer sur le point d'interrogation dans le coin supérieur droit." - IDS_UPDATE_TITLE "Mise à jour" - IDS_UPDATE "Désolé, cette fonctionnalité n'est pas encore implémentée." - IDS_HELP_TITLE "Aide" - IDS_HELP "Choisissez une catégorie sur la gauche, puis choisissez une application et cliquez sur le bouton Télécharger. Pour mettre à jour les informations sur l'application, cliquez sur le bouton à côté du bouton d'aide." - IDS_NO_APPS "Désolé, il n'y a pas encore d'application dans cette catégorie. Vous pouvez contribuer et ajouter plus d'applications." - IDS_CHOOSE_APP "Veuillez choisir une application." - IDS_CHOOSE_SUB "Veuillez choisir une sous-catégorie." - IDS_CHOOSE_CATEGORY "Veuillez choisir une catégorie." - IDS_CHOOSE_BOTH "Veuillez choisir une sous-catégorie ou une application." - IDS_XMLERROR_1 "Impossible de trouver le fichier xml !" - IDS_XMLERROR_2 "Impossible d'analyser le fichier xml !" - IDS_DOWNLOAD_ERROR "Impossible de télécharger le fichier.\nVeuillez vérifier votre connexion Internet." - IDS_VERSION "Version: " - IDS_LICENCE "Licence: " - IDS_MAINTAINER "Maintainer: " - IDS_APPS_TITLE "Applications" - IDS_CATS_TITLE "Catégories" - IDS_CHOOSE_FOLDER "Veuillez choisir le répertoire..." - IDS_NOTCREATE_REGKEY "Échec lors de la création de la clé registre." - IDS_DOWNLOAD_FOLDER "Downloader" - IDS_UNABLECREATE_FOLDER "Échec lors du répertoire avec ce nom !" - IDS_UPDATE_URL "http://svn.reactos.org" - IDS_INSTALL_DEP "%s est nécessaire pour lancer %s. Voulez-vous installer %s maintenant ?" - TTT_HELPBUTTON "Obtenez de l'aide à propros du téléchargeur" - TTT_UPDATEBUTTON "Pas encore disponible" - TTT_PROFBUTTON "Vous permet de configurer le téléchargeur" -END diff --git a/reactos/base/applications/downloader/lang/id-ID.rc b/reactos/base/applications/downloader/lang/id-ID.rc deleted file mode 100644 index d632a4e4812..00000000000 --- a/reactos/base/applications/downloader/lang/id-ID.rc +++ /dev/null @@ -1,61 +0,0 @@ -LANGUAGE LANG_INDONESIAN, SUBLANG_DEFAULT - -IDD_DOWNLOAD DIALOGEX LOADONCALL MOVEABLE DISCARDABLE 0, 0, 220, 76 -STYLE DS_SHELLFONT | DS_CENTER | WS_BORDER | WS_CAPTION | WS_POPUP | WS_SYSMENU | WS_VISIBLE -CAPTION "Download..." -FONT 8, "MS Shell Dlg" -BEGIN - CONTROL "Progress1",IDC_PROGRESS,"msctls_progress32",WS_BORDER|PBS_SMOOTH,10,10,200,12 - LTEXT "", IDC_STATUS, 10, 30, 200, 10, SS_CENTER - PUSHBUTTON "Batal", IDCANCEL, 85, 58, 50, 15, WS_GROUP | WS_TABSTOP -END - -IDD_PROF DIALOGEX 6, 6, 267, 110 -STYLE DS_SHELLFONT | DS_CENTER | WS_BORDER | WS_CAPTION | WS_POPUP | WS_SYSMENU | WS_VISIBLE -CAPTION "Proferences" -FONT 8, "MS Shell Dlg" -BEGIN - LTEXT "Download folder:", -1, 6, 10, 140, 8 - EDITTEXT IDC_DOWNLOAD_FOLDER_EDIT, 6, 20, 205, 14, WS_VISIBLE | WS_TABSTOP - PUSHBUTTON "C&hoose...", IDC_CHOOSE_BUTTON, 216, 20, 45, 14 - AUTOCHECKBOX "&Delete installation files after setup", IDC_DELINST_FILES_CHECKBOX, 8, 40, 210, 10, WS_GROUP - LTEXT "Update server:", -1, 6, 55, 140, 8 - EDITTEXT IDC_UPDATE_SERVER_EDIT, 6, 65, 255, 14, WS_VISIBLE | WS_TABSTOP - DEFPUSHBUTTON "&OK", IDOK, 147, 90, 54, 15 - PUSHBUTTON "&Cancel", IDCANCEL, 207, 90, 54, 15 -END - -STRINGTABLE DISCARDABLE -BEGIN - IDS_WINDOW_TITLE "Download ! - ReactOS Downloader" - IDS_WELCOME_TITLE "Selamat datang di ReactOS Downloader" - IDS_WELCOME "Silahkan pilih kategori di sebelah kiri. Ini versi 1.1." - IDS_NO_APP_TITLE "Tidak ada aplikasi yang dipilih" - IDS_NO_APP "Silahkan pilih Aplikasi sebelum anda mengklik tombol download, jika anda membutuhkan asistensi silahkan klik pada tombol di sudut kanan atas." - IDS_UPDATE_TITLE "Mutakhirkan" - IDS_UPDATE "Maaf fitur ini belum diimplementasikan." - IDS_HELP_TITLE "Bantuan" - IDS_HELP "Pilih kategori di sisi kiri, lalu pilih aplikasi dan klik tombol download. Untuk memutakhirkan informasi aplikasi klik tombol disebelah tombol bantuan." - IDS_NO_APPS "Maaf, belum ada aplikasi dalam kategori ini. Anda dapat membantu dan menambahkan aplikasi lebih banyak." - IDS_CHOOSE_APP "Silahkan pilih aplikasi." - IDS_CHOOSE_SUB "Silahkan pilih subkategori." - IDS_CHOOSE_CATEGORY "Silahkan pilih kategori." - IDS_CHOOSE_BOTH "Silahkan pilih subkategori atau aplikasi." - IDS_XMLERROR_1 "Tidak dapat menemukan file xml !" - IDS_XMLERROR_2 "Tidak dapat mengurai file xml !" - IDS_DOWNLOAD_ERROR "Tidak bisa mendownload file.\nSilahkan periksa koneksi internet anda." - IDS_VERSION "Versi: " - IDS_LICENCE "Lisensi: " - IDS_MAINTAINER "Pemelihara: " - IDS_APPS_TITLE "Applications" - IDS_CATS_TITLE "Categories" - IDS_CHOOSE_FOLDER "Please, choose the folder..." - IDS_NOTCREATE_REGKEY "Could not create the registry key." - IDS_DOWNLOAD_FOLDER "Downloader" - IDS_UNABLECREATE_FOLDER "Unable to create a folder with this name!" - IDS_UPDATE_URL "http://svn.reactos.org" - IDS_INSTALL_DEP "%s is required to run %s. Should %s be installed now?" - TTT_HELPBUTTON "Get help about the downloader" - TTT_UPDATEBUTTON "Not yet available" - TTT_PROFBUTTON "Let you configure the downloader" -END diff --git a/reactos/base/applications/downloader/lang/it-IT.rc b/reactos/base/applications/downloader/lang/it-IT.rc deleted file mode 100644 index 28c97530bba..00000000000 --- a/reactos/base/applications/downloader/lang/it-IT.rc +++ /dev/null @@ -1,61 +0,0 @@ -LANGUAGE LANG_ITALIAN, SUBLANG_NEUTRAL - -IDD_DOWNLOAD DIALOGEX LOADONCALL MOVEABLE DISCARDABLE 0, 0, 220, 76 -STYLE DS_SHELLFONT | DS_CENTER | WS_BORDER | WS_CAPTION | WS_POPUP | WS_SYSMENU | WS_VISIBLE -CAPTION "Scarica..." -FONT 8, "MS Shell Dlg" -BEGIN - CONTROL "Progress1",IDC_PROGRESS,"msctls_progress32",WS_BORDER|PBS_SMOOTH,10,10,200,12 - LTEXT "", IDC_STATUS, 10, 30, 200, 10, SS_CENTER - PUSHBUTTON "Annulla", IDCANCEL, 85, 58, 50, 15, WS_GROUP | WS_TABSTOP -END - -IDD_PROF DIALOGEX 6, 6, 267, 110 -STYLE DS_SHELLFONT | DS_CENTER | WS_BORDER | WS_CAPTION | WS_POPUP | WS_SYSMENU | WS_VISIBLE -CAPTION "Preferenze" -FONT 8, "MS Shell Dlg" -BEGIN - LTEXT "Cartella dove scaricare:", -1, 6, 10, 140, 8 - EDITTEXT IDC_DOWNLOAD_FOLDER_EDIT, 6, 20, 205, 14, WS_VISIBLE | WS_TABSTOP - PUSHBUTTON "&Scegliere...", IDC_CHOOSE_BUTTON, 216, 20, 45, 14 - AUTOCHECKBOX "&Cancellare i file di installazione dopo il setup", IDC_DELINST_FILES_CHECKBOX, 8, 40, 210, 10, WS_GROUP - LTEXT "Server per gli aggiornamenti:", -1, 6, 55, 140, 8 - EDITTEXT IDC_UPDATE_SERVER_EDIT, 6, 65, 255, 14, WS_VISIBLE | WS_TABSTOP - DEFPUSHBUTTON "&OK", IDOK, 147, 90, 54, 15 - PUSHBUTTON "&Annulla", IDCANCEL, 207, 90, 54, 15 -END - -STRINGTABLE DISCARDABLE -BEGIN - IDS_WINDOW_TITLE "Scarica ! - ReactOS Downloader" - IDS_WELCOME_TITLE "Benvenuto al ReactOS Downloader" - IDS_WELCOME "Scegli una categoria a sinistra. Questa è la versione 1.1." - IDS_NO_APP_TITLE "Nessuna applicazione selezionata" - IDS_NO_APP "Scegli una Applicazione prima di premere il bottone Scarica, se serve assistenza clicca sul punto di domanda nell'angolo in alto a destra." - IDS_UPDATE_TITLE "Aggiorna" - IDS_UPDATE "Funzione non ancora implementata." - IDS_HELP_TITLE "Aiuto" - IDS_HELP "Scegli una categoria a sinistra, poi scegli una applicazione e clicca il bottone download. Per aggiornare le informazioni sulla applicazione clicca il bottone accanto a quello di aiuto." - IDS_NO_APPS "Non ci sono ancora applicazioni in questa categoria. Puoi aiutare aggiungendone altre." - IDS_CHOOSE_APP "Scegli una applicazione." - IDS_CHOOSE_SUB "Scegli una sottocategoria." - IDS_CHOOSE_CATEGORY "Scegli una categoria." - IDS_CHOOSE_BOTH "Scegli una sottocategoria o una applicazione." - IDS_XMLERROR_1 "File xml non trovato !" - IDS_XMLERROR_2 "Impossibile trattare il contenuto del file xml !" - IDS_DOWNLOAD_ERROR "Scaricamento del file impossibile.\nVerificare la connessione a Internet." - IDS_VERSION "Versione: " - IDS_LICENCE "Licenza: " - IDS_MAINTAINER "Manutentore: " - IDS_APPS_TITLE "Applicazioni" - IDS_CATS_TITLE "Categorie" - IDS_CHOOSE_FOLDER "Scegliere una cartella..." - IDS_NOTCREATE_REGKEY "Impossibile creare la chiave del registry." - IDS_DOWNLOAD_FOLDER "Scarica" - IDS_UNABLECREATE_FOLDER "Impossibile creare una cartella con questo nome!" - IDS_UPDATE_URL "http://svn.reactos.org" - IDS_INSTALL_DEP "%s è necessario per la esecuzione di %s. Si vuole procedere alla installazione di %s?" - TTT_HELPBUTTON "Informazioni su ReactOS Downloader" - TTT_UPDATEBUTTON "Non disponibile" - TTT_PROFBUTTON "Permette la configurazione del downloader" -END diff --git a/reactos/base/applications/downloader/lang/ja-JP.rc b/reactos/base/applications/downloader/lang/ja-JP.rc deleted file mode 100644 index eb8dd3949a4..00000000000 --- a/reactos/base/applications/downloader/lang/ja-JP.rc +++ /dev/null @@ -1,61 +0,0 @@ -LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT - -IDD_DOWNLOAD DIALOGEX LOADONCALL MOVEABLE DISCARDABLE 0, 0, 220, 76 -STYLE DS_SHELLFONT | DS_CENTER | WS_BORDER | WS_CAPTION | WS_POPUP | WS_SYSMENU | WS_VISIBLE -CAPTION "ƒ_ƒEƒ“ƒ[ƒh..." -FONT 9, "MS UI Gothic" -BEGIN - CONTROL "Progress1",IDC_PROGRESS,"msctls_progress32",WS_BORDER|PBS_SMOOTH,10,10,200,12 - LTEXT "", IDC_STATUS, 10, 30, 200, 10, SS_CENTER - PUSHBUTTON "ƒLƒƒƒ“ƒZƒ‹", IDCANCEL, 85, 58, 50, 15, WS_GROUP | WS_TABSTOP -END - -IDD_PROF DIALOGEX 6, 6, 267, 110 -STYLE DS_SHELLFONT | DS_CENTER | WS_BORDER | WS_CAPTION | WS_POPUP | WS_SYSMENU | WS_VISIBLE -CAPTION "ƒ†[ƒUÝ’è" -FONT 9, "MS UI Gothic" -BEGIN - LTEXT "ƒ_ƒEƒ“ƒ[ƒh‚·‚éƒtƒHƒ‹ƒ_:", -1, 6, 10, 140, 8 - EDITTEXT IDC_DOWNLOAD_FOLDER_EDIT, 6, 20, 205, 14, WS_VISIBLE | WS_TABSTOP - PUSHBUTTON "‘I‘ð(&H)...", IDC_CHOOSE_BUTTON, 216, 20, 45, 14 - AUTOCHECKBOX "ƒZƒbƒgƒAƒbƒvŒã‚ɃCƒ“ƒXƒg[ƒ‹ƒtƒ@ƒCƒ‹‚ð휂·‚é(&D)", IDC_DELINST_FILES_CHECKBOX, 8, 40, 210, 10, WS_GROUP - LTEXT "ƒAƒbƒvƒf[ƒg‚ÉŽg—p‚·‚éƒT[ƒo:", -1, 6, 55, 140, 8 - EDITTEXT IDC_UPDATE_SERVER_EDIT, 6, 65, 255, 14, WS_VISIBLE | WS_TABSTOP - DEFPUSHBUTTON "OK(&O)", IDOK, 147, 90, 54, 15 - PUSHBUTTON "ƒLƒƒƒ“ƒZƒ‹(&C)", IDCANCEL, 207, 90, 54, 15 -END - -STRINGTABLE DISCARDABLE -BEGIN - IDS_WINDOW_TITLE "ƒ_ƒEƒ“ƒ[ƒh ! - ReactOS ƒ_ƒEƒ“ƒ[ƒ_" - IDS_WELCOME_TITLE "ReactOS ƒ_ƒEƒ“ƒ[ƒ_‚ւ悤‚±‚»" - IDS_WELCOME "¶‘¤‚©‚çƒJƒeƒSƒŠ‚ð‘I‘ð‚µ‚Ä‚­‚¾‚³‚¢B ƒo[ƒWƒ‡ƒ“ 1.1‚Å‚·B" - IDS_NO_APP_TITLE "ƒAƒvƒŠƒP[ƒVƒ‡ƒ“‚ª‘I‘ð‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ" - IDS_NO_APP "ƒ_ƒEƒ“ƒ[ƒhƒ{ƒ^ƒ“‚ðƒNƒŠƒbƒN‚·‚é‘O‚ɃAƒvƒŠƒP[ƒVƒ‡ƒ“‚ð‘I‘ð‚µ‚Ä‚­‚¾‚³‚¢ ƒwƒ‹ƒv‚ª•K—v‚Èê‡Aˆê”Ô‰Eã‚ÌHƒ}[ƒNƒ{ƒ^ƒ“‚ðƒNƒŠƒbƒN‚µ‚Ä‚­‚¾‚³‚¢B" - IDS_UPDATE_TITLE "ƒAƒbƒvƒf[ƒg" - IDS_UPDATE "\\‚µ–ó‚ ‚è‚Ü‚¹‚ñB‚±‚Ì‹@”\\‚Í–¢ŽÀ‘•‚Å‚·B" - IDS_HELP_TITLE "ƒwƒ‹ƒv" - IDS_HELP "¶‘¤‚©‚çƒJƒeƒSƒŠ‚ð‘I‘ð‚µAƒAƒvƒŠƒP[ƒVƒ‡ƒ“‚ð‘I‘ð‚µ‚Äƒ_ƒEƒ“ƒ[ƒhƒ{ƒ^ƒ“‚ðƒNƒŠƒbƒN‚µ‚Ä‚­‚¾‚³‚¢B ƒAƒvƒŠƒP[ƒVƒ‡ƒ“‚Ìî•ñ‚ðƒAƒbƒvƒf[ƒg‚·‚é‚ɂ̓wƒ‹ƒvƒ{ƒ^ƒ“—ׂ̃{ƒ^ƒ“‚ðƒNƒŠƒbƒN‚µ‚Ä‚­‚¾‚³‚¢B" - IDS_NO_APPS "\\‚µ–ó‚ ‚è‚Ü‚¹‚ñB‚±‚̃JƒeƒSƒŠ‚ɂ̓AƒvƒŠƒP[ƒVƒ‡ƒ“‚ª‚Ü‚¾‚ ‚è‚Ü‚¹‚ñB Žè“`‚Á‚ÄA‚à‚Á‚ƃAƒvƒŠƒP[ƒVƒ‡ƒ“‚ð’ljÁ‚Å‚«‚Ü‚·B" - IDS_CHOOSE_APP "ƒAƒvƒŠƒP[ƒVƒ‡ƒ“‚ð‘I‘ð‚µ‚Ä‚­‚¾‚³‚¢B" - IDS_CHOOSE_SUB "ƒTƒuƒJƒeƒSƒŠ‚ð‘I‘ð‚µ‚Ä‚­‚¾‚³‚¢B" - IDS_CHOOSE_CATEGORY "ƒJƒeƒSƒŠ‚ð‘I‘ð‚µ‚Ä‚­‚¾‚³‚¢B" - IDS_CHOOSE_BOTH "ƒTƒuƒJƒeƒSƒŠ‚à‚µ‚­‚̓AƒvƒŠƒP[ƒVƒ‡ƒ“‚ð‘I‘ð‚µ‚Ä‚­‚¾‚³‚¢B" - IDS_XMLERROR_1 "xml ƒtƒ@ƒCƒ‹‚ªŒ©‚‚©‚è‚Ü‚¹‚ñ‚Å‚µ‚½ !" - IDS_XMLERROR_2 "xml ƒtƒ@ƒCƒ‹‚ð‰ð͂ł«‚Ü‚¹‚ñ‚Å‚µ‚½ !" - IDS_DOWNLOAD_ERROR "ƒtƒ@ƒCƒ‹‚ðƒ_ƒEƒ“ƒ[ƒh‚Å‚«‚Ü‚¹‚ñ‚Å‚µ‚½B\nƒCƒ“ƒ^[ƒlƒbƒgÚ‘±‚ðŠm”F‚µ‚Ä‚­‚¾‚³‚¢B" - IDS_VERSION "ƒo[ƒWƒ‡ƒ“: " - IDS_LICENCE "ƒ‰ƒCƒZƒ“ƒX: " - IDS_MAINTAINER "ŠÇ—ŽÒ: " - IDS_APPS_TITLE "ƒAƒvƒŠƒP[ƒVƒ‡ƒ“" - IDS_CATS_TITLE "ƒJƒeƒSƒŠ" - IDS_CHOOSE_FOLDER "ƒtƒHƒ‹ƒ_‚ð‘I‘ð‚µ‚Ä‚­‚¾‚³‚¢..." - IDS_NOTCREATE_REGKEY "ƒŒƒWƒXƒgƒŠƒL[‚ð쬂ł«‚Ü‚¹‚ñ‚Å‚µ‚½B" - IDS_DOWNLOAD_FOLDER "ƒ_ƒEƒ“ƒ[ƒ_" - IDS_UNABLECREATE_FOLDER "‚±‚Ì–¼‘O‚ŃtƒHƒ‹ƒ_‚ð쬂ł«‚Ü‚¹‚ñ!" - IDS_UPDATE_URL "http://svn.reactos.org" - IDS_INSTALL_DEP "%s‚Í%s‚ÌŽÀs‚É•K—v‚Å‚·B %s‚ð¡‚·‚®ƒCƒ“ƒXƒg[ƒ‹‚µ‚Ü‚·‚©?" - TTT_HELPBUTTON "‚±‚̃_ƒEƒ“ƒ[ƒ_‚ÉŠÖ‚·‚éƒwƒ‹ƒv‚ð“üŽè‚·‚é" - TTT_UPDATEBUTTON "‚Ü‚¾—˜—p‚Å‚«‚Ü‚¹‚ñ" - TTT_PROFBUTTON "ƒ_ƒEƒ“ƒ[ƒ_‚ðݒ肳‚¹‚Ü‚·" -END diff --git a/reactos/base/applications/downloader/lang/lt-LT.rc b/reactos/base/applications/downloader/lang/lt-LT.rc deleted file mode 100644 index cf5be5ff85e..00000000000 --- a/reactos/base/applications/downloader/lang/lt-LT.rc +++ /dev/null @@ -1,63 +0,0 @@ -/* Translation by Vytis "CMan" Girdþijauskas (cman@cman.us) */ - -LANGUAGE LANG_LITHUANIAN, SUBLANG_DEFAULT - -IDD_DOWNLOAD DIALOGEX LOADONCALL MOVEABLE DISCARDABLE 0, 0, 220, 76 -STYLE DS_SHELLFONT | DS_CENTER | WS_BORDER | WS_CAPTION | WS_POPUP | WS_SYSMENU | WS_VISIBLE -CAPTION "Siunèiama..." -FONT 8, "MS Shell Dlg" -BEGIN - CONTROL "Progress1",IDC_PROGRESS,"msctls_progress32",WS_BORDER|PBS_SMOOTH,10,10,200,12 - LTEXT "", IDC_STATUS, 10, 30, 200, 10, SS_CENTER - PUSHBUTTON "Atðaukti", IDCANCEL, 85, 58, 50, 15, WS_GROUP | WS_TABSTOP -END - -IDD_PROF DIALOGEX 6, 6, 267, 110 -STYLE DS_SHELLFONT | DS_CENTER | WS_BORDER | WS_CAPTION | WS_POPUP | WS_SYSMENU | WS_VISIBLE -CAPTION "Nuostatos" -FONT 8, "MS Shell Dlg" -BEGIN - LTEXT "Siuntø katalogas:", -1, 6, 10, 140, 8 - EDITTEXT IDC_DOWNLOAD_FOLDER_EDIT, 6, 20, 205, 14, WS_VISIBLE | WS_TABSTOP - PUSHBUTTON "&Pasirinkti...", IDC_CHOOSE_BUTTON, 216, 20, 45, 14 - AUTOCHECKBOX "&Naikinti diegimo bylas baigus diegimà", IDC_DELINST_FILES_CHECKBOX, 8, 40, 210, 10, WS_GROUP - LTEXT "Atnaujinimø serveris:", -1, 6, 55, 140, 8 - EDITTEXT IDC_UPDATE_SERVER_EDIT, 6, 65, 255, 14, WS_VISIBLE | WS_TABSTOP - DEFPUSHBUTTON "&OK", IDOK, 147, 90, 54, 15 - PUSHBUTTON "&Atðaukti", IDCANCEL, 207, 90, 54, 15 -END - -STRINGTABLE DISCARDABLE -BEGIN - IDS_WINDOW_TITLE "Download ! - ReactOS atsiuntimø tvarkytuvë" - IDS_WELCOME_TITLE "Jus sveikina ReactOS atsiuntimø tvarkytuvë" - IDS_WELCOME "Praðome pasirinkti kategorijà kairëje. \nÈia yra versija 1.1." - IDS_NO_APP_TITLE "Nepasirinkta programa" - IDS_NO_APP "Praðome pasirinkti programà prieð paspaudþiant siuntimo mygtukà, jei jums reikalinga pagalba, praðome spausti ant klaustuko virðutiniame deðiniajame kampe." - IDS_UPDATE_TITLE "Atnaujinti" - IDS_UPDATE "Atsipraðome, bet ði funkcija dar nesukurta." - IDS_HELP_TITLE "Pagalba" - IDS_HELP "Pasirinkite kategorijà kairëje, tuomet pasirinkite programà ir spauskite siuntimo mygtukà. Norëdami atnaujinti programos informacijà, spaukite mygtukà, kuris yra ðalia nuostatø mygtuko." - IDS_NO_APPS "Atsipraðome, bet ðioje kategorijoje programø dar nëra. Jûs galite padëti pridëdami daugiau programø." - IDS_CHOOSE_APP "Praðome pasirinkti programà." - IDS_CHOOSE_SUB "Praðome pasirinkti pokategorá." - IDS_CHOOSE_CATEGORY "Praðome pasirinkti kategorijà." - IDS_CHOOSE_BOTH "Praðome pasirinkti pokategorá arba programà." - IDS_XMLERROR_1 "Nepavyko rasti xml bylos!" - IDS_XMLERROR_2 "Nepavyko nuskaityti xml bylos!" - IDS_DOWNLOAD_ERROR "Nepavyko parsiøsti bylos.\nPraðome patikrinti interneto ryðá." - IDS_VERSION "Versija: " - IDS_LICENCE "Licencija: " - IDS_MAINTAINER "Palaikymas: " - IDS_APPS_TITLE "Programos" - IDS_CATS_TITLE "Kategorijos" - IDS_CHOOSE_FOLDER "Praðome pasirinkti katalogà..." - IDS_NOTCREATE_REGKEY "Nepavyko sukurti registro rakto." - IDS_DOWNLOAD_FOLDER "Downloader" - IDS_UNABLECREATE_FOLDER "Nepavyko sukurti katalogo su ðiuo vardu!" - IDS_UPDATE_URL "http://svn.reactos.org" - IDS_INSTALL_DEP "%s reikalingas paleisti %s. Diegti %s dabar?" - TTT_HELPBUTTON "Pateikia informacijà apie naudojimàsi programa" - TTT_UPDATEBUTTON "Dar nëra" - TTT_PROFBUTTON "Leidþia konfiguruoti programà" -END diff --git a/reactos/base/applications/downloader/lang/no-NO.rc b/reactos/base/applications/downloader/lang/no-NO.rc deleted file mode 100644 index 0a03c9bfa43..00000000000 --- a/reactos/base/applications/downloader/lang/no-NO.rc +++ /dev/null @@ -1,61 +0,0 @@ -LANGUAGE LANG_NORWEGIAN, SUBLANG_NEUTRAL - -IDD_DOWNLOAD DIALOGEX LOADONCALL MOVEABLE DISCARDABLE 0, 0, 220, 76 -STYLE DS_SHELLFONT | DS_CENTER | WS_BORDER | WS_CAPTION | WS_POPUP | WS_SYSMENU | WS_VISIBLE -CAPTION "Nedlasting..." -FONT 8, "MS Shell Dlg" -BEGIN - CONTROL "Prosess1",IDC_PROGRESS,"msctls_progress32",WS_BORDER|PBS_SMOOTH,10,10,200,12 - LTEXT "", IDC_STATUS, 10, 30, 200, 10, SS_CENTER - PUSHBUTTON "Avbryt", IDCANCEL, 85, 58, 50, 15, WS_GROUP | WS_TABSTOP -END - -IDD_PROF DIALOGEX 6, 6, 267, 110 -STYLE DS_SHELLFONT | DS_CENTER | WS_BORDER | WS_CAPTION | WS_POPUP | WS_SYSMENU | WS_VISIBLE -CAPTION "Innstillinger" -FONT 8, "MS Shell Dlg" -BEGIN - LTEXT "Nedlastingsmappe:", -1, 6, 10, 140, 8 - EDITTEXT IDC_DOWNLOAD_FOLDER_EDIT, 6, 20, 205, 14, WS_VISIBLE | WS_TABSTOP - PUSHBUTTON "V&elg...", IDC_CHOOSE_BUTTON, 216, 20, 45, 14 - AUTOCHECKBOX "&Slett installasjonsfiler etter innstallering", IDC_DELINST_FILES_CHECKBOX, 8, 40, 210, 10, WS_GROUP - LTEXT "Oppdater server:", -1, 6, 55, 140, 8 - EDITTEXT IDC_UPDATE_SERVER_EDIT, 6, 65, 255, 14, WS_VISIBLE | WS_TABSTOP - DEFPUSHBUTTON "&OK", IDOK, 147, 90, 54, 15 - PUSHBUTTON "&Avbryt", IDCANCEL, 207, 90, 54, 15 -END - -STRINGTABLE DISCARDABLE -BEGIN - IDS_WINDOW_TITLE "Nedlasting ! - ReactOS Nedlasting" - IDS_WELCOME_TITLE "Velkommen til ReactOS Nedlasting" - IDS_WELCOME "Vennligst velg en kategori til høyre. Dette er versjon 1.1." - IDS_NO_APP_TITLE "Ingen applikasjoner er valgt" - IDS_NO_APP "Vennligst velg en applikasjon før du klikker på nedlasting knappen, hvis du trenger hjelp vennligst klikk på spørsmålsmerke knappen på toppen i høyre hjørne." - IDS_UPDATE_TITLE "Oppdater" - IDS_UPDATE "Beklager denne funksjonen er ikke implementert ennå." - IDS_HELP_TITLE "Hjelp" - IDS_HELP "Velg en kategori til venstre, også velg en applikasjon og klikk på nedlastings knappen. For å oppdatere applikasjon informasjonen klikk på knappen neste etter hjelp knappen." - IDS_NO_APPS "Beklager, det er ingen applikasjoner i denne kategorien ennå. Du kan hjelpe og legge til flere applikasjoner." - IDS_CHOOSE_APP "Vennligst velg en applikasjon." - IDS_CHOOSE_SUB "Vennligst velg en underkategori." - IDS_CHOOSE_CATEGORY "Vennligst velg en kategori." - IDS_CHOOSE_BOTH "Vennligst velg en underkategori eller en applikasjon." - IDS_XMLERROR_1 "Kan ikke finne xml filen !" - IDS_XMLERROR_2 "Kan ikke analysere xml filen !" - IDS_DOWNLOAD_ERROR "Ikke mulig å laste ned filen.\nVennligst sjekk din internett forbindelse." - IDS_VERSION "Versjon: " - IDS_LICENCE "Lisens: " - IDS_MAINTAINER "Produsent: " - IDS_APPS_TITLE "Applikasjoner" - IDS_CATS_TITLE "Kategori" - IDS_CHOOSE_FOLDER "Vennligst, velg mappen..." - IDS_NOTCREATE_REGKEY "Kan ikke opprette registernøkkel." - IDS_DOWNLOAD_FOLDER "Nedlasting" - IDS_UNABLECREATE_FOLDER "Ikke mulig å opprette mappe med dette navnet!" - IDS_UPDATE_URL "http://svn.reactos.org" - IDS_INSTALL_DEP "%s trengs å bli kjørt %s. Skal %s bli innstallert nå?" - TTT_HELPBUTTON "Få hjelp om nedlastingen" - TTT_UPDATEBUTTON "Ikke ennå tilgjengelig" - TTT_PROFBUTTON "La deg konfigurere nedlastingen" -END diff --git a/reactos/base/applications/downloader/lang/pl-PL.rc b/reactos/base/applications/downloader/lang/pl-PL.rc deleted file mode 100644 index 17e950a7ab0..00000000000 --- a/reactos/base/applications/downloader/lang/pl-PL.rc +++ /dev/null @@ -1,68 +0,0 @@ -/* - * translated by Caemyr - Olaf Siejka (Feb, 2008) - * Use ReactOS forum PM or IRC to contact me - * http://www.reactos.org - * IRC: irc.freenode.net #reactos-pl; - */ - -LANGUAGE LANG_POLISH, SUBLANG_DEFAULT - -IDD_DOWNLOAD DIALOGEX LOADONCALL MOVEABLE DISCARDABLE 0, 0, 220, 76 -STYLE DS_SHELLFONT | DS_CENTER | WS_BORDER | WS_CAPTION | WS_POPUP | WS_SYSMENU | WS_VISIBLE -CAPTION "Œci¹gaj..." -FONT 8, "MS Shell Dlg" -BEGIN - CONTROL "Progress1",IDC_PROGRESS,"msctls_progress32",WS_BORDER|PBS_SMOOTH,10,10,200,12 - LTEXT "", IDC_STATUS, 10, 30, 200, 10, SS_CENTER - PUSHBUTTON "Anuluj", IDCANCEL, 85, 58, 50, 15, WS_GROUP | WS_TABSTOP -END - -IDD_PROF DIALOGEX 6, 6, 267, 110 -STYLE DS_SHELLFONT | DS_CENTER | WS_BORDER | WS_CAPTION | WS_POPUP | WS_SYSMENU | WS_VISIBLE -CAPTION "Ustawienia" -FONT 8, "MS Shell Dlg" -BEGIN - LTEXT "Katalog do œci¹gania:", -1, 6, 10, 140, 8 - EDITTEXT IDC_DOWNLOAD_FOLDER_EDIT, 6, 20, 205, 14, WS_VISIBLE | WS_TABSTOP - PUSHBUTTON "&Wybierz...", IDC_CHOOSE_BUTTON, 216, 20, 45, 14 - AUTOCHECKBOX "&Skasuj œci¹gniête pliki po zainstalowaniu programu", IDC_DELINST_FILES_CHECKBOX, 8, 40, 210, 10, WS_GROUP - LTEXT "Uaktualnij:", -1, 6, 55, 140, 8 - EDITTEXT IDC_UPDATE_SERVER_EDIT, 6, 65, 255, 14, WS_VISIBLE | WS_TABSTOP - DEFPUSHBUTTON "&OK", IDOK, 147, 90, 54, 15 - PUSHBUTTON "&Anuluj", IDCANCEL, 207, 90, 54, 15 -END - -STRINGTABLE DISCARDABLE -BEGIN - IDS_WINDOW_TITLE "Download! - Mened¿er pobierania dla ReactOS" - IDS_WELCOME_TITLE "Witamy w Download! dla ReactOS" - IDS_WELCOME "Proszê wybraæ kategoriê po lewej. Wersja programu: 1.1." - IDS_NO_APP_TITLE "Nie wybrano programu" - IDS_NO_APP "Proszê wybraæ program, przed klikniêciem w przycisk Œci¹gnij. W razie problemów kliknij w znak zapytania, w prawym górnym rogu okna." - IDS_UPDATE_TITLE "Uaktualnij" - IDS_UPDATE "Przepraszamy, ta opcja nie jest jeszcze dostêpna." - IDS_HELP_TITLE "Pomoc" - IDS_HELP "Wybierz kategoriê po lewej, nastêpnie wybierz program i kliknij w przycisk Œci¹gnij. Aby uaktualniæ listê programów, naciœnij przycisk obok przycisku Pomocy." - IDS_NO_APPS "Przepraszamy, nie ma programów w tej kategorii. Mo¿esz pomóc nam w wyborze nowych programów." - IDS_CHOOSE_APP "Proszê wybraæ program." - IDS_CHOOSE_SUB "Proszê wybraæ podkategoriê." - IDS_CHOOSE_CATEGORY "Proszê wybraæ kategoriê." - IDS_CHOOSE_BOTH "Proszê wybraæ podkategoriê albo program." - IDS_XMLERROR_1 "Plik XML nie zosta³ znaleziony !" - IDS_XMLERROR_2 "Nie uda³o siê przetworzyæ pliku XML !" - IDS_DOWNLOAD_ERROR "Sci¹ganie pliku nieudane.\nProszê sprawdziæ po³¹czenie z internetem." - IDS_VERSION "Wersja: " - IDS_LICENCE "Licencja: " - IDS_MAINTAINER "Opiekun: " - IDS_APPS_TITLE "Programy" - IDS_CATS_TITLE "Kategorie" - IDS_CHOOSE_FOLDER "Proszê wybraæ katalog..." - IDS_NOTCREATE_REGKEY "Nie uda³o siê utworzyæ kluczy rejestru." - IDS_DOWNLOAD_FOLDER "Pobrane" - IDS_UNABLECREATE_FOLDER "Nie uda³o siê stworzyæ katalogu o tej nazwie!" - IDS_UPDATE_URL "http://svn.reactos.org" - IDS_INSTALL_DEP "%s jest wymagany do uruchomienia %s. Czy chcesz zainstalowaæ %s w tej chwili?" - TTT_HELPBUTTON "Pomoc Mened¿era pobierania" - TTT_UPDATEBUTTON "Niedostêpne" - TTT_PROFBUTTON "Ustawienia Mened¿era pobierania" -END diff --git a/reactos/base/applications/downloader/lang/ru-RU.rc b/reactos/base/applications/downloader/lang/ru-RU.rc deleted file mode 100644 index 36f7cca0ea1..00000000000 --- a/reactos/base/applications/downloader/lang/ru-RU.rc +++ /dev/null @@ -1,63 +0,0 @@ -//Russian language file. (Dmitry Chapyshev, 2007.06.21) - -LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT - -IDD_DOWNLOAD DIALOGEX LOADONCALL MOVEABLE DISCARDABLE 0, 0, 220, 76 -STYLE DS_SHELLFONT | DS_CENTER | WS_BORDER | WS_CAPTION | WS_POPUP | WS_SYSMENU | WS_VISIBLE -CAPTION "Çàãðóçêà..." -FONT 8, "MS Shell Dlg" -BEGIN - CONTROL "Progress1",IDC_PROGRESS,"msctls_progress32",WS_BORDER|PBS_SMOOTH,10,10,200,12 - LTEXT "", IDC_STATUS, 10, 30, 200, 17, SS_CENTER - PUSHBUTTON "Îòìåíà", IDCANCEL, 85, 58, 50, 15, WS_GROUP | WS_TABSTOP -END - -IDD_PROF DIALOGEX 6, 6, 267, 110 -STYLE DS_SHELLFONT | DS_CENTER | WS_BORDER | WS_CAPTION | WS_POPUP | WS_SYSMENU | WS_VISIBLE -CAPTION "Íàñòðîéêè" -FONT 8, "MS Shell Dlg" -BEGIN - LTEXT "Ïàïêà äëÿ çàêà÷êè:", -1, 6, 10, 140, 8 - EDITTEXT IDC_DOWNLOAD_FOLDER_EDIT, 6, 20, 205, 14, WS_VISIBLE | WS_TABSTOP - PUSHBUTTON "&Âûáðàòü...", IDC_CHOOSE_BUTTON, 216, 20, 45, 14 - AUTOCHECKBOX "&Óäàëÿòü óñòàíîâî÷íûå ôàéëû ïîñëå óñòàíîâêè", IDC_DELINST_FILES_CHECKBOX, 8, 40, 210, 10, WS_GROUP - LTEXT "Ñåðâåð îáíîâëåíèé:", -1, 6, 55, 140, 8 - EDITTEXT IDC_UPDATE_SERVER_EDIT, 6, 65, 255, 14, WS_VISIBLE | WS_TABSTOP - DEFPUSHBUTTON "&OK", IDOK, 147, 90, 54, 15 - PUSHBUTTON "Î&òìåíà", IDCANCEL, 207, 90, 54, 15 -END - -STRINGTABLE DISCARDABLE -BEGIN - IDS_WINDOW_TITLE "Ñêà÷àòü! - Ìåíåäæåð çàêà÷åê ReactOS" - IDS_WELCOME_TITLE "Äîáðî ïîæàëîâàòü â Ìåíåäæåð çàêà÷åê ReactOS" - IDS_WELCOME "Ïîæàëóéñòà âûáåðèòå êàòåãîðèþ ñïðàâà. Âåðñèÿ 1.1" - IDS_NO_APP_TITLE "Ïðèëîæåíèå íå âûáðàíî" - IDS_NO_APP "Ïîæàëóéñòà, âûáåðèòå ïðèëîæåíèå ïðåæäå, ÷åì íàæàòü êíîïêó çàãðóçêè. Åñëè âàì íóæíà ñïðàâêà, òî íàæìèòå êíîïêó ñî çíàêîì âîïðîñà â âåðõíåì ïðàâîì óãëó." - IDS_UPDATE_TITLE "Îáíîâèòü" - IDS_UPDATE "Èçâèíèòå, äàííàÿ âîçìîæíîñòü íà äàííûì ìîìåíò íåäîñòóïíà." - IDS_HELP_TITLE "Ñïðàâêà" - IDS_HELP "Âûáåðèòå êàòåãîðèþ ñëåâà, çàòåì âûáåðèòå ïðèëîæåíèå è íàæìèòå êíîïêó çàãðóçêè. Äëÿ ïîëó÷åíèÿ èíôîðìàöèè îá îáíîâëåíèÿõ íàæìèòå êíîïêó ðÿäîì ñ êíîïêîé ñïðàâêè." - IDS_NO_APPS "Èçâåíèòå, íà äàííûé ìîìåíò â ýòîé êàòåãîðèè ïðèëîæåíèé íåò, íî âû ìîæåòå ïîìî÷ü äîáàâèòü èõ." - IDS_CHOOSE_APP "Ïîæàëóéñòà âûáåðèòå ïðèëîæåíèå." - IDS_CHOOSE_SUB "Ïîæàëóéñòà âûáåðèòå ïîäêàòåãîðèþ." - IDS_CHOOSE_CATEGORY "Ïîæàëóéñòà âûáåðèòå êàòåãîðèþ." - IDS_CHOOSE_BOTH "Ïîæàëóéñòà âûáåðèòå ïîäêàòåãîðèþ èëè ïðèëîæåíèå." - IDS_XMLERROR_1 "Íå óäàëîñü íàéòè xml-ôàéë!" - IDS_XMLERROR_2 "Íå óäàëîñü îáðàáîòàòü xml-ôàéë!" - IDS_DOWNLOAD_ERROR "Íå óäàåòñÿ çàãðóçèòü ôàéë.\nÏîæàëóéñòà ïðîâåðüòå âàøå ïîäêëþ÷åíèå ê èíòåðíåò." - IDS_VERSION "Âåðñèÿ: " - IDS_LICENCE "Ëèöåíçèÿ: " - IDS_MAINTAINER "Ïðîèçâîäèòåëü: " - IDS_APPS_TITLE "Ïðèëîæåíèÿ" - IDS_CATS_TITLE "Êàòåãîðèè" - IDS_CHOOSE_FOLDER "Ïîæàëóéñòâà âûáåðèòå ïàïêó..." - IDS_NOTCREATE_REGKEY "Íå óäàëîñü ñîçäàòü êëþ÷ â ðååñòðå." - IDS_DOWNLOAD_FOLDER "Downloader" - IDS_UNABLECREATE_FOLDER "Íå óäàëîñü ñîçäàòü ïàïêó ñ òàêèì èìåíåì!" - IDS_UPDATE_URL "http://svn.reactos.org" - IDS_INSTALL_DEP "%s òðåáóåòñÿ äëÿ çàïóñêà %s. Óñòàíîâèòü %s?" - TTT_HELPBUTTON "Ïîêàçàòü ñïðàâêó ïðîãðàììû" - TTT_UPDATEBUTTON "Ñåé÷àñ íåäîñòóïíî" - TTT_PROFBUTTON "Âûïîëíèòü íàñòðîéêó ïðîãðàììû" -END diff --git a/reactos/base/applications/downloader/lang/sk-SK.rc b/reactos/base/applications/downloader/lang/sk-SK.rc deleted file mode 100644 index 9acd98d9370..00000000000 --- a/reactos/base/applications/downloader/lang/sk-SK.rc +++ /dev/null @@ -1,67 +0,0 @@ -/* TRANSLATOR: Mário Kaèmár /Mario Kacmar/ aka Kario (kario@szm.sk) - * DATE OF TR: 21-01-2008 - * LastChange: 31-10-2008 - */ - - -LANGUAGE LANG_SLOVAK, SUBLANG_DEFAULT - -IDD_DOWNLOAD DIALOGEX LOADONCALL MOVEABLE DISCARDABLE 0, 0, 220, 76 -STYLE DS_SHELLFONT | DS_CENTER | WS_BORDER | WS_CAPTION | WS_POPUP | WS_SYSMENU | WS_VISIBLE -CAPTION "Sahujem ..." -FONT 8, "MS Shell Dlg" -BEGIN - CONTROL "Progress1",IDC_PROGRESS,"msctls_progress32",WS_BORDER|PBS_SMOOTH,10,10,200,12 - LTEXT "", IDC_STATUS, 10, 30, 200, 10, SS_CENTER - PUSHBUTTON "Zruši", IDCANCEL, 85, 58, 50, 15, WS_GROUP | WS_TABSTOP -END - -IDD_PROF DIALOGEX 6, 6, 267, 110 -STYLE DS_SHELLFONT | DS_CENTER | WS_BORDER | WS_CAPTION | WS_POPUP | WS_SYSMENU | WS_VISIBLE -CAPTION "Nastavenia" //Preferencies -FONT 8, "MS Shell Dlg" -BEGIN - LTEXT "Prieèinok sahovania:", -1, 6, 10, 140, 8 - EDITTEXT IDC_DOWNLOAD_FOLDER_EDIT, 6, 20, 205, 14, WS_VISIBLE | WS_TABSTOP - PUSHBUTTON "&Vybra ...", IDC_CHOOSE_BUTTON, 216, 20, 45, 14 - AUTOCHECKBOX "&Odstráni inštalaèné súbory po nainštalovaní", IDC_DELINST_FILES_CHECKBOX, 8, 40, 210, 10, WS_GROUP - LTEXT "Aktualizova server:", -1, 6, 55, 140, 8 - EDITTEXT IDC_UPDATE_SERVER_EDIT, 6, 65, 255, 14, WS_VISIBLE | WS_TABSTOP - DEFPUSHBUTTON "&OK", IDOK, 147, 90, 54, 15 - PUSHBUTTON "&Zruši", IDCANCEL, 207, 90, 54, 15 -END - -STRINGTABLE DISCARDABLE -BEGIN - IDS_WINDOW_TITLE "ahaj! - Downloader systému ReactOS" - IDS_WELCOME_TITLE "Vitajte v programe Downloader systému ReactOS" - IDS_WELCOME "Vyberte, prosím, kategóriu na ¾avej strane. Toto je verzia 1.1." - IDS_NO_APP_TITLE "Nie je vybraný žiadny program" - IDS_NO_APP "Vyberte, prosím, program predtým než kliknete na tlaèidlo stiahnu. Ak potrebujete pomoc, kliknite, prosím, na tlaèidlo otáznika v pravom hornom rohu." - IDS_UPDATE_TITLE "Aktualizova" - IDS_UPDATE "Prepáète, ale táto funkcia zatia¾ nie je implementovaná." - IDS_HELP_TITLE "Pomocník" - IDS_HELP "Vyberte kategóriu na ¾avej strane, potom vyberte program a kliknite na tlaèidlo stiahnu. Pre aktualizáciu informácii o programe kliknite na tlaèidlo ved¾a tlaèidla pomoc." - IDS_NO_APPS "Prepáète, ale zatia¾ sa v tejto kategórii nenachádzajú žiadne programy. Môžete pomôc a prida viac programov." - IDS_CHOOSE_APP "Vyberte program, prosím." - IDS_CHOOSE_SUB "Vyberte podkategóriu, prosím." - IDS_CHOOSE_CATEGORY "Vyberte kategóriu, prosím." - IDS_CHOOSE_BOTH "Vyberte podkategóriu alebo program, prosím." - IDS_XMLERROR_1 "Nepodarilo sa nájs súbor xml!" - IDS_XMLERROR_2 "Nepodarilo sa správne analyzova súbor xml!" - IDS_DOWNLOAD_ERROR "Nepodarilo sa stiahnu súbor.\nSkontrolujte, prosím, pripojenie do siete internet." - IDS_VERSION "Verzia: " - IDS_LICENCE "Licencia: " - IDS_MAINTAINER "Údržbár: " //Maintainer - IDS_APPS_TITLE "Programy" - IDS_CATS_TITLE "Kategórie" - IDS_CHOOSE_FOLDER "Vyberte, prosím, prieèinok ..." - IDS_NOTCREATE_REGKEY "Nepodarilo sa vytvori k¾úè registra." - IDS_DOWNLOAD_FOLDER "Downloader" - IDS_UNABLECREATE_FOLDER "Nie je možné vytvori prieèinok s týmto názvom!" - IDS_UPDATE_URL "http://svn.reactos.org" - IDS_INSTALL_DEP "%s je potrebný pre spustenie %s. Má sa %s nainštalova teraz?" - TTT_HELPBUTTON "Získa nápoveï k programu downloader" - TTT_UPDATEBUTTON "Zatia¾ nie je k dispozícií" - TTT_PROFBUTTON "Dovolí Vám konfigurova program downloader" -END diff --git a/reactos/base/applications/downloader/lang/uk-UA.rc b/reactos/base/applications/downloader/lang/uk-UA.rc deleted file mode 100644 index acd1a0fe5ad..00000000000 --- a/reactos/base/applications/downloader/lang/uk-UA.rc +++ /dev/null @@ -1,69 +0,0 @@ -/* - * PROJECT: ReactOS Downloader - * LICENSE: GPL - See COPYING in the top level directory - * FILE: rosapps/downloader/lang/uk-UA.rc - * PURPOSE: Ukraianian Language File for Downloader - * TRANSLATOR: Artem Reznikov - */ - -LANGUAGE LANG_UKRAINIAN, SUBLANG_DEFAULT - -IDD_DOWNLOAD DIALOGEX LOADONCALL MOVEABLE DISCARDABLE 0, 0, 220, 76 -STYLE DS_SHELLFONT | DS_CENTER | WS_BORDER | WS_CAPTION | WS_POPUP | WS_SYSMENU | WS_VISIBLE -CAPTION "Çàâàíòàæåííÿ..." -FONT 8, "MS Shell Dlg" -BEGIN - CONTROL "Progress1",IDC_PROGRESS,"msctls_progress32",WS_BORDER|PBS_SMOOTH,10,10,200,12 - LTEXT "", IDC_STATUS, 10, 30, 200, 10, SS_CENTER - PUSHBUTTON "Ñêàñóâàòè", IDCANCEL, 85, 58, 50, 15, WS_GROUP | WS_TABSTOP -END - -IDD_PROF DIALOGEX 6, 6, 267, 110 -STYLE DS_SHELLFONT | DS_CENTER | WS_BORDER | WS_CAPTION | WS_POPUP | WS_SYSMENU | WS_VISIBLE -CAPTION "Íàñòðîéêè" -FONT 8, "MS Shell Dlg" -BEGIN - LTEXT "Ïàïêà äëÿ çàâàíòàæåííÿ:", -1, 6, 10, 140, 8 - EDITTEXT IDC_DOWNLOAD_FOLDER_EDIT, 6, 20, 205, 14, WS_VISIBLE | WS_TABSTOP - PUSHBUTTON "&Âèáðàòè...", IDC_CHOOSE_BUTTON, 216, 20, 45, 14 - AUTOCHECKBOX "&Âèäàëÿòè íàñòàíîâí³ ôàéëè ï³ñëÿ óñòàíîâêè", IDC_DELINST_FILES_CHECKBOX, 8, 40, 210, 10, WS_GROUP - LTEXT "Ñåðâåð îíîâëåíü:", -1, 6, 55, 140, 8 - EDITTEXT IDC_UPDATE_SERVER_EDIT, 6, 65, 255, 14, WS_VISIBLE | WS_TABSTOP - DEFPUSHBUTTON "&OK", IDOK, 147, 90, 54, 15 - PUSHBUTTON "&Ñêàñóâàòè", IDCANCEL, 207, 90, 54, 15 -END - -STRINGTABLE DISCARDABLE -BEGIN - IDS_WINDOW_TITLE "Çàâàíòàæèòè ! - Çàâàíòàæóâà÷ ReactOS" - IDS_WELCOME_TITLE "Ëàñêàâî ïðîñèìî ó Çàâàíòàæóâà÷ ReactOS" - IDS_WELCOME "Áóäü ëàñêà âèáåð³òü êàòåãîð³þ çë³âà. Öå âåðñ³ÿ 1.1." - IDS_NO_APP_TITLE "Äîäàòîê íå âèáðàíèé" - IDS_NO_APP "Áóäü ëàñêà, âèáåð³òü äîäàòîê ïåðø í³æ íàòèñíóòè êíîïêó çàâàíòàæåííÿ. ßêùî Âàì ïîòð³áíà äîïîìîãà, íàòèñí³òü êíîïêó ç³ çíàêîì ïèòàííÿ ó âåðõíüîìó ïðàâîìó êóòêó." - IDS_UPDATE_TITLE "Îíîâèòè" - IDS_UPDATE "Âèáà÷òå, äàíà ìîæëèâ³ñòü ùå íåäîñòóïíà." - IDS_HELP_TITLE "Äîâ³äêà" - IDS_HELP "Âèáåð³òü êàòåãîð³þ çë³âà, ïîò³ì âèáåð³òü äîäàòîê ³ íàòèñí³òü êíîïêó çàâàíòàæåííÿ. Äëÿ îòðèìàííÿ ³íôîðìàö³¿ ïðî îíîâëåííÿ íàòèñí³òü êíîïêó ïîðÿä ç êíîïêîþ äîâ³äêè." - IDS_NO_APPS "Âèáà÷òå, â ö³é êàòåãî𳿠ùå íåìຠäîäàòê³â. Âè ìîæåòå äîïîìîãòè ³ äîäàòè á³ëüøå äîäàòê³â." - IDS_CHOOSE_APP "Áóäü ëàñêà âèáåð³òü äîäàòîê." - IDS_CHOOSE_SUB "Áóäü ëàñêà âèáåð³òü ï³äêàòåãîð³þ." - IDS_CHOOSE_CATEGORY "Áóäü ëàñêà âèáåð³òü êàòåãîð³þ." - IDS_CHOOSE_BOTH "Áóäü ëàñêà âèáåð³òü ï³äêàòåãîð³þ àáî äîäàòîê." - IDS_XMLERROR_1 "Íå âäàëîñÿ çíàéòè ôàéë XML !" - IDS_XMLERROR_2 "Íå âäàëîñÿ îáðîáèòè ôàéë XML !" - IDS_DOWNLOAD_ERROR "Íåìîæëèâî çàâàíòàæèòè ôàéë.\nÁóäü ëàñêà ïåðåâ³ðòå âàøå ³íòåðíåò-ç'ºäíàííÿ." - IDS_VERSION "Âåðñ³ÿ: " - IDS_LICENCE "˳öåíç³ÿ: " - IDS_MAINTAINER "Âèðîáíèê: " - IDS_APPS_TITLE "Äîäàòêè" - IDS_CATS_TITLE "Êàòåãîð³¿" - IDS_CHOOSE_FOLDER "Áóäü ëàñêà âèáåð³òü ïàïêó..." - IDS_NOTCREATE_REGKEY "Íå âäàëîñÿ ñòâîðèòè êëþ÷ ó ðåºñòð³." - IDS_DOWNLOAD_FOLDER "Downloader" - IDS_UNABLECREATE_FOLDER "Íå âäàëîñÿ ñòâîðèòè ïàïêó ç òàêèì ³ì'ÿì!" - IDS_UPDATE_URL "http://svn.reactos.org" - IDS_INSTALL_DEP "%s ïîòð³áíèé ùîá çàïóñòèòè %s. Âñòàíîâèòè %s çàðàç?" - TTT_HELPBUTTON "Îòðèìàéòè äîïîìîãó ïðî çàâàíòàæóâà÷" - TTT_UPDATEBUTTON "Ïîêè ùî íå äîñòóïíî" - TTT_PROFBUTTON "Íàëàøòóâàòè çàâàíòàæóâà÷" -END diff --git a/reactos/base/applications/downloader/main.c b/reactos/base/applications/downloader/main.c deleted file mode 100644 index 5e14ecb2de6..00000000000 --- a/reactos/base/applications/downloader/main.c +++ /dev/null @@ -1,922 +0,0 @@ -/* PROJECT: ReactOS Downloader - * LICENSE: GPL - See COPYING in the top level directory - * FILE: base/applications/downloader/xml.c - * PURPOSE: Main program - * PROGRAMMERS: Maarten Bosma, Lester Kortenhoeven, Dmitry Chapyshev - */ - -#include -#include -#include -#include -#include -#include -#include -#include "resources.h" -#include "structures.h" - -HWND hwnd, hCategories, hApps, hDownloadButton, hUninstallButton, hUpdateButton, hHelpButton, hProfButton; -HBITMAP hLogo, hUnderline; -WCHAR* DescriptionHeadline = L""; -WCHAR* DescriptionText = L""; -WCHAR ApplicationText[700]; - -struct Category Root; -struct Application* SelectedApplication; - -INT_PTR CALLBACK DownloadProc (HWND, UINT, WPARAM, LPARAM); -BOOL ProcessXML (const char* filename, struct Category* Root); -VOID FreeTree (struct Category* Node); -WCHAR Strings [STRING_COUNT][MAX_STRING_LENGHT]; - - -BOOL -getUninstaller(WCHAR* RegName, WCHAR* Uninstaller) { - HKEY hKey1; - HKEY hKey2; - DWORD Type = 0; - DWORD Size = MAX_PATH; - WCHAR Value[MAX_PATH]; - WCHAR KeyName[MAX_PATH]; - LONG i = 0; - - if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall",0,KEY_READ,&hKey1) == ERROR_SUCCESS) { - while (RegEnumKeyExW(hKey1,i,KeyName,&Size,NULL,NULL,NULL,NULL) == ERROR_SUCCESS) { - ++i; - RegOpenKeyExW(hKey1,KeyName,0,KEY_READ,&hKey2); - Size = MAX_PATH; - if (RegQueryValueExW(hKey2,L"DisplayName",0,&Type,(LPBYTE)Value,&Size) == ERROR_SUCCESS) { - Size = MAX_PATH; - if (StrCmpW(Value,RegName) == 0) { - if (RegQueryValueExW(hKey2,L"UninstallString",0,&Type,(LPBYTE)Uninstaller,&Size) == ERROR_SUCCESS) { - RegCloseKey(hKey2); - RegCloseKey(hKey1); - return TRUE; - } else { - RegCloseKey(hKey2); - RegCloseKey(hKey1); - return FALSE; - } - } - } - RegCloseKey(hKey2); - Size = MAX_PATH; - } - RegCloseKey(hKey1); - } - return FALSE; -} - -void -ShowMessage (WCHAR* title, WCHAR* message) -{ - DescriptionHeadline = title; - DescriptionText = message; - InvalidateRect(hwnd,NULL,TRUE); - UpdateWindow(hwnd); -} - -void -AddItems(HWND hwnd, struct Category* Category, struct Category* Parent) -{ - TV_INSERTSTRUCTW Insert; - - Insert.item.lParam = (LPARAM)Category; - Insert.item.mask = TVIF_TEXT|TVIF_PARAM|TVIF_IMAGE|TVIF_SELECTEDIMAGE;; - Insert.item.pszText = Category->Name; - Insert.item.cchTextMax = lstrlenW(Category->Name); - Insert.item.iImage = Category->Icon; - Insert.item.iSelectedImage = Category->Icon; - Insert.hInsertAfter = TVI_LAST; - Insert.hParent = Category->Parent ? Category->Parent->TreeviewItem : TVI_ROOT; - - Category->TreeviewItem = (HTREEITEM)SendMessage(hwnd, TVM_INSERTITEM, 0, (LPARAM)&Insert); - - if(Category->Next) - AddItems (hwnd,Category->Next,Parent); - - if(Category->Children) - AddItems (hwnd,Category->Children,Category); -} - -void -CategoryChoosen(HWND hwnd, struct Category* Category) -{ - struct Application* CurrentApplication; - TV_INSERTSTRUCTW Insert; - WCHAR Uninstaller[200]; - SelectedApplication = NULL; - - if(Category->Children && !Category->Apps) - ShowMessage(Category->Name, Strings[IDS_CHOOSE_SUB]); - else if(!Category->Children && Category->Apps) - ShowMessage(Category->Name, Strings[IDS_CHOOSE_APP]); - else if(Category->Children && Category->Apps) - ShowMessage(Category->Name, Strings[IDS_CHOOSE_BOTH]); - else - ShowMessage(Category->Name, Strings[IDS_NO_APPS]); - - (void)TreeView_DeleteItem(hwnd, TVI_ROOT); - (void)TreeView_DeleteItem(hwnd, TVI_ROOT); // Delete twice to bypass bug in windows - - Insert.item.mask = TVIF_TEXT|TVIF_PARAM|TVIF_IMAGE; - Insert.hInsertAfter = TVI_LAST; - Insert.hParent = TVI_ROOT; - - CurrentApplication = Category->Apps; - while(CurrentApplication) - { - Insert.item.lParam = (LPARAM)CurrentApplication; - Insert.item.pszText = CurrentApplication->Name; - Insert.item.cchTextMax = lstrlenW(CurrentApplication->Name); - Insert.item.iImage = 10; - if(StrCmpW(CurrentApplication->RegName,L"")) { - if(getUninstaller(CurrentApplication->RegName, Uninstaller)) - Insert.item.iImage = 9; - } - SendMessage(hwnd, TVM_INSERTITEM, 0, (LPARAM)&Insert); - CurrentApplication = CurrentApplication->Next; - } -} - -BOOL CreateToolTip(HWND hwndTool, HWND hDlg, WCHAR* pText) -{ - HWND hwndTip; - TOOLINFO toolInfo; - - if (!hwndTool || !hDlg || !pText) - return FALSE; - - hwndTip = CreateWindowExW(0, TOOLTIPS_CLASS, NULL, - WS_POPUP |TTS_ALWAYSTIP | TTS_BALLOON, - CW_USEDEFAULT, CW_USEDEFAULT, - CW_USEDEFAULT, CW_USEDEFAULT, - hDlg, NULL, - GetModuleHandle(NULL), NULL); - if (!hwndTip) - return FALSE; - - ZeroMemory(&toolInfo, sizeof(TOOLINFO)); - toolInfo.cbSize = sizeof(toolInfo); - toolInfo.hwnd = hDlg; - toolInfo.uFlags = TTF_IDISHWND | TTF_SUBCLASS; - toolInfo.uId = (UINT_PTR)hwndTool; - toolInfo.lpszText = pText; - SendMessage(hwndTip, TTM_ADDTOOL, 0, (LPARAM)&toolInfo); - - return TRUE; -} - -BOOL -SetupControls (HWND hwnd) -{ - TV_INSERTSTRUCTW Insert = {0}; - HIMAGELIST hImageList; - HINSTANCE hInstance = GetModuleHandle(NULL); - WCHAR Cats[MAX_STRING_LENGHT], Apps[MAX_STRING_LENGHT]; - WCHAR Tooltip1[MAX_STRING_LENGHT], Tooltip2[MAX_STRING_LENGHT], Tooltip3[MAX_STRING_LENGHT]; - char Buf[MAX_PATH]; - - // Getting downloader.xml path - if(!GetSystemDirectoryA(Buf,sizeof(Buf))) return FALSE; - strcat(Buf, "\\downloader.xml"); - - // Parse the XML file - if (!ProcessXML(Buf, &Root)) - return FALSE; - - LoadStringW(hInstance, IDS_CATS_TITLE, Cats, MAX_STRING_LENGHT); - LoadStringW(hInstance, IDS_APPS_TITLE, Apps, MAX_STRING_LENGHT); - - // Set up the controls - hCategories = CreateWindowExW(0, WC_TREEVIEWW, Cats, - WS_CHILD|WS_VISIBLE|WS_BORDER|TVS_HASLINES|TVS_LINESATROOT|TVS_HASBUTTONS|TVS_SHOWSELALWAYS, - 0, 0, 0, 0, hwnd, NULL, hInstance, NULL); - - hApps = CreateWindowExW(0, WC_TREEVIEWW, Apps, - WS_CHILD|WS_VISIBLE|WS_BORDER|TVS_HASLINES|TVS_LINESATROOT|TVS_HASBUTTONS|TVS_SHOWSELALWAYS, - 0, 0, 0, 0, hwnd, NULL, hInstance, NULL); - - hLogo = LoadBitmap(GetModuleHandle(NULL), - MAKEINTRESOURCE(IDB_LOGO)); - hUnderline = LoadBitmap(GetModuleHandle(NULL), - MAKEINTRESOURCE(IDB_UNDERLINE)); - - hHelpButton = CreateWindowW(L"Button", L"", - WS_CHILD | WS_VISIBLE | BS_ICON, - 550, 10, 40, 40, - hwnd, 0, hInstance, NULL); - LoadString(hInstance, TTT_HELPBUTTON, Tooltip1, MAX_STRING_LENGHT); - CreateToolTip(hHelpButton, hwnd, Tooltip1); - - hUpdateButton = CreateWindowW(L"Button", L"", - WS_CHILD | WS_VISIBLE | BS_ICON, - 450, 10, 40, 40, - hwnd, 0, hInstance, NULL); - LoadString(hInstance, TTT_UPDATEBUTTON, Tooltip2, MAX_STRING_LENGHT); - CreateToolTip(hUpdateButton, hwnd, Tooltip2); - - hProfButton = CreateWindowW(L"Button", L"", - WS_CHILD | WS_VISIBLE | BS_ICON, - 500, 10, 40, 40, - hwnd, 0, hInstance, NULL); - LoadString(hInstance, TTT_PROFBUTTON, Tooltip3, MAX_STRING_LENGHT); - CreateToolTip(hProfButton, hwnd, Tooltip3); - - hDownloadButton = CreateWindowW(L"Button", L"", - WS_CHILD | WS_VISIBLE | BS_BITMAP, - 330, 505, 140, 33, - hwnd, 0, hInstance, NULL); - - hUninstallButton = CreateWindowW(L"Button", L"", - WS_CHILD | WS_VISIBLE | BS_BITMAP, - 260, 505, 140, 33, - hwnd, 0, hInstance, NULL); - - SendMessageW(hProfButton, - BM_SETIMAGE, - (WPARAM)IMAGE_ICON, - (LPARAM)(HANDLE)LoadIcon(hInstance,MAKEINTRESOURCE(IDI_PROF))); - SendMessageW(hHelpButton, - BM_SETIMAGE, - (WPARAM)IMAGE_ICON, - (LPARAM)(HANDLE)LoadIcon(hInstance, MAKEINTRESOURCE(IDI_HELP))); - SendMessageW(hUpdateButton, - BM_SETIMAGE, - (WPARAM)IMAGE_ICON, - (LPARAM)(HANDLE)LoadIcon(hInstance, MAKEINTRESOURCE(IDI_UPDATE))); - SendMessageW(hDownloadButton, - BM_SETIMAGE, - (WPARAM)IMAGE_BITMAP, - (LPARAM)(HANDLE)LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_DOWNLOAD))); - SendMessageW(hUninstallButton, - BM_SETIMAGE, - (WPARAM)IMAGE_BITMAP, - (LPARAM)(HANDLE)LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_UNINSTALL))); - ShowWindow(hUninstallButton, SW_HIDE); - - // Set deflaut entry for hApps - Insert.item.mask = TVIF_TEXT|TVIF_IMAGE; - Insert.item.pszText = Strings[IDS_CHOOSE_CATEGORY]; - Insert.item.cchTextMax = lstrlenW(Strings[IDS_CHOOSE_CATEGORY]); - Insert.item.iImage = 0; - SendMessage(hApps, TVM_INSERTITEM, 0, (LPARAM)&Insert); - - // Create Tree Icons - hImageList = ImageList_Create(16, 16, ILC_COLORDDB, 1, 1); - SendMessageW(hCategories, TVM_SETIMAGELIST, TVSIL_NORMAL, (LPARAM)(HIMAGELIST)hImageList); - SendMessageW(hApps, TVM_SETIMAGELIST, TVSIL_NORMAL, (LPARAM)(HIMAGELIST)hImageList); - - ImageList_Add(hImageList, - LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_0)), NULL); - ImageList_Add(hImageList, - LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_1)), NULL); - ImageList_Add(hImageList, - LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_2)), NULL); - ImageList_Add(hImageList, - LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_3)), NULL); - ImageList_Add(hImageList, - LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_4)), NULL); - ImageList_Add(hImageList, - LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_5)), NULL); - ImageList_Add(hImageList, - LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_6)), NULL); - ImageList_Add(hImageList, - LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_7)), NULL); - ImageList_Add(hImageList, - LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_8)), NULL); - ImageList_Add(hImageList, - LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_9)), NULL); - ImageList_Add(hImageList, - LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_10)), NULL); - ImageList_Add(hImageList, - LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_11)), NULL); - ImageList_Add(hImageList, - LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_12)), NULL); - ImageList_Add(hImageList, - LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_13)), NULL); - - // Fill the TreeViews - AddItems (hCategories, Root.Children, NULL); - - return TRUE; -} - -static void -ResizeControl (HWND hwnd, int x1, int y1, int x2, int y2) -{ - // Make resizing a little easier - MoveWindow(hwnd, x1, y1, x2-x1, y2-y1, TRUE); -} - -static void -DrawBitmap (HDC hdc, int x, int y, HBITMAP hBmp) -{ - BITMAP bm; - HDC hdcMem = CreateCompatibleDC(hdc); - - SelectObject(hdcMem, hBmp); - GetObject(hBmp, sizeof(bm), &bm); - TransparentBlt(hdc, x, y, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, 0xFFFFFF); - - DeleteDC(hdcMem); -} - -static void -DrawDescription (HDC hdc, RECT DescriptionRect) -{ - int i; - HFONT Font; - RECT Rect = {DescriptionRect.left+5, DescriptionRect.top+3, DescriptionRect.right-2, DescriptionRect.top+22}; - - // Backgroud - Rectangle(hdc, DescriptionRect.left, DescriptionRect.top, DescriptionRect.right, DescriptionRect.bottom); - - // Underline - for (i=DescriptionRect.left+1;iRegName, L"")) { - if(getUninstaller(App->RegName, Uninstaller)) { - return TRUE; - } - } - return FALSE; -} - -struct Application* GetDependency(const WCHAR* Dependency) -{ - struct Category* Category = Root.Children; - - while (Category->Next) - { - while (Category->Apps) - { - if(StrCmpW(Category->Apps->RegName, Dependency) == 0) - return Category->Apps; - Category->Apps = Category->Apps->Next; - } - Category = Category->Next; - } - return NULL; -} - -LRESULT CALLBACK -WndProc (HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) -{ - static RECT DescriptionRect; - struct Application* AppToInstall; - WCHAR InstallDep[260]; - WCHAR InstallDepBuffer[260]; - WCHAR Title[260]; - - switch (Message) - { - case WM_CREATE: - { - if(!SetupControls(hwnd)) - return -1; - ShowMessage(Strings[IDS_WELCOME_TITLE], Strings[IDS_WELCOME]); - } - break; - - case WM_PAINT: - { - PAINTSTRUCT ps; - HDC hdc = BeginPaint(hwnd, &ps); - HDC BackbufferHdc = CreateCompatibleDC(hdc); - HBITMAP BackbufferBmp = CreateCompatibleBitmap(hdc, ps.rcPaint.right, ps.rcPaint.bottom); - SelectObject(BackbufferHdc, BackbufferBmp); - - FillRect(BackbufferHdc, &ps.rcPaint, CreateSolidBrush(RGB(235,235,235))); - DrawBitmap(BackbufferHdc, 10, 12, hLogo); - DrawDescription(BackbufferHdc, DescriptionRect); - - BitBlt(hdc, 0, 0, ps.rcPaint.right, ps.rcPaint.bottom, BackbufferHdc, 0, 0, SRCCOPY); - DeleteObject(BackbufferBmp); - DeleteDC(BackbufferHdc); - EndPaint(hwnd, &ps); - } - break; - - case WM_COMMAND: - { - if(HIWORD(wParam) == BN_CLICKED) - { - if (lParam == (LPARAM)hProfButton) - { - DialogBox(GetModuleHandle(NULL), - MAKEINTRESOURCE(IDD_PROF), - hwnd, - ProfDlgProc); - } - if (lParam == (LPARAM)hDownloadButton) - { - if(SelectedApplication) - { - /* install dependencies */ - if(StrCmpW(SelectedApplication->Depends, L"")) - { - AppToInstall = SelectedApplication; - SelectedApplication = GetDependency(SelectedApplication->Depends); - if (SelectedApplication) - if (!IsApplicationInstalled(SelectedApplication)) - { - LoadString(GetModuleHandle(NULL), IDS_INSTALL_DEP, InstallDep, sizeof(InstallDep) / sizeof(WCHAR)); - LoadString(GetModuleHandle(NULL), IDS_WINDOW_TITLE, Title, sizeof(Title) / sizeof(WCHAR)); - _snwprintf(InstallDepBuffer, sizeof(InstallDepBuffer) / sizeof(WCHAR), InstallDep, SelectedApplication->Name, AppToInstall->Name, SelectedApplication->Name); - if (MessageBox(hwnd, InstallDepBuffer, Title, MB_YESNO | MB_ICONINFORMATION) == IDYES) - { - DialogBoxW(GetModuleHandle(NULL), MAKEINTRESOURCEW(IDD_DOWNLOAD), 0, DownloadProc); - } - } - SelectedApplication = AppToInstall; - } - - /* download and install the app */ - DialogBoxW(GetModuleHandle(NULL), MAKEINTRESOURCEW(IDD_DOWNLOAD), 0, DownloadProc); - - /* install req. hacks to get it working */ - if(StrCmpW(SelectedApplication->PostInstallAction, L"")) - { - AppToInstall = SelectedApplication; - CopyMemory(SelectedApplication->Location, SelectedApplication->PostInstallAction, sizeof(SelectedApplication->Location)); - DialogBoxW(GetModuleHandle(NULL), MAKEINTRESOURCEW(IDD_DOWNLOAD), 0, DownloadProc); - SelectedApplication = AppToInstall; - } - } - else - ShowMessage(Strings[IDS_NO_APP_TITLE], Strings[IDS_NO_APP]); - } - else if (lParam == (LPARAM)hUninstallButton) - { - if(SelectedApplication) - { - WCHAR Uninstaller[200]; - if(StrCmpW(SelectedApplication->RegName, L"")) { - if(getUninstaller(SelectedApplication->RegName, Uninstaller)) - startUninstaller(Uninstaller); - } - } - } - else if (lParam == (LPARAM)hUpdateButton) - { - ShowMessage(Strings[IDS_UPDATE_TITLE], Strings[IDS_UPDATE]); - } - else if (lParam == (LPARAM)hHelpButton) - { - ShowMessage(Strings[IDS_HELP_TITLE], Strings[IDS_HELP]); - } - } - } - break; - - case WM_NOTIFY: - { - LPNMHDR data = (LPNMHDR)lParam; - WCHAR Uninstaller[200]; - - if(data->code == TVN_SELCHANGED) - { - BOOL bShowUninstaller = FALSE; - if(data->hwndFrom == hCategories) - { - struct Category* Category = (struct Category*) ((LPNMTREEVIEW)lParam)->itemNew.lParam; - CategoryChoosen (hApps, Category); - } - else if(data->hwndFrom == hApps) - { - SelectedApplication = (struct Application*) ((LPNMTREEVIEW)lParam)->itemNew.lParam; - if(SelectedApplication) - { - ApplicationText[0]=L'\0'; - if(StrCmpW(SelectedApplication->Version, L"")) { - StrCatW(ApplicationText, Strings[IDS_VERSION]); - StrCatW(ApplicationText, SelectedApplication->Version); - StrCatW(ApplicationText, L"\n"); - } - if(StrCmpW(SelectedApplication->Licence, L"")) { - StrCatW(ApplicationText, Strings[IDS_LICENCE]); - StrCatW(ApplicationText, SelectedApplication->Licence); - StrCatW(ApplicationText, L"\n"); - } - if(StrCmpW(SelectedApplication->Maintainer, L"")) { - StrCatW(ApplicationText, Strings[IDS_MAINTAINER]); - StrCatW(ApplicationText, SelectedApplication->Maintainer); - StrCatW(ApplicationText, L"\n"); - } - if(StrCmpW(SelectedApplication->Licence, L"") || StrCmpW(SelectedApplication->Version, L"") || StrCmpW(SelectedApplication->Maintainer, L"")) - StrCatW(ApplicationText, L"\n"); - StrCatW(ApplicationText, SelectedApplication->Description); - ShowMessage(SelectedApplication->Name, ApplicationText); - if(StrCmpW(SelectedApplication->RegName, L"")) { - if(getUninstaller(SelectedApplication->RegName, Uninstaller)) { - bShowUninstaller = TRUE; - } - } - } - } - if (bShowUninstaller) - showUninstaller(); - else - hideUninstaller(); - } - } - break; - - case WM_SIZING: - { - LPRECT pRect = (LPRECT)lParam; - if (pRect->right-pRect->left < 520) - pRect->right = pRect->left + 520; - - if (pRect->bottom-pRect->top < 300) - pRect->bottom = pRect->top + 300; - } - break; - - case WM_SIZE: - { - int Split_Hozizontal = (HIWORD(lParam)-(45+60))/2 + 60; - int Split_Vertical = 200; - RECT Rect; - - ResizeControl(hCategories, 10, 60, Split_Vertical, HIWORD(lParam)-10); - ResizeControl(hApps, Split_Vertical+5, 60, LOWORD(lParam)-10, Split_Hozizontal); - SetRect(&Rect, Split_Vertical+5, Split_Hozizontal+5, LOWORD(lParam)-10, HIWORD(lParam)-50); - DescriptionRect = Rect; - - MoveWindow(hHelpButton, LOWORD(lParam)-50, 10, 40, 40, TRUE); - MoveWindow(hUpdateButton, LOWORD(lParam)-150, 10, 40, 40, TRUE); - MoveWindow(hProfButton, LOWORD(lParam)-100, 10, 40, 40, TRUE); - if(IsWindowVisible(hUninstallButton)) - MoveWindow(hDownloadButton, (Split_Vertical+LOWORD(lParam))/2, HIWORD(lParam)-45, 140, 35, TRUE); - else - MoveWindow(hDownloadButton, (Split_Vertical+LOWORD(lParam))/2-70, HIWORD(lParam)-45, 140, 35, TRUE); - MoveWindow(hUninstallButton, (Split_Vertical+LOWORD(lParam))/2-140, HIWORD(lParam)-45, 140, 35, TRUE); - } - break; - - case WM_DESTROY: - { - DeleteObject(hLogo); - if(Root.Children) - FreeTree(Root.Children); - PostQuitMessage(0); - return 0; - } - break; - } - - return DefWindowProc (hwnd, Message, wParam, lParam); -} - -INT WINAPI -wWinMain (HINSTANCE hInstance, - HINSTANCE hPrevInst, - LPTSTR lpCmdLine, - INT nCmdShow) -{ - int i; - WNDCLASSEXW WndClass = {0}; - MSG msg; - - InitCommonControls(); - - // Load strings - for(i=0; i -#include - -int main() -{ - - HKEY hKey; - DWORD dwVal = 1; - DWORD dwSize = MAX_PATH; - DWORD lpdwDisposition = 0; - CHAR szBuf[MAX_PATH]; - - printf("%s", "Setting Diablo 2 commandline parameters to -w -glide..."); - - if (RegCreateKeyExA (HKEY_CURRENT_USER, - "SOFTWARE\\Blizzard Entertainment\\Diablo II Shareware", - 0, - NULL, - 0, - KEY_ALL_ACCESS, - NULL, - &hKey, - &lpdwDisposition)); - { - strcpy(szBuf, "-w -glide"); - - RegSetValueExA(hKey, "UseCmdLine", 0, REG_DWORD, (LPCSTR)&dwVal, sizeof(dwVal)); - RegSetValueExA(hKey, "CmdLine", 0, REG_SZ, (LPCSTR)szBuf, strlen(szBuf)+1); - - RegCloseKey(hKey); - printf("%s", "done."); - - } - - return 0; -} diff --git a/reactos/base/applications/downloader/resources.h b/reactos/base/applications/downloader/resources.h deleted file mode 100644 index 172ed9a4c1f..00000000000 --- a/reactos/base/applications/downloader/resources.h +++ /dev/null @@ -1,71 +0,0 @@ -/* Icons */ -#define IDI_MAIN 0x0 -#define IDI_UPDATE 5000 -#define IDI_HELP 5001 -#define IDI_PROF 5002 -/* Bitmaps */ -#define IDB_UNDERLINE 0x100 -#define IDB_LOGO 0x101 -#define IDB_DOWNLOAD 0x102 -#define IDB_UNINSTALL 0x103 -#define IDB_TREEVIEW_ICON_0 0x900 -#define IDB_TREEVIEW_ICON_1 0x901 -#define IDB_TREEVIEW_ICON_2 0x902 -#define IDB_TREEVIEW_ICON_3 0x903 -#define IDB_TREEVIEW_ICON_4 0x904 -#define IDB_TREEVIEW_ICON_5 0x905 -#define IDB_TREEVIEW_ICON_6 0x906 -#define IDB_TREEVIEW_ICON_7 0x907 -#define IDB_TREEVIEW_ICON_8 0x908 -#define IDB_TREEVIEW_ICON_9 0x909 -#define IDB_TREEVIEW_ICON_10 0x910 -#define IDB_TREEVIEW_ICON_11 0x911 -#define IDB_TREEVIEW_ICON_12 0x912 -#define IDB_TREEVIEW_ICON_13 0x913 -/* Dialogs */ -#define IDD_DOWNLOAD 0x100 -#define IDD_PROF 6000 -/* Controls */ -#define IDC_PROGRESS 0x1000 -#define IDC_STATUS 0x1001 -#define IDC_REMOVE 0x1002 -#define IDC_DOWNLOAD_FOLDER_EDIT 0x1003 -#define IDC_CHOOSE_BUTTON 0x1004 -#define IDC_UPDATE_SERVER_EDIT 0x1005 -#define IDC_DELINST_FILES_CHECKBOX 0x1006 -/* Strings */ -#define IDS_WINDOW_TITLE 0 -#define IDS_WELCOME_TITLE 1 -#define IDS_WELCOME 2 -#define IDS_NO_APP_TITLE 3 -#define IDS_NO_APP 4 -#define IDS_UPDATE_TITLE 5 -#define IDS_UPDATE 6 -#define IDS_HELP_TITLE 7 -#define IDS_HELP 8 -#define IDS_NO_APPS 9 -#define IDS_CHOOSE_APP 10 -#define IDS_CHOOSE_SUB 11 -#define IDS_CHOOSE_CATEGORY 12 -#define IDS_CHOOSE_BOTH 13 -#define IDS_XMLERROR_1 14 -#define IDS_XMLERROR_2 15 -#define IDS_DOWNLOAD_ERROR 16 -#define IDS_VERSION 17 -#define IDS_LICENCE 18 -#define IDS_MAINTAINER 19 -#define IDS_APPS_TITLE 20 -#define IDS_CATS_TITLE 21 -#define IDS_CHOOSE_FOLDER 22 -#define IDS_NOTCREATE_REGKEY 23 -#define IDS_DOWNLOAD_FOLDER 24 -#define IDS_UNABLECREATE_FOLDER 25 -#define IDS_UPDATE_URL 26 -#define IDS_INSTALL_DEP 27 -/* Tool tips */ -#define TTT_HELPBUTTON 50 -#define TTT_UPDATEBUTTON 51 -#define TTT_PROFBUTTON 52 -/* Other */ -#define STRING_COUNT 20 -#define MAX_STRING_LENGHT 0x100 diff --git a/reactos/base/applications/downloader/resources/0.bmp b/reactos/base/applications/downloader/resources/0.bmp deleted file mode 100644 index e31ccefe73705c02c8be8d33e3ce0fd0af4754e9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 822 zcmZ?rHDhJ~12Z700mK4O%*Y@C7H0s;ACiM$hyVk_e^g*QC1cKsji_Sycr3+Mik%_h zi)%jr_=Zm%Ob)2N`tmZHC3#A1!Iz)ifeGWJf$AHtugaW%5rfGX=wEry~qOX@E!Z@jvSZ+oJ^{xp-*^%b{P zIIk#CY72t94WgcHmLCYs@#k0)!o4PncXJ%y&LsXlDKh(W(l5=4+ubc*?+I}miuzf8 z>G#E^tZD+c=gaPK$}r5v1?c(A|t#N7Ee zcgL=6R%!`^`xiYts~opIIGulF=EO@I=UmxtF*!ACAxe0n#T?K(yC0uhedln?u_coA mUYPNPseb#z({XECk==l%2AK;q-)KU7_#%96KvqvMJp%yX)*;6L diff --git a/reactos/base/applications/downloader/resources/1.bmp b/reactos/base/applications/downloader/resources/1.bmp deleted file mode 100644 index b5d584bf20682e940a6727526d9d288ff20a00c8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 822 zcmZ?rHDhJ~12Z700mK4O%*Y@C7H0s;U+0BjhyVk_e-Kk^2F{4(>5<9AZqg0X-NxQx?s-Uy?Y-$dW5X&{rmSD zX0*5as4OpVJ~X@Yz!5 zzr8VVORdk|-lTiSHhy{g{Nc3==ML|E^5h9b{iiq2dqZ^h^(Jj?44D~kx-8%2!phdO z%bLzCZn%AD?eCx8ZXH^;uq@{D+m{gahZgs(tO&ZhfAQgk?Hiht_D-+9xT5*o;;Iv~ z@()cf+A*Q{$eilsMV{+Biy-P376l!elK1)blV9JzUf8;5-^84IJ7?V9GV$`N=4~xe z)8mY0#2EoS)gNI3QQs4+b8ddwÏKe_Yx)Ry-bx4t>I@#^}%B?TVyGwf$3noW;2 z1bV;2TM44R%TM*poPs+$=lpne=f{H+f1aNE`QXIq#Z8NH-R5UF%ucpklw}7}@1qP+ zKO@x%7&1p@SA2VL^8cr2|6gAI|N8o;+ecSdhAzo>Uta9FFw+j`o(bVb5cT`!bu2G* zKe@Q&&AlssKRy5d<;DNcFaCae|M1N2(+lhNOw2nttq2$|i!0(G>Ve_e6Qpx&R>{}5 z&)z+`{rla+|9^k~|M&0n%Lk`cOGV^Dq=(b9a!=37J3J|Eb(v33 pkk*046VVhyxIl+(>M5NRZ4L~IP9K#?F%~Q8(>}d^j#V*{f&hdJIMDzA diff --git a/reactos/base/applications/downloader/resources/10.bmp b/reactos/base/applications/downloader/resources/10.bmp deleted file mode 100644 index d0825e8fb7960913de3052c6650fc4bca54283e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 824 zcmbu6v1)@*7=>*+7drM4@&u)G_dZ9TK|&IO=&X_@QN$%78In=V5|XHmrC^kxi$)}a znF4tLp*`GNMA|f=^oM)7T)%Vv|6HG*A8!~^57=v1cVFv@xhMD6_#WNTMJ}*?{JVC$ z-3zJX@p#b;4A>+|w%aWZXCy^YW>$*QB6b{1>Sg+U9b=@@0)oS%h%5fZ;1@A!Pqay)BL)o@%Sr*2ll9ET?X0zFDw=v9YHtYBMC7;n{8fMX diff --git a/reactos/base/applications/downloader/resources/11.bmp b/reactos/base/applications/downloader/resources/11.bmp deleted file mode 100644 index 94bd89c385442d243bf695c5c9a7cee665c20942..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1080 zcmZvaTTByK7{^D~xQQlS*caafpNKCe-d1Bs3?{zSWK(FVwpEI(i6}yAFSH665o;3_ z6^v1lwulmpRuNDvakVv#LLl2R^~?K(x~ z=W>1*1p>h$sX|_I!dPgd`{`zyrdwOuTA!Ah&5kmwwMl2t-`TZCT0-)E$ET*HY97|t z+k4)=?%iH@B)F_h99ejI2bNqF&i-xQAFXJrj$X5vaUkp9Cta?=t<5!DRvI*$=Db8Z zCAJ6?>4~wXFmaAU>>Af`tRFRj#MqWh{AEso&*y_yp94o*D{3FqviXGtA$@*s0r8N? zq*XIBGrh|#VrGr2fM*F$6#vqImDY4T>>Ncxsu8i7-N?S?gnQ%-4(qiH;kkd7>!j&+ z)w3&O6~is)m>Ndo#{palG~=H(6Ef;5QFOZl@%ySkDf&T4yW#PULzSc9a8N>_aMeL& zmMuIp?Pl00YYw(zL;nfHb!oA==@{y|MzAfT2!Ce$4{Glq&yV}O-+1C7+bv5gE-9{M zS=RIHc{}Ruk8r_Ug-+)XBzf1dTG@asY&IrSRiAKS2(RkqsmP#Mp*8Z-?_`Po6P_N&fdd>8o_Qb^1I*sXp&0&DA)m)@whJw?-lvlXB7-VzKWiw6ZRCE+9 zb?QdL5vF~p)S~G{flXbaC@E%B+=t>#22#|&b6z*G&-{(B3XOf5@ zKF8R4n6Wp2M2KZ?f)K*=eY@5W57+`gkmfhKLKJnscI4InkYp5{XU7qYNJb3fAS0F$ zC6N^>cnpt~<~O*wmlJleK^zSDu2&SG?a8kHZcAob}WIvFBrv*GqFK>Nl7awl2LL0gn!uQt}_{?PVw zm|XaR0(%{ZAp@k2<)}_W*JwXFKRG~3PJ$FAgSM%*^qa@+aLkNgf3ti&hth7u#QY4% z-4qbj2~dlAOMk4b08?H!COorvH2fTjmleqA)QCMepw9-;q<~sWxAgOWi0Zh4MprjR z=00QEJBOU^GCUjWN3?-`Q+X<=O|z+A(O-j&P=^lGUIohT_TSm~>;BT?zixN_gwyd} Hadw11#L_|t diff --git a/reactos/base/applications/downloader/resources/13.bmp b/reactos/base/applications/downloader/resources/13.bmp deleted file mode 100644 index bfaa9c0e56849a76a9ef24e6eb9fdbf019d31092..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1080 zcma))OD_Xa6vv0y*@#bIX<;pP#NGyFVZ}G#8wgd?7oWhGPV2F-kf=vhQm=>vZIHAT zp%iJ_NlSGwolcK?E_X7m1~>WNbMBq{KfiNtrn{%3fup0H%&kOC->TzUNXBvX?di{_45 z_bKz3qnRJt+oflBj}B-&4WGfn@)87sK^o1z>KyxI{A@03@Ue!R%>u@1k9m!L#y^Ri z8T`NcXEn_Hmwevf|Mh;%PdGZ`N3Y@rzn0(Xu(nO|{1AD2H}7^Hlc;V6x8K?Q3yM;c zZ*$p4$a!5_@+tnn#@qhUVL5Vn4!3s+h+SV9_rFgjYw~SQzCijl2J)(f{iaf>3Vz?9 z1yK0yKayp+;#}`QzhbdiIzyol_nV}}1<*7N?vnSAd(J_rRDwB=2;&puqoipL^WTJi zwOE8`JO=4Z26SDgcNKkJMUaFpLGl#B(FebC~qAH%}h`iUVcQ)B_#-@87?p7p^Vcd3fp0LreFZIC$*%!982=-n;kf z*Ds(fR`ozFK=lt^yqU3X*W9fKuk2a=>h-Oziw{4xbV19PT^vun-6`ObDOhLr&*4BiBQ}d6` zt+}vy=Jxg^;ziD%gd{)tLxz4U~FtGDJeO7 z_H110f#Tue;Xudq_V%t`z1rK`TU}kfpr8Pc`fuO90kr^K-qh4&Z*Q-ts8~=^^z8X_ zJX(JJ`qkdv?&{_i8yCBAR08u^g!7!J~(Gw5;E>arfRmKr2q2I<cfbrqWHv%f~N&^5CH+7u= diff --git a/reactos/base/applications/downloader/resources/4.bmp b/reactos/base/applications/downloader/resources/4.bmp deleted file mode 100644 index 5df366dd321ba1f05bf24233aedd4fd2f2ee7a4c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 822 zcmbV}O-lk%6ow~S2Q9;2(5h9q3O{DXc4?NOq68ug5~3UNW73Ue{ehqmK?>X$1#WfS zZ)oGvtqVb1DfDh-$t)oK+!l}Zf;1AIE2?)7@@c6&G+ zP9_t}vN#c-TwV{06^jKr&~iK;)6H!zF+Q100)Po$DCGH^&*!7jh@ldRL_8h`BVZ;1 zrU%I9FNDwKEHaD5qSNWn%H@H%2|UjR0497UbFSX+7njXugg*=!YcqpbNSSE{Oe0|E zepC13^`H+6_z#5d_xrQijLRE_;l@6n&y6L|Zx?>KTu!G`kH-V^L)>b${>OhgSMK)R OeO{iQ{yy*HL-!pLj!icJ diff --git a/reactos/base/applications/downloader/resources/5.bmp b/reactos/base/applications/downloader/resources/5.bmp deleted file mode 100644 index fd5099eded63601871b9b7fdc3fa5a771ebf6696..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 822 zcmbV}TWHf@6vs2x;bjQQKsJU7>cf20!BBiqhTx0N3)_RT7a59z;EQ|kLGT8G1DOmI z?2vYww{^A(8(x@}xx}v5>9%(3Elrj-iOJd|?YA~*)9KkFbIdnC{@>x`e}3mAU%uv( zO_kWnYJ%7Rd+VQFfz__~7}RIC7~3!~?AQM;2ffhfn5ci{+T2f6Sa48vA5r%lZ?sR0 z(BitOO~aFz1wTJF=Mu8ARw^$ofgpiLFrjp4II!As?BfhL@ob@oNk2_xEUff`mu-UL z5R`W-5lR5GI%ka*la*kQ+RsU!(z$!2&>7{9_{eH!@Wgk@Obc!~?^f~vm@K%#LoYZF zXb~Ho-c5ud{*?o-7@fYK5P$@1mG7cO@J(N4_PgU7oxx4c5D1d0w*;6_TF2jr^Lt#e z?L_2am}?8Bj!!WM19XEsUi01yX3cnb+t=k&8}lozxS5qNMffYxpY37pbcj6@;!cIw z=4s}DpWf%A_Ik)&6Y;hD0I%GdPj{u{ZdU2$lrC1jla#I}(pSlaj+k(GDtYt=17nT( zwS%5Vq}an}ts?Rx&7R3y7Zx82==QwSGMRWLqH{5^%}?#Lc@4gUh}I8z@tkUx3Y4aQ z&S`c<8<5n8Y_@fZ9z)tSMyj)UI(-R)PcCY31vi5!f4(S`${$c^1nF;brQVEsc9ME2 zsT~2Ts*eE7;2}Pl0ICJQdNZ^4K*gGx zAOvIpU4^E;y}cbM2oE0s%K1H*WOw^Z*ScQa#*iBGm)k1_2QDFdjM$ls$a(2#_Qa H0n;-8-_=#w diff --git a/reactos/base/applications/downloader/resources/7.bmp b/reactos/base/applications/downloader/resources/7.bmp deleted file mode 100644 index 1c8007b117d1675bdd79c617728a92a080dab064..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 822 zcmaiu%}T>i5QQTy-3V@6y7US904@bzMqEg-E2)*J3zcp}i$4+ZCvMW(RB6RDlq!PS zL|j-AS_P|V5(qXB2ztoKC8Pl_bBDPz-#K?CrV@i(a1zMlxWj*UfEx|^9OffKbg98{ zPf9*BIY#k%r~dqRKvwqGVC{g1~OX6WnUQDQXQc+Xq%ow*v-S zA;=$7Fq)>9E0-vs^?jc{rA!j25b62Ukto)$Zx|dV`|CnchG$VO#X5thRWYTwe`xFp z0_yP2%$8usaV*>Jn&ziroR!YWnKC1(K=ZrTJ3Ki?;ks_C{f_0)VgJG~EFph3^*j$k z2GBIK%uABQnydh6+IE=72v0j`MkMHWz6|8Z0>IETEen}BqoA)NFaacq9fciY>t84K BaXbJ3 diff --git a/reactos/base/applications/downloader/resources/8.bmp b/reactos/base/applications/downloader/resources/8.bmp deleted file mode 100644 index e30064272fd41a97b138de957e3b50c225ecb587..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 822 zcmZ?rHDhJ~12Z700mK4O%*Y@C7H0s;U+0BjhyVk_e~Q8R2j3WC&H>T0_rC}l22=x7 zdEnlUgAYLrJX-$z`E%##2cVkeSAJ9;{Wbsk-z%?vhC#M zejk2>-4=-Az4v|^E_!dY_+$5(A2ToioO$WzjEg@owLlbax%s{S%oo>H@BP<*sy^~< z`o$m9E_|N~MCZO8dhi42Fkm=9yboj_c<@7Y#xtwMuX;~?@m=>mX6wf(=e_~aFTSWKw}~5 zApt(;+$YJ2kEAC*$>06XeZ_0V>Cb#tzs}wDE_K`6bvM2M6`#Hbbq`P%#0zuJeH80| z=)dY^-NE-7GoAu%l$h{n`q_^_#Sh=0#~nn=ymKF2mOM?{`bxa-zDV!=>1VJjhByqO rWykHWsheNOO}IDh^n0u(Llh%xIduQ)mYbgmDn{0V=0RjLNn!&4R40Oq diff --git a/reactos/base/applications/downloader/resources/9.bmp b/reactos/base/applications/downloader/resources/9.bmp deleted file mode 100644 index 1e28d936e2bd036696932e328b6b9954aa2f5a4e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 824 zcmbtQ&nts*82_@819Ef~N*XCm?+z}zVMGp+QC!u^a-cZSSZiZjb9iHG^KKzO=AuTE z8Z$1;i3hq2mUx#6f7(7Mv=PU zD)bH_xWNo6Bs5sDAfsapy>@sa{J0}bi7?@Etw4$yXbE~jUV0fBuMMkL3 z%gE)u3%q!6-v(Io2W!FTEZPQ9Zh~ZkZ3Y7l#18pBXPLr2^br<(3aPxAZLqsgC2>V& ze5aKN{P6e<7M-B@6*Tpsf0Dqj%=qFC>w~qFM2h>R;k3N&WUZ1=IXcI7@^`RS<%dD- J%s=&veF7ImWL^LO diff --git a/reactos/base/applications/downloader/resources/download.bmp b/reactos/base/applications/downloader/resources/download.bmp deleted file mode 100644 index 09ff0a35183eb3c856996e634aef9e4f5acff51c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13914 zcmeHL`%_g_6t)=?XGer7 zJ9qj9`g(eMI=YaHTP>|On{PBXHWgKtjosmRsvxcYT3usZJviV)3Jj3IV-_-tOuYbC zUs@B`LBsb4?+@G^xZRHpf}PUd+SaOR(KKGKt*y1)>)~`ZbaKp+yz=6@n%buN2Jj&T z21wn8y4{bt&>-)oQC&iOq3hS)?(OP9{88WBPi$ML3ftS4zp`xKy9ui`n&!5fx4?%K z7$8v?v5Bw^p>qFhrwHQqh4UG31Mw5kt%yCo*(&IQ{;-lwW^{uh5_qk;%@^z~TBe-TuF>XYjU zld6M|qsh%-PMrrLy40`5xz)5a3Gm{>e_x>g`9F5-SbIDB(BKelSC3#Kb}0B$rc42J z`m|}=z6k?IfB_Ryzppnie&FUU0uDrEj9~;EfmGZsq|4piO-xMSxr2j4;^{Nr@7)It zZcCOj{iI>Cl@%}mV<<4ekc^N7Fr+>)JTx@>&|2@}{oa~m7MB7hT?w?T4Y6w2YSp;a zqx1Osx?@xKxDVVDhE87(nKp$f(kY!D}D8*1+%bL(Ra0VfRCQ^qsIzoNMf=f2%f{!l6Dme1yf#8T4rOT z`{IVbww6}XfBfh#7-ADq*6?)XIhecy{}p}gclDxEA<-?VuNMZG7p|XB>W4Hi9BT$7RgC0`w zkr&X6&yZl^j}1Za9G;f6iz){^F0rHyY2v4YNt@{BBR?^7$-kWyV3=rx#Ko3c`-9#m z+KWG}++&vIqsU!rUa;Q0cmpyuq1<2B%KSmwT?*gXqIxrac}_!xF%}JZOAFX%^=eW= z%aw%!OdMF43qAobM7U7vkXG<%B6`rx4NX|O*k81{fY&$5b9h?P?q|zB10E|1XC)Q} z>N7tbwoqol;XNOv^QgPO*JkgEpES9FwI@HW*gZ2paD0}J*#%!k-dY7RRrpU+uYL36Abi1k56&&#3Al{Gbvg`GejcJ@FF@F_;Vj;699A`Q3}`{g9<(!1URF~f%j(3 z0v^F+Mwv(uG~?|)_0jn00FWDSiGgu82{25=2uT1#g7~pq^+nS54DFTk+AC?=%c`DA zw8cf=Iu}JPD2VtVKYT`3fSJnEB;_kzJLeIrQO7o?#WtnJHl`{YR5SN`B$Ooa3I((w zXK-bO2!{ya4c)K62Y^Z$(HNrO(@~Dw6!h>Ku+%XmqsSWe9d;AFRpBfnB=3^AUEs+O z!VW!XD5sc?y+f+dQxV32i0cG~*xkn5>v$iSDnkT5YonP*EkYX?u@H2sw#uzoxu_t@ zF>lA53t_XeLuO_KD9)~WHStTd$ogbOq>JgUg*1hx8&VFwA!q3D#aT>q5$dPDAAyfX zuZP$U%n%*rD0++oDKbu3Bcm)slD?lov5KC+xk<;J4E^Pfz{Y^vsG^PcKJ~EMpcM{~Bw^8I*U3 z_=m;rKp5#Q6+LKh;9lyv6d?KcdN8RH^0g66x|S0jQ?LwNoL!JOEc;CxH<32L1TGn} z3nVqz!up|e2afTo2!Nv#pFVKGgRK|vodG#gYcGFZ5{GiPFn`y)3*ob~Lf=W>JR{9- za`Ni`Dn|$lu4IUnAjm8%qe=*JG#a)fO-KSnyh4u7_g=xxVM$SpbN;URPjY0JzQsoE zZ=JGk+-Y5{8_7OGZNaflHw0XpF%)rTltd$mkC84(nvevD7@{04FNrRMk4O#FfvNBXWuFaahnrTEv-A5{)E2M!F% zrg|fCG%;z_$a92y0;)Ir-X-G9D2YZAA0u6oG$9EPF(jU&Nl9MMnj;Zgvgr9DAYSV% z&&oNH`1bXDVSlDsl%v$1s^spAiJj%Yc9i_mR`hdg{^6Us2X18V(`4Z7b<(#>jK6z7 zlXV$vOazdl@w=SSOn2(uXAL#U&veGvk}+}wRK#qVM0XYKC7lFS4^A)Nx diff --git a/reactos/base/applications/downloader/resources/help.ico b/reactos/base/applications/downloader/resources/help.ico deleted file mode 100644 index e0373ec8db852bb15805d4765705a5d9054763bd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9774 zcmeI1c~n$an!q1gK_MU|1&J*h0n?ex73MvTTK!7VOPgGLQ1Dj*02g>wAn_uVQMO^oqm`ka|Fd8aN_ z)V=Rp@4fH)-Lfn%tEm+lYVqFON^fpi|87~H|65tNR=VA?;)5;gX&pm* zfu{HA6=ySV?mu1)pL0_uSp%PMWfkP_vC?9@Se>4>TlraOR$`YnR$*bGwSLk-E4BCY z*73|_D>o(9+LJ!V%1@hQ#dQj`3JZ=~X`|n=3if1Km6erNZt_4YlmE}3+Hal8OSewt zq+5wSp0>)$imWnZWzLMTQu}qX@-tJc{i!3Yvh$~`oS7r6ti*S%Q&}kuM*aHf*9iO? zfq!TOMC5-`{v%BS%+=(PACuZ7psjyXd+XNrrvA2oCijkL641u(sK4xC_lyXz(QALa zg5q{0;2WWR-u<7-ixy@;pd;irMnf|%tf4)wFZFT)ET0GkRQ3hy#u-)OqfM(tf|N8#sgs8pe{@^DZ z-t-4BtZm)>+8?L}>ivEWyY`1TY`%5&wbBqj?&%LQ1_U@9ZRu}m4D=%|4o537-$EFCd(;aLJa_jeYcxk^|0QsXoM7wSN#(wqR z*FB(lpkH{<~`!05fZPHAQ76-Q0;|L*Gkj3f5Nwi6=4Cr5-QM27L2 z92w5PLprqS{B+t|~9Sap~NplV5(dA!TVy zxA@5LfxmD4uv$Ls5E9?D{nnYoi!Yw8z2&OCRdc^rX<@;(xuX)gJlXHrke{h#a%9-D zAw900J7FZdkZ^j}hW)FOb}t;gWA@Id7WM}0OcI&V(Qu6ZBs`uosb^M>Zl9rD@i z!G|}_ExUXUEj7-Yx%0

GtGLs7UJ49^toZsuBL}-t12%_R5<4ZqAesw$B)_bM|1w z?pZMWi`0>O7meDRI&#m#k3LTsh8DUm9Nb|Xapk7mR|Ue?jeV!4s^WHy>(HhJ8^*kW z{H=+-w@>enouB_b_R_`kmkTeL*TpZFk2|n*42pKoAC8LLnFCI4UxkWW)y@qQdn4+H zUL?Qv&!vTD5q=_f&AL%NGsnG&@t;opV8`DE5tA<#jwmWBx_b5MHFF(Gk3YC_B3e*^ z7Z|W@TK|GCHlw2K%7y7YpSeeVQe^n9z|bmqvKk9w^C`1MWW|FR|FJ?_H&-Sda- zTRa-U*RNkMHrKI?R_>9dl$-j#@{-Jhx`zCz@; zPLEC>-aTXVpFWxJ_Lju=No(GmA%yzCva#2$T)JL#x%gTUuWvq?b!@}5!)p@0S`mi} zq-Mw81~LtHFOI9NaXCw`P3`ed^)4hvgk_9>AK{n2IhYpHdCl-1Du3eJTa$WY6}Dj^ zp&%y6Je4)OVB7rDTjrg}oPi5prA^qk_+zp|7zrjJy>|8(E@Z~{L#$f`!8w|<3i`eSC?Usze6Cii1meV!6akWcSii)5$MSyffVhi`YSB{=(+jAl__1DV2KqM9>p z0P-tKuO>!%;*$^&if~@bqdP4h^vbHCUDl2K!^Uy{g)x}qP60xQ^ZER3)z#H5my5rs zIJI*PsbMW^@RR#u53??F{M*Q9DzekwV}JUH*Ov}>dF7A@rYI>UMA-@N;R3hk&Ha$2 zgcs-bXV;hu6%`dX4`s|^^1F@SJgL{lv474=>Z|sbTqP_X`4OR)PanblP4Rsf_kYoZ zsO!3sJ&g;xgttvID&`C!k7&7gIPcc2TX;dNE}c2b9Kg-2_;)crOa=~)jw|wI5+qZFoM3mhq zLAXX{!dq-9Ye)Pce?toLk8NL@)WwruChFR8@7{J*e}DYIg7=@ph2_z&l7+P&y+)K! zQCd>`?fy@9FB(UXw@r&Wy(^=(w$>xRi*lC z*Dl?1Rb`C-Yigh0Es1(*#o&&rV#I5>Tvk@bv?LnNit=h_1;Vl49iOv@c3}XPBRqXr zx2-b<6Nif8qNzQeatGg&g2>PvsgrP_@Z?tudOt^$NHl8!737+g#mq-MImK*(&tE>5 z6n(#C+CajH8Cbq@XylbMR@RIKf*oyBF&cCeU z)uY~YRo=wG&zDb`|K78Bv84Zt%LcuIBWPJ2+m#5AcRXT`LM%2L$(_j;dkZ(#I4jnS z>Gh-gzp97~+ngLj78rRnXZ3oUs)dA5k+iJX+z8_rZYKWJ@WmD z9qYLT-?z*hmeA#=p2Do<%~NBlZk95*=-aQelB0>$!ak~HalaQ(v^45vQp1bS%(PEu z4P&Y!yt?8>_Vn2LIse1>)PIv0(Qe702=;1JaAQ%yu`e@HSbD2R{BcSDmzG4moIdJ} z%}G)D8y8+ZdqT~wsb+aD8{9RiZo$@zy5EQRPN4~r;Tz+lbYC@E+;V>S7wwyp1~E7( zBJ_UJ?)QB{=P;6<+V7Q}ixLVBwf-Nynqs#e3abZ?)7sIrOi&#A7ti}|dDrh1 zlUve!X^l^i`S+o&CXDu{DF8g>`^Y2z2J#Gmc`~7#@1UMiCZ9fyU4YLGzPkYWWWzqO z&26@qxJQq@|COfGT@r9niMAdwR$x&ssmR3u=Lz(oQW31lRo z(H+>RiY4HLjyANmH|vHBwL>@NwzNlSKj+fewE~wWz)KYX(`|@Js1Im04{V^1Ku@>9 zr%L!~I2b#(Rr=0MVN3Tm%E=(mrl|WSjRta1sfR#X20$K@dRc{}7 zCGb@hfVK6>K%X`!^?8tD`n`Eb<^x1E;Fi%1a0$dElp8{^DwIt^Ng`mEP+|&YIPXJ+ zl2@pz1o*;^bH)z%O8~GM2rOS^KR~}1&$vxWdThx?H#{Z)lTeKaAR#cBPzxEI6puoc zE0lKvnF+igP>r!e$AD*^Shxg2b78|K^n2aU26PXD)ttbZ@I)7IO(;=}e#$-k?r;2~ z+!LrxU^Y*?C=}cRx*1!j1&s~ho4{|z1_(|-IH&6PG5ym!wh5$uD2C;XZfH)xIf3Vl z??8x9&zg8s91Bz@V4Xl;ra>_R+8H}E9vTPD1*9ebp0NSM6Bw^pb=_+NFp~=E)vDjX zo=}Vk6_ilC3czRNXiQ-~0s4$iuus4~(;z>AYXtTq4r4`a)cHX5YVrmFntZ~5wLoBM zWBqY2JmaS%2nynRwE%-c86;Gx0uKtnW9A%4XmSh`3REayp#X)ZL52dx32Z39p~-{J zOZd>tSqM=;M1c{7lCMH_*4aQs`zJ`zsk*5@gjz|c#N7HPzAXTb@k9MlzckkxZ`B7k z3g9S^qkxVk2JjIv`dDpP()doj=h5Hbzv_o3OgvRT zP$|^D0#*tIuxXH`fR=9kE5-|SS+8H$EQBc_rqK^%3Y3{$r=McvG8K{04{HkLqClJY zPyQ#o<%xfP0rv#v6rfX}PNSCsUqCj2JO%U=*we&E*QM?a@F)52BjAjHphiCsDp2U< zdi{~1HIS&$4~q(^U&0$t_fB^iur`JY+tDrlPS2PO)>iu~+vh zjUR+6Aga+1q@q8pre1$UXpQDx8>}i6$3g)v;Hm(7#&-2V=d#WLm96;&TLs(@kjA`g z9AH;7M|3|lxlitE?ALV!!W#X$#&~Wv=x^jdEGtye0t%WnsB1uT0MUxZKxG28ti$0Z z4sfkNJ*KHGu&n^MX6@Jc4&VxeD|0%eI`rVU*uEe0HCkDMl z_duA}Z3Amj=eODc_zLi4;-L8ee$9N@S1V)ETsE9TGjq{%k2^;;eumDH` z4ZCB&KA`&$v}p1G6Pq|_F7z3sdlFzQkfn)%&IRDu%sG8tY3y_l2iOEeHu`~Nfs*Uz zzph0{*$EN|tSrE?i2?X!<^jNL_5!s5W)`4Xpl0moOFW`@CT9q6+n~SXx>@f=H*wb( z>U;*Fjea2duJx~b5hPs!N(&Sxz_dWq0!pzKJGyNcfepj~rY6S~qHzYR1+F%_)qkCb z`aN)M;-!A8ZtzkdY!hD?oBi*pyY@d_2h4{>pmwds0N562+vGv#qV5N}9`u=@`;P88 zsz>LW&OOb&zU%+6w*cQJXW+N-8vqvw-1rWI*HT|Bs#|+?@A0pNIM|mxRj0S{ zJNw`;SltP%n^=MC*zl~01H>*MyNQL`0kxaB!tEw5`n*t`nrFA(&g>-`AwA5{ORx<_#;ARG&z^JU>+KsXr?jt0tDn4rdGHI#%z|d+!nVOa8S@j%@cL zXAbk2qsQ1UuF$GHjn84n;I4T(1|<)}dcVY`Uwp4Qr#NqZNA1Axo%*|H0PpP@|DKxn d5Wl6yd46xLyXQQ=sg~XQd#YuLITu0se*@w9I{g3u diff --git a/reactos/base/applications/downloader/resources/logo.bmp b/reactos/base/applications/downloader/resources/logo.bmp deleted file mode 100644 index 4f10e49d3ef89219dc40f7bec9a329fe1f587a66..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17414 zcmeHOYiyI}6=r|-XFvC6Q>RwdM#T^yf*@8|E4sGox{0Y>JE<*ItNmCjjaAyzYOU6F zy}*DpToRH1A&`VifW#1*G{lfNw+5ULCwA;FzQsIe=Pv)q(J47PIXMxHjz=QliHT4+90-L2!Jsb?81skx0qEnwFzmPsA9%taQFpmc z*8QF!uqeJkSaf^>y!yRk-Vx8}u-ok%8ge?F_Q64$!)~?NEjHVLl>|D(VYB0|(=j;g zbh%x_9`^`hkpUBcZ1<#27bkmhIuhtTUEQ$vUez1)ef zec>ldI`-6E#iIdx9j8e4ke`>PjNQD0Z@g7S!sA5tuybhnPR-}ec)1kcZ;Yoe@geB<6GJm3Y&v+r~n<8`h?ckn%PjEAt{z=753czAnbo99|y&s4?*)1$V< z9@(kE>mHuy-cc`J@9|1FSCv_NrVzM;Z+bz)i!}4yesB0LGT{7=EBMCuZ<*>Un`bTr z?%;doJfFZ;!-liloeyun(Be*hawU>++1(SZw#dtOXzu#4z(^z-x z*bzuayLPVTm)LHR%xd*%stWq7tLuBZ-~hL|94Lw#M0fa^$E>MlHQvEDJn-IxM>r@S z9vZ=U-ZUJ4zax}!*`W(pNm204WY7A&8JgepR8G3Q`KQ-F=d69gc;G;RB4qRPPo%TX z$&pF{%`2}xhYauhZL4Sp4U|?iLgzeC=oY!bpFKejvMH*9MI;qE`VxKc5yX>)lOw01 zLFz7jQ7%}FRq{@yHGh1`Fdg*ULFWDWbqS`UD(| zDJdU*{2n>rE&vr#R#47xAVf?8+<6Jn&i;w$e9gYUVRCJ00*ff_zS zupMdtQIleaxJAbN{O$0MP0A4PN4Ve$BW1=_#FvdwL_kHP7(US%x>zLLQWS<_$b#vl zl5iDE6_cPUOaL5EDsOItQzbA`FPIp1LnBnz$!@U51{e_w6SxV%y4EYgjAOTN)3Kdr%&NL4x< zwDp-kI<&Egan=DTAV`Q1{cvNT8L4l^H%HO&D;6ehO4e~uqY-xFGKe zg$4P(P-6;jK55Cgysowvbb7x%-@HY@6SoJ2QDB9UqUPz1iMBQANQGOZBO7!=kbuTV zW{xuORa}>hBJ>=^m57SyDZV$LT6{z-%^%#T4DLcqLb{lW%HYDdR4DWA?`;=O8-q_* zm@+Oeow4M1j4a>LD3+40bHz~7JA{R|1<+ai{^lrpoD(I;Kzkj)(F+cNi@Q`9GpDFi zERt@C&~w!M`@H|^98FaK8~ zt%d826lI2mnWMXW z<<|(J1a?}B24$WW_!b>4oDlV(5`^PvMdu9?QgYN!$>(a27Nu02pEE;I?(b@yL1V`gwO$V3TGymHZ&2* z&uj$JuA+B!hKz}%VqmAWX!ny5SIUN4I5x;gZj^`55>Tb6ipf(Xse0?!u4PXD3B89HKSgxzr-~6$I*ezE)7vHos(JFz< zaERanO{SA5p|PM5q2-t}q+)asNFdVwW4@e^AL^G6LX7eOqg--J ziVZUU$pjyJ{nzqZT<@y&wDe?jO55+|;uw^<_~zFcAVpDp0D=av2vTX+0y6U94M!tF zQ49^Dcy%Zgi#*VoZ=w@dUJE+;P%Jrceh|quAOv=15q8|AC~g)$aDZ?WCWd@)Wj87S zZZvR;Md8T>BZR|m^1Y?J^Ra!}s!n@kViHsH=TqHvQb^~WKI=%T?I{8GHMT^xEpf(n za|ljZ6IIrDl_h@Ck{W^&1M%YnGeaQ7DrV&75SU{}%<>VFTxOCFo8;2|lpHdqCZKgB z*)>CmH8MF@OgfgS$zhnwZHNkI)_ayY}28z&$B$U_DMryDINu?(U|eZC1x<@UeoH{=jsTd-^kH^1L%y>r9@53?|PGCe;`MN3zC| zzz|g1g$YO<191!ij)B`JLFyQYRf-dUlfWFSb0&KI$wv#cmj^tBm&_}6Xdc?$xN)!6 z>mTRh7y>9vGbw<85mbb~pg&@Vwr>5DGFH)=9Eee3d@8m!^VZu#xn{-5p8 zRP~Ns_T1*1i5Haxhv4=}F!Mri+Mdw+k~^CRANZtkO=0KS!^Ty`S6A-R;2lDN3-is7 zH1Vm14q+FML`C@h`j`&=5>%4D=)!!Xtj>Yab-SBdT~TNBMvpiCLBqgBSFCO@PEtP@ zuXo1l@T-Z^M71$+rq6puKT_Q@e6H7BXB=%bc`iv_t>kGP811l(b~$_ocgW_SbcPe| z==D+ghG#~+@(sOLeq?{wx(fUH3fr2425fPi)sqei^G(f&S8Qv%to^U;Y-%AL`t;T^ zZb@HsQGBD03%x_Cy;_|o2Ff8-{h@~LK%T3#sYcv(I8(mB^lwXRn_b6<8(zIVx; zTjkzx+_|<)TCwZmMZ@r{{p0C{qSHluAk7+he~szTFF`%&ivlHrPJ9Wt{rnbds=91{ zvZ$@kp9J5I=)a3}{uj%;SMJoXoM<;iqtWT<>94-}>iYHTvMdLK!B8j^kH>G^xbgMZ zUni5vNF?I(`9A%;H>X@$e{6953D<_I;ccxW>i&SL+M9dIy{^)}GOy|M6^FR=|A7vm zAtK64(9|Lqott>sUt7{FEddtUB^ZG@ z`G&_wb%re!I_r3f@?zcC*0W}j@0EEMSLQdb-lN@Irdz$QV|C%>HAT8LCEaTe=$}8) zpHphgDKq69m6&gw-t|)81MTRe>Ok(P(N%lek)P|xDocaFe0<|4ZhJLm{MPVa)W%vV zd`KVORMer`qs>i8^M<|J4F#>a``dH(f1xVAl3Suv9q3ja(yI>ls>%$iBmJs!NmVhR zsD~`>sSerZEIhyG9CVPF;rrbUpYdCmZ>kIbUfIy=dZwgxb4lB8N?Lzi()w(1>oY|y z&lI;lUDWbaQOhs)w>(j(-BhT3yg>UHWS8%UML|Kj zQc~zusZs)j&_W3W5<&|QiX^0vP*hei=ljjQ@4dVfUh+a4vSndO6dF$SmwiechR!?KUF)2a4Pv4y*D7)<}BO=;{`Z!l3-VF880TGtY(1=j!bipKU7x66_`Iz-~ zeU;rJo!snk6kv9H87RkUC--H(_)BS$F15r+IA_c$apGg`Gx`@KxI|v&JezYFf;i7} z9P7?tjunP*PAXfRS8Ks9t6rUFXG=KR)7h?}K10o^>07uQXqvTssQERaouf4!%iit# znjJ$2b~1YHF7&pRZ7=k0d%@b@R;*NQG1d;|QZv_YY2wr=Z5iidu2cJd2tlDU;%ujI z?tN#d>~?bITlvdscFUMw%jm)@+q!JU>uu}I*=NsKYoAHCZR<>$;@XE=$31WR7)@6w zydSL_j??PA&#mhrw5^Zx$}rpHEbV$*N35T=ZMlgHH@Q18pnZfh_kkRy0F%sw_Py=P z#d+5cwGN|UAGQ*k3S7}(RkM_z3nIbgk#s6#gqqa|7m+wF*L1e?MQV}W|04O=U2iFc zu*>uZrd6InoY%Q9hB-q$=Zduq=Z0d1PQY65%c@uX0jYm-p@H*)v6s#!^Kpz&&I|Ha zj*7coq1GWYBAM`S+wZ!e%}xAfUza^a_rK}d@4BI_`nL0Of7?swm$koWBimc1*^0HY zX;SOHc8na();CKoboY_nd1#>7+cvaBMhr$|-@AB5RG*A|BHTJ2D<{(%8GA1Db!Ng+E7OaSugWtu?#s!f9h4oN2tMQ|8BsWVEbTUgT zT>i4?`$cV2xPcitof;mCe|2{%aOdA zx-nhmY(FZ~wj7mJsTs2St244VHAn6q@}&gzoGL-D%#b^VtdKiDSR;20kC%rg?UaWj zljW(oX|m<`ImtTrFNxfdBOk}^ljN`RW#6fD^6t`oa(nnTS-9h<95|IH&qZ&O$%$FA>-cHemvKg(kK8ERPMnj?$Ii;eqh};3 zAeRC5K&BL;_;Md$&HEY(CfPerA4i1)E zZn;J7zWZ)@;DHC^(MKPZr=NaW!otF&Z{NN$c<^8uHENVZMn=lqxpQUt^5wE|<3`!N zd$$}ud|0xxv*p5t3zGl6%Cx8`iA#%<{H-%6up{y$(hr%4tVH%B`O>q;xC(-YS{*&nULw_RrE79MNem?p%NEajw8Hp@Gq~lHKcS8R$^t+?qAN|qj z&q03~`tj)RK>q;xC(&o};K}Cba|cbl9sLgIKZyS0==Vf_F#40xUy6RBr{+PwHTqr9 z4?}+>`b#`DkMu-;F#40xUy6Pr`W~7`mZ2Yy{tomHpnnp556#2%(i-W4gdro5C7j29 zUwEc^k?^e3lIl-9=?YIh`LwIos{Z$XxP|{K-2cCSbqjwh-2a!y+`{99`~UQ3xA3TQ ze-UG>4cnmVfA}9OJoM1Rghw9vqm=-K-~ala4!`Nxsq?+Rz3=|}A9(P0>=LQozWv?B z_IK%G_TPHjFGGKIyY&EY2chkqceQI~a;n}uIHU!)aLZP$+x+|&H{5vB&9_(uNOk{u z^#cML1U9^`QBdRSn>4kwjY-vgYFtyZX06(_e|Bx1y1st4wsoLL70jM19?aNLTuPfe zG5gHiiIH#yAE(55HGg7{W1Zc`uF}S_ukycd|{hl2wO?pg}JNwO&cJI!To-y&(7&KtPHt9KagZMu)TH+37OYa#Q zWbU4PnU#Vh=gCYYdRHF%^5oU&8|0n2Tjc)1^JP9dF}w1Mj8V?<$$e~^m3&(68#GV+ z$p6);>*e#k`Le*0JXw&MC;b^yFK1ke-1b$~xa6VZts0lE{J7*{*cM&JI2O-1wu5o( z0OQ!nQpT~z-21}E=`>xP{-b~Xi|LQ)$(_OU=+0i=boCFJ?ca5Ah2NX)`+2N#ga@mO zd+yeH$4(}6?tJgP_x|>`_f@ZM`uaQQh$N$nl-2I4{2d~ z{_4Jd{`KhZo!xzPM<-v)>g26~#jVJa-MV?y39q#ISG%7Lui;jXTc2zC`vxyhle%4_ zq)xX;sngX+l=ybz9iZ2AY4Yk!=`nwg3|xCc2E-nf@YrKAH2$P~wBe+TO~{l<+fK>U zo!K%cIae0$&65=e@+FRE?9Io{%O;-HUx?fweqqzaulrP~+ap>UhE0_>=IoTuww{!i z=ch{WYcnPI^%>IqwHeZg@`7HSEkV8KOXEI^leK$JTTSd1H<=3X75E!*)rh$*Hnz zPo~^8cDFPex*dCBB(T>s>9Zh7K2JU+!#8Hi`0cqeVN0frOE@WGHl36SEGKWvkeD5r zGBfFv%-fwM3sbUWS!%Yd+@B+>4;aanJ*U30-b)&X$J36{avk-!_rovc-Vc^bgRp7x zaa=m@3cR0eJSn3#Wysjg88SYBF>FhQOhTfzXGnBnrc9%p89Ncmnz8egtk|DR`svc( zwfR!Fo5^>E_+$6qKHDH0j-Hb!#+NBc`7&u|o=n`4C!ZmoCgxF((=rYjyX~}$K}K&q zEuU=3m66DZgk1R;`Dk;l4BM0=A0kWkpOqk-H;=L*JsNhWMF)@ypIe<)*Lz~J?A7zed-$6bDGRe%9O3g&r7?(OU1uOjMRU5 zs?;+={zI1Um)7C2^46kM85Mt2LOAiU)f`C>REYx<+S88Qonnoyz}J| znZvQ!d(O%%WM;})nUQivrgOZ{l0#Cz+Z3tQ{&A_tHDB}ghqyt)t@z*a-saXL{CHQ_ z#ru>9@#_og^X2kIi&m^yv2x|gRk5+FSFc{PX4$f}afQcy7A;;FG_@k z?#JiNFA)~FAD=y^M40P-e8$WYVV3*xsnbe?>F&p)qDzDr_v4eNln9Zo<368$Hukf^ zFwqWwpY*AZtul7p_|n6Krp#BMGh}GQn|@PKx z=i8alNoPLYNNA;eKXW{%T>a(j>SwNY!dp3;cJr03FnS zSA~ByJ;;eClTEVqT54RC~?<}66n%_MhLhWF;(ZedDO~YF~gnMd(<|`7s z*Z1`hZY?GM79N7{Z6)k!;z7NIuU|=he-ELBm-@d9E}8#b9)f>K{g7XI2&L%zc~JjV zr;_>m)%OrOH7#y`H9tPMT{6@!s^6xZ!FdJ!rWGjIvOIB%G~o** zq10rxJG5=nCLq93fi_JV)@b9`(AIbS7EOln0X3cKlyFmMtDuHWtl;P8*QimWb|KB1 zUwdt{U(;wU2@L}{HLm87HXR#=hWZ6xZ$h(XJcl>C*?Jtmrdgd@zq;l*$t@J2Uv z3b?aXXuaV29SPMN*S)1~-NyXh!tc*+3=9lx>K7PzqiM#%(56<0&?dn~zhh9lmUXZF z+3l@=UH67Yzqk?o>snn`T%8iGZxtF`!%7eka7Vx$_NBzMU|?WKi@?Cbx;o3CNkf8b z-Dv_Jjoj4Rhuj!Y)EGySHf`GSF_=ITnWk#kuvM!L9a=TKqf~8^sPxO!X+hQU$Jhe) zOWNh*NUSF*ehN$@T*YM(+>INqCdkhv24HoGz#$+)AcV?{Ac#EY1MCRYQJE1`lIMJYGJ#|&GlF#ToDZL& zK}VGtK~G&OANE%umTYM<0mB7^t5^ikWySo&6OIV9iwL-@m`N@(z=HuN15E~)3@jN? zGLU3^s0T*|jEpb!fXIlz$Uu<+B6B6Qtzr{Y8WCKYSNVWNBf6|&1tc6mIB;;l;6T9v zf&&BR9)ZKTBKtwc0gM9|2L#WR4_2`bAP+nqa6Hg>fcfkQDi2T|m^>hPAo2j@fyV=m z2O1AB9#}m0OkA}C7YHm6RG=fDS7v|;1QZA+5J(`1KmdW@0f7U81}tWY`-vlSAc-In z0VIM)G;!^I0Es5X9|n;KAQ3zwa756EB`qnI6$<5v?y0KQ%WMHN*HT=r9R9~1M>`jP zt1r{aQWeTM47dgWt{xBFz1`6RopD`=td!ZUyLag5m)U*0ciiZg*-g85(CC-h9lJVW zl)a5Wkw7B3M?gtd%v-S6im7?PlRzigIRkkD@dV(>)s5PHsCx$r)Cr^$Kqry_r2 zkO~}Ck(itZq6$D2cq-sjps4^}p$|+8lolW@JA%|Ag4F`5MFgxxhX_;)q?WBuw*?vu zFc?@cB4{wcU|_+3f`J4B2u6nm3=9+)ATYZMAk6@pfinYUMg(YPVsZu@6F@U?X28sB zP5TP8*FFE1daahZvvTnt_I(x(_q8fiwZIi@0iYBhDF6~xAd=8VV0f?(NC$|Hxv6J~ zz&h**w!@A9JivDlL3r2^mC?Cw~x4 z0GcWgfk2fff6!Barz#METY1QzL*TT4X@TD2*K-8PRWbr|1KmX?WL2^tvIP?cB<%7d zm@)$+v;sIqS6N`zfUJR71Na8+4cHr~H^6IP-hjM;cmwbT-VL}LXg0uXVA+7Ofn)>7 z296CF8z?qFYzD(7+^W%b&USSG-hsOVb_ePX&>fgNAa@|{0NjDM18(PDC`h}Kg#xhy zVF$nt9HgD60oqvsv>;$Xu!6K9NI`&t-~{amSP-lrP(hG_00qG!0u=-)2v885ATU8t zfn(as=aOM}Ust9DzBKGayGWjzAniI0A44 z-w3=BbR!XbBd@oh8v$X0n=F>OT@KhwpqC&o0bYW;1a|3&y`}@{1knkg6FetyPSBj> z1C|pgC&)~Incy;kWrE5ibAv&>L;yMpaunbwxKUuEphf|Wf*JLYKS)u4qTobXvR}iiMT*0@R)9Sn|J(ge& zg16-wpr(Lr9npQ=wbQ!14G^~~RJFhrXaW1XLdo9?{}%rVj`x(J(7P*8>#8iPTA->0 zs#@Tu*8;U3c)9+I6Y6z~tmOFo_*xyF6rY-2wb-?P>UaBl3x}*pAHOx*6~}GOvg6n- zS;gX*Em_3T2}R5Zo zBb6SzEj&6r{-hs-GjD=#x9I2{S&z>+Q0ej6d1(=AkCVSQ=0FIHp1dvd;i%L~kN=pt zf8eU4Ufa_(n%S)fC+@EF_?MVH;VTYTz@7=4PIMZ(qtfFelXvx7n&z!N%qomsf2`ez zEtMW09G}>C(SGmki5j&oy#iBtWhUu7dJEs~ytSv!OOeB3(|+;(+Deb@hOO^8C%Mi` zQRTV6n7E*4U~nP&cW0$|q+XXF=?v-r9r<*PwkPFEHLvOGGvf}Qx%_#>a^|oh{aoAk z7uP8|z23JG$V0B;_2A5GfiHfNm;I|kyGQ|PBhVLa}pmOwHn*%^@w?N?7H>o z=ceq+o0OD4acBN#R^)5;1cM7Q7J4?4W^`{!&b8}wf1GfdobMgJ(zkmwbF%@j%n5vL z9#**jdk$<**}rLL%9;%cNvZpG?mf8s;Ng^mhm%qdY~8hI!}g>F zu^aDt@AD305<86Fb&nN4-<|o?jO38vyMiOOH+^rNaT8Eh;Nl5+WA>V~eC$a)`R&_Z z9{%;vK{ygrv@X~eo$dTOKT-+ ztl0I~q^-@FqW^HGZO>g}cP-zW)po*u>+v* zTbB07_>JyOguA)Mug$*xjd?BJT6q1Nd?{Gk@&aRTVJ$%dvU9NOI!9|-fFC zMDp{~5+`mt#utr%*FR^*zOMJixLT@S_h?Sv{Ug>6SeYJf$5rM_#K6_ZK8QQ<(fX64 zHuA|PbISHpF*~wm?#iB@oU>@}>E#FWSErqcPd~Rl{e1k9GfR^*fARJ_K6!W;s$3y8SRaOee`WUm$x1nyV#L&_CcAv_o9qXF)s;?O3Y33@OsurkffvOfL z(gOAux+?w;-zEP8{O^WX=jIvyS4dU3Vl7aOoSkyHgc+e)EZDI9_l0^>^E#puAi zQm9u7_e!BW70FtuEE zo4i~ZyRA6OfV8EswiMcyLfW!r?S6%~WlQ{Fg}tS)BozLZLf}#uT&3FWmc6y=EW^~L z0#d5o#mlJLzIrXdb7~R(*hT(Xg1fJ1cP^Rn9UX^+Gt9e7oSP5n;`!Y`Rq7!jNHyzM zr1PalP;@RQRAg*-jOkXf=6WvA*zFv%A)6KNN4y%F-Ns~B`QD7Z#m8J@zc*uR@iEn; z_h#&LA2Ufiz@)FBn6y7YU@L&Wro{ygo7$4c(jloV5!h^|%mUA)ZepA?Q&h%>;8!p0tD}Vx500B;oz=Bg~a0(AjA;Kw4 zIE4yljR}z96gHefhg(beMifR|0hG8O;KV76I7{HfsU^u7R-X?w?jqc{A0Wq>wlgxo zT!1XCG0L&ed918urS$0)<hXg*li_-uEECKmw4`g7F9wWa@0nhDNB62roay}l81{$WWf9LY)%h?7?N z&iotpm}BM#iv+*!k?l>n&>z2pJE;I})GW&@&?)s&0x3{oR+_vom@04dSN4+*GKW zKy;_BaFz#svxjMiy3bB&2!rzw6wZrqIM12$1&fn+Kjy$To^%ORPKC>!&oPKDIT(iUij3b9jRb}FCpzk%CX0D$N_>d!wwD-3mBnAix4=W#fm z7a@5nEKlm0tB^ch0@YLDdMad3t6b=w3g1&9d@77jh4QIzJ{8g@l4}XPPc?IJFh3Q_ zrUHifnzCKzzt94apS>`xDICxYNTA=t0##_B3J+9affh=y=?Ym>VS_4kP=ybw5JDA3 zsFgpQPz6GvutF7DsKN_Xh@lEI)G8asB>yb#(!u|Qm==&kb6|=708Lcki55TX^W!@fJ5Pu zDr8cHO{&mI6+Wp#C{-AxYR)yBQsyGhE3DE2Xr&6T^gP$xVeYvi=ew}9ORv>^G3sV` zreB!rm3F%T&-5FYbhFmYJ}oJB9|MSGgWpRr?JiwH)sd_94e(vXp>5k1D&D9kC zA+p?vn0dcuh?xU4bDm`d)8+>2V$%H*xf?O_TkWs1bf!Erw`iU-4F;zL;t^BAadXX> zdYX2>O=|hy3-5Ut#OK3Me9vArd4Bv}Skc3vML&ui42_$NTMSTGp^=Rz) z17gmuy>sAITi6b0)moZBuGVtP8g$Dc23G>>TA^JZ!IsX* z9f+BqHS_Q0-t-jATxJ6aZ1Hmt?HA!;D?H_^DyELGv=x@tzp%wT#u?kqwNno<*LYc> zri9$p$k-2W`>NV*+N#k0XdY9ozQ^>1rXMYj?asQ@Hul5wR#@IwRUmD)Y z`{A7{tn;fXkkS=ax^n)_^;6Mc*$+=$VX0qLfyAz`*e~DyuF)6G_YPR?S5+XrE3EfQ zu^%41!h*l50!dzB$zQhp%*S4YH?Oefuc|<*S6KCxV1Lv_c=na@t;m~iPLS{|d{PDP z-`d>pwdLu^deHJO!pm1!`BzmS?ek3}S)uKl{>Qe*UV0qIuI(E62kYAj;}*{zMid^u z>4!@d+Q*#ZDapvVE0~D75 z7JeG10cr%YyW%%MaU7s{4zL7TzT!MU@gCrM9>;-z;z2-hA)vSpP&^1&V%G5^pg0ov z4o?Deowhf6GNz7i_sQm&RPZOT5K3wm*Gd?h=2|oV=X)7m1%AM-fWq3hFyBzksn2P} zv4AB8|LtBkQ?KH6GxaKO-AuiT*A2G=ir)d{x;Yv6++^SSFMaAyd-sQ(dKT{ktBtK} zH-)^K1=+U%7X*3uAb7LRi<4U7h2Si12oygAVAuIJh`{n!d=XeUc4xf|p547}re2p* zH*?O6;H5xuQ=s@M_=fBM0c0q04*7v=^^*Iaid@*hd z6z>9x;{wGg09gEd#dm=v29uBb0$07tTQ_sgik~-gJ-T0$_z|$m#jOF~fB7EUE&6Lb z8+?sxg97Z&<-IV(GTiNlI^0DazQ)Ia;^aW_a_|lHQ2ZPyjt;>38@zw%Qjxlub5{Jk znR*%9ae|<|X7Av8dbHvP;aeObD4q~ZUv!o}-ONRl8mPmA_(b>yrw9s@U2%(`_(f10 zBPebWN(k-|6#oc{g9ODxg5n}U@sXf7Nl?5bC~guIKM9JX1jSQ=;wnM$m7q9FP`o85 z?h+J#35vG_m*6u&ahjlbO;Fq>D1H<8j%v|9QmkNqc1;wd?;#EO$tDyK*P#h~Lo)y?W zp!il$oGU2a6%_Xhihl*g!Ghvp!4iBdC{7j>FAIvB1;x*T^?ld3YxEyI8t!(GYyUO8 zE_{vK1*;A?UQj$Q6ySQHkPG49T;P8}Gcqz14-AS62E_-1;)FqQ!l1ZeQ2a0`ju;eA z42mlT#TSF(j6w0nz_;hEivI(}A%o(PL2=2T_+%)+2?F->ZF)$8;+Nq(jv1bJGp}5$ z+zTJzrr|t(8mv0tsX=kop!jMiQ3o70C>|RWmko-~2E}QE;+o1SuP#iZXo*NX` z4T|pu#d(9`EkSYL;IbbN4vGth0(>~Au^%rEiW`S>_;Ki0E`v)^!iPc(ejUEXv4d3y zTssut+o8an?_#aPOToi~;^IN^@t`<);QRkl#m$4_=RtAwpm=&vTs?}Lh%cstp~*^o*@+15Q=XI#W{rH9YS#rq4!J(u& zo^i^B2Q1U@k_y*QmwzxW?Bv;S7k$-kB!zxCm8Ef;wGTOf;9@N15X&RGkse&#;vr`J_9_cP?Kw+kE8K%spUA=UWNaFUrN34+bi3YWk9e~!mf+5i9m diff --git a/reactos/base/applications/downloader/resources/preferences.ico b/reactos/base/applications/downloader/resources/preferences.ico deleted file mode 100644 index c2b7757040741faffae408f091efdb7de5bf7762..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9774 zcmeI1c~sQb702InG$V_S3b+ti+;FKHO-y1;8cj5dTh!JyHOr}KVq;9LRgaqFII+O| zW?>dU1w|YTu8a{AqNu0?L5n-ejvKMD8ckagLBJ4hzxOwQgAAaFr_CR}Gk50Ad-vUY z-|~C&K5v9j2&D)P7Wixg}8t+XMM2P(q4#gKOy?E4rC;R+i}vg zl0Tepire{6qa@}G>mo8UGez|LNn+MeU*U++2>ZhEA}-M;G*gC&G<%{*j5dm|zy4Y* zS+Yc=MZYIP$M+J2X^G<8afgU|>ltB;juz3zP?4RRE2R0eM6TT^>>th&$tfwqo|q^! zb0-gRg9xMx<&c3FDj32)ivtl$Mr?thgm2D`vjX zOd2dKGx`e4q`o31CPt)6Z$fv5*pj?OSmwMeQXQ$HBr6#@gGCnd57L7XcrXIZj{p%h zuTWpx`d9T?H<{MzUk_EgDX%SRt?tsQhpK4>^`LgW`>Q%OG@$TNv~`xKJGSqv^6=== zz<`fZ=~ughsXKOV|5%VmZ&wcrziw@m18Xg+RXsbm5Aqn&quzqTFHqUFuDuZIjy?N! zZspOcW32+Jk$ik^M>L>szjj0F6u8>kd!S1-OtkCwNUeh0+Ph7IYNtYPbmC$6)vVC& zkzVbFc4FV&gYRg~k*NE2=&VwQaCKKV)lhgyrGDJg-_QF|m%aUVAB5=NDa13_-&5(f zH53(oO8;)b{=TkloO#8-!EF?%R=QPC_yqRp)5kl|uN!8?x3L8uZ)XbhR|fhB-)`MQ z8n{q&t*s99MzvrCFJBi8A3r~ZLeUi-`m~XI1_e)-C>325Xr}OoLT%T4y9We#-nPKi zP=J@(dan*00s=z3oPDc%=lX8Wk@NEG01dC(7V6s9Eh(>%fDRp8Jg|8sn%9r4mzQe* zTb9zfNQ(&a=YBV=3FA=39zS2|%-EdT@$x*4I^lBA-T%#r> z1(6ocTvEexN*B5B8k}kV|LN^vUFHmT26Uf;nf-XD@NwO(Gap$sYlwDi@cp&^#?VgE zgq|rYUW;2eZPU_eJ3pKPU-!|4G@-{HX?D7Gu4VR!71JKywrtwE*-ziSeaWb|u8fi* z3`;-ypmD3PvB4YOd-2@<#M4Qp?Mo+VW(?ELdS=J+-y0_OZmit6B*JPraq`5mW5=>j zXY0)ojTJE3ws)Q_Oj&*LOZ!(@DTzyGXr>Q~cp91^xWzNji|Bb1Kbb#98rQ>Z6BNRDPHs+7Q4xaQ zy?b{~PLAGWY)V->p-225pFX`Q^jQ4T>?G6b1yeLLpNjpGjl&tJH30q-kgS4Tu!o3igLw@e*yH2#CEm<1Wp^P}gz^6|{!YyUdMHs^V%p$mh> zl$W0en`h6SEh#CveED)r+*-@Z=;n<(YxNU*9a^>U$eKlaLtl-0cZ_D{@c2bj*S|eN zH=(u{h&;cb;GCQg`IReI)^A9#tcAz=Xm$T)?D>)gt$x&MuO*Bp&n4A~~ghJSGarNre z-Fs3^Q7ufUtHH*3!^Dux^?Y$joP=}d0U2{|1~ZJk+a(VD9Q79RG% z;-wJi0w$O}s_t8e~&>y~VU^Pb$_k%+@D3 zs^0;Mii;v5Z!g7oi}dBbUD-!7x5ckQzQvB1qa$r@NVNlDwc-?(uD#^J(| zk>2=GT4&bg9?Qr+v^P6*uOnq!ytO$O2-_0XU>iXRh6sa(>yxabM;hC=S@lJy4i_DF zsnQxw?*l8B*YXSJLq(=Z~G@0wEEg+GFVY3Po2d2gz>#;`%F#m z1_@DyO|j)&YeFG7q-L=28)|hLA^3E>n%EjZHv^q7B-(p z{6@U2rf|bg+-jP)|DYBlz{v2+;gn!`PBge{y^F+H$HI3gN*CepTzd~>%0p9DF^L*58Nro3A|$ZAm2r(<7@1}kbaOJ5Pt{*G{@}$;g}e~nZX{01VVyp zKfB?xD}?>9UK>bV?EIbk6a*A{9V}D<7$VRR0fz`YL>y0WN7c*F844Ky=>@5?*$H{R zjbhvEw>u;R!g`PT`uaXLYSgF~a1GNR-?>ZF%kw2Ckkp$%sdBIs0j3BvMF0^3PZ5BMKvXvuj`SZ5W%kE$-0l~_`bh;PZHI~M9e-T$ zFj<~7`u5e}owf{C(+u_vIwKsl<-P;Z2!uvJvAFOr*uvP_HBj6f= z*9gEyAT|QB5tywC(3aya27}22NHJFe-U#$YIARefNd5%DRRZCbx^?VQXq*t@D~;=( z0-7rW&JlQy0CWVRBft=W=?G9)1**$+jX`gT7?1OG71&Pp2ht$m9pMZ>I2Koe@M2ut zw3rPa+w&dZUO9M=0DJ`EBOo8fVK@Q$2-H^v>`P}ulF|4Q_Z#R(z$aO_-#En*_^%28 zxD9IcYrRG1wF=rXLC=E+zXuT3fCvdlNMJ&F96*HxEc^~!I2S+V6(BV_?>L(f z@URMexEJPlPy9&P((7Qj(nYutB^fqjERegHlm zfm43Ye^$c&_X>#eCXkZAlmw_GP$dB?30z6w1mZsPddIPq0GB`D$eNF5o%f~tlCW2Ii~=bXJ2p3D`;CP6Bum$WvZxV9#p6=Osy!ct5Ej*n6QT^FTxk8c#{>`8r9jem}gEfyZgJBS!u^WKa8c-_%TM67M z#{hCAplelVL@57`{;VV!3={D@UB`12?@)DR=-qS(7vVU+d0eq`LzPETTz`i%Z zj0~&yoWjDwI)jD3<2?(gDz9bs%X!{QIL~VxP)wj=0u~dvxI$;ty#O+H0FA4_#soMn z2OS&lH2{D?7+ABKpI`RrD*RmWeqOh)f|?1~Tp^hZ6WLE}ti}_3mIZdc1$ZXVGh&dA zV=Q#>CP~(5DITEo8L%_~ritgeP5{)A0O|?|0eA`AOQ7mo!0LEcn;Zi$>lEPn7U-IQ z*95*M#6fW;9iQKtO;}@>(SMAo`3KPUBvua7>jwk4{|Vy$2*}OMEyn=ruE8D?cc;Nv zJof-H0(}$ko50@$0IvaoUsE2p!Z7PI{~g`0l^axz6^6QtC8^*3c?NHPjdg!_e%E9V*skZfxT&@yQVzOp!;;- zeHr+^J_aB@@!X&dGr?UY{I)-f=b{`q{v$ts>>JQu4eCGKf&nG)KOX#Fh6@0~4L~*4 z=D*fj!Una_uD)7_esI5WAwakhAjCkp6R5zYzy;nb>J^*G;C^5c_Zc??m*R|}%p>=d z!u9&!p#K+fV{jFF<00G`yblA+FL#~RnY1s)nM}+J57IAe1o)o9fxkwD7|GnE&WU4f;xy cs{f&>R9Eo-sTzo)MpdIAHK}Ml`>ad<1)lHD<^TWy diff --git a/reactos/base/applications/downloader/resources/underline.bmp b/reactos/base/applications/downloader/resources/underline.bmp deleted file mode 100644 index 7facc72707b46d036a8062f874816c620a6661a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 170 zcmZw5F%Ci@5CqWi7B*UY0uNyCH9Uc*@(zSVLID*G6%7>?1tB3nfdGHyw{G%gCi{4P zaNM2hMo#3i`b-JD$@h9#4~jV_#u(_mqqT-@+mLfcj1eIOc<b(B_k8i572>Gtv~y& zeQ)1)ci;CrcJ&H7vghgFlYjQZuMB?g!tW=0-hh73p7(&EeFy!X5}_c6J!nb9H$|sn&c*k9)!I%vRbfA-?We zX@f(`*(t-_uWxVXsCSlc@Yv7I7{AD1c(>GCHcwwM86Z#g_CQ~@Oq3-NW{Cx;Ws3R9{Px4yjC0xPYSl2<{PzAgJ8LPn zt+(*NPft$&Jjf@1VTyWvBv_{iRLlHT62HM-AGy%Gzx!Nor>C&(ba(Tq&Ib23&dFxB zTSKKQr~CxF)TOfMcts&&v0%N0cg~VHUE#ZKK{{c5ldn% z&5`t~u<@Y~?Lg3oG*Bt=SBU&%0$&NwOVoK*(CW!+I^EGg?d1k>o89UvPSmhms)~sm z0f02YZrU5{J2p14VqJdp?Zch56x-R`5ySNR>4_!Qxrpl{Wc_gX*ie{O9x@^g9ufx* zi2S7jKQY&*r^AciN)_`uOfzI*heu=8$+`+xcIk=AB1jF9snlNHZ(>RMS>yK)A8qH5 zcbsp1W4cfBbBZj+$VoM{hzS*0HyEywhYm}k)v~m$^0WyGi=N;{B!U0X7%FEWe=NxI_{eY{1Jz+&Q?Ax*R0rkPA>&uLEisp?XX>Js*|Q%e#(%TG$0C>3PQ!ai)uyMpd^6ToG9jJ%ll&Z?OyfQ&T-1m)|PwL zmeF{vCrg=EgxwqT4Hf}KXVb?-MH3e6!^bJ>VWf_8Awg(}_r&w?)|+o4I+3HmfB;;Q zz&(6{y>Y}Pe0Dk@u`2?F9qC4Wl0la|GnPD~OPtm+=cnZNZ*fP#L3p?76=WV(yuP% zE?caivN&%p$jb)`(BZ*GM(o4KDeGZ-U9?SL+ro<*)SQ*&6`=d>@7~2Fr}UF(2tC@` zXs;<1Lm-Lf0w-}5drVkxBJeC_!XANY!GCNJN;}9AeMXl)GbX!#YvA6k?o|uNJR76x zj~eWw%6lUE`Q$!svRuT}3>9gWnX=x1)>{9@>hld%ehrn>&c@*Ss=$ikjkxD|<_tug zm62&9oSvEnbl@U7S{Ymhr>uw9(Fd7T0(@c2nh*VoI6`?m+~eSKwSoHinjRZ5~2y-~6rs)QfW%cTfAk|hFa zcUy3KeNannU=ur_v6|A}KyKk2XXb9iJ@jDfb>lX|I*k@W1}>u8hmTX%!|Un7Ed%FU zXmAKR-1hI^zn&y|gkbw5B_zV`gDr;71zPwJ$H<^_`}Z>G(eU0nK7?|F`i$9e_R@U& zszrQzC3Retq#1}GmKEqVm4=BHlR;>mr^`hYVLQ3IHN2}Sw7ov0r8c;^CcLdKrlaxT z#ng>>h~lz;)rGSN4;jbEEKXSu+e<=r;%RZ{1VdUcz4VeoCbySF6gYmNR6vq=kGRk~ zo|+JI3V5ACqm8TJpu=NuhP2$GX5ARZ@F8 zse*P2ua(r<6y8=J*2;k#L237PO58>q!(+6O$5{yDU;pg6NZqj{Q3D)5c1$YnhwMPs zhago7CV5LfA(m^B$H^v;%ohzORllMh87b z?QG*@*Wz5~!ffTF&b_(XvxR-WtuCyykVb5fHx zt)q_)CXC3q*7+`rDOxJbRV#eCjc$#Vu65<`?asZ13SFnTXx@X!!mQhYY41}RU!3pYcR1$I7 zPff6#3yjM*_T@0bCRESJ5gd0TQg5Z$XQ-Dv+#fdB*Su(KTbwJHP6Ik&R!O{ude6y) zXZyQ7#a(Aa?Wg%Ir+7^so%N6)7k0_#CHY75vp>#ae3X*#5hMO+dh$CNiJE!Sb3Mdk zv=PQx2*W0Vdjwvc;7NuzT;eL(xFk$be6Sh9&1@f-|BHcW#qwOU-dk+2>_f{=~d=I5*>?w4_7H zw1Y`82NRZc9u)X zj?rR$JDU7LpqJCzz8LbX#p2jo2XQ%IIkvfJ?j~l$RdBp%AD*e`@t2%(A#ZhMX?4X4 zZRG}PmX#Zp8_UoZmzRiUUS2XUSy5Y9vMyLHsLfj~^OnUYZP9G{Z=1W?)#7?7>zR`h zLU=ivFY+TYt(PjuW37E1WIv(OvquIXo(*seOU0;{+0{F)N9_VAmaVE-suOf-}S330T<__!zKK~f?;DTzT( zg7P4R@!XmrzmTaJ(+o^c{4q6&u)hnOvI2fr^DlL^JbLVeBK+>R_x_yCsFVGO|8wG$ l5dQCtSXWk0<>kB*9=P?d4X`D@Y;F3#U$NZ)cUJ&b;6FT6k{kd4 diff --git a/reactos/base/applications/downloader/resources/update.ico b/reactos/base/applications/downloader/resources/update.ico deleted file mode 100644 index 82b4a1f986a5704602079d57141cf59bb6c1bc1f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9774 zcmeI12~<@_nt%%g&7z1~n@)?`&y7W+lBjGF7l^1GJ=2}(ICEm!Nh6S`5seXzv|@`I zyVXXe4H}IoWWu;iTtJC?00|0F6fmO5qPVZ4Xwable03l1@z^|_^qI^#-TBY^xpiy# z|Ej<0-dkUxl$~m#I(JrFpHfLrDb-)8>ig$ZQgfw>$upOCR!PoEEoi5dtFD6%LUlVW zQ4Yq%{Ku{)?dn>jrUeA3xVShK9UZMQGBT8(pPvf$a#k~D%uxB8qt({P0JSFAPbDTM zszmCPmzS&3+zgeKoT!p!j8lF3^ife^y~%3t=0vqPI9O%HO;nMuy{2NZm!F@n@^dm&&ek}U8vUBu9PX!*W1>_=MTM%k zUarbd<*SM!?Jrp+uZdN$k<(OpPO>UWj#U-q`6}mNvPvR9C@4s+nHZ$DZr!T3CdI47 zm>3n0ousI66&@b0V#3F$FzSRczJqa5DmgY>9i(myWgmu*Q@QaoR19t6Vm?$`bz8=N zJ2zRK%1EvW*iWgSBJd9o0TKBTN71xKTGw%FE@@|#>Y6pRng=@gHhn7ascLE3uAQ$# z6W)B)Vlp|I9Gf~iIXW5Azp106qsht1QmoAO9GW{+i~0T~Yq^oonGU$n*V-l4yPw(H z`w#q?^|nsJ-@apu7A;=rXz$M}7pYzBZ|~*xT)$_Z?e~kIA(k38b^PszIdUs6F^KrBY=d$lr|yt{Sl_RKTSb@=5A_O>pXDdpe7r-zfP>!9bK@7C=_$L4K@ znEPO~Zbo_MUV~hbUICptJ>SdZIJDY;xm-8z(UoFT*QcKj=;Y~Sdf^uxjUMQ7-Q3^h z<)>X;J%9f5K7Cx;JGnYJwrycJu$K4i<>Kktd-(9)p4yF52fsSyPM%$R5BKQX*TbaC z-3D~knrE71B`}S?A%e$CfY+k#(gR85HF7Dg6i<75w2Pc!!-rRlN!H%@*(AUk) zt*^<&#pLQ_>Z}7)Q|_<*db+#efH1i_xnRCpn(6kcv#Y1cr0uu#>_BtkTT^UAprfm& zXBSh?5xqxr!Me3Mt+f!M&h*U5wZjPKo-TTRYoxk@@*gtT*Eb*_U}z&kQNMouzE>Oq z0|STI2o~OX=bcH72t`z|sXpu#L!Rt0At7PKiWPI`&YeDeIvtOUj9k8aIe%w0BvfG6 zIeGHrh=_=J^X9Eyy?WE8O;50&o10rwQc_x4T2N4M^ypEVr=_Lcx^*i(J^j+9OC+qq z?T#HgsF0bNnU$4A8x`BZl4ke|7A#=zym;~AKh=}@^XJ!z4^4&- zAKs|-dIf_A55@wWM3yXB5*r))fg$D`idX>k8vT%rG5-GHBSuUM3VL_QkjX(o-2Mc z^CozEzaJQw7#o`uyDag8kPYFZ)=wC+Hgrf_*vPoaZ^qAw{AlXbX@P+ge0mRuKaAWlYxuT^fGtz~Kbq2{J%mqD9S-pD8oZ!O3Q>@s;*oAu*y|Hi6zwe&^ue+i~ zZ=X4A?d-QwQ&U$gS+s8U?DvKaHQRA_$G-l#xit`|P~Yke7?B~)TNb>x?W4IjZ{ECn z_wK!W_qN4M$y_-xeR;@%#lPD#|F>H{iDB7q+4NrvC;rFEDN`m|qGSZ8xM$DeIz12b zaSrxrWzL-Qo8Rn?U%P)*#QppCA6sO{`enI^f5=%Ek+o`a`m*sUiLpFThYufKG%fg( z$Oxv}Is~(eI`+qVw=w6iU=rrd`(ow%>>X<@wjZB8ee%e*RfXG^7HnRa`|0c>Yu?Mr z*mvQ=g_9>w#?GJl@su}MVCGqHcRx#%_}SVI@op93TWz0Jw?8Q<{o|GA| zv^^IyKE05hc<#WuqFo>D|9r!abxUttyK?8wowBmB>?22(zC9`-I@-EijriBI?^9#{ z=)Qfs6PBg#+?b!a`$T%m)vveT&f9f6FZD+5&ZCF+SqD{BRdwy!wL@tKV%{IS`7eL5 z+BYxJTK)HJ9cp9$a(Vf&%>DVh)?EL3>)n%kD@(rm?qc4Ql@9#j>*0jq8u@T6gtW%EPj3xltrH&&ti>s;j3; z^AFqF&pVcV=5*nv^{f6nA%RtAwrRwt)Yg88PiubW99G&_Uwna)M^#n(w`K}m$K8o$lkp%bI*2O$VEj(>tkcB{pVd_Yn(JIU%T*bYtHBO^4)h2 zadG#~okROmzP(&1w@T$!8NY{@z9~L^a`)$-rtREZcrvfDvXWI)Qd~Uy_1Dd9U0qo} zbr*jK_G?eU=@TdP5FR~x`0!y?`hly(C*=0I$2UtVFBY6Xk$&U)HFK0W=HNq<`uXS9 z$*t3K^X+)=wt5OIOO(vnzy9_8ii+&Cy+tRFmz+KG?UgeRt`t4Ea{Au6<7Fof<)){8 zwSVXRdlh`nPMmCHjKiY$y2s$(xf}LZ|9`#%lUF=ac)LIUT*gO zFEtC*$0vHsn1aKHFP}emB5e=W zh{?Xx9cK@1Kbrhm_O9f8NlCL_ef7zavHE3-%`W&G=370{l+ygKQ>T8pZClZa6IU-> zC@n0^N=ezcc=5uqWB*3WRu|Spm|vSP%j0IwWbI+i_Ghj9Q{wN5fDJN;W)jUN|9_m) z*%(R`XRZH0qH$SsuSL!H{C_tN>ivrJdyp zKz)lY9W`py6Z->mIK{`ukA$Y?fKyxGspA0EO+98{N?31312@Wt?wrke0+cnVuvvrg*ET@3 z^&>`%c;fgQ=~z>UZ4rI=&a(EPHUZlNY%|o7uj}Zwikhd66b2j$<-RXBq6Vz^^ukTB27xu$^!k%29 zJ^}j#9udG#*qR9}Abd*GCi(h$X}{p#+wAEI*f)MgU*09HPc3Z!tHo`@@|JJg7Gr(d z>%&_IHlX2fRTW4mFrfg20u>5aC~%;Ns_w(@@L5D3&TIeZ9n#0i8>h={C3HY*_qV;BUncKq#-K^K3ZN8-Qb0=K zxfGyMph^KN1+EmpQXoqKEd{m|;8LJV0WTlF>+3rhTXu|hE&fiTXMxPII?vXxPU~^A z9eX`=K)Y`Gp12><^9yha#3>-Bz?=ef3e+iJr@);8cnahxpr`T71D^tY3iv5d0Y{C> z4)A<|ac42^T+-TqU2y zjR2p)$`T3-yV3cM-+tJSaW z1JEi^tAMQnw+i4YkgI^M0(A)RD$uKdug0^&I{2%$3BtZbA5zeD`rcL`*-$pz3q#E7 zPH%s+!C8T41)vp(*60IFD?qJ4wF1@(Tq}UBK(+$f3T!LDEo=3NfVTqQ>SwY*`(o?^ zng7q++)CnYeUrAs|B4WwHY<7Vp4VlxxeV?Kyej~&K)eF-3d}1&FPbV~ufV;vVgvgM z@GH=-fWHF&YX7&jO%SXXeOQGq)Atq`H^|u;fY}IPBu*O8+W0>ZZLWaB0uKv7ED*7P z!~zowP%KcffW-nA*YdCD2RIh!Sioa}kA-LWj`ro@ak>w_7X!)DExz?tj~Pr$#s7|R z{n{Dd2mBuemjzxHfLS1B(a5ZsSwpjCTd-N+=6e2tXMvstd=~gwc#ckKKg|08;y>HX zt@K~?y+uL>wP*{*WujjO`?b}3E5&oO9Go_61JnXhi$-egR}-~G;c5Y_1+o^+yfAZMwUc4(A;_#lxehtG>4pd!G9o{2zn0Lv_A>Z|HYAylwOW;uerw zG;?d{*3_*P?iRpXAa4P^1@;!;+jtJZZ-Kw{dr+T^IxzqLM*M$Ey52X5`QL&TGY7jV z*Y74fJqPf(IR=j&2}mw5xo9Yd$^|SJxLg2pfy}M*0Gu296Y$)!_U*fOFEjDnk8*P> z?u6}n0;x}94P1vpFOBzWWgKcTZ$shr#{fIA-76rw!0ZCF3)GID7PwsicY)jmbQjp& z*bhPP0=~;6FRxc|=IG&3$oKe+{vOwo2|mu9@VOkVApQ?|2JaDv{I~sD8i#VchvotF z0?`XdFEG6T^#aukSTAtB0QLge3urIUxB&M8-HU#Q;f!~0k&CNqNoUga;*Q@0-a8k# zibd(iWBn{pU+=x`Sc}mR|6`C}V15Dm4L|x>gZl;W7sy{ge}Vl4_}6j&Gi{r+Z-4pO z9z9O!J#W454S801$Gcru*5L2y!+Nwt_l4tto%-FNE3t-O!R9f}1cXBY;Z#6477)$_ zgo6R$WI#9?Fy^~@y;*Jlkc9pga$GQ$^MYBS16y16taf@$(3h3;B_F+o-bM@1Rp>B$ z)r;{D@&8ksA14CVbBa>_ZyKfMR4UbskCmZ1Ee93v8VAlW>|0hv*{KKoKb4Qk&~s=x nESzDZ(WEU(eveG0hNUSrnuWiP|EIoua8MJe>eJHdQYZcw9sz{& diff --git a/reactos/base/applications/downloader/rsrc.rc b/reactos/base/applications/downloader/rsrc.rc deleted file mode 100644 index 3943e3ae8a8..00000000000 --- a/reactos/base/applications/downloader/rsrc.rc +++ /dev/null @@ -1,41 +0,0 @@ -LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL - -IDI_MAIN ICON DISCARDABLE "resources/main.ico" -IDI_UPDATE ICON DISCARDABLE "resources/update.ico" -IDI_HELP ICON DISCARDABLE "resources/help.ico" -IDI_PROF ICON DISCARDABLE "resources/preferences.ico" -IDB_LOGO BITMAP DISCARDABLE "resources/logo.bmp" -IDB_DOWNLOAD BITMAP DISCARDABLE "resources/download.bmp" -IDB_UNINSTALL BITMAP DISCARDABLE "resources/uninstall.bmp" -IDB_UNDERLINE BITMAP DISCARDABLE "resources/underline.bmp" -IDB_TREEVIEW_ICON_0 BITMAP DISCARDABLE "resources/0.bmp" -IDB_TREEVIEW_ICON_1 BITMAP DISCARDABLE "resources/1.bmp" -IDB_TREEVIEW_ICON_2 BITMAP DISCARDABLE "resources/2.bmp" -IDB_TREEVIEW_ICON_3 BITMAP DISCARDABLE "resources/3.bmp" -IDB_TREEVIEW_ICON_4 BITMAP DISCARDABLE "resources/4.bmp" -IDB_TREEVIEW_ICON_5 BITMAP DISCARDABLE "resources/5.bmp" -IDB_TREEVIEW_ICON_6 BITMAP DISCARDABLE "resources/6.bmp" -IDB_TREEVIEW_ICON_7 BITMAP DISCARDABLE "resources/7.bmp" -IDB_TREEVIEW_ICON_8 BITMAP DISCARDABLE "resources/8.bmp" -IDB_TREEVIEW_ICON_9 BITMAP DISCARDABLE "resources/9.bmp" -IDB_TREEVIEW_ICON_10 BITMAP DISCARDABLE "resources/10.bmp" -IDB_TREEVIEW_ICON_11 BITMAP DISCARDABLE "resources/11.bmp" -IDB_TREEVIEW_ICON_12 BITMAP DISCARDABLE "resources/12.bmp" -IDB_TREEVIEW_ICON_13 BITMAP DISCARDABLE "resources/13.bmp" - - -#include "lang/bg-BG.rc" -#include "lang/de-DE.rc" -#include "lang/el-GR.rc" -#include "lang/en-US.rc" -#include "lang/es-ES.rc" -#include "lang/fr-FR.rc" -#include "lang/id-ID.rc" -#include "lang/it-IT.rc" -#include "lang/ja-JP.rc" -#include "lang/no-NO.rc" -#include "lang/pl-PL.rc" -#include "lang/lt-LT.rc" -#include "lang/ru-RU.rc" -#include "lang/sk-SK.rc" -#include "lang/uk-UA.rc" diff --git a/reactos/base/applications/downloader/structures.h b/reactos/base/applications/downloader/structures.h deleted file mode 100644 index 7aeee667866..00000000000 --- a/reactos/base/applications/downloader/structures.h +++ /dev/null @@ -1,26 +0,0 @@ - -struct Application -{ - WCHAR Name[0x100]; - WCHAR RegName[0x100]; - WCHAR Version[0x100]; - WCHAR Maintainer[0x100]; - WCHAR Licence[0x100]; - WCHAR Description[0x400]; - WCHAR Location[0x100]; - WCHAR Depends[0x100]; - WCHAR PostInstallAction[0x100]; - struct Application* Next; -}; - -struct Category -{ - WCHAR Name[0x100]; - //WCHAR Description[0x100]; - int Icon; - HANDLE TreeviewItem; - struct Application* Apps; - struct Category* Next; - struct Category* Children; - struct Category* Parent; -}; diff --git a/reactos/base/applications/downloader/xml.c b/reactos/base/applications/downloader/xml.c deleted file mode 100644 index a29c7bf74a9..00000000000 --- a/reactos/base/applications/downloader/xml.c +++ /dev/null @@ -1,237 +0,0 @@ -/* PROJECT: ReactOS Downloader - * LICENSE: GPL - See COPYING in the top level directory - * FILE: base\applications\downloader\xml.c - * PURPOSE: Parsing of application information xml files - * PROGRAMMERS: Maarten Bosma, Lester Kortenhoeven - */ - -#include -#include -#include -#include -#include -#include "structures.h" -#include "resources.h" - -BOOL TagOpen; -struct Category* Current; -struct Application* CurrentApplication; -char CurrentTag [0x100]; -extern WCHAR Strings [STRING_COUNT][MAX_STRING_LENGHT]; - -void tag_opened (void* usrdata, const char* tag, const char** arg) -{ - int i; - - if(!strcmp(tag, "tree") && !CurrentApplication) - { - // check version - } - - else if(!strcmp(tag, "category") && !CurrentApplication) - { - if (!Current) - { - Current = malloc(sizeof(struct Category)); - memset(Current, 0, sizeof(struct Category)); - } - else if (TagOpen) - { - Current->Children = malloc(sizeof(struct Category)); - memset(Current->Children, 0, sizeof(struct Category)); - Current->Children->Parent = Current; - Current = Current->Children; - } - else - { - Current->Next = malloc(sizeof(struct Category)); - memset(Current->Next, 0, sizeof(struct Category)); - Current->Next->Parent = Current->Parent; - Current = Current->Next; - } - TagOpen = TRUE; - - for (i=0; arg[i]; i+=2) - { - if(!strcmp(arg[i], "name")) - { - MultiByteToWideChar(CP_UTF8, 0, arg[i+1], -1, Current->Name, 0x100); - } - if(!strcmp(arg[i], "icon")) - { - Current->Icon = atoi(arg[i+1]); - } - } - } - - else if(!strcmp(tag, "application") && !CurrentApplication) - { - if(Current->Apps) - { - CurrentApplication = Current->Apps; - while(CurrentApplication->Next) - CurrentApplication = CurrentApplication->Next; - CurrentApplication->Next = malloc(sizeof(struct Application)); - memset(CurrentApplication->Next, 0, sizeof(struct Application)); - CurrentApplication = CurrentApplication->Next; - } - else - { - Current->Apps = malloc(sizeof(struct Application)); - memset(Current->Apps, 0, sizeof(struct Application)); - CurrentApplication = Current->Apps; - } - - for (i=0; arg[i]; i+=2) - { - if(!strcmp(arg[i], "name")) - { - MultiByteToWideChar(CP_UTF8, 0, arg[i+1], -1, CurrentApplication->Name, 0x100); - } - } - } - else if (CurrentApplication) - { - strncpy(CurrentTag, tag, 0x100); - } - else - MessageBoxW(0,Strings[IDS_XMLERROR_2],0,0); -} - - -void text (void* usrdata, const char* data, int len) -{ - if (!CurrentApplication) - return; - - if(!strcmp(CurrentTag, "maintainer")) - { - int currentlengt = lstrlenW(CurrentApplication->Maintainer); - MultiByteToWideChar(CP_UTF8, 0, data, len, &CurrentApplication->Maintainer[currentlengt], 0x100-currentlengt); - } - else if(!strcmp(CurrentTag, "regname")) - { - int currentlengt = lstrlenW(CurrentApplication->RegName); - MultiByteToWideChar(CP_UTF8, 0, data, len, &CurrentApplication->RegName[currentlengt], 0x100-currentlengt); - } - else if(!strcmp(CurrentTag, "description")) - { - int currentlengt = lstrlenW(CurrentApplication->Description); - MultiByteToWideChar(CP_UTF8, 0, data, len, &CurrentApplication->Description[currentlengt], 0x400-currentlengt); - } - else if(!strcmp(CurrentTag, "location")) - { - int currentlengt = lstrlenW(CurrentApplication->Location); - MultiByteToWideChar(CP_UTF8, 0, data, len, &CurrentApplication->Location[currentlengt], 0x100-currentlengt); - } - else if(!strcmp(CurrentTag, "version")) - { - int currentlengt = lstrlenW(CurrentApplication->Version); - MultiByteToWideChar(CP_UTF8, 0, data, len, &CurrentApplication->Version[currentlengt], 0x400-currentlengt); - } - else if(!strcmp(CurrentTag, "licence")) - { - int currentlengt = lstrlenW(CurrentApplication->Licence); - MultiByteToWideChar(CP_UTF8, 0, data, len, &CurrentApplication->Licence[currentlengt], 0x100-currentlengt); - } - else if(!strcmp(CurrentTag, "depends")) - { - int currentlengt = lstrlenW(CurrentApplication->Depends); - MultiByteToWideChar(CP_UTF8, 0, data, len, &CurrentApplication->Depends[currentlengt], 0x100-currentlengt); - } - else if(!strcmp(CurrentTag, "postinstallaction")) - { - int currentlengt = lstrlenW(CurrentApplication->PostInstallAction); - MultiByteToWideChar(CP_UTF8, 0, data, len, &CurrentApplication->PostInstallAction[currentlengt], 0x100-currentlengt); - } -} - -void tag_closed (void* tree, const char* tag) -{ - CurrentTag[0] = 0; - - if(!strcmp(tag, "category")) - { - if (TagOpen) - { - TagOpen = FALSE; - } - else - { - Current = Current->Parent; - } - } - else if(!strcmp(tag, "application")) - { - CurrentApplication = NULL; - } -} - -BOOL ProcessXML (const char* filename, struct Category* Root) -{ - int done = 0; - char buffer[255]; - FILE* file; - XML_Parser parser; - - if(Current) - return FALSE; - - Current = Root; - TagOpen = TRUE; - - file = fopen("downloader.xml", "r"); - if(!file) - { - file = fopen(filename, "r"); - if(!file) - { - MessageBoxW(0,Strings[IDS_XMLERROR_1],0,0); - return FALSE; - } - } - - parser = XML_ParserCreate(NULL); - XML_SetElementHandler(parser, tag_opened, tag_closed); - XML_SetCharacterDataHandler(parser, text); - - while (!done) - { - size_t len = fread (buffer, 1, sizeof(buffer), file); - done = len < sizeof(buffer); - - if(!XML_Parse(parser, buffer, len, done)) - { - MessageBoxW(0,Strings[IDS_XMLERROR_2],0,0); - fclose(file); - return FALSE; - } - } - - XML_ParserFree(parser); - fclose(file); - - return TRUE; -} - -void FreeApps (struct Application* Apps) -{ - if (Apps->Next) - FreeApps(Apps->Next); - - free(Apps); -} - -void FreeTree (struct Category* Node) -{ - if (Node->Children) - FreeTree(Node->Children); - - if (Node->Next) - FreeTree(Node->Next); - - if (Node->Apps) - FreeApps(Node->Apps); - - free(Node); -} From f4769202d73861b1bd9840ab8d9e6306bf93c83d Mon Sep 17 00:00:00 2001 From: Daniel Reimer Date: Wed, 14 Jul 2010 14:53:35 +0000 Subject: [PATCH 41/43] Reapply some Win32 specific magic to properly build a Windows DLL of libjpeg. (Samuel Serapion) svn path=/trunk/; revision=48038 --- .../include/reactos/libs/libjpeg/jmorecfg.h | 53 +++++++++++++- .../reactos/libs/libjpeg/rosdiff.patch | 70 +++++++++++++++++++ 2 files changed, 121 insertions(+), 2 deletions(-) create mode 100644 reactos/include/reactos/libs/libjpeg/rosdiff.patch diff --git a/reactos/include/reactos/libs/libjpeg/jmorecfg.h b/reactos/include/reactos/libs/libjpeg/jmorecfg.h index a9478f460bd..ce741f84c6e 100644 --- a/reactos/include/reactos/libs/libjpeg/jmorecfg.h +++ b/reactos/include/reactos/libs/libjpeg/jmorecfg.h @@ -191,14 +191,63 @@ typedef unsigned int JDIMENSION; * or code profilers that require it. */ +#ifdef _WIN32 +# if defined(ALL_STATIC) +# if defined(JPEG_DLL) +# undef JPEG_DLL +# endif +# if !defined(JPEG_STATIC) +# define JPEG_STATIC +# endif +# endif +# if defined(JPEG_DLL) +# if defined(JPEG_STATIC) +# undef JPEG_STATIC +# endif +# endif +# if defined(JPEG_DLL) +/* building a DLL */ +# define JPEG_IMPEXP __declspec(dllexport) +# elif defined(JPEG_STATIC) +/* building or linking to a static library */ +# define JPEG_IMPEXP +# else +/* linking to the DLL */ +# define JPEG_IMPEXP __declspec(dllimport) +# endif +# if !defined(JPEG_API) +# define JPEG_API __cdecl +# endif +/* The only remaining magic that is necessary for cygwin */ +#elif defined(__CYGWIN__) +# if !defined(JPEG_IMPEXP) +# define JPEG_IMPEXP +# endif +# if !defined(JPEG_API) +# define JPEG_API __cdecl +# endif +#endif + +/* Ensure our magic doesn't hurt other platforms */ +#if !defined(JPEG_IMPEXP) +# define JPEG_IMPEXP +#endif +#if !defined(JPEG_API) +# define JPEG_API +#endif + /* a function called through method pointers: */ #define METHODDEF(type) static type /* a function used only in its module: */ #define LOCAL(type) static type /* a function referenced thru EXTERNs: */ -#define GLOBAL(type) type +#define GLOBAL(type) type JPEG_API /* a reference to a GLOBAL function: */ -#define EXTERN(type) extern type +#ifndef EXTERN +# define EXTERN(type) extern JPEG_IMPEXP type JPEG_API +/* a reference to a "GLOBAL" function exported by sourcefiles of utility progs */ +#endif /* EXTERN */ +#define EXTERN_1(type) extern type JPEG_API /* This macro is used to declare a "method", that is, a function pointer. diff --git a/reactos/include/reactos/libs/libjpeg/rosdiff.patch b/reactos/include/reactos/libs/libjpeg/rosdiff.patch new file mode 100644 index 00000000000..5ef5bc41ab0 --- /dev/null +++ b/reactos/include/reactos/libs/libjpeg/rosdiff.patch @@ -0,0 +1,70 @@ +Index: libs/libjpeg/jmorecfg.h +=================================================================== +--- libs/libjpeg/jmorecfg.h (revision 48026) ++++ libs/libjpeg/jmorecfg.h (working copy) +@@ -191,14 +191,63 @@ + * or code profilers that require it. + */ + ++#ifdef _WIN32 ++# if defined(ALL_STATIC) ++# if defined(JPEG_DLL) ++# undef JPEG_DLL ++# endif ++# if !defined(JPEG_STATIC) ++# define JPEG_STATIC ++# endif ++# endif ++# if defined(JPEG_DLL) ++# if defined(JPEG_STATIC) ++# undef JPEG_STATIC ++# endif ++# endif ++# if defined(JPEG_DLL) ++/* building a DLL */ ++# define JPEG_IMPEXP __declspec(dllexport) ++# elif defined(JPEG_STATIC) ++/* building or linking to a static library */ ++# define JPEG_IMPEXP ++# else ++/* linking to the DLL */ ++# define JPEG_IMPEXP __declspec(dllimport) ++# endif ++# if !defined(JPEG_API) ++# define JPEG_API __cdecl ++# endif ++/* The only remaining magic that is necessary for cygwin */ ++#elif defined(__CYGWIN__) ++# if !defined(JPEG_IMPEXP) ++# define JPEG_IMPEXP ++# endif ++# if !defined(JPEG_API) ++# define JPEG_API __cdecl ++# endif ++#endif ++ ++/* Ensure our magic doesn't hurt other platforms */ ++#if !defined(JPEG_IMPEXP) ++# define JPEG_IMPEXP ++#endif ++#if !defined(JPEG_API) ++# define JPEG_API ++#endif ++ + /* a function called through method pointers: */ + #define METHODDEF(type) static type + /* a function used only in its module: */ + #define LOCAL(type) static type + /* a function referenced thru EXTERNs: */ +-#define GLOBAL(type) type ++#define GLOBAL(type) type JPEG_API + /* a reference to a GLOBAL function: */ +-#define EXTERN(type) extern type ++#ifndef EXTERN ++# define EXTERN(type) extern JPEG_IMPEXP type JPEG_API ++/* a reference to a "GLOBAL" function exported by sourcefiles of utility progs */ ++#endif /* EXTERN */ ++#define EXTERN_1(type) extern type JPEG_API + + + /* This macro is used to declare a "method", that is, a function pointer. From 8ad729230c1fd7ac8591fb1c0285991b0b0256ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Wed, 14 Jul 2010 14:56:53 +0000 Subject: [PATCH 42/43] [W32KNAPI] - Test ONE_PARAM_ROUTINE_CREATEEMPTYCUROBJECT - Test NtUserGetIconInfo svn path=/trunk/; revision=48039 --- .../w32knapi/ntuser/NtUserCallOneParam.c | 21 +++++++ .../w32knapi/ntuser/NtUserGetIconInfo.c | 62 +++++++++++++++++++ rostests/apitests/w32knapi/osver.c | 1 + rostests/apitests/w32knapi/testlist.c | 2 + rostests/apitests/w32knapi/w32knapi.h | 2 + 5 files changed, 88 insertions(+) create mode 100644 rostests/apitests/w32knapi/ntuser/NtUserGetIconInfo.c diff --git a/rostests/apitests/w32knapi/ntuser/NtUserCallOneParam.c b/rostests/apitests/w32knapi/ntuser/NtUserCallOneParam.c index 72b83a07901..519d8e8887c 100644 --- a/rostests/apitests/w32knapi/ntuser/NtUserCallOneParam.c +++ b/rostests/apitests/w32knapi/ntuser/NtUserCallOneParam.c @@ -25,6 +25,26 @@ Test_OneParamRoutine_WindowFromDC(PTESTINFO pti) /* 0x1f */ return APISTATUS_NORMAL; } +INT +Test_OneParamRoutine_CreateEmptyCurObject(PTESTINFO pti) /* XP/2k3 : 0x21, vista 0x25 */ +{ + HICON hIcon ; + + /* Test 0 */ + hIcon = (HICON) NtUserCallOneParam(0, _ONEPARAM_ROUTINE_CREATEEMPTYCUROBJECT); + TEST(hIcon != NULL); + + TEST(NtUserDestroyCursor(hIcon, 0) == TRUE); + + /* Test Garbage */ + hIcon = (HICON) NtUserCallOneParam(0xdeadbeef, _ONEPARAM_ROUTINE_CREATEEMPTYCUROBJECT); + TEST(hIcon != NULL); + + TEST(NtUserDestroyCursor(hIcon, 0xbaadf00d) == TRUE); + + return APISTATUS_NORMAL; +} + INT Test_OneParamRoutine_MapDesktopObject(PTESTINFO pti) /* 0x30 */ { @@ -66,6 +86,7 @@ Test_NtUserCallOneParam(PTESTINFO pti) { Test_OneParamRoutine_BeginDeferWindowPos(pti); /* 0x1e */ Test_OneParamRoutine_WindowFromDC(pti); /* 0x1f */ + Test_OneParamRoutine_CreateEmptyCurObject(pti); /* XP/2k3 : 0x21, vista 0x25 */ Test_OneParamRoutine_MapDesktopObject(pti); /* 0x30 */ Test_OneParamRoutine_SwapMouseButtons(pti); /* 0x42 */ diff --git a/rostests/apitests/w32knapi/ntuser/NtUserGetIconInfo.c b/rostests/apitests/w32knapi/ntuser/NtUserGetIconInfo.c new file mode 100644 index 00000000000..d0e1ec018a3 --- /dev/null +++ b/rostests/apitests/w32knapi/ntuser/NtUserGetIconInfo.c @@ -0,0 +1,62 @@ +INT +Test_NtUserGetIconInfo(PTESTINFO pti) +{ + HICON hIcon; + ICONINFO iinfo; + HBITMAP mask, color; + + ZeroMemory(&iinfo, sizeof(ICONINFO)); + + /* BASIC TESTS */ + hIcon = (HICON) NtUserCallOneParam(0, _ONEPARAM_ROUTINE_CREATEEMPTYCUROBJECT); + TEST(hIcon != NULL); + + /* Last param is unknown */ + TEST(NtUserGetIconInfo(hIcon, &iinfo, NULL, NULL, NULL, FALSE) == FALSE); + TEST(NtUserGetIconInfo(hIcon, &iinfo, NULL, NULL, NULL, TRUE) == FALSE); + + TEST(NtUserDestroyCursor(hIcon, 0) == TRUE); + + mask = CreateBitmap(16,16,1,1,NULL); + color = CreateBitmap(16,16,1,16,NULL); + + iinfo.hbmMask = mask; + iinfo.hbmColor = color ; + iinfo.fIcon = TRUE; + iinfo.xHotspot = 8; + iinfo.yHotspot = 8; + + hIcon = CreateIconIndirect(&iinfo); + TEST(hIcon!=NULL); + + // TODO : test last parameter... + TEST(NtUserGetIconInfo(hIcon, &iinfo, NULL, NULL, NULL, FALSE) == TRUE); + + TEST(iinfo.hbmMask != NULL); + TEST(iinfo.hbmColor != NULL); + TEST(iinfo.fIcon == TRUE); + TEST(iinfo.yHotspot == 8); + TEST(iinfo.xHotspot == 8); + + TEST(iinfo.hbmMask != mask); + TEST(iinfo.hbmColor != color); + + /* Does it make a difference? */ + TEST(NtUserGetIconInfo(hIcon, &iinfo, NULL, NULL, NULL, TRUE) == TRUE); + + TEST(iinfo.hbmMask != NULL); + TEST(iinfo.hbmColor != NULL); + TEST(iinfo.fIcon == TRUE); + TEST(iinfo.yHotspot == 8); + TEST(iinfo.xHotspot == 8); + + TEST(iinfo.hbmMask != mask); + TEST(iinfo.hbmColor != color); + + DeleteObject(mask); + DeleteObject(color); + + DestroyIcon(hIcon); + + return APISTATUS_NORMAL; +} \ No newline at end of file diff --git a/rostests/apitests/w32knapi/osver.c b/rostests/apitests/w32knapi/osver.c index d9639b1f197..18e0dc44867 100644 --- a/rostests/apitests/w32knapi/osver.c +++ b/rostests/apitests/w32knapi/osver.c @@ -6,6 +6,7 @@ UINT g_OsIdx; ASPI gNOPARAM_ROUTINE_CREATEMENU = {-1,-1,0x00,-1,0x00}; ASPI gNOPARAM_ROUTINE_CREATEMENUPOPUP = {-1,-1,0x01,-1,0x01}; ASPI gNOPARAM_ROUTINE_LOADUSERAPIHOOK = {-1,-1,0x1d,-1,0x0e}; +ASPI gONEPARAM_ROUTINE_CREATEEMPTYCUROBJECT = {-1, -1, 0x21, 0x21, 0x25}; ASPI gONEPARAM_ROUTINE_MAPDEKTOPOBJECT = {-1,-1,0x30,-1,0x31}; ASPI gONEPARAM_ROUTINE_SWAPMOUSEBUTTON = {-1,-1,0x42,-1,0x44}; diff --git a/rostests/apitests/w32knapi/testlist.c b/rostests/apitests/w32knapi/testlist.c index b38e66bf0b5..aa87801236e 100644 --- a/rostests/apitests/w32knapi/testlist.c +++ b/rostests/apitests/w32knapi/testlist.c @@ -50,6 +50,7 @@ #include "ntuser/NtUserEnumDisplaySettings.c" #include "ntuser/NtUserFindExistingCursorIcon.c" #include "ntuser/NtUserGetClassInfo.c" +#include "ntuser/NtUserGetIconInfo.c" #include "ntuser/NtUserGetTitleBarInfo.c" #include "ntuser/NtUserProcessConnect.c" #include "ntuser/NtUserRedrawWindow.c" @@ -114,6 +115,7 @@ TESTENTRY TestList[] = { L"NtUserEnumDisplaySettings", TEST_NtUserEnumDisplaySettings }, { L"NtUserFindExistingCursorIcon", Test_NtUserFindExistingCursoricon }, { L"NtUserGetClassInfo", Test_NtUserGetClassInfo }, + { L"NtUserGetIconInfo", Test_NtUserGetIconInfo }, { L"NtUserGetTitleBarInfo", Test_NtUserGetTitleBarInfo }, { L"NtUserProcessConnect", Test_NtUserProcessConnect }, { L"NtUserRedrawWindow", Test_NtUserRedrawWindow }, diff --git a/rostests/apitests/w32knapi/w32knapi.h b/rostests/apitests/w32knapi/w32knapi.h index 2821787814a..4b15d05c9ff 100644 --- a/rostests/apitests/w32knapi/w32knapi.h +++ b/rostests/apitests/w32knapi/w32knapi.h @@ -47,6 +47,7 @@ typedef UINT ASPI[5]; extern ASPI gNOPARAM_ROUTINE_CREATEMENU; extern ASPI gNOPARAM_ROUTINE_CREATEMENUPOPUP; extern ASPI gNOPARAM_ROUTINE_LOADUSERAPIHOOK; +extern ASPI gONEPARAM_ROUTINE_CREATEEMPTYCUROBJECT; extern ASPI gONEPARAM_ROUTINE_MAPDEKTOPOBJECT; extern ASPI gONEPARAM_ROUTINE_SWAPMOUSEBUTTON; extern ASPI gHWND_ROUTINE_DEREGISTERSHELLHOOKWINDOW; @@ -56,6 +57,7 @@ extern ASPI gHWNDPARAM_ROUTINE_SETWNDCONTEXTHLPID; #define _NOPARAM_ROUTINE_CREATEMENU gNOPARAM_ROUTINE_CREATEMENU[g_OsIdx] #define _NOPARAM_ROUTINE_CREATEMENUPOPUP gNOPARAM_ROUTINE_CREATEMENUPOPUP[g_OsIdx] #define _NOPARAM_ROUTINE_LOADUSERAPIHOOK gNOPARAM_ROUTINE_LOADUSERAPIHOOK[g_OsIdx] +#define _ONEPARAM_ROUTINE_CREATEEMPTYCUROBJECT gONEPARAM_ROUTINE_CREATEEMPTYCUROBJECT[g_OsIdx] #define _ONEPARAM_ROUTINE_MAPDEKTOPOBJECT gONEPARAM_ROUTINE_MAPDEKTOPOBJECT[g_OsIdx] #define _ONEPARAM_ROUTINE_SWAPMOUSEBUTTON gONEPARAM_ROUTINE_SWAPMOUSEBUTTON[g_OsIdx] #define _HWND_ROUTINE_DEREGISTERSHELLHOOKWINDOW gHWND_ROUTINE_DEREGISTERSHELLHOOKWINDOW[g_OsIdx] From d61b5efe6c6da325ae79fdf6995e761395af6d52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Wed, 14 Jul 2010 15:01:02 +0000 Subject: [PATCH 43/43] [WIN32K, USER32] - Get rid of ONEPARAM_ROUTINE_CREATECURICONHANDLE svn path=/trunk/; revision=48040 --- reactos/dll/win32/user32/windows/cursoricon.c | 4 ++-- reactos/include/reactos/win32k/ntuser.h | 1 - reactos/subsystems/win32/win32k/ntuser/simplecall.c | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/reactos/dll/win32/user32/windows/cursoricon.c b/reactos/dll/win32/user32/windows/cursoricon.c index 52a22a47c18..d0936a93b1c 100644 --- a/reactos/dll/win32/user32/windows/cursoricon.c +++ b/reactos/dll/win32/user32/windows/cursoricon.c @@ -76,8 +76,8 @@ static HICON CreateCursorIconHandle( PICONINFO IconInfo ) { - HICON hIcon = (HICON)NtUserCallOneParam(0, //FIXME ? - ONEPARAM_ROUTINE_CREATECURICONHANDLE); + HICON hIcon = (HICON)NtUserCallOneParam(0, + ONEPARAM_ROUTINE_CREATEEMPTYCUROBJECT); if(!hIcon) return NULL; diff --git a/reactos/include/reactos/win32k/ntuser.h b/reactos/include/reactos/win32k/ntuser.h index fec4e9b437d..f07263a6f1d 100644 --- a/reactos/include/reactos/win32k/ntuser.h +++ b/reactos/include/reactos/win32k/ntuser.h @@ -3140,7 +3140,6 @@ typedef struct tagKMDDELPARAM #define ONEPARAM_ROUTINE_ISWINDOWINDESTROY 0xfffe000c #define ONEPARAM_ROUTINE_ENABLEPROCWNDGHSTING 0xfffe000d #define ONEPARAM_ROUTINE_GETDESKTOPMAPPING 0xfffe000e -#define ONEPARAM_ROUTINE_CREATECURICONHANDLE 0xfffe0025 // CREATE_EMPTY_CURSOR_OBJECT ? #define ONEPARAM_ROUTINE_MSQSETWAKEMASK 0xfffe0027 #define ONEPARAM_ROUTINE_GETCURSORPOSITION 0xfffe0048 // use ONEPARAM_ or TWOPARAM routine ? #define TWOPARAM_ROUTINE_GETWINDOWRGNBOX 0xfffd0048 // user mode diff --git a/reactos/subsystems/win32/win32k/ntuser/simplecall.c b/reactos/subsystems/win32/win32k/ntuser/simplecall.c index d25ead5dc46..bf26bc27962 100644 --- a/reactos/subsystems/win32/win32k/ntuser/simplecall.c +++ b/reactos/subsystems/win32/win32k/ntuser/simplecall.c @@ -192,7 +192,7 @@ NtUserCallOneParam( case ONEPARAM_ROUTINE_SETMESSAGEEXTRAINFO: RETURN( (DWORD_PTR)MsqSetMessageExtraInfo((LPARAM)Param)); - case ONEPARAM_ROUTINE_CREATECURICONHANDLE: + case ONEPARAM_ROUTINE_CREATEEMPTYCUROBJECT: { PCURICON_OBJECT CurIcon; DWORD_PTR Result ;