From ffae01d432c715961c44e499258ee2a9f7e3d5f1 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 6 Mar 2005 17:02:14 +0000 Subject: r5672: Use switch_type() and the token storage mechanism for unions: - 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) --- source4/build/pidl/ndr.pm | 94 +++++++++++++++++++----------------- source4/build/pidl/pidl.pl | 5 +- source4/build/pidl/typelist.pm | 9 ++++ source4/build/pidl/validator.pm | 25 +++++++++- source4/librpc/idl/drsuapi.idl | 18 +++---- source4/librpc/idl/dssetup.idl | 2 +- source4/librpc/idl/echo.idl | 4 +- source4/librpc/idl/lsa.idl | 4 +- source4/librpc/idl/netlogon.idl | 8 +-- source4/librpc/idl/samr.idl | 10 ++-- source4/librpc/idl/xattr.idl | 4 +- source4/librpc/ndr/libndr.h | 2 + source4/librpc/ndr/ndr.c | 26 ++++++++++ source4/librpc/ndr/ndr_spoolss_buf.c | 6 ++- 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 @@ -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 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;iout.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;iout.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) -- cgit