From: Hans Leidekker hans@codeweavers.com
--- dlls/wpcap/unixlib.c | 59 ++++++++++++++++++++++++++++++++++++++++---- dlls/wpcap/unixlib.h | 5 +++- dlls/wpcap/wpcap.c | 21 ++++++++++++---- 3 files changed, 74 insertions(+), 11 deletions(-)
diff --git a/dlls/wpcap/unixlib.c b/dlls/wpcap/unixlib.c index b2e2537647b..338c3a1629a 100644 --- a/dlls/wpcap/unixlib.c +++ b/dlls/wpcap/unixlib.c @@ -40,6 +40,8 @@ #include "wine/debug.h" #include "unixlib.h"
+static ULONG_PTR zero_bits = 0; + WINE_DEFAULT_DEBUG_CHANNEL(wpcap);
static NTSTATUS wrap_activate( void *args ) @@ -318,7 +320,8 @@ static NTSTATUS wrap_next_ex( void *args ) if (sizeof(void *) == 4) { struct pcap_pkthdr_win32 *hdr32; - if ((ret = pcap_next_ex( (pcap_t *)(ULONG_PTR)params->handle, (struct pcap_pkthdr **)&hdr32, params->data )) == 1) + + if ((ret = pcap_next_ex( (pcap_t *)(ULONG_PTR)params->handle, (struct pcap_pkthdr **)&hdr32, ¶ms->data )) == 1) { params->hdr->ts.tv_sec = hdr32->ts.tv_sec; params->hdr->ts.tv_usec = hdr32->ts.tv_usec; @@ -329,13 +332,33 @@ static NTSTATUS wrap_next_ex( void *args ) else { struct pcap_pkthdr *hdr64; - if ((ret = pcap_next_ex( (pcap_t *)(ULONG_PTR)params->handle, &hdr64, params->data )) == 1) + const unsigned char *data; + + if ((ret = pcap_next_ex( (pcap_t *)(ULONG_PTR)params->handle, &hdr64, &data )) == 1) { + SIZE_T size; + if (hdr64->ts.tv_sec > INT_MAX || hdr64->ts.tv_usec > INT_MAX) WARN( "truncating timeval values(s)\n" ); params->hdr->ts.tv_sec = hdr64->ts.tv_sec; params->hdr->ts.tv_usec = hdr64->ts.tv_usec; params->hdr->caplen = hdr64->caplen; params->hdr->len = hdr64->len; + + if (zero_bits && (ULONG_PTR)data > zero_bits) + { + if (params->buf && params->bufsize < hdr64->caplen) + { + size = 0; + NtFreeVirtualMemory( GetCurrentProcess(), (void **)¶ms->buf, &size, MEM_RELEASE ); + } + size = hdr64->caplen; + if (NtAllocateVirtualMemory( GetCurrentProcess(), (void **)¶ms->buf, zero_bits, &size, + MEM_COMMIT, PAGE_READWRITE )) return PCAP_ERROR; + params->bufsize = size; + memcpy( params->buf, data, hdr64->caplen ); + params->data = params->buf; + } + else params->data = data; } } return ret; @@ -484,8 +507,22 @@ static NTSTATUS wrap_tstamp_type_val_to_name( void *args ) return STATUS_SUCCESS; }
+static NTSTATUS process_attach( void *args ) +{ +#ifdef _WIN64 + if (NtCurrentTeb()->WowTebOffset) + { + SYSTEM_BASIC_INFORMATION info; + NtQuerySystemInformation( SystemEmulationBasicInformation, &info, sizeof(info), NULL ); + zero_bits = (ULONG_PTR)info.HighestUserAddress | 0x7fffffff; + } +#endif + return STATUS_SUCCESS; +} + const unixlib_entry_t __wine_unix_call_funcs[] = { + process_attach, wrap_activate, wrap_breakloop, wrap_bufsize, @@ -806,20 +843,31 @@ static NTSTATUS wow64_lookupnet( void *args )
static NTSTATUS wow64_next_ex( void *args ) { + NTSTATUS ret; + struct { UINT64 handle; PTR32 hdr; PTR32 data; - } const *params32 = args; + PTR32 buf; + UINT32 bufsize; + } *params32 = args;
struct next_ex_params params = { params32->handle, ULongToPtr(params32->hdr), - ULongToPtr(params32->data) + ULongToPtr(params32->data), + ULongToPtr(params32->buf), + params32->bufsize }; - return wrap_next_ex( ¶ms ); + ret = wrap_next_ex( ¶ms ); + + params32->data = PtrToUlong( params.data ); + params32->buf = PtrToUlong( params.buf ); + params32->bufsize = params.bufsize; + return ret; }
static NTSTATUS wow64_open_live( void *args ) @@ -952,6 +1000,7 @@ static NTSTATUS wow64_tstamp_type_val_to_name( void *args )
const unixlib_entry_t __wine_unix_call_wow64_funcs[] = { + process_attach, wrap_activate, wrap_breakloop, wrap_bufsize, diff --git a/dlls/wpcap/unixlib.h b/dlls/wpcap/unixlib.h index fa821085e4d..e618c1c090b 100644 --- a/dlls/wpcap/unixlib.h +++ b/dlls/wpcap/unixlib.h @@ -222,7 +222,9 @@ struct next_ex_params { UINT64 handle; struct pcap_pkthdr_win32 *hdr; - const unsigned char **data; + const unsigned char *data; + unsigned char *buf; + UINT32 bufsize; };
struct open_live_params @@ -342,6 +344,7 @@ struct tstamp_type_val_to_name_params
enum pcap_funcs { + unix_process_attach, unix_activate, unix_breakloop, unix_bufsize, diff --git a/dlls/wpcap/wpcap.c b/dlls/wpcap/wpcap.c index 96fe737476e..4f9717d5e41 100644 --- a/dlls/wpcap/wpcap.c +++ b/dlls/wpcap/wpcap.c @@ -64,6 +64,8 @@ struct pcap { UINT64 handle; struct pcap_pkthdr_win32 hdr; + unsigned char *buf; + UINT32 bufsize; char errbuf[PCAP_ERRBUF_SIZE]; };
@@ -133,12 +135,14 @@ int CDECL pcap_can_set_rfmon( struct pcap *pcap ) void CDECL pcap_close( struct pcap *pcap ) { struct close_params params; + SIZE_T size = 0;
TRACE( "%p\n", pcap );
if (!pcap) return; params.handle = pcap->handle; PCAP_CALL( close, ¶ms ); + if (pcap->buf) NtFreeVirtualMemory( GetCurrentProcess(), (void **)&pcap->buf, &size, MEM_RELEASE ); free( pcap ); }
@@ -946,10 +950,17 @@ int CDECL pcap_next_ex( struct pcap *pcap, struct pcap_pkthdr_win32 **hdr, const TRACE( "%p, %p, %p\n", pcap, hdr, data );
if (!pcap) return PCAP_ERROR; - params.handle = pcap->handle; - params.hdr = &pcap->hdr; - params.data = data; - if ((ret = PCAP_CALL( next_ex, ¶ms )) == 1) *hdr = &pcap->hdr; + params.handle = pcap->handle; + params.hdr = &pcap->hdr; + params.buf = pcap->buf; + params.bufsize = pcap->bufsize; + if ((ret = PCAP_CALL( next_ex, ¶ms )) == 1) + { + *hdr = &pcap->hdr; + *data = params.data; + pcap->buf = params.buf; + pcap->bufsize = params.bufsize; + } return ret; }
@@ -1466,7 +1477,7 @@ BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, void *reserved ) { DisableThreadLibraryCalls( hinst ); if (__wine_init_unix_call()) ERR( "No pcap support, expect problems\n" ); - else + else if (!PCAP_CALL( process_attach, NULL )) { char errbuf[PCAP_ERRBUF_SIZE]; struct init_params params = { PCAP_CHAR_ENC_UTF_8, errbuf };