From ba6d3075bc7806878ed22f0bde7abf83142a714b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 17 Aug 2005 01:29:35 +0000 Subject: r9339: treat arrays of uint8 values as a special DATA_BLOB type in the ejs interfaces to RPC. This makes large blobs of data much saner. Tim, you will probably want to do the same for the smb_interfaces.h generated code. Next we will need ways of extracting different data types from these blobs, for example asking for the blob to be interpreted as a utf16 string, or as a little-endian integer. That will allow for registry scripting to be quite sane. (This used to be commit a8bca2e8e27c953c0413693326ec3b5ecf17ba41) --- source4/build/pidl/Parse/Pidl/Samba/EJS.pm | 22 +++++++++++++++--- source4/scripting/ejs/ejsrpc.c | 37 ++++++++++++++++++++++++++++++ source4/scripting/ejs/ejsrpc.h | 7 ++++++ source4/scripting/ejs/mprutil.c | 25 ++++++++++++++++++++ 4 files changed, 88 insertions(+), 3 deletions(-) diff --git a/source4/build/pidl/Parse/Pidl/Samba/EJS.pm b/source4/build/pidl/Parse/Pidl/Samba/EJS.pm index 1227e7aeb8..743139c8cd 100644 --- a/source4/build/pidl/Parse/Pidl/Samba/EJS.pm +++ b/source4/build/pidl/Parse/Pidl/Samba/EJS.pm @@ -165,22 +165,32 @@ sub EjsPullString($$$$$) sub EjsPullArray($$$$$) { my ($e, $l, $var, $name, $env) = @_; + my $nl = Parse::Pidl::NDR::GetNextLevel($e, $l); my $length = Parse::Pidl::Util::ParseExpr($l->{LENGTH_IS}, $env); + my $size = Parse::Pidl::Util::ParseExpr($l->{SIZE_IS}, $env); my $pl = Parse::Pidl::NDR::GetPrevLevel($e, $l); if ($pl && $pl->{TYPE} eq "POINTER") { $var = get_pointer_to($var); } + # uint8 arrays are treated as data blobs + if ($nl->{TYPE} eq 'DATA' && $e->{TYPE} eq 'uint8') { + if (!$l->{IS_FIXED}) { + pidl "EJS_ALLOC_N(ejs, $var, $size);"; + } + pidl "ejs_pull_array_uint8(ejs, v, $name, $var, $length);"; + return; + } my $avar = $var . "[i]"; pidl "{"; indent; pidl "uint32_t i;"; if (!$l->{IS_FIXED}) { - pidl "EJS_ALLOC_N(ejs, $var, $length);"; + pidl "EJS_ALLOC_N(ejs, $var, $size);"; } pidl "for (i=0;i<$length;i++) {"; indent; pidl "char *id = talloc_asprintf(ejs, \"%s.%u\", $name, i);"; - EjsPullElement($e, Parse::Pidl::NDR::GetNextLevel($e, $l), $avar, "id", $env); + EjsPullElement($e, $nl, $avar, "id", $env); pidl "talloc_free(id);"; deindent; pidl "}"; @@ -451,11 +461,17 @@ sub EjsPushSwitch($$$$$) sub EjsPushArray($$$$$) { my ($e, $l, $var, $name, $env) = @_; + my $nl = Parse::Pidl::NDR::GetNextLevel($e, $l); my $length = Parse::Pidl::Util::ParseExpr($l->{LENGTH_IS}, $env); my $pl = Parse::Pidl::NDR::GetPrevLevel($e, $l); if ($pl && $pl->{TYPE} eq "POINTER") { $var = get_pointer_to($var); } + # uint8 arrays are treated as data blobs + if ($nl->{TYPE} eq 'DATA' && $e->{TYPE} eq 'uint8') { + pidl "ejs_push_array_uint8(ejs, v, $name, $var, $length);"; + return; + } my $avar = $var . "[i]"; pidl "{"; indent; @@ -463,7 +479,7 @@ sub EjsPushArray($$$$$) pidl "for (i=0;i<$length;i++) {"; indent; pidl "const char *id = talloc_asprintf(ejs, \"%s.%u\", $name, i);"; - EjsPushElement($e, Parse::Pidl::NDR::GetNextLevel($e, $l), $avar, "id", $env); + EjsPushElement($e, $nl, $avar, "id", $env); deindent; pidl "}"; pidl "ejs_push_uint32(ejs, v, $name \".length\", &i);"; diff --git a/source4/scripting/ejs/ejsrpc.c b/source4/scripting/ejs/ejsrpc.c index f107c84b73..de25d3a0f0 100644 --- a/source4/scripting/ejs/ejsrpc.c +++ b/source4/scripting/ejs/ejsrpc.c @@ -349,3 +349,40 @@ NTSTATUS ejs_push_BOOL(struct ejs_rpc *ejs, { return mprSetVar(v, name, mprCreateBoolVar(*r)); } + + +/* + pull a uint8 array from a mpr variable to a C element - treating as a data blob +*/ +NTSTATUS ejs_pull_array_uint8(struct ejs_rpc *ejs, + struct MprVar *v, const char *name, + uint8_t *r, uint32_t length) +{ + NTSTATUS status; + DATA_BLOB *blob; + + status = mprGetVar(&v, name); + NT_STATUS_NOT_OK_RETURN(status); + + blob = mprToDataBlob(v); + if (blob == NULL) { + return NT_STATUS_OBJECT_NAME_INVALID; + } + if (blob->length != length) { + return NT_STATUS_INFO_LENGTH_MISMATCH; + } + memcpy(r, blob->data, length); + return NT_STATUS_OK; + +} + +NTSTATUS ejs_push_array_uint8(struct ejs_rpc *ejs, + struct MprVar *v, const char *name, + const uint8_t *r, uint32_t length) +{ + DATA_BLOB blob; + blob.data = discard_const(r); + blob.length = length; + mprSetVar(v, name, mprDataBlob(blob)); + return NT_STATUS_OK; +} diff --git a/source4/scripting/ejs/ejsrpc.h b/source4/scripting/ejs/ejsrpc.h index 99da0d35ea..03919c3602 100644 --- a/source4/scripting/ejs/ejsrpc.h +++ b/source4/scripting/ejs/ejsrpc.h @@ -108,6 +108,13 @@ NTSTATUS ejs_pull_BOOL(struct ejs_rpc *ejs, NTSTATUS ejs_push_BOOL(struct ejs_rpc *ejs, struct MprVar *v, const char *name, const BOOL *r); +NTSTATUS ejs_pull_array_uint8(struct ejs_rpc *ejs, + struct MprVar *v, const char *name, + uint8_t *r, uint32_t length); +NTSTATUS ejs_push_array_uint8(struct ejs_rpc *ejs, + struct MprVar *v, const char *name, + const uint8_t *r, uint32_t length); + #define EJS_ALLOC_SIZE(ejs, s, size) do { \ (s) = talloc_size(ejs, size); \ if (!(s)) return ejs_panic(ejs, "out of memory"); \ diff --git a/source4/scripting/ejs/mprutil.c b/source4/scripting/ejs/mprutil.c index 657078e7c7..700185f07e 100644 --- a/source4/scripting/ejs/mprutil.c +++ b/source4/scripting/ejs/mprutil.c @@ -317,6 +317,31 @@ struct MprVar mprNTSTATUS(NTSTATUS status) return res; } +/* + create a data-blob in a mpr variable +*/ +struct MprVar mprDataBlob(DATA_BLOB blob) +{ + struct MprVar res; + struct data_blob *pblob = talloc(mprMemCtx(), struct data_blob); + *pblob = data_blob_talloc(pblob, blob.data, blob.length); + + res = mprObject("DATA_BLOB"); + + mprSetVar(&res, "size", mprCreateIntegerVar(blob.length)); + mprSetPtrChild(&res, "blob", pblob); + + return res; +} + +/* + return a data blob from a mpr var created using mprDataBlob +*/ +struct data_blob *mprToDataBlob(struct MprVar *v) +{ + return talloc_get_type(mprGetPtr(v, "blob"), struct data_blob); +} + /* turn a WERROR into a MprVar object with lots of funky properties */ -- cgit