forked from PowerShell/PowerShell
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathComBinderHelpers.cs
More file actions
143 lines (123 loc) · 5.15 KB
/
Copy pathComBinderHelpers.cs
File metadata and controls
143 lines (123 loc) · 5.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/********************************************************************++
Copyright (c) Microsoft Corporation. All rights reserved.
--********************************************************************/
#if !SILVERLIGHT
#if !CLR2
using System.Linq.Expressions;
#else
using Microsoft.Scripting.Ast;
#endif
using System.Diagnostics;
using System.Dynamic;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Globalization;
using System.Management.Automation.Language;
namespace System.Management.Automation.ComInterop
{
internal static class ComBinderHelpers
{
internal static bool PreferPut(Type type, bool holdsNull)
{
Debug.Assert(type != null);
if (type.IsValueType || type.IsArray) return true;
if (type == typeof(String) ||
type == typeof(DBNull) ||
holdsNull ||
type == typeof(System.Reflection.Missing) ||
type == typeof(CurrencyWrapper))
{
return true;
}
else
{
return false;
}
}
internal static bool IsByRef(DynamicMetaObject mo)
{
ParameterExpression pe = mo.Expression as ParameterExpression;
return pe != null && pe.IsByRef;
}
internal static bool IsPSReferenceArg(DynamicMetaObject o)
{
Type t = o.LimitType;
return t.IsGenericType && t.GetGenericTypeDefinition() == typeof(PSReference<>);
}
// this helper prepares arguments for COM binding by transforming ByVal StongBox arguments
// into ByRef expressions that represent the argument's Value fields.
internal static bool[] ProcessArgumentsForCom(ComMethodDesc method, ref DynamicMetaObject[] args,
List<ParameterExpression> temps, List<Expression> initTemps)
{
Debug.Assert(args != null);
DynamicMetaObject[] newArgs = new DynamicMetaObject[args.Length];
bool[] isByRefArg = new bool[args.Length];
for (int i = 0; i < args.Length; i++)
{
DynamicMetaObject curArgument = args[i];
// set new arg infos to their original values or set default ones
// we will do this fixup early so that we can assume we always have
// arginfos in COM binder.
if (IsByRef(curArgument))
{
newArgs[i] = curArgument;
isByRefArg[i] = true;
}
else
{
if (IsPSReferenceArg(curArgument))
{
var restrictions = curArgument.Restrictions.Merge(
GetTypeRestrictionForDynamicMetaObject(curArgument)
);
// we have restricted this argument to LimitType so we can convert and conversion will be trivial cast.
Expression boxedValueAccessor = Expression.Property(
Helpers.Convert(
curArgument.Expression,
curArgument.LimitType
),
curArgument.LimitType.GetProperty("Value")
);
PSReference value = curArgument.Value as PSReference;
object boxedValue = value != null ? value.Value : null;
newArgs[i] = new DynamicMetaObject(
boxedValueAccessor,
restrictions,
boxedValue
);
isByRefArg[i] = true;
}
else
{
if ((method.ParameterInformation != null) && (i < method.ParameterInformation.Length))
{
newArgs[i] = new DynamicMetaObject(curArgument.CastOrConvertMethodArgument(
method.ParameterInformation[i].parameterType,
i.ToString(CultureInfo.InvariantCulture),
method.Name,
temps,
initTemps), curArgument.Restrictions);
}
else
{
newArgs[i] = curArgument;
}
isByRefArg[i] = false;
}
}
}
args = newArgs;
return isByRefArg;
}
internal static BindingRestrictions GetTypeRestrictionForDynamicMetaObject(DynamicMetaObject obj)
{
if (obj.Value == null && obj.HasValue)
{
//If the meta object holds a null value, create an instance restriction for checking null
return BindingRestrictions.GetInstanceRestriction(obj.Expression, null);
}
return BindingRestrictions.GetTypeRestriction(obj.Expression, obj.LimitType);
}
}
}
#endif