15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/policy_engine_opcodes.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/sandbox_nt_types.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/sandbox_types.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const unsigned short kMaxUniStrSize = 0xfffc;
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool InitStringUnicode(const wchar_t* source, size_t length,
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       UNICODE_STRING* ustring) {
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ustring->Buffer = const_cast<wchar_t*>(source);
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ustring->Length = static_cast<USHORT>(length) * sizeof(wchar_t);
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (length > kMaxUniStrSize) {
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ustring->MaximumLength = (NULL != source) ?
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                ustring->Length + sizeof(wchar_t) : 0;
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace sandbox {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SANDBOX_INTERCEPT NtExports g_nt;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note: The opcodes are implemented as functions (as opposed to classes derived
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// from PolicyOpcode) because you should not add more member variables to the
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// PolicyOpcode class since it would cause object slicing on the target. So to
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// enforce that (instead of just trusting the developer) the opcodes became
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// just functions.
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In the code that follows I have keep the evaluation function and the factory
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// function together to stress the close relationship between both. For example,
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// only the factory method and the evaluation function know the stored argument
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// order and meaning.
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <int>
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EvalResult OpcodeEval(PolicyOpcode* opcode, const ParameterSet* pp,
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      MatchContext* match);
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Opcode OpAlwaysFalse:
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Does not require input parameter.
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PolicyOpcode* OpcodeFactory::MakeOpAlwaysFalse(uint32 options) {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return MakeBase(OP_ALWAYS_FALSE, options, -1);
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <>
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EvalResult OpcodeEval<OP_ALWAYS_FALSE>(PolicyOpcode* opcode,
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       const ParameterSet* param,
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       MatchContext* context) {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNREFERENCED_PARAMETER(opcode);
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNREFERENCED_PARAMETER(param);
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNREFERENCED_PARAMETER(context);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return EVAL_FALSE;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Opcode OpAlwaysTrue:
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Does not require input parameter.
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PolicyOpcode* OpcodeFactory::MakeOpAlwaysTrue(uint32 options) {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return MakeBase(OP_ALWAYS_TRUE, options, -1);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <>
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EvalResult OpcodeEval<OP_ALWAYS_TRUE>(PolicyOpcode* opcode,
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      const ParameterSet* param,
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      MatchContext* context) {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNREFERENCED_PARAMETER(opcode);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNREFERENCED_PARAMETER(param);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNREFERENCED_PARAMETER(context);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return EVAL_TRUE;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Opcode OpAction:
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Does not require input parameter.
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Argument 0 contains the actual action to return.
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PolicyOpcode* OpcodeFactory::MakeOpAction(EvalResult action,
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          uint32 options) {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PolicyOpcode* opcode = MakeBase(OP_ACTION, options, 0);
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NULL == opcode) return NULL;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  opcode->SetArgument(0, action);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return opcode;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <>
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EvalResult OpcodeEval<OP_ACTION>(PolicyOpcode* opcode,
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const ParameterSet* param,
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 MatchContext* context) {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNREFERENCED_PARAMETER(param);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNREFERENCED_PARAMETER(context);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int action = 0;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  opcode->GetArgument(0, &action);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return static_cast<EvalResult>(action);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Opcode OpNumberMatch:
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Requires a unsigned long or void* in selected_param
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Argument 0 is the stored number to match.
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Argument 1 is the C++ type of the 0th argument.
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PolicyOpcode* OpcodeFactory::MakeOpNumberMatch(int16 selected_param,
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               unsigned long match,
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               uint32 options) {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PolicyOpcode* opcode = MakeBase(OP_NUMBER_MATCH, options, selected_param);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NULL == opcode) return NULL;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  opcode->SetArgument(0, match);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  opcode->SetArgument(1, ULONG_TYPE);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return opcode;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PolicyOpcode* OpcodeFactory::MakeOpVoidPtrMatch(int16 selected_param,
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                const void* match,
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                uint32 options) {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PolicyOpcode* opcode = MakeBase(OP_NUMBER_MATCH, options, selected_param);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NULL == opcode) return NULL;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  opcode->SetArgument(0, match);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  opcode->SetArgument(1, VOIDPTR_TYPE);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return opcode;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <>
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EvalResult OpcodeEval<OP_NUMBER_MATCH>(PolicyOpcode* opcode,
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       const ParameterSet* param,
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       MatchContext* context) {
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNREFERENCED_PARAMETER(context);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned long value_ulong = 0;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (param->Get(&value_ulong)) {
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned long match_ulong = 0;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    opcode->GetArgument(0, &match_ulong);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return (match_ulong != value_ulong)? EVAL_FALSE : EVAL_TRUE;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const void* value_ptr = NULL;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (param->Get(&value_ptr)) {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const void* match_ptr = NULL;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      opcode->GetArgument(0, &match_ptr);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return (match_ptr != value_ptr)? EVAL_FALSE : EVAL_TRUE;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return EVAL_ERROR;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Opcode OpUlongMatchRange
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Requires a unsigned long in selected_param.
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Argument 0 is the stored lower bound to match.
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Argument 1 is the stored upper bound to match.
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PolicyOpcode* OpcodeFactory::MakeOpUlongMatchRange(int16 selected_param,
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   unsigned long lower_bound,
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   unsigned long upper_bound,
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   uint32 options) {
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (lower_bound > upper_bound) {
165c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return NULL;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PolicyOpcode* opcode = MakeBase(OP_ULONG_MATCH_RANGE, options,
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  selected_param);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NULL == opcode) return NULL;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  opcode->SetArgument(0, lower_bound);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  opcode->SetArgument(1, upper_bound);
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return opcode;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <>
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EvalResult OpcodeEval<OP_ULONG_MATCH_RANGE>(PolicyOpcode* opcode,
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            const ParameterSet* param,
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            MatchContext* context) {
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNREFERENCED_PARAMETER(context);
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned long value = 0;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!param->Get(&value)) return EVAL_ERROR;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned long lower_bound = 0;
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned long upper_bound = 0;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  opcode->GetArgument(0, &lower_bound);
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  opcode->GetArgument(1, &upper_bound);
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return((lower_bound <= value) && (upper_bound >= value))?
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EVAL_TRUE : EVAL_FALSE;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Opcode OpUlongAndMatch:
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Requires a unsigned long in selected_param.
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Argument 0 is the stored number to match.
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PolicyOpcode* OpcodeFactory::MakeOpUlongAndMatch(int16 selected_param,
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 unsigned long match,
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 uint32 options) {
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PolicyOpcode* opcode = MakeBase(OP_ULONG_AND_MATCH, options, selected_param);
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NULL == opcode) return NULL;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  opcode->SetArgument(0, match);
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return opcode;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <>
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EvalResult OpcodeEval<OP_ULONG_AND_MATCH>(PolicyOpcode* opcode,
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          const ParameterSet* param,
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          MatchContext* context) {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNREFERENCED_PARAMETER(context);
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned long value = 0;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!param->Get(&value)) return EVAL_ERROR;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned long number = 0;
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  opcode->GetArgument(0, &number);
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (number & value)? EVAL_TRUE : EVAL_FALSE;
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Opcode OpWStringMatch:
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Requires a wchar_t* in selected_param.
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Argument 0 is the byte displacement of the stored string.
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Argument 1 is the lenght in chars of the stored string.
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Argument 2 is the offset to apply on the input string. It has special values.
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// as noted in the header file.
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Argument 3 is the string matching options.
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PolicyOpcode* OpcodeFactory::MakeOpWStringMatch(int16 selected_param,
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                const wchar_t* match_str,
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                int start_position,
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                StringMatchOptions match_opts,
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                uint32 options) {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NULL == match_str) {
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ('\0' == match_str[0]) {
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int lenght = lstrlenW(match_str);
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PolicyOpcode* opcode = MakeBase(OP_WSTRING_MATCH, options, selected_param);
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NULL == opcode) {
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ptrdiff_t delta_str = AllocRelative(opcode, match_str, wcslen(match_str)+1);
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (0 == delta_str) {
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  opcode->SetArgument(0, delta_str);
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  opcode->SetArgument(1, lenght);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  opcode->SetArgument(2, start_position);
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  opcode->SetArgument(3, match_opts);
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return opcode;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<>
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EvalResult OpcodeEval<OP_WSTRING_MATCH>(PolicyOpcode* opcode,
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        const ParameterSet* param,
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        MatchContext* context) {
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NULL == context) {
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return EVAL_ERROR;
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const wchar_t* source_str = NULL;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!param->Get(&source_str)) return EVAL_ERROR;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int start_position = 0;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int match_len = 0;
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int match_opts = 0;
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  opcode->GetArgument(1, &match_len);
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  opcode->GetArgument(2, &start_position);
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  opcode->GetArgument(3, &match_opts);
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const wchar_t* match_str = opcode->GetRelativeString(0);
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Advance the source string to the last successfully evaluated position
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // according to the match context.
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  source_str = &source_str[context->position];
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int source_len  = static_cast<int>(g_nt.wcslen(source_str));
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (0 == source_len) {
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If we reached the end of the source string there is nothing we can
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // match against.
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return EVAL_FALSE;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (match_len > source_len) {
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // There can't be a positive match when the target string is bigger than
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the source string
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return EVAL_FALSE;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BOOL case_sensitive = (match_opts & CASE_INSENSITIVE) ? TRUE : FALSE;
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We have three cases, depending on the value of start_pos:
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Case 1. We skip N characters and compare once.
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Case 2: We skip to the end and compare once.
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Case 3: We match the first substring (if we find any).
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (start_position >= 0) {
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (kSeekToEnd == start_position) {
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        start_position = source_len - match_len;
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (match_opts & EXACT_LENGHT) {
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // A sub-case of case 3 is when the EXACT_LENGHT flag is on
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // the match needs to be not just substring but full match.
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if ((match_len + start_position) != source_len) {
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return EVAL_FALSE;
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Advance start_pos characters. Warning! this does not consider
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // utf16 encodings (surrogate pairs) or other Unicode 'features'.
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    source_str += start_position;
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Since we skipped, lets reevaluate just the lengths again.
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((match_len + start_position) > source_len) {
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return EVAL_FALSE;
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UNICODE_STRING match_ustr;
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InitStringUnicode(match_str, match_len, &match_ustr);
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UNICODE_STRING source_ustr;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InitStringUnicode(source_str, match_len, &source_ustr);
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (0 == g_nt.RtlCompareUnicodeString(&match_ustr, &source_ustr,
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          case_sensitive)) {
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Match! update the match context.
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context->position += start_position + match_len;
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return EVAL_TRUE;
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return EVAL_FALSE;
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (start_position < 0) {
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UNICODE_STRING match_ustr;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InitStringUnicode(match_str, match_len, &match_ustr);
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UNICODE_STRING source_ustr;
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InitStringUnicode(source_str, match_len, &source_ustr);
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    do {
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (0 == g_nt.RtlCompareUnicodeString(&match_ustr, &source_ustr,
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            case_sensitive)) {
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Match! update the match context.
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        context->position += (source_ustr.Buffer - source_str) + match_len;
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return EVAL_TRUE;
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++source_ustr.Buffer;
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      --source_len;
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } while (source_len >= match_len);
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return EVAL_FALSE;
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OpcodeMaker (other member functions).
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PolicyOpcode* OpcodeFactory::MakeBase(OpcodeID opcode_id,
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      uint32 options,
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      int16 selected_param) {
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (memory_size() < sizeof(PolicyOpcode)) {
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create opcode using placement-new on the buffer memory.
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PolicyOpcode* opcode = new(memory_top_) PolicyOpcode();
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Fill in the standard fields, that every opcode has.
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memory_top_ += sizeof(PolicyOpcode);
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  opcode->opcode_id_ = opcode_id;
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  opcode->options_ = static_cast<int16>(options);
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  opcode->parameter_ = selected_param;
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return opcode;
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ptrdiff_t OpcodeFactory::AllocRelative(void* start, const wchar_t* str,
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       size_t lenght) {
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t bytes = lenght * sizeof(wchar_t);
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (memory_size() < bytes) {
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memory_bottom_ -= bytes;
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (reinterpret_cast<UINT_PTR>(memory_bottom_) & 1) {
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(cpu) replace this for something better.
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::DebugBreak();
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(memory_bottom_, str, bytes);
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ptrdiff_t delta = memory_bottom_ - reinterpret_cast<char*>(start);
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return delta;
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Opcode evaluation dispatchers.
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This function is the one and only entry for evaluating any opcode. It is
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in charge of applying any relevant opcode options and calling EvaluateInner
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// were the actual dispatch-by-id is made. It would seem at first glance that
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the dispatch should be done by virtual function (vtable) calls but you have
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to remember that the opcodes are made in the broker process and copied as
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// raw memory to the target process.
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EvalResult PolicyOpcode::Evaluate(const ParameterSet* call_params,
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  size_t param_count, MatchContext* match) {
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NULL == call_params) {
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return EVAL_ERROR;
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ParameterSet* selected_param = NULL;
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (parameter_ >= 0) {
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (static_cast<size_t>(parameter_) >= param_count) {
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return EVAL_ERROR;
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    selected_param = &call_params[parameter_];
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EvalResult result = EvaluateHelper(selected_param, match);
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Apply the general options regardless of the particular type of opcode.
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (kPolNone == options_) {
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (options_ & kPolNegateEval) {
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (EVAL_TRUE == result) {
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result = EVAL_FALSE;
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (EVAL_FALSE == result) {
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result = EVAL_TRUE;
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (EVAL_ERROR != result) {
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result = EVAL_ERROR;
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NULL != match) {
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (options_ & kPolClearContext) {
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      match->Clear();
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (options_ & kPolUseOREval) {
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      match->options = kPolUseOREval;
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define OPCODE_EVAL(op, x, y, z) case op: return OpcodeEval<op>(x, y, z)
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EvalResult PolicyOpcode::EvaluateHelper(const ParameterSet* parameters,
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       MatchContext* match) {
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (opcode_id_) {
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OPCODE_EVAL(OP_ALWAYS_FALSE, this, parameters, match);
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OPCODE_EVAL(OP_ALWAYS_TRUE, this, parameters, match);
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OPCODE_EVAL(OP_NUMBER_MATCH, this, parameters, match);
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OPCODE_EVAL(OP_ULONG_MATCH_RANGE, this, parameters, match);
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OPCODE_EVAL(OP_WSTRING_MATCH, this, parameters, match);
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OPCODE_EVAL(OP_ULONG_AND_MATCH, this, parameters, match);
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OPCODE_EVAL(OP_ACTION, this, parameters, match);
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return EVAL_ERROR;
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef OPCODE_EVAL
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace sandbox
455