public EvaluatedObjectContext(DkmVisualizedExpression expr, DkmVisualizedExpression callback_expr): base(expr, callback_expr)
		{
			DkmEvaluationResult eval = null;
			if (expr_.TagValue == DkmVisualizedExpression.Tag.ChildVisualizedExpression)
			{
				eval = ((DkmChildVisualizedExpression)expr_).EvaluationResult;
			}
			else
			{
				eval = DefaultEE.DefaultEval(expr_, true);
			}
			eval_ = (DkmSuccessEvaluationResult)eval;

			// @NOTE: Pretty sure this is reliable
			is_pointer_ = eval_.Type.Contains('*');

			string fullname = Utility.GetExpressionFullName(expr_);
			// Remove any trailing format specifiers.
			int comma = fullname.IndexOf(',');
			if(comma != -1)
			{
				fullname = fullname.Substring(0, comma);
			}
            string base_expr_stub_ = String.Format(
				"({0})",
				fullname
				);
			ptr_expr_stub_ = is_pointer_ ?
				base_expr_stub_ : String.Format("(&{0})", base_expr_stub_);
		}
Beispiel #2
0
        void IDkmCustomVisualizer.UseDefaultEvaluationBehavior(DkmVisualizedExpression expression, out bool useDefaultEvaluationBehavior, out DkmEvaluationResult defaultEvaluationResult)
        {
            BasicVisualizer visualizer = null;

            defaultEvaluationResult      = null;
            useDefaultEvaluationBehavior = true;
            if (expression.VisualizerId != Guids.CustomVisualizer.ForceDefault &&
                VisualizerRegistrar.TryCreateVisualizer(expression, out visualizer))
            {
                // If this visualizer has custom fields, or displays default fields non-inline, don't use
                // the default evaluation behavior.
                ChildDisplayFlags flags = visualizer.ChildDisplayFlags;
                if (flags.HasFlag(ChildDisplayFlags.HasCustomFields) ||
                    !flags.HasFlag(ChildDisplayFlags.DefaultFieldsInline))
                {
                    useDefaultEvaluationBehavior = false;
                }
            }

            if (useDefaultEvaluationBehavior)
            {
                string name     = null;
                string fullName = null;
                Utility.GetExpressionName(expression, out name, out fullName);
                fullName += ",!";
                defaultEvaluationResult = CppExpressionEvaluator.Evaluate(expression, fullName);
            }
        }
Beispiel #3
0
        public static DkmEvaluationResult DefaultEval(string text, DkmVisualizedExpression expression, bool raw_format)
        {
            if (raw_format && text.Length > 0)
            {
                // Ensure we have the format specifier for raw format, to prevent the evaluator just calling back again to us.
                int comma = text.IndexOf(',');
                if (comma == -1)
                {
                    text += ",!";
                }
                else
                {
                    int raw = text.IndexOf('!', comma + 1);
                    if (raw == -1)
                    {
                        text += "!";
                    }
                }
            }

            var LangExpr = DkmLanguageExpression.Create(CppLanguage, DkmEvaluationFlags.None, text, null);

            DkmEvaluationResult result;

            try
            {
                expression.EvaluateExpressionCallback(expression.InspectionContext, LangExpr, expression.StackFrame, out result);
            }
            catch (Exception e)
            {
                result = null;
            }
            return(result);
        }
        public void GetChildren(DkmVisualizedExpression visualizedExpression, int initialRequestSize, DkmInspectionContext inspectionContext, out DkmChildVisualizedExpression[] initialChildren, out DkmEvaluationResultEnumContext enumContext)
        {
            var rawResultHolder = visualizedExpression.GetDataItem <RawEvaluationResultHolder>();

            if (rawResultHolder == null)
            {
                Debug.Fail("PythonViewNativeVisualizer.GetChildren passed a visualized expression that does not have an associated RawEvaluationResultHolder.");
                throw new NotSupportedException();
            }
            var rawResult = rawResultHolder.RawResult;

            DkmEvaluationResult[]          rawInitialChildren;
            DkmEvaluationResultEnumContext rawEnumContext;

            visualizedExpression.GetChildrenCallback(rawResult, 0, inspectionContext, out rawInitialChildren, out rawEnumContext);

            initialChildren = new DkmChildVisualizedExpression[0];
            enumContext     = rawEnumContext;

            if (DebuggerOptions.ShowPythonViewNodes)
            {
                var pythonView = GetPythonView(visualizedExpression, (uint)rawEnumContext.Count);
                if (pythonView != null)
                {
                    enumContext = DkmEvaluationResultEnumContext.Create(
                        rawEnumContext.Count + 1,
                        rawEnumContext.StackFrame,
                        rawEnumContext.InspectionContext,
                        new RawEnumContextData {
                        RawContext = rawEnumContext, PythonView = pythonView
                    });
                }
            }
        }
Beispiel #5
0
		public static string GetExpressionType(DkmVisualizedExpression expression)
		{
			if (expression.TagValue == DkmVisualizedExpression.Tag.RootVisualizedExpression)
			{
                var temp = expression as DkmRootVisualizedExpression;
				return ((DkmRootVisualizedExpression)expression).Type;
			}
			else if (expression.TagValue == DkmVisualizedExpression.Tag.ChildVisualizedExpression)
			{
				var eval = ((DkmChildVisualizedExpression)expression).EvaluationResult;
				if (eval.TagValue == DkmEvaluationResult.Tag.SuccessResult)
				{
					var success = eval as DkmSuccessEvaluationResult;
					return success.Type;
				}
				else
				{
					return "";
				}
			}
			else
			{
				return null;
			}
		}
Beispiel #6
0
 public static string GetExpressionType(DkmVisualizedExpression expression)
 {
     if (expression.TagValue == DkmVisualizedExpression.Tag.RootVisualizedExpression)
     {
         var temp = expression as DkmRootVisualizedExpression;
         return(((DkmRootVisualizedExpression)expression).Type);
     }
     else if (expression.TagValue == DkmVisualizedExpression.Tag.ChildVisualizedExpression)
     {
         var eval = ((DkmChildVisualizedExpression)expression).EvaluationResult;
         if (eval.TagValue == DkmEvaluationResult.Tag.SuccessResult)
         {
             var success = eval as DkmSuccessEvaluationResult;
             return(success.Type);
         }
         else
         {
             return("");
         }
     }
     else
     {
         return(null);
     }
 }
        public PropertyListVisualizer(DkmVisualizedExpression proplist_expr, UPropertyAccessContext access_ctx)
            : base(proplist_expr)
        {
            prop_evals_ = new Dictionary<string, DkmEvaluationResult>();

            access_ctx_ = access_ctx;
        }
		void IDkmCustomVisualizer.EvaluateVisualizedExpression(DkmVisualizedExpression expression, out DkmEvaluationResult resultObject)
		{
			Debug.Print("UE4PV: EvaluateVisualizedExpression('{0}'/'{1}', [{2}])",
				Utility.GetExpressionFullName(expression),
				Utility.GetExpressionName(expression),
				expression.TagValue
				);

			// Sanity check to confirm this is only being invoked for UObject types. @TODO: Remove eventually.
			// Believe this method is only invoked on DkmRootVisualizedExpression instances, not children.
			Debug.Assert(expression.VisualizerId == Guids.Visualizer.UObject);

			UE4Visualizer visualizer = null;
			bool result = UE4VisualizerRegistrar.TryCreateVisualizer(expression, out visualizer);
			if(!result)
			{
				OnVisualizerMatchFailed(expression, out resultObject);
				return;
			}

			// Evaluate the visualization result
			DkmEvaluationResult eval = visualizer.EvaluationResult;
			resultObject = eval;

			// Associate the visualizer with the expression
			expression.SetDataItem<ExpressionDataItem>(
				DkmDataCreationDisposition.CreateAlways,
				new ExpressionDataItem(visualizer)
				);
		}
