2005-03-25 16:40:17 +03:00
/*
Unix SMB / CIFS implementation .
libndr compression support
Copyright ( C ) Stefan Metzmacher 2005
2008-07-10 13:31:43 +04:00
Copyright ( C ) Matthieu Suiche 2008
2005-03-25 16:40:17 +03:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2005-03-25 16:40:17 +03:00
( at your option ) any later version .
This program 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 General Public License for more details .
You should have received a copy of the GNU General Public License
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2005-03-25 16:40:17 +03:00
*/
# include "includes.h"
2008-09-17 16:11:12 +04:00
# include "../lib/compression/lzxpress.h"
2006-03-18 18:42:57 +03:00
# include "librpc/ndr/libndr.h"
2008-10-15 01:46:34 +04:00
# include "../librpc/ndr/ndr_compression.h"
2008-08-07 20:24:57 +04:00
# include <zlib.h>
static voidpf ndr_zlib_alloc ( voidpf opaque , uInt items , uInt size )
{
return talloc_zero_size ( opaque , items * size ) ;
}
static void ndr_zlib_free ( voidpf opaque , voidpf address )
{
talloc_free ( address ) ;
}
2005-03-25 16:40:17 +03:00
2007-11-09 21:24:10 +03:00
static enum ndr_err_code ndr_pull_compression_mszip_chunk ( struct ndr_pull * ndrpull ,
2005-03-30 14:48:52 +04:00
struct ndr_push * ndrpush ,
2008-08-07 20:24:57 +04:00
z_stream * z ,
2007-11-01 11:48:42 +03:00
bool * last )
2005-03-25 16:40:17 +03:00
{
2005-03-30 14:48:52 +04:00
DATA_BLOB comp_chunk ;
2005-03-29 12:10:31 +04:00
uint32_t comp_chunk_offset ;
uint32_t comp_chunk_size ;
2005-03-30 14:48:52 +04:00
DATA_BLOB plain_chunk ;
2005-03-29 12:10:31 +04:00
uint32_t plain_chunk_offset ;
uint32_t plain_chunk_size ;
2008-08-07 20:24:57 +04:00
int z_ret ;
2005-03-25 16:40:17 +03:00
2005-03-29 12:10:31 +04:00
NDR_CHECK ( ndr_pull_uint32 ( ndrpull , NDR_SCALARS , & plain_chunk_size ) ) ;
if ( plain_chunk_size > 0x00008000 ) {
2005-10-10 16:10:10 +04:00
return ndr_pull_error ( ndrpull , NDR_ERR_COMPRESSION , " Bad MSZIP plain chunk size %08X > 0x00008000 (PULL) " ,
2005-03-29 14:01:34 +04:00
plain_chunk_size ) ;
2005-03-25 16:40:17 +03:00
}
2005-03-29 12:10:31 +04:00
NDR_CHECK ( ndr_pull_uint32 ( ndrpull , NDR_SCALARS , & comp_chunk_size ) ) ;
2005-03-25 16:40:17 +03:00
2008-09-06 12:55:04 +04:00
DEBUG ( 9 , ( " MSZIP plain_chunk_size: %08X (%u) comp_chunk_size: %08X (%u) \n " ,
plain_chunk_size , plain_chunk_size , comp_chunk_size , comp_chunk_size ) ) ;
2005-03-29 12:10:31 +04:00
comp_chunk_offset = ndrpull - > offset ;
NDR_CHECK ( ndr_pull_advance ( ndrpull , comp_chunk_size ) ) ;
2005-03-30 14:48:52 +04:00
comp_chunk . length = comp_chunk_size ;
comp_chunk . data = ndrpull - > data + comp_chunk_offset ;
2005-03-29 12:10:31 +04:00
plain_chunk_offset = ndrpush - > offset ;
NDR_CHECK ( ndr_push_zero ( ndrpush , plain_chunk_size ) ) ;
2005-03-30 14:48:52 +04:00
plain_chunk . length = plain_chunk_size ;
plain_chunk . data = ndrpush - > data + plain_chunk_offset ;
2008-08-07 20:24:57 +04:00
if ( comp_chunk . length < 2 ) {
return ndr_pull_error ( ndrpull , NDR_ERR_COMPRESSION ,
" Bad MSZIP comp chunk size %u < 2 (PULL) " ,
( unsigned int ) comp_chunk . length ) ;
}
/* CK = Chris Kirmse, official Microsoft purloiner */
if ( comp_chunk . data [ 0 ] ! = ' C ' | |
comp_chunk . data [ 1 ] ! = ' K ' ) {
return ndr_pull_error ( ndrpull , NDR_ERR_COMPRESSION ,
" Bad MSZIP invalid prefix [%c%c] != [CK] " ,
comp_chunk . data [ 0 ] , comp_chunk . data [ 1 ] ) ;
}
z - > next_in = comp_chunk . data + 2 ;
z - > avail_in = comp_chunk . length - 2 ;
z - > total_in = 0 ;
z - > next_out = plain_chunk . data ;
z - > avail_out = plain_chunk . length ;
z - > total_out = 0 ;
if ( ! z - > opaque ) {
/* the first time we need to intialize completely */
z - > zalloc = ndr_zlib_alloc ;
z - > zfree = ndr_zlib_free ;
z - > opaque = ndrpull ;
z_ret = inflateInit2 ( z , - 15 ) ;
if ( z_ret ! = Z_OK ) {
return ndr_pull_error ( ndrpull , NDR_ERR_COMPRESSION ,
" Bad inflateInit2 error %s(%d) (PULL) " ,
zError ( z_ret ) , z_ret ) ;
}
}
/* call inflate untill we get Z_STREAM_END or an error */
while ( true ) {
z_ret = inflate ( z , Z_BLOCK ) ;
if ( z_ret ! = Z_OK ) break ;
}
if ( z_ret ! = Z_STREAM_END ) {
return ndr_pull_error ( ndrpull , NDR_ERR_COMPRESSION ,
" Bad inflate(Z_BLOCK) error %s(%d) (PULL) " ,
zError ( z_ret ) , z_ret ) ;
}
if ( z - > avail_in ) {
return ndr_pull_error ( ndrpull , NDR_ERR_COMPRESSION ,
" MSZIP not all avail_in[%u] bytes consumed (PULL) " ,
z - > avail_in ) ;
}
if ( z - > avail_out ) {
return ndr_pull_error ( ndrpull , NDR_ERR_COMPRESSION ,
" MSZIP not all avail_out[%u] bytes consumed (PULL) " ,
z - > avail_out ) ;
2005-03-25 16:40:17 +03:00
}
2005-03-29 12:10:31 +04:00
if ( ( plain_chunk_size < 0x00008000 ) | | ( ndrpull - > offset + 4 > = ndrpull - > data_size ) ) {
/* this is the last chunk */
2007-11-01 11:48:42 +03:00
* last = true ;
2005-03-29 12:10:31 +04:00
}
2005-03-25 16:40:17 +03:00
2008-09-05 22:18:07 +04:00
z_ret = inflateReset ( z ) ;
if ( z_ret ! = Z_OK ) {
return ndr_pull_error ( ndrpull , NDR_ERR_COMPRESSION ,
" Bad inflateReset error %s(%d) (PULL) " ,
zError ( z_ret ) , z_ret ) ;
}
z_ret = inflateSetDictionary ( z , plain_chunk . data , plain_chunk . length ) ;
if ( z_ret ! = Z_OK ) {
return ndr_pull_error ( ndrpull , NDR_ERR_COMPRESSION ,
" Bad inflateSetDictionary error %s(%d) (PULL) " ,
zError ( z_ret ) , z_ret ) ;
}
2007-11-09 21:24:10 +03:00
return NDR_ERR_SUCCESS ;
2005-03-29 12:10:31 +04:00
}
2005-03-25 16:40:17 +03:00
2008-08-07 20:26:45 +04:00
static enum ndr_err_code ndr_push_compression_mszip_chunk ( struct ndr_push * ndrpush ,
struct ndr_pull * ndrpull ,
z_stream * z ,
bool * last )
2005-03-30 14:48:52 +04:00
{
2008-08-20 17:48:00 +04:00
DATA_BLOB comp_chunk ;
uint32_t comp_chunk_size ;
uint32_t comp_chunk_size_offset ;
DATA_BLOB plain_chunk ;
uint32_t plain_chunk_size ;
uint32_t plain_chunk_offset ;
uint32_t max_plain_size = 0x00008000 ;
uint32_t max_comp_size = 0x00008000 + 2 + 12 /*TODO: what value do we really need here?*/ ;
uint32_t tmp_offset ;
int z_ret ;
plain_chunk_size = MIN ( max_plain_size , ndrpull - > data_size - ndrpull - > offset ) ;
plain_chunk_offset = ndrpull - > offset ;
NDR_CHECK ( ndr_pull_advance ( ndrpull , plain_chunk_size ) ) ;
plain_chunk . data = ndrpull - > data + plain_chunk_offset ;
plain_chunk . length = plain_chunk_size ;
if ( plain_chunk_size < max_plain_size ) {
* last = true ;
}
NDR_CHECK ( ndr_push_uint32 ( ndrpush , NDR_SCALARS , plain_chunk_size ) ) ;
comp_chunk_size_offset = ndrpush - > offset ;
NDR_CHECK ( ndr_push_uint32 ( ndrpush , NDR_SCALARS , 0xFEFEFEFE ) ) ;
NDR_CHECK ( ndr_push_expand ( ndrpush , max_comp_size ) ) ;
comp_chunk . data = ndrpush - > data + ndrpush - > offset ;
comp_chunk . length = max_comp_size ;
/* CK = Chris Kirmse, official Microsoft purloiner */
comp_chunk . data [ 0 ] = ' C ' ;
comp_chunk . data [ 1 ] = ' K ' ;
z - > next_in = plain_chunk . data ;
z - > avail_in = plain_chunk . length ;
z - > total_in = 0 ;
z - > next_out = comp_chunk . data + 2 ;
z - > avail_out = comp_chunk . length - 2 ;
z - > total_out = 0 ;
if ( ! z - > opaque ) {
/* the first time we need to intialize completely */
z - > zalloc = ndr_zlib_alloc ;
z - > zfree = ndr_zlib_free ;
z - > opaque = ndrpull ;
/* TODO: find how to trigger the same parameters windows uses */
z_ret = deflateInit2 ( z ,
Z_DEFAULT_COMPRESSION ,
Z_DEFLATED ,
- 15 ,
9 ,
Z_DEFAULT_STRATEGY ) ;
if ( z_ret ! = Z_OK ) {
return ndr_push_error ( ndrpush , NDR_ERR_COMPRESSION ,
" Bad deflateInit2 error %s(%d) (PUSH) " ,
zError ( z_ret ) , z_ret ) ;
}
}
/* call deflate untill we get Z_STREAM_END or an error */
while ( true ) {
z_ret = deflate ( z , Z_FINISH ) ;
if ( z_ret ! = Z_OK ) break ;
}
if ( z_ret ! = Z_STREAM_END ) {
return ndr_push_error ( ndrpush , NDR_ERR_COMPRESSION ,
" Bad delate(Z_BLOCK) error %s(%d) (PUSH) " ,
zError ( z_ret ) , z_ret ) ;
}
if ( z - > avail_in ) {
return ndr_push_error ( ndrpush , NDR_ERR_COMPRESSION ,
" MSZIP not all avail_in[%u] bytes consumed (PUSH) " ,
z - > avail_in ) ;
}
comp_chunk_size = 2 + z - > total_out ;
2008-09-06 18:16:00 +04:00
z_ret = deflateReset ( z ) ;
if ( z_ret ! = Z_OK ) {
return ndr_pull_error ( ndrpull , NDR_ERR_COMPRESSION ,
" Bad deflateReset error %s(%d) (PULL) " ,
zError ( z_ret ) , z_ret ) ;
}
z_ret = deflateSetDictionary ( z , plain_chunk . data , plain_chunk . length ) ;
if ( z_ret ! = Z_OK ) {
return ndr_pull_error ( ndrpull , NDR_ERR_COMPRESSION ,
" Bad deflateSetDictionary error %s(%d) (PULL) " ,
zError ( z_ret ) , z_ret ) ;
}
2008-08-20 17:48:00 +04:00
tmp_offset = ndrpush - > offset ;
ndrpush - > offset = comp_chunk_size_offset ;
NDR_CHECK ( ndr_push_uint32 ( ndrpush , NDR_SCALARS , comp_chunk_size ) ) ;
ndrpush - > offset = tmp_offset ;
2008-09-06 12:55:04 +04:00
DEBUG ( 9 , ( " MSZIP comp plain_chunk_size: %08X (%u) comp_chunk_size: %08X (%u) \n " ,
2008-10-20 00:37:27 +04:00
( unsigned int ) plain_chunk . length ,
( unsigned int ) plain_chunk . length ,
comp_chunk_size , comp_chunk_size ) ) ;
2008-09-06 18:16:00 +04:00
2008-08-20 17:48:00 +04:00
ndrpush - > offset + = comp_chunk_size ;
return NDR_ERR_SUCCESS ;
2005-10-10 16:10:10 +04:00
}
2007-11-09 21:24:10 +03:00
static enum ndr_err_code ndr_pull_compression_xpress_chunk ( struct ndr_pull * ndrpull ,
2007-11-01 11:48:42 +03:00
struct ndr_push * ndrpush ,
bool * last )
2005-10-10 16:10:10 +04:00
{
DATA_BLOB comp_chunk ;
2008-07-10 13:31:43 +04:00
DATA_BLOB plain_chunk ;
2005-10-10 16:10:10 +04:00
uint32_t comp_chunk_offset ;
2008-07-10 13:31:43 +04:00
uint32_t plain_chunk_offset ;
2005-10-10 16:10:10 +04:00
uint32_t comp_chunk_size ;
uint32_t plain_chunk_size ;
2008-09-07 20:52:29 +04:00
ssize_t ret ;
2005-10-10 16:10:10 +04:00
NDR_CHECK ( ndr_pull_uint32 ( ndrpull , NDR_SCALARS , & plain_chunk_size ) ) ;
if ( plain_chunk_size > 0x00010000 ) {
return ndr_pull_error ( ndrpull , NDR_ERR_COMPRESSION , " Bad XPRESS plain chunk size %08X > 0x00010000 (PULL) " ,
plain_chunk_size ) ;
}
NDR_CHECK ( ndr_pull_uint32 ( ndrpull , NDR_SCALARS , & comp_chunk_size ) ) ;
2008-07-10 13:31:43 +04:00
comp_chunk_offset = ndrpull - > offset ;
2005-10-10 16:10:10 +04:00
NDR_CHECK ( ndr_pull_advance ( ndrpull , comp_chunk_size ) ) ;
2008-07-10 13:31:43 +04:00
comp_chunk . length = comp_chunk_size ;
2005-10-10 16:10:10 +04:00
comp_chunk . data = ndrpull - > data + comp_chunk_offset ;
2008-07-10 13:31:43 +04:00
plain_chunk_offset = ndrpush - > offset ;
NDR_CHECK ( ndr_push_zero ( ndrpush , plain_chunk_size ) ) ;
plain_chunk . length = plain_chunk_size ;
plain_chunk . data = ndrpush - > data + plain_chunk_offset ;
2008-09-06 12:55:04 +04:00
DEBUG ( 9 , ( " XPRESS plain_chunk_size: %08X (%u) comp_chunk_size: %08X (%u) \n " ,
plain_chunk_size , plain_chunk_size , comp_chunk_size , comp_chunk_size ) ) ;
2005-10-10 16:10:10 +04:00
2008-07-10 13:31:43 +04:00
/* Uncompressing the buffer using LZ Xpress algorithm */
2008-09-07 20:52:29 +04:00
ret = lzxpress_decompress ( comp_chunk . data ,
comp_chunk . length ,
plain_chunk . data ,
plain_chunk . length ) ;
if ( ret < 0 ) {
return ndr_pull_error ( ndrpull , NDR_ERR_COMPRESSION ,
" XPRESS lzxpress_decompress() returned %d \n " ,
2008-10-20 00:37:27 +04:00
( int ) ret ) ;
2008-09-07 20:52:29 +04:00
}
plain_chunk . length = ret ;
2005-10-10 16:10:10 +04:00
if ( ( plain_chunk_size < 0x00010000 ) | | ( ndrpull - > offset + 4 > = ndrpull - > data_size ) ) {
/* this is the last chunk */
2007-11-01 11:48:42 +03:00
* last = true ;
2005-10-10 16:10:10 +04:00
}
2007-11-09 21:24:10 +03:00
return NDR_ERR_SUCCESS ;
2005-10-10 16:10:10 +04:00
}
2008-08-07 20:26:45 +04:00
static enum ndr_err_code ndr_push_compression_xpress_chunk ( struct ndr_push * ndrpush ,
struct ndr_pull * ndrpull ,
bool * last )
2008-08-19 12:29:40 +04:00
{
2008-08-21 00:12:51 +04:00
DATA_BLOB comp_chunk ;
uint32_t comp_chunk_size_offset ;
DATA_BLOB plain_chunk ;
uint32_t plain_chunk_size ;
uint32_t plain_chunk_offset ;
uint32_t max_plain_size = 0x00010000 ;
uint32_t max_comp_size = 0x00020000 + 2 ; /* TODO: use the correct value here */
uint32_t tmp_offset ;
ssize_t ret ;
plain_chunk_size = MIN ( max_plain_size , ndrpull - > data_size - ndrpull - > offset ) ;
plain_chunk_offset = ndrpull - > offset ;
NDR_CHECK ( ndr_pull_advance ( ndrpull , plain_chunk_size ) ) ;
plain_chunk . data = ndrpull - > data + plain_chunk_offset ;
plain_chunk . length = plain_chunk_size ;
if ( plain_chunk_size < max_plain_size ) {
* last = true ;
}
NDR_CHECK ( ndr_push_uint32 ( ndrpush , NDR_SCALARS , plain_chunk_size ) ) ;
comp_chunk_size_offset = ndrpush - > offset ;
NDR_CHECK ( ndr_push_uint32 ( ndrpush , NDR_SCALARS , 0xFEFEFEFE ) ) ;
NDR_CHECK ( ndr_push_expand ( ndrpush , max_comp_size ) ) ;
comp_chunk . data = ndrpush - > data + ndrpush - > offset ;
comp_chunk . length = max_comp_size ;
/* Compressing the buffer using LZ Xpress algorithm */
ret = lzxpress_compress ( plain_chunk . data ,
plain_chunk . length ,
comp_chunk . data ,
comp_chunk . length ) ;
if ( ret < 0 ) {
return ndr_pull_error ( ndrpull , NDR_ERR_COMPRESSION ,
" XPRESS lzxpress_compress() returned %d \n " ,
2008-10-20 00:37:27 +04:00
( int ) ret ) ;
2008-08-21 00:12:51 +04:00
}
comp_chunk . length = ret ;
tmp_offset = ndrpush - > offset ;
ndrpush - > offset = comp_chunk_size_offset ;
NDR_CHECK ( ndr_push_uint32 ( ndrpush , NDR_SCALARS , comp_chunk . length ) ) ;
ndrpush - > offset = tmp_offset ;
ndrpush - > offset + = comp_chunk . length ;
return NDR_ERR_SUCCESS ;
2008-08-19 12:29:40 +04:00
}
/*
handle compressed subcontext buffers , which in midl land are user - marshalled , but
we use magic in pidl to make them easier to cope with
*/
enum ndr_err_code ndr_pull_compression_start ( struct ndr_pull * subndr ,
struct ndr_pull * * _comndr ,
enum ndr_compression_alg compression_alg ,
ssize_t decompressed_len )
2005-10-10 16:10:10 +04:00
{
struct ndr_push * ndrpush ;
struct ndr_pull * comndr ;
DATA_BLOB uncompressed ;
2007-11-01 11:48:42 +03:00
bool last = false ;
2008-08-19 12:29:40 +04:00
z_stream z ;
2005-10-10 16:10:10 +04:00
2007-12-14 00:46:23 +03:00
ndrpush = ndr_push_init_ctx ( subndr , subndr - > iconv_convenience ) ;
2007-11-09 21:24:10 +03:00
NDR_ERR_HAVE_NO_MEMORY ( ndrpush ) ;
2005-10-10 16:10:10 +04:00
2008-08-19 12:29:40 +04:00
switch ( compression_alg ) {
case NDR_COMPRESSION_MSZIP :
ZERO_STRUCT ( z ) ;
while ( ! last ) {
NDR_CHECK ( ndr_pull_compression_mszip_chunk ( subndr , ndrpush , & z , & last ) ) ;
}
break ;
case NDR_COMPRESSION_XPRESS :
while ( ! last ) {
NDR_CHECK ( ndr_pull_compression_xpress_chunk ( subndr , ndrpush , & last ) ) ;
}
break ;
default :
return ndr_pull_error ( subndr , NDR_ERR_COMPRESSION , " Bad compression algorithm %d (PULL) " ,
compression_alg ) ;
2005-10-10 16:10:10 +04:00
}
uncompressed = ndr_push_blob ( ndrpush ) ;
2008-07-10 13:31:43 +04:00
if ( uncompressed . length ! = decompressed_len ) {
return ndr_pull_error ( subndr , NDR_ERR_COMPRESSION ,
2008-08-19 12:29:40 +04:00
" Bad uncompressed_len [%u] != [%u](0x%08X) (PULL) " ,
2008-07-10 13:31:43 +04:00
( int ) uncompressed . length ,
( int ) decompressed_len ,
( int ) decompressed_len ) ;
}
2005-10-10 16:10:10 +04:00
comndr = talloc_zero ( subndr , struct ndr_pull ) ;
2007-11-09 21:24:10 +03:00
NDR_ERR_HAVE_NO_MEMORY ( comndr ) ;
2005-10-10 16:10:10 +04:00
comndr - > flags = subndr - > flags ;
comndr - > current_mem_ctx = subndr - > current_mem_ctx ;
comndr - > data = uncompressed . data ;
comndr - > data_size = uncompressed . length ;
comndr - > offset = 0 ;
2008-01-21 12:56:27 +03:00
comndr - > iconv_convenience = talloc_reference ( comndr , subndr - > iconv_convenience ) ;
2005-10-10 16:10:10 +04:00
* _comndr = comndr ;
2007-11-09 21:24:10 +03:00
return NDR_ERR_SUCCESS ;
2005-10-10 16:10:10 +04:00
}
2007-11-09 21:24:10 +03:00
enum ndr_err_code ndr_pull_compression_end ( struct ndr_pull * subndr ,
2005-08-18 04:45:19 +04:00
struct ndr_pull * comndr ,
enum ndr_compression_alg compression_alg ,
ssize_t decompressed_len )
{
2007-11-09 21:24:10 +03:00
return NDR_ERR_SUCCESS ;
2005-08-18 04:45:19 +04:00
}
2005-03-25 16:40:17 +03:00
/*
push a compressed subcontext
*/
2007-11-09 21:24:10 +03:00
enum ndr_err_code ndr_push_compression_start ( struct ndr_push * subndr ,
2008-08-07 20:26:45 +04:00
struct ndr_push * * _uncomndr ,
2005-08-18 04:45:19 +04:00
enum ndr_compression_alg compression_alg ,
ssize_t decompressed_len )
2005-03-25 16:40:17 +03:00
{
2008-08-07 20:26:45 +04:00
struct ndr_push * uncomndr ;
2005-08-18 04:45:19 +04:00
2008-08-07 20:26:45 +04:00
switch ( compression_alg ) {
case NDR_COMPRESSION_MSZIP :
case NDR_COMPRESSION_XPRESS :
break ;
default :
return ndr_push_error ( subndr , NDR_ERR_COMPRESSION ,
" Bad compression algorithm %d (PUSH) " ,
compression_alg ) ;
}
2005-03-25 16:40:17 +03:00
2008-08-07 20:26:45 +04:00
uncomndr = ndr_push_init_ctx ( subndr , subndr - > iconv_convenience ) ;
NDR_ERR_HAVE_NO_MEMORY ( uncomndr ) ;
uncomndr - > flags = subndr - > flags ;
* _uncomndr = uncomndr ;
2007-11-09 21:24:10 +03:00
return NDR_ERR_SUCCESS ;
2005-08-18 04:45:19 +04:00
}
/*
push a compressed subcontext
*/
2007-11-09 21:24:10 +03:00
enum ndr_err_code ndr_push_compression_end ( struct ndr_push * subndr ,
2008-08-07 20:26:45 +04:00
struct ndr_push * uncomndr ,
2005-08-18 04:45:19 +04:00
enum ndr_compression_alg compression_alg ,
ssize_t decompressed_len )
{
2008-08-07 20:26:45 +04:00
struct ndr_pull * ndrpull ;
bool last = false ;
z_stream z ;
ndrpull = talloc_zero ( uncomndr , struct ndr_pull ) ;
NDR_ERR_HAVE_NO_MEMORY ( ndrpull ) ;
ndrpull - > flags = uncomndr - > flags ;
ndrpull - > data = uncomndr - > data ;
ndrpull - > data_size = uncomndr - > offset ;
ndrpull - > offset = 0 ;
ndrpull - > iconv_convenience = talloc_reference ( ndrpull , subndr - > iconv_convenience ) ;
2005-03-25 16:40:17 +03:00
switch ( compression_alg ) {
2005-03-30 14:48:52 +04:00
case NDR_COMPRESSION_MSZIP :
2008-08-07 20:26:45 +04:00
ZERO_STRUCT ( z ) ;
while ( ! last ) {
NDR_CHECK ( ndr_push_compression_mszip_chunk ( subndr , ndrpull , & z , & last ) ) ;
}
break ;
2005-10-10 16:10:10 +04:00
case NDR_COMPRESSION_XPRESS :
2008-08-07 20:26:45 +04:00
while ( ! last ) {
NDR_CHECK ( ndr_push_compression_xpress_chunk ( subndr , ndrpull , & last ) ) ;
}
break ;
2005-03-25 16:40:17 +03:00
default :
return ndr_push_error ( subndr , NDR_ERR_COMPRESSION , " Bad compression algorithm %d (PUSH) " ,
compression_alg ) ;
}
2008-08-07 20:26:45 +04:00
talloc_free ( uncomndr ) ;
2007-11-09 21:24:10 +03:00
return NDR_ERR_SUCCESS ;
2005-03-25 16:40:17 +03:00
}