2003-10-30 11:32:26 +03:00
/*
Unix SMB / CIFS implementation .
2003-11-03 09:22:45 +03:00
2003-10-30 11:32:26 +03:00
libndr interface
2003-11-03 09:22:45 +03:00
2003-10-30 11:32:26 +03:00
Copyright ( C ) Andrew Tridgell 2003
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
the Free Software Foundation ; either version 2 of the License , or
( 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
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
/*
2003-11-03 09:22:45 +03:00
this provides the core routines for NDR parsing functions
see http : //www.opengroup.org/onlinepubs/9629399/chap14.htm for details
of NDR encoding rules
2003-10-30 11:32:26 +03:00
*/
# include "includes.h"
2006-03-18 18:42:57 +03:00
# include "librpc/ndr/libndr.h"
2006-08-30 15:29:34 +04:00
# include "lib/util/dlinklist.h"
2006-03-18 18:42:57 +03:00
# include "librpc/gen_ndr/dcerpc.h"
2003-10-30 11:32:26 +03:00
2003-11-05 02:12:44 +03:00
# define NDR_BASE_MARSHALL_SIZE 1024
2005-12-27 19:47:09 +03:00
/* this guid indicates NDR encoding in a protocol tower */
const struct dcerpc_syntax_id ndr_transfer_syntax = {
{ 0x8a885d04 , 0x1ceb , 0x11c9 , { 0x9f , 0xe8 } , { 0x08 , 0x00 , 0x2b , 0x10 , 0x48 , 0x60 } } ,
2
} ;
const struct dcerpc_syntax_id ndr64_transfer_syntax = {
{ 0x71710533 , 0xbeba , 0x4937 , { 0x83 , 0x19 } , { 0xb5 , 0xdb , 0xef , 0x9c , 0xcc , 0x36 } } ,
1
} ;
2003-11-23 09:28:12 +03:00
/*
work out the number of bytes needed to align on a n byte boundary
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ size_t ndr_align_size ( uint32_t offset , size_t n )
2003-11-23 09:28:12 +03:00
{
if ( ( offset & ( n - 1 ) ) = = 0 ) return 0 ;
return n - ( offset & ( n - 1 ) ) ;
}
2003-10-30 11:32:26 +03:00
/*
initialise a ndr parse structure from a data blob
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ struct ndr_pull * ndr_pull_init_blob ( const DATA_BLOB * blob , TALLOC_CTX * mem_ctx )
2003-10-30 11:32:26 +03:00
{
2003-11-03 09:22:45 +03:00
struct ndr_pull * ndr ;
2003-10-30 11:32:26 +03:00
2005-01-27 10:08:20 +03:00
ndr = talloc_zero ( mem_ctx , struct ndr_pull ) ;
2003-10-30 11:32:26 +03:00
if ( ! ndr ) return NULL ;
2005-08-18 05:24:08 +04:00
ndr - > current_mem_ctx = mem_ctx ;
2003-10-30 11:32:26 +03:00
ndr - > data = blob - > data ;
ndr - > data_size = blob - > length ;
return ndr ;
}
/*
advance by ' size ' bytes
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ NTSTATUS ndr_pull_advance ( struct ndr_pull * ndr , uint32_t size )
2003-10-30 11:32:26 +03:00
{
ndr - > offset + = size ;
if ( ndr - > offset > ndr - > data_size ) {
2003-11-22 11:11:32 +03:00
return ndr_pull_error ( ndr , NDR_ERR_BUFSIZE ,
" ndr_pull_advance by %u failed " ,
size ) ;
2003-10-30 11:32:26 +03:00
}
return NT_STATUS_OK ;
}
/*
set the parse offset to ' ofs '
*/
2005-05-16 00:16:26 +04:00
static NTSTATUS ndr_pull_set_offset ( struct ndr_pull * ndr , uint32_t ofs )
2003-10-30 11:32:26 +03:00
{
ndr - > offset = ofs ;
if ( ndr - > offset > ndr - > data_size ) {
2003-11-22 11:11:32 +03:00
return ndr_pull_error ( ndr , NDR_ERR_BUFSIZE ,
" ndr_pull_set_offset %u failed " ,
ofs ) ;
2003-10-30 11:32:26 +03:00
}
return NT_STATUS_OK ;
}
/* save the offset/size of the current ndr state */
2006-03-05 20:15:19 +03:00
_PUBLIC_ void ndr_pull_save ( struct ndr_pull * ndr , struct ndr_pull_save * save )
2003-10-30 11:32:26 +03:00
{
save - > offset = ndr - > offset ;
save - > data_size = ndr - > data_size ;
}
/* restore the size/offset of a ndr structure */
2006-03-05 20:15:19 +03:00
_PUBLIC_ void ndr_pull_restore ( struct ndr_pull * ndr , struct ndr_pull_save * save )
2003-10-30 11:32:26 +03:00
{
ndr - > offset = save - > offset ;
ndr - > data_size = save - > data_size ;
}
2003-11-03 09:22:45 +03:00
/* create a ndr_push structure, ready for some marshalling */
2006-03-05 20:15:19 +03:00
_PUBLIC_ struct ndr_push * ndr_push_init_ctx ( TALLOC_CTX * mem_ctx )
2003-11-03 09:22:45 +03:00
{
struct ndr_push * ndr ;
2005-01-27 10:08:20 +03:00
ndr = talloc_zero ( mem_ctx , struct ndr_push ) ;
2003-11-03 09:22:45 +03:00
if ( ! ndr ) {
return NULL ;
}
ndr - > flags = 0 ;
ndr - > alloc_size = NDR_BASE_MARSHALL_SIZE ;
2005-01-27 10:08:20 +03:00
ndr - > data = talloc_array ( ndr , uint8_t , ndr - > alloc_size ) ;
2003-11-03 09:22:45 +03:00
if ( ! ndr - > data ) {
return NULL ;
}
2004-08-12 09:15:41 +04:00
2003-11-03 09:22:45 +03:00
return ndr ;
}
/* return a DATA_BLOB structure for the current ndr_push marshalled data */
2006-03-05 20:15:19 +03:00
_PUBLIC_ DATA_BLOB ndr_push_blob ( struct ndr_push * ndr )
2003-11-03 09:22:45 +03:00
{
DATA_BLOB blob ;
blob . data = ndr - > data ;
blob . length = ndr - > offset ;
2005-07-17 13:13:05 +04:00
if ( ndr - > alloc_size > ndr - > offset ) {
ndr - > data [ ndr - > offset ] = 0 ;
}
2003-11-03 09:22:45 +03:00
return blob ;
}
/*
expand the available space in the buffer to ' size '
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ NTSTATUS ndr_push_expand ( struct ndr_push * ndr , uint32_t size )
2003-11-03 09:22:45 +03:00
{
2005-07-17 13:08:19 +04:00
if ( ndr - > alloc_size > size ) {
2003-11-03 09:22:45 +03:00
return NT_STATUS_OK ;
}
2003-11-12 08:34:21 +03:00
ndr - > alloc_size + = NDR_BASE_MARSHALL_SIZE ;
2005-07-17 13:08:19 +04:00
if ( size + 1 > ndr - > alloc_size ) {
ndr - > alloc_size = size + 1 ;
2003-11-12 08:34:21 +03:00
}
2005-01-07 07:39:16 +03:00
ndr - > data = talloc_realloc ( ndr , ndr - > data , uint8_t , ndr - > alloc_size ) ;
2003-11-03 09:22:45 +03:00
if ( ! ndr - > data ) {
2003-11-22 11:11:32 +03:00
return ndr_push_error ( ndr , NDR_ERR_ALLOC , " Failed to push_expand to %u " ,
ndr - > alloc_size ) ;
2003-11-03 09:22:45 +03:00
}
return NT_STATUS_OK ;
}
2006-03-05 20:15:19 +03:00
_PUBLIC_ void ndr_print_debug_helper ( struct ndr_print * ndr , const char * format , . . . ) _PRINTF_ATTRIBUTE ( 2 , 3 )
2003-11-11 07:04:36 +03:00
{
va_list ap ;
char * s = NULL ;
int i ;
va_start ( ap , format ) ;
vasprintf ( & s , format , ap ) ;
va_end ( ap ) ;
for ( i = 0 ; i < ndr - > depth ; i + + ) {
2003-11-21 05:50:40 +03:00
DEBUG ( 0 , ( " " ) ) ;
2003-11-11 07:04:36 +03:00
}
2003-11-21 05:50:40 +03:00
DEBUG ( 0 , ( " %s \n " , s ) ) ;
2003-11-11 07:04:36 +03:00
free ( s ) ;
}
2006-05-16 04:37:13 +04:00
_PUBLIC_ void ndr_print_string_helper ( struct ndr_print * ndr , const char * format , . . . ) _PRINTF_ATTRIBUTE ( 2 , 3 )
2005-12-31 07:29:34 +03:00
{
va_list ap ;
int i ;
for ( i = 0 ; i < ndr - > depth ; i + + ) {
2006-05-04 15:01:10 +04:00
ndr - > private_data = talloc_asprintf_append ( ndr - > private_data , " " ) ;
2005-12-31 07:29:34 +03:00
}
va_start ( ap , format ) ;
2006-05-04 15:01:10 +04:00
ndr - > private_data = talloc_vasprintf_append ( ndr - > private_data , format , ap ) ;
2005-12-31 07:29:34 +03:00
va_end ( ap ) ;
2006-05-04 15:01:10 +04:00
ndr - > private_data = talloc_asprintf_append ( ndr - > private_data , " \n " ) ;
2005-12-31 07:29:34 +03:00
}
2003-11-11 07:04:36 +03:00
/*
a useful helper function for printing idl structures via DEBUG ( )
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ void ndr_print_debug ( ndr_print_fn_t fn , const char * name , void * ptr )
2003-11-11 07:04:36 +03:00
{
2004-08-21 11:43:29 +04:00
struct ndr_print * ndr ;
2003-11-11 07:04:36 +03:00
2005-04-04 09:52:53 +04:00
ndr = talloc_zero ( NULL , struct ndr_print ) ;
2004-08-21 11:43:29 +04:00
if ( ! ndr ) return ;
ndr - > print = ndr_print_debug_helper ;
ndr - > depth = 1 ;
ndr - > flags = 0 ;
fn ( ndr , name , ptr ) ;
talloc_free ( ndr ) ;
2003-11-11 07:04:36 +03:00
}
2003-11-11 07:38:51 +03:00
2005-05-11 03:33:56 +04:00
/*
a useful helper function for printing idl unions via DEBUG ( )
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ void ndr_print_union_debug ( ndr_print_fn_t fn , const char * name , uint32_t level , void * ptr )
2005-05-11 03:33:56 +04:00
{
struct ndr_print * ndr ;
ndr = talloc_zero ( NULL , struct ndr_print ) ;
if ( ! ndr ) return ;
ndr - > print = ndr_print_debug_helper ;
ndr - > depth = 1 ;
ndr - > flags = 0 ;
ndr_print_set_switch_value ( ndr , ptr , level ) ;
fn ( ndr , name , ptr ) ;
talloc_free ( ndr ) ;
}
2003-11-17 14:55:56 +03:00
/*
a useful helper function for printing idl function calls via DEBUG ( )
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ void ndr_print_function_debug ( ndr_print_function_t fn , const char * name , int flags , void * ptr )
2003-11-17 14:55:56 +03:00
{
2004-08-21 11:43:29 +04:00
struct ndr_print * ndr ;
2003-11-17 14:55:56 +03:00
2005-04-04 09:52:53 +04:00
ndr = talloc_zero ( NULL , struct ndr_print ) ;
2004-08-21 11:43:29 +04:00
if ( ! ndr ) return ;
ndr - > print = ndr_print_debug_helper ;
ndr - > depth = 1 ;
ndr - > flags = 0 ;
fn ( ndr , name , flags , ptr ) ;
talloc_free ( ndr ) ;
2003-11-17 14:55:56 +03:00
}
2006-05-15 18:38:04 +04:00
/*
a useful helper function for printing idl structures to a string
*/
_PUBLIC_ char * ndr_print_struct_string ( TALLOC_CTX * mem_ctx , ndr_print_fn_t fn , const char * name , void * ptr )
{
struct ndr_print * ndr ;
char * ret = NULL ;
ndr = talloc_zero ( mem_ctx , struct ndr_print ) ;
if ( ! ndr ) return NULL ;
ndr - > private_data = talloc_strdup ( ndr , " " ) ;
if ( ! ndr - > private_data ) {
goto failed ;
}
ndr - > print = ndr_print_string_helper ;
ndr - > depth = 1 ;
ndr - > flags = 0 ;
fn ( ndr , name , ptr ) ;
ret = talloc_steal ( mem_ctx , ndr - > private_data ) ;
failed :
talloc_free ( ndr ) ;
return ret ;
}
/*
a useful helper function for printing idl unions to a string
*/
_PUBLIC_ char * ndr_print_union_string ( TALLOC_CTX * mem_ctx , ndr_print_fn_t fn , const char * name , uint32_t level , void * ptr )
{
struct ndr_print * ndr ;
char * ret = NULL ;
ndr = talloc_zero ( mem_ctx , struct ndr_print ) ;
if ( ! ndr ) return NULL ;
ndr - > private_data = talloc_strdup ( ndr , " " ) ;
if ( ! ndr - > private_data ) {
goto failed ;
}
ndr - > print = ndr_print_string_helper ;
ndr - > depth = 1 ;
ndr - > flags = 0 ;
ndr_print_set_switch_value ( ndr , ptr , level ) ;
fn ( ndr , name , ptr ) ;
ret = talloc_steal ( mem_ctx , ndr - > private_data ) ;
failed :
talloc_free ( ndr ) ;
return ret ;
}
2005-12-31 07:29:34 +03:00
/*
a useful helper function for printing idl function calls to a string
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ char * ndr_print_function_string ( TALLOC_CTX * mem_ctx ,
2005-12-31 07:29:34 +03:00
ndr_print_function_t fn , const char * name ,
int flags , void * ptr )
{
struct ndr_print * ndr ;
2006-01-11 23:38:10 +03:00
char * ret = NULL ;
2005-12-31 07:29:34 +03:00
ndr = talloc_zero ( mem_ctx , struct ndr_print ) ;
if ( ! ndr ) return NULL ;
2006-05-04 15:01:10 +04:00
ndr - > private_data = talloc_strdup ( ndr , " " ) ;
if ( ! ndr - > private_data ) {
2006-01-11 23:38:10 +03:00
goto failed ;
}
2005-12-31 07:29:34 +03:00
ndr - > print = ndr_print_string_helper ;
ndr - > depth = 1 ;
ndr - > flags = 0 ;
fn ( ndr , name , flags , ptr ) ;
2006-05-04 15:01:10 +04:00
ret = talloc_steal ( mem_ctx , ndr - > private_data ) ;
2006-01-11 23:38:10 +03:00
failed :
2005-12-31 07:29:34 +03:00
talloc_free ( ndr ) ;
2006-01-10 00:59:42 +03:00
return ret ;
2005-12-31 07:29:34 +03:00
}
2006-03-05 20:15:19 +03:00
_PUBLIC_ void ndr_set_flags ( uint32_t * pflags , uint32_t new_flags )
2004-10-14 13:07:41 +04:00
{
/* the big/little endian flags are inter-dependent */
if ( new_flags & LIBNDR_FLAG_LITTLE_ENDIAN ) {
( * pflags ) & = ~ LIBNDR_FLAG_BIGENDIAN ;
}
if ( new_flags & LIBNDR_FLAG_BIGENDIAN ) {
( * pflags ) & = ~ LIBNDR_FLAG_LITTLE_ENDIAN ;
}
2005-09-10 12:46:28 +04:00
if ( new_flags & LIBNDR_FLAG_REMAINING ) {
( * pflags ) & = ~ LIBNDR_ALIGN_FLAGS ;
}
if ( new_flags & LIBNDR_ALIGN_FLAGS ) {
( * pflags ) & = ~ LIBNDR_FLAG_REMAINING ;
}
2004-10-14 13:07:41 +04:00
( * pflags ) | = new_flags ;
}
2003-11-22 11:11:32 +03:00
2006-03-22 17:33:06 +03:00
static NTSTATUS ndr_map_error ( enum ndr_err_code ndr_err )
2003-11-22 11:11:32 +03:00
{
2006-03-22 17:33:06 +03:00
switch ( ndr_err ) {
2003-11-22 11:11:32 +03:00
case NDR_ERR_BUFSIZE :
return NT_STATUS_BUFFER_TOO_SMALL ;
2004-12-09 10:05:00 +03:00
case NDR_ERR_TOKEN :
return NT_STATUS_INTERNAL_ERROR ;
2003-11-22 11:11:32 +03:00
case NDR_ERR_ALLOC :
return NT_STATUS_NO_MEMORY ;
2004-12-09 10:05:00 +03:00
case NDR_ERR_ARRAY_SIZE :
return NT_STATUS_ARRAY_BOUNDS_EXCEEDED ;
2004-10-28 16:46:59 +04:00
default :
break ;
2003-11-22 11:11:32 +03:00
}
r6973: Merge new version of pidl into the main SAMBA_4_0 branch.
The main difference in this new version is the extra data structure generated
between the IDL data structure and the NDR parser:
IDL -> NDR -> { ndr_parser, ndr_header, eparser, etc }
This makes the ndr_parser.pm internals much more sane.
Other changes include:
- Remove unnecessary calls with NDR_BUFFERS (for example, GUID doesn't have any buffers, just scalars) as well as some (unnecessary) nested setting of flags.
- Parse array loops in the C code rather then calling ndr_pull_array(). This allows us to have, for example, arrays of pointers or arrays of pointers to arrays, etc..
- Use if() {} rather then if () goto foo; everywhere
- NDR_IN no longer implies LIBNDR_FLAG_REF_ALLOC
- By default, top level pointers are now "ref" (as is the default in
most other IDL compilers). This can be overridden using the
default_pointer_top() property.
- initial work on new ethereal parser generators by Alan DeKok and me
- pidl now writes errors in the standard format used by compilers, which
is parsable by most editors
- ability to warn about the fact that pidl extension(s) have been used,
useful for making sure IDL files work with other IDL compilers.
oh, and there's probably some other things I can't think of right now..
(This used to be commit 13cf227615f6b9e0e5fa62e59197024410254f01)
2005-05-25 17:50:27 +04:00
/* we should map all error codes to different status codes */
2003-11-22 11:11:32 +03:00
return NT_STATUS_INVALID_PARAMETER ;
}
2003-11-13 12:26:53 +03:00
/*
return and possibly log an NDR error
*/
2006-03-22 17:33:06 +03:00
_PUBLIC_ NTSTATUS ndr_pull_error ( struct ndr_pull * ndr ,
enum ndr_err_code ndr_err ,
const char * format , . . . ) _PRINTF_ATTRIBUTE ( 3 , 4 )
2003-11-13 12:26:53 +03:00
{
char * s = NULL ;
va_list ap ;
va_start ( ap , format ) ;
vasprintf ( & s , format , ap ) ;
va_end ( ap ) ;
2006-03-22 17:33:06 +03:00
DEBUG ( 3 , ( " ndr_pull_error(%u): %s \n " , ndr_err , s ) ) ;
2003-11-13 12:26:53 +03:00
free ( s ) ;
2003-11-22 11:11:32 +03:00
2006-03-22 17:33:06 +03:00
return ndr_map_error ( ndr_err ) ;
2003-11-13 12:26:53 +03:00
}
2003-11-14 10:20:46 +03:00
/*
return and possibly log an NDR error
*/
2006-03-22 17:33:06 +03:00
_PUBLIC_ NTSTATUS ndr_push_error ( struct ndr_push * ndr ,
enum ndr_err_code ndr_err ,
const char * format , . . . ) _PRINTF_ATTRIBUTE ( 3 , 4 )
2003-11-14 10:20:46 +03:00
{
char * s = NULL ;
va_list ap ;
va_start ( ap , format ) ;
vasprintf ( & s , format , ap ) ;
va_end ( ap ) ;
2006-03-22 17:33:06 +03:00
DEBUG ( 3 , ( " ndr_push_error(%u): %s \n " , ndr_err , s ) ) ;
2003-11-14 10:20:46 +03:00
free ( s ) ;
2003-11-22 11:11:32 +03:00
2006-03-22 17:33:06 +03:00
return ndr_map_error ( ndr_err ) ;
2003-11-14 10:20:46 +03:00
}
2003-11-16 09:00:15 +03:00
2003-11-21 16:14:17 +03:00
/*
handle subcontext buffers , which in midl land are user - marshalled , but
we use magic in pidl to make them easier to cope with
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ NTSTATUS ndr_pull_subcontext_start ( struct ndr_pull * ndr ,
2005-08-18 04:45:19 +04:00
struct ndr_pull * * _subndr ,
size_t header_size ,
ssize_t size_is )
2003-11-21 16:14:17 +03:00
{
2005-08-18 04:45:19 +04:00
struct ndr_pull * subndr ;
uint32_t r_content_size ;
2005-01-29 06:17:14 +03:00
2005-03-15 17:33:38 +03:00
switch ( header_size ) {
2003-11-21 16:14:17 +03:00
case 0 : {
2005-03-15 17:33:38 +03:00
uint32_t content_size = ndr - > data_size - ndr - > offset ;
if ( size_is > = 0 ) {
content_size = size_is ;
}
2005-08-18 04:45:19 +04:00
r_content_size = content_size ;
2003-11-21 16:14:17 +03:00
break ;
}
case 2 : {
2005-03-15 17:33:38 +03:00
uint16_t content_size ;
NDR_CHECK ( ndr_pull_uint16 ( ndr , NDR_SCALARS , & content_size ) ) ;
if ( size_is > = 0 & & size_is ! = content_size ) {
return ndr_pull_error ( ndr , NDR_ERR_SUBCONTEXT , " Bad subcontext (PULL) size_is(%d) mismatch content_size %d " ,
2005-07-17 13:08:19 +04:00
( int ) size_is , ( int ) content_size ) ;
2005-03-15 17:33:38 +03:00
}
2005-08-18 04:45:19 +04:00
r_content_size = content_size ;
2003-11-21 16:14:17 +03:00
break ;
}
case 4 : {
2005-03-15 17:33:38 +03:00
uint32_t content_size ;
NDR_CHECK ( ndr_pull_uint32 ( ndr , NDR_SCALARS , & content_size ) ) ;
if ( size_is > = 0 & & size_is ! = content_size ) {
return ndr_pull_error ( ndr , NDR_ERR_SUBCONTEXT , " Bad subcontext (PULL) size_is(%d) mismatch content_size %d " ,
2005-07-17 13:08:19 +04:00
( int ) size_is , ( int ) content_size ) ;
2005-03-15 17:33:38 +03:00
}
2005-08-18 04:45:19 +04:00
r_content_size = content_size ;
2003-11-21 16:14:17 +03:00
break ;
}
default :
2005-03-15 17:33:38 +03:00
return ndr_pull_error ( ndr , NDR_ERR_SUBCONTEXT , " Bad subcontext (PULL) header_size %d " ,
2005-07-17 13:08:19 +04:00
( int ) header_size ) ;
2003-11-21 16:14:17 +03:00
}
2005-08-18 04:45:19 +04:00
NDR_PULL_NEED_BYTES ( ndr , r_content_size ) ;
subndr = talloc_zero ( ndr , struct ndr_pull ) ;
NT_STATUS_HAVE_NO_MEMORY ( subndr ) ;
subndr - > flags = ndr - > flags ;
2005-08-18 05:24:08 +04:00
subndr - > current_mem_ctx = ndr - > current_mem_ctx ;
2005-08-18 04:45:19 +04:00
subndr - > data = ndr - > data + ndr - > offset ;
subndr - > offset = 0 ;
subndr - > data_size = r_content_size ;
* _subndr = subndr ;
return NT_STATUS_OK ;
}
2006-03-05 20:15:19 +03:00
_PUBLIC_ NTSTATUS ndr_pull_subcontext_end ( struct ndr_pull * ndr ,
2005-08-18 04:45:19 +04:00
struct ndr_pull * subndr ,
size_t header_size ,
ssize_t size_is )
{
uint32_t advance ;
if ( size_is > = 0 ) {
advance = size_is ;
} else if ( header_size > 0 ) {
advance = subndr - > data_size ;
} else {
advance = subndr - > offset ;
}
NDR_CHECK ( ndr_pull_advance ( ndr , advance ) ) ;
return NT_STATUS_OK ;
}
2006-03-05 20:15:19 +03:00
_PUBLIC_ NTSTATUS ndr_push_subcontext_start ( struct ndr_push * ndr ,
2005-08-18 04:45:19 +04:00
struct ndr_push * * _subndr ,
size_t header_size ,
ssize_t size_is )
{
struct ndr_push * subndr ;
subndr = ndr_push_init_ctx ( ndr ) ;
NT_STATUS_HAVE_NO_MEMORY ( subndr ) ;
subndr - > flags = ndr - > flags ;
* _subndr = subndr ;
2003-11-21 16:14:17 +03:00
return NT_STATUS_OK ;
}
2003-11-22 11:11:32 +03:00
/*
push a subcontext header
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ NTSTATUS ndr_push_subcontext_end ( struct ndr_push * ndr ,
2005-08-18 04:45:19 +04:00
struct ndr_push * subndr ,
size_t header_size ,
ssize_t size_is )
2003-11-22 11:11:32 +03:00
{
2005-03-15 17:33:38 +03:00
if ( size_is > = 0 ) {
2005-08-18 04:45:19 +04:00
ssize_t padding_len = size_is - subndr - > offset ;
2005-03-15 17:33:38 +03:00
if ( padding_len > 0 ) {
2005-08-18 04:45:19 +04:00
NDR_CHECK ( ndr_push_zero ( subndr , padding_len ) ) ;
2005-03-15 17:33:38 +03:00
} else if ( padding_len < 0 ) {
return ndr_push_error ( ndr , NDR_ERR_SUBCONTEXT , " Bad subcontext (PUSH) content_size %d is larger than size_is(%d) " ,
2005-08-18 04:45:19 +04:00
( int ) subndr - > offset , ( int ) size_is ) ;
2005-03-15 17:33:38 +03:00
}
}
switch ( header_size ) {
2003-11-22 11:11:32 +03:00
case 0 :
break ;
case 2 :
2005-08-18 04:45:19 +04:00
NDR_CHECK ( ndr_push_uint16 ( ndr , NDR_SCALARS , subndr - > offset ) ) ;
2003-11-22 11:11:32 +03:00
break ;
case 4 :
2005-08-18 04:45:19 +04:00
NDR_CHECK ( ndr_push_uint32 ( ndr , NDR_SCALARS , subndr - > offset ) ) ;
2003-11-22 11:11:32 +03:00
break ;
default :
2005-03-15 17:33:38 +03:00
return ndr_push_error ( ndr , NDR_ERR_SUBCONTEXT , " Bad subcontext header size %d " ,
2005-07-17 13:08:19 +04:00
( int ) header_size ) ;
2003-11-22 11:11:32 +03:00
}
2005-08-18 04:45:19 +04:00
NDR_CHECK ( ndr_push_bytes ( ndr , subndr - > data , subndr - > offset ) ) ;
2003-11-22 11:11:32 +03:00
return NT_STATUS_OK ;
}
2004-08-12 09:15:41 +04:00
/*
store a token in the ndr context , for later retrieval
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ NTSTATUS ndr_token_store ( TALLOC_CTX * mem_ctx ,
2005-07-07 23:13:32 +04:00
struct ndr_token_list * * list ,
const void * key ,
uint32_t value )
2004-08-12 09:15:41 +04:00
{
struct ndr_token_list * tok ;
2005-01-27 10:08:20 +03:00
tok = talloc ( mem_ctx , struct ndr_token_list ) ;
2004-08-12 09:15:41 +04:00
if ( tok = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
tok - > key = key ;
tok - > value = value ;
DLIST_ADD ( ( * list ) , tok ) ;
return NT_STATUS_OK ;
}
2003-11-16 16:49:14 +03:00
/*
2005-07-07 23:13:32 +04:00
retrieve a token from a ndr context , using cmp_fn to match the tokens
2003-11-16 16:49:14 +03:00
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ NTSTATUS ndr_token_retrieve_cmp_fn ( struct ndr_token_list * * list , const void * key , uint32_t * v ,
2005-07-07 23:13:32 +04:00
comparison_fn_t _cmp_fn , BOOL _remove_tok )
2003-11-16 16:49:14 +03:00
{
2004-08-12 09:15:41 +04:00
struct ndr_token_list * tok ;
for ( tok = * list ; tok ; tok = tok - > next ) {
2005-07-07 23:13:32 +04:00
if ( _cmp_fn & & _cmp_fn ( tok - > key , key ) = = 0 ) goto found ;
else if ( ! _cmp_fn & & tok - > key = = key ) goto found ;
2004-12-09 10:05:00 +03:00
}
return ndr_map_error ( NDR_ERR_TOKEN ) ;
2005-07-07 23:13:32 +04:00
found :
* v = tok - > value ;
if ( _remove_tok ) {
DLIST_REMOVE ( ( * list ) , tok ) ;
talloc_free ( tok ) ;
}
return NT_STATUS_OK ;
}
/*
retrieve a token from a ndr context
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ NTSTATUS ndr_token_retrieve ( struct ndr_token_list * * list , const void * key , uint32_t * v )
2005-07-07 23:13:32 +04:00
{
return ndr_token_retrieve_cmp_fn ( list , key , v , NULL , True ) ;
2004-12-09 10:05:00 +03:00
}
/*
peek at but don ' t removed a token from a ndr context
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ uint32_t ndr_token_peek ( struct ndr_token_list * * list , const void * key )
2004-12-09 10:05:00 +03:00
{
2005-07-07 23:13:32 +04:00
NTSTATUS status ;
uint32_t v ;
status = ndr_token_retrieve_cmp_fn ( list , key , & v , NULL , False ) ;
if ( NT_STATUS_IS_OK ( status ) ) return v ;
2004-08-12 09:15:41 +04:00
return 0 ;
}
2004-12-09 10:05:00 +03:00
/*
pull an array size field and add it to the array_size_list token list
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ NTSTATUS ndr_pull_array_size ( struct ndr_pull * ndr , const void * p )
2004-12-09 10:05:00 +03:00
{
uint32_t size ;
2005-02-10 00:10:23 +03:00
NDR_CHECK ( ndr_pull_uint32 ( ndr , NDR_SCALARS , & size ) ) ;
2004-12-09 10:05:00 +03:00
return ndr_token_store ( ndr , & ndr - > array_size_list , p , size ) ;
}
/*
get the stored array size field
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ uint32_t ndr_get_array_size ( struct ndr_pull * ndr , const void * p )
2004-12-09 10:05:00 +03:00
{
return ndr_token_peek ( & ndr - > array_size_list , p ) ;
}
/*
check the stored array size field
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ NTSTATUS ndr_check_array_size ( struct ndr_pull * ndr , void * p , uint32_t size )
2004-12-09 10:05:00 +03:00
{
2004-12-11 01:36:46 +03:00
uint32_t stored ;
r6973: Merge new version of pidl into the main SAMBA_4_0 branch.
The main difference in this new version is the extra data structure generated
between the IDL data structure and the NDR parser:
IDL -> NDR -> { ndr_parser, ndr_header, eparser, etc }
This makes the ndr_parser.pm internals much more sane.
Other changes include:
- Remove unnecessary calls with NDR_BUFFERS (for example, GUID doesn't have any buffers, just scalars) as well as some (unnecessary) nested setting of flags.
- Parse array loops in the C code rather then calling ndr_pull_array(). This allows us to have, for example, arrays of pointers or arrays of pointers to arrays, etc..
- Use if() {} rather then if () goto foo; everywhere
- NDR_IN no longer implies LIBNDR_FLAG_REF_ALLOC
- By default, top level pointers are now "ref" (as is the default in
most other IDL compilers). This can be overridden using the
default_pointer_top() property.
- initial work on new ethereal parser generators by Alan DeKok and me
- pidl now writes errors in the standard format used by compilers, which
is parsable by most editors
- ability to warn about the fact that pidl extension(s) have been used,
useful for making sure IDL files work with other IDL compilers.
oh, and there's probably some other things I can't think of right now..
(This used to be commit 13cf227615f6b9e0e5fa62e59197024410254f01)
2005-05-25 17:50:27 +04:00
stored = ndr_token_peek ( & ndr - > array_size_list , p ) ;
2004-12-09 10:05:00 +03:00
if ( stored ! = size ) {
return ndr_pull_error ( ndr , NDR_ERR_ARRAY_SIZE ,
" Bad array size - got %u expected %u \n " ,
stored , size ) ;
}
return NT_STATUS_OK ;
}
/*
pull an array length field and add it to the array_length_list token list
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ NTSTATUS ndr_pull_array_length ( struct ndr_pull * ndr , const void * p )
2004-12-09 10:05:00 +03:00
{
uint32_t length , offset ;
2005-02-10 00:10:23 +03:00
NDR_CHECK ( ndr_pull_uint32 ( ndr , NDR_SCALARS , & offset ) ) ;
2004-12-09 10:05:00 +03:00
if ( offset ! = 0 ) {
return ndr_pull_error ( ndr , NDR_ERR_ARRAY_SIZE ,
" non-zero array offset %u \n " , offset ) ;
}
2005-02-10 00:10:23 +03:00
NDR_CHECK ( ndr_pull_uint32 ( ndr , NDR_SCALARS , & length ) ) ;
2004-12-09 10:05:00 +03:00
return ndr_token_store ( ndr , & ndr - > array_length_list , p , length ) ;
}
/*
get the stored array length field
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ uint32_t ndr_get_array_length ( struct ndr_pull * ndr , const void * p )
2004-12-09 10:05:00 +03:00
{
return ndr_token_peek ( & ndr - > array_length_list , p ) ;
}
/*
check the stored array length field
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ NTSTATUS ndr_check_array_length ( struct ndr_pull * ndr , void * p , uint32_t length )
2004-12-09 10:05:00 +03:00
{
uint32_t stored ;
r6973: Merge new version of pidl into the main SAMBA_4_0 branch.
The main difference in this new version is the extra data structure generated
between the IDL data structure and the NDR parser:
IDL -> NDR -> { ndr_parser, ndr_header, eparser, etc }
This makes the ndr_parser.pm internals much more sane.
Other changes include:
- Remove unnecessary calls with NDR_BUFFERS (for example, GUID doesn't have any buffers, just scalars) as well as some (unnecessary) nested setting of flags.
- Parse array loops in the C code rather then calling ndr_pull_array(). This allows us to have, for example, arrays of pointers or arrays of pointers to arrays, etc..
- Use if() {} rather then if () goto foo; everywhere
- NDR_IN no longer implies LIBNDR_FLAG_REF_ALLOC
- By default, top level pointers are now "ref" (as is the default in
most other IDL compilers). This can be overridden using the
default_pointer_top() property.
- initial work on new ethereal parser generators by Alan DeKok and me
- pidl now writes errors in the standard format used by compilers, which
is parsable by most editors
- ability to warn about the fact that pidl extension(s) have been used,
useful for making sure IDL files work with other IDL compilers.
oh, and there's probably some other things I can't think of right now..
(This used to be commit 13cf227615f6b9e0e5fa62e59197024410254f01)
2005-05-25 17:50:27 +04:00
stored = ndr_token_peek ( & ndr - > array_length_list , p ) ;
2004-12-09 10:05:00 +03:00
if ( stored ! = length ) {
return ndr_pull_error ( ndr , NDR_ERR_ARRAY_SIZE ,
" Bad array length - got %u expected %u \n " ,
stored , length ) ;
}
return NT_STATUS_OK ;
}
2004-08-12 09:15:41 +04:00
2005-03-06 20:02:14 +03:00
/*
store a switch value
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ NTSTATUS ndr_push_set_switch_value ( struct ndr_push * ndr , const void * p , uint32_t val )
2005-03-06 20:02:14 +03:00
{
return ndr_token_store ( ndr , & ndr - > switch_list , p , val ) ;
}
2006-03-05 20:15:19 +03:00
_PUBLIC_ NTSTATUS ndr_pull_set_switch_value ( struct ndr_pull * ndr , const void * p , uint32_t val )
2005-03-06 20:02:14 +03:00
{
return ndr_token_store ( ndr , & ndr - > switch_list , p , val ) ;
}
2006-03-05 20:15:19 +03:00
_PUBLIC_ NTSTATUS ndr_print_set_switch_value ( struct ndr_print * ndr , const void * p , uint32_t val )
2005-04-04 18:22:28 +04:00
{
return ndr_token_store ( ndr , & ndr - > switch_list , p , val ) ;
}
2005-03-06 20:02:14 +03:00
/*
retrieve a switch value
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ uint32_t ndr_push_get_switch_value ( struct ndr_push * ndr , const void * p )
2005-03-06 20:02:14 +03:00
{
return ndr_token_peek ( & ndr - > switch_list , p ) ;
}
2006-03-05 20:15:19 +03:00
_PUBLIC_ uint32_t ndr_pull_get_switch_value ( struct ndr_pull * ndr , const void * p )
2005-03-06 20:02:14 +03:00
{
return ndr_token_peek ( & ndr - > switch_list , p ) ;
}
2006-03-05 20:15:19 +03:00
_PUBLIC_ uint32_t ndr_print_get_switch_value ( struct ndr_print * ndr , const void * p )
2005-04-03 00:57:27 +04:00
{
return ndr_token_peek ( & ndr - > switch_list , p ) ;
}
2003-11-17 07:56:59 +03:00
/*
pull a struct from a blob using NDR
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ NTSTATUS ndr_pull_struct_blob ( const DATA_BLOB * blob , TALLOC_CTX * mem_ctx , void * p ,
2004-11-05 10:29:02 +03:00
ndr_pull_flags_fn_t fn )
2003-11-17 07:56:59 +03:00
{
struct ndr_pull * ndr ;
ndr = ndr_pull_init_blob ( blob , mem_ctx ) ;
if ( ! ndr ) {
return NT_STATUS_NO_MEMORY ;
}
return fn ( ndr , NDR_SCALARS | NDR_BUFFERS , p ) ;
}
2003-11-24 04:24:29 +03:00
2005-05-10 05:58:34 +04:00
/*
pull a struct from a blob using NDR - failing if all bytes are not consumed
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ NTSTATUS ndr_pull_struct_blob_all ( const DATA_BLOB * blob , TALLOC_CTX * mem_ctx , void * p ,
2005-05-10 05:58:34 +04:00
ndr_pull_flags_fn_t fn )
{
struct ndr_pull * ndr ;
NTSTATUS status ;
ndr = ndr_pull_init_blob ( blob , mem_ctx ) ;
if ( ! ndr ) {
return NT_STATUS_NO_MEMORY ;
}
status = fn ( ndr , NDR_SCALARS | NDR_BUFFERS , p ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) return status ;
if ( ndr - > offset ! = ndr - > data_size ) {
return NT_STATUS_BUFFER_TOO_SMALL ;
}
return status ;
}
2005-05-11 03:33:56 +04:00
/*
pull a union from a blob using NDR , given the union discriminator
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ NTSTATUS ndr_pull_union_blob ( const DATA_BLOB * blob , TALLOC_CTX * mem_ctx , void * p ,
2005-05-11 03:33:56 +04:00
uint32_t level , ndr_pull_flags_fn_t fn )
{
struct ndr_pull * ndr ;
NTSTATUS status ;
ndr = ndr_pull_init_blob ( blob , mem_ctx ) ;
if ( ! ndr ) {
return NT_STATUS_NO_MEMORY ;
}
ndr_pull_set_switch_value ( ndr , p , level ) ;
status = fn ( ndr , NDR_SCALARS | NDR_BUFFERS , p ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) return status ;
if ( ndr - > offset ! = ndr - > data_size ) {
return NT_STATUS_BUFFER_TOO_SMALL ;
}
return status ;
}
2003-11-26 04:16:41 +03:00
/*
push a struct to a blob using NDR
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ NTSTATUS ndr_push_struct_blob ( DATA_BLOB * blob , TALLOC_CTX * mem_ctx , const void * p ,
2004-11-05 10:29:02 +03:00
ndr_push_flags_fn_t fn )
2003-11-26 04:16:41 +03:00
{
NTSTATUS status ;
struct ndr_push * ndr ;
ndr = ndr_push_init_ctx ( mem_ctx ) ;
if ( ! ndr ) {
return NT_STATUS_NO_MEMORY ;
}
status = fn ( ndr , NDR_SCALARS | NDR_BUFFERS , p ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2003-11-24 04:24:29 +03:00
2003-11-26 04:16:41 +03:00
* blob = ndr_push_blob ( ndr ) ;
2006-10-16 15:03:12 +04:00
talloc_steal ( mem_ctx , blob - > data ) ;
talloc_free ( ndr ) ;
2003-11-26 04:16:41 +03:00
return NT_STATUS_OK ;
}
2005-01-05 05:01:19 +03:00
2005-05-12 12:27:04 +04:00
/*
push a union to a blob using NDR
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ NTSTATUS ndr_push_union_blob ( DATA_BLOB * blob , TALLOC_CTX * mem_ctx , void * p ,
2005-05-12 12:27:04 +04:00
uint32_t level , ndr_push_flags_fn_t fn )
{
NTSTATUS status ;
struct ndr_push * ndr ;
ndr = ndr_push_init_ctx ( mem_ctx ) ;
if ( ! ndr ) {
return NT_STATUS_NO_MEMORY ;
}
ndr_push_set_switch_value ( ndr , p , level ) ;
status = fn ( ndr , NDR_SCALARS | NDR_BUFFERS , p ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
* blob = ndr_push_blob ( ndr ) ;
2006-10-16 18:32:07 +04:00
talloc_steal ( mem_ctx , blob - > data ) ;
talloc_free ( ndr ) ;
2005-05-12 12:27:04 +04:00
return NT_STATUS_OK ;
}
2005-01-05 05:01:19 +03:00
/*
generic ndr_size_ * ( ) handler for structures
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ size_t ndr_size_struct ( const void * p , int flags , ndr_push_flags_fn_t push )
2005-01-05 05:01:19 +03:00
{
struct ndr_push * ndr ;
NTSTATUS status ;
size_t ret ;
2005-03-11 13:09:16 +03:00
/* avoid recursion */
if ( flags & LIBNDR_FLAG_NO_NDR_SIZE ) return 0 ;
2005-01-05 05:01:19 +03:00
ndr = ndr_push_init_ctx ( NULL ) ;
if ( ! ndr ) return 0 ;
2005-03-11 13:09:16 +03:00
ndr - > flags | = flags | LIBNDR_FLAG_NO_NDR_SIZE ;
2005-01-05 05:01:19 +03:00
status = push ( ndr , NDR_SCALARS | NDR_BUFFERS , discard_const ( p ) ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return 0 ;
}
ret = ndr - > offset ;
talloc_free ( ndr ) ;
return ret ;
}
2005-01-21 09:54:10 +03:00
/*
generic ndr_size_ * ( ) handler for unions
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ size_t ndr_size_union ( const void * p , int flags , uint32_t level , ndr_push_flags_fn_t push )
2005-01-21 09:54:10 +03:00
{
struct ndr_push * ndr ;
NTSTATUS status ;
size_t ret ;
2005-03-11 13:09:16 +03:00
/* avoid recursion */
if ( flags & LIBNDR_FLAG_NO_NDR_SIZE ) return 0 ;
2005-01-21 09:54:10 +03:00
ndr = ndr_push_init_ctx ( NULL ) ;
if ( ! ndr ) return 0 ;
2005-03-11 13:09:16 +03:00
ndr - > flags | = flags | LIBNDR_FLAG_NO_NDR_SIZE ;
2005-03-12 20:12:52 +03:00
ndr_push_set_switch_value ( ndr , p , level ) ;
2005-07-04 06:25:33 +04:00
status = push ( ndr , NDR_SCALARS | NDR_BUFFERS , p ) ;
2005-01-21 09:54:10 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return 0 ;
}
ret = ndr - > offset ;
talloc_free ( ndr ) ;
return ret ;
}
2005-06-02 07:41:12 +04:00
/*
get the current base for relative pointers for the push
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ uint32_t ndr_push_get_relative_base_offset ( struct ndr_push * ndr )
2005-06-02 07:41:12 +04:00
{
return ndr - > relative_base_offset ;
}
/*
restore the old base for relative pointers for the push
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ void ndr_push_restore_relative_base_offset ( struct ndr_push * ndr , uint32_t offset )
2005-06-02 07:41:12 +04:00
{
ndr - > relative_base_offset = offset ;
}
/*
setup the current base for relative pointers for the push
called in the NDR_SCALAR stage
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ NTSTATUS ndr_push_setup_relative_base_offset1 ( struct ndr_push * ndr , const void * p , uint32_t offset )
2005-06-02 07:41:12 +04:00
{
ndr - > relative_base_offset = offset ;
return ndr_token_store ( ndr , & ndr - > relative_base_list , p , offset ) ;
}
/*
setup the current base for relative pointers for the push
called in the NDR_BUFFERS stage
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ NTSTATUS ndr_push_setup_relative_base_offset2 ( struct ndr_push * ndr , const void * p )
2005-06-02 07:41:12 +04:00
{
return ndr_token_retrieve ( & ndr - > relative_base_list , p , & ndr - > relative_base_offset ) ;
}
/*
push a relative object - stage1
this is called during SCALARS processing
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ NTSTATUS ndr_push_relative_ptr1 ( struct ndr_push * ndr , const void * p )
2005-06-02 07:41:12 +04:00
{
if ( p = = NULL ) {
NDR_CHECK ( ndr_push_uint32 ( ndr , NDR_SCALARS , 0 ) ) ;
return NT_STATUS_OK ;
}
NDR_CHECK ( ndr_push_align ( ndr , 4 ) ) ;
NDR_CHECK ( ndr_token_store ( ndr , & ndr - > relative_list , p , ndr - > offset ) ) ;
return ndr_push_uint32 ( ndr , NDR_SCALARS , 0xFFFFFFFF ) ;
}
/*
push a relative object - stage2
this is called during buffers processing
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ NTSTATUS ndr_push_relative_ptr2 ( struct ndr_push * ndr , const void * p )
2005-06-02 07:41:12 +04:00
{
struct ndr_push_save save ;
2005-06-02 10:25:48 +04:00
uint32_t ptr_offset = 0xFFFFFFFF ;
2005-06-02 07:41:12 +04:00
if ( p = = NULL ) {
return NT_STATUS_OK ;
}
ndr_push_save ( ndr , & save ) ;
2005-06-02 10:25:48 +04:00
NDR_CHECK ( ndr_token_retrieve ( & ndr - > relative_list , p , & ptr_offset ) ) ;
if ( ptr_offset > ndr - > offset ) {
return ndr_push_error ( ndr , NDR_ERR_BUFSIZE ,
" ndr_push_relative_ptr2 ptr_offset(%u) > ndr->offset(%u) " ,
ptr_offset , ndr - > offset ) ;
}
ndr - > offset = ptr_offset ;
if ( save . offset < ndr - > relative_base_offset ) {
return ndr_push_error ( ndr , NDR_ERR_BUFSIZE ,
" ndr_push_relative_ptr2 save.offset(%u) < ndr->relative_base_offset(%u) " ,
save . offset , ndr - > relative_base_offset ) ;
}
NDR_CHECK ( ndr_push_uint32 ( ndr , NDR_SCALARS , save . offset - ndr - > relative_base_offset ) ) ;
2005-06-02 07:41:12 +04:00
ndr_push_restore ( ndr , & save ) ;
return NT_STATUS_OK ;
}
/*
get the current base for relative pointers for the pull
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ uint32_t ndr_pull_get_relative_base_offset ( struct ndr_pull * ndr )
2005-06-02 07:41:12 +04:00
{
return ndr - > relative_base_offset ;
}
/*
restore the old base for relative pointers for the pull
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ void ndr_pull_restore_relative_base_offset ( struct ndr_pull * ndr , uint32_t offset )
2005-06-02 07:41:12 +04:00
{
ndr - > relative_base_offset = offset ;
}
/*
setup the current base for relative pointers for the pull
called in the NDR_SCALAR stage
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ NTSTATUS ndr_pull_setup_relative_base_offset1 ( struct ndr_pull * ndr , const void * p , uint32_t offset )
2005-06-02 07:41:12 +04:00
{
ndr - > relative_base_offset = offset ;
return ndr_token_store ( ndr , & ndr - > relative_base_list , p , offset ) ;
}
/*
setup the current base for relative pointers for the pull
called in the NDR_BUFFERS stage
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ NTSTATUS ndr_pull_setup_relative_base_offset2 ( struct ndr_pull * ndr , const void * p )
2005-06-02 07:41:12 +04:00
{
return ndr_token_retrieve ( & ndr - > relative_base_list , p , & ndr - > relative_base_offset ) ;
}
/*
pull a relative object - stage1
called during SCALARS processing
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ NTSTATUS ndr_pull_relative_ptr1 ( struct ndr_pull * ndr , const void * p , uint32_t rel_offset )
2005-06-02 07:41:12 +04:00
{
rel_offset + = ndr - > relative_base_offset ;
2005-06-02 10:25:48 +04:00
if ( rel_offset > ndr - > data_size ) {
return ndr_pull_error ( ndr , NDR_ERR_BUFSIZE ,
" ndr_pull_relative_ptr1 rel_offset(%u) > ndr->data_size(%u) " ,
rel_offset , ndr - > data_size ) ;
}
2005-06-02 07:41:12 +04:00
return ndr_token_store ( ndr , & ndr - > relative_list , p , rel_offset ) ;
}
/*
pull a relative object - stage2
called during BUFFERS processing
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ NTSTATUS ndr_pull_relative_ptr2 ( struct ndr_pull * ndr , const void * p )
2005-06-02 07:41:12 +04:00
{
uint32_t rel_offset ;
NDR_CHECK ( ndr_token_retrieve ( & ndr - > relative_list , p , & rel_offset ) ) ;
return ndr_pull_set_offset ( ndr , rel_offset ) ;
}