Beispiel #9
0
        public static DkmEvaluationResult DefaultEval(string text, DkmVisualizedExpression expression, bool raw_format)
        {
            if (raw_format && text.Length > 0)
            {
                // Ensure we have the format specifier for raw format, to prevent the evaluator just calling back again to us.
                text = text.TrimEnd(new char[] { ' ' });
                if (text.Last() == ',')
                {
                    text += '!';
                }
                else
                {
                    text += ",!";
                }
            }

            var LangExpr = DkmLanguageExpression.Create(CppLanguage, DkmEvaluationFlags.None, text, null);

            DkmEvaluationResult result;

            try
            {
                expression.EvaluateExpressionCallback(expression.InspectionContext, LangExpr, expression.StackFrame, out result);
            }
            catch (Exception e)
            {
                result = null;
            }
            return(result);
        }
Beispiel #10
0
        // @NOTE: Currently ignoring FName::Number, and assuming valid.
        public static string GetFNameAsString(string expr_str, DkmVisualizedExpression context_expr)
        {
            /*			var em = ExpressionManipulator.FromExpression(expr_str);
             *                      em = em.DirectMember(Memb.CompIndex);
             *                      DkmSuccessEvaluationResult comp_idx_eval = DefaultEE.DefaultEval(em.Expression, context_expr, true) as DkmSuccessEvaluationResult;
             *
             *                      // @TODO: For now, to avoid requiring more lookups, we'll allow a failure and return null,
             *                      // and let the caller decide how to interpret it.
             *                      //Debug.Assert(comp_idx_eval != null);
             *                      if(comp_idx_eval == null)
             *                      {
             *                              return null;
             *                      }
             *
             *                      string comp_idx_str = comp_idx_eval.Value;
             * //			"((FNameEntry&)GNameBlocksDebug[Value >> FNameDebugVisualizer::OffsetBits][FNameDebugVisualizer::EntryStride * (Value & FNameDebugVisualizer::OffsetMask)])"
             * //			// @TODO: Condition = "Header.Len &gt; FNameDebugVisualizer::MaxLength" -> Illegal
             * //			"Header.bIsWide" -> WideName,[Header.Len]su
             * //			AnsiName,[Header.Len]s
             *
             *                      string ansi_expr_str = String.Format("((FNameEntry*)(((FNameEntry***)GFNameTableForDebuggerVisualizers_MT)[{0} / 16384][{0} % 16384]))->AnsiName", comp_idx_str);
             *                      var ansi_eval = DefaultEE.DefaultEval(ansi_expr_str, context_expr, true);
             *                      return ansi_eval.GetUnderlyingString();
             */

            var default_eval = DefaultEE.DefaultEval(expr_str, context_expr, false /*true*/) as DkmSuccessEvaluationResult;

            if (default_eval == null)
            {
                return(null);
            }
            // Remove quotes
            return(default_eval.Value.Substring(1, default_eval.Value.Length - 2));
        }
Beispiel #11
0
        private bool TryGetRegisteredVisualizer(DkmVisualizedExpression expression, out BasicVisualizer visualizer, out DkmFailedEvaluationResult failureResult)
        {
            visualizer    = null;
            failureResult = null;

            if (VisualizerRegistrar.TryCreateVisualizer(expression, out visualizer))
            {
                return(true);
            }

            string name     = null;
            string fullName = null;

            Utility.GetExpressionName(expression, out name, out fullName);

            DkmFailedEvaluationResult failure = DkmFailedEvaluationResult.Create(
                expression.InspectionContext,
                expression.StackFrame,
                name,
                fullName,
                String.Format("No formatter is registered for VisualizerId {0}",
                              expression.VisualizerId),
                DkmEvaluationResultFlags.Invalid,
                null);

            failureResult = failure;
            return(false);
        }
Beispiel #12
0
        public EvaluatedObjectContext(DkmVisualizedExpression expr, DkmVisualizedExpression callback_expr) : base(expr, callback_expr)
        {
            DkmEvaluationResult eval = null;

            if (expr_.TagValue == DkmVisualizedExpression.Tag.ChildVisualizedExpression)
            {
                eval = ((DkmChildVisualizedExpression)expr_).EvaluationResult;
            }
            else
            {
                eval = DefaultEE.DefaultEval(expr_, true);
            }
            eval_ = (DkmSuccessEvaluationResult)eval;

            // @NOTE: Pretty sure this is reliable
            is_pointer_ = eval_.Type.Contains('*');

            string fullname = Utility.GetExpressionFullName(expr_);
            // Remove any trailing format specifiers.
            int comma = fullname.IndexOf(',');

            if (comma != -1)
            {
                fullname = fullname.Substring(0, comma);
            }
            string base_expr_stub_ = String.Format(
                "({0})",
                fullname
                );

            ptr_expr_stub_ = is_pointer_ ?
                             base_expr_stub_ : String.Format("(&{0})", base_expr_stub_);
        }
        void IDkmCustomVisualizer.EvaluateVisualizedExpression(DkmVisualizedExpression expression, out DkmEvaluationResult resultObject)
        {
            Debug.Print("UE4PV: EvaluateVisualizedExpression('{0}'/'{1}', [{2}])",
                        Utility.GetExpressionFullName(expression),
                        Utility.GetExpressionName(expression),
                        expression.TagValue
                        );

            // Sanity check to confirm this is only being invoked for UObject types. @TODO: Remove eventually.
            // Believe this method is only invoked on DkmRootVisualizedExpression instances, not children.
            Debug.Assert(expression.VisualizerId == Guids.Visualizer.UObject);

            UE4Visualizer visualizer = null;
            bool          result     = UE4VisualizerRegistrar.TryCreateVisualizer(expression, out visualizer);

            if (!result)
            {
                OnVisualizerMatchFailed(expression, out resultObject);
                return;
            }

            // Evaluate the visualization result
            DkmEvaluationResult eval = visualizer.EvaluationResult;

            resultObject = eval;

            // Associate the visualizer with the expression
            expression.SetDataItem <ExpressionDataItem>(
                DkmDataCreationDisposition.CreateAlways,
                new ExpressionDataItem(visualizer)
                );
        }
    public EvaluationDataItem(DkmVisualizedExpression expression, DkmEvaluationResult evalResult)
    {
      expression_ = expression;
      evalResult_ = evalResult;

      VisualizerRegistrar.TryCreateVisualizer(expression, out visualizer_);
    }
Beispiel #15
0
        // Given an expression string resolving to a UClass* (which is assumed to point to a **Blueprint** class), this determines
        // the UE4 (non-prefixed) name of the native base class.
        public static string GetBlueprintClassNativeBaseName(string uclass_expr_str, DkmVisualizedExpression context_expr)
        {
            var uclass_em = ExpressionManipulator.FromExpression(uclass_expr_str);

            do
            {
                var super_em      = uclass_em.PtrCast(Typ.UStruct).PtrMember(Memb.SuperStruct).PtrCast(Typ.UClass);
                var is_native_res = IsNativeUClassOrUInterface(super_em.Expression, context_expr);
                if (!is_native_res.IsValid)
                {
                    return(null);
                }

                if (is_native_res.Value)
                {
                    var name_em = super_em.PtrCast(Typ.UObjectBase).PtrMember(Memb.ObjName);
                    return(GetFNameAsString(name_em.Expression, context_expr));
                }


                uclass_em = super_em;
            }while (DefaultEE.DefaultEval(uclass_em.PtrCast(Cpp.Void).Expression, context_expr, true).TagValue == DkmEvaluationResult.Tag.SuccessResult);

            // This shouldn't really happen
            return(null);
        }
