|
|
|
@ -59,7 +59,17 @@ namespace ILSpy.BamlDecompiler.Rewrite
@@ -59,7 +59,17 @@ namespace ILSpy.BamlDecompiler.Rewrite
|
|
|
|
|
foreach (var entry in eventMappings[index].value) |
|
|
|
|
{ |
|
|
|
|
string xmlns = ""; // TODO : implement xmlns resolver!
|
|
|
|
|
element.Add(new XAttribute(xmlns + entry.EventName, entry.MethodName)); |
|
|
|
|
var type = element.Annotation<XamlType>(); |
|
|
|
|
if (type?.TypeNamespace + "." + type?.TypeName == "System.Windows.Style") |
|
|
|
|
{ |
|
|
|
|
element.Add(new XElement(type.Namespace + "EventSetter", |
|
|
|
|
new XAttribute("Event", entry.EventName), |
|
|
|
|
new XAttribute("Handler", entry.MethodName))); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
element.Add(new XAttribute(xmlns + entry.EventName, entry.MethodName)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -133,8 +143,9 @@ namespace ILSpy.BamlDecompiler.Rewrite
@@ -133,8 +143,9 @@ namespace ILSpy.BamlDecompiler.Rewrite
|
|
|
|
|
{ |
|
|
|
|
foreach (var section in ilSwitch.Sections) |
|
|
|
|
{ |
|
|
|
|
var events = FindEvents(section.Body); |
|
|
|
|
result.Add((section.Labels, events)); |
|
|
|
|
var events = new List<EventRegistration>(); |
|
|
|
|
FindEvents(section.Body, events); |
|
|
|
|
result.Add((section.Labels, events.ToArray())); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
@ -147,47 +158,126 @@ namespace ILSpy.BamlDecompiler.Rewrite
@@ -147,47 +158,126 @@ namespace ILSpy.BamlDecompiler.Rewrite
|
|
|
|
|
continue; |
|
|
|
|
if (!comp.Right.MatchLdcI4(out int id)) |
|
|
|
|
continue; |
|
|
|
|
var events = FindEvents(comp.Kind == ComparisonKind.Inequality |
|
|
|
|
var inst = comp.Kind == ComparisonKind.Inequality |
|
|
|
|
? ifInst.FalseInst |
|
|
|
|
: ifInst.TrueInst); |
|
|
|
|
result.Add((new LongSet(id), events)); |
|
|
|
|
: ifInst.TrueInst; |
|
|
|
|
var events = new List<EventRegistration>(); |
|
|
|
|
FindEvents(inst, events); |
|
|
|
|
result.Add((new LongSet(id), events.ToArray())); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
EventRegistration[] FindEvents(ILInstruction inst) |
|
|
|
|
void FindEvents(ILInstruction inst, List<EventRegistration> events) |
|
|
|
|
{ |
|
|
|
|
var events = new List<EventRegistration>(); |
|
|
|
|
|
|
|
|
|
switch (inst) |
|
|
|
|
{ |
|
|
|
|
case Block _: |
|
|
|
|
foreach (var node in ((Block)inst).Instructions) |
|
|
|
|
case Block b: |
|
|
|
|
if (MatchEventSetterCreation(b, out var @event)) |
|
|
|
|
{ |
|
|
|
|
FindEvents(node, events); |
|
|
|
|
events.Add(@event); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
foreach (var node in b.Instructions) |
|
|
|
|
{ |
|
|
|
|
if (MatchSimpleEventRegistration(node, out @event)) |
|
|
|
|
events.Add(@event); |
|
|
|
|
} |
|
|
|
|
FindEvents(((Block)inst).FinalInstruction, events); |
|
|
|
|
break; |
|
|
|
|
case Branch br: |
|
|
|
|
return FindEvents(br.TargetBlock); |
|
|
|
|
FindEvents(br.TargetBlock, events); |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
FindEvents(inst, events); |
|
|
|
|
if (MatchSimpleEventRegistration(inst, out @event)) |
|
|
|
|
events.Add(@event); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
return events.ToArray(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void FindEvents(ILInstruction inst, List<EventRegistration> events) |
|
|
|
|
// stloc v(newobj EventSetter..ctor())
|
|
|
|
|
// callvirt set_Event(ldloc v, ldsfld eventName)
|
|
|
|
|
// callvirt set_Handler(ldloc v, newobj RoutedEventHandler..ctor(ldloc this, ldftn eventHandler))
|
|
|
|
|
// callvirt Add(callvirt get_Setters(castclass System.Windows.Style(ldloc target)), ldloc v)
|
|
|
|
|
// leave IL_0007 (nop)
|
|
|
|
|
bool MatchEventSetterCreation(Block b, out EventRegistration @event) |
|
|
|
|
{ |
|
|
|
|
CallInstruction call = inst as CallInstruction; |
|
|
|
|
if (call == null || call.OpCode == OpCode.NewObj) |
|
|
|
|
return; |
|
|
|
|
@event = null; |
|
|
|
|
var instr = b.Instructions; |
|
|
|
|
if (instr.Count != 5 || !b.FinalInstruction.MatchNop()) |
|
|
|
|
return false; |
|
|
|
|
// stloc v(newobj EventSetter..ctor())
|
|
|
|
|
if (!instr.ElementAt(0).MatchStLoc(out var v, out var initializer)) |
|
|
|
|
return false; |
|
|
|
|
if (!(initializer is NewObj newObj |
|
|
|
|
&& newObj.Method.DeclaringType.FullName == "System.Windows.EventSetter" |
|
|
|
|
&& newObj.Arguments.Count == 0)) |
|
|
|
|
{ |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
//callvirt set_Event(ldloc v, ldsfld eventName)
|
|
|
|
|
if (!(instr.ElementAt(1) is CallVirt setEventCall && setEventCall.Arguments.Count == 2)) |
|
|
|
|
return false; |
|
|
|
|
if (!setEventCall.Method.IsAccessor) |
|
|
|
|
return false; |
|
|
|
|
if (!setEventCall.Arguments[0].MatchLdLoc(v)) |
|
|
|
|
return false; |
|
|
|
|
if (setEventCall.Method.Name != "set_Event") |
|
|
|
|
return false; |
|
|
|
|
if (!setEventCall.Arguments[1].MatchLdsFld(out var eventField)) |
|
|
|
|
return false; |
|
|
|
|
string eventName = eventField.Name; |
|
|
|
|
if (eventName.EndsWith("Event")) |
|
|
|
|
{ |
|
|
|
|
eventName = eventName.Remove(eventName.Length - "Event".Length); |
|
|
|
|
} |
|
|
|
|
// callvirt set_Handler(ldloc v, newobj RoutedEventHandler..ctor(ldloc this, ldftn eventHandler))
|
|
|
|
|
if (!(instr.ElementAt(2) is CallVirt setHandlerCall && setHandlerCall.Arguments.Count == 2)) |
|
|
|
|
return false; |
|
|
|
|
if (!setHandlerCall.Method.IsAccessor) |
|
|
|
|
return false; |
|
|
|
|
if (!setHandlerCall.Arguments[0].MatchLdLoc(v)) |
|
|
|
|
return false; |
|
|
|
|
if (setHandlerCall.Method.Name != "set_Handler") |
|
|
|
|
return false; |
|
|
|
|
if (!MatchEventHandlerCreation(setHandlerCall.Arguments[1], out string handlerName)) |
|
|
|
|
return false; |
|
|
|
|
@event = new EventRegistration { EventName = eventName, MethodName = handlerName }; |
|
|
|
|
// callvirt Add(callvirt get_Setters(castclass System.Windows.Style(ldloc target)), ldloc v)
|
|
|
|
|
if (!(instr.ElementAt(3) is CallVirt addCall && addCall.Arguments.Count == 2)) |
|
|
|
|
return false; |
|
|
|
|
if (addCall.Method.Name != "Add") |
|
|
|
|
return false; |
|
|
|
|
if (!(addCall.Arguments[0] is CallVirt getSettersCall && getSettersCall.Arguments.Count == 1)) |
|
|
|
|
return false; |
|
|
|
|
if (!getSettersCall.Method.IsAccessor) |
|
|
|
|
return false; |
|
|
|
|
if (getSettersCall.Method.Name != "get_Setters") |
|
|
|
|
return false; |
|
|
|
|
if (!getSettersCall.Arguments[0].MatchCastClass(out var arg, out var type)) |
|
|
|
|
return false; |
|
|
|
|
if (type.FullName != "System.Windows.Style") |
|
|
|
|
return false; |
|
|
|
|
if (!(arg.MatchLdLoc(out var t) && t.Kind == VariableKind.Parameter && t.Index == 1)) |
|
|
|
|
return false; |
|
|
|
|
if (!addCall.Arguments[1].MatchLdLoc(v)) |
|
|
|
|
return false; |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool MatchSimpleEventRegistration(ILInstruction inst, out EventRegistration @event) |
|
|
|
|
{ |
|
|
|
|
@event = null; |
|
|
|
|
if (!(inst is CallInstruction call) || call.OpCode == OpCode.NewObj) |
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
if (IsAddEvent(call, out string eventName, out string handlerName) |
|
|
|
|
|| IsAddAttachedEvent(call, out eventName, out handlerName)) |
|
|
|
|
if (!IsAddEvent(call, out string eventName, out string handlerName) |
|
|
|
|
&& !IsAddAttachedEvent(call, out eventName, out handlerName)) |
|
|
|
|
{ |
|
|
|
|
events.Add(new EventRegistration { EventName = eventName, MethodName = handlerName }); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@event = new EventRegistration { EventName = eventName, MethodName = handlerName }; |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool IsAddAttachedEvent(CallInstruction call, out string eventName, out string handlerName) |
|
|
|
@ -208,14 +298,7 @@ namespace ILSpy.BamlDecompiler.Rewrite
@@ -208,14 +298,7 @@ namespace ILSpy.BamlDecompiler.Rewrite
|
|
|
|
|
{ |
|
|
|
|
eventName = eventName.Remove(eventName.Length - "Event".Length); |
|
|
|
|
} |
|
|
|
|
var newObj = call.Arguments[2] as NewObj; |
|
|
|
|
if (newObj == null || newObj.Arguments.Count != 2) |
|
|
|
|
return false; |
|
|
|
|
var ldftn = newObj.Arguments[1]; |
|
|
|
|
if (ldftn.OpCode != OpCode.LdFtn && ldftn.OpCode != OpCode.LdVirtFtn) |
|
|
|
|
return false; |
|
|
|
|
handlerName = ((IInstructionWithMethodOperand)ldftn).Method.Name; |
|
|
|
|
return true; |
|
|
|
|
return MatchEventHandlerCreation(call.Arguments[2], out handlerName); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return false; |
|
|
|
@ -235,18 +318,23 @@ namespace ILSpy.BamlDecompiler.Rewrite
@@ -235,18 +318,23 @@ namespace ILSpy.BamlDecompiler.Rewrite
|
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
eventName = addMethod.Name.Substring("add_".Length); |
|
|
|
|
var newObj = call.Arguments[1] as NewObj; |
|
|
|
|
if (newObj == null || newObj.Arguments.Count != 2) |
|
|
|
|
return false; |
|
|
|
|
var ldftn = newObj.Arguments[1]; |
|
|
|
|
if (ldftn.OpCode != OpCode.LdFtn && ldftn.OpCode != OpCode.LdVirtFtn) |
|
|
|
|
return false; |
|
|
|
|
handlerName = ((IInstructionWithMethodOperand)ldftn).Method.Name; |
|
|
|
|
handlerName = XamlUtils.EscapeName(handlerName); |
|
|
|
|
return true; |
|
|
|
|
return MatchEventHandlerCreation(call.Arguments[1], out handlerName); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool MatchEventHandlerCreation(ILInstruction inst, out string handlerName) |
|
|
|
|
{ |
|
|
|
|
handlerName = ""; |
|
|
|
|
if (!(inst is NewObj newObj) || newObj.Arguments.Count != 2) |
|
|
|
|
return false; |
|
|
|
|
var ldftn = newObj.Arguments[1]; |
|
|
|
|
if (ldftn.OpCode != OpCode.LdFtn && ldftn.OpCode != OpCode.LdVirtFtn) |
|
|
|
|
return false; |
|
|
|
|
handlerName = ((IInstructionWithMethodOperand)ldftn).Method.Name; |
|
|
|
|
handlerName = XamlUtils.EscapeName(handlerName); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|