summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/build/pidl/ndr.pm94
-rwxr-xr-xsource4/build/pidl/pidl.pl5
-rw-r--r--source4/build/pidl/typelist.pm9
-rw-r--r--source4/build/pidl/validator.pm25
-rw-r--r--source4/librpc/idl/drsuapi.idl18
-rw-r--r--source4/librpc/idl/dssetup.idl2
-rw-r--r--source4/librpc/idl/echo.idl4
-rw-r--r--source4/librpc/idl/lsa.idl4
-rw-r--r--source4/librpc/idl/netlogon.idl8
-rw-r--r--source4/librpc/idl/samr.idl10
-rw-r--r--source4/librpc/idl/xattr.idl4
-rw-r--r--source4/librpc/ndr/libndr.h2
-rw-r--r--source4/librpc/ndr/ndr.c26
-rw-r--r--source4/librpc/ndr/ndr_spoolss_buf.c6
14 files changed, 140 insertions, 77 deletions
diff --git a/source4/build/pidl/ndr.pm b/source4/build/pidl/ndr.pm
index 333f20e78f..ac65f16d95 100644
--- a/source4/build/pidl/ndr.pm
+++ b/source4/build/pidl/ndr.pm
@@ -666,9 +666,11 @@ sub ParseElementPushScalar($$$)
ParseArrayPush($e, $ndr, "r->", "NDR_SCALARS");
} elsif (need_alloc($e)) {
# no scalar component
- } elsif (my $switch = util::has_property($e, "switch_is")) {
- ParseSwitchPush($e, $ndr, $var_prefix, $ndr_flags, $switch);
} else {
+ if (my $switch = util::has_property($e, "switch_is")) {
+ ParseSwitchPush($e, $ndr, $var_prefix, $ndr_flags, $switch);
+ }
+
pidl "NDR_CHECK(ndr_push_$e->{TYPE}($ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
}
@@ -759,33 +761,8 @@ sub ParseSwitchPull($$$$$)
check_null_pointer($switch_var);
- if (!defined $utype ||
- !util::has_property($utype, "nodiscriminant")) {
- my $e2 = util::find_sibling($e, $switch);
- my $type_decl = typelist::mapType($e2);
- pidl "if (($ndr_flags) & NDR_SCALARS) {";
- indent;
- pidl "$type_decl _level;";
- pidl "NDR_CHECK(ndr_pull_$e2->{TYPE}($ndr, NDR_SCALARS, &_level));";
- if ($switch_var =~ /r->in/) {
- pidl "if (!($ndr->flags & LIBNDR_FLAG_REF_ALLOC) && _level != $switch_var) {";
- indent;
- } else {
- pidl "if (_level != $switch_var) {";
- indent;
- }
- pidl "return ndr_pull_error($ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %u in $e->{NAME}\", _level);";
- deindent;
- if ($switch_var =~ /r->/) {
- pidl "} else { $switch_var = _level; }";
- } else {
- pidl "}";
- }
- deindent;
- pidl "}";
- }
+ pidl "NDR_CHECK(ndr_pull_set_switch_value($ndr, $cprefix$var_prefix$e->{NAME}, $switch_var));";
- pidl "NDR_CHECK(ndr_pull_$e->{TYPE}($ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME}));";
}
#####################################################################
@@ -802,16 +779,8 @@ sub ParseSwitchPush($$$$$)
check_null_pointer($switch_var);
- my $utype = typelist::getType($e->{TYPE});
- if (!defined $utype ||
- !util::has_property($utype, "nodiscriminant")) {
- my $e2 = util::find_sibling($e, $switch);
- pidl "if (($ndr_flags) & NDR_SCALARS) {";
- pidl "\tNDR_CHECK(ndr_push_$e2->{TYPE}($ndr, NDR_SCALARS, $switch_var));";
- pidl "}";
- }
+ pidl "NDR_CHECK(ndr_push_set_switch_value($ndr, $cprefix$var_prefix$e->{NAME}, $switch_var));";
- pidl "NDR_CHECK(ndr_push_$e->{TYPE}($ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME}));";
}
#####################################################################
@@ -838,9 +807,11 @@ sub ParseElementPullScalar($$$)
} elsif (need_wire_pointer($e)) {
ParsePtrPull($e, $ptr_prefix.$var_prefix);
} elsif (is_surrounding_array($e)) {
- } elsif (my $switch = util::has_property($e, "switch_is")) {
- ParseSwitchPull($e, $ndr, $var_prefix, $ndr_flags, $switch);
} else {
+ if (my $switch = util::has_property($e, "switch_is")) {
+ ParseSwitchPull($e, $ndr, $var_prefix, $ndr_flags, $switch);
+ }
+
pidl "NDR_CHECK(ndr_pull_$e->{TYPE}($ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
}
@@ -919,9 +890,11 @@ sub ParseElementPushBuffer($$)
if (util::array_size($e)) {
ParseArrayPush($e, $ndr, "r->", $ndr_flags);
- } elsif (my $switch = util::has_property($e, "switch_is")) {
- ParseSwitchPush($e, $ndr, $var_prefix, $ndr_flags, $switch);
} else {
+ if (my $switch = util::has_property($e, "switch_is")) {
+ ParseSwitchPush($e, $ndr, $var_prefix, $ndr_flags, $switch);
+ }
+
pidl "NDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
}
@@ -980,9 +953,11 @@ sub ParseElementPullBuffer($$)
if (util::array_size($e)) {
ParseArrayPull($e, $ndr, "r->", $ndr_flags);
- } elsif (my $switch = util::has_property($e, "switch_is")) {
- ParseSwitchPull($e, $ndr, $var_prefix, $ndr_flags, $switch);
} else {
+ if (my $switch = util::has_property($e, "switch_is")) {
+ ParseSwitchPull($e, $ndr, $var_prefix, $ndr_flags, $switch);
+ }
+
pidl "NDR_CHECK(ndr_pull_$e->{TYPE}($ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
}
@@ -1400,10 +1375,20 @@ sub ParseUnionPush($)
my $e = shift;
my $have_default = 0;
+ pidl "int level;";
+
start_flags($e);
+ pidl "level = ndr_push_get_switch_value(ndr, r);";
+
pidl "if (!(ndr_flags & NDR_SCALARS)) goto buffers;";
+ if (!util::has_property($e, "nodiscriminant")) {
+ my $switch_type = util::has_property($e, "switch_type");
+ $switch_type = "uint32" unless (defined ($switch_type));
+ pidl "NDR_CHECK(ndr_push_$switch_type(ndr, NDR_SCALARS, level));";
+ }
+
pidl "NDR_CHECK(ndr_push_struct_start(ndr));";
# my $align = union_alignment($e);
@@ -1506,11 +1491,30 @@ sub ParseUnionPull($)
{
my $e = shift;
my $have_default = 0;
+ my $switch_type = util::has_property($e, "switch_type");
+ $switch_type = "uint32" unless defined($switch_type);
+
+ pidl "int level;";
+ if (!util::has_property($e, "nodiscriminant")) {
+ if (typelist::typeIs($switch_type, "ENUM")) {
+ $switch_type = typelist::enum_type_fn(typelist::getType($switch_type));
+ }
+ pidl typelist::mapScalarType($switch_type) . " _level;";
+ }
start_flags($e);
+ pidl "level = ndr_pull_get_switch_value(ndr, r);";
+
pidl "if (!(ndr_flags & NDR_SCALARS)) goto buffers;";
+ if (!util::has_property($e, "nodiscriminant")) {
+ pidl "NDR_CHECK(ndr_pull_$switch_type(ndr, NDR_SCALARS, &_level));";
+ pidl "if (_level != level) {";
+ pidl "\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %u for $e->{PARENT}->{NAME}\", _level);";
+ pidl "}";
+ }
+
pidl "NDR_CHECK(ndr_pull_struct_start(ndr));";
# my $align = union_alignment($e);
@@ -1574,7 +1578,7 @@ sub ParseUnionPull($)
sub ArgsUnionPush($)
{
my $e = shift;
- return "struct ndr_push *ndr, int ndr_flags, int level, union $e->{NAME} *r";
+ return "struct ndr_push *ndr, int ndr_flags, union $e->{NAME} *r";
}
sub ArgsUnionPrint($)
@@ -1586,7 +1590,7 @@ sub ArgsUnionPrint($)
sub ArgsUnionPull($)
{
my $e = shift;
- return "struct ndr_pull *ndr, int ndr_flags, int level, union $e->{NAME} *r";
+ return "struct ndr_pull *ndr, int ndr_flags, union $e->{NAME} *r";
}
sub ArgsUnionNdrSize($)
diff --git a/source4/build/pidl/pidl.pl b/source4/build/pidl/pidl.pl
index 6bbb2ec78c..9e1ce48467 100755
--- a/source4/build/pidl/pidl.pl
+++ b/source4/build/pidl/pidl.pl
@@ -137,6 +137,7 @@ sub process_file($)
if ($opt_parse) {
$pidl = IdlParse($idl_file);
defined @$pidl || die "Failed to parse $idl_file";
+ typelist::LoadIdl($pidl);
IdlValidator::Validate($pidl);
if ($opt_keep && !util::SaveStructure($pidl_file, $pidl)) {
die "Failed to save $pidl_file\n";
@@ -157,10 +158,6 @@ sub process_file($)
unlink($tempfile);
}
- if ($opt_header || $opt_parser || $opt_com_header || $opt_dcom_proxy) {
- typelist::LoadIdl($pidl);
- }
-
if ($opt_com_header) {
my $res = COMHeader::Parse($pidl);
if ($res) {
diff --git a/source4/build/pidl/typelist.pm b/source4/build/pidl/typelist.pm
index 2d38d1f18d..432497f9f6 100644
--- a/source4/build/pidl/typelist.pm
+++ b/source4/build/pidl/typelist.pm
@@ -22,6 +22,15 @@ sub getType($)
return $typedefs{$t};
}
+sub typeIs($$)
+{
+ my $t = shift;
+ my $tt = shift;
+
+ return 1 if (hasType($t) and getType($t)->{DATA}->{TYPE} eq $tt);
+ return 0;
+}
+
sub hasType($)
{
my $t = shift;
diff --git a/source4/build/pidl/validator.pm b/source4/build/pidl/validator.pm
index 1636a155e3..bbef008ee5 100644
--- a/source4/build/pidl/validator.pm
+++ b/source4/build/pidl/validator.pm
@@ -45,6 +45,25 @@ sub ValidElement($)
fatal(el_name($e) . " : pidl does not support full NDR pointers yet\n");
}
+ # Check whether switches are used correctly.
+ if (my $switch = util::has_property($e, "switch_is")) {
+ my $e2 = util::find_sibling($e, $switch);
+ my $type = typelist::getType($e->{TYPE});
+
+ if (defined($type) and $type->{DATA}->{TYPE} ne "UNION") {
+ fatal(el_name($e) . ": switch_is() used on non-union type $e->{TYPE} which is a $type->{DATA}->{TYPE}");
+ }
+
+ if (!util::has_property($type, "nodiscriminant") and defined($e2)) {
+ my $discriminator_type = util::has_property($type, "switch_type");
+ $discriminator_type = "uint32" unless defined ($discriminator_type);
+
+ if ($e2->{TYPE} ne $discriminator_type) {
+ print el_name($e) . ": Warning: switch_is() is of type $e2->{TYPE}, while discriminator type for union $type->{NAME} is $discriminator_type\n";
+ }
+ }
+ }
+
if (util::has_property($e, "size_is") and not defined ($e->{ARRAY_LEN})) {
fatal(el_name($e) . " : size_is() on non-array element");
}
@@ -53,7 +72,6 @@ sub ValidElement($)
fatal(el_name($e) . " : length_is() on non-array element");
}
-
if (!$e->{POINTERS} && (
util::has_property($e, "ptr") or
util::has_property($e, "unique") or
@@ -84,6 +102,11 @@ sub ValidStruct($)
sub ValidUnion($)
{
my($union) = shift;
+
+ if (util::has_property($union->{PARENT}, "nodiscriminant") and util::has_property($union->{PARENT}, "switch_type")) {
+ fatal($union->{PARENT}->{NAME} . ": switch_type() on union without discriminant");
+ }
+
foreach my $e (@{$union->{ELEMENTS}}) {
$e->{PARENT} = $union;
diff --git a/source4/librpc/idl/drsuapi.idl b/source4/librpc/idl/drsuapi.idl
index 72197aec16..759599e707 100644
--- a/source4/librpc/idl/drsuapi.idl
+++ b/source4/librpc/idl/drsuapi.idl
@@ -127,7 +127,7 @@ interface drsuapi
uint32 unknown1;
} drsuapi_DsReplicaSyncRequest1;
- typedef union {
+ typedef [switch_type(int32)] union {
[case(1)] drsuapi_DsReplicaSyncRequest1 req1;
} drsuapi_DsReplicaSyncRequest;
@@ -222,7 +222,7 @@ interface drsuapi
[size_is(count)] drsuapi_DsNameString *names[];
} drsuapi_DsNameRequest1;
- typedef union {
+ typedef [switch_type(int32)] union {
[case(1)] drsuapi_DsNameRequest1 req1;
} drsuapi_DsNameRequest;
@@ -237,7 +237,7 @@ interface drsuapi
[size_is(count)] drsuapi_DsNameInfo1 *array[];
} drsuapi_DsNameCtr1;
- typedef union {
+ typedef [switch_type(int32)] union {
[case(1)] drsuapi_DsNameCtr1 *ctr1;
} drsuapi_DsNameCtr;
@@ -264,7 +264,7 @@ interface drsuapi
[size_is(count)] drsuapi_DsNameString *spn_names[];
} drsuapi_DsWriteAccountSpnRequest1;
- typedef union {
+ typedef [switch_type(int32)] union {
[case(1)] drsuapi_DsWriteAccountSpnRequest1 req1;
} drsuapi_DsWriteAccountSpnRequest;
@@ -272,7 +272,7 @@ interface drsuapi
WERROR status;
} drsuapi_DsWriteAccountSpnResult1;
- typedef union {
+ typedef [switch_type(int32)] union {
[case(1)] drsuapi_DsWriteAccountSpnResult1 res1;
} drsuapi_DsWriteAccountSpnResult;
@@ -298,7 +298,7 @@ interface drsuapi
int32 level; /* specifies the switch level for the request */
} drsuapi_DsGetDCInfoRequest1;
- typedef union {
+ typedef [switch_type(int32)] union {
[case(1)] drsuapi_DsGetDCInfoRequest1 req1;
} drsuapi_DsGetDCInfoRequest;
@@ -354,7 +354,7 @@ interface drsuapi
[size_is(count)] drsuapi_DsGetDCInfo01 *array[];
} drsuapi_DsGetDCInfoCtr01;
- typedef union {
+ typedef [switch_type(int32)] union {
[case(1)] drsuapi_DsGetDCInfoCtr1 ctr1;
[case(2)] drsuapi_DsGetDCInfoCtr2 ctr2;
[case(-1)] drsuapi_DsGetDCInfoCtr01 ctr01;
@@ -416,7 +416,7 @@ interface drsuapi
uint32 unknown2;
} drsuapi_DsReplicaGetInfoRequest2;
- typedef union {
+ typedef [switch_type(drsuapi_DsReplicaGetInfoLevel)] union {
[case(DRSUAPI_DS_REPLICA_GET_INFO)] drsuapi_DsReplicaGetInfoRequest1 req1;
[case(DRSUAPI_DS_REPLICA_GET_INFO2)] drsuapi_DsReplicaGetInfoRequest2 req2;
} drsuapi_DsReplicaGetInfoRequest;
@@ -628,7 +628,7 @@ interface drsuapi
[size_is(count)] drsuapi_DsReplica06 array[];
} drsuapi_DsReplica06Ctr;
- typedef union {
+ typedef [switch_type(drsuapi_DsReplicaInfoType)] union {
[case(DRSUAPI_DS_REPLICA_INFO_NEIGHBORS)] drsuapi_DsReplicaNeighbourCtr *neighbours;
[case(DRSUAPI_DS_REPLICA_INFO_CURSORS)] drsuapi_DsReplicaCoursorCtr *coursors;
[case(DRSUAPI_DS_REPLICA_INFO_OBJ_METADATA)] drsuapi_DsReplicaObjMetaDataCtr *objmetadata;
diff --git a/source4/librpc/idl/dssetup.idl b/source4/librpc/idl/dssetup.idl
index 9a4fcafccc..098a148904 100644
--- a/source4/librpc/idl/dssetup.idl
+++ b/source4/librpc/idl/dssetup.idl
@@ -72,7 +72,7 @@
DS_ROLE_OP_STATUS = 3
} dssetup_DsRoleInfoLevel;
- typedef union {
+ typedef [switch_type(dssetup_DsRoleInfoLevel)] union {
[case(DS_ROLE_BASIC_INFORMATION)] dssetup_DsRolePrimaryDomInfoBasic basic;
[case(DS_ROLE_UPGRADE_STATUS)] dssetup_DsRoleUpgradeStatus upgrade;
[case(DS_ROLE_OP_STATUS)] dssetup_DsRoleOpStatus opstatus;
diff --git a/source4/librpc/idl/echo.idl b/source4/librpc/idl/echo.idl
index e7a2571235..86e16763c2 100644
--- a/source4/librpc/idl/echo.idl
+++ b/source4/librpc/idl/echo.idl
@@ -75,7 +75,7 @@ interface rpcecho
echo_info4 info4;
} echo_info7;
- typedef union {
+ typedef [switch_type(uint16)] union {
[case(1)] echo_info1 info1;
[case(2)] echo_info2 info2;
[case(3)] echo_info3 info3;
@@ -109,7 +109,7 @@ interface rpcecho
echo_Enum1_32 e2;
} echo_Enum2;
- typedef union {
+ typedef [switch_type(echo_Enum1)] union {
[case(ECHO_ENUM1)] echo_Enum1 e1;
[case(ECHO_ENUM2)] echo_Enum2 e2;
} echo_Enum3;
diff --git a/source4/librpc/idl/lsa.idl b/source4/librpc/idl/lsa.idl
index 8b20b6db90..68adcf1d9d 100644
--- a/source4/librpc/idl/lsa.idl
+++ b/source4/librpc/idl/lsa.idl
@@ -191,7 +191,7 @@
LSA_POLICY_INFO_DNS=12
} lsaPolicyInfo;
- typedef union {
+ typedef [switch_type(uint16)] union {
[case(LSA_POLICY_INFO_AUDIT_LOG)] lsa_AuditLogInfo audit_log;
[case(LSA_POLICY_INFO_AUDIT_EVENTS)] lsa_AuditEventsInfo audit_events;
[case(LSA_POLICY_INFO_DOMAIN)] lsa_DomainInfo domain;
@@ -515,7 +515,7 @@
lsa_TrustDomainInfoAuthInfo auth_info;
} lsa_TrustDomainInfoInfoAll;
- typedef union {
+ typedef [switch_type(lsa_TrustDomInfoEnum)] union {
[case(LSA_TRUSTED_DOMAIN_INFO_NAME)] lsa_TrustDomainInfoName name;
[case(LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET)] lsa_TrustDomainInfoPosixOffset posix_offset;
[case(LSA_TRUSTED_DOMAIN_INFO_PASSWORD)] lsa_TrustDomainInfoPassword password;
diff --git a/source4/librpc/idl/netlogon.idl b/source4/librpc/idl/netlogon.idl
index 5a7477bdfb..b99f13638d 100644
--- a/source4/librpc/idl/netlogon.idl
+++ b/source4/librpc/idl/netlogon.idl
@@ -118,7 +118,7 @@ interface netlogon
netr_ChallengeResponse lm;
} netr_NetworkInfo;
- typedef union {
+ typedef [switch_type(uint16)] union {
[case(1)] netr_PasswordInfo *password;
[case(2)] netr_NetworkInfo *network;
[case(3)] netr_PasswordInfo *password;
@@ -208,7 +208,7 @@ interface netlogon
netr_String unknown4;
} netr_PacInfo;
- typedef union {
+ typedef [switch_type(uint16)] union {
[case(2)] netr_SamInfo2 *sam2;
[case(3)] netr_SamInfo3 *sam3;
[case(4)] netr_PacInfo *pac;
@@ -613,7 +613,7 @@ interface netlogon
NETR_DELTA_MODIFY_COUNT = 22
} netr_DeltaEnum;
- typedef union {
+ typedef [switch_type(netr_DeltaEnum)] union {
[case(NETR_DELTA_DOMAIN)] netr_DELTA_DOMAIN *domain;
[case(NETR_DELTA_GROUP)] netr_DELTA_GROUP *group;
[case(NETR_DELTA_DELETE_GROUP)] ; /* rid only */
@@ -638,7 +638,7 @@ interface netlogon
[case(NETR_DELTA_MODIFY_COUNT)] udlong *modified_count;
} netr_DELTA_UNION;
- typedef union {
+ typedef [switch_type(netr_DeltaEnum)] union {
[case(NETR_DELTA_DOMAIN)] uint32 rid;
[case(NETR_DELTA_GROUP)] uint32 rid;
[case(NETR_DELTA_DELETE_GROUP)] uint32 rid;
diff --git a/source4/librpc/idl/samr.idl b/source4/librpc/idl/samr.idl
index 85f032c414..e8b269dc66 100644
--- a/source4/librpc/idl/samr.idl
+++ b/source4/librpc/idl/samr.idl
@@ -202,7 +202,7 @@
uint32 unknown2;
} samr_DomInfo13;
- typedef union {
+ typedef [switch_type(uint16)] union {
[case(1)] samr_DomInfo1 info1;
[case(2)] samr_DomInfo2 info2;
[case(3)] samr_DomInfo3 info3;
@@ -383,7 +383,7 @@
GROUPINFOALL2 = 5
} samr_GroupInfoEnum;
- typedef union {
+ typedef [switch_type(samr_GroupInfoEnum)] union {
[case(GROUPINFOALL)] samr_GroupInfoAll all;
[case(GROUPINFONAME)] samr_String name;
[case(GROUPINFOX)] samr_GroupInfoX unknown;
@@ -482,7 +482,7 @@
ALIASINFODESCRIPTION = 3
} samr_AliasInfoEnum;
- typedef union {
+ typedef [switch_type(samr_AliasInfoEnum)] union {
[case(ALIASINFOALL)] samr_AliasInfoAll all;
[case(ALIASINFONAME)] samr_String name;
[case(ALIASINFODESCRIPTION)] samr_String description;
@@ -745,7 +745,7 @@
uint8 pw_len;
} samr_UserInfo26;
- typedef union {
+ typedef [switch_type(uint16)] union {
[case(1)] samr_UserInfo1 info1;
[case(2)] samr_UserInfo2 info2;
[case(3)] samr_UserInfo3 info3;
@@ -873,7 +873,7 @@
[size_is(count)] samr_DispEntryAscii *entries[];
} samr_DispInfoAscii;
- typedef union {
+ typedef [switch_type(uint16)] union {
[case(1)] samr_DispInfoGeneral info1;/* users */
[case(2)] samr_DispInfoFull info2; /* trust accounts? */
[case(3)] samr_DispInfoFull info3; /* groups */
diff --git a/source4/librpc/idl/xattr.idl b/source4/librpc/idl/xattr.idl
index 84d055ea88..4aa92ca5b2 100644
--- a/source4/librpc/idl/xattr.idl
+++ b/source4/librpc/idl/xattr.idl
@@ -44,7 +44,7 @@ interface xattr
utf8string name; /* will be used for case-insensitive speedup */
} xattr_DosInfo2;
- typedef union {
+ typedef [switch_type(uint16)] union {
[case(1)] xattr_DosInfo1 info1;
[case(2)] xattr_DosInfo2 info2;
} xattr_DosInfo;
@@ -102,7 +102,7 @@ interface xattr
*/
const string XATTR_NTACL_NAME = "security.NTACL";
- typedef union {
+ typedef [switch_type(uint16)] union {
[case(1)] security_descriptor *sd;
} xattr_NTACL_Info;
diff --git a/source4/librpc/ndr/libndr.h b/source4/librpc/ndr/libndr.h
index 4880df43bd..e2ac4279f1 100644
--- a/source4/librpc/ndr/libndr.h
+++ b/source4/librpc/ndr/libndr.h
@@ -49,6 +49,7 @@ struct ndr_pull {
struct ndr_token_list *relative_list;
struct ndr_token_list *array_size_list;
struct ndr_token_list *array_length_list;
+ struct ndr_token_list *switch_list;
/* this is used to ensure we generate unique reference IDs
between request and reply */
@@ -68,6 +69,7 @@ struct ndr_push {
uint32_t alloc_size;
uint32_t offset;
+ struct ndr_token_list *switch_list;
struct ndr_token_list *relative_list;
/* this is used to ensure we generate unique reference IDs */
diff --git a/source4/librpc/ndr/ndr.c b/source4/librpc/ndr/ndr.c
index 549230bb29..2e350aa0da 100644
--- a/source4/librpc/ndr/ndr.c
+++ b/source4/librpc/ndr/ndr.c
@@ -642,6 +642,32 @@ NTSTATUS ndr_check_array_length(struct ndr_pull *ndr, void *p, uint32_t length)
}
/*
+ store a switch value
+ */
+NTSTATUS ndr_push_set_switch_value(struct ndr_push *ndr, void *p, uint32_t val)
+{
+ return ndr_token_store(ndr, &ndr->switch_list, p, val);
+}
+
+NTSTATUS ndr_pull_set_switch_value(struct ndr_pull *ndr, void *p, uint32_t val)
+{
+ return ndr_token_store(ndr, &ndr->switch_list, p, val);
+}
+
+/*
+ retrieve a switch value
+ */
+uint32_t ndr_push_get_switch_value(struct ndr_push *ndr, void *p)
+{
+ return ndr_token_peek(&ndr->switch_list, p);
+}
+
+uint32_t ndr_pull_get_switch_value(struct ndr_pull *ndr, void *p)
+{
+ return ndr_token_peek(&ndr->switch_list, p);
+}
+
+/*
pull a relative object - stage1
called during SCALARS processing
*/
diff --git a/source4/librpc/ndr/ndr_spoolss_buf.c b/source4/librpc/ndr/ndr_spoolss_buf.c
index e13e912b68..4b1483709a 100644
--- a/source4/librpc/ndr/ndr_spoolss_buf.c
+++ b/source4/librpc/ndr/ndr_spoolss_buf.c
@@ -39,7 +39,8 @@
for (i=0;i<r->out.count;i++) {\
ndr2->data += ndr2->offset;\
ndr2->offset = 0;\
- NDR_CHECK(ndr_push_##type(ndr2, NDR_SCALARS|NDR_BUFFERS, r->in.level, &(*r->out.info)[i]));\
+ NDR_CHECK(ndr_push_set_switch_value(ndr2, &(*r->out.info)[i], r->in.level)); \
+ NDR_CHECK(ndr_push_##type(ndr2, NDR_SCALARS|NDR_BUFFERS, &(*r->out.info)[i]));\
}\
if (*r->in.buf_size >= ndr2->offset) {\
buffer = data_blob_const(ndr2->data, ndr2->offset);\
@@ -94,7 +95,8 @@
for (i=0;i<r->out.count;i++) {\
ndr2->data += ndr2->offset;\
ndr2->offset = 0;\
- NDR_CHECK(ndr_pull_##type(ndr2, NDR_SCALARS|NDR_BUFFERS, r->in.level, &(*r->out.info)[i]));\
+ NDR_CHECK(ndr_pull_set_switch_value(ndr2, &(*r->out.info)[i], r->in.level)); \
+ NDR_CHECK(ndr_pull_##type(ndr2, NDR_SCALARS|NDR_BUFFERS, &(*r->out.info)[i]));\
}\
}\
} while(0)