Beispiel #16
0
        public EvaluationDataItem(DkmVisualizedExpression expression, DkmEvaluationResult evalResult)
        {
            expression_ = expression;
            evalResult_ = evalResult;

            VisualizerRegistrar.TryCreateVisualizer(expression, out visualizer_);
        }
Beispiel #17
0
		public static DkmEvaluationResult DefaultEval(string text, DkmVisualizedExpression expression, bool raw_format)
		{
			if (raw_format && text.Length > 0)
			{
				// Ensure we have the format specifier for raw format, to prevent the evaluator just calling back again to us.
				int comma = text.IndexOf(',');
				if (comma == -1)
				{
					text += ",!";
				}
				else
				{
					int raw = text.IndexOf('!', comma + 1);
					if (raw == -1)
					{
						text += "!";
					}
				}
			}

			var LangExpr = DkmLanguageExpression.Create(CppLanguage, DkmEvaluationFlags.None, text, null);

			DkmEvaluationResult result;
			try
			{
				expression.EvaluateExpressionCallback(expression.InspectionContext, LangExpr, expression.StackFrame, out result);
			}
			catch(Exception e)
			{
				result = null;
			}
			return result;
		}
            public void GetItems(DkmVisualizedExpression visualizedExpression, DkmEvaluationResultEnumContext enumContext, int startIndex, int count, out DkmChildVisualizedExpression[] items)
            {
                DkmEvaluationResult[] itemsAsResult;

                visualizedExpression.GetItemsCallback(enumContext, startIndex, count, out itemsAsResult);
                items = Convert(visualizedExpression, itemsAsResult, startIndex);
            }
        public static DkmSuccessEvaluationResult EvaluateSuccess(DkmVisualizedExpression expr, DkmEvaluationFlags flags, string text, DkmDataItem data)
        {
            DkmEvaluationResult result = Evaluate(expr, flags, text, data);
              if (result.TagValue != DkmEvaluationResult.Tag.SuccessResult)
            throw new EvaluationException(result);

              return (DkmSuccessEvaluationResult)result;
        }
Beispiel #20
0
        // Returns the type of property identified by the expression string
        // (As in, "IntProperty", "ObjectProperty", etc)
        protected string GetPropertyType(string uprop_expr_str, DkmVisualizedExpression context_expr)
        {
            // We get this from the value of the Name member of the UProperty's UClass.
            var    uprop_em = ExpressionManipulator.FromExpression(uprop_expr_str);
            string prop_class_name_expr_str = uprop_em.PtrCast(Typ.UObjectBase).PtrMember(Memb.ObjClass).PtrCast(Typ.UObjectBase).PtrMember(Memb.ObjName).Expression;

            return(UE4Utility.GetFNameAsString(prop_class_name_expr_str, context_expr));
        }
            public void GetChildren(DkmVisualizedExpression visualizedExpression, int initialRequestSize, DkmInspectionContext inspectionContext, out DkmChildVisualizedExpression[] initialChildren, out DkmEvaluationResultEnumContext enumContext)
            {
                DkmEvaluationResult[] initialChildrenAsResult;

                visualizedExpression.GetChildrenCallback(EvaluationResult, 0, inspectionContext, out initialChildrenAsResult, out enumContext);
                initialChildren = Convert(visualizedExpression, initialChildrenAsResult);
                enumContext.SetDataItem(DkmDataCreationDisposition.CreateAlways, this);
            }
        /// <summary>
        /// Evaluates the specified visualized expression using our custom evaluator.
        /// </summary>
        public void EvaluateVisualizedExpression(DkmVisualizedExpression visualizedExpression, out DkmEvaluationResult resultObject)
        {
            VSContext.InitializeInteractiveExecution();
            VSCustomVisualizerEvaluator evaluator = new VSCustomVisualizerEvaluator(visualizedExpression);

            resultObject = evaluator.EvaluationResult;
            visualizedExpression.SetDataItem(DkmDataCreationDisposition.CreateAlways, evaluator);
        }
Beispiel #23
0
        public void GetItems(DkmVisualizedExpression visualizedExpression, DkmEvaluationResultEnumContext enumContext, int startIndex, int count, out DkmChildVisualizedExpression[] items)
        {
            if (count == 0)
            {
                items = new DkmChildVisualizedExpression[0];
                return;
            }

            var rawContextData = enumContext.GetDataItem <RawEnumContextData>();
            var rawContext     = rawContextData != null ? rawContextData.RawContext : enumContext;

            var result = new List <DkmChildVisualizedExpression>(count);

            if (rawContextData != null && rawContextData.PythonView != null)
            {
                if (startIndex == 0)
                {
                    result.Add(rawContextData.PythonView);
                    --count;
                }
                else
                {
                    --startIndex;
                }
            }

            DkmEvaluationResult[] rawItems;
            visualizedExpression.GetItemsCallback(rawContext, startIndex, count, out rawItems);
            for (int i = 0; i < rawItems.Length; ++i)
            {
                var rawItem = rawItems[i];

                var rawSuccessItem          = rawItem as DkmSuccessEvaluationResult;
                DkmExpressionValueHome home = null;
                if (rawSuccessItem != null && rawSuccessItem.Address != null)
                {
                    home = DkmPointerValueHome.Create(rawSuccessItem.Address.Value);
                }
                else
                {
                    home = DkmFakeValueHome.Create(0);
                }

                var item = DkmChildVisualizedExpression.Create(
                    visualizedExpression.InspectionContext,
                    visualizedExpression.VisualizerId,
                    visualizedExpression.SourceId,
                    visualizedExpression.StackFrame,
                    home,
                    rawItem,
                    visualizedExpression,
                    (uint)(startIndex + i),
                    rawItem.GetDataItem <RawEvaluationResultHolder>());
                result.Add(item);
            }

            items = result.ToArray();
        }
 public void UseDefaultEvaluationBehavior(DkmVisualizedExpression visualizedExpression, out bool useDefaultEvaluationBehavior, out DkmEvaluationResult defaultEvaluationResult)
 {
     useDefaultEvaluationBehavior = true;
     defaultEvaluationResult      = GetPythonView(visualizedExpression);
     if (defaultEvaluationResult == null)
     {
         throw new NotSupportedException();
     }
 }
Beispiel #25
0
		// @TODO: Unsafe, assumes valid and non-empty.
		public static string GetFStringAsString(string expr_str, DkmVisualizedExpression context_expr)
		{
			var em = ExpressionManipulator.FromExpression(expr_str);
			em = em.DirectMember("Data").DirectMember("AllocatorInstance").DirectMember("Data").PtrCast("wchar_t");
            var data_eval = DefaultEE.DefaultEval(em.Expression, context_expr, true);

			Debug.Assert(data_eval != null);
			return data_eval.GetUnderlyingString();
		}
