diff options
-rw-r--r-- | source4/build/pidl/parser.pm | 16 | ||||
-rw-r--r-- | source4/build/pidl/util.pm | 18 | ||||
-rw-r--r-- | source4/librpc/idl/idl_types.h | 18 | ||||
-rw-r--r-- | source4/librpc/ndr/libndr.h | 43 | ||||
-rw-r--r-- | source4/librpc/ndr/ndr_basic.c | 55 |
5 files changed, 115 insertions, 35 deletions
diff --git a/source4/build/pidl/parser.pm b/source4/build/pidl/parser.pm index c52be637ec..34f9df197f 100644 --- a/source4/build/pidl/parser.pm +++ b/source4/build/pidl/parser.pm @@ -705,7 +705,6 @@ sub ParseElementPullBuffer($$$) sub ParseStructPush($) { my($struct) = shift; - my $conform_e; if (! defined $struct->{ELEMENTS}) { return; @@ -722,10 +721,14 @@ sub ParseStructPush($) if (defined $e->{ARRAY_LEN} && $e->{ARRAY_LEN} eq "*") { my $size = find_size_var($e, util::array_size($e), "r->"); $e->{CONFORMANT_SIZE} = $size; - $conform_e = $e; pidl "\tNDR_CHECK(ndr_push_uint32(ndr, $size));\n"; } + if (defined $e->{TYPE} && $e->{TYPE} eq "string" + && util::property_matches($e, "flag", ".*LIBNDR_FLAG_STR_CONFORMANT.*")) { + pidl "\tNDR_CHECK(ndr_push_uint32(ndr, ndr_string_array_size(ndr, r->$e->{NAME})));\n"; + } + pidl "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n"; pidl "\tNDR_CHECK(ndr_push_struct_start(ndr));\n"; @@ -790,6 +793,15 @@ sub ParseStructPull($) my $e = $struct->{ELEMENTS}[-1]; if (defined $e->{ARRAY_LEN} && $e->{ARRAY_LEN} eq "*") { $conform_e = $e; + } + + if (defined $e->{TYPE} && $e->{TYPE} eq "string" + && util::property_matches($e, "flag", ".*LIBNDR_FLAG_STR_CONFORMANT.*")) { + $conform_e = $e; + } + + if (defined $conform_e) { + $conform_e = $e; pidl "\tuint32_t _conformant_size;\n"; $conform_e->{CONFORMANT_SIZE} = "_conformant_size"; } diff --git a/source4/build/pidl/util.pm b/source4/build/pidl/util.pm index c49e956e50..bddce57740 100644 --- a/source4/build/pidl/util.pm +++ b/source4/build/pidl/util.pm @@ -181,6 +181,24 @@ sub has_property($$) return $e->{PROPERTIES}->{$p}; } +##################################################################### +# see if a pidl property matches a value +sub property_matches($$$) +{ + my($e) = shift; + my($p) = shift; + my($v) = shift; + + if (!defined has_property($e, $p)) { + return undef; + } + + if ($e->{PROPERTIES}->{$p} =~ /$v/) { + return 1; + } + + return undef; +} sub is_scalar_type($) { diff --git a/source4/librpc/idl/idl_types.h b/source4/librpc/idl/idl_types.h index d74523d8fb..860c9d7260 100644 --- a/source4/librpc/idl/idl_types.h +++ b/source4/librpc/idl/idl_types.h @@ -1,11 +1,13 @@ -#define STR_ASCII LIBNDR_FLAG_STR_ASCII -#define STR_LEN4 LIBNDR_FLAG_STR_LEN4 -#define STR_SIZE4 LIBNDR_FLAG_STR_SIZE4 -#define STR_SIZE2 LIBNDR_FLAG_STR_SIZE2 -#define STR_NOTERM LIBNDR_FLAG_STR_NOTERM -#define STR_NULLTERM LIBNDR_FLAG_STR_NULLTERM -#define STR_BYTESIZE LIBNDR_FLAG_STR_BYTESIZE -#define STR_FIXLEN32 LIBNDR_FLAG_STR_FIXLEN32 +#define STR_ASCII LIBNDR_FLAG_STR_ASCII +#define STR_LEN4 LIBNDR_FLAG_STR_LEN4 +#define STR_SIZE4 LIBNDR_FLAG_STR_SIZE4 +#define STR_SIZE2 LIBNDR_FLAG_STR_SIZE2 +#define STR_NOTERM LIBNDR_FLAG_STR_NOTERM +#define STR_NULLTERM LIBNDR_FLAG_STR_NULLTERM +#define STR_BYTESIZE LIBNDR_FLAG_STR_BYTESIZE +#define STR_FIXLEN32 LIBNDR_FLAG_STR_FIXLEN32 +#define STR_CONFORMANT LIBNDR_FLAG_STR_CONFORMANT +#define STR_CHARLEN LIBNDR_FLAG_STR_CHARLEN /* a UCS2 string prefixed with [size] [offset] [length], all 32 bits diff --git a/source4/librpc/ndr/libndr.h b/source4/librpc/ndr/libndr.h index 09d06a7c7f..72d75f7d47 100644 --- a/source4/librpc/ndr/libndr.h +++ b/source4/librpc/ndr/libndr.h @@ -89,36 +89,39 @@ struct ndr_print { #define LIBNDR_FLAG_BIGENDIAN (1<<0) #define LIBNDR_FLAG_NOALIGN (1<<1) -#define LIBNDR_FLAG_STR_ASCII (1<<2) -#define LIBNDR_FLAG_STR_LEN4 (1<<3) -#define LIBNDR_FLAG_STR_SIZE4 (1<<4) -#define LIBNDR_FLAG_STR_NOTERM (1<<5) -#define LIBNDR_FLAG_STR_NULLTERM (1<<6) -#define LIBNDR_FLAG_STR_SIZE2 (1<<7) -#define LIBNDR_FLAG_STR_BYTESIZE (1<<8) -#define LIBNDR_FLAG_STR_FIXLEN32 (1<<9) -#define LIBNDR_STRING_FLAGS (0x3FC) - -#define LIBNDR_FLAG_REF_ALLOC (1<<10) -#define LIBNDR_FLAG_REMAINING (1<<11) -#define LIBNDR_FLAG_ALIGN2 (1<<12) -#define LIBNDR_FLAG_ALIGN4 (1<<13) -#define LIBNDR_FLAG_ALIGN8 (1<<14) +#define LIBNDR_FLAG_STR_ASCII (1<<2) +#define LIBNDR_FLAG_STR_LEN4 (1<<3) +#define LIBNDR_FLAG_STR_SIZE4 (1<<4) +#define LIBNDR_FLAG_STR_NOTERM (1<<5) +#define LIBNDR_FLAG_STR_NULLTERM (1<<6) +#define LIBNDR_FLAG_STR_SIZE2 (1<<7) +#define LIBNDR_FLAG_STR_BYTESIZE (1<<8) +#define LIBNDR_FLAG_STR_FIXLEN32 (1<<9) +#define LIBNDR_FLAG_STR_CONFORMANT (1<<10) +#define LIBNDR_FLAG_STR_CHARLEN (1<<11) +#define LIBNDR_STRING_FLAGS (0xFFC) + + +#define LIBNDR_FLAG_REF_ALLOC (1<<20) +#define LIBNDR_FLAG_REMAINING (1<<21) +#define LIBNDR_FLAG_ALIGN2 (1<<22) +#define LIBNDR_FLAG_ALIGN4 (1<<23) +#define LIBNDR_FLAG_ALIGN8 (1<<24) #define LIBNDR_ALIGN_FLAGS (LIBNDR_FLAG_ALIGN2|LIBNDR_FLAG_ALIGN4|LIBNDR_FLAG_ALIGN8) -#define LIBNDR_PRINT_ARRAY_HEX (1<<15) -#define LIBNDR_PRINT_SET_VALUES (1<<16) +#define LIBNDR_PRINT_ARRAY_HEX (1<<25) +#define LIBNDR_PRINT_SET_VALUES (1<<26) /* used to force a section of IDL to be little-endian */ -#define LIBNDR_FLAG_LITTLE_ENDIAN (1<<17) +#define LIBNDR_FLAG_LITTLE_ENDIAN (1<<27) /* used to check if alignment padding is zero */ -#define LIBNDR_FLAG_PAD_CHECK (1<<18) +#define LIBNDR_FLAG_PAD_CHECK (1<<28) /* used to indicate spoolss style relative pointers (relative to current offset, not base) */ -#define LIBNDR_FLAG_RELATIVE_CURRENT (1<<19) +#define LIBNDR_FLAG_RELATIVE_CURRENT (1<<29) /* useful macro for debugging */ diff --git a/source4/librpc/ndr/ndr_basic.c b/source4/librpc/ndr/ndr_basic.c index 95d8c28e75..84c4ab9ddc 100644 --- a/source4/librpc/ndr/ndr_basic.c +++ b/source4/librpc/ndr/ndr_basic.c @@ -522,6 +522,9 @@ NTSTATUS ndr_pull_string(struct ndr_pull *ndr, int ndr_flags, const char **s) flags &= ~LIBNDR_FLAG_STR_ASCII; } + flags &= ~LIBNDR_FLAG_STR_CONFORMANT; + flags &= ~LIBNDR_FLAG_STR_CHARLEN; + switch (flags & LIBNDR_STRING_FLAGS) { case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4: case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM: @@ -740,6 +743,7 @@ NTSTATUS ndr_push_string(struct ndr_push *ndr, int ndr_flags, const char *s) int chset = CH_UTF16; unsigned flags = ndr->flags; unsigned byte_mul = 2; + unsigned c_len_term = 1; if (!(ndr_flags & NDR_SCALARS)) { return NT_STATUS_OK; @@ -758,11 +762,18 @@ NTSTATUS ndr_push_string(struct ndr_push *ndr, int ndr_flags, const char *s) flags &= ~LIBNDR_FLAG_STR_ASCII; } + flags &= ~LIBNDR_FLAG_STR_CONFORMANT; + + if (flags & LIBNDR_FLAG_STR_CHARLEN) { + c_len_term = 0; + flags &= ~LIBNDR_FLAG_STR_CHARLEN; + } + switch (flags & LIBNDR_STRING_FLAGS) { case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4: - NDR_CHECK(ndr_push_uint32(ndr, c_len+1)); + NDR_CHECK(ndr_push_uint32(ndr, c_len+c_len_term)); NDR_CHECK(ndr_push_uint32(ndr, 0)); - NDR_CHECK(ndr_push_uint32(ndr, c_len+1)); + NDR_CHECK(ndr_push_uint32(ndr, c_len+c_len_term)); NDR_PUSH_NEED_BYTES(ndr, byte_mul*(c_len+1)); ret = convert_string(CH_UNIX, chset, s, s_len+1, @@ -792,7 +803,7 @@ NTSTATUS ndr_push_string(struct ndr_push *ndr, int ndr_flags, const char *s) case LIBNDR_FLAG_STR_LEN4: NDR_CHECK(ndr_push_uint32(ndr, 0)); - NDR_CHECK(ndr_push_uint32(ndr, c_len + 1)); + NDR_CHECK(ndr_push_uint32(ndr, c_len + c_len_term)); NDR_PUSH_NEED_BYTES(ndr, byte_mul*(c_len+1)); ret = convert_string(CH_UNIX, chset, s, s_len + 1, @@ -805,7 +816,7 @@ NTSTATUS ndr_push_string(struct ndr_push *ndr, int ndr_flags, const char *s) break; case LIBNDR_FLAG_STR_SIZE4: - NDR_CHECK(ndr_push_uint32(ndr, c_len + 1)); + NDR_CHECK(ndr_push_uint32(ndr, c_len + c_len_term)); NDR_PUSH_NEED_BYTES(ndr, byte_mul*(c_len+1)); ret = convert_string(CH_UNIX, chset, s, s_len + 1, @@ -818,7 +829,7 @@ NTSTATUS ndr_push_string(struct ndr_push *ndr, int ndr_flags, const char *s) break; case LIBNDR_FLAG_STR_SIZE2: - NDR_CHECK(ndr_push_uint16(ndr, c_len + 1)); + NDR_CHECK(ndr_push_uint16(ndr, c_len + c_len_term)); NDR_PUSH_NEED_BYTES(ndr, byte_mul*(c_len+1)); ret = convert_string(CH_UNIX, chset, s, s_len + 1, @@ -876,6 +887,40 @@ NTSTATUS ndr_push_string(struct ndr_push *ndr, int ndr_flags, const char *s) } /* + push a general string onto the wire +*/ +size_t ndr_string_array_size(struct ndr_push *ndr, const char *s) +{ + size_t c_len; + unsigned flags = ndr->flags; + unsigned byte_mul = 2; + unsigned c_len_term = 1; + + if (flags & LIBNDR_FLAG_STR_FIXLEN32) { + return 32; + } + + c_len = s?strlen_m(s):0; + + if (flags & LIBNDR_FLAG_STR_ASCII) { + byte_mul = 1; + } + + if (flags & LIBNDR_FLAG_STR_NOTERM) { + c_len_term = 0; + } + + c_len = c_len + c_len_term; + + if (flags & LIBNDR_FLAG_STR_BYTESIZE) { + c_len = c_len * byte_mul; + } + + return c_len; +} + + +/* push a NTTIME */ NTSTATUS ndr_push_NTTIME(struct ndr_push *ndr, NTTIME t) |