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}));";
}
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}));";
}
#####################################################################
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}));";
}
#####################################################################
} 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}));";
}
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}));";
}
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}));";
}
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);
{
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);
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($)
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($)
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";
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) {
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;
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");
}
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
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;
uint32 unknown1;
} drsuapi_DsReplicaSyncRequest1;
- typedef union {
+ typedef [switch_type(int32)] union {
[case(1)] drsuapi_DsReplicaSyncRequest1 req1;
} drsuapi_DsReplicaSyncRequest;
[size_is(count)] drsuapi_DsNameString *names[];
} drsuapi_DsNameRequest1;
- typedef union {
+ typedef [switch_type(int32)] union {
[case(1)] drsuapi_DsNameRequest1 req1;
} drsuapi_DsNameRequest;
[size_is(count)] drsuapi_DsNameInfo1 *array[];
} drsuapi_DsNameCtr1;
- typedef union {
+ typedef [switch_type(int32)] union {
[case(1)] drsuapi_DsNameCtr1 *ctr1;
} drsuapi_DsNameCtr;
[size_is(count)] drsuapi_DsNameString *spn_names[];
} drsuapi_DsWriteAccountSpnRequest1;
- typedef union {
+ typedef [switch_type(int32)] union {
[case(1)] drsuapi_DsWriteAccountSpnRequest1 req1;
} drsuapi_DsWriteAccountSpnRequest;
WERROR status;
} drsuapi_DsWriteAccountSpnResult1;
- typedef union {
+ typedef [switch_type(int32)] union {
[case(1)] drsuapi_DsWriteAccountSpnResult1 res1;
} drsuapi_DsWriteAccountSpnResult;
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;
[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;
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;
[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;
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;
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;
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;
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;
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;
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;
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 */
[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;
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 */
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;
*/
const string XATTR_NTACL_NAME = "security.NTACL";
- typedef union {
+ typedef [switch_type(uint16)] union {
[case(1)] security_descriptor *sd;
} xattr_NTACL_Info;
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 */
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 */
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
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);\
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)