Beispiel #26
0
        void IDkmCustomVisualizer.EvaluateVisualizedExpression(DkmVisualizedExpression expression, out DkmEvaluationResult resultObject)
        {
            BasicVisualizer           visualizer    = null;
            DkmFailedEvaluationResult failureResult = null;

            if (!TryGetRegisteredVisualizer(expression, out visualizer, out failureResult))
            {
                resultObject = failureResult;
                return;
            }

            DkmEvaluationResult evalResult     = visualizer.EvaluationResult;
            EvaluationDataItem  resultDataItem = new EvaluationDataItem(expression, evalResult);

            expression.SetDataItem(DkmDataCreationDisposition.CreateAlways, resultDataItem);

            string name     = null;
            string fullName = null;

            Utility.GetExpressionName(expression, out name, out fullName);

            if (evalResult.TagValue == DkmEvaluationResult.Tag.SuccessResult)
            {
                DkmSuccessEvaluationResult successResult = (DkmSuccessEvaluationResult)evalResult;
                resultObject = DkmSuccessEvaluationResult.Create(
                    successResult.InspectionContext,
                    successResult.StackFrame,
                    name,
                    successResult.FullName,
                    successResult.Flags,
                    successResult.Value,
                    successResult.EditableValue,
                    successResult.Type,
                    successResult.Category,
                    successResult.Access,
                    successResult.StorageType,
                    successResult.TypeModifierFlags,
                    successResult.Address,
                    successResult.CustomUIVisualizers,
                    successResult.ExternalModules,
                    resultDataItem);
            }
            else
            {
                DkmFailedEvaluationResult failResult = (DkmFailedEvaluationResult)evalResult;

                resultObject = DkmFailedEvaluationResult.Create(
                    failResult.InspectionContext,
                    failResult.StackFrame,
                    name,
                    fullName,
                    failResult.ErrorMessage,
                    failResult.Flags,
                    null);
                return;
            }
        }
Beispiel #27
0
        protected static string GetBoolPropertyFieldMask(string uboolprop_expr_str, DkmVisualizedExpression context_expr)
        {
            var boolprop_em = ExpressionManipulator.FromExpression(uboolprop_expr_str).PtrMember(Memb.FieldMask);
            // uint8 property
            var eval    = DefaultEE.DefaultEval(boolprop_em.Expression, context_expr, true) as DkmSuccessEvaluationResult;
            var val_str = eval.Value;

            return(Utility.GetNumberFromUcharValueString(val_str));
        }
        void IDkmCustomVisualizer.GetItems(DkmVisualizedExpression expression, DkmEvaluationResultEnumContext enumContext, int startIndex, int count, out DkmChildVisualizedExpression[] items)
        {
            var data_item  = expression.GetDataItem <ExpressionDataItem>();
            var visualizer = data_item.Visualizer;

            Debug.Assert(visualizer != null);

            visualizer.GetChildItems(enumContext, startIndex, count, out items);
        }
        void IDkmCustomVisualizer.EvaluateVisualizedExpression(DkmVisualizedExpression expression, out DkmEvaluationResult resultObject)
        {
            BasicVisualizer visualizer = null;
            DkmFailedEvaluationResult failureResult = null;

            if (!TryGetRegisteredVisualizer(expression, out visualizer, out failureResult))
            {
              resultObject = failureResult;
              return;
            }

            DkmEvaluationResult evalResult = visualizer.EvaluationResult;
            EvaluationDataItem resultDataItem = new EvaluationDataItem(expression, evalResult);

            expression.SetDataItem(DkmDataCreationDisposition.CreateAlways, resultDataItem);

            string name = null;
            string fullName = null;
            Utility.GetExpressionName(expression, out name, out fullName);

            if (evalResult.TagValue == DkmEvaluationResult.Tag.SuccessResult)
            {
              DkmSuccessEvaluationResult successResult = (DkmSuccessEvaluationResult)evalResult;
              resultObject = DkmSuccessEvaluationResult.Create(
              successResult.InspectionContext,
              successResult.StackFrame,
              name,
              successResult.FullName,
              successResult.Flags,
              successResult.Value,
              successResult.EditableValue,
              successResult.Type,
              successResult.Category,
              successResult.Access,
              successResult.StorageType,
              successResult.TypeModifierFlags,
              successResult.Address,
              successResult.CustomUIVisualizers,
              successResult.ExternalModules,
              resultDataItem);
            }
            else
            {
              DkmFailedEvaluationResult failResult = (DkmFailedEvaluationResult)evalResult;

              resultObject = DkmFailedEvaluationResult.Create(
              failResult.InspectionContext,
              failResult.StackFrame,
              name,
              fullName,
              failResult.ErrorMessage,
              failResult.Flags,
              null);
              return;
            }
        }
        public static DkmEvaluationResult Evaluate(DkmVisualizedExpression expr, DkmEvaluationFlags flags, string text, DkmDataItem data)
        {
            using (DkmLanguageExpression vexpr = DkmLanguageExpression.Create(CppLanguage, flags, text, data))
              {
            DkmEvaluationResult result = null;
            expr.EvaluateExpressionCallback(expr.InspectionContext, vexpr, expr.StackFrame, out result);

            return result;
              }
        }
Beispiel #31
0
        public static DkmEvaluationResult Evaluate(DkmVisualizedExpression expr, DkmEvaluationFlags flags, string text, DkmDataItem data)
        {
            using (DkmLanguageExpression vexpr = DkmLanguageExpression.Create(CppLanguage, flags, text, data))
            {
                DkmEvaluationResult result = null;
                expr.EvaluateExpressionCallback(expr.InspectionContext, vexpr, expr.StackFrame, out result);

                return(result);
            }
        }
Beispiel #32
0
        // @TODO: Unsafe, assumes valid and non-empty.
        public static string GetFStringAsString(string expr_str, DkmVisualizedExpression context_expr)
        {
            var em = ExpressionManipulator.FromExpression(expr_str);

            em = em.DirectMember("Data").DirectMember("AllocatorInstance").DirectMember("Data").PtrCast("wchar_t");
            var data_eval = DefaultEE.DefaultEval(em.Expression, context_expr, true);

            Debug.Assert(data_eval != null);
            return(data_eval.GetUnderlyingString());
        }
Beispiel #33
0
        // In VS 2015+, the injection of the child [Python view] node is handled in the PythonDkm.natvis, and the visualizer is only responsible
        // for producing a DkmEvaluationResult for that node.

        public void EvaluateVisualizedExpression(DkmVisualizedExpression visualizedExpression, out DkmEvaluationResult resultObject)
        {
            resultObject = GetPythonView(visualizedExpression);
            if (resultObject == null)
            {
                resultObject = DkmFailedEvaluationResult.Create(
                    visualizedExpression.InspectionContext, visualizedExpression.StackFrame, "[Python view]",
                    null, "Python view is unavailable for this object", DkmEvaluationResultFlags.Invalid, null);
            }
        }
