r5672: Use switch_type() and the token storage mechanism for unions:
authorJelmer Vernooij <jelmer@samba.org>
Sun, 6 Mar 2005 17:02:14 +0000 (17:02 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:10:58 +0000 (13:10 -0500)
 - Makes union handling less special
 - Allows unions in arrays, etc
 - Compatible with midl
 - Pidl will warn about switch_type() and the type of the switch_is() variable being different
(This used to be commit dc6b4ffc82a191631bc16a4b93a4916a39183ec6)

14 files changed:
source4/build/pidl/ndr.pm
source4/build/pidl/pidl.pl
source4/build/pidl/typelist.pm
source4/build/pidl/validator.pm
source4/librpc/idl/drsuapi.idl
source4/librpc/idl/dssetup.idl
source4/librpc/idl/echo.idl
source4/librpc/idl/lsa.idl
source4/librpc/idl/netlogon.idl
source4/librpc/idl/samr.idl
source4/librpc/idl/xattr.idl
source4/librpc/ndr/libndr.h
source4/librpc/ndr/ndr.c
source4/librpc/ndr/ndr_spoolss_buf.c

index 333f20e78f19423153d308fe7d799cae56e9262a..ac65f16d95e3857d6ca30e4345a8dcd14793e4fe 100644 (file)
@@ -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($)
index 6bbb2ec78c946df75f135a30a5df00071db8f616..9e1ce48467e1bc2b0e73b3804ce7713ae60ab874 100755 (executable)
@@ -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) {
index 2d38d1f18d5a77e5ba12abcb7dc500b5f22c30b5..432497f9f6b8b39557ce9668bd1d58b64d4130d9 100644 (file)
@@ -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;
index 1636a155e30fba7945b7aeb5848cd4f54d8f0978..bbef008ee50c95839ea5b3c6335ad29ab29a2195 100644 (file)
@@ -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;
 
index 72197aec160697981e1f558c65c20e95cafa6d8d..759599e7076cebf8d38fc780738320fe60105d7d 100644 (file)
@@ -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;
index 9a4fcafcccb8a813b5dac45f441b57d4b11d7031..098a14890497dfe685e6857f939840da9a8cca2a 100644 (file)
@@ -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;
index e7a2571235e85bcd9d08890d9e56075680eb1f49..86e16763c2bea7d2e97b657426a50db314026d7e 100644 (file)
@@ -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;
index 8b20b6db903071f1d4b56d93fcbb670b0f9b91e3..68adcf1d9dc7e5f74e7f66ca929d2b0f2d841030 100644 (file)
                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;
                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;
index 5a7477bdfbe83da1fee2da6494eba0ce77165273..b99f13638d1aa450beaa0891bb28c9227253c7f8 100644 (file)
@@ -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;
index 85f032c41481bdc4896edb41ea8d6d9a7f1a9a71..e8b269dc66194ede58aca5b352a64149322b45cb 100644 (file)
                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;
                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;
                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;
                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;
                [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 */
index 84d055ea886bf0464101d4a5b5a5c5fa9e731bbd..4aa92ca5b2d00d40e1f8a5b945ccd6dae0e2577a 100644 (file)
@@ -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;
 
index 4880df43bdfc9a94b944f03e28474b35e5ac70b2..e2ac4279f1d71a0d9720ab3c1d3c28ee3f74aef3 100644 (file)
@@ -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 */
index 549230bb29cd2285608ea5d0a141f17aada80e62..2e350aa0da7e72a880ecc17c2d63f40fa77d5c3f 100644 (file)
@@ -641,6 +641,32 @@ NTSTATUS ndr_check_array_length(struct ndr_pull *ndr, void *p, uint32_t length)
        return NT_STATUS_OK;
 }
 
+/*
+  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
index e13e912b68f26578fba2e693471f2ea4eea3f930..4b1483709aa10db48d06821abb97563c2a1a5c54 100644 (file)
@@ -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)