Beispiel #34
0
        public static DkmSuccessEvaluationResult EvaluateSuccess(DkmVisualizedExpression expr, DkmEvaluationFlags flags, string text, DkmDataItem data)
        {
            DkmEvaluationResult result = Evaluate(expr, flags, text, data);

            if (result.TagValue != DkmEvaluationResult.Tag.SuccessResult)
            {
                throw new EvaluationException(result);
            }

            return((DkmSuccessEvaluationResult)result);
        }
        // In VS 2015+, the injection of the child [Python view] node is handled in the PythonDkm.natvis, and the visualizer is only responsible
        // for producing a DkmEvaluationResult for that node.

        public void EvaluateVisualizedExpression(DkmVisualizedExpression visualizedExpression, out DkmEvaluationResult resultObject)
        {
            resultObject = GetPythonView(visualizedExpression);
            if (resultObject == null)
            {
                resultObject = DkmFailedEvaluationResult.Create(
                    // TODO: Localization - [Python view] also appears in .natvis file, leave as-is for now
                    visualizedExpression.InspectionContext, visualizedExpression.StackFrame, "[Python view]",
                    null, Strings.DebugPythonViewNotAvailableForObject, DkmEvaluationResultFlags.Invalid, null);
            }
        }
		void OnVisualizerMatchFailed(DkmVisualizedExpression expression, out DkmEvaluationResult result)
		{
			result = DkmFailedEvaluationResult.Create(
				expression.InspectionContext,
				expression.StackFrame,
				Utility.GetExpressionName(expression),
				Utility.GetExpressionFullName(expression),
				String.Format("UE4PropVis: No visualizer is registered for VisualizerId {0}", expression.VisualizerId),
				DkmEvaluationResultFlags.Invalid,
				null
				);
		}
Beispiel #37
0
        void IDkmCustomVisualizer.GetItems(DkmVisualizedExpression expression, DkmEvaluationResultEnumContext enumContext, int startIndex, int count, out DkmChildVisualizedExpression[] items)
        {
            EvaluationDataItem dataItem = expression.GetDataItem <EvaluationDataItem>();

            if (dataItem == null)
            {
                Debug.Fail("DebugComponent.GetItems passed a visualized expression that does not have an associated ExpressionDataItem.");
                throw new NotSupportedException();
            }

            items = dataItem.Visualizer.GetChildItems(startIndex, count);
        }
 void OnVisualizerMatchFailed(DkmVisualizedExpression expression, out DkmEvaluationResult result)
 {
     result = DkmFailedEvaluationResult.Create(
         expression.InspectionContext,
         expression.StackFrame,
         Utility.GetExpressionName(expression),
         Utility.GetExpressionFullName(expression),
         String.Format("UE4PropVis: No visualizer is registered for VisualizerId {0}", expression.VisualizerId),
         DkmEvaluationResultFlags.Invalid,
         null
         );
 }
Beispiel #39
0
        public void SetValueAsString(DkmVisualizedExpression visualizedExpression, string value, int timeout, out string errorText)
        {
            var rawResultHolder = visualizedExpression.GetDataItem <RawEvaluationResultHolder>();

            if (rawResultHolder == null)
            {
                Debug.Fail("PythonViewNativeVisualizer.GetUnderlyingString passed a visualized expression that does not have an associated RawEvaluationResultHolder.");
                throw new NotSupportedException();
            }

            visualizedExpression.SetValueAsStringCallback(rawResultHolder.RawResult, value, timeout, out errorText);
        }
Beispiel #40
0
        public string GetUnderlyingString(DkmVisualizedExpression visualizedExpression)
        {
            var rawResultHolder = visualizedExpression.GetDataItem <RawEvaluationResultHolder>();

            if (rawResultHolder == null)
            {
                Debug.Fail("PythonViewNativeVisualizer.GetUnderlyingString passed a visualized expression that does not have an associated RawEvaluationResultHolder.");
                throw new NotSupportedException();
            }

            return(visualizedExpression.GetUnderlyingStringCallback(rawResultHolder.RawResult));
        }
Beispiel #41
0
 // Given an expression which resolves to a pointer of any kind, returns the pointer value as an integer.
 public static ulong EvaluatePointerAddress(string pointer_expr_str, DkmVisualizedExpression context_expr)
 {
     ExpressionManipulator em = ExpressionManipulator.FromExpression(pointer_expr_str);
     // Cast to void* to avoid unnecessary visualization processing.
     string address_expr_str = em.PtrCast(Cpp.Void).Expression;
     var address_eval = (DkmEvaluationResult)DefaultEE.DefaultEval(address_expr_str, context_expr, true);
     if(address_eval.TagValue == DkmEvaluationResult.Tag.SuccessResult)
     {
         var eval = address_eval as DkmSuccessEvaluationResult;
         return eval.Address != null ? eval.Address.Value : 0;
     }
     return 0;
 }
		public UObjectVisualizer(DkmVisualizedExpression expression) : base(expression)
		{
			// @NOTE: Moved here since EvaluationResult was always retrieved immediately after
			// successful construction.
			EvaluateExpressionResult();

			if (state_ == EvaluationState.Evaluated)
			{
				// Initialize the context object which we use to access properties on the object.
				// This can potentially be shared with a PropertyListVisualizer child.
				access_ctx_ = new UPropertyAccessContext(expression_);
			}
		}
Beispiel #43
0
        public UObjectVisualizer(DkmVisualizedExpression expression) : base(expression)
        {
            // @NOTE: Moved here since EvaluationResult was always retrieved immediately after
            // successful construction.
            EvaluateExpressionResult();

            if (state_ == EvaluationState.Evaluated)
            {
                // Initialize the context object which we use to access properties on the object.
                // This can potentially be shared with a PropertyListVisualizer child.
                access_ctx_ = new UPropertyAccessContext(expression_);
            }
        }
Beispiel #44
0
 public static string GetExpressionFullName(DkmVisualizedExpression expression)
 {
     if (expression.TagValue == DkmVisualizedExpression.Tag.RootVisualizedExpression)
     {
         return ((DkmRootVisualizedExpression)expression).FullName;
     }
     else if (expression.TagValue == DkmVisualizedExpression.Tag.ChildVisualizedExpression)
     {
         return ((DkmChildVisualizedExpression)expression).EvaluationResult.FullName;
     }
     else
     {
         return null;
     }
 }
Beispiel #45
0
 public static void GetExpressionName(DkmVisualizedExpression expression, out string name, out string fullName)
 {
   if (expression.TagValue == DkmVisualizedExpression.Tag.RootVisualizedExpression)
   {
     DkmRootVisualizedExpression rootExpr = (DkmRootVisualizedExpression)expression;
     name = rootExpr.Name;
     fullName = rootExpr.FullName;
   }
   else
   {
     DkmChildVisualizedExpression childExpr = (DkmChildVisualizedExpression)expression;
     name = childExpr.EvaluationResult.Name;
     fullName = childExpr.EvaluationResult.FullName;
   }
 }
        void IDkmCustomVisualizer.GetChildren(DkmVisualizedExpression expression, int initialRequestSize, DkmInspectionContext inspectionContext, out DkmChildVisualizedExpression[] initialChildren, out DkmEvaluationResultEnumContext enumContext)
        {
			Debug.Print("UE4PV: GetChildren('{0}'/'{1}', [{2}, {3}])",
				Utility.GetExpressionFullName(expression),
				Utility.GetExpressionName(expression),
				expression.TagValue,
				expression.VisualizerId
				);

			var data_item = expression.GetDataItem<ExpressionDataItem>();
			var visualizer = data_item.Visualizer;
			Debug.Assert(visualizer != null);

			visualizer.PrepareExpansion(out enumContext);
			initialChildren = new DkmChildVisualizedExpression[0];
		}
		// NOTE: 'expr' must resolve to either <UObject-type>* or <UObject-type>.
		// Furthermore, it must have already been passed to a UObjectVisualizer, which has 
		// performed the initial evalution.
		public UPropertyAccessContext(DkmVisualizedExpression expr)
		{
			context_expr_ = expr;

			string base_expression_str = Utility.GetExpressionFullName(context_expr_);
			base_expression_str = Utility.StripExpressionFormatting(base_expression_str);

			obj_em_ = ExpressionManipulator.FromExpression(base_expression_str);

			// Determine if our base expression is <UObject-type>* or <UObject-type>
			var uobj_data = context_expr_.GetDataItem<UObjectDataItem>();
			Debug.Assert(uobj_data != null);
            if (!uobj_data.IsPointer)
			{
				obj_em_ = obj_em_.AddressOf();
			}
		}
Beispiel #48
0
		// @NOTE: Currently ignoring FName::Number, and assuming valid.
		public static string GetFNameAsString(string expr_str, DkmVisualizedExpression context_expr)
		{
			var em = ExpressionManipulator.FromExpression(expr_str);
			em = em.DirectMember(Memb.CompIndex);
			DkmSuccessEvaluationResult comp_idx_eval = DefaultEE.DefaultEval(em.Expression, context_expr, true) as DkmSuccessEvaluationResult;

			// @TODO: For now, to avoid requiring more lookups, we'll allow a failure and return null,
			// and let the caller decide how to interpret it.
			//Debug.Assert(comp_idx_eval != null);
			if(comp_idx_eval == null)
			{
				return null;
			}

			string comp_idx_str = comp_idx_eval.Value;
			string ansi_expr_str = String.Format("((FNameEntry*)(((FNameEntry***)GFNameTableForDebuggerVisualizers_MT)[{0} / 16384][{0} % 16384]))->AnsiName", comp_idx_str);
			var ansi_eval = DefaultEE.DefaultEval(ansi_expr_str, context_expr, true);
			return ansi_eval.GetUnderlyingString();
		}
Beispiel #49
0
 // @TODO: Differentiate between false result and evaluation failure
 public static BoolEvaluation EvaluateBooleanExpression(string bool_expr_str, DkmVisualizedExpression context_expr)
 {
     try
     {
         var eval = DefaultEE.DefaultEval(bool_expr_str, context_expr, true);
         if (eval.TagValue == DkmEvaluationResult.Tag.SuccessResult)
         {
             var eval_result = eval as DkmSuccessEvaluationResult;
             return new BoolEvaluation(bool.Parse(eval_result.Value));
         }
         else
         {
             return BoolEvaluation.Indeterminate;
         }
     }
     catch(Exception)
     {
         return BoolEvaluation.Indeterminate;
     }
 }
Beispiel #50
0
      private bool TryGetRegisteredVisualizer(DkmVisualizedExpression expression, out BasicVisualizer visualizer, out DkmFailedEvaluationResult failureResult)
      {
        visualizer = null;
        failureResult = null;

        if (VisualizerRegistrar.TryCreateVisualizer(expression, out visualizer))
          return true;

        string name = null;
        string fullName = null;
        Utility.GetExpressionName(expression, out name, out fullName);

        DkmFailedEvaluationResult failure = DkmFailedEvaluationResult.Create(
            expression.InspectionContext,
            expression.StackFrame,
            name,
            fullName,
            String.Format("No formatter is registered for VisualizerId {0}",
                expression.VisualizerId),
            DkmEvaluationResultFlags.Invalid,
            null);
        failureResult = failure;
        return false;
      }
Beispiel #51
0
        // Determines the corresponding C++ name for the passed in UClass unprefixed name.
        public static string DetermineNativeUClassCppTypeName(string uclass_fname, DkmVisualizedExpression context_expr)
        {
            // Now we need to prefix the name, with either 'A' for actor-derived classes, or 'U' for all others.
            string cpp_prefix = "U";
            // This is kind of awkward. Cleanest approach would be to walk up the super-class chain, but that could be
            // a LOT of expression evaluations.
            // The following approach is hacky but should be quicker. Relying on the assumption that UE4 wouldn't allow
            // both a UObject class and an AActor class with the same name (@TODO: is this true??), we just assume the 'U'
            // prefix, form an arbitrary expression using it, and see if it can be successfully evaluated by the debugger.
            // If not, we assume the prefix is 'A' instead.

            // @NOTE: This will fail if someone is stupid enough to create a reflected class 'AMyClass' as well
            // as a non-reflected class 'UMyClass'.

            // First do quick checks for common types, to avoid an unnecessary expression evaluation.
            if (uclass_fname == "Actor")
            {
                cpp_prefix = "A";
            }
            else if (uclass_fname != "Object")
            {
                // Assume 'U'.
                // Also, after casting to our assumed type, cast again to void*. This shouldn't affect the success/failure result
                // of the evaluation, but will avoid unnecessary visualization callbacks when the evaluation succeeds.
                string assumed_cpp_type = cpp_prefix + uclass_fname;
                string cast_expr_str = String.Format("(void*)({0}*)nullptr", assumed_cpp_type);
                var cast_eval = DefaultEE.DefaultEval(cast_expr_str, context_expr, true);
                if (cast_eval.TagValue != DkmEvaluationResult.Tag.SuccessResult)
                {
                    // Cast failed, assume therefore must be an actor type
                    cpp_prefix = "A";
                }
            }

            return cpp_prefix + uclass_fname;
        }
 // Returns the type of property identified by the expression string
 // (As in, "IntProperty", "ObjectProperty", etc)
 protected string GetPropertyType(string uprop_expr_str, DkmVisualizedExpression context_expr)
 {
     // We get this from the value of the Name member of the UProperty's UClass.
     var uprop_em = ExpressionManipulator.FromExpression(uprop_expr_str);
     string prop_class_name_expr_str = uprop_em.PtrCast(Typ.UObjectBase).PtrMember(Memb.ObjClass).PtrCast(Typ.UObjectBase).PtrMember(Memb.ObjName).Expression;
     return UE4Utility.GetFNameAsString(prop_class_name_expr_str, context_expr);
 }
        // Takes in a UE4 property type string (eg. IntPropery, ObjectProperty, etc) along with a
        // expression string which evaluates to a UProperty*, and maps to the corresponding C++ type.
        protected CppTypeInfo[] GetCppTypeForPropertyType(string prop_type, string uprop_expr_str, DkmVisualizedExpression context_expr)
        {
            switch (prop_type)
            {
                case Prop.Bool:
                    return new CppTypeInfo[] {
                        new CppTypeInfo("bool")
                    };

                case Prop.Struct:
                    {
                        // This is gonna be effort.
                        // Get UStructProperty
                        var ustructprop_em = ExpressionManipulator.FromExpression(uprop_expr_str).PtrCast(CppProp.Struct);
                        // Need to access its UScriptStruct* member 'Struct', and get its object name.
                        var struct_name_expr_str = ustructprop_em.PtrMember(Memb.CppStruct).PtrCast(Typ.UObjectBase).PtrMember(Memb.ObjName).Expression;
                        // Get that name string
                        string struct_name = UE4Utility.GetFNameAsString(struct_name_expr_str, context_expr);
                        // Add the 'F' prefix
                        return new CppTypeInfo[] {
                            new CppTypeInfo("F" + struct_name)
                        };
                    }

                case Prop.Byte:
                    {
                        // Could be plain uint8, or a UEnum.
                        // Get UByteProperty
                        var ubyteprop_em = ExpressionManipulator.FromExpression(uprop_expr_str).PtrCast(CppProp.Byte);
                        // Need to access its UEnum* member 'Enum'.
                        var uenum_em = ubyteprop_em.PtrMember(Memb.EnumType);
                        // Evaluate this to see if it is null or not
                        bool is_enum_valid = !UE4Utility.IsPointerNull(uenum_em.Expression, context_expr);
                        if (is_enum_valid)
                        {
                            // This property is an enum, so the type we want is the fully qualified C++ enum type.

                            // @NOTE: Seems that the CppType member should be exactly what we need, but appears to actually be unused.
                            //string cpp_enum_name_expr_str = uenum_em.PtrMember("CppType").Expression;

                            string uenum_fname_expr_str = uenum_em.PtrCast(Typ.UObjectBase).PtrMember(Memb.ObjName).Expression;
                            string uenum_name = UE4Utility.GetFNameAsString(uenum_fname_expr_str, context_expr);

                            // We need to know if it's a namespaced enum or not
                            string is_namespaced_enum_expr_str = String.Format(
                                "{0}==UEnum::ECppForm::Namespaced",
                                uenum_em.PtrMember(Memb.EnumCppForm).Expression
                                );
                            var is_namespaced_res = UE4Utility.EvaluateBooleanExpression(is_namespaced_enum_expr_str, context_expr);
                            // @TODO: on evaluation failure??
                            CppTypeInfo primary;
                            if (is_namespaced_res.IsValid && is_namespaced_res.Value)
                            {
                                // A namespaced enum type should (hopefully) always be <UEnum::Name>::Type
                                primary = new CppTypeInfo(String.Format("{0}::Type", uenum_name), uenum_name);
                            }
                            else
                            {
                                // For regular or enum class enums, the full type name should be just the name of the UEnum object.
                                primary = new CppTypeInfo(uenum_name);
                            }

                            return new CppTypeInfo[] {
                                primary,
                                // Fallback onto regular byte display, in case enum name symbol not available
                                new CppTypeInfo(Typ.Byte, uenum_name + "?")
                            };
                        }
                        else
                        {
                            // Must just be a regular uint8
                            return new CppTypeInfo[] {
                                new CppTypeInfo(Typ.Byte)
                            };
                        }
                    }

                case Prop.Array:
                    {
                        // Okay, cast to UArrayProperty and get the inner property type
                        var array_prop_em = ExpressionManipulator.FromExpression(uprop_expr_str).PtrCast(CppProp.Array);
                        var inner_prop_em = array_prop_em.PtrMember(Memb.ArrayInner);

                        // @TODO: Need to look into how TArray< bool > is handled.
                        string inner_prop_type = GetPropertyType(inner_prop_em.Expression, context_expr);
                        var inner_cpp_type_info = GetCppTypeForPropertyType(inner_prop_type, inner_prop_em.Expression, context_expr);

                        var result = new CppTypeInfo[inner_cpp_type_info.Length];
                        for (int i = 0; i < inner_cpp_type_info.Length; ++i)
                        {
                            // Type needed is TArray< %inner_cpp_type%, FDefaultAllocator >
                            string type = String.Format("{0}<{1},{2}>", Typ.Array, inner_cpp_type_info[i].Type, Typ.DefaultAlloc);
                            // Omit allocator from display string, since for UPROPERTY arrays it can't be anything else
                            string display = String.Format("{0}<{1}>", Typ.Array, inner_cpp_type_info[i].Display);
                            result[i] = new CppTypeInfo(type, display);
                        }
                        return result;
                    }

                case Prop.Object:
                case Prop.Asset:
                    {
                        if(!Config.ShowExactUObjectTypes)
                        {
                            break;
                        }

                        string obj_cpp_type_name = Typ.UObject;

                        // Need to find out the subtype of the property, which is specified by UObjectPropertyBase::PropertyClass
                        var objprop_em = ExpressionManipulator.FromExpression(uprop_expr_str).PtrCast(CppProp.ObjectBase);
                        var subtype_uclass_em = objprop_em.PtrMember(Memb.ObjectSubtype);
                        var uclass_fname_em = subtype_uclass_em.PtrCast(Typ.UObjectBase).PtrMember(Memb.ObjName);
                        string uclass_fname = UE4Utility.GetFNameAsString(uclass_fname_em.Expression, context_expr);

                        // Is the property class native?
                        var is_native_res = UE4Utility.IsNativeUClassOrUInterface(subtype_uclass_em.Expression, context_expr);
                        // @TODO: currently not really handling failed eval
                        bool is_native = is_native_res.IsValid ? is_native_res.Value : true;
                        string native_uclass_fname;
                        if (is_native)
                        {
                            // Yes
                            native_uclass_fname = uclass_fname;
                        }
                        else
                        {
                            // No, we need to retrieve the name of its native base
                            native_uclass_fname = UE4Utility.GetBlueprintClassNativeBaseName(subtype_uclass_em.Expression, context_expr);
                        }

                        Debug.Assert(native_uclass_fname != null);

                        // Now we have to convert the unprefixed name, to a prefixed C++ type name
                        obj_cpp_type_name = UE4Utility.DetermineNativeUClassCppTypeName(native_uclass_fname, context_expr);

                        string uclass_display_name = UE4Utility.GetBlueprintClassDisplayName(uclass_fname);
                        switch (prop_type)
                        {
                            case Prop.Object:
                                {
                                    // if not native, add a suffix to the display type showing the blueprint class of the property
                                    // @NOTE: this is nothing to do with what object the value points to and what its type may be. property meta data only.
                                    string suffix = is_native ? String.Empty : String.Format(" [{0}]", uclass_display_name);
                                    string primary_type = String.Format("{0} *", obj_cpp_type_name);
                                    string primary_display = String.Format("{0} *{1}", obj_cpp_type_name, suffix);
                                    // fallback, no symbols available for the native base type, so use 'UObject' instead
                                    string fallback_type = String.Format("{0} *", Typ.UObject);
                                    string fallback_display = String.Format("{0}? *{1}", obj_cpp_type_name, suffix);

                                    return new CppTypeInfo[]
                                    {
                                        new CppTypeInfo(primary_type, primary_display),
                                        new CppTypeInfo(fallback_type, fallback_display)
                                    };
                                }

                            case Prop.Asset:
                                {
                                    // @NOTE: Don't really see anything to gain by casting to TAssetPtr< xxx >, since it's just another level of encapsulation that isn't
                                    // needed for visualization purposes.
                                    string suffix = String.Format(" [{0}]", is_native ? obj_cpp_type_name : uclass_display_name);
                                    string primary_type = Typ.AssetPtr; //String.Format("TAssetPtr<{0}>", obj_cpp_type_name);
                                    string primary_display = String.Format("{0}{1}", Typ.AssetPtr, suffix);

                                    // If just using FAssetPtr, no need for a fallback since we don't need to evaluate the specialized template parameter type
                                    return new CppTypeInfo[]
                                    {
                                        new CppTypeInfo(primary_type, primary_display)
                                    };
                                }

                            default:
                                Debug.Assert(false);
                                return null;
                        }
                    }

            /*				@TODO: Not so important. What's below is wrong, but essentially if we implement this, it's just to differentiate between UClass, UBlueprintGeneratedClass, etc
                case "ClassProperty":
                case "AssetClassProperty":
                    {
                        if (!Config.ShowExactUObjectTypes)
                        {
                            break;
                        }

                        // Need to find out the subtype of the property, which is specified by UClassProperty::MetaClass/UAssetClassProperty::MetaClass
                        // Cast to whichever property type we are (either UClassProperty or UAssetClassProperty)
                        string propclass_name = String.Format("U{0}", prop_type);
                        var classprop_em = ExpressionManipulator.FromExpression(uprop_expr_str).PtrCast(propclass_name);
                        // Either way, we have a member called 'MetaClass' which specified the base UClass stored in this property
                        var subtype_uclass_em = classprop_em.PtrMember("MetaClass");
                        var subtype_fname_em = subtype_uclass_em.PtrCast("UObjectBase").PtrMember("Name");
                        string subtype_fname = UE4Utility.GetFNameAsString(subtype_fname_em.Expression, context_expr);
                        return String.Format("U{0}*", subtype_fname);
                    }
            */			}

            // Standard cases, just use cpp type stored in map.
            // If not found, null string will be returned.
            string cpp_type = null;
            if (ue4_proptype_map_.TryGetValue(prop_type, out cpp_type))
            {
                return new CppTypeInfo[] { new CppTypeInfo(cpp_type) };
            }
            else
            {
                return null;
            }
        }
        protected DkmEvaluationResult GeneratePropertyValueEval(string container_expr_str, string uprop_expr_str, uint index, DkmVisualizedExpression context_expr)
        {
            Debug.Print("UE4PV: Trying to generate property value for property #{0}", index + 1);

            var uprop_em = ExpressionManipulator.FromExpression(uprop_expr_str);

            // Get name of property
            string prop_name_expr_str = uprop_em.PtrCast(Typ.UObjectBase).PtrMember(Memb.ObjName).Expression;
            string prop_name = UE4Utility.GetFNameAsString(prop_name_expr_str, context_expr);

            // And the property type
            string prop_type = GetPropertyType(uprop_em.Expression, context_expr);

            // Now, determine address of the actual property value
            // First requires container address
            // Cast to void* first, so that expression evaluation is simplified and faster
            container_expr_str = ExpressionManipulator.FromExpression(container_expr_str).PtrCast(Cpp.Void).Expression;
            var container_eval = DefaultEE.DefaultEval(container_expr_str, context_expr, true) as DkmSuccessEvaluationResult;
            Debug.Assert(container_eval != null && container_eval.Address != null);
            string address_str = container_eval.Address.Value.ToString();

            // Next need offset in container (which is an int32 property of the UProperty class)
            var offset_expr_str = uprop_em.PtrMember(Memb.PropOffset).Expression;
            var offset_eval = DefaultEE.DefaultEval(offset_expr_str, context_expr, true) as DkmSuccessEvaluationResult;
            string offset_str = offset_eval.Value;

            // Then need to create an expression which adds on the offset
            address_str = String.Format("((uint8*){0} + {1})", address_str, offset_str);

            // Next, we need to cast this expression depending on the type of property we have.
            // Retrieve a list of possible cast expressions.
            var cpp_type_info_list = GetCppTypeForPropertyType(prop_type, uprop_em.Expression, context_expr);
            // Accept the first one that is successfully evaluated
            DkmSuccessEvaluationResult success_eval = null;
            string display_type = null;
            foreach (var cpp_type_info in cpp_type_info_list)
            {
                string prop_value_expr_str = AdjustPropertyExpressionStringForType(address_str, prop_type, uprop_em.Expression, context_expr, cpp_type_info);

                Debug.Print("UE4PV: Attempting exp eval as: '{0}'", prop_value_expr_str);

                // Attempt to evaluate the expression
                DkmEvaluationResult raw_eval = DefaultEE.DefaultEval(prop_value_expr_str, context_expr, false);
                if (raw_eval.TagValue == DkmEvaluationResult.Tag.SuccessResult)
                {
                    // Success
                    success_eval = raw_eval as DkmSuccessEvaluationResult;
                    display_type = cpp_type_info.Display;
                    break;
                }
            }

            if(success_eval == null)
            {
                // Was not able to find an evaluatable expression.
                return null;
            }

            return DkmSuccessEvaluationResult.Create(
                expression_.InspectionContext,
                expression_.StackFrame,
                prop_name,
                success_eval.FullName,//prop_value_expr_str,
                success_eval.Flags,
                success_eval.Value,
                // @TODO: Perhaps need to disable for some stuff, like bitfield bool?
                success_eval.EditableValue,
                display_type,//success_eval.Type,
                success_eval.Category,
                success_eval.Access,
                success_eval.StorageType,
                success_eval.TypeModifierFlags,
                success_eval.Address,
                success_eval.CustomUIVisualizers,
                success_eval.ExternalModules,
                null
                );
        }
        // Takes in an address string which identifies the location of the property value in memory,
        // along with property type information.
        // Outputs a string expression which will evaluate to the precise location with the correct C++ type.
        protected string AdjustPropertyExpressionStringForType(string address_str, string prop_type, string uprop_expr_str, DkmVisualizedExpression context_expr, CppTypeInfo cpp_type_info)
        {
            // Special cases first
            switch (prop_type)
            {
                case Prop.Bool:
                    {
                        // Needs special treatment since can be a single bit field as well as just a regular bool
                        // Get a UBoolProperty context
                        var uboolprop_em = ExpressionManipulator.FromExpression(uprop_expr_str).PtrCast(CppProp.Bool);
                        // Read the byte offset and field mask properties
                        string byte_offset_str = GetBoolPropertyByteOffset(uboolprop_em.Expression, context_expr);
                        string field_mask_str = GetBoolPropertyFieldMask(uboolprop_em.Expression, context_expr);
                        // Format an expression which adds the byte offset onto the address, derefs
                        // and then bitwise ANDs with the field mask.
                        return String.Format("(*({0} + {1}) & {2}) != 0",
                            address_str,
                            byte_offset_str,
                            field_mask_str
                            );
                    }

                case Prop.Byte:
                    {
                        // Enum properties are a bit awkward, since due to the different ways the enums can be declared,
                        // we can't reliably access them by a cast and dereference.
                        // eg. A regular enum type will be considered 64 bits.
                        // So, we need to use uint8 to get at the memory, and then do the cast, or rather conversion,
                        // *after* dereferencing in order to get the correct type.
                        return String.Format("({0})*({1}*){2}{3}",
                            cpp_type_info.Type,
                            Typ.Byte,
                            address_str,
                            cpp_type_info.Format
                            );
                    }

                default:
                    break;
            }

            // If we got here, we just need to get the corresponding C++ type, then cast the address
            // to it and dereference.
            // [*(type*)address,fmt]
            return String.Format("*({0}*){1}{2}", cpp_type_info.Type, address_str, cpp_type_info.Format);
        }
 protected static string GetBoolPropertyFieldMask(string uboolprop_expr_str, DkmVisualizedExpression context_expr)
 {
     var boolprop_em = ExpressionManipulator.FromExpression(uboolprop_expr_str).PtrMember(Memb.FieldMask);
     // uint8 property
     var eval = DefaultEE.DefaultEval(boolprop_em.Expression, context_expr, true) as DkmSuccessEvaluationResult;
     var val_str = eval.Value;
     return Utility.GetNumberFromUcharValueString(val_str);
 }
 public BasicVisualizer CreateVisualizer(DkmVisualizedExpression expression)
 {
     return new DateTimeVisualizer(expression);
 }
 public DateTimeVisualizer(DkmVisualizedExpression expression)
     : base(expression)
 {
     RegisterDefaultChildEntries(ChildDisplayMode.Inline);
 }
		public EnumeratedObjectContext(DkmVisualizedExpression expr, DkmVisualizedExpression callback_expr) : base(expr, callback_expr)
		{
			EvaluateChildren();
		}
			public ObjectContext CreateObjectContext(DkmVisualizedExpression expr, DkmVisualizedExpression callback_expr)
			{
				return new EvaluatedObjectContext(expr, callback_expr